@axonfi/sdk 0.4.0 → 0.4.2

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 (97) hide show
  1. package/README.md +15 -9
  2. package/dist/index.cjs +4325 -0
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/index.d.cts +3256 -0
  5. package/dist/index.d.ts +3256 -21
  6. package/dist/index.js +4261 -27
  7. package/dist/index.js.map +1 -1
  8. package/package.json +1 -1
  9. package/dist/abis/AxonRegistry.d.ts +0 -294
  10. package/dist/abis/AxonRegistry.d.ts.map +0 -1
  11. package/dist/abis/AxonRegistry.js +0 -381
  12. package/dist/abis/AxonRegistry.js.map +0 -1
  13. package/dist/abis/AxonVault.d.ts +0 -1577
  14. package/dist/abis/AxonVault.d.ts.map +0 -1
  15. package/dist/abis/AxonVault.js +0 -2026
  16. package/dist/abis/AxonVault.js.map +0 -1
  17. package/dist/abis/AxonVaultFactory.d.ts +0 -207
  18. package/dist/abis/AxonVaultFactory.d.ts.map +0 -1
  19. package/dist/abis/AxonVaultFactory.js +0 -269
  20. package/dist/abis/AxonVaultFactory.js.map +0 -1
  21. package/dist/amounts.d.ts +0 -37
  22. package/dist/amounts.d.ts.map +0 -1
  23. package/dist/amounts.js +0 -72
  24. package/dist/amounts.js.map +0 -1
  25. package/dist/amounts.spec.d.ts +0 -2
  26. package/dist/amounts.spec.d.ts.map +0 -1
  27. package/dist/amounts.spec.js +0 -92
  28. package/dist/amounts.spec.js.map +0 -1
  29. package/dist/client.d.ts +0 -196
  30. package/dist/client.d.ts.map +0 -1
  31. package/dist/client.js +0 -621
  32. package/dist/client.js.map +0 -1
  33. package/dist/client.spec.d.ts +0 -2
  34. package/dist/client.spec.d.ts.map +0 -1
  35. package/dist/client.spec.js +0 -437
  36. package/dist/client.spec.js.map +0 -1
  37. package/dist/constants.d.ts +0 -110
  38. package/dist/constants.d.ts.map +0 -1
  39. package/dist/constants.js +0 -172
  40. package/dist/constants.js.map +0 -1
  41. package/dist/constants.spec.d.ts +0 -2
  42. package/dist/constants.spec.d.ts.map +0 -1
  43. package/dist/constants.spec.js +0 -95
  44. package/dist/constants.spec.js.map +0 -1
  45. package/dist/eip3009.d.ts +0 -45
  46. package/dist/eip3009.d.ts.map +0 -1
  47. package/dist/eip3009.js +0 -85
  48. package/dist/eip3009.js.map +0 -1
  49. package/dist/index.d.ts.map +0 -1
  50. package/dist/keystore.d.ts +0 -60
  51. package/dist/keystore.d.ts.map +0 -1
  52. package/dist/keystore.js +0 -182
  53. package/dist/keystore.js.map +0 -1
  54. package/dist/keystore.spec.d.ts +0 -2
  55. package/dist/keystore.spec.d.ts.map +0 -1
  56. package/dist/keystore.spec.js +0 -71
  57. package/dist/keystore.spec.js.map +0 -1
  58. package/dist/permit2.d.ts +0 -45
  59. package/dist/permit2.d.ts.map +0 -1
  60. package/dist/permit2.js +0 -81
  61. package/dist/permit2.js.map +0 -1
  62. package/dist/signer.d.ts +0 -35
  63. package/dist/signer.d.ts.map +0 -1
  64. package/dist/signer.js +0 -132
  65. package/dist/signer.js.map +0 -1
  66. package/dist/signer.spec.d.ts +0 -2
  67. package/dist/signer.spec.d.ts.map +0 -1
  68. package/dist/signer.spec.js +0 -94
  69. package/dist/signer.spec.js.map +0 -1
  70. package/dist/tokens.d.ts +0 -215
  71. package/dist/tokens.d.ts.map +0 -1
  72. package/dist/tokens.js +0 -247
  73. package/dist/tokens.js.map +0 -1
  74. package/dist/types.d.ts +0 -302
  75. package/dist/types.d.ts.map +0 -1
  76. package/dist/types.js +0 -2
  77. package/dist/types.js.map +0 -1
  78. package/dist/utils.d.ts +0 -8
  79. package/dist/utils.d.ts.map +0 -1
  80. package/dist/utils.js +0 -29
  81. package/dist/utils.js.map +0 -1
  82. package/dist/vault.d.ts +0 -60
  83. package/dist/vault.d.ts.map +0 -1
  84. package/dist/vault.js +0 -267
  85. package/dist/vault.js.map +0 -1
  86. package/dist/vault.spec.d.ts +0 -2
  87. package/dist/vault.spec.d.ts.map +0 -1
  88. package/dist/vault.spec.js +0 -162
  89. package/dist/vault.spec.js.map +0 -1
  90. package/dist/x402.d.ts +0 -88
  91. package/dist/x402.d.ts.map +0 -1
  92. package/dist/x402.js +0 -124
  93. package/dist/x402.js.map +0 -1
  94. package/dist/x402.spec.d.ts +0 -2
  95. package/dist/x402.spec.d.ts.map +0 -1
  96. package/dist/x402.spec.js +0 -411
  97. package/dist/x402.spec.js.map +0 -1
