@devlab.group/agent-commerce 1.6.1 → 2.0.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.
- package/LICENSE +187 -2
- package/README.md +6 -6
- package/dist/ap2.d.ts +2 -2
- package/dist/ap2.js +94 -28
- package/dist/ap2.js.map +1 -1
- package/dist/{chunk-V2V2E7HX.js → chunk-3LUJHVKX.js} +4 -4
- package/dist/{chunk-V2V2E7HX.js.map → chunk-3LUJHVKX.js.map} +1 -1
- package/dist/{chunk-N5KRK7YA.js → chunk-53WXXIPR.js} +3 -3
- package/dist/{chunk-N5KRK7YA.js.map → chunk-53WXXIPR.js.map} +1 -1
- package/dist/chunk-CKJRITWY.js +113 -0
- package/dist/chunk-CKJRITWY.js.map +1 -0
- package/dist/chunk-HOZA3IWP.js +115 -0
- package/dist/chunk-HOZA3IWP.js.map +1 -0
- package/dist/{chunk-JKEKKXRJ.js → chunk-RKBGCPCK.js} +78 -25
- package/dist/chunk-RKBGCPCK.js.map +1 -0
- package/dist/{chunk-VKDXMXHL.js → chunk-SYEGCNJZ.js} +3 -3
- package/dist/{chunk-VKDXMXHL.js.map → chunk-SYEGCNJZ.js.map} +1 -1
- package/dist/{chunk-CBJIT7QP.js → chunk-TWRUNWDR.js} +11 -4
- package/dist/chunk-TWRUNWDR.js.map +1 -0
- package/dist/cli/index.js +142 -33
- package/dist/cli/index.js.map +1 -1
- package/dist/{constants-Bkq04FRZ.d.ts → constants-BSBRlKRR.d.ts} +2 -2
- package/dist/index.d.ts +42 -22
- package/dist/index.js +1254 -377
- package/dist/index.js.map +1 -1
- package/dist/mcp.d.ts +1 -1
- package/dist/mcp.js +247 -94
- package/dist/mcp.js.map +1 -1
- package/dist/mpp.d.ts +6 -2
- package/dist/mpp.js +65 -28
- package/dist/mpp.js.map +1 -1
- package/dist/{guardrails-71XwtXlT.d.ts → payment-flow-DCS882tR.d.ts} +9 -1
- package/dist/{protocol-adapter-DTkrXTev.d.ts → protocol-adapter-DonxfAwa.d.ts} +2 -0
- package/dist/{types-O6lg3Q5V.d.ts → types-CVw6Sf46.d.ts} +11 -0
- package/dist/x402.d.ts +11 -3
- package/dist/x402.js +4 -4
- package/package.json +16 -13
- package/dist/chunk-AFI2CEZS.js +0 -10
- package/dist/chunk-AFI2CEZS.js.map +0 -1
- package/dist/chunk-CBJIT7QP.js.map +0 -1
- package/dist/chunk-JKEKKXRJ.js.map +0 -1
|
@@ -28,4 +28,12 @@ type X402FacilitatorConfig = {
|
|
|
28
28
|
readonly auth: FacilitatorAuth;
|
|
29
29
|
};
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
/**
|
|
32
|
+
* x402 exact-scheme flows, shared by the config loader and CLI.
|
|
33
|
+
* The default `authorization` flow settles after a successful backend call;
|
|
34
|
+
* `upfront` settles first.
|
|
35
|
+
*/
|
|
36
|
+
declare const X402_PAYMENT_FLOWS: readonly ["authorization", "upfront"];
|
|
37
|
+
type X402PaymentFlow = (typeof X402_PAYMENT_FLOWS)[number];
|
|
38
|
+
|
|
39
|
+
export type { FacilitatorAuth as F, X402PaymentFlow as X, X402FacilitatorConfig as a };
|
|
@@ -112,6 +112,8 @@ interface CanonicalRequest {
|
|
|
112
112
|
* Passed on as `BackendRequest.idempotencyKey`.
|
|
113
113
|
*/
|
|
114
114
|
readonly idempotencyKey?: string;
|
|
115
|
+
/** Adapter headers passed to the backend; configured headers take precedence */
|
|
116
|
+
readonly backendHeaders?: Readonly<Record<string, string>>;
|
|
115
117
|
/** Non-secret transport metadata, such as client id or user agent */
|
|
116
118
|
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
117
119
|
}
|
|
@@ -80,6 +80,17 @@ type Ap2AuthorizationConfig = {
|
|
|
80
80
|
readonly checkoutIssuers: readonly Ap2TrustedIssuer[];
|
|
81
81
|
};
|
|
82
82
|
readonly clockSkewSeconds: number;
|
|
83
|
+
/**
|
|
84
|
+
* Refuse a mandate with no `aud`. AP2 makes the claim optional, so by
|
|
85
|
+
* default it is checked only when present.
|
|
86
|
+
*/
|
|
87
|
+
readonly requireMandateAudience?: boolean;
|
|
88
|
+
/**
|
|
89
|
+
* Refuse a mandate with no `exp`, at the top level or in the mandate
|
|
90
|
+
* content. AP2 makes it optional, so by default it is checked only when
|
|
91
|
+
* present.
|
|
92
|
+
*/
|
|
93
|
+
readonly requireMandateExpiry?: boolean;
|
|
83
94
|
/** Its own SQLite file. An authorization replay is not a payment replay */
|
|
84
95
|
readonly replay: {
|
|
85
96
|
readonly path: string;
|
package/dist/x402.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { X as X402FacilitatorConfig } from './
|
|
2
|
-
export { F as FacilitatorAuth } from './
|
|
1
|
+
import { X as X402PaymentFlow, a as X402FacilitatorConfig } from './payment-flow-DCS882tR.js';
|
|
2
|
+
export { F as FacilitatorAuth } from './payment-flow-DCS882tR.js';
|
|
3
3
|
import { L as Logger, C as Clock, e as IdGenerator, d as PaymentProvider } from './runtime-CiYbgGpi.js';
|
|
4
4
|
|
|
5
5
|
interface NetworkProfile {
|
|
@@ -91,6 +91,14 @@ interface X402ProviderOptions {
|
|
|
91
91
|
/** Merchant-controlled settlement destination. Never a gateway-owned wallet */
|
|
92
92
|
readonly payTo: `0x${string}`;
|
|
93
93
|
readonly maxTimeoutSeconds?: number;
|
|
94
|
+
/**
|
|
95
|
+
* When the payment settles relative to the backend call. Defaults to
|
|
96
|
+
* `authorization`, the x402 default: settle only after the backend succeeds.
|
|
97
|
+
* `upfront` settles before the backend call.
|
|
98
|
+
*/
|
|
99
|
+
readonly paymentFlow?: X402PaymentFlow;
|
|
100
|
+
/** Per-resource overrides of `paymentFlow`, keyed by resource id */
|
|
101
|
+
readonly resourcePaymentFlows?: Readonly<Record<string, X402PaymentFlow>>;
|
|
94
102
|
/**
|
|
95
103
|
* Which facilitator verifies and broadcasts. `local` runs one in this process
|
|
96
104
|
* against a dev chain, and its `signerPrivateKey` pays gas there, usually
|
|
@@ -108,4 +116,4 @@ interface X402ProviderOptions {
|
|
|
108
116
|
}
|
|
109
117
|
declare function createX402PaymentProvider(options: X402ProviderOptions): PaymentProvider;
|
|
110
118
|
|
|
111
|
-
export { type CreatePaymentProofOptions, type DeploymentMode, type NetworkProfile, SUPPORTED_NETWORK_IDS, X402FacilitatorConfig, type X402ProviderOptions, createPaymentProof, createX402PaymentProvider, createX402PaymentProvider as x402 };
|
|
119
|
+
export { type CreatePaymentProofOptions, type DeploymentMode, type NetworkProfile, SUPPORTED_NETWORK_IDS, X402FacilitatorConfig, X402PaymentFlow, type X402ProviderOptions, createPaymentProof, createX402PaymentProvider, createX402PaymentProvider as x402 };
|
package/dist/x402.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { chainIdFromCaip2 } from './chunk-
|
|
2
|
-
export { createX402PaymentProvider, createX402PaymentProvider as x402 } from './chunk-
|
|
3
|
-
export { SUPPORTED_NETWORK_IDS } from './chunk-
|
|
4
|
-
import { CommerceError } from './chunk-
|
|
1
|
+
import { chainIdFromCaip2 } from './chunk-RKBGCPCK.js';
|
|
2
|
+
export { createX402PaymentProvider, createX402PaymentProvider as x402 } from './chunk-RKBGCPCK.js';
|
|
3
|
+
export { SUPPORTED_NETWORK_IDS } from './chunk-TWRUNWDR.js';
|
|
4
|
+
import { CommerceError } from './chunk-53WXXIPR.js';
|
|
5
5
|
import { PaymentRequirementsV2Schema } from '@x402/core/schemas';
|
|
6
6
|
import { getAddress, toHex } from 'viem';
|
|
7
7
|
import { privateKeyToAccount } from 'viem/accounts';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devlab.group/agent-commerce",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Open-source, self-hosted, non-custodial commerce and payment orchestration gateway for AI agents.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -118,20 +118,20 @@
|
|
|
118
118
|
},
|
|
119
119
|
"peerDependencies": {
|
|
120
120
|
"@coinbase/x402": "2.1.0",
|
|
121
|
-
"@modelcontextprotocol/
|
|
121
|
+
"@modelcontextprotocol/server": "2.3.0",
|
|
122
122
|
"@sd-jwt/core": "0.20.1",
|
|
123
|
-
"@x402/core": "2.
|
|
124
|
-
"@x402/evm": "2.
|
|
123
|
+
"@x402/core": "2.25.0",
|
|
124
|
+
"@x402/evm": "2.25.0",
|
|
125
125
|
"canonicalize": "5.0.0",
|
|
126
126
|
"jose": "6.2.12",
|
|
127
|
-
"mppx": "0.
|
|
128
|
-
"viem": "2.
|
|
127
|
+
"mppx": "0.13.1",
|
|
128
|
+
"viem": "2.57.1"
|
|
129
129
|
},
|
|
130
130
|
"peerDependenciesMeta": {
|
|
131
131
|
"@coinbase/x402": {
|
|
132
132
|
"optional": true
|
|
133
133
|
},
|
|
134
|
-
"@modelcontextprotocol/
|
|
134
|
+
"@modelcontextprotocol/server": {
|
|
135
135
|
"optional": true
|
|
136
136
|
},
|
|
137
137
|
"@sd-jwt/core": {
|
|
@@ -157,10 +157,12 @@
|
|
|
157
157
|
}
|
|
158
158
|
},
|
|
159
159
|
"devDependencies": {
|
|
160
|
-
"@a2a-js/sdk": "1.
|
|
160
|
+
"@a2a-js/sdk": "1.3.0",
|
|
161
161
|
"@biomejs/biome": "2.5.9",
|
|
162
162
|
"@coinbase/x402": "2.1.0",
|
|
163
|
-
"@modelcontextprotocol/
|
|
163
|
+
"@modelcontextprotocol/client": "2.3.0",
|
|
164
|
+
"@modelcontextprotocol/sdk": "1.32.0",
|
|
165
|
+
"@modelcontextprotocol/server": "2.3.0",
|
|
164
166
|
"@sd-jwt/core": "0.20.1",
|
|
165
167
|
"@types/better-sqlite3": "9.6.0",
|
|
166
168
|
"@types/node": "24.13.3",
|
|
@@ -168,18 +170,19 @@
|
|
|
168
170
|
"@types/react-dom": "19.2.4",
|
|
169
171
|
"@vitejs/plugin-react": "6.0.5",
|
|
170
172
|
"@vitest/coverage-v8": "4.1.11",
|
|
171
|
-
"@x402/core": "2.
|
|
172
|
-
"@x402/evm": "2.
|
|
173
|
+
"@x402/core": "2.25.0",
|
|
174
|
+
"@x402/evm": "2.25.0",
|
|
175
|
+
"@x402/mcp": "2.25.0",
|
|
173
176
|
"canonicalize": "5.0.0",
|
|
174
177
|
"jose": "6.2.12",
|
|
175
|
-
"mppx": "0.
|
|
178
|
+
"mppx": "0.13.1",
|
|
176
179
|
"pino-pretty": "13.1.2",
|
|
177
180
|
"react": "19.0.8",
|
|
178
181
|
"react-dom": "19.0.8",
|
|
179
182
|
"tsup": "8.5.1",
|
|
180
183
|
"tsx": "4.23.12",
|
|
181
184
|
"typescript": "5.9.3",
|
|
182
|
-
"viem": "2.
|
|
185
|
+
"viem": "2.57.1",
|
|
183
186
|
"vite": "8.2.1",
|
|
184
187
|
"vitest": "4.1.11"
|
|
185
188
|
},
|
package/dist/chunk-AFI2CEZS.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
// src/protocols/mcp/constants.ts
|
|
2
|
-
var MCP_TOOL_NAME_CHARS = "A-Za-z0-9._-";
|
|
3
|
-
var MCP_TOOL_NAME_MAX_LENGTH = 128;
|
|
4
|
-
var MCP_TOOL_NAME_PATTERN = new RegExp(
|
|
5
|
-
`^[${MCP_TOOL_NAME_CHARS}]{1,${MCP_TOOL_NAME_MAX_LENGTH}}$`
|
|
6
|
-
);
|
|
7
|
-
|
|
8
|
-
export { MCP_TOOL_NAME_PATTERN };
|
|
9
|
-
//# sourceMappingURL=chunk-AFI2CEZS.js.map
|
|
10
|
-
//# sourceMappingURL=chunk-AFI2CEZS.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/protocols/mcp/constants.ts"],"names":[],"mappings":";AAUO,IAAM,mBAAA,GAAsB,cAAA;AAG5B,IAAM,wBAAA,GAA2B,GAAA;AAQjC,IAAM,wBAAwB,IAAI,MAAA;AAAA,EACvC,CAAA,EAAA,EAAK,mBAAmB,CAAA,IAAA,EAAO,wBAAwB,CAAA,EAAA;AACzD","file":"chunk-AFI2CEZS.js","sourcesContent":["/**\n * MCP protocol constants shared by the config layer, the adapter and the\n * OpenAPI importer.\n *\n * Kept dependency-free: `src/config` validates tool names at load time, so\n * anything imported here would become a config-load dependency too, and the\n * MCP SDK is an optional peer the main entry and CLI must never load.\n */\n\n/** Characters SEP-986 allows in an MCP tool name, as a regex character class body */\nexport const MCP_TOOL_NAME_CHARS = 'A-Za-z0-9._-';\n\n/** Longest MCP tool name SEP-986 allows */\nexport const MCP_TOOL_NAME_MAX_LENGTH = 128;\n\n/**\n * MCP tool names per SEP-986: 1-128 chars of [A-Za-z0-9._-], the SDK's own\n * `TOOL_NAME_REGEX`, which it does not export. Config refuses an mcp-exposed\n * resource whose id fails it; the low-level `Server` checks no names, so the\n * adapter also skips such an id with a warning.\n */\nexport const MCP_TOOL_NAME_PATTERN = new RegExp(\n `^[${MCP_TOOL_NAME_CHARS}]{1,${MCP_TOOL_NAME_MAX_LENGTH}}$`,\n);\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/payments/x402/networks.ts","../src/payments/x402/local-chain/accounts.ts","../src/payments/x402/dev-key-guard.ts","../src/payments/x402/guardrails.ts"],"names":[],"mappings":"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","file":"chunk-CBJIT7QP.js","sourcesContent":["/**\n * The networks this gateway settles on, as data: the chain id to sign against,\n * a display name, and whether real money is involved.\n *\n * A registry rather than \"parse any `eip155:*`\": the chain id parses from any\n * such string, but whether it is a mainnet does not, and the guardrails key off\n * that. An unknown id is refused at startup instead of passing as a testnet.\n *\n * The local dev chain runs under Base Sepolia's `eip155:84532`, so nothing may\n * infer \"public network\" from the id alone. `resolveDeploymentMode` derives\n * the mode from the facilitator too, and the provider's health check confirms\n * that a local facilitator's node is Anvil.\n */\nimport { CommerceError } from '../../core';\n\n/** Chain id of the local dev chain, which Base Sepolia uses too */\nexport const LOCAL_CHAIN_ID = 84532;\n\nexport interface NetworkProfile {\n /** CAIP-2 identifier, e.g. `eip155:84532` */\n readonly id: string;\n /** Signed into the buyer's EIP-712 domain */\n readonly chainId: number;\n readonly displayName: string;\n readonly kind: 'testnet' | 'mainnet';\n /**\n * The USDC deployment this network settles in, with the EIP-712 domain the\n * token reports. Enforced on mainnet only, since a testnet may use a mock\n * token.\n *\n * `name` is the signed EIP-712 domain name, not the symbol, and the two\n * deployments differ: `\"USDC\"` on Base Sepolia, `\"USD Coin\"` on Base. The\n * values were read back from the contracts.\n */\n readonly canonicalAsset?: {\n readonly symbol: string;\n readonly address: string;\n readonly name: string;\n readonly version: string;\n };\n}\n\nconst PROFILES: readonly NetworkProfile[] = [\n {\n id: 'eip155:84532',\n chainId: 84532,\n displayName: 'Base Sepolia',\n kind: 'testnet',\n canonicalAsset: {\n symbol: 'USDC',\n address: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',\n name: 'USDC',\n version: '2',\n },\n },\n {\n id: 'eip155:8453',\n chainId: 8453,\n displayName: 'Base',\n kind: 'mainnet',\n canonicalAsset: {\n symbol: 'USDC',\n address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n name: 'USD Coin',\n version: '2',\n },\n },\n];\n\nconst BY_ID = new Map(PROFILES.map((profile) => [profile.id, profile]));\n\nexport const SUPPORTED_NETWORK_IDS: readonly string[] = PROFILES.map((p) => p.id);\n\nexport function findNetworkProfile(id: string): NetworkProfile | undefined {\n return BY_ID.get(id);\n}\n\nexport function requireNetworkProfile(id: string, path: string): NetworkProfile {\n const profile = BY_ID.get(id);\n if (!profile) {\n throw new CommerceError(\n 'CONFIG_INVALID',\n `${path}: \"${id}\" is not a supported network. Supported CAIP-2 identifiers: ${SUPPORTED_NETWORK_IDS.join(', ')}`,\n { details: { path, network: id } },\n );\n }\n return profile;\n}\n\n/**\n * What a deployment is, as opposed to the network it names. `local` comes from\n * the facilitator: the in-process facilitator makes a deployment local whatever\n * CAIP-2 id it is configured with, which lets diagnostics show `eip155:84532`\n * without claiming public Base Sepolia.\n */\nexport type DeploymentMode = 'local' | 'testnet' | 'mainnet';\n\nexport function resolveDeploymentMode(\n profile: NetworkProfile,\n facilitatorMode: 'local' | 'remote',\n): DeploymentMode {\n if (facilitatorMode === 'local') return 'local';\n return profile.kind;\n}\n\n// The banner an operator must not miss. Printed for mainnet only\nconst LIVE_MAINNET_BANNER = 'LIVE MAINNET MODE - REAL FUNDS';\n\nexport function describeDeploymentMode(mode: DeploymentMode): string {\n return mode === 'mainnet' ? LIVE_MAINNET_BANNER : mode.toUpperCase();\n}\n","/**\n * Anvil's well-known development accounts.\n *\n * LOCAL DEVELOPMENT ONLY - DO NOT FUND. The keys come from Foundry's public\n * default mnemonic (\"test test ... junk\"), so value sent to these addresses on\n * a real network can be taken by anyone.\n *\n * Index layout on the local demo chain:\n * 0 - deployer and local facilitator signer (pays gas, broadcasts settlement)\n * 1 - merchant settlement destination (`payTo`)\n * 2 - buyer (signs EIP-3009 authorizations; never held by the gateway)\n */\nexport interface AnvilWellKnownAccount {\n readonly address: `0x${string}`;\n readonly privateKey: `0x${string}`;\n}\n\n/** A fixed-length tuple, so indexing by the layout above is typed */\nexport const ANVIL_WELL_KNOWN_ACCOUNTS: readonly [\n AnvilWellKnownAccount,\n AnvilWellKnownAccount,\n AnvilWellKnownAccount,\n] = [\n {\n address: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',\n privateKey: '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80',\n },\n {\n address: '0x70997970C51812dc3A010C7d01b50e0d17dc79C8',\n privateKey: '0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d',\n },\n {\n address: '0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC',\n privateKey: '0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a',\n },\n];\n\nexport const LOCAL_FACILITATOR_ACCOUNT = ANVIL_WELL_KNOWN_ACCOUNTS[0];\nexport const LOCAL_MERCHANT_ACCOUNT = ANVIL_WELL_KNOWN_ACCOUNTS[1];\nexport const LOCAL_BUYER_ACCOUNT = ANVIL_WELL_KNOWN_ACCOUNTS[2];\n\n/** Label printed wherever a dev key appears in output, logs or manifests */\nexport const DEV_KEY_LABEL = 'LOCAL DEVELOPMENT ONLY - DO NOT FUND';\n","/**\n * Rejects well-known Anvil keys and payment destinations when the RPC host\n * does not look local or private. Their private keys are published, so anyone\n * can spend what such an address receives on a public chain.\n *\n * The check uses the RPC hostname because the local chain shares Base\n * Sepolia's chain id. Both guards run at provider construction.\n */\nimport { CommerceError } from '../../core';\nimport { ANVIL_WELL_KNOWN_ACCOUNTS } from './local-chain/accounts';\n\nconst WELL_KNOWN_DEV_KEYS: ReadonlySet<string> = new Set(\n ANVIL_WELL_KNOWN_ACCOUNTS.map((a) => a.privateKey.toLowerCase()),\n);\n\nconst WELL_KNOWN_DEV_ADDRESSES: ReadonlySet<string> = new Set(\n ANVIL_WELL_KNOWN_ACCOUNTS.map((a) => a.address.toLowerCase()),\n);\n\n// `0x` plus 64 hex characters, the only shape `privateKeyToAccount` accepts\nconst PRIVATE_KEY_SHAPE = /^0x[0-9a-fA-F]{64}$/;\n\nexport function isWellKnownDevKey(privateKey: string): boolean {\n return WELL_KNOWN_DEV_KEYS.has(privateKey.toLowerCase());\n}\n\nexport function isWellKnownDevAddress(address: string): boolean {\n return WELL_KNOWN_DEV_ADDRESSES.has(address.toLowerCase());\n}\n\n/**\n * True for loopback addresses, RFC 1918 private ranges, and bare (dot-free)\n * hostnames, such as the compose service name \"anvil\".\n *\n * Bare hostnames are treated as local without resolving them. Operators must\n * point them at a private chain.\n */\nexport function isLikelyLocalOrPrivateHost(hostname: string): boolean {\n const h = hostname.toLowerCase().replace(/^\\[|\\]$/g, '');\n if (h === 'localhost' || h === '::1') return true;\n if (/^127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/.test(h)) return true;\n if (/^10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/.test(h)) return true;\n if (/^192\\.168\\.\\d{1,3}\\.\\d{1,3}$/.test(h)) return true;\n if (/^172\\.(1[6-9]|2\\d|3[01])\\.\\d{1,3}\\.\\d{1,3}$/.test(h)) return true;\n if (!h.includes('.') && !h.includes(':')) return true; // bare hostname\n return false;\n}\n\nfunction parseHostnameOrThrow(rpcUrl: string): string {\n try {\n return new URL(rpcUrl).hostname;\n } catch (cause) {\n // Never the URL itself: RPC providers commonly put an API key in the path,\n // and this message reaches startup output and CI logs\n throw new CommerceError('CONFIG_INVALID', 'x402 provider: rpcUrl is not a valid URL', {\n cause,\n });\n }\n}\n\n/** Origin only, for diagnostics: RPC URLs often carry an API key in the path or query */\nexport function describeRpc(rpcUrl: string): string {\n try {\n return new URL(rpcUrl).origin;\n } catch {\n return '[unparseable rpcUrl]';\n }\n}\n\n/**\n * Throws CONFIG_INVALID if `signerPrivateKey` is not shaped like a private key,\n * or if it is a well-known dev key and the RPC is not local.\n *\n * The shape check runs first, so a truncated key is reported as malformed\n * instead of passing as \"not a dev key\".\n */\nexport function assertDevKeyIsLocalOnly(rpcUrl: string, signerPrivateKey: string): void {\n if (!PRIVATE_KEY_SHAPE.test(signerPrivateKey)) {\n throw new CommerceError(\n 'CONFIG_INVALID',\n 'x402 provider: facilitator.signerPrivateKey is not a well-formed private key ' +\n '(expected \"0x\" followed by exactly 64 hex characters).',\n );\n }\n\n if (!isWellKnownDevKey(signerPrivateKey)) return; // the operator's own key\n\n const hostname = parseHostnameOrThrow(rpcUrl);\n\n if (!isLikelyLocalOrPrivateHost(hostname)) {\n throw new CommerceError(\n 'CONFIG_INVALID',\n 'x402 provider: facilitator.signerPrivateKey is a well-known Anvil development key, but rpcUrl ' +\n `${describeRpc(rpcUrl)} does not look like a local/private chain. A public dev key must never sign against ` +\n 'a public network: it is instantly drainable and can grief real settlements via nonce exhaustion. ' +\n 'Use a real facilitator key for any non-local RPC, or point rpcUrl at your local/dev chain.',\n );\n }\n}\n\n/**\n * Throws CONFIG_INVALID if `payTo` is a well-known Anvil address and `rpcUrl`\n * does not look local or private.\n *\n * Guards the receiving side, in every facilitator mode. `agent-commerce init`\n * defaults `payTo` to a well-known address for the local demo, and on a real\n * network that default sends every payment where anyone can sweep it.\n */\nexport function assertPayToIsNotDevAddress(rpcUrl: string, payTo: string): void {\n if (!isWellKnownDevAddress(payTo)) return;\n\n const hostname = parseHostnameOrThrow(rpcUrl);\n\n if (!isLikelyLocalOrPrivateHost(hostname)) {\n throw new CommerceError(\n 'CONFIG_INVALID',\n `x402 provider: \"payTo\" (${payTo}) is a well-known Anvil development address, but rpcUrl ` +\n `${describeRpc(rpcUrl)} does not look like a local/private chain. The private key behind that address ` +\n 'is public knowledge, so any revenue settled to it is immediately spendable by anyone. Set ' +\n '\"payTo\" to your own merchant wallet for any non-local RPC, or point rpcUrl at your ' +\n 'local/dev chain.',\n );\n }\n}\n","/**\n * What must hold before this gateway may settle a payment on the configured\n * network. Two callers share these checks: the provider runs them at\n * construction, so a library consumer who skips our config loader still gets\n * them, and the config loader runs them, so `validate` and `doctor` report\n * them too.\n *\n * Both run before any request, because a failure found in `settle()` would\n * come after the pipeline reserved the buyer's replay key.\n *\n * Imports no peer (no viem, no `@x402/*`), so the CLI can load it.\n */\nimport { CommerceError } from '../../core';\nimport { isLikelyLocalOrPrivateHost, isWellKnownDevAddress } from './dev-key-guard';\nimport {\n type DeploymentMode,\n type NetworkProfile,\n requireNetworkProfile,\n resolveDeploymentMode,\n} from './networks';\n\n/**\n * How the gateway authenticates to a remote facilitator.\n *\n * - `none`: send no credential; use it when the facilitator accepts\n * anonymous requests.\n * - `bearer`: send a static token; no extra peer package is needed.\n * - `cdp`: Coinbase Developer Platform. The optional peer `@coinbase/x402`,\n * imported only for this type, signs a fresh JWT per request.\n *\n * Any other auth type is refused at config load.\n */\nexport type FacilitatorAuth =\n | { readonly type: 'none' }\n | { readonly type: 'bearer'; readonly token: string }\n | { readonly type: 'cdp'; readonly apiKeyId: string; readonly apiKeySecret: string };\n\nexport type X402FacilitatorConfig =\n | { readonly mode: 'local'; readonly signerPrivateKey: string }\n | { readonly mode: 'remote'; readonly url: string; readonly auth: FacilitatorAuth };\n\nexport interface X402DeploymentInput {\n readonly network: string;\n readonly payTo: string;\n readonly asset: string;\n /** EIP-712 domain of the asset, as the token itself reports it */\n readonly assetName?: string;\n readonly assetVersion?: string;\n readonly facilitator: X402FacilitatorConfig;\n /** Must be `true` before anything settles on a mainnet */\n readonly allowMainnet?: boolean;\n /**\n * Must be `true` on mainnet when facilitator auth is `none`. A separate\n * decision from `allowMainnet`: it accepts settling without an account at\n * the facilitator, under its anonymous-access limits.\n */\n readonly allowUnauthenticatedFacilitator?: boolean;\n /** Error-path prefix, `payments.x402` by default */\n readonly configPath?: string;\n /** Settlement-recipient field named in errors, `payTo` by default */\n readonly payToField?: string;\n}\n\nexport interface X402Deployment {\n readonly profile: NetworkProfile;\n readonly mode: DeploymentMode;\n}\n\nfunction invalid(message: string, path: string): CommerceError {\n return new CommerceError('CONFIG_INVALID', message, { details: { path } });\n}\n\n/**\n * Resolves the deployment and refuses the combinations that could move real\n * money by accident. The network must resolve first; the other checks are\n * independent.\n */\nexport function resolveX402Deployment(input: X402DeploymentInput): X402Deployment {\n const at = input.configPath ?? 'payments.x402';\n const payTo = input.payToField ?? 'payTo';\n const profile = requireNetworkProfile(input.network, `${at}.network`);\n const mode = resolveDeploymentMode(profile, input.facilitator.mode);\n\n // Local mode keeps a gas-paying key in the gateway process. A compromise\n // could expose that key, so mainnet requires a remote facilitator.\n if (profile.kind === 'mainnet' && input.facilitator.mode === 'local') {\n throw invalid(\n `${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.`,\n `${at}.facilitator.mode`,\n );\n }\n\n if (mode === 'mainnet' && input.allowMainnet !== true) {\n throw invalid(\n `${at}: network \"${profile.id}\" (${profile.displayName}) settles real funds. Set ${at}.allowMainnet: true to acknowledge this explicitly - it is never the default.`,\n `${at}.allowMainnet`,\n );\n }\n\n if (input.facilitator.mode === 'remote') {\n assertFacilitatorUrlIsSafe(input.facilitator.url, mode, at);\n // The authorization fixes recipient, amount and chain, so a facilitator\n // cannot redirect funds. A credential adds an account: rate limits, terms\n // and support. On mainnet, going without one is an explicit choice.\n if (\n mode === 'mainnet' &&\n input.facilitator.auth.type === 'none' &&\n input.allowUnauthenticatedFacilitator !== true\n ) {\n throw invalid(\n `${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.`,\n `${at}.allowUnauthenticatedFacilitator`,\n );\n }\n // A blank credential reaches the facilitator as \"unauthenticated\" and fails\n // every payment after the buyer signed. `${VAR:- }` resolving to whitespace\n // is the usual cause.\n for (const [field, value] of credentialFields(input.facilitator.auth)) {\n if (value.trim() === '') {\n throw invalid(\n `${at}: facilitator.auth.type is \"${input.facilitator.auth.type}\" but ${field} is empty. An empty credential is refused rather than sent.`,\n `${at}.facilitator.auth.${field}`,\n );\n }\n }\n }\n\n // The config loader's address check refuses this too; repeated here for a\n // library consumer who calls `createX402PaymentProvider` without it\n if (/^0x0{40}$/i.test(input.payTo)) {\n throw invalid(\n `${at}: \"${payTo}\" is the zero address. Every payment settled there is destroyed.`,\n `${at}.${payTo}`,\n );\n }\n\n // Anyone can spend from a well-known Anvil address. `dev-key-guard` refuses\n // one behind a public RPC; this refuses one on any non-local deployment,\n // whose RPC host says nothing about where a remote facilitator settles.\n if (mode !== 'local' && isWellKnownDevAddress(input.payTo)) {\n throw invalid(\n `${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.`,\n `${at}.${payTo}`,\n );\n }\n\n // Mainnet only: a testnet is where pointing at a mock token is normal\n const canonical = profile.canonicalAsset;\n if (mode === 'mainnet' && canonical) {\n if (!sameAddress(input.asset, canonical.address)) {\n throw invalid(\n `${at}: asset ${input.asset} is not ${canonical.symbol} on ${profile.displayName} (expected ${canonical.address}). Settling a mainnet payment in an unintended token is refused.`,\n `${at}.asset`,\n );\n }\n // The buyer signs the EIP-712 domain and the scheme checks it. A wrong one\n // refuses every payment with `invalid_exact_evm_token_name_mismatch` after\n // the buyer signed, so it is caught here, before the gateway starts.\n if (input.assetName !== undefined && input.assetName !== canonical.name) {\n throw invalid(\n `${at}: assetName \"${input.assetName}\" is not the EIP-712 domain name ${canonical.symbol} reports on ${profile.displayName} (expected \"${canonical.name}\"). Every payment would be refused after the buyer signed.`,\n `${at}.assetName`,\n );\n }\n if (input.assetVersion !== undefined && input.assetVersion !== canonical.version) {\n throw invalid(\n `${at}: assetVersion \"${input.assetVersion}\" is not the EIP-712 domain version ${canonical.symbol} reports on ${profile.displayName} (expected \"${canonical.version}\").`,\n `${at}.assetVersion`,\n );\n }\n }\n\n return { profile, mode };\n}\n\n/**\n * A facilitator sees every payment authorization this gateway handles. Plain\n * HTTP puts those on the wire in the clear and lets anyone in the path rewrite\n * a settlement result, so it is allowed only to a local or private host, and\n * never on a mainnet.\n */\nfunction assertFacilitatorUrlIsSafe(url: string, mode: DeploymentMode, at: string): void {\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch (cause) {\n throw new CommerceError('CONFIG_INVALID', `${at}: facilitator.url is not a valid URL`, {\n cause,\n details: { path: `${at}.facilitator.url` },\n });\n }\n\n if (parsed.protocol === 'https:') return;\n if (parsed.protocol !== 'http:') {\n throw invalid(\n `${at}: facilitator ${describeOrigin(url)} must be reached over https (or http on a local/private host); got \"${parsed.protocol}//\"`,\n `${at}.facilitator.url`,\n );\n }\n if (mode !== 'mainnet' && isLikelyLocalOrPrivateHost(parsed.hostname)) return;\n\n // The origin, never the whole URL: the path can carry a tenant or an API\n // key, and this message reaches `validate`, `doctor`, startup output and CI logs\n throw invalid(\n `${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.`,\n `${at}.facilitator.url`,\n );\n}\n\n// Origin only: a facilitator URL can carry a tenant path or an API key\nfunction describeOrigin(url: string): string {\n try {\n return new URL(url).origin;\n } catch {\n return '[unparseable facilitator.url]';\n }\n}\n\n// The secret-bearing fields of an auth block, for emptiness checks only. Never logged\nfunction credentialFields(auth: FacilitatorAuth): readonly (readonly [string, string])[] {\n switch (auth.type) {\n case 'bearer':\n return [['token', auth.token]];\n case 'cdp':\n return [\n ['apiKeyId', auth.apiKeyId],\n ['apiKeySecret', auth.apiKeySecret],\n ];\n default:\n return [];\n }\n}\n\nfunction sameAddress(a: string, b: string): boolean {\n return a.toLowerCase() === b.toLowerCase();\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/payments/x402/amount.ts","../src/payments/x402/chain.ts","../src/payments/x402/facilitator.ts","../src/payments/x402/payload.ts","../src/payments/x402/replay-key.ts","../src/payments/x402/provider.ts"],"names":[],"mappings":"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","file":"chunk-JKEKKXRJ.js","sourcesContent":["/**\n * Exact conversion from display amounts (\"0.01\" USDC) to the integer base\n * units x402 and EIP-3009 carry (\"10000\" at 6 decimals).\n *\n * It never goes through a JS `number`, which cannot represent most decimal\n * fractions. viem's `parseUnits` is not used either: it silently rounds excess\n * fractional digits, and \"0.0000001\" against a 6-decimal asset is a\n * configuration bug that must be refused, not rounded. The reverse direction\n * is viem's `formatUnits`, which is exact.\n */\nimport { CommerceError } from '../../core';\n\nconst DECIMAL_STRING_PATTERN = /^\\d+(?:\\.\\d+)?$/;\n\n/**\n * Parses a canonical decimal display amount (e.g. \"0.01\") into base units\n * for an asset with the given number of decimals, without floating point.\n *\n * Throws `CommerceError('PAYMENT_INVALID')` if the string is not a plain\n * non-negative decimal, or if it carries more fractional digits than the\n * asset supports.\n */\nexport function parseCanonicalAmount(amount: string, decimals: number): bigint {\n if (!Number.isInteger(decimals) || decimals < 0) {\n throw new CommerceError('INTERNAL_ERROR', `Invalid asset decimals: ${decimals}`);\n }\n if (!DECIMAL_STRING_PATTERN.test(amount)) {\n throw new CommerceError(\n 'PAYMENT_INVALID',\n `Amount \"${amount}\" is not a valid non-negative decimal string`,\n {\n details: { amount },\n },\n );\n }\n\n const [integerPart = '0', fractionPart = ''] = amount.split('.');\n\n if (fractionPart.length > decimals) {\n throw new CommerceError(\n 'PAYMENT_INVALID',\n `Amount \"${amount}\" has more precision than the asset supports (${decimals} decimals)`,\n { details: { amount, assetDecimals: decimals } },\n );\n }\n\n const paddedFraction = fractionPart.padEnd(decimals, '0');\n const combined = `${integerPart}${paddedFraction}`;\n return BigInt(combined);\n}\n","/**\n * viem clients for the x402 provider, built on the configured `rpcUrl`. The\n * SDK uses the client it is handed, so the provider's chain calls reach no\n * other RPC.\n *\n * Despite the `Local` names, `createLocalFacilitatorClient` sits on the\n * settlement path and `createLocalPublicClient` backs `health()`. The health\n * client is built for whichever network is configured. The facilitator client\n * always uses chain id 84532: an in-process facilitator is refused on a\n * mainnet, and Base Sepolia is the registry's only testnet. Registering a\n * second testnet means building this client for the configured chain.\n */\nimport {\n type Account,\n type Chain,\n type Client,\n createPublicClient,\n createWalletClient,\n http,\n type PublicActions,\n type PublicClient,\n publicActions,\n type Transport,\n type WalletActions,\n} from 'viem';\nimport { privateKeyToAccount } from 'viem/accounts';\nimport { LOCAL_CHAIN_ID } from './networks';\n\n/** A wallet client that can also read chain state, matching x402's `SignerWallet` */\nexport type LocalFacilitatorClient = Client<\n Transport,\n Chain,\n Account,\n undefined,\n PublicActions<Transport, Chain, Account> & WalletActions<Chain, Account>\n>;\n\n/** CAIP-2 identifier the local dev chain is advertised under */\nexport const LOCAL_NETWORK = `eip155:${LOCAL_CHAIN_ID}`;\n\n/**\n * Chain id carried by a CAIP-2 `eip155` network identifier, or `undefined` for\n * anything else. A caller must never fall back to a default chain id, because\n * the chain id is part of the EIP-712 domain the buyer signed.\n */\nexport function chainIdFromCaip2(network: string): number | undefined {\n const match = /^eip155:(\\d+)$/.exec(network);\n if (!match?.[1]) return undefined;\n const chainId = Number(match[1]);\n return Number.isSafeInteger(chainId) && chainId > 0 ? chainId : undefined;\n}\n\n/**\n * `chainId` defaults to the local dev chain, the only chain the facilitator\n * client is built for. The health client passes the configured network's id.\n */\nfunction buildLocalChain(rpcUrl: string, chainId: number = LOCAL_CHAIN_ID): Chain {\n return {\n id: chainId,\n name: 'agent-commerce-local',\n nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },\n rpcUrls: {\n default: { http: [rpcUrl] },\n },\n } satisfies Chain;\n}\n\n/**\n * A read-only viem `PublicClient`.\n *\n * `timeoutMs` goes to viem's `http()` transport, which aborts the underlying\n * `fetch` when it expires rather than only abandoning the wait. Omit it to keep\n * viem's default of 10s.\n */\nexport function createLocalPublicClient(\n rpcUrl: string,\n timeoutMs?: number,\n chainId?: number,\n): PublicClient {\n return createPublicClient({\n chain: buildLocalChain(rpcUrl, chainId),\n transport: http(rpcUrl, timeoutMs !== undefined ? { timeout: timeoutMs } : undefined),\n });\n}\n\n/**\n * A viem `WalletClient` extended with public actions, for the local\n * facilitator signer only: the SDK's settlement both writes and reads through\n * it.\n *\n * LOCAL DEVELOPMENT ONLY. The key behind it pays gas on the dev chain. It is\n * usually an Anvil well-known key, and must never be a merchant, buyer or\n * production key.\n */\nexport function createLocalFacilitatorClient(\n rpcUrl: string,\n signerPrivateKey: `0x${string}`,\n): LocalFacilitatorClient {\n const chain = buildLocalChain(rpcUrl);\n const account = privateKeyToAccount(signerPrivateKey);\n return createWalletClient({\n account,\n chain,\n transport: http(rpcUrl),\n }).extend(publicActions);\n}\n","/**\n * The facilitator verifies an authorization and broadcasts the transfer. Two\n * kinds sit behind one interface, both driving the SDK's own code:\n *\n * local the SDK's in-process `x402Facilitator`, signing against a dev node\n * remote the SDK's HTTP facilitator client, with or without a credential\n *\n * Each verify or settle call opens its own session so that `transportFailed()`\n * covers one request only: concurrent payments must not see each other's\n * transport failures.\n */\nimport { x402Facilitator } from '@x402/core/facilitator';\nimport { HTTPFacilitatorClient } from '@x402/core/http';\nimport {\n type Network,\n type PaymentPayload,\n type PaymentRequirements,\n type SettleResponse,\n VerifyError,\n type VerifyResponse,\n} from '@x402/core/types';\nimport { toFacilitatorEvmSigner } from '@x402/evm';\nimport { registerExactEvmScheme } from '@x402/evm/exact/facilitator';\nimport { CommerceError } from '../../core';\nimport type { LocalFacilitatorClient } from './chain';\nimport type { FacilitatorAuth } from './guardrails';\n\n/** One verify or one settle, with its own transport-failure flag */\nexport interface FacilitatorSession {\n verify(payload: PaymentPayload, requirements: PaymentRequirements): Promise<VerifyResponse>;\n settle(payload: PaymentPayload, requirements: PaymentRequirements): Promise<SettleResponse>;\n /**\n * True when the call produced no verdict: the local binding sets it when an\n * RPC call to the chain fails in transport, the remote binding on every\n * throw other than a 400 refusal.\n *\n * The SDK's `exact`/EVM scheme reports its own RPC errors as ordinary\n * verification failures: an unreachable node comes back as\n * `invalid_exact_evm_signature`. Without this flag the buyer would be told\n * their signature is bad for a payment nothing checked.\n */\n transportFailed(): boolean;\n}\n\nexport interface SupportedKind {\n readonly x402Version: number;\n readonly scheme: string;\n readonly network: string;\n}\n\ninterface BindingBase {\n /** Human-readable, never a credential */\n readonly describe: string;\n open(): FacilitatorSession;\n}\n\nexport type FacilitatorBinding =\n | (BindingBase & { readonly kind: 'local' })\n | (BindingBase & {\n readonly kind: 'remote';\n /** What the facilitator says it can settle. Used by health(), not by the payment path */\n supported(): Promise<readonly SupportedKind[]>;\n });\n\n// Bounds each receipt wait of the in-process facilitator, and each request to a\n// remote one\nconst SETTLEMENT_CONFIRMATION_TIMEOUT_MS = 60_000;\n\n/**\n * An in-process `x402Facilitator` with the `exact`/EVM scheme registered for\n * one network rather than an `eip155:*` wildcard, so a payload naming another\n * chain finds no scheme at all\n */\nexport function createLocalFacilitatorBinding(\n client: LocalFacilitatorClient,\n network: string,\n isTransportError: (err: unknown) => boolean,\n): FacilitatorBinding {\n const build = (): { facilitator: x402Facilitator; failed: () => boolean } => {\n let failed = false;\n const watch = <T>(promise: Promise<T>): Promise<T> =>\n promise.catch((err: unknown) => {\n if (isTransportError(err)) failed = true;\n throw err;\n });\n\n // Exactly the `FacilitatorEvmSigner` surface, so every call the SDK makes is\n // watched. `toFacilitatorEvmSigner` wants a flat `address`, which viem\n // keeps on `client.account`.\n const signer = {\n address: client.account.address,\n readContract: (args: Parameters<LocalFacilitatorClient['readContract']>[0]) =>\n watch(client.readContract(args)),\n verifyTypedData: (args: Parameters<LocalFacilitatorClient['verifyTypedData']>[0]) =>\n watch(client.verifyTypedData(args)),\n writeContract: (args: Parameters<LocalFacilitatorClient['writeContract']>[0]) =>\n watch(client.writeContract(args)),\n sendTransaction: (args: Parameters<LocalFacilitatorClient['sendTransaction']>[0]) =>\n watch(client.sendTransaction(args)),\n waitForTransactionReceipt: (\n args: Parameters<LocalFacilitatorClient['waitForTransactionReceipt']>[0],\n ) => watch(client.waitForTransactionReceipt(args)),\n getCode: (args: Parameters<LocalFacilitatorClient['getCode']>[0]) =>\n watch(client.getCode(args)),\n } as unknown as Parameters<typeof toFacilitatorEvmSigner>[0];\n\n // `confirmationTimeoutMs` turns a lost receipt wait into `settlement_pending`\n // with the broadcast hash, instead of a discarded broadcast\n const facilitator = registerExactEvmScheme(new x402Facilitator(), {\n signer: toFacilitatorEvmSigner(signer, {\n confirmationTimeoutMs: SETTLEMENT_CONFIRMATION_TIMEOUT_MS,\n }),\n networks: network as Network,\n });\n\n return { facilitator, failed: () => failed };\n };\n\n return {\n kind: 'local',\n describe: 'local (in-process)',\n open(): FacilitatorSession {\n const { facilitator, failed } = build();\n return {\n verify: (payload, requirements) => facilitator.verify(payload, requirements),\n settle: (payload, requirements) => facilitator.settle(payload, requirements),\n transportFailed: failed,\n };\n },\n };\n}\n\nexport interface RemoteFacilitatorOptions {\n readonly url: string;\n readonly auth: FacilitatorAuth;\n}\n\n// The SDK's path-keyed auth-header shape. A flat object throws inside it\ntype AuthHeaderFactory = () => Promise<Record<string, Record<string, string>>>;\n\n/**\n * CDP needs a fresh JWT per request over method, host and path, which a static\n * header cannot express. The optional peer `@coinbase/x402` does the signing.\n * It is imported dynamically, so only `auth.type: cdp` pulls in the CDP SDK and\n * its Solana, axios and JOSE dependencies.\n *\n * The import starts at construction, so a missing peer fails the health check\n * before any payment needs it. A payment that arrives first fails as\n * `PAYMENT_PROVIDER_UNAVAILABLE`, never as a rejection blamed on the buyer.\n */\nfunction cdpAuthHeaders(apiKeyId: string, apiKeySecret: string): AuthHeaderFactory {\n const loading = import('@coinbase/x402').then(\n (mod) => mod.createCdpAuthHeaders(apiKeyId, apiKeySecret),\n (cause: unknown) => {\n throw new CommerceError(\n 'CONFIG_INVALID',\n 'x402 provider: facilitator.auth.type is \"cdp\", which needs the optional peer ' +\n '\"@coinbase/x402\". Install it (npm install @coinbase/x402), or use a facilitator ' +\n 'that accepts a static token with auth.type \"bearer\".',\n { cause },\n );\n },\n );\n // Nothing awaits this before the first call, so without a handler a failed\n // import would be an unhandled rejection at startup\n loading.catch(() => {});\n\n return async () => {\n const create = await loading;\n if (!create) {\n throw new CommerceError(\n 'PAYMENT_PROVIDER_UNAVAILABLE',\n 'x402 provider: @coinbase/x402 returned no auth-header factory',\n );\n }\n return (await create()) as Record<string, Record<string, string>>;\n };\n}\n\n/**\n * A 400 from `/verify` whose body names an `invalidReason` is the facilitator\n * refusing the payment, so it returns as an invalid verdict. The SDK throws it\n * as a `VerifyError`, which keeps the status and reason but not `isValid`.\n * A 400 without a reason and every other status, 401, 403, 429 and 5xx\n * included, are rethrown as \"no verdict\".\n */\nfunction verdictFromVerifyError(err: unknown): VerifyResponse {\n if (\n err instanceof VerifyError &&\n err.statusCode === 400 &&\n typeof err.invalidReason === 'string'\n ) {\n return {\n isValid: false,\n invalidReason: err.invalidReason,\n ...(err.payer !== undefined ? { payer: err.payer } : {}),\n };\n }\n throw err;\n}\n\n/**\n * An HTTP facilitator. The SDK client produces the auth headers per request;\n * this module never logs them, and they appear neither in `/.well-known` nor\n * in `describe`.\n */\nexport function createRemoteFacilitatorBinding(\n options: RemoteFacilitatorOptions,\n): FacilitatorBinding {\n const auth = options.auth;\n let createAuthHeaders: AuthHeaderFactory | undefined;\n if (auth.type === 'bearer') {\n createAuthHeaders = async () => {\n // Path-keyed, as the SDK requires (see `AuthHeaderFactory`)\n const headers = { Authorization: `Bearer ${auth.token}` };\n return { verify: headers, settle: headers, supported: headers };\n };\n } else if (auth.type === 'cdp') {\n createAuthHeaders = cdpAuthHeaders(auth.apiKeyId, auth.apiKeySecret);\n }\n\n const client = new HTTPFacilitatorClient({\n url: options.url,\n timeoutMs: SETTLEMENT_CONFIRMATION_TIMEOUT_MS,\n ...(createAuthHeaders ? { createAuthHeaders } : {}),\n });\n\n return {\n kind: 'remote',\n describe: `remote ${new URL(options.url).origin} (auth=${auth.type})`,\n open(): FacilitatorSession {\n let failed = false;\n const watch = async <T>(call: () => Promise<T>): Promise<T> => {\n try {\n return await call();\n } catch (err) {\n // A throw here means no verdict (`verdictFromVerifyError` has already\n // turned a 400 refusal into one): the client could not reach or\n // authenticate to the facilitator, got another non-2xx, or could not\n // parse the body. None of that may be recorded against the payer.\n // Every throw counts, whatever its type: the SDK can report a 401 as a\n // bare `Error`, so no type singles out a credential failure. For\n // settle(), the facilitator may have settled after we stopped waiting,\n // so the outcome stays unknown.\n failed = true;\n throw err;\n }\n };\n return {\n verify: (payload, requirements) =>\n watch(() => client.verify(payload, requirements).catch(verdictFromVerifyError)),\n settle: (payload, requirements) => watch(() => client.settle(payload, requirements)),\n transportFailed: () => failed,\n };\n },\n async supported(): Promise<readonly SupportedKind[]> {\n const response = await client.getSupported();\n return response.kinds as readonly SupportedKind[];\n },\n };\n}\n","/**\n * Decodes and validates the base64 `PAYMENT-SIGNATURE` submission.\n *\n * A malformed payload must become a `rejected` verification, never a thrown\n * request, so this returns `undefined` on any failure. That is why it parses\n * the schema itself instead of calling the SDK's `decodePaymentSignatureHeader`,\n * which throws.\n */\nimport { PaymentPayloadV2Schema } from '@x402/core/schemas';\nimport type { PaymentPayload } from '@x402/core/types';\nimport { type ExactEIP3009Payload, isEIP3009Payload } from '@x402/evm';\n\nexport function decodePaymentSubmission(payloadBase64: string): PaymentPayload | undefined {\n let json: unknown;\n try {\n const decoded = Buffer.from(payloadBase64, 'base64').toString('utf8');\n json = JSON.parse(decoded);\n } catch {\n return undefined;\n }\n\n const result = PaymentPayloadV2Schema.safeParse(json);\n return result.success ? (result.data as PaymentPayload) : undefined;\n}\n\n/**\n * Narrows a decoded payload to the EIP-3009 `exact`/EVM shape this provider\n * settles.\n *\n * The `exact` scheme on EVM also has a Permit2 method. The challenge names\n * EIP-3009 (`extra.assetTransferMethod`), and a Permit2 payload is rejected\n * here rather than handed to the SDK. On the local chain, which has no Permit2\n * proxy, it would fail as an opaque settlement revert.\n */\nexport function isExactEvmPayload(\n payload: PaymentPayload,\n): payload is PaymentPayload & { payload: ExactEIP3009Payload } {\n return (\n payload.accepted.scheme === 'exact' &&\n typeof payload.payload === 'object' &&\n payload.payload !== null &&\n isEIP3009Payload(payload.payload as ExactEIP3009Payload) &&\n typeof (payload.payload as ExactEIP3009Payload).signature === 'string'\n );\n}\n","/**\n * `PaymentResult.replayKey` is derived from the payment authorization alone\n * (chain id, asset, payer, nonce), never from the request id, so the same\n * authorization replayed on another request collides in the receipt store's\n * reservation. The MPP provider uses the same derivation.\n */\nimport { encodeAbiParameters, keccak256 } from 'viem';\n\nexport interface ReplayKeyInput {\n readonly chainId: number;\n readonly asset: `0x${string}`;\n readonly from: `0x${string}`;\n readonly nonce: `0x${string}`;\n}\n\nexport function computeReplayKey(input: ReplayKeyInput): string {\n const encoded = encodeAbiParameters(\n [{ type: 'uint256' }, { type: 'address' }, { type: 'address' }, { type: 'bytes32' }],\n [BigInt(input.chainId), input.asset, input.from, input.nonce],\n );\n return keccak256(encoded);\n}\n","/**\n * x402 payment provider: protocol v2, `exact` scheme, EVM, EIP-3009\n * `transferWithAuthorization`.\n *\n * `verify()` never moves funds. `settle()` does, and throws unless it is handed\n * a successful verification. Both run through a facilitator (see\n * `facilitator.ts`): the SDK's own `x402Facilitator` in this process, or a\n * remote HTTP facilitator.\n */\n\nimport type {\n Network,\n PaymentRequired,\n PaymentRequirements,\n SettleResponse,\n VerifyResponse,\n} from '@x402/core/types';\nimport {\n BaseError,\n ContractFunctionRevertedError,\n formatUnits,\n getAddress,\n HttpRequestError,\n isAddress,\n TimeoutError,\n WaitForTransactionReceiptTimeoutError,\n} from 'viem';\nimport {\n type AdapterDescriptor,\n type AdapterHealth,\n type Clock,\n CommerceError,\n type IdGenerator,\n type Logger,\n NOOP_LOGGER,\n type PaymentContext,\n type PaymentProvider,\n type PaymentRequirement,\n type PaymentResult,\n type PaymentSettlementContext,\n type PaymentVerificationContext,\n systemClock,\n} from '../../core';\nimport { redactedErrorText } from '../../core/errors';\nimport { PACKAGE_VERSION } from '../../version';\nimport { parseCanonicalAmount } from './amount';\nimport {\n createLocalFacilitatorClient,\n createLocalPublicClient,\n type LocalFacilitatorClient,\n} from './chain';\nimport { assertDevKeyIsLocalOnly, assertPayToIsNotDevAddress, describeRpc } from './dev-key-guard';\nimport {\n createLocalFacilitatorBinding,\n createRemoteFacilitatorBinding,\n type FacilitatorBinding,\n} from './facilitator';\nimport { resolveX402Deployment, type X402FacilitatorConfig } from './guardrails';\nimport { describeDeploymentMode } from './networks';\nimport { decodePaymentSubmission, isExactEvmPayload } from './payload';\nimport { computeReplayKey } from './replay-key';\n\nconst X402_VERSION = 2;\nconst X402_PROTOCOL_VERSION = String(X402_VERSION);\nconst DEFAULT_MAX_TIMEOUT_SECONDS = 60;\nconst DEFAULT_MIME_TYPE = 'application/json';\nconst HEALTH_TIMEOUT_MS = 4_000;\n// `SettleResponse.errorReason` the SDK uses for \"broadcast, not confirmed\"\nconst SETTLEMENT_PENDING_REASON = 'settlement_pending';\n/**\n * The SDK's catch-all for a throw from the broadcast call, and its reason for\n * a mined transaction that reverted. Only the second carries a hash. A revert\n * the SDK recognizes during gas estimation gets its own reason instead.\n */\nconst TRANSACTION_FAILED_REASON = 'invalid_exact_evm_transaction_failed';\n/**\n * `invalidReason`/`errorReason` are `z.string()` in the SDK schema, with no\n * length or charset bound. They reach the buyer's error, the persisted events\n * and the merchant's ledger. A remote facilitator controls these values, so\n * they are treated as untrusted input rather than diagnostic text.\n */\nconst MAX_REASON_LENGTH = 64;\nconst REASON_SHAPE = /^[a-z0-9_.-]+$/i;\n\nfunction sanitizeReason(reason: string | undefined, fallback: string): string {\n if (reason === undefined) return fallback;\n const trimmed = reason.trim();\n if (trimmed.length === 0 || trimmed.length > MAX_REASON_LENGTH) return fallback;\n return REASON_SHAPE.test(trimmed) ? trimmed : fallback;\n}\n\nexport interface X402ProviderOptions {\n /**\n * CAIP-2 network identifier, e.g. `eip155:84532`. The chain id it carries is\n * part of the EIP-712 domain the buyer signs, so it is read from this value\n * rather than defaulted.\n */\n readonly network: string;\n /** RPC endpoint. Local chain: http://127.0.0.1:8545 */\n readonly rpcUrl: string;\n /** ERC-20 (EIP-3009) asset address used for settlement */\n readonly asset: `0x${string}`;\n /** EIP-712 domain name of the asset, e.g. 'MockUSDC' */\n readonly assetName: string;\n /** EIP-712 domain version of the asset, e.g. '2' */\n readonly assetVersion: string;\n readonly assetDecimals: number;\n /** Merchant-controlled settlement destination. Never a gateway-owned wallet */\n readonly payTo: `0x${string}`;\n readonly maxTimeoutSeconds?: number;\n /**\n * Which facilitator verifies and broadcasts. `local` runs one in this process\n * against a dev chain, and its `signerPrivateKey` pays gas there, usually\n * an Anvil well-known key (LOCAL DEVELOPMENT ONLY - DO NOT FUND). `remote`\n * calls an HTTP facilitator, and the gateway then holds no signing key.\n */\n readonly facilitator: X402FacilitatorConfig;\n /** Must be `true` before anything settles on a mainnet. Never a default */\n readonly allowMainnet?: boolean;\n /** Required on mainnet when facilitator auth is `none` */\n readonly allowUnauthenticatedFacilitator?: boolean;\n readonly logger?: Logger;\n readonly clock?: Clock;\n readonly ids?: IdGenerator;\n}\n\n/** Prefixed random UUIDs, shared with the MPP rail */\nexport const DEFAULT_IDS: IdGenerator = {\n next: (prefix?: string) => `${prefix ? `${prefix}_` : ''}${crypto.randomUUID()}`,\n};\n\nexport function createX402PaymentProvider(options: X402ProviderOptions): PaymentProvider {\n if (!isAddress(options.asset)) {\n throw new CommerceError(\n 'CONFIG_INVALID',\n `x402 provider: \"asset\" is not a valid EVM address: ${options.asset}`,\n );\n }\n if (!isAddress(options.payTo)) {\n throw new CommerceError(\n 'CONFIG_INVALID',\n `x402 provider: \"payTo\" is not a valid EVM address: ${options.payTo}`,\n );\n }\n // In every facilitator mode. `resolveX402Deployment` below also refuses a dev\n // payTo on any non-local deployment, whatever the RPC host.\n assertPayToIsNotDevAddress(options.rpcUrl, options.payTo);\n if (!Number.isInteger(options.assetDecimals) || options.assetDecimals < 0) {\n throw new CommerceError(\n 'CONFIG_INVALID',\n `x402 provider: \"assetDecimals\" must be a non-negative integer`,\n );\n }\n // The chain id is signed into the buyer's EIP-712 domain, so a network it\n // cannot be resolved from fails here, never at request time\n const { profile, mode } = resolveX402Deployment({\n network: options.network,\n payTo: options.payTo,\n asset: options.asset,\n assetName: options.assetName,\n assetVersion: options.assetVersion,\n facilitator: options.facilitator,\n ...(options.allowMainnet !== undefined ? { allowMainnet: options.allowMainnet } : {}),\n ...(options.allowUnauthenticatedFacilitator !== undefined\n ? { allowUnauthenticatedFacilitator: options.allowUnauthenticatedFacilitator }\n : {}),\n });\n const network = options.network as Network;\n // Built once, here, rather than in settle(): an unusable key fails the\n // provider at startup, not on the first paid request after that buyer's\n // replay key is already reserved\n let binding: FacilitatorBinding;\n if (options.facilitator.mode === 'local') {\n assertDevKeyIsLocalOnly(options.rpcUrl, options.facilitator.signerPrivateKey);\n let client: LocalFacilitatorClient;\n try {\n client = createLocalFacilitatorClient(\n options.rpcUrl,\n options.facilitator.signerPrivateKey as `0x${string}`,\n );\n } catch (cause) {\n throw new CommerceError(\n 'CONFIG_INVALID',\n 'x402 provider: could not construct a local facilitator signer from ' +\n 'facilitator.signerPrivateKey. It must be a valid 32-byte hex private key.',\n { cause },\n );\n }\n binding = createLocalFacilitatorBinding(client, network, isProviderUnavailableError);\n } else {\n binding = createRemoteFacilitatorBinding({\n url: options.facilitator.url,\n auth: options.facilitator.auth,\n });\n }\n\n // health() reads the chain through its own client, whose timeout aborts the\n // request. Verification and settlement go through the facilitator instead.\n // Health details can reach logs, so they name the RPC by origin only.\n const rpcOrigin = describeRpc(options.rpcUrl);\n const healthPublicClient = createLocalPublicClient(\n options.rpcUrl,\n HEALTH_TIMEOUT_MS,\n profile.chainId,\n );\n\n const clock = options.clock ?? systemClock;\n const ids = options.ids ?? DEFAULT_IDS;\n const logger = options.logger ?? NOOP_LOGGER;\n const maxTimeoutSeconds = options.maxTimeoutSeconds ?? DEFAULT_MAX_TIMEOUT_SECONDS;\n\n const descriptor: AdapterDescriptor = {\n name: 'x402',\n kind: 'payment',\n implementationVersion: PACKAGE_VERSION,\n supportedSpec: `x402/v${X402_VERSION} scheme=exact family=eip155`,\n capabilities: [\n 'exact-evm',\n `${binding.kind}-facilitator`,\n 'eip-3009',\n 'caip-2',\n `mode=${mode}`,\n ],\n status: 'stable',\n unsupported: ['svm', 'permit2', 'upto scheme', 'deferred scheme'],\n };\n\n async function createRequirement(context: PaymentContext): Promise<PaymentRequirement> {\n const amount = parseCanonicalAmount(context.amount, options.assetDecimals).toString();\n\n const requirements: PaymentRequirements = {\n scheme: 'exact',\n network,\n asset: options.asset,\n amount,\n payTo: options.payTo,\n maxTimeoutSeconds,\n // `name`/`version` let the buyer and the facilitator build the same\n // EIP-712 domain without calling `version()` on the token.\n // `assetTransferMethod` names the one method this provider settles, so a\n // conforming client never picks the `exact` scheme's Permit2 path.\n extra: {\n name: options.assetName,\n version: options.assetVersion,\n assetTransferMethod: 'eip3009',\n },\n };\n\n // The v2 challenge document as sent on the wire. The HTTP adapter\n // base64-encodes it into `PAYMENT-REQUIRED` and MCP passes it through, so\n // both surfaces offer the same challenge.\n //\n // `resource.url` is descriptive: the EIP-3009 authorization does not cover\n // it and nothing verifies against it. It carries `network` and `payTo`,\n // both already public in the challenge, because other x402 servers may use\n // the `agent-commerce` authority too.\n const envelope: PaymentRequired = {\n x402Version: X402_VERSION,\n resource: {\n url: `resource://agent-commerce/${encodeURIComponent(options.network)}/${options.payTo}/resources/${encodeURIComponent(context.resource.id)}`,\n description: context.resource.description ?? context.resource.name,\n mimeType: DEFAULT_MIME_TYPE,\n },\n accepts: [requirements],\n };\n\n const expiresAt = new Date(clock.now().getTime() + maxTimeoutSeconds * 1000).toISOString();\n\n return {\n id: ids.next('payreq'),\n requestId: context.requestId,\n resourceId: context.resource.id,\n provider: 'x402',\n amount: context.amount,\n currency: context.currency,\n destination: options.payTo,\n network: options.network,\n asset: options.asset,\n expiresAt,\n challenge: {\n provider: 'x402',\n version: X402_PROTOCOL_VERSION,\n accepts: [requirements as unknown as Record<string, unknown>],\n envelope: envelope as unknown as Record<string, unknown>,\n },\n };\n }\n\n /**\n * Checks a submission against the requirement this provider built, never\n * against `payload.accepted`, the copy the client echoes back.\n *\n * The amount must match exactly. The pinned `@x402/evm` exact/EVM scheme\n * rejects any other value as\n * `invalid_exact_evm_payload_authorization_value_mismatch`, so an\n * overpayment is refused here as `wrong_amount`, a reason the buyer can act on.\n */\n async function verify(context: PaymentVerificationContext): Promise<PaymentResult> {\n const { requirement, submission } = context;\n\n const rejected = (reason: string): PaymentResult => ({\n status: 'rejected',\n provider: 'x402',\n amount: requirement.amount,\n currency: requirement.currency,\n ...(requirement.network !== undefined ? { network: requirement.network } : {}),\n ...(requirement.asset !== undefined ? { asset: requirement.asset } : {}),\n rejectionReason: reason,\n });\n\n if (requirement.provider !== 'x402' || requirement.challenge.provider !== 'x402') {\n return rejected('wrong_provider');\n }\n\n const requirements = requirement.challenge.accepts[0] as PaymentRequirements | undefined;\n if (!requirements) {\n return rejected('missing_payment_requirements');\n }\n\n // Defense in depth only: the pipeline builds a fresh requirement for every\n // request, so this rarely fires. The real expiry is EIP-3009's\n // `validBefore`, which the facilitator checks.\n if (\n requirement.expiresAt !== undefined &&\n Date.parse(requirement.expiresAt) < clock.now().getTime()\n ) {\n return rejected('requirement_expired');\n }\n\n // This provider built the requirement, so the asset always matches in\n // normal operation. A corrupted one must still never authorize a transfer\n // of a different asset.\n if (\n !isAddress(requirements.asset) ||\n getAddress(requirements.asset) !== getAddress(options.asset)\n ) {\n return rejected('wrong_asset');\n }\n\n const payload = decodePaymentSubmission(submission.payload);\n if (!payload) {\n return rejected('malformed_payment_payload');\n }\n if (payload.x402Version !== X402_VERSION) {\n return rejected('unsupported_x402_version');\n }\n if (!isExactEvmPayload(payload)) {\n return rejected('unsupported_scheme');\n }\n\n const { authorization } = payload.payload;\n\n if (!isAddress(authorization.from) || !isAddress(authorization.to)) {\n return rejected('malformed_payment_payload');\n }\n // `accepted.network` names the chain the buyer signed for, so a mismatch\n // means a signature bound to a chain we do not settle on\n if (payload.accepted.network !== options.network) {\n return rejected('wrong_network');\n }\n if (getAddress(authorization.to) !== getAddress(options.payTo)) {\n return rejected('wrong_recipient');\n }\n let authorizedValue: bigint;\n let required: bigint;\n try {\n authorizedValue = BigInt(authorization.value);\n required = BigInt(requirements.amount);\n } catch {\n return rejected('malformed_payment_payload');\n }\n if (authorizedValue !== required) {\n return rejected('wrong_amount');\n }\n\n const scope = binding.open();\n let sdkResult: VerifyResponse;\n try {\n sdkResult = await scope.verify(payload, requirements);\n } catch (err) {\n // A throw means no verdict was obtained, so it is never held against the\n // buyer. Only an unclassified one is logged, as it may be an SDK fault.\n if (!isProviderUnavailableError(err) && !scope.transportFailed()) {\n logger.warn({ err: redactedErrorText(err) }, 'x402 verify(): unexpected SDK error');\n }\n throw new CommerceError(\n 'PAYMENT_PROVIDER_UNAVAILABLE',\n `x402 provider: ${binding.kind} facilitator returned no verdict during verify()`,\n { cause: err },\n );\n }\n\n if (!sdkResult.isValid) {\n // An RPC that never answered is not a payment that failed a check\n if (scope.transportFailed()) {\n if (sdkResult.invalidReason !== undefined) {\n logger.debug(\n { reportedReason: sdkResult.invalidReason },\n 'x402 verify(): local facilitator transport failure reason',\n );\n }\n throw new CommerceError(\n 'PAYMENT_PROVIDER_UNAVAILABLE',\n `x402 provider: ${binding.kind} facilitator unreachable during verify()`,\n );\n }\n // The raw reason is logged at debug level. Only what the buyer sees and\n // the ledger records is constrained.\n if (sdkResult.invalidReason !== undefined) {\n logger.debug(\n { reportedReason: sdkResult.invalidReason },\n 'x402 verify(): facilitator rejection reason',\n );\n }\n return rejected(sanitizeReason(sdkResult.invalidReason, 'invalid_payment'));\n }\n\n // `accepted.network` equals the configured network (checked above), so the\n // profile's chain id is the one the authorization is bound to\n const replayKey = computeReplayKey({\n chainId: profile.chainId,\n asset: getAddress(requirements.asset),\n from: getAddress(authorization.from),\n nonce: authorization.nonce,\n });\n\n return {\n status: 'verified',\n provider: 'x402',\n payer: getAddress(authorization.from),\n payee: getAddress(authorization.to),\n amount: formatUnits(authorizedValue, options.assetDecimals),\n currency: requirement.currency,\n network: payload.accepted.network,\n asset: getAddress(requirements.asset),\n replayKey,\n };\n }\n\n async function settle(context: PaymentSettlementContext): Promise<PaymentResult> {\n const { requirement, submission, verification } = context;\n\n if (verification.status !== 'verified') {\n throw new CommerceError(\n 'PAYMENT_INVALID',\n 'x402 provider: settle() called without a successful verify()',\n );\n }\n\n const requirements = requirement.challenge.accepts[0] as PaymentRequirements | undefined;\n if (!requirements) {\n throw new CommerceError(\n 'PAYMENT_INVALID',\n 'x402 provider: settle() found no payment requirements to settle against',\n );\n }\n\n const payload = decodePaymentSubmission(submission.payload);\n if (!payload || !isExactEvmPayload(payload)) {\n throw new CommerceError(\n 'PAYMENT_INVALID',\n 'x402 provider: settle() received an undecodable payment payload',\n );\n }\n\n const rejectedSettlement = (rejectionReason: string): PaymentResult => ({\n status: 'rejected',\n provider: 'x402',\n amount: verification.amount,\n currency: requirement.currency,\n ...(verification.network !== undefined ? { network: verification.network } : {}),\n ...(verification.asset !== undefined ? { asset: verification.asset } : {}),\n ...(verification.replayKey !== undefined ? { replayKey: verification.replayKey } : {}),\n rejectionReason,\n });\n\n const scope = binding.open();\n let sdkResult: SettleResponse;\n try {\n sdkResult = await scope.settle(payload, requirements);\n } catch (err) {\n if (isProviderUnavailableError(err) || scope.transportFailed()) {\n throw new CommerceError(\n 'PAYMENT_PROVIDER_UNAVAILABLE',\n `x402 provider: ${binding.kind} facilitator unreachable during settle()`,\n { cause: err },\n );\n }\n // The pinned SDK returns a result for every failure from gas estimation\n // on, so a throw comes from its checks before anything is sent. A revert\n // there is a real rejection, which releases any mandate the pipeline\n // holds for the purchase. Any other throw goes back as an unavailable\n // provider, which the pipeline records as `settlement-uncertain`, never\n // as a rejection blamed on the buyer.\n if (!isOnChainRevertError(err)) {\n logger.warn(\n { err: redactedErrorText(err) },\n 'x402 settle(): settlement failed with an unclassified error; outcome unknown',\n );\n throw new CommerceError(\n 'PAYMENT_PROVIDER_UNAVAILABLE',\n 'x402 provider: settlement failed with an unclassified error; outcome unknown',\n { cause: err },\n );\n }\n logger.warn(\n { err: redactedErrorText(err), rejectionReason: 'transaction_reverted' },\n 'x402 settle(): settlement transaction reverted on chain',\n );\n return rejectedSettlement('transaction_reverted');\n }\n\n if (!sdkResult.success) {\n // \"Broadcast, never confirmed\" is not \"did not happen\": the transfer may\n // be on-chain, so it throws as an unavailable provider carrying the hash,\n // and the pipeline records the attempt `settlement-uncertain`, not\n // `rejected`. The SDK's catch-all without a hash is treated the same way,\n // because its throw may have followed a broadcast and viem reports an\n // RPC error on the send as a revert. Everything else is a real rejection.\n if (\n sdkResult.errorReason === TRANSACTION_FAILED_REASON &&\n !/^0x[0-9a-f]{64}$/i.test(sdkResult.transaction)\n ) {\n logger.warn(\n { reportedReason: sdkResult.errorReason },\n 'x402 settle(): the broadcast failed without a transaction hash; outcome unknown',\n );\n throw new CommerceError(\n 'PAYMENT_PROVIDER_UNAVAILABLE',\n 'x402 provider: settlement failed with an unclassified error; outcome unknown',\n );\n }\n if (sdkResult.errorReason === SETTLEMENT_PENDING_REASON || scope.transportFailed()) {\n throw new CommerceError(\n 'PAYMENT_PROVIDER_UNAVAILABLE',\n 'x402 provider: settlement was broadcast but could not be confirmed',\n {\n ...(sdkResult.transaction\n ? { details: { transactionHash: sdkResult.transaction } }\n : {}),\n },\n );\n }\n if (sdkResult.errorReason !== undefined) {\n logger.debug(\n { reportedReason: sdkResult.errorReason },\n 'x402 settle(): facilitator failure reason',\n );\n }\n return {\n ...rejectedSettlement(sanitizeReason(sdkResult.errorReason, 'settlement_failed')),\n network: sdkResult.network,\n ...(sdkResult.payer !== undefined ? { payer: sdkResult.payer } : {}),\n };\n }\n\n return {\n status: 'settled',\n provider: 'x402',\n externalReference: sdkResult.transaction,\n ...(sdkResult.payer !== undefined ? { payer: sdkResult.payer } : {}),\n payee: requirements.payTo,\n amount: verification.amount,\n currency: requirement.currency,\n network: sdkResult.network,\n ...(verification.asset !== undefined ? { asset: verification.asset } : {}),\n ...(verification.replayKey !== undefined ? { replayKey: verification.replayKey } : {}),\n settledAt: clock.nowIso(),\n };\n }\n\n async function computeHealth(): Promise<AdapterHealth> {\n const startedAt = clock.monotonicMs();\n const checkedAt = clock.nowIso();\n\n try {\n const chainId = await healthPublicClient.getChainId();\n if (chainId !== profile.chainId) {\n return {\n status: 'fail',\n detail: `RPC at ${rpcOrigin} reports chain id ${chainId}, expected ${profile.chainId} (${profile.displayName})`,\n checkedAt,\n durationMs: clock.monotonicMs() - startedAt,\n };\n }\n\n const code = await healthPublicClient.getCode({ address: options.asset });\n if (!code || code === '0x') {\n return {\n status: 'fail',\n detail: `No contract code found at configured asset address ${options.asset}`,\n checkedAt,\n durationMs: clock.monotonicMs() - startedAt,\n };\n }\n\n if (binding.kind === 'remote') {\n // Reachable is not enough: a facilitator that does not carry our\n // scheme on our network fails every payment after the buyer has signed\n const kinds = await binding.supported();\n const supportsUs = kinds.some(\n (kind) =>\n kind.x402Version === X402_VERSION &&\n kind.scheme === 'exact' &&\n kind.network === options.network,\n );\n if (!supportsUs) {\n return {\n status: 'fail',\n detail:\n `Facilitator ${binding.describe} does not advertise x402 v${X402_VERSION} scheme=exact ` +\n `on ${options.network} (${profile.displayName}); no payment on this deployment can settle`,\n checkedAt,\n durationMs: clock.monotonicMs() - startedAt,\n };\n }\n return {\n status: 'pass',\n detail:\n `${describeDeploymentMode(mode)}: RPC ${rpcOrigin} reachable, chain id ` +\n `${profile.chainId} (${profile.displayName}), asset ${options.asset} has code, ` +\n `facilitator ${binding.describe} supports exact/${options.network}`,\n checkedAt,\n durationMs: clock.monotonicMs() - startedAt,\n };\n }\n\n // Chain id alone cannot prove this is a dev chain, because Base Sepolia\n // reports the same 84532 as the local chain. An Anvil-only RPC method\n // must answer before a local facilitator counts as healthy.\n const isAnvil = await probeIsAnvilNode(healthPublicClient);\n if (!isAnvil) {\n return {\n status: 'fail',\n detail:\n `RPC at ${rpcOrigin} reports chain id ${profile.chainId} but does not answer ` +\n '\"anvil_nodeInfo\", so it does not look like a local Anvil dev node. Refusing to treat it ' +\n 'as safe for a local-facilitator dev key.',\n checkedAt,\n durationMs: clock.monotonicMs() - startedAt,\n };\n }\n\n return {\n status: 'pass',\n detail:\n `${describeDeploymentMode(mode)}: RPC ${rpcOrigin} reachable, chain id ` +\n `${profile.chainId}, asset ${options.asset} has code, confirmed Anvil dev node`,\n checkedAt,\n durationMs: clock.monotonicMs() - startedAt,\n };\n } catch (err) {\n return {\n status: 'fail',\n detail: `x402 health check failed: ${redactedErrorText(err)}`,\n checkedAt,\n durationMs: clock.monotonicMs() - startedAt,\n };\n }\n }\n\n // A probe makes several upstream calls, and `/ready` is unauthenticated.\n // A short TTL plus one shared in-flight probe keeps upstream volume independent\n // of request volume, for library callers as well as the gateway, whose\n // readiness probe adds its own cache on top. Pass and fail share the TTL: a\n // shorter one for fail would bring the load back during an RPC outage,\n // exactly when each call is slowest.\n const HEALTH_CACHE_MS = 5_000;\n let cachedHealth: { at: number; value: AdapterHealth } | undefined;\n let inFlightHealth: Promise<AdapterHealth> | undefined;\n\n async function health(): Promise<AdapterHealth> {\n const now = clock.monotonicMs();\n if (cachedHealth && now - cachedHealth.at < HEALTH_CACHE_MS) {\n return cachedHealth.value;\n }\n if (inFlightHealth) return inFlightHealth;\n\n inFlightHealth = computeHealth()\n .then((value) => {\n cachedHealth = { at: clock.monotonicMs(), value };\n return value;\n })\n .finally(() => {\n inFlightHealth = undefined;\n });\n return inFlightHealth;\n }\n\n return {\n name: 'x402',\n descriptor,\n createRequirement,\n verify,\n settle,\n health,\n };\n}\n\n// viem wraps every failed contract call in ContractFunctionExecutionError, so\n// only the cause chain can show a revert. A revert alone does not prove nothing\n// moved, because viem also reports an RPC error on a send as one; settle()\n// relies on the SDK throwing only before the broadcast.\nfunction isOnChainRevertError(err: unknown): boolean {\n return (\n err instanceof BaseError && err.walk((e) => e instanceof ContractFunctionRevertedError) !== null\n );\n}\n\n/**\n * The `instanceof` checks cover what the pinned viem HTTP transport throws\n * (`HttpRequestError` for every fetch failure, including connection refused,\n * or `TimeoutError`) and what `waitForTransactionReceipt` throws when it stops\n * polling after a broadcast. Message matching is only a fallback for errors\n * outside those classes, such as a raw undici error, because message text can\n * change with any viem or undici upgrade.\n */\nfunction isProviderUnavailableError(err: unknown): boolean {\n if (\n err instanceof HttpRequestError ||\n err instanceof TimeoutError ||\n err instanceof WaitForTransactionReceiptTimeoutError\n ) {\n return true;\n }\n const message = redactedErrorText(err).toLowerCase();\n return (\n message.includes('econnrefused') ||\n message.includes('fetch failed') ||\n message.includes('enotfound') ||\n message.includes('etimedout') ||\n message.includes('timed out') ||\n message.includes('network error')\n );\n}\n\n/**\n * True only when the RPC answers Anvil's own `anvil_nodeInfo` method. A public\n * node, Base Sepolia included, answers \"method not found\". Never throws.\n */\nasync function probeIsAnvilNode(\n client: ReturnType<typeof createLocalPublicClient>,\n): Promise<boolean> {\n // Anvil-only method, absent from viem's typed PublicRpcSchema, hence the cast\n const request = client.request as unknown as (args: {\n method: string;\n params: unknown[];\n }) => Promise<unknown>;\n try {\n await request({ method: 'anvil_nodeInfo', params: [] });\n return true;\n } catch {\n return false;\n }\n}\n"]}
|