@devlab.group/agent-commerce 1.4.1 → 1.6.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 (44) hide show
  1. package/README.md +168 -183
  2. package/dist/ap2.d.ts +21 -24
  3. package/dist/ap2.js +68 -82
  4. package/dist/ap2.js.map +1 -1
  5. package/dist/authorization-BpbWGGrf.d.ts +115 -0
  6. package/dist/{chunk-NWIQLJNU.js → chunk-74BSEXB5.js} +37 -34
  7. package/dist/chunk-74BSEXB5.js.map +1 -0
  8. package/dist/chunk-AFI2CEZS.js +10 -0
  9. package/dist/chunk-AFI2CEZS.js.map +1 -0
  10. package/dist/chunk-ATTWSFQP.js +680 -0
  11. package/dist/chunk-ATTWSFQP.js.map +1 -0
  12. package/dist/{chunk-ZEGFLRGV.js → chunk-IVJC5YLE.js} +63 -26
  13. package/dist/chunk-IVJC5YLE.js.map +1 -0
  14. package/dist/{chunk-GF6KHHKL.js → chunk-RAJGPGJG.js} +5 -8
  15. package/dist/chunk-RAJGPGJG.js.map +1 -0
  16. package/dist/chunk-V2V2E7HX.js +27 -0
  17. package/dist/chunk-V2V2E7HX.js.map +1 -0
  18. package/dist/cli/index.js +812 -573
  19. package/dist/cli/index.js.map +1 -1
  20. package/dist/constants-Bkq04FRZ.d.ts +48 -0
  21. package/dist/guardrails-71XwtXlT.d.ts +31 -0
  22. package/dist/index.d.ts +245 -265
  23. package/dist/index.js +1222 -626
  24. package/dist/index.js.map +1 -1
  25. package/dist/mcp.d.ts +6 -59
  26. package/dist/mcp.js +64 -53
  27. package/dist/mcp.js.map +1 -1
  28. package/dist/mpp.d.ts +50 -0
  29. package/dist/mpp.js +353 -0
  30. package/dist/mpp.js.map +1 -0
  31. package/dist/protocol-adapter-DTkrXTev.d.ts +238 -0
  32. package/dist/runtime-CiYbgGpi.d.ts +303 -0
  33. package/dist/{types-CJtwLu1c.d.ts → types-O6lg3Q5V.d.ts} +17 -23
  34. package/dist/x402.d.ts +43 -75
  35. package/dist/x402.js +13 -693
  36. package/dist/x402.js.map +1 -1
  37. package/package.json +13 -2
  38. package/dist/authorization-CPDcpJVa.d.ts +0 -123
  39. package/dist/chunk-GF6KHHKL.js.map +0 -1
  40. package/dist/chunk-NWIQLJNU.js.map +0 -1
  41. package/dist/chunk-ZEGFLRGV.js.map +0 -1
  42. package/dist/guardrails-Dmwi63KB.d.ts +0 -38
  43. package/dist/protocol-adapter-Bebmggf_.d.ts +0 -273
  44. package/dist/runtime-CKq3d_3K.d.ts +0 -340
