@leashmarket/core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/README.md +32 -0
  2. package/dist/agent/agent.d.ts +8 -0
  3. package/dist/agent/agent.d.ts.map +1 -0
  4. package/dist/agent/agent.js +14 -0
  5. package/dist/agent/agent.js.map +1 -0
  6. package/dist/agent/treasury-pda.d.ts +49 -0
  7. package/dist/agent/treasury-pda.d.ts.map +1 -0
  8. package/dist/agent/treasury-pda.js +55 -0
  9. package/dist/agent/treasury-pda.js.map +1 -0
  10. package/dist/explorer/index.d.ts +55 -0
  11. package/dist/explorer/index.d.ts.map +1 -0
  12. package/dist/explorer/index.js +95 -0
  13. package/dist/explorer/index.js.map +1 -0
  14. package/dist/fees/leash-fee.d.ts +248 -0
  15. package/dist/fees/leash-fee.d.ts.map +1 -0
  16. package/dist/fees/leash-fee.js +246 -0
  17. package/dist/fees/leash-fee.js.map +1 -0
  18. package/dist/format/index.d.ts +55 -0
  19. package/dist/format/index.d.ts.map +1 -0
  20. package/dist/format/index.js +130 -0
  21. package/dist/format/index.js.map +1 -0
  22. package/dist/index.d.ts +25 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +25 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/policy/evaluate.d.ts +17 -0
  27. package/dist/policy/evaluate.d.ts.map +1 -0
  28. package/dist/policy/evaluate.js +46 -0
  29. package/dist/policy/evaluate.js.map +1 -0
  30. package/dist/policy/state.d.ts +8 -0
  31. package/dist/policy/state.d.ts.map +1 -0
  32. package/dist/policy/state.js +2 -0
  33. package/dist/policy/state.js.map +1 -0
  34. package/dist/receipt/build.d.ts +5 -0
  35. package/dist/receipt/build.d.ts.map +1 -0
  36. package/dist/receipt/build.js +9 -0
  37. package/dist/receipt/build.js.map +1 -0
  38. package/dist/receipt/hash.d.ts +15 -0
  39. package/dist/receipt/hash.d.ts.map +1 -0
  40. package/dist/receipt/hash.js +40 -0
  41. package/dist/receipt/hash.js.map +1 -0
  42. package/dist/receipt/verify.d.ts +10 -0
  43. package/dist/receipt/verify.d.ts.map +1 -0
  44. package/dist/receipt/verify.js +36 -0
  45. package/dist/receipt/verify.js.map +1 -0
  46. package/dist/tokens/index.d.ts +86 -0
  47. package/dist/tokens/index.d.ts.map +1 -0
  48. package/dist/tokens/index.js +163 -0
  49. package/dist/tokens/index.js.map +1 -0
  50. package/dist/treasury/balance.d.ts +3 -0
  51. package/dist/treasury/balance.d.ts.map +1 -0
  52. package/dist/treasury/balance.js +13 -0
  53. package/dist/treasury/balance.js.map +1 -0
  54. package/dist/treasury/inspect-token-account.d.ts +46 -0
  55. package/dist/treasury/inspect-token-account.d.ts.map +1 -0
  56. package/dist/treasury/inspect-token-account.js +67 -0
  57. package/dist/treasury/inspect-token-account.js.map +1 -0
  58. package/dist/treasury/list-balances.d.ts +57 -0
  59. package/dist/treasury/list-balances.d.ts.map +1 -0
  60. package/dist/treasury/list-balances.js +115 -0
  61. package/dist/treasury/list-balances.js.map +1 -0
  62. package/dist/treasury/pause.d.ts +32 -0
  63. package/dist/treasury/pause.d.ts.map +1 -0
  64. package/dist/treasury/pause.js +40 -0
  65. package/dist/treasury/pause.js.map +1 -0
  66. package/dist/treasury/withdraw.d.ts +13 -0
  67. package/dist/treasury/withdraw.d.ts.map +1 -0
  68. package/dist/treasury/withdraw.js +4 -0
  69. package/dist/treasury/withdraw.js.map +1 -0
  70. package/dist/wallet/index.d.ts +3 -0
  71. package/dist/wallet/index.d.ts.map +1 -0
  72. package/dist/wallet/index.js +2 -0
  73. package/dist/wallet/index.js.map +1 -0
  74. package/dist/x402/client.d.ts +72 -0
  75. package/dist/x402/client.d.ts.map +1 -0
  76. package/dist/x402/client.js +94 -0
  77. package/dist/x402/client.js.map +1 -0
  78. package/dist/x402/delegate-scheme.d.ts +107 -0
  79. package/dist/x402/delegate-scheme.d.ts.map +1 -0
  80. package/dist/x402/delegate-scheme.js +268 -0
  81. package/dist/x402/delegate-scheme.js.map +1 -0
  82. package/dist/x402/discovery.d.ts +110 -0
  83. package/dist/x402/discovery.d.ts.map +1 -0
  84. package/dist/x402/discovery.js +213 -0
  85. package/dist/x402/discovery.js.map +1 -0
  86. package/dist/x402/envelope.d.ts +65 -0
  87. package/dist/x402/envelope.d.ts.map +1 -0
  88. package/dist/x402/envelope.js +67 -0
  89. package/dist/x402/envelope.js.map +1 -0
  90. package/dist/x402/facilitator.d.ts +45 -0
  91. package/dist/x402/facilitator.d.ts.map +1 -0
  92. package/dist/x402/facilitator.js +61 -0
  93. package/dist/x402/facilitator.js.map +1 -0
  94. package/dist/x402/headers.d.ts +51 -0
  95. package/dist/x402/headers.d.ts.map +1 -0
  96. package/dist/x402/headers.js +84 -0
  97. package/dist/x402/headers.js.map +1 -0
  98. package/dist/x402/parse.d.ts +20 -0
  99. package/dist/x402/parse.d.ts.map +1 -0
  100. package/dist/x402/parse.js +31 -0
  101. package/dist/x402/parse.js.map +1 -0
  102. package/dist/x402/webhook.d.ts +48 -0
  103. package/dist/x402/webhook.d.ts.map +1 -0
  104. package/dist/x402/webhook.js +88 -0
  105. package/dist/x402/webhook.js.map +1 -0
  106. package/package.json +46 -0
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Synchronous SHA-256 via `@noble/hashes` so receipts can be hashed in
3
+ * Node, in the browser (Privy buyer), and in workers without depending
4
+ * on `node:crypto` or async `crypto.subtle`.
5
+ */
6
+ export declare function requestHash(input: {
7
+ method: string;
8
+ url: string;
9
+ body: string | null;
10
+ headers?: Record<string, string>;
11
+ }): string;
12
+ export declare function sha256Hex(data: string): string;
13
+ /** Stable JSON stringify with sorted keys (shallow + deep for plain objects). */
14
+ export declare function canonicalJson(value: unknown): string;
15
+ //# sourceMappingURL=hash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/receipt/hash.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC,GAAG,MAAM,CAUT;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED,iFAAiF;AACjF,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEpD"}
@@ -0,0 +1,40 @@
1
+ import { sha256 } from '@noble/hashes/sha256';
2
+ import { bytesToHex, utf8ToBytes } from '@noble/hashes/utils';
3
+ /**
4
+ * Synchronous SHA-256 via `@noble/hashes` so receipts can be hashed in
5
+ * Node, in the browser (Privy buyer), and in workers without depending
6
+ * on `node:crypto` or async `crypto.subtle`.
7
+ */
8
+ export function requestHash(input) {
9
+ const parts = [input.method, input.url, input.body ?? ''];
10
+ if (input.headers) {
11
+ const keys = Object.keys(input.headers).sort();
12
+ for (const k of keys) {
13
+ parts.push(`${k}=${String(input.headers[k])}`);
14
+ }
15
+ }
16
+ const concatenated = `${parts.join('\n')}\n`;
17
+ return `sha256:${bytesToHex(sha256(utf8ToBytes(concatenated)))}`;
18
+ }
19
+ export function sha256Hex(data) {
20
+ return bytesToHex(sha256(utf8ToBytes(data)));
21
+ }
22
+ /** Stable JSON stringify with sorted keys (shallow + deep for plain objects). */
23
+ export function canonicalJson(value) {
24
+ return JSON.stringify(sortKeys(value));
25
+ }
26
+ function sortKeys(value) {
27
+ if (value === null || typeof value !== 'object') {
28
+ return value;
29
+ }
30
+ if (Array.isArray(value)) {
31
+ return value.map(sortKeys);
32
+ }
33
+ const obj = value;
34
+ const out = {};
35
+ for (const k of Object.keys(obj).sort()) {
36
+ out[k] = sortKeys(obj[k]);
37
+ }
38
+ return out;
39
+ }
40
+ //# sourceMappingURL=hash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hash.js","sourceRoot":"","sources":["../../src/receipt/hash.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAE9D;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,KAK3B;IACC,MAAM,KAAK,GAAa,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IACpE,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAClB,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;QAC/C,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;YACrB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IACD,MAAM,YAAY,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;IAC7C,OAAO,UAAU,UAAU,CAAC,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;AACnE,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,OAAO,UAAU,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC/C,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;AACzC,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC7B,CAAC;IACD,MAAM,GAAG,GAAG,KAAgC,CAAC;IAC7C,MAAM,GAAG,GAA4B,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QACxC,GAAG,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,10 @@
1
+ export type VerifyResult = {
2
+ ok: true;
3
+ count: number;
4
+ } | {
5
+ ok: false;
6
+ nonce: number;
7
+ reason: string;
8
+ };
9
+ export declare function verifyReceiptChain(lines: string[]): VerifyResult;
10
+ //# sourceMappingURL=verify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/receipt/verify.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,YAAY,GACpB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC3B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,YAAY,CA8BhE"}
@@ -0,0 +1,36 @@
1
+ import { ReceiptV1Schema } from '@leashmarket/schemas';
2
+ import { computeReceiptHash } from './build.js';
3
+ export function verifyReceiptChain(lines) {
4
+ let prev = null;
5
+ for (let i = 0; i < lines.length; i++) {
6
+ const line = lines[i]?.trim();
7
+ if (!line)
8
+ continue;
9
+ let parsed;
10
+ try {
11
+ parsed = JSON.parse(line);
12
+ }
13
+ catch {
14
+ return { ok: false, nonce: i, reason: 'invalid_json' };
15
+ }
16
+ const r = ReceiptV1Schema.safeParse(parsed);
17
+ if (!r.success) {
18
+ return { ok: false, nonce: i, reason: 'invalid_schema' };
19
+ }
20
+ const rec = r.data;
21
+ if (rec.nonce !== i) {
22
+ return { ok: false, nonce: i, reason: 'nonce_mismatch' };
23
+ }
24
+ if (rec.prev_receipt_hash !== prev) {
25
+ return { ok: false, nonce: i, reason: 'prev_hash_mismatch' };
26
+ }
27
+ const { receipt_hash, ...rest } = rec;
28
+ const expected = computeReceiptHash(rest);
29
+ if (receipt_hash !== expected) {
30
+ return { ok: false, nonce: i, reason: 'receipt_hash_mismatch' };
31
+ }
32
+ prev = rec.receipt_hash;
33
+ }
34
+ return { ok: true, count: lines.filter((l) => l.trim()).length };
35
+ }
36
+ //# sourceMappingURL=verify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/receipt/verify.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAMhD,MAAM,UAAU,kBAAkB,CAAC,KAAe;IAChD,IAAI,IAAI,GAAkB,IAAI,CAAC;IAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;QAC9B,IAAI,CAAC,IAAI;YAAE,SAAS;QACpB,IAAI,MAAe,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAY,CAAC;QACvC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;QACzD,CAAC;QACD,MAAM,CAAC,GAAG,eAAe,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QAC5C,IAAI,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;YACf,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;QAC3D,CAAC;QACD,MAAM,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC;QACnB,IAAI,GAAG,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;YACpB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;QAC3D,CAAC;QACD,IAAI,GAAG,CAAC,iBAAiB,KAAK,IAAI,EAAE,CAAC;YACnC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,oBAAoB,EAAE,CAAC;QAC/D,CAAC;QACD,MAAM,EAAE,YAAY,EAAE,GAAG,IAAI,EAAE,GAAG,GAAG,CAAC;QACtC,MAAM,QAAQ,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;QAC1C,IAAI,YAAY,KAAK,QAAQ,EAAE,CAAC;YAC9B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,uBAAuB,EAAE,CAAC;QAClE,CAAC;QACD,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC;IAC1B,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;AACnE,CAAC"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Static registry of well-known SPL token mints used by the Leash UI / CLI
3
+ * surfaces to enrich raw RPC balances with symbols, decimals, and the
4
+ * correct token program id. The registry deliberately stays small —
5
+ * stables + bluechips that are policy-relevant for x402 / agent treasuries.
6
+ *
7
+ * For full registry resolution (Token-2022 metadata, Jupiter token list,
8
+ * etc.) consume an external source; this module covers the common case so
9
+ * SDK consumers never need to hard-code mint addresses.
10
+ *
11
+ * Mainnet and devnet entries are listed separately because devnet stables
12
+ * are usually faucet-mintable test versions with different mint authorities
13
+ * than their mainnet counterparts.
14
+ */
15
+ export declare const TOKEN_PROGRAM_ID = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
16
+ export declare const TOKEN_2022_PROGRAM_ID = "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb";
17
+ export type TokenProgram = 'spl-token' | 'spl-token-2022';
18
+ export type TokenNetwork = 'mainnet' | 'devnet';
19
+ export type KnownToken = {
20
+ mint: string;
21
+ symbol: string;
22
+ name: string;
23
+ decimals: number;
24
+ /**
25
+ * SPL token program owning this mint. Defaults to legacy `spl-token` when
26
+ * omitted by callers; explicit on every entry below for clarity.
27
+ */
28
+ program: TokenProgram;
29
+ /** True when the token is a USD-pegged stablecoin. */
30
+ stable: boolean;
31
+ };
32
+ export declare const KNOWN_TOKENS: Record<TokenNetwork, ReadonlyArray<KnownToken>>;
33
+ /** Look up a known token by mint address on a given network. */
34
+ export declare function lookupToken(mint: string, network: TokenNetwork): KnownToken | undefined;
35
+ /**
36
+ * Symbols of the well-known USD-pegged stablecoins Leash supports for x402
37
+ * settlement. Restricted to the registry's stable entries so consumers can
38
+ * pin a typed dropdown without re-deriving the list.
39
+ */
40
+ export type KnownStableSymbol = 'USDC' | 'USDT' | 'USDG';
41
+ /** All stablecoin tickers we recognise on at least one network. */
42
+ export declare const KNOWN_STABLE_SYMBOLS: ReadonlyArray<KnownStableSymbol>;
43
+ /**
44
+ * Look up a known token by ticker symbol (case-insensitive) on a given
45
+ * network. Useful for translating a user-facing currency dropdown into the
46
+ * underlying mint address required by x402 `AssetAmount` prices.
47
+ */
48
+ export declare function lookupTokenBySymbol(symbol: string, network: TokenNetwork): KnownToken | undefined;
49
+ /**
50
+ * Reverse-lookup a currency ticker for an asset mint. Falls back to `'USDC'`
51
+ * (the v0.1 default settlement currency) when the mint is unknown — buyer
52
+ * receipts surface a usable label even if the seller advertises a token the
53
+ * Leash registry hasn't catalogued yet.
54
+ */
55
+ export declare function currencyForAsset(asset: string | null | undefined, network: TokenNetwork): string;
56
+ /**
57
+ * Mints we always want to render in a treasury UI even when the agent
58
+ * holds zero — the headline stables. Other tokens only appear once the
59
+ * agent actually holds a balance.
60
+ */
61
+ export declare function pinnedMints(network: TokenNetwork): string[];
62
+ /**
63
+ * Heuristic mapping of an RPC URL to a logical network bucket. Treats
64
+ * anything containing `devnet`, `localhost`, or a private-network IP as
65
+ * devnet; everything else as mainnet.
66
+ */
67
+ export declare function networkFromRpc(rpc: string): TokenNetwork;
68
+ /**
69
+ * Resolve the canonical USDC mint for the given network. Used by buyer-kit
70
+ * pre-flight checks ("does the treasury have enough?") and by UI to seed
71
+ * default token selectors.
72
+ */
73
+ export declare function defaultUsdcMint(network: TokenNetwork): KnownToken;
74
+ /**
75
+ * Look up the SPL token program a known mint lives under (`spl-token` for
76
+ * legacy or `spl-token-2022` for Token-2022). Tries both networks since
77
+ * known stable mints are disjoint, so callers don't have to thread the
78
+ * x402 envelope's CAIP-2 network down through every layer.
79
+ *
80
+ * Returns `null` when the mint isn't catalogued — callers should default
81
+ * to legacy SPL token for back-compat, but this lets surfaces that DO
82
+ * understand Token-2022 (Pay card, buyer-kit preflight, withdraw flow)
83
+ * pick the right ATA without hard-coding mints.
84
+ */
85
+ export declare function tokenProgramForMint(mint: string): TokenProgram | null;
86
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tokens/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,eAAO,MAAM,gBAAgB,gDAAgD,CAAC;AAC9E,eAAO,MAAM,qBAAqB,gDAAgD,CAAC;AAEnF,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG,gBAAgB,CAAC;AAC1D,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEhD,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,OAAO,EAAE,YAAY,CAAC;IACtB,sDAAsD;IACtD,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAwEF,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,YAAY,EAAE,aAAa,CAAC,UAAU,CAAC,CAGxE,CAAC;AAEF,gEAAgE;AAChE,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,UAAU,GAAG,SAAS,CAEvF;AAED;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAEzD,mEAAmE;AACnE,eAAO,MAAM,oBAAoB,EAAE,aAAa,CAAC,iBAAiB,CAA4B,CAAC;AAE/F;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,UAAU,GAAG,SAAS,CAGjG;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,OAAO,EAAE,YAAY,GAAG,MAAM,CAGhG;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,EAAE,CAE3D;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAExD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,UAAU,CAMjE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAOrE"}
@@ -0,0 +1,163 @@
1
+ /**
2
+ * Static registry of well-known SPL token mints used by the Leash UI / CLI
3
+ * surfaces to enrich raw RPC balances with symbols, decimals, and the
4
+ * correct token program id. The registry deliberately stays small —
5
+ * stables + bluechips that are policy-relevant for x402 / agent treasuries.
6
+ *
7
+ * For full registry resolution (Token-2022 metadata, Jupiter token list,
8
+ * etc.) consume an external source; this module covers the common case so
9
+ * SDK consumers never need to hard-code mint addresses.
10
+ *
11
+ * Mainnet and devnet entries are listed separately because devnet stables
12
+ * are usually faucet-mintable test versions with different mint authorities
13
+ * than their mainnet counterparts.
14
+ */
15
+ export const TOKEN_PROGRAM_ID = 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA';
16
+ export const TOKEN_2022_PROGRAM_ID = 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb';
17
+ const MAINNET = [
18
+ {
19
+ mint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
20
+ symbol: 'USDC',
21
+ name: 'USD Coin',
22
+ decimals: 6,
23
+ program: 'spl-token',
24
+ stable: true,
25
+ },
26
+ {
27
+ mint: 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB',
28
+ symbol: 'USDT',
29
+ name: 'Tether USD',
30
+ decimals: 6,
31
+ program: 'spl-token',
32
+ stable: true,
33
+ },
34
+ {
35
+ mint: '2u1tszSeqZ3qBWF3uNGPFc8TzMk2tdiwknnRMWGWjGWH',
36
+ symbol: 'USDG',
37
+ name: 'Global Dollar',
38
+ decimals: 6,
39
+ program: 'spl-token-2022',
40
+ stable: true,
41
+ },
42
+ {
43
+ mint: 'So11111111111111111111111111111111111111112',
44
+ symbol: 'wSOL',
45
+ name: 'Wrapped SOL',
46
+ decimals: 9,
47
+ program: 'spl-token',
48
+ stable: false,
49
+ },
50
+ ];
51
+ const DEVNET = [
52
+ {
53
+ mint: '4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU',
54
+ symbol: 'USDC',
55
+ name: 'USD Coin (devnet)',
56
+ decimals: 6,
57
+ program: 'spl-token',
58
+ stable: true,
59
+ },
60
+ {
61
+ mint: 'EcFc2cMyZxaKBkFK1XooxiyDyCPneLXiMwSJiVY6eTad',
62
+ symbol: 'USDT',
63
+ name: 'Tether USD (devnet)',
64
+ decimals: 6,
65
+ program: 'spl-token',
66
+ stable: true,
67
+ },
68
+ {
69
+ mint: '4F6PM96JJxngmHnZLBh9n58RH4aTVNWvDs2nuwrT5BP7',
70
+ symbol: 'USDG',
71
+ name: 'Global Dollar (devnet)',
72
+ decimals: 6,
73
+ program: 'spl-token-2022',
74
+ stable: true,
75
+ },
76
+ {
77
+ mint: 'So11111111111111111111111111111111111111112',
78
+ symbol: 'wSOL',
79
+ name: 'Wrapped SOL (devnet)',
80
+ decimals: 9,
81
+ program: 'spl-token',
82
+ stable: false,
83
+ },
84
+ ];
85
+ export const KNOWN_TOKENS = {
86
+ mainnet: MAINNET,
87
+ devnet: DEVNET,
88
+ };
89
+ /** Look up a known token by mint address on a given network. */
90
+ export function lookupToken(mint, network) {
91
+ return KNOWN_TOKENS[network].find((t) => t.mint === mint);
92
+ }
93
+ /** All stablecoin tickers we recognise on at least one network. */
94
+ export const KNOWN_STABLE_SYMBOLS = ['USDC', 'USDT', 'USDG'];
95
+ /**
96
+ * Look up a known token by ticker symbol (case-insensitive) on a given
97
+ * network. Useful for translating a user-facing currency dropdown into the
98
+ * underlying mint address required by x402 `AssetAmount` prices.
99
+ */
100
+ export function lookupTokenBySymbol(symbol, network) {
101
+ const upper = symbol.trim().toUpperCase();
102
+ return KNOWN_TOKENS[network].find((t) => t.symbol.toUpperCase() === upper);
103
+ }
104
+ /**
105
+ * Reverse-lookup a currency ticker for an asset mint. Falls back to `'USDC'`
106
+ * (the v0.1 default settlement currency) when the mint is unknown — buyer
107
+ * receipts surface a usable label even if the seller advertises a token the
108
+ * Leash registry hasn't catalogued yet.
109
+ */
110
+ export function currencyForAsset(asset, network) {
111
+ if (!asset)
112
+ return 'USDC';
113
+ return lookupToken(asset, network)?.symbol ?? 'USDC';
114
+ }
115
+ /**
116
+ * Mints we always want to render in a treasury UI even when the agent
117
+ * holds zero — the headline stables. Other tokens only appear once the
118
+ * agent actually holds a balance.
119
+ */
120
+ export function pinnedMints(network) {
121
+ return KNOWN_TOKENS[network].filter((t) => t.stable).map((t) => t.mint);
122
+ }
123
+ /**
124
+ * Heuristic mapping of an RPC URL to a logical network bucket. Treats
125
+ * anything containing `devnet`, `localhost`, or a private-network IP as
126
+ * devnet; everything else as mainnet.
127
+ */
128
+ export function networkFromRpc(rpc) {
129
+ return /devnet|localhost|127\.0\.0\.1/.test(rpc) ? 'devnet' : 'mainnet';
130
+ }
131
+ /**
132
+ * Resolve the canonical USDC mint for the given network. Used by buyer-kit
133
+ * pre-flight checks ("does the treasury have enough?") and by UI to seed
134
+ * default token selectors.
135
+ */
136
+ export function defaultUsdcMint(network) {
137
+ const usdc = KNOWN_TOKENS[network].find((t) => t.symbol === 'USDC');
138
+ if (!usdc) {
139
+ throw new Error(`No USDC mint registered for network "${network}"`);
140
+ }
141
+ return usdc;
142
+ }
143
+ /**
144
+ * Look up the SPL token program a known mint lives under (`spl-token` for
145
+ * legacy or `spl-token-2022` for Token-2022). Tries both networks since
146
+ * known stable mints are disjoint, so callers don't have to thread the
147
+ * x402 envelope's CAIP-2 network down through every layer.
148
+ *
149
+ * Returns `null` when the mint isn't catalogued — callers should default
150
+ * to legacy SPL token for back-compat, but this lets surfaces that DO
151
+ * understand Token-2022 (Pay card, buyer-kit preflight, withdraw flow)
152
+ * pick the right ATA without hard-coding mints.
153
+ */
154
+ export function tokenProgramForMint(mint) {
155
+ const trimmed = mint.trim();
156
+ for (const net of ['mainnet', 'devnet']) {
157
+ const hit = KNOWN_TOKENS[net].find((t) => t.mint === trimmed);
158
+ if (hit)
159
+ return hit.program;
160
+ }
161
+ return null;
162
+ }
163
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tokens/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Connection } from '@solana/web3.js';
2
+ export declare function getSplTokenBalance(connection: Connection, ownerBase58: string, mintBase58: string): Promise<bigint>;
3
+ //# sourceMappingURL=balance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"balance.d.ts","sourceRoot":"","sources":["../../src/treasury/balance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAGlD,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,UAAU,EACtB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CAUjB"}
@@ -0,0 +1,13 @@
1
+ import { PublicKey } from '@solana/web3.js';
2
+ export async function getSplTokenBalance(connection, ownerBase58, mintBase58) {
3
+ const owner = new PublicKey(ownerBase58);
4
+ const mint = new PublicKey(mintBase58);
5
+ const accounts = await connection.getParsedTokenAccountsByOwner(owner, { mint });
6
+ let sum = 0n;
7
+ for (const { account } of accounts.value) {
8
+ const amount = account.data.parsed.info.tokenAmount.amount;
9
+ sum += BigInt(amount);
10
+ }
11
+ return sum;
12
+ }
13
+ //# sourceMappingURL=balance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"balance.js","sourceRoot":"","sources":["../../src/treasury/balance.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,UAAsB,EACtB,WAAmB,EACnB,UAAkB;IAElB,MAAM,KAAK,GAAG,IAAI,SAAS,CAAC,WAAW,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,IAAI,SAAS,CAAC,UAAU,CAAC,CAAC;IACvC,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,6BAA6B,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IACjF,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,KAAK,MAAM,EAAE,OAAO,EAAE,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;QACzC,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;QAC3D,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC;IACxB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Read the live state of a single SPL token account (legacy SPL or
3
+ * Token-2022) over JSON-RPC and surface the bits Leash cares about for
4
+ * pre-flight diagnostics: holdings (`amount`), the SPL **delegate**, and the
5
+ * outstanding **delegated allowance**.
6
+ *
7
+ * The raw on-chain layout is parsed by the RPC's `jsonParsed` encoder, so we
8
+ * never have to ship a base58 / Borsh decoder here. Returns `null` when the
9
+ * account does not exist (uninitialised ATA) so callers can distinguish
10
+ * "truly empty" from "missing".
11
+ *
12
+ * Used by `@leashmarket/buyer-kit` to reclassify a generic facilitator
13
+ * `transaction_simulation` failure into a precise
14
+ * `insufficient_balance` / `insufficient_allowance` / `no_delegate`
15
+ * verdict on the resulting receipt.
16
+ */
17
+ export type SplTokenAccountState = {
18
+ /** The token account address that was inspected. */
19
+ address: string;
20
+ /** SPL mint this account holds. */
21
+ mint: string;
22
+ /** On-chain owner of the token account (treasury PDA, wallet, etc.). */
23
+ owner: string;
24
+ /** Holdings in atomic units (e.g. `5_000_000n` for 5 USDC at 6 decimals). */
25
+ amount: bigint;
26
+ /** SPL token decimals as reported by the RPC's parsed encoding. */
27
+ decimals: number;
28
+ /** SPL delegate address (the authority approved to spend), or `null`. */
29
+ delegate: string | null;
30
+ /** Outstanding allowance in atomic units. `0n` when no delegate is set. */
31
+ delegatedAmount: bigint;
32
+ /** Which token program owns this account (matters for instruction encoding). */
33
+ program: 'spl-token' | 'spl-token-2022' | 'unknown';
34
+ };
35
+ export type InspectSplTokenAccountOptions = {
36
+ rpcUrl: string;
37
+ /** The token account address (an ATA, typically). */
38
+ address: string;
39
+ };
40
+ /**
41
+ * Returns the parsed state of `address` or `null` if the account does not
42
+ * exist on-chain. Throws on RPC transport errors (so callers can decide
43
+ * whether to surface a degraded-mode warning vs. fail open).
44
+ */
45
+ export declare function inspectSplTokenAccount(opts: InspectSplTokenAccountOptions): Promise<SplTokenAccountState | null>;
46
+ //# sourceMappingURL=inspect-token-account.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspect-token-account.d.ts","sourceRoot":"","sources":["../../src/treasury/inspect-token-account.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,MAAM,oBAAoB,GAAG;IACjC,oDAAoD;IACpD,OAAO,EAAE,MAAM,CAAC;IAChB,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,wEAAwE;IACxE,KAAK,EAAE,MAAM,CAAC;IACd,6EAA6E;IAC7E,MAAM,EAAE,MAAM,CAAC;IACf,mEAAmE;IACnE,QAAQ,EAAE,MAAM,CAAC;IACjB,yEAAyE;IACzE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,2EAA2E;IAC3E,eAAe,EAAE,MAAM,CAAC;IACxB,gFAAgF;IAChF,OAAO,EAAE,WAAW,GAAG,gBAAgB,GAAG,SAAS,CAAC;CACrD,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,qDAAqD;IACrD,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAoBF;;;;GAIG;AACH,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,6BAA6B,GAClC,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CA2BtC"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Read the live state of a single SPL token account (legacy SPL or
3
+ * Token-2022) over JSON-RPC and surface the bits Leash cares about for
4
+ * pre-flight diagnostics: holdings (`amount`), the SPL **delegate**, and the
5
+ * outstanding **delegated allowance**.
6
+ *
7
+ * The raw on-chain layout is parsed by the RPC's `jsonParsed` encoder, so we
8
+ * never have to ship a base58 / Borsh decoder here. Returns `null` when the
9
+ * account does not exist (uninitialised ATA) so callers can distinguish
10
+ * "truly empty" from "missing".
11
+ *
12
+ * Used by `@leashmarket/buyer-kit` to reclassify a generic facilitator
13
+ * `transaction_simulation` failure into a precise
14
+ * `insufficient_balance` / `insufficient_allowance` / `no_delegate`
15
+ * verdict on the resulting receipt.
16
+ */
17
+ /**
18
+ * Returns the parsed state of `address` or `null` if the account does not
19
+ * exist on-chain. Throws on RPC transport errors (so callers can decide
20
+ * whether to surface a degraded-mode warning vs. fail open).
21
+ */
22
+ export async function inspectSplTokenAccount(opts) {
23
+ const result = await rpc(opts.rpcUrl, 'getAccountInfo', [
24
+ opts.address,
25
+ { encoding: 'jsonParsed', commitment: 'confirmed' },
26
+ ]);
27
+ if (!result.value)
28
+ return null;
29
+ const parsed = result.value.data.parsed;
30
+ // Only token accounts have `parsed.type === 'account'`. Anything else
31
+ // (mint accounts, plain wallets, etc.) is not what callers asked for.
32
+ if (parsed.type !== 'account')
33
+ return null;
34
+ const info = parsed.info;
35
+ const programLabel = result.value.data.program === 'spl-token'
36
+ ? 'spl-token'
37
+ : result.value.data.program === 'spl-token-2022'
38
+ ? 'spl-token-2022'
39
+ : 'unknown';
40
+ return {
41
+ address: opts.address,
42
+ mint: info.mint,
43
+ owner: info.owner,
44
+ amount: BigInt(info.tokenAmount.amount),
45
+ decimals: info.tokenAmount.decimals,
46
+ delegate: info.delegate ?? null,
47
+ delegatedAmount: info.delegatedAmount ? BigInt(info.delegatedAmount.amount) : 0n,
48
+ program: programLabel,
49
+ };
50
+ }
51
+ async function rpc(rpcUrl, method, params) {
52
+ const res = await fetch(rpcUrl, {
53
+ method: 'POST',
54
+ headers: { 'content-type': 'application/json' },
55
+ body: JSON.stringify({ jsonrpc: '2.0', id: 1, method, params }),
56
+ cache: 'no-store',
57
+ });
58
+ if (!res.ok)
59
+ throw new Error(`RPC ${method} HTTP ${res.status}`);
60
+ const json = (await res.json());
61
+ if (json.error)
62
+ throw new Error(`RPC ${method}: ${json.error.message}`);
63
+ if (json.result === undefined)
64
+ throw new Error(`RPC ${method}: empty result`);
65
+ return json.result;
66
+ }
67
+ //# sourceMappingURL=inspect-token-account.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspect-token-account.js","sourceRoot":"","sources":["../../src/treasury/inspect-token-account.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AA6CH;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,IAAmC;IAEnC,MAAM,MAAM,GAAG,MAAM,GAAG,CAAkC,IAAI,CAAC,MAAM,EAAE,gBAAgB,EAAE;QACvF,IAAI,CAAC,OAAO;QACZ,EAAE,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE;KACpD,CAAC,CAAC;IACH,IAAI,CAAC,MAAM,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IAC/B,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;IACxC,sEAAsE;IACtE,sEAAsE;IACtE,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAC3C,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;IACzB,MAAM,YAAY,GAChB,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,KAAK,WAAW;QACvC,CAAC,CAAC,WAAW;QACb,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,KAAK,gBAAgB;YAC9C,CAAC,CAAC,gBAAgB;YAClB,CAAC,CAAC,SAAS,CAAC;IAClB,OAAO;QACL,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;QACvC,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC,QAAQ;QACnC,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,IAAI;QAC/B,eAAe,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE;QAChF,OAAO,EAAE,YAAY;KACtB,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,GAAG,CAAI,MAAc,EAAE,MAAc,EAAE,MAAiB;IACrE,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,MAAM,EAAE;QAC9B,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAC/D,KAAK,EAAE,UAAU;KACkB,CAAC,CAAC;IACvC,IAAI,CAAC,GAAG,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,OAAO,MAAM,SAAS,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IACjE,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAgD,CAAC;IAC/E,IAAI,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,OAAO,MAAM,KAAK,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IACxE,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,OAAO,MAAM,gBAAgB,CAAC,CAAC;IAC9E,OAAO,IAAI,CAAC,MAAM,CAAC;AACrB,CAAC"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Enumerate every SPL token an owner holds (legacy SPL + Token-2022),
3
+ * enrich with metadata from the {@link KNOWN_TOKENS} registry, and pin
4
+ * stablecoin entries with zero balance when missing so UI surfaces always
5
+ * render them.
6
+ *
7
+ * This consolidates logic that previously lived in
8
+ * `apps/playground/app/api/agents/balance/route.ts` and
9
+ * `apps/playground/app/api/wallet/balance/route.ts`. Calling it from the SDK means
10
+ * any future Leash surface (CLI, mobile, downstream agents) gets the same
11
+ * canonical balance shape without re-implementing the RPC plumbing.
12
+ */
13
+ import { KNOWN_TOKENS, type TokenNetwork } from '../tokens/index.js';
14
+ export type SplTokenBalance = {
15
+ mint: string;
16
+ symbol: string | null;
17
+ name: string | null;
18
+ decimals: number;
19
+ /** Atomic integer string (e.g. `"1500000"` for 1.5 USDC). */
20
+ amount: string;
21
+ /** UI decimal as a number — best-effort, lossy for very large amounts. */
22
+ ui: number;
23
+ program: 'spl-token' | 'spl-token-2022';
24
+ /** True when the mint is in {@link KNOWN_TOKENS} for the requested network. */
25
+ known: boolean;
26
+ };
27
+ export type ListSplBalancesOptions = {
28
+ /** Owner address (a wallet, an agent treasury PDA, etc.). */
29
+ owner: string;
30
+ /** Solana RPC endpoint to query. */
31
+ rpcUrl: string;
32
+ /** Logical network bucket — controls which mints get pinned. */
33
+ network: TokenNetwork;
34
+ /**
35
+ * If true, include stable-coin mints from {@link KNOWN_TOKENS} with zero
36
+ * balance when the owner doesn't hold them. Defaults to `true`. Disable
37
+ * for callers that want a strict on-chain view (e.g. analytics).
38
+ */
39
+ pinKnownStables?: boolean;
40
+ };
41
+ export type ListSplBalancesResult = {
42
+ owner: string;
43
+ network: TokenNetwork;
44
+ /** SOL balance as decimal (lossy for large balances; see `lamports`). */
45
+ sol: number;
46
+ /** Raw lamport count as a string (lossless). */
47
+ lamports: string;
48
+ tokens: SplTokenBalance[];
49
+ };
50
+ /**
51
+ * Enumerate balances. Tolerates RPC failures on either token program — if
52
+ * Token-2022 calls fail (some RPCs lag here), the function still returns
53
+ * legacy SPL balances rather than throwing.
54
+ */
55
+ export declare function listSplBalances(opts: ListSplBalancesOptions): Promise<ListSplBalancesResult>;
56
+ export { KNOWN_TOKENS };
57
+ //# sourceMappingURL=list-balances.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-balances.d.ts","sourceRoot":"","sources":["../../src/treasury/list-balances.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EACL,YAAY,EAMZ,KAAK,YAAY,EAClB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,MAAM,EAAE,MAAM,CAAC;IACf,0EAA0E;IAC1E,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,WAAW,GAAG,gBAAgB,CAAC;IACxC,+EAA+E;IAC/E,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC;IACd,oCAAoC;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,gEAAgE;IAChE,OAAO,EAAE,YAAY,CAAC;IACtB;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,YAAY,CAAC;IACtB,yEAAyE;IACzE,GAAG,EAAE,MAAM,CAAC;IACZ,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B,CAAC;AAEF;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,sBAAsB,GAC3B,OAAO,CAAC,qBAAqB,CAAC,CA6ChC;AAsFD,OAAO,EAAE,YAAY,EAAE,CAAC"}