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