x402-core-mantle 2.1.1-mantle

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 (64) hide show
  1. package/README.md +293 -0
  2. package/dist/cjs/client/index.d.ts +243 -0
  3. package/dist/cjs/client/index.js +413 -0
  4. package/dist/cjs/client/index.js.map +1 -0
  5. package/dist/cjs/facilitator/index.d.ts +192 -0
  6. package/dist/cjs/facilitator/index.js +398 -0
  7. package/dist/cjs/facilitator/index.js.map +1 -0
  8. package/dist/cjs/http/index.d.ts +52 -0
  9. package/dist/cjs/http/index.js +827 -0
  10. package/dist/cjs/http/index.js.map +1 -0
  11. package/dist/cjs/index.d.ts +3 -0
  12. package/dist/cjs/index.js +31 -0
  13. package/dist/cjs/index.js.map +1 -0
  14. package/dist/cjs/mechanisms-CzuGzYsS.d.ts +270 -0
  15. package/dist/cjs/server/index.d.ts +2 -0
  16. package/dist/cjs/server/index.js +1305 -0
  17. package/dist/cjs/server/index.js.map +1 -0
  18. package/dist/cjs/types/index.d.ts +1 -0
  19. package/dist/cjs/types/index.js +66 -0
  20. package/dist/cjs/types/index.js.map +1 -0
  21. package/dist/cjs/types/v1/index.d.ts +1 -0
  22. package/dist/cjs/types/v1/index.js +19 -0
  23. package/dist/cjs/types/v1/index.js.map +1 -0
  24. package/dist/cjs/utils/index.d.ts +48 -0
  25. package/dist/cjs/utils/index.js +116 -0
  26. package/dist/cjs/utils/index.js.map +1 -0
  27. package/dist/cjs/x402HTTPResourceServer-D1YtlH_r.d.ts +719 -0
  28. package/dist/esm/chunk-BJTO5JO5.mjs +11 -0
  29. package/dist/esm/chunk-BJTO5JO5.mjs.map +1 -0
  30. package/dist/esm/chunk-TDLQZ6MP.mjs +86 -0
  31. package/dist/esm/chunk-TDLQZ6MP.mjs.map +1 -0
  32. package/dist/esm/chunk-VE37GDG2.mjs +7 -0
  33. package/dist/esm/chunk-VE37GDG2.mjs.map +1 -0
  34. package/dist/esm/chunk-X4W4S5RB.mjs +39 -0
  35. package/dist/esm/chunk-X4W4S5RB.mjs.map +1 -0
  36. package/dist/esm/chunk-Z4QX3O5V.mjs +748 -0
  37. package/dist/esm/chunk-Z4QX3O5V.mjs.map +1 -0
  38. package/dist/esm/client/index.d.mts +243 -0
  39. package/dist/esm/client/index.mjs +260 -0
  40. package/dist/esm/client/index.mjs.map +1 -0
  41. package/dist/esm/facilitator/index.d.mts +192 -0
  42. package/dist/esm/facilitator/index.mjs +373 -0
  43. package/dist/esm/facilitator/index.mjs.map +1 -0
  44. package/dist/esm/http/index.d.mts +52 -0
  45. package/dist/esm/http/index.mjs +29 -0
  46. package/dist/esm/http/index.mjs.map +1 -0
  47. package/dist/esm/index.d.mts +3 -0
  48. package/dist/esm/index.mjs +8 -0
  49. package/dist/esm/index.mjs.map +1 -0
  50. package/dist/esm/mechanisms-CzuGzYsS.d.mts +270 -0
  51. package/dist/esm/server/index.d.mts +2 -0
  52. package/dist/esm/server/index.mjs +563 -0
  53. package/dist/esm/server/index.mjs.map +1 -0
  54. package/dist/esm/types/index.d.mts +1 -0
  55. package/dist/esm/types/index.mjs +10 -0
  56. package/dist/esm/types/index.mjs.map +1 -0
  57. package/dist/esm/types/v1/index.d.mts +1 -0
  58. package/dist/esm/types/v1/index.mjs +1 -0
  59. package/dist/esm/types/v1/index.mjs.map +1 -0
  60. package/dist/esm/utils/index.d.mts +48 -0
  61. package/dist/esm/utils/index.mjs +20 -0
  62. package/dist/esm/utils/index.mjs.map +1 -0
  63. package/dist/esm/x402HTTPResourceServer-BIfIK5HS.d.mts +719 -0
  64. package/package.json +129 -0
