@piprail/sdk 1.9.0 → 1.10.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 (29) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/ERRORS.md +21 -8
  3. package/README.md +20 -0
  4. package/STANDARDS.md +5 -2
  5. package/dist/{algorand-IJJKE35X.cjs → algorand-MXUSKX46.cjs} +17 -17
  6. package/dist/{algorand-B67G4335.js → algorand-WGVF4KTU.js} +1 -1
  7. package/dist/{aptos-YQWTGFRZ.js → aptos-LPBLSEIQ.js} +1 -1
  8. package/dist/{aptos-X3G2UBYW.cjs → aptos-YT7SXWPF.cjs} +16 -16
  9. package/dist/{chunk-IQGT65WS.cjs → chunk-MDLZJGLY.cjs} +20 -16
  10. package/dist/{chunk-QDS6FBZP.js → chunk-SVMGHASK.js} +4 -0
  11. package/dist/index.cjs +811 -253
  12. package/dist/index.d.cts +400 -31
  13. package/dist/index.d.ts +400 -31
  14. package/dist/index.js +734 -176
  15. package/dist/{near-GGUHLXAF.cjs → near-7ZDNISUX.cjs} +19 -19
  16. package/dist/{near-7MBBCDUE.js → near-K6BDBABG.js} +1 -1
  17. package/dist/{solana-W24TCJV4.cjs → solana-PU7N2M64.cjs} +14 -14
  18. package/dist/{solana-7WJVZGDW.js → solana-S3UFI3FE.js} +1 -1
  19. package/dist/{stellar-HV6VGZX3.js → stellar-Q5PO23SC.js} +1 -1
  20. package/dist/{stellar-YMY3K2YB.cjs → stellar-VDQOFQEO.cjs} +21 -21
  21. package/dist/{sui-32KVESR5.cjs → sui-FKSMLKRF.cjs} +17 -17
  22. package/dist/{sui-2WFWVFJX.js → sui-WOXRKJXS.js} +1 -1
  23. package/dist/{ton-FIQGV2LC.cjs → ton-VK6KRJHP.cjs} +14 -14
  24. package/dist/{ton-DGZB7W4U.js → ton-WPTXGLVK.js} +1 -1
  25. package/dist/{tron-RLIL2FDI.js → tron-6GXBXTR4.js} +1 -1
  26. package/dist/{tron-ZSXAPZ2C.cjs → tron-WLOF5OUV.cjs} +24 -24
  27. package/dist/{xrpl-2PKP7HOI.cjs → xrpl-CMNI25BV.cjs} +21 -21
  28. package/dist/{xrpl-UEC2GYVV.js → xrpl-HEAPEXAM.js} +1 -1
  29. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -4,6 +4,47 @@ 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
+ ## [1.10.0] — 2026-06-09
8
+
9
+ ### Added — Universal Payments (the standard x402 `exact` rail)
10
+ - **Get paid by ANY standard x402 client.** A gate can now opt into advertising a ratified x402
11
+ `exact` rail (EIP-3009) **alongside** its backendless `onchain-proof` rail (dual-advertise) —
12
+ `requirePayment({ …, exact: { settle: 'self', relayer: { privateKey } } })`. A standard client
13
+ (`x402-fetch`, `@x402/fetch`, …) picks `exact`; a PipRail client picks `onchain-proof`. Opt-in;
14
+ omitting `exact` leaves the gate byte-identical. EVM + EIP-3009 only (USDC/EURC); USDT, native, and
15
+ non-EVM chains stay `onchain-proof` (a clear config error if you request `exact` on them).
16
+ - **Two backendless settlement modes.** `settle: 'self'` broadcasts `transferWithAuthorization` from
17
+ the merchant's own relayer key (payer spends **zero** gas; the merchant pays gas to receive — the
18
+ signature binds `to`, so no redirect risk). `settle: { facilitator }` delegates verify+settle to a
19
+ third-party x402 facilitator the merchant chooses (Coinbase CDP, x402.org, …) via the new pure
20
+ `settleViaFacilitator` — PipRail hosts nothing either way.
21
+ - **EIP-712 domain read from the token.** The exact rail reads `name()`/`version()` from the contract
22
+ (never assumed from the symbol — USDC's domain name is `"USD Coin"`, EURC's is `"EURC"`, bridged
23
+ USDC differs), so it's correct across all 18 built-in EVM USDC chains. Proven live: a real
24
+ `@x402/fetch` reference client settles against a PipRail gate on Base mainnet.
25
+ - New exports: `ExactRailOption`, `SettlementError` (`SETTLEMENT_FAILED`), `signature_invalid`
26
+ (`VerifyErrorCode`), `settleViaFacilitator` + `FacilitatorConfig`, `parseExactPaymentHeader`,
27
+ `readExactDomain`, `eip3009Abi`, the `X402ExactAcceptEntry`/`X402AnyAccept`/`ExactPaymentPayload`
28
+ types, and the v1 header constants `HEADER_SIGNATURE_V1`/`HEADER_RESPONSE_V1`.
29
+
30
+ ### Changed — x402 v2 conformance
31
+ - **A rejected proof is now a conformant 402.** The gate re-issues a full v2 `PaymentRequired`
32
+ re-challenge on rejection (carries `accepts[]` so a standard client can retry, the human reason in
33
+ `error`, and the machine code in `extensions.piprail`) instead of the old non-standard
34
+ `{ status: 'invalid' }` body. The built-in `requirePayment` adapter emits it automatically; the
35
+ client reads the structured reason. `toInvalidBody` is **deprecated** (kept for back-compat) — prefer
36
+ the gate's `result.challenge`.
37
+ - **Receive + respond on both header sets.** The gate accepts an inbound payment on `PAYMENT-SIGNATURE`
38
+ (v2) **or** `X-PAYMENT` (v1), and emits the settlement on both `PAYMENT-RESPONSE` and
39
+ `X-PAYMENT-RESPONSE`, so deprecated-but-common v1 clients interoperate on the `exact` rail.
40
+ - A fresh challenge now omits `error` (was `error: null`) and may carry `extensions`/`resource.mimeType`.
41
+
42
+ ### Fixed
43
+ - **UTF-8-safe base64 envelope codec.** The wire codec preferred `btoa`/`atob`, which are Latin1-only —
44
+ and modern Node defines them globally — so a challenge/receipt containing a non-ASCII byte (a chain
45
+ error `detail`, an `…` in a viem message, a token symbol) threw `InvalidCharacterError`. It now
46
+ prefers `Buffer` and bridges through `TextEncoder`/`TextDecoder` in the browser.
47
+
7
48
  ## [1.9.0] — 2026-06-08
