@agent-score/commerce 1.0.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 +21 -0
- package/README.md +306 -0
- package/dist/_response-DmziuJz6.d.mts +137 -0
- package/dist/_response-rbK0zM7y.d.ts +137 -0
- package/dist/api/index.d.mts +1 -0
- package/dist/api/index.d.ts +1 -0
- package/dist/api/index.js +37 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/index.mjs +14 -0
- package/dist/api/index.mjs.map +1 -0
- package/dist/challenge/index.d.mts +523 -0
- package/dist/challenge/index.d.ts +523 -0
- package/dist/challenge/index.js +354 -0
- package/dist/challenge/index.js.map +1 -0
- package/dist/challenge/index.mjs +318 -0
- package/dist/challenge/index.mjs.map +1 -0
- package/dist/core.d.mts +252 -0
- package/dist/core.d.ts +252 -0
- package/dist/core.js +500 -0
- package/dist/core.js.map +1 -0
- package/dist/core.mjs +472 -0
- package/dist/core.mjs.map +1 -0
- package/dist/discovery/index.d.mts +382 -0
- package/dist/discovery/index.d.ts +382 -0
- package/dist/discovery/index.js +675 -0
- package/dist/discovery/index.js.map +1 -0
- package/dist/discovery/index.mjs +630 -0
- package/dist/discovery/index.mjs.map +1 -0
- package/dist/identity/express.d.mts +44 -0
- package/dist/identity/express.d.ts +44 -0
- package/dist/identity/express.js +777 -0
- package/dist/identity/express.js.map +1 -0
- package/dist/identity/express.mjs +738 -0
- package/dist/identity/express.mjs.map +1 -0
- package/dist/identity/fastify.d.mts +63 -0
- package/dist/identity/fastify.d.ts +63 -0
- package/dist/identity/fastify.js +780 -0
- package/dist/identity/fastify.js.map +1 -0
- package/dist/identity/fastify.mjs +741 -0
- package/dist/identity/fastify.mjs.map +1 -0
- package/dist/identity/hono.d.mts +83 -0
- package/dist/identity/hono.d.ts +83 -0
- package/dist/identity/hono.js +779 -0
- package/dist/identity/hono.js.map +1 -0
- package/dist/identity/hono.mjs +740 -0
- package/dist/identity/hono.mjs.map +1 -0
- package/dist/identity/nextjs.d.mts +62 -0
- package/dist/identity/nextjs.d.ts +62 -0
- package/dist/identity/nextjs.js +784 -0
- package/dist/identity/nextjs.js.map +1 -0
- package/dist/identity/nextjs.mjs +747 -0
- package/dist/identity/nextjs.mjs.map +1 -0
- package/dist/identity/policy.d.mts +115 -0
- package/dist/identity/policy.d.ts +115 -0
- package/dist/identity/policy.js +81 -0
- package/dist/identity/policy.js.map +1 -0
- package/dist/identity/policy.mjs +53 -0
- package/dist/identity/policy.mjs.map +1 -0
- package/dist/identity/web.d.mts +82 -0
- package/dist/identity/web.d.ts +82 -0
- package/dist/identity/web.js +775 -0
- package/dist/identity/web.js.map +1 -0
- package/dist/identity/web.mjs +738 -0
- package/dist/identity/web.mjs.map +1 -0
- package/dist/index.d.mts +252 -0
- package/dist/index.d.ts +252 -0
- package/dist/index.js +432 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +388 -0
- package/dist/index.mjs.map +1 -0
- package/dist/payment/index.d.mts +716 -0
- package/dist/payment/index.d.ts +716 -0
- package/dist/payment/index.js +691 -0
- package/dist/payment/index.js.map +1 -0
- package/dist/payment/index.mjs +639 -0
- package/dist/payment/index.mjs.map +1 -0
- package/dist/signer-Cvdwn6Cs.d.mts +48 -0
- package/dist/signer-Cvdwn6Cs.d.ts +48 -0
- package/dist/stripe-multichain/index.d.mts +221 -0
- package/dist/stripe-multichain/index.d.ts +221 -0
- package/dist/stripe-multichain/index.js +243 -0
- package/dist/stripe-multichain/index.js.map +1 -0
- package/dist/stripe-multichain/index.mjs +199 -0
- package/dist/stripe-multichain/index.mjs.map +1 -0
- package/dist/wwwauthenticate-CU1eNvMQ.d.mts +37 -0
- package/dist/wwwauthenticate-CU1eNvMQ.d.ts +37 -0
- package/package.json +172 -0
|
@@ -0,0 +1,691 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/payment/index.ts
|
|
21
|
+
var payment_exports = {};
|
|
22
|
+
__export(payment_exports, {
|
|
23
|
+
SETTLEMENT_OVERRIDES_HEADER: () => SETTLEMENT_OVERRIDES_HEADER,
|
|
24
|
+
USDC: () => USDC,
|
|
25
|
+
X402_SUPPORTED_BASE_NETWORKS: () => X402_SUPPORTED_BASE_NETWORKS,
|
|
26
|
+
X402_SUPPORTED_SVM_NETWORKS: () => X402_SUPPORTED_SVM_NETWORKS,
|
|
27
|
+
aliasAmountFields: () => aliasAmountFields,
|
|
28
|
+
buildIdempotencyKey: () => buildIdempotencyKey,
|
|
29
|
+
buildPaymentDirective: () => buildPaymentDirective,
|
|
30
|
+
buildPaymentHeaders: () => buildPaymentHeaders,
|
|
31
|
+
buildPaymentRequestBlob: () => buildPaymentRequestBlob,
|
|
32
|
+
createMppxServer: () => createMppxServer,
|
|
33
|
+
createX402Server: () => createX402Server,
|
|
34
|
+
dispatchSettlementByNetwork: () => dispatchSettlementByNetwork,
|
|
35
|
+
extractPaymentSigner: () => extractPaymentSigner,
|
|
36
|
+
lookupRail: () => lookupRail,
|
|
37
|
+
networkFamily: () => networkFamily,
|
|
38
|
+
networks: () => networks,
|
|
39
|
+
paymentDirective: () => paymentDirective,
|
|
40
|
+
paymentRequiredHeader: () => paymentRequiredHeader,
|
|
41
|
+
processX402Settle: () => processX402Settle,
|
|
42
|
+
rails: () => rails,
|
|
43
|
+
readX402PaymentHeader: () => readX402PaymentHeader,
|
|
44
|
+
registerX402SchemesV1V2: () => registerX402SchemesV1V2,
|
|
45
|
+
settlementOverrideHeader: () => settlementOverrideHeader,
|
|
46
|
+
validateX402NetworkConfig: () => validateX402NetworkConfig,
|
|
47
|
+
verifyX402Request: () => verifyX402Request,
|
|
48
|
+
wwwAuthenticateHeader: () => wwwAuthenticateHeader
|
|
49
|
+
});
|
|
50
|
+
module.exports = __toCommonJS(payment_exports);
|
|
51
|
+
|
|
52
|
+
// src/payment/networks.ts
|
|
53
|
+
var networks = {
|
|
54
|
+
base: {
|
|
55
|
+
mainnet: { caip2: "eip155:8453", chainId: 8453 },
|
|
56
|
+
sepolia: { caip2: "eip155:84532", chainId: 84532 }
|
|
57
|
+
},
|
|
58
|
+
solana: {
|
|
59
|
+
mainnet: { caip2: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp" },
|
|
60
|
+
devnet: { caip2: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1" }
|
|
61
|
+
},
|
|
62
|
+
tempo: {
|
|
63
|
+
mainnet: { caip2: "eip155:4217", chainId: 4217 },
|
|
64
|
+
testnet: { caip2: "eip155:42431", chainId: 42431 }
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
function networkFamily(caip2) {
|
|
68
|
+
if (caip2 === networks.base.mainnet.caip2 || caip2 === networks.base.sepolia.caip2) return "base";
|
|
69
|
+
if (caip2 === networks.solana.mainnet.caip2 || caip2 === networks.solana.devnet.caip2) return "solana";
|
|
70
|
+
if (caip2 === networks.tempo.mainnet.caip2 || caip2 === networks.tempo.testnet.caip2) return "tempo";
|
|
71
|
+
if (caip2.startsWith("solana:")) return "solana";
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// src/payment/usdc.ts
|
|
76
|
+
var USDC = {
|
|
77
|
+
base: {
|
|
78
|
+
mainnet: { address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", decimals: 6 },
|
|
79
|
+
sepolia: { address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e", decimals: 6 }
|
|
80
|
+
},
|
|
81
|
+
solana: {
|
|
82
|
+
mainnet: { mint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", decimals: 6 },
|
|
83
|
+
devnet: { mint: "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU", decimals: 6 }
|
|
84
|
+
},
|
|
85
|
+
tempo: {
|
|
86
|
+
mainnet: { address: "0x20C000000000000000000000b9537d11c60E8b50", decimals: 6 },
|
|
87
|
+
testnet: { address: "0x20c0000000000000000000000000000000000000", decimals: 6 }
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
// src/payment/rails.ts
|
|
92
|
+
var rails = {
|
|
93
|
+
"tempo-mainnet": {
|
|
94
|
+
method: "tempo",
|
|
95
|
+
network: networks.tempo.mainnet.caip2,
|
|
96
|
+
chainId: networks.tempo.mainnet.chainId,
|
|
97
|
+
currency: USDC.tempo.mainnet.address,
|
|
98
|
+
decimals: USDC.tempo.mainnet.decimals,
|
|
99
|
+
asset: USDC.tempo.mainnet.address
|
|
100
|
+
},
|
|
101
|
+
"tempo-testnet": {
|
|
102
|
+
method: "tempo",
|
|
103
|
+
network: networks.tempo.testnet.caip2,
|
|
104
|
+
chainId: networks.tempo.testnet.chainId,
|
|
105
|
+
currency: USDC.tempo.testnet.address,
|
|
106
|
+
decimals: USDC.tempo.testnet.decimals,
|
|
107
|
+
asset: USDC.tempo.testnet.address
|
|
108
|
+
},
|
|
109
|
+
"x402-base-mainnet": {
|
|
110
|
+
method: "x402",
|
|
111
|
+
network: networks.base.mainnet.caip2,
|
|
112
|
+
chainId: networks.base.mainnet.chainId,
|
|
113
|
+
currency: USDC.base.mainnet.address,
|
|
114
|
+
decimals: USDC.base.mainnet.decimals,
|
|
115
|
+
asset: USDC.base.mainnet.address
|
|
116
|
+
},
|
|
117
|
+
"x402-base-sepolia": {
|
|
118
|
+
method: "x402",
|
|
119
|
+
network: networks.base.sepolia.caip2,
|
|
120
|
+
chainId: networks.base.sepolia.chainId,
|
|
121
|
+
currency: USDC.base.sepolia.address,
|
|
122
|
+
decimals: USDC.base.sepolia.decimals,
|
|
123
|
+
asset: USDC.base.sepolia.address
|
|
124
|
+
},
|
|
125
|
+
// Upto rails — pay UP TO a max amount (Permit2-based, vs EIP-3009 for exact). Use for
|
|
126
|
+
// variable-cost APIs where the actual cost depends on output (LLM tokens, bandwidth, etc.).
|
|
127
|
+
// Only available on EVM networks; Solana svm doesn't ship an upto scheme yet.
|
|
128
|
+
"x402-base-mainnet-upto": {
|
|
129
|
+
method: "x402-upto",
|
|
130
|
+
network: networks.base.mainnet.caip2,
|
|
131
|
+
chainId: networks.base.mainnet.chainId,
|
|
132
|
+
currency: USDC.base.mainnet.address,
|
|
133
|
+
decimals: USDC.base.mainnet.decimals,
|
|
134
|
+
asset: USDC.base.mainnet.address
|
|
135
|
+
},
|
|
136
|
+
"x402-base-sepolia-upto": {
|
|
137
|
+
method: "x402-upto",
|
|
138
|
+
network: networks.base.sepolia.caip2,
|
|
139
|
+
chainId: networks.base.sepolia.chainId,
|
|
140
|
+
currency: USDC.base.sepolia.address,
|
|
141
|
+
decimals: USDC.base.sepolia.decimals,
|
|
142
|
+
asset: USDC.base.sepolia.address
|
|
143
|
+
},
|
|
144
|
+
"x402-solana-mainnet": {
|
|
145
|
+
method: "x402",
|
|
146
|
+
network: networks.solana.mainnet.caip2,
|
|
147
|
+
currency: USDC.solana.mainnet.mint,
|
|
148
|
+
decimals: USDC.solana.mainnet.decimals,
|
|
149
|
+
asset: USDC.solana.mainnet.mint
|
|
150
|
+
},
|
|
151
|
+
"x402-solana-devnet": {
|
|
152
|
+
method: "x402",
|
|
153
|
+
network: networks.solana.devnet.caip2,
|
|
154
|
+
currency: USDC.solana.devnet.mint,
|
|
155
|
+
decimals: USDC.solana.devnet.decimals,
|
|
156
|
+
asset: USDC.solana.devnet.mint
|
|
157
|
+
},
|
|
158
|
+
"stripe-spt": {
|
|
159
|
+
method: "stripe",
|
|
160
|
+
currency: "usd",
|
|
161
|
+
decimals: 2
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
function lookupRail(name) {
|
|
165
|
+
return rails[name];
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// src/payment/directive.ts
|
|
169
|
+
function buildPaymentRequestBlob(input) {
|
|
170
|
+
const railDef = input.rail ? lookupRail(input.rail) : void 0;
|
|
171
|
+
const decimals = input.decimals ?? railDef?.decimals ?? 6;
|
|
172
|
+
const currency = input.currency ?? railDef?.currency ?? "usd";
|
|
173
|
+
const chainId = input.chainId ?? railDef?.chainId;
|
|
174
|
+
const amountNum = typeof input.amountUsd === "string" ? Number(input.amountUsd) : input.amountUsd;
|
|
175
|
+
const amountRaw = BigInt(Math.round(amountNum * 10 ** decimals)).toString();
|
|
176
|
+
const blob = { amount: amountRaw, currency, decimals };
|
|
177
|
+
if (input.recipient) blob.recipient = input.recipient;
|
|
178
|
+
const methodDetails = {};
|
|
179
|
+
if (chainId !== void 0) methodDetails.chainId = chainId;
|
|
180
|
+
if (input.networkId) methodDetails.networkId = input.networkId;
|
|
181
|
+
if (Object.keys(methodDetails).length > 0) blob.methodDetails = methodDetails;
|
|
182
|
+
return Buffer.from(JSON.stringify(blob)).toString("base64url");
|
|
183
|
+
}
|
|
184
|
+
function paymentDirective(input) {
|
|
185
|
+
const railDef = input.rail ? lookupRail(input.rail) : void 0;
|
|
186
|
+
const method = input.method ?? railDef?.method ?? "unknown";
|
|
187
|
+
const intent = input.intent ?? "charge";
|
|
188
|
+
const expires = input.expires ?? new Date(Date.now() + 5 * 60 * 1e3).toISOString();
|
|
189
|
+
return `Payment id="${input.id}", realm="${input.realm}", method="${method}", intent="${intent}", expires="${expires}", request="${input.request}"`;
|
|
190
|
+
}
|
|
191
|
+
function buildPaymentDirective(input) {
|
|
192
|
+
const request = buildPaymentRequestBlob({
|
|
193
|
+
rail: input.rail,
|
|
194
|
+
amountUsd: input.amountUsd,
|
|
195
|
+
currency: input.currency,
|
|
196
|
+
decimals: input.decimals,
|
|
197
|
+
recipient: input.recipient,
|
|
198
|
+
chainId: input.chainId,
|
|
199
|
+
networkId: input.networkId
|
|
200
|
+
});
|
|
201
|
+
return paymentDirective({
|
|
202
|
+
rail: input.rail,
|
|
203
|
+
id: input.id,
|
|
204
|
+
realm: input.realm,
|
|
205
|
+
method: input.method,
|
|
206
|
+
intent: input.intent,
|
|
207
|
+
expires: input.expires,
|
|
208
|
+
request
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// src/payment/x402.ts
|
|
213
|
+
function registerX402SchemesV1V2(server, network, scheme) {
|
|
214
|
+
server.register(network, scheme);
|
|
215
|
+
if (typeof server.registerV1 === "function") {
|
|
216
|
+
server.registerV1(network, scheme);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// src/payment/x402_server.ts
|
|
221
|
+
async function createX402Server(opts = {}) {
|
|
222
|
+
for (const rail of opts.rails ?? []) {
|
|
223
|
+
if (rail.startsWith("x402-solana") && rail.endsWith("-upto")) {
|
|
224
|
+
throw new Error(`Rail "${rail}" not supported \u2014 @x402/svm does not ship an upto scheme yet (EVM-only).`);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
const x402Core = await dynamicImport("@x402/core/server") ?? null;
|
|
228
|
+
if (!x402Core) {
|
|
229
|
+
throw new Error(
|
|
230
|
+
"@x402/core not installed \u2014 `npm install @x402/core` to use createX402Server."
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
let facilitator;
|
|
234
|
+
if (opts.facilitator === "coinbase") {
|
|
235
|
+
const cb = await dynamicImport("@coinbase/x402");
|
|
236
|
+
if (!cb?.facilitator) {
|
|
237
|
+
throw new Error(
|
|
238
|
+
'@coinbase/x402 not installed \u2014 `npm install @coinbase/x402` for facilitator: "coinbase".'
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
facilitator = new x402Core.HTTPFacilitatorClient(cb.facilitator);
|
|
242
|
+
} else if (opts.facilitator === void 0 || opts.facilitator === "http") {
|
|
243
|
+
facilitator = new x402Core.HTTPFacilitatorClient();
|
|
244
|
+
} else {
|
|
245
|
+
facilitator = opts.facilitator;
|
|
246
|
+
}
|
|
247
|
+
const server = new x402Core.x402ResourceServer(facilitator);
|
|
248
|
+
let evmExactModule = null;
|
|
249
|
+
let evmUptoModule = null;
|
|
250
|
+
let svmModule = null;
|
|
251
|
+
for (const rail of opts.rails ?? []) {
|
|
252
|
+
const isUpto = rail.endsWith("-upto");
|
|
253
|
+
if (rail.startsWith("x402-base")) {
|
|
254
|
+
const baseRail = isUpto ? rail.slice(0, -5) : rail;
|
|
255
|
+
const network = baseRail === "x402-base-mainnet" ? networks.base.mainnet.caip2 : networks.base.sepolia.caip2;
|
|
256
|
+
if (isUpto) {
|
|
257
|
+
evmUptoModule ??= await dynamicImport("@x402/evm/upto/server");
|
|
258
|
+
if (!evmUptoModule?.UptoEvmScheme) {
|
|
259
|
+
throw new Error("@x402/evm not installed \u2014 `npm install @x402/evm` for x402 base upto rails.");
|
|
260
|
+
}
|
|
261
|
+
registerX402SchemesV1V2(server, network, new evmUptoModule.UptoEvmScheme());
|
|
262
|
+
} else {
|
|
263
|
+
evmExactModule ??= await dynamicImport("@x402/evm/exact/server");
|
|
264
|
+
if (!evmExactModule?.ExactEvmScheme) {
|
|
265
|
+
throw new Error("@x402/evm not installed \u2014 `npm install @x402/evm` for x402 base rails.");
|
|
266
|
+
}
|
|
267
|
+
registerX402SchemesV1V2(server, network, new evmExactModule.ExactEvmScheme());
|
|
268
|
+
}
|
|
269
|
+
} else if (rail.startsWith("x402-solana")) {
|
|
270
|
+
svmModule ??= await dynamicImport("@x402/svm/exact/server");
|
|
271
|
+
if (!svmModule?.ExactSvmScheme) {
|
|
272
|
+
throw new Error("@x402/svm not installed \u2014 `npm install @x402/svm` for x402 solana rails.");
|
|
273
|
+
}
|
|
274
|
+
const network = rail === "x402-solana-mainnet" ? networks.solana.mainnet.caip2 : networks.solana.devnet.caip2;
|
|
275
|
+
registerX402SchemesV1V2(server, network, new svmModule.ExactSvmScheme());
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
for (const { network, scheme } of opts.schemes ?? []) {
|
|
279
|
+
registerX402SchemesV1V2(server, network, scheme);
|
|
280
|
+
}
|
|
281
|
+
if (opts.bazaar) {
|
|
282
|
+
const bazaar = await dynamicImport("@x402/extensions/bazaar");
|
|
283
|
+
if (!bazaar?.bazaarResourceServerExtension) {
|
|
284
|
+
throw new Error(
|
|
285
|
+
"@x402/extensions not installed \u2014 `npm install @x402/extensions` for bazaar discovery."
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
server.registerExtension(bazaar.bazaarResourceServerExtension);
|
|
289
|
+
}
|
|
290
|
+
if (opts.initialize !== false) {
|
|
291
|
+
await server.initialize();
|
|
292
|
+
}
|
|
293
|
+
return server;
|
|
294
|
+
}
|
|
295
|
+
async function dynamicImport(moduleName) {
|
|
296
|
+
try {
|
|
297
|
+
return await import(moduleName);
|
|
298
|
+
} catch {
|
|
299
|
+
return null;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// src/payment/x402_settle.ts
|
|
304
|
+
async function processX402Settle(input) {
|
|
305
|
+
const server = input.x402Server;
|
|
306
|
+
const builtRequirements = await server.buildPaymentRequirements(input.resourceConfig);
|
|
307
|
+
const matchedRequirement = builtRequirements[0];
|
|
308
|
+
if (!matchedRequirement) {
|
|
309
|
+
return { success: false, phase: "no_requirements", reason: "x402Server.buildPaymentRequirements returned empty" };
|
|
310
|
+
}
|
|
311
|
+
const transportContext = input.transportContext ?? (() => {
|
|
312
|
+
const path = new URL(input.resourceMeta.url).pathname;
|
|
313
|
+
return { method: "POST", adapter: { getPath: () => path }, routePattern: path };
|
|
314
|
+
})();
|
|
315
|
+
const enrichedExt = input.extension !== void 0 ? server.enrichExtensions(input.extension, transportContext) : void 0;
|
|
316
|
+
const verifyResult = await server.processPaymentRequest(
|
|
317
|
+
input.payload,
|
|
318
|
+
input.resourceConfig,
|
|
319
|
+
input.resourceMeta,
|
|
320
|
+
enrichedExt
|
|
321
|
+
);
|
|
322
|
+
if (!verifyResult.success) {
|
|
323
|
+
return { success: false, phase: "verify_failed", verifyResult };
|
|
324
|
+
}
|
|
325
|
+
try {
|
|
326
|
+
const settleResult = await server.settlePayment(input.payload, matchedRequirement);
|
|
327
|
+
const paymentResponseHeader = settleResult ? Buffer.from(JSON.stringify(settleResult)).toString("base64") : void 0;
|
|
328
|
+
return {
|
|
329
|
+
success: true,
|
|
330
|
+
matchedRequirement,
|
|
331
|
+
settleResult,
|
|
332
|
+
paymentResponseHeader,
|
|
333
|
+
verifyResult
|
|
334
|
+
};
|
|
335
|
+
} catch (err) {
|
|
336
|
+
return { success: false, phase: "settle_failed", error: err, matchedRequirement };
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// src/payment/x402_validation.ts
|
|
341
|
+
var X402_SUPPORTED_BASE_NETWORKS = /* @__PURE__ */ new Set([
|
|
342
|
+
networks.base.mainnet.caip2,
|
|
343
|
+
networks.base.sepolia.caip2
|
|
344
|
+
]);
|
|
345
|
+
var X402_SUPPORTED_SVM_NETWORKS = /* @__PURE__ */ new Set([
|
|
346
|
+
networks.solana.mainnet.caip2,
|
|
347
|
+
networks.solana.devnet.caip2
|
|
348
|
+
]);
|
|
349
|
+
function validateX402NetworkConfig(input) {
|
|
350
|
+
if (!X402_SUPPORTED_BASE_NETWORKS.has(input.baseNetwork)) {
|
|
351
|
+
throw new Error(
|
|
352
|
+
`X402_BASE_NETWORK=${input.baseNetwork} is not supported. Use one of: ${[...X402_SUPPORTED_BASE_NETWORKS].join(", ")}`
|
|
353
|
+
);
|
|
354
|
+
}
|
|
355
|
+
if (!X402_SUPPORTED_SVM_NETWORKS.has(input.svmNetwork)) {
|
|
356
|
+
throw new Error(
|
|
357
|
+
`X402_SVM_NETWORK=${input.svmNetwork} is not supported. Use one of: ${[...X402_SUPPORTED_SVM_NETWORKS].join(", ")}`
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
if (input.baseNetwork === input.svmNetwork) {
|
|
361
|
+
throw new Error(
|
|
362
|
+
`X402_BASE_NETWORK and X402_SVM_NETWORK must be different (both set to ${input.baseNetwork}).`
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
var EVM_ADDRESS_RE = /^0x[0-9a-fA-F]{40}$/;
|
|
367
|
+
var SOLANA_ADDRESS_RE = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
|
|
368
|
+
var REGENERATE_WARNING = "If you're trying to pay with Tempo USDC, use `tempo request` (sends Authorization: Payment), not a manual X-Payment header. Do NOT use `tempo wallet transfer` \u2014 that sends USDC on-chain but will not complete the MPP handshake. For x402 on Base/Solana, use `agentscore-pay pay` so the X-Payment credential is signed and submitted; bare wallet transfers do not complete the handshake.";
|
|
369
|
+
function regenerateBody(message, userMessage) {
|
|
370
|
+
return {
|
|
371
|
+
error: { code: "payment_proof_invalid", message },
|
|
372
|
+
next_steps: {
|
|
373
|
+
action: "regenerate_payment_credential",
|
|
374
|
+
user_message: userMessage,
|
|
375
|
+
warning: REGENERATE_WARNING
|
|
376
|
+
}
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
async function verifyX402Request(input) {
|
|
380
|
+
const headerValue = input.request.headers.get("payment-signature") ?? input.request.headers.get("x-payment");
|
|
381
|
+
if (!headerValue) {
|
|
382
|
+
return {
|
|
383
|
+
ok: false,
|
|
384
|
+
status: 400,
|
|
385
|
+
body: regenerateBody(
|
|
386
|
+
"X-Payment header missing",
|
|
387
|
+
"No X-Payment header was sent. Generate the credential from the 402 challenge and resubmit on the same endpoint."
|
|
388
|
+
)
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
let payload;
|
|
392
|
+
try {
|
|
393
|
+
payload = JSON.parse(Buffer.from(headerValue, "base64").toString());
|
|
394
|
+
} catch {
|
|
395
|
+
return {
|
|
396
|
+
ok: false,
|
|
397
|
+
status: 400,
|
|
398
|
+
body: regenerateBody(
|
|
399
|
+
"X-Payment header is not valid base64 JSON",
|
|
400
|
+
"The payment credential could not be decoded. Reconstruct the credential from the 402 challenge and retry."
|
|
401
|
+
)
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
const signedNetwork = payload.accepted?.network;
|
|
405
|
+
const signedPayTo = payload.accepted?.payTo;
|
|
406
|
+
if (!signedNetwork || signedNetwork !== input.acceptedNetworks.base && signedNetwork !== input.acceptedNetworks.svm) {
|
|
407
|
+
return {
|
|
408
|
+
ok: false,
|
|
409
|
+
status: 400,
|
|
410
|
+
body: regenerateBody(
|
|
411
|
+
`Unsupported x402 network ${signedNetwork ?? "<missing>"}; this server accepts ${input.acceptedNetworks.base} (Base) and ${input.acceptedNetworks.svm} (Solana)`,
|
|
412
|
+
"The credential signed for an unsupported network. Pick one of the accepted networks from the 402 challenge and re-sign."
|
|
413
|
+
)
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
const isSolana = networkFamily(signedNetwork) === "solana";
|
|
417
|
+
const addressShapeOk = isSolana ? typeof signedPayTo === "string" && SOLANA_ADDRESS_RE.test(signedPayTo) : typeof signedPayTo === "string" && EVM_ADDRESS_RE.test(signedPayTo);
|
|
418
|
+
if (!signedPayTo || !addressShapeOk) {
|
|
419
|
+
return {
|
|
420
|
+
ok: false,
|
|
421
|
+
status: 400,
|
|
422
|
+
body: regenerateBody(
|
|
423
|
+
`Payment payload missing or malformed accepted.payTo address for network ${signedNetwork}`,
|
|
424
|
+
"The credential payload is missing or malformed payTo for the signed network. Reconstruct the credential from the 402 challenge."
|
|
425
|
+
)
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
if (!await input.isCachedAddress(signedPayTo)) {
|
|
429
|
+
return {
|
|
430
|
+
ok: false,
|
|
431
|
+
status: 400,
|
|
432
|
+
body: regenerateBody(
|
|
433
|
+
"payTo address not found in cache or expired. Request a fresh 402 challenge and retry.",
|
|
434
|
+
"The deposit address is unknown or expired on this server. Request a fresh 402 challenge and re-sign against the new payTo."
|
|
435
|
+
)
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
return { ok: true, payload, signedNetwork, signedPayTo, isSolana };
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// src/stripe-multichain/mppx_stripe.ts
|
|
442
|
+
async function createMppxStripe(input) {
|
|
443
|
+
const moduleName = "mppx/server";
|
|
444
|
+
const mppx = await import(moduleName).catch(() => null);
|
|
445
|
+
if (!mppx?.stripe?.charge) {
|
|
446
|
+
throw new Error(
|
|
447
|
+
"mppx not installed \u2014 install with `npm install mppx` to use createMppxStripe."
|
|
448
|
+
);
|
|
449
|
+
}
|
|
450
|
+
return mppx.stripe.charge({
|
|
451
|
+
networkId: input.profileId,
|
|
452
|
+
paymentMethodTypes: input.paymentMethodTypes ?? ["card", "link"],
|
|
453
|
+
secretKey: input.secretKey
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// src/payment/mppx_server.ts
|
|
458
|
+
async function createMppxServer(opts) {
|
|
459
|
+
const mppx = await dynamicImport2("mppx/server");
|
|
460
|
+
if (!mppx?.Mppx?.create) {
|
|
461
|
+
throw new Error("mppx not installed \u2014 `npm install mppx` to use createMppxServer.");
|
|
462
|
+
}
|
|
463
|
+
const methods = [...opts.methods ?? []];
|
|
464
|
+
if (opts.rails?.tempo) {
|
|
465
|
+
if (!mppx.tempo?.charge) {
|
|
466
|
+
throw new Error("mppx.tempo.charge not available \u2014 check installed mppx version.");
|
|
467
|
+
}
|
|
468
|
+
const t = opts.rails.tempo;
|
|
469
|
+
const defaultCurrency = t.testnet ? USDC.tempo.testnet.address : USDC.tempo.mainnet.address;
|
|
470
|
+
methods.push(
|
|
471
|
+
mppx.tempo.charge({
|
|
472
|
+
currency: t.currency ?? defaultCurrency,
|
|
473
|
+
recipient: t.recipient,
|
|
474
|
+
testnet: t.testnet ?? false
|
|
475
|
+
})
|
|
476
|
+
);
|
|
477
|
+
}
|
|
478
|
+
if (opts.rails?.tempo_session) {
|
|
479
|
+
if (!mppx.tempo?.session) {
|
|
480
|
+
throw new Error(
|
|
481
|
+
"mppx.tempo.session not available \u2014 your mppx version may not support sessions yet. Upgrade with `npm install mppx@latest`."
|
|
482
|
+
);
|
|
483
|
+
}
|
|
484
|
+
const s = opts.rails.tempo_session;
|
|
485
|
+
const defaultCurrency = s.testnet ? USDC.tempo.testnet.address : USDC.tempo.mainnet.address;
|
|
486
|
+
methods.push(
|
|
487
|
+
mppx.tempo.session({
|
|
488
|
+
currency: s.currency ?? defaultCurrency,
|
|
489
|
+
recipient: s.recipient,
|
|
490
|
+
escrowContract: s.escrowContract,
|
|
491
|
+
store: s.store,
|
|
492
|
+
testnet: s.testnet ?? false,
|
|
493
|
+
...s.chains ? { chains: s.chains } : {}
|
|
494
|
+
})
|
|
495
|
+
);
|
|
496
|
+
}
|
|
497
|
+
if (opts.rails?.stripe) {
|
|
498
|
+
const stripeMethod = await createMppxStripe(opts.rails.stripe);
|
|
499
|
+
methods.push(stripeMethod);
|
|
500
|
+
}
|
|
501
|
+
return mppx.Mppx.create({ methods, secretKey: opts.secretKey });
|
|
502
|
+
}
|
|
503
|
+
async function dynamicImport2(moduleName) {
|
|
504
|
+
try {
|
|
505
|
+
return await import(moduleName);
|
|
506
|
+
} catch {
|
|
507
|
+
return null;
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
// src/payment/dispatch.ts
|
|
512
|
+
async function dispatchSettlementByNetwork(payload, handlers) {
|
|
513
|
+
const network = payload.accepted.network;
|
|
514
|
+
if (network.startsWith("eip155:")) {
|
|
515
|
+
if (!handlers.evm) {
|
|
516
|
+
throw new Error(`No EVM settlement handler registered (network: ${network})`);
|
|
517
|
+
}
|
|
518
|
+
return handlers.evm(payload);
|
|
519
|
+
}
|
|
520
|
+
if (network.startsWith("solana:")) {
|
|
521
|
+
if (!handlers.svm) {
|
|
522
|
+
throw new Error(`No Solana settlement handler registered (network: ${network})`);
|
|
523
|
+
}
|
|
524
|
+
return handlers.svm(payload);
|
|
525
|
+
}
|
|
526
|
+
throw new Error(`Unrecognized network in settlement payload: ${network}`);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
// src/payment/wwwauthenticate.ts
|
|
530
|
+
function wwwAuthenticateHeader(directives) {
|
|
531
|
+
return directives.join(", ");
|
|
532
|
+
}
|
|
533
|
+
function aliasAmountFields(accepts) {
|
|
534
|
+
return accepts.map((entry) => {
|
|
535
|
+
if (entry === null || typeof entry !== "object") return entry;
|
|
536
|
+
const e = entry;
|
|
537
|
+
const hasAmount = e.amount !== void 0;
|
|
538
|
+
const hasMaxAmount = e.maxAmountRequired !== void 0;
|
|
539
|
+
if (hasAmount && !hasMaxAmount) return { ...e, maxAmountRequired: e.amount };
|
|
540
|
+
if (hasMaxAmount && !hasAmount) return { ...e, amount: e.maxAmountRequired };
|
|
541
|
+
return e;
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
function paymentRequiredHeader(input) {
|
|
545
|
+
return Buffer.from(JSON.stringify(input)).toString("base64");
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
// src/payment/headers.ts
|
|
549
|
+
function buildPaymentHeaders(input) {
|
|
550
|
+
const directives = input.rails.map((rail) => {
|
|
551
|
+
const directiveInput = {
|
|
552
|
+
id: `${input.orderId}-${rail.rail}`,
|
|
553
|
+
realm: input.realm,
|
|
554
|
+
rail: rail.rail,
|
|
555
|
+
amountUsd: rail.amountUsd
|
|
556
|
+
};
|
|
557
|
+
if (rail.recipient !== void 0) directiveInput.recipient = rail.recipient;
|
|
558
|
+
if (rail.networkId !== void 0) directiveInput.networkId = rail.networkId;
|
|
559
|
+
if (rail.chainId !== void 0) directiveInput.chainId = rail.chainId;
|
|
560
|
+
if (rail.currency !== void 0) directiveInput.currency = rail.currency;
|
|
561
|
+
if (rail.decimals !== void 0) directiveInput.decimals = rail.decimals;
|
|
562
|
+
if (rail.method !== void 0) directiveInput.method = rail.method;
|
|
563
|
+
if (rail.intent !== void 0) directiveInput.intent = rail.intent;
|
|
564
|
+
if (rail.expires !== void 0) directiveInput.expires = rail.expires;
|
|
565
|
+
return buildPaymentDirective(directiveInput);
|
|
566
|
+
});
|
|
567
|
+
const result = {
|
|
568
|
+
"www-authenticate": wwwAuthenticateHeader(directives)
|
|
569
|
+
};
|
|
570
|
+
if (input.x402) {
|
|
571
|
+
result["PAYMENT-REQUIRED"] = paymentRequiredHeader({
|
|
572
|
+
x402Version: input.x402.version ?? 2,
|
|
573
|
+
accepts: input.x402.accepts,
|
|
574
|
+
...input.x402.resource ? { resource: input.x402.resource } : {}
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
return result;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
// src/payment/idempotency.ts
|
|
581
|
+
var SERVER_IDEMPOTENCY_KEY_MAX = 200;
|
|
582
|
+
function buildIdempotencyKey(input) {
|
|
583
|
+
const prefix = input.prefix ? `${input.prefix}-` : "";
|
|
584
|
+
if (input.paymentIntentId) {
|
|
585
|
+
const key = `${prefix}${input.paymentIntentId}`;
|
|
586
|
+
return clampKey(key);
|
|
587
|
+
}
|
|
588
|
+
if (input.orderId) {
|
|
589
|
+
const amountSuffix = input.amountCents !== void 0 ? `-${input.amountCents}` : "";
|
|
590
|
+
const key = `${prefix}pi-${input.orderId}${amountSuffix}`;
|
|
591
|
+
return clampKey(key);
|
|
592
|
+
}
|
|
593
|
+
return void 0;
|
|
594
|
+
}
|
|
595
|
+
function clampKey(key) {
|
|
596
|
+
if (key.length <= SERVER_IDEMPOTENCY_KEY_MAX) return key;
|
|
597
|
+
console.warn(
|
|
598
|
+
`[agentscore-commerce] idempotency key longer than ${SERVER_IDEMPOTENCY_KEY_MAX} chars \u2014 server will truncate, may cause silent collisions if multiple keys share the first ${SERVER_IDEMPOTENCY_KEY_MAX} chars.`
|
|
599
|
+
);
|
|
600
|
+
return key;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
// src/signer.ts
|
|
604
|
+
async function extractPaymentSigner(request, x402PaymentHeader) {
|
|
605
|
+
const authHeader = request.headers.get("authorization");
|
|
606
|
+
if (authHeader) {
|
|
607
|
+
try {
|
|
608
|
+
const moduleName = "mppx";
|
|
609
|
+
const mppx = await import(moduleName).catch(() => null);
|
|
610
|
+
if (mppx?.Credential?.extractPaymentScheme(authHeader)) {
|
|
611
|
+
const credential = mppx.Credential.fromRequest(request);
|
|
612
|
+
const source = credential.source;
|
|
613
|
+
const match = source?.match(/^did:pkh:eip155:\d+:(0x[0-9a-fA-F]{40})$/);
|
|
614
|
+
if (match) return { address: match[1].toLowerCase(), network: "evm" };
|
|
615
|
+
}
|
|
616
|
+
} catch (err) {
|
|
617
|
+
console.warn("[gate] MPP signer extraction failed:", err instanceof Error ? err.message : err);
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
if (x402PaymentHeader) {
|
|
621
|
+
try {
|
|
622
|
+
const decoded = atob(x402PaymentHeader);
|
|
623
|
+
const parsed = JSON.parse(decoded);
|
|
624
|
+
const network = parsed?.accepted?.network ?? "";
|
|
625
|
+
if (network.startsWith("eip155:")) {
|
|
626
|
+
const from = parsed?.payload?.authorization?.from;
|
|
627
|
+
if (typeof from === "string" && /^0x[0-9a-fA-F]{40}$/.test(from)) {
|
|
628
|
+
return { address: from.toLowerCase(), network: "evm" };
|
|
629
|
+
}
|
|
630
|
+
} else if (network.startsWith("solana:")) {
|
|
631
|
+
const transaction = parsed?.payload?.transaction;
|
|
632
|
+
if (typeof transaction === "string") {
|
|
633
|
+
const moduleName = "@x402/svm";
|
|
634
|
+
const svm = await import(moduleName).catch(() => null);
|
|
635
|
+
if (svm?.decodeTransactionFromPayload && svm.getTokenPayerFromTransaction) {
|
|
636
|
+
const tx = svm.decodeTransactionFromPayload({ transaction });
|
|
637
|
+
const payer = svm.getTokenPayerFromTransaction(tx);
|
|
638
|
+
if (typeof payer === "string" && payer.length > 0) return { address: payer, network: "solana" };
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
} else {
|
|
642
|
+
const from = parsed?.payload?.authorization?.from;
|
|
643
|
+
if (typeof from === "string" && /^0x[0-9a-fA-F]{40}$/.test(from)) {
|
|
644
|
+
return { address: from.toLowerCase(), network: "evm" };
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
} catch (err) {
|
|
648
|
+
console.warn("[gate] x402 signer extraction failed:", err instanceof Error ? err.message : err);
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
return null;
|
|
652
|
+
}
|
|
653
|
+
function readX402PaymentHeader(request) {
|
|
654
|
+
return request.headers.get("payment-signature") ?? request.headers.get("x-payment") ?? void 0;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
// src/payment/settlement_override.ts
|
|
658
|
+
var SETTLEMENT_OVERRIDES_HEADER = "Settlement-Overrides";
|
|
659
|
+
function settlementOverrideHeader(overrides) {
|
|
660
|
+
return { name: SETTLEMENT_OVERRIDES_HEADER, value: JSON.stringify(overrides) };
|
|
661
|
+
}
|
|
662
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
663
|
+
0 && (module.exports = {
|
|
664
|
+
SETTLEMENT_OVERRIDES_HEADER,
|
|
665
|
+
USDC,
|
|
666
|
+
X402_SUPPORTED_BASE_NETWORKS,
|
|
667
|
+
X402_SUPPORTED_SVM_NETWORKS,
|
|
668
|
+
aliasAmountFields,
|
|
669
|
+
buildIdempotencyKey,
|
|
670
|
+
buildPaymentDirective,
|
|
671
|
+
buildPaymentHeaders,
|
|
672
|
+
buildPaymentRequestBlob,
|
|
673
|
+
createMppxServer,
|
|
674
|
+
createX402Server,
|
|
675
|
+
dispatchSettlementByNetwork,
|
|
676
|
+
extractPaymentSigner,
|
|
677
|
+
lookupRail,
|
|
678
|
+
networkFamily,
|
|
679
|
+
networks,
|
|
680
|
+
paymentDirective,
|
|
681
|
+
paymentRequiredHeader,
|
|
682
|
+
processX402Settle,
|
|
683
|
+
rails,
|
|
684
|
+
readX402PaymentHeader,
|
|
685
|
+
registerX402SchemesV1V2,
|
|
686
|
+
settlementOverrideHeader,
|
|
687
|
+
validateX402NetworkConfig,
|
|
688
|
+
verifyX402Request,
|
|
689
|
+
wwwAuthenticateHeader
|
|
690
|
+
});
|
|
691
|
+
//# sourceMappingURL=index.js.map
|