@@ -0,0 +1,303 @@
1
+ /**
2
+ * A JSON Schema document (in practice a draft 2020-12 subset). Deliberately
3
+ * loose: adapters translate it to their own schema representation. Never treat
4
+ * it as trusted input without validation.
5
+ */
6
+ type JsonSchema = Record<string, unknown>;
7
+ /** Protocol surfaces a resource can be exposed through */
8
+ type ProtocolName = 'http' | 'mcp' | 'a2a' | 'acp';
9
+ /**
10
+ * The same names as a value, for code that checks one at runtime: config
11
+ * validation and the OpenAPI importer's `--expose`
12
+ */
13
+ declare const PROTOCOL_NAMES: readonly ProtocolName[];
14
+ /**
15
+ * Payment rails a resource can accept.
16
+ *
17
+ * A resource's list is an ordered candidate list, not a buyer-selected menu.
18
+ * The pipeline uses the first method with an enabled provider, and a
19
+ * rejection ends the request instead of trying another rail. Config requires at
20
+ * least one named rail to be enabled and permits others that are not.
21
+ */
22
+ type PaymentMethodName = 'x402' | 'mpp';
23
+ /** The same names as a value, for config validation */
24
+ declare const PAYMENT_METHOD_NAMES: readonly PaymentMethodName[];
25
+ /**
26
+ * Authorization methods a resource can require. Neither a transport nor a
27
+ * payment rail: it proves the purchase was approved, and sits beside the
28
+ * payment rather than replacing it.
29
+ */
30
+ type AuthorizationMethodName = 'ap2';
31
+ /** ISO-8601 timestamp string, always UTC with millisecond precision */
32
+ type IsoTimestamp = string;
33
+ /**
34
+ * A decimal amount as a string in the currency's display unit (for example
35
+ * "0.01" USDC), never a float and never base units. Payment providers convert
36
+ * it to on-chain base units.
37
+ */
38
+ type DecimalAmount = string;
39
+ /** Health of an individual adapter or subsystem */
40
+ interface AdapterHealth {
41
+ readonly status: 'pass' | 'warn' | 'fail';
42
+ readonly detail?: string;
43
+ readonly checkedAt: IsoTimestamp;
44
+ readonly durationMs?: number;
45
+ }
46
+ /** Describes an adapter's supported surface for diagnostics */
47
+ interface AdapterDescriptor {
48
+ readonly name: string;
49
+ readonly kind: 'protocol' | 'payment' | 'storage' | 'authorization';
50
+ /** Version of this adapter implementation, independent of the spec */
51
+ readonly implementationVersion: string;
52
+ /** Exact pinned specification revision this adapter targets */
53
+ readonly supportedSpec: string;
54
+ readonly capabilities: readonly string[];
55
+ readonly status: 'stable' | 'experimental' | 'planned';
56
+ /** Capabilities explicitly not implemented, printed by `doctor` */
57
+ readonly unsupported?: readonly string[];
58
+ }
59
+
60
+ /** HTTP methods a backend handler may use */
61
+ type BackendMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
62
+ /**
63
+ * How the gateway calls the merchant's existing backend.
64
+ *
65
+ * Backend URLs come from operator configuration only, never from users or
66
+ * agents (docs/security.md, SSRF). Secret header values belong in `${ENV_VAR}`
67
+ * placeholders resolved by the config loader, not in plaintext configuration.
68
+ */
69
+ interface BackendHandler {
70
+ readonly type: 'http';
71
+ readonly method: BackendMethod;
72
+ readonly url: string;
73
+ readonly headers?: Readonly<Record<string, string>>;
74
+ /** Hard upper bound on the backend call. Defaults to `DEFAULT_BACKEND_TIMEOUT_MS` */
75
+ readonly timeoutMs?: number;
76
+ /**
77
+ * Names the top-level input properties carrying each part of the request.
78
+ *
79
+ * When absent, `{param}` values come from top-level input and everything left
80
+ * over becomes the query string (GET/DELETE) or the whole JSON body
81
+ * (POST/PUT/PATCH). That cannot express an operation with path, query and
82
+ * body at once, such as `POST /users/{userId}/orders?notify=true`.
83
+ *
84
+ * When present, each group comes from its named property, and top-level input
85
+ * that no binding names is not forwarded.
86
+ */
87
+ readonly inputBindings?: {
88
+ readonly path?: string;
89
+ readonly query?: string;
90
+ readonly body?: string;
91
+ };
92
+ }
93
+ /** Default backend timeout when a resource does not specify one */
94
+ declare const DEFAULT_BACKEND_TIMEOUT_MS = 10000;
95
+ /**
96
+ * Canonical pricing. `dynamic` exists in the type for forward compatibility;
97
+ * config validation rejects it and the pipeline refuses it as defense in depth.
98
+ */
99
+ type Pricing = {
100
+ readonly type: 'free';
101
+ } | {
102
+ readonly type: 'fixed';
103
+ readonly amount: DecimalAmount;
104
+ readonly currency: string;
105
+ } | {
106
+ readonly type: 'dynamic';
107
+ readonly resolver: string;
108
+ };
109
+ /**
110
+ * A merchant capability exposed to agents. Protocol adapters map it outward and
111
+ * never define their own parallel notion of a resource.
112
+ */
113
+ interface CommerceResource {
114
+ readonly id: string;
115
+ readonly name: string;
116
+ readonly description?: string;
117
+ readonly inputSchema?: JsonSchema;
118
+ readonly outputSchema?: JsonSchema;
119
+ readonly handler: BackendHandler;
120
+ readonly pricing: Pricing;
121
+ readonly exposedVia: readonly ProtocolName[];
122
+ readonly paymentMethods: readonly PaymentMethodName[];
123
+ /**
124
+ * Authorization the buyer must present in addition to payment. Opt-in per
125
+ * resource. It sits beside `paymentMethods`, not inside it, because an
126
+ * authorization method is not a payment rail and must never be selectable as
127
+ * one.
128
+ */
129
+ readonly authorization?: {
130
+ readonly required: readonly AuthorizationMethodName[];
131
+ };
132
+ }
133
+ /** Read-only view of every configured resource */
134
+ interface ResourceRegistry {
135
+ get(id: string): CommerceResource | undefined;
136
+ list(): readonly CommerceResource[];
137
+ /** Resources exposed through a given protocol surface */
138
+ listExposedVia(protocol: ProtocolName): readonly CommerceResource[];
139
+ has(id: string): boolean;
140
+ }
141
+
142
+ /**
143
+ * Canonical payment model. FROZEN CONTRACT.
144
+ *
145
+ * Core decides that a payment is required and for how much. Payment providers
146
+ * decide how the challenge is encoded, verified and settled. No x402- or
147
+ * EVM-specific type may appear in this file.
148
+ */
149
+
150
+ /**
151
+ * Provider-native payment challenge, opaque to core. For x402 the `accepts`
152
+ * entries are x402 `PaymentRequirements` objects, passed to protocol adapters
153
+ * verbatim.
154
+ */
155
+ interface PaymentChallenge {
156
+ readonly provider: PaymentMethodName;
157
+ /** Provider protocol version, e.g. the x402 `x402Version` value as a string */
158
+ readonly version: string;
159
+ readonly accepts: readonly Readonly<Record<string, unknown>>[];
160
+ /**
161
+ * The provider's own challenge document, verbatim: for x402 v2 the
162
+ * `PaymentRequired` object a buyer's client consumes, for MPP an object
163
+ * carrying the serialized `WWW-Authenticate` challenge. Opaque to core.
164
+ *
165
+ * `accepts` alone is not that document: x402 v2 carries the resource
166
+ * description and protocol version on the envelope. Adapters with a native
167
+ * channel for it (x402's `PAYMENT-REQUIRED` header, MPP's `WWW-Authenticate`)
168
+ * send it there as is, so every surface offers the same challenge.
169
+ */
170
+ readonly envelope?: Readonly<Record<string, unknown>>;
171
+ }
172
+ /**
173
+ * What the buyer must pay, in canonical terms, plus the provider-native
174
+ * challenge the buyer's client needs to construct a payment
175
+ */
176
+ interface PaymentRequirement {
177
+ readonly id: string;
178
+ readonly requestId: string;
179
+ readonly resourceId: string;
180
+ readonly provider: PaymentMethodName;
181
+ readonly amount: DecimalAmount;
182
+ readonly currency: string;
183
+ /** Merchant-controlled settlement destination, never a gateway-owned wallet */
184
+ readonly destination: string;
185
+ readonly network?: string;
186
+ readonly asset?: string;
187
+ readonly expiresAt?: IsoTimestamp;
188
+ readonly challenge: PaymentChallenge;
189
+ readonly metadata?: Readonly<Record<string, unknown>>;
190
+ }
191
+ /**
192
+ * Opaque payment proof supplied by the buyer's client. For x402 over HTTP it is
193
+ * the base64 `PAYMENT-SIGNATURE` header value; over MCP and A2A it is the same
194
+ * string in the reserved `_payment` input field.
195
+ */
196
+ interface PaymentSubmission {
197
+ readonly method: PaymentMethodName;
198
+ readonly payload: string;
199
+ }
200
+ /** Outcome of verification or settlement */
201
+ interface PaymentResult {
202
+ readonly status: 'verified' | 'settled' | 'rejected';
203
+ readonly provider: PaymentMethodName;
204
+ /** Settlement reference, e.g. an on-chain transaction hash */
205
+ readonly externalReference?: string;
206
+ readonly payer?: string;
207
+ readonly payee?: string;
208
+ readonly amount: DecimalAmount;
209
+ readonly currency: string;
210
+ readonly network?: string;
211
+ readonly asset?: string;
212
+ /**
213
+ * Stable, provider-computed identity of the payment authorization.
214
+ *
215
+ * The pipeline reserves this key before settlement and rejects a second
216
+ * request presenting it with `PAYMENT_REPLAYED`. Providers must derive it
217
+ * only from the authorization (payer, nonce, asset, network), so the same
218
+ * authorization always maps to the same key.
219
+ */
220
+ readonly replayKey?: string;
221
+ /** Machine-readable rejection reason when status is `rejected` */
222
+ readonly rejectionReason?: string;
223
+ readonly settledAt?: IsoTimestamp;
224
+ readonly metadata?: Readonly<Record<string, unknown>>;
225
+ }
226
+ /** Input to {@link PaymentProvider.createRequirement} */
227
+ interface PaymentContext {
228
+ readonly requestId: string;
229
+ readonly resource: CommerceResource;
230
+ readonly amount: DecimalAmount;
231
+ readonly currency: string;
232
+ readonly requestedAt: IsoTimestamp;
233
+ readonly metadata?: Readonly<Record<string, unknown>>;
234
+ }
235
+ /** Input to {@link PaymentProvider.verify} */
236
+ interface PaymentVerificationContext {
237
+ readonly requestId: string;
238
+ readonly resource: CommerceResource;
239
+ readonly requirement: PaymentRequirement;
240
+ readonly submission: PaymentSubmission;
241
+ }
242
+ /** Input to {@link PaymentProvider.settle} */
243
+ interface PaymentSettlementContext extends PaymentVerificationContext {
244
+ readonly verification: PaymentResult;
245
+ }
246
+ /**
247
+ * Contract every payment rail implements. Implementations must be
248
+ * non-custodial: they orchestrate an external payment protocol and never hold
249
+ * buyer or merchant production signing keys.
250
+ */
251
+ interface PaymentProvider {
252
+ readonly name: PaymentMethodName;
253
+ readonly descriptor: AdapterDescriptor;
254
+ /**
255
+ * Build the requirement and its challenge. The pipeline calls it for every
256
+ * paid request, including one that already carries a proof to verify.
257
+ */
258
+ createRequirement(context: PaymentContext): Promise<PaymentRequirement>;
259
+ /**
260
+ * Validate a submitted proof against the requirement. Must return `rejected`
261
+ * or throw a `CommerceError` rather than an untyped error, and must never
262
+ * move funds.
263
+ */
264
+ verify(context: PaymentVerificationContext): Promise<PaymentResult>;
265
+ /**
266
+ * Execute settlement. Called only after `verify` returned `verified` and the
267
+ * replay key was reserved. A settlement verdict, including a rejection, is a
268
+ * returned result; the pipeline records any throw as settlement-uncertain.
269
+ */
270
+ settle(context: PaymentSettlementContext): Promise<PaymentResult>;
271
+ health(): Promise<AdapterHealth>;
272
+ }
273
+
274
+ /**
275
+ * Minimal structural logger. Core does not depend on pino; the gateway injects
276
+ * a pino instance that satisfies this shape.
277
+ *
278
+ * Never log secrets: private keys, seed phrases, Authorization headers or
279
+ * payment authorization payloads.
280
+ */
281
+ interface Logger {
282
+ debug(obj: Record<string, unknown>, msg?: string): void;
283
+ info(obj: Record<string, unknown>, msg?: string): void;
284
+ warn(obj: Record<string, unknown>, msg?: string): void;
285
+ error(obj: Record<string, unknown>, msg?: string): void;
286
+ child(bindings: Record<string, unknown>): Logger;
287
+ }
288
+ /** A logger that discards everything */
289
+ declare const NOOP_LOGGER: Logger;
290
+
291
+ interface Clock {
292
+ now(): Date;
293
+ nowIso(): IsoTimestamp;
294
+ /** Milliseconds since an arbitrary origin; use for durations only */
295
+ monotonicMs(): number;
296
+ }
297
+ interface IdGenerator {
298
+ /** Opaque, collision-resistant identifier */
299
+ next(prefix?: string): string;
300
+ }
301
+ declare const systemClock: Clock;
302
+
303
+ export { type AdapterDescriptor as A, type BackendHandler as B, type Clock as C, type DecimalAmount as D, type IsoTimestamp as I, type JsonSchema as J, type Logger as L, NOOP_LOGGER as N, type PaymentMethodName as P, type ResourceRegistry as R, type CommerceResource as a, type PaymentSubmission as b, type AdapterHealth as c, type PaymentProvider as d, type IdGenerator as e, type AuthorizationMethodName as f, type BackendMethod as g, DEFAULT_BACKEND_TIMEOUT_MS as h, PAYMENT_METHOD_NAMES as i, PROTOCOL_NAMES as j, type PaymentChallenge as k, type PaymentContext as l, type PaymentRequirement as m, type PaymentResult as n, type PaymentSettlementContext as o, type PaymentVerificationContext as p, type Pricing as q, type ProtocolName as r, systemClock as s };
@@ -7,49 +7,43 @@
7
7
  */
