@devlab.group/agent-commerce 2.4.0 → 2.5.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 (108) hide show
  1. package/README.md +115 -15
  2. package/dist/ap2.d.ts +24 -12
  3. package/dist/ap2.js +31 -13
  4. package/dist/ap2.js.map +1 -1
  5. package/dist/{chunk-AITMDXKW.js → chunk-3OTCFFFT.js} +37 -4
  6. package/dist/chunk-3OTCFFFT.js.map +1 -0
  7. package/dist/{chunk-4OEXK3YG.js → chunk-4K7FIBJM.js} +25 -4
  8. package/dist/chunk-4K7FIBJM.js.map +1 -0
  9. package/dist/{chunk-WUIAUAA7.js → chunk-FKQK5XZA.js} +652 -68
  10. package/dist/chunk-FKQK5XZA.js.map +1 -0
  11. package/dist/chunk-GA3O2A7R.js +92 -0
  12. package/dist/chunk-GA3O2A7R.js.map +1 -0
  13. package/dist/{chunk-6WACRJVT.js → chunk-VUCMBGUR.js} +3 -3
  14. package/dist/{chunk-6WACRJVT.js.map → chunk-VUCMBGUR.js.map} +1 -1
  15. package/dist/cli/{ap2-QDHPRSTF.js → ap2-YAPLERSC.js} +34 -15
  16. package/dist/cli/ap2-YAPLERSC.js.map +1 -0
  17. package/dist/cli/{chunk-G2JEY7MB.js → chunk-2J2IQQ4X.js} +8 -7
  18. package/dist/cli/chunk-2J2IQQ4X.js.map +1 -0
  19. package/dist/cli/chunk-2UPPX3FJ.js +311 -0
  20. package/dist/cli/chunk-2UPPX3FJ.js.map +1 -0
  21. package/dist/cli/{chunk-WYOGIANL.js → chunk-4H2QLHQI.js} +4 -4
  22. package/dist/cli/{chunk-WYOGIANL.js.map → chunk-4H2QLHQI.js.map} +1 -1
  23. package/dist/cli/{chunk-OZ4LAWBK.js → chunk-5R7DM5LM.js} +25 -4
  24. package/dist/cli/chunk-5R7DM5LM.js.map +1 -0
  25. package/dist/cli/chunk-663ALDZA.js +92 -0
  26. package/dist/cli/chunk-663ALDZA.js.map +1 -0
  27. package/dist/cli/{chunk-QQ3WY5L3.js → chunk-IDY2735M.js} +36 -104
  28. package/dist/cli/chunk-IDY2735M.js.map +1 -0
  29. package/dist/cli/chunk-JFVRG2HH.js +107 -0
  30. package/dist/cli/chunk-JFVRG2HH.js.map +1 -0
  31. package/dist/cli/chunk-M7NXVRU5.js +8 -0
  32. package/dist/cli/{chunk-UXB65XCS.js.map → chunk-M7NXVRU5.js.map} +1 -1
  33. package/dist/cli/chunk-NIU5EMSB.js +119 -0
  34. package/dist/cli/chunk-NIU5EMSB.js.map +1 -0
  35. package/dist/cli/{chunk-AZDWFVDW.js → chunk-QA2OPHBF.js} +655 -70
  36. package/dist/cli/chunk-QA2OPHBF.js.map +1 -0
  37. package/dist/cli/{chunk-DCMW67JM.js → chunk-QLUCNPRT.js} +404 -161
  38. package/dist/cli/chunk-QLUCNPRT.js.map +1 -0
  39. package/dist/cli/chunk-SYQLJXIU.js +105 -0
  40. package/dist/cli/chunk-SYQLJXIU.js.map +1 -0
  41. package/dist/cli/{chunk-3MGAJ5FX.js → chunk-VJ4EO4LE.js} +3 -3
  42. package/dist/cli/{chunk-3MGAJ5FX.js.map → chunk-VJ4EO4LE.js.map} +1 -1
  43. package/dist/cli/{chunk-PIMFPCNZ.js → chunk-Z34UMZBB.js} +234 -85
  44. package/dist/cli/chunk-Z34UMZBB.js.map +1 -0
  45. package/dist/cli/config-BWFMN2ZB.js +12 -0
  46. package/dist/cli/{config-UI4EDG4L.js.map → config-BWFMN2ZB.js.map} +1 -1
  47. package/dist/cli/index.js +258 -11
  48. package/dist/cli/index.js.map +1 -1
  49. package/dist/cli/{mcp-26LJMN4N.js → mcp-KZEMXLHR.js} +5 -4
  50. package/dist/cli/mcp-KZEMXLHR.js.map +1 -0
  51. package/dist/cli/{near-5AY3HWYF.js → near-U6365VFX.js} +15 -4
  52. package/dist/cli/near-U6365VFX.js.map +1 -0
  53. package/dist/cli/payment-providers-SZL36H3Y.js +6 -0
  54. package/dist/cli/payment-providers-SZL36H3Y.js.map +1 -0
  55. package/dist/cli/{provider-Z4OJNAYI.js → provider-6TKB5ADJ.js} +30 -16
  56. package/dist/cli/provider-6TKB5ADJ.js.map +1 -0
  57. package/dist/cli/receipts-ZGLJWMQG.js +8 -0
  58. package/dist/cli/receipts-ZGLJWMQG.js.map +1 -0
  59. package/dist/cli/reconcile-IC22MJD5.js +4 -0
  60. package/dist/cli/reconcile-IC22MJD5.js.map +1 -0
  61. package/dist/cli/{run-TEPYJUHG.js → run-ZTYPQI4D.js} +151 -115
  62. package/dist/cli/run-ZTYPQI4D.js.map +1 -0
  63. package/dist/cli/svm-KDSPDFJG.js +48 -0
  64. package/dist/cli/svm-KDSPDFJG.js.map +1 -0
  65. package/dist/cli/{x402-BMVONZKA.js → x402-WLYBLODI.js} +10 -9
  66. package/dist/cli/x402-WLYBLODI.js.map +1 -0
  67. package/dist/index.d.ts +112 -12
  68. package/dist/index.js +948 -157
  69. package/dist/index.js.map +1 -1
  70. package/dist/mcp.d.ts +1 -2
  71. package/dist/mcp.js +1 -1
  72. package/dist/mpp.js +24 -11
  73. package/dist/mpp.js.map +1 -1
  74. package/dist/{near-D6C42VPE.js → near-FH7HPZV3.js} +15 -4
  75. package/dist/near-FH7HPZV3.js.map +1 -0
  76. package/dist/{protocol-adapter-C9odYl6l.d.ts → protocol-adapter-DEXpdp8m.d.ts} +102 -48
  77. package/dist/{runtime-Cl_BLVZV.d.ts → runtime-Dz2fSO-P.d.ts} +220 -2
  78. package/dist/svm-KNC3PHMS.js +48 -0
  79. package/dist/svm-KNC3PHMS.js.map +1 -0
  80. package/dist/x402.js +5 -5
  81. package/package.json +1 -1
  82. package/dist/authorization-DjAecwuW.d.ts +0 -115
  83. package/dist/chunk-4OEXK3YG.js.map +0 -1
  84. package/dist/chunk-AITMDXKW.js.map +0 -1
  85. package/dist/chunk-KA2AX5FH.js +0 -44
  86. package/dist/chunk-KA2AX5FH.js.map +0 -1
  87. package/dist/chunk-WUIAUAA7.js.map +0 -1
  88. package/dist/cli/ap2-QDHPRSTF.js.map +0 -1
  89. package/dist/cli/chunk-AZDWFVDW.js.map +0 -1
  90. package/dist/cli/chunk-DCMW67JM.js.map +0 -1
  91. package/dist/cli/chunk-G2JEY7MB.js.map +0 -1
  92. package/dist/cli/chunk-OSTCU6ZK.js +0 -44
  93. package/dist/cli/chunk-OSTCU6ZK.js.map +0 -1
  94. package/dist/cli/chunk-OZ4LAWBK.js.map +0 -1
  95. package/dist/cli/chunk-PIMFPCNZ.js.map +0 -1
  96. package/dist/cli/chunk-QQ3WY5L3.js.map +0 -1
  97. package/dist/cli/chunk-UXB65XCS.js +0 -8
  98. package/dist/cli/config-UI4EDG4L.js +0 -11
  99. package/dist/cli/mcp-26LJMN4N.js.map +0 -1
  100. package/dist/cli/near-5AY3HWYF.js.map +0 -1
  101. package/dist/cli/provider-Z4OJNAYI.js.map +0 -1
  102. package/dist/cli/run-TEPYJUHG.js.map +0 -1
  103. package/dist/cli/svm-3MMYFPC7.js +0 -33
  104. package/dist/cli/svm-3MMYFPC7.js.map +0 -1
  105. package/dist/cli/x402-BMVONZKA.js.map +0 -1
  106. package/dist/near-D6C42VPE.js.map +0 -1
  107. package/dist/svm-QEUAUNPQ.js +0 -33
  108. package/dist/svm-QEUAUNPQ.js.map +0 -1
