@piprail/sdk 1.6.0 → 1.8.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
@@ -737,6 +737,17 @@ function makeEvmNetwork(resolved) {
737
737
  async recipientReady() {
738
738
  return { ready: "n/a" };
739
739
  },
740
+ // Discovery only (ownership proofs / SIWX) — never the payment path. Signs
741
+ // through the wallet client so it works for both { privateKey } (local) and
742
+ // bring-your-own { walletClient } (JSON-RPC) accounts. eip191 → recoverable
743
+ // with viem's recoverMessageAddress (how x402scan verifies origin ownership).
744
+ discoverySigner(wallet) {
745
+ const a = wallet._native;
746
+ return {
747
+ address: a.account.address,
748
+ signMessage: (message) => a.walletClient.signMessage({ account: a.account, message })
749
+ };
750
+ },
740
751
  async verify(ref, accept) {
741
752
  return verifyEvm({
742
753
  publicClient,
@@ -888,6 +899,334 @@ async function resolveNetwork2(opts) {
888
899
  return resolveNetwork(opts);
889
900
  }
890
901
 
902
+ // src/indexes.ts
903
+ var BAZAAR_URL = "https://api.cdp.coinbase.com/platform/v2/x402/discovery/resources";
904
+ var INDEX402_SEARCH = "https://402index.io/api/v1/services";
905
+ var INDEX402_REGISTER = "https://402index.io/api/v1/register";
906
+ var X402SCAN_REGISTER = "https://www.x402scan.com/api/x402/registry/register";
907
+ var USER_AGENT = "@piprail/sdk (+https://piprail.com)";
908
+ function clientHeaders(extra = {}) {
909
+ return { "user-agent": USER_AGENT, ...extra };
910
+ }
911
+ var SLUG_TO_CAIP2 = {
912
+ // EVM (the common index-reported slugs; others fall through to net.supports)
913
+ ethereum: "eip155:1",
914
+ base: "eip155:8453",
915
+ polygon: "eip155:137",
916
+ arbitrum: "eip155:42161",
917
+ optimism: "eip155:10",
918
+ avalanche: "eip155:43114",
919
+ bnb: "eip155:56",
920
+ bsc: "eip155:56",
921
+ // non-EVM families — values mirror each driver's bound caip2 exactly
922
+ solana: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
923
+ ton: "ton:-239",
924
+ tron: "tron:mainnet",
925
+ near: "near:mainnet",
926
+ sui: "sui:mainnet",
927
+ aptos: "aptos:1",
928
+ algorand: "algorand:wGHE2Pwdvd7S12BL5FaOP20EGYesN73k",
929
+ stellar: "stellar:pubnet",
930
+ xrpl: "xrpl:0"
931
+ };
932
+ function normalizeNetwork(network) {
933
+ if (network.includes(":")) return network;
934
+ return _nullishCoalesce(SLUG_TO_CAIP2[network.toLowerCase()], () => ( network));
935
+ }
936
+ async function searchOpenIndexes(opts = {}) {
937
+ const sources = _nullishCoalesce(opts.sources, () => ( ["bazaar", "402index"]));
938
+ const limit = _nullishCoalesce(opts.limit, () => ( 20));
939
+ const results = await Promise.all(
940
+ sources.map((source) => {
941
+ if (source === "bazaar") return safeSearch(() => searchBazaar(opts.query, limit, opts.signal));
942
+ if (source === "402index") return safeSearch(() => search402Index(opts.query, limit, opts.signal));
943
+ return Promise.resolve([]);
944
+ })
945
+ );
946
+ return dedupeByResource(results.flat());
947
+ }
948
+ async function safeSearch(run) {
949
+ try {
950
+ return await run();
951
+ } catch (e12) {
952
+ return [];
953
+ }
954
+ }
955
+ function dedupeByResource(items) {
956
+ const seen = /* @__PURE__ */ new Set();
957
+ const out = [];
958
+ for (const it of items) {
959
+ const key = it.resource;
960
+ if (!key || seen.has(key)) continue;
961
+ seen.add(key);
962
+ out.push(it);
963
+ }
964
+ return out;
965
+ }
966
+ async function searchBazaar(query, limit, signal) {
967
+ const res = await fetch(`${BAZAAR_URL}?limit=${encodeURIComponent(String(limit))}`, {
968
+ headers: clientHeaders({ accept: "application/json" }),
969
+ ...signal ? { signal } : {}
970
+ });
971
+ if (!res.ok) return [];
972
+ const body = await res.json();
973
+ const items = Array.isArray(body.items) ? body.items : [];
974
+ const mapped = items.map(mapBazaarItem).filter((r) => r !== null);
975
+ return query ? mapped.filter((r) => matchesQuery(r, query)) : mapped;
976
+ }
977
+ function mapBazaarItem(raw) {
978
+ if (!raw || typeof raw !== "object") return null;
979
+ const o = raw;
980
+ const resource = pickString(o, "resource", "url", "endpoint");
981
+ if (!resource) return null;
982
+ const meta = o.metadata && typeof o.metadata === "object" ? o.metadata : {};
983
+ return {
984
+ resource,
985
+ source: "bazaar",
986
+ rails: mapRails(o.accepts),
987
+ ...optionalString("name", pickString(meta, "name", "title")),
988
+ ...optionalString("description", _nullishCoalesce(pickString(meta, "description"), () => ( pickString(o, "description")))),
989
+ ...optionalString("category", pickString(meta, "category"))
990
+ };
991
+ }
992
+ async function search402Index(query, limit, signal) {
993
+ const qs = new URLSearchParams({ limit: String(limit) });
994
+ if (query) qs.set("q", query);
995
+ const res = await fetch(`${INDEX402_SEARCH}?${qs.toString()}`, {
996
+ headers: clientHeaders({ accept: "application/json" }),
997
+ ...signal ? { signal } : {}
998
+ });
999
+ if (!res.ok) return [];
1000
+ const body = await res.json();
1001
+ const list = firstArray(body, "services", "results", "items", "data");
1002
+ return list.map(map402IndexItem).filter((r) => r !== null).filter((r) => r.rails.length > 0);
1003
+ }
1004
+ function map402IndexItem(raw) {
1005
+ if (!raw || typeof raw !== "object") return null;
1006
+ const o = raw;
1007
+ const resource = pickString(o, "url", "resource", "endpoint");
1008
+ if (!resource) return null;
1009
+ const protocol = (_nullishCoalesce(pickString(o, "protocol"), () => ( "x402"))).toLowerCase();
1010
+ if (protocol !== "x402") return null;
1011
+ const rails = Array.isArray(o.accepts) ? mapRails(o.accepts) : railFrom402IndexFields(o);
1012
+ const priceUsd = pickNumber(o, "price_usd", "priceUsd", "price");
1013
+ return {
1014
+ resource,
1015
+ source: "402index",
1016
+ rails,
1017
+ ...priceUsd !== void 0 ? { priceUsd } : {},
1018
+ ...optionalString("name", pickString(o, "name", "title")),
1019
+ ...optionalString("description", pickString(o, "description")),
1020
+ ...optionalString("category", pickString(o, "category", "tag"))
1021
+ };
1022
+ }
1023
+ function railFrom402IndexFields(o) {
1024
+ const network = pickString(o, "payment_network", "network");
1025
+ const asset = pickString(o, "payment_asset", "asset", "token");
1026
+ if (!network && !asset) return [];
1027
+ return [
1028
+ {
1029
+ scheme: "exact",
1030
+ network: _nullishCoalesce(network, () => ( "unknown")),
1031
+ ...asset ? { asset } : {},
1032
+ ...optionalString("symbol", asset)
1033
+ }
1034
+ ];
1035
+ }
1036
+ async function register402Index(input) {
1037
+ try {
1038
+ const payload = {
1039
+ url: input.url,
1040
+ name: _nullishCoalesce(input.name, () => ( hostOf(input.url))),
1041
+ protocol: "x402",
1042
+ ...input.description ? { description: input.description } : {},
1043
+ ...typeof input.priceUsd === "number" ? { price_usd: input.priceUsd } : {},
1044
+ ...input.asset ? { payment_asset: input.asset } : {},
1045
+ ...input.network ? { payment_network: input.network } : {},
1046
+ ...input.method ? { http_method: input.method.toUpperCase() } : {},
1047
+ ...input.attribution ? { via: "@piprail/sdk" } : {}
1048
+ };
1049
+ const res = await fetch(INDEX402_REGISTER, {
1050
+ method: "POST",
1051
+ headers: clientHeaders({ "content-type": "application/json", accept: "application/json" }),
1052
+ body: JSON.stringify(payload)
1053
+ });
1054
+ if (res.ok) {
1055
+ return { source: "402index", ok: true, status: res.status, detail: "Listed on 402 Index (searchable at 402index.io)." };
1056
+ }
1057
+ const why = await readIndexError(res);
1058
+ return {
1059
+ source: "402index",
1060
+ ok: false,
1061
+ status: res.status,
1062
+ detail: why ? `402 Index rejected it (HTTP ${res.status}): ${why}` : `402 Index returned HTTP ${res.status}.`
1063
+ };
1064
+ } catch (err) {
1065
+ return { source: "402index", ok: false, detail: errMsg(err) };
1066
+ }
1067
+ }
1068
+ async function readIndexError(res) {
1069
+ try {
1070
+ const body = await res.json();
1071
+ const parts = [body.error, body.detail, body.message].filter(
1072
+ (p) => typeof p === "string" && p.length > 0
1073
+ );
1074
+ return parts.length ? [...new Set(parts)].join(" \u2014 ") : void 0;
1075
+ } catch (e13) {
1076
+ return void 0;
1077
+ }
1078
+ }
1079
+ async function registerX402Scan(input, signer) {
1080
+ try {
1081
+ const challengeRes = await fetch(X402SCAN_REGISTER, {
1082
+ method: "POST",
1083
+ headers: clientHeaders({ "content-type": "application/json", accept: "application/json" }),
1084
+ body: JSON.stringify({ url: input.url })
1085
+ });
1086
+ if (challengeRes.status !== 402) {
1087
+ return {
1088
+ source: "x402scan",
1089
+ ok: challengeRes.ok,
1090
+ status: challengeRes.status,
1091
+ detail: challengeRes.ok ? "Listed on x402scan." : `x402scan returned HTTP ${challengeRes.status} (expected a SIWX 402 challenge).`
1092
+ };
1093
+ }
1094
+ const info = await readSiwxInfo(challengeRes);
1095
+ if (!info) {
1096
+ return { source: "x402scan", ok: false, status: 402, detail: "x402scan SIWX challenge was unparseable." };
1097
+ }
1098
+ const resolvedInfo = { ...info, issuedAt: _nullishCoalesce(info.issuedAt, () => ( (/* @__PURE__ */ new Date()).toISOString())) };
1099
+ const message = formatSiweMessage(resolvedInfo, signer.address);
1100
+ const signature = await signer.signMessage(message);
1101
+ const header = encodeBase642(
1102
+ JSON.stringify({ ...resolvedInfo, address: signer.address, type: "eip191", message, signature })
1103
+ );
1104
+ const res = await fetch(X402SCAN_REGISTER, {
1105
+ method: "POST",
1106
+ headers: clientHeaders({
1107
+ "content-type": "application/json",
1108
+ accept: "application/json",
1109
+ "sign-in-with-x": header
1110
+ }),
1111
+ body: JSON.stringify({ url: input.url })
1112
+ });
1113
+ if (res.ok) {
1114
+ return { source: "x402scan", ok: true, status: res.status, detail: "Listed on x402scan (SIWX)." };
1115
+ }
1116
+ const why = await readIndexError(res);
1117
+ return {
1118
+ source: "x402scan",
1119
+ ok: false,
1120
+ status: res.status,
1121
+ detail: why ? `x402scan rejected it (HTTP ${res.status}): ${why}` : `x402scan returned HTTP ${res.status} after signing.`
1122
+ };
1123
+ } catch (err) {
1124
+ return { source: "x402scan", ok: false, detail: errMsg(err) };
1125
+ }
1126
+ }
1127
+ async function readSiwxInfo(res) {
1128
+ try {
1129
+ const body = await res.json();
1130
+ const ext = body.extensions;
1131
+ const siwx = _optionalChain([ext, 'optionalAccess', _2 => _2["sign-in-with-x"]]);
1132
+ const info = _nullishCoalesce(_optionalChain([siwx, 'optionalAccess', _3 => _3.info]), () => ( siwx));
1133
+ if (info && typeof info.domain === "string" && info.domain.length > 0 && typeof info.nonce === "string" && info.nonce.length > 0 && typeof info.uri === "string" && info.uri.length > 0) {
1134
+ return info;
1135
+ }
1136
+ return null;
1137
+ } catch (e14) {
1138
+ return null;
1139
+ }
1140
+ }
1141
+ function formatSiweMessage(info, address) {
1142
+ const chainId = info.chainId ? caip2ToChainId(info.chainId) : 1;
1143
+ const statement = info.statement && info.statement.trim() ? info.statement : void 0;
1144
+ const lines = [
1145
+ `${info.domain} wants you to sign in with your Ethereum account:`,
1146
+ address,
1147
+ "",
1148
+ ...statement ? [statement, ""] : [""],
1149
+ `URI: ${info.uri}`,
1150
+ "Version: 1",
1151
+ `Chain ID: ${chainId}`,
1152
+ `Nonce: ${info.nonce}`,
1153
+ `Issued At: ${info.issuedAt}`,
1154
+ ...info.expirationTime ? [`Expiration Time: ${info.expirationTime}`] : []
1155
+ ];
1156
+ return lines.join("\n");
1157
+ }
1158
+ function caip2ToChainId(caip2) {
1159
+ const m = /^eip155:(\d+)$/.exec(caip2);
1160
+ const n = m ? Number(m[1]) : Number(caip2);
1161
+ return Number.isSafeInteger(n) && n > 0 ? n : 1;
1162
+ }
1163
+ function mapRails(accepts) {
1164
+ if (!Array.isArray(accepts)) return [];
1165
+ const out = [];
1166
+ for (const raw of accepts) {
1167
+ if (!raw || typeof raw !== "object") continue;
1168
+ const a = raw;
1169
+ const network = pickString(a, "network");
1170
+ if (!network) continue;
1171
+ const extra = a.extra && typeof a.extra === "object" ? a.extra : {};
1172
+ out.push({
1173
+ scheme: _nullishCoalesce(pickString(a, "scheme"), () => ( "exact")),
1174
+ network,
1175
+ ...optionalString("asset", pickString(a, "asset")),
1176
+ ...optionalString("amount", pickString(a, "amount", "maxAmountRequired")),
1177
+ ...optionalString("payTo", pickString(a, "payTo")),
1178
+ ...optionalString("symbol", pickString(extra, "symbol"))
1179
+ });
1180
+ }
1181
+ return out;
1182
+ }
1183
+ function matchesQuery(r, query) {
1184
+ const q = query.toLowerCase();
1185
+ return r.resource.toLowerCase().includes(q) || (_nullishCoalesce(_optionalChain([r, 'access', _4 => _4.name, 'optionalAccess', _5 => _5.toLowerCase, 'call', _6 => _6(), 'access', _7 => _7.includes, 'call', _8 => _8(q)]), () => ( false))) || (_nullishCoalesce(_optionalChain([r, 'access', _9 => _9.description, 'optionalAccess', _10 => _10.toLowerCase, 'call', _11 => _11(), 'access', _12 => _12.includes, 'call', _13 => _13(q)]), () => ( false)));
1186
+ }
1187
+ function pickString(o, ...keys) {
1188
+ for (const k of keys) {
1189
+ const v = o[k];
1190
+ if (typeof v === "string" && v.length > 0) return v;
1191
+ }
1192
+ return void 0;
1193
+ }
1194
+ function pickNumber(o, ...keys) {
1195
+ for (const k of keys) {
1196
+ const v = o[k];
1197
+ if (typeof v === "number" && Number.isFinite(v)) return v;
1198
+ if (typeof v === "string" && /^\d+(\.\d+)?$/.test(v.trim())) {
1199
+ const n = Number(v.trim());
1200
+ if (Number.isFinite(n)) return n;
1201
+ }
1202
+ }
1203
+ return void 0;
1204
+ }
1205
+ function optionalString(field, value) {
1206
+ return value !== void 0 ? { [field]: value } : {};
1207
+ }
1208
+ function firstArray(o, ...keys) {
1209
+ for (const k of keys) {
1210
+ if (Array.isArray(o[k])) return o[k];
1211
+ }
1212
+ return Array.isArray(o) ? o : [];
1213
+ }
1214
+ function hostOf(url) {
1215
+ try {
1216
+ return new URL(url).hostname;
1217
+ } catch (e15) {
1218
+ return url;
1219
+ }
1220
+ }
1221
+ function errMsg(err) {
1222
+ return err instanceof Error ? err.message : String(err);
1223
+ }
1224
+ function encodeBase642(str) {
1225
+ if (typeof btoa === "function") return btoa(str);
1226
+ if (typeof Buffer !== "undefined") return Buffer.from(str, "utf8").toString("base64");
1227
+ throw new Error("No base64 encoder available in this runtime.");
1228
+ }
1229
+
891
1230
  // src/policy.ts
892
1231
  var ALLOW = { allowed: true };
893
1232
  var deny = (reason) => ({ allowed: false, reason });
@@ -981,7 +1320,7 @@ var SpendLedger = (_class = class {constructor() { _class.prototype.__init.call(
981
1320
  }
982
1321
  /** Running total (base units) already spent on this (network, asset). */
983
1322
  totalFor(network, asset) {
984
- return _nullishCoalesce(_optionalChain([this, 'access', _2 => _2.buckets, 'access', _3 => _3.get, 'call', _4 => _4(keyFor(network, asset)), 'optionalAccess', _5 => _5.total]), () => ( 0n));
1323
+ return _nullishCoalesce(_optionalChain([this, 'access', _14 => _14.buckets, 'access', _15 => _15.get, 'call', _16 => _16(keyFor(network, asset)), 'optionalAccess', _17 => _17.total]), () => ( 0n));
985
1324
  }
986
1325
  /** An immutable snapshot of all spend so far. */
987
1326
  summary() {
@@ -1030,7 +1369,7 @@ var PipRailClient = (_class2 = class {
1030
1369
  safeEmit(event) {
1031
1370
  try {
1032
1371
  this.onEvent(event);
1033
- } catch (e12) {
1372
+ } catch (e16) {
1034
1373
  }
1035
1374
  }
1036
1375
  /** Auto-mount the chain's driver, resolve the network, and bind the wallet — once. */
@@ -1055,7 +1394,7 @@ var PipRailClient = (_class2 = class {
1055
1394
  * as-is) or a plain object (serialised as JSON).
1056
1395
  */
1057
1396
  post(url, body, init) {
1058
- const headers = new Headers(_optionalChain([init, 'optionalAccess', _6 => _6.headers]));
1397
+ const headers = new Headers(_optionalChain([init, 'optionalAccess', _18 => _18.headers]));
1059
1398
  let payload;
1060
1399
  if (body === void 0 || body === null) {
1061
1400
  payload = void 0;
@@ -1086,7 +1425,7 @@ var PipRailClient = (_class2 = class {
1086
1425
  * "0.05 USDC on Base, within budget → pay it." No funds move.
1087
1426
  */
1088
1427
  async quote(url, init) {
1089
- const res = await fetch(url, { ..._nullishCoalesce(init, () => ( {})), method: _nullishCoalesce(_optionalChain([init, 'optionalAccess', _7 => _7.method]), () => ( "GET")) });
1428
+ const res = await fetch(url, { ..._nullishCoalesce(init, () => ( {})), method: _nullishCoalesce(_optionalChain([init, 'optionalAccess', _19 => _19.method]), () => ( "GET")) });
1090
1429
  if (res.status !== 402) return null;
1091
1430
  const { quote } = await this.resolveChallenge(url, res);
1092
1431
  return quote;
@@ -1105,7 +1444,7 @@ var PipRailClient = (_class2 = class {
1105
1444
  * on Tron, where a USD₮ transfer can cost real TRX.
1106
1445
  */
1107
1446
  async estimateCost(url, init) {
1108
- const res = await fetch(url, { ..._nullishCoalesce(init, () => ( {})), method: _nullishCoalesce(_optionalChain([init, 'optionalAccess', _8 => _8.method]), () => ( "GET")) });
1447
+ const res = await fetch(url, { ..._nullishCoalesce(init, () => ( {})), method: _nullishCoalesce(_optionalChain([init, 'optionalAccess', _20 => _20.method]), () => ( "GET")) });
1109
1448
  if (res.status !== 402) return null;
1110
1449
  const { net, accept, quote } = await this.resolveChallenge(url, res);
1111
1450
  const cost = await net.estimateCost(accept);
@@ -1136,7 +1475,7 @@ var PipRailClient = (_class2 = class {
1136
1475
  * the plan yourself. No funds move.
1137
1476
  */
1138
1477
  async planPayment(url, init) {
1139
- const res = await fetch(url, { ..._nullishCoalesce(init, () => ( {})), method: _nullishCoalesce(_optionalChain([init, 'optionalAccess', _9 => _9.method]), () => ( "GET")) });
1478
+ const res = await fetch(url, { ..._nullishCoalesce(init, () => ( {})), method: _nullishCoalesce(_optionalChain([init, 'optionalAccess', _21 => _21.method]), () => ( "GET")) });
1140
1479
  if (res.status !== 402) return null;
1141
1480
  const challenge = await parseChallenge(res);
1142
1481
  if (!challenge) {
@@ -1154,6 +1493,100 @@ var PipRailClient = (_class2 = class {
1154
1493
  const plan = await this.planPayment(url, init);
1155
1494
  return plan == null ? true : plan.payable;
1156
1495
  }
1496
+ /* ------------------------- discovery (find + list) ------------------------- */
1497
+ /**
1498
+ * Find payable resources on the OPEN x402 indexes — WITHOUT paying. Reads the
1499
+ * free indexes (CDP Bazaar + 402 Index by default), merges + dedupes them, and
1500
+ * by default returns only resources payable on THIS client's chain
1501
+ * (`network: 'self'`). Each result carries its advertised `rails[]`; feed a
1502
+ * chosen `resource` straight into `quote()` → `planPayment()` → `fetch()`.
1503
+ *
1504
+ * Nothing PipRail-hosted: these are third-party open directories. Never throws
1505
+ * for a read problem — an index that's down or changed simply contributes
1506
+ * nothing. Honest caveat: index results are cross-scheme (mostly the
1507
+ * mainstream `exact` scheme); `fetch()` pays only `onchain-proof` rails
1508
+ * directly (pay `exact` resources with the experimental `drivers/evm/exact.ts`).
1509
+ */
1510
+ async discover(opts = {}) {
1511
+ const found = await searchOpenIndexes({
1512
+ ...opts.query !== void 0 ? { query: opts.query } : {},
1513
+ ...opts.sources ? { sources: opts.sources } : {},
1514
+ ...opts.limit !== void 0 ? { limit: opts.limit } : {}
1515
+ });
1516
+ const scope = _nullishCoalesce(opts.network, () => ( "self"));
1517
+ let out = found;
1518
+ if (scope === "self") {
1519
+ const { net } = await this.ensure();
1520
+ out = out.filter((r) => r.rails.some((rail) => railOnNetwork(rail, (n) => net.supports(n))));
1521
+ } else if (scope !== "any") {
1522
+ const target = normalizeNetwork(scope);
1523
+ out = out.filter((r) => r.rails.some((rail) => railOnNetwork(rail, (n) => n === target)));
1524
+ }
1525
+ if (opts.maxPrice !== void 0) {
1526
+ const max = opts.maxPrice;
1527
+ out = out.filter((r) => r.priceUsd === void 0 || r.priceUsd <= max);
1528
+ }
1529
+ return out;
1530
+ }
1531
+ /**
1532
+ * List a resource you run on the OPEN x402 registries, so agents can find it.
1533
+ * Default target is **402 Index** — one POST, no auth, no signature, no payment
1534
+ * (searchable within seconds). Add `'x402scan'` to also register via SIWX (one
1535
+ * wallet signature; EVM + a Base/Solana rail). Returns one {@link RegisterOutcome}
1536
+ * per target — a target the chain can't satisfy comes back `{ ok:false, detail }`,
1537
+ * never a throw. An explicit, developer-invoked action; it moves no funds, and
1538
+ * nothing is PipRail-hosted — you're listing on third-party open directories.
1539
+ */
1540
+ async register(url, opts = {}) {
1541
+ const targets = _nullishCoalesce(opts.targets, () => ( ["402index"]));
1542
+ const networkSlug = _nullishCoalesce(opts.network, () => ( (typeof this.opts.chain === "string" ? this.opts.chain : void 0)));
1543
+ const outcomes = [];
1544
+ for (const target of targets) {
1545
+ if (target === "402index") {
1546
+ outcomes.push(
1547
+ await register402Index({
1548
+ url,
1549
+ ...opts.name ? { name: opts.name } : {},
1550
+ ...opts.description ? { description: opts.description } : {},
1551
+ ...opts.priceUsd !== void 0 ? { priceUsd: opts.priceUsd } : {},
1552
+ ...opts.asset ? { asset: opts.asset } : {},
1553
+ ...networkSlug ? { network: networkSlug } : {},
1554
+ ...opts.method ? { method: opts.method } : {},
1555
+ ...opts.attribution ? { attribution: true } : {}
1556
+ })
1557
+ );
1558
+ } else if (target === "x402scan") {
1559
+ const signer = await this.discoverySigner();
1560
+ if (!signer) {
1561
+ outcomes.push({
1562
+ source: "x402scan",
1563
+ ok: false,
1564
+ detail: "x402scan registration needs an EVM signer; this chain family has no discoverySigner. Use 402 Index (the default), which needs no signature."
1565
+ });
1566
+ continue;
1567
+ }
1568
+ outcomes.push(await registerX402Scan({ url }, signer));
1569
+ } else {
1570
+ outcomes.push({
1571
+ source: "bazaar",
1572
+ ok: false,
1573
+ detail: "CDP Bazaar has no register endpoint \u2014 it catalogs a resource only when its facilitator settles a payment (PipRail uses no facilitator). List on 402 Index / x402scan instead."
1574
+ });
1575
+ }
1576
+ }
1577
+ return outcomes;
1578
+ }
1579
+ /**
1580
+ * The discovery signer for the bound wallet (its address + a message signer),
1581
+ * or `null` if the chain family doesn't support it (EVM does today). For
1582
+ * discovery only — ownership proofs (sign the bare origin string and pass it to
1583
+ * `buildOpenApi({ ownershipProofs })`) and SIWX registration. Never signs a
1584
+ * payment.
1585
+ */
1586
+ async discoverySigner() {
1587
+ const { net, wallet } = await this.ensure();
1588
+ return net.discoverySigner ? net.discoverySigner(wallet) : null;
1589
+ }
1157
1590
  /**
1158
1591
  * Lower-level: drive any HTTP method through the 402 flow.
1159
1592
  *
@@ -1162,7 +1595,7 @@ var PipRailClient = (_class2 = class {
1162
1595
  * streams throw `NonReplayableBodyError`.
1163
1596
  */
1164
1597
  async fetch(url, init) {
1165
- const body = _optionalChain([init, 'optionalAccess', _10 => _10.body]);
1598
+ const body = _optionalChain([init, 'optionalAccess', _22 => _22.body]);
1166
1599
  if (body !== void 0 && body !== null && !isReplayableBodyInit(body)) {
1167
1600
  throw new (0, _chunkIQGT65WScjs.NonReplayableBodyError)(
1168
1601
  "fetch(): init.body is not replayable. Pass a string, FormData, URLSearchParams, ArrayBuffer, or Blob \u2014 not a ReadableStream."
@@ -1174,7 +1607,7 @@ var PipRailClient = (_class2 = class {
1174
1607
  const { net, wallet, challenge } = resolved;
1175
1608
  let accept = resolved.accept;
1176
1609
  let quote = resolved.quote;
1177
- const autoRoute = _nullishCoalesce(_nullishCoalesce(_optionalChain([init, 'optionalAccess', _11 => _11.autoRoute]), () => ( this.opts.autoRoute)), () => ( false));
1610
+ const autoRoute = _nullishCoalesce(_nullishCoalesce(_optionalChain([init, 'optionalAccess', _23 => _23.autoRoute]), () => ( this.opts.autoRoute)), () => ( false));
1178
1611
  if (autoRoute) {
1179
1612
  const plan = await this.planFromChallenge(net, wallet, challenge, url);
1180
1613
  if (!plan.best) {
@@ -1333,11 +1766,11 @@ var PipRailClient = (_class2 = class {
1333
1766
  }
1334
1767
  const amountBase = BigInt(accept.amount);
1335
1768
  const described = net.describeAsset(accept.asset);
1336
- const decimals = _nullishCoalesce(_optionalChain([described, 'optionalAccess', _12 => _12.decimals]), () => ( accept.extra.decimals));
1337
- const symbol = _nullishCoalesce(_optionalChain([described, 'optionalAccess', _13 => _13.symbol]), () => ( accept.extra.symbol));
1769
+ const decimals = _nullishCoalesce(_optionalChain([described, 'optionalAccess', _24 => _24.decimals]), () => ( accept.extra.decimals));
1770
+ const symbol = _nullishCoalesce(_optionalChain([described, 'optionalAccess', _25 => _25.symbol]), () => ( accept.extra.symbol));
1338
1771
  const amountFormatted = _chunkIQGT65WScjs.formatUnits.call(void 0, amountBase, decimals);
1339
1772
  const intent = {
1340
- host: hostOf(url),
1773
+ host: hostOf2(url),
1341
1774
  chain: this.opts.chain,
1342
1775
  network: accept.network,
1343
1776
  asset: accept.asset,
@@ -1400,7 +1833,7 @@ var PipRailClient = (_class2 = class {
1400
1833
  this.ledger.record(
1401
1834
  {
1402
1835
  url: quote.url,
1403
- host: hostOf(quote.url),
1836
+ host: hostOf2(quote.url),
1404
1837
  network: quote.network,
1405
1838
  asset: quote.asset,
1406
1839
  amountBase: quote.amount,
@@ -1443,7 +1876,7 @@ var PipRailClient = (_class2 = class {
1443
1876
  accepted: accept,
1444
1877
  payload: { nonce: accept.extra.nonce, txHash: ref }
1445
1878
  };
1446
- const headers = new Headers(_optionalChain([originalInit, 'optionalAccess', _14 => _14.headers]));
1879
+ const headers = new Headers(_optionalChain([originalInit, 'optionalAccess', _26 => _26.headers]));
1447
1880
  headers.set(HEADER_SIGNATURE, buildSignatureHeader(signature));
1448
1881
  let lastResponse = null;
1449
1882
  let lastReason = null;
@@ -1458,7 +1891,7 @@ var PipRailClient = (_class2 = class {
1458
1891
  () => timeoutController.abort(),
1459
1892
  this.retryTimeoutMs
1460
1893
  );
1461
- const signal = _optionalChain([originalInit, 'optionalAccess', _15 => _15.signal]) && typeof AbortSignal.any === "function" ? AbortSignal.any([timeoutController.signal, originalInit.signal]) : timeoutController.signal;
1894
+ const signal = _optionalChain([originalInit, 'optionalAccess', _27 => _27.signal]) && typeof AbortSignal.any === "function" ? AbortSignal.any([timeoutController.signal, originalInit.signal]) : timeoutController.signal;
1462
1895
  try {
1463
1896
  lastResponse = await fetch(url, {
1464
1897
  ..._nullishCoalesce(originalInit, () => ( {})),
@@ -1498,7 +1931,7 @@ var PipRailClient = (_class2 = class {
1498
1931
  function safeBig(s) {
1499
1932
  try {
1500
1933
  return BigInt(s);
1501
- } catch (e13) {
1934
+ } catch (e17) {
1502
1935
  return 0n;
1503
1936
  }
1504
1937
  }
@@ -1531,10 +1964,10 @@ function buildFundingHint(options, chainLabel) {
1531
1964
  return `Couldn't fully read your wallet on ${chainLabel} (RPC throttled) \u2014 retry; you may already be able to pay ${target.quote.amountFormatted} ${sym}.`;
1532
1965
  }
1533
1966
  const parts = [];
1534
- if (target.blockers.includes("INSUFFICIENT_TOKEN") && _optionalChain([target, 'access', _16 => _16.shortfall, 'optionalAccess', _17 => _17.token])) {
1967
+ if (target.blockers.includes("INSUFFICIENT_TOKEN") && _optionalChain([target, 'access', _28 => _28.shortfall, 'optionalAccess', _29 => _29.token])) {
1535
1968
  parts.push(`top up ${target.shortfall.token} ${sym}`);
1536
1969
  }
1537
- if (target.blockers.includes("INSUFFICIENT_GAS") && _optionalChain([target, 'access', _18 => _18.shortfall, 'optionalAccess', _19 => _19.native])) {
1970
+ if (target.blockers.includes("INSUFFICIENT_GAS") && _optionalChain([target, 'access', _30 => _30.shortfall, 'optionalAccess', _31 => _31.native])) {
1538
1971
  parts.push(`add ~${target.shortfall.native} ${target.cost.feeSymbol} for gas`);
1539
1972
  }
1540
1973
  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}.`;
@@ -1548,7 +1981,7 @@ async function planAcross(clients, url, init) {
1548
1981
  const status = best ? "ready" : options.some((o) => o.state === "unknown") ? "unknown" : "blocked";
1549
1982
  return {
1550
1983
  url,
1551
- network: _nullishCoalesce(_optionalChain([best, 'optionalAccess', _20 => _20.accept, 'access', _21 => _21.network]), () => ( live[0].network)),
1984
+ network: _nullishCoalesce(_optionalChain([best, 'optionalAccess', _32 => _32.accept, 'access', _33 => _33.network]), () => ( live[0].network)),
1552
1985
  status,
1553
1986
  payable: best !== null,
1554
1987
  best,
@@ -1557,10 +1990,14 @@ async function planAcross(clients, url, init) {
1557
1990
  fundingHint: best ? null : _nullishCoalesce(live.map((p) => p.fundingHint).find(Boolean), () => ( null))
1558
1991
  };
1559
1992
  }
1560
- function hostOf(url) {
1993
+ function railOnNetwork(rail, matches) {
1994
+ const n = normalizeNetwork(rail.network);
1995
+ return !n.includes(":") || matches(n);
1996
+ }
1997
+ function hostOf2(url) {
1561
1998
  try {
1562
1999
  return new URL(url).hostname;
1563
- } catch (e14) {
2000
+ } catch (e18) {
1564
2001
  return url;
1565
2002
  }
1566
2003
  }
@@ -1583,7 +2020,7 @@ async function readInvalidReason(response) {
1583
2020
  detail: typeof body.detail === "string" ? body.detail : ""
1584
2021
  };
1585
2022
  }
1586
- } catch (e15) {
2023
+ } catch (e19) {
1587
2024
  }
1588
2025
  return null;
1589
2026
  }
@@ -1594,15 +2031,65 @@ async function readBody(res) {
1594
2031
  if (!text) return null;
1595
2032
  try {
1596
2033
  return JSON.parse(text);
1597
- } catch (e16) {
2034
+ } catch (e20) {
1598
2035
  return text;
1599
2036
  }
1600
2037
  }
1601
2038
  function paymentTools(client) {
1602
2039
  return [
2040
+ {
2041
+ name: "piprail_discover",
2042
+ description: `Find x402 payment-gated resources on the OPEN indexes (a phone book of payable APIs) WITHOUT paying. Use it to answer "what can I buy?" \u2014 search by topic, then quote/plan/pay a chosen one. By default returns only resources payable on your wallet's chain (network='self'); pass 'any' for every chain. Results are cross-scheme: ALWAYS call piprail_quote_payment on a chosen resource (it re-checks the live price) before piprail_pay_request.`,
2043
+ annotations: {
2044
+ title: "Discover payable x402 APIs",
2045
+ readOnlyHint: true,
2046
+ // reads the open indexes only; never pays
2047
+ openWorldHint: true
2048
+ // reaches external indexes (402 Index, CDP Bazaar)
2049
+ },
2050
+ parameters: {
2051
+ type: "object",
2052
+ properties: {
2053
+ query: { type: "string", description: "Free-text topic to search for (optional)." },
2054
+ network: {
2055
+ type: "string",
2056
+ description: "CAIP-2 id, 'self' (your chain \u2014 default), or 'any' (all chains)."
2057
+ },
2058
+ maxPrice: { type: "number", description: "Drop results advertised above this USD price." },
2059
+ limit: { type: "number", description: "Max results per index (default 20)." }
2060
+ },
2061
+ additionalProperties: false
2062
+ },
2063
+ invoke: async (args) => {
2064
+ const opts = {};
2065
+ if (typeof args.query === "string") opts.query = args.query;
2066
+ if (typeof args.network === "string") opts.network = args.network;
2067
+ if (typeof args.maxPrice === "number") opts.maxPrice = args.maxPrice;
2068
+ if (typeof args.limit === "number") opts.limit = args.limit;
2069
+ const found = await client.discover(opts);
2070
+ return {
2071
+ count: found.length,
2072
+ resources: found.map((r) => ({
2073
+ resource: r.resource,
2074
+ name: r.name,
2075
+ description: r.description,
2076
+ source: r.source,
2077
+ priceUsd: r.priceUsd,
2078
+ networks: [...new Set(r.rails.map((rail) => rail.network))]
2079
+ }))
2080
+ };
2081
+ }
2082
+ },
1603
2083
  {
1604
2084
  name: "piprail_quote_payment",
1605
2085
  description: "Get the price of an x402 payment-gated URL WITHOUT paying. Returns the amount, token, chain, recipient, and whether it is within the spend policy. Returns { gated: false } when the URL needs no payment. Call this first to decide whether a resource is worth buying.",
2086
+ annotations: {
2087
+ title: "Quote an x402 price",
2088
+ readOnlyHint: true,
2089
+ // reads the 402 challenge; never pays
2090
+ openWorldHint: true
2091
+ // fetches an arbitrary URL
2092
+ },
1606
2093
  parameters: {
1607
2094
  type: "object",
1608
2095
  properties: {
@@ -1619,6 +2106,13 @@ function paymentTools(client) {
1619
2106
  {
1620
2107
  name: "piprail_plan_payment",
1621
2108
  description: "Check whether you CAN pay an x402-gated URL before paying. Reads your wallet balance, native gas, and whether the recipient can receive \u2014 across every rail the URL offers on your chain \u2014 and returns { gated, payable, best, options, fundingHint }. payable:false means do NOT attempt the payment; fundingHint says exactly what to top up. Call this before piprail_pay_request so you never commit to a payment you cannot finish. Returns { gated: false } when no payment is needed.",
2109
+ annotations: {
2110
+ title: "Plan an x402 payment",
2111
+ readOnlyHint: true,
2112
+ // reads balances + the challenge; never pays
2113
+ openWorldHint: true
2114
+ // fetches a URL and reads chain state
2115
+ },
1622
2116
  parameters: {
1623
2117
  type: "object",
1624
2118
  properties: {
@@ -1657,6 +2151,17 @@ function paymentTools(client) {
1657
2151
  {
1658
2152
  name: "piprail_pay_request",
1659
2153
  description: "Fetch an x402 payment-gated URL, automatically paying the required on-chain payment if needed (subject to the spend policy + approval hook). Returns the HTTP status, the response body, and a payment receipt if one settled. If the payment is refused by policy or the approval hook, returns { declined: true, reason } \u2014 no funds moved.",
2154
+ annotations: {
2155
+ title: "Pay an x402 request",
2156
+ readOnlyHint: false,
2157
+ // this is the one tool that MOVES FUNDS
2158
+ destructiveHint: true,
2159
+ // an on-chain payment is value-moving and not reversible
2160
+ idempotentHint: false,
2161
+ // paying twice = two payments
2162
+ openWorldHint: true
2163
+ // fetches a URL and settles on-chain
2164
+ },
1660
2165
  parameters: {
1661
2166
  type: "object",
1662
2167
  properties: {
@@ -1703,6 +2208,39 @@ function paymentTools(client) {
1703
2208
  throw err;
1704
2209
  }
1705
2210
  }
2211
+ },
2212
+ {
2213
+ name: "piprail_register",
2214
+ description: "List an x402 payment-gated resource YOU run on the open indexes so other agents can discover it. Default target is 402 Index \u2014 no auth, no signature, no payment; searchable within seconds. Returns one outcome per index ({ source, ok, detail }); a step the chain can't satisfy comes back ok:false with the reason. Moves no funds; nothing is PipRail-hosted.",
2215
+ annotations: {
2216
+ title: "Register an x402 endpoint",
2217
+ readOnlyHint: false,
2218
+ // writes a listing to an external index
2219
+ destructiveHint: false,
2220
+ // adds a listing; nothing is destroyed and no funds move
2221
+ openWorldHint: true
2222
+ // posts to external indexes (402 Index)
2223
+ // idempotentHint intentionally omitted — index dedup behaviour isn't guaranteed.
2224
+ },
2225
+ parameters: {
2226
+ type: "object",
2227
+ properties: {
2228
+ url: { type: "string", description: "Full URL of the resource to list." },
2229
+ name: { type: "string", description: "Display name (defaults to the host)." },
2230
+ description: { type: "string", description: "What the resource offers." },
2231
+ priceUsd: { type: "number", description: "Advertised price in USD (metadata)." }
2232
+ },
2233
+ required: ["url"],
2234
+ additionalProperties: false
2235
+ },
2236
+ invoke: async (args) => {
2237
+ const opts = {};
2238
+ if (typeof args.name === "string") opts.name = args.name;
2239
+ if (typeof args.description === "string") opts.description = args.description;
2240
+ if (typeof args.priceUsd === "number") opts.priceUsd = args.priceUsd;
2241
+ const outcomes = await client.register(String(args.url), opts);
2242
+ return { outcomes };
2243
+ }
1706
2244
  }
1707
2245
  ];
1708
2246
  }
@@ -1805,6 +2343,25 @@ function createPaymentGate(options) {
1805
2343
  const { challenge: c, requiredHeader } = await challenge();
1806
2344
  return { kind: "challenge", challenge: c, requiredHeader, statusCode: 402 };
1807
2345
  }
2346
+ async function describe(resourceUrl = "") {
2347
+ const specs = await ready();
2348
+ const accepts = specs.map((s) => ({
2349
+ scheme: "onchain-proof",
2350
+ network: s.net.network,
2351
+ asset: s.asset,
2352
+ payTo: s.payTo,
2353
+ amount: s.amountBase.toString(),
2354
+ amountFormatted: s.amountFormatted,
2355
+ decimals: s.decimals,
2356
+ maxTimeoutSeconds,
2357
+ ...s.symbol ? { symbol: s.symbol } : {}
2358
+ }));
2359
+ return {
2360
+ url: resourceUrl,
2361
+ ...options.description ? { description: options.description } : {},
2362
+ accepts
2363
+ };
2364
+ }
1808
2365
  async function verify(paymentSignature) {
1809
2366
  const raw = normaliseHeader(paymentSignature);
1810
2367
  if (!raw) return asChallenge();
@@ -1847,7 +2404,7 @@ function createPaymentGate(options) {
1847
2404
  if (options.onPaid) {
1848
2405
  try {
1849
2406
  options.onPaid(result.receipt);
1850
- } catch (e17) {
2407
+ } catch (e21) {
1851
2408
  }
1852
2409
  }
1853
2410
  return {
@@ -1856,7 +2413,7 @@ function createPaymentGate(options) {
1856
2413
  receiptHeader: buildReceiptHeader(result.receipt)
1857
2414
  };
1858
2415
  }
1859
- return { challenge, verify };
2416
+ return { challenge, verify, describe };
1860
2417
  }
1861
2418
  function requirePayment(options) {
1862
2419
  const gate = createPaymentGate(options);
@@ -1954,8 +2511,8 @@ async function buildExactAuthorization(params) {
1954
2511
  };
1955
2512
  const signature = await account.signTypedData({
1956
2513
  domain: {
1957
- name: _nullishCoalesce(_optionalChain([accept, 'access', _22 => _22.extra, 'optionalAccess', _23 => _23.name]), () => ( "USD Coin")),
1958
- version: _nullishCoalesce(_optionalChain([accept, 'access', _24 => _24.extra, 'optionalAccess', _25 => _25.version]), () => ( "2")),
2514
+ name: _nullishCoalesce(_optionalChain([accept, 'access', _34 => _34.extra, 'optionalAccess', _35 => _35.name]), () => ( "USD Coin")),
2515
+ version: _nullishCoalesce(_optionalChain([accept, 'access', _36 => _36.extra, 'optionalAccess', _37 => _37.version]), () => ( "2")),
1959
2516
  chainId,
1960
2517
  verifyingContract: accept.asset
1961
2518
  },
@@ -1987,6 +2544,69 @@ function encodeXPaymentHeader(input) {
1987
2544
  return base64(JSON.stringify(payload));
1988
2545
  }
1989
2546
 
2547
+ // src/discovery.ts
2548
+ var GENERATOR = "@piprail/sdk \xB7 https://piprail.com";
2549
+ function pathOf(url) {
2550
+ try {
2551
+ return new URL(url).pathname || "/";
2552
+ } catch (e22) {
2553
+ return url.startsWith("/") ? url : `/${url}`;
2554
+ }
2555
+ }
2556
+ function buildOpenApi(input) {
2557
+ const paths = {};
2558
+ for (const r of input.resources) {
2559
+ const path = pathOf(r.url);
2560
+ const method = (_nullishCoalesce(r.method, () => ( "GET"))).toLowerCase();
2561
+ const op = {
2562
+ ...r.description ? { summary: r.description } : {},
2563
+ responses: {
2564
+ "200": { description: "Paid \u2014 the resource." },
2565
+ "402": { description: "Payment required (x402)." }
2566
+ },
2567
+ "x-payment-info": {
2568
+ x402Version: 2,
2569
+ accepts: r.accepts,
2570
+ bazaar: { discoverable: true }
2571
+ }
2572
+ };
2573
+ paths[path] = { ..._nullishCoalesce(paths[path], () => ( {})), [method]: op };
2574
+ }
2575
+ return {
2576
+ openapi: "3.1.0",
2577
+ info: { title: _nullishCoalesce(input.title, () => ( "PipRail x402 resources")), version: _nullishCoalesce(input.version, () => ( "1.0.0")) },
2578
+ servers: [{ url: input.origin }],
2579
+ paths,
2580
+ // "Built with @piprail/sdk" — default on (opt out with attribution:false). At the
2581
+ // document ROOT so `info` stays exactly { title, version }.
2582
+ ...input.attribution === false ? {} : { "x-generator": GENERATOR },
2583
+ ...input.ownershipProofs && input.ownershipProofs.length > 0 ? { "x-agentcash-provenance": { ownershipProofs: input.ownershipProofs } } : {}
2584
+ };
2585
+ }
2586
+ function buildWellKnownX402(input) {
2587
+ return {
2588
+ version: 1,
2589
+ resources: input.resources.map((r) => r.url),
2590
+ ...input.ownershipProofs && input.ownershipProofs.length > 0 ? { ownershipProofs: input.ownershipProofs } : {}
2591
+ };
2592
+ }
2593
+ function buildX402DnsTxt(input) {
2594
+ const descriptor = input.descriptor ? `descriptor=${input.descriptor};` : "";
2595
+ return {
2596
+ name: `_x402.${input.host}`,
2597
+ type: "TXT",
2598
+ value: `v=x4021;${descriptor}url=${input.discoveryUrl}`
2599
+ };
2600
+ }
2601
+
2602
+
2603
+
2604
+
2605
+
2606
+
2607
+
2608
+
2609
+
1990
2610
 
1991
2611
 
1992
2612
 
@@ -2026,4 +2646,4 @@ function encodeXPaymentHeader(input) {
2026
2646
 
2027
2647
 
2028
2648
 
2029
- exports.CHAINS = CHAINS; exports.ConfirmationTimeoutError = _chunkIQGT65WScjs.ConfirmationTimeoutError; exports.EIP3009_TYPES = EIP3009_TYPES; exports.EXACT_NETWORK_SLUGS = EXACT_NETWORK_SLUGS; exports.InsufficientFundsError = _chunkIQGT65WScjs.InsufficientFundsError; exports.InvalidEnvelopeError = _chunkIQGT65WScjs.InvalidEnvelopeError; exports.MaxRetriesExceededError = _chunkIQGT65WScjs.MaxRetriesExceededError; exports.MissingDriverError = _chunkIQGT65WScjs.MissingDriverError; exports.NoCompatibleAcceptError = _chunkIQGT65WScjs.NoCompatibleAcceptError; exports.NonReplayableBodyError = _chunkIQGT65WScjs.NonReplayableBodyError; exports.PaymentDeclinedError = _chunkIQGT65WScjs.PaymentDeclinedError; exports.PaymentTimeoutError = _chunkIQGT65WScjs.PaymentTimeoutError; exports.PipRailClient = PipRailClient; exports.PipRailError = _chunkIQGT65WScjs.PipRailError; exports.RecipientNotReadyError = _chunkIQGT65WScjs.RecipientNotReadyError; exports.UnknownTokenError = _chunkIQGT65WScjs.UnknownTokenError; exports.UnsupportedNetworkError = _chunkIQGT65WScjs.UnsupportedNetworkError; exports.WrongChainError = _chunkIQGT65WScjs.WrongChainError; exports.WrongFamilyError = _chunkIQGT65WScjs.WrongFamilyError; exports.buildChallengeHeader = buildChallengeHeader; exports.buildExactAuthorization = buildExactAuthorization; exports.buildReceiptHeader = buildReceiptHeader; exports.buildSignatureHeader = buildSignatureHeader; exports.chainIdForExactNetwork = chainIdForExactNetwork; exports.createPaymentGate = createPaymentGate; exports.encodeXPaymentHeader = encodeXPaymentHeader; exports.evaluatePolicy = evaluatePolicy; exports.parseChallenge = parseChallenge; exports.parseExactRequirements = parseExactRequirements; exports.parseReceipt = parseReceipt; exports.parseSignatureHeader = parseSignatureHeader; exports.paymentTools = paymentTools; exports.pickAccept = pickAccept; exports.planAcross = planAcross; exports.registerDriver = registerDriver; exports.requirePayment = requirePayment; exports.resolveChain = resolveChain; exports.toInsufficientFundsError = _chunkIQGT65WScjs.toInsufficientFundsError; exports.toInvalidBody = toInvalidBody;
2649
+ exports.CHAINS = CHAINS; exports.ConfirmationTimeoutError = _chunkIQGT65WScjs.ConfirmationTimeoutError; exports.EIP3009_TYPES = EIP3009_TYPES; exports.EXACT_NETWORK_SLUGS = EXACT_NETWORK_SLUGS; exports.GENERATOR = GENERATOR; exports.InsufficientFundsError = _chunkIQGT65WScjs.InsufficientFundsError; exports.InvalidEnvelopeError = _chunkIQGT65WScjs.InvalidEnvelopeError; exports.MaxRetriesExceededError = _chunkIQGT65WScjs.MaxRetriesExceededError; exports.MissingDriverError = _chunkIQGT65WScjs.MissingDriverError; exports.NoCompatibleAcceptError = _chunkIQGT65WScjs.NoCompatibleAcceptError; exports.NonReplayableBodyError = _chunkIQGT65WScjs.NonReplayableBodyError; exports.PaymentDeclinedError = _chunkIQGT65WScjs.PaymentDeclinedError; exports.PaymentTimeoutError = _chunkIQGT65WScjs.PaymentTimeoutError; exports.PipRailClient = PipRailClient; exports.PipRailError = _chunkIQGT65WScjs.PipRailError; exports.RecipientNotReadyError = _chunkIQGT65WScjs.RecipientNotReadyError; exports.UnknownTokenError = _chunkIQGT65WScjs.UnknownTokenError; exports.UnsupportedNetworkError = _chunkIQGT65WScjs.UnsupportedNetworkError; exports.WrongChainError = _chunkIQGT65WScjs.WrongChainError; exports.WrongFamilyError = _chunkIQGT65WScjs.WrongFamilyError; exports.buildChallengeHeader = buildChallengeHeader; exports.buildExactAuthorization = buildExactAuthorization; exports.buildOpenApi = buildOpenApi; exports.buildReceiptHeader = buildReceiptHeader; exports.buildSignatureHeader = buildSignatureHeader; exports.buildWellKnownX402 = buildWellKnownX402; exports.buildX402DnsTxt = buildX402DnsTxt; exports.chainIdForExactNetwork = chainIdForExactNetwork; exports.createPaymentGate = createPaymentGate; exports.encodeXPaymentHeader = encodeXPaymentHeader; exports.evaluatePolicy = evaluatePolicy; exports.normalizeNetwork = normalizeNetwork; exports.parseChallenge = parseChallenge; exports.parseExactRequirements = parseExactRequirements; exports.parseReceipt = parseReceipt; exports.parseSignatureHeader = parseSignatureHeader; exports.paymentTools = paymentTools; exports.pickAccept = pickAccept; exports.planAcross = planAcross; exports.register402Index = register402Index; exports.registerDriver = registerDriver; exports.registerX402Scan = registerX402Scan; exports.requirePayment = requirePayment; exports.resolveChain = resolveChain; exports.searchOpenIndexes = searchOpenIndexes; exports.toInsufficientFundsError = _chunkIQGT65WScjs.toInsufficientFundsError; exports.toInvalidBody = toInvalidBody;