@nevermined-io/payments 1.7.0 → 1.9.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 (88) hide show
  1. package/README.md +2 -1
  2. package/dist/a2a/agent-card.d.ts +26 -0
  3. package/dist/a2a/agent-card.d.ts.map +1 -1
  4. package/dist/a2a/agent-card.js +36 -1
  5. package/dist/a2a/agent-card.js.map +1 -1
  6. package/dist/a2a/paymentsClient.d.ts +41 -1
  7. package/dist/a2a/paymentsClient.d.ts.map +1 -1
  8. package/dist/a2a/paymentsClient.js +120 -8
  9. package/dist/a2a/paymentsClient.js.map +1 -1
  10. package/dist/a2a/paymentsRequestHandler.d.ts +25 -2
  11. package/dist/a2a/paymentsRequestHandler.d.ts.map +1 -1
  12. package/dist/a2a/paymentsRequestHandler.js +240 -20
  13. package/dist/a2a/paymentsRequestHandler.js.map +1 -1
  14. package/dist/a2a/server.d.ts +2 -2
  15. package/dist/a2a/server.d.ts.map +1 -1
  16. package/dist/a2a/server.js +70 -20
  17. package/dist/a2a/server.js.map +1 -1
  18. package/dist/a2a/types.d.ts +31 -1
  19. package/dist/a2a/types.d.ts.map +1 -1
  20. package/dist/a2a/types.js.map +1 -1
  21. package/dist/a2a/x402-a2a.d.ts +142 -0
  22. package/dist/a2a/x402-a2a.d.ts.map +1 -0
  23. package/dist/a2a/x402-a2a.js +254 -0
  24. package/dist/a2a/x402-a2a.js.map +1 -0
  25. package/dist/api/agents-api.d.ts +19 -0
  26. package/dist/api/agents-api.d.ts.map +1 -1
  27. package/dist/api/agents-api.js +28 -1
  28. package/dist/api/agents-api.js.map +1 -1
  29. package/dist/api/nvm-api.d.ts +1 -0
  30. package/dist/api/nvm-api.d.ts.map +1 -1
  31. package/dist/api/nvm-api.js +4 -0
  32. package/dist/api/nvm-api.js.map +1 -1
  33. package/dist/api/plans-api.d.ts +12 -2
  34. package/dist/api/plans-api.d.ts.map +1 -1
  35. package/dist/api/plans-api.js +9 -2
  36. package/dist/api/plans-api.js.map +1 -1
  37. package/dist/index.d.ts +2 -0
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +3 -0
  40. package/dist/index.js.map +1 -1
  41. package/dist/mcp/core/auth.d.ts +16 -2
  42. package/dist/mcp/core/auth.d.ts.map +1 -1
  43. package/dist/mcp/core/auth.js +70 -26
  44. package/dist/mcp/core/auth.js.map +1 -1
  45. package/dist/mcp/core/paywall.d.ts +6 -0
  46. package/dist/mcp/core/paywall.d.ts.map +1 -1
  47. package/dist/mcp/core/paywall.js +179 -89
  48. package/dist/mcp/core/paywall.js.map +1 -1
  49. package/dist/mcp/core/server-manager.d.ts.map +1 -1
  50. package/dist/mcp/core/server-manager.js +6 -4
  51. package/dist/mcp/core/server-manager.js.map +1 -1
  52. package/dist/mcp/http/client-registration.d.ts.map +1 -1
  53. package/dist/mcp/http/client-registration.js +4 -2
  54. package/dist/mcp/http/client-registration.js.map +1 -1
  55. package/dist/mcp/http/oauth-metadata.d.ts.map +1 -1
  56. package/dist/mcp/http/oauth-metadata.js +2 -1
  57. package/dist/mcp/http/oauth-metadata.js.map +1 -1
  58. package/dist/mcp/index.d.ts +12 -5
  59. package/dist/mcp/index.d.ts.map +1 -1
  60. package/dist/mcp/index.js +46 -23
  61. package/dist/mcp/index.js.map +1 -1
  62. package/dist/mcp/types/http.types.d.ts +2 -2
  63. package/dist/mcp/types/http.types.d.ts.map +1 -1
  64. package/dist/mcp/types/http.types.js.map +1 -1
  65. package/dist/mcp/types/paywall.types.d.ts +6 -2
  66. package/dist/mcp/types/paywall.types.d.ts.map +1 -1
  67. package/dist/mcp/types/paywall.types.js.map +1 -1
  68. package/dist/mcp/types/server.types.d.ts +4 -2
  69. package/dist/mcp/types/server.types.d.ts.map +1 -1
  70. package/dist/mcp/types/server.types.js.map +1 -1
  71. package/dist/mcp/utils/errors.d.ts +26 -0
  72. package/dist/mcp/utils/errors.d.ts.map +1 -1
  73. package/dist/mcp/utils/errors.js +32 -0
  74. package/dist/mcp/utils/errors.js.map +1 -1
  75. package/dist/mcp/utils/meta.d.ts +54 -0
  76. package/dist/mcp/utils/meta.d.ts.map +1 -0
  77. package/dist/mcp/utils/meta.js +72 -0
  78. package/dist/mcp/utils/meta.js.map +1 -0
  79. package/dist/payments.d.ts.map +1 -1
  80. package/dist/utils.d.ts +27 -0
  81. package/dist/utils.d.ts.map +1 -1
  82. package/dist/utils.js +34 -0
  83. package/dist/utils.js.map +1 -1
  84. package/dist/x402/facilitator-api.d.ts +21 -0
  85. package/dist/x402/facilitator-api.d.ts.map +1 -1
  86. package/dist/x402/facilitator-api.js +39 -0
  87. package/dist/x402/facilitator-api.js.map +1 -1
  88. package/package.json +2 -2
