56ab4ec3fe
environment variables instead of hardcoded SPEND_SECRET values. Required env vars: SPEND_SECRET, TX_HASH Optional: DAEMON_URL (defaults to seed01.salvium.io:19081)
101 lines
3.2 KiB
JavaScript
101 lines
3.2 KiB
JavaScript
#!/usr/bin/env bun
|
|
// Test parsing many blocks to ensure transaction parsing is robust
|
|
|
|
import { createDaemonRPC } from '../src/rpc/index.js';
|
|
import { parseTransaction } from '../src/transaction.js';
|
|
import { hexToBytes } from '../src/address.js';
|
|
|
|
const daemon = createDaemonRPC({ url: 'http://seed01.salvium.io:19081', timeout: 30000 });
|
|
|
|
async function test() {
|
|
console.log('=== Block parsing test ===\n');
|
|
|
|
const info = await daemon.getInfo();
|
|
const currentHeight = info.result.height;
|
|
console.log(`Current chain height: ${currentHeight}`);
|
|
|
|
const startHeight = 0;
|
|
const endHeight = Math.min(10000, currentHeight);
|
|
const batchSize = 100;
|
|
|
|
let totalTxs = 0;
|
|
let parsedTxs = 0;
|
|
let failedTxs = 0;
|
|
let startTime = Date.now();
|
|
|
|
console.log(`\nParsing blocks ${startHeight} to ${endHeight}...\n`);
|
|
|
|
for (let height = startHeight; height < endHeight; height += batchSize) {
|
|
const endBatch = Math.min(height + batchSize, endHeight);
|
|
|
|
// Get block headers for this batch
|
|
const headers = await daemon.getBlockHeadersRange(height, endBatch - 1);
|
|
if (!headers.result?.headers) continue;
|
|
|
|
// Collect all tx hashes from these blocks
|
|
const txHashes = [];
|
|
for (const header of headers.result.headers) {
|
|
// Get full block
|
|
const block = await daemon.getBlock(header.hash);
|
|
if (block.result?.tx_hashes) {
|
|
txHashes.push(...block.result.tx_hashes);
|
|
}
|
|
}
|
|
|
|
if (txHashes.length === 0) continue;
|
|
|
|
// Get transactions in batches of 100
|
|
for (let i = 0; i < txHashes.length; i += 100) {
|
|
const batch = txHashes.slice(i, i + 100);
|
|
const txResp = await daemon.getTransactions(batch, { decode_as_json: false });
|
|
|
|
if (!txResp.result?.txs) continue;
|
|
|
|
for (const txData of txResp.result.txs) {
|
|
totalTxs++;
|
|
|
|
try {
|
|
const tx = parseTransaction(hexToBytes(txData.as_hex));
|
|
parsedTxs++;
|
|
|
|
// Basic validation
|
|
if (!tx.prefix) throw new Error('Missing prefix');
|
|
if (tx.prefix.version === 2 && !tx.rct) throw new Error('Missing RCT for v2 tx');
|
|
|
|
} catch (e) {
|
|
failedTxs++;
|
|
if (failedTxs <= 10) {
|
|
console.log(` FAILED tx at height ~${height}: ${e.message}`);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Progress update
|
|
const elapsed = (Date.now() - startTime) / 1000;
|
|
const rate = totalTxs / elapsed;
|
|
const memMB = Math.round(process.memoryUsage().heapUsed / 1024 / 1024);
|
|
console.log(`Height ${endBatch}: ${totalTxs} txs (${parsedTxs} ok, ${failedTxs} failed), ${rate.toFixed(1)} tx/s, ${memMB} MB`);
|
|
|
|
// Memory check
|
|
if (memMB > 500) {
|
|
console.log('\nWARNING: Memory usage > 500 MB, stopping');
|
|
break;
|
|
}
|
|
|
|
// Force GC if available
|
|
if (global.gc) global.gc();
|
|
}
|
|
|
|
const elapsed = (Date.now() - startTime) / 1000;
|
|
console.log(`\n=== Results ===`);
|
|
console.log(`Total transactions: ${totalTxs}`);
|
|
console.log(`Successfully parsed: ${parsedTxs}`);
|
|
console.log(`Failed: ${failedTxs}`);
|
|
console.log(`Success rate: ${(parsedTxs / totalTxs * 100).toFixed(2)}%`);
|
|
console.log(`Time: ${elapsed.toFixed(1)} seconds`);
|
|
console.log(`Rate: ${(totalTxs / elapsed).toFixed(1)} tx/s`);
|
|
}
|
|
|
|
test().catch(console.error);
|