@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.
- package/README.md +2 -1
- package/dist/a2a/agent-card.d.ts +26 -0
- package/dist/a2a/agent-card.d.ts.map +1 -1
- package/dist/a2a/agent-card.js +36 -1
- package/dist/a2a/agent-card.js.map +1 -1
- package/dist/a2a/paymentsClient.d.ts +41 -1
- package/dist/a2a/paymentsClient.d.ts.map +1 -1
- package/dist/a2a/paymentsClient.js +120 -8
- package/dist/a2a/paymentsClient.js.map +1 -1
- package/dist/a2a/paymentsRequestHandler.d.ts +25 -2
- package/dist/a2a/paymentsRequestHandler.d.ts.map +1 -1
- package/dist/a2a/paymentsRequestHandler.js +240 -20
- package/dist/a2a/paymentsRequestHandler.js.map +1 -1
- package/dist/a2a/server.d.ts +2 -2
- package/dist/a2a/server.d.ts.map +1 -1
- package/dist/a2a/server.js +70 -20
- package/dist/a2a/server.js.map +1 -1
- package/dist/a2a/types.d.ts +31 -1
- package/dist/a2a/types.d.ts.map +1 -1
- package/dist/a2a/types.js.map +1 -1
- package/dist/a2a/x402-a2a.d.ts +142 -0
- package/dist/a2a/x402-a2a.d.ts.map +1 -0
- package/dist/a2a/x402-a2a.js +254 -0
- package/dist/a2a/x402-a2a.js.map +1 -0
- package/dist/api/agents-api.d.ts +19 -0
- package/dist/api/agents-api.d.ts.map +1 -1
- package/dist/api/agents-api.js +28 -1
- package/dist/api/agents-api.js.map +1 -1
- package/dist/api/nvm-api.d.ts +1 -0
- package/dist/api/nvm-api.d.ts.map +1 -1
- package/dist/api/nvm-api.js +4 -0
- package/dist/api/nvm-api.js.map +1 -1
- package/dist/api/plans-api.d.ts +12 -2
- package/dist/api/plans-api.d.ts.map +1 -1
- package/dist/api/plans-api.js +9 -2
- package/dist/api/plans-api.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp/core/auth.d.ts +16 -2
- package/dist/mcp/core/auth.d.ts.map +1 -1
- package/dist/mcp/core/auth.js +70 -26
- package/dist/mcp/core/auth.js.map +1 -1
- package/dist/mcp/core/paywall.d.ts +6 -0
- package/dist/mcp/core/paywall.d.ts.map +1 -1
- package/dist/mcp/core/paywall.js +179 -89
- package/dist/mcp/core/paywall.js.map +1 -1
- package/dist/mcp/core/server-manager.d.ts.map +1 -1
- package/dist/mcp/core/server-manager.js +6 -4
- package/dist/mcp/core/server-manager.js.map +1 -1
- package/dist/mcp/http/client-registration.d.ts.map +1 -1
- package/dist/mcp/http/client-registration.js +4 -2
- package/dist/mcp/http/client-registration.js.map +1 -1
- package/dist/mcp/http/oauth-metadata.d.ts.map +1 -1
- package/dist/mcp/http/oauth-metadata.js +2 -1
- package/dist/mcp/http/oauth-metadata.js.map +1 -1
- package/dist/mcp/index.d.ts +12 -5
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +46 -23
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/types/http.types.d.ts +2 -2
- package/dist/mcp/types/http.types.d.ts.map +1 -1
- package/dist/mcp/types/http.types.js.map +1 -1
- package/dist/mcp/types/paywall.types.d.ts +6 -2
- package/dist/mcp/types/paywall.types.d.ts.map +1 -1
- package/dist/mcp/types/paywall.types.js.map +1 -1
- package/dist/mcp/types/server.types.d.ts +4 -2
- package/dist/mcp/types/server.types.d.ts.map +1 -1
- package/dist/mcp/types/server.types.js.map +1 -1
- package/dist/mcp/utils/errors.d.ts +26 -0
- package/dist/mcp/utils/errors.d.ts.map +1 -1
- package/dist/mcp/utils/errors.js +32 -0
- package/dist/mcp/utils/errors.js.map +1 -1
- package/dist/mcp/utils/meta.d.ts +54 -0
- package/dist/mcp/utils/meta.d.ts.map +1 -0
- package/dist/mcp/utils/meta.js +72 -0
- package/dist/mcp/utils/meta.js.map +1 -0
- package/dist/payments.d.ts.map +1 -1
- package/dist/utils.d.ts +27 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +34 -0
- package/dist/utils.js.map +1 -1
- package/dist/x402/facilitator-api.d.ts +21 -0
- package/dist/x402/facilitator-api.d.ts.map +1 -1
- package/dist/x402/facilitator-api.js +39 -0
- package/dist/x402/facilitator-api.js.map +1 -1
- 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"]}
|
package/dist/payments.d.ts.map
CHANGED
|
@@ -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;;;
|
|
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
|
package/dist/utils.d.ts.map
CHANGED
|
@@ -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":"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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\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.
|
|
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.
|
|
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",
|