@agent-score/commerce 1.2.0 → 1.3.1
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 +26 -11
- package/dist/{_response-RpEB7-vl.d.ts → _response-C2yFQoIA.d.ts} +1 -1
- package/dist/{_response-DS-LR590.d.mts → _response-DpB-cm2c.d.mts} +1 -1
- package/dist/{agent_instructions-d3UWTdam.d.mts → agent_instructions-DiMSGkdm.d.mts} +10 -6
- package/dist/{agent_instructions-d3UWTdam.d.ts → agent_instructions-DiMSGkdm.d.ts} +10 -6
- package/dist/challenge/index.d.mts +18 -9
- package/dist/challenge/index.d.ts +18 -9
- package/dist/challenge/index.js +25 -24
- package/dist/challenge/index.js.map +1 -1
- package/dist/challenge/index.mjs +25 -24
- package/dist/challenge/index.mjs.map +1 -1
- 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 +130 -6
- package/dist/discovery/index.d.ts +130 -6
- package/dist/discovery/index.js +75 -59
- package/dist/discovery/index.js.map +1 -1
- package/dist/discovery/index.mjs +70 -58
- package/dist/discovery/index.mjs.map +1 -1
- package/dist/identity/express.d.mts +2 -2
- package/dist/identity/express.d.ts +2 -2
- package/dist/identity/express.js +48 -25
- package/dist/identity/express.js.map +1 -1
- package/dist/identity/express.mjs +48 -25
- package/dist/identity/express.mjs.map +1 -1
- package/dist/identity/fastify.d.mts +2 -2
- package/dist/identity/fastify.d.ts +2 -2
- package/dist/identity/fastify.js +48 -25
- package/dist/identity/fastify.js.map +1 -1
- package/dist/identity/fastify.mjs +48 -25
- package/dist/identity/fastify.mjs.map +1 -1
- package/dist/identity/hono.d.mts +2 -2
- package/dist/identity/hono.d.ts +2 -2
- package/dist/identity/hono.js +48 -25
- package/dist/identity/hono.js.map +1 -1
- package/dist/identity/hono.mjs +48 -25
- package/dist/identity/hono.mjs.map +1 -1
- package/dist/identity/nextjs.d.mts +2 -2
- package/dist/identity/nextjs.d.ts +2 -2
- package/dist/identity/nextjs.js +48 -25
- package/dist/identity/nextjs.js.map +1 -1
- package/dist/identity/nextjs.mjs +48 -25
- package/dist/identity/nextjs.mjs.map +1 -1
- package/dist/identity/web.d.mts +2 -2
- package/dist/identity/web.d.ts +2 -2
- package/dist/identity/web.js +48 -25
- package/dist/identity/web.js.map +1 -1
- package/dist/identity/web.mjs +48 -25
- package/dist/identity/web.mjs.map +1 -1
- package/dist/index.d.mts +12 -12
- package/dist/index.d.ts +12 -12
- package/dist/index.js +47 -24
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +47 -24
- package/dist/index.mjs.map +1 -1
- package/dist/payment/index.d.mts +158 -49
- package/dist/payment/index.d.ts +158 -49
- package/dist/payment/index.js +194 -73
- package/dist/payment/index.js.map +1 -1
- package/dist/payment/index.mjs +192 -72
- package/dist/payment/index.mjs.map +1 -1
- package/dist/{signer-Cvdwn6Cs.d.mts → signer-kCAJUZwp.d.mts} +10 -12
- package/dist/{signer-Cvdwn6Cs.d.ts → signer-kCAJUZwp.d.ts} +10 -12
- package/dist/stripe-multichain/index.d.mts +2 -2
- package/dist/stripe-multichain/index.d.ts +2 -2
- package/dist/stripe-multichain/index.js.map +1 -1
- package/dist/stripe-multichain/index.mjs.map +1 -1
- package/package.json +13 -4
package/dist/payment/index.js
CHANGED
|
@@ -23,12 +23,12 @@ __export(payment_exports, {
|
|
|
23
23
|
SETTLEMENT_OVERRIDES_HEADER: () => SETTLEMENT_OVERRIDES_HEADER,
|
|
24
24
|
USDC: () => USDC,
|
|
25
25
|
X402_SUPPORTED_BASE_NETWORKS: () => X402_SUPPORTED_BASE_NETWORKS,
|
|
26
|
-
X402_SUPPORTED_SVM_NETWORKS: () => X402_SUPPORTED_SVM_NETWORKS,
|
|
27
26
|
aliasAmountFields: () => aliasAmountFields,
|
|
28
27
|
buildIdempotencyKey: () => buildIdempotencyKey,
|
|
29
28
|
buildPaymentDirective: () => buildPaymentDirective,
|
|
30
29
|
buildPaymentHeaders: () => buildPaymentHeaders,
|
|
31
30
|
buildPaymentRequestBlob: () => buildPaymentRequestBlob,
|
|
31
|
+
classifyX402SettleResult: () => classifyX402SettleResult,
|
|
32
32
|
createMppxServer: () => createMppxServer,
|
|
33
33
|
createX402Server: () => createX402Server,
|
|
34
34
|
dispatchSettlementByNetwork: () => dispatchSettlementByNetwork,
|
|
@@ -45,6 +45,7 @@ __export(payment_exports, {
|
|
|
45
45
|
settlementOverrideHeader: () => settlementOverrideHeader,
|
|
46
46
|
validateX402NetworkConfig: () => validateX402NetworkConfig,
|
|
47
47
|
verifyX402Request: () => verifyX402Request,
|
|
48
|
+
wrapSolanaChargeWithFinalizedBlockhash: () => wrapSolanaChargeWithFinalizedBlockhash,
|
|
48
49
|
wwwAuthenticateHeader: () => wwwAuthenticateHeader
|
|
49
50
|
});
|
|
50
51
|
module.exports = __toCommonJS(payment_exports);
|
|
@@ -141,15 +142,15 @@ var rails = {
|
|
|
141
142
|
decimals: USDC.base.sepolia.decimals,
|
|
142
143
|
asset: USDC.base.sepolia.address
|
|
143
144
|
},
|
|
144
|
-
"
|
|
145
|
-
method: "
|
|
145
|
+
"mpp-solana-mainnet": {
|
|
146
|
+
method: "solana",
|
|
146
147
|
network: networks.solana.mainnet.caip2,
|
|
147
148
|
currency: USDC.solana.mainnet.mint,
|
|
148
149
|
decimals: USDC.solana.mainnet.decimals,
|
|
149
150
|
asset: USDC.solana.mainnet.mint
|
|
150
151
|
},
|
|
151
|
-
"
|
|
152
|
-
method: "
|
|
152
|
+
"mpp-solana-devnet": {
|
|
153
|
+
method: "solana",
|
|
153
154
|
network: networks.solana.devnet.caip2,
|
|
154
155
|
currency: USDC.solana.devnet.mint,
|
|
155
156
|
decimals: USDC.solana.devnet.decimals,
|
|
@@ -219,11 +220,6 @@ function registerX402SchemesV1V2(server, network, scheme) {
|
|
|
219
220
|
|
|
220
221
|
// src/payment/x402_server.ts
|
|
221
222
|
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
223
|
const x402Core = await dynamicImport("@x402/core/server") ?? null;
|
|
228
224
|
if (!x402Core) {
|
|
229
225
|
throw new Error(
|
|
@@ -247,7 +243,6 @@ async function createX402Server(opts = {}) {
|
|
|
247
243
|
const server = new x402Core.x402ResourceServer(facilitator);
|
|
248
244
|
let evmExactModule = null;
|
|
249
245
|
let evmUptoModule = null;
|
|
250
|
-
let svmModule = null;
|
|
251
246
|
for (const rail of opts.rails ?? []) {
|
|
252
247
|
const isUpto = rail.endsWith("-upto");
|
|
253
248
|
if (rail.startsWith("x402-base")) {
|
|
@@ -266,13 +261,6 @@ async function createX402Server(opts = {}) {
|
|
|
266
261
|
}
|
|
267
262
|
registerX402SchemesV1V2(server, network, new evmExactModule.ExactEvmScheme());
|
|
268
263
|
}
|
|
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
264
|
}
|
|
277
265
|
}
|
|
278
266
|
for (const { network, scheme } of opts.schemes ?? []) {
|
|
@@ -301,9 +289,60 @@ async function dynamicImport(moduleName) {
|
|
|
301
289
|
}
|
|
302
290
|
|
|
303
291
|
// src/payment/x402_settle.ts
|
|
292
|
+
function classifyX402SettleResult(result) {
|
|
293
|
+
if (result.success) return null;
|
|
294
|
+
switch (result.phase) {
|
|
295
|
+
case "no_requirements":
|
|
296
|
+
return {
|
|
297
|
+
status: 500,
|
|
298
|
+
code: "payment_internal_error",
|
|
299
|
+
message: "Failed to build x402 payment requirements for this configuration",
|
|
300
|
+
nextSteps: {
|
|
301
|
+
action: "contact_support",
|
|
302
|
+
user_message: "The merchant could not produce a payment challenge for this request. Try again later or contact support."
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
case "verify_failed":
|
|
306
|
+
return {
|
|
307
|
+
status: 400,
|
|
308
|
+
code: "payment_proof_invalid",
|
|
309
|
+
message: "Payment credential failed verification; regenerate from a fresh 402 challenge",
|
|
310
|
+
nextSteps: {
|
|
311
|
+
action: "regenerate_payment_credential",
|
|
312
|
+
user_message: "The payment credential was rejected at verify time. Discard it, fetch a fresh 402 challenge, and re-sign."
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
case "facilitator_error":
|
|
316
|
+
return {
|
|
317
|
+
status: 503,
|
|
318
|
+
code: "payment_provider_unavailable",
|
|
319
|
+
message: "Payment provider could not process this network configuration",
|
|
320
|
+
nextSteps: {
|
|
321
|
+
action: "try_different_rail",
|
|
322
|
+
user_message: "This rail is currently unavailable. Pick a different rail from the 402 challenge and retry."
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
case "settle_failed":
|
|
326
|
+
return {
|
|
327
|
+
status: 503,
|
|
328
|
+
code: "payment_provider_unavailable",
|
|
329
|
+
message: "Payment credential verified but on-chain settlement failed",
|
|
330
|
+
nextSteps: {
|
|
331
|
+
action: "retry_or_swap_method",
|
|
332
|
+
retry_after_seconds: 10,
|
|
333
|
+
user_message: "Transient settlement error. Retry in a few seconds, or pick a different rail from the 402 challenge."
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
}
|
|
304
338
|
async function processX402Settle(input) {
|
|
305
339
|
const server = input.x402Server;
|
|
306
|
-
|
|
340
|
+
let builtRequirements;
|
|
341
|
+
try {
|
|
342
|
+
builtRequirements = await server.buildPaymentRequirements(input.resourceConfig);
|
|
343
|
+
} catch (err) {
|
|
344
|
+
return { success: false, phase: "facilitator_error", step: "build_requirements", error: err };
|
|
345
|
+
}
|
|
307
346
|
const matchedRequirement = builtRequirements[0];
|
|
308
347
|
if (!matchedRequirement) {
|
|
309
348
|
return { success: false, phase: "no_requirements", reason: "x402Server.buildPaymentRequirements returned empty" };
|
|
@@ -312,13 +351,23 @@ async function processX402Settle(input) {
|
|
|
312
351
|
const path = new URL(input.resourceMeta.url).pathname;
|
|
313
352
|
return { method: "POST", adapter: { getPath: () => path }, routePattern: path };
|
|
314
353
|
})();
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
input.
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
354
|
+
let enrichedExt;
|
|
355
|
+
try {
|
|
356
|
+
enrichedExt = input.extension !== void 0 ? server.enrichExtensions(input.extension, transportContext) : void 0;
|
|
357
|
+
} catch (err) {
|
|
358
|
+
return { success: false, phase: "facilitator_error", step: "enrich_extensions", error: err };
|
|
359
|
+
}
|
|
360
|
+
let verifyResult;
|
|
361
|
+
try {
|
|
362
|
+
verifyResult = await server.processPaymentRequest(
|
|
363
|
+
input.payload,
|
|
364
|
+
input.resourceConfig,
|
|
365
|
+
input.resourceMeta,
|
|
366
|
+
enrichedExt
|
|
367
|
+
);
|
|
368
|
+
} catch (err) {
|
|
369
|
+
return { success: false, phase: "facilitator_error", step: "process_payment_request", error: err };
|
|
370
|
+
}
|
|
322
371
|
if (!verifyResult.success) {
|
|
323
372
|
return { success: false, phase: "verify_failed", verifyResult };
|
|
324
373
|
}
|
|
@@ -342,30 +391,15 @@ var X402_SUPPORTED_BASE_NETWORKS = /* @__PURE__ */ new Set([
|
|
|
342
391
|
networks.base.mainnet.caip2,
|
|
343
392
|
networks.base.sepolia.caip2
|
|
344
393
|
]);
|
|
345
|
-
var X402_SUPPORTED_SVM_NETWORKS = /* @__PURE__ */ new Set([
|
|
346
|
-
networks.solana.mainnet.caip2,
|
|
347
|
-
networks.solana.devnet.caip2
|
|
348
|
-
]);
|
|
349
394
|
function validateX402NetworkConfig(input) {
|
|
350
395
|
if (!X402_SUPPORTED_BASE_NETWORKS.has(input.baseNetwork)) {
|
|
351
396
|
throw new Error(
|
|
352
397
|
`X402_BASE_NETWORK=${input.baseNetwork} is not supported. Use one of: ${[...X402_SUPPORTED_BASE_NETWORKS].join(", ")}`
|
|
353
398
|
);
|
|
354
399
|
}
|
|
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
400
|
}
|
|
366
401
|
var EVM_ADDRESS_RE = /^0x[0-9a-fA-F]{40}$/;
|
|
367
|
-
var
|
|
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.";
|
|
402
|
+
var REGENERATE_WARNING = "Use `agentscore-pay pay --chain base` (or `tempo request` for Tempo USDC) so the credential is signed and submitted via the protocol handshake. Do NOT use `tempo wallet transfer` \u2014 that sends USDC on-chain but does not complete the handshake.";
|
|
369
403
|
function regenerateBody(message, userMessage) {
|
|
370
404
|
return {
|
|
371
405
|
error: { code: "payment_proof_invalid", message },
|
|
@@ -403,18 +437,27 @@ async function verifyX402Request(input) {
|
|
|
403
437
|
}
|
|
404
438
|
const signedNetwork = payload.accepted?.network;
|
|
405
439
|
const signedPayTo = payload.accepted?.payTo;
|
|
406
|
-
if (!signedNetwork || signedNetwork !== input.
|
|
440
|
+
if (!signedNetwork || signedNetwork !== input.acceptedNetwork) {
|
|
441
|
+
if (signedNetwork && signedNetwork.toLowerCase().startsWith("solana:")) {
|
|
442
|
+
return {
|
|
443
|
+
ok: false,
|
|
444
|
+
status: 400,
|
|
445
|
+
body: regenerateBody(
|
|
446
|
+
`x402 on ${signedNetwork} is not accepted; Solana payments must use the \`solana/charge\` rail advertised in the 402 challenge. This server accepts x402 on ${input.acceptedNetwork} only.`,
|
|
447
|
+
"Solana payments are not accepted over x402 at this merchant. Pick the `solana/charge` rail from the 402 challenge and re-sign."
|
|
448
|
+
)
|
|
449
|
+
};
|
|
450
|
+
}
|
|
407
451
|
return {
|
|
408
452
|
ok: false,
|
|
409
453
|
status: 400,
|
|
410
454
|
body: regenerateBody(
|
|
411
|
-
`Unsupported x402 network ${signedNetwork ?? "<missing>"}; this server accepts ${input.
|
|
412
|
-
"The credential signed for an unsupported network. Pick
|
|
455
|
+
`Unsupported x402 network ${signedNetwork ?? "<missing>"}; this server accepts ${input.acceptedNetwork}.`,
|
|
456
|
+
"The credential signed for an unsupported network. Pick the accepted network from the 402 challenge and re-sign."
|
|
413
457
|
)
|
|
414
458
|
};
|
|
415
459
|
}
|
|
416
|
-
const
|
|
417
|
-
const addressShapeOk = isSolana ? typeof signedPayTo === "string" && SOLANA_ADDRESS_RE.test(signedPayTo) : typeof signedPayTo === "string" && EVM_ADDRESS_RE.test(signedPayTo);
|
|
460
|
+
const addressShapeOk = typeof signedPayTo === "string" && EVM_ADDRESS_RE.test(signedPayTo);
|
|
418
461
|
if (!signedPayTo || !addressShapeOk) {
|
|
419
462
|
return {
|
|
420
463
|
ok: false,
|
|
@@ -435,7 +478,7 @@ async function verifyX402Request(input) {
|
|
|
435
478
|
)
|
|
436
479
|
};
|
|
437
480
|
}
|
|
438
|
-
return { ok: true, payload, signedNetwork, signedPayTo
|
|
481
|
+
return { ok: true, payload, signedNetwork, signedPayTo };
|
|
439
482
|
}
|
|
440
483
|
|
|
441
484
|
// src/stripe-multichain/mppx_stripe.ts
|
|
@@ -494,6 +537,29 @@ async function createMppxServer(opts) {
|
|
|
494
537
|
})
|
|
495
538
|
);
|
|
496
539
|
}
|
|
540
|
+
if (opts.rails?.solana) {
|
|
541
|
+
const solanaMpp = await dynamicImport2("@solana/mpp/server");
|
|
542
|
+
if (!solanaMpp?.charge) {
|
|
543
|
+
throw new Error(
|
|
544
|
+
"@solana/mpp not installed \u2014 `npm install @solana/mpp @solana/kit` to use the solana rail."
|
|
545
|
+
);
|
|
546
|
+
}
|
|
547
|
+
const s = opts.rails.solana;
|
|
548
|
+
const network = s.network ?? "mainnet-beta";
|
|
549
|
+
const defaultMint = network === "mainnet-beta" ? USDC.solana.mainnet.mint : USDC.solana.devnet.mint;
|
|
550
|
+
const defaultDecimals = network === "mainnet-beta" ? USDC.solana.mainnet.decimals : USDC.solana.devnet.decimals;
|
|
551
|
+
const baseMethod = solanaMpp.charge({
|
|
552
|
+
recipient: s.recipient,
|
|
553
|
+
currency: s.currency ?? defaultMint,
|
|
554
|
+
decimals: s.decimals ?? defaultDecimals,
|
|
555
|
+
network,
|
|
556
|
+
...s.rpcUrl ? { rpcUrl: s.rpcUrl } : {},
|
|
557
|
+
...s.signer ? { signer: s.signer } : {},
|
|
558
|
+
...s.tokenProgram ? { tokenProgram: s.tokenProgram } : {}
|
|
559
|
+
});
|
|
560
|
+
const rpcUrl = s.rpcUrl ?? (network === "mainnet-beta" ? "https://api.mainnet-beta.solana.com" : network === "devnet" ? "https://api.devnet.solana.com" : "http://localhost:8899");
|
|
561
|
+
methods.push(wrapSolanaChargeWithFinalizedBlockhash(baseMethod, rpcUrl));
|
|
562
|
+
}
|
|
497
563
|
if (opts.rails?.stripe) {
|
|
498
564
|
const stripeMethod = await createMppxStripe(opts.rails.stripe);
|
|
499
565
|
methods.push(stripeMethod);
|
|
@@ -507,6 +573,37 @@ async function dynamicImport2(moduleName) {
|
|
|
507
573
|
return null;
|
|
508
574
|
}
|
|
509
575
|
}
|
|
576
|
+
function wrapSolanaChargeWithFinalizedBlockhash(baseMethod, rpcUrl) {
|
|
577
|
+
return {
|
|
578
|
+
...baseMethod,
|
|
579
|
+
async request(args) {
|
|
580
|
+
const orig = await baseMethod.request(args);
|
|
581
|
+
if (args.credential || !orig || typeof orig !== "object") return orig;
|
|
582
|
+
try {
|
|
583
|
+
const res = await fetch(rpcUrl, {
|
|
584
|
+
method: "POST",
|
|
585
|
+
headers: { "Content-Type": "application/json" },
|
|
586
|
+
body: JSON.stringify({
|
|
587
|
+
id: 1,
|
|
588
|
+
jsonrpc: "2.0",
|
|
589
|
+
method: "getLatestBlockhash",
|
|
590
|
+
params: [{ commitment: "finalized" }]
|
|
591
|
+
})
|
|
592
|
+
});
|
|
593
|
+
const data = await res.json();
|
|
594
|
+
const finalized = data?.result?.value?.blockhash;
|
|
595
|
+
if (finalized) {
|
|
596
|
+
return {
|
|
597
|
+
...orig,
|
|
598
|
+
methodDetails: { ...orig.methodDetails ?? {}, recentBlockhash: finalized }
|
|
599
|
+
};
|
|
600
|
+
}
|
|
601
|
+
} catch {
|
|
602
|
+
}
|
|
603
|
+
return orig;
|
|
604
|
+
}
|
|
605
|
+
};
|
|
606
|
+
}
|
|
510
607
|
|
|
511
608
|
// src/payment/dispatch.ts
|
|
512
609
|
async function dispatchSettlementByNetwork(payload, handlers) {
|
|
@@ -601,6 +698,44 @@ function clampKey(key) {
|
|
|
601
698
|
}
|
|
602
699
|
|
|
603
700
|
// src/signer.ts
|
|
701
|
+
var TOKEN_PROGRAM = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
|
|
702
|
+
var TOKEN_2022_PROGRAM = "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb";
|
|
703
|
+
var TRANSFER_CHECKED_DISCRIMINATOR = 12;
|
|
704
|
+
async function extractSolanaSignerFromCredential(credential) {
|
|
705
|
+
const payload = credential.payload;
|
|
706
|
+
if (!payload?.transaction || payload.type !== "transaction") return null;
|
|
707
|
+
const moduleName = "@solana/kit";
|
|
708
|
+
const kit = await import(moduleName).catch(() => null);
|
|
709
|
+
if (!kit?.getBase64Codec || !kit.getTransactionDecoder || !kit.getCompiledTransactionMessageDecoder) {
|
|
710
|
+
return null;
|
|
711
|
+
}
|
|
712
|
+
try {
|
|
713
|
+
const txBytes = kit.getBase64Codec().encode(payload.transaction);
|
|
714
|
+
const decoded = kit.getTransactionDecoder().decode(txBytes);
|
|
715
|
+
const message = kit.getCompiledTransactionMessageDecoder().decode(decoded.messageBytes);
|
|
716
|
+
for (const ix of message.instructions) {
|
|
717
|
+
const programId = message.staticAccounts[ix.programAddressIndex];
|
|
718
|
+
if (programId !== TOKEN_PROGRAM && programId !== TOKEN_2022_PROGRAM) continue;
|
|
719
|
+
const data = ix.data;
|
|
720
|
+
if (!data || data.length === 0 || data[0] !== TRANSFER_CHECKED_DISCRIMINATOR) continue;
|
|
721
|
+
const accountIndices = ix.accountIndices ?? [];
|
|
722
|
+
const authorityIndex = accountIndices[3];
|
|
723
|
+
if (authorityIndex === void 0) continue;
|
|
724
|
+
if (authorityIndex >= message.staticAccounts.length) {
|
|
725
|
+
console.warn(
|
|
726
|
+
"[gate] Solana TransferChecked authority resolves through an address lookup table; signer-match recovery requires the static-account form. Skipping."
|
|
727
|
+
);
|
|
728
|
+
continue;
|
|
729
|
+
}
|
|
730
|
+
const authority = message.staticAccounts[authorityIndex];
|
|
731
|
+
if (authority) return authority;
|
|
732
|
+
}
|
|
733
|
+
return null;
|
|
734
|
+
} catch (err) {
|
|
735
|
+
console.warn("[gate] Solana credential decode failed:", err instanceof Error ? err.message : err);
|
|
736
|
+
return null;
|
|
737
|
+
}
|
|
738
|
+
}
|
|
604
739
|
async function extractPaymentSigner(request, x402PaymentHeader) {
|
|
605
740
|
const authHeader = request.headers.get("authorization");
|
|
606
741
|
if (authHeader) {
|
|
@@ -610,8 +745,12 @@ async function extractPaymentSigner(request, x402PaymentHeader) {
|
|
|
610
745
|
if (mppx?.Credential?.extractPaymentScheme(authHeader)) {
|
|
611
746
|
const credential = mppx.Credential.fromRequest(request);
|
|
612
747
|
const source = credential.source;
|
|
613
|
-
const
|
|
614
|
-
if (
|
|
748
|
+
const evmMatch = source?.match(/^did:pkh:eip155:\d+:(0x[0-9a-fA-F]{40})$/);
|
|
749
|
+
if (evmMatch) return { address: evmMatch[1].toLowerCase(), network: "evm" };
|
|
750
|
+
const solMatch = source?.match(/^did:pkh:solana:[1-9A-HJ-NP-Za-km-z]{32,44}:([1-9A-HJ-NP-Za-km-z]{32,44})$/);
|
|
751
|
+
if (solMatch) return { address: solMatch[1], network: "solana" };
|
|
752
|
+
const solanaFromTx = await extractSolanaSignerFromCredential(credential);
|
|
753
|
+
if (solanaFromTx) return { address: solanaFromTx, network: "solana" };
|
|
615
754
|
}
|
|
616
755
|
} catch (err) {
|
|
617
756
|
console.warn("[gate] MPP signer extraction failed:", err instanceof Error ? err.message : err);
|
|
@@ -621,28 +760,9 @@ async function extractPaymentSigner(request, x402PaymentHeader) {
|
|
|
621
760
|
try {
|
|
622
761
|
const decoded = atob(x402PaymentHeader);
|
|
623
762
|
const parsed = JSON.parse(decoded);
|
|
624
|
-
const
|
|
625
|
-
if (
|
|
626
|
-
|
|
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
|
-
}
|
|
763
|
+
const from = parsed?.payload?.authorization?.from;
|
|
764
|
+
if (typeof from === "string" && /^0x[0-9a-fA-F]{40}$/.test(from)) {
|
|
765
|
+
return { address: from.toLowerCase(), network: "evm" };
|
|
646
766
|
}
|
|
647
767
|
} catch (err) {
|
|
648
768
|
console.warn("[gate] x402 signer extraction failed:", err instanceof Error ? err.message : err);
|
|
@@ -664,12 +784,12 @@ function settlementOverrideHeader(overrides) {
|
|
|
664
784
|
SETTLEMENT_OVERRIDES_HEADER,
|
|
665
785
|
USDC,
|
|
666
786
|
X402_SUPPORTED_BASE_NETWORKS,
|
|
667
|
-
X402_SUPPORTED_SVM_NETWORKS,
|
|
668
787
|
aliasAmountFields,
|
|
669
788
|
buildIdempotencyKey,
|
|
670
789
|
buildPaymentDirective,
|
|
671
790
|
buildPaymentHeaders,
|
|
672
791
|
buildPaymentRequestBlob,
|
|
792
|
+
classifyX402SettleResult,
|
|
673
793
|
createMppxServer,
|
|
674
794
|
createX402Server,
|
|
675
795
|
dispatchSettlementByNetwork,
|
|
@@ -686,6 +806,7 @@ function settlementOverrideHeader(overrides) {
|
|
|
686
806
|
settlementOverrideHeader,
|
|
687
807
|
validateX402NetworkConfig,
|
|
688
808
|
verifyX402Request,
|
|
809
|
+
wrapSolanaChargeWithFinalizedBlockhash,
|
|
689
810
|
wwwAuthenticateHeader
|
|
690
811
|
});
|
|
691
812
|
//# sourceMappingURL=index.js.map
|