8
8
  declare const AP2_SPEC_VERSION = "0.2.0";
9
9
  /**
10
- * Autonomous mode needs open mandates, cnf-bound agent keys and constraint
11
- * evaluation over `checkout.line_items`. Half of that would be worse than a
12
- * declared Direct-only profile, so it is refused rather than partly served.
10
+ * Direct only. Autonomous mode needs open mandates, cnf-bound agent keys and
11
+ * constraint evaluation over `checkout.line_items`, none of which is
12
+ * implemented, so it is refused rather than partly served.
13
13
  */
14
14
  declare const AP2_MODES: readonly ["direct"];
15
15
  type Ap2Mode = (typeof AP2_MODES)[number];
16
16
  /**
17
- * One entry, so `alg=none` and the HMAC family are excluded by construction
18
- * rather than by a check that has to remember them
17
+ * A single algorithm, so `alg=none` and the HMAC family are excluded by
18
+ * construction rather than by a denylist
19
19
  */
20
20
  declare const AP2_SIGNING_ALGORITHM = "ES256";
21
21
  /**
22
22
  * Compared against this literal, never as a prefix. `mandate.checkout.open.1`
23
- * carries spending constraints this release does not evaluate, so accepting it
24
- * would tell a buyer their limits were checked when nothing read them.
23
+ * carries spending constraints nothing here evaluates, so accepting it would
24
+ * tell a buyer their limits were checked when nothing read them.
25
25
  */
