web3/test-testnet.mjs
Claude 5e38ba0bc8
rebrand(lethean): update branding, ports, and config for Lethean blockchain
- Coin: Zano → Lethean, ticker: ZAN/ZANO → LTHN
- Ports: 11211 → 36941 (mainnet RPC), 46941 (testnet RPC)
- Wallet: 11212 → 36944/46944
- Address prefix: iTHN
- URLs: zano.org → lethean.io
- Explorer links: explorer.lthn.io

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 22:24:13 +01:00

127 lines
5.7 KiB
JavaScript

/**
* Live testnet connectivity test for lethean_web3
* Daemon RPC: http://127.0.0.1:46941/json_rpc
* Wallet RPC: http://127.0.0.1:46944/json_rpc
*/
import { ServerWallet } from './server/dist/index.js';
import { validateTokensInput } from './shared/dist/index.js';
// Node 22 ESM — imports now have .js extensions in built output
const DAEMON_URL = 'http://127.0.0.1:46941/json_rpc';
const WALLET_URL = 'http://127.0.0.1:46944/json_rpc';
const api = new ServerWallet({
walletUrl: WALLET_URL,
daemonUrl: DAEMON_URL,
});
let passed = 0;
let failed = 0;
function ok(label, value) {
console.log(` [PASS] ${label}:`, typeof value === 'object' ? JSON.stringify(value).slice(0, 120) : value);
passed++;
}
function fail(label, err) {
console.error(` [FAIL] ${label}:`, err?.message || err);
failed++;
}
// ── Shared utils ─────────────────────────────────────────────────────────────
console.log('\n=== shared: validateTokensInput ===');
try {
const r1 = validateTokensInput('100.5', 12);
r1.valid ? ok('100.5 valid', r1) : fail('100.5 should be valid', r1.error);
} catch (e) { fail('validateTokensInput 100.5', e); }
try {
const r2 = validateTokensInput('18446744.073709551616', 12);
!r2.valid ? ok('overflow rejected', r2) : fail('overflow should be rejected', r2);
} catch (e) { fail('validateTokensInput overflow', e); }
try {
const r3 = validateTokensInput('0.000000000001', 12);
r3.valid ? ok('min unit valid', r3) : fail('min unit should be valid', r3.error);
} catch (e) { fail('validateTokensInput min unit', e); }
// ── Daemon: fetchDaemon raw ───────────────────────────────────────────────────
console.log('\n=== server: fetchDaemon("getinfo") ===');
try {
const resp = await api.fetchDaemon('getinfo', {});
const result = resp.data.result;
result && result.height > 0
? ok('getinfo height', result.height)
: fail('getinfo missing height', result);
} catch (e) { fail('fetchDaemon getinfo', e); }
// ── Daemon: get_assets_list ───────────────────────────────────────────────────
console.log('\n=== server: getAssetsList ===');
let assetsList = [];
try {
assetsList = await api.getAssetsList();
Array.isArray(assetsList)
? ok(`got ${assetsList.length} assets`, assetsList.map(a => a.ticker))
: fail('assets not an array', assetsList);
} catch (e) { fail('getAssetsList', e); }
// ── Daemon: get_alias_details (no alias registered is fine) ──────────────────
console.log('\n=== server: getAliasDetails("lthn") ===');
try {
const details = await api.getAliasDetails('lthn');
ok('getAliasDetails returned', details);
} catch (e) {
// NOT_FOUND is acceptable on a fresh testnet
e?.message?.includes('fetch alias') || e?.code === 'ALIAS_FETCH_ERROR'
? ok('getAliasDetails NOT_FOUND (expected on empty testnet)', e.message)
: fail('getAliasDetails unexpected error', e);
}
// ── Wallet: fetchWallet("getaddress") ────────────────────────────────────────
console.log('\n=== server: fetchWallet("getaddress") ===');
let walletAddress = '';
try {
const resp = await api.fetchWallet('getaddress', {});
walletAddress = resp.data?.result?.address;
walletAddress && walletAddress.startsWith('iTHN')
? ok('address starts with iTHN', walletAddress.slice(0, 24) + '…')
: fail('address wrong prefix', walletAddress);
} catch (e) { fail('fetchWallet getaddress', e); }
// ── Wallet: getBalances ───────────────────────────────────────────────────────
console.log('\n=== server: getBalances ===');
try {
const balances = await api.getBalances();
Array.isArray(balances)
? ok(`balances (${balances.length})`, balances.map(b => `${b.ticker}=${b.amount}`))
: fail('balances not array', balances);
} catch (e) { fail('getBalances', e); }
// ── Wallet: getTxs ────────────────────────────────────────────────────────────
console.log('\n=== server: getTxs(count=5, offset=0) ===');
try {
const txInfo = await api.getTxs({ count: 5, offset: 0 });
typeof txInfo.total_transfers === 'number'
? ok('total_transfers', txInfo.total_transfers)
: fail('getTxs malformed result', txInfo);
} catch (e) { fail('getTxs', e); }
// ── Wallet: validate_signature (dummy data — should return false) ─────────────
console.log('\n=== server: validateWallet (dummy data, expect false) ===');
try {
const valid = await api.validateWallet({
message: 'test nonce',
address: 'iTHNdummy',
signature: 'invalidsig',
pkey: 'dummypkey',
});
valid === false
? ok('bad sig correctly rejected', false)
: fail('validateWallet should return false for bad sig', valid);
} catch (e) { fail('validateWallet', e); }
// ── Summary ───────────────────────────────────────────────────────────────────
console.log(`\n${'='.repeat(50)}`);
console.log(`Results: ${passed} passed, ${failed} failed`);
console.log('='.repeat(50));
if (failed > 0) process.exit(1);