@piprail/sdk 2.7.0 → 2.9.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 +96 -0
  2. package/README.md +5 -3
  3. package/dist/{algorand-WB6PBJU4.js → algorand-AA3WXKW4.js} +1 -1
  4. package/dist/{algorand-TMA62DN2.cjs → algorand-FCEECDG6.cjs} +32 -32
  5. package/dist/{aptos-JQMZNTMD.cjs → aptos-GHJPO6JJ.cjs} +31 -31
  6. package/dist/{aptos-QAAXIUY3.js → aptos-LY67Q6QF.js} +1 -1
  7. package/dist/{chunk-JG6KRAW6.cjs → chunk-MWBT7MCE.cjs} +13 -1
  8. package/dist/chunk-O4UQOZ4Z.cjs +14 -0
  9. package/dist/{chunk-7XK22JSQ.js → chunk-SC2ZYDHD.js} +12 -0
  10. package/dist/chunk-SK3CB7UA.js +14 -0
  11. package/dist/index.cjs +754 -238
  12. package/dist/index.d.cts +2386 -2577
  13. package/dist/index.d.ts +2386 -2577
  14. package/dist/index.js +595 -79
  15. package/dist/ledger-BtzrfO-3.d.cts +658 -0
  16. package/dist/ledger-BtzrfO-3.d.ts +658 -0
  17. package/dist/{near-H5AQ253I.cjs → near-6KAQVVG2.cjs} +26 -26
  18. package/dist/{near-OTPQD6BI.js → near-FZBUICCS.js} +1 -1
  19. package/dist/node.cjs +38 -0
  20. package/dist/node.d.cts +16 -0
  21. package/dist/node.d.ts +16 -0
  22. package/dist/node.js +38 -0
  23. package/dist/{solana-3FMCWSEE.js → solana-ELUWO6N5.js} +33 -2
  24. package/dist/{solana-M3VOHCMO.cjs → solana-MYF4HBO4.cjs} +64 -33
  25. package/dist/{stellar-U5NCRIOJ.js → stellar-BEMT7UYF.js} +1 -1
  26. package/dist/{stellar-FW6C6FBE.cjs → stellar-SUKASK4N.cjs} +20 -20
  27. package/dist/{sui-Y53M4GUM.js → sui-F5JQ2N6I.js} +1 -1
  28. package/dist/{sui-47C2KEZI.cjs → sui-VE5LT7BL.cjs} +16 -16
  29. package/dist/{ton-5ZPT5PSP.js → ton-7GKCTC5H.js} +11 -7
  30. package/dist/{ton-MMPKWT6N.cjs → ton-AOR3EURW.cjs} +25 -21
  31. package/dist/{tron-JOT4STIG.cjs → tron-EMFXDFHW.cjs} +24 -24
  32. package/dist/{tron-WYS4X2I5.js → tron-ZZZS3FNN.js} +1 -1
  33. package/dist/{xrpl-2MZEOIFY.js → xrpl-DD7TJL5L.js} +1 -1
  34. package/dist/{xrpl-PECT4IMX.cjs → xrpl-Y6SQNYLC.cjs} +20 -20
  35. package/package.json +11 -1
package/CHANGELOG.md CHANGED
@@ -4,6 +4,100 @@ All notable changes to `@piprail/sdk` are documented here. The format
4
4
  follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the
