uvd-x402-sdk 2.74.0 → 2.76.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +145 -1
- package/dist/adapters/index.d.mts +3 -3
- package/dist/adapters/index.d.ts +3 -3
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/index.mjs.map +1 -1
- package/dist/backend/index.d.mts +350 -54
- package/dist/backend/index.d.ts +350 -54
- package/dist/backend/index.js +488 -253
- package/dist/backend/index.js.map +1 -1
- package/dist/backend/index.mjs +477 -254
- package/dist/backend/index.mjs.map +1 -1
- package/dist/erc8128/index.d.mts +1 -1
- package/dist/erc8128/index.d.ts +1 -1
- package/dist/{index-BkeMrSHP.d.mts → index-CiRbsqXe.d.mts} +2 -2
- package/dist/{index-BQ45e-Xa.d.ts → index-DTXTOEby.d.ts} +2 -2
- package/dist/{index-DeJMYEKC.d.mts → index-ZH10otHE.d.mts} +1 -1
- package/dist/{index-DeJMYEKC.d.ts → index-ZH10otHE.d.ts} +1 -1
- package/dist/index.d.mts +50 -10
- package/dist/index.d.ts +50 -10
- package/dist/index.js +238 -39
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +228 -40
- package/dist/index.mjs.map +1 -1
- package/dist/{ows-Z9v4GxOZ.d.mts → ows-CYIVd4xO.d.mts} +1 -1
- package/dist/{ows-C-KmORG9.d.ts → ows-DTDixPzO.d.ts} +1 -1
- package/dist/providers/algorand/index.d.mts +1 -1
- package/dist/providers/algorand/index.d.ts +1 -1
- package/dist/providers/algorand/index.js +2 -0
- package/dist/providers/algorand/index.js.map +1 -1
- package/dist/providers/algorand/index.mjs +2 -0
- package/dist/providers/algorand/index.mjs.map +1 -1
- package/dist/providers/evm/index.d.mts +1 -1
- package/dist/providers/evm/index.d.ts +1 -1
- package/dist/providers/evm/index.js.map +1 -1
- package/dist/providers/evm/index.mjs.map +1 -1
- package/dist/providers/near/index.d.mts +1 -1
- package/dist/providers/near/index.d.ts +1 -1
- package/dist/providers/near/index.js +2 -0
- package/dist/providers/near/index.js.map +1 -1
- package/dist/providers/near/index.mjs +2 -0
- package/dist/providers/near/index.mjs.map +1 -1
- package/dist/providers/solana/index.d.mts +1 -1
- package/dist/providers/solana/index.d.ts +1 -1
- package/dist/providers/solana/index.js +2 -0
- package/dist/providers/solana/index.js.map +1 -1
- package/dist/providers/solana/index.mjs +2 -0
- package/dist/providers/solana/index.mjs.map +1 -1
- package/dist/providers/stellar/index.d.mts +1 -1
- package/dist/providers/stellar/index.d.ts +1 -1
- package/dist/providers/stellar/index.js +2 -0
- package/dist/providers/stellar/index.js.map +1 -1
- package/dist/providers/stellar/index.mjs +2 -0
- package/dist/providers/stellar/index.mjs.map +1 -1
- package/dist/providers/sui/index.d.mts +1 -1
- package/dist/providers/sui/index.d.ts +1 -1
- package/dist/providers/sui/index.js +2 -0
- package/dist/providers/sui/index.js.map +1 -1
- package/dist/providers/sui/index.mjs +2 -0
- package/dist/providers/sui/index.mjs.map +1 -1
- package/dist/providers/xrpl/index.d.mts +1 -1
- package/dist/providers/xrpl/index.d.ts +1 -1
- package/dist/providers/xrpl/index.js +2 -0
- package/dist/providers/xrpl/index.js.map +1 -1
- package/dist/providers/xrpl/index.mjs +2 -0
- package/dist/providers/xrpl/index.mjs.map +1 -1
- package/dist/react/index.d.mts +3 -3
- package/dist/react/index.d.ts +3 -3
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs.map +1 -1
- package/dist/utils/index.d.mts +31 -260
- package/dist/utils/index.d.ts +31 -260
- package/dist/utils/index.js +17 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/index.mjs +16 -1
- package/dist/utils/index.mjs.map +1 -1
- package/dist/validation-De3bessL.d.mts +273 -0
- package/dist/validation-DsbfDAtV.d.ts +273 -0
- package/dist/{wallet-w7BnImDG.d.mts → wallet-0cX9Pw2F.d.mts} +1 -1
- package/dist/{wallet-w7BnImDG.d.ts → wallet-0cX9Pw2F.d.ts} +1 -1
- package/package.json +1 -1
- package/src/backend/facilitator-error.ts +355 -0
- package/src/backend/index.ts +536 -263
- package/src/dx402.ts +123 -8
- package/src/index.ts +17 -0
- package/src/utils/index.ts +5 -0
- package/src/utils/personal-sign.ts +54 -0
package/dist/backend/index.d.mts
CHANGED
|
@@ -1,5 +1,210 @@
|
|
|
1
|
-
import { S as SigningWalletAdapter } from '../wallet-
|
|
2
|
-
import {
|
|
1
|
+
import { S as SigningWalletAdapter } from '../wallet-0cX9Pw2F.mjs';
|
|
2
|
+
import { x as X402Header, Q as X402Version, G as X402PayloadData } from '../index-ZH10otHE.mjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Reading a facilitator refusal as DATA instead of prose.
|
|
6
|
+
*
|
|
7
|
+
* # Why this file exists
|
|
8
|
+
*
|
|
9
|
+
* `402` and `503` say opposite things and the SDK used to collapse both into
|
|
10
|
+
* `success: false` plus an English sentence.
|
|
11
|
+
*
|
|
12
|
+
* - **402** means the payment was REJECTED. The credential is spent; sign a new
|
|
13
|
+
* authorization.
|
|
14
|
+
* - **503** means NO VERDICT WAS REACHED. Nothing was rejected and nothing was
|
|
15
|
+
* executed; retry the SAME credential.
|
|
16
|
+
*
|
|
17
|
+
* Turning a 503 into a 402 makes the buyer sign and send a second payment for a
|
|
18
|
+
* money movement that was never refused — they pay twice. That is the most
|
|
19
|
+
* expensive mistake this SDK can make, so every facilitator edge now reports the
|
|
20
|
+
* status, the facilitator's own `reason`, and whether the request may be
|
|
21
|
+
* replayed.
|
|
22
|
+
*
|
|
23
|
+
* # The writer lease
|
|
24
|
+
*
|
|
25
|
+
* The facilitator serialises every EVM write through the one process that holds
|
|
26
|
+
* the EVM writer lease, because they all spend gas from the same EOA and the
|
|
27
|
+
* nonce for it is allocated in memory. A task that does not hold the lease
|
|
28
|
+
* forwards the request to the one that does; when it cannot, it answers
|
|
29
|
+
* `503` + `Retry-After: 5` + `{"error": "...", "reason": "<why>"}`.
|
|
30
|
+
*
|
|
31
|
+
* The five reasons do NOT share retry semantics, which is the whole point of
|
|
32
|
+
* surfacing them:
|
|
33
|
+
*
|
|
34
|
+
* | reason | did the write run? | replay? |
|
|
35
|
+
* |----------------------------|--------------------|---------|
|
|
36
|
+
* | `holder_unknown` | no | yes |
|
|
37
|
+
* | `forwarding_disabled` | no | yes |
|
|
38
|
+
* | `forwarded_but_not_writer` | no | yes |
|
|
39
|
+
* | `body_unreadable` | no | yes |
|
|
40
|
+
* | `forward_failed` | **maybe** | **no** |
|
|
41
|
+
*
|
|
42
|
+
* `forward_failed` is emitted after the forward was attempted: the holder may
|
|
43
|
+
* have executed the write and the response been lost on the way back. It is a
|
|
44
|
+
* timeout wearing a status code. Replaying a `/register` on it is exactly the
|
|
45
|
+
* sequence that once minted five duplicate agents — reconcile with
|
|
46
|
+
* `GET /identity/{network}/owner/{recipient}` or `getRegisterStatus` instead.
|
|
47
|
+
*
|
|
48
|
+
* Source of the shape: x402-rs `src/handlers.rs` `writer_lease_unavailable()`
|
|
49
|
+
* and `require_writer_lease()`.
|
|
50
|
+
*/
|
|
51
|
+
/**
|
|
52
|
+
* A `reason` the facilitator attaches to a writer-lease 503.
|
|
53
|
+
*
|
|
54
|
+
* Typed as a union for discrimination but never used to VALIDATE: the fields
|
|
55
|
+
* that carry it are plain `string`, so a reason added on the server does not
|
|
56
|
+
* break compilation here.
|
|
57
|
+
*/
|
|
58
|
+
type WriterLeaseReason = 'holder_unknown' | 'forwarding_disabled' | 'forwarded_but_not_writer' | 'body_unreadable' | 'forward_failed';
|
|
59
|
+
/** Every writer-lease reason the facilitator emits today. */
|
|
60
|
+
declare const WRITER_LEASE_REASONS: readonly WriterLeaseReason[];
|
|
61
|
+
/**
|
|
62
|
+
* The reasons returned BEFORE the write is handed to anyone.
|
|
63
|
+
*
|
|
64
|
+
* The facilitator refuses these in its router, so the request provably did not
|
|
65
|
+
* execute and re-sending the identical body is safe — including a mint.
|
|
66
|
+
*/
|
|
67
|
+
declare const REPLAYABLE_LEASE_REASONS: readonly WriterLeaseReason[];
|
|
68
|
+
/**
|
|
69
|
+
* The reason that is ambiguous: the write may already have happened.
|
|
70
|
+
*
|
|
71
|
+
* Still `retryable` — the credential was not rejected — but never replayed
|
|
72
|
+
* automatically. Resolve it by reading state, not by re-POSTing.
|
|
73
|
+
*/
|
|
74
|
+
declare const AMBIGUOUS_LEASE_REASONS: readonly WriterLeaseReason[];
|
|
75
|
+
/**
|
|
76
|
+
* Ceiling, in seconds, on how long an automatic retry will wait.
|
|
77
|
+
*
|
|
78
|
+
* `Retry-After` is a hint from a server that may be misconfigured. Honouring a
|
|
79
|
+
* literal `Retry-After: 3600` would hang the caller's request for an hour
|
|
80
|
+
* inside a function documented as returning promptly, so the header is honoured
|
|
81
|
+
* only up to this bound.
|
|
82
|
+
*/
|
|
83
|
+
declare const MAX_RETRY_AFTER_SECONDS = 15;
|
|
84
|
+
/** Wait used when a 503 carries no usable `Retry-After`. */
|
|
85
|
+
declare const DEFAULT_RETRY_AFTER_SECONDS = 5;
|
|
86
|
+
/** How many EXTRA attempts a retryable facilitator refusal gets by default. */
|
|
87
|
+
declare const DEFAULT_FACILITATOR_RETRIES = 2;
|
|
88
|
+
/**
|
|
89
|
+
* A non-2xx answer from the facilitator, kept structured.
|
|
90
|
+
*
|
|
91
|
+
* `error` is byte-identical to the string this SDK has always produced, so
|
|
92
|
+
* callers matching on it keep working; everything else is new and optional.
|
|
93
|
+
*/
|
|
94
|
+
interface FacilitatorErrorInfo {
|
|
95
|
+
/** Legacy flattened message: `Facilitator error: <status> - <body>`. */
|
|
96
|
+
error: string;
|
|
97
|
+
/** HTTP status the facilitator answered with. */
|
|
98
|
+
status: number;
|
|
99
|
+
/** The facilitator's own `reason`, when the body carried one. */
|
|
100
|
+
reason?: string;
|
|
101
|
+
/**
|
|
102
|
+
* Seconds to wait before retrying, already clamped to
|
|
103
|
+
* {@link MAX_RETRY_AFTER_SECONDS}. Absent when the answer is not retryable.
|
|
104
|
+
*/
|
|
105
|
+
retryAfterSeconds?: number;
|
|
106
|
+
/**
|
|
107
|
+
* The request reached no verdict; the credential is untouched and the SAME
|
|
108
|
+
* request may be sent again. Never surface this as a payment rejection.
|
|
109
|
+
*/
|
|
110
|
+
retryable: boolean;
|
|
111
|
+
/**
|
|
112
|
+
* The facilitator NAMED a reason that proves it executed nothing, so an
|
|
113
|
+
* automatic replay cannot double-write.
|
|
114
|
+
*
|
|
115
|
+
* False for `forward_failed`, whose write may already have landed, and false
|
|
116
|
+
* for an unattributed 5xx from a proxy — "something in front answered" is not
|
|
117
|
+
* evidence that nothing ran.
|
|
118
|
+
*/
|
|
119
|
+
safeToReplay: boolean;
|
|
120
|
+
/** Raw response body, for logs. */
|
|
121
|
+
body: string;
|
|
122
|
+
}
|
|
123
|
+
/** Fields every facilitator response type gained so a 503 stops looking terminal. */
|
|
124
|
+
interface FacilitatorFailureFields {
|
|
125
|
+
/** HTTP status, when the failure was transport-level rather than a verdict. */
|
|
126
|
+
status?: number;
|
|
127
|
+
/** The facilitator's `reason` for the refusal (see {@link WriterLeaseReason}). */
|
|
128
|
+
reason?: string;
|
|
129
|
+
/** True when the same request may be sent again without re-signing anything. */
|
|
130
|
+
retryable?: boolean;
|
|
131
|
+
/** Seconds to wait before retrying, clamped to {@link MAX_RETRY_AFTER_SECONDS}. */
|
|
132
|
+
retryAfterSeconds?: number;
|
|
133
|
+
/** True when the facilitator provably executed nothing. */
|
|
134
|
+
safeToReplay?: boolean;
|
|
135
|
+
}
|
|
136
|
+
/** A 503/429 that carries a reason known to be pre-execution. */
|
|
137
|
+
declare function isReplayableLeaseReason(reason?: string): boolean;
|
|
138
|
+
/** A 503 whose write may already have run. Reconcile, do not re-POST. */
|
|
139
|
+
declare function isAmbiguousLeaseReason(reason?: string): boolean;
|
|
140
|
+
/**
|
|
141
|
+
* Read `Retry-After` and clamp it.
|
|
142
|
+
*
|
|
143
|
+
* Tolerates a `Response`-shaped object with no `headers` at all: test doubles
|
|
144
|
+
* and non-standard fetch polyfills routinely omit it, and throwing there would
|
|
145
|
+
* turn a readable refusal into an unreadable crash.
|
|
146
|
+
*/
|
|
147
|
+
declare function parseRetryAfterSeconds(response: {
|
|
148
|
+
headers?: {
|
|
149
|
+
get?: (name: string) => string | null;
|
|
150
|
+
};
|
|
151
|
+
}): number | undefined;
|
|
152
|
+
/**
|
|
153
|
+
* Turn a non-2xx facilitator response into {@link FacilitatorErrorInfo}.
|
|
154
|
+
*
|
|
155
|
+
* Reads the body exactly once. The `error` string keeps the historical format
|
|
156
|
+
* verbatim; reformatting it would break callers that match on it.
|
|
157
|
+
*/
|
|
158
|
+
declare function readFacilitatorError(response: {
|
|
159
|
+
status: number;
|
|
160
|
+
text: () => Promise<string>;
|
|
161
|
+
headers?: {
|
|
162
|
+
get?: (name: string) => string | null;
|
|
163
|
+
};
|
|
164
|
+
}): Promise<FacilitatorErrorInfo>;
|
|
165
|
+
/**
|
|
166
|
+
* Copy the failure fields off one response onto another.
|
|
167
|
+
*
|
|
168
|
+
* Used where a wrapper returns its own shape: without this the wrapper flattens
|
|
169
|
+
* a `503` back into a bare failure and reintroduces, one level up, exactly the
|
|
170
|
+
* ambiguity the fields exist to remove.
|
|
171
|
+
*/
|
|
172
|
+
declare function carryFailureFields(source: FacilitatorFailureFields): FacilitatorFailureFields;
|
|
173
|
+
/** Options for {@link facilitatorFetch}. */
|
|
174
|
+
interface FacilitatorFetchOptions {
|
|
175
|
+
/** Abort the request after this many milliseconds. */
|
|
176
|
+
timeoutMs: number;
|
|
177
|
+
/** Extra attempts after the first. Default {@link DEFAULT_FACILITATOR_RETRIES}. */
|
|
178
|
+
retries?: number;
|
|
179
|
+
/**
|
|
180
|
+
* Whether this particular refusal may be replayed.
|
|
181
|
+
*
|
|
182
|
+
* Default: only when the facilitator proved it executed nothing
|
|
183
|
+
* (`info.safeToReplay`). Pass a stricter predicate on paths where even a
|
|
184
|
+
* proven-safe replay is unwanted.
|
|
185
|
+
*/
|
|
186
|
+
canReplay?: (info: FacilitatorErrorInfo) => boolean;
|
|
187
|
+
/** Injected for tests. */
|
|
188
|
+
fetchImpl?: typeof fetch;
|
|
189
|
+
/** Injected for tests, so a retry does not really sleep. */
|
|
190
|
+
sleepImpl?: (ms: number) => Promise<void>;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* POST/GET the facilitator, replaying a refusal that provably executed nothing.
|
|
194
|
+
*
|
|
195
|
+
* Returns the response plus, when it was not ok, the structured refusal — the
|
|
196
|
+
* body has already been consumed to build it, so callers must not read it
|
|
197
|
+
* again.
|
|
198
|
+
*
|
|
199
|
+
* Network errors and timeouts still THROW, exactly as before: callers already
|
|
200
|
+
* have `catch` blocks that turn them into `{ success: false }`, and an
|
|
201
|
+
* `AbortError` on the escrow paths triggers an on-chain reconciliation that
|
|
202
|
+
* must keep firing.
|
|
203
|
+
*/
|
|
204
|
+
declare function facilitatorFetch(url: string, init: RequestInit, options: FacilitatorFetchOptions): Promise<{
|
|
205
|
+
response: Response;
|
|
206
|
+
error?: FacilitatorErrorInfo;
|
|
207
|
+
}>;
|
|
3
208
|
|
|
4
209
|
/**
|
|
5
210
|
* Payment requirements sent to the facilitator
|
|
@@ -47,8 +252,16 @@ interface SettleRequest {
|
|
|
47
252
|
/**
|
|
48
253
|
* Verify response from the facilitator
|
|
49
254
|
*/
|
|
50
|
-
interface VerifyResponse {
|
|
255
|
+
interface VerifyResponse extends FacilitatorFailureFields {
|
|
51
256
|
isValid: boolean;
|
|
257
|
+
/**
|
|
258
|
+
* Why the payment is not valid.
|
|
259
|
+
*
|
|
260
|
+
* Read `retryable` before showing this to anyone. When `retryable` is true the
|
|
261
|
+
* facilitator reached NO VERDICT -- it did not reject the payment, so this
|
|
262
|
+
* string is a transport diagnosis, not a rejection, and re-signing on it makes
|
|
263
|
+
* the buyer pay twice.
|
|
264
|
+
*/
|
|
52
265
|
invalidReason?: string;
|
|
53
266
|
payer?: string;
|
|
54
267
|
network?: string;
|
|
@@ -56,11 +269,17 @@ interface VerifyResponse {
|
|
|
56
269
|
/**
|
|
57
270
|
* Settle response from the facilitator
|
|
58
271
|
*/
|
|
59
|
-
interface SettleResponse {
|
|
272
|
+
interface SettleResponse extends FacilitatorFailureFields {
|
|
60
273
|
success: boolean;
|
|
61
274
|
transactionHash?: string;
|
|
62
275
|
network?: string;
|
|
63
|
-
/**
|
|
276
|
+
/**
|
|
277
|
+
* Transport-level failure (unreachable facilitator, non-2xx, timeout).
|
|
278
|
+
*
|
|
279
|
+
* `success: false` with `retryable: true` is NOT a rejected payment. The
|
|
280
|
+
* authorization is untouched and the same one must be resent; treating it as
|
|
281
|
+
* a refusal and asking for a new signature charges the buyer twice.
|
|
282
|
+
*/
|
|
64
283
|
error?: string;
|
|
65
284
|
/**
|
|
66
285
|
* The facilitator's own reason when it settled nothing — e.g. a transfer that
|
|
@@ -357,6 +576,15 @@ interface FacilitatorClientOptions {
|
|
|
357
576
|
* Set explicitly to override per-network auto-detection.
|
|
358
577
|
*/
|
|
359
578
|
timeout?: number;
|
|
579
|
+
/**
|
|
580
|
+
* Extra attempts after the first when the facilitator answers a refusal it
|
|
581
|
+
* proved it did not execute (`safeToReplay`). Default 2; `0` disables.
|
|
582
|
+
*
|
|
583
|
+
* Only ever spent on `429` and on a `503` naming a pre-execution writer-lease
|
|
584
|
+
* reason. An ambiguous `forward_failed` -- whose write may already have landed
|
|
585
|
+
* -- is never replayed here, at any setting.
|
|
586
|
+
*/
|
|
587
|
+
retries?: number;
|
|
360
588
|
}
|
|
361
589
|
/**
|
|
362
590
|
* Client for interacting with the x402 facilitator API
|
|
@@ -382,6 +610,7 @@ declare class FacilitatorClient {
|
|
|
382
610
|
private readonly baseUrl;
|
|
383
611
|
private readonly timeout;
|
|
384
612
|
private readonly explicitTimeout;
|
|
613
|
+
private readonly retries;
|
|
385
614
|
constructor(options?: FacilitatorClientOptions);
|
|
386
615
|
/**
|
|
387
616
|
* Get timeout for a specific network, using per-chain defaults when no explicit timeout was set.
|
|
@@ -422,7 +651,7 @@ declare class FacilitatorClient {
|
|
|
422
651
|
settled: boolean;
|
|
423
652
|
transactionHash?: string;
|
|
424
653
|
error?: string;
|
|
425
|
-
}>;
|
|
654
|
+
} & FacilitatorFailureFields>;
|
|
426
655
|
/**
|
|
427
656
|
* Check if the facilitator is healthy
|
|
428
657
|
*
|
|
@@ -645,37 +874,6 @@ interface HonoMiddlewareOptions extends PaymentMiddlewareOptions {
|
|
|
645
874
|
/** Custom requirement resolver for ambiguous multi-accept flows */
|
|
646
875
|
resolveRequirement?: PaymentRequirementResolver;
|
|
647
876
|
}
|
|
648
|
-
/**
|
|
649
|
-
* Create a Hono-compatible middleware for x402 payments.
|
|
650
|
-
*
|
|
651
|
-
* Handles the x402 payment flow:
|
|
652
|
-
* 1. Returns 402 with payment requirements if no X-PAYMENT header
|
|
653
|
-
* 2. Verifies the payment with the facilitator
|
|
654
|
-
* 3. Optionally settles before the handler when settlementStrategy is set
|
|
655
|
-
* 4. Passes control to the next handler on success
|
|
656
|
-
*
|
|
657
|
-
* @param options - Middleware options with facilitator URL and payment accepts
|
|
658
|
-
* @returns Hono middleware function
|
|
659
|
-
*
|
|
660
|
-
* @example
|
|
661
|
-
* ```ts
|
|
662
|
-
* import { createHonoMiddleware } from 'uvd-x402-sdk';
|
|
663
|
-
*
|
|
664
|
-
* const paywall = createHonoMiddleware({
|
|
665
|
-
* accepts: [{
|
|
666
|
-
* network: 'skale-base',
|
|
667
|
-
* asset: '0x85889c8c714505E0c94b30fcfcF64fE3Ac8FCb20',
|
|
668
|
-
* amount: '1000000',
|
|
669
|
-
* payTo: '0xYourWallet',
|
|
670
|
-
* extra: { name: 'Bridged USDC (SKALE Bridge)', version: '2' },
|
|
671
|
-
* }],
|
|
672
|
-
* });
|
|
673
|
-
*
|
|
674
|
-
* app.get('/api/premium', paywall, (c) => {
|
|
675
|
-
* return c.json({ message: 'Premium content!' });
|
|
676
|
-
* });
|
|
677
|
-
* ```
|
|
678
|
-
*/
|
|
679
877
|
declare function createHonoMiddleware(options: HonoMiddlewareOptions): (c: {
|
|
680
878
|
req: {
|
|
681
879
|
header: (name: string) => string | undefined;
|
|
@@ -683,6 +881,8 @@ declare function createHonoMiddleware(options: HonoMiddlewareOptions): (c: {
|
|
|
683
881
|
};
|
|
684
882
|
json: (body: unknown, status?: number) => unknown;
|
|
685
883
|
set?: (key: string, value: unknown) => void;
|
|
884
|
+
/** Hono's response-header setter. Optional so older context doubles still fit. */
|
|
885
|
+
header?: (name: string, value: string) => void;
|
|
686
886
|
}, next: () => Promise<void>) => Promise<unknown>;
|
|
687
887
|
/**
|
|
688
888
|
* Maximum length of the free-text `q` filter.
|
|
@@ -1744,7 +1944,7 @@ interface FeedbackRequest {
|
|
|
1744
1944
|
/**
|
|
1745
1945
|
* Feedback response from POST /feedback
|
|
1746
1946
|
*/
|
|
1747
|
-
interface FeedbackResponse {
|
|
1947
|
+
interface FeedbackResponse extends FacilitatorFailureFields {
|
|
1748
1948
|
/** Whether the feedback was successfully submitted */
|
|
1749
1949
|
success: boolean;
|
|
1750
1950
|
/** Transaction hash of the feedback submission */
|
|
@@ -1774,11 +1974,42 @@ declare class Erc8004LookupError extends Error {
|
|
|
1774
1974
|
readonly status: number;
|
|
1775
1975
|
/** Raw response body, for debugging */
|
|
1776
1976
|
readonly body: string;
|
|
1777
|
-
|
|
1977
|
+
/**
|
|
1978
|
+
* `Retry-After`, already clamped, when the facilitator sent one.
|
|
1979
|
+
*
|
|
1980
|
+
* Optional so every existing three-argument construction keeps compiling; it
|
|
1981
|
+
* falls back to the default wait rather than to zero, because a caller that
|
|
1982
|
+
* retries instantly on a 503 is the load that caused it.
|
|
1983
|
+
*/
|
|
1984
|
+
private readonly retryAfterHint;
|
|
1985
|
+
constructor(message: string, status: number, body: string, retryAfterSeconds?: number);
|
|
1778
1986
|
/** The address genuinely owns no agent on this network. */
|
|
1779
1987
|
get notFound(): boolean;
|
|
1780
|
-
/**
|
|
1988
|
+
/**
|
|
1989
|
+
* The lookup reached no verdict. Retry; never read as "owns nothing".
|
|
1990
|
+
*
|
|
1991
|
+
* `502` and `504` join `503` and `429` here: a gateway that answered on the
|
|
1992
|
+
* facilitator's behalf is exactly as silent about the agent's existence, and
|
|
1993
|
+
* reading either as absence has the same consequence -- a duplicate mint.
|
|
1994
|
+
*/
|
|
1781
1995
|
get retryable(): boolean;
|
|
1996
|
+
/**
|
|
1997
|
+
* The facilitator's own `reason`, when the body carried one.
|
|
1998
|
+
*
|
|
1999
|
+
* On a WRITE route this is the writer-lease reason and it decides whether the
|
|
2000
|
+
* request may be re-sent; see {@link isReplayableLeaseReason}.
|
|
2001
|
+
*/
|
|
2002
|
+
get reason(): string | undefined;
|
|
2003
|
+
/**
|
|
2004
|
+
* The facilitator NAMED a reason proving it executed nothing.
|
|
2005
|
+
*
|
|
2006
|
+
* False for `forward_failed` and for every unattributed 5xx: "something
|
|
2007
|
+
* answered" is not evidence that nothing ran. On `/register`, replaying when
|
|
2008
|
+
* this is false is the sequence that minted five duplicate agents.
|
|
2009
|
+
*/
|
|
2010
|
+
get safeToReplay(): boolean;
|
|
2011
|
+
/** Seconds to wait before retrying, clamped. Absent when not retryable. */
|
|
2012
|
+
get retryAfterSeconds(): number | undefined;
|
|
1782
2013
|
}
|
|
1783
2014
|
/**
|
|
1784
2015
|
* ATOM Engine reputation analytics (Solana only).
|
|
@@ -1851,7 +2082,7 @@ interface RegisterAgentRequest {
|
|
|
1851
2082
|
/**
|
|
1852
2083
|
* Response from POST /register
|
|
1853
2084
|
*/
|
|
1854
|
-
interface RegisterAgentResponse {
|
|
2085
|
+
interface RegisterAgentResponse extends FacilitatorFailureFields {
|
|
1855
2086
|
/** Whether registration succeeded */
|
|
1856
2087
|
success: boolean;
|
|
1857
2088
|
/** The newly assigned agent ID (EVM: tokenId number, Solana: base58 pubkey string) */
|
|
@@ -1972,6 +2203,12 @@ interface Erc8004ClientOptions {
|
|
|
1972
2203
|
baseUrl?: string;
|
|
1973
2204
|
/** Request timeout in milliseconds (default: 30000) */
|
|
1974
2205
|
timeout?: number;
|
|
2206
|
+
/**
|
|
2207
|
+
* Extra attempts after the first, spent only on a refusal the facilitator
|
|
2208
|
+
* proved it did not execute. Default 2; `0` disables. An ambiguous
|
|
2209
|
+
* `forward_failed` is never replayed at any setting.
|
|
2210
|
+
*/
|
|
2211
|
+
retries?: number;
|
|
1975
2212
|
}
|
|
1976
2213
|
/**
|
|
1977
2214
|
* Client for ERC-8004 Trustless Agents API
|
|
@@ -2013,7 +2250,21 @@ interface Erc8004ClientOptions {
|
|
|
2013
2250
|
declare class Erc8004Client {
|
|
2014
2251
|
private readonly baseUrl;
|
|
2015
2252
|
private readonly timeout;
|
|
2253
|
+
private readonly retries;
|
|
2016
2254
|
constructor(options?: Erc8004ClientOptions);
|
|
2255
|
+
/**
|
|
2256
|
+
* POST a write route, keeping a refusal readable.
|
|
2257
|
+
*
|
|
2258
|
+
* Every ERC-8004 write goes through the facilitator's EVM writer lease, so
|
|
2259
|
+
* every one of them can answer `503` + `reason`. Flattened to a string, those
|
|
2260
|
+
* are indistinguishable from "the registry rejected your feedback" — and on
|
|
2261
|
+
* `/register` the wrong reading re-POSTs a mint that may already have landed,
|
|
2262
|
+
* which is precisely how five duplicate agents were once created.
|
|
2263
|
+
*
|
|
2264
|
+
* A refusal the facilitator proved it did not execute is replayed
|
|
2265
|
+
* automatically (`safeToReplay`); `forward_failed` never is.
|
|
2266
|
+
*/
|
|
2267
|
+
private writeJson;
|
|
2017
2268
|
/**
|
|
2018
2269
|
* Get agent identity from the Identity Registry
|
|
2019
2270
|
*
|
|
@@ -2489,10 +2740,19 @@ interface AdvancedAuthorizationResult {
|
|
|
2489
2740
|
/**
|
|
2490
2741
|
* Result of an on-chain transaction (release, refund, charge).
|
|
2491
2742
|
*/
|
|
2492
|
-
interface AdvancedTransactionResult {
|
|
2743
|
+
interface AdvancedTransactionResult extends FacilitatorFailureFields {
|
|
2493
2744
|
success: boolean;
|
|
2494
2745
|
transactionHash?: string;
|
|
2495
2746
|
gasUsed?: number;
|
|
2747
|
+
/**
|
|
2748
|
+
* Why it failed.
|
|
2749
|
+
*
|
|
2750
|
+
* On the gasless (`*ViaFacilitator`) paths, check `retryable` first: a
|
|
2751
|
+
* facilitator that could not hand the write to its lease holder rejected
|
|
2752
|
+
* nothing on-chain, and the escrow is exactly as it was. Reporting that as a
|
|
2753
|
+
* failed refund is how funds get written off while they are still sitting in
|
|
2754
|
+
* escrow, recoverable.
|
|
2755
|
+
*/
|
|
2496
2756
|
error?: string;
|
|
2497
2757
|
}
|
|
2498
2758
|
/**
|
|
@@ -2583,6 +2843,11 @@ interface AdvancedEscrowClientOptions {
|
|
|
2583
2843
|
* ```
|
|
2584
2844
|
*/
|
|
2585
2845
|
wallet?: SigningWalletAdapter;
|
|
2846
|
+
/**
|
|
2847
|
+
* Extra attempts on the gasless facilitator paths when the facilitator proved
|
|
2848
|
+
* it executed nothing. Default 2; `0` disables.
|
|
2849
|
+
*/
|
|
2850
|
+
retries?: number;
|
|
2586
2851
|
}
|
|
2587
2852
|
/**
|
|
2588
2853
|
* Minimal PaymentOperator ABI for the 4 on-chain functions.
|
|
@@ -2644,6 +2909,7 @@ declare class AdvancedEscrowClient {
|
|
|
2644
2909
|
private chainId;
|
|
2645
2910
|
private gasLimit;
|
|
2646
2911
|
private readonly timeout;
|
|
2912
|
+
private readonly retries;
|
|
2647
2913
|
private contracts;
|
|
2648
2914
|
private signer;
|
|
2649
2915
|
private walletAdapter;
|
|
@@ -2751,23 +3017,53 @@ declare class AdvancedEscrowClient {
|
|
|
2751
3017
|
*/
|
|
2752
3018
|
releaseViaFacilitator(paymentInfo: AdvancedPaymentInfo, amount?: string): Promise<AdvancedTransactionResult>;
|
|
2753
3019
|
/**
|
|
2754
|
-
* GASLESS REFUND:
|
|
3020
|
+
* GASLESS REFUND: return escrowed funds to the payer via the facilitator.
|
|
2755
3021
|
*
|
|
2756
|
-
*
|
|
2757
|
-
*
|
|
2758
|
-
*
|
|
3022
|
+
* Sends `action: "refundInEscrow"` to `POST /settle`; the facilitator's
|
|
3023
|
+
* PaymentOperator calls `AuthCaptureEscrow.partialVoid`.
|
|
3024
|
+
*
|
|
3025
|
+
* # This is how an EXPIRED escrow is recovered
|
|
3026
|
+
*
|
|
3027
|
+
* A widely repeated claim — including in this SDK's own comments until now —
|
|
3028
|
+
* says that once `authorizationExpiry` passes, only the payer's `reclaim()`
|
|
3029
|
+
* can move the funds. **That is false, and believing it has left real money
|
|
3030
|
+
* stranded.**
|
|
3031
|
+
*
|
|
3032
|
+
* Read the contract (`AuthCaptureEscrow.sol`):
|
|
3033
|
+
*
|
|
3034
|
+
* - `partialVoid` is `onlySender(paymentInfo.operator)` — the operator is the
|
|
3035
|
+
* FACILITATOR, not the payer — it sends the tokens **to the payer**, and it
|
|
3036
|
+
* **does not check `authorizationExpiry` at all**. It works before expiry
|
|
3037
|
+
* and after it, and the payer never has to appear.
|
|
3038
|
+
* - `reclaim` is `onlySender(paymentInfo.payer)` and only after expiry. It is
|
|
3039
|
+
* a payer's self-service escape hatch, which is why this facilitator does
|
|
3040
|
+
* not expose it — **not** the only way out.
|
|
3041
|
+
*
|
|
3042
|
+
* So a release that reverted with `AfterAuthorizationExpiry` is recoverable
|
|
3043
|
+
* from here, with no gas and no cooperation from the payer. Get the amount
|
|
3044
|
+
* from {@link queryEscrowState}'s `capturableAmount`.
|
|
3045
|
+
*
|
|
3046
|
+
* # A refusal that is not a refusal
|
|
3047
|
+
*
|
|
3048
|
+
* Check `retryable` before writing an escrow off. A `503` means the
|
|
3049
|
+
* facilitator never reached the chain — the escrow is untouched and the same
|
|
3050
|
+
* request should be sent again.
|
|
2759
3051
|
*
|
|
2760
3052
|
* @param paymentInfo - PaymentInfo from the authorize step
|
|
2761
|
-
* @param amount - Amount to refund in atomic units (defaults to maxAmount)
|
|
3053
|
+
* @param amount - Amount to refund in atomic units (defaults to maxAmount).
|
|
3054
|
+
* For a stuck escrow pass `capturableAmount` from {@link queryEscrowState}.
|
|
2762
3055
|
* @returns Transaction result from the facilitator
|
|
2763
3056
|
*
|
|
2764
|
-
* @example
|
|
3057
|
+
* @example Recovering an escrow whose release window already closed
|
|
2765
3058
|
* ```typescript
|
|
2766
|
-
* const
|
|
2767
|
-
*
|
|
2768
|
-
*
|
|
2769
|
-
*
|
|
2770
|
-
*
|
|
3059
|
+
* const state = await client.queryEscrowState(pi);
|
|
3060
|
+
* if (state.capturableAmount !== '0') {
|
|
3061
|
+
* // No payer needed, no gas, and expiry is irrelevant to partialVoid.
|
|
3062
|
+
* const result = await client.refundViaFacilitator(pi, state.capturableAmount);
|
|
3063
|
+
* if (!result.success && result.retryable) {
|
|
3064
|
+
* // No verdict was reached. The funds are still there; send it again.
|
|
3065
|
+
* }
|
|
3066
|
+
* }
|
|
2771
3067
|
* ```
|
|
2772
3068
|
*/
|
|
2773
3069
|
refundViaFacilitator(paymentInfo: AdvancedPaymentInfo, amount?: string): Promise<AdvancedTransactionResult>;
|
|
@@ -2838,4 +3134,4 @@ declare class AdvancedEscrowClient {
|
|
|
2838
3134
|
private sendViaAdapter;
|
|
2839
3135
|
}
|
|
2840
3136
|
|
|
2841
|
-
export { type AdvancedAuthorizationResult, AdvancedEscrowClient, type AdvancedEscrowClientOptions, type AdvancedEscrowContracts, type AdvancedEscrowTaskTier, type AdvancedPaymentInfo, type AdvancedTransactionResult, type AgentId, type AgentIdentity, type AgentRegistration, type AgentRegistrationFile, type AgentService, type AtomStats, BASE_MAINNET_CONTRACTS, BazaarClient, type BazaarClientOptions, type BazaarDiscoverOptions, type BazaarDiscoverResponse, type BazaarRegisterOptions, type BazaarResource, type CreateEscrowOptions, DEPOSIT_LIMIT_USDC, type DiscoveryAccepts, type DiscoveryCuration, type DiscoveryHealth, type DiscoveryHealthStatus, type DiscoveryListOptions, type DiscoveryPagination, type DiscoveryRegisterOptions, type DiscoveryResource, type DiscoveryResponse, type DiscoverySource, type DiscoveryStats, type DiscoveryTier, type Dispute, type DisputeOutcome, ERC8004_CONTRACTS, ERC8004_EXTENSION_ID, ESCROW_CONTRACTS, ESCROW_TIMEOUT_MS, Erc8004Client, type Erc8004ClientOptions, Erc8004LookupError, type Erc8004Network, EscrowClient, type EscrowClientOptions, type EscrowPayment, type EscrowStateResponse, type EscrowStatus, FacilitatorClient, type FacilitatorClientOptions, type FeedbackEntry, type FeedbackParams, type FeedbackRequest, type FeedbackResponse, HEALTH_FILTERS, type HonoMiddlewareOptions, type IdentityByOwnerResponse, type IdentityMetadataResponse, type IdentityTotalSupplyResponse, MAX_SEARCH_LEN, type MetadataEntryParam, OPERATOR_ABI, OPERATOR_ABI_CREATE3, PAYMENT_INFO_TYPEHASH, type PaymentAcceptance, type PaymentMiddlewareOptions, type PaymentPayloadV2, type PaymentRequirementResolver, type PaymentRequirements, type PaymentRequirementsOptions, type PaymentRequirementsV2, type PrepareRelayFeedbackRequest, type PrepareRelayFeedbackResponse, type PrepareRelayResponseRequest, type ProofOfPayment, RELAYED_FEEDBACK_NETWORKS, type RefundRequest, type RefundStatus, type RegisterAgentRequest, type RegisterAgentResponse, type RegisterJobResponse, type RegisterJobStatus, RegistrationPendingError, type RelayAuthorizationParams, type ReputationResponse, type ReputationSummary, type RequestRefundOptions, type ResourceInfoV2, type SettleRequest, type SettleRequestV2, type SettleResponse, type SettleResponseWithProof, type SubmitRelayFeedbackRequest, type SubmitRelayResponseRequest, TIER_FILTERS, TIER_TIMINGS, USDC_DOMAIN_NAME, type VerifiedPaymentState, type VerifyRequest, type VerifyRequestV2, type VerifyResponse, X402_CORS_HEADERS, X402_HEADER_NAMES, ZERO_ADDRESS, buildErc8004PaymentRequirements, buildPaymentRequirements, buildSettleRequest, buildSettleRequestV2, buildVerifyRequest, buildVerifyRequestV2, canRefundEscrow, canReleaseEscrow, create402Response, createHonoMiddleware, createPaymentMiddleware, epochToDate, escrowTimeRemaining, extractPaymentFromHeaders, getCorsHeaders, getEscrowContractsByChainId, getEscrowSupportedChainIds, isAlive, isEscrowExpired, isEscrowSupportedOnChain, isRegisterJobTerminal, parsePaymentHeader, supportsRelayedFeedback, wireNetwork };
|
|
3137
|
+
export { AMBIGUOUS_LEASE_REASONS, type AdvancedAuthorizationResult, AdvancedEscrowClient, type AdvancedEscrowClientOptions, type AdvancedEscrowContracts, type AdvancedEscrowTaskTier, type AdvancedPaymentInfo, type AdvancedTransactionResult, type AgentId, type AgentIdentity, type AgentRegistration, type AgentRegistrationFile, type AgentService, type AtomStats, BASE_MAINNET_CONTRACTS, BazaarClient, type BazaarClientOptions, type BazaarDiscoverOptions, type BazaarDiscoverResponse, type BazaarRegisterOptions, type BazaarResource, type CreateEscrowOptions, DEFAULT_FACILITATOR_RETRIES, DEFAULT_RETRY_AFTER_SECONDS, DEPOSIT_LIMIT_USDC, type DiscoveryAccepts, type DiscoveryCuration, type DiscoveryHealth, type DiscoveryHealthStatus, type DiscoveryListOptions, type DiscoveryPagination, type DiscoveryRegisterOptions, type DiscoveryResource, type DiscoveryResponse, type DiscoverySource, type DiscoveryStats, type DiscoveryTier, type Dispute, type DisputeOutcome, ERC8004_CONTRACTS, ERC8004_EXTENSION_ID, ESCROW_CONTRACTS, ESCROW_TIMEOUT_MS, Erc8004Client, type Erc8004ClientOptions, Erc8004LookupError, type Erc8004Network, EscrowClient, type EscrowClientOptions, type EscrowPayment, type EscrowStateResponse, type EscrowStatus, FacilitatorClient, type FacilitatorClientOptions, type FacilitatorErrorInfo, type FacilitatorFailureFields, type FacilitatorFetchOptions, type FeedbackEntry, type FeedbackParams, type FeedbackRequest, type FeedbackResponse, HEALTH_FILTERS, type HonoMiddlewareOptions, type IdentityByOwnerResponse, type IdentityMetadataResponse, type IdentityTotalSupplyResponse, MAX_RETRY_AFTER_SECONDS, MAX_SEARCH_LEN, type MetadataEntryParam, OPERATOR_ABI, OPERATOR_ABI_CREATE3, PAYMENT_INFO_TYPEHASH, type PaymentAcceptance, type PaymentMiddlewareOptions, type PaymentPayloadV2, type PaymentRequirementResolver, type PaymentRequirements, type PaymentRequirementsOptions, type PaymentRequirementsV2, type PrepareRelayFeedbackRequest, type PrepareRelayFeedbackResponse, type PrepareRelayResponseRequest, type ProofOfPayment, RELAYED_FEEDBACK_NETWORKS, REPLAYABLE_LEASE_REASONS, type RefundRequest, type RefundStatus, type RegisterAgentRequest, type RegisterAgentResponse, type RegisterJobResponse, type RegisterJobStatus, RegistrationPendingError, type RelayAuthorizationParams, type ReputationResponse, type ReputationSummary, type RequestRefundOptions, type ResourceInfoV2, type SettleRequest, type SettleRequestV2, type SettleResponse, type SettleResponseWithProof, type SubmitRelayFeedbackRequest, type SubmitRelayResponseRequest, TIER_FILTERS, TIER_TIMINGS, USDC_DOMAIN_NAME, type VerifiedPaymentState, type VerifyRequest, type VerifyRequestV2, type VerifyResponse, WRITER_LEASE_REASONS, type WriterLeaseReason, X402_CORS_HEADERS, X402_HEADER_NAMES, ZERO_ADDRESS, buildErc8004PaymentRequirements, buildPaymentRequirements, buildSettleRequest, buildSettleRequestV2, buildVerifyRequest, buildVerifyRequestV2, canRefundEscrow, canReleaseEscrow, carryFailureFields, create402Response, createHonoMiddleware, createPaymentMiddleware, epochToDate, escrowTimeRemaining, extractPaymentFromHeaders, facilitatorFetch, getCorsHeaders, getEscrowContractsByChainId, getEscrowSupportedChainIds, isAlive, isAmbiguousLeaseReason, isEscrowExpired, isEscrowSupportedOnChain, isRegisterJobTerminal, isReplayableLeaseReason, parsePaymentHeader, parseRetryAfterSeconds, readFacilitatorError, supportsRelayedFeedback, wireNetwork };
|