mirror of
https://github.com/codex-storage/cli.git
synced 2025-02-28 16:40:43 +00:00
getting erc20 addresses optionally after running node
This commit is contained in:
parent
5a51c8a3a3
commit
60a9576fbe
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "codexstorage",
|
||||
"version": "1.0.7",
|
||||
"version": "1.0.8",
|
||||
"description": "CLI tool for Codex Storage",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { createSpinner } from 'nanospinner';
|
||||
import { runCommand } from '../utils/command.js';
|
||||
import { showErrorMessage, showInfoMessage, showSuccessMessage } from '../utils/messages.js';
|
||||
import { isNodeRunning, isCodexInstalled, logToSupabase } from '../services/nodeService.js';
|
||||
import { isNodeRunning, isCodexInstalled, logToSupabase, startPeriodicLogging, getWalletAddress, setWalletAddress } from '../services/nodeService.js';
|
||||
import inquirer from 'inquirer';
|
||||
import boxen from 'boxen';
|
||||
import chalk from 'chalk';
|
||||
@ -11,6 +11,22 @@ import axios from 'axios';
|
||||
|
||||
const platform = os.platform();
|
||||
|
||||
async function promptForWalletAddress() {
|
||||
const { wallet } = await inquirer.prompt([
|
||||
{
|
||||
type: 'input',
|
||||
name: 'wallet',
|
||||
message: 'Please enter your ERC20 wallet address (or press enter to skip):',
|
||||
validate: (input) => {
|
||||
if (!input) return true; // Allow empty input
|
||||
if (/^0x[a-fA-F0-9]{40}$/.test(input)) return true;
|
||||
return 'Please enter a valid ERC20 wallet address (0x followed by 40 hexadecimal characters) or press enter to skip';
|
||||
}
|
||||
}
|
||||
]);
|
||||
return wallet || null;
|
||||
}
|
||||
|
||||
export async function runCodex(showNavigationMenu) {
|
||||
const isInstalled = await isCodexInstalled();
|
||||
if (!isInstalled) {
|
||||
@ -84,7 +100,28 @@ export async function runCodex(showNavigationMenu) {
|
||||
try {
|
||||
const response = await axios.get('http://localhost:8080/api/codex/v1/debug/info');
|
||||
if (response.status === 200) {
|
||||
await logToSupabase(response.data);
|
||||
// Check if wallet exists
|
||||
try {
|
||||
const existingWallet = await getWalletAddress();
|
||||
if (!existingWallet) {
|
||||
console.log(showInfoMessage('[OPTIONAL] Please provide your ERC20 wallet address.'));
|
||||
const wallet = await promptForWalletAddress();
|
||||
if (wallet) {
|
||||
await setWalletAddress(wallet);
|
||||
console.log(showSuccessMessage('Wallet address saved successfully!'));
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(showErrorMessage('Failed to process wallet address. Continuing without wallet update.'));
|
||||
}
|
||||
|
||||
// Start periodic logging
|
||||
const stopLogging = await startPeriodicLogging();
|
||||
|
||||
nodeProcess.on('exit', () => {
|
||||
stopLogging();
|
||||
});
|
||||
|
||||
console.log(boxen(
|
||||
chalk.cyan('We are logging some of your node\'s public data for improving the Codex experience'),
|
||||
{
|
||||
@ -131,10 +168,11 @@ async function showNodeDetails(data, showNavigationMenu) {
|
||||
choices: [
|
||||
'1. View Connected Peers',
|
||||
'2. View Node Information',
|
||||
'3. Back to Main Menu',
|
||||
'4. Exit'
|
||||
'3. Update Wallet Address',
|
||||
'4. Back to Main Menu',
|
||||
'5. Exit'
|
||||
],
|
||||
pageSize: 4,
|
||||
pageSize: 5,
|
||||
loop: true
|
||||
}
|
||||
]);
|
||||
@ -183,8 +221,31 @@ async function showNodeDetails(data, showNavigationMenu) {
|
||||
));
|
||||
return showNodeDetails(data, showNavigationMenu);
|
||||
case '3':
|
||||
return showNavigationMenu();
|
||||
try {
|
||||
const existingWallet = await getWalletAddress();
|
||||
|
||||
console.log(boxen(
|
||||
`${chalk.cyan('Current wallet address:')}\n${existingWallet || 'Not set'}`,
|
||||
{
|
||||
padding: 1,
|
||||
margin: 1,
|
||||
borderStyle: 'round',
|
||||
borderColor: 'blue'
|
||||
}
|
||||
));
|
||||
|
||||
const wallet = await promptForWalletAddress();
|
||||
if (wallet) {
|
||||
await setWalletAddress(wallet);
|
||||
console.log(showSuccessMessage('Wallet address updated successfully!'));
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(showErrorMessage(`Failed to update wallet address: ${error.message}`));
|
||||
}
|
||||
return showNodeDetails(data, showNavigationMenu);
|
||||
case '4':
|
||||
return showNavigationMenu();
|
||||
case '5':
|
||||
process.exit(0);
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,21 @@ import os from 'os';
|
||||
|
||||
const platform = os.platform();
|
||||
|
||||
// Add a variable to store wallet address in memory
|
||||
let currentWallet = null;
|
||||
|
||||
export async function setWalletAddress(wallet) {
|
||||
// Basic ERC20 address validation
|
||||
if (wallet && !/^0x[a-fA-F0-9]{40}$/.test(wallet)) {
|
||||
throw new Error('Invalid ERC20 wallet address format');
|
||||
}
|
||||
currentWallet = wallet;
|
||||
}
|
||||
|
||||
export async function getWalletAddress() {
|
||||
return currentWallet;
|
||||
}
|
||||
|
||||
export async function isNodeRunning() {
|
||||
try {
|
||||
const response = await axios.get('http://localhost:8080/api/codex/v1/debug/info');
|
||||
@ -23,36 +38,53 @@ export async function isCodexInstalled() {
|
||||
}
|
||||
}
|
||||
|
||||
export async function logToSupabase(nodeData) {
|
||||
try {
|
||||
const peerCount = nodeData.table.nodes ? nodeData.table.nodes.length : "0";
|
||||
const payload = {
|
||||
nodeId: nodeData.table.localNode.nodeId,
|
||||
peerId: nodeData.table.localNode.peerId,
|
||||
publicIp: nodeData.announceAddresses[0].split('/')[2],
|
||||
version: nodeData.codex.version,
|
||||
peerCount: peerCount == 0 ? "0" : peerCount,
|
||||
port: nodeData.announceAddresses[0].split('/')[4],
|
||||
listeningAddress: nodeData.table.localNode.address
|
||||
};
|
||||
export async function logToSupabase(nodeData, retryCount = 3, retryDelay = 1000) {
|
||||
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
|
||||
|
||||
const response = await axios.post('https://vfcnsjxahocmzefhckfz.supabase.co/functions/v1/codexnodes', payload, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
return response.status === 200;
|
||||
} catch (error) {
|
||||
console.error('Failed to log to Supabase:', error.message);
|
||||
if (error.response) {
|
||||
console.error('Error response:', {
|
||||
status: error.response.status,
|
||||
data: error.response.data
|
||||
for (let attempt = 1; attempt <= retryCount; attempt++) {
|
||||
try {
|
||||
const peerCount = nodeData.table.nodes ? nodeData.table.nodes.length : "0";
|
||||
const payload = {
|
||||
nodeId: nodeData.table.localNode.nodeId,
|
||||
peerId: nodeData.table.localNode.peerId,
|
||||
publicIp: nodeData.announceAddresses[0].split('/')[2],
|
||||
version: nodeData.codex.version,
|
||||
peerCount: peerCount == 0 ? "0" : peerCount,
|
||||
port: nodeData.announceAddresses[0].split('/')[4],
|
||||
listeningAddress: nodeData.table.localNode.address,
|
||||
timestamp: new Date().toISOString(),
|
||||
wallet: currentWallet // Include wallet address in payload
|
||||
};
|
||||
|
||||
const response = await axios.post('https://vfcnsjxahocmzefhckfz.supabase.co/functions/v1/codexnodes', payload, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
timeout: 5000 // 5 second timeout
|
||||
});
|
||||
|
||||
return response.status === 200;
|
||||
} catch (error) {
|
||||
const isLastAttempt = attempt === retryCount;
|
||||
const isNetworkError = error.code === 'ENOTFOUND' || error.code === 'ETIMEDOUT' || error.code === 'ECONNREFUSED';
|
||||
|
||||
if (isLastAttempt || !isNetworkError) {
|
||||
console.error(`Failed to log to Supabase (attempt ${attempt}/${retryCount}):`, error.message);
|
||||
if (error.response) {
|
||||
console.error('Error response:', {
|
||||
status: error.response.status,
|
||||
data: error.response.data
|
||||
});
|
||||
}
|
||||
if (isLastAttempt) return false;
|
||||
} else {
|
||||
// Only log retry attempts for network errors
|
||||
console.log(`Retrying Supabase log (attempt ${attempt}/${retryCount}) after ${retryDelay}ms...`);
|
||||
await delay(retryDelay);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export async function checkDependencies() {
|
||||
@ -70,4 +102,52 @@ export async function checkDependencies() {
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export async function startPeriodicLogging() {
|
||||
const FIFTEEN_MINUTES = 15 * 60 * 1000; // 15 minutes in milliseconds
|
||||
|
||||
const logNodeInfo = async () => {
|
||||
try {
|
||||
const response = await axios.get('http://localhost:8080/api/codex/v1/debug/info');
|
||||
if (response.status === 200) {
|
||||
await logToSupabase(response.data);
|
||||
}
|
||||
} catch (error) {
|
||||
// Silently handle any logging errors to not disrupt the node operation
|
||||
console.error('Failed to log node info:', error.message);
|
||||
}
|
||||
};
|
||||
|
||||
// Initial log
|
||||
await logNodeInfo();
|
||||
|
||||
// Set up periodic logging
|
||||
const intervalId = setInterval(logNodeInfo, FIFTEEN_MINUTES);
|
||||
|
||||
// Return cleanup function
|
||||
return () => clearInterval(intervalId);
|
||||
}
|
||||
|
||||
export async function updateWalletAddress(nodeId, wallet) {
|
||||
// Basic ERC20 address validation
|
||||
if (!/^0x[a-fA-F0-9]{40}$/.test(wallet)) {
|
||||
throw new Error('Invalid ERC20 wallet address format');
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await axios.post('https://vfcnsjxahocmzefhckfz.supabase.co/functions/v1/wallet', {
|
||||
nodeId,
|
||||
wallet
|
||||
}, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
timeout: 5000
|
||||
});
|
||||
return response.status === 200;
|
||||
} catch (error) {
|
||||
console.error('Failed to update wallet address:', error.message);
|
||||
throw error;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user