5
5
  versions follow [Semantic Versioning](https://semver.org/).
6
6
 
7
+ ## [2.9.0] — 2026-06-19 — Cross-token grand total · payment-count caps · durable budget · richer spend observability
8
+
9
+ Spend controls grow up — a single budget across every token and chain, caps on the *number* of
10
+ payments, a budget that can survive a restart, and first-class decline/threshold events. Everything
11
+ is **additive and opt-in**: omit the new fields and behaviour is byte-identical to 2.8.0.
12
+
13
+ - **feat(policy): `maxTotalPerDenom` — the cross-token GRAND TOTAL.** Cap "$20 total across every
14
+ stablecoin and chain, full stop" with one number: `policy: { maxTotalPerDenom: { USD: '20.00', EUR: '5.00' } }`.
15
+ The SDK sums the human value of every token of that denomination (USDC/USDT/USD1/FDUSD/RLUSD → `USD`,
16
+ EURC → `EUR`; extend via `denomFor`) and refuses the payment that would breach it
17
+ (`reasonCode: 'BUDGET'`). **Not a price oracle** — PipRail still reads no market and never prices a
18
+ volatile coin; it's a user-declared unit-of-account sum (each token counted 1:1), and native/unknown
19
+ tokens are never in a bucket. Coexists with the per-asset `maxTotal`; the stricter cap wins. Exported
20
+ helpers: `denomOf`, `BUILTIN_DENOMS`, `DENOM_PRECISION`.
21
+ - **feat(policy): payment-COUNT caps.** `maxPayments` (lifetime) and `maxPaymentsPerWindow`
22
+ (+ `windowSeconds`) cap the *number* of payments across every chain + token — a rate limit that
23
+ needs no oracle. (`windowSeconds` is now the shared width for the money window AND the count window.)
24
+ - **feat(client): durable budget via a pluggable `spendStore`.** Pass `spendStore` and the spend
25
+ ledger hydrates at construction + persists every settle, so `maxTotal` / `maxTotalPerDenom` / the
26
+ count caps **survive a restart** — with no PipRail backend (you own the store, like the gate's
27
+ replay set). Ships `memorySpendStore` (from `@piprail/sdk`) and **`fileSpendStore(path)` from the new
28
+ `@piprail/sdk/node` entry** (a one-line local JSONL log; kept out of the browser bundle). `SpendLedger`
29
+ is now exported so several single-chain clients can SHARE one — `MultiChainPayer.fromWallets` does this
30
+ for you, making the grand total + count caps span every chain as ONE budget (also `spendStore` on its options).
31
+ - **feat(client): richer spend observability.** New constructor option `onSpend(record, budget)` —
32
+ the ergonomic "log my spend locally" hook, fired after each settle. Two new additive `PipRailEvent`
33
+ kinds: **`payment-declined`** (the rich decline — typed `reasonCode`, fine `PolicyDenyCode`, the quote,
34
+ and a budget snapshot; `payment-failed` still fires too for back-compat) and **`budget-threshold`**
35
+ (an early warning the first time spend crosses `policy.warnAtFraction` of any cap).
36
+ - **feat(client): budget surface extended (additive).** `client.budget()` now also returns
37
+ `byDenom: DenomRemaining[]` (the grand-total leash, previewable *before* any spend) and
38
+ `counts: CountStatus`; new reads `client.denomRemaining()`, `client.countStatus()`, and
39
+ `client.policy()` (the configured leash read back, also on `MultiChainPayer` + the `PayingClient`
40
+ interface). `client.spent()` / `SpendSummary` gains `byDenom: SpendDenomTotal[]`; `SpendRecord` now
41
+ carries `decimals` + `denom`. `formatSpendReport` appends the grand total when present.
42
+ - **New deny codes** on `PolicyDenyCode`: `MAX_TOTAL_DENOM`, `MAX_PAYMENTS`, `WINDOW_COUNT` (the
43
+ coarse `DeclineReasonCode` set is unchanged — they map to `BUDGET` / `BUDGET` / `OUTSIDE_WINDOW`).
44
+ - **New package entry `@piprail/sdk/node`** (`exports["./node"]`) for the Node-only `fileSpendStore`;
45
+ the core `@piprail/sdk` bundle stays browser-safe (no static `node:fs`).
46
+ - **Hardened against an adversarial review** (38-agent fuzz of the new surface). Fixes shipped
47
+ before release — see [Internals & hardening](https://docs.piprail.com/spend-controls/internals/):
48
+ - **OOM/DoS:** an absurd server-stated `decimals` (e.g. `1e9`) is rejected by a new `MAX_DECIMALS`
49
+ (100) bound at the envelope + the `assertValidDecimals` chokepoint (no multi-GB string).
50
+ - **Grand-total bypass (fund safety):** a token labelled `USDC` with `decimals` in `(24, 100]`
51
+ once **escaped** `maxTotalPerDenom`. `DENOM_PRECISION` is now pinned to `MAX_DECIMALS` and the
52
+ denom check **fails closed** (refuses an unscalable capped token, never skips it).
53
+ - **Strictest-cap-wins:** case-variant / whitespace / duplicate denomination keys (`{ USD, usd }`,
54
+ `" USD "`, a repeated CSV denom) now enforce the SMALLEST cap, never silently relax the leash.
55
+ - **Native never bucketed:** a native coin can't be summed into a USD/EUR total even if its symbol
56
+ matches a stablecoin.
57
+ - **Poisoned-store crash-safety:** the ledger validates + skips un-tallyable hydrated records
58
+ (non-numeric/negative `amountBase`, out-of-range `decimals`), so a corrupt store line can't crash
59
+ construction or make `budget()`/`spent()`/`summary()` throw; an unparseable `at` fails closed.
60
+ - **Loud validation:** `expiresAt` (must be a representable epoch-ms), a non-plain-object
61
+ `maxTotalPerDenom`, and a non-string `denomFor` value are all rejected at construction (the last
62
+ would otherwise throw at PAY time, after settlement).
63
+ - **Poisoned `denom` (final-pass fix):** a hydrated store record with a non-string `denom` is
64
+ coerced to "no denomination" (it still tallies per-asset) rather than throwing
65
+ `denom.toUpperCase()` out of construction/reads — completing the crash-safety guarantee.
66
+ - **`budget-threshold` dedup is ledger-scoped:** on a shared cross-chain ledger
67
+ (`MultiChainPayer.fromWallets`) a threshold now fires ONCE for the whole budget, not once per chain.
68
+
69
+ ## [2.8.0] — 2026-06-19 — Solana exact SPL-Memo conformance · TON canonical CAIP-2 (`tvm:-239`) · Toncoin→Gram
70
+
71
+ - **chore(ton): native coin symbol `TON` → `GRAM` (Toncoin → Gram rebrand).** A TON community
72
+ governance vote renamed the native token *Toncoin → Gram* (ticker `TON` → `GRAM`), live 2026-06-15.
73
+ It's a token-only, presentation-layer rename — the blockchain is still **The Open Network (TON)**, the
74
+ CAIP-2 network id stays `tvm:-239`, and addresses/contracts/jettons are unchanged (no migration). The
75
+ SDK now surfaces the native coin's symbol as `GRAM` (a 402's `extra.symbol`, `describeAsset`, and
76
+ `estimateCost`'s `feeSymbol`); `chain: 'ton'` and `token: 'native'` select it exactly as before, and
77
+ USD₮ / other jettons are unaffected.
78
+ - **fix(ton): emit canonical CAIP-2 `tvm:-239` (was `ton:-239`)** — the chainagnostic CAIP-2 registry
79
+ has no `ton` namespace and the merged foundation TON exact scheme mandates the `tvm` namespace, so a
80
+ TON 402's `accepts[].network` (and slug resolution / receipts) now emit `tvm:-239`. This makes
81
+ PipRail's TON 402s matchable by discovery indexes and any standard x402 client/facilitator keying on
82
+ the canonical id. **Back-compat:** the legacy `ton:-239` id is still accepted on parse — an inbound or
83
+ foreign challenge using the old id normalizes to `tvm:-239` and routes/verifies unchanged. The
84
+ internal `ton:<address>|<nonce>` proof-locator prefix is unrelated and unchanged.
85
+ - **Solana `exact` SVM conformance — the buyer now emits the spec-required SPL-Memo.** The ratified
86
+ x402 SVM `exact` scheme (§1.2/§3.1) says clients **MUST** include a Memo instruction — `extra.memo`
87
+ verbatim when present, else a random ≥16-byte hex nonce for transaction uniqueness across concurrent
88
+ identical-parameter payments. PipRail's Solana exact buyer previously emitted none, so a seller that
89
+ set `extra.memo` (or a facilitator enforcing the uniqueness Memo) rejected the payment. The buyer now
90
+ appends one SPL-Memo as instruction `[3]`, keeping the exact-rail tx at **4** instructions (still
91
+ inside Path-1's 3-to-7 fast path; SPL-Memo is category-exempt, so it never trips the smart-wallet
92
+ allowlist or the fee-payer drain guard). An `extra.memo` over the 256-byte scheme cap is rejected
93
+ (`UnsupportedSchemeError`). This **changes the exact-rail's default emitted bytes** (a Memo is now
94
+ present) — a *required* conformance change, additive on the wire (old PipRail gates already tolerate
95
+ an inbound Memo). The `onchain-proof` default is byte-identical and untouched.
96
+ - **harden(units): validate `decimals` is a non-negative safe integer.** `parseUnits` / `floorUnits` /
97
+ `formatUnits` now reject a negative, fractional, or NaN `decimals` argument up front (instead of
98
+ silently corrupting the bigint math via `padStart` / `slice`) — defence against a malformed preset or
99
+ a bad caller arg. Existing valid calls are unaffected. Thanks to @samsamtrum (#25).
100
+
7
101
  ## [2.7.0] — 2026-06-19 — symmetric payment notifications (`onFailed`: both sides notified on success AND failure)
8
102
 
9
103
  Additive and backward-compatible — defaults and the zero-config 402 stay byte-identical; omit the new
@@ -1433,6 +1527,8 @@ straight into your wallet. The API is small and self-contained.
1433
1527
  to your wallet; PipRail never holds funds.
1434
1528
  - `viem ^2.21` is a peer dependency. Node 20+ or a modern browser.
1435
1529
 
1530
+ [2.8.0]: https://www.npmjs.com/package/@piprail/sdk
1531
+ [2.7.0]: https://www.npmjs.com/package/@piprail/sdk
1436
1532
  [2.6.0]: https://www.npmjs.com/package/@piprail/sdk
1437
1533
  [2.5.0]: https://www.npmjs.com/package/@piprail/sdk
1438
1534
  [2.4.0]: https://www.npmjs.com/package/@piprail/sdk
package/README.md CHANGED
@@ -53,7 +53,9 @@ const payer = MultiChainPayer.fromWallets({
53
53
  solana: { key: process.env.SOLANA_KEY },
54
54
  xrpl: { key: process.env.XRPL_SEED },
55
55
  },
56
- policy: { maxAmount: '1.00', maxTotal: '10.00', tokens: ['USDC', 'USDT'] }, // one budget, every chain
56
+ // ONE budget across every chain: $20 total + at most 100 payments. `maxTotalPerDenom`
57
+ // sums every USD stablecoin on every chain (not a price oracle — a 1:1 unit sum).
58
+ policy: { maxAmount: '1.00', maxTotalPerDenom: { USD: '20.00' }, maxPayments: 100 },
57
59
  })
58
60
 
59
61
  await payer.planPayment(url) // read-only: every chain ranked, payable-first in your listed order
@@ -61,7 +63,7 @@ const res = await payer.get(url) // pays on the first chain that can settle —
61
63
  ```
62
64
 
63
65
  Built on `planAcross` / `fetchAcross` (the same composable primitives, for when you
64
- already hold an array of clients). See [`examples/multi-chain`](../examples/multi-chain).
66
+ already hold an array of clients). See [`examples/basics/multi-chain`](../examples/basics/multi-chain).
65
67
 
66
68
  The same app can **take** payments and **make** them. → [Making payments](https://docs.piprail.com/making-payments/piprail-client/)
67
69
 
@@ -74,7 +76,7 @@ The same app can **take** payments and **make** them. → [Making payments](http
74
76
  | **[Getting started](https://docs.piprail.com/getting-started/introduction/)** | Install · quickstart · how it works |
75
77
  | **[Accepting payments](https://docs.piprail.com/accepting-payments/require-payment-and-gate/)** | `requirePayment` · `createPaymentGate` · the `exact` rail |
76
78
  | **[Making payments](https://docs.piprail.com/making-payments/piprail-client/)** | `PipRailClient` · `quote` · `estimateCost` · `planPayment` · auto-route · `MultiChainPayer` |
77
- | **[Spend controls](https://docs.piprail.com/spend-controls/payment-policy/)** | Budgets · time envelope · the spend ledger |
79
+ | **[Spend controls](https://docs.piprail.com/spend-controls/payment-policy/)** | Per-token + cross-token grand total · payment-count caps · time envelope · durable budget · the spend ledger |
78
80
  | **[Agent toolkit](https://docs.piprail.com/agent-toolkit/payment-tools/)** | `paymentTools` · the agent guide · NL renderers |
79
81
  | **[Discovery](https://docs.piprail.com/discovery/discover-and-register/)** | Find & be found on the open x402 indexes ($0, no backend) |
80
82
  | **[Chains & tokens](https://docs.piprail.com/chains/overview/)** | Every chain, per-family setup & caveats |
@@ -10,7 +10,7 @@ import {
10
10
  nativeCost,
11
11
  rejectForeignToken,
12
12
  toInsufficientFundsError
13
- } from "./chunk-7XK22JSQ.js";
13
+ } from "./chunk-SC2ZYDHD.js";
14
14
 
15
15
  // src/drivers/algorand/index.ts
16
16
  import algosdk3 from "algosdk";
@@ -10,7 +10,7 @@
10
10
 
11
11
 
12
12
 
13
- var _chunkJG6KRAW6cjs = require('./chunk-JG6KRAW6.cjs');
13
+ var _chunkMWBT7MCEcjs = require('./chunk-MWBT7MCE.cjs');
14
14
 
15
15
  // src/drivers/algorand/index.ts
16
16
  var _algosdk = require('algosdk'); var _algosdk2 = _interopRequireDefault(_algosdk);
@@ -58,13 +58,13 @@ async function payAlgorand(params) {
58
58
  } catch (err) {
59
59
  const mapped = mapAlgorandError(err, accept.payTo);
60
60
  if (mapped) throw mapped;
61
- throw _nullishCoalesce(_chunkJG6KRAW6cjs.toInsufficientFundsError.call(void 0, err), () => ( err));
61
+ throw _nullishCoalesce(_chunkMWBT7MCEcjs.toInsufficientFundsError.call(void 0, err), () => ( err));
62
62
  }
63
63
  }
64
64
  function mapAlgorandError(err, payTo) {
65
65
  const m = err instanceof Error ? err.message : String(err);
66
66
  if (/must optin/i.test(m) || /missing from/i.test(m) && m.includes(payTo)) {
67
- return new (0, _chunkJG6KRAW6cjs.RecipientNotReadyError)(
67
+ return new (0, _chunkMWBT7MCEcjs.RecipientNotReadyError)(
68
68
  `Algorand recipient ${payTo} hasn't opted into this asset \u2014 it must opt in (a 0-amount asset transfer to itself) before it can receive. (Algorand: ${firstLine(m)})`,
69
69
  { cause: err }
70
70
  );
