@piprail/sdk 3.0.0 → 3.1.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/dist/index.cjs CHANGED
@@ -401,6 +401,11 @@ function resolveChain(input, rpcUrlOverride) {
401
401
  }
402
402
  return { chain: input, chainId: input.id, rpcUrl: rpcUrl2, tokens: knownTokensForId(input.id) };
403
403
  }
404
+ if (!Number.isSafeInteger(input.id) || input.id <= 0) {
405
+ throw new Error(
406
+ `resolveChain: chain id must be a positive safe integer (EIP-155), got ${String(input.id)}.`
407
+ );
408
+ }
404
409
  const rpcUrl = _nullishCoalesce(rpcUrlOverride, () => ( input.rpcUrl));
405
410
  if (!rpcUrl) {
406
411
  throw new Error(`resolveChain: chain ${input.id} needs an rpcUrl.`);
@@ -574,12 +579,29 @@ async function quoteEvmSwap(p) {
574
579
  } catch (e3) {
575
580
  return null;
576
581
  }
577
- const real = await route(needIn);
578
- const summary = _optionalChain([real, 'optionalAccess', _5 => _5.data, 'optionalAccess', _6 => _6.routeSummary]);
579
- if (!_optionalChain([summary, 'optionalAccess', _7 => _7.amountOut]) || !_optionalChain([real, 'optionalAccess', _8 => _8.data, 'optionalAccess', _9 => _9.routerAddress])) return null;
582
+ const MAX_REFINEMENTS = 3;
583
+ let real = await route(needIn);
584
+ let summary = _optionalChain([real, 'optionalAccess', _5 => _5.data, 'optionalAccess', _6 => _6.routeSummary]);
585
+ for (let attempt = 0; attempt < MAX_REFINEMENTS; attempt++) {
586
+ if (!_optionalChain([summary, 'optionalAccess', _7 => _7.amountOut])) break;
587
+ let out;
588
+ try {
589
+ out = BigInt(summary.amountOut);
590
+ } catch (e4) {
591
+ return null;
592
+ }
593
+ if (out >= p.wantAmount) break;
594
+ if (out <= 0n) return null;
595
+ const next = _chunkMZXVXC3Ccjs.applySlippage.call(void 0, (needIn * p.wantAmount + out - 1n) / out, p.slippageBps);
596
+ if (next <= needIn) break;
597
+ needIn = next;
598
+ real = await route(needIn);
599
+ summary = _optionalChain([real, 'optionalAccess', _8 => _8.data, 'optionalAccess', _9 => _9.routeSummary]);
600
+ }
601
+ if (!_optionalChain([summary, 'optionalAccess', _10 => _10.amountOut]) || !_optionalChain([real, 'optionalAccess', _11 => _11.data, 'optionalAccess', _12 => _12.routerAddress])) return null;
580
602
  try {
581
603
  if (BigInt(summary.amountOut) < p.wantAmount) return null;
582
- } catch (e4) {
604
+ } catch (e5) {
583
605
  return null;
584
606
  }
585
607
  const needsApproval = p.from.asset !== "native";
@@ -606,7 +628,7 @@ async function quoteEvmSwap(p) {
606
628
  async function swapEvm(p) {
607
629
  const { publicClient, walletClient, account, chain, quote } = p;
608
630
  const route = quote.route;
609
- if (!_optionalChain([route, 'optionalAccess', _10 => _10.routerAddress]) || !route.routeSummary) {
631
+ if (!_optionalChain([route, 'optionalAccess', _13 => _13.routerAddress]) || !route.routeSummary) {
610
632
  throw new Error("EVM: swap quote is missing its routing data \u2014 re-quote before swapping.");
611
633
  }
612
634
  const router = route.routerAddress;
@@ -621,7 +643,7 @@ async function swapEvm(p) {
621
643
  functionName: "allowance",
622
644
  args: [account.address, router]
623
645
  });
624
- } catch (e5) {
646
+ } catch (e6) {
625
647
  allowance = 0n;
626
648
  }
627
649
  if (allowance < spend) {
@@ -661,7 +683,7 @@ async function swapEvm(p) {
661
683
  })
662
684
  }
663
685
  );
