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",
|
"name": "codexstorage",
|
||||||
"version": "1.0.7",
|
"version": "1.0.8",
|
||||||
"description": "CLI tool for Codex Storage",
|
"description": "CLI tool for Codex Storage",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { createSpinner } from 'nanospinner';
|
import { createSpinner } from 'nanospinner';
|
||||||
import { runCommand } from '../utils/command.js';
|
import { runCommand } from '../utils/command.js';
|
||||||
import { showErrorMessage, showInfoMessage, showSuccessMessage } from '../utils/messages.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 inquirer from 'inquirer';
|
||||||
import boxen from 'boxen';
|
import boxen from 'boxen';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
@ -11,6 +11,22 @@ import axios from 'axios';
|
|||||||
|
|
||||||
const platform = os.platform();
|
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) {
|
export async function runCodex(showNavigationMenu) {
|
||||||
const isInstalled = await isCodexInstalled();
|
const isInstalled = await isCodexInstalled();
|
||||||
if (!isInstalled) {
|
if (!isInstalled) {
|
||||||
@ -84,7 +100,28 @@ export async function runCodex(showNavigationMenu) {
|
|||||||
try {
|
try {
|
||||||
const response = await axios.get('http://localhost:8080/api/codex/v1/debug/info');
|
const response = await axios.get('http://localhost:8080/api/codex/v1/debug/info');
|
||||||
if (response.status === 200) {
|
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(
|
console.log(boxen(
|
||||||
chalk.cyan('We are logging some of your node\'s public data for improving the Codex experience'),
|
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: [
|
choices: [
|
||||||
'1. View Connected Peers',
|
'1. View Connected Peers',
|
||||||
'2. View Node Information',
|
'2. View Node Information',
|
||||||
'3. Back to Main Menu',
|
'3. Update Wallet Address',
|
||||||
'4. Exit'
|
'4. Back to Main Menu',
|
||||||
|
'5. Exit'
|
||||||
],
|
],
|
||||||
pageSize: 4,
|
pageSize: 5,
|
||||||
loop: true
|
loop: true
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
@ -183,8 +221,31 @@ async function showNodeDetails(data, showNavigationMenu) {
|
|||||||
));
|
));
|
||||||
return showNodeDetails(data, showNavigationMenu);
|
return showNodeDetails(data, showNavigationMenu);
|
||||||
case '3':
|
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':
|
case '4':
|
||||||
|
return showNavigationMenu();
|
||||||
|
case '5':
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,21 @@ import os from 'os';
|
|||||||
|
|
||||||
const platform = os.platform();
|
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() {
|
export async function isNodeRunning() {
|
||||||
try {
|
try {
|
||||||
const response = await axios.get('http://localhost:8080/api/codex/v1/debug/info');
|
const response = await axios.get('http://localhost:8080/api/codex/v1/debug/info');
|
||||||
@ -23,7 +38,10 @@ export async function isCodexInstalled() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function logToSupabase(nodeData) {
|
export async function logToSupabase(nodeData, retryCount = 3, retryDelay = 1000) {
|
||||||
|
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
|
||||||
|
|
||||||
|
for (let attempt = 1; attempt <= retryCount; attempt++) {
|
||||||
try {
|
try {
|
||||||
const peerCount = nodeData.table.nodes ? nodeData.table.nodes.length : "0";
|
const peerCount = nodeData.table.nodes ? nodeData.table.nodes.length : "0";
|
||||||
const payload = {
|
const payload = {
|
||||||
@ -33,26 +51,40 @@ export async function logToSupabase(nodeData) {
|
|||||||
version: nodeData.codex.version,
|
version: nodeData.codex.version,
|
||||||
peerCount: peerCount == 0 ? "0" : peerCount,
|
peerCount: peerCount == 0 ? "0" : peerCount,
|
||||||
port: nodeData.announceAddresses[0].split('/')[4],
|
port: nodeData.announceAddresses[0].split('/')[4],
|
||||||
listeningAddress: nodeData.table.localNode.address
|
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, {
|
const response = await axios.post('https://vfcnsjxahocmzefhckfz.supabase.co/functions/v1/codexnodes', payload, {
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
}
|
},
|
||||||
|
timeout: 5000 // 5 second timeout
|
||||||
});
|
});
|
||||||
|
|
||||||
return response.status === 200;
|
return response.status === 200;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to log to Supabase:', error.message);
|
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) {
|
if (error.response) {
|
||||||
console.error('Error response:', {
|
console.error('Error response:', {
|
||||||
status: error.response.status,
|
status: error.response.status,
|
||||||
data: error.response.data
|
data: error.response.data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return false;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function checkDependencies() {
|
export async function checkDependencies() {
|
||||||
@ -71,3 +103,51 @@ export async function checkDependencies() {
|
|||||||
}
|
}
|
||||||
return true;
|
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