@bankofai/x402-core 2.6.0-beta.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 (74) hide show
  1. package/README.md +293 -0
  2. package/dist/cjs/assetRegistry-CL0zA4s0.d.ts +831 -0
  3. package/dist/cjs/assetRegistry-CRVM0KEs.d.ts +831 -0
  4. package/dist/cjs/client/index.d.ts +329 -0
  5. package/dist/cjs/client/index.js +712 -0
  6. package/dist/cjs/client/index.js.map +1 -0
  7. package/dist/cjs/facilitator/index.d.ts +206 -0
  8. package/dist/cjs/facilitator/index.js +625 -0
  9. package/dist/cjs/facilitator/index.js.map +1 -0
  10. package/dist/cjs/http/index.d.ts +51 -0
  11. package/dist/cjs/http/index.js +1178 -0
  12. package/dist/cjs/http/index.js.map +1 -0
  13. package/dist/cjs/index.d.ts +13 -0
  14. package/dist/cjs/index.js +250 -0
  15. package/dist/cjs/index.js.map +1 -0
  16. package/dist/cjs/mechanisms-q7I6xfUE.d.ts +726 -0
  17. package/dist/cjs/schemas/index.d.ts +825 -0
  18. package/dist/cjs/schemas/index.js +212 -0
  19. package/dist/cjs/schemas/index.js.map +1 -0
  20. package/dist/cjs/server/index.d.ts +2 -0
  21. package/dist/cjs/server/index.js +1782 -0
  22. package/dist/cjs/server/index.js.map +1 -0
  23. package/dist/cjs/types/index.d.ts +1 -0
  24. package/dist/cjs/types/index.js +72 -0
  25. package/dist/cjs/types/index.js.map +1 -0
  26. package/dist/cjs/types/v1/index.d.ts +1 -0
  27. package/dist/cjs/types/v1/index.js +19 -0
  28. package/dist/cjs/types/v1/index.js.map +1 -0
  29. package/dist/cjs/utils/index.d.ts +48 -0
  30. package/dist/cjs/utils/index.js +116 -0
  31. package/dist/cjs/utils/index.js.map +1 -0
  32. package/dist/cjs/x402HTTPResourceServer-BFVo1_74.d.ts +433 -0
  33. package/dist/cjs/x402HTTPResourceServer-DaU2yFzy.d.ts +434 -0
  34. package/dist/cjs/x402HTTPResourceServer-DswI2hZQ.d.ts +434 -0
  35. package/dist/esm/assetRegistry-CRVM0KEs.d.mts +831 -0
  36. package/dist/esm/chunk-BJTO5JO5.mjs +11 -0
  37. package/dist/esm/chunk-BJTO5JO5.mjs.map +1 -0
  38. package/dist/esm/chunk-DACUCTGT.mjs +891 -0
  39. package/dist/esm/chunk-DACUCTGT.mjs.map +1 -0
  40. package/dist/esm/chunk-DFUINDLZ.mjs +221 -0
  41. package/dist/esm/chunk-DFUINDLZ.mjs.map +1 -0
  42. package/dist/esm/chunk-HRQUGJ3Y.mjs +45 -0
  43. package/dist/esm/chunk-HRQUGJ3Y.mjs.map +1 -0
  44. package/dist/esm/chunk-TDLQZ6MP.mjs +86 -0
  45. package/dist/esm/chunk-TDLQZ6MP.mjs.map +1 -0
  46. package/dist/esm/client/index.d.mts +329 -0
  47. package/dist/esm/client/index.mjs +330 -0
  48. package/dist/esm/client/index.mjs.map +1 -0
  49. package/dist/esm/facilitator/index.d.mts +206 -0
  50. package/dist/esm/facilitator/index.mjs +398 -0
  51. package/dist/esm/facilitator/index.mjs.map +1 -0
  52. package/dist/esm/http/index.d.mts +51 -0
  53. package/dist/esm/http/index.mjs +29 -0
  54. package/dist/esm/http/index.mjs.map +1 -0
  55. package/dist/esm/index.d.mts +13 -0
  56. package/dist/esm/index.mjs +14 -0
  57. package/dist/esm/index.mjs.map +1 -0
  58. package/dist/esm/schemas/index.d.mts +825 -0
  59. package/dist/esm/schemas/index.mjs +158 -0
  60. package/dist/esm/schemas/index.mjs.map +1 -0
  61. package/dist/esm/server/index.d.mts +2 -0
  62. package/dist/esm/server/index.mjs +712 -0
  63. package/dist/esm/server/index.mjs.map +1 -0
  64. package/dist/esm/types/index.d.mts +1 -0
  65. package/dist/esm/types/index.mjs +10 -0
  66. package/dist/esm/types/index.mjs.map +1 -0
  67. package/dist/esm/types/v1/index.d.mts +1 -0
  68. package/dist/esm/types/v1/index.mjs +1 -0
  69. package/dist/esm/types/v1/index.mjs.map +1 -0
  70. package/dist/esm/utils/index.d.mts +48 -0
  71. package/dist/esm/utils/index.mjs +20 -0
  72. package/dist/esm/utils/index.mjs.map +1 -0
  73. package/dist/esm/x402HTTPResourceServer-B6uf_UDm.d.mts +434 -0
  74. package/package.json +139 -0
