// Self-test: offline maths on a hand-built transaction, then a live read of a busy public // account (the Raydium AMM authority, which trades every second). Run: node test.mjs import { pathToFileURL } from "node:url"; import { walletChanges, walletTrades } from "./scripts/trades.mjs"; const W = "Wa11etWa11etWa11etWa11etWa11etWa11etWa11et1"; const MINT = "JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN"; export default async function test() { const checks = []; const check = (name, ok) => checks.push({ name, ok: Boolean(ok) }); const tx = { transaction: { message: { accountKeys: [{ pubkey: W }] } }, meta: { err: null, fee: 5000, preBalances: [2_000_000_000], postBalances: [999_995_000], preTokenBalances: [], postTokenBalances: [{ owner: W, mint: MINT, uiTokenAmount: { uiAmountString: "350" } }], }, }; const c = walletChanges(tx, W); check("reads a buy as a swap", c.kind === "swap"); check("SOL spent excludes the fee", c.changes.find((x) => x.mint === "SOL")?.delta === -1); check("token received", c.changes.find((x) => x.mint === MINT)?.delta === 350); const r = await walletTrades("5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1", { limit: 3, rpcUrl: "https://api.mainnet-beta.solana.com" }); check("returns transactions", r.transactions.length > 0); check("each has a signature and kind", r.transactions.every((t) => t.signature && t.kind)); let rejected = false; try { await walletTrades("nope"); } catch { rejected = true; } check("rejects a malformed address", rejected); return { ok: checks.every((x) => x.ok), checks }; } if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) { test().then((r) => { console.log(JSON.stringify(r, null, 2)); process.exit(r.ok ? 0 : 1); }, (e) => { console.log(JSON.stringify({ ok: false, error: String(e?.message ?? e) })); process.exit(1); }); }