@@ -1,11 +1,12 @@
1
- import { isWellKnownDevKey, assertPayToIsNotDevAddress, resolveX402Deployment, assertDevKeyIsLocalOnly, describeRpc, x402OfferName } from './chunk-WYOGIANL.js';
2
- import { findX402Network, normalizeAddress, X402_DEFAULT_PAYMENT_FLOW, REUSE_REJECTED_AUTHORIZATION_METADATA_KEY, SETTLE_AFTER_BACKEND_METADATA_KEY, sameAddress, LOCAL_CHAIN_ID, isTransactionReference, isEvmAddress, describeDeploymentMode } from './chunk-OZ4LAWBK.js';
3
- import { computeReplayKey, computePermit2ReplayKey } from './chunk-OSTCU6ZK.js';
4
- import { PACKAGE_VERSION } from './chunk-UXB65XCS.js';
5
- import { CommerceError, systemClock, NOOP_LOGGER, redactedErrorText } from './chunk-QQ3WY5L3.js';
1
+ import { PACKAGE_VERSION } from './chunk-M7NXVRU5.js';
2
+ import { isWellKnownDevKey, assertPayToIsNotDevAddress, resolveX402Deployment, assertDevKeyIsLocalOnly, describeRpc, x402OfferName } from './chunk-4H2QLHQI.js';
3
+ import { findX402Network, normalizeAddress, canonicalJson, X402_DEFAULT_PAYMENT_FLOW, REUSE_REJECTED_AUTHORIZATION_METADATA_KEY, SETTLE_AFTER_BACKEND_METADATA_KEY, sameAddress, LOCAL_CHAIN_ID, isTransactionReference, isEvmAddress, describeDeploymentMode } from './chunk-5R7DM5LM.js';
4
+ import { systemClock, NOOP_LOGGER, RECONCILIATION_METADATA_KEY } from './chunk-IDY2735M.js';
5
+ import { CommerceError, redactedErrorText, isCommerceError } from './chunk-SYQLJXIU.js';
6
+ import { LOCATOR_VERSION, eip3009Locator, computeReplayKey, permit2Locator, computePermit2ReplayKey, isoFromSeconds } from './chunk-663ALDZA.js';
6
7
  import { isRecord } from './chunk-3M6U7ILB.js';
7
- import { x402ExactPermit2ProxyAddress, toFacilitatorEvmSigner, PERMIT2_ADDRESS } from '@x402/evm';
8
- import { isAddress, keccak256, stringToBytes, getAddress, formatUnits, createWalletClient, http, publicActions, createPublicClient, HttpRequestError, TimeoutError, WaitForTransactionReceiptTimeoutError, BaseError, ContractFunctionRevertedError, erc20Abi } from 'viem';
8
+ import { x402ExactPermit2ProxyAddress, toFacilitatorEvmSigner, PERMIT2_ADDRESS, eip3009ABI, x402ExactPermit2ProxyABI } from '@x402/evm';
9
+ import { parseAbi, isAddress, keccak256, stringToBytes, isHash, getAddress, formatUnits, createWalletClient, http, publicActions, createPublicClient, HttpRequestError, TimeoutError, WaitForTransactionReceiptTimeoutError, BaseError, ContractFunctionRevertedError, erc20Abi, parseEventLogs, isAddressEqual, TransactionReceiptNotFoundError, decodeFunctionData } from 'viem';
9
10
  import { privateKeyToAccount } from 'viem/accounts';
10
11
  import { HTTPFacilitatorClient } from '@x402/core/http';
11
12
  import { SettleError, VerifyError } from '@x402/core/types';
