@agent-score/commerce 1.8.1 → 2.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/README.md +73 -9
- package/dist/{_response-9yp6Fit2.d.mts → _response-BFYN3b6i.d.mts} +17 -19
- package/dist/{_response-CC6jNb8q.d.ts → _response-_iPD5AIj.d.ts} +17 -19
- package/dist/challenge/index.d.mts +106 -198
- package/dist/challenge/index.d.ts +106 -198
- package/dist/challenge/index.js +238 -111
- package/dist/challenge/index.js.map +1 -1
- package/dist/challenge/index.mjs +238 -111
- package/dist/challenge/index.mjs.map +1 -1
- package/dist/checkout-BoFwnVsj.d.ts +931 -0
- package/dist/checkout-DRbQ0Fsh.d.mts +931 -0
- package/dist/core.d.mts +2 -2
- package/dist/core.d.ts +2 -2
- package/dist/core.js +1 -1
- package/dist/core.js.map +1 -1
- package/dist/core.mjs +1 -1
- package/dist/core.mjs.map +1 -1
- package/dist/discovery/index.d.mts +453 -51
- package/dist/discovery/index.d.ts +453 -51
- package/dist/discovery/index.js +1092 -58
- package/dist/discovery/index.js.map +1 -1
- package/dist/discovery/index.mjs +1060 -57
- package/dist/discovery/index.mjs.map +1 -1
- package/dist/identity/express.d.mts +3 -3
- package/dist/identity/express.d.ts +3 -3
- package/dist/identity/express.js +30 -19
- package/dist/identity/express.js.map +1 -1
- package/dist/identity/express.mjs +30 -19
- package/dist/identity/express.mjs.map +1 -1
- package/dist/identity/fastify.d.mts +4 -4
- package/dist/identity/fastify.d.ts +4 -4
- package/dist/identity/fastify.js +30 -19
- package/dist/identity/fastify.js.map +1 -1
- package/dist/identity/fastify.mjs +30 -19
- package/dist/identity/fastify.mjs.map +1 -1
- package/dist/identity/hono.d.mts +3 -3
- package/dist/identity/hono.d.ts +3 -3
- package/dist/identity/hono.js +30 -19
- package/dist/identity/hono.js.map +1 -1
- package/dist/identity/hono.mjs +30 -19
- package/dist/identity/hono.mjs.map +1 -1
- package/dist/identity/nextjs.d.mts +6 -7
- package/dist/identity/nextjs.d.ts +6 -7
- package/dist/identity/nextjs.js +30 -19
- package/dist/identity/nextjs.js.map +1 -1
- package/dist/identity/nextjs.mjs +30 -19
- package/dist/identity/nextjs.mjs.map +1 -1
- package/dist/identity/policy.d.mts +41 -4
- package/dist/identity/policy.d.ts +41 -4
- package/dist/identity/policy.js +3662 -18
- package/dist/identity/policy.js.map +1 -1
- package/dist/identity/policy.mjs +3648 -3
- package/dist/identity/policy.mjs.map +1 -1
- package/dist/identity/web.d.mts +3 -3
- package/dist/identity/web.d.ts +3 -3
- package/dist/identity/web.js +30 -19
- package/dist/identity/web.js.map +1 -1
- package/dist/identity/web.mjs +30 -19
- package/dist/identity/web.mjs.map +1 -1
- package/dist/index.d.mts +72 -329
- package/dist/index.d.ts +72 -329
- package/dist/index.js +3651 -373
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3628 -361
- package/dist/index.mjs.map +1 -1
- package/dist/payment/index.d.mts +256 -265
- package/dist/payment/index.d.ts +256 -265
- package/dist/payment/index.js +586 -149
- package/dist/payment/index.js.map +1 -1
- package/dist/payment/index.mjs +573 -148
- package/dist/payment/index.mjs.map +1 -1
- package/dist/{agent_instructions-DiMSGkdm.d.mts → pricing-CQ9DIFaw.d.ts} +109 -56
- package/dist/{agent_instructions-DiMSGkdm.d.ts → pricing-CxzwyiO6.d.mts} +109 -56
- package/dist/rail_spec-XP0wKgJV.d.mts +132 -0
- package/dist/rail_spec-XP0wKgJV.d.ts +132 -0
- package/dist/{signer-CFVQsWjL.d.mts → signer-3FAit11j.d.mts} +27 -1
- package/dist/{signer-CFVQsWjL.d.ts → signer-3FAit11j.d.ts} +27 -1
- package/dist/solana-Cds87OTu.d.mts +67 -0
- package/dist/solana-Cds87OTu.d.ts +67 -0
- package/dist/stripe-multichain/index.d.mts +55 -66
- package/dist/stripe-multichain/index.d.ts +55 -66
- package/dist/stripe-multichain/index.js +68 -42
- package/dist/stripe-multichain/index.js.map +1 -1
- package/dist/stripe-multichain/index.mjs +68 -41
- package/dist/stripe-multichain/index.mjs.map +1 -1
- package/dist/{wwwauthenticate-CU1eNvMQ.d.mts → wwwauthenticate-D_FMnPgU.d.mts} +9 -10
- package/dist/{wwwauthenticate-CU1eNvMQ.d.ts → wwwauthenticate-D_FMnPgU.d.ts} +9 -10
- package/dist/x402_server-hgQzWQwB.d.mts +81 -0
- package/dist/x402_server-hgQzWQwB.d.ts +81 -0
- package/package.json +9 -7
package/dist/payment/index.js
CHANGED
|
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/payment/index.ts
|
|
21
21
|
var payment_exports = {};
|
|
22
22
|
__export(payment_exports, {
|
|
23
|
+
RAIL_SPEC_DEFAULTS: () => RAIL_SPEC_DEFAULTS,
|
|
23
24
|
SETTLEMENT_OVERRIDES_HEADER: () => SETTLEMENT_OVERRIDES_HEADER,
|
|
24
25
|
USDC: () => USDC,
|
|
25
26
|
X402_SUPPORTED_BASE_NETWORKS: () => X402_SUPPORTED_BASE_NETWORKS,
|
|
@@ -29,11 +30,19 @@ __export(payment_exports, {
|
|
|
29
30
|
buildPaymentHeaders: () => buildPaymentHeaders,
|
|
30
31
|
buildPaymentRequestBlob: () => buildPaymentRequestBlob,
|
|
31
32
|
buildX402AcceptsFor402: () => buildX402AcceptsFor402,
|
|
33
|
+
classifyOrchestrationError: () => classifyOrchestrationError,
|
|
32
34
|
classifyX402SettleResult: () => classifyX402SettleResult,
|
|
33
35
|
createMppxServer: () => createMppxServer,
|
|
34
36
|
createX402Server: () => createX402Server,
|
|
37
|
+
detectRailFromHeaders: () => detectRailFromHeaders,
|
|
35
38
|
dispatchSettlementByNetwork: () => dispatchSettlementByNetwork,
|
|
36
39
|
extractPaymentSigner: () => extractPaymentSigner,
|
|
40
|
+
extractPaymentSignerFromAuth: () => extractPaymentSignerFromAuth,
|
|
41
|
+
extractSignerForPrecheck: () => extractSignerForPrecheck,
|
|
42
|
+
formatUsdCents: () => formatUsdCents,
|
|
43
|
+
lazyMppxServer: () => lazyMppxServer,
|
|
44
|
+
lazyX402Server: () => lazyX402Server,
|
|
45
|
+
loadSolanaFeePayer: () => loadSolanaFeePayer,
|
|
37
46
|
lookupRail: () => lookupRail,
|
|
38
47
|
networkFamily: () => networkFamily,
|
|
39
48
|
networks: () => networks,
|
|
@@ -43,11 +52,14 @@ __export(payment_exports, {
|
|
|
43
52
|
rails: () => rails,
|
|
44
53
|
readX402PaymentHeader: () => readX402PaymentHeader,
|
|
45
54
|
registerX402SchemesV1V2: () => registerX402SchemesV1V2,
|
|
55
|
+
resolveRecipient: () => resolveRecipient,
|
|
46
56
|
settlementOverrideHeader: () => settlementOverrideHeader,
|
|
57
|
+
usdToAtomic: () => usdToAtomic,
|
|
47
58
|
validateX402NetworkConfig: () => validateX402NetworkConfig,
|
|
48
59
|
verifyX402Request: () => verifyX402Request,
|
|
49
60
|
wrapSolanaChargeWithFinalizedBlockhash: () => wrapSolanaChargeWithFinalizedBlockhash,
|
|
50
|
-
wwwAuthenticateHeader: () => wwwAuthenticateHeader
|
|
61
|
+
wwwAuthenticateHeader: () => wwwAuthenticateHeader,
|
|
62
|
+
zeroAmountCarveOut: () => zeroAmountCarveOut
|
|
51
63
|
});
|
|
52
64
|
module.exports = __toCommonJS(payment_exports);
|
|
53
65
|
|
|
@@ -168,49 +180,116 @@ function lookupRail(name) {
|
|
|
168
180
|
}
|
|
169
181
|
|
|
170
182
|
// src/payment/directive.ts
|
|
171
|
-
function buildPaymentRequestBlob(
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
183
|
+
function buildPaymentRequestBlob({
|
|
184
|
+
rail,
|
|
185
|
+
amountUsd,
|
|
186
|
+
currency,
|
|
187
|
+
decimals,
|
|
188
|
+
recipient,
|
|
189
|
+
chainId,
|
|
190
|
+
networkId
|
|
191
|
+
}) {
|
|
192
|
+
const railDef = rail ? lookupRail(rail) : void 0;
|
|
193
|
+
const decimalsResolved = decimals ?? railDef?.decimals ?? 6;
|
|
194
|
+
const currencyResolved = currency ?? railDef?.currency ?? "usd";
|
|
195
|
+
const chainIdResolved = chainId ?? railDef?.chainId;
|
|
196
|
+
const amountNum = typeof amountUsd === "string" ? Number(amountUsd) : amountUsd;
|
|
197
|
+
const amountRaw = BigInt(Math.round(amountNum * 10 ** decimalsResolved)).toString();
|
|
198
|
+
const blob = { amount: amountRaw, currency: currencyResolved, decimals: decimalsResolved };
|
|
199
|
+
if (recipient) blob.recipient = recipient;
|
|
180
200
|
const methodDetails = {};
|
|
181
|
-
if (
|
|
182
|
-
if (
|
|
201
|
+
if (chainIdResolved !== void 0) methodDetails.chainId = chainIdResolved;
|
|
202
|
+
if (networkId) methodDetails.networkId = networkId;
|
|
183
203
|
if (Object.keys(methodDetails).length > 0) blob.methodDetails = methodDetails;
|
|
184
204
|
return Buffer.from(JSON.stringify(blob)).toString("base64url");
|
|
185
205
|
}
|
|
186
|
-
function paymentDirective(
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
206
|
+
function paymentDirective({
|
|
207
|
+
rail,
|
|
208
|
+
id,
|
|
209
|
+
realm,
|
|
210
|
+
method,
|
|
211
|
+
intent,
|
|
212
|
+
expires,
|
|
213
|
+
request
|
|
214
|
+
}) {
|
|
215
|
+
const railDef = rail ? lookupRail(rail) : void 0;
|
|
216
|
+
const methodResolved = method ?? railDef?.method ?? "unknown";
|
|
217
|
+
const intentResolved = intent ?? "charge";
|
|
218
|
+
const expiresResolved = expires ?? new Date(Date.now() + 5 * 60 * 1e3).toISOString();
|
|
219
|
+
return `Payment id="${id}", realm="${realm}", method="${methodResolved}", intent="${intentResolved}", expires="${expiresResolved}", request="${request}"`;
|
|
192
220
|
}
|
|
193
|
-
function buildPaymentDirective(
|
|
221
|
+
function buildPaymentDirective({
|
|
222
|
+
rail,
|
|
223
|
+
id,
|
|
224
|
+
realm,
|
|
225
|
+
amountUsd,
|
|
226
|
+
currency,
|
|
227
|
+
decimals,
|
|
228
|
+
recipient,
|
|
229
|
+
chainId,
|
|
230
|
+
networkId,
|
|
231
|
+
method,
|
|
232
|
+
intent,
|
|
233
|
+
expires
|
|
234
|
+
}) {
|
|
194
235
|
const request = buildPaymentRequestBlob({
|
|
195
|
-
rail
|
|
196
|
-
amountUsd
|
|
197
|
-
currency
|
|
198
|
-
decimals
|
|
199
|
-
recipient
|
|
200
|
-
chainId
|
|
201
|
-
networkId
|
|
236
|
+
rail,
|
|
237
|
+
amountUsd,
|
|
238
|
+
currency,
|
|
239
|
+
decimals,
|
|
240
|
+
recipient,
|
|
241
|
+
chainId,
|
|
242
|
+
networkId
|
|
202
243
|
});
|
|
203
244
|
return paymentDirective({
|
|
204
|
-
rail
|
|
205
|
-
id
|
|
206
|
-
realm
|
|
207
|
-
method
|
|
208
|
-
intent
|
|
209
|
-
expires
|
|
245
|
+
rail,
|
|
246
|
+
id,
|
|
247
|
+
realm,
|
|
248
|
+
method,
|
|
249
|
+
intent,
|
|
250
|
+
expires,
|
|
210
251
|
request
|
|
211
252
|
});
|
|
212
253
|
}
|
|
213
254
|
|
|
255
|
+
// src/payment/rail_spec.ts
|
|
256
|
+
async function resolveRecipient(r) {
|
|
257
|
+
if (typeof r === "string") return r;
|
|
258
|
+
return Promise.resolve(r());
|
|
259
|
+
}
|
|
260
|
+
var RAIL_SPEC_DEFAULTS = {
|
|
261
|
+
tempo: {
|
|
262
|
+
network: "tempo-mainnet",
|
|
263
|
+
chainId: 4217,
|
|
264
|
+
token: USDC.tempo.mainnet.address,
|
|
265
|
+
symbol: "USDC.e",
|
|
266
|
+
decimals: 6,
|
|
267
|
+
testnet: false,
|
|
268
|
+
recommend: "both"
|
|
269
|
+
},
|
|
270
|
+
x402Base: {
|
|
271
|
+
network: "eip155:8453",
|
|
272
|
+
chainId: 8453,
|
|
273
|
+
token: USDC.base.mainnet.address,
|
|
274
|
+
symbol: "USDC",
|
|
275
|
+
decimals: 6,
|
|
276
|
+
mode: "exact"
|
|
277
|
+
},
|
|
278
|
+
solanaMpp: {
|
|
279
|
+
network: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
|
|
280
|
+
token: USDC.solana.mainnet.mint,
|
|
281
|
+
symbol: "USDC",
|
|
282
|
+
decimals: 6
|
|
283
|
+
},
|
|
284
|
+
stripe: {
|
|
285
|
+
rails: ["card", "link", "shared_payment_token"]
|
|
286
|
+
},
|
|
287
|
+
tempoSession: {
|
|
288
|
+
currency: USDC.tempo.mainnet.address,
|
|
289
|
+
testnet: false
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
|
|
214
293
|
// src/payment/x402.ts
|
|
215
294
|
function registerX402SchemesV1V2(server, network, scheme) {
|
|
216
295
|
server.register(network, scheme);
|
|
@@ -228,7 +307,8 @@ async function createX402Server(opts = {}) {
|
|
|
228
307
|
);
|
|
229
308
|
}
|
|
230
309
|
let facilitator;
|
|
231
|
-
|
|
310
|
+
const facilitatorChoice = opts.facilitator ?? (process.env.CDP_API_KEY_ID && process.env.CDP_API_KEY_SECRET ? "coinbase" : "http");
|
|
311
|
+
if (facilitatorChoice === "coinbase") {
|
|
232
312
|
const cb = await dynamicImport("@coinbase/x402");
|
|
233
313
|
if (!cb?.facilitator) {
|
|
234
314
|
throw new Error(
|
|
@@ -236,10 +316,10 @@ async function createX402Server(opts = {}) {
|
|
|
236
316
|
);
|
|
237
317
|
}
|
|
238
318
|
facilitator = new x402Core.HTTPFacilitatorClient(cb.facilitator);
|
|
239
|
-
} else if (
|
|
319
|
+
} else if (facilitatorChoice === "http") {
|
|
240
320
|
facilitator = new x402Core.HTTPFacilitatorClient();
|
|
241
321
|
} else {
|
|
242
|
-
facilitator =
|
|
322
|
+
facilitator = facilitatorChoice;
|
|
243
323
|
}
|
|
244
324
|
const server = new x402Core.x402ResourceServer(facilitator);
|
|
245
325
|
let evmExactModule = null;
|
|
@@ -349,44 +429,95 @@ function classifyX402SettleResult(result) {
|
|
|
349
429
|
};
|
|
350
430
|
}
|
|
351
431
|
}
|
|
352
|
-
|
|
353
|
-
|
|
432
|
+
function classifyOrchestrationError(err) {
|
|
433
|
+
let msg;
|
|
434
|
+
if (err instanceof Error) {
|
|
435
|
+
msg = err.message;
|
|
436
|
+
} else if (typeof err === "string") {
|
|
437
|
+
msg = err;
|
|
438
|
+
} else {
|
|
439
|
+
return null;
|
|
440
|
+
}
|
|
441
|
+
const msgLower = msg.toLowerCase();
|
|
442
|
+
if (msgLower.includes("x402version") || msgLower.includes("invalid payment") || msgLower.includes("unsupported x402")) {
|
|
443
|
+
return {
|
|
444
|
+
status: 400,
|
|
445
|
+
code: "payment_proof_invalid",
|
|
446
|
+
message: "Payment credential is malformed or uses an unsupported version",
|
|
447
|
+
nextSteps: {
|
|
448
|
+
action: "regenerate_payment_credential",
|
|
449
|
+
user_message: "The payment credential is malformed or uses an unsupported version. Regenerate from a fresh 402 challenge and re-sign."
|
|
450
|
+
}
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
if (msgLower.includes("stripe") || msgLower.includes("facilitator") || msgLower.includes("cdp")) {
|
|
454
|
+
return {
|
|
455
|
+
status: 503,
|
|
456
|
+
code: "payment_provider_unavailable",
|
|
457
|
+
message: "Payment provider returned an error",
|
|
458
|
+
nextSteps: {
|
|
459
|
+
action: "retry_or_swap_method",
|
|
460
|
+
retry_after_seconds: 10,
|
|
461
|
+
user_message: "Transient payment-provider error. Retry in a few seconds, or pick a different rail from the 402 challenge."
|
|
462
|
+
}
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
return null;
|
|
466
|
+
}
|
|
467
|
+
async function processX402Settle({
|
|
468
|
+
x402Server,
|
|
469
|
+
payload,
|
|
470
|
+
resourceConfig,
|
|
471
|
+
resourceMeta,
|
|
472
|
+
extension,
|
|
473
|
+
transportContext
|
|
474
|
+
}) {
|
|
475
|
+
const server = x402Server;
|
|
354
476
|
let builtRequirements;
|
|
355
477
|
try {
|
|
356
|
-
builtRequirements = await server.buildPaymentRequirements(
|
|
478
|
+
builtRequirements = await server.buildPaymentRequirements(resourceConfig);
|
|
357
479
|
} catch (err) {
|
|
480
|
+
console.warn("[x402_settle] build_requirements failed:", err instanceof Error ? err.message : err);
|
|
358
481
|
return { success: false, phase: "facilitator_error", step: "build_requirements", error: err };
|
|
359
482
|
}
|
|
360
483
|
const matchedRequirement = builtRequirements[0];
|
|
361
484
|
if (!matchedRequirement) {
|
|
362
485
|
return { success: false, phase: "no_requirements", reason: "x402Server.buildPaymentRequirements returned empty" };
|
|
363
486
|
}
|
|
364
|
-
const
|
|
365
|
-
const path = new URL(
|
|
487
|
+
const resolvedTransportContext = transportContext ?? (() => {
|
|
488
|
+
const path = new URL(resourceMeta.url).pathname;
|
|
366
489
|
return { method: "POST", adapter: { getPath: () => path }, routePattern: path };
|
|
367
490
|
})();
|
|
368
491
|
let enrichedExt;
|
|
369
492
|
try {
|
|
370
|
-
enrichedExt =
|
|
493
|
+
enrichedExt = extension !== void 0 ? server.enrichExtensions(extension, resolvedTransportContext) : void 0;
|
|
371
494
|
} catch (err) {
|
|
495
|
+
console.warn("[x402_settle] enrich_extensions failed:", err instanceof Error ? err.message : err);
|
|
372
496
|
return { success: false, phase: "facilitator_error", step: "enrich_extensions", error: err };
|
|
373
497
|
}
|
|
374
498
|
let verifyResult;
|
|
375
499
|
try {
|
|
376
|
-
verifyResult = await server.
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
500
|
+
verifyResult = await server.verifyPayment(
|
|
501
|
+
payload,
|
|
502
|
+
matchedRequirement,
|
|
503
|
+
enrichedExt,
|
|
504
|
+
resolvedTransportContext
|
|
381
505
|
);
|
|
382
506
|
} catch (err) {
|
|
383
|
-
|
|
507
|
+
console.warn("[x402_settle] verify_payment failed:", err instanceof Error ? err.message : err);
|
|
508
|
+
return { success: false, phase: "facilitator_error", step: "verify_payment", error: err };
|
|
384
509
|
}
|
|
385
|
-
|
|
510
|
+
const verifyOk = verifyResult.isValid === true || verifyResult.success === true;
|
|
511
|
+
if (!verifyOk) {
|
|
386
512
|
return { success: false, phase: "verify_failed", verifyResult };
|
|
387
513
|
}
|
|
388
514
|
try {
|
|
389
|
-
const settleResult = await server.settlePayment(
|
|
515
|
+
const settleResult = await server.settlePayment(
|
|
516
|
+
payload,
|
|
517
|
+
matchedRequirement,
|
|
518
|
+
enrichedExt,
|
|
519
|
+
resolvedTransportContext
|
|
520
|
+
);
|
|
390
521
|
const paymentResponseHeader = settleResult ? Buffer.from(JSON.stringify(settleResult)).toString("base64") : void 0;
|
|
391
522
|
return {
|
|
392
523
|
success: true,
|
|
@@ -405,10 +536,10 @@ var X402_SUPPORTED_BASE_NETWORKS = /* @__PURE__ */ new Set([
|
|
|
405
536
|
networks.base.mainnet.caip2,
|
|
406
537
|
networks.base.sepolia.caip2
|
|
407
538
|
]);
|
|
408
|
-
function validateX402NetworkConfig(
|
|
409
|
-
if (!X402_SUPPORTED_BASE_NETWORKS.has(
|
|
539
|
+
function validateX402NetworkConfig({ baseNetwork }) {
|
|
540
|
+
if (!X402_SUPPORTED_BASE_NETWORKS.has(baseNetwork)) {
|
|
410
541
|
throw new Error(
|
|
411
|
-
`X402_BASE_NETWORK=${
|
|
542
|
+
`X402_BASE_NETWORK=${baseNetwork} is not supported. Use one of: ${[...X402_SUPPORTED_BASE_NETWORKS].join(", ")}`
|
|
412
543
|
);
|
|
413
544
|
}
|
|
414
545
|
}
|
|
@@ -424,8 +555,12 @@ function regenerateBody(message, userMessage) {
|
|
|
424
555
|
}
|
|
425
556
|
};
|
|
426
557
|
}
|
|
427
|
-
async function verifyX402Request(
|
|
428
|
-
|
|
558
|
+
async function verifyX402Request({
|
|
559
|
+
request,
|
|
560
|
+
isCachedAddress,
|
|
561
|
+
acceptedNetwork
|
|
562
|
+
}) {
|
|
563
|
+
const headerValue = request.headers.get("payment-signature") ?? request.headers.get("x-payment");
|
|
429
564
|
if (!headerValue) {
|
|
430
565
|
return {
|
|
431
566
|
ok: false,
|
|
@@ -451,13 +586,13 @@ async function verifyX402Request(input) {
|
|
|
451
586
|
}
|
|
452
587
|
const signedNetwork = payload.accepted?.network;
|
|
453
588
|
const signedPayTo = payload.accepted?.payTo;
|
|
454
|
-
if (!signedNetwork || signedNetwork !==
|
|
589
|
+
if (!signedNetwork || signedNetwork !== acceptedNetwork) {
|
|
455
590
|
if (signedNetwork && signedNetwork.toLowerCase().startsWith("solana:")) {
|
|
456
591
|
return {
|
|
457
592
|
ok: false,
|
|
458
593
|
status: 400,
|
|
459
594
|
body: regenerateBody(
|
|
460
|
-
`x402 on ${signedNetwork} is not accepted; Solana payments must use the \`solana/charge\` rail advertised in the 402 challenge. This server accepts x402 on ${
|
|
595
|
+
`x402 on ${signedNetwork} is not accepted; Solana payments must use the \`solana/charge\` rail advertised in the 402 challenge. This server accepts x402 on ${acceptedNetwork} only.`,
|
|
461
596
|
"Solana payments are not accepted over x402 at this merchant. Pick the `solana/charge` rail from the 402 challenge and re-sign."
|
|
462
597
|
)
|
|
463
598
|
};
|
|
@@ -466,7 +601,7 @@ async function verifyX402Request(input) {
|
|
|
466
601
|
ok: false,
|
|
467
602
|
status: 400,
|
|
468
603
|
body: regenerateBody(
|
|
469
|
-
`Unsupported x402 network ${signedNetwork ?? "<missing>"}; this server accepts ${
|
|
604
|
+
`Unsupported x402 network ${signedNetwork ?? "<missing>"}; this server accepts ${acceptedNetwork}.`,
|
|
470
605
|
"The credential signed for an unsupported network. Pick the accepted network from the 402 challenge and re-sign."
|
|
471
606
|
)
|
|
472
607
|
};
|
|
@@ -482,7 +617,7 @@ async function verifyX402Request(input) {
|
|
|
482
617
|
)
|
|
483
618
|
};
|
|
484
619
|
}
|
|
485
|
-
if (!await
|
|
620
|
+
if (!await isCachedAddress(signedPayTo)) {
|
|
486
621
|
return {
|
|
487
622
|
ok: false,
|
|
488
623
|
status: 400,
|
|
@@ -496,7 +631,11 @@ async function verifyX402Request(input) {
|
|
|
496
631
|
}
|
|
497
632
|
|
|
498
633
|
// src/stripe-multichain/mppx_stripe.ts
|
|
499
|
-
async function createMppxStripe(
|
|
634
|
+
async function createMppxStripe({
|
|
635
|
+
profileId,
|
|
636
|
+
secretKey,
|
|
637
|
+
paymentMethodTypes
|
|
638
|
+
}) {
|
|
500
639
|
const moduleName = "mppx/server";
|
|
501
640
|
const mppx = await import(moduleName).catch(() => null);
|
|
502
641
|
if (!mppx?.stripe?.charge) {
|
|
@@ -505,80 +644,130 @@ async function createMppxStripe(input) {
|
|
|
505
644
|
);
|
|
506
645
|
}
|
|
507
646
|
return mppx.stripe.charge({
|
|
508
|
-
networkId:
|
|
509
|
-
paymentMethodTypes:
|
|
510
|
-
secretKey
|
|
647
|
+
networkId: profileId,
|
|
648
|
+
paymentMethodTypes: paymentMethodTypes ?? ["card", "link"],
|
|
649
|
+
secretKey
|
|
511
650
|
});
|
|
512
651
|
}
|
|
513
652
|
|
|
514
653
|
// src/payment/mppx_server.ts
|
|
515
|
-
|
|
654
|
+
function isStripeRailSpec(s) {
|
|
655
|
+
return !("recipient" in s);
|
|
656
|
+
}
|
|
657
|
+
function isTempoSessionRailSpec(s) {
|
|
658
|
+
return "escrowContract" in s && "store" in s;
|
|
659
|
+
}
|
|
660
|
+
function isSolanaMppRailSpec(s) {
|
|
661
|
+
if (!("recipient" in s)) return false;
|
|
662
|
+
if ("escrowContract" in s) return false;
|
|
663
|
+
if ("rpcUrl" in s || "tokenProgram" in s) return true;
|
|
664
|
+
return s.network?.startsWith("solana:") ?? false;
|
|
665
|
+
}
|
|
666
|
+
function solanaNetworkFromCAIP2(caip2) {
|
|
667
|
+
if (caip2 === networks.solana.devnet.caip2) return "devnet";
|
|
668
|
+
return "mainnet-beta";
|
|
669
|
+
}
|
|
670
|
+
function solanaDefaultRpcUrl(network) {
|
|
671
|
+
if (network === "mainnet-beta") return "https://api.mainnet-beta.solana.com";
|
|
672
|
+
if (network === "devnet") return "https://api.devnet.solana.com";
|
|
673
|
+
return "http://localhost:8899";
|
|
674
|
+
}
|
|
675
|
+
async function createMppxServer({
|
|
676
|
+
rails: rails2,
|
|
677
|
+
methods: extraMethods,
|
|
678
|
+
secretKey
|
|
679
|
+
}) {
|
|
516
680
|
const mppx = await dynamicImport2("mppx/server");
|
|
517
681
|
if (!mppx?.Mppx?.create) {
|
|
518
682
|
throw new Error("mppx not installed \u2014 `npm install mppx` to use createMppxServer.");
|
|
519
683
|
}
|
|
520
|
-
const methods = [...
|
|
521
|
-
|
|
522
|
-
if (
|
|
523
|
-
|
|
684
|
+
const methods = [...extraMethods ?? []];
|
|
685
|
+
for (const [name, spec] of Object.entries(rails2 ?? {})) {
|
|
686
|
+
if (isStripeRailSpec(spec)) {
|
|
687
|
+
methods.push(await registerStripe(spec));
|
|
688
|
+
continue;
|
|
689
|
+
}
|
|
690
|
+
if (isTempoSessionRailSpec(spec)) {
|
|
691
|
+
methods.push(await registerTempoSession(mppx, spec));
|
|
692
|
+
continue;
|
|
524
693
|
}
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
694
|
+
if (isSolanaMppRailSpec(spec)) {
|
|
695
|
+
methods.push(await registerSolana(spec));
|
|
696
|
+
continue;
|
|
697
|
+
}
|
|
698
|
+
methods.push(registerTempo(mppx, spec, name));
|
|
699
|
+
}
|
|
700
|
+
return mppx.Mppx.create({ methods, secretKey });
|
|
701
|
+
}
|
|
702
|
+
function registerTempo(mppx, spec, _name) {
|
|
703
|
+
if (!mppx.tempo?.charge) {
|
|
704
|
+
throw new Error("mppx.tempo.charge not available \u2014 check installed mppx version.");
|
|
705
|
+
}
|
|
706
|
+
const defaultCurrency = spec.testnet ? USDC.tempo.testnet.address : USDC.tempo.mainnet.address;
|
|
707
|
+
if (typeof spec.recipient !== "string") {
|
|
708
|
+
throw new TypeError(
|
|
709
|
+
"createMppxServer: TempoRailSpec requires a string recipient (per-order factories not supported here)."
|
|
533
710
|
);
|
|
534
711
|
}
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
mppx.tempo.session
|
|
545
|
-
currency: s.currency ?? defaultCurrency,
|
|
546
|
-
recipient: s.recipient,
|
|
547
|
-
escrowContract: s.escrowContract,
|
|
548
|
-
store: s.store,
|
|
549
|
-
testnet: s.testnet ?? false,
|
|
550
|
-
...s.chains ? { chains: s.chains } : {}
|
|
551
|
-
})
|
|
712
|
+
return mppx.tempo.charge({
|
|
713
|
+
currency: spec.token ?? defaultCurrency,
|
|
714
|
+
recipient: spec.recipient,
|
|
715
|
+
testnet: spec.testnet ?? false
|
|
716
|
+
});
|
|
717
|
+
}
|
|
718
|
+
async function registerTempoSession(mppx, spec) {
|
|
719
|
+
if (!mppx.tempo?.session) {
|
|
720
|
+
throw new Error(
|
|
721
|
+
"mppx.tempo.session not available \u2014 your mppx version may not support sessions yet. Upgrade with `npm install mppx@latest`."
|
|
552
722
|
);
|
|
553
723
|
}
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
...s.rpcUrl ? { rpcUrl: s.rpcUrl } : {},
|
|
571
|
-
...s.signer ? { signer: s.signer } : {},
|
|
572
|
-
...s.tokenProgram ? { tokenProgram: s.tokenProgram } : {}
|
|
573
|
-
});
|
|
574
|
-
const rpcUrl = s.rpcUrl ?? (network === "mainnet-beta" ? "https://api.mainnet-beta.solana.com" : network === "devnet" ? "https://api.devnet.solana.com" : "http://localhost:8899");
|
|
575
|
-
methods.push(wrapSolanaChargeWithFinalizedBlockhash(baseMethod, rpcUrl));
|
|
724
|
+
const defaultCurrency = spec.testnet ? USDC.tempo.testnet.address : USDC.tempo.mainnet.address;
|
|
725
|
+
return mppx.tempo.session({
|
|
726
|
+
currency: spec.currency ?? defaultCurrency,
|
|
727
|
+
recipient: await resolveRecipient(spec.recipient),
|
|
728
|
+
escrowContract: spec.escrowContract,
|
|
729
|
+
store: spec.store,
|
|
730
|
+
testnet: spec.testnet ?? false,
|
|
731
|
+
...spec.chains ? { chains: spec.chains } : {}
|
|
732
|
+
});
|
|
733
|
+
}
|
|
734
|
+
async function registerSolana(spec) {
|
|
735
|
+
const solanaMpp = await dynamicImport2("@solana/mpp/server");
|
|
736
|
+
if (!solanaMpp?.charge) {
|
|
737
|
+
throw new Error(
|
|
738
|
+
"@solana/mpp not installed \u2014 `npm install @solana/mpp @solana/kit` to use the solana rail."
|
|
739
|
+
);
|
|
576
740
|
}
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
741
|
+
const network = solanaNetworkFromCAIP2(spec.network);
|
|
742
|
+
const defaultMint = network === "mainnet-beta" ? USDC.solana.mainnet.mint : USDC.solana.devnet.mint;
|
|
743
|
+
const defaultDecimals = network === "mainnet-beta" ? USDC.solana.mainnet.decimals : USDC.solana.devnet.decimals;
|
|
744
|
+
if (typeof spec.recipient !== "string") {
|
|
745
|
+
throw new TypeError(
|
|
746
|
+
"createMppxServer: SolanaMppRailSpec requires a string recipient (per-order factories not supported here)."
|
|
747
|
+
);
|
|
580
748
|
}
|
|
581
|
-
|
|
749
|
+
const baseMethod = solanaMpp.charge({
|
|
750
|
+
recipient: spec.recipient,
|
|
751
|
+
currency: spec.token ?? defaultMint,
|
|
752
|
+
decimals: spec.decimals ?? defaultDecimals,
|
|
753
|
+
network,
|
|
754
|
+
...spec.rpcUrl ? { rpcUrl: spec.rpcUrl } : {},
|
|
755
|
+
...spec.signer ? { signer: spec.signer } : {},
|
|
756
|
+
...spec.tokenProgram ? { tokenProgram: spec.tokenProgram } : {}
|
|
757
|
+
});
|
|
758
|
+
return wrapSolanaChargeWithFinalizedBlockhash(baseMethod, spec.rpcUrl ?? solanaDefaultRpcUrl(network));
|
|
759
|
+
}
|
|
760
|
+
async function registerStripe(spec) {
|
|
761
|
+
if (!spec.profileId || !spec.secretKey) {
|
|
762
|
+
throw new Error(
|
|
763
|
+
"createMppxServer: StripeRailSpec requires both profileId and secretKey."
|
|
764
|
+
);
|
|
765
|
+
}
|
|
766
|
+
return createMppxStripe({
|
|
767
|
+
profileId: spec.profileId,
|
|
768
|
+
secretKey: spec.secretKey,
|
|
769
|
+
paymentMethodTypes: spec.paymentMethodTypes
|
|
770
|
+
});
|
|
582
771
|
}
|
|
583
772
|
async function dynamicImport2(moduleName) {
|
|
584
773
|
try {
|
|
@@ -620,6 +809,29 @@ function wrapSolanaChargeWithFinalizedBlockhash(baseMethod, rpcUrl) {
|
|
|
620
809
|
}
|
|
621
810
|
|
|
622
811
|
// src/payment/dispatch.ts
|
|
812
|
+
function detectRailFromHeaders(headers) {
|
|
813
|
+
const get = (name) => {
|
|
814
|
+
if (headers instanceof Headers) {
|
|
815
|
+
return headers.get(name) ?? "";
|
|
816
|
+
}
|
|
817
|
+
const lower = name.toLowerCase();
|
|
818
|
+
for (const [k, v] of Object.entries(headers)) {
|
|
819
|
+
if (k.toLowerCase() === lower) {
|
|
820
|
+
if (v === void 0 || v === null) return "";
|
|
821
|
+
return Array.isArray(v) ? v[0] ?? "" : v;
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
return "";
|
|
825
|
+
};
|
|
826
|
+
const auth = get("authorization");
|
|
827
|
+
if (auth.toLowerCase().startsWith("payment ")) {
|
|
828
|
+
return "mpp";
|
|
829
|
+
}
|
|
830
|
+
if (get("payment-signature") || get("x-payment")) {
|
|
831
|
+
return "x402";
|
|
832
|
+
}
|
|
833
|
+
return null;
|
|
834
|
+
}
|
|
623
835
|
async function dispatchSettlementByNetwork(payload, handlers) {
|
|
624
836
|
const network = payload.accepted.network;
|
|
625
837
|
if (network.startsWith("eip155:")) {
|
|
@@ -652,37 +864,45 @@ function aliasAmountFields(accepts) {
|
|
|
652
864
|
return e;
|
|
653
865
|
});
|
|
654
866
|
}
|
|
655
|
-
function paymentRequiredHeader(
|
|
656
|
-
|
|
867
|
+
function paymentRequiredHeader({
|
|
868
|
+
x402Version,
|
|
869
|
+
accepts,
|
|
870
|
+
resource
|
|
871
|
+
}) {
|
|
872
|
+
return Buffer.from(JSON.stringify({ x402Version, accepts, ...resource ? { resource } : {} })).toString("base64");
|
|
657
873
|
}
|
|
658
874
|
|
|
659
875
|
// src/payment/headers.ts
|
|
660
|
-
function buildPaymentHeaders(
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
876
|
+
function buildPaymentHeaders({
|
|
877
|
+
rails: rails2,
|
|
878
|
+
orderId,
|
|
879
|
+
realm,
|
|
880
|
+
x402
|
|
881
|
+
}) {
|
|
882
|
+
const directives = rails2.map(
|
|
883
|
+
(rail) => buildPaymentDirective({
|
|
884
|
+
id: `${orderId}-${rail.rail}`,
|
|
885
|
+
realm,
|
|
665
886
|
rail: rail.rail,
|
|
666
|
-
amountUsd: rail.amountUsd
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
});
|
|
887
|
+
amountUsd: rail.amountUsd,
|
|
888
|
+
...rail.recipient !== void 0 ? { recipient: rail.recipient } : {},
|
|
889
|
+
...rail.networkId !== void 0 ? { networkId: rail.networkId } : {},
|
|
890
|
+
...rail.chainId !== void 0 ? { chainId: rail.chainId } : {},
|
|
891
|
+
...rail.currency !== void 0 ? { currency: rail.currency } : {},
|
|
892
|
+
...rail.decimals !== void 0 ? { decimals: rail.decimals } : {},
|
|
893
|
+
...rail.method !== void 0 ? { method: rail.method } : {},
|
|
894
|
+
...rail.intent !== void 0 ? { intent: rail.intent } : {},
|
|
895
|
+
...rail.expires !== void 0 ? { expires: rail.expires } : {}
|
|
896
|
+
})
|
|
897
|
+
);
|
|
678
898
|
const result = {
|
|
679
899
|
"www-authenticate": wwwAuthenticateHeader(directives)
|
|
680
900
|
};
|
|
681
|
-
if (
|
|
901
|
+
if (x402) {
|
|
682
902
|
result["PAYMENT-REQUIRED"] = paymentRequiredHeader({
|
|
683
|
-
x402Version:
|
|
684
|
-
accepts:
|
|
685
|
-
...
|
|
903
|
+
x402Version: x402.version ?? 2,
|
|
904
|
+
accepts: x402.accepts,
|
|
905
|
+
...x402.resource ? { resource: x402.resource } : {}
|
|
686
906
|
});
|
|
687
907
|
}
|
|
688
908
|
return result;
|
|
@@ -690,15 +910,20 @@ function buildPaymentHeaders(input) {
|
|
|
690
910
|
|
|
691
911
|
// src/payment/idempotency.ts
|
|
692
912
|
var SERVER_IDEMPOTENCY_KEY_MAX = 200;
|
|
693
|
-
function buildIdempotencyKey(
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
913
|
+
function buildIdempotencyKey({
|
|
914
|
+
paymentIntentId,
|
|
915
|
+
orderId,
|
|
916
|
+
amountCents,
|
|
917
|
+
prefix
|
|
918
|
+
}) {
|
|
919
|
+
const prefixPart = prefix ? `${prefix}-` : "";
|
|
920
|
+
if (paymentIntentId) {
|
|
921
|
+
const key = `${prefixPart}${paymentIntentId}`;
|
|
697
922
|
return clampKey(key);
|
|
698
923
|
}
|
|
699
|
-
if (
|
|
700
|
-
const amountSuffix =
|
|
701
|
-
const key = `${
|
|
924
|
+
if (orderId) {
|
|
925
|
+
const amountSuffix = amountCents !== void 0 ? `-${amountCents}` : "";
|
|
926
|
+
const key = `${prefixPart}pi-${orderId}${amountSuffix}`;
|
|
702
927
|
return clampKey(key);
|
|
703
928
|
}
|
|
704
929
|
return void 0;
|
|
@@ -784,17 +1009,218 @@ async function extractPaymentSigner(request, x402PaymentHeader) {
|
|
|
784
1009
|
}
|
|
785
1010
|
return null;
|
|
786
1011
|
}
|
|
1012
|
+
async function extractPaymentSignerFromAuth(authHeader, x402PaymentHeader) {
|
|
1013
|
+
const request = new Request("http://internal.gate/", {
|
|
1014
|
+
headers: authHeader ? { authorization: authHeader } : {}
|
|
1015
|
+
});
|
|
1016
|
+
return extractPaymentSigner(request, x402PaymentHeader);
|
|
1017
|
+
}
|
|
787
1018
|
function readX402PaymentHeader(request) {
|
|
788
1019
|
return request.headers.get("payment-signature") ?? request.headers.get("x-payment") ?? void 0;
|
|
789
1020
|
}
|
|
1021
|
+
function lowerHeaders(headers) {
|
|
1022
|
+
const out = {};
|
|
1023
|
+
for (const [k, v] of Object.entries(headers)) out[k.toLowerCase()] = v;
|
|
1024
|
+
return out;
|
|
1025
|
+
}
|
|
1026
|
+
async function extractSignerForPrecheck(headers) {
|
|
1027
|
+
const lower = lowerHeaders(headers);
|
|
1028
|
+
const x402 = lower["payment-signature"] ?? lower["x-payment"];
|
|
1029
|
+
if (x402) {
|
|
1030
|
+
const signer = await extractPaymentSignerFromAuth(void 0, x402);
|
|
1031
|
+
if (signer !== null) return signer;
|
|
1032
|
+
}
|
|
1033
|
+
const authorization = lower["authorization"];
|
|
1034
|
+
if (authorization && authorization.toLowerCase().startsWith("payment ")) {
|
|
1035
|
+
return await extractPaymentSignerFromAuth(authorization);
|
|
1036
|
+
}
|
|
1037
|
+
return null;
|
|
1038
|
+
}
|
|
790
1039
|
|
|
791
1040
|
// src/payment/settlement_override.ts
|
|
792
1041
|
var SETTLEMENT_OVERRIDES_HEADER = "Settlement-Overrides";
|
|
793
1042
|
function settlementOverrideHeader(overrides) {
|
|
794
1043
|
return { name: SETTLEMENT_OVERRIDES_HEADER, value: JSON.stringify(overrides) };
|
|
795
1044
|
}
|
|
1045
|
+
|
|
1046
|
+
// src/payment/amounts.ts
|
|
1047
|
+
function usdToAtomic(usd, opts) {
|
|
1048
|
+
const { decimals } = opts;
|
|
1049
|
+
if (!Number.isInteger(decimals) || decimals < 0) {
|
|
1050
|
+
throw new RangeError(`decimals must be a non-negative integer, got ${decimals}`);
|
|
1051
|
+
}
|
|
1052
|
+
if (typeof usd === "number") {
|
|
1053
|
+
if (!Number.isFinite(usd)) {
|
|
1054
|
+
throw new RangeError(`usd must be finite, got ${usd}`);
|
|
1055
|
+
}
|
|
1056
|
+
if (usd < 0) {
|
|
1057
|
+
throw new RangeError(`usd must be non-negative, got ${usd}`);
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
const s = (typeof usd === "number" ? usd.toString() : usd).trim();
|
|
1061
|
+
if (s.startsWith("-")) {
|
|
1062
|
+
throw new RangeError(`usd must be non-negative, got ${s}`);
|
|
1063
|
+
}
|
|
1064
|
+
if (s === "NaN" || s === "Infinity") {
|
|
1065
|
+
throw new RangeError(`usd must be finite, got ${s}`);
|
|
1066
|
+
}
|
|
1067
|
+
const match = /^(\d*)(?:\.(\d*))?$/.exec(s);
|
|
1068
|
+
if (!match || match[1] === "" && (match[2] === void 0 || match[2] === "")) {
|
|
1069
|
+
throw new SyntaxError(`invalid usd value: ${JSON.stringify(usd)}`);
|
|
1070
|
+
}
|
|
1071
|
+
const intPart = match[1] || "0";
|
|
1072
|
+
const fracPart = match[2] ?? "";
|
|
1073
|
+
if (fracPart.length <= decimals) {
|
|
1074
|
+
return BigInt(intPart + fracPart.padEnd(decimals, "0"));
|
|
1075
|
+
}
|
|
1076
|
+
const kept = fracPart.slice(0, decimals);
|
|
1077
|
+
const roundDigit = fracPart[decimals];
|
|
1078
|
+
let result = BigInt(intPart + kept);
|
|
1079
|
+
if (roundDigit >= "5") {
|
|
1080
|
+
result += 1n;
|
|
1081
|
+
}
|
|
1082
|
+
return result;
|
|
1083
|
+
}
|
|
1084
|
+
function formatUsdCents(cents) {
|
|
1085
|
+
return (cents / 100).toFixed(2);
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
// src/payment/zero-settle.ts
|
|
1089
|
+
var EVM_RE = /^0x[0-9a-fA-F]{40}$/;
|
|
1090
|
+
var SOLANA_BASE58_RE = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
|
|
1091
|
+
var NULL_RESULT = {
|
|
1092
|
+
signerAddress: null,
|
|
1093
|
+
signerNetwork: null,
|
|
1094
|
+
txHash: null
|
|
1095
|
+
};
|
|
1096
|
+
function zeroAmountCarveOut({
|
|
1097
|
+
rail,
|
|
1098
|
+
payload,
|
|
1099
|
+
authorizationHeader
|
|
1100
|
+
}) {
|
|
1101
|
+
if (rail === "x402-base") {
|
|
1102
|
+
return x402SignerFromPayload(payload);
|
|
1103
|
+
}
|
|
1104
|
+
if (rail === "tempo" || rail === "solana") {
|
|
1105
|
+
return mppSignerFromAuth(authorizationHeader);
|
|
1106
|
+
}
|
|
1107
|
+
return NULL_RESULT;
|
|
1108
|
+
}
|
|
1109
|
+
function x402SignerFromPayload(payload) {
|
|
1110
|
+
if (!payload || typeof payload !== "object") return NULL_RESULT;
|
|
1111
|
+
const inner = payload.payload;
|
|
1112
|
+
if (!inner || typeof inner !== "object") return NULL_RESULT;
|
|
1113
|
+
const authorization = inner.authorization;
|
|
1114
|
+
if (!authorization || typeof authorization !== "object") return NULL_RESULT;
|
|
1115
|
+
const fromAddr = authorization.from;
|
|
1116
|
+
if (typeof fromAddr !== "string" || !EVM_RE.test(fromAddr)) return NULL_RESULT;
|
|
1117
|
+
return {
|
|
1118
|
+
signerAddress: fromAddr.toLowerCase(),
|
|
1119
|
+
signerNetwork: "evm",
|
|
1120
|
+
txHash: null
|
|
1121
|
+
};
|
|
1122
|
+
}
|
|
1123
|
+
function mppSignerFromAuth(authorizationHeader) {
|
|
1124
|
+
if (typeof authorizationHeader !== "string") return NULL_RESULT;
|
|
1125
|
+
if (!authorizationHeader.toLowerCase().startsWith("payment ")) return NULL_RESULT;
|
|
1126
|
+
const token = authorizationHeader.slice("payment ".length).trim();
|
|
1127
|
+
if (!token) return NULL_RESULT;
|
|
1128
|
+
let credential;
|
|
1129
|
+
try {
|
|
1130
|
+
credential = JSON.parse(atob(token));
|
|
1131
|
+
} catch {
|
|
1132
|
+
return NULL_RESULT;
|
|
1133
|
+
}
|
|
1134
|
+
if (!credential || typeof credential !== "object") return NULL_RESULT;
|
|
1135
|
+
let source = credential.source;
|
|
1136
|
+
if (typeof source !== "string") {
|
|
1137
|
+
const challenge = credential.challenge;
|
|
1138
|
+
if (challenge && typeof challenge === "object") {
|
|
1139
|
+
source = challenge.source;
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
if (typeof source !== "string") return NULL_RESULT;
|
|
1143
|
+
const parts = source.split(":");
|
|
1144
|
+
if (parts.length < 4 || parts[0] !== "did" || parts[1] !== "pkh") return NULL_RESULT;
|
|
1145
|
+
const family = parts[2];
|
|
1146
|
+
const addr = parts[parts.length - 1] ?? "";
|
|
1147
|
+
if (family === "eip155" && EVM_RE.test(addr)) {
|
|
1148
|
+
return { signerAddress: addr.toLowerCase(), signerNetwork: "evm", txHash: null };
|
|
1149
|
+
}
|
|
1150
|
+
if (family === "solana" && SOLANA_BASE58_RE.test(addr)) {
|
|
1151
|
+
return { signerAddress: addr, signerNetwork: "solana", txHash: null };
|
|
1152
|
+
}
|
|
1153
|
+
return NULL_RESULT;
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
// src/payment/lazy.ts
|
|
1157
|
+
function x402RailName(spec) {
|
|
1158
|
+
const network = spec.network ?? "eip155:8453";
|
|
1159
|
+
if (network === "eip155:8453") return "x402-base-mainnet";
|
|
1160
|
+
if (network === "eip155:84532") return "x402-base-sepolia";
|
|
1161
|
+
throw new Error(
|
|
1162
|
+
`lazyX402Server: unsupported X402BaseRailSpec.network=${JSON.stringify(network)}`
|
|
1163
|
+
);
|
|
1164
|
+
}
|
|
1165
|
+
function lazyX402Server(opts) {
|
|
1166
|
+
const { spec, cdpApiKeyId, cdpApiKeySecret } = opts;
|
|
1167
|
+
const railName = x402RailName(spec);
|
|
1168
|
+
const useCdp = Boolean(cdpApiKeyId && cdpApiKeySecret);
|
|
1169
|
+
const facilitator = useCdp ? "coinbase" : "http";
|
|
1170
|
+
let cached;
|
|
1171
|
+
let pending;
|
|
1172
|
+
return async () => {
|
|
1173
|
+
if (cached !== void 0) return cached;
|
|
1174
|
+
if (pending !== void 0) return pending;
|
|
1175
|
+
pending = (async () => {
|
|
1176
|
+
const server = await createX402Server({ facilitator, rails: [railName] });
|
|
1177
|
+
cached = server;
|
|
1178
|
+
pending = void 0;
|
|
1179
|
+
return server;
|
|
1180
|
+
})();
|
|
1181
|
+
return pending;
|
|
1182
|
+
};
|
|
1183
|
+
}
|
|
1184
|
+
function lazyMppxServer(opts) {
|
|
1185
|
+
const { rails: rails2, secretKey } = opts;
|
|
1186
|
+
let cached;
|
|
1187
|
+
let pending;
|
|
1188
|
+
return async () => {
|
|
1189
|
+
if (cached !== void 0) return cached;
|
|
1190
|
+
if (pending !== void 0) return pending;
|
|
1191
|
+
pending = (async () => {
|
|
1192
|
+
const server = await createMppxServer({ secretKey, rails: rails2 });
|
|
1193
|
+
cached = server;
|
|
1194
|
+
pending = void 0;
|
|
1195
|
+
return server;
|
|
1196
|
+
})();
|
|
1197
|
+
return pending;
|
|
1198
|
+
};
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
// src/payment/solana.ts
|
|
1202
|
+
async function loadSolanaFeePayer(opts) {
|
|
1203
|
+
const raw = opts.privateKey;
|
|
1204
|
+
if (!raw) return void 0;
|
|
1205
|
+
const moduleName = "@solana/kit";
|
|
1206
|
+
const kit = await import(moduleName).catch(() => null);
|
|
1207
|
+
if (!kit?.createKeyPairSignerFromPrivateKeyBytes || !kit.getBase58Codec) {
|
|
1208
|
+
throw new Error(
|
|
1209
|
+
"@solana/kit not installed \u2014 `npm install @solana/kit` for loadSolanaFeePayer."
|
|
1210
|
+
);
|
|
1211
|
+
}
|
|
1212
|
+
let bytes;
|
|
1213
|
+
if (/^[0-9a-fA-F]{128}$/.test(raw)) {
|
|
1214
|
+
bytes = new Uint8Array(raw.match(/.{2}/g).map((h) => parseInt(h, 16))).slice(0, 32);
|
|
1215
|
+
} else {
|
|
1216
|
+
const decoded = new Uint8Array(kit.getBase58Codec().encode(raw));
|
|
1217
|
+
bytes = decoded.length === 64 ? decoded.slice(0, 32) : decoded;
|
|
1218
|
+
}
|
|
1219
|
+
return kit.createKeyPairSignerFromPrivateKeyBytes(bytes);
|
|
1220
|
+
}
|
|
796
1221
|
// Annotate the CommonJS export names for ESM import in node:
|
|
797
1222
|
0 && (module.exports = {
|
|
1223
|
+
RAIL_SPEC_DEFAULTS,
|
|
798
1224
|
SETTLEMENT_OVERRIDES_HEADER,
|
|
799
1225
|
USDC,
|
|
800
1226
|
X402_SUPPORTED_BASE_NETWORKS,
|
|
@@ -804,11 +1230,19 @@ function settlementOverrideHeader(overrides) {
|
|
|
804
1230
|
buildPaymentHeaders,
|
|
805
1231
|
buildPaymentRequestBlob,
|
|
806
1232
|
buildX402AcceptsFor402,
|
|
1233
|
+
classifyOrchestrationError,
|
|
807
1234
|
classifyX402SettleResult,
|
|
808
1235
|
createMppxServer,
|
|
809
1236
|
createX402Server,
|
|
1237
|
+
detectRailFromHeaders,
|
|
810
1238
|
dispatchSettlementByNetwork,
|
|
811
1239
|
extractPaymentSigner,
|
|
1240
|
+
extractPaymentSignerFromAuth,
|
|
1241
|
+
extractSignerForPrecheck,
|
|
1242
|
+
formatUsdCents,
|
|
1243
|
+
lazyMppxServer,
|
|
1244
|
+
lazyX402Server,
|
|
1245
|
+
loadSolanaFeePayer,
|
|
812
1246
|
lookupRail,
|
|
813
1247
|
networkFamily,
|
|
814
1248
|
networks,
|
|
@@ -818,10 +1252,13 @@ function settlementOverrideHeader(overrides) {
|
|
|
818
1252
|
rails,
|
|
819
1253
|
readX402PaymentHeader,
|
|
820
1254
|
registerX402SchemesV1V2,
|
|
1255
|
+
resolveRecipient,
|
|
821
1256
|
settlementOverrideHeader,
|
|
1257
|
+
usdToAtomic,
|
|
822
1258
|
validateX402NetworkConfig,
|
|
823
1259
|
verifyX402Request,
|
|
824
1260
|
wrapSolanaChargeWithFinalizedBlockhash,
|
|
825
|
-
wwwAuthenticateHeader
|
|
1261
|
+
wwwAuthenticateHeader,
|
|
1262
|
+
zeroAmountCarveOut
|
|
826
1263
|
});
|
|
827
1264
|
//# sourceMappingURL=index.js.map
|