UNPKG

nano-mcp

Version:

NANO MCP (Nano Cryptocurrency) Server for AI Assistants - A JSON-RPC 2.0 API server for Nano cryptocurrency operations

202 lines (173 loc) 7.28 kB
const https = require('https'); const { wallet, tools, block } = require('nanocurrency-web'); // Helper function to make RPC calls async function makeRPCCall(action, params) { return new Promise((resolve, reject) => { const data = JSON.stringify({ action, ...params, key: 'RPC-KEY-BAB822FCCDAE42ECB7A331CCAAAA23' }); console.log('Making RPC call:', JSON.parse(data)); const options = { hostname: 'rpc.nano.to', port: 443, path: '/', method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': data.length } }; const req = https.request(options, (res) => { let responseData = ''; res.on('data', (chunk) => { responseData += chunk; }); res.on('end', () => { try { const jsonResponse = JSON.parse(responseData); console.log('RPC Response:', jsonResponse); resolve(jsonResponse); } catch (error) { reject(new Error(`Failed to parse response: ${error.message}`)); } }); }); req.on('error', (error) => { reject(error); }); req.write(data); req.end(); }); } // Helper function to wait for a specified time function wait(minutes) { return new Promise(resolve => setTimeout(resolve, minutes * 60 * 1000)); } async function testReceiveScenario() { try { // Step 1: Generate wallet console.log('1. Generating new wallet...'); // Generate a new wallet using nanocurrency-web const walletData = wallet.generateLegacy(); const account = walletData.accounts[0].address; const privateKey = walletData.accounts[0].privateKey; const publicKey = walletData.accounts[0].publicKey; const seed = walletData.seed; console.log('\nWallet generated successfully!'); console.log('Seed (KEEP THIS SAFE):', seed); console.log('Account Address:', account); console.log('Public Key:', publicKey); console.log('Private Key:', privateKey); // Step 2: Initialize the account console.log('\n2. Checking account info...'); const initResult = await makeRPCCall('account_info', { account: account }); if (initResult.error) { console.log('Account not yet initialized (This is normal for new accounts)'); } else { console.log('Account info:', initResult); } // Step 3: Wait for funds console.log('\n3. Waiting for funds...'); console.log(`Please send exactly 0.00001 NANO to this address:\n${account}`); console.log('\nWaiting 4 minutes for funds to arrive...'); // Wait for 4 minutes for (let i = 0; i < 4; i++) { await wait(1); console.log(`${3 - i} minutes remaining...`); // Check for pending during wait const checkPending = await makeRPCCall('pending', { account: account, count: '1', source: 'true' }); if (checkPending.blocks && Object.keys(checkPending.blocks).length > 0) { console.log('\nPending transaction detected!'); break; } } // Step 4: Check for pending blocks console.log('\n4. Checking for pending blocks...'); const pendingResult = await makeRPCCall('pending', { account: account, count: '1', source: 'true' }); console.log('Pending blocks:', pendingResult); if (pendingResult.blocks && Object.keys(pendingResult.blocks).length > 0) { // Step 5: Generate work for receiving console.log('\n5. Generating work...'); const workResult = await makeRPCCall('work_generate', { hash: publicKey, // For first receive, use public key as frontier key: 'RPC-KEY-BAB822FCCDAE42ECB7A331CCAAAA23' }); console.log('Work generated:', workResult); if (!workResult.work) { throw new Error('Failed to generate work'); } // Step 6: Process pending blocks console.log('\n6. Processing pending blocks...'); for (const [hash, blockInfo] of Object.entries(pendingResult.blocks)) { // Convert raw amount to nano for display const rawToNanoResult = await makeRPCCall('raw_to_nano', { amount: blockInfo.amount }); console.log(`Receiving ${rawToNanoResult.nano} NANO from block ${hash}`); // Create and sign the receive block using nanocurrency-web const receiveBlockData = { walletBalanceRaw: '0', // Initial balance is 0 for first receive toAddress: account, representativeAddress: account, // Using self as representative for test frontier: '0000000000000000000000000000000000000000000000000000000000000000', // Genesis frontier for first receive transactionHash: hash, amountRaw: blockInfo.amount, work: workResult.work }; // Create and sign the block const signedBlock = block.receive(receiveBlockData, privateKey); // Process the signed block const processResult = await makeRPCCall('process', { json_block: 'true', subtype: 'receive', block: signedBlock }); console.log('Block processed:', processResult); } // Step 7: Final balance check console.log('\n7. Checking final balance...'); const balanceResult = await makeRPCCall('account_balance', { account: account }); if (balanceResult.balance) { const finalBalanceNano = await makeRPCCall('raw_to_nano', { amount: balanceResult.balance }); console.log('Final balance:', finalBalanceNano.nano, 'NANO'); } else { console.log('Final balance:', balanceResult); } } else { console.log('No pending blocks found after waiting'); } } catch (error) { console.error('\nError occurred during test:'); console.error('Message:', error.message); if (error.response) { console.error('RPC Response:', error.response.data); } throw error; } } // Run the test console.log('Starting NANO receive test scenario...\n'); testReceiveScenario() .then(() => { console.log('\nTest completed successfully'); }) .catch(err => { console.error('\nTest failed with error:', err); process.exit(1); });