import { test } from "node:test";
import assert from "node:assert/strict";
import { createHash } from "node:crypto";
import { readFileSync, mkdtempSync, writeFileSync, existsSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { spawnSync } from "node:child_process";
import {
buildSnapshot,
snapshot,
fetchAccounts,
programAccountsRequest,
run,
TOKEN_PROGRAM,
TOKEN_2022_PROGRAM,
type ParsedTokenAccountItem,
} from "../src/index.js";
const MINT = "AfzuVQFSimXiJdp6F8kgZb6R45GU1muu2Uj3u3tZLLpu";
const OTHER_MINT = "2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo";
const A = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
const B = "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB";
const C = "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC";
const D = "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD";
const a = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
let n = 0;
function acct(owner: string, amount: string, o: { mint?: string; program?: "spl-token" | "spl-token-2022"; type?: string; state?: string; extensions?: unknown[]; pubkey?: string } = {}): ParsedTokenAccountItem {
const program = o.program ?? "spl-token-2022";
return {
pubkey: o.pubkey ?? `TokAcct${String(++n).padStart(37, "x")}`,
account: {
owner: program === "spl-token" ? TOKEN_PROGRAM : TOKEN_2022_PROGRAM,
data: {
program,
parsed: {
type: o.type ?? "account",
info: { mint: o.mint ?? MINT, owner, state: o.state ?? "initialized", tokenAmount: { amount, decimals: 6 }, ...(o.extensions ? { extensions: o.extensions } : {}) },
},
},
},
};
}
const sha = (s: string) => createHash("sha256").update(s, "utf8").digest("hex");
const load = (p: string) => JSON.parse(readFileSync(new URL(`../fixtures/${p}`, import.meta.url), "utf8"));
// A1
test("A1 accounts are grouped by owner across both token programs; other mints, zero balances and non token accounts are ignored", () => {
const accounts = [
acct(A, "100", { program: "spl-token" }),
acct(A, "250", { program: "spl-token-2022" }),
acct(B, "300"),
acct(C, "999", { mint: OTHER_MINT }),
acct(D, "0"),
acct(D, "5", { type: "mint" }),
{ pubkey: "NotParsed11111111111111111111111111111111111", account: { data: ["AAAA", "base64"] } } as unknown as ParsedTokenAccountItem,
];
const s = buildSnapshot({ mint: MINT, slot: 7, accounts, exclusions: { owners: [], token_accounts: [] } });
assert.deepEqual(s.holders, [
{ rank: 1, owner: A, amount: "350" },
{ rank: 2, owner: B, amount: "300" },
]);
assert.equal(s.total, "650");
assert.equal(s.mint, MINT);
assert.equal(s.slot, 7);
});
test("A1 amounts use BigInt: values past 2^53 are summed exactly as decimal strings", () => {
const big = "18446744073709551615"; // u64 max
const s = buildSnapshot({ mint: MINT, slot: 1, accounts: [acct(A, big), acct(A, "1", { program: "spl-token" })], exclusions: {} });
assert.equal(s.holders[0].amount, "18446744073709551616");
assert.equal(s.total, "18446744073709551616");
});
// A2
test("A2 exclusions by owner and by token account are applied, and total counts only what is left", () => {
const keep = acct(B, "40", { pubkey: "KeepAcct11111111111111111111111111111111111" });
const dropAcct = acct(B, "60", { pubkey: "PoolVault1111111111111111111111111111111111" });
const accounts = [acct(A, "500"), acct(A, "1"), keep, dropAcct, acct(C, "10")];
const s = buildSnapshot({
mint: MINT,
slot: 1,
accounts,
exclusions: { owners: [{ address: A, label: "bonding curve" }], token_accounts: ["PoolVault1111111111111111111111111111111111"] },
});
assert.deepEqual(s.holders.map((h) => [h.owner, h.amount]), [[B, "40"], [C, "10"]]);
assert.equal(s.total, "50");
});
// A3
test("A3 ranking by amount descending, ties broken by owner ascending with plain string comparison", () => {
const accounts = [acct(C, "10"), acct(a, "10"), acct(B, "10"), acct(A, "5"), acct(D, "99")];
const s = buildSnapshot({ mint: MINT, slot: 1, accounts, exclusions: {} });
// "B" < "C" < "a" in code unit order (upper case sorts before lower case)
assert.deepEqual(s.holders.map((h) => [h.rank, h.owner]), [[1, D], [2, B], [3, C], [4, a], [5, A]]);
});
test("A3 top keeps the first N (default 100) while total still covers every counted owner", () => {
const accounts = Array.from({ length: 130 }, (_, i) => acct(`Own${String(i).padStart(41, "x")}`, String(1000 - i)));
const s = buildSnapshot({ mint: MINT, slot: 1, accounts, exclusions: {} });
assert.equal(s.holders.length, 100);
assert.equal(s.holders[99].rank, 100);
const s3 = buildSnapshot({ mint: MINT, slot: 1, accounts, exclusions: {}, top: 3 });
assert.deepEqual(s3.holders.map((h) => h.amount), ["1000", "999", "998"]);
const expectedTotal = accounts.reduce((t, x) => t + BigInt((x.account.data as any).parsed.info.tokenAmount.amount), 0n).toString();
assert.equal(s3.total, expectedTotal);
assert.throws(() => buildSnapshot({ mint: MINT, slot: 1, accounts, exclusions: {}, top: 0 }), RangeError);
});
// A4
test("A4 the hash is sha256 of rank,owner,amount lines joined by a newline with no trailing newline", () => {
const s = buildSnapshot({ mint: MINT, slot: 1, accounts: [acct(A, "7"), acct(B, "9")], exclusions: {} });
assert.equal(s.hash, sha(`1,${B},9\n2,${A},7`));
assert.match(s.hash, /^[0-9a-f]{64}$/);
const empty = buildSnapshot({ mint: MINT, slot: 1, accounts: [], exclusions: {} });
assert.equal(empty.hash, sha(""));
});
test("A4 the same accounts in any order give the same snapshot and hash", () => {
const fx = load("token2022-full.json");
const first = buildSnapshot({ mint: fx.mint, slot: fx.slot, accounts: fx.accounts, exclusions: {} });
const reversed = buildSnapshot({ mint: fx.mint, slot: fx.slot, accounts: [...fx.accounts].reverse(), exclusions: {} });
let seed = 42;
const shuffled = [...fx.accounts].sort(() => ((seed = (seed * 1103515245 + 12345) % 2147483648) / 2147483648) - 0.5);
const third = buildSnapshot({ mint: fx.mint, slot: fx.slot, accounts: shuffled, exclusions: {} });
assert.deepEqual(reversed, first);
assert.deepEqual(third, first);
});
// A5
test("A5 Token 2022 accounts with extensions (transfer fee, immutable owner) and a frozen state count by their amount", () => {
const accounts = [
acct(A, "70", { extensions: [{ extension: "immutableOwner" }, { extension: "transferFeeAmount", state: { withheldAmount: 5 } }] }),
acct(B, "30", { state: "frozen", extensions: [{ extension: "immutableOwner" }] }),
acct(C, "20", { extensions: [{ extension: "transferHookAccount", state: { transferring: false } }] }),
];
const s = buildSnapshot({ mint: MINT, slot: 1, accounts, exclusions: {} });
assert.deepEqual(s.holders.map((h) => [h.owner, h.amount]), [[A, "70"], [B, "30"], [C, "20"]]);
assert.equal(s.total, "120");
});
test("A5 recorded PYUSD Token 2022 accounts with transfer fee, transfer hook and frozen state are read as recorded", () => {
const fx = load("pyusd-token2022-sample.json");
const frozen = fx.accounts.filter((x: any) => x.account.data.parsed.info.state === "frozen");
assert.ok(frozen.length > 0, "the sample holds frozen accounts");
assert.ok(fx.accounts.some((x: any) => (x.account.data.parsed.info.extensions ?? []).some((e: any) => e.extension === "transferFeeAmount")));
// a frozen account with a positive balance must count; force one from the recorded shape
const f = structuredClone(frozen[0]);
f.account.data.parsed.info.tokenAmount.amount = "123";
f.account.data.parsed.info.owner = A;
const s = buildSnapshot({ mint: fx.mint, slot: fx.slot, accounts: [...fx.accounts, f], exclusions: {} });
assert.ok(s.holders.some((h) => h.owner === A && h.amount === "123"));
const base = buildSnapshot({ mint: fx.mint, slot: fx.slot, accounts: fx.accounts, exclusions: {} });
assert.equal(base.total, "2759326745");
assert.equal(base.hash, "d433fa17c701bda5626cae0ded1e90389370956a42732a47bb0dae1d515d838d");
});
// A6
test("A6 fetchAccounts sends one getProgramAccounts call per token program and returns the lowest context slot", async () => {
const calls: any[] = [];
const fake = async (url: string, init: any) => {
const body = JSON.parse(init.body);
calls.push({ url, body, method: init.method });
const isLegacy = body.params[0] === TOKEN_PROGRAM;
return {
ok: true,
status: 200,
json: async () => ({ jsonrpc: "2.0", id: body.id, result: { context: { slot: isLegacy ? 500 : 480 }, value: [acct(A, isLegacy ? "1" : "2", { program: isLegacy ? "spl-token" : "spl-token-2022" })] } }),
};
};
const r = await fetchAccounts({ rpcUrl: "https://rpc.invalid/secret-key", mint: MINT, fetch: fake });
assert.equal(calls.length, 2);
assert.deepEqual(calls.map((c) => c.body.params[0]).sort(), [TOKEN_PROGRAM, TOKEN_2022_PROGRAM].sort());
for (const c of calls) {
assert.equal(c.method, "POST");
assert.equal(c.body.method, "getProgramAccounts");
assert.deepEqual(c.body.params[1], { encoding: "jsonParsed", withContext: true, filters: [{ memcmp: { offset: 0, bytes: MINT } }] });
}
assert.equal(r.slot, 480);
assert.equal(r.accounts.length, 2);
assert.equal(programAccountsRequest(TOKEN_PROGRAM, MINT, 1, 9).params[1].minContextSlot, 9);
});
test("A6 fetchAccounts reports RPC errors without the RPC URL", async () => {
const fake = async () => ({ ok: true, status: 200, json: async () => ({ error: { code: -32010, message: "excluded from account secondary indexes" } }) });
await assert.rejects(fetchAccounts({ rpcUrl: "https://rpc.invalid/secret-key", mint: MINT, fetch: fake }), (e: Error) => /excluded/.test(e.message) && !/secret-key/.test(e.message));
const down = async () => ({ ok: false, status: 503, json: async () => ({}) });
await assert.rejects(fetchAccounts({ rpcUrl: "https://rpc.invalid/secret-key", mint: MINT, fetch: down }), /HTTP 503/);
});
test("A6 the CLI writes the snapshot from a recorded fixture with no network, and saves a fixture", async () => {
const dir = mkdtempSync(join(tmpdir(), "kogsnap-"));
const ex = join(dir, "ex.json");
writeFileSync(ex, JSON.stringify({ owners: ["FhVo3mqL8PW5pH5U2CN4XE33DokiyZnUwuGpH2hmHLuM"], token_accounts: [] }));
const out = join(dir, "snap.json");
const fixture = new URL("../fixtures/token2022-full.json", import.meta.url).pathname;
let fetched = 0;
const code = await run(["--mint", MINT, "--exclusions", ex, "--fixture", fixture, "--top", "10", "--out", out, "--save-fixture", join(dir, "fx.json")], {
env: {},
fetch: async () => {
fetched++;
throw new Error("no network in this test");
},
});
assert.equal(code, 0);
assert.equal(fetched, 0);
const snap = JSON.parse(readFileSync(out, "utf8"));
assert.equal(snap.holders.length, 10);
assert.ok(!snap.holders.some((h: any) => h.owner === "FhVo3mqL8PW5pH5U2CN4XE33DokiyZnUwuGpH2hmHLuM"));
assert.ok(existsSync(join(dir, "fx.json")));
// the spawned bin gives the same answer on stdout
const r = spawnSync(process.execPath, ["--import", "tsx", "src/bin.ts", "--mint", MINT, "--exclusions", ex, "--fixture", fixture, "--top", "10"], { encoding: "utf8", env: { ...process.env, SOLANA_RPC_URL: "" } });
assert.equal(r.status, 0, r.stderr);
assert.deepEqual(JSON.parse(r.stdout), snap);
});
test("A6 the CLI exits 1 with a plain message on bad input and never prints the RPC URL", async () => {
const dir = mkdtempSync(join(tmpdir(), "kogsnap-"));
const ex = join(dir, "ex.json");
writeFileSync(ex, "{}");
const cases: Array<[string[], RegExp]> = [
[["--exclusions", ex], /missing --mint/],
[["--mint", "not-a-mint!", "--exclusions", ex], /base58/],
[["--mint", MINT, "--exclusions", join(dir, "nope.json"), "--fixture", "x"], /cannot read exclusions/],
[["--mint", MINT, "--exclusions", ex, "--fixture", join(dir, "nope.json")], /cannot read fixture/],
[["--mint", MINT, "--exclusions", ex, "--top", "-1"], /needs a value|whole number/],
[["--mint", MINT, "--exclusions", ex, "--bogus", "1"], /unknown option/],
];
for (const [argv, re] of cases) {
let err = "";
const code = await run(argv, { env: {}, stderr: (s) => (err += s), stdout: () => {} });
assert.equal(code, 1, argv.join(" "));
assert.match(err, re);
}
let err = "";
const secret = "https://mainnet.helius-rpc.example/?api-key=SECRET123";
const code = await run(["--mint", MINT, "--exclusions", ex], {
env: { SOLANA_RPC_URL: secret },
stderr: (s) => (err += s),
fetch: async () => ({ ok: true, status: 200, json: async () => ({ error: { message: `bad key for ${secret}` } }) }),
});
assert.equal(code, 1);
assert.match(err, /RPC error/);
assert.ok(!err.includes("SECRET123"));
const r = spawnSync(process.execPath, ["--import", "tsx", "src/bin.ts", "--exclusions", ex], { encoding: "utf8" });
assert.equal(r.status, 1);
assert.match(r.stderr, /missing --mint/);
});
// A7
test("A7 recorded fixture of a real Token 2022 mint gives the pinned snapshot (checked by an independent Python count)", () => {
const fx = load("token2022-full.json");
assert.equal(fx.mint, MINT);
assert.ok(fx.accounts.every((x: any) => x.account.owner === TOKEN_2022_PROGRAM));
const s = buildSnapshot({ mint: fx.mint, slot: fx.slot, accounts: fx.accounts, exclusions: { owners: [], token_accounts: [] } });
assert.equal(s.slot, 459792671);
assert.equal(s.total, "1000000000000000");
assert.equal(s.holders.length, 100);
assert.deepEqual(s.holders[0], { rank: 1, owner: "FhVo3mqL8PW5pH5U2CN4XE33DokiyZnUwuGpH2hmHLuM", amount: "900525968095527" });
assert.equal(s.hash, "03c58f3a5cb5ab11c518c82c69375cf498c0de3de842d2fdf1ead8fed39f6db2");
});
test("A7 seat interface snapshot({accounts, exclusions, top}) gives the same holders and hash", () => {
const fx = load("token2022-full.json");
const s = snapshot({ accounts: fx.accounts, exclusions: { owners: [], token_accounts: [] }, top: 100 });
assert.equal(s.hash, "03c58f3a5cb5ab11c518c82c69375cf498c0de3de842d2fdf1ead8fed39f6db2");
});
test("A1 the same token account listed twice (for example by both program calls) counts once", () => {
const one = acct(A, "500", { pubkey: "DupTokenAccount1111111111111111111111111111" });
const r = buildSnapshot({ mint: MINT, slot: 1, accounts: [one, structuredClone(one), acct(B, "400")], exclusions: { owners: [], token_accounts: [] } });
assert.deepEqual(r.holders.map((h) => [h.owner, h.amount]), [[A, "500"], [B, "400"]]);
assert.equal(r.total, "900");
});
agentgate-source: code mirror on Cloudflare Pages. All repos