@piprail/sdk 1.14.0 → 1.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -0
- package/ERRORS.md +15 -1
- package/README.md +38 -2
- package/STANDARDS.md +4 -2
- package/dist/{algorand-OIHGJN5S.cjs → algorand-EJ3S2V7E.cjs} +17 -17
- package/dist/{algorand-7EUZYL2Z.js → algorand-F3OYB534.js} +1 -1
- package/dist/{aptos-WDWZOU25.cjs → aptos-GJGIZHNI.cjs} +16 -16
- package/dist/{aptos-CDEYDDM5.js → aptos-SUXOVP7B.js} +1 -1
- package/dist/{chunk-H3A4KWLJ.js → chunk-ILPABTI2.js} +6 -0
- package/dist/{chunk-FTKVCP6K.cjs → chunk-PA6YD3HL.cjs} +17 -11
- package/dist/index.cjs +493 -115
- package/dist/index.d.cts +264 -12
- package/dist/index.d.ts +264 -12
- package/dist/index.js +403 -25
- package/dist/{near-DT6LRIKB.js → near-LM7S3WUD.js} +1 -1
- package/dist/{near-FUH3VAXT.cjs → near-ZJLZE26R.cjs} +19 -19
- package/dist/{solana-QUVXPKBZ.cjs → solana-MPPE6K24.cjs} +14 -14
- package/dist/{solana-3TRYD4QB.js → solana-WDKWWF33.js} +1 -1
- package/dist/{stellar-IK3UML6O.js → stellar-FIJPQZVW.js} +1 -1
- package/dist/{stellar-APZEBFAD.cjs → stellar-XHLLNHQP.cjs} +21 -21
- package/dist/{sui-L7BQNJWO.cjs → sui-6CVLEXLA.cjs} +17 -17
- package/dist/{sui-VSE63WQM.js → sui-B7AVN7NK.js} +1 -1
- package/dist/{ton-QHGQLJX2.js → ton-CHJ26BVA.js} +1 -1
- package/dist/{ton-5DLKKOFE.cjs → ton-RNEFN25G.cjs} +14 -14
- package/dist/{tron-2N2GA62O.js → tron-DD3JDROV.js} +1 -1
- package/dist/{tron-HHIT6WKY.cjs → tron-TKJHNFGM.cjs} +24 -24
- package/dist/{xrpl-2GZMDYW5.js → xrpl-GTUPP6SK.js} +1 -1
- package/dist/{xrpl-USEG4AHX.cjs → xrpl-XN2NBNGI.cjs} +21 -21
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
|
|
25
|
-
var
|
|
25
|
+
var _chunkPA6YD3HLcjs = require('./chunk-PA6YD3HL.cjs');
|
|
26
26
|
|
|
27
27
|
// src/drivers/registry.ts
|
|
28
28
|
var byFamily = /* @__PURE__ */ new Map();
|
|
@@ -51,13 +51,13 @@ function resolveNetwork(opts) {
|
|
|
51
51
|
const family = familyForChain(opts.chain);
|
|
52
52
|
const driver = byFamily.get(family);
|
|
53
53
|
if (!driver) {
|
|
54
|
-
throw new (0,
|
|
54
|
+
throw new (0, _chunkPA6YD3HLcjs.UnsupportedNetworkError)(
|
|
55
55
|
`No driver registered for the "${family}" family \u2014 it may not be mounted yet (use the async resolveNetwork()).`
|
|
56
56
|
);
|
|
57
57
|
}
|
|
58
58
|
const net = driver.resolve(opts);
|
|
59
59
|
if (!net) {
|
|
60
|
-
throw new (0,
|
|
60
|
+
throw new (0, _chunkPA6YD3HLcjs.UnsupportedNetworkError)(
|
|
61
61
|
`The ${family} driver didn't recognise this chain input.`
|
|
62
62
|
);
|
|
63
63
|
}
|
|
@@ -320,12 +320,12 @@ function createWalletAdapter(config, resolved) {
|
|
|
320
320
|
}
|
|
321
321
|
const wc = config.walletClient;
|
|
322
322
|
if (!wc.account) {
|
|
323
|
-
throw new (0,
|
|
323
|
+
throw new (0, _chunkPA6YD3HLcjs.WrongFamilyError)(
|
|
324
324
|
"chain is EVM; the provided walletClient has no attached account. Use `createWalletClient({ account, chain, transport })`, or pass { privateKey }."
|
|
325
325
|
);
|
|
326
326
|
}
|
|
327
327
|
if (wc.chain && wc.chain.id !== resolved.chainId) {
|
|
328
|
-
throw new (0,
|
|
328
|
+
throw new (0, _chunkPA6YD3HLcjs.WrongChainError)(
|
|
329
329
|
`PipRailClient: walletClient is on chain ${wc.chain.id} but the SDK was configured with chain ${resolved.chainId}. They must match.`
|
|
330
330
|
);
|
|
331
331
|
}
|
|
@@ -608,19 +608,19 @@ async function payExactEvm(input) {
|
|
|
608
608
|
code = void 0;
|
|
609
609
|
}
|
|
610
610
|
if (code && code !== "0x") {
|
|
611
|
-
throw new (0,
|
|
611
|
+
throw new (0, _chunkPA6YD3HLcjs.UnsupportedSchemeError)(
|
|
612
612
|
`exact buyer rail requires an EOA signer; ${account.address} is a contract / EIP-1271 / EIP-7702-delegated account (no recoverable ECDSA signature). Pay via onchain-proof.`
|
|
613
613
|
);
|
|
614
614
|
}
|
|
615
615
|
const domain = await readExactDomain(publicClient, accept.asset);
|
|
616
616
|
if (!domain) {
|
|
617
|
-
throw new (0,
|
|
617
|
+
throw new (0, _chunkPA6YD3HLcjs.UnsupportedSchemeError)(
|
|
618
618
|
`exact: ${accept.asset} on ${accept.network} isn't an EIP-3009 token (USDT needs Permit2; native coin and plain ERC-20s aren't exact-payable). Pay via onchain-proof.`
|
|
619
619
|
);
|
|
620
620
|
}
|
|
621
621
|
const g = globalThis.crypto;
|
|
622
622
|
if (!_optionalChain([g, 'optionalAccess', _5 => _5.getRandomValues])) {
|
|
623
|
-
throw new (0,
|
|
623
|
+
throw new (0, _chunkPA6YD3HLcjs.UnsupportedSchemeError)(
|
|
624
624
|
"this runtime lacks Web Crypto (globalThis.crypto.getRandomValues); the exact rail needs a CSPRNG nonce."
|
|
625
625
|
);
|
|
626
626
|
}
|
|
@@ -841,7 +841,7 @@ async function verifyAndSettleExactEvm(input) {
|
|
|
841
841
|
args: writeArgs
|
|
842
842
|
});
|
|
843
843
|
} catch (err) {
|
|
844
|
-
throw new (0,
|
|
844
|
+
throw new (0, _chunkPA6YD3HLcjs.SettlementError)(
|
|
845
845
|
`exact settle: the merchant relayer failed to broadcast transferWithAuthorization (${shorten(err instanceof Error ? err.message : String(err))}). The payer's authorization is still valid and unused \u2014 fund/fix the relayer and the payer can retry.`,
|
|
846
846
|
{ cause: err }
|
|
847
847
|
);
|
|
@@ -853,7 +853,7 @@ async function verifyAndSettleExactEvm(input) {
|
|
|
853
853
|
return { ok: false, error: "tx_reverted", detail: `Settlement tx ${txHash} reverted on-chain.` };
|
|
854
854
|
}
|
|
855
855
|
} catch (err) {
|
|
856
|
-
throw new (0,
|
|
856
|
+
throw new (0, _chunkPA6YD3HLcjs.SettlementError)(
|
|
857
857
|
`exact settle: broadcast ${txHash} but couldn't confirm it (${shorten(err instanceof Error ? err.message : String(err))}).`,
|
|
858
858
|
{ cause: err }
|
|
859
859
|
);
|
|
@@ -1068,15 +1068,15 @@ function makeEvmNetwork(resolved) {
|
|
|
1068
1068
|
const info = resolved.tokens[token.toUpperCase()];
|
|
1069
1069
|
if (!info) {
|
|
1070
1070
|
const known = Object.keys(resolved.tokens).join(", ") || "(none built in)";
|
|
1071
|
-
throw new (0,
|
|
1071
|
+
throw new (0, _chunkPA6YD3HLcjs.UnknownTokenError)(
|
|
1072
1072
|
`token "${token}" isn't built in for ${resolved.chain.name} (known: ${known}). Pass { address, decimals } instead, or use 'native'.`
|
|
1073
1073
|
);
|
|
1074
1074
|
}
|
|
1075
1075
|
return { asset: info.address, decimals: info.decimals, symbol: info.symbol };
|
|
1076
1076
|
}
|
|
1077
|
-
|
|
1077
|
+
_chunkPA6YD3HLcjs.rejectForeignToken.call(void 0, token, "evm", network);
|
|
1078
1078
|
if (!("address" in token)) {
|
|
1079
|
-
throw new (0,
|
|
1079
|
+
throw new (0, _chunkPA6YD3HLcjs.WrongFamilyError)(
|
|
1080
1080
|
`chain ${network} is EVM; a custom token must be { address, decimals }.`
|
|
1081
1081
|
);
|
|
1082
1082
|
}
|
|
@@ -1108,14 +1108,14 @@ function makeEvmNetwork(resolved) {
|
|
|
1108
1108
|
},
|
|
1109
1109
|
assertValidPayTo(payTo) {
|
|
1110
1110
|
if (!_viem.isAddress.call(void 0, payTo)) {
|
|
1111
|
-
throw new (0,
|
|
1111
|
+
throw new (0, _chunkPA6YD3HLcjs.WrongFamilyError)(
|
|
1112
1112
|
`chain ${network} is EVM, but payTo "${payTo}" is not a valid 0x address.`
|
|
1113
1113
|
);
|
|
1114
1114
|
}
|
|
1115
1115
|
},
|
|
1116
1116
|
bindWallet(wallet) {
|
|
1117
1117
|
if (typeof wallet !== "object" || wallet === null || !("privateKey" in wallet) && !("walletClient" in wallet)) {
|
|
1118
|
-
throw new (0,
|
|
1118
|
+
throw new (0, _chunkPA6YD3HLcjs.WrongFamilyError)(
|
|
1119
1119
|
`chain ${network} is EVM; wallet must be { privateKey } or { walletClient }.`
|
|
1120
1120
|
);
|
|
1121
1121
|
}
|
|
@@ -1132,12 +1132,12 @@ function makeEvmNetwork(resolved) {
|
|
|
1132
1132
|
});
|
|
1133
1133
|
} catch (err) {
|
|
1134
1134
|
if (isViemInsufficientFunds(err)) {
|
|
1135
|
-
throw new (0,
|
|
1135
|
+
throw new (0, _chunkPA6YD3HLcjs.InsufficientFundsError)(
|
|
1136
1136
|
err instanceof Error ? err.message : "Insufficient funds for payment.",
|
|
1137
1137
|
{ cause: err }
|
|
1138
1138
|
);
|
|
1139
1139
|
}
|
|
1140
|
-
throw _nullishCoalesce(
|
|
1140
|
+
throw _nullishCoalesce(_chunkPA6YD3HLcjs.toInsufficientFundsError.call(void 0, err), () => ( err));
|
|
1141
1141
|
}
|
|
1142
1142
|
},
|
|
1143
1143
|
async confirm(ref, minConfirmations) {
|
|
@@ -1148,7 +1148,7 @@ function makeEvmNetwork(resolved) {
|
|
|
1148
1148
|
});
|
|
1149
1149
|
return { height: receipt.blockNumber.toString() };
|
|
1150
1150
|
} catch (err) {
|
|
1151
|
-
throw new (0,
|
|
1151
|
+
throw new (0, _chunkPA6YD3HLcjs.ConfirmationTimeoutError)(
|
|
1152
1152
|
`EVM tx ${ref} did not reach ${minConfirmations} confirmation(s) in time.`,
|
|
1153
1153
|
{ cause: err }
|
|
1154
1154
|
);
|
|
@@ -1157,7 +1157,7 @@ function makeEvmNetwork(resolved) {
|
|
|
1157
1157
|
async estimateCost(accept) {
|
|
1158
1158
|
const { decimals, symbol } = resolved.chain.nativeCurrency;
|
|
1159
1159
|
if (accept.scheme === "exact") {
|
|
1160
|
-
return
|
|
1160
|
+
return _chunkPA6YD3HLcjs.nativeCost.call(void 0, {
|
|
1161
1161
|
symbol,
|
|
1162
1162
|
decimals,
|
|
1163
1163
|
fee: 0n,
|
|
@@ -1168,7 +1168,7 @@ function makeEvmNetwork(resolved) {
|
|
|
1168
1168
|
const gasLimit = accept.asset === "native" ? 21000n : 65000n;
|
|
1169
1169
|
try {
|
|
1170
1170
|
const gasPrice = await publicClient.getGasPrice();
|
|
1171
|
-
return
|
|
1171
|
+
return _chunkPA6YD3HLcjs.nativeCost.call(void 0, {
|
|
1172
1172
|
symbol,
|
|
1173
1173
|
decimals,
|
|
1174
1174
|
fee: gasPrice * gasLimit,
|
|
@@ -1177,7 +1177,7 @@ function makeEvmNetwork(resolved) {
|
|
|
1177
1177
|
});
|
|
1178
1178
|
} catch (e15) {
|
|
1179
1179
|
const gasPrice = 5000000000n;
|
|
1180
|
-
return
|
|
1180
|
+
return _chunkPA6YD3HLcjs.nativeCost.call(void 0, {
|
|
1181
1181
|
symbol,
|
|
1182
1182
|
decimals,
|
|
1183
1183
|
fee: gasPrice * gasLimit,
|
|
@@ -1271,9 +1271,9 @@ var loaders = {
|
|
|
1271
1271
|
solana: async () => {
|
|
1272
1272
|
let mod;
|
|
1273
1273
|
try {
|
|
1274
|
-
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./solana-
|
|
1274
|
+
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./solana-MPPE6K24.cjs")));
|
|
1275
1275
|
} catch (cause) {
|
|
1276
|
-
throw new (0,
|
|
1276
|
+
throw new (0, _chunkPA6YD3HLcjs.MissingDriverError)(
|
|
1277
1277
|
`Solana selected, but its packages aren't installed. Run: npm install @solana/web3.js @solana/spl-token bs58`,
|
|
1278
1278
|
{ cause }
|
|
1279
1279
|
);
|
|
@@ -1283,9 +1283,9 @@ var loaders = {
|
|
|
1283
1283
|
ton: async () => {
|
|
1284
1284
|
let mod;
|
|
1285
1285
|
try {
|
|
1286
|
-
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./ton-
|
|
1286
|
+
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./ton-RNEFN25G.cjs")));
|
|
1287
1287
|
} catch (cause) {
|
|
1288
|
-
throw new (0,
|
|
1288
|
+
throw new (0, _chunkPA6YD3HLcjs.MissingDriverError)(
|
|
1289
1289
|
`TON selected, but its packages aren't installed. Run: npm install @ton/ton @ton/core @ton/crypto`,
|
|
1290
1290
|
{ cause }
|
|
1291
1291
|
);
|
|
@@ -1295,9 +1295,9 @@ var loaders = {
|
|
|
1295
1295
|
stellar: async () => {
|
|
1296
1296
|
let mod;
|
|
1297
1297
|
try {
|
|
1298
|
-
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./stellar-
|
|
1298
|
+
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./stellar-XHLLNHQP.cjs")));
|
|
1299
1299
|
} catch (cause) {
|
|
1300
|
-
throw new (0,
|
|
1300
|
+
throw new (0, _chunkPA6YD3HLcjs.MissingDriverError)(
|
|
1301
1301
|
`Stellar selected, but its package isn't installed. Run: npm install @stellar/stellar-sdk`,
|
|
1302
1302
|
{ cause }
|
|
1303
1303
|
);
|
|
@@ -1307,9 +1307,9 @@ var loaders = {
|
|
|
1307
1307
|
xrpl: async () => {
|
|
1308
1308
|
let mod;
|
|
1309
1309
|
try {
|
|
1310
|
-
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./xrpl-
|
|
1310
|
+
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./xrpl-XN2NBNGI.cjs")));
|
|
1311
1311
|
} catch (cause) {
|
|
1312
|
-
throw new (0,
|
|
1312
|
+
throw new (0, _chunkPA6YD3HLcjs.MissingDriverError)(
|
|
1313
1313
|
`XRPL selected, but its package isn't installed. Run: npm install xrpl`,
|
|
1314
1314
|
{ cause }
|
|
1315
1315
|
);
|
|
@@ -1319,9 +1319,9 @@ var loaders = {
|
|
|
1319
1319
|
tron: async () => {
|
|
1320
1320
|
let mod;
|
|
1321
1321
|
try {
|
|
1322
|
-
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./tron-
|
|
1322
|
+
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./tron-TKJHNFGM.cjs")));
|
|
1323
1323
|
} catch (cause) {
|
|
1324
|
-
throw new (0,
|
|
1324
|
+
throw new (0, _chunkPA6YD3HLcjs.MissingDriverError)(
|
|
1325
1325
|
`Tron selected, but its package isn't installed. Run: npm install tronweb`,
|
|
1326
1326
|
{ cause }
|
|
1327
1327
|
);
|
|
@@ -1331,9 +1331,9 @@ var loaders = {
|
|
|
1331
1331
|
sui: async () => {
|
|
1332
1332
|
let mod;
|
|
1333
1333
|
try {
|
|
1334
|
-
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./sui-
|
|
1334
|
+
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./sui-6CVLEXLA.cjs")));
|
|
1335
1335
|
} catch (cause) {
|
|
1336
|
-
throw new (0,
|
|
1336
|
+
throw new (0, _chunkPA6YD3HLcjs.MissingDriverError)(
|
|
1337
1337
|
`Sui selected, but its package isn't installed. Run: npm install @mysten/sui`,
|
|
1338
1338
|
{ cause }
|
|
1339
1339
|
);
|
|
@@ -1343,9 +1343,9 @@ var loaders = {
|
|
|
1343
1343
|
near: async () => {
|
|
1344
1344
|
let mod;
|
|
1345
1345
|
try {
|
|
1346
|
-
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./near-
|
|
1346
|
+
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./near-ZJLZE26R.cjs")));
|
|
1347
1347
|
} catch (cause) {
|
|
1348
|
-
throw new (0,
|
|
1348
|
+
throw new (0, _chunkPA6YD3HLcjs.MissingDriverError)(
|
|
1349
1349
|
`NEAR selected, but its package isn't installed. Run: npm install near-api-js`,
|
|
1350
1350
|
{ cause }
|
|
1351
1351
|
);
|
|
@@ -1355,9 +1355,9 @@ var loaders = {
|
|
|
1355
1355
|
aptos: async () => {
|
|
1356
1356
|
let mod;
|
|
1357
1357
|
try {
|
|
1358
|
-
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./aptos-
|
|
1358
|
+
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./aptos-GJGIZHNI.cjs")));
|
|
1359
1359
|
} catch (cause) {
|
|
1360
|
-
throw new (0,
|
|
1360
|
+
throw new (0, _chunkPA6YD3HLcjs.MissingDriverError)(
|
|
1361
1361
|
`Aptos selected, but its package isn't installed. Run: npm install @aptos-labs/ts-sdk`,
|
|
1362
1362
|
{ cause }
|
|
1363
1363
|
);
|
|
@@ -1367,9 +1367,9 @@ var loaders = {
|
|
|
1367
1367
|
algorand: async () => {
|
|
1368
1368
|
let mod;
|
|
1369
1369
|
try {
|
|
1370
|
-
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./algorand-
|
|
1370
|
+
mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./algorand-EJ3S2V7E.cjs")));
|
|
1371
1371
|
} catch (cause) {
|
|
1372
|
-
throw new (0,
|
|
1372
|
+
throw new (0, _chunkPA6YD3HLcjs.MissingDriverError)(
|
|
1373
1373
|
`Algorand selected, but its package isn't installed. Run: npm install algosdk`,
|
|
1374
1374
|
{ cause }
|
|
1375
1375
|
);
|
|
@@ -1842,7 +1842,18 @@ function encodeBase642(str) {
|
|
|
1842
1842
|
|
|
1843
1843
|
// src/policy.ts
|
|
1844
1844
|
var ALLOW = { allowed: true };
|
|
1845
|
-
var deny = (reason) => ({
|
|
1845
|
+
var deny = (code, reason) => ({
|
|
1846
|
+
allowed: false,
|
|
1847
|
+
reason,
|
|
1848
|
+
code
|
|
1849
|
+
});
|
|
1850
|
+
function resolveDeadline(policy, sessionStart) {
|
|
1851
|
+
const fromTtl = policy.ttlSeconds != null && Number.isSafeInteger(sessionStart + policy.ttlSeconds * 1e3) ? sessionStart + policy.ttlSeconds * 1e3 : null;
|
|
1852
|
+
const fromAbs = policy.expiresAt != null ? policy.expiresAt : null;
|
|
1853
|
+
if (fromTtl == null) return fromAbs;
|
|
1854
|
+
if (fromAbs == null) return fromTtl;
|
|
1855
|
+
return Math.min(fromTtl, fromAbs);
|
|
1856
|
+
}
|
|
1846
1857
|
function hostMatches(host, pattern) {
|
|
1847
1858
|
if (pattern.startsWith("*.")) {
|
|
1848
1859
|
const suffix = pattern.slice(1);
|
|
@@ -1858,18 +1869,26 @@ function chainMatches(intent, allowed) {
|
|
|
1858
1869
|
const id = "id" in allowed ? allowed.id : void 0;
|
|
1859
1870
|
return id !== void 0 && intent.network === `eip155:${id}`;
|
|
1860
1871
|
}
|
|
1861
|
-
function evaluatePolicy(intent, policy, spentForAssetBase) {
|
|
1872
|
+
function evaluatePolicy(intent, policy, spentForAssetBase, ctx) {
|
|
1862
1873
|
if (!policy) return ALLOW;
|
|
1874
|
+
if (ctx) {
|
|
1875
|
+
const deadline = resolveDeadline(policy, ctx.sessionStart);
|
|
1876
|
+
if (deadline != null && ctx.now >= deadline) {
|
|
1877
|
+
return deny("SESSION_EXPIRED", "session expired (TTL elapsed) \u2014 refusing to pay.");
|
|
1878
|
+
}
|
|
1879
|
+
}
|
|
1863
1880
|
if (policy.chains && !policy.chains.some((c) => chainMatches(intent, c))) {
|
|
1864
1881
|
return deny(
|
|
1882
|
+
"CHAIN",
|
|
1865
1883
|
`chain ${intent.network} is not in the allowed set (policy.chains).`
|
|
1866
1884
|
);
|
|
1867
1885
|
}
|
|
1868
1886
|
if (policy.hosts && !policy.hosts.some((h) => hostMatches(intent.host, h))) {
|
|
1869
|
-
return deny(`host ${intent.host} is not in the allowed set (policy.hosts).`);
|
|
1887
|
+
return deny("HOST", `host ${intent.host} is not in the allowed set (policy.hosts).`);
|
|
1870
1888
|
}
|
|
1871
1889
|
if (!intent.recognized && !policy.allowUnknownTokens) {
|
|
1872
1890
|
return deny(
|
|
1891
|
+
"UNKNOWN_TOKEN",
|
|
1873
1892
|
`asset ${intent.asset} on ${intent.network} isn't a token the SDK can price; refusing to pay it on trust. Set policy.allowUnknownTokens to override.`
|
|
1874
1893
|
);
|
|
1875
1894
|
}
|
|
@@ -1882,34 +1901,52 @@ function evaluatePolicy(intent, policy, spentForAssetBase) {
|
|
|
1882
1901
|
});
|
|
1883
1902
|
if (!matches) {
|
|
1884
1903
|
return deny(
|
|
1904
|
+
"TOKEN",
|
|
1885
1905
|
`token ${_nullishCoalesce(intent.symbol, () => ( intent.asset))} is not in the allowed set (policy.tokens).`
|
|
1886
1906
|
);
|
|
1887
1907
|
}
|
|
1888
1908
|
}
|
|
1889
1909
|
if (policy.maxAmount !== void 0) {
|
|
1890
|
-
const cap =
|
|
1910
|
+
const cap = _chunkPA6YD3HLcjs.floorUnits.call(void 0, policy.maxAmount, intent.decimals);
|
|
1891
1911
|
if (intent.amountBase > cap) {
|
|
1892
1912
|
return deny(
|
|
1913
|
+
"MAX_AMOUNT",
|
|
1893
1914
|
`payment of ${intent.amountBase} base units exceeds policy.maxAmount ` + `(${policy.maxAmount} ${_nullishCoalesce(intent.symbol, () => ( ""))}).`.trimEnd()
|
|
1894
1915
|
);
|
|
1895
1916
|
}
|
|
1896
1917
|
}
|
|
1897
1918
|
if (policy.maxTotal !== void 0) {
|
|
1898
|
-
const cap =
|
|
1919
|
+
const cap = _chunkPA6YD3HLcjs.floorUnits.call(void 0, policy.maxTotal, intent.decimals);
|
|
1899
1920
|
if (spentForAssetBase + intent.amountBase > cap) {
|
|
1900
1921
|
return deny(
|
|
1922
|
+
"MAX_TOTAL",
|
|
1901
1923
|
`this payment would push spend on ${_nullishCoalesce(intent.symbol, () => ( intent.asset))} past policy.maxTotal (${policy.maxTotal}); already spent ${spentForAssetBase} base units.`
|
|
1902
1924
|
);
|
|
1903
1925
|
}
|
|
1904
1926
|
}
|
|
1927
|
+
if (ctx && policy.windowTotal !== void 0 && policy.windowSeconds !== void 0) {
|
|
1928
|
+
const cap = _chunkPA6YD3HLcjs.floorUnits.call(void 0, policy.windowTotal, intent.decimals);
|
|
1929
|
+
if (ctx.spentInWindowBase + intent.amountBase > cap) {
|
|
1930
|
+
return deny(
|
|
1931
|
+
"WINDOW_TOTAL",
|
|
1932
|
+
`this payment would exceed policy.windowTotal (${policy.windowTotal}) within the last ${policy.windowSeconds}s on ${_nullishCoalesce(intent.symbol, () => ( intent.asset))}.`
|
|
1933
|
+
);
|
|
1934
|
+
}
|
|
1935
|
+
}
|
|
1905
1936
|
return ALLOW;
|
|
1906
1937
|
}
|
|
1907
1938
|
|
|
1908
1939
|
// src/ledger.ts
|
|
1909
1940
|
var keyFor = (network, asset) => `${network}|${asset}`;
|
|
1910
|
-
var SpendLedger = (_class = class {constructor() { _class.prototype.__init.call(this);_class.prototype.__init2.call(this); }
|
|
1941
|
+
var SpendLedger = (_class = class {constructor() { _class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this); }
|
|
1911
1942
|
__init() {this.records = []}
|
|
1912
1943
|
__init2() {this.buckets = /* @__PURE__ */ new Map()}
|
|
1944
|
+
/**
|
|
1945
|
+
* Session clock origin (epoch-ms) — process/session start = ledger
|
|
1946
|
+
* construction. In-memory; a new process is a new session. The client reads it
|
|
1947
|
+
* to compute the `ttlSeconds` deadline and the rolling-window slice.
|
|
1948
|
+
*/
|
|
1949
|
+
__init3() {this.sessionStart = Date.now()}
|
|
1913
1950
|
/** Record a settled payment. `decimals` is the TRUE token decimals (for the
|
|
1914
1951
|
* per-asset running total used by maxTotal + the formatted summary). */
|
|
1915
1952
|
record(r, decimals) {
|
|
@@ -1935,6 +1972,38 @@ var SpendLedger = (_class = class {constructor() { _class.prototype.__init.call(
|
|
|
1935
1972
|
totalFor(network, asset) {
|
|
1936
1973
|
return _nullishCoalesce(_optionalChain([this, 'access', _25 => _25.buckets, 'access', _26 => _26.get, 'call', _27 => _27(keyFor(network, asset)), 'optionalAccess', _28 => _28.total]), () => ( 0n));
|
|
1937
1974
|
}
|
|
1975
|
+
/**
|
|
1976
|
+
* Sum of base-unit amounts for (network, asset) whose record `at` (ISO
|
|
1977
|
+
* timestamp) is at or after `sinceMs` (epoch-ms). Backs the rolling window
|
|
1978
|
+
* (`sinceMs = now - windowSeconds*1000`). A linear scan of `records` —
|
|
1979
|
+
* agent-session cardinality is small (tens), and it only runs when a window
|
|
1980
|
+
* policy is set, so it's negligible against the network round-trip.
|
|
1981
|
+
*/
|
|
1982
|
+
totalSince(network, asset, sinceMs) {
|
|
1983
|
+
let sum = 0n;
|
|
1984
|
+
for (const r of this.records) {
|
|
1985
|
+
if (r.network === network && r.asset === asset && Date.parse(r.at) >= sinceMs) {
|
|
1986
|
+
sum += BigInt(r.amountBase);
|
|
1987
|
+
}
|
|
1988
|
+
}
|
|
1989
|
+
return sum;
|
|
1990
|
+
}
|
|
1991
|
+
/**
|
|
1992
|
+
* The per-(network, asset) buckets, as read-only tuples — `network`, `asset`,
|
|
1993
|
+
* `symbol`, the TRUE `decimals` (frozen from the first record), and the running
|
|
1994
|
+
* `totalBase`. Lets the client compose a budget view WITHOUT coupling the ledger
|
|
1995
|
+
* to the policy (the cap math lives in the client). Decimals only exist for a
|
|
1996
|
+
* pair once it's been spent on — a never-spent pair simply isn't a bucket.
|
|
1997
|
+
*/
|
|
1998
|
+
assetBuckets() {
|
|
1999
|
+
return [...this.buckets.values()].map((b) => ({
|
|
2000
|
+
network: b.network,
|
|
2001
|
+
asset: b.asset,
|
|
2002
|
+
...b.symbol ? { symbol: b.symbol } : {},
|
|
2003
|
+
decimals: b.decimals,
|
|
2004
|
+
totalBase: b.total
|
|
2005
|
+
}));
|
|
2006
|
+
}
|
|
1938
2007
|
/** An immutable snapshot of all spend so far. */
|
|
1939
2008
|
summary() {
|
|
1940
2009
|
return {
|
|
@@ -1945,7 +2014,7 @@ var SpendLedger = (_class = class {constructor() { _class.prototype.__init.call(
|
|
|
1945
2014
|
symbol: b.symbol,
|
|
1946
2015
|
decimals: b.decimals,
|
|
1947
2016
|
totalBase: b.total.toString(),
|
|
1948
|
-
totalFormatted:
|
|
2017
|
+
totalFormatted: _chunkPA6YD3HLcjs.formatUnits.call(void 0, b.total, b.decimals),
|
|
1949
2018
|
count: b.count
|
|
1950
2019
|
})),
|
|
1951
2020
|
records: [...this.records]
|
|
@@ -1968,15 +2037,46 @@ var PipRailClient = (_class2 = class {
|
|
|
1968
2037
|
|
|
1969
2038
|
// Per-asset tally of everything this client has paid (powers spent() and the
|
|
1970
2039
|
// policy's maxTotal cap).
|
|
1971
|
-
|
|
2040
|
+
__init4() {this.ledger = new SpendLedger()}
|
|
1972
2041
|
// Resolved lazily on first request — this is what lets Solana (and future
|
|
1973
2042
|
// families) auto-mount with no setup call.
|
|
1974
2043
|
|
|
1975
|
-
constructor(opts) {;_class2.prototype.
|
|
2044
|
+
constructor(opts) {;_class2.prototype.__init4.call(this);
|
|
1976
2045
|
this.opts = opts;
|
|
1977
2046
|
this.maxRetries = Math.max(1, _nullishCoalesce(opts.maxPaymentRetries, () => ( 3)));
|
|
1978
2047
|
this.retryTimeoutMs = _nullishCoalesce(opts.retryTimeoutMs, () => ( 3e4));
|
|
1979
2048
|
this.onEvent = _nullishCoalesce(opts.onEvent, () => ( (() => void 0)));
|
|
2049
|
+
this.assertPolicyTimeOptions(opts.policy);
|
|
2050
|
+
}
|
|
2051
|
+
/**
|
|
2052
|
+
* Fail LOUDLY at construction on a misconfigured time policy — a security
|
|
2053
|
+
* boundary must never silently half-arm. Two invariants (a misconfiguration is
|
|
2054
|
+
* a programmer error → `TypeError`, no new SDK error code):
|
|
2055
|
+
* - the rolling window needs BOTH `windowTotal` and `windowSeconds`, or NEITHER
|
|
2056
|
+
* (one alone is a leash that silently doesn't bite);
|
|
2057
|
+
* - `ttlSeconds` must be a positive, safe integer whose `*1000` deadline stays
|
|
2058
|
+
* within `Number.MAX_SAFE_INTEGER` (else the arithmetic would lose precision).
|
|
2059
|
+
*/
|
|
2060
|
+
assertPolicyTimeOptions(policy) {
|
|
2061
|
+
if (!policy) return;
|
|
2062
|
+
const hasWindowTotal = policy.windowTotal !== void 0;
|
|
2063
|
+
const hasWindowSeconds = policy.windowSeconds !== void 0;
|
|
2064
|
+
if (hasWindowTotal !== hasWindowSeconds) {
|
|
2065
|
+
throw new TypeError(
|
|
2066
|
+
"policy.windowTotal and policy.windowSeconds must be set together \u2014 a rolling-window cap can't be half-armed (set both, or neither)."
|
|
2067
|
+
);
|
|
2068
|
+
}
|
|
2069
|
+
if (hasWindowSeconds && !(Number.isSafeInteger(policy.windowSeconds) && policy.windowSeconds > 0)) {
|
|
2070
|
+
throw new TypeError("policy.windowSeconds must be a positive integer number of seconds.");
|
|
2071
|
+
}
|
|
2072
|
+
if (policy.ttlSeconds !== void 0) {
|
|
2073
|
+
const ttl = policy.ttlSeconds;
|
|
2074
|
+
if (!Number.isSafeInteger(ttl) || ttl <= 0 || !Number.isSafeInteger(this.ledger.sessionStart + ttl * 1e3)) {
|
|
2075
|
+
throw new TypeError(
|
|
2076
|
+
"policy.ttlSeconds must be a positive integer number of seconds small enough that the resulting deadline stays a safe integer."
|
|
2077
|
+
);
|
|
2078
|
+
}
|
|
2079
|
+
}
|
|
1980
2080
|
}
|
|
1981
2081
|
/** Emit an observability event, never letting a throwing handler break the
|
|
1982
2082
|
* payment flow (mirrors the server gate's `onPaid` isolation). */
|
|
@@ -2074,6 +2174,64 @@ var PipRailClient = (_class2 = class {
|
|
|
2074
2174
|
spent() {
|
|
2075
2175
|
return this.ledger.summary();
|
|
2076
2176
|
}
|
|
2177
|
+
/**
|
|
2178
|
+
* Read-only budget + time leash for a Mode-A (headless) agent — the policy IS
|
|
2179
|
+
* the consent, and this is how the agent SEES what's left of it before paying.
|
|
2180
|
+
* Composes the in-memory ledger with the configured policy; never throws, moves
|
|
2181
|
+
* no funds. PROCESS-SCOPED — every figure resets on restart (see {@link SessionBudget}).
|
|
2182
|
+
*/
|
|
2183
|
+
budget() {
|
|
2184
|
+
const view = this.sessionView();
|
|
2185
|
+
const start = new Date(this.ledger.sessionStart).toISOString();
|
|
2186
|
+
return {
|
|
2187
|
+
session: {
|
|
2188
|
+
start,
|
|
2189
|
+
expiresAt: _optionalChain([view, 'optionalAccess', _32 => _32.expiresAt]) != null ? new Date(view.expiresAt).toISOString() : null,
|
|
2190
|
+
secondsRemaining: _nullishCoalesce(_optionalChain([view, 'optionalAccess', _33 => _33.secondsRemaining]), () => ( null))
|
|
2191
|
+
},
|
|
2192
|
+
byAsset: this.remaining()
|
|
2193
|
+
};
|
|
2194
|
+
}
|
|
2195
|
+
/**
|
|
2196
|
+
* Per-(network, asset) remaining budget — ONE row per pair the ledger already
|
|
2197
|
+
* holds (decimals are known only after the first spend), so a fresh client with
|
|
2198
|
+
* a `maxTotal` set returns `[]` until its first payment. `cap`/`remaining` are
|
|
2199
|
+
* `undefined` when no `maxTotal` is configured (unbounded). Pure + in-memory;
|
|
2200
|
+
* never throws, never sums across tokens (no price oracle). PROCESS-SCOPED.
|
|
2201
|
+
*/
|
|
2202
|
+
remaining() {
|
|
2203
|
+
const maxTotal = _optionalChain([this, 'access', _34 => _34.opts, 'access', _35 => _35.policy, 'optionalAccess', _36 => _36.maxTotal]);
|
|
2204
|
+
return this.ledger.assetBuckets().map((b) => {
|
|
2205
|
+
const base2 = {
|
|
2206
|
+
network: b.network,
|
|
2207
|
+
asset: b.asset,
|
|
2208
|
+
...b.symbol ? { symbol: b.symbol } : {},
|
|
2209
|
+
decimals: b.decimals,
|
|
2210
|
+
spentBase: b.totalBase.toString()
|
|
2211
|
+
};
|
|
2212
|
+
if (maxTotal === void 0) return base2;
|
|
2213
|
+
const capBase = _chunkPA6YD3HLcjs.floorUnits.call(void 0, maxTotal, b.decimals);
|
|
2214
|
+
const remainingBase = capBase > b.totalBase ? capBase - b.totalBase : 0n;
|
|
2215
|
+
return {
|
|
2216
|
+
...base2,
|
|
2217
|
+
capBase: capBase.toString(),
|
|
2218
|
+
remainingBase: remainingBase.toString(),
|
|
2219
|
+
remainingFormatted: _chunkPA6YD3HLcjs.formatUnits.call(void 0, remainingBase, b.decimals)
|
|
2220
|
+
};
|
|
2221
|
+
});
|
|
2222
|
+
}
|
|
2223
|
+
/** The read-only TIME envelope for the plan/budget surfaces, or `undefined`
|
|
2224
|
+
* when no session deadline (`ttlSeconds`/`expiresAt`) is set. `secondsRemaining`
|
|
2225
|
+
* is clamped ≥ 0 — a best-effort host wall-clock estimate. */
|
|
2226
|
+
sessionView(now = Date.now()) {
|
|
2227
|
+
const policy = this.opts.policy;
|
|
2228
|
+
if (!policy || policy.ttlSeconds == null && policy.expiresAt == null) return void 0;
|
|
2229
|
+
const deadline = resolveDeadline(policy, this.ledger.sessionStart);
|
|
2230
|
+
return {
|
|
2231
|
+
expiresAt: deadline,
|
|
2232
|
+
secondsRemaining: deadline == null ? null : Math.max(0, Math.floor((deadline - now) / 1e3))
|
|
2233
|
+
};
|
|
2234
|
+
}
|
|
2077
2235
|
/**
|
|
2078
2236
|
* Plan a payment for a gated URL — WITHOUT paying. The read-only completion of
|
|
2079
2237
|
* the `quote()` → `estimateCost()` → **`planPayment()`** trio: it surveys every
|
|
@@ -2094,11 +2252,11 @@ var PipRailClient = (_class2 = class {
|
|
|
2094
2252
|
* the plan yourself. No funds move.
|
|
2095
2253
|
*/
|
|
2096
2254
|
async planPayment(url, init) {
|
|
2097
|
-
const res = await fetch(url, { ..._nullishCoalesce(init, () => ( {})), method: _nullishCoalesce(_optionalChain([init, 'optionalAccess',
|
|
2255
|
+
const res = await fetch(url, { ..._nullishCoalesce(init, () => ( {})), method: _nullishCoalesce(_optionalChain([init, 'optionalAccess', _37 => _37.method]), () => ( "GET")) });
|
|
2098
2256
|
if (res.status !== 402) return null;
|
|
2099
2257
|
const challenge = await parseChallenge(res);
|
|
2100
2258
|
if (!challenge) {
|
|
2101
|
-
throw new (0,
|
|
2259
|
+
throw new (0, _chunkPA6YD3HLcjs.InvalidEnvelopeError)("402 response did not include a parseable x402 challenge.");
|
|
2102
2260
|
}
|
|
2103
2261
|
const { net, wallet } = await this.ensure();
|
|
2104
2262
|
return this.planFromChallenge(net, wallet, challenge, url, this.resolveSchemes());
|
|
@@ -2261,24 +2419,24 @@ var PipRailClient = (_class2 = class {
|
|
|
2261
2419
|
* streams throw `NonReplayableBodyError`.
|
|
2262
2420
|
*/
|
|
2263
2421
|
async fetch(url, init) {
|
|
2264
|
-
const body = _optionalChain([init, 'optionalAccess',
|
|
2422
|
+
const body = _optionalChain([init, 'optionalAccess', _38 => _38.body]);
|
|
2265
2423
|
if (body !== void 0 && body !== null && !isReplayableBodyInit(body)) {
|
|
2266
|
-
throw new (0,
|
|
2424
|
+
throw new (0, _chunkPA6YD3HLcjs.NonReplayableBodyError)(
|
|
2267
2425
|
"fetch(): init.body is not replayable. Pass a string, FormData, URLSearchParams, ArrayBuffer, or Blob \u2014 not a ReadableStream."
|
|
2268
2426
|
);
|
|
2269
2427
|
}
|
|
2270
2428
|
const firstResponse = await fetch(url, init);
|
|
2271
2429
|
if (firstResponse.status !== 402) return firstResponse;
|
|
2272
|
-
const schemes = this.resolveSchemes(_optionalChain([init, 'optionalAccess',
|
|
2430
|
+
const schemes = this.resolveSchemes(_optionalChain([init, 'optionalAccess', _39 => _39.schemes]));
|
|
2273
2431
|
const resolved = await this.resolveChallenge(url, firstResponse, schemes);
|
|
2274
2432
|
const { net, wallet, challenge } = resolved;
|
|
2275
2433
|
let accept = resolved.accept;
|
|
2276
2434
|
let quote = resolved.quote;
|
|
2277
|
-
const autoRoute = _nullishCoalesce(_nullishCoalesce(_optionalChain([init, 'optionalAccess',
|
|
2435
|
+
const autoRoute = _nullishCoalesce(_nullishCoalesce(_optionalChain([init, 'optionalAccess', _40 => _40.autoRoute]), () => ( this.opts.autoRoute)), () => ( false));
|
|
2278
2436
|
if (autoRoute) {
|
|
2279
2437
|
const plan = await this.planFromChallenge(net, wallet, challenge, url, schemes);
|
|
2280
2438
|
if (!plan.best) {
|
|
2281
|
-
throw new (0,
|
|
2439
|
+
throw new (0, _chunkPA6YD3HLcjs.PaymentDeclinedError)(_nullishCoalesce(plan.fundingHint, () => ( "No rail is settleable for this payment.")));
|
|
2282
2440
|
}
|
|
2283
2441
|
accept = plan.best.accept;
|
|
2284
2442
|
quote = plan.best.quote;
|
|
@@ -2302,7 +2460,7 @@ var PipRailClient = (_class2 = class {
|
|
|
2302
2460
|
async resolveChallenge(url, response, schemes) {
|
|
2303
2461
|
const challenge = await parseChallenge(response);
|
|
2304
2462
|
if (!challenge) {
|
|
2305
|
-
throw new (0,
|
|
2463
|
+
throw new (0, _chunkPA6YD3HLcjs.InvalidEnvelopeError)(
|
|
2306
2464
|
"402 response did not include a parseable x402 challenge."
|
|
2307
2465
|
);
|
|
2308
2466
|
}
|
|
@@ -2313,7 +2471,7 @@ var PipRailClient = (_class2 = class {
|
|
|
2313
2471
|
(a) => a.scheme === "exact" && net.supports(a.network)
|
|
2314
2472
|
);
|
|
2315
2473
|
if (schemes.includes("exact") && exactOnNet && typeof net.payExact !== "function") {
|
|
2316
|
-
throw new (0,
|
|
2474
|
+
throw new (0, _chunkPA6YD3HLcjs.UnsupportedSchemeError)(
|
|
2317
2475
|
`This 402 offers a standard 'exact' rail on ${net.network}, but the ${net.family} family can't pay 'exact' (EVM + EIP-3009 only), and no 'onchain-proof' rail was offered.`
|
|
2318
2476
|
);
|
|
2319
2477
|
}
|
|
@@ -2322,13 +2480,13 @@ var PipRailClient = (_class2 = class {
|
|
|
2322
2480
|
(a) => a.scheme === "exact" && net.supports(a.network) && net.describeAsset(a.asset) != null
|
|
2323
2481
|
);
|
|
2324
2482
|
if (payable) {
|
|
2325
|
-
throw new (0,
|
|
2483
|
+
throw new (0, _chunkPA6YD3HLcjs.NoCompatibleAcceptError)(
|
|
2326
2484
|
`This 402 is payable only via the standard 'exact' rail on ${net.network}, which is OFF by default. Enable it: new PipRailClient({ \u2026, schemes: ['onchain-proof', 'exact'] }) or per call fetch(url, { schemes: ['exact'] }) (MCP: PIPRAIL_SCHEMES=onchain-proof,exact).`
|
|
2327
2485
|
);
|
|
2328
2486
|
}
|
|
2329
2487
|
}
|
|
2330
2488
|
const networks = [...new Set(challenge.accepts.map((a) => a.network))].join(", ");
|
|
2331
|
-
throw new (0,
|
|
2489
|
+
throw new (0, _chunkPA6YD3HLcjs.NoCompatibleAcceptError)(
|
|
2332
2490
|
`No accepts[] entry payable by this client on ${net.network} (schemes: ${schemes.join(", ")}; challenge offered: ${networks || "none"}).`
|
|
2333
2491
|
);
|
|
2334
2492
|
}
|
|
@@ -2369,6 +2527,7 @@ var PipRailClient = (_class2 = class {
|
|
|
2369
2527
|
* net/wallet. Shared by `planPayment` (read-only) and `fetch`'s autoRoute. */
|
|
2370
2528
|
async planFromChallenge(net, wallet, challenge, url, schemes) {
|
|
2371
2529
|
const chainLabel = typeof this.opts.chain === "string" ? this.opts.chain : net.network;
|
|
2530
|
+
const session = this.sessionView();
|
|
2372
2531
|
const candidates = this.gatherCandidates(net, challenge, schemes);
|
|
2373
2532
|
if (candidates.length === 0) {
|
|
2374
2533
|
const offered = [...new Set(challenge.accepts.map((a) => a.network))].join(", ") || "none";
|
|
@@ -2379,7 +2538,8 @@ var PipRailClient = (_class2 = class {
|
|
|
2379
2538
|
payable: false,
|
|
2380
2539
|
best: null,
|
|
2381
2540
|
options: [],
|
|
2382
|
-
fundingHint: `This 402 isn't offered on your chain (${chainLabel}); it's payable on: ${offered}
|
|
2541
|
+
fundingHint: `This 402 isn't offered on your chain (${chainLabel}); it's payable on: ${offered}.`,
|
|
2542
|
+
...session ? { session } : {}
|
|
2383
2543
|
};
|
|
2384
2544
|
}
|
|
2385
2545
|
const analysed = await Promise.all(
|
|
@@ -2397,7 +2557,8 @@ var PipRailClient = (_class2 = class {
|
|
|
2397
2557
|
payable: best !== null,
|
|
2398
2558
|
best,
|
|
2399
2559
|
options,
|
|
2400
|
-
fundingHint: best ? null : buildFundingHint(options, chainLabel)
|
|
2560
|
+
fundingHint: best ? null : buildFundingHint(options, chainLabel),
|
|
2561
|
+
...session ? { session } : {}
|
|
2401
2562
|
};
|
|
2402
2563
|
}
|
|
2403
2564
|
/** Analyse ONE rail against the wallet's holdings — quote (existing) + gas
|
|
@@ -2414,7 +2575,11 @@ var PipRailClient = (_class2 = class {
|
|
|
2414
2575
|
const blockers = [];
|
|
2415
2576
|
const warnings = [];
|
|
2416
2577
|
const shortfall = {};
|
|
2417
|
-
if (!quote.withinPolicy)
|
|
2578
|
+
if (!quote.withinPolicy) {
|
|
2579
|
+
blockers.push(
|
|
2580
|
+
quote.policyCode === "SESSION_EXPIRED" || quote.policyCode === "WINDOW_TOTAL" ? "OUTSIDE_WINDOW" : "OUTSIDE_POLICY"
|
|
2581
|
+
);
|
|
2582
|
+
}
|
|
2418
2583
|
if (quote.symbolMismatch) warnings.push("SYMBOL_MISMATCH");
|
|
2419
2584
|
if (!isExact && cost.basis === "heuristic") warnings.push("GAS_HEURISTIC");
|
|
2420
2585
|
const tokenKnown = bal.token != null;
|
|
@@ -2423,21 +2588,21 @@ var PipRailClient = (_class2 = class {
|
|
|
2423
2588
|
if (isExact) {
|
|
2424
2589
|
if (tokenKnown && bal.token < amount) {
|
|
2425
2590
|
blockers.push("INSUFFICIENT_TOKEN");
|
|
2426
|
-
shortfall.token =
|
|
2591
|
+
shortfall.token = _chunkPA6YD3HLcjs.formatUnits.call(void 0, amount - bal.token, quote.decimals);
|
|
2427
2592
|
}
|
|
2428
2593
|
} else if (isNative) {
|
|
2429
2594
|
if (nativeKnown && bal.native < amount + fee) {
|
|
2430
2595
|
blockers.push("INSUFFICIENT_TOKEN");
|
|
2431
|
-
shortfall.token =
|
|
2596
|
+
shortfall.token = _chunkPA6YD3HLcjs.formatUnits.call(void 0, amount + fee - bal.native, quote.decimals);
|
|
2432
2597
|
}
|
|
2433
2598
|
} else {
|
|
2434
2599
|
if (tokenKnown && bal.token < amount) {
|
|
2435
2600
|
blockers.push("INSUFFICIENT_TOKEN");
|
|
2436
|
-
shortfall.token =
|
|
2601
|
+
shortfall.token = _chunkPA6YD3HLcjs.formatUnits.call(void 0, amount - bal.token, quote.decimals);
|
|
2437
2602
|
}
|
|
2438
2603
|
if (nativeKnown && bal.native < fee) {
|
|
2439
2604
|
blockers.push("INSUFFICIENT_GAS");
|
|
2440
|
-
shortfall.native =
|
|
2605
|
+
shortfall.native = _chunkPA6YD3HLcjs.formatUnits.call(void 0, fee - bal.native, cost.feeDecimals);
|
|
2441
2606
|
} else if (nativeKnown && fee > 0n && bal.native < fee * 3n / 2n) {
|
|
2442
2607
|
warnings.push("THIN_GAS_MARGIN");
|
|
2443
2608
|
}
|
|
@@ -2462,8 +2627,8 @@ var PipRailClient = (_class2 = class {
|
|
|
2462
2627
|
blockers,
|
|
2463
2628
|
warnings,
|
|
2464
2629
|
balance: {
|
|
2465
|
-
token: bal.token != null ?
|
|
2466
|
-
native: bal.native != null ?
|
|
2630
|
+
token: bal.token != null ? _chunkPA6YD3HLcjs.formatUnits.call(void 0, bal.token, quote.decimals) : null,
|
|
2631
|
+
native: bal.native != null ? _chunkPA6YD3HLcjs.formatUnits.call(void 0, bal.native, cost.feeDecimals) : null
|
|
2467
2632
|
},
|
|
2468
2633
|
need: { token: quote.amountFormatted, native: cost.feeFormatted },
|
|
2469
2634
|
...shortfall.token || shortfall.native ? { shortfall } : {},
|
|
@@ -2474,20 +2639,20 @@ var PipRailClient = (_class2 = class {
|
|
|
2474
2639
|
* driver's describeAsset) + the policy verdict + a symbol-mismatch flag. */
|
|
2475
2640
|
buildQuote(net, accept, url, description) {
|
|
2476
2641
|
if (!/^\d+$/.test(accept.amount)) {
|
|
2477
|
-
throw new (0,
|
|
2642
|
+
throw new (0, _chunkPA6YD3HLcjs.InvalidEnvelopeError)(
|
|
2478
2643
|
`challenge amount "${accept.amount}" is not a base-unit integer.`
|
|
2479
2644
|
);
|
|
2480
2645
|
}
|
|
2481
2646
|
const amountBase = BigInt(accept.amount);
|
|
2482
2647
|
const described = net.describeAsset(accept.asset);
|
|
2483
|
-
const decimals = _nullishCoalesce(_optionalChain([described, 'optionalAccess',
|
|
2648
|
+
const decimals = _nullishCoalesce(_optionalChain([described, 'optionalAccess', _41 => _41.decimals]), () => ( accept.extra.decimals));
|
|
2484
2649
|
if (decimals === void 0) {
|
|
2485
|
-
throw new (0,
|
|
2650
|
+
throw new (0, _chunkPA6YD3HLcjs.InvalidEnvelopeError)(
|
|
2486
2651
|
`challenge for ${accept.asset} on ${accept.network} states no decimals and the SDK doesn't recognise the token \u2014 refusing to price it.`
|
|
2487
2652
|
);
|
|
2488
2653
|
}
|
|
2489
|
-
const symbol = _nullishCoalesce(_optionalChain([described, 'optionalAccess',
|
|
2490
|
-
const amountFormatted =
|
|
2654
|
+
const symbol = _nullishCoalesce(_optionalChain([described, 'optionalAccess', _42 => _42.symbol]), () => ( accept.extra.symbol));
|
|
2655
|
+
const amountFormatted = _chunkPA6YD3HLcjs.formatUnits.call(void 0, amountBase, decimals);
|
|
2491
2656
|
const intent = {
|
|
2492
2657
|
host: hostOf2(url),
|
|
2493
2658
|
chain: this.opts.chain,
|
|
@@ -2498,10 +2663,25 @@ var PipRailClient = (_class2 = class {
|
|
|
2498
2663
|
symbol,
|
|
2499
2664
|
recognized: described != null
|
|
2500
2665
|
};
|
|
2666
|
+
const policy = this.opts.policy;
|
|
2667
|
+
const hasWindow = !!policy && policy.windowTotal != null && policy.windowSeconds != null;
|
|
2668
|
+
const hasTimePolicy = !!policy && (policy.ttlSeconds != null || policy.expiresAt != null || hasWindow);
|
|
2669
|
+
const now = Date.now();
|
|
2670
|
+
const ctx = hasTimePolicy ? {
|
|
2671
|
+
now,
|
|
2672
|
+
sessionStart: this.ledger.sessionStart,
|
|
2673
|
+
// Window slice ONLY when BOTH fields are set — never a `?? 0` width.
|
|
2674
|
+
spentInWindowBase: hasWindow ? this.ledger.totalSince(
|
|
2675
|
+
accept.network,
|
|
2676
|
+
accept.asset,
|
|
2677
|
+
now - policy.windowSeconds * 1e3
|
|
2678
|
+
) : 0n
|
|
2679
|
+
} : void 0;
|
|
2501
2680
|
const decision = evaluatePolicy(
|
|
2502
2681
|
intent,
|
|
2503
2682
|
this.opts.policy,
|
|
2504
|
-
this.ledger.totalFor(accept.network, accept.asset)
|
|
2683
|
+
this.ledger.totalFor(accept.network, accept.asset),
|
|
2684
|
+
ctx
|
|
2505
2685
|
);
|
|
2506
2686
|
const serverSymbol = accept.extra.symbol;
|
|
2507
2687
|
const symbolMismatch = intent.recognized && !!serverSymbol && !!symbol && serverSymbol.toUpperCase() !== symbol.toUpperCase();
|
|
@@ -2520,15 +2700,19 @@ var PipRailClient = (_class2 = class {
|
|
|
2520
2700
|
recognized: intent.recognized,
|
|
2521
2701
|
symbolMismatch,
|
|
2522
2702
|
withinPolicy: decision.allowed,
|
|
2523
|
-
...decision.reason ? { policyReason: decision.reason } : {}
|
|
2703
|
+
...decision.reason ? { policyReason: decision.reason } : {},
|
|
2704
|
+
...decision.code ? { policyCode: decision.code } : {}
|
|
2524
2705
|
};
|
|
2525
2706
|
}
|
|
2526
2707
|
/** Enforce the spend policy and the onBeforePay hook — both refuse by
|
|
2527
|
-
* throwing PaymentDeclinedError, before any funds move.
|
|
2708
|
+
* throwing PaymentDeclinedError, before any funds move. Every refusal carries
|
|
2709
|
+
* a typed `reasonCode` so an agent can branch on the cause (and spot a
|
|
2710
|
+
* TERMINAL expiry/approval decline it must not retry) without parsing prose. */
|
|
2528
2711
|
async authorize(quote) {
|
|
2529
2712
|
if (!quote.withinPolicy) {
|
|
2530
|
-
throw new (0,
|
|
2531
|
-
`Payment refused by policy: ${_nullishCoalesce(quote.policyReason, () => ( "not allowed"))}
|
|
2713
|
+
throw new (0, _chunkPA6YD3HLcjs.PaymentDeclinedError)(
|
|
2714
|
+
`Payment refused by policy: ${_nullishCoalesce(quote.policyReason, () => ( "not allowed"))}`,
|
|
2715
|
+
{ reasonCode: reasonCodeForPolicy(quote.policyCode) }
|
|
2532
2716
|
);
|
|
2533
2717
|
}
|
|
2534
2718
|
const hook = this.opts.onBeforePay;
|
|
@@ -2537,13 +2721,15 @@ var PipRailClient = (_class2 = class {
|
|
|
2537
2721
|
try {
|
|
2538
2722
|
approved = await hook(quote);
|
|
2539
2723
|
} catch (err) {
|
|
2540
|
-
throw new (0,
|
|
2541
|
-
cause: err
|
|
2724
|
+
throw new (0, _chunkPA6YD3HLcjs.PaymentDeclinedError)("onBeforePay threw \u2014 refusing to pay.", {
|
|
2725
|
+
cause: err,
|
|
2726
|
+
reasonCode: "APPROVAL"
|
|
2542
2727
|
});
|
|
2543
2728
|
}
|
|
2544
2729
|
if (!approved) {
|
|
2545
|
-
throw new (0,
|
|
2546
|
-
`onBeforePay declined ${quote.amountFormatted} ${_nullishCoalesce(quote.symbol, () => ( ""))}`.trimEnd() + ` on ${quote.network}
|
|
2730
|
+
throw new (0, _chunkPA6YD3HLcjs.PaymentDeclinedError)(
|
|
2731
|
+
`onBeforePay declined ${quote.amountFormatted} ${_nullishCoalesce(quote.symbol, () => ( ""))}`.trimEnd() + ` on ${quote.network}.`,
|
|
2732
|
+
{ reasonCode: "APPROVAL" }
|
|
2547
2733
|
);
|
|
2548
2734
|
}
|
|
2549
2735
|
}
|
|
@@ -2566,7 +2752,7 @@ var PipRailClient = (_class2 = class {
|
|
|
2566
2752
|
}
|
|
2567
2753
|
async payAndConfirm(net, wallet, accept) {
|
|
2568
2754
|
if (!net.supports(accept.network)) {
|
|
2569
|
-
throw new (0,
|
|
2755
|
+
throw new (0, _chunkPA6YD3HLcjs.WrongChainError)(
|
|
2570
2756
|
`Challenge expects ${accept.network} but client is on ${net.network}.`
|
|
2571
2757
|
);
|
|
2572
2758
|
}
|
|
@@ -2595,7 +2781,7 @@ var PipRailClient = (_class2 = class {
|
|
|
2595
2781
|
accepted: accept,
|
|
2596
2782
|
payload: { nonce: accept.extra.nonce, txHash: ref }
|
|
2597
2783
|
};
|
|
2598
|
-
const headers = new Headers(_optionalChain([originalInit, 'optionalAccess',
|
|
2784
|
+
const headers = new Headers(_optionalChain([originalInit, 'optionalAccess', _43 => _43.headers]));
|
|
2599
2785
|
headers.set(HEADER_SIGNATURE, buildSignatureHeader(signature));
|
|
2600
2786
|
let lastResponse = null;
|
|
2601
2787
|
let lastReason = null;
|
|
@@ -2610,7 +2796,7 @@ var PipRailClient = (_class2 = class {
|
|
|
2610
2796
|
() => timeoutController.abort(),
|
|
2611
2797
|
this.retryTimeoutMs
|
|
2612
2798
|
);
|
|
2613
|
-
const signal = _optionalChain([originalInit, 'optionalAccess',
|
|
2799
|
+
const signal = _optionalChain([originalInit, 'optionalAccess', _44 => _44.signal]) && typeof AbortSignal.any === "function" ? AbortSignal.any([timeoutController.signal, originalInit.signal]) : timeoutController.signal;
|
|
2614
2800
|
try {
|
|
2615
2801
|
lastResponse = await fetch(url, {
|
|
2616
2802
|
..._nullishCoalesce(originalInit, () => ( {})),
|
|
@@ -2619,7 +2805,7 @@ var PipRailClient = (_class2 = class {
|
|
|
2619
2805
|
});
|
|
2620
2806
|
} catch (err) {
|
|
2621
2807
|
if (timeoutController.signal.aborted) {
|
|
2622
|
-
throw new (0,
|
|
2808
|
+
throw new (0, _chunkPA6YD3HLcjs.PaymentTimeoutError)(
|
|
2623
2809
|
`Server did not respond within ${this.retryTimeoutMs}ms after broadcasting payment ${ref}. Re-verify or re-submit ref=${ref} \u2014 do NOT re-pay.`,
|
|
2624
2810
|
{ cause: err, ref }
|
|
2625
2811
|
);
|
|
@@ -2641,7 +2827,7 @@ var PipRailClient = (_class2 = class {
|
|
|
2641
2827
|
kind: "payment-failed",
|
|
2642
2828
|
reason: `server returned 402 after broadcasting payment ${ref}${unconfirmedNote} (${why})`
|
|
2643
2829
|
});
|
|
2644
|
-
throw new (0,
|
|
2830
|
+
throw new (0, _chunkPA6YD3HLcjs.MaxRetriesExceededError)(
|
|
2645
2831
|
`Server still returned 402 after ${attempts} attempt(s) with on-chain proof ref=${ref}${unconfirmedNote}. Last server rejection: ${why}. Re-verify or re-submit ref=${ref} before retrying \u2014 never re-pay (it would double-spend).`,
|
|
2646
2832
|
{ ref }
|
|
2647
2833
|
);
|
|
@@ -2665,17 +2851,17 @@ var PipRailClient = (_class2 = class {
|
|
|
2665
2851
|
*/
|
|
2666
2852
|
async payExactRail(net, wallet, accept, url, init, quote) {
|
|
2667
2853
|
if (!net.payExact) {
|
|
2668
|
-
throw new (0,
|
|
2854
|
+
throw new (0, _chunkPA6YD3HLcjs.UnsupportedSchemeError)(
|
|
2669
2855
|
`the ${net.family} family can't pay a standard 'exact' rail (EVM + EIP-3009 only).`
|
|
2670
2856
|
);
|
|
2671
2857
|
}
|
|
2672
|
-
throwIfAborted(_optionalChain([init, 'optionalAccess',
|
|
2858
|
+
throwIfAborted(_optionalChain([init, 'optionalAccess', _45 => _45.signal]));
|
|
2673
2859
|
const { payload, accepted, payerFrom, nonce } = await net.payExact(wallet, accept);
|
|
2674
|
-
const headers = new Headers(_optionalChain([init, 'optionalAccess',
|
|
2860
|
+
const headers = new Headers(_optionalChain([init, 'optionalAccess', _46 => _46.headers]));
|
|
2675
2861
|
headers.set(HEADER_SIGNATURE, buildExactSignatureHeader({ accepted, payload }));
|
|
2676
2862
|
const rejectDefinitive = (why2) => {
|
|
2677
2863
|
this.safeEmit({ kind: "payment-failed", reason: `exact: facilitator rejected nonce=${nonce} (${why2})` });
|
|
2678
|
-
throw new (0,
|
|
2864
|
+
throw new (0, _chunkPA6YD3HLcjs.MaxRetriesExceededError)(
|
|
2679
2865
|
`exact: the facilitator rejected the payment (${why2}). Fix the cause, then re-present the SAME signed authorization (nonce=${nonce}) \u2014 do NOT re-sign a fresh nonce. ref=${nonce}.`,
|
|
2680
2866
|
{ ref: nonce }
|
|
2681
2867
|
);
|
|
@@ -2688,17 +2874,17 @@ var PipRailClient = (_class2 = class {
|
|
|
2688
2874
|
if (Date.now() >= deadline) break;
|
|
2689
2875
|
await new Promise((r) => setTimeout(r, Math.min(2e3, 400 * 2 ** (attempt - 1))));
|
|
2690
2876
|
}
|
|
2691
|
-
throwIfAborted(_optionalChain([init, 'optionalAccess',
|
|
2877
|
+
throwIfAborted(_optionalChain([init, 'optionalAccess', _47 => _47.signal]));
|
|
2692
2878
|
const budget = Math.min(this.retryTimeoutMs, deadline - Date.now());
|
|
2693
2879
|
if (budget <= 0) break;
|
|
2694
2880
|
const timeoutController = new AbortController();
|
|
2695
2881
|
const timeoutId = setTimeout(() => timeoutController.abort(), budget);
|
|
2696
|
-
const signal = _optionalChain([init, 'optionalAccess',
|
|
2882
|
+
const signal = _optionalChain([init, 'optionalAccess', _48 => _48.signal]) && typeof AbortSignal.any === "function" ? AbortSignal.any([timeoutController.signal, init.signal]) : timeoutController.signal;
|
|
2697
2883
|
let response;
|
|
2698
2884
|
try {
|
|
2699
2885
|
response = await fetch(url, { ..._nullishCoalesce(init, () => ( {})), headers, signal });
|
|
2700
2886
|
} catch (err) {
|
|
2701
|
-
throw new (0,
|
|
2887
|
+
throw new (0, _chunkPA6YD3HLcjs.PaymentTimeoutError)(
|
|
2702
2888
|
`exact: no response after submitting the authorization (nonce=${nonce}) to ${hostOf2(url)}. The facilitator may have already settled it \u2014 verify on-chain with authorizationState(${payerFrom}, ${nonce}) before re-presenting; do NOT re-pay.`,
|
|
2703
2889
|
{ cause: err, ref: nonce }
|
|
2704
2890
|
);
|
|
@@ -2714,7 +2900,7 @@ var PipRailClient = (_class2 = class {
|
|
|
2714
2900
|
if (response.ok && !(settle && settle.success === false)) {
|
|
2715
2901
|
const receipt = parseReceipt(response);
|
|
2716
2902
|
this.safeEmit({ kind: "payment-settled", receipt, ...settle ? { settle } : {} });
|
|
2717
|
-
const ref = _optionalChain([settle, 'optionalAccess',
|
|
2903
|
+
const ref = _optionalChain([settle, 'optionalAccess', _49 => _49.transaction]) || _optionalChain([receipt, 'optionalAccess', _50 => _50.transaction]) || `eip3009-nonce:${nonce}`;
|
|
2718
2904
|
this.recordSpend(quote, ref);
|
|
2719
2905
|
return response;
|
|
2720
2906
|
}
|
|
@@ -2731,14 +2917,14 @@ var PipRailClient = (_class2 = class {
|
|
|
2731
2917
|
kind: "payment-failed",
|
|
2732
2918
|
reason: `exact: 402 after submitting authorization nonce=${nonce} (${why})`
|
|
2733
2919
|
});
|
|
2734
|
-
throw new (0,
|
|
2920
|
+
throw new (0, _chunkPA6YD3HLcjs.MaxRetriesExceededError)(
|
|
2735
2921
|
`exact: server still returned 402 after submitting the signed authorization (nonce=${nonce}). Last rejection: ${why}. Re-present the SAME authorization \u2014 do NOT re-sign a fresh nonce; verify authorizationState(${payerFrom}, ${nonce}) first. ref=${nonce}.`,
|
|
2736
2922
|
{ ref: nonce }
|
|
2737
2923
|
);
|
|
2738
2924
|
}
|
|
2739
2925
|
}, _class2);
|
|
2740
2926
|
function throwIfAborted(signal) {
|
|
2741
|
-
if (_optionalChain([signal, 'optionalAccess',
|
|
2927
|
+
if (_optionalChain([signal, 'optionalAccess', _51 => _51.aborted])) {
|
|
2742
2928
|
throw _nullishCoalesce(signal.reason, () => ( new DOMException("This operation was aborted.", "AbortError")));
|
|
2743
2929
|
}
|
|
2744
2930
|
}
|
|
@@ -2771,6 +2957,9 @@ function buildFundingHint(options, chainLabel) {
|
|
|
2771
2957
|
if (target.blockers.includes("RECIPIENT_NOT_READY")) {
|
|
2772
2958
|
return `Recipient ${shortAddr(target.accept.payTo)} can't receive on ${chainLabel} yet \u2014 ${_nullishCoalesce(target.recipient.fix, () => ( "recipient not ready"))}.`;
|
|
2773
2959
|
}
|
|
2960
|
+
if (target.blockers.includes("OUTSIDE_WINDOW")) {
|
|
2961
|
+
return target.quote.policyCode === "SESSION_EXPIRED" ? `Session is over on ${chainLabel} \u2014 restart the process or extend the TTL; no retry will succeed.` : `Budget window exhausted on ${chainLabel} \u2014 wait for it to free, or raise policy.windowTotal.`;
|
|
2962
|
+
}
|
|
2774
2963
|
if (target.blockers.includes("OUTSIDE_POLICY")) {
|
|
2775
2964
|
return `Refused by spend policy: ${_nullishCoalesce(target.quote.policyReason, () => ( "not allowed"))}.`;
|
|
2776
2965
|
}
|
|
@@ -2778,10 +2967,10 @@ function buildFundingHint(options, chainLabel) {
|
|
|
2778
2967
|
return `Couldn't fully read your wallet on ${chainLabel} (RPC throttled) \u2014 retry; you may already be able to pay ${target.quote.amountFormatted} ${sym}.`;
|
|
2779
2968
|
}
|
|
2780
2969
|
const parts = [];
|
|
2781
|
-
if (target.blockers.includes("INSUFFICIENT_TOKEN") && _optionalChain([target, 'access',
|
|
2970
|
+
if (target.blockers.includes("INSUFFICIENT_TOKEN") && _optionalChain([target, 'access', _52 => _52.shortfall, 'optionalAccess', _53 => _53.token])) {
|
|
2782
2971
|
parts.push(`top up ${target.shortfall.token} ${sym}`);
|
|
2783
2972
|
}
|
|
2784
|
-
if (target.blockers.includes("INSUFFICIENT_GAS") && _optionalChain([target, 'access',
|
|
2973
|
+
if (target.blockers.includes("INSUFFICIENT_GAS") && _optionalChain([target, 'access', _54 => _54.shortfall, 'optionalAccess', _55 => _55.native])) {
|
|
2785
2974
|
parts.push(`add ~${target.shortfall.native} ${target.cost.feeSymbol} for gas`);
|
|
2786
2975
|
}
|
|
2787
2976
|
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}.`;
|
|
@@ -2795,7 +2984,7 @@ async function planAcross(clients, url, init) {
|
|
|
2795
2984
|
const status = best ? "ready" : options.some((o) => o.state === "unknown") ? "unknown" : "blocked";
|
|
2796
2985
|
return {
|
|
2797
2986
|
url,
|
|
2798
|
-
network: _nullishCoalesce(_optionalChain([best, 'optionalAccess',
|
|
2987
|
+
network: _nullishCoalesce(_optionalChain([best, 'optionalAccess', _56 => _56.accept, 'access', _57 => _57.network]), () => ( live[0].network)),
|
|
2799
2988
|
status,
|
|
2800
2989
|
payable: best !== null,
|
|
2801
2990
|
best,
|
|
@@ -2808,6 +2997,20 @@ function railOnNetwork(rail, matches) {
|
|
|
2808
2997
|
const n = normalizeNetwork(rail.network);
|
|
2809
2998
|
return !n.includes(":") || matches(n);
|
|
2810
2999
|
}
|
|
3000
|
+
function reasonCodeForPolicy(code) {
|
|
3001
|
+
switch (code) {
|
|
3002
|
+
case "SESSION_EXPIRED":
|
|
3003
|
+
return "SESSION_EXPIRED";
|
|
3004
|
+
case "WINDOW_TOTAL":
|
|
3005
|
+
return "OUTSIDE_WINDOW";
|
|
3006
|
+
case "MAX_TOTAL":
|
|
3007
|
+
return "BUDGET";
|
|
3008
|
+
case void 0:
|
|
3009
|
+
return void 0;
|
|
3010
|
+
default:
|
|
3011
|
+
return "POLICY";
|
|
3012
|
+
}
|
|
3013
|
+
}
|
|
2811
3014
|
function hostOf2(url) {
|
|
2812
3015
|
try {
|
|
2813
3016
|
return new URL(url).hostname;
|
|
@@ -2828,8 +3031,8 @@ function isReplayableBodyInit(value) {
|
|
|
2828
3031
|
async function readInvalidReason(response) {
|
|
2829
3032
|
try {
|
|
2830
3033
|
const body = await response.clone().json();
|
|
2831
|
-
const ext = _optionalChain([body, 'optionalAccess',
|
|
2832
|
-
const piprail = _optionalChain([ext, 'optionalAccess',
|
|
3034
|
+
const ext = _optionalChain([body, 'optionalAccess', _58 => _58.extensions]);
|
|
3035
|
+
const piprail = _optionalChain([ext, 'optionalAccess', _59 => _59.piprail]);
|
|
2833
3036
|
if (piprail && typeof piprail.code === "string") {
|
|
2834
3037
|
return {
|
|
2835
3038
|
error: piprail.code,
|
|
@@ -2851,11 +3054,115 @@ async function readInvalidReason(response) {
|
|
|
2851
3054
|
} catch (e24) {
|
|
2852
3055
|
}
|
|
2853
3056
|
const settle = parseSettleResponse(response);
|
|
2854
|
-
if (_optionalChain([settle, 'optionalAccess',
|
|
3057
|
+
if (_optionalChain([settle, 'optionalAccess', _60 => _60.errorReason])) return { error: settle.errorReason, detail: "" };
|
|
2855
3058
|
return null;
|
|
2856
3059
|
}
|
|
2857
3060
|
|
|
3061
|
+
// src/render.ts
|
|
3062
|
+
function summarizePlan(plan) {
|
|
3063
|
+
if (plan == null) return "No payment required \u2014 the URL is not payment-gated.";
|
|
3064
|
+
if (plan.payable && plan.best) {
|
|
3065
|
+
const q = plan.best.quote;
|
|
3066
|
+
const c = plan.best.cost;
|
|
3067
|
+
const otherRails = plan.options.length - 1;
|
|
3068
|
+
const note = otherRails > 0 ? ` ${otherRails} other rail(s) not settleable.` : "";
|
|
3069
|
+
return `Payable: ${q.amountFormatted} ${_nullishCoalesce(q.symbol, () => ( q.asset))} on ${plan.best.accept.network} (gas ~${c.feeFormatted} ${c.feeSymbol}).${note}`;
|
|
3070
|
+
}
|
|
3071
|
+
return `NOT payable: ${_nullishCoalesce(plan.fundingHint, () => ( `no settleable rail on ${plan.network}`))}`;
|
|
3072
|
+
}
|
|
3073
|
+
function explainDecline(err) {
|
|
3074
|
+
if (!(err instanceof _chunkPA6YD3HLcjs.PipRailError)) {
|
|
3075
|
+
return `Payment failed: ${err instanceof Error ? err.message : String(err)}`;
|
|
3076
|
+
}
|
|
3077
|
+
switch (err.code) {
|
|
3078
|
+
case "PAYMENT_DECLINED":
|
|
3079
|
+
return err.message;
|
|
3080
|
+
case "PAYMENT_TIMEOUT":
|
|
3081
|
+
case "MAX_RETRIES_EXCEEDED":
|
|
3082
|
+
case "CONFIRMATION_TIMEOUT":
|
|
3083
|
+
return `${err.message} Recover using the proof on .ref (re-verify or re-submit it); never re-pay \u2014 a fresh payment would double-spend.`;
|
|
3084
|
+
case "INSUFFICIENT_FUNDS":
|
|
3085
|
+
return "The wallet cannot cover the payment + gas \u2014 top up the payer (token and/or native gas) and retry.";
|
|
3086
|
+
case "RECIPIENT_NOT_READY":
|
|
3087
|
+
return `${err.message} The fix is on the RECIPIENT (trustline / registration / opt-in / activation), not your balance.`;
|
|
3088
|
+
case "NO_COMPATIBLE_ACCEPT":
|
|
3089
|
+
case "UNSUPPORTED_SCHEME":
|
|
3090
|
+
return err.message;
|
|
3091
|
+
default:
|
|
3092
|
+
return `Payment failed: ${err.message}`;
|
|
3093
|
+
}
|
|
3094
|
+
}
|
|
3095
|
+
function formatSpendReport(summary) {
|
|
3096
|
+
if (summary.count === 0) return "No payments yet.";
|
|
3097
|
+
return summary.byAsset.map(
|
|
3098
|
+
(a) => `${a.totalFormatted} ${_nullishCoalesce(a.symbol, () => ( a.asset))} on ${a.network} (${a.count} payment${a.count === 1 ? "" : "s"})`
|
|
3099
|
+
).join("; ");
|
|
3100
|
+
}
|
|
3101
|
+
|
|
3102
|
+
// src/agentGuide.ts
|
|
3103
|
+
var PIPRAIL_AGENT_GUIDE = `# Paying with PipRail \u2014 the agent contract
|
|
3104
|
+
|
|
3105
|
+
You can pay for x402 "402 Payment Required" resources autonomously. Money moves
|
|
3106
|
+
straight from your wallet to the server; PipRail custodies nothing. Follow this.
|
|
3107
|
+
|
|
3108
|
+
## The loop: quote \u2192 plan \u2192 pay
|
|
3109
|
+
1. piprail_quote_payment(url) \u2014 PRICE it. Returns the amount, token, chain, and
|
|
3110
|
+
whether it is within your spend policy. No funds move. Use it to decide if a
|
|
3111
|
+
resource is worth buying.
|
|
3112
|
+
2. piprail_plan_payment(url) \u2014 can I afford it NOW? Reads your balance, native gas,
|
|
3113
|
+
and recipient-readiness across every rail, and returns { payable, best,
|
|
3114
|
+
fundingHint, session? }. If payable is false, do NOT attempt the payment \u2014
|
|
3115
|
+
fundingHint says exactly what to fix.
|
|
3116
|
+
3. piprail_pay_request(url, method?, body?) \u2014 PAY (only if the plan was payable)
|
|
3117
|
+
and return the result.
|
|
3118
|
+
Always plan before you pay so you never commit to a payment you cannot finish.
|
|
3119
|
+
|
|
3120
|
+
## Reading a refusal \u2014 never crash, never double-spend
|
|
3121
|
+
A failed pay returns a STRUCTURED object, never a thrown error you must catch:
|
|
3122
|
+
{ ok:false, code, reason, explain, ref?, reasonCode?, declined? }
|
|
3123
|
+
Branch on \`code\` (always reliable). Key cases:
|
|
3124
|
+
- declined:true with reasonCode:'SESSION_EXPIRED' \u2014 your time budget is over. This
|
|
3125
|
+
is TERMINAL: STOP. Do not retry ANY payment this process; it cannot be undone
|
|
3126
|
+
without a restart / a longer TTL.
|
|
3127
|
+
- declined:true with reasonCode:'APPROVAL' \u2014 a human (or hook) declined this
|
|
3128
|
+
payment. Terminal for this pay: do NOT auto-retry \u2014 they said no, or no one
|
|
3129
|
+
answered.
|
|
3130
|
+
- declined:true with reasonCode:'OUTSIDE_WINDOW' \u2014 your rolling rate-limit is
|
|
3131
|
+
exhausted. Wait for it to free, then retry; do not raise the amount.
|
|
3132
|
+
- declined:true with reasonCode:'POLICY' or 'BUDGET' \u2014 a spend cap or allowlist
|
|
3133
|
+
refused it. Don't retry the same payment; pick a cheaper/allowed one.
|
|
3134
|
+
- code:'INSUFFICIENT_FUNDS' \u2014 top up the wallet (token and/or native gas), retry.
|
|
3135
|
+
- code:'PAYMENT_TIMEOUT' / 'MAX_RETRIES_EXCEEDED' / 'CONFIRMATION_TIMEOUT' \u2014 the
|
|
3136
|
+
payment may ALREADY be on-chain. Recover using the proof on \`.ref\` (re-verify
|
|
3137
|
+
or re-submit it); never re-pay \u2014 a fresh payment would double-spend.
|
|
3138
|
+
- code:'NO_COMPATIBLE_ACCEPT' / 'UNSUPPORTED_SCHEME' \u2014 the 402 isn't payable on
|
|
3139
|
+
your chain/scheme; \`explain\` says whether it's the wrong chain or a scheme to enable.
|
|
3140
|
+
|
|
3141
|
+
## Knowing your leash \u2014 call piprail_budget
|
|
3142
|
+
piprail_budget tells you how much budget and time you have left, per
|
|
3143
|
+
(network, asset), plus your spend so far. Read-only; moves no funds. Use it in
|
|
3144
|
+
Mode A to self-check before paying.
|
|
3145
|
+
|
|
3146
|
+
## Two modes
|
|
3147
|
+
- Mode A (headless, default): you run FREE inside a pre-set budget + time
|
|
3148
|
+
envelope. The policy IS the consent \u2014 there is no per-payment prompt. Stay
|
|
3149
|
+
inside it; piprail_budget shows what's left.
|
|
3150
|
+
- Mode B (supervised): the host may ask a human to approve each payment. A
|
|
3151
|
+
decline/cancel/timeout comes back as declined:true (reasonCode:'APPROVAL') \u2014
|
|
3152
|
+
do NOT retry it as if it were a transient error.
|
|
3153
|
+
|
|
3154
|
+
## Hard facts
|
|
3155
|
+
- Spend caps are PER (network, asset). There is no single cross-token dollar cap \u2014
|
|
3156
|
+
budgets aren't summed across tokens (no price oracle).
|
|
3157
|
+
- Spend totals and the time envelope live IN-MEMORY for THIS process; they reset on restart
|
|
3158
|
+
(a convenience, not a durable ledger).
|
|
3159
|
+
`;
|
|
3160
|
+
function agentGuide() {
|
|
3161
|
+
return PIPRAIL_AGENT_GUIDE;
|
|
3162
|
+
}
|
|
3163
|
+
|
|
2858
3164
|
// src/agent.ts
|
|
3165
|
+
var OPEN_OBJECT = { type: "object", additionalProperties: true };
|
|
2859
3166
|
async function readBody(res) {
|
|
2860
3167
|
const text = await res.text();
|
|
2861
3168
|
if (!text) return null;
|
|
@@ -2928,6 +3235,7 @@ function paymentTools(client) {
|
|
|
2928
3235
|
required: ["url"],
|
|
2929
3236
|
additionalProperties: false
|
|
2930
3237
|
},
|
|
3238
|
+
outputSchema: OPEN_OBJECT,
|
|
2931
3239
|
invoke: async (args) => {
|
|
2932
3240
|
const quote = await client.quote(String(args.url));
|
|
2933
3241
|
return quote ? { gated: true, ...quote } : { gated: false, url: String(args.url) };
|
|
@@ -2951,6 +3259,7 @@ function paymentTools(client) {
|
|
|
2951
3259
|
required: ["url"],
|
|
2952
3260
|
additionalProperties: false
|
|
2953
3261
|
},
|
|
3262
|
+
outputSchema: OPEN_OBJECT,
|
|
2954
3263
|
invoke: async (args) => {
|
|
2955
3264
|
const plan = await client.planPayment(String(args.url));
|
|
2956
3265
|
if (plan == null) return { gated: false, url: String(args.url) };
|
|
@@ -2959,6 +3268,8 @@ function paymentTools(client) {
|
|
|
2959
3268
|
payable: plan.payable,
|
|
2960
3269
|
status: plan.status,
|
|
2961
3270
|
fundingHint: plan.fundingHint,
|
|
3271
|
+
// One model-readable line distilling the whole plan.
|
|
3272
|
+
summary: summarizePlan(plan),
|
|
2962
3273
|
best: plan.best ? {
|
|
2963
3274
|
network: plan.best.accept.network,
|
|
2964
3275
|
symbol: plan.best.quote.symbol,
|
|
@@ -2974,7 +3285,9 @@ function paymentTools(client) {
|
|
|
2974
3285
|
blockers: o.blockers,
|
|
2975
3286
|
warnings: o.warnings,
|
|
2976
3287
|
recipientReady: o.recipient.ready
|
|
2977
|
-
}))
|
|
3288
|
+
})),
|
|
3289
|
+
// The session's time leash, present only when a time policy is configured.
|
|
3290
|
+
...plan.session ? { session: plan.session } : {}
|
|
2978
3291
|
};
|
|
2979
3292
|
}
|
|
2980
3293
|
},
|
|
@@ -3032,8 +3345,20 @@ function paymentTools(client) {
|
|
|
3032
3345
|
receipt: parseReceipt(res)
|
|
3033
3346
|
};
|
|
3034
3347
|
} catch (err) {
|
|
3035
|
-
if (err instanceof
|
|
3036
|
-
|
|
3348
|
+
if (err instanceof _chunkPA6YD3HLcjs.PipRailError) {
|
|
3349
|
+
const out = {
|
|
3350
|
+
ok: false,
|
|
3351
|
+
code: err.code,
|
|
3352
|
+
reason: err.message,
|
|
3353
|
+
explain: explainDecline(err)
|
|
3354
|
+
};
|
|
3355
|
+
if (err instanceof _chunkPA6YD3HLcjs.PaymentDeclinedError) {
|
|
3356
|
+
out.declined = true;
|
|
3357
|
+
if (err.reasonCode) out.reasonCode = err.reasonCode;
|
|
3358
|
+
}
|
|
3359
|
+
const ref = err.ref;
|
|
3360
|
+
if (typeof ref === "string") out.ref = ref;
|
|
3361
|
+
return out;
|
|
3037
3362
|
}
|
|
3038
3363
|
throw err;
|
|
3039
3364
|
}
|
|
@@ -3071,10 +3396,57 @@ function paymentTools(client) {
|
|
|
3071
3396
|
const outcomes = await client.register(String(args.url), opts);
|
|
3072
3397
|
return { outcomes };
|
|
3073
3398
|
}
|
|
3399
|
+
},
|
|
3400
|
+
{
|
|
3401
|
+
name: "piprail_budget",
|
|
3402
|
+
description: "Read how much of your spend budget and time leash is left \u2014 per (network, asset) remaining, the session time envelope, and your spend so far. Use it in Mode A (headless) to self-check BEFORE paying, so you never discover the leash by hitting a decline. Read-only; moves no funds. NOTE: totals and the time envelope are in-memory for THIS process and reset on restart.",
|
|
3403
|
+
annotations: {
|
|
3404
|
+
title: "Check remaining budget",
|
|
3405
|
+
readOnlyHint: true,
|
|
3406
|
+
// reads the in-memory ledger + policy; never pays
|
|
3407
|
+
idempotentHint: true
|
|
3408
|
+
// a pure read
|
|
3409
|
+
},
|
|
3410
|
+
parameters: { type: "object", properties: {}, additionalProperties: false },
|
|
3411
|
+
outputSchema: OPEN_OBJECT,
|
|
3412
|
+
invoke: async () => {
|
|
3413
|
+
const spent = client.spent();
|
|
3414
|
+
const budget = client.budget();
|
|
3415
|
+
return {
|
|
3416
|
+
spent,
|
|
3417
|
+
remaining: budget.byAsset,
|
|
3418
|
+
session: budget.session,
|
|
3419
|
+
report: formatSpendReport(spent)
|
|
3420
|
+
};
|
|
3421
|
+
}
|
|
3422
|
+
},
|
|
3423
|
+
{
|
|
3424
|
+
name: "piprail_guide",
|
|
3425
|
+
description: "Read the PipRail agent contract \u2014 the quote \u2192 plan \u2192 pay loop, how to read a refusal (and which declines are TERMINAL), the never-re-pay rule for broadcast-but-unconfirmed payments, and Mode A (headless) vs Mode B (supervised). Read-only; call it once if unsure how to use these tools.",
|
|
3426
|
+
annotations: {
|
|
3427
|
+
title: "How to use PipRail",
|
|
3428
|
+
readOnlyHint: true,
|
|
3429
|
+
idempotentHint: true
|
|
3430
|
+
},
|
|
3431
|
+
parameters: { type: "object", properties: {}, additionalProperties: false },
|
|
3432
|
+
invoke: async () => ({ guide: PIPRAIL_AGENT_GUIDE })
|
|
3074
3433
|
}
|
|
3075
3434
|
];
|
|
3076
3435
|
}
|
|
3077
3436
|
|
|
3437
|
+
// src/classify.ts
|
|
3438
|
+
function classifyChallenge(challenge, opts) {
|
|
3439
|
+
const accepts = _nullishCoalesce(challenge.accepts, () => ( []));
|
|
3440
|
+
const offeredSchemes = [...new Set(accepts.map((a) => a.scheme))];
|
|
3441
|
+
const offeredNetworks = [...new Set(accepts.map((a) => a.network))];
|
|
3442
|
+
const onClientChain = accepts.some((a) => a.network === opts.network);
|
|
3443
|
+
const payableScheme = accepts.some(
|
|
3444
|
+
(a) => a.network === opts.network && opts.schemes.includes(a.scheme)
|
|
3445
|
+
);
|
|
3446
|
+
const verdict = accepts.length === 0 ? "NO_RAIL" : payableScheme ? "PAYABLE_RAIL" : onClientChain ? "UNPAYABLE_SCHEME" : "WRONG_CHAIN";
|
|
3447
|
+
return { onClientChain, payableScheme, offeredSchemes, offeredNetworks, verdict };
|
|
3448
|
+
}
|
|
3449
|
+
|
|
3078
3450
|
// src/discovery.ts
|
|
3079
3451
|
var GENERATOR = "@piprail/sdk \xB7 https://piprail.com";
|
|
3080
3452
|
function buildBazaarExtension(descriptor = {}) {
|
|
@@ -3196,13 +3568,13 @@ async function settleViaFacilitator(input) {
|
|
|
3196
3568
|
try {
|
|
3197
3569
|
verify = await post(`${base2}/verify`, body, auth);
|
|
3198
3570
|
} catch (err) {
|
|
3199
|
-
throw new (0,
|
|
3571
|
+
throw new (0, _chunkPA6YD3HLcjs.SettlementError)(
|
|
3200
3572
|
`exact settle (facilitator ${base2}): /verify request failed (${err instanceof Error ? err.message : String(err)}).`,
|
|
3201
3573
|
{ cause: err }
|
|
3202
3574
|
);
|
|
3203
3575
|
}
|
|
3204
3576
|
if (verify.status !== 200) {
|
|
3205
|
-
throw new (0,
|
|
3577
|
+
throw new (0, _chunkPA6YD3HLcjs.SettlementError)(
|
|
3206
3578
|
`exact settle (facilitator ${base2}): /verify returned HTTP ${verify.status} (transport/auth error).`
|
|
3207
3579
|
);
|
|
3208
3580
|
}
|
|
@@ -3218,13 +3590,13 @@ async function settleViaFacilitator(input) {
|
|
|
3218
3590
|
try {
|
|
3219
3591
|
settle = await post(`${base2}/settle`, body, auth);
|
|
3220
3592
|
} catch (err) {
|
|
3221
|
-
throw new (0,
|
|
3593
|
+
throw new (0, _chunkPA6YD3HLcjs.SettlementError)(
|
|
3222
3594
|
`exact settle (facilitator ${base2}): /settle request failed (${err instanceof Error ? err.message : String(err)}).`,
|
|
3223
3595
|
{ cause: err }
|
|
3224
3596
|
);
|
|
3225
3597
|
}
|
|
3226
3598
|
if (settle.status !== 200) {
|
|
3227
|
-
throw new (0,
|
|
3599
|
+
throw new (0, _chunkPA6YD3HLcjs.SettlementError)(
|
|
3228
3600
|
`exact settle (facilitator ${base2}): /settle returned HTTP ${settle.status} (transport/auth error).`
|
|
3229
3601
|
);
|
|
3230
3602
|
}
|
|
@@ -3290,7 +3662,7 @@ function createPaymentGate(options) {
|
|
|
3290
3662
|
}
|
|
3291
3663
|
net.assertValidPayTo(payTo);
|
|
3292
3664
|
const { asset, decimals, symbol } = net.resolveToken(a.token);
|
|
3293
|
-
const amountBase =
|
|
3665
|
+
const amountBase = _chunkPA6YD3HLcjs.parseUnits.call(void 0, a.amount, decimals);
|
|
3294
3666
|
const spec = { net, asset, decimals, symbol, amountBase, amountFormatted: a.amount, payTo };
|
|
3295
3667
|
if (options.exact) spec.exact = await resolveExactRail(net, asset);
|
|
3296
3668
|
return spec;
|
|
@@ -3405,7 +3777,7 @@ function createPaymentGate(options) {
|
|
|
3405
3777
|
const specs = await ready();
|
|
3406
3778
|
const nonce = genNonce();
|
|
3407
3779
|
const bazaar = options.discovery ? { bazaar: buildBazaarExtension(options.discovery === true ? {} : options.discovery) } : void 0;
|
|
3408
|
-
const extensions = { ...bazaar, ..._optionalChain([opts, 'optionalAccess',
|
|
3780
|
+
const extensions = { ...bazaar, ..._optionalChain([opts, 'optionalAccess', _61 => _61.extensions]) };
|
|
3409
3781
|
const challenge2 = {
|
|
3410
3782
|
x402Version: 2,
|
|
3411
3783
|
resource: {
|
|
@@ -3413,7 +3785,7 @@ function createPaymentGate(options) {
|
|
|
3413
3785
|
...options.description ? { description: options.description } : {}
|
|
3414
3786
|
},
|
|
3415
3787
|
accepts: buildAccepts(specs, nonce),
|
|
3416
|
-
..._optionalChain([opts, 'optionalAccess',
|
|
3788
|
+
..._optionalChain([opts, 'optionalAccess', _62 => _62.error]) ? { error: opts.error } : {},
|
|
3417
3789
|
...Object.keys(extensions).length > 0 ? { extensions } : {}
|
|
3418
3790
|
};
|
|
3419
3791
|
return { challenge: challenge2, requiredHeader: buildChallengeHeader(challenge2) };
|
|
@@ -3572,7 +3944,7 @@ function requirePayment(options) {
|
|
|
3572
3944
|
try {
|
|
3573
3945
|
result = await gate.verify(_nullishCoalesce(req.headers[HEADER_SIGNATURE], () => ( req.headers[HEADER_SIGNATURE_V1])));
|
|
3574
3946
|
} catch (err) {
|
|
3575
|
-
if (err instanceof
|
|
3947
|
+
if (err instanceof _chunkPA6YD3HLcjs.SettlementError) {
|
|
3576
3948
|
res.status(502);
|
|
3577
3949
|
res.json({ x402Version: 2, error: "settlement_failed", detail: err.message });
|
|
3578
3950
|
return;
|
|
@@ -3669,4 +4041,10 @@ function normaliseHeader(value) {
|
|
|
3669
4041
|
|
|
3670
4042
|
|
|
3671
4043
|
|
|
3672
|
-
|
|
4044
|
+
|
|
4045
|
+
|
|
4046
|
+
|
|
4047
|
+
|
|
4048
|
+
|
|
4049
|
+
|
|
4050
|
+
exports.CHAINS = CHAINS; exports.ConfirmationTimeoutError = _chunkPA6YD3HLcjs.ConfirmationTimeoutError; exports.DIRECTORY_INFO = DIRECTORY_INFO; exports.EIP3009_TYPES = EIP3009_TYPES; exports.EXACT_NETWORK_SLUGS = EXACT_NETWORK_SLUGS; exports.GENERATOR = GENERATOR; exports.HEADER_REQUIRED = HEADER_REQUIRED; exports.HEADER_RESPONSE = HEADER_RESPONSE; exports.HEADER_RESPONSE_V1 = HEADER_RESPONSE_V1; exports.HEADER_SIGNATURE = HEADER_SIGNATURE; exports.HEADER_SIGNATURE_V1 = HEADER_SIGNATURE_V1; exports.InsufficientFundsError = _chunkPA6YD3HLcjs.InsufficientFundsError; exports.InvalidEnvelopeError = _chunkPA6YD3HLcjs.InvalidEnvelopeError; exports.MaxRetriesExceededError = _chunkPA6YD3HLcjs.MaxRetriesExceededError; exports.MissingDriverError = _chunkPA6YD3HLcjs.MissingDriverError; exports.NoCompatibleAcceptError = _chunkPA6YD3HLcjs.NoCompatibleAcceptError; exports.NonReplayableBodyError = _chunkPA6YD3HLcjs.NonReplayableBodyError; exports.PIPRAIL_AGENT_GUIDE = PIPRAIL_AGENT_GUIDE; exports.PaymentDeclinedError = _chunkPA6YD3HLcjs.PaymentDeclinedError; exports.PaymentTimeoutError = _chunkPA6YD3HLcjs.PaymentTimeoutError; exports.PipRailClient = PipRailClient; exports.PipRailError = _chunkPA6YD3HLcjs.PipRailError; exports.RecipientNotReadyError = _chunkPA6YD3HLcjs.RecipientNotReadyError; exports.SettlementError = _chunkPA6YD3HLcjs.SettlementError; exports.UnknownTokenError = _chunkPA6YD3HLcjs.UnknownTokenError; exports.UnsupportedNetworkError = _chunkPA6YD3HLcjs.UnsupportedNetworkError; exports.UnsupportedSchemeError = _chunkPA6YD3HLcjs.UnsupportedSchemeError; exports.WrongChainError = _chunkPA6YD3HLcjs.WrongChainError; exports.WrongFamilyError = _chunkPA6YD3HLcjs.WrongFamilyError; exports.agentGuide = agentGuide; exports.buildBazaarExtension = buildBazaarExtension; exports.buildChallengeHeader = buildChallengeHeader; exports.buildExactAuthorization = buildExactAuthorization; exports.buildExactSignatureHeader = buildExactSignatureHeader; exports.buildOpenApi = buildOpenApi; exports.buildReceiptHeader = buildReceiptHeader; exports.buildSignatureHeader = buildSignatureHeader; exports.buildWellKnownX402 = buildWellKnownX402; exports.buildX402DnsTxt = buildX402DnsTxt; exports.chainIdForExactNetwork = chainIdForExactNetwork; exports.claim402IndexDomain = claim402IndexDomain; exports.classifyChallenge = classifyChallenge; exports.createPaymentGate = createPaymentGate; exports.decorateOutcome = decorateOutcome; exports.eip3009Abi = eip3009Abi; exports.encodeXPaymentHeader = encodeXPaymentHeader; exports.evaluatePolicy = evaluatePolicy; exports.explainDecline = explainDecline; exports.formatSpendReport = formatSpendReport; exports.getDirectoryInfo = getDirectoryInfo; exports.normalizeNetwork = normalizeNetwork; exports.parseChallenge = parseChallenge; exports.parseExactPaymentHeader = parseExactPaymentHeader; exports.parseExactRequirements = parseExactRequirements; exports.parseReceipt = parseReceipt; exports.parseSettleResponse = parseSettleResponse; exports.parseSignatureHeader = parseSignatureHeader; exports.paymentTools = paymentTools; exports.pickAccept = pickAccept; exports.planAcross = planAcross; exports.readExactDomain = readExactDomain; exports.register402Index = register402Index; exports.registerDriver = registerDriver; exports.registerX402Scan = registerX402Scan; exports.requirePayment = requirePayment; exports.resolveChain = resolveChain; exports.searchOpenIndexes = searchOpenIndexes; exports.settleViaFacilitator = settleViaFacilitator; exports.summarizePlan = summarizePlan; exports.toInsufficientFundsError = _chunkPA6YD3HLcjs.toInsufficientFundsError; exports.toInvalidBody = toInvalidBody; exports.verify402IndexDomain = verify402IndexDomain;
|