@piprail/sdk 2.9.0 → 2.10.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 +62 -0
- package/README.md +2 -1
- package/dist/chunk-3SBTJKAG.js +92 -0
- package/dist/chunk-CQQI5IJX.cjs +92 -0
- package/dist/index.cjs +1485 -174
- package/dist/index.d.cts +717 -13
- package/dist/index.d.ts +717 -13
- package/dist/index.js +1353 -42
- package/dist/{ledger-BtzrfO-3.d.cts → ledger-OQos-tmj.d.cts} +276 -9
- package/dist/{ledger-BtzrfO-3.d.ts → ledger-OQos-tmj.d.ts} +276 -9
- package/dist/node.d.cts +2 -2
- package/dist/node.d.ts +2 -2
- package/dist/receipt-NNEID77X.js +14 -0
- package/dist/receipt-QCDPMWNF.cjs +14 -0
- package/dist/{stellar-BEMT7UYF.js → stellar-ASP2THL2.js} +1 -1
- package/dist/{stellar-SUKASK4N.cjs → stellar-CRWBSX4E.cjs} +1 -1
- package/dist/{sui-F5JQ2N6I.js → sui-FZIKZNVI.js} +13 -3
- package/dist/{sui-VE5LT7BL.cjs → sui-Y4RLKKE2.cjs} +13 -3
- package/dist/{tron-ZZZS3FNN.js → tron-BMCWN5SS.js} +7 -1
- package/dist/{tron-EMFXDFHW.cjs → tron-OMXB6EW2.cjs} +7 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } async function _asyncNullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return await rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } async function _asyncOptionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = await fn(value); } else if (op === 'call' || op === 'optionalCall') { value = await fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class;
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } async function _asyncNullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return await rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } async function _asyncOptionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = await fn(value); } else if (op === 'call' || op === 'optionalCall') { value = await fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3;
|
|
2
2
|
|
|
3
3
|
var _chunkO4UQOZ4Zcjs = require('./chunk-O4UQOZ4Z.cjs');
|
|
4
4
|
|
|
5
5
|
|
|
6
|
+
var _chunkCQQI5IJXcjs = require('./chunk-CQQI5IJX.cjs');
|
|
7
|
+
|
|
8
|
+
|
|
6
9
|
|
|
7
10
|
|
|
8
11
|
|
|
@@ -1357,6 +1360,361 @@ async function verifyAndSettlePermit2Evm(input) {
|
|
|
1357
1360
|
};
|
|
1358
1361
|
}
|
|
1359
1362
|
|
|
1363
|
+
// src/drivers/evm/upto.ts
|
|
1364
|
+
|
|
1365
|
+
|
|
1366
|
+
|
|
1367
|
+
|
|
1368
|
+
var X402_UPTO_PERMIT2_PROXY = "0x4020A4f3b7b90ccA423B9fabCc0CE57C6C240002";
|
|
1369
|
+
var UPTO_PROXY_CHAIN_IDS = /* @__PURE__ */ new Set([
|
|
1370
|
+
1,
|
|
1371
|
+
// Ethereum
|
|
1372
|
+
8453,
|
|
1373
|
+
// Base
|
|
1374
|
+
42161,
|
|
1375
|
+
// Arbitrum
|
|
1376
|
+
10,
|
|
1377
|
+
// Optimism
|
|
1378
|
+
137,
|
|
1379
|
+
// Polygon
|
|
1380
|
+
56
|
|
1381
|
+
// BNB
|
|
1382
|
+
]);
|
|
1383
|
+
function isUptoProxyChain(chainId) {
|
|
1384
|
+
return UPTO_PROXY_CHAIN_IDS.has(chainId);
|
|
1385
|
+
}
|
|
1386
|
+
var PERMIT2_UPTO_WITNESS_TYPES = {
|
|
1387
|
+
PermitWitnessTransferFrom: PERMIT2_WITNESS_TYPES.PermitWitnessTransferFrom,
|
|
1388
|
+
TokenPermissions: PERMIT2_WITNESS_TYPES.TokenPermissions,
|
|
1389
|
+
Witness: [
|
|
1390
|
+
{ name: "to", type: "address" },
|
|
1391
|
+
{ name: "facilitator", type: "address" },
|
|
1392
|
+
{ name: "validAfter", type: "uint256" }
|
|
1393
|
+
]
|
|
1394
|
+
};
|
|
1395
|
+
var x402UptoProxyAbi = [
|
|
1396
|
+
{
|
|
1397
|
+
type: "function",
|
|
1398
|
+
name: "settle",
|
|
1399
|
+
stateMutability: "nonpayable",
|
|
1400
|
+
outputs: [],
|
|
1401
|
+
inputs: [
|
|
1402
|
+
{
|
|
1403
|
+
name: "permit",
|
|
1404
|
+
type: "tuple",
|
|
1405
|
+
components: [
|
|
1406
|
+
{
|
|
1407
|
+
name: "permitted",
|
|
1408
|
+
type: "tuple",
|
|
1409
|
+
components: [
|
|
1410
|
+
{ name: "token", type: "address" },
|
|
1411
|
+
{ name: "amount", type: "uint256" }
|
|
1412
|
+
]
|
|
1413
|
+
},
|
|
1414
|
+
{ name: "nonce", type: "uint256" },
|
|
1415
|
+
{ name: "deadline", type: "uint256" }
|
|
1416
|
+
]
|
|
1417
|
+
},
|
|
1418
|
+
{ name: "amount", type: "uint256" },
|
|
1419
|
+
{ name: "owner", type: "address" },
|
|
1420
|
+
{
|
|
1421
|
+
name: "witness",
|
|
1422
|
+
type: "tuple",
|
|
1423
|
+
components: [
|
|
1424
|
+
{ name: "to", type: "address" },
|
|
1425
|
+
{ name: "facilitator", type: "address" },
|
|
1426
|
+
{ name: "validAfter", type: "uint256" }
|
|
1427
|
+
]
|
|
1428
|
+
},
|
|
1429
|
+
{ name: "signature", type: "bytes" }
|
|
1430
|
+
]
|
|
1431
|
+
}
|
|
1432
|
+
];
|
|
1433
|
+
function shorten3(msg) {
|
|
1434
|
+
const oneLine = msg.replace(/\s+/g, " ").trim();
|
|
1435
|
+
return oneLine.length > 200 ? `${oneLine.slice(0, 200)}\u2026` : oneLine;
|
|
1436
|
+
}
|
|
1437
|
+
function randomPermit2Nonce2() {
|
|
1438
|
+
const g = globalThis.crypto;
|
|
1439
|
+
if (!_optionalChain([g, 'optionalAccess', _9 => _9.getRandomValues])) {
|
|
1440
|
+
throw new (0, _chunkMWBT7MCEcjs.UnsupportedSchemeError)(
|
|
1441
|
+
"this runtime lacks Web Crypto (globalThis.crypto.getRandomValues); the upto rail needs a CSPRNG nonce."
|
|
1442
|
+
);
|
|
1443
|
+
}
|
|
1444
|
+
const raw = new Uint8Array(32);
|
|
1445
|
+
g.getRandomValues(raw);
|
|
1446
|
+
return BigInt(`0x${[...raw].map((b) => b.toString(16).padStart(2, "0")).join("")}`);
|
|
1447
|
+
}
|
|
1448
|
+
async function payUptoEvm(input) {
|
|
1449
|
+
const { publicClient, walletClient, account, chainId, chain, accept } = input;
|
|
1450
|
+
let code;
|
|
1451
|
+
try {
|
|
1452
|
+
code = await publicClient.getCode({ address: account.address });
|
|
1453
|
+
} catch (e16) {
|
|
1454
|
+
code = void 0;
|
|
1455
|
+
}
|
|
1456
|
+
if (code && code !== "0x") {
|
|
1457
|
+
throw new (0, _chunkMWBT7MCEcjs.UnsupportedSchemeError)(
|
|
1458
|
+
`upto buyer rail requires an EOA signer; ${account.address} is a contract / EIP-1271 / EIP-7702-delegated account. Pay via onchain-proof.`
|
|
1459
|
+
);
|
|
1460
|
+
}
|
|
1461
|
+
const facilitatorAddress = _optionalChain([accept, 'access', _10 => _10.extra, 'optionalAccess', _11 => _11.facilitatorAddress]);
|
|
1462
|
+
if (typeof facilitatorAddress !== "string" || facilitatorAddress.length === 0) {
|
|
1463
|
+
throw new (0, _chunkMWBT7MCEcjs.UnsupportedSchemeError)(
|
|
1464
|
+
`upto: the rail carries no extra.facilitatorAddress to bind into witness.facilitator \u2014 refusing to sign.`
|
|
1465
|
+
);
|
|
1466
|
+
}
|
|
1467
|
+
const token = _viem.getAddress.call(void 0, accept.asset);
|
|
1468
|
+
const payTo = _viem.getAddress.call(void 0, accept.payTo);
|
|
1469
|
+
const facilitator = _viem.getAddress.call(void 0, facilitatorAddress);
|
|
1470
|
+
const value = BigInt(accept.amount);
|
|
1471
|
+
const approvalTx = await ensurePermit2Allowance({
|
|
1472
|
+
publicClient,
|
|
1473
|
+
walletClient,
|
|
1474
|
+
account,
|
|
1475
|
+
chain,
|
|
1476
|
+
token,
|
|
1477
|
+
amount: value
|
|
1478
|
+
});
|
|
1479
|
+
const nonce = randomPermit2Nonce2();
|
|
1480
|
+
const deadline = BigInt(Math.floor(Date.now() / 1e3) + accept.maxTimeoutSeconds);
|
|
1481
|
+
const validAfter = 0n;
|
|
1482
|
+
const spender = _viem.getAddress.call(void 0, X402_UPTO_PERMIT2_PROXY);
|
|
1483
|
+
const from = account.address;
|
|
1484
|
+
const signature = await walletClient.signTypedData({
|
|
1485
|
+
account,
|
|
1486
|
+
domain: { name: "Permit2", chainId, verifyingContract: PERMIT2_ADDRESS },
|
|
1487
|
+
types: PERMIT2_UPTO_WITNESS_TYPES,
|
|
1488
|
+
primaryType: "PermitWitnessTransferFrom",
|
|
1489
|
+
message: {
|
|
1490
|
+
permitted: { token, amount: value },
|
|
1491
|
+
spender,
|
|
1492
|
+
nonce,
|
|
1493
|
+
deadline,
|
|
1494
|
+
witness: { to: payTo, facilitator, validAfter }
|
|
1495
|
+
}
|
|
1496
|
+
});
|
|
1497
|
+
const permit2Authorization = {
|
|
1498
|
+
permitted: { token, amount: value.toString() },
|
|
1499
|
+
from,
|
|
1500
|
+
spender,
|
|
1501
|
+
nonce: nonce.toString(),
|
|
1502
|
+
deadline: deadline.toString(),
|
|
1503
|
+
witness: { to: payTo, facilitator, validAfter: validAfter.toString() }
|
|
1504
|
+
};
|
|
1505
|
+
return {
|
|
1506
|
+
payload: { signature, permit2Authorization },
|
|
1507
|
+
payerFrom: from,
|
|
1508
|
+
nonce: nonce.toString(),
|
|
1509
|
+
...approvalTx ? { approvalTx } : {}
|
|
1510
|
+
};
|
|
1511
|
+
}
|
|
1512
|
+
function resolveUptoRailEvm(input) {
|
|
1513
|
+
const { asset, relayerAddress, proxySupported, domain } = input;
|
|
1514
|
+
if (asset === "native") return null;
|
|
1515
|
+
if (!proxySupported()) return null;
|
|
1516
|
+
const extra = { facilitatorAddress: _viem.getAddress.call(void 0, relayerAddress) };
|
|
1517
|
+
if (domain) {
|
|
1518
|
+
extra.name = domain.name;
|
|
1519
|
+
extra.version = domain.version;
|
|
1520
|
+
}
|
|
1521
|
+
return { method: "permit2-upto", extra };
|
|
1522
|
+
}
|
|
1523
|
+
async function verifyAndSettleUptoEvm(input) {
|
|
1524
|
+
const { publicClient, walletClient, account, chain, payload, accept, settleAmount } = input;
|
|
1525
|
+
const token = _viem.getAddress.call(void 0, accept.asset);
|
|
1526
|
+
const payTo = _viem.getAddress.call(void 0, accept.payTo);
|
|
1527
|
+
const maxAmount = BigInt(accept.amount);
|
|
1528
|
+
const proxy = _viem.getAddress.call(void 0, X402_UPTO_PERMIT2_PROXY);
|
|
1529
|
+
const relayerAddress = _viem.getAddress.call(void 0, account.address);
|
|
1530
|
+
let from;
|
|
1531
|
+
let spender;
|
|
1532
|
+
let permittedToken;
|
|
1533
|
+
let witnessTo;
|
|
1534
|
+
let witnessFacilitator;
|
|
1535
|
+
let permittedAmount;
|
|
1536
|
+
let nonce;
|
|
1537
|
+
let deadline;
|
|
1538
|
+
let validAfter;
|
|
1539
|
+
const signature = payload.signature;
|
|
1540
|
+
try {
|
|
1541
|
+
const pa = payload.permit2Authorization;
|
|
1542
|
+
from = _viem.getAddress.call(void 0, pa.from);
|
|
1543
|
+
spender = _viem.getAddress.call(void 0, pa.spender);
|
|
1544
|
+
permittedToken = _viem.getAddress.call(void 0, pa.permitted.token);
|
|
1545
|
+
witnessTo = _viem.getAddress.call(void 0, pa.witness.to);
|
|
1546
|
+
witnessFacilitator = _viem.getAddress.call(void 0, pa.witness.facilitator);
|
|
1547
|
+
permittedAmount = BigInt(pa.permitted.amount);
|
|
1548
|
+
nonce = BigInt(pa.nonce);
|
|
1549
|
+
deadline = BigInt(pa.deadline);
|
|
1550
|
+
validAfter = BigInt(pa.witness.validAfter);
|
|
1551
|
+
if (!/^0x[0-9a-fA-F]+$/.test(signature)) throw new Error("signature must be hex");
|
|
1552
|
+
} catch (err) {
|
|
1553
|
+
return {
|
|
1554
|
+
ok: false,
|
|
1555
|
+
error: "signature_invalid",
|
|
1556
|
+
detail: `Malformed upto authorization: ${err instanceof Error ? err.message : String(err)}.`
|
|
1557
|
+
};
|
|
1558
|
+
}
|
|
1559
|
+
if (witnessTo !== payTo) {
|
|
1560
|
+
return { ok: false, error: "wrong_recipient", detail: `Authorization pays witness.to ${witnessTo}, not ${payTo}.` };
|
|
1561
|
+
}
|
|
1562
|
+
if (permittedToken !== token) {
|
|
1563
|
+
return { ok: false, error: "signature_invalid", detail: `Authorization permits token ${permittedToken}, not the rail's ${token}.` };
|
|
1564
|
+
}
|
|
1565
|
+
if (spender !== proxy) {
|
|
1566
|
+
return { ok: false, error: "signature_invalid", detail: `Authorization spender ${spender} is not the x402UptoPermit2Proxy ${proxy}; it can't be settled here.` };
|
|
1567
|
+
}
|
|
1568
|
+
if (witnessFacilitator !== relayerAddress) {
|
|
1569
|
+
return { ok: false, error: "signature_invalid", detail: `Authorization binds facilitator ${witnessFacilitator}, not this relayer ${relayerAddress}; only the bound facilitator can settle.` };
|
|
1570
|
+
}
|
|
1571
|
+
if (permittedAmount < maxAmount) {
|
|
1572
|
+
return { ok: false, error: "amount_too_low", detail: `Permitted (signed MAX) ${permittedAmount} is below the rail max ${maxAmount}.` };
|
|
1573
|
+
}
|
|
1574
|
+
if (permittedAmount > maxAmount) {
|
|
1575
|
+
return { ok: false, error: "upto_settle_exceeds_max", detail: `Permitted (signed MAX) ${permittedAmount} exceeds the advertised rail max ${maxAmount}; sign exactly the ceiling.` };
|
|
1576
|
+
}
|
|
1577
|
+
if (settleAmount < 0n) {
|
|
1578
|
+
return { ok: false, error: "upto_settle_exceeds_max", detail: `Settle amount ${settleAmount} is negative.` };
|
|
1579
|
+
}
|
|
1580
|
+
if (settleAmount > permittedAmount) {
|
|
1581
|
+
return { ok: false, error: "upto_settle_exceeds_max", detail: `Settle amount ${settleAmount} exceeds the signed MAX ${permittedAmount}.` };
|
|
1582
|
+
}
|
|
1583
|
+
const now = BigInt(Math.floor(Date.now() / 1e3));
|
|
1584
|
+
if (deadline <= now) {
|
|
1585
|
+
return { ok: false, error: "payment_expired", detail: `Permit2 deadline ${deadline} <= now ${now}.` };
|
|
1586
|
+
}
|
|
1587
|
+
let fromCode;
|
|
1588
|
+
try {
|
|
1589
|
+
fromCode = await publicClient.getCode({ address: from });
|
|
1590
|
+
} catch (e17) {
|
|
1591
|
+
return { ok: false, error: "tx_not_found", detail: `Could not read code at ${from} (transient RPC) \u2014 retry.` };
|
|
1592
|
+
}
|
|
1593
|
+
if (!(fromCode && fromCode !== "0x")) {
|
|
1594
|
+
let recovered;
|
|
1595
|
+
try {
|
|
1596
|
+
recovered = await _viem.recoverTypedDataAddress.call(void 0, {
|
|
1597
|
+
domain: { name: "Permit2", chainId: chain.id, verifyingContract: PERMIT2_ADDRESS },
|
|
1598
|
+
types: PERMIT2_UPTO_WITNESS_TYPES,
|
|
1599
|
+
primaryType: "PermitWitnessTransferFrom",
|
|
1600
|
+
message: {
|
|
1601
|
+
permitted: { token: permittedToken, amount: permittedAmount },
|
|
1602
|
+
spender,
|
|
1603
|
+
nonce,
|
|
1604
|
+
deadline,
|
|
1605
|
+
witness: { to: witnessTo, facilitator: witnessFacilitator, validAfter }
|
|
1606
|
+
},
|
|
1607
|
+
signature
|
|
1608
|
+
});
|
|
1609
|
+
} catch (err) {
|
|
1610
|
+
return { ok: false, error: "signature_invalid", detail: `Not a valid EIP-712 signature: ${shorten3(err instanceof Error ? err.message : String(err))}.` };
|
|
1611
|
+
}
|
|
1612
|
+
if (recovered !== from) {
|
|
1613
|
+
return { ok: false, error: "signature_invalid", detail: `Signature recovered to ${recovered}, not the authorizer ${from}.` };
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
if (settleAmount === 0n) {
|
|
1617
|
+
return {
|
|
1618
|
+
ok: true,
|
|
1619
|
+
receipt: {
|
|
1620
|
+
scheme: "upto",
|
|
1621
|
+
success: true,
|
|
1622
|
+
network: accept.network,
|
|
1623
|
+
transaction: "",
|
|
1624
|
+
asset: accept.asset,
|
|
1625
|
+
amount: "0",
|
|
1626
|
+
payer: from,
|
|
1627
|
+
payTo: accept.payTo,
|
|
1628
|
+
verifiedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1629
|
+
}
|
|
1630
|
+
};
|
|
1631
|
+
}
|
|
1632
|
+
try {
|
|
1633
|
+
const word = nonce >> 8n;
|
|
1634
|
+
const bit = nonce & 0xffn;
|
|
1635
|
+
const bitmap = await publicClient.readContract({
|
|
1636
|
+
address: PERMIT2_ADDRESS,
|
|
1637
|
+
abi: permit2NonceBitmapAbi,
|
|
1638
|
+
functionName: "nonceBitmap",
|
|
1639
|
+
args: [from, word]
|
|
1640
|
+
});
|
|
1641
|
+
if ((bitmap >> bit & 1n) === 1n) {
|
|
1642
|
+
return { ok: false, error: "tx_already_used", detail: `Permit2 nonce ${nonce} already used or invalidated for ${from}.` };
|
|
1643
|
+
}
|
|
1644
|
+
} catch (e18) {
|
|
1645
|
+
return { ok: false, error: "tx_not_found", detail: "Could not read the Permit2 nonce bitmap (transient RPC) \u2014 retry." };
|
|
1646
|
+
}
|
|
1647
|
+
const settleArgs = [
|
|
1648
|
+
{ permitted: { token: permittedToken, amount: permittedAmount }, nonce, deadline },
|
|
1649
|
+
settleAmount,
|
|
1650
|
+
from,
|
|
1651
|
+
{ to: witnessTo, facilitator: witnessFacilitator, validAfter },
|
|
1652
|
+
signature
|
|
1653
|
+
];
|
|
1654
|
+
try {
|
|
1655
|
+
await publicClient.simulateContract({
|
|
1656
|
+
account,
|
|
1657
|
+
address: proxy,
|
|
1658
|
+
abi: x402UptoProxyAbi,
|
|
1659
|
+
functionName: "settle",
|
|
1660
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1661
|
+
args: settleArgs
|
|
1662
|
+
});
|
|
1663
|
+
} catch (err) {
|
|
1664
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1665
|
+
if (/nonce|invalidated|used/i.test(msg)) return { ok: false, error: "tx_already_used", detail: "Permit2 nonce is used or invalidated." };
|
|
1666
|
+
if (/expired|deadline|too early|not yet/i.test(msg)) return { ok: false, error: "payment_expired", detail: shorten3(msg) };
|
|
1667
|
+
if (/exceeds.*permitted|AmountExceeds/i.test(msg)) return { ok: false, error: "upto_settle_exceeds_max", detail: shorten3(msg) };
|
|
1668
|
+
if (/facilitator|Unauthorized/i.test(msg)) return { ok: false, error: "signature_invalid", detail: shorten3(msg) };
|
|
1669
|
+
if (/signature/i.test(msg)) return { ok: false, error: "signature_invalid", detail: shorten3(msg) };
|
|
1670
|
+
return { ok: false, error: "tx_reverted", detail: `upto settle would revert: ${shorten3(msg)}` };
|
|
1671
|
+
}
|
|
1672
|
+
let txHash;
|
|
1673
|
+
try {
|
|
1674
|
+
txHash = await walletClient.writeContract({
|
|
1675
|
+
account,
|
|
1676
|
+
chain,
|
|
1677
|
+
address: proxy,
|
|
1678
|
+
abi: x402UptoProxyAbi,
|
|
1679
|
+
functionName: "settle",
|
|
1680
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1681
|
+
args: settleArgs
|
|
1682
|
+
});
|
|
1683
|
+
} catch (err) {
|
|
1684
|
+
throw new (0, _chunkMWBT7MCEcjs.SettlementError)(
|
|
1685
|
+
`upto settle: the merchant relayer failed to broadcast the proxy settle (${shorten3(err instanceof Error ? err.message : String(err))}). The payer's signature is still valid and its nonce unused \u2014 fund/fix the relayer and the payer can retry.`,
|
|
1686
|
+
{ cause: err }
|
|
1687
|
+
);
|
|
1688
|
+
}
|
|
1689
|
+
try {
|
|
1690
|
+
const confirmations = _nullishCoalesce(accept.extra.minConfirmations, () => ( 1));
|
|
1691
|
+
const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash, confirmations });
|
|
1692
|
+
if (receipt.status !== "success") {
|
|
1693
|
+
return { ok: false, error: "tx_reverted", detail: `Settlement tx ${txHash} reverted on-chain.` };
|
|
1694
|
+
}
|
|
1695
|
+
} catch (err) {
|
|
1696
|
+
throw new (0, _chunkMWBT7MCEcjs.SettlementError)(
|
|
1697
|
+
`upto settle: broadcast ${txHash} but couldn't confirm it (${shorten3(err instanceof Error ? err.message : String(err))}).`,
|
|
1698
|
+
{ cause: err }
|
|
1699
|
+
);
|
|
1700
|
+
}
|
|
1701
|
+
return {
|
|
1702
|
+
ok: true,
|
|
1703
|
+
receipt: {
|
|
1704
|
+
scheme: "upto",
|
|
1705
|
+
success: true,
|
|
1706
|
+
network: accept.network,
|
|
1707
|
+
transaction: txHash,
|
|
1708
|
+
asset: accept.asset,
|
|
1709
|
+
// The ACTUAL settled amount (≤ max) — what the buyer reads back to record metered spend.
|
|
1710
|
+
amount: settleAmount.toString(),
|
|
1711
|
+
payer: from,
|
|
1712
|
+
payTo: accept.payTo,
|
|
1713
|
+
verifiedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1714
|
+
}
|
|
1715
|
+
};
|
|
1716
|
+
}
|
|
1717
|
+
|
|
1360
1718
|
// src/x402.ts
|
|
1361
1719
|
var HEADER_REQUIRED = "payment-required";
|
|
1362
1720
|
var HEADER_SIGNATURE = "payment-signature";
|
|
@@ -1386,10 +1744,13 @@ function decodeBase64(b64) {
|
|
|
1386
1744
|
function fromBase64Json(b64) {
|
|
1387
1745
|
try {
|
|
1388
1746
|
return JSON.parse(decodeBase64(b64));
|
|
1389
|
-
} catch (
|
|
1747
|
+
} catch (e19) {
|
|
1390
1748
|
return null;
|
|
1391
1749
|
}
|
|
1392
1750
|
}
|
|
1751
|
+
function decodeBase64Json(value) {
|
|
1752
|
+
return fromBase64Json(value);
|
|
1753
|
+
}
|
|
1393
1754
|
function toBase64Json(value) {
|
|
1394
1755
|
return encodeBase64(JSON.stringify(value));
|
|
1395
1756
|
}
|
|
@@ -1405,8 +1766,15 @@ function chainIdFromNetwork(network) {
|
|
|
1405
1766
|
function buildChallengeHeader(challenge) {
|
|
1406
1767
|
return toBase64Json(challenge);
|
|
1407
1768
|
}
|
|
1408
|
-
function buildReceiptHeader(receipt) {
|
|
1409
|
-
return toBase64Json(receipt);
|
|
1769
|
+
function buildReceiptHeader(receipt, extensions) {
|
|
1770
|
+
return toBase64Json(extensions ? { ...receipt, extensions } : receipt);
|
|
1771
|
+
}
|
|
1772
|
+
var EXT_OFFER_RECEIPT = "offer-receipt";
|
|
1773
|
+
function buildReceiptExtension(bundle) {
|
|
1774
|
+
const info = { settlement: bundle.receipt, resource: bundle.resource };
|
|
1775
|
+
if (typeof bundle.decimals === "number") info.decimals = bundle.decimals;
|
|
1776
|
+
if (bundle.attestation) info.receipt = bundle.attestation;
|
|
1777
|
+
return { [EXT_OFFER_RECEIPT]: { info } };
|
|
1410
1778
|
}
|
|
1411
1779
|
function buildSignatureHeader(signature) {
|
|
1412
1780
|
return toBase64Json(signature);
|
|
@@ -1414,6 +1782,9 @@ function buildSignatureHeader(signature) {
|
|
|
1414
1782
|
function buildExactSignatureHeader(input) {
|
|
1415
1783
|
return toBase64Json({ x402Version: 2, accepted: input.accepted, payload: input.payload });
|
|
1416
1784
|
}
|
|
1785
|
+
function buildUptoSignatureHeader(input) {
|
|
1786
|
+
return toBase64Json({ x402Version: 2, accepted: input.accepted, payload: input.payload });
|
|
1787
|
+
}
|
|
1417
1788
|
async function parseChallenge(response) {
|
|
1418
1789
|
const headerValue = response.headers.get(HEADER_REQUIRED);
|
|
1419
1790
|
if (headerValue) {
|
|
@@ -1423,7 +1794,7 @@ async function parseChallenge(response) {
|
|
|
1423
1794
|
try {
|
|
1424
1795
|
const body = await response.clone().json();
|
|
1425
1796
|
if (isValidChallenge(body)) return body;
|
|
1426
|
-
} catch (
|
|
1797
|
+
} catch (e20) {
|
|
1427
1798
|
}
|
|
1428
1799
|
return null;
|
|
1429
1800
|
}
|
|
@@ -1433,6 +1804,27 @@ function parseReceipt(response) {
|
|
|
1433
1804
|
const parsed = fromBase64Json(headerValue);
|
|
1434
1805
|
return isValidReceipt(parsed) ? parsed : null;
|
|
1435
1806
|
}
|
|
1807
|
+
function parseReceiptExtension(response) {
|
|
1808
|
+
const headerValue = _nullishCoalesce(response.headers.get(HEADER_RESPONSE), () => ( response.headers.get(HEADER_RESPONSE_V1)));
|
|
1809
|
+
if (!headerValue) return null;
|
|
1810
|
+
const parsed = fromBase64Json(headerValue);
|
|
1811
|
+
if (!parsed || typeof parsed !== "object") return null;
|
|
1812
|
+
const ext = parsed.extensions;
|
|
1813
|
+
const block = _optionalChain([ext, 'optionalAccess', _12 => _12[EXT_OFFER_RECEIPT]]);
|
|
1814
|
+
const info = _optionalChain([block, 'optionalAccess', _13 => _13.info]);
|
|
1815
|
+
if (!info) return null;
|
|
1816
|
+
const settlement = isValidReceipt(info.settlement) ? info.settlement : isValidReceipt(info.receipt) ? info.receipt : void 0;
|
|
1817
|
+
if (!settlement) return null;
|
|
1818
|
+
const attestation = info.receipt && info.receipt !== settlement ? info.receipt : void 0;
|
|
1819
|
+
const res = info.resource;
|
|
1820
|
+
return {
|
|
1821
|
+
piprail: "1",
|
|
1822
|
+
receipt: settlement,
|
|
1823
|
+
resource: { url: res && typeof res.url === "string" ? res.url : "" },
|
|
1824
|
+
...typeof info.decimals === "number" ? { decimals: info.decimals } : {},
|
|
1825
|
+
...attestation ? { attestation } : {}
|
|
1826
|
+
};
|
|
1827
|
+
}
|
|
1436
1828
|
function parseSettleResponse(response) {
|
|
1437
1829
|
const headerValue = _nullishCoalesce(response.headers.get(HEADER_RESPONSE), () => ( response.headers.get(HEADER_RESPONSE_V1)));
|
|
1438
1830
|
if (!headerValue) return null;
|
|
@@ -1443,15 +1835,17 @@ function parseSettleResponse(response) {
|
|
|
1443
1835
|
...typeof parsed.transaction === "string" ? { transaction: parsed.transaction } : {},
|
|
1444
1836
|
...typeof parsed.network === "string" ? { network: parsed.network } : {},
|
|
1445
1837
|
...typeof parsed.payer === "string" ? { payer: parsed.payer } : {},
|
|
1446
|
-
...typeof parsed.errorReason === "string" ? { errorReason: parsed.errorReason } : {}
|
|
1838
|
+
...typeof parsed.errorReason === "string" ? { errorReason: parsed.errorReason } : {},
|
|
1839
|
+
// The upto SettleResponse's REQUIRED `amount` (actual settled atomic units) — string
|
|
1840
|
+
// passthrough so the upto buyer records ACTUAL, not MAX. Absent on onchain-proof/exact.
|
|
1841
|
+
...typeof parsed.amount === "string" ? { amount: parsed.amount } : {}
|
|
1447
1842
|
};
|
|
1448
1843
|
}
|
|
1449
|
-
function
|
|
1450
|
-
const parsed = fromBase64Json(value);
|
|
1844
|
+
function parseSignatureObject(parsed) {
|
|
1451
1845
|
if (!parsed || typeof parsed !== "object") return null;
|
|
1452
1846
|
const v = parsed;
|
|
1453
1847
|
const accepted = v.accepted;
|
|
1454
|
-
const scheme = _nullishCoalesce(_optionalChain([accepted, 'optionalAccess',
|
|
1848
|
+
const scheme = _nullishCoalesce(_optionalChain([accepted, 'optionalAccess', _14 => _14.scheme]), () => ( v.scheme));
|
|
1455
1849
|
if (scheme !== "onchain-proof") return null;
|
|
1456
1850
|
const payload = v.payload;
|
|
1457
1851
|
if (!payload || typeof payload.txHash !== "string" || typeof payload.nonce !== "string") {
|
|
@@ -1459,14 +1853,19 @@ function parseSignatureHeader(value) {
|
|
|
1459
1853
|
}
|
|
1460
1854
|
return parsed;
|
|
1461
1855
|
}
|
|
1856
|
+
function parseSignatureHeader(value) {
|
|
1857
|
+
return parseSignatureObject(fromBase64Json(value));
|
|
1858
|
+
}
|
|
1462
1859
|
function parseExactPaymentHeader(value) {
|
|
1463
|
-
|
|
1860
|
+
return parseExactObject(fromBase64Json(value));
|
|
1861
|
+
}
|
|
1862
|
+
function parseExactObject(parsed) {
|
|
1464
1863
|
if (!parsed || typeof parsed !== "object") return null;
|
|
1465
1864
|
const v = parsed;
|
|
1466
1865
|
const accepted = _nullishCoalesce(v.accepted, () => ( null));
|
|
1467
|
-
const scheme = _nullishCoalesce(_optionalChain([accepted, 'optionalAccess',
|
|
1866
|
+
const scheme = _nullishCoalesce(_optionalChain([accepted, 'optionalAccess', _15 => _15.scheme]), () => ( v.scheme));
|
|
1468
1867
|
if (scheme !== "exact") return null;
|
|
1469
|
-
const network = _nullishCoalesce(_optionalChain([accepted, 'optionalAccess',
|
|
1868
|
+
const network = _nullishCoalesce(_optionalChain([accepted, 'optionalAccess', _16 => _16.network]), () => ( v.network));
|
|
1470
1869
|
if (typeof network !== "string") return null;
|
|
1471
1870
|
const payload = v.payload;
|
|
1472
1871
|
if (!payload || typeof payload !== "object") return null;
|
|
@@ -1525,6 +1924,42 @@ function parseExactPaymentHeader(value) {
|
|
|
1525
1924
|
}
|
|
1526
1925
|
return null;
|
|
1527
1926
|
}
|
|
1927
|
+
function parseUptoPaymentHeader(value) {
|
|
1928
|
+
return parseUptoObject(fromBase64Json(value));
|
|
1929
|
+
}
|
|
1930
|
+
function parseUptoObject(parsed) {
|
|
1931
|
+
if (!parsed || typeof parsed !== "object") return null;
|
|
1932
|
+
const v = parsed;
|
|
1933
|
+
const accepted = _nullishCoalesce(v.accepted, () => ( null));
|
|
1934
|
+
const scheme = _nullishCoalesce(_optionalChain([accepted, 'optionalAccess', _17 => _17.scheme]), () => ( v.scheme));
|
|
1935
|
+
if (scheme !== "upto") return null;
|
|
1936
|
+
const network = _nullishCoalesce(_optionalChain([accepted, 'optionalAccess', _18 => _18.network]), () => ( v.network));
|
|
1937
|
+
if (typeof network !== "string") return null;
|
|
1938
|
+
const payload = v.payload;
|
|
1939
|
+
if (!payload || typeof payload !== "object") return null;
|
|
1940
|
+
const signature = payload.signature;
|
|
1941
|
+
if (typeof signature !== "string") return null;
|
|
1942
|
+
const p2 = payload.permit2Authorization;
|
|
1943
|
+
if (!p2 || typeof p2 !== "object") return null;
|
|
1944
|
+
const permitted = p2.permitted;
|
|
1945
|
+
const witness = p2.witness;
|
|
1946
|
+
if (!permitted || typeof permitted !== "object" || !witness || typeof witness !== "object") return null;
|
|
1947
|
+
if (typeof permitted.token !== "string" || typeof permitted.amount !== "string") return null;
|
|
1948
|
+
if (typeof witness.to !== "string" || typeof witness.facilitator !== "string" || typeof witness.validAfter !== "string") {
|
|
1949
|
+
return null;
|
|
1950
|
+
}
|
|
1951
|
+
for (const k of ["from", "spender", "nonce", "deadline"]) {
|
|
1952
|
+
if (typeof p2[k] !== "string") return null;
|
|
1953
|
+
}
|
|
1954
|
+
const x402Version = typeof v.x402Version === "number" ? v.x402Version : 2;
|
|
1955
|
+
const asset = accepted && typeof accepted.asset === "string" ? accepted.asset : void 0;
|
|
1956
|
+
const base2 = { x402Version, network, ...asset ? { asset } : {}, raw: v };
|
|
1957
|
+
return {
|
|
1958
|
+
...base2,
|
|
1959
|
+
method: "permit2-upto",
|
|
1960
|
+
payload: { signature, permit2Authorization: p2 }
|
|
1961
|
+
};
|
|
1962
|
+
}
|
|
1528
1963
|
function isValidChallenge(value) {
|
|
1529
1964
|
if (!value || typeof value !== "object") return false;
|
|
1530
1965
|
const v = value;
|
|
@@ -1537,7 +1972,7 @@ function isValidChallenge(value) {
|
|
|
1537
1972
|
function isValidReceipt(value) {
|
|
1538
1973
|
if (!value || typeof value !== "object") return false;
|
|
1539
1974
|
const v = value;
|
|
1540
|
-
if (v.scheme !== "onchain-proof" && v.scheme !== "exact") return false;
|
|
1975
|
+
if (v.scheme !== "onchain-proof" && v.scheme !== "exact" && v.scheme !== "upto") return false;
|
|
1541
1976
|
if (typeof v.transaction !== "string" && typeof v.txHash !== "string") return false;
|
|
1542
1977
|
if (typeof v.payer !== "string") return false;
|
|
1543
1978
|
return true;
|
|
@@ -1560,7 +1995,7 @@ var evmDriver = {
|
|
|
1560
1995
|
let resolved;
|
|
1561
1996
|
try {
|
|
1562
1997
|
resolved = resolveChain(opts.chain, opts.rpcUrl);
|
|
1563
|
-
} catch (
|
|
1998
|
+
} catch (e21) {
|
|
1564
1999
|
return null;
|
|
1565
2000
|
}
|
|
1566
2001
|
return makeEvmNetwork(resolved);
|
|
@@ -1616,7 +2051,7 @@ function makeEvmNetwork(resolved) {
|
|
|
1616
2051
|
let normalized;
|
|
1617
2052
|
try {
|
|
1618
2053
|
normalized = _viem.getAddress.call(void 0, asset);
|
|
1619
|
-
} catch (
|
|
2054
|
+
} catch (e22) {
|
|
1620
2055
|
return null;
|
|
1621
2056
|
}
|
|
1622
2057
|
for (const info of Object.values(resolved.tokens)) {
|
|
@@ -1702,7 +2137,7 @@ function makeEvmNetwork(resolved) {
|
|
|
1702
2137
|
basis: "estimated",
|
|
1703
2138
|
detail: `~${gasLimit} gas @ ${gasPrice} wei/gas`
|
|
1704
2139
|
});
|
|
1705
|
-
} catch (
|
|
2140
|
+
} catch (e23) {
|
|
1706
2141
|
const gasPrice = 5000000000n;
|
|
1707
2142
|
return _chunkMWBT7MCEcjs.nativeCost.call(void 0, {
|
|
1708
2143
|
symbol,
|
|
@@ -1725,7 +2160,7 @@ function makeEvmNetwork(resolved) {
|
|
|
1725
2160
|
functionName: "balanceOf",
|
|
1726
2161
|
args: [owner]
|
|
1727
2162
|
});
|
|
1728
|
-
} catch (
|
|
2163
|
+
} catch (e24) {
|
|
1729
2164
|
token = null;
|
|
1730
2165
|
}
|
|
1731
2166
|
return { token, native };
|
|
@@ -1745,6 +2180,12 @@ function makeEvmNetwork(resolved) {
|
|
|
1745
2180
|
signMessage: (message) => a.walletClient.signMessage({ account: a.account, message })
|
|
1746
2181
|
};
|
|
1747
2182
|
},
|
|
2183
|
+
// Tier-2 service-delivery attestation (EVM-only) — sign the official offer-receipt
|
|
2184
|
+
// EIP-712 RECEIPT_TYPES with the bound (payTo) wallet. Chain-independent (domain
|
|
2185
|
+
// chainId is hardcoded 1); viem lives in ./receipt.ts (a lazy chunk).
|
|
2186
|
+
signReceipt(wallet, input) {
|
|
2187
|
+
return _chunkCQQI5IJXcjs.signReceiptEvm.call(void 0, wallet, input);
|
|
2188
|
+
},
|
|
1748
2189
|
async verify(ref, accept) {
|
|
1749
2190
|
return verifyEvm({
|
|
1750
2191
|
publicClient,
|
|
@@ -1828,6 +2269,43 @@ function makeEvmNetwork(resolved) {
|
|
|
1828
2269
|
payload,
|
|
1829
2270
|
accept
|
|
1830
2271
|
});
|
|
2272
|
+
},
|
|
2273
|
+
// Standard x402 `upto` (metered) rail — EVM-Permit2 ONLY. The metered sibling of the
|
|
2274
|
+
// exact trio. resolveUptoRail advertises (Permit2-only, proxy-gated, relayer = facilitator);
|
|
2275
|
+
// payUpto signs the MAX with witness.facilitator bound; settleUptoSelf self-settles the actual.
|
|
2276
|
+
async resolveUptoRail({ asset, relayer }) {
|
|
2277
|
+
const relayerAddress = relayer._native.account.address;
|
|
2278
|
+
const domain = asset === "native" ? null : await readExactDomain(publicClient, asset).catch(() => null);
|
|
2279
|
+
return resolveUptoRailEvm({
|
|
2280
|
+
asset,
|
|
2281
|
+
relayerAddress,
|
|
2282
|
+
proxySupported: () => isUptoProxyChain(resolved.chainId),
|
|
2283
|
+
domain
|
|
2284
|
+
});
|
|
2285
|
+
},
|
|
2286
|
+
async payUpto(wallet, accept) {
|
|
2287
|
+
const a = wallet._native;
|
|
2288
|
+
const { payload, payerFrom, nonce } = await payUptoEvm({
|
|
2289
|
+
publicClient,
|
|
2290
|
+
walletClient: a.walletClient,
|
|
2291
|
+
account: a.account,
|
|
2292
|
+
chainId: resolved.chainId,
|
|
2293
|
+
chain: resolved.chain,
|
|
2294
|
+
accept
|
|
2295
|
+
});
|
|
2296
|
+
return { payload, accepted: accept, payerFrom, nonce };
|
|
2297
|
+
},
|
|
2298
|
+
async settleUptoSelf({ relayer, payload, accept, settleAmount }) {
|
|
2299
|
+
const a = relayer._native;
|
|
2300
|
+
return verifyAndSettleUptoEvm({
|
|
2301
|
+
publicClient,
|
|
2302
|
+
walletClient: a.walletClient,
|
|
2303
|
+
account: a.account,
|
|
2304
|
+
chain: resolved.chain,
|
|
2305
|
+
payload,
|
|
2306
|
+
accept,
|
|
2307
|
+
settleAmount
|
|
2308
|
+
});
|
|
1831
2309
|
}
|
|
1832
2310
|
};
|
|
1833
2311
|
}
|
|
@@ -1868,7 +2346,7 @@ var loaders = {
|
|
|
1868
2346
|
stellar: async () => {
|
|
1869
2347
|
let mod;
|
|
1870
2348
|
try {
|
|
1871
|
-
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./stellar-
|
|
2349
|
+
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./stellar-CRWBSX4E.cjs")));
|
|
1872
2350
|
} catch (cause) {
|
|
1873
2351
|
throw new (0, _chunkMWBT7MCEcjs.MissingDriverError)(
|
|
1874
2352
|
`Stellar selected, but its package isn't installed. Run: npm install @stellar/stellar-sdk`,
|
|
@@ -1892,7 +2370,7 @@ var loaders = {
|
|
|
1892
2370
|
tron: async () => {
|
|
1893
2371
|
let mod;
|
|
1894
2372
|
try {
|
|
1895
|
-
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./tron-
|
|
2373
|
+
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./tron-OMXB6EW2.cjs")));
|
|
1896
2374
|
} catch (cause) {
|
|
1897
2375
|
throw new (0, _chunkMWBT7MCEcjs.MissingDriverError)(
|
|
1898
2376
|
`Tron selected, but its package isn't installed. Run: npm install tronweb`,
|
|
@@ -1904,7 +2382,7 @@ var loaders = {
|
|
|
1904
2382
|
sui: async () => {
|
|
1905
2383
|
let mod;
|
|
1906
2384
|
try {
|
|
1907
|
-
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./sui-
|
|
2385
|
+
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./sui-Y4RLKKE2.cjs")));
|
|
1908
2386
|
} catch (cause) {
|
|
1909
2387
|
throw new (0, _chunkMWBT7MCEcjs.MissingDriverError)(
|
|
1910
2388
|
`Sui selected, but its package isn't installed. Run: npm install @mysten/sui`,
|
|
@@ -2109,7 +2587,7 @@ function fieldTokens(r) {
|
|
|
2109
2587
|
try {
|
|
2110
2588
|
const u = new URL(r.resource);
|
|
2111
2589
|
pathText = `${u.hostname} ${u.pathname}`;
|
|
2112
|
-
} catch (
|
|
2590
|
+
} catch (e25) {
|
|
2113
2591
|
}
|
|
2114
2592
|
return [
|
|
2115
2593
|
[tokenize(r.name), FIELD_WEIGHTS.name],
|
|
@@ -2164,7 +2642,7 @@ function sortResources(items, sort, order) {
|
|
|
2164
2642
|
async function safeSearch(run) {
|
|
2165
2643
|
try {
|
|
2166
2644
|
return await run();
|
|
2167
|
-
} catch (
|
|
2645
|
+
} catch (e26) {
|
|
2168
2646
|
return [];
|
|
2169
2647
|
}
|
|
2170
2648
|
}
|
|
@@ -2303,7 +2781,7 @@ async function register402Index(input) {
|
|
|
2303
2781
|
if (res.ok) {
|
|
2304
2782
|
const body = await res.json().catch(() => ({}));
|
|
2305
2783
|
const msg = typeof body.message === "string" && body.message.length > 0 ? body.message : void 0;
|
|
2306
|
-
const live = _optionalChain([body, 'access',
|
|
2784
|
+
const live = _optionalChain([body, 'access', _19 => _19.service, 'optionalAccess', _20 => _20.status]) === "active";
|
|
2307
2785
|
return {
|
|
2308
2786
|
source: "402index",
|
|
2309
2787
|
ok: true,
|
|
@@ -2330,7 +2808,7 @@ async function readIndexError(res) {
|
|
|
2330
2808
|
(p) => typeof p === "string" && p.length > 0
|
|
2331
2809
|
);
|
|
2332
2810
|
return parts.length ? [...new Set(parts)].join(" \u2014 ") : void 0;
|
|
2333
|
-
} catch (
|
|
2811
|
+
} catch (e27) {
|
|
2334
2812
|
return void 0;
|
|
2335
2813
|
}
|
|
2336
2814
|
}
|
|
@@ -2440,11 +2918,11 @@ async function readSiwxInfo(res) {
|
|
|
2440
2918
|
try {
|
|
2441
2919
|
const body = await res.json();
|
|
2442
2920
|
const ext = body.extensions;
|
|
2443
|
-
const siwx = _optionalChain([ext, 'optionalAccess',
|
|
2444
|
-
const info = _nullishCoalesce(_optionalChain([siwx, 'optionalAccess',
|
|
2445
|
-
if (info && info.chainId == null && Array.isArray(_optionalChain([siwx, 'optionalAccess',
|
|
2921
|
+
const siwx = _optionalChain([ext, 'optionalAccess', _21 => _21["sign-in-with-x"]]);
|
|
2922
|
+
const info = _nullishCoalesce(_optionalChain([siwx, 'optionalAccess', _22 => _22.info]), () => ( siwx));
|
|
2923
|
+
if (info && info.chainId == null && Array.isArray(_optionalChain([siwx, 'optionalAccess', _23 => _23.supportedChains]))) {
|
|
2446
2924
|
const evm = siwx.supportedChains.find(
|
|
2447
|
-
(c) => typeof _optionalChain([c, 'optionalAccess',
|
|
2925
|
+
(c) => typeof _optionalChain([c, 'optionalAccess', _24 => _24.chainId]) === "string" && c.chainId.startsWith("eip155:")
|
|
2448
2926
|
);
|
|
2449
2927
|
if (evm && typeof evm.chainId === "string") info.chainId = evm.chainId;
|
|
2450
2928
|
}
|
|
@@ -2452,7 +2930,7 @@ async function readSiwxInfo(res) {
|
|
|
2452
2930
|
return info;
|
|
2453
2931
|
}
|
|
2454
2932
|
return null;
|
|
2455
|
-
} catch (
|
|
2933
|
+
} catch (e28) {
|
|
2456
2934
|
return null;
|
|
2457
2935
|
}
|
|
2458
2936
|
}
|
|
@@ -2549,7 +3027,7 @@ function hostOf(url) {
|
|
|
2549
3027
|
try {
|
|
2550
3028
|
const withScheme = /^[a-z][a-z0-9+.-]*:\/\//i.test(url) ? url : `https://${url}`;
|
|
2551
3029
|
return new URL(withScheme).hostname || url;
|
|
2552
|
-
} catch (
|
|
3030
|
+
} catch (e29) {
|
|
2553
3031
|
return url;
|
|
2554
3032
|
}
|
|
2555
3033
|
}
|
|
@@ -2598,7 +3076,7 @@ var BUILTIN_DENOMS = {
|
|
|
2598
3076
|
function denomOf(symbol, asset, policy) {
|
|
2599
3077
|
if (asset === "native") return void 0;
|
|
2600
3078
|
const norm = (v) => typeof v === "string" && v.trim() !== "" ? v.trim().toUpperCase() : void 0;
|
|
2601
|
-
const override = _optionalChain([policy, 'optionalAccess',
|
|
3079
|
+
const override = _optionalChain([policy, 'optionalAccess', _25 => _25.denomFor]);
|
|
2602
3080
|
if (override && typeof override === "object") {
|
|
2603
3081
|
if (asset && asset in override) {
|
|
2604
3082
|
const d = norm(override[asset]);
|
|
@@ -2796,10 +3274,10 @@ var SpendLedger = (_class = class {
|
|
|
2796
3274
|
let seed = [];
|
|
2797
3275
|
try {
|
|
2798
3276
|
seed = _nullishCoalesce(store.load(), () => ( []));
|
|
2799
|
-
} catch (
|
|
3277
|
+
} catch (e30) {
|
|
2800
3278
|
seed = [];
|
|
2801
3279
|
}
|
|
2802
|
-
for (const r of seed) this.ingest(r, _nullishCoalesce(_optionalChain([r, 'optionalAccess',
|
|
3280
|
+
for (const r of seed) this.ingest(r, _nullishCoalesce(_optionalChain([r, 'optionalAccess', _26 => _26.decimals]), () => ( 0)), _optionalChain([r, 'optionalAccess', _27 => _27.denom]));
|
|
2803
3281
|
}
|
|
2804
3282
|
}
|
|
2805
3283
|
/**
|
|
@@ -2855,13 +3333,13 @@ var SpendLedger = (_class = class {
|
|
|
2855
3333
|
if (rec && this.store) {
|
|
2856
3334
|
try {
|
|
2857
3335
|
this.store.append(rec);
|
|
2858
|
-
} catch (
|
|
3336
|
+
} catch (e31) {
|
|
2859
3337
|
}
|
|
2860
3338
|
}
|
|
2861
3339
|
}
|
|
2862
3340
|
/** Running total (base units) already spent on this (network, asset). */
|
|
2863
3341
|
totalFor(network, asset) {
|
|
2864
|
-
return _nullishCoalesce(_optionalChain([this, 'access',
|
|
3342
|
+
return _nullishCoalesce(_optionalChain([this, 'access', _28 => _28.buckets, 'access', _29 => _29.get, 'call', _30 => _30(keyFor(network, asset)), 'optionalAccess', _31 => _31.total]), () => ( 0n));
|
|
2865
3343
|
}
|
|
2866
3344
|
/**
|
|
2867
3345
|
* Running grand total for a DENOMINATION, scaled to {@link DENOM_PRECISION} (so
|
|
@@ -2955,7 +3433,7 @@ var SpendLedger = (_class = class {
|
|
|
2955
3433
|
denom,
|
|
2956
3434
|
totalScaled: scaled.toString(),
|
|
2957
3435
|
totalFormatted: _chunkMWBT7MCEcjs.formatUnits.call(void 0, scaled, DENOM_PRECISION),
|
|
2958
|
-
count: this.records.filter((r) => _optionalChain([r, 'access',
|
|
3436
|
+
count: this.records.filter((r) => _optionalChain([r, 'access', _32 => _32.denom, 'optionalAccess', _33 => _33.toUpperCase, 'call', _34 => _34()]) === denom).length
|
|
2959
3437
|
})),
|
|
2960
3438
|
records: [...this.records]
|
|
2961
3439
|
};
|
|
@@ -2970,7 +3448,8 @@ var RECIPIENT_FIX = {
|
|
|
2970
3448
|
NOT_OPTED_IN: "the recipient must opt into this asset once (a 0-amount self-transfer)",
|
|
2971
3449
|
INACTIVE: "the recipient account doesn't exist yet \u2014 fund it with the chain's base reserve to activate it"
|
|
2972
3450
|
};
|
|
2973
|
-
var
|
|
3451
|
+
var RECEIPT_VERIFY_WINDOW_SECONDS = 100 * 365 * 24 * 60 * 60;
|
|
3452
|
+
var PipRailClient = (_class2 = class {
|
|
2974
3453
|
|
|
2975
3454
|
|
|
2976
3455
|
|
|
@@ -2986,7 +3465,11 @@ var PipRailClient = class {
|
|
|
2986
3465
|
// Resolved lazily on first request — this is what lets Solana (and future
|
|
2987
3466
|
// families) auto-mount with no setup call.
|
|
2988
3467
|
|
|
2989
|
-
|
|
3468
|
+
// The verifiable receipt from the most recent settled fetch (null if the server emitted
|
|
3469
|
+
// none). Captured pure (no chain read) and surfaced via lastReceipt(); the resource URL is
|
|
3470
|
+
// stamped from the URL this client actually fetched (authoritative over the gate's default).
|
|
3471
|
+
__init6() {this.lastReceiptValue = null}
|
|
3472
|
+
constructor(opts) {;_class2.prototype.__init6.call(this);
|
|
2990
3473
|
this.opts = opts;
|
|
2991
3474
|
this.maxRetries = Math.max(1, _nullishCoalesce(opts.maxPaymentRetries, () => ( 3)));
|
|
2992
3475
|
this.retryTimeoutMs = _nullishCoalesce(opts.retryTimeoutMs, () => ( 3e4));
|
|
@@ -3129,7 +3612,130 @@ var PipRailClient = class {
|
|
|
3129
3612
|
safeEmit(event) {
|
|
3130
3613
|
try {
|
|
3131
3614
|
this.onEvent(event);
|
|
3132
|
-
} catch (
|
|
3615
|
+
} catch (e32) {
|
|
3616
|
+
}
|
|
3617
|
+
}
|
|
3618
|
+
/**
|
|
3619
|
+
* Capture the verifiable receipt from a settled response (pure — no chain read), stamping
|
|
3620
|
+
* the resource URL this client actually fetched (authoritative over the gate's default ''). A
|
|
3621
|
+
* settled fetch with no receipt extension sets it to `null` so {@link lastReceipt} reflects the
|
|
3622
|
+
* latest fetch. Never throws — a malformed header just yields `null`.
|
|
3623
|
+
*/
|
|
3624
|
+
captureReceipt(response, url) {
|
|
3625
|
+
try {
|
|
3626
|
+
const parsed = parseReceiptExtension(response);
|
|
3627
|
+
this.lastReceiptValue = parsed ? { ...parsed, resource: { url } } : null;
|
|
3628
|
+
} catch (e33) {
|
|
3629
|
+
this.lastReceiptValue = null;
|
|
3630
|
+
}
|
|
3631
|
+
}
|
|
3632
|
+
/**
|
|
3633
|
+
* The verifiable {@link PipRailReceipt} from the most recent settled `fetch` — the
|
|
3634
|
+
* self-contained record the buyer KEEPS and anyone re-verifies against the chain
|
|
3635
|
+
* (see {@link PipRailClient.verifyReceipt}). `null` when the last settled fetch carried
|
|
3636
|
+
* no receipt (the gate's `receipts` option was off) or no payment has settled yet. Pure.
|
|
3637
|
+
*/
|
|
3638
|
+
lastReceipt() {
|
|
3639
|
+
return this.lastReceiptValue;
|
|
3640
|
+
}
|
|
3641
|
+
/**
|
|
3642
|
+
* Re-verify ANY {@link PipRailReceipt} against the chain — the anyone-can-run primitive.
|
|
3643
|
+
* Re-reads `receipt.transaction` via the receipt's own network driver and re-derives
|
|
3644
|
+
* `payTo`/`asset`/`payer` from the tx, **never trusting the receipt's claims**: a forged
|
|
3645
|
+
* `payTo`/`asset`/over-stated `amount` makes the driver's `verify()` fail (`ok:false`); a
|
|
3646
|
+
* forged `payer` surfaces as `matchesClaims:false`. Static + WALLET-FREE — a third party
|
|
3647
|
+
* verifies with only a chain + RPC, no PipRail account. **Never throws** (an RPC error or a
|
|
3648
|
+
* malformed receipt → `{ ok:false, error }`). Viem-free here — the chain read happens inside
|
|
3649
|
+
* the lazily-mounted family driver (the protocol layer pulls no chain libs). Durable for
|
|
3650
|
+
* digest-bound families; recency-bounded for the account-watch families (see
|
|
3651
|
+
* {@link ReceiptVerification}).
|
|
3652
|
+
*/
|
|
3653
|
+
static async verifyReceipt(receipt, opts) {
|
|
3654
|
+
const r = _optionalChain([receipt, 'optionalAccess', _35 => _35.receipt]);
|
|
3655
|
+
if (!r || typeof r !== "object") {
|
|
3656
|
+
return { ok: false, onChain: { payTo: "", asset: "", amount: "", payer: "" }, matchesClaims: false, ageSeconds: 0, error: "tx_not_found" };
|
|
3657
|
+
}
|
|
3658
|
+
const claimed = { payTo: _nullishCoalesce(r.payTo, () => ( "")), asset: _nullishCoalesce(r.asset, () => ( "")), amount: _nullishCoalesce(r.amount, () => ( "")), payer: _nullishCoalesce(r.payer, () => ( "")) };
|
|
3659
|
+
const ageSeconds = receiptAgeSeconds(r.verifiedAt);
|
|
3660
|
+
try {
|
|
3661
|
+
const chain = chainSelectorForNetwork(r.network, _optionalChain([opts, 'optionalAccess', _36 => _36.rpcUrl]));
|
|
3662
|
+
const net = await resolveNetwork2({
|
|
3663
|
+
chain,
|
|
3664
|
+
..._optionalChain([opts, 'optionalAccess', _37 => _37.rpcUrl]) ? { rpcUrl: opts.rpcUrl } : {}
|
|
3665
|
+
});
|
|
3666
|
+
const accept = {
|
|
3667
|
+
scheme: "onchain-proof",
|
|
3668
|
+
network: r.network,
|
|
3669
|
+
amount: r.amount,
|
|
3670
|
+
asset: r.asset,
|
|
3671
|
+
payTo: r.payTo,
|
|
3672
|
+
maxTimeoutSeconds: RECEIPT_VERIFY_WINDOW_SECONDS,
|
|
3673
|
+
extra: {
|
|
3674
|
+
nonce: _nullishCoalesce(r.nonce, () => ( "")),
|
|
3675
|
+
// the challenge/memo nonce — REQUIRED for Template-A re-verify
|
|
3676
|
+
decimals: _nullishCoalesce(receipt.decimals, () => ( 6)),
|
|
3677
|
+
// B10c — Stellar/XRPL/TON re-scale by it; 6 = USDC fallback
|
|
3678
|
+
minConfirmations: 0,
|
|
3679
|
+
amountFormatted: ""
|
|
3680
|
+
}
|
|
3681
|
+
};
|
|
3682
|
+
const ref = familyForChain(chain) === "near" ? `${r.payer}:${r.transaction}` : r.transaction;
|
|
3683
|
+
const result = await net.verify(ref, accept);
|
|
3684
|
+
if (!result.ok) {
|
|
3685
|
+
return { ok: false, onChain: claimed, matchesClaims: false, ageSeconds, error: result.error };
|
|
3686
|
+
}
|
|
3687
|
+
const oc = result.receipt;
|
|
3688
|
+
const onChain = { payTo: oc.payTo, asset: oc.asset, amount: oc.amount, payer: oc.payer };
|
|
3689
|
+
const matchesClaims = sameAddress(oc.payer, r.payer);
|
|
3690
|
+
return { ok: true, onChain, matchesClaims, ageSeconds };
|
|
3691
|
+
} catch (e34) {
|
|
3692
|
+
return { ok: false, onChain: claimed, matchesClaims: false, ageSeconds, error: "tx_not_found" };
|
|
3693
|
+
}
|
|
3694
|
+
}
|
|
3695
|
+
/**
|
|
3696
|
+
* Verify the OPTIONAL Tier-2 service-delivery attestation on a {@link PipRailReceipt}
|
|
3697
|
+
* — the merchant's signed proof that the resource was actually SERVED (the one thing
|
|
3698
|
+
* the chain can't attest). For an EVM EIP-712 attestation this re-recovers the signer
|
|
3699
|
+
* from the signature over the official `offer-receipt` typed data and checks
|
|
3700
|
+
* `recover === receipt.payTo` (spec §4.5.1 / §5.5) — the classic EIP-712 footgun made
|
|
3701
|
+
* safe (`recoverTypedDataAddress` returns a WRONG address rather than throwing on a bad
|
|
3702
|
+
* signature, so the equality check is the real verification). A tampered signature →
|
|
3703
|
+
* `{ ok:false }`, never a throw.
|
|
3704
|
+
*
|
|
3705
|
+
* Static + wallet-free. **Never throws** (a malformed/absent attestation, an unsupported
|
|
3706
|
+
* format, or a recovery fault → `{ ok:false, reason }`). Viem-free HERE — the recover runs
|
|
3707
|
+
* inside the lazily-imported EVM receipt driver (a lazy chunk), so the protocol layer pulls
|
|
3708
|
+
* no chain libs. The JWS format defers to R3 (`{ ok:false, reason:'jws-not-loaded' }`).
|
|
3709
|
+
*/
|
|
3710
|
+
static async verifyAttestation(receipt) {
|
|
3711
|
+
const att = _optionalChain([receipt, 'optionalAccess', _38 => _38.attestation]);
|
|
3712
|
+
if (!att || typeof att !== "object" || typeof att.signature !== "string") {
|
|
3713
|
+
return { ok: false, reason: "no-attestation" };
|
|
3714
|
+
}
|
|
3715
|
+
if (att.format === "jws") {
|
|
3716
|
+
return { ok: false, reason: "jws-not-loaded" };
|
|
3717
|
+
}
|
|
3718
|
+
const r = receipt.receipt;
|
|
3719
|
+
if (!r || typeof r !== "object") return { ok: false, reason: "no-receipt" };
|
|
3720
|
+
const payload = _nullishCoalesce(att.payload, () => ( {}));
|
|
3721
|
+
const network = typeof payload.network === "string" ? payload.network : r.network;
|
|
3722
|
+
const resourceUrl = typeof payload.resourceUrl === "string" ? payload.resourceUrl : _nullishCoalesce(_optionalChain([receipt, 'access', _39 => _39.resource, 'optionalAccess', _40 => _40.url]), () => ( ""));
|
|
3723
|
+
const payer = typeof payload.payer === "string" ? payload.payer : r.payer;
|
|
3724
|
+
const issuedAt = typeof payload.issuedAt === "number" ? payload.issuedAt : receiptIssuedAtSeconds(r.verifiedAt);
|
|
3725
|
+
const transaction = typeof payload.transaction === "string" ? payload.transaction : _nullishCoalesce(r.transaction, () => ( ""));
|
|
3726
|
+
try {
|
|
3727
|
+
const { verifyReceiptAttestationEvm } = await Promise.resolve().then(() => _interopRequireWildcard(require("./receipt-QCDPMWNF.cjs")));
|
|
3728
|
+
return await verifyReceiptAttestationEvm({
|
|
3729
|
+
payTo: r.payTo,
|
|
3730
|
+
network,
|
|
3731
|
+
resourceUrl,
|
|
3732
|
+
payer,
|
|
3733
|
+
issuedAt,
|
|
3734
|
+
transaction,
|
|
3735
|
+
signature: att.signature
|
|
3736
|
+
});
|
|
3737
|
+
} catch (e35) {
|
|
3738
|
+
return { ok: false, reason: "verify-failed" };
|
|
3133
3739
|
}
|
|
3134
3740
|
}
|
|
3135
3741
|
/** Auto-mount the chain's driver, resolve the network, and bind the wallet — once. */
|
|
@@ -3159,7 +3765,7 @@ var PipRailClient = class {
|
|
|
3159
3765
|
* as-is) or a plain object (serialised as JSON).
|
|
3160
3766
|
*/
|
|
3161
3767
|
post(url, body, init) {
|
|
3162
|
-
const headers = new Headers(_optionalChain([init, 'optionalAccess',
|
|
3768
|
+
const headers = new Headers(_optionalChain([init, 'optionalAccess', _41 => _41.headers]));
|
|
3163
3769
|
let payload;
|
|
3164
3770
|
if (body === void 0 || body === null) {
|
|
3165
3771
|
payload = void 0;
|
|
@@ -3190,7 +3796,7 @@ var PipRailClient = class {
|
|
|
3190
3796
|
* "0.05 USDC on Base, within budget → pay it." No funds move.
|
|
3191
3797
|
*/
|
|
3192
3798
|
async quote(url, init) {
|
|
3193
|
-
const res = await fetch(url, { ..._nullishCoalesce(init, () => ( {})), method: _nullishCoalesce(_optionalChain([init, 'optionalAccess',
|
|
3799
|
+
const res = await fetch(url, { ..._nullishCoalesce(init, () => ( {})), method: _nullishCoalesce(_optionalChain([init, 'optionalAccess', _42 => _42.method]), () => ( "GET")) });
|
|
3194
3800
|
if (res.status !== 402) return null;
|
|
3195
3801
|
const { quote } = await this.resolveChallenge(url, res, this.resolveSchemes());
|
|
3196
3802
|
return quote;
|
|
@@ -3209,11 +3815,16 @@ var PipRailClient = class {
|
|
|
3209
3815
|
* on Tron, where a USD₮ transfer can cost real TRX.
|
|
3210
3816
|
*/
|
|
3211
3817
|
async estimateCost(url, init) {
|
|
3212
|
-
const res = await fetch(url, { ..._nullishCoalesce(init, () => ( {})), method: _nullishCoalesce(_optionalChain([init, 'optionalAccess',
|
|
3818
|
+
const res = await fetch(url, { ..._nullishCoalesce(init, () => ( {})), method: _nullishCoalesce(_optionalChain([init, 'optionalAccess', _43 => _43.method]), () => ( "GET")) });
|
|
3213
3819
|
if (res.status !== 402) return null;
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3820
|
+
try {
|
|
3821
|
+
const { net, accept, quote } = await this.resolveChallenge(url, res, this.resolveSchemes());
|
|
3822
|
+
const cost = await net.estimateCost(accept);
|
|
3823
|
+
return { quote, cost };
|
|
3824
|
+
} catch (err) {
|
|
3825
|
+
if (err instanceof _chunkMWBT7MCEcjs.InvalidEnvelopeError) return null;
|
|
3826
|
+
throw err;
|
|
3827
|
+
}
|
|
3217
3828
|
}
|
|
3218
3829
|
/** Aggregated snapshot of every payment this client has settled — total
|
|
3219
3830
|
* count, cumulative spend per token, cumulative spend per denomination (the
|
|
@@ -3242,8 +3853,8 @@ var PipRailClient = class {
|
|
|
3242
3853
|
return {
|
|
3243
3854
|
session: {
|
|
3244
3855
|
start,
|
|
3245
|
-
expiresAt: _optionalChain([view, 'optionalAccess',
|
|
3246
|
-
secondsRemaining: _nullishCoalesce(_optionalChain([view, 'optionalAccess',
|
|
3856
|
+
expiresAt: _optionalChain([view, 'optionalAccess', _44 => _44.expiresAt]) != null ? new Date(view.expiresAt).toISOString() : null,
|
|
3857
|
+
secondsRemaining: _nullishCoalesce(_optionalChain([view, 'optionalAccess', _45 => _45.secondsRemaining]), () => ( null))
|
|
3247
3858
|
},
|
|
3248
3859
|
byAsset: this.remaining(),
|
|
3249
3860
|
byDenom: this.denomRemaining(),
|
|
@@ -3258,7 +3869,7 @@ var PipRailClient = class {
|
|
|
3258
3869
|
* price-converted figure (tokens grouped as one unit, each 1:1).
|
|
3259
3870
|
*/
|
|
3260
3871
|
denomRemaining() {
|
|
3261
|
-
const caps = _optionalChain([this, 'access',
|
|
3872
|
+
const caps = _optionalChain([this, 'access', _46 => _46.opts, 'access', _47 => _47.policy, 'optionalAccess', _48 => _48.maxTotalPerDenom]);
|
|
3262
3873
|
if (!caps) return [];
|
|
3263
3874
|
return Object.entries(caps).map(([rawDenom, capStr]) => {
|
|
3264
3875
|
const denom = rawDenom.toUpperCase();
|
|
@@ -3281,11 +3892,11 @@ var PipRailClient = class {
|
|
|
3281
3892
|
const policy = this.opts.policy;
|
|
3282
3893
|
const settled = this.ledger.count();
|
|
3283
3894
|
const out = { settled };
|
|
3284
|
-
if (_optionalChain([policy, 'optionalAccess',
|
|
3895
|
+
if (_optionalChain([policy, 'optionalAccess', _49 => _49.maxPayments]) !== void 0) {
|
|
3285
3896
|
out.lifetimeCap = policy.maxPayments;
|
|
3286
3897
|
out.lifetimeRemaining = Math.max(0, policy.maxPayments - settled);
|
|
3287
3898
|
}
|
|
3288
|
-
if (_optionalChain([policy, 'optionalAccess',
|
|
3899
|
+
if (_optionalChain([policy, 'optionalAccess', _50 => _50.maxPaymentsPerWindow]) !== void 0 && policy.windowSeconds !== void 0) {
|
|
3289
3900
|
const windowSettled = this.ledger.countSince(Date.now() - policy.windowSeconds * 1e3);
|
|
3290
3901
|
out.windowCap = policy.maxPaymentsPerWindow;
|
|
3291
3902
|
out.windowSettled = windowSettled;
|
|
@@ -3301,7 +3912,7 @@ var PipRailClient = class {
|
|
|
3301
3912
|
* never throws, never sums across tokens (no price oracle). PROCESS-SCOPED.
|
|
3302
3913
|
*/
|
|
3303
3914
|
remaining() {
|
|
3304
|
-
const maxTotal = _optionalChain([this, 'access',
|
|
3915
|
+
const maxTotal = _optionalChain([this, 'access', _51 => _51.opts, 'access', _52 => _52.policy, 'optionalAccess', _53 => _53.maxTotal]);
|
|
3305
3916
|
return this.ledger.assetBuckets().map((b) => {
|
|
3306
3917
|
const base2 = {
|
|
3307
3918
|
network: b.network,
|
|
@@ -3353,7 +3964,7 @@ var PipRailClient = class {
|
|
|
3353
3964
|
* the plan yourself. No funds move.
|
|
3354
3965
|
*/
|
|
3355
3966
|
async planPayment(url, init) {
|
|
3356
|
-
const res = await fetch(url, { ..._nullishCoalesce(init, () => ( {})), method: _nullishCoalesce(_optionalChain([init, 'optionalAccess',
|
|
3967
|
+
const res = await fetch(url, { ..._nullishCoalesce(init, () => ( {})), method: _nullishCoalesce(_optionalChain([init, 'optionalAccess', _54 => _54.method]), () => ( "GET")) });
|
|
3357
3968
|
if (res.status !== 402) return null;
|
|
3358
3969
|
const challenge = await parseChallenge(res);
|
|
3359
3970
|
if (!challenge) {
|
|
@@ -3534,7 +4145,7 @@ var PipRailClient = class {
|
|
|
3534
4145
|
* streams throw `NonReplayableBodyError`.
|
|
3535
4146
|
*/
|
|
3536
4147
|
async fetch(url, init) {
|
|
3537
|
-
const body = _optionalChain([init, 'optionalAccess',
|
|
4148
|
+
const body = _optionalChain([init, 'optionalAccess', _55 => _55.body]);
|
|
3538
4149
|
if (body !== void 0 && body !== null && !isReplayableBodyInit(body)) {
|
|
3539
4150
|
throw new (0, _chunkMWBT7MCEcjs.NonReplayableBodyError)(
|
|
3540
4151
|
"fetch(): init.body is not replayable. Pass a string, FormData, URLSearchParams, ArrayBuffer, or Blob \u2014 not a ReadableStream."
|
|
@@ -3542,7 +4153,7 @@ var PipRailClient = class {
|
|
|
3542
4153
|
}
|
|
3543
4154
|
const firstResponse = await fetch(url, init);
|
|
3544
4155
|
if (firstResponse.status !== 402) return firstResponse;
|
|
3545
|
-
const schemes = this.resolveSchemes(_optionalChain([init, 'optionalAccess',
|
|
4156
|
+
const schemes = this.resolveSchemes(_optionalChain([init, 'optionalAccess', _56 => _56.schemes]));
|
|
3546
4157
|
const resolved = await this.resolveChallenge(url, firstResponse, schemes);
|
|
3547
4158
|
const { net, wallet, challenge } = resolved;
|
|
3548
4159
|
if (!wallet) {
|
|
@@ -3552,7 +4163,7 @@ var PipRailClient = class {
|
|
|
3552
4163
|
}
|
|
3553
4164
|
let accept = resolved.accept;
|
|
3554
4165
|
let quote = resolved.quote;
|
|
3555
|
-
const autoRoute = _nullishCoalesce(_nullishCoalesce(_optionalChain([init, 'optionalAccess',
|
|
4166
|
+
const autoRoute = _nullishCoalesce(_nullishCoalesce(_optionalChain([init, 'optionalAccess', _57 => _57.autoRoute]), () => ( this.opts.autoRoute)), () => ( false));
|
|
3556
4167
|
if (autoRoute) {
|
|
3557
4168
|
const plan = await this.planFromChallenge(net, wallet, challenge, url, schemes);
|
|
3558
4169
|
if (!plan.best) {
|
|
@@ -3565,9 +4176,17 @@ var PipRailClient = class {
|
|
|
3565
4176
|
}
|
|
3566
4177
|
this.safeEmit({ kind: "payment-required", challenge, accept });
|
|
3567
4178
|
await this.authorize(quote);
|
|
4179
|
+
if (accept.scheme === "upto") {
|
|
4180
|
+
return this.payUptoRail(net, wallet, accept, url, init, quote);
|
|
4181
|
+
}
|
|
3568
4182
|
if (accept.scheme === "exact") {
|
|
3569
4183
|
return this.payExactRail(net, wallet, accept, url, init, quote);
|
|
3570
4184
|
}
|
|
4185
|
+
if (accept.scheme !== "onchain-proof") {
|
|
4186
|
+
throw new (0, _chunkMWBT7MCEcjs.UnsupportedSchemeError)(
|
|
4187
|
+
`internal: unrouted accept scheme '${accept.scheme}' reached the onchain-proof pay path.`
|
|
4188
|
+
);
|
|
4189
|
+
}
|
|
3571
4190
|
const { ref, confirmed } = await this.payAndConfirm(net, wallet, accept);
|
|
3572
4191
|
const response = await this.retryWithProof(url, init, accept, ref, confirmed);
|
|
3573
4192
|
this.recordSpend(quote, ref);
|
|
@@ -3654,6 +4273,13 @@ var PipRailClient = class {
|
|
|
3654
4273
|
)
|
|
3655
4274
|
);
|
|
3656
4275
|
}
|
|
4276
|
+
if (schemes.includes("upto")) {
|
|
4277
|
+
out.push(
|
|
4278
|
+
...challenge.accepts.filter(
|
|
4279
|
+
(a) => a.scheme === "upto" && this.supportsNetwork(net, a.network) && typeof net.payUpto === "function" && net.describeAsset(a.asset) != null && typeof _optionalChain([a, 'access', _58 => _58.extra, 'optionalAccess', _59 => _59.facilitatorAddress]) === "string" && a.extra.facilitatorAddress.length > 0 && Number.isInteger(a.maxTimeoutSeconds) && a.maxTimeoutSeconds > 0
|
|
4280
|
+
)
|
|
4281
|
+
);
|
|
4282
|
+
}
|
|
3657
4283
|
return out;
|
|
3658
4284
|
}
|
|
3659
4285
|
/** Build the full {@link PaymentPlan} from an already-parsed challenge + bound
|
|
@@ -3675,11 +4301,11 @@ var PipRailClient = class {
|
|
|
3675
4301
|
...session ? { session } : {}
|
|
3676
4302
|
};
|
|
3677
4303
|
}
|
|
3678
|
-
const analysed = await Promise.all(
|
|
4304
|
+
const analysed = (await Promise.all(
|
|
3679
4305
|
candidates.map(
|
|
3680
|
-
(accept) => this.analyzeRail(net, wallet, accept, url, challenge.resource.description)
|
|
4306
|
+
(accept) => this.analyzeRail(net, wallet, accept, url, challenge.resource.description).catch(() => null)
|
|
3681
4307
|
)
|
|
3682
|
-
);
|
|
4308
|
+
)).filter((o) => o !== null);
|
|
3683
4309
|
const options = rankOptions(analysed);
|
|
3684
4310
|
const best = _nullishCoalesce(options.find((o) => o.state === "payable"), () => ( null));
|
|
3685
4311
|
const status = best ? "ready" : options.some((o) => o.state === "unknown") ? "unknown" : "blocked";
|
|
@@ -3703,7 +4329,7 @@ var PipRailClient = class {
|
|
|
3703
4329
|
const rr = await net.recipientReady(accept.payTo, accept.asset).catch(() => ({ ready: "unknown" }));
|
|
3704
4330
|
const amount = BigInt(accept.amount);
|
|
3705
4331
|
const fee = safeBig(cost.fee);
|
|
3706
|
-
const isExact = accept.scheme === "exact";
|
|
4332
|
+
const isExact = accept.scheme === "exact" || accept.scheme === "upto";
|
|
3707
4333
|
const isNative = accept.asset === "native";
|
|
3708
4334
|
const blockers = [];
|
|
3709
4335
|
const warnings = [];
|
|
@@ -3783,7 +4409,7 @@ var PipRailClient = class {
|
|
|
3783
4409
|
}
|
|
3784
4410
|
const amountBase = BigInt(accept.amount);
|
|
3785
4411
|
const described = net.describeAsset(accept.asset);
|
|
3786
|
-
const decimals = _nullishCoalesce(_optionalChain([described, 'optionalAccess',
|
|
4412
|
+
const decimals = _nullishCoalesce(_optionalChain([described, 'optionalAccess', _60 => _60.decimals]), () => ( _optionalChain([accept, 'access', _61 => _61.extra, 'optionalAccess', _62 => _62.decimals])));
|
|
3787
4413
|
if (typeof decimals !== "number" || !Number.isInteger(decimals) || decimals < 0) {
|
|
3788
4414
|
throw new (0, _chunkMWBT7MCEcjs.InvalidEnvelopeError)(
|
|
3789
4415
|
`challenge for ${accept.asset} on ${accept.network} states no valid decimals and the SDK doesn't recognise the token \u2014 refusing to price it.`
|
|
@@ -3794,7 +4420,7 @@ var PipRailClient = class {
|
|
|
3794
4420
|
`challenge for ${accept.asset} on ${accept.network} states ${decimals} decimals (> ${_chunkMWBT7MCEcjs.MAX_DECIMALS}) \u2014 refusing to price it (no real token is that deep).`
|
|
3795
4421
|
);
|
|
3796
4422
|
}
|
|
3797
|
-
const symbol = _nullishCoalesce(_optionalChain([described, 'optionalAccess',
|
|
4423
|
+
const symbol = _nullishCoalesce(_optionalChain([described, 'optionalAccess', _63 => _63.symbol]), () => ( _optionalChain([accept, 'access', _64 => _64.extra, 'optionalAccess', _65 => _65.symbol])));
|
|
3798
4424
|
const amountFormatted = _chunkMWBT7MCEcjs.formatUnits.call(void 0, amountBase, decimals);
|
|
3799
4425
|
const intent = {
|
|
3800
4426
|
host: hostOf2(url),
|
|
@@ -3836,7 +4462,7 @@ var PipRailClient = class {
|
|
|
3836
4462
|
this.ledger.totalFor(accept.network, accept.asset),
|
|
3837
4463
|
ctx
|
|
3838
4464
|
);
|
|
3839
|
-
const serverSymbol = _optionalChain([accept, 'access',
|
|
4465
|
+
const serverSymbol = _optionalChain([accept, 'access', _66 => _66.extra, 'optionalAccess', _67 => _67.symbol]);
|
|
3840
4466
|
const symbolMismatch = intent.recognized && !!serverSymbol && !!symbol && serverSymbol.toUpperCase() !== symbol.toUpperCase();
|
|
3841
4467
|
return {
|
|
3842
4468
|
url,
|
|
@@ -3909,16 +4535,41 @@ var PipRailClient = class {
|
|
|
3909
4535
|
* denomination it counts toward in the grand total). Then fire the `onSpend` callback
|
|
3910
4536
|
* with the record + the post-payment budget, and emit any `warnAtFraction` thresholds
|
|
3911
4537
|
* this payment just crossed. All observability is isolated — a throwing hook never
|
|
3912
|
-
* affects the (already-settled) payment.
|
|
3913
|
-
|
|
4538
|
+
* affects the (already-settled) payment.
|
|
4539
|
+
*
|
|
4540
|
+
* `settledAmountBase` is the SINGLE upto ledger-reconciliation seam: the quote (and thus
|
|
4541
|
+
* the policy/budget) gates on the MAX, and for the metered `upto` rail the budgeted amount
|
|
4542
|
+
* RECORDED is ALSO the authorized MAX — the only buyer-provable bound. The merchant's
|
|
4543
|
+
* claimed actual is UNTRUSTED (a malicious merchant can settle the MAX on-chain yet report
|
|
4544
|
+
* a tiny `SettleOutcome.amount`); recording it would let an under-report silently loosen a
|
|
4545
|
+
* cumulative cap (`maxTotal`/`maxTotalPerDenom`/`windowTotal`) past the buyer's real on-chain
|
|
4546
|
+
* spend (POL-1). So the cap-bearing `amountBase` is the MAX; the clamped actual is surfaced
|
|
4547
|
+
* separately on `settledBase`/`settledFormatted` for transparency (it equals the receipt's
|
|
4548
|
+
* amount). When absent (onchain-proof/exact) this is byte-identical to before. */
|
|
4549
|
+
recordSpend(quote, ref, settledAmountBase) {
|
|
3914
4550
|
const denom = denomOf(quote.symbol, quote.asset, this.opts.policy);
|
|
4551
|
+
const amountBase = quote.amount;
|
|
4552
|
+
const amountFormatted = quote.amountFormatted;
|
|
4553
|
+
let settledBase;
|
|
4554
|
+
let settledFormatted;
|
|
4555
|
+
if (settledAmountBase !== void 0 && /^\d+$/.test(settledAmountBase)) {
|
|
4556
|
+
try {
|
|
4557
|
+
const claimed = BigInt(settledAmountBase);
|
|
4558
|
+
const max = BigInt(quote.amount);
|
|
4559
|
+
const shown = claimed < max ? claimed : max;
|
|
4560
|
+
settledBase = shown.toString();
|
|
4561
|
+
settledFormatted = _chunkMWBT7MCEcjs.formatUnits.call(void 0, shown, quote.decimals);
|
|
4562
|
+
} catch (e36) {
|
|
4563
|
+
}
|
|
4564
|
+
}
|
|
3915
4565
|
const record = {
|
|
3916
4566
|
url: quote.url,
|
|
3917
4567
|
host: hostOf2(quote.url),
|
|
3918
4568
|
network: quote.network,
|
|
3919
4569
|
asset: quote.asset,
|
|
3920
|
-
amountBase
|
|
3921
|
-
amountFormatted
|
|
4570
|
+
amountBase,
|
|
4571
|
+
amountFormatted,
|
|
4572
|
+
...settledBase !== void 0 ? { settledBase, settledFormatted } : {},
|
|
3922
4573
|
...quote.symbol ? { symbol: quote.symbol } : {},
|
|
3923
4574
|
decimals: quote.decimals,
|
|
3924
4575
|
...denom ? { denom } : {},
|
|
@@ -3930,7 +4581,7 @@ var PipRailClient = class {
|
|
|
3930
4581
|
if (this.opts.onSpend) {
|
|
3931
4582
|
try {
|
|
3932
4583
|
this.opts.onSpend(record, budget);
|
|
3933
|
-
} catch (
|
|
4584
|
+
} catch (e37) {
|
|
3934
4585
|
}
|
|
3935
4586
|
}
|
|
3936
4587
|
this.emitThresholds(budget);
|
|
@@ -3943,7 +4594,7 @@ var PipRailClient = class {
|
|
|
3943
4594
|
* `warnAtFraction` is set. Reads the just-computed {@link SessionBudget}; isolated (safeEmit).
|
|
3944
4595
|
*/
|
|
3945
4596
|
emitThresholds(budget) {
|
|
3946
|
-
const frac = _optionalChain([this, 'access',
|
|
4597
|
+
const frac = _optionalChain([this, 'access', _68 => _68.opts, 'access', _69 => _69.policy, 'optionalAccess', _70 => _70.warnAtFraction]);
|
|
3947
4598
|
if (frac === void 0) return;
|
|
3948
4599
|
const fire = (scope, label, spentFormatted, capFormatted, fraction) => {
|
|
3949
4600
|
if (fraction < frac) return;
|
|
@@ -3967,7 +4618,7 @@ var PipRailClient = class {
|
|
|
3967
4618
|
fire("denom", d.denom, d.spentFormatted, d.capFormatted, d.fraction);
|
|
3968
4619
|
}
|
|
3969
4620
|
const policy = this.opts.policy;
|
|
3970
|
-
if (_optionalChain([policy, 'optionalAccess',
|
|
4621
|
+
if (_optionalChain([policy, 'optionalAccess', _71 => _71.windowTotal]) !== void 0 && policy.windowSeconds !== void 0) {
|
|
3971
4622
|
const since = Date.now() - policy.windowSeconds * 1e3;
|
|
3972
4623
|
for (const r of budget.byAsset) {
|
|
3973
4624
|
const cap = _chunkMWBT7MCEcjs.floorUnits.call(void 0, policy.windowTotal, r.decimals);
|
|
@@ -4005,7 +4656,7 @@ var PipRailClient = class {
|
|
|
4005
4656
|
const ref = await net.send(wallet, accept);
|
|
4006
4657
|
this.safeEmit({ kind: "payment-broadcast", ref });
|
|
4007
4658
|
try {
|
|
4008
|
-
const { height } = await net.confirm(ref, _nullishCoalesce(_optionalChain([accept, 'access',
|
|
4659
|
+
const { height } = await net.confirm(ref, _nullishCoalesce(_optionalChain([accept, 'access', _72 => _72.extra, 'optionalAccess', _73 => _73.minConfirmations]), () => ( 1)));
|
|
4009
4660
|
this.safeEmit({
|
|
4010
4661
|
kind: "payment-confirmed",
|
|
4011
4662
|
ref,
|
|
@@ -4025,9 +4676,9 @@ var PipRailClient = class {
|
|
|
4025
4676
|
const signature = {
|
|
4026
4677
|
x402Version: 2,
|
|
4027
4678
|
accepted: accept,
|
|
4028
|
-
payload: { nonce: _optionalChain([accept, 'access',
|
|
4679
|
+
payload: { nonce: _optionalChain([accept, 'access', _74 => _74.extra, 'optionalAccess', _75 => _75.nonce]), txHash: ref }
|
|
4029
4680
|
};
|
|
4030
|
-
const headers = new Headers(_optionalChain([originalInit, 'optionalAccess',
|
|
4681
|
+
const headers = new Headers(_optionalChain([originalInit, 'optionalAccess', _76 => _76.headers]));
|
|
4031
4682
|
headers.set(HEADER_SIGNATURE, buildSignatureHeader(signature));
|
|
4032
4683
|
let lastResponse = null;
|
|
4033
4684
|
let lastReason = null;
|
|
@@ -4042,7 +4693,7 @@ var PipRailClient = class {
|
|
|
4042
4693
|
() => timeoutController.abort(),
|
|
4043
4694
|
this.retryTimeoutMs
|
|
4044
4695
|
);
|
|
4045
|
-
const signal = _optionalChain([originalInit, 'optionalAccess',
|
|
4696
|
+
const signal = _optionalChain([originalInit, 'optionalAccess', _77 => _77.signal]) && typeof AbortSignal.any === "function" ? AbortSignal.any([timeoutController.signal, originalInit.signal]) : timeoutController.signal;
|
|
4046
4697
|
try {
|
|
4047
4698
|
lastResponse = await fetch(url, {
|
|
4048
4699
|
..._nullishCoalesce(originalInit, () => ( {})),
|
|
@@ -4062,54 +4713,139 @@ var PipRailClient = class {
|
|
|
4062
4713
|
}
|
|
4063
4714
|
if (lastResponse.status !== 402) {
|
|
4064
4715
|
const receipt = parseReceipt(lastResponse);
|
|
4716
|
+
this.captureReceipt(lastResponse, url);
|
|
4065
4717
|
this.safeEmit({ kind: "payment-settled", receipt });
|
|
4066
4718
|
return lastResponse;
|
|
4067
4719
|
}
|
|
4068
|
-
lastReason = await _asyncNullishCoalesce(await readInvalidReason(lastResponse), async () => ( lastReason));
|
|
4720
|
+
lastReason = await _asyncNullishCoalesce(await readInvalidReason(lastResponse), async () => ( lastReason));
|
|
4721
|
+
}
|
|
4722
|
+
const why = lastReason ? `${lastReason.error}${lastReason.detail ? ` \u2014 ${lastReason.detail}` : ""}` : "server gave no reason";
|
|
4723
|
+
const unconfirmedNote = confirmed ? "" : " (broadcast but NOT locally confirmed \u2014 it may still have settled on-chain)";
|
|
4724
|
+
this.safeEmit({
|
|
4725
|
+
kind: "payment-failed",
|
|
4726
|
+
reason: `server returned 402 after broadcasting payment ${ref}${unconfirmedNote} (${why})`,
|
|
4727
|
+
...lastReason ? { code: lastReason.error, detail: lastReason.detail } : {}
|
|
4728
|
+
});
|
|
4729
|
+
throw new (0, _chunkMWBT7MCEcjs.MaxRetriesExceededError)(
|
|
4730
|
+
`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).`,
|
|
4731
|
+
{ ref }
|
|
4732
|
+
);
|
|
4733
|
+
}
|
|
4734
|
+
/**
|
|
4735
|
+
* Pay a standard x402 `exact` rail — a SEPARATE, fundamentally more conservative
|
|
4736
|
+
* path than {@link retryWithProof}. The buyer SIGNS an EIP-3009 authorization ONCE
|
|
4737
|
+
* (the driver's `payExact`) and the server / merchant-chosen facilitator BROADCASTS
|
|
4738
|
+
* it synchronously, so a blind re-POST of a still-in-flight authorization could
|
|
4739
|
+
* double-BROADCAST it. Hence, unlike the onchain-proof loop:
|
|
4740
|
+
*
|
|
4741
|
+
* • sign exactly once — reuse the SAME header on every retry, never re-sign;
|
|
4742
|
+
* • retry ONLY an explicit 402 (a definitive pre-broadcast rejection), bounded
|
|
4743
|
+
* well under `maxTimeoutSeconds` so the loop can't outlive the authorization;
|
|
4744
|
+
* • a post-POST transport error/timeout → {@link PaymentTimeoutError} carrying the
|
|
4745
|
+
* nonce (the facilitator MAY have settled — verify on-chain, NEVER re-pay);
|
|
4746
|
+
* • a 5xx → return as-is (server settle failure; the authorization stays valid +
|
|
4747
|
+
* its nonce unused) — no settled event, no spend;
|
|
4748
|
+
* • a 200 whose SettleResponse says `success:false` → a rejection, NEVER a spend;
|
|
4749
|
+
* • the spend is recorded EXACTLY ONCE, on an affirmative settlement only.
|
|
4750
|
+
*/
|
|
4751
|
+
async payExactRail(net, wallet, accept, url, init, quote) {
|
|
4752
|
+
if (!net.payExact) {
|
|
4753
|
+
throw new (0, _chunkMWBT7MCEcjs.UnsupportedSchemeError)(
|
|
4754
|
+
`the ${net.family} family can't pay a standard 'exact' rail (supported on EVM, Solana, Algorand + NEAR today).`
|
|
4755
|
+
);
|
|
4756
|
+
}
|
|
4757
|
+
throwIfAborted(_optionalChain([init, 'optionalAccess', _78 => _78.signal]));
|
|
4758
|
+
const { payload, accepted, payerFrom, nonce } = await net.payExact(wallet, accept);
|
|
4759
|
+
const headers = new Headers(_optionalChain([init, 'optionalAccess', _79 => _79.headers]));
|
|
4760
|
+
headers.set(HEADER_SIGNATURE, buildExactSignatureHeader({ accepted, payload }));
|
|
4761
|
+
const rejectDefinitive = (why2) => {
|
|
4762
|
+
this.safeEmit({ kind: "payment-failed", reason: `exact: facilitator rejected nonce=${nonce} (${why2})`, code: why2 });
|
|
4763
|
+
throw new (0, _chunkMWBT7MCEcjs.MaxRetriesExceededError)(
|
|
4764
|
+
`exact: the facilitator rejected the payment (${why2}). Fix the cause, then re-present the SAME signed authorization (nonce=${nonce}) \u2014 do NOT re-sign a fresh nonce. ref=${nonce}.`,
|
|
4765
|
+
{ ref: nonce }
|
|
4766
|
+
);
|
|
4767
|
+
};
|
|
4768
|
+
const deadline = Date.now() + Math.max(1, Math.floor(accept.maxTimeoutSeconds / 2)) * 1e3;
|
|
4769
|
+
const maxAttempts = Math.min(this.maxRetries, 3);
|
|
4770
|
+
let lastReason = null;
|
|
4771
|
+
for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
|
|
4772
|
+
if (attempt > 0) {
|
|
4773
|
+
if (Date.now() >= deadline) break;
|
|
4774
|
+
await new Promise((r) => setTimeout(r, Math.min(2e3, 400 * 2 ** (attempt - 1))));
|
|
4775
|
+
}
|
|
4776
|
+
throwIfAborted(_optionalChain([init, 'optionalAccess', _80 => _80.signal]));
|
|
4777
|
+
const budget = Math.min(this.retryTimeoutMs, deadline - Date.now());
|
|
4778
|
+
if (budget <= 0) break;
|
|
4779
|
+
const timeoutController = new AbortController();
|
|
4780
|
+
const timeoutId = setTimeout(() => timeoutController.abort(), budget);
|
|
4781
|
+
const signal = _optionalChain([init, 'optionalAccess', _81 => _81.signal]) && typeof AbortSignal.any === "function" ? AbortSignal.any([timeoutController.signal, init.signal]) : timeoutController.signal;
|
|
4782
|
+
let response;
|
|
4783
|
+
try {
|
|
4784
|
+
response = await fetch(url, { ..._nullishCoalesce(init, () => ( {})), headers, signal });
|
|
4785
|
+
} catch (err) {
|
|
4786
|
+
throw new (0, _chunkMWBT7MCEcjs.PaymentTimeoutError)(
|
|
4787
|
+
`exact: no response after submitting the authorization (nonce=${nonce}) to ${hostOf2(url)}. The facilitator may have already settled it \u2014 verify on-chain with authorizationState(${payerFrom}, ${nonce}) before re-presenting; do NOT re-pay.`,
|
|
4788
|
+
{ cause: err, ref: nonce }
|
|
4789
|
+
);
|
|
4790
|
+
} finally {
|
|
4791
|
+
clearTimeout(timeoutId);
|
|
4792
|
+
}
|
|
4793
|
+
const settle = parseSettleResponse(response);
|
|
4794
|
+
if (response.status === 402) {
|
|
4795
|
+
if (settle && settle.success === false) rejectDefinitive(_nullishCoalesce(settle.errorReason, () => ( "the facilitator reported success:false")));
|
|
4796
|
+
lastReason = await _asyncNullishCoalesce(await readInvalidReason(response), async () => ( lastReason));
|
|
4797
|
+
continue;
|
|
4798
|
+
}
|
|
4799
|
+
if (response.ok && !(settle && settle.success === false)) {
|
|
4800
|
+
const receipt = parseReceipt(response);
|
|
4801
|
+
this.captureReceipt(response, url);
|
|
4802
|
+
this.safeEmit({ kind: "payment-settled", receipt, ...settle ? { settle } : {} });
|
|
4803
|
+
const ref = _optionalChain([settle, 'optionalAccess', _82 => _82.transaction]) || _optionalChain([receipt, 'optionalAccess', _83 => _83.transaction]) || `eip3009-nonce:${nonce}`;
|
|
4804
|
+
this.recordSpend(quote, ref);
|
|
4805
|
+
return response;
|
|
4806
|
+
}
|
|
4807
|
+
if (response.status >= 500) {
|
|
4808
|
+
this.safeEmit({ kind: "payment-failed", reason: `exact: server ${response.status} \u2014 authorization nonce=${nonce} not settled` });
|
|
4809
|
+
return response;
|
|
4810
|
+
}
|
|
4811
|
+
if (settle && settle.success === false) rejectDefinitive(_nullishCoalesce(settle.errorReason, () => ( "the facilitator reported success:false")));
|
|
4812
|
+
this.safeEmit({ kind: "payment-failed", reason: `exact: server ${response.status} \u2014 authorization nonce=${nonce} not settled` });
|
|
4813
|
+
return response;
|
|
4069
4814
|
}
|
|
4070
4815
|
const why = lastReason ? `${lastReason.error}${lastReason.detail ? ` \u2014 ${lastReason.detail}` : ""}` : "server gave no reason";
|
|
4071
|
-
const unconfirmedNote = confirmed ? "" : " (broadcast but NOT locally confirmed \u2014 it may still have settled on-chain)";
|
|
4072
4816
|
this.safeEmit({
|
|
4073
4817
|
kind: "payment-failed",
|
|
4074
|
-
reason: `
|
|
4818
|
+
reason: `exact: 402 after submitting authorization nonce=${nonce} (${why})`,
|
|
4075
4819
|
...lastReason ? { code: lastReason.error, detail: lastReason.detail } : {}
|
|
4076
4820
|
});
|
|
4077
4821
|
throw new (0, _chunkMWBT7MCEcjs.MaxRetriesExceededError)(
|
|
4078
|
-
`
|
|
4079
|
-
{ ref }
|
|
4822
|
+
`exact: server still returned 402 after submitting the signed authorization (nonce=${nonce}). Last rejection: ${why}. Re-present the SAME authorization \u2014 do NOT re-sign a fresh nonce; verify authorizationState(${payerFrom}, ${nonce}) first. ref=${nonce}.`,
|
|
4823
|
+
{ ref: nonce }
|
|
4080
4824
|
);
|
|
4081
4825
|
}
|
|
4082
4826
|
/**
|
|
4083
|
-
*
|
|
4084
|
-
*
|
|
4085
|
-
*
|
|
4086
|
-
*
|
|
4087
|
-
*
|
|
4088
|
-
*
|
|
4089
|
-
*
|
|
4090
|
-
* • retry ONLY an explicit 402 (a definitive pre-broadcast rejection), bounded
|
|
4091
|
-
* well under `maxTimeoutSeconds` so the loop can't outlive the authorization;
|
|
4092
|
-
* • a post-POST transport error/timeout → {@link PaymentTimeoutError} carrying the
|
|
4093
|
-
* nonce (the facilitator MAY have settled — verify on-chain, NEVER re-pay);
|
|
4094
|
-
* • a 5xx → return as-is (server settle failure; the authorization stays valid +
|
|
4095
|
-
* its nonce unused) — no settled event, no spend;
|
|
4096
|
-
* • a 200 whose SettleResponse says `success:false` → a rejection, NEVER a spend;
|
|
4097
|
-
* • the spend is recorded EXACTLY ONCE, on an affirmative settlement only.
|
|
4827
|
+
* The standard `upto` (metered) buyer path — a near-clone of {@link payExactRail} with TWO
|
|
4828
|
+
* deltas: (1) it signs a Permit2-upto authorization for the MAX via `payUpto` + frames it
|
|
4829
|
+
* with `buildUptoSignatureHeader`; (2) it records the ACTUAL settled amount (read off the
|
|
4830
|
+
* SettleResponse's required `amount` field, via `recordSpend(quote, ref, settle.amount)`) in
|
|
4831
|
+
* the ledger — the budget gated on the MAX, the ledger records the ACTUAL. A server that omits
|
|
4832
|
+
* `settle.amount` FAILS SAFE to the MAX (over-counts, never under-counts). The buyer SIGNS, the
|
|
4833
|
+
* merchant self-settles — the buyer never broadcasts.
|
|
4098
4834
|
*/
|
|
4099
|
-
async
|
|
4100
|
-
if (!net.
|
|
4835
|
+
async payUptoRail(net, wallet, accept, url, init, quote) {
|
|
4836
|
+
if (!net.payUpto) {
|
|
4101
4837
|
throw new (0, _chunkMWBT7MCEcjs.UnsupportedSchemeError)(
|
|
4102
|
-
`the ${net.family} family can't pay a standard '
|
|
4838
|
+
`the ${net.family} family can't pay a standard 'upto' rail (EVM-Permit2 only today).`
|
|
4103
4839
|
);
|
|
4104
4840
|
}
|
|
4105
|
-
throwIfAborted(_optionalChain([init, 'optionalAccess',
|
|
4106
|
-
const { payload, accepted, payerFrom, nonce } = await net.
|
|
4107
|
-
const headers = new Headers(_optionalChain([init, 'optionalAccess',
|
|
4108
|
-
headers.set(HEADER_SIGNATURE,
|
|
4841
|
+
throwIfAborted(_optionalChain([init, 'optionalAccess', _84 => _84.signal]));
|
|
4842
|
+
const { payload, accepted, payerFrom, nonce } = await net.payUpto(wallet, accept);
|
|
4843
|
+
const headers = new Headers(_optionalChain([init, 'optionalAccess', _85 => _85.headers]));
|
|
4844
|
+
headers.set(HEADER_SIGNATURE, buildUptoSignatureHeader({ accepted, payload }));
|
|
4109
4845
|
const rejectDefinitive = (why2) => {
|
|
4110
|
-
this.safeEmit({ kind: "payment-failed", reason: `
|
|
4846
|
+
this.safeEmit({ kind: "payment-failed", reason: `upto: facilitator rejected nonce=${nonce} (${why2})`, code: why2 });
|
|
4111
4847
|
throw new (0, _chunkMWBT7MCEcjs.MaxRetriesExceededError)(
|
|
4112
|
-
`
|
|
4848
|
+
`upto: the server rejected the payment (${why2}). Fix the cause, then re-present the SAME signed authorization (nonce=${nonce}) \u2014 do NOT re-sign a fresh nonce. ref=${nonce}.`,
|
|
4113
4849
|
{ ref: nonce }
|
|
4114
4850
|
);
|
|
4115
4851
|
};
|
|
@@ -4121,18 +4857,18 @@ var PipRailClient = class {
|
|
|
4121
4857
|
if (Date.now() >= deadline) break;
|
|
4122
4858
|
await new Promise((r) => setTimeout(r, Math.min(2e3, 400 * 2 ** (attempt - 1))));
|
|
4123
4859
|
}
|
|
4124
|
-
throwIfAborted(_optionalChain([init, 'optionalAccess',
|
|
4860
|
+
throwIfAborted(_optionalChain([init, 'optionalAccess', _86 => _86.signal]));
|
|
4125
4861
|
const budget = Math.min(this.retryTimeoutMs, deadline - Date.now());
|
|
4126
4862
|
if (budget <= 0) break;
|
|
4127
4863
|
const timeoutController = new AbortController();
|
|
4128
4864
|
const timeoutId = setTimeout(() => timeoutController.abort(), budget);
|
|
4129
|
-
const signal = _optionalChain([init, 'optionalAccess',
|
|
4865
|
+
const signal = _optionalChain([init, 'optionalAccess', _87 => _87.signal]) && typeof AbortSignal.any === "function" ? AbortSignal.any([timeoutController.signal, init.signal]) : timeoutController.signal;
|
|
4130
4866
|
let response;
|
|
4131
4867
|
try {
|
|
4132
4868
|
response = await fetch(url, { ..._nullishCoalesce(init, () => ( {})), headers, signal });
|
|
4133
4869
|
} catch (err) {
|
|
4134
4870
|
throw new (0, _chunkMWBT7MCEcjs.PaymentTimeoutError)(
|
|
4135
|
-
`
|
|
4871
|
+
`upto: no response after submitting the authorization (nonce=${nonce}) to ${hostOf2(url)}. The merchant may have already settled it \u2014 verify on-chain before re-presenting; do NOT re-pay.`,
|
|
4136
4872
|
{ cause: err, ref: nonce }
|
|
4137
4873
|
);
|
|
4138
4874
|
} finally {
|
|
@@ -4140,46 +4876,48 @@ var PipRailClient = class {
|
|
|
4140
4876
|
}
|
|
4141
4877
|
const settle = parseSettleResponse(response);
|
|
4142
4878
|
if (response.status === 402) {
|
|
4143
|
-
if (settle && settle.success === false) rejectDefinitive(_nullishCoalesce(settle.errorReason, () => ( "the
|
|
4879
|
+
if (settle && settle.success === false) rejectDefinitive(_nullishCoalesce(settle.errorReason, () => ( "the server reported success:false")));
|
|
4144
4880
|
lastReason = await _asyncNullishCoalesce(await readInvalidReason(response), async () => ( lastReason));
|
|
4145
4881
|
continue;
|
|
4146
4882
|
}
|
|
4147
4883
|
if (response.ok && !(settle && settle.success === false)) {
|
|
4148
4884
|
const receipt = parseReceipt(response);
|
|
4885
|
+
this.captureReceipt(response, url);
|
|
4149
4886
|
this.safeEmit({ kind: "payment-settled", receipt, ...settle ? { settle } : {} });
|
|
4150
|
-
const ref = _optionalChain([settle, 'optionalAccess',
|
|
4151
|
-
|
|
4887
|
+
const ref = _optionalChain([settle, 'optionalAccess', _88 => _88.transaction]) || _optionalChain([receipt, 'optionalAccess', _89 => _89.transaction]) || `upto-nonce:${nonce}`;
|
|
4888
|
+
const settledAmount = _nullishCoalesce(_optionalChain([settle, 'optionalAccess', _90 => _90.amount]), () => ( _optionalChain([receipt, 'optionalAccess', _91 => _91.amount])));
|
|
4889
|
+
this.recordSpend(quote, ref, settledAmount);
|
|
4152
4890
|
return response;
|
|
4153
4891
|
}
|
|
4154
4892
|
if (response.status >= 500) {
|
|
4155
|
-
this.safeEmit({ kind: "payment-failed", reason: `
|
|
4893
|
+
this.safeEmit({ kind: "payment-failed", reason: `upto: server ${response.status} \u2014 authorization nonce=${nonce} not settled` });
|
|
4156
4894
|
return response;
|
|
4157
4895
|
}
|
|
4158
|
-
if (settle && settle.success === false) rejectDefinitive(_nullishCoalesce(settle.errorReason, () => ( "the
|
|
4159
|
-
this.safeEmit({ kind: "payment-failed", reason: `
|
|
4896
|
+
if (settle && settle.success === false) rejectDefinitive(_nullishCoalesce(settle.errorReason, () => ( "the server reported success:false")));
|
|
4897
|
+
this.safeEmit({ kind: "payment-failed", reason: `upto: server ${response.status} \u2014 authorization nonce=${nonce} not settled` });
|
|
4160
4898
|
return response;
|
|
4161
4899
|
}
|
|
4162
4900
|
const why = lastReason ? `${lastReason.error}${lastReason.detail ? ` \u2014 ${lastReason.detail}` : ""}` : "server gave no reason";
|
|
4163
4901
|
this.safeEmit({
|
|
4164
4902
|
kind: "payment-failed",
|
|
4165
|
-
reason: `
|
|
4903
|
+
reason: `upto: 402 after submitting authorization nonce=${nonce} (${why})`,
|
|
4166
4904
|
...lastReason ? { code: lastReason.error, detail: lastReason.detail } : {}
|
|
4167
4905
|
});
|
|
4168
4906
|
throw new (0, _chunkMWBT7MCEcjs.MaxRetriesExceededError)(
|
|
4169
|
-
`
|
|
4907
|
+
`upto: server still returned 402 after submitting the signed authorization (nonce=${nonce}). Last rejection: ${why}. Re-present the SAME authorization \u2014 do NOT re-sign a fresh nonce. ref=${nonce}.`,
|
|
4170
4908
|
{ ref: nonce }
|
|
4171
4909
|
);
|
|
4172
4910
|
}
|
|
4173
|
-
};
|
|
4911
|
+
}, _class2);
|
|
4174
4912
|
function throwIfAborted(signal) {
|
|
4175
|
-
if (_optionalChain([signal, 'optionalAccess',
|
|
4913
|
+
if (_optionalChain([signal, 'optionalAccess', _92 => _92.aborted])) {
|
|
4176
4914
|
throw _nullishCoalesce(signal.reason, () => ( new DOMException("This operation was aborted.", "AbortError")));
|
|
4177
4915
|
}
|
|
4178
4916
|
}
|
|
4179
4917
|
function safeBig(s) {
|
|
4180
4918
|
try {
|
|
4181
4919
|
return BigInt(s);
|
|
4182
|
-
} catch (
|
|
4920
|
+
} catch (e38) {
|
|
4183
4921
|
return 0n;
|
|
4184
4922
|
}
|
|
4185
4923
|
}
|
|
@@ -4242,10 +4980,10 @@ function buildFundingHint(options, chainLabel) {
|
|
|
4242
4980
|
return `Couldn't fully read your wallet on ${chainLabel} (RPC throttled) \u2014 retry; you may already be able to pay ${target.quote.amountFormatted} ${sym}.`;
|
|
4243
4981
|
}
|
|
4244
4982
|
const parts = [];
|
|
4245
|
-
if (target.blockers.includes("INSUFFICIENT_TOKEN") && _optionalChain([target, 'access',
|
|
4983
|
+
if (target.blockers.includes("INSUFFICIENT_TOKEN") && _optionalChain([target, 'access', _93 => _93.shortfall, 'optionalAccess', _94 => _94.token])) {
|
|
4246
4984
|
parts.push(`top up ${target.shortfall.token} ${sym}`);
|
|
4247
4985
|
}
|
|
4248
|
-
if (target.blockers.includes("INSUFFICIENT_GAS") && _optionalChain([target, 'access',
|
|
4986
|
+
if (target.blockers.includes("INSUFFICIENT_GAS") && _optionalChain([target, 'access', _95 => _95.shortfall, 'optionalAccess', _96 => _96.native])) {
|
|
4249
4987
|
parts.push(`add ~${target.shortfall.native} ${target.cost.feeSymbol} for gas`);
|
|
4250
4988
|
}
|
|
4251
4989
|
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}.`;
|
|
@@ -4259,7 +4997,7 @@ async function planAcross(clients, url, init) {
|
|
|
4259
4997
|
const status = best ? "ready" : options.some((o) => o.state === "unknown") ? "unknown" : "blocked";
|
|
4260
4998
|
return {
|
|
4261
4999
|
url,
|
|
4262
|
-
network: _nullishCoalesce(_optionalChain([best, 'optionalAccess',
|
|
5000
|
+
network: _nullishCoalesce(_optionalChain([best, 'optionalAccess', _97 => _97.accept, 'access', _98 => _98.network]), () => ( live[0].network)),
|
|
4263
5001
|
status,
|
|
4264
5002
|
payable: best !== null,
|
|
4265
5003
|
best,
|
|
@@ -4307,7 +5045,7 @@ function reasonCodeForPolicy(code) {
|
|
|
4307
5045
|
function hostOf2(url) {
|
|
4308
5046
|
try {
|
|
4309
5047
|
return new URL(url).hostname;
|
|
4310
|
-
} catch (
|
|
5048
|
+
} catch (e39) {
|
|
4311
5049
|
return url;
|
|
4312
5050
|
}
|
|
4313
5051
|
}
|
|
@@ -4324,8 +5062,8 @@ function isReplayableBodyInit(value) {
|
|
|
4324
5062
|
async function readInvalidReason(response) {
|
|
4325
5063
|
try {
|
|
4326
5064
|
const body = await response.clone().json();
|
|
4327
|
-
const ext = _optionalChain([body, 'optionalAccess',
|
|
4328
|
-
const piprail = _optionalChain([ext, 'optionalAccess',
|
|
5065
|
+
const ext = _optionalChain([body, 'optionalAccess', _99 => _99.extensions]);
|
|
5066
|
+
const piprail = _optionalChain([ext, 'optionalAccess', _100 => _100.piprail]);
|
|
4329
5067
|
if (piprail && typeof piprail.code === "string") {
|
|
4330
5068
|
return {
|
|
4331
5069
|
error: piprail.code,
|
|
@@ -4344,12 +5082,44 @@ async function readInvalidReason(response) {
|
|
|
4344
5082
|
detail: typeof body.invalidMessage === "string" ? body.invalidMessage : ""
|
|
4345
5083
|
};
|
|
4346
5084
|
}
|
|
4347
|
-
} catch (
|
|
5085
|
+
} catch (e40) {
|
|
4348
5086
|
}
|
|
4349
5087
|
const settle = parseSettleResponse(response);
|
|
4350
|
-
if (_optionalChain([settle, 'optionalAccess',
|
|
5088
|
+
if (_optionalChain([settle, 'optionalAccess', _101 => _101.errorReason])) return { error: settle.errorReason, detail: "" };
|
|
4351
5089
|
return null;
|
|
4352
5090
|
}
|
|
5091
|
+
var EVM_PRESET_FOR_CHAINID = {
|
|
5092
|
+
1: "ethereum",
|
|
5093
|
+
8453: "base",
|
|
5094
|
+
137: "polygon",
|
|
5095
|
+
42161: "arbitrum",
|
|
5096
|
+
10: "optimism",
|
|
5097
|
+
43114: "avalanche",
|
|
5098
|
+
56: "bnb"
|
|
5099
|
+
};
|
|
5100
|
+
function chainSelectorForNetwork(network, rpcUrl) {
|
|
5101
|
+
const chainId = chainIdFromNetwork(network);
|
|
5102
|
+
if (chainId !== null) {
|
|
5103
|
+
const preset = EVM_PRESET_FOR_CHAINID[chainId];
|
|
5104
|
+
if (preset) return preset;
|
|
5105
|
+
return { id: chainId, rpcUrl: _nullishCoalesce(rpcUrl, () => ( "")) };
|
|
5106
|
+
}
|
|
5107
|
+
const namespace = _nullishCoalesce(network.split(":")[0], () => ( ""));
|
|
5108
|
+
return namespace === "tvm" ? "ton" : namespace;
|
|
5109
|
+
}
|
|
5110
|
+
function receiptAgeSeconds(verifiedAt) {
|
|
5111
|
+
const t = Date.parse(verifiedAt);
|
|
5112
|
+
if (Number.isNaN(t)) return 0;
|
|
5113
|
+
return Math.max(0, Math.round((Date.now() - t) / 1e3));
|
|
5114
|
+
}
|
|
5115
|
+
function receiptIssuedAtSeconds(verifiedAt) {
|
|
5116
|
+
const t = Date.parse(verifiedAt);
|
|
5117
|
+
if (Number.isNaN(t)) return 0;
|
|
5118
|
+
return Math.floor(t / 1e3);
|
|
5119
|
+
}
|
|
5120
|
+
function sameAddress(a, b) {
|
|
5121
|
+
return typeof a === "string" && typeof b === "string" && a.toLowerCase() === b.toLowerCase();
|
|
5122
|
+
}
|
|
4353
5123
|
|
|
4354
5124
|
// src/payer.ts
|
|
4355
5125
|
var MultiChainPayer = class _MultiChainPayer {
|
|
@@ -4413,7 +5183,7 @@ var MultiChainPayer = class _MultiChainPayer {
|
|
|
4413
5183
|
ledger,
|
|
4414
5184
|
...opts.policy ? { policy: opts.policy } : {},
|
|
4415
5185
|
...opts.schemes ? { schemes: opts.schemes } : {},
|
|
4416
|
-
..._optionalChain([opts, 'access',
|
|
5186
|
+
..._optionalChain([opts, 'access', _102 => _102.rpcUrls, 'optionalAccess', _103 => _103[chain]]) ? { rpcUrl: opts.rpcUrls[chain] } : {},
|
|
4417
5187
|
...opts.onBeforePay ? { onBeforePay: opts.onBeforePay } : {},
|
|
4418
5188
|
...opts.onEvent ? { onEvent: opts.onEvent } : {},
|
|
4419
5189
|
...opts.maxPaymentRetries != null ? { maxPaymentRetries: opts.maxPaymentRetries } : {},
|
|
@@ -4471,7 +5241,7 @@ var MultiChainPayer = class _MultiChainPayer {
|
|
|
4471
5241
|
* {@link PipRailClient.post}.
|
|
4472
5242
|
*/
|
|
4473
5243
|
post(url, body, init) {
|
|
4474
|
-
const headers = new Headers(_optionalChain([init, 'optionalAccess',
|
|
5244
|
+
const headers = new Headers(_optionalChain([init, 'optionalAccess', _104 => _104.headers]));
|
|
4475
5245
|
let payload;
|
|
4476
5246
|
if (body === void 0 || body === null) {
|
|
4477
5247
|
payload = void 0;
|
|
@@ -4582,7 +5352,13 @@ var BRAND = {
|
|
|
4582
5352
|
};
|
|
4583
5353
|
var WHAT = 'This is an x402 "402 Payment Required" endpoint. Pay one of the offered rails to access it.';
|
|
4584
5354
|
function howFor(scheme) {
|
|
4585
|
-
|
|
5355
|
+
if (scheme === "exact") {
|
|
5356
|
+
return "Standard x402 exact rail \u2014 sign an EIP-3009 / Permit2 / SVM authorization; any stock x402 client (e.g. @x402/fetch) can pay this.";
|
|
5357
|
+
}
|
|
5358
|
+
if (scheme === "upto") {
|
|
5359
|
+
return "Standard x402 upto (metered) rail \u2014 sign a Permit2 authorization for the MAX amount; the server settles the ACTUAL (\u2264 max) after serving. BUDGET AGAINST THE MAX \u2014 the server MAY fully charge it. EVM-Permit2 only; enable with schemes:['upto'].";
|
|
5360
|
+
}
|
|
5361
|
+
return "Pay this amount on-chain to payTo, then resubmit with a payment-signature header carrying the proof ref + nonce. Easiest with @piprail/sdk (see sdk.install).";
|
|
4586
5362
|
}
|
|
4587
5363
|
function railOf(a) {
|
|
4588
5364
|
const extra = _nullishCoalesce(a.extra, () => ( {}));
|
|
@@ -4609,19 +5385,20 @@ function buildSelfDescription(input) {
|
|
|
4609
5385
|
mcp: { run: BRAND.mcpRun, tool: "piprail_pay_request" },
|
|
4610
5386
|
docs: { home: BRAND.home, agents: BRAND.docs, pay: BRAND.payDocs },
|
|
4611
5387
|
discovery: { openapi: "/openapi.json", wellKnown: "/.well-known/x402" },
|
|
5388
|
+
...input.verifiableReceipts ? { verifiableReceipts: true } : {},
|
|
4612
5389
|
...input.instruction ? { instruction: input.instruction } : {}
|
|
4613
5390
|
};
|
|
4614
5391
|
}
|
|
4615
5392
|
function buildEndpointInfo(input) {
|
|
4616
5393
|
const d = input.descriptor;
|
|
4617
|
-
const summary = _nullishCoalesce(_optionalChain([d, 'optionalAccess',
|
|
4618
|
-
const hasInput = _optionalChain([d, 'optionalAccess',
|
|
5394
|
+
const summary = _nullishCoalesce(_optionalChain([d, 'optionalAccess', _105 => _105.summary]), () => ( input.description));
|
|
5395
|
+
const hasInput = _optionalChain([d, 'optionalAccess', _106 => _106.queryParams]) && Object.keys(d.queryParams).length > 0;
|
|
4619
5396
|
const endpoint = {
|
|
4620
5397
|
...summary ? { summary } : {},
|
|
4621
|
-
..._optionalChain([d, 'optionalAccess',
|
|
5398
|
+
..._optionalChain([d, 'optionalAccess', _107 => _107.method]) ? { method: d.method.toUpperCase() } : {},
|
|
4622
5399
|
...input.mimeType ? { mimeType: input.mimeType } : {},
|
|
4623
5400
|
...hasInput ? { input: d.queryParams } : {},
|
|
4624
|
-
..._optionalChain([d, 'optionalAccess',
|
|
5401
|
+
..._optionalChain([d, 'optionalAccess', _108 => _108.output]) ? { output: d.output } : {}
|
|
4625
5402
|
};
|
|
4626
5403
|
return Object.keys(endpoint).length > 0 ? endpoint : void 0;
|
|
4627
5404
|
}
|
|
@@ -4708,17 +5485,21 @@ and pay with the tools below.
|
|
|
4708
5485
|
Always plan before you pay so you never commit to a payment you cannot finish.
|
|
4709
5486
|
|
|
4710
5487
|
## Gasless \u2014 the exact rail (zero gas for you)
|
|
4711
|
-
A 402 may offer up to
|
|
5488
|
+
A 402 may offer up to three rails; you don't choose per payment \u2014 the client does, automatically:
|
|
4712
5489
|
- onchain-proof (PipRail's default): you broadcast the payment yourself and pay the network gas
|
|
4713
5490
|
(the native coin \u2014 ETH/SOL/\u2026). Works on every chain.
|
|
4714
5491
|
- exact (the ratified x402 rail, opt-in): you only SIGN; the server \u2014 or a facilitator it chose
|
|
4715
5492
|
(e.g. PayAI) \u2014 broadcasts it, so you pay ZERO gas (you need only the token, no native coin). It
|
|
4716
5493
|
works on EVM, Solana + Algorand, and the on-chain method (EIP-3009 / Permit2 / SVM / Algorand
|
|
4717
5494
|
fee-pooled group) is picked automatically.
|
|
5495
|
+
- upto (the metered/variable x402 rail, opt-in, EVM): the amount you see is a MAXIMUM \u2014 you sign
|
|
5496
|
+
a ceiling, the server meters real usage and settles the ACTUAL (<= the max). BUDGET AGAINST THE MAX:
|
|
5497
|
+
the plan/policy treat the ceiling as the spend (a server may charge up to it), so a payable plan
|
|
5498
|
+
means the MAX fits your budget; the settled actual is recorded for reconciliation.
|
|
4718
5499
|
When the exact scheme is enabled AND balance-aware routing is on, paying picks the cheapest
|
|
4719
5500
|
settleable rail \u2014 i.e. the gasless exact one. Nothing changes in your loop: quote \u2192 plan \u2192 pay is
|
|
4720
|
-
identical. The exact
|
|
4721
|
-
you can't enable
|
|
5501
|
+
identical. The exact/upto schemes are OPT-IN by the operator (MCP: PIPRAIL_SCHEMES=onchain-proof,exact,upto);
|
|
5502
|
+
you can't enable them yourself, but you can report when a 402 needs one (see UNSUPPORTED_SCHEME below).
|
|
4722
5503
|
|
|
4723
5504
|
## Reading a refusal \u2014 never crash, never double-spend
|
|
4724
5505
|
A failed pay returns a STRUCTURED object, never a thrown error you must catch:
|
|
@@ -4782,7 +5563,7 @@ async function readBody(res) {
|
|
|
4782
5563
|
if (!text) return null;
|
|
4783
5564
|
try {
|
|
4784
5565
|
return JSON.parse(text);
|
|
4785
|
-
} catch (
|
|
5566
|
+
} catch (e41) {
|
|
4786
5567
|
return text;
|
|
4787
5568
|
}
|
|
4788
5569
|
}
|
|
@@ -5001,11 +5782,13 @@ function paymentTools(client) {
|
|
|
5001
5782
|
}
|
|
5002
5783
|
res = await client.fetch(url, { method, headers, body });
|
|
5003
5784
|
}
|
|
5785
|
+
const verifiable = parseReceiptExtension(res);
|
|
5004
5786
|
return {
|
|
5005
5787
|
status: res.status,
|
|
5006
5788
|
ok: res.ok,
|
|
5007
5789
|
body: await readBody(res),
|
|
5008
|
-
receipt: parseReceipt(res)
|
|
5790
|
+
receipt: parseReceipt(res),
|
|
5791
|
+
...verifiable ? { verifiableReceipt: { ...verifiable, resource: { url } } } : {}
|
|
5009
5792
|
};
|
|
5010
5793
|
} catch (err) {
|
|
5011
5794
|
if (err instanceof _chunkMWBT7MCEcjs.PipRailError) {
|
|
@@ -5125,6 +5908,38 @@ function paymentTools(client) {
|
|
|
5125
5908
|
},
|
|
5126
5909
|
parameters: { type: "object", properties: {}, additionalProperties: false },
|
|
5127
5910
|
invoke: async () => ({ guide: PIPRAIL_AGENT_GUIDE })
|
|
5911
|
+
},
|
|
5912
|
+
{
|
|
5913
|
+
name: "piprail_verify_receipt",
|
|
5914
|
+
description: "Re-verify a PipRail VERIFIABLE RECEIPT against the chain \u2014 confirm a payment REALLY settled (the funds provably moved to payTo for AT LEAST the stated amount) WITHOUT trusting whoever handed you the receipt. Read-only and WALLET-FREE: pass the PipRailReceipt JSON (from a prior piprail_pay_request `verifiableReceipt`, or any third party). Returns { ok, onChain:{payTo,asset,amount,payer}, matchesClaims, ageSeconds, error? }: `ok` = the chain confirms the settlement; `onChain.payer` is RE-DERIVED from the tx and `matchesClaims:false` means the receipt forged the payer; `amount` is a verified lower bound. Pass `rpcUrl` for a chain outside the common presets.",
|
|
5915
|
+
annotations: {
|
|
5916
|
+
title: "Verify a payment receipt",
|
|
5917
|
+
readOnlyHint: true,
|
|
5918
|
+
// re-reads the chain; moves nothing, needs no wallet
|
|
5919
|
+
idempotentHint: true,
|
|
5920
|
+
openWorldHint: true
|
|
5921
|
+
// reads an on-chain tx via RPC
|
|
5922
|
+
},
|
|
5923
|
+
parameters: {
|
|
5924
|
+
type: "object",
|
|
5925
|
+
properties: {
|
|
5926
|
+
receipt: {
|
|
5927
|
+
type: "object",
|
|
5928
|
+
description: "The PipRailReceipt JSON ({ piprail, receipt, resource, decimals? }) to re-verify."
|
|
5929
|
+
},
|
|
5930
|
+
rpcUrl: {
|
|
5931
|
+
type: "string",
|
|
5932
|
+
description: "Optional RPC URL for the receipt's chain (required for chains outside the common presets)."
|
|
5933
|
+
}
|
|
5934
|
+
},
|
|
5935
|
+
required: ["receipt"],
|
|
5936
|
+
additionalProperties: false
|
|
5937
|
+
},
|
|
5938
|
+
invoke: async (args) => {
|
|
5939
|
+
const receipt = args.receipt;
|
|
5940
|
+
const opts = args.rpcUrl ? { rpcUrl: String(args.rpcUrl) } : void 0;
|
|
5941
|
+
return await PipRailClient.verifyReceipt(receipt, opts);
|
|
5942
|
+
}
|
|
5128
5943
|
}
|
|
5129
5944
|
];
|
|
5130
5945
|
}
|
|
@@ -5181,7 +5996,7 @@ function buildBazaarExtension(descriptor = {}) {
|
|
|
5181
5996
|
function pathOf(url) {
|
|
5182
5997
|
try {
|
|
5183
5998
|
return new URL(url).pathname || "/";
|
|
5184
|
-
} catch (
|
|
5999
|
+
} catch (e42) {
|
|
5185
6000
|
return url.startsWith("/") ? url : `/${url}`;
|
|
5186
6001
|
}
|
|
5187
6002
|
}
|
|
@@ -5290,28 +6105,28 @@ async function fetchFacilitatorFeePayer(url, network, timeoutMs = 8e3) {
|
|
|
5290
6105
|
const res = await fetch(`${base2}/supported`, { signal: ctrl.signal });
|
|
5291
6106
|
if (!res.ok) return void 0;
|
|
5292
6107
|
const body = await res.json();
|
|
5293
|
-
const kinds = Array.isArray(_optionalChain([body, 'optionalAccess',
|
|
6108
|
+
const kinds = Array.isArray(_optionalChain([body, 'optionalAccess', _109 => _109.kinds])) ? body.kinds : [];
|
|
5294
6109
|
const want = normalizeNetwork(network);
|
|
5295
|
-
const kind = kinds.find((k) => _optionalChain([k, 'optionalAccess',
|
|
5296
|
-
const fp = _optionalChain([kind, 'optionalAccess',
|
|
6110
|
+
const kind = kinds.find((k) => _optionalChain([k, 'optionalAccess', _110 => _110.scheme]) === "exact" && normalizeNetwork(String(_nullishCoalesce(_optionalChain([k, 'optionalAccess', _111 => _111.network]), () => ( "")))) === want);
|
|
6111
|
+
const fp = _optionalChain([kind, 'optionalAccess', _112 => _112.extra, 'optionalAccess', _113 => _113.feePayer]);
|
|
5297
6112
|
return typeof fp === "string" ? fp : void 0;
|
|
5298
|
-
} catch (
|
|
6113
|
+
} catch (e43) {
|
|
5299
6114
|
return void 0;
|
|
5300
6115
|
} finally {
|
|
5301
6116
|
clearTimeout(timer);
|
|
5302
6117
|
}
|
|
5303
6118
|
}
|
|
5304
6119
|
function parseFacilitatorSupported(body) {
|
|
5305
|
-
const kinds = _optionalChain([body, 'optionalAccess',
|
|
6120
|
+
const kinds = _optionalChain([body, 'optionalAccess', _114 => _114.kinds]);
|
|
5306
6121
|
if (!Array.isArray(kinds)) return [];
|
|
5307
6122
|
const out = [];
|
|
5308
6123
|
for (const k of kinds) {
|
|
5309
6124
|
if (!k || typeof k !== "object") continue;
|
|
5310
6125
|
const o = k;
|
|
5311
6126
|
if (typeof o.scheme !== "string" || typeof o.network !== "string") continue;
|
|
5312
|
-
const fp = _optionalChain([o, 'access',
|
|
6127
|
+
const fp = _optionalChain([o, 'access', _115 => _115.extra, 'optionalAccess', _116 => _116.feePayer]);
|
|
5313
6128
|
const ver = o.x402Version;
|
|
5314
|
-
const method = _optionalChain([o, 'access',
|
|
6129
|
+
const method = _optionalChain([o, 'access', _117 => _117.extra, 'optionalAccess', _118 => _118.assetTransferMethod]);
|
|
5315
6130
|
out.push({
|
|
5316
6131
|
scheme: o.scheme,
|
|
5317
6132
|
network: o.network,
|
|
@@ -5330,7 +6145,7 @@ async function facilitatorCoverage(url, timeoutMs = 8e3) {
|
|
|
5330
6145
|
const res = await fetch(`${base2}/supported`, { signal: ctrl.signal });
|
|
5331
6146
|
if (!res.ok) return [];
|
|
5332
6147
|
return parseFacilitatorSupported(await res.json());
|
|
5333
|
-
} catch (
|
|
6148
|
+
} catch (e44) {
|
|
5334
6149
|
return [];
|
|
5335
6150
|
} finally {
|
|
5336
6151
|
clearTimeout(timer);
|
|
@@ -5359,7 +6174,7 @@ async function post(url, body, headers) {
|
|
|
5359
6174
|
let json = null;
|
|
5360
6175
|
try {
|
|
5361
6176
|
json = await res.json();
|
|
5362
|
-
} catch (
|
|
6177
|
+
} catch (e45) {
|
|
5363
6178
|
}
|
|
5364
6179
|
return { status: res.status, json };
|
|
5365
6180
|
}
|
|
@@ -5774,17 +6589,40 @@ function normaliseExactOption(exact) {
|
|
|
5774
6589
|
return exact;
|
|
5775
6590
|
}
|
|
5776
6591
|
var TRANSIENT_VERIFY_CODES = /* @__PURE__ */ new Set(["tx_not_found", "insufficient_confirmations"]);
|
|
6592
|
+
function nowUnixSeconds(verifiedAt) {
|
|
6593
|
+
if (verifiedAt) {
|
|
6594
|
+
const t = Date.parse(verifiedAt);
|
|
6595
|
+
if (!Number.isNaN(t)) return Math.floor(t / 1e3);
|
|
6596
|
+
}
|
|
6597
|
+
return Math.floor(Date.now() / 1e3);
|
|
6598
|
+
}
|
|
5777
6599
|
function createPaymentGate(options) {
|
|
5778
6600
|
const minConfirmations = _nullishCoalesce(options.minConfirmations, () => ( 1));
|
|
5779
6601
|
const maxTimeoutSeconds = _nullishCoalesce(options.maxTimeoutSeconds, () => ( 600));
|
|
5780
6602
|
const genNonce = _nullishCoalesce(options.generateNonce, () => ( (() => globalThis.crypto.randomUUID())));
|
|
5781
6603
|
const exactOption = normaliseExactOption(options.exact);
|
|
6604
|
+
const receiptsOn = options.receipts !== void 0 && options.receipts !== false;
|
|
6605
|
+
const receiptOpt = typeof options.receipts === "object" ? options.receipts : {};
|
|
6606
|
+
const receiptIncludeTxHash = receiptOpt.includeTxHash !== false;
|
|
6607
|
+
const receiptResourceUrl = _nullishCoalesce(receiptOpt.resource, () => ( ""));
|
|
6608
|
+
const attestWallet = receiptOpt.attest && "wallet" in receiptOpt.attest ? receiptOpt.attest.wallet : void 0;
|
|
6609
|
+
const attestJws = receiptOpt.attest && "jws" in receiptOpt.attest;
|
|
6610
|
+
let attestWarned = false;
|
|
6611
|
+
function warnAttestDegrade(reason) {
|
|
6612
|
+
if (attestWarned) return;
|
|
6613
|
+
attestWarned = true;
|
|
6614
|
+
try {
|
|
6615
|
+
console.warn(`[piprail] receipts.attest ${reason}; emitting an unsigned Tier-1 receipt instead.`);
|
|
6616
|
+
} catch (e46) {
|
|
6617
|
+
}
|
|
6618
|
+
}
|
|
5782
6619
|
let resolved;
|
|
5783
6620
|
function ready() {
|
|
5784
6621
|
if (resolved) return resolved;
|
|
5785
6622
|
const p = (async () => {
|
|
5786
6623
|
const accepts = normaliseAccepts(options);
|
|
5787
6624
|
const exactSkips = [];
|
|
6625
|
+
const uptoSkips = [];
|
|
5788
6626
|
const specs = await Promise.all(
|
|
5789
6627
|
accepts.map(async (a) => {
|
|
5790
6628
|
const net = await resolveNetwork2({ chain: a.chain, rpcUrl: _nullishCoalesce(a.rpcUrl, () => ( options.rpcUrl)) });
|
|
@@ -5803,13 +6641,23 @@ function createPaymentGate(options) {
|
|
|
5803
6641
|
if (outcome.rail) spec.exact = outcome.rail;
|
|
5804
6642
|
else if (outcome.skipReason) exactSkips.push(outcome.skipReason);
|
|
5805
6643
|
}
|
|
6644
|
+
if (options.upto) {
|
|
6645
|
+
const upto = await resolveUptoRail(net, asset);
|
|
6646
|
+
if (upto) spec.upto = upto;
|
|
6647
|
+
else uptoSkips.push(`${net.network}/${asset}`);
|
|
6648
|
+
}
|
|
5806
6649
|
return spec;
|
|
5807
6650
|
})
|
|
5808
6651
|
);
|
|
6652
|
+
if (options.upto && !specs.some((s) => s.upto)) {
|
|
6653
|
+
throw new Error(
|
|
6654
|
+
`requirePayment: \`upto\` (the metered rail) was requested but none of the offered rails support it (tried: ${uptoSkips.join(", ") || "none"}). The \`upto\` scheme is EVM-Permit2 ONLY \u2014 an ERC-20 on a chain with the x402UptoPermit2Proxy deployed (Ethereum/Base/Arbitrum/Optimism/Polygon/BNB), NOT a native coin, NOT a non-EVM family. (Native coins + non-Permit2 chains can never carry \`upto\`.)`
|
|
6655
|
+
);
|
|
6656
|
+
}
|
|
5809
6657
|
if (exactOption && !specs.some((s) => s.exact)) {
|
|
5810
6658
|
const why = exactSkips.length > 0 ? exactSkips.join(" ") : "The standard `exact` rail is EVM ERC-20 (EIP-3009 \u2014 USDC / EURC \u2014 or Permit2, e.g. Binance-Peg USDC on BNB) or a Solana SPL token (SVM) \u2014 NOT native coins, NOT families without a standard `exact` scheme.";
|
|
5811
6659
|
if (exactOption.settle === "keyless") {
|
|
5812
|
-
if (typeof process === "undefined" || !_optionalChain([process, 'optionalAccess',
|
|
6660
|
+
if (typeof process === "undefined" || !_optionalChain([process, 'optionalAccess', _119 => _119.env, 'optionalAccess', _120 => _120.PIPRAIL_NO_HINTS])) {
|
|
5813
6661
|
console.warn(
|
|
5814
6662
|
`[piprail] exact: true \u2014 no offered chain has a gasless \`exact\` rail available, so this gate serves ONCHAIN-PROOF ONLY (buyers PAY GAS \u2014 the fallback when no facilitator can sponsor). ${why} To be gasless: pin \`exact: { settle: { facilitator } }\` or self-settle \`exact: { settle: 'self', relayer }\`. (Suppress with PIPRAIL_NO_HINTS=1.)`
|
|
5815
6663
|
);
|
|
@@ -5837,7 +6685,7 @@ function createPaymentGate(options) {
|
|
|
5837
6685
|
skipReason: `${net.network}: \`exact: true\` found no known keyless facilitator for this network. Pass \`exact: { settle: { facilitator } }\`, \`exact: { settle: 'self', relayer }\`, or see the coverage map (KNOWN_FACILITATORS / docs.piprail.com).`
|
|
5838
6686
|
};
|
|
5839
6687
|
}
|
|
5840
|
-
if (typeof process === "undefined" || _optionalChain([process, 'optionalAccess',
|
|
6688
|
+
if (typeof process === "undefined" || _optionalChain([process, 'optionalAccess', _121 => _121.env, 'optionalAccess', _122 => _122.NODE_ENV]) !== "production" && !_optionalChain([process, 'optionalAccess', _123 => _123.env, 'optionalAccess', _124 => _124.PIPRAIL_NO_HINTS])) {
|
|
5841
6689
|
console.warn(
|
|
5842
6690
|
`[piprail] exact: keyless rail on ${net.network} auto-settles via ${picked.url} (zero-config; pin \`exact.settle.facilitator\` in production).`
|
|
5843
6691
|
);
|
|
@@ -5885,7 +6733,27 @@ function createPaymentGate(options) {
|
|
|
5885
6733
|
};
|
|
5886
6734
|
return { rail: { method: info.method, ...info.extra ? { extra: info.extra } : {}, mode } };
|
|
5887
6735
|
}
|
|
5888
|
-
|
|
6736
|
+
async function resolveUptoRail(net, asset) {
|
|
6737
|
+
const cfg = options.upto;
|
|
6738
|
+
if (!net.resolveUptoRail) return null;
|
|
6739
|
+
if (cfg.relayer === void 0) {
|
|
6740
|
+
throw new Error(
|
|
6741
|
+
"requirePayment: `upto` needs a `relayer` wallet (the gas-paying key that self-settles the metered actual AND is the bound witness.facilitator), e.g. upto: { relayer: { key }, settleAmount }."
|
|
6742
|
+
);
|
|
6743
|
+
}
|
|
6744
|
+
const relayer = net.bindWallet(cfg.relayer);
|
|
6745
|
+
const info = await net.resolveUptoRail({ asset, relayer });
|
|
6746
|
+
if (!info) return null;
|
|
6747
|
+
return { method: info.method, ...info.extra ? { extra: info.extra } : {}, relayer };
|
|
6748
|
+
}
|
|
6749
|
+
const hasIsUsed = typeof options.isUsed === "function";
|
|
6750
|
+
const hasMarkUsed = typeof options.markUsed === "function";
|
|
6751
|
+
if (hasIsUsed !== hasMarkUsed) {
|
|
6752
|
+
throw new Error(
|
|
6753
|
+
"requirePayment/createPaymentGate: `isUsed` and `markUsed` must be provided TOGETHER \u2014 a custom replay store needs both a read and a write. Supplying only " + (hasIsUsed ? "`isUsed`" : "`markUsed`") + " silently disables replay protection (double-spend). Provide both, or neither (the built-in in-memory store)."
|
|
6754
|
+
);
|
|
6755
|
+
}
|
|
6756
|
+
const hasCustomStore = hasIsUsed && hasMarkUsed;
|
|
5889
6757
|
const localUsed = /* @__PURE__ */ new Map();
|
|
5890
6758
|
const replayWindowMs = maxTimeoutSeconds * 1e3;
|
|
5891
6759
|
function pruneUsed(now) {
|
|
@@ -5948,10 +6816,33 @@ function createPaymentGate(options) {
|
|
|
5948
6816
|
}
|
|
5949
6817
|
};
|
|
5950
6818
|
}
|
|
6819
|
+
function buildUptoAccept(s) {
|
|
6820
|
+
const rail = s.upto;
|
|
6821
|
+
return {
|
|
6822
|
+
scheme: "upto",
|
|
6823
|
+
network: s.net.network,
|
|
6824
|
+
amount: s.amountBase.toString(),
|
|
6825
|
+
// the authorized MAX (base units)
|
|
6826
|
+
asset: s.asset,
|
|
6827
|
+
payTo: s.payTo,
|
|
6828
|
+
maxTimeoutSeconds,
|
|
6829
|
+
extra: {
|
|
6830
|
+
assetTransferMethod: "permit2-upto",
|
|
6831
|
+
// facilitatorAddress comes from rail.extra; the spread below carries it (+ name/version).
|
|
6832
|
+
facilitatorAddress: _nullishCoalesce(_optionalChain([rail, 'access', _125 => _125.extra, 'optionalAccess', _126 => _126.facilitatorAddress]), () => ( "")),
|
|
6833
|
+
minConfirmations,
|
|
6834
|
+
decimals: s.decimals,
|
|
6835
|
+
amountFormatted: s.amountFormatted,
|
|
6836
|
+
...s.symbol ? { symbol: s.symbol } : {},
|
|
6837
|
+
...rail.extra
|
|
6838
|
+
}
|
|
6839
|
+
};
|
|
6840
|
+
}
|
|
5951
6841
|
function buildAccepts(specs, nonce) {
|
|
5952
6842
|
const out = [];
|
|
5953
6843
|
for (const s of specs) {
|
|
5954
6844
|
if (s.exact) out.push(buildExactAccept(s));
|
|
6845
|
+
if (s.upto) out.push(buildUptoAccept(s));
|
|
5955
6846
|
out.push(buildAccept(s, nonce));
|
|
5956
6847
|
}
|
|
5957
6848
|
return out;
|
|
@@ -5969,9 +6860,10 @@ function createPaymentGate(options) {
|
|
|
5969
6860
|
const selfDescribe = options.selfDescribe === false ? void 0 : buildSelfDescription({
|
|
5970
6861
|
accepts,
|
|
5971
6862
|
instruction: describeChallenge({ x402Version: 2, resource: { url: resourceUrl }, accepts }),
|
|
5972
|
-
...endpointInfo ? { endpoint: endpointInfo } : {}
|
|
6863
|
+
...endpointInfo ? { endpoint: endpointInfo } : {},
|
|
6864
|
+
...receiptsOn ? { verifiableReceipts: true } : {}
|
|
5973
6865
|
});
|
|
5974
|
-
const rejectionExt = _nullishCoalesce(_optionalChain([opts, 'optionalAccess',
|
|
6866
|
+
const rejectionExt = _nullishCoalesce(_optionalChain([opts, 'optionalAccess', _127 => _127.extensions]), () => ( {}));
|
|
5975
6867
|
const rejectionPiprail = _nullishCoalesce(rejectionExt.piprail, () => ( {}));
|
|
5976
6868
|
const bodyPiprail = { ..._nullishCoalesce(selfDescribe, () => ( {})), ...rejectionPiprail };
|
|
5977
6869
|
const bodyExtensions = {
|
|
@@ -5991,7 +6883,7 @@ function createPaymentGate(options) {
|
|
|
5991
6883
|
...options.mimeType ? { mimeType: options.mimeType } : {}
|
|
5992
6884
|
},
|
|
5993
6885
|
accepts,
|
|
5994
|
-
..._optionalChain([opts, 'optionalAccess',
|
|
6886
|
+
..._optionalChain([opts, 'optionalAccess', _128 => _128.error]) ? { error: opts.error } : {},
|
|
5995
6887
|
...Object.keys(bodyExtensions).length > 0 ? { extensions: bodyExtensions } : {}
|
|
5996
6888
|
};
|
|
5997
6889
|
const headerChallenge = {
|
|
@@ -6023,7 +6915,7 @@ function createPaymentGate(options) {
|
|
|
6023
6915
|
let amountFormatted = receipt.amount;
|
|
6024
6916
|
try {
|
|
6025
6917
|
amountFormatted = _chunkMWBT7MCEcjs.formatUnits.call(void 0, BigInt(receipt.amount), spec.decimals);
|
|
6026
|
-
} catch (
|
|
6918
|
+
} catch (e47) {
|
|
6027
6919
|
}
|
|
6028
6920
|
return {
|
|
6029
6921
|
...receipt,
|
|
@@ -6037,7 +6929,7 @@ function createPaymentGate(options) {
|
|
|
6037
6929
|
if (!options.onPaidError) return;
|
|
6038
6930
|
try {
|
|
6039
6931
|
options.onPaidError(error, receipt);
|
|
6040
|
-
} catch (
|
|
6932
|
+
} catch (e48) {
|
|
6041
6933
|
}
|
|
6042
6934
|
}
|
|
6043
6935
|
function fireOnPaid(receipt) {
|
|
@@ -6058,11 +6950,60 @@ function createPaymentGate(options) {
|
|
|
6058
6950
|
if (options.awaitOnPaid) await fireOnPaid(paid);
|
|
6059
6951
|
else void fireOnPaid(paid);
|
|
6060
6952
|
}
|
|
6953
|
+
async function buildPaidResult(spec, receipt, nonce) {
|
|
6954
|
+
if (!receiptsOn) {
|
|
6955
|
+
return { kind: "paid", receipt, receiptHeader: buildReceiptHeader(receipt) };
|
|
6956
|
+
}
|
|
6957
|
+
try {
|
|
6958
|
+
const stamped = {
|
|
6959
|
+
...receipt,
|
|
6960
|
+
...nonce ? { nonce } : {},
|
|
6961
|
+
// §5.3: a suppressed tx is the empty string on the wire, never a missing key.
|
|
6962
|
+
...receiptIncludeTxHash ? {} : { transaction: "" }
|
|
6963
|
+
};
|
|
6964
|
+
const attestation = await maybeSignAttestation(spec, stamped);
|
|
6965
|
+
const extensions = buildReceiptExtension({
|
|
6966
|
+
receipt: stamped,
|
|
6967
|
+
resource: { url: receiptResourceUrl },
|
|
6968
|
+
decimals: spec.decimals,
|
|
6969
|
+
...attestation ? { attestation } : {}
|
|
6970
|
+
});
|
|
6971
|
+
return { kind: "paid", receipt: stamped, receiptHeader: buildReceiptHeader(stamped, extensions) };
|
|
6972
|
+
} catch (e49) {
|
|
6973
|
+
return { kind: "paid", receipt, receiptHeader: buildReceiptHeader(receipt) };
|
|
6974
|
+
}
|
|
6975
|
+
}
|
|
6976
|
+
async function maybeSignAttestation(spec, stamped) {
|
|
6977
|
+
if (attestJws) {
|
|
6978
|
+
warnAttestDegrade("JWS attestation is not yet implemented (R3)");
|
|
6979
|
+
return void 0;
|
|
6980
|
+
}
|
|
6981
|
+
if (attestWallet === void 0) return void 0;
|
|
6982
|
+
if (typeof spec.net.signReceipt !== "function") {
|
|
6983
|
+
warnAttestDegrade(`is EVM-only; the ${spec.net.family} rail can't sign an EIP-712 attestation`);
|
|
6984
|
+
return void 0;
|
|
6985
|
+
}
|
|
6986
|
+
try {
|
|
6987
|
+
const wallet = spec.net.bindWallet(attestWallet);
|
|
6988
|
+
return await spec.net.signReceipt(wallet, {
|
|
6989
|
+
payTo: spec.payTo,
|
|
6990
|
+
network: spec.net.network,
|
|
6991
|
+
resourceUrl: receiptResourceUrl,
|
|
6992
|
+
payer: stamped.payer,
|
|
6993
|
+
issuedAt: nowUnixSeconds(stamped.verifiedAt),
|
|
6994
|
+
// §5.3: the signed message carries the empty string for a suppressed tx, never omitted.
|
|
6995
|
+
transaction: receiptIncludeTxHash ? stamped.transaction : ""
|
|
6996
|
+
});
|
|
6997
|
+
} catch (e50) {
|
|
6998
|
+
warnAttestDegrade("signing failed");
|
|
6999
|
+
return void 0;
|
|
7000
|
+
}
|
|
7001
|
+
}
|
|
6061
7002
|
function reportOnFailedError(error, failure) {
|
|
6062
7003
|
if (!options.onFailedError) return;
|
|
6063
7004
|
try {
|
|
6064
7005
|
options.onFailedError(error, failure);
|
|
6065
|
-
} catch (
|
|
7006
|
+
} catch (e51) {
|
|
6066
7007
|
}
|
|
6067
7008
|
}
|
|
6068
7009
|
function fireOnFailed(failure) {
|
|
@@ -6084,6 +7025,14 @@ function createPaymentGate(options) {
|
|
|
6084
7025
|
if (options.awaitOnFailed) await fireOnFailed(failure);
|
|
6085
7026
|
else void fireOnFailed(failure);
|
|
6086
7027
|
}
|
|
7028
|
+
function railExtra(full) {
|
|
7029
|
+
const out = {};
|
|
7030
|
+
for (const k of ["assetTransferMethod", "facilitatorAddress", "name", "version"]) {
|
|
7031
|
+
const v = full[k];
|
|
7032
|
+
if (v !== void 0 && v !== "") out[k] = v;
|
|
7033
|
+
}
|
|
7034
|
+
return Object.keys(out).length > 0 ? { extra: out } : {};
|
|
7035
|
+
}
|
|
6087
7036
|
async function describe(resourceUrl = "") {
|
|
6088
7037
|
const specs = await ready();
|
|
6089
7038
|
const accepts = [];
|
|
@@ -6098,7 +7047,8 @@ function createPaymentGate(options) {
|
|
|
6098
7047
|
maxTimeoutSeconds,
|
|
6099
7048
|
...s.symbol ? { symbol: s.symbol } : {}
|
|
6100
7049
|
};
|
|
6101
|
-
if (s.exact) accepts.push({ scheme: "exact", ...base2 });
|
|
7050
|
+
if (s.exact) accepts.push({ scheme: "exact", ...base2, ...railExtra(buildExactAccept(s).extra) });
|
|
7051
|
+
if (s.upto) accepts.push({ scheme: "upto", ...base2, ...railExtra(buildUptoAccept(s).extra) });
|
|
6102
7052
|
accepts.push({ scheme: "onchain-proof", ...base2 });
|
|
6103
7053
|
}
|
|
6104
7054
|
return {
|
|
@@ -6134,7 +7084,7 @@ function createPaymentGate(options) {
|
|
|
6134
7084
|
}
|
|
6135
7085
|
await settleTx(ref, true);
|
|
6136
7086
|
await deliverOnPaid(spec, result.receipt);
|
|
6137
|
-
return
|
|
7087
|
+
return await buildPaidResult(spec, result.receipt, sig.payload.nonce);
|
|
6138
7088
|
}
|
|
6139
7089
|
async function verifyExact(exact) {
|
|
6140
7090
|
const specs = await ready();
|
|
@@ -6162,28 +7112,28 @@ function createPaymentGate(options) {
|
|
|
6162
7112
|
nonce = [exact.payload.transaction, exact.payload.senderAuth].map((t) => {
|
|
6163
7113
|
try {
|
|
6164
7114
|
return Buffer.from(t, "base64").toString("base64");
|
|
6165
|
-
} catch (
|
|
7115
|
+
} catch (e52) {
|
|
6166
7116
|
return t;
|
|
6167
7117
|
}
|
|
6168
7118
|
}).join("|");
|
|
6169
7119
|
} else if ("transaction" in exact.payload) {
|
|
6170
7120
|
try {
|
|
6171
7121
|
nonce = Buffer.from(exact.payload.transaction, "base64").toString("base64");
|
|
6172
|
-
} catch (
|
|
7122
|
+
} catch (e53) {
|
|
6173
7123
|
nonce = exact.payload.transaction;
|
|
6174
7124
|
}
|
|
6175
7125
|
} else if ("paymentGroup" in exact.payload) {
|
|
6176
7126
|
nonce = exact.payload.paymentGroup.map((t) => {
|
|
6177
7127
|
try {
|
|
6178
7128
|
return Buffer.from(t, "base64").toString("base64");
|
|
6179
|
-
} catch (
|
|
7129
|
+
} catch (e54) {
|
|
6180
7130
|
return t;
|
|
6181
7131
|
}
|
|
6182
7132
|
}).join("|");
|
|
6183
7133
|
} else if ("signedDelegateAction" in exact.payload) {
|
|
6184
7134
|
try {
|
|
6185
7135
|
nonce = Buffer.from(exact.payload.signedDelegateAction, "base64").toString("base64");
|
|
6186
|
-
} catch (
|
|
7136
|
+
} catch (e55) {
|
|
6187
7137
|
nonce = exact.payload.signedDelegateAction;
|
|
6188
7138
|
}
|
|
6189
7139
|
} else if ("permit2Authorization" in exact.payload) {
|
|
@@ -6244,27 +7194,122 @@ function createPaymentGate(options) {
|
|
|
6244
7194
|
}
|
|
6245
7195
|
await settleTx(nonce, true);
|
|
6246
7196
|
await deliverOnPaid(spec, result.receipt);
|
|
6247
|
-
return
|
|
7197
|
+
return await buildPaidResult(spec, result.receipt);
|
|
7198
|
+
}
|
|
7199
|
+
function resolveSettleAmount(raw, maxAmount, decimals) {
|
|
7200
|
+
if (typeof raw === "bigint") return raw < 0n ? null : raw;
|
|
7201
|
+
const s = raw.trim();
|
|
7202
|
+
if (s.length === 0) return null;
|
|
7203
|
+
try {
|
|
7204
|
+
if (s.endsWith("%")) {
|
|
7205
|
+
const pct = s.slice(0, -1).trim();
|
|
7206
|
+
if (!/^\d+(\.\d+)?$/.test(pct)) return null;
|
|
7207
|
+
const pctScaled = _chunkMWBT7MCEcjs.floorUnits.call(void 0, pct, 4);
|
|
7208
|
+
return maxAmount * pctScaled / (100n * 10n ** 4n);
|
|
7209
|
+
}
|
|
7210
|
+
if (s.startsWith("$")) {
|
|
7211
|
+
const amt = s.slice(1).trim();
|
|
7212
|
+
return _chunkMWBT7MCEcjs.floorUnits.call(void 0, amt, decimals);
|
|
7213
|
+
}
|
|
7214
|
+
if (/^\d+$/.test(s)) return BigInt(s);
|
|
7215
|
+
return _chunkMWBT7MCEcjs.floorUnits.call(void 0, s, decimals);
|
|
7216
|
+
} catch (e56) {
|
|
7217
|
+
return null;
|
|
7218
|
+
}
|
|
7219
|
+
}
|
|
7220
|
+
async function verifyUpto(upto) {
|
|
7221
|
+
const specs = await ready();
|
|
7222
|
+
const uptoSpecs = specs.filter((s) => s.upto);
|
|
7223
|
+
if (uptoSpecs.length === 0) {
|
|
7224
|
+
return rejection("transfer_not_found", "This resource offers no standard `upto` (metered) rail.");
|
|
7225
|
+
}
|
|
7226
|
+
const isCaip = upto.network.includes(":");
|
|
7227
|
+
let candidates = isCaip ? uptoSpecs.filter((s) => s.net.network === upto.network) : uptoSpecs;
|
|
7228
|
+
if (upto.asset) {
|
|
7229
|
+
candidates = candidates.filter((s) => s.asset.toLowerCase() === upto.asset.toLowerCase());
|
|
7230
|
+
}
|
|
7231
|
+
let spec = candidates[0];
|
|
7232
|
+
if (!isCaip && !upto.asset && uptoSpecs.length > 1) spec = void 0;
|
|
7233
|
+
if (!spec && !isCaip && !upto.asset && uptoSpecs.length === 1) spec = uptoSpecs[0];
|
|
7234
|
+
if (!spec || !spec.upto) {
|
|
7235
|
+
return rejection(
|
|
7236
|
+
"transfer_not_found",
|
|
7237
|
+
`No \`upto\` rail offered for ${upto.network}${upto.asset ? `/${upto.asset}` : ""} (offered: ${uptoSpecs.map((s) => `${s.asset}@${s.net.network}`).join(", ")}).`
|
|
7238
|
+
);
|
|
7239
|
+
}
|
|
7240
|
+
const nonce = upto.payload.permit2Authorization.nonce;
|
|
7241
|
+
if (await claimTx(nonce)) {
|
|
7242
|
+
return rejection("tx_already_used", `Authorization nonce ${nonce} was already redeemed.`);
|
|
7243
|
+
}
|
|
7244
|
+
const accept = buildUptoAccept(spec);
|
|
7245
|
+
const relayer = spec.upto.relayer;
|
|
7246
|
+
let result;
|
|
7247
|
+
try {
|
|
7248
|
+
const rawAmount = await options.upto.settleAmount({
|
|
7249
|
+
maxAmount: spec.amountBase,
|
|
7250
|
+
asset: spec.asset,
|
|
7251
|
+
network: spec.net.network,
|
|
7252
|
+
decimals: spec.decimals,
|
|
7253
|
+
...upto.raw ? { request: upto.raw } : {}
|
|
7254
|
+
});
|
|
7255
|
+
const settleAmount = resolveSettleAmount(rawAmount, spec.amountBase, spec.decimals);
|
|
7256
|
+
if (settleAmount === null) {
|
|
7257
|
+
await settleTx(nonce, false);
|
|
7258
|
+
return rejection(
|
|
7259
|
+
"upto_settle_exceeds_max",
|
|
7260
|
+
`The settleAmount callback returned an unparseable amount (${String(rawAmount)}). Return a bigint, a raw/"NN%"/"$X" string, or 0.`
|
|
7261
|
+
);
|
|
7262
|
+
}
|
|
7263
|
+
result = await spec.net.settleUptoSelf({ relayer, payload: upto.payload, accept, settleAmount });
|
|
7264
|
+
} catch (err) {
|
|
7265
|
+
await settleTx(nonce, false);
|
|
7266
|
+
if (err instanceof _chunkMWBT7MCEcjs.SettlementError) throw err;
|
|
7267
|
+
return rejection(
|
|
7268
|
+
"tx_reverted",
|
|
7269
|
+
`upto: metering/settle failed (${err instanceof Error ? err.message : String(err)}).`
|
|
7270
|
+
);
|
|
7271
|
+
}
|
|
7272
|
+
if (!result.ok) {
|
|
7273
|
+
await settleTx(nonce, false);
|
|
7274
|
+
return rejection(result.error, result.detail);
|
|
7275
|
+
}
|
|
7276
|
+
await settleTx(nonce, true);
|
|
7277
|
+
await deliverOnPaid(spec, result.receipt);
|
|
7278
|
+
return await buildPaidResult(spec, result.receipt);
|
|
6248
7279
|
}
|
|
6249
7280
|
async function verify(paymentSignature) {
|
|
6250
|
-
const
|
|
7281
|
+
const raw = normaliseHeader(paymentSignature);
|
|
7282
|
+
const result = await resolveVerdictObject(raw === void 0 ? void 0 : decodeBase64Json(raw));
|
|
6251
7283
|
if (result.kind === "invalid") await deliverOnFailed(result);
|
|
6252
7284
|
return result;
|
|
6253
7285
|
}
|
|
6254
|
-
async function
|
|
6255
|
-
const
|
|
6256
|
-
if (
|
|
6257
|
-
|
|
7286
|
+
async function verifyObject(payload) {
|
|
7287
|
+
const result = await resolveVerdictObject(payload);
|
|
7288
|
+
if (result.kind === "invalid") await deliverOnFailed(result);
|
|
7289
|
+
return result;
|
|
7290
|
+
}
|
|
7291
|
+
async function resolveVerdictObject(obj) {
|
|
7292
|
+
if (obj === void 0 || obj === null) return asChallenge();
|
|
7293
|
+
const sig = parseSignatureObject(obj);
|
|
6258
7294
|
if (sig && sig.accepted && typeof sig.accepted.network === "string" && typeof sig.accepted.asset === "string") {
|
|
6259
7295
|
return verifyOnchainProof(sig);
|
|
6260
7296
|
}
|
|
6261
|
-
const
|
|
7297
|
+
const upto = parseUptoObject(obj);
|
|
7298
|
+
if (upto) return verifyUpto(upto);
|
|
7299
|
+
const exact = parseExactObject(obj);
|
|
6262
7300
|
if (exact) return verifyExact(exact);
|
|
6263
7301
|
return asChallenge();
|
|
6264
7302
|
}
|
|
6265
|
-
return { challenge, verify, describe, landingPage };
|
|
7303
|
+
return { challenge, verify, verifyObject, describe, landingPage };
|
|
6266
7304
|
}
|
|
6267
7305
|
function requirePayment(options) {
|
|
7306
|
+
if (options.upto) {
|
|
7307
|
+
throw new (_class3 = class extends _chunkMWBT7MCEcjs.PipRailError {constructor(...args2) { super(...args2); _class3.prototype.__init7.call(this); }
|
|
7308
|
+
__init7() {this.code = "UNSUPPORTED_SCHEME"}
|
|
7309
|
+
}, _class3)(
|
|
7310
|
+
"requirePayment: the 'upto' (metered) rail is unsupported through the Express middleware \u2014 it settles before the route handler serves, so metered usage is unknown at settle time. Call gate.verify() directly (createPaymentGate) and meter inside settleAmount; see docs/accepting-payments/upto-rail-seller.md."
|
|
7311
|
+
);
|
|
7312
|
+
}
|
|
6268
7313
|
const gate = createPaymentGate(options);
|
|
6269
7314
|
return async (req, res, next) => {
|
|
6270
7315
|
let result;
|
|
@@ -6319,7 +7364,7 @@ function isRetryableStatus(status) {
|
|
|
6319
7364
|
}
|
|
6320
7365
|
var sleep = (ms) => ms > 0 ? new Promise((resolve) => setTimeout(resolve, ms)) : Promise.resolve();
|
|
6321
7366
|
async function signBody(secret, body) {
|
|
6322
|
-
const subtle = _optionalChain([globalThis, 'access',
|
|
7367
|
+
const subtle = _optionalChain([globalThis, 'access', _129 => _129.crypto, 'optionalAccess', _130 => _130.subtle]);
|
|
6323
7368
|
if (!subtle) return null;
|
|
6324
7369
|
try {
|
|
6325
7370
|
const enc = new TextEncoder();
|
|
@@ -6329,7 +7374,7 @@ async function signBody(secret, body) {
|
|
|
6329
7374
|
const sig = await subtle.sign("HMAC", key, enc.encode(body));
|
|
6330
7375
|
const hex = Array.from(new Uint8Array(sig)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
6331
7376
|
return `sha256=${hex}`;
|
|
6332
|
-
} catch (
|
|
7377
|
+
} catch (e57) {
|
|
6333
7378
|
return null;
|
|
6334
7379
|
}
|
|
6335
7380
|
}
|
|
@@ -6389,8 +7434,8 @@ async function deliverReceipt(receipt, options) {
|
|
|
6389
7434
|
const retryable = status === void 0 ? true : isRetryableStatus(status);
|
|
6390
7435
|
const willRetry = !ok && retryable && attempt < maxAttempts;
|
|
6391
7436
|
try {
|
|
6392
|
-
_optionalChain([onAttempt, 'optionalCall',
|
|
6393
|
-
} catch (
|
|
7437
|
+
_optionalChain([onAttempt, 'optionalCall', _131 => _131({ attempt, ok, ...status !== void 0 ? { status } : {}, ...error ? { error } : {}, willRetry })]);
|
|
7438
|
+
} catch (e58) {
|
|
6394
7439
|
}
|
|
6395
7440
|
if (ok) return { delivered: true, attempts: attempt, status };
|
|
6396
7441
|
if (!willRetry) {
|
|
@@ -6411,6 +7456,272 @@ async function deliverReceipt(receipt, options) {
|
|
|
6411
7456
|
};
|
|
6412
7457
|
}
|
|
6413
7458
|
|
|
7459
|
+
// src/transports/a2a.ts
|
|
7460
|
+
var A2A_X402_EXTENSION_URI_V01 = "https://github.com/google-a2a/a2a-x402/v0.1";
|
|
7461
|
+
var A2A_X402_EXTENSION_URI_V02 = "https://github.com/google-agentic-commerce/a2a-x402/blob/main/spec/v0.2";
|
|
7462
|
+
var A2A_STATUS_KEY = "x402.payment.status";
|
|
7463
|
+
var A2A_REQUIRED_KEY = "x402.payment.required";
|
|
7464
|
+
var A2A_PAYLOAD_KEY = "x402.payment.payload";
|
|
7465
|
+
var A2A_RECEIPTS_KEY = "x402.payment.receipts";
|
|
7466
|
+
var A2A_ERROR_KEY = "x402.payment.error";
|
|
7467
|
+
var A2A_EXTENSIONS_HEADER = "X-A2A-Extensions";
|
|
7468
|
+
var MAX_TASK_RECEIPTS = 64;
|
|
7469
|
+
var VERIFY_CODE_TO_A2A_ERROR = {
|
|
7470
|
+
payment_expired: "EXPIRED_PAYMENT",
|
|
7471
|
+
tx_already_used: "DUPLICATE_NONCE",
|
|
7472
|
+
amount_too_low: "INVALID_AMOUNT",
|
|
7473
|
+
upto_settle_exceeds_max: "INVALID_AMOUNT",
|
|
7474
|
+
signature_invalid: "INVALID_SIGNATURE",
|
|
7475
|
+
transfer_not_found: "INVALID_AMOUNT",
|
|
7476
|
+
wrong_recipient: "INVALID_AMOUNT",
|
|
7477
|
+
tx_reverted: "SETTLEMENT_FAILED",
|
|
7478
|
+
tx_not_found: "EXPIRED_PAYMENT",
|
|
7479
|
+
insufficient_confirmations: "EXPIRED_PAYMENT",
|
|
7480
|
+
no_meta: "INVALID_SIGNATURE",
|
|
7481
|
+
// The settlement-side throw code the handler emits for a SettlementError (the merchant's
|
|
7482
|
+
// relayer/facilitator never moved funds) — maps to the spec's SETTLEMENT_FAILED.
|
|
7483
|
+
settlement_failed: "SETTLEMENT_FAILED"
|
|
7484
|
+
};
|
|
7485
|
+
function toA2AErrorCode(code) {
|
|
7486
|
+
return _nullishCoalesce(VERIFY_CODE_TO_A2A_ERROR[code], () => ( code));
|
|
7487
|
+
}
|
|
7488
|
+
function toA2APaymentRequired(taskId, challenge, parts) {
|
|
7489
|
+
const metadata = {
|
|
7490
|
+
[A2A_STATUS_KEY]: "payment-required",
|
|
7491
|
+
[A2A_REQUIRED_KEY]: challenge
|
|
7492
|
+
};
|
|
7493
|
+
return {
|
|
7494
|
+
kind: "task",
|
|
7495
|
+
id: taskId,
|
|
7496
|
+
status: {
|
|
7497
|
+
state: "input-required",
|
|
7498
|
+
message: { kind: "message", role: "agent", taskId, ...parts ? { parts } : {}, metadata }
|
|
7499
|
+
}
|
|
7500
|
+
};
|
|
7501
|
+
}
|
|
7502
|
+
function toA2APaymentReceipts(receipts) {
|
|
7503
|
+
return { [A2A_RECEIPTS_KEY]: receipts };
|
|
7504
|
+
}
|
|
7505
|
+
function toA2APaymentFailed(code, detail, receipts = [], network) {
|
|
7506
|
+
const entry = {
|
|
7507
|
+
success: false,
|
|
7508
|
+
transaction: "",
|
|
7509
|
+
...network ? { network } : {},
|
|
7510
|
+
errorReason: `${code}: ${detail}`
|
|
7511
|
+
};
|
|
7512
|
+
return {
|
|
7513
|
+
[A2A_STATUS_KEY]: "payment-failed",
|
|
7514
|
+
[A2A_ERROR_KEY]: toA2AErrorCode(code),
|
|
7515
|
+
[A2A_RECEIPTS_KEY]: [...receipts, entry]
|
|
7516
|
+
};
|
|
7517
|
+
}
|
|
7518
|
+
function fromA2APaymentRequired(task) {
|
|
7519
|
+
const meta = _optionalChain([task, 'access', _132 => _132.status, 'optionalAccess', _133 => _133.message, 'optionalAccess', _134 => _134.metadata]);
|
|
7520
|
+
const required = _optionalChain([meta, 'optionalAccess', _135 => _135[A2A_REQUIRED_KEY]]);
|
|
7521
|
+
if (!required || typeof required !== "object") return null;
|
|
7522
|
+
return required;
|
|
7523
|
+
}
|
|
7524
|
+
function fromA2APaymentPayload(message) {
|
|
7525
|
+
const raw = _optionalChain([message, 'access', _136 => _136.metadata, 'optionalAccess', _137 => _137[A2A_PAYLOAD_KEY]]);
|
|
7526
|
+
if (raw === void 0 || raw === null) return null;
|
|
7527
|
+
return { raw, taskId: _nullishCoalesce(message.taskId, () => ( "")) };
|
|
7528
|
+
}
|
|
7529
|
+
function defaultTaskStore() {
|
|
7530
|
+
const map = /* @__PURE__ */ new Map();
|
|
7531
|
+
function prune(now) {
|
|
7532
|
+
for (const [key, { expiry }] of map) {
|
|
7533
|
+
if (expiry > now) break;
|
|
7534
|
+
map.delete(key);
|
|
7535
|
+
}
|
|
7536
|
+
}
|
|
7537
|
+
return {
|
|
7538
|
+
get(taskId) {
|
|
7539
|
+
const now = Date.now();
|
|
7540
|
+
prune(now);
|
|
7541
|
+
const hit = map.get(taskId);
|
|
7542
|
+
return hit && hit.expiry > now ? hit.record : void 0;
|
|
7543
|
+
},
|
|
7544
|
+
set(taskId, value, ttlMs) {
|
|
7545
|
+
const now = Date.now();
|
|
7546
|
+
prune(now);
|
|
7547
|
+
map.delete(taskId);
|
|
7548
|
+
map.set(taskId, { record: value, expiry: now + ttlMs });
|
|
7549
|
+
}
|
|
7550
|
+
};
|
|
7551
|
+
}
|
|
7552
|
+
function createA2APaymentHandler(options) {
|
|
7553
|
+
const gate = _nullishCoalesce(options.gate, () => ( createPaymentGate(options)));
|
|
7554
|
+
const maxTimeoutSeconds = _nullishCoalesce(options.maxTimeoutSeconds, () => ( 600));
|
|
7555
|
+
const ttlMs = _nullishCoalesce(options.taskTtlMs, () => ( maxTimeoutSeconds * 1e3));
|
|
7556
|
+
const store = _nullishCoalesce(options.taskStore, () => ( defaultTaskStore()));
|
|
7557
|
+
function appendReceipt(taskId, entry) {
|
|
7558
|
+
const prior = _nullishCoalesce(_optionalChain([store, 'access', _138 => _138.get, 'call', _139 => _139(taskId), 'optionalAccess', _140 => _140.receipts]), () => ( []));
|
|
7559
|
+
const isDup = "success" in entry && entry.success === true && prior.some((r) => "transaction" in r && r.transaction === entry.transaction);
|
|
7560
|
+
const next = isDup ? prior : [...prior, entry];
|
|
7561
|
+
const receipts = next.length > MAX_TASK_RECEIPTS ? next.slice(-MAX_TASK_RECEIPTS) : next;
|
|
7562
|
+
store.set(taskId, { receipts }, ttlMs);
|
|
7563
|
+
return receipts;
|
|
7564
|
+
}
|
|
7565
|
+
function completedTask(taskId, receipts, artifacts, status = "payment-completed") {
|
|
7566
|
+
const metadata = { [A2A_STATUS_KEY]: status, ...toA2APaymentReceipts(receipts) };
|
|
7567
|
+
return {
|
|
7568
|
+
kind: "task",
|
|
7569
|
+
id: taskId,
|
|
7570
|
+
status: { state: "completed", message: { kind: "message", role: "agent", taskId, metadata } },
|
|
7571
|
+
...artifacts.length > 0 ? { artifacts } : {}
|
|
7572
|
+
};
|
|
7573
|
+
}
|
|
7574
|
+
function reChallengeTask(taskId, result, attempted) {
|
|
7575
|
+
if (result.kind !== "invalid") {
|
|
7576
|
+
const metadata2 = {
|
|
7577
|
+
[A2A_STATUS_KEY]: "payment-required",
|
|
7578
|
+
[A2A_REQUIRED_KEY]: result.challenge
|
|
7579
|
+
};
|
|
7580
|
+
return {
|
|
7581
|
+
kind: "task",
|
|
7582
|
+
id: taskId,
|
|
7583
|
+
status: { state: "input-required", message: { kind: "message", role: "agent", taskId, metadata: metadata2 } }
|
|
7584
|
+
};
|
|
7585
|
+
}
|
|
7586
|
+
const network = _nullishCoalesce(attempted, () => ( singleNetworkOf(result.challenge)));
|
|
7587
|
+
const receipts = appendReceiptFailed(taskId, result.error, result.detail, network);
|
|
7588
|
+
const metadata = {
|
|
7589
|
+
[A2A_STATUS_KEY]: "payment-rejected",
|
|
7590
|
+
[A2A_ERROR_KEY]: toA2AErrorCode(result.error),
|
|
7591
|
+
[A2A_REQUIRED_KEY]: result.challenge,
|
|
7592
|
+
...toA2APaymentReceipts(receipts)
|
|
7593
|
+
};
|
|
7594
|
+
return {
|
|
7595
|
+
kind: "task",
|
|
7596
|
+
id: taskId,
|
|
7597
|
+
status: { state: "input-required", message: { kind: "message", role: "agent", taskId, metadata } }
|
|
7598
|
+
};
|
|
7599
|
+
}
|
|
7600
|
+
function failedTask(taskId, code, detail, network) {
|
|
7601
|
+
const receipts = appendReceiptFailed(taskId, code, detail, network);
|
|
7602
|
+
const metadata = {
|
|
7603
|
+
[A2A_STATUS_KEY]: "payment-failed",
|
|
7604
|
+
[A2A_ERROR_KEY]: toA2AErrorCode(code),
|
|
7605
|
+
...toA2APaymentReceipts(receipts)
|
|
7606
|
+
};
|
|
7607
|
+
return {
|
|
7608
|
+
kind: "task",
|
|
7609
|
+
id: taskId,
|
|
7610
|
+
status: { state: "failed", message: { kind: "message", role: "agent", taskId, metadata } }
|
|
7611
|
+
};
|
|
7612
|
+
}
|
|
7613
|
+
function appendReceiptFailed(taskId, code, detail, network) {
|
|
7614
|
+
return appendReceipt(taskId, {
|
|
7615
|
+
success: false,
|
|
7616
|
+
transaction: "",
|
|
7617
|
+
...network ? { network } : {},
|
|
7618
|
+
errorReason: `${code}: ${detail}`
|
|
7619
|
+
});
|
|
7620
|
+
}
|
|
7621
|
+
async function handleMessage(message, taskId) {
|
|
7622
|
+
const id = _nullishCoalesce(_nullishCoalesce(taskId, () => ( message.taskId)), () => ( newTaskId()));
|
|
7623
|
+
const inbound = fromA2APaymentPayload(message);
|
|
7624
|
+
if (!inbound) {
|
|
7625
|
+
const { challenge } = await gate.challenge(resourceUrlFromMessage(message));
|
|
7626
|
+
store.set(id, { receipts: [] }, ttlMs);
|
|
7627
|
+
return toA2APaymentRequired(id, challenge);
|
|
7628
|
+
}
|
|
7629
|
+
const attempted = networkFromPayload(inbound.raw);
|
|
7630
|
+
let result;
|
|
7631
|
+
try {
|
|
7632
|
+
result = await gate.verifyObject(inbound.raw);
|
|
7633
|
+
} catch (err) {
|
|
7634
|
+
if (err instanceof _chunkMWBT7MCEcjs.SettlementError) {
|
|
7635
|
+
return failedTask(id, "settlement_failed", err.message, attempted);
|
|
7636
|
+
}
|
|
7637
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
7638
|
+
return failedTask(id, "tx_reverted", detail, attempted);
|
|
7639
|
+
}
|
|
7640
|
+
switch (result.kind) {
|
|
7641
|
+
case "challenge":
|
|
7642
|
+
return reChallengeTask(id, result, attempted);
|
|
7643
|
+
case "invalid":
|
|
7644
|
+
return reChallengeTask(id, result, attempted);
|
|
7645
|
+
case "paid": {
|
|
7646
|
+
const receipts = appendReceipt(id, result.receipt);
|
|
7647
|
+
let artifacts = [];
|
|
7648
|
+
if (options.fulfill) {
|
|
7649
|
+
try {
|
|
7650
|
+
artifacts = await _asyncNullishCoalesce(await options.fulfill({ taskId: id, receipt: result.receipt, message }), async () => ( []));
|
|
7651
|
+
} catch (err) {
|
|
7652
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
7653
|
+
const annotation = {
|
|
7654
|
+
name: "fulfillment-error",
|
|
7655
|
+
metadata: { "x402.fulfillment.error": detail, "x402.fulfillment.settled": true },
|
|
7656
|
+
parts: [{ kind: "text", text: `Payment settled, but serving the result failed: ${detail}` }]
|
|
7657
|
+
};
|
|
7658
|
+
return completedTask(id, receipts, [annotation]);
|
|
7659
|
+
}
|
|
7660
|
+
}
|
|
7661
|
+
return completedTask(id, receipts, artifacts);
|
|
7662
|
+
}
|
|
7663
|
+
}
|
|
7664
|
+
}
|
|
7665
|
+
function agentCardExtension(opts) {
|
|
7666
|
+
const uri = _optionalChain([opts, 'optionalAccess', _141 => _141.version]) === "v0.2" ? A2A_X402_EXTENSION_URI_V02 : A2A_X402_EXTENSION_URI_V01;
|
|
7667
|
+
return {
|
|
7668
|
+
uri,
|
|
7669
|
+
description: "Supports payments using the x402 protocol for on-chain settlement.",
|
|
7670
|
+
..._optionalChain([opts, 'optionalAccess', _142 => _142.required]) ? { required: true } : {}
|
|
7671
|
+
};
|
|
7672
|
+
}
|
|
7673
|
+
return { handleMessage, agentCardExtension, gate };
|
|
7674
|
+
}
|
|
7675
|
+
function singleNetworkOf(challenge) {
|
|
7676
|
+
const nets = new Set((_nullishCoalesce(challenge.accepts, () => ( []))).map((a) => a.network).filter(Boolean));
|
|
7677
|
+
return nets.size === 1 ? [...nets][0] : void 0;
|
|
7678
|
+
}
|
|
7679
|
+
function networkFromPayload(raw) {
|
|
7680
|
+
const v = raw;
|
|
7681
|
+
if (v && typeof _optionalChain([v, 'access', _143 => _143.accepted, 'optionalAccess', _144 => _144.network]) === "string") return v.accepted.network;
|
|
7682
|
+
if (v && typeof v.network === "string") return v.network;
|
|
7683
|
+
return void 0;
|
|
7684
|
+
}
|
|
7685
|
+
function newTaskId() {
|
|
7686
|
+
return `task-${globalThis.crypto.randomUUID()}`;
|
|
7687
|
+
}
|
|
7688
|
+
function resourceUrlFromMessage(message) {
|
|
7689
|
+
for (const part of _nullishCoalesce(message.parts, () => ( []))) {
|
|
7690
|
+
const data = part.data;
|
|
7691
|
+
if (data && typeof data.url === "string") return data.url;
|
|
7692
|
+
}
|
|
7693
|
+
return "";
|
|
7694
|
+
}
|
|
7695
|
+
|
|
7696
|
+
|
|
7697
|
+
|
|
7698
|
+
|
|
7699
|
+
|
|
7700
|
+
|
|
7701
|
+
|
|
7702
|
+
|
|
7703
|
+
|
|
7704
|
+
|
|
7705
|
+
|
|
7706
|
+
|
|
7707
|
+
|
|
7708
|
+
|
|
7709
|
+
|
|
7710
|
+
|
|
7711
|
+
|
|
7712
|
+
|
|
7713
|
+
|
|
7714
|
+
|
|
7715
|
+
|
|
7716
|
+
|
|
7717
|
+
|
|
7718
|
+
|
|
7719
|
+
|
|
7720
|
+
|
|
7721
|
+
|
|
7722
|
+
|
|
7723
|
+
|
|
7724
|
+
|
|
6414
7725
|
|
|
6415
7726
|
|
|
6416
7727
|
|
|
@@ -6514,4 +7825,4 @@ async function deliverReceipt(receipt, options) {
|
|
|
6514
7825
|
|
|
6515
7826
|
|
|
6516
7827
|
|
|
6517
|
-
exports.BRAND = BRAND; exports.BUILTIN_DENOMS = BUILTIN_DENOMS; exports.CHAINS = CHAINS; exports.ConfirmationTimeoutError = _chunkMWBT7MCEcjs.ConfirmationTimeoutError; exports.DENOM_PRECISION = DENOM_PRECISION; 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 = _chunkMWBT7MCEcjs.InsufficientFundsError; exports.InvalidEnvelopeError = _chunkMWBT7MCEcjs.InvalidEnvelopeError; exports.KNOWN_FACILITATORS = KNOWN_FACILITATORS; exports.MaxRetriesExceededError = _chunkMWBT7MCEcjs.MaxRetriesExceededError; exports.MissingDriverError = _chunkMWBT7MCEcjs.MissingDriverError; exports.MultiChainPayer = MultiChainPayer; exports.NoCompatibleAcceptError = _chunkMWBT7MCEcjs.NoCompatibleAcceptError; exports.NonReplayableBodyError = _chunkMWBT7MCEcjs.NonReplayableBodyError; exports.PERMIT2_ADDRESS = PERMIT2_ADDRESS; exports.PERMIT2_PROXY_CHAIN_IDS = PERMIT2_PROXY_CHAIN_IDS; exports.PERMIT2_WITNESS_TYPES = PERMIT2_WITNESS_TYPES; exports.PIPRAIL_AGENT_GUIDE = PIPRAIL_AGENT_GUIDE; exports.POWERED_BY = POWERED_BY; exports.PaymentDeclinedError = _chunkMWBT7MCEcjs.PaymentDeclinedError; exports.PaymentTimeoutError = _chunkMWBT7MCEcjs.PaymentTimeoutError; exports.PipRailClient = PipRailClient; exports.PipRailError = _chunkMWBT7MCEcjs.PipRailError; exports.REGISTER_ATTRIBUTION = REGISTER_ATTRIBUTION; exports.RecipientNotReadyError = _chunkMWBT7MCEcjs.RecipientNotReadyError; exports.SettlementError = _chunkMWBT7MCEcjs.SettlementError; exports.SpendLedger = SpendLedger; exports.UnknownTokenError = _chunkMWBT7MCEcjs.UnknownTokenError; exports.UnsupportedNetworkError = _chunkMWBT7MCEcjs.UnsupportedNetworkError; exports.UnsupportedSchemeError = _chunkMWBT7MCEcjs.UnsupportedSchemeError; exports.WalletRequiredError = _chunkMWBT7MCEcjs.WalletRequiredError; exports.WrongChainError = _chunkMWBT7MCEcjs.WrongChainError; exports.WrongFamilyError = _chunkMWBT7MCEcjs.WrongFamilyError; exports.X402_EXACT_PERMIT2_PROXY = X402_EXACT_PERMIT2_PROXY; exports.agentGuide = agentGuide; exports.appendAttribution = appendAttribution; exports.appendKeywords = appendKeywords; exports.buildBazaarExtension = buildBazaarExtension; exports.buildChallengeHeader = buildChallengeHeader; exports.buildEndpointInfo = buildEndpointInfo; exports.buildExactAuthorization = buildExactAuthorization; exports.buildExactSignatureHeader = buildExactSignatureHeader; exports.buildOpenApi = buildOpenApi; exports.buildReceiptHeader = buildReceiptHeader; exports.buildSelfDescription = buildSelfDescription; exports.buildSignatureHeader = buildSignatureHeader; exports.buildWellKnownX402 = buildWellKnownX402; exports.buildX402DnsTxt = buildX402DnsTxt; exports.chainIdForExactNetwork = chainIdForExactNetwork; exports.claim402IndexDomain = claim402IndexDomain; exports.classifyChallenge = classifyChallenge; exports.createPaymentGate = createPaymentGate; exports.decorateOutcome = decorateOutcome; exports.deliverReceipt = deliverReceipt; exports.denomOf = denomOf; exports.describeChallenge = describeChallenge; exports.discoveryHeaders = discoveryHeaders; exports.eip3009Abi = eip3009Abi; exports.encodeXPaymentHeader = encodeXPaymentHeader; exports.evaluatePolicy = evaluatePolicy; exports.explainDecline = explainDecline; exports.facilitatorCoverage = facilitatorCoverage; exports.fetchAcross = fetchAcross; exports.firstKeylessFacilitator = firstKeylessFacilitator; exports.formatSpendReport = formatSpendReport; exports.getDirectoryInfo = getDirectoryInfo; exports.isPermit2ProxyChain = isPermit2ProxyChain; exports.knownFacilitatorsFor = knownFacilitatorsFor; exports.memorySpendStore = _chunkO4UQOZ4Zcjs.memorySpendStore; exports.normalizeNetwork = normalizeNetwork; exports.parseChallenge = parseChallenge; exports.parseExactPaymentHeader = parseExactPaymentHeader; exports.parseExactRequirements = parseExactRequirements; exports.parseFacilitatorSupported = parseFacilitatorSupported; exports.parseReceipt = parseReceipt; exports.parseSettleResponse = parseSettleResponse; exports.parseSignatureHeader = parseSignatureHeader; exports.paymentTools = paymentTools; exports.pickAccept = pickAccept; exports.planAcross = planAcross; exports.rankResources = rankResources; exports.readExactDomain = readExactDomain; exports.register402Index = register402Index; exports.registerDriver = registerDriver; exports.registerX402Scan = registerX402Scan; exports.renderLandingPage = renderLandingPage; exports.requirePayment = requirePayment; exports.resolveChain = resolveChain; exports.scoreResource = scoreResource; exports.searchOpenIndexes = searchOpenIndexes; exports.settleViaFacilitator = settleViaFacilitator; exports.summarizePlan = summarizePlan; exports.toInsufficientFundsError = _chunkMWBT7MCEcjs.toInsufficientFundsError; exports.toInvalidBody = toInvalidBody; exports.verify402IndexDomain = verify402IndexDomain;
|
|
7828
|
+
exports.A2A_ERROR_KEY = A2A_ERROR_KEY; exports.A2A_EXTENSIONS_HEADER = A2A_EXTENSIONS_HEADER; exports.A2A_PAYLOAD_KEY = A2A_PAYLOAD_KEY; exports.A2A_RECEIPTS_KEY = A2A_RECEIPTS_KEY; exports.A2A_REQUIRED_KEY = A2A_REQUIRED_KEY; exports.A2A_STATUS_KEY = A2A_STATUS_KEY; exports.A2A_X402_EXTENSION_URI_V01 = A2A_X402_EXTENSION_URI_V01; exports.A2A_X402_EXTENSION_URI_V02 = A2A_X402_EXTENSION_URI_V02; exports.BRAND = BRAND; exports.BUILTIN_DENOMS = BUILTIN_DENOMS; exports.CHAINS = CHAINS; exports.ConfirmationTimeoutError = _chunkMWBT7MCEcjs.ConfirmationTimeoutError; exports.DENOM_PRECISION = DENOM_PRECISION; exports.DIRECTORY_INFO = DIRECTORY_INFO; exports.EIP3009_TYPES = EIP3009_TYPES; exports.EXACT_NETWORK_SLUGS = EXACT_NETWORK_SLUGS; exports.EXT_OFFER_RECEIPT = EXT_OFFER_RECEIPT; 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 = _chunkMWBT7MCEcjs.InsufficientFundsError; exports.InvalidEnvelopeError = _chunkMWBT7MCEcjs.InvalidEnvelopeError; exports.KNOWN_FACILITATORS = KNOWN_FACILITATORS; exports.MaxRetriesExceededError = _chunkMWBT7MCEcjs.MaxRetriesExceededError; exports.MissingDriverError = _chunkMWBT7MCEcjs.MissingDriverError; exports.MultiChainPayer = MultiChainPayer; exports.NoCompatibleAcceptError = _chunkMWBT7MCEcjs.NoCompatibleAcceptError; exports.NonReplayableBodyError = _chunkMWBT7MCEcjs.NonReplayableBodyError; exports.PERMIT2_ADDRESS = PERMIT2_ADDRESS; exports.PERMIT2_PROXY_CHAIN_IDS = PERMIT2_PROXY_CHAIN_IDS; exports.PERMIT2_UPTO_WITNESS_TYPES = PERMIT2_UPTO_WITNESS_TYPES; exports.PERMIT2_WITNESS_TYPES = PERMIT2_WITNESS_TYPES; exports.PIPRAIL_AGENT_GUIDE = PIPRAIL_AGENT_GUIDE; exports.POWERED_BY = POWERED_BY; exports.PaymentDeclinedError = _chunkMWBT7MCEcjs.PaymentDeclinedError; exports.PaymentTimeoutError = _chunkMWBT7MCEcjs.PaymentTimeoutError; exports.PipRailClient = PipRailClient; exports.PipRailError = _chunkMWBT7MCEcjs.PipRailError; exports.REGISTER_ATTRIBUTION = REGISTER_ATTRIBUTION; exports.RecipientNotReadyError = _chunkMWBT7MCEcjs.RecipientNotReadyError; exports.SettlementError = _chunkMWBT7MCEcjs.SettlementError; exports.SpendLedger = SpendLedger; exports.UPTO_PROXY_CHAIN_IDS = UPTO_PROXY_CHAIN_IDS; exports.UnknownTokenError = _chunkMWBT7MCEcjs.UnknownTokenError; exports.UnsupportedNetworkError = _chunkMWBT7MCEcjs.UnsupportedNetworkError; exports.UnsupportedSchemeError = _chunkMWBT7MCEcjs.UnsupportedSchemeError; exports.VERIFY_CODE_TO_A2A_ERROR = VERIFY_CODE_TO_A2A_ERROR; exports.WalletRequiredError = _chunkMWBT7MCEcjs.WalletRequiredError; exports.WrongChainError = _chunkMWBT7MCEcjs.WrongChainError; exports.WrongFamilyError = _chunkMWBT7MCEcjs.WrongFamilyError; exports.X402_EXACT_PERMIT2_PROXY = X402_EXACT_PERMIT2_PROXY; exports.X402_UPTO_PERMIT2_PROXY = X402_UPTO_PERMIT2_PROXY; exports.agentGuide = agentGuide; exports.appendAttribution = appendAttribution; exports.appendKeywords = appendKeywords; exports.buildBazaarExtension = buildBazaarExtension; exports.buildChallengeHeader = buildChallengeHeader; exports.buildEndpointInfo = buildEndpointInfo; exports.buildExactAuthorization = buildExactAuthorization; exports.buildExactSignatureHeader = buildExactSignatureHeader; exports.buildOpenApi = buildOpenApi; exports.buildReceiptExtension = buildReceiptExtension; exports.buildReceiptHeader = buildReceiptHeader; exports.buildSelfDescription = buildSelfDescription; exports.buildSignatureHeader = buildSignatureHeader; exports.buildUptoSignatureHeader = buildUptoSignatureHeader; exports.buildWellKnownX402 = buildWellKnownX402; exports.buildX402DnsTxt = buildX402DnsTxt; exports.chainIdForExactNetwork = chainIdForExactNetwork; exports.claim402IndexDomain = claim402IndexDomain; exports.classifyChallenge = classifyChallenge; exports.createA2APaymentHandler = createA2APaymentHandler; exports.createPaymentGate = createPaymentGate; exports.decodeBase64Json = decodeBase64Json; exports.decorateOutcome = decorateOutcome; exports.deliverReceipt = deliverReceipt; exports.denomOf = denomOf; exports.describeChallenge = describeChallenge; exports.discoveryHeaders = discoveryHeaders; exports.eip3009Abi = eip3009Abi; exports.encodeXPaymentHeader = encodeXPaymentHeader; exports.evaluatePolicy = evaluatePolicy; exports.explainDecline = explainDecline; exports.facilitatorCoverage = facilitatorCoverage; exports.fetchAcross = fetchAcross; exports.firstKeylessFacilitator = firstKeylessFacilitator; exports.formatSpendReport = formatSpendReport; exports.fromA2APaymentPayload = fromA2APaymentPayload; exports.fromA2APaymentRequired = fromA2APaymentRequired; exports.getDirectoryInfo = getDirectoryInfo; exports.isPermit2ProxyChain = isPermit2ProxyChain; exports.isUptoProxyChain = isUptoProxyChain; exports.knownFacilitatorsFor = knownFacilitatorsFor; exports.memorySpendStore = _chunkO4UQOZ4Zcjs.memorySpendStore; exports.normalizeNetwork = normalizeNetwork; exports.parseChallenge = parseChallenge; exports.parseExactObject = parseExactObject; exports.parseExactPaymentHeader = parseExactPaymentHeader; exports.parseExactRequirements = parseExactRequirements; exports.parseFacilitatorSupported = parseFacilitatorSupported; exports.parseReceipt = parseReceipt; exports.parseReceiptExtension = parseReceiptExtension; exports.parseSettleResponse = parseSettleResponse; exports.parseSignatureHeader = parseSignatureHeader; exports.parseSignatureObject = parseSignatureObject; exports.parseUptoObject = parseUptoObject; exports.parseUptoPaymentHeader = parseUptoPaymentHeader; exports.paymentTools = paymentTools; exports.pickAccept = pickAccept; exports.planAcross = planAcross; exports.rankResources = rankResources; exports.readExactDomain = readExactDomain; exports.register402Index = register402Index; exports.registerDriver = registerDriver; exports.registerX402Scan = registerX402Scan; exports.renderLandingPage = renderLandingPage; exports.requirePayment = requirePayment; exports.resolveChain = resolveChain; exports.scoreResource = scoreResource; exports.searchOpenIndexes = searchOpenIndexes; exports.settleViaFacilitator = settleViaFacilitator; exports.summarizePlan = summarizePlan; exports.toA2AErrorCode = toA2AErrorCode; exports.toA2APaymentFailed = toA2APaymentFailed; exports.toA2APaymentReceipts = toA2APaymentReceipts; exports.toA2APaymentRequired = toA2APaymentRequired; exports.toInsufficientFundsError = _chunkMWBT7MCEcjs.toInsufficientFundsError; exports.toInvalidBody = toInvalidBody; exports.verify402IndexDomain = verify402IndexDomain;
|