uvd-x402-sdk 2.85.0 → 2.86.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.
@@ -1,3474 +1,3 @@
1
- import { S as SigningWalletAdapter } from '../wallet-w7BnImDG.mjs';
2
- import { X as X402Version, i as X402Header, j as X402PayloadData } from '../index-DOBhTF-j.mjs';
3
-
4
- /**
5
- * Reading a facilitator refusal as DATA instead of prose.
6
- *
7
- * # Why this file exists
8
- *
9
- * `402` and `503` say opposite things and the SDK used to collapse both into
10
- * `success: false` plus an English sentence.
11
- *
12
- * - **402** means the payment was REJECTED. The credential is spent; sign a new
13
- * authorization.
14
- * - **503** means NO VERDICT WAS REACHED. Nothing was rejected and nothing was
15
- * executed; retry the SAME credential.
16
- *
17
- * Turning a 503 into a 402 makes the buyer sign and send a second payment for a
18
- * money movement that was never refused — they pay twice. That is the most
19
- * expensive mistake this SDK can make, so every facilitator edge now reports the
20
- * status, the facilitator's own `reason`, and whether the request may be
21
- * replayed.
22
- *
23
- * # The writer lease
24
- *
25
- * The facilitator serialises every EVM write through the one process that holds
26
- * the EVM writer lease, because they all spend gas from the same EOA and the
27
- * nonce for it is allocated in memory. A task that does not hold the lease
28
- * forwards the request to the one that does; when it cannot, it answers
29
- * `503` + `Retry-After: 5` + `{"error": "...", "reason": "<why>"}`.
30
- *
31
- * The five reasons do NOT share retry semantics, which is the whole point of
32
- * surfacing them:
33
- *
34
- * | reason | did the write run? | replay? |
35
- * |----------------------------|--------------------|---------|
36
- * | `holder_unknown` | no | yes |
37
- * | `forwarding_disabled` | no | yes |
38
- * | `forwarded_but_not_writer` | no | yes |
39
- * | `body_unreadable` | no | yes |
40
- * | `forward_failed` | **maybe** | **no** |
41
- *
42
- * `forward_failed` is emitted after the forward was attempted: the holder may
43
- * have executed the write and the response been lost on the way back. It is a
44
- * timeout wearing a status code. Replaying a `/register` on it is exactly the
45
- * sequence that once minted five duplicate agents — reconcile with
46
- * `GET /identity/{network}/owner/{recipient}` or `getRegisterStatus` instead.
47
- *
48
- * # The two `502`s of `/settle`, which mean opposite things
49
- *
50
- * | body `error` | `Retry-After` | did the money move? | retry? |
51
- * |----------------------------|---------------|---------------------|-----------|
52
- * | `upstream_rpc_unavailable` | `30` | no, never broadcast | **yes** |
53
- * | `settlement_unconfirmed` | **absent** | **maybe — mined?** | **NEVER** |
54
- *
55
- * `settlement_unconfirmed` is answered after the transaction was broadcast and
56
- * no receipt ever arrived, so it MAY be mined. Retrying re-signs a new
57
- * authorization with a fresh nonce, which the chain accepts as a second,
58
- * perfectly valid payment for the same purchase — the buyer pays twice, in
59
- * exactly the case the facilitator emits it to prevent. The `transaction` hash
60
- * and `paymentId` travel in the body so the caller can LOOK AT THE CHAIN; they
61
- * are not an invitation to send it again.
62
- *
63
- * The status cannot tell the two apart, which is why this file used to get it
64
- * wrong: every `502` was retryable, and until `settlement_unconfirmed` existed
65
- * that was correct. **Branch on the body.**
66
- *
67
- * The general form of that rule — **a 5xx whose body carries a transaction hash
68
- * was broadcast, whatever the error is called** — is adopted from the Python
69
- * SDK, which has carried it as its anti-double-settle guard
70
- * (`uvd_x402_sdk/client.py`, `_is_retryable_settle_error`) while this one had
71
- * only the status to go on.
72
- *
73
- * Source of the shape: x402-rs `src/handlers.rs` `writer_lease_unavailable()`
74
- * and `require_writer_lease()`; `SettlementUnconfirmedResponse` in
75
- * `src/types.rs`, built in the `IntoResponse` of `FacilitatorLocalError`.
76
- */
77
- /**
78
- * A `reason` the facilitator attaches to a writer-lease 503.
79
- *
80
- * Typed as a union for discrimination but never used to VALIDATE: the fields
81
- * that carry it are plain `string`, so a reason added on the server does not
82
- * break compilation here.
83
- */
84
- type WriterLeaseReason = 'holder_unknown' | 'forwarding_disabled' | 'forwarded_but_not_writer' | 'body_unreadable' | 'forward_failed';
85
- /** Every writer-lease reason the facilitator emits today. */
86
- declare const WRITER_LEASE_REASONS: readonly WriterLeaseReason[];
87
- /**
88
- * The reasons returned BEFORE the write is handed to anyone.
89
- *
90
- * The facilitator refuses these in its router, so the request provably did not
91
- * execute and re-sending the identical body is safe — including a mint.
92
- */
93
- declare const REPLAYABLE_LEASE_REASONS: readonly WriterLeaseReason[];
94
- /**
95
- * The reason that is ambiguous: the write may already have happened.
96
- *
97
- * Still `retryable` — the credential was not rejected — but never replayed
98
- * automatically. Resolve it by reading state, not by re-POSTing.
99
- */
100
- declare const AMBIGUOUS_LEASE_REASONS: readonly WriterLeaseReason[];
101
- /**
102
- * The facilitator's `error` code for a settle it broadcast and could not confirm.
103
- *
104
- * The transaction may be mined. This is the one upstream failure that must
105
- * never be retried; reconcile with `transaction` / `paymentId` instead.
106
- */
107
- declare const SETTLEMENT_UNCONFIRMED = "settlement_unconfirmed";
108
- /**
109
- * Ceiling, in seconds, on how long an automatic retry will wait.
110
- *
111
- * `Retry-After` is a hint from a server that may be misconfigured. Honouring a
112
- * literal `Retry-After: 3600` would hang the caller's request for an hour
113
- * inside a function documented as returning promptly, so the header is honoured
114
- * only up to this bound.
115
- */
116
- declare const MAX_RETRY_AFTER_SECONDS = 15;
117
- /** Wait used when a 503 carries no usable `Retry-After`. */
118
- declare const DEFAULT_RETRY_AFTER_SECONDS = 5;
119
- /** How many EXTRA attempts a retryable facilitator refusal gets by default. */
120
- declare const DEFAULT_FACILITATOR_RETRIES = 2;
121
- /**
122
- * A non-2xx answer from the facilitator, kept structured.
123
- *
124
- * `error` is byte-identical to the string this SDK has always produced, so
125
- * callers matching on it keep working; everything else is new and optional.
126
- */
127
- interface FacilitatorErrorInfo {
128
- /** Legacy flattened message: `Facilitator error: <status> - <body>`. */
129
- error: string;
130
- /** HTTP status the facilitator answered with. */
131
- status: number;
132
- /** The facilitator's own `reason`, when the body carried one. */
133
- reason?: string;
134
- /**
135
- * The facilitator's machine-readable `error` code, verbatim.
136
- *
137
- * Some codes carry a `(ref: <uuid>)` suffix, so compare with care —
138
- * {@link SETTLEMENT_UNCONFIRMED} is emitted bare. Branch on this rather than
139
- * on the status: `/settle` has two `502`s that mean opposite things.
140
- */
141
- errorCode?: string;
142
- /**
143
- * The hash of a transaction that WAS broadcast, in that chain's own encoding.
144
- *
145
- * Present on {@link SETTLEMENT_UNCONFIRMED}. Not always `0x`-prefixed:
146
- * Algorand prints base32 and Solana base58, and reformatting it makes it
147
- * unpasteable in an explorer — which is the entire remedy on offer.
148
- */
149
- transaction?: string;
150
- /** `keccak256(caip2 ‖ txHash)`, the same id a successful settle would print. */
151
- paymentId?: string;
152
- /**
153
- * Seconds to wait before retrying, already clamped to
154
- * {@link MAX_RETRY_AFTER_SECONDS}. Absent when the answer is not retryable.
155
- */
156
- retryAfterSeconds?: number;
157
- /**
158
- * The request reached no verdict; the credential is untouched and the SAME
159
- * request may be sent again. Never surface this as a payment rejection.
160
- */
161
- retryable: boolean;
162
- /**
163
- * The facilitator NAMED a reason that proves it executed nothing, so an
164
- * automatic replay cannot double-write.
165
- *
166
- * False for `forward_failed`, whose write may already have landed, and false
167
- * for an unattributed 5xx from a proxy — "something in front answered" is not
168
- * evidence that nothing ran.
169
- */
170
- safeToReplay: boolean;
171
- /** Raw response body, for logs. */
172
- body: string;
173
- }
174
- /** Fields every facilitator response type gained so a 503 stops looking terminal. */
175
- interface FacilitatorFailureFields {
176
- /** HTTP status, when the failure was transport-level rather than a verdict. */
177
- status?: number;
178
- /** The facilitator's `reason` for the refusal (see {@link WriterLeaseReason}). */
179
- reason?: string;
180
- /** The facilitator's machine-readable `error` code (see {@link FacilitatorErrorInfo.errorCode}). */
181
- errorCode?: string;
182
- /**
183
- * A transaction that WAS broadcast and could not be confirmed. Look it up on
184
- * chain; do NOT send the payment again. See {@link SETTLEMENT_UNCONFIRMED}.
185
- */
186
- transaction?: string;
187
- /** The payment id for that transaction, identical to the one a settle prints. */
188
- paymentId?: string;
189
- /** True when the same request may be sent again without re-signing anything. */
190
- retryable?: boolean;
191
- /** Seconds to wait before retrying, clamped to {@link MAX_RETRY_AFTER_SECONDS}. */
192
- retryAfterSeconds?: number;
193
- /** True when the facilitator provably executed nothing. */
194
- safeToReplay?: boolean;
195
- }
196
- /** A 503/429 that carries a reason known to be pre-execution. */
197
- declare function isReplayableLeaseReason(reason?: string): boolean;
198
- /** A 503 whose write may already have run. Reconcile, do not re-POST. */
199
- declare function isAmbiguousLeaseReason(reason?: string): boolean;
200
- /**
201
- * Read `Retry-After` and clamp it.
202
- *
203
- * Tolerates a `Response`-shaped object with no `headers` at all: test doubles
204
- * and non-standard fetch polyfills routinely omit it, and throwing there would
205
- * turn a readable refusal into an unreadable crash.
206
- */
207
- declare function parseRetryAfterSeconds(response: {
208
- headers?: {
209
- get?: (name: string) => string | null;
210
- };
211
- }): number | undefined;
212
- /** Everything this SDK reads out of a facilitator error body. */
213
- interface ParsedFacilitatorErrorBody {
214
- /** The `error` code, verbatim. */
215
- errorCode?: string;
216
- /** The writer-lease `reason`. */
217
- reason?: string;
218
- /** A broadcast transaction hash, in its own chain's encoding. */
219
- transaction?: string;
220
- /** The payment id for that hash. */
221
- paymentId?: string;
222
- /**
223
- * The facilitator's OWN retry verdict, when it stated one.
224
- *
225
- * `undefined` on every body that does not carry the field — which is most of
226
- * them, so absence means "the facilitator did not say", never "no".
227
- */
228
- retryable?: boolean;
229
- }
230
- /**
231
- * Read a JSON error body, tolerating anything that is not one.
232
- *
233
- * Exported so {@link FacilitatorErrorInfo} and `Erc8004LookupError` read the
234
- * SAME fields the same way. Two subtly different parses of the same body is how
235
- * one code path stops honouring a `retryable: false` the other one honours.
236
- */
237
- declare function parseFacilitatorErrorBody(body: string): ParsedFacilitatorErrorBody;
238
- /**
239
- * This refusal reports a transaction that may already be mined.
240
- *
241
- * The caller's move is to look up `transaction` / `paymentId` on chain. Sending
242
- * the payment again is the double-charge.
243
- */
244
- declare function isSettlementUnconfirmed(failure: {
245
- errorCode?: string;
246
- }): boolean;
247
- /**
248
- * Turn a non-2xx facilitator response into {@link FacilitatorErrorInfo}.
249
- *
250
- * Reads the body exactly once. The `error` string keeps the historical format
251
- * verbatim; reformatting it would break callers that match on it.
252
- */
253
- declare function readFacilitatorError(response: {
254
- status: number;
255
- text: () => Promise<string>;
256
- headers?: {
257
- get?: (name: string) => string | null;
258
- };
259
- }): Promise<FacilitatorErrorInfo>;
260
- /**
261
- * Copy the failure fields off one response onto another.
262
- *
263
- * Used where a wrapper returns its own shape: without this the wrapper flattens
264
- * a `503` back into a bare failure and reintroduces, one level up, exactly the
265
- * ambiguity the fields exist to remove.
266
- */
267
- declare function carryFailureFields(source: FacilitatorFailureFields): FacilitatorFailureFields;
268
- /** Options for {@link facilitatorFetch}. */
269
- interface FacilitatorFetchOptions {
270
- /** Abort the request after this many milliseconds. */
271
- timeoutMs: number;
272
- /** Extra attempts after the first. Default {@link DEFAULT_FACILITATOR_RETRIES}. */
273
- retries?: number;
274
- /**
275
- * Whether this particular refusal may be replayed.
276
- *
277
- * Default: only when the facilitator proved it executed nothing
278
- * (`info.safeToReplay`). Pass a stricter predicate on paths where even a
279
- * proven-safe replay is unwanted.
280
- */
281
- canReplay?: (info: FacilitatorErrorInfo) => boolean;
282
- /** Injected for tests. */
283
- fetchImpl?: typeof fetch;
284
- /** Injected for tests, so a retry does not really sleep. */
285
- sleepImpl?: (ms: number) => Promise<void>;
286
- }
287
- /**
288
- * POST/GET the facilitator, replaying a refusal that provably executed nothing.
289
- *
290
- * Returns the response plus, when it was not ok, the structured refusal — the
291
- * body has already been consumed to build it, so callers must not read it
292
- * again.
293
- *
294
- * Network errors and timeouts still THROW, exactly as before: callers already
295
- * have `catch` blocks that turn them into `{ success: false }`, and an
296
- * `AbortError` on the escrow paths triggers an on-chain reconciliation that
297
- * must keep firing.
298
- */
299
- declare function facilitatorFetch(url: string, init: RequestInit, options: FacilitatorFetchOptions): Promise<{
300
- response: Response;
301
- error?: FacilitatorErrorInfo;
302
- }>;
303
-
304
- /**
305
- * Payment requirements sent to the facilitator
306
- */
307
- interface PaymentRequirements {
308
- /** Payment scheme */
309
- scheme: 'exact' | 'escrow' | 'commerce';
310
- /** Network name (v1) or CAIP-2 identifier (v2) */
311
- network: string;
312
- /** Maximum amount required in atomic units (e.g., "1000000" for 1 USDC) */
313
- maxAmountRequired: string;
314
- /** Resource URL being paid for */
315
- resource: string;
316
- /** Description of what's being paid for */
317
- description: string;
318
- /** MIME type of the resource */
319
- mimeType: string;
320
- /** Recipient address for payment */
321
- payTo: string;
322
- /** Maximum timeout in seconds */
323
- maxTimeoutSeconds: number;
324
- /** Token contract address */
325
- asset: string;
326
- /** Optional output schema for the resource */
327
- outputSchema?: unknown;
328
- /** Optional extra data */
329
- extra?: unknown;
330
- }
331
- /**
332
- * Verify request body for the facilitator /verify endpoint -- the **v1**
333
- * envelope. {@link VerifyRequestV2} is the other one.
334
- */
335
- interface VerifyRequest {
336
- /**
337
- * Always `1`: this marker names the ENVELOPE, and this envelope is v1.
338
- *
339
- * Narrowed from `X402Version` on 2026-09-04. A `VerifyRequest` carrying `2`
340
- * was always an uninhabitable value -- a body declaring v2 while shaped as
341
- * v1 -- and typing it as `1 | 2` is what let the payer's marker be copied in
342
- * here. The payer's version lives in `paymentPayload.x402Version`, which is
343
- * still the full union.
344
- */
345
- x402Version: 1;
346
- paymentPayload: X402Header;
347
- paymentRequirements: PaymentRequirements;
348
- }
349
- /**
350
- * Settle request body for the facilitator /settle endpoint -- the **v1**
351
- * envelope. {@link SettleRequestV2} is the other one.
352
- */
353
- interface SettleRequest {
354
- /** Always `1` -- see {@link VerifyRequest.x402Version}. */
355
- x402Version: 1;
356
- paymentPayload: X402Header;
357
- paymentRequirements: PaymentRequirements;
358
- }
359
- /**
360
- * Verify response from the facilitator
361
- */
362
- interface VerifyResponse extends FacilitatorFailureFields {
363
- isValid: boolean;
364
- /**
365
- * Why the payment is not valid.
366
- *
367
- * Read `retryable` before showing this to anyone. When `retryable` is true the
368
- * facilitator reached NO VERDICT -- it did not reject the payment, so this
369
- * string is a transport diagnosis, not a rejection, and re-signing on it makes
370
- * the buyer pay twice.
371
- */
372
- invalidReason?: string;
373
- payer?: string;
374
- network?: string;
375
- }
376
- /**
377
- * Settle response from the facilitator
378
- */
379
- interface SettleResponse extends FacilitatorFailureFields {
380
- success: boolean;
381
- transactionHash?: string;
382
- network?: string;
383
- /**
384
- * Transport-level failure (unreachable facilitator, non-2xx, timeout).
385
- *
386
- * `success: false` with `retryable: true` is NOT a rejected payment. The
387
- * authorization is untouched and the same one must be resent; treating it as
388
- * a refusal and asking for a new signature charges the buyer twice.
389
- */
390
- error?: string;
391
- /**
392
- * The facilitator's own reason when it settled nothing — e.g. a transfer that
393
- * mined and reverted. Distinct from `error` above, which is this client
394
- * failing to ask; this one is the facilitator answering "no".
395
- */
396
- errorReason?: string;
397
- /** The address the facilitator confirmed as the payer. */
398
- payer?: string;
399
- /**
400
- * Settlement proof, present when the ERC-8004 extension asked for it.
401
- *
402
- * Typed here rather than only on {@link SettleResponseWithProof} because
403
- * `settle()` returns it whenever the facilitator sends it, and it is what
404
- * DX402's `anchorEvidence` needs to reach `verified: true`.
405
- */
406
- proofOfPayment?: ProofOfPayment;
407
- }
408
- /**
409
- * Options for building payment requirements
410
- */
411
- interface PaymentRequirementsOptions {
412
- /** Amount in human-readable format (e.g., "1.00") */
413
- amount: string;
414
- /** Recipient address */
415
- recipient: string;
416
- /** Resource URL being protected */
417
- resource: string;
418
- /** Chain name (e.g., "base") */
419
- chainName?: string;
420
- /** Description of the resource */
421
- description?: string;
422
- /** MIME type of the resource */
423
- mimeType?: string;
424
- /** Timeout in seconds (default: 300) */
425
- timeoutSeconds?: number;
426
- /** x402 version to use */
427
- x402Version?: X402Version;
428
- }
429
- /**
430
- * x402 payment option advertised in a 402 response.
431
- *
432
- * The SDK keeps the response shape richer than the minimal protocol fields so
433
- * servers can preserve settlement-critical metadata such as payTo and extra.
434
- */
435
- interface PaymentAcceptance {
436
- network: string;
437
- asset: string;
438
- amount: string;
439
- /**
440
- * Payment scheme. REQUIRED by the facilitator's v2 `PaymentRequirementsV2`.
441
- *
442
- * Optional here only so existing callers keep compiling — when it is absent,
443
- * `buildRequirementFromAcceptance` defaults it to `'exact'`. Do not treat its
444
- * optionality as "the facilitator does not need it": an accepts[] entry that
445
- * reaches a v2 client without a scheme is unpayable.
446
- */
447
- scheme?: string;
448
- payTo?: string;
449
- facilitator?: string;
450
- resource?: string;
451
- description?: string;
452
- mimeType?: string;
453
- maxTimeoutSeconds?: number;
454
- outputSchema?: unknown;
455
- extra?: unknown;
456
- }
457
- /**
458
- * Verified payment context attached by server middleware.
459
- */
460
- interface VerifiedPaymentState {
461
- payment: X402Header;
462
- requirements: PaymentRequirements;
463
- verifyResult: VerifyResponse;
464
- settle: () => Promise<SettleResponse>;
465
- }
466
- /**
467
- * Shared server middleware options.
468
- */
469
- interface PaymentMiddlewareOptions extends FacilitatorClientOptions {
470
- /** Alias for baseUrl to keep middleware options ergonomic */
471
- facilitatorUrl?: string;
472
- /**
473
- * Settlement behavior after verification.
474
- * - manual: verify only; caller settles explicitly
475
- * - before-handler: settle immediately before calling next()
476
- */
477
- settlementStrategy?: 'manual' | 'before-handler';
478
- }
479
- /**
480
- * Custom resolver for selecting the correct payment requirement when multiple
481
- * accepts are advertised.
482
- */
483
- type PaymentRequirementResolver = (payment: X402Header, requirements: PaymentRequirements[]) => PaymentRequirements | null | Promise<PaymentRequirements | null>;
484
- /**
485
- * Parse X-PAYMENT or PAYMENT-SIGNATURE header value
486
- *
487
- * @param headerValue - Base64-encoded header value (or undefined/null)
488
- * @returns Parsed x402 header object, or null if invalid
489
- *
490
- * @example
491
- * ```ts
492
- * // Express.js
493
- * const payment = parsePaymentHeader(req.headers['x-payment']);
494
- * if (!payment) {
495
- * return res.status(400).json({ error: 'Invalid payment header' });
496
- * }
497
- * ```
498
- */
499
- declare function parsePaymentHeader(headerValue: string | undefined | null): X402Header | null;
500
- /**
501
- * Extract payment header from request headers object
502
- *
503
- * Checks both X-PAYMENT and PAYMENT-SIGNATURE headers.
504
- *
505
- * @param headers - Request headers object (case-insensitive)
506
- * @returns Parsed x402 header object, or null if not found/invalid
507
- *
508
- * @example
509
- * ```ts
510
- * const payment = extractPaymentFromHeaders(req.headers);
511
- * ```
512
- */
513
- declare function extractPaymentFromHeaders(headers: Record<string, string | string[] | undefined>): X402Header | null;
514
- /**
515
- * Build payment requirements for the facilitator
516
- *
517
- * @param options - Payment requirements options
518
- * @returns PaymentRequirements object ready for verify/settle
519
- *
520
- * @example
521
- * ```ts
522
- * const requirements = buildPaymentRequirements({
523
- * amount: '1.00',
524
- * recipient: '0x1234...',
525
- * resource: 'https://api.example.com/premium-data',
526
- * chainName: 'base',
527
- * });
528
- * ```
529
- */
530
- declare function buildPaymentRequirements(options: PaymentRequirementsOptions): PaymentRequirements;
531
- /**
532
- * Build a verify request for the facilitator /verify endpoint
533
- *
534
- * @param paymentHeader - Parsed x402 payment header
535
- * @param requirements - Payment requirements
536
- * @returns VerifyRequest body ready for fetch/axios
537
- *
538
- * @example
539
- * ```ts
540
- * const payment = parsePaymentHeader(req.headers['x-payment']);
541
- * const verifyBody = buildVerifyRequest(payment, requirements);
542
- *
543
- * const response = await fetch('https://facilitator.uvd.xyz/verify', {
544
- * method: 'POST',
545
- * headers: { 'Content-Type': 'application/json' },
546
- * body: JSON.stringify(verifyBody),
547
- * });
548
- * ```
549
- */
550
- declare function buildVerifyRequest(paymentHeader: X402Header, requirements: PaymentRequirements): VerifyRequest;
551
- /**
552
- * Build a settle request for the facilitator /settle endpoint
553
- *
554
- * @param paymentHeader - Parsed x402 payment header
555
- * @param requirements - Payment requirements
556
- * @returns SettleRequest body ready for fetch/axios
557
- */
558
- /**
559
- * Describes the protected resource, as x402 v2 expects it.
560
- *
561
- * Note this is an OBJECT in v2. Sending a bare URL string here is the single
562
- * most common v2 mistake and it fails as an unhelpful "no variant matched"
563
- * deserialization error at the facilitator, naming no field.
564
- */
565
- interface ResourceInfoV2 {
566
- url: string;
567
- description: string;
568
- mimeType: string;
569
- }
570
- /**
571
- * Payment requirements in x402 v2 form.
572
- *
573
- * Differences from v1 that actually bite:
574
- * - `network` is CAIP-2 (`eip155:8453`), NOT a plain name (`base`). Mixing a v1
575
- * name into a v2 request fails deserialization, and vice versa.
576
- * - `maxAmountRequired` is renamed to `amount`.
577
- * - `resource` / `description` / `mimeType` moved out to {@link ResourceInfoV2}.
578
- */
579
- interface PaymentRequirementsV2 {
580
- scheme: string;
581
- /** CAIP-2 chain id, e.g. `eip155:8453`. */
582
- network: string;
583
- asset: string;
584
- amount: string;
585
- payTo: string;
586
- maxTimeoutSeconds: number;
587
- extra?: unknown;
588
- }
589
- /** The v2 payment payload — note it carries no top-level scheme/network. */
590
- interface PaymentPayloadV2 {
591
- x402Version: 2;
592
- resource: ResourceInfoV2;
593
- accepted: PaymentRequirementsV2;
594
- payload: X402PayloadData;
595
- extensions?: Record<string, unknown>;
596
- }
597
- /**
598
- * Verify request body in x402 v2 form.
599
- *
600
- * There is deliberately NO `paymentRequirements` key: that is the v1 envelope.
601
- * v2 carries `resource` and `accepted` at the top level instead.
602
- */
603
- interface VerifyRequestV2 {
604
- x402Version: 2;
605
- paymentPayload: PaymentPayloadV2;
606
- resource: ResourceInfoV2;
607
- accepted: PaymentRequirementsV2;
608
- }
609
- /** Settle request body in x402 v2 form. Same shape as {@link VerifyRequestV2}. */
610
- type SettleRequestV2 = VerifyRequestV2;
611
- /**
612
- * Build a verify request for the facilitator `/verify` endpoint, in **v2** form.
613
- *
614
- * Use this whenever your 402 advertises CAIP-2 networks. {@link buildVerifyRequest}
615
- * emits the v1 envelope `{x402Version, paymentPayload, paymentRequirements}` and
616
- * cannot express v2 — putting a v2 payload inside it matches no variant at the
617
- * facilitator and fails with an error that names no field.
618
- *
619
- * @example
620
- * ```ts
621
- * const body = buildVerifyRequestV2(
622
- * payment.payload,
623
- * { url: 'https://api.example.com/thing', description: 'Thing', mimeType: 'application/json' },
624
- * { scheme: 'exact', network: 'eip155:8453', asset: '0x8335...', amount: '100000',
625
- * payTo: '0xabc...', maxTimeoutSeconds: 300 }
626
- * );
627
- * ```
628
- */
629
- declare function buildVerifyRequestV2(payload: X402PayloadData, resource: ResourceInfoV2, accepted: PaymentRequirementsV2): VerifyRequestV2;
630
- /**
631
- * Build a settle request for the facilitator `/settle` endpoint, in **v2** form.
632
- *
633
- * See {@link buildVerifyRequestV2} — the envelope is identical.
634
- */
635
- declare function buildSettleRequestV2(payload: X402PayloadData, resource: ResourceInfoV2, accepted: PaymentRequirementsV2): SettleRequestV2;
636
- declare function buildSettleRequest(paymentHeader: X402Header, requirements: PaymentRequirements): SettleRequest;
637
- /**
638
- * Derive the v2 `resource` object from v1-shaped requirements.
639
- *
640
- * v2 moved `resource` / `description` / `mimeType` out of the requirements and
641
- * into an object of their own, and the facilitator requires ALL THREE keys:
642
- * measured 2026-09-03, a `resource` carrying only `url` is a 400.
643
- *
644
- * The `??` defaults are not decoration. `PaymentRequirements` types these as
645
- * required, but a JavaScript caller can still hand over an object without them,
646
- * and a missing key does not fail with "description is missing" -- it fails with
647
- * `data did not match any variant of untagged enum VerifyRequestEnvelope`, which
648
- * names no field. That error is what cost two teams a day.
649
- */
650
- declare function toResourceInfoV2(requirements: PaymentRequirements): ResourceInfoV2;
651
- /**
652
- * Derive v2 `accepted` requirements from v1-shaped requirements.
653
- *
654
- * Two renames do the damage, and neither is reported by name when it is wrong:
655
- * - `maxAmountRequired` is spelled `amount` in v2.
656
- * - `network` must be CAIP-2; a plain name inside a v2 body is a 400.
657
- *
658
- * `extra` is carried through when present -- it is where the EIP-712 domain
659
- * `name`/`version` live for tokens the facilitator does not know by address, so
660
- * dropping it breaks EURC and the bridged USDCs.
661
- *
662
- * @throws If `requirements.network` has NO CAIP-2 form. `chainToCAIP2` answers
663
- * with the name unchanged when it does not know a chain, and XRPL maps to
664
- * itself on purpose -- its v1 string IS its network id. Passing that through
665
- * would put a plain name inside a v2 body, which is a measured 400 (the same
666
- * `no variant matched` that names no field). Only reachable by PINNING version
667
- * 2 on such a network; `auto` leaves them on v1, where they work. Failing here
668
- * names the network and the fix, which a 400 from the facilitator does not.
669
- */
670
- declare function toPaymentRequirementsV2(requirements: PaymentRequirements): PaymentRequirementsV2;
671
- /**
672
- * Decide which envelope this (payment, requirements) pair has to travel in.
673
- *
674
- * `requested` wins when it names a version; `'auto'` (the default) reads the
675
- * wire.
676
- *
677
- * **Auto keys off CAIP-2, NOT off `paymentHeader.x402Version`,** and that is a
678
- * measured decision rather than a stylistic one. The facilitator's envelope enum
679
- * is untagged: it matches on SHAPE and ignores the version marker.
680
- *
681
- * Re-measured against `https://facilitator.ultravioletadao.xyz/verify` on
682
- * **2026-09-04** with a fabricated signature. The signature never verifies, so
683
- * every row is an HTTP 400 and the STATUS discriminates nothing -- what does is
684
- * the error code. `invalid_request_body` means the facilitator could not
685
- * deserialize the body; `contract_call_failed` means it read the body, resolved
686
- * the chain and got as far as the on-chain call, i.e. the envelope was fine.
687
- *
688
- * | payload network | requirements network | v1 envelope today |
689
- * |-----------------|----------------------|-------------------|
690
- * | `base` | `base` | understood |
691
- * | `base` (header says `x402Version: 2`) | `base` | understood |
692
- * | `eip155:8453` | `base` | understood |
693
- * | `base` | `eip155:8453` | understood |
694
- * | `eip155:8453` | `eip155:8453` | understood |
695
- *
696
- * **The last three rows used to be a hard 400** (`unknown variant
697
- * \`eip155:8453\``) when this function was written on 2026-09-03. The
698
- * facilitator has since taught the v1 envelope to read CAIP-2, so the original
699
- * argument for this rule -- "every CAIP-2 combination is already a 400, so
700
- * upgrading them cannot regress anyone" -- **is no longer true**. The rule is
701
- * unchanged; three other reasons hold it up:
702
- *
703
- * 1. A CAIP-2 network on the wire means the 402 that produced it advertised v2.
704
- * Answering in v2 is speaking the protocol the seller announced.
705
- * 2. v2-with-CAIP-2 is the only shape BOTH generations of the facilitator
706
- * accept. v1-with-CAIP-2 is a hard 400 on any build older than 2026-09-04,
707
- * so choosing v1 there is what breaks against a self-hosted or pinned one.
708
- * 3. The Python SDK resolves the identical rule, so the same wire produces the
709
- * same body in both SDKs -- pinned by phase 6 of `npm run test:xlang`.
710
- *
711
- * And the marker still decides nothing: row 2 above is served correctly today,
712
- * so upgrading on the strength of it would change a call that works.
713
- *
714
- * The negative half of that measurement, without which "understood" proves
715
- * nothing -- the same run, bodies broken on purpose, all three
716
- * `invalid_request_body`: a v2 body carrying a plain network name, one with
717
- * `resource` as a bare string, and one with `accepted` removed. A well-formed
718
- * v2 body with CAIP-2 reached `contract_call_failed` like the rows above.
719
- */
720
- declare function resolveEnvelopeVersion(paymentHeader: X402Header | PaymentPayloadV2, requirements: PaymentRequirements, requested?: X402Version | 'auto'): X402Version;
721
- /**
722
- * Build a `/verify` body in whichever envelope `version` names.
723
- *
724
- * The v1 return is byte-for-byte what {@link buildVerifyRequest} produces, so
725
- * pinning `1` is exactly today's behaviour.
726
- *
727
- * @example
728
- * ```ts
729
- * const version = resolveEnvelopeVersion(payment, requirements);
730
- * const body = buildVerifyRequestForVersion(payment, requirements, version);
731
- * ```
732
- */
733
- declare function buildVerifyRequestForVersion(paymentHeader: X402Header, requirements: PaymentRequirements, version: X402Version): VerifyRequest | VerifyRequestV2;
734
- /**
735
- * Build a `/settle` body in whichever envelope `version` names.
736
- *
737
- * See {@link buildVerifyRequestForVersion} -- `/settle` takes the same body as
738
- * `/verify` in both versions.
739
- */
740
- declare function buildSettleRequestForVersion(paymentHeader: X402Header, requirements: PaymentRequirements, version: X402Version): SettleRequest | SettleRequestV2;
741
- /**
742
- * Recommended CORS headers for x402 payment APIs
743
- *
744
- * These headers allow browsers to send payment headers in cross-origin requests.
745
- */
746
- declare const X402_CORS_HEADERS: {
747
- readonly 'Access-Control-Allow-Headers': "Content-Type, X-PAYMENT, PAYMENT-SIGNATURE, Authorization";
748
- readonly 'Access-Control-Expose-Headers': "X-PAYMENT-RESPONSE, PAYMENT-RESPONSE, PAYMENT-REQUIRED";
749
- readonly 'Access-Control-Allow-Methods': "GET, POST, OPTIONS";
750
- };
751
- /**
752
- * All x402 custom header names that should be allowed in CORS
753
- */
754
- declare const X402_HEADER_NAMES: readonly ["X-PAYMENT", "PAYMENT-SIGNATURE", "X-PAYMENT-RESPONSE", "PAYMENT-RESPONSE", "PAYMENT-REQUIRED"];
755
- /**
756
- * Get CORS headers with custom origin
757
- *
758
- * @param origin - Allowed origin (use '*' for any, or specific domain)
759
- * @returns Complete CORS headers object
760
- *
761
- * @example
762
- * ```ts
763
- * // Express.js middleware
764
- * app.use((req, res, next) => {
765
- * const corsHeaders = getCorsHeaders('https://myapp.com');
766
- * Object.entries(corsHeaders).forEach(([key, value]) => {
767
- * res.setHeader(key, value);
768
- * });
769
- * if (req.method === 'OPTIONS') {
770
- * return res.status(204).end();
771
- * }
772
- * next();
773
- * });
774
- * ```
775
- */
776
- declare function getCorsHeaders(origin?: string): Record<string, string>;
777
- /**
778
- * Options for the FacilitatorClient
779
- */
780
- interface FacilitatorClientOptions {
781
- /** Base URL of the facilitator (default: https://facilitator.ultravioletadao.xyz) */
782
- baseUrl?: string;
783
- /**
784
- * Request timeout in milliseconds (default: auto per network).
785
- * When not set, the client uses per-network defaults from ESCROW_TIMEOUT_MS
786
- * (960s for Ethereum L1, 90s for L2s, 30s for others).
787
- * Set explicitly to override per-network auto-detection.
788
- */
789
- timeout?: number;
790
- /**
791
- * Extra attempts after the first when the facilitator answers a refusal it
792
- * proved it did not execute (`safeToReplay`). Default 2; `0` disables.
793
- *
794
- * Only ever spent on `429` and on a `503` naming a pre-execution writer-lease
795
- * reason. An ambiguous `forward_failed` -- whose write may already have landed
796
- * -- is never replayed here, at any setting.
797
- */
798
- retries?: number;
799
- /**
800
- * Which envelope to send to `/verify` and `/settle`. Default `'auto'`.
801
- *
802
- * `'auto'` reads the wire: CAIP-2 networks get the v2 envelope, plain names
803
- * get v1. See {@link resolveEnvelopeVersion} for the measurements behind that
804
- * rule. Pin `1` or `2` to take the decision yourself -- a pin is honoured
805
- * even when it contradicts the wire, because choosing the version is the
806
- * point of the option.
807
- */
808
- x402Version?: X402Version | 'auto';
809
- }
810
- /**
811
- * Client for interacting with the x402 facilitator API
812
- *
813
- * @example
814
- * ```ts
815
- * const client = new FacilitatorClient();
816
- *
817
- * // Verify a payment
818
- * const verifyResult = await client.verify(paymentHeader, requirements);
819
- * if (!verifyResult.isValid) {
820
- * return res.status(402).json({ error: verifyResult.invalidReason });
821
- * }
822
- *
823
- * // Provide the service, then settle
824
- * const settleResult = await client.settle(paymentHeader, requirements);
825
- * if (!settleResult.success) {
826
- * // Handle settlement failure (maybe refund or retry)
827
- * }
828
- * ```
829
- */
830
- declare class FacilitatorClient {
831
- private readonly baseUrl;
832
- private readonly timeout;
833
- private readonly explicitTimeout;
834
- private readonly retries;
835
- private readonly x402Version;
836
- constructor(options?: FacilitatorClientOptions);
837
- /**
838
- * Get timeout for a specific network, using per-chain defaults when no explicit timeout was set.
839
- */
840
- private getTimeout;
841
- /**
842
- * Verify a payment with the facilitator
843
- *
844
- * Call this before providing the paid resource to validate the payment.
845
- *
846
- * @param paymentHeader - Parsed x402 payment header
847
- * @param requirements - Payment requirements
848
- * @returns Verification result
849
- */
850
- verify(paymentHeader: X402Header, requirements: PaymentRequirements): Promise<VerifyResponse>;
851
- /**
852
- * Settle a payment with the facilitator
853
- *
854
- * Call this after providing the paid resource to execute the on-chain transfer.
855
- *
856
- * @param paymentHeader - Parsed x402 payment header
857
- * @param requirements - Payment requirements
858
- * @returns Settlement result with transaction hash
859
- */
860
- settle(paymentHeader: X402Header, requirements: PaymentRequirements): Promise<SettleResponse>;
861
- /**
862
- * Verify and settle atomically
863
- *
864
- * Convenience method that verifies first, then settles if valid.
865
- * Use this for simple payment flows where you don't need custom logic between verify and settle.
866
- *
867
- * @param paymentHeader - Parsed x402 payment header
868
- * @param requirements - Payment requirements
869
- * @returns Combined result with verify and settle status
870
- */
871
- verifyAndSettle(paymentHeader: X402Header, requirements: PaymentRequirements): Promise<{
872
- verified: boolean;
873
- settled: boolean;
874
- transactionHash?: string;
875
- error?: string;
876
- } & FacilitatorFailureFields>;
877
- /**
878
- * Check if the facilitator is healthy
879
- *
880
- * @returns True if the facilitator is responding
881
- */
882
- healthCheck(): Promise<boolean>;
883
- /**
884
- * Get the facilitator version info
885
- *
886
- * @returns Version info (e.g., { version: "1.37.0" })
887
- */
888
- getVersion(): Promise<{
889
- version: string;
890
- [key: string]: unknown;
891
- }>;
892
- /**
893
- * Get the facilitator's supported networks and payment schemes
894
- *
895
- * @returns Supported networks/schemes with 'kinds' array
896
- *
897
- * @example
898
- * ```ts
899
- * const supported = await client.getSupported();
900
- * for (const kind of supported.kinds) {
901
- * console.log(`${kind.network} - ${kind.scheme}`);
902
- * }
903
- * ```
904
- */
905
- getSupported(): Promise<{
906
- kinds: Array<{
907
- network: string;
908
- scheme: string;
909
- [key: string]: unknown;
910
- }>;
911
- [key: string]: unknown;
912
- }>;
913
- /**
914
- * Aggregated totals per network and asset (`GET /api/stats`).
915
- *
916
- * **An index, not a ledger.** Records are written best-effort AFTER
917
- * settlement, so an outage loses rows while payments proceed — verify
918
- * anything that matters against the transaction hash. Counting starts when
919
- * the operator enabled the store, so earlier operations are UNKNOWN, not
920
- * zero. And unless `X402_EVENTS_PUBLISH_FAILURES=true`, operations that ERROR
921
- * are not recorded at all: a 100% success rate means "no failures were
922
- * recorded".
923
- *
924
- * `volumeAtomic` is a STRING (u256-shaped; a JS number loses precision above
925
- * 2^53) and each row carries its own `decimals`. **Use that, never a
926
- * constant** — USDC is 6 decimals nearly everywhere and 18 on BSC, so scaling
927
- * by 6 there overstates volume by 10^12. `decimals` is null when the asset is
928
- * unrecognised; render the atomic value rather than guessing a scale.
929
- */
930
- getStats(): Promise<{
931
- totals: {
932
- settlesOk: number;
933
- settlesFailed: number;
934
- verifies: number;
935
- networks: number;
936
- };
937
- byNetworkAndAsset: Array<{
938
- network: string;
939
- asset: string;
940
- settlesOk: number;
941
- settlesFailed: number;
942
- verifies: number;
943
- volumeAtomic: string;
944
- decimals: number | null;
945
- lastTs: number;
946
- }>;
947
- [key: string]: unknown;
948
- }>;
949
- /**
950
- * Recent recorded operations, newest first (`GET /transactions`).
951
- *
952
- * There is **no pagination and no cursor**: this returns the newest N,
953
- * walking back at most 30 days. With 10,000 rows you get the newest 200, not
954
- * page one of fifty. `limit` is clamped to 200 by the facilitator.
955
- *
956
- * `network` matches the canonical slug `/supported` uses, which is not always
957
- * the alias you may send — `skale` is accepted inbound but records say
958
- * `skale-base`.
959
- */
960
- getTransactions(options?: {
961
- limit?: number;
962
- network?: string;
963
- }): Promise<{
964
- transactions: Array<Record<string, unknown>>;
965
- count: number;
966
- [key: string]: unknown;
967
- }>;
968
- /**
969
- * Get the facilitator's blocked/sanctioned addresses
970
- *
971
- * @returns Blacklist info (totalBlocked, loadedAtStartup, addresses)
972
- *
973
- * @example
974
- * ```ts
975
- * const bl = await client.getBlacklist();
976
- * console.log(`Blocked: ${bl.totalBlocked} addresses`);
977
- * ```
978
- */
979
- getBlacklist(): Promise<{
980
- totalBlocked: number;
981
- loadedAtStartup: boolean;
982
- [key: string]: unknown;
983
- }>;
984
- /**
985
- * Negotiate payment requirements with the facilitator via POST /accepts.
986
- *
987
- * Sends merchant payment requirements to the facilitator, which matches
988
- * them against its supported capabilities and returns enriched requirements
989
- * with facilitator data (feePayer, tokens, escrow configuration).
990
- *
991
- * This is used by Faremeter middleware and clients that need to discover
992
- * what the facilitator can settle before constructing payment authorizations.
993
- *
994
- * @param paymentRequirements - List of payment requirement objects
995
- * @param x402Version - x402 protocol version (default: 2)
996
- * @returns List of enriched payment requirements with facilitator extras
997
- *
998
- * @example
999
- * ```ts
1000
- * const enriched = await client.accepts([
1001
- * {
1002
- * scheme: 'exact',
1003
- * network: 'base-mainnet',
1004
- * maxAmountRequired: '1000000',
1005
- * resource: 'https://api.example.com/data',
1006
- * payTo: '0xMerchant...',
1007
- * },
1008
- * ]);
1009
- * // enriched[0].extra.feePayer is now set
1010
- * ```
1011
- */
1012
- accepts(paymentRequirements: PaymentRequirements[], x402Version?: number): Promise<PaymentRequirements[]>;
1013
- }
1014
- /**
1015
- * Create a 402 Payment Required response
1016
- *
1017
- * @param requirements - Payment requirements
1018
- * @param options - Additional response options
1019
- * @returns Object with status code, headers, and body for the 402 response
1020
- *
1021
- * @example
1022
- * ```ts
1023
- * // Express.js
1024
- * app.get('/premium-data', (req, res) => {
1025
- * const payment = extractPaymentFromHeaders(req.headers);
1026
- *
1027
- * if (!payment) {
1028
- * const { status, headers, body } = create402Response({
1029
- * amount: '1.00',
1030
- * recipient: '0x...',
1031
- * resource: 'https://api.example.com/premium-data',
1032
- * });
1033
- * return res.status(status).set(headers).json(body);
1034
- * }
1035
- *
1036
- * // Verify and serve...
1037
- * });
1038
- * ```
1039
- */
1040
- declare function create402Response(requirements: PaymentRequirementsOptions, options?: {
1041
- accepts?: PaymentAcceptance[];
1042
- }): {
1043
- status: 402;
1044
- headers: Record<string, string>;
1045
- body: Record<string, unknown>;
1046
- };
1047
- /** The body of a no-verdict refusal. See {@link buildUnavailableResponse}. */
1048
- interface UnavailableBody {
1049
- /** Human-readable summary. Never says the payment was rejected. */
1050
- error: string;
1051
- /** The facilitator's own reason, under whichever field it populated. */
1052
- reason?: string;
1053
- /** Always `true` — this response exists to say "no verdict", not "refused". */
1054
- retryable: true;
1055
- /** Whole seconds to wait, mirroring the `Retry-After` header. */
1056
- retryAfterSeconds: number;
1057
- /**
1058
- * `false` for `forward_failed` and for a bare timeout: the write may already
1059
- * have landed, so the caller must reconcile before resending.
1060
- */
1061
- safeToReplay: boolean;
1062
- }
1063
- /** A framework-agnostic HTTP response. See {@link buildUnavailableResponse}. */
1064
- interface UnavailableResponse {
1065
- /** Always 503. */
1066
- status: 503;
1067
- /** `Retry-After`, ready to spread onto any framework's header setter. */
1068
- headers: Record<string, string>;
1069
- body: UnavailableBody;
1070
- /** Same value as the header, already clamped to a whole second >= 1. */
1071
- retryAfterSeconds: number;
1072
- }
1073
- /**
1074
- * Build the answer to a facilitator refusal that reached NO VERDICT.
1075
- *
1076
- * `verify` returns invalid for two different things: a payment that was
1077
- * REJECTED, and a facilitator that never reached a verdict (`retryable`).
1078
- * Answering `402` in the second case tells the buyer to sign a NEW
1079
- * authorization while the first one is still live and still spendable by the
1080
- * facilitator — so the buyer pays twice. The correct answer is `503` plus
1081
- * `Retry-After`, which asks for the SAME credential again.
1082
- *
1083
- * This returns plain data — status, headers, body — so a handler written
1084
- * without Express (Lambda, Hono, a Next route, Fastify, a bare `Response`) can
1085
- * answer correctly without re-deriving the rule. The Express and Hono
1086
- * middlewares in this SDK both build their reply from it.
1087
- *
1088
- * @param message - Summary for the `error` field, e.g. `'Payment verification unavailable'`
1089
- * @param failure - The facilitator result. Only its failure fields are read.
1090
- *
1091
- * @example Lambda / any framework
1092
- * ```ts
1093
- * const verifyResult = await client.verify(payment, requirements);
1094
- * if (!verifyResult.isValid && verifyResult.retryable) {
1095
- * const r = buildUnavailableResponse('Payment verification unavailable', verifyResult);
1096
- * return { statusCode: r.status, headers: r.headers, body: JSON.stringify(r.body) };
1097
- * }
1098
- * ```
1099
- *
1100
- * @example Web `Response`
1101
- * ```ts
1102
- * const r = buildUnavailableResponse('Payment settlement unavailable', settleResult);
1103
- * return Response.json(r.body, { status: r.status, headers: r.headers });
1104
- * ```
1105
- */
1106
- declare function buildUnavailableResponse(message: string, failure: FacilitatorFailureFields & {
1107
- error?: string;
1108
- invalidReason?: string;
1109
- }): UnavailableResponse;
1110
- /**
1111
- * Create an Express-compatible middleware for x402 payments
1112
- *
1113
- * @param getRequirements - Function to get payment requirements for a request
1114
- * @param options - Middleware options
1115
- * @returns Express middleware function
1116
- *
1117
- * @example
1118
- * ```ts
1119
- * const paymentMiddleware = createPaymentMiddleware(
1120
- * (req) => ({
1121
- * amount: '1.00',
1122
- * recipient: process.env.PAYMENT_RECIPIENT,
1123
- * resource: `${req.protocol}://${req.get('host')}${req.originalUrl}`,
1124
- * }),
1125
- * { facilitatorUrl: 'https://facilitator.uvd.xyz' }
1126
- * );
1127
- *
1128
- * app.get('/premium/*', paymentMiddleware, async (req, res) => {
1129
- * const settleResult = await req.x402?.settle();
1130
- * if (!settleResult?.success) {
1131
- * return res.status(500).json({ error: settleResult?.error });
1132
- * }
1133
- *
1134
- * res.json({ premium: 'data' });
1135
- * });
1136
- * ```
1137
- */
1138
- declare function createPaymentMiddleware(getRequirements: (req: {
1139
- headers: Record<string, string | string[] | undefined>;
1140
- }) => PaymentRequirementsOptions, options?: PaymentMiddlewareOptions): (req: {
1141
- headers: Record<string, string | string[] | undefined>;
1142
- x402?: VerifiedPaymentState;
1143
- }, res: {
1144
- status: (code: number) => {
1145
- json: (body: unknown) => void;
1146
- set: (headers: Record<string, string>) => {
1147
- json: (body: unknown) => void;
1148
- };
1149
- };
1150
- }, next: () => void) => Promise<void>;
1151
- /**
1152
- * Options for creating a Hono x402 payment middleware
1153
- */
1154
- interface HonoMiddlewareOptions extends PaymentMiddlewareOptions {
1155
- /** Payment requirements to advertise */
1156
- accepts: PaymentAcceptance[];
1157
- /** Response version to advertise (defaults to auto) */
1158
- x402Version?: X402Version | 'auto';
1159
- /** Custom requirement resolver for ambiguous multi-accept flows */
1160
- resolveRequirement?: PaymentRequirementResolver;
1161
- }
1162
- declare function createHonoMiddleware(options: HonoMiddlewareOptions): (c: {
1163
- req: {
1164
- header: (name: string) => string | undefined;
1165
- url: string;
1166
- };
1167
- json: (body: unknown, status?: number) => unknown;
1168
- set?: (key: string, value: unknown) => void;
1169
- /** Hono's response-header setter. Optional so older context doubles still fit. */
1170
- header?: (name: string, value: string) => void;
1171
- }, next: () => Promise<void>) => Promise<unknown>;
1172
- /**
1173
- * Maximum length of the free-text `q` filter.
1174
- *
1175
- * Mirrors the facilitator's `MAX_SEARCH_LEN`; a longer needle is rejected
1176
- * server-side with a 400.
1177
- */
1178
- declare const MAX_SEARCH_LEN = 128;
1179
- /**
1180
- * Liveness of a registered resource, as measured by the facilitator's prober.
1181
- *
1182
- * Resources that stop answering are quarantined rather than deleted, so filter
1183
- * on this before paying anyone.
1184
- */
1185
- type DiscoveryHealthStatus = 'alive' | 'degraded' | 'auth_gated' | 'quarantined' | 'unknown' | 'unprobeable';
1186
- /** Values accepted by the `health` filter, including the `any` escape hatch. */
1187
- declare const HEALTH_FILTERS: readonly ["alive", "degraded", "auth_gated", "quarantined", "unknown", "unprobeable", "any"];
1188
- /** Curated tier, in descending order of trust. */
1189
- type DiscoveryTier = 'first_party' | 'vip' | 'verified' | 'listed';
1190
- /** Values accepted by the `tier` filter. */
1191
- declare const TIER_FILTERS: readonly ["first_party", "vip", "verified", "listed"];
1192
- /** How a resource got into the registry. */
1193
- type DiscoverySource = 'self_registered' | 'settlement' | 'crawled' | 'aggregated';
1194
- /** Health of a single resource, as reported by the registry's prober. */
1195
- interface DiscoveryHealth {
1196
- /** Last observed liveness */
1197
- status?: DiscoveryHealthStatus;
1198
- /** Unix epoch seconds of the last probe */
1199
- lastChecked?: number;
1200
- /** HTTP status the probe got back (402 is the healthy answer for x402) */
1201
- httpStatus?: number;
1202
- /** Round-trip time of the last probe, in milliseconds */
1203
- latencyMs?: number;
1204
- }
1205
- /** Curation metadata attached to a resource. */
1206
- interface DiscoveryCuration {
1207
- /** Curated tier */
1208
- tier?: DiscoveryTier;
1209
- /** Human-readable name of the curated set */
1210
- label?: string;
1211
- }
1212
- /** One payment method a resource declares. */
1213
- interface DiscoveryAccepts {
1214
- /** Payment scheme ("exact", "escrow", "commerce") */
1215
- scheme: string;
1216
- /** CAIP-2 network id, e.g. "eip155:8453" */
1217
- network: string;
1218
- /** Token contract address */
1219
- asset?: string;
1220
- /** Price in atomic units of `asset` */
1221
- amount?: string;
1222
- /** Recipient address */
1223
- payTo?: string;
1224
- /** Settlement deadline in seconds */
1225
- maxTimeoutSeconds?: number;
1226
- /** Scheme-specific extras (EIP-712 domain, etc.) */
1227
- extra?: Record<string, unknown>;
1228
- /** Anything the registry adds later */
1229
- [key: string]: unknown;
1230
- }
1231
- /**
1232
- * A discoverable paid resource, exactly as `GET /discovery/resources` serves it.
1233
- *
1234
- * Timestamps are Unix epoch **seconds**, not ISO strings and not milliseconds.
1235
- */
1236
- interface DiscoveryResource {
1237
- /** Resource URL. This is the registry's primary key -- there is no `id` */
1238
- url: string;
1239
- /** Resource type ("http", "mcp", "a2a") */
1240
- type: string;
1241
- /** x402 protocol version the resource speaks */
1242
- x402Version: number;
1243
- /** Human-readable description */
1244
- description?: string;
1245
- /** Payment methods the resource accepts */
1246
- accepts: DiscoveryAccepts[];
1247
- /** Free-form metadata (category, provider, tags) */
1248
- metadata?: Record<string, unknown>;
1249
- /** How this resource entered the registry */
1250
- source?: DiscoverySource;
1251
- /** Facilitator this resource was aggregated from */
1252
- sourceFacilitator?: string;
1253
- /** Unix epoch seconds when the registry first saw this resource */
1254
- firstSeen?: number;
1255
- /** Unix epoch seconds when the registry last saw this resource */
1256
- lastSeen?: number;
1257
- /** Unix epoch seconds of the last change to this record */
1258
- lastUpdated?: number;
1259
- /** Liveness, when the resource has been probed */
1260
- health?: DiscoveryHealth;
1261
- /** Curation tier, when the resource has been curated */
1262
- curation?: DiscoveryCuration;
1263
- /** Anything the registry adds later */
1264
- [key: string]: unknown;
1265
- }
1266
- /** Pagination envelope of `GET /discovery/resources`. */
1267
- interface DiscoveryPagination {
1268
- /** Page size that was applied */
1269
- limit: number;
1270
- /** Offset that was applied */
1271
- offset: number;
1272
- /** Total number of resources matching the filters, across all pages */
1273
- total: number;
1274
- }
1275
- /** Paginated response from `GET /discovery/resources`. */
1276
- interface DiscoveryResponse {
1277
- /** x402 protocol version of the response envelope */
1278
- x402Version: number;
1279
- /** Resources on this page */
1280
- items: DiscoveryResource[];
1281
- /** Pagination state */
1282
- pagination: DiscoveryPagination;
1283
- }
1284
- /**
1285
- * Filters for `listResources()`.
1286
- *
1287
- * Every one of these is applied server-side over the whole catalog, so
1288
- * `pagination.total` reflects the filtered set. Filtering a page after the
1289
- * fact is not the same thing and will under-report.
1290
- */
1291
- interface DiscoveryListOptions {
1292
- /** Page size (default: 10, max: 100) */
1293
- limit?: number;
1294
- /** Number of resources to skip */
1295
- offset?: number;
1296
- /** Filter by category */
1297
- category?: string;
1298
- /** Filter by network, CAIP-2 or v1 name */
1299
- network?: string;
1300
- /** Filter by provider name */
1301
- provider?: string;
1302
- /** Filter by tag */
1303
- tag?: string;
1304
- /** Filter by how the resource was discovered */
1305
- source?: DiscoverySource;
1306
- /** Filter by originating facilitator */
1307
- sourceFacilitator?: string;
1308
- /** Filter by liveness, or 'any' to opt out of the default visibility rules */
1309
- health?: DiscoveryHealthStatus | 'any';
1310
- /** Filter by curated tier */
1311
- tier?: DiscoveryTier;
1312
- /** Free-text search over url / description / provider / category / tags */
1313
- q?: string;
1314
- }
1315
- /** Options for `registerResource()`. */
1316
- interface DiscoveryRegisterOptions {
1317
- /** URL of the paid resource. Doubles as its identity in the registry */
1318
- url: string;
1319
- /** Resource type (default: "http") */
1320
- type?: string;
1321
- /** Human-readable description */
1322
- description?: string;
1323
- /** Payment methods the resource accepts */
1324
- accepts?: DiscoveryAccepts[];
1325
- /** Free-form metadata (category, provider, tags) */
1326
- metadata?: Record<string, unknown>;
1327
- }
1328
- /** Aggregate catalog metrics from `GET /discovery/stats`. */
1329
- interface DiscoveryStats {
1330
- /** Every record the registry holds, including quarantined ones */
1331
- total: number;
1332
- /** Records served by default listings */
1333
- visible: number;
1334
- /** Counts by discovery source */
1335
- bySource: Record<string, number>;
1336
- /** Counts by originating facilitator */
1337
- bySourceFacilitator: Record<string, number>;
1338
- /** Counts by CAIP-2 network */
1339
- byNetwork: Record<string, number>;
1340
- /** Counts by curated tier */
1341
- byTier: Record<string, number>;
1342
- /** Counts by liveness */
1343
- byHealth: Record<string, number>;
1344
- /** Unix epoch seconds this snapshot was computed (60s cache) */
1345
- generatedAt?: number;
1346
- }
1347
- /** Options for the {@link BazaarClient}. */
1348
- interface BazaarClientOptions {
1349
- /** Facilitator base URL (default: https://facilitator.ultravioletadao.xyz) */
1350
- baseUrl?: string;
1351
- /** Request timeout in milliseconds (default: 30000) */
1352
- timeout?: number;
1353
- }
1354
- /** Render an epoch-seconds field as a `Date`. */
1355
- declare function epochToDate(seconds?: number): Date | undefined;
1356
- /** True when the last probe reached this resource. */
1357
- declare function isAlive(resource: DiscoveryResource): boolean;
1358
- /**
1359
- * Client for the x402 Bazaar Discovery API.
1360
- *
1361
- * The Bazaar is the facilitator's own registry of x402-enabled resources.
1362
- * Providers register their endpoints and consumers discover them, with a
1363
- * liveness probe and a curation tier attached to every record.
1364
- *
1365
- * @example
1366
- * ```ts
1367
- * const bazaar = new BazaarClient();
1368
- *
1369
- * // Only endpoints a probe actually reached, best-curated first
1370
- * const page = await bazaar.listResources({ limit: 20, health: 'alive', tier: 'vip' });
1371
- * for (const r of page.items) {
1372
- * console.log(r.url, r.health?.status, r.health?.latencyMs, r.curation?.label);
1373
- * }
1374
- *
1375
- * // Free-text search runs server-side over the whole catalog
1376
- * const hits = await bazaar.listResources({ q: 'logs' });
1377
- * console.log(hits.pagination.total);
1378
- *
1379
- * // Register your own
1380
- * await bazaar.registerResource({
1381
- * url: 'https://api.example.com/v1/generate',
1382
- * description: 'Generate images with AI',
1383
- * accepts: [{
1384
- * scheme: 'exact',
1385
- * network: 'eip155:8453',
1386
- * asset: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
1387
- * amount: '10000',
1388
- * payTo: '0xYourWallet...',
1389
- * maxTimeoutSeconds: 60,
1390
- * }],
1391
- * metadata: { category: 'ai', tags: ['image'] },
1392
- * });
1393
- * ```
1394
- */
1395
- declare class BazaarClient {
1396
- private readonly baseUrl;
1397
- private readonly timeout;
1398
- constructor(options?: BazaarClientOptions);
1399
- /**
1400
- * Issue a request against the facilitator with the configured timeout.
1401
- */
1402
- private request;
1403
- /**
1404
- * List resources from the discovery registry.
1405
- *
1406
- * @param options - Server-side filters and pagination
1407
- * @returns One page of resources plus the total across all pages
1408
- *
1409
- * @example
1410
- * ```ts
1411
- * const page = await bazaar.listResources({ network: 'eip155:8453', health: 'alive' });
1412
- * ```
1413
- */
1414
- listResources(options?: DiscoveryListOptions): Promise<DiscoveryResponse>;
1415
- /**
1416
- * Walk the whole filtered catalog, one page at a time.
1417
- *
1418
- * Pages are fetched in sequence rather than in parallel: the read routes are
1419
- * rate limited, and a burst of parallel pages is how a legitimate catalog
1420
- * walk turns into a wall of 429s.
1421
- *
1422
- * @param options - Same filters as {@link listResources}; `limit` is the page size
1423
- *
1424
- * @example
1425
- * ```ts
1426
- * for await (const r of bazaar.iterateResources({ health: 'alive' })) {
1427
- * console.log(r.url);
1428
- * }
1429
- * ```
1430
- */
1431
- iterateResources(options?: DiscoveryListOptions): AsyncGenerator<DiscoveryResource, void, undefined>;
1432
- /**
1433
- * Look up a single resource by its URL.
1434
- *
1435
- * The registry keys on URL and has no by-id lookup, so this searches and
1436
- * then matches exactly.
1437
- *
1438
- * @param resourceUrl - Exact URL of the resource
1439
- * @returns The resource, or null when it is not registered
1440
- */
1441
- getResourceByUrl(resourceUrl: string): Promise<DiscoveryResource | null>;
1442
- /**
1443
- * Register a paid resource in the discovery registry.
1444
- *
1445
- * Registration is open and rate limited; re-registering a known URL updates
1446
- * the existing record rather than creating a duplicate.
1447
- *
1448
- * @param options - Resource details
1449
- * @returns The registry's acknowledgement
1450
- */
1451
- registerResource(options: DiscoveryRegisterOptions): Promise<Record<string, unknown>>;
1452
- /**
1453
- * Aggregate catalog metrics (60s cached server-side).
1454
- *
1455
- * @returns Counts by source, facilitator, network, tier and liveness
1456
- */
1457
- getStats(): Promise<DiscoveryStats>;
1458
- /**
1459
- * Check that the facilitator serving the registry is up.
1460
- *
1461
- * @returns True when the facilitator answers its health check
1462
- */
1463
- healthCheck(): Promise<boolean>;
1464
- /**
1465
- * @deprecated Renamed to {@link listResources}, which returns the registry's
1466
- * real `{ items, pagination }` envelope. The old `discover()` returned a
1467
- * `{ resources, page, totalPages }` shape that no endpoint ever served.
1468
- */
1469
- discover(options?: DiscoveryListOptions): Promise<DiscoveryResponse>;
1470
- }
1471
- /**
1472
- * @deprecated Use {@link DiscoveryResource}. The old shape (`id`, `name`,
1473
- * `pricePerRequest`, `isActive`, ISO `createdAt`) described an API that was
1474
- * never deployed.
1475
- */
1476
- type BazaarResource = DiscoveryResource;
1477
- /** @deprecated Use {@link DiscoveryResponse}. */
1478
- type BazaarDiscoverResponse = DiscoveryResponse;
1479
- /** @deprecated Use {@link DiscoveryListOptions}. */
1480
- type BazaarDiscoverOptions = DiscoveryListOptions;
1481
- /** @deprecated Use {@link DiscoveryRegisterOptions}. */
1482
- type BazaarRegisterOptions = DiscoveryRegisterOptions;
1483
- /**
1484
- * Escrow payment status
1485
- */
1486
- type EscrowStatus = 'pending' | 'held' | 'released' | 'refunded' | 'disputed' | 'expired';
1487
- /**
1488
- * Refund request status
1489
- */
1490
- type RefundStatus = 'pending' | 'approved' | 'rejected' | 'processed' | 'disputed';
1491
- /**
1492
- * Dispute resolution outcome
1493
- */
1494
- type DisputeOutcome = 'pending' | 'payer_wins' | 'recipient_wins' | 'split';
1495
- /**
1496
- * Escrow payment record
1497
- */
1498
- interface EscrowPayment {
1499
- /** Unique escrow ID */
1500
- id: string;
1501
- /** Original payment header (base64 encoded) */
1502
- paymentHeader: string;
1503
- /** Current status */
1504
- status: EscrowStatus;
1505
- /** Network where payment was made */
1506
- network: string;
1507
- /** Payer address */
1508
- payer: string;
1509
- /** Recipient address */
1510
- recipient: string;
1511
- /** Amount in atomic units */
1512
- amount: string;
1513
- /** Token/asset contract */
1514
- asset: string;
1515
- /** Resource URL being paid for */
1516
- resource: string;
1517
- /** Escrow expiration timestamp (ISO) */
1518
- expiresAt: string;
1519
- /** Release conditions (optional) */
1520
- releaseConditions?: {
1521
- /** Minimum time before release (seconds) */
1522
- minHoldTime?: number;
1523
- /** Required confirmations */
1524
- confirmations?: number;
1525
- /** Custom condition metadata */
1526
- custom?: unknown;
1527
- };
1528
- /** Transaction hash if released/refunded */
1529
- transactionHash?: string;
1530
- /** Creation timestamp (ISO) */
1531
- createdAt: string;
1532
- /** Last update timestamp (ISO) */
1533
- updatedAt: string;
1534
- }
1535
- /**
1536
- * Refund request record
1537
- */
1538
- interface RefundRequest {
1539
- /** Unique refund request ID */
1540
- id: string;
1541
- /** Related escrow ID */
1542
- escrowId: string;
1543
- /** Current status */
1544
- status: RefundStatus;
1545
- /** Reason for refund request */
1546
- reason: string;
1547
- /** Additional evidence/details */
1548
- evidence?: string;
1549
- /** Amount requested (may be partial) */
1550
- amountRequested: string;
1551
- /** Amount approved (if any) */
1552
- amountApproved?: string;
1553
- /** Requester (payer) address */
1554
- requester: string;
1555
- /** Transaction hash if processed */
1556
- transactionHash?: string;
1557
- /** Response from recipient/facilitator */
1558
- response?: {
1559
- status: 'approved' | 'rejected';
1560
- reason?: string;
1561
- respondedAt: string;
1562
- };
1563
- /** Creation timestamp (ISO) */
1564
- createdAt: string;
1565
- /** Last update timestamp (ISO) */
1566
- updatedAt: string;
1567
- }
1568
- /**
1569
- * Dispute record
1570
- */
1571
- interface Dispute {
1572
- /** Unique dispute ID */
1573
- id: string;
1574
- /** Related escrow ID */
1575
- escrowId: string;
1576
- /** Related refund request ID (if any) */
1577
- refundRequestId?: string;
1578
- /** Dispute outcome */
1579
- outcome: DisputeOutcome;
1580
- /** Initiator (payer or recipient) */
1581
- initiator: 'payer' | 'recipient';
1582
- /** Reason for dispute */
1583
- reason: string;
1584
- /** Evidence from payer */
1585
- payerEvidence?: string;
1586
- /** Evidence from recipient */
1587
- recipientEvidence?: string;
1588
- /** Arbitration notes */
1589
- arbitrationNotes?: string;
1590
- /** Amount resolved to payer */
1591
- payerAmount?: string;
1592
- /** Amount resolved to recipient */
1593
- recipientAmount?: string;
1594
- /** Transaction hash(es) for resolution */
1595
- transactionHashes?: string[];
1596
- /** Creation timestamp (ISO) */
1597
- createdAt: string;
1598
- /** Resolution timestamp (ISO) */
1599
- resolvedAt?: string;
1600
- }
1601
- /**
1602
- * Options for creating an escrow payment
1603
- */
1604
- interface CreateEscrowOptions {
1605
- /** Payment header (from client SDK) */
1606
- paymentHeader: string;
1607
- /** Payment requirements */
1608
- requirements: PaymentRequirements;
1609
- /** Escrow duration in seconds (default: 86400 = 24h) */
1610
- escrowDuration?: number;
1611
- /** Release conditions */
1612
- releaseConditions?: {
1613
- minHoldTime?: number;
1614
- confirmations?: number;
1615
- custom?: unknown;
1616
- };
1617
- }
1618
- /**
1619
- * Options for requesting a refund
1620
- */
1621
- interface RequestRefundOptions {
1622
- /** Escrow ID to refund */
1623
- escrowId: string;
1624
- /** Reason for refund */
1625
- reason: string;
1626
- /** Amount to refund (full amount if not specified) */
1627
- amount?: string;
1628
- /** Supporting evidence */
1629
- evidence?: string;
1630
- }
1631
- /**
1632
- * Options for the EscrowClient
1633
- */
1634
- interface EscrowClientOptions {
1635
- /** Base URL of the Escrow API (default: https://escrow.ultravioletadao.xyz) */
1636
- baseUrl?: string;
1637
- /** API key for authenticated operations */
1638
- apiKey?: string;
1639
- /** Request timeout in milliseconds (default: 30000) */
1640
- timeout?: number;
1641
- }
1642
- /**
1643
- * Client for x402 Escrow & Refund operations
1644
- *
1645
- * The Escrow system holds payments until service is verified,
1646
- * enabling refunds and dispute resolution.
1647
- *
1648
- * @example
1649
- * ```ts
1650
- * // Create escrow payment (backend)
1651
- * const escrow = new EscrowClient();
1652
- * const escrowPayment = await escrow.createEscrow({
1653
- * paymentHeader: req.headers['x-payment'],
1654
- * requirements: paymentRequirements,
1655
- * escrowDuration: 86400, // 24 hours
1656
- * });
1657
- *
1658
- * // After service is provided, release the escrow
1659
- * await escrow.release(escrowPayment.id);
1660
- *
1661
- * // If service not provided, payer can request refund
1662
- * await escrow.requestRefund({
1663
- * escrowId: escrowPayment.id,
1664
- * reason: 'Service not delivered within expected timeframe',
1665
- * });
1666
- * ```
1667
- */
1668
- declare class EscrowClient {
1669
- private readonly baseUrl;
1670
- private readonly apiKey?;
1671
- private readonly timeout;
1672
- constructor(options?: EscrowClientOptions);
1673
- private getHeaders;
1674
- /**
1675
- * Create an escrow payment
1676
- *
1677
- * Holds the payment in escrow until released or refunded.
1678
- *
1679
- * @param options - Escrow creation options
1680
- * @returns Created escrow payment
1681
- */
1682
- createEscrow(options: CreateEscrowOptions): Promise<EscrowPayment>;
1683
- /**
1684
- * Get escrow payment by ID
1685
- *
1686
- * @param escrowId - Escrow payment ID
1687
- * @returns Escrow payment details
1688
- */
1689
- getEscrow(escrowId: string): Promise<EscrowPayment>;
1690
- /**
1691
- * Release escrow funds to recipient
1692
- *
1693
- * Call this after service has been successfully provided.
1694
- *
1695
- * @param escrowId - Escrow payment ID
1696
- * @returns Updated escrow payment with transaction hash
1697
- */
1698
- release(escrowId: string): Promise<EscrowPayment>;
1699
- /**
1700
- * Request a refund for an escrow payment
1701
- *
1702
- * Initiates a refund request that must be approved.
1703
- *
1704
- * @param options - Refund request options
1705
- * @returns Created refund request
1706
- */
1707
- requestRefund(options: RequestRefundOptions): Promise<RefundRequest>;
1708
- /**
1709
- * Approve a refund request (for recipients)
1710
- *
1711
- * @param refundId - Refund request ID
1712
- * @param amount - Amount to approve (may be less than requested)
1713
- * @returns Updated refund request
1714
- */
1715
- approveRefund(refundId: string, amount?: string): Promise<RefundRequest>;
1716
- /**
1717
- * Reject a refund request (for recipients)
1718
- *
1719
- * @param refundId - Refund request ID
1720
- * @param reason - Reason for rejection
1721
- * @returns Updated refund request
1722
- */
1723
- rejectRefund(refundId: string, reason: string): Promise<RefundRequest>;
1724
- /**
1725
- * Get refund request by ID
1726
- *
1727
- * @param refundId - Refund request ID
1728
- * @returns Refund request details
1729
- */
1730
- getRefund(refundId: string): Promise<RefundRequest>;
1731
- /**
1732
- * Open a dispute for an escrow payment
1733
- *
1734
- * Initiates arbitration when payer and recipient disagree.
1735
- *
1736
- * @param escrowId - Escrow payment ID
1737
- * @param reason - Reason for dispute
1738
- * @param evidence - Supporting evidence
1739
- * @returns Created dispute
1740
- */
1741
- openDispute(escrowId: string, reason: string, evidence?: string): Promise<Dispute>;
1742
- /**
1743
- * Submit evidence to a dispute
1744
- *
1745
- * @param disputeId - Dispute ID
1746
- * @param evidence - Evidence to submit
1747
- * @returns Updated dispute
1748
- */
1749
- submitEvidence(disputeId: string, evidence: string): Promise<Dispute>;
1750
- /**
1751
- * Get dispute by ID
1752
- *
1753
- * @param disputeId - Dispute ID
1754
- * @returns Dispute details
1755
- */
1756
- getDispute(disputeId: string): Promise<Dispute>;
1757
- /**
1758
- * List escrow payments (with filters)
1759
- *
1760
- * @param options - Filter and pagination options
1761
- * @returns Paginated list of escrow payments
1762
- */
1763
- listEscrows(options?: {
1764
- status?: EscrowStatus;
1765
- payer?: string;
1766
- recipient?: string;
1767
- page?: number;
1768
- limit?: number;
1769
- }): Promise<{
1770
- escrows: EscrowPayment[];
1771
- total: number;
1772
- page: number;
1773
- limit: number;
1774
- hasMore: boolean;
1775
- }>;
1776
- /**
1777
- * Query on-chain escrow state from the facilitator
1778
- *
1779
- * Calls POST /escrow/state to read current escrow state without settlement.
1780
- *
1781
- * @param options - Escrow state query parameters
1782
- * @returns On-chain escrow state (status, balance, timestamps)
1783
- *
1784
- * @example
1785
- * ```ts
1786
- * const state = await escrow.getEscrowState({
1787
- * network: 'base-mainnet',
1788
- * payer: '0xPayer...',
1789
- * recipient: '0xRecipient...',
1790
- * nonce: '0x1234...',
1791
- * });
1792
- * console.log(`Status: ${state.status}`);
1793
- * ```
1794
- */
1795
- getEscrowState(options: {
1796
- network: string;
1797
- payer: string;
1798
- recipient: string;
1799
- nonce: string;
1800
- }): Promise<Record<string, unknown>>;
1801
- /**
1802
- * Check Escrow API health
1803
- *
1804
- * @returns True if healthy
1805
- */
1806
- healthCheck(): Promise<boolean>;
1807
- }
1808
- /**
1809
- * Check if an escrow can be released
1810
- *
1811
- * @param escrow - Escrow payment to check
1812
- * @returns True if the escrow can be released
1813
- */
1814
- declare function canReleaseEscrow(escrow: EscrowPayment): boolean;
1815
- /**
1816
- * Check if an escrow can be refunded
1817
- *
1818
- * @param escrow - Escrow payment to check
1819
- * @returns True if the escrow can be refunded
1820
- */
1821
- declare function canRefundEscrow(escrow: EscrowPayment): boolean;
1822
- /**
1823
- * Check if an escrow is expired
1824
- *
1825
- * @param escrow - Escrow payment to check
1826
- * @returns True if the escrow is expired
1827
- */
1828
- declare function isEscrowExpired(escrow: EscrowPayment): boolean;
1829
- /**
1830
- * Calculate time remaining until escrow expires
1831
- *
1832
- * @param escrow - Escrow payment to check
1833
- * @returns Milliseconds until expiration (negative if expired)
1834
- */
1835
- declare function escrowTimeRemaining(escrow: EscrowPayment): number;
1836
- /**
1837
- * ERC-8004 extension identifier
1838
- */
1839
- declare const ERC8004_EXTENSION_ID = "8004-reputation";
1840
- /**
1841
- * Agent ID type: EVM uses sequential uint256 (number), Solana uses base58 pubkey (string)
1842
- */
1843
- type AgentId = number | string;
1844
- /**
1845
- * ERC-8004 contract addresses per network (21 networks: 19 EVM + 2 Solana)
1846
- */
1847
- declare const ERC8004_CONTRACTS: Record<string, {
1848
- identityRegistry?: string;
1849
- reputationRegistry?: string;
1850
- validationRegistry?: string;
1851
- agentRegistryProgram?: string;
1852
- atomEngineProgram?: string;
1853
- }>;
1854
- /**
1855
- * Return the network name the facilitator actually accepts.
1856
- *
1857
- * `base-mainnet` reads like the canonical spelling and is not: the facilitator
1858
- * answers `400 {"error": "Invalid network: base-mainnet"}`. Every name is passed
1859
- * through here before it reaches a URL or a request body, so callers holding the
1860
- * old spelling keep working instead of being rejected at the edge.
1861
- */
1862
- declare function wireNetwork(network: string): string;
1863
- /**
1864
- * Network type for ERC-8004 operations (21 networks: 19 EVM + 2 Solana)
1865
- *
1866
- * These are the names the FACILITATOR accepts, verified against
1867
- * GET /feedback -> supportedNetworks. 'base-mainnet' is kept only as a
1868
- * deprecated alias: the facilitator rejects it outright (400 "Invalid network"),
1869
- * so anything passed through this module is normalised to 'base' before it
1870
- * reaches the wire. Use 'base'.
1871
- */
1872
- type Erc8004Network = 'ethereum' | 'base' | 'polygon' | 'arbitrum' | 'optimism' | 'celo' | 'bsc' | 'monad' | 'avalanche' | 'scroll' | 'skale-base' | 'base-mainnet' | 'ethereum-sepolia' | 'base-sepolia' | 'polygon-amoy' | 'arbitrum-sepolia' | 'optimism-sepolia' | 'celo-sepolia' | 'avalanche-fuji' | 'skale-base-sepolia' | 'solana' | 'solana-devnet';
1873
- /**
1874
- * Networks where the facilitator serves the RELAYED feedback rail, i.e. where
1875
- * Execution Market has deployed a `FeedbackDelegate` and the facilitator
1876
- * verified it on-chain (code present, and its `REPUTATION_REGISTRY()` reads
1877
- * back that network's registry).
1878
- *
1879
- * Anywhere else `POST /feedback/evm/prepare` answers 400 — and it should. An
1880
- * invented delegate address would send a type-4 transaction to an account with
1881
- * no code behind it, and in the EVM a `.call()` to an address with no code
1882
- * RETURNS SUCCESS. The failure would look exactly like a rating that rated
1883
- * nobody.
1884
- *
1885
- * `avalanche` is absent and is not waiting to join: the C-Chain rejects the
1886
- * transaction type itself (`-32000 transaction type not supported`), so there
1887
- * is nothing to deploy against. Anchor the rating on a chain that supports
1888
- * EIP-7702; the payment stays where it was made.
1889
- */
1890
- declare const RELAYED_FEEDBACK_NETWORKS: readonly Erc8004Network[];
1891
- /**
1892
- * Whether `network` serves the rater-authored feedback rail.
1893
- *
1894
- * Lets a caller route without paying a round trip for a 400. The facilitator
1895
- * re-checks the delegate on-chain on every request regardless — this list is a
1896
- * routing hint, never the authority.
1897
- */
1898
- declare function supportsRelayedFeedback(network: string): boolean;
1899
- /**
1900
- * An EIP-7702 authorization, as a wallet produces it.
1901
- *
1902
- * Needed only the first time a rater rates: it points their EOA at the
1903
- * `FeedbackDelegate`. Once delegated, `prepare` answers `delegated: true` and
1904
- * the submission carries no authorization at all.
1905
- */
1906
- interface RelayAuthorizationParams {
1907
- /**
1908
- * Chain the authorization is for.
1909
- *
1910
- * `0` is EIP-7702's wildcard and is valid on EVERY chain — a far broader
1911
- * grant than pinning this one. Send the chain id `prepare` returned.
1912
- */
1913
- chainId: number;
1914
- /**
1915
- * The delegate the account is pointed at. Must be the address `prepare`
1916
- * offered; the facilitator refuses anything else before it pays for a
1917
- * transaction.
1918
- */
1919
- address: string;
1920
- /** The rater account's nonce at the moment the authorization executes */
1921
- nonce: number;
1922
- yParity: number;
1923
- r: string;
1924
- s: string;
1925
- }
1926
- /**
1927
- * Request body for `POST /feedback/evm/prepare`.
1928
- *
1929
- * `rater` is the address that will appear on-chain as the author, which is the
1930
- * whole point of this rail.
1931
- */
1932
- interface PrepareRelayFeedbackRequest {
1933
- x402Version: 1 | 2;
1934
- network: Erc8004Network;
1935
- feedback: FeedbackParams & {
1936
- rater: string;
1937
- };
1938
- }
1939
- /**
1940
- * Response from `POST /feedback/evm/prepare`.
1941
- *
1942
- * Everything the rater has to sign so the CHAIN records them as the author
1943
- * while the facilitator pays the gas.
1944
- */
1945
- interface PrepareRelayFeedbackResponse {
1946
- success: boolean;
1947
- /** The `FeedbackDelegate` the rater's EOA must be delegated to */
1948
- delegate?: string;
1949
- /** Registry calldata the rater is authorising, hex-encoded */
1950
- data?: string;
1951
- /**
1952
- * The value the rater's signature must recover against.
1953
- *
1954
- * **The EIP-191 envelope is already applied here.** A holder of a raw key
1955
- * signs this directly as a prehash (viem's `sign({ hash })`, ethers'
1956
- * `signingKey.sign`). A WALLET must not be handed this value: `personal_sign`
1957
- * applies the envelope itself, so it gets wrapped twice and recovers an
1958
- * address that is not the rater. Wallets sign {@link signingPayload}.
1959
- */
1960
- digest?: string;
1961
- /**
1962
- * The same hash with the envelope still OFF — what a wallet signs.
1963
- *
1964
- * `keccak256('\x19Ethereum Signed Message:\n32' || signingPayload)` is
1965
- * exactly {@link digest}, so a client can check the two against each other
1966
- * rather than rebuilding the preimage from `data`.
1967
- *
1968
- * Requires facilitator v1.95.0+. Older facilitators omit it; a client that
1969
- * needs it should fail loudly rather than fall back to signing `digest`
1970
- * through a wallet, which produces a well-formed signature that authorises
1971
- * nobody.
1972
- */
1973
- signingPayload?: string;
1974
- /**
1975
- * The full `eth_signTypedData_v4` payload. **v4 delegates only.**
1976
- *
1977
- * Present exactly when the delegate deployed on that chain is v4, which the
1978
- * facilitator reads from the chain per request rather than assuming from a
1979
- * release. **When it is present, sign IT** — the wallet renders the agent, the
1980
- * score, the tags and the deadline as named fields, so the rater sees what
1981
- * they authorise instead of a hex blob.
1982
- *
1983
- * v4 carries no {@link signingPayload} and needs none: `signTypedData` has no
1984
- * envelope to apply twice, which is the entire class of bug that kept the v3
1985
- * rail at zero signatures for days.
1986
- *
1987
- * Requires facilitator v1.96.0+.
1988
- */
1989
- typedData?: Record<string, unknown>;
1990
- /**
1991
- * Unix seconds after which the authorisation is void. Short on purpose:
1992
- * relaying is permissionless, so a signed authorisation is live in the wild
1993
- * until it expires.
1994
- */
1995
- deadline?: number;
1996
- /** Single-use value binding this authorisation. Echo it back on submit */
1997
- nonce?: string;
1998
- /**
1999
- * Whether the account is already delegated. When `false` the submission MUST
2000
- * carry an `authorization`.
2001
- */
2002
- delegated: boolean;
2003
- /** The account nonce to put in the EIP-7702 authorization, when needed */
2004
- accountNonce?: number;
2005
- chainId: number;
2006
- error?: string;
2007
- network: Erc8004Network;
2008
- }
2009
- /**
2010
- * Request body for `POST /feedback/evm/submit`.
2011
- *
2012
- * The feedback parameters are not redundant with `prepare`: the facilitator
2013
- * rebuilds the registry calldata from them and requires the rater's signature
2014
- * to cover exactly that. It does not relay calldata it was handed.
2015
- */
2016
- interface SubmitRelayFeedbackRequest {
2017
- x402Version: 1 | 2;
2018
- network: Erc8004Network;
2019
- feedback: FeedbackParams & {
2020
- rater: string;
2021
- };
2022
- /** The deadline `prepare` returned */
2023
- deadline: number;
2024
- /** The single-use nonce `prepare` returned */
2025
- nonce: string;
2026
- /**
2027
- * The rater's signature. It must recover to `rater` over `digest` — so
2028
- * either a raw-key prehash signature over `digest`, or a wallet
2029
- * `personal_sign` over `signingPayload`. Not `personal_sign` over `digest`.
2030
- */
2031
- signature: string;
2032
- /** Required only when `prepare` answered `delegated: false` */
2033
- authorization?: RelayAuthorizationParams;
2034
- }
2035
- /**
2036
- * Request body for `POST /feedback/response/evm/prepare`.
2037
- *
2038
- * `responder` is the address the chain will record as the author.
2039
- */
2040
- interface PrepareRelayResponseRequest {
2041
- x402Version: 1 | 2;
2042
- network: Erc8004Network;
2043
- responder: string;
2044
- agentId: number | string;
2045
- /** WHOSE feedback is being answered — inside the signed struct. */
2046
- clientAddress: string;
2047
- /** Which feedback (1-indexed) — also inside the struct. */
2048
- feedbackIndex: number;
2049
- responseUri: string;
2050
- responseHash?: string;
2051
- }
2052
- /** Request body for `POST /feedback/response/evm/submit`. */
2053
- interface SubmitRelayResponseRequest {
2054
- x402Version: 1 | 2;
2055
- network: Erc8004Network;
2056
- responder: string;
2057
- agentId: number | string;
2058
- clientAddress: string;
2059
- feedbackIndex: number;
2060
- responseUri: string;
2061
- responseHash?: string;
2062
- deadline: number;
2063
- nonce: string;
2064
- /** The responder's signature over the typed data. */
2065
- signature: string;
2066
- authorization?: RelayAuthorizationParams;
2067
- }
2068
- /**
2069
- * Proof of payment returned when settling with ERC-8004 extension
2070
- */
2071
- interface ProofOfPayment {
2072
- /** Transaction hash of the settled payment */
2073
- transactionHash: string;
2074
- /** Block number where the transaction was included */
2075
- blockNumber: number;
2076
- /** Network where the payment was settled */
2077
- network: string;
2078
- /** The payer (consumer/client) address */
2079
- payer: string;
2080
- /** The payee (agent/resource owner) address */
2081
- payee: string;
2082
- /** Amount paid in token base units */
2083
- amount: string;
2084
- /** Token contract address */
2085
- token: string;
2086
- /** Unix timestamp of the block */
2087
- timestamp: number;
2088
- /** Keccak256 hash of the payment data for verification */
2089
- paymentHash: string;
2090
- }
2091
- /**
2092
- * Extended settle response with ERC-8004 proof of payment
2093
- */
2094
- interface SettleResponseWithProof extends SettleResponse {
2095
- /** Proof of payment for ERC-8004 reputation submission */
2096
- proofOfPayment?: ProofOfPayment;
2097
- }
2098
- /**
2099
- * Agent identity from the Identity Registry
2100
- */
2101
- interface AgentIdentity {
2102
- /** The agent's ID (EVM: sequential uint256, Solana: base58 pubkey string) */
2103
- agentId: AgentId;
2104
- /** Owner address of the agent NFT */
2105
- owner: string;
2106
- /** URI pointing to agent registration file */
2107
- agentUri: string;
2108
- /** Payment wallet address (if set) */
2109
- agentWallet?: string;
2110
- /** Network where the agent is registered */
2111
- network: Erc8004Network;
2112
- }
2113
- /**
2114
- * Agent registration file structure (resolved from agentURI)
2115
- */
2116
- interface AgentRegistrationFile {
2117
- /** Type identifier */
2118
- type: string;
2119
- /** Agent name */
2120
- name: string;
2121
- /** Agent description */
2122
- description: string;
2123
- /** Image URL */
2124
- image?: string;
2125
- /** List of services the agent provides */
2126
- services: AgentService[];
2127
- /** Whether x402 payments are supported */
2128
- x402Support: boolean;
2129
- /** Whether the agent is active */
2130
- active: boolean;
2131
- /** List of registrations across chains */
2132
- registrations: AgentRegistration[];
2133
- /** Supported trust models */
2134
- supportedTrust: string[];
2135
- }
2136
- /**
2137
- * Agent service entry
2138
- */
2139
- interface AgentService {
2140
- name: string;
2141
- endpoint: string;
2142
- version?: string;
2143
- }
2144
- /**
2145
- * Agent registration reference
2146
- */
2147
- interface AgentRegistration {
2148
- agentId: AgentId;
2149
- agentRegistry: string;
2150
- }
2151
- /**
2152
- * Reputation summary for an agent
2153
- */
2154
- interface ReputationSummary {
2155
- /** Agent ID (EVM: number, Solana: string) */
2156
- agentId: AgentId;
2157
- /** Number of feedback entries */
2158
- count: number;
2159
- /** Aggregated value */
2160
- summaryValue: number;
2161
- /** Decimal places for summaryValue */
2162
- summaryValueDecimals: number;
2163
- /** Network */
2164
- network: Erc8004Network;
2165
- }
2166
- /**
2167
- * Individual feedback entry
2168
- */
2169
- interface FeedbackEntry {
2170
- /** Client who submitted the feedback */
2171
- client: string;
2172
- /** Feedback index (1-indexed) */
2173
- feedbackIndex: number;
2174
- /** Feedback value */
2175
- value: number;
2176
- /** Value decimals */
2177
- valueDecimals: number;
2178
- /** Primary tag */
2179
- tag1: string;
2180
- /** Secondary tag */
2181
- tag2: string;
2182
- /** Whether this feedback was revoked */
2183
- isRevoked: boolean;
2184
- }
2185
- /**
2186
- * Parameters for submitting reputation feedback
2187
- */
2188
- interface FeedbackParams {
2189
- /** The agent's ID (EVM: tokenId number, Solana: base58 pubkey string) */
2190
- agentId: AgentId;
2191
- /** Feedback value (e.g., 87 for 87/100) */
2192
- value: number;
2193
- /** Decimal places for value interpretation (0-18) */
2194
- valueDecimals?: number;
2195
- /** Primary categorization tag (e.g., "starred", "uptime") */
2196
- tag1?: string;
2197
- /** Secondary categorization tag */
2198
- tag2?: string;
2199
- /** Service endpoint that was used */
2200
- endpoint?: string;
2201
- /** URI to off-chain feedback file (IPFS, HTTPS) */
2202
- feedbackUri?: string;
2203
- /** Keccak256 hash of feedback content (for integrity) */
2204
- feedbackHash?: string;
2205
- /**
2206
- * Quality score 0-100.
2207
- *
2208
- * Solana only, and effectively required there: the ATOM Engine ignores an
2209
- * unscored feedback. It is written to the agent but contributes nothing to
2210
- * reputation, and the program reports `had_impact=false`. This is not
2211
- * retroactive — reputation stays at zero however much unscored feedback
2212
- * accumulates.
2213
- */
2214
- score?: number;
2215
- /** Proof of payment (required for authorized feedback) */
2216
- proof?: ProofOfPayment;
2217
- }
2218
- /**
2219
- * Feedback request body for POST /feedback
2220
- */
2221
- interface FeedbackRequest {
2222
- /** x402 protocol version */
2223
- x402Version: 1 | 2;
2224
- /** Network where feedback will be submitted */
2225
- network: Erc8004Network;
2226
- /** Feedback parameters */
2227
- feedback: FeedbackParams;
2228
- }
2229
- /**
2230
- * Feedback response from POST /feedback
2231
- */
2232
- interface FeedbackResponse extends FacilitatorFailureFields {
2233
- /** Whether the feedback was successfully submitted */
2234
- success: boolean;
2235
- /** Transaction hash of the feedback submission */
2236
- transaction?: string;
2237
- /** Feedback index assigned (1-indexed) */
2238
- feedbackIndex?: number;
2239
- /** Error message (if failed) */
2240
- error?: string;
2241
- /** Network where feedback was submitted */
2242
- network: Erc8004Network;
2243
- }
2244
- /**
2245
- * Reputation query response
2246
- */
2247
- /**
2248
- * Error from an ERC-8004 lookup, carrying the HTTP status as a field.
2249
- *
2250
- * `notFound` and `retryable` are mutually exclusive and must stay that way in
2251
- * calling code: the facilitator answers 404 for "this address owns no agent"
2252
- * and 503 for "I could not find out", usually an RPC failure behind it.
2253
- * Treating a 503 as absence is how a transient failure becomes a permanent
2254
- * wrong answer — on a registration path it mints a second agent for an owner
2255
- * who already has one, burning gas and leaving an orphan.
2256
- */
2257
- declare class Erc8004LookupError extends Error {
2258
- /** HTTP status returned by the facilitator */
2259
- readonly status: number;
2260
- /** Raw response body, for debugging */
2261
- readonly body: string;
2262
- /**
2263
- * `Retry-After`, already clamped, when the facilitator sent one.
2264
- *
2265
- * Optional so every existing three-argument construction keeps compiling; it
2266
- * falls back to the default wait rather than to zero, because a caller that
2267
- * retries instantly on a 503 is the load that caused it.
2268
- */
2269
- private readonly retryAfterHint;
2270
- constructor(message: string, status: number, body: string, retryAfterSeconds?: number);
2271
- /** The address genuinely owns no agent on this network. */
2272
- get notFound(): boolean;
2273
- /**
2274
- * The lookup reached no verdict. Retry; never read as "owns nothing".
2275
- *
2276
- * `502` and `504` join `503` and `429` here: a gateway that answered on the
2277
- * facilitator's behalf is exactly as silent about the agent's existence, and
2278
- * reading either as absence has the same consequence -- a duplicate mint.
2279
- *
2280
- * **Except when the body says otherwise.** `POST /register` goes through the
2281
- * same EVM `send_transaction_from` as a settle, so it can answer
2282
- * `settlement_unconfirmed`: the mint was broadcast and may be mined. That is
2283
- * a `502` where retrying is precisely the thing that mints the duplicate this
2284
- * class exists to prevent, so an explicit `retryable: false` wins over the
2285
- * status. See {@link SETTLEMENT_UNCONFIRMED}.
2286
- */
2287
- get retryable(): boolean;
2288
- /**
2289
- * The facilitator's own `reason`, when the body carried one.
2290
- *
2291
- * On a WRITE route this is the writer-lease reason and it decides whether the
2292
- * request may be re-sent; see {@link isReplayableLeaseReason}.
2293
- */
2294
- get reason(): string | undefined;
2295
- /** The facilitator's machine-readable `error` code, when the body carried one. */
2296
- get errorCode(): string | undefined;
2297
- /**
2298
- * A transaction that WAS broadcast and could not be confirmed.
2299
- *
2300
- * Present on `settlement_unconfirmed`. This is what to do INSTEAD of
2301
- * retrying: look it up on chain. An error that carries "do not retry" and no
2302
- * hash leaves the caller with nothing to act on.
2303
- */
2304
- get transaction(): string | undefined;
2305
- /** The payment id for {@link transaction}, identical to a successful settle's. */
2306
- get paymentId(): string | undefined;
2307
- /**
2308
- * The facilitator NAMED a reason proving it executed nothing.
2309
- *
2310
- * False for `forward_failed` and for every unattributed 5xx: "something
2311
- * answered" is not evidence that nothing ran. On `/register`, replaying when
2312
- * this is false is the sequence that minted five duplicate agents.
2313
- */
2314
- get safeToReplay(): boolean;
2315
- /** Seconds to wait before retrying, clamped. Absent when not retryable. */
2316
- get retryAfterSeconds(): number | undefined;
2317
- }
2318
- /**
2319
- * ATOM Engine reputation analytics (Solana only).
2320
- *
2321
- * Present only when the agent's `atom_stats` account has been initialized. The
2322
- * facilitator does that during `registerAgent`; agents registered elsewhere may
2323
- * never have it, in which case their feedback is never scored.
2324
- *
2325
- * The engine measures quality through EMA scores, so there are no
2326
- * positive/negative tallies.
2327
- */
2328
- interface AtomStats {
2329
- /** Trust tier 0-4 */
2330
- trustTier: number;
2331
- /** Human-readable trust tier */
2332
- trustTierName: string;
2333
- /** Cached quality score */
2334
- qualityScore: number;
2335
- /** Cached loyalty score */
2336
- loyaltyScore: number;
2337
- /** Statistical confidence */
2338
- confidence: number;
2339
- /** Risk assessment (lower is better) */
2340
- riskScore: number;
2341
- /** Client diversity from HyperLogLog */
2342
- diversityRatio: number;
2343
- /** Lowest score ever recorded */
2344
- minScore: number;
2345
- /** Highest score ever recorded */
2346
- maxScore: number;
2347
- /** Most recent score recorded */
2348
- lastScore: number;
2349
- /** Total feedback counted by the engine */
2350
- feedbackCount: number;
2351
- /** Slot of the most recent feedback */
2352
- lastFeedbackSlot: number;
2353
- }
2354
- interface ReputationResponse {
2355
- agentId: AgentId;
2356
- summary: ReputationSummary;
2357
- feedback?: FeedbackEntry[];
2358
- /** ATOM Engine analytics; absent when the agent has no initialized stats */
2359
- atomStats?: AtomStats | null;
2360
- network: Erc8004Network;
2361
- }
2362
- /**
2363
- * Key-value metadata entry for agent registration
2364
- */
2365
- interface MetadataEntryParam {
2366
- /** Metadata key */
2367
- key: string;
2368
- /** Metadata value (hex-encoded bytes or UTF-8 string) */
2369
- value: string;
2370
- }
2371
- /**
2372
- * Request body for POST /register
2373
- */
2374
- interface RegisterAgentRequest {
2375
- /** x402 protocol version */
2376
- x402Version: 1 | 2;
2377
- /** Network where agent will be registered */
2378
- network: Erc8004Network;
2379
- /** URI pointing to agent registration file (IPFS, HTTPS) */
2380
- agentUri: string;
2381
- /** Optional metadata key-value pairs */
2382
- metadata?: MetadataEntryParam[];
2383
- /** Optional recipient address - NFT is transferred to this address after minting */
2384
- recipient?: string;
2385
- }
2386
- /**
2387
- * Response from POST /register
2388
- */
2389
- interface RegisterAgentResponse extends FacilitatorFailureFields {
2390
- /** Whether registration succeeded */
2391
- success: boolean;
2392
- /** The newly assigned agent ID (EVM: tokenId number, Solana: base58 pubkey string) */
2393
- agentId?: AgentId;
2394
- /** Registration transaction hash */
2395
- transaction?: string;
2396
- /** Transfer transaction hash (if recipient was specified) */
2397
- transferTransaction?: string;
2398
- /** Owner address of the agent NFT */
2399
- owner?: string;
2400
- /** Error message if failed */
2401
- error?: string;
2402
- /** Network where agent was registered */
2403
- network: string;
2404
- }
2405
- /**
2406
- * Response from GET /identity/{network}/owner/{address}
2407
- */
2408
- interface IdentityByOwnerResponse {
2409
- /** First (lowest) token ID owned by this address */
2410
- agentId: AgentId;
2411
- /** The queried address (checksummed) */
2412
- owner: string;
2413
- /** Agent's registration URI (may be empty) */
2414
- agentUri: string;
2415
- /** Network name */
2416
- network: string;
2417
- /** Total number of agent NFTs owned (as string) */
2418
- balance: string;
2419
- }
2420
- /**
2421
- * Response from GET /identity/{network}/{agent_id}/metadata/{key}
2422
- */
2423
- /**
2424
- * Lifecycle of an async registration. `mint_confirmed` and `done` carry an
2425
- * `agentId`; `failed` carries an `error`.
2426
- */
2427
- type RegisterJobStatus = 'pending' | 'mint_confirmed' | 'done' | 'failed';
2428
- /**
2429
- * Status of an asynchronous registration.
2430
- *
2431
- * Returned by `POST /register` with `Prefer: respond-async` (HTTP 202) and by
2432
- * `GET /register/status/{jobId}`.
2433
- *
2434
- * Terminal jobs are retained for one hour and then age out, after which the
2435
- * status endpoint 404s. Read the agent id before then, or it is only
2436
- * recoverable from the chain.
2437
- */
2438
- interface RegisterJobResponse {
2439
- jobId: string;
2440
- status: RegisterJobStatus;
2441
- network?: string;
2442
- agentId?: AgentId;
2443
- transaction?: string;
2444
- transferTransaction?: string;
2445
- owner?: string;
2446
- error?: string;
2447
- }
2448
- /** Whether polling can stop: the job either finished or failed. */
2449
- declare function isRegisterJobTerminal(job: RegisterJobResponse): boolean;
2450
- /**
2451
- * Thrown when a registration is still running after the wait elapsed.
2452
- *
2453
- * This is emphatically **not** a failure. The mint may still land. `jobId` is a
2454
- * field rather than only part of the message, because the correct recovery is to
2455
- * keep polling `getRegisterStatus(jobId)` — and a caller who cannot reach the id
2456
- * without parsing a string will re-register instead, minting a duplicate agent.
2457
- * That is the exact sequence that once produced five duplicate mints.
2458
- *
2459
- * Never map this to "registration failed".
2460
- */
2461
- declare class RegistrationPendingError extends Error {
2462
- readonly jobId: string;
2463
- readonly lastStatus: RegisterJobStatus;
2464
- readonly timeoutMs: number;
2465
- readonly retryable = true;
2466
- constructor(jobId: string, lastStatus: RegisterJobStatus, timeoutMs: number);
2467
- }
2468
- interface IdentityMetadataResponse {
2469
- /** Agent ID (EVM: number, Solana: string) */
2470
- agentId: AgentId;
2471
- /** Metadata key */
2472
- key: string;
2473
- /**
2474
- * Raw hex-encoded value. The facilitator sends this as `value`; this field
2475
- * used to be declared as `valueHex`, which no response ever carried, so it
2476
- * was always undefined at runtime.
2477
- */
2478
- value: string;
2479
- /** UTF-8 decoded value (if decodable) */
2480
- valueUtf8?: string;
2481
- /** Whether the entry can still be changed */
2482
- immutable?: boolean;
2483
- /** Network */
2484
- network: string;
2485
- }
2486
- /**
2487
- * Response from GET /identity/{network}/total-supply
2488
- *
2489
- * On Solana the counts come from the Metaplex Core collection, not the registry,
2490
- * which keeps no counter of its own.
2491
- */
2492
- interface IdentityTotalSupplyResponse {
2493
- /** Registered agents, net of burns */
2494
- totalSupply: number;
2495
- /** All-time mint count (Solana) */
2496
- numMinted?: number;
2497
- /** Metaplex Core collection backing the count (Solana) */
2498
- collection?: string;
2499
- /** Network */
2500
- network: string;
2501
- }
2502
- /**
2503
- * Options for the ERC8004Client
2504
- */
2505
- interface Erc8004ClientOptions {
2506
- /** Base URL of the facilitator (default: https://facilitator.ultravioletadao.xyz) */
2507
- baseUrl?: string;
2508
- /** Request timeout in milliseconds (default: 30000) */
2509
- timeout?: number;
2510
- /**
2511
- * Extra attempts after the first, spent only on a refusal the facilitator
2512
- * proved it did not execute. Default 2; `0` disables. An ambiguous
2513
- * `forward_failed` is never replayed at any setting.
2514
- */
2515
- retries?: number;
2516
- }
2517
- /**
2518
- * Client for ERC-8004 Trustless Agents API
2519
- *
2520
- * Provides methods for:
2521
- * - Registering new agents (gasless, facilitator pays gas)
2522
- * - Registering agents on behalf of users (gasless delegation)
2523
- * - Querying agent identity, metadata, and total supply
2524
- * - Querying agent reputation
2525
- * - Submitting reputation feedback
2526
- * - Revoking feedback
2527
- *
2528
- * @example
2529
- * ```ts
2530
- * const client = new Erc8004Client();
2531
- *
2532
- * // Get agent identity
2533
- * const identity = await client.getIdentity('ethereum', 42);
2534
- * console.log(identity.agentUri);
2535
- *
2536
- * // Get agent reputation
2537
- * const reputation = await client.getReputation('ethereum', 42);
2538
- * console.log(`Score: ${reputation.summary.summaryValue}`);
2539
- *
2540
- * // Submit feedback after payment
2541
- * const result = await client.submitFeedback({
2542
- * x402Version: 1,
2543
- * network: 'ethereum',
2544
- * feedback: {
2545
- * agentId: 42,
2546
- * value: 95,
2547
- * valueDecimals: 0,
2548
- * tag1: 'quality',
2549
- * proof: settleResponse.proofOfPayment,
2550
- * },
2551
- * });
2552
- * ```
2553
- */
2554
- declare class Erc8004Client {
2555
- private readonly baseUrl;
2556
- private readonly timeout;
2557
- private readonly retries;
2558
- constructor(options?: Erc8004ClientOptions);
2559
- /**
2560
- * POST a write route, keeping a refusal readable.
2561
- *
2562
- * Every ERC-8004 write goes through the facilitator's EVM writer lease, so
2563
- * every one of them can answer `503` + `reason`. Flattened to a string, those
2564
- * are indistinguishable from "the registry rejected your feedback" — and on
2565
- * `/register` the wrong reading re-POSTs a mint that may already have landed,
2566
- * which is precisely how five duplicate agents were once created.
2567
- *
2568
- * A refusal the facilitator proved it did not execute is replayed
2569
- * automatically (`safeToReplay`); `forward_failed` never is.
2570
- */
2571
- private writeJson;
2572
- /**
2573
- * Get agent identity from the Identity Registry
2574
- *
2575
- * @param network - Network where agent is registered
2576
- * @param agentId - Agent's tokenId
2577
- * @returns Agent identity information
2578
- */
2579
- getIdentity(network: Erc8004Network, agentId: AgentId): Promise<AgentIdentity>;
2580
- /**
2581
- * Get agent identity by owner address
2582
- *
2583
- * Resolves the first ERC-8004 agent ID owned by a wallet address on a given network.
2584
- *
2585
- * @param network - Network to query
2586
- * @param address - Owner wallet address
2587
- * @returns Agent identity information including balance
2588
- *
2589
- * @example
2590
- * ```ts
2591
- * const identity = await client.getIdentityByOwner('base-mainnet', '0x52E0...');
2592
- * console.log(`Agent #${identity.agentId}, balance: ${identity.balance}`);
2593
- * ```
2594
- */
2595
- getIdentityByOwner(network: Erc8004Network, address: string): Promise<IdentityByOwnerResponse>;
2596
- /**
2597
- * Resolve agent registration file from agentURI
2598
- *
2599
- * @param agentUri - URI pointing to agent registration file
2600
- * @returns Resolved agent registration file
2601
- */
2602
- resolveAgentUri(agentUri: string): Promise<AgentRegistrationFile>;
2603
- /**
2604
- * Get agent reputation from the Reputation Registry
2605
- *
2606
- * @param network - Network where agent is registered
2607
- * @param agentId - Agent's tokenId
2608
- * @param options - Query options (tag filters, include individual feedback, client addresses)
2609
- * @param options.clientAddresses - Comma-separated client addresses to filter by.
2610
- * If omitted, the facilitator auto-discovers all clients via getClients().
2611
- * @returns Reputation summary and optionally individual feedback entries
2612
- */
2613
- getReputation(network: Erc8004Network, agentId: AgentId, options?: {
2614
- tag1?: string;
2615
- tag2?: string;
2616
- includeFeedback?: boolean;
2617
- clientAddresses?: string;
2618
- }): Promise<ReputationResponse>;
2619
- /**
2620
- * Submit reputation feedback for an agent
2621
- *
2622
- * Requires proof of payment for authorized feedback submission.
2623
- *
2624
- * @deprecated On this route the facilitator is the AUTHOR: the registry
2625
- * records `msg.sender`, and that is the facilitator's wallet — which can also
2626
- * revoke what it wrote. On the networks in {@link RELAYED_FEEDBACK_NETWORKS}
2627
- * use {@link Erc8004Client.prepareRelayedFeedback} +
2628
- * {@link Erc8004Client.submitRelayedFeedback} instead, which record the RATER
2629
- * as author. This route still works and is not going away without notice: it
2630
- * is the only one available where no `FeedbackDelegate` is deployed.
2631
- *
2632
- * @param request - Feedback request with agent ID, value, and proof
2633
- * @returns Feedback response with transaction hash
2634
- *
2635
- * @example
2636
- * ```ts
2637
- * // After settling a payment with ERC-8004 extension
2638
- * const settleResult = await facilitator.settle(payment, {
2639
- * ...requirements,
2640
- * extra: { '8004-reputation': { includeProof: true } },
2641
- * });
2642
- *
2643
- * // Submit feedback with proof of payment
2644
- * const feedback = await erc8004.submitFeedback({
2645
- * x402Version: 1,
2646
- * network: 'ethereum',
2647
- * feedback: {
2648
- * agentId: 42,
2649
- * value: 95, // 95/100
2650
- * valueDecimals: 0,
2651
- * tag1: 'quality',
2652
- * tag2: 'response-time',
2653
- * proof: settleResult.proofOfPayment,
2654
- * },
2655
- * });
2656
- * ```
2657
- */
2658
- submitFeedback(request: FeedbackRequest): Promise<FeedbackResponse>;
2659
- /**
2660
- * Ask the facilitator what the rater must sign to author a rating.
2661
- *
2662
- * Step 1 of the rater-authored rail. Writes nothing on-chain and costs
2663
- * nothing: it reads the delegate, the rater's delegation state and their
2664
- * account nonce, then hands back a digest, a deadline and a single-use nonce.
2665
- *
2666
- * Why this exists: the ERC-8004 Reputation Registry records `msg.sender` as
2667
- * the author, and the deployed implementation has no delegation path — no
2668
- * `giveFeedbackWithSignature`, no ERC-2771 forwarder. So a rating the
2669
- * facilitator relays the ordinary way is a rating attributed to the
2670
- * FACILITATOR. EIP-7702 fixes it without touching the registry: the rater
2671
- * delegates their own EOA to the `FeedbackDelegate` and the transaction is
2672
- * sent TO THE RATER'S ADDRESS, so the registry sees the rater while the
2673
- * facilitator pays.
2674
- *
2675
- * What to do with the answer:
2676
- * 1. Produce the rater's signature. **Which value you sign depends on how you
2677
- * sign it**, and getting it wrong yields a well-formed signature that
2678
- * authorises nobody:
2679
- * - raw key: sign `digest` as a **prehash**. It already carries the
2680
- * EIP-191 envelope.
2681
- * - wallet: `personal_sign` over `signingPayload`. `personal_sign` adds the
2682
- * envelope itself, so signing `digest` with it wraps the value TWICE and
2683
- * recovers a stranger — the only symptom is `relay_bad_signature`.
2684
- * - **unless `typedData` came back** — that chain runs a v4 delegate. Then
2685
- * sign THAT with `eth_signTypedData_v4` and ignore the other two: it is
2686
- * the only form the rater can read, and it has no envelope ambiguity.
2687
- * 2. If `delegated` is `false`, also produce an EIP-7702 authorization over
2688
- * `(chainId, delegate, accountNonce)`.
2689
- * 3. Hand both to {@link submitRelayedFeedback} with the SAME feedback
2690
- * parameters, `deadline` and `nonce`.
2691
- *
2692
- * @param request - Network, rater address and feedback parameters
2693
- * @returns Everything needed to sign, including whether an EIP-7702
2694
- * authorization is still required
2695
- *
2696
- * @example
2697
- * ```ts
2698
- * const prep = await erc8004.prepareRelayedFeedback({
2699
- * x402Version: 1,
2700
- * network: 'base',
2701
- * feedback: { agentId: 18896, value: 95, tag1: 'quality', rater: raterAddress },
2702
- * });
2703
- * // prep.delegated === false -> an EIP-7702 authorization is required
2704
- * ```
2705
- */
2706
- prepareRelayedFeedback(request: PrepareRelayFeedbackRequest): Promise<PrepareRelayFeedbackResponse>;
2707
- /**
2708
- * Relay a rater-authored rating; the facilitator pays the gas.
2709
- *
2710
- * Step 2 of the rater-authored rail. The on-chain record that comes out of it
2711
- * has the RATER as `msg.sender`, so `getClients(agentId)` shows the rater
2712
- * rather than the facilitator.
2713
- *
2714
- * Pass back the same feedback parameters, `deadline` and `nonce` that
2715
- * {@link prepareRelayedFeedback} returned. They are not redundant: the
2716
- * facilitator rebuilds the registry calldata from them and requires the
2717
- * rater's signature to cover exactly that.
2718
- *
2719
- * `authorization` is required only when `prepare` answered
2720
- * `delegated: false`. One that names a different delegate than the one
2721
- * `prepare` offered is refused before any gas is spent.
2722
- *
2723
- * @param request - Feedback parameters plus the rater's signature
2724
- * @returns Feedback response with the transaction hash
2725
- */
2726
- submitRelayedFeedback(request: SubmitRelayFeedbackRequest): Promise<FeedbackResponse>;
2727
- /**
2728
- * Revoke previously submitted feedback
2729
- *
2730
- * Only the original submitter can revoke their feedback.
2731
- *
2732
- * @param network - Network where feedback was submitted
2733
- * @param agentId - Agent ID
2734
- * @param feedbackIndex - Index of feedback to revoke
2735
- * @returns Revocation result
2736
- */
2737
- revokeFeedback(network: Erc8004Network, agentId: AgentId, feedbackIndex: number, options?: {
2738
- sealHash?: string;
2739
- originalFeedback?: Omit<FeedbackParams, 'agentId' | 'proof'>;
2740
- }): Promise<FeedbackResponse>;
2741
- /**
2742
- * Get ERC-8004 contract addresses for a network
2743
- *
2744
- * @param network - Network to get contracts for
2745
- * @returns Contract addresses or undefined if not deployed
2746
- */
2747
- getContracts(network: Erc8004Network): typeof ERC8004_CONTRACTS[Erc8004Network] | undefined;
2748
- /**
2749
- * Check if ERC-8004 is available on a network
2750
- *
2751
- * @param network - Network to check
2752
- * @returns True if ERC-8004 contracts are deployed
2753
- */
2754
- isAvailable(network: string): network is Erc8004Network;
2755
- /**
2756
- * Get feedback endpoint metadata
2757
- *
2758
- * @returns Endpoint information for /feedback
2759
- */
2760
- getFeedbackMetadata(): Promise<{
2761
- endpoint: string;
2762
- supportedNetworks: Erc8004Network[];
2763
- version: string;
2764
- }>;
2765
- /**
2766
- * Ask what the RESPONDER must sign to author a response on-chain.
2767
- *
2768
- * The mirror of {@link prepareRelayedFeedback}, for the other write the
2769
- * registry accepts from anybody. `appendResponse` is not agent-only — the
2770
- * registry takes it from any address — so on the plain {@link appendResponse}
2771
- * route the `responder` recorded on-chain is the FACILITATOR. That does not
2772
- * destroy anyone's reputation the way a revoke would; it ties the
2773
- * facilitator's on-chain identity to a third party's content, which is its own
2774
- * kind of wrong.
2775
- *
2776
- * **v4 delegates only.** The v3 delegate accepts exactly two selectors and
2777
- * `appendResponse` is not one of them, so a v3 network answers 400
2778
- * `relay_response_needs_v4` rather than silently falling back to the route
2779
- * this replaces.
2780
- *
2781
- * `clientAddress` and `feedbackIndex` are inside the signed struct: without
2782
- * them one signature would answer any client's rating, or any rating at that
2783
- * index.
2784
- */
2785
- prepareRelayedResponse(request: PrepareRelayResponseRequest): Promise<PrepareRelayFeedbackResponse>;
2786
- /**
2787
- * Relay a responder-authored response; the facilitator pays the gas.
2788
- *
2789
- * Pass back the same parameters, `deadline` and `nonce` that
2790
- * {@link prepareRelayedResponse} returned: the facilitator rebuilds the struct
2791
- * from them and refuses to relay anything the signature does not cover.
2792
- */
2793
- submitRelayedResponse(request: SubmitRelayResponseRequest): Promise<FeedbackResponse>;
2794
- /** Shared POST for the relay routes: a refusal is data, never a throw. */
2795
- private postRelay;
2796
- /**
2797
- * Append a response to existing feedback
2798
- *
2799
- * @deprecated On this route the facilitator is the AUTHOR: the registry
2800
- * records `msg.sender` as the `responder`, and that is the facilitator's
2801
- * wallet. Where the delegate is **v4**, use {@link prepareRelayedResponse} +
2802
- * {@link submitRelayedResponse} instead. This route still works and is the
2803
- * only one available where the delegate is still v3.
2804
- *
2805
- * **This is NOT agent-only**, despite what this comment claimed until
2806
- * 2026-08-25. Verified on-chain on 2026-08-18: the registry accepts
2807
- * `appendResponse` from ANY address. There is no identity-owner check, here or
2808
- * in the contract.
2809
- *
2810
- * @param network - Network where feedback was submitted
2811
- * @param agentId - Agent ID
2812
- * @param feedbackIndex - Index of feedback to respond to
2813
- * @param response - Response content
2814
- * @param responseUri - Optional URI to off-chain response file
2815
- * @returns Response result
2816
- *
2817
- * @example
2818
- * ```ts
2819
- * // Agent responds to feedback
2820
- * const result = await erc8004.appendResponse(
2821
- * 'ethereum',
2822
- * 42,
2823
- * 1,
2824
- * 'Thank you for your feedback! We have addressed the issue.',
2825
- * );
2826
- * ```
2827
- */
2828
- appendResponse(network: Erc8004Network, agentId: AgentId, feedbackIndex: number, response: string, options?: {
2829
- responseUri?: string;
2830
- sealHash?: string;
2831
- }): Promise<FeedbackResponse>;
2832
- /**
2833
- * Register an agent on the Identity Registry (idempotent)
2834
- *
2835
- * If the recipient already owns an agent on the target network, returns the
2836
- * existing one instead of minting a duplicate. The facilitator pays gas fees.
2837
- * Optionally transfer the NFT to a recipient address (gasless delegation).
2838
- *
2839
- * @param request - Registration request
2840
- * @returns Registration response with agent ID and transaction hash
2841
- *
2842
- * @example
2843
- * ```ts
2844
- * // Register agent owned by facilitator
2845
- * const result = await client.registerAgent({
2846
- * x402Version: 1,
2847
- * network: 'ethereum',
2848
- * agentUri: 'ipfs://QmYourAgentFile',
2849
- * });
2850
- * console.log(`Agent #${result.agentId} registered`);
2851
- *
2852
- * // Register agent and transfer to user
2853
- * const result = await client.registerAgent({
2854
- * x402Version: 1,
2855
- * network: 'ethereum',
2856
- * agentUri: 'ipfs://QmYourAgentFile',
2857
- * recipient: '0xUserAddress...',
2858
- * });
2859
- * console.log(`Agent #${result.agentId} transferred to user`);
2860
- * ```
2861
- */
2862
- registerAgent(request: RegisterAgentRequest, options?: {
2863
- asyncTransport?: boolean;
2864
- pollIntervalMs?: number;
2865
- timeoutMs?: number;
2866
- }): Promise<RegisterAgentResponse>;
2867
- /**
2868
- * Start a registration without waiting for the chain to confirm it.
2869
- *
2870
- * Registration waits on a mint receipt, which on a congested chain outlives
2871
- * client and proxy timeouts. A timed-out synchronous call is genuinely
2872
- * ambiguous — the mint may well have landed — and retrying it is how five
2873
- * duplicate agents once got minted. This returns immediately with a job id
2874
- * instead; poll {@link getRegisterStatus} or use {@link waitForRegistration}.
2875
- *
2876
- * On Solana, `recipient` is a base58 address: the facilitator mints,
2877
- * initializes the ATOM stats and transfers, paying every fee.
2878
- */
2879
- registerAgentAsync(request: RegisterAgentRequest): Promise<RegisterJobResponse>;
2880
- /**
2881
- * Read the current state of an asynchronous registration.
2882
- *
2883
- * Throws {@link Erc8004LookupError} with `notFound` when the job is unknown or
2884
- * has aged out — terminal jobs are kept for one hour.
2885
- */
2886
- getRegisterStatus(jobId: string): Promise<RegisterJobResponse>;
2887
- /**
2888
- * Poll an asynchronous registration until it finishes.
2889
- *
2890
- * Rejects on timeout rather than resolving with the last non-terminal status,
2891
- * so "still pending" is never mistaken for "did not happen": the mint may
2892
- * still land afterwards, and treating a timeout as failure is what leads to
2893
- * registering the same agent twice. Keep the job id and poll again rather
2894
- * than re-registering.
2895
- */
2896
- waitForRegistration(jobId: string, options?: {
2897
- pollIntervalMs?: number;
2898
- timeoutMs?: number;
2899
- }): Promise<RegisterJobResponse>;
2900
- /**
2901
- * Get registration endpoint metadata
2902
- *
2903
- * @returns Endpoint information for POST /register
2904
- */
2905
- getRegisterInfo(): Promise<Record<string, unknown>>;
2906
- /**
2907
- * Get a specific metadata entry for an agent
2908
- *
2909
- * @param network - Network where agent is registered
2910
- * @param agentId - Agent's tokenId
2911
- * @param key - Metadata key to retrieve
2912
- * @returns Metadata value (hex-encoded and UTF-8 decoded if possible)
2913
- */
2914
- getIdentityMetadata(network: Erc8004Network, agentId: AgentId, key: string): Promise<IdentityMetadataResponse>;
2915
- /**
2916
- * Get total number of registered agents on a network
2917
- *
2918
- * @param network - Network to query
2919
- * @returns Total supply count
2920
- */
2921
- getIdentityTotalSupply(network: Erc8004Network): Promise<IdentityTotalSupplyResponse>;
2922
- }
2923
- /**
2924
- * Build payment requirements with ERC-8004 extension
2925
- *
2926
- * Adds the 8004-reputation extension to include proof of payment
2927
- * in settlement responses for reputation submission.
2928
- *
2929
- * @param options - Base payment requirements options
2930
- * @returns Payment requirements with ERC-8004 extension
2931
- *
2932
- * @example
2933
- * ```ts
2934
- * const requirements = buildErc8004PaymentRequirements({
2935
- * amount: '1.00',
2936
- * recipient: '0x...',
2937
- * resource: 'https://api.example.com/service',
2938
- * chainName: 'ethereum',
2939
- * });
2940
- *
2941
- * // Settlement will include proofOfPayment
2942
- * const result = await facilitator.settle(payment, requirements);
2943
- * console.log(result.proofOfPayment);
2944
- * ```
2945
- */
2946
- declare function buildErc8004PaymentRequirements(options: PaymentRequirementsOptions): PaymentRequirements & {
2947
- extra: {
2948
- '8004-reputation': {
2949
- includeProof: boolean;
2950
- };
2951
- };
2952
- };
2953
- /**
2954
- * PAYMENT_INFO_TYPEHASH used for nonce computation.
2955
- * Must match the on-chain AuthCaptureEscrow contract.
2956
- */
2957
- declare const PAYMENT_INFO_TYPEHASH = "0xae68ac7ce30c86ece8196b61a7c486d8f0061f575037fbd34e7fe4e2820c6591";
2958
- declare const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
2959
- /**
2960
- * Contract deposit limit (enforced by PaymentOperator condition).
2961
- * As of 2026-02-03, commerce-payments contracts enforce $100 max per deposit.
2962
- */
2963
- declare const DEPOSIT_LIMIT_USDC = "100000000";
2964
- /**
2965
- * Default facilitator request timeout per chain in milliseconds.
2966
- * Ethereum L1 (~12s blocks) needs much longer than L2s (~2s blocks).
2967
- * Timeout chain: Client > SDK > Facilitator. The facilitator uses 900s for Ethereum L1.
2968
- *
2969
- * These are correct, and they are also a PRODUCT constraint worth reading before
2970
- * you offer a network in a checkout: Ethereum L1 is 960s against 90s for every
2971
- * L2 here. A buyer waiting in a browser will not wait sixteen minutes, so a
2972
- * human-facing flow should offer the L2s and leave L1 to agent-to-agent or
2973
- * batch callers that can tolerate the wait. Do not shorten this to make a
2974
- * checkout feel faster — the value tracks L1 block time and the facilitator's
2975
- * own 900s TxWatcher, and cutting it just times out a payment that was going
2976
- * to land.
2977
- */
2978
- declare const ESCROW_TIMEOUT_MS: Record<number, number>;
2979
- /**
2980
- * USDC EIP-712 domain name per chain.
2981
- * Most chains use "USD Coin", but some (Celo, Monad, HyperEVM) use "USDC".
2982
- * This must match the on-chain token's name() for EIP-712 signing to work.
2983
- */
2984
- declare const USDC_DOMAIN_NAME: Record<number, string>;
2985
- /**
2986
- * Multi-chain escrow contract addresses for the Advanced Escrow system.
2987
- * Keyed by EVM chain ID. Source: x402r-sdk A1igator/multichain-config deployment.
2988
- */
2989
- /**
2990
- * Per-chain escrow contract addresses.
2991
- *
2992
- * KNOWN GAP, measured 2026-09-05: the `operator` entries are
2993
- * PaymentOperatorFactory addresses, not deployed PaymentOperator instances.
2994
- * Verified on Base mainnet, Base Sepolia and Arbitrum — they answer
2995
- * `ESCROW()` and `operators(bytes32)` and revert on `FEE_CALCULATOR()`,
2996
- * `FEE_RECIPIENT()` and `release(...)` — and x402-rs
2997
- * `docs/X402R_MULTICHAIN_DEPLOYMENT.md` labels the same addresses
2998
- * "PaymentOperatorFactory". A factory has no `release`/`charge`, so the direct
2999
- * on-chain paths below cannot execute against these addresses as written;
3000
- * resolve the real operator from the marketplace's own escrow config
3001
- * ({@link EscrowNetworkConfig}) and pass it via `options.contracts`.
3002
- * See {@link OPERATOR_FEE_BPS} for the commands.
3003
- */
3004
- declare const ESCROW_CONTRACTS: Record<number, AdvancedEscrowContracts>;
3005
- /**
3006
- * Base Mainnet contract addresses for the Advanced Escrow system.
3007
- * @deprecated Use ESCROW_CONTRACTS[8453] or getEscrowContractsByChainId(8453) instead.
3008
- */
3009
- declare const BASE_MAINNET_CONTRACTS: AdvancedEscrowContracts;
3010
- /**
3011
- * Get escrow contract addresses for a given chain ID.
3012
- *
3013
- * @param chainId - EVM chain ID (e.g., 8453 for Base, 1 for Ethereum)
3014
- * @returns Contract addresses or undefined if chain is not supported
3015
- */
3016
- declare function getEscrowContractsByChainId(chainId: number): AdvancedEscrowContracts | undefined;
3017
- /**
3018
- * Get all chain IDs that have escrow contracts deployed.
3019
- *
3020
- * @returns Array of chain IDs with escrow support
3021
- */
3022
- declare function getEscrowSupportedChainIds(): number[];
3023
- /**
3024
- * Check if escrow contracts are deployed on a given chain.
3025
- *
3026
- * @param chainId - EVM chain ID
3027
- * @returns True if escrow is supported on this chain
3028
- */
3029
- declare function isEscrowSupportedOnChain(chainId: number): boolean;
3030
- /**
3031
- * Task tiers determine timing parameters for escrow operations.
3032
- */
3033
- type AdvancedEscrowTaskTier = 'micro' | 'standard' | 'premium' | 'enterprise';
3034
- /**
3035
- * Timing configuration per task tier (in seconds).
3036
- */
3037
- declare const TIER_TIMINGS: Record<AdvancedEscrowTaskTier, {
3038
- pre: number;
3039
- auth: number;
3040
- refund: number;
3041
- }>;
3042
- /**
3043
- * PaymentInfo struct matching the on-chain PaymentOperator contract.
3044
- */
3045
- interface AdvancedPaymentInfo {
3046
- operator: string;
3047
- receiver: string;
3048
- token: string;
3049
- maxAmount: string;
3050
- preApprovalExpiry: number;
3051
- authorizationExpiry: number;
3052
- refundExpiry: number;
3053
- minFeeBps: number;
3054
- maxFeeBps: number;
3055
- feeReceiver: string;
3056
- salt: string;
3057
- }
3058
- /**
3059
- * Result of an AUTHORIZE operation.
3060
- */
3061
- interface AdvancedAuthorizationResult {
3062
- success: boolean;
3063
- transactionHash?: string;
3064
- paymentInfo?: AdvancedPaymentInfo;
3065
- salt?: string;
3066
- error?: string;
3067
- }
3068
- /**
3069
- * Result of an on-chain transaction (release, refund, charge).
3070
- */
3071
- interface AdvancedTransactionResult extends FacilitatorFailureFields {
3072
- success: boolean;
3073
- transactionHash?: string;
3074
- gasUsed?: number;
3075
- /**
3076
- * Why it failed.
3077
- *
3078
- * On the gasless (`*ViaFacilitator`) paths, check `retryable` first: a
3079
- * facilitator that could not hand the write to its lease holder rejected
3080
- * nothing on-chain, and the escrow is exactly as it was. Reporting that as a
3081
- * failed refund is how funds get written off while they are still sitting in
3082
- * escrow, recoverable.
3083
- */
3084
- error?: string;
3085
- }
3086
- /**
3087
- * Response from the facilitator's /escrow/state endpoint.
3088
- * Represents the on-chain state of an escrow for a given paymentInfo + payer.
3089
- */
3090
- interface EscrowStateResponse {
3091
- /** Whether the payment has already been collected (released) */
3092
- hasCollectedPayment: boolean;
3093
- /** Amount that can still be captured/released (in atomic units) */
3094
- capturableAmount: string;
3095
- /** Amount that can still be refunded to the payer (in atomic units) */
3096
- refundableAmount: string;
3097
- /** Keccak256 hash of the paymentInfo struct */
3098
- paymentInfoHash: string;
3099
- /** Network in CAIP-2 format (e.g., "eip155:8453") */
3100
- network: string;
3101
- }
3102
- /**
3103
- * Contract addresses configuration for AdvancedEscrowClient.
3104
- *
3105
- * Maps to the on-chain x402r escrow contracts:
3106
- * - operator: PaymentOperatorFactory
3107
- * - escrow: AuthCaptureEscrow
3108
- * - tokenCollector: TokenCollector
3109
- * - protocolFeeConfig: ProtocolFeeConfig
3110
- * - refundRequest: RefundRequest
3111
- * - usdc: USDC token contract
3112
- */
3113
- interface AdvancedEscrowContracts {
3114
- /** PaymentOperatorFactory contract address */
3115
- operator: string;
3116
- /** AuthCaptureEscrow contract address */
3117
- escrow: string;
3118
- /** TokenCollector contract address */
3119
- tokenCollector: string;
3120
- /** ProtocolFeeConfig contract address */
3121
- protocolFeeConfig: string;
3122
- /** RefundRequest contract address */
3123
- refundRequest: string;
3124
- /** USDC token contract address */
3125
- usdc: string;
3126
- }
3127
- /**
3128
- * Configuration options for AdvancedEscrowClient.
3129
- */
3130
- interface AdvancedEscrowClientOptions {
3131
- /** Facilitator URL for AUTHORIZE operations */
3132
- facilitatorUrl?: string;
3133
- /** JSON-RPC URL for on-chain operations (required when using SigningWalletAdapter) */
3134
- rpcUrl?: string;
3135
- /**
3136
- * Chain ID (default: 8453 for Base Mainnet).
3137
- * Supported chains: 8453 (Base), 84532 (Base Sepolia), 1 (Ethereum),
3138
- * 11155111 (Ethereum Sepolia), 137 (Polygon), 42161 (Arbitrum),
3139
- * 10 (Optimism), 42220 (Celo), 143 (Monad), 43114 (Avalanche).
3140
- */
3141
- chainId?: number;
3142
- /** Contract addresses (auto-resolved from chainId if not provided) */
3143
- contracts?: AdvancedEscrowContracts;
3144
- /** Gas limit for transactions (default: 300000) */
3145
- gasLimit?: number;
3146
- /**
3147
- * Request timeout in milliseconds for facilitator HTTP calls (authorize, gasless release/refund).
3148
- * Default is per-network: 960s for Ethereum L1, 90s for L2s.
3149
- * Ethereum L1 confirmations can take several minutes under congestion.
3150
- */
3151
- timeout?: number;
3152
- /**
3153
- * SigningWalletAdapter for OWS wallet signing (v2.36.0+).
3154
- *
3155
- * When provided, the client uses the adapter for all signing operations
3156
- * instead of requiring a raw ethers.Signer. The first constructor argument
3157
- * is ignored when `wallet` is set.
3158
- *
3159
- * Requires `rpcUrl` to be set for on-chain transaction building.
3160
- *
3161
- * @example
3162
- * ```typescript
3163
- * import { OWSWalletAdapter, AdvancedEscrowClient } from 'uvd-x402-sdk/backend';
3164
- *
3165
- * const wallet = new OWSWalletAdapter(owsWallet);
3166
- * const client = new AdvancedEscrowClient(null, {
3167
- * wallet,
3168
- * rpcUrl: 'https://mainnet.base.org',
3169
- * chainId: 8453,
3170
- * });
3171
- * ```
3172
- */
3173
- wallet?: SigningWalletAdapter;
3174
- /**
3175
- * Extra attempts on the gasless facilitator paths when the facilitator proved
3176
- * it executed nothing. Default 2; `0` disables.
3177
- */
3178
- retries?: number;
3179
- }
3180
- /**
3181
- * Minimal PaymentOperator ABI for the 4 on-chain functions.
3182
- * (AUTHORIZE goes through the facilitator, not directly on-chain)
3183
- */
3184
- declare const OPERATOR_ABI: string[];
3185
- /**
3186
- * CREATE3-deployed operators (SKALE, future chains) use updated ABI with extra `bytes data` param
3187
- * on release() and refundInEscrow(). Pass empty bytes (0x) for the data parameter.
3188
- */
3189
- declare const OPERATOR_ABI_CREATE3: string[];
3190
- /**
3191
- * AdvancedEscrowClient provides the 5 Advanced Escrow flows via the
3192
- * PaymentOperator contract on 9 supported EVM networks.
3193
- *
3194
- * Supported chains: Base (8453), Base Sepolia (84532), Ethereum (1),
3195
- * Ethereum Sepolia (11155111), Polygon (137), Arbitrum (42161),
3196
- * Optimism (10), Celo (42220), Monad (143), Avalanche (43114).
3197
- *
3198
- * Contract addresses are auto-resolved from the chain ID.
3199
- * Pass custom contracts to override.
3200
- *
3201
- * Two signer modes (v2.36.0+):
3202
- * - **Legacy**: Pass an ethers.Signer as the first argument.
3203
- * - **OWS Wallet**: Pass a SigningWalletAdapter via `options.wallet`.
3204
- * The adapter signs transactions offline (no raw private key needed).
3205
- * Requires `rpcUrl` for transaction building and broadcast.
3206
- *
3207
- * @example Legacy mode (ethers.Signer)
3208
- * ```typescript
3209
- * import { ethers } from 'ethers';
3210
- * import { AdvancedEscrowClient } from 'uvd-x402-sdk/backend';
3211
- *
3212
- * const provider = new ethers.JsonRpcProvider('https://mainnet.base.org');
3213
- * const signer = new ethers.Wallet(process.env.KEY!, provider);
3214
- * const client = new AdvancedEscrowClient(signer, { chainId: 8453 });
3215
- * ```
3216
- *
3217
- * @example OWS Wallet mode (SigningWalletAdapter)
3218
- * ```typescript
3219
- * import { OWSWalletAdapter } from 'uvd-x402-sdk';
3220
- * import { AdvancedEscrowClient } from 'uvd-x402-sdk/backend';
3221
- *
3222
- * const wallet = new OWSWalletAdapter(owsWallet);
3223
- * const client = new AdvancedEscrowClient(null, {
3224
- * wallet,
3225
- * rpcUrl: 'https://mainnet.base.org',
3226
- * chainId: 8453,
3227
- * });
3228
- * await client.init();
3229
- *
3230
- * const pi = client.buildPaymentInfo('0xWorker...', '5000000', 'standard');
3231
- * const auth = await client.authorize(pi);
3232
- * const release = await client.release(pi);
3233
- * ```
3234
- */
3235
- declare class AdvancedEscrowClient {
3236
- private facilitatorUrl;
3237
- private chainId;
3238
- private gasLimit;
3239
- private readonly timeout;
3240
- private readonly retries;
3241
- private contracts;
3242
- private signer;
3243
- private walletAdapter;
3244
- private rpcUrl;
3245
- private payerAddress;
3246
- /**
3247
- * Create an AdvancedEscrowClient.
3248
- *
3249
- * Two modes of operation:
3250
- *
3251
- * 1. **Legacy (ethers.Signer)**: Pass an ethers Signer as the first argument.
3252
- * ```ts
3253
- * const client = new AdvancedEscrowClient(signer, { rpcUrl, chainId });
3254
- * ```
3255
- *
3256
- * 2. **OWS Wallet (SigningWalletAdapter)**: Pass `wallet` in options. The
3257
- * first argument is ignored (pass `null`). Requires `rpcUrl` for on-chain
3258
- * transaction building and broadcast.
3259
- * ```ts
3260
- * const wallet = new OWSWalletAdapter(owsWallet);
3261
- * const client = new AdvancedEscrowClient(null, { wallet, rpcUrl, chainId });
3262
- * ```
3263
- *
3264
- * @param signer - ethers.Signer instance (ignored when options.wallet is set)
3265
- * @param options - Configuration options
3266
- */
3267
- constructor(signer: any, options?: AdvancedEscrowClientOptions);
3268
- /**
3269
- * Initialize the client (resolves payer address).
3270
- * Call this before using any methods.
3271
- */
3272
- init(): Promise<void>;
3273
- /**
3274
- * Build a PaymentInfo struct with appropriate timing for the task tier.
3275
- *
3276
- * @param receiver - Worker's wallet address
3277
- * @param amount - Amount in token atomic units (e.g., '5000000' for $5 USDC)
3278
- * @param tier - Task tier determines timing parameters
3279
- * @param salt - Random salt (auto-generated if not provided)
3280
- */
3281
- buildPaymentInfo(receiver: string, amount: string, tier?: AdvancedEscrowTaskTier, salt?: string, opts?: {
3282
- deadline?: number;
3283
- reviewWindowSec?: number;
3284
- /**
3285
- * Fee bounds to sign, in basis points. Default
3286
- * {@link DEFAULT_MIN_FEE_BPS} / {@link DEFAULT_MAX_FEE_BPS}. Override
3287
- * only against an operator whose fee you have actually read on-chain —
3288
- * `maxFeeBps` is a CEILING, so a value under the operator's own fee does
3289
- * not shave the fee, it reverts the deposit.
3290
- */
3291
- minFeeBps?: number;
3292
- maxFeeBps?: number;
3293
- }): AdvancedPaymentInfo;
3294
- /**
3295
- * Compute the correct nonce (with PAYMENT_INFO_TYPEHASH).
3296
- * Matches the on-chain AuthCaptureEscrow nonce derivation.
3297
- */
3298
- private computeNonce;
3299
- /**
3300
- * Sign ReceiveWithAuthorization for ERC-3009.
3301
- *
3302
- * Uses SigningWalletAdapter.signTypedData() when in OWS mode,
3303
- * or ethers Signer.signTypedData() in legacy mode.
3304
- */
3305
- private signErc3009;
3306
- /**
3307
- * Build the on-chain PaymentInfo tuple for contract calls.
3308
- */
3309
- private buildTuple;
3310
- /**
3311
- * AUTHORIZE: Lock funds in escrow via the facilitator.
3312
- *
3313
- * Sends an ERC-3009 ReceiveWithAuthorization to the facilitator,
3314
- * which calls PaymentOperator.authorize() on-chain.
3315
- */
3316
- authorize(paymentInfo: AdvancedPaymentInfo): Promise<AdvancedAuthorizationResult>;
3317
- /**
3318
- * RELEASE: Capture escrowed funds to receiver (worker gets paid).
3319
- *
3320
- * Calls PaymentOperator.release() -> escrow.capture()
3321
- *
3322
- * @param paymentInfo - PaymentInfo from the authorize step
3323
- * @param amount - Amount to release (defaults to maxAmount)
3324
- */
3325
- release(paymentInfo: AdvancedPaymentInfo, amount?: string): Promise<AdvancedTransactionResult>;
3326
- /**
3327
- * REFUND IN ESCROW: Return escrowed funds to payer (cancel task).
3328
- *
3329
- * Calls PaymentOperator.refundInEscrow() -> escrow.partialVoid()
3330
- *
3331
- * @param paymentInfo - PaymentInfo from the authorize step
3332
- * @param amount - Amount to refund (defaults to maxAmount)
3333
- */
3334
- refundInEscrow(paymentInfo: AdvancedPaymentInfo, amount?: string): Promise<AdvancedTransactionResult>;
3335
- /**
3336
- * GASLESS RELEASE: Release escrowed funds via the facilitator.
3337
- *
3338
- * Instead of calling the PaymentOperator contract directly (which requires
3339
- * gas), this sends a release request to the facilitator, which submits
3340
- * the transaction on your behalf.
3341
- *
3342
- * @param paymentInfo - PaymentInfo from the authorize step
3343
- * @param amount - Amount to release in atomic units (defaults to maxAmount)
3344
- * @returns Transaction result from the facilitator
3345
- *
3346
- * @example
3347
- * ```typescript
3348
- * const pi = client.buildPaymentInfo('0xWorker...', '5000000', 'standard');
3349
- * await client.authorize(pi);
3350
- * // Worker completes task...
3351
- * const result = await client.releaseViaFacilitator(pi);
3352
- * console.log(result.transactionHash);
3353
- * ```
3354
- */
3355
- releaseViaFacilitator(paymentInfo: AdvancedPaymentInfo, amount?: string): Promise<AdvancedTransactionResult>;
3356
- /**
3357
- * GASLESS REFUND: return escrowed funds to the payer via the facilitator.
3358
- *
3359
- * Sends `action: "refundInEscrow"` to `POST /settle`; the facilitator's
3360
- * PaymentOperator calls `AuthCaptureEscrow.partialVoid`.
3361
- *
3362
- * # This is how an EXPIRED escrow is recovered
3363
- *
3364
- * A widely repeated claim — including in this SDK's own comments until now —
3365
- * says that once `authorizationExpiry` passes, only the payer's `reclaim()`
3366
- * can move the funds. **That is false, and believing it has left real money
3367
- * stranded.**
3368
- *
3369
- * Read the contract (`AuthCaptureEscrow.sol`):
3370
- *
3371
- * - `partialVoid` is `onlySender(paymentInfo.operator)` — the operator is the
3372
- * FACILITATOR, not the payer — it sends the tokens **to the payer**, and it
3373
- * **does not check `authorizationExpiry` at all**. It works before expiry
3374
- * and after it, and the payer never has to appear.
3375
- * - `reclaim` is `onlySender(paymentInfo.payer)` and only after expiry. It is
3376
- * a payer's self-service escape hatch, which is why this facilitator does
3377
- * not expose it — **not** the only way out.
3378
- *
3379
- * So a release that reverted with `AfterAuthorizationExpiry` is recoverable
3380
- * from here, with no gas and no cooperation from the payer. Get the amount
3381
- * from {@link queryEscrowState}'s `capturableAmount`.
3382
- *
3383
- * # A refusal that is not a refusal
3384
- *
3385
- * Check `retryable` before writing an escrow off. A `503` means the
3386
- * facilitator never reached the chain — the escrow is untouched and the same
3387
- * request should be sent again.
3388
- *
3389
- * @param paymentInfo - PaymentInfo from the authorize step
3390
- * @param amount - Amount to refund in atomic units (defaults to maxAmount).
3391
- * For a stuck escrow pass `capturableAmount` from {@link queryEscrowState}.
3392
- * @returns Transaction result from the facilitator
3393
- *
3394
- * @example Recovering an escrow whose release window already closed
3395
- * ```typescript
3396
- * const state = await client.queryEscrowState(pi);
3397
- * if (state.capturableAmount !== '0') {
3398
- * // No payer needed, no gas, and expiry is irrelevant to partialVoid.
3399
- * const result = await client.refundViaFacilitator(pi, state.capturableAmount);
3400
- * if (!result.success && result.retryable) {
3401
- * // No verdict was reached. The funds are still there; send it again.
3402
- * }
3403
- * }
3404
- * ```
3405
- */
3406
- refundViaFacilitator(paymentInfo: AdvancedPaymentInfo, amount?: string): Promise<AdvancedTransactionResult>;
3407
- /**
3408
- * QUERY ESCROW STATE: Read on-chain escrow state via the facilitator.
3409
- *
3410
- * This is a read-only operation that queries the facilitator for the
3411
- * current escrow state without requiring gas or a signer.
3412
- *
3413
- * @param paymentInfo - PaymentInfo to query state for
3414
- * @returns Escrow state including capturable/refundable amounts
3415
- *
3416
- * @example
3417
- * ```typescript
3418
- * const pi = client.buildPaymentInfo('0xWorker...', '5000000', 'standard');
3419
- * await client.authorize(pi);
3420
- *
3421
- * const state = await client.queryEscrowState(pi);
3422
- * console.log(`Capturable: ${state.capturableAmount}`);
3423
- * console.log(`Refundable: ${state.refundableAmount}`);
3424
- * console.log(`Already collected: ${state.hasCollectedPayment}`);
3425
- * ```
3426
- */
3427
- queryEscrowState(paymentInfo: AdvancedPaymentInfo): Promise<EscrowStateResponse>;
3428
- /**
3429
- * CHARGE: Direct instant payment (no escrow hold).
3430
- *
3431
- * Calls PaymentOperator.charge() -> escrow.charge()
3432
- * Funds go directly from payer to receiver.
3433
- *
3434
- * @param paymentInfo - PaymentInfo with receiver and amount
3435
- * @param amount - Amount to charge (defaults to maxAmount)
3436
- */
3437
- charge(paymentInfo: AdvancedPaymentInfo, amount?: string): Promise<AdvancedTransactionResult>;
3438
- /**
3439
- * REFUND POST ESCROW: Dispute refund after funds were released.
3440
- *
3441
- * Calls PaymentOperator.refundPostEscrow() -> escrow.refund()
3442
- *
3443
- * WARNING: NOT FUNCTIONAL IN PRODUCTION (as of 2026-02-03).
3444
- * The protocol team has not implemented the required tokenCollector
3445
- * contract. This call will fail on-chain.
3446
- *
3447
- * For dispute resolution, use refundInEscrow() instead: keep funds
3448
- * in escrow and refund before releasing. This guarantees funds are
3449
- * available and under arbiter control.
3450
- *
3451
- * Kept for future use when tokenCollector is implemented.
3452
- *
3453
- * @param paymentInfo - PaymentInfo from the original authorization
3454
- * @param amount - Amount to refund (defaults to maxAmount)
3455
- * @param tokenCollector - Address of token collector for refund sourcing
3456
- * @param collectorData - Data for the token collector
3457
- */
3458
- refundPostEscrow(paymentInfo: AdvancedPaymentInfo, amount?: string, tokenCollector?: string, collectorData?: string): Promise<AdvancedTransactionResult>;
3459
- /**
3460
- * Build an unsigned transaction, sign via SigningWalletAdapter, and broadcast.
3461
- *
3462
- * Used by release(), refundInEscrow(), charge(), refundPostEscrow() when
3463
- * operating in OWS wallet adapter mode. The adapter signs the serialized
3464
- * transaction offline; the RPC provider broadcasts the signed raw TX.
3465
- *
3466
- * @param ethersModule - ethers namespace (from `const { ethers } = await import('ethers')`)
3467
- * @param abi - Contract ABI (OPERATOR_ABI or OPERATOR_ABI_CREATE3)
3468
- * @param encodeCalldata - Function that encodes the calldata using the interface
3469
- * @returns Transaction result
3470
- */
3471
- private sendViaAdapter;
3472
- }
3473
-
3474
- export { AMBIGUOUS_LEASE_REASONS, type AdvancedAuthorizationResult, AdvancedEscrowClient, type AdvancedEscrowClientOptions, type AdvancedEscrowContracts, type AdvancedEscrowTaskTier, type AdvancedPaymentInfo, type AdvancedTransactionResult, type AgentId, type AgentIdentity, type AgentRegistration, type AgentRegistrationFile, type AgentService, type AtomStats, BASE_MAINNET_CONTRACTS, BazaarClient, type BazaarClientOptions, type BazaarDiscoverOptions, type BazaarDiscoverResponse, type BazaarRegisterOptions, type BazaarResource, type CreateEscrowOptions, DEFAULT_FACILITATOR_RETRIES, DEFAULT_RETRY_AFTER_SECONDS, DEPOSIT_LIMIT_USDC, type DiscoveryAccepts, type DiscoveryCuration, type DiscoveryHealth, type DiscoveryHealthStatus, type DiscoveryListOptions, type DiscoveryPagination, type DiscoveryRegisterOptions, type DiscoveryResource, type DiscoveryResponse, type DiscoverySource, type DiscoveryStats, type DiscoveryTier, type Dispute, type DisputeOutcome, ERC8004_CONTRACTS, ERC8004_EXTENSION_ID, ESCROW_CONTRACTS, ESCROW_TIMEOUT_MS, Erc8004Client, type Erc8004ClientOptions, Erc8004LookupError, type Erc8004Network, EscrowClient, type EscrowClientOptions, type EscrowPayment, type EscrowStateResponse, type EscrowStatus, FacilitatorClient, type FacilitatorClientOptions, type FacilitatorErrorInfo, type FacilitatorFailureFields, type FacilitatorFetchOptions, type FeedbackEntry, type FeedbackParams, type FeedbackRequest, type FeedbackResponse, HEALTH_FILTERS, type HonoMiddlewareOptions, type IdentityByOwnerResponse, type IdentityMetadataResponse, type IdentityTotalSupplyResponse, MAX_RETRY_AFTER_SECONDS, MAX_SEARCH_LEN, type MetadataEntryParam, OPERATOR_ABI, OPERATOR_ABI_CREATE3, PAYMENT_INFO_TYPEHASH, type ParsedFacilitatorErrorBody, type PaymentAcceptance, type PaymentMiddlewareOptions, type PaymentPayloadV2, type PaymentRequirementResolver, type PaymentRequirements, type PaymentRequirementsOptions, type PaymentRequirementsV2, type PrepareRelayFeedbackRequest, type PrepareRelayFeedbackResponse, type PrepareRelayResponseRequest, type ProofOfPayment, RELAYED_FEEDBACK_NETWORKS, REPLAYABLE_LEASE_REASONS, type RefundRequest, type RefundStatus, type RegisterAgentRequest, type RegisterAgentResponse, type RegisterJobResponse, type RegisterJobStatus, RegistrationPendingError, type RelayAuthorizationParams, type ReputationResponse, type ReputationSummary, type RequestRefundOptions, type ResourceInfoV2, SETTLEMENT_UNCONFIRMED, type SettleRequest, type SettleRequestV2, type SettleResponse, type SettleResponseWithProof, type SubmitRelayFeedbackRequest, type SubmitRelayResponseRequest, TIER_FILTERS, TIER_TIMINGS, USDC_DOMAIN_NAME, type UnavailableBody, type UnavailableResponse, type VerifiedPaymentState, type VerifyRequest, type VerifyRequestV2, type VerifyResponse, WRITER_LEASE_REASONS, type WriterLeaseReason, X402_CORS_HEADERS, X402_HEADER_NAMES, ZERO_ADDRESS, buildErc8004PaymentRequirements, buildPaymentRequirements, buildSettleRequest, buildSettleRequestForVersion, buildSettleRequestV2, buildUnavailableResponse, buildVerifyRequest, buildVerifyRequestForVersion, buildVerifyRequestV2, canRefundEscrow, canReleaseEscrow, carryFailureFields, create402Response, createHonoMiddleware, createPaymentMiddleware, epochToDate, escrowTimeRemaining, extractPaymentFromHeaders, facilitatorFetch, getCorsHeaders, getEscrowContractsByChainId, getEscrowSupportedChainIds, isAlive, isAmbiguousLeaseReason, isEscrowExpired, isEscrowSupportedOnChain, isRegisterJobTerminal, isReplayableLeaseReason, isSettlementUnconfirmed, parseFacilitatorErrorBody, parsePaymentHeader, parseRetryAfterSeconds, readFacilitatorError, resolveEnvelopeVersion, supportsRelayedFeedback, toPaymentRequirementsV2, toResourceInfoV2, wireNetwork };
1
+ import '../wallet-w7BnImDG.mjs';
2
+ import '../index-DOBhTF-j.mjs';
3
+ export { A as AMBIGUOUS_LEASE_REASONS, a9 as AdvancedAuthorizationResult, aa as AdvancedEscrowClient, ab as AdvancedEscrowClientOptions, ac as AdvancedEscrowContracts, ad as AdvancedEscrowTaskTier, ae as AdvancedPaymentInfo, af as AdvancedTransactionResult, ag as AgentId, ah as AgentIdentity, ai as AgentRegistration, aj as AgentRegistrationFile, ak as AgentService, al as AtomStats, am as BASE_MAINNET_CONTRACTS, an as BazaarClient, ao as BazaarClientOptions, ap as BazaarDiscoverOptions, aq as BazaarDiscoverResponse, ar as BazaarRegisterOptions, as as BazaarResource, at as CreateEscrowOptions, D as DEFAULT_FACILITATOR_RETRIES, a as DEFAULT_RETRY_AFTER_SECONDS, au as DEPOSIT_LIMIT_USDC, av as DiscoveryAccepts, aw as DiscoveryCuration, ax as DiscoveryHealth, ay as DiscoveryHealthStatus, az as DiscoveryListOptions, aA as DiscoveryPagination, aB as DiscoveryRegisterOptions, aC as DiscoveryResource, aD as DiscoveryResponse, aE as DiscoverySource, aF as DiscoveryStats, aG as DiscoveryTier, aH as Dispute, aI as DisputeOutcome, aJ as ERC8004_CONTRACTS, aK as ERC8004_EXTENSION_ID, aL as ESCROW_CONTRACTS, aM as ESCROW_TIMEOUT_MS, aN as Erc8004Client, aO as Erc8004ClientOptions, aP as Erc8004LookupError, aQ as Erc8004Network, aR as EscrowClient, aS as EscrowClientOptions, aT as EscrowPayment, aU as EscrowStateResponse, aV as EscrowStatus, F as FacilitatorClient, b as FacilitatorClientOptions, c as FacilitatorErrorInfo, d as FacilitatorFailureFields, e as FacilitatorFetchOptions, aW as FeedbackEntry, aX as FeedbackParams, aY as FeedbackRequest, aZ as FeedbackResponse, a_ as HEALTH_FILTERS, H as HonoMiddlewareOptions, a$ as IdentityByOwnerResponse, b0 as IdentityMetadataResponse, b1 as IdentityTotalSupplyResponse, b2 as LifecycleAuthOptions, M as MAX_RETRY_AFTER_SECONDS, b3 as MAX_SEARCH_LEN, b4 as MetadataEntryParam, b5 as OPERATOR_ABI, b6 as OPERATOR_ABI_CREATE3, b7 as PAYMENT_INFO_TYPEHASH, P as ParsedFacilitatorErrorBody, p as PaymentAcceptance, q as PaymentMiddlewareOptions, r as PaymentPayloadV2, b8 as PaymentRequirementResolver, b9 as PaymentRequirements, ba as PaymentRequirementsOptions, s as PaymentRequirementsV2, bb as PrepareRelayFeedbackRequest, bc as PrepareRelayFeedbackResponse, bd as PrepareRelayResponseRequest, be as ProofOfPayment, bf as RELAYED_FEEDBACK_NETWORKS, R as REPLAYABLE_LEASE_REASONS, bg as RefundRequest, bh as RefundStatus, bi as RegisterAgentRequest, bj as RegisterAgentResponse, bk as RegisterJobResponse, bl as RegisterJobStatus, bm as RegistrationPendingError, bn as RelayAuthorizationParams, bo as ReputationResponse, bp as ReputationSummary, bq as RequestRefundOptions, t as ResourceInfoV2, S as SETTLEMENT_UNCONFIRMED, br as SettleRequest, u as SettleRequestV2, bs as SettleResponse, bt as SettleResponseWithProof, bu as SubmitRelayFeedbackRequest, bv as SubmitRelayResponseRequest, bw as TIER_FILTERS, bx as TIER_TIMINGS, by as USDC_DOMAIN_NAME, bz as UnavailableBody, bA as UnavailableResponse, V as VerifiedPaymentState, bB as VerifyRequest, v as VerifyRequestV2, bC as VerifyResponse, W as WRITER_LEASE_REASONS, x as WriterLeaseReason, X as X402_CORS_HEADERS, y as X402_HEADER_NAMES, bD as ZERO_ADDRESS, bE as buildErc8004PaymentRequirements, E as buildPaymentRequirements, G as buildSettleRequest, I as buildSettleRequestForVersion, J as buildSettleRequestV2, bF as buildUnavailableResponse, K as buildVerifyRequest, N as buildVerifyRequestForVersion, O as buildVerifyRequestV2, bG as canRefundEscrow, bH as canReleaseEscrow, bI as carryFailureFields, Q as create402Response, T as createHonoMiddleware, U as createPaymentMiddleware, bJ as epochToDate, bK as escrowTimeRemaining, Y as extractPaymentFromHeaders, Z as facilitatorFetch, _ as getCorsHeaders, bL as getEscrowContractsByChainId, bM as getEscrowSupportedChainIds, bN as isAlive, $ as isAmbiguousLeaseReason, bO as isEscrowExpired, bP as isEscrowSupportedOnChain, bQ as isRegisterJobTerminal, a0 as isReplayableLeaseReason, a1 as isSettlementUnconfirmed, a2 as parseFacilitatorErrorBody, bR as parsePaymentHeader, a3 as parseRetryAfterSeconds, a4 as readFacilitatorError, a5 as resolveEnvelopeVersion, bS as supportsRelayedFeedback, a6 as toPaymentRequirementsV2, a7 as toResourceInfoV2, bT as wireNetwork } from '../index-De03nksW.mjs';