@piprail/sdk 2.16.2 → 3.0.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 (33) hide show
  1. package/CHANGELOG.md +343 -0
  2. package/README.md +1 -0
  3. package/dist/{algorand-25FMBCT3.js → algorand-HL57PQHE.js} +157 -2
  4. package/dist/{algorand-Q3TUQLPK.cjs → algorand-W776EEM2.cjs} +205 -50
  5. package/dist/{aptos-VBJONBFY.cjs → aptos-5QBXJ6NV.cjs} +255 -39
  6. package/dist/{aptos-SBV6SGDP.js → aptos-H5VLH2QL.js} +217 -1
  7. package/dist/{chunk-QONQSZHJ.cjs → chunk-6XTNI2OQ.cjs} +44 -44
  8. package/dist/{chunk-OXEFPLZA.cjs → chunk-6ZRAIQXF.cjs} +4 -4
  9. package/dist/chunk-GVCGUSTE.js +30 -0
  10. package/dist/{chunk-V2IJ5HUW.cjs → chunk-MZAJQYM3.cjs} +1 -0
  11. package/dist/chunk-MZXVXC3C.cjs +30 -0
  12. package/dist/{chunk-2CX7XRZK.js → chunk-TZDVZCTC.js} +1 -0
  13. package/dist/{chunk-C52H5TYB.js → chunk-YXBQKBDH.js} +2 -2
  14. package/dist/index.cjs +2929 -1444
  15. package/dist/index.d.cts +625 -13
  16. package/dist/index.d.ts +625 -13
  17. package/dist/index.js +2506 -1021
  18. package/dist/{near-OLKCMTBI.js → near-5X2CQGML.js} +197 -1
  19. package/dist/{near-5LTTDU6G.cjs → near-XSQXEIHT.cjs} +242 -46
  20. package/dist/{solana-AI2G7V33.cjs → solana-EBV6PUCU.cjs} +211 -52
  21. package/dist/{solana-HTKDRTD3.js → solana-O6Q6QILH.js} +167 -8
  22. package/dist/{stellar-E2KWEV2E.cjs → stellar-5C7FQLPS.cjs} +191 -29
  23. package/dist/{stellar-EUFZLX6J.js → stellar-YF5LOJEM.js} +163 -1
  24. package/dist/{sui-KCIITCYH.js → sui-JFQSDNSZ.js} +165 -3
  25. package/dist/{sui-Q3NJOJZS.cjs → sui-WIZEAO7E.cjs} +185 -23
  26. package/dist/{ton-J7TQWRN4.cjs → ton-AGTKLQA5.cjs} +264 -22
  27. package/dist/{ton-WH2JVQOO.js → ton-OZKFNRLT.js} +244 -2
  28. package/dist/{tron-FXBXDNEY.js → tron-HG3IOOCG.js} +283 -1
  29. package/dist/{tron-HIPMOX7S.cjs → tron-S4WX7OHY.cjs} +323 -41
  30. package/dist/{xrpl-RUOB37QH.js → xrpl-GOVHMYYK.js} +222 -5
  31. package/dist/{xrpl-SVVS445B.cjs → xrpl-YS3IXPLV.cjs} +273 -56
  32. package/package.json +12 -2
  33. package/dist/{chunk-QU25LSVS.js → chunk-5GRBEMCA.js} +44 -44
@@ -1,17 +1,22 @@
1
+ import {
2
+ applySlippage
3
+ } from "./chunk-GVCGUSTE.js";
1
4
  import {
2
5
  ConfirmationTimeoutError,
6
+ InsufficientFundsError,
3
7
  SettlementError,
4
8
  UnknownTokenError,
5
9
  UnsupportedSchemeError,
6
10
  WrongFamilyError,
7
11
  assertNoLegacyWalletKey,
12
+ formatUnits,
8
13
  nativeCost,
9
14
  rejectForeignToken,
10
15
  toInsufficientFundsError
11
- } from "./chunk-QU25LSVS.js";
16
+ } from "./chunk-5GRBEMCA.js";
12
17
 
13
18
  // src/drivers/solana/index.ts
