@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.
- package/dist/encoding/x402.d.ts +2 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +162 -344
- package/dist/payment-client.d.ts +23 -0
- package/dist/types/protocol.d.ts +0 -4
- package/dist/types/v2.d.ts +6 -6
- package/dist/types/x402.d.ts +18 -44
- package/dist/utils/utils/index.d.ts +0 -1
- package/package.json +3 -3
- package/dist/fixtures/config.d.ts +0 -48
- package/dist/fixtures/payloads.d.ts +0 -16
- package/dist/fixtures/requirements.d.ts +0 -35
- package/dist/types/v1.d.ts +0 -156
package/dist/encoding/x402.d.ts
CHANGED
|
@@ -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,
|
|
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
|
|
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,
|
|
2
|
-
export { X402_VERSION, SCHEMES, isPaymentPayload, isExactEvmPayload,
|
|
3
|
-
export { safeBase64Encode, safeBase64Decode, encodePayment, decodePayment, encodeSettlementResponse, decodeSettlementResponse, encodeX402Response, decodeX402Response, detectPaymentVersion, extractPaymentFromHeaders, createPaymentRequiredHeaders, createSettlementHeaders,
|
|
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,
|
|
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 {
|
|
23
|
-
export {
|
|
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 =
|
|
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 && "
|
|
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 && "
|
|
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
|
-
|
|
167
|
-
|
|
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(
|
|
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
|
-
|
|
182
|
-
|
|
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
|
-
|
|
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
|
-
|
|
199
|
-
|
|
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
|
-
|
|
206
|
-
|
|
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 && "
|
|
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: "
|
|
274
|
+
usdcAddress: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
|
|
371
275
|
rpcUrl: "https://sepolia.base.org",
|
|
372
276
|
caip2Id: "eip155:84532",
|
|
373
|
-
caipAssetId: "eip155:84532/erc20:
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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) => "
|
|
1293
|
-
var isSettlementV2 = (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/
|
|
1296
|
-
var
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
}
|
|
1308
|
-
|
|
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
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
}
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
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
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
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 {};
|
package/dist/types/protocol.d.ts
CHANGED
|
@@ -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
|
*/
|
package/dist/types/v2.d.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
/**
|
|
111
|
-
|
|
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
|
|
116
|
+
/** Resource being accessed (optional) */
|
|
117
117
|
resource?: ResourceInfo;
|
|
118
118
|
/** Protocol extensions data */
|
|
119
119
|
extensions?: Extensions;
|
package/dist/types/x402.d.ts
CHANGED
|
@@ -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:
|
|
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
|
-
*
|
|
34
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@armory-sh/base",
|
|
3
|
-
"version": "0.2.
|
|
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/
|
|
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
|
-
};
|
package/dist/types/v1.d.ts
DELETED
|
@@ -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;
|