@piprail/sdk 1.9.0 → 1.11.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/CHANGELOG.md +70 -0
- package/ERRORS.md +21 -8
- package/README.md +20 -0
- package/STANDARDS.md +5 -2
- package/dist/{algorand-IJJKE35X.cjs → algorand-MXUSKX46.cjs} +17 -17
- package/dist/{algorand-B67G4335.js → algorand-WGVF4KTU.js} +1 -1
- package/dist/{aptos-YQWTGFRZ.js → aptos-LPBLSEIQ.js} +1 -1
- package/dist/{aptos-X3G2UBYW.cjs → aptos-YT7SXWPF.cjs} +16 -16
- package/dist/{chunk-IQGT65WS.cjs → chunk-MDLZJGLY.cjs} +20 -16
- package/dist/{chunk-QDS6FBZP.js → chunk-SVMGHASK.js} +4 -0
- package/dist/index.cjs +897 -265
- package/dist/index.d.cts +504 -45
- package/dist/index.d.ts +504 -45
- package/dist/index.js +820 -188
- package/dist/{near-GGUHLXAF.cjs → near-7ZDNISUX.cjs} +19 -19
- package/dist/{near-7MBBCDUE.js → near-K6BDBABG.js} +1 -1
- package/dist/{solana-W24TCJV4.cjs → solana-PU7N2M64.cjs} +14 -14
- package/dist/{solana-7WJVZGDW.js → solana-S3UFI3FE.js} +1 -1
- package/dist/{stellar-HV6VGZX3.js → stellar-Q5PO23SC.js} +1 -1
- package/dist/{stellar-YMY3K2YB.cjs → stellar-VDQOFQEO.cjs} +21 -21
- package/dist/{sui-32KVESR5.cjs → sui-FKSMLKRF.cjs} +17 -17
- package/dist/{sui-2WFWVFJX.js → sui-WOXRKJXS.js} +1 -1
- package/dist/{ton-FIQGV2LC.cjs → ton-VK6KRJHP.cjs} +14 -14
- package/dist/{ton-DGZB7W4U.js → ton-WPTXGLVK.js} +1 -1
- package/dist/{tron-RLIL2FDI.js → tron-6GXBXTR4.js} +1 -1
- package/dist/{tron-ZSXAPZ2C.cjs → tron-WLOF5OUV.cjs} +24 -24
- package/dist/{xrpl-2PKP7HOI.cjs → xrpl-CMNI25BV.cjs} +21 -21
- package/dist/{xrpl-UEC2GYVV.js → xrpl-HEAPEXAM.js} +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
|
|
24
|
+
var _chunkMDLZJGLYcjs = require('./chunk-MDLZJGLY.cjs');
|
|
24
25
|
|
|
25
26
|
// src/drivers/registry.ts
|
|
26
27
|
var byFamily = /* @__PURE__ */ new Map();
|
|
@@ -49,13 +50,13 @@ function resolveNetwork(opts) {
|
|
|
49
50
|
const family = familyForChain(opts.chain);
|
|
50
51
|
const driver = byFamily.get(family);
|
|
51
52
|
if (!driver) {
|
|
52
|
-
throw new (0,
|
|
53
|
+
throw new (0, _chunkMDLZJGLYcjs.UnsupportedNetworkError)(
|
|
53
54
|
`No driver registered for the "${family}" family \u2014 it may not be mounted yet (use the async resolveNetwork()).`
|
|
54
55
|
);
|
|
55
56
|
}
|
|
56
57
|
const net = driver.resolve(opts);
|
|
57
58
|
if (!net) {
|
|
58
|
-
throw new (0,
|
|
59
|
+
throw new (0, _chunkMDLZJGLYcjs.UnsupportedNetworkError)(
|
|
59
60
|
`The ${family} driver didn't recognise this chain input.`
|
|
60
61
|
);
|
|
61
62
|
}
|
|
@@ -311,12 +312,12 @@ function createWalletAdapter(config, resolved) {
|
|
|
311
312
|
}
|
|
312
313
|
const wc = config.walletClient;
|
|
313
314
|
if (!wc.account) {
|
|
314
|
-
throw new (0,
|
|
315
|
+
throw new (0, _chunkMDLZJGLYcjs.WrongFamilyError)(
|
|
315
316
|
"chain is EVM; the provided walletClient has no attached account. Use `createWalletClient({ account, chain, transport })`, or pass { privateKey }."
|
|
316
317
|
);
|
|
317
318
|
}
|
|
318
319
|
if (wc.chain && wc.chain.id !== resolved.chainId) {
|
|
319
|
-
throw new (0,
|
|
320
|
+
throw new (0, _chunkMDLZJGLYcjs.WrongChainError)(
|
|
320
321
|
`PipRailClient: walletClient is on chain ${wc.chain.id} but the SDK was configured with chain ${resolved.chainId}. They must match.`
|
|
321
322
|
);
|
|
322
323
|
}
|
|
@@ -483,24 +484,371 @@ function sumTransfersTo(logs, asset, payTo) {
|
|
|
483
484
|
return { total, from };
|
|
484
485
|
}
|
|
485
486
|
|
|
487
|
+
// src/drivers/evm/exact.ts
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
var EXACT_NETWORK_SLUGS = {
|
|
494
|
+
ethereum: 1,
|
|
495
|
+
base: 8453,
|
|
496
|
+
"base-sepolia": 84532,
|
|
497
|
+
arbitrum: 42161,
|
|
498
|
+
optimism: 10,
|
|
499
|
+
polygon: 137,
|
|
500
|
+
avalanche: 43114
|
|
501
|
+
};
|
|
502
|
+
function chainIdForExactNetwork(slug) {
|
|
503
|
+
return _nullishCoalesce(EXACT_NETWORK_SLUGS[slug], () => ( null));
|
|
504
|
+
}
|
|
505
|
+
var EIP3009_TYPES = {
|
|
506
|
+
TransferWithAuthorization: [
|
|
507
|
+
{ name: "from", type: "address" },
|
|
508
|
+
{ name: "to", type: "address" },
|
|
509
|
+
{ name: "value", type: "uint256" },
|
|
510
|
+
{ name: "validAfter", type: "uint256" },
|
|
511
|
+
{ name: "validBefore", type: "uint256" },
|
|
512
|
+
{ name: "nonce", type: "bytes32" }
|
|
513
|
+
]
|
|
514
|
+
};
|
|
515
|
+
function parseExactRequirements(body) {
|
|
516
|
+
if (!body || typeof body !== "object") return null;
|
|
517
|
+
const accepts = body.accepts;
|
|
518
|
+
if (!Array.isArray(accepts)) return null;
|
|
519
|
+
const out = [];
|
|
520
|
+
for (const raw of accepts) {
|
|
521
|
+
if (!raw || typeof raw !== "object") continue;
|
|
522
|
+
const a = raw;
|
|
523
|
+
if (a.scheme !== "exact") continue;
|
|
524
|
+
const amount = _nullishCoalesce(a.maxAmountRequired, () => ( a.amount));
|
|
525
|
+
if (typeof a.network !== "string" || typeof amount !== "string" || typeof a.asset !== "string" || typeof a.payTo !== "string") {
|
|
526
|
+
continue;
|
|
527
|
+
}
|
|
528
|
+
out.push({
|
|
529
|
+
scheme: "exact",
|
|
530
|
+
network: a.network,
|
|
531
|
+
maxAmountRequired: amount,
|
|
532
|
+
asset: a.asset,
|
|
533
|
+
payTo: a.payTo,
|
|
534
|
+
maxTimeoutSeconds: typeof a.maxTimeoutSeconds === "number" ? a.maxTimeoutSeconds : 600,
|
|
535
|
+
...a.extra && typeof a.extra === "object" ? { extra: a.extra } : {},
|
|
536
|
+
...typeof a.description === "string" ? { description: a.description } : {},
|
|
537
|
+
...typeof a.resource === "string" ? { resource: a.resource } : {}
|
|
538
|
+
});
|
|
539
|
+
}
|
|
540
|
+
return out;
|
|
541
|
+
}
|
|
542
|
+
async function buildExactAuthorization(params) {
|
|
543
|
+
const { account, accept, chainId, now, nonce } = params;
|
|
544
|
+
if (!account.signTypedData) {
|
|
545
|
+
throw new Error("buildExactAuthorization: the account cannot sign EIP-712 typed data.");
|
|
546
|
+
}
|
|
547
|
+
const authorization = {
|
|
548
|
+
from: account.address,
|
|
549
|
+
to: accept.payTo,
|
|
550
|
+
value: accept.maxAmountRequired,
|
|
551
|
+
validAfter: "0",
|
|
552
|
+
validBefore: String(now + accept.maxTimeoutSeconds),
|
|
553
|
+
nonce
|
|
554
|
+
};
|
|
555
|
+
const signature = await account.signTypedData({
|
|
556
|
+
domain: {
|
|
557
|
+
name: _nullishCoalesce(_optionalChain([accept, 'access', _ => _.extra, 'optionalAccess', _2 => _2.name]), () => ( "USD Coin")),
|
|
558
|
+
version: _nullishCoalesce(_optionalChain([accept, 'access', _3 => _3.extra, 'optionalAccess', _4 => _4.version]), () => ( "2")),
|
|
559
|
+
chainId,
|
|
560
|
+
verifyingContract: accept.asset
|
|
561
|
+
},
|
|
562
|
+
types: EIP3009_TYPES,
|
|
563
|
+
primaryType: "TransferWithAuthorization",
|
|
564
|
+
message: {
|
|
565
|
+
from: authorization.from,
|
|
566
|
+
to: authorization.to,
|
|
567
|
+
value: BigInt(authorization.value),
|
|
568
|
+
validAfter: BigInt(authorization.validAfter),
|
|
569
|
+
validBefore: BigInt(authorization.validBefore),
|
|
570
|
+
nonce: authorization.nonce
|
|
571
|
+
}
|
|
572
|
+
});
|
|
573
|
+
return { authorization, signature };
|
|
574
|
+
}
|
|
575
|
+
function base64(str) {
|
|
576
|
+
if (typeof Buffer !== "undefined") return Buffer.from(str, "utf8").toString("base64");
|
|
577
|
+
if (typeof btoa === "function" && typeof TextEncoder !== "undefined") {
|
|
578
|
+
const bytes = new TextEncoder().encode(str);
|
|
579
|
+
let binary = "";
|
|
580
|
+
for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);
|
|
581
|
+
return btoa(binary);
|
|
582
|
+
}
|
|
583
|
+
throw new Error("No base64 encoder available in this runtime.");
|
|
584
|
+
}
|
|
585
|
+
function encodeXPaymentHeader(input) {
|
|
586
|
+
const payload = {
|
|
587
|
+
x402Version: _nullishCoalesce(input.x402Version, () => ( 1)),
|
|
588
|
+
scheme: "exact",
|
|
589
|
+
network: input.network,
|
|
590
|
+
payload: { signature: input.signature, authorization: input.authorization }
|
|
591
|
+
};
|
|
592
|
+
return base64(JSON.stringify(payload));
|
|
593
|
+
}
|
|
594
|
+
var eip3009Abi = [
|
|
595
|
+
{
|
|
596
|
+
type: "function",
|
|
597
|
+
name: "transferWithAuthorization",
|
|
598
|
+
stateMutability: "nonpayable",
|
|
599
|
+
outputs: [],
|
|
600
|
+
inputs: [
|
|
601
|
+
{ name: "from", type: "address" },
|
|
602
|
+
{ name: "to", type: "address" },
|
|
603
|
+
{ name: "value", type: "uint256" },
|
|
604
|
+
{ name: "validAfter", type: "uint256" },
|
|
605
|
+
{ name: "validBefore", type: "uint256" },
|
|
606
|
+
{ name: "nonce", type: "bytes32" },
|
|
607
|
+
{ name: "v", type: "uint8" },
|
|
608
|
+
{ name: "r", type: "bytes32" },
|
|
609
|
+
{ name: "s", type: "bytes32" }
|
|
610
|
+
]
|
|
611
|
+
},
|
|
612
|
+
{
|
|
613
|
+
type: "function",
|
|
614
|
+
name: "transferWithAuthorization",
|
|
615
|
+
stateMutability: "nonpayable",
|
|
616
|
+
outputs: [],
|
|
617
|
+
inputs: [
|
|
618
|
+
{ name: "from", type: "address" },
|
|
619
|
+
{ name: "to", type: "address" },
|
|
620
|
+
{ name: "value", type: "uint256" },
|
|
621
|
+
{ name: "validAfter", type: "uint256" },
|
|
622
|
+
{ name: "validBefore", type: "uint256" },
|
|
623
|
+
{ name: "nonce", type: "bytes32" },
|
|
624
|
+
{ name: "signature", type: "bytes" }
|
|
625
|
+
]
|
|
626
|
+
},
|
|
627
|
+
{
|
|
628
|
+
type: "function",
|
|
629
|
+
name: "authorizationState",
|
|
630
|
+
stateMutability: "view",
|
|
631
|
+
inputs: [
|
|
632
|
+
{ name: "authorizer", type: "address" },
|
|
633
|
+
{ name: "nonce", type: "bytes32" }
|
|
634
|
+
],
|
|
635
|
+
outputs: [{ type: "bool" }]
|
|
636
|
+
},
|
|
637
|
+
{ type: "function", name: "name", stateMutability: "view", inputs: [], outputs: [{ type: "string" }] },
|
|
638
|
+
{ type: "function", name: "version", stateMutability: "view", inputs: [], outputs: [{ type: "string" }] }
|
|
639
|
+
];
|
|
640
|
+
var ZERO_ADDR = "0x0000000000000000000000000000000000000000";
|
|
641
|
+
var ZERO_NONCE = `0x${"00".repeat(32)}`;
|
|
642
|
+
async function readExactDomain(publicClient, asset) {
|
|
643
|
+
if (asset === "native") return null;
|
|
644
|
+
let token;
|
|
645
|
+
try {
|
|
646
|
+
token = _viem.getAddress.call(void 0, asset);
|
|
647
|
+
} catch (e6) {
|
|
648
|
+
return null;
|
|
649
|
+
}
|
|
650
|
+
try {
|
|
651
|
+
const [name, version] = await Promise.all([
|
|
652
|
+
publicClient.readContract({ address: token, abi: eip3009Abi, functionName: "name" }),
|
|
653
|
+
publicClient.readContract({ address: token, abi: eip3009Abi, functionName: "version" }),
|
|
654
|
+
// The EIP-3009 probe: this view exists only on EIP-3009 tokens; it reverts on
|
|
655
|
+
// a plain ERC-20 / USDT, marking the token as not exact-payable.
|
|
656
|
+
publicClient.readContract({
|
|
657
|
+
address: token,
|
|
658
|
+
abi: eip3009Abi,
|
|
659
|
+
functionName: "authorizationState",
|
|
660
|
+
args: [ZERO_ADDR, ZERO_NONCE]
|
|
661
|
+
})
|
|
662
|
+
]);
|
|
663
|
+
if (typeof name !== "string" || typeof version !== "string" || !name || !version) return null;
|
|
664
|
+
return { name, version };
|
|
665
|
+
} catch (e7) {
|
|
666
|
+
return null;
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
function shorten(msg) {
|
|
670
|
+
const oneLine = msg.replace(/\s+/g, " ").trim();
|
|
671
|
+
return oneLine.length > 200 ? `${oneLine.slice(0, 200)}\u2026` : oneLine;
|
|
672
|
+
}
|
|
673
|
+
async function verifyAndSettleExactEvm(input) {
|
|
674
|
+
const { publicClient, walletClient, account, chain, payload, accept } = input;
|
|
675
|
+
const token = _viem.getAddress.call(void 0, accept.asset);
|
|
676
|
+
const payTo = _viem.getAddress.call(void 0, accept.payTo);
|
|
677
|
+
const requiredAmount = BigInt(accept.amount);
|
|
678
|
+
let from;
|
|
679
|
+
let to;
|
|
680
|
+
let value;
|
|
681
|
+
let validAfter;
|
|
682
|
+
let validBefore;
|
|
683
|
+
let nonce;
|
|
684
|
+
try {
|
|
685
|
+
from = _viem.getAddress.call(void 0, payload.authorization.from);
|
|
686
|
+
to = _viem.getAddress.call(void 0, payload.authorization.to);
|
|
687
|
+
value = BigInt(payload.authorization.value);
|
|
688
|
+
validAfter = BigInt(payload.authorization.validAfter);
|
|
689
|
+
validBefore = BigInt(payload.authorization.validBefore);
|
|
690
|
+
nonce = payload.authorization.nonce;
|
|
691
|
+
if (!/^0x[0-9a-fA-F]{64}$/.test(nonce)) throw new Error("nonce must be 32-byte hex");
|
|
692
|
+
if (!/^0x[0-9a-fA-F]+$/.test(payload.signature)) throw new Error("signature must be hex");
|
|
693
|
+
} catch (err) {
|
|
694
|
+
return {
|
|
695
|
+
ok: false,
|
|
696
|
+
error: "signature_invalid",
|
|
697
|
+
detail: `Malformed exact authorization: ${err instanceof Error ? err.message : String(err)}.`
|
|
698
|
+
};
|
|
699
|
+
}
|
|
700
|
+
if (to !== payTo) {
|
|
701
|
+
return { ok: false, error: "wrong_recipient", detail: `Authorization pays ${to}, not ${payTo}.` };
|
|
702
|
+
}
|
|
703
|
+
if (value < requiredAmount) {
|
|
704
|
+
return { ok: false, error: "amount_too_low", detail: `Authorized ${value}, required ${requiredAmount}.` };
|
|
705
|
+
}
|
|
706
|
+
const now = BigInt(Math.floor(Date.now() / 1e3));
|
|
707
|
+
if (validBefore <= now) {
|
|
708
|
+
return { ok: false, error: "payment_expired", detail: `Authorization expired: validBefore ${validBefore} <= now ${now}.` };
|
|
709
|
+
}
|
|
710
|
+
let fromCode;
|
|
711
|
+
try {
|
|
712
|
+
fromCode = await publicClient.getCode({ address: from });
|
|
713
|
+
} catch (e8) {
|
|
714
|
+
return { ok: false, error: "tx_not_found", detail: `Could not read code at ${from} (transient RPC) \u2014 retry.` };
|
|
715
|
+
}
|
|
716
|
+
const isContractWallet = Boolean(fromCode && fromCode !== "0x");
|
|
717
|
+
if (!isContractWallet) {
|
|
718
|
+
let recovered;
|
|
719
|
+
try {
|
|
720
|
+
recovered = await _viem.recoverTypedDataAddress.call(void 0, {
|
|
721
|
+
domain: {
|
|
722
|
+
name: accept.extra.name,
|
|
723
|
+
version: accept.extra.version,
|
|
724
|
+
chainId: chain.id,
|
|
725
|
+
verifyingContract: token
|
|
726
|
+
},
|
|
727
|
+
types: EIP3009_TYPES,
|
|
728
|
+
primaryType: "TransferWithAuthorization",
|
|
729
|
+
message: { from, to, value, validAfter, validBefore, nonce },
|
|
730
|
+
signature: payload.signature
|
|
731
|
+
});
|
|
732
|
+
} catch (err) {
|
|
733
|
+
return { ok: false, error: "signature_invalid", detail: `Not a valid EIP-712 signature: ${shorten(err instanceof Error ? err.message : String(err))}.` };
|
|
734
|
+
}
|
|
735
|
+
if (recovered !== from) {
|
|
736
|
+
return { ok: false, error: "signature_invalid", detail: `Signature recovered to ${recovered}, not the authorizer ${from}.` };
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
try {
|
|
740
|
+
const used = await publicClient.readContract({
|
|
741
|
+
address: token,
|
|
742
|
+
abi: eip3009Abi,
|
|
743
|
+
functionName: "authorizationState",
|
|
744
|
+
args: [from, nonce]
|
|
745
|
+
});
|
|
746
|
+
if (used) {
|
|
747
|
+
return { ok: false, error: "tx_already_used", detail: `Authorization nonce ${nonce} already used or canceled on-chain.` };
|
|
748
|
+
}
|
|
749
|
+
} catch (e9) {
|
|
750
|
+
return { ok: false, error: "tx_not_found", detail: "Could not read authorizationState (transient RPC) \u2014 retry." };
|
|
751
|
+
}
|
|
752
|
+
const baseArgs = [from, to, value, validAfter, validBefore, nonce];
|
|
753
|
+
const isEcdsa = !isContractWallet && payload.signature.length - 2 === 130;
|
|
754
|
+
let writeArgs;
|
|
755
|
+
if (isEcdsa) {
|
|
756
|
+
const { r, s, yParity } = _viem.parseSignature.call(void 0, payload.signature);
|
|
757
|
+
writeArgs = [...baseArgs, BigInt(yParity + 27), r, s];
|
|
758
|
+
} else {
|
|
759
|
+
writeArgs = [...baseArgs, payload.signature];
|
|
760
|
+
}
|
|
761
|
+
try {
|
|
762
|
+
await publicClient.simulateContract({
|
|
763
|
+
account,
|
|
764
|
+
address: token,
|
|
765
|
+
abi: eip3009Abi,
|
|
766
|
+
functionName: "transferWithAuthorization",
|
|
767
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
768
|
+
args: writeArgs
|
|
769
|
+
});
|
|
770
|
+
} catch (err) {
|
|
771
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
772
|
+
if (/used or canceled/i.test(msg)) return { ok: false, error: "tx_already_used", detail: "Authorization is used or canceled." };
|
|
773
|
+
if (/expired|not yet valid/i.test(msg)) return { ok: false, error: "payment_expired", detail: shorten(msg) };
|
|
774
|
+
if (/invalid signature/i.test(msg)) return { ok: false, error: "signature_invalid", detail: shorten(msg) };
|
|
775
|
+
return { ok: false, error: "tx_reverted", detail: `transferWithAuthorization would revert: ${shorten(msg)}` };
|
|
776
|
+
}
|
|
777
|
+
let txHash;
|
|
778
|
+
try {
|
|
779
|
+
txHash = await walletClient.writeContract({
|
|
780
|
+
account,
|
|
781
|
+
chain,
|
|
782
|
+
address: token,
|
|
783
|
+
abi: eip3009Abi,
|
|
784
|
+
functionName: "transferWithAuthorization",
|
|
785
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
786
|
+
args: writeArgs
|
|
787
|
+
});
|
|
788
|
+
} catch (err) {
|
|
789
|
+
throw new (0, _chunkMDLZJGLYcjs.SettlementError)(
|
|
790
|
+
`exact settle: the merchant relayer failed to broadcast transferWithAuthorization (${shorten(err instanceof Error ? err.message : String(err))}). The payer's authorization is still valid and unused \u2014 fund/fix the relayer and the payer can retry.`,
|
|
791
|
+
{ cause: err }
|
|
792
|
+
);
|
|
793
|
+
}
|
|
794
|
+
try {
|
|
795
|
+
const confirmations = _nullishCoalesce(accept.extra.minConfirmations, () => ( 1));
|
|
796
|
+
const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash, confirmations });
|
|
797
|
+
if (receipt.status !== "success") {
|
|
798
|
+
return { ok: false, error: "tx_reverted", detail: `Settlement tx ${txHash} reverted on-chain.` };
|
|
799
|
+
}
|
|
800
|
+
} catch (err) {
|
|
801
|
+
throw new (0, _chunkMDLZJGLYcjs.SettlementError)(
|
|
802
|
+
`exact settle: broadcast ${txHash} but couldn't confirm it (${shorten(err instanceof Error ? err.message : String(err))}).`,
|
|
803
|
+
{ cause: err }
|
|
804
|
+
);
|
|
805
|
+
}
|
|
806
|
+
return {
|
|
807
|
+
ok: true,
|
|
808
|
+
receipt: {
|
|
809
|
+
scheme: "exact",
|
|
810
|
+
success: true,
|
|
811
|
+
network: accept.network,
|
|
812
|
+
transaction: txHash,
|
|
813
|
+
asset: accept.asset,
|
|
814
|
+
amount: accept.amount,
|
|
815
|
+
payer: from,
|
|
816
|
+
payTo: accept.payTo,
|
|
817
|
+
verifiedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
818
|
+
}
|
|
819
|
+
};
|
|
820
|
+
}
|
|
821
|
+
|
|
486
822
|
// src/x402.ts
|
|
487
823
|
var HEADER_REQUIRED = "payment-required";
|
|
488
824
|
var HEADER_SIGNATURE = "payment-signature";
|
|
489
825
|
var HEADER_RESPONSE = "payment-response";
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
if (typeof Buffer !== "undefined") return Buffer.from(b64, "base64").toString("utf8");
|
|
493
|
-
throw new Error("No base64 decoder available in this runtime.");
|
|
494
|
-
}
|
|
826
|
+
var HEADER_SIGNATURE_V1 = "x-payment";
|
|
827
|
+
var HEADER_RESPONSE_V1 = "x-payment-response";
|
|
495
828
|
function encodeBase64(str) {
|
|
496
|
-
if (typeof btoa === "function") return btoa(str);
|
|
497
829
|
if (typeof Buffer !== "undefined") return Buffer.from(str, "utf8").toString("base64");
|
|
830
|
+
if (typeof btoa === "function" && typeof TextEncoder !== "undefined") {
|
|
831
|
+
const bytes = new TextEncoder().encode(str);
|
|
832
|
+
let binary = "";
|
|
833
|
+
for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);
|
|
834
|
+
return btoa(binary);
|
|
835
|
+
}
|
|
498
836
|
throw new Error("No base64 encoder available in this runtime.");
|
|
499
837
|
}
|
|
838
|
+
function decodeBase64(b64) {
|
|
839
|
+
if (typeof Buffer !== "undefined") return Buffer.from(b64, "base64").toString("utf8");
|
|
840
|
+
if (typeof atob === "function" && typeof TextDecoder !== "undefined") {
|
|
841
|
+
const binary = atob(b64);
|
|
842
|
+
const bytes = new Uint8Array(binary.length);
|
|
843
|
+
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
844
|
+
return new TextDecoder().decode(bytes);
|
|
845
|
+
}
|
|
846
|
+
throw new Error("No base64 decoder available in this runtime.");
|
|
847
|
+
}
|
|
500
848
|
function fromBase64Json(b64) {
|
|
501
849
|
try {
|
|
502
850
|
return JSON.parse(decodeBase64(b64));
|
|
503
|
-
} catch (
|
|
851
|
+
} catch (e10) {
|
|
504
852
|
return null;
|
|
505
853
|
}
|
|
506
854
|
}
|
|
@@ -534,7 +882,7 @@ async function parseChallenge(response) {
|
|
|
534
882
|
try {
|
|
535
883
|
const body = await response.clone().json();
|
|
536
884
|
if (isValidChallenge(body)) return body;
|
|
537
|
-
} catch (
|
|
885
|
+
} catch (e11) {
|
|
538
886
|
}
|
|
539
887
|
return null;
|
|
540
888
|
}
|
|
@@ -549,7 +897,7 @@ function parseSignatureHeader(value) {
|
|
|
549
897
|
if (!parsed || typeof parsed !== "object") return null;
|
|
550
898
|
const v = parsed;
|
|
551
899
|
const accepted = v.accepted;
|
|
552
|
-
const scheme = _nullishCoalesce(_optionalChain([accepted, 'optionalAccess',
|
|
900
|
+
const scheme = _nullishCoalesce(_optionalChain([accepted, 'optionalAccess', _5 => _5.scheme]), () => ( v.scheme));
|
|
553
901
|
if (scheme !== "onchain-proof") return null;
|
|
554
902
|
const payload = v.payload;
|
|
555
903
|
if (!payload || typeof payload.txHash !== "string" || typeof payload.nonce !== "string") {
|
|
@@ -557,6 +905,36 @@ function parseSignatureHeader(value) {
|
|
|
557
905
|
}
|
|
558
906
|
return parsed;
|
|
559
907
|
}
|
|
908
|
+
function parseExactPaymentHeader(value) {
|
|
909
|
+
const parsed = fromBase64Json(value);
|
|
910
|
+
if (!parsed || typeof parsed !== "object") return null;
|
|
911
|
+
const v = parsed;
|
|
912
|
+
const accepted = _nullishCoalesce(v.accepted, () => ( null));
|
|
913
|
+
const scheme = _nullishCoalesce(_optionalChain([accepted, 'optionalAccess', _6 => _6.scheme]), () => ( v.scheme));
|
|
914
|
+
if (scheme !== "exact") return null;
|
|
915
|
+
const network = _nullishCoalesce(_optionalChain([accepted, 'optionalAccess', _7 => _7.network]), () => ( v.network));
|
|
916
|
+
if (typeof network !== "string") return null;
|
|
917
|
+
const payload = v.payload;
|
|
918
|
+
if (!payload || typeof payload !== "object") return null;
|
|
919
|
+
const signature = payload.signature;
|
|
920
|
+
const authorization = payload.authorization;
|
|
921
|
+
if (typeof signature !== "string" || !authorization || typeof authorization !== "object") return null;
|
|
922
|
+
for (const k of ["from", "to", "value", "validAfter", "validBefore", "nonce"]) {
|
|
923
|
+
if (typeof authorization[k] !== "string") return null;
|
|
924
|
+
}
|
|
925
|
+
const x402Version = typeof v.x402Version === "number" ? v.x402Version : 2;
|
|
926
|
+
const asset = accepted && typeof accepted.asset === "string" ? accepted.asset : void 0;
|
|
927
|
+
return {
|
|
928
|
+
x402Version,
|
|
929
|
+
network,
|
|
930
|
+
...asset ? { asset } : {},
|
|
931
|
+
payload: {
|
|
932
|
+
signature,
|
|
933
|
+
authorization
|
|
934
|
+
},
|
|
935
|
+
raw: v
|
|
936
|
+
};
|
|
937
|
+
}
|
|
560
938
|
function isValidChallenge(value) {
|
|
561
939
|
if (!value || typeof value !== "object") return false;
|
|
562
940
|
const v = value;
|
|
@@ -568,7 +946,7 @@ function isValidChallenge(value) {
|
|
|
568
946
|
function isValidReceipt(value) {
|
|
569
947
|
if (!value || typeof value !== "object") return false;
|
|
570
948
|
const v = value;
|
|
571
|
-
if (v.scheme !== "onchain-proof") return false;
|
|
949
|
+
if (v.scheme !== "onchain-proof" && v.scheme !== "exact") return false;
|
|
572
950
|
if (typeof v.transaction !== "string" && typeof v.txHash !== "string") return false;
|
|
573
951
|
if (typeof v.payer !== "string") return false;
|
|
574
952
|
return true;
|
|
@@ -591,7 +969,7 @@ var evmDriver = {
|
|
|
591
969
|
let resolved;
|
|
592
970
|
try {
|
|
593
971
|
resolved = resolveChain(opts.chain, opts.rpcUrl);
|
|
594
|
-
} catch (
|
|
972
|
+
} catch (e12) {
|
|
595
973
|
return null;
|
|
596
974
|
}
|
|
597
975
|
return makeEvmNetwork(resolved);
|
|
@@ -619,15 +997,15 @@ function makeEvmNetwork(resolved) {
|
|
|
619
997
|
const info = resolved.tokens[token.toUpperCase()];
|
|
620
998
|
if (!info) {
|
|
621
999
|
const known = Object.keys(resolved.tokens).join(", ") || "(none built in)";
|
|
622
|
-
throw new (0,
|
|
1000
|
+
throw new (0, _chunkMDLZJGLYcjs.UnknownTokenError)(
|
|
623
1001
|
`token "${token}" isn't built in for ${resolved.chain.name} (known: ${known}). Pass { address, decimals } instead, or use 'native'.`
|
|
624
1002
|
);
|
|
625
1003
|
}
|
|
626
1004
|
return { asset: info.address, decimals: info.decimals, symbol: info.symbol };
|
|
627
1005
|
}
|
|
628
|
-
|
|
1006
|
+
_chunkMDLZJGLYcjs.rejectForeignToken.call(void 0, token, "evm", network);
|
|
629
1007
|
if (!("address" in token)) {
|
|
630
|
-
throw new (0,
|
|
1008
|
+
throw new (0, _chunkMDLZJGLYcjs.WrongFamilyError)(
|
|
631
1009
|
`chain ${network} is EVM; a custom token must be { address, decimals }.`
|
|
632
1010
|
);
|
|
633
1011
|
}
|
|
@@ -647,7 +1025,7 @@ function makeEvmNetwork(resolved) {
|
|
|
647
1025
|
let normalized;
|
|
648
1026
|
try {
|
|
649
1027
|
normalized = _viem.getAddress.call(void 0, asset);
|
|
650
|
-
} catch (
|
|
1028
|
+
} catch (e13) {
|
|
651
1029
|
return null;
|
|
652
1030
|
}
|
|
653
1031
|
for (const info of Object.values(resolved.tokens)) {
|
|
@@ -659,14 +1037,14 @@ function makeEvmNetwork(resolved) {
|
|
|
659
1037
|
},
|
|
660
1038
|
assertValidPayTo(payTo) {
|
|
661
1039
|
if (!_viem.isAddress.call(void 0, payTo)) {
|
|
662
|
-
throw new (0,
|
|
1040
|
+
throw new (0, _chunkMDLZJGLYcjs.WrongFamilyError)(
|
|
663
1041
|
`chain ${network} is EVM, but payTo "${payTo}" is not a valid 0x address.`
|
|
664
1042
|
);
|
|
665
1043
|
}
|
|
666
1044
|
},
|
|
667
1045
|
bindWallet(wallet) {
|
|
668
1046
|
if (typeof wallet !== "object" || wallet === null || !("privateKey" in wallet) && !("walletClient" in wallet)) {
|
|
669
|
-
throw new (0,
|
|
1047
|
+
throw new (0, _chunkMDLZJGLYcjs.WrongFamilyError)(
|
|
670
1048
|
`chain ${network} is EVM; wallet must be { privateKey } or { walletClient }.`
|
|
671
1049
|
);
|
|
672
1050
|
}
|
|
@@ -683,12 +1061,12 @@ function makeEvmNetwork(resolved) {
|
|
|
683
1061
|
});
|
|
684
1062
|
} catch (err) {
|
|
685
1063
|
if (isViemInsufficientFunds(err)) {
|
|
686
|
-
throw new (0,
|
|
1064
|
+
throw new (0, _chunkMDLZJGLYcjs.InsufficientFundsError)(
|
|
687
1065
|
err instanceof Error ? err.message : "Insufficient funds for payment.",
|
|
688
1066
|
{ cause: err }
|
|
689
1067
|
);
|
|
690
1068
|
}
|
|
691
|
-
throw _nullishCoalesce(
|
|
1069
|
+
throw _nullishCoalesce(_chunkMDLZJGLYcjs.toInsufficientFundsError.call(void 0, err), () => ( err));
|
|
692
1070
|
}
|
|
693
1071
|
},
|
|
694
1072
|
async confirm(ref, minConfirmations) {
|
|
@@ -699,7 +1077,7 @@ function makeEvmNetwork(resolved) {
|
|
|
699
1077
|
});
|
|
700
1078
|
return { height: receipt.blockNumber.toString() };
|
|
701
1079
|
} catch (err) {
|
|
702
|
-
throw new (0,
|
|
1080
|
+
throw new (0, _chunkMDLZJGLYcjs.ConfirmationTimeoutError)(
|
|
703
1081
|
`EVM tx ${ref} did not reach ${minConfirmations} confirmation(s) in time.`,
|
|
704
1082
|
{ cause: err }
|
|
705
1083
|
);
|
|
@@ -710,16 +1088,16 @@ function makeEvmNetwork(resolved) {
|
|
|
710
1088
|
const gasLimit = accept.asset === "native" ? 21000n : 65000n;
|
|
711
1089
|
try {
|
|
712
1090
|
const gasPrice = await publicClient.getGasPrice();
|
|
713
|
-
return
|
|
1091
|
+
return _chunkMDLZJGLYcjs.nativeCost.call(void 0, {
|
|
714
1092
|
symbol,
|
|
715
1093
|
decimals,
|
|
716
1094
|
fee: gasPrice * gasLimit,
|
|
717
1095
|
basis: "estimated",
|
|
718
1096
|
detail: `~${gasLimit} gas @ ${gasPrice} wei/gas`
|
|
719
1097
|
});
|
|
720
|
-
} catch (
|
|
1098
|
+
} catch (e14) {
|
|
721
1099
|
const gasPrice = 5000000000n;
|
|
722
|
-
return
|
|
1100
|
+
return _chunkMDLZJGLYcjs.nativeCost.call(void 0, {
|
|
723
1101
|
symbol,
|
|
724
1102
|
decimals,
|
|
725
1103
|
fee: gasPrice * gasLimit,
|
|
@@ -740,7 +1118,7 @@ function makeEvmNetwork(resolved) {
|
|
|
740
1118
|
functionName: "balanceOf",
|
|
741
1119
|
args: [owner]
|
|
742
1120
|
});
|
|
743
|
-
} catch (
|
|
1121
|
+
} catch (e15) {
|
|
744
1122
|
token = null;
|
|
745
1123
|
}
|
|
746
1124
|
return { token, native };
|
|
@@ -767,6 +1145,21 @@ function makeEvmNetwork(resolved) {
|
|
|
767
1145
|
accept,
|
|
768
1146
|
minConfirmations: accept.extra.minConfirmations
|
|
769
1147
|
});
|
|
1148
|
+
},
|
|
1149
|
+
// Standard x402 `exact` rail (EIP-3009), seller side — EVM only.
|
|
1150
|
+
async exactDomain(asset) {
|
|
1151
|
+
return readExactDomain(publicClient, asset);
|
|
1152
|
+
},
|
|
1153
|
+
async settleExactSelf({ relayer, payload, accept }) {
|
|
1154
|
+
const a = relayer._native;
|
|
1155
|
+
return verifyAndSettleExactEvm({
|
|
1156
|
+
publicClient,
|
|
1157
|
+
walletClient: a.walletClient,
|
|
1158
|
+
account: a.account,
|
|
1159
|
+
chain: resolved.chain,
|
|
1160
|
+
payload,
|
|
1161
|
+
accept
|
|
1162
|
+
});
|
|
770
1163
|
}
|
|
771
1164
|
};
|
|
772
1165
|
}
|
|
@@ -783,9 +1176,9 @@ var loaders = {
|
|
|
783
1176
|
solana: async () => {
|
|
784
1177
|
let mod;
|
|
785
1178
|
try {
|
|
786
|
-
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./solana-
|
|
1179
|
+
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./solana-PU7N2M64.cjs")));
|
|
787
1180
|
} catch (cause) {
|
|
788
|
-
throw new (0,
|
|
1181
|
+
throw new (0, _chunkMDLZJGLYcjs.MissingDriverError)(
|
|
789
1182
|
`Solana selected, but its packages aren't installed. Run: npm install @solana/web3.js @solana/spl-token bs58`,
|
|
790
1183
|
{ cause }
|
|
791
1184
|
);
|
|
@@ -795,9 +1188,9 @@ var loaders = {
|
|
|
795
1188
|
ton: async () => {
|
|
796
1189
|
let mod;
|
|
797
1190
|
try {
|
|
798
|
-
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./ton-
|
|
1191
|
+
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./ton-VK6KRJHP.cjs")));
|
|
799
1192
|
} catch (cause) {
|
|
800
|
-
throw new (0,
|
|
1193
|
+
throw new (0, _chunkMDLZJGLYcjs.MissingDriverError)(
|
|
801
1194
|
`TON selected, but its packages aren't installed. Run: npm install @ton/ton @ton/core @ton/crypto`,
|
|
802
1195
|
{ cause }
|
|
803
1196
|
);
|
|
@@ -807,9 +1200,9 @@ var loaders = {
|
|
|
807
1200
|
stellar: async () => {
|
|
808
1201
|
let mod;
|
|
809
1202
|
try {
|
|
810
|
-
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./stellar-
|
|
1203
|
+
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./stellar-VDQOFQEO.cjs")));
|
|
811
1204
|
} catch (cause) {
|
|
812
|
-
throw new (0,
|
|
1205
|
+
throw new (0, _chunkMDLZJGLYcjs.MissingDriverError)(
|
|
813
1206
|
`Stellar selected, but its package isn't installed. Run: npm install @stellar/stellar-sdk`,
|
|
814
1207
|
{ cause }
|
|
815
1208
|
);
|
|
@@ -819,9 +1212,9 @@ var loaders = {
|
|
|
819
1212
|
xrpl: async () => {
|
|
820
1213
|
let mod;
|
|
821
1214
|
try {
|
|
822
|
-
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./xrpl-
|
|
1215
|
+
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./xrpl-CMNI25BV.cjs")));
|
|
823
1216
|
} catch (cause) {
|
|
824
|
-
throw new (0,
|
|
1217
|
+
throw new (0, _chunkMDLZJGLYcjs.MissingDriverError)(
|
|
825
1218
|
`XRPL selected, but its package isn't installed. Run: npm install xrpl`,
|
|
826
1219
|
{ cause }
|
|
827
1220
|
);
|
|
@@ -831,9 +1224,9 @@ var loaders = {
|
|
|
831
1224
|
tron: async () => {
|
|
832
1225
|
let mod;
|
|
833
1226
|
try {
|
|
834
|
-
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./tron-
|
|
1227
|
+
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./tron-WLOF5OUV.cjs")));
|
|
835
1228
|
} catch (cause) {
|
|
836
|
-
throw new (0,
|
|
1229
|
+
throw new (0, _chunkMDLZJGLYcjs.MissingDriverError)(
|
|
837
1230
|
`Tron selected, but its package isn't installed. Run: npm install tronweb`,
|
|
838
1231
|
{ cause }
|
|
839
1232
|
);
|
|
@@ -843,9 +1236,9 @@ var loaders = {
|
|
|
843
1236
|
sui: async () => {
|
|
844
1237
|
let mod;
|
|
845
1238
|
try {
|
|
846
|
-
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./sui-
|
|
1239
|
+
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./sui-FKSMLKRF.cjs")));
|
|
847
1240
|
} catch (cause) {
|
|
848
|
-
throw new (0,
|
|
1241
|
+
throw new (0, _chunkMDLZJGLYcjs.MissingDriverError)(
|
|
849
1242
|
`Sui selected, but its package isn't installed. Run: npm install @mysten/sui`,
|
|
850
1243
|
{ cause }
|
|
851
1244
|
);
|
|
@@ -855,9 +1248,9 @@ var loaders = {
|
|
|
855
1248
|
near: async () => {
|
|
856
1249
|
let mod;
|
|
857
1250
|
try {
|
|
858
|
-
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./near-
|
|
1251
|
+
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./near-7ZDNISUX.cjs")));
|
|
859
1252
|
} catch (cause) {
|
|
860
|
-
throw new (0,
|
|
1253
|
+
throw new (0, _chunkMDLZJGLYcjs.MissingDriverError)(
|
|
861
1254
|
`NEAR selected, but its package isn't installed. Run: npm install near-api-js`,
|
|
862
1255
|
{ cause }
|
|
863
1256
|
);
|
|
@@ -867,9 +1260,9 @@ var loaders = {
|
|
|
867
1260
|
aptos: async () => {
|
|
868
1261
|
let mod;
|
|
869
1262
|
try {
|
|
870
|
-
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./aptos-
|
|
1263
|
+
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./aptos-YT7SXWPF.cjs")));
|
|
871
1264
|
} catch (cause) {
|
|
872
|
-
throw new (0,
|
|
1265
|
+
throw new (0, _chunkMDLZJGLYcjs.MissingDriverError)(
|
|
873
1266
|
`Aptos selected, but its package isn't installed. Run: npm install @aptos-labs/ts-sdk`,
|
|
874
1267
|
{ cause }
|
|
875
1268
|
);
|
|
@@ -879,9 +1272,9 @@ var loaders = {
|
|
|
879
1272
|
algorand: async () => {
|
|
880
1273
|
let mod;
|
|
881
1274
|
try {
|
|
882
|
-
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./algorand-
|
|
1275
|
+
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./algorand-MXUSKX46.cjs")));
|
|
883
1276
|
} catch (cause) {
|
|
884
|
-
throw new (0,
|
|
1277
|
+
throw new (0, _chunkMDLZJGLYcjs.MissingDriverError)(
|
|
885
1278
|
`Algorand selected, but its package isn't installed. Run: npm install algosdk`,
|
|
886
1279
|
{ cause }
|
|
887
1280
|
);
|
|
@@ -912,6 +1305,42 @@ async function resolveNetwork2(opts) {
|
|
|
912
1305
|
}
|
|
913
1306
|
|
|
914
1307
|
// src/indexes.ts
|
|
1308
|
+
var DIRECTORY_INFO = {
|
|
1309
|
+
"402index": {
|
|
1310
|
+
source: "402index",
|
|
1311
|
+
review: "probe-sync",
|
|
1312
|
+
auth: "none",
|
|
1313
|
+
chains: null,
|
|
1314
|
+
onSuccess: "pending-review",
|
|
1315
|
+
readByDiscover: true,
|
|
1316
|
+
caveat: "402 Index probes your URL on submit, then lists it as PENDING REVIEW \u2014 a self-registered resource is NOT in search until approved. Verify your domain on 402index.io for instant approval; otherwise it appears after manual review, so retry discover() later."
|
|
1317
|
+
},
|
|
1318
|
+
x402scan: {
|
|
1319
|
+
source: "x402scan",
|
|
1320
|
+
review: "probe-sync",
|
|
1321
|
+
auth: "siwx",
|
|
1322
|
+
chains: ["eip155:8453", "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"],
|
|
1323
|
+
onSuccess: "live",
|
|
1324
|
+
readByDiscover: false,
|
|
1325
|
+
caveat: "x402scan lists Base/Solana only, needs one wallet signature (SIWX), and requires a resolvable input schema (from /openapi.json or the bazaar extension in the 402 body). It goes live on x402scan.com immediately on success \u2014 but discover() does NOT read x402scan, so the listing won't appear in discover() results."
|
|
1326
|
+
},
|
|
1327
|
+
bazaar: {
|
|
1328
|
+
source: "bazaar",
|
|
1329
|
+
review: "settle-coupled",
|
|
1330
|
+
auth: "facilitator-only",
|
|
1331
|
+
chains: null,
|
|
1332
|
+
onSuccess: "not-listable",
|
|
1333
|
+
readByDiscover: true,
|
|
1334
|
+
caveat: "CDP Bazaar has no register endpoint \u2014 it catalogs a resource only when its own facilitator settles a payment. PipRail verifies locally with no facilitator, so a PipRail resource cannot be listed here (you can still READ Bazaar to find others). List on 402 Index or x402scan instead."
|
|
1335
|
+
}
|
|
1336
|
+
};
|
|
1337
|
+
function getDirectoryInfo(source) {
|
|
1338
|
+
return DIRECTORY_INFO[source];
|
|
1339
|
+
}
|
|
1340
|
+
function decorateOutcome(o) {
|
|
1341
|
+
const info = DIRECTORY_INFO[o.source];
|
|
1342
|
+
return { ...o, visibility: o.ok ? info.onSuccess : "not-listable", note: info.caveat };
|
|
1343
|
+
}
|
|
915
1344
|
var BAZAAR_URL = "https://api.cdp.coinbase.com/platform/v2/x402/discovery/resources";
|
|
916
1345
|
var INDEX402_SEARCH = "https://402index.io/api/v1/services";
|
|
917
1346
|
var INDEX402_REGISTER = "https://402index.io/api/v1/register";
|
|
@@ -960,7 +1389,7 @@ async function searchOpenIndexes(opts = {}) {
|
|
|
960
1389
|
async function safeSearch(run) {
|
|
961
1390
|
try {
|
|
962
1391
|
return await run();
|
|
963
|
-
} catch (
|
|
1392
|
+
} catch (e16) {
|
|
964
1393
|
return [];
|
|
965
1394
|
}
|
|
966
1395
|
}
|
|
@@ -1064,7 +1493,13 @@ async function register402Index(input) {
|
|
|
1064
1493
|
body: JSON.stringify(payload)
|
|
1065
1494
|
});
|
|
1066
1495
|
if (res.ok) {
|
|
1067
|
-
|
|
1496
|
+
const msg = await readIndexMessage(res);
|
|
1497
|
+
return {
|
|
1498
|
+
source: "402index",
|
|
1499
|
+
ok: true,
|
|
1500
|
+
status: res.status,
|
|
1501
|
+
detail: _nullishCoalesce(msg, () => ( "Registered on 402 Index \u2014 pending review (verify your domain on 402index.io for instant approval)."))
|
|
1502
|
+
};
|
|
1068
1503
|
}
|
|
1069
1504
|
const why = await readIndexError(res);
|
|
1070
1505
|
return {
|
|
@@ -1077,6 +1512,14 @@ async function register402Index(input) {
|
|
|
1077
1512
|
return { source: "402index", ok: false, detail: errMsg(err) };
|
|
1078
1513
|
}
|
|
1079
1514
|
}
|
|
1515
|
+
async function readIndexMessage(res) {
|
|
1516
|
+
try {
|
|
1517
|
+
const body = await res.json();
|
|
1518
|
+
return typeof body.message === "string" && body.message.length > 0 ? body.message : void 0;
|
|
1519
|
+
} catch (e17) {
|
|
1520
|
+
return void 0;
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1080
1523
|
async function readIndexError(res) {
|
|
1081
1524
|
try {
|
|
1082
1525
|
const body = await res.json();
|
|
@@ -1084,7 +1527,7 @@ async function readIndexError(res) {
|
|
|
1084
1527
|
(p) => typeof p === "string" && p.length > 0
|
|
1085
1528
|
);
|
|
1086
1529
|
return parts.length ? [...new Set(parts)].join(" \u2014 ") : void 0;
|
|
1087
|
-
} catch (
|
|
1530
|
+
} catch (e18) {
|
|
1088
1531
|
return void 0;
|
|
1089
1532
|
}
|
|
1090
1533
|
}
|
|
@@ -1140,13 +1583,13 @@ async function readSiwxInfo(res) {
|
|
|
1140
1583
|
try {
|
|
1141
1584
|
const body = await res.json();
|
|
1142
1585
|
const ext = body.extensions;
|
|
1143
|
-
const siwx = _optionalChain([ext, 'optionalAccess',
|
|
1144
|
-
const info = _nullishCoalesce(_optionalChain([siwx, 'optionalAccess',
|
|
1586
|
+
const siwx = _optionalChain([ext, 'optionalAccess', _8 => _8["sign-in-with-x"]]);
|
|
1587
|
+
const info = _nullishCoalesce(_optionalChain([siwx, 'optionalAccess', _9 => _9.info]), () => ( siwx));
|
|
1145
1588
|
if (info && typeof info.domain === "string" && info.domain.length > 0 && typeof info.nonce === "string" && info.nonce.length > 0 && typeof info.uri === "string" && info.uri.length > 0) {
|
|
1146
1589
|
return info;
|
|
1147
1590
|
}
|
|
1148
1591
|
return null;
|
|
1149
|
-
} catch (
|
|
1592
|
+
} catch (e19) {
|
|
1150
1593
|
return null;
|
|
1151
1594
|
}
|
|
1152
1595
|
}
|
|
@@ -1194,7 +1637,7 @@ function mapRails(accepts) {
|
|
|
1194
1637
|
}
|
|
1195
1638
|
function matchesQuery(r, query) {
|
|
1196
1639
|
const q = query.toLowerCase();
|
|
1197
|
-
return r.resource.toLowerCase().includes(q) || (_nullishCoalesce(_optionalChain([r, 'access',
|
|
1640
|
+
return r.resource.toLowerCase().includes(q) || (_nullishCoalesce(_optionalChain([r, 'access', _10 => _10.name, 'optionalAccess', _11 => _11.toLowerCase, 'call', _12 => _12(), 'access', _13 => _13.includes, 'call', _14 => _14(q)]), () => ( false))) || (_nullishCoalesce(_optionalChain([r, 'access', _15 => _15.description, 'optionalAccess', _16 => _16.toLowerCase, 'call', _17 => _17(), 'access', _18 => _18.includes, 'call', _19 => _19(q)]), () => ( false)));
|
|
1198
1641
|
}
|
|
1199
1642
|
function pickString(o, ...keys) {
|
|
1200
1643
|
for (const k of keys) {
|
|
@@ -1226,7 +1669,7 @@ function firstArray(o, ...keys) {
|
|
|
1226
1669
|
function hostOf(url) {
|
|
1227
1670
|
try {
|
|
1228
1671
|
return new URL(url).hostname;
|
|
1229
|
-
} catch (
|
|
1672
|
+
} catch (e20) {
|
|
1230
1673
|
return url;
|
|
1231
1674
|
}
|
|
1232
1675
|
}
|
|
@@ -1286,7 +1729,7 @@ function evaluatePolicy(intent, policy, spentForAssetBase) {
|
|
|
1286
1729
|
}
|
|
1287
1730
|
}
|
|
1288
1731
|
if (policy.maxAmount !== void 0) {
|
|
1289
|
-
const cap =
|
|
1732
|
+
const cap = _chunkMDLZJGLYcjs.floorUnits.call(void 0, policy.maxAmount, intent.decimals);
|
|
1290
1733
|
if (intent.amountBase > cap) {
|
|
1291
1734
|
return deny(
|
|
1292
1735
|
`payment of ${intent.amountBase} base units exceeds policy.maxAmount ` + `(${policy.maxAmount} ${_nullishCoalesce(intent.symbol, () => ( ""))}).`.trimEnd()
|
|
@@ -1294,7 +1737,7 @@ function evaluatePolicy(intent, policy, spentForAssetBase) {
|
|
|
1294
1737
|
}
|
|
1295
1738
|
}
|
|
1296
1739
|
if (policy.maxTotal !== void 0) {
|
|
1297
|
-
const cap =
|
|
1740
|
+
const cap = _chunkMDLZJGLYcjs.floorUnits.call(void 0, policy.maxTotal, intent.decimals);
|
|
1298
1741
|
if (spentForAssetBase + intent.amountBase > cap) {
|
|
1299
1742
|
return deny(
|
|
1300
1743
|
`this payment would push spend on ${_nullishCoalesce(intent.symbol, () => ( intent.asset))} past policy.maxTotal (${policy.maxTotal}); already spent ${spentForAssetBase} base units.`
|
|
@@ -1332,7 +1775,7 @@ var SpendLedger = (_class = class {constructor() { _class.prototype.__init.call(
|
|
|
1332
1775
|
}
|
|
1333
1776
|
/** Running total (base units) already spent on this (network, asset). */
|
|
1334
1777
|
totalFor(network, asset) {
|
|
1335
|
-
return _nullishCoalesce(_optionalChain([this, 'access',
|
|
1778
|
+
return _nullishCoalesce(_optionalChain([this, 'access', _20 => _20.buckets, 'access', _21 => _21.get, 'call', _22 => _22(keyFor(network, asset)), 'optionalAccess', _23 => _23.total]), () => ( 0n));
|
|
1336
1779
|
}
|
|
1337
1780
|
/** An immutable snapshot of all spend so far. */
|
|
1338
1781
|
summary() {
|
|
@@ -1344,7 +1787,7 @@ var SpendLedger = (_class = class {constructor() { _class.prototype.__init.call(
|
|
|
1344
1787
|
symbol: b.symbol,
|
|
1345
1788
|
decimals: b.decimals,
|
|
1346
1789
|
totalBase: b.total.toString(),
|
|
1347
|
-
totalFormatted:
|
|
1790
|
+
totalFormatted: _chunkMDLZJGLYcjs.formatUnits.call(void 0, b.total, b.decimals),
|
|
1348
1791
|
count: b.count
|
|
1349
1792
|
})),
|
|
1350
1793
|
records: [...this.records]
|
|
@@ -1381,7 +1824,7 @@ var PipRailClient = (_class2 = class {
|
|
|
1381
1824
|
safeEmit(event) {
|
|
1382
1825
|
try {
|
|
1383
1826
|
this.onEvent(event);
|
|
1384
|
-
} catch (
|
|
1827
|
+
} catch (e21) {
|
|
1385
1828
|
}
|
|
1386
1829
|
}
|
|
1387
1830
|
/** Auto-mount the chain's driver, resolve the network, and bind the wallet — once. */
|
|
@@ -1406,7 +1849,7 @@ var PipRailClient = (_class2 = class {
|
|
|
1406
1849
|
* as-is) or a plain object (serialised as JSON).
|
|
1407
1850
|
*/
|
|
1408
1851
|
post(url, body, init) {
|
|
1409
|
-
const headers = new Headers(_optionalChain([init, 'optionalAccess',
|
|
1852
|
+
const headers = new Headers(_optionalChain([init, 'optionalAccess', _24 => _24.headers]));
|
|
1410
1853
|
let payload;
|
|
1411
1854
|
if (body === void 0 || body === null) {
|
|
1412
1855
|
payload = void 0;
|
|
@@ -1437,7 +1880,7 @@ var PipRailClient = (_class2 = class {
|
|
|
1437
1880
|
* "0.05 USDC on Base, within budget → pay it." No funds move.
|
|
1438
1881
|
*/
|
|
1439
1882
|
async quote(url, init) {
|
|
1440
|
-
const res = await fetch(url, { ..._nullishCoalesce(init, () => ( {})), method: _nullishCoalesce(_optionalChain([init, 'optionalAccess',
|
|
1883
|
+
const res = await fetch(url, { ..._nullishCoalesce(init, () => ( {})), method: _nullishCoalesce(_optionalChain([init, 'optionalAccess', _25 => _25.method]), () => ( "GET")) });
|
|
1441
1884
|
if (res.status !== 402) return null;
|
|
1442
1885
|
const { quote } = await this.resolveChallenge(url, res);
|
|
1443
1886
|
return quote;
|
|
@@ -1456,7 +1899,7 @@ var PipRailClient = (_class2 = class {
|
|
|
1456
1899
|
* on Tron, where a USD₮ transfer can cost real TRX.
|
|
1457
1900
|
*/
|
|
1458
1901
|
async estimateCost(url, init) {
|
|
1459
|
-
const res = await fetch(url, { ..._nullishCoalesce(init, () => ( {})), method: _nullishCoalesce(_optionalChain([init, 'optionalAccess',
|
|
1902
|
+
const res = await fetch(url, { ..._nullishCoalesce(init, () => ( {})), method: _nullishCoalesce(_optionalChain([init, 'optionalAccess', _26 => _26.method]), () => ( "GET")) });
|
|
1460
1903
|
if (res.status !== 402) return null;
|
|
1461
1904
|
const { net, accept, quote } = await this.resolveChallenge(url, res);
|
|
1462
1905
|
const cost = await net.estimateCost(accept);
|
|
@@ -1487,11 +1930,11 @@ var PipRailClient = (_class2 = class {
|
|
|
1487
1930
|
* the plan yourself. No funds move.
|
|
1488
1931
|
*/
|
|
1489
1932
|
async planPayment(url, init) {
|
|
1490
|
-
const res = await fetch(url, { ..._nullishCoalesce(init, () => ( {})), method: _nullishCoalesce(_optionalChain([init, 'optionalAccess',
|
|
1933
|
+
const res = await fetch(url, { ..._nullishCoalesce(init, () => ( {})), method: _nullishCoalesce(_optionalChain([init, 'optionalAccess', _27 => _27.method]), () => ( "GET")) });
|
|
1491
1934
|
if (res.status !== 402) return null;
|
|
1492
1935
|
const challenge = await parseChallenge(res);
|
|
1493
1936
|
if (!challenge) {
|
|
1494
|
-
throw new (0,
|
|
1937
|
+
throw new (0, _chunkMDLZJGLYcjs.InvalidEnvelopeError)("402 response did not include a parseable x402 challenge.");
|
|
1495
1938
|
}
|
|
1496
1939
|
const { net, wallet } = await this.ensure();
|
|
1497
1940
|
return this.planFromChallenge(net, wallet, challenge, url);
|
|
@@ -1515,9 +1958,15 @@ var PipRailClient = (_class2 = class {
|
|
|
1515
1958
|
*
|
|
1516
1959
|
* Nothing PipRail-hosted: these are third-party open directories. Never throws
|
|
1517
1960
|
* for a read problem — an index that's down or changed simply contributes
|
|
1518
|
-
* nothing. Honest
|
|
1519
|
-
*
|
|
1520
|
-
*
|
|
1961
|
+
* nothing. Honest caveats (see {@link DIRECTORY_INFO}):
|
|
1962
|
+
* - Reads **`bazaar` + `402index`** only — **NOT `x402scan`** (its reads are paid). A
|
|
1963
|
+
* resource you registered on x402scan is live there but will NOT appear here; don't
|
|
1964
|
+
* read that absence as failure. (Passing `sources:['x402scan']` explicitly yields `[]`.)
|
|
1965
|
+
* - A resource just listed via {@link register} may not appear yet — 402 Index reviews
|
|
1966
|
+
* before publishing, so retry with a brief backoff if a fresh listing is missing.
|
|
1967
|
+
* - Results are cross-scheme (mostly the mainstream `exact` scheme); `fetch()` pays
|
|
1968
|
+
* only `onchain-proof` rails directly (pay `exact` resources with the experimental
|
|
1969
|
+
* `drivers/evm/exact.ts`).
|
|
1521
1970
|
*/
|
|
1522
1971
|
async discover(opts = {}) {
|
|
1523
1972
|
const found = await searchOpenIndexes({
|
|
@@ -1542,12 +1991,27 @@ var PipRailClient = (_class2 = class {
|
|
|
1542
1991
|
}
|
|
1543
1992
|
/**
|
|
1544
1993
|
* List a resource you run on the OPEN x402 registries, so agents can find it.
|
|
1545
|
-
* Default target is **402 Index** — one POST, no auth, no signature, no payment
|
|
1546
|
-
*
|
|
1547
|
-
*
|
|
1548
|
-
*
|
|
1549
|
-
*
|
|
1550
|
-
*
|
|
1994
|
+
* Default target is **402 Index** — one POST, no auth, no signature, no payment.
|
|
1995
|
+
* Add `'x402scan'` to also register via SIWX (one wallet signature; EVM + a
|
|
1996
|
+
* Base/Solana rail). Returns one {@link RegisterOutcome} per target — a target the
|
|
1997
|
+
* chain can't satisfy comes back `{ ok:false, detail }`, never a throw. An explicit,
|
|
1998
|
+
* developer-invoked action; it moves no funds, and nothing is PipRail-hosted —
|
|
1999
|
+
* you're listing on third-party open directories.
|
|
2000
|
+
*
|
|
2001
|
+
* **Listing is asynchronous — each outcome carries a `visibility` + `note` so an
|
|
2002
|
+
* agent knows when/where the resource is findable (don't assume `ok:true` means
|
|
2003
|
+
* "searchable now"):**
|
|
2004
|
+
* - **402 Index** → `visibility:'pending-review'`. It probes your URL on submit, then lists it
|
|
2005
|
+
* PENDING REVIEW — not searchable until approved (verify your domain on 402index.io for instant
|
|
2006
|
+
* approval), so `discover()` returns nothing for a fresh listing until then. Retry later.
|
|
2007
|
+
* - **x402scan** → `visibility:'live'`, but **`discover()` does NOT read x402scan** — the
|
|
2008
|
+
* listing is real on x402scan.com yet won't show up in `discover()`. Base/Solana only;
|
|
2009
|
+
* needs a resolvable input schema (`/openapi.json` or the `extensions.bazaar` block).
|
|
2010
|
+
* - **Bazaar** → `visibility:'not-listable'` for PipRail (it lists only what its facilitator
|
|
2011
|
+
* settles; PipRail uses none). You can still READ Bazaar via {@link discover} to find others.
|
|
2012
|
+
*
|
|
2013
|
+
* The per-source facts live in {@link DIRECTORY_INFO} (importable) if you'd rather branch
|
|
2014
|
+
* on them before calling.
|
|
1551
2015
|
*/
|
|
1552
2016
|
async register(url, opts = {}) {
|
|
1553
2017
|
const targets = _nullishCoalesce(opts.targets, () => ( ["402index"]));
|
|
@@ -1586,7 +2050,7 @@ var PipRailClient = (_class2 = class {
|
|
|
1586
2050
|
});
|
|
1587
2051
|
}
|
|
1588
2052
|
}
|
|
1589
|
-
return outcomes;
|
|
2053
|
+
return outcomes.map(decorateOutcome);
|
|
1590
2054
|
}
|
|
1591
2055
|
/**
|
|
1592
2056
|
* The discovery signer for the bound wallet (its address + a message signer),
|
|
@@ -1607,9 +2071,9 @@ var PipRailClient = (_class2 = class {
|
|
|
1607
2071
|
* streams throw `NonReplayableBodyError`.
|
|
1608
2072
|
*/
|
|
1609
2073
|
async fetch(url, init) {
|
|
1610
|
-
const body = _optionalChain([init, 'optionalAccess',
|
|
2074
|
+
const body = _optionalChain([init, 'optionalAccess', _28 => _28.body]);
|
|
1611
2075
|
if (body !== void 0 && body !== null && !isReplayableBodyInit(body)) {
|
|
1612
|
-
throw new (0,
|
|
2076
|
+
throw new (0, _chunkMDLZJGLYcjs.NonReplayableBodyError)(
|
|
1613
2077
|
"fetch(): init.body is not replayable. Pass a string, FormData, URLSearchParams, ArrayBuffer, or Blob \u2014 not a ReadableStream."
|
|
1614
2078
|
);
|
|
1615
2079
|
}
|
|
@@ -1619,11 +2083,11 @@ var PipRailClient = (_class2 = class {
|
|
|
1619
2083
|
const { net, wallet, challenge } = resolved;
|
|
1620
2084
|
let accept = resolved.accept;
|
|
1621
2085
|
let quote = resolved.quote;
|
|
1622
|
-
const autoRoute = _nullishCoalesce(_nullishCoalesce(_optionalChain([init, 'optionalAccess',
|
|
2086
|
+
const autoRoute = _nullishCoalesce(_nullishCoalesce(_optionalChain([init, 'optionalAccess', _29 => _29.autoRoute]), () => ( this.opts.autoRoute)), () => ( false));
|
|
1623
2087
|
if (autoRoute) {
|
|
1624
2088
|
const plan = await this.planFromChallenge(net, wallet, challenge, url);
|
|
1625
2089
|
if (!plan.best) {
|
|
1626
|
-
throw new (0,
|
|
2090
|
+
throw new (0, _chunkMDLZJGLYcjs.PaymentDeclinedError)(_nullishCoalesce(plan.fundingHint, () => ( "No rail is settleable for this payment.")));
|
|
1627
2091
|
}
|
|
1628
2092
|
accept = plan.best.accept;
|
|
1629
2093
|
quote = plan.best.quote;
|
|
@@ -1644,7 +2108,7 @@ var PipRailClient = (_class2 = class {
|
|
|
1644
2108
|
async resolveChallenge(url, response) {
|
|
1645
2109
|
const challenge = await parseChallenge(response);
|
|
1646
2110
|
if (!challenge) {
|
|
1647
|
-
throw new (0,
|
|
2111
|
+
throw new (0, _chunkMDLZJGLYcjs.InvalidEnvelopeError)(
|
|
1648
2112
|
"402 response did not include a parseable x402 challenge."
|
|
1649
2113
|
);
|
|
1650
2114
|
}
|
|
@@ -1652,7 +2116,7 @@ var PipRailClient = (_class2 = class {
|
|
|
1652
2116
|
const candidates = this.gatherCandidates(net, challenge);
|
|
1653
2117
|
if (candidates.length === 0) {
|
|
1654
2118
|
const networks = challenge.accepts.map((a) => a.network).join(", ");
|
|
1655
|
-
throw new (0,
|
|
2119
|
+
throw new (0, _chunkMDLZJGLYcjs.NoCompatibleAcceptError)(
|
|
1656
2120
|
`No accepts[] entry for ${net.network} (challenge offered: ${networks || "none"}).`
|
|
1657
2121
|
);
|
|
1658
2122
|
}
|
|
@@ -1663,7 +2127,10 @@ var PipRailClient = (_class2 = class {
|
|
|
1663
2127
|
const chosen = _nullishCoalesce(priced.find((p) => p.quote.withinPolicy), () => ( priced[0]));
|
|
1664
2128
|
return { net, wallet, accept: chosen.accept, challenge, quote: chosen.quote };
|
|
1665
2129
|
}
|
|
1666
|
-
/** The candidate accepts this client could pay: our scheme, on the bound network.
|
|
2130
|
+
/** The candidate accepts this client could pay: our scheme, on the bound network.
|
|
2131
|
+
* A dual-advertised challenge may also carry standard `exact` rails — the PipRail
|
|
2132
|
+
* client ignores those (it pays the backendless `onchain-proof` rail); the type
|
|
2133
|
+
* predicate narrows the `X402AnyAccept` union to the rails we settle. */
|
|
1667
2134
|
gatherCandidates(net, challenge) {
|
|
1668
2135
|
return challenge.accepts.filter(
|
|
1669
2136
|
(a) => a.scheme === "onchain-proof" && net.supports(a.network)
|
|
@@ -1726,16 +2193,16 @@ var PipRailClient = (_class2 = class {
|
|
|
1726
2193
|
if (isNative) {
|
|
1727
2194
|
if (nativeKnown && bal.native < amount + fee) {
|
|
1728
2195
|
blockers.push("INSUFFICIENT_TOKEN");
|
|
1729
|
-
shortfall.token =
|
|
2196
|
+
shortfall.token = _chunkMDLZJGLYcjs.formatUnits.call(void 0, amount + fee - bal.native, quote.decimals);
|
|
1730
2197
|
}
|
|
1731
2198
|
} else {
|
|
1732
2199
|
if (tokenKnown && bal.token < amount) {
|
|
1733
2200
|
blockers.push("INSUFFICIENT_TOKEN");
|
|
1734
|
-
shortfall.token =
|
|
2201
|
+
shortfall.token = _chunkMDLZJGLYcjs.formatUnits.call(void 0, amount - bal.token, quote.decimals);
|
|
1735
2202
|
}
|
|
1736
2203
|
if (nativeKnown && bal.native < fee) {
|
|
1737
2204
|
blockers.push("INSUFFICIENT_GAS");
|
|
1738
|
-
shortfall.native =
|
|
2205
|
+
shortfall.native = _chunkMDLZJGLYcjs.formatUnits.call(void 0, fee - bal.native, cost.feeDecimals);
|
|
1739
2206
|
} else if (nativeKnown && fee > 0n && bal.native < fee * 3n / 2n) {
|
|
1740
2207
|
warnings.push("THIN_GAS_MARGIN");
|
|
1741
2208
|
}
|
|
@@ -1760,8 +2227,8 @@ var PipRailClient = (_class2 = class {
|
|
|
1760
2227
|
blockers,
|
|
1761
2228
|
warnings,
|
|
1762
2229
|
balance: {
|
|
1763
|
-
token: bal.token != null ?
|
|
1764
|
-
native: bal.native != null ?
|
|
2230
|
+
token: bal.token != null ? _chunkMDLZJGLYcjs.formatUnits.call(void 0, bal.token, quote.decimals) : null,
|
|
2231
|
+
native: bal.native != null ? _chunkMDLZJGLYcjs.formatUnits.call(void 0, bal.native, cost.feeDecimals) : null
|
|
1765
2232
|
},
|
|
1766
2233
|
need: { token: quote.amountFormatted, native: cost.feeFormatted },
|
|
1767
2234
|
...shortfall.token || shortfall.native ? { shortfall } : {},
|
|
@@ -1772,15 +2239,15 @@ var PipRailClient = (_class2 = class {
|
|
|
1772
2239
|
* driver's describeAsset) + the policy verdict + a symbol-mismatch flag. */
|
|
1773
2240
|
buildQuote(net, accept, url, description) {
|
|
1774
2241
|
if (!/^\d+$/.test(accept.amount)) {
|
|
1775
|
-
throw new (0,
|
|
2242
|
+
throw new (0, _chunkMDLZJGLYcjs.InvalidEnvelopeError)(
|
|
1776
2243
|
`challenge amount "${accept.amount}" is not a base-unit integer.`
|
|
1777
2244
|
);
|
|
1778
2245
|
}
|
|
1779
2246
|
const amountBase = BigInt(accept.amount);
|
|
1780
2247
|
const described = net.describeAsset(accept.asset);
|
|
1781
|
-
const decimals = _nullishCoalesce(_optionalChain([described, 'optionalAccess',
|
|
1782
|
-
const symbol = _nullishCoalesce(_optionalChain([described, 'optionalAccess',
|
|
1783
|
-
const amountFormatted =
|
|
2248
|
+
const decimals = _nullishCoalesce(_optionalChain([described, 'optionalAccess', _30 => _30.decimals]), () => ( accept.extra.decimals));
|
|
2249
|
+
const symbol = _nullishCoalesce(_optionalChain([described, 'optionalAccess', _31 => _31.symbol]), () => ( accept.extra.symbol));
|
|
2250
|
+
const amountFormatted = _chunkMDLZJGLYcjs.formatUnits.call(void 0, amountBase, decimals);
|
|
1784
2251
|
const intent = {
|
|
1785
2252
|
host: hostOf2(url),
|
|
1786
2253
|
chain: this.opts.chain,
|
|
@@ -1820,7 +2287,7 @@ var PipRailClient = (_class2 = class {
|
|
|
1820
2287
|
* throwing PaymentDeclinedError, before any funds move. */
|
|
1821
2288
|
async authorize(quote) {
|
|
1822
2289
|
if (!quote.withinPolicy) {
|
|
1823
|
-
throw new (0,
|
|
2290
|
+
throw new (0, _chunkMDLZJGLYcjs.PaymentDeclinedError)(
|
|
1824
2291
|
`Payment refused by policy: ${_nullishCoalesce(quote.policyReason, () => ( "not allowed"))}`
|
|
1825
2292
|
);
|
|
1826
2293
|
}
|
|
@@ -1830,12 +2297,12 @@ var PipRailClient = (_class2 = class {
|
|
|
1830
2297
|
try {
|
|
1831
2298
|
approved = await hook(quote);
|
|
1832
2299
|
} catch (err) {
|
|
1833
|
-
throw new (0,
|
|
2300
|
+
throw new (0, _chunkMDLZJGLYcjs.PaymentDeclinedError)("onBeforePay threw \u2014 refusing to pay.", {
|
|
1834
2301
|
cause: err
|
|
1835
2302
|
});
|
|
1836
2303
|
}
|
|
1837
2304
|
if (!approved) {
|
|
1838
|
-
throw new (0,
|
|
2305
|
+
throw new (0, _chunkMDLZJGLYcjs.PaymentDeclinedError)(
|
|
1839
2306
|
`onBeforePay declined ${quote.amountFormatted} ${_nullishCoalesce(quote.symbol, () => ( ""))}`.trimEnd() + ` on ${quote.network}.`
|
|
1840
2307
|
);
|
|
1841
2308
|
}
|
|
@@ -1859,7 +2326,7 @@ var PipRailClient = (_class2 = class {
|
|
|
1859
2326
|
}
|
|
1860
2327
|
async payAndConfirm(net, wallet, accept) {
|
|
1861
2328
|
if (!net.supports(accept.network)) {
|
|
1862
|
-
throw new (0,
|
|
2329
|
+
throw new (0, _chunkMDLZJGLYcjs.WrongChainError)(
|
|
1863
2330
|
`Challenge expects ${accept.network} but client is on ${net.network}.`
|
|
1864
2331
|
);
|
|
1865
2332
|
}
|
|
@@ -1888,7 +2355,7 @@ var PipRailClient = (_class2 = class {
|
|
|
1888
2355
|
accepted: accept,
|
|
1889
2356
|
payload: { nonce: accept.extra.nonce, txHash: ref }
|
|
1890
2357
|
};
|
|
1891
|
-
const headers = new Headers(_optionalChain([originalInit, 'optionalAccess',
|
|
2358
|
+
const headers = new Headers(_optionalChain([originalInit, 'optionalAccess', _32 => _32.headers]));
|
|
1892
2359
|
headers.set(HEADER_SIGNATURE, buildSignatureHeader(signature));
|
|
1893
2360
|
let lastResponse = null;
|
|
1894
2361
|
let lastReason = null;
|
|
@@ -1903,7 +2370,7 @@ var PipRailClient = (_class2 = class {
|
|
|
1903
2370
|
() => timeoutController.abort(),
|
|
1904
2371
|
this.retryTimeoutMs
|
|
1905
2372
|
);
|
|
1906
|
-
const signal = _optionalChain([originalInit, 'optionalAccess',
|
|
2373
|
+
const signal = _optionalChain([originalInit, 'optionalAccess', _33 => _33.signal]) && typeof AbortSignal.any === "function" ? AbortSignal.any([timeoutController.signal, originalInit.signal]) : timeoutController.signal;
|
|
1907
2374
|
try {
|
|
1908
2375
|
lastResponse = await fetch(url, {
|
|
1909
2376
|
..._nullishCoalesce(originalInit, () => ( {})),
|
|
@@ -1912,7 +2379,7 @@ var PipRailClient = (_class2 = class {
|
|
|
1912
2379
|
});
|
|
1913
2380
|
} catch (err) {
|
|
1914
2381
|
if (timeoutController.signal.aborted) {
|
|
1915
|
-
throw new (0,
|
|
2382
|
+
throw new (0, _chunkMDLZJGLYcjs.PaymentTimeoutError)(
|
|
1916
2383
|
`Server did not respond within ${this.retryTimeoutMs}ms after broadcasting payment ${ref}. Re-verify or re-submit ref=${ref} \u2014 do NOT re-pay.`,
|
|
1917
2384
|
{ cause: err, ref }
|
|
1918
2385
|
);
|
|
@@ -1934,7 +2401,7 @@ var PipRailClient = (_class2 = class {
|
|
|
1934
2401
|
kind: "payment-failed",
|
|
1935
2402
|
reason: `server returned 402 after broadcasting payment ${ref}${unconfirmedNote} (${why})`
|
|
1936
2403
|
});
|
|
1937
|
-
throw new (0,
|
|
2404
|
+
throw new (0, _chunkMDLZJGLYcjs.MaxRetriesExceededError)(
|
|
1938
2405
|
`Server still returned 402 after ${attempts} attempt(s) with on-chain proof ref=${ref}${unconfirmedNote}. Last server rejection: ${why}. Re-verify or re-submit ref=${ref} before retrying \u2014 never re-pay (it would double-spend).`,
|
|
1939
2406
|
{ ref }
|
|
1940
2407
|
);
|
|
@@ -1943,7 +2410,7 @@ var PipRailClient = (_class2 = class {
|
|
|
1943
2410
|
function safeBig(s) {
|
|
1944
2411
|
try {
|
|
1945
2412
|
return BigInt(s);
|
|
1946
|
-
} catch (
|
|
2413
|
+
} catch (e22) {
|
|
1947
2414
|
return 0n;
|
|
1948
2415
|
}
|
|
1949
2416
|
}
|
|
@@ -1976,10 +2443,10 @@ function buildFundingHint(options, chainLabel) {
|
|
|
1976
2443
|
return `Couldn't fully read your wallet on ${chainLabel} (RPC throttled) \u2014 retry; you may already be able to pay ${target.quote.amountFormatted} ${sym}.`;
|
|
1977
2444
|
}
|
|
1978
2445
|
const parts = [];
|
|
1979
|
-
if (target.blockers.includes("INSUFFICIENT_TOKEN") && _optionalChain([target, 'access',
|
|
2446
|
+
if (target.blockers.includes("INSUFFICIENT_TOKEN") && _optionalChain([target, 'access', _34 => _34.shortfall, 'optionalAccess', _35 => _35.token])) {
|
|
1980
2447
|
parts.push(`top up ${target.shortfall.token} ${sym}`);
|
|
1981
2448
|
}
|
|
1982
|
-
if (target.blockers.includes("INSUFFICIENT_GAS") && _optionalChain([target, 'access',
|
|
2449
|
+
if (target.blockers.includes("INSUFFICIENT_GAS") && _optionalChain([target, 'access', _36 => _36.shortfall, 'optionalAccess', _37 => _37.native])) {
|
|
1983
2450
|
parts.push(`add ~${target.shortfall.native} ${target.cost.feeSymbol} for gas`);
|
|
1984
2451
|
}
|
|
1985
2452
|
return parts.length ? `Can't settle on ${chainLabel}: ${parts.join(" and ")} (to pay ${target.quote.amountFormatted} ${sym}).` : `Can't settle on ${chainLabel} for ${target.quote.amountFormatted} ${sym}.`;
|
|
@@ -1993,7 +2460,7 @@ async function planAcross(clients, url, init) {
|
|
|
1993
2460
|
const status = best ? "ready" : options.some((o) => o.state === "unknown") ? "unknown" : "blocked";
|
|
1994
2461
|
return {
|
|
1995
2462
|
url,
|
|
1996
|
-
network: _nullishCoalesce(_optionalChain([best, 'optionalAccess',
|
|
2463
|
+
network: _nullishCoalesce(_optionalChain([best, 'optionalAccess', _38 => _38.accept, 'access', _39 => _39.network]), () => ( live[0].network)),
|
|
1997
2464
|
status,
|
|
1998
2465
|
payable: best !== null,
|
|
1999
2466
|
best,
|
|
@@ -2009,7 +2476,7 @@ function railOnNetwork(rail, matches) {
|
|
|
2009
2476
|
function hostOf2(url) {
|
|
2010
2477
|
try {
|
|
2011
2478
|
return new URL(url).hostname;
|
|
2012
|
-
} catch (
|
|
2479
|
+
} catch (e23) {
|
|
2013
2480
|
return url;
|
|
2014
2481
|
}
|
|
2015
2482
|
}
|
|
@@ -2026,13 +2493,21 @@ function isReplayableBodyInit(value) {
|
|
|
2026
2493
|
async function readInvalidReason(response) {
|
|
2027
2494
|
try {
|
|
2028
2495
|
const body = await response.clone().json();
|
|
2496
|
+
const ext = _optionalChain([body, 'optionalAccess', _40 => _40.extensions]);
|
|
2497
|
+
const piprail = _optionalChain([ext, 'optionalAccess', _41 => _41.piprail]);
|
|
2498
|
+
if (piprail && typeof piprail.code === "string") {
|
|
2499
|
+
return {
|
|
2500
|
+
error: piprail.code,
|
|
2501
|
+
detail: typeof piprail.detail === "string" ? piprail.detail : ""
|
|
2502
|
+
};
|
|
2503
|
+
}
|
|
2029
2504
|
if (body && (body.status === "invalid" || typeof body.error === "string")) {
|
|
2030
2505
|
return {
|
|
2031
2506
|
error: typeof body.error === "string" ? body.error : "no error code",
|
|
2032
2507
|
detail: typeof body.detail === "string" ? body.detail : ""
|
|
2033
2508
|
};
|
|
2034
2509
|
}
|
|
2035
|
-
} catch (
|
|
2510
|
+
} catch (e24) {
|
|
2036
2511
|
}
|
|
2037
2512
|
return null;
|
|
2038
2513
|
}
|
|
@@ -2043,7 +2518,7 @@ async function readBody(res) {
|
|
|
2043
2518
|
if (!text) return null;
|
|
2044
2519
|
try {
|
|
2045
2520
|
return JSON.parse(text);
|
|
2046
|
-
} catch (
|
|
2521
|
+
} catch (e25) {
|
|
2047
2522
|
return text;
|
|
2048
2523
|
}
|
|
2049
2524
|
}
|
|
@@ -2214,7 +2689,7 @@ function paymentTools(client) {
|
|
|
2214
2689
|
receipt: parseReceipt(res)
|
|
2215
2690
|
};
|
|
2216
2691
|
} catch (err) {
|
|
2217
|
-
if (err instanceof
|
|
2692
|
+
if (err instanceof _chunkMDLZJGLYcjs.PaymentDeclinedError) {
|
|
2218
2693
|
return { declined: true, reason: err.message };
|
|
2219
2694
|
}
|
|
2220
2695
|
throw err;
|
|
@@ -2223,7 +2698,7 @@ function paymentTools(client) {
|
|
|
2223
2698
|
},
|
|
2224
2699
|
{
|
|
2225
2700
|
name: "piprail_register",
|
|
2226
|
-
description: "List an x402 payment-gated resource YOU run on the open indexes so other agents can discover it. Default target is 402 Index \u2014 no auth, no signature, no payment;
|
|
2701
|
+
description: "List an x402 payment-gated resource YOU run on the open indexes so other agents can discover it. Default target is 402 Index \u2014 no auth, no signature, no payment; a self-registered listing is pending review (verify your domain on 402index.io for instant approval). Returns one outcome per index ({ source, ok, detail, visibility, note }); a step the chain can't satisfy comes back ok:false with the reason. Moves no funds; nothing is PipRail-hosted.",
|
|
2227
2702
|
annotations: {
|
|
2228
2703
|
title: "Register an x402 endpoint",
|
|
2229
2704
|
readOnlyHint: false,
|
|
@@ -2257,6 +2732,100 @@ function paymentTools(client) {
|
|
|
2257
2732
|
];
|
|
2258
2733
|
}
|
|
2259
2734
|
|
|
2735
|
+
// src/facilitator.ts
|
|
2736
|
+
function safeStringify(value) {
|
|
2737
|
+
return JSON.stringify(value, (_k, v) => typeof v === "bigint" ? v.toString() : v);
|
|
2738
|
+
}
|
|
2739
|
+
function mapReason(reason) {
|
|
2740
|
+
const r = (_nullishCoalesce(reason, () => ( ""))).toLowerCase();
|
|
2741
|
+
if (r.includes("signature")) return "signature_invalid";
|
|
2742
|
+
if (r.includes("recipient")) return "wrong_recipient";
|
|
2743
|
+
if (r.includes("value") || r.includes("amount")) return "amount_too_low";
|
|
2744
|
+
if (r.includes("valid_before") || r.includes("valid_after") || r.includes("expired")) return "payment_expired";
|
|
2745
|
+
if (r.includes("used") || r.includes("replay") || r.includes("nonce") || r.includes("transaction_state")) {
|
|
2746
|
+
return "tx_already_used";
|
|
2747
|
+
}
|
|
2748
|
+
return "tx_reverted";
|
|
2749
|
+
}
|
|
2750
|
+
async function post(url, body, headers) {
|
|
2751
|
+
const res = await fetch(url, {
|
|
2752
|
+
method: "POST",
|
|
2753
|
+
headers: { "content-type": "application/json", ...headers },
|
|
2754
|
+
body: safeStringify(body)
|
|
2755
|
+
});
|
|
2756
|
+
let json = null;
|
|
2757
|
+
try {
|
|
2758
|
+
json = await res.json();
|
|
2759
|
+
} catch (e26) {
|
|
2760
|
+
}
|
|
2761
|
+
return { status: res.status, json };
|
|
2762
|
+
}
|
|
2763
|
+
async function settleViaFacilitator(input) {
|
|
2764
|
+
const base2 = input.url.replace(/\/+$/, "");
|
|
2765
|
+
const body = {
|
|
2766
|
+
x402Version: input.x402Version,
|
|
2767
|
+
paymentPayload: input.paymentPayload,
|
|
2768
|
+
paymentRequirements: input.paymentRequirements
|
|
2769
|
+
};
|
|
2770
|
+
const auth = input.authHeaders ? await input.authHeaders() : {};
|
|
2771
|
+
let verify;
|
|
2772
|
+
try {
|
|
2773
|
+
verify = await post(`${base2}/verify`, body, auth);
|
|
2774
|
+
} catch (err) {
|
|
2775
|
+
throw new (0, _chunkMDLZJGLYcjs.SettlementError)(
|
|
2776
|
+
`exact settle (facilitator ${base2}): /verify request failed (${err instanceof Error ? err.message : String(err)}).`,
|
|
2777
|
+
{ cause: err }
|
|
2778
|
+
);
|
|
2779
|
+
}
|
|
2780
|
+
if (verify.status !== 200) {
|
|
2781
|
+
throw new (0, _chunkMDLZJGLYcjs.SettlementError)(
|
|
2782
|
+
`exact settle (facilitator ${base2}): /verify returned HTTP ${verify.status} (transport/auth error).`
|
|
2783
|
+
);
|
|
2784
|
+
}
|
|
2785
|
+
const vr = _nullishCoalesce(verify.json, () => ( {}));
|
|
2786
|
+
if (vr.isValid === false) {
|
|
2787
|
+
return {
|
|
2788
|
+
ok: false,
|
|
2789
|
+
error: mapReason(vr.invalidReason),
|
|
2790
|
+
detail: `Facilitator rejected the payment: ${_nullishCoalesce(vr.invalidReason, () => ( "invalid"))}${vr.invalidMessage ? ` \u2014 ${vr.invalidMessage}` : ""}.`
|
|
2791
|
+
};
|
|
2792
|
+
}
|
|
2793
|
+
let settle;
|
|
2794
|
+
try {
|
|
2795
|
+
settle = await post(`${base2}/settle`, body, auth);
|
|
2796
|
+
} catch (err) {
|
|
2797
|
+
throw new (0, _chunkMDLZJGLYcjs.SettlementError)(
|
|
2798
|
+
`exact settle (facilitator ${base2}): /settle request failed (${err instanceof Error ? err.message : String(err)}).`,
|
|
2799
|
+
{ cause: err }
|
|
2800
|
+
);
|
|
2801
|
+
}
|
|
2802
|
+
if (settle.status !== 200) {
|
|
2803
|
+
throw new (0, _chunkMDLZJGLYcjs.SettlementError)(
|
|
2804
|
+
`exact settle (facilitator ${base2}): /settle returned HTTP ${settle.status} (transport/auth error).`
|
|
2805
|
+
);
|
|
2806
|
+
}
|
|
2807
|
+
const sr = _nullishCoalesce(settle.json, () => ( {}));
|
|
2808
|
+
if (!sr.success) {
|
|
2809
|
+
return {
|
|
2810
|
+
ok: false,
|
|
2811
|
+
error: mapReason(sr.errorReason),
|
|
2812
|
+
detail: `Facilitator settlement failed: ${_nullishCoalesce(sr.errorReason, () => ( "unknown"))}${sr.errorMessage ? ` \u2014 ${sr.errorMessage}` : ""}.`
|
|
2813
|
+
};
|
|
2814
|
+
}
|
|
2815
|
+
const receipt = {
|
|
2816
|
+
scheme: "exact",
|
|
2817
|
+
success: true,
|
|
2818
|
+
network: input.receipt.network,
|
|
2819
|
+
transaction: sr.transaction,
|
|
2820
|
+
asset: input.receipt.asset,
|
|
2821
|
+
amount: input.receipt.amount,
|
|
2822
|
+
payer: _nullishCoalesce(_nullishCoalesce(sr.payer, () => ( input.payerHint)), () => ( "")),
|
|
2823
|
+
payTo: input.receipt.payTo,
|
|
2824
|
+
verifiedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2825
|
+
};
|
|
2826
|
+
return { ok: true, receipt };
|
|
2827
|
+
}
|
|
2828
|
+
|
|
2260
2829
|
// src/server.ts
|
|
2261
2830
|
function toInvalidBody(result) {
|
|
2262
2831
|
return { x402Version: 2, status: "invalid", error: result.error, detail: result.detail };
|
|
@@ -2283,9 +2852,10 @@ function createPaymentGate(options) {
|
|
|
2283
2852
|
const genNonce = _nullishCoalesce(options.generateNonce, () => ( (() => globalThis.crypto.randomUUID())));
|
|
2284
2853
|
let resolved;
|
|
2285
2854
|
function ready() {
|
|
2286
|
-
|
|
2855
|
+
if (resolved) return resolved;
|
|
2856
|
+
const p = (async () => {
|
|
2287
2857
|
const accepts = normaliseAccepts(options);
|
|
2288
|
-
|
|
2858
|
+
const specs = await Promise.all(
|
|
2289
2859
|
accepts.map(async (a) => {
|
|
2290
2860
|
const net = await resolveNetwork2({ chain: a.chain, rpcUrl: _nullishCoalesce(a.rpcUrl, () => ( options.rpcUrl)) });
|
|
2291
2861
|
const payTo = _nullishCoalesce(a.payTo, () => ( options.payTo));
|
|
@@ -2296,11 +2866,53 @@ function createPaymentGate(options) {
|
|
|
2296
2866
|
}
|
|
2297
2867
|
net.assertValidPayTo(payTo);
|
|
2298
2868
|
const { asset, decimals, symbol } = net.resolveToken(a.token);
|
|
2299
|
-
const amountBase =
|
|
2300
|
-
|
|
2869
|
+
const amountBase = _chunkMDLZJGLYcjs.parseUnits.call(void 0, a.amount, decimals);
|
|
2870
|
+
const spec = { net, asset, decimals, symbol, amountBase, amountFormatted: a.amount, payTo };
|
|
2871
|
+
if (options.exact) spec.exact = await resolveExactRail(net, asset);
|
|
2872
|
+
return spec;
|
|
2301
2873
|
})
|
|
2302
2874
|
);
|
|
2875
|
+
if (options.exact && !specs.some((s) => s.exact)) {
|
|
2876
|
+
throw new Error(
|
|
2877
|
+
"requirePayment: `exact` was requested but none of the offered rails support it. The standard `exact` rail is EVM + EIP-3009 only (USDC / EURC) \u2014 not native coins, not USDT, not non-EVM chains. Offer an EVM EIP-3009 token, or drop `exact`."
|
|
2878
|
+
);
|
|
2879
|
+
}
|
|
2880
|
+
return specs;
|
|
2303
2881
|
})();
|
|
2882
|
+
p.catch(() => {
|
|
2883
|
+
if (resolved === p) resolved = void 0;
|
|
2884
|
+
});
|
|
2885
|
+
resolved = p;
|
|
2886
|
+
return p;
|
|
2887
|
+
}
|
|
2888
|
+
async function resolveExactRail(net, asset) {
|
|
2889
|
+
const cfg = options.exact;
|
|
2890
|
+
if (net.family !== "evm" || asset === "native" || !net.exactDomain || !net.settleExactSelf) {
|
|
2891
|
+
return void 0;
|
|
2892
|
+
}
|
|
2893
|
+
const domain = await net.exactDomain(asset);
|
|
2894
|
+
if (!domain) {
|
|
2895
|
+
throw new Error(
|
|
2896
|
+
`requirePayment: \`exact\` requested for asset ${asset} on ${net.network}, but it isn't an EIP-3009 token (couldn't read name()/version()/authorizationState). The exact rail supports USDC / EURC and other EIP-3009 tokens \u2014 USDT and native coins need onchain-proof. (Or check your rpcUrl is reachable.)`
|
|
2897
|
+
);
|
|
2898
|
+
}
|
|
2899
|
+
if (cfg.settle === "self") {
|
|
2900
|
+
if (cfg.relayer === void 0) {
|
|
2901
|
+
throw new Error(
|
|
2902
|
+
"requirePayment: exact `settle: 'self'` needs a `relayer` wallet (the gas-paying key that broadcasts transferWithAuthorization), e.g. exact: { settle: 'self', relayer: { privateKey } }."
|
|
2903
|
+
);
|
|
2904
|
+
}
|
|
2905
|
+
const relayer = net.bindWallet(cfg.relayer);
|
|
2906
|
+
return { domain, mode: { kind: "self", relayer } };
|
|
2907
|
+
}
|
|
2908
|
+
return {
|
|
2909
|
+
domain,
|
|
2910
|
+
mode: {
|
|
2911
|
+
kind: "facilitator",
|
|
2912
|
+
url: cfg.settle.facilitator,
|
|
2913
|
+
...cfg.settle.authHeaders ? { authHeaders: cfg.settle.authHeaders } : {}
|
|
2914
|
+
}
|
|
2915
|
+
};
|
|
2304
2916
|
}
|
|
2305
2917
|
const hasCustomStore = Boolean(options.isUsed || options.markUsed);
|
|
2306
2918
|
const localUsed = /* @__PURE__ */ new Set();
|
|
@@ -2337,93 +2949,191 @@ function createPaymentGate(options) {
|
|
|
2337
2949
|
}
|
|
2338
2950
|
};
|
|
2339
2951
|
}
|
|
2340
|
-
|
|
2952
|
+
function buildExactAccept(s) {
|
|
2953
|
+
const d = s.exact.domain;
|
|
2954
|
+
return {
|
|
2955
|
+
scheme: "exact",
|
|
2956
|
+
network: s.net.network,
|
|
2957
|
+
amount: s.amountBase.toString(),
|
|
2958
|
+
asset: s.asset,
|
|
2959
|
+
payTo: s.payTo,
|
|
2960
|
+
maxTimeoutSeconds,
|
|
2961
|
+
extra: {
|
|
2962
|
+
assetTransferMethod: "eip3009",
|
|
2963
|
+
name: d.name,
|
|
2964
|
+
version: d.version,
|
|
2965
|
+
minConfirmations,
|
|
2966
|
+
decimals: s.decimals,
|
|
2967
|
+
amountFormatted: s.amountFormatted,
|
|
2968
|
+
...s.symbol ? { symbol: s.symbol } : {}
|
|
2969
|
+
}
|
|
2970
|
+
};
|
|
2971
|
+
}
|
|
2972
|
+
function buildAccepts(specs, nonce) {
|
|
2973
|
+
const out = [];
|
|
2974
|
+
for (const s of specs) {
|
|
2975
|
+
if (s.exact) out.push(buildExactAccept(s));
|
|
2976
|
+
out.push(buildAccept(s, nonce));
|
|
2977
|
+
}
|
|
2978
|
+
return out;
|
|
2979
|
+
}
|
|
2980
|
+
async function makeChallenge(resourceUrl, opts) {
|
|
2341
2981
|
const specs = await ready();
|
|
2342
2982
|
const nonce = genNonce();
|
|
2343
2983
|
const challenge2 = {
|
|
2344
2984
|
x402Version: 2,
|
|
2345
|
-
error: null,
|
|
2346
2985
|
resource: {
|
|
2347
2986
|
url: resourceUrl,
|
|
2348
2987
|
...options.description ? { description: options.description } : {}
|
|
2349
2988
|
},
|
|
2350
|
-
accepts: specs
|
|
2989
|
+
accepts: buildAccepts(specs, nonce),
|
|
2990
|
+
..._optionalChain([opts, 'optionalAccess', _42 => _42.error]) ? { error: opts.error } : {},
|
|
2991
|
+
..._optionalChain([opts, 'optionalAccess', _43 => _43.extensions]) ? { extensions: opts.extensions } : {}
|
|
2351
2992
|
};
|
|
2352
2993
|
return { challenge: challenge2, requiredHeader: buildChallengeHeader(challenge2) };
|
|
2353
2994
|
}
|
|
2995
|
+
async function challenge(resourceUrl = "") {
|
|
2996
|
+
return makeChallenge(resourceUrl);
|
|
2997
|
+
}
|
|
2354
2998
|
async function asChallenge() {
|
|
2355
|
-
const { challenge: c, requiredHeader } = await
|
|
2999
|
+
const { challenge: c, requiredHeader } = await makeChallenge("");
|
|
2356
3000
|
return { kind: "challenge", challenge: c, requiredHeader, statusCode: 402 };
|
|
2357
3001
|
}
|
|
3002
|
+
async function rejection(code, detail) {
|
|
3003
|
+
const { challenge: c, requiredHeader } = await makeChallenge("", {
|
|
3004
|
+
error: `${code}: ${detail}`,
|
|
3005
|
+
extensions: { piprail: { code, detail } }
|
|
3006
|
+
});
|
|
3007
|
+
return { kind: "invalid", error: code, detail, challenge: c, requiredHeader, statusCode: 402 };
|
|
3008
|
+
}
|
|
3009
|
+
function fireOnPaid(receipt) {
|
|
3010
|
+
if (options.onPaid) {
|
|
3011
|
+
try {
|
|
3012
|
+
options.onPaid(receipt);
|
|
3013
|
+
} catch (e27) {
|
|
3014
|
+
}
|
|
3015
|
+
}
|
|
3016
|
+
}
|
|
2358
3017
|
async function describe(resourceUrl = "") {
|
|
2359
3018
|
const specs = await ready();
|
|
2360
|
-
const accepts =
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
3019
|
+
const accepts = [];
|
|
3020
|
+
for (const s of specs) {
|
|
3021
|
+
const base2 = {
|
|
3022
|
+
network: s.net.network,
|
|
3023
|
+
asset: s.asset,
|
|
3024
|
+
payTo: s.payTo,
|
|
3025
|
+
amount: s.amountBase.toString(),
|
|
3026
|
+
amountFormatted: s.amountFormatted,
|
|
3027
|
+
decimals: s.decimals,
|
|
3028
|
+
maxTimeoutSeconds,
|
|
3029
|
+
...s.symbol ? { symbol: s.symbol } : {}
|
|
3030
|
+
};
|
|
3031
|
+
if (s.exact) accepts.push({ scheme: "exact", ...base2 });
|
|
3032
|
+
accepts.push({ scheme: "onchain-proof", ...base2 });
|
|
3033
|
+
}
|
|
2371
3034
|
return {
|
|
2372
3035
|
url: resourceUrl,
|
|
2373
3036
|
...options.description ? { description: options.description } : {},
|
|
2374
3037
|
accepts
|
|
2375
3038
|
};
|
|
2376
3039
|
}
|
|
2377
|
-
async function
|
|
2378
|
-
const raw = normaliseHeader(paymentSignature);
|
|
2379
|
-
if (!raw) return asChallenge();
|
|
2380
|
-
const sig = parseSignatureHeader(raw);
|
|
2381
|
-
if (!sig || !sig.accepted || typeof sig.accepted.network !== "string" || typeof sig.accepted.asset !== "string") {
|
|
2382
|
-
return asChallenge();
|
|
2383
|
-
}
|
|
3040
|
+
async function verifyOnchainProof(sig) {
|
|
2384
3041
|
const specs = await ready();
|
|
2385
3042
|
const spec = specs.find(
|
|
2386
3043
|
(s) => s.net.network === sig.accepted.network && s.asset === sig.accepted.asset
|
|
2387
3044
|
);
|
|
2388
3045
|
if (!spec) {
|
|
2389
|
-
return
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
statusCode: 402
|
|
2394
|
-
};
|
|
3046
|
+
return rejection(
|
|
3047
|
+
"transfer_not_found",
|
|
3048
|
+
`Proof claims ${sig.accepted.asset} on ${sig.accepted.network}, which this resource doesn't accept (offered: ${specs.map((s) => `${s.asset}@${s.net.network}`).join(", ")}).`
|
|
3049
|
+
);
|
|
2395
3050
|
}
|
|
2396
3051
|
const ref = sig.payload.txHash;
|
|
2397
|
-
if (await claimTx(ref)) {
|
|
2398
|
-
return {
|
|
2399
|
-
kind: "invalid",
|
|
2400
|
-
error: "tx_already_used",
|
|
2401
|
-
detail: `Proof ${ref} was already redeemed.`,
|
|
2402
|
-
statusCode: 402
|
|
2403
|
-
};
|
|
2404
|
-
}
|
|
3052
|
+
if (await claimTx(ref)) return rejection("tx_already_used", `Proof ${ref} was already redeemed.`);
|
|
2405
3053
|
const result = await spec.net.verify(ref, buildAccept(spec, sig.payload.nonce));
|
|
2406
3054
|
if (!result.ok) {
|
|
2407
3055
|
await settleTx(ref, false);
|
|
2408
|
-
return
|
|
2409
|
-
kind: "invalid",
|
|
2410
|
-
error: result.error,
|
|
2411
|
-
detail: result.detail,
|
|
2412
|
-
statusCode: 402
|
|
2413
|
-
};
|
|
3056
|
+
return rejection(result.error, result.detail);
|
|
2414
3057
|
}
|
|
2415
3058
|
await settleTx(ref, true);
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
3059
|
+
fireOnPaid(result.receipt);
|
|
3060
|
+
return { kind: "paid", receipt: result.receipt, receiptHeader: buildReceiptHeader(result.receipt) };
|
|
3061
|
+
}
|
|
3062
|
+
async function verifyExact(exact) {
|
|
3063
|
+
const specs = await ready();
|
|
3064
|
+
const exactSpecs = specs.filter((s) => s.exact);
|
|
3065
|
+
if (exactSpecs.length === 0) {
|
|
3066
|
+
return rejection("transfer_not_found", "This resource offers no standard `exact` rail.");
|
|
3067
|
+
}
|
|
3068
|
+
const isCaip = exact.network.startsWith("eip155:");
|
|
3069
|
+
let candidates = isCaip ? exactSpecs.filter((s) => s.net.network === exact.network) : exactSpecs;
|
|
3070
|
+
if (exact.asset) {
|
|
3071
|
+
candidates = candidates.filter((s) => s.asset.toLowerCase() === exact.asset.toLowerCase());
|
|
3072
|
+
}
|
|
3073
|
+
let spec = candidates[0];
|
|
3074
|
+
if (!isCaip && !exact.asset && exactSpecs.length > 1) spec = void 0;
|
|
3075
|
+
if (!spec && !isCaip && !exact.asset && exactSpecs.length === 1) spec = exactSpecs[0];
|
|
3076
|
+
if (!spec || !spec.exact) {
|
|
3077
|
+
return rejection(
|
|
3078
|
+
"transfer_not_found",
|
|
3079
|
+
`No \`exact\` rail offered for ${exact.network}${exact.asset ? `/${exact.asset}` : ""} (offered: ${exactSpecs.map((s) => `${s.asset}@${s.net.network}`).join(", ")}).`
|
|
3080
|
+
);
|
|
3081
|
+
}
|
|
3082
|
+
const nonce = exact.payload.authorization.nonce;
|
|
3083
|
+
if (await claimTx(nonce)) {
|
|
3084
|
+
return rejection("tx_already_used", `Authorization nonce ${nonce} was already redeemed.`);
|
|
3085
|
+
}
|
|
3086
|
+
const accept = buildExactAccept(spec);
|
|
3087
|
+
const mode = spec.exact.mode;
|
|
3088
|
+
let result;
|
|
3089
|
+
try {
|
|
3090
|
+
if (mode.kind === "self") {
|
|
3091
|
+
result = await spec.net.settleExactSelf({ relayer: mode.relayer, payload: exact.payload, accept });
|
|
3092
|
+
} else {
|
|
3093
|
+
result = await settleViaFacilitator({
|
|
3094
|
+
url: mode.url,
|
|
3095
|
+
...mode.authHeaders ? { authHeaders: mode.authHeaders } : {},
|
|
3096
|
+
// PipRail always builds a v2-shaped paymentRequirements (CAIP-2 network + `amount`),
|
|
3097
|
+
// so force x402Version:2 — echoing a v1 client's version here would hand the facilitator
|
|
3098
|
+
// a self-inconsistent request (v1 envelope, v2 requirements). The inner payload is
|
|
3099
|
+
// byte-identical across versions, so forwarding it verbatim is fine.
|
|
3100
|
+
x402Version: 2,
|
|
3101
|
+
paymentPayload: exact.raw,
|
|
3102
|
+
paymentRequirements: {
|
|
3103
|
+
scheme: "exact",
|
|
3104
|
+
network: accept.network,
|
|
3105
|
+
asset: accept.asset,
|
|
3106
|
+
amount: accept.amount,
|
|
3107
|
+
payTo: accept.payTo,
|
|
3108
|
+
maxTimeoutSeconds: accept.maxTimeoutSeconds,
|
|
3109
|
+
extra: { name: accept.extra.name, version: accept.extra.version }
|
|
3110
|
+
},
|
|
3111
|
+
receipt: { network: accept.network, asset: accept.asset, payTo: accept.payTo, amount: accept.amount },
|
|
3112
|
+
payerHint: exact.payload.authorization.from
|
|
3113
|
+
});
|
|
2420
3114
|
}
|
|
3115
|
+
} catch (err) {
|
|
3116
|
+
await settleTx(nonce, false);
|
|
3117
|
+
throw err;
|
|
2421
3118
|
}
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
3119
|
+
if (!result.ok) {
|
|
3120
|
+
await settleTx(nonce, false);
|
|
3121
|
+
return rejection(result.error, result.detail);
|
|
3122
|
+
}
|
|
3123
|
+
await settleTx(nonce, true);
|
|
3124
|
+
fireOnPaid(result.receipt);
|
|
3125
|
+
return { kind: "paid", receipt: result.receipt, receiptHeader: buildReceiptHeader(result.receipt) };
|
|
3126
|
+
}
|
|
3127
|
+
async function verify(paymentSignature) {
|
|
3128
|
+
const raw = normaliseHeader(paymentSignature);
|
|
3129
|
+
if (!raw) return asChallenge();
|
|
3130
|
+
const sig = parseSignatureHeader(raw);
|
|
3131
|
+
if (sig && sig.accepted && typeof sig.accepted.network === "string" && typeof sig.accepted.asset === "string") {
|
|
3132
|
+
return verifyOnchainProof(sig);
|
|
3133
|
+
}
|
|
3134
|
+
const exact = parseExactPaymentHeader(raw);
|
|
3135
|
+
if (exact) return verifyExact(exact);
|
|
3136
|
+
return asChallenge();
|
|
2427
3137
|
}
|
|
2428
3138
|
return { challenge, verify, describe };
|
|
2429
3139
|
}
|
|
@@ -2432,14 +3142,20 @@ function requirePayment(options) {
|
|
|
2432
3142
|
return async (req, res, next) => {
|
|
2433
3143
|
let result;
|
|
2434
3144
|
try {
|
|
2435
|
-
result = await gate.verify(req.headers[HEADER_SIGNATURE]);
|
|
3145
|
+
result = await gate.verify(_nullishCoalesce(req.headers[HEADER_SIGNATURE], () => ( req.headers[HEADER_SIGNATURE_V1])));
|
|
2436
3146
|
} catch (err) {
|
|
3147
|
+
if (err instanceof _chunkMDLZJGLYcjs.SettlementError) {
|
|
3148
|
+
res.status(502);
|
|
3149
|
+
res.json({ x402Version: 2, error: "settlement_failed", detail: err.message });
|
|
3150
|
+
return;
|
|
3151
|
+
}
|
|
2437
3152
|
next(err);
|
|
2438
3153
|
return;
|
|
2439
3154
|
}
|
|
2440
3155
|
switch (result.kind) {
|
|
2441
3156
|
case "paid":
|
|
2442
3157
|
res.setHeader(HEADER_RESPONSE, result.receiptHeader);
|
|
3158
|
+
res.setHeader(HEADER_RESPONSE_V1, result.receiptHeader);
|
|
2443
3159
|
return next();
|
|
2444
3160
|
case "challenge":
|
|
2445
3161
|
res.setHeader(HEADER_REQUIRED, result.requiredHeader);
|
|
@@ -2447,8 +3163,9 @@ function requirePayment(options) {
|
|
|
2447
3163
|
res.json(result.challenge);
|
|
2448
3164
|
return;
|
|
2449
3165
|
case "invalid":
|
|
3166
|
+
res.setHeader(HEADER_REQUIRED, result.requiredHeader);
|
|
2450
3167
|
res.status(result.statusCode);
|
|
2451
|
-
res.json(
|
|
3168
|
+
res.json(result.challenge);
|
|
2452
3169
|
return;
|
|
2453
3170
|
}
|
|
2454
3171
|
};
|
|
@@ -2458,110 +3175,12 @@ function normaliseHeader(value) {
|
|
|
2458
3175
|
return value;
|
|
2459
3176
|
}
|
|
2460
3177
|
|
|
2461
|
-
// src/drivers/evm/exact.ts
|
|
2462
|
-
var EXACT_NETWORK_SLUGS = {
|
|
2463
|
-
ethereum: 1,
|
|
2464
|
-
base: 8453,
|
|
2465
|
-
"base-sepolia": 84532,
|
|
2466
|
-
arbitrum: 42161,
|
|
2467
|
-
optimism: 10,
|
|
2468
|
-
polygon: 137,
|
|
2469
|
-
avalanche: 43114
|
|
2470
|
-
};
|
|
2471
|
-
function chainIdForExactNetwork(slug) {
|
|
2472
|
-
return _nullishCoalesce(EXACT_NETWORK_SLUGS[slug], () => ( null));
|
|
2473
|
-
}
|
|
2474
|
-
var EIP3009_TYPES = {
|
|
2475
|
-
TransferWithAuthorization: [
|
|
2476
|
-
{ name: "from", type: "address" },
|
|
2477
|
-
{ name: "to", type: "address" },
|
|
2478
|
-
{ name: "value", type: "uint256" },
|
|
2479
|
-
{ name: "validAfter", type: "uint256" },
|
|
2480
|
-
{ name: "validBefore", type: "uint256" },
|
|
2481
|
-
{ name: "nonce", type: "bytes32" }
|
|
2482
|
-
]
|
|
2483
|
-
};
|
|
2484
|
-
function parseExactRequirements(body) {
|
|
2485
|
-
if (!body || typeof body !== "object") return null;
|
|
2486
|
-
const accepts = body.accepts;
|
|
2487
|
-
if (!Array.isArray(accepts)) return null;
|
|
2488
|
-
const out = [];
|
|
2489
|
-
for (const raw of accepts) {
|
|
2490
|
-
if (!raw || typeof raw !== "object") continue;
|
|
2491
|
-
const a = raw;
|
|
2492
|
-
if (a.scheme !== "exact") continue;
|
|
2493
|
-
const amount = _nullishCoalesce(a.maxAmountRequired, () => ( a.amount));
|
|
2494
|
-
if (typeof a.network !== "string" || typeof amount !== "string" || typeof a.asset !== "string" || typeof a.payTo !== "string") {
|
|
2495
|
-
continue;
|
|
2496
|
-
}
|
|
2497
|
-
out.push({
|
|
2498
|
-
scheme: "exact",
|
|
2499
|
-
network: a.network,
|
|
2500
|
-
maxAmountRequired: amount,
|
|
2501
|
-
asset: a.asset,
|
|
2502
|
-
payTo: a.payTo,
|
|
2503
|
-
maxTimeoutSeconds: typeof a.maxTimeoutSeconds === "number" ? a.maxTimeoutSeconds : 600,
|
|
2504
|
-
...a.extra && typeof a.extra === "object" ? { extra: a.extra } : {},
|
|
2505
|
-
...typeof a.description === "string" ? { description: a.description } : {},
|
|
2506
|
-
...typeof a.resource === "string" ? { resource: a.resource } : {}
|
|
2507
|
-
});
|
|
2508
|
-
}
|
|
2509
|
-
return out;
|
|
2510
|
-
}
|
|
2511
|
-
async function buildExactAuthorization(params) {
|
|
2512
|
-
const { account, accept, chainId, now, nonce } = params;
|
|
2513
|
-
if (!account.signTypedData) {
|
|
2514
|
-
throw new Error("buildExactAuthorization: the account cannot sign EIP-712 typed data.");
|
|
2515
|
-
}
|
|
2516
|
-
const authorization = {
|
|
2517
|
-
from: account.address,
|
|
2518
|
-
to: accept.payTo,
|
|
2519
|
-
value: accept.maxAmountRequired,
|
|
2520
|
-
validAfter: "0",
|
|
2521
|
-
validBefore: String(now + accept.maxTimeoutSeconds),
|
|
2522
|
-
nonce
|
|
2523
|
-
};
|
|
2524
|
-
const signature = await account.signTypedData({
|
|
2525
|
-
domain: {
|
|
2526
|
-
name: _nullishCoalesce(_optionalChain([accept, 'access', _34 => _34.extra, 'optionalAccess', _35 => _35.name]), () => ( "USD Coin")),
|
|
2527
|
-
version: _nullishCoalesce(_optionalChain([accept, 'access', _36 => _36.extra, 'optionalAccess', _37 => _37.version]), () => ( "2")),
|
|
2528
|
-
chainId,
|
|
2529
|
-
verifyingContract: accept.asset
|
|
2530
|
-
},
|
|
2531
|
-
types: EIP3009_TYPES,
|
|
2532
|
-
primaryType: "TransferWithAuthorization",
|
|
2533
|
-
message: {
|
|
2534
|
-
from: authorization.from,
|
|
2535
|
-
to: authorization.to,
|
|
2536
|
-
value: BigInt(authorization.value),
|
|
2537
|
-
validAfter: BigInt(authorization.validAfter),
|
|
2538
|
-
validBefore: BigInt(authorization.validBefore),
|
|
2539
|
-
nonce: authorization.nonce
|
|
2540
|
-
}
|
|
2541
|
-
});
|
|
2542
|
-
return { authorization, signature };
|
|
2543
|
-
}
|
|
2544
|
-
function base64(str) {
|
|
2545
|
-
if (typeof btoa === "function") return btoa(str);
|
|
2546
|
-
if (typeof Buffer !== "undefined") return Buffer.from(str, "utf8").toString("base64");
|
|
2547
|
-
throw new Error("No base64 encoder available in this runtime.");
|
|
2548
|
-
}
|
|
2549
|
-
function encodeXPaymentHeader(input) {
|
|
2550
|
-
const payload = {
|
|
2551
|
-
x402Version: _nullishCoalesce(input.x402Version, () => ( 1)),
|
|
2552
|
-
scheme: "exact",
|
|
2553
|
-
network: input.network,
|
|
2554
|
-
payload: { signature: input.signature, authorization: input.authorization }
|
|
2555
|
-
};
|
|
2556
|
-
return base64(JSON.stringify(payload));
|
|
2557
|
-
}
|
|
2558
|
-
|
|
2559
3178
|
// src/discovery.ts
|
|
2560
3179
|
var GENERATOR = "@piprail/sdk \xB7 https://piprail.com";
|
|
2561
3180
|
function pathOf(url) {
|
|
2562
3181
|
try {
|
|
2563
3182
|
return new URL(url).pathname || "/";
|
|
2564
|
-
} catch (
|
|
3183
|
+
} catch (e28) {
|
|
2565
3184
|
return url.startsWith("/") ? url : `/${url}`;
|
|
2566
3185
|
}
|
|
2567
3186
|
}
|
|
@@ -2658,4 +3277,17 @@ function buildX402DnsTxt(input) {
|
|
|
2658
3277
|
|
|
2659
3278
|
|
|
2660
3279
|
|
|
2661
|
-
|
|
3280
|
+
|
|
3281
|
+
|
|
3282
|
+
|
|
3283
|
+
|
|
3284
|
+
|
|
3285
|
+
|
|
3286
|
+
|
|
3287
|
+
|
|
3288
|
+
|
|
3289
|
+
|
|
3290
|
+
|
|
3291
|
+
|
|
3292
|
+
|
|
3293
|
+
exports.CHAINS = CHAINS; exports.ConfirmationTimeoutError = _chunkMDLZJGLYcjs.ConfirmationTimeoutError; exports.DIRECTORY_INFO = DIRECTORY_INFO; exports.EIP3009_TYPES = EIP3009_TYPES; exports.EXACT_NETWORK_SLUGS = EXACT_NETWORK_SLUGS; exports.GENERATOR = GENERATOR; exports.HEADER_REQUIRED = HEADER_REQUIRED; exports.HEADER_RESPONSE = HEADER_RESPONSE; exports.HEADER_RESPONSE_V1 = HEADER_RESPONSE_V1; exports.HEADER_SIGNATURE = HEADER_SIGNATURE; exports.HEADER_SIGNATURE_V1 = HEADER_SIGNATURE_V1; exports.InsufficientFundsError = _chunkMDLZJGLYcjs.InsufficientFundsError; exports.InvalidEnvelopeError = _chunkMDLZJGLYcjs.InvalidEnvelopeError; exports.MaxRetriesExceededError = _chunkMDLZJGLYcjs.MaxRetriesExceededError; exports.MissingDriverError = _chunkMDLZJGLYcjs.MissingDriverError; exports.NoCompatibleAcceptError = _chunkMDLZJGLYcjs.NoCompatibleAcceptError; exports.NonReplayableBodyError = _chunkMDLZJGLYcjs.NonReplayableBodyError; exports.PaymentDeclinedError = _chunkMDLZJGLYcjs.PaymentDeclinedError; exports.PaymentTimeoutError = _chunkMDLZJGLYcjs.PaymentTimeoutError; exports.PipRailClient = PipRailClient; exports.PipRailError = _chunkMDLZJGLYcjs.PipRailError; exports.RecipientNotReadyError = _chunkMDLZJGLYcjs.RecipientNotReadyError; exports.SettlementError = _chunkMDLZJGLYcjs.SettlementError; exports.UnknownTokenError = _chunkMDLZJGLYcjs.UnknownTokenError; exports.UnsupportedNetworkError = _chunkMDLZJGLYcjs.UnsupportedNetworkError; exports.WrongChainError = _chunkMDLZJGLYcjs.WrongChainError; exports.WrongFamilyError = _chunkMDLZJGLYcjs.WrongFamilyError; exports.buildChallengeHeader = buildChallengeHeader; exports.buildExactAuthorization = buildExactAuthorization; exports.buildOpenApi = buildOpenApi; exports.buildReceiptHeader = buildReceiptHeader; exports.buildSignatureHeader = buildSignatureHeader; exports.buildWellKnownX402 = buildWellKnownX402; exports.buildX402DnsTxt = buildX402DnsTxt; exports.chainIdForExactNetwork = chainIdForExactNetwork; exports.createPaymentGate = createPaymentGate; exports.decorateOutcome = decorateOutcome; exports.eip3009Abi = eip3009Abi; exports.encodeXPaymentHeader = encodeXPaymentHeader; exports.evaluatePolicy = evaluatePolicy; exports.getDirectoryInfo = getDirectoryInfo; exports.normalizeNetwork = normalizeNetwork; exports.parseChallenge = parseChallenge; exports.parseExactPaymentHeader = parseExactPaymentHeader; exports.parseExactRequirements = parseExactRequirements; exports.parseReceipt = parseReceipt; exports.parseSignatureHeader = parseSignatureHeader; exports.paymentTools = paymentTools; exports.pickAccept = pickAccept; exports.planAcross = planAcross; exports.readExactDomain = readExactDomain; exports.register402Index = register402Index; exports.registerDriver = registerDriver; exports.registerX402Scan = registerX402Scan; exports.requirePayment = requirePayment; exports.resolveChain = resolveChain; exports.searchOpenIndexes = searchOpenIndexes; exports.settleViaFacilitator = settleViaFacilitator; exports.toInsufficientFundsError = _chunkMDLZJGLYcjs.toInsufficientFundsError; exports.toInvalidBody = toInvalidBody;
|