@piprail/sdk 2.13.0 → 2.14.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 (30) hide show
  1. package/CHANGELOG.md +96 -0
  2. package/dist/{algorand-AA3WXKW4.js → algorand-6J3IABVF.js} +12 -11
  3. package/dist/{algorand-FCEECDG6.cjs → algorand-QU6G2DQZ.cjs} +43 -42
  4. package/dist/{aptos-LY67Q6QF.js → aptos-DHOMTBLZ.js} +11 -10
  5. package/dist/{aptos-GHJPO6JJ.cjs → aptos-LFTQGBBK.cjs} +41 -40
  6. package/dist/{chunk-MWBT7MCE.cjs → chunk-GYM46G5L.cjs} +22 -4
  7. package/dist/{chunk-SC2ZYDHD.js → chunk-PAMKCWVW.js} +22 -4
  8. package/dist/index.cjs +505 -234
  9. package/dist/index.d.cts +281 -12
  10. package/dist/index.d.ts +281 -12
  11. package/dist/index.js +302 -31
  12. package/dist/{ledger-mF_SoiDB.d.ts → ledger-uFtXlIHY.d.cts} +31 -1
  13. package/dist/{ledger-mF_SoiDB.d.cts → ledger-uFtXlIHY.d.ts} +31 -1
  14. package/dist/{near-FZBUICCS.js → near-5PXTVQ47.js} +14 -5
  15. package/dist/{near-6KAQVVG2.cjs → near-YNNK7RW7.cjs} +39 -30
  16. package/dist/node.d.cts +2 -2
  17. package/dist/node.d.ts +2 -2
  18. package/dist/{solana-ELUWO6N5.js → solana-HITVI3HF.js} +22 -7
  19. package/dist/{solana-MYF4HBO4.cjs → solana-N3UCNCYE.cjs} +54 -39
  20. package/dist/{stellar-ASP2THL2.js → stellar-2QT6YYKN.js} +4 -4
  21. package/dist/{stellar-CRWBSX4E.cjs → stellar-Y3SQN7S5.cjs} +23 -23
  22. package/dist/{sui-Y4RLKKE2.cjs → sui-4AL4E6XU.cjs} +35 -27
  23. package/dist/{sui-FZIKZNVI.js → sui-FV5L6WF5.js} +20 -12
  24. package/dist/{ton-7GKCTC5H.js → ton-5FWDQ4QR.js} +18 -7
  25. package/dist/{ton-AOR3EURW.cjs → ton-5HDVOTMR.cjs} +33 -22
  26. package/dist/{tron-BMCWN5SS.js → tron-AZDY7BMQ.js} +10 -10
  27. package/dist/{tron-OMXB6EW2.cjs → tron-TX2B4N2A.cjs} +39 -39
  28. package/dist/{xrpl-Y6SQNYLC.cjs → xrpl-5TYDLQFS.cjs} +31 -31
  29. package/dist/{xrpl-DD7TJL5L.js → xrpl-UJL5J7CY.js} +13 -13
  30. package/package.json +1 -1
@@ -210,6 +210,13 @@ interface X402PaymentSignature {
210
210
  nonce: string;
211
211
  txHash: string;
212
212
  };
213
+ /**
214
+ * Optional v2 extensions the client attaches to its payload — e.g. the
215
+ * `payment-identifier` idempotency id at `extensions['payment-identifier'].info.id`
216
+ * (read by the gate via {@link readPaymentIdentifier}). A standard reader ignores it,
217
+ * and omitting it keeps the payload byte-identical.
218
+ */
219
+ extensions?: Record<string, unknown>;
213
220
  }
214
221
  /**
215
222
  * The EIP-3009 authorization a payer signs for a standard `exact` rail. All
@@ -590,6 +597,29 @@ declare function buildReceiptExtension(bundle: {
590
597
  decimals?: number;
591
598
  attestation?: SignedReceipt;
592
599
  }): Record<string, unknown>;
600
+ /** The x402 extension key for the optional idempotency identifier (the official
601
+ * `payment-identifier` extension). A client MAY attach a stable `id` so the server dedupes
602
+ * retries and rejects a reused id bound to a DIFFERENT payment. */
603
+ declare const EXT_PAYMENT_IDENTIFIER = "payment-identifier";
604
+ /**
605
+ * Advertise the `payment-identifier` extension on a 402 challenge — PURE JSON, viem-free. The
606
+ * v2 `{ info, schema }` shape: `info.required:false` (PipRail never MANDATES an id) plus a
607
+ * JSON-Schema bound of {@link PAYMENT_ID_MIN}–{@link PAYMENT_ID_MAX} chars. A client reads this
608
+ * from the challenge and MAY echo an `id` back on its payload; the gate dedupes it on its
609
+ * existing used-proof set. The gate merges this into the challenge `extensions` (a sibling key,
610
+ * never inside `extensions.piprail`).
611
+ */
612
+ declare function buildPaymentIdentifierAdvertisement(): Record<string, unknown>;
613
+ /**
614
+ * Read + validate an inbound `payment-identifier` id from a decoded payment-payload object
615
+ * (`payload.extensions['payment-identifier'].info.id`). PURE, NEVER throws. Returns:
616
+ * - the `id` string when present + valid (16–128 chars, `[A-Za-z0-9_-]`),
617
+ * - `null` when ABSENT (the id is OPTIONAL — the gate proceeds exactly as without the feature),
618
+ * - `{ invalid }` when PRESENT but malformed (the gate re-challenges so the buyer can fix it).
619
+ */
620
+ declare function readPaymentIdentifier(payload: unknown): string | null | {
621
+ invalid: string;
622
+ };
593
623
  declare function buildSignatureHeader(signature: X402PaymentSignature): string;