@@ -0,0 +1,54 @@
1
+ /**
2
+ * In-band x402 metadata helpers for the MCP transport (x402 v2 MCP spec).
3
+ *
4
+ * The x402 v2 MCP transport signals payments *in band* via the MCP tool-call
5
+ * machinery instead of HTTP status codes / headers:
6
+ *
7
+ * - The client sends the `PaymentPayload` in the request params
8
+ * `_meta["x402/payment"]` (plain JSON).
9
+ * - The server returns the settlement receipt in the response
10
+ * `_meta["x402/payment-response"]` (plain JSON).
11
+ * - Payment-required is signalled as a tool result with `isError: true` whose
12
+ * `structuredContent` carries the `PaymentRequired` object and whose
13
+ * `content[0].text` is the JSON-stringified copy of it.
14
+ *
15
+ * Nevermined-specific observability (txHash, creditsRedeemed, …) is kept under
16
+ * a namespaced `_meta["nevermined/credits"]` key so it never collides with the
17
+ * spec-defined keys.
18
+ */
19
+ /** Spec-defined JSON-RPC `_meta` keys (x402 v2 MCP transport). */
20
+ export declare const X402_PAYMENT_META_KEY = "x402/payment";
21
+ export declare const X402_PAYMENT_RESPONSE_META_KEY = "x402/payment-response";
22
+ /** Nevermined-namespaced observability key (NOT part of the x402 spec). */
23
+ export declare const NEVERMINED_CREDITS_META_KEY = "nevermined/credits";
24
+ /**
25
+ * Read the in-band x402 payment payload from the current request's `_meta`.
26
+ *
27
+ * The MCP TS SDK exposes the incoming request `_meta` on the tool handler's
28
+ * `extra` argument (`extra._meta`), and its schema is a passthrough object, so
29
+ * non-standard keys like `"x402/payment"` survive parsing.
30
+ *
31
+ * @param extra - The MCP handler `extra` argument.
32
+ * @returns The decoded PaymentPayload object, or `undefined` when absent.
33
+ */
34
+ export declare function readPaymentPayload(extra: any): Record<string, any> | undefined;
35
+ /**
36
+ * Build a spec-shaped payment-required tool result.
37
+ *
38
+ * Per the x402 v2 MCP transport, payment-required is an *error* tool result
39
+ * that carries the `PaymentRequired` object in BOTH `structuredContent` (the
40
+ * object) and `content[0].text` (the JSON-stringified copy, for clients that
41
+ * cannot read structured content).
42
+ *
43
+ * @param paymentRequired - The `PaymentRequired` object.
44
+ * @returns A `CallToolResult`-shaped object with `isError: true`.
45
+ */
46
+ export declare function paymentRequiredResult(paymentRequired: Record<string, any>): {
47
+ isError: boolean;
48
+ structuredContent: Record<string, any>;
49
+ content: {
50
+ type: "text";
51
+ text: string;
52
+ }[];
53
+ };
54
+ //# sourceMappingURL=meta.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meta.d.ts","sourceRoot":"","sources":["../../../src/mcp/utils/meta.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,kEAAkE;AAClE,eAAO,MAAM,qBAAqB,iBAAiB,CAAA;AACnD,eAAO,MAAM,8BAA8B,0BAA0B,CAAA;AAErE,2EAA2E;AAC3E,eAAO,MAAM,2BAA2B,uBAAuB,CAAA;AAS/D;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,CAa9E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;;;;;;;EAMzE"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * In-band x402 metadata helpers for the MCP transport (x402 v2 MCP spec).
3
+ *
4
+ * The x402 v2 MCP transport signals payments *in band* via the MCP tool-call
5
+ * machinery instead of HTTP status codes / headers:
6
+ *
7
+ * - The client sends the `PaymentPayload` in the request params
8
+ * `_meta["x402/payment"]` (plain JSON).
9
+ * - The server returns the settlement receipt in the response
10
+ * `_meta["x402/payment-response"]` (plain JSON).
11
+ * - Payment-required is signalled as a tool result with `isError: true` whose
12
+ * `structuredContent` carries the `PaymentRequired` object and whose
13
+ * `content[0].text` is the JSON-stringified copy of it.
14
+ *
15
+ * Nevermined-specific observability (txHash, creditsRedeemed, …) is kept under
16
+ * a namespaced `_meta["nevermined/credits"]` key so it never collides with the
17
+ * spec-defined keys.
18
+ */
19
+ /** Spec-defined JSON-RPC `_meta` keys (x402 v2 MCP transport). */
20
+ export const X402_PAYMENT_META_KEY = 'x402/payment';
21
+ export const X402_PAYMENT_RESPONSE_META_KEY = 'x402/payment-response';
22
+ /** Nevermined-namespaced observability key (NOT part of the x402 spec). */
23
+ export const NEVERMINED_CREDITS_META_KEY = 'nevermined/credits';
24
+ /**
25
+ * Upper bound on the serialized size of an in-band payment payload. The payload
26
+ * is untrusted client input that gets re-encoded into a token, so cap it as
27
+ * defense-in-depth (mirrors the Python sibling's `len(json.dumps(value))` guard).
28
+ */
29
+ const MAX_INBAND_PAYMENT_PAYLOAD_LEN = 64 * 1024;
30
+ /**
31
+ * Read the in-band x402 payment payload from the current request's `_meta`.
32
+ *
33
+ * The MCP TS SDK exposes the incoming request `_meta` on the tool handler's
34
+ * `extra` argument (`extra._meta`), and its schema is a passthrough object, so
35
+ * non-standard keys like `"x402/payment"` survive parsing.
36
+ *
37
+ * @param extra - The MCP handler `extra` argument.
38
+ * @returns The decoded PaymentPayload object, or `undefined` when absent.
39
+ */
40
+ export function readPaymentPayload(extra) {
41
+ const value = extra?._meta?.[X402_PAYMENT_META_KEY];
42
+ // Only a plain object is a valid PaymentPayload; reject null and arrays
43
+ // (`typeof [] === 'object'`), mirroring the Python `isinstance(value, dict)`.
44
+ if (value === null || typeof value !== 'object' || Array.isArray(value)) {
45
+ return undefined;
46
+ }
47
+ // Defense-in-depth: reject oversized client-supplied payloads before they are
48
+ // re-encoded into a token.
49
+ if (JSON.stringify(value).length > MAX_INBAND_PAYMENT_PAYLOAD_LEN) {
50
+ return undefined;
51
+ }
52
+ return value;
53
+ }
54
+ /**
55
+ * Build a spec-shaped payment-required tool result.
56
+ *
57
+ * Per the x402 v2 MCP transport, payment-required is an *error* tool result
58
+ * that carries the `PaymentRequired` object in BOTH `structuredContent` (the
59
+ * object) and `content[0].text` (the JSON-stringified copy, for clients that
60
+ * cannot read structured content).
61
+ *
62
+ * @param paymentRequired - The `PaymentRequired` object.
63
+ * @returns A `CallToolResult`-shaped object with `isError: true`.
64
+ */
65
+ export function paymentRequiredResult(paymentRequired) {
66
+ return {
67
+ isError: true,
68
+ structuredContent: paymentRequired,
69
+ content: [{ type: 'text', text: JSON.stringify(paymentRequired) }],
70
+ };
71
+ }
72
+ //# sourceMappingURL=meta.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meta.js","sourceRoot":"","sources":["../../../src/mcp/utils/meta.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,kEAAkE;AAClE,MAAM,CAAC,MAAM,qBAAqB,GAAG,cAAc,CAAA;AACnD,MAAM,CAAC,MAAM,8BAA8B,GAAG,uBAAuB,CAAA;AAErE,2EAA2E;AAC3E,MAAM,CAAC,MAAM,2BAA2B,GAAG,oBAAoB,CAAA;AAE/D;;;;GAIG;AACH,MAAM,8BAA8B,GAAG,EAAE,GAAG,IAAI,CAAA;AAEhD;;;;;;;;;GASG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAU;IAC3C,MAAM,KAAK,GAAG,KAAK,EAAE,KAAK,EAAE,CAAC,qBAAqB,CAAC,CAAA;IACnD,wEAAwE;IACxE,8EAA8E;IAC9E,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACxE,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,8EAA8E;IAC9E,2BAA2B;IAC3B,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,8BAA8B,EAAE,CAAC;QAClE,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,qBAAqB,CAAC,eAAoC;IACxE,OAAO;QACL,OAAO,EAAE,IAAI;QACb,iBAAiB,EAAE,eAAe;QAClC,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,EAAE,CAAC;KAC5E,CAAA;AACH,CAAC","sourcesContent":["/**\n * In-band x402 metadata helpers for the MCP transport (x402 v2 MCP spec).\n *\n * The x402 v2 MCP transport signals payments *in band* via the MCP tool-call\n * machinery instead of HTTP status codes / headers:\n *\n * - The client sends the `PaymentPayload` in the request params\n * `_meta[\"x402/payment\"]` (plain JSON).\n * - The server returns the settlement receipt in the response\n * `_meta[\"x402/payment-response\"]` (plain JSON).\n * - Payment-required is signalled as a tool result with `isError: true` whose\n * `structuredContent` carries the `PaymentRequired` object and whose\n * `content[0].text` is the JSON-stringified copy of it.\n *\n * Nevermined-specific observability (txHash, creditsRedeemed, …) is kept under\n * a namespaced `_meta[\"nevermined/credits\"]` key so it never collides with the\n * spec-defined keys.\n */\n\n/** Spec-defined JSON-RPC `_meta` keys (x402 v2 MCP transport). */\nexport const X402_PAYMENT_META_KEY = 'x402/payment'\nexport const X402_PAYMENT_RESPONSE_META_KEY = 'x402/payment-response'\n\n/** Nevermined-namespaced observability key (NOT part of the x402 spec). */\nexport const NEVERMINED_CREDITS_META_KEY = 'nevermined/credits'\n\n/**\n * Upper bound on the serialized size of an in-band payment payload. The payload\n * is untrusted client input that gets re-encoded into a token, so cap it as\n * defense-in-depth (mirrors the Python sibling's `len(json.dumps(value))` guard).\n */\nconst MAX_INBAND_PAYMENT_PAYLOAD_LEN = 64 * 1024\n\n/**\n * Read the in-band x402 payment payload from the current request's `_meta`.\n *\n * The MCP TS SDK exposes the incoming request `_meta` on the tool handler's\n * `extra` argument (`extra._meta`), and its schema is a passthrough object, so\n * non-standard keys like `\"x402/payment\"` survive parsing.\n *\n * @param extra - The MCP handler `extra` argument.\n * @returns The decoded PaymentPayload object, or `undefined` when absent.\n */\nexport function readPaymentPayload(extra: any): Record<string, any> | undefined {\n const value = extra?._meta?.[X402_PAYMENT_META_KEY]\n // Only a plain object is a valid PaymentPayload; reject null and arrays\n // (`typeof [] === 'object'`), mirroring the Python `isinstance(value, dict)`.\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n return undefined\n }\n // Defense-in-depth: reject oversized client-supplied payloads before they are\n // re-encoded into a token.\n if (JSON.stringify(value).length > MAX_INBAND_PAYMENT_PAYLOAD_LEN) {\n return undefined\n }\n return value\n}\n\n/**\n * Build a spec-shaped payment-required tool result.\n *\n * Per the x402 v2 MCP transport, payment-required is an *error* tool result\n * that carries the `PaymentRequired` object in BOTH `structuredContent` (the\n * object) and `content[0].text` (the JSON-stringified copy, for clients that\n * cannot read structured content).\n *\n * @param paymentRequired - The `PaymentRequired` object.\n * @returns A `CallToolResult`-shaped object with `isError: true`.\n */\nexport function paymentRequiredResult(paymentRequired: Record<string, any>) {\n return {\n isError: true,\n structuredContent: paymentRequired,\n content: [{ type: 'text' as const, text: JSON.stringify(paymentRequired) }],\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"payments.d.ts","sourceRoot":"","sources":["../src/payments.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAE/C,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,8CAA8C,CAAA;AAE/E,OAAO,KAAK,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAA;AAExF,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAC3D,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAA;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,8CAA8C,CAAA;AAC/E,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAExD;;;;;;;;;;;;GAYG;AACH,qBAAa,QAAS,SAAQ,eAAe;IACpC,KAAK,EAAG,UAAU,CAAA;IAClB,KAAK,EAAG,QAAQ,CAAA;IAChB,MAAM,EAAG,SAAS,CAAA;IAClB,QAAQ,EAAG,gBAAgB,CAAA;IAC3B,aAAa,EAAG,gBAAgB,CAAA;IAChC,aAAa,EAAG,gBAAgB,CAAA;IAChC,SAAS,EAAG,YAAY,CAAA;IACxB,WAAW,EAAG,cAAc,CAAA;IAC5B,IAAI,EAAG,YAAY,CAAA;IAC1B,OAAO,CAAC,YAAY,CAAC,CAAgB;IACrC,OAAO,CAAC,WAAW,CAAC,CAAe;IAEnC;;;;OAIG;IACH,OAAO,CAAC,eAAe,CAAC,CAAkD;IAE1E;;;OAGG;IACH,IAAW,GAAG;QAEV;;;WAGG;yBAEQ,IAAI,CAAC,wBAAwB,EAAE,iBAAiB,CAAC,KACzD,uBAAuB;QAE1B;;;;WAIG;6BACwB,GAAG;MAOjC;IAED;;;OAGG;IACH,IAAW,GAAG;;;sDA0HgD,CAAC,cAC5D,CAAC,2LAKA,CAAC;sDAKuB,CAAC,cAC1B,CAAC,uEAAiE,CAAC;oFAQrE,CAAF,cAAoB,CAAC,mLAWV,CAAC;;;;;;;6FA6BoB,CAAC,cAI9B,CAHJ;8IAec,CAAC,cACb,CAAC;+FAEmc,CAAC,cAAc,CAAC;;;kBAtCxb,CAAC;;;;mBAsC04F,CAAC;;;;;;;;;MApMv6F;IAED;;;;;;;OAOG;IACH,IAAW,UAAU,IAAI,aAAa,CAUrC;IAED;;;OAGG;IACH,MAAM,CAAC,GAAG;;MAA4B;IAEtC;;;;;;;;;;;;;OAaG;IACH,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,cAAc;IAO1C;;;;;;;;;;;;;;;;;;OAkBG;IACH,MAAM,CAAC,kBAAkB,CAAC,OAAO,EAAE,cAAc;IAoBjD;;;;;OAKG;IACH,OAAO;IAOP;;OAEG;IACH,OAAO,CAAC,aAAa;IAYrB;;;;;;;;;;OAUG;IACI,OAAO;IAMd;;;;;;;;;OASG;IACI,MAAM;IAIb;;;;;;;;;;;;;;;;;;;;OAoBG;IACa,iBAAiB,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAgBtE;;;;;;;OAOG;IACH,IAAI,UAAU,IAAI,OAAO,CAExB;CACF"}
1
+ {"version":3,"file":"payments.d.ts","sourceRoot":"","sources":["../src/payments.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAE/C,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,8CAA8C,CAAA;AAE/E,OAAO,KAAK,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAA;AAExF,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAC3D,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAA;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,8CAA8C,CAAA;AAC/E,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAExD;;;;;;;;;;;;GAYG;AACH,qBAAa,QAAS,SAAQ,eAAe;IACpC,KAAK,EAAG,UAAU,CAAA;IAClB,KAAK,EAAG,QAAQ,CAAA;IAChB,MAAM,EAAG,SAAS,CAAA;IAClB,QAAQ,EAAG,gBAAgB,CAAA;IAC3B,aAAa,EAAG,gBAAgB,CAAA;IAChC,aAAa,EAAG,gBAAgB,CAAA;IAChC,SAAS,EAAG,YAAY,CAAA;IACxB,WAAW,EAAG,cAAc,CAAA;IAC5B,IAAI,EAAG,YAAY,CAAA;IAC1B,OAAO,CAAC,YAAY,CAAC,CAAgB;IACrC,OAAO,CAAC,WAAW,CAAC,CAAe;IAEnC;;;;OAIG;IACH,OAAO,CAAC,eAAe,CAAC,CAAkD;IAE1E;;;OAGG;IACH,IAAW,GAAG;QAEV;;;WAGG;yBAEQ,IAAI,CAAC,wBAAwB,EAAE,iBAAiB,CAAC,KACzD,uBAAuB;QAE1B;;;;WAIG;6BACwB,GAAG;MAOjC;IAED;;;OAGG;IACH,IAAW,GAAG;;;sDA+JO,CAAA,cAAc,CAAC,2LAEgC,CAAC;sDAE/C,CAAC,cAAc,CAAC,uEAGrC,CAAA;oFAGsC,CAAC,cAC1B,CAAC,mLAGwC,CAAC;;;;;;;6FA4B4yB,CAAC,cAAc,CAAC;8IAAwd,CAAC,cAAwB,CAAC;+FAAyc,CAAC,cAAc,CAAC;;;kBAJvyD,CAAC;;;;mBAIqvK,CAAC;;;;;;;;;MApM9wK;IAED;;;;;;;OAOG;IACH,IAAW,UAAU,IAAI,aAAa,CAUrC;IAED;;;OAGG;IACH,MAAM,CAAC,GAAG;;MAA4B;IAEtC;;;;;;;;;;;;;OAaG;IACH,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,cAAc;IAO1C;;;;;;;;;;;;;;;;;;OAkBG;IACH,MAAM,CAAC,kBAAkB,CAAC,OAAO,EAAE,cAAc;IAoBjD;;;;;OAKG;IACH,OAAO;IAOP;;OAEG;IACH,OAAO,CAAC,aAAa;IAYrB;;;;;;;;;;OAUG;IACI,OAAO;IAMd;;;;;;;;;OASG;IACI,MAAM;IAIb;;;;;;;;;;;;;;;;;;;;OAoBG;IACa,iBAAiB,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAgBtE;;;;;;;OAOG;IACH,IAAI,UAAU,IAAI,OAAO,CAExB;CACF"}
package/dist/utils.d.ts CHANGED
@@ -26,6 +26,33 @@ export declare const isStepIdValid: (stepId: string) => boolean;
26
26
  * @returns The decoded token data or null if invalid
27
27
  */
28
28
  export declare const decodeAccessToken: (accessToken: string) => Record<string, any> | null;
29
+ /**
30
+ * Encode a PaymentPayload object into an x402 access token string.
31
+ *
32
+ * Inverse of {@link decodeAccessToken}. Used by the MCP transport to turn the
33
+ * in-band `_meta["x402/payment"]` PaymentPayload object back into the
34
+ * base64url token string the facilitator's verify/settle APIs consume.
35
+ *
36
+ * The base64 envelope is transport-only: the EIP-712 signature lives inside
37
+ * `payload.authorization` / `payload.signature`, not over the base64 wrapper,
38
+ * so re-encoding a decoded (or foreign-encoded) payload is byte-safe for the
39
+ * facilitator — the invariant is semantic recovery, not byte-identity.
40
+ *
41
+ * Produces unpadded base64url with compact JSON (no spaces), matching the form
42
+ * {@link decodeAccessToken} accepts.
43
+ *
44
+ * Encodes UTF-8 bytes before base64 so it never throws on non-ASCII input — this
45
+ * runs on client-supplied `_meta["x402/payment"]`, and `btoa` alone throws a
46
+ * DOMException on code points > U+00FF. For ASCII JSON (all real x402
47
+ * PaymentPayloads: EIP-712 hex/decimal/signature fields) the output is
48
+ * byte-identical to `btoa(json)`, so the round-trip with {@link decodeAccessToken}
49
+ * is unchanged. `decodeAccessToken` is intentionally left as-is; a full UTF-8
50
+ * round-trip would additionally require decoding the bytes there.
51
+ *
52
+ * @param payload - The decoded PaymentPayload object (e.g. from `_meta["x402/payment"]`)
53
+ * @returns The base64url-encoded access token string (unpadded)
54
+ */
55
+ export declare const encodeAccessToken: (payload: Record<string, any>) => string;
29
56
  /**
30
57
  * It returns the list of endpoints that are used by agents/services implementing the Nevermined Query Protocol
31
58
  * @param serverHost - The host of the server where the agents/services are running
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAE5C;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAAI,SAAS,MAAM,GAAG,SAAS,KAAG,OAG/D,CAAA;AAED,eAAO,MAAM,eAAe,GAAI,aAAU,KAAG,MAW5C,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,QAAO,MAEjC,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,aAAa,GAAI,QAAQ,MAAM,KAAG,OAG9C,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,GAAI,aAAa,MAAM,KAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAsB7E,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,GAAI,YAAY,MAAM,KAAG,QAAQ,EAMtE,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,GAAI,YAAY,MAAM,KAAG,MAGvD,CAAA;AAKD,eAAO,MAAM,4BAA4B,GAAI,SAAS,MAAM,EAAE,YAAY,MAAM,KAAG,MAKlF,CAAA;AAGD,eAAO,MAAM,iBAAiB,QAAO,MAEpC,CAAA;AAGD,eAAO,MAAM,cAAc,GACzB,SAAS,MAAM,EACf,WAAW,MAAM,EACjB,kBAAqC,KACpC,IAsCF,CAAA"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAE5C;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAAI,SAAS,MAAM,GAAG,SAAS,KAAG,OAG/D,CAAA;AAED,eAAO,MAAM,eAAe,GAAI,aAAU,KAAG,MAW5C,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,QAAO,MAEjC,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,aAAa,GAAI,QAAQ,MAAM,KAAG,OAG9C,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,GAAI,aAAa,MAAM,KAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAsB7E,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,iBAAiB,GAAI,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAG,MAMhE,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,GAAI,YAAY,MAAM,KAAG,QAAQ,EAMtE,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,GAAI,YAAY,MAAM,KAAG,MAGvD,CAAA;AAKD,eAAO,MAAM,4BAA4B,GAAI,SAAS,MAAM,EAAE,YAAY,MAAM,KAAG,MAKlF,CAAA;AAGD,eAAO,MAAM,iBAAiB,QAAO,MAEpC,CAAA;AAGD,eAAO,MAAM,cAAc,GACzB,SAAS,MAAM,EACf,WAAW,MAAM,EACjB,kBAAqC,KACpC,IAsCF,CAAA"}
package/dist/utils.js CHANGED
@@ -69,6 +69,40 @@ export const decodeAccessToken = (accessToken) => {
69
69
  }
70
70
  return null;
71
71
  };
72
+ /**
73
+ * Encode a PaymentPayload object into an x402 access token string.
74
+ *
75
+ * Inverse of {@link decodeAccessToken}. Used by the MCP transport to turn the
76
+ * in-band `_meta["x402/payment"]` PaymentPayload object back into the
77
+ * base64url token string the facilitator's verify/settle APIs consume.
78
+ *
79
+ * The base64 envelope is transport-only: the EIP-712 signature lives inside
80
+ * `payload.authorization` / `payload.signature`, not over the base64 wrapper,
81
+ * so re-encoding a decoded (or foreign-encoded) payload is byte-safe for the
82
+ * facilitator — the invariant is semantic recovery, not byte-identity.
83
+ *
84
+ * Produces unpadded base64url with compact JSON (no spaces), matching the form
85
+ * {@link decodeAccessToken} accepts.
86
+ *
87
+ * Encodes UTF-8 bytes before base64 so it never throws on non-ASCII input — this
88
+ * runs on client-supplied `_meta["x402/payment"]`, and `btoa` alone throws a
89
+ * DOMException on code points > U+00FF. For ASCII JSON (all real x402
90
+ * PaymentPayloads: EIP-712 hex/decimal/signature fields) the output is
91
+ * byte-identical to `btoa(json)`, so the round-trip with {@link decodeAccessToken}
92
+ * is unchanged. `decodeAccessToken` is intentionally left as-is; a full UTF-8
93
+ * round-trip would additionally require decoding the bytes there.
94
+ *
95
+ * @param payload - The decoded PaymentPayload object (e.g. from `_meta["x402/payment"]`)
96
+ * @returns The base64url-encoded access token string (unpadded)
97
+ */
98
+ export const encodeAccessToken = (payload) => {
99
+ const json = JSON.stringify(payload);
100
+ const bytes = new TextEncoder().encode(json);
101
+ let binary = '';
102
+ for (const byte of bytes)
103
+ binary += String.fromCharCode(byte);
104
+ return btoa(binary).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
105
+ };
72
106
  /**
73
107
  * It returns the list of endpoints that are used by agents/services implementing the Nevermined Query Protocol
74
108
  * @param serverHost - The host of the server where the agents/services are running
package/dist/utils.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import * as crypto from 'crypto'\nimport * as fs from 'fs'\nimport * as path from 'path'\nimport { v4 as uuidv4, validate as uuidValidate } from 'uuid'\nimport { Endpoint } from './common/types.js'\n\n/**\n * Validates if a string is a valid Ethereum address\n * @param address - the address to check\n * @returns true if it's a valid Ethereum address\n */\nexport const isEthereumAddress = (address: string | undefined): boolean => {\n if (address && address.match(/^0x[a-fA-F0-9]{40}$/) !== null) return true\n return false\n}\n\nexport const getRandomBigInt = (bits = 128): bigint => {\n const bytes = Math.ceil(bits / 8)\n const array = new Uint8Array(bytes)\n crypto.getRandomValues(array)\n\n let result = 0n\n for (const byte of array) {\n result = (result << 8n) | BigInt(byte)\n }\n\n return result\n}\n\n/**\n * It generates a random step id\n * @returns the step id\n */\nexport const generateStepId = (): string => {\n return `step-${uuidv4()}`\n}\n\n/**\n * It checks the step id has the right format\n * @param stepId - the step id to validate\n * @returns true if it's a valid step id\n */\nexport const isStepIdValid = (stepId: string): boolean => {\n if (!stepId.startsWith('step-')) return false\n return uuidValidate(stepId.substring(5))\n}\n\n/**\n * Decode an x402 access token to extract subscriber address and plan ID.\n * The x402 access token is a base64-encoded JSON document containing\n * session key information and permissions.\n *\n * @param accessToken - The x402 access token to decode (base64-encoded JSON)\n * @returns The decoded token data or null if invalid\n */\nexport const decodeAccessToken = (accessToken: string): Record<string, any> | null => {\n // Try base64-encoded JSON (x402 format)\n\n // Try URL-safe base64 first\n try {\n const padded = accessToken + '='.repeat((4 - (accessToken.length % 4)) % 4)\n const urlSafeDecoded = atob(padded.replace(/-/g, '+').replace(/_/g, '/'))\n return JSON.parse(urlSafeDecoded)\n } catch {\n // Continue to next attempt\n }\n\n // Try standard base64 (non-URL-safe)\n try {\n const padded = accessToken + '='.repeat((4 - (accessToken.length % 4)) % 4)\n const decoded = atob(padded)\n return JSON.parse(decoded)\n } catch {\n // Continue to return null\n }\n\n return null\n}\n\n/**\n * It returns the list of endpoints that are used by agents/services implementing the Nevermined Query Protocol\n * @param serverHost - The host of the server where the agents/services are running\n * @returns the list of endpoints\n */\nexport const getQueryProtocolEndpoints = (serverHost: string): Endpoint[] => {\n const url = new URL(serverHost)\n return [\n { POST: `${url.origin}/api/v1/agents/(.*)/tasks` },\n { GET: `${url.origin}/api/v1/agents/(.*)/tasks/(.*)` },\n ]\n}\n\n/**\n * Giving a server host it returns the URL to the OpenAPI documentation of the AI Hub\n * @param serverHost - the server host (i.e http://localhost:5000)\n * @returns\n */\nexport const getAIHubOpenApiUrl = (serverHost: string): string => {\n const url = new URL(serverHost)\n return `${url.origin}/api/v1/rest/docs-json`\n}\n\n///////////////////// OBSERVABILITY /////////////////////\n\n// Generate deterministic agent ID: if no argument, return AGENT_DID as is; if argument, hash it as before\nexport const generateDeterministicAgentId = (agentId: string, className?: string): string => {\n if (!className) return agentId\n const hash = crypto.createHash('sha256').update(className).digest('hex').substring(0, 32)\n // Format as UUID: 8-4-4-4-12\n return `${hash.substring(0, 8)}-${hash.substring(8, 12)}-${hash.substring(12, 16)}-${hash.substring(16, 20)}-${hash.substring(20, 32)}`\n}\n\n// Generate random session ID\nexport const generateSessionId = (): string => {\n return uuidv4()\n}\n\n// Log session information\nexport const logSessionInfo = (\n agentId: string,\n sessionId: string,\n agentName = 'SceneTechnicalExtractor',\n): void => {\n const timestamp = new Date().toISOString()\n const logsDir = path.join(__dirname, 'logs')\n\n // Ensure logs directory exists\n if (!fs.existsSync(logsDir)) {\n fs.mkdirSync(logsDir, { recursive: true })\n }\n\n // Create session-specific log file with timestamp format (YYYYMMDD_HHMMSS)\n const now = new Date()\n const timestampStr = now\n .toISOString()\n .replace(/[-:]/g, '') // Remove dashes and colons\n .replace(/T/, '_') // Replace T with underscore\n .substring(0, 15) // Take YYYYMMDD_HHMMSS format\n\n const sessionLogFile = path.join(logsDir, `session_${timestampStr}.txt`)\n\n // Check if session file already exists to avoid duplicating session ID\n let sessionExists = false\n if (fs.existsSync(sessionLogFile)) {\n sessionExists = true\n }\n\n // If session file doesn't exist, create it with session ID header\n if (!sessionExists) {\n const sessionHeader = `Session ID: ${sessionId}\\n`\n fs.writeFileSync(sessionLogFile, sessionHeader)\n }\n\n // Append agent information in the expected format\n const agentEntry = `${agentName}: ${agentId}\\n`\n fs.appendFileSync(sessionLogFile, agentEntry)\n\n console.log(\n `Session logged: Timestamp: ${timestamp}, Agent Name: ${agentName}, Agent ID: ${agentId}, Session ID: ${sessionId}`,\n )\n}\n"]}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import * as crypto from 'crypto'\nimport * as fs from 'fs'\nimport * as path from 'path'\nimport { v4 as uuidv4, validate as uuidValidate } from 'uuid'\nimport { Endpoint } from './common/types.js'\n\n/**\n * Validates if a string is a valid Ethereum address\n * @param address - the address to check\n * @returns true if it's a valid Ethereum address\n */\nexport const isEthereumAddress = (address: string | undefined): boolean => {\n if (address && address.match(/^0x[a-fA-F0-9]{40}$/) !== null) return true\n return false\n}\n\nexport const getRandomBigInt = (bits = 128): bigint => {\n const bytes = Math.ceil(bits / 8)\n const array = new Uint8Array(bytes)\n crypto.getRandomValues(array)\n\n let result = 0n\n for (const byte of array) {\n result = (result << 8n) | BigInt(byte)\n }\n\n return result\n}\n\n/**\n * It generates a random step id\n * @returns the step id\n */\nexport const generateStepId = (): string => {\n return `step-${uuidv4()}`\n}\n\n/**\n * It checks the step id has the right format\n * @param stepId - the step id to validate\n * @returns true if it's a valid step id\n */\nexport const isStepIdValid = (stepId: string): boolean => {\n if (!stepId.startsWith('step-')) return false\n return uuidValidate(stepId.substring(5))\n}\n\n/**\n * Decode an x402 access token to extract subscriber address and plan ID.\n * The x402 access token is a base64-encoded JSON document containing\n * session key information and permissions.\n *\n * @param accessToken - The x402 access token to decode (base64-encoded JSON)\n * @returns The decoded token data or null if invalid\n */\nexport const decodeAccessToken = (accessToken: string): Record<string, any> | null => {\n // Try base64-encoded JSON (x402 format)\n\n // Try URL-safe base64 first\n try {\n const padded = accessToken + '='.repeat((4 - (accessToken.length % 4)) % 4)\n const urlSafeDecoded = atob(padded.replace(/-/g, '+').replace(/_/g, '/'))\n return JSON.parse(urlSafeDecoded)\n } catch {\n // Continue to next attempt\n }\n\n // Try standard base64 (non-URL-safe)\n try {\n const padded = accessToken + '='.repeat((4 - (accessToken.length % 4)) % 4)\n const decoded = atob(padded)\n return JSON.parse(decoded)\n } catch {\n // Continue to return null\n }\n\n return null\n}\n\n/**\n * Encode a PaymentPayload object into an x402 access token string.\n *\n * Inverse of {@link decodeAccessToken}. Used by the MCP transport to turn the\n * in-band `_meta[\"x402/payment\"]` PaymentPayload object back into the\n * base64url token string the facilitator's verify/settle APIs consume.\n *\n * The base64 envelope is transport-only: the EIP-712 signature lives inside\n * `payload.authorization` / `payload.signature`, not over the base64 wrapper,\n * so re-encoding a decoded (or foreign-encoded) payload is byte-safe for the\n * facilitator — the invariant is semantic recovery, not byte-identity.\n *\n * Produces unpadded base64url with compact JSON (no spaces), matching the form\n * {@link decodeAccessToken} accepts.\n *\n * Encodes UTF-8 bytes before base64 so it never throws on non-ASCII input — this\n * runs on client-supplied `_meta[\"x402/payment\"]`, and `btoa` alone throws a\n * DOMException on code points > U+00FF. For ASCII JSON (all real x402\n * PaymentPayloads: EIP-712 hex/decimal/signature fields) the output is\n * byte-identical to `btoa(json)`, so the round-trip with {@link decodeAccessToken}\n * is unchanged. `decodeAccessToken` is intentionally left as-is; a full UTF-8\n * round-trip would additionally require decoding the bytes there.\n *\n * @param payload - The decoded PaymentPayload object (e.g. from `_meta[\"x402/payment\"]`)\n * @returns The base64url-encoded access token string (unpadded)\n */\nexport const encodeAccessToken = (payload: Record<string, any>): string => {\n const json = JSON.stringify(payload)\n const bytes = new TextEncoder().encode(json)\n let binary = ''\n for (const byte of bytes) binary += String.fromCharCode(byte)\n return btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '')\n}\n\n/**\n * It returns the list of endpoints that are used by agents/services implementing the Nevermined Query Protocol\n * @param serverHost - The host of the server where the agents/services are running\n * @returns the list of endpoints\n */\nexport const getQueryProtocolEndpoints = (serverHost: string): Endpoint[] => {\n const url = new URL(serverHost)\n return [\n { POST: `${url.origin}/api/v1/agents/(.*)/tasks` },\n { GET: `${url.origin}/api/v1/agents/(.*)/tasks/(.*)` },\n ]\n}\n\n/**\n * Giving a server host it returns the URL to the OpenAPI documentation of the AI Hub\n * @param serverHost - the server host (i.e http://localhost:5000)\n * @returns\n */\nexport const getAIHubOpenApiUrl = (serverHost: string): string => {\n const url = new URL(serverHost)\n return `${url.origin}/api/v1/rest/docs-json`\n}\n\n///////////////////// OBSERVABILITY /////////////////////\n\n// Generate deterministic agent ID: if no argument, return AGENT_DID as is; if argument, hash it as before\nexport const generateDeterministicAgentId = (agentId: string, className?: string): string => {\n if (!className) return agentId\n const hash = crypto.createHash('sha256').update(className).digest('hex').substring(0, 32)\n // Format as UUID: 8-4-4-4-12\n return `${hash.substring(0, 8)}-${hash.substring(8, 12)}-${hash.substring(12, 16)}-${hash.substring(16, 20)}-${hash.substring(20, 32)}`\n}\n\n// Generate random session ID\nexport const generateSessionId = (): string => {\n return uuidv4()\n}\n\n// Log session information\nexport const logSessionInfo = (\n agentId: string,\n sessionId: string,\n agentName = 'SceneTechnicalExtractor',\n): void => {\n const timestamp = new Date().toISOString()\n const logsDir = path.join(__dirname, 'logs')\n\n // Ensure logs directory exists\n if (!fs.existsSync(logsDir)) {\n fs.mkdirSync(logsDir, { recursive: true })\n }\n\n // Create session-specific log file with timestamp format (YYYYMMDD_HHMMSS)\n const now = new Date()\n const timestampStr = now\n .toISOString()\n .replace(/[-:]/g, '') // Remove dashes and colons\n .replace(/T/, '_') // Replace T with underscore\n .substring(0, 15) // Take YYYYMMDD_HHMMSS format\n\n const sessionLogFile = path.join(logsDir, `session_${timestampStr}.txt`)\n\n // Check if session file already exists to avoid duplicating session ID\n let sessionExists = false\n if (fs.existsSync(sessionLogFile)) {\n sessionExists = true\n }\n\n // If session file doesn't exist, create it with session ID header\n if (!sessionExists) {\n const sessionHeader = `Session ID: ${sessionId}\\n`\n fs.writeFileSync(sessionLogFile, sessionHeader)\n }\n\n // Append agent information in the expected format\n const agentEntry = `${agentName}: ${agentId}\\n`\n fs.appendFileSync(sessionLogFile, agentEntry)\n\n console.log(\n `Session logged: Timestamp: ${timestamp}, Agent Name: ${agentName}, Agent ID: ${agentId}, Session ID: ${sessionId}`,\n )\n}\n"]}
@@ -220,6 +220,27 @@ export declare function buildPaymentRequired(planId: string, options?: {
220
220
  scheme?: X402SchemeType;
221
221
  environment?: EnvironmentName;
222
222
  }): X402PaymentRequired;
223
+ /**
224
+ * Build an X402PaymentRequired object advertising one or more plans.
225
+ *
226
+ * Like {@link buildPaymentRequired} but produces one `accepts[]` entry per plan
227
+ * id, so a payment-required response can advertise every plan that unlocks the
228
+ * resource. For a single plan this is equivalent to {@link buildPaymentRequired}.
229
+ *
230
+ * @param planIds - The Nevermined plan identifiers (falls back to `['']` if empty)
231
+ * @param options - Same options as {@link buildPaymentRequired}
232
+ * @returns X402PaymentRequired object with one accepts entry per plan
233
+ */
234
+ export declare function buildPaymentRequiredForPlans(planIds: string[], options?: {
235
+ endpoint?: string;
236
+ agentId?: string;
237
+ httpVerb?: string;
238
+ network?: string;
239
+ description?: string;
240
+ mimeType?: string;
241
+ scheme?: X402SchemeType;
242
+ environment?: EnvironmentName;
243
+ }): X402PaymentRequired;
223
244
  /**
224
245
  * Resolve the network for a plan from its fiatPaymentProvider metadata.
225
246
  * For card-delegation plans, returns the provider ('stripe' or 'braintree').
@@ -1 +1 @@
1
- {"version":3,"file":"facilitator-api.d.ts","sourceRoot":"","sources":["../../src/x402/facilitator-api.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"facilitator-api.d.ts","sourceRoot":"","sources":["../../src/x402/facilitator-api.ts"],"names":[],"mappings":"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"}
@@ -98,6 +98,45 @@ export function buildPaymentRequired(planId, options) {
98
98
  extensions: {},
99
99
  };
100
100
  }
101
+ /**
102
+ * Build an X402PaymentRequired object advertising one or more plans.
103
+ *
104
+ * Like {@link buildPaymentRequired} but produces one `accepts[]` entry per plan
105
+ * id, so a payment-required response can advertise every plan that unlocks the
106
+ * resource. For a single plan this is equivalent to {@link buildPaymentRequired}.
107
+ *
108
+ * @param planIds - The Nevermined plan identifiers (falls back to `['']` if empty)
109
+ * @param options - Same options as {@link buildPaymentRequired}
110
+ * @returns X402PaymentRequired object with one accepts entry per plan
111
+ */
112
+ export function buildPaymentRequiredForPlans(planIds, options) {
113
+ const ids = planIds.length > 0 ? planIds : [''];
114
+ if (ids.length === 1) {
115
+ return buildPaymentRequired(ids[0], options);
116
+ }
117
+ const { endpoint, agentId, httpVerb, scheme = 'nvm:erc4337', network, description, mimeType, environment, } = options || {};
118
+ const resolvedNetwork = network ?? getDefaultNetwork(scheme, environment);
119
+ const extra = {
120
+ version: '1',
121
+ ...(agentId && { agentId }),
122
+ ...(httpVerb && { httpVerb }),
123
+ };
124
+ return {
125
+ x402Version: 2,
126
+ resource: {
127
+ url: endpoint || '',
128
+ ...(description && { description }),
129
+ ...(mimeType && { mimeType }),
130
+ },
131
+ accepts: ids.map((planId) => ({
132
+ scheme,
133
+ network: resolvedNetwork,
134
+ planId,
135
+ extra,
136
+ })),
137
+ extensions: {},
138
+ };
139
+ }
101
140
  const CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes
102
141
  const planMetadataCache = new Map();
103
142
  async function fetchPlanMetadata(payments, planId) {
@@ -1 +1 @@
1
- {"version":3,"file":"facilitator-api.js","sourceRoot":"","sources":["../../src/x402/facilitator-api.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACzD,OAAO,EAAE,0BAA0B,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAA;AAC1F,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAC3D,OAAO,EAIL,iBAAiB,GAClB,MAAM,oBAAoB,CAAA;AAwJ3B;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,UAAU,oBAAoB,CAClC,MAAc,EACd,OASC;IAED,MAAM,EACJ,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,MAAM,GAAG,aAAa,EACtB,OAAO,EACP,WAAW,EACX,QAAQ,EACR,WAAW,GACZ,GAAG,OAAO,IAAI,EAAE,CAAA;IACjB,MAAM,eAAe,GAAG,OAAO,IAAI,iBAAiB,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;IAEzE,oEAAoE;IACpE,MAAM,KAAK,GAAoB;QAC7B,OAAO,EAAE,GAAG;QACZ,GAAG,CAAC,OAAO,IAAI,EAAE,OAAO,EAAE,CAAC;QAC3B,GAAG,CAAC,QAAQ,IAAI,EAAE,QAAQ,EAAE,CAAC;KAC9B,CAAA;IAED,OAAO;QACL,WAAW,EAAE,CAAC;QACd,QAAQ,EAAE;YACR,GAAG,EAAE,QAAQ,IAAI,EAAE;YACnB,GAAG,CAAC,WAAW,IAAI,EAAE,WAAW,EAAE,CAAC;YACnC,GAAG,CAAC,QAAQ,IAAI,EAAE,QAAQ,EAAE,CAAC;SAC9B;QACD,OAAO,EAAE;YACP;gBACE,MAAM;gBACN,OAAO,EAAE,eAAe;gBACxB,MAAM;gBACN,KAAK;aACN;SACF;QACD,UAAU,EAAE,EAAE;KACf,CAAA;AACH,CAAC;AAQD,MAAM,YAAY,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAA,CAAC,YAAY;AAC/C,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAA8B,CAAA;AAE/D,KAAK,UAAU,iBAAiB,CAC9B,QAAkB,EAClB,MAAc;IAEd,MAAM,MAAM,GAAG,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;IAC5C,IAAI,MAAM,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,QAAQ,GAAG,YAAY,EAAE,CAAC;QAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAA;IAClC,CAAC;IACD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;QACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAA;QAC/C,sEAAsE;QACtE,MAAM,YAAY,GAAI,IAAY,CAAC,QAAQ,EAAE,IAAI,EAAE,mBAAmB,CAAA;QACtE,MAAM,MAAM,GAAmB,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,aAAa,CAAA;QACzF,iBAAiB,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;QAC7E,OAAO,EAAE,MAAM,EAAE,CAAA;IACnB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,CAAA;IAClC,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,QAAkB,EAClB,MAAc,EACd,eAAwB;IAExB,IAAI,eAAe;QAAE,OAAO,eAAe,CAAA;IAC3C,MAAM,iBAAiB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;IACzC,MAAM,MAAM,GAAG,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;IAC5C,OAAO,MAAM,EAAE,YAAY,CAAA;AAC7B,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,QAAkB,EAClB,MAAc,EACd,cAA+B;IAE/B,IAAI,cAAc;QAAE,OAAO,cAAc,CAAA;IACzC,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;IAC1D,OAAO,QAAQ,CAAC,MAAM,CAAA;AACxB,CAAC;AAED;;;;GAIG;AACH,MAAM,OAAO,cAAe,SAAQ,eAAe;IACjD;;;;;OAKG;IACH,MAAM,CAAC,WAAW,CAAC,OAAuB;QACxC,OAAO,IAAI,cAAc,CAAC,OAAO,CAAC,CAAA;IACpC,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACH,KAAK,CAAC,iBAAiB,CAAC,MAA+B;QACrD,MAAM,EAAE,eAAe,EAAE,eAAe,EAAE,SAAS,EAAE,GAAG,MAAM,CAAA;QAE9D,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,0BAA0B,EAAE,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAA;QAEzE,MAAM,IAAI,GAA4B;YACpC,eAAe;YACf,eAAe;SAChB,CAAA;QAED,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAC5B,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC,QAAQ,EAAE,CAAA;QACvC,CAAC;QAED,wEAAwE;QACxE,yEAAyE;QACzE,wEAAwE;QACxE,oEAAoE;QACpE,MAAM,OAAO,GAAG,IAAI,CAAC,qBAAqB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;QAExD,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;YAC1C,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,IAAI,YAAY,GAAG,gCAAgC,CAAA;gBACnD,IAAI,SAAS,GAAG,QAAQ,QAAQ,CAAC,MAAM,EAAE,CAAA;gBACzC,IAAI,CAAC;oBACH,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;oBACvC,IAAI,SAAS,CAAC,OAAO;wBAAE,YAAY,GAAG,SAAS,CAAC,OAAO,CAAA;oBACvD,IAAI,SAAS,CAAC,IAAI;wBAAE,SAAS,GAAG,SAAS,CAAC,IAAI,CAAA;oBAC9C,IAAI,SAAS,CAAC,IAAI;wBAAE,YAAY,GAAG,GAAG,YAAY,MAAM,SAAS,CAAC,IAAI,EAAE,CAAA;gBAC1E,CAAC;gBAAC,MAAM,CAAC;oBACP,4BAA4B;gBAC9B,CAAC;gBACD,MAAM,aAAa,CAAC,WAAW,CAAC,YAAY,EAAE;oBAC5C,OAAO,EAAE,YAAY;oBACrB,IAAI,EAAE,SAAS;iBAChB,CAAC,CAAA;YACJ,CAAC;YACD,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;QAC9B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,aAAa,EAAE,CAAC;gBACnC,MAAM,KAAK,CAAA;YACb,CAAC;YACD,MAAM,aAAa,CAAC,WAAW,CAAC,8CAA8C,EAAE;gBAC9E,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;gBAC/D,IAAI,EAAE,eAAe;aACtB,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACH,KAAK,CAAC,iBAAiB,CAAC,MAA+B;QACrD,MAAM,EAAE,eAAe,EAAE,eAAe,EAAE,SAAS,EAAE,cAAc,EAAE,KAAK,EAAE,aAAa,EAAE,GACzF,MAAM,CAAA;QAER,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,0BAA0B,EAAE,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAA;QAEzE,MAAM,IAAI,GAA4B;YACpC,eAAe;YACf,eAAe;SAChB,CAAA;QAED,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAC5B,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC,QAAQ,EAAE,CAAA;QACvC,CAAC;QACD,IAAI,cAAc,KAAK,SAAS,EAAE,CAAC;YACjC,IAAI,CAAC,cAAc,GAAG,cAAc,CAAA;QACtC,CAAC;QACD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;QACpB,CAAC;QACD,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;YAChC,IAAI,CAAC,aAAa,GAAG,aAAa,CAAA;QACpC,CAAC;QAED,wEAAwE;QACxE,yEAAyE;QACzE,wEAAwE;QACxE,oEAAoE;QACpE,MAAM,OAAO,GAAG,IAAI,CAAC,qBAAqB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;QAExD,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;YAC1C,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,IAAI,YAAY,GAAG,8BAA8B,CAAA;gBACjD,IAAI,SAAS,GAAG,QAAQ,QAAQ,CAAC,MAAM,EAAE,CAAA;gBACzC,IAAI,CAAC;oBACH,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;oBACvC,IAAI,SAAS,CAAC,OAAO;wBAAE,YAAY,GAAG,SAAS,CAAC,OAAO,CAAA;oBACvD,IAAI,SAAS,CAAC,IAAI;wBAAE,SAAS,GAAG,SAAS,CAAC,IAAI,CAAA;oBAC9C,IAAI,SAAS,CAAC,IAAI;wBAAE,YAAY,GAAG,GAAG,YAAY,MAAM,SAAS,CAAC,IAAI,EAAE,CAAA;gBAC1E,CAAC;gBAAC,MAAM,CAAC;oBACP,4BAA4B;gBAC9B,CAAC;gBACD,MAAM,aAAa,CAAC,WAAW,CAAC,YAAY,EAAE;oBAC5C,OAAO,EAAE,YAAY;oBACrB,IAAI,EAAE,SAAS;iBAChB,CAAC,CAAA;YACJ,CAAC;YACD,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;QAC9B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,aAAa,EAAE,CAAC;gBACnC,MAAM,KAAK,CAAA;YACb,CAAC;YACD,MAAM,aAAa,CAAC,WAAW,CAAC,4CAA4C,EAAE;gBAC5E,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;gBAC/D,IAAI,EAAE,eAAe;aACtB,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;CACF","sourcesContent":["/**\n * The FacilitatorAPI class provides methods to verify and settle AI agent permissions using X402 access tokens.\n * This allows AI agents to act as facilitators, verifying and settling credits on behalf of subscribers.\n *\n * @example\n * ```typescript\n * import { Payments, X402PaymentRequired } from '@nevermined-io/payments'\n *\n * // Initialize the Payments instance\n * const payments = Payments.getInstance({\n * nvmApiKey: 'your-nvm-api-key',\n * environment: 'sandbox'\n * })\n *\n * // The server's 402 PaymentRequired response\n * const paymentRequired: X402PaymentRequired = buildPaymentRequired('123456789', {\n * endpoint: '/api/v1/agents/task',\n * agentId: '987654321',\n * httpVerb: 'POST'\n * })\n *\n * // Get X402 access token from subscriber (x402 v2: payment-signature header)\n * const x402Token = req.headers['payment-signature'] as string\n *\n * // Verify if subscriber has sufficient permissions/credits\n * const verification = await payments.facilitator.verifyPermissions({\n * paymentRequired,\n * x402AccessToken: x402Token,\n * maxAmount: 2n\n * })\n *\n * if (verification.isValid) {\n * // Settle (burn) the credits\n * const settlement = await payments.facilitator.settlePermissions({\n * paymentRequired,\n * x402AccessToken: x402Token,\n * maxAmount: 2n\n * })\n * console.log(`Credits redeemed: ${settlement.creditsRedeemed}`)\n * }\n * ```\n */\n\nimport { BasePaymentsAPI } from '../api/base-payments.js'\nimport { API_URL_SETTLE_PERMISSIONS, API_URL_VERIFY_PERMISSIONS } from '../api/nvm-api.js'\nimport { PaymentsError } from '../common/payments.error.js'\nimport {\n PaymentOptions,\n StartAgentRequest,\n X402SchemeType,\n getDefaultNetwork,\n} from '../common/types.js'\nimport type { EnvironmentName } from '../environments.js'\nimport type { Payments } from '../payments.js'\n\n/**\n * x402 Resource information\n */\nexport interface X402Resource {\n /** The protected resource URL */\n url: string\n /** Human-readable description */\n description?: string\n /** Expected response MIME type (e.g., \"application/json\") */\n mimeType?: string\n}\n\n/**\n * x402 Scheme extra fields for nvm:erc4337\n */\nexport interface X402SchemeExtra {\n /** Scheme version (e.g., \"1\") */\n version?: string\n /** Agent identifier */\n agentId?: string\n /** HTTP method for the endpoint */\n httpVerb?: string\n}\n\n/**\n * x402 Scheme definition (nvm:erc4337)\n */\nexport interface X402Scheme {\n /** Payment scheme identifier (e.g., \"nvm:erc4337\") */\n scheme: string\n /** Blockchain network in CAIP-2 format (e.g., \"eip155:84532\") */\n network: string\n /** 256-bit plan identifier */\n planId: string\n /** Scheme-specific extra fields */\n extra?: X402SchemeExtra\n}\n\n/**\n * x402 PaymentRequired response (402 response from server)\n */\nexport interface X402PaymentRequired {\n /** x402 protocol version (always 2) */\n x402Version: number\n /** Human-readable error message */\n error?: string\n /** Protected resource information */\n resource: X402Resource\n /** Array of accepted payment schemes */\n accepts: X402Scheme[]\n /** Extensions object (empty object for nvm:erc4337) */\n extensions: Record<string, unknown>\n}\n\n/**\n * x402 PaymentAccepted response (accepted payment scheme)\n */\nexport interface X402PaymentAccepted {\n /** The x402 version */\n x402Version: number\n /** The accepted payment scheme (nvm:erc4337) */\n accepted: X402Scheme\n /** The payload of the payment accepted */\n payload: {\n signature: string\n authorization: {\n from: string\n sessionKeysProvider: string\n sessionKeys: string[]\n }\n }\n extensions: Record<string, unknown>\n}\n\n/**\n * Parameters for verifying permissions\n */\nexport interface VerifyPermissionsParams {\n /** The server's 402 PaymentRequired response */\n paymentRequired: X402PaymentRequired\n /** The X402 access token (base64-encoded) */\n x402AccessToken: string\n /** Maximum credits to verify (optional) */\n maxAmount?: bigint\n}\n\n/**\n * x402 Verify Response - per x402 facilitator spec\n * @see https://github.com/coinbase/x402/blob/main/specs/x402-specification-v2.md\n */\nexport interface VerifyPermissionsResult {\n /** Whether the payment authorization is valid */\n isValid: boolean\n /** Reason for invalidity (only present if isValid is false) */\n invalidReason?: string\n /** Address of the payer's wallet */\n payer?: string\n /** Network identifier (e.g., 'stripe', 'braintree', 'visa', 'eip155:84532') */\n network?: string\n /** Agent request ID for observability tracking (Nevermined extension) */\n agentRequestId?: string\n /** URL pattern that matched the endpoint (Nevermined extension) */\n urlMatching?: string\n /** Agent request context for observability (Nevermined extension) */\n agentRequest?: StartAgentRequest\n}\n\n/**\n * Parameters for settling permissions\n */\nexport interface SettlePermissionsParams {\n /** The server's 402 PaymentRequired response */\n paymentRequired: X402PaymentRequired\n /** The X402 access token (base64-encoded) */\n x402AccessToken: string\n /** Number of credits to burn (optional) */\n maxAmount?: bigint\n /** Agent request ID for observability tracking. Returned by verifyPermissions. */\n agentRequestId?: string\n /** Whether this is a batch request (multiple LLM calls under one agentRequestId) */\n batch?: boolean\n /** Margin percentage (0-10) for credit calculation. Mutually exclusive with maxAmount when agentRequestId provided. */\n marginPercent?: number\n}\n\n/**\n * x402 Settle Response - per x402 facilitator spec\n * @see https://github.com/coinbase/x402/blob/main/specs/x402-specification-v2.md\n */\nexport interface SettlePermissionsResult {\n /** Whether settlement was successful */\n success: boolean\n /** Reason for settlement failure (only present if success is false) */\n errorReason?: string\n /** Address of the payer's wallet */\n payer?: string\n /** Blockchain transaction hash (empty string if settlement failed) */\n transaction: string\n /** Blockchain network identifier in CAIP-2 format */\n network: string\n /** Number of credits redeemed (Nevermined extension) */\n creditsRedeemed?: string\n /** Subscriber's remaining balance (Nevermined extension) */\n remainingBalance?: string\n /** Transaction hash of the order operation if auto top-up occurred (Nevermined extension) */\n orderTx?: string\n}\n\n/**\n * Build an X402PaymentRequired object for verify/settle operations.\n *\n * This helper simplifies the creation of payment requirement objects\n * that are needed for the facilitator API.\n *\n * @param planId - The Nevermined plan identifier (required)\n * @param options - Optional configuration with endpoint, agentId, httpVerb, network, description\n * @returns X402PaymentRequired object ready to use with verifyPermissions/settlePermissions\n *\n * @example\n * ```typescript\n * import { buildPaymentRequired } from '@nevermined-io/payments'\n *\n * const paymentRequired = buildPaymentRequired('123456789', {\n * endpoint: '/api/v1/agents/task',\n * agentId: '987654321',\n * httpVerb: 'POST'\n * })\n *\n * const result = await payments.facilitator.verifyPermissions({\n * paymentRequired,\n * x402AccessToken: token,\n * maxAmount: 2n\n * })\n * ```\n */\nexport function buildPaymentRequired(\n planId: string,\n options?: {\n endpoint?: string\n agentId?: string\n httpVerb?: string\n network?: string\n description?: string\n mimeType?: string\n scheme?: X402SchemeType\n environment?: EnvironmentName\n },\n): X402PaymentRequired {\n const {\n endpoint,\n agentId,\n httpVerb,\n scheme = 'nvm:erc4337',\n network,\n description,\n mimeType,\n environment,\n } = options || {}\n const resolvedNetwork = network ?? getDefaultNetwork(scheme, environment)\n\n // Build extra fields — always include version for scheme versioning\n const extra: X402SchemeExtra = {\n version: '1',\n ...(agentId && { agentId }),\n ...(httpVerb && { httpVerb }),\n }\n\n return {\n x402Version: 2,\n resource: {\n url: endpoint || '',\n ...(description && { description }),\n ...(mimeType && { mimeType }),\n },\n accepts: [\n {\n scheme,\n network: resolvedNetwork,\n planId,\n extra,\n },\n ],\n extensions: {},\n }\n}\n\ninterface CachedPlanMetadata {\n scheme: X402SchemeType\n fiatProvider?: string\n cachedAt: number\n}\n\nconst CACHE_TTL_MS = 5 * 60 * 1000 // 5 minutes\nconst planMetadataCache = new Map<string, CachedPlanMetadata>()\n\nasync function fetchPlanMetadata(\n payments: Payments,\n planId: string,\n): Promise<{ scheme: X402SchemeType }> {\n const cached = planMetadataCache.get(planId)\n if (cached && Date.now() - cached.cachedAt < CACHE_TTL_MS) {\n return { scheme: cached.scheme }\n }\n try {\n const plan = await payments.plans.getPlan(planId)\n const isCrypto = plan.registry?.price?.isCrypto\n // fiatPaymentProvider is in plan.metadata.plan, not in registry.price\n const fiatProvider = (plan as any).metadata?.plan?.fiatPaymentProvider\n const scheme: X402SchemeType = isCrypto === false ? 'nvm:card-delegation' : 'nvm:erc4337'\n planMetadataCache.set(planId, { scheme, fiatProvider, cachedAt: Date.now() })\n return { scheme }\n } catch {\n return { scheme: 'nvm:erc4337' }\n }\n}\n\n/**\n * Resolve the network for a plan from its fiatPaymentProvider metadata.\n * For card-delegation plans, returns the provider ('stripe' or 'braintree').\n * Returns undefined for crypto plans.\n */\nexport async function resolveNetwork(\n payments: Payments,\n planId: string,\n explicitNetwork?: string,\n): Promise<string | undefined> {\n if (explicitNetwork) return explicitNetwork\n await fetchPlanMetadata(payments, planId)\n const cached = planMetadataCache.get(planId)\n return cached?.fiatProvider\n}\n\n/**\n * Resolve the x402 scheme for a plan by fetching plan metadata (cached).\n * Used in callsites that don't have a token to extract scheme from\n * (402 responses and token generation).\n *\n * @param payments - The Payments instance for API access\n * @param planId - The plan identifier\n * @param explicitScheme - Optional explicit override; returned immediately if provided\n * @returns The resolved scheme type\n */\nexport async function resolveScheme(\n payments: Payments,\n planId: string,\n explicitScheme?: X402SchemeType,\n): Promise<X402SchemeType> {\n if (explicitScheme) return explicitScheme\n const metadata = await fetchPlanMetadata(payments, planId)\n return metadata.scheme\n}\n\n/**\n * The FacilitatorAPI class provides methods to verify and settle AI agent permissions.\n * It enables AI agents to act as facilitators, managing credit verification and settlement\n * for subscribers using X402 access tokens.\n */\nexport class FacilitatorAPI extends BasePaymentsAPI {\n /**\n * Get a singleton instance of the FacilitatorAPI class.\n *\n * @param options - The options to initialize the payments class\n * @returns The instance of the FacilitatorAPI class\n */\n static getInstance(options: PaymentOptions): FacilitatorAPI {\n return new FacilitatorAPI(options)\n }\n\n /**\n * Verify if a subscriber has permission to use credits from a payment plan.\n * This method simulates the credit usage without actually burning credits,\n * checking if the subscriber has sufficient balance and permissions.\n *\n * The planId and subscriberAddress are extracted from the x402AccessToken.\n *\n * @param params - Verification parameters (see {@link VerifyPermissionsParams}).\n * - paymentRequired: x402 PaymentRequired from 402 response (required, for validation)\n * - x402AccessToken: X402 access token (contains planId, subscriberAddress, agentId)\n * - maxAmount: maximum credits to verify (optional, bigint)\n * @returns A promise that resolves to a verification result with 'isValid' boolean\n *\n * @throws PaymentsError if verification fails\n */\n async verifyPermissions(params: VerifyPermissionsParams): Promise<VerifyPermissionsResult> {\n const { paymentRequired, x402AccessToken, maxAmount } = params\n\n const url = new URL(API_URL_VERIFY_PERMISSIONS, this.environment.backend)\n\n const body: Record<string, unknown> = {\n paymentRequired,\n x402AccessToken,\n }\n\n if (maxAmount !== undefined) {\n body.maxAmount = maxAmount.toString()\n }\n\n // Send the NVM API-key auth header (Authorization: Bearer <nvmApiKey>).\n // The backend /verify endpoint runs an OPTIONAL guard that tolerates the\n // header's absence today, so this is non-breaking; it pre-positions for\n // the later strict-guard flip. See nevermined-io/nvm-monorepo#1570.\n const options = this.getBackendHTTPOptions('POST', body)\n\n try {\n const response = await fetch(url, options)\n if (!response.ok) {\n let errorMessage = 'Permission verification failed'\n let errorCode = `http_${response.status}`\n try {\n const errorData = await response.json()\n if (errorData.message) errorMessage = errorData.message\n if (errorData.code) errorCode = errorData.code\n if (errorData.hint) errorMessage = `${errorMessage} — ${errorData.hint}`\n } catch {\n // Use default error message\n }\n throw PaymentsError.fromBackend(errorMessage, {\n message: errorMessage,\n code: errorCode,\n })\n }\n return await response.json()\n } catch (error) {\n if (error instanceof PaymentsError) {\n throw error\n }\n throw PaymentsError.fromBackend('Network error during permission verification', {\n message: error instanceof Error ? error.message : String(error),\n code: 'network_error',\n })\n }\n }\n\n /**\n * Settle (burn) credits from a subscriber's payment plan.\n * This method executes the actual credit consumption, burning the specified\n * number of credits from the subscriber's balance. If the subscriber doesn't\n * have enough credits, it will attempt to order more before settling.\n *\n * The planId and subscriberAddress are extracted from the x402AccessToken.\n *\n * @param params - Settlement parameters (see {@link SettlePermissionsParams}).\n * - paymentRequired: x402 PaymentRequired from 402 response (required, for validation)\n * - x402AccessToken: X402 access token (contains planId, subscriberAddress, agentId)\n * - maxAmount: number of credits to burn (optional, bigint)\n * - agentRequestId: Agent request ID for observability tracking (optional)\n * - batch: Whether this is a batch request (optional)\n * - marginPercent: Margin percentage for credit calculation (optional)\n * @returns A promise that resolves to a settlement result with transaction details\n *\n * @throws PaymentsError if settlement fails\n */\n async settlePermissions(params: SettlePermissionsParams): Promise<SettlePermissionsResult> {\n const { paymentRequired, x402AccessToken, maxAmount, agentRequestId, batch, marginPercent } =\n params\n\n const url = new URL(API_URL_SETTLE_PERMISSIONS, this.environment.backend)\n\n const body: Record<string, unknown> = {\n paymentRequired,\n x402AccessToken,\n }\n\n if (maxAmount !== undefined) {\n body.maxAmount = maxAmount.toString()\n }\n if (agentRequestId !== undefined) {\n body.agentRequestId = agentRequestId\n }\n if (batch !== undefined) {\n body.batch = batch\n }\n if (marginPercent !== undefined) {\n body.marginPercent = marginPercent\n }\n\n // Send the NVM API-key auth header (Authorization: Bearer <nvmApiKey>).\n // The backend /settle endpoint runs an OPTIONAL guard that tolerates the\n // header's absence today, so this is non-breaking; it pre-positions for\n // the later strict-guard flip. See nevermined-io/nvm-monorepo#1570.\n const options = this.getBackendHTTPOptions('POST', body)\n\n try {\n const response = await fetch(url, options)\n if (!response.ok) {\n let errorMessage = 'Permission settlement failed'\n let errorCode = `http_${response.status}`\n try {\n const errorData = await response.json()\n if (errorData.message) errorMessage = errorData.message\n if (errorData.code) errorCode = errorData.code\n if (errorData.hint) errorMessage = `${errorMessage} — ${errorData.hint}`\n } catch {\n // Use default error message\n }\n throw PaymentsError.fromBackend(errorMessage, {\n message: errorMessage,\n code: errorCode,\n })\n }\n return await response.json()\n } catch (error) {\n if (error instanceof PaymentsError) {\n throw error\n }\n throw PaymentsError.fromBackend('Network error during permission settlement', {\n message: error instanceof Error ? error.message : String(error),\n code: 'network_error',\n })\n }\n }\n}\n"]}
1
+ {"version":3,"file":"facilitator-api.js","sourceRoot":"","sources":["../../src/x402/facilitator-api.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The FacilitatorAPI class provides methods to verify and settle AI agent permissions using X402 access tokens.\n * This allows AI agents to act as facilitators, verifying and settling credits on behalf of subscribers.\n *\n * @example\n * ```typescript\n * import { Payments, X402PaymentRequired } from '@nevermined-io/payments'\n *\n * // Initialize the Payments instance\n * const payments = Payments.getInstance({\n * nvmApiKey: 'your-nvm-api-key',\n * environment: 'sandbox'\n * })\n *\n * // The server's 402 PaymentRequired response\n * const paymentRequired: X402PaymentRequired = buildPaymentRequired('123456789', {\n * endpoint: '/api/v1/agents/task',\n * agentId: '987654321',\n * httpVerb: 'POST'\n * })\n *\n * // Get X402 access token from subscriber (x402 v2: payment-signature header)\n * const x402Token = req.headers['payment-signature'] as string\n *\n * // Verify if subscriber has sufficient permissions/credits\n * const verification = await payments.facilitator.verifyPermissions({\n * paymentRequired,\n * x402AccessToken: x402Token,\n * maxAmount: 2n\n * })\n *\n * if (verification.isValid) {\n * // Settle (burn) the credits\n * const settlement = await payments.facilitator.settlePermissions({\n * paymentRequired,\n * x402AccessToken: x402Token,\n * maxAmount: 2n\n * })\n * console.log(`Credits redeemed: ${settlement.creditsRedeemed}`)\n * }\n * ```\n */\n\nimport { BasePaymentsAPI } from '../api/base-payments.js'\nimport { API_URL_SETTLE_PERMISSIONS, API_URL_VERIFY_PERMISSIONS } from '../api/nvm-api.js'\nimport { PaymentsError } from '../common/payments.error.js'\nimport {\n PaymentOptions,\n StartAgentRequest,\n X402SchemeType,\n getDefaultNetwork,\n} from '../common/types.js'\nimport type { EnvironmentName } from '../environments.js'\nimport type { Payments } from '../payments.js'\n\n/**\n * x402 Resource information\n */\nexport interface X402Resource {\n /** The protected resource URL */\n url: string\n /** Human-readable description */\n description?: string\n /** Expected response MIME type (e.g., \"application/json\") */\n mimeType?: string\n}\n\n/**\n * x402 Scheme extra fields for nvm:erc4337\n */\nexport interface X402SchemeExtra {\n /** Scheme version (e.g., \"1\") */\n version?: string\n /** Agent identifier */\n agentId?: string\n /** HTTP method for the endpoint */\n httpVerb?: string\n}\n\n/**\n * x402 Scheme definition (nvm:erc4337)\n */\nexport interface X402Scheme {\n /** Payment scheme identifier (e.g., \"nvm:erc4337\") */\n scheme: string\n /** Blockchain network in CAIP-2 format (e.g., \"eip155:84532\") */\n network: string\n /** 256-bit plan identifier */\n planId: string\n /** Scheme-specific extra fields */\n extra?: X402SchemeExtra\n}\n\n/**\n * x402 PaymentRequired response (402 response from server)\n */\nexport interface X402PaymentRequired {\n /** x402 protocol version (always 2) */\n x402Version: number\n /** Human-readable error message */\n error?: string\n /** Protected resource information */\n resource: X402Resource\n /** Array of accepted payment schemes */\n accepts: X402Scheme[]\n /** Extensions object (empty object for nvm:erc4337) */\n extensions: Record<string, unknown>\n}\n\n/**\n * x402 PaymentAccepted response (accepted payment scheme)\n */\nexport interface X402PaymentAccepted {\n /** The x402 version */\n x402Version: number\n /** The accepted payment scheme (nvm:erc4337) */\n accepted: X402Scheme\n /** The payload of the payment accepted */\n payload: {\n signature: string\n authorization: {\n from: string\n sessionKeysProvider: string\n sessionKeys: string[]\n }\n }\n extensions: Record<string, unknown>\n}\n\n/**\n * Parameters for verifying permissions\n */\nexport interface VerifyPermissionsParams {\n /** The server's 402 PaymentRequired response */\n paymentRequired: X402PaymentRequired\n /** The X402 access token (base64-encoded) */\n x402AccessToken: string\n /** Maximum credits to verify (optional) */\n maxAmount?: bigint\n}\n\n/**\n * x402 Verify Response - per x402 facilitator spec\n * @see https://github.com/coinbase/x402/blob/main/specs/x402-specification-v2.md\n */\nexport interface VerifyPermissionsResult {\n /** Whether the payment authorization is valid */\n isValid: boolean\n /** Reason for invalidity (only present if isValid is false) */\n invalidReason?: string\n /** Address of the payer's wallet */\n payer?: string\n /** Network identifier (e.g., 'stripe', 'braintree', 'visa', 'eip155:84532') */\n network?: string\n /** Agent request ID for observability tracking (Nevermined extension) */\n agentRequestId?: string\n /** URL pattern that matched the endpoint (Nevermined extension) */\n urlMatching?: string\n /** Agent request context for observability (Nevermined extension) */\n agentRequest?: StartAgentRequest\n}\n\n/**\n * Parameters for settling permissions\n */\nexport interface SettlePermissionsParams {\n /** The server's 402 PaymentRequired response */\n paymentRequired: X402PaymentRequired\n /** The X402 access token (base64-encoded) */\n x402AccessToken: string\n /** Number of credits to burn (optional) */\n maxAmount?: bigint\n /** Agent request ID for observability tracking. Returned by verifyPermissions. */\n agentRequestId?: string\n /** Whether this is a batch request (multiple LLM calls under one agentRequestId) */\n batch?: boolean\n /** Margin percentage (0-10) for credit calculation. Mutually exclusive with maxAmount when agentRequestId provided. */\n marginPercent?: number\n}\n\n/**\n * x402 Settle Response - per x402 facilitator spec\n * @see https://github.com/coinbase/x402/blob/main/specs/x402-specification-v2.md\n */\nexport interface SettlePermissionsResult {\n /** Whether settlement was successful */\n success: boolean\n /** Reason for settlement failure (only present if success is false) */\n errorReason?: string\n /** Address of the payer's wallet */\n payer?: string\n /** Blockchain transaction hash (empty string if settlement failed) */\n transaction: string\n /** Blockchain network identifier in CAIP-2 format */\n network: string\n /** Number of credits redeemed (Nevermined extension) */\n creditsRedeemed?: string\n /** Subscriber's remaining balance (Nevermined extension) */\n remainingBalance?: string\n /** Transaction hash of the order operation if auto top-up occurred (Nevermined extension) */\n orderTx?: string\n}\n\n/**\n * Build an X402PaymentRequired object for verify/settle operations.\n *\n * This helper simplifies the creation of payment requirement objects\n * that are needed for the facilitator API.\n *\n * @param planId - The Nevermined plan identifier (required)\n * @param options - Optional configuration with endpoint, agentId, httpVerb, network, description\n * @returns X402PaymentRequired object ready to use with verifyPermissions/settlePermissions\n *\n * @example\n * ```typescript\n * import { buildPaymentRequired } from '@nevermined-io/payments'\n *\n * const paymentRequired = buildPaymentRequired('123456789', {\n * endpoint: '/api/v1/agents/task',\n * agentId: '987654321',\n * httpVerb: 'POST'\n * })\n *\n * const result = await payments.facilitator.verifyPermissions({\n * paymentRequired,\n * x402AccessToken: token,\n * maxAmount: 2n\n * })\n * ```\n */\nexport function buildPaymentRequired(\n planId: string,\n options?: {\n endpoint?: string\n agentId?: string\n httpVerb?: string\n network?: string\n description?: string\n mimeType?: string\n scheme?: X402SchemeType\n environment?: EnvironmentName\n },\n): X402PaymentRequired {\n const {\n endpoint,\n agentId,\n httpVerb,\n scheme = 'nvm:erc4337',\n network,\n description,\n mimeType,\n environment,\n } = options || {}\n const resolvedNetwork = network ?? getDefaultNetwork(scheme, environment)\n\n // Build extra fields — always include version for scheme versioning\n const extra: X402SchemeExtra = {\n version: '1',\n ...(agentId && { agentId }),\n ...(httpVerb && { httpVerb }),\n }\n\n return {\n x402Version: 2,\n resource: {\n url: endpoint || '',\n ...(description && { description }),\n ...(mimeType && { mimeType }),\n },\n accepts: [\n {\n scheme,\n network: resolvedNetwork,\n planId,\n extra,\n },\n ],\n extensions: {},\n }\n}\n\n/**\n * Build an X402PaymentRequired object advertising one or more plans.\n *\n * Like {@link buildPaymentRequired} but produces one `accepts[]` entry per plan\n * id, so a payment-required response can advertise every plan that unlocks the\n * resource. For a single plan this is equivalent to {@link buildPaymentRequired}.\n *\n * @param planIds - The Nevermined plan identifiers (falls back to `['']` if empty)\n * @param options - Same options as {@link buildPaymentRequired}\n * @returns X402PaymentRequired object with one accepts entry per plan\n */\nexport function buildPaymentRequiredForPlans(\n planIds: string[],\n options?: {\n endpoint?: string\n agentId?: string\n httpVerb?: string\n network?: string\n description?: string\n mimeType?: string\n scheme?: X402SchemeType\n environment?: EnvironmentName\n },\n): X402PaymentRequired {\n const ids = planIds.length > 0 ? planIds : ['']\n if (ids.length === 1) {\n return buildPaymentRequired(ids[0], options)\n }\n\n const {\n endpoint,\n agentId,\n httpVerb,\n scheme = 'nvm:erc4337',\n network,\n description,\n mimeType,\n environment,\n } = options || {}\n const resolvedNetwork = network ?? getDefaultNetwork(scheme, environment)\n\n const extra: X402SchemeExtra = {\n version: '1',\n ...(agentId && { agentId }),\n ...(httpVerb && { httpVerb }),\n }\n\n return {\n x402Version: 2,\n resource: {\n url: endpoint || '',\n ...(description && { description }),\n ...(mimeType && { mimeType }),\n },\n accepts: ids.map((planId) => ({\n scheme,\n network: resolvedNetwork,\n planId,\n extra,\n })),\n extensions: {},\n }\n}\n\ninterface CachedPlanMetadata {\n scheme: X402SchemeType\n fiatProvider?: string\n cachedAt: number\n}\n\nconst CACHE_TTL_MS = 5 * 60 * 1000 // 5 minutes\nconst planMetadataCache = new Map<string, CachedPlanMetadata>()\n\nasync function fetchPlanMetadata(\n payments: Payments,\n planId: string,\n): Promise<{ scheme: X402SchemeType }> {\n const cached = planMetadataCache.get(planId)\n if (cached && Date.now() - cached.cachedAt < CACHE_TTL_MS) {\n return { scheme: cached.scheme }\n }\n try {\n const plan = await payments.plans.getPlan(planId)\n const isCrypto = plan.registry?.price?.isCrypto\n // fiatPaymentProvider is in plan.metadata.plan, not in registry.price\n const fiatProvider = (plan as any).metadata?.plan?.fiatPaymentProvider\n const scheme: X402SchemeType = isCrypto === false ? 'nvm:card-delegation' : 'nvm:erc4337'\n planMetadataCache.set(planId, { scheme, fiatProvider, cachedAt: Date.now() })\n return { scheme }\n } catch {\n return { scheme: 'nvm:erc4337' }\n }\n}\n\n/**\n * Resolve the network for a plan from its fiatPaymentProvider metadata.\n * For card-delegation plans, returns the provider ('stripe' or 'braintree').\n * Returns undefined for crypto plans.\n */\nexport async function resolveNetwork(\n payments: Payments,\n planId: string,\n explicitNetwork?: string,\n): Promise<string | undefined> {\n if (explicitNetwork) return explicitNetwork\n await fetchPlanMetadata(payments, planId)\n const cached = planMetadataCache.get(planId)\n return cached?.fiatProvider\n}\n\n/**\n * Resolve the x402 scheme for a plan by fetching plan metadata (cached).\n * Used in callsites that don't have a token to extract scheme from\n * (402 responses and token generation).\n *\n * @param payments - The Payments instance for API access\n * @param planId - The plan identifier\n * @param explicitScheme - Optional explicit override; returned immediately if provided\n * @returns The resolved scheme type\n */\nexport async function resolveScheme(\n payments: Payments,\n planId: string,\n explicitScheme?: X402SchemeType,\n): Promise<X402SchemeType> {\n if (explicitScheme) return explicitScheme\n const metadata = await fetchPlanMetadata(payments, planId)\n return metadata.scheme\n}\n\n/**\n * The FacilitatorAPI class provides methods to verify and settle AI agent permissions.\n * It enables AI agents to act as facilitators, managing credit verification and settlement\n * for subscribers using X402 access tokens.\n */\nexport class FacilitatorAPI extends BasePaymentsAPI {\n /**\n * Get a singleton instance of the FacilitatorAPI class.\n *\n * @param options - The options to initialize the payments class\n * @returns The instance of the FacilitatorAPI class\n */\n static getInstance(options: PaymentOptions): FacilitatorAPI {\n return new FacilitatorAPI(options)\n }\n\n /**\n * Verify if a subscriber has permission to use credits from a payment plan.\n * This method simulates the credit usage without actually burning credits,\n * checking if the subscriber has sufficient balance and permissions.\n *\n * The planId and subscriberAddress are extracted from the x402AccessToken.\n *\n * @param params - Verification parameters (see {@link VerifyPermissionsParams}).\n * - paymentRequired: x402 PaymentRequired from 402 response (required, for validation)\n * - x402AccessToken: X402 access token (contains planId, subscriberAddress, agentId)\n * - maxAmount: maximum credits to verify (optional, bigint)\n * @returns A promise that resolves to a verification result with 'isValid' boolean\n *\n * @throws PaymentsError if verification fails\n */\n async verifyPermissions(params: VerifyPermissionsParams): Promise<VerifyPermissionsResult> {\n const { paymentRequired, x402AccessToken, maxAmount } = params\n\n const url = new URL(API_URL_VERIFY_PERMISSIONS, this.environment.backend)\n\n const body: Record<string, unknown> = {\n paymentRequired,\n x402AccessToken,\n }\n\n if (maxAmount !== undefined) {\n body.maxAmount = maxAmount.toString()\n }\n\n // Send the NVM API-key auth header (Authorization: Bearer <nvmApiKey>).\n // The backend /verify endpoint runs an OPTIONAL guard that tolerates the\n // header's absence today, so this is non-breaking; it pre-positions for\n // the later strict-guard flip. See nevermined-io/nvm-monorepo#1570.\n const options = this.getBackendHTTPOptions('POST', body)\n\n try {\n const response = await fetch(url, options)\n if (!response.ok) {\n let errorMessage = 'Permission verification failed'\n let errorCode = `http_${response.status}`\n try {\n const errorData = await response.json()\n if (errorData.message) errorMessage = errorData.message\n if (errorData.code) errorCode = errorData.code\n if (errorData.hint) errorMessage = `${errorMessage} — ${errorData.hint}`\n } catch {\n // Use default error message\n }\n throw PaymentsError.fromBackend(errorMessage, {\n message: errorMessage,\n code: errorCode,\n })\n }\n return await response.json()\n } catch (error) {\n if (error instanceof PaymentsError) {\n throw error\n }\n throw PaymentsError.fromBackend('Network error during permission verification', {\n message: error instanceof Error ? error.message : String(error),\n code: 'network_error',\n })\n }\n }\n\n /**\n * Settle (burn) credits from a subscriber's payment plan.\n * This method executes the actual credit consumption, burning the specified\n * number of credits from the subscriber's balance. If the subscriber doesn't\n * have enough credits, it will attempt to order more before settling.\n *\n * The planId and subscriberAddress are extracted from the x402AccessToken.\n *\n * @param params - Settlement parameters (see {@link SettlePermissionsParams}).\n * - paymentRequired: x402 PaymentRequired from 402 response (required, for validation)\n * - x402AccessToken: X402 access token (contains planId, subscriberAddress, agentId)\n * - maxAmount: number of credits to burn (optional, bigint)\n * - agentRequestId: Agent request ID for observability tracking (optional)\n * - batch: Whether this is a batch request (optional)\n * - marginPercent: Margin percentage for credit calculation (optional)\n * @returns A promise that resolves to a settlement result with transaction details\n *\n * @throws PaymentsError if settlement fails\n */\n async settlePermissions(params: SettlePermissionsParams): Promise<SettlePermissionsResult> {\n const { paymentRequired, x402AccessToken, maxAmount, agentRequestId, batch, marginPercent } =\n params\n\n const url = new URL(API_URL_SETTLE_PERMISSIONS, this.environment.backend)\n\n const body: Record<string, unknown> = {\n paymentRequired,\n x402AccessToken,\n }\n\n if (maxAmount !== undefined) {\n body.maxAmount = maxAmount.toString()\n }\n if (agentRequestId !== undefined) {\n body.agentRequestId = agentRequestId\n }\n if (batch !== undefined) {\n body.batch = batch\n }\n if (marginPercent !== undefined) {\n body.marginPercent = marginPercent\n }\n\n // Send the NVM API-key auth header (Authorization: Bearer <nvmApiKey>).\n // The backend /settle endpoint runs an OPTIONAL guard that tolerates the\n // header's absence today, so this is non-breaking; it pre-positions for\n // the later strict-guard flip. See nevermined-io/nvm-monorepo#1570.\n const options = this.getBackendHTTPOptions('POST', body)\n\n try {\n const response = await fetch(url, options)\n if (!response.ok) {\n let errorMessage = 'Permission settlement failed'\n let errorCode = `http_${response.status}`\n try {\n const errorData = await response.json()\n if (errorData.message) errorMessage = errorData.message\n if (errorData.code) errorCode = errorData.code\n if (errorData.hint) errorMessage = `${errorMessage} — ${errorData.hint}`\n } catch {\n // Use default error message\n }\n throw PaymentsError.fromBackend(errorMessage, {\n message: errorMessage,\n code: errorCode,\n })\n }\n return await response.json()\n } catch (error) {\n if (error instanceof PaymentsError) {\n throw error\n }\n throw PaymentsError.fromBackend('Network error during permission settlement', {\n message: error instanceof Error ? error.message : String(error),\n code: 'network_error',\n })\n }\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nevermined-io/payments",
3
- "version": "1.7.0",
3
+ "version": "1.9.0",
4
4
  "description": "Typescript SDK to interact with the Nevermined Payments Protocol",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -122,7 +122,7 @@
122
122
  }
123
123
  },
124
124
  "dependencies": {
125
- "@a2a-js/sdk": "^0.3.4",
125
+ "@a2a-js/sdk": "^0.3.13",
126
126
  "@helicone/helpers": "^1.6.0",
127
127
  "@opentelemetry/api": "^1.9.0",
128
128
  "@opentelemetry/exporter-trace-otlp-http": "^0.215.0",