26
26
  declare const AP2_CHECKOUT_MANDATE_VCT = "mandate.checkout.1";
27
27
  /**
28
- * The checkout profile every merchant checkout JWT must declare.
29
- *
30
- * Ours, not AP2's: AP2 leaves the checkout payload outside its scope, so the
31
- * claims a paid-resource invocation needs had to be specified somewhere.
32
- *
33
- * A bare name, matching the gateway's other wire identifiers
34
- * (`agent-commerce/delivery`, `agent-commerce/v1.0.0`). A profile id is a
35
- * namespace and is never dereferenced, so a URL would only tie the wire format
36
- * to a domain. Frozen once released: merchants sign it into every checkout JWT.
28
+ * Merchant checkout JWTs declare this gateway-specific profile; AP2 leaves
29
+ * the checkout payload out of scope. The identifier is a namespace that
30
+ * clients do not dereference. Merchants sign it into each checkout JWT, so
31
+ * changing the expected value would reject previously signed JWTs.
37
32
  */
38
33
  declare const AP2_CHECKOUT_PROFILE = "agent-commerce/ap2/checkout/v1";
39
34
  /** Seconds of clock skew tolerated on mandate and checkout time claims */
40
35
  declare const AP2_DEFAULT_CLOCK_SKEW_SECONDS = 60;
