@nevermined-io/payments 1.6.0 → 1.8.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/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 +30 -3
- package/dist/api/agents-api.js.map +1 -1
- package/dist/api/base-payments.d.ts +6 -4
- package/dist/api/base-payments.d.ts.map +1 -1
- package/dist/api/base-payments.js +10 -0
- package/dist/api/base-payments.js.map +1 -1
- package/dist/api/contracts-api.js +1 -1
- package/dist/api/contracts-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 +12 -12
- package/dist/api/plans-api.js.map +1 -1
- package/dist/common/api-version.d.ts +24 -0
- package/dist/common/api-version.d.ts.map +1 -0
- package/dist/common/api-version.js +24 -0
- package/dist/common/api-version.js.map +1 -0
- package/dist/common/types.d.ts +73 -18
- package/dist/common/types.d.ts.map +1 -1
- package/dist/common/types.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp/core/auth.d.ts +14 -0
- package/dist/mcp/core/auth.d.ts.map +1 -1
- package/dist/mcp/core/auth.js +56 -23
- 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 +170 -84
- package/dist/mcp/core/paywall.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 +4 -3
- package/dist/payments.d.ts.map +1 -1
- package/dist/payments.js +5 -3
- package/dist/payments.js.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/dist/x402/index.d.ts +1 -1
- package/dist/x402/index.d.ts.map +1 -1
- package/dist/x402/index.js.map +1 -1
- package/dist/x402/token.d.ts +13 -10
- package/dist/x402/token.d.ts.map +1 -1
- package/dist/x402/token.js +46 -16
- package/dist/x402/token.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paywall.js","sourceRoot":"","sources":["../../../src/mcp/core/paywall.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Main paywall decorator for MCP handlers (tools, resources, prompts)\n */\nimport { Address, isValidScheme } from '../../common/types.js'\nimport type { Payments } from '../../payments.js'\nimport { decodeAccessToken } from '../../utils.js'\nimport {\n buildPaymentRequired,\n type SettlePermissionsResult,\n type X402PaymentRequired,\n} from '../../x402/facilitator-api.js'\nimport {\n McpConfig,\n PaywallOptions,\n PromptOptions,\n ResourceOptions,\n ToolOptions,\n} from '../types/paywall.types.js'\nimport { ERROR_CODES, createRpcError } from '../utils/errors.js'\nimport { PaywallAuthenticator } from './auth.js'\nimport { CreditsContextProvider } from './credits-context.js'\n\n/**\n * Main class for creating paywall-protected MCP handlers\n */\nexport class PaywallDecorator {\n // Internal config ensures serverName is always a concrete string\n private config: { agentId: string; serverName: string } = {\n agentId: '',\n serverName: 'mcp-server',\n }\n\n constructor(\n private payments: Payments,\n private authenticator: PaywallAuthenticator,\n private creditsContext: CreditsContextProvider,\n ) {}\n\n /**\n * Configure the paywall with agent and server information\n */\n configure(options: McpConfig): void {\n this.config = {\n agentId: options.agentId || this.config.agentId,\n serverName: options.serverName ?? this.config.serverName,\n }\n }\n\n /**\n * Create a paywall-protected handler (uncurried version only)\n */\n // Overloads per kind for stronger typing\n protect<TArgs = any>(\n handler: (args: TArgs, extra?: any) => Promise<any> | any,\n options: ToolOptions | PromptOptions,\n ): (args: TArgs, extra?: any) => Promise<any>\n protect(\n handler: (\n uri: URL,\n variables: Record<string, string | string[]>,\n extra?: any,\n ) => Promise<any> | any,\n options: ResourceOptions,\n ): (uri: URL, variables: Record<string, string | string[]>, extra?: any) => Promise<any>\n protect(handler: any, options: PaywallOptions): any {\n return this.createWrappedHandler(handler, options)\n }\n\n /**\n * Internal method to create the wrapped handler\n */\n private createWrappedHandler<TArgs = any>(\n handler: (args: TArgs, extra?: any) => Promise<any> | any,\n options: PaywallOptions,\n ): (...allArgs: any[]) => Promise<any> {\n return async (...allArgs: any[]): Promise<any> => {\n // Validate configuration\n if (!this.config.agentId) {\n throw createRpcError(\n ERROR_CODES.Misconfiguration,\n 'Server misconfiguration: missing agentId',\n )\n }\n\n const kind = options?.kind ?? 'tool'\n const name = options?.name ?? 'unnamed'\n\n // Detect resource signature: (url, variables, extra)\n const isResource = allArgs.length >= 2 && allArgs[0] instanceof URL\n const extra = isResource ? allArgs[2] : allArgs[1]\n const argsOrVars = isResource ? allArgs[1] : allArgs[0]\n\n // 1. Authenticate request\n const authResult = await this.authenticator.authenticate(\n extra,\n { planId: options?.planId, maxAmount: options?.maxAmount },\n this.config.agentId,\n this.config.serverName,\n name,\n kind,\n argsOrVars,\n )\n\n // 2. Pre-calculate credits if they are fixed (not a function)\n // This allows handlers to access credits during execution\n const creditsOption = options?.credits\n const isFixedCredits = typeof creditsOption === 'bigint' || creditsOption === undefined\n const preCalculatedCredits = isFixedCredits\n ? this.creditsContext.resolve(creditsOption, argsOrVars, null, authResult)\n : undefined\n\n // Determine effective planId: explicit option overrides token-derived value\n const effectivePlanId = options?.planId ?? authResult.planId\n\n // 3. Build PaywallContext for handler (with extra wrapper for backward compatibility)\n const paywallContext = {\n authResult,\n credits: preCalculatedCredits,\n planId: authResult.planId,\n subscriberAddress: authResult.subscriberAddress,\n agentRequest: authResult.agentRequest,\n }\n\n // 4. Execute original handler with context\n const result = await (handler as any)(...allArgs, paywallContext)\n\n // 5. Resolve final credits to burn (may be different if credits are dynamic)\n const credits = isFixedCredits\n ? (preCalculatedCredits ?? 1n)\n : this.creditsContext.resolve(creditsOption, argsOrVars, result, authResult)\n\n // Update context with final resolved credits\n paywallContext.credits = credits\n\n // 6. If the result is an AsyncIterable (stream), redeem on completion\n if (isAsyncIterable(result)) {\n const onFinally = async () => {\n return await this.redeemCredits(\n effectivePlanId,\n authResult.token,\n authResult.subscriberAddress,\n credits,\n options,\n authResult.agentId,\n authResult.logicalUrl,\n authResult.httpUrl,\n 'POST',\n )\n }\n return wrapAsyncIterable(\n result,\n onFinally,\n effectivePlanId,\n authResult.subscriberAddress,\n credits,\n )\n }\n\n // 7. Non-streaming: redeem immediately\n const creditsResult = await this.redeemCredits(\n effectivePlanId,\n authResult.token,\n authResult.subscriberAddress,\n credits,\n options,\n authResult.agentId,\n authResult.logicalUrl,\n 'POST',\n authResult.httpUrl,\n )\n result._meta = {\n ...result._meta,\n ...(creditsResult.transaction && { txHash: creditsResult.transaction }),\n creditsRedeemed: creditsResult.success ? (creditsResult.creditsRedeemed ?? credits.toString()) : '0',\n remainingBalance: creditsResult.remainingBalance,\n planId: authResult.planId,\n subscriberAddress: authResult.subscriberAddress,\n success: creditsResult.success,\n ...(creditsResult.errorReason && { errorReason: creditsResult.errorReason }),\n }\n return result\n }\n }\n\n /**\n * Redeem credits after successful request\n */\n private async redeemCredits(\n planId: string,\n token: string,\n subscriberAddress: Address,\n credits: bigint,\n options: PaywallOptions,\n agentId?: string,\n endpoint?: string,\n fallbackEndpoint?: string,\n httpVerb?: string,\n ): Promise<SettlePermissionsResult> {\n let ret: SettlePermissionsResult = {\n success: true,\n transaction: '',\n network: '',\n }\n const decoded = decodeAccessToken(token)\n const scheme = isValidScheme(decoded?.accepted?.scheme) ? decoded.accepted.scheme : 'nvm:erc4337'\n try {\n if (credits && credits > 0n && subscriberAddress && planId) {\n const paymentRequired: X402PaymentRequired = buildPaymentRequired(planId, {\n endpoint: endpoint || '',\n agentId,\n httpVerb,\n scheme,\n environment: this.payments.getEnvironmentName(),\n })\n\n ret = await this.payments.facilitator.settlePermissions({\n paymentRequired,\n x402AccessToken: token,\n maxAmount: credits,\n })\n }\n } catch (primaryError) {\n // If logical URL fails and we have an HTTP URL fallback, retry with it\n let lastError: unknown = primaryError\n if (fallbackEndpoint) {\n try {\n const paymentRequired: X402PaymentRequired = buildPaymentRequired(planId, {\n endpoint: fallbackEndpoint,\n agentId,\n httpVerb,\n scheme,\n environment: this.payments.getEnvironmentName(),\n })\n\n ret = await this.payments.facilitator.settlePermissions({\n paymentRequired,\n x402AccessToken: token,\n maxAmount: credits,\n })\n return ret\n } catch (fallbackError) {\n // Fallback also failed, use fallback error as the reported error\n lastError = fallbackError\n }\n }\n\n ret.success = false\n ret.errorReason = lastError instanceof Error ? lastError.message : String(lastError)\n if (options.onRedeemError === 'propagate') {\n throw createRpcError(ERROR_CODES.Misconfiguration, `Failed to redeem credits: ${ret.errorReason}`)\n }\n // Default: attach error to result but don't throw\n }\n return ret\n }\n}\n\n/**\n * Type guard to detect AsyncIterable values.\n */\nfunction isAsyncIterable<T = unknown>(value: any): value is AsyncIterable<T> {\n return value != null && typeof value[Symbol.asyncIterator] === 'function'\n}\n\n/**\n * Wrap an AsyncIterable with metadata injection at the end of the stream\n */\nfunction wrapAsyncIterable<T>(\n iterable: AsyncIterable<T>,\n onFinally: () => Promise<any>,\n planId: string,\n subscriberAddress: Address,\n credits: bigint,\n) {\n async function* generator() {\n let creditsResult: any = null\n try {\n for await (const chunk of iterable) {\n yield chunk as T\n }\n } finally {\n creditsResult = await onFinally()\n }\n\n // Yield a _meta chunk at the end with the redemption result\n const metadataChunk = {\n _meta: {\n // Only include txHash if it has a value\n ...(creditsResult?.transaction && { txHash: creditsResult.transaction }),\n creditsRedeemed: creditsResult?.success ? (creditsResult.creditsRedeemed ?? credits.toString()) : '0',\n remainingBalance: creditsResult?.remainingBalance,\n planId,\n subscriberAddress,\n success: creditsResult?.success || false,\n ...(creditsResult?.errorReason && { errorReason: creditsResult.errorReason }),\n },\n }\n yield metadataChunk as T\n }\n return generator()\n}\n"]}
|
|
1
|
+
{"version":3,"file":"paywall.js","sourceRoot":"","sources":["../../../src/mcp/core/paywall.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Main paywall decorator for MCP handlers (tools, resources, prompts)\n */\nimport { Address, isValidScheme } from '../../common/types.js'\nimport type { Payments } from '../../payments.js'\nimport { decodeAccessToken, encodeAccessToken } from '../../utils.js'\nimport {\n buildPaymentRequired,\n buildPaymentRequiredForPlans,\n type SettlePermissionsResult,\n type X402PaymentRequired,\n} from '../../x402/facilitator-api.js'\nimport {\n AuthResult,\n McpConfig,\n PaywallOptions,\n PromptOptions,\n ResourceOptions,\n ToolOptions,\n} from '../types/paywall.types.js'\nimport {\n ERROR_CODES,\n PaymentRequiredError,\n SettlementFailedError,\n createRpcError,\n} from '../utils/errors.js'\nimport {\n NEVERMINED_CREDITS_META_KEY,\n X402_PAYMENT_RESPONSE_META_KEY,\n paymentRequiredResult,\n readPaymentPayload,\n} from '../utils/meta.js'\nimport { PaywallAuthenticator } from './auth.js'\nimport { CreditsContextProvider } from './credits-context.js'\n\n// Emit the Authorization-header deprecation notice at most once per process to\n// avoid log spam on high-traffic servers still using the legacy header path.\nlet authHeaderDeprecationWarned = false\n\n/**\n * Main class for creating paywall-protected MCP handlers\n */\nexport class PaywallDecorator {\n // Internal config ensures serverName is always a concrete string\n private config: { agentId: string; serverName: string } = {\n agentId: '',\n serverName: 'mcp-server',\n }\n\n constructor(\n private payments: Payments,\n private authenticator: PaywallAuthenticator,\n private creditsContext: CreditsContextProvider,\n ) {}\n\n /**\n * Configure the paywall with agent and server information\n */\n configure(options: McpConfig): void {\n this.config = {\n agentId: options.agentId || this.config.agentId,\n serverName: options.serverName ?? this.config.serverName,\n }\n }\n\n /**\n * Create a paywall-protected handler (uncurried version only)\n */\n // Overloads per kind for stronger typing\n protect<TArgs = any>(\n handler: (args: TArgs, extra?: any) => Promise<any> | any,\n options: ToolOptions | PromptOptions,\n ): (args: TArgs, extra?: any) => Promise<any>\n protect(\n handler: (\n uri: URL,\n variables: Record<string, string | string[]>,\n extra?: any,\n ) => Promise<any> | any,\n options: ResourceOptions,\n ): (uri: URL, variables: Record<string, string | string[]>, extra?: any) => Promise<any>\n protect(handler: any, options: PaywallOptions): any {\n return this.createWrappedHandler(handler, options)\n }\n\n /**\n * Internal method to create the wrapped handler\n */\n private createWrappedHandler<TArgs = any>(\n handler: (args: TArgs, extra?: any) => Promise<any> | any,\n options: PaywallOptions,\n ): (...allArgs: any[]) => Promise<any> {\n return async (...allArgs: any[]): Promise<any> => {\n // Validate configuration\n if (!this.config.agentId) {\n throw createRpcError(\n ERROR_CODES.Misconfiguration,\n 'Server misconfiguration: missing agentId',\n )\n }\n\n const kind = options?.kind ?? 'tool'\n const name = options?.name ?? 'unnamed'\n\n // Detect resource signature: (url, variables, extra)\n const isResource = allArgs.length >= 2 && allArgs[0] instanceof URL\n const extra = isResource ? allArgs[2] : allArgs[1]\n const argsOrVars = isResource ? allArgs[1] : allArgs[0]\n\n try {\n // x402 v2 MCP transport: prefer the in-band payment payload from\n // params._meta[\"x402/payment\"]. Re-encode it into the access token\n // string the verify/settle path expects and present it via the same\n // extra/headers shape the auth flow reads, so the in-band payload takes\n // precedence over the Authorization header (kept as a deprecated\n // fallback when the in-band payload is absent). The RAW extra is still\n // forwarded to the user handler below.\n const paymentPayload = readPaymentPayload(extra)\n let authExtra = extra\n if (paymentPayload) {\n const token = encodeAccessToken(paymentPayload)\n // Synthesize an auth-only extra carrying the in-band token. This\n // intentionally drops the rest of `extra` for the AUTH call only; the\n // RAW `extra` (with `_meta`) is still forwarded to the user handler below.\n authExtra = { requestInfo: { headers: { authorization: `Bearer ${token}` } } }\n } else if (!authHeaderDeprecationWarned) {\n authHeaderDeprecationWarned = true\n console.warn(\n '[x402] No _meta[\"x402/payment\"] on the MCP request; falling back to the ' +\n 'Authorization header (deprecated under the x402 v2 MCP transport).',\n )\n }\n\n // 1. Authenticate request\n const authResult = await this.authenticator.authenticate(\n authExtra,\n { planId: options?.planId, maxAmount: options?.maxAmount },\n this.config.agentId,\n this.config.serverName,\n name,\n kind,\n argsOrVars,\n )\n\n // 2. Pre-calculate credits if they are fixed (not a function)\n // This allows handlers to access credits during execution\n const creditsOption = options?.credits\n const isFixedCredits = typeof creditsOption === 'bigint' || creditsOption === undefined\n const preCalculatedCredits = isFixedCredits\n ? this.creditsContext.resolve(creditsOption, argsOrVars, null, authResult)\n : undefined\n\n // Determine effective planId: explicit option overrides token-derived value\n const effectivePlanId = options?.planId ?? authResult.planId\n\n // 3. Build PaywallContext for handler (with extra wrapper for backward compatibility)\n const paywallContext = {\n authResult,\n credits: preCalculatedCredits,\n planId: authResult.planId,\n subscriberAddress: authResult.subscriberAddress,\n agentRequest: authResult.agentRequest,\n }\n\n // 4. Execute original handler with context\n const result = await (handler as any)(...allArgs, paywallContext)\n\n // 5. Resolve final credits to burn (may be different if credits are dynamic)\n const credits = isFixedCredits\n ? (preCalculatedCredits ?? 1n)\n : this.creditsContext.resolve(creditsOption, argsOrVars, result, authResult)\n\n // Update context with final resolved credits\n paywallContext.credits = credits\n\n // 6. If the result is an AsyncIterable (stream), redeem on completion\n if (isAsyncIterable(result)) {\n const onFinally = async () => {\n return await this.redeemCredits(\n effectivePlanId,\n authResult.token,\n authResult.subscriberAddress,\n credits,\n options,\n authResult.agentId,\n authResult.logicalUrl,\n authResult.httpUrl,\n 'POST',\n )\n }\n return wrapAsyncIterable(\n result,\n onFinally,\n effectivePlanId,\n authResult.subscriberAddress,\n credits,\n )\n }\n\n // 7. Non-streaming: redeem immediately\n const creditsResult = await this.redeemCredits(\n effectivePlanId,\n authResult.token,\n authResult.subscriberAddress,\n credits,\n options,\n authResult.agentId,\n authResult.logicalUrl,\n // fix: pre-existing arg order — fallbackEndpoint=httpUrl, httpVerb='POST'\n // (matches the streaming site above)\n authResult.httpUrl,\n 'POST',\n )\n\n // Settlement failed AFTER the tool executed: per the x402 v2 MCP\n // transport spec, do NOT return the tool's content — surface only the\n // payment error so a paid result is never delivered without payment\n // landing. (onRedeemError \"ignore\" therefore no longer delivers paid\n // content; \"propagate\" already threw a Misconfiguration in redeemCredits.)\n if (creditsResult && !creditsResult.success) {\n console.error(\n `[x402] settlement failed after tool execution; suppressing tool content. reason=${creditsResult.errorReason}`,\n )\n throw new SettlementFailedError(this.buildPaymentRequiredFromAuth(authResult))\n }\n\n // creditsResult is undefined for free / no-credit calls (no settlement\n // performed) — in that case the spec receipt is omitted. On success the\n // full receipt goes under the spec key; Nevermined observability is kept\n // under a namespaced key so it never collides with the spec shape.\n result._meta = {\n ...result._meta,\n ...(creditsResult && { [X402_PAYMENT_RESPONSE_META_KEY]: creditsResult }),\n [NEVERMINED_CREDITS_META_KEY]: {\n ...(creditsResult?.transaction && { txHash: creditsResult.transaction }),\n creditsRedeemed: creditsResult?.success\n ? (creditsResult.creditsRedeemed ?? credits.toString())\n : '0',\n remainingBalance: creditsResult?.remainingBalance,\n planId: authResult.planId,\n subscriberAddress: authResult.subscriberAddress,\n success: creditsResult ? creditsResult.success : true,\n },\n }\n return result\n } catch (error) {\n // Payment-required (pre-execution, from auth) and settlement-failure\n // (post-execution) are surfaced in band as an error tool result for\n // tools. Resources/prompts have no tool-result error channel, so the\n // error propagates as a JSON-RPC error instead.\n if (error instanceof PaymentRequiredError && kind === 'tool') {\n return paymentRequiredResult(error.paymentRequired)\n }\n throw error\n }\n }\n }\n\n /**\n * Build a spec-shaped `PaymentRequired` dict for a settlement failure, from\n * the authenticated request context. Surfaced (with tool content suppressed)\n * when settlement fails after the tool has executed.\n */\n private buildPaymentRequiredFromAuth(authResult: AuthResult): Record<string, any> {\n const planId = authResult.planId || ''\n const paymentRequired = buildPaymentRequiredForPlans(planId ? [planId] : [''], {\n endpoint: authResult.logicalUrl || authResult.httpUrl,\n agentId: authResult.agentId,\n httpVerb: 'POST',\n environment: this.payments.getEnvironmentName(),\n }) as X402PaymentRequired & { error?: string }\n paymentRequired.error = 'settlement failed'\n return paymentRequired\n }\n\n /**\n * Redeem credits after successful request\n */\n private async redeemCredits(\n planId: string,\n token: string,\n subscriberAddress: Address,\n credits: bigint,\n options: PaywallOptions,\n agentId?: string,\n endpoint?: string,\n fallbackEndpoint?: string,\n httpVerb?: string,\n ): Promise<SettlePermissionsResult | undefined> {\n // No settlement for free / no-credit calls — signalled to the caller as\n // `undefined` so the spec receipt (_meta[\"x402/payment-response\"]) is omitted.\n if (!(credits && credits > 0n && subscriberAddress && planId)) {\n return undefined\n }\n\n const decoded = decodeAccessToken(token)\n const scheme = isValidScheme(decoded?.accepted?.scheme)\n ? decoded.accepted.scheme\n : 'nvm:erc4337'\n try {\n const paymentRequired: X402PaymentRequired = buildPaymentRequired(planId, {\n endpoint: endpoint || '',\n agentId,\n httpVerb,\n scheme,\n environment: this.payments.getEnvironmentName(),\n })\n\n return await this.payments.facilitator.settlePermissions({\n paymentRequired,\n x402AccessToken: token,\n maxAmount: credits,\n })\n } catch (primaryError) {\n // If logical URL fails and we have an HTTP URL fallback, retry with it\n let lastError: unknown = primaryError\n if (fallbackEndpoint) {\n try {\n const paymentRequired: X402PaymentRequired = buildPaymentRequired(planId, {\n endpoint: fallbackEndpoint,\n agentId,\n httpVerb,\n scheme,\n environment: this.payments.getEnvironmentName(),\n })\n\n return await this.payments.facilitator.settlePermissions({\n paymentRequired,\n x402AccessToken: token,\n maxAmount: credits,\n })\n } catch (fallbackError) {\n // Fallback also failed, use fallback error as the reported error\n lastError = fallbackError\n }\n }\n\n const errorReason = lastError instanceof Error ? lastError.message : String(lastError)\n console.error(`[x402] settle failed: ${errorReason}`)\n if (options.onRedeemError === 'propagate') {\n throw createRpcError(\n ERROR_CODES.Misconfiguration,\n `Failed to redeem credits: ${errorReason}`,\n )\n }\n // Default (\"ignore\"): return a failed result so the caller suppresses the\n // tool content and surfaces the in-band payment error (always-suppress\n // under the x402 v2 MCP transport).\n return { success: false, transaction: '', network: '', errorReason }\n }\n }\n}\n\n/**\n * Type guard to detect AsyncIterable values.\n */\nfunction isAsyncIterable<T = unknown>(value: any): value is AsyncIterable<T> {\n return value != null && typeof value[Symbol.asyncIterator] === 'function'\n}\n\n/**\n * Wrap an AsyncIterable with metadata injection at the end of the stream\n */\nfunction wrapAsyncIterable<T>(\n iterable: AsyncIterable<T>,\n onFinally: () => Promise<any>,\n planId: string,\n subscriberAddress: Address,\n credits: bigint,\n) {\n async function* generator() {\n let creditsResult: any = null\n try {\n for await (const chunk of iterable) {\n yield chunk as T\n }\n } finally {\n creditsResult = await onFinally()\n }\n\n // Yield a _meta chunk at the end with the redemption result.\n // NOTE: a stream cannot retroactively suppress already-yielded chunks, so a\n // post-execution settlement failure on a stream is only reported here in the\n // final _meta chunk (under nevermined/credits) — it cannot withhold content\n // the way a non-streaming tool result does. `creditsResult` is undefined for\n // free / no-credit calls.\n const settlement = creditsResult || undefined\n const metadataChunk = {\n _meta: {\n // Spec receipt only on a successful settlement.\n ...(settlement?.success && { [X402_PAYMENT_RESPONSE_META_KEY]: settlement }),\n // Nevermined-namespaced observability (NOT part of the x402 spec).\n [NEVERMINED_CREDITS_META_KEY]: {\n ...(settlement?.transaction && { txHash: settlement.transaction }),\n creditsRedeemed: settlement?.success\n ? (settlement.creditsRedeemed ?? credits.toString())\n : '0',\n remainingBalance: settlement?.remainingBalance,\n planId,\n subscriberAddress,\n success: settlement ? settlement.success : true,\n ...(settlement?.errorReason && { errorReason: settlement.errorReason }),\n },\n },\n }\n yield metadataChunk as T\n }\n return generator()\n}\n"]}
|
|
@@ -14,4 +14,30 @@ export declare function createRpcError(code: ErrorCode, message: string, data?:
|
|
|
14
14
|
code: number;
|
|
15
15
|
data?: any;
|
|
16
16
|
};
|
|
17
|
+
/**
|
|
18
|
+
* Raised by the paywall when payment is required (x402 v2 MCP transport).
|
|
19
|
+
*
|
|
20
|
+
* Carries the spec-shaped `PaymentRequired` object so the tool paywall wrapper
|
|
21
|
+
* can surface it *in band* as a `CallToolResult({ isError: true, ... })`. Also
|
|
22
|
+
* exposes a JSON-RPC `code` so that non-tool paths (resources / prompts), which
|
|
23
|
+
* cannot return a tool-result error, still degrade to a JSON-RPC error when the
|
|
24
|
+
* exception propagates. Note: the MCP SDK's low-level catch-all only forwards
|
|
25
|
+
* the error message (not `code`) to the wire for those paths.
|
|
26
|
+
*/
|
|
27
|
+
export declare class PaymentRequiredError extends Error {
|
|
28
|
+
paymentRequired: Record<string, any>;
|
|
29
|
+
code: number;
|
|
30
|
+
constructor(paymentRequired: Record<string, any>, message?: string);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Raised when settlement fails AFTER the tool has already executed.
|
|
34
|
+
*
|
|
35
|
+
* Same in-band shape as {@link PaymentRequiredError}; the tool paywall wrapper
|
|
36
|
+
* suppresses the already-computed tool content and returns only the payment
|
|
37
|
+
* error, per the x402 v2 MCP transport spec ("do not return the tool's content
|
|
38
|
+
* if settlement fails").
|
|
39
|
+
*/
|
|
40
|
+
export declare class SettlementFailedError extends PaymentRequiredError {
|
|
41
|
+
constructor(paymentRequired: Record<string, any>, message?: string);
|
|
42
|
+
}
|
|
17
43
|
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/mcp/utils/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,WAAW;;;CAGd,CAAA;AAEV,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,OAAO,WAAW,CAAC,CAAA;AAEtE;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG;UAClB,MAAM;WAAS,GAAG;EAK1E"}
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/mcp/utils/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,WAAW;;;CAGd,CAAA;AAEV,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,OAAO,WAAW,CAAC,CAAA;AAEtE;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG;UAClB,MAAM;WAAS,GAAG;EAK1E;AAED;;;;;;;;;GASG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;IAGpC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAF7C,IAAI,EAAE,MAAM,CAA8B;gBAEjC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC3C,OAAO,SAAqB;CAK/B;AAED;;;;;;;GAOG;AACH,qBAAa,qBAAsB,SAAQ,oBAAoB;gBAE3D,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACpC,OAAO,SAA2C;CAKrD"}
|
package/dist/mcp/utils/errors.js
CHANGED
|
@@ -17,4 +17,36 @@ export function createRpcError(code, message, data) {
|
|
|
17
17
|
rpcError.data = data;
|
|
18
18
|
return rpcError;
|
|
19
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Raised by the paywall when payment is required (x402 v2 MCP transport).
|
|
22
|
+
*
|
|
23
|
+
* Carries the spec-shaped `PaymentRequired` object so the tool paywall wrapper
|
|
24
|
+
* can surface it *in band* as a `CallToolResult({ isError: true, ... })`. Also
|
|
25
|
+
* exposes a JSON-RPC `code` so that non-tool paths (resources / prompts), which
|
|
26
|
+
* cannot return a tool-result error, still degrade to a JSON-RPC error when the
|
|
27
|
+
* exception propagates. Note: the MCP SDK's low-level catch-all only forwards
|
|
28
|
+
* the error message (not `code`) to the wire for those paths.
|
|
29
|
+
*/
|
|
30
|
+
export class PaymentRequiredError extends Error {
|
|
31
|
+
constructor(paymentRequired, message = 'Payment required') {
|
|
32
|
+
super(message);
|
|
33
|
+
this.paymentRequired = paymentRequired;
|
|
34
|
+
this.code = ERROR_CODES.PaymentRequired;
|
|
35
|
+
this.name = 'PaymentRequiredError';
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Raised when settlement fails AFTER the tool has already executed.
|
|
40
|
+
*
|
|
41
|
+
* Same in-band shape as {@link PaymentRequiredError}; the tool paywall wrapper
|
|
42
|
+
* suppresses the already-computed tool content and returns only the payment
|
|
43
|
+
* error, per the x402 v2 MCP transport spec ("do not return the tool's content
|
|
44
|
+
* if settlement fails").
|
|
45
|
+
*/
|
|
46
|
+
export class SettlementFailedError extends PaymentRequiredError {
|
|
47
|
+
constructor(paymentRequired, message = 'Settlement failed after tool execution') {
|
|
48
|
+
super(paymentRequired, message);
|
|
49
|
+
this.name = 'SettlementFailedError';
|
|
50
|
+
}
|
|
51
|
+
}
|
|
20
52
|
//# sourceMappingURL=errors.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/mcp/utils/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,gBAAgB,EAAE,CAAC,KAAK;IACxB,eAAe,EAAE,CAAC,KAAK;CACf,CAAA;AAIV;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,IAAe,EAAE,OAAe,EAAE,IAAU;IACzE,MAAM,QAAQ,GAAG,IAAI,KAAK,CAAC,OAAO,CAAyC,CAAA;IAC3E,QAAQ,CAAC,IAAI,GAAG,cAAc,CAAA;IAC9B,QAAQ,CAAC,IAAI,GAAG,IAAI,CAAA;IACpB,IAAI,IAAI,KAAK,SAAS;QAAE,QAAQ,CAAC,IAAI,GAAG,IAAI,CAAA;IAC5C,OAAO,QAAQ,CAAA;AACjB,CAAC","sourcesContent":["/**\n * Error utilities and common JSON-RPC error codes used by the MCP paywall.\n */\n\nexport const ERROR_CODES = {\n Misconfiguration: -32002,\n PaymentRequired: -32003,\n} as const\n\nexport type ErrorCode = (typeof ERROR_CODES)[keyof typeof ERROR_CODES]\n\n/**\n * Create a JSON-RPC-like error object preserving numeric code and message.\n * Returns an Error instance augmented with a numeric `code` and optional `data`.\n */\nexport function createRpcError(code: ErrorCode, message: string, data?: any) {\n const rpcError = new Error(message) as Error & { code: number; data?: any }\n rpcError.name = 'JSONRpcError'\n rpcError.code = code\n if (data !== undefined) rpcError.data = data\n return rpcError\n}\n"]}
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/mcp/utils/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,gBAAgB,EAAE,CAAC,KAAK;IACxB,eAAe,EAAE,CAAC,KAAK;CACf,CAAA;AAIV;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,IAAe,EAAE,OAAe,EAAE,IAAU;IACzE,MAAM,QAAQ,GAAG,IAAI,KAAK,CAAC,OAAO,CAAyC,CAAA;IAC3E,QAAQ,CAAC,IAAI,GAAG,cAAc,CAAA;IAC9B,QAAQ,CAAC,IAAI,GAAG,IAAI,CAAA;IACpB,IAAI,IAAI,KAAK,SAAS;QAAE,QAAQ,CAAC,IAAI,GAAG,IAAI,CAAA;IAC5C,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IAE7C,YACS,eAAoC,EAC3C,OAAO,GAAG,kBAAkB;QAE5B,KAAK,CAAC,OAAO,CAAC,CAAA;QAHP,oBAAe,GAAf,eAAe,CAAqB;QAF7C,SAAI,GAAW,WAAW,CAAC,eAAe,CAAA;QAMxC,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAA;IACpC,CAAC;CACF;AAED;;;;;;;GAOG;AACH,MAAM,OAAO,qBAAsB,SAAQ,oBAAoB;IAC7D,YACE,eAAoC,EACpC,OAAO,GAAG,wCAAwC;QAElD,KAAK,CAAC,eAAe,EAAE,OAAO,CAAC,CAAA;QAC/B,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAA;IACrC,CAAC;CACF","sourcesContent":["/**\n * Error utilities and common JSON-RPC error codes used by the MCP paywall.\n */\n\nexport const ERROR_CODES = {\n Misconfiguration: -32002,\n PaymentRequired: -32003,\n} as const\n\nexport type ErrorCode = (typeof ERROR_CODES)[keyof typeof ERROR_CODES]\n\n/**\n * Create a JSON-RPC-like error object preserving numeric code and message.\n * Returns an Error instance augmented with a numeric `code` and optional `data`.\n */\nexport function createRpcError(code: ErrorCode, message: string, data?: any) {\n const rpcError = new Error(message) as Error & { code: number; data?: any }\n rpcError.name = 'JSONRpcError'\n rpcError.code = code\n if (data !== undefined) rpcError.data = data\n return rpcError\n}\n\n/**\n * Raised by the paywall when payment is required (x402 v2 MCP transport).\n *\n * Carries the spec-shaped `PaymentRequired` object so the tool paywall wrapper\n * can surface it *in band* as a `CallToolResult({ isError: true, ... })`. Also\n * exposes a JSON-RPC `code` so that non-tool paths (resources / prompts), which\n * cannot return a tool-result error, still degrade to a JSON-RPC error when the\n * exception propagates. Note: the MCP SDK's low-level catch-all only forwards\n * the error message (not `code`) to the wire for those paths.\n */\nexport class PaymentRequiredError extends Error {\n code: number = ERROR_CODES.PaymentRequired\n constructor(\n public paymentRequired: Record<string, any>,\n message = 'Payment required',\n ) {\n super(message)\n this.name = 'PaymentRequiredError'\n }\n}\n\n/**\n * Raised when settlement fails AFTER the tool has already executed.\n *\n * Same in-band shape as {@link PaymentRequiredError}; the tool paywall wrapper\n * suppresses the already-computed tool content and returns only the payment\n * error, per the x402 v2 MCP transport spec (\"do not return the tool's content\n * if settlement fails\").\n */\nexport class SettlementFailedError extends PaymentRequiredError {\n constructor(\n paymentRequired: Record<string, any>,\n message = 'Settlement failed after tool execution',\n ) {\n super(paymentRequired, message)\n this.name = 'SettlementFailedError'\n }\n}\n"]}
|
|
@@ -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
CHANGED
|
@@ -100,8 +100,9 @@ export declare class Payments extends BasePaymentsAPI {
|
|
|
100
100
|
* Returns the Delegation API for listing enrolled payment methods.
|
|
101
101
|
* The instance is lazily initialized on first access — the current
|
|
102
102
|
* organization pin (set via `setOrganizationId` or the constructor
|
|
103
|
-
* option)
|
|
104
|
-
* `X-Current-Org-Id`
|
|
103
|
+
* option) and the backend API version pin (`options.version`) are
|
|
104
|
+
* forwarded so the first call carries the right `X-Current-Org-Id`
|
|
105
|
+
* and `Nevermined-Version` headers.
|
|
105
106
|
*/
|
|
106
107
|
get delegation(): DelegationAPI;
|
|
107
108
|
/**
|
|
@@ -139,7 +140,7 @@ export declare class Payments extends BasePaymentsAPI {
|
|
|
139
140
|
* returnUrl: 'https://mysite.example',
|
|
140
141
|
* environment: 'sandbox',
|
|
141
142
|
* appId: 'my-app-id',
|
|
142
|
-
* version: '1.
|
|
143
|
+
* version: '1.1'
|
|
143
144
|
* })
|
|
144
145
|
* ```
|
|
145
146
|
* @returns An instance of {@link Payments}
|
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;;;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"}
|
package/dist/payments.js
CHANGED
|
@@ -66,8 +66,9 @@ export class Payments extends BasePaymentsAPI {
|
|
|
66
66
|
* Returns the Delegation API for listing enrolled payment methods.
|
|
67
67
|
* The instance is lazily initialized on first access — the current
|
|
68
68
|
* organization pin (set via `setOrganizationId` or the constructor
|
|
69
|
-
* option)
|
|
70
|
-
* `X-Current-Org-Id`
|
|
69
|
+
* option) and the backend API version pin (`options.version`) are
|
|
70
|
+
* forwarded so the first call carries the right `X-Current-Org-Id`
|
|
71
|
+
* and `Nevermined-Version` headers.
|
|
71
72
|
*/
|
|
72
73
|
get delegation() {
|
|
73
74
|
if (!this._delegation) {
|
|
@@ -75,6 +76,7 @@ export class Payments extends BasePaymentsAPI {
|
|
|
75
76
|
nvmApiKey: this.nvmApiKey,
|
|
76
77
|
environment: this.environmentName,
|
|
77
78
|
organizationId: this.currentOrganizationId ?? undefined,
|
|
79
|
+
version: this.version,
|
|
78
80
|
});
|
|
79
81
|
}
|
|
80
82
|
return this._delegation;
|
|
@@ -112,7 +114,7 @@ export class Payments extends BasePaymentsAPI {
|
|
|
112
114
|
* returnUrl: 'https://mysite.example',
|
|
113
115
|
* environment: 'sandbox',
|
|
114
116
|
* appId: 'my-app-id',
|
|
115
|
-
* version: '1.
|
|
117
|
+
* version: '1.1'
|
|
116
118
|
* })
|
|
117
119
|
* ```
|
|
118
120
|
* @returns An instance of {@link Payments}
|
package/dist/payments.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payments.js","sourceRoot":"","sources":["../src/payments.ts"],"names":[],"mappings":"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","sourcesContent":["import { AIQueryApi } from './api/query-api.js'\nimport { PaymentsError } from './common/payments.error.js'\nimport { PaymentOptions } from './common/types.js'\nimport { BasePaymentsAPI } from './api/base-payments.js'\nimport { PlansAPI } from './api/plans-api.js'\nimport { ContractsAPI } from './api/contracts-api.js'\nimport { AgentsAPI } from './api/agents-api.js'\nimport { AgentRequestsAPI } from './api/requests-api.js'\nimport { ObservabilityAPI } from './api/observability-api/observability-api.js'\nimport { ClientRegistry } from './a2a/clientRegistry.js'\nimport type { PaymentsA2AServerOptions, PaymentsA2AServerResult } from './a2a/server.js'\nimport { PaymentsA2AServer } from './a2a/server.js'\nimport { buildPaymentAgentCard } from './a2a/agent-card.js'\nimport * as mcpModule from './mcp/index.js'\nimport { OrganizationsAPI } from './api/organizations-api/organizations-api.js'\nimport { FacilitatorAPI } from './x402/facilitator-api.js'\nimport { X402TokenAPI } from './x402/token.js'\nimport { DelegationAPI } from './x402/delegation-api.js'\n\n/**\n * Main class that interacts with the Nevermined payments API.\n * Use `Payments.getInstance` for server-side usage or `Payments.getBrowserInstance` for browser usage.\n * @remarks This API requires a Nevermined API Key, which can be obtained by logging in to the Nevermined App.\n *\n * The library provides methods to manage AI Agents, Plans & process AI Agent Requests.\n *\n * Each of these functionalities is encapsulated in its own API class:\n * - `plans`: Manages AI Plans, including registration and ordering and retrieving plan details.\n * - `agents`: Handles AI Agents, including registration of AI Agents and access token generation.\n * - `requests`: Manages requests received by AI Agents, including validation and tracking.\n * - `observability`: Provides observability and logging utilities for AI Agents with Helicone integration\n */\nexport class Payments extends BasePaymentsAPI {\n public query!: AIQueryApi\n public plans!: PlansAPI\n public agents!: AgentsAPI\n public requests!: AgentRequestsAPI\n public observability!: ObservabilityAPI\n public organizations!: OrganizationsAPI\n public contracts!: ContractsAPI\n public facilitator!: FacilitatorAPI\n public x402!: X402TokenAPI\n private _a2aRegistry?: ClientRegistry\n private _delegation?: DelegationAPI\n\n /**\n * Cached MCP integration to preserve configuration (e.g., agentId, serverName)\n * across multiple getter accesses. This ensures callers do not need to retain\n * a reference to a previously configured instance.\n */\n private _mcpIntegration?: ReturnType<typeof mcpModule.buildMcpIntegration>\n\n /**\n * Exposes A2A server and client registry methods.\n * The client registry is initialized only if getClient is called.\n */\n public get a2a() {\n return {\n /**\n * Starts the A2A server with payment integration.\n * @param options - Server options.\n */\n start: (\n options: Omit<PaymentsA2AServerOptions, 'paymentsService'>,\n ): PaymentsA2AServerResult => PaymentsA2AServer.start({ ...options, paymentsService: this }),\n\n /**\n * Gets (or creates) a RegisteredPaymentsClient for the given alias.\n * The registry is initialized only on first use.\n * @param options - ClientRegistryOptions.\n */\n getClient: async (options: any) => {\n if (!this._a2aRegistry) {\n this._a2aRegistry = new ClientRegistry(this)\n }\n return await this._a2aRegistry.getClient(options)\n },\n }\n }\n\n /**\n * Returns the MCP integration API. The instance is memoized so that configuration\n * set via `configure({ agentId, serverName })` persists across calls.\n */\n public get mcp() {\n if (!this._mcpIntegration) {\n this._mcpIntegration = mcpModule.buildMcpIntegration(this)\n }\n return this._mcpIntegration\n }\n\n /**\n * Returns the Delegation API for listing enrolled payment methods.\n * The instance is lazily initialized on first access — the current\n * organization pin (set via `setOrganizationId` or the constructor\n * option) is forwarded so the first call carries the right\n * `X-Current-Org-Id` header.\n */\n public get delegation(): DelegationAPI {\n if (!this._delegation) {\n this._delegation = DelegationAPI.getInstance({\n nvmApiKey: this.nvmApiKey,\n environment: this.environmentName,\n organizationId: this.currentOrganizationId ?? undefined,\n })\n }\n return this._delegation\n }\n\n /**\n * Static A2A helpers and utilities.\n * Example: Payments.a2a.buildPaymentAgentCard(...)\n */\n static a2a = { buildPaymentAgentCard }\n\n /**\n * Get an instance of the Payments class for server-side usage.\n *\n * @param options - The options to initialize the payments class.\n * @example\n * ```\n * const payments = Payments.getInstance({\n * nvmApiKey: 'your-nvm-api-key',\n * environment: 'sandbox'\n * })\n * ```\n * @returns An instance of {@link Payments}\n * @throws PaymentsError if nvmApiKey is missing.\n */\n static getInstance(options: PaymentOptions) {\n if (!options.nvmApiKey) {\n throw new PaymentsError('Nevermined API Key is required')\n }\n return new Payments(options, false)\n }\n\n /**\n * Get an instance of the Payments class for browser usage.\n *\n * @remarks\n * This is a browser-only function.\n *\n * @param options - The options to initialize the payments class.\n * @example\n * ```\n * const payments = Payments.getBrowserInstance({\n * returnUrl: 'https://mysite.example',\n * environment: 'sandbox',\n * appId: 'my-app-id',\n * version: '1.0.0'\n * })\n * ```\n * @returns An instance of {@link Payments}\n * @throws PaymentsError if returnUrl is missing.\n */\n static getBrowserInstance(options: PaymentOptions) {\n if (!options.returnUrl) {\n throw new PaymentsError('returnUrl is required')\n }\n const url = new URL(window.location.href)\n const urlNvmApiKey = url.searchParams.get('nvmApiKey') as string\n if (urlNvmApiKey) {\n url.searchParams.delete('nvmApiKey')\n }\n\n const urlAccountAddress = url.searchParams.get('accountAddress') as string\n if (urlAccountAddress) {\n url.searchParams.delete('accountAddress')\n }\n\n history.replaceState(history.state, '', url.toString())\n\n return new Payments(options, true)\n }\n\n /**\n * Initializes the Payments class.\n *\n * @param options - The options to initialize the payments class.\n * @param isBrowserInstance - Whether this instance is for browser usage.\n */\n private constructor(options: PaymentOptions, isBrowserInstance = true) {\n super(options)\n\n this.isBrowserInstance = isBrowserInstance\n this.initializeApi(options)\n }\n\n /**\n * Initializes the AI Query Protocol API.\n */\n private initializeApi(options: PaymentOptions) {\n this.plans = PlansAPI.getInstance(options)\n this.agents = AgentsAPI.getInstance(options)\n this.requests = AgentRequestsAPI.getInstance(options)\n this.observability = ObservabilityAPI.getInstance(options)\n this.organizations = OrganizationsAPI.getInstance(options)\n this.query = AIQueryApi.getInstance()\n this.contracts = new ContractsAPI(options)\n this.facilitator = FacilitatorAPI.getInstance(options)\n this.x402 = X402TokenAPI.getInstance(options)\n }\n\n /**\n * Initiates the connect flow. The user's browser will be redirected to\n * the Nevermined App login page.\n *\n * @remarks\n * This is a browser-only function.\n * @example\n * ```\n * payments.connect()\n * ```\n */\n public connect() {\n if (!this.isBrowserInstance) return\n const url = new URL(`/login?returnUrl=${this.returnUrl}`, this.environment.frontend)\n window.location.href = url.toString()\n }\n\n /**\n * Logs out the user by removing the NVM API key.\n *\n * @remarks\n * This is a browser-only function.\n * @example\n * ```\n * payments.logout()\n * ```\n */\n public logout() {\n this.nvmApiKey = ''\n }\n\n /**\n * Pins (or clears) the active organization workspace used by every\n * subsequent authenticated request. The SDK forwards the choice as the\n * `X-Current-Org-Id` header so the backend scopes publications and\n * other org-aware queries to the requested organization.\n *\n * Pass `null` to clear the pin and let the backend fall back to the\n * API key's org tag or the caller's most-recent active membership.\n *\n * For one-off targeting (e.g. publish a single agent into Org B without\n * leaving Org B as the active workspace) prefer the per-call\n * `{ organizationId }` option on `agents.registerAgent` /\n * `plans.registerPlan` / similar.\n *\n * @param organizationId - Org ID to pin (e.g. `org-…`) or `null` to clear.\n * @example\n * ```ts\n * payments.setOrganizationId('org-abc123')\n * await payments.agents.registerAgent(metadata, api, [planId]) // lands in org-abc123\n * ```\n */\n public override setOrganizationId(organizationId: string | null): void {\n super.setOrganizationId(organizationId)\n this.plans?.setOrganizationId(organizationId)\n this.agents?.setOrganizationId(organizationId)\n this.requests?.setOrganizationId(organizationId)\n this.observability?.setOrganizationId(organizationId)\n this.organizations?.setOrganizationId(organizationId)\n this.contracts?.setOrganizationId(organizationId)\n this.facilitator?.setOrganizationId(organizationId)\n this.x402?.setOrganizationId(organizationId)\n // `_delegation` is lazy — the getter forwards `currentOrganizationId`\n // on first access, so only propagate to an already-built instance.\n // (Eagerly constructing it here would change the lazy contract.)\n this._delegation?.setOrganizationId(organizationId)\n }\n\n /**\n * Checks if a user is logged in.\n * @example\n * ```\n * payments.isLoggedIn\n * ```\n * @returns True if the user is logged in.\n */\n get isLoggedIn(): boolean {\n return this.nvmApiKey.length > 0\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"payments.js","sourceRoot":"","sources":["../src/payments.ts"],"names":[],"mappings":"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","sourcesContent":["import { AIQueryApi } from './api/query-api.js'\nimport { PaymentsError } from './common/payments.error.js'\nimport { PaymentOptions } from './common/types.js'\nimport { BasePaymentsAPI } from './api/base-payments.js'\nimport { PlansAPI } from './api/plans-api.js'\nimport { ContractsAPI } from './api/contracts-api.js'\nimport { AgentsAPI } from './api/agents-api.js'\nimport { AgentRequestsAPI } from './api/requests-api.js'\nimport { ObservabilityAPI } from './api/observability-api/observability-api.js'\nimport { ClientRegistry } from './a2a/clientRegistry.js'\nimport type { PaymentsA2AServerOptions, PaymentsA2AServerResult } from './a2a/server.js'\nimport { PaymentsA2AServer } from './a2a/server.js'\nimport { buildPaymentAgentCard } from './a2a/agent-card.js'\nimport * as mcpModule from './mcp/index.js'\nimport { OrganizationsAPI } from './api/organizations-api/organizations-api.js'\nimport { FacilitatorAPI } from './x402/facilitator-api.js'\nimport { X402TokenAPI } from './x402/token.js'\nimport { DelegationAPI } from './x402/delegation-api.js'\n\n/**\n * Main class that interacts with the Nevermined payments API.\n * Use `Payments.getInstance` for server-side usage or `Payments.getBrowserInstance` for browser usage.\n * @remarks This API requires a Nevermined API Key, which can be obtained by logging in to the Nevermined App.\n *\n * The library provides methods to manage AI Agents, Plans & process AI Agent Requests.\n *\n * Each of these functionalities is encapsulated in its own API class:\n * - `plans`: Manages AI Plans, including registration and ordering and retrieving plan details.\n * - `agents`: Handles AI Agents, including registration of AI Agents and access token generation.\n * - `requests`: Manages requests received by AI Agents, including validation and tracking.\n * - `observability`: Provides observability and logging utilities for AI Agents with Helicone integration\n */\nexport class Payments extends BasePaymentsAPI {\n public query!: AIQueryApi\n public plans!: PlansAPI\n public agents!: AgentsAPI\n public requests!: AgentRequestsAPI\n public observability!: ObservabilityAPI\n public organizations!: OrganizationsAPI\n public contracts!: ContractsAPI\n public facilitator!: FacilitatorAPI\n public x402!: X402TokenAPI\n private _a2aRegistry?: ClientRegistry\n private _delegation?: DelegationAPI\n\n /**\n * Cached MCP integration to preserve configuration (e.g., agentId, serverName)\n * across multiple getter accesses. This ensures callers do not need to retain\n * a reference to a previously configured instance.\n */\n private _mcpIntegration?: ReturnType<typeof mcpModule.buildMcpIntegration>\n\n /**\n * Exposes A2A server and client registry methods.\n * The client registry is initialized only if getClient is called.\n */\n public get a2a() {\n return {\n /**\n * Starts the A2A server with payment integration.\n * @param options - Server options.\n */\n start: (\n options: Omit<PaymentsA2AServerOptions, 'paymentsService'>,\n ): PaymentsA2AServerResult => PaymentsA2AServer.start({ ...options, paymentsService: this }),\n\n /**\n * Gets (or creates) a RegisteredPaymentsClient for the given alias.\n * The registry is initialized only on first use.\n * @param options - ClientRegistryOptions.\n */\n getClient: async (options: any) => {\n if (!this._a2aRegistry) {\n this._a2aRegistry = new ClientRegistry(this)\n }\n return await this._a2aRegistry.getClient(options)\n },\n }\n }\n\n /**\n * Returns the MCP integration API. The instance is memoized so that configuration\n * set via `configure({ agentId, serverName })` persists across calls.\n */\n public get mcp() {\n if (!this._mcpIntegration) {\n this._mcpIntegration = mcpModule.buildMcpIntegration(this)\n }\n return this._mcpIntegration\n }\n\n /**\n * Returns the Delegation API for listing enrolled payment methods.\n * The instance is lazily initialized on first access — the current\n * organization pin (set via `setOrganizationId` or the constructor\n * option) and the backend API version pin (`options.version`) are\n * forwarded so the first call carries the right `X-Current-Org-Id`\n * and `Nevermined-Version` headers.\n */\n public get delegation(): DelegationAPI {\n if (!this._delegation) {\n this._delegation = DelegationAPI.getInstance({\n nvmApiKey: this.nvmApiKey,\n environment: this.environmentName,\n organizationId: this.currentOrganizationId ?? undefined,\n version: this.version,\n })\n }\n return this._delegation\n }\n\n /**\n * Static A2A helpers and utilities.\n * Example: Payments.a2a.buildPaymentAgentCard(...)\n */\n static a2a = { buildPaymentAgentCard }\n\n /**\n * Get an instance of the Payments class for server-side usage.\n *\n * @param options - The options to initialize the payments class.\n * @example\n * ```\n * const payments = Payments.getInstance({\n * nvmApiKey: 'your-nvm-api-key',\n * environment: 'sandbox'\n * })\n * ```\n * @returns An instance of {@link Payments}\n * @throws PaymentsError if nvmApiKey is missing.\n */\n static getInstance(options: PaymentOptions) {\n if (!options.nvmApiKey) {\n throw new PaymentsError('Nevermined API Key is required')\n }\n return new Payments(options, false)\n }\n\n /**\n * Get an instance of the Payments class for browser usage.\n *\n * @remarks\n * This is a browser-only function.\n *\n * @param options - The options to initialize the payments class.\n * @example\n * ```\n * const payments = Payments.getBrowserInstance({\n * returnUrl: 'https://mysite.example',\n * environment: 'sandbox',\n * appId: 'my-app-id',\n * version: '1.1'\n * })\n * ```\n * @returns An instance of {@link Payments}\n * @throws PaymentsError if returnUrl is missing.\n */\n static getBrowserInstance(options: PaymentOptions) {\n if (!options.returnUrl) {\n throw new PaymentsError('returnUrl is required')\n }\n const url = new URL(window.location.href)\n const urlNvmApiKey = url.searchParams.get('nvmApiKey') as string\n if (urlNvmApiKey) {\n url.searchParams.delete('nvmApiKey')\n }\n\n const urlAccountAddress = url.searchParams.get('accountAddress') as string\n if (urlAccountAddress) {\n url.searchParams.delete('accountAddress')\n }\n\n history.replaceState(history.state, '', url.toString())\n\n return new Payments(options, true)\n }\n\n /**\n * Initializes the Payments class.\n *\n * @param options - The options to initialize the payments class.\n * @param isBrowserInstance - Whether this instance is for browser usage.\n */\n private constructor(options: PaymentOptions, isBrowserInstance = true) {\n super(options)\n\n this.isBrowserInstance = isBrowserInstance\n this.initializeApi(options)\n }\n\n /**\n * Initializes the AI Query Protocol API.\n */\n private initializeApi(options: PaymentOptions) {\n this.plans = PlansAPI.getInstance(options)\n this.agents = AgentsAPI.getInstance(options)\n this.requests = AgentRequestsAPI.getInstance(options)\n this.observability = ObservabilityAPI.getInstance(options)\n this.organizations = OrganizationsAPI.getInstance(options)\n this.query = AIQueryApi.getInstance()\n this.contracts = new ContractsAPI(options)\n this.facilitator = FacilitatorAPI.getInstance(options)\n this.x402 = X402TokenAPI.getInstance(options)\n }\n\n /**\n * Initiates the connect flow. The user's browser will be redirected to\n * the Nevermined App login page.\n *\n * @remarks\n * This is a browser-only function.\n * @example\n * ```\n * payments.connect()\n * ```\n */\n public connect() {\n if (!this.isBrowserInstance) return\n const url = new URL(`/login?returnUrl=${this.returnUrl}`, this.environment.frontend)\n window.location.href = url.toString()\n }\n\n /**\n * Logs out the user by removing the NVM API key.\n *\n * @remarks\n * This is a browser-only function.\n * @example\n * ```\n * payments.logout()\n * ```\n */\n public logout() {\n this.nvmApiKey = ''\n }\n\n /**\n * Pins (or clears) the active organization workspace used by every\n * subsequent authenticated request. The SDK forwards the choice as the\n * `X-Current-Org-Id` header so the backend scopes publications and\n * other org-aware queries to the requested organization.\n *\n * Pass `null` to clear the pin and let the backend fall back to the\n * API key's org tag or the caller's most-recent active membership.\n *\n * For one-off targeting (e.g. publish a single agent into Org B without\n * leaving Org B as the active workspace) prefer the per-call\n * `{ organizationId }` option on `agents.registerAgent` /\n * `plans.registerPlan` / similar.\n *\n * @param organizationId - Org ID to pin (e.g. `org-…`) or `null` to clear.\n * @example\n * ```ts\n * payments.setOrganizationId('org-abc123')\n * await payments.agents.registerAgent(metadata, api, [planId]) // lands in org-abc123\n * ```\n */\n public override setOrganizationId(organizationId: string | null): void {\n super.setOrganizationId(organizationId)\n this.plans?.setOrganizationId(organizationId)\n this.agents?.setOrganizationId(organizationId)\n this.requests?.setOrganizationId(organizationId)\n this.observability?.setOrganizationId(organizationId)\n this.organizations?.setOrganizationId(organizationId)\n this.contracts?.setOrganizationId(organizationId)\n this.facilitator?.setOrganizationId(organizationId)\n this.x402?.setOrganizationId(organizationId)\n // `_delegation` is lazy — the getter forwards `currentOrganizationId`\n // on first access, so only propagate to an already-built instance.\n // (Eagerly constructing it here would change the lazy contract.)\n this._delegation?.setOrganizationId(organizationId)\n }\n\n /**\n * Checks if a user is logged in.\n * @example\n * ```\n * payments.isLoggedIn\n * ```\n * @returns True if the user is logged in.\n */\n get isLoggedIn(): boolean {\n return this.nvmApiKey.length > 0\n }\n}\n"]}
|
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"]}
|