@agent-score/commerce 1.8.0 → 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-BMt2y4Or.d.mts → _response-BFYN3b6i.d.mts} +19 -22
- package/dist/{_response-DyJ3mWI3.d.ts → _response-_iPD5AIj.d.ts} +19 -22
- 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 +257 -266
- package/dist/payment/index.d.ts +257 -266
- 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 +56 -67
- package/dist/stripe-multichain/index.d.ts +56 -67
- 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 +13 -9
package/dist/payment/index.mjs
CHANGED
|
@@ -115,49 +115,116 @@ function lookupRail(name) {
|
|
|
115
115
|
}
|
|
116
116
|
|
|
117
117
|
// src/payment/directive.ts
|
|
118
|
-
function buildPaymentRequestBlob(
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
118
|
+
function buildPaymentRequestBlob({
|
|
119
|
+
rail,
|
|
120
|
+
amountUsd,
|
|
121
|
+
currency,
|
|
122
|
+
decimals,
|
|
123
|
+
recipient,
|
|
124
|
+
chainId,
|
|
125
|
+
networkId
|
|
126
|
+
}) {
|
|
127
|
+
const railDef = rail ? lookupRail(rail) : void 0;
|
|
128
|
+
const decimalsResolved = decimals ?? railDef?.decimals ?? 6;
|
|
129
|
+
const currencyResolved = currency ?? railDef?.currency ?? "usd";
|
|
130
|
+
const chainIdResolved = chainId ?? railDef?.chainId;
|
|
131
|
+
const amountNum = typeof amountUsd === "string" ? Number(amountUsd) : amountUsd;
|
|
132
|
+
const amountRaw = BigInt(Math.round(amountNum * 10 ** decimalsResolved)).toString();
|
|
133
|
+
const blob = { amount: amountRaw, currency: currencyResolved, decimals: decimalsResolved };
|
|
134
|
+
if (recipient) blob.recipient = recipient;
|
|
127
135
|
const methodDetails = {};
|
|
128
|
-
if (
|
|
129
|
-
if (
|
|
136
|
+
if (chainIdResolved !== void 0) methodDetails.chainId = chainIdResolved;
|
|
137
|
+
if (networkId) methodDetails.networkId = networkId;
|
|
130
138
|
if (Object.keys(methodDetails).length > 0) blob.methodDetails = methodDetails;
|
|
131
139
|
return Buffer.from(JSON.stringify(blob)).toString("base64url");
|
|
132
140
|
}
|
|
133
|
-
function paymentDirective(
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
141
|
+
function paymentDirective({
|
|
142
|
+
rail,
|
|
143
|
+
id,
|
|
144
|
+
realm,
|
|
145
|
+
method,
|
|
146
|
+
intent,
|
|
147
|
+
expires,
|
|
148
|
+
request
|
|
149
|
+
}) {
|
|
150
|
+
const railDef = rail ? lookupRail(rail) : void 0;
|
|
151
|
+
const methodResolved = method ?? railDef?.method ?? "unknown";
|
|
152
|
+
const intentResolved = intent ?? "charge";
|
|
153
|
+
const expiresResolved = expires ?? new Date(Date.now() + 5 * 60 * 1e3).toISOString();
|
|
154
|
+
return `Payment id="${id}", realm="${realm}", method="${methodResolved}", intent="${intentResolved}", expires="${expiresResolved}", request="${request}"`;
|
|
139
155
|
}
|
|
140
|
-
function buildPaymentDirective(
|
|
156
|
+
function buildPaymentDirective({
|
|
157
|
+
rail,
|
|
158
|
+
id,
|
|
159
|
+
realm,
|
|
160
|
+
amountUsd,
|
|
161
|
+
currency,
|
|
162
|
+
decimals,
|
|
163
|
+
recipient,
|
|
164
|
+
chainId,
|
|
165
|
+
networkId,
|
|
166
|
+
method,
|
|
167
|
+
intent,
|
|
168
|
+
expires
|
|
169
|
+
}) {
|
|
141
170
|
const request = buildPaymentRequestBlob({
|
|
142
|
-
rail
|
|
143
|
-
amountUsd
|
|
144
|
-
currency
|
|
145
|
-
decimals
|
|
146
|
-
recipient
|
|
147
|
-
chainId
|
|
148
|
-
networkId
|
|
171
|
+
rail,
|
|
172
|
+
amountUsd,
|
|
173
|
+
currency,
|
|
174
|
+
decimals,
|
|
175
|
+
recipient,
|
|
176
|
+
chainId,
|
|
177
|
+
networkId
|
|
149
178
|
});
|
|
150
179
|
return paymentDirective({
|
|
151
|
-
rail
|
|
152
|
-
id
|
|
153
|
-
realm
|
|
154
|
-
method
|
|
155
|
-
intent
|
|
156
|
-
expires
|
|
180
|
+
rail,
|
|
181
|
+
id,
|
|
182
|
+
realm,
|
|
183
|
+
method,
|
|
184
|
+
intent,
|
|
185
|
+
expires,
|
|
157
186
|
request
|
|
158
187
|
});
|
|
159
188
|
}
|
|
160
189
|
|
|
190
|
+
// src/payment/rail_spec.ts
|
|
191
|
+
async function resolveRecipient(r) {
|
|
192
|
+
if (typeof r === "string") return r;
|
|
193
|
+
return Promise.resolve(r());
|
|
194
|
+
}
|
|
195
|
+
var RAIL_SPEC_DEFAULTS = {
|
|
196
|
+
tempo: {
|
|
197
|
+
network: "tempo-mainnet",
|
|
198
|
+
chainId: 4217,
|
|
199
|
+
token: USDC.tempo.mainnet.address,
|
|
200
|
+
symbol: "USDC.e",
|
|
201
|
+
decimals: 6,
|
|
202
|
+
testnet: false,
|
|
203
|
+
recommend: "both"
|
|
204
|
+
},
|
|
205
|
+
x402Base: {
|
|
206
|
+
network: "eip155:8453",
|
|
207
|
+
chainId: 8453,
|
|
208
|
+
token: USDC.base.mainnet.address,
|
|
209
|
+
symbol: "USDC",
|
|
210
|
+
decimals: 6,
|
|
211
|
+
mode: "exact"
|
|
212
|
+
},
|
|
213
|
+
solanaMpp: {
|
|
214
|
+
network: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
|
|
215
|
+
token: USDC.solana.mainnet.mint,
|
|
216
|
+
symbol: "USDC",
|
|
217
|
+
decimals: 6
|
|
218
|
+
},
|
|
219
|
+
stripe: {
|
|
220
|
+
rails: ["card", "link", "shared_payment_token"]
|
|
221
|
+
},
|
|
222
|
+
tempoSession: {
|
|
223
|
+
currency: USDC.tempo.mainnet.address,
|
|
224
|
+
testnet: false
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
|
|
161
228
|
// src/payment/x402.ts
|
|
162
229
|
function registerX402SchemesV1V2(server, network, scheme) {
|
|
163
230
|
server.register(network, scheme);
|
|
@@ -175,7 +242,8 @@ async function createX402Server(opts = {}) {
|
|
|
175
242
|
);
|
|
176
243
|
}
|
|
177
244
|
let facilitator;
|
|
178
|
-
|
|
245
|
+
const facilitatorChoice = opts.facilitator ?? (process.env.CDP_API_KEY_ID && process.env.CDP_API_KEY_SECRET ? "coinbase" : "http");
|
|
246
|
+
if (facilitatorChoice === "coinbase") {
|
|
179
247
|
const cb = await dynamicImport("@coinbase/x402");
|
|
180
248
|
if (!cb?.facilitator) {
|
|
181
249
|
throw new Error(
|
|
@@ -183,10 +251,10 @@ async function createX402Server(opts = {}) {
|
|
|
183
251
|
);
|
|
184
252
|
}
|
|
185
253
|
facilitator = new x402Core.HTTPFacilitatorClient(cb.facilitator);
|
|
186
|
-
} else if (
|
|
254
|
+
} else if (facilitatorChoice === "http") {
|
|
187
255
|
facilitator = new x402Core.HTTPFacilitatorClient();
|
|
188
256
|
} else {
|
|
189
|
-
facilitator =
|
|
257
|
+
facilitator = facilitatorChoice;
|
|
190
258
|
}
|
|
191
259
|
const server = new x402Core.x402ResourceServer(facilitator);
|
|
192
260
|
let evmExactModule = null;
|
|
@@ -296,44 +364,95 @@ function classifyX402SettleResult(result) {
|
|
|
296
364
|
};
|
|
297
365
|
}
|
|
298
366
|
}
|
|
299
|
-
|
|
300
|
-
|
|
367
|
+
function classifyOrchestrationError(err) {
|
|
368
|
+
let msg;
|
|
369
|
+
if (err instanceof Error) {
|
|
370
|
+
msg = err.message;
|
|
371
|
+
} else if (typeof err === "string") {
|
|
372
|
+
msg = err;
|
|
373
|
+
} else {
|
|
374
|
+
return null;
|
|
375
|
+
}
|
|
376
|
+
const msgLower = msg.toLowerCase();
|
|
377
|
+
if (msgLower.includes("x402version") || msgLower.includes("invalid payment") || msgLower.includes("unsupported x402")) {
|
|
378
|
+
return {
|
|
379
|
+
status: 400,
|
|
380
|
+
code: "payment_proof_invalid",
|
|
381
|
+
message: "Payment credential is malformed or uses an unsupported version",
|
|
382
|
+
nextSteps: {
|
|
383
|
+
action: "regenerate_payment_credential",
|
|
384
|
+
user_message: "The payment credential is malformed or uses an unsupported version. Regenerate from a fresh 402 challenge and re-sign."
|
|
385
|
+
}
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
if (msgLower.includes("stripe") || msgLower.includes("facilitator") || msgLower.includes("cdp")) {
|
|
389
|
+
return {
|
|
390
|
+
status: 503,
|
|
391
|
+
code: "payment_provider_unavailable",
|
|
392
|
+
message: "Payment provider returned an error",
|
|
393
|
+
nextSteps: {
|
|
394
|
+
action: "retry_or_swap_method",
|
|
395
|
+
retry_after_seconds: 10,
|
|
396
|
+
user_message: "Transient payment-provider error. Retry in a few seconds, or pick a different rail from the 402 challenge."
|
|
397
|
+
}
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
return null;
|
|
401
|
+
}
|
|
402
|
+
async function processX402Settle({
|
|
403
|
+
x402Server,
|
|
404
|
+
payload,
|
|
405
|
+
resourceConfig,
|
|
406
|
+
resourceMeta,
|
|
407
|
+
extension,
|
|
408
|
+
transportContext
|
|
409
|
+
}) {
|
|
410
|
+
const server = x402Server;
|
|
301
411
|
let builtRequirements;
|
|
302
412
|
try {
|
|
303
|
-
builtRequirements = await server.buildPaymentRequirements(
|
|
413
|
+
builtRequirements = await server.buildPaymentRequirements(resourceConfig);
|
|
304
414
|
} catch (err) {
|
|
415
|
+
console.warn("[x402_settle] build_requirements failed:", err instanceof Error ? err.message : err);
|
|
305
416
|
return { success: false, phase: "facilitator_error", step: "build_requirements", error: err };
|
|
306
417
|
}
|
|
307
418
|
const matchedRequirement = builtRequirements[0];
|
|
308
419
|
if (!matchedRequirement) {
|
|
309
420
|
return { success: false, phase: "no_requirements", reason: "x402Server.buildPaymentRequirements returned empty" };
|
|
310
421
|
}
|
|
311
|
-
const
|
|
312
|
-
const path = new URL(
|
|
422
|
+
const resolvedTransportContext = transportContext ?? (() => {
|
|
423
|
+
const path = new URL(resourceMeta.url).pathname;
|
|
313
424
|
return { method: "POST", adapter: { getPath: () => path }, routePattern: path };
|
|
314
425
|
})();
|
|
315
426
|
let enrichedExt;
|
|
316
427
|
try {
|
|
317
|
-
enrichedExt =
|
|
428
|
+
enrichedExt = extension !== void 0 ? server.enrichExtensions(extension, resolvedTransportContext) : void 0;
|
|
318
429
|
} catch (err) {
|
|
430
|
+
console.warn("[x402_settle] enrich_extensions failed:", err instanceof Error ? err.message : err);
|
|
319
431
|
return { success: false, phase: "facilitator_error", step: "enrich_extensions", error: err };
|
|
320
432
|
}
|
|
321
433
|
let verifyResult;
|
|
322
434
|
try {
|
|
323
|
-
verifyResult = await server.
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
435
|
+
verifyResult = await server.verifyPayment(
|
|
436
|
+
payload,
|
|
437
|
+
matchedRequirement,
|
|
438
|
+
enrichedExt,
|
|
439
|
+
resolvedTransportContext
|
|
328
440
|
);
|
|
329
441
|
} catch (err) {
|
|
330
|
-
|
|
442
|
+
console.warn("[x402_settle] verify_payment failed:", err instanceof Error ? err.message : err);
|
|
443
|
+
return { success: false, phase: "facilitator_error", step: "verify_payment", error: err };
|
|
331
444
|
}
|
|
332
|
-
|
|
445
|
+
const verifyOk = verifyResult.isValid === true || verifyResult.success === true;
|
|
446
|
+
if (!verifyOk) {
|
|
333
447
|
return { success: false, phase: "verify_failed", verifyResult };
|
|
334
448
|
}
|
|
335
449
|
try {
|
|
336
|
-
const settleResult = await server.settlePayment(
|
|
450
|
+
const settleResult = await server.settlePayment(
|
|
451
|
+
payload,
|
|
452
|
+
matchedRequirement,
|
|
453
|
+
enrichedExt,
|
|
454
|
+
resolvedTransportContext
|
|
455
|
+
);
|
|
337
456
|
const paymentResponseHeader = settleResult ? Buffer.from(JSON.stringify(settleResult)).toString("base64") : void 0;
|
|
338
457
|
return {
|
|
339
458
|
success: true,
|
|
@@ -352,10 +471,10 @@ var X402_SUPPORTED_BASE_NETWORKS = /* @__PURE__ */ new Set([
|
|
|
352
471
|
networks.base.mainnet.caip2,
|
|
353
472
|
networks.base.sepolia.caip2
|
|
354
473
|
]);
|
|
355
|
-
function validateX402NetworkConfig(
|
|
356
|
-
if (!X402_SUPPORTED_BASE_NETWORKS.has(
|
|
474
|
+
function validateX402NetworkConfig({ baseNetwork }) {
|
|
475
|
+
if (!X402_SUPPORTED_BASE_NETWORKS.has(baseNetwork)) {
|
|
357
476
|
throw new Error(
|
|
358
|
-
`X402_BASE_NETWORK=${
|
|
477
|
+
`X402_BASE_NETWORK=${baseNetwork} is not supported. Use one of: ${[...X402_SUPPORTED_BASE_NETWORKS].join(", ")}`
|
|
359
478
|
);
|
|
360
479
|
}
|
|
361
480
|
}
|
|
@@ -371,8 +490,12 @@ function regenerateBody(message, userMessage) {
|
|
|
371
490
|
}
|
|
372
491
|
};
|
|
373
492
|
}
|
|
374
|
-
async function verifyX402Request(
|
|
375
|
-
|
|
493
|
+
async function verifyX402Request({
|
|
494
|
+
request,
|
|
495
|
+
isCachedAddress,
|
|
496
|
+
acceptedNetwork
|
|
497
|
+
}) {
|
|
498
|
+
const headerValue = request.headers.get("payment-signature") ?? request.headers.get("x-payment");
|
|
376
499
|
if (!headerValue) {
|
|
377
500
|
return {
|
|
378
501
|
ok: false,
|
|
@@ -398,13 +521,13 @@ async function verifyX402Request(input) {
|
|
|
398
521
|
}
|
|
399
522
|
const signedNetwork = payload.accepted?.network;
|
|
400
523
|
const signedPayTo = payload.accepted?.payTo;
|
|
401
|
-
if (!signedNetwork || signedNetwork !==
|
|
524
|
+
if (!signedNetwork || signedNetwork !== acceptedNetwork) {
|
|
402
525
|
if (signedNetwork && signedNetwork.toLowerCase().startsWith("solana:")) {
|
|
403
526
|
return {
|
|
404
527
|
ok: false,
|
|
405
528
|
status: 400,
|
|
406
529
|
body: regenerateBody(
|
|
407
|
-
`x402 on ${signedNetwork} is not accepted; Solana payments must use the \`solana/charge\` rail advertised in the 402 challenge. This server accepts x402 on ${
|
|
530
|
+
`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.`,
|
|
408
531
|
"Solana payments are not accepted over x402 at this merchant. Pick the `solana/charge` rail from the 402 challenge and re-sign."
|
|
409
532
|
)
|
|
410
533
|
};
|
|
@@ -413,7 +536,7 @@ async function verifyX402Request(input) {
|
|
|
413
536
|
ok: false,
|
|
414
537
|
status: 400,
|
|
415
538
|
body: regenerateBody(
|
|
416
|
-
`Unsupported x402 network ${signedNetwork ?? "<missing>"}; this server accepts ${
|
|
539
|
+
`Unsupported x402 network ${signedNetwork ?? "<missing>"}; this server accepts ${acceptedNetwork}.`,
|
|
417
540
|
"The credential signed for an unsupported network. Pick the accepted network from the 402 challenge and re-sign."
|
|
418
541
|
)
|
|
419
542
|
};
|
|
@@ -429,7 +552,7 @@ async function verifyX402Request(input) {
|
|
|
429
552
|
)
|
|
430
553
|
};
|
|
431
554
|
}
|
|
432
|
-
if (!await
|
|
555
|
+
if (!await isCachedAddress(signedPayTo)) {
|
|
433
556
|
return {
|
|
434
557
|
ok: false,
|
|
435
558
|
status: 400,
|
|
@@ -443,7 +566,11 @@ async function verifyX402Request(input) {
|
|
|
443
566
|
}
|
|
444
567
|
|
|
445
568
|
// src/stripe-multichain/mppx_stripe.ts
|
|
446
|
-
async function createMppxStripe(
|
|
569
|
+
async function createMppxStripe({
|
|
570
|
+
profileId,
|
|
571
|
+
secretKey,
|
|
572
|
+
paymentMethodTypes
|
|
573
|
+
}) {
|
|
447
574
|
const moduleName = "mppx/server";
|
|
448
575
|
const mppx = await import(moduleName).catch(() => null);
|
|
449
576
|
if (!mppx?.stripe?.charge) {
|
|
@@ -452,80 +579,130 @@ async function createMppxStripe(input) {
|
|
|
452
579
|
);
|
|
453
580
|
}
|
|
454
581
|
return mppx.stripe.charge({
|
|
455
|
-
networkId:
|
|
456
|
-
paymentMethodTypes:
|
|
457
|
-
secretKey
|
|
582
|
+
networkId: profileId,
|
|
583
|
+
paymentMethodTypes: paymentMethodTypes ?? ["card", "link"],
|
|
584
|
+
secretKey
|
|
458
585
|
});
|
|
459
586
|
}
|
|
460
587
|
|
|
461
588
|
// src/payment/mppx_server.ts
|
|
462
|
-
|
|
589
|
+
function isStripeRailSpec(s) {
|
|
590
|
+
return !("recipient" in s);
|
|
591
|
+
}
|
|
592
|
+
function isTempoSessionRailSpec(s) {
|
|
593
|
+
return "escrowContract" in s && "store" in s;
|
|
594
|
+
}
|
|
595
|
+
function isSolanaMppRailSpec(s) {
|
|
596
|
+
if (!("recipient" in s)) return false;
|
|
597
|
+
if ("escrowContract" in s) return false;
|
|
598
|
+
if ("rpcUrl" in s || "tokenProgram" in s) return true;
|
|
599
|
+
return s.network?.startsWith("solana:") ?? false;
|
|
600
|
+
}
|
|
601
|
+
function solanaNetworkFromCAIP2(caip2) {
|
|
602
|
+
if (caip2 === networks.solana.devnet.caip2) return "devnet";
|
|
603
|
+
return "mainnet-beta";
|
|
604
|
+
}
|
|
605
|
+
function solanaDefaultRpcUrl(network) {
|
|
606
|
+
if (network === "mainnet-beta") return "https://api.mainnet-beta.solana.com";
|
|
607
|
+
if (network === "devnet") return "https://api.devnet.solana.com";
|
|
608
|
+
return "http://localhost:8899";
|
|
609
|
+
}
|
|
610
|
+
async function createMppxServer({
|
|
611
|
+
rails: rails2,
|
|
612
|
+
methods: extraMethods,
|
|
613
|
+
secretKey
|
|
614
|
+
}) {
|
|
463
615
|
const mppx = await dynamicImport2("mppx/server");
|
|
464
616
|
if (!mppx?.Mppx?.create) {
|
|
465
617
|
throw new Error("mppx not installed \u2014 `npm install mppx` to use createMppxServer.");
|
|
466
618
|
}
|
|
467
|
-
const methods = [...
|
|
468
|
-
|
|
469
|
-
if (
|
|
470
|
-
|
|
619
|
+
const methods = [...extraMethods ?? []];
|
|
620
|
+
for (const [name, spec] of Object.entries(rails2 ?? {})) {
|
|
621
|
+
if (isStripeRailSpec(spec)) {
|
|
622
|
+
methods.push(await registerStripe(spec));
|
|
623
|
+
continue;
|
|
624
|
+
}
|
|
625
|
+
if (isTempoSessionRailSpec(spec)) {
|
|
626
|
+
methods.push(await registerTempoSession(mppx, spec));
|
|
627
|
+
continue;
|
|
471
628
|
}
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
629
|
+
if (isSolanaMppRailSpec(spec)) {
|
|
630
|
+
methods.push(await registerSolana(spec));
|
|
631
|
+
continue;
|
|
632
|
+
}
|
|
633
|
+
methods.push(registerTempo(mppx, spec, name));
|
|
634
|
+
}
|
|
635
|
+
return mppx.Mppx.create({ methods, secretKey });
|
|
636
|
+
}
|
|
637
|
+
function registerTempo(mppx, spec, _name) {
|
|
638
|
+
if (!mppx.tempo?.charge) {
|
|
639
|
+
throw new Error("mppx.tempo.charge not available \u2014 check installed mppx version.");
|
|
640
|
+
}
|
|
641
|
+
const defaultCurrency = spec.testnet ? USDC.tempo.testnet.address : USDC.tempo.mainnet.address;
|
|
642
|
+
if (typeof spec.recipient !== "string") {
|
|
643
|
+
throw new TypeError(
|
|
644
|
+
"createMppxServer: TempoRailSpec requires a string recipient (per-order factories not supported here)."
|
|
480
645
|
);
|
|
481
646
|
}
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
mppx.tempo.session
|
|
492
|
-
currency: s.currency ?? defaultCurrency,
|
|
493
|
-
recipient: s.recipient,
|
|
494
|
-
escrowContract: s.escrowContract,
|
|
495
|
-
store: s.store,
|
|
496
|
-
testnet: s.testnet ?? false,
|
|
497
|
-
...s.chains ? { chains: s.chains } : {}
|
|
498
|
-
})
|
|
647
|
+
return mppx.tempo.charge({
|
|
648
|
+
currency: spec.token ?? defaultCurrency,
|
|
649
|
+
recipient: spec.recipient,
|
|
650
|
+
testnet: spec.testnet ?? false
|
|
651
|
+
});
|
|
652
|
+
}
|
|
653
|
+
async function registerTempoSession(mppx, spec) {
|
|
654
|
+
if (!mppx.tempo?.session) {
|
|
655
|
+
throw new Error(
|
|
656
|
+
"mppx.tempo.session not available \u2014 your mppx version may not support sessions yet. Upgrade with `npm install mppx@latest`."
|
|
499
657
|
);
|
|
500
658
|
}
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
...s.rpcUrl ? { rpcUrl: s.rpcUrl } : {},
|
|
518
|
-
...s.signer ? { signer: s.signer } : {},
|
|
519
|
-
...s.tokenProgram ? { tokenProgram: s.tokenProgram } : {}
|
|
520
|
-
});
|
|
521
|
-
const rpcUrl = s.rpcUrl ?? (network === "mainnet-beta" ? "https://api.mainnet-beta.solana.com" : network === "devnet" ? "https://api.devnet.solana.com" : "http://localhost:8899");
|
|
522
|
-
methods.push(wrapSolanaChargeWithFinalizedBlockhash(baseMethod, rpcUrl));
|
|
659
|
+
const defaultCurrency = spec.testnet ? USDC.tempo.testnet.address : USDC.tempo.mainnet.address;
|
|
660
|
+
return mppx.tempo.session({
|
|
661
|
+
currency: spec.currency ?? defaultCurrency,
|
|
662
|
+
recipient: await resolveRecipient(spec.recipient),
|
|
663
|
+
escrowContract: spec.escrowContract,
|
|
664
|
+
store: spec.store,
|
|
665
|
+
testnet: spec.testnet ?? false,
|
|
666
|
+
...spec.chains ? { chains: spec.chains } : {}
|
|
667
|
+
});
|
|
668
|
+
}
|
|
669
|
+
async function registerSolana(spec) {
|
|
670
|
+
const solanaMpp = await dynamicImport2("@solana/mpp/server");
|
|
671
|
+
if (!solanaMpp?.charge) {
|
|
672
|
+
throw new Error(
|
|
673
|
+
"@solana/mpp not installed \u2014 `npm install @solana/mpp @solana/kit` to use the solana rail."
|
|
674
|
+
);
|
|
523
675
|
}
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
676
|
+
const network = solanaNetworkFromCAIP2(spec.network);
|
|
677
|
+
const defaultMint = network === "mainnet-beta" ? USDC.solana.mainnet.mint : USDC.solana.devnet.mint;
|
|
678
|
+
const defaultDecimals = network === "mainnet-beta" ? USDC.solana.mainnet.decimals : USDC.solana.devnet.decimals;
|
|
679
|
+
if (typeof spec.recipient !== "string") {
|
|
680
|
+
throw new TypeError(
|
|
681
|
+
"createMppxServer: SolanaMppRailSpec requires a string recipient (per-order factories not supported here)."
|
|
682
|
+
);
|
|
527
683
|
}
|
|
528
|
-
|
|
684
|
+
const baseMethod = solanaMpp.charge({
|
|
685
|
+
recipient: spec.recipient,
|
|
686
|
+
currency: spec.token ?? defaultMint,
|
|
687
|
+
decimals: spec.decimals ?? defaultDecimals,
|
|
688
|
+
network,
|
|
689
|
+
...spec.rpcUrl ? { rpcUrl: spec.rpcUrl } : {},
|
|
690
|
+
...spec.signer ? { signer: spec.signer } : {},
|
|
691
|
+
...spec.tokenProgram ? { tokenProgram: spec.tokenProgram } : {}
|
|
692
|
+
});
|
|
693
|
+
return wrapSolanaChargeWithFinalizedBlockhash(baseMethod, spec.rpcUrl ?? solanaDefaultRpcUrl(network));
|
|
694
|
+
}
|
|
695
|
+
async function registerStripe(spec) {
|
|
696
|
+
if (!spec.profileId || !spec.secretKey) {
|
|
697
|
+
throw new Error(
|
|
698
|
+
"createMppxServer: StripeRailSpec requires both profileId and secretKey."
|
|
699
|
+
);
|
|
700
|
+
}
|
|
701
|
+
return createMppxStripe({
|
|
702
|
+
profileId: spec.profileId,
|
|
703
|
+
secretKey: spec.secretKey,
|
|
704
|
+
paymentMethodTypes: spec.paymentMethodTypes
|
|
705
|
+
});
|
|
529
706
|
}
|
|
530
707
|
async function dynamicImport2(moduleName) {
|
|
531
708
|
try {
|
|
@@ -567,6 +744,29 @@ function wrapSolanaChargeWithFinalizedBlockhash(baseMethod, rpcUrl) {
|
|
|
567
744
|
}
|
|
568
745
|
|
|
569
746
|
// src/payment/dispatch.ts
|
|
747
|
+
function detectRailFromHeaders(headers) {
|
|
748
|
+
const get = (name) => {
|
|
749
|
+
if (headers instanceof Headers) {
|
|
750
|
+
return headers.get(name) ?? "";
|
|
751
|
+
}
|
|
752
|
+
const lower = name.toLowerCase();
|
|
753
|
+
for (const [k, v] of Object.entries(headers)) {
|
|
754
|
+
if (k.toLowerCase() === lower) {
|
|
755
|
+
if (v === void 0 || v === null) return "";
|
|
756
|
+
return Array.isArray(v) ? v[0] ?? "" : v;
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
return "";
|
|
760
|
+
};
|
|
761
|
+
const auth = get("authorization");
|
|
762
|
+
if (auth.toLowerCase().startsWith("payment ")) {
|
|
763
|
+
return "mpp";
|
|
764
|
+
}
|
|
765
|
+
if (get("payment-signature") || get("x-payment")) {
|
|
766
|
+
return "x402";
|
|
767
|
+
}
|
|
768
|
+
return null;
|
|
769
|
+
}
|
|
570
770
|
async function dispatchSettlementByNetwork(payload, handlers) {
|
|
571
771
|
const network = payload.accepted.network;
|
|
572
772
|
if (network.startsWith("eip155:")) {
|
|
@@ -599,37 +799,45 @@ function aliasAmountFields(accepts) {
|
|
|
599
799
|
return e;
|
|
600
800
|
});
|
|
601
801
|
}
|
|
602
|
-
function paymentRequiredHeader(
|
|
603
|
-
|
|
802
|
+
function paymentRequiredHeader({
|
|
803
|
+
x402Version,
|
|
804
|
+
accepts,
|
|
805
|
+
resource
|
|
806
|
+
}) {
|
|
807
|
+
return Buffer.from(JSON.stringify({ x402Version, accepts, ...resource ? { resource } : {} })).toString("base64");
|
|
604
808
|
}
|
|
605
809
|
|
|
606
810
|
// src/payment/headers.ts
|
|
607
|
-
function buildPaymentHeaders(
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
811
|
+
function buildPaymentHeaders({
|
|
812
|
+
rails: rails2,
|
|
813
|
+
orderId,
|
|
814
|
+
realm,
|
|
815
|
+
x402
|
|
816
|
+
}) {
|
|
817
|
+
const directives = rails2.map(
|
|
818
|
+
(rail) => buildPaymentDirective({
|
|
819
|
+
id: `${orderId}-${rail.rail}`,
|
|
820
|
+
realm,
|
|
612
821
|
rail: rail.rail,
|
|
613
|
-
amountUsd: rail.amountUsd
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
});
|
|
822
|
+
amountUsd: rail.amountUsd,
|
|
823
|
+
...rail.recipient !== void 0 ? { recipient: rail.recipient } : {},
|
|
824
|
+
...rail.networkId !== void 0 ? { networkId: rail.networkId } : {},
|
|
825
|
+
...rail.chainId !== void 0 ? { chainId: rail.chainId } : {},
|
|
826
|
+
...rail.currency !== void 0 ? { currency: rail.currency } : {},
|
|
827
|
+
...rail.decimals !== void 0 ? { decimals: rail.decimals } : {},
|
|
828
|
+
...rail.method !== void 0 ? { method: rail.method } : {},
|
|
829
|
+
...rail.intent !== void 0 ? { intent: rail.intent } : {},
|
|
830
|
+
...rail.expires !== void 0 ? { expires: rail.expires } : {}
|
|
831
|
+
})
|
|
832
|
+
);
|
|
625
833
|
const result = {
|
|
626
834
|
"www-authenticate": wwwAuthenticateHeader(directives)
|
|
627
835
|
};
|
|
628
|
-
if (
|
|
836
|
+
if (x402) {
|
|
629
837
|
result["PAYMENT-REQUIRED"] = paymentRequiredHeader({
|
|
630
|
-
x402Version:
|
|
631
|
-
accepts:
|
|
632
|
-
...
|
|
838
|
+
x402Version: x402.version ?? 2,
|
|
839
|
+
accepts: x402.accepts,
|
|
840
|
+
...x402.resource ? { resource: x402.resource } : {}
|
|
633
841
|
});
|
|
634
842
|
}
|
|
635
843
|
return result;
|
|
@@ -637,15 +845,20 @@ function buildPaymentHeaders(input) {
|
|
|
637
845
|
|
|
638
846
|
// src/payment/idempotency.ts
|
|
639
847
|
var SERVER_IDEMPOTENCY_KEY_MAX = 200;
|
|
640
|
-
function buildIdempotencyKey(
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
848
|
+
function buildIdempotencyKey({
|
|
849
|
+
paymentIntentId,
|
|
850
|
+
orderId,
|
|
851
|
+
amountCents,
|
|
852
|
+
prefix
|
|
853
|
+
}) {
|
|
854
|
+
const prefixPart = prefix ? `${prefix}-` : "";
|
|
855
|
+
if (paymentIntentId) {
|
|
856
|
+
const key = `${prefixPart}${paymentIntentId}`;
|
|
644
857
|
return clampKey(key);
|
|
645
858
|
}
|
|
646
|
-
if (
|
|
647
|
-
const amountSuffix =
|
|
648
|
-
const key = `${
|
|
859
|
+
if (orderId) {
|
|
860
|
+
const amountSuffix = amountCents !== void 0 ? `-${amountCents}` : "";
|
|
861
|
+
const key = `${prefixPart}pi-${orderId}${amountSuffix}`;
|
|
649
862
|
return clampKey(key);
|
|
650
863
|
}
|
|
651
864
|
return void 0;
|
|
@@ -731,16 +944,217 @@ async function extractPaymentSigner(request, x402PaymentHeader) {
|
|
|
731
944
|
}
|
|
732
945
|
return null;
|
|
733
946
|
}
|
|
947
|
+
async function extractPaymentSignerFromAuth(authHeader, x402PaymentHeader) {
|
|
948
|
+
const request = new Request("http://internal.gate/", {
|
|
949
|
+
headers: authHeader ? { authorization: authHeader } : {}
|
|
950
|
+
});
|
|
951
|
+
return extractPaymentSigner(request, x402PaymentHeader);
|
|
952
|
+
}
|
|
734
953
|
function readX402PaymentHeader(request) {
|
|
735
954
|
return request.headers.get("payment-signature") ?? request.headers.get("x-payment") ?? void 0;
|
|
736
955
|
}
|
|
956
|
+
function lowerHeaders(headers) {
|
|
957
|
+
const out = {};
|
|
958
|
+
for (const [k, v] of Object.entries(headers)) out[k.toLowerCase()] = v;
|
|
959
|
+
return out;
|
|
960
|
+
}
|
|
961
|
+
async function extractSignerForPrecheck(headers) {
|
|
962
|
+
const lower = lowerHeaders(headers);
|
|
963
|
+
const x402 = lower["payment-signature"] ?? lower["x-payment"];
|
|
964
|
+
if (x402) {
|
|
965
|
+
const signer = await extractPaymentSignerFromAuth(void 0, x402);
|
|
966
|
+
if (signer !== null) return signer;
|
|
967
|
+
}
|
|
968
|
+
const authorization = lower["authorization"];
|
|
969
|
+
if (authorization && authorization.toLowerCase().startsWith("payment ")) {
|
|
970
|
+
return await extractPaymentSignerFromAuth(authorization);
|
|
971
|
+
}
|
|
972
|
+
return null;
|
|
973
|
+
}
|
|
737
974
|
|
|
738
975
|
// src/payment/settlement_override.ts
|
|
739
976
|
var SETTLEMENT_OVERRIDES_HEADER = "Settlement-Overrides";
|
|
740
977
|
function settlementOverrideHeader(overrides) {
|
|
741
978
|
return { name: SETTLEMENT_OVERRIDES_HEADER, value: JSON.stringify(overrides) };
|
|
742
979
|
}
|
|
980
|
+
|
|
981
|
+
// src/payment/amounts.ts
|
|
982
|
+
function usdToAtomic(usd, opts) {
|
|
983
|
+
const { decimals } = opts;
|
|
984
|
+
if (!Number.isInteger(decimals) || decimals < 0) {
|
|
985
|
+
throw new RangeError(`decimals must be a non-negative integer, got ${decimals}`);
|
|
986
|
+
}
|
|
987
|
+
if (typeof usd === "number") {
|
|
988
|
+
if (!Number.isFinite(usd)) {
|
|
989
|
+
throw new RangeError(`usd must be finite, got ${usd}`);
|
|
990
|
+
}
|
|
991
|
+
if (usd < 0) {
|
|
992
|
+
throw new RangeError(`usd must be non-negative, got ${usd}`);
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
const s = (typeof usd === "number" ? usd.toString() : usd).trim();
|
|
996
|
+
if (s.startsWith("-")) {
|
|
997
|
+
throw new RangeError(`usd must be non-negative, got ${s}`);
|
|
998
|
+
}
|
|
999
|
+
if (s === "NaN" || s === "Infinity") {
|
|
1000
|
+
throw new RangeError(`usd must be finite, got ${s}`);
|
|
1001
|
+
}
|
|
1002
|
+
const match = /^(\d*)(?:\.(\d*))?$/.exec(s);
|
|
1003
|
+
if (!match || match[1] === "" && (match[2] === void 0 || match[2] === "")) {
|
|
1004
|
+
throw new SyntaxError(`invalid usd value: ${JSON.stringify(usd)}`);
|
|
1005
|
+
}
|
|
1006
|
+
const intPart = match[1] || "0";
|
|
1007
|
+
const fracPart = match[2] ?? "";
|
|
1008
|
+
if (fracPart.length <= decimals) {
|
|
1009
|
+
return BigInt(intPart + fracPart.padEnd(decimals, "0"));
|
|
1010
|
+
}
|
|
1011
|
+
const kept = fracPart.slice(0, decimals);
|
|
1012
|
+
const roundDigit = fracPart[decimals];
|
|
1013
|
+
let result = BigInt(intPart + kept);
|
|
1014
|
+
if (roundDigit >= "5") {
|
|
1015
|
+
result += 1n;
|
|
1016
|
+
}
|
|
1017
|
+
return result;
|
|
1018
|
+
}
|
|
1019
|
+
function formatUsdCents(cents) {
|
|
1020
|
+
return (cents / 100).toFixed(2);
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
// src/payment/zero-settle.ts
|
|
1024
|
+
var EVM_RE = /^0x[0-9a-fA-F]{40}$/;
|
|
1025
|
+
var SOLANA_BASE58_RE = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
|
|
1026
|
+
var NULL_RESULT = {
|
|
1027
|
+
signerAddress: null,
|
|
1028
|
+
signerNetwork: null,
|
|
1029
|
+
txHash: null
|
|
1030
|
+
};
|
|
1031
|
+
function zeroAmountCarveOut({
|
|
1032
|
+
rail,
|
|
1033
|
+
payload,
|
|
1034
|
+
authorizationHeader
|
|
1035
|
+
}) {
|
|
1036
|
+
if (rail === "x402-base") {
|
|
1037
|
+
return x402SignerFromPayload(payload);
|
|
1038
|
+
}
|
|
1039
|
+
if (rail === "tempo" || rail === "solana") {
|
|
1040
|
+
return mppSignerFromAuth(authorizationHeader);
|
|
1041
|
+
}
|
|
1042
|
+
return NULL_RESULT;
|
|
1043
|
+
}
|
|
1044
|
+
function x402SignerFromPayload(payload) {
|
|
1045
|
+
if (!payload || typeof payload !== "object") return NULL_RESULT;
|
|
1046
|
+
const inner = payload.payload;
|
|
1047
|
+
if (!inner || typeof inner !== "object") return NULL_RESULT;
|
|
1048
|
+
const authorization = inner.authorization;
|
|
1049
|
+
if (!authorization || typeof authorization !== "object") return NULL_RESULT;
|
|
1050
|
+
const fromAddr = authorization.from;
|
|
1051
|
+
if (typeof fromAddr !== "string" || !EVM_RE.test(fromAddr)) return NULL_RESULT;
|
|
1052
|
+
return {
|
|
1053
|
+
signerAddress: fromAddr.toLowerCase(),
|
|
1054
|
+
signerNetwork: "evm",
|
|
1055
|
+
txHash: null
|
|
1056
|
+
};
|
|
1057
|
+
}
|
|
1058
|
+
function mppSignerFromAuth(authorizationHeader) {
|
|
1059
|
+
if (typeof authorizationHeader !== "string") return NULL_RESULT;
|
|
1060
|
+
if (!authorizationHeader.toLowerCase().startsWith("payment ")) return NULL_RESULT;
|
|
1061
|
+
const token = authorizationHeader.slice("payment ".length).trim();
|
|
1062
|
+
if (!token) return NULL_RESULT;
|
|
1063
|
+
let credential;
|
|
1064
|
+
try {
|
|
1065
|
+
credential = JSON.parse(atob(token));
|
|
1066
|
+
} catch {
|
|
1067
|
+
return NULL_RESULT;
|
|
1068
|
+
}
|
|
1069
|
+
if (!credential || typeof credential !== "object") return NULL_RESULT;
|
|
1070
|
+
let source = credential.source;
|
|
1071
|
+
if (typeof source !== "string") {
|
|
1072
|
+
const challenge = credential.challenge;
|
|
1073
|
+
if (challenge && typeof challenge === "object") {
|
|
1074
|
+
source = challenge.source;
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
if (typeof source !== "string") return NULL_RESULT;
|
|
1078
|
+
const parts = source.split(":");
|
|
1079
|
+
if (parts.length < 4 || parts[0] !== "did" || parts[1] !== "pkh") return NULL_RESULT;
|
|
1080
|
+
const family = parts[2];
|
|
1081
|
+
const addr = parts[parts.length - 1] ?? "";
|
|
1082
|
+
if (family === "eip155" && EVM_RE.test(addr)) {
|
|
1083
|
+
return { signerAddress: addr.toLowerCase(), signerNetwork: "evm", txHash: null };
|
|
1084
|
+
}
|
|
1085
|
+
if (family === "solana" && SOLANA_BASE58_RE.test(addr)) {
|
|
1086
|
+
return { signerAddress: addr, signerNetwork: "solana", txHash: null };
|
|
1087
|
+
}
|
|
1088
|
+
return NULL_RESULT;
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
// src/payment/lazy.ts
|
|
1092
|
+
function x402RailName(spec) {
|
|
1093
|
+
const network = spec.network ?? "eip155:8453";
|
|
1094
|
+
if (network === "eip155:8453") return "x402-base-mainnet";
|
|
1095
|
+
if (network === "eip155:84532") return "x402-base-sepolia";
|
|
1096
|
+
throw new Error(
|
|
1097
|
+
`lazyX402Server: unsupported X402BaseRailSpec.network=${JSON.stringify(network)}`
|
|
1098
|
+
);
|
|
1099
|
+
}
|
|
1100
|
+
function lazyX402Server(opts) {
|
|
1101
|
+
const { spec, cdpApiKeyId, cdpApiKeySecret } = opts;
|
|
1102
|
+
const railName = x402RailName(spec);
|
|
1103
|
+
const useCdp = Boolean(cdpApiKeyId && cdpApiKeySecret);
|
|
1104
|
+
const facilitator = useCdp ? "coinbase" : "http";
|
|
1105
|
+
let cached;
|
|
1106
|
+
let pending;
|
|
1107
|
+
return async () => {
|
|
1108
|
+
if (cached !== void 0) return cached;
|
|
1109
|
+
if (pending !== void 0) return pending;
|
|
1110
|
+
pending = (async () => {
|
|
1111
|
+
const server = await createX402Server({ facilitator, rails: [railName] });
|
|
1112
|
+
cached = server;
|
|
1113
|
+
pending = void 0;
|
|
1114
|
+
return server;
|
|
1115
|
+
})();
|
|
1116
|
+
return pending;
|
|
1117
|
+
};
|
|
1118
|
+
}
|
|
1119
|
+
function lazyMppxServer(opts) {
|
|
1120
|
+
const { rails: rails2, secretKey } = opts;
|
|
1121
|
+
let cached;
|
|
1122
|
+
let pending;
|
|
1123
|
+
return async () => {
|
|
1124
|
+
if (cached !== void 0) return cached;
|
|
1125
|
+
if (pending !== void 0) return pending;
|
|
1126
|
+
pending = (async () => {
|
|
1127
|
+
const server = await createMppxServer({ secretKey, rails: rails2 });
|
|
1128
|
+
cached = server;
|
|
1129
|
+
pending = void 0;
|
|
1130
|
+
return server;
|
|
1131
|
+
})();
|
|
1132
|
+
return pending;
|
|
1133
|
+
};
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
// src/payment/solana.ts
|
|
1137
|
+
async function loadSolanaFeePayer(opts) {
|
|
1138
|
+
const raw = opts.privateKey;
|
|
1139
|
+
if (!raw) return void 0;
|
|
1140
|
+
const moduleName = "@solana/kit";
|
|
1141
|
+
const kit = await import(moduleName).catch(() => null);
|
|
1142
|
+
if (!kit?.createKeyPairSignerFromPrivateKeyBytes || !kit.getBase58Codec) {
|
|
1143
|
+
throw new Error(
|
|
1144
|
+
"@solana/kit not installed \u2014 `npm install @solana/kit` for loadSolanaFeePayer."
|
|
1145
|
+
);
|
|
1146
|
+
}
|
|
1147
|
+
let bytes;
|
|
1148
|
+
if (/^[0-9a-fA-F]{128}$/.test(raw)) {
|
|
1149
|
+
bytes = new Uint8Array(raw.match(/.{2}/g).map((h) => parseInt(h, 16))).slice(0, 32);
|
|
1150
|
+
} else {
|
|
1151
|
+
const decoded = new Uint8Array(kit.getBase58Codec().encode(raw));
|
|
1152
|
+
bytes = decoded.length === 64 ? decoded.slice(0, 32) : decoded;
|
|
1153
|
+
}
|
|
1154
|
+
return kit.createKeyPairSignerFromPrivateKeyBytes(bytes);
|
|
1155
|
+
}
|
|
743
1156
|
export {
|
|
1157
|
+
RAIL_SPEC_DEFAULTS,
|
|
744
1158
|
SETTLEMENT_OVERRIDES_HEADER,
|
|
745
1159
|
USDC,
|
|
746
1160
|
X402_SUPPORTED_BASE_NETWORKS,
|
|
@@ -750,11 +1164,19 @@ export {
|
|
|
750
1164
|
buildPaymentHeaders,
|
|
751
1165
|
buildPaymentRequestBlob,
|
|
752
1166
|
buildX402AcceptsFor402,
|
|
1167
|
+
classifyOrchestrationError,
|
|
753
1168
|
classifyX402SettleResult,
|
|
754
1169
|
createMppxServer,
|
|
755
1170
|
createX402Server,
|
|
1171
|
+
detectRailFromHeaders,
|
|
756
1172
|
dispatchSettlementByNetwork,
|
|
757
1173
|
extractPaymentSigner,
|
|
1174
|
+
extractPaymentSignerFromAuth,
|
|
1175
|
+
extractSignerForPrecheck,
|
|
1176
|
+
formatUsdCents,
|
|
1177
|
+
lazyMppxServer,
|
|
1178
|
+
lazyX402Server,
|
|
1179
|
+
loadSolanaFeePayer,
|
|
758
1180
|
lookupRail,
|
|
759
1181
|
networkFamily,
|
|
760
1182
|
networks,
|
|
@@ -764,10 +1186,13 @@ export {
|
|
|
764
1186
|
rails,
|
|
765
1187
|
readX402PaymentHeader,
|
|
766
1188
|
registerX402SchemesV1V2,
|
|
1189
|
+
resolveRecipient,
|
|
767
1190
|
settlementOverrideHeader,
|
|
1191
|
+
usdToAtomic,
|
|
768
1192
|
validateX402NetworkConfig,
|
|
769
1193
|
verifyX402Request,
|
|
770
1194
|
wrapSolanaChargeWithFinalizedBlockhash,
|
|
771
|
-
wwwAuthenticateHeader
|
|
1195
|
+
wwwAuthenticateHeader,
|
|
1196
|
+
zeroAmountCarveOut
|
|
772
1197
|
};
|
|
773
1198
|
//# sourceMappingURL=index.mjs.map
|