664
- if (!_optionalChain([built, 'optionalAccess', _11 => _11.data, 'optionalAccess', _12 => _12.data])) {
686
+ if (!_optionalChain([built, 'optionalAccess', _14 => _14.data, 'optionalAccess', _15 => _15.data])) {
665
687
  throw new (0, _chunk6XTNI2OQcjs.InsufficientFundsError)(
666
688
  "KyberSwap could not build this swap (the route went stale, or the market moved). Nothing was spent \u2014 re-quote and retry."
667
689
  );
@@ -701,7 +723,7 @@ async function swapEvm(p) {
701
723
  to: quote.to
702
724
  };
703
725
  } catch (err) {
704
- const msg = String(_nullishCoalesce(_optionalChain([err, 'optionalAccess', _13 => _13.message]), () => ( err)));
726
+ const msg = String(_nullishCoalesce(_optionalChain([err, 'optionalAccess', _16 => _16.message]), () => ( err)));
705
727
  if (/TRANSFER_FROM_FAILED/i.test(msg)) {
706
728
  throw new (0, _chunk6XTNI2OQcjs.InsufficientFundsError)(
707
729
  "EVM swap reverted moving the token: the router allowance was rejected or the balance is short. Nothing was swapped. Some tokens refuse a non-zero to non-zero approve; re-quote and retry, which resets the allowance first.",
@@ -733,7 +755,7 @@ async function verifyEvm(params) {
733
755
  let receipt;
734
756
  try {
735
757
  receipt = await publicClient.getTransactionReceipt({ hash: txHash });
736
- } catch (e6) {
758
+ } catch (e7) {
737
759
  return {
738
760
  ok: false,
739
761
  error: "tx_not_found",
@@ -752,7 +774,7 @@ async function verifyEvm(params) {
752
774
  try {
753
775
  latestBlock = await publicClient.getBlockNumber();
754
776
  block = await publicClient.getBlock({ blockNumber: receipt.blockNumber });
755
- } catch (e7) {
777
+ } catch (e8) {
756
778
  return {
757
779
  ok: false,
758
780
  error: "tx_not_found",
@@ -780,7 +802,7 @@ async function verifyEvm(params) {
780
802
  let tx;
781
803
  try {
782
804
  tx = await publicClient.getTransaction({ hash: txHash });
783
- } catch (e8) {
805
+ } catch (e9) {
784
806
  return {
785
807
  ok: false,
786
808
  error: "tx_not_found",
@@ -846,7 +868,7 @@ function sumTransfersTo(logs, asset, payTo) {
846
868
  if (_viem.getAddress.call(void 0, args.to) !== payTo) continue;
847
869
  total += args.value;
848
870
  from = _viem.getAddress.call(void 0, args.from);
849
- } catch (e9) {
871
+ } catch (e10) {
850
872
  }
851
873
  }
852
874
  return { total, from };
@@ -969,8 +991,8 @@ async function buildExactAuthorization(params) {
969
991
  };
970
992
  const signature = await account.signTypedData({
971
993
  domain: {
972
- name: _nullishCoalesce(_optionalChain([accept, 'access', _14 => _14.extra, 'optionalAccess', _15 => _15.name]), () => ( "USD Coin")),
973
- version: _nullishCoalesce(_optionalChain([accept, 'access', _16 => _16.extra, 'optionalAccess', _17 => _17.version]), () => ( "2")),
994
+ name: _nullishCoalesce(_optionalChain([accept, 'access', _17 => _17.extra, 'optionalAccess', _18 => _18.name]), () => ( "USD Coin")),
995
+ version: _nullishCoalesce(_optionalChain([accept, 'access', _19 => _19.extra, 'optionalAccess', _20 => _20.version]), () => ( "2")),
974
996
  chainId,
975
997
  verifyingContract: accept.asset
976
998
  },
@@ -1011,7 +1033,7 @@ async function payExactEvm(input) {
1011
1033
  let code;
1012
1034
  try {
1013
1035
  code = await publicClient.getCode({ address: account.address });
1014
- } catch (e10) {
1036
+ } catch (e11) {
1015
1037
  code = void 0;
1016
1038
  }
1017
1039
  if (code && code !== "0x") {
@@ -1030,7 +1052,7 @@ async function payExactEvm(input) {
1030
1052
  );
1031
1053
  }
1032
1054
  const g = globalThis.crypto;
1033
- if (!_optionalChain([g, 'optionalAccess', _18 => _18.getRandomValues])) {
1055
+ if (!_optionalChain([g, 'optionalAccess', _21 => _21.getRandomValues])) {
1034
1056
  throw new (0, _chunk6XTNI2OQcjs.UnsupportedSchemeError)(
1035
1057
  "this runtime lacks Web Crypto (globalThis.crypto.getRandomValues); the exact rail needs a CSPRNG nonce."
1036
1058
  );
@@ -1125,7 +1147,7 @@ async function readExactDomain(publicClient, asset) {
1125
1147
  let token;
1126
1148
  try {
1127
1149
  token = _viem.getAddress.call(void 0, asset);
1128
- } catch (e11) {
1150
+ } catch (e12) {
1129
1151
  return null;
1130
1152
  }
1131
1153
  let name;
@@ -1141,13 +1163,13 @@ async function readExactDomain(publicClient, asset) {
1141
1163
  ]);
1142
1164
  if (typeof n !== "string" || !n) return null;
1143
1165
  name = n;
1144
- } catch (e12) {
1166
+ } catch (e13) {
1145
1167
  return null;
1146
1168
  }
1147
1169
  try {
1148
1170
  const version = await publicClient.readContract({ address: token, abi: eip3009Abi, functionName: "version" });
1149
1171
  if (typeof version === "string" && version) return { name, version };
1150
- } catch (e13) {
1172
+ } catch (e14) {
1151
1173
  }
1152
1174
  return deriveExactDomainVersion(publicClient, token, name);
1153
1175
  }
@@ -1156,8 +1178,8 @@ async function deriveExactDomainVersion(publicClient, token, name) {
1156
1178
  let chainId;
1157
1179
  try {
1158
1180
  onchain = await publicClient.readContract({ address: token, abi: eip3009Abi, functionName: "DOMAIN_SEPARATOR" });
1159
- chainId = await _asyncNullishCoalesce(await _asyncOptionalChain([publicClient, 'access', async _19 => _19.chain, 'optionalAccess', async _20 => _20.id]), async () => ( await publicClient.getChainId()));
1160
- } catch (e14) {
1181
+ chainId = await _asyncNullishCoalesce(await _asyncOptionalChain([publicClient, 'access', async _22 => _22.chain, 'optionalAccess', async _23 => _23.id]), async () => ( await publicClient.getChainId()));
1182
+ } catch (e15) {
1161
1183
  return null;
1162
1184
  }
1163
1185
  const target = onchain.toLowerCase();
@@ -1212,7 +1234,7 @@ async function verifyAndSettleExactEvm(input) {
1212
1234
  let fromCode;
1213
1235
  try {
1214
1236
  fromCode = await publicClient.getCode({ address: from });
1215
- } catch (e15) {
1237
+ } catch (e16) {
1216
1238
  return { ok: false, error: "tx_not_found", detail: `Could not read code at ${from} (transient RPC) \u2014 retry.` };
1217
1239
  }
1218
1240
  const isContractWallet = Boolean(fromCode && fromCode !== "0x");
@@ -1221,8 +1243,8 @@ async function verifyAndSettleExactEvm(input) {
1221
1243
  try {
1222
1244
  recovered = await _viem.recoverTypedDataAddress.call(void 0, {
1223
1245
  domain: {
1224
- name: _optionalChain([accept, 'access', _21 => _21.extra, 'optionalAccess', _22 => _22.name]),
1225
- version: _optionalChain([accept, 'access', _23 => _23.extra, 'optionalAccess', _24 => _24.version]),
1246
+ name: _optionalChain([accept, 'access', _24 => _24.extra, 'optionalAccess', _25 => _25.name]),
1247
+ version: _optionalChain([accept, 'access', _26 => _26.extra, 'optionalAccess', _27 => _27.version]),
1226
1248
  chainId: chain.id,
1227
1249
  verifyingContract: token
1228
1250
  },
@@ -1248,7 +1270,7 @@ async function verifyAndSettleExactEvm(input) {
1248
1270
  if (used) {
1249
1271
  return { ok: false, error: "tx_already_used", detail: `Authorization nonce ${nonce} already used or canceled on-chain.` };
1250
1272
  }
1251
- } catch (e16) {
1273
+ } catch (e17) {
1252
1274
  return { ok: false, error: "tx_not_found", detail: "Could not read authorizationState (transient RPC) \u2014 retry." };
1253
1275
  }
1254
1276
  const baseArgs = [from, to, value, validAfter, validBefore, nonce];
@@ -1294,7 +1316,7 @@ async function verifyAndSettleExactEvm(input) {
1294
1316
  );
1295
1317
  }
1296
1318
  try {
1297
- const confirmations = _nullishCoalesce(_optionalChain([accept, 'access', _25 => _25.extra, 'optionalAccess', _26 => _26.minConfirmations]), () => ( 1));
1319
+ const confirmations = _nullishCoalesce(_optionalChain([accept, 'access', _28 => _28.extra, 'optionalAccess', _29 => _29.minConfirmations]), () => ( 1));
1298
1320
  const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash, confirmations });
1299
1321
  if (receipt.status !== "success") {
1300
1322
  return { ok: false, error: "tx_reverted", detail: `Settlement tx ${txHash} reverted on-chain.` };
@@ -1430,7 +1452,7 @@ function shorten2(msg) {
1430
1452
  }
1431
1453
  function randomPermit2Nonce() {
1432
1454
  const g = globalThis.crypto;
1433
- if (!_optionalChain([g, 'optionalAccess', _27 => _27.getRandomValues])) {
1455
+ if (!_optionalChain([g, 'optionalAccess', _30 => _30.getRandomValues])) {
1434
1456
  throw new (0, _chunk6XTNI2OQcjs.UnsupportedSchemeError)(
1435
1457
  "this runtime lacks Web Crypto (globalThis.crypto.getRandomValues); the permit2 rail needs a CSPRNG nonce."
1436
1458
  );
@@ -1478,7 +1500,7 @@ async function payPermit2Evm(input) {
1478
1500
  let code;
1479
1501
  try {
1480
1502
  code = await publicClient.getCode({ address: account.address });
1481
- } catch (e17) {
1503
+ } catch (e18) {
1482
1504
  code = void 0;
1483
1505
  }
1484
1506
  if (code && code !== "0x") {
@@ -1582,7 +1604,7 @@ async function verifyAndSettlePermit2Evm(input) {
1582
1604
  let fromCode;
1583
1605
  try {
1584
1606
  fromCode = await publicClient.getCode({ address: from });
1585
- } catch (e18) {
1607
+ } catch (e19) {
1586
1608
  return { ok: false, error: "tx_not_found", detail: `Could not read code at ${from} (transient RPC) \u2014 retry.` };
1587
1609
  }
1588
1610
  if (!(fromCode && fromCode !== "0x")) {
@@ -1620,7 +1642,7 @@ async function verifyAndSettlePermit2Evm(input) {
1620
1642
  if ((bitmap >> bit & 1n) === 1n) {
1621
1643
  return { ok: false, error: "tx_already_used", detail: `Permit2 nonce ${nonce} already used or invalidated for ${from}.` };
1622
1644
  }
1623
- } catch (e19) {
1645
+ } catch (e20) {
1624
1646
  return { ok: false, error: "tx_not_found", detail: "Could not read the Permit2 nonce bitmap (transient RPC) \u2014 retry." };
1625
1647
  }
1626
1648
  const settleArgs = [
@@ -1663,7 +1685,7 @@ async function verifyAndSettlePermit2Evm(input) {
1663
1685
  );
1664
1686
  }
1665
1687
  try {
1666
- const confirmations = _nullishCoalesce(_optionalChain([accept, 'access', _28 => _28.extra, 'optionalAccess', _29 => _29.minConfirmations]), () => ( 1));
1688
+ const confirmations = _nullishCoalesce(_optionalChain([accept, 'access', _31 => _31.extra, 'optionalAccess', _32 => _32.minConfirmations]), () => ( 1));
1667
1689
  const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash, confirmations });
1668
1690
  if (receipt.status !== "success") {
1669
1691
  return { ok: false, error: "tx_reverted", detail: `Settlement tx ${txHash} reverted on-chain.` };
@@ -1766,7 +1788,7 @@ function shorten3(msg) {
1766
1788
  }
1767
1789
  function randomPermit2Nonce2() {
1768
1790
  const g = globalThis.crypto;
1769
- if (!_optionalChain([g, 'optionalAccess', _30 => _30.getRandomValues])) {
1791
+ if (!_optionalChain([g, 'optionalAccess', _33 => _33.getRandomValues])) {
1770
1792
  throw new (0, _chunk6XTNI2OQcjs.UnsupportedSchemeError)(
1771
1793
  "this runtime lacks Web Crypto (globalThis.crypto.getRandomValues); the upto rail needs a CSPRNG nonce."
1772
1794
  );
@@ -1780,7 +1802,7 @@ async function payUptoEvm(input) {
1780
1802
  let code;
1781
1803
  try {
1782
1804
  code = await publicClient.getCode({ address: account.address });
1783
- } catch (e20) {
1805
+ } catch (e21) {
1784
1806
  code = void 0;
1785
1807
  }
1786
1808
  if (code && code !== "0x") {
@@ -1788,7 +1810,7 @@ async function payUptoEvm(input) {
1788
1810
  `upto buyer rail requires an EOA signer; ${account.address} is a contract / EIP-1271 / EIP-7702-delegated account. Pay via onchain-proof.`
1789
1811
  );
1790
1812
  }
1791
- const facilitatorAddress = _optionalChain([accept, 'access', _31 => _31.extra, 'optionalAccess', _32 => _32.facilitatorAddress]);
1813
+ const facilitatorAddress = _optionalChain([accept, 'access', _34 => _34.extra, 'optionalAccess', _35 => _35.facilitatorAddress]);
1792
1814
  if (typeof facilitatorAddress !== "string" || facilitatorAddress.length === 0) {
1793
1815
  throw new (0, _chunk6XTNI2OQcjs.UnsupportedSchemeError)(
1794
1816
  `upto: the rail carries no extra.facilitatorAddress to bind into witness.facilitator \u2014 refusing to sign.`
@@ -1917,7 +1939,7 @@ async function verifyAndSettleUptoEvm(input) {
1917
1939
  let fromCode;
1918
1940
  try {
1919
1941
  fromCode = await publicClient.getCode({ address: from });
1920
- } catch (e21) {
1942
+ } catch (e22) {
1921
1943
  return { ok: false, error: "tx_not_found", detail: `Could not read code at ${from} (transient RPC) \u2014 retry.` };
1922
1944
  }
1923
1945
  if (!(fromCode && fromCode !== "0x")) {
@@ -1971,7 +1993,7 @@ async function verifyAndSettleUptoEvm(input) {
1971
1993
  if ((bitmap >> bit & 1n) === 1n) {
1972
1994
  return { ok: false, error: "tx_already_used", detail: `Permit2 nonce ${nonce} already used or invalidated for ${from}.` };
1973
1995
  }
1974
- } catch (e22) {
1996
+ } catch (e23) {
1975
1997
  return { ok: false, error: "tx_not_found", detail: "Could not read the Permit2 nonce bitmap (transient RPC) \u2014 retry." };
1976
1998
  }
1977
1999
  const settleArgs = [
@@ -2060,7 +2082,7 @@ var evmDriver = {
2060
2082
  let resolved;
2061
2083
  try {
2062
2084
  resolved = resolveChain(opts.chain, opts.rpcUrl);
2063
- } catch (e23) {
2085
+ } catch (e24) {
2064
2086
  return null;
2065
2087
  }
2066
2088
  return makeEvmNetwork(resolved);
@@ -2121,7 +2143,7 @@ function makeEvmNetwork(resolved) {
2121
2143
  let normalized;
2122
2144
  try {
2123
2145
  normalized = _viem.getAddress.call(void 0, asset);
2124
- } catch (e24) {
2146
+ } catch (e25) {
2125
2147
  return null;
2126
2148
  }
2127
2149
  for (const info of Object.values(resolved.tokens)) {
@@ -2188,7 +2210,7 @@ function makeEvmNetwork(resolved) {
2188
2210
  async estimateCost(accept) {
2189
2211
  const { decimals, symbol } = resolved.chain.nativeCurrency;
2190
2212
  if (accept.scheme === "exact" || accept.scheme === "upto") {
2191
- const m = _optionalChain([accept, 'access', _33 => _33.extra, 'optionalAccess', _34 => _34.assetTransferMethod]);
2213
+ const m = _optionalChain([accept, 'access', _36 => _36.extra, 'optionalAccess', _37 => _37.assetTransferMethod]);
2192
2214
  const permit2 = m === "permit2" || m === "permit2-exact" || m === "permit2-upto";
2193
2215
  return _chunk6XTNI2OQcjs.nativeCost.call(void 0, {
2194
2216
  symbol,
@@ -2208,7 +2230,7 @@ function makeEvmNetwork(resolved) {
2208
2230
  basis: "estimated",
2209
2231
  detail: `~${gasLimit} gas @ ${gasPrice} wei/gas`
2210
2232
  });
2211
- } catch (e25) {
2233
+ } catch (e26) {
2212
2234
  const gasPrice = 5000000000n;
2213
2235
  return _chunk6XTNI2OQcjs.nativeCost.call(void 0, {
2214
2236
  symbol,
@@ -2236,7 +2258,7 @@ function makeEvmNetwork(resolved) {
2236
2258
  functionName: "balanceOf",
2237
2259
  args: [owner]
2238
2260
  });
2239
- } catch (e26) {
2261
+ } catch (e27) {
2240
2262
  token = null;
2241
2263
  }
2242
2264
  return { token, native };
@@ -2269,7 +2291,7 @@ function makeEvmNetwork(resolved) {
2269
2291
  publicClient,
2270
2292
  chainId: resolved.chainId,
2271
2293
  network,
2272
- nativeSymbol: _nullishCoalesce(_optionalChain([resolved, 'access', _35 => _35.chain, 'access', _36 => _36.nativeCurrency, 'optionalAccess', _37 => _37.symbol]), () => ( "ETH")),
2294
+ nativeSymbol: _nullishCoalesce(_optionalChain([resolved, 'access', _38 => _38.chain, 'access', _39 => _39.nativeCurrency, 'optionalAccess', _40 => _40.symbol]), () => ( "ETH")),
2273
2295
  owner: a.account.address,
2274
2296
  from,
2275
2297
  to,
@@ -2440,7 +2462,7 @@ var loaders = {
2440
2462
  solana: async () => {
2441
2463
  let mod;
2442
2464
  try {
2443
- mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./solana-EBV6PUCU.cjs")));
2465
+ mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./solana-TIEJV742.cjs")));
2444
2466
  } catch (cause) {
2445
2467
  throw new (0, _chunk6XTNI2OQcjs.MissingDriverError)(
2446
2468
  `Solana selected, but its packages aren't installed. Run: npm install @solana/web3.js @solana/spl-token bs58`,
@@ -2464,7 +2486,7 @@ var loaders = {
2464
2486
  stellar: async () => {
2465
2487
  let mod;
2466
2488
  try {
2467
- mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./stellar-5C7FQLPS.cjs")));
2489
+ mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./stellar-5GMZJBTA.cjs")));
2468
2490
  } catch (cause) {
2469
2491
  throw new (0, _chunk6XTNI2OQcjs.MissingDriverError)(
2470
2492
  `Stellar selected, but its package isn't installed. Run: npm install @stellar/stellar-sdk`,
@@ -2476,7 +2498,7 @@ var loaders = {
2476
2498
  xrpl: async () => {
2477
2499
  let mod;
2478
2500
  try {
2479
- mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./xrpl-YS3IXPLV.cjs")));
2501
+ mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./xrpl-G2FKFXRI.cjs")));
2480
2502
  } catch (cause) {
2481
2503
  throw new (0, _chunk6XTNI2OQcjs.MissingDriverError)(
2482
2504
  `XRPL selected, but its package isn't installed. Run: npm install xrpl`,
@@ -2536,7 +2558,7 @@ var loaders = {
2536
2558
  algorand: async () => {
2537
2559
  let mod;
2538
2560
  try {
2539
- mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./algorand-W776EEM2.cjs")));
2561
+ mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./algorand-4FTTEV7X.cjs")));
2540
2562
  } catch (cause) {
2541
2563
  throw new (0, _chunk6XTNI2OQcjs.MissingDriverError)(
2542
2564
  `Algorand selected, but its package isn't installed. Run: npm install algosdk`,
@@ -2584,7 +2606,7 @@ var BUILTIN_DENOMS = {
2584
2606
  function denomOf(symbol, asset, policy) {
2585
2607
  if (asset === "native") return void 0;
2586
2608
  const norm = (v) => typeof v === "string" && v.trim() !== "" ? v.trim().toUpperCase() : void 0;
2587
- const override = _optionalChain([policy, 'optionalAccess', _38 => _38.denomFor]);
2609
+ const override = _optionalChain([policy, 'optionalAccess', _41 => _41.denomFor]);
2588
2610
  if (override && typeof override === "object") {
2589
2611
  if (asset && asset in override) {
2590
2612
  const d = norm(override[asset]);
@@ -2776,16 +2798,16 @@ var SpendLedger = (_class = class {
2776
2798
  * `append()`s every settled payment. A throwing/absent store fails SAFE to an
2777
2799
  * empty in-memory ledger — it never blocks construction (ERRORS.md: never throw).
2778
2800
  */
2779
- constructor(store) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);_class.prototype.__init4.call(this);_class.prototype.__init5.call(this);
2801
+ constructor(store) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);_class.prototype.__init4.call(this);_class.prototype.__init5.call(this);_class.prototype.__init6.call(this);_class.prototype.__init7.call(this);
2780
2802
  this.store = store;
2781
2803
  if (store) {
2782
2804
  let seed = [];
2783
2805
  try {
2784
2806
  seed = _nullishCoalesce(store.load(), () => ( []));
2785
- } catch (e27) {
2807
+ } catch (e28) {
2786
2808
  seed = [];
2787
2809
  }
2788
- for (const r of seed) this.ingest(r, _nullishCoalesce(_optionalChain([r, 'optionalAccess', _39 => _39.decimals]), () => ( 0)), _optionalChain([r, 'optionalAccess', _40 => _40.denom]));
2810
+ for (const r of seed) this.ingest(r, _nullishCoalesce(_optionalChain([r, 'optionalAccess', _42 => _42.decimals]), () => ( 0)), _optionalChain([r, 'optionalAccess', _43 => _43.denom]));
2789
2811
  }
2790
2812
  }
2791
2813
  /**
@@ -2841,13 +2863,44 @@ var SpendLedger = (_class = class {
2841
2863
  if (rec && this.store) {
2842
2864
  try {
2843
2865
  this.store.append(rec);
2844
- } catch (e28) {
2866
+ } catch (e29) {
2845
2867
  }
2846
2868
  }
2847
2869
  }
2848
2870
  /** Running total (base units) already spent on this (network, asset). */
2871
+ /*
2872
+ * ── IN-FLIGHT RESERVATIONS ─────────────────────────────────────────────────────────
2873
+ *
2874
+ * A cap is read when a quote is priced and written when the payment settles, and a whole
2875
+ * network round trip sits between the two. Without a reservation, N concurrent payments all
2876
+ * price against the same "spent so far", all pass, and all settle: an agent with a 2.50 cap
2877
+ * spends 4.00 and every individual check was correct. It is the same read-await-write shape
2878
+ * that let one proof be redeemed N times, on the other side of the wire.
2879
+ *
2880
+ * A reservation is taken SYNCHRONOUSLY by the client before it pays, counts toward every
2881
+ * total below while it is outstanding, and is released the moment the payment either settles
2882
+ * (the real record replaces it) or fails (so a refused payment never consumes the leash).
2883
+ */
2884
+ __init6() {this.pending = /* @__PURE__ */ new Map()}
2885
+ __init7() {this.pendingSeq = 0}
2886
+ /** Reserve budget for a payment about to be attempted. Returns the token to settle it with. */
2887
+ reserve(network, asset, amountBase, decimals, denom) {
2888
+ const token = `r${++this.pendingSeq}`;
2889
+ const scaled = denom ? _nullishCoalesce(scaleToDenom(amountBase, decimals), () => ( 0n)) : 0n;
2890
+ this.pending.set(token, { network, asset, amountBase, denom: _optionalChain([denom, 'optionalAccess', _44 => _44.toUpperCase, 'call', _45 => _45()]), scaled, at: Date.now() });
2891
+ return token;
2892
+ }
2893
+ /** Drop a reservation: the payment settled (its real record now counts) or it failed. */
2894
+ release(token) {
2895
+ if (token) this.pending.delete(token);
2896
+ }
2897
+ pendingFor(network, asset) {
2898
+ let sum = 0n;
2899
+ for (const p of this.pending.values()) if (p.network === network && p.asset === asset) sum += p.amountBase;
2900
+ return sum;
2901
+ }
2849
2902
  totalFor(network, asset) {
2850
- return _nullishCoalesce(_optionalChain([this, 'access', _41 => _41.buckets, 'access', _42 => _42.get, 'call', _43 => _43(keyFor(network, asset)), 'optionalAccess', _44 => _44.total]), () => ( 0n));
2903
+ return (_nullishCoalesce(_optionalChain([this, 'access', _46 => _46.buckets, 'access', _47 => _47.get, 'call', _48 => _48(keyFor(network, asset)), 'optionalAccess', _49 => _49.total]), () => ( 0n))) + this.pendingFor(network, asset);
2851
2904
  }
2852
2905
  /**
2853
2906
  * Running grand total for a DENOMINATION, scaled to {@link DENOM_PRECISION} (so
@@ -2856,11 +2909,14 @@ var SpendLedger = (_class = class {
2856
2909
  * `0n` for a denomination never spent on. Case-insensitive.
2857
2910
  */
2858
2911
  totalForDenom(denom) {
2859
- return _nullishCoalesce(this.denomTotals.get(denom.toUpperCase()), () => ( 0n));
2912
+ const key = denom.toUpperCase();
2913
+ let pending = 0n;
2914
+ for (const p of this.pending.values()) if (p.denom === key) pending += p.scaled;
2915
+ return (_nullishCoalesce(this.denomTotals.get(key), () => ( 0n))) + pending;
2860
2916
  }
2861
2917
  /** Total number of settled payments (across every chain + token). Powers `maxPayments`. */
2862
2918
  count() {
2863
- return this.records.length;
2919
+ return this.records.length + this.pending.size;
2864
2920
  }
2865
2921
  /** Mark a `warnAtFraction` threshold key as fired; returns `true` the FIRST time (so the
2866
2922
  * caller emits the `budget-threshold` event once) and `false` thereafter. Shared across
@@ -2878,6 +2934,7 @@ var SpendLedger = (_class = class {
2878
2934
  */
2879
2935
  countSince(sinceMs) {
2880
2936
  let n = 0;
2937
+ for (const p of this.pending.values()) if (p.at >= sinceMs) n += 1;
2881
2938
  for (const r of this.records) {
2882
2939
  const t = Date.parse(r.at);
2883
2940
  if (Number.isNaN(t) || t >= sinceMs) n += 1;
@@ -2893,6 +2950,9 @@ var SpendLedger = (_class = class {
2893
2950
  */
2894
2951
  totalSince(network, asset, sinceMs) {
2895
2952
  let sum = 0n;
2953
+ for (const p of this.pending.values()) {
2954
+ if (p.network === network && p.asset === asset && p.at >= sinceMs) sum += p.amountBase;
2955
+ }
2896
2956
  for (const r of this.records) {
2897
2957
  if (r.network !== network || r.asset !== asset) continue;
2898
2958
  const t = Date.parse(r.at);
@@ -2941,7 +3001,7 @@ var SpendLedger = (_class = class {
2941
3001
  denom,
2942
3002
  totalScaled: scaled.toString(),
2943
3003
  totalFormatted: _chunk6XTNI2OQcjs.formatUnits.call(void 0, scaled, DENOM_PRECISION),
2944
- count: this.records.filter((r) => _optionalChain([r, 'access', _45 => _45.denom, 'optionalAccess', _46 => _46.toUpperCase, 'call', _47 => _47()]) === denom).length
3004
+ count: this.records.filter((r) => _optionalChain([r, 'access', _50 => _50.denom, 'optionalAccess', _51 => _51.toUpperCase, 'call', _52 => _52()]) === denom).length
2945
3005
  })),
2946
3006
  records: [...this.records]
2947
3007
  };
@@ -3287,8 +3347,8 @@ var PipRailClient = (_class2 = class {
3287
3347
  // The verifiable receipt from the most recent settled fetch (null if the server emitted
3288
3348
  // none). Captured pure (no chain read) and surfaced via lastReceipt(); the resource URL is
3289
3349
  // stamped from the URL this client actually fetched (authoritative over the gate's default).
3290
- __init6() {this.lastReceiptValue = null}
3291
- constructor(opts) {;_class2.prototype.__init6.call(this);
3350
+ __init8() {this.lastReceiptValue = null}
3351
+ constructor(opts) {;_class2.prototype.__init8.call(this);
3292
3352
  this.opts = opts;
3293
3353
  this.maxRetries = Math.max(1, _nullishCoalesce(opts.maxPaymentRetries, () => ( 3)));
3294
3354
  this.retryTimeoutMs = _nullishCoalesce(opts.retryTimeoutMs, () => ( 3e4));
@@ -3303,6 +3363,32 @@ var PipRailClient = (_class2 = class {
3303
3363
  this.assertPolicyTimeOptions(opts.policy);
3304
3364
  this.assertPolicySpendControls(opts.policy);
3305
3365
  this.assertModeIsHonest(opts);
3366
+ this.sealAuthority();
3367
+ }
3368
+ /**
3369
+ * Pin the three authority accessors to THIS instance, non-writable and non-configurable.
3370
+ *
3371
+ * `paymentTools()` decides which tools a model is handed by calling `canAgentSell()` /
3372
+ * `canAgentSwap()`, which read `mode()`. Those were plain prototype methods, so any code
3373
+ * holding the client could reassign one — `client.mode = () => 'sovereign'` turned a
3374
+ * budgeted client's eight tools into sovereign's fourteen.
3375
+ *
3376
+ * A MODEL could never do that (it sends JSON tool arguments; it does not hold the object),
3377
+ * so this is not a path a model can walk. It is defence in depth for the case where a
3378
+ * client passes through code that is not the operator's own: an agent framework, a plugin,
3379
+ * some middleware that wraps or proxies objects. Authority is set once, by whoever
3380
+ * provisioned the key, and nothing downstream gets to revise it.
3381
+ */
3382
+ sealAuthority() {
3383
+ const mode = _nullishCoalesce(this.opts.mode, () => ( _chunkMZXVXC3Ccjs.DEFAULT_AGENT_MODE));
3384
+ const sovereign = mode === "sovereign";
3385
+ for (const [name, fn] of [
3386
+ ["mode", () => mode],
3387
+ ["canAgentSell", () => sovereign],
3388
+ ["canAgentSwap", () => sovereign]
3389
+ ]) {
3390
+ Object.defineProperty(this, name, { value: fn, writable: false, configurable: false, enumerable: false });
3391
+ }
3306
3392
  }
3307
3393
  /**
3308
3394
  * Fail LOUDLY at construction on a malformed amount cap — a security boundary
@@ -3432,7 +3518,7 @@ var PipRailClient = (_class2 = class {
3432
3518
  safeEmit(event) {
3433
3519
  try {
3434
3520
  this.onEvent(event);
3435
- } catch (e29) {
3521
+ } catch (e30) {
3436
3522
  }
3437
3523
  }
3438
3524
  /**
@@ -3445,7 +3531,7 @@ var PipRailClient = (_class2 = class {
3445
3531
  try {
3446
3532
  const parsed = _chunk6ZRAIQXFcjs.parseReceiptExtension.call(void 0, response);
3447
3533
  this.lastReceiptValue = parsed ? { ...parsed, resource: { url } } : null;
3448
- } catch (e30) {
3534
+ } catch (e31) {
3449
3535
  this.lastReceiptValue = null;
3450
3536
  }
3451
3537
  }
@@ -3471,17 +3557,17 @@ var PipRailClient = (_class2 = class {
3471
3557
  * {@link ReceiptVerification}).
3472
3558
  */
3473
3559
  static async verifyReceipt(receipt, opts) {
3474
- const r = _optionalChain([receipt, 'optionalAccess', _48 => _48.receipt]);
3560
+ const r = _optionalChain([receipt, 'optionalAccess', _53 => _53.receipt]);
3475
3561
  if (!r || typeof r !== "object") {
3476
3562
  return { ok: false, onChain: { payTo: "", asset: "", amount: "", payer: "" }, matchesClaims: false, ageSeconds: 0, error: "tx_not_found" };
3477
3563
  }
3478
3564
  const claimed = { payTo: _nullishCoalesce(r.payTo, () => ( "")), asset: _nullishCoalesce(r.asset, () => ( "")), amount: _nullishCoalesce(r.amount, () => ( "")), payer: _nullishCoalesce(r.payer, () => ( "")) };
3479
3565
  const ageSeconds = receiptAgeSeconds(r.verifiedAt);
3480
3566
  try {
3481
- const chain = chainSelectorForNetwork(r.network, _optionalChain([opts, 'optionalAccess', _49 => _49.rpcUrl]));
3567
+ const chain = chainSelectorForNetwork(r.network, _optionalChain([opts, 'optionalAccess', _54 => _54.rpcUrl]));
3482
3568
  const net = await resolveNetwork2({
3483
3569
  chain,
3484
- ..._optionalChain([opts, 'optionalAccess', _50 => _50.rpcUrl]) ? { rpcUrl: opts.rpcUrl } : {}
3570
+ ..._optionalChain([opts, 'optionalAccess', _55 => _55.rpcUrl]) ? { rpcUrl: opts.rpcUrl } : {}
3485
3571
  });
3486
3572
  const accept = {
3487
3573
  scheme: "onchain-proof",
@@ -3508,7 +3594,7 @@ var PipRailClient = (_class2 = class {
3508
3594
  const onChain = { payTo: oc.payTo, asset: oc.asset, amount: oc.amount, payer: oc.payer };
3509
3595
  const matchesClaims = sameAddress(oc.payer, r.payer);
3510
3596
  return { ok: true, onChain, matchesClaims, ageSeconds };
3511
- } catch (e31) {
3597
+ } catch (e32) {
3512
3598
  return { ok: false, onChain: claimed, matchesClaims: false, ageSeconds, error: "tx_not_found" };
3513
3599
  }
3514
3600
  }
@@ -3528,7 +3614,7 @@ var PipRailClient = (_class2 = class {
3528
3614
  * no chain libs. The JWS format defers to R3 (`{ ok:false, reason:'jws-not-loaded' }`).
3529
3615
  */
3530
3616
  static async verifyAttestation(receipt) {
3531
- const att = _optionalChain([receipt, 'optionalAccess', _51 => _51.attestation]);
3617
+ const att = _optionalChain([receipt, 'optionalAccess', _56 => _56.attestation]);
3532
3618
  if (!att || typeof att !== "object" || typeof att.signature !== "string") {
3533
3619
  return { ok: false, reason: "no-attestation" };
3534
3620
  }
@@ -3539,7 +3625,7 @@ var PipRailClient = (_class2 = class {
3539
3625
  if (!r || typeof r !== "object") return { ok: false, reason: "no-receipt" };
3540
3626
  const payload = _nullishCoalesce(att.payload, () => ( {}));
3541
3627
  const network = typeof payload.network === "string" ? payload.network : r.network;
3542
- const resourceUrl = typeof payload.resourceUrl === "string" ? payload.resourceUrl : _nullishCoalesce(_optionalChain([receipt, 'access', _52 => _52.resource, 'optionalAccess', _53 => _53.url]), () => ( ""));
3628
+ const resourceUrl = typeof payload.resourceUrl === "string" ? payload.resourceUrl : _nullishCoalesce(_optionalChain([receipt, 'access', _57 => _57.resource, 'optionalAccess', _58 => _58.url]), () => ( ""));
3543
3629
  const payer = typeof payload.payer === "string" ? payload.payer : r.payer;
3544
3630
  const issuedAt = typeof payload.issuedAt === "number" ? payload.issuedAt : receiptIssuedAtSeconds(r.verifiedAt);
3545
3631
  const transaction = typeof payload.transaction === "string" ? payload.transaction : _nullishCoalesce(r.transaction, () => ( ""));
@@ -3554,7 +3640,7 @@ var PipRailClient = (_class2 = class {
3554
3640
  transaction,
3555
3641
  signature: att.signature
3556
3642
  });
3557
- } catch (e32) {
3643
+ } catch (e33) {
3558
3644
  return { ok: false, reason: "verify-failed" };
3559
3645
  }
3560
3646
  }
@@ -3585,7 +3671,7 @@ var PipRailClient = (_class2 = class {
3585
3671
  * as-is) or a plain object (serialised as JSON).
3586
3672
  */
3587
3673
  post(url, body, init) {
3588
- const headers = new Headers(_optionalChain([init, 'optionalAccess', _54 => _54.headers]));
3674
+ const headers = new Headers(_optionalChain([init, 'optionalAccess', _59 => _59.headers]));
3589
3675
  let payload;
3590
3676
  if (body === void 0 || body === null) {
3591
3677
  payload = void 0;
@@ -3616,7 +3702,7 @@ var PipRailClient = (_class2 = class {
3616
3702
  * "0.05 USDC on Base, within budget → pay it." No funds move.
3617
3703
  */
3618
3704
  async quote(url, init) {
3619
- const res = await fetch(url, { ..._nullishCoalesce(init, () => ( {})), method: _nullishCoalesce(_optionalChain([init, 'optionalAccess', _55 => _55.method]), () => ( "GET")) });
3705
+ const res = await fetch(url, { ..._nullishCoalesce(init, () => ( {})), method: _nullishCoalesce(_optionalChain([init, 'optionalAccess', _60 => _60.method]), () => ( "GET")) });
3620
3706
  if (res.status !== 402) return null;
3621
3707
  const { quote } = await this.resolveChallenge(url, res, this.resolveSchemes());
3622
3708
  return quote;
@@ -3635,7 +3721,7 @@ var PipRailClient = (_class2 = class {
3635
3721
  * on Tron, where a USD₮ transfer can cost real TRX.
3636
3722
  */
3637
3723
  async estimateCost(url, init) {
3638
- const res = await fetch(url, { ..._nullishCoalesce(init, () => ( {})), method: _nullishCoalesce(_optionalChain([init, 'optionalAccess', _56 => _56.method]), () => ( "GET")) });
3724
+ const res = await fetch(url, { ..._nullishCoalesce(init, () => ( {})), method: _nullishCoalesce(_optionalChain([init, 'optionalAccess', _61 => _61.method]), () => ( "GET")) });
3639
3725
  if (res.status !== 402) return null;
3640
3726
  try {
3641
3727
  const { net, accept, quote } = await this.resolveChallenge(url, res, this.resolveSchemes());
@@ -3672,7 +3758,7 @@ var PipRailClient = (_class2 = class {
3672
3758
  "mode: 'supervised' needs an `onBeforePay` hook \u2014 it is the only thing that can pause a payment for a human, so without it this client would pay without asking anyone, which is exactly what 'supervised' promises not to do. Add onBeforePay, or use 'budgeted' if the policy is meant to be the consent. (@piprail/mcp wires this for you from PIPRAIL_MODE.)"
3673
3759
  );
3674
3760
  }
3675
- if (mode === "sovereign" && _optionalChain([opts, 'access', _57 => _57.swapPolicy, 'optionalAccess', _58 => _58.maxPerSwap]) === void 0) {
3761
+ if (mode === "sovereign" && _optionalChain([opts, 'access', _62 => _62.swapPolicy, 'optionalAccess', _63 => _63.maxPerSwap]) === void 0) {
3676
3762
  throw new TypeError(
3677
3763
  "mode: 'sovereign' needs `swapPolicy.maxPerSwap` \u2014 it hands a model the swap tools, and your payment caps do NOT bound a swap (they count payments; a swap is not one), so without a ceiling nothing limits what one swap may spend. Set a ceiling, e.g. swapPolicy: { maxPerSwap: '25.00' }. Selling needs no ceiling: it takes money rather than spending it."
3678
3764
  );
@@ -3741,7 +3827,7 @@ var PipRailClient = (_class2 = class {
3741
3827
  asset = t.asset;
3742
3828
  decimals = t.decimals;
3743
3829
  resolvedSymbol = t.symbol;
3744
- } catch (e33) {
3830
+ } catch (e34) {
3745
3831
  out.push({ symbol, asset: null, decimals: null, known: false, amount: null, amountFormatted: null });
3746
3832
  continue;
3747
3833
  }
@@ -3802,8 +3888,8 @@ var PipRailClient = (_class2 = class {
3802
3888
  return {
3803
3889
  session: {
3804
3890
  start,
3805
- expiresAt: _optionalChain([view, 'optionalAccess', _59 => _59.expiresAt]) != null ? new Date(view.expiresAt).toISOString() : null,
3806
- secondsRemaining: _nullishCoalesce(_optionalChain([view, 'optionalAccess', _60 => _60.secondsRemaining]), () => ( null))
3891
+ expiresAt: _optionalChain([view, 'optionalAccess', _64 => _64.expiresAt]) != null ? new Date(view.expiresAt).toISOString() : null,
3892
+ secondsRemaining: _nullishCoalesce(_optionalChain([view, 'optionalAccess', _65 => _65.secondsRemaining]), () => ( null))
3807
3893
  },
3808
3894
  byAsset: this.remaining(),
3809
3895
  byDenom: this.denomRemaining(),
@@ -3818,7 +3904,7 @@ var PipRailClient = (_class2 = class {
3818
3904
  * price-converted figure (tokens grouped as one unit, each 1:1).
3819
3905
  */
3820
3906
  denomRemaining() {
3821
- const caps = _optionalChain([this, 'access', _61 => _61.opts, 'access', _62 => _62.policy, 'optionalAccess', _63 => _63.maxTotalPerDenom]);
3907
+ const caps = _optionalChain([this, 'access', _66 => _66.opts, 'access', _67 => _67.policy, 'optionalAccess', _68 => _68.maxTotalPerDenom]);
3822
3908
  if (!caps) return [];
3823
3909
  return Object.entries(caps).map(([rawDenom, capStr]) => {
3824
3910
  const denom = rawDenom.toUpperCase();
@@ -3841,11 +3927,11 @@ var PipRailClient = (_class2 = class {
3841
3927
  const policy = this.opts.policy;
3842
3928
  const settled = this.ledger.count();
3843
3929
  const out = { settled };
3844
- if (_optionalChain([policy, 'optionalAccess', _64 => _64.maxPayments]) !== void 0) {
3930
+ if (_optionalChain([policy, 'optionalAccess', _69 => _69.maxPayments]) !== void 0) {
3845
3931
  out.lifetimeCap = policy.maxPayments;
3846
3932
  out.lifetimeRemaining = Math.max(0, policy.maxPayments - settled);
3847
3933
  }
3848
- if (_optionalChain([policy, 'optionalAccess', _65 => _65.maxPaymentsPerWindow]) !== void 0 && policy.windowSeconds !== void 0) {
3934
+ if (_optionalChain([policy, 'optionalAccess', _70 => _70.maxPaymentsPerWindow]) !== void 0 && policy.windowSeconds !== void 0) {
3849
3935
  const windowSettled = this.ledger.countSince(Date.now() - policy.windowSeconds * 1e3);
3850
3936
  out.windowCap = policy.maxPaymentsPerWindow;
3851
3937
  out.windowSettled = windowSettled;
@@ -3861,7 +3947,7 @@ var PipRailClient = (_class2 = class {
3861
3947
  * never throws, never sums across tokens (no price oracle). PROCESS-SCOPED.
3862
3948
  */
3863
3949
  remaining() {
3864
- const maxTotal = _optionalChain([this, 'access', _66 => _66.opts, 'access', _67 => _67.policy, 'optionalAccess', _68 => _68.maxTotal]);
3950
+ const maxTotal = _optionalChain([this, 'access', _71 => _71.opts, 'access', _72 => _72.policy, 'optionalAccess', _73 => _73.maxTotal]);
3865
3951
  return this.ledger.assetBuckets().map((b) => {
3866
3952
  const base2 = {
3867
3953
  network: b.network,
@@ -3913,7 +3999,7 @@ var PipRailClient = (_class2 = class {
3913
3999
  * the plan yourself. No funds move.
3914
4000
  */
3915
4001
  async planPayment(url, init) {
3916
- const res = await fetch(url, { ..._nullishCoalesce(init, () => ( {})), method: _nullishCoalesce(_optionalChain([init, 'optionalAccess', _69 => _69.method]), () => ( "GET")) });
4002
+ const res = await fetch(url, { ..._nullishCoalesce(init, () => ( {})), method: _nullishCoalesce(_optionalChain([init, 'optionalAccess', _74 => _74.method]), () => ( "GET")) });
3917
4003
  if (res.status !== 402) return null;
3918
4004
  const challenge = await _chunk6ZRAIQXFcjs.parseChallenge.call(void 0, res);
3919
4005
  if (!challenge) {
@@ -3960,7 +4046,7 @@ var PipRailClient = (_class2 = class {
3960
4046
  async quoteSwap(req) {
3961
4047
  const slippageBps = _chunkMZXVXC3Ccjs.resolveSlippageBps.call(void 0, req.slippageBps);
3962
4048
  const sp = this.opts.swapPolicy;
3963
- if (_optionalChain([sp, 'optionalAccess', _70 => _70.maxSlippageBps]) !== void 0 && slippageBps > sp.maxSlippageBps) {
4049
+ if (_optionalChain([sp, 'optionalAccess', _75 => _75.maxSlippageBps]) !== void 0 && slippageBps > sp.maxSlippageBps) {
3964
4050
  throw new (0, _chunk6XTNI2OQcjs.PaymentDeclinedError)(
3965
4051
  `slippageBps ${slippageBps} exceeds this agent's swapPolicy.maxSlippageBps of ${sp.maxSlippageBps}.`,
3966
4052
  { reasonCode: "POLICY" }
@@ -3975,12 +4061,12 @@ var PipRailClient = (_class2 = class {
3975
4061
  from = net.resolveToken(req.from);
3976
4062
  to = net.resolveToken(req.to);
3977
4063
  wantAmount = _chunk6XTNI2OQcjs.parseUnits.call(void 0, req.wantAmount, to.decimals);
3978
- } catch (e34) {
4064
+ } catch (e35) {
3979
4065
  return null;
3980
4066
  }
3981
4067
  try {
3982
4068
  return await net.quoteSwap({ from, to, wantAmount, slippageBps, wallet });
3983
- } catch (e35) {
4069
+ } catch (e36) {
3984
4070
  return null;
3985
4071
  }
3986
4072
  }
@@ -4018,7 +4104,7 @@ var PipRailClient = (_class2 = class {
4018
4104
  );
4019
4105
  }
4020
4106
  const sp = this.opts.swapPolicy;
4021
- if (_optionalChain([sp, 'optionalAccess', _71 => _71.maxPerSwap]) !== void 0) {
4107
+ if (_optionalChain([sp, 'optionalAccess', _76 => _76.maxPerSwap]) !== void 0) {
4022
4108
  const cap = _chunk6XTNI2OQcjs.parseUnits.call(void 0, sp.maxPerSwap, quote.from.decimals);
4023
4109
  if (BigInt(quote.maxSpend) > cap) {
4024
4110
  throw new (0, _chunk6XTNI2OQcjs.PaymentDeclinedError)(
@@ -4027,7 +4113,7 @@ var PipRailClient = (_class2 = class {
4027
4113
  );
4028
4114
  }
4029
4115
  }
4030
- if (_optionalChain([sp, 'optionalAccess', _72 => _72.allowTo, 'optionalAccess', _73 => _73.length])) {
4116
+ if (_optionalChain([sp, 'optionalAccess', _77 => _77.allowTo, 'optionalAccess', _78 => _78.length])) {
4031
4117
  const want = quote.to.symbol;
4032
4118
  if (!sp.allowTo.some((t) => t.toUpperCase() === want.toUpperCase())) {
4033
4119
  throw new (0, _chunk6XTNI2OQcjs.PaymentDeclinedError)(
@@ -4215,7 +4301,7 @@ var PipRailClient = (_class2 = class {
4215
4301
  * streams throw `NonReplayableBodyError`.
4216
4302
  */
4217
4303
  async fetch(url, init) {
4218
- const body = _optionalChain([init, 'optionalAccess', _74 => _74.body]);
4304
+ const body = _optionalChain([init, 'optionalAccess', _79 => _79.body]);
4219
4305
  if (body !== void 0 && body !== null && !isReplayableBodyInit(body)) {
4220
4306
  throw new (0, _chunk6XTNI2OQcjs.NonReplayableBodyError)(
4221
4307
  "fetch(): init.body is not replayable. Pass a string, FormData, URLSearchParams, ArrayBuffer, or Blob \u2014 not a ReadableStream."
@@ -4223,7 +4309,7 @@ var PipRailClient = (_class2 = class {
4223
4309
  }
4224
4310
  const firstResponse = await fetch(url, init);
4225
4311
  if (firstResponse.status !== 402) return firstResponse;
4226
- const schemes = this.resolveSchemes(_optionalChain([init, 'optionalAccess', _75 => _75.schemes]));
4312
+ const schemes = this.resolveSchemes(_optionalChain([init, 'optionalAccess', _80 => _80.schemes]));
4227
4313
  const resolved = await this.resolveChallenge(url, firstResponse, schemes);
4228
4314
  const { net, wallet, challenge } = resolved;
4229
4315
  if (!wallet) {
@@ -4233,7 +4319,7 @@ var PipRailClient = (_class2 = class {
4233
4319
  }
4234
4320
  let accept = resolved.accept;
4235
4321
  let quote = resolved.quote;
4236
- const autoRoute = _nullishCoalesce(_nullishCoalesce(_optionalChain([init, 'optionalAccess', _76 => _76.autoRoute]), () => ( this.opts.autoRoute)), () => ( false));
4322
+ const autoRoute = _nullishCoalesce(_nullishCoalesce(_optionalChain([init, 'optionalAccess', _81 => _81.autoRoute]), () => ( this.opts.autoRoute)), () => ( false));
4237
4323
  if (autoRoute) {
4238
4324
  const plan = await this.planFromChallenge(net, wallet, challenge, url, schemes);
4239
4325
  if (!plan.best) {
@@ -4245,22 +4331,35 @@ var PipRailClient = (_class2 = class {
4245
4331
  quote = plan.best.quote;
4246
4332
  }
4247
4333
  this.safeEmit({ kind: "payment-required", challenge, accept });
4248
- await this.authorize(quote);
4334
+ const reservation = await this.authorize(quote);
4249
4335
  if (accept.scheme === "upto") {
4250
- return this.payUptoRail(net, wallet, accept, url, init, quote);
4336
+ try {
4337
+ return await this.payUptoRail(net, wallet, accept, url, init, quote, reservation);
4338
+ } finally {
4339
+ this.ledger.release(reservation);
4340
+ }
4251
4341
  }
4252
4342
  if (accept.scheme === "exact") {
4253
- return this.payExactRail(net, wallet, accept, url, init, quote, challenge.x402Version);
4343
+ try {
4344
+ return await this.payExactRail(net, wallet, accept, url, init, quote, challenge.x402Version, reservation);
4345
+ } finally {
4346
+ this.ledger.release(reservation);
4347
+ }
4254
4348
  }
4255
4349
  if (accept.scheme !== "onchain-proof") {
4350
+ this.ledger.release(reservation);
4256
4351
  throw new (0, _chunk6XTNI2OQcjs.UnsupportedSchemeError)(
4257
4352
  `internal: unrouted accept scheme '${accept.scheme}' reached the onchain-proof pay path.`
4258
4353
  );
4259
4354
  }
4260
- const { ref, confirmed } = await this.payAndConfirm(net, wallet, accept);
4261
- const response = await this.retryWithProof(url, init, accept, ref, confirmed);
4262
- this.recordSpend(quote, ref);
4263
- return response;
4355
+ try {
4356
+ const { ref, confirmed } = await this.payAndConfirm(net, wallet, accept);
4357
+ const response = await this.retryWithProof(url, init, accept, ref, confirmed);
4358
+ this.recordSpend(quote, ref, void 0, reservation);
4359
+ return response;
4360
+ } finally {
4361
+ this.ledger.release(reservation);
4362
+ }
4264
4363
  }
4265
4364
  /* ------------------------- internals ------------------------- */
4266
4365
  /**
@@ -4375,7 +4474,7 @@ var PipRailClient = (_class2 = class {
4375
4474
  out.push(
4376
4475
  ...challenge.accepts.filter(
4377
4476
  (a) => a.scheme === "upto" && this.supportsNetwork(net, a.network) && typeof net.payUpto === "function" && a.asset !== "native" && // native is not upto-payable either (same reason as exact)
4378
- net.describeAsset(a.asset) != null && typeof _optionalChain([a, 'access', _77 => _77.extra, 'optionalAccess', _78 => _78.facilitatorAddress]) === "string" && a.extra.facilitatorAddress.length > 0 && Number.isInteger(a.maxTimeoutSeconds) && a.maxTimeoutSeconds > 0
4477
+ net.describeAsset(a.asset) != null && typeof _optionalChain([a, 'access', _82 => _82.extra, 'optionalAccess', _83 => _83.facilitatorAddress]) === "string" && a.extra.facilitatorAddress.length > 0 && Number.isInteger(a.maxTimeoutSeconds) && a.maxTimeoutSeconds > 0
4379
4478
  )
4380
4479
  );
4381
4480
  }
@@ -4449,9 +4548,11 @@ var PipRailClient = (_class2 = class {
4449
4548
  shortfall.token = _chunk6XTNI2OQcjs.formatUnits.call(void 0, amount - bal.token, quote.decimals);
4450
4549
  }
4451
4550
  } else if (isNative) {
4452
- if (nativeKnown && bal.native < amount + fee) {
4551
+ const spendable = _nullishCoalesce(bal.token, () => ( bal.native));
4552
+ const spendableKnown = spendable != null;
4553
+ if (spendableKnown && spendable < amount + fee) {
4453
4554
  blockers.push("INSUFFICIENT_TOKEN");
4454
- shortfall.token = _chunk6XTNI2OQcjs.formatUnits.call(void 0, amount + fee - bal.native, quote.decimals);
4555
+ shortfall.token = _chunk6XTNI2OQcjs.formatUnits.call(void 0, amount + fee - spendable, quote.decimals);
4455
4556
  }
4456
4557
  } else {
4457
4558
  if (tokenKnown && bal.token < amount) {
@@ -4486,7 +4587,7 @@ var PipRailClient = (_class2 = class {
4486
4587
  // why a domain-only rail is payable and gasless. The default is PER FAMILY: a Solana rail
4487
4588
  // naming nothing means `svm`, never `eip3009`.
4488
4589
  ...accept.scheme === "exact" ? {
4489
- method: _optionalChain([accept, 'access', _79 => _79.extra, 'optionalAccess', _80 => _80.assetTransferMethod]) ? _chunk6ZRAIQXFcjs.exactTransferMethod.call(void 0, accept) : `${_chunk6ZRAIQXFcjs.exactTransferMethod.call(void 0, accept, net.family)} (default)`
4590
+ method: _optionalChain([accept, 'access', _84 => _84.extra, 'optionalAccess', _85 => _85.assetTransferMethod]) ? _chunk6ZRAIQXFcjs.exactTransferMethod.call(void 0, accept) : `${_chunk6ZRAIQXFcjs.exactTransferMethod.call(void 0, accept, net.family)} (default)`
4490
4591
  } : {},
4491
4592
  ...accept.scheme === "upto" ? { method: "permit2-upto" } : {},
4492
4593
  state,
@@ -4516,7 +4617,7 @@ var PipRailClient = (_class2 = class {
4516
4617
  }
4517
4618
  const amountBase = BigInt(accept.amount);
4518
4619
  const described = net.describeAsset(accept.asset);
4519
- const decimals = _nullishCoalesce(_optionalChain([described, 'optionalAccess', _81 => _81.decimals]), () => ( _optionalChain([accept, 'access', _82 => _82.extra, 'optionalAccess', _83 => _83.decimals])));
4620
+ const decimals = _nullishCoalesce(_optionalChain([described, 'optionalAccess', _86 => _86.decimals]), () => ( _optionalChain([accept, 'access', _87 => _87.extra, 'optionalAccess', _88 => _88.decimals])));
4520
4621
  if (typeof decimals !== "number" || !Number.isInteger(decimals) || decimals < 0) {
4521
4622
  throw new (0, _chunk6XTNI2OQcjs.InvalidEnvelopeError)(
4522
4623
  `challenge for ${accept.asset} on ${accept.network} states no valid decimals and the SDK doesn't recognise the token \u2014 refusing to price it.`
@@ -4527,7 +4628,7 @@ var PipRailClient = (_class2 = class {
4527
4628
  `challenge for ${accept.asset} on ${accept.network} states ${decimals} decimals (> ${_chunk6XTNI2OQcjs.MAX_DECIMALS}) \u2014 refusing to price it (no real token is that deep).`
4528
4629
  );
4529
4630
  }
4530
- const symbol = _nullishCoalesce(_optionalChain([described, 'optionalAccess', _84 => _84.symbol]), () => ( _optionalChain([accept, 'access', _85 => _85.extra, 'optionalAccess', _86 => _86.symbol])));
4631
+ const symbol = _nullishCoalesce(_optionalChain([described, 'optionalAccess', _89 => _89.symbol]), () => ( _optionalChain([accept, 'access', _90 => _90.extra, 'optionalAccess', _91 => _91.symbol])));
4531
4632
  const amountFormatted = _chunk6XTNI2OQcjs.formatUnits.call(void 0, amountBase, decimals);
4532
4633
  const intent = {
4533
4634
  host: hostOf(url),
@@ -4569,7 +4670,7 @@ var PipRailClient = (_class2 = class {
4569
4670
  this.ledger.totalFor(accept.network, accept.asset),
4570
4671
  ctx
4571
4672
  );
4572
- const serverSymbol = _optionalChain([accept, 'access', _87 => _87.extra, 'optionalAccess', _88 => _88.symbol]);
4673
+ const serverSymbol = _optionalChain([accept, 'access', _92 => _92.extra, 'optionalAccess', _93 => _93.symbol]);
4573
4674
  const symbolMismatch = intent.recognized && !!serverSymbol && !!symbol && serverSymbol.toUpperCase() !== symbol.toUpperCase();
4574
4675
  return {
4575
4676
  url,
@@ -4603,18 +4704,28 @@ var PipRailClient = (_class2 = class {
4603
4704
  quote
4604
4705
  });
4605
4706
  }
4707
+ const reservation = this.ledger.reserve(
4708
+ quote.network,
4709
+ quote.asset,
4710
+ BigInt(quote.amount),
4711
+ quote.decimals,
4712
+ denomOf(quote.symbol, quote.asset, this.opts.policy)
4713
+ );
4606
4714
  const hook = this.opts.onBeforePay;
4607
- if (!hook) return;
4715
+ if (!hook) return reservation;
4608
4716
  let approved;
4609
4717
  try {
4610
4718
  approved = await hook(quote);
4611
4719
  } catch (err) {
4720
+ this.ledger.release(reservation);
4612
4721
  this.refuse("onBeforePay threw \u2014 refusing to pay.", { reasonCode: "APPROVAL", quote, cause: err });
4613
4722
  }
4614
4723
  if (!approved) {
4724
+ this.ledger.release(reservation);
4615
4725
  const reason = `onBeforePay declined ${quote.amountFormatted} ${_nullishCoalesce(quote.symbol, () => ( ""))}`.trimEnd() + ` on ${quote.network}.`;
4616
4726
  this.refuse(reason, { reasonCode: "APPROVAL", quote });
4617
4727
  }
4728
+ return reservation;
4618
4729
  }
4619
4730
  /**
4620
4731
  * Refuse a payment BEFORE any send: emit BOTH the legacy `payment-failed` (so existing
@@ -4653,7 +4764,7 @@ var PipRailClient = (_class2 = class {
4653
4764
  * spend (POL-1). So the cap-bearing `amountBase` is the MAX; the clamped actual is surfaced
4654
4765
  * separately on `settledBase`/`settledFormatted` for transparency (it equals the receipt's
4655
4766
  * amount). When absent (onchain-proof/exact) this is byte-identical to before. */
4656
- recordSpend(quote, ref, settledAmountBase) {
4767
+ recordSpend(quote, ref, settledAmountBase, reservation) {
4657
4768
  const denom = denomOf(quote.symbol, quote.asset, this.opts.policy);
4658
4769
  const amountBase = quote.amount;
4659
4770
  const amountFormatted = quote.amountFormatted;
@@ -4666,7 +4777,7 @@ var PipRailClient = (_class2 = class {
4666
4777
  const shown = claimed < max ? claimed : max;
4667
4778
  settledBase = shown.toString();
4668
4779
  settledFormatted = _chunk6XTNI2OQcjs.formatUnits.call(void 0, shown, quote.decimals);
4669
- } catch (e36) {
4780
+ } catch (e37) {
4670
4781
  }
4671
4782
  }
4672
4783
  const record = {
@@ -4684,11 +4795,12 @@ var PipRailClient = (_class2 = class {
4684
4795
  at: (/* @__PURE__ */ new Date()).toISOString()
4685
4796
  };
4686
4797
  this.ledger.record(record, quote.decimals, denom);
4798
+ this.ledger.release(reservation);
4687
4799
  const budget = this.budget();
4688
4800
  if (this.opts.onSpend) {
4689
4801
  try {
4690
4802
  this.opts.onSpend(record, budget);
4691
- } catch (e37) {
4803
+ } catch (e38) {
4692
4804
  }
4693
4805
  }
4694
4806
  this.emitThresholds(budget);
@@ -4701,7 +4813,7 @@ var PipRailClient = (_class2 = class {
4701
4813
  * `warnAtFraction` is set. Reads the just-computed {@link SessionBudget}; isolated (safeEmit).
4702
4814
  */
4703
4815
  emitThresholds(budget) {
4704
- const frac = _optionalChain([this, 'access', _89 => _89.opts, 'access', _90 => _90.policy, 'optionalAccess', _91 => _91.warnAtFraction]);
4816
+ const frac = _optionalChain([this, 'access', _94 => _94.opts, 'access', _95 => _95.policy, 'optionalAccess', _96 => _96.warnAtFraction]);
4705
4817
  if (frac === void 0) return;
4706
4818
  const fire = (scope, label, spentFormatted, capFormatted, fraction) => {
4707
4819
  if (fraction < frac) return;
@@ -4725,7 +4837,7 @@ var PipRailClient = (_class2 = class {
4725
4837
  fire("denom", d.denom, d.spentFormatted, d.capFormatted, d.fraction);
4726
4838
  }
4727
4839
  const policy = this.opts.policy;
4728
- if (_optionalChain([policy, 'optionalAccess', _92 => _92.windowTotal]) !== void 0 && policy.windowSeconds !== void 0) {
4840
+ if (_optionalChain([policy, 'optionalAccess', _97 => _97.windowTotal]) !== void 0 && policy.windowSeconds !== void 0) {
4729
4841
  const since = Date.now() - policy.windowSeconds * 1e3;
4730
4842
  for (const r of budget.byAsset) {
4731
4843
  const cap = _chunk6XTNI2OQcjs.floorUnits.call(void 0, policy.windowTotal, r.decimals);
@@ -4763,7 +4875,7 @@ var PipRailClient = (_class2 = class {
4763
4875
  const ref = await net.send(wallet, accept);
4764
4876
  this.safeEmit({ kind: "payment-broadcast", ref });
4765
4877
  try {
4766
- const { height } = await net.confirm(ref, _nullishCoalesce(_optionalChain([accept, 'access', _93 => _93.extra, 'optionalAccess', _94 => _94.minConfirmations]), () => ( 1)));
4878
+ const { height } = await net.confirm(ref, _nullishCoalesce(_optionalChain([accept, 'access', _98 => _98.extra, 'optionalAccess', _99 => _99.minConfirmations]), () => ( 1)));
4767
4879
  this.safeEmit({
4768
4880
  kind: "payment-confirmed",
4769
4881
  ref,
@@ -4783,9 +4895,9 @@ var PipRailClient = (_class2 = class {
4783
4895
  const signature = {
4784
4896
  x402Version: 2,
4785
4897
  accepted: accept,
4786
- payload: { nonce: _optionalChain([accept, 'access', _95 => _95.extra, 'optionalAccess', _96 => _96.nonce]), txHash: ref }
4898
+ payload: { nonce: _optionalChain([accept, 'access', _100 => _100.extra, 'optionalAccess', _101 => _101.nonce]), txHash: ref }
4787
4899
  };
4788
- const headers = new Headers(_optionalChain([originalInit, 'optionalAccess', _97 => _97.headers]));
4900
+ const headers = new Headers(_optionalChain([originalInit, 'optionalAccess', _102 => _102.headers]));
4789
4901
  headers.set(_chunk6ZRAIQXFcjs.HEADER_SIGNATURE, _chunk6ZRAIQXFcjs.buildSignatureHeader.call(void 0, signature));
4790
4902
  let lastResponse = null;
4791
4903
  let lastReason = null;
@@ -4800,7 +4912,7 @@ var PipRailClient = (_class2 = class {
4800
4912
  () => timeoutController.abort(),
4801
4913
  this.retryTimeoutMs
4802
4914
  );
4803
- const signal = _optionalChain([originalInit, 'optionalAccess', _98 => _98.signal]) && typeof AbortSignal.any === "function" ? AbortSignal.any([timeoutController.signal, originalInit.signal]) : timeoutController.signal;
4915
+ const signal = _optionalChain([originalInit, 'optionalAccess', _103 => _103.signal]) && typeof AbortSignal.any === "function" ? AbortSignal.any([timeoutController.signal, originalInit.signal]) : timeoutController.signal;
4804
4916
  try {
4805
4917
  lastResponse = await fetch(url, {
4806
4918
  ..._nullishCoalesce(originalInit, () => ( {})),
@@ -4855,15 +4967,15 @@ var PipRailClient = (_class2 = class {
4855
4967
  * • a 200 whose SettleResponse says `success:false` → a rejection, NEVER a spend;
4856
4968
  * • the spend is recorded EXACTLY ONCE, on an affirmative settlement only.
4857
4969
  */
4858
- async payExactRail(net, wallet, accept, url, init, quote, x402Version = 2) {
4970
+ async payExactRail(net, wallet, accept, url, init, quote, x402Version = 2, reservation) {
4859
4971
  if (!net.payExact) {
4860
4972
  throw new (0, _chunk6XTNI2OQcjs.UnsupportedSchemeError)(
4861
4973
  `the ${net.family} family can't pay a standard 'exact' rail (supported on EVM, Solana, Algorand, Aptos + NEAR today).`
4862
4974
  );
4863
4975
  }
4864
- throwIfAborted(_optionalChain([init, 'optionalAccess', _99 => _99.signal]));
4976
+ throwIfAborted(_optionalChain([init, 'optionalAccess', _104 => _104.signal]));
4865
4977
  const { payload, accepted, payerFrom, nonce } = await net.payExact(wallet, accept);
4866
- const headers = new Headers(_optionalChain([init, 'optionalAccess', _100 => _100.headers]));
4978
+ const headers = new Headers(_optionalChain([init, 'optionalAccess', _105 => _105.headers]));
4867
4979
  if (x402Version === 1) {
4868
4980
  headers.set(
4869
4981
  _chunk6ZRAIQXFcjs.HEADER_SIGNATURE_V1,
@@ -4891,12 +5003,12 @@ var PipRailClient = (_class2 = class {
4891
5003
  if (Date.now() >= deadline) break;
4892
5004
  await new Promise((r) => setTimeout(r, Math.min(2e3, 400 * 2 ** (attempt - 1))));
4893
5005
  }
4894
- throwIfAborted(_optionalChain([init, 'optionalAccess', _101 => _101.signal]));
5006
+ throwIfAborted(_optionalChain([init, 'optionalAccess', _106 => _106.signal]));
4895
5007
  const budget = Math.min(this.retryTimeoutMs, deadline - Date.now());
4896
5008
  if (budget <= 0) break;
4897
5009
  const timeoutController = new AbortController();
4898
5010
  const timeoutId = setTimeout(() => timeoutController.abort(), budget);
4899
- const signal = _optionalChain([init, 'optionalAccess', _102 => _102.signal]) && typeof AbortSignal.any === "function" ? AbortSignal.any([timeoutController.signal, init.signal]) : timeoutController.signal;
5011
+ const signal = _optionalChain([init, 'optionalAccess', _107 => _107.signal]) && typeof AbortSignal.any === "function" ? AbortSignal.any([timeoutController.signal, init.signal]) : timeoutController.signal;
4900
5012
  let response;
4901
5013
  try {
4902
5014
  response = await fetch(url, { ..._nullishCoalesce(init, () => ( {})), headers, signal });
@@ -4918,8 +5030,8 @@ var PipRailClient = (_class2 = class {
4918
5030
  const receipt = _chunk6ZRAIQXFcjs.parseReceipt.call(void 0, response);
4919
5031
  this.captureReceipt(response, url);
4920
5032
  this.safeEmit({ kind: "payment-settled", receipt, ...settle ? { settle } : {} });
4921
- const ref = _optionalChain([settle, 'optionalAccess', _103 => _103.transaction]) || _optionalChain([receipt, 'optionalAccess', _104 => _104.transaction]) || `${net.family === "evm" ? "eip3009" : net.family}-nonce:${nonce}`;
4922
- this.recordSpend(quote, ref);
5033
+ const ref = _optionalChain([settle, 'optionalAccess', _108 => _108.transaction]) || _optionalChain([receipt, 'optionalAccess', _109 => _109.transaction]) || `${net.family === "evm" ? "eip3009" : net.family}-nonce:${nonce}`;
5034
+ this.recordSpend(quote, ref, void 0, reservation);
4923
5035
  return response;
4924
5036
  }
4925
5037
  if (response.status >= 500) {
@@ -4950,15 +5062,15 @@ var PipRailClient = (_class2 = class {
4950
5062
  * `settle.amount` FAILS SAFE to the MAX (over-counts, never under-counts). The buyer SIGNS, the
4951
5063
  * merchant self-settles — the buyer never broadcasts.
4952
5064
  */
4953
- async payUptoRail(net, wallet, accept, url, init, quote) {
5065
+ async payUptoRail(net, wallet, accept, url, init, quote, reservation) {
4954
5066
  if (!net.payUpto) {
4955
5067
  throw new (0, _chunk6XTNI2OQcjs.UnsupportedSchemeError)(
4956
5068
  `the ${net.family} family can't pay a standard 'upto' rail (EVM-Permit2 only today).`
4957
5069
  );
4958
5070
  }
4959
- throwIfAborted(_optionalChain([init, 'optionalAccess', _105 => _105.signal]));
5071
+ throwIfAborted(_optionalChain([init, 'optionalAccess', _110 => _110.signal]));
4960
5072
  const { payload, accepted, payerFrom, nonce } = await net.payUpto(wallet, accept);
4961
- const headers = new Headers(_optionalChain([init, 'optionalAccess', _106 => _106.headers]));
5073
+ const headers = new Headers(_optionalChain([init, 'optionalAccess', _111 => _111.headers]));
4962
5074
  headers.set(_chunk6ZRAIQXFcjs.HEADER_SIGNATURE, _chunk6ZRAIQXFcjs.buildUptoSignatureHeader.call(void 0, { accepted, payload }));
4963
5075
  const rejectDefinitive = (why2) => {
4964
5076
  this.safeEmit({ kind: "payment-failed", reason: `upto: facilitator rejected nonce=${nonce} (${why2})`, code: why2 });
@@ -4975,12 +5087,12 @@ var PipRailClient = (_class2 = class {
4975
5087
  if (Date.now() >= deadline) break;
4976
5088
  await new Promise((r) => setTimeout(r, Math.min(2e3, 400 * 2 ** (attempt - 1))));
4977
5089
  }
4978
- throwIfAborted(_optionalChain([init, 'optionalAccess', _107 => _107.signal]));
5090
+ throwIfAborted(_optionalChain([init, 'optionalAccess', _112 => _112.signal]));
4979
5091
  const budget = Math.min(this.retryTimeoutMs, deadline - Date.now());
4980
5092
  if (budget <= 0) break;
4981
5093
  const timeoutController = new AbortController();
4982
5094
  const timeoutId = setTimeout(() => timeoutController.abort(), budget);
4983
- const signal = _optionalChain([init, 'optionalAccess', _108 => _108.signal]) && typeof AbortSignal.any === "function" ? AbortSignal.any([timeoutController.signal, init.signal]) : timeoutController.signal;
5095
+ const signal = _optionalChain([init, 'optionalAccess', _113 => _113.signal]) && typeof AbortSignal.any === "function" ? AbortSignal.any([timeoutController.signal, init.signal]) : timeoutController.signal;
4984
5096
  let response;
4985
5097
  try {
4986
5098
  response = await fetch(url, { ..._nullishCoalesce(init, () => ( {})), headers, signal });
@@ -5002,9 +5114,9 @@ var PipRailClient = (_class2 = class {
5002
5114
  const receipt = _chunk6ZRAIQXFcjs.parseReceipt.call(void 0, response);
5003
5115
  this.captureReceipt(response, url);
5004
5116
  this.safeEmit({ kind: "payment-settled", receipt, ...settle ? { settle } : {} });
5005
- const ref = _optionalChain([settle, 'optionalAccess', _109 => _109.transaction]) || _optionalChain([receipt, 'optionalAccess', _110 => _110.transaction]) || `upto-nonce:${nonce}`;
5006
- const settledAmount = _nullishCoalesce(_optionalChain([settle, 'optionalAccess', _111 => _111.amount]), () => ( _optionalChain([receipt, 'optionalAccess', _112 => _112.amount])));
5007
- this.recordSpend(quote, ref, settledAmount);
5117
+ const ref = _optionalChain([settle, 'optionalAccess', _114 => _114.transaction]) || _optionalChain([receipt, 'optionalAccess', _115 => _115.transaction]) || `upto-nonce:${nonce}`;
5118
+ const settledAmount = _nullishCoalesce(_optionalChain([settle, 'optionalAccess', _116 => _116.amount]), () => ( _optionalChain([receipt, 'optionalAccess', _117 => _117.amount])));
5119
+ this.recordSpend(quote, ref, settledAmount, reservation);
5008
5120
  return response;
5009
5121
  }
5010
5122
  if (response.status >= 500) {
@@ -5028,14 +5140,14 @@ var PipRailClient = (_class2 = class {
5028
5140
  }
5029
5141
  }, _class2);
5030
5142
  function throwIfAborted(signal) {
5031
- if (_optionalChain([signal, 'optionalAccess', _113 => _113.aborted])) {
5143
+ if (_optionalChain([signal, 'optionalAccess', _118 => _118.aborted])) {
5032
5144
  throw _nullishCoalesce(signal.reason, () => ( new DOMException("This operation was aborted.", "AbortError")));
5033
5145
  }
5034
5146
  }
5035
5147
  function safeBig(s) {
5036
5148
  try {
5037
5149
  return BigInt(s);
5038
- } catch (e38) {
5150
+ } catch (e39) {
5039
5151
  return 0n;
5040
5152
  }
5041
5153
  }
@@ -5098,10 +5210,10 @@ function buildFundingHint(options, chainLabel) {
5098
5210
  return `Couldn't fully read your wallet on ${chainLabel} (RPC throttled) \u2014 retry; you may already be able to pay ${target.quote.amountFormatted} ${sym}.`;
5099
5211
  }
5100
5212
  const parts = [];
5101
- if (target.blockers.includes("INSUFFICIENT_TOKEN") && _optionalChain([target, 'access', _114 => _114.shortfall, 'optionalAccess', _115 => _115.token])) {
5213
+ if (target.blockers.includes("INSUFFICIENT_TOKEN") && _optionalChain([target, 'access', _119 => _119.shortfall, 'optionalAccess', _120 => _120.token])) {
5102
5214
  parts.push(`top up ${target.shortfall.token} ${sym}`);
5103
5215
  }
5104
- if (target.blockers.includes("INSUFFICIENT_GAS") && _optionalChain([target, 'access', _116 => _116.shortfall, 'optionalAccess', _117 => _117.native])) {
5216
+ if (target.blockers.includes("INSUFFICIENT_GAS") && _optionalChain([target, 'access', _121 => _121.shortfall, 'optionalAccess', _122 => _122.native])) {
5105
5217
  parts.push(`add ~${target.shortfall.native} ${target.cost.feeSymbol} for gas`);
5106
5218
  }
5107
5219
  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}.`;
@@ -5115,7 +5227,7 @@ async function planAcross(clients, url, init) {
5115
5227
  const status = best ? "ready" : options.some((o) => o.state === "unknown") ? "unknown" : "blocked";
5116
5228
  return {
5117
5229
  url,
5118
- network: _nullishCoalesce(_optionalChain([best, 'optionalAccess', _118 => _118.accept, 'access', _119 => _119.network]), () => ( live[0].network)),
5230
+ network: _nullishCoalesce(_optionalChain([best, 'optionalAccess', _123 => _123.accept, 'access', _124 => _124.network]), () => ( live[0].network)),
5119
5231
  status,
5120
5232
  payable: best !== null,
5121
5233
  best,
@@ -5163,7 +5275,7 @@ function reasonCodeForPolicy(code) {
5163
5275
  function hostOf(url) {
5164
5276
  try {
5165
5277
  return new URL(url).hostname;
5166
- } catch (e39) {
5278
+ } catch (e40) {
5167
5279
  return url;
5168
5280
  }
5169
5281
  }
@@ -5180,8 +5292,8 @@ function isReplayableBodyInit(value) {
5180
5292
  async function readInvalidReason(response) {
5181
5293
  try {
5182
5294
  const body = await response.clone().json();
5183
- const ext = _optionalChain([body, 'optionalAccess', _120 => _120.extensions]);
5184
- const piprail = _optionalChain([ext, 'optionalAccess', _121 => _121.piprail]);
5295
+ const ext = _optionalChain([body, 'optionalAccess', _125 => _125.extensions]);
5296
+ const piprail = _optionalChain([ext, 'optionalAccess', _126 => _126.piprail]);
5185
5297
  if (piprail && typeof piprail.code === "string") {
5186
5298
  return {
5187
5299
  error: piprail.code,
@@ -5200,10 +5312,10 @@ async function readInvalidReason(response) {
5200
5312
  detail: typeof body.invalidMessage === "string" ? body.invalidMessage : ""
5201
5313
  };
5202
5314
  }
5203
- } catch (e40) {
5315
+ } catch (e41) {
5204
5316
  }
5205
5317
  const settle = _chunk6ZRAIQXFcjs.parseSettleResponse.call(void 0, response);
5206
- if (_optionalChain([settle, 'optionalAccess', _122 => _122.errorReason])) return { error: settle.errorReason, detail: "" };
5318
+ if (_optionalChain([settle, 'optionalAccess', _127 => _127.errorReason])) return { error: settle.errorReason, detail: "" };
5207
5319
  return null;
5208
5320
  }
5209
5321
  var EVM_PRESET_FOR_CHAINID = {
@@ -5301,7 +5413,7 @@ var MultiChainPayer = class _MultiChainPayer {
5301
5413
  ledger,
5302
5414
  ...opts.policy ? { policy: opts.policy } : {},
5303
5415
  ...opts.schemes ? { schemes: opts.schemes } : {},
5304
- ..._optionalChain([opts, 'access', _123 => _123.rpcUrls, 'optionalAccess', _124 => _124[chain]]) ? { rpcUrl: opts.rpcUrls[chain] } : {},
5416
+ ..._optionalChain([opts, 'access', _128 => _128.rpcUrls, 'optionalAccess', _129 => _129[chain]]) ? { rpcUrl: opts.rpcUrls[chain] } : {},
5305
5417
  ...opts.onBeforePay ? { onBeforePay: opts.onBeforePay } : {},
5306
5418
  ...opts.onEvent ? { onEvent: opts.onEvent } : {},
5307
5419
  ...opts.maxPaymentRetries != null ? { maxPaymentRetries: opts.maxPaymentRetries } : {},
@@ -5359,7 +5471,7 @@ var MultiChainPayer = class _MultiChainPayer {
5359
5471
  * {@link PipRailClient.post}.
5360
5472
  */
5361
5473
  post(url, body, init) {
5362
- const headers = new Headers(_optionalChain([init, 'optionalAccess', _125 => _125.headers]));
5474
+ const headers = new Headers(_optionalChain([init, 'optionalAccess', _130 => _130.headers]));
5363
5475
  let payload;
5364
5476
  if (body === void 0 || body === null) {
5365
5477
  payload = void 0;
@@ -5503,7 +5615,7 @@ var MultiChainPayer = class _MultiChainPayer {
5503
5615
  try {
5504
5616
  return await c.swap(quote);
5505
5617
  } catch (err) {
5506
- if (err instanceof _chunk6XTNI2OQcjs.WrongChainError || _optionalChain([err, 'optionalAccess', _126 => _126.name]) === "UnsupportedNetworkError") {
5618
+ if (err instanceof _chunk6XTNI2OQcjs.WrongChainError || _optionalChain([err, 'optionalAccess', _131 => _131.name]) === "UnsupportedNetworkError") {
5507
5619
  firstRefusal ??= err;
5508
5620
  continue;
5509
5621
  }
@@ -5574,14 +5686,14 @@ function buildSelfDescription(input) {
5574
5686
  }
5575
5687
  function buildEndpointInfo(input) {
5576
5688
  const d = input.descriptor;
5577
- const summary = _nullishCoalesce(_optionalChain([d, 'optionalAccess', _127 => _127.summary]), () => ( input.description));
5578
- const hasInput = _optionalChain([d, 'optionalAccess', _128 => _128.queryParams]) && Object.keys(d.queryParams).length > 0;
5689
+ const summary = _nullishCoalesce(_optionalChain([d, 'optionalAccess', _132 => _132.summary]), () => ( input.description));
5690
+ const hasInput = _optionalChain([d, 'optionalAccess', _133 => _133.queryParams]) && Object.keys(d.queryParams).length > 0;
5579
5691
  const endpoint = {
5580
5692
  ...summary ? { summary } : {},
5581
- ..._optionalChain([d, 'optionalAccess', _129 => _129.method]) ? { method: d.method.toUpperCase() } : {},
5693
+ ..._optionalChain([d, 'optionalAccess', _134 => _134.method]) ? { method: d.method.toUpperCase() } : {},
5582
5694
  ...input.mimeType ? { mimeType: input.mimeType } : {},
5583
5695
  ...hasInput ? { input: d.queryParams } : {},
5584
- ..._optionalChain([d, 'optionalAccess', _130 => _130.output]) ? { output: d.output } : {}
5696
+ ..._optionalChain([d, 'optionalAccess', _135 => _135.output]) ? { output: d.output } : {}
5585
5697
  };
5586
5698
  return Object.keys(endpoint).length > 0 ? endpoint : void 0;
5587
5699
  }
@@ -5632,16 +5744,16 @@ function formatSpendReport(summary) {
5632
5744
  function describeChallenge(challenge) {
5633
5745
  const generic = `${BRAND.name} x402 payment endpoint. Pay with @piprail/sdk (${BRAND.sdkInstall}). Docs: ${BRAND.home}.`;
5634
5746
  try {
5635
- const accepts = Array.isArray(_optionalChain([challenge, 'optionalAccess', _131 => _131.accepts])) ? challenge.accepts : [];
5747
+ const accepts = Array.isArray(_optionalChain([challenge, 'optionalAccess', _136 => _136.accepts])) ? challenge.accepts : [];
5636
5748
  const first = accepts[0];
5637
5749
  if (!first) return generic;
5638
5750
  const extra = _nullishCoalesce(first.extra, () => ( {}));
5639
5751
  const amount = _nullishCoalesce(extra.amountFormatted, () => ( first.amount));
5640
5752
  const token = _nullishCoalesce(extra.symbol, () => ( first.asset));
5641
- const hasExact = accepts.some((a) => _optionalChain([a, 'optionalAccess', _132 => _132.scheme]) === "exact");
5753
+ const hasExact = accepts.some((a) => _optionalChain([a, 'optionalAccess', _137 => _137.scheme]) === "exact");
5642
5754
  const standard = hasExact ? "; or any standard x402 client (an exact rail is offered)" : "";
5643
5755
  return `${BRAND.name} x402 payment endpoint \u2014 pay ${amount} ${token} on ${first.network} to ${first.payTo}. Programmatic: ${BRAND.sdkInstall} then client.fetch(url)${standard}. Docs: ${BRAND.home}.`;
5644
- } catch (e41) {
5756
+ } catch (e42) {
5645
5757
  return generic;
5646
5758
  }
5647
5759
  }
@@ -5884,12 +5996,12 @@ function buildBazaarExtension(descriptor = {}) {
5884
5996
  function pathOf(url) {
5885
5997
  try {
5886
5998
  return new URL(url).pathname || "/";
5887
- } catch (e42) {
5999
+ } catch (e43) {
5888
6000
  return url.startsWith("/") ? url : `/${url}`;
5889
6001
  }
5890
6002
  }
5891
6003
  function buildOpenApi(input) {
5892
- assertResourceList(_optionalChain([input, 'optionalAccess', _133 => _133.resources]), "buildOpenApi");
6004
+ assertResourceList(_optionalChain([input, 'optionalAccess', _138 => _138.resources]), "buildOpenApi");
5893
6005
  const paths = {};
5894
6006
  for (const r of input.resources) {
5895
6007
  const path = pathOf(r.url);
@@ -5919,7 +6031,7 @@ function buildOpenApi(input) {
5919
6031
  };
5920
6032
  }
5921
6033
  function buildWellKnownX402(input) {
5922
- assertResourceList(_optionalChain([input, 'optionalAccess', _134 => _134.resources]), "buildWellKnownX402");
6034
+ assertResourceList(_optionalChain([input, 'optionalAccess', _139 => _139.resources]), "buildWellKnownX402");
5923
6035
  return {
5924
6036
  version: 1,
5925
6037
  resources: input.resources.map((r) => r.url),
@@ -5939,7 +6051,7 @@ function assertResourceList(resources, fn) {
5939
6051
  });
5940
6052
  }
5941
6053
  function buildWellKnownX402Manifest(input) {
5942
- assertResourceList(_optionalChain([input, 'optionalAccess', _135 => _135.resources]), "buildWellKnownX402Manifest");
6054
+ assertResourceList(_optionalChain([input, 'optionalAccess', _140 => _140.resources]), "buildWellKnownX402Manifest");
5943
6055
  const lastUpdated = typeof input.lastUpdated === "number" && Number.isFinite(input.lastUpdated) ? input.lastUpdated : Math.floor(Date.now() / 1e3);
5944
6056
  return {
5945
6057
  x402Version: 2,
@@ -6018,7 +6130,7 @@ function renderLandingPage(sd) {
6018
6130
  }
6019
6131
 
6020
6132
  // src/facilitator.ts
6021
- async function fetchFacilitatorFeePayer(url, network, timeoutMs = 8e3) {
6133
+ async function fetchFacilitatorFeePayer(url, network, timeoutMs = 15e3) {
6022
6134
  const base2 = url.replace(/\/+$/, "");
6023
6135
  const ctrl = new AbortController();
6024
6136
  const timer = setTimeout(() => ctrl.abort(), timeoutMs);
@@ -6026,28 +6138,28 @@ async function fetchFacilitatorFeePayer(url, network, timeoutMs = 8e3) {
6026
6138
  const res = await fetch(`${base2}/supported`, { signal: ctrl.signal });
6027
6139
  if (!res.ok) return void 0;
6028
6140
  const body = await res.json();
6029
- const kinds = Array.isArray(_optionalChain([body, 'optionalAccess', _136 => _136.kinds])) ? body.kinds : [];
6141
+ const kinds = Array.isArray(_optionalChain([body, 'optionalAccess', _141 => _141.kinds])) ? body.kinds : [];
6030
6142
  const want = _chunkMZAJQYM3cjs.normalizeNetwork.call(void 0, network);
6031
- const kind = kinds.find((k) => _optionalChain([k, 'optionalAccess', _137 => _137.scheme]) === "exact" && _chunkMZAJQYM3cjs.normalizeNetwork.call(void 0, String(_nullishCoalesce(_optionalChain([k, 'optionalAccess', _138 => _138.network]), () => ( "")))) === want);
6032
- const fp = _optionalChain([kind, 'optionalAccess', _139 => _139.extra, 'optionalAccess', _140 => _140.feePayer]);
6143
+ const kind = kinds.find((k) => _optionalChain([k, 'optionalAccess', _142 => _142.scheme]) === "exact" && _chunkMZAJQYM3cjs.normalizeNetwork.call(void 0, String(_nullishCoalesce(_optionalChain([k, 'optionalAccess', _143 => _143.network]), () => ( "")))) === want);
6144
+ const fp = _optionalChain([kind, 'optionalAccess', _144 => _144.extra, 'optionalAccess', _145 => _145.feePayer]);
6033
6145
  return typeof fp === "string" ? fp : void 0;
6034
- } catch (e43) {
6146
+ } catch (e44) {
6035
6147
  return void 0;
6036
6148
  } finally {
6037
6149
  clearTimeout(timer);
6038
6150
  }
6039
6151
  }
6040
6152
  function parseFacilitatorSupported(body) {
6041
- const kinds = _optionalChain([body, 'optionalAccess', _141 => _141.kinds]);
6153
+ const kinds = _optionalChain([body, 'optionalAccess', _146 => _146.kinds]);
6042
6154
  if (!Array.isArray(kinds)) return [];
6043
6155
  const out = [];
6044
6156
  for (const k of kinds) {
6045
6157
  if (!k || typeof k !== "object") continue;
6046
6158
  const o = k;
6047
6159
  if (typeof o.scheme !== "string" || typeof o.network !== "string") continue;
6048
- const fp = _optionalChain([o, 'access', _142 => _142.extra, 'optionalAccess', _143 => _143.feePayer]);
6160
+ const fp = _optionalChain([o, 'access', _147 => _147.extra, 'optionalAccess', _148 => _148.feePayer]);
6049
6161
  const ver = o.x402Version;
6050
- const method = _optionalChain([o, 'access', _144 => _144.extra, 'optionalAccess', _145 => _145.assetTransferMethod]);
6162
+ const method = _optionalChain([o, 'access', _149 => _149.extra, 'optionalAccess', _150 => _150.assetTransferMethod]);
6051
6163
  out.push({
6052
6164
  scheme: o.scheme,
6053
6165
  network: o.network,
@@ -6058,7 +6170,7 @@ function parseFacilitatorSupported(body) {
6058
6170
  }
6059
6171
  return out;
6060
6172
  }
6061
- async function facilitatorCoverage(url, timeoutMs = 8e3) {
6173
+ async function facilitatorCoverage(url, timeoutMs = 15e3) {
6062
6174
  const base2 = url.replace(/\/+$/, "");
6063
6175
  const ctrl = new AbortController();
6064
6176
  const timer = setTimeout(() => ctrl.abort(), timeoutMs);
@@ -6066,7 +6178,7 @@ async function facilitatorCoverage(url, timeoutMs = 8e3) {
6066
6178
  const res = await fetch(`${base2}/supported`, { signal: ctrl.signal });
6067
6179
  if (!res.ok) return [];
6068
6180
  return parseFacilitatorSupported(await res.json());
6069
- } catch (e44) {
6181
+ } catch (e45) {
6070
6182
  return [];
6071
6183
  } finally {
6072
6184
  clearTimeout(timer);
@@ -6095,7 +6207,7 @@ async function post(url, body, headers) {
6095
6207
  let json = null;
6096
6208
  try {
6097
6209
  json = await res.json();
6098
- } catch (e45) {
6210
+ } catch (e46) {
6099
6211
  }
6100
6212
  return { status: res.status, json };
6101
6213
  }
@@ -6109,9 +6221,9 @@ async function settleViaFacilitator(input) {
6109
6221
  ...v2 ? {
6110
6222
  accepted: input.paymentRequirements,
6111
6223
  resource: {
6112
- url: _optionalChain([input, 'access', _146 => _146.resource, 'optionalAccess', _147 => _147.url]) || "https://piprail.com/x402/resource",
6113
- description: _optionalChain([input, 'access', _148 => _148.resource, 'optionalAccess', _149 => _149.description]) || "Paid resource",
6114
- mimeType: _optionalChain([input, 'access', _150 => _150.resource, 'optionalAccess', _151 => _151.mimeType]) || "application/json"
6224
+ url: _optionalChain([input, 'access', _151 => _151.resource, 'optionalAccess', _152 => _152.url]) || "https://piprail.com/x402/resource",
6225
+ description: _optionalChain([input, 'access', _153 => _153.resource, 'optionalAccess', _154 => _154.description]) || "Paid resource",
6226
+ mimeType: _optionalChain([input, 'access', _155 => _155.resource, 'optionalAccess', _156 => _156.mimeType]) || "application/json"
6115
6227
  }
6116
6228
  } : {}
6117
6229
  };
@@ -6558,7 +6670,7 @@ function createPaymentGate(options) {
6558
6670
  attestWarned = true;
6559
6671
  try {
6560
6672
  console.warn(`[piprail] receipts.attest ${reason}; emitting an unsigned Tier-1 receipt instead.`);
6561
- } catch (e46) {
6673
+ } catch (e47) {
6562
6674
  }
6563
6675
  }
6564
6676
  let resolved;
@@ -6580,6 +6692,11 @@ function createPaymentGate(options) {
6580
6692
  net.assertValidPayTo(payTo);
6581
6693
  const { asset, decimals, symbol } = net.resolveToken(a.token);
6582
6694
  const amountBase = _chunk6XTNI2OQcjs.parseUnits.call(void 0, a.amount, decimals);
6695
+ if (amountBase <= 0n) {
6696
+ throw new (0, _chunk6XTNI2OQcjs.InvalidConfigError)(
6697
+ `requirePayment: amount must be greater than zero, got "${a.amount}" on ${net.network}. A gate that charges nothing gates nothing; omit the gate instead.`
6698
+ );
6699
+ }
6583
6700
  const spec = { net, asset, decimals, symbol, amountBase, amountFormatted: a.amount, payTo };
6584
6701
  if (exactOption) {
6585
6702
  const outcome = await resolveExactRail(net, asset);
@@ -6602,7 +6719,7 @@ function createPaymentGate(options) {
6602
6719
  if (exactOption && !specs.some((s) => s.exact)) {
6603
6720
  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.";
6604
6721
  if (exactOption.settle === "keyless") {
6605
- if (typeof process === "undefined" || !_optionalChain([process, 'optionalAccess', _152 => _152.env, 'optionalAccess', _153 => _153.PIPRAIL_NO_HINTS])) {
6722
+ if (typeof process === "undefined" || !_optionalChain([process, 'optionalAccess', _157 => _157.env, 'optionalAccess', _158 => _158.PIPRAIL_NO_HINTS])) {
6606
6723
  console.warn(
6607
6724
  `[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.)`
6608
6725
  );
@@ -6630,7 +6747,7 @@ function createPaymentGate(options) {
6630
6747
  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).`
6631
6748
  };
6632
6749
  }
6633
- if (typeof process === "undefined" || _optionalChain([process, 'optionalAccess', _154 => _154.env, 'optionalAccess', _155 => _155.NODE_ENV]) !== "production" && !_optionalChain([process, 'optionalAccess', _156 => _156.env, 'optionalAccess', _157 => _157.PIPRAIL_NO_HINTS])) {
6750
+ if (typeof process === "undefined" || _optionalChain([process, 'optionalAccess', _159 => _159.env, 'optionalAccess', _160 => _160.NODE_ENV]) !== "production" && !_optionalChain([process, 'optionalAccess', _161 => _161.env, 'optionalAccess', _162 => _162.PIPRAIL_NO_HINTS])) {
6634
6751
  console.warn(
6635
6752
  `[piprail] exact: keyless rail on ${net.network} auto-settles via ${picked.url} (zero-config; pin \`exact.settle.facilitator\` in production).`
6636
6753
  );
@@ -6698,6 +6815,11 @@ function createPaymentGate(options) {
6698
6815
  "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)."
6699
6816
  );
6700
6817
  }
6818
+ if (typeof options.releaseUsed === "function" && !(hasIsUsed && hasMarkUsed)) {
6819
+ throw new Error(
6820
+ "requirePayment/createPaymentGate: `releaseUsed` needs `isUsed` + `markUsed` too \u2014 it releases a reservation a CUSTOM store made, so without one it would never fire. Provide all three, or none (the built-in store already releases on failure)."
6821
+ );
6822
+ }
6701
6823
  const hasCustomStore = hasIsUsed && hasMarkUsed;
6702
6824
  const localUsed = /* @__PURE__ */ new Map();
6703
6825
  const replayWindowMs = maxTimeoutSeconds * 1e3;
@@ -6707,23 +6829,35 @@ function createPaymentGate(options) {
6707
6829
  localUsed.delete(key);
6708
6830
  }
6709
6831
  }
6832
+ const localKey = (ref) => ref.startsWith("pid:") ? ref : ref.toLowerCase();
6710
6833
  async function claimTx(ref) {
6711
- if (hasCustomStore) {
6712
- return options.isUsed ? Boolean(await options.isUsed(ref)) : false;
6713
- }
6714
- const key = ref.startsWith("pid:") ? ref : ref.toLowerCase();
6834
+ const key = localKey(ref);
6715
6835
  const now = Date.now();
6716
6836
  pruneUsed(now);
6717
6837
  if (localUsed.has(key)) return true;
6718
6838
  localUsed.set(key, now + replayWindowMs);
6839
+ if (hasCustomStore) {
6840
+ try {
6841
+ if (options.isUsed && await options.isUsed(ref)) return true;
6842
+ } catch (err) {
6843
+ localUsed.delete(key);
6844
+ throw err;
6845
+ }
6846
+ }
6719
6847
  return false;
6720
6848
  }
6721
6849
  async function settleTx(ref, ok) {
6722
- if (hasCustomStore) {
6723
- if (ok && options.markUsed) await options.markUsed(ref);
6850
+ if (!ok) {
6851
+ localUsed.delete(localKey(ref));
6852
+ if (hasCustomStore && options.releaseUsed) {
6853
+ try {
6854
+ await options.releaseUsed(ref);
6855
+ } catch (e48) {
6856
+ }
6857
+ }
6724
6858
  return;
6725
6859
  }
6726
- if (!ok) localUsed.delete(ref.startsWith("pid:") ? ref : ref.toLowerCase());
6860
+ if (hasCustomStore && options.markUsed) await options.markUsed(ref);
6727
6861
  }
6728
6862
  function buildAccept(s, nonce) {
6729
6863
  return {
@@ -6774,7 +6908,7 @@ function createPaymentGate(options) {
6774
6908
  extra: {
6775
6909
  assetTransferMethod: "permit2-upto",
6776
6910
  // facilitatorAddress comes from rail.extra; the spread below carries it (+ name/version).
6777
- facilitatorAddress: _nullishCoalesce(_optionalChain([rail, 'access', _158 => _158.extra, 'optionalAccess', _159 => _159.facilitatorAddress]), () => ( "")),
6911
+ facilitatorAddress: _nullishCoalesce(_optionalChain([rail, 'access', _163 => _163.extra, 'optionalAccess', _164 => _164.facilitatorAddress]), () => ( "")),
6778
6912
  minConfirmations,
6779
6913
  decimals: s.decimals,
6780
6914
  amountFormatted: s.amountFormatted,
@@ -6809,7 +6943,7 @@ function createPaymentGate(options) {
6809
6943
  ...endpointInfo ? { endpoint: endpointInfo } : {},
6810
6944
  ...receiptsOn ? { verifiableReceipts: true } : {}
6811
6945
  });
6812
- const rejectionExt = _nullishCoalesce(_optionalChain([opts, 'optionalAccess', _160 => _160.extensions]), () => ( {}));
6946
+ const rejectionExt = _nullishCoalesce(_optionalChain([opts, 'optionalAccess', _165 => _165.extensions]), () => ( {}));
6813
6947
  const rejectionPiprail = _nullishCoalesce(rejectionExt.piprail, () => ( {}));
6814
6948
  const bodyPiprail = { ..._nullishCoalesce(selfDescribe, () => ( {})), ...rejectionPiprail };
6815
6949
  const bodyExtensions = {
@@ -6831,7 +6965,7 @@ function createPaymentGate(options) {
6831
6965
  ...options.mimeType ? { mimeType: options.mimeType } : {}
6832
6966
  },
6833
6967
  accepts,
6834
- ..._optionalChain([opts, 'optionalAccess', _161 => _161.error]) ? { error: opts.error } : {},
6968
+ ..._optionalChain([opts, 'optionalAccess', _166 => _166.error]) ? { error: opts.error } : {},
6835
6969
  ...Object.keys(bodyExtensions).length > 0 ? { extensions: bodyExtensions } : {}
6836
6970
  };
6837
6971
  const headerChallenge = {
@@ -6863,7 +6997,7 @@ function createPaymentGate(options) {
6863
6997
  let amountFormatted = receipt.amount;
6864
6998
  try {
6865
6999
  amountFormatted = _chunk6XTNI2OQcjs.formatUnits.call(void 0, BigInt(receipt.amount), spec.decimals);
6866
- } catch (e47) {
7000
+ } catch (e49) {
6867
7001
  }
6868
7002
  return {
6869
7003
  ...receipt,
@@ -6877,7 +7011,7 @@ function createPaymentGate(options) {
6877
7011
  if (!options.onPaidError) return;
6878
7012
  try {
6879
7013
  options.onPaidError(error, receipt);
6880
- } catch (e48) {
7014
+ } catch (e50) {
6881
7015
  }
6882
7016
  }
6883
7017
  function fireOnPaid(receipt) {
@@ -6917,7 +7051,7 @@ function createPaymentGate(options) {
6917
7051
  ...attestation ? { attestation } : {}
6918
7052
  });
6919
7053
  return { kind: "paid", receipt: stamped, receiptHeader: _chunk6ZRAIQXFcjs.buildReceiptHeader.call(void 0, stamped, extensions) };
6920
- } catch (e49) {
7054
+ } catch (e51) {
6921
7055
  return { kind: "paid", receipt, receiptHeader: _chunk6ZRAIQXFcjs.buildReceiptHeader.call(void 0, receipt) };
6922
7056
  }
6923
7057
  }
@@ -6942,7 +7076,7 @@ function createPaymentGate(options) {
6942
7076
  // §5.3: the signed message carries the empty string for a suppressed tx, never omitted.
6943
7077
  transaction: receiptIncludeTxHash ? stamped.transaction : ""
6944
7078
  });
6945
- } catch (e50) {
7079
+ } catch (e52) {
6946
7080
  warnAttestDegrade("signing failed");
6947
7081
  return void 0;
6948
7082
  }
@@ -6951,7 +7085,7 @@ function createPaymentGate(options) {
6951
7085
  if (!options.onFailedError) return;
6952
7086
  try {
6953
7087
  options.onFailedError(error, failure);
6954
- } catch (e51) {
7088
+ } catch (e53) {
6955
7089
  }
6956
7090
  }
6957
7091
  function fireOnFailed(failure) {
@@ -7071,28 +7205,28 @@ function createPaymentGate(options) {
7071
7205
  nonce = [exact.payload.transaction, exact.payload.senderAuth].map((t) => {
7072
7206
  try {
7073
7207
  return Buffer.from(t, "base64").toString("base64");
7074
- } catch (e52) {
7208
+ } catch (e54) {
7075
7209
  return t;
7076
7210
  }
7077
7211
  }).join("|");
7078
7212
  } else if ("transaction" in exact.payload) {
7079
7213
  try {
7080
7214
  nonce = Buffer.from(exact.payload.transaction, "base64").toString("base64");
7081
- } catch (e53) {
7215
+ } catch (e55) {
7082
7216
  nonce = exact.payload.transaction;
7083
7217
  }
7084
7218
  } else if ("paymentGroup" in exact.payload) {
7085
7219
  nonce = exact.payload.paymentGroup.map((t) => {
7086
7220
  try {
7087
7221
  return Buffer.from(t, "base64").toString("base64");
7088
- } catch (e54) {
7222
+ } catch (e56) {
7089
7223
  return t;
7090
7224
  }
7091
7225
  }).join("|");
7092
7226
  } else if ("signedDelegateAction" in exact.payload) {
7093
7227
  try {
7094
7228
  nonce = Buffer.from(exact.payload.signedDelegateAction, "base64").toString("base64");
7095
- } catch (e55) {
7229
+ } catch (e57) {
7096
7230
  nonce = exact.payload.signedDelegateAction;
7097
7231
  }
7098
7232
  } else if ("signedTxBlob" in exact.payload) {
@@ -7114,9 +7248,9 @@ function createPaymentGate(options) {
7114
7248
  if (mode.kind === "self") {
7115
7249
  result = await spec.net.settleExactSelf({ relayer: mode.relayer, payload: exact.payload, accept });
7116
7250
  } else {
7117
- const ftMethod = _optionalChain([accept, 'access', _162 => _162.extra, 'optionalAccess', _163 => _163.assetTransferMethod]);
7251
+ const ftMethod = _optionalChain([accept, 'access', _167 => _167.extra, 'optionalAccess', _168 => _168.assetTransferMethod]);
7118
7252
  const needsFeePayer = ftMethod === "svm" || ftMethod === "algorand" || ftMethod === "aptos" || ftMethod === "near";
7119
- if (needsFeePayer && !_optionalChain([accept, 'access', _164 => _164.extra, 'optionalAccess', _165 => _165.feePayer])) {
7253
+ if (needsFeePayer && !_optionalChain([accept, 'access', _169 => _169.extra, 'optionalAccess', _170 => _170.feePayer])) {
7120
7254
  throw new (0, _chunk6XTNI2OQcjs.SettlementError)(
7121
7255
  `exact settle: the ${ftMethod} facilitator rail is missing extra.feePayer (the gas sponsor) \u2014 cannot settle.`
7122
7256
  );
@@ -7137,7 +7271,7 @@ function createPaymentGate(options) {
7137
7271
  amount: accept.amount,
7138
7272
  payTo: accept.payTo,
7139
7273
  maxTimeoutSeconds: accept.maxTimeoutSeconds,
7140
- extra: needsFeePayer ? { feePayer: accept.extra.feePayer } : { name: _nullishCoalesce(_optionalChain([accept, 'access', _166 => _166.extra, 'optionalAccess', _167 => _167.name]), () => ( "")), version: _nullishCoalesce(_optionalChain([accept, 'access', _168 => _168.extra, 'optionalAccess', _169 => _169.version]), () => ( "")) }
7274
+ extra: needsFeePayer ? { feePayer: accept.extra.feePayer } : { name: _nullishCoalesce(_optionalChain([accept, 'access', _171 => _171.extra, 'optionalAccess', _172 => _172.name]), () => ( "")), version: _nullishCoalesce(_optionalChain([accept, 'access', _173 => _173.extra, 'optionalAccess', _174 => _174.version]), () => ( "")) }
7141
7275
  },
7142
7276
  receipt: { network: accept.network, asset: accept.asset, payTo: accept.payTo, amount: accept.amount },
7143
7277
  // From the merchant's own config, never the client's echo — same rule as `accept`.
@@ -7180,7 +7314,7 @@ function createPaymentGate(options) {
7180
7314
  }
7181
7315
  if (/^\d+$/.test(s)) return BigInt(s);
7182
7316
  return _chunk6XTNI2OQcjs.floorUnits.call(void 0, s, decimals);
7183
- } catch (e56) {
7317
+ } catch (e58) {
7184
7318
  return null;
7185
7319
  }
7186
7320
  }
@@ -7278,7 +7412,7 @@ function createPaymentGate(options) {
7278
7412
  [_chunk6ZRAIQXFcjs.EXT_PAYMENT_IDENTIFIER]: { info: { required: false, id } }
7279
7413
  };
7280
7414
  return { ...result, receiptHeader: _chunk6ZRAIQXFcjs.buildReceiptHeader.call(void 0, receiptOnly, merged) };
7281
- } catch (e57) {
7415
+ } catch (e59) {
7282
7416
  return result;
7283
7417
  }
7284
7418
  }
@@ -7339,8 +7473,8 @@ function createPaymentGate(options) {
7339
7473
  }
7340
7474
  function requirePayment(options) {
7341
7475
  if (options.upto) {
7342
- throw new (_class3 = class extends _chunk6XTNI2OQcjs.PipRailError {constructor(...args2) { super(...args2); _class3.prototype.__init7.call(this); }
7343
- __init7() {this.code = "UNSUPPORTED_SCHEME"}
7476
+ throw new (_class3 = class extends _chunk6XTNI2OQcjs.PipRailError {constructor(...args2) { super(...args2); _class3.prototype.__init9.call(this); }
7477
+ __init9() {this.code = "UNSUPPORTED_SCHEME"}
7344
7478
  }, _class3)(
7345
7479
  "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."
7346
7480
  );
@@ -7394,15 +7528,15 @@ async function readBody(res) {
7394
7528
  if (!text) return null;
7395
7529
  try {
7396
7530
  return JSON.parse(text);
7397
- } catch (e58) {
7531
+ } catch (e60) {
7398
7532
  return text;
7399
7533
  }
7400
7534
  }
7401
7535
  function canSwap(client) {
7402
- return _optionalChain([client, 'access', _170 => _170.canAgentSwap, 'optionalCall', _171 => _171()]) === true && typeof client.quoteSwap === "function";
7536
+ return _optionalChain([client, 'access', _175 => _175.canAgentSwap, 'optionalCall', _176 => _176()]) === true && typeof client.quoteSwap === "function";
7403
7537
  }
7404
7538
  function canSell(client) {
7405
- return _optionalChain([client, 'access', _172 => _172.canAgentSell, 'optionalCall', _173 => _173()]) === true && typeof client.address === "function";
7539
+ return _optionalChain([client, 'access', _177 => _177.canAgentSell, 'optionalCall', _178 => _178()]) === true && typeof client.address === "function";
7406
7540
  }
7407
7541
  function nonceIn(payload) {
7408
7542
  if (typeof payload !== "object" || payload === null) return void 0;
@@ -7410,9 +7544,15 @@ function nonceIn(payload) {
7410
7544
  const inner = p.payload;
7411
7545
  const fromPayload = inner && typeof inner.nonce === "string" ? inner.nonce : void 0;
7412
7546
  const accepted = p.accepted;
7413
- const fromAccept = typeof _optionalChain([accepted, 'optionalAccess', _174 => _174.extra, 'optionalAccess', _175 => _175.nonce]) === "string" ? accepted.extra.nonce : void 0;
7547
+ const fromAccept = typeof _optionalChain([accepted, 'optionalAccess', _179 => _179.extra, 'optionalAccess', _180 => _180.nonce]) === "string" ? accepted.extra.nonce : void 0;
7414
7548
  return _nullishCoalesce(fromPayload, () => ( fromAccept));
7415
7549
  }
7550
+ function refIn(payload) {
7551
+ if (typeof payload !== "object" || payload === null) return void 0;
7552
+ const inner = payload.payload;
7553
+ const ref = inner && typeof inner.txHash === "string" ? inner.txHash.trim() : void 0;
7554
+ return ref ? ref.toLowerCase() : void 0;
7555
+ }
7416
7556
  function toToolError(err) {
7417
7557
  if (!(err instanceof _chunk6XTNI2OQcjs.PipRailError)) throw err;
7418
7558
  const out = {
@@ -7817,7 +7957,7 @@ function paymentTools(client) {
7817
7957
  invoke: async (args) => {
7818
7958
  const a = args;
7819
7959
  try {
7820
- const quote = await _optionalChain([client, 'access', _176 => _176.quoteSwap, 'optionalCall', _177 => _177({
7960
+ const quote = await _optionalChain([client, 'access', _181 => _181.quoteSwap, 'optionalCall', _182 => _182({
7821
7961
  from: a.from,
7822
7962
  to: a.to,
7823
7963
  wantAmount: a.wantAmount,
@@ -7866,7 +8006,7 @@ function paymentTools(client) {
7866
8006
  invoke: async (args) => {
7867
8007
  const a = args;
7868
8008
  try {
7869
- const receipt = await _optionalChain([client, 'access', _178 => _178.swap, 'optionalCall', _179 => _179(a.quote)]);
8009
+ const receipt = await _optionalChain([client, 'access', _183 => _183.swap, 'optionalCall', _184 => _184(a.quote)]);
7870
8010
  if (!receipt) return { ok: false, reason: "unsupported", explain: "This client cannot swap." };
7871
8011
  return {
7872
8012
  ok: true,
@@ -7935,7 +8075,7 @@ function paymentTools(client) {
7935
8075
  if (!description) return { ok: false, reason: "sell needs a `description` \u2014 it is what the buyer sees and what you owe them." };
7936
8076
  if (!price) return { ok: false, reason: "sell needs a `price`, human-readable, e.g. '2.50'." };
7937
8077
  const token = typeof args.token === "string" && args.token.trim() ? args.token.trim() : "USDC";
7938
- const chain = typeof args.chain === "string" && args.chain.trim() ? args.chain.trim() : _optionalChain([client, 'access', _180 => _180.chain, 'optionalCall', _181 => _181()]);
8078
+ const chain = typeof args.chain === "string" && args.chain.trim() ? args.chain.trim() : _optionalChain([client, 'access', _185 => _185.chain, 'optionalCall', _186 => _186()]);
7939
8079
  if (chain === void 0) {
7940
8080
  return { ok: false, reason: "sell needs a `chain` \u2014 this wallet cannot report one of its own." };
7941
8081
  }
@@ -7953,16 +8093,12 @@ function paymentTools(client) {
7953
8093
  const railSchemes = (t) => [
7954
8094
  ...new Set((_nullishCoalesce(t.rails, () => ( []))).flatMap((r) => [..._nullishCoalesce(r.schemes, () => ( []))]))
7955
8095
  ];
7956
- const shared = {
7957
- isUsed: (ref) => spentProofs.has(ref),
7958
- markUsed: (ref) => void spentProofs.add(ref)
7959
- };
7960
- let gate = createPaymentGate({ ...base3, ...shared, exact: true });
8096
+ let gate = createPaymentGate({ ...base3, exact: true });
7961
8097
  let check = await gate.selfTest();
7962
8098
  const warnings = [];
7963
8099
  if (!check.ok || !railSchemes(check).includes("exact")) {
7964
8100
  const why = _nullishCoalesce(check.error, () => ( "it did not resolve on this RPC"));
7965
- gate = createPaymentGate({ ...base3, ...shared });
8101
+ gate = createPaymentGate({ ...base3 });
7966
8102
  check = await gate.selfTest();
7967
8103
  warnings.push(
7968
8104
  `This offer carries onchain-proof ONLY, so a standard x402 agent-buyer cannot pay it. A PipRail buyer (piprail_pay_request) and a human still can. The gasless exact rail was dropped because ${why} Two things cause this: the token or family has no exact scheme (a native coin never does, so price in USDC), or the token domain read failed on a busy public RPC, which is transient. Retrying on a dedicated rpcUrl is worth one attempt before you settle for this.`
@@ -7974,7 +8110,7 @@ function paymentTools(client) {
7974
8110
  for (const w of _nullishCoalesce(check.warnings, () => ( []))) warnings.push(String(w));
7975
8111
  const { challenge, requiredHeader } = await gate.challenge(resource);
7976
8112
  const schemes = railSchemes(check);
7977
- const nonce = _optionalChain([challenge, 'access', _182 => _182.accepts, 'access', _183 => _183.find, 'call', _184 => _184((a) => a.scheme === "onchain-proof"), 'optionalAccess', _185 => _185.extra, 'optionalAccess', _186 => _186.nonce]);
8113
+ const nonce = _optionalChain([challenge, 'access', _187 => _187.accepts, 'access', _188 => _188.find, 'call', _189 => _189((a) => a.scheme === "onchain-proof"), 'optionalAccess', _190 => _190.extra, 'optionalAccess', _191 => _191.nonce]);
7978
8114
  const offer = {
7979
8115
  id,
7980
8116
  nonce: typeof nonce === "string" ? nonce : void 0,
@@ -8059,7 +8195,30 @@ function paymentTools(client) {
8059
8195
  next: "Do NOT deliver. Ask the buyer to pay THIS offer's challenge."
8060
8196
  };
8061
8197
  }
8062
- const result = asObject !== void 0 ? await offer.gate.verifyObject(asObject) : await offer.gate.verify(raw);
8198
+ const proofRef = refIn(_nullishCoalesce(asObject, () => ( _chunk6ZRAIQXFcjs.decodeBase64Json.call(void 0, raw))));
8199
+ let reservedHere;
8200
+ if (proofRef) {
8201
+ if (spentProofs.has(proofRef)) {
8202
+ return {
8203
+ ok: true,
8204
+ paid: false,
8205
+ offerId: offer.id,
8206
+ reason: "this settlement was already collected \u2014 one payment settles exactly one offer.",
8207
+ code: "tx_already_used",
8208
+ next: "Do NOT deliver. Ask the buyer to pay THIS offer's challenge."
8209
+ };
8210
+ }
8211
+ spentProofs.add(proofRef);
8212
+ reservedHere = proofRef;
8213
+ }
8214
+ let result;
8215
+ try {
8216
+ result = asObject !== void 0 ? await offer.gate.verifyObject(asObject) : await offer.gate.verify(raw);
8217
+ } catch (err) {
8218
+ if (reservedHere) spentProofs.delete(reservedHere);
8219
+ throw err;
8220
+ }
8221
+ if (result.kind !== "paid" && reservedHere) spentProofs.delete(reservedHere);
8063
8222
  if (result.kind === "paid") {
8064
8223
  const r = result.receipt;
8065
8224
  const entry = {
@@ -8191,20 +8350,20 @@ function paymentTools(client) {
8191
8350
  // src/classify.ts
8192
8351
  function classifyChallenge(challenge, opts) {
8193
8352
  try {
8194
- const accepts = Array.isArray(_optionalChain([challenge, 'optionalAccess', _187 => _187.accepts])) ? challenge.accepts : [];
8195
- const network = _optionalChain([opts, 'optionalAccess', _188 => _188.network]);
8196
- const schemes = _nullishCoalesce(_optionalChain([opts, 'optionalAccess', _189 => _189.schemes]), () => ( []));
8353
+ const accepts = Array.isArray(_optionalChain([challenge, 'optionalAccess', _192 => _192.accepts])) ? challenge.accepts : [];
8354
+ const network = _optionalChain([opts, 'optionalAccess', _193 => _193.network]);
8355
+ const schemes = _nullishCoalesce(_optionalChain([opts, 'optionalAccess', _194 => _194.schemes]), () => ( []));
8197
8356
  const offeredSchemes = [
8198
- ...new Set(accepts.map((a) => _optionalChain([a, 'optionalAccess', _190 => _190.scheme])).filter((s) => s != null))
8357
+ ...new Set(accepts.map((a) => _optionalChain([a, 'optionalAccess', _195 => _195.scheme])).filter((s) => s != null))
8199
8358
  ];
8200
- const offeredNetworks = [...new Set(accepts.map((a) => _optionalChain([a, 'optionalAccess', _191 => _191.network])).filter((n) => n != null))];
8201
- const onClientChain = accepts.some((a) => _optionalChain([a, 'optionalAccess', _192 => _192.network]) === network);
8359
+ const offeredNetworks = [...new Set(accepts.map((a) => _optionalChain([a, 'optionalAccess', _196 => _196.network])).filter((n) => n != null))];
8360
+ const onClientChain = accepts.some((a) => _optionalChain([a, 'optionalAccess', _197 => _197.network]) === network);
8202
8361
  const payableScheme = accepts.some(
8203
- (a) => _optionalChain([a, 'optionalAccess', _193 => _193.network]) === network && schemes.includes(_optionalChain([a, 'optionalAccess', _194 => _194.scheme]))
8362
+ (a) => _optionalChain([a, 'optionalAccess', _198 => _198.network]) === network && schemes.includes(_optionalChain([a, 'optionalAccess', _199 => _199.scheme]))
8204
8363
  );
8205
8364
  const verdict = accepts.length === 0 ? "NO_RAIL" : payableScheme ? "PAYABLE_RAIL" : onClientChain ? "UNPAYABLE_SCHEME" : "WRONG_CHAIN";
8206
8365
  return { onClientChain, payableScheme, offeredSchemes, offeredNetworks, verdict };
8207
- } catch (e59) {
8366
+ } catch (e61) {
8208
8367
  return {
8209
8368
  onClientChain: false,
8210
8369
  payableScheme: false,
@@ -8308,7 +8467,7 @@ function isRetryableStatus(status) {
8308
8467
  }
8309
8468
  var sleep = (ms) => ms > 0 ? new Promise((resolve) => setTimeout(resolve, ms)) : Promise.resolve();
8310
8469
  async function signBody(secret, body) {
8311
- const subtle = _optionalChain([globalThis, 'access', _195 => _195.crypto, 'optionalAccess', _196 => _196.subtle]);
8470
+ const subtle = _optionalChain([globalThis, 'access', _200 => _200.crypto, 'optionalAccess', _201 => _201.subtle]);
8312
8471
  if (!subtle) return null;
8313
8472
  try {
8314
8473
  const enc = new TextEncoder();
@@ -8318,7 +8477,7 @@ async function signBody(secret, body) {
8318
8477
  const sig = await subtle.sign("HMAC", key, enc.encode(body));
8319
8478
  const hex = Array.from(new Uint8Array(sig)).map((b) => b.toString(16).padStart(2, "0")).join("");
8320
8479
  return `sha256=${hex}`;
8321
- } catch (e60) {
8480
+ } catch (e62) {
8322
8481
  return null;
8323
8482
  }
8324
8483
  }
@@ -8378,8 +8537,8 @@ async function deliverReceipt(receipt, options) {
8378
8537
  const retryable = status === void 0 ? true : isRetryableStatus(status);
8379
8538
  const willRetry = !ok && retryable && attempt < maxAttempts;
8380
8539
  try {
8381
- _optionalChain([onAttempt, 'optionalCall', _197 => _197({ attempt, ok, ...status !== void 0 ? { status } : {}, ...error ? { error } : {}, willRetry })]);
8382
- } catch (e61) {
8540
+ _optionalChain([onAttempt, 'optionalCall', _202 => _202({ attempt, ok, ...status !== void 0 ? { status } : {}, ...error ? { error } : {}, willRetry })]);
8541
+ } catch (e63) {
8383
8542
  }
8384
8543
  if (ok) return { delivered: true, attempts: attempt, status };
8385
8544
  if (!willRetry) {
@@ -8467,13 +8626,13 @@ function toA2APaymentFailed(code, detail, receipts = [], network) {
8467
8626
  };
8468
8627
  }
8469
8628
  function fromA2APaymentRequired(task) {
8470
- const meta = _optionalChain([task, 'access', _198 => _198.status, 'optionalAccess', _199 => _199.message, 'optionalAccess', _200 => _200.metadata]);
8471
- const required = _optionalChain([meta, 'optionalAccess', _201 => _201[A2A_REQUIRED_KEY]]);
8629
+ const meta = _optionalChain([task, 'access', _203 => _203.status, 'optionalAccess', _204 => _204.message, 'optionalAccess', _205 => _205.metadata]);
8630
+ const required = _optionalChain([meta, 'optionalAccess', _206 => _206[A2A_REQUIRED_KEY]]);
8472
8631
  if (!required || typeof required !== "object") return null;
8473
8632
  return required;
8474
8633
  }
8475
8634
  function fromA2APaymentPayload(message) {
8476
- const raw = _optionalChain([message, 'access', _202 => _202.metadata, 'optionalAccess', _203 => _203[A2A_PAYLOAD_KEY]]);
8635
+ const raw = _optionalChain([message, 'access', _207 => _207.metadata, 'optionalAccess', _208 => _208[A2A_PAYLOAD_KEY]]);
8477
8636
  if (raw === void 0 || raw === null) return null;
8478
8637
  return { raw, taskId: _nullishCoalesce(message.taskId, () => ( "")) };
8479
8638
  }
@@ -8506,7 +8665,7 @@ function createA2APaymentHandler(options) {
8506
8665
  const ttlMs = _nullishCoalesce(options.taskTtlMs, () => ( maxTimeoutSeconds * 1e3));
8507
8666
  const store = _nullishCoalesce(options.taskStore, () => ( defaultTaskStore()));
8508
8667
  function appendReceipt(taskId, entry) {
8509
- const prior = _nullishCoalesce(_optionalChain([store, 'access', _204 => _204.get, 'call', _205 => _205(taskId), 'optionalAccess', _206 => _206.receipts]), () => ( []));
8668
+ const prior = _nullishCoalesce(_optionalChain([store, 'access', _209 => _209.get, 'call', _210 => _210(taskId), 'optionalAccess', _211 => _211.receipts]), () => ( []));
8510
8669
  const isDup = "success" in entry && entry.success === true && entry.transaction !== "" && prior.some((r) => "transaction" in r && r.transaction === entry.transaction);
8511
8670
  const next = isDup ? prior : [...prior, entry];
8512
8671
  const receipts = next.length > MAX_TASK_RECEIPTS ? next.slice(-MAX_TASK_RECEIPTS) : next;
@@ -8614,11 +8773,11 @@ function createA2APaymentHandler(options) {
8614
8773
  }
8615
8774
  }
8616
8775
  function agentCardExtension(opts) {
8617
- const uri = _optionalChain([opts, 'optionalAccess', _207 => _207.version]) === "v0.2" ? A2A_X402_EXTENSION_URI_V02 : A2A_X402_EXTENSION_URI_V01;
8776
+ const uri = _optionalChain([opts, 'optionalAccess', _212 => _212.version]) === "v0.2" ? A2A_X402_EXTENSION_URI_V02 : A2A_X402_EXTENSION_URI_V01;
8618
8777
  return {
8619
8778
  uri,
8620
8779
  description: "Supports payments using the x402 protocol for on-chain settlement.",
8621
- ..._optionalChain([opts, 'optionalAccess', _208 => _208.required]) ? { required: true } : {}
8780
+ ..._optionalChain([opts, 'optionalAccess', _213 => _213.required]) ? { required: true } : {}
8622
8781
  };
8623
8782
  }
8624
8783
  return { handleMessage, agentCardExtension, gate };
@@ -8629,7 +8788,7 @@ function singleNetworkOf(challenge) {
8629
8788
  }
8630
8789
  function networkFromPayload(raw) {
8631
8790
  const v = raw;
8632
- if (v && typeof _optionalChain([v, 'access', _209 => _209.accepted, 'optionalAccess', _210 => _210.network]) === "string") return v.accepted.network;
8791
+ if (v && typeof _optionalChain([v, 'access', _214 => _214.accepted, 'optionalAccess', _215 => _215.network]) === "string") return v.accepted.network;
8633
8792
  if (v && typeof v.network === "string") return v.network;
8634
8793
  return void 0;
8635
8794
  }
@@ -8671,7 +8830,7 @@ function toMcpPaymentResponse(content, receipt) {
8671
8830
  };
8672
8831
  }
8673
8832
  function fromMcpPayment(params) {
8674
- const meta = _optionalChain([params, 'optionalAccess', _211 => _211._meta, 'optionalAccess', _212 => _212[MCP_PAYMENT_META_KEY]]);
8833
+ const meta = _optionalChain([params, 'optionalAccess', _216 => _216._meta, 'optionalAccess', _217 => _217[MCP_PAYMENT_META_KEY]]);
8675
8834
  return meta == null ? null : meta;
8676
8835
  }
8677
8836
  function fromMcpPaymentRequired(result) {
@@ -8680,14 +8839,14 @@ function fromMcpPaymentRequired(result) {
8680
8839
  if (sc && typeof sc === "object" && typeof sc.x402Version === "number") {
8681
8840
  return sc;
8682
8841
  }
8683
- const text = _optionalChain([result, 'access', _213 => _213.content, 'optionalAccess', _214 => _214[0], 'optionalAccess', _215 => _215.text]);
8842
+ const text = _optionalChain([result, 'access', _218 => _218.content, 'optionalAccess', _219 => _219[0], 'optionalAccess', _220 => _220.text]);
8684
8843
  if (typeof text === "string") {
8685
8844
  try {
8686
8845
  const parsed = JSON.parse(text);
8687
8846
  if (parsed && typeof parsed === "object" && typeof parsed.x402Version === "number") {
8688
8847
  return parsed;
8689
8848
  }
8690
- } catch (e62) {
8849
+ } catch (e64) {
8691
8850
  }
8692
8851
  }
8693
8852
  return null;
@@ -8696,7 +8855,7 @@ function isMcpPaymentRequired(result) {
8696
8855
  return fromMcpPaymentRequired(result) != null;
8697
8856
  }
8698
8857
  function fromMcpPaymentResponse(result) {
8699
- const meta = _optionalChain([result, 'optionalAccess', _216 => _216._meta, 'optionalAccess', _217 => _217[MCP_PAYMENT_RESPONSE_META_KEY]]);
8858
+ const meta = _optionalChain([result, 'optionalAccess', _221 => _221._meta, 'optionalAccess', _222 => _222[MCP_PAYMENT_RESPONSE_META_KEY]]);
8700
8859
  if (!meta || typeof meta !== "object") return null;
8701
8860
  return meta;
8702
8861
  }