@@ -72,7 +72,7 @@ function mapAlgorandError(err, payTo) {
72
72
  if (/overspend|below min|min(imum)? balance|tried to spend|balance \d+ below|asset \d+ missing from|insufficient|underflow/i.test(
73
73
  m
74
74
  )) {
75
- return new (0, _chunkJG6KRAW6cjs.InsufficientFundsError)(
75
+ return new (0, _chunkMWBT7MCEcjs.InsufficientFundsError)(
76
76
  `Algorand payment failed: the sender can't cover it \u2014 token balance, ALGO for fees, the 0.1-ALGO minimum balance, or a missing asset opt-in on the sender. (Algorand: ${firstLine(m)})`,
77
77
  { cause: err }
78
78
  );
@@ -99,33 +99,33 @@ function isSet(addr) {
99
99
  function randomNote() {
100
100
  const g = globalThis.crypto;
101
101
  if (!_optionalChain([g, 'optionalAccess', _ => _.getRandomValues])) {
102
- throw new (0, _chunkJG6KRAW6cjs.UnsupportedSchemeError)("Algorand exact: no Web Crypto CSPRNG available to generate a unique note.");
102
+ throw new (0, _chunkMWBT7MCEcjs.UnsupportedSchemeError)("Algorand exact: no Web Crypto CSPRNG available to generate a unique note.");
103
103
  }
104
104
  return g.getRandomValues(new Uint8Array(32));
105
105
  }
106
106
  async function payExactAlgorand(input) {
107
107
  const { suggestedParams, sk, sender, accept } = input;
108
108
  if (accept.asset === "native") {
109
- throw new (0, _chunkJG6KRAW6cjs.UnsupportedSchemeError)(
109
+ throw new (0, _chunkMWBT7MCEcjs.UnsupportedSchemeError)(
110
110
  "Algorand exact is ASA-only (an asset transfer); native ALGO is not exact-payable. Pay via onchain-proof."
111
111
  );
112
112
  }
113
113
  const feePayer = accept.extra.feePayer;
114
114
  if (!feePayer) {
115
- throw new (0, _chunkJG6KRAW6cjs.UnsupportedSchemeError)("Algorand exact rail must advertise extra.feePayer (the fee sponsor address).");
115
+ throw new (0, _chunkMWBT7MCEcjs.UnsupportedSchemeError)("Algorand exact rail must advertise extra.feePayer (the fee sponsor address).");
116
116
  }
117
117
  const assetId = parseAlgorandAssetId(accept.asset);
118
118
  if (assetId === null) {
119
- throw new (0, _chunkJG6KRAW6cjs.UnsupportedSchemeError)(`Algorand exact rail asset "${accept.asset}" must be a numeric ASA id.`);
119
+ throw new (0, _chunkMWBT7MCEcjs.UnsupportedSchemeError)(`Algorand exact rail asset "${accept.asset}" must be a numeric ASA id.`);
120
120
  }
121
121
  if (!_algosdk2.default.isValidAddress(feePayer)) {
122
- throw new (0, _chunkJG6KRAW6cjs.UnsupportedSchemeError)(`Algorand exact: extra.feePayer "${feePayer}" is not a valid Algorand address.`);
122
+ throw new (0, _chunkMWBT7MCEcjs.UnsupportedSchemeError)(`Algorand exact: extra.feePayer "${feePayer}" is not a valid Algorand address.`);
123
123
  }
124
124
  if (!_algosdk2.default.isValidAddress(accept.payTo)) {
125
- throw new (0, _chunkJG6KRAW6cjs.UnsupportedSchemeError)(`Algorand exact: payTo "${accept.payTo}" is not a valid Algorand address.`);
125
+ throw new (0, _chunkMWBT7MCEcjs.UnsupportedSchemeError)(`Algorand exact: payTo "${accept.payTo}" is not a valid Algorand address.`);
126
126
  }
127
127
  if (feePayer === sender) {
128
- throw new (0, _chunkJG6KRAW6cjs.UnsupportedSchemeError)(
128
+ throw new (0, _chunkMWBT7MCEcjs.UnsupportedSchemeError)(
129
129
  "Algorand exact: the fee payer must differ from the payer \u2014 the buyer must pay ZERO ALGO (the sponsor pays the pooled fee)."
130
130
  );
131
131
  }
@@ -172,13 +172,13 @@ function decodeElement(bytes) {
172
172
  async function verifyAndSettleExactAlgorand(input) {
173
173
  const { client, feePayerSk, feePayerAddr, payload, accept } = input;
174
174
  const railFeePayer = accept.extra.feePayer;
175
- if (!railFeePayer) throw new (0, _chunkJG6KRAW6cjs.SettlementError)("Algorand exact: rail is missing extra.feePayer.");
175
+ if (!railFeePayer) throw new (0, _chunkMWBT7MCEcjs.SettlementError)("Algorand exact: rail is missing extra.feePayer.");
176
176
  if (railFeePayer !== feePayerAddr) {
177
- throw new (0, _chunkJG6KRAW6cjs.SettlementError)("Algorand exact: the gate relayer address does not match the rail extra.feePayer \u2014 misconfigured rail.");
177
+ throw new (0, _chunkMWBT7MCEcjs.SettlementError)("Algorand exact: the gate relayer address does not match the rail extra.feePayer \u2014 misconfigured rail.");
178
178
  }
179
179
  const assetId = parseAlgorandAssetId(accept.asset);
180
- if (assetId === null) throw new (0, _chunkJG6KRAW6cjs.SettlementError)(`Algorand exact: rail asset "${accept.asset}" is not a numeric ASA id.`);
181
- if (!_algosdk2.default.isValidAddress(accept.payTo)) throw new (0, _chunkJG6KRAW6cjs.SettlementError)(`Algorand exact: rail payTo "${accept.payTo}" is invalid.`);
180
+ if (assetId === null) throw new (0, _chunkMWBT7MCEcjs.SettlementError)(`Algorand exact: rail asset "${accept.asset}" is not a numeric ASA id.`);
181
+ if (!_algosdk2.default.isValidAddress(accept.payTo)) throw new (0, _chunkMWBT7MCEcjs.SettlementError)(`Algorand exact: rail payTo "${accept.payTo}" is invalid.`);
182
182
  const { paymentIndex, paymentGroup } = payload;
183
183
  if (paymentGroup.length !== GROUP_SIZE) {
184
184
  return fail("signature_invalid", `Algorand exact expects a ${GROUP_SIZE}-transaction group (payment + fee), got ${paymentGroup.length}.`);
@@ -244,7 +244,7 @@ async function verifyAndSettleExactAlgorand(input) {
244
244
  try {
245
245
  feeSigned = fee.signTxn(feePayerSk);
246
246
  } catch (err) {
247
- throw new (0, _chunkJG6KRAW6cjs.SettlementError)(`Algorand exact settle: the gate could not sign the fee transaction (${shorten(err instanceof Error ? err.message : String(err))}).`, { cause: err });
247
+ throw new (0, _chunkMWBT7MCEcjs.SettlementError)(`Algorand exact settle: the gate could not sign the fee transaction (${shorten(err instanceof Error ? err.message : String(err))}).`, { cause: err });
248
248
  }
249
249
  const signedGroup = elements.map((el, i) => i === paymentIndex ? payElement.raw : feeSigned);
250
250
  try {
@@ -266,7 +266,7 @@ async function verifyAndSettleExactAlgorand(input) {
266
266
  if (/signature|sig|auth|malformed/i.test(m)) return fail("signature_invalid", `Settle rejected \u2014 bad signature: ${shorten(m)}.`);
267
267
  if (/already in ledger|already committed|duplicate/i.test(m)) return fail("tx_already_used", `This payment was already settled: ${shorten(m)}.`);
268
268
  if (/\bround\b|expired|lifetime|stale|validity/i.test(m)) return fail("payment_expired", `Settle rejected \u2014 validity window expired: ${shorten(m)}.`);
269
- throw new (0, _chunkJG6KRAW6cjs.SettlementError)(
269
+ throw new (0, _chunkMWBT7MCEcjs.SettlementError)(
270
270
  `Algorand exact settle: the group failed to submit (${shorten(m)}). The buyer's signed transaction is still valid \u2014 fund/fix the fee payer (${railFeePayer}) and the buyer can re-present it.`,
271
271
  { cause: err }
272
272
  );
@@ -275,10 +275,10 @@ async function verifyAndSettleExactAlgorand(input) {
275
275
  try {
276
276
  round = await client.waitForConfirmation(buyerTxid);
277
277
  } catch (err) {
278
- throw new (0, _chunkJG6KRAW6cjs.SettlementError)(`Algorand exact settle: submitted ${buyerTxid} but confirmation read failed (${shorten(err instanceof Error ? err.message : String(err))}). It likely landed \u2014 re-verify before re-presenting; do NOT re-pay.`, { cause: err });
278
+ throw new (0, _chunkMWBT7MCEcjs.SettlementError)(`Algorand exact settle: submitted ${buyerTxid} but confirmation read failed (${shorten(err instanceof Error ? err.message : String(err))}). It likely landed \u2014 re-verify before re-presenting; do NOT re-pay.`, { cause: err });
279
279
  }
280
280
  if (round === null) {
281
- throw new (0, _chunkJG6KRAW6cjs.SettlementError)(`Algorand exact settle: submitted ${buyerTxid} but it did not confirm in time. It likely landed \u2014 re-verify before re-presenting; do NOT re-pay.`);
281
+ throw new (0, _chunkMWBT7MCEcjs.SettlementError)(`Algorand exact settle: submitted ${buyerTxid} but it did not confirm in time. It likely landed \u2014 re-verify before re-presenting; do NOT re-pay.`);
282
282
  }
283
283
  return {
284
284
  ok: true,
@@ -373,13 +373,13 @@ function rpcFailed(nonce) {
373
373
 
374
374
  function assertAlgorandWallet(wallet, network) {
375
375
  if (typeof wallet !== "object" || wallet === null) {
376
- throw new (0, _chunkJG6KRAW6cjs.WrongFamilyError)(
376
+ throw new (0, _chunkMWBT7MCEcjs.WrongFamilyError)(
377
377
  `chain ${network} is Algorand; wallet must be { key } (25-word mnemonic) or { account }.`
378
378
  );
379
379
  }
380
- _chunkJG6KRAW6cjs.assertNoLegacyWalletKey.call(void 0, wallet, "Algorand");
380
+ _chunkMWBT7MCEcjs.assertNoLegacyWalletKey.call(void 0, wallet, "Algorand");
381
381
  if (!("key" in wallet) && !("account" in wallet)) {
382
- throw new (0, _chunkJG6KRAW6cjs.WrongFamilyError)(
382
+ throw new (0, _chunkMWBT7MCEcjs.WrongFamilyError)(
383
383
  `chain ${network} is Algorand; wallet must be { key } (25-word mnemonic) or { account }.`
384
384
  );
385
385
  }
@@ -394,13 +394,13 @@ function resolveAlgorandWallet(config) {
394
394
  const { addr, sk } = _algosdk2.default.mnemonicToSecretKey(config.key);
395
395
  return { addr: addr.toString(), sk };
396
396
  } catch (cause) {
397
- throw new (0, _chunkJG6KRAW6cjs.WrongFamilyError)(
397
+ throw new (0, _chunkMWBT7MCEcjs.WrongFamilyError)(
398
398
  "Algorand wallet { key } is not a valid 25-word Algorand mnemonic.",
399
399
  { cause }
400
400
  );
401
401
  }
402
402
  }
403
- throw new (0, _chunkJG6KRAW6cjs.WrongFamilyError)("Algorand wallet needs { key } (25-word mnemonic) or { account }.");
403
+ throw new (0, _chunkMWBT7MCEcjs.WrongFamilyError)("Algorand wallet needs { key } (25-word mnemonic) or { account }.");
404
404
  }
405
405
 
406
406
  // src/drivers/algorand/index.ts
@@ -471,16 +471,16 @@ function makeAlgorandNetwork(preset, algodUrl) {
471
471
  const info = preset.tokens[token.toUpperCase()];
472
472
  if (!info) {
473
473
  const known = Object.keys(preset.tokens).join(", ") || "(none built in)";
474
- throw new (0, _chunkJG6KRAW6cjs.UnknownTokenError)(
474
+ throw new (0, _chunkMWBT7MCEcjs.UnknownTokenError)(
475
475
  `token "${token}" isn't built in for Algorand (known: ${known}). Pass { assetId, decimals } for a custom ASA, or use 'native'.`
476
476
  );
477
477
  }
478
478
  return { asset: algorandAssetId(info.assetId), decimals: info.decimals, symbol: info.symbol };
479
479
  }
480
- _chunkJG6KRAW6cjs.rejectForeignToken.call(void 0, token, "algorand", network);
480
+ _chunkMWBT7MCEcjs.rejectForeignToken.call(void 0, token, "algorand", network);
481
481
  const t = token;
482
482
  if (typeof t.assetId !== "number" || typeof t.decimals !== "number") {
483
- throw new (0, _chunkJG6KRAW6cjs.WrongFamilyError)(
483
+ throw new (0, _chunkMWBT7MCEcjs.WrongFamilyError)(
484
484
  `chain ${network} is Algorand; a custom token must be { assetId, decimals }.`
485
485
  );
486
486
  }
@@ -501,12 +501,12 @@ function makeAlgorandNetwork(preset, algodUrl) {
501
501
  },
502
502
  assertValidPayTo(payTo) {
503
503
  if (payTo.startsWith("0x")) {
504
- throw new (0, _chunkJG6KRAW6cjs.WrongFamilyError)(
504
+ throw new (0, _chunkMWBT7MCEcjs.WrongFamilyError)(
505
505
  `chain ${network} is Algorand, but payTo "${payTo}" looks like an EVM address.`
506
506
  );
507
507
  }
508
508
  if (!_algosdk2.default.isValidAddress(payTo)) {
509
- throw new (0, _chunkJG6KRAW6cjs.WrongFamilyError)(
509
+ throw new (0, _chunkMWBT7MCEcjs.WrongFamilyError)(
510
510
  `chain ${network} is Algorand, but payTo "${payTo}" is not a valid Algorand address.`
511
511
  );
512
512
  }
@@ -523,14 +523,14 @@ function makeAlgorandNetwork(preset, algodUrl) {
523
523
  const info = await _algosdk2.default.waitForConfirmation(algod, ref, 10);
524
524
  return { height: String(_nullishCoalesce(info.confirmedRound, () => ( 0))) };
525
525
  } catch (err) {
526
- throw new (0, _chunkJG6KRAW6cjs.ConfirmationTimeoutError)(`Algorand tx ${ref} did not confirm in time.`, {
526
+ throw new (0, _chunkMWBT7MCEcjs.ConfirmationTimeoutError)(`Algorand tx ${ref} did not confirm in time.`, {
527
527
  cause: err
528
528
  });
529
529
  }
530
530
  },
531
531
  async estimateCost(accept) {
532
532
  if (accept.scheme === "exact") {
533
- return _chunkJG6KRAW6cjs.nativeCost.call(void 0, {
533
+ return _chunkMWBT7MCEcjs.nativeCost.call(void 0, {
534
534
  symbol: ALGO_SYMBOL,
535
535
  decimals: ALGO_DECIMALS,
536
536
  fee: 0n,
@@ -538,7 +538,7 @@ function makeAlgorandNetwork(preset, algodUrl) {
538
538
  detail: "gasless \u2014 the fee payer (facilitator/relayer) pools the group fee; the buyer pays 0 ALGO"
539
539
  });
540
540
  }
541
- return _chunkJG6KRAW6cjs.nativeCost.call(void 0, {
541
+ return _chunkMWBT7MCEcjs.nativeCost.call(void 0, {
542
542
  symbol: ALGO_SYMBOL,
543
543
  decimals: ALGO_DECIMALS,
544
544
  fee: 1000n,
@@ -9,7 +9,7 @@
9
9
 
10
10
 
11
11
 
12
- var _chunkJG6KRAW6cjs = require('./chunk-JG6KRAW6.cjs');
12
+ var _chunkMWBT7MCEcjs = require('./chunk-MWBT7MCE.cjs');
13
13
 
14
14
  // src/drivers/aptos/index.ts
15
15
  var _tssdk = require('@aptos-labs/ts-sdk');
@@ -58,14 +58,14 @@ async function payAptos(params) {
58
58
  const res = await client.signSubmit({ signer, transaction });
59
59
  return res.hash;
60
60
  } catch (err) {
61
- if (err instanceof _chunkJG6KRAW6cjs.InsufficientFundsError) throw err;
61
+ if (err instanceof _chunkMWBT7MCEcjs.InsufficientFundsError) throw err;
62
62
  if (isAptosAffordability(err)) {
63
- throw new (0, _chunkJG6KRAW6cjs.InsufficientFundsError)(
63
+ throw new (0, _chunkMWBT7MCEcjs.InsufficientFundsError)(
64
64
  err instanceof Error ? err.message : "Insufficient APT/token balance for the payment.",
65
65
  { cause: err }
66
66
  );
67
67
  }
68
- throw _nullishCoalesce(_chunkJG6KRAW6cjs.toInsufficientFundsError.call(void 0, err), () => ( err));
68
+ throw _nullishCoalesce(_chunkMWBT7MCEcjs.toInsufficientFundsError.call(void 0, err), () => ( err));
69
69
  }
70
70
  }
71
71
  function isAptosAffordability(err) {
@@ -103,24 +103,24 @@ function parseAddr(addr) {
103
103
  async function payExactAptos(input) {
104
104
  const { client, sender, accept } = input;
105
105
  if (accept.asset === "native") {
106
- throw new (0, _chunkJG6KRAW6cjs.UnsupportedSchemeError)(
106
+ throw new (0, _chunkMWBT7MCEcjs.UnsupportedSchemeError)(
107
107
  "Aptos exact is Fungible-Asset only (a primary_fungible_store transfer); native APT is not exact-payable. Pay via onchain-proof."
108
108
  );
109
109
  }
110
110
  const feePayer = accept.extra.feePayer;
111
111
  if (!feePayer) {
112
- throw new (0, _chunkJG6KRAW6cjs.UnsupportedSchemeError)("Aptos exact rail must advertise extra.feePayer (the gas sponsor address).");
112
+ throw new (0, _chunkMWBT7MCEcjs.UnsupportedSchemeError)("Aptos exact rail must advertise extra.feePayer (the gas sponsor address).");
113
113
  }
114
114
  const feePayerAddr = parseAddr(feePayer);
115
- if (!feePayerAddr) throw new (0, _chunkJG6KRAW6cjs.UnsupportedSchemeError)(`Aptos exact: extra.feePayer "${feePayer}" is not a valid Aptos address.`);
115
+ if (!feePayerAddr) throw new (0, _chunkMWBT7MCEcjs.UnsupportedSchemeError)(`Aptos exact: extra.feePayer "${feePayer}" is not a valid Aptos address.`);
116
116
  const payToAddr = parseAddr(accept.payTo);
117
- if (!payToAddr) throw new (0, _chunkJG6KRAW6cjs.UnsupportedSchemeError)(`Aptos exact: payTo "${accept.payTo}" is not a valid Aptos address.`);
117
+ if (!payToAddr) throw new (0, _chunkMWBT7MCEcjs.UnsupportedSchemeError)(`Aptos exact: payTo "${accept.payTo}" is not a valid Aptos address.`);
118
118
  const metadataAddr = parseAddr(accept.asset);
119
- if (!metadataAddr) throw new (0, _chunkJG6KRAW6cjs.UnsupportedSchemeError)(`Aptos exact: asset "${accept.asset}" is not a valid FA metadata address.`);
119
+ if (!metadataAddr) throw new (0, _chunkMWBT7MCEcjs.UnsupportedSchemeError)(`Aptos exact: asset "${accept.asset}" is not a valid FA metadata address.`);
120
120
  const senderAddr = parseAddr(sender);
121
- if (!senderAddr) throw new (0, _chunkJG6KRAW6cjs.UnsupportedSchemeError)(`Aptos exact: payer "${sender}" is not a valid Aptos address.`);
121
+ if (!senderAddr) throw new (0, _chunkMWBT7MCEcjs.UnsupportedSchemeError)(`Aptos exact: payer "${sender}" is not a valid Aptos address.`);
122
122
  if (feePayerAddr.equals(senderAddr)) {
123
- throw new (0, _chunkJG6KRAW6cjs.UnsupportedSchemeError)(
123
+ throw new (0, _chunkMWBT7MCEcjs.UnsupportedSchemeError)(
124
124
  "Aptos exact: the fee payer must differ from the payer \u2014 the buyer must pay ZERO APT (the sponsor pays gas)."
125
125
  );
126
126
  }
@@ -158,16 +158,16 @@ function argBytes(arg) {
158
158
  async function verifyAndSettleExactAptos(input) {
159
159
  const { client, feePayerAddr, payload, accept } = input;
160
160
  const railFeePayer = accept.extra.feePayer;
161
- if (!railFeePayer) throw new (0, _chunkJG6KRAW6cjs.SettlementError)("Aptos exact: rail is missing extra.feePayer.");
161
+ if (!railFeePayer) throw new (0, _chunkMWBT7MCEcjs.SettlementError)("Aptos exact: rail is missing extra.feePayer.");
162
162
  if (railFeePayer !== feePayerAddr) {
163
- throw new (0, _chunkJG6KRAW6cjs.SettlementError)("Aptos exact: the gate relayer address does not match the rail extra.feePayer \u2014 misconfigured rail.");
163
+ throw new (0, _chunkMWBT7MCEcjs.SettlementError)("Aptos exact: the gate relayer address does not match the rail extra.feePayer \u2014 misconfigured rail.");
164
164
  }
165
- if (accept.asset === "native") throw new (0, _chunkJG6KRAW6cjs.SettlementError)("Aptos exact: native APT is not exact-payable (misconfigured rail).");
165
+ if (accept.asset === "native") throw new (0, _chunkMWBT7MCEcjs.SettlementError)("Aptos exact: native APT is not exact-payable (misconfigured rail).");
166
166
  const railFeePayerAddr = parseAddr(railFeePayer);
167
167
  const railPayTo = parseAddr(accept.payTo);
168
168
  const railMetadata = parseAddr(accept.asset);
169
169
  if (!railFeePayerAddr || !railPayTo || !railMetadata) {
170
- throw new (0, _chunkJG6KRAW6cjs.SettlementError)("Aptos exact: rail feePayer/payTo/asset is not a valid Aptos address (misconfigured rail).");
170
+ throw new (0, _chunkMWBT7MCEcjs.SettlementError)("Aptos exact: rail feePayer/payTo/asset is not a valid Aptos address (misconfigured rail).");
171
171
  }
172
172
  let tx;
173
173
  let senderAuth;
@@ -241,7 +241,7 @@ async function verifyAndSettleExactAptos(input) {
241
241
  try {
242
242
  feePayerAuth = client.signAsFeePayer({ transaction: tx });
243
243
  } catch (err) {
244
- throw new (0, _chunkJG6KRAW6cjs.SettlementError)(`Aptos exact settle: the gate could not sign as fee payer (${shorten(err instanceof Error ? err.message : String(err))}).`, { cause: err });
244
+ throw new (0, _chunkMWBT7MCEcjs.SettlementError)(`Aptos exact settle: the gate could not sign as fee payer (${shorten(err instanceof Error ? err.message : String(err))}).`, { cause: err });
245
245
  }
246
246
  if (senderAuth instanceof _tssdk.AccountAuthenticatorEd25519) {
247
247
  try {
@@ -264,7 +264,7 @@ async function verifyAndSettleExactAptos(input) {
264
264
  if (/signature|invalid.*auth|INVALID_SIGNATURE/i.test(m)) return fail("signature_invalid", `Settle rejected \u2014 bad signature: ${shorten(m)}.`);
265
265
  if (/SEQUENCE_NUMBER_TOO_OLD|already.*(committed|ledger)|duplicate/i.test(m)) return fail("tx_already_used", `This payment was already settled: ${shorten(m)}.`);
266
266
  if (/EXPIRED|expired|TOO_NEW/i.test(m)) return fail("payment_expired", `Settle rejected \u2014 expired/stale: ${shorten(m)}.`);
267
- throw new (0, _chunkJG6KRAW6cjs.SettlementError)(
267
+ throw new (0, _chunkMWBT7MCEcjs.SettlementError)(
268
268
  `Aptos exact settle: the transaction failed to submit (${shorten(m)}). The buyer's signed transaction is still valid \u2014 fund/fix the fee payer (${railFeePayer}) and the buyer can re-present it.`,
269
269
  { cause: err }
270
270
  );
@@ -273,10 +273,10 @@ async function verifyAndSettleExactAptos(input) {
273
273
  try {
274
274
  confirmed = await client.waitForConfirmation(hash);
275
275
  } catch (err) {
276
- throw new (0, _chunkJG6KRAW6cjs.SettlementError)(`Aptos exact settle: submitted ${hash} but confirmation read failed (${shorten(err instanceof Error ? err.message : String(err))}). It likely landed \u2014 re-verify before re-presenting; do NOT re-pay.`, { cause: err });
276
+ throw new (0, _chunkMWBT7MCEcjs.SettlementError)(`Aptos exact settle: submitted ${hash} but confirmation read failed (${shorten(err instanceof Error ? err.message : String(err))}). It likely landed \u2014 re-verify before re-presenting; do NOT re-pay.`, { cause: err });
277
277
  }
278
278
  if (confirmed === null) {
279
- throw new (0, _chunkJG6KRAW6cjs.SettlementError)(`Aptos exact settle: submitted ${hash} but it did not confirm in time. It likely landed \u2014 re-verify before re-presenting; do NOT re-pay.`);
279
+ throw new (0, _chunkMWBT7MCEcjs.SettlementError)(`Aptos exact settle: submitted ${hash} but it did not confirm in time. It likely landed \u2014 re-verify before re-presenting; do NOT re-pay.`);
280
280
  }
281
281
  if (!confirmed.success) {
282
282
  return fail("tx_reverted", `Settle tx ${hash} reverted on-chain (a post-simulate race).`);
@@ -371,13 +371,13 @@ function txNotFound(hash) {
371
371
 
372
372
  function assertAptosWallet(wallet, network) {
373
373
  if (typeof wallet !== "object" || wallet === null) {
374
- throw new (0, _chunkJG6KRAW6cjs.WrongFamilyError)(
374
+ throw new (0, _chunkMWBT7MCEcjs.WrongFamilyError)(
375
375
  `chain ${network} is Aptos; wallet must be { key } (ed25519-priv-0x\u2026) or { account }.`
376
376
  );
377
377
  }
378
- _chunkJG6KRAW6cjs.assertNoLegacyWalletKey.call(void 0, wallet, "Aptos");
378
+ _chunkMWBT7MCEcjs.assertNoLegacyWalletKey.call(void 0, wallet, "Aptos");
379
379
  if (!("key" in wallet) && !("account" in wallet)) {
380
- throw new (0, _chunkJG6KRAW6cjs.WrongFamilyError)(
380
+ throw new (0, _chunkMWBT7MCEcjs.WrongFamilyError)(
381
381
  `chain ${network} is Aptos; wallet must be { key } (ed25519-priv-0x\u2026) or { account }.`
382
382
  );
383
383
  }
@@ -389,13 +389,13 @@ function resolveAptosAccount(config) {
389
389
  try {
390
390
  return _tssdk.Account.fromPrivateKey({ privateKey: new (0, _tssdk.Ed25519PrivateKey)(config.key) });
391
391
  } catch (cause) {
392
- throw new (0, _chunkJG6KRAW6cjs.WrongFamilyError)(
392
+ throw new (0, _chunkMWBT7MCEcjs.WrongFamilyError)(
393
393
  "Aptos wallet { key } is not a valid ed25519 secret (ed25519-priv-0x\u2026 or 0x\u2026 hex).",
394
394
  { cause }
395
395
  );
396
396
  }
397
397
  }
398
- throw new (0, _chunkJG6KRAW6cjs.WrongFamilyError)("Aptos wallet needs { key } (ed25519-priv-0x\u2026) or { account }.");
398
+ throw new (0, _chunkMWBT7MCEcjs.WrongFamilyError)("Aptos wallet needs { key } (ed25519-priv-0x\u2026) or { account }.");
399
399
  }
400
400
 
401
401
  // src/drivers/aptos/index.ts
@@ -467,16 +467,16 @@ function makeAptosNetwork(preset, rpcUrl) {
467
467
  const info = preset.tokens[token.toUpperCase()];
468
468
  if (!info) {
469
469
  const known = Object.keys(preset.tokens).join(", ") || "(none built in)";
470
- throw new (0, _chunkJG6KRAW6cjs.UnknownTokenError)(
470
+ throw new (0, _chunkMWBT7MCEcjs.UnknownTokenError)(
471
471
  `token "${token}" isn't built in for Aptos (known: ${known}). Pass { metadata, decimals } for a custom Fungible Asset, or use 'native'.`
472
472
  );
473
473
  }
474
474
  return { asset: info.metadata, decimals: info.decimals, symbol: info.symbol };
475
475
  }
476
- _chunkJG6KRAW6cjs.rejectForeignToken.call(void 0, token, "aptos", network);
476
+ _chunkMWBT7MCEcjs.rejectForeignToken.call(void 0, token, "aptos", network);
477
477
  const t = token;
478
478
  if (!t.metadata || typeof t.decimals !== "number") {
479
- throw new (0, _chunkJG6KRAW6cjs.WrongFamilyError)(
479
+ throw new (0, _chunkMWBT7MCEcjs.WrongFamilyError)(
480
480
  `chain ${network} is Aptos; a custom token must be { metadata, decimals }.`
481
481
  );
482
482
  }
@@ -503,7 +503,7 @@ function makeAptosNetwork(preset, rpcUrl) {
503
503
  valid = false;
504
504
  }
505
505
  if (!valid || evmLike) {
506
- throw new (0, _chunkJG6KRAW6cjs.WrongFamilyError)(
506
+ throw new (0, _chunkMWBT7MCEcjs.WrongFamilyError)(
507
507
  `chain ${network} is Aptos, but payTo "${payTo}" is not a valid Aptos address (0x + 32 bytes).`
508
508
  );
509
509
  }
@@ -525,12 +525,12 @@ function makeAptosNetwork(preset, rpcUrl) {
525
525
  const tx = await aptos.waitForTransaction({ transactionHash: ref });
526
526
  return { height: String(_nullishCoalesce(tx.version, () => ( "0"))) };
527
527
  } catch (err) {
528
- throw new (0, _chunkJG6KRAW6cjs.ConfirmationTimeoutError)(`Aptos tx ${ref} did not finalize in time.`, { cause: err });
528
+ throw new (0, _chunkMWBT7MCEcjs.ConfirmationTimeoutError)(`Aptos tx ${ref} did not finalize in time.`, { cause: err });
529
529
  }
530
530
  },
531
531
  async estimateCost(accept) {
532
532
  if (accept.scheme === "exact") {
533
- return _chunkJG6KRAW6cjs.nativeCost.call(void 0, {
533
+ return _chunkMWBT7MCEcjs.nativeCost.call(void 0, {
534
534
  symbol: APT_SYMBOL,
535
535
  decimals: APT_DECIMALS,
536
536
  fee: 0n,
@@ -538,7 +538,7 @@ function makeAptosNetwork(preset, rpcUrl) {
538
538
  detail: "gasless \u2014 the fee payer (facilitator/relayer) sponsors gas; the buyer pays 0 APT"
539
539
  });
540
540
  }
541
- return _chunkJG6KRAW6cjs.nativeCost.call(void 0, {
541
+ return _chunkMWBT7MCEcjs.nativeCost.call(void 0, {
542
542
  symbol: APT_SYMBOL,
543
543
  decimals: APT_DECIMALS,
544
544
  fee: 100000n,
@@ -9,7 +9,7 @@ import {
9
9
  nativeCost,
10
10
  rejectForeignToken,
11
11
  toInsufficientFundsError
12
- } from "./chunk-7XK22JSQ.js";
12
+ } from "./chunk-SC2ZYDHD.js";
13
13
 
14
14
  // src/drivers/aptos/index.ts
15
15
  import { Aptos, AptosConfig, Network, AccountAddress as AccountAddress2 } from "@aptos-labs/ts-sdk";
@@ -133,7 +133,16 @@ function rejectForeignToken(token, family, network) {
133
133
  }
134
134
 
135
135
  // src/util/units.ts
136
+ var MAX_DECIMALS = 100;
137
+ function assertValidDecimals(decimals, fn) {
138
+ if (!Number.isSafeInteger(decimals) || decimals < 0 || decimals > MAX_DECIMALS) {
139
+ throw new Error(
140
+ `${fn}: decimals must be a non-negative integer \u2264 ${MAX_DECIMALS} (got ${decimals}).`
141
+ );
142
+ }
143
+ }
136
144
  function parseUnits(value, decimals) {
145
+ assertValidDecimals(decimals, "parseUnits");
137
146
  if (!/^\d+(\.\d+)?$/.test(value)) {
138
147
  throw new Error(`parseUnits: "${value}" is not a non-negative decimal amount.`);
139
148
  }
@@ -147,6 +156,7 @@ function parseUnits(value, decimals) {
147
156
  return BigInt(whole + fracPadded);
148
157
  }
149
158
  function floorUnits(value, decimals) {
159
+ assertValidDecimals(decimals, "floorUnits");
150
160
  if (!/^\d+(\.\d+)?$/.test(value)) {
151
161
  throw new Error(`floorUnits: "${value}" is not a non-negative decimal amount.`);
152
162
  }
@@ -155,6 +165,7 @@ function floorUnits(value, decimals) {
155
165
  return BigInt(whole + fracTrunc);
156
166
  }
157
167
  function formatUnits(value, decimals) {
168
+ assertValidDecimals(decimals, "formatUnits");
158
169
  const negative = value < 0n;
159
170
  const digits = (negative ? -value : value).toString().padStart(decimals + 1, "0");
160
171
  const whole = digits.slice(0, digits.length - decimals);
@@ -212,4 +223,5 @@ function assertNoLegacyWalletKey(wallet, family) {
212
223
 
213
224
 
214
225
 
215
- exports.PipRailError = PipRailError; exports.InsufficientFundsError = InsufficientFundsError; exports.RecipientNotReadyError = RecipientNotReadyError; exports.toInsufficientFundsError = toInsufficientFundsError; exports.WrongChainError = WrongChainError; exports.PaymentTimeoutError = PaymentTimeoutError; exports.MaxRetriesExceededError = MaxRetriesExceededError; exports.PaymentDeclinedError = PaymentDeclinedError; exports.ConfirmationTimeoutError = ConfirmationTimeoutError; exports.SettlementError = SettlementError; exports.InvalidEnvelopeError = InvalidEnvelopeError; exports.NoCompatibleAcceptError = NoCompatibleAcceptError; exports.UnsupportedSchemeError = UnsupportedSchemeError; exports.NonReplayableBodyError = NonReplayableBodyError; exports.WalletRequiredError = WalletRequiredError; exports.WrongFamilyError = WrongFamilyError; exports.UnknownTokenError = UnknownTokenError; exports.MissingDriverError = MissingDriverError; exports.UnsupportedNetworkError = UnsupportedNetworkError; exports.assertNoLegacyWalletKey = assertNoLegacyWalletKey; exports.rejectForeignToken = rejectForeignToken; exports.parseUnits = parseUnits; exports.floorUnits = floorUnits; exports.formatUnits = formatUnits; exports.nativeCost = nativeCost;
226
+
227
+ exports.PipRailError = PipRailError; exports.InsufficientFundsError = InsufficientFundsError; exports.RecipientNotReadyError = RecipientNotReadyError; exports.toInsufficientFundsError = toInsufficientFundsError; exports.WrongChainError = WrongChainError; exports.PaymentTimeoutError = PaymentTimeoutError; exports.MaxRetriesExceededError = MaxRetriesExceededError; exports.PaymentDeclinedError = PaymentDeclinedError; exports.ConfirmationTimeoutError = ConfirmationTimeoutError; exports.SettlementError = SettlementError; exports.InvalidEnvelopeError = InvalidEnvelopeError; exports.NoCompatibleAcceptError = NoCompatibleAcceptError; exports.UnsupportedSchemeError = UnsupportedSchemeError; exports.NonReplayableBodyError = NonReplayableBodyError; exports.WalletRequiredError = WalletRequiredError; exports.WrongFamilyError = WrongFamilyError; exports.UnknownTokenError = UnknownTokenError; exports.MissingDriverError = MissingDriverError; exports.UnsupportedNetworkError = UnsupportedNetworkError; exports.assertNoLegacyWalletKey = assertNoLegacyWalletKey; exports.rejectForeignToken = rejectForeignToken; exports.MAX_DECIMALS = MAX_DECIMALS; exports.parseUnits = parseUnits; exports.floorUnits = floorUnits; exports.formatUnits = formatUnits; exports.nativeCost = nativeCost;
@@ -0,0 +1,14 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/spendstore.ts
2
+ function memorySpendStore(seed = []) {
3
+ const records = [...seed];
4
+ return {
5
+ load: () => [...records],
6
+ append: (r) => {
7
+ records.push(r);
8
+ }
9
+ };
10
+ }
11
+
12
+
13
+
14
+ exports.memorySpendStore = memorySpendStore;