@devlab.group/agent-commerce 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +104 -53
  2. package/dist/ap2.d.ts +2 -2
  3. package/dist/ap2.js +4 -3
  4. package/dist/ap2.js.map +1 -1
  5. package/dist/{authorization-BpbWGGrf.d.ts → authorization-CMkIuAkO.d.ts} +1 -1
  6. package/dist/chunk-2CJNA7MS.js +8 -0
  7. package/dist/chunk-2CJNA7MS.js.map +1 -0
  8. package/dist/{chunk-CKJRITWY.js → chunk-5ZYXBCDX.js} +3 -3
  9. package/dist/{chunk-CKJRITWY.js.map → chunk-5ZYXBCDX.js.map} +1 -1
  10. package/dist/{chunk-3LUJHVKX.js → chunk-6Z2H53CG.js} +5 -4
  11. package/dist/chunk-6Z2H53CG.js.map +1 -0
  12. package/dist/{chunk-HOZA3IWP.js → chunk-ES3V6ECS.js} +16 -6
  13. package/dist/chunk-ES3V6ECS.js.map +1 -0
  14. package/dist/chunk-IFGRCXME.js +581 -0
  15. package/dist/chunk-IFGRCXME.js.map +1 -0
  16. package/dist/chunk-KA2AX5FH.js +44 -0
  17. package/dist/chunk-KA2AX5FH.js.map +1 -0
  18. package/dist/{chunk-SYEGCNJZ.js → chunk-LZS5BL3W.js} +3 -3
  19. package/dist/{chunk-SYEGCNJZ.js.map → chunk-LZS5BL3W.js.map} +1 -1
  20. package/dist/{chunk-53WXXIPR.js → chunk-SY6GUYSQ.js} +6 -10
  21. package/dist/chunk-SY6GUYSQ.js.map +1 -0
  22. package/dist/chunk-UHMYRV3J.js +1396 -0
  23. package/dist/chunk-UHMYRV3J.js.map +1 -0
  24. package/dist/cli/index.js +3119 -2212
  25. package/dist/cli/index.js.map +1 -1
  26. package/dist/{constants-BSBRlKRR.d.ts → constants-nackLItD.d.ts} +2 -1
  27. package/dist/index.d.ts +59 -40
  28. package/dist/index.js +2602 -2208
  29. package/dist/index.js.map +1 -1
  30. package/dist/mcp.d.ts +3 -3
  31. package/dist/mcp.js +10 -5
  32. package/dist/mcp.js.map +1 -1
  33. package/dist/mpp.d.ts +12 -5
  34. package/dist/mpp.js +69 -65
  35. package/dist/mpp.js.map +1 -1
  36. package/dist/near-D6C42VPE.js +58 -0
  37. package/dist/near-D6C42VPE.js.map +1 -0
  38. package/dist/networks-olfflCI_.d.ts +38 -0
  39. package/dist/{protocol-adapter-DonxfAwa.d.ts → protocol-adapter-CfxU8Z2T.d.ts} +2 -2
  40. package/dist/{runtime-CiYbgGpi.d.ts → runtime-7vLNYvmU.d.ts} +25 -3
  41. package/dist/svm-QEUAUNPQ.js +33 -0
  42. package/dist/svm-QEUAUNPQ.js.map +1 -0
  43. package/dist/x402.d.ts +71 -64
  44. package/dist/x402.js +13 -4
  45. package/dist/x402.js.map +1 -1
  46. package/package.json +21 -1
  47. package/dist/chunk-3LUJHVKX.js.map +0 -1
  48. package/dist/chunk-53WXXIPR.js.map +0 -1
  49. package/dist/chunk-HOZA3IWP.js.map +0 -1
  50. package/dist/chunk-RKBGCPCK.js +0 -733
  51. package/dist/chunk-RKBGCPCK.js.map +0 -1
  52. package/dist/chunk-TWRUNWDR.js +0 -265
  53. package/dist/chunk-TWRUNWDR.js.map +0 -1
  54. package/dist/{payment-flow-DCS882tR.d.ts → guardrails-CX_jYXvZ.d.ts} +8 -8
