- 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>
127 lines
5.7 KiB
JavaScript
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);
|