@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,712 @@
1
+ import {
2
+ HTTPFacilitatorClient,
3
+ RouteConfigurationError,
4
+ x402HTTPResourceServer
5
+ } from "../chunk-DACUCTGT.mjs";
6
+ import {
7
+ convertMoney,
8
+ globalAssetRegistry,
9
+ x402Version
10
+ } from "../chunk-DFUINDLZ.mjs";
11
+ import {
12
+ SettleError,
13
+ VerifyError
14
+ } from "../chunk-HRQUGJ3Y.mjs";
15
+ import {
16
+ deepEqual,
17
+ findByNetworkAndScheme
18
+ } from "../chunk-TDLQZ6MP.mjs";
19
+ import "../chunk-BJTO5JO5.mjs";
20
+
21
+ // src/server/x402ResourceServer.ts
22
+ var x402ResourceServer = class {
23
+ /**
24
+ * Creates a new x402ResourceServer instance.
25
+ *
26
+ * @param facilitatorClients - Optional facilitator client(s) for payment processing
27
+ * @param assetRegistry - Optional asset registry for symbol-based asset resolution
28
+ */
29
+ constructor(facilitatorClients, assetRegistry) {
30
+ this.registeredServerSchemes = /* @__PURE__ */ new Map();
31
+ this.supportedResponsesMap = /* @__PURE__ */ new Map();
32
+ this.facilitatorClientsMap = /* @__PURE__ */ new Map();
33
+ this.registeredExtensions = /* @__PURE__ */ new Map();
34
+ this.beforeVerifyHooks = [];
35
+ this.afterVerifyHooks = [];
36
+ this.onVerifyFailureHooks = [];
37
+ this.beforeSettleHooks = [];
38
+ this.afterSettleHooks = [];
39
+ this.onSettleFailureHooks = [];
40
+ this.assetRegistry = assetRegistry ?? globalAssetRegistry;
41
+ if (!facilitatorClients) {
42
+ this.facilitatorClients = [new HTTPFacilitatorClient()];
43
+ } else if (Array.isArray(facilitatorClients)) {
44
+ this.facilitatorClients = facilitatorClients.length > 0 ? facilitatorClients : [new HTTPFacilitatorClient()];
45
+ } else {
46
+ this.facilitatorClients = [facilitatorClients];
47
+ }
48
+ }
49
+ /**
50
+ * Register a scheme/network server implementation.
51
+ *
52
+ * @param network - The network identifier
53
+ * @param server - The scheme/network server implementation
54
+ * @returns The x402ResourceServer instance for chaining
55
+ */
56
+ register(network, server) {
57
+ if (!this.registeredServerSchemes.has(network)) {
58
+ this.registeredServerSchemes.set(network, /* @__PURE__ */ new Map());
59
+ }
60
+ const serverByScheme = this.registeredServerSchemes.get(network);
61
+ if (!serverByScheme.has(server.scheme)) {
62
+ serverByScheme.set(server.scheme, server);
63
+ }
64
+ return this;
65
+ }
66
+ /**
67
+ * Check if a scheme is registered for a given network.
68
+ *
69
+ * @param network - The network identifier
70
+ * @param scheme - The payment scheme name
71
+ * @returns True if the scheme is registered for the network, false otherwise
72
+ */
73
+ hasRegisteredScheme(network, scheme) {
74
+ return !!findByNetworkAndScheme(this.registeredServerSchemes, scheme, network);
75
+ }
76
+ /**
77
+ * Registers a resource service extension that can enrich extension declarations.
78
+ *
79
+ * @param extension - The extension to register
80
+ * @returns The x402ResourceServer instance for chaining
81
+ */
82
+ registerExtension(extension) {
83
+ this.registeredExtensions.set(extension.key, extension);
84
+ return this;
85
+ }
86
+ /**
87
+ * Check if an extension is registered.
88
+ *
89
+ * @param key - The extension key
90
+ * @returns True if the extension is registered
91
+ */
92
+ hasExtension(key) {
93
+ return this.registeredExtensions.has(key);
94
+ }
95
+ /**
96
+ * Get all registered extensions.
97
+ *
98
+ * @returns Array of registered extensions
99
+ */
100
+ getExtensions() {
101
+ return Array.from(this.registeredExtensions.values());
102
+ }
103
+ /**
104
+ * Enriches declared extensions using registered extension hooks.
105
+ *
106
+ * @param declaredExtensions - Extensions declared on the route
107
+ * @param transportContext - Transport-specific context (HTTP, A2A, MCP, etc.)
108
+ * @returns Enriched extensions map
109
+ */
110
+ enrichExtensions(declaredExtensions, transportContext) {
111
+ const enriched = {};
112
+ for (const [key, declaration] of Object.entries(declaredExtensions)) {
113
+ const extension = this.registeredExtensions.get(key);
114
+ if (extension?.enrichDeclaration) {
115
+ enriched[key] = extension.enrichDeclaration(declaration, transportContext);
116
+ } else {
117
+ enriched[key] = declaration;
118
+ }
119
+ }
120
+ return enriched;
121
+ }
122
+ /**
123
+ * Register a hook to execute before payment verification.
124
+ * Can abort verification by returning { abort: true, reason: string }
125
+ *
126
+ * @param hook - The hook function to register
127
+ * @returns The x402ResourceServer instance for chaining
128
+ */
129
+ onBeforeVerify(hook) {
130
+ this.beforeVerifyHooks.push(hook);
131
+ return this;
132
+ }
133
+ /**
134
+ * Register a hook to execute after successful payment verification.
135
+ *
136
+ * @param hook - The hook function to register
137
+ * @returns The x402ResourceServer instance for chaining
138
+ */
139
+ onAfterVerify(hook) {
140
+ this.afterVerifyHooks.push(hook);
141
+ return this;
142
+ }
143
+ /**
144
+ * Register a hook to execute when payment verification fails.
145
+ * Can recover from failure by returning { recovered: true, result: VerifyResponse }
146
+ *
147
+ * @param hook - The hook function to register
148
+ * @returns The x402ResourceServer instance for chaining
149
+ */
150
+ onVerifyFailure(hook) {
151
+ this.onVerifyFailureHooks.push(hook);
152
+ return this;
153
+ }
154
+ /**
155
+ * Register a hook to execute before payment settlement.
156
+ * Can abort settlement by returning { abort: true, reason: string }
157
+ *
158
+ * @param hook - The hook function to register
159
+ * @returns The x402ResourceServer instance for chaining
160
+ */
161
+ onBeforeSettle(hook) {
162
+ this.beforeSettleHooks.push(hook);
163
+ return this;
164
+ }
165
+ /**
166
+ * Register a hook to execute after successful payment settlement.
167
+ *
168
+ * @param hook - The hook function to register
169
+ * @returns The x402ResourceServer instance for chaining
170
+ */
171
+ onAfterSettle(hook) {
172
+ this.afterSettleHooks.push(hook);
173
+ return this;
174
+ }
175
+ /**
176
+ * Register a hook to execute when payment settlement fails.
177
+ * Can recover from failure by returning { recovered: true, result: SettleResponse }
178
+ *
179
+ * @param hook - The hook function to register
180
+ * @returns The x402ResourceServer instance for chaining
181
+ */
182
+ onSettleFailure(hook) {
183
+ this.onSettleFailureHooks.push(hook);
184
+ return this;
185
+ }
186
+ /**
187
+ * Initialize by fetching supported kinds from all facilitators
188
+ * Creates mappings for supported responses and facilitator clients
189
+ * Earlier facilitators in the array get precedence
190
+ */
191
+ async initialize() {
192
+ this.supportedResponsesMap.clear();
193
+ this.facilitatorClientsMap.clear();
194
+ for (const facilitatorClient of this.facilitatorClients) {
195
+ try {
196
+ const supported = await facilitatorClient.getSupported();
197
+ for (const kind of supported.kinds) {
198
+ const x402Version2 = kind.x402Version;
199
+ if (!this.supportedResponsesMap.has(x402Version2)) {
200
+ this.supportedResponsesMap.set(x402Version2, /* @__PURE__ */ new Map());
201
+ }
202
+ const responseVersionMap = this.supportedResponsesMap.get(x402Version2);
203
+ if (!this.facilitatorClientsMap.has(x402Version2)) {
204
+ this.facilitatorClientsMap.set(x402Version2, /* @__PURE__ */ new Map());
205
+ }
206
+ const clientVersionMap = this.facilitatorClientsMap.get(x402Version2);
207
+ if (!responseVersionMap.has(kind.network)) {
208
+ responseVersionMap.set(kind.network, /* @__PURE__ */ new Map());
209
+ }
210
+ const responseNetworkMap = responseVersionMap.get(kind.network);
211
+ if (!clientVersionMap.has(kind.network)) {
212
+ clientVersionMap.set(kind.network, /* @__PURE__ */ new Map());
213
+ }
214
+ const clientNetworkMap = clientVersionMap.get(kind.network);
215
+ if (!responseNetworkMap.has(kind.scheme)) {
216
+ responseNetworkMap.set(kind.scheme, supported);
217
+ clientNetworkMap.set(kind.scheme, facilitatorClient);
218
+ }
219
+ }
220
+ } catch (error) {
221
+ console.warn(`Failed to fetch supported kinds from facilitator: ${error}`);
222
+ }
223
+ }
224
+ if (this.supportedResponsesMap.size === 0) {
225
+ throw new Error(
226
+ "Failed to initialize: no supported payment kinds loaded from any facilitator."
227
+ );
228
+ }
229
+ }
230
+ /**
231
+ * Get supported kind for a specific version, network, and scheme
232
+ *
233
+ * @param x402Version - The x402 version
234
+ * @param network - The network identifier
235
+ * @param scheme - The payment scheme
236
+ * @returns The supported kind or undefined if not found
237
+ */
238
+ getSupportedKind(x402Version2, network, scheme) {
239
+ const versionMap = this.supportedResponsesMap.get(x402Version2);
240
+ if (!versionMap) return void 0;
241
+ const supportedResponse = findByNetworkAndScheme(versionMap, scheme, network);
242
+ if (!supportedResponse) return void 0;
243
+ return supportedResponse.kinds.find(
244
+ (kind) => kind.x402Version === x402Version2 && kind.network === network && kind.scheme === scheme
245
+ );
246
+ }
247
+ /**
248
+ * Get facilitator extensions for a specific version, network, and scheme
249
+ *
250
+ * @param x402Version - The x402 version
251
+ * @param network - The network identifier
252
+ * @param scheme - The payment scheme
253
+ * @returns The facilitator extensions or empty array if not found
254
+ */
255
+ getFacilitatorExtensions(x402Version2, network, scheme) {
256
+ const versionMap = this.supportedResponsesMap.get(x402Version2);
257
+ if (!versionMap) return [];
258
+ const supportedResponse = findByNetworkAndScheme(versionMap, scheme, network);
259
+ return supportedResponse?.extensions || [];
260
+ }
261
+ /**
262
+ * Build payment requirements for a protected resource
263
+ *
264
+ * @param resourceConfig - Configuration for the protected resource
265
+ * @returns Array of payment requirements
266
+ */
267
+ async buildPaymentRequirements(resourceConfig) {
268
+ const requirements = [];
269
+ const scheme = resourceConfig.scheme;
270
+ const SchemeNetworkServer = findByNetworkAndScheme(
271
+ this.registeredServerSchemes,
272
+ scheme,
273
+ resourceConfig.network
274
+ );
275
+ if (!SchemeNetworkServer) {
276
+ console.warn(
277
+ `No server implementation registered for scheme: ${scheme}, network: ${resourceConfig.network}`
278
+ );
279
+ return requirements;
280
+ }
281
+ const supportedKind = this.getSupportedKind(
282
+ x402Version,
283
+ resourceConfig.network,
284
+ SchemeNetworkServer.scheme
285
+ );
286
+ if (!supportedKind) {
287
+ throw new Error(
288
+ `Facilitator does not support ${SchemeNetworkServer.scheme} on ${resourceConfig.network}. Make sure to call initialize() to fetch supported kinds from facilitators.`
289
+ );
290
+ }
291
+ const facilitatorExtensions = this.getFacilitatorExtensions(
292
+ x402Version,
293
+ resourceConfig.network,
294
+ SchemeNetworkServer.scheme
295
+ );
296
+ if (resourceConfig.assets?.length && (typeof resourceConfig.price === "string" || typeof resourceConfig.price === "number")) {
297
+ const results = [];
298
+ for (const symbol of resourceConfig.assets) {
299
+ const assetInfo = this.assetRegistry.resolve(resourceConfig.network, symbol);
300
+ const amount = convertMoney(resourceConfig.price, assetInfo.decimals);
301
+ const { address, decimals, name, version, assetTransferMethod, supportsEip2612, ...rest } = assetInfo;
302
+ const includeEip712Domain = !assetTransferMethod || supportsEip2612;
303
+ const extra = {
304
+ ...includeEip712Domain && name && { name },
305
+ ...includeEip712Domain && version && { version },
306
+ ...assetTransferMethod && { assetTransferMethod },
307
+ ...rest,
308
+ ...resourceConfig.extra
309
+ };
310
+ const baseReq = {
311
+ scheme: SchemeNetworkServer.scheme,
312
+ network: resourceConfig.network,
313
+ amount,
314
+ asset: address,
315
+ payTo: resourceConfig.payTo,
316
+ maxTimeoutSeconds: resourceConfig.maxTimeoutSeconds || 300,
317
+ extra
318
+ };
319
+ const enhanced = await SchemeNetworkServer.enhancePaymentRequirements(
320
+ baseReq,
321
+ { ...supportedKind, x402Version },
322
+ facilitatorExtensions
323
+ );
324
+ results.push(enhanced);
325
+ }
326
+ return results;
327
+ }
328
+ const parsedPrice = await SchemeNetworkServer.parsePrice(
329
+ resourceConfig.price,
330
+ resourceConfig.network
331
+ );
332
+ const baseRequirements = {
333
+ scheme: SchemeNetworkServer.scheme,
334
+ network: resourceConfig.network,
335
+ amount: parsedPrice.amount,
336
+ asset: parsedPrice.asset,
337
+ payTo: resourceConfig.payTo,
338
+ maxTimeoutSeconds: resourceConfig.maxTimeoutSeconds || 300,
339
+ // Default 5 minutes
340
+ extra: {
341
+ ...parsedPrice.extra,
342
+ ...resourceConfig.extra
343
+ // Merge user-provided extra
344
+ }
345
+ };
346
+ const requirement = await SchemeNetworkServer.enhancePaymentRequirements(
347
+ baseRequirements,
348
+ {
349
+ ...supportedKind,
350
+ x402Version
351
+ },
352
+ facilitatorExtensions
353
+ );
354
+ requirements.push(requirement);
355
+ return requirements;
356
+ }
357
+ /**
358
+ * Build payment requirements from multiple payment options
359
+ * This method handles resolving dynamic payTo/price functions and builds requirements for each option
360
+ *
361
+ * @param paymentOptions - Array of payment options to convert
362
+ * @param context - HTTP request context for resolving dynamic functions
363
+ * @returns Array of payment requirements (one per option)
364
+ */
365
+ async buildPaymentRequirementsFromOptions(paymentOptions, context) {
366
+ const allRequirements = [];
367
+ for (const option of paymentOptions) {
368
+ const resolvedPayTo = typeof option.payTo === "function" ? await option.payTo(context) : option.payTo;
369
+ const resolvedPrice = typeof option.price === "function" ? await option.price(context) : option.price;
370
+ const resourceConfig = {
371
+ scheme: option.scheme,
372
+ payTo: resolvedPayTo,
373
+ price: resolvedPrice,
374
+ network: option.network,
375
+ maxTimeoutSeconds: option.maxTimeoutSeconds,
376
+ extra: option.extra,
377
+ assets: option.assets
378
+ };
379
+ const requirements = await this.buildPaymentRequirements(resourceConfig);
380
+ allRequirements.push(...requirements);
381
+ }
382
+ return allRequirements;
383
+ }
384
+ /**
385
+ * Create a payment required response
386
+ *
387
+ * @param requirements - Payment requirements
388
+ * @param resourceInfo - Resource information
389
+ * @param error - Error message
390
+ * @param extensions - Optional declared extensions (for per-key enrichment)
391
+ * @param transportContext - Optional transport-specific context (e.g., HTTP request, MCP tool context)
392
+ * @returns Payment required response object
393
+ */
394
+ async createPaymentRequiredResponse(requirements, resourceInfo, error, extensions, transportContext) {
395
+ let response = {
396
+ x402Version: 2,
397
+ error,
398
+ resource: resourceInfo,
399
+ accepts: requirements
400
+ };
401
+ if (extensions && Object.keys(extensions).length > 0) {
402
+ response.extensions = extensions;
403
+ }
404
+ if (extensions) {
405
+ for (const [key, declaration] of Object.entries(extensions)) {
406
+ const extension = this.registeredExtensions.get(key);
407
+ if (extension?.enrichPaymentRequiredResponse) {
408
+ try {
409
+ const context = {
410
+ requirements,
411
+ resourceInfo,
412
+ error,
413
+ paymentRequiredResponse: response,
414
+ transportContext
415
+ };
416
+ const extensionData = await extension.enrichPaymentRequiredResponse(
417
+ declaration,
418
+ context
419
+ );
420
+ if (extensionData !== void 0) {
421
+ if (!response.extensions) {
422
+ response.extensions = {};
423
+ }
424
+ response.extensions[key] = extensionData;
425
+ }
426
+ } catch (error2) {
427
+ console.error(
428
+ `Error in enrichPaymentRequiredResponse hook for extension ${key}:`,
429
+ error2
430
+ );
431
+ }
432
+ }
433
+ }
434
+ }
435
+ return response;
436
+ }
437
+ /**
438
+ * Verify a payment against requirements
439
+ *
440
+ * @param paymentPayload - The payment payload to verify
441
+ * @param requirements - The payment requirements
442
+ * @returns Verification response
443
+ */
444
+ async verifyPayment(paymentPayload, requirements) {
445
+ const context = {
446
+ paymentPayload,
447
+ requirements
448
+ };
449
+ for (const hook of this.beforeVerifyHooks) {
450
+ try {
451
+ const result = await hook(context);
452
+ if (result && "abort" in result && result.abort) {
453
+ return {
454
+ isValid: false,
455
+ invalidReason: result.reason,
456
+ invalidMessage: result.message
457
+ };
458
+ }
459
+ } catch (error) {
460
+ throw new VerifyError(400, {
461
+ isValid: false,
462
+ invalidReason: "before_verify_hook_error",
463
+ invalidMessage: error instanceof Error ? error.message : ""
464
+ });
465
+ }
466
+ }
467
+ try {
468
+ const facilitatorClient = this.getFacilitatorClient(
469
+ paymentPayload.x402Version,
470
+ requirements.network,
471
+ requirements.scheme
472
+ );
473
+ let verifyResult;
474
+ if (!facilitatorClient) {
475
+ let lastError;
476
+ for (const client of this.facilitatorClients) {
477
+ try {
478
+ verifyResult = await client.verify(paymentPayload, requirements);
479
+ break;
480
+ } catch (error) {
481
+ lastError = error;
482
+ }
483
+ }
484
+ if (!verifyResult) {
485
+ throw lastError || new Error(
486
+ `No facilitator supports ${requirements.scheme} on ${requirements.network} for v${paymentPayload.x402Version}`
487
+ );
488
+ }
489
+ } else {
490
+ verifyResult = await facilitatorClient.verify(paymentPayload, requirements);
491
+ }
492
+ const resultContext = {
493
+ ...context,
494
+ result: verifyResult
495
+ };
496
+ for (const hook of this.afterVerifyHooks) {
497
+ await hook(resultContext);
498
+ }
499
+ return verifyResult;
500
+ } catch (error) {
501
+ const failureContext = {
502
+ ...context,
503
+ error
504
+ };
505
+ for (const hook of this.onVerifyFailureHooks) {
506
+ const result = await hook(failureContext);
507
+ if (result && "recovered" in result && result.recovered) {
508
+ return result.result;
509
+ }
510
+ }
511
+ throw error;
512
+ }
513
+ }
514
+ /**
515
+ * Settle a verified payment
516
+ *
517
+ * @param paymentPayload - The payment payload to settle
518
+ * @param requirements - The payment requirements
519
+ * @param declaredExtensions - Optional declared extensions (for per-key enrichment)
520
+ * @param transportContext - Optional transport-specific context (e.g., HTTP request/response, MCP tool context)
521
+ * @returns Settlement response
522
+ */
523
+ async settlePayment(paymentPayload, requirements, declaredExtensions, transportContext) {
524
+ const context = {
525
+ paymentPayload,
526
+ requirements
527
+ };
528
+ for (const hook of this.beforeSettleHooks) {
529
+ try {
530
+ const result = await hook(context);
531
+ if (result && "abort" in result && result.abort) {
532
+ throw new SettleError(400, {
533
+ success: false,
534
+ errorReason: result.reason,
535
+ errorMessage: result.message,
536
+ transaction: "",
537
+ network: requirements.network
538
+ });
539
+ }
540
+ } catch (error) {
541
+ if (error instanceof SettleError) {
542
+ throw error;
543
+ }
544
+ throw new SettleError(400, {
545
+ success: false,
546
+ errorReason: "before_settle_hook_error",
547
+ errorMessage: error instanceof Error ? error.message : "",
548
+ transaction: "",
549
+ network: requirements.network
550
+ });
551
+ }
552
+ }
553
+ try {
554
+ const facilitatorClient = this.getFacilitatorClient(
555
+ paymentPayload.x402Version,
556
+ requirements.network,
557
+ requirements.scheme
558
+ );
559
+ let settleResult;
560
+ if (!facilitatorClient) {
561
+ let lastError;
562
+ for (const client of this.facilitatorClients) {
563
+ try {
564
+ settleResult = await client.settle(paymentPayload, requirements);
565
+ break;
566
+ } catch (error) {
567
+ lastError = error;
568
+ }
569
+ }
570
+ if (!settleResult) {
571
+ throw lastError || new Error(
572
+ `No facilitator supports ${requirements.scheme} on ${requirements.network} for v${paymentPayload.x402Version}`
573
+ );
574
+ }
575
+ } else {
576
+ settleResult = await facilitatorClient.settle(paymentPayload, requirements);
577
+ }
578
+ const resultContext = {
579
+ ...context,
580
+ result: settleResult,
581
+ transportContext
582
+ };
583
+ for (const hook of this.afterSettleHooks) {
584
+ await hook(resultContext);
585
+ }
586
+ if (declaredExtensions) {
587
+ for (const [key, declaration] of Object.entries(declaredExtensions)) {
588
+ const extension = this.registeredExtensions.get(key);
589
+ if (extension?.enrichSettlementResponse) {
590
+ try {
591
+ const extensionData = await extension.enrichSettlementResponse(
592
+ declaration,
593
+ resultContext
594
+ );
595
+ if (extensionData !== void 0) {
596
+ if (!settleResult.extensions) {
597
+ settleResult.extensions = {};
598
+ }
599
+ settleResult.extensions[key] = extensionData;
600
+ }
601
+ } catch (error) {
602
+ console.error(`Error in enrichSettlementResponse hook for extension ${key}:`, error);
603
+ }
604
+ }
605
+ }
606
+ }
607
+ return settleResult;
608
+ } catch (error) {
609
+ const failureContext = {
610
+ ...context,
611
+ error
612
+ };
613
+ for (const hook of this.onSettleFailureHooks) {
614
+ const result = await hook(failureContext);
615
+ if (result && "recovered" in result && result.recovered) {
616
+ return result.result;
617
+ }
618
+ }
619
+ throw error;
620
+ }
621
+ }
622
+ /**
623
+ * Find matching payment requirements for a payment
624
+ *
625
+ * @param availableRequirements - Array of available payment requirements
626
+ * @param paymentPayload - The payment payload
627
+ * @returns Matching payment requirements or undefined
628
+ */
629
+ findMatchingRequirements(availableRequirements, paymentPayload) {
630
+ switch (paymentPayload.x402Version) {
631
+ case 2:
632
+ return availableRequirements.find(
633
+ (paymentRequirements) => deepEqual(paymentRequirements, paymentPayload.accepted)
634
+ );
635
+ case 1:
636
+ return availableRequirements.find(
637
+ (req) => req.scheme === paymentPayload.accepted.scheme && req.network === paymentPayload.accepted.network
638
+ );
639
+ default:
640
+ throw new Error(
641
+ `Unsupported x402 version: ${paymentPayload.x402Version}`
642
+ );
643
+ }
644
+ }
645
+ /**
646
+ * Process a payment request
647
+ *
648
+ * @param paymentPayload - Optional payment payload if provided
649
+ * @param resourceConfig - Configuration for the protected resource
650
+ * @param resourceInfo - Information about the resource being accessed
651
+ * @param extensions - Optional extensions to include in the response
652
+ * @returns Processing result
653
+ */
654
+ async processPaymentRequest(paymentPayload, resourceConfig, resourceInfo, extensions) {
655
+ const requirements = await this.buildPaymentRequirements(resourceConfig);
656
+ if (!paymentPayload) {
657
+ return {
658
+ success: false,
659
+ requiresPayment: await this.createPaymentRequiredResponse(
660
+ requirements,
661
+ resourceInfo,
662
+ "Payment required",
663
+ extensions
664
+ )
665
+ };
666
+ }
667
+ const matchingRequirements = this.findMatchingRequirements(requirements, paymentPayload);
668
+ if (!matchingRequirements) {
669
+ return {
670
+ success: false,
671
+ requiresPayment: await this.createPaymentRequiredResponse(
672
+ requirements,
673
+ resourceInfo,
674
+ "No matching payment requirements found",
675
+ extensions
676
+ )
677
+ };
678
+ }
679
+ const verificationResult = await this.verifyPayment(paymentPayload, matchingRequirements);
680
+ if (!verificationResult.isValid) {
681
+ return {
682
+ success: false,
683
+ error: verificationResult.invalidReason,
684
+ verificationResult
685
+ };
686
+ }
687
+ return {
688
+ success: true,
689
+ verificationResult
690
+ };
691
+ }
692
+ /**
693
+ * Get facilitator client for a specific version, network, and scheme
694
+ *
695
+ * @param x402Version - The x402 version
696
+ * @param network - The network identifier
697
+ * @param scheme - The payment scheme
698
+ * @returns The facilitator client or undefined if not found
699
+ */
700
+ getFacilitatorClient(x402Version2, network, scheme) {
701
+ const versionMap = this.facilitatorClientsMap.get(x402Version2);
702
+ if (!versionMap) return void 0;
703
+ return findByNetworkAndScheme(versionMap, scheme, network);
704
+ }
705
+ };
706
+ export {
707
+ HTTPFacilitatorClient,
708
+ RouteConfigurationError,
709
+ x402HTTPResourceServer,
710
+ x402ResourceServer
711
+ };
712
+ //# sourceMappingURL=index.mjs.map