41
36
  /**
42
- * Skew wide enough to cover a mandate's validity window stops `exp` rejecting
43
- * anything. An operator needing more than five minutes has a clock to fix.
37
+ * Skew as wide as a mandate's validity window would stop `exp` rejecting
38
+ * anything. An operator who needs more than five minutes has a clock to fix.
44
39
  */
45
40
  declare const AP2_MAX_CLOCK_SKEW_SECONDS = 300;
46
41
 
47
42
  /**
48
43
  * AP2 trust configuration and the shape a successful verification produces.
49
44
  *
50
- * Trust types live here, not in `src/config`, so the dependency points the way
51
- * `X402FacilitatorConfig` does: the subsystem owns its own config shape and
52
- * the loader imports it.
45
+ * The subsystem owns its config shape and the config loader imports it, as
46
+ * with `X402FacilitatorConfig`.
53
47
  */
54
48
 
55
49
  /** One inline public verification key, trusted because an operator wrote it here */
@@ -62,8 +56,8 @@ interface Ap2TrustedKey {
62
56
  interface Ap2TrustedIssuer {
63
57
  readonly issuer: string;
64
58
  /**
65
- * Per issuer, not one gateway-wide value: the mandate is addressed to the
66
- * merchant and the checkout JWT it binds to the gateway
59
+ * Per issuer, not gateway-wide: a mandate is addressed to the merchant, while
60
+ * the checkout JWT it binds is addressed to the gateway
67
61
  */
68
62
  readonly audience: string;
69
63
  readonly keys: readonly Ap2TrustedKey[];
package/dist/x402.d.ts CHANGED
@@ -1,25 +1,22 @@
1
- import { X as X402FacilitatorConfig } from './guardrails-Dmwi63KB.js';
2
- export { F as FacilitatorAuth } from './guardrails-Dmwi63KB.js';
3
- import { L as Logger, C as Clock, e as IdGenerator, d as PaymentProvider } from './runtime-CKq3d_3K.js';
1
+ import { X as X402FacilitatorConfig } from './guardrails-71XwtXlT.js';
2
+ export { F as FacilitatorAuth } from './guardrails-71XwtXlT.js';
3
+ import { L as Logger, C as Clock, e as IdGenerator, d as PaymentProvider } from './runtime-CiYbgGpi.js';
4
4
 
5
5
  interface NetworkProfile {
6
- /** CAIP-2 identifier, e.g. `eip155:84532`. */
6
+ /** CAIP-2 identifier, e.g. `eip155:84532` */
7
7
  readonly id: string;
8
- /** Signed into the buyer's EIP-712 domain. */
8
+ /** Signed into the buyer's EIP-712 domain */
9
9
  readonly chainId: number;
10
10
  readonly displayName: string;
11
11
  readonly kind: 'testnet' | 'mainnet';
12
12
  /**
13
- * The USDC deployment this network is expected to settle in, with the EIP-712
14
- * domain the token actually reports. Enforced only on mainnet (see
15
- * `guardrails.ts`) — a testnet is where a mock token is a legitimate thing to
16
- * point at.
13
+ * The USDC deployment this network settles in, with the EIP-712 domain the
14
+ * token reports. Enforced on mainnet only, since a testnet may use a mock
15
+ * token.
17
16
  *
18
- * `name` is not decorative and is not the symbol: it is signed into every
19
- * buyer's EIP-712 domain, and the two USDC deployments disagree. Base Sepolia
20
- * reports `"USDC"`; Base mainnet reports `"USD Coin"`. Configure the wrong
21
- * one and every payment is refused `invalid_exact_evm_token_name_mismatch`
22
- * after the buyer has signed. Read back from the contracts, not assumed.
17
+ * `name` is the signed EIP-712 domain name, not the symbol, and the two
18
+ * deployments differ: `"USDC"` on Base Sepolia, `"USD Coin"` on Base. The
19
+ * values were read back from the contracts.
23
20
  */
24
21
  readonly canonicalAsset?: {
25
22
  readonly symbol: string;
@@ -30,42 +27,30 @@ interface NetworkProfile {
30
27
  }
31
28
  declare const SUPPORTED_NETWORK_IDS: readonly string[];
32
29
  /**
33
- * What this deployment actually is, as opposed to what it is called.
34
- *
35
- * `local` is a property of the *facilitator*, not the network: settling
36
- * through the in-process facilitator against a dev node is local regardless of
37
- * the CAIP-2 id that node answers to. This distinction is the whole reason
38
- * diagnostics can say `eip155:84532` without claiming to be on public Base
39
- * Sepolia.
30
+ * What a deployment is, as opposed to the network it names. `local` comes from
31
+ * the facilitator: the in-process facilitator makes a deployment local whatever
32
+ * CAIP-2 id it is configured with, which lets diagnostics show `eip155:84532`
33
+ * without claiming public Base Sepolia.
40
34
  */
41
35
  type DeploymentMode = 'local' | 'testnet' | 'mainnet';
42
36
 
43
37
  /**
44
- * CLIENT-SIDE payment helper.
45
- *
46
- * This module is used by the demo buyer agent (`demo/agent`) and by the
47
- * payment E2E test suite to build and EIP-712-sign an x402 v2 `exact`/EVM
48
- * payment authorisation, entirely on the buyer's side.
49
- *
50
- * The gateway NEVER calls this module and NEVER holds a buyer private key.
51
- * `buyerPrivateKey` here is always an Anvil well-known
52
- * development key (LOCAL DEVELOPMENT ONLY — DO NOT FUND) supplied by whoever
53
- * is driving the demo/test, not something the provider or gateway manages.
38
+ * Client-side payment helper: builds and EIP-712-signs an x402 v2 `exact`/EVM
39
+ * authorization on the buyer's side. The demo buyer agent and the test suites
40
+ * use it, and the `/x402` entry exports it. The gateway never calls it and
41
+ * never holds a buyer key.
54
42
  *
55
- * It signs the EIP-712 authorisation directly rather than going through the
56
- * SDK's `x402Client`, for one reason: `overrides`. The negative payment tests
57
- * need authorisations that are deliberately wrong — wrong recipient, short
58
- * amount, reused nonce, expired window — and a conforming client will not
59
- * produce those. Interop with a real SDK client is proved separately, by a
60
- * test that pays the gateway using `x402Client` itself.
43
+ * It signs directly rather than through the SDK's `x402Client` because of
44
+ * `overrides`: negative tests need deliberately wrong authorizations that a
45
+ * conforming client will not produce. The x402 settlement E2E suite also
46
+ * settles a payment built by `x402Client` itself to cover interoperability.
61
47
  */
62
48
  interface CreatePaymentProofOptions {
63
- /** Buyer's dev-only private key. LOCAL DEVELOPMENT ONLY — DO NOT FUND. */
49
+ /** The buyer's private key. It signs locally and is never sent anywhere */
64
50
  readonly buyerPrivateKey: `0x${string}`;
65
- readonly rpcUrl: string;
66
- /** One entry from PaymentRequiredEnvelope.payment.accepts, verbatim. */
51
+ /** One entry from PaymentRequiredEnvelope.payment.accepts, verbatim */
67
52
  readonly accepts: Readonly<Record<string, unknown>>;
68
- /** Overrides used only by negative tests (wrong amount/recipient/nonce…). */
53
+ /** For negative tests only: a wrong amount, recipient, nonce or validity window */
69
54
  readonly overrides?: {
70
55
  readonly value?: string;
71
56
  readonly payTo?: string;
@@ -74,26 +59,17 @@ interface CreatePaymentProofOptions {
74
59
  readonly validAfter?: number;
75
60
  };
76
61
  }
77
- /** Returns the base64 `PAYMENT-SIGNATURE` value to send back to the gateway. */
62
+ /** Returns the base64 `PAYMENT-SIGNATURE` value to send back to the gateway */
78
63
  declare function createPaymentProof(options: CreatePaymentProofOptions): Promise<string>;
79
64
 
80
65
  /**
81
- * x402 payment provider — protocol version 2, `exact` scheme, EVM,
82
- * EIP-3009 `transferWithAuthorization`.
83
- *
84
- * Implements the frozen `PaymentProvider` interface (src/core/domain/payment.ts).
85
- * `verify()` never moves funds; only `settle()` does, and only after a
86
- * successful `verify()` (enforced by the gateway's execution pipeline, not by
87
- * this file, but this file never calls settle-like RPCs from verify()).
88
- *
89
- * Verification and settlement run through the SDK's own `x402Facilitator`
90
- * with the `exact`/EVM scheme registered against a single CAIP-2 network. The
91
- * facilitator is in-process — it is the same code a hosted facilitator runs,
92
- * pointed at the local dev chain — so there is no network hop and no third
93
- * party in the settlement path.
66
+ * x402 payment provider: protocol v2, `exact` scheme, EVM, EIP-3009
67
+ * `transferWithAuthorization`.
94
68
  *
95
- * The SDK behaviour relied on here is verified, not assumed: see the notes
96
- * beside each call site below.
69
+ * `verify()` never moves funds. `settle()` does, and throws unless it is handed
70
+ * a successful verification. Both run through a facilitator (see
71
+ * `facilitator.ts`): the SDK's own `x402Facilitator` in this process, or a
72
+ * remote HTTP facilitator.
97
73
  */
98
74
 
99
75
  interface X402ProviderOptions {
@@ -105,34 +81,26 @@ interface X402ProviderOptions {
105
81
  readonly network: string;
106
82
  /** RPC endpoint. Local chain: http://127.0.0.1:8545 */
107
83
  readonly rpcUrl: string;
108
- /** ERC-20 (EIP-3009) asset address used for settlement. */
84
+ /** ERC-20 (EIP-3009) asset address used for settlement */
109
85
  readonly asset: `0x${string}`;
110
- /** EIP-712 domain name of the asset, e.g. 'MockUSDC'. */
86
+ /** EIP-712 domain name of the asset, e.g. 'MockUSDC' */
111
87
  readonly assetName: string;
112
- /** EIP-712 domain version of the asset, e.g. '2'. */
88
+ /** EIP-712 domain version of the asset, e.g. '2' */
113
89
  readonly assetVersion: string;
114
90
  readonly assetDecimals: number;
115
- /** Merchant-controlled settlement destination. Never a gateway-owned wallet. */
91
+ /** Merchant-controlled settlement destination. Never a gateway-owned wallet */
116
92
  readonly payTo: `0x${string}`;
117
93
  readonly maxTimeoutSeconds?: number;
118
94
  /**
119
- * Which facilitator verifies and broadcasts.
120
- *
121
- * `local` runs the facilitator in this process against the dev chain, and
122
- * its `signerPrivateKey` must be an Anvil well-known key — LOCAL DEVELOPMENT
123
- * ONLY — DO NOT FUND. `remote` calls an HTTP facilitator, and this gateway
124
- * then holds no signing key at all.
95
+ * Which facilitator verifies and broadcasts. `local` runs one in this process
96
+ * against a dev chain, and its `signerPrivateKey` pays gas there, usually
97
+ * an Anvil well-known key (LOCAL DEVELOPMENT ONLY - DO NOT FUND). `remote`
98
+ * calls an HTTP facilitator, and the gateway then holds no signing key.
125
99
  */
126
100
  readonly facilitator: X402FacilitatorConfig;
127
- /**
128
- * Required to be `true` before anything settles on a mainnet. Never a
129
- * default — see `guardrails.ts`.
130
- */
101
+ /** Must be `true` before anything settles on a mainnet. Never a default */
131
102
  readonly allowMainnet?: boolean;
132
- /**
133
- * Required to be `true` to settle on a mainnet through a facilitator that
134
- * takes no credential. Never a default.
135
- */
103
+ /** Required on mainnet when facilitator auth is `none` */
136
104
  readonly allowUnauthenticatedFacilitator?: boolean;
137
105
  readonly logger?: Logger;
138
106
  readonly clock?: Clock;