uvd-x402-sdk 2.95.0 → 2.97.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.
Files changed (99) hide show
  1. package/README.md +34 -5
  2. package/dist/adapters/index.d.mts +1 -1
  3. package/dist/adapters/index.d.ts +1 -1
  4. package/dist/adapters/index.js +2 -1
  5. package/dist/adapters/index.js.map +1 -1
  6. package/dist/adapters/index.mjs +2 -1
  7. package/dist/adapters/index.mjs.map +1 -1
  8. package/dist/backend/index.d.mts +3 -2
  9. package/dist/backend/index.d.ts +3 -2
  10. package/dist/backend/index.js +498 -30
  11. package/dist/backend/index.js.map +1 -1
  12. package/dist/backend/index.mjs +475 -31
  13. package/dist/backend/index.mjs.map +1 -1
  14. package/dist/{index-CF2HBEAJ.d.mts → index--bevvYU9.d.ts} +3 -1
  15. package/dist/{index-CkHu2s9r.d.ts → index-B2i1mGpW.d.mts} +3 -1
  16. package/dist/{index-DnxubrYX.d.mts → index-BsKsZzP3.d.mts} +1 -1
  17. package/dist/{index-DnxubrYX.d.ts → index-BsKsZzP3.d.ts} +1 -1
  18. package/dist/{index-CIUGPbu8.d.mts → index-ClOAmprt.d.mts} +232 -18
  19. package/dist/{index-DTbVW7EU.d.ts → index-DNTFp6WT.d.ts} +232 -18
  20. package/dist/index.d.mts +5 -4
  21. package/dist/index.d.ts +5 -4
  22. package/dist/index.js +512 -43
  23. package/dist/index.js.map +1 -1
  24. package/dist/index.mjs +489 -44
  25. package/dist/index.mjs.map +1 -1
  26. package/dist/providers/algorand/index.d.mts +1 -1
  27. package/dist/providers/algorand/index.d.ts +1 -1
  28. package/dist/providers/algorand/index.js +2 -1
  29. package/dist/providers/algorand/index.js.map +1 -1
  30. package/dist/providers/algorand/index.mjs +2 -1
  31. package/dist/providers/algorand/index.mjs.map +1 -1
  32. package/dist/providers/evm/index.d.mts +1 -1
  33. package/dist/providers/evm/index.d.ts +1 -1
  34. package/dist/providers/evm/index.js +2 -1
  35. package/dist/providers/evm/index.js.map +1 -1
  36. package/dist/providers/evm/index.mjs +2 -1
  37. package/dist/providers/evm/index.mjs.map +1 -1
  38. package/dist/providers/hedera/index.d.mts +1 -1
  39. package/dist/providers/hedera/index.d.ts +1 -1
  40. package/dist/providers/near/index.d.mts +1 -1
  41. package/dist/providers/near/index.d.ts +1 -1
  42. package/dist/providers/near/index.js +2 -1
  43. package/dist/providers/near/index.js.map +1 -1
  44. package/dist/providers/near/index.mjs +2 -1
  45. package/dist/providers/near/index.mjs.map +1 -1
  46. package/dist/providers/solana/index.d.mts +1 -1
  47. package/dist/providers/solana/index.d.ts +1 -1
  48. package/dist/providers/solana/index.js +2 -1
  49. package/dist/providers/solana/index.js.map +1 -1
  50. package/dist/providers/solana/index.mjs +2 -1
  51. package/dist/providers/solana/index.mjs.map +1 -1
  52. package/dist/providers/stellar/index.d.mts +1 -1
  53. package/dist/providers/stellar/index.d.ts +1 -1
  54. package/dist/providers/stellar/index.js +2 -1
  55. package/dist/providers/stellar/index.js.map +1 -1
  56. package/dist/providers/stellar/index.mjs +2 -1
  57. package/dist/providers/stellar/index.mjs.map +1 -1
  58. package/dist/providers/sui/index.d.mts +1 -1
  59. package/dist/providers/sui/index.d.ts +1 -1
  60. package/dist/providers/sui/index.js +2 -1
  61. package/dist/providers/sui/index.js.map +1 -1
  62. package/dist/providers/sui/index.mjs +2 -1
  63. package/dist/providers/sui/index.mjs.map +1 -1
  64. package/dist/providers/xrpl/index.d.mts +1 -1
  65. package/dist/providers/xrpl/index.d.ts +1 -1
  66. package/dist/providers/xrpl/index.js +2 -1
  67. package/dist/providers/xrpl/index.js.map +1 -1
  68. package/dist/providers/xrpl/index.mjs +2 -1
  69. package/dist/providers/xrpl/index.mjs.map +1 -1
  70. package/dist/react/index.d.mts +4 -3
  71. package/dist/react/index.d.ts +4 -3
  72. package/dist/react/index.js +153 -1
  73. package/dist/react/index.js.map +1 -1
  74. package/dist/react/index.mjs +153 -1
  75. package/dist/react/index.mjs.map +1 -1
  76. package/dist/react/picker/index.d.mts +1 -1
  77. package/dist/react/picker/index.d.ts +1 -1
  78. package/dist/react/picker/index.js +2 -1
  79. package/dist/react/picker/index.js.map +1 -1
  80. package/dist/react/picker/index.mjs +2 -1
  81. package/dist/react/picker/index.mjs.map +1 -1
  82. package/dist/receipts-Co6C9FPO.d.ts +111 -0
  83. package/dist/receipts-D0zg-8uK.d.mts +111 -0
  84. package/dist/utils/index.d.mts +2 -2
  85. package/dist/utils/index.d.ts +2 -2
  86. package/dist/utils/index.js +2 -1
  87. package/dist/utils/index.js.map +1 -1
  88. package/dist/utils/index.mjs +2 -1
  89. package/dist/utils/index.mjs.map +1 -1
  90. package/dist/{validity-SD6nwegA.d.mts → validity-BcPTzuK8.d.mts} +1 -1
  91. package/dist/{validity-BrvXzCEF.d.ts → validity-CoCrj9pZ.d.ts} +1 -1
  92. package/package.json +1 -1
  93. package/src/backend/facilitator-error.ts +87 -2
  94. package/src/backend/index.ts +445 -41
  95. package/src/chains/index.ts +2 -1
  96. package/src/client/X402Client.ts +5 -0
  97. package/src/fixtures/facilitator-receipts-v1.json +299 -0
  98. package/src/index.ts +18 -0
  99. package/src/receipts.ts +237 -0
@@ -1,3 +1,6 @@
1
+ import { ed25519 } from '@noble/curves/ed25519';
2
+ import { sha256 } from '@noble/hashes/sha256';
3
+ import { bytesToHex, randomBytes } from '@noble/hashes/utils';
1
4
  import { parseUnits, ethers } from 'ethers';
2
5
 
3
6
  var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
@@ -6,6 +9,205 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
6
9
  if (typeof require !== "undefined") return require.apply(this, arguments);
7
10
  throw Error('Dynamic require of "' + x + '" is not supported');
