@armory-sh/base 0.2.21 → 0.2.22-alpha.3.20

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.
@@ -4,7 +4,7 @@
4
4
  * Payment payloads are JSON-encoded for transport in HTTP headers.
5
5
  * Matches the Coinbase x402 v2 SDK format.
6
6
  */
7
- import type { PaymentPayload, X402Response, PaymentPayloadV2, PaymentRequirements, SettlementResponse } from "../types/x402";
7
+ import type { PaymentPayload, X402Response, PaymentRequirements, SettlementResponse } from "../types/x402";
8
8
  /**
9
9
  * Safe Base64 encode (URL-safe, no padding)
10
10
  */
@@ -16,7 +16,7 @@ export declare function safeBase64Decode(str: string): string;
16
16
  /**
17
17
  * Encode payment payload to JSON string
18
18
  */
19
- export declare function encodePayment(payload: PaymentPayload | PaymentPayloadV2): string;
19
+ export declare function encodePayment(payload: PaymentPayload): string;
20
20
  /**
21
21
  * Decode payment payload from JSON string
22
22
  */
@@ -56,10 +56,6 @@ export declare function createPaymentRequiredHeaders(requirements: PaymentRequir
56
56
  * Create settlement response headers (V2 format)
57
57
  */
58
58
  export declare function createSettlementHeaders(settlement: SettlementResponse): Record<string, string>;
59
- /**
60
- * Type guard for legacy V2 payload (without x402Version)
61
- */
62
- export declare function isLegacyV2(payload: unknown): payload is PaymentPayloadV2;
63
59
  /**
64
60
  * Decode settlement from headers (V2 only)
65
61
  */
package/dist/index.d.ts CHANGED
@@ -1,11 +1,11 @@
1
- export type { Address as X402Address, Hex, X402Version, Scheme, Network as X402Network, ExactEvmAuthorization, ExactEvmPayload, PaymentPayload as X402PaymentPayload, UnsignedPaymentPayload as X402UnsignedPaymentPayload, PaymentRequirements as X402PaymentRequirements, SettlementResponse as X402SettlementResponse, VerifyResponse, X402Response, PaymentPayloadV2 as X402PayloadV2, LegacyPaymentPayload as X402LegacyPayload, } from "./types/x402";
2
- export { X402_VERSION, SCHEMES, isPaymentPayload, isExactEvmPayload, legacyToPaymentPayload, } from "./types/x402";
3
- export { safeBase64Encode, safeBase64Decode, encodePayment, decodePayment, encodeSettlementResponse, decodeSettlementResponse, encodeX402Response, decodeX402Response, detectPaymentVersion, extractPaymentFromHeaders, createPaymentRequiredHeaders, createSettlementHeaders, isLegacyV2, } from "./encoding/x402";
1
+ export type { Address as X402Address, Hex, X402Version, Scheme, Network as X402Network, ExactEvmAuthorization, ExactEvmPayload, PaymentPayload as X402PaymentPayload, UnsignedPaymentPayload as X402UnsignedPaymentPayload, PaymentRequirements as X402PaymentRequirements, SettlementResponse as X402SettlementResponse, VerifyResponse, X402Response, } from "./types/x402";
2
+ export { X402_VERSION, SCHEMES, isPaymentPayload, isExactEvmPayload, } from "./types/x402";
3
+ export { safeBase64Encode, safeBase64Decode, encodePayment, decodePayment, encodeSettlementResponse, decodeSettlementResponse, encodeX402Response, decodeX402Response, detectPaymentVersion, extractPaymentFromHeaders, createPaymentRequiredHeaders, createSettlementHeaders, } from "./encoding/x402";
4
4
  export { createNonce, toAtomicUnits, fromAtomicUnits, caip2ToNetwork, networkToCaip2, getCurrentTimestamp, isValidAddress, normalizeAddress, } from "./utils/x402";
5
5
  export type { CAIP2Network as CAIP2ChainId, CAIPAssetId, Address, Signature, PayToV2, Extensions, PaymentPayloadV2, PaymentRequirementsV2, SettlementResponseV2, PaymentRequiredV2, ResourceInfo, EIP3009Authorization, SchemePayloadV2, } from "./types/v2";
6
6
  export { V2_HEADERS, isCAIP2ChainId, isCAIPAssetId, isAddress, isPaymentRequiredV2, isPaymentPayloadV2, assetIdToAddress, addressToAssetId, parseSignature as parseSignatureV2, combineSignature as combineSignatureV2, } from "./types/v2";
7
7
  export type { PaymentPayload, PaymentRequirements, SettlementResponse, PaymentRequired, } from "./types/protocol";
8
- export { isX402V2Payload, isX402V2Requirements, isX402V2Settlement, isX402V2PaymentRequired, isLegacyV2Payload, isSettlementSuccessful, getTxHash, PAYMENT_SIGNATURE_HEADER, PAYMENT_RESPONSE_HEADER, PAYMENT_REQUIRED_HEADER, } from "./types/protocol";
8
+ export { isX402V2Payload, isX402V2Requirements, isX402V2Settlement, isX402V2PaymentRequired, isSettlementSuccessful, getTxHash, PAYMENT_SIGNATURE_HEADER, PAYMENT_RESPONSE_HEADER, PAYMENT_REQUIRED_HEADER, } from "./types/protocol";
9
9
  export type { NetworkConfig, CustomToken } from "./types/networks";
10
10
  export { NETWORKS, getNetworkConfig, getNetworkByChainId, getMainnets, getTestnets, registerToken, getCustomToken, getAllCustomTokens, unregisterToken, isCustomToken, } from "./types/networks";
11
11
  export { TOKENS, USDC_BASE, EURC_BASE, USDC_BASE_SEPOLIA, USDC_SKALE_BASE, SKL_SKALE_BASE, USDT_SKALE_BASE, WBTC_SKALE_BASE, WETH_SKALE_BASE, SKL_SKALE_BASE_SEPOLIA, USDC_SKALE_BASE_SEPOLIA, USDT_SKALE_BASE_SEPOLIA, WBTC_SKALE_BASE_SEPOLIA, WETH_SKALE_BASE_SEPOLIA, getToken, getAllTokens, getTokensBySymbol, getTokensByChain, getUSDCTokens, getEURCTokens, getSKLTokens, getUSDTTokens, getWBTCTokens, getWETHTokens, } from "./data/tokens";
@@ -19,5 +19,5 @@ export { parseRoutePattern, matchRoute, findMatchingRoute, validateRouteConfig,
19
19
  export { encodePaymentV2, decodePaymentV2, encodeSettlementV2, decodeSettlementV2, isPaymentV2, isSettlementV2, } from "./encoding";
20
20
  export type { NetworkId, TokenId, FacilitatorConfig, FacilitatorVerifyResult, FacilitatorSettleResult, SettlementMode, PayToAddress, AcceptPaymentOptions, PricingConfig, PaymentResult, PaymentError, PaymentErrorCode, ArmoryPaymentResult, ResolvedNetwork, ResolvedToken, ResolvedFacilitator, ResolvedPaymentConfig, ValidationError, } from "./types/api";
21
21
  export type { PaymentRequiredContext, PaymentPayloadContext, HookResult, OnPaymentRequiredHook, BeforePaymentHook, ExtensionHook, HookConfig, HookRegistry, } from "./types/hooks";
22
- export { createX402V2Payload, createLegacyV2Payload, INVALID_PAYLOADS, TEST_PAYER_ADDRESS, TEST_PAY_TO_ADDRESS, TEST_CONTRACT_ADDRESS, TEST_PRIVATE_KEY, } from "./fixtures/payloads";
23
- export { DEFAULT_PAYMENT_CONFIG, type TestPaymentConfig } from "./fixtures/config";
22
+ export type { FacilitatorClientConfig, SupportedKind, SupportedResponse, } from "./payment-client";
23
+ export { verifyPayment, settlePayment, getSupported, decodePayloadHeader, extractPayerAddress, } from "./payment-client";
package/dist/index.js CHANGED
@@ -1,108 +1,14 @@
1
+ import { randomBytes } from 'crypto';
2
+
1
3
  // src/types/x402.ts
2
- var X402_VERSION = 1;
4
+ var X402_VERSION = 2;
3
5
  var SCHEMES = ["exact"];
4
- var CHAIN_ID_TO_NETWORK = {
5
- 1: "ethereum",
6
- 8453: "base",
7
- 84532: "base-sepolia",
8
- 137: "polygon",
9
- 42161: "arbitrum",
10
- 421614: "arbitrum-sepolia",
11
- 10: "optimism",
12
- 11155420: "optimism-sepolia",
13
- 11155111: "ethereum-sepolia"
14
- };
15
6
  function isPaymentPayload(obj) {
16
- return typeof obj === "object" && obj !== null && "x402Version" in obj && "scheme" in obj && "network" in obj && "payload" in obj;
7
+ return typeof obj === "object" && obj !== null && "x402Version" in obj && "accepted" in obj && "payload" in obj;
17
8
  }
18
9
  function isExactEvmPayload(obj) {
19
10
  return typeof obj === "object" && obj !== null && "signature" in obj && "authorization" in obj;
20
11
  }
21
- function extractNetworkFromLegacy(legacy) {
22
- if ("network" in legacy && typeof legacy.network === "string") {
23
- return legacy.network;
24
- }
25
- if ("chainId" in legacy && typeof legacy.chainId === "string") {
26
- const match = legacy.chainId.match(/^eip155:(\d+)$/);
27
- if (match) {
28
- const chainId = parseInt(match[1], 10);
29
- return CHAIN_ID_TO_NETWORK[chainId] || `eip155:${chainId}`;
30
- }
31
- }
32
- if ("chainId" in legacy && typeof legacy.chainId === "number") {
33
- return CHAIN_ID_TO_NETWORK[legacy.chainId] || `eip155:${legacy.chainId}`;
34
- }
35
- return "base";
36
- }
37
- function extractSignatureFromLegacy(legacy) {
38
- if ("v" in legacy && "r" in legacy && "s" in legacy) {
39
- const v = legacy.v.toString(16).padStart(2, "0");
40
- const r = legacy.r.startsWith("0x") ? legacy.r.slice(2) : legacy.r;
41
- const s = legacy.s.startsWith("0x") ? legacy.s.slice(2) : legacy.s;
42
- return `0x${r}${s}${v}`;
43
- }
44
- if ("signature" in legacy && typeof legacy.signature === "object" && legacy.signature !== null) {
45
- const sig = legacy.signature;
46
- const v = sig.v.toString(16).padStart(2, "0");
47
- const r = sig.r.startsWith("0x") ? sig.r.slice(2) : sig.r;
48
- const s = sig.s.startsWith("0x") ? sig.s.slice(2) : sig.s;
49
- return `0x${r}${s}${v}`;
50
- }
51
- return "0x";
52
- }
53
- function convertAmountToAtomic(amount) {
54
- if (amount.includes(".")) {
55
- const parts = amount.split(".");
56
- const whole = parts[0];
57
- const fractional = parts[1] || "";
58
- const paddedFractional = fractional.padEnd(6, "0").slice(0, 6);
59
- return `${whole}${paddedFractional}`;
60
- }
61
- return amount;
62
- }
63
- function convertNonceToHex(nonce) {
64
- if (nonce.startsWith("0x") && nonce.length === 66) {
65
- return nonce;
66
- }
67
- const hex = BigInt(nonce).toString(16).padStart(64, "0");
68
- return `0x${hex}`;
69
- }
70
- function extractFromAddress(legacy) {
71
- return legacy.from;
72
- }
73
- function extractToAddress(legacy) {
74
- if ("to" in legacy && typeof legacy.to === "string") {
75
- return legacy.to;
76
- }
77
- return legacy.from;
78
- }
79
- function legacyToPaymentPayload(legacy) {
80
- if (isPaymentPayload(legacy)) {
81
- return legacy;
82
- }
83
- const network = extractNetworkFromLegacy(legacy);
84
- const signature = extractSignatureFromLegacy(legacy);
85
- const value = convertAmountToAtomic(legacy.amount);
86
- const nonce = convertNonceToHex(legacy.nonce);
87
- const from = extractFromAddress(legacy);
88
- const to = extractToAddress(legacy);
89
- return {
90
- x402Version: X402_VERSION,
91
- scheme: "exact",
92
- network,
93
- payload: {
94
- signature,
95
- authorization: {
96
- from,
97
- to,
98
- value,
99
- validAfter: "0",
100
- validBefore: legacy.expiry.toString(),
101
- nonce
102
- }
103
- }
104
- };
105
- }
106
12
 
107
13
  // src/types/v2.ts
108
14
  var V2_HEADERS = {
@@ -123,7 +29,7 @@ function isPaymentRequiredV2(obj) {
123
29
  return typeof obj === "object" && obj !== null && "x402Version" in obj && obj.x402Version === 2 && "resource" in obj && "accepts" in obj && Array.isArray(obj.accepts);
124
30
  }
125
31
  function isPaymentPayloadV2(obj) {
126
- return typeof obj === "object" && obj !== null && "x402Version" in obj && obj.x402Version === 2 && "scheme" in obj && "network" in obj && "payload" in obj;
32
+ return typeof obj === "object" && obj !== null && "x402Version" in obj && obj.x402Version === 2 && "accepted" in obj && "payload" in obj;
127
33
  }
128
34
  function assetIdToAddress(assetId) {
129
35
  const match = assetId.match(/\/erc20:(0x[a-fA-F0-9]{40})$/);
@@ -163,13 +69,10 @@ function safeBase64Decode(str) {
163
69
  return Buffer.from(str, "base64").toString("utf-8");
164
70
  }
165
71
  function encodePayment(payload) {
166
- let normalizedPayload;
167
- if (isPaymentPayload(payload)) {
168
- normalizedPayload = payload;
169
- } else {
170
- normalizedPayload = legacyToPaymentPayload(payload);
72
+ if (!isPaymentPayload(payload)) {
73
+ throw new Error("Invalid payment payload format");
171
74
  }
172
- const safePayload = JSON.parse(JSON.stringify(normalizedPayload, (_, value) => {
75
+ const safePayload = JSON.parse(JSON.stringify(payload, (_, value) => {
173
76
  if (typeof value === "bigint") {
174
77
  return value.toString();
175
78
  }
@@ -178,10 +81,15 @@ function encodePayment(payload) {
178
81
  return safeBase64Encode(JSON.stringify(safePayload));
179
82
  }
180
83
  function decodePayment(encoded) {
181
- const decoded = safeBase64Decode(encoded);
182
- const parsed = JSON.parse(decoded);
84
+ let parsed;
85
+ try {
86
+ parsed = JSON.parse(encoded);
87
+ } catch {
88
+ const decoded = safeBase64Decode(encoded);
89
+ parsed = JSON.parse(decoded);
90
+ }
183
91
  if (!isPaymentPayload(parsed)) {
184
- return legacyToPaymentPayload(parsed);
92
+ throw new Error("Invalid payment payload format");
185
93
  }
186
94
  return parsed;
187
95
  }
@@ -195,15 +103,23 @@ function encodeSettlementResponse(response) {
195
103
  return safeBase64Encode(JSON.stringify(safeResponse));
196
104
  }
197
105
  function decodeSettlementResponse(encoded) {
198
- const decoded = safeBase64Decode(encoded);
199
- return JSON.parse(decoded);
106
+ try {
107
+ return JSON.parse(encoded);
108
+ } catch {
109
+ const decoded = safeBase64Decode(encoded);
110
+ return JSON.parse(decoded);
111
+ }
200
112
  }
201
113
  function encodeX402Response(response) {
202
114
  return safeBase64Encode(JSON.stringify(response));
203
115
  }
204
116
  function decodeX402Response(encoded) {
205
- const decoded = safeBase64Decode(encoded);
206
- return JSON.parse(decoded);
117
+ try {
118
+ return JSON.parse(encoded);
119
+ } catch {
120
+ const decoded = safeBase64Decode(encoded);
121
+ return JSON.parse(decoded);
122
+ }
207
123
  }
208
124
  function detectPaymentVersion(headers) {
209
125
  if (headers.has("PAYMENT-SIGNATURE")) {
@@ -235,12 +151,6 @@ function createSettlementHeaders(settlement) {
235
151
  [V2_HEADERS.PAYMENT_RESPONSE]: encodeSettlementResponse(settlement)
236
152
  };
237
153
  }
238
- function isLegacyV2(payload) {
239
- return typeof payload === "object" && payload !== null && "signature" in payload && typeof payload.signature === "object";
240
- }
241
-
242
- // src/utils/x402.ts
243
- import { randomBytes } from "crypto";
244
154
  function createNonce() {
245
155
  const bytes = randomBytes(32);
246
156
  return `0x${bytes.toString("hex")}`;
@@ -314,13 +224,7 @@ function normalizeAddress(address) {
314
224
 
315
225
  // src/types/protocol.ts
316
226
  function isX402V2Payload(obj) {
317
- return typeof obj === "object" && obj !== null && "x402Version" in obj && obj.x402Version === 2 && "signature" in obj && "chainId" in obj && "assetId" in obj;
318
- }
319
- function isLegacyV2Payload(obj) {
320
- if (typeof obj !== "object" || obj === null) return false;
321
- const record = obj;
322
- const signature = record.signature;
323
- return "signature" in record && typeof signature === "object" && signature !== null && "v" in signature && "chainId" in record && typeof record.chainId === "string" && record.chainId.startsWith("eip155:") && "assetId" in record && !("x402Version" in record);
227
+ return typeof obj === "object" && obj !== null && "x402Version" in obj && obj.x402Version === 2 && "accepted" in obj && "payload" in obj;
324
228
  }
325
229
  function isX402V2Requirements(obj) {
326
230
  return typeof obj === "object" && obj !== null && "scheme" in obj && obj.scheme === "exact" && "network" in obj && typeof obj.network === "string" && obj.network.startsWith("eip155:") && // CAIP-2 format
@@ -367,10 +271,10 @@ var NETWORKS = {
367
271
  "base-sepolia": {
368
272
  name: "Base Sepolia",
369
273
  chainId: 84532,
370
- usdcAddress: "0x036CbD53842c5426634e7929541eA237834d2D14",
274
+ usdcAddress: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
371
275
  rpcUrl: "https://sepolia.base.org",
372
276
  caip2Id: "eip155:84532",
373
- caipAssetId: "eip155:84532/erc20:0x036CbD53842c5426634e7929541eA237834d2D14"
277
+ caipAssetId: "eip155:84532/erc20:0x036CbD53842c5426634e7929541eC2318f3dCF7e"
374
278
  },
375
279
  "skale-base": {
376
280
  name: "SKALE Base",
@@ -461,7 +365,7 @@ var USDC_BASE_SEPOLIA = {
461
365
  symbol: "USDC",
462
366
  name: "USD Coin",
463
367
  version: "2",
464
- contractAddress: "0x036CbD5d9A3b9231f83BefBE4F9E3FAA03eee2e0",
368
+ contractAddress: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
465
369
  chainId: 84532,
466
370
  decimals: 6
467
371
  };
@@ -469,7 +373,7 @@ var USDC_SKALE_BASE = {
469
373
  symbol: "USDC",
470
374
  name: "USD Coin",
471
375
  version: "2",
472
- contractAddress: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
376
+ contractAddress: "0x85889c8c714505E0c94b30fcfcF64fE3Ac8FCb20",
473
377
  chainId: 1187947933,
474
378
  decimals: 6
475
379
  };
@@ -477,7 +381,7 @@ var SKL_SKALE_BASE = {
477
381
  symbol: "SKL",
478
382
  name: "SKALE",
479
383
  version: "1",
480
- contractAddress: "0xaf2e1eb5c9f4a94dbf7400f76e4ec0d8de18fb8584",
384
+ contractAddress: "0xE0595a049d02b7674572b0d59cd4880Db60EDC50",
481
385
  chainId: 1187947933,
482
386
  decimals: 18
483
387
  };
@@ -485,7 +389,7 @@ var USDT_SKALE_BASE = {
485
389
  symbol: "USDT",
486
390
  name: "Tether USD",
487
391
  version: "1",
488
- contractAddress: "0x2bF5bF154b4881Ef4E3Ff28Ac1a60Fa1aDcb5fE5F6",
392
+ contractAddress: "0x2bF5bF154b515EaA82C31a65ec11554fF5aF7fCA",
489
393
  chainId: 1187947933,
490
394
  decimals: 6
491
395
  };
@@ -493,7 +397,7 @@ var WBTC_SKALE_BASE = {
493
397
  symbol: "WBTC",
494
398
  name: "Wrapped BTC",
495
399
  version: "1",
496
- contractAddress: "0x1aee79F6316aD699F96468A32F7BaF2fD8d55c0000",
400
+ contractAddress: "0x1aeeCFE5454c83B42D8A316246CAc9739E7f690e",
497
401
  chainId: 1187947933,
498
402
  decimals: 8
499
403
  };
@@ -501,7 +405,7 @@ var WETH_SKALE_BASE = {
501
405
  symbol: "WETH",
502
406
  name: "Wrapped Ether",
503
407
  version: "1",
504
- contractAddress: "0x8fF2237e4d845bc7Db6E1f1a93C8bCb288Bc5a400",
408
+ contractAddress: "0x7bD39ABBd0Dd13103542cAe3276C7fA332bCA486",
505
409
  chainId: 1187947933,
506
410
  decimals: 18
507
411
  };
@@ -509,7 +413,7 @@ var SKL_SKALE_BASE_SEPOLIA = {
509
413
  symbol: "SKL",
510
414
  name: "SKALE",
511
415
  version: "1",
512
- contractAddress: "0xaf2e1eb5c9f4a94dbf7400f76e4ec0d8de18fb8584",
416
+ contractAddress: "0xaf2e0ff5b5f51553fdb34ce7f04a6c3201cee57b",
513
417
  chainId: 324705682,
514
418
  decimals: 18
515
419
  };
@@ -517,7 +421,7 @@ var USDC_SKALE_BASE_SEPOLIA = {
517
421
  symbol: "USDC",
518
422
  name: "USD Coin",
519
423
  version: "2",
520
- contractAddress: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
424
+ contractAddress: "0x2e08028E3C4c2356572E096d8EF835cD5C6030bD",
521
425
  chainId: 324705682,
522
426
  decimals: 6
523
427
  };
@@ -525,7 +429,7 @@ var USDT_SKALE_BASE_SEPOLIA = {
525
429
  symbol: "USDT",
526
430
  name: "Tether USD",
527
431
  version: "1",
528
- contractAddress: "0xe8af39ca6558a983f6b5f8c0b828cc609f7a1c200",
432
+ contractAddress: "0x3ca0a49f511c2c89c4dcbbf1731120d8919050bf",
529
433
  chainId: 324705682,
530
434
  decimals: 6
531
435
  };
@@ -533,7 +437,7 @@ var WBTC_SKALE_BASE_SEPOLIA = {
533
437
  symbol: "WBTC",
534
438
  name: "Wrapped BTC",
535
439
  version: "1",
536
- contractAddress: "0x1aee79F6316aD699F96468A32F7BaF2fD8d55c0000",
440
+ contractAddress: "0x4512eacd4186b025186e1cf6cc0d89497c530e87",
537
441
  chainId: 324705682,
538
442
  decimals: 8
539
443
  };
@@ -541,7 +445,7 @@ var WETH_SKALE_BASE_SEPOLIA = {
541
445
  symbol: "WETH",
542
446
  name: "Wrapped Ether",
543
447
  version: "1",
544
- contractAddress: "0x8fF2237e4d845bc7Db6E1f1a93C8bCb288Bc5a400",
448
+ contractAddress: "0xf94056bd7f6965db3757e1b145f200b7346b4fc0",
545
449
  chainId: 324705682,
546
450
  decimals: 18
547
451
  };
@@ -1289,214 +1193,128 @@ var encodePaymentV2 = (payload) => base64JsonEncode(payload);
1289
1193
  var decodePaymentV2 = (encoded) => base64JsonDecode(encoded);
1290
1194
  var encodeSettlementV2 = (response) => base64JsonEncode(response);
1291
1195
  var decodeSettlementV2 = (encoded) => base64JsonDecode(encoded);
1292
- var isPaymentV2 = (payload) => "signature" in payload && typeof payload.signature === "object";
1293
- var isSettlementV2 = (response) => "status" in response;
1196
+ var isPaymentV2 = (payload) => "x402Version" in payload && payload.x402Version === 2 && "accepted" in payload && "payload" in payload;
1197
+ var isSettlementV2 = (response) => "success" in response && typeof response.success === "boolean" && "network" in response;
1294
1198
 
1295
- // src/fixtures/payloads.ts
1296
- var TEST_PRIVATE_KEY = "0x0000000000000000000000000000000000000000000000000000000000000000001";
1297
- var TEST_PAYER_ADDRESS = "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb1";
1298
- var TEST_PAY_TO_ADDRESS = "0x1234567890123456789012345678901234567890";
1299
- var TEST_CONTRACT_ADDRESS = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";
1300
- var createV2Authorization = (nonce) => ({
1301
- from: TEST_PAYER_ADDRESS,
1302
- to: TEST_PAY_TO_ADDRESS,
1303
- value: "1000000",
1304
- validAfter: Math.floor(Date.now() / 1e3).toString(),
1305
- validBefore: (Math.floor(Date.now() / 1e3) + 3600).toString(),
1306
- nonce: `0x${Buffer.from(nonce).toString("hex").padStart(64, "0")}`
1307
- });
1308
- var createV2SchemePayload = (nonce) => ({
1309
- signature: `0x${"b".repeat(130)}`,
1310
- authorization: createV2Authorization(nonce)
1311
- });
1312
- var createX402V2Payload = (nonce) => ({
1313
- x402Version: 2,
1314
- scheme: "exact",
1315
- network: "eip155:84532",
1316
- payload: createV2SchemePayload(nonce ?? "test_v2_nonce"),
1317
- resource: {
1318
- url: "https://example.com/api/test",
1319
- description: "Test resource"
1199
+ // src/payment-client.ts
1200
+ var DEFAULT_FACILITATOR_URL = "https://facilitator.payai.network";
1201
+ function toJsonSafe(data) {
1202
+ function convert(value) {
1203
+ if (value !== null && typeof value === "object" && !Array.isArray(value)) {
1204
+ return Object.fromEntries(Object.entries(value).map(([key, val]) => [key, convert(val)]));
1205
+ }
1206
+ if (Array.isArray(value)) {
1207
+ return value.map(convert);
1208
+ }
1209
+ if (typeof value === "bigint") {
1210
+ return value.toString();
1211
+ }
1212
+ return value;
1320
1213
  }
1321
- });
1322
- var createLegacyV2Payload = (nonce) => ({
1323
- from: TEST_PAYER_ADDRESS,
1324
- to: TEST_PAY_TO_ADDRESS,
1325
- amount: "1000000",
1326
- nonce: nonce ?? "test_legacy_v2_nonce",
1327
- expiry: Math.floor(Date.now() / 1e3) + 3600,
1328
- signature: {
1329
- v: 27,
1330
- r: `0x${"f".repeat(64)}`,
1331
- s: `0x${"0".repeat(64)}`
1332
- },
1333
- chainId: "eip155:84532",
1334
- assetId: `eip155:84532/erc20:${TEST_CONTRACT_ADDRESS.slice(2)}`
1335
- });
1336
- var INVALID_PAYLOADS = {
1337
- missingFields: {},
1338
- invalidAddress: {
1339
- x402Version: 2,
1340
- scheme: "exact",
1341
- network: "eip155:84532",
1342
- payload: {
1343
- signature: `0x${"i".repeat(130)}`,
1344
- authorization: {
1345
- from: "not-an-address",
1346
- to: TEST_PAY_TO_ADDRESS,
1347
- value: "1000000",
1348
- validAfter: Math.floor(Date.now() / 1e3).toString(),
1349
- validBefore: (Math.floor(Date.now() / 1e3) + 3600).toString(),
1350
- nonce: `0x${"1".repeat(64)}`
1214
+ return convert(data);
1215
+ }
1216
+ function resolveUrl(config) {
1217
+ return config?.url ?? DEFAULT_FACILITATOR_URL;
1218
+ }
1219
+ async function resolveHeaders(config) {
1220
+ const base = { "Content-Type": "application/json" };
1221
+ if (!config?.createHeaders) return base;
1222
+ const extra = await config.createHeaders();
1223
+ return { ...base, ...extra };
1224
+ }
1225
+ async function verifyPayment(payload, requirements, config) {
1226
+ const url = resolveUrl(config);
1227
+ const headers = await resolveHeaders(config);
1228
+ const response = await fetch(`${url}/verify`, {
1229
+ method: "POST",
1230
+ headers,
1231
+ body: JSON.stringify({
1232
+ paymentPayload: toJsonSafe(payload),
1233
+ paymentRequirements: toJsonSafe(requirements)
1234
+ })
1235
+ });
1236
+ if (response.status !== 200) {
1237
+ const text = await response.text().catch(() => response.statusText);
1238
+ throw new Error(`Facilitator verify failed: ${response.status} ${text}`);
1239
+ }
1240
+ return await response.json();
1241
+ }
1242
+ async function settlePayment(payload, requirements, config) {
1243
+ const url = resolveUrl(config);
1244
+ const headers = await resolveHeaders(config);
1245
+ const response = await fetch(`${url}/settle`, {
1246
+ method: "POST",
1247
+ headers,
1248
+ body: JSON.stringify({
1249
+ paymentPayload: toJsonSafe(payload),
1250
+ paymentRequirements: toJsonSafe(requirements)
1251
+ })
1252
+ });
1253
+ if (response.status !== 200) {
1254
+ const text = await response.text().catch(() => response.statusText);
1255
+ throw new Error(`Facilitator settle failed: ${response.status} ${text}`);
1256
+ }
1257
+ return await response.json();
1258
+ }
1259
+ async function getSupported(config) {
1260
+ const url = resolveUrl(config);
1261
+ const headers = await resolveHeaders(config);
1262
+ const response = await fetch(`${url}/supported`, {
1263
+ method: "GET",
1264
+ headers
1265
+ });
1266
+ if (response.status !== 200) {
1267
+ throw new Error(`Facilitator supported failed: ${response.statusText}`);
1268
+ }
1269
+ return await response.json();
1270
+ }
1271
+ function isCompactV2Payload(payload) {
1272
+ if (typeof payload !== "object" || payload === null) return false;
1273
+ const record = payload;
1274
+ return typeof record.x402Version === "number" && "payload" in record && !("accepted" in record);
1275
+ }
1276
+ function decodePayloadHeader(headerValue, defaults) {
1277
+ if (headerValue.startsWith("{")) {
1278
+ const parsed = JSON.parse(headerValue);
1279
+ if (isPaymentPayload(parsed)) return parsed;
1280
+ if (isCompactV2Payload(parsed)) {
1281
+ const compact = parsed;
1282
+ if (!defaults?.accepted) {
1283
+ throw new Error("Invalid payment payload: missing 'accepted' field and no defaults provided");
1351
1284
  }
1285
+ return {
1286
+ x402Version: 2,
1287
+ accepted: defaults.accepted,
1288
+ payload: compact.payload
1289
+ };
1352
1290
  }
1353
- },
1354
- expired: (() => {
1355
- const payload = createX402V2Payload("test_expired_nonce");
1356
- payload.payload.authorization.validBefore = (Math.floor(Date.now() / 1e3) - 100).toString();
1357
- return payload;
1358
- })(),
1359
- malformedSignature: (() => {
1360
- const payload = createX402V2Payload("test_malformed_sig_nonce");
1361
- payload.payload.signature = "not-hex";
1362
- return payload;
1363
- })()
1364
- };
1365
-
1366
- // src/fixtures/config.ts
1367
- var TEST_PRIVATE_KEY2 = process.env.TEST_PRIVATE_KEY || "0x0000000000000000000000000000000000000000000000000000000000000000000001";
1368
- var TEST_PAY_TO_ADDRESS2 = "0x1234567890123456789012345678901234567890";
1369
- var TEST_NETWORK = "base-sepolia";
1370
- var TEST_AMOUNT_DECIMAL = "1.0";
1371
- var FACILITATOR_URL = process.env.FACILITATOR_URL || "https://facilitator.payai.network";
1372
- var TEST_RPC_URL = process.env.TEST_RPC_URL || "https://sepolia.base.org";
1373
- var DEFAULT_PAYMENT_CONFIG = {
1374
- payTo: TEST_PAY_TO_ADDRESS2,
1375
- amount: TEST_AMOUNT_DECIMAL,
1376
- network: TEST_NETWORK,
1377
- defaultVersion: 2,
1378
- accept: {
1379
- networks: [TEST_NETWORK],
1380
- tokens: ["usdc"],
1381
- facilitators: [{ url: FACILITATOR_URL }]
1291
+ throw new Error("Invalid payment payload: unrecognized format");
1382
1292
  }
1383
- };
1384
- export {
1385
- DEFAULT_PAYMENT_CONFIG,
1386
- EIP712_TYPES,
1387
- ERC20_ABI,
1388
- EURC_BASE,
1389
- INVALID_PAYLOADS,
1390
- NETWORKS,
1391
- PAYMENT_REQUIRED_HEADER,
1392
- PAYMENT_RESPONSE_HEADER,
1393
- PAYMENT_SIGNATURE_HEADER,
1394
- SCHEMES,
1395
- SKL_SKALE_BASE,
1396
- SKL_SKALE_BASE_SEPOLIA,
1397
- TEST_CONTRACT_ADDRESS,
1398
- TEST_PAYER_ADDRESS,
1399
- TEST_PAY_TO_ADDRESS,
1400
- TEST_PRIVATE_KEY,
1401
- TOKENS,
1402
- USDC_BASE,
1403
- USDC_BASE_SEPOLIA,
1404
- USDC_DOMAIN,
1405
- USDC_SKALE_BASE,
1406
- USDC_SKALE_BASE_SEPOLIA,
1407
- USDT_SKALE_BASE,
1408
- USDT_SKALE_BASE_SEPOLIA,
1409
- V2_HEADERS,
1410
- WBTC_SKALE_BASE,
1411
- WBTC_SKALE_BASE_SEPOLIA,
1412
- WETH_SKALE_BASE,
1413
- WETH_SKALE_BASE_SEPOLIA,
1414
- X402_VERSION,
1415
- addressToAssetId,
1416
- assetIdToAddress,
1417
- caip2ToNetwork,
1418
- checkFacilitatorSupport,
1419
- combineSignature as combineSignatureV2,
1420
- createEIP712Domain,
1421
- createError,
1422
- createLegacyV2Payload,
1423
- createNonce,
1424
- createPaymentRequiredHeaders,
1425
- createSettlementHeaders,
1426
- createTransferWithAuthorization,
1427
- createX402V2Payload,
1428
- decodePayment,
1429
- decodePaymentV2,
1430
- decodeSettlementResponse,
1431
- decodeSettlementV2,
1432
- decodeX402Response,
1433
- detectPaymentVersion,
1434
- encodePayment,
1435
- encodePaymentV2,
1436
- encodeSettlementResponse,
1437
- encodeSettlementV2,
1438
- encodeX402Response,
1439
- extractPaymentFromHeaders,
1440
- findMatchingRoute,
1441
- fromAtomicUnits,
1442
- getAllCustomTokens,
1443
- getAllTokens,
1444
- getAvailableNetworks,
1445
- getAvailableTokens,
1446
- getCurrentTimestamp,
1447
- getCustomToken,
1448
- getEURCTokens,
1449
- getMainnets,
1450
- getNetworkByChainId,
1451
- getNetworkConfig,
1452
- getSKLTokens,
1453
- getTestnets,
1454
- getToken,
1455
- getTokensByChain,
1456
- getTokensBySymbol,
1457
- getTxHash,
1458
- getUSDCTokens,
1459
- getUSDTTokens,
1460
- getWBTCTokens,
1461
- getWETHTokens,
1462
- isAddress,
1463
- isCAIP2ChainId,
1464
- isCAIPAssetId,
1465
- isCustomToken,
1466
- isExactEvmPayload,
1467
- isLegacyV2,
1468
- isLegacyV2Payload,
1469
- isPaymentPayload,
1470
- isPaymentPayloadV2,
1471
- isPaymentRequiredV2,
1472
- isPaymentV2,
1473
- isResolvedNetwork,
1474
- isResolvedToken,
1475
- isSettlementSuccessful,
1476
- isSettlementV2,
1477
- isValidAddress,
1478
- isValidationError,
1479
- isX402V2Payload,
1480
- isX402V2PaymentRequired,
1481
- isX402V2Requirements,
1482
- isX402V2Settlement,
1483
- legacyToPaymentPayload,
1484
- matchRoute,
1485
- networkToCaip2,
1486
- normalizeAddress,
1487
- normalizeNetworkName,
1488
- parseRoutePattern,
1489
- parseSignature as parseSignatureV2,
1490
- registerToken,
1491
- resolveFacilitator,
1492
- resolveNetwork,
1493
- resolveToken,
1494
- safeBase64Decode,
1495
- safeBase64Encode,
1496
- toAtomicUnits,
1497
- unregisterToken,
1498
- validateAcceptConfig,
1499
- validatePaymentConfig,
1500
- validateRouteConfig,
1501
- validateTransferWithAuthorization
1502
- };
1293
+ const normalized = headerValue.replace(/-/g, "+").replace(/_/g, "/").padEnd(Math.ceil(headerValue.length / 4) * 4, "=");
1294
+ try {
1295
+ const decoded = JSON.parse(Buffer.from(normalized, "base64").toString("utf-8"));
1296
+ if (isPaymentPayload(decoded)) return decoded;
1297
+ if (isCompactV2Payload(decoded)) {
1298
+ const compact = decoded;
1299
+ if (!defaults?.accepted) {
1300
+ throw new Error("Invalid payment payload: missing 'accepted' field and no defaults provided");
1301
+ }
1302
+ return {
1303
+ x402Version: 2,
1304
+ accepted: defaults.accepted,
1305
+ payload: compact.payload
1306
+ };
1307
+ }
1308
+ throw new Error("Invalid payment payload: unrecognized format");
1309
+ } catch {
1310
+ throw new Error("Invalid payment payload: failed to decode");
1311
+ }
1312
+ }
1313
+ function extractPayerAddress(payload) {
1314
+ if (isExactEvmPayload(payload.payload)) {
1315
+ return payload.payload.authorization.from;
1316
+ }
1317
+ throw new Error("Unable to extract payer address from payload");
1318
+ }
1319
+
1320
+ export { EIP712_TYPES, ERC20_ABI, EURC_BASE, NETWORKS, PAYMENT_REQUIRED_HEADER, PAYMENT_RESPONSE_HEADER, PAYMENT_SIGNATURE_HEADER, SCHEMES, SKL_SKALE_BASE, SKL_SKALE_BASE_SEPOLIA, TOKENS, USDC_BASE, USDC_BASE_SEPOLIA, USDC_DOMAIN, USDC_SKALE_BASE, USDC_SKALE_BASE_SEPOLIA, USDT_SKALE_BASE, USDT_SKALE_BASE_SEPOLIA, V2_HEADERS, WBTC_SKALE_BASE, WBTC_SKALE_BASE_SEPOLIA, WETH_SKALE_BASE, WETH_SKALE_BASE_SEPOLIA, X402_VERSION, addressToAssetId, assetIdToAddress, caip2ToNetwork, checkFacilitatorSupport, combineSignature as combineSignatureV2, createEIP712Domain, createError, createNonce, createPaymentRequiredHeaders, createSettlementHeaders, createTransferWithAuthorization, decodePayloadHeader, decodePayment, decodePaymentV2, decodeSettlementResponse, decodeSettlementV2, decodeX402Response, detectPaymentVersion, encodePayment, encodePaymentV2, encodeSettlementResponse, encodeSettlementV2, encodeX402Response, extractPayerAddress, extractPaymentFromHeaders, findMatchingRoute, fromAtomicUnits, getAllCustomTokens, getAllTokens, getAvailableNetworks, getAvailableTokens, getCurrentTimestamp, getCustomToken, getEURCTokens, getMainnets, getNetworkByChainId, getNetworkConfig, getSKLTokens, getSupported, getTestnets, getToken, getTokensByChain, getTokensBySymbol, getTxHash, getUSDCTokens, getUSDTTokens, getWBTCTokens, getWETHTokens, isAddress, isCAIP2ChainId, isCAIPAssetId, isCustomToken, isExactEvmPayload, isPaymentPayload, isPaymentPayloadV2, isPaymentRequiredV2, isPaymentV2, isResolvedNetwork, isResolvedToken, isSettlementSuccessful, isSettlementV2, isValidAddress, isValidationError, isX402V2Payload, isX402V2PaymentRequired, isX402V2Requirements, isX402V2Settlement, matchRoute, networkToCaip2, normalizeAddress, normalizeNetworkName, parseRoutePattern, parseSignature as parseSignatureV2, registerToken, resolveFacilitator, resolveNetwork, resolveToken, safeBase64Decode, safeBase64Encode, settlePayment, toAtomicUnits, unregisterToken, validateAcceptConfig, validatePaymentConfig, validateRouteConfig, validateTransferWithAuthorization, verifyPayment };
@@ -0,0 +1,23 @@
1
+ import type { PaymentPayload, PaymentRequirements, VerifyResponse, SettlementResponse } from "./types/x402";
2
+ export interface FacilitatorClientConfig {
3
+ url: string;
4
+ createHeaders?: () => Record<string, string> | Promise<Record<string, string>>;
5
+ }
6
+ export declare function verifyPayment(payload: PaymentPayload, requirements: PaymentRequirements, config?: FacilitatorClientConfig): Promise<VerifyResponse>;
7
+ export declare function settlePayment(payload: PaymentPayload, requirements: PaymentRequirements, config?: FacilitatorClientConfig): Promise<SettlementResponse>;
8
+ export interface SupportedKind {
9
+ x402Version: number;
10
+ scheme: string;
11
+ network: string;
12
+ extra?: Record<string, unknown>;
13
+ }
14
+ export interface SupportedResponse {
15
+ kinds: SupportedKind[];
16
+ }
17
+ interface DecodePayloadDefaults {
18
+ accepted?: PaymentRequirements;
19
+ }
20
+ export declare function getSupported(config?: FacilitatorClientConfig): Promise<SupportedResponse>;
21
+ export declare function decodePayloadHeader(headerValue: string, defaults?: DecodePayloadDefaults): PaymentPayload;
22
+ export declare function extractPayerAddress(payload: PaymentPayload): string;
23
+ export {};
@@ -53,10 +53,6 @@ export type CAIPAssetId = `eip155:${string}/erc20:${string}`;
53
53
  * Check if payload is x402 V2 format (Coinbase format)
54
54
  */
55
55
  export declare function isX402V2Payload(obj: unknown): obj is PaymentPayloadV2;
56
- /**
57
- * Check if payload is legacy Armory V2 format
58
- */
59
- export declare function isLegacyV2Payload(obj: unknown): boolean;
60
56
  /**
61
57
  * Check if requirements is x402 V2 format
62
58
  */
@@ -43,7 +43,7 @@ export interface PaymentRequirementsV2 {
43
43
  /** Blockchain network identifier in CAIP-2 format */
44
44
  network: CAIP2Network;
45
45
  /** Required payment amount in atomic token units */
46
- amount: string;
46
+ maxAmountRequired: string;
47
47
  /** Token contract address (extracted from CAIP asset ID) */
48
48
  asset: Address;
49
49
  /** Recipient wallet address or role constant */
@@ -103,17 +103,17 @@ export interface SchemePayloadV2 {
103
103
  /**
104
104
  * Payment payload sent by client
105
105
  * Matches x402 V2 PaymentPayload spec (Coinbase format)
106
+ *
107
+ * The 'accepted' field echoes the server's requirements being accepted.
106
108
  */
107
109
  export interface PaymentPayloadV2 {
108
110
  /** Protocol version identifier */
109
111
  x402Version: 2;
110
- /** Payment scheme (e.g., "exact") */
111
- scheme: string;
112
- /** Network identifier in CAIP-2 format */
113
- network: string;
112
+ /** The payment requirements being accepted (echoed from server) */
113
+ accepted: PaymentRequirementsV2;
114
114
  /** Scheme-specific payment data */
115
115
  payload: SchemePayloadV2;
116
- /** Resource being accessed (optional, echoed from server) */
116
+ /** Resource being accessed (optional) */
117
117
  resource?: ResourceInfo;
118
118
  /** Protocol extensions data */
119
119
  extensions?: Extensions;
@@ -6,7 +6,7 @@
6
6
  */
7
7
  export type Address = `0x${string}`;
8
8
  export type Hex = `0x${string}`;
9
- export declare const X402_VERSION: 1;
9
+ export declare const X402_VERSION: 2;
10
10
  export type X402Version = typeof X402_VERSION;
11
11
  export declare const SCHEMES: readonly ["exact"];
12
12
  export type Scheme = (typeof SCHEMES)[number];
@@ -30,25 +30,35 @@ export interface ExactEvmPayload {
30
30
  authorization: ExactEvmAuthorization;
31
31
  }
32
32
  /**
33
- * Payment payload - Coinbase compatible format
34
- * This is the unified format that works with both v1 and v2
33
+ * Resource information for payment payload
34
+ */
35
+ export interface ResourceInfo {
36
+ url: string;
37
+ description?: string;
38
+ mimeType?: string;
39
+ }
40
+ /**
41
+ * Payment payload - Coinbase compatible format (x402 v2)
42
+ * Uses 'accepted' field to echo server's requirements
35
43
  */
36
44
  export interface PaymentPayload {
37
45
  x402Version: X402Version;
38
- scheme: Scheme;
39
- network: Network;
46
+ accepted: PaymentRequirements;
40
47
  payload: ExactEvmPayload;
48
+ resource?: ResourceInfo;
49
+ extensions?: Record<string, unknown>;
41
50
  }
42
51
  /**
43
52
  * Unsigned payment payload (before signing)
44
53
  */
45
54
  export interface UnsignedPaymentPayload {
46
55
  x402Version: X402Version;
47
- scheme: Scheme;
48
- network: Network;
56
+ accepted: PaymentRequirements;
49
57
  payload: Omit<ExactEvmPayload, "signature"> & {
50
58
  signature: undefined;
51
59
  };
60
+ resource?: ResourceInfo;
61
+ extensions?: Record<string, unknown>;
52
62
  }
53
63
  /**
54
64
  * Payment requirements for 402 response
@@ -57,7 +67,7 @@ export interface UnsignedPaymentPayload {
57
67
  export interface PaymentRequirements {
58
68
  scheme: Scheme;
59
69
  network: Network;
60
- amount: string;
70
+ maxAmountRequired: string;
61
71
  payTo: Address;
62
72
  maxTimeoutSeconds: number;
63
73
  asset: Address;
@@ -92,44 +102,8 @@ export interface X402Response {
92
102
  accepts?: PaymentRequirements[];
93
103
  payer?: Address;
94
104
  }
95
- export interface PaymentPayloadV1 {
96
- from: string;
97
- to: string;
98
- amount: string;
99
- nonce: string;
100
- expiry: number;
101
- v: number;
102
- r: string;
103
- s: string;
104
- chainId: number;
105
- contractAddress: string;
106
- network: string;
107
- }
108
- export interface PaymentPayloadV2 {
109
- from: Address;
110
- to: Address | {
111
- role?: string;
112
- callback?: string;
113
- };
114
- amount: string;
115
- nonce: string;
116
- expiry: number;
117
- signature: {
118
- v: number;
119
- r: string;
120
- s: string;
121
- };
122
- chainId: `eip155:${string}`;
123
- assetId: `eip155:${string}/erc20:${string}`;
124
- extensions?: Record<string, unknown>;
125
- }
126
- export type LegacyPaymentPayload = PaymentPayloadV1 | PaymentPayloadV2;
127
105
  /**
128
106
  * Type guards
129
107
  */
130
108
  export declare function isPaymentPayload(obj: unknown): obj is PaymentPayload;
131
109
  export declare function isExactEvmPayload(obj: unknown): obj is ExactEvmPayload;
132
- /**
133
- * Convert legacy payload to new format
134
- */
135
- export declare function legacyToPaymentPayload(legacy: LegacyPaymentPayload | PaymentPayload): PaymentPayload;
@@ -4,4 +4,3 @@
4
4
  * Re-exports commonly used test utilities
5
5
  */
6
6
  export * from "./mock-facilitator";
7
- export * from "../../fixtures/config";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@armory-sh/base",
3
- "version": "0.2.21",
3
+ "version": "0.2.22-alpha.3.20",
4
4
  "license": "MIT",
5
5
  "author": "Sawyer Cutler <sawyer@dirtroad.dev>",
6
6
  "type": "module",
@@ -23,7 +23,7 @@
23
23
  },
24
24
  "repository": {
25
25
  "type": "git",
26
- "url": "git+https://github.com/thegreataxios/armory.git",
26
+ "url": "git+https://github.com/TheGreatAxios/armory.git",
27
27
  "directory": "packages/base"
28
28
  },
29
29
  "dependencies": {},
@@ -37,4 +37,4 @@
37
37
  "test": "bun test",
38
38
  "typecheck": "tsc --noEmit"
39
39
  }
40
- }
40
+ }
@@ -1,48 +0,0 @@
1
- /**
2
- * Test Configuration
3
- *
4
- * Shared configuration for E2E tests including network configs,
5
- * test keys, and facilitator URLs.
6
- */
7
- export declare const TEST_PRIVATE_KEY: `0x${string}`;
8
- export declare const TEST_PAYER_ADDRESS: "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb1";
9
- export declare const TEST_PAY_TO_ADDRESS: "0x1234567890123456789012345678901234567890";
10
- export declare const TEST_CONTRACT_ADDRESS: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";
11
- export declare const TEST_NETWORK: "base-sepolia";
12
- export declare const TEST_CHAIN_ID: 84532;
13
- export declare const TEST_CAIP2_NETWORK: "eip155:84532";
14
- export declare const TEST_ASSET_ID: "eip155:84532/erc20:0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";
15
- export declare const TEST_AMOUNT: "1000000";
16
- export declare const TEST_AMOUNT_DECIMAL: "1.0";
17
- export declare const FACILITATOR_URL: string;
18
- export declare const MOCK_FACILITATOR_PORT = 8899;
19
- export declare const TEST_TIMEOUT_MS = 30000;
20
- export declare const SERVER_STARTUP_DELAY_MS = 100;
21
- export declare const SETTLEMENT_TIMEOUT_MS = 10000;
22
- export declare const TEST_RPC_URL: string;
23
- export interface TestPaymentConfig {
24
- payTo: `0x${string}`;
25
- amount: string;
26
- network: string;
27
- defaultVersion: 1 | 2;
28
- accept: {
29
- networks: string[];
30
- tokens: string[];
31
- facilitators: Array<{
32
- url: string;
33
- }>;
34
- };
35
- }
36
- export declare const DEFAULT_PAYMENT_CONFIG: TestPaymentConfig;
37
- /**
38
- * Get a random port for test servers
39
- */
40
- export declare const getRandomPort: () => number;
41
- /**
42
- * Create a test nonce with timestamp
43
- */
44
- export declare const createTestNonce: (prefix: string) => string;
45
- /**
46
- * Sleep for specified milliseconds
47
- */
48
- export declare const sleep: (ms: number) => Promise<void>;
@@ -1,16 +0,0 @@
1
- /**
2
- * Mock Payment Payloads for Testing (V2 Only)
3
- */
4
- import type { X402PayloadV2, PaymentPayloadV2 } from "@armory-sh/base";
5
- export declare const TEST_PRIVATE_KEY = "0x0000000000000000000000000000000000000000000000000000000000000000001";
6
- export declare const TEST_PAYER_ADDRESS = "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb1";
7
- export declare const TEST_PAY_TO_ADDRESS = "0x1234567890123456789012345678901234567890";
8
- export declare const TEST_CONTRACT_ADDRESS = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";
9
- export declare const createX402V2Payload: (nonce?: string) => PaymentPayloadV2;
10
- export declare const createLegacyV2Payload: (nonce?: string) => X402PayloadV2;
11
- export declare const INVALID_PAYLOADS: {
12
- readonly missingFields: {};
13
- readonly invalidAddress: PaymentPayloadV2;
14
- readonly expired: PaymentPayloadV2;
15
- readonly malformedSignature: PaymentPayloadV2;
16
- };
@@ -1,35 +0,0 @@
1
- /**
2
- * Mock Payment Requirements for Testing (V2 Only)
3
- */
4
- import type { PaymentRequirementsV2 } from "@armory-sh/base";
5
- export declare const MOCK_X402_V2_REQUIREMENTS: PaymentRequirementsV2;
6
- export declare const createX402V2Requirements: (overrides?: Partial<PaymentRequirementsV2>) => PaymentRequirementsV2;
7
- export declare const INVALID_REQUIREMENTS: {
8
- readonly missingAmount: {
9
- scheme: "exact";
10
- network: import("@armory-sh/base").CAIP2ChainId;
11
- amount: string;
12
- asset: import("@armory-sh/base").Address;
13
- payTo: import("@armory-sh/base").Address;
14
- maxTimeoutSeconds: number;
15
- name?: string;
16
- version?: string;
17
- extra?: import("@armory-sh/base").Extensions;
18
- };
19
- readonly invalidNetwork: {
20
- readonly scheme: "exact";
21
- readonly network: `eip155:${string}`;
22
- readonly amount: "1000000";
23
- readonly asset: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";
24
- readonly payTo: "0x1234567890123456789012345678901234567890";
25
- readonly maxTimeoutSeconds: 300;
26
- };
27
- readonly invalidAsset: {
28
- readonly scheme: "exact";
29
- readonly network: "eip155:84532";
30
- readonly amount: "1000000";
31
- readonly asset: `0x${string}`;
32
- readonly payTo: "0x1234567890123456789012345678901234567890";
33
- readonly maxTimeoutSeconds: 300;
34
- };
35
- };
@@ -1,156 +0,0 @@
1
- /**
2
- * Armory V1 Types - x402 Protocol V1 Compatible
3
- *
4
- * Supports both the x402 V1 specification format and legacy Armory V1 format.
5
- *
6
- * x402 V1 Specification: https://github.com/coinbase/x402
7
- */
8
- import type { Address } from "./v2";
9
- /**
10
- * Network name for x402 V1 (e.g., "base-sepolia", "ethereum-mainnet")
11
- */
12
- export type X402V1Network = string;
13
- /**
14
- * EIP-3009 authorization data (same format for V1 and V2)
15
- */
16
- export interface EIP3009AuthorizationV1 {
17
- from: Address;
18
- to: Address;
19
- value: string;
20
- validAfter: string;
21
- validBefore: string;
22
- nonce: `0x${string}`;
23
- }
24
- /**
25
- * Payment requirements for a specific payment method (x402 V1)
26
- */
27
- export interface X402PaymentRequirementsV1 {
28
- scheme: "exact";
29
- network: X402V1Network;
30
- maxAmountRequired: string;
31
- asset: Address;
32
- payTo: Address;
33
- resource: string;
34
- description: string;
35
- mimeType?: string;
36
- outputSchema?: object | null;
37
- maxTimeoutSeconds: number;
38
- extra?: Record<string, unknown>;
39
- }
40
- /**
41
- * Payment requirements response (x402 V1)
42
- * Matches x402 V1 PaymentRequirementsResponse spec
43
- */
44
- export interface X402PaymentRequiredV1 {
45
- x402Version: 1;
46
- error: string;
47
- accepts: X402PaymentRequirementsV1[];
48
- }
49
- /**
50
- * Scheme payload data (x402 V1)
51
- */
52
- export interface X402SchemePayloadV1 {
53
- signature: `0x${string}`;
54
- authorization: EIP3009AuthorizationV1;
55
- }
56
- /**
57
- * Payment payload (x402 V1)
58
- * Matches x402 V1 PaymentPayload spec
59
- */
60
- export interface X402PaymentPayloadV1 {
61
- x402Version: 1;
62
- scheme: "exact";
63
- network: X402V1Network;
64
- payload: X402SchemePayloadV1;
65
- }
66
- /**
67
- * Settlement response (x402 V1)
68
- * Matches x402 V1 SettlementResponse spec
69
- */
70
- export interface X402SettlementResponseV1 {
71
- success: boolean;
72
- errorReason?: string;
73
- transaction: string;
74
- network: X402V1Network;
75
- payer: Address;
76
- }
77
- /**
78
- * Legacy Armory V1 payment payload format
79
- * @deprecated Use X402PaymentPayloadV1 for new code
80
- */
81
- export interface LegacyPaymentPayloadV1 {
82
- from: string;
83
- to: string;
84
- amount: string;
85
- nonce: string;
86
- expiry: number;
87
- v: number;
88
- r: string;
89
- s: string;
90
- chainId: number;
91
- contractAddress: string;
92
- network: string;
93
- }
94
- /**
95
- * Legacy Armory V1 payment requirements format
96
- * @deprecated Use X402PaymentRequirementsV1 for new code
97
- */
98
- export interface LegacyPaymentRequirementsV1 {
99
- amount: string;
100
- network: string;
101
- contractAddress: string;
102
- payTo: string;
103
- expiry: number;
104
- }
105
- /**
106
- * Legacy Armory V1 settlement response format
107
- * @deprecated Use X402SettlementResponseV1 for new code
108
- */
109
- export interface LegacySettlementResponseV1 {
110
- success: boolean;
111
- txHash?: string;
112
- error?: string;
113
- timestamp: number;
114
- }
115
- export type PaymentPayloadV1 = X402PaymentPayloadV1 | LegacyPaymentPayloadV1;
116
- export type PaymentRequirementsV1 = X402PaymentRequirementsV1 | LegacyPaymentRequirementsV1;
117
- export type SettlementResponseV1 = X402SettlementResponseV1 | LegacySettlementResponseV1;
118
- export declare const V1_HEADERS: {
119
- readonly PAYMENT: "X-PAYMENT";
120
- readonly PAYMENT_RESPONSE: "X-PAYMENT-RESPONSE";
121
- readonly PAYMENT_REQUIRED: "X-PAYMENT-REQUIRED";
122
- };
123
- export declare function encodeX402PaymentRequiredV1(data: X402PaymentRequiredV1): string;
124
- export declare function decodeX402PaymentRequiredV1(encoded: string): X402PaymentRequiredV1;
125
- export declare function encodeX402PaymentPayloadV1(data: X402PaymentPayloadV1): string;
126
- export declare function decodeX402PaymentPayloadV1(encoded: string): X402PaymentPayloadV1;
127
- export declare function encodeX402SettlementResponseV1(data: X402SettlementResponseV1): string;
128
- export declare function decodeX402SettlementResponseV1(encoded: string): X402SettlementResponseV1;
129
- /**
130
- * @deprecated Use encodeX402PaymentPayloadV1 instead
131
- */
132
- export declare function encodePaymentPayloadLegacy(payload: LegacyPaymentPayloadV1): string;
133
- /**
134
- * @deprecated Use decodeX402PaymentPayloadV1 instead
135
- */
136
- export declare function decodePaymentPayloadLegacy(encoded: string): LegacyPaymentPayloadV1;
137
- /**
138
- * @deprecated Use encodeX402SettlementResponseV1 instead
139
- */
140
- export declare function encodeSettlementResponseLegacy(response: LegacySettlementResponseV1): string;
141
- /**
142
- * @deprecated Use decodeX402SettlementResponseV1 instead
143
- */
144
- export declare function decodeSettlementResponseLegacy(encoded: string): LegacySettlementResponseV1;
145
- /**
146
- * Check if value is x402 V1 PaymentRequired
147
- */
148
- export declare function isX402PaymentRequiredV1(obj: unknown): obj is X402PaymentRequiredV1;
149
- /**
150
- * Check if value is x402 V1 PaymentPayload
151
- */
152
- export declare function isX402PaymentPayloadV1(obj: unknown): obj is X402PaymentPayloadV1;
153
- /**
154
- * Check if value is legacy Armory V1 format
155
- */
156
- export declare function isLegacyPaymentPayloadV1(obj: unknown): obj is LegacyPaymentPayloadV1;