8
49
 
9
50
  ### Added
@@ -508,6 +549,7 @@ straight into your wallet. The API is small and self-contained.
508
549
  to your wallet; PipRail never holds funds.
509
550
  - `viem ^2.21` is a peer dependency. Node 20+ or a modern browser.
510
551
 
552
+ [1.10.0]: https://www.npmjs.com/package/@piprail/sdk
511
553
  [1.9.0]: https://www.npmjs.com/package/@piprail/sdk
512
554
  [1.8.0]: https://www.npmjs.com/package/@piprail/sdk
513
555
  [1.7.0]: https://www.npmjs.com/package/@piprail/sdk
package/ERRORS.md CHANGED
@@ -25,9 +25,13 @@ Every failure surfaces through exactly one of two chain-agnostic channels:
25
25
  (a stable `SCREAMING_SNAKE` string). They never leak a raw `viem`/`@solana`/`@ton`/
26
26
  `@stellar` error for a condition the SDK recognises.
27
27
  - **Returned** `VerifyResult` is how a driver's `verify()` reports *why a proof was rejected*
28
- without throwing. The gate turns `{ ok: false, error, detail }` into the canonical 402
29
- body `{ x402Version: 2, status: 'invalid', error, detail }` (built once by
30
- [`toInvalidBody`](src/server.ts)); the client relays it to the agent.
28
+ without throwing. The gate turns `{ ok: false, error, detail }` into a **conformant v2
29
+ `PaymentRequired` re-challenge** a full 402 body with `accepts[]` (so a standard x402 client
30
+ can retry), the human reason in `error`, and the machine code in `extensions.piprail.{code,detail}`.
31
+ The built-in `requirePayment` adapter emits it + the `PAYMENT-REQUIRED` header automatically; the
32
+ client reads the structured reason and relays it to the agent. (The legacy
33
+ [`toInvalidBody`](src/server.ts) `{ status: 'invalid', … }` helper is **deprecated** — it has no
34
+ `accepts[]`, so a standard client can't retry; prefer the gate's `result.challenge`.)
31
35
 
32
36
  Rule of thumb: **config/flow/wallet/registry/affordability → throw; proof-verification
33
37
  outcome → return.** Replay (`tx_already_used`) is the one verify-style code emitted by the