8
11
  });
12
+ var RECEIPT_ISSUER = "https://facilitator.ultravioletadao.xyz";
13
+ var encoder = new TextEncoder();
14
+ var decoder = new TextDecoder("utf-8", { fatal: true });
15
+ var digest = (value) => bytesToHex(sha256(value));
16
+ function canonicalReceiptJson(value) {
17
+ if (value === null || typeof value === "string" || typeof value === "boolean") return JSON.stringify(value);
18
+ if (typeof value === "number" && Number.isSafeInteger(value) && value >= 0) return String(value);
19
+ if (Array.isArray(value)) return `[${value.map(canonicalReceiptJson).join(",")}]`;
20
+ if (typeof value === "object" && value) {
21
+ const object = value;
22
+ const keys = Object.keys(object).sort();
23
+ if (keys.some((key) => !/^[\x00-\x7f]*$/.test(key))) throw new Error("non-ASCII canonical key");
24
+ return `{${keys.map((key) => `${JSON.stringify(key)}:${canonicalReceiptJson(object[key])}`).join(",")}}`;
25
+ }
26
+ throw new Error("unsupported canonical value");
27
+ }
28
+ function receiptCommitment(domain, value) {
29
+ return digest(encoder.encode(`${domain}
30
+ ${canonicalReceiptJson(value)}`));
31
+ }
32
+ function encode64(bytes) {
33
+ if (typeof Buffer !== "undefined") return Buffer.from(bytes).toString("base64");
34
+ return btoa(Array.from(bytes, (b) => String.fromCharCode(b)).join(""));
35
+ }
36
+ function decode64(value) {
37
+ if (!/^[A-Za-z0-9+/]*={0,2}$/.test(value) || value.length % 4 !== 0) throw new Error("invalid base64");
38
+ if (typeof Buffer !== "undefined") return new Uint8Array(Buffer.from(value, "base64"));
39
+ return Uint8Array.from(atob(value), (c) => c.charCodeAt(0));
40
+ }
41
+ function decodeUrl64(value) {
42
+ const padded = value.replace(/-/g, "+").replace(/_/g, "/");
43
+ return decode64(padded + "=".repeat((4 - padded.length % 4) % 4));
44
+ }
45
+ function parseFacilitatorReceipt(value) {
46
+ if (value === null || value === void 0) return null;
47
+ const r = value;
48
+ if (r.schemaVersion !== 1 || !["verified", "pending", "confirmed", "rejected", "unknown"].includes(r.status)) throw new Error("unsupported receipt version or state");
49
+ for (const key of ["receiptId", "issuer", "operation", "network", "scheme", "asset", "amount", "payTo", "paymentRequestHash", "authorizationId"]) {
50
+ if (typeof r[key] !== "string" || !r[key]) throw new Error(`invalid receipt ${key}`);
51
+ }
52
+ if (!Number.isSafeInteger(r.revision) || r.revision < 1 || !r.request || !r.retry) throw new Error("incomplete receipt");
53
+ if (r.requestHashVersion !== "uvd-x402-request-v1" || r.requestHash !== receiptCommitment(r.requestHashVersion, r.request)) throw new Error("receipt request hash mismatch");
54
+ for (const key of ["network", "scheme", "asset", "amount", "payTo", "purchaseId"]) {
55
+ if (r[key] !== r.request[key]) throw new Error("receipt terms mismatch");
56
+ }
57
+ if (!/^[0-9]+$/.test(r.amount)) throw new Error("receipt amount must be an atomic integer string");
58
+ if (r.status === "confirmed" && (r.operation !== "settle" || !r.settlement?.id)) throw new Error("confirmation has no settlement");
59
+ return r;
60
+ }
61
+ function verifyFacilitatorReceipt(receipt, jwks, issuer = RECEIPT_ISSUER) {
62
+ try {
63
+ parseFacilitatorReceipt(receipt);
64
+ if (receipt.issuer !== issuer || receipt.proof?.type !== "jws" || !receipt.proof.jws) return false;
65
+ const parts = receipt.proof.jws.split(".");
66
+ if (parts.length !== 3) return false;
67
+ const [protectedHeader, payload, signature] = parts;
68
+ const header = JSON.parse(decoder.decode(decodeUrl64(protectedHeader)));
69
+ if (header.alg !== "EdDSA" || header.typ !== "uvd-facilitator-receipt+jws") return false;
70
+ const keys = jwks.keys.filter((k) => k.kid === header.kid && k.kty === "OKP" && k.crv === "Ed25519");
71
+ if (keys.length !== 1 || !keys[0].x) return false;
72
+ if (decoder.decode(decodeUrl64(payload)) !== canonicalReceiptJson({ ...receipt, proof: null })) return false;
73
+ return ed25519.verify(decodeUrl64(signature), encoder.encode(`${protectedHeader}.${payload}`), decodeUrl64(keys[0].x));
74
+ } catch {
75
+ return false;
76
+ }
77
+ }
78
+ function createPurchaseContext() {
79
+ return { purchaseId: bytesToHex(randomBytes(16)), accessToken: bytesToHex(randomBytes(32)) };
80
+ }
81
+ function purchaseContextHeader(context) {
82
+ return encode64(encoder.encode(canonicalReceiptJson({
83
+ purchaseId: context.purchaseId,
84
+ accessToken: context.accessToken,
85
+ method: context.method,
86
+ url: context.url,
87
+ bodySha256: context.bodySha256
88
+ })));
89
+ }
90
+ function validatePurchaseContext(header, method, url, body) {
91
+ if (!header) return void 0;
92
+ if (header.length > 8192) throw new Error("invalid purchase context");
93
+ const context = JSON.parse(decoder.decode(decode64(header)));
94
+ if (typeof context.purchaseId !== "string" || !context.purchaseId || context.purchaseId.length > 128 || typeof context.accessToken !== "string" || !/^[0-9a-f]{64}$/.test(context.accessToken) || context.method !== method.toUpperCase() || context.url !== new URL(url).toString() || context.bodySha256 !== digest(body)) throw new Error("purchase context does not match the HTTP request");
95
+ return header;
96
+ }
97
+ function paymentResponseHeaders(result) {
98
+ const encoded = encode64(encoder.encode(JSON.stringify(result)));
99
+ if (encoded.length > 32768) throw new Error("payment response too large");
100
+ return {
101
+ "PAYMENT-RESPONSE": encoded,
102
+ "X-PAYMENT-RESPONSE": encoded,
103
+ "Access-Control-Expose-Headers": "PAYMENT-RESPONSE, X-PAYMENT-RESPONSE",
104
+ "Cache-Control": "no-store"
105
+ };
106
+ }
107
+ var LIST_HEADERS = ["Access-Control-Expose-Headers", "Cache-Control"];
108
+ function mergeHeaderList(existing, additions) {
109
+ const name = (entry) => entry.split("=")[0].trim().toLowerCase();
110
+ const kept = (existing || "").split(",").map((entry) => entry.trim()).filter(Boolean);
111
+ const seen = new Set(kept.map(name));
112
+ for (const entry of additions.split(",").map((value) => value.trim()).filter(Boolean)) {
113
+ if (!seen.has(name(entry))) {
114
+ kept.push(entry);
115
+ seen.add(name(entry));
116
+ }
117
+ }
118
+ return kept.join(", ");
119
+ }
120
+ function mergePaymentResponseHeaders(result, current) {
121
+ const headers = paymentResponseHeaders(result);
122
+ for (const name of LIST_HEADERS) headers[name] = mergeHeaderList(current(name), headers[name]);
123
+ return headers;
124
+ }
125
+ function receiptFromResponse(response) {
126
+ const values = [response.headers.get("PAYMENT-RESPONSE"), response.headers.get("X-PAYMENT-RESPONSE")].filter((v) => v !== null);
127
+ if (!values.length) return null;
128
+ if (new Set(values).size !== 1 || values[0].includes(",") || values[0].length > 32768) throw new Error("ambiguous or oversized payment response header");
129
+ return parseFacilitatorReceipt(JSON.parse(decoder.decode(decode64(values[0]))).receipt);
130
+ }
131
+ function receiptFromErrorBody(body) {
132
+ try {
133
+ return parseFacilitatorReceipt(JSON.parse(body).receipt);
134
+ } catch {
135
+ return null;
136
+ }
137
+ }
138
+ async function fetchWithReceipt(fetchClient, url, options) {
139
+ const { context, persist, trustedKeys, issuer = RECEIPT_ISSUER } = options;
140
+ const transport = options.fetchImpl || globalThis.fetch;
141
+ const method = (options.method || "GET").toUpperCase();
142
+ const request = new Request(url, { ...options.init, method });
143
+ const bytes = new Uint8Array(await request.arrayBuffer());
144
+ const bodyHash = digest(bytes);
145
+ if (context.method && (context.method !== method || context.url !== request.url || context.bodySha256 !== bodyHash)) throw new Error("purchase context cannot be reused for another HTTP request");
146
+ context.method = method;
147
+ context.url = request.url;
148
+ context.bodySha256 = bodyHash;
149
+ const init = { ...options.init, method, headers: new Headers(request.headers), body: ["GET", "HEAD"].includes(method) ? void 0 : bytes };
150
+ let receipt = parseFacilitatorReceipt(context.receipt);
151
+ let transportError;
152
+ const persistCopy = async () => {
153
+ await persist(JSON.parse(JSON.stringify(context)));
154
+ };
155
+ const send = async (input, sendOptions) => {
156
+ const headers = new Headers(sendOptions?.headers);
157
+ const paid = headers.get("X-PAYMENT") || headers.get("PAYMENT-SIGNATURE");
158
+ if (paid) {
159
+ const paymentHeaders = {};
160
+ for (const name of ["X-PAYMENT", "PAYMENT-SIGNATURE"]) {
161
+ const value = headers.get(name);
162
+ if (value) paymentHeaders[name] = value;
163
+ }
164
+ if (context.paymentHeaders && JSON.stringify(context.paymentHeaders) !== JSON.stringify(paymentHeaders)) throw new Error("refusing a new authorization for an existing purchase");
165
+ context.paymentHeaders = paymentHeaders;
166
+ headers.set("X-UVD-Purchase", purchaseContextHeader(context));
167
+ await persistCopy();
168
+ }
169
+ try {
170
+ return await transport(input, { ...sendOptions, headers });
171
+ } catch (error) {
172
+ transportError = error;
173
+ throw error;
174
+ }
175
+ };
176
+ try {
177
+ let response;
178
+ if (context.paymentHeaders) {
179
+ const headers = new Headers(init.headers);
180
+ for (const [name, value] of Object.entries(context.paymentHeaders)) headers.set(name, value);
181
+ response = await send(request.url, { ...init, headers });
182
+ } else {
183
+ response = await fetchClient(request.url, { ...options, method, init, fetchImpl: send });
184
+ }
185
+ const incoming = receiptFromResponse(response);
186
+ if (incoming) {
187
+ if (incoming.issuer !== issuer || Object.entries({ purchaseId: context.purchaseId, method, url: context.url, bodySha256: bodyHash }).some(([key, value]) => incoming.request[key] !== value)) throw new Error("receipt does not bind this purchase");
188
+ if (receipt?.operation === "settle" && (incoming.receiptId !== receipt.receiptId || incoming.revision < receipt.revision)) throw new Error("receipt revision conflict");
189
+ if (trustedKeys && !verifyFacilitatorReceipt(incoming, trustedKeys, issuer)) throw new Error("receipt signature verification failed");
190
+ receipt = incoming;
191
+ context.receipt = incoming;
192
+ await persistCopy();
193
+ }
194
+ const proofVerified = !!(receipt && trustedKeys && verifyFacilitatorReceipt(receipt, trustedKeys, issuer));
195
+ if (receipt && trustedKeys && !proofVerified) throw new Error("receipt signature verification failed");
196
+ return { response, receipt, paymentState: receipt ? receipt.status : context.paymentHeaders ? "unknown" : "not_required", context, proofVerified };
197
+ } catch (error) {
198
+ if (!transportError) throw error;
199
+ return { response: null, receipt, paymentState: "unknown", context, proofVerified: false, error };
200
+ }
201
+ }
202
+ async function getFacilitatorReceipt(receiptId, context, options = {}) {
203
+ if (!/^[0-9a-f-]{36}$/.test(receiptId)) throw new Error("invalid receipt ID");
204
+ const issuer = options.issuer || RECEIPT_ISSUER;
205
+ const response = await (options.fetchImpl || globalThis.fetch)(`${issuer}/receipts/${receiptId}`, { headers: { Authorization: `Bearer ${context.accessToken}` } });
206
+ if (!response.ok) throw new Error(`receipt lookup failed: ${response.status}`);
207
+ const receipt = parseFacilitatorReceipt((await response.json()).receipt);
208
+ if (!receipt || receipt.issuer !== issuer || receipt.purchaseId !== context.purchaseId) throw new Error("receipt lookup mismatch");
209
+ return receipt;
210
+ }
9
211
 
