kog-holder-snapshot / tree / test/snapshot.test.ts ยท raw (this view has old GitHub links rewritten for the mirror; raw is byte-exact)
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