aere-quantum/agents/x402/inregistreaza-rpc.mjs

31 lines
3.0 KiB
JavaScript

#!/usr/bin/env node
// inregistreaza-rpc.mjs: scoate de pe lant, O DATA, raspunsurile RPC de care are nevoie verifica-plati.mjs pentru un dosar-dovada
// (eth_chainId, chitanta fiecarei plati, Transfer-urile din portofel, si codul portofelului cand e un contract 2-din-2), ca proba verificatorului sa ruleze apoi fara retea pe date REALE.
// node inregistreaza-rpc.mjs <dovada.json> --rpc <url> --out <rpc-inregistrat.json>
import fs from 'node:fs';
import { incarcaEthers } from './wallet.mjs';
import { jurnalePaginate } from './verifica-plati.mjs';
const a = process.argv.slice(2); const get = (f) => { const i = a.indexOf(f); return i >= 0 ? a[i + 1] : undefined; };
const f = a[0]; const rpc = get('--rpc'); const out = get('--out');
if (!f || !rpc || !out) { console.error('usage: node inregistreaza-rpc.mjs <evidence.json> --rpc <url> --out <file>'); process.exit(2); }
const ethers = incarcaEthers();
const d = JSON.parse(fs.readFileSync(f, 'utf8'));
const apel = async (method, params) => { const r = await fetch(rpc, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ jsonrpc: '2.0', id: 1, method, params }) }); const j = await r.json(); if (j.error) throw new Error(j.error.message); return j.result; };
const chainId = await apel('eth_chainId', []);
const receipts = {};
for (const p of d.payments) receipts[p.transaction.toLowerCase()] = await apel('eth_getTransactionReceipt', [p.transaction]);
// 2026-10-21: in ferestre, ca verificatorul (o usa publica refuza un interval lung); o fereastra necitita OPRESTE inregistrarea, fiindca o
// inregistrare cu o fereastra lipsa ar fi o lista de transferuri mai scurta decat lantul, pe care proba ar lua-o drept adevar
const capul = Number(await apel('eth_blockNumber', []));
const apelBrut = async (method, params) => { const r = await fetch(rpc, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ jsonrpc: '2.0', id: 1, method, params }) }); return r.json(); };
const citite = await jurnalePaginate(apelBrut, { address: d.token, topics: [ethers.id('Transfer(address,address,uint256)'), '0x' + '0'.repeat(24) + d.wallet.toLowerCase().slice(2)] }, { from: Number(d.fromBlock), to: capul });
// process.exitCode, nu process.exit(): dupa un fetch, iesirea imediata cade pe Windows in libuv (UV_HANDLE_CLOSING, lectia din 2026-09-11)
if (citite.refused || citite.unreadable) { console.error(`not recorded: ${citite.refused || `${citite.unreadable} of ${citite.windows} windows unread (first: ${citite.first})`}`); process.exitCode = 2; }
else {
const logs = citite.logs;
const code = d.walletContract ? await apel('eth_getCode', [d.wallet, 'latest']) : undefined;
fs.writeFileSync(out, JSON.stringify({ v: 1, recordedAt: new Date().toISOString(), rpc, chainId, receipts, transfersOut: logs, ...(code ? { code } : {}) }, null, 1) + '\n');
console.log(`recorded chain ${Number(chainId)}: ${Object.keys(receipts).length} receipts, ${logs.length} transfers out of the wallet${code ? `, the wallet code (${(code.length - 2) / 2} bytes)` : ''} -> ${out}`);
}