@devlab.group/agent-commerce 0.1.0-alpha.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.
@@ -0,0 +1,223 @@
1
+ import { IncomingMessage, ServerResponse } from 'node:http';
2
+ import { I as IsoTimestamp, j as PaymentResult, o as ProtocolName, l as PaymentSubmission, i as PaymentRequirement, A as AdapterDescriptor, R as ResourceRegistry, L as Logger, c as Clock, d as IdGenerator, a as AdapterHealth } from './runtime-LCk2TzGN.js';
3
+
4
+ /**
5
+ * Canonical commerce events.
6
+ *
7
+ * FROZEN CONTRACT. Every event in a single flow shares one `requestId` so that
8
+ * logs, payment attempts, backend calls and receipts are correlatable
9
+ *.
10
+ */
11
+
12
+ declare const COMMERCE_EVENT_TYPES: readonly ["resource.discovered", "resource.requested", "payment.required", "payment.rejected", "payment.verified", "payment.settled", "backend.called", "backend.failed", "resource.delivered"];
13
+ type CommerceEventType = (typeof COMMERCE_EVENT_TYPES)[number];
14
+ interface CommerceEvent {
15
+ readonly id: string;
16
+ readonly type: CommerceEventType;
17
+ readonly requestId: string;
18
+ readonly resourceId?: string;
19
+ readonly at: IsoTimestamp;
20
+ /** Protocol adapter that originated the request, e.g. 'mcp' or 'http'. */
21
+ readonly adapter?: string;
22
+ readonly paymentProvider?: string;
23
+ readonly durationMs?: number;
24
+ readonly status?: 'ok' | 'error';
25
+ /** Non-secret, structured detail. Must never contain keys, headers or proofs. */
26
+ readonly data?: Readonly<Record<string, unknown>>;
27
+ }
28
+ /**
29
+ * Sink for canonical events.
30
+ *
31
+ * Implementations must be non-throwing from the caller's perspective: an event
32
+ * sink failure must never fail an otherwise successful commerce flow.
33
+ */
34
+ interface EventSink {
35
+ emit(event: CommerceEvent): Promise<void>;
36
+ }
37
+
38
+ /**
39
+ * Canonical receipt model.
40
+ *
41
+ * FROZEN CONTRACT.
42
+ */
43
+
44
+ interface CommerceReceipt {
45
+ readonly id: string;
46
+ readonly requestId: string;
47
+ readonly resourceId: string;
48
+ /** Absent for free resources. */
49
+ readonly payment?: PaymentResult;
50
+ readonly deliveredAt: IsoTimestamp;
51
+ readonly backendStatus: number;
52
+ readonly durationMs?: number;
53
+ readonly protocol?: string;
54
+ /** Non-secret summary only. Never the full backend body if it is sensitive. */
55
+ readonly metadata?: Readonly<Record<string, unknown>>;
56
+ }
57
+ /** Record of a single payment authorisation seen by the gateway. */
58
+ interface PaymentAttempt {
59
+ readonly id: string;
60
+ readonly requestId: string;
61
+ readonly resourceId: string;
62
+ readonly provider: string;
63
+ /** See PaymentResult.replayKey — unique across the store. */
64
+ readonly replayKey: string;
65
+ /**
66
+ * Terminal state of the authorisation.
67
+ *
68
+ * `settlement-uncertain` is deliberately distinct from `failed`: it means the
69
+ * settlement transaction was broadcast but its outcome could not be
70
+ * confirmed (RPC timeout, dropped connection). "The RPC did not answer" and
71
+ * "the transfer did not happen" are different facts, and recording the first
72
+ * as the second makes the merchant's reconciliation artefact wrong in exactly
73
+ * the case where reconciliation matters. When this status is set,
74
+ * `externalReference` carries the broadcast transaction hash so the outcome
75
+ * can be resolved later.
76
+ */
77
+ readonly status: 'reserved' | 'verified' | 'settled' | 'rejected' | 'failed' | 'settlement-uncertain';
78
+ readonly amount: string;
79
+ readonly currency: string;
80
+ readonly payer?: string;
81
+ readonly payee?: string;
82
+ readonly externalReference?: string;
83
+ readonly rejectionReason?: string;
84
+ readonly createdAt: IsoTimestamp;
85
+ readonly updatedAt: IsoTimestamp;
86
+ }
87
+
88
+ /**
89
+ * Canonical request/response model for the execution pipeline.
90
+ *
91
+ * FROZEN CONTRACT. Protocol adapters normalise into `CanonicalRequest` and map
92
+ * `ExecutionOutcome` (or a thrown `CommerceError`) back into their own wire
93
+ * format. Adapters must never call merchant backends directly.
94
+ */
95
+
96
+ interface CanonicalRequest {
97
+ /** Correlation id for the entire flow. Generated by the protocol adapter. */
98
+ readonly requestId: string;
99
+ readonly resourceId: string;
100
+ /** Raw, unvalidated resource input. Validated against the resource schema. */
101
+ readonly input: unknown;
102
+ readonly protocol: ProtocolName;
103
+ /** Payment proof, when the client is retrying after a challenge. */
104
+ readonly payment?: PaymentSubmission;
105
+ readonly receivedAt: IsoTimestamp;
106
+ /** Non-secret transport metadata (client id, user agent, …). */
107
+ readonly metadata?: Readonly<Record<string, unknown>>;
108
+ }
109
+ /** Successful delivery of a resource. */
110
+ interface DeliveredOutcome {
111
+ readonly kind: 'delivered';
112
+ readonly requestId: string;
113
+ readonly resourceId: string;
114
+ readonly backendStatus: number;
115
+ readonly body: unknown;
116
+ readonly headers?: Readonly<Record<string, string>>;
117
+ readonly payment?: PaymentResult;
118
+ readonly receipt: CommerceReceipt;
119
+ readonly durationMs: number;
120
+ }
121
+ /** The resource costs money and no acceptable proof was supplied. */
122
+ interface PaymentRequiredOutcome {
123
+ readonly kind: 'payment-required';
124
+ readonly requestId: string;
125
+ readonly resourceId: string;
126
+ readonly requirement: PaymentRequirement;
127
+ }
128
+ /**
129
+ * Result of a pipeline execution.
130
+ *
131
+ * Every other condition (unknown resource, invalid input, rejected payment,
132
+ * backend failure, storage failure) is signalled by throwing a `CommerceError`.
133
+ */
134
+ type ExecutionOutcome = DeliveredOutcome | PaymentRequiredOutcome;
135
+ /**
136
+ * The single execution path every protocol adapter converges on.
137
+ *
138
+ * NOTE — two different signalling styles, deliberately:
139
+ *
140
+ * - `payment-required` is a normal RETURN VALUE (`PaymentRequiredOutcome`).
141
+ * It is an expected step in the protocol, not a failure: the caller is
142
+ * meant to read the challenge and retry with a proof.
143
+ * - Everything else that goes wrong — including a *rejected* payment — is a
144
+ * THROWN `CommerceError`.
145
+ *
146
+ * So `payment-required` and `payment-invalid` arrive through different
147
+ * channels despite sounding symmetrical. Adapters must handle both:
148
+ *
149
+ * try {
150
+ * const outcome = await pipeline.execute(request);
151
+ * if (outcome.kind === 'payment-required') return toPaymentRequiredEnvelope(outcome);
152
+ * return renderDelivered(outcome);
153
+ * } catch (error) {
154
+ * return toErrorEnvelope(toCommerceError(error));
155
+ * }
156
+ */
157
+ interface ExecutionPipeline {
158
+ execute(request: CanonicalRequest): Promise<ExecutionOutcome>;
159
+ }
160
+
161
+ /**
162
+ * Protocol adapter boundary.
163
+ *
164
+ * FROZEN CONTRACT. An adapter translates a protocol's wire format into a
165
+ * `CanonicalRequest`, hands it to the execution pipeline and maps the outcome
166
+ * back. It must not call merchant backends, implement payment logic, or hold
167
+ * its own copy of the canonical model.
168
+ *
169
+ * Adapter isolation: a failure while starting or serving one adapter must not
170
+ * prevent the others from operating.
171
+ */
172
+
173
+ /** Everything an adapter is given. Nothing else is available to it. */
174
+ interface ProtocolAdapterContext {
175
+ readonly pipeline: ExecutionPipeline;
176
+ readonly resources: ResourceRegistry;
177
+ readonly events: EventSink;
178
+ readonly logger: Logger;
179
+ readonly clock: Clock;
180
+ readonly ids: IdGenerator;
181
+ /** Externally reachable base URL of the gateway, from config. */
182
+ readonly publicBaseUrl: string;
183
+ }
184
+ interface ProtocolAdapter {
185
+ readonly name: ProtocolName;
186
+ readonly descriptor: AdapterDescriptor;
187
+ start(context: ProtocolAdapterContext): Promise<void>;
188
+ health(): Promise<AdapterHealth>;
189
+ stop(): Promise<void>;
190
+ }
191
+ /**
192
+ * A protocol adapter served over HTTP.
193
+ *
194
+ * The gateway mounts `handleHttp` at `mountPath` using raw Node request and
195
+ * response objects, so adapters stay independent of the HTTP framework.
196
+ *
197
+ * GUARANTEE — the request body is **unconsumed**.
198
+ *
199
+ * `req` is handed over with its stream unread: the gateway suppresses every
200
+ * body parser on this mount, so an adapter whose SDK reads the body itself
201
+ * (MCP's Streamable HTTP transport does) can do so. The adapter owns reading,
202
+ * size-limiting beyond the gateway's own cap, and parsing.
203
+ *
204
+ * This is load-bearing and easy to break silently. Fastify pre-registers
205
+ * exact-match parsers for `application/json` and `text/plain` and prefers them
206
+ * over a `'*'` wildcard, so registering only a wildcard no-op leaves the
207
+ * built-in JSON parser draining the body first — the adapter then reads an
208
+ * empty stream and every request fails to parse. That exact regression shipped
209
+ * once and no unit test caught it, because adapter conformance suites drive
210
+ * `handleHttp` over a bare `node:http` server and never traverse the gateway.
211
+ *
212
+ * Any change to how adapters are mounted must be covered by a test that POSTs
213
+ * a real JSON body through the real gateway and asserts the adapter received
214
+ * it intact.
215
+ */
216
+ interface HttpProtocolAdapter extends ProtocolAdapter {
217
+ /** Path prefix the gateway mounts this adapter at, e.g. '/mcp'. */
218
+ readonly mountPath: string;
219
+ handleHttp(req: IncomingMessage, res: ServerResponse): Promise<void>;
220
+ }
221
+ declare function isHttpProtocolAdapter(adapter: ProtocolAdapter): adapter is HttpProtocolAdapter;
222
+
223
+ export { type CommerceEvent as C, type DeliveredOutcome as D, type ExecutionPipeline as E, type HttpProtocolAdapter as H, type PaymentRequiredOutcome as P, type PaymentAttempt as a, type CommerceReceipt as b, type ProtocolAdapter as c, COMMERCE_EVENT_TYPES as d, type CanonicalRequest as e, type CommerceEventType as f, type EventSink as g, type ExecutionOutcome as h, type ProtocolAdapterContext as i, isHttpProtocolAdapter as j };
@@ -0,0 +1,277 @@
1
+ /**
2
+ * Shared primitive aliases used across the canonical domain model.
3
+ *
4
+ * FROZEN CONTRACT. Every consumer codes against these shapes; changing one
5
+ * is a breaking change.
6
+ */
7
+ /**
8
+ * A JSON Schema document (draft 2020-12 subset in practice).
9
+ *
10
+ * Deliberately loose: protocol adapters translate this to their own schema
11
+ * representation, and the gateway only validates structurally at trust
12
+ * boundaries. Never treat this as trusted input without validation.
13
+ */
14
+ type JsonSchema = Record<string, unknown>;
15
+ /** Protocol surfaces a resource can be exposed through in v0.1. */
16
+ type ProtocolName = 'http' | 'mcp';
17
+ /** Payment methods a resource can accept in v0.1. */
18
+ type PaymentMethodName = 'x402';
19
+ /** ISO-8601 timestamp string, always UTC with millisecond precision. */
20
+ type IsoTimestamp = string;
21
+ /**
22
+ * A decimal amount expressed as a string in the *display* unit of the currency
23
+ * (for example "0.01" USDC), never as a float and never in base units.
24
+ *
25
+ * Conversion to on-chain base units is a payment-provider responsibility.
26
+ */
27
+ type DecimalAmount = string;
28
+ /** Health of an individual adapter or subsystem. */
29
+ interface AdapterHealth {
30
+ readonly status: 'pass' | 'warn' | 'fail';
31
+ readonly detail?: string;
32
+ readonly checkedAt: IsoTimestamp;
33
+ readonly durationMs?: number;
34
+ }
35
+ /**
36
+ * Self-description every adapter must expose so diagnostics can report exactly
37
+ * what is supported instead of implying blanket protocol compatibility.
38
+ *
39
+ *
40
+ */
41
+ interface AdapterDescriptor {
42
+ readonly name: string;
43
+ readonly kind: 'protocol' | 'payment' | 'storage';
44
+ /** Version of this adapter implementation (independent of the spec). */
45
+ readonly implementationVersion: string;
46
+ /** Exact pinned specification revision this adapter targets. */
47
+ readonly supportedSpec: string;
48
+ readonly capabilities: readonly string[];
49
+ readonly status: 'stable' | 'experimental' | 'planned';
50
+ /** Capabilities explicitly NOT implemented, surfaced by `doctor`. */
51
+ readonly unsupported?: readonly string[];
52
+ }
53
+
54
+ /**
55
+ * Canonical resource model.
56
+ *
57
+ * FROZEN CONTRACT.
58
+ */
59
+
60
+ /** HTTP methods a backend handler may use. */
61
+ type BackendMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
62
+ /**
63
+ * Describes how the gateway calls the merchant's existing backend.
64
+ *
65
+ * Backend URLs are administrator-controlled configuration only. User- or
66
+ * agent-controlled backend URLs are forbidden (see docs/security.md, SSRF).
67
+ * Secret header values must come from `${ENV_VAR}` placeholders resolved by
68
+ * the config loader, never from plaintext configuration.
69
+ */
70
+ interface BackendHandler {
71
+ readonly type: 'http';
72
+ readonly method: BackendMethod;
73
+ readonly url: string;
74
+ readonly headers?: Readonly<Record<string, string>>;
75
+ /** Hard upper bound on the backend call. Defaults to DEFAULT_BACKEND_TIMEOUT_MS. */
76
+ readonly timeoutMs?: number;
77
+ }
78
+ /** Default backend timeout when a resource does not specify one. */
79
+ declare const DEFAULT_BACKEND_TIMEOUT_MS = 10000;
80
+ /**
81
+ * Canonical pricing.
82
+ *
83
+ * `dynamic` exists in the type system for forward compatibility but is
84
+ * REJECTED by config validation in v0.1.0-alpha.
85
+ */
86
+ type Pricing = {
87
+ readonly type: 'free';
88
+ } | {
89
+ readonly type: 'fixed';
90
+ readonly amount: DecimalAmount;
91
+ readonly currency: string;
92
+ } | {
93
+ readonly type: 'dynamic';
94
+ readonly resolver: string;
95
+ };
96
+ /**
97
+ * A merchant capability exposed to agents.
98
+ *
99
+ * The canonical resource is the single source of truth: protocol adapters map
100
+ * it outward, they never define their own parallel notion of a resource.
101
+ */
102
+ interface CommerceResource {
103
+ readonly id: string;
104
+ readonly name: string;
105
+ readonly description?: string;
106
+ readonly inputSchema?: JsonSchema;
107
+ readonly outputSchema?: JsonSchema;
108
+ readonly handler: BackendHandler;
109
+ readonly pricing: Pricing;
110
+ readonly exposedVia: readonly ProtocolName[];
111
+ readonly paymentMethods: readonly PaymentMethodName[];
112
+ }
113
+ /** Read-only view of every configured resource. */
114
+ interface ResourceRegistry {
115
+ get(id: string): CommerceResource | undefined;
116
+ list(): readonly CommerceResource[];
117
+ /** Resources exposed through a given protocol surface. */
118
+ listExposedVia(protocol: ProtocolName): readonly CommerceResource[];
119
+ has(id: string): boolean;
120
+ }
121
+
122
+ /**
123
+ * Canonical payment model.
124
+ *
125
+ * FROZEN CONTRACT.
126
+ *
127
+ * Core decides *that* a payment is required and for how much.
128
+ * Payment providers decide *how* the challenge is encoded, verified and settled.
129
+ * No x402/EVM-specific type may appear in this file.
130
+ */
131
+
132
+ /**
133
+ * Provider-native payment challenge, opaque to core.
134
+ *
135
+ * For x402 the `accepts` entries are x402 `PaymentRequirements` objects; core
136
+ * passes them through to protocol adapters verbatim and never inspects them.
137
+ */
138
+ interface PaymentChallenge {
139
+ readonly provider: PaymentMethodName;
140
+ /** Provider protocol version, e.g. the x402 `x402Version` value as a string. */
141
+ readonly version: string;
142
+ readonly accepts: readonly Readonly<Record<string, unknown>>[];
143
+ }
144
+ /**
145
+ * What the buyer must pay, in canonical terms, plus the provider-native
146
+ * challenge the buyer's client needs in order to construct a payment.
147
+ */
148
+ interface PaymentRequirement {
149
+ readonly id: string;
150
+ readonly requestId: string;
151
+ readonly resourceId: string;
152
+ readonly provider: PaymentMethodName;
153
+ readonly amount: DecimalAmount;
154
+ readonly currency: string;
155
+ /** Merchant-controlled settlement destination. Never a gateway-owned wallet. */
156
+ readonly destination: string;
157
+ readonly network?: string;
158
+ readonly asset?: string;
159
+ readonly expiresAt?: IsoTimestamp;
160
+ readonly challenge: PaymentChallenge;
161
+ readonly metadata?: Readonly<Record<string, unknown>>;
162
+ }
163
+ /**
164
+ * Opaque payment proof supplied by the buyer's client.
165
+ *
166
+ * For x402 over HTTP this is the base64 `X-PAYMENT` header value; over MCP it
167
+ * is the same string carried in the tool input's `_payment` field.
168
+ */
169
+ interface PaymentSubmission {
170
+ readonly method: PaymentMethodName;
171
+ readonly payload: string;
172
+ }
173
+ /** Outcome of verification or settlement. */
174
+ interface PaymentResult {
175
+ readonly status: 'verified' | 'settled' | 'rejected';
176
+ readonly provider: PaymentMethodName;
177
+ /** Settlement reference, e.g. an on-chain transaction hash. */
178
+ readonly externalReference?: string;
179
+ readonly payer?: string;
180
+ readonly payee?: string;
181
+ readonly amount: DecimalAmount;
182
+ readonly currency: string;
183
+ readonly network?: string;
184
+ readonly asset?: string;
185
+ /**
186
+ * Stable, provider-computed identity of the payment authorisation itself.
187
+ *
188
+ * The gateway reserves this key before settlement and rejects any second
189
+ * request presenting the same key (see PAYMENT_REPLAYED). Providers MUST
190
+ * derive it only from the authorisation (payer, nonce, asset, network) so
191
+ * that the same authorisation always maps to the same key.
192
+ */
193
+ readonly replayKey?: string;
194
+ /** Machine-readable rejection reason when status is `rejected`. */
195
+ readonly rejectionReason?: string;
196
+ readonly settledAt?: IsoTimestamp;
197
+ readonly metadata?: Readonly<Record<string, unknown>>;
198
+ }
199
+ /** Input to {@link PaymentProvider.createRequirement}. */
200
+ interface PaymentContext {
201
+ readonly requestId: string;
202
+ readonly resource: CommerceResource;
203
+ readonly amount: DecimalAmount;
204
+ readonly currency: string;
205
+ readonly requestedAt: IsoTimestamp;
206
+ readonly metadata?: Readonly<Record<string, unknown>>;
207
+ }
208
+ /** Input to {@link PaymentProvider.verify}. */
209
+ interface PaymentVerificationContext {
210
+ readonly requestId: string;
211
+ readonly resource: CommerceResource;
212
+ readonly requirement: PaymentRequirement;
213
+ readonly submission: PaymentSubmission;
214
+ }
215
+ /** Input to {@link PaymentProvider.settle}. */
216
+ interface PaymentSettlementContext extends PaymentVerificationContext {
217
+ readonly verification: PaymentResult;
218
+ }
219
+ /**
220
+ * Contract every payment rail implements.
221
+ *
222
+ * Implementations must be non-custodial: they orchestrate an external payment
223
+ * protocol and must never hold buyer or merchant production signing keys.
224
+ */
225
+ interface PaymentProvider {
226
+ readonly name: PaymentMethodName;
227
+ readonly descriptor: AdapterDescriptor;
228
+ /** Build the challenge presented to an unpaid request. */
229
+ createRequirement(context: PaymentContext): Promise<PaymentRequirement>;
230
+ /**
231
+ * Validate a submitted proof against the requirement.
232
+ *
233
+ * Must return `rejected` (or throw a CommerceError) rather than throwing an
234
+ * untyped error. Must never have side effects that move funds.
235
+ */
236
+ verify(context: PaymentVerificationContext): Promise<PaymentResult>;
237
+ /** Execute settlement. Called only after `verify` returned `verified`. */
238
+ settle(context: PaymentSettlementContext): Promise<PaymentResult>;
239
+ health(): Promise<AdapterHealth>;
240
+ }
241
+
242
+ /**
243
+ * Minimal structural logger interface.
244
+ *
245
+ * Core must not depend on pino directly; the gateway injects a pino instance
246
+ * that satisfies this shape. Never log secrets: private keys, seed phrases,
247
+ * Authorization headers or payment authorisation payloads.
248
+ */
249
+ interface Logger {
250
+ debug(obj: Record<string, unknown>, msg?: string): void;
251
+ info(obj: Record<string, unknown>, msg?: string): void;
252
+ warn(obj: Record<string, unknown>, msg?: string): void;
253
+ error(obj: Record<string, unknown>, msg?: string): void;
254
+ child(bindings: Record<string, unknown>): Logger;
255
+ }
256
+ /** A logger that discards everything. Useful in unit tests. */
257
+ declare const NOOP_LOGGER: Logger;
258
+
259
+ /**
260
+ * Injected runtime primitives.
261
+ *
262
+ * Everything non-deterministic (time, ids) is injected so tests can be exact.
263
+ */
264
+
265
+ interface Clock {
266
+ now(): Date;
267
+ nowIso(): IsoTimestamp;
268
+ /** Milliseconds since an arbitrary origin; use for durations only. */
269
+ monotonicMs(): number;
270
+ }
271
+ interface IdGenerator {
272
+ /** Opaque, collision-resistant identifier. */
273
+ next(prefix?: string): string;
274
+ }
275
+ declare const systemClock: Clock;
276
+
277
+ export { type AdapterDescriptor as A, type BackendHandler as B, type CommerceResource 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 AdapterHealth as a, type PaymentProvider as b, type Clock as c, type IdGenerator as d, type BackendMethod as e, DEFAULT_BACKEND_TIMEOUT_MS as f, type PaymentChallenge as g, type PaymentContext as h, type PaymentRequirement as i, type PaymentResult as j, type PaymentSettlementContext as k, type PaymentSubmission as l, type PaymentVerificationContext as m, type Pricing as n, type ProtocolName as o, systemClock as s };
package/dist/x402.d.ts ADDED
@@ -0,0 +1,77 @@
1
+ import { L as Logger, c as Clock, d as IdGenerator, b as PaymentProvider } from './runtime-LCk2TzGN.js';
2
+
3
+ /**
4
+ * CLIENT-SIDE payment helper.
5
+ *
6
+ * This module is used by the demo buyer agent (`demo/agent`) and by the
7
+ * payment E2E test suite to build and EIP-712-sign an x402 `exact`/EVM
8
+ * payment authorisation, entirely on the buyer's side.
9
+ *
10
+ * The gateway NEVER calls this module and NEVER holds a buyer private key.
11
+ * `buyerPrivateKey` here is always an Anvil well-known
12
+ * development key (LOCAL DEVELOPMENT ONLY — DO NOT FUND) supplied by whoever
13
+ * is driving the demo/test, not something the provider or gateway manages.
14
+ */
15
+ interface CreatePaymentProofOptions {
16
+ /** Buyer's dev-only private key. LOCAL DEVELOPMENT ONLY — DO NOT FUND. */
17
+ readonly buyerPrivateKey: `0x${string}`;
18
+ readonly rpcUrl: string;
19
+ /** One entry from PaymentRequiredEnvelope.payment.accepts, verbatim. */
20
+ readonly accepts: Readonly<Record<string, unknown>>;
21
+ /** Overrides used only by negative tests (wrong amount/recipient/nonce…). */
22
+ readonly overrides?: {
23
+ readonly value?: string;
24
+ readonly payTo?: string;
25
+ readonly nonce?: `0x${string}`;
26
+ readonly validBefore?: number;
27
+ readonly validAfter?: number;
28
+ };
29
+ }
30
+ /** Returns the base64 `X-PAYMENT` value to send back to the gateway. */
31
+ declare function createPaymentProof(options: CreatePaymentProofOptions): Promise<string>;
32
+
33
+ /**
34
+ * x402 payment provider — `exact` scheme, EVM, EIP-3009 `transferWithAuthorization`.
35
+ *
36
+ * Implements the frozen `PaymentProvider` interface (src/core/domain/payment.ts).
37
+ * `verify()` never moves funds; only `settle()` does, and only after a
38
+ * successful `verify()` (enforced by the gateway's execution pipeline, not by
39
+ * this file, but this file never calls settle-like RPCs from verify()).
40
+ *
41
+ * The behaviour of x402@1.2.0 relied on here is verified, not assumed: see the
42
+ * SDK-behaviour notes beside each call site below.
43
+ */
44
+
45
+ interface X402ProviderOptions {
46
+ /** x402 network name. Local deterministic chain uses 'base-sepolia'. */
47
+ readonly network: string;
48
+ /** RPC endpoint. Local chain: http://127.0.0.1:8545 */
49
+ readonly rpcUrl: string;
50
+ /** ERC-20 (EIP-3009) asset address used for settlement. */
51
+ readonly asset: `0x${string}`;
52
+ /** EIP-712 domain name of the asset, e.g. 'MockUSDC'. */
53
+ readonly assetName: string;
54
+ /** EIP-712 domain version of the asset, e.g. '2'. */
55
+ readonly assetVersion: string;
56
+ readonly assetDecimals: number;
57
+ /** Merchant-controlled settlement destination. Never a gateway-owned wallet. */
58
+ readonly payTo: `0x${string}`;
59
+ readonly maxTimeoutSeconds?: number;
60
+ /**
61
+ * Local facilitator: signer broadcasts settlement on the dev chain only.
62
+ * LOCAL DEVELOPMENT ONLY — DO NOT FUND.
63
+ */
64
+ readonly facilitator: {
65
+ readonly mode: 'local';
66
+ readonly signerPrivateKey: `0x${string}`;
67
+ } | {
68
+ readonly mode: 'remote';
69
+ readonly url: string;
70
+ };
71
+ readonly logger?: Logger;
72
+ readonly clock?: Clock;
73
+ readonly ids?: IdGenerator;
74
+ }
75
+ declare function createX402PaymentProvider(options: X402ProviderOptions): PaymentProvider;
76
+
77
+ export { type CreatePaymentProofOptions, type X402ProviderOptions, createPaymentProof, createX402PaymentProvider, createX402PaymentProvider as x402 };