x402-express-mantle 1.0.0 → 1.0.3

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