594
624
  /**
595
625
  * Build the v2 PAYMENT-SIGNATURE header value for a standard x402 `exact` payment:
@@ -928,4 +958,4 @@ declare class SpendLedger {
928
958
  summary(): SpendSummary;
929
959
  }
930
960
 
931
- export { parseSignatureObject as $, type AddressId as A, type X402PaymentSignature as B, type Caip2 as C, type X402Receipt as D, EXT_OFFER_RECEIPT as E, type X402ResourceObject as F, type X402UptoAcceptEntry as G, HEADER_REQUIRED as H, buildChallengeHeader as I, buildExactSignatureHeader as J, buildReceiptExtension as K, buildReceiptHeader as L, buildSignatureHeader as M, buildUptoSignatureHeader as N, decodeBase64Json as O, type PaidReceipt as P, memorySpendStore as Q, parseChallenge as R, type SettleOutcome as S, parseExactObject as T, parseExactPaymentHeader as U, type VerifyErrorCode as V, parseReceipt as W, type X402AcceptEntry as X, parseReceiptExtension as Y, parseSettleResponse as Z, parseSignatureHeader as _, type AssetId as a, parseUptoObject as a0, parseUptoPaymentHeader as a1, pickAccept as a2, type ExactAuthorizationWire as b, type ExactPaymentPayload as c, type ExactPaymentPayloadAny as d, HEADER_RESPONSE as e, HEADER_RESPONSE_V1 as f, HEADER_SIGNATURE as g, HEADER_SIGNATURE_V1 as h, type ParsedExactPayment as i, type ParsedUptoPayment as j, type Permit2Authorization as k, type Permit2PaymentPayload as l, type Permit2UptoAuthorization as m, type Permit2UptoPaymentPayload as n, type PipRailReceipt as o, type SignedReceipt as p, type SpendAssetTotal as q, type SpendDenomTotal as r, SpendLedger as s, type SpendRecord as t, type SpendStore as u, type SpendSummary as v, type VerifyResult as w, type X402AnyAccept as x, type X402Challenge as y, type X402ExactAcceptEntry as z };
961
+ export { parseSettleResponse as $, type AddressId as A, type X402ExactAcceptEntry as B, type Caip2 as C, type X402PaymentSignature as D, EXT_OFFER_RECEIPT as E, type X402Receipt as F, type X402ResourceObject as G, HEADER_REQUIRED as H, type X402UptoAcceptEntry as I, buildChallengeHeader as J, buildExactSignatureHeader as K, buildPaymentIdentifierAdvertisement as L, buildReceiptExtension as M, buildReceiptHeader as N, buildSignatureHeader as O, type PaidReceipt as P, buildUptoSignatureHeader as Q, decodeBase64Json as R, type SettleOutcome as S, memorySpendStore as T, parseChallenge as U, type VerifyErrorCode as V, parseExactObject as W, type X402AcceptEntry as X, parseExactPaymentHeader as Y, parseReceipt as Z, parseReceiptExtension as _, type AssetId as a, parseSignatureHeader as a0, parseSignatureObject as a1, parseUptoObject as a2, parseUptoPaymentHeader as a3, pickAccept as a4, readPaymentIdentifier as a5, EXT_PAYMENT_IDENTIFIER as b, type ExactAuthorizationWire as c, type ExactPaymentPayload as d, type ExactPaymentPayloadAny as e, HEADER_RESPONSE as f, HEADER_RESPONSE_V1 as g, HEADER_SIGNATURE as h, HEADER_SIGNATURE_V1 as i, type ParsedExactPayment as j, type ParsedUptoPayment as k, type Permit2Authorization as l, type Permit2PaymentPayload as m, type Permit2UptoAuthorization as n, type Permit2UptoPaymentPayload as o, type PipRailReceipt as p, type SignedReceipt as q, type SpendAssetTotal as r, type SpendDenomTotal as s, SpendLedger as t, type SpendRecord as u, type SpendStore as v, type SpendSummary as w, type VerifyResult as x, type X402AnyAccept as y, type X402Challenge as z };
@@ -210,6 +210,13 @@ interface X402PaymentSignature {
210
210
  nonce: string;
211
211
  txHash: string;
212
212
  };
213
+ /**
214
+ * Optional v2 extensions the client attaches to its payload — e.g. the
215
+ * `payment-identifier` idempotency id at `extensions['payment-identifier'].info.id`
216
+ * (read by the gate via {@link readPaymentIdentifier}). A standard reader ignores it,
217
+ * and omitting it keeps the payload byte-identical.
218
+ */
219
+ extensions?: Record<string, unknown>;
213
220
  }