@@ -54,10 +55,9 @@ function parseCanonicalAmount(amount, decimals) {
54
55
 
55
56
  // src/payments/x402/provider/fee-payer.ts
56
57
  var SUPPORTED_TTL_MS = 6e4;
57
- function createSvmFeePayerSource(ctx) {
58
+ function createSupportedSource(ctx) {
58
59
  const { clock, remoteBinding } = ctx;
59
60
  let supportedSnapshot;
60
- const feePayers = /* @__PURE__ */ new Map();
61
61
  function currentSupported() {
62
62
  const now = clock.monotonicMs();
63
63
  if (supportedSnapshot && now - supportedSnapshot.at < SUPPORTED_TTL_MS) {
@@ -72,6 +72,10 @@ function createSvmFeePayerSource(ctx) {
72
72
  });
73
73
  return response;
74
74
  }
75
+ return currentSupported;
76
+ }
77
+ function createSvmFeePayerSource(currentSupported) {
78
+ const feePayers = /* @__PURE__ */ new Map();
75
79
  async function svmFeePayer(offer) {
76
80
  let supported;
77
81
  try {
@@ -100,6 +104,43 @@ function createSvmFeePayerSource(ctx) {
100
104
  }
101
105
  return svmFeePayer;
102
106
  }
107
+ function createNearRelayerSource(currentSupported, logger) {
108
+ return async (offer) => {
109
+ let supported;
110
+ try {
111
+ supported = await currentSupported();
112
+ } catch (err) {
113
+ logger.warn(
114
+ { err: redactedErrorText(err) },
115
+ `x402 verify(): facilitator ${offer.binding.describe} did not answer /supported; the NEAR locator names no relayer`
116
+ );
117
+ return [];
118
+ }
119
+ const { signers } = supported;
120
+ return [.../* @__PURE__ */ new Set([...signers[offer.network] ?? [], ...signers["near:*"] ?? []])];
121
+ };
122
+ }
123
+
124
+ // src/payments/x402/json-rpc.ts
125
+ async function jsonRpc(rpcUrl, method, params, timeoutMs) {
126
+ const response = await fetch(rpcUrl, {
127
+ method: "POST",
128
+ headers: { "content-type": "application/json" },
129
+ body: JSON.stringify({ jsonrpc: "2.0", id: 1, method, params }),
130
+ signal: AbortSignal.timeout(timeoutMs)
131
+ });
132
+ const body = await response.json();
133
+ if (body.error !== void 0) {
134
+ throw new CommerceError(
135
+ "PAYMENT_PROVIDER_UNAVAILABLE",
136
+ `RPC ${method} failed: ${JSON.stringify(body.error)}`,
137
+ { details: { rpcError: body.error } }
138
+ );
139
+ }
140
+ return body.result;
141
+ }
142
+
143
+ // src/payments/x402/provider/health.ts
103
144
  function createHealthCheck(ctx) {
104
145
  const { offers, clock, deploymentMode, remoteBinding, svm, near } = ctx;
105
146
  async function offerHealth(offer, kinds) {
@@ -173,7 +214,7 @@ function createHealthCheck(ctx) {
173
214
  async function svmOfferHealth(offer, kinds) {
174
215
  const { profile, rpcOrigin, binding } = offer;
175
216
  const svmModule = await svm();
176
- const genesis = await jsonRpc(offer.rpcUrl, "getGenesisHash", []);
217
+ const genesis = await rpc(offer.rpcUrl, "getGenesisHash", []);
177
218
  const cluster = typeof genesis === "string" ? `solana:${genesis.slice(0, 32)}` : void 0;
178
219
  if (cluster !== offer.network) {
179
220
  return {
@@ -181,10 +222,7 @@ function createHealthCheck(ctx) {
181
222
  detail: `RPC at ${rpcOrigin} serves ${cluster ?? "an unknown cluster"}, expected ${offer.network} (${profile.displayName})`
182
223
  };
183
224
  }
184
- const mint = await jsonRpc(offer.rpcUrl, "getAccountInfo", [
185
- offer.asset,
186
- { encoding: "base64" }
187
- ]);
225
+ const mint = await rpc(offer.rpcUrl, "getAccountInfo", [offer.asset, { encoding: "base64" }]);
188
226
  const mintInfo = readMint(mint);
189
227
  if (mintInfo === void 0) {
190
228
  return {
@@ -204,7 +242,7 @@ function createHealthCheck(ctx) {
204
242
  offer.asset,
205
243
  tokenProgram
206
244
  );
207
- const account = await jsonRpc(offer.rpcUrl, "getAccountInfo", [
245
+ const account = await rpc(offer.rpcUrl, "getAccountInfo", [
208
246
  payeeAccount,
209
247
  { encoding: "base64" }
210
248
  ]);
@@ -232,7 +270,7 @@ function createHealthCheck(ctx) {
232
270
  async function nearOfferHealth(offer, kinds) {
233
271
  const { profile, rpcOrigin, binding, rpcUrl } = offer;
234
272
  await near();
235
- const status = await jsonRpc(rpcUrl, "status", []);
273
+ const status = await rpc(rpcUrl, "status", []);
236
274
  const chainId = isRecord(status) ? status["chain_id"] : void 0;
237
275
  const expected = offer.network.slice("near:".length);
238
276
  if (chainId !== expected) {
@@ -241,7 +279,7 @@ function createHealthCheck(ctx) {
241
279
  detail: `RPC at ${rpcOrigin} serves chain ${String(chainId ?? "unknown")}, expected ${expected} (${profile.displayName})`
242
280
  };
243
281
  }
244
- const token = await jsonRpc(rpcUrl, "query", {
282
+ const token = await rpc(rpcUrl, "query", {
245
283
  request_type: "view_account",
246
284
  finality: "final",
247
285
  account_id: offer.asset
@@ -359,24 +397,9 @@ function readMint(result) {
359
397
  const decimals = bytes[44];
360
398
  return bytes.length >= 82 && bytes[45] === 1 && decimals !== void 0 ? { decimals, tokenProgram: owner } : void 0;
361
399
  }
362
- async function jsonRpc(rpcUrl, method, params) {
363
- const response = await fetch(rpcUrl, {
364
- method: "POST",
365
- headers: { "content-type": "application/json" },
366
- body: JSON.stringify({ jsonrpc: "2.0", id: 1, method, params }),
367
- signal: AbortSignal.timeout(HEALTH_TIMEOUT_MS)
368
- });
369
- const body = await response.json();
370
- if (body.error !== void 0) {
371
- throw new CommerceError(
372
- "PAYMENT_PROVIDER_UNAVAILABLE",
373
- `RPC ${method} failed: ${JSON.stringify(body.error)}`
374
- );
375
- }
376
- return body.result;
377
- }
400
+ var rpc = (rpcUrl, method, params) => jsonRpc(rpcUrl, method, params, HEALTH_TIMEOUT_MS);
378
401
  async function nearView(rpcUrl, accountId, method, args) {
379
- const result = await jsonRpc(rpcUrl, "query", {
402
+ const result = await rpc(rpcUrl, "query", {
380
403
  request_type: "call_function",
381
404
  finality: "final",
382
405
  account_id: accountId,
@@ -421,7 +444,7 @@ function buildLocalChain(rpcUrl, chainId = LOCAL_CHAIN_ID) {
421
444
  function createLocalPublicClient(rpcUrl, timeoutMs, chainId) {
422
445
  return createPublicClient({
423
446
  chain: buildLocalChain(rpcUrl, chainId),
424
- transport: http(rpcUrl, { timeout: timeoutMs } )
447
+ transport: http(rpcUrl, timeoutMs !== void 0 ? { timeout: timeoutMs } : void 0)
425
448
  });
426
449
  }
427
450
  function createLocalFacilitatorClient(rpcUrl, signerPrivateKey, chainId) {
@@ -800,29 +823,6 @@ function offerCurrency(offer, quoted) {
800
823
  const canonical = offer.profile.canonicalAsset;
801
824
  return canonical !== void 0 && sameAddress(offer.profile, offer.asset, canonical.address) ? canonical.symbol : quoted;
802
825
  }
803
-
804
- // src/core/canonical-json.ts
805
- var LONE_SURROGATE = new RegExp("\\p{Cs}", "u");
806
- function canonicalJson(value) {
807
- if (typeof value === "string")
808
- return LONE_SURROGATE.test(value) ? void 0 : JSON.stringify(value);
809
- if (typeof value === "number") return Number.isFinite(value) ? JSON.stringify(value) : void 0;
810
- if (value === null || typeof value === "boolean") return JSON.stringify(value);
811
- if (Array.isArray(value)) {
812
- const items = value.map(canonicalJson);
813
- return items.includes(void 0) ? void 0 : `[${items.join(",")}]`;
814
- }
815
- if (typeof value !== "object") return void 0;
816
- const members = [];
817
- for (const key of Object.keys(value).sort()) {
818
- const member = canonicalJson(value[key]);
819
- if (member === void 0 || LONE_SURROGATE.test(key)) return void 0;
820
- members.push(`${JSON.stringify(key)}:${member}`);
821
- }
822
- return `{${members.join(",")}}`;
823
- }
824
-
825
- // src/payments/x402/provider/quote.ts
826
826
  var QUOTE_EXTENSION = "erc-8409";
827
827
  var QUOTE_REQUEST_SCHEME = "agent-commerce/request/v1";
828
828
  var QUOTE_DOMAIN = { name: "Signed Service Payment Quotes", version: "1" };
@@ -966,6 +966,553 @@ function quoteRequestHash(resourceId, input) {
966
966
  const canonical = canonicalJson({ input, resource: resourceId });
967
967
  return canonical === void 0 ? void 0 : keccak256(stringToBytes(canonical));
968
968
  }
969
+ var EVENTS = parseAbi([
970
+ "event AuthorizationUsed(address indexed authorizer, bytes32 indexed nonce)",
971
+ "event Transfer(address indexed from, address indexed to, uint256 value)"
972
+ ]);
973
+ var NONCE_BITMAP_ABI = parseAbi([
974
+ "function nonceBitmap(address owner, uint256 wordPosition) view returns (uint256)"
975
+ ]);
976
+ var CLOCK_MARGIN_SECONDS = 900n;
977
+ var LOG_CHUNK_BLOCKS = 10000n;
978
+ var MAX_WINDOW_BLOCKS = 200000n;
979
+ var UINT = /^\d{1,78}$/;
980
+ function parseEvmLocator(locator) {
981
+ const address = (key) => {
982
+ const value = locator[key];
983
+ return typeof value === "string" && isAddress(value) ? value : void 0;
984
+ };
985
+ const uint = (key) => {
986
+ const value = locator[key];
987
+ return typeof value === "string" && UINT.test(value) ? BigInt(value) : void 0;
988
+ };
989
+ const expiresAt = typeof locator["expiresAt"] === "string" ? locator["expiresAt"] : void 0;
990
+ if (locator["method"] === "eip3009") {
991
+ const [asset, from, to] = [address("asset"), address("from"), address("to")];
992
+ const [value, validAfter, validBefore] = [
993
+ uint("value"),
994
+ uint("validAfter"),
995
+ uint("validBefore")
996
+ ];
997
+ const nonce = locator["nonce"];
998
+ if (!asset || !from || !to || value === void 0 || validAfter === void 0) return void 0;
999
+ if (validBefore === void 0 || typeof nonce !== "string" || !isHash(nonce)) return void 0;
1000
+ return { method: "eip3009", asset, from, to, value, nonce, validAfter, validBefore, expiresAt };
1001
+ }
1002
+ if (locator["method"] === "permit2") {
1003
+ const [asset, owner, to, proxy] = [
1004
+ address("asset"),
1005
+ address("owner"),
1006
+ address("to"),
1007
+ address("proxy")
1008
+ ];
1009
+ const [amount, nonce, deadline, validAfter] = [
1010
+ uint("amount"),
1011
+ uint("nonce"),
1012
+ uint("deadline"),
1013
+ uint("validAfter")
1014
+ ];
1015
+ if (!asset || !owner || !to || !proxy || amount === void 0 || nonce === void 0) {
1016
+ return void 0;
1017
+ }
1018
+ if (deadline === void 0 || validAfter === void 0) return void 0;
1019
+ return {
1020
+ method: "permit2",
1021
+ asset,
1022
+ owner,
1023
+ to,
1024
+ amount,
1025
+ nonce,
1026
+ deadline,
1027
+ validAfter,
1028
+ proxy,
1029
+ expiresAt
1030
+ };
1031
+ }
1032
+ return void 0;
1033
+ }
1034
+ async function readEvmEvidence(input) {
1035
+ const { client, chainId, locator, attempt } = input;
1036
+ const reported = await client.getChainId();
1037
+ if (reported !== chainId) {
1038
+ return unknown("chain_mismatch", { chainId: reported, expectedChainId: chainId });
1039
+ }
1040
+ const finalized = await client.getBlock({ blockTag: "finalized" });
1041
+ const finalizedAt = isoFromSeconds(String(finalized.timestamp));
1042
+ const finality = {
1043
+ finalizedBlock: String(finalized.number),
1044
+ ...finalizedAt !== void 0 ? { finalizedAt } : {}
1045
+ };
1046
+ const method = locator.method === "eip3009" ? eip3009(client, locator) : permit2(client, locator);
1047
+ const settled = (hash, block) => block <= finalized.number ? {
1048
+ outcome: "settled",
1049
+ reason: "transfer_final",
1050
+ externalReference: hash,
1051
+ evidence: { transactionHash: hash, blockNumber: String(block), ...finality }
1052
+ } : unknown("not_final", { transactionHash: hash, blockNumber: String(block), ...finality });
1053
+ const reference = attempt.externalReference;
1054
+ if (reference !== void 0 && isHash(reference)) {
1055
+ const block = await method.carries(reference);
1056
+ if (block !== void 0) return settled(reference, block);
1057
+ }
1058
+ if (!await method.used(finalized.number)) {
1059
+ if (finalized.timestamp >= method.endsAt) {
1060
+ return {
1061
+ outcome: "not-settled",
1062
+ reason: "expired_unused",
1063
+ evidence: { nonceUsed: false, ...finality }
1064
+ };
1065
+ }
1066
+ if (await method.used()) return unknown("not_final", finality);
1067
+ return {
1068
+ ...unknown("not_expired", finality),
1069
+ ...locator.expiresAt !== void 0 ? { retryAfter: locator.expiresAt } : {}
1070
+ };
1071
+ }
1072
+ const createdAt = BigInt(Math.floor(Date.parse(attempt.createdAt) / 1e3));
1073
+ const fromSeconds = max(method.validAfter, createdAt - CLOCK_MARGIN_SECONDS);
1074
+ const fromBlock = await firstBlockAt(client, fromSeconds, finalized);
1075
+ const endBlock = await firstBlockAt(client, method.endsAt, finalized) - 1n;
1076
+ const toBlock = min(endBlock, fromBlock + MAX_WINDOW_BLOCKS - 1n);
1077
+ const window = { fromBlock: String(fromBlock), toBlock: String(toBlock), ...finality };
1078
+ for (const [start, end] of logRanges(fromBlock, toBlock)) {
1079
+ for (const hash of await method.candidates(start, end)) {
1080
+ const block = await method.carries(hash);
1081
+ if (block !== void 0) return settled(hash, block);
1082
+ }
1083
+ }
1084
+ if (toBlock < endBlock) {
1085
+ return unknown("search_window_too_wide", { ...window, endBlock: String(endBlock) });
1086
+ }
1087
+ return unknown("used_without_record", { nonceUsed: true, ...window });
1088
+ }
1089
+ function eip3009(client, locator) {
1090
+ const { asset, from, to, value, nonce } = locator;
1091
+ return {
1092
+ endsAt: locator.validBefore,
1093
+ validAfter: locator.validAfter,
1094
+ used: (blockNumber) => client.readContract({
1095
+ address: asset,
1096
+ abi: eip3009ABI,
1097
+ functionName: "authorizationState",
1098
+ args: [from, nonce],
1099
+ ...blockNumber !== void 0 ? { blockNumber } : {}
1100
+ }),
1101
+ async candidates(fromBlock, toBlock) {
1102
+ const logs = await client.getLogs({
1103
+ address: asset,
1104
+ event: EVENTS[0],
1105
+ args: { authorizer: from, nonce },
1106
+ fromBlock,
1107
+ toBlock
1108
+ });
1109
+ return logs.map((log) => log.transactionHash);
1110
+ },
1111
+ async carries(hash) {
1112
+ const receipt = await receiptOf(client, hash);
1113
+ if (receipt?.status !== "success") return void 0;
1114
+ const logs = parseEventLogs({ abi: EVENTS, logs: receipt.logs }).filter(
1115
+ (log) => isAddressEqual(log.address, asset)
1116
+ );
1117
+ const used = logs.some(
1118
+ (log) => log.eventName === "AuthorizationUsed" && isAddressEqual(log.args.authorizer, from) && log.args.nonce.toLowerCase() === nonce.toLowerCase()
1119
+ );
1120
+ return used && logs.some((log) => isTransfer(log, from, to, value)) ? receipt.blockNumber : void 0;
1121
+ }
1122
+ };
1123
+ }
1124
+ function permit2(client, locator) {
1125
+ const { asset, owner, to, amount, nonce, proxy } = locator;
1126
+ return {
1127
+ // Permit2 accepts a transfer while the timestamp is at most the deadline
1128
+ endsAt: locator.deadline + 1n,
1129
+ validAfter: locator.validAfter,
1130
+ async used(blockNumber) {
1131
+ const bitmap = await client.readContract({
1132
+ address: PERMIT2_ADDRESS,
1133
+ abi: NONCE_BITMAP_ABI,
1134
+ functionName: "nonceBitmap",
1135
+ args: [owner, nonce >> 8n],
1136
+ ...blockNumber !== void 0 ? { blockNumber } : {}
1137
+ });
1138
+ return (bitmap >> (nonce & 0xffn) & 1n) === 1n;
1139
+ },
1140
+ // Match the nonce in proxy calldata to distinguish transfers with the
1141
+ // same owner, recipient and amount
1142
+ async candidates(fromBlock, toBlock) {
1143
+ const logs = await client.getLogs({
1144
+ address: asset,
1145
+ event: EVENTS[1],
1146
+ args: { from: owner, to },
1147
+ fromBlock,
1148
+ toBlock
1149
+ });
1150
+ return [...new Set(logs.map((log) => log.transactionHash))];
1151
+ },
1152
+ async carries(hash) {
1153
+ const receipt = await receiptOf(client, hash);
1154
+ if (receipt?.status !== "success" || !receipt.to || !isAddressEqual(receipt.to, proxy)) {
1155
+ return void 0;
1156
+ }
1157
+ const call = proxyCall((await client.getTransaction({ hash })).input);
1158
+ const named = call !== void 0 && isAddressEqual(call.owner, owner) && call.nonce === nonce && isAddressEqual(call.asset, asset) && isAddressEqual(call.to, to);
1159
+ const transferred = parseEventLogs({ abi: EVENTS, logs: receipt.logs }).some(
1160
+ (log) => isAddressEqual(log.address, asset) && isTransfer(log, owner, to, amount)
1161
+ );
1162
+ return named && transferred ? receipt.blockNumber : void 0;
1163
+ }
1164
+ };
1165
+ }
1166
+ function proxyCall(input) {
1167
+ let call;
1168
+ try {
1169
+ call = decodeProxyInput(input);
1170
+ } catch {
1171
+ return void 0;
1172
+ }
1173
+ const parts = call.functionName === "settle" ? call.args : call.functionName === "settleWithPermit" ? [call.args[1], call.args[2], call.args[3]] : void 0;
1174
+ if (parts === void 0) return void 0;
1175
+ const [permit, owner, witness] = parts;
1176
+ return { owner, nonce: permit.nonce, asset: permit.permitted.token, to: witness.to };
1177
+ }
1178
+ var decodeProxyInput = (data) => decodeFunctionData({ abi: x402ExactPermit2ProxyABI, data });
1179
+ function isTransfer(log, from, to, value) {
1180
+ return log.eventName === "Transfer" && isAddressEqual(log.args.from, from) && isAddressEqual(log.args.to, to) && log.args.value === value;
1181
+ }
1182
+ async function receiptOf(client, hash) {
1183
+ try {
1184
+ return await client.getTransactionReceipt({ hash });
1185
+ } catch (err) {
1186
+ if (err instanceof TransactionReceiptNotFoundError) return void 0;
1187
+ throw err;
1188
+ }
1189
+ }
1190
+ function logRanges(fromBlock, toBlock) {
1191
+ const ranges = [];
1192
+ for (let start = fromBlock; start <= toBlock; start += LOG_CHUNK_BLOCKS) {
1193
+ ranges.push([start, min(start + LOG_CHUNK_BLOCKS - 1n, toBlock)]);
1194
+ }
1195
+ return ranges;
1196
+ }
1197
+ async function firstBlockAt(client, seconds, finalized) {
1198
+ if (seconds > finalized.timestamp) return finalized.number + 1n;
1199
+ const timestampOf = async (blockNumber) => (await client.getBlock({ blockNumber })).timestamp;
1200
+ let low = 0n;
1201
+ let lowTime = await timestampOf(low);
1202
+ if (lowTime >= seconds) return 0n;
1203
+ let high = finalized.number;
1204
+ let highTime = finalized.timestamp;
1205
+ for (let step = 0; high - low > 1n; step++) {
1206
+ let middle = (low + high) / 2n;
1207
+ if (step % 2 === 0 && highTime > lowTime) {
1208
+ const guess = low + (seconds - lowTime) * (high - low) / (highTime - lowTime);
1209
+ middle = min(max(guess, low + 1n), high - 1n);
1210
+ }
1211
+ const timestamp = await timestampOf(middle);
1212
+ if (timestamp >= seconds) [high, highTime] = [middle, timestamp];
1213
+ else [low, lowTime] = [middle, timestamp];
1214
+ }
1215
+ return high;
1216
+ }
1217
+ function unknown(reason, evidence) {
1218
+ return { outcome: "unknown", reason, ...evidence !== void 0 ? { evidence } : {} };
1219
+ }
1220
+ var max = (a, b) => a > b ? a : b;
1221
+ var min = (a, b) => a < b ? a : b;
1222
+
1223
+ // src/payments/x402/reconcile/near.ts
1224
+ var UINT2 = /^\d{1,20}$/;
1225
+ var TX_HASH = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
1226
+ function parseNearLocator(locator) {
1227
+ const text = (key) => {
1228
+ const value = locator[key];
1229
+ return typeof value === "string" && value !== "" ? value : void 0;
1230
+ };
1231
+ const uint = (key) => {
1232
+ const value = text(key);
1233
+ return value !== void 0 && UINT2.test(value) ? value : void 0;
1234
+ };
1235
+ const [senderId, publicKey, asset, receiver] = [
1236
+ text("senderId"),
1237
+ text("publicKey"),
1238
+ text("asset"),
1239
+ text("receiver")
1240
+ ];
1241
+ const [nonce, maxBlockHeight, amount] = [uint("nonce"), uint("maxBlockHeight"), uint("amount")];
1242
+ const relayers = locator["relayers"] ?? [];
1243
+ if (!senderId || !publicKey || !asset || !receiver || !nonce || !maxBlockHeight || !amount) {
1244
+ return void 0;
1245
+ }
1246
+ if (!Array.isArray(relayers) || !relayers.every((id) => typeof id === "string")) {
1247
+ return void 0;
1248
+ }
1249
+ return {
1250
+ senderId,
1251
+ publicKey,
1252
+ nonce: BigInt(nonce),
1253
+ maxBlockHeight: BigInt(maxBlockHeight),
1254
+ asset,
1255
+ receiver,
1256
+ amount,
1257
+ relayers
1258
+ };
1259
+ }
1260
+ async function readNearEvidence(input) {
1261
+ const { rpc: rpc2, network, locator, attempt } = input;
1262
+ const status = await rpc2("status", []);
1263
+ const chainId = isRecord(status) ? status["chain_id"] : void 0;
1264
+ const expected = network.slice("near:".length);
1265
+ if (chainId !== expected) {
1266
+ return unknown("chain_mismatch", { chainId, expectedChainId: expected });
1267
+ }
1268
+ const reference = attempt.externalReference;
1269
+ if (reference !== void 0 && TX_HASH.test(reference)) {
1270
+ for (const relayer of locator.relayers) {
1271
+ const outcome = await txStatus(rpc2, reference, relayer);
1272
+ if (outcome === void 0) continue;
1273
+ if (outcome.final_execution_status !== "FINAL") {
1274
+ return unknown("not_final", { transactionHash: reference });
1275
+ }
1276
+ if (carries(outcome, locator)) {
1277
+ return {
1278
+ outcome: "settled",
1279
+ reason: "transfer_final",
1280
+ externalReference: reference,
1281
+ evidence: { transactionHash: reference, relayer }
1282
+ };
1283
+ }
1284
+ break;
1285
+ }
1286
+ }
1287
+ const block = await rpc2("block", { finality: "final" });
1288
+ const height = block.header?.height;
1289
+ if (typeof height !== "number" || !Number.isSafeInteger(height)) {
1290
+ throw new CommerceError("PAYMENT_PROVIDER_UNAVAILABLE", "block returned no height");
1291
+ }
1292
+ const finality = { finalBlock: String(height) };
1293
+ let key;
1294
+ try {
1295
+ key = await rpc2("query", {
1296
+ request_type: "view_access_key",
1297
+ block_id: height,
1298
+ account_id: locator.senderId,
1299
+ public_key: locator.publicKey
1300
+ });
1301
+ } catch (err) {
1302
+ if (rpcErrorName(err) === "UNKNOWN_ACCESS_KEY") return unknown("access_key_missing", finality);
1303
+ throw err;
1304
+ }
1305
+ if (typeof key.error === "string") return unknown("access_key_missing", finality);
1306
+ if (typeof key.nonce !== "number" || !Number.isSafeInteger(key.nonce)) {
1307
+ throw new CommerceError("PAYMENT_PROVIDER_UNAVAILABLE", "view_access_key returned no nonce");
1308
+ }
1309
+ const evidence = { keyNonce: String(key.nonce), ...finality };
1310
+ if (BigInt(key.nonce) >= locator.nonce) return unknown("used_without_record", evidence);
1311
+ if (BigInt(height) > locator.maxBlockHeight) {
1312
+ return { outcome: "not-settled", reason: "expired_unused", evidence };
1313
+ }
1314
+ return unknown("not_expired", { maxBlockHeight: String(locator.maxBlockHeight), ...evidence });
1315
+ }
1316
+ async function txStatus(rpc2, hash, sender) {
1317
+ try {
1318
+ return await rpc2("EXPERIMENTAL_tx_status", {
1319
+ tx_hash: hash,
1320
+ sender_account_id: sender,
1321
+ wait_until: "NONE"
1322
+ });
1323
+ } catch (err) {
1324
+ if (rpcErrorName(err) === "UNKNOWN_TRANSACTION") return void 0;
1325
+ throw err;
1326
+ }
1327
+ }
1328
+ function carries(outcome, locator) {
1329
+ const delegated = (outcome.transaction?.actions ?? []).some((action) => {
1330
+ const delegate = action.Delegate?.delegate_action;
1331
+ return delegate?.sender_id === locator.senderId && delegate.public_key === locator.publicKey && String(delegate.nonce) === String(locator.nonce);
1332
+ });
1333
+ const succeeded = new Set(
1334
+ (outcome.receipts_outcome ?? []).filter((entry) => isRecord(entry.outcome?.status) && "SuccessValue" in entry.outcome.status).map((entry) => entry.id)
1335
+ );
1336
+ const transferred = (outcome.receipts ?? []).some(
1337
+ (receipt) => receipt.receiver_id === locator.asset && receipt.predecessor_id === locator.senderId && succeeded.has(receipt.receipt_id) && (receipt.receipt?.Action?.actions ?? []).some((action) => {
1338
+ const call = action.FunctionCall;
1339
+ if (call?.method_name !== "ft_transfer" || typeof call.args !== "string") return false;
1340
+ const args = parseArgs(call.args);
1341
+ return args?.["receiver_id"] === locator.receiver && args["amount"] === locator.amount;
1342
+ })
1343
+ );
1344
+ return delegated && transferred;
1345
+ }
1346
+ function parseArgs(base64) {
1347
+ try {
1348
+ const args = JSON.parse(Buffer.from(base64, "base64").toString("utf8"));
1349
+ return isRecord(args) ? args : void 0;
1350
+ } catch {
1351
+ return void 0;
1352
+ }
1353
+ }
1354
+ function rpcErrorName(err) {
1355
+ const rpcError = isCommerceError(err) ? err.details?.["rpcError"] : void 0;
1356
+ return isRecord(rpcError) && isRecord(rpcError["cause"]) ? rpcError["cause"]["name"] : void 0;
1357
+ }
1358
+
1359
+ // src/payments/x402/reconcile/svm.ts
1360
+ var CLOCK_MARGIN_SECONDS2 = 900;
1361
+ var HISTORY_PAGE = 1e3;
1362
+ var MAX_HISTORY_PAGES = 5;
1363
+ var BASE58 = /^[1-9A-HJ-NP-Za-km-z]+$/;
1364
+ var MESSAGE_HASH = /^[A-Za-z0-9+/]{43}=$/;
1365
+ function parseSvmLocator(locator) {
1366
+ const { messageHash, recentBlockhash, payer } = locator;
1367
+ if (typeof messageHash !== "string" || !MESSAGE_HASH.test(messageHash)) return void 0;
1368
+ if (!isBase58(recentBlockhash, 32, 44)) return void 0;
1369
+ if (payer !== void 0 && !isBase58(payer, 32, 44)) return void 0;
1370
+ return { messageHash, recentBlockhash, payer };
1371
+ }
1372
+ async function readSvmEvidence(input) {
1373
+ const { rpc: rpc2, network, locator, attempt, messageHashOf } = input;
1374
+ const genesis = await rpc2("getGenesisHash", []);
1375
+ const served = `solana:${String(genesis).slice(0, 32)}`;
1376
+ if (served !== network) {
1377
+ return unknown("chain_mismatch", { network: served, expectedNetwork: network });
1378
+ }
1379
+ const carries2 = async (id) => {
1380
+ const landed = await rpc2("getTransaction", [
1381
+ id,
1382
+ { encoding: "base64", commitment: "finalized", maxSupportedTransactionVersion: 0 }
1383
+ ]);
1384
+ if (landed?.meta?.err !== null || typeof landed.slot !== "number") return void 0;
1385
+ const [wire] = Array.isArray(landed.transaction) ? landed.transaction : [];
1386
+ return typeof wire === "string" && messageHashOf(wire) === locator.messageHash ? landed.slot : void 0;
1387
+ };
1388
+ const settled = (id, slot) => ({
1389
+ outcome: "settled",
1390
+ reason: "transfer_final",
1391
+ externalReference: id,
1392
+ evidence: { transactionId: id, slot: String(slot) }
1393
+ });
1394
+ const reference = attempt.externalReference;
1395
+ if (reference !== void 0 && isBase58(reference, 64, 88)) {
1396
+ const slot = await carries2(reference);
1397
+ if (slot !== void 0) return settled(reference, slot);
1398
+ }
1399
+ if (locator.payer !== void 0) {
1400
+ const createdAt = Math.floor(Date.parse(attempt.createdAt) / 1e3);
1401
+ const from = createdAt - CLOCK_MARGIN_SECONDS2;
1402
+ const to = createdAt + CLOCK_MARGIN_SECONDS2;
1403
+ let before;
1404
+ search: for (let page = 0; ; page += 1) {
1405
+ if (page === MAX_HISTORY_PAGES) return unknown("history_too_long", { payer: locator.payer });
1406
+ const entries = await rpc2("getSignaturesForAddress", [
1407
+ locator.payer,
1408
+ {
1409
+ commitment: "finalized",
1410
+ limit: HISTORY_PAGE,
1411
+ ...before !== void 0 ? { before } : {}
1412
+ }
1413
+ ]);
1414
+ if (!Array.isArray(entries)) {
1415
+ throw new CommerceError(
1416
+ "PAYMENT_PROVIDER_UNAVAILABLE",
1417
+ "getSignaturesForAddress returned no list"
1418
+ );
1419
+ }
1420
+ for (const entry of entries) {
1421
+ if (typeof entry.signature !== "string") continue;
1422
+ before = entry.signature;
1423
+ const time = typeof entry.blockTime === "number" ? entry.blockTime : void 0;
1424
+ if (time !== void 0 && time < from) break search;
1425
+ if (entry.err !== null || time !== void 0 && time > to) continue;
1426
+ const slot = await carries2(entry.signature);
1427
+ if (slot !== void 0) return settled(entry.signature, slot);
1428
+ }
1429
+ if (entries.length < HISTORY_PAGE) break;
1430
+ }
1431
+ }
1432
+ const validity = await rpc2("isBlockhashValid", [
1433
+ locator.recentBlockhash,
1434
+ { commitment: "confirmed" }
1435
+ ]);
1436
+ const valid = isRecord(validity) ? validity["value"] : void 0;
1437
+ if (typeof valid !== "boolean") {
1438
+ throw new CommerceError("PAYMENT_PROVIDER_UNAVAILABLE", "isBlockhashValid returned no value");
1439
+ }
1440
+ return unknown(valid ? "not_expired" : "blockhash_expired", {
1441
+ payerSearched: locator.payer !== void 0
1442
+ });
1443
+ }
1444
+ function isBase58(value, minLength, maxLength) {
1445
+ return typeof value === "string" && value.length >= minLength && value.length <= maxLength && BASE58.test(value);
1446
+ }
1447
+
1448
+ // src/payments/x402/provider/reconcile.ts
1449
+ var RECONCILE_TIMEOUT_MS = 3e4;
1450
+ function createReconcile(ctx) {
1451
+ const clients = /* @__PURE__ */ new Map();
1452
+ const evmClient = (offer) => {
1453
+ let client = clients.get(offer);
1454
+ if (client === void 0) {
1455
+ client = createLocalPublicClient(offer.rpcUrl, RECONCILE_TIMEOUT_MS, offer.profile.chainId);
1456
+ clients.set(offer, client);
1457
+ }
1458
+ return client;
1459
+ };
1460
+ const rpc2 = (offer) => (method, params) => jsonRpc(offer.rpcUrl, method, params, RECONCILE_TIMEOUT_MS);
1461
+ const read = async (offer, evidence) => {
1462
+ try {
1463
+ return await evidence();
1464
+ } catch (err) {
1465
+ return unknown("rpc_error", { rpc: offer.rpcOrigin, error: redactedErrorText(err) });
1466
+ }
1467
+ };
1468
+ return async ({ attempt, locator }) => {
1469
+ if (locator === void 0) return unknown("no_locator");
1470
+ if (locator["v"] !== LOCATOR_VERSION) return unknown("unsupported_locator_version");
1471
+ const network = locator["network"];
1472
+ if (typeof network !== "string") return unknown("unsupported_family");
1473
+ const offerFor = (family) => ctx.offers.find(
1474
+ (candidate) => candidate.family === family && candidate.network === network
1475
+ );
1476
+ const notConfigured = unknown("network_not_configured", { network });
1477
+ if (network.startsWith("eip155:")) {
1478
+ const parsed = parseEvmLocator(locator);
1479
+ if (parsed === void 0) return unknown("invalid_locator");
1480
+ const offer = offerFor("evm");
1481
+ if (offer === void 0) return notConfigured;
1482
+ return read(
1483
+ offer,
1484
+ () => readEvmEvidence({
1485
+ client: evmClient(offer),
1486
+ chainId: offer.profile.chainId,
1487
+ locator: parsed,
1488
+ attempt
1489
+ })
1490
+ );
1491
+ }
1492
+ if (network.startsWith("solana:")) {
1493
+ const parsed = parseSvmLocator(locator);
1494
+ if (parsed === void 0) return unknown("invalid_locator");
1495
+ const offer = offerFor("svm");
1496
+ if (offer === void 0) return notConfigured;
1497
+ const { messageHashOf } = await ctx.svm();
1498
+ return read(
1499
+ offer,
1500
+ () => readSvmEvidence({ rpc: rpc2(offer), network, locator: parsed, attempt, messageHashOf })
1501
+ );
1502
+ }
1503
+ if (network.startsWith("near:")) {
1504
+ const parsed = parseNearLocator(locator);
1505
+ if (parsed === void 0) return unknown("invalid_locator");
1506
+ const offer = offerFor("near");
1507
+ if (offer === void 0) return notConfigured;
1508
+ return read(
1509
+ offer,
1510
+ () => readNearEvidence({ rpc: rpc2(offer), network, locator: parsed, attempt })
1511
+ );
1512
+ }
1513
+ return unknown("unsupported_family");
1514
+ };
1515
+ }
969
1516
  function decodePaymentSubmission(payloadBase64) {
970
1517
  const json = decodeJson(payloadBase64);
971
1518
  if (json === void 0) return void 0;
@@ -1140,12 +1687,13 @@ function readTransfer(payload, offer) {
1140
1687
  from: getAddress(from2),
1141
1688
  nonce: nonce2
1142
1689
  }),
1690
+ locator: eip3009Locator(offer.network, offer.asset, authorization),
1143
1691
  recipientMismatch: "invalid_exact_evm_payload_recipient_mismatch",
1144
1692
  amountMismatch: "invalid_exact_evm_payload_authorization_value_mismatch"
1145
1693
  };
1146
1694
  }
1147
1695
  if (!isExactPermit2Payload(payload)) return "unsupported_scheme";
1148
- const { from, spender, permitted, witness, nonce } = payload.payload.permit2Authorization;
1696
+ const { from, spender, permitted, witness, nonce, deadline } = payload.payload.permit2Authorization;
1149
1697
  if (getAddress(spender) !== getAddress(x402ExactPermit2ProxyAddress)) {
1150
1698
  return "invalid_permit2_spender";
1151
1699
  }
@@ -1155,6 +1703,16 @@ function readTransfer(payload, offer) {
1155
1703
  to: getAddress(witness.to),
1156
1704
  value: permitted.amount,
1157
1705
  replayKey: computePermit2ReplayKey({ chainId, owner: getAddress(from), nonce }),
1706
+ locator: permit2Locator(offer.network, {
1707
+ asset: permitted.token,
1708
+ owner: from,
1709
+ to: witness.to,
1710
+ amount: permitted.amount,
1711
+ nonce,
1712
+ deadline,
1713
+ validAfter: witness.validAfter,
1714
+ proxy: spender
1715
+ }),
1158
1716
  recipientMismatch: "invalid_permit2_recipient_mismatch",
1159
1717
  amountMismatch: "permit2_amount_mismatch"
1160
1718
  };
@@ -1329,7 +1887,8 @@ function createSettle(ctx) {
1329
1887
  }
1330
1888
  return settle;
1331
1889
  }
1332
- function createVerify(ctx) {
1890
+ var RELAYER_GRACE_MS = 1e3;
1891
+ function createVerify(ctx, nearRelayers) {
1333
1892
  const { offersFor, clock, logger, svm, near } = ctx;
1334
1893
  async function verify(context) {
1335
1894
  const { requirement, submission } = context;
@@ -1372,11 +1931,13 @@ function createVerify(ctx) {
1372
1931
  }
1373
1932
  let transfer;
1374
1933
  let replayKey;
1934
+ let locator;
1375
1935
  let derivedPayer;
1376
1936
  if (offer.family === "svm") {
1377
- const identity = (await svm()).svmReplayKey(payload.payload, offer.network);
1378
- if (typeof identity === "string") return rejected(identity);
1379
- replayKey = identity.replayKey;
1937
+ const inspected = (await svm()).inspectSvmPayload(payload.payload, offer.network);
1938
+ if (typeof inspected === "string") return rejected(inspected);
1939
+ replayKey = inspected.replayKey;
1940
+ locator = inspected.locator;
1380
1941
  } else if (offer.family === "near") {
1381
1942
  const inspected = (await near()).inspectNearPayload(payload.payload, {
1382
1943
  network: offer.network,
@@ -1386,12 +1947,14 @@ function createVerify(ctx) {
1386
1947
  });
1387
1948
  if (typeof inspected === "string") return rejected(inspected);
1388
1949
  replayKey = inspected.replayKey;
1950
+ locator = inspected.locator;
1389
1951
  derivedPayer = inspected.payer;
1390
1952
  } else {
1391
1953
  const read = readTransfer(payload, offer);
1392
1954
  if (typeof read === "string") return rejected(read);
1393
1955
  transfer = read;
1394
1956
  replayKey = read.replayKey;
1957
+ locator = read.locator;
1395
1958
  derivedPayer = read.from;
1396
1959
  }
1397
1960
  if (payload.accepted.network !== offer.network) {
@@ -1421,6 +1984,7 @@ function createVerify(ctx) {
1421
1984
  return rejected(transfer.amountMismatch);
1422
1985
  }
1423
1986
  }
1987
+ const relayers = offer.family === "near" ? nearRelayers(offer) : void 0;
1424
1988
  const scope = offer.binding.open();
1425
1989
  let sdkResult;
1426
1990
  try {
@@ -1457,6 +2021,9 @@ function createVerify(ctx) {
1457
2021
  return rejected(sanitizeReason(sdkResult.invalidReason, "invalid_payment"));
1458
2022
  }
1459
2023
  const payer = derivedPayer ?? (sdkResult.payer !== void 0 && normalizeAddress(offer.profile, sdkResult.payer) ? sdkResult.payer : void 0);
2024
+ if (offer.family === "svm" && payer !== void 0) locator = { ...locator, payer };
2025
+ const relayerIds = relayers !== void 0 ? await withinGrace(relayers) : [];
2026
+ if (relayerIds.length > 0) locator = { ...locator, relayers: relayerIds };
1460
2027
  return {
1461
2028
  status: "verified",
1462
2029
  provider: "x402",
@@ -1466,10 +2033,26 @@ function createVerify(ctx) {
1466
2033
  currency: offerCurrency(offer, requirement.currency),
1467
2034
  network: payload.accepted.network,
1468
2035
  asset: offer.family === "evm" ? getAddress(requirements.asset) : offer.asset,
1469
- replayKey
2036
+ replayKey,
2037
+ metadata: { [RECONCILIATION_METADATA_KEY]: locator }
1470
2038
  };
1471
2039
  }
1472
2040
  return verify;
2041
+ async function withinGrace(relayers) {
2042
+ let timer;
2043
+ const late = new Promise((resolve) => {
2044
+ timer = setTimeout(() => resolve(void 0), RELAYER_GRACE_MS);
2045
+ timer.unref();
2046
+ });
2047
+ const ids = await Promise.race([relayers, late]).finally(() => clearTimeout(timer));
2048
+ if (ids === void 0) {
2049
+ logger.warn(
2050
+ { graceMs: RELAYER_GRACE_MS },
2051
+ "x402 verify(): /supported is slow; the NEAR locator names no relayer"
2052
+ );
2053
+ }
2054
+ return ids ?? [];
2055
+ }
1473
2056
  }
1474
2057
 
1475
2058
  // src/payments/x402/provider/index.ts
@@ -1538,8 +2121,8 @@ function createX402PaymentProvider(options) {
1538
2121
  "auth-capture scheme"
1539
2122
  ]
1540
2123
  };
1541
- const svmModule = hasSvm ? loadOptionalModule(() => import('./svm-3MMYFPC7.js'), "Solana offers need @x402/svm and @solana/kit") : void 0;
1542
- const nearModule = hasNear ? loadOptionalModule(() => import('./near-5AY3HWYF.js'), "NEAR offers need @x402/near") : void 0;
2124
+ const svmModule = hasSvm ? loadOptionalModule(() => import('./svm-KDSPDFJG.js'), "Solana offers need @x402/svm and @solana/kit") : void 0;
2125
+ const nearModule = hasNear ? loadOptionalModule(() => import('./near-U6365VFX.js'), "NEAR offers need @x402/near") : void 0;
1543
2126
  const svm = async () => {
1544
2127
  if (!svmModule)
1545
2128
  throw new CommerceError("INTERNAL_ERROR", "x402 provider: no Solana offer is configured");
@@ -1564,11 +2147,12 @@ function createX402PaymentProvider(options) {
1564
2147
  svm,
1565
2148
  near
1566
2149
  };
2150
+ const supported = createSupportedSource(ctx);
1567
2151
  const { createRequirement, selectRequirement } = createRequirementBuilders(
1568
2152
  ctx,
1569
- createSvmFeePayerSource(ctx)
2153
+ createSvmFeePayerSource(supported)
1570
2154
  );
1571
- const verify = createVerify(ctx);
2155
+ const verify = createVerify(ctx, createNearRelayerSource(supported, logger));
1572
2156
  const settle = createSettle(ctx);
1573
2157
  const health = createHealthCheck(ctx);
1574
2158
  return {
@@ -1579,6 +2163,7 @@ function createX402PaymentProvider(options) {
1579
2163
  ...severalOffers ? { selectRequirement } : {},
1580
2164
  verify,
1581
2165
  settle,
2166
+ reconcile: createReconcile(ctx),
1582
2167
  health,
1583
2168
  ...quotes ? {
1584
2169
  quote: {
@@ -1601,5 +2186,5 @@ function loadOptionalModule(load, missing) {
1601
2186
  }
1602
2187
 
1603
2188
  export { DEFAULT_IDS, chainIdFromCaip2, createX402PaymentProvider, parseCanonicalAmount };
1604
- //# sourceMappingURL=chunk-AZDWFVDW.js.map
1605
- //# sourceMappingURL=chunk-AZDWFVDW.js.map
2189
+ //# sourceMappingURL=chunk-QA2OPHBF.js.map
2190
+ //# sourceMappingURL=chunk-QA2OPHBF.js.map