@@ -0,0 +1,827 @@
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
+ super(`verification failed: ${response.invalidReason || "unknown reason"}`);
69
+ this.name = "VerifyError";
70
+ this.statusCode = statusCode;
71
+ this.invalidReason = response.invalidReason;
72
+ this.payer = response.payer;
73
+ }
74
+ };
75
+ var SettleError = class extends Error {
76
+ /**
77
+ * Creates a SettleError from a failed settlement response.
78
+ *
79
+ * @param statusCode - HTTP status code from the facilitator
80
+ * @param response - The settle response containing error details
81
+ */
82
+ constructor(statusCode, response) {
83
+ super(`settlement failed: ${response.errorReason || "unknown reason"}`);
84
+ this.name = "SettleError";
85
+ this.statusCode = statusCode;
86
+ this.errorReason = response.errorReason;
87
+ this.payer = response.payer;
88
+ this.transaction = response.transaction;
89
+ this.network = response.network;
90
+ }
91
+ };
92
+
93
+ // src/index.ts
94
+ var x402Version = 2;
95
+
96
+ // src/http/x402HTTPResourceServer.ts
97
+ var RouteConfigurationError = class extends Error {
98
+ /**
99
+ * Creates a new RouteConfigurationError with the given validation errors.
100
+ *
101
+ * @param errors - The validation errors that caused this exception.
102
+ */
103
+ constructor(errors) {
104
+ const message = `x402 Route Configuration Errors:
105
+ ${errors.map((e) => ` - ${e.message}`).join("\n")}`;
106
+ super(message);
107
+ this.name = "RouteConfigurationError";
108
+ this.errors = errors;
109
+ }
110
+ };
111
+ var x402HTTPResourceServer = class {
112
+ /**
113
+ * Creates a new x402HTTPResourceServer instance.
114
+ *
115
+ * @param ResourceServer - The core x402ResourceServer instance to use
116
+ * @param routes - Route configuration for payment-protected endpoints
117
+ */
118
+ constructor(ResourceServer, routes) {
119
+ this.compiledRoutes = [];
120
+ this.ResourceServer = ResourceServer;
121
+ this.routesConfig = routes;
122
+ const normalizedRoutes = typeof routes === "object" && !("accepts" in routes) ? routes : { "*": routes };
123
+ for (const [pattern, config] of Object.entries(normalizedRoutes)) {
124
+ const parsed = this.parseRoutePattern(pattern);
125
+ this.compiledRoutes.push({
126
+ verb: parsed.verb,
127
+ regex: parsed.regex,
128
+ config
129
+ });
130
+ }
131
+ }
132
+ /**
133
+ * Initialize the HTTP resource server.
134
+ *
135
+ * This method initializes the underlying resource server (fetching facilitator support)
136
+ * and then validates that all route payment configurations have corresponding
137
+ * registered schemes and facilitator support.
138
+ *
139
+ * @throws RouteConfigurationError if any route's payment options don't have
140
+ * corresponding registered schemes or facilitator support
141
+ *
142
+ * @example
143
+ * ```typescript
144
+ * const httpServer = new x402HTTPResourceServer(server, routes);
145
+ * await httpServer.initialize();
146
+ * ```
147
+ */
148
+ async initialize() {
149
+ await this.ResourceServer.initialize();
150
+ const errors = this.validateRouteConfiguration();
151
+ if (errors.length > 0) {
152
+ throw new RouteConfigurationError(errors);
153
+ }
154
+ }
155
+ /**
156
+ * Register a custom paywall provider for generating HTML
157
+ *
158
+ * @param provider - PaywallProvider instance
159
+ * @returns This service instance for chaining
160
+ */
161
+ registerPaywallProvider(provider) {
162
+ this.paywallProvider = provider;
163
+ return this;
164
+ }
165
+ /**
166
+ * Process HTTP request and return response instructions
167
+ * This is the main entry point for framework middleware
168
+ *
169
+ * @param context - HTTP request context
170
+ * @param paywallConfig - Optional paywall configuration
171
+ * @returns Process result indicating next action for middleware
172
+ */
173
+ async processHTTPRequest(context, paywallConfig) {
174
+ const { adapter, path, method } = context;
175
+ const routeConfig = this.getRouteConfig(path, method);
176
+ if (!routeConfig) {
177
+ return { type: "no-payment-required" };
178
+ }
179
+ const paymentOptions = this.normalizePaymentOptions(routeConfig);
180
+ const paymentPayload = this.extractPayment(adapter);
181
+ const resourceInfo = {
182
+ url: routeConfig.resource || context.adapter.getUrl(),
183
+ description: routeConfig.description || "",
184
+ mimeType: routeConfig.mimeType || ""
185
+ };
186
+ const requirements = await this.ResourceServer.buildPaymentRequirementsFromOptions(
187
+ paymentOptions,
188
+ context
189
+ );
190
+ let extensions = routeConfig.extensions;
191
+ if (extensions) {
192
+ extensions = this.ResourceServer.enrichExtensions(extensions, context);
193
+ }
194
+ const paymentRequired = this.ResourceServer.createPaymentRequiredResponse(
195
+ requirements,
196
+ resourceInfo,
197
+ !paymentPayload ? "Payment required" : void 0,
198
+ extensions
199
+ );
200
+ if (!paymentPayload) {
201
+ const unpaidBody = routeConfig.unpaidResponseBody ? await routeConfig.unpaidResponseBody(context) : void 0;
202
+ return {
203
+ type: "payment-error",
204
+ response: this.createHTTPResponse(
205
+ paymentRequired,
206
+ this.isWebBrowser(adapter),
207
+ paywallConfig,
208
+ routeConfig.customPaywallHtml,
209
+ unpaidBody
210
+ )
211
+ };
212
+ }
213
+ try {
214
+ const matchingRequirements = this.ResourceServer.findMatchingRequirements(
215
+ paymentRequired.accepts,
216
+ paymentPayload
217
+ );
218
+ if (!matchingRequirements) {
219
+ const errorResponse = this.ResourceServer.createPaymentRequiredResponse(
220
+ requirements,
221
+ resourceInfo,
222
+ "No matching payment requirements",
223
+ routeConfig.extensions
224
+ );
225
+ return {
226
+ type: "payment-error",
227
+ response: this.createHTTPResponse(errorResponse, false, paywallConfig)
228
+ };
229
+ }
230
+ const verifyResult = await this.ResourceServer.verifyPayment(
231
+ paymentPayload,
232
+ matchingRequirements
233
+ );
234
+ if (!verifyResult.isValid) {
235
+ const errorResponse = this.ResourceServer.createPaymentRequiredResponse(
236
+ requirements,
237
+ resourceInfo,
238
+ verifyResult.invalidReason,
239
+ routeConfig.extensions
240
+ );
241
+ return {
242
+ type: "payment-error",
243
+ response: this.createHTTPResponse(errorResponse, false, paywallConfig)
244
+ };
245
+ }
246
+ return {
247
+ type: "payment-verified",
248
+ paymentPayload,
249
+ paymentRequirements: matchingRequirements
250
+ };
251
+ } catch (error) {
252
+ const errorResponse = this.ResourceServer.createPaymentRequiredResponse(
253
+ requirements,
254
+ resourceInfo,
255
+ error instanceof Error ? error.message : "Payment verification failed",
256
+ routeConfig.extensions
257
+ );
258
+ return {
259
+ type: "payment-error",
260
+ response: this.createHTTPResponse(errorResponse, false, paywallConfig)
261
+ };
262
+ }
263
+ }
264
+ /**
265
+ * Process settlement after successful response
266
+ *
267
+ * @param paymentPayload - The verified payment payload
268
+ * @param requirements - The matching payment requirements
269
+ * @returns ProcessSettleResultResponse - SettleResponse with headers if success or errorReason if failure
270
+ */
271
+ async processSettlement(paymentPayload, requirements) {
272
+ try {
273
+ const settleResponse = await this.ResourceServer.settlePayment(paymentPayload, requirements);
274
+ if (!settleResponse.success) {
275
+ return {
276
+ ...settleResponse,
277
+ success: false,
278
+ errorReason: settleResponse.errorReason || "Settlement failed"
279
+ };
280
+ }
281
+ return {
282
+ ...settleResponse,
283
+ success: true,
284
+ headers: this.createSettlementHeaders(settleResponse, requirements),
285
+ requirements
286
+ };
287
+ } catch (error) {
288
+ if (error instanceof SettleError) {
289
+ return {
290
+ success: false,
291
+ errorReason: error.errorReason || error.message,
292
+ payer: error.payer,
293
+ network: error.network,
294
+ transaction: error.transaction
295
+ };
296
+ }
297
+ return {
298
+ success: false,
299
+ errorReason: error instanceof Error ? error.message : "Settlement failed",
300
+ network: requirements.network,
301
+ transaction: ""
302
+ };
303
+ }
304
+ }
305
+ /**
306
+ * Check if a request requires payment based on route configuration
307
+ *
308
+ * @param context - HTTP request context
309
+ * @returns True if the route requires payment, false otherwise
310
+ */
311
+ requiresPayment(context) {
312
+ const routeConfig = this.getRouteConfig(context.path, context.method);
313
+ return routeConfig !== void 0;
314
+ }
315
+ /**
316
+ * Normalizes a RouteConfig's accepts field into an array of PaymentOptions
317
+ * Handles both single PaymentOption and array formats
318
+ *
319
+ * @param routeConfig - Route configuration
320
+ * @returns Array of payment options
321
+ */
322
+ normalizePaymentOptions(routeConfig) {
323
+ return Array.isArray(routeConfig.accepts) ? routeConfig.accepts : [routeConfig.accepts];
324
+ }
325
+ /**
326
+ * Validates that all payment options in routes have corresponding registered schemes
327
+ * and facilitator support.
328
+ *
329
+ * @returns Array of validation errors (empty if all routes are valid)
330
+ */
331
+ validateRouteConfiguration() {
332
+ const errors = [];
333
+ const normalizedRoutes = typeof this.routesConfig === "object" && !("accepts" in this.routesConfig) ? Object.entries(this.routesConfig) : [["*", this.routesConfig]];
334
+ for (const [pattern, config] of normalizedRoutes) {
335
+ const paymentOptions = this.normalizePaymentOptions(config);
336
+ for (const option of paymentOptions) {
337
+ if (!this.ResourceServer.hasRegisteredScheme(option.network, option.scheme)) {
338
+ errors.push({
339
+ routePattern: pattern,
340
+ scheme: option.scheme,
341
+ network: option.network,
342
+ reason: "missing_scheme",
343
+ message: `Route "${pattern}": No scheme implementation registered for "${option.scheme}" on network "${option.network}"`
344
+ });
345
+ continue;
346
+ }
347
+ const supportedKind = this.ResourceServer.getSupportedKind(
348
+ x402Version,
349
+ option.network,
350
+ option.scheme
351
+ );
352
+ if (!supportedKind) {
353
+ errors.push({
354
+ routePattern: pattern,
355
+ scheme: option.scheme,
356
+ network: option.network,
357
+ reason: "missing_facilitator",
358
+ message: `Route "${pattern}": Facilitator does not support scheme "${option.scheme}" on network "${option.network}"`
359
+ });
360
+ }
361
+ }
362
+ }
363
+ return errors;
364
+ }
365
+ /**
366
+ * Get route configuration for a request
367
+ *
368
+ * @param path - Request path
369
+ * @param method - HTTP method
370
+ * @returns Route configuration or undefined if no match
371
+ */
372
+ getRouteConfig(path, method) {
373
+ const normalizedPath = this.normalizePath(path);
374
+ const upperMethod = method.toUpperCase();
375
+ const matchingRoute = this.compiledRoutes.find(
376
+ (route) => route.regex.test(normalizedPath) && (route.verb === "*" || route.verb === upperMethod)
377
+ );
378
+ return matchingRoute?.config;
379
+ }
380
+ /**
381
+ * Extract payment from HTTP headers (handles v1 and v2)
382
+ *
383
+ * @param adapter - HTTP adapter
384
+ * @returns Decoded payment payload or null
385
+ */
386
+ extractPayment(adapter) {
387
+ const header = adapter.getHeader("payment-signature") || adapter.getHeader("PAYMENT-SIGNATURE");
388
+ if (header) {
389
+ try {
390
+ return decodePaymentSignatureHeader(header);
391
+ } catch (error) {
392
+ console.warn("Failed to decode PAYMENT-SIGNATURE header:", error);
393
+ }
394
+ }
395
+ return null;
396
+ }
397
+ /**
398
+ * Check if request is from a web browser
399
+ *
400
+ * @param adapter - HTTP adapter
401
+ * @returns True if request appears to be from a browser
402
+ */
403
+ isWebBrowser(adapter) {
404
+ const accept = adapter.getAcceptHeader();
405
+ const userAgent = adapter.getUserAgent();
406
+ return accept.includes("text/html") && userAgent.includes("Mozilla");
407
+ }
408
+ /**
409
+ * Create HTTP response instructions from payment required
410
+ *
411
+ * @param paymentRequired - Payment requirements
412
+ * @param isWebBrowser - Whether request is from browser
413
+ * @param paywallConfig - Paywall configuration
414
+ * @param customHtml - Custom HTML template
415
+ * @param unpaidResponse - Optional custom response (content type and body) for unpaid API requests
416
+ * @returns Response instructions
417
+ */
418
+ createHTTPResponse(paymentRequired, isWebBrowser, paywallConfig, customHtml, unpaidResponse) {
419
+ if (isWebBrowser) {
420
+ const html = this.generatePaywallHTML(paymentRequired, paywallConfig, customHtml);
421
+ return {
422
+ status: 402,
423
+ headers: { "Content-Type": "text/html" },
424
+ body: html,
425
+ isHtml: true
426
+ };
427
+ }
428
+ const response = this.createHTTPPaymentRequiredResponse(paymentRequired);
429
+ const contentType = unpaidResponse ? unpaidResponse.contentType : "application/json";
430
+ const body = unpaidResponse ? unpaidResponse.body : {};
431
+ return {
432
+ status: 402,
433
+ headers: {
434
+ "Content-Type": contentType,
435
+ ...response.headers
436
+ },
437
+ body
438
+ };
439
+ }
440
+ /**
441
+ * Create HTTP payment required response (v1 puts in body, v2 puts in header)
442
+ *
443
+ * @param paymentRequired - Payment required object
444
+ * @returns Headers and body for the HTTP response
445
+ */
446
+ createHTTPPaymentRequiredResponse(paymentRequired) {
447
+ return {
448
+ headers: {
449
+ "PAYMENT-REQUIRED": encodePaymentRequiredHeader(paymentRequired)
450
+ }
451
+ };
452
+ }
453
+ /**
454
+ * Create settlement response headers
455
+ *
456
+ * @param settleResponse - Settlement response
457
+ * @param requirements - Payment requirements that were settled
458
+ * @returns Headers to add to response
459
+ */
460
+ createSettlementHeaders(settleResponse, requirements) {
461
+ const encoded = encodePaymentResponseHeader({
462
+ ...settleResponse,
463
+ requirements
464
+ });
465
+ return { "PAYMENT-RESPONSE": encoded };
466
+ }
467
+ /**
468
+ * Parse route pattern into verb and regex
469
+ *
470
+ * @param pattern - Route pattern like "GET /api/*" or "/api/[id]"
471
+ * @returns Parsed pattern with verb and regex
472
+ */
473
+ parseRoutePattern(pattern) {
474
+ const [verb, path] = pattern.includes(" ") ? pattern.split(/\s+/) : ["*", pattern];
475
+ const regex = new RegExp(
476
+ `^${path.replace(/[$()+.?^{|}]/g, "\\$&").replace(/\*/g, ".*?").replace(/\[([^\]]+)\]/g, "[^/]+").replace(/\//g, "\\/")}$`,
477
+ "i"
478
+ );
479
+ return { verb: verb.toUpperCase(), regex };
480
+ }
481
+ /**
482
+ * Normalize path for matching
483
+ *
484
+ * @param path - Raw path from request
485
+ * @returns Normalized path
486
+ */
487
+ normalizePath(path) {
488
+ try {
489
+ const pathWithoutQuery = path.split(/[?#]/)[0];
490
+ const decodedPath = decodeURIComponent(pathWithoutQuery);
491
+ return decodedPath.replace(/\\/g, "/").replace(/\/+/g, "/").replace(/(.+?)\/+$/, "$1");
492
+ } catch {
493
+ return path;
494
+ }
495
+ }
496
+ /**
497
+ * Generate paywall HTML for browser requests
498
+ *
499
+ * @param paymentRequired - Payment required response
500
+ * @param paywallConfig - Optional paywall configuration
501
+ * @param customHtml - Optional custom HTML template
502
+ * @returns HTML string
503
+ */
504
+ generatePaywallHTML(paymentRequired, paywallConfig, customHtml) {
505
+ if (customHtml) {
506
+ return customHtml;
507
+ }
508
+ if (this.paywallProvider) {
509
+ return this.paywallProvider.generateHtml(paymentRequired, paywallConfig);
510
+ }
511
+ try {
512
+ const paywall = require("@x402/paywall");
513
+ const displayAmount2 = this.getDisplayAmount(paymentRequired);
514
+ const resource2 = paymentRequired.resource;
515
+ return paywall.getPaywallHtml({
516
+ amount: displayAmount2,
517
+ paymentRequired,
518
+ currentUrl: resource2?.url || paywallConfig?.currentUrl || "",
519
+ testnet: paywallConfig?.testnet ?? true,
520
+ appName: paywallConfig?.appName,
521
+ appLogo: paywallConfig?.appLogo,
522
+ sessionTokenEndpoint: paywallConfig?.sessionTokenEndpoint
523
+ });
524
+ } catch {
525
+ }
526
+ const resource = paymentRequired.resource;
527
+ const displayAmount = this.getDisplayAmount(paymentRequired);
528
+ return `
529
+ <!DOCTYPE html>
530
+ <html>
531
+ <head>
532
+ <title>Payment Required</title>
533
+ <meta charset="UTF-8">
534
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
535
+ </head>
536
+ <body>
537
+ <div style="max-width: 600px; margin: 50px auto; padding: 20px; font-family: system-ui, -apple-system, sans-serif;">
538
+ ${paywallConfig?.appLogo ? `<img src="${paywallConfig.appLogo}" alt="${paywallConfig.appName || "App"}" style="max-width: 200px; margin-bottom: 20px;">` : ""}
539
+ <h1>Payment Required</h1>
540
+ ${resource ? `<p><strong>Resource:</strong> ${resource.description || resource.url}</p>` : ""}
541
+ <p><strong>Amount:</strong> $${displayAmount.toFixed(2)} USDC</p>
542
+ <div id="payment-widget"
543
+ data-requirements='${JSON.stringify(paymentRequired)}'
544
+ data-app-name="${paywallConfig?.appName || ""}"
545
+ data-testnet="${paywallConfig?.testnet || false}">
546
+ <!-- Install @x402/paywall for full wallet integration -->
547
+ <p style="margin-top: 2rem; padding: 1rem; background: #fef3c7; border-radius: 0.5rem;">
548
+ <strong>Note:</strong> Install <code>@x402/paywall</code> for full wallet connection and payment UI.
549
+ </p>
550
+ </div>
551
+ </div>
552
+ </body>
553
+ </html>
554
+ `;
555
+ }
556
+ /**
557
+ * Extract display amount from payment requirements.
558
+ *
559
+ * @param paymentRequired - The payment required object
560
+ * @returns The display amount in decimal format
561
+ */
562
+ getDisplayAmount(paymentRequired) {
563
+ const accepts = paymentRequired.accepts;
564
+ if (accepts && accepts.length > 0) {
565
+ const firstReq = accepts[0];
566
+ if ("amount" in firstReq) {
567
+ return parseFloat(firstReq.amount) / 1e6;
568
+ }
569
+ }
570
+ return 0;
571
+ }
572
+ };
573
+
574
+ // src/http/httpFacilitatorClient.ts
575
+ var DEFAULT_FACILITATOR_URL = "https://x402.org/facilitator";
576
+ var HTTPFacilitatorClient = class {
577
+ /**
578
+ * Creates a new HTTPFacilitatorClient instance.
579
+ *
580
+ * @param config - Configuration options for the facilitator client
581
+ */
582
+ constructor(config) {
583
+ this.url = config?.url || DEFAULT_FACILITATOR_URL;
584
+ this._createAuthHeaders = config?.createAuthHeaders;
585
+ }
586
+ /**
587
+ * Verify a payment with the facilitator
588
+ *
589
+ * @param paymentPayload - The payment to verify
590
+ * @param paymentRequirements - The requirements to verify against
591
+ * @returns Verification response
592
+ */
593
+ async verify(paymentPayload, paymentRequirements) {
594
+ let headers = {
595
+ "Content-Type": "application/json"
596
+ };
597
+ if (this._createAuthHeaders) {
598
+ const authHeaders = await this.createAuthHeaders("verify");
599
+ headers = { ...headers, ...authHeaders.headers };
600
+ }
601
+ const response = await fetch(`${this.url}/verify`, {
602
+ method: "POST",
603
+ headers,
604
+ body: JSON.stringify({
605
+ x402Version: paymentPayload.x402Version,
606
+ paymentPayload: this.toJsonSafe(paymentPayload),
607
+ paymentRequirements: this.toJsonSafe(paymentRequirements)
608
+ })
609
+ });
610
+ const data = await response.json();
611
+ if (typeof data === "object" && data !== null && "isValid" in data) {
612
+ const verifyResponse = data;
613
+ if (!response.ok) {
614
+ throw new VerifyError(response.status, verifyResponse);
615
+ }
616
+ return verifyResponse;
617
+ }
618
+ throw new Error(`Facilitator verify failed (${response.status}): ${JSON.stringify(data)}`);
619
+ }
620
+ /**
621
+ * Settle a payment with the facilitator
622
+ *
623
+ * @param paymentPayload - The payment to settle
624
+ * @param paymentRequirements - The requirements for settlement
625
+ * @returns Settlement response
626
+ */
627
+ async settle(paymentPayload, paymentRequirements) {
628
+ let headers = {
629
+ "Content-Type": "application/json"
630
+ };
631
+ if (this._createAuthHeaders) {
632
+ const authHeaders = await this.createAuthHeaders("settle");
633
+ headers = { ...headers, ...authHeaders.headers };
634
+ }
635
+ const response = await fetch(`${this.url}/settle`, {
636
+ method: "POST",
637
+ headers,
638
+ body: JSON.stringify({
639
+ x402Version: paymentPayload.x402Version,
640
+ paymentPayload: this.toJsonSafe(paymentPayload),
641
+ paymentRequirements: this.toJsonSafe(paymentRequirements)
642
+ })
643
+ });
644
+ const data = await response.json();
645
+ if (typeof data === "object" && data !== null && "success" in data) {
646
+ const settleResponse = data;
647
+ if (!response.ok) {
648
+ throw new SettleError(response.status, settleResponse);
649
+ }
650
+ return settleResponse;
651
+ }
652
+ throw new Error(`Facilitator settle failed (${response.status}): ${JSON.stringify(data)}`);
653
+ }
654
+ /**
655
+ * Get supported payment kinds and extensions from the facilitator
656
+ *
657
+ * @returns Supported payment kinds and extensions
658
+ */
659
+ async getSupported() {
660
+ let headers = {
661
+ "Content-Type": "application/json"
662
+ };
663
+ if (this._createAuthHeaders) {
664
+ const authHeaders = await this.createAuthHeaders("supported");
665
+ headers = { ...headers, ...authHeaders.headers };
666
+ }
667
+ const response = await fetch(`${this.url}/supported`, {
668
+ method: "GET",
669
+ headers
670
+ });
671
+ if (!response.ok) {
672
+ const errorText = await response.text().catch(() => response.statusText);
673
+ throw new Error(`Facilitator getSupported failed (${response.status}): ${errorText}`);
674
+ }
675
+ return await response.json();
676
+ }
677
+ /**
678
+ * Creates authentication headers for a specific path.
679
+ *
680
+ * @param path - The path to create authentication headers for (e.g., "verify", "settle", "supported")
681
+ * @returns An object containing the authentication headers for the specified path
682
+ */
683
+ async createAuthHeaders(path) {
684
+ if (this._createAuthHeaders) {
685
+ const authHeaders = await this._createAuthHeaders();
686
+ return {
687
+ headers: authHeaders[path] ?? {}
688
+ };
689
+ }
690
+ return {
691
+ headers: {}
692
+ };
693
+ }
694
+ /**
695
+ * Helper to convert objects to JSON-safe format.
696
+ * Handles BigInt and other non-JSON types.
697
+ *
698
+ * @param obj - The object to convert
699
+ * @returns The JSON-safe representation of the object
700
+ */
701
+ toJsonSafe(obj) {
702
+ return JSON.parse(
703
+ JSON.stringify(obj, (_, value) => typeof value === "bigint" ? value.toString() : value)
704
+ );
705
+ }
706
+ };
707
+
708
+ // src/http/x402HTTPClient.ts
709
+ var x402HTTPClient = class {
710
+ /**
711
+ * Creates a new x402HTTPClient instance.
712
+ *
713
+ * @param client - The underlying x402Client for payment logic
714
+ */
715
+ constructor(client) {
716
+ this.client = client;
717
+ }
718
+ /**
719
+ * Encodes a payment payload into appropriate HTTP headers based on version.
720
+ *
721
+ * @param paymentPayload - The payment payload to encode
722
+ * @returns HTTP headers containing the encoded payment signature
723
+ */
724
+ encodePaymentSignatureHeader(paymentPayload) {
725
+ switch (paymentPayload.x402Version) {
726
+ case 2:
727
+ return {
728
+ "PAYMENT-SIGNATURE": encodePaymentSignatureHeader(paymentPayload)
729
+ };
730
+ case 1:
731
+ return {
732
+ "X-PAYMENT": encodePaymentSignatureHeader(paymentPayload)
733
+ };
734
+ default:
735
+ throw new Error(
736
+ `Unsupported x402 version: ${paymentPayload.x402Version}`
737
+ );
738
+ }
739
+ }
740
+ /**
741
+ * Extracts payment required information from HTTP response.
742
+ *
743
+ * @param getHeader - Function to retrieve header value by name (case-insensitive)
744
+ * @param body - Optional response body for v1 compatibility
745
+ * @returns The payment required object
746
+ */
747
+ getPaymentRequiredResponse(getHeader, body) {
748
+ const paymentRequired = getHeader("PAYMENT-REQUIRED");
749
+ if (paymentRequired) {
750
+ return decodePaymentRequiredHeader(paymentRequired);
751
+ }
752
+ if (body && body instanceof Object && "x402Version" in body && body.x402Version === 1) {
753
+ return body;
754
+ }
755
+ throw new Error("Invalid payment required response");
756
+ }
757
+ /**
758
+ * Extracts payment settlement response from HTTP headers.
759
+ *
760
+ * @param getHeader - Function to retrieve header value by name (case-insensitive)
761
+ * @returns The settlement response object
762
+ */
763
+ getPaymentSettleResponse(getHeader) {
764
+ const paymentResponse = getHeader("PAYMENT-RESPONSE");
765
+ if (paymentResponse) {
766
+ return decodePaymentResponseHeader(paymentResponse);
767
+ }
768
+ const xPaymentResponse = getHeader("X-PAYMENT-RESPONSE");
769
+ if (xPaymentResponse) {
770
+ return decodePaymentResponseHeader(xPaymentResponse);
771
+ }
772
+ throw new Error("Payment response header not found");
773
+ }
774
+ /**
775
+ * Creates a payment payload for the given payment requirements.
776
+ * Delegates to the underlying x402Client.
777
+ *
778
+ * @param paymentRequired - The payment required response from the server
779
+ * @returns Promise resolving to the payment payload
780
+ */
781
+ async createPaymentPayload(paymentRequired) {
782
+ return this.client.createPaymentPayload(paymentRequired);
783
+ }
784
+ };
785
+
786
+ // src/http/index.ts
787
+ function encodePaymentSignatureHeader(paymentPayload) {
788
+ return safeBase64Encode(JSON.stringify(paymentPayload));
789
+ }
790
+ function decodePaymentSignatureHeader(paymentSignatureHeader) {
791
+ if (!Base64EncodedRegex.test(paymentSignatureHeader)) {
792
+ throw new Error("Invalid payment signature header");
793
+ }
794
+ return JSON.parse(safeBase64Decode(paymentSignatureHeader));
795
+ }
796
+ function encodePaymentRequiredHeader(paymentRequired) {
797
+ return safeBase64Encode(JSON.stringify(paymentRequired));
798
+ }
799
+ function decodePaymentRequiredHeader(paymentRequiredHeader) {
800
+ if (!Base64EncodedRegex.test(paymentRequiredHeader)) {
801
+ throw new Error("Invalid payment required header");
802
+ }
803
+ return JSON.parse(safeBase64Decode(paymentRequiredHeader));
804
+ }
805
+ function encodePaymentResponseHeader(paymentResponse) {
806
+ return safeBase64Encode(JSON.stringify(paymentResponse));
807
+ }
808
+ function decodePaymentResponseHeader(paymentResponseHeader) {
809
+ if (!Base64EncodedRegex.test(paymentResponseHeader)) {
810
+ throw new Error("Invalid payment response header");
811
+ }
812
+ return JSON.parse(safeBase64Decode(paymentResponseHeader));
813
+ }
814
+ // Annotate the CommonJS export names for ESM import in node:
815
+ 0 && (module.exports = {
816
+ HTTPFacilitatorClient,
817
+ RouteConfigurationError,
818
+ decodePaymentRequiredHeader,
819
+ decodePaymentResponseHeader,
820
+ decodePaymentSignatureHeader,
821
+ encodePaymentRequiredHeader,
822
+ encodePaymentResponseHeader,
823
+ encodePaymentSignatureHeader,
824
+ x402HTTPClient,
825
+ x402HTTPResourceServer
826
+ });
827
+ //# sourceMappingURL=index.js.map