10
212
  // src/utils/base64.ts
11
213
  function decodeBase64Utf8(encoded) {
@@ -807,7 +1009,8 @@ var SUPPORTED_CHAINS = {
807
1009
  // Pinned by src/arc-testnet.test.ts.
808
1010
  //
809
1011
  // Mainnet (5042) and testnet (5042002) were verified independently against
810
- // their official RPCs on 2026-09-16. EURC domains checked on 2026-09-17; live payments pending.
1012
+ // their official RPCs on 2026-09-16. EURC domains checked on 2026-09-17; funded EURC payments settled on Arc mainnet on
1013
+ // 2026-09-22 (x402 v1/v2, docs/networks/arc.md); testnet pending.
811
1014
  arc: {
812
1015
  chainId: 5042,
813
1016
  chainIdHex: "0x13b2",
@@ -1522,6 +1725,9 @@ var REPLAYABLE_LEASE_REASONS = [
1522
1725
  ];
1523
1726
  var AMBIGUOUS_LEASE_REASONS = ["forward_failed"];
1524
1727
  var SETTLEMENT_UNCONFIRMED = "settlement_unconfirmed";
1728
+ var AUTHORIZATION_ALREADY_SETTLED = "authorization_already_settled";
1729
+ var AUTHORIZATION_IN_FLIGHT = "authorization_in_flight";
1730
+ var RECEIPT_REQUEST_CONFLICT = "receipt_request_conflict";
1525
1731
  var MAX_RETRY_AFTER_SECONDS = 15;
1526
1732
  var DEFAULT_RETRY_AFTER_SECONDS = 5;
1527
1733
  var DEFAULT_FACILITATOR_RETRIES = 2;
@@ -1582,6 +1788,12 @@ function isDeclaredUnretryable(parsed) {
1582
1788
  function isSettlementUnconfirmed(failure) {
1583
1789
  return failure.errorCode === SETTLEMENT_UNCONFIRMED;
1584
1790
  }
1791
+ function isAuthorizationAlreadyUsed(failure) {
1792
+ return failure.errorCode === AUTHORIZATION_ALREADY_SETTLED || failure.errorCode === RECEIPT_REQUEST_CONFLICT;
1793
+ }
1794
+ function isAuthorizationInFlight(failure) {
1795
+ return failure.errorCode === AUTHORIZATION_IN_FLIGHT;
1796
+ }
1585
1797
  async function readFacilitatorError(response) {
1586
1798
  let body = "";
1587
1799
  try {
@@ -1593,7 +1805,8 @@ async function readFacilitatorError(response) {
1593
1805
  const parsed = parseFacilitatorErrorBody(body);
1594
1806
  const reason = parsed.reason;
1595
1807
  const transportRetryable = status === 429 || status === 502 || status === 503 || status === 504;
1596
- const retryable = transportRetryable && !isDeclaredUnretryable(parsed);
1808
+ const inFlight = status === 409 && parsed.errorCode === AUTHORIZATION_IN_FLIGHT;
1809
+ const retryable = inFlight || transportRetryable && !isDeclaredUnretryable(parsed);
1597
1810
  const retryAfterSeconds = retryable ? parseRetryAfterSeconds(response) ?? DEFAULT_RETRY_AFTER_SECONDS : void 0;
1598
1811
  const safeToReplay = retryable && (status === 429 || status === 503 && isReplayableLeaseReason(reason));
1599
1812
  return {
@@ -1851,7 +2064,7 @@ function buildSettleRequestForVersion(paymentHeader, requirements, version) {
1851
2064
  return buildSettleRequest(paymentHeader, requirements);
1852
2065
  }
1853
2066
  var X402_CORS_HEADERS = {
1854
- "Access-Control-Allow-Headers": "Content-Type, X-PAYMENT, PAYMENT-SIGNATURE, Authorization",
2067
+ "Access-Control-Allow-Headers": "Content-Type, X-PAYMENT, PAYMENT-SIGNATURE, X-UVD-Purchase, Authorization",
1855
2068
  "Access-Control-Expose-Headers": "X-PAYMENT-RESPONSE, PAYMENT-RESPONSE, PAYMENT-REQUIRED",
1856
2069
  "Access-Control-Allow-Methods": "GET, POST, OPTIONS"
1857
2070
  };
@@ -1860,7 +2073,8 @@ var X402_HEADER_NAMES = [
1860
2073
  "PAYMENT-SIGNATURE",
1861
2074
  "X-PAYMENT-RESPONSE",
1862
2075
  "PAYMENT-RESPONSE",
1863
- "PAYMENT-REQUIRED"
2076
+ "PAYMENT-REQUIRED",
2077
+ "X-UVD-Purchase"
1864
2078
  ];
1865
2079
  function getCorsHeaders(origin = "*") {
1866
2080
  return {
@@ -1868,6 +2082,78 @@ function getCorsHeaders(origin = "*") {
1868
2082
  ...X402_CORS_HEADERS
1869
2083
  };
1870
2084
  }
2085
+ var IDEMPOTENCY_KEY_HEADER = "Idempotency-Key";
2086
+ var IDEMPOTENT_REPLAYED_HEADER = "Idempotent-Replayed";
2087
+ function createIdempotencyKey() {
2088
+ return `x402-${bytesToHex(randomBytes(32))}`;
2089
+ }
2090
+ function checkIdempotencyKey(key) {
2091
+ if (typeof key !== "string" || !/^[\x21-\x7e]{1,255}$/.test(key) || key.startsWith("receipt:")) {
2092
+ throw new Error('idempotencyKey must be 1-255 visible ASCII characters and must not start with "receipt:"');
2093
+ }
2094
+ return key;
2095
+ }
2096
+ function isReplayed(response) {
2097
+ try {
2098
+ return response?.headers?.get?.(IDEMPOTENT_REPLAYED_HEADER)?.trim().toLowerCase() === "true";
2099
+ } catch {
2100
+ return false;
2101
+ }
2102
+ }
2103
+ function refuseUnboundReplay(result) {
2104
+ if (!result.replayed) return result;
2105
+ const pending = result.receipt?.status === "pending" || result.receipt?.status === "unknown" || result.errorCode === "settlement_in_progress";
2106
+ if (!result.success && !pending) return result;
2107
+ const {
2108
+ transactionHash: _tx,
2109
+ proofOfPayment: _proof,
2110
+ paymentId: _id,
2111
+ transaction: _t,
2112
+ retryAfterSeconds,
2113
+ ...rest
2114
+ } = result;
2115
+ if (result.success) {
2116
+ return {
2117
+ ...rest,
2118
+ success: false,
2119
+ error: AUTHORIZATION_ALREADY_SETTLED,
2120
+ errorCode: AUTHORIZATION_ALREADY_SETTLED,
2121
+ retryable: false,
2122
+ safeToReplay: false
2123
+ };
2124
+ }
2125
+ return {
2126
+ ...rest,
2127
+ success: false,
2128
+ error: AUTHORIZATION_IN_FLIGHT,
2129
+ errorCode: AUTHORIZATION_IN_FLIGHT,
2130
+ retryable: true,
2131
+ safeToReplay: false,
2132
+ retryAfterSeconds: retryAfterSeconds ?? DEFAULT_RETRY_AFTER_SECONDS
2133
+ };
2134
+ }
2135
+ function facilitatorHeaders(idempotencyKey, receiptContext) {
2136
+ return {
2137
+ "Content-Type": "application/json",
2138
+ [IDEMPOTENCY_KEY_HEADER]: idempotencyKey,
2139
+ ...receiptContext ? { "X-UVD-Purchase": receiptContext } : {}
2140
+ };
2141
+ }
2142
+ function admittedVerdict(result) {
2143
+ if (result.isValid !== false) return {};
2144
+ if (result.invalidReason === AUTHORIZATION_IN_FLIGHT) {
2145
+ return {
2146
+ errorCode: AUTHORIZATION_IN_FLIGHT,
2147
+ retryable: true,
2148
+ safeToReplay: false,
2149
+ retryAfterSeconds: DEFAULT_RETRY_AFTER_SECONDS
2150
+ };
2151
+ }
2152
+ if (result.invalidReason === AUTHORIZATION_ALREADY_SETTLED) {
2153
+ return { errorCode: AUTHORIZATION_ALREADY_SETTLED, retryable: false, safeToReplay: false };
2154
+ }
2155
+ return {};
2156
+ }
1871
2157
  var FacilitatorClient = class {
1872
2158
  baseUrl;
1873
2159
  timeout;
@@ -1900,11 +2186,19 @@ var FacilitatorClient = class {
1900
2186
  *
1901
2187
  * Call this before providing the paid resource to validate the payment.
1902
2188
  *
2189
+ * An authorization the facilitator already admitted for another request
2190
+ * comes back invalid with `errorCode` {@link AUTHORIZATION_ALREADY_SETTLED}
2191
+ * (do not serve, do not ask for a new signature) or
2192
+ * {@link AUTHORIZATION_IN_FLIGHT} (`retryable`: the same request learns the
2193
+ * verdict later). Neither is a rejected payment: never answer them with 402.
2194
+ *
1903
2195
  * @param paymentHeader - Parsed x402 payment header
1904
2196
  * @param requirements - Payment requirements
2197
+ * @param options - Purchase context and the payment's `idempotencyKey`
1905
2198
  * @returns Verification result
1906
2199
  */
1907
- async verify(paymentHeader, requirements) {
2200
+ async verify(paymentHeader, requirements, options = {}) {
2201
+ const idempotencyKey = checkIdempotencyKey(options.idempotencyKey ?? createIdempotencyKey());
1908
2202
  const body = buildVerifyRequestForVersion(
1909
2203
  paymentHeader,
1910
2204
  requirements,
@@ -1915,7 +2209,7 @@ var FacilitatorClient = class {
1915
2209
  `${this.baseUrl}/verify`,
1916
2210
  {
1917
2211
  method: "POST",
1918
- headers: { "Content-Type": "application/json" },
2212
+ headers: facilitatorHeaders(idempotencyKey, options.receiptContext),
1919
2213
  body: JSON.stringify(body)
1920
2214
  },
1921
2215
  { timeoutMs: this.timeout, retries: this.retries }
@@ -1924,17 +2218,21 @@ var FacilitatorClient = class {
1924
2218
  return {
1925
2219
  isValid: false,
1926
2220
  invalidReason: error.error,
1927
- ...failureFields(error)
2221
+ ...failureFields(error),
2222
+ receipt: receiptFromErrorBody(error.body),
2223
+ idempotencyKey
1928
2224
  };
1929
2225
  }
1930
- return await response.json();
2226
+ const result = await response.json();
2227
+ return { ...result, ...admittedVerdict(result), receipt: parseFacilitatorReceipt(result.receipt), idempotencyKey };
1931
2228
  } catch (error) {
1932
2229
  return {
1933
2230
  isValid: false,
1934
2231
  invalidReason: error instanceof Error ? error.message : "Unknown error",
1935
2232
  retryable: true,
1936
2233
  safeToReplay: false,
1937
- retryAfterSeconds: DEFAULT_RETRY_AFTER_SECONDS
2234
+ retryAfterSeconds: DEFAULT_RETRY_AFTER_SECONDS,
2235
+ idempotencyKey
1938
2236
  };
1939
2237
  }
1940
2238
  }
@@ -1943,11 +2241,23 @@ var FacilitatorClient = class {
1943
2241
  *
1944
2242
  * Call this after providing the paid resource to execute the on-chain transfer.
1945
2243
  *
2244
+ * Send the `idempotencyKey` the payment was verified with, and the same one
2245
+ * on any retry: it is the binding that earns the original answer back after
2246
+ * a lost response (`replayed: true`). Without it, or with another one, an
2247
+ * authorization already admitted comes back `409`
2248
+ * {@link AUTHORIZATION_ALREADY_SETTLED}, {@link AUTHORIZATION_IN_FLIGHT} or
2249
+ * {@link RECEIPT_REQUEST_CONFLICT} -- the X-PAYMENT was used; do not serve it
2250
+ * again. With no key and no context the call uses a fresh key, so a replay
2251
+ * it receives is refused the same way.
2252
+ *
1946
2253
  * @param paymentHeader - Parsed x402 payment header
1947
2254
  * @param requirements - Payment requirements
2255
+ * @param options - Purchase context and the payment's `idempotencyKey`
1948
2256
  * @returns Settlement result with transaction hash
1949
2257
  */
1950
- async settle(paymentHeader, requirements) {
2258
+ async settle(paymentHeader, requirements, options = {}) {
2259
+ const unbound = options.idempotencyKey === void 0 && !options.receiptContext;
2260
+ const idempotencyKey = checkIdempotencyKey(options.idempotencyKey ?? createIdempotencyKey());
1951
2261
  const body = buildSettleRequestForVersion(
1952
2262
  paymentHeader,
1953
2263
  requirements,
@@ -1959,7 +2269,8 @@ var FacilitatorClient = class {
1959
2269
  `${this.baseUrl}/settle`,
1960
2270
  {
1961
2271
  method: "POST",
1962
- headers: { "Content-Type": "application/json" },
2272
+ // The same init, key included, goes out on every automatic retry.
2273
+ headers: facilitatorHeaders(idempotencyKey, options.receiptContext),
1963
2274
  body: JSON.stringify(body)
1964
2275
  },
1965
2276
  { timeoutMs: settleTimeout, retries: this.retries }
@@ -1968,7 +2279,9 @@ var FacilitatorClient = class {
1968
2279
  return {
1969
2280
  success: false,
1970
2281
  error: error.error,
1971
- ...failureFields(error)
2282
+ ...failureFields(error),
2283
+ receipt: receiptFromErrorBody(error.body),
2284
+ idempotencyKey
1972
2285
  };
1973
2286
  }
1974
2287
  const result = await response.json();
@@ -1978,7 +2291,7 @@ var FacilitatorClient = class {
1978
2291
  "[x402] settle reported success but carried no transaction hash under transaction/transactionHash/transaction_hash \u2014 treat delivery as unconfirmed"
1979
2292
  );
1980
2293
  }
1981
- return {
2294
+ const settled = {
1982
2295
  // Read the facilitator's verdict instead of asserting one.
1983
2296
  //
1984
2297
  // This was the literal `true`, so a settle was reported successful
@@ -2006,15 +2319,24 @@ var FacilitatorClient = class {
2006
2319
  // facilitator returns it, and this method threw it away — so a seller
2007
2320
  // using the SDK end to end could only ever produce provisional anchors.
2008
2321
  proofOfPayment: result.proofOfPayment ?? result.proof_of_payment,
2009
- payer: result.payer
2322
+ payer: result.payer,
2323
+ receipt: parseFacilitatorReceipt(result.receipt),
2324
+ paymentId: result.paymentId,
2325
+ ...result.receipt?.status === "unknown" || result.receipt?.status === "pending" ? { retryable: true, safeToReplay: false } : {},
2326
+ // `202 settlement_in_progress` and friends: a 2xx that names its state.
2327
+ ...!result.success && typeof result.error === "string" && result.error ? { errorCode: result.error } : {},
2328
+ ...isReplayed(response) ? { replayed: true } : {},
2329
+ idempotencyKey
2010
2330
  };
2331
+ return unbound ? refuseUnboundReplay(settled) : settled;
2011
2332
  } catch (error) {
2012
2333
  return {
2013
2334
  success: false,
2014
2335
  error: error instanceof Error ? error.message : "Unknown error",
2015
2336
  retryable: true,
2016
2337
  safeToReplay: false,
2017
- retryAfterSeconds: DEFAULT_RETRY_AFTER_SECONDS
2338
+ retryAfterSeconds: DEFAULT_RETRY_AFTER_SECONDS,
2339
+ idempotencyKey
2018
2340
  };
2019
2341
  }
2020
2342
  }
@@ -2024,27 +2346,41 @@ var FacilitatorClient = class {
2024
2346
  * Convenience method that verifies first, then settles if valid.
2025
2347
  * Use this for simple payment flows where you don't need custom logic between verify and settle.
2026
2348
  *
2349
+ * Both steps carry ONE `Idempotency-Key` (`options.idempotencyKey`, or a
2350
+ * fresh one reported back as `idempotencyKey`). With a fresh key and no
2351
+ * purchase context, a replay of an earlier settle is not this purchase and
2352
+ * comes back `settled: false` with `errorCode`
2353
+ * {@link AUTHORIZATION_ALREADY_SETTLED}.
2354
+ *
2027
2355
  * @param paymentHeader - Parsed x402 payment header
2028
2356
  * @param requirements - Payment requirements
2357
+ * @param options - Purchase context and the payment's `idempotencyKey`
2029
2358
  * @returns Combined result with verify and settle status
2030
2359
  */
2031
- async verifyAndSettle(paymentHeader, requirements) {
2032
- const verifyResult = await this.verify(paymentHeader, requirements);
2360
+ async verifyAndSettle(paymentHeader, requirements, options = {}) {
2361
+ const unbound = options.idempotencyKey === void 0 && !options.receiptContext;
2362
+ const binding = { ...options, idempotencyKey: checkIdempotencyKey(options.idempotencyKey ?? createIdempotencyKey()) };
2363
+ const { idempotencyKey } = binding;
2364
+ const verifyResult = await this.verify(paymentHeader, requirements, binding);
2033
2365
  if (!verifyResult.isValid) {
2034
2366
  return {
2035
2367
  verified: false,
2036
2368
  settled: false,
2037
2369
  error: verifyResult.invalidReason,
2038
- ...carryFailureFields(verifyResult)
2370
+ ...carryFailureFields(verifyResult),
2371
+ idempotencyKey
2039
2372
  };
2040
2373
  }
2041
- const settleResult = await this.settle(paymentHeader, requirements);
2374
+ const answered = await this.settle(paymentHeader, requirements, binding);
2375
+ const settleResult = unbound ? refuseUnboundReplay(answered) : answered;
2042
2376
  return {
2043
2377
  verified: true,
2044
2378
  settled: settleResult.success,
2045
2379
  transactionHash: settleResult.transactionHash,
2046
2380
  error: settleResult.error,
2047
- ...carryFailureFields(settleResult)
2381
+ ...carryFailureFields(settleResult),
2382
+ ...settleResult.replayed ? { replayed: true } : {},
2383
+ idempotencyKey
2048
2384
  };
2049
2385
  }
2050
2386
  /**
@@ -2432,20 +2768,51 @@ async function resolvePaymentRequirement(payment, requirements, resolver) {
2432
2768
  }
2433
2769
  return { requirement: matches[0] };
2434
2770
  }
2435
- function createVerifiedPaymentState(client, payment, requirements, verifyResult) {
2771
+ function createVerifiedPaymentState(client, payment, requirements, verifyResult, binding, onSettled) {
2436
2772
  let settlePromise = null;
2437
2773
  return {
2438
2774
  payment,
2439
2775
  requirements,
2440
2776
  verifyResult,
2777
+ idempotencyKey: binding.idempotencyKey,
2441
2778
  settle: () => {
2442
2779
  if (!settlePromise) {
2443
- settlePromise = client.settle(payment, requirements);
2780
+ settlePromise = client.settle(payment, requirements, binding).then((answer) => {
2781
+ const result = binding.receiptContext ? answer : refuseUnboundReplay(answer);
2782
+ try {
2783
+ onSettled?.(result);
2784
+ } catch (error) {
2785
+ console.warn("[x402] settled, but the payment response headers could not be attached:", error);
2786
+ }
2787
+ return result;
2788
+ });
2444
2789
  }
2445
2790
  return settlePromise;
2446
2791
  }
2447
2792
  };
2448
2793
  }
2794
+ function propagatedResult(result) {
2795
+ const { idempotencyKey: _key, ...propagated } = result;
2796
+ return propagated;
2797
+ }
2798
+ function buildPaymentConflictResponse(failure) {
2799
+ if (isAuthorizationInFlight(failure)) {
2800
+ const { headers, body } = buildUnavailableResponse("Payment authorization in flight", failure);
2801
+ return { status: 503, headers, body: { ...body, reason: AUTHORIZATION_IN_FLIGHT } };
2802
+ }
2803
+ const used = isAuthorizationAlreadyUsed(failure);
2804
+ if (!used && failure.status !== 409) return null;
2805
+ return {
2806
+ status: 409,
2807
+ headers: {},
2808
+ body: {
2809
+ error: used ? "Payment authorization already used" : "Payment request conflict",
2810
+ reason: failure.errorCode ?? failure.invalidReason ?? failure.error,
2811
+ retryable: false,
2812
+ safeToReplay: false
2813
+ }
2814
+ };
2815
+ }
2449
2816
  function buildUnavailableResponse(message, failure) {
2450
2817
  const seconds = Math.max(1, Math.ceil(failure.retryAfterSeconds ?? DEFAULT_RETRY_AFTER_SECONDS));
2451
2818
  return {
@@ -2462,14 +2829,25 @@ function buildUnavailableResponse(message, failure) {
2462
2829
  };
2463
2830
  }
2464
2831
  function respondUnavailable(res, message, failure) {
2465
- const { status, headers, body } = buildUnavailableResponse(message, failure);
2832
+ respondExpress(res, buildUnavailableResponse(message, failure));
2833
+ }
2834
+ function respondExpress(res, { status, headers, body }) {
2466
2835
  const staged = res.status(status);
2467
- if (typeof staged.set === "function") {
2836
+ if (Object.keys(headers).length > 0 && typeof staged.set === "function") {
2468
2837
  staged.set(headers).json(body);
2469
2838
  return;
2470
2839
  }
2471
2840
  staged.json(body);
2472
2841
  }
2842
+ function setExpressPaymentHeaders(res, result) {
2843
+ if (!result.receipt || !res.set || res.headersSent) return;
2844
+ const current = (name) => {
2845
+ const value = res.getHeader ? res.getHeader(name) : res.get?.(name);
2846
+ if (value === void 0 || value === null) return void 0;
2847
+ return Array.isArray(value) ? value.join(", ") : String(value);
2848
+ };
2849
+ res.set(mergePaymentResponseHeaders(propagatedResult(result), current));
2850
+ }
2473
2851
  function createPaymentMiddleware(getRequirements, options = {}) {
2474
2852
  const client = new FacilitatorClient({
2475
2853
  baseUrl: options.facilitatorUrl || options.baseUrl,
@@ -2487,8 +2865,28 @@ function createPaymentMiddleware(getRequirements, options = {}) {
2487
2865
  }
2488
2866
  const reqOptions = getRequirements(req);
2489
2867
  const requirements = buildPaymentRequirements(reqOptions);
2490
- const verifyResult = await client.verify(payment, requirements);
2868
+ let receiptContext;
2869
+ try {
2870
+ const entry = Object.entries(req.headers).find(([name]) => name.toLowerCase() === "x-uvd-purchase")?.[1];
2871
+ if (entry !== void 0) {
2872
+ if (typeof entry !== "string" || !req.method || !["GET", "HEAD"].includes(req.method.toUpperCase()) && !req.rawBody) throw new Error("receipt context requires method and exact raw body");
2873
+ const actualUrl = new URL(req.originalUrl || req.url || reqOptions.resource, reqOptions.resource).toString();
2874
+ receiptContext = validatePurchaseContext(entry, req.method, actualUrl, req.rawBody || new Uint8Array());
2875
+ requirements.resource = actualUrl;
2876
+ }
2877
+ } catch {
2878
+ res.status(400).json({ error: "receipt_context_mismatch" });
2879
+ return;
2880
+ }
2881
+ const binding = { idempotencyKey: createIdempotencyKey(), receiptContext };
2882
+ const verifyResult = await client.verify(payment, requirements, binding);
2883
+ setExpressPaymentHeaders(res, verifyResult);
2491
2884
  if (!verifyResult.isValid) {
2885
+ const conflict = buildPaymentConflictResponse(verifyResult);
2886
+ if (conflict) {
2887
+ respondExpress(res, conflict);
2888
+ return;
2889
+ }
2492
2890
  if (verifyResult.retryable) {
2493
2891
  respondUnavailable(res, "Payment verification unavailable", verifyResult);
2494
2892
  return;
@@ -2499,10 +2897,22 @@ function createPaymentMiddleware(getRequirements, options = {}) {
2499
2897
  });
2500
2898
  return;
2501
2899
  }
2502
- req.x402 = createVerifiedPaymentState(client, payment, requirements, verifyResult);
2900
+ req.x402 = createVerifiedPaymentState(
2901
+ client,
2902
+ payment,
2903
+ requirements,
2904
+ verifyResult,
2905
+ binding,
2906
+ (result) => setExpressPaymentHeaders(res, result)
2907
+ );
2503
2908
  if (settlementStrategy === "before-handler") {
2504
2909
  const settleResult = await req.x402.settle();
2505
2910
  if (!settleResult.success) {
2911
+ const conflict = buildPaymentConflictResponse(settleResult);
2912
+ if (conflict) {
2913
+ respondExpress(res, conflict);
2914
+ return;
2915
+ }
2506
2916
  if (settleResult.retryable) {
2507
2917
  respondUnavailable(res, "Payment settlement unavailable", settleResult);
2508
2918
  return;
@@ -2525,12 +2935,21 @@ function settlementFailureBody(failure, fallbackReason) {
2525
2935
  };
2526
2936
  }
2527
2937
  function honoUnavailable(c, message, failure) {
2528
- const { status, headers, body } = buildUnavailableResponse(message, failure);
2938
+ return respondHono(c, buildUnavailableResponse(message, failure));
2939
+ }
2940
+ function respondHono(c, { status, headers, body }) {
2529
2941
  for (const [name, value] of Object.entries(headers)) {
2530
2942
  c.header?.(name, value);
2531
2943
  }
2532
2944
  return c.json(body, status);
2533
2945
  }
2946
+ function setHonoPaymentHeaders(c, result) {
2947
+ if (!result.receipt || !c.header || c.finalized) return;
2948
+ const current = (name) => c.res?.headers.get(name) ?? void 0;
2949
+ for (const [name, value] of Object.entries(mergePaymentResponseHeaders(propagatedResult(result), current))) {
2950
+ c.header(name, value);
2951
+ }
2952
+ }
2534
2953
  function createHonoMiddleware(options) {
2535
2954
  const client = new FacilitatorClient({
2536
2955
  baseUrl: options.facilitatorUrl || options.baseUrl,
@@ -2542,7 +2961,7 @@ function createHonoMiddleware(options) {
2542
2961
  throw new Error("At least one accept entry is required");
2543
2962
  }
2544
2963
  return async (c, next) => {
2545
- const paymentHeader = c.req.header("X-PAYMENT") || c.req.header("x-payment");
2964
+ const paymentHeader = c.req.header("PAYMENT-SIGNATURE") || c.req.header("X-PAYMENT") || c.req.header("x-payment");
2546
2965
  const advertisedVersion = resolveAdvertisedVersion(options.accepts, options.x402Version);
2547
2966
  const advertisedRequirements = options.accepts.map(
2548
2967
  (accept) => buildRequirementFromAcceptance(accept, c.req.url, advertisedVersion)
@@ -2573,8 +2992,24 @@ function createHonoMiddleware(options) {
2573
2992
  reason
2574
2993
  }, 402);
2575
2994
  }
2576
- const verifyResult = await client.verify(parsed, requirement);
2995
+ let receiptContext;
2996
+ try {
2997
+ const header = c.req.header("X-UVD-Purchase");
2998
+ if (header) {
2999
+ const method = c.req.method || c.req.raw?.method;
3000
+ if (!method || !["GET", "HEAD"].includes(method) && !c.req.raw) throw new Error("raw request required");
3001
+ const bytes = c.req.raw ? new Uint8Array(await c.req.raw.clone().arrayBuffer()) : new Uint8Array();
3002
+ receiptContext = validatePurchaseContext(header, method, c.req.url, bytes);
3003
+ }
3004
+ } catch {
3005
+ return c.json({ error: "receipt_context_mismatch" }, 400);
3006
+ }
3007
+ const binding = { idempotencyKey: createIdempotencyKey(), receiptContext };
3008
+ const verifyResult = await client.verify(parsed, requirement, binding);
3009
+ setHonoPaymentHeaders(c, verifyResult);
2577
3010
  if (!verifyResult.isValid) {
3011
+ const conflict = buildPaymentConflictResponse(verifyResult);
3012
+ if (conflict) return respondHono(c, conflict);
2578
3013
  if (verifyResult.retryable) {
2579
3014
  return honoUnavailable(c, "Payment verification unavailable", verifyResult);
2580
3015
  }
@@ -2583,11 +3018,20 @@ function createHonoMiddleware(options) {
2583
3018
  reason: verifyResult.invalidReason
2584
3019
  }, 402);
2585
3020
  }
2586
- const verifiedPayment = createVerifiedPaymentState(client, parsed, requirement, verifyResult);
3021
+ const verifiedPayment = createVerifiedPaymentState(
3022
+ client,
3023
+ parsed,
3024
+ requirement,
3025
+ verifyResult,
3026
+ binding,
3027
+ (result) => setHonoPaymentHeaders(c, result)
3028
+ );
2587
3029
  c.set?.("x402", verifiedPayment);
2588
3030
  if (settlementStrategy === "before-handler") {
2589
3031
  const settleResult = await verifiedPayment.settle();
2590
3032
  if (!settleResult.success) {
3033
+ const conflict = buildPaymentConflictResponse(settleResult);
3034
+ if (conflict) return respondHono(c, conflict);
2591
3035
  if (settleResult.retryable) {
2592
3036
  return honoUnavailable(c, "Payment settlement unavailable", settleResult);
2593
3037
  }
@@ -5478,6 +5922,6 @@ var AdvancedEscrowClient = class {
5478
5922
  }
5479
5923
  };
5480
5924
 
5481
- export { AMBIGUOUS_LEASE_REASONS, AdvancedEscrowClient, BASE_MAINNET_CONTRACTS, BazaarClient, DEFAULT_FACILITATOR_RETRIES, DEFAULT_RETRY_AFTER_SECONDS, DEPOSIT_LIMIT_USDC, ERC8004_CONTRACTS, ERC8004_EXTENSION_ID, ESCROW_CONTRACTS, ESCROW_TIMEOUT_MS, Erc8004Client, Erc8004LookupError, EscrowClient, FacilitatorClient, HEALTH_FILTERS, MAX_RETRY_AFTER_SECONDS, MAX_SEARCH_LEN, OPERATOR_ABI, OPERATOR_ABI_CREATE3, PAYMENT_INFO_TYPEHASH, RELAYED_FEEDBACK_NETWORKS, REPLAYABLE_LEASE_REASONS, RegistrationPendingError, SETTLEMENT_UNCONFIRMED, SOLANA_FEEDBACK_NETWORKS, TIER_FILTERS, TIER_TIMINGS, USDC_DOMAIN_NAME, WRITER_LEASE_REASONS, X402_CORS_HEADERS, X402_HEADER_NAMES, ZERO_ADDRESS, buildErc8004PaymentRequirements, buildPaymentRequirements, buildSettleRequest, buildSettleRequestForVersion, buildSettleRequestV2, buildUnavailableResponse, buildVerifyRequest, buildVerifyRequestForVersion, buildVerifyRequestV2, canRefundEscrow, canReleaseEscrow, carryFailureFields, create402Response, createHonoMiddleware, createPaymentMiddleware, epochToDate, escrowTimeRemaining, extractPaymentFromHeaders, facilitatorFetch, getCorsHeaders, getEscrowContractsByChainId, getEscrowSupportedChainIds, isAlive, isAmbiguousLeaseReason, isEscrowExpired, isEscrowSupportedOnChain, isRegisterJobTerminal, isReplayableLeaseReason, isSettlementUnconfirmed, parseFacilitatorErrorBody, parsePaymentHeader, parseRetryAfterSeconds, readFacilitatorError, resolveEnvelopeVersion, supportsRelayedFeedback, supportsSolanaFeedback, toPaymentRequirementsV2, toResourceInfoV2, wireNetwork };
5925
+ export { AMBIGUOUS_LEASE_REASONS, AUTHORIZATION_ALREADY_SETTLED, AUTHORIZATION_IN_FLIGHT, AdvancedEscrowClient, BASE_MAINNET_CONTRACTS, BazaarClient, DEFAULT_FACILITATOR_RETRIES, DEFAULT_RETRY_AFTER_SECONDS, DEPOSIT_LIMIT_USDC, ERC8004_CONTRACTS, ERC8004_EXTENSION_ID, ESCROW_CONTRACTS, ESCROW_TIMEOUT_MS, Erc8004Client, Erc8004LookupError, EscrowClient, FacilitatorClient, HEALTH_FILTERS, IDEMPOTENCY_KEY_HEADER, IDEMPOTENT_REPLAYED_HEADER, MAX_RETRY_AFTER_SECONDS, MAX_SEARCH_LEN, OPERATOR_ABI, OPERATOR_ABI_CREATE3, PAYMENT_INFO_TYPEHASH, RECEIPT_ISSUER, RECEIPT_REQUEST_CONFLICT, RELAYED_FEEDBACK_NETWORKS, REPLAYABLE_LEASE_REASONS, RegistrationPendingError, SETTLEMENT_UNCONFIRMED, SOLANA_FEEDBACK_NETWORKS, TIER_FILTERS, TIER_TIMINGS, USDC_DOMAIN_NAME, WRITER_LEASE_REASONS, X402_CORS_HEADERS, X402_HEADER_NAMES, ZERO_ADDRESS, buildErc8004PaymentRequirements, buildPaymentConflictResponse, buildPaymentRequirements, buildSettleRequest, buildSettleRequestForVersion, buildSettleRequestV2, buildUnavailableResponse, buildVerifyRequest, buildVerifyRequestForVersion, buildVerifyRequestV2, canRefundEscrow, canReleaseEscrow, canonicalReceiptJson, carryFailureFields, create402Response, createHonoMiddleware, createIdempotencyKey, createPaymentMiddleware, createPurchaseContext, epochToDate, escrowTimeRemaining, extractPaymentFromHeaders, facilitatorFetch, fetchWithReceipt, getCorsHeaders, getEscrowContractsByChainId, getEscrowSupportedChainIds, getFacilitatorReceipt, isAlive, isAmbiguousLeaseReason, isAuthorizationAlreadyUsed, isAuthorizationInFlight, isEscrowExpired, isEscrowSupportedOnChain, isRegisterJobTerminal, isReplayableLeaseReason, isSettlementUnconfirmed, mergeHeaderList, mergePaymentResponseHeaders, parseFacilitatorErrorBody, parseFacilitatorReceipt, parsePaymentHeader, parseRetryAfterSeconds, paymentResponseHeaders, purchaseContextHeader, readFacilitatorError, receiptCommitment, receiptFromErrorBody, receiptFromResponse, resolveEnvelopeVersion, supportsRelayedFeedback, supportsSolanaFeedback, toPaymentRequirementsV2, toResourceInfoV2, validatePurchaseContext, verifyFacilitatorReceipt, wireNetwork };
5482
5926
  //# sourceMappingURL=index.mjs.map
5483
5927
  //# sourceMappingURL=index.mjs.map