214
221
  /**
215
222
  * The EIP-3009 authorization a payer signs for a standard `exact` rail. All
@@ -590,6 +597,29 @@ declare function buildReceiptExtension(bundle: {
590
597
  decimals?: number;
591
598
  attestation?: SignedReceipt;
592
599
  }): Record<string, unknown>;
600
+ /** The x402 extension key for the optional idempotency identifier (the official
601
+ * `payment-identifier` extension). A client MAY attach a stable `id` so the server dedupes
602
+ * retries and rejects a reused id bound to a DIFFERENT payment. */
603
+ declare const EXT_PAYMENT_IDENTIFIER = "payment-identifier";
604
+ /**
605
+ * Advertise the `payment-identifier` extension on a 402 challenge — PURE JSON, viem-free. The
606
+ * v2 `{ info, schema }` shape: `info.required:false` (PipRail never MANDATES an id) plus a
607
+ * JSON-Schema bound of {@link PAYMENT_ID_MIN}–{@link PAYMENT_ID_MAX} chars. A client reads this
608
+ * from the challenge and MAY echo an `id` back on its payload; the gate dedupes it on its
609
+ * existing used-proof set. The gate merges this into the challenge `extensions` (a sibling key,
610
+ * never inside `extensions.piprail`).
611
+ */
612
+ declare function buildPaymentIdentifierAdvertisement(): Record<string, unknown>;
613
+ /**
614
+ * Read + validate an inbound `payment-identifier` id from a decoded payment-payload object
615
+ * (`payload.extensions['payment-identifier'].info.id`). PURE, NEVER throws. Returns:
616
+ * - the `id` string when present + valid (16–128 chars, `[A-Za-z0-9_-]`),
617
+ * - `null` when ABSENT (the id is OPTIONAL — the gate proceeds exactly as without the feature),
618
+ * - `{ invalid }` when PRESENT but malformed (the gate re-challenges so the buyer can fix it).
619
+ */
620
+ declare function readPaymentIdentifier(payload: unknown): string | null | {
621
+ invalid: string;
622
+ };
593
623
  declare function buildSignatureHeader(signature: X402PaymentSignature): string;