14
- import { Connection, PublicKey as PublicKey3 } from "@solana/web3.js";
19
+ import { Connection as Connection2, PublicKey as PublicKey3 } from "@solana/web3.js";
15
20
  import {
16
21
  getAccount,
17
22
  getAssociatedTokenAddressSync as getAssociatedTokenAddressSync3,
@@ -102,6 +107,148 @@ async function paySolana(params) {
102
107
  return signature;
103
108
  }
104
109
 
110
+ // src/drivers/solana/swap.ts
111
+ import { VersionedTransaction } from "@solana/web3.js";
112
+ var JUPITER_API = "https://lite-api.jup.ag/swap/v1";
113
+ var WSOL_MINT = "So11111111111111111111111111111111111111112";
114
+ function sourceFor(platformFee) {
115
+ const charged = platformFee != null && !(typeof platformFee === "object" && Object.keys(platformFee).length === 0);
116
+ return {
117
+ kind: "provider",
118
+ name: "Jupiter",
119
+ note: "Third-party Solana DEX aggregator (lite-api.jup.ag), used keyless. It routes and builds the transaction; your own key signs it and Jupiter never holds your funds. " + (charged ? `\u26A0\uFE0F THIS QUOTE CARRIES A PLATFORM FEE: ${JSON.stringify(platformFee)}. PipRail did not set one.` : "This quote carries no platform fee, and PipRail adds none.")
120
+ };
121
+ }
122
+ function mintFor(t) {
123
+ return t.asset === "native" ? WSOL_MINT : t.asset;
124
+ }
125
+ function side(t, amount) {
126
+ const decimals = t.asset === "native" ? SOL_DECIMALS : t.decimals;
127
+ return {
128
+ asset: t.asset,
129
+ symbol: t.symbol ?? (t.asset === "native" ? "SOL" : t.asset),
130
+ decimals,
131
+ amount: amount.toString(),
132
+ amountFormatted: formatUnits(amount, decimals)
133
+ };
134
+ }
135
+ async function getJson(url, init) {
136
+ const ctrl = new AbortController();
137
+ const timer = setTimeout(() => ctrl.abort(), 1e4);
138
+ try {
139
+ const res = await fetch(url, { ...init ?? {}, signal: ctrl.signal });
140
+ if (!res.ok) return null;
141
+ return await res.json();
142
+ } catch {
143
+ return null;
144
+ } finally {
145
+ clearTimeout(timer);
146
+ }
147
+ }
148
+ async function quoteSolanaSwap(p) {
149
+ if (p.wantAmount <= 0n) return null;
150
+ const inputMint = mintFor(p.from);
151
+ const outputMint = mintFor(p.to);
152
+ if (inputMint === outputMint) return null;
153
+ const url = `${JUPITER_API}/quote?inputMint=${inputMint}&outputMint=${outputMint}&amount=${p.wantAmount.toString()}&swapMode=ExactOut&slippageBps=${p.slippageBps}`;
154
+ const q = await getJson(url);
155
+ if (!q?.otherAmountThreshold || !q.inAmount) return null;
156
+ if (q.swapMode !== "ExactOut") return null;
157
+ if (q.outAmount !== p.wantAmount.toString()) return null;
158
+ let spend;
159
+ let maxSpend;
160
+ try {
161
+ spend = BigInt(q.inAmount);
162
+ const jupCap = BigInt(q.otherAmountThreshold);
163
+ const ourCap = applySlippage(spend, p.slippageBps);
164
+ maxSpend = jupCap > ourCap ? jupCap : ourCap;
165
+ } catch {
166
+ return null;
167
+ }
168
+ if (spend <= 0n) return null;
169
+ const fromDecimals = p.from.asset === "native" ? SOL_DECIMALS : p.from.decimals;
170
+ return {
171
+ source: sourceFor(q.platformFee),
172
+ network: p.network,
173
+ from: side(p.from, spend),
174
+ to: side(p.to, p.wantAmount),
175
+ maxSpend: maxSpend.toString(),
176
+ maxSpendFormatted: formatUnits(maxSpend, fromDecimals),
177
+ slippageBps: p.slippageBps,
178
+ // Jupiter needs its own quote object back verbatim to build the transaction.
179
+ route: q
180
+ };
181
+ }
182
+ async function swapSolana(p) {
183
+ const { connection, keypair, quote } = p;
184
+ const jupQuote = quote.route;
185
+ if (!jupQuote?.otherAmountThreshold) {
186
+ throw new Error("Solana: swap quote is missing its Jupiter routing data \u2014 re-quote before swapping.");
187
+ }
188
+ const built = await getJson(`${JUPITER_API}/swap`, {
189
+ method: "POST",
190
+ headers: { "content-type": "application/json" },
191
+ body: JSON.stringify({
192
+ quoteResponse: jupQuote,
193
+ userPublicKey: keypair.publicKey.toBase58(),
194
+ // Let Jupiter create + close the wrapped-SOL account in the same transaction,
195
+ // so a SOL leg needs no separate setup step from the caller.
196
+ wrapAndUnwrapSol: true,
197
+ dynamicComputeUnitLimit: true
198
+ })
199
+ });
200
+ if (!built?.swapTransaction) {
201
+ throw new InsufficientFundsError(
202
+ "Jupiter could not build this swap transaction (no route, or the market moved). Nothing was spent \u2014 re-quote and retry."
203
+ );
204
+ }
205
+ let tx;
206
+ try {
207
+ tx = VersionedTransaction.deserialize(Buffer.from(built.swapTransaction, "base64"));
208
+ } catch (cause) {
209
+ throw new Error("Solana: Jupiter returned a transaction this SDK could not decode.", { cause });
210
+ }
211
+ tx.sign([keypair]);
212
+ try {
213
+ const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash();
214
+ const sig = await connection.sendRawTransaction(tx.serialize(), {
215
+ skipPreflight: false,
216
+ maxRetries: 3
217
+ });
218
+ const conf = await connection.confirmTransaction(
219
+ { signature: sig, blockhash, lastValidBlockHeight },
220
+ "confirmed"
221
+ );
222
+ if (conf?.value?.err) {
223
+ throw new InsufficientFundsError(
224
+ `Solana swap failed on-chain (tx ${sig}): ${JSON.stringify(conf.value.err)}. Nothing was swapped. The usual cause is slippage \u2014 re-quote and retry.`
225
+ );
226
+ }
227
+ return {
228
+ transaction: sig,
229
+ network: quote.network,
230
+ source: quote.source,
231
+ from: quote.from,
232
+ to: quote.to
233
+ };
234
+ } catch (err) {
235
+ const msg = String(err?.message ?? err);
236
+ if (/insufficient|0x1\b/i.test(msg)) {
237
+ throw new InsufficientFundsError(
238
+ `Solana swap failed: the wallet can't cover it (token balance, or SOL for fees and rent). (${msg.slice(0, 160)})`,
239
+ { cause: err }
240
+ );
241
+ }
242
+ if (/slippage|0x1771/i.test(msg)) {
243
+ throw new InsufficientFundsError(
244
+ "Solana swap refused: the price moved past your slippage cap, so nothing was spent. Re-quote and retry, or raise slippageBps.",
245
+ { cause: err }
246
+ );
247
+ }
248
+ throw err;
249
+ }
250
+ }
251
+
105
252
  // src/drivers/solana/verify.ts
106
253
  async function verifySolana(params) {
107
254
  const { connection, signature, accept } = params;
@@ -210,7 +357,7 @@ import {
210
357
  PublicKey as PublicKey2,
211
358
  TransactionInstruction,
212
359
  TransactionMessage,
213
- VersionedTransaction
360
+ VersionedTransaction as VersionedTransaction2
214
361
  } from "@solana/web3.js";
215
362
  import {
216
363
  createTransferCheckedInstruction as createTransferCheckedInstruction2,
@@ -348,7 +495,7 @@ async function payExactSolana(input) {
348
495
  recentBlockhash: blockhash,
349
496
  instructions
350
497
  }).compileToV0Message();
351
- const tx = new VersionedTransaction(message);
498
+ const tx = new VersionedTransaction2(message);
352
499
  tx.sign([keypair]);
353
500
  const buyerIndex = message.staticAccountKeys.findIndex((k) => k.equals(keypair.publicKey));
354
501
  if (buyerIndex < 1 || buyerIndex >= message.header.numRequiredSignatures) {
@@ -396,7 +543,7 @@ async function verifyAndSettleExactSolana(input) {
396
543
  const program = tokenProgramFor(accept);
397
544
  let tx;
398
545
  try {
399
- tx = VersionedTransaction.deserialize(Buffer.from(payload.transaction, "base64"));
546
+ tx = VersionedTransaction2.deserialize(Buffer.from(payload.transaction, "base64"));
400
547
  } catch (err) {
401
548
  return fail("signature_invalid", `Unparseable SVM transaction: ${shorten(err instanceof Error ? err.message : String(err))}.`);
402
549
  }
@@ -582,7 +729,7 @@ async function pollConfirmed(connection, signature) {
582
729
  }
583
730
 
584
731
  // src/drivers/solana/wallet.ts
585
- import { Keypair as Keypair3 } from "@solana/web3.js";
732
+ import { Keypair as Keypair4 } from "@solana/web3.js";
586
733
  import bs582 from "bs58";
587
734
  function toKeypair(wallet, network) {
588
735
  if (typeof wallet !== "object" || wallet === null) {
@@ -603,7 +750,7 @@ function toKeypair(wallet, network) {
603
750
  }
604
751
  try {
605
752
  const bytes = typeof sk === "string" ? bs582.decode(sk) : sk;
606
- return Keypair3.fromSecretKey(bytes);
753
+ return Keypair4.fromSecretKey(bytes);
607
754
  } catch (err) {
608
755
  throw new WrongFamilyError(
609
756
  `chain ${network} is Solana; the wallet { key } isn't a valid Solana secret (expected a base58 secret string or a 64-byte Uint8Array): ${err instanceof Error ? err.message : String(err)}.`
@@ -625,7 +772,7 @@ var solanaDriver = {
625
772
  }
626
773
  };
627
774
  function makeSolanaNetwork(preset, rpcUrl) {
628
- const connection = new Connection(rpcUrl, "confirmed");
775
+ const connection = new Connection2(rpcUrl, "confirmed");
629
776
  const network = preset.caip2;
630
777
  return {
631
778
  family: "solana",
@@ -735,6 +882,11 @@ function makeSolanaNetwork(preset, rpcUrl) {
735
882
  detail: "1 signature + recipient token-account rent (~0.00204 SOL, if not already created)"
736
883
  });
737
884
  },
885
+ /** The bound wallet's own address — where THIS wallet gets paid. Derived from the key
886
+ * material only: no RPC, nothing moved. See {@link ResolvedNetwork.addressOf}. */
887
+ async addressOf(wallet) {
888
+ return wallet._native.publicKey.toBase58();
889
+ },
738
890
  async balanceOf(wallet, asset) {
739
891
  const owner = wallet._native.publicKey;
740
892
  const native = await connection.getBalance(owner).then((n) => BigInt(n)).catch(() => null);
@@ -764,6 +916,13 @@ function makeSolanaNetwork(preset, rpcUrl) {
764
916
  async recipientReady() {
765
917
  return { ready: "n/a" };
766
918
  },
919
+ /* ---- swap (OPTIONAL, opt-in): via Jupiter, keyless + no platform fee. See ./swap.ts ---- */
920
+ async quoteSwap({ from, to, wantAmount, slippageBps }) {
921
+ return quoteSolanaSwap({ network, from, to, wantAmount, slippageBps });
922
+ },
923
+ async swap(wallet, quote) {
924
+ return swapSolana({ connection, keypair: wallet._native, quote });
925
+ },
767
926
  async verify(ref, accept) {
768
927
  return verifySolana({ connection, signature: ref, accept });
769
928
  },
@@ -1,5 +1,8 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } 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; }
2
2
 
3
+ var _chunkMZXVXC3Ccjs = require('./chunk-MZXVXC3C.cjs');
4
+
5
+
3
6
  var _chunkCQREG5LEcjs = require('./chunk-CQREG5LE.cjs');
4
7
 
5
8
 
@@ -12,7 +15,8 @@ var _chunkCQREG5LEcjs = require('./chunk-CQREG5LE.cjs');
12
15
 
13
16
 
14
17
 
15
- var _chunkQONQSZHJcjs = require('./chunk-QONQSZHJ.cjs');
18
+
19
+ var _chunk6XTNI2OQcjs = require('./chunk-6XTNI2OQ.cjs');
16
20
 
17
21
  // src/drivers/stellar/index.ts
18
22
  var _stellarsdk = require('@stellar/stellar-sdk');
@@ -98,30 +102,30 @@ function mapSubmitError(err) {
98
102
  const seen = codes.join(", ");
99
103
  const has = (re) => codes.some((c) => re.test(c));
100
104
  if (has(/op_no_destination/i)) {
101
- return new (0, _chunkQONQSZHJcjs.RecipientNotReadyError)(
105
+ return new (0, _chunk6XTNI2OQcjs.RecipientNotReadyError)(
102
106
  `Stellar destination account doesn't exist yet \u2014 create it with \u22651 XLM (the base reserve) before it can receive. (Stellar: ${seen})`,
103
107
  { cause: err }
104
108
  );
105
109
  }
106
110
  if (has(/op_(no_trust|line_full|not_authorized)/i) && !has(/src_no_trust/i)) {
107
- return new (0, _chunkQONQSZHJcjs.RecipientNotReadyError)(
111
+ return new (0, _chunk6XTNI2OQcjs.RecipientNotReadyError)(
108
112
  `Stellar destination can't hold this asset \u2014 it needs a trustline for it (and to be authorized) before it can receive. (Stellar: ${seen})`,
109
113
  { cause: err }
110
114
  );
111
115
  }
112
116
  if (has(/underfunded|insufficient|low_reserve|src_no_trust/i)) {
113
- return new (0, _chunkQONQSZHJcjs.InsufficientFundsError)(
117
+ return new (0, _chunk6XTNI2OQcjs.InsufficientFundsError)(
114
118
  `Stellar payment failed: the sender can't cover it \u2014 balance, base reserve, or no trustline to send this asset. (Stellar: ${seen})`,
115
119
  { cause: err }
116
120
  );
117
121
  }
118
122
  if (isAccountNotFound(err)) {
119
- return new (0, _chunkQONQSZHJcjs.InsufficientFundsError)(
123
+ return new (0, _chunk6XTNI2OQcjs.InsufficientFundsError)(
120
124
  "Stellar source account not found on-chain \u2014 fund the sender (\u2265 base reserve) before it can pay.",
121
125
  { cause: err }
122
126
  );
123
127
  }
124
- return _nullishCoalesce(_chunkQONQSZHJcjs.toInsufficientFundsError.call(void 0, err), () => ( err));
128
+ return _nullishCoalesce(_chunk6XTNI2OQcjs.toInsufficientFundsError.call(void 0, err), () => ( err));
125
129
  }
126
130
  function isAccountNotFound(err) {
127
131
  const e = err;
@@ -133,6 +137,151 @@ function extractResultCodes(err) {
133
137
  return [_nullishCoalesce(extras.transaction, () => ( "")), ..._nullishCoalesce(extras.operations, () => ( []))].filter(Boolean);
134
138
  }
135
139
 
140
+ // src/drivers/stellar/swap.ts
141
+
142
+ var SOURCE = {
143
+ kind: "protocol",
144
+ name: "Stellar SDEX",
145
+ note: "Rate from the ledger\u2019s own order books and liquidity pools, read live from Horizon. Order books charge no trading fee; liquidity pools charge a fixed 0.30%."
146
+ };
147
+ function assetForId(asset) {
148
+ if (asset === "native") return _stellarsdk.Asset.native();
149
+ const parts = parseStellarAssetId(asset);
150
+ if (!parts) return null;
151
+ try {
152
+ return new (0, _stellarsdk.Asset)(parts.code, parts.issuer);
153
+ } catch (e2) {
154
+ return null;
155
+ }
156
+ }
157
+ function hopToAsset(h) {
158
+ return h.asset_type === "native" ? _stellarsdk.Asset.native() : new (0, _stellarsdk.Asset)(h.asset_code, h.asset_issuer);
159
+ }
160
+ function side(t, amount) {
161
+ return {
162
+ asset: t.asset,
163
+ symbol: _nullishCoalesce(t.symbol, () => ( (t.asset === "native" ? XLM_SYMBOL : t.asset))),
164
+ decimals: STELLAR_DECIMALS,
165
+ amount: amount.toString(),
166
+ amountFormatted: _chunk6XTNI2OQcjs.formatUnits.call(void 0, amount, STELLAR_DECIMALS)
167
+ };
168
+ }
169
+ async function quoteStellarSwap(p) {
170
+ const fromAsset = assetForId(p.from.asset);
171
+ const toAsset = assetForId(p.to.asset);
172
+ if (!fromAsset || !toAsset) return null;
173
+ if (p.from.asset === p.to.asset) return null;
174
+ if (p.wantAmount <= 0n) return null;
175
+ const wantFormatted = _chunk6XTNI2OQcjs.formatUnits.call(void 0, p.wantAmount, STELLAR_DECIMALS);
176
+ let records;
177
+ try {
178
+ const page = await p.server.strictReceivePaths([fromAsset], toAsset, wantFormatted).call();
179
+ records = page.records;
180
+ } catch (e3) {
181
+ return null;
182
+ }
183
+ if (!_optionalChain([records, 'optionalAccess', _9 => _9.length])) return null;
184
+ let best = null;
185
+ let spend = null;
186
+ for (const r of records) {
187
+ let candidate;
188
+ try {
189
+ candidate = _chunk6XTNI2OQcjs.parseUnits.call(void 0, r.source_amount, STELLAR_DECIMALS);
190
+ } catch (e4) {
191
+ continue;
192
+ }
193
+ if (candidate <= 0n) continue;
194
+ if (spend === null || candidate < spend) {
195
+ spend = candidate;
196
+ best = r;
197
+ }
198
+ }
199
+ if (best === null || spend === null) return null;
200
+ const maxSpend = _chunkMZXVXC3Ccjs.applySlippage.call(void 0, spend, p.slippageBps);
201
+ return {
202
+ source: SOURCE,
203
+ network: p.network,
204
+ from: side(p.from, spend),
205
+ to: side(p.to, p.wantAmount),
206
+ maxSpend: maxSpend.toString(),
207
+ maxSpendFormatted: _chunk6XTNI2OQcjs.formatUnits.call(void 0, maxSpend, STELLAR_DECIMALS),
208
+ slippageBps: p.slippageBps,
209
+ route: _nullishCoalesce(best.path, () => ( []))
210
+ };
211
+ }
212
+ async function swapStellar(p) {
213
+ const { server, keypair, quote } = p;
214
+ const sendAsset = assetForId(quote.from.asset);
215
+ const destAsset = assetForId(quote.to.asset);
216
+ if (!sendAsset || !destAsset) {
217
+ throw new Error(`Stellar: malformed asset id in swap quote (${quote.from.asset} \u2192 ${quote.to.asset}).`);
218
+ }
219
+ const path = Array.isArray(quote.route) ? quote.route.map(hopToAsset) : [];
220
+ try {
221
+ const source = await server.loadAccount(keypair.publicKey());
222
+ const tx = new (0, _stellarsdk.TransactionBuilder)(source, { fee: _stellarsdk.BASE_FEE, networkPassphrase: STELLAR_PASSPHRASE }).addOperation(
223
+ _stellarsdk.Operation.pathPaymentStrictReceive({
224
+ sendAsset,
225
+ // The on-chain slippage cap. Validators enforce it; we do not.
226
+ sendMax: _chunk6XTNI2OQcjs.formatUnits.call(void 0, BigInt(quote.maxSpend), STELLAR_DECIMALS),
227
+ destination: keypair.publicKey(),
228
+ // ← ourselves: this is what makes it a swap
229
+ destAsset,
230
+ destAmount: quote.to.amountFormatted,
231
+ path
232
+ })
233
+ ).setTimeout(120).build();
234
+ tx.sign(keypair);
235
+ const res = await server.submitTransaction(tx);
236
+ return {
237
+ transaction: res.hash,
238
+ network: quote.network,
239
+ source: quote.source,
240
+ // Strict-RECEIVE fixes the output exactly; the input is whatever the market
241
+ // took, bounded by maxSpend. We report the quoted estimate for `from`.
242
+ from: quote.from,
243
+ to: quote.to
244
+ };
245
+ } catch (err) {
246
+ throw mapSwapError(err);
247
+ }
248
+ }
249
+ function mapSwapError(err) {
250
+ const codes = extractResultCodes2(err);
251
+ const seen = codes.join(", ");
252
+ const has = (re) => codes.some((c) => re.test(c));
253
+ if (has(/op_over_sendmax/i)) {
254
+ return new (0, _chunk6XTNI2OQcjs.InsufficientFundsError)(
255
+ `Stellar swap refused: the price moved past your slippage cap, so nothing was spent. Re-quote and retry, or raise slippageBps. (Stellar: ${seen})`,
256
+ { cause: err }
257
+ );
258
+ }
259
+ if (has(/op_too_few_offers|op_no_path/i)) {
260
+ return new (0, _chunk6XTNI2OQcjs.InsufficientFundsError)(
261
+ `Stellar swap refused: not enough liquidity on this pair right now, so nothing was spent. (Stellar: ${seen})`,
262
+ { cause: err }
263
+ );
264
+ }
265
+ if (has(/op_no_(trust|issuer)|op_not_authorized|op_line_full/i)) {
266
+ return new (0, _chunk6XTNI2OQcjs.RecipientNotReadyError)(
267
+ `Stellar swap refused: your account needs a trustline for the asset you're swapping INTO (and authorization) before it can hold it. (Stellar: ${seen})`,
268
+ { cause: err }
269
+ );
270
+ }
271
+ if (has(/underfunded|insufficient|low_reserve|src_no_trust/i)) {
272
+ return new (0, _chunk6XTNI2OQcjs.InsufficientFundsError)(
273
+ `Stellar swap failed: the account can't cover it \u2014 balance, base reserve, or no trustline to send this asset. (Stellar: ${seen})`,
274
+ { cause: err }
275
+ );
276
+ }
277
+ return _nullishCoalesce(_chunk6XTNI2OQcjs.toInsufficientFundsError.call(void 0, err), () => ( err));
278
+ }
279
+ function extractResultCodes2(err) {
280
+ const extras = _optionalChain([err, 'optionalAccess', _10 => _10.response, 'optionalAccess', _11 => _11.data, 'optionalAccess', _12 => _12.extras, 'optionalAccess', _13 => _13.result_codes]);
281
+ if (!extras) return [];
282
+ return [_nullishCoalesce(extras.transaction, () => ( "")), ..._nullishCoalesce(extras.operations, () => ( []))].filter(Boolean);
283
+ }
284
+
136
285
  // src/drivers/stellar/verify.ts
137
286
 
138
287
  function memoCandidatesForNonce(nonce) {
@@ -148,7 +297,7 @@ async function verifyStellar(params) {
148
297
  let txs;
149
298
  try {
150
299
  txs = await reader.transactionsForAccount(accept.payTo, 200);
151
- } catch (e2) {
300
+ } catch (e5) {
152
301
  return rpcFailed(nonce);
153
302
  }
154
303
  const tx = txs.find(
@@ -173,7 +322,7 @@ async function verifyStellar(params) {
173
322
  let payments;
174
323
  try {
175
324
  payments = await reader.paymentsForTransaction(tx.hash);
176
- } catch (e3) {
325
+ } catch (e6) {
177
326
  return rpcFailed(nonce);
178
327
  }
179
328
  const toUs = payments.filter(
@@ -218,8 +367,8 @@ function assetMatches(p, want) {
218
367
  }
219
368
  function parseAmount(amount, decimals) {
220
369
  try {
221
- return _chunkQONQSZHJcjs.parseUnits.call(void 0, amount, decimals);
222
- } catch (e4) {
370
+ return _chunk6XTNI2OQcjs.parseUnits.call(void 0, amount, decimals);
371
+ } catch (e7) {
223
372
  return 0n;
224
373
  }
225
374
  }
@@ -242,13 +391,13 @@ function rpcFailed(nonce) {
242
391
 
243
392
  function assertStellarWallet(wallet, network) {
244
393
  if (typeof wallet !== "object" || wallet === null) {
245
- throw new (0, _chunkQONQSZHJcjs.WrongFamilyError)(
394
+ throw new (0, _chunk6XTNI2OQcjs.WrongFamilyError)(
246
395
  `chain ${network} is Stellar; wallet must be { key } (S\u2026 seed) or { keypair }.`
247
396
  );
248
397
  }
249
- _chunkQONQSZHJcjs.assertNoLegacyWalletKey.call(void 0, wallet, "Stellar");
398
+ _chunk6XTNI2OQcjs.assertNoLegacyWalletKey.call(void 0, wallet, "Stellar");
250
399
  if (!("key" in wallet) && !("keypair" in wallet)) {
251
- throw new (0, _chunkQONQSZHJcjs.WrongFamilyError)(
400
+ throw new (0, _chunk6XTNI2OQcjs.WrongFamilyError)(
252
401
  `chain ${network} is Stellar; wallet must be { key } (S\u2026 seed) or { keypair }.`
253
402
  );
254
403
  }
@@ -258,17 +407,17 @@ function resolveStellarWallet(config) {
258
407
  if (config.keypair) return config.keypair;
259
408
  if (config.key) {
260
409
  if (!_stellarsdk.StrKey.isValidEd25519SecretSeed(config.key)) {
261
- throw new (0, _chunkQONQSZHJcjs.WrongFamilyError)("Stellar wallet { key } is not a valid S\u2026 secret seed.");
410
+ throw new (0, _chunk6XTNI2OQcjs.WrongFamilyError)("Stellar wallet { key } is not a valid S\u2026 secret seed.");
262
411
  }
263
412
  return _stellarsdk.Keypair.fromSecret(config.key);
264
413
  }
265
- throw new (0, _chunkQONQSZHJcjs.WrongFamilyError)("Stellar wallet needs { key } (S\u2026 seed) or { keypair }.");
414
+ throw new (0, _chunk6XTNI2OQcjs.WrongFamilyError)("Stellar wallet needs { key } (S\u2026 seed) or { keypair }.");
266
415
  }
267
416
 
268
417
  // src/drivers/stellar/index.ts
269
418
  function isStellarNotFound(e) {
270
419
  const x = e;
271
- return _optionalChain([x, 'optionalAccess', _9 => _9.response, 'optionalAccess', _10 => _10.status]) === 404 || _optionalChain([x, 'optionalAccess', _11 => _11.name]) === "NotFoundError";
420
+ return _optionalChain([x, 'optionalAccess', _14 => _14.response, 'optionalAccess', _15 => _15.status]) === 404 || _optionalChain([x, 'optionalAccess', _16 => _16.name]) === "NotFoundError";
272
421
  }
273
422
  var stellarDriver = {
274
423
  family: "stellar",
@@ -317,7 +466,7 @@ function makeStellarNetwork(preset, rpcUrl) {
317
466
  const info = preset.tokens[token.toUpperCase()];
318
467
  if (!info) {
319
468
  const known = Object.keys(preset.tokens).join(", ") || "(none built in)";
320
- throw new (0, _chunkQONQSZHJcjs.UnknownTokenError)(
469
+ throw new (0, _chunk6XTNI2OQcjs.UnknownTokenError)(
321
470
  `token "${token}" isn't built in for Stellar (known: ${known}). Pass { issuer, code, decimals } for a custom asset, or use 'native'.`
322
471
  );
323
472
  }
@@ -327,10 +476,10 @@ function makeStellarNetwork(preset, rpcUrl) {
327
476
  symbol: info.symbol
328
477
  };
329
478
  }
330
- _chunkQONQSZHJcjs.rejectForeignToken.call(void 0, token, "stellar", network);
479
+ _chunk6XTNI2OQcjs.rejectForeignToken.call(void 0, token, "stellar", network);
331
480
  const t = token;
332
481
  if (!t.issuer || !t.code || typeof t.decimals !== "number") {
333
- throw new (0, _chunkQONQSZHJcjs.WrongFamilyError)(
482
+ throw new (0, _chunk6XTNI2OQcjs.WrongFamilyError)(
334
483
  `chain ${network} is Stellar; a custom token must be { issuer, code, decimals }.`
335
484
  );
336
485
  }
@@ -351,12 +500,12 @@ function makeStellarNetwork(preset, rpcUrl) {
351
500
  },
352
501
  assertValidPayTo(payTo) {
353
502
  if (payTo.startsWith("0x")) {
354
- throw new (0, _chunkQONQSZHJcjs.WrongFamilyError)(
503
+ throw new (0, _chunk6XTNI2OQcjs.WrongFamilyError)(
355
504
  `chain ${network} is Stellar, but payTo "${payTo}" looks like an EVM address.`
356
505
  );
357
506
  }
358
507
  if (!_stellarsdk.StrKey.isValidEd25519PublicKey(payTo)) {
359
- throw new (0, _chunkQONQSZHJcjs.WrongFamilyError)(
508
+ throw new (0, _chunk6XTNI2OQcjs.WrongFamilyError)(
360
509
  `chain ${network} is Stellar, but payTo "${payTo}" is not a valid Stellar account (G\u2026).`
361
510
  );
362
511
  }
@@ -373,14 +522,14 @@ function makeStellarNetwork(preset, rpcUrl) {
373
522
  try {
374
523
  const tx = await server.transactions().transaction(ref).call();
375
524
  return { height: String(_nullishCoalesce(_nullishCoalesce(tx.ledger_attr, () => ( tx.ledger)), () => ( 0))) };
376
- } catch (e5) {
525
+ } catch (e8) {
377
526
  await _chunkCQREG5LEcjs.delay.call(void 0, 1500);
378
527
  }
379
528
  }
380
- throw new (0, _chunkQONQSZHJcjs.ConfirmationTimeoutError)(`Stellar tx ${ref} not visible on Horizon in time.`);
529
+ throw new (0, _chunk6XTNI2OQcjs.ConfirmationTimeoutError)(`Stellar tx ${ref} not visible on Horizon in time.`);
381
530
  },
382
531
  async estimateCost() {
383
- return _chunkQONQSZHJcjs.nativeCost.call(void 0, {
532
+ return _chunk6XTNI2OQcjs.nativeCost.call(void 0, {
384
533
  symbol: XLM_SYMBOL,
385
534
  decimals: STELLAR_DECIMALS,
386
535
  fee: 100n,
@@ -388,11 +537,16 @@ function makeStellarNetwork(preset, rpcUrl) {
388
537
  detail: "base fee 100 stroops (1 operation)"
389
538
  });
390
539
  },
540
+ /** The bound wallet's own address — where THIS wallet gets paid. Derived from the key
541
+ * material only: no RPC, nothing moved. See {@link ResolvedNetwork.addressOf}. */
542
+ async addressOf(wallet) {
543
+ return resolveStellarWallet(wallet._native).publicKey();
544
+ },
391
545
  async balanceOf(wallet, asset) {
392
546
  let owner;
393
547
  try {
394
548
  owner = resolveStellarWallet(wallet._native).publicKey();
395
- } catch (e6) {
549
+ } catch (e9) {
396
550
  return { token: null, native: null };
397
551
  }
398
552
  let lines;
@@ -404,18 +558,18 @@ function makeStellarNetwork(preset, rpcUrl) {
404
558
  }
405
559
  const toBase = (s) => {
406
560
  try {
407
- return s != null ? _chunkQONQSZHJcjs.parseUnits.call(void 0, s, STELLAR_DECIMALS) : 0n;
408
- } catch (e7) {
561
+ return s != null ? _chunk6XTNI2OQcjs.parseUnits.call(void 0, s, STELLAR_DECIMALS) : 0n;
562
+ } catch (e10) {
409
563
  return 0n;
410
564
  }
411
565
  };
412
- const native = toBase(_optionalChain([lines, 'access', _12 => _12.find, 'call', _13 => _13((b) => b.asset_type === "native"), 'optionalAccess', _14 => _14.balance]));
566
+ const native = toBase(_optionalChain([lines, 'access', _17 => _17.find, 'call', _18 => _18((b) => b.asset_type === "native"), 'optionalAccess', _19 => _19.balance]));
413
567
  if (asset === "native") return { token: native, native };
414
568
  const parts = parseStellarAssetId(asset);
415
569
  const line = parts ? lines.find(
416
570
  (b) => (b.asset_type === "credit_alphanum4" || b.asset_type === "credit_alphanum12") && b.asset_code === parts.code && b.asset_issuer === parts.issuer
417
571
  ) : void 0;
418
- return { token: toBase(_optionalChain([line, 'optionalAccess', _15 => _15.balance])), native };
572
+ return { token: toBase(_optionalChain([line, 'optionalAccess', _20 => _20.balance])), native };
419
573
  },
420
574
  async recipientReady(payTo, asset) {
421
575
  let lines;
@@ -434,6 +588,14 @@ function makeStellarNetwork(preset, rpcUrl) {
434
588
  );
435
589
  return hasTrustline ? { ready: true } : { ready: false, reason: "NO_TRUSTLINE" };
436
590
  },
591
+ /* ---- swap (OPTIONAL, opt-in): a path payment to yourself. See ./swap.ts ---- */
592
+ async quoteSwap({ from, to, wantAmount, slippageBps }) {
593
+ return quoteStellarSwap({ server, network, from, to, wantAmount, slippageBps });
594
+ },
595
+ async swap(wallet, quote) {
596
+ const keypair = resolveStellarWallet(wallet._native);
597
+ return swapStellar({ server, keypair, quote });
598
+ },
437
599
  async verify(_ref, accept) {
438
600
  return verifyStellar({ reader, accept });
439
601
  }