import { test } from "node:test";
import assert from "node:assert/strict";
import { verifyKogFee } from "../src/index.js";
import { load, PYUSD, USDG, X402, MEMO, USDG_TX } from "./fixtures.js";
const quote = (amount: string, expires_at: number | string = X402.blockTime + 60) => ({ amount, expires_at });
test("A1 right fee: a recorded Token 2022 x402 payment of the quoted amount to the payee is accepted", () => {
const tx = load(X402.name);
const r = verifyKogFee({ tx, quote: quote(X402.amount), payee: X402.payee, mint: PYUSD, seen: new Set() });
assert.deepEqual(r, { ok: true, reason: "ok", signature: tx.transaction.signatures[0], received: X402.amount });
// paying more than the quote is fine; the payee may also be given as its token account
assert.equal(verifyKogFee({ tx, quote: quote("39999999"), payee: X402.payee, mint: PYUSD }).ok, true);
assert.equal(verifyKogFee({ tx, quote: quote(X402.amount), payee: X402.payeeAta, mint: PYUSD }).ok, true);
// a second real transfer (with a memo instruction) also passes
const m = load(MEMO.name);
assert.equal(verifyKogFee({ tx: m, quote: { amount: MEMO.amount, expires_at: MEMO.blockTime }, payee: MEMO.payee, mint: PYUSD }).reason, "ok");
});
test("A2 short fee: a payment below the quote is refused with short_fee and the amount received", () => {
const tx = load(X402.name);
const r = verifyKogFee({ tx, quote: quote("40000001"), payee: X402.payee, mint: PYUSD, seen: [] });
assert.equal(r.ok, false);
assert.equal(r.reason, "short_fee");
assert.equal(r.received, X402.amount);
});
test("A3 wrong mint: a real Token 2022 transfer in another mint is refused", () => {
const tx = load(USDG_TX.name);
const r = verifyKogFee({ tx, quote: { amount: "1", expires_at: USDG_TX.blockTime + 60 }, payee: USDG_TX.payee, mint: PYUSD });
assert.deepEqual([r.ok, r.reason], [false, "wrong_mint"]);
// the same transaction is fine for its own mint
assert.equal(verifyKogFee({ tx, quote: { amount: USDG_TX.amount, expires_at: USDG_TX.blockTime }, payee: USDG_TX.payee, mint: USDG }).ok, true);
});
test("A4 wrong payee: the right mint paid to someone else is refused, including the payer itself", () => {
const tx = load(X402.name);
for (const payee of [MEMO.payee, X402.payer]) {
const r = verifyKogFee({ tx, quote: quote("1"), payee, mint: PYUSD });
assert.deepEqual([r.ok, r.reason], [false, "wrong_payee"], payee);
}
});
test("A5 expired quote: a payment landed after the quote expiry is refused", () => {
const tx = load(X402.name);
assert.equal(verifyKogFee({ tx, quote: quote(X402.amount, X402.blockTime - 1), payee: X402.payee, mint: PYUSD }).reason, "expired");
assert.equal(verifyKogFee({ tx, quote: quote(X402.amount, X402.blockTime), payee: X402.payee, mint: PYUSD }).reason, "ok");
const iso = new Date((X402.blockTime - 30) * 1000).toISOString();
assert.equal(verifyKogFee({ tx, quote: quote(X402.amount, iso), payee: X402.payee, mint: PYUSD }).reason, "expired");
// with no blockTime the caller's now is used, and with neither the input is refused
const noTime = { ...tx, blockTime: null };
assert.equal(verifyKogFee({ tx: noTime, quote: quote(X402.amount, 100), payee: X402.payee, mint: PYUSD, now: 101 }).reason, "expired");
assert.equal(verifyKogFee({ tx: noTime, quote: quote(X402.amount, 100), payee: X402.payee, mint: PYUSD }).reason, "bad_input");
});
test("A6 replay: a signature already used for a fee is refused, whatever form seen takes", () => {
const tx = load(X402.name);
const sig = tx.transaction.signatures[0];
for (const seen of [new Set([sig]), [sig], new Map([[sig, true]]), { has: (s: string) => s === sig }]) {
const r = verifyKogFee({ tx, quote: quote(X402.amount), payee: X402.payee, mint: PYUSD, seen });
assert.deepEqual([r.ok, r.reason, r.signature], [false, "replay", sig]);
}
});
test("A7 a failed transaction, a bad quote or malformed input never pass", () => {
const tx = load(X402.name);
const failed = structuredClone(tx);
failed.meta.err = { InstructionError: [2, { Custom: 1 }] };
assert.equal(verifyKogFee({ tx: failed, quote: quote(X402.amount), payee: X402.payee, mint: PYUSD }).reason, "tx_failed");
assert.equal(verifyKogFee({ tx, quote: quote("0"), payee: X402.payee, mint: PYUSD }).reason, "bad_quote");
assert.equal(verifyKogFee({ tx, quote: quote("1.5"), payee: X402.payee, mint: PYUSD }).reason, "bad_quote");
assert.equal(verifyKogFee({ tx, quote: { amount: X402.amount, expires_at: "soon" }, payee: X402.payee, mint: PYUSD }).reason, "bad_quote");
assert.equal(verifyKogFee({ tx, quote: { ...quote(X402.amount), mint: USDG }, payee: X402.payee, mint: PYUSD }).reason, "bad_quote");
assert.equal(verifyKogFee({ tx: {}, quote: quote(X402.amount), payee: X402.payee, mint: PYUSD }).reason, "bad_input");
assert.equal(verifyKogFee({ tx, quote: quote(X402.amount), payee: "", mint: PYUSD }).reason, "bad_input");
assert.equal(verifyKogFee(null as any).reason, "bad_input");
});
test("A7 a balance rise without a transfer instruction to the payee (for example a swap) is not a fee", () => {
const tx = structuredClone(load(X402.name));
tx.transaction.message.instructions = tx.transaction.message.instructions.filter((i: any) => i.parsed?.type !== "transferChecked");
assert.equal(verifyKogFee({ tx, quote: quote("1"), payee: X402.payee, mint: PYUSD }).reason, "wrong_mint");
});
test("A7 the verifier is pure: same input, same answer, and the transaction is not changed", () => {
const tx = load(X402.name);
const before = JSON.stringify(tx);
const a = verifyKogFee({ tx, quote: quote(X402.amount), payee: X402.payee, mint: PYUSD });
const b = verifyKogFee({ tx, quote: quote(X402.amount), payee: X402.payee, mint: PYUSD });
assert.deepEqual(a, b);
assert.equal(JSON.stringify(tx), before);
});
test("A7 a quote bound to another payee or mint is refused as bad_quote", () => {
const tx = load(X402.name);
const base = { amount: X402.amount, expires_at: X402.blockTime + 60 };
assert.equal(verifyKogFee({ tx, quote: { ...base, payee: X402.payee, mint: PYUSD }, payee: X402.payee, mint: PYUSD }).ok, true);
assert.equal(verifyKogFee({ tx, quote: { ...base, payee: MEMO.payee }, payee: X402.payee, mint: PYUSD }).reason, "bad_quote");
assert.equal(verifyKogFee({ tx, quote: { ...base, mint: USDG }, payee: X402.payee, mint: PYUSD }).reason, "bad_quote");
});
test("A2 short fee: a payee token account closed in the same transaction counts against what was received", () => {
const tx = load(X402.name);
const keys = tx.transaction.message.accountKeys;
const idx = keys.length;
keys.push(typeof keys[0] === "string" ? "ClosedPayeeAta11111111111111111111111111111" : { ...keys[0], pubkey: "ClosedPayeeAta11111111111111111111111111111", signer: false, writable: true });
tx.meta.preTokenBalances.push({ accountIndex: idx, mint: PYUSD, owner: X402.payee, uiTokenAmount: { amount: "1000", decimals: 6 } });
const r = verifyKogFee({ tx, quote: { amount: X402.amount, expires_at: X402.blockTime + 60 }, payee: X402.payee, mint: PYUSD });
assert.deepEqual([r.ok, r.reason, r.received], [false, "short_fee", String(BigInt(X402.amount) - 1000n)]);
});
agentgate-source: code mirror on Cloudflare Pages. All repos