@@ -0,0 +1,1178 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/http/index.ts
21
+ var http_exports = {};
22
+ __export(http_exports, {
23
+ HTTPFacilitatorClient: () => HTTPFacilitatorClient,
24
+ RouteConfigurationError: () => RouteConfigurationError,
25
+ decodePaymentRequiredHeader: () => decodePaymentRequiredHeader,
26
+ decodePaymentResponseHeader: () => decodePaymentResponseHeader,
27
+ decodePaymentSignatureHeader: () => decodePaymentSignatureHeader,
28
+ encodePaymentRequiredHeader: () => encodePaymentRequiredHeader,
29
+ encodePaymentResponseHeader: () => encodePaymentResponseHeader,
30
+ encodePaymentSignatureHeader: () => encodePaymentSignatureHeader,
31
+ x402HTTPClient: () => x402HTTPClient,
32
+ x402HTTPResourceServer: () => x402HTTPResourceServer
33
+ });
34
+ module.exports = __toCommonJS(http_exports);
35
+
36
+ // src/utils/index.ts
37
+ var Base64EncodedRegex = /^[A-Za-z0-9+/]*={0,2}$/;
38
+ function safeBase64Encode(data) {
39
+ if (typeof globalThis !== "undefined" && typeof globalThis.btoa === "function") {
40
+ const bytes = new TextEncoder().encode(data);
41
+ const binaryString = Array.from(bytes, (byte) => String.fromCharCode(byte)).join("");
42
+ return globalThis.btoa(binaryString);
43
+ }
44
+ return Buffer.from(data, "utf8").toString("base64");
45
+ }
46
+ function safeBase64Decode(data) {
47
+ if (typeof globalThis !== "undefined" && typeof globalThis.atob === "function") {
48
+ const binaryString = globalThis.atob(data);
49
+ const bytes = new Uint8Array(binaryString.length);
50
+ for (let i = 0; i < binaryString.length; i++) {
51
+ bytes[i] = binaryString.charCodeAt(i);
52
+ }
53
+ const decoder = new TextDecoder("utf-8");
54
+ return decoder.decode(bytes);
55
+ }
56
+ return Buffer.from(data, "base64").toString("utf-8");
57
+ }
58
+
59
+ // src/types/facilitator.ts
60
+ var VerifyError = class extends Error {
61
+ /**
62
+ * Creates a VerifyError from a failed verification response.
63
+ *
64
+ * @param statusCode - HTTP status code from the facilitator
65
+ * @param response - The verify response containing error details
66
+ */
67
+ constructor(statusCode, response) {
68
+ const reason = response.invalidReason || "unknown reason";
69
+ const message = response.invalidMessage;
70
+ super(message ? `${reason}: ${message}` : reason);
71
+ this.name = "VerifyError";
72
+ this.statusCode = statusCode;
73
+ this.invalidReason = response.invalidReason;
74
+ this.invalidMessage = response.invalidMessage;
75
+ this.payer = response.payer;
76
+ }
77
+ };
78
+ var SettleError = class extends Error {
79
+ /**
80
+ * Creates a SettleError from a failed settlement response.
81
+ *
82
+ * @param statusCode - HTTP status code from the facilitator
83
+ * @param response - The settle response containing error details
84
+ */
85
+ constructor(statusCode, response) {
86
+ const reason = response.errorReason || "unknown reason";
87
+ const message = response.errorMessage;
88
+ super(message ? `${reason}: ${message}` : reason);
89
+ this.name = "SettleError";
90
+ this.statusCode = statusCode;
91
+ this.errorReason = response.errorReason;
92
+ this.errorMessage = response.errorMessage;
93
+ this.payer = response.payer;
94
+ this.transaction = response.transaction;
95
+ this.network = response.network;
96
+ }
97
+ };
98
+
99
+ // src/registry/assetRegistry.ts
100
+ var AssetRegistry = class {
101
+ /** Creates a new AssetRegistry pre-populated with built-in token data. */
102
+ constructor() {
103
+ this.assets = /* @__PURE__ */ new Map();
104
+ this.defaults = /* @__PURE__ */ new Map();
105
+ this.registerBuiltins();
106
+ }
107
+ /**
108
+ * Register a single asset for a network.
109
+ *
110
+ * @param network - The network identifier (e.g. "eip155:1")
111
+ * @param symbol - The token symbol (e.g. "USDT")
112
+ * @param info - Asset metadata
113
+ */
114
+ register(network, symbol, info) {
115
+ if (!this.assets.has(network)) {
116
+ this.assets.set(network, /* @__PURE__ */ new Map());
117
+ }
118
+ this.assets.get(network).set(symbol, info);
119
+ }
120
+ /**
121
+ * Batch-register multiple assets for a network.
122
+ *
123
+ * @param network - The network identifier
124
+ * @param assets - Map of symbol to AssetInfo
125
+ */
126
+ registerAll(network, assets) {
127
+ for (const [symbol, info] of Object.entries(assets)) {
128
+ this.register(network, symbol, info);
129
+ }
130
+ }
131
+ /**
132
+ * Set the default asset symbol for a network.
133
+ *
134
+ * @param network - The network identifier
135
+ * @param symbol - The symbol to set as default
136
+ */
137
+ setDefault(network, symbol) {
138
+ if (!this.has(network, symbol)) {
139
+ throw new Error(
140
+ `Cannot set default: asset "${symbol}" is not registered on network "${network}"`
141
+ );
142
+ }
143
+ this.defaults.set(network, symbol);
144
+ }
145
+ /**
146
+ * Resolve a symbol to its AssetInfo on a network.
147
+ *
148
+ * @param network - The network identifier
149
+ * @param symbol - The token symbol
150
+ * @returns The resolved AssetInfo
151
+ * @throws If the asset is not registered
152
+ */
153
+ resolve(network, symbol) {
154
+ const networkAssets = this.assets.get(network);
155
+ if (!networkAssets || !networkAssets.has(symbol)) {
156
+ throw new Error(
157
+ `Asset "${symbol}" is not registered on network "${network}". Available: ${networkAssets ? Array.from(networkAssets.keys()).join(", ") : "none"}`
158
+ );
159
+ }
160
+ return networkAssets.get(symbol);
161
+ }
162
+ /**
163
+ * Get the default asset for a network.
164
+ *
165
+ * @param network - The network identifier
166
+ * @returns The default symbol and its AssetInfo
167
+ * @throws If no default is configured
168
+ */
169
+ getDefault(network) {
170
+ const symbol = this.defaults.get(network);
171
+ if (!symbol) {
172
+ throw new Error(`No default asset configured for network "${network}"`);
173
+ }
174
+ return { symbol, info: this.resolve(network, symbol) };
175
+ }
176
+ /**
177
+ * List all registered symbols for a network.
178
+ *
179
+ * @param network - The network identifier
180
+ * @returns Array of registered symbols
181
+ */
182
+ getSymbols(network) {
183
+ const networkAssets = this.assets.get(network);
184
+ return networkAssets ? Array.from(networkAssets.keys()) : [];
185
+ }
186
+ /**
187
+ * Check if an asset is registered on a network.
188
+ *
189
+ * @param network - The network identifier
190
+ * @param symbol - The token symbol
191
+ * @returns True if the asset is registered
192
+ */
193
+ has(network, symbol) {
194
+ return this.assets.get(network)?.has(symbol) ?? false;
195
+ }
196
+ /**
197
+ * Register built-in known assets.
198
+ * Data sourced from mechanism defaults and built-in registry.
199
+ */
200
+ registerBuiltins() {
201
+ this.registerAll("eip155:1", {
202
+ USDC: {
203
+ address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
204
+ decimals: 6,
205
+ name: "USD Coin",
206
+ version: "2"
207
+ },
208
+ USDT: {
209
+ address: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
210
+ decimals: 6,
211
+ name: "Tether USD",
212
+ version: "1",
213
+ assetTransferMethod: "permit2"
214
+ }
215
+ });
216
+ this.defaults.set("eip155:1", "USDC");
217
+ this.registerAll("eip155:56", {
218
+ USDC: {
219
+ address: "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d",
220
+ decimals: 18,
221
+ name: "USD Coin",
222
+ version: "1",
223
+ assetTransferMethod: "permit2"
224
+ },
225
+ USDT: {
226
+ address: "0x55d398326f99059fF775485246999027B3197955",
227
+ decimals: 18,
228
+ name: "Tether USD",
229
+ version: "1",
230
+ assetTransferMethod: "permit2"
231
+ }
232
+ });
233
+ this.defaults.set("eip155:56", "USDC");
234
+ this.registerAll("eip155:97", {
235
+ USDT: {
236
+ address: "0x337610d27c682E347C9cD60BD4b3b107C9d34dDd",
237
+ decimals: 18,
238
+ name: "Tether USD",
239
+ version: "1",
240
+ assetTransferMethod: "permit2"
241
+ },
242
+ USDC: {
243
+ address: "0x64544969ed7EBf5f083679233325356EbE738930",
244
+ decimals: 18,
245
+ name: "USD Coin",
246
+ version: "1",
247
+ assetTransferMethod: "permit2"
248
+ }
249
+ });
250
+ this.defaults.set("eip155:97", "USDT");
251
+ this.registerAll("tron:mainnet", {
252
+ USDT: {
253
+ address: "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
254
+ decimals: 6,
255
+ name: "Tether USD",
256
+ version: "1",
257
+ assetTransferMethod: "permit2"
258
+ },
259
+ USDD: {
260
+ address: "TXDk8mbtRbXeYuMNS83CfKPaYYT8XWv9Hz",
261
+ decimals: 18,
262
+ name: "Decentralized USD",
263
+ version: "1",
264
+ supportsEip2612: true,
265
+ assetTransferMethod: "permit2"
266
+ }
267
+ });
268
+ this.defaults.set("tron:mainnet", "USDT");
269
+ this.register("tron:shasta", "USDT", {
270
+ address: "TG3XXyExBkPp9nzdajDZsozEu4BkaSJozs",
271
+ decimals: 6,
272
+ name: "Tether USD",
273
+ version: "1",
274
+ assetTransferMethod: "permit2"
275
+ });
276
+ this.defaults.set("tron:shasta", "USDT");
277
+ this.registerAll("tron:nile", {
278
+ USDT: {
279
+ address: "TXYZopYRdj2D9XRtbG411XZZ3kM5VkAeBf",
280
+ decimals: 6,
281
+ name: "Tether USD",
282
+ version: "1",
283
+ assetTransferMethod: "permit2"
284
+ },
285
+ USDD: {
286
+ address: "TGjgvdTWWrybVLaVeFqSyVqJQWjxqRYbaK",
287
+ decimals: 18,
288
+ name: "Decentralized USD",
289
+ version: "1",
290
+ supportsEip2612: true,
291
+ assetTransferMethod: "permit2"
292
+ }
293
+ });
294
+ this.defaults.set("tron:nile", "USDT");
295
+ }
296
+ };
297
+
298
+ // src/registry/index.ts
299
+ var globalAssetRegistry = new AssetRegistry();
300
+
301
+ // src/index.ts
302
+ var x402Version = 2;
303
+
304
+ // src/http/x402HTTPResourceServer.ts
305
+ var RouteConfigurationError = class extends Error {
306
+ /**
307
+ * Creates a new RouteConfigurationError with the given validation errors.
308
+ *
309
+ * @param errors - The validation errors that caused this exception.
310
+ */
311
+ constructor(errors) {
312
+ const message = `x402 Route Configuration Errors:
313
+ ${errors.map((e) => ` - ${e.message}`).join("\n")}`;
314
+ super(message);
315
+ this.name = "RouteConfigurationError";
316
+ this.errors = errors;
317
+ }
318
+ };
319
+ var x402HTTPResourceServer = class {
320
+ /**
321
+ * Creates a new x402HTTPResourceServer instance.
322
+ *
323
+ * @param ResourceServer - The core x402ResourceServer instance to use
324
+ * @param routes - Route configuration for payment-protected endpoints
325
+ */
326
+ constructor(ResourceServer, routes) {
327
+ this.compiledRoutes = [];
328
+ this.protectedRequestHooks = [];
329
+ this.ResourceServer = ResourceServer;
330
+ this.routesConfig = routes;
331
+ const normalizedRoutes = typeof routes === "object" && !("accepts" in routes) ? routes : { "*": routes };
332
+ for (const [pattern, config] of Object.entries(normalizedRoutes)) {
333
+ const parsed = this.parseRoutePattern(pattern);
334
+ this.compiledRoutes.push({
335
+ verb: parsed.verb,
336
+ regex: parsed.regex,
337
+ config
338
+ });
339
+ }
340
+ }
341
+ /**
342
+ * Get the underlying x402ResourceServer instance.
343
+ *
344
+ * @returns The underlying x402ResourceServer instance
345
+ */
346
+ get server() {
347
+ return this.ResourceServer;
348
+ }
349
+ /**
350
+ * Get the routes configuration.
351
+ *
352
+ * @returns The routes configuration
353
+ */
354
+ get routes() {
355
+ return this.routesConfig;
356
+ }
357
+ /**
358
+ * Initialize the HTTP resource server.
359
+ *
360
+ * This method initializes the underlying resource server (fetching facilitator support)
361
+ * and then validates that all route payment configurations have corresponding
362
+ * registered schemes and facilitator support.
363
+ *
364
+ * @throws RouteConfigurationError if any route's payment options don't have
365
+ * corresponding registered schemes or facilitator support
366
+ *
367
+ * @example
368
+ * ```typescript
369
+ * const httpServer = new x402HTTPResourceServer(server, routes);
370
+ * await httpServer.initialize();
371
+ * ```
372
+ */
373
+ async initialize() {
374
+ await this.ResourceServer.initialize();
375
+ const errors = this.validateRouteConfiguration();
376
+ if (errors.length > 0) {
377
+ throw new RouteConfigurationError(errors);
378
+ }
379
+ }
380
+ /**
381
+ * Register a custom paywall provider for generating HTML
382
+ *
383
+ * @param provider - PaywallProvider instance
384
+ * @returns This service instance for chaining
385
+ */
386
+ registerPaywallProvider(provider) {
387
+ this.paywallProvider = provider;
388
+ return this;
389
+ }
390
+ /**
391
+ * Register a hook that runs on every request to a protected route, before payment processing.
392
+ * Hooks are executed in order of registration. The first hook to return a non-void result wins.
393
+ *
394
+ * @param hook - The request hook function
395
+ * @returns The x402HTTPResourceServer instance for chaining
396
+ */
397
+ onProtectedRequest(hook) {
398
+ this.protectedRequestHooks.push(hook);
399
+ return this;
400
+ }
401
+ /**
402
+ * Process HTTP request and return response instructions
403
+ * This is the main entry point for framework middleware
404
+ *
405
+ * @param context - HTTP request context
406
+ * @param paywallConfig - Optional paywall configuration
407
+ * @returns Process result indicating next action for middleware
408
+ */
409
+ async processHTTPRequest(context, paywallConfig) {
410
+ const { adapter, path, method } = context;
411
+ const routeConfig = this.getRouteConfig(path, method);
412
+ if (!routeConfig) {
413
+ return { type: "no-payment-required" };
414
+ }
415
+ for (const hook of this.protectedRequestHooks) {
416
+ const result = await hook(context, routeConfig);
417
+ if (result && "grantAccess" in result) {
418
+ return { type: "no-payment-required" };
419
+ }
420
+ if (result && "abort" in result) {
421
+ return {
422
+ type: "payment-error",
423
+ response: {
424
+ status: 403,
425
+ headers: { "Content-Type": "application/json" },
426
+ body: { error: result.reason }
427
+ }
428
+ };
429
+ }
430
+ }
431
+ const paymentOptions = this.normalizePaymentOptions(routeConfig);
432
+ const paymentPayload = this.extractPayment(adapter);
433
+ const resourceInfo = {
434
+ url: routeConfig.resource || context.adapter.getUrl(),
435
+ description: routeConfig.description || "",
436
+ mimeType: routeConfig.mimeType || ""
437
+ };
438
+ let requirements = await this.ResourceServer.buildPaymentRequirementsFromOptions(
439
+ paymentOptions,
440
+ context
441
+ );
442
+ let extensions = routeConfig.extensions;
443
+ if (extensions) {
444
+ extensions = this.ResourceServer.enrichExtensions(extensions, context);
445
+ }
446
+ const transportContext = { request: context };
447
+ const paymentRequired = await this.ResourceServer.createPaymentRequiredResponse(
448
+ requirements,
449
+ resourceInfo,
450
+ !paymentPayload ? "Payment required" : void 0,
451
+ extensions,
452
+ transportContext
453
+ );
454
+ if (!paymentPayload) {
455
+ const unpaidBody = routeConfig.unpaidResponseBody ? await routeConfig.unpaidResponseBody(context) : void 0;
456
+ return {
457
+ type: "payment-error",
458
+ response: this.createHTTPResponse(
459
+ paymentRequired,
460
+ this.isWebBrowser(adapter),
461
+ paywallConfig,
462
+ routeConfig.customPaywallHtml,
463
+ unpaidBody
464
+ )
465
+ };
466
+ }
467
+ try {
468
+ const matchingRequirements = this.ResourceServer.findMatchingRequirements(
469
+ paymentRequired.accepts,
470
+ paymentPayload
471
+ );
472
+ if (!matchingRequirements) {
473
+ const errorResponse = await this.ResourceServer.createPaymentRequiredResponse(
474
+ requirements,
475
+ resourceInfo,
476
+ "No matching payment requirements",
477
+ routeConfig.extensions,
478
+ transportContext
479
+ );
480
+ return {
481
+ type: "payment-error",
482
+ response: this.createHTTPResponse(errorResponse, false, paywallConfig)
483
+ };
484
+ }
485
+ const verifyResult = await this.ResourceServer.verifyPayment(
486
+ paymentPayload,
487
+ matchingRequirements
488
+ );
489
+ if (!verifyResult.isValid) {
490
+ const errorResponse = await this.ResourceServer.createPaymentRequiredResponse(
491
+ requirements,
492
+ resourceInfo,
493
+ verifyResult.invalidReason,
494
+ routeConfig.extensions,
495
+ transportContext
496
+ );
497
+ return {
498
+ type: "payment-error",
499
+ response: this.createHTTPResponse(errorResponse, false, paywallConfig)
500
+ };
501
+ }
502
+ return {
503
+ type: "payment-verified",
504
+ paymentPayload,
505
+ paymentRequirements: matchingRequirements,
506
+ declaredExtensions: routeConfig.extensions
507
+ };
508
+ } catch (error) {
509
+ const errorResponse = await this.ResourceServer.createPaymentRequiredResponse(
510
+ requirements,
511
+ resourceInfo,
512
+ error instanceof Error ? error.message : "Payment verification failed",
513
+ routeConfig.extensions,
514
+ transportContext
515
+ );
516
+ return {
517
+ type: "payment-error",
518
+ response: this.createHTTPResponse(errorResponse, false, paywallConfig)
519
+ };
520
+ }
521
+ }
522
+ /**
523
+ * Process settlement after successful response
524
+ *
525
+ * @param paymentPayload - The verified payment payload
526
+ * @param requirements - The matching payment requirements
527
+ * @param declaredExtensions - Optional declared extensions (for per-key enrichment)
528
+ * @param transportContext - Optional HTTP transport context
529
+ * @returns ProcessSettleResultResponse - SettleResponse with headers if success or errorReason if failure
530
+ */
531
+ async processSettlement(paymentPayload, requirements, declaredExtensions, transportContext) {
532
+ try {
533
+ const settleResponse = await this.ResourceServer.settlePayment(
534
+ paymentPayload,
535
+ requirements,
536
+ declaredExtensions,
537
+ transportContext
538
+ );
539
+ if (!settleResponse.success) {
540
+ const failure = {
541
+ ...settleResponse,
542
+ success: false,
543
+ errorReason: settleResponse.errorReason || "Settlement failed",
544
+ errorMessage: settleResponse.errorMessage || settleResponse.errorReason || "Settlement failed",
545
+ headers: this.createSettlementHeaders(settleResponse)
546
+ };
547
+ const response = await this.buildSettlementFailureResponse(failure, transportContext);
548
+ return { ...failure, response };
549
+ }
550
+ return {
551
+ ...settleResponse,
552
+ success: true,
553
+ headers: this.createSettlementHeaders(settleResponse),
554
+ requirements
555
+ };
556
+ } catch (error) {
557
+ if (error instanceof SettleError) {
558
+ const errorReason2 = error.errorReason || error.message;
559
+ const settleResponse2 = {
560
+ success: false,
561
+ errorReason: errorReason2,
562
+ errorMessage: error.errorMessage || errorReason2,
563
+ payer: error.payer,
564
+ network: error.network,
565
+ transaction: error.transaction
566
+ };
567
+ const failure2 = {
568
+ ...settleResponse2,
569
+ success: false,
570
+ errorReason: errorReason2,
571
+ headers: this.createSettlementHeaders(settleResponse2)
572
+ };
573
+ const response2 = await this.buildSettlementFailureResponse(failure2, transportContext);
574
+ return { ...failure2, response: response2 };
575
+ }
576
+ const errorReason = error instanceof Error ? error.message : "Settlement failed";
577
+ const settleResponse = {
578
+ success: false,
579
+ errorReason,
580
+ errorMessage: errorReason,
581
+ network: requirements.network,
582
+ transaction: ""
583
+ };
584
+ const failure = {
585
+ ...settleResponse,
586
+ success: false,
587
+ errorReason,
588
+ headers: this.createSettlementHeaders(settleResponse)
589
+ };
590
+ const response = await this.buildSettlementFailureResponse(failure, transportContext);
591
+ return { ...failure, response };
592
+ }
593
+ }
594
+ /**
595
+ * Check if a request requires payment based on route configuration
596
+ *
597
+ * @param context - HTTP request context
598
+ * @returns True if the route requires payment, false otherwise
599
+ */
600
+ requiresPayment(context) {
601
+ const routeConfig = this.getRouteConfig(context.path, context.method);
602
+ return routeConfig !== void 0;
603
+ }
604
+ /**
605
+ * Build HTTPResponseInstructions for settlement failure.
606
+ * Uses settlementFailedResponseBody hook if configured, otherwise defaults to empty body.
607
+ *
608
+ * @param failure - Settlement failure result with headers
609
+ * @param transportContext - Optional HTTP transport context for the request
610
+ * @returns HTTP response instructions for the 402 settlement failure response
611
+ */
612
+ async buildSettlementFailureResponse(failure, transportContext) {
613
+ const settlementHeaders = failure.headers;
614
+ const routeConfig = transportContext ? this.getRouteConfig(transportContext.request.path, transportContext.request.method) : void 0;
615
+ const customBody = routeConfig?.settlementFailedResponseBody ? await routeConfig.settlementFailedResponseBody(transportContext.request, failure) : void 0;
616
+ const contentType = customBody ? customBody.contentType : "application/json";
617
+ const body = customBody ? customBody.body : {};
618
+ return {
619
+ status: 402,
620
+ headers: {
621
+ "Content-Type": contentType,
622
+ ...settlementHeaders
623
+ },
624
+ body,
625
+ isHtml: contentType.includes("text/html")
626
+ };
627
+ }
628
+ /**
629
+ * Normalizes a RouteConfig's accepts field into an array of PaymentOptions
630
+ * Handles both single PaymentOption and array formats
631
+ *
632
+ * @param routeConfig - Route configuration
633
+ * @returns Array of payment options
634
+ */
635
+ normalizePaymentOptions(routeConfig) {
636
+ return Array.isArray(routeConfig.accepts) ? routeConfig.accepts : [routeConfig.accepts];
637
+ }
638
+ /**
639
+ * Validates that all payment options in routes have corresponding registered schemes
640
+ * and facilitator support.
641
+ *
642
+ * @returns Array of validation errors (empty if all routes are valid)
643
+ */
644
+ validateRouteConfiguration() {
645
+ const errors = [];
646
+ const normalizedRoutes = typeof this.routesConfig === "object" && !("accepts" in this.routesConfig) ? Object.entries(this.routesConfig) : [["*", this.routesConfig]];
647
+ for (const [pattern, config] of normalizedRoutes) {
648
+ const paymentOptions = this.normalizePaymentOptions(config);
649
+ for (const option of paymentOptions) {
650
+ if (!this.ResourceServer.hasRegisteredScheme(option.network, option.scheme)) {
651
+ errors.push({
652
+ routePattern: pattern,
653
+ scheme: option.scheme,
654
+ network: option.network,
655
+ reason: "missing_scheme",
656
+ message: `Route "${pattern}": No scheme implementation registered for "${option.scheme}" on network "${option.network}"`
657
+ });
658
+ continue;
659
+ }
660
+ const supportedKind = this.ResourceServer.getSupportedKind(
661
+ x402Version,
662
+ option.network,
663
+ option.scheme
664
+ );
665
+ if (!supportedKind) {
666
+ errors.push({
667
+ routePattern: pattern,
668
+ scheme: option.scheme,
669
+ network: option.network,
670
+ reason: "missing_facilitator",
671
+ message: `Route "${pattern}": Facilitator does not support scheme "${option.scheme}" on network "${option.network}"`
672
+ });
673
+ }
674
+ }
675
+ }
676
+ return errors;
677
+ }
678
+ /**
679
+ * Get route configuration for a request
680
+ *
681
+ * @param path - Request path
682
+ * @param method - HTTP method
683
+ * @returns Route configuration or undefined if no match
684
+ */
685
+ getRouteConfig(path, method) {
686
+ const normalizedPath = this.normalizePath(path);
687
+ const upperMethod = method.toUpperCase();
688
+ const matchingRoute = this.compiledRoutes.find(
689
+ (route) => route.regex.test(normalizedPath) && (route.verb === "*" || route.verb === upperMethod)
690
+ );
691
+ return matchingRoute?.config;
692
+ }
693
+ /**
694
+ * Extract payment from HTTP headers (handles v1 and v2)
695
+ *
696
+ * @param adapter - HTTP adapter
697
+ * @returns Decoded payment payload or null
698
+ */
699
+ extractPayment(adapter) {
700
+ const header = adapter.getHeader("payment-signature") || adapter.getHeader("PAYMENT-SIGNATURE");
701
+ if (header) {
702
+ try {
703
+ return decodePaymentSignatureHeader(header);
704
+ } catch (error) {
705
+ console.warn("Failed to decode PAYMENT-SIGNATURE header:", error);
706
+ }
707
+ }
708
+ return null;
709
+ }
710
+ /**
711
+ * Check if request is from a web browser
712
+ *
713
+ * @param adapter - HTTP adapter
714
+ * @returns True if request appears to be from a browser
715
+ */
716
+ isWebBrowser(adapter) {
717
+ const accept = adapter.getAcceptHeader();
718
+ const userAgent = adapter.getUserAgent();
719
+ return accept.includes("text/html") && userAgent.includes("Mozilla");
720
+ }
721
+ /**
722
+ * Create HTTP response instructions from payment required
723
+ *
724
+ * @param paymentRequired - Payment requirements
725
+ * @param isWebBrowser - Whether request is from browser
726
+ * @param paywallConfig - Paywall configuration
727
+ * @param customHtml - Custom HTML template
728
+ * @param unpaidResponse - Optional custom response (content type and body) for unpaid API requests
729
+ * @returns Response instructions
730
+ */
731
+ createHTTPResponse(paymentRequired, isWebBrowser, paywallConfig, customHtml, unpaidResponse) {
732
+ const status = paymentRequired.error === "permit2_allowance_required" ? 412 : 402;
733
+ if (isWebBrowser) {
734
+ const html = this.generatePaywallHTML(paymentRequired, paywallConfig, customHtml);
735
+ return {
736
+ status,
737
+ headers: { "Content-Type": "text/html" },
738
+ body: html,
739
+ isHtml: true
740
+ };
741
+ }
742
+ const response = this.createHTTPPaymentRequiredResponse(paymentRequired);
743
+ const contentType = unpaidResponse ? unpaidResponse.contentType : "application/json";
744
+ const body = unpaidResponse ? unpaidResponse.body : {};
745
+ return {
746
+ status,
747
+ headers: {
748
+ "Content-Type": contentType,
749
+ ...response.headers
750
+ },
751
+ body
752
+ };
753
+ }
754
+ /**
755
+ * Create HTTP payment required response (v1 puts in body, v2 puts in header)
756
+ *
757
+ * @param paymentRequired - Payment required object
758
+ * @returns Headers and body for the HTTP response
759
+ */
760
+ createHTTPPaymentRequiredResponse(paymentRequired) {
761
+ return {
762
+ headers: {
763
+ "PAYMENT-REQUIRED": encodePaymentRequiredHeader(paymentRequired)
764
+ }
765
+ };
766
+ }
767
+ /**
768
+ * Create settlement response headers
769
+ *
770
+ * @param settleResponse - Settlement response
771
+ * @returns Headers to add to response
772
+ */
773
+ createSettlementHeaders(settleResponse) {
774
+ const encoded = encodePaymentResponseHeader(settleResponse);
775
+ return { "PAYMENT-RESPONSE": encoded };
776
+ }
777
+ /**
778
+ * Parse route pattern into verb and regex
779
+ *
780
+ * @param pattern - Route pattern like "GET /api/*" or "/api/[id]"
781
+ * @returns Parsed pattern with verb and regex
782
+ */
783
+ parseRoutePattern(pattern) {
784
+ const [verb, path] = pattern.includes(" ") ? pattern.split(/\s+/) : ["*", pattern];
785
+ const regex = new RegExp(
786
+ `^${path.replace(/[$()+.?^{|}]/g, "\\$&").replace(/\*/g, ".*?").replace(/\[([^\]]+)\]/g, "[^/]+").replace(/\//g, "\\/")}$`,
787
+ "i"
788
+ );
789
+ return { verb: verb.toUpperCase(), regex };
790
+ }
791
+ /**
792
+ * Normalize path for matching
793
+ *
794
+ * @param path - Raw path from request
795
+ * @returns Normalized path
796
+ */
797
+ normalizePath(path) {
798
+ const pathWithoutQuery = path.split(/[?#]/)[0];
799
+ let decodedOrRawPath;
800
+ try {
801
+ decodedOrRawPath = decodeURIComponent(pathWithoutQuery);
802
+ } catch {
803
+ decodedOrRawPath = pathWithoutQuery;
804
+ }
805
+ return decodedOrRawPath.replace(/\\/g, "/").replace(/\/+/g, "/").replace(/(.+?)\/+$/, "$1");
806
+ }
807
+ /**
808
+ * Generate paywall HTML for browser requests
809
+ *
810
+ * @param paymentRequired - Payment required response
811
+ * @param paywallConfig - Optional paywall configuration
812
+ * @param customHtml - Optional custom HTML template
813
+ * @returns HTML string
814
+ */
815
+ generatePaywallHTML(paymentRequired, paywallConfig, customHtml) {
816
+ if (customHtml) {
817
+ return customHtml;
818
+ }
819
+ if (this.paywallProvider) {
820
+ return this.paywallProvider.generateHtml(paymentRequired, paywallConfig);
821
+ }
822
+ try {
823
+ const paywall = require("@bankofai/x402-paywall");
824
+ const displayAmount2 = this.getDisplayAmount(paymentRequired);
825
+ const resource2 = paymentRequired.resource;
826
+ return paywall.getPaywallHtml({
827
+ amount: displayAmount2,
828
+ paymentRequired,
829
+ currentUrl: resource2?.url || paywallConfig?.currentUrl || "",
830
+ testnet: paywallConfig?.testnet ?? true,
831
+ appName: paywallConfig?.appName,
832
+ appLogo: paywallConfig?.appLogo,
833
+ sessionTokenEndpoint: paywallConfig?.sessionTokenEndpoint
834
+ });
835
+ } catch {
836
+ }
837
+ const resource = paymentRequired.resource;
838
+ const displayAmount = this.getDisplayAmount(paymentRequired);
839
+ return `
840
+ <!DOCTYPE html>
841
+ <html>
842
+ <head>
843
+ <title>Payment Required</title>
844
+ <meta charset="UTF-8">
845
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
846
+ </head>
847
+ <body>
848
+ <div style="max-width: 600px; margin: 50px auto; padding: 20px; font-family: system-ui, -apple-system, sans-serif;">
849
+ ${paywallConfig?.appLogo ? `<img src="${paywallConfig.appLogo}" alt="${paywallConfig.appName || "App"}" style="max-width: 200px; margin-bottom: 20px;">` : ""}
850
+ <h1>Payment Required</h1>
851
+ ${resource ? `<p><strong>Resource:</strong> ${resource.description || resource.url}</p>` : ""}
852
+ <p><strong>Amount:</strong> $${displayAmount.toFixed(2)} USDC</p>
853
+ <div id="payment-widget"
854
+ data-requirements='${JSON.stringify(paymentRequired)}'
855
+ data-app-name="${paywallConfig?.appName || ""}"
856
+ data-testnet="${paywallConfig?.testnet || false}">
857
+ <!-- Install @bankofai/x402-paywall for full wallet integration -->
858
+ <p style="margin-top: 2rem; padding: 1rem; background: #fef3c7; border-radius: 0.5rem;">
859
+ <strong>Note:</strong> Install <code>@bankofai/x402-paywall</code> for full wallet connection and payment UI.
860
+ </p>
861
+ </div>
862
+ </div>
863
+ </body>
864
+ </html>
865
+ `;
866
+ }
867
+ /**
868
+ * Extract display amount from payment requirements.
869
+ *
870
+ * @param paymentRequired - The payment required object
871
+ * @returns The display amount in decimal format
872
+ */
873
+ getDisplayAmount(paymentRequired) {
874
+ const accepts = paymentRequired.accepts;
875
+ if (accepts && accepts.length > 0) {
876
+ const firstReq = accepts[0];
877
+ if ("amount" in firstReq) {
878
+ return parseFloat(firstReq.amount) / 1e6;
879
+ }
880
+ }
881
+ return 0;
882
+ }
883
+ };
884
+
885
+ // src/http/httpFacilitatorClient.ts
886
+ var DEFAULT_FACILITATOR_URL = "https://x402.org/facilitator";
887
+ var GET_SUPPORTED_RETRIES = 3;
888
+ var GET_SUPPORTED_RETRY_DELAY_MS = 1e3;
889
+ var HTTPFacilitatorClient = class {
890
+ /**
891
+ * Creates a new HTTPFacilitatorClient instance.
892
+ *
893
+ * @param config - Configuration options for the facilitator client
894
+ */
895
+ constructor(config) {
896
+ this.url = config?.url || DEFAULT_FACILITATOR_URL;
897
+ this._createAuthHeaders = config?.createAuthHeaders;
898
+ }
899
+ /**
900
+ * Verify a payment with the facilitator
901
+ *
902
+ * @param paymentPayload - The payment to verify
903
+ * @param paymentRequirements - The requirements to verify against
904
+ * @returns Verification response
905
+ */
906
+ async verify(paymentPayload, paymentRequirements) {
907
+ let headers = {
908
+ "Content-Type": "application/json"
909
+ };
910
+ if (this._createAuthHeaders) {
911
+ const authHeaders = await this.createAuthHeaders("verify");
912
+ headers = { ...headers, ...authHeaders.headers };
913
+ }
914
+ const response = await fetch(`${this.url}/verify`, {
915
+ method: "POST",
916
+ headers,
917
+ body: JSON.stringify({
918
+ x402Version: paymentPayload.x402Version,
919
+ paymentPayload: this.toJsonSafe(paymentPayload),
920
+ paymentRequirements: this.toJsonSafe(paymentRequirements)
921
+ })
922
+ });
923
+ const data = await response.json();
924
+ if (typeof data === "object" && data !== null && "isValid" in data) {
925
+ const verifyResponse = data;
926
+ if (!response.ok) {
927
+ throw new VerifyError(response.status, verifyResponse);
928
+ }
929
+ return verifyResponse;
930
+ }
931
+ throw new Error(`Facilitator verify failed (${response.status}): ${JSON.stringify(data)}`);
932
+ }
933
+ /**
934
+ * Settle a payment with the facilitator
935
+ *
936
+ * @param paymentPayload - The payment to settle
937
+ * @param paymentRequirements - The requirements for settlement
938
+ * @returns Settlement response
939
+ */
940
+ async settle(paymentPayload, paymentRequirements) {
941
+ let headers = {
942
+ "Content-Type": "application/json"
943
+ };
944
+ if (this._createAuthHeaders) {
945
+ const authHeaders = await this.createAuthHeaders("settle");
946
+ headers = { ...headers, ...authHeaders.headers };
947
+ }
948
+ const response = await fetch(`${this.url}/settle`, {
949
+ method: "POST",
950
+ headers,
951
+ body: JSON.stringify({
952
+ x402Version: paymentPayload.x402Version,
953
+ paymentPayload: this.toJsonSafe(paymentPayload),
954
+ paymentRequirements: this.toJsonSafe(paymentRequirements)
955
+ })
956
+ });
957
+ const data = await response.json();
958
+ if (typeof data === "object" && data !== null && "success" in data) {
959
+ const settleResponse = data;
960
+ if (!response.ok) {
961
+ throw new SettleError(response.status, settleResponse);
962
+ }
963
+ return settleResponse;
964
+ }
965
+ throw new Error(`Facilitator settle failed (${response.status}): ${JSON.stringify(data)}`);
966
+ }
967
+ /**
968
+ * Get supported payment kinds and extensions from the facilitator.
969
+ * Retries with exponential backoff on 429 rate limit errors.
970
+ *
971
+ * @returns Supported payment kinds and extensions
972
+ */
973
+ async getSupported() {
974
+ let headers = {
975
+ "Content-Type": "application/json"
976
+ };
977
+ if (this._createAuthHeaders) {
978
+ const authHeaders = await this.createAuthHeaders("supported");
979
+ headers = { ...headers, ...authHeaders.headers };
980
+ }
981
+ let lastError = null;
982
+ for (let attempt = 0; attempt < GET_SUPPORTED_RETRIES; attempt++) {
983
+ const response = await fetch(`${this.url}/supported`, {
984
+ method: "GET",
985
+ headers
986
+ });
987
+ if (response.ok) {
988
+ return await response.json();
989
+ }
990
+ const errorText = await response.text().catch(() => response.statusText);
991
+ lastError = new Error(`Facilitator getSupported failed (${response.status}): ${errorText}`);
992
+ if (response.status === 429 && attempt < GET_SUPPORTED_RETRIES - 1) {
993
+ const delay = GET_SUPPORTED_RETRY_DELAY_MS * Math.pow(2, attempt);
994
+ await new Promise((resolve) => setTimeout(resolve, delay));
995
+ continue;
996
+ }
997
+ throw lastError;
998
+ }
999
+ throw lastError ?? new Error("Facilitator getSupported failed after retries");
1000
+ }
1001
+ /**
1002
+ * Creates authentication headers for a specific path.
1003
+ *
1004
+ * @param path - The path to create authentication headers for (e.g., "verify", "settle", "supported")
1005
+ * @returns An object containing the authentication headers for the specified path
1006
+ */
1007
+ async createAuthHeaders(path) {
1008
+ if (this._createAuthHeaders) {
1009
+ const authHeaders = await this._createAuthHeaders();
1010
+ return {
1011
+ headers: authHeaders[path] ?? {}
1012
+ };
1013
+ }
1014
+ return {
1015
+ headers: {}
1016
+ };
1017
+ }
1018
+ /**
1019
+ * Helper to convert objects to JSON-safe format.
1020
+ * Handles BigInt and other non-JSON types.
1021
+ *
1022
+ * @param obj - The object to convert
1023
+ * @returns The JSON-safe representation of the object
1024
+ */
1025
+ toJsonSafe(obj) {
1026
+ return JSON.parse(
1027
+ JSON.stringify(obj, (_, value) => typeof value === "bigint" ? value.toString() : value)
1028
+ );
1029
+ }
1030
+ };
1031
+
1032
+ // src/http/x402HTTPClient.ts
1033
+ var x402HTTPClient = class {
1034
+ /**
1035
+ * Creates a new x402HTTPClient instance.
1036
+ *
1037
+ * @param client - The underlying x402Client for payment logic
1038
+ */
1039
+ constructor(client) {
1040
+ this.client = client;
1041
+ this.paymentRequiredHooks = [];
1042
+ }
1043
+ /**
1044
+ * Register a hook to handle 402 responses before payment.
1045
+ * Hooks run in order; first to return headers wins.
1046
+ *
1047
+ * @param hook - The hook function to register
1048
+ * @returns This instance for chaining
1049
+ */
1050
+ onPaymentRequired(hook) {
1051
+ this.paymentRequiredHooks.push(hook);
1052
+ return this;
1053
+ }
1054
+ /**
1055
+ * Run hooks and return headers if any hook provides them.
1056
+ *
1057
+ * @param paymentRequired - The payment required response from the server
1058
+ * @returns Headers to use for retry, or null to proceed to payment
1059
+ */
1060
+ async handlePaymentRequired(paymentRequired) {
1061
+ for (const hook of this.paymentRequiredHooks) {
1062
+ const result = await hook({ paymentRequired });
1063
+ if (result?.headers) {
1064
+ return result.headers;
1065
+ }
1066
+ }
1067
+ return null;
1068
+ }
1069
+ /**
1070
+ * Encodes a payment payload into appropriate HTTP headers based on version.
1071
+ *
1072
+ * @param paymentPayload - The payment payload to encode
1073
+ * @returns HTTP headers containing the encoded payment signature
1074
+ */
1075
+ encodePaymentSignatureHeader(paymentPayload) {
1076
+ switch (paymentPayload.x402Version) {
1077
+ case 2:
1078
+ return {
1079
+ "PAYMENT-SIGNATURE": encodePaymentSignatureHeader(paymentPayload)
1080
+ };
1081
+ case 1:
1082
+ return {
1083
+ "X-PAYMENT": encodePaymentSignatureHeader(paymentPayload)
1084
+ };
1085
+ default:
1086
+ throw new Error(
1087
+ `Unsupported x402 version: ${paymentPayload.x402Version}`
1088
+ );
1089
+ }
1090
+ }
1091
+ /**
1092
+ * Extracts payment required information from HTTP response.
1093
+ *
1094
+ * @param getHeader - Function to retrieve header value by name (case-insensitive)
1095
+ * @param body - Optional response body for v1 compatibility
1096
+ * @returns The payment required object
1097
+ */
1098
+ getPaymentRequiredResponse(getHeader, body) {
1099
+ const paymentRequired = getHeader("PAYMENT-REQUIRED");
1100
+ if (paymentRequired) {
1101
+ return decodePaymentRequiredHeader(paymentRequired);
1102
+ }
1103
+ if (body && body instanceof Object && "x402Version" in body && body.x402Version === 1) {
1104
+ return body;
1105
+ }
1106
+ throw new Error("Invalid payment required response");
1107
+ }
1108
+ /**
1109
+ * Extracts payment settlement response from HTTP headers.
1110
+ *
1111
+ * @param getHeader - Function to retrieve header value by name (case-insensitive)
1112
+ * @returns The settlement response object
1113
+ */
1114
+ getPaymentSettleResponse(getHeader) {
1115
+ const paymentResponse = getHeader("PAYMENT-RESPONSE");
1116
+ if (paymentResponse) {
1117
+ return decodePaymentResponseHeader(paymentResponse);
1118
+ }
1119
+ const xPaymentResponse = getHeader("X-PAYMENT-RESPONSE");
1120
+ if (xPaymentResponse) {
1121
+ return decodePaymentResponseHeader(xPaymentResponse);
1122
+ }
1123
+ throw new Error("Payment response header not found");
1124
+ }
1125
+ /**
1126
+ * Creates a payment payload for the given payment requirements.
1127
+ * Delegates to the underlying x402Client.
1128
+ *
1129
+ * @param paymentRequired - The payment required response from the server
1130
+ * @returns Promise resolving to the payment payload
1131
+ */
1132
+ async createPaymentPayload(paymentRequired) {
1133
+ return this.client.createPaymentPayload(paymentRequired);
1134
+ }
1135
+ };
1136
+
1137
+ // src/http/index.ts
1138
+ function encodePaymentSignatureHeader(paymentPayload) {
1139
+ return safeBase64Encode(JSON.stringify(paymentPayload));
1140
+ }
1141
+ function decodePaymentSignatureHeader(paymentSignatureHeader) {
1142
+ if (!Base64EncodedRegex.test(paymentSignatureHeader)) {
1143
+ throw new Error("Invalid payment signature header");
1144
+ }
1145
+ return JSON.parse(safeBase64Decode(paymentSignatureHeader));
1146
+ }
1147
+ function encodePaymentRequiredHeader(paymentRequired) {
1148
+ return safeBase64Encode(JSON.stringify(paymentRequired));
1149
+ }
1150
+ function decodePaymentRequiredHeader(paymentRequiredHeader) {
1151
+ if (!Base64EncodedRegex.test(paymentRequiredHeader)) {
1152
+ throw new Error("Invalid payment required header");
1153
+ }
1154
+ return JSON.parse(safeBase64Decode(paymentRequiredHeader));
1155
+ }
1156
+ function encodePaymentResponseHeader(paymentResponse) {
1157
+ return safeBase64Encode(JSON.stringify(paymentResponse));
1158
+ }
1159
+ function decodePaymentResponseHeader(paymentResponseHeader) {
1160
+ if (!Base64EncodedRegex.test(paymentResponseHeader)) {
1161
+ throw new Error("Invalid payment response header");
1162
+ }
1163
+ return JSON.parse(safeBase64Decode(paymentResponseHeader));
1164
+ }
1165
+ // Annotate the CommonJS export names for ESM import in node:
1166
+ 0 && (module.exports = {
1167
+ HTTPFacilitatorClient,
1168
+ RouteConfigurationError,
1169
+ decodePaymentRequiredHeader,
1170
+ decodePaymentResponseHeader,
1171
+ decodePaymentSignatureHeader,
1172
+ encodePaymentRequiredHeader,
1173
+ encodePaymentResponseHeader,
1174
+ encodePaymentSignatureHeader,
1175
+ x402HTTPClient,
1176
+ x402HTTPResourceServer
1177
+ });
1178
+ //# sourceMappingURL=index.js.map