@@ -56,6 +60,7 @@ Base class [`PipRailError`](src/errors.ts) (abstract; `.name` = the subclass nam
56
60
  | `NON_REPLAYABLE_BODY` | `NonReplayableBodyError` | `init.body` isn't replayable (e.g. a one-shot stream) | client |
57
61
  | `MISSING_DRIVER` | `MissingDriverError` | a family's **optional peer deps aren't installed** (the lazy `import()` failed) — message names the exact `npm install` and sets `{ cause }` | registry loaders |
58
62
  | `UNSUPPORTED_NETWORK` | `UnsupportedNetworkError` | no driver for the family, or the driver's `resolve()` returned `null` (unrecognised `chain`) | registry |
63
+ | `SETTLEMENT_FAILED` | `SettlementError` | the standard `exact` rail: a payment was VALID (sig recovered, simulated) but **settlement failed server-side** — the merchant's relayer couldn't broadcast, or a Mode-B facilitator returned a transport/auth error. NOT the payer's fault (their authorization stays valid + unused), so the adapter returns **5xx**, never 402 | gate (`exact` rail) |
59
64
 
60
65
  `MISSING_DRIVER` vs `UNSUPPORTED_NETWORK` is a deliberate split: *deps not installed* vs
61
66
  *chain not supported*. Don't reuse one for the other.
@@ -77,8 +82,9 @@ a code, and you must use the same code other drivers use for the same condition.
77
82
  | `wrong_recipient` | paid, but not to `payTo` | definitive | EVM / Solana native path |
78
83
  | `amount_too_low` | paid to `payTo`, but `< required` | definitive | all |
79
84
  | `transfer_not_found` | no matching transfer (asset / amount / nonce) to `payTo` | definitive | all |
80
- | `payment_expired` | older than `maxTimeoutSeconds` (replay window) | definitive | all |
81
- | `tx_already_used` | this proof was already redeemed (replay) | definitive | the **gate** (not drivers) |
85
+ | `payment_expired` | older than `maxTimeoutSeconds` (replay window); on `exact`, an expired/not-yet-valid EIP-3009 authorization | definitive | all |
86
+ | `tx_already_used` | this proof was already redeemed (replay); on `exact`, an on-chain-consumed authorization nonce | definitive | the **gate** (+ EVM `exact` via `authorizationState`) |
87
+ | `signature_invalid` | `exact` rail: the EIP-712 authorization signature didn't recover to the payer | definitive | EVM `exact` |
82
88
 
83
89
  **Family-specificity is structural, not drift.** Account-watch chains (TON, Stellar) scan the
84
90
  merchant account and can't tell "wrong recipient" from "no payment", so both collapse to
@@ -95,9 +101,14 @@ the code. A consumer building a custom client may branch on it.
95
101
 
96
102
  ## 4. What the agent receives
97
103
 
98
- - **Rejected proof →** a `402` with body `{ x402Version: 2, status: 'invalid', error, detail }`.
99
- Always build it with [`toInvalidBody(result)`](src/server.ts) so Express, Hono, Fastify,
100
- Workers, etc. emit the *identical* envelope.
104
+ - **Rejected proof →** a conformant `402` **re-challenge**: a full v2 `PaymentRequired` body with
105
+ `accepts[]` (so a standard x402 client can retry), the reason in `error`, and the machine code in
106
+ `extensions.piprail.{code,detail}`, plus the `PAYMENT-REQUIRED` header. The built-in
107
+ `requirePayment` adapter emits `result.challenge` automatically; other adapters should do the same
108
+ (NOT the deprecated bare [`toInvalidBody`](src/server.ts), which omits `accepts[]`).
109
+ - **`exact`-rail settlement failed server-side →** a `5xx` (a thrown `SettlementError`), never a 402:
110
+ the payer's EIP-3009 authorization is still valid and its nonce unused, so re-presenting it once the
111
+ merchant fixes their relayer/facilitator settles — re-paying would be wrong.
101
112
  - **Client gave up →** `MaxRetriesExceededError` whose message embeds the last server
102
113
  `error — detail` (e.g. `… Last server rejection: amount_too_low — Paid 40000, required
103
114
  500000.`), and a `payment-failed` event carrying the same reason.
@@ -148,6 +159,8 @@ Every `PaymentDriver` / `ResolvedNetwork` method has a fixed error behaviour:
148
159
  | `bindWallet(wallet)` | a foreign / unusable wallet shape → `WrongFamilyError`. |
149
160
  | `send(wallet, accept)` | wrap the broadcast; map **sender** affordability → `InsufficientFundsError` (§6) and **recipient** setup → `RecipientNotReadyError` (§6.1); **rethrow everything else unchanged** (never swallow). Every mapped throw carries `{ cause }` = the raw chain error. |
150
161
  | `verify(ref, accept)` | **return** a `VerifyResult` with a canonical `VerifyErrorCode`. **Guard every RPC read** so a transient failure returns `tx_not_found` — `verify()` must not throw for an RPC hiccup. Re-derive the watched account from the trusted `accept`, never the client ref. |
162
+ | `exactDomain?(asset)` *(optional, EVM)* | **never throw for a non-EIP-3009 token** — return `null` (the gate raises a clear config error). May throw only on a hard RPC failure at gate setup. |
163
+ | `settleExactSelf?(input)` *(optional, EVM)* | **return** a `VerifyResult` for a CLIENT-fixable fault (`signature_invalid`/`wrong_recipient`/`amount_too_low`/`payment_expired`/`tx_already_used`/`tx_reverted` → 402); **throw `SettlementError`** when a valid+simulated payment fails to BROADCAST (relayer/RPC → 5xx). Re-derive every checked field from the trusted `accept`, never the client echo. |
151
164
  | `confirm(ref, n)` | broadcast-but-not-confirmed / timeout → `ConfirmationTimeoutError`. |
152
165
  | `estimateCost(accept, opts?)` | **never throw** — guard the RPC read and fall back to a `'heuristic'` constant; always return a valid `CostEstimate`. |
153
166
  | `balanceOf(wallet, asset)` | **never throw** — RPC-read-only. A field whose read was unavailable (transient/rate-limit) returns `null`, NOT `0` (a false 0 reads as "broke"). For `asset==='native'`, `token === native`. |
package/README.md CHANGED
@@ -40,6 +40,25 @@ const data = await res.json()
40
40
 
41
41
  On a `402`, the client reads the challenge, sends the payment on-chain, waits for confirmation, and retries with proof — all inside `client.fetch`. The same app can **take** payments with `requirePayment` and **make** them with `PipRailClient`. Built for autonomous agents: install, add a wallet, monetize or pay — nothing else to wire up.
42
42
 
43
+ ## Universal payments — get paid by *any* x402 client
44
+
45
+ PipRail's envelope is x402 **v2**-conformant, and its default `onchain-proof` scheme is backendless (the payer broadcasts, you verify locally — zero merchant key, zero merchant gas). To **also** be payable by a standard x402 client (Coinbase's `x402-fetch`, `@x402/fetch`, anything speaking the ratified `exact`/EIP-3009 scheme), opt into a standard `exact` rail — advertised **alongside** `onchain-proof` in the same 402:
46
+
47
+ ```ts
48
+ requirePayment({
49
+ chain: 'base', token: 'USDC', amount: '0.05', payTo: '0xYourWallet…',
50
+ exact: { settle: 'self', relayer: { privateKey: process.env.RELAYER_KEY } },
51
+ })
52
+ ```
53
+
54
+ Now the gate offers two rails: a standard x402 client picks `exact`; a PipRail client picks `onchain-proof`. The `exact` rail is **self-settled** — your own `relayer` key broadcasts the client's signed EIP-3009 authorization, so the **payer spends no gas** (you do, to receive). The EIP-712 token domain is read from the contract, so it's correct on every chain (USDC's domain name is `"USD Coin"`, not the symbol). Prefer not to run a relayer key? Delegate settlement to a third-party facilitator you choose — PipRail still hosts nothing:
55
+
56
+ ```ts
57
+ exact: { settle: { facilitator: 'https://x402.org/facilitator' } }
58
+ ```
59
+
60
+ EVM + EIP-3009 tokens only (USDC, EURC — not USDT, not native; those stay `onchain-proof`). Omit `exact` and the gate is byte-identical to today. Proven end-to-end: a real `@x402/fetch` reference client settles against a PipRail gate on Base mainnet.
61
+
43
62
  ## Built for agents — spend safely
44
63
 
45
64
  A funded key loose on the internet needs guardrails. Opt in to a `policy` and the client refuses anything outside it **before any on-chain send** — plus learn a price without paying it, approve each payment, and read back exactly what you spent. All opt-in, all local, no backend; omit it and the client behaves exactly as before.
@@ -659,6 +678,7 @@ The full standard every module follows is **[ERRORS.md](./ERRORS.md)**.
659
678
  | `onPaid` | — | `(receipt) => void` on a verified payment (see [Receipts](#receipts--record-every-payment)) |
660
679
  | `isUsed` / `markUsed` | in-memory | Replay store hooks — share across instances (e.g. Redis `SET NX`) |
661
680
  | `generateNonce` | `crypto.randomUUID()` | Custom per-challenge nonce generator |
681
+ | `exact` | — | Opt in to **also** advertise a standard x402 `exact` rail (EIP-3009) so any standard client can pay: `{ settle: 'self', relayer: { privateKey } }` (your relayer broadcasts) or `{ settle: { facilitator } }` (delegate to a chosen facilitator). EVM + USDC/EURC only — see [Universal payments](#universal-payments--get-paid-by-any-x402-client) |
662
682
 
663
683
  Provide **either** `chain` + `token` + `amount` (single) **or** a non-empty `accept` array (multi) — not both.
664
684
 
package/STANDARDS.md CHANGED
@@ -15,8 +15,11 @@ zero-config path still read in one line? If a feature can't be opt-in, reconside
15
15
 
16
16
  - **Opt-in, defaults unchanged.** New capability is a new optional field/method. Omitting it
17
17
  leaves behaviour byte-identical. (`policy`, `onBeforePay`, `accept[]`, `quote()` all obey this.)
18
- - **No backend, no database, no auth, no dashboard, no fee, no hosted facilitator.** Ever. If a
19
- feature needs one of those, it's the wrong feature for this SDK.
18
+ - **No backend, no database, no auth, no dashboard, no fee, no PipRail-hosted facilitator.** Ever. If
19
+ a feature needs one of those, it's the wrong feature for this SDK. (The opt-in standard `exact` rail
20
+ is consistent with this: settlement is either **merchant-self-hosted** — the merchant's own relayer
21
+ key broadcasts in-process, which x402 v2 §7 explicitly blesses — or **delegated to a third-party
22
+ facilitator the merchant chooses**. PipRail still hosts nothing.)
20
23
  - **One obvious way.** Prefer one clear API over flags. `token` is required so a gate is never
21
24
  ambiguous; `chain` is one word. Don't add a second way to do the same thing.
22
25
 
@@ -7,7 +7,7 @@
7
7
 
8
8
 
9
9
 
10
- var _chunkIQGT65WScjs = require('./chunk-IQGT65WS.cjs');
10
+ var _chunkMDLZJGLYcjs = require('./chunk-MDLZJGLY.cjs');
11
11
 
12
12
  // src/drivers/algorand/index.ts
13
13
  var _algosdk = require('algosdk'); var _algosdk2 = _interopRequireDefault(_algosdk);
@@ -55,13 +55,13 @@ async function payAlgorand(params) {
55
55
  } catch (err) {
56
56
  const mapped = mapAlgorandError(err, accept.payTo);
57
57
  if (mapped) throw mapped;
58
- throw _nullishCoalesce(_chunkIQGT65WScjs.toInsufficientFundsError.call(void 0, err), () => ( err));
58
+ throw _nullishCoalesce(_chunkMDLZJGLYcjs.toInsufficientFundsError.call(void 0, err), () => ( err));
59
59
  }
60
60
  }
61
61
  function mapAlgorandError(err, payTo) {
62
62
  const m = err instanceof Error ? err.message : String(err);
63
63
  if (/must optin/i.test(m) || /missing from/i.test(m) && m.includes(payTo)) {
64
- return new (0, _chunkIQGT65WScjs.RecipientNotReadyError)(
64
+ return new (0, _chunkMDLZJGLYcjs.RecipientNotReadyError)(
65
65
  `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)})`,
66
66
  { cause: err }
67
67
  );
@@ -69,7 +69,7 @@ function mapAlgorandError(err, payTo) {
69
69
  if (/overspend|below min|min(imum)? balance|tried to spend|balance \d+ below|asset \d+ missing from|insufficient|underflow/i.test(
70
70
  m
71
71
  )) {
72
- return new (0, _chunkIQGT65WScjs.InsufficientFundsError)(
72
+ return new (0, _chunkMDLZJGLYcjs.InsufficientFundsError)(
73
73
  `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)})`,
74
74
  { cause: err }
75
75
  );
@@ -157,22 +157,22 @@ function rpcFailed(nonce) {
157
157
 
158
158
  function assertAlgorandWallet(wallet, network) {
159
159
  if (typeof wallet !== "object" || wallet === null) {
160
- throw new (0, _chunkIQGT65WScjs.WrongFamilyError)(
160
+ throw new (0, _chunkMDLZJGLYcjs.WrongFamilyError)(
161
161
  `chain ${network} is Algorand; wallet must be { mnemonic } (25 words) or { account }.`
162
162
  );
163
163
  }
164
164
  if ("privateKey" in wallet || "walletClient" in wallet) {
165
- throw new (0, _chunkIQGT65WScjs.WrongFamilyError)(
165
+ throw new (0, _chunkMDLZJGLYcjs.WrongFamilyError)(
166
166
  `chain ${network} is Algorand; an EVM/Aptos wallet can't be used \u2014 pass { mnemonic } (25 words) or { account }.`
167
167
  );
168
168
  }
169
169
  if ("secretKey" in wallet || "signer" in wallet || "secret" in wallet || "keypair" in wallet || "keyPair" in wallet || "seed" in wallet || "accountId" in wallet) {
170
- throw new (0, _chunkIQGT65WScjs.WrongFamilyError)(
170
+ throw new (0, _chunkMDLZJGLYcjs.WrongFamilyError)(
171
171
  `chain ${network} is Algorand; that looks like another family's wallet \u2014 pass { mnemonic } (25 words) or { account }.`
172
172
  );
173
173
  }
174
174
  if (!("mnemonic" in wallet) && !("account" in wallet)) {
175
- throw new (0, _chunkIQGT65WScjs.WrongFamilyError)(
175
+ throw new (0, _chunkMDLZJGLYcjs.WrongFamilyError)(
176
176
  `chain ${network} is Algorand; wallet must be { mnemonic } (25 words) or { account }.`
177
177
  );
178
178
  }
@@ -187,13 +187,13 @@ function resolveAlgorandWallet(config) {
187
187
  const { addr, sk } = _algosdk2.default.mnemonicToSecretKey(config.mnemonic);
188
188
  return { addr: addr.toString(), sk };
189
189
  } catch (cause) {
190
- throw new (0, _chunkIQGT65WScjs.WrongFamilyError)(
190
+ throw new (0, _chunkMDLZJGLYcjs.WrongFamilyError)(
191
191
  "Algorand wallet { mnemonic } is not a valid 25-word Algorand mnemonic.",
192
192
  { cause }
193
193
  );
194
194
  }
195
195
  }
196
- throw new (0, _chunkIQGT65WScjs.WrongFamilyError)("Algorand wallet needs { mnemonic } (25 words) or { account }.");
196
+ throw new (0, _chunkMDLZJGLYcjs.WrongFamilyError)("Algorand wallet needs { mnemonic } (25 words) or { account }.");
197
197
  }
198
198
 
199
199
  // src/drivers/algorand/index.ts
@@ -248,16 +248,16 @@ function makeAlgorandNetwork(preset, algodUrl) {
248
248
  const info = preset.tokens[token.toUpperCase()];
249
249
  if (!info) {
250
250
  const known = Object.keys(preset.tokens).join(", ") || "(none built in)";
251
- throw new (0, _chunkIQGT65WScjs.UnknownTokenError)(
251
+ throw new (0, _chunkMDLZJGLYcjs.UnknownTokenError)(
252
252
  `token "${token}" isn't built in for Algorand (known: ${known}). Pass { assetId, decimals } for a custom ASA, or use 'native'.`
253
253
  );
254
254
  }
255
255
  return { asset: algorandAssetId(info.assetId), decimals: info.decimals, symbol: info.symbol };
256
256
  }
257
- _chunkIQGT65WScjs.rejectForeignToken.call(void 0, token, "algorand", network);
257
+ _chunkMDLZJGLYcjs.rejectForeignToken.call(void 0, token, "algorand", network);
258
258
  const t = token;
259
259
  if (typeof t.assetId !== "number" || typeof t.decimals !== "number") {
260
- throw new (0, _chunkIQGT65WScjs.WrongFamilyError)(
260
+ throw new (0, _chunkMDLZJGLYcjs.WrongFamilyError)(
261
261
  `chain ${network} is Algorand; a custom token must be { assetId, decimals }.`
262
262
  );
263
263
  }
@@ -278,12 +278,12 @@ function makeAlgorandNetwork(preset, algodUrl) {
278
278
  },
279
279
  assertValidPayTo(payTo) {
280
280
  if (payTo.startsWith("0x")) {
281
- throw new (0, _chunkIQGT65WScjs.WrongFamilyError)(
281
+ throw new (0, _chunkMDLZJGLYcjs.WrongFamilyError)(
282
282
  `chain ${network} is Algorand, but payTo "${payTo}" looks like an EVM address.`
283
283
  );
284
284
  }
285
285
  if (!_algosdk2.default.isValidAddress(payTo)) {
286
- throw new (0, _chunkIQGT65WScjs.WrongFamilyError)(
286
+ throw new (0, _chunkMDLZJGLYcjs.WrongFamilyError)(
287
287
  `chain ${network} is Algorand, but payTo "${payTo}" is not a valid Algorand address.`
288
288
  );
289
289
  }
@@ -300,13 +300,13 @@ function makeAlgorandNetwork(preset, algodUrl) {
300
300
  const info = await _algosdk2.default.waitForConfirmation(algod, ref, 10);
301
301
  return { height: String(_nullishCoalesce(info.confirmedRound, () => ( 0))) };
302
302
  } catch (err) {
303
- throw new (0, _chunkIQGT65WScjs.ConfirmationTimeoutError)(`Algorand tx ${ref} did not confirm in time.`, {
303
+ throw new (0, _chunkMDLZJGLYcjs.ConfirmationTimeoutError)(`Algorand tx ${ref} did not confirm in time.`, {
304
304
  cause: err
305
305
  });
306
306
  }
307
307
  },
308
308
  async estimateCost() {
309
- return _chunkIQGT65WScjs.nativeCost.call(void 0, {
309
+ return _chunkMDLZJGLYcjs.nativeCost.call(void 0, {
310
310
  symbol: ALGO_SYMBOL,
311
311
  decimals: ALGO_DECIMALS,
312
312
  fee: 1000n,
@@ -7,7 +7,7 @@ import {
7
7
  nativeCost,
8
8
  rejectForeignToken,
9
9
  toInsufficientFundsError
10
- } from "./chunk-QDS6FBZP.js";
10
+ } from "./chunk-SVMGHASK.js";
11
11
 
12
12
  // src/drivers/algorand/index.ts
13
13
  import algosdk2 from "algosdk";
@@ -6,7 +6,7 @@ import {
6
6
  nativeCost,
7
7
  rejectForeignToken,
8
8
  toInsufficientFundsError
9
- } from "./chunk-QDS6FBZP.js";
9
+ } from "./chunk-SVMGHASK.js";
10
10
 
11
11
  // src/drivers/aptos/index.ts
12
12
  import { Aptos, AptosConfig, Network, AccountAddress } from "@aptos-labs/ts-sdk";
@@ -6,7 +6,7 @@
6
6
 
7
7
 
8
8
 
9
- var _chunkIQGT65WScjs = require('./chunk-IQGT65WS.cjs');
9
+ var _chunkMDLZJGLYcjs = require('./chunk-MDLZJGLY.cjs');
10
10
 
11
11
  // src/drivers/aptos/index.ts
12
12
  var _tssdk = require('@aptos-labs/ts-sdk');
@@ -55,14 +55,14 @@ async function payAptos(params) {
55
55
  const res = await client.signSubmit({ signer, transaction });
56
56
  return res.hash;
57
57
  } catch (err) {
58
- if (err instanceof _chunkIQGT65WScjs.InsufficientFundsError) throw err;
58
+ if (err instanceof _chunkMDLZJGLYcjs.InsufficientFundsError) throw err;
59
59
  if (isAptosAffordability(err)) {
60
- throw new (0, _chunkIQGT65WScjs.InsufficientFundsError)(
60
+ throw new (0, _chunkMDLZJGLYcjs.InsufficientFundsError)(
61
61
  err instanceof Error ? err.message : "Insufficient APT/token balance for the payment.",
62
62
  { cause: err }
63
63
  );
64
64
  }
65
- throw _nullishCoalesce(_chunkIQGT65WScjs.toInsufficientFundsError.call(void 0, err), () => ( err));
65
+ throw _nullishCoalesce(_chunkMDLZJGLYcjs.toInsufficientFundsError.call(void 0, err), () => ( err));
66
66
  }
67
67
  }
68
68
  function isAptosAffordability(err) {
@@ -146,22 +146,22 @@ function txNotFound(hash) {
146
146
 
147
147
  function assertAptosWallet(wallet, network) {
148
148
  if (typeof wallet !== "object" || wallet === null) {
149
- throw new (0, _chunkIQGT65WScjs.WrongFamilyError)(
149
+ throw new (0, _chunkMDLZJGLYcjs.WrongFamilyError)(
150
150
  `chain ${network} is Aptos; wallet must be { privateKey } (ed25519-priv-0x\u2026) or { account }.`
151
151
  );
152
152
  }
153
153
  if ("walletClient" in wallet) {
154
- throw new (0, _chunkIQGT65WScjs.WrongFamilyError)(
154
+ throw new (0, _chunkMDLZJGLYcjs.WrongFamilyError)(
155
155
  `chain ${network} is Aptos; a viem { walletClient } can't be used \u2014 pass { privateKey } (ed25519-priv-0x\u2026) or { account }.`
156
156
  );
157
157
  }
158
158
  if ("secretKey" in wallet || "signer" in wallet || "mnemonic" in wallet || "keypair" in wallet || "keyPair" in wallet || "secret" in wallet || "seed" in wallet || "accountId" in wallet) {
159
- throw new (0, _chunkIQGT65WScjs.WrongFamilyError)(
159
+ throw new (0, _chunkMDLZJGLYcjs.WrongFamilyError)(
160
160
  `chain ${network} is Aptos; that looks like another family's wallet \u2014 pass { privateKey } (ed25519-priv-0x\u2026) or { account }.`
161
161
  );
162
162
  }
163
163
  if (!("privateKey" in wallet) && !("account" in wallet)) {
164
- throw new (0, _chunkIQGT65WScjs.WrongFamilyError)(
164
+ throw new (0, _chunkMDLZJGLYcjs.WrongFamilyError)(
165
165
  `chain ${network} is Aptos; wallet must be { privateKey } (ed25519-priv-0x\u2026) or { account }.`
166
166
  );
167
167
  }
@@ -173,13 +173,13 @@ function resolveAptosAccount(config) {
173
173
  try {
174
174
  return _tssdk.Account.fromPrivateKey({ privateKey: new (0, _tssdk.Ed25519PrivateKey)(config.privateKey) });
175
175
  } catch (cause) {
176
- throw new (0, _chunkIQGT65WScjs.WrongFamilyError)(
176
+ throw new (0, _chunkMDLZJGLYcjs.WrongFamilyError)(
177
177
  "Aptos wallet { privateKey } is not a valid ed25519 secret (ed25519-priv-0x\u2026 or 0x\u2026 hex).",
178
178
  { cause }
179
179
  );
180
180
  }
181
181
  }
182
- throw new (0, _chunkIQGT65WScjs.WrongFamilyError)("Aptos wallet needs { privateKey } (ed25519-priv-0x\u2026) or { account }.");
182
+ throw new (0, _chunkMDLZJGLYcjs.WrongFamilyError)("Aptos wallet needs { privateKey } (ed25519-priv-0x\u2026) or { account }.");
183
183
  }
184
184
 
185
185
  // src/drivers/aptos/index.ts
@@ -251,16 +251,16 @@ function makeAptosNetwork(preset, rpcUrl) {
251
251
  const info = preset.tokens[token.toUpperCase()];
252
252
  if (!info) {
253
253
  const known = Object.keys(preset.tokens).join(", ") || "(none built in)";
254
- throw new (0, _chunkIQGT65WScjs.UnknownTokenError)(
254
+ throw new (0, _chunkMDLZJGLYcjs.UnknownTokenError)(
255
255
  `token "${token}" isn't built in for Aptos (known: ${known}). Pass { metadata, decimals } for a custom Fungible Asset, or use 'native'.`
256
256
  );
257
257
  }
258
258
  return { asset: info.metadata, decimals: info.decimals, symbol: info.symbol };
259
259
  }
260
- _chunkIQGT65WScjs.rejectForeignToken.call(void 0, token, "aptos", network);
260
+ _chunkMDLZJGLYcjs.rejectForeignToken.call(void 0, token, "aptos", network);
261
261
  const t = token;
262
262
  if (!t.metadata || typeof t.decimals !== "number") {
263
- throw new (0, _chunkIQGT65WScjs.WrongFamilyError)(
263
+ throw new (0, _chunkMDLZJGLYcjs.WrongFamilyError)(
264
264
  `chain ${network} is Aptos; a custom token must be { metadata, decimals }.`
265
265
  );
266
266
  }
@@ -287,7 +287,7 @@ function makeAptosNetwork(preset, rpcUrl) {
287
287
  valid = false;
288
288
  }
289
289
  if (!valid || evmLike) {
290
- throw new (0, _chunkIQGT65WScjs.WrongFamilyError)(
290
+ throw new (0, _chunkMDLZJGLYcjs.WrongFamilyError)(
291
291
  `chain ${network} is Aptos, but payTo "${payTo}" is not a valid Aptos address (0x + 32 bytes).`
292
292
  );
293
293
  }
@@ -309,11 +309,11 @@ function makeAptosNetwork(preset, rpcUrl) {
309
309
  const tx = await aptos.waitForTransaction({ transactionHash: ref });
310
310
  return { height: String(_nullishCoalesce(tx.version, () => ( "0"))) };
311
311
  } catch (err) {
312
- throw new (0, _chunkIQGT65WScjs.ConfirmationTimeoutError)(`Aptos tx ${ref} did not finalize in time.`, { cause: err });
312
+ throw new (0, _chunkMDLZJGLYcjs.ConfirmationTimeoutError)(`Aptos tx ${ref} did not finalize in time.`, { cause: err });
313
313
  }
314
314
  },
315
315
  async estimateCost() {
316
- return _chunkIQGT65WScjs.nativeCost.call(void 0, {
316
+ return _chunkMDLZJGLYcjs.nativeCost.call(void 0, {
317
317
  symbol: APT_SYMBOL,
318
318
  decimals: APT_DECIMALS,
319
319
  fee: 100000n,
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3; var _class4; var _class5; var _class6; var _class7; var _class8; var _class9; var _class10; var _class11; var _class12; var _class13; var _class14;// src/errors.ts
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3; var _class4; var _class5; var _class6; var _class7; var _class8; var _class9; var _class10; var _class11; var _class12; var _class13; var _class14; var _class15;// src/errors.ts
2
2
  var PipRailError = class extends Error {
3
3
  constructor(message, options) {
4
4
  super(message, options);
@@ -50,27 +50,30 @@ var PaymentDeclinedError = (_class6 = class extends PipRailError {constructor(..
50
50
  var ConfirmationTimeoutError = (_class7 = class extends PipRailError {constructor(...args5) { super(...args5); _class7.prototype.__init7.call(this); }
51
51
  __init7() {this.code = "CONFIRMATION_TIMEOUT"}
52
52
  }, _class7);
53
- var InvalidEnvelopeError = (_class8 = class extends PipRailError {constructor(...args6) { super(...args6); _class8.prototype.__init8.call(this); }
54
- __init8() {this.code = "INVALID_ENVELOPE"}
53
+ var SettlementError = (_class8 = class extends PipRailError {constructor(...args6) { super(...args6); _class8.prototype.__init8.call(this); }
54
+ __init8() {this.code = "SETTLEMENT_FAILED"}
55
55
  }, _class8);
56
- var NoCompatibleAcceptError = (_class9 = class extends PipRailError {constructor(...args7) { super(...args7); _class9.prototype.__init9.call(this); }
57
- __init9() {this.code = "NO_COMPATIBLE_ACCEPT"}
56
+ var InvalidEnvelopeError = (_class9 = class extends PipRailError {constructor(...args7) { super(...args7); _class9.prototype.__init9.call(this); }
57
+ __init9() {this.code = "INVALID_ENVELOPE"}
58
58
  }, _class9);
59
- var NonReplayableBodyError = (_class10 = class extends PipRailError {constructor(...args8) { super(...args8); _class10.prototype.__init10.call(this); }
60
- __init10() {this.code = "NON_REPLAYABLE_BODY"}
59
+ var NoCompatibleAcceptError = (_class10 = class extends PipRailError {constructor(...args8) { super(...args8); _class10.prototype.__init10.call(this); }
60
+ __init10() {this.code = "NO_COMPATIBLE_ACCEPT"}
61
61
  }, _class10);
62
- var WrongFamilyError = (_class11 = class extends PipRailError {constructor(...args9) { super(...args9); _class11.prototype.__init11.call(this); }
63
- __init11() {this.code = "WRONG_FAMILY"}
62
+ var NonReplayableBodyError = (_class11 = class extends PipRailError {constructor(...args9) { super(...args9); _class11.prototype.__init11.call(this); }
63
+ __init11() {this.code = "NON_REPLAYABLE_BODY"}
64
64
  }, _class11);
65
- var UnknownTokenError = (_class12 = class extends PipRailError {constructor(...args10) { super(...args10); _class12.prototype.__init12.call(this); }
66
- __init12() {this.code = "UNKNOWN_TOKEN"}
65
+ var WrongFamilyError = (_class12 = class extends PipRailError {constructor(...args10) { super(...args10); _class12.prototype.__init12.call(this); }
66
+ __init12() {this.code = "WRONG_FAMILY"}
67
67
  }, _class12);
68
- var MissingDriverError = (_class13 = class extends PipRailError {constructor(...args11) { super(...args11); _class13.prototype.__init13.call(this); }
69
- __init13() {this.code = "MISSING_DRIVER"}
68
+ var UnknownTokenError = (_class13 = class extends PipRailError {constructor(...args11) { super(...args11); _class13.prototype.__init13.call(this); }
69
+ __init13() {this.code = "UNKNOWN_TOKEN"}
70
70
  }, _class13);
71
- var UnsupportedNetworkError = (_class14 = class extends PipRailError {constructor(...args12) { super(...args12); _class14.prototype.__init14.call(this); }
72
- __init14() {this.code = "UNSUPPORTED_NETWORK"}
71
+ var MissingDriverError = (_class14 = class extends PipRailError {constructor(...args12) { super(...args12); _class14.prototype.__init14.call(this); }
72
+ __init14() {this.code = "MISSING_DRIVER"}
73
73
  }, _class14);
74
+ var UnsupportedNetworkError = (_class15 = class extends PipRailError {constructor(...args13) { super(...args13); _class15.prototype.__init15.call(this); }
75
+ __init15() {this.code = "UNSUPPORTED_NETWORK"}
76
+ }, _class15);
74
77
 
75
78
  // src/drivers/shared.ts
76
79
  var FAMILY_LABEL = {
@@ -174,4 +177,5 @@ function nativeCost(opts) {
174
177
 
175
178
 
176
179
 
177
- 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.InvalidEnvelopeError = InvalidEnvelopeError; exports.NoCompatibleAcceptError = NoCompatibleAcceptError; exports.NonReplayableBodyError = NonReplayableBodyError; exports.WrongFamilyError = WrongFamilyError; exports.UnknownTokenError = UnknownTokenError; exports.MissingDriverError = MissingDriverError; exports.UnsupportedNetworkError = UnsupportedNetworkError; exports.rejectForeignToken = rejectForeignToken; exports.parseUnits = parseUnits; exports.floorUnits = floorUnits; exports.formatUnits = formatUnits; exports.nativeCost = nativeCost;
180
+
181
+ 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.NonReplayableBodyError = NonReplayableBodyError; exports.WrongFamilyError = WrongFamilyError; exports.UnknownTokenError = UnknownTokenError; exports.MissingDriverError = MissingDriverError; exports.UnsupportedNetworkError = UnsupportedNetworkError; exports.rejectForeignToken = rejectForeignToken; exports.parseUnits = parseUnits; exports.floorUnits = floorUnits; exports.formatUnits = formatUnits; exports.nativeCost = nativeCost;
@@ -50,6 +50,9 @@ var PaymentDeclinedError = class extends PipRailError {
50
50
  var ConfirmationTimeoutError = class extends PipRailError {
51
51
  code = "CONFIRMATION_TIMEOUT";
52
52
  };
53
+ var SettlementError = class extends PipRailError {
54
+ code = "SETTLEMENT_FAILED";
55
+ };
53
56
  var InvalidEnvelopeError = class extends PipRailError {
54
57
  code = "INVALID_ENVELOPE";
55
58
  };
@@ -162,6 +165,7 @@ export {
162
165
  MaxRetriesExceededError,
163
166
  PaymentDeclinedError,
164
167
  ConfirmationTimeoutError,
168
+ SettlementError,
165
169
  InvalidEnvelopeError,
166
170
  NoCompatibleAcceptError,
167
171
  NonReplayableBodyError,