@piprail/sdk 2.15.0 → 2.16.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.
Files changed (35) hide show
  1. package/CHANGELOG.md +260 -0
  2. package/README.md +2 -2
  3. package/dist/{algorand-CSEUTWNW.js → algorand-25FMBCT3.js} +13 -4
  4. package/dist/{algorand-I2O24RSM.cjs → algorand-Q3TUQLPK.cjs} +49 -40
  5. package/dist/{aptos-J7QGCWNW.js → aptos-SBV6SGDP.js} +3 -3
  6. package/dist/{aptos-GA5AEYYL.cjs → aptos-VBJONBFY.cjs} +36 -36
  7. package/dist/chunk-2CX7XRZK.js +649 -0
  8. package/dist/chunk-C52H5TYB.js +474 -0
  9. package/dist/chunk-OXEFPLZA.cjs +474 -0
  10. package/dist/{chunk-3FR22M3O.cjs → chunk-QONQSZHJ.cjs} +2 -2
  11. package/dist/{chunk-3ZWM3DKM.js → chunk-QU25LSVS.js} +2 -2
  12. package/dist/chunk-V2IJ5HUW.cjs +649 -0
  13. package/dist/index.cjs +507 -1347
  14. package/dist/index.d.cts +39 -6
  15. package/dist/index.d.ts +39 -6
  16. package/dist/index.js +192 -1032
  17. package/dist/{ledger-uFtXlIHY.d.cts → ledger-Crc1bZox.d.cts} +164 -10
  18. package/dist/{ledger-uFtXlIHY.d.ts → ledger-Crc1bZox.d.ts} +164 -10
  19. package/dist/{near-NDQLGI4U.cjs → near-5LTTDU6G.cjs} +27 -27
  20. package/dist/{near-YA4Y4IGC.js → near-OLKCMTBI.js} +1 -1
  21. package/dist/node.d.cts +2 -2
  22. package/dist/node.d.ts +2 -2
  23. package/dist/{solana-OU6IUMQM.cjs → solana-AI2G7V33.cjs} +73 -52
  24. package/dist/{solana-MB6G3OA5.js → solana-HTKDRTD3.js} +32 -11
  25. package/dist/{stellar-RSNVOIKL.cjs → stellar-E2KWEV2E.cjs} +20 -20
  26. package/dist/{stellar-WDWSYOED.js → stellar-EUFZLX6J.js} +1 -1
  27. package/dist/{sui-GVSFNNJX.js → sui-KCIITCYH.js} +6 -2
  28. package/dist/{sui-MVC46BFJ.cjs → sui-Q3NJOJZS.cjs} +21 -17
  29. package/dist/{ton-MYOI3U3H.cjs → ton-J7TQWRN4.cjs} +16 -16
  30. package/dist/{ton-EJMGM3YI.js → ton-WH2JVQOO.js} +1 -1
  31. package/dist/{tron-VAPVMGJK.js → tron-FXBXDNEY.js} +1 -1
  32. package/dist/{tron-42X5N4GQ.cjs → tron-HIPMOX7S.cjs} +25 -25
  33. package/dist/{xrpl-Q2UWPCTJ.js → xrpl-RUOB37QH.js} +283 -5
  34. package/dist/{xrpl-MGUBUNSZ.cjs → xrpl-SVVS445B.cjs} +312 -34
  35. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -4,6 +4,59 @@ import {
4
4
  import {
5
5
  signReceiptEvm
6
6
  } from "./chunk-3SBTJKAG.js";
7
+ import {
8
+ DEFAULT_EXACT_TRANSFER_METHOD,
9
+ EXT_OFFER_RECEIPT,
10
+ EXT_PAYMENT_IDENTIFIER,
11
+ HEADER_REQUIRED,
12
+ HEADER_RESPONSE,
13
+ HEADER_RESPONSE_V1,
14
+ HEADER_SIGNATURE,
15
+ HEADER_SIGNATURE_V1,
16
+ KNOWN_EXACT_TRANSFER_METHODS,
17
+ buildChallengeHeader,
18
+ buildExactSignatureHeader,
19
+ buildPaymentIdentifierAdvertisement,
20
+ buildReceiptExtension,
21
+ buildReceiptHeader,
22
+ buildSignatureHeader,
23
+ buildUptoSignatureHeader,
24
+ buildV1PaymentHeader,
25
+ chainIdFromNetwork,
26
+ decodeBase64Json,
27
+ exactTransferMethod,
28
+ isSettleableExactMethod,
29
+ networkForChain,
30
+ normalizeV1Challenge,
31
+ parseChallenge,
32
+ parseExactObject,
33
+ parseExactPaymentHeader,
34
+ parseReceipt,
35
+ parseReceiptExtension,
36
+ parseSettleResponse,
37
+ parseSignatureHeader,
38
+ parseSignatureObject,
39
+ parseUptoObject,
40
+ parseUptoPaymentHeader,
41
+ pickAccept,
42
+ readPaymentIdentifier
43
+ } from "./chunk-C52H5TYB.js";
44
+ import {
45
+ DIRECTORY_INFO,
46
+ REGISTER_ATTRIBUTION,
47
+ appendAttribution,
48
+ appendKeywords,
49
+ claim402IndexDomain,
50
+ decorateOutcome,
51
+ getDirectoryInfo,
52
+ normalizeNetwork,
53
+ rankResources,
54
+ register402Index,
55
+ registerX402Scan,
56
+ scoreResource,
57
+ searchOpenIndexes,
58
+ verify402IndexDomain
59
+ } from "./chunk-2CX7XRZK.js";
7
60
  import {
8
61
  ConfirmationTimeoutError,
9
62
  InsufficientFundsError,
@@ -32,7 +85,7 @@ import {
32
85
  parseUnits,
33
86
  rejectForeignToken,
34
87
  toInsufficientFundsError
35
- } from "./chunk-3ZWM3DKM.js";
88
+ } from "./chunk-QU25LSVS.js";
36
89
 
37
90
  // src/drivers/registry.ts
38
91
  var byFamily = /* @__PURE__ */ new Map();
@@ -896,8 +949,8 @@ async function verifyAndSettleExactEvm(input) {
896
949
  try {
897
950
  recovered = await recoverTypedDataAddress({
898
951
  domain: {
899
- name: accept.extra.name,
900
- version: accept.extra.version,
952
+ name: accept.extra?.name,
953
+ version: accept.extra?.version,
901
954
  chainId: chain.id,
902
955
  verifyingContract: token
903
956
  },
@@ -969,7 +1022,7 @@ async function verifyAndSettleExactEvm(input) {
969
1022
  );
970
1023
  }
971
1024
  try {
972
- const confirmations = accept.extra.minConfirmations ?? 1;
1025
+ const confirmations = accept.extra?.minConfirmations ?? 1;
973
1026
  const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash, confirmations });
974
1027
  if (receipt.status !== "success") {
975
1028
  return { ok: false, error: "tx_reverted", detail: `Settlement tx ${txHash} reverted on-chain.` };
@@ -1338,7 +1391,7 @@ async function verifyAndSettlePermit2Evm(input) {
1338
1391
  );
1339
1392
  }
1340
1393
  try {
1341
- const confirmations = accept.extra.minConfirmations ?? 1;
1394
+ const confirmations = accept.extra?.minConfirmations ?? 1;
1342
1395
  const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash, confirmations });
1343
1396
  if (receipt.status !== "success") {
1344
1397
  return { ok: false, error: "tx_reverted", detail: `Settlement tx ${txHash} reverted on-chain.` };
@@ -1720,318 +1773,6 @@ async function verifyAndSettleUptoEvm(input) {
1720
1773
  };
1721
1774
  }
1722
1775
 
1723
- // src/x402.ts
1724
- var HEADER_REQUIRED = "payment-required";
1725
- var HEADER_SIGNATURE = "payment-signature";
1726
- var HEADER_RESPONSE = "payment-response";
1727
- var HEADER_SIGNATURE_V1 = "x-payment";
1728
- var HEADER_RESPONSE_V1 = "x-payment-response";
1729
- function encodeBase64(str) {
1730
- if (typeof Buffer !== "undefined") return Buffer.from(str, "utf8").toString("base64");
1731
- if (typeof btoa === "function" && typeof TextEncoder !== "undefined") {
1732
- const bytes = new TextEncoder().encode(str);
1733
- let binary = "";
1734
- for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);
1735
- return btoa(binary);
1736
- }
1737
- throw new Error("No base64 encoder available in this runtime.");
1738
- }
1739
- function decodeBase64(b64) {
1740
- if (typeof Buffer !== "undefined") return Buffer.from(b64, "base64").toString("utf8");
1741
- if (typeof atob === "function" && typeof TextDecoder !== "undefined") {
1742
- const binary = atob(b64);
1743
- const bytes = new Uint8Array(binary.length);
1744
- for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
1745
- return new TextDecoder().decode(bytes);
1746
- }
1747
- throw new Error("No base64 decoder available in this runtime.");
1748
- }
1749
- function fromBase64Json(b64) {
1750
- try {
1751
- return JSON.parse(decodeBase64(b64));
1752
- } catch {
1753
- return null;
1754
- }
1755
- }
1756
- function decodeBase64Json(value) {
1757
- return fromBase64Json(value);
1758
- }
1759
- function toBase64Json(value) {
1760
- return encodeBase64(JSON.stringify(value));
1761
- }
1762
- function networkForChain(chainId) {
1763
- return `eip155:${chainId}`;
1764
- }
1765
- function chainIdFromNetwork(network) {
1766
- const match = /^eip155:(\d+)$/.exec(network);
1767
- if (!match || !match[1]) return null;
1768
- const n = Number(match[1]);
1769
- return Number.isSafeInteger(n) && n > 0 ? n : null;
1770
- }
1771
- function buildChallengeHeader(challenge) {
1772
- return toBase64Json(challenge);
1773
- }
1774
- function buildReceiptHeader(receipt, extensions) {
1775
- return toBase64Json(extensions ? { ...receipt, extensions } : receipt);
1776
- }
1777
- var EXT_OFFER_RECEIPT = "offer-receipt";
1778
- function buildReceiptExtension(bundle) {
1779
- const info = { settlement: bundle.receipt, resource: bundle.resource };
1780
- if (typeof bundle.decimals === "number") info.decimals = bundle.decimals;
1781
- if (bundle.attestation) info.receipt = bundle.attestation;
1782
- return { [EXT_OFFER_RECEIPT]: { info } };
1783
- }
1784
- var EXT_PAYMENT_IDENTIFIER = "payment-identifier";
1785
- var PAYMENT_ID_MIN = 16;
1786
- var PAYMENT_ID_MAX = 128;
1787
- var PAYMENT_ID_RE = /^[A-Za-z0-9_-]+$/;
1788
- function buildPaymentIdentifierAdvertisement() {
1789
- return {
1790
- [EXT_PAYMENT_IDENTIFIER]: {
1791
- info: { required: false },
1792
- schema: { properties: { id: { type: "string", minLength: PAYMENT_ID_MIN, maxLength: PAYMENT_ID_MAX } } }
1793
- }
1794
- };
1795
- }
1796
- function readPaymentIdentifier(payload) {
1797
- if (typeof payload !== "object" || payload === null) return null;
1798
- const ext = payload.extensions;
1799
- if (typeof ext !== "object" || ext === null) return null;
1800
- const block = ext[EXT_PAYMENT_IDENTIFIER];
1801
- if (typeof block !== "object" || block === null) return null;
1802
- const info = block.info;
1803
- if (typeof info !== "object" || info === null) return null;
1804
- const id = info.id;
1805
- if (id === void 0) return null;
1806
- if (typeof id !== "string") return { invalid: "payment-identifier id must be a string" };
1807
- if (id.length < PAYMENT_ID_MIN || id.length > PAYMENT_ID_MAX) {
1808
- return { invalid: `payment-identifier id must be ${PAYMENT_ID_MIN}\u2013${PAYMENT_ID_MAX} chars (got ${id.length})` };
1809
- }
1810
- if (!PAYMENT_ID_RE.test(id)) {
1811
- return { invalid: "payment-identifier id must match [A-Za-z0-9_-]" };
1812
- }
1813
- return id;
1814
- }
1815
- function buildSignatureHeader(signature) {
1816
- return toBase64Json(signature);
1817
- }
1818
- function buildExactSignatureHeader(input) {
1819
- return toBase64Json({ x402Version: 2, accepted: input.accepted, payload: input.payload });
1820
- }
1821
- function buildUptoSignatureHeader(input) {
1822
- return toBase64Json({ x402Version: 2, accepted: input.accepted, payload: input.payload });
1823
- }
1824
- async function parseChallenge(response) {
1825
- const headerValue = response.headers.get(HEADER_REQUIRED);
1826
- if (headerValue) {
1827
- const parsed = fromBase64Json(headerValue);
1828
- if (isValidChallenge(parsed)) return parsed;
1829
- }
1830
- try {
1831
- const body = await response.clone().json();
1832
- if (isValidChallenge(body)) return body;
1833
- } catch {
1834
- }
1835
- return null;
1836
- }
1837
- function parseReceipt(response) {
1838
- const headerValue = response.headers.get(HEADER_RESPONSE) ?? response.headers.get(HEADER_RESPONSE_V1);
1839
- if (!headerValue) return null;
1840
- const parsed = fromBase64Json(headerValue);
1841
- if (!isValidReceipt(parsed)) return null;
1842
- const r = parsed;
1843
- if (typeof r.transaction !== "string" && typeof r.txHash === "string") r.transaction = r.txHash;
1844
- return r;
1845
- }
1846
- function parseReceiptExtension(response) {
1847
- const headerValue = response.headers.get(HEADER_RESPONSE) ?? response.headers.get(HEADER_RESPONSE_V1);
1848
- if (!headerValue) return null;
1849
- const parsed = fromBase64Json(headerValue);
1850
- if (!parsed || typeof parsed !== "object") return null;
1851
- const ext = parsed.extensions;
1852
- const block = ext?.[EXT_OFFER_RECEIPT];
1853
- const info = block?.info;
1854
- if (!info) return null;
1855
- const settlement = isValidReceipt(info.settlement) ? info.settlement : isValidReceipt(info.receipt) ? info.receipt : void 0;
1856
- if (!settlement) return null;
1857
- const attestation = info.receipt && info.receipt !== settlement ? info.receipt : void 0;
1858
- const res = info.resource;
1859
- return {
1860
- piprail: "1",
1861
- receipt: settlement,
1862
- resource: { url: res && typeof res.url === "string" ? res.url : "" },
1863
- ...typeof info.decimals === "number" ? { decimals: info.decimals } : {},
1864
- ...attestation ? { attestation } : {}
1865
- };
1866
- }
1867
- function parseSettleResponse(response) {
1868
- const headerValue = response.headers.get(HEADER_RESPONSE) ?? response.headers.get(HEADER_RESPONSE_V1);
1869
- if (!headerValue) return null;
1870
- const parsed = fromBase64Json(headerValue);
1871
- if (!parsed || typeof parsed !== "object" || typeof parsed.success !== "boolean") return null;
1872
- return {
1873
- success: parsed.success,
1874
- // Tolerate the legacy v1 `txHash` alias for `transaction` (mirrors isValidReceipt/parseReceipt).
1875
- ...typeof parsed.transaction === "string" ? { transaction: parsed.transaction } : typeof parsed.txHash === "string" ? { transaction: parsed.txHash } : {},
1876
- ...typeof parsed.network === "string" ? { network: parsed.network } : {},
1877
- ...typeof parsed.payer === "string" ? { payer: parsed.payer } : {},
1878
- ...typeof parsed.errorReason === "string" ? { errorReason: parsed.errorReason } : {},
1879
- // The upto SettleResponse's REQUIRED `amount` (actual settled atomic units) — string
1880
- // passthrough so the upto buyer records ACTUAL, not MAX. Absent on onchain-proof/exact.
1881
- ...typeof parsed.amount === "string" ? { amount: parsed.amount } : {}
1882
- };
1883
- }
1884
- function parseSignatureObject(parsed) {
1885
- if (!parsed || typeof parsed !== "object") return null;
1886
- const v = parsed;
1887
- const accepted = v.accepted;
1888
- const scheme = accepted?.scheme ?? v.scheme;
1889
- if (scheme !== "onchain-proof") return null;
1890
- const payload = v.payload;
1891
- if (!payload || typeof payload.txHash !== "string" || typeof payload.nonce !== "string") {
1892
- return null;
1893
- }
1894
- if (!accepted) {
1895
- const synthesized = {
1896
- scheme: "onchain-proof",
1897
- ...typeof v.network === "string" ? { network: v.network } : {},
1898
- ...typeof v.asset === "string" ? { asset: v.asset } : {}
1899
- };
1900
- return { ...v, accepted: synthesized, payload };
1901
- }
1902
- return parsed;
1903
- }
1904
- function parseSignatureHeader(value) {
1905
- return parseSignatureObject(fromBase64Json(value));
1906
- }
1907
- function parseExactPaymentHeader(value) {
1908
- return parseExactObject(fromBase64Json(value));
1909
- }
1910
- function parseExactObject(parsed) {
1911
- if (!parsed || typeof parsed !== "object") return null;
1912
- const v = parsed;
1913
- const accepted = v.accepted ?? null;
1914
- const scheme = accepted?.scheme ?? v.scheme;
1915
- if (scheme !== "exact") return null;
1916
- const network = accepted?.network ?? v.network;
1917
- if (typeof network !== "string") return null;
1918
- const payload = v.payload;
1919
- if (!payload || typeof payload !== "object") return null;
1920
- const x402Version = typeof v.x402Version === "number" ? v.x402Version : 2;
1921
- const asset = accepted && typeof accepted.asset === "string" ? accepted.asset : void 0;
1922
- const base2 = { x402Version, network, ...asset ? { asset } : {}, raw: v };
1923
- if (typeof payload.signedDelegateAction === "string") {
1924
- return { ...base2, method: "near", payload: { signedDelegateAction: payload.signedDelegateAction } };
1925
- }
1926
- if (typeof payload.transaction === "string" && typeof payload.senderAuth === "string") {
1927
- return { ...base2, method: "aptos", payload: { transaction: payload.transaction, senderAuth: payload.senderAuth } };
1928
- }
1929
- if (typeof payload.transaction === "string") {
1930
- return { ...base2, method: "svm", payload: { transaction: payload.transaction } };
1931
- }
1932
- if (Array.isArray(payload.paymentGroup)) {
1933
- const group = payload.paymentGroup;
1934
- const index = payload.paymentIndex;
1935
- if (group.length === 0 || group.length > 16 || !group.every((t) => typeof t === "string") || typeof index !== "number" || !Number.isInteger(index) || index < 0 || index >= group.length) {
1936
- return null;
1937
- }
1938
- return {
1939
- ...base2,
1940
- method: "algorand",
1941
- payload: { paymentIndex: index, paymentGroup: group }
1942
- };
1943
- }
1944
- const signature = payload.signature;
1945
- if (typeof signature !== "string") return null;
1946
- const authorization = payload.authorization;
1947
- if (authorization && typeof authorization === "object") {
1948
- for (const k of ["from", "to", "value", "validAfter", "validBefore", "nonce"]) {
1949
- if (typeof authorization[k] !== "string") return null;
1950
- }
1951
- return {
1952
- ...base2,
1953
- method: "eip3009",
1954
- payload: { signature, authorization }
1955
- };
1956
- }
1957
- const p2 = payload.permit2Authorization;
1958
- if (p2 && typeof p2 === "object") {
1959
- const permitted = p2.permitted;
1960
- const witness = p2.witness;
1961
- if (!permitted || typeof permitted !== "object" || !witness || typeof witness !== "object") return null;
1962
- if (typeof permitted.token !== "string" || typeof permitted.amount !== "string") return null;
1963
- if (typeof witness.to !== "string" || typeof witness.validAfter !== "string") return null;
1964
- for (const k of ["from", "spender", "nonce", "deadline"]) {
1965
- if (typeof p2[k] !== "string") return null;
1966
- }
1967
- return {
1968
- ...base2,
1969
- method: "permit2",
1970
- payload: { signature, permit2Authorization: p2 }
1971
- };
1972
- }
1973
- return null;
1974
- }
1975
- function parseUptoPaymentHeader(value) {
1976
- return parseUptoObject(fromBase64Json(value));
1977
- }
1978
- function parseUptoObject(parsed) {
1979
- if (!parsed || typeof parsed !== "object") return null;
1980
- const v = parsed;
1981
- const accepted = v.accepted ?? null;
1982
- const scheme = accepted?.scheme ?? v.scheme;
1983
- if (scheme !== "upto") return null;
1984
- const network = accepted?.network ?? v.network;
1985
- if (typeof network !== "string") return null;
1986
- const payload = v.payload;
1987
- if (!payload || typeof payload !== "object") return null;
1988
- const signature = payload.signature;
1989
- if (typeof signature !== "string") return null;
1990
- const p2 = payload.permit2Authorization;
1991
- if (!p2 || typeof p2 !== "object") return null;
1992
- const permitted = p2.permitted;
1993
- const witness = p2.witness;
1994
- if (!permitted || typeof permitted !== "object" || !witness || typeof witness !== "object") return null;
1995
- if (typeof permitted.token !== "string" || typeof permitted.amount !== "string") return null;
1996
- if (typeof witness.to !== "string" || typeof witness.facilitator !== "string" || typeof witness.validAfter !== "string") {
1997
- return null;
1998
- }
1999
- for (const k of ["from", "spender", "nonce", "deadline"]) {
2000
- if (typeof p2[k] !== "string") return null;
2001
- }
2002
- const x402Version = typeof v.x402Version === "number" ? v.x402Version : 2;
2003
- const asset = accepted && typeof accepted.asset === "string" ? accepted.asset : void 0;
2004
- const base2 = { x402Version, network, ...asset ? { asset } : {}, raw: v };
2005
- return {
2006
- ...base2,
2007
- method: "permit2-upto",
2008
- payload: { signature, permit2Authorization: p2 }
2009
- };
2010
- }
2011
- function isValidChallenge(value) {
2012
- if (!value || typeof value !== "object") return false;
2013
- const v = value;
2014
- if (v.x402Version !== 2) return false;
2015
- if (!Array.isArray(v.accepts) || v.accepts.length === 0) return false;
2016
- if (!v.accepts.every((a) => a !== null && typeof a === "object")) return false;
2017
- if (!v.resource || typeof v.resource !== "object") return false;
2018
- return true;
2019
- }
2020
- function isValidReceipt(value) {
2021
- if (!value || typeof value !== "object") return false;
2022
- const v = value;
2023
- if (v.scheme !== "onchain-proof" && v.scheme !== "exact" && v.scheme !== "upto") return false;
2024
- if (typeof v.transaction !== "string" && typeof v.txHash !== "string") return false;
2025
- if (typeof v.payer !== "string") return false;
2026
- return true;
2027
- }
2028
- function pickAccept(challenge, matches) {
2029
- for (const accept of challenge.accepts) {
2030
- if (accept.scheme === "onchain-proof" && matches(accept.network)) return accept;
2031
- }
2032
- return null;
2033
- }
2034
-
2035
1776
  // src/drivers/evm/index.ts
2036
1777
  var evmDriver = {
2037
1778
  family: "evm",
@@ -2260,7 +2001,7 @@ function makeEvmNetwork(resolved) {
2260
2001
  // Throws UnsupportedSchemeError for a contract signer (or a non-EIP-3009 token on the eip3009 path).
2261
2002
  async payExact(wallet, accept) {
2262
2003
  const a = wallet._native;
2263
- const method = accept.extra.assetTransferMethod;
2004
+ const method = exactTransferMethod(accept);
2264
2005
  if (method === "permit2" || method === "permit2-exact") {
2265
2006
  const { payload: payload2, payerFrom: payerFrom2, nonce: nonce2 } = await payPermit2Evm({
2266
2007
  publicClient,
@@ -2296,7 +2037,19 @@ function makeEvmNetwork(resolved) {
2296
2037
  return resolveExactRailEvm({
2297
2038
  asset,
2298
2039
  method,
2299
- readDomain: (a) => readExactDomain(publicClient, a),
2040
+ // `readExactDomain` fails CLOSED to null on two very different causes: the token really
2041
+ // isn't EIP-3009, or the RPC read blipped (rate-limit, timeout, an HTML error page from a
2042
+ // proxy). Treating a blip as "not EIP-3009" silently downgrades a perfectly good gasless
2043
+ // rail to onchain-proof — the merchant's buyers start paying gas and the warning blames
2044
+ // their TOKEN, which is the one thing that isn't wrong. The buyer side already retries
2045
+ // once for exactly this reason (see payExactEvm); the gate side did not, so a rate-limited
2046
+ // public RPC could turn real Base USDC into "this token isn't EIP-3009". Mirror it.
2047
+ readDomain: async (a) => {
2048
+ const first = await readExactDomain(publicClient, a);
2049
+ if (first) return first;
2050
+ await new Promise((r) => setTimeout(r, 300));
2051
+ return readExactDomain(publicClient, a);
2052
+ },
2300
2053
  permit2Supported: () => isPermit2ProxyChain(resolved.chainId)
2301
2054
  });
2302
2055
  },
@@ -2321,6 +2074,9 @@ function makeEvmNetwork(resolved) {
2321
2074
  if ("signedDelegateAction" in payload) {
2322
2075
  return { ok: false, error: "signature_invalid", detail: "A NEAR payload was submitted to an EVM exact rail." };
2323
2076
  }
2077
+ if ("signedTxBlob" in payload) {
2078
+ return { ok: false, error: "signature_invalid", detail: "An XRPL payload was submitted to an EVM exact rail." };
2079
+ }
2324
2080
  return verifyAndSettleExactEvm({
2325
2081
  publicClient,
2326
2082
  walletClient: a.walletClient,
@@ -2382,7 +2138,7 @@ var loaders = {
2382
2138
  solana: async () => {
2383
2139
  let mod;
2384
2140
  try {
2385
- mod = await import("./solana-MB6G3OA5.js");
2141
+ mod = await import("./solana-HTKDRTD3.js");
2386
2142
  } catch (cause) {
2387
2143
  throw new MissingDriverError(
2388
2144
  `Solana selected, but its packages aren't installed. Run: npm install @solana/web3.js @solana/spl-token bs58`,
@@ -2394,7 +2150,7 @@ var loaders = {
2394
2150
  ton: async () => {
2395
2151
  let mod;
2396
2152
  try {
2397
- mod = await import("./ton-EJMGM3YI.js");
2153
+ mod = await import("./ton-WH2JVQOO.js");
2398
2154
  } catch (cause) {
2399
2155
  throw new MissingDriverError(
2400
2156
  `TON selected, but its packages aren't installed. Run: npm install @ton/ton @ton/core @ton/crypto`,
@@ -2406,7 +2162,7 @@ var loaders = {
2406
2162
  stellar: async () => {
2407
2163
  let mod;
2408
2164
  try {
2409
- mod = await import("./stellar-WDWSYOED.js");
2165
+ mod = await import("./stellar-EUFZLX6J.js");
2410
2166
  } catch (cause) {
2411
2167
  throw new MissingDriverError(
2412
2168
  `Stellar selected, but its package isn't installed. Run: npm install @stellar/stellar-sdk`,
@@ -2418,7 +2174,7 @@ var loaders = {
2418
2174
  xrpl: async () => {
2419
2175
  let mod;
2420
2176
  try {
2421
- mod = await import("./xrpl-Q2UWPCTJ.js");
2177
+ mod = await import("./xrpl-RUOB37QH.js");
2422
2178
  } catch (cause) {
2423
2179
  throw new MissingDriverError(
2424
2180
  `XRPL selected, but its package isn't installed. Run: npm install xrpl`,
@@ -2430,7 +2186,7 @@ var loaders = {
2430
2186
  tron: async () => {
2431
2187
  let mod;
2432
2188
  try {
2433
- mod = await import("./tron-VAPVMGJK.js");
2189
+ mod = await import("./tron-FXBXDNEY.js");
2434
2190
  } catch (cause) {
2435
2191
  throw new MissingDriverError(
2436
2192
  `Tron selected, but its package isn't installed. Run: npm install tronweb`,
@@ -2442,7 +2198,7 @@ var loaders = {
2442
2198
  sui: async () => {
2443
2199
  let mod;
2444
2200
  try {
2445
- mod = await import("./sui-GVSFNNJX.js");
2201
+ mod = await import("./sui-KCIITCYH.js");
2446
2202
  } catch (cause) {
2447
2203
  throw new MissingDriverError(
2448
2204
  `Sui selected, but its package isn't installed. Run: npm install @mysten/sui`,
@@ -2454,7 +2210,7 @@ var loaders = {
2454
2210
  near: async () => {
2455
2211
  let mod;
2456
2212
  try {
2457
- mod = await import("./near-YA4Y4IGC.js");
2213
+ mod = await import("./near-OLKCMTBI.js");
2458
2214
  } catch (cause) {
2459
2215
  throw new MissingDriverError(
2460
2216
  `NEAR selected, but its package isn't installed. Run: npm install near-api-js`,
@@ -2466,7 +2222,7 @@ var loaders = {
2466
2222
  aptos: async () => {
2467
2223
  let mod;
2468
2224
  try {
2469
- mod = await import("./aptos-J7QGCWNW.js");
2225
+ mod = await import("./aptos-SBV6SGDP.js");
2470
2226
  } catch (cause) {
2471
2227
  throw new MissingDriverError(
2472
2228
  `Aptos selected, but its package isn't installed. Run: npm install @aptos-labs/ts-sdk`,
@@ -2478,7 +2234,7 @@ var loaders = {
2478
2234
  algorand: async () => {
2479
2235
  let mod;
2480
2236
  try {
2481
- mod = await import("./algorand-CSEUTWNW.js");
2237
+ mod = await import("./algorand-25FMBCT3.js");
2482
2238
  } catch (cause) {
2483
2239
  throw new MissingDriverError(
2484
2240
  `Algorand selected, but its package isn't installed. Run: npm install algosdk`,
@@ -2510,619 +2266,6 @@ async function resolveNetwork2(opts) {
2510
2266
  return resolveNetwork(opts);
2511
2267
  }
2512
2268
 
2513
- // src/indexes.ts
2514
- var DIRECTORY_INFO = Object.freeze({
2515
- "402index": {
2516
- source: "402index",
2517
- review: "probe-sync",
2518
- auth: "none",
2519
- chains: null,
2520
- onSuccess: "pending-review",
2521
- readByDiscover: true,
2522
- caveat: "402 Index probes your URL on submit (rejecting anything that does not return a real 402), then lists it \u2014 a self-registered resource becomes searchable once it passes automated health + payment-validity checks, with NO domain verification required (observed live: searchable within ~2 days for a healthy endpoint). Verify your domain on 402index.io for instant, guaranteed approval + a verified badge, which also flips every pending listing on that domain live at once."
2523
- },
2524
- x402scan: {
2525
- source: "x402scan",
2526
- review: "probe-sync",
2527
- auth: "siwx",
2528
- chains: ["eip155:8453", "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"],
2529
- onSuccess: "live",
2530
- readByDiscover: false,
2531
- caveat: "x402scan lists Base/Solana only, needs one wallet signature (SIWX), and requires a resolvable input schema (from /openapi.json or the bazaar extension in the 402 body). It goes live on x402scan.com immediately on success \u2014 but discover() does NOT read x402scan, so the listing won't appear in discover() results."
2532
- },
2533
- bazaar: {
2534
- source: "bazaar",
2535
- review: "settle-coupled",
2536
- auth: "facilitator-only",
2537
- chains: null,
2538
- onSuccess: "not-listable",
2539
- readByDiscover: true,
2540
- caveat: "CDP Bazaar has no register endpoint \u2014 it catalogs a resource only when its own facilitator settles a payment. PipRail verifies locally with no facilitator, so a PipRail resource cannot be listed here (you can still READ Bazaar to find others). List on 402 Index or x402scan instead."
2541
- }
2542
- });
2543
- function getDirectoryInfo(source) {
2544
- return DIRECTORY_INFO[source];
2545
- }
2546
- function decorateOutcome(o) {
2547
- const info = DIRECTORY_INFO[o.source];
2548
- return { ...o, visibility: o.visibility ?? (o.ok ? info.onSuccess : "not-listable"), note: info.caveat };
2549
- }
2550
- var BAZAAR_URL = "https://api.cdp.coinbase.com/platform/v2/x402/discovery/resources";
2551
- var INDEX402_SEARCH = "https://402index.io/api/v1/services";
2552
- var INDEX402_REGISTER = "https://402index.io/api/v1/register";
2553
- var INDEX402_CLAIM = "https://402index.io/api/v1/claim";
2554
- var INDEX402_VERIFY = "https://402index.io/api/v1/claim/verify";
2555
- var X402SCAN_REGISTER = "https://www.x402scan.com/api/x402/registry/register";
2556
- var USER_AGENT = "@piprail/sdk (+https://piprail.com)";
2557
- function clientHeaders(extra = {}) {
2558
- return { "user-agent": USER_AGENT, ...extra };
2559
- }
2560
- var SLUG_TO_CAIP2 = {
2561
- // EVM (the common index-reported slugs; others fall through to net.supports)
2562
- ethereum: "eip155:1",
2563
- base: "eip155:8453",
2564
- polygon: "eip155:137",
2565
- arbitrum: "eip155:42161",
2566
- optimism: "eip155:10",
2567
- avalanche: "eip155:43114",
2568
- bnb: "eip155:56",
2569
- bsc: "eip155:56",
2570
- // non-EVM families — values mirror each driver's bound caip2 exactly
2571
- solana: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
2572
- ton: "tvm:-239",
2573
- tron: "tron:mainnet",
2574
- near: "near:mainnet",
2575
- sui: "sui:mainnet",
2576
- aptos: "aptos:1",
2577
- algorand: "algorand:wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=",
2578
- stellar: "stellar:pubnet",
2579
- xrpl: "xrpl:0"
2580
- };
2581
- var LEGACY_CAIP2_ALIAS = {
2582
- "ton:-239": "tvm:-239"
2583
- };
2584
- function normalizeNetwork(network) {
2585
- const legacy = LEGACY_CAIP2_ALIAS[network];
2586
- if (legacy) return legacy;
2587
- if (network.includes(":")) return network;
2588
- return SLUG_TO_CAIP2[network.toLowerCase()] ?? network;
2589
- }
2590
- async function searchOpenIndexes(opts = {}) {
2591
- const sources = opts.sources ?? ["bazaar", "402index"];
2592
- const limit = opts.limit ?? 20;
2593
- const filters = {
2594
- ...optionalRaw("category", opts.category),
2595
- ...optionalRaw("asset", opts.asset),
2596
- ...optionalRaw("maxPrice", opts.maxPrice),
2597
- ...optionalRaw("verified", opts.verified),
2598
- ...optionalRaw("paymentValid", opts.paymentValid),
2599
- ...optionalRaw("sort", opts.sort),
2600
- ...optionalRaw("order", opts.order)
2601
- };
2602
- const results = await Promise.all(
2603
- sources.map((source) => {
2604
- if (source === "bazaar") return safeSearch(() => searchBazaar(opts.query, limit, opts.signal));
2605
- if (source === "402index") return safeSearch(() => search402Index(opts.query, limit, filters, opts.signal));
2606
- return Promise.resolve([]);
2607
- })
2608
- );
2609
- const merged = applyClientFilters(dedupeByResource(results.flat()), opts);
2610
- const wantRelevance = opts.query !== void 0 && (opts.sort ?? "relevance") === "relevance";
2611
- if (wantRelevance) return rankResources(merged, opts.query);
2612
- if (opts.sort && opts.sort !== "relevance") return sortResources(merged, opts.sort, opts.order ?? "desc");
2613
- return merged;
2614
- }
2615
- function optionalRaw(field, value) {
2616
- return value !== void 0 ? { [field]: value } : {};
2617
- }
2618
- function applyClientFilters(items, opts) {
2619
- let out = items;
2620
- if (opts.category) {
2621
- const want = opts.category.toLowerCase();
2622
- out = out.filter((r) => r.category !== void 0 && r.category.toLowerCase().startsWith(want));
2623
- }
2624
- if (opts.maxPrice !== void 0) {
2625
- const max = opts.maxPrice;
2626
- out = out.filter((r) => r.priceUsd === void 0 || r.priceUsd <= max);
2627
- }
2628
- if (opts.asset) {
2629
- const want = opts.asset.toLowerCase();
2630
- out = out.filter((r) => {
2631
- const known = r.rails.map((x) => x.symbol ?? x.asset).filter((a) => !!a);
2632
- return known.length === 0 || known.some((a) => a.toLowerCase() === want);
2633
- });
2634
- }
2635
- if (opts.minReliability !== void 0) {
2636
- const min = opts.minReliability;
2637
- out = out.filter((r) => r.reliabilityScore === void 0 || r.reliabilityScore >= min);
2638
- }
2639
- return out;
2640
- }
2641
- function tokenize(s) {
2642
- return (s ?? "").toLowerCase().match(/[a-z0-9]+/g) ?? [];
2643
- }
2644
- var FIELD_WEIGHTS = { name: 6, category: 4, tags: 4, path: 3, description: 2 };
2645
- function fieldTokens(r) {
2646
- let pathText = r.resource;
2647
- try {
2648
- const u = new URL(r.resource);
2649
- pathText = `${u.hostname} ${u.pathname}`;
2650
- } catch {
2651
- }
2652
- return [
2653
- [tokenize(r.name), FIELD_WEIGHTS.name],
2654
- [tokenize(r.category), FIELD_WEIGHTS.category],
2655
- [tokenize((r.tags ?? []).join(" ")), FIELD_WEIGHTS.tags],
2656
- [tokenize(pathText), FIELD_WEIGHTS.path],
2657
- [tokenize(r.description), FIELD_WEIGHTS.description]
2658
- ];
2659
- }
2660
- function scoreResource(r, queryTokens) {
2661
- if (queryTokens.length === 0) return 0;
2662
- const fields = fieldTokens(r);
2663
- let score = 0;
2664
- let matched = 0;
2665
- for (const qt of queryTokens) {
2666
- let hit = false;
2667
- for (const [toks, w] of fields) {
2668
- if (toks.includes(qt)) {
2669
- score += w;
2670
- hit = true;
2671
- } else if (qt.length >= 4 && toks.some((t) => t.startsWith(qt) || t.length >= 4 && qt.startsWith(t))) {
2672
- score += w * 0.4;
2673
- hit = true;
2674
- }
2675
- }
2676
- if (hit) matched++;
2677
- }
2678
- if (matched === 0) return 0;
2679
- if (matched === queryTokens.length) score += 8;
2680
- if (r.reliabilityScore !== void 0) score += r.reliabilityScore / 1e3;
2681
- return score;
2682
- }
2683
- function rankResources(items, query) {
2684
- const qTokens = tokenize(query);
2685
- if (qTokens.length === 0) return items;
2686
- return items.map((r, i) => ({ r, i, s: scoreResource(r, qTokens) })).filter((x) => x.s > 0).sort((a, b) => b.s - a.s || a.i - b.i).map((x) => ({ ...x.r, score: x.s }));
2687
- }
2688
- function sortResources(items, sort, order) {
2689
- const dir = order === "asc" ? 1 : -1;
2690
- const key = (r) => sort === "reliability" || sort === "uptime" ? r.reliabilityScore : sort === "price" ? r.priceUsd : sort === "name" ? (r.name ?? r.resource).toLowerCase() : void 0;
2691
- return items.map((r, i) => ({ r, i })).sort((a, b) => {
2692
- const ka = key(a.r);
2693
- const kb = key(b.r);
2694
- if (ka === void 0 && kb === void 0) return a.i - b.i;
2695
- if (ka === void 0) return 1;
2696
- if (kb === void 0) return -1;
2697
- if (ka < kb) return -1 * dir;
2698
- if (ka > kb) return 1 * dir;
2699
- return a.i - b.i;
2700
- }).map((x) => x.r);
2701
- }
2702
- async function safeSearch(run) {
2703
- try {
2704
- return await run();
2705
- } catch {
2706
- return [];
2707
- }
2708
- }
2709
- function dedupeByResource(items) {
2710
- const seen = /* @__PURE__ */ new Set();
2711
- const out = [];
2712
- for (const it of items) {
2713
- const key = it.resource;
2714
- if (!key || seen.has(key)) continue;
2715
- seen.add(key);
2716
- out.push(it);
2717
- }
2718
- return out;
2719
- }
2720
- async function searchBazaar(query, limit, signal) {
2721
- const res = await fetch(`${BAZAAR_URL}?limit=${encodeURIComponent(String(limit))}`, {
2722
- headers: clientHeaders({ accept: "application/json" }),
2723
- ...signal ? { signal } : {}
2724
- });
2725
- if (!res.ok) return [];
2726
- const body = await res.json();
2727
- const items = Array.isArray(body.items) ? body.items : [];
2728
- const mapped = items.map(mapBazaarItem).filter((r) => r !== null);
2729
- return query ? mapped.filter((r) => matchesQuery(r, query)) : mapped;
2730
- }
2731
- function mapBazaarItem(raw) {
2732
- if (!raw || typeof raw !== "object") return null;
2733
- const o = raw;
2734
- const resource = pickString(o, "resource", "url", "endpoint");
2735
- if (!resource) return null;
2736
- const meta = o.metadata && typeof o.metadata === "object" ? o.metadata : {};
2737
- return {
2738
- resource,
2739
- source: "bazaar",
2740
- rails: mapRails(o.accepts),
2741
- ...optionalString("name", pickString(meta, "name", "title")),
2742
- ...optionalString("description", pickString(meta, "description") ?? pickString(o, "description")),
2743
- ...optionalString("category", pickString(meta, "category"))
2744
- };
2745
- }
2746
- async function search402Index(query, limit, filters, signal) {
2747
- const tokens = tokenize(query);
2748
- const queries = query && tokens.length > 1 ? [.../* @__PURE__ */ new Set([query, ...tokens])].slice(0, 5) : [query];
2749
- const pages = await Promise.all(queries.map((q) => safeSearch(() => fetch402Page(q, limit, filters, signal))));
2750
- return dedupeByResource(pages.flat());
2751
- }
2752
- async function fetch402Page(query, limit, filters, signal) {
2753
- const qs = new URLSearchParams({ limit: String(limit) });
2754
- if (query) qs.set("q", query);
2755
- if (filters.category) qs.set("category", filters.category);
2756
- if (filters.asset) qs.set("payment_asset", filters.asset);
2757
- if (filters.maxPrice !== void 0) qs.set("max_price_usd", String(filters.maxPrice));
2758
- if (filters.verified) qs.set("verified", "true");
2759
- if (filters.paymentValid) qs.set("payment_valid", "true");
2760
- if (filters.sort && filters.sort !== "relevance") {
2761
- qs.set("sort", filters.sort);
2762
- qs.set("order", filters.order ?? "desc");
2763
- }
2764
- const res = await fetch(`${INDEX402_SEARCH}?${qs.toString()}`, {
2765
- headers: clientHeaders({ accept: "application/json" }),
2766
- ...signal ? { signal } : {}
2767
- });
2768
- if (!res.ok) return [];
2769
- const body = await res.json();
2770
- const list = firstArray(body, "services", "results", "items", "data");
2771
- return list.map(map402IndexItem).filter((r) => r !== null).filter((r) => r.rails.length > 0);
2772
- }
2773
- function map402IndexItem(raw) {
2774
- if (!raw || typeof raw !== "object") return null;
2775
- const o = raw;
2776
- const resource = pickString(o, "url", "resource", "endpoint");
2777
- if (!resource) return null;
2778
- const protocol = (pickString(o, "protocol") ?? "x402").toLowerCase();
2779
- if (protocol !== "x402") return null;
2780
- const rails = Array.isArray(o.accepts) ? mapRails(o.accepts) : railFrom402IndexFields(o);
2781
- const priceUsd = pickNumber(o, "price_usd", "priceUsd", "price");
2782
- const reliabilityScore = pickNumber(o, "reliability_score", "reliabilityScore");
2783
- const tags = pickStringArray(o, "tags", "keywords");
2784
- return {
2785
- resource,
2786
- source: "402index",
2787
- rails,
2788
- ...priceUsd !== void 0 ? { priceUsd } : {},
2789
- ...reliabilityScore !== void 0 ? { reliabilityScore } : {},
2790
- ...tags ? { tags } : {},
2791
- ...optionalString("name", pickString(o, "name", "title")),
2792
- ...optionalString("description", pickString(o, "description")),
2793
- ...optionalString("category", pickString(o, "category", "tag")),
2794
- ...optionalString("health", pickString(o, "health_status", "health")),
2795
- // 402 Index reports domain_verified as 0/1; surface a boolean only when the field is present.
2796
- ...o.domain_verified !== void 0 || o.verified !== void 0 ? { verified: isTruthyFlag(o.domain_verified) || isTruthyFlag(o.verified) } : {}
2797
- };
2798
- }
2799
- function isTruthyFlag(v) {
2800
- return v === 1 || v === true || v === "1" || v === "true";
2801
- }
2802
- function railFrom402IndexFields(o) {
2803
- const network = pickString(o, "payment_network", "network");
2804
- const asset = pickString(o, "payment_asset", "asset", "token");
2805
- if (!network && !asset) return [];
2806
- return [
2807
- {
2808
- scheme: "exact",
2809
- network: network ?? "unknown",
2810
- ...asset ? { asset } : {},
2811
- ...optionalString("symbol", asset)
2812
- }
2813
- ];
2814
- }
2815
- async function register402Index(input) {
2816
- try {
2817
- const attributionOn = input.attribution !== false;
2818
- const withTags = appendKeywords(input.description, input.tags);
2819
- const description = attributionOn ? appendAttribution(withTags) : withTags;
2820
- const payload = {
2821
- url: input.url,
2822
- name: input.name ?? hostOf(input.url),
2823
- protocol: "x402",
2824
- ...description ? { description } : {},
2825
- ...typeof input.priceUsd === "number" ? { price_usd: input.priceUsd } : {},
2826
- ...input.asset ? { payment_asset: input.asset } : {},
2827
- ...input.network ? { payment_network: input.network } : {},
2828
- ...input.method ? { http_method: input.method.toUpperCase() } : {},
2829
- ...input.category ? { category: input.category } : {},
2830
- ...input.tags && input.tags.length > 0 ? { tags: input.tags } : {},
2831
- ...input.provider ? { provider: input.provider } : {},
2832
- ...input.contactEmail ? { contact_email: input.contactEmail } : {},
2833
- ...input.probeBody !== void 0 ? { probe_body: input.probeBody } : {},
2834
- ...attributionOn ? { via: "@piprail/sdk" } : {}
2835
- };
2836
- const res = await fetch(INDEX402_REGISTER, {
2837
- method: "POST",
2838
- headers: clientHeaders({ "content-type": "application/json", accept: "application/json" }),
2839
- body: JSON.stringify(payload)
2840
- });
2841
- if (res.ok) {
2842
- const body = await res.json().catch(() => ({}));
2843
- const msg = typeof body.message === "string" && body.message.length > 0 ? body.message : void 0;
2844
- const live = body.service?.status === "active";
2845
- return {
2846
- source: "402index",
2847
- ok: true,
2848
- status: res.status,
2849
- ...live ? { visibility: "live" } : {},
2850
- detail: msg ?? (live ? "Registered + live on 402 Index (domain verified)." : "Registered on 402 Index \u2014 probed on submit, then searchable once it passes automated health + payment checks (verify your domain on 402index.io for instant approval + a verified badge).")
2851
- };
2852
- }
2853
- const why = await readIndexError(res);
2854
- return {
2855
- source: "402index",
2856
- ok: false,
2857
- status: res.status,
2858
- detail: why ? `402 Index rejected it (HTTP ${res.status}): ${why}` : `402 Index returned HTTP ${res.status}.`
2859
- };
2860
- } catch (err) {
2861
- return { source: "402index", ok: false, detail: errMsg(err) };
2862
- }
2863
- }
2864
- async function readIndexError(res) {
2865
- try {
2866
- const body = await res.json();
2867
- const parts = [body.error, body.detail, body.message].filter(
2868
- (p) => typeof p === "string" && p.length > 0
2869
- );
2870
- return parts.length ? [...new Set(parts)].join(" \u2014 ") : void 0;
2871
- } catch {
2872
- return void 0;
2873
- }
2874
- }
2875
- async function registerX402Scan(input, signer) {
2876
- try {
2877
- const challengeRes = await fetch(X402SCAN_REGISTER, {
2878
- method: "POST",
2879
- headers: clientHeaders({ "content-type": "application/json", accept: "application/json" }),
2880
- body: JSON.stringify({ url: input.url })
2881
- });
2882
- if (challengeRes.status !== 402) {
2883
- return {
2884
- source: "x402scan",
2885
- ok: challengeRes.ok,
2886
- status: challengeRes.status,
2887
- detail: challengeRes.ok ? "Listed on x402scan." : `x402scan returned HTTP ${challengeRes.status} (expected a SIWX 402 challenge).`
2888
- };
2889
- }
2890
- const info = await readSiwxInfo(challengeRes);
2891
- if (!info) {
2892
- return { source: "x402scan", ok: false, status: 402, detail: "x402scan SIWX challenge was unparseable." };
2893
- }
2894
- const resolvedInfo = { ...info, issuedAt: info.issuedAt ?? (/* @__PURE__ */ new Date()).toISOString() };
2895
- const message = formatSiweMessage(resolvedInfo, signer.address);
2896
- const signature = await signer.signMessage(message);
2897
- const header = encodeBase642(
2898
- JSON.stringify({ ...resolvedInfo, address: signer.address, type: "eip191", message, signature })
2899
- );
2900
- const res = await fetch(X402SCAN_REGISTER, {
2901
- method: "POST",
2902
- headers: clientHeaders({
2903
- "content-type": "application/json",
2904
- accept: "application/json",
2905
- "sign-in-with-x": header
2906
- }),
2907
- body: JSON.stringify({ url: input.url })
2908
- });
2909
- if (res.ok) {
2910
- return { source: "x402scan", ok: true, status: res.status, detail: "Listed on x402scan (SIWX)." };
2911
- }
2912
- const why = await readIndexError(res);
2913
- return {
2914
- source: "x402scan",
2915
- ok: false,
2916
- status: res.status,
2917
- detail: why ? `x402scan rejected it (HTTP ${res.status}): ${why}` : `x402scan returned HTTP ${res.status} after signing.`
2918
- };
2919
- } catch (err) {
2920
- return { source: "x402scan", ok: false, detail: errMsg(err) };
2921
- }
2922
- }
2923
- async function claim402IndexDomain(domainOrUrl, opts = {}) {
2924
- const domain = hostOf(domainOrUrl);
2925
- try {
2926
- const res = await fetch(INDEX402_CLAIM, {
2927
- method: "POST",
2928
- headers: clientHeaders({ "content-type": "application/json", accept: "application/json" }),
2929
- body: JSON.stringify({ domain, ...opts.contactEmail ? { contact_email: opts.contactEmail } : {} })
2930
- });
2931
- const body = await res.json().catch(() => ({}));
2932
- if (!res.ok) {
2933
- return { ok: false, domain, httpStatus: res.status, detail: pickString(body, "error", "detail", "message") ?? `402 Index claim returned HTTP ${res.status}.` };
2934
- }
2935
- const verificationToken = pickString(body, "verification_token");
2936
- const verificationHash = pickString(body, "verification_hash") ?? (verificationToken ? await sha256Hex(verificationToken) : void 0);
2937
- return {
2938
- ok: true,
2939
- domain,
2940
- httpStatus: res.status,
2941
- ...optionalString("verificationHash", verificationHash),
2942
- ...optionalString("verificationToken", verificationToken),
2943
- ...optionalString("verificationUrl", pickString(body, "verification_url")),
2944
- ...optionalString("instructions", pickString(body, "instructions"))
2945
- };
2946
- } catch (err) {
2947
- return { ok: false, domain, detail: errMsg(err) };
2948
- }
2949
- }
2950
- async function sha256Hex(input) {
2951
- const digest = await globalThis.crypto.subtle.digest("SHA-256", new TextEncoder().encode(input));
2952
- return Array.from(new Uint8Array(digest)).map((b) => b.toString(16).padStart(2, "0")).join("");
2953
- }
2954
- async function verify402IndexDomain(domainOrUrl) {
2955
- const domain = hostOf(domainOrUrl);
2956
- try {
2957
- const res = await fetch(INDEX402_VERIFY, {
2958
- method: "POST",
2959
- headers: clientHeaders({ "content-type": "application/json", accept: "application/json" }),
2960
- body: JSON.stringify({ domain })
2961
- });
2962
- const body = await res.json().catch(() => ({}));
2963
- if (!res.ok) {
2964
- return { ok: false, domain, httpStatus: res.status, detail: pickString(body, "error", "detail", "message") ?? `402 Index verify returned HTTP ${res.status}.` };
2965
- }
2966
- return {
2967
- ok: true,
2968
- domain,
2969
- httpStatus: res.status,
2970
- ...optionalString("status", pickString(body, "status")),
2971
- ...typeof body.services_count === "number" ? { servicesCount: body.services_count } : {}
2972
- };
2973
- } catch (err) {
2974
- return { ok: false, domain, detail: errMsg(err) };
2975
- }
2976
- }
2977
- async function readSiwxInfo(res) {
2978
- try {
2979
- const body = await res.json();
2980
- const ext = body.extensions;
2981
- const siwx = ext?.["sign-in-with-x"];
2982
- const info = siwx?.info ?? siwx;
2983
- if (info && info.chainId == null && Array.isArray(siwx?.supportedChains)) {
2984
- const evm = siwx.supportedChains.find(
2985
- (c) => typeof c?.chainId === "string" && c.chainId.startsWith("eip155:")
2986
- );
2987
- if (evm && typeof evm.chainId === "string") info.chainId = evm.chainId;
2988
- }
2989
- 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) {
2990
- return info;
2991
- }
2992
- return null;
2993
- } catch {
2994
- return null;
2995
- }
2996
- }
2997
- function formatSiweMessage(info, address) {
2998
- const chainId = info.chainId ? caip2ToChainId(info.chainId) : 1;
2999
- const statement = info.statement && info.statement.trim() ? info.statement : void 0;
3000
- const lines = [
3001
- `${info.domain} wants you to sign in with your Ethereum account:`,
3002
- address,
3003
- "",
3004
- ...statement ? [statement, ""] : [""],
3005
- `URI: ${info.uri}`,
3006
- "Version: 1",
3007
- `Chain ID: ${chainId}`,
3008
- `Nonce: ${info.nonce}`,
3009
- `Issued At: ${info.issuedAt}`,
3010
- ...info.expirationTime ? [`Expiration Time: ${info.expirationTime}`] : []
3011
- ];
3012
- return lines.join("\n");
3013
- }
3014
- function caip2ToChainId(caip2) {
3015
- const m = /^eip155:(\d+)$/.exec(caip2);
3016
- const n = m ? Number(m[1]) : Number(caip2);
3017
- return Number.isSafeInteger(n) && n > 0 ? n : 1;
3018
- }
3019
- function mapRails(accepts) {
3020
- if (!Array.isArray(accepts)) return [];
3021
- const out = [];
3022
- for (const raw of accepts) {
3023
- if (!raw || typeof raw !== "object") continue;
3024
- const a = raw;
3025
- const network = pickString(a, "network");
3026
- if (!network) continue;
3027
- const extra = a.extra && typeof a.extra === "object" ? a.extra : {};
3028
- out.push({
3029
- scheme: pickString(a, "scheme") ?? "exact",
3030
- network,
3031
- ...optionalString("asset", pickString(a, "asset")),
3032
- ...optionalString("amount", pickString(a, "amount", "maxAmountRequired")),
3033
- ...optionalString("payTo", pickString(a, "payTo")),
3034
- ...optionalString("symbol", pickString(extra, "symbol"))
3035
- });
3036
- }
3037
- return out;
3038
- }
3039
- function matchesQuery(r, query) {
3040
- const haystack = [r.name, r.description, r.category, (r.tags ?? []).join(" "), r.resource].filter(Boolean).join(" ").toLowerCase();
3041
- if (haystack.includes(query.toLowerCase())) return true;
3042
- const qTokens = tokenize(query);
3043
- const hayTokens = new Set(tokenize(haystack));
3044
- return qTokens.some((t) => hayTokens.has(t));
3045
- }
3046
- function pickStringArray(o, ...keys) {
3047
- for (const k of keys) {
3048
- const v = o[k];
3049
- if (Array.isArray(v)) {
3050
- const arr = v.filter((x) => typeof x === "string" && x.length > 0);
3051
- if (arr.length) return arr;
3052
- } else if (typeof v === "string" && v.trim()) {
3053
- const arr = v.split(/[,\s]+/).filter((x) => x.length > 0);
3054
- if (arr.length) return arr;
3055
- }
3056
- }
3057
- return void 0;
3058
- }
3059
- function pickString(o, ...keys) {
3060
- for (const k of keys) {
3061
- const v = o[k];
3062
- if (typeof v === "string" && v.length > 0) return v;
3063
- }
3064
- return void 0;
3065
- }
3066
- function pickNumber(o, ...keys) {
3067
- for (const k of keys) {
3068
- const v = o[k];
3069
- if (typeof v === "number" && Number.isFinite(v)) return v;
3070
- if (typeof v === "string" && /^\d+(\.\d+)?$/.test(v.trim())) {
3071
- const n = Number(v.trim());
3072
- if (Number.isFinite(n)) return n;
3073
- }
3074
- }
3075
- return void 0;
3076
- }
3077
- function optionalString(field, value) {
3078
- return value !== void 0 ? { [field]: value } : {};
3079
- }
3080
- function firstArray(o, ...keys) {
3081
- for (const k of keys) {
3082
- if (Array.isArray(o[k])) return o[k];
3083
- }
3084
- return Array.isArray(o) ? o : [];
3085
- }
3086
- function hostOf(url) {
3087
- try {
3088
- const withScheme = /^[a-z][a-z0-9+.-]*:\/\//i.test(url) ? url : `https://${url}`;
3089
- return new URL(withScheme).hostname || url;
3090
- } catch {
3091
- return url;
3092
- }
3093
- }
3094
- function errMsg(err) {
3095
- return err instanceof Error ? err.message : String(err);
3096
- }
3097
- var REGISTER_ATTRIBUTION = "\xB7 Built with @piprail/sdk";
3098
- function appendAttribution(description) {
3099
- if (!description) return description;
3100
- if (/piprail/i.test(description)) return description;
3101
- const next = `${description.trimEnd()} ${REGISTER_ATTRIBUTION}`;
3102
- return next.length <= 500 ? next : description;
3103
- }
3104
- function appendKeywords(description, tags) {
3105
- const clean = (tags ?? []).map((t) => t.trim()).filter((t) => t.length > 0);
3106
- if (clean.length === 0) return description;
3107
- const have = (description ?? "").toLowerCase();
3108
- const fresh = [...new Set(clean.filter((t) => !have.includes(t.toLowerCase())))];
3109
- if (fresh.length === 0) return description;
3110
- const tail = `Keywords: ${fresh.join(", ")}`;
3111
- if (!description) return tail;
3112
- const next = `${description.trimEnd()} \xB7 ${tail}`;
3113
- return next.length <= 500 ? next : description;
3114
- }
3115
- function encodeBase642(str) {
3116
- if (typeof Buffer !== "undefined") return Buffer.from(str, "utf8").toString("base64");
3117
- if (typeof btoa === "function" && typeof TextEncoder !== "undefined") {
3118
- const bytes = new TextEncoder().encode(str);
3119
- let binary = "";
3120
- for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);
3121
- return btoa(binary);
3122
- }
3123
- throw new Error("No base64 encoder available in this runtime.");
3124
- }
3125
-
3126
2269
  // src/policy.ts
3127
2270
  var DENOM_PRECISION = MAX_DECIMALS;
3128
2271
  var BUILTIN_DENOMS = {
@@ -4086,7 +3229,7 @@ var PipRailClient = class {
4086
3229
  * - Results are cross-scheme (mostly the mainstream `exact` scheme); `fetch()` pays
4087
3230
  * `onchain-proof` rails by default, and standard `exact` rails too once you opt in
4088
3231
  * with `schemes: ['onchain-proof', 'exact']` (EVM EIP-3009/Permit2 + Solana SVM + Algorand
4089
- * + Aptos + NEAR).
3232
+ * + Aptos + NEAR + XRPL native XRP).
4090
3233
  */
4091
3234
  async discover(opts = {}) {
4092
3235
  const found = await searchOpenIndexes({
@@ -4261,7 +3404,7 @@ var PipRailClient = class {
4261
3404
  return this.payUptoRail(net, wallet, accept, url, init, quote);
4262
3405
  }
4263
3406
  if (accept.scheme === "exact") {
4264
- return this.payExactRail(net, wallet, accept, url, init, quote);
3407
+ return this.payExactRail(net, wallet, accept, url, init, quote, challenge.x402Version);
4265
3408
  }
4266
3409
  if (accept.scheme !== "onchain-proof") {
4267
3410
  throw new UnsupportedSchemeError(
@@ -4347,15 +3490,35 @@ var PipRailClient = class {
4347
3490
  if (schemes.includes("exact")) {
4348
3491
  out.push(
4349
3492
  ...challenge.accepts.filter(
4350
- (a) => a.scheme === "exact" && this.supportsNetwork(net, a.network) && typeof net.payExact === "function" && // `native` is never `exact`-payable on ANY family (exact = an EIP-3009/Permit2-style
4351
- // signed-authorization scheme a native coin can't support; every driver's payExact
4352
- // throws/returns-null for it). describeAsset('native') IS non-null (onchain-proof needs
4353
- // it), so without this guard a malformed 402 advertising a native `exact` rail would be
4354
- // gathered, planned `payable`, even chosen by autoRoute then throw at pay time.
4355
- a.asset !== "native" && // the exact pay path (payExact → driver) reads `extra.assetTransferMethod`; a malformed
4356
- // 402 offering an exact rail for a RECOGNISED token but omitting `extra` would otherwise
4357
- // be planned payable then throw a raw TypeError mid-pay. Require it at gather time.
4358
- typeof a.extra?.assetTransferMethod === "string" && net.describeAsset(a.asset) != null && // a foreign rail's maxTimeoutSeconds must be a usable positive integer, or
3493
+ (a) => a.scheme === "exact" && this.supportsNetwork(net, a.network) && typeof net.payExact === "function" && /*
3494
+ * Can this family sign an `exact` payment for THIS asset?
3495
+ *
3496
+ * The default for every family that doesn't say otherwise is "any recognised token
3497
+ * yes, the native coin no". `exact` is an EIP-3009/Permit2-style signed-authorization
3498
+ * scheme a native coin can't carry, and `describeAsset('native')` IS non-null
3499
+ * (onchain-proof needs it), so without the rule a 402 advertising a native exact rail
3500
+ * would gather, plan `payable`, even win autoRoute then throw at pay time.
3501
+ *
3502
+ * XRPL is the first family to overturn it, in BOTH directions. There an `exact` payment
3503
+ * is simply a fully signed `Payment`, so native XRP is the most natural thing to send —
3504
+ * 863 of its 1,732 live rails are priced in XRP. Its ISSUED currencies are excluded
3505
+ * instead: they state a decimal `value` on the wire while the spend policy caps in base
3506
+ * units, so pricing one as base units would let a 12-RLUSD rail slip under any cap.
3507
+ * A driver that declares `exactPayableAsset` replaces this rule for all of its assets.
3508
+ */
3509
+ (net.exactPayableAsset ? net.exactPayableAsset(a.asset) : a.asset !== "native") && /*
3510
+ * The rail's transfer method must be one a driver can sign — but an ABSENT method is
3511
+ * not an unknown one. `scheme_exact_evm.md`: "If no `assetTransferMethod` is specified
3512
+ * in `PaymentRequired.extra`, clients should default to `eip3009`", and the SVM /
3513
+ * Algorand / Aptos / NEAR / Hedera schemes never define the key at all. This predicate
3514
+ * previously REQUIRED the key, which rejected 91% of the deployed x402 web — every
3515
+ * Solana rail, every Arbitrum rail, 85% of Base — while the pay path had always
3516
+ * handled its absence correctly (the EVM driver defaults to eip3009 and re-derives the
3517
+ * EIP-712 domain on-chain). `isSettleableExactMethod` keeps the real guard: a rail that
3518
+ * NAMES a method we don't implement (the spec's `erc7710`) is still skipped, because
3519
+ * signing an EIP-3009 authorization for it would just be rejected by its facilitator.
3520
+ */
3521
+ isSettleableExactMethod(a) && net.describeAsset(a.asset) != null && // a foreign rail's maxTimeoutSeconds must be a usable positive integer, or
4359
3522
  // signing it would build a NaN/garbage validBefore — drop it silently
4360
3523
  // (symmetric with an unrecognised token) rather than leak a raw SyntaxError.
4361
3524
  Number.isInteger(a.maxTimeoutSeconds) && a.maxTimeoutSeconds > 0
@@ -4472,6 +3635,14 @@ var PipRailClient = class {
4472
3635
  accept,
4473
3636
  quote,
4474
3637
  cost,
3638
+ // Surface the transfer method we INFERRED, not just the one the rail named — an absent
3639
+ // marker means the scheme's default, and saying so is how an agent (or a maintainer) sees
3640
+ // why a domain-only rail is payable and gasless. The default is PER FAMILY: a Solana rail
3641
+ // naming nothing means `svm`, never `eip3009`.
3642
+ ...accept.scheme === "exact" ? {
3643
+ method: accept.extra?.assetTransferMethod ? exactTransferMethod(accept) : `${exactTransferMethod(accept, net.family)} (default)`
3644
+ } : {},
3645
+ ...accept.scheme === "upto" ? { method: "permit2-upto" } : {},
4475
3646
  state,
4476
3647
  blockers,
4477
3648
  warnings,
@@ -4513,7 +3684,7 @@ var PipRailClient = class {
4513
3684
  const symbol = described?.symbol ?? accept.extra?.symbol;
4514
3685
  const amountFormatted = formatUnits(amountBase, decimals);
4515
3686
  const intent = {
4516
- host: hostOf2(url),
3687
+ host: hostOf(url),
4517
3688
  chain: this.opts.chain,
4518
3689
  network: accept.network,
4519
3690
  asset: accept.asset,
@@ -4654,7 +3825,7 @@ var PipRailClient = class {
4654
3825
  }
4655
3826
  const record = {
4656
3827
  url: quote.url,
4657
- host: hostOf2(quote.url),
3828
+ host: hostOf(quote.url),
4658
3829
  network: quote.network,
4659
3830
  asset: quote.asset,
4660
3831
  amountBase,
@@ -4838,7 +4009,7 @@ var PipRailClient = class {
4838
4009
  * • a 200 whose SettleResponse says `success:false` → a rejection, NEVER a spend;
4839
4010
  * • the spend is recorded EXACTLY ONCE, on an affirmative settlement only.
4840
4011
  */
4841
- async payExactRail(net, wallet, accept, url, init, quote) {
4012
+ async payExactRail(net, wallet, accept, url, init, quote, x402Version = 2) {
4842
4013
  if (!net.payExact) {
4843
4014
  throw new UnsupportedSchemeError(
4844
4015
  `the ${net.family} family can't pay a standard 'exact' rail (supported on EVM, Solana, Algorand, Aptos + NEAR today).`
@@ -4847,7 +4018,18 @@ var PipRailClient = class {
4847
4018
  throwIfAborted(init?.signal);
4848
4019
  const { payload, accepted, payerFrom, nonce } = await net.payExact(wallet, accept);
4849
4020
  const headers = new Headers(init?.headers);
4850
- headers.set(HEADER_SIGNATURE, buildExactSignatureHeader({ accepted, payload }));
4021
+ if (x402Version === 1) {
4022
+ headers.set(
4023
+ HEADER_SIGNATURE_V1,
4024
+ buildV1PaymentHeader({
4025
+ scheme: accepted.scheme,
4026
+ network: accept.wireNetwork ?? accepted.network,
4027
+ payload
4028
+ })
4029
+ );
4030
+ } else {
4031
+ headers.set(HEADER_SIGNATURE, buildExactSignatureHeader({ accepted, payload }));
4032
+ }
4851
4033
  const rejectDefinitive = (why2) => {
4852
4034
  this.safeEmit({ kind: "payment-failed", reason: `exact: facilitator rejected nonce=${nonce} (${why2})`, code: why2 });
4853
4035
  throw new MaxRetriesExceededError(
@@ -4874,7 +4056,7 @@ var PipRailClient = class {
4874
4056
  response = await fetch(url, { ...init ?? {}, headers, signal });
4875
4057
  } catch (err) {
4876
4058
  throw new PaymentTimeoutError(
4877
- `exact: no response after submitting the authorization (nonce=${nonce}) to ${hostOf2(url)}. The facilitator may have already settled it \u2014 verify on-chain via ${exactSettleCheckHint(net.family, payerFrom, nonce)} before re-presenting the SAME signed authorization; do NOT re-pay.`,
4059
+ `exact: no response after submitting the authorization (nonce=${nonce}) to ${hostOf(url)}. The facilitator may have already settled it \u2014 verify on-chain via ${exactSettleCheckHint(net.family, payerFrom, nonce)} before re-presenting the SAME signed authorization; do NOT re-pay.`,
4878
4060
  { cause: err, ref: nonce }
4879
4061
  );
4880
4062
  } finally {
@@ -4958,7 +4140,7 @@ var PipRailClient = class {
4958
4140
  response = await fetch(url, { ...init ?? {}, headers, signal });
4959
4141
  } catch (err) {
4960
4142
  throw new PaymentTimeoutError(
4961
- `upto: no response after submitting the authorization (nonce=${nonce}) to ${hostOf2(url)}. The merchant may have already settled it \u2014 verify on-chain before re-presenting; do NOT re-pay.`,
4143
+ `upto: no response after submitting the authorization (nonce=${nonce}) to ${hostOf(url)}. The merchant may have already settled it \u2014 verify on-chain before re-presenting; do NOT re-pay.`,
4962
4144
  { cause: err, ref: nonce }
4963
4145
  );
4964
4146
  } finally {
@@ -5132,7 +4314,7 @@ function reasonCodeForPolicy(code) {
5132
4314
  return "POLICY";
5133
4315
  }
5134
4316
  }
5135
- function hostOf2(url) {
4317
+ function hostOf(url) {
5136
4318
  try {
5137
4319
  return new URL(url).hostname;
5138
4320
  } catch {
@@ -5586,6 +4768,9 @@ A 402 may offer up to three rails; you don't choose per payment \u2014 the clien
5586
4768
  (e.g. PayAI) \u2014 broadcasts it, so you pay ZERO gas (you need only the token, no native coin). It
5587
4769
  works on EVM, Solana, Algorand, Aptos + NEAR, and the on-chain method (EIP-3009 / Permit2 / SVM /
5588
4770
  Algorand fee-pooled group / Aptos fee-payer / NEAR SignedDelegateAction) is picked automatically.
4771
+ XRPL also supports exact (native XRP), with ONE difference that matters to your budget: there the
4772
+ PAYER pays the network fee, because on the XRP Ledger the fee lives inside the signed transaction.
4773
+ So keep a little XRP for fees on that chain \u2014 everywhere else exact means you need no native coin.
5589
4774
  - upto (the metered/variable x402 rail, opt-in, EVM): the amount you see is a MAXIMUM \u2014 you sign
5590
4775
  a ceiling, the server meters real usage and settles the ACTUAL (<= the max). BUDGET AGAINST THE MAX:
5591
4776
  the plan/policy treat the ceiling as the spend (a server may charge up to it), so a payable plan
@@ -6395,82 +5580,61 @@ var KNOWN_FACILITATORS = {
6395
5580
  keyless: true,
6396
5581
  schemes: ["exact"],
6397
5582
  settles: ["eip3009"],
6398
- note: "PayAI \u2014 keyless, sponsors gas (Base USDC EIP-3009). Verified 2026-06-14 (/supported + live demo)."
5583
+ note: "PayAI: keyless, sponsors gas (Base USDC EIP-3009). Verified 2026-06-14 (/supported + live demo)."
6399
5584
  },
6400
5585
  {
6401
5586
  url: "https://facilitator.xpay.sh",
6402
5587
  keyless: true,
6403
5588
  schemes: ["exact"],
6404
5589
  settles: ["eip3009"],
6405
- note: "xpay \u2014 keyless, zero-fee, sponsors gas. LIVE-settled on Base 2026-06-15 (tx 0x2273d5\u2026)."
5590
+ note: "xpay: keyless, zero-fee, sponsors gas. LIVE-settled on Base 2026-06-15 (tx 0x2273d5\u2026)."
6406
5591
  },
6407
5592
  {
6408
5593
  url: "https://facilitator.ultravioletadao.xyz",
6409
5594
  keyless: true,
6410
5595
  schemes: ["exact"],
6411
5596
  settles: ["eip3009"],
6412
- note: "Ultravioleta DAO \u2014 keyless, 100% gas-sponsored (Base USDC EIP-3009). LIVE-settled on Base 2026-06-17 (tx 0x58a69042a4129be649c5642456752ede95a5ff921daddfd30560ae70ae5907ff). 2nd UVD validation chain (after HyperEVM)."
5597
+ note: "Ultravioleta DAO: keyless, 100% gas-sponsored (Base USDC EIP-3009). LIVE-settled on Base 2026-06-17 (tx 0x58a69042a4129be649c5642456752ede95a5ff921daddfd30560ae70ae5907ff). 2nd UVD validation chain (after HyperEVM)."
6413
5598
  },
6414
5599
  {
6415
5600
  url: "https://x402.dexter.cash",
6416
5601
  keyless: true,
6417
5602
  schemes: ["exact"],
6418
5603
  settles: ["eip3009"],
6419
- note: "Dexter \u2014 keyless, gas-sponsored (Base USDC EIP-3009). LIVE-settled on Base 2026-06-17 (tx 0xdf030e4d5bf41a88c5a3bfe73bb433dfbb90b058d3b8ded63b68e026eedb9de8). Note: ~$0.001 dynamic floor on Base."
6420
- },
6421
- {
6422
- url: "https://facilitator.corbits.dev",
6423
- keyless: true,
6424
- schemes: ["exact"],
6425
- settles: ["eip3009"],
6426
- note: "Corbits (Faremeter) \u2014 keyless, sponsors gas (Base USDC EIP-3009). LIVE-settled on Base 2026-06-17 (tx 0x2e41c581af023100429ada81f1371bef82d41dd577ed438d72ddc18676d4213d). Also seeded on Monad + Solana."
5604
+ note: "Dexter: keyless, gas-sponsored (Base USDC EIP-3009). LIVE-settled on Base 2026-06-17 (tx 0xdf030e4d5bf41a88c5a3bfe73bb433dfbb90b058d3b8ded63b68e026eedb9de8). Note: ~$0.001 dynamic floor on Base."
6427
5605
  },
6428
5606
  {
6429
5607
  url: "https://facilitator.goplausible.xyz",
6430
5608
  keyless: true,
6431
5609
  schemes: ["exact"],
6432
5610
  settles: ["eip3009"],
6433
- note: "GoPlausible \u2014 keyless, sponsors gas (Base USDC EIP-3009). LIVE-settled on Base 2026-06-17 (tx 0x9bcbc1f01fe1fd1aed2a79e5582555164cc4185e9800189df378a6b46eb9c59e). 2nd GoPlausible validation chain (after Algorand)."
5611
+ note: "GoPlausible: keyless, sponsors gas (Base USDC EIP-3009). LIVE-settled on Base 2026-06-17 (tx 0x9bcbc1f01fe1fd1aed2a79e5582555164cc4185e9800189df378a6b46eb9c59e). 2nd GoPlausible validation chain (after Algorand)."
6434
5612
  },
6435
5613
  {
6436
5614
  url: "https://facilitator.cascade.fyi",
6437
5615
  keyless: true,
6438
5616
  schemes: ["exact"],
6439
5617
  settles: ["eip3009"],
6440
- note: "Cascade \u2014 keyless, sponsors gas (Base USDC EIP-3009). LIVE-settled on Base 2026-06-18 (tx 0x2e784725f3c66e170720cc8df43a9248f02ad80914fcbe05dadbdbe411c3b52b)."
6441
- },
6442
- {
6443
- url: "https://facilitator.bitcoinsapi.com",
6444
- keyless: true,
6445
- schemes: ["exact"],
6446
- settles: ["eip3009"],
6447
- note: "Satoshi (bitcoinsapi) \u2014 keyless, sponsors gas (Base USDC EIP-3009). LIVE-settled on Base 2026-06-18 (tx 0xbb2b6c354b12c6d07cce91e2b337e38327d4b0833bbd1dfbeda3ad495b67b819)."
5618
+ note: "Cascade: keyless, sponsors gas (Base USDC EIP-3009). LIVE-settled on Base 2026-06-18 (tx 0x2e784725f3c66e170720cc8df43a9248f02ad80914fcbe05dadbdbe411c3b52b)."
6448
5619
  }
6449
5620
  ],
6450
5621
  // Monad (eip155:143). Corbits + Ultravioleta DAO each keyless-settle the EVM EIP-3009 exact rail
6451
5622
  // (Monad's native Circle USDC), buyer paid zero gas — real LIVE settles, not just /supported reads.
6452
5623
  // Makes `exact: true` zero-config gasless on Monad.
6453
5624
  "eip155:143": [
6454
- {
6455
- url: "https://facilitator.corbits.dev",
6456
- keyless: true,
6457
- schemes: ["exact"],
6458
- settles: ["eip3009"],
6459
- note: "Corbits (Faremeter) \u2014 keyless, sponsors gas (Monad native USDC EIP-3009). LIVE-settled on Monad 2026-06-17 (tx 0x7797be27ce22c17f7433a0389bd22d46e338899b1faac505fffd068174428ae6)."
6460
- },
6461
5625
  {
6462
5626
  url: "https://facilitator.ultravioletadao.xyz",
6463
5627
  keyless: true,
6464
5628
  schemes: ["exact"],
6465
5629
  settles: ["eip3009"],
6466
- note: "Ultravioleta DAO \u2014 keyless, 100% gas-sponsored (Monad native USDC EIP-3009). LIVE-settled on Monad 2026-06-17 (tx 0xb107576effbaceb5586c07a9ddc996ef2b6d455f1858314995ef83a7c6e64d11). 3rd UVD validation chain."
5630
+ note: "Ultravioleta DAO: keyless, 100% gas-sponsored (Monad native USDC EIP-3009). LIVE-settled on Monad 2026-06-17 (tx 0xb107576effbaceb5586c07a9ddc996ef2b6d455f1858314995ef83a7c6e64d11). 3rd UVD validation chain."
6467
5631
  },
6468
5632
  {
6469
5633
  url: "https://facilitator.pieverse.io",
6470
5634
  keyless: true,
6471
5635
  schemes: ["exact"],
6472
5636
  settles: ["eip3009"],
6473
- note: "Pieverse \u2014 keyless, sponsors gas (Monad USDC EIP-3009). LIVE-settled on Monad 2026-06-17 (tx 0x00cfeb93876e5ef57dcb002510038b7304913233ca286d7ab33c72a8b119eb0d)."
5637
+ note: "Pieverse: keyless, sponsors gas (Monad USDC EIP-3009). LIVE-settled on Monad 2026-06-17 (tx 0x00cfeb93876e5ef57dcb002510038b7304913233ca286d7ab33c72a8b119eb0d)."
6474
5638
  }
6475
5639
  ],
6476
5640
  // BNB Chain (eip155:56). Dexter + Pieverse keyless-settle the EVM EIP-3009 exact rail for BNB's
@@ -6484,14 +5648,14 @@ var KNOWN_FACILITATORS = {
6484
5648
  keyless: true,
6485
5649
  schemes: ["exact"],
6486
5650
  settles: ["eip3009"],
6487
- note: "Dexter \u2014 keyless, gas-sponsored. BNB EIP-3009 tokens FDUSD/USD1/U (Binance-Peg USDC/USDT are Permit2 \u2192 not facilitator-settleable); ~$0.003 dynamic floor. LIVE-settled on BNB 2026-06-17 with FDUSD (tx 0x6d9eb4e4939f3f3c74cb19424cc7822d66ec8ed5c5c7c330d9f88a5f9ad59e9e); accepts U (verify confirmed 2026-06-21)."
5651
+ note: "Dexter: keyless, gas-sponsored. BNB EIP-3009 tokens FDUSD/USD1/U (Binance-Peg USDC/USDT are Permit2 \u2192 not facilitator-settleable); ~$0.003 dynamic floor. LIVE-settled on BNB 2026-06-17 with FDUSD (tx 0x6d9eb4e4939f3f3c74cb19424cc7822d66ec8ed5c5c7c330d9f88a5f9ad59e9e); accepts U (verify confirmed 2026-06-21)."
6488
5652
  },
6489
5653
  {
6490
5654
  url: "https://facilitator.pieverse.io",
6491
5655
  keyless: true,
6492
5656
  schemes: ["exact"],
6493
5657
  settles: ["eip3009"],
6494
- note: "Pieverse \u2014 keyless, sponsors gas. BNB EIP-3009 tokens FDUSD/USD1/U (same Binance-Peg caveat as Dexter). LIVE-settled on BNB with FDUSD 2026-06-17 (tx 0xb9c76affc45bd07a51559efd813ca71516fc30625478724476c2cf42fc2203d3) AND with the U / United Stables token 2026-06-21 (tx 0x2b3b8c51ae81df441551301c44a64652c84c796af3b9d03ec58ea38f1cb013d5, buyer 0 BNB) \u2014 a 2nd keyless BNB facilitator (failover for Dexter)."
5658
+ note: "Pieverse: keyless, sponsors gas. BNB EIP-3009 tokens FDUSD/USD1/U (same Binance-Peg caveat as Dexter). LIVE-settled on BNB with FDUSD 2026-06-17 (tx 0xb9c76affc45bd07a51559efd813ca71516fc30625478724476c2cf42fc2203d3) AND with the U / United Stables token 2026-06-21 (tx 0x2b3b8c51ae81df441551301c44a64652c84c796af3b9d03ec58ea38f1cb013d5, buyer 0 BNB). A 2nd keyless BNB facilitator (failover for Dexter)."
6495
5659
  }
6496
5660
  ],
6497
5661
  // HyperEVM (eip155:999). Ultravioleta DAO keyless-settles the EVM EIP-3009 exact rail (HyperEVM's
@@ -6504,7 +5668,7 @@ var KNOWN_FACILITATORS = {
6504
5668
  keyless: true,
6505
5669
  schemes: ["exact"],
6506
5670
  settles: ["eip3009"],
6507
- note: "Ultravioleta DAO \u2014 keyless, 100% gas-sponsored (HyperEVM native USDC EIP-3009). LIVE-settled on HyperEVM 2026-06-17 (tx 0x56af8148a92a291f0ce362e250919f7742074e5464ac0f315ad68abaec93bd0a)."
5671
+ note: "Ultravioleta DAO: keyless, 100% gas-sponsored (HyperEVM native USDC EIP-3009). LIVE-settled on HyperEVM 2026-06-17 (tx 0x56af8148a92a291f0ce362e250919f7742074e5464ac0f315ad68abaec93bd0a)."
6508
5672
  }
6509
5673
  ],
6510
5674
  // ── gasless-extension (2026-06-18): 7 more EVM mainnets, each LIVE-settled by us — a real EIP-3009
@@ -6521,7 +5685,7 @@ var KNOWN_FACILITATORS = {
6521
5685
  keyless: true,
6522
5686
  schemes: ["exact"],
6523
5687
  settles: ["eip3009"],
6524
- note: "Ultravioleta DAO \u2014 keyless, 100% gas-sponsored (Ethereum native USDC EIP-3009; no settlement floor). LIVE-settled on Ethereum mainnet 2026-06-18 (tx 0x7fcc3cafdf43c52888f0117cde633eff35371f832dfb8dbd84e6fd7704ae5cfc)."
5688
+ note: "Ultravioleta DAO: keyless, 100% gas-sponsored (Ethereum native USDC EIP-3009; no settlement floor). LIVE-settled on Ethereum mainnet 2026-06-18 (tx 0x7fcc3cafdf43c52888f0117cde633eff35371f832dfb8dbd84e6fd7704ae5cfc)."
6525
5689
  }
6526
5690
  ],
6527
5691
  // Polygon PoS (eip155:137) — FIVE keyless facilitators (the broadest after Base), all live-settled.
@@ -6531,35 +5695,28 @@ var KNOWN_FACILITATORS = {
6531
5695
  keyless: true,
6532
5696
  schemes: ["exact"],
6533
5697
  settles: ["eip3009"],
6534
- note: "PayAI \u2014 keyless, sponsors gas (Polygon native USDC EIP-3009). LIVE-settled on Polygon 2026-06-18 (tx 0xb37630871504618c4db35e8ef0edd3c99deac102b143b7e5eb738c03fb13a619)."
5698
+ note: "PayAI: keyless, sponsors gas (Polygon native USDC EIP-3009). LIVE-settled on Polygon 2026-06-18 (tx 0xb37630871504618c4db35e8ef0edd3c99deac102b143b7e5eb738c03fb13a619)."
6535
5699
  },
6536
5700
  {
6537
5701
  url: "https://x402.polygon.technology",
6538
5702
  keyless: true,
6539
5703
  schemes: ["exact"],
6540
5704
  settles: ["eip3009"],
6541
- note: "Polygon Labs (the official Polygon facilitator) \u2014 keyless, sponsors gas. LIVE-settled on Polygon 2026-06-18 (tx 0x6a8ca60ea111959a61a85ad6c4f2ed99e192052ec7b9ffb59baa33691a86f419)."
6542
- },
6543
- {
6544
- url: "https://facilitator.corbits.dev",
6545
- keyless: true,
6546
- schemes: ["exact"],
6547
- settles: ["eip3009"],
6548
- note: "Corbits (Faremeter) \u2014 keyless, sponsors gas. LIVE-settled on Polygon 2026-06-18 (tx 0x2fadca2ee3cd7fcff32d015e8b06109de6b747d7cd0f80dcd8fb022b2d58d008)."
5705
+ note: "Polygon Labs (the official Polygon facilitator): keyless, sponsors gas. LIVE-settled on Polygon 2026-06-18 (tx 0x6a8ca60ea111959a61a85ad6c4f2ed99e192052ec7b9ffb59baa33691a86f419)."
6549
5706
  },
6550
5707
  {
6551
5708
  url: "https://facilitator.ultravioletadao.xyz",
6552
5709
  keyless: true,
6553
5710
  schemes: ["exact"],
6554
5711
  settles: ["eip3009"],
6555
- note: "Ultravioleta DAO \u2014 keyless, 100% gas-sponsored. LIVE-settled on Polygon 2026-06-18 (tx 0x0922cd78f3b7c35cc294cf0c0d9b7609e6596eb337be0d197fa5fc511eacba34)."
5712
+ note: "Ultravioleta DAO: keyless, 100% gas-sponsored. LIVE-settled on Polygon 2026-06-18 (tx 0x0922cd78f3b7c35cc294cf0c0d9b7609e6596eb337be0d197fa5fc511eacba34)."
6556
5713
  },
6557
5714
  {
6558
5715
  url: "https://x402.dexter.cash",
6559
5716
  keyless: true,
6560
5717
  schemes: ["exact"],
6561
5718
  settles: ["eip3009"],
6562
- note: "Dexter \u2014 keyless, sponsors gas; ~$0.004 dynamic settlement floor (sub-floor \u2192 amount_too_low). LIVE-settled on Polygon 2026-06-18 at $0.005 (tx 0x4a7cfc96e4e2496652435c77b0021db4a459e7bcd97948c15e6bea09077c164b)."
5719
+ note: "Dexter: keyless, sponsors gas; ~$0.004 dynamic settlement floor (sub-floor \u2192 amount_too_low). LIVE-settled on Polygon 2026-06-18 at $0.005 (tx 0x4a7cfc96e4e2496652435c77b0021db4a459e7bcd97948c15e6bea09077c164b)."
6563
5720
  }
6564
5721
  ],
6565
5722
  // Arbitrum One (eip155:42161) — PayAI + UVD + Dexter.
@@ -6569,21 +5726,21 @@ var KNOWN_FACILITATORS = {
6569
5726
  keyless: true,
6570
5727
  schemes: ["exact"],
6571
5728
  settles: ["eip3009"],
6572
- note: "PayAI \u2014 keyless, sponsors gas (Arbitrum native USDC EIP-3009). LIVE-settled on Arbitrum 2026-06-18 (tx 0x4c7fbfb37ef087bb9bc8872b1b2b0b83ea7ca4cf6b50bc883e51f9b85be61199)."
5729
+ note: "PayAI: keyless, sponsors gas (Arbitrum native USDC EIP-3009). LIVE-settled on Arbitrum 2026-06-18 (tx 0x4c7fbfb37ef087bb9bc8872b1b2b0b83ea7ca4cf6b50bc883e51f9b85be61199)."
6573
5730
  },
6574
5731
  {
6575
5732
  url: "https://facilitator.ultravioletadao.xyz",
6576
5733
  keyless: true,
6577
5734
  schemes: ["exact"],
6578
5735
  settles: ["eip3009"],
6579
- note: "Ultravioleta DAO \u2014 keyless, 100% gas-sponsored. LIVE-settled on Arbitrum 2026-06-18 (tx 0xd1fa7e6ffbd59502bba5809ce181d7936749b93a45c8c2277b4f6d8638326dec)."
5736
+ note: "Ultravioleta DAO: keyless, 100% gas-sponsored. LIVE-settled on Arbitrum 2026-06-18 (tx 0xd1fa7e6ffbd59502bba5809ce181d7936749b93a45c8c2277b4f6d8638326dec)."
6580
5737
  },
6581
5738
  {
6582
5739
  url: "https://x402.dexter.cash",
6583
5740
  keyless: true,
6584
5741
  schemes: ["exact"],
6585
5742
  settles: ["eip3009"],
6586
- note: "Dexter \u2014 keyless, sponsors gas; ~$0.004 dynamic floor. LIVE-settled on Arbitrum 2026-06-18 at $0.005 (tx 0x0993d51b3859dfd7e8d5b2af709ce64f01ff34ed14bfef665dbb340e7373d599)."
5743
+ note: "Dexter: keyless, sponsors gas; ~$0.004 dynamic floor. LIVE-settled on Arbitrum 2026-06-18 at $0.005 (tx 0x0993d51b3859dfd7e8d5b2af709ce64f01ff34ed14bfef665dbb340e7373d599)."
6587
5744
  }
6588
5745
  ],
6589
5746
  // Optimism (eip155:10) — Dexter + UVD.
@@ -6593,14 +5750,14 @@ var KNOWN_FACILITATORS = {
6593
5750
  keyless: true,
6594
5751
  schemes: ["exact"],
6595
5752
  settles: ["eip3009"],
6596
- note: "Dexter \u2014 keyless, sponsors gas; ~$0.004 dynamic floor. LIVE-settled on Optimism 2026-06-18 at $0.005 (tx 0x98b282a5dd698054eff4900ff8547170d4f7605b51140c55147fc5ae485f81da)."
5753
+ note: "Dexter: keyless, sponsors gas; ~$0.004 dynamic floor. LIVE-settled on Optimism 2026-06-18 at $0.005 (tx 0x98b282a5dd698054eff4900ff8547170d4f7605b51140c55147fc5ae485f81da)."
6597
5754
  },
6598
5755
  {
6599
5756
  url: "https://facilitator.ultravioletadao.xyz",
6600
5757
  keyless: true,
6601
5758
  schemes: ["exact"],
6602
5759
  settles: ["eip3009"],
6603
- note: "Ultravioleta DAO \u2014 keyless, 100% gas-sponsored. LIVE-settled on Optimism 2026-06-18 (tx 0xdd91dfdf12bed2d196e37fa1dea9a0da71a97e3c39a0ec0ed114be6a9af22837)."
5760
+ note: "Ultravioleta DAO: keyless, 100% gas-sponsored. LIVE-settled on Optimism 2026-06-18 (tx 0xdd91dfdf12bed2d196e37fa1dea9a0da71a97e3c39a0ec0ed114be6a9af22837)."
6604
5761
  }
6605
5762
  ],
6606
5763
  // Avalanche C-Chain (eip155:43114) — PayAI + Dexter. (UVD advertises it but contract_call_failed → unseeded.)
@@ -6610,14 +5767,14 @@ var KNOWN_FACILITATORS = {
6610
5767
  keyless: true,
6611
5768
  schemes: ["exact"],
6612
5769
  settles: ["eip3009"],
6613
- note: "PayAI \u2014 keyless, sponsors gas (Avalanche native USDC EIP-3009). LIVE-settled on Avalanche 2026-06-18 (tx 0x6a1307bc48a157de236ea03440ea2cb6ad4f27e22dd9c89a4345b4c3edb270c7)."
5770
+ note: "PayAI: keyless, sponsors gas (Avalanche native USDC EIP-3009). LIVE-settled on Avalanche 2026-06-18 (tx 0x6a1307bc48a157de236ea03440ea2cb6ad4f27e22dd9c89a4345b4c3edb270c7)."
6614
5771
  },
6615
5772
  {
6616
5773
  url: "https://x402.dexter.cash",
6617
5774
  keyless: true,
6618
5775
  schemes: ["exact"],
6619
5776
  settles: ["eip3009"],
6620
- note: "Dexter \u2014 keyless, sponsors gas (no floor hit at $0.001 here). LIVE-settled on Avalanche 2026-06-18 (tx 0xb2263e9a4ea3917eee6acabcb454d42a50264fdd69a0781ed8fcaec5590e264b)."
5777
+ note: "Dexter: keyless, sponsors gas (no floor hit at $0.001 here). LIVE-settled on Avalanche 2026-06-18 (tx 0xb2263e9a4ea3917eee6acabcb454d42a50264fdd69a0781ed8fcaec5590e264b)."
6621
5778
  }
6622
5779
  ],
6623
5780
  // Sei (eip155:1329) — PayAI (the only keyless facilitator that lists Sei).
@@ -6627,7 +5784,7 @@ var KNOWN_FACILITATORS = {
6627
5784
  keyless: true,
6628
5785
  schemes: ["exact"],
6629
5786
  settles: ["eip3009"],
6630
- note: "PayAI \u2014 keyless, sponsors gas (Sei native USDC EIP-3009). LIVE-settled on Sei 2026-06-18 (tx 0xde63679b64749cb59625527e5c7682503c851d66b9b8b8ba217ed7b099461312)."
5787
+ note: "PayAI: keyless, sponsors gas (Sei native USDC EIP-3009). LIVE-settled on Sei 2026-06-18 (tx 0xde63679b64749cb59625527e5c7682503c851d66b9b8b8ba217ed7b099461312)."
6631
5788
  }
6632
5789
  ],
6633
5790
  // Unichain (eip155:130) — UVD (the only keyless facilitator that lists Unichain).
@@ -6637,7 +5794,7 @@ var KNOWN_FACILITATORS = {
6637
5794
  keyless: true,
6638
5795
  schemes: ["exact"],
6639
5796
  settles: ["eip3009"],
6640
- note: "Ultravioleta DAO \u2014 keyless, 100% gas-sponsored (Unichain native USDC EIP-3009). LIVE-settled on Unichain 2026-06-18 (tx 0xf8bf4a9a200f24159ac67c6315c30b194257999d7da21471b39d5f2cc32b2236)."
5797
+ note: "Ultravioleta DAO: keyless, 100% gas-sponsored (Unichain native USDC EIP-3009). LIVE-settled on Unichain 2026-06-18 (tx 0xf8bf4a9a200f24159ac67c6315c30b194257999d7da21471b39d5f2cc32b2236)."
6641
5798
  }
6642
5799
  ],
6643
5800
  // Algorand (mainnet, CAIP-2 = full base64 genesis hash). GoPlausible keyless-settles the ratified
@@ -6653,7 +5810,7 @@ var KNOWN_FACILITATORS = {
6653
5810
  keyless: true,
6654
5811
  schemes: ["exact"],
6655
5812
  settles: ["algorand"],
6656
- note: "GoPlausible \u2014 keyless, 100% gas-sponsored (Algorand USDCa, atomic-group fee pooling; both buyer AND merchant pay 0 ALGO). LIVE-settled on Algorand mainnet 2026-06-17 (tx PDVDVRFGJAG2K6AJ7L26OTSCSRL7AURVKEX4D4KHBAOLNSCYENXA). The only keyless Algorand x402 facilitator."
5813
+ note: "GoPlausible: keyless, 100% gas-sponsored (Algorand USDCa, atomic-group fee pooling; both buyer AND merchant pay 0 ALGO). LIVE-settled on Algorand mainnet 2026-06-17 (tx PDVDVRFGJAG2K6AJ7L26OTSCSRL7AURVKEX4D4KHBAOLNSCYENXA). The only keyless Algorand x402 facilitator."
6657
5814
  }
6658
5815
  ],
6659
5816
  // Solana (mainnet-beta). Keyless fee-payer sponsors for the SVM exact rail, each LIVE-settled
@@ -6666,21 +5823,14 @@ var KNOWN_FACILITATORS = {
6666
5823
  keyless: true,
6667
5824
  schemes: ["exact"],
6668
5825
  settles: ["svm"],
6669
- note: "PayAI \u2014 keyless fee-payer sponsor (Solana SPL SVM). LIVE-settled 2026-06-14 (tx 4dL8jRKH\u2026)."
5826
+ note: "PayAI: keyless fee-payer sponsor (Solana SPL SVM). LIVE-settled 2026-06-14 (tx 4dL8jRKH\u2026)."
6670
5827
  },
6671
5828
  {
6672
5829
  url: "https://pay.openfacilitator.io",
6673
5830
  keyless: true,
6674
5831
  schemes: ["exact"],
6675
5832
  settles: ["svm"],
6676
- note: "OpenFacilitator \u2014 keyless (no signup), fee-payer sponsor. LIVE-settled on Solana 2026-06-15 (tx 5BabDtX\u2026)."
6677
- },
6678
- {
6679
- url: "https://facilitator.corbits.dev",
6680
- keyless: true,
6681
- schemes: ["exact"],
6682
- settles: ["svm"],
6683
- note: "Corbits \u2014 keyless, Solana-first fee-payer sponsor. LIVE-settled on Solana 2026-06-15 (tx BCreYer\u2026)."
5833
+ note: "OpenFacilitator: keyless (no signup), fee-payer sponsor. LIVE-settled on Solana 2026-06-15 (tx 5BabDtX\u2026)."
6684
5834
  }
6685
5835
  ]
6686
5836
  // NEAR (near:mainnet) — DELIBERATELY UNSEEDED: no x402 facilitator settles NEAR yet.
@@ -6871,7 +6021,7 @@ function createPaymentGate(options) {
6871
6021
  );
6872
6022
  }
6873
6023
  return {
6874
- skipReason: `${net.network}: this token isn't EIP-3009 (auto-selected Permit2), which a third-party facilitator can't settle \u2014 it would serve onchain-proof only here. Use an EIP-3009 token (USDC / EURC) with the facilitator, or \`settle: 'self'\` to settle Permit2 yourself.`
6024
+ skipReason: `${net.network}: auto-selected Permit2, which a third-party facilitator can't settle \u2014 it would serve onchain-proof only here. Either this token isn't EIP-3009 (use USDC / EURC with the facilitator, or \`settle: 'self'\` to settle Permit2 yourself), OR the EIP-712 domain read failed on your RPC (transient): if you expected a gasless rail here, pass a reliable \`rpcUrl\` and retry.`
6875
6025
  };
6876
6026
  }
6877
6027
  const mode = settle === "self" ? { kind: "self", relayer } : {
@@ -7198,8 +6348,8 @@ function createPaymentGate(options) {
7198
6348
  maxTimeoutSeconds,
7199
6349
  ...s.symbol ? { symbol: s.symbol } : {}
7200
6350
  };
7201
- if (s.exact) accepts.push({ scheme: "exact", ...base2, ...railExtra(buildExactAccept(s).extra) });
7202
- if (s.upto) accepts.push({ scheme: "upto", ...base2, ...railExtra(buildUptoAccept(s).extra) });
6351
+ if (s.exact) accepts.push({ scheme: "exact", ...base2, ...railExtra(buildExactAccept(s).extra ?? {}) });
6352
+ if (s.upto) accepts.push({ scheme: "upto", ...base2, ...railExtra(buildUptoAccept(s).extra ?? {}) });
7203
6353
  accepts.push({ scheme: "onchain-proof", ...base2 });
7204
6354
  }
7205
6355
  return {
@@ -7212,7 +6362,7 @@ function createPaymentGate(options) {
7212
6362
  async function verifyOnchainProof(sig) {
7213
6363
  const specs = await ready();
7214
6364
  const spec = specs.find(
7215
- (s) => s.net.network === sig.accepted.network && s.asset === sig.accepted.asset
6365
+ (s) => normalizeNetwork(s.net.network) === normalizeNetwork(sig.accepted.network) && s.asset === sig.accepted.asset
7216
6366
  );
7217
6367
  if (!spec) {
7218
6368
  return rejection(
@@ -7220,7 +6370,7 @@ function createPaymentGate(options) {
7220
6370
  `Proof claims ${sig.accepted.asset} on ${sig.accepted.network}, which this resource doesn't accept (offered: ${specs.map((s) => `${s.asset}@${s.net.network}`).join(", ")}).`
7221
6371
  );
7222
6372
  }
7223
- const ref = sig.payload.txHash;
6373
+ const ref = typeof sig.payload.txHash === "string" ? sig.payload.txHash.trim() : sig.payload.txHash;
7224
6374
  if (await claimTx(ref)) return rejection("tx_already_used", `Proof ${ref} was already redeemed.`);
7225
6375
  let result;
7226
6376
  try {
@@ -7254,7 +6404,8 @@ function createPaymentGate(options) {
7254
6404
  return rejection("transfer_not_found", "This resource offers no standard `exact` rail.");
7255
6405
  }
7256
6406
  const isCaip = exact.network.includes(":");
7257
- let candidates = isCaip ? exactSpecs.filter((s) => s.net.network === exact.network) : exactSpecs;
6407
+ const wantExactNet = normalizeNetwork(exact.network);
6408
+ let candidates = isCaip ? exactSpecs.filter((s) => normalizeNetwork(s.net.network) === wantExactNet) : exactSpecs;
7258
6409
  if (exact.asset) {
7259
6410
  candidates = candidates.filter((s) => s.asset.toLowerCase() === exact.asset.toLowerCase());
7260
6411
  }
@@ -7297,6 +6448,8 @@ function createPaymentGate(options) {
7297
6448
  } catch {
7298
6449
  nonce = exact.payload.signedDelegateAction;
7299
6450
  }
6451
+ } else if ("signedTxBlob" in exact.payload) {
6452
+ nonce = exact.payload.signedTxBlob.trim().toUpperCase();
7300
6453
  } else if ("permit2Authorization" in exact.payload) {
7301
6454
  evmAuth = exact.payload.permit2Authorization;
7302
6455
  nonce = evmAuth.nonce;
@@ -7314,9 +6467,9 @@ function createPaymentGate(options) {
7314
6467
  if (mode.kind === "self") {
7315
6468
  result = await spec.net.settleExactSelf({ relayer: mode.relayer, payload: exact.payload, accept });
7316
6469
  } else {
7317
- const ftMethod = accept.extra.assetTransferMethod;
6470
+ const ftMethod = accept.extra?.assetTransferMethod;
7318
6471
  const needsFeePayer = ftMethod === "svm" || ftMethod === "algorand" || ftMethod === "aptos" || ftMethod === "near";
7319
- if (needsFeePayer && !accept.extra.feePayer) {
6472
+ if (needsFeePayer && !accept.extra?.feePayer) {
7320
6473
  throw new SettlementError(
7321
6474
  `exact settle: the ${ftMethod} facilitator rail is missing extra.feePayer (the gas sponsor) \u2014 cannot settle.`
7322
6475
  );
@@ -7337,7 +6490,7 @@ function createPaymentGate(options) {
7337
6490
  amount: accept.amount,
7338
6491
  payTo: accept.payTo,
7339
6492
  maxTimeoutSeconds: accept.maxTimeoutSeconds,
7340
- extra: needsFeePayer ? { feePayer: accept.extra.feePayer } : { name: accept.extra.name ?? "", version: accept.extra.version ?? "" }
6493
+ extra: needsFeePayer ? { feePayer: accept.extra.feePayer } : { name: accept.extra?.name ?? "", version: accept.extra?.version ?? "" }
7341
6494
  },
7342
6495
  receipt: { network: accept.network, asset: accept.asset, payTo: accept.payTo, amount: accept.amount },
7343
6496
  // The buyer address, for the receipt's `payer` fallback. EVM carries it in the
@@ -7385,7 +6538,8 @@ function createPaymentGate(options) {
7385
6538
  return rejection("transfer_not_found", "This resource offers no standard `upto` (metered) rail.");
7386
6539
  }
7387
6540
  const isCaip = upto.network.includes(":");
7388
- let candidates = isCaip ? uptoSpecs.filter((s) => s.net.network === upto.network) : uptoSpecs;
6541
+ const wantUptoNet = normalizeNetwork(upto.network);
6542
+ let candidates = isCaip ? uptoSpecs.filter((s) => normalizeNetwork(s.net.network) === wantUptoNet) : uptoSpecs;
7389
6543
  if (upto.asset) {
7390
6544
  candidates = candidates.filter((s) => s.asset.toLowerCase() === upto.asset.toLowerCase());
7391
6545
  }
@@ -8130,6 +7284,7 @@ export {
8130
7284
  BUILTIN_DENOMS,
8131
7285
  CHAINS,
8132
7286
  ConfirmationTimeoutError,
7287
+ DEFAULT_EXACT_TRANSFER_METHOD,
8133
7288
  DENOM_PRECISION,
8134
7289
  DIRECTORY_INFO,
8135
7290
  EIP3009_TYPES,
@@ -8145,6 +7300,7 @@ export {
8145
7300
  InsufficientFundsError,
8146
7301
  InvalidConfigError,
8147
7302
  InvalidEnvelopeError,
7303
+ KNOWN_EXACT_TRANSFER_METHODS,
8148
7304
  KNOWN_FACILITATORS,
8149
7305
  MCP_PAYMENT_META_KEY,
8150
7306
  MCP_PAYMENT_RESPONSE_META_KEY,
@@ -8193,6 +7349,7 @@ export {
8193
7349
  buildSelfDescription,
8194
7350
  buildSignatureHeader,
8195
7351
  buildUptoSignatureHeader,
7352
+ buildV1PaymentHeader,
8196
7353
  buildWellKnownX402,
8197
7354
  buildWellKnownX402Manifest,
8198
7355
  buildX402DnsTxt,
@@ -8213,6 +7370,7 @@ export {
8213
7370
  eip3009Abi,
8214
7371
  encodeXPaymentHeader,
8215
7372
  evaluatePolicy,
7373
+ exactTransferMethod,
8216
7374
  explainDecline,
8217
7375
  facilitatorCoverage,
8218
7376
  fetchAcross,
@@ -8226,10 +7384,12 @@ export {
8226
7384
  getDirectoryInfo,
8227
7385
  isMcpPaymentRequired,
8228
7386
  isPermit2ProxyChain,
7387
+ isSettleableExactMethod,
8229
7388
  isUptoProxyChain,
8230
7389
  knownFacilitatorsFor,
8231
7390
  memorySpendStore,
8232
7391
  normalizeNetwork,
7392
+ normalizeV1Challenge,
8233
7393
  parseChallenge,
8234
7394
  parseExactObject,
8235
7395
  parseExactPaymentHeader,