@@ -0,0 +1,581 @@
1
+ import { CommerceError } from './chunk-SY6GUYSQ.js';
2
+
3
+ // src/payments/x402/networks.ts
4
+ var LOCAL_CHAIN_ID = 31337;
5
+ var usdc = (address, name) => ({ symbol: "USDC", address, name, version: "2", decimals: 6 });
6
+ var PROFILES = [
7
+ {
8
+ family: "evm",
9
+ id: `eip155:${LOCAL_CHAIN_ID}`,
10
+ chainId: LOCAL_CHAIN_ID,
11
+ displayName: "Local Anvil",
12
+ kind: "testnet",
13
+ local: true
14
+ },
15
+ {
16
+ family: "evm",
17
+ id: "eip155:84532",
18
+ chainId: 84532,
19
+ displayName: "Base Sepolia",
20
+ kind: "testnet",
21
+ canonicalAsset: usdc("0x036CbD53842c5426634e7929541eC2318f3dCF7e", "USDC")
22
+ },
23
+ {
24
+ family: "evm",
25
+ id: "eip155:8453",
26
+ chainId: 8453,
27
+ displayName: "Base",
28
+ kind: "mainnet",
29
+ canonicalAsset: usdc("0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", "USD Coin")
30
+ },
31
+ {
32
+ family: "evm",
33
+ id: "eip155:1",
34
+ chainId: 1,
35
+ displayName: "Ethereum",
36
+ kind: "mainnet",
37
+ canonicalAsset: usdc("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "USD Coin")
38
+ },
39
+ {
40
+ family: "evm",
41
+ id: "eip155:137",
42
+ chainId: 137,
43
+ displayName: "Polygon",
44
+ kind: "mainnet",
45
+ canonicalAsset: usdc("0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359", "USD Coin")
46
+ },
47
+ {
48
+ family: "evm",
49
+ id: "eip155:42161",
50
+ chainId: 42161,
51
+ displayName: "Arbitrum One",
52
+ kind: "mainnet",
53
+ canonicalAsset: usdc("0xaf88d065e77c8cC2239327C5EDb3A432268e5831", "USD Coin")
54
+ },
55
+ {
56
+ family: "evm",
57
+ id: "eip155:421614",
58
+ chainId: 421614,
59
+ displayName: "Arbitrum Sepolia",
60
+ kind: "testnet",
61
+ canonicalAsset: usdc("0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d", "USD Coin")
62
+ },
63
+ {
64
+ family: "evm",
65
+ id: "eip155:43114",
66
+ chainId: 43114,
67
+ displayName: "Avalanche C-Chain",
68
+ kind: "mainnet",
69
+ canonicalAsset: usdc("0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E", "USD Coin")
70
+ },
71
+ {
72
+ family: "svm",
73
+ id: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
74
+ displayName: "Solana",
75
+ kind: "mainnet",
76
+ canonicalAsset: {
77
+ symbol: "USDC",
78
+ address: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
79
+ decimals: 6
80
+ }
81
+ },
82
+ {
83
+ family: "svm",
84
+ id: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",
85
+ displayName: "Solana Devnet",
86
+ kind: "testnet",
87
+ canonicalAsset: {
88
+ symbol: "USDC",
89
+ address: "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU",
90
+ decimals: 6
91
+ }
92
+ },
93
+ // NEAR's USDC contracts are implicit accounts: 64 lowercase hex characters
94
+ {
95
+ family: "near",
96
+ id: "near:mainnet",
97
+ displayName: "NEAR",
98
+ kind: "mainnet",
99
+ canonicalAsset: {
100
+ symbol: "USDC",
101
+ address: "17208628f84f5d6ad33f0da3bbbeb27ffcb398eac501a31bd6ad2011e36133a1",
102
+ decimals: 6
103
+ }
104
+ },
105
+ {
106
+ family: "near",
107
+ id: "near:testnet",
108
+ displayName: "NEAR Testnet",
109
+ kind: "testnet",
110
+ canonicalAsset: {
111
+ symbol: "USDC",
112
+ address: "3e2210e1184b45b64c8a434c0a7e7b23cc04ea7eb7a6c3c32520d03d4afcb8af",
113
+ decimals: 6
114
+ }
115
+ }
116
+ ];
117
+ var BY_ID = new Map(PROFILES.map((profile) => [profile.id, profile]));
118
+ var SUPPORTED_NETWORK_IDS = PROFILES.filter(
119
+ (p) => p.family === "evm"
120
+ ).map((p) => p.id);
121
+ var EVM_NETWORK_ID = /^eip155:([1-9]\d{0,15})$/;
122
+ function invalid(message, path) {
123
+ return new CommerceError("CONFIG_INVALID", message, { details: { path } });
124
+ }
125
+ function findX402Network(id, custom) {
126
+ const builtIn = BY_ID.get(id);
127
+ if (builtIn) return builtIn;
128
+ const declared = custom?.[id];
129
+ const chainId = Number(EVM_NETWORK_ID.exec(id)?.[1]);
130
+ if (!declared || !Number.isSafeInteger(chainId)) return void 0;
131
+ return {
132
+ family: "evm",
133
+ id,
134
+ chainId,
135
+ displayName: declared.displayName,
136
+ kind: declared.kind
137
+ };
138
+ }
139
+ function requireX402Network(id, path, custom) {
140
+ const network = findX402Network(id, custom);
141
+ if (!network) {
142
+ throw new CommerceError(
143
+ "CONFIG_INVALID",
144
+ `${path}: "${id}" is not a known network. Built-in CAIP-2 identifiers: ${PROFILES.map((p) => p.id).join(", ")}. Declare another EVM network under payments.x402.networks with its kind and displayName.`,
145
+ { details: { path, network: id } }
146
+ );
147
+ }
148
+ return network;
149
+ }
150
+ function validateCustomNetworks(custom, path) {
151
+ for (const id of Object.keys(custom)) {
152
+ const at = `${path}.${id}`;
153
+ if (BY_ID.has(id)) {
154
+ throw invalid(
155
+ `${at}: "${id}" is a built-in network and cannot be redeclared; remove this entry`,
156
+ at
157
+ );
158
+ }
159
+ if (!findX402Network(id, custom)) {
160
+ throw invalid(
161
+ `${at}: "${id}" is not an EVM CAIP-2 identifier ("eip155:" followed by a positive chain id below 2^53). Only EVM networks can be declared.`,
162
+ at
163
+ );
164
+ }
165
+ }
166
+ }
167
+ function resolveDeploymentMode(profile) {
168
+ return profile.local ? "local" : profile.kind;
169
+ }
170
+ var LIVE_MAINNET_BANNER = "LIVE MAINNET MODE - REAL FUNDS";
171
+ function describeDeploymentMode(mode) {
172
+ return mode === "mainnet" ? LIVE_MAINNET_BANNER : mode.toUpperCase();
173
+ }
174
+
175
+ // src/core/execution/settlement-order.ts
176
+ var SETTLE_AFTER_BACKEND_METADATA_KEY = "settleAfterBackend";
177
+ var REUSE_REJECTED_AUTHORIZATION_METADATA_KEY = "reuseRejectedAuthorization";
178
+
179
+ // src/payments/x402/addresses.ts
180
+ var EVM_ADDRESS = /^0x[0-9a-fA-F]{40}$/;
181
+ var EVM_ZERO = /^0x0{40}$/i;
182
+ var isEvmAddress = (value) => typeof value === "string" && EVM_ADDRESS.test(value);
183
+ var isEvmZeroAddress = (value) => EVM_ZERO.test(value);
184
+ var BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
185
+ var SOLANA_ADDRESS = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
186
+ var SOLANA_ZERO = "11111111111111111111111111111111";
187
+ var EVM_TRANSACTION_HASH = /^0x[0-9a-fA-F]{64}$/;
188
+ var SOLANA_SIGNATURE = /^[1-9A-HJ-NP-Za-km-z]{64,88}$/;
189
+ var NEAR_ACCOUNT_ID = /^(([a-z\d]+[-_])*[a-z\d]+\.)*([a-z\d]+[-_])*[a-z\d]+$/;
190
+ var NEAR_TRANSACTION_HASH = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
191
+ function normalizeAddress(network, value) {
192
+ switch (network.family) {
193
+ case "evm":
194
+ return isEvmAddress(value) ? value : void 0;
195
+ case "svm":
196
+ return SOLANA_ADDRESS.test(value) && base58ByteLength(value) === 32 ? value : void 0;
197
+ case "near":
198
+ return value.length >= 2 && value.length <= 64 && NEAR_ACCOUNT_ID.test(value) ? value : void 0;
199
+ }
200
+ }
201
+ function isBurnAddress(network, wireAddress) {
202
+ switch (network.family) {
203
+ case "evm":
204
+ return isEvmZeroAddress(wireAddress);
205
+ case "svm":
206
+ return wireAddress === SOLANA_ZERO;
207
+ case "near":
208
+ return false;
209
+ }
210
+ }
211
+ function sameAddress(network, a, b) {
212
+ return network.family === "evm" ? a.toLowerCase() === b.toLowerCase() : a === b;
213
+ }
214
+ function isTransactionReference(network, value) {
215
+ switch (network.family) {
216
+ case "evm":
217
+ return EVM_TRANSACTION_HASH.test(value);
218
+ case "svm":
219
+ return SOLANA_SIGNATURE.test(value) && base58ByteLength(value) === 64;
220
+ case "near":
221
+ return NEAR_TRANSACTION_HASH.test(value) && base58ByteLength(value) === 32;
222
+ }
223
+ }
224
+ function base58ByteLength(value) {
225
+ let n = 0n;
226
+ for (const char of value) n = n * 58n + BigInt(BASE58_ALPHABET.indexOf(char));
227
+ const leadingZeros = value.length - value.replace(/^1+/, "").length;
228
+ return leadingZeros + (n === 0n ? 0 : Math.ceil(n.toString(16).length / 2));
229
+ }
230
+
231
+ // src/payments/x402/local-chain/accounts.ts
232
+ var ANVIL_WELL_KNOWN_ACCOUNTS = [
233
+ {
234
+ address: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
235
+ privateKey: "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
236
+ },
237
+ {
238
+ address: "0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
239
+ privateKey: "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d"
240
+ },
241
+ {
242
+ address: "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC",
243
+ privateKey: "0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a"
244
+ }
245
+ ];
246
+
247
+ // src/payments/x402/dev-key-guard.ts
248
+ var WELL_KNOWN_DEV_KEYS = new Set(
249
+ ANVIL_WELL_KNOWN_ACCOUNTS.map((a) => a.privateKey.toLowerCase())
250
+ );
251
+ var WELL_KNOWN_DEV_ADDRESSES = new Set(
252
+ ANVIL_WELL_KNOWN_ACCOUNTS.map((a) => a.address.toLowerCase())
253
+ );
254
+ var PRIVATE_KEY_SHAPE = /^0x[0-9a-fA-F]{64}$/;
255
+ function isWellKnownDevKey(privateKey) {
256
+ return WELL_KNOWN_DEV_KEYS.has(privateKey.toLowerCase());
257
+ }
258
+ function isWellKnownDevAddress(address) {
259
+ return WELL_KNOWN_DEV_ADDRESSES.has(address.toLowerCase());
260
+ }
261
+ function isLikelyLocalOrPrivateHost(hostname) {
262
+ const h = hostname.toLowerCase().replace(/^\[|\]$/g, "");
263
+ if (h === "localhost" || h === "::1") return true;
264
+ if (/^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(h)) return true;
265
+ if (/^10\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(h)) return true;
266
+ if (/^192\.168\.\d{1,3}\.\d{1,3}$/.test(h)) return true;
267
+ if (/^172\.(1[6-9]|2\d|3[01])\.\d{1,3}\.\d{1,3}$/.test(h)) return true;
268
+ if (!h.includes(".") && !h.includes(":")) return true;
269
+ return false;
270
+ }
271
+ function parseHostnameOrThrow(rpcUrl) {
272
+ try {
273
+ return new URL(rpcUrl).hostname;
274
+ } catch (cause) {
275
+ throw new CommerceError("CONFIG_INVALID", "x402 provider: rpcUrl is not a valid URL", {
276
+ cause
277
+ });
278
+ }
279
+ }
280
+ function describeRpc(rpcUrl) {
281
+ try {
282
+ return new URL(rpcUrl).origin;
283
+ } catch {
284
+ return "[unparseable rpcUrl]";
285
+ }
286
+ }
287
+ function assertDevKeyIsLocalOnly(rpcUrl, signerPrivateKey) {
288
+ if (!PRIVATE_KEY_SHAPE.test(signerPrivateKey)) {
289
+ throw new CommerceError(
290
+ "CONFIG_INVALID",
291
+ 'x402 provider: facilitator.signerPrivateKey is not a well-formed private key (expected "0x" followed by exactly 64 hex characters).'
292
+ );
293
+ }
294
+ if (!isWellKnownDevKey(signerPrivateKey)) return;
295
+ const hostname = parseHostnameOrThrow(rpcUrl);
296
+ if (!isLikelyLocalOrPrivateHost(hostname)) {
297
+ throw new CommerceError(
298
+ "CONFIG_INVALID",
299
+ `x402 provider: facilitator.signerPrivateKey is a well-known Anvil development key, but rpcUrl ${describeRpc(rpcUrl)} does not look like a local/private chain. A public dev key must never sign against a public network: it is instantly drainable and can grief real settlements via nonce exhaustion. Use a real facilitator key for any non-local RPC, or point rpcUrl at your local/dev chain.`
300
+ );
301
+ }
302
+ }
303
+ function assertPayToIsNotDevAddress(rpcUrl, payTo) {
304
+ if (!isWellKnownDevAddress(payTo)) return;
305
+ const hostname = parseHostnameOrThrow(rpcUrl);
306
+ if (!isLikelyLocalOrPrivateHost(hostname)) {
307
+ throw new CommerceError(
308
+ "CONFIG_INVALID",
309
+ `x402 provider: "payTo" (${payTo}) is a well-known Anvil development address, but rpcUrl ${describeRpc(rpcUrl)} does not look like a local/private chain. The private key behind that address is public knowledge, so any revenue settled to it is immediately spendable by anyone. Set "payTo" to your own merchant wallet for any non-local RPC, or point rpcUrl at your local/dev chain.`
310
+ );
311
+ }
312
+ }
313
+
314
+ // src/payments/x402/guardrails.ts
315
+ var BASE_SEPOLIA = "eip155:84532";
316
+ function invalid2(message, path) {
317
+ return new CommerceError("CONFIG_INVALID", message, { details: { path } });
318
+ }
319
+ function resolveX402Deployment(input) {
320
+ const at = input.configPath ?? "payments.x402";
321
+ const payTo = input.payToField ?? "payTo";
322
+ const profile = requireX402Network(input.network, `${at}.network`, input.customNetworks);
323
+ const mode = resolveDeploymentMode(profile);
324
+ if (profile.kind === "mainnet" && input.facilitator.mode === "local") {
325
+ throw invalid2(
326
+ `${at}: network "${profile.id}" (${profile.displayName}) is a mainnet and cannot be served by facilitator.mode "local". A mainnet deployment must settle through a remote facilitator.`,
327
+ `${at}.facilitator.mode`
328
+ );
329
+ }
330
+ if (input.facilitator.mode === "local" && mode !== "local") {
331
+ throw invalid2(
332
+ profile.id === BASE_SEPOLIA ? `${at}: the local Anvil chain is eip155:${LOCAL_CHAIN_ID}, Anvil's default chain id; "${BASE_SEPOLIA}" is public Base Sepolia. Set ${at}.network to eip155:${LOCAL_CHAIN_ID}, start Anvil with its default chain id and redeploy the local contracts (npm run chain:start, npm run chain:deploy).` : `${at}: facilitator.mode "local" serves the local Anvil chain (eip155:${LOCAL_CHAIN_ID}) only, not "${profile.id}" (${profile.displayName}). Use a remote facilitator.`,
333
+ `${at}.facilitator.mode`
334
+ );
335
+ }
336
+ if (mode === "mainnet" && input.allowMainnet !== true) {
337
+ throw invalid2(
338
+ `${at}: network "${profile.id}" (${profile.displayName}) settles real funds. Set ${at}.allowMainnet: true to acknowledge this explicitly - it is never the default.`,
339
+ `${at}.allowMainnet`
340
+ );
341
+ }
342
+ if (input.facilitator.mode === "remote") {
343
+ assertFacilitatorUrlIsSafe(input.facilitator.url, mode, at);
344
+ if (input.facilitator.auth.type === "cdp" && !isCdpFacilitatorUrl(input.facilitator.url)) {
345
+ throw invalid2(
346
+ `${at}: facilitator.auth.type "cdp" signs requests for ${CDP_FACILITATOR_URL} only, so facilitator ${describeOrigin(input.facilitator.url)} cannot accept its credential. Set facilitator.url to ${CDP_FACILITATOR_URL}, or use auth.type "bearer" or "none".`,
347
+ `${at}.facilitator.url`
348
+ );
349
+ }
350
+ if (mode === "mainnet" && input.facilitator.auth.type === "none" && input.allowUnauthenticatedFacilitator !== true) {
351
+ throw invalid2(
352
+ `${at}: no credential is configured for facilitator ${describeOrigin(input.facilitator.url)} on mainnet. Set ${at}.allowUnauthenticatedFacilitator: true to accept anonymous access and the facilitator's limits, or configure facilitator.auth.`,
353
+ `${at}.allowUnauthenticatedFacilitator`
354
+ );
355
+ }
356
+ for (const [field, value] of credentialFields(input.facilitator.auth)) {
357
+ if (value.trim() === "") {
358
+ throw invalid2(
359
+ `${at}: facilitator.auth.type is "${input.facilitator.auth.type}" but ${field} is empty. An empty credential is refused rather than sent.`,
360
+ `${at}.facilitator.auth.${field}`
361
+ );
362
+ }
363
+ }
364
+ }
365
+ if (isBurnAddress(profile, input.payTo)) {
366
+ throw invalid2(
367
+ `${at}: "${payTo}" is the zero address. Every payment settled there is destroyed.`,
368
+ `${at}.${payTo}`
369
+ );
370
+ }
371
+ if (mode !== "local" && isWellKnownDevAddress(input.payTo)) {
372
+ throw invalid2(
373
+ `${at}: "${payTo}" (${input.payTo}) is a well-known Anvil development address and this is a ${mode} deployment. Anyone can spend what settles there. Set ${payTo} to your own merchant wallet.`,
374
+ `${at}.${payTo}`
375
+ );
376
+ }
377
+ const canonical = profile.canonicalAsset;
378
+ if (canonical) {
379
+ if (!sameAddress(profile, input.asset, canonical.address)) {
380
+ throw invalid2(
381
+ `${at}: asset ${input.asset} is not ${canonical.symbol} on ${profile.displayName} (expected ${canonical.address}). A built-in network settles only in its ${canonical.symbol}.`,
382
+ `${at}.asset`
383
+ );
384
+ }
385
+ const domain = "name" in canonical ? canonical : void 0;
386
+ if (domain && input.assetName !== void 0 && input.assetName !== domain.name) {
387
+ throw invalid2(
388
+ `${at}: assetName "${input.assetName}" is not the EIP-712 domain name ${canonical.symbol} reports on ${profile.displayName} (expected "${domain.name}"). Every payment would be refused after the buyer signed.`,
389
+ `${at}.assetName`
390
+ );
391
+ }
392
+ if (domain && input.assetVersion !== void 0 && input.assetVersion !== domain.version) {
393
+ throw invalid2(
394
+ `${at}: assetVersion "${input.assetVersion}" is not the EIP-712 domain version ${canonical.symbol} reports on ${profile.displayName} (expected "${domain.version}").`,
395
+ `${at}.assetVersion`
396
+ );
397
+ }
398
+ }
399
+ return { profile, mode };
400
+ }
401
+ function assertFacilitatorUrlIsSafe(url, mode, at) {
402
+ let parsed;
403
+ try {
404
+ parsed = new URL(url);
405
+ } catch (cause) {
406
+ throw new CommerceError("CONFIG_INVALID", `${at}: facilitator.url is not a valid URL`, {
407
+ cause,
408
+ details: { path: `${at}.facilitator.url` }
409
+ });
410
+ }
411
+ if (parsed.protocol === "https:") return;
412
+ if (parsed.protocol !== "http:") {
413
+ throw invalid2(
414
+ `${at}: facilitator ${describeOrigin(url)} must be reached over https (or http on a local/private host); got "${parsed.protocol}//"`,
415
+ `${at}.facilitator.url`
416
+ );
417
+ }
418
+ if (mode !== "mainnet" && isLikelyLocalOrPrivateHost(parsed.hostname)) return;
419
+ throw invalid2(
420
+ `${at}: facilitator ${describeOrigin(url)} is reached over plain HTTP. Payment authorizations and settlement results would travel unencrypted. Use https, or point at a local/private host on a non-mainnet deployment.`,
421
+ `${at}.facilitator.url`
422
+ );
423
+ }
424
+ var CDP_FACILITATOR_URL = "https://api.cdp.coinbase.com/platform/v2/x402";
425
+ function isCdpFacilitatorUrl(url) {
426
+ try {
427
+ const parsed = new URL(url);
428
+ const expected = new URL(CDP_FACILITATOR_URL);
429
+ return parsed.origin === expected.origin && parsed.pathname.replace(/\/+$/, "") === expected.pathname && parsed.search === "";
430
+ } catch {
431
+ return false;
432
+ }
433
+ }
434
+ function describeOrigin(url) {
435
+ try {
436
+ return new URL(url).origin;
437
+ } catch {
438
+ return "[unparseable facilitator.url]";
439
+ }
440
+ }
441
+ function credentialFields(auth) {
442
+ switch (auth.type) {
443
+ case "bearer":
444
+ return [["token", auth.token]];
445
+ case "cdp":
446
+ return [
447
+ ["apiKeyId", auth.apiKeyId],
448
+ ["apiKeySecret", auth.apiKeySecret]
449
+ ];
450
+ default:
451
+ return [];
452
+ }
453
+ }
454
+
455
+ // src/payments/x402/options.ts
456
+ function x402OfferName(offer) {
457
+ const evm = offer.network.startsWith("eip155:");
458
+ const address = (value) => evm ? value.toLowerCase() : value;
459
+ return `${offer.network} ${address(offer.asset)} ${address(offer.payTo)}`;
460
+ }
461
+ var FIELD_MEANINGS = {
462
+ assetName: "EIP-712 domain name",
463
+ assetVersion: "EIP-712 domain version",
464
+ assetDecimals: "decimals"
465
+ };
466
+ var ADDRESS_SHAPES = {
467
+ evm: '"0x" followed by 40 hex characters',
468
+ svm: "a base58 public key of 32 bytes",
469
+ near: 'a NEAR account ID: 2 to 64 lowercase characters, digits and single "-", "_" or "." separators'
470
+ };
471
+ function invalid3(message, path) {
472
+ return new CommerceError("CONFIG_INVALID", message, { details: { path } });
473
+ }
474
+ function resolveX402Option(input, path, custom) {
475
+ if (input.scheme !== void 0 && input.scheme !== "exact") {
476
+ throw invalid3(
477
+ `${path}.scheme: "${input.scheme}" is not supported; the only x402 scheme is "exact"`,
478
+ `${path}.scheme`
479
+ );
480
+ }
481
+ const network = requireX402Network(input.network, `${path}.network`, custom);
482
+ const address = (field, value) => {
483
+ const wire = normalizeAddress(network, value);
484
+ if (wire === void 0) {
485
+ throw invalid3(
486
+ // The value is not echoed: a swapped variable could put a key here
487
+ `${path}.${field} is not a plausible address on ${network.displayName} (expected ${ADDRESS_SHAPES[network.family]})`,
488
+ `${path}.${field}`
489
+ );
490
+ }
491
+ return wire;
492
+ };
493
+ const payTo = address("payTo", input.payTo);
494
+ if (isBurnAddress(network, payTo)) {
495
+ throw invalid3(
496
+ `${path}.payTo is the zero address of ${network.displayName}. Every payment settled there is destroyed.`,
497
+ `${path}.payTo`
498
+ );
499
+ }
500
+ const method = input.assetTransferMethod ?? "eip3009";
501
+ if (method !== "eip3009" && method !== "permit2") {
502
+ throw invalid3(
503
+ `${path}.assetTransferMethod: "${method}" is not supported; use "eip3009" or "permit2"`,
504
+ `${path}.assetTransferMethod`
505
+ );
506
+ }
507
+ if (network.family !== "evm" && input.assetTransferMethod !== void 0) {
508
+ throw invalid3(
509
+ `${path}.assetTransferMethod applies to EVM networks only, not to ${network.displayName}`,
510
+ `${path}.assetTransferMethod`
511
+ );
512
+ }
513
+ if (network.family !== "evm") {
514
+ for (const field of ["assetName", "assetVersion"]) {
515
+ if (input[field] !== void 0) {
516
+ throw invalid3(
517
+ `${path}.${field}: an EIP-712 domain applies to EVM tokens only, not to ${network.displayName}`,
518
+ `${path}.${field}`
519
+ );
520
+ }
521
+ }
522
+ }
523
+ const canonical = network.canonicalAsset;
524
+ const domain = canonical && "name" in canonical ? canonical : void 0;
525
+ const asset = input.asset !== void 0 ? address("asset", input.asset) : void 0;
526
+ if (asset !== void 0 && isBurnAddress(network, asset)) {
527
+ throw invalid3(`${path}.asset must not be the zero address`, `${path}.asset`);
528
+ }
529
+ if (canonical && (asset === void 0 || sameAddress(network, asset, canonical.address))) {
530
+ const expected = {
531
+ assetName: domain?.name,
532
+ assetVersion: domain?.version,
533
+ assetDecimals: canonical.decimals
534
+ };
535
+ for (const field of ["assetName", "assetVersion", "assetDecimals"]) {
536
+ const given = input[field];
537
+ if (given !== void 0 && given !== expected[field]) {
538
+ throw invalid3(
539
+ `${path}.${field} does not match ${canonical.symbol} on ${network.displayName}, which reports ${FIELD_MEANINGS[field]} ${JSON.stringify(expected[field])}. Remove ${field}, or set asset to the token it describes.`,
540
+ `${path}.${field}`
541
+ );
542
+ }
543
+ }
544
+ return {
545
+ scheme: "exact",
546
+ network,
547
+ payTo,
548
+ asset: asset ?? canonical.address,
549
+ ...domain ? { assetName: domain.name, assetVersion: domain.version } : {},
550
+ assetDecimals: canonical.decimals,
551
+ defaultAssetSymbol: canonical.symbol,
552
+ assetTransferMethod: method
553
+ };
554
+ }
555
+ const required = network.family === "evm" && method === "eip3009" ? ["asset", "assetName", "assetVersion", "assetDecimals"] : ["asset", "assetDecimals"];
556
+ const missing = required.filter((field) => input[field] === void 0);
557
+ if (asset === void 0 || missing.length > 0) {
558
+ throw invalid3(
559
+ canonical ? `${path}: a token other than ${canonical.symbol} on ${network.displayName} needs ${missing.join(", ")}` : `${path}: ${network.displayName} has no default asset, so the option needs ${missing.join(", ")}`,
560
+ `${path}.${missing[0] ?? "asset"}`
561
+ );
562
+ }
563
+ return {
564
+ scheme: "exact",
565
+ network,
566
+ payTo,
567
+ asset,
568
+ ...input.assetName !== void 0 ? { assetName: input.assetName } : {},
569
+ ...input.assetVersion !== void 0 ? { assetVersion: input.assetVersion } : {},
570
+ assetDecimals: input.assetDecimals,
571
+ assetTransferMethod: method
572
+ };
573
+ }
574
+
575
+ // src/payments/x402/payment-flow.ts
576
+ var X402_PAYMENT_FLOWS = ["authorization", "upfront"];
577
+ var X402_DEFAULT_PAYMENT_FLOW = "authorization";
578
+
579
+ export { LOCAL_CHAIN_ID, REUSE_REJECTED_AUTHORIZATION_METADATA_KEY, SETTLE_AFTER_BACKEND_METADATA_KEY, SUPPORTED_NETWORK_IDS, X402_DEFAULT_PAYMENT_FLOW, X402_PAYMENT_FLOWS, assertDevKeyIsLocalOnly, assertPayToIsNotDevAddress, describeDeploymentMode, describeRpc, findX402Network, isEvmAddress, isEvmZeroAddress, isTransactionReference, normalizeAddress, requireX402Network, resolveDeploymentMode, resolveX402Deployment, resolveX402Option, sameAddress, validateCustomNetworks, x402OfferName };
580
+ //# sourceMappingURL=chunk-IFGRCXME.js.map
581
+ //# sourceMappingURL=chunk-IFGRCXME.js.map