@devlab.group/agent-commerce 1.6.1 → 2.1.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/LICENSE +187 -2
- package/README.md +105 -54
- package/dist/ap2.d.ts +4 -4
- package/dist/ap2.js +95 -28
- package/dist/ap2.js.map +1 -1
- package/dist/{authorization-BpbWGGrf.d.ts → authorization-CMkIuAkO.d.ts} +1 -1
- package/dist/chunk-2CJNA7MS.js +8 -0
- package/dist/chunk-2CJNA7MS.js.map +1 -0
- package/dist/chunk-5ZYXBCDX.js +113 -0
- package/dist/chunk-5ZYXBCDX.js.map +1 -0
- package/dist/{chunk-V2V2E7HX.js → chunk-6Z2H53CG.js} +7 -6
- package/dist/chunk-6Z2H53CG.js.map +1 -0
- package/dist/chunk-ES3V6ECS.js +125 -0
- package/dist/chunk-ES3V6ECS.js.map +1 -0
- package/dist/chunk-IFGRCXME.js +581 -0
- package/dist/chunk-IFGRCXME.js.map +1 -0
- package/dist/chunk-KA2AX5FH.js +44 -0
- package/dist/chunk-KA2AX5FH.js.map +1 -0
- package/dist/{chunk-VKDXMXHL.js → chunk-LZS5BL3W.js} +3 -3
- package/dist/{chunk-VKDXMXHL.js.map → chunk-LZS5BL3W.js.map} +1 -1
- package/dist/{chunk-N5KRK7YA.js → chunk-SY6GUYSQ.js} +6 -10
- package/dist/chunk-SY6GUYSQ.js.map +1 -0
- package/dist/chunk-UHMYRV3J.js +1396 -0
- package/dist/chunk-UHMYRV3J.js.map +1 -0
- package/dist/cli/index.js +2980 -1964
- package/dist/cli/index.js.map +1 -1
- package/dist/{constants-Bkq04FRZ.d.ts → constants-nackLItD.d.ts} +4 -3
- package/dist/{guardrails-71XwtXlT.d.ts → guardrails-CX_jYXvZ.d.ts} +9 -1
- package/dist/index.d.ts +88 -49
- package/dist/index.js +3432 -2161
- package/dist/index.js.map +1 -1
- package/dist/mcp.d.ts +3 -3
- package/dist/mcp.js +252 -94
- package/dist/mcp.js.map +1 -1
- package/dist/mpp.d.ts +15 -4
- package/dist/mpp.js +115 -74
- package/dist/mpp.js.map +1 -1
- package/dist/near-D6C42VPE.js +58 -0
- package/dist/near-D6C42VPE.js.map +1 -0
- package/dist/networks-olfflCI_.d.ts +38 -0
- package/dist/{protocol-adapter-DTkrXTev.d.ts → protocol-adapter-CfxU8Z2T.d.ts} +4 -2
- package/dist/{runtime-CiYbgGpi.d.ts → runtime-7vLNYvmU.d.ts} +25 -3
- package/dist/svm-QEUAUNPQ.js +33 -0
- package/dist/svm-QEUAUNPQ.js.map +1 -0
- package/dist/{types-O6lg3Q5V.d.ts → types-CVw6Sf46.d.ts} +11 -0
- package/dist/x402.d.ts +78 -63
- package/dist/x402.js +13 -4
- package/dist/x402.js.map +1 -1
- package/package.json +36 -13
- package/dist/chunk-AFI2CEZS.js +0 -10
- package/dist/chunk-AFI2CEZS.js.map +0 -1
- package/dist/chunk-CBJIT7QP.js +0 -258
- package/dist/chunk-CBJIT7QP.js.map +0 -1
- package/dist/chunk-JKEKKXRJ.js +0 -680
- package/dist/chunk-JKEKKXRJ.js.map +0 -1
- package/dist/chunk-N5KRK7YA.js.map +0 -1
- package/dist/chunk-V2V2E7HX.js.map +0 -1
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { isRecord } from './chunk-2CJNA7MS.js';
|
|
2
|
+
import { createHash } from 'crypto';
|
|
3
|
+
|
|
4
|
+
// src/payments/mpp/problems.ts
|
|
5
|
+
var MPP_PROBLEM_BASE_URI = "https://paymentauth.org/problems/";
|
|
6
|
+
var TITLES = {
|
|
7
|
+
"payment-required": "Payment Required",
|
|
8
|
+
"malformed-credential": "Malformed Credential",
|
|
9
|
+
"invalid-challenge": "Invalid Challenge",
|
|
10
|
+
"payment-expired": "Payment Expired",
|
|
11
|
+
"verification-failed": "Verification Failed",
|
|
12
|
+
"internal-payment-error": "Internal Payment Error"
|
|
13
|
+
};
|
|
14
|
+
var REASON_TYPES = /* @__PURE__ */ new Map([
|
|
15
|
+
["malformed_credential", "malformed-credential"],
|
|
16
|
+
["invalid_payload", "malformed-credential"],
|
|
17
|
+
["invalid_challenge", "invalid-challenge"],
|
|
18
|
+
["challenge_not_issued", "invalid-challenge"],
|
|
19
|
+
["wrong_realm", "invalid-challenge"],
|
|
20
|
+
["wrong_resource", "invalid-challenge"],
|
|
21
|
+
["challenge_already_used", "invalid-challenge"],
|
|
22
|
+
["challenge_expired", "payment-expired"],
|
|
23
|
+
["authorization_expired", "payment-expired"]
|
|
24
|
+
]);
|
|
25
|
+
function mppProblem(code, httpStatus, reason) {
|
|
26
|
+
const problem = problemType(code, httpStatus, reason);
|
|
27
|
+
return { type: `${MPP_PROBLEM_BASE_URI}${problem}`, title: TITLES[problem] };
|
|
28
|
+
}
|
|
29
|
+
var REASON_DETAILS = /* @__PURE__ */ new Map([
|
|
30
|
+
["wrong_provider", "The challenge was issued for another payment method."],
|
|
31
|
+
["missing_challenge", "No challenge is available for this request."],
|
|
32
|
+
["malformed_credential", "The credential could not be decoded."],
|
|
33
|
+
["invalid_payload", "The credential payload does not match the expected format."],
|
|
34
|
+
["invalid_challenge", "The credential does not answer a valid challenge."],
|
|
35
|
+
["challenge_not_issued", "The challenge was not issued by this server or was altered."],
|
|
36
|
+
["challenge_already_used", "The challenge has already been used for a payment."],
|
|
37
|
+
["challenge_expired", "The challenge has expired."],
|
|
38
|
+
["wrong_realm", "The challenge was issued for another realm."],
|
|
39
|
+
["wrong_resource", "The challenge was issued for another resource."],
|
|
40
|
+
[
|
|
41
|
+
"unsupported_method",
|
|
42
|
+
"The challenge names a payment method or intent this server does not accept."
|
|
43
|
+
],
|
|
44
|
+
["unsupported_credential", "The credential type is not accepted for this challenge."],
|
|
45
|
+
["body_digest_mismatch", "The request body differs from the one the challenge was issued for."],
|
|
46
|
+
["wrong_amount", "The payment amount does not match the challenge."],
|
|
47
|
+
["wrong_recipient", "The payment recipient does not match the challenge."],
|
|
48
|
+
["wrong_network", "The payment uses a different network from the challenge."],
|
|
49
|
+
["wrong_asset", "The payment uses a different asset from the challenge."],
|
|
50
|
+
["wrong_terms", "The payment terms do not match the challenge."],
|
|
51
|
+
["wrong_nonce", "The authorization nonce is not derived from the challenge."],
|
|
52
|
+
["invalid_signature", "The authorization signature does not match the payer."],
|
|
53
|
+
["source_mismatch", "The credential source is not the account that signed the authorization."],
|
|
54
|
+
["authorization_not_yet_valid", "The authorization is not valid yet."],
|
|
55
|
+
["authorization_expired", "The authorization has expired."],
|
|
56
|
+
["authorization_invalid", "The authorization failed verification."],
|
|
57
|
+
["settlement_rejected", "The payment was refused before settlement."],
|
|
58
|
+
["settlement_mismatch", "The payment could not be matched to its settlement."],
|
|
59
|
+
["invalid_exact_evm_insufficient_balance", "The payer balance is too low for this payment."],
|
|
60
|
+
[
|
|
61
|
+
"invalid_exact_evm_transaction_simulation_failed",
|
|
62
|
+
"The transfer failed in simulation, so it was not submitted."
|
|
63
|
+
]
|
|
64
|
+
]);
|
|
65
|
+
function mppProblemDetail(reason, fallback) {
|
|
66
|
+
if (reason === void 0) return fallback;
|
|
67
|
+
return REASON_DETAILS.get(reason) ?? `The payment was refused: ${reason}.`;
|
|
68
|
+
}
|
|
69
|
+
function problemType(code, httpStatus, reason) {
|
|
70
|
+
if (code === "PAYMENT_REQUIRED") return "payment-required";
|
|
71
|
+
if (httpStatus >= 500) return "internal-payment-error";
|
|
72
|
+
if (code === "PAYMENT_REPLAYED") return "invalid-challenge";
|
|
73
|
+
return (reason !== void 0 ? REASON_TYPES.get(reason) : void 0) ?? "verification-failed";
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// src/payments/mpp/transport.ts
|
|
77
|
+
var CONTENT_DIGEST_METADATA_KEY = "contentDigest";
|
|
78
|
+
function contentDigest(body) {
|
|
79
|
+
return `sha-256=:${createHash("sha256").update(body).digest("base64")}:`;
|
|
80
|
+
}
|
|
81
|
+
var MPP_MCP_CREDENTIAL_META_KEY = "org.paymentauth/credential";
|
|
82
|
+
var MPP_MCP_PAYMENT_REQUIRED_META_KEY = "org.paymentauth/payment-required";
|
|
83
|
+
var MPP_MCP_RECEIPT_META_KEY = "org.paymentauth/receipt";
|
|
84
|
+
function mcpPaymentRequired(envelope, refusal) {
|
|
85
|
+
const challenges = isRecord(envelope) ? envelope["challenges"] : void 0;
|
|
86
|
+
if (!Array.isArray(challenges) || challenges.length === 0) return void 0;
|
|
87
|
+
const reason = typeof refusal?.reason === "string" ? refusal.reason : void 0;
|
|
88
|
+
return {
|
|
89
|
+
httpStatus: 402,
|
|
90
|
+
challenges,
|
|
91
|
+
...refusal !== void 0 ? {
|
|
92
|
+
problem: {
|
|
93
|
+
...mppProblem(refusal.code, 402, reason),
|
|
94
|
+
status: 402,
|
|
95
|
+
detail: mppProblemDetail(reason, refusal.detail),
|
|
96
|
+
...reason !== void 0 ? { reason } : {}
|
|
97
|
+
}
|
|
98
|
+
} : {}
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
function receiptObject(serialized) {
|
|
102
|
+
if (typeof serialized !== "string") return void 0;
|
|
103
|
+
try {
|
|
104
|
+
const decoded = JSON.parse(Buffer.from(serialized, "base64url").toString("utf8"));
|
|
105
|
+
return isRecord(decoded) ? decoded : void 0;
|
|
106
|
+
} catch {
|
|
107
|
+
return void 0;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export { CONTENT_DIGEST_METADATA_KEY, MPP_MCP_CREDENTIAL_META_KEY, MPP_MCP_PAYMENT_REQUIRED_META_KEY, MPP_MCP_RECEIPT_META_KEY, contentDigest, mcpPaymentRequired, mppProblem, mppProblemDetail, receiptObject };
|
|
112
|
+
//# sourceMappingURL=chunk-5ZYXBCDX.js.map
|
|
113
|
+
//# sourceMappingURL=chunk-5ZYXBCDX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/payments/mpp/problems.ts","../src/payments/mpp/transport.ts"],"names":[],"mappings":"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","file":"chunk-5ZYXBCDX.js","sourcesContent":["/**\n * Map MPP payment errors to the Problem Details types in\n * `draft-httpauth-payment-01`. This module has no optional peer imports, so\n * the main HTTP route can use it.\n */\n\nexport const MPP_PROBLEM_BASE_URI = 'https://paymentauth.org/problems/';\n\nexport type MppProblemType =\n | 'payment-required'\n | 'malformed-credential'\n | 'invalid-challenge'\n | 'payment-expired'\n | 'verification-failed'\n | 'internal-payment-error';\n\nconst TITLES: Readonly<Record<MppProblemType, string>> = {\n 'payment-required': 'Payment Required',\n 'malformed-credential': 'Malformed Credential',\n 'invalid-challenge': 'Invalid Challenge',\n 'payment-expired': 'Payment Expired',\n 'verification-failed': 'Verification Failed',\n 'internal-payment-error': 'Internal Payment Error',\n};\n\n// Map known MPP refusal reasons to problem types; other reasons use\n// `verification-failed`. A Map keeps facilitator text out of Object.prototype\nconst REASON_TYPES: ReadonlyMap<string, MppProblemType> = new Map([\n ['malformed_credential', 'malformed-credential'],\n ['invalid_payload', 'malformed-credential'],\n ['invalid_challenge', 'invalid-challenge'],\n ['challenge_not_issued', 'invalid-challenge'],\n ['wrong_realm', 'invalid-challenge'],\n ['wrong_resource', 'invalid-challenge'],\n ['challenge_already_used', 'invalid-challenge'],\n ['challenge_expired', 'payment-expired'],\n ['authorization_expired', 'payment-expired'],\n]);\n\n/** The Problem Details `type` URI and `title` for an MPP payment error */\nexport function mppProblem(\n code: string,\n httpStatus: number,\n reason?: string,\n): { readonly type: string; readonly title: string } {\n const problem = problemType(code, httpStatus, reason);\n return { type: `${MPP_PROBLEM_BASE_URI}${problem}`, title: TITLES[problem] };\n}\n\n// Descriptions for MPP reasons and two x402 facilitator refusals\nconst REASON_DETAILS: ReadonlyMap<string, string> = new Map([\n ['wrong_provider', 'The challenge was issued for another payment method.'],\n ['missing_challenge', 'No challenge is available for this request.'],\n ['malformed_credential', 'The credential could not be decoded.'],\n ['invalid_payload', 'The credential payload does not match the expected format.'],\n ['invalid_challenge', 'The credential does not answer a valid challenge.'],\n ['challenge_not_issued', 'The challenge was not issued by this server or was altered.'],\n ['challenge_already_used', 'The challenge has already been used for a payment.'],\n ['challenge_expired', 'The challenge has expired.'],\n ['wrong_realm', 'The challenge was issued for another realm.'],\n ['wrong_resource', 'The challenge was issued for another resource.'],\n [\n 'unsupported_method',\n 'The challenge names a payment method or intent this server does not accept.',\n ],\n ['unsupported_credential', 'The credential type is not accepted for this challenge.'],\n ['body_digest_mismatch', 'The request body differs from the one the challenge was issued for.'],\n ['wrong_amount', 'The payment amount does not match the challenge.'],\n ['wrong_recipient', 'The payment recipient does not match the challenge.'],\n ['wrong_network', 'The payment uses a different network from the challenge.'],\n ['wrong_asset', 'The payment uses a different asset from the challenge.'],\n ['wrong_terms', 'The payment terms do not match the challenge.'],\n ['wrong_nonce', 'The authorization nonce is not derived from the challenge.'],\n ['invalid_signature', 'The authorization signature does not match the payer.'],\n ['source_mismatch', 'The credential source is not the account that signed the authorization.'],\n ['authorization_not_yet_valid', 'The authorization is not valid yet.'],\n ['authorization_expired', 'The authorization has expired.'],\n ['authorization_invalid', 'The authorization failed verification.'],\n ['settlement_rejected', 'The payment was refused before settlement.'],\n ['settlement_mismatch', 'The payment could not be matched to its settlement.'],\n ['invalid_exact_evm_insufficient_balance', 'The payer balance is too low for this payment.'],\n [\n 'invalid_exact_evm_transaction_simulation_failed',\n 'The transfer failed in simulation, so it was not submitted.',\n ],\n]);\n\n/** Return a sentence for a known reason, or quote an unknown reason */\nexport function mppProblemDetail(reason: string | undefined, fallback: string): string {\n if (reason === undefined) return fallback;\n return REASON_DETAILS.get(reason) ?? `The payment was refused: ${reason}.`;\n}\n\nfunction problemType(code: string, httpStatus: number, reason?: string): MppProblemType {\n if (code === 'PAYMENT_REQUIRED') return 'payment-required';\n if (httpStatus >= 500) return 'internal-payment-error';\n // A replayed credential reuses its challenge because the replay key\n // includes the challenge-derived nonce\n if (code === 'PAYMENT_REPLAYED') return 'invalid-challenge';\n return (reason !== undefined ? REASON_TYPES.get(reason) : undefined) ?? 'verification-failed';\n}\n","/**\n * Build MPP MCP metadata accepted by the `mppx` client. This module has no\n * optional peer imports, so the `./mcp` subpath can use it.\n */\n\nimport { createHash } from 'node:crypto';\nimport { isRecord } from '../../core/is-record';\nimport { mppProblem, mppProblemDetail } from './problems';\n\n/**\n * `CanonicalRequest.metadata` key for the digest of an HTTP request body. The\n * MPP provider binds it into the challenge when present, so a credential\n * cannot pay for a different body.\n */\nexport const CONTENT_DIGEST_METADATA_KEY = 'contentDigest';\n\n/** RFC 9530 `sha-256` digest of a request body, the form of the MPP `digest` parameter */\nexport function contentDigest(body: Uint8Array): string {\n return `sha-256=:${createHash('sha256').update(body).digest('base64')}:`;\n}\n\n/** MCP `_meta` key of a tool call's credential object */\nexport const MPP_MCP_CREDENTIAL_META_KEY = 'org.paymentauth/credential';\n\n/** MCP `_meta` key of a tool result's challenges */\nexport const MPP_MCP_PAYMENT_REQUIRED_META_KEY = 'org.paymentauth/payment-required';\n\n/** MCP `_meta` key of a paid tool result's receipt object */\nexport const MPP_MCP_RECEIPT_META_KEY = 'org.paymentauth/receipt';\n\n/**\n * Build payment-required metadata from the provider's challenge objects.\n * Return undefined if the envelope has none. The draft uses JSON-RPC error\n * -32042; this gateway puts the data in a tool result's `_meta`, which\n * `mppx` also reads. A refusal adds its Problem Details, with the provider's\n * reason token in the `reason` member.\n */\nexport function mcpPaymentRequired(\n envelope: unknown,\n refusal?: { readonly code: string; readonly reason?: unknown; readonly detail: string },\n): Record<string, unknown> | undefined {\n const challenges = isRecord(envelope) ? envelope['challenges'] : undefined;\n if (!Array.isArray(challenges) || challenges.length === 0) return undefined;\n const reason = typeof refusal?.reason === 'string' ? refusal.reason : undefined;\n return {\n httpStatus: 402,\n challenges,\n ...(refusal !== undefined\n ? {\n problem: {\n ...mppProblem(refusal.code, 402, reason),\n status: 402,\n detail: mppProblemDetail(reason, refusal.detail),\n ...(reason !== undefined ? { reason } : {}),\n },\n }\n : {}),\n };\n}\n\n/** The receipt object from a serialized `Payment-Receipt` value, base64url JSON */\nexport function receiptObject(serialized: unknown): Record<string, unknown> | undefined {\n if (typeof serialized !== 'string') return undefined;\n try {\n const decoded: unknown = JSON.parse(Buffer.from(serialized, 'base64url').toString('utf8'));\n return isRecord(decoded) ? decoded : undefined;\n } catch {\n return undefined;\n }\n}\n"]}
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
var MPP_SPEC_REPOSITORY = "https://github.com/tempoxyz/mpp-specs";
|
|
3
3
|
var MPP_SPEC_COMMIT = "806fdb8b8c92cda5c84b8660558921b6bbeef7e0";
|
|
4
4
|
var MPP_SPEC_DRAFTS = {
|
|
5
|
-
core: "draft-httpauth-payment-
|
|
5
|
+
core: "draft-httpauth-payment-01",
|
|
6
6
|
intent: "draft-payment-intent-charge-00",
|
|
7
7
|
method: "draft-evm-charge-00"
|
|
8
8
|
};
|
|
9
9
|
var MPP_MIN_CHALLENGE_SECRET_LENGTH = 32;
|
|
10
|
-
var MPPX_VERSION = "0.
|
|
10
|
+
var MPPX_VERSION = "0.13.1";
|
|
11
11
|
var MPP_PROFILE = {
|
|
12
12
|
intent: "charge",
|
|
13
13
|
method: "evm",
|
|
@@ -15,13 +15,14 @@ var MPP_PROFILE = {
|
|
|
15
15
|
assetSymbol: "USDC",
|
|
16
16
|
assetDecimals: 6
|
|
17
17
|
};
|
|
18
|
-
var MPP_NETWORKS = ["eip155:84532", "eip155:8453"];
|
|
18
|
+
var MPP_NETWORKS = ["eip155:31337", "eip155:84532", "eip155:8453"];
|
|
19
19
|
var MPP_DEFAULT_NETWORK = "eip155:84532";
|
|
20
|
+
var MPP_DEFAULT_PAYMENT_FLOW = "upfront";
|
|
20
21
|
function isMppNetwork(value) {
|
|
21
22
|
return MPP_NETWORKS.includes(value);
|
|
22
23
|
}
|
|
23
24
|
var MPP_SUPPORTED_SPEC = `mpp/${MPP_SPEC_DRAFTS.core} intent=${MPP_PROFILE.intent} method=${MPP_PROFILE.method}`;
|
|
24
25
|
|
|
25
|
-
export { MPPX_VERSION, MPP_DEFAULT_NETWORK, MPP_MIN_CHALLENGE_SECRET_LENGTH, MPP_NETWORKS, MPP_PROFILE, MPP_SPEC_COMMIT, MPP_SPEC_DRAFTS, MPP_SPEC_REPOSITORY, MPP_SUPPORTED_SPEC, isMppNetwork };
|
|
26
|
-
//# sourceMappingURL=chunk-
|
|
27
|
-
//# sourceMappingURL=chunk-
|
|
26
|
+
export { MPPX_VERSION, MPP_DEFAULT_NETWORK, MPP_DEFAULT_PAYMENT_FLOW, MPP_MIN_CHALLENGE_SECRET_LENGTH, MPP_NETWORKS, MPP_PROFILE, MPP_SPEC_COMMIT, MPP_SPEC_DRAFTS, MPP_SPEC_REPOSITORY, MPP_SUPPORTED_SPEC, isMppNetwork };
|
|
27
|
+
//# sourceMappingURL=chunk-6Z2H53CG.js.map
|
|
28
|
+
//# sourceMappingURL=chunk-6Z2H53CG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/payments/mpp/constants.ts"],"names":[],"mappings":";AAYO,IAAM,mBAAA,GAAsB;AAQ5B,IAAM,eAAA,GAAkB;AAGxB,IAAM,eAAA,GAAkB;AAAA,EAC7B,IAAA,EAAM,2BAAA;AAAA,EACN,MAAA,EAAQ,gCAAA;AAAA,EACR,MAAA,EAAQ;AACV;AAMO,IAAM,+BAAA,GAAkC;AAGxC,IAAM,YAAA,GAAe;AAUrB,IAAM,WAAA,GAAc;AAAA,EACzB,MAAA,EAAQ,QAAA;AAAA,EACR,MAAA,EAAQ,KAAA;AAAA,EACR,cAAA,EAAgB,eAAA;AAAA,EAChB,WAAA,EAAa,MAAA;AAAA,EACb,aAAA,EAAe;AACjB;AAGO,IAAM,YAAA,GAAe,CAAC,cAAA,EAAgB,cAAA,EAAgB,aAAa;AAKnE,IAAM,mBAAA,GAAkC;AAOxC,IAAM,wBAAA,GAA4C;AAElD,SAAS,aAAa,KAAA,EAAoC;AAC/D,EAAA,OAAQ,YAAA,CAAmC,SAAS,KAAK,CAAA;AAC3D;AAGO,IAAM,kBAAA,GAAqB,OAAO,eAAA,CAAgB,IAAI,WAAW,WAAA,CAAY,MAAM,CAAA,QAAA,EAAW,WAAA,CAAY,MAAM,CAAA","file":"chunk-6Z2H53CG.js","sourcesContent":["/**\n * The one MPP profile this rail targets.\n *\n * MPP combines a core HTTP authentication layer, an intent, a method and\n * optional extensions. These constants identify the selected combination and\n * the exact specification revision.\n *\n * Importing this metadata does not load `mppx`.\n */\nimport type { X402PaymentFlow } from '../x402/payment-flow';\n\n/** Upstream specification repository the pinned drafts were read from */\nexport const MPP_SPEC_REPOSITORY = 'https://github.com/tempoxyz/mpp-specs';\n\n/**\n * Upstream commit the pinned drafts were read at.\n *\n * A draft's content can change without its `-00` name changing, so the name\n * alone does not identify a document; the commit does.\n */\nexport const MPP_SPEC_COMMIT = '806fdb8b8c92cda5c84b8660558921b6bbeef7e0';\n\n/** The core HTTP authentication draft, the `charge` intent, and its EVM method */\nexport const MPP_SPEC_DRAFTS = {\n core: 'draft-httpauth-payment-01',\n intent: 'draft-payment-intent-charge-00',\n method: 'draft-evm-charge-00',\n} as const;\n\n/**\n * Minimum accepted `challengeSecret.length`. This is a configuration floor,\n * not an entropy check.\n */\nexport const MPP_MIN_CHALLENGE_SECRET_LENGTH = 32;\n\n/** Exact `mppx` release the rail is pinned to */\nexport const MPPX_VERSION = '0.13.1';\n\n/**\n * The pinned profile.\n *\n * `intent`, `method` and `credentialType` copy MPP wire identifiers from\n * `mppx` so this module has no peer import; tests detect drift. `assetSymbol`\n * is the pricing currency an MPP resource must use. EVM charge requests carry a\n * numeric `chainId` and token address instead.\n */\nexport const MPP_PROFILE = {\n intent: 'charge',\n method: 'evm',\n credentialType: 'authorization',\n assetSymbol: 'USDC',\n assetDecimals: 6,\n} as const;\n\n/** Supported CAIP-2 networks; gateway config applies the x402 mainnet guardrails */\nexport const MPP_NETWORKS = ['eip155:31337', 'eip155:84532', 'eip155:8453'] as const;\n\nexport type MppNetwork = (typeof MPP_NETWORKS)[number];\n\n/** Default network: Base Sepolia. The local Anvil chain is `eip155:31337` */\nexport const MPP_DEFAULT_NETWORK: MppNetwork = 'eip155:84532';\n\n/**\n * Default payment flow: `upfront` settles before the backend runs. The\n * `charge` intent counts a backend call made before verification completes as\n * partial access, and EVM charge verification includes the transfer itself.\n */\nexport const MPP_DEFAULT_PAYMENT_FLOW: X402PaymentFlow = 'upfront';\n\nexport function isMppNetwork(value: string): value is MppNetwork {\n return (MPP_NETWORKS as readonly string[]).includes(value);\n}\n\n/** Compact descriptor value naming the core draft, intent and method */\nexport const MPP_SUPPORTED_SPEC = `mpp/${MPP_SPEC_DRAFTS.core} intent=${MPP_PROFILE.intent} method=${MPP_PROFILE.method}`;\n"]}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { isRecord } from './chunk-2CJNA7MS.js';
|
|
2
|
+
import { timingSafeEqual, createHash } from 'crypto';
|
|
3
|
+
|
|
4
|
+
// src/protocols/mcp/constants.ts
|
|
5
|
+
var MCP_TOOL_NAME_CHARS = "A-Za-z0-9._-";
|
|
6
|
+
var MCP_TOOL_NAME_MAX_LENGTH = 128;
|
|
7
|
+
var MCP_TOOL_NAME_PATTERN = new RegExp(
|
|
8
|
+
`^[${MCP_TOOL_NAME_CHARS}]{1,${MCP_TOOL_NAME_MAX_LENGTH}}$`
|
|
9
|
+
);
|
|
10
|
+
var MCP_MODERN_PROTOCOL_REVISION = "2026-07-28";
|
|
11
|
+
var BEARER_PREFIX = /^Bearer +/i;
|
|
12
|
+
function createBearerCheck(expectedToken) {
|
|
13
|
+
const expected = sha256(expectedToken);
|
|
14
|
+
return (header) => {
|
|
15
|
+
if (header === void 0 || !BEARER_PREFIX.test(header)) return false;
|
|
16
|
+
const presented = header.replace(BEARER_PREFIX, "");
|
|
17
|
+
return presented.length > 0 && timingSafeEqual(sha256(presented), expected);
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function sha256(value) {
|
|
21
|
+
return createHash("sha256").update(value, "utf8").digest();
|
|
22
|
+
}
|
|
23
|
+
async function readCappedBody(req, maxBytes) {
|
|
24
|
+
const chunks = [];
|
|
25
|
+
let total = 0;
|
|
26
|
+
try {
|
|
27
|
+
for await (const chunk of req) {
|
|
28
|
+
const buffer = chunk;
|
|
29
|
+
total += buffer.length;
|
|
30
|
+
if (total > maxBytes) return { kind: "too-large" };
|
|
31
|
+
chunks.push(buffer);
|
|
32
|
+
}
|
|
33
|
+
} catch {
|
|
34
|
+
return { kind: "unreadable" };
|
|
35
|
+
}
|
|
36
|
+
return { kind: "ok", text: Buffer.concat(chunks).toString("utf8") };
|
|
37
|
+
}
|
|
38
|
+
function joinUrl(baseUrl, mountPath) {
|
|
39
|
+
return `${baseUrl.replace(/\/+$/, "")}/${mountPath.replace(/^\/+|\/+$/g, "")}`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// src/payments/x402/transport.ts
|
|
43
|
+
var X402_MCP_PAYMENT_META_KEY = "x402/payment";
|
|
44
|
+
var X402_MCP_ERROR_META_KEY = "x402/error";
|
|
45
|
+
function x402McpPaymentSubmission(value) {
|
|
46
|
+
if (value === void 0 || value === null) return void 0;
|
|
47
|
+
if (typeof value === "string") return value;
|
|
48
|
+
return Buffer.from(JSON.stringify(value), "utf8").toString("base64");
|
|
49
|
+
}
|
|
50
|
+
var X402_MCP_PAYMENT_RESPONSE_META_KEY = "x402/payment-response";
|
|
51
|
+
var REPLAY_CODES = {
|
|
52
|
+
near: "invalid_exact_near_payload_delegate_action_nonce_already_used",
|
|
53
|
+
solana: "duplicate_settlement"
|
|
54
|
+
};
|
|
55
|
+
function x402ErrorCode(code, reason, network) {
|
|
56
|
+
if (code === "PAYMENT_REPLAYED") {
|
|
57
|
+
const namespace = typeof network === "string" ? network.split(":")[0] : void 0;
|
|
58
|
+
return (namespace !== void 0 ? REPLAY_CODES[namespace] : void 0) ?? "invalid_exact_evm_nonce_already_used";
|
|
59
|
+
}
|
|
60
|
+
return typeof reason === "string" ? reason : "unexpected_verify_error";
|
|
61
|
+
}
|
|
62
|
+
function x402RefusalStatus(code, httpStatus, reason) {
|
|
63
|
+
return code === "PAYMENT_INVALID" && reason === "permit2_allowance_required" ? 412 : httpStatus;
|
|
64
|
+
}
|
|
65
|
+
function settlementDocument(payment) {
|
|
66
|
+
return {
|
|
67
|
+
success: payment.status === "settled",
|
|
68
|
+
transaction: payment.externalReference ?? "",
|
|
69
|
+
network: payment.network ?? "",
|
|
70
|
+
...payment.payer !== void 0 ? { payer: payment.payer } : {},
|
|
71
|
+
...payment.amountBaseUnits !== void 0 ? { amount: payment.amountBaseUnits } : {},
|
|
72
|
+
status: payment.status,
|
|
73
|
+
provider: payment.provider,
|
|
74
|
+
currency: payment.currency,
|
|
75
|
+
...payment.externalReference !== void 0 ? { externalReference: payment.externalReference } : {}
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function settlementResponse(payment) {
|
|
79
|
+
const amountBaseUnits = payment.metadata?.["amountBaseUnits"];
|
|
80
|
+
return settlementDocument({
|
|
81
|
+
...payment,
|
|
82
|
+
...typeof amountBaseUnits === "string" ? { amountBaseUnits } : {}
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
function settlementResponseFromDetails(details) {
|
|
86
|
+
const payment = details?.["payment"];
|
|
87
|
+
if (!isRecord(payment)) return void 0;
|
|
88
|
+
const text = (key) => typeof payment[key] === "string" ? payment[key] : void 0;
|
|
89
|
+
const status = text("status");
|
|
90
|
+
const provider = text("provider");
|
|
91
|
+
const currency = text("currency");
|
|
92
|
+
if (status === void 0 || provider === void 0 || currency === void 0) return void 0;
|
|
93
|
+
return settlementDocument({
|
|
94
|
+
status,
|
|
95
|
+
provider,
|
|
96
|
+
currency,
|
|
97
|
+
network: text("network"),
|
|
98
|
+
externalReference: text("externalReference"),
|
|
99
|
+
payer: text("payer"),
|
|
100
|
+
amountBaseUnits: text("amountBaseUnits")
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
function settlementFailure(details) {
|
|
104
|
+
const text = (key) => {
|
|
105
|
+
const value = details?.[key];
|
|
106
|
+
return typeof value === "string" ? value : void 0;
|
|
107
|
+
};
|
|
108
|
+
const transaction = text("transactionHash");
|
|
109
|
+
const payer = text("payer");
|
|
110
|
+
let errorReason = text("reason") ?? "unexpected_settle_error";
|
|
111
|
+
if (details?.["settlementUncertain"] === true) {
|
|
112
|
+
errorReason = transaction !== void 0 ? "settlement_pending" : "unexpected_settle_error";
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
success: false,
|
|
116
|
+
errorReason,
|
|
117
|
+
transaction: transaction ?? "",
|
|
118
|
+
network: text("network") ?? "",
|
|
119
|
+
...payer !== void 0 ? { payer } : {}
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export { MCP_MODERN_PROTOCOL_REVISION, MCP_TOOL_NAME_PATTERN, X402_MCP_ERROR_META_KEY, X402_MCP_PAYMENT_META_KEY, X402_MCP_PAYMENT_RESPONSE_META_KEY, createBearerCheck, joinUrl, readCappedBody, settlementFailure, settlementResponse, settlementResponseFromDetails, x402ErrorCode, x402McpPaymentSubmission, x402RefusalStatus };
|
|
124
|
+
//# sourceMappingURL=chunk-ES3V6ECS.js.map
|
|
125
|
+
//# sourceMappingURL=chunk-ES3V6ECS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/protocols/mcp/constants.ts","../src/protocols/http.ts","../src/payments/x402/transport.ts"],"names":[],"mappings":"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","file":"chunk-ES3V6ECS.js","sourcesContent":["/**\n * MCP protocol constants shared by the config layer, the adapter and the\n * OpenAPI importer.\n *\n * Kept dependency-free: `src/config` validates tool names at load time, so\n * anything imported here would become a config-load dependency too, and the\n * MCP SDK is an optional peer the main entry and CLI must never load.\n */\n\n/** Characters SEP-986 allows in an MCP tool name, as a regex character class body */\nexport const MCP_TOOL_NAME_CHARS = 'A-Za-z0-9._-';\n\n/** Longest MCP tool name SEP-986 allows */\nexport const MCP_TOOL_NAME_MAX_LENGTH = 128;\n\n/**\n * MCP tool names per SEP-986: 1-128 chars of [A-Za-z0-9._-], the SDK's own\n * `TOOL_NAME_REGEX`, which it does not export. Config refuses an mcp-exposed\n * resource whose id fails it; the low-level `Server` checks no names, so the\n * adapter also skips such an id with a warning.\n */\nexport const MCP_TOOL_NAME_PATTERN = new RegExp(\n `^[${MCP_TOOL_NAME_CHARS}]{1,${MCP_TOOL_NAME_MAX_LENGTH}}$`,\n);\n\n/**\n * The modern revision served by the SDK. A v2 client negotiates this value\n * in the conformance test.\n */\nexport const MCP_MODERN_PROTOCOL_REVISION = '2026-07-28';\n","// HTTP helpers shared by the A2A and ACP adapters and the gateway's admin-token gate\nimport { createHash, timingSafeEqual } from 'node:crypto';\nimport type { IncomingMessage } from 'node:http';\n\nconst BEARER_PREFIX = /^Bearer +/i;\n\n/**\n * Builds a check of an `Authorization: Bearer <token>` header against a fixed\n * token. The scheme is case-insensitive (RFC 9110). Both sides are compared as\n * SHA-256 digests, because `timingSafeEqual` throws on a length mismatch and\n * would reveal the token's length; the expected digest is computed once here.\n */\nexport function createBearerCheck(expectedToken: string): (header: string | undefined) => boolean {\n const expected = sha256(expectedToken);\n return (header) => {\n if (header === undefined || !BEARER_PREFIX.test(header)) return false;\n const presented = header.replace(BEARER_PREFIX, '');\n return presented.length > 0 && timingSafeEqual(sha256(presented), expected);\n };\n}\n\nfunction sha256(value: string): Buffer {\n return createHash('sha256').update(value, 'utf8').digest();\n}\n\n/** A tagged result, so no body text can be mistaken for a failure */\nexport type BodyRead =\n | { readonly kind: 'ok'; readonly text: string }\n | { readonly kind: 'too-large' }\n | { readonly kind: 'unreadable' };\n\n/**\n * Reads the unconsumed request stream the gateway hands an adapter, stopping\n * at the cap rather than buffering whatever arrives\n */\nexport async function readCappedBody(req: IncomingMessage, maxBytes: number): Promise<BodyRead> {\n const chunks: Buffer[] = [];\n let total = 0;\n try {\n for await (const chunk of req) {\n const buffer = chunk as Buffer;\n total += buffer.length;\n if (total > maxBytes) return { kind: 'too-large' };\n chunks.push(buffer);\n }\n } catch {\n return { kind: 'unreadable' };\n }\n return { kind: 'ok', text: Buffer.concat(chunks).toString('utf8') };\n}\n\n/**\n * Joins a base URL and a mount path with exactly one slash between them and\n * none at the end. Plain concatenation can yield `https://host//a2a`, which a\n * router may treat as a different path.\n */\nexport function joinUrl(baseUrl: string, mountPath: string): string {\n return `${baseUrl.replace(/\\/+$/, '')}/${mountPath.replace(/^\\/+|\\/+$/g, '')}`;\n}\n","/**\n * Build x402 v2 responses for the HTTP route and MCP adapter. This module\n * has no optional peer imports, so both entries can use it.\n */\n\nimport type { PaymentResult } from '../../core';\nimport { isRecord } from '../../core/is-record';\n\n/** MCP `_meta` key of a tool call's `PaymentPayload` (x402 MCP transport) */\nexport const X402_MCP_PAYMENT_META_KEY = 'x402/payment';\n\n/** Challenge key read by the `cloudflare/agents` x402 MCP client */\nexport const X402_MCP_ERROR_META_KEY = 'x402/error';\n\n/**\n * Accept an object or base64 string from `x402/payment` and return the string\n * the provider decodes. An absent value returns undefined; other JSON\n * values are encoded for provider validation.\n */\nexport function x402McpPaymentSubmission(value: unknown): string | undefined {\n if (value === undefined || value === null) return undefined;\n if (typeof value === 'string') return value;\n return Buffer.from(JSON.stringify(value), 'utf8').toString('base64');\n}\n\n/** MCP `_meta` key of a tool result's settlement response (x402 MCP transport) */\nexport const X402_MCP_PAYMENT_RESPONSE_META_KEY = 'x402/payment-response';\n\n// The code an SDK facilitator gives a spent authorization, by CAIP-2 namespace.\n// The Solana scheme has none; its specification refuses a payload being\n// settled again as `duplicate_settlement`.\nconst REPLAY_CODES: Readonly<Record<string, string>> = {\n near: 'invalid_exact_near_payload_delegate_action_nonce_already_used',\n solana: 'duplicate_settlement',\n};\n\n/**\n * Returns the provider's refusal reason, or the paid network family's replay\n * code. Unknown networks use EVM's replay code.\n */\nexport function x402ErrorCode(code: string, reason: unknown, network?: unknown): string {\n if (code === 'PAYMENT_REPLAYED') {\n const namespace = typeof network === 'string' ? network.split(':')[0] : undefined;\n return (\n (namespace !== undefined ? REPLAY_CODES[namespace] : undefined) ??\n 'invalid_exact_evm_nonce_already_used'\n );\n }\n return typeof reason === 'string' ? reason : 'unexpected_verify_error';\n}\n\n/**\n * Returns 412 Precondition Failed for a missing Permit2 allowance: the buyer\n * must approve Permit2 before retrying. Other refusals keep their status.\n */\nexport function x402RefusalStatus(code: string, httpStatus: number, reason: unknown): number {\n return code === 'PAYMENT_INVALID' && reason === 'permit2_allowance_required' ? 412 : httpStatus;\n}\n\ninterface SettledPayment {\n readonly status: string;\n readonly provider: string;\n readonly currency: string;\n readonly network?: string | undefined;\n readonly externalReference?: string | undefined;\n readonly payer?: string | undefined;\n readonly amountBaseUnits?: string | undefined;\n}\n\n// The `SettleResponse` shape. When present, `amount` uses base units.\n// `status`, `provider`, `currency`, and `externalReference` are gateway\n// extensions; an x402 v2 client ignores fields it does not know.\nfunction settlementDocument(payment: SettledPayment): Record<string, unknown> {\n return {\n success: payment.status === 'settled',\n transaction: payment.externalReference ?? '',\n network: payment.network ?? '',\n ...(payment.payer !== undefined ? { payer: payment.payer } : {}),\n ...(payment.amountBaseUnits !== undefined ? { amount: payment.amountBaseUnits } : {}),\n status: payment.status,\n provider: payment.provider,\n currency: payment.currency,\n ...(payment.externalReference !== undefined\n ? { externalReference: payment.externalReference }\n : {}),\n };\n}\n\n/** A delivered payment's settlement response */\nexport function settlementResponse(payment: PaymentResult): Record<string, unknown> {\n const amountBaseUnits = payment.metadata?.['amountBaseUnits'];\n return settlementDocument({\n ...payment,\n ...(typeof amountBaseUnits === 'string' ? { amountBaseUnits } : {}),\n });\n}\n\n/**\n * The settlement response for a backend failure after settlement, from the\n * error's `details.payment`; undefined when the error carries none\n */\nexport function settlementResponseFromDetails(\n details: Readonly<Record<string, unknown>> | undefined,\n): Record<string, unknown> | undefined {\n const payment = details?.['payment'];\n if (!isRecord(payment)) return undefined;\n const text = (key: string): string | undefined =>\n typeof payment[key] === 'string' ? payment[key] : undefined;\n const status = text('status');\n const provider = text('provider');\n const currency = text('currency');\n if (status === undefined || provider === undefined || currency === undefined) return undefined;\n return settlementDocument({\n status,\n provider,\n currency,\n network: text('network'),\n externalReference: text('externalReference'),\n payer: text('payer'),\n amountBaseUnits: text('amountBaseUnits'),\n });\n}\n\n/**\n * A refused or unconfirmed settlement as a failed `SettleResponse`. An\n * unconfirmed transfer with a hash uses x402's `settlement_pending` reason.\n */\nexport function settlementFailure(\n details: Readonly<Record<string, unknown>> | undefined,\n): Record<string, unknown> {\n const text = (key: string): string | undefined => {\n const value = details?.[key];\n return typeof value === 'string' ? value : undefined;\n };\n const transaction = text('transactionHash');\n const payer = text('payer');\n let errorReason = text('reason') ?? 'unexpected_settle_error';\n if (details?.['settlementUncertain'] === true) {\n errorReason = transaction !== undefined ? 'settlement_pending' : 'unexpected_settle_error';\n }\n return {\n success: false,\n errorReason,\n transaction: transaction ?? '',\n network: text('network') ?? '',\n ...(payer !== undefined ? { payer } : {}),\n };\n}\n"]}
|