uvd-x402-sdk 2.78.0 → 2.80.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 +107 -0
- package/dist/backend/index.d.mts +179 -21
- package/dist/backend/index.d.ts +179 -21
- package/dist/backend/index.js +133 -31
- package/dist/backend/index.js.map +1 -1
- package/dist/backend/index.mjs +131 -32
- package/dist/backend/index.mjs.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +102 -22
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +100 -23
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/backend/facilitator-error.ts +201 -11
- package/src/backend/index.ts +201 -44
- package/src/index.ts +6 -0
package/dist/backend/index.d.ts
CHANGED
|
@@ -45,8 +45,34 @@ import { Q as X402Version, x as X402Header, G as X402PayloadData } from '../inde
|
|
|
45
45
|
* sequence that once minted five duplicate agents — reconcile with
|
|
46
46
|
* `GET /identity/{network}/owner/{recipient}` or `getRegisterStatus` instead.
|
|
47
47
|
*
|
|
48
|
+
* # The two `502`s of `/settle`, which mean opposite things
|
|
49
|
+
*
|
|
50
|
+
* | body `error` | `Retry-After` | did the money move? | retry? |
|
|
51
|
+
* |----------------------------|---------------|---------------------|-----------|
|
|
52
|
+
* | `upstream_rpc_unavailable` | `30` | no, never broadcast | **yes** |
|
|
53
|
+
* | `settlement_unconfirmed` | **absent** | **maybe — mined?** | **NEVER** |
|
|
54
|
+
*
|
|
55
|
+
* `settlement_unconfirmed` is answered after the transaction was broadcast and
|
|
56
|
+
* no receipt ever arrived, so it MAY be mined. Retrying re-signs a new
|
|
57
|
+
* authorization with a fresh nonce, which the chain accepts as a second,
|
|
58
|
+
* perfectly valid payment for the same purchase — the buyer pays twice, in
|
|
59
|
+
* exactly the case the facilitator emits it to prevent. The `transaction` hash
|
|
60
|
+
* and `paymentId` travel in the body so the caller can LOOK AT THE CHAIN; they
|
|
61
|
+
* are not an invitation to send it again.
|
|
62
|
+
*
|
|
63
|
+
* The status cannot tell the two apart, which is why this file used to get it
|
|
64
|
+
* wrong: every `502` was retryable, and until `settlement_unconfirmed` existed
|
|
65
|
+
* that was correct. **Branch on the body.**
|
|
66
|
+
*
|
|
67
|
+
* The general form of that rule — **a 5xx whose body carries a transaction hash
|
|
68
|
+
* was broadcast, whatever the error is called** — is adopted from the Python
|
|
69
|
+
* SDK, which has carried it as its anti-double-settle guard
|
|
70
|
+
* (`uvd_x402_sdk/client.py`, `_is_retryable_settle_error`) while this one had
|
|
71
|
+
* only the status to go on.
|
|
72
|
+
*
|
|
48
73
|
* Source of the shape: x402-rs `src/handlers.rs` `writer_lease_unavailable()`
|
|
49
|
-
* and `require_writer_lease()
|
|
74
|
+
* and `require_writer_lease()`; `SettlementUnconfirmedResponse` in
|
|
75
|
+
* `src/types.rs`, built in the `IntoResponse` of `FacilitatorLocalError`.
|
|
50
76
|
*/
|
|
51
77
|
/**
|
|
52
78
|
* A `reason` the facilitator attaches to a writer-lease 503.
|
|
@@ -72,6 +98,13 @@ declare const REPLAYABLE_LEASE_REASONS: readonly WriterLeaseReason[];
|
|
|
72
98
|
* automatically. Resolve it by reading state, not by re-POSTing.
|
|
73
99
|
*/
|
|
74
100
|
declare const AMBIGUOUS_LEASE_REASONS: readonly WriterLeaseReason[];
|
|
101
|
+
/**
|
|
102
|
+
* The facilitator's `error` code for a settle it broadcast and could not confirm.
|
|
103
|
+
*
|
|
104
|
+
* The transaction may be mined. This is the one upstream failure that must
|
|
105
|
+
* never be retried; reconcile with `transaction` / `paymentId` instead.
|
|
106
|
+
*/
|
|
107
|
+
declare const SETTLEMENT_UNCONFIRMED = "settlement_unconfirmed";
|
|
75
108
|
/**
|
|
76
109
|
* Ceiling, in seconds, on how long an automatic retry will wait.
|
|
77
110
|
*
|
|
@@ -98,6 +131,24 @@ interface FacilitatorErrorInfo {
|
|
|
98
131
|
status: number;
|
|
99
132
|
/** The facilitator's own `reason`, when the body carried one. */
|
|
100
133
|
reason?: string;
|
|
134
|
+
/**
|
|
135
|
+
* The facilitator's machine-readable `error` code, verbatim.
|
|
136
|
+
*
|
|
137
|
+
* Some codes carry a `(ref: <uuid>)` suffix, so compare with care —
|
|
138
|
+
* {@link SETTLEMENT_UNCONFIRMED} is emitted bare. Branch on this rather than
|
|
139
|
+
* on the status: `/settle` has two `502`s that mean opposite things.
|
|
140
|
+
*/
|
|
141
|
+
errorCode?: string;
|
|
142
|
+
/**
|
|
143
|
+
* The hash of a transaction that WAS broadcast, in that chain's own encoding.
|
|
144
|
+
*
|
|
145
|
+
* Present on {@link SETTLEMENT_UNCONFIRMED}. Not always `0x`-prefixed:
|
|
146
|
+
* Algorand prints base32 and Solana base58, and reformatting it makes it
|
|
147
|
+
* unpasteable in an explorer — which is the entire remedy on offer.
|
|
148
|
+
*/
|
|
149
|
+
transaction?: string;
|
|
150
|
+
/** `keccak256(caip2 ‖ txHash)`, the same id a successful settle would print. */
|
|
151
|
+
paymentId?: string;
|
|
101
152
|
/**
|
|
102
153
|
* Seconds to wait before retrying, already clamped to
|
|
103
154
|
* {@link MAX_RETRY_AFTER_SECONDS}. Absent when the answer is not retryable.
|
|
@@ -126,6 +177,15 @@ interface FacilitatorFailureFields {
|
|
|
126
177
|
status?: number;
|
|
127
178
|
/** The facilitator's `reason` for the refusal (see {@link WriterLeaseReason}). */
|
|
128
179
|
reason?: string;
|
|
180
|
+
/** The facilitator's machine-readable `error` code (see {@link FacilitatorErrorInfo.errorCode}). */
|
|
181
|
+
errorCode?: string;
|
|
182
|
+
/**
|
|
183
|
+
* A transaction that WAS broadcast and could not be confirmed. Look it up on
|
|
184
|
+
* chain; do NOT send the payment again. See {@link SETTLEMENT_UNCONFIRMED}.
|
|
185
|
+
*/
|
|
186
|
+
transaction?: string;
|
|
187
|
+
/** The payment id for that transaction, identical to the one a settle prints. */
|
|
188
|
+
paymentId?: string;
|
|
129
189
|
/** True when the same request may be sent again without re-signing anything. */
|
|
130
190
|
retryable?: boolean;
|
|
131
191
|
/** Seconds to wait before retrying, clamped to {@link MAX_RETRY_AFTER_SECONDS}. */
|
|
@@ -149,6 +209,41 @@ declare function parseRetryAfterSeconds(response: {
|
|
|
149
209
|
get?: (name: string) => string | null;
|
|
150
210
|
};
|
|
151
211
|
}): number | undefined;
|
|
212
|
+
/** Everything this SDK reads out of a facilitator error body. */
|
|
213
|
+
interface ParsedFacilitatorErrorBody {
|
|
214
|
+
/** The `error` code, verbatim. */
|
|
215
|
+
errorCode?: string;
|
|
216
|
+
/** The writer-lease `reason`. */
|
|
217
|
+
reason?: string;
|
|
218
|
+
/** A broadcast transaction hash, in its own chain's encoding. */
|
|
219
|
+
transaction?: string;
|
|
220
|
+
/** The payment id for that hash. */
|
|
221
|
+
paymentId?: string;
|
|
222
|
+
/**
|
|
223
|
+
* The facilitator's OWN retry verdict, when it stated one.
|
|
224
|
+
*
|
|
225
|
+
* `undefined` on every body that does not carry the field — which is most of
|
|
226
|
+
* them, so absence means "the facilitator did not say", never "no".
|
|
227
|
+
*/
|
|
228
|
+
retryable?: boolean;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Read a JSON error body, tolerating anything that is not one.
|
|
232
|
+
*
|
|
233
|
+
* Exported so {@link FacilitatorErrorInfo} and `Erc8004LookupError` read the
|
|
234
|
+
* SAME fields the same way. Two subtly different parses of the same body is how
|
|
235
|
+
* one code path stops honouring a `retryable: false` the other one honours.
|
|
236
|
+
*/
|
|
237
|
+
declare function parseFacilitatorErrorBody(body: string): ParsedFacilitatorErrorBody;
|
|
238
|
+
/**
|
|
239
|
+
* This refusal reports a transaction that may already be mined.
|
|
240
|
+
*
|
|
241
|
+
* The caller's move is to look up `transaction` / `paymentId` on chain. Sending
|
|
242
|
+
* the payment again is the double-charge.
|
|
243
|
+
*/
|
|
244
|
+
declare function isSettlementUnconfirmed(failure: {
|
|
245
|
+
errorCode?: string;
|
|
246
|
+
}): boolean;
|
|
152
247
|
/**
|
|
153
248
|
* Turn a non-2xx facilitator response into {@link FacilitatorErrorInfo}.
|
|
154
249
|
*
|
|
@@ -234,18 +329,30 @@ interface PaymentRequirements {
|
|
|
234
329
|
extra?: unknown;
|
|
235
330
|
}
|
|
236
331
|
/**
|
|
237
|
-
* Verify request body for the facilitator /verify endpoint
|
|
332
|
+
* Verify request body for the facilitator /verify endpoint -- the **v1**
|
|
333
|
+
* envelope. {@link VerifyRequestV2} is the other one.
|
|
238
334
|
*/
|
|
239
335
|
interface VerifyRequest {
|
|
240
|
-
|
|
336
|
+
/**
|
|
337
|
+
* Always `1`: this marker names the ENVELOPE, and this envelope is v1.
|
|
338
|
+
*
|
|
339
|
+
* Narrowed from `X402Version` on 2026-09-04. A `VerifyRequest` carrying `2`
|
|
340
|
+
* was always an uninhabitable value -- a body declaring v2 while shaped as
|
|
341
|
+
* v1 -- and typing it as `1 | 2` is what let the payer's marker be copied in
|
|
342
|
+
* here. The payer's version lives in `paymentPayload.x402Version`, which is
|
|
343
|
+
* still the full union.
|
|
344
|
+
*/
|
|
345
|
+
x402Version: 1;
|
|
241
346
|
paymentPayload: X402Header;
|
|
242
347
|
paymentRequirements: PaymentRequirements;
|
|
243
348
|
}
|
|
244
349
|
/**
|
|
245
|
-
* Settle request body for the facilitator /settle endpoint
|
|
350
|
+
* Settle request body for the facilitator /settle endpoint -- the **v1**
|
|
351
|
+
* envelope. {@link SettleRequestV2} is the other one.
|
|
246
352
|
*/
|
|
247
353
|
interface SettleRequest {
|
|
248
|
-
x402Version
|
|
354
|
+
/** Always `1` -- see {@link VerifyRequest.x402Version}. */
|
|
355
|
+
x402Version: 1;
|
|
249
356
|
paymentPayload: X402Header;
|
|
250
357
|
paymentRequirements: PaymentRequirements;
|
|
251
358
|
}
|
|
@@ -551,6 +658,14 @@ declare function toResourceInfoV2(requirements: PaymentRequirements): ResourceIn
|
|
|
551
658
|
* `extra` is carried through when present -- it is where the EIP-712 domain
|
|
552
659
|
* `name`/`version` live for tokens the facilitator does not know by address, so
|
|
553
660
|
* dropping it breaks EURC and the bridged USDCs.
|
|
661
|
+
*
|
|
662
|
+
* @throws If `requirements.network` has NO CAIP-2 form. `chainToCAIP2` answers
|
|
663
|
+
* with the name unchanged when it does not know a chain, and XRPL maps to
|
|
664
|
+
* itself on purpose -- its v1 string IS its network id. Passing that through
|
|
665
|
+
* would put a plain name inside a v2 body, which is a measured 400 (the same
|
|
666
|
+
* `no variant matched` that names no field). Only reachable by PINNING version
|
|
667
|
+
* 2 on such a network; `auto` leaves them on v1, where they work. Failing here
|
|
668
|
+
* names the network and the fix, which a 400 from the facilitator does not.
|
|
554
669
|
*/
|
|
555
670
|
declare function toPaymentRequirementsV2(requirements: PaymentRequirements): PaymentRequirementsV2;
|
|
556
671
|
/**
|
|
@@ -561,24 +676,48 @@ declare function toPaymentRequirementsV2(requirements: PaymentRequirements): Pay
|
|
|
561
676
|
*
|
|
562
677
|
* **Auto keys off CAIP-2, NOT off `paymentHeader.x402Version`,** and that is a
|
|
563
678
|
* measured decision rather than a stylistic one. The facilitator's envelope enum
|
|
564
|
-
* is untagged: it matches on SHAPE and ignores the version marker.
|
|
565
|
-
*
|
|
679
|
+
* is untagged: it matches on SHAPE and ignores the version marker.
|
|
680
|
+
*
|
|
681
|
+
* Re-measured against `https://facilitator.ultravioletadao.xyz/verify` on
|
|
682
|
+
* **2026-09-04** with a fabricated signature. The signature never verifies, so
|
|
683
|
+
* every row is an HTTP 400 and the STATUS discriminates nothing -- what does is
|
|
684
|
+
* the error code. `invalid_request_body` means the facilitator could not
|
|
685
|
+
* deserialize the body; `contract_call_failed` means it read the body, resolved
|
|
686
|
+
* the chain and got as far as the on-chain call, i.e. the envelope was fine.
|
|
566
687
|
*
|
|
567
688
|
* | payload network | requirements network | v1 envelope today |
|
|
568
689
|
* |-----------------|----------------------|-------------------|
|
|
569
|
-
* | `base` | `base` |
|
|
570
|
-
* | `base` (header says `x402Version: 2`) | `base` |
|
|
571
|
-
* | `eip155:8453` | `base` |
|
|
572
|
-
* | `base` | `eip155:8453` |
|
|
573
|
-
* | `eip155:8453` | `eip155:8453` |
|
|
574
|
-
*
|
|
575
|
-
*
|
|
576
|
-
*
|
|
577
|
-
*
|
|
578
|
-
*
|
|
579
|
-
* cannot regress anyone
|
|
580
|
-
|
|
581
|
-
|
|
690
|
+
* | `base` | `base` | understood |
|
|
691
|
+
* | `base` (header says `x402Version: 2`) | `base` | understood |
|
|
692
|
+
* | `eip155:8453` | `base` | understood |
|
|
693
|
+
* | `base` | `eip155:8453` | understood |
|
|
694
|
+
* | `eip155:8453` | `eip155:8453` | understood |
|
|
695
|
+
*
|
|
696
|
+
* **The last three rows used to be a hard 400** (`unknown variant
|
|
697
|
+
* \`eip155:8453\``) when this function was written on 2026-09-03. The
|
|
698
|
+
* facilitator has since taught the v1 envelope to read CAIP-2, so the original
|
|
699
|
+
* argument for this rule -- "every CAIP-2 combination is already a 400, so
|
|
700
|
+
* upgrading them cannot regress anyone" -- **is no longer true**. The rule is
|
|
701
|
+
* unchanged; three other reasons hold it up:
|
|
702
|
+
*
|
|
703
|
+
* 1. A CAIP-2 network on the wire means the 402 that produced it advertised v2.
|
|
704
|
+
* Answering in v2 is speaking the protocol the seller announced.
|
|
705
|
+
* 2. v2-with-CAIP-2 is the only shape BOTH generations of the facilitator
|
|
706
|
+
* accept. v1-with-CAIP-2 is a hard 400 on any build older than 2026-09-04,
|
|
707
|
+
* so choosing v1 there is what breaks against a self-hosted or pinned one.
|
|
708
|
+
* 3. The Python SDK resolves the identical rule, so the same wire produces the
|
|
709
|
+
* same body in both SDKs -- pinned by phase 6 of `npm run test:xlang`.
|
|
710
|
+
*
|
|
711
|
+
* And the marker still decides nothing: row 2 above is served correctly today,
|
|
712
|
+
* so upgrading on the strength of it would change a call that works.
|
|
713
|
+
*
|
|
714
|
+
* The negative half of that measurement, without which "understood" proves
|
|
715
|
+
* nothing -- the same run, bodies broken on purpose, all three
|
|
716
|
+
* `invalid_request_body`: a v2 body carrying a plain network name, one with
|
|
717
|
+
* `resource` as a bare string, and one with `accepted` removed. A well-formed
|
|
718
|
+
* v2 body with CAIP-2 reached `contract_call_failed` like the rows above.
|
|
719
|
+
*/
|
|
720
|
+
declare function resolveEnvelopeVersion(paymentHeader: X402Header | PaymentPayloadV2, requirements: PaymentRequirements, requested?: X402Version | 'auto'): X402Version;
|
|
582
721
|
/**
|
|
583
722
|
* Build a `/verify` body in whichever envelope `version` names.
|
|
584
723
|
*
|
|
@@ -2074,6 +2213,13 @@ declare class Erc8004LookupError extends Error {
|
|
|
2074
2213
|
* `502` and `504` join `503` and `429` here: a gateway that answered on the
|
|
2075
2214
|
* facilitator's behalf is exactly as silent about the agent's existence, and
|
|
2076
2215
|
* reading either as absence has the same consequence -- a duplicate mint.
|
|
2216
|
+
*
|
|
2217
|
+
* **Except when the body says otherwise.** `POST /register` goes through the
|
|
2218
|
+
* same EVM `send_transaction_from` as a settle, so it can answer
|
|
2219
|
+
* `settlement_unconfirmed`: the mint was broadcast and may be mined. That is
|
|
2220
|
+
* a `502` where retrying is precisely the thing that mints the duplicate this
|
|
2221
|
+
* class exists to prevent, so an explicit `retryable: false` wins over the
|
|
2222
|
+
* status. See {@link SETTLEMENT_UNCONFIRMED}.
|
|
2077
2223
|
*/
|
|
2078
2224
|
get retryable(): boolean;
|
|
2079
2225
|
/**
|
|
@@ -2083,6 +2229,18 @@ declare class Erc8004LookupError extends Error {
|
|
|
2083
2229
|
* request may be re-sent; see {@link isReplayableLeaseReason}.
|
|
2084
2230
|
*/
|
|
2085
2231
|
get reason(): string | undefined;
|
|
2232
|
+
/** The facilitator's machine-readable `error` code, when the body carried one. */
|
|
2233
|
+
get errorCode(): string | undefined;
|
|
2234
|
+
/**
|
|
2235
|
+
* A transaction that WAS broadcast and could not be confirmed.
|
|
2236
|
+
*
|
|
2237
|
+
* Present on `settlement_unconfirmed`. This is what to do INSTEAD of
|
|
2238
|
+
* retrying: look it up on chain. An error that carries "do not retry" and no
|
|
2239
|
+
* hash leaves the caller with nothing to act on.
|
|
2240
|
+
*/
|
|
2241
|
+
get transaction(): string | undefined;
|
|
2242
|
+
/** The payment id for {@link transaction}, identical to a successful settle's. */
|
|
2243
|
+
get paymentId(): string | undefined;
|
|
2086
2244
|
/**
|
|
2087
2245
|
* The facilitator NAMED a reason proving it executed nothing.
|
|
2088
2246
|
*
|
|
@@ -3217,4 +3375,4 @@ declare class AdvancedEscrowClient {
|
|
|
3217
3375
|
private sendViaAdapter;
|
|
3218
3376
|
}
|
|
3219
3377
|
|
|
3220
|
-
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, buildSettleRequestForVersion, buildSettleRequestV2, buildVerifyRequest, buildVerifyRequestForVersion, buildVerifyRequestV2, canRefundEscrow, canReleaseEscrow, carryFailureFields, create402Response, createHonoMiddleware, createPaymentMiddleware, epochToDate, escrowTimeRemaining, extractPaymentFromHeaders, facilitatorFetch, getCorsHeaders, getEscrowContractsByChainId, getEscrowSupportedChainIds, isAlive, isAmbiguousLeaseReason, isEscrowExpired, isEscrowSupportedOnChain, isRegisterJobTerminal, isReplayableLeaseReason, parsePaymentHeader, parseRetryAfterSeconds, readFacilitatorError, resolveEnvelopeVersion, supportsRelayedFeedback, toPaymentRequirementsV2, toResourceInfoV2, wireNetwork };
|
|
3378
|
+
export { AMBIGUOUS_LEASE_REASONS, type AdvancedAuthorizationResult, AdvancedEscrowClient, type AdvancedEscrowClientOptions, type AdvancedEscrowContracts, type AdvancedEscrowTaskTier, type AdvancedPaymentInfo, type AdvancedTransactionResult, type AgentId, type AgentIdentity, type AgentRegistration, type AgentRegistrationFile, type AgentService, type AtomStats, BASE_MAINNET_CONTRACTS, BazaarClient, type BazaarClientOptions, type BazaarDiscoverOptions, type BazaarDiscoverResponse, type BazaarRegisterOptions, type BazaarResource, type CreateEscrowOptions, DEFAULT_FACILITATOR_RETRIES, DEFAULT_RETRY_AFTER_SECONDS, DEPOSIT_LIMIT_USDC, type DiscoveryAccepts, type DiscoveryCuration, type DiscoveryHealth, type DiscoveryHealthStatus, type DiscoveryListOptions, type DiscoveryPagination, type DiscoveryRegisterOptions, type DiscoveryResource, type DiscoveryResponse, type DiscoverySource, type DiscoveryStats, type DiscoveryTier, type Dispute, type DisputeOutcome, ERC8004_CONTRACTS, ERC8004_EXTENSION_ID, ESCROW_CONTRACTS, ESCROW_TIMEOUT_MS, Erc8004Client, type Erc8004ClientOptions, Erc8004LookupError, type Erc8004Network, EscrowClient, type EscrowClientOptions, type EscrowPayment, type EscrowStateResponse, type EscrowStatus, FacilitatorClient, type FacilitatorClientOptions, type FacilitatorErrorInfo, type FacilitatorFailureFields, type FacilitatorFetchOptions, type FeedbackEntry, type FeedbackParams, type FeedbackRequest, type FeedbackResponse, HEALTH_FILTERS, type HonoMiddlewareOptions, type IdentityByOwnerResponse, type IdentityMetadataResponse, type IdentityTotalSupplyResponse, MAX_RETRY_AFTER_SECONDS, MAX_SEARCH_LEN, type MetadataEntryParam, OPERATOR_ABI, OPERATOR_ABI_CREATE3, PAYMENT_INFO_TYPEHASH, type ParsedFacilitatorErrorBody, type PaymentAcceptance, type PaymentMiddlewareOptions, type PaymentPayloadV2, type PaymentRequirementResolver, type PaymentRequirements, type PaymentRequirementsOptions, type PaymentRequirementsV2, type PrepareRelayFeedbackRequest, type PrepareRelayFeedbackResponse, type PrepareRelayResponseRequest, type ProofOfPayment, RELAYED_FEEDBACK_NETWORKS, REPLAYABLE_LEASE_REASONS, type RefundRequest, type RefundStatus, type RegisterAgentRequest, type RegisterAgentResponse, type RegisterJobResponse, type RegisterJobStatus, RegistrationPendingError, type RelayAuthorizationParams, type ReputationResponse, type ReputationSummary, type RequestRefundOptions, type ResourceInfoV2, SETTLEMENT_UNCONFIRMED, type SettleRequest, type SettleRequestV2, type SettleResponse, type SettleResponseWithProof, type SubmitRelayFeedbackRequest, type SubmitRelayResponseRequest, TIER_FILTERS, TIER_TIMINGS, USDC_DOMAIN_NAME, type VerifiedPaymentState, type VerifyRequest, type VerifyRequestV2, type VerifyResponse, WRITER_LEASE_REASONS, type WriterLeaseReason, X402_CORS_HEADERS, X402_HEADER_NAMES, ZERO_ADDRESS, buildErc8004PaymentRequirements, buildPaymentRequirements, buildSettleRequest, buildSettleRequestForVersion, buildSettleRequestV2, buildVerifyRequest, buildVerifyRequestForVersion, buildVerifyRequestV2, canRefundEscrow, canReleaseEscrow, carryFailureFields, create402Response, createHonoMiddleware, createPaymentMiddleware, epochToDate, escrowTimeRemaining, extractPaymentFromHeaders, facilitatorFetch, getCorsHeaders, getEscrowContractsByChainId, getEscrowSupportedChainIds, isAlive, isAmbiguousLeaseReason, isEscrowExpired, isEscrowSupportedOnChain, isRegisterJobTerminal, isReplayableLeaseReason, isSettlementUnconfirmed, parseFacilitatorErrorBody, parsePaymentHeader, parseRetryAfterSeconds, readFacilitatorError, resolveEnvelopeVersion, supportsRelayedFeedback, toPaymentRequirementsV2, toResourceInfoV2, wireNetwork };
|
package/dist/backend/index.js
CHANGED
|
@@ -1108,6 +1108,7 @@ var REPLAYABLE_LEASE_REASONS = [
|
|
|
1108
1108
|
"body_unreadable"
|
|
1109
1109
|
];
|
|
1110
1110
|
var AMBIGUOUS_LEASE_REASONS = ["forward_failed"];
|
|
1111
|
+
var SETTLEMENT_UNCONFIRMED = "settlement_unconfirmed";
|
|
1111
1112
|
var MAX_RETRY_AFTER_SECONDS = 15;
|
|
1112
1113
|
var DEFAULT_RETRY_AFTER_SECONDS = 5;
|
|
1113
1114
|
var DEFAULT_FACILITATOR_RETRIES = 2;
|
|
@@ -1129,15 +1130,44 @@ function parseRetryAfterSeconds(response) {
|
|
|
1129
1130
|
if (!Number.isFinite(seconds) || seconds < 0) return void 0;
|
|
1130
1131
|
return Math.min(seconds, MAX_RETRY_AFTER_SECONDS);
|
|
1131
1132
|
}
|
|
1132
|
-
function
|
|
1133
|
+
function stringField(source, key) {
|
|
1134
|
+
const value = source[key];
|
|
1135
|
+
return typeof value === "string" && value !== "" ? value : void 0;
|
|
1136
|
+
}
|
|
1137
|
+
function transactionHashIn(source) {
|
|
1138
|
+
const tx = source.transaction;
|
|
1139
|
+
if (tx && typeof tx === "object") {
|
|
1140
|
+
const hash = tx.hash;
|
|
1141
|
+
if (typeof hash === "string" && hash !== "") return hash;
|
|
1142
|
+
}
|
|
1143
|
+
if (typeof tx === "string" && tx !== "") return tx;
|
|
1144
|
+
for (const key of ["txHash", "tx_hash", "transaction_hash"]) {
|
|
1145
|
+
const value = stringField(source, key);
|
|
1146
|
+
if (value !== void 0) return value;
|
|
1147
|
+
}
|
|
1148
|
+
return void 0;
|
|
1149
|
+
}
|
|
1150
|
+
function parseFacilitatorErrorBody(body) {
|
|
1151
|
+
let parsed;
|
|
1133
1152
|
try {
|
|
1134
|
-
|
|
1135
|
-
if (parsed && typeof parsed === "object" && typeof parsed.reason === "string") {
|
|
1136
|
-
return parsed.reason;
|
|
1137
|
-
}
|
|
1153
|
+
parsed = JSON.parse(body);
|
|
1138
1154
|
} catch {
|
|
1155
|
+
return {};
|
|
1139
1156
|
}
|
|
1140
|
-
return
|
|
1157
|
+
if (!parsed || typeof parsed !== "object") return {};
|
|
1158
|
+
return {
|
|
1159
|
+
errorCode: stringField(parsed, "error"),
|
|
1160
|
+
reason: stringField(parsed, "reason"),
|
|
1161
|
+
transaction: transactionHashIn(parsed),
|
|
1162
|
+
paymentId: stringField(parsed, "paymentId"),
|
|
1163
|
+
retryable: typeof parsed.retryable === "boolean" ? parsed.retryable : void 0
|
|
1164
|
+
};
|
|
1165
|
+
}
|
|
1166
|
+
function isDeclaredUnretryable(parsed) {
|
|
1167
|
+
return parsed.retryable === false || parsed.errorCode === SETTLEMENT_UNCONFIRMED || parsed.transaction !== void 0;
|
|
1168
|
+
}
|
|
1169
|
+
function isSettlementUnconfirmed(failure) {
|
|
1170
|
+
return failure.errorCode === SETTLEMENT_UNCONFIRMED;
|
|
1141
1171
|
}
|
|
1142
1172
|
async function readFacilitatorError(response) {
|
|
1143
1173
|
let body = "";
|
|
@@ -1147,14 +1177,19 @@ async function readFacilitatorError(response) {
|
|
|
1147
1177
|
body = "";
|
|
1148
1178
|
}
|
|
1149
1179
|
const status = response.status;
|
|
1150
|
-
const
|
|
1151
|
-
const
|
|
1180
|
+
const parsed = parseFacilitatorErrorBody(body);
|
|
1181
|
+
const reason = parsed.reason;
|
|
1182
|
+
const transportRetryable = status === 429 || status === 502 || status === 503 || status === 504;
|
|
1183
|
+
const retryable = transportRetryable && !isDeclaredUnretryable(parsed);
|
|
1152
1184
|
const retryAfterSeconds = retryable ? parseRetryAfterSeconds(response) ?? DEFAULT_RETRY_AFTER_SECONDS : void 0;
|
|
1153
|
-
const safeToReplay = status === 429 || status === 503 && isReplayableLeaseReason(reason);
|
|
1185
|
+
const safeToReplay = retryable && (status === 429 || status === 503 && isReplayableLeaseReason(reason));
|
|
1154
1186
|
return {
|
|
1155
1187
|
error: `Facilitator error: ${status} - ${body}`,
|
|
1156
1188
|
status,
|
|
1157
1189
|
reason,
|
|
1190
|
+
errorCode: parsed.errorCode,
|
|
1191
|
+
transaction: parsed.transaction,
|
|
1192
|
+
paymentId: parsed.paymentId,
|
|
1158
1193
|
retryAfterSeconds,
|
|
1159
1194
|
retryable,
|
|
1160
1195
|
safeToReplay,
|
|
@@ -1167,6 +1202,11 @@ function failureFields(info) {
|
|
|
1167
1202
|
retryable: info.retryable,
|
|
1168
1203
|
safeToReplay: info.safeToReplay,
|
|
1169
1204
|
...info.reason !== void 0 ? { reason: info.reason } : {},
|
|
1205
|
+
...info.errorCode !== void 0 ? { errorCode: info.errorCode } : {},
|
|
1206
|
+
// Without these the caller is told "do not retry" and given nothing to do
|
|
1207
|
+
// instead — an error that swallows the hash is the same defect one layer up.
|
|
1208
|
+
...info.transaction !== void 0 ? { transaction: info.transaction } : {},
|
|
1209
|
+
...info.paymentId !== void 0 ? { paymentId: info.paymentId } : {},
|
|
1170
1210
|
...info.retryAfterSeconds !== void 0 ? { retryAfterSeconds: info.retryAfterSeconds } : {}
|
|
1171
1211
|
};
|
|
1172
1212
|
}
|
|
@@ -1174,6 +1214,9 @@ function carryFailureFields(source) {
|
|
|
1174
1214
|
return {
|
|
1175
1215
|
...source.status !== void 0 ? { status: source.status } : {},
|
|
1176
1216
|
...source.reason !== void 0 ? { reason: source.reason } : {},
|
|
1217
|
+
...source.errorCode !== void 0 ? { errorCode: source.errorCode } : {},
|
|
1218
|
+
...source.transaction !== void 0 ? { transaction: source.transaction } : {},
|
|
1219
|
+
...source.paymentId !== void 0 ? { paymentId: source.paymentId } : {},
|
|
1177
1220
|
...source.retryable !== void 0 ? { retryable: source.retryable } : {},
|
|
1178
1221
|
...source.retryAfterSeconds !== void 0 ? { retryAfterSeconds: source.retryAfterSeconds } : {},
|
|
1179
1222
|
...source.safeToReplay !== void 0 ? { safeToReplay: source.safeToReplay } : {}
|
|
@@ -1261,7 +1304,23 @@ function buildPaymentRequirements(options) {
|
|
|
1261
1304
|
}
|
|
1262
1305
|
function buildVerifyRequest(paymentHeader, requirements) {
|
|
1263
1306
|
return {
|
|
1264
|
-
|
|
1307
|
+
// The literal `1` names THIS ENVELOPE, not the payer's header. Echoing
|
|
1308
|
+
// `paymentHeader.x402Version` here -- what this did until 2026-09-04 --
|
|
1309
|
+
// let a buyer who declared `2` produce a body that says "2" while carrying
|
|
1310
|
+
// `paymentRequirements`, which is the v1 shape. The facilitator serves it
|
|
1311
|
+
// anyway because its envelope enum is untagged and matches on shape, so
|
|
1312
|
+
// nothing broke; but it ALREADY picks the hint in its 400 off this marker:
|
|
1313
|
+
//
|
|
1314
|
+
// "This body declares `x402Version: 2`. x402 v2 is a JSON object with
|
|
1315
|
+
// `paymentPayload`, `resource` and `accepted`..."
|
|
1316
|
+
//
|
|
1317
|
+
// So the day that body fails for any other reason, the diagnosis sends the
|
|
1318
|
+
// integrator to document the wrong shape. That inversion -- being told to
|
|
1319
|
+
// fix the fields when the wrapper is what is wrong -- is what cost two
|
|
1320
|
+
// teams a day. The payer's own marker survives untouched inside
|
|
1321
|
+
// `paymentPayload`, where it belongs: it describes the payment, not the
|
|
1322
|
+
// envelope carrying it.
|
|
1323
|
+
x402Version: 1,
|
|
1265
1324
|
paymentPayload: paymentHeader,
|
|
1266
1325
|
paymentRequirements: requirements
|
|
1267
1326
|
};
|
|
@@ -1284,13 +1343,21 @@ function buildSettleRequestV2(payload, resource, accepted) {
|
|
|
1284
1343
|
}
|
|
1285
1344
|
function buildSettleRequest(paymentHeader, requirements) {
|
|
1286
1345
|
return {
|
|
1287
|
-
|
|
1346
|
+
// `1` for the same reason as {@link buildVerifyRequest}: it names the
|
|
1347
|
+
// envelope, and `/settle` takes the same body as `/verify`.
|
|
1348
|
+
x402Version: 1,
|
|
1288
1349
|
paymentPayload: paymentHeader,
|
|
1289
1350
|
paymentRequirements: requirements
|
|
1290
1351
|
};
|
|
1291
1352
|
}
|
|
1292
1353
|
function isCaip2Network(network) {
|
|
1293
|
-
return network.includes(":");
|
|
1354
|
+
return typeof network === "string" && network.includes(":");
|
|
1355
|
+
}
|
|
1356
|
+
function networkOfPayload(payload) {
|
|
1357
|
+
const top = payload.network;
|
|
1358
|
+
if (typeof top === "string") return top;
|
|
1359
|
+
const accepted = payload.accepted;
|
|
1360
|
+
return typeof accepted?.network === "string" ? accepted.network : void 0;
|
|
1294
1361
|
}
|
|
1295
1362
|
function toResourceInfoV2(requirements) {
|
|
1296
1363
|
return {
|
|
@@ -1300,9 +1367,15 @@ function toResourceInfoV2(requirements) {
|
|
|
1300
1367
|
};
|
|
1301
1368
|
}
|
|
1302
1369
|
function toPaymentRequirementsV2(requirements) {
|
|
1370
|
+
const network = isCaip2Network(requirements.network) ? requirements.network : chainToCAIP2(requirements.network);
|
|
1371
|
+
if (!isCaip2Network(network)) {
|
|
1372
|
+
throw new Error(
|
|
1373
|
+
`Network '${requirements.network}' has no CAIP-2 form, so it cannot travel in the x402 v2 envelope. Use x402Version: 1 for this network.`
|
|
1374
|
+
);
|
|
1375
|
+
}
|
|
1303
1376
|
return {
|
|
1304
1377
|
scheme: requirements.scheme,
|
|
1305
|
-
network
|
|
1378
|
+
network,
|
|
1306
1379
|
asset: requirements.asset,
|
|
1307
1380
|
amount: requirements.maxAmountRequired,
|
|
1308
1381
|
payTo: requirements.payTo,
|
|
@@ -1315,7 +1388,7 @@ function resolveEnvelopeVersion(paymentHeader, requirements, requested = "auto")
|
|
|
1315
1388
|
if (requested !== "auto") {
|
|
1316
1389
|
return requested;
|
|
1317
1390
|
}
|
|
1318
|
-
return isCaip2Network(paymentHeader
|
|
1391
|
+
return isCaip2Network(networkOfPayload(paymentHeader)) || isCaip2Network(requirements.network) ? 2 : 1;
|
|
1319
1392
|
}
|
|
1320
1393
|
function buildVerifyRequestForVersion(paymentHeader, requirements, version) {
|
|
1321
1394
|
if (version === 2) {
|
|
@@ -1988,16 +2061,23 @@ function createPaymentMiddleware(getRequirements, options = {}) {
|
|
|
1988
2061
|
respondUnavailable(res, "Payment settlement unavailable", settleResult);
|
|
1989
2062
|
return;
|
|
1990
2063
|
}
|
|
1991
|
-
res.status(500).json(
|
|
1992
|
-
error: "Payment settlement failed",
|
|
1993
|
-
reason: settleResult.error || "Unknown settlement error"
|
|
1994
|
-
});
|
|
2064
|
+
res.status(500).json(settlementFailureBody(settleResult, "Unknown settlement error"));
|
|
1995
2065
|
return;
|
|
1996
2066
|
}
|
|
1997
2067
|
}
|
|
1998
2068
|
next();
|
|
1999
2069
|
};
|
|
2000
2070
|
}
|
|
2071
|
+
function settlementFailureBody(failure, fallbackReason) {
|
|
2072
|
+
return {
|
|
2073
|
+
error: "Payment settlement failed",
|
|
2074
|
+
reason: failure.error || fallbackReason,
|
|
2075
|
+
retryable: false,
|
|
2076
|
+
...failure.errorCode !== void 0 ? { errorCode: failure.errorCode } : {},
|
|
2077
|
+
...failure.transaction !== void 0 ? { transaction: failure.transaction } : {},
|
|
2078
|
+
...failure.paymentId !== void 0 ? { paymentId: failure.paymentId } : {}
|
|
2079
|
+
};
|
|
2080
|
+
}
|
|
2001
2081
|
function honoUnavailable(c, message, failure) {
|
|
2002
2082
|
const seconds = Math.max(1, Math.ceil(failure.retryAfterSeconds ?? DEFAULT_RETRY_AFTER_SECONDS));
|
|
2003
2083
|
c.header?.("Retry-After", String(seconds));
|
|
@@ -2072,10 +2152,7 @@ function createHonoMiddleware(options) {
|
|
|
2072
2152
|
if (settleResult.retryable) {
|
|
2073
2153
|
return honoUnavailable(c, "Payment settlement unavailable", settleResult);
|
|
2074
2154
|
}
|
|
2075
|
-
return c.json(
|
|
2076
|
-
error: "Payment settlement failed",
|
|
2077
|
-
reason: settleResult.error || "Unknown error"
|
|
2078
|
-
}, 500);
|
|
2155
|
+
return c.json(settlementFailureBody(settleResult, "Unknown error"), 500);
|
|
2079
2156
|
}
|
|
2080
2157
|
}
|
|
2081
2158
|
await next();
|
|
@@ -2878,8 +2955,19 @@ var Erc8004LookupError = class extends Error {
|
|
|
2878
2955
|
* `502` and `504` join `503` and `429` here: a gateway that answered on the
|
|
2879
2956
|
* facilitator's behalf is exactly as silent about the agent's existence, and
|
|
2880
2957
|
* reading either as absence has the same consequence -- a duplicate mint.
|
|
2958
|
+
*
|
|
2959
|
+
* **Except when the body says otherwise.** `POST /register` goes through the
|
|
2960
|
+
* same EVM `send_transaction_from` as a settle, so it can answer
|
|
2961
|
+
* `settlement_unconfirmed`: the mint was broadcast and may be mined. That is
|
|
2962
|
+
* a `502` where retrying is precisely the thing that mints the duplicate this
|
|
2963
|
+
* class exists to prevent, so an explicit `retryable: false` wins over the
|
|
2964
|
+
* status. See {@link SETTLEMENT_UNCONFIRMED}.
|
|
2881
2965
|
*/
|
|
2882
2966
|
get retryable() {
|
|
2967
|
+
const parsed = parseFacilitatorErrorBody(this.body);
|
|
2968
|
+
if (parsed.retryable === false || parsed.errorCode === SETTLEMENT_UNCONFIRMED) {
|
|
2969
|
+
return false;
|
|
2970
|
+
}
|
|
2883
2971
|
return this.status === 429 || this.status === 502 || this.status === 503 || this.status === 504;
|
|
2884
2972
|
}
|
|
2885
2973
|
/**
|
|
@@ -2889,14 +2977,25 @@ var Erc8004LookupError = class extends Error {
|
|
|
2889
2977
|
* request may be re-sent; see {@link isReplayableLeaseReason}.
|
|
2890
2978
|
*/
|
|
2891
2979
|
get reason() {
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2980
|
+
return parseFacilitatorErrorBody(this.body).reason;
|
|
2981
|
+
}
|
|
2982
|
+
/** The facilitator's machine-readable `error` code, when the body carried one. */
|
|
2983
|
+
get errorCode() {
|
|
2984
|
+
return parseFacilitatorErrorBody(this.body).errorCode;
|
|
2985
|
+
}
|
|
2986
|
+
/**
|
|
2987
|
+
* A transaction that WAS broadcast and could not be confirmed.
|
|
2988
|
+
*
|
|
2989
|
+
* Present on `settlement_unconfirmed`. This is what to do INSTEAD of
|
|
2990
|
+
* retrying: look it up on chain. An error that carries "do not retry" and no
|
|
2991
|
+
* hash leaves the caller with nothing to act on.
|
|
2992
|
+
*/
|
|
2993
|
+
get transaction() {
|
|
2994
|
+
return parseFacilitatorErrorBody(this.body).transaction;
|
|
2995
|
+
}
|
|
2996
|
+
/** The payment id for {@link transaction}, identical to a successful settle's. */
|
|
2997
|
+
get paymentId() {
|
|
2998
|
+
return parseFacilitatorErrorBody(this.body).paymentId;
|
|
2900
2999
|
}
|
|
2901
3000
|
/**
|
|
2902
3001
|
* The facilitator NAMED a reason proving it executed nothing.
|
|
@@ -2906,7 +3005,7 @@ var Erc8004LookupError = class extends Error {
|
|
|
2906
3005
|
* this is false is the sequence that minted five duplicate agents.
|
|
2907
3006
|
*/
|
|
2908
3007
|
get safeToReplay() {
|
|
2909
|
-
return this.status === 429 || this.status === 503 && isReplayableLeaseReason(this.reason);
|
|
3008
|
+
return this.retryable && (this.status === 429 || this.status === 503 && isReplayableLeaseReason(this.reason));
|
|
2910
3009
|
}
|
|
2911
3010
|
/** Seconds to wait before retrying, clamped. Absent when not retryable. */
|
|
2912
3011
|
get retryAfterSeconds() {
|
|
@@ -4767,6 +4866,7 @@ exports.PAYMENT_INFO_TYPEHASH = PAYMENT_INFO_TYPEHASH;
|
|
|
4767
4866
|
exports.RELAYED_FEEDBACK_NETWORKS = RELAYED_FEEDBACK_NETWORKS;
|
|
4768
4867
|
exports.REPLAYABLE_LEASE_REASONS = REPLAYABLE_LEASE_REASONS;
|
|
4769
4868
|
exports.RegistrationPendingError = RegistrationPendingError;
|
|
4869
|
+
exports.SETTLEMENT_UNCONFIRMED = SETTLEMENT_UNCONFIRMED;
|
|
4770
4870
|
exports.TIER_FILTERS = TIER_FILTERS;
|
|
4771
4871
|
exports.TIER_TIMINGS = TIER_TIMINGS;
|
|
4772
4872
|
exports.USDC_DOMAIN_NAME = USDC_DOMAIN_NAME;
|
|
@@ -4801,6 +4901,8 @@ exports.isEscrowExpired = isEscrowExpired;
|
|
|
4801
4901
|
exports.isEscrowSupportedOnChain = isEscrowSupportedOnChain;
|
|
4802
4902
|
exports.isRegisterJobTerminal = isRegisterJobTerminal;
|
|
4803
4903
|
exports.isReplayableLeaseReason = isReplayableLeaseReason;
|
|
4904
|
+
exports.isSettlementUnconfirmed = isSettlementUnconfirmed;
|
|
4905
|
+
exports.parseFacilitatorErrorBody = parseFacilitatorErrorBody;
|
|
4804
4906
|
exports.parsePaymentHeader = parsePaymentHeader;
|
|
4805
4907
|
exports.parseRetryAfterSeconds = parseRetryAfterSeconds;
|
|
4806
4908
|
exports.readFacilitatorError = readFacilitatorError;
|