package/dist/x402.js DELETED
@@ -1,124 +0,0 @@
1
- import { USDC } from './constants.js';
2
- // ============================================================================
3
- // Parsing & Matching
4
- // ============================================================================
5
- /**
6
- * Parse the PAYMENT-REQUIRED header value (base64 JSON).
7
- *
8
- * The x402 spec encodes the payment requirements as a base64-encoded JSON
9
- * string in the response header.
10
- */
11
- export function parsePaymentRequired(headerValue) {
12
- let decoded;
13
- // Handle both base64 and plain JSON
14
- try {
15
- decoded = atob(headerValue);
16
- }
17
- catch {
18
- decoded = headerValue;
19
- }
20
- const parsed = JSON.parse(decoded);
21
- if (!parsed.accepts || !Array.isArray(parsed.accepts) || parsed.accepts.length === 0) {
22
- throw new Error('x402: no payment options in PAYMENT-REQUIRED header');
23
- }
24
- if (!parsed.resource) {
25
- throw new Error('x402: missing resource in PAYMENT-REQUIRED header');
26
- }
27
- return parsed;
28
- }
29
- /**
30
- * Parse a CAIP-2 network identifier to a numeric chain ID.
31
- *
32
- * @example parseChainId("eip155:8453") // → 8453
33
- * @example parseChainId("eip155:84532") // → 84532
34
- */
35
- export function parseChainId(network) {
36
- const parts = network.split(':');
37
- if (parts.length !== 2 || parts[0] !== 'eip155') {
38
- throw new Error(`x402: unsupported network format "${network}" (expected "eip155:<chainId>")`);
39
- }
40
- const chainId = parseInt(parts[1], 10);
41
- if (isNaN(chainId)) {
42
- throw new Error(`x402: invalid chain ID in network "${network}"`);
43
- }
44
- return chainId;
45
- }
46
- /**
47
- * Find a payment option matching the bot's chain ID.
48
- *
49
- * Prefers USDC options (EIP-3009 path — no gas needed from bot).
50
- * Falls back to any matching chain option.
51
- *
52
- * @returns The best matching payment option, or null if none match.
53
- */
54
- export function findMatchingOption(accepts, chainId) {
55
- const matchingOptions = [];
56
- for (const option of accepts) {
57
- try {
58
- const optionChainId = parseChainId(option.network);
59
- if (optionChainId === chainId) {
60
- matchingOptions.push(option);
61
- }
62
- }
63
- catch {
64
- // Skip options with unparseable network identifiers
65
- continue;
66
- }
67
- }
68
- if (matchingOptions.length === 0)
69
- return null;
70
- // Prefer USDC (EIP-3009 — gasless for bot)
71
- const usdcAddress = USDC[chainId]?.toLowerCase();
72
- if (usdcAddress) {
73
- const usdcOption = matchingOptions.find((opt) => opt.asset.toLowerCase() === usdcAddress);
74
- if (usdcOption)
75
- return usdcOption;
76
- }
77
- // Fall back to first matching option
78
- return matchingOptions[0] ?? null;
79
- }
80
- /**
81
- * Extract metadata fields from a parsed x402 header for payment enrichment.
82
- *
83
- * These fields flow into the Axon payment record, giving vault owners
84
- * full visibility into what their bots are accessing.
85
- */
86
- export function extractX402Metadata(parsed, selectedOption) {
87
- const metadata = {};
88
- if (parsed.x402Version !== undefined) {
89
- metadata.x402_version = String(parsed.x402Version);
90
- }
91
- if (selectedOption.scheme) {
92
- metadata.x402_scheme = selectedOption.scheme;
93
- }
94
- if (parsed.resource.mimeType) {
95
- metadata.x402_mime_type = parsed.resource.mimeType;
96
- }
97
- if (selectedOption.payTo) {
98
- metadata.x402_merchant = selectedOption.payTo;
99
- }
100
- if (parsed.resource.description) {
101
- metadata.x402_resource_description = parsed.resource.description;
102
- }
103
- return {
104
- resourceUrl: parsed.resource.url,
105
- memo: parsed.resource.description ?? null,
106
- recipientLabel: selectedOption.payTo
107
- ? `${selectedOption.payTo.slice(0, 6)}...${selectedOption.payTo.slice(-4)}`
108
- : null,
109
- metadata,
110
- };
111
- }
112
- // ============================================================================
113
- // Response Formatting
114
- // ============================================================================
115
- /**
116
- * Format a payment signature payload for the PAYMENT-SIGNATURE header.
117
- *
118
- * The x402 spec requires the header value to be base64-encoded JSON.
119
- */
120
- export function formatPaymentSignature(payload) {
121
- const json = JSON.stringify(payload);
122
- return btoa(json);
123
- }
124
- //# sourceMappingURL=x402.js.map
package/dist/x402.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"x402.js","sourceRoot":"","sources":["../src/x402.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=x402.spec.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"x402.spec.d.ts","sourceRoot":"","sources":["../src/x402.spec.ts"],"names":[],"mappings":""}
package/dist/x402.spec.js DELETED
@@ -1,411 +0,0 @@
1
- import { describe, it, expect } from '@jest/globals';
2
- import { recoverTypedDataAddress } from 'viem';
3
- import { privateKeyToAccount } from 'viem/accounts';
4
- import { parsePaymentRequired, parseChainId, findMatchingOption, extractX402Metadata, formatPaymentSignature, } from './x402.js';
5
- import { signTransferWithAuthorization, randomNonce, USDC_EIP712_DOMAIN } from './eip3009.js';
6
- import { signPermit2WitnessTransfer, randomPermit2Nonce, PERMIT2_ADDRESS, X402_PROXY_ADDRESS } from './permit2.js';
7
- import { USDC } from './constants.js';
8
- // ---------------------------------------------------------------------------
9
- // Test data
10
- // ---------------------------------------------------------------------------
11
- const BOT_KEY = '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80';
12
- const BOT_ACCOUNT = privateKeyToAccount(BOT_KEY);
13
- const BOT_ADDRESS = BOT_ACCOUNT.address;
14
- const MERCHANT = '0x70997970C51812dc3A010C7d01b50e0d17dc79C8';
15
- const CHAIN_ID = 84532; // Base Sepolia
16
- const USDC_ADDRESS = USDC[CHAIN_ID];
17
- function makeParsedHeader(overrides) {
18
- return {
19
- x402Version: 1,
20
- resource: {
21
- url: 'https://weather-api.example.com/forecast',
22
- description: 'Premium weather forecast data',
23
- mimeType: 'application/json',
24
- },
25
- accepts: [
26
- {
27
- payTo: MERCHANT,
28
- amount: '1000000',
29
- asset: USDC_ADDRESS,
30
- network: `eip155:${CHAIN_ID}`,
31
- scheme: 'exact',
32
- },
33
- ],
34
- ...overrides,
35
- };
36
- }
37
- function encodeHeader(parsed) {
38
- return btoa(JSON.stringify(parsed));
39
- }
40
- // ============================================================================
41
- // x402 Header Parsing
42
- // ============================================================================
43
- describe('parsePaymentRequired', () => {
44
- it('parses base64-encoded header', () => {
45
- const header = encodeHeader(makeParsedHeader());
46
- const result = parsePaymentRequired(header);
47
- expect(result.x402Version).toBe(1);
48
- expect(result.resource.url).toBe('https://weather-api.example.com/forecast');
49
- expect(result.accepts).toHaveLength(1);
50
- expect(result.accepts[0].payTo).toBe(MERCHANT);
51
- });
52
- it('parses plain JSON header', () => {
53
- const raw = JSON.stringify(makeParsedHeader());
54
- const result = parsePaymentRequired(raw);
55
- expect(result.resource.url).toBe('https://weather-api.example.com/forecast');
56
- });
57
- it('throws on missing accepts', () => {
58
- const header = btoa(JSON.stringify({ resource: { url: 'test' } }));
59
- expect(() => parsePaymentRequired(header)).toThrow('no payment options');
60
- });
61
- it('throws on empty accepts', () => {
62
- const header = btoa(JSON.stringify({ resource: { url: 'test' }, accepts: [] }));
63
- expect(() => parsePaymentRequired(header)).toThrow('no payment options');
64
- });
65
- it('throws on missing resource', () => {
66
- const header = btoa(JSON.stringify({ accepts: [{ payTo: MERCHANT, amount: '100', asset: USDC_ADDRESS, network: 'eip155:84532' }] }));
67
- expect(() => parsePaymentRequired(header)).toThrow('missing resource');
68
- });
69
- it('parses header with multiple accepts options', () => {
70
- const parsed = makeParsedHeader({
71
- accepts: [
72
- { payTo: MERCHANT, amount: '1000000', asset: USDC_ADDRESS, network: 'eip155:84532', scheme: 'exact' },
73
- { payTo: MERCHANT, amount: '500000000000000', asset: '0xWETH', network: 'eip155:8453', scheme: 'permit2' },
74
- { payTo: MERCHANT, amount: '2000000', asset: USDC_ADDRESS, network: 'eip155:42161', scheme: 'exact' },
75
- ],
76
- });
77
- const header = encodeHeader(parsed);
78
- const result = parsePaymentRequired(header);
79
- expect(result.accepts).toHaveLength(3);
80
- });
81
- });
82
- // ============================================================================
83
- // CAIP-2 Chain ID Parsing
84
- // ============================================================================
85
- describe('parseChainId', () => {
86
- it('parses eip155:8453', () => {
87
- expect(parseChainId('eip155:8453')).toBe(8453);
88
- });
89
- it('parses eip155:84532', () => {
90
- expect(parseChainId('eip155:84532')).toBe(84532);
91
- });
92
- it('parses eip155:42161', () => {
93
- expect(parseChainId('eip155:42161')).toBe(42161);
94
- });
95
- it('throws on non-eip155 namespace', () => {
96
- expect(() => parseChainId('solana:mainnet')).toThrow('unsupported network format');
97
- });
98
- it('throws on invalid format', () => {
99
- expect(() => parseChainId('8453')).toThrow('unsupported network format');
100
- });
101
- it('throws on non-numeric chain ID', () => {
102
- expect(() => parseChainId('eip155:base')).toThrow('invalid chain ID');
103
- });
104
- });
105
- // ============================================================================
106
- // Chain Matching + USDC Preference
107
- // ============================================================================
108
- describe('findMatchingOption', () => {
109
- it('returns USDC option when available', () => {
110
- const accepts = [
111
- {
112
- payTo: MERCHANT,
113
- amount: '500000000000000',
114
- asset: '0x4200000000000000000000000000000000000006',
115
- network: 'eip155:84532',
116
- scheme: 'permit2',
117
- },
118
- { payTo: MERCHANT, amount: '1000000', asset: USDC_ADDRESS, network: 'eip155:84532', scheme: 'exact' },
119
- ];
120
- const result = findMatchingOption(accepts, CHAIN_ID);
121
- expect(result).not.toBeNull();
122
- expect(result.asset).toBe(USDC_ADDRESS);
123
- expect(result.scheme).toBe('exact');
124
- });
125
- it('falls back to non-USDC option on matching chain', () => {
126
- const wethAddress = '0x4200000000000000000000000000000000000006';
127
- const accepts = [
128
- { payTo: MERCHANT, amount: '500000000000000', asset: wethAddress, network: 'eip155:84532', scheme: 'permit2' },
129
- ];
130
- const result = findMatchingOption(accepts, CHAIN_ID);
131
- expect(result).not.toBeNull();
132
- expect(result.asset).toBe(wethAddress);
133
- });
134
- it('returns null when no chain matches', () => {
135
- const accepts = [
136
- { payTo: MERCHANT, amount: '1000000', asset: USDC_ADDRESS, network: 'eip155:8453' },
137
- ];
138
- const result = findMatchingOption(accepts, CHAIN_ID); // 84532 ≠ 8453
139
- expect(result).toBeNull();
140
- });
141
- it('skips options with invalid network format', () => {
142
- const accepts = [
143
- { payTo: MERCHANT, amount: '1000000', asset: USDC_ADDRESS, network: 'invalid' },
144
- { payTo: MERCHANT, amount: '1000000', asset: USDC_ADDRESS, network: 'eip155:84532' },
145
- ];
146
- const result = findMatchingOption(accepts, CHAIN_ID);
147
- expect(result).not.toBeNull();
148
- expect(result.network).toBe('eip155:84532');
149
- });
150
- it('handles USDC address case-insensitivity', () => {
151
- const accepts = [
152
- { payTo: MERCHANT, amount: '1000000', asset: USDC_ADDRESS.toUpperCase(), network: 'eip155:84532' },
153
- ];
154
- const result = findMatchingOption(accepts, CHAIN_ID);
155
- expect(result).not.toBeNull();
156
- });
157
- });
158
- // ============================================================================
159
- // Metadata Extraction
160
- // ============================================================================
161
- describe('extractX402Metadata', () => {
162
- it('extracts all metadata fields', () => {
163
- const parsed = makeParsedHeader();
164
- const option = parsed.accepts[0];
165
- const meta = extractX402Metadata(parsed, option);
166
- expect(meta.resourceUrl).toBe('https://weather-api.example.com/forecast');
167
- expect(meta.memo).toBe('Premium weather forecast data');
168
- expect(meta.recipientLabel).toMatch(/^0x7099\.\.\.79C8$/);
169
- expect(meta.metadata.x402_version).toBe('1');
170
- expect(meta.metadata.x402_scheme).toBe('exact');
171
- expect(meta.metadata.x402_mime_type).toBe('application/json');
172
- expect(meta.metadata.x402_merchant).toBe(MERCHANT);
173
- expect(meta.metadata.x402_resource_description).toBe('Premium weather forecast data');
174
- });
175
- it('handles missing optional fields', () => {
176
- const parsed = {
177
- x402Version: 1,
178
- resource: { url: 'https://example.com' },
179
- accepts: [{ payTo: MERCHANT, amount: '100', asset: USDC_ADDRESS, network: 'eip155:84532' }],
180
- };
181
- const meta = extractX402Metadata(parsed, parsed.accepts[0]);
182
- expect(meta.resourceUrl).toBe('https://example.com');
183
- expect(meta.memo).toBeNull();
184
- expect(meta.metadata.x402_scheme).toBeUndefined();
185
- expect(meta.metadata.x402_mime_type).toBeUndefined();
186
- });
187
- });
188
- // ============================================================================
189
- // Header Format Roundtrip
190
- // ============================================================================
191
- describe('formatPaymentSignature', () => {
192
- it('encodes payload as base64 JSON', () => {
193
- const payload = { scheme: 'exact', signature: '0xabc', authorization: { from: BOT_ADDRESS } };
194
- const encoded = formatPaymentSignature(payload);
195
- const decoded = JSON.parse(atob(encoded));
196
- expect(decoded.scheme).toBe('exact');
197
- expect(decoded.signature).toBe('0xabc');
198
- expect(decoded.authorization.from).toBe(BOT_ADDRESS);
199
- });
200
- it('roundtrips complex payloads', () => {
201
- const payload = {
202
- scheme: 'permit2',
203
- signature: '0x' + 'ab'.repeat(65),
204
- permit: { nonce: '12345', deadline: '999999' },
205
- witness: { to: MERCHANT, requestedAmount: '1000000' },
206
- };
207
- const encoded = formatPaymentSignature(payload);
208
- const decoded = JSON.parse(atob(encoded));
209
- expect(decoded).toEqual(payload);
210
- });
211
- });
212
- // ============================================================================
213
- // EIP-3009 Signing
214
- // ============================================================================
215
- describe('signTransferWithAuthorization', () => {
216
- it('produces a valid 65-byte signature', async () => {
217
- const auth = {
218
- from: BOT_ADDRESS,
219
- to: MERCHANT,
220
- value: 1000000n,
221
- validAfter: 0n,
222
- validBefore: BigInt(Math.floor(Date.now() / 1000) + 300),
223
- nonce: randomNonce(),
224
- };
225
- const sig = await signTransferWithAuthorization(BOT_KEY, CHAIN_ID, auth);
226
- expect(sig).toMatch(/^0x[0-9a-f]{130}$/i);
227
- });
228
- it('signature recovers to the signer address', async () => {
229
- const auth = {
230
- from: BOT_ADDRESS,
231
- to: MERCHANT,
232
- value: 1000000n,
233
- validAfter: 0n,
234
- validBefore: 999999999n,
235
- nonce: randomNonce(),
236
- };
237
- const sig = await signTransferWithAuthorization(BOT_KEY, CHAIN_ID, auth);
238
- const domainConfig = USDC_EIP712_DOMAIN[CHAIN_ID];
239
- const recovered = await recoverTypedDataAddress({
240
- domain: {
241
- name: domainConfig.name,
242
- version: domainConfig.version,
243
- chainId: CHAIN_ID,
244
- verifyingContract: USDC_ADDRESS,
245
- },
246
- types: {
247
- TransferWithAuthorization: [
248
- { name: 'from', type: 'address' },
249
- { name: 'to', type: 'address' },
250
- { name: 'value', type: 'uint256' },
251
- { name: 'validAfter', type: 'uint256' },
252
- { name: 'validBefore', type: 'uint256' },
253
- { name: 'nonce', type: 'bytes32' },
254
- ],
255
- },
256
- primaryType: 'TransferWithAuthorization',
257
- message: {
258
- from: auth.from,
259
- to: auth.to,
260
- value: auth.value,
261
- validAfter: auth.validAfter,
262
- validBefore: auth.validBefore,
263
- nonce: auth.nonce,
264
- },
265
- signature: sig,
266
- });
267
- expect(recovered.toLowerCase()).toBe(BOT_ADDRESS.toLowerCase());
268
- });
269
- it('throws for unsupported chain', async () => {
270
- const auth = {
271
- from: BOT_ADDRESS,
272
- to: MERCHANT,
273
- value: 1000000n,
274
- validAfter: 0n,
275
- validBefore: 999999999n,
276
- nonce: randomNonce(),
277
- };
278
- await expect(signTransferWithAuthorization(BOT_KEY, 999999, auth)).rejects.toThrow('EIP-3009 not configured');
279
- });
280
- it('deterministic for same inputs', async () => {
281
- const nonce = '0x0000000000000000000000000000000000000000000000000000000000000001';
282
- const auth = {
283
- from: BOT_ADDRESS,
284
- to: MERCHANT,
285
- value: 1000000n,
286
- validAfter: 0n,
287
- validBefore: 999999999n,
288
- nonce,
289
- };
290
- const sig1 = await signTransferWithAuthorization(BOT_KEY, CHAIN_ID, auth);
291
- const sig2 = await signTransferWithAuthorization(BOT_KEY, CHAIN_ID, auth);
292
- expect(sig1).toBe(sig2);
293
- });
294
- });
295
- describe('randomNonce', () => {
296
- it('returns a bytes32 hex string', () => {
297
- const nonce = randomNonce();
298
- expect(nonce).toMatch(/^0x[0-9a-f]{64}$/);
299
- });
300
- it('generates unique nonces', () => {
301
- const nonces = new Set(Array.from({ length: 10 }, () => randomNonce()));
302
- expect(nonces.size).toBe(10);
303
- });
304
- });
305
- // ============================================================================
306
- // Permit2 Signing
307
- // ============================================================================
308
- describe('signPermit2WitnessTransfer', () => {
309
- it('produces a valid 65-byte signature', async () => {
310
- const permit = {
311
- token: USDC_ADDRESS,
312
- amount: 1000000n,
313
- spender: X402_PROXY_ADDRESS,
314
- nonce: randomPermit2Nonce(),
315
- deadline: BigInt(Math.floor(Date.now() / 1000) + 300),
316
- witnessTo: MERCHANT,
317
- witnessRequestedAmount: 1000000n,
318
- };
319
- const sig = await signPermit2WitnessTransfer(BOT_KEY, CHAIN_ID, permit);
320
- expect(sig).toMatch(/^0x[0-9a-f]{130}$/i);
321
- });
322
- it('signature recovers to the signer address', async () => {
323
- const permit = {
324
- token: USDC_ADDRESS,
325
- amount: 1000000n,
326
- spender: X402_PROXY_ADDRESS,
327
- nonce: 42n,
328
- deadline: 999999999n,
329
- witnessTo: MERCHANT,
330
- witnessRequestedAmount: 1000000n,
331
- };
332
- const sig = await signPermit2WitnessTransfer(BOT_KEY, CHAIN_ID, permit);
333
- const recovered = await recoverTypedDataAddress({
334
- domain: {
335
- name: 'Permit2',
336
- chainId: CHAIN_ID,
337
- verifyingContract: PERMIT2_ADDRESS,
338
- },
339
- types: {
340
- PermitWitnessTransferFrom: [
341
- { name: 'permitted', type: 'TokenPermissions' },
342
- { name: 'spender', type: 'address' },
343
- { name: 'nonce', type: 'uint256' },
344
- { name: 'deadline', type: 'uint256' },
345
- { name: 'witness', type: 'TransferDetails' },
346
- ],
347
- TokenPermissions: [
348
- { name: 'token', type: 'address' },
349
- { name: 'amount', type: 'uint256' },
350
- ],
351
- TransferDetails: [
352
- { name: 'to', type: 'address' },
353
- { name: 'requestedAmount', type: 'uint256' },
354
- ],
355
- },
356
- primaryType: 'PermitWitnessTransferFrom',
357
- message: {
358
- permitted: { token: permit.token, amount: permit.amount },
359
- spender: permit.spender,
360
- nonce: permit.nonce,
361
- deadline: permit.deadline,
362
- witness: { to: permit.witnessTo, requestedAmount: permit.witnessRequestedAmount },
363
- },
364
- signature: sig,
365
- });
366
- expect(recovered.toLowerCase()).toBe(BOT_ADDRESS.toLowerCase());
367
- });
368
- it('deterministic for same inputs', async () => {
369
- const permit = {
370
- token: USDC_ADDRESS,
371
- amount: 1000000n,
372
- spender: X402_PROXY_ADDRESS,
373
- nonce: 1n,
374
- deadline: 999999999n,
375
- witnessTo: MERCHANT,
376
- witnessRequestedAmount: 1000000n,
377
- };
378
- const sig1 = await signPermit2WitnessTransfer(BOT_KEY, CHAIN_ID, permit);
379
- const sig2 = await signPermit2WitnessTransfer(BOT_KEY, CHAIN_ID, permit);
380
- expect(sig1).toBe(sig2);
381
- });
382
- });
383
- describe('randomPermit2Nonce', () => {
384
- it('returns a bigint', () => {
385
- const nonce = randomPermit2Nonce();
386
- expect(typeof nonce).toBe('bigint');
387
- expect(nonce).toBeGreaterThanOrEqual(0n);
388
- });
389
- it('generates unique nonces', () => {
390
- const nonces = new Set(Array.from({ length: 10 }, () => randomPermit2Nonce()));
391
- expect(nonces.size).toBe(10);
392
- });
393
- });
394
- // ============================================================================
395
- // Constants
396
- // ============================================================================
397
- describe('x402 constants', () => {
398
- it('PERMIT2_ADDRESS is canonical', () => {
399
- expect(PERMIT2_ADDRESS).toBe('0x000000000022D473030F116dDEE9F6B43aC78BA3');
400
- });
401
- it('X402_PROXY_ADDRESS is canonical', () => {
402
- expect(X402_PROXY_ADDRESS).toBe('0x4020CD856C882D5fb903D99CE35316A085Bb0001');
403
- });
404
- it('USDC_EIP712_DOMAIN covers all supported chains', () => {
405
- expect(USDC_EIP712_DOMAIN[8453]).toEqual({ name: 'USD Coin', version: '2' });
406
- expect(USDC_EIP712_DOMAIN[84532]).toEqual({ name: 'USDC', version: '2' });
407
- expect(USDC_EIP712_DOMAIN[42161]).toEqual({ name: 'USD Coin', version: '2' });
408
- expect(USDC_EIP712_DOMAIN[421614]).toEqual({ name: 'USDC', version: '2' });
409
- });
410
- });
411
- //# sourceMappingURL=x402.spec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"x402.spec.js","sourceRoot":"","sources":["../src/x402.spec.ts"],"names":[],"mappings":"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"}