594
624
  /**
595
625
  * Build the v2 PAYMENT-SIGNATURE header value for a standard x402 `exact` payment:
@@ -928,4 +958,4 @@ declare class SpendLedger {
928
958
  summary(): SpendSummary;
929
959
  }
930
960
 
931
- export { parseSignatureObject as $, type AddressId as A, type X402PaymentSignature as B, type Caip2 as C, type X402Receipt as D, EXT_OFFER_RECEIPT as E, type X402ResourceObject as F, type X402UptoAcceptEntry as G, HEADER_REQUIRED as H, buildChallengeHeader as I, buildExactSignatureHeader as J, buildReceiptExtension as K, buildReceiptHeader as L, buildSignatureHeader as M, buildUptoSignatureHeader as N, decodeBase64Json as O, type PaidReceipt as P, memorySpendStore as Q, parseChallenge as R, type SettleOutcome as S, parseExactObject as T, parseExactPaymentHeader as U, type VerifyErrorCode as V, parseReceipt as W, type X402AcceptEntry as X, parseReceiptExtension as Y, parseSettleResponse as Z, parseSignatureHeader as _, type AssetId as a, parseUptoObject as a0, parseUptoPaymentHeader as a1, pickAccept as a2, type ExactAuthorizationWire as b, type ExactPaymentPayload as c, type ExactPaymentPayloadAny as d, HEADER_RESPONSE as e, HEADER_RESPONSE_V1 as f, HEADER_SIGNATURE as g, HEADER_SIGNATURE_V1 as h, type ParsedExactPayment as i, type ParsedUptoPayment as j, type Permit2Authorization as k, type Permit2PaymentPayload as l, type Permit2UptoAuthorization as m, type Permit2UptoPaymentPayload as n, type PipRailReceipt as o, type SignedReceipt as p, type SpendAssetTotal as q, type SpendDenomTotal as r, SpendLedger as s, type SpendRecord as t, type SpendStore as u, type SpendSummary as v, type VerifyResult as w, type X402AnyAccept as x, type X402Challenge as y, type X402ExactAcceptEntry as z };
961
+ export { parseSettleResponse as $, type AddressId as A, type X402ExactAcceptEntry as B, type Caip2 as C, type X402PaymentSignature as D, EXT_OFFER_RECEIPT as E, type X402Receipt as F, type X402ResourceObject as G, HEADER_REQUIRED as H, type X402UptoAcceptEntry as I, buildChallengeHeader as J, buildExactSignatureHeader as K, buildPaymentIdentifierAdvertisement as L, buildReceiptExtension as M, buildReceiptHeader as N, buildSignatureHeader as O, type PaidReceipt as P, buildUptoSignatureHeader as Q, decodeBase64Json as R, type SettleOutcome as S, memorySpendStore as T, parseChallenge as U, type VerifyErrorCode as V, parseExactObject as W, type X402AcceptEntry as X, parseExactPaymentHeader as Y, parseReceipt as Z, parseReceiptExtension as _, type AssetId as a, parseSignatureHeader as a0, parseSignatureObject as a1, parseUptoObject as a2, parseUptoPaymentHeader as a3, pickAccept as a4, readPaymentIdentifier as a5, EXT_PAYMENT_IDENTIFIER as b, type ExactAuthorizationWire as c, type ExactPaymentPayload as d, type ExactPaymentPayloadAny as e, HEADER_RESPONSE as f, HEADER_RESPONSE_V1 as g, HEADER_SIGNATURE as h, HEADER_SIGNATURE_V1 as i, type ParsedExactPayment as j, type ParsedUptoPayment as k, type Permit2Authorization as l, type Permit2PaymentPayload as m, type Permit2UptoAuthorization as n, type Permit2UptoPaymentPayload as o, type PipRailReceipt as p, type SignedReceipt as q, type SpendAssetTotal as r, type SpendDenomTotal as s, SpendLedger as t, type SpendRecord as u, type SpendStore as v, type SpendSummary as w, type VerifyResult as x, type X402AnyAccept as y, type X402Challenge as z };
@@ -10,7 +10,7 @@ import {
10
10
  nativeCost,
11
11
  rejectForeignToken,
12
12
  toInsufficientFundsError
13
- } from "./chunk-SC2ZYDHD.js";
13
+ } from "./chunk-PAMKCWVW.js";
14
14
 
15
15
  // src/drivers/near/index.ts
16
16
  import { JsonRpcProvider, Account, actions as actions2 } from "near-api-js";
@@ -312,11 +312,11 @@ async function verifyNear(params) {
312
312
  return { ok: false, error: "tx_reverted", detail: `NEAR tx ${hash} failed on-chain.` };
313
313
  }
314
314
  if (accept.asset === "native") {
315
- if (typeof tx.timestampMs !== "number") {
316
- return { ok: false, error: "payment_expired", detail: `Cannot bound the age of native NEAR tx ${hash} (no block time) \u2014 failing closed.` };
315
+ if (!Number.isFinite(tx.timestampMs)) {
316
+ return { ok: false, error: "payment_expired", detail: `Cannot bound the age of native NEAR tx ${hash} (no/invalid block time) \u2014 failing closed.` };
317
317
  }
318
318
  const ageSeconds = Math.floor(Date.now() / 1e3) - Math.floor(tx.timestampMs / 1e3);
319
- if (ageSeconds > accept.maxTimeoutSeconds) {
319
+ if (!Number.isFinite(ageSeconds) || ageSeconds > accept.maxTimeoutSeconds) {
320
320
  return { ok: false, error: "payment_expired", detail: `Payment is ${ageSeconds}s old; max allowed is ${accept.maxTimeoutSeconds}s.` };
321
321
  }
322
322
  if (tx.receiverId !== accept.payTo) {
@@ -569,7 +569,16 @@ function makeNearNetwork(preset, rpcUrl) {
569
569
  }
570
570
  throw new ConfirmationTimeoutError(`NEAR tx ${hash} not confirmed in time.`);
571
571
  },
572
- async estimateCost() {
572
+ async estimateCost(accept) {
573
+ if (accept.scheme === "exact") {
574
+ return nativeCost({
575
+ symbol: "NEAR",
576
+ decimals: NEAR_DECIMALS,
577
+ fee: 0n,
578
+ basis: "estimated",
579
+ detail: "gasless \u2014 the relayer prepays gas + the 1 yocto; the buyer pays 0 NEAR"
580
+ });
581
+ }
573
582
  return nativeCost({
574
583
  symbol: "NEAR",
575
584
  decimals: NEAR_DECIMALS,
@@ -10,7 +10,7 @@
10
10
 
11
11
 
12
12
 
13
- var _chunkMWBT7MCEcjs = require('./chunk-MWBT7MCE.cjs');
13
+ var _chunkGYM46G5Lcjs = require('./chunk-GYM46G5L.cjs');
14
14
 
15
15
  // src/drivers/near/index.ts
16
16
  var _nearapijs = require('near-api-js');
@@ -61,18 +61,18 @@ async function payNear(params) {
61
61
  return res.hash;
62
62
  } catch (err) {
63
63
  if (isNearRegistrationError(err)) {
64
- throw new (0, _chunkMWBT7MCEcjs.RecipientNotReadyError)(
64
+ throw new (0, _chunkGYM46G5Lcjs.RecipientNotReadyError)(
65
65
  `NEAR recipient ${accept.payTo} isn't registered on token ${accept.asset} (NEP-145 storage_deposit) \u2014 register it once (\u22480.00125 NEAR) before it can receive. (NEAR: not registered)`,
66
66
  { cause: err }
67
67
  );
68
68
  }
69
69
  if (isNearAffordability(err)) {
70
- throw new (0, _chunkMWBT7MCEcjs.InsufficientFundsError)(
70
+ throw new (0, _chunkGYM46G5Lcjs.InsufficientFundsError)(
71
71
  err instanceof Error ? err.message : "Insufficient NEAR balance for the payment.",
72
72
  { cause: err }
73
73
  );
74
74
  }
75
- throw _nullishCoalesce(_chunkMWBT7MCEcjs.toInsufficientFundsError.call(void 0, err), () => ( err));
75
+ throw _nullishCoalesce(_chunkGYM46G5Lcjs.toInsufficientFundsError.call(void 0, err), () => ( err));
76
76
  }
77
77
  }
78
78
  async function payNearNative(params) {
@@ -82,12 +82,12 @@ async function payNearNative(params) {
82
82
  return res.hash;
83
83
  } catch (err) {
84
84
  if (isNearAffordability(err)) {
85
- throw new (0, _chunkMWBT7MCEcjs.InsufficientFundsError)(
85
+ throw new (0, _chunkGYM46G5Lcjs.InsufficientFundsError)(
86
86
  err instanceof Error ? err.message : "Insufficient NEAR balance for the payment.",
87
87
  { cause: err }
88
88
  );
89
89
  }
90
- throw _nullishCoalesce(_chunkMWBT7MCEcjs.toInsufficientFundsError.call(void 0, err), () => ( err));
90
+ throw _nullishCoalesce(_chunkGYM46G5Lcjs.toInsufficientFundsError.call(void 0, err), () => ( err));
91
91
  }
92
92
  }
93
93
  function isNearRegistrationError(err) {
@@ -109,28 +109,28 @@ var NONCE_BLOCK_MULTIPLIER = 1000000n;
109
109
  async function payExactNear(input) {
110
110
  const { signer, senderId, blockHeight, accessKeyNonce, accept } = input;
111
111
  if (accept.asset === "native") {
112
- throw new (0, _chunkMWBT7MCEcjs.UnsupportedSchemeError)(
112
+ throw new (0, _chunkGYM46G5Lcjs.UnsupportedSchemeError)(
113
113
  "NEAR exact is NEP-141-only (an ft_transfer); native NEAR is not exact-payable. Pay via onchain-proof."
114
114
  );
115
115
  }
116
116
  if (!isValidNearAccountId(accept.asset)) {
117
- throw new (0, _chunkMWBT7MCEcjs.UnsupportedSchemeError)(`NEAR exact: asset "${accept.asset}" must be a NEP-141 contract account id.`);
117
+ throw new (0, _chunkGYM46G5Lcjs.UnsupportedSchemeError)(`NEAR exact: asset "${accept.asset}" must be a NEP-141 contract account id.`);
118
118
  }
119
119
  if (!isValidNearAccountId(accept.payTo)) {
120
- throw new (0, _chunkMWBT7MCEcjs.UnsupportedSchemeError)(`NEAR exact: payTo "${accept.payTo}" is not a valid NEAR account id.`);
120
+ throw new (0, _chunkGYM46G5Lcjs.UnsupportedSchemeError)(`NEAR exact: payTo "${accept.payTo}" is not a valid NEAR account id.`);
121
121
  }
122
122
  if (!isValidNearAccountId(senderId)) {
123
- throw new (0, _chunkMWBT7MCEcjs.UnsupportedSchemeError)(`NEAR exact: sender "${senderId}" is not a valid NEAR account id.`);
123
+ throw new (0, _chunkGYM46G5Lcjs.UnsupportedSchemeError)(`NEAR exact: sender "${senderId}" is not a valid NEAR account id.`);
124
124
  }
125
125
  const t = accept.maxTimeoutSeconds;
126
126
  if (!Number.isInteger(t) || t <= 0) {
127
- throw new (0, _chunkMWBT7MCEcjs.UnsupportedSchemeError)("NEAR exact: maxTimeoutSeconds must be a positive integer.");
127
+ throw new (0, _chunkGYM46G5Lcjs.UnsupportedSchemeError)("NEAR exact: maxTimeoutSeconds must be a positive integer.");
128
128
  }
129
129
  const timeoutBlocks = BigInt(Math.max(1, Math.ceil(t / ESTIMATED_BLOCK_SECONDS)));
130
130
  const maxBlockHeight = blockHeight + timeoutBlocks;
131
131
  const nonce = accessKeyNonce + 1n;
132
132
  if (nonce >= blockHeight * NONCE_BLOCK_MULTIPLIER) {
133
- throw new (0, _chunkMWBT7MCEcjs.UnsupportedSchemeError)(
133
+ throw new (0, _chunkGYM46G5Lcjs.UnsupportedSchemeError)(
134
134
  "NEAR exact: the access-key nonce is at the protocol ceiling for this block height; cannot build a delegate action."
135
135
  );
136
136
  }
@@ -259,7 +259,7 @@ async function verifyAndSettleExactNear(input) {
259
259
  if (/not enough|insufficient|exceeded the prepaid gas|NotEnoughBalance|doesn't have enough|is not registered/i.test(m)) {
260
260
  return fail("tx_reverted", `the ft_transfer would fail on chain: ${shorten(m)}.`);
261
261
  }
262
- throw new (0, _chunkMWBT7MCEcjs.SettlementError)(
262
+ throw new (0, _chunkGYM46G5Lcjs.SettlementError)(
263
263
  `NEAR exact settle: the relayer could not submit the delegate (${shorten(m)}). The buyer's signed delegate is still valid \u2014 fund/fix the relayer and the buyer can re-present it.`,
264
264
  { cause: err }
265
265
  );
@@ -312,11 +312,11 @@ async function verifyNear(params) {
312
312
  return { ok: false, error: "tx_reverted", detail: `NEAR tx ${hash} failed on-chain.` };
313
313
  }
314
314
  if (accept.asset === "native") {
315
- if (typeof tx.timestampMs !== "number") {
316
- return { ok: false, error: "payment_expired", detail: `Cannot bound the age of native NEAR tx ${hash} (no block time) \u2014 failing closed.` };
315
+ if (!Number.isFinite(tx.timestampMs)) {
316
+ return { ok: false, error: "payment_expired", detail: `Cannot bound the age of native NEAR tx ${hash} (no/invalid block time) \u2014 failing closed.` };
317
317
  }
318
318
  const ageSeconds = Math.floor(Date.now() / 1e3) - Math.floor(tx.timestampMs / 1e3);
319
- if (ageSeconds > accept.maxTimeoutSeconds) {
319
+ if (!Number.isFinite(ageSeconds) || ageSeconds > accept.maxTimeoutSeconds) {
320
320
  return { ok: false, error: "payment_expired", detail: `Payment is ${ageSeconds}s old; max allowed is ${accept.maxTimeoutSeconds}s.` };
321
321
  }
322
322
  if (tx.receiverId !== accept.payTo) {
@@ -408,13 +408,13 @@ function txNotFound(hash) {
408
408
 
409
409
  function assertNearWallet(wallet, network) {
410
410
  if (typeof wallet !== "object" || wallet === null) {
411
- throw new (0, _chunkMWBT7MCEcjs.WrongFamilyError)(
411
+ throw new (0, _chunkGYM46G5Lcjs.WrongFamilyError)(
412
412
  `chain ${network} is NEAR; wallet must be { accountId, key } (key = ed25519:\u2026).`
413
413
  );
414
414
  }
415
- _chunkMWBT7MCEcjs.assertNoLegacyWalletKey.call(void 0, wallet, "NEAR");
415
+ _chunkGYM46G5Lcjs.assertNoLegacyWalletKey.call(void 0, wallet, "NEAR");
416
416
  if (!("accountId" in wallet) || !("key" in wallet)) {
417
- throw new (0, _chunkMWBT7MCEcjs.WrongFamilyError)(
417
+ throw new (0, _chunkGYM46G5Lcjs.WrongFamilyError)(
418
418
  `chain ${network} is NEAR; wallet must be { accountId, key } (key = ed25519:\u2026).`
419
419
  );
420
420
  }
@@ -422,13 +422,13 @@ function assertNearWallet(wallet, network) {
422
422
  }
423
423
  function resolveNearWallet(config) {
424
424
  if (!config.accountId || !config.key) {
425
- throw new (0, _chunkMWBT7MCEcjs.WrongFamilyError)("NEAR wallet needs { accountId, key } (key = ed25519:\u2026).");
425
+ throw new (0, _chunkGYM46G5Lcjs.WrongFamilyError)("NEAR wallet needs { accountId, key } (key = ed25519:\u2026).");
426
426
  }
427
427
  let signer;
428
428
  try {
429
429
  signer = _nearapijs.KeyPairSigner.fromSecretKey(config.key);
430
430
  } catch (cause) {
431
- throw new (0, _chunkMWBT7MCEcjs.WrongFamilyError)("NEAR wallet { key } is not a valid ed25519:\u2026 secret key.", {
431
+ throw new (0, _chunkGYM46G5Lcjs.WrongFamilyError)("NEAR wallet { key } is not a valid ed25519:\u2026 secret key.", {
432
432
  cause
433
433
  });
434
434
  }
@@ -490,16 +490,16 @@ function makeNearNetwork(preset, rpcUrl) {
490
490
  const info = preset.tokens[token.toUpperCase()];
491
491
  if (!info) {
492
492
  const known = Object.keys(preset.tokens).join(", ") || "(none built in)";
493
- throw new (0, _chunkMWBT7MCEcjs.UnknownTokenError)(
493
+ throw new (0, _chunkGYM46G5Lcjs.UnknownTokenError)(
494
494
  `token "${token}" isn't built in for NEAR (known: ${known}). Pass { contractId, decimals } for a custom NEP-141.`
495
495
  );
496
496
  }
497
497
  return { asset: info.contractId, decimals: info.decimals, symbol: info.symbol };
498
498
  }
499
- _chunkMWBT7MCEcjs.rejectForeignToken.call(void 0, token, "near", network);
499
+ _chunkGYM46G5Lcjs.rejectForeignToken.call(void 0, token, "near", network);
500
500
  const t = token;
501
501
  if (!t.contractId || typeof t.decimals !== "number") {
502
- throw new (0, _chunkMWBT7MCEcjs.WrongFamilyError)(
502
+ throw new (0, _chunkGYM46G5Lcjs.WrongFamilyError)(
503
503
  `chain ${network} is NEAR; a custom token must be { contractId, decimals }.`
504
504
  );
505
505
  }
@@ -518,12 +518,12 @@ function makeNearNetwork(preset, rpcUrl) {
518
518
  },
519
519
  assertValidPayTo(payTo) {
520
520
  if (payTo.startsWith("0x")) {
521
- throw new (0, _chunkMWBT7MCEcjs.WrongFamilyError)(
521
+ throw new (0, _chunkGYM46G5Lcjs.WrongFamilyError)(
522
522
  `chain ${network} is NEAR, but payTo "${payTo}" looks like an EVM/Sui 0x address.`
523
523
  );
524
524
  }
525
525
  if (!isValidNearAccountId(payTo)) {
526
- throw new (0, _chunkMWBT7MCEcjs.WrongFamilyError)(
526
+ throw new (0, _chunkGYM46G5Lcjs.WrongFamilyError)(
527
527
  `chain ${network} is NEAR, but payTo "${payTo}" is not a valid NEAR account id.`
528
528
  );
529
529
  }
@@ -567,10 +567,19 @@ function makeNearNetwork(preset, rpcUrl) {
567
567
  if (tx && tx.success) return { height: "0" };
568
568
  } catch (e11) {
569
569
  }
570
- throw new (0, _chunkMWBT7MCEcjs.ConfirmationTimeoutError)(`NEAR tx ${hash} not confirmed in time.`);
570
+ throw new (0, _chunkGYM46G5Lcjs.ConfirmationTimeoutError)(`NEAR tx ${hash} not confirmed in time.`);
571
571
  },
572
- async estimateCost() {
573
- return _chunkMWBT7MCEcjs.nativeCost.call(void 0, {
572
+ async estimateCost(accept) {
573
+ if (accept.scheme === "exact") {
574
+ return _chunkGYM46G5Lcjs.nativeCost.call(void 0, {
575
+ symbol: "NEAR",
576
+ decimals: NEAR_DECIMALS,
577
+ fee: 0n,
578
+ basis: "estimated",
579
+ detail: "gasless \u2014 the relayer prepays gas + the 1 yocto; the buyer pays 0 NEAR"
580
+ });
581
+ }
582
+ return _chunkGYM46G5Lcjs.nativeCost.call(void 0, {
574
583
  symbol: "NEAR",
575
584
  decimals: NEAR_DECIMALS,
576
585
  fee: 1500000000000000000000n,
@@ -692,7 +701,7 @@ function makeNearNetwork(preset, rpcUrl) {
692
701
  try {
693
702
  relayerWallet = resolveNearWallet(relayer._native);
694
703
  } catch (err) {
695
- throw new (0, _chunkMWBT7MCEcjs.SettlementError)(
704
+ throw new (0, _chunkGYM46G5Lcjs.SettlementError)(
696
705
  `NEAR exact settle: the relayer wallet is invalid (${err instanceof Error ? err.message : String(err)}).`,
697
706
  { cause: err }
698
707
  );
package/dist/node.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { u as SpendStore } from './ledger-mF_SoiDB.cjs';
2
- export { Q as memorySpendStore } from './ledger-mF_SoiDB.cjs';
1
+ import { v as SpendStore } from './ledger-uFtXlIHY.cjs';
2
+ export { T as memorySpendStore } from './ledger-uFtXlIHY.cjs';
3
3
 
4
4
  /**
5
5
  * A durable {@link SpendStore} backed by a local JSONL file (one settled payment per
package/dist/node.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { u as SpendStore } from './ledger-mF_SoiDB.js';
2
- export { Q as memorySpendStore } from './ledger-mF_SoiDB.js';
1
+ import { v as SpendStore } from './ledger-uFtXlIHY.js';
2
+ export { T as memorySpendStore } from './ledger-uFtXlIHY.js';
3
3
 
4
4
  /**
5
5
  * A durable {@link SpendStore} backed by a local JSONL file (one settled payment per
@@ -8,7 +8,7 @@ import {
8
8
  nativeCost,
9
9
  rejectForeignToken,
10
10
  toInsufficientFundsError
11
- } from "./chunk-SC2ZYDHD.js";
11
+ } from "./chunk-PAMKCWVW.js";
12
12
 
13
13
  // src/drivers/solana/index.ts
14
14
  import { Connection, PublicKey as PublicKey3 } from "@solana/web3.js";
@@ -16,6 +16,7 @@ import {
16
16
  getAccount,
17
17
  getAssociatedTokenAddressSync as getAssociatedTokenAddressSync3,
18
18
  TOKEN_2022_PROGRAM_ID as TOKEN_2022_PROGRAM_ID2,
19
+ TOKEN_PROGRAM_ID as TOKEN_PROGRAM_ID2,
19
20
  TokenAccountNotFoundError
20
21
  } from "@solana/spl-token";
21
22
 
@@ -126,15 +127,15 @@ async function verifySolana(params) {
126
127
  detail: `Transaction ${signature} failed on-chain.`
127
128
  };
128
129
  }
129
- if (typeof tx.blockTime !== "number") {
130
+ if (!Number.isFinite(tx.blockTime)) {
130
131
  return {
131
132
  ok: false,
132
133
  error: "payment_expired",
133
- detail: `Cannot determine the age of ${signature} (no blockTime).`
134
+ detail: `Cannot determine the age of ${signature} (no/invalid blockTime).`
134
135
  };
135
136
  }
136
137
  const ageSeconds = Math.floor(Date.now() / 1e3) - tx.blockTime;
137
- if (ageSeconds > accept.maxTimeoutSeconds) {
138
+ if (!Number.isFinite(ageSeconds) || ageSeconds > accept.maxTimeoutSeconds) {
138
139
  return {
139
140
  ok: false,
140
141
  error: "payment_expired",
@@ -429,6 +430,8 @@ async function verifyAndSettleExactSolana(input) {
429
430
  if (price > MAX_COMPUTE_UNIT_PRICE_MICROLAMPORTS) {
430
431
  return fail("signature_invalid", `Compute-unit price ${price} \xB5lamports exceeds the ${MAX_COMPUTE_UNIT_PRICE_MICROLAMPORTS} cap (fee-payer drain guard).`);
431
432
  }
433
+ } else {
434
+ return fail("signature_invalid", `Unexpected ComputeBudget instruction (discriminator ${data[0]}) \u2014 only set-unit-limit/price are allowed (fee-payer drain guard).`);
432
435
  }
433
436
  }
434
437
  const isSignedSigner = (pubkey) => {
@@ -717,14 +720,26 @@ function makeSolanaNetwork(preset, rpcUrl) {
717
720
  if (asset === "native") return { token: native, native };
718
721
  let token;
719
722
  try {
720
- const ata = getAssociatedTokenAddressSync3(new PublicKey3(asset), owner);
721
- token = (await getAccount(connection, ata, "confirmed")).amount;
723
+ const mint = new PublicKey3(asset);
724
+ const info = await connection.getAccountInfo(mint);
725
+ const programId = info?.owner.equals(TOKEN_2022_PROGRAM_ID2) ? TOKEN_2022_PROGRAM_ID2 : TOKEN_PROGRAM_ID2;
726
+ const ata = getAssociatedTokenAddressSync3(mint, owner, false, programId);
727
+ token = (await getAccount(connection, ata, "confirmed", programId)).amount;
722
728
  } catch (e) {
723
729
  token = e instanceof TokenAccountNotFoundError ? 0n : null;
724
730
  }
725
731
  return { token, native };
726
732
  },
727
- // No receive prerequisite the payer's tx idempotently creates the recipient's ATA (pay.ts).
733
+ // No receive prerequisite for the DEFAULT onchain-proof rail the payer's tx idempotently
734
+ // creates the recipient's ATA (pay.ts). KNOWN LIMITATION (documented, not a bug): on the opt-in
735
+ // `exact` rail the buyer cannot create the ATA (payExactSolana throws if payTo's token account
736
+ // is missing), so `planPayment`/`canAfford` can be OPTIMISTIC for an exact payment to a
737
+ // brand-new recipient whose ATA doesn't yet exist — marked payable, and `autoRoute` would pick
738
+ // it then refuse (pre-broadcast, recoverable) at pay time. Mitigations in practice: onchain-proof
739
+ // is always co-offered (and DOES create the ATA), `exact` + `autoRoute` are both off by default,
740
+ // and most merchant receive accounts already exist. 'n/a' is correct for onchain-proof; an
741
+ // exact-aware probe needs the token-program-correct ATA derivation (an extra mint-owner read)
742
+ // and is deferred as disproportionate to this opt-in edge.
728
743
  async recipientReady() {
729
744
  return { ready: "n/a" };
730
745
  },