@piprail/sdk 2.16.2 → 3.1.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.
- package/CHANGELOG.md +448 -0
- package/README.md +1 -0
- package/dist/{algorand-Q3TUQLPK.cjs → algorand-4FTTEV7X.cjs} +212 -51
- package/dist/{algorand-25FMBCT3.js → algorand-KJ5XHSMT.js} +164 -3
- package/dist/{aptos-VBJONBFY.cjs → aptos-5QBXJ6NV.cjs} +255 -39
- package/dist/{aptos-SBV6SGDP.js → aptos-H5VLH2QL.js} +217 -1
- package/dist/{chunk-QONQSZHJ.cjs → chunk-6XTNI2OQ.cjs} +44 -44
- package/dist/{chunk-OXEFPLZA.cjs → chunk-6ZRAIQXF.cjs} +4 -4
- package/dist/chunk-GVCGUSTE.js +30 -0
- package/dist/{chunk-V2IJ5HUW.cjs → chunk-MZAJQYM3.cjs} +1 -0
- package/dist/chunk-MZXVXC3C.cjs +30 -0
- package/dist/{chunk-2CX7XRZK.js → chunk-TZDVZCTC.js} +1 -0
- package/dist/{chunk-C52H5TYB.js → chunk-YXBQKBDH.js} +2 -2
- package/dist/index.cjs +2906 -1262
- package/dist/index.d.cts +679 -21
- package/dist/index.d.ts +679 -21
- package/dist/index.js +2678 -1034
- package/dist/{ledger-Crc1bZox.d.cts → ledger-DkHUORUe.d.cts} +7 -0
- package/dist/{ledger-Crc1bZox.d.ts → ledger-DkHUORUe.d.ts} +7 -0
- package/dist/{near-OLKCMTBI.js → near-5X2CQGML.js} +197 -1
- package/dist/{near-5LTTDU6G.cjs → near-XSQXEIHT.cjs} +242 -46
- package/dist/node.d.cts +2 -2
- package/dist/node.d.ts +2 -2
- package/dist/{solana-AI2G7V33.cjs → solana-TIEJV742.cjs} +218 -53
- package/dist/{solana-HTKDRTD3.js → solana-WRXL54MR.js} +174 -9
- package/dist/{stellar-E2KWEV2E.cjs → stellar-5GMZJBTA.cjs} +200 -30
- package/dist/{stellar-EUFZLX6J.js → stellar-YQLOIFDD.js} +172 -2
- package/dist/{sui-KCIITCYH.js → sui-JFQSDNSZ.js} +165 -3
- package/dist/{sui-Q3NJOJZS.cjs → sui-WIZEAO7E.cjs} +185 -23
- package/dist/{ton-J7TQWRN4.cjs → ton-AGTKLQA5.cjs} +264 -22
- package/dist/{ton-WH2JVQOO.js → ton-OZKFNRLT.js} +244 -2
- package/dist/{tron-FXBXDNEY.js → tron-HG3IOOCG.js} +283 -1
- package/dist/{tron-HIPMOX7S.cjs → tron-S4WX7OHY.cjs} +323 -41
- package/dist/{xrpl-RUOB37QH.js → xrpl-5K444RGX.js} +238 -6
- package/dist/{xrpl-SVVS445B.cjs → xrpl-G2FKFXRI.cjs} +289 -57
- package/package.json +12 -2
- package/dist/{chunk-QU25LSVS.js → chunk-5GRBEMCA.js} +44 -44
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } 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
|
|
4
|
-
require('./chunk-
|
|
3
|
+
var _chunk6ZRAIQXFcjs = require('./chunk-6ZRAIQXF.cjs');
|
|
4
|
+
require('./chunk-MZAJQYM3.cjs');
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
var _chunkMZXVXC3Ccjs = require('./chunk-MZXVXC3C.cjs');
|
|
5
8
|
|
|
6
9
|
|
|
7
10
|
var _chunkCQREG5LEcjs = require('./chunk-CQREG5LE.cjs');
|
|
@@ -18,7 +21,8 @@ var _chunkCQREG5LEcjs = require('./chunk-CQREG5LE.cjs');
|
|
|
18
21
|
|
|
19
22
|
|
|
20
23
|
|
|
21
|
-
|
|
24
|
+
|
|
25
|
+
var _chunk6XTNI2OQcjs = require('./chunk-6XTNI2OQ.cjs');
|
|
22
26
|
|
|
23
27
|
// src/drivers/xrpl/index.ts
|
|
24
28
|
var _xrpl = require('xrpl');
|
|
@@ -85,6 +89,13 @@ async function payXrpl(params) {
|
|
|
85
89
|
client.feeDrops(),
|
|
86
90
|
client.currentLedgerIndex()
|
|
87
91
|
]);
|
|
92
|
+
for (const [field, value] of [["Sequence", sequence], ["LastLedgerSequence", ledgerIndex]]) {
|
|
93
|
+
if (!Number.isSafeInteger(value) || value < 0) {
|
|
94
|
+
throw new Error(
|
|
95
|
+
`XRPL: could not read ${field} from the ledger (got ${String(value)}) \u2014 the RPC read failed or was throttled. NOTHING was signed or submitted, so this is safe to retry. A dedicated rpcUrl avoids the public cluster's rate limits.`
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
88
99
|
const tx = {
|
|
89
100
|
TransactionType: "Payment",
|
|
90
101
|
Account: wallet.classicAddress,
|
|
@@ -103,17 +114,17 @@ async function payXrpl(params) {
|
|
|
103
114
|
const code = res.engine_result;
|
|
104
115
|
if (code.startsWith("tes")) return _nullishCoalesce(_optionalChain([res, 'access', _ => _.tx_json, 'optionalAccess', _2 => _2.hash]), () => ( signed.hash));
|
|
105
116
|
const recipientMsg = recipientNotReadyMessage(code);
|
|
106
|
-
if (recipientMsg) throw new (0,
|
|
117
|
+
if (recipientMsg) throw new (0, _chunk6XTNI2OQcjs.RecipientNotReadyError)(recipientMsg, { cause: makeEngineError(res) });
|
|
107
118
|
if (isAffordabilityCode(code)) {
|
|
108
|
-
throw new (0,
|
|
119
|
+
throw new (0, _chunk6XTNI2OQcjs.InsufficientFundsError)(
|
|
109
120
|
`XRPL payment rejected: the sender can't cover it \u2014 balance or the 1 XRP base reserve. (XRPL: ${code})`,
|
|
110
121
|
{ cause: makeEngineError(res) }
|
|
111
122
|
);
|
|
112
123
|
}
|
|
113
124
|
throw makeEngineError(res);
|
|
114
125
|
} catch (err) {
|
|
115
|
-
if (err instanceof
|
|
116
|
-
throw _nullishCoalesce(
|
|
126
|
+
if (err instanceof _chunk6XTNI2OQcjs.InsufficientFundsError || err instanceof _chunk6XTNI2OQcjs.RecipientNotReadyError) throw err;
|
|
127
|
+
throw _nullishCoalesce(_chunk6XTNI2OQcjs.toInsufficientFundsError.call(void 0, err), () => ( err));
|
|
117
128
|
}
|
|
118
129
|
}
|
|
119
130
|
function amountForAccept(accept) {
|
|
@@ -150,6 +161,197 @@ function isAffordabilityCode(code) {
|
|
|
150
161
|
return /^(tecUNFUNDED|tecINSUFF|terINSUF)/.test(code);
|
|
151
162
|
}
|
|
152
163
|
|
|
164
|
+
// src/drivers/xrpl/swap.ts
|
|
165
|
+
var SOURCE = {
|
|
166
|
+
kind: "protocol",
|
|
167
|
+
name: "XRPL DEX + AMM",
|
|
168
|
+
note: "Rate from the ledger\u2019s own order books and AMM pools, read live via ripple_path_find, with auto-bridging through XRP where cheaper. Order books charge no protocol fee; AMM pools charge a per-pool fee (0%\u20131%) paid to the pool."
|
|
169
|
+
};
|
|
170
|
+
function toAmount(t, base) {
|
|
171
|
+
if (t.asset === "native") return base.toString();
|
|
172
|
+
const parts = parseXrplAssetId(t.asset);
|
|
173
|
+
if (!parts) throw new Error(`XRPL: malformed asset id "${t.asset}".`);
|
|
174
|
+
return { currency: parts.currencyHex, issuer: parts.issuer, value: _chunk6XTNI2OQcjs.formatUnits.call(void 0, base, t.decimals) };
|
|
175
|
+
}
|
|
176
|
+
function parseCeil(value, decimals) {
|
|
177
|
+
const [whole = "0", frac = ""] = value.trim().split(".");
|
|
178
|
+
const kept = frac.slice(0, decimals).padEnd(decimals, "0");
|
|
179
|
+
const rest = frac.slice(decimals);
|
|
180
|
+
const base = BigInt(whole + kept);
|
|
181
|
+
return /[1-9]/.test(rest) ? base + 1n : base;
|
|
182
|
+
}
|
|
183
|
+
function fromAmount(t, a) {
|
|
184
|
+
if (a == null) return null;
|
|
185
|
+
try {
|
|
186
|
+
return typeof a === "string" ? BigInt(a) : parseCeil(a.value, t.decimals);
|
|
187
|
+
} catch (e2) {
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
function sourceCurrency(t) {
|
|
192
|
+
if (t.asset === "native") return { currency: "XRP" };
|
|
193
|
+
const parts = parseXrplAssetId(t.asset);
|
|
194
|
+
if (!parts) throw new Error(`XRPL: malformed asset id "${t.asset}".`);
|
|
195
|
+
return { currency: parts.currencyHex, issuer: parts.issuer };
|
|
196
|
+
}
|
|
197
|
+
function side(t, amount) {
|
|
198
|
+
return {
|
|
199
|
+
asset: t.asset,
|
|
200
|
+
symbol: _nullishCoalesce(t.symbol, () => ( (t.asset === "native" ? XRP_SYMBOL : t.asset))),
|
|
201
|
+
decimals: t.asset === "native" ? XRP_DECIMALS : t.decimals,
|
|
202
|
+
amount: amount.toString(),
|
|
203
|
+
amountFormatted: _chunk6XTNI2OQcjs.formatUnits.call(void 0, amount, t.asset === "native" ? XRP_DECIMALS : t.decimals)
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
async function quoteXrplSwap(p) {
|
|
207
|
+
if (p.from.asset === p.to.asset) return null;
|
|
208
|
+
if (p.wantAmount <= 0n) return null;
|
|
209
|
+
let alternatives = [];
|
|
210
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
211
|
+
try {
|
|
212
|
+
const res = await p.client.pathFind({
|
|
213
|
+
source_account: p.owner,
|
|
214
|
+
destination_account: p.owner,
|
|
215
|
+
// ← ourselves: this is what makes it a swap
|
|
216
|
+
destination_amount: toAmount(p.to, p.wantAmount),
|
|
217
|
+
source_currencies: [sourceCurrency(p.from)]
|
|
218
|
+
});
|
|
219
|
+
alternatives = _nullishCoalesce(res.alternatives, () => ( []));
|
|
220
|
+
} catch (e3) {
|
|
221
|
+
alternatives = [];
|
|
222
|
+
}
|
|
223
|
+
if (alternatives.length) break;
|
|
224
|
+
if (attempt === 0) await new Promise((r) => setTimeout(r, 600));
|
|
225
|
+
}
|
|
226
|
+
if (!alternatives.length) return null;
|
|
227
|
+
let best = null;
|
|
228
|
+
let bestSpend = null;
|
|
229
|
+
for (const alt of alternatives) {
|
|
230
|
+
const spend = fromAmount(p.from, alt.source_amount);
|
|
231
|
+
if (spend == null || spend <= 0n) continue;
|
|
232
|
+
if (bestSpend == null || spend < bestSpend) {
|
|
233
|
+
bestSpend = spend;
|
|
234
|
+
best = alt;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
if (!best || bestSpend == null) return null;
|
|
238
|
+
const maxSpend = _chunkMZXVXC3Ccjs.applySlippage.call(void 0, bestSpend, p.slippageBps);
|
|
239
|
+
return {
|
|
240
|
+
source: SOURCE,
|
|
241
|
+
network: p.network,
|
|
242
|
+
from: side(p.from, bestSpend),
|
|
243
|
+
to: side(p.to, p.wantAmount),
|
|
244
|
+
maxSpend: maxSpend.toString(),
|
|
245
|
+
maxSpendFormatted: _chunk6XTNI2OQcjs.formatUnits.call(void 0, maxSpend, p.from.asset === "native" ? XRP_DECIMALS : p.from.decimals),
|
|
246
|
+
slippageBps: p.slippageBps,
|
|
247
|
+
// `paths_computed` drops straight into the transaction's Paths field.
|
|
248
|
+
route: { paths: _nullishCoalesce(best.paths_computed, () => ( [])), from: p.from, to: p.to }
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
function sanitizePaths(paths) {
|
|
252
|
+
if (!Array.isArray(paths)) return [];
|
|
253
|
+
return paths.map(
|
|
254
|
+
(path) => (Array.isArray(path) ? path : []).map((raw) => {
|
|
255
|
+
const step = raw;
|
|
256
|
+
const clean = {};
|
|
257
|
+
if (typeof step.account === "string") clean.account = step.account;
|
|
258
|
+
if (typeof step.currency === "string") clean.currency = step.currency;
|
|
259
|
+
if (typeof step.issuer === "string") clean.issuer = step.issuer;
|
|
260
|
+
return clean;
|
|
261
|
+
}).filter((step) => Object.keys(step).length > 0)
|
|
262
|
+
).filter((path) => path.length > 0);
|
|
263
|
+
}
|
|
264
|
+
async function swapXrpl(p) {
|
|
265
|
+
const { client, wallet, quote } = p;
|
|
266
|
+
const route = quote.route;
|
|
267
|
+
if (!_optionalChain([route, 'optionalAccess', _3 => _3.from]) || !_optionalChain([route, 'optionalAccess', _4 => _4.to])) {
|
|
268
|
+
throw new Error("XRPL: swap quote is missing its routing data \u2014 re-quote before swapping.");
|
|
269
|
+
}
|
|
270
|
+
try {
|
|
271
|
+
const [sequence, feeDrops, ledgerIndex] = await Promise.all([
|
|
272
|
+
client.accountSequence(wallet.classicAddress),
|
|
273
|
+
client.feeDrops(),
|
|
274
|
+
client.currentLedgerIndex()
|
|
275
|
+
]);
|
|
276
|
+
const tx = {
|
|
277
|
+
TransactionType: "Payment",
|
|
278
|
+
Account: wallet.classicAddress,
|
|
279
|
+
Destination: wallet.classicAddress,
|
|
280
|
+
// ← ourselves: the ledger's own swap idiom
|
|
281
|
+
Amount: toAmount(route.to, BigInt(quote.to.amount)),
|
|
282
|
+
// exact output
|
|
283
|
+
SendMax: toAmount(route.from, BigInt(quote.maxSpend)),
|
|
284
|
+
// the on-chain slippage cap
|
|
285
|
+
// Sanitized: raw path steps from ripple_path_find can break xrpl.js encoding.
|
|
286
|
+
...sanitizePaths(route.paths).length ? { Paths: sanitizePaths(route.paths) } : {},
|
|
287
|
+
Sequence: sequence,
|
|
288
|
+
Fee: feeForSubmit2(feeDrops),
|
|
289
|
+
LastLedgerSequence: ledgerIndex + 20,
|
|
290
|
+
// NOT tfPartialPayment: we want the full `Amount` delivered or nothing at all.
|
|
291
|
+
Flags: 0
|
|
292
|
+
};
|
|
293
|
+
let signed;
|
|
294
|
+
try {
|
|
295
|
+
signed = wallet.sign(tx);
|
|
296
|
+
} catch (cause) {
|
|
297
|
+
const shape = Object.fromEntries(
|
|
298
|
+
Object.entries(tx).map(([k, v]) => [k, typeof v === "object" ? JSON.stringify(v) : `${typeof v}:${String(v)}`])
|
|
299
|
+
);
|
|
300
|
+
throw new Error(
|
|
301
|
+
`XRPL could not encode the swap transaction: ${String(_nullishCoalesce(_optionalChain([cause, 'optionalAccess', _5 => _5.message]), () => ( cause)))}. Transaction was ${JSON.stringify(shape)}`,
|
|
302
|
+
{ cause }
|
|
303
|
+
);
|
|
304
|
+
}
|
|
305
|
+
const res = await client.submit(signed.tx_blob);
|
|
306
|
+
const code = res.engine_result;
|
|
307
|
+
if (code.startsWith("tes")) {
|
|
308
|
+
return {
|
|
309
|
+
transaction: _nullishCoalesce(_optionalChain([res, 'access', _6 => _6.tx_json, 'optionalAccess', _7 => _7.hash]), () => ( signed.hash)),
|
|
310
|
+
network: quote.network,
|
|
311
|
+
source: quote.source,
|
|
312
|
+
from: quote.from,
|
|
313
|
+
to: quote.to
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
throw mapEngineResult(code, res);
|
|
317
|
+
} catch (err) {
|
|
318
|
+
if (err instanceof _chunk6XTNI2OQcjs.InsufficientFundsError || err instanceof _chunk6XTNI2OQcjs.RecipientNotReadyError) throw err;
|
|
319
|
+
throw _nullishCoalesce(_chunk6XTNI2OQcjs.toInsufficientFundsError.call(void 0, err), () => ( err));
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
function feeForSubmit2(openLedgerFee) {
|
|
323
|
+
try {
|
|
324
|
+
const f = BigInt(openLedgerFee);
|
|
325
|
+
const padded = f * 2n;
|
|
326
|
+
return (padded < 10n ? 10n : padded).toString();
|
|
327
|
+
} catch (e4) {
|
|
328
|
+
return "12";
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
function mapEngineResult(code, res) {
|
|
332
|
+
const err = new Error(`XRPL swap rejected: ${code}`);
|
|
333
|
+
err.cause = res;
|
|
334
|
+
if (code === "tecPATH_PARTIAL" || code === "tecPATH_DRY") {
|
|
335
|
+
return new (0, _chunk6XTNI2OQcjs.InsufficientFundsError)(
|
|
336
|
+
`XRPL swap refused: the price moved past your slippage cap, or the path ran dry, so nothing was spent. Re-quote and retry, or raise slippageBps. (XRPL: ${code})`,
|
|
337
|
+
{ cause: res }
|
|
338
|
+
);
|
|
339
|
+
}
|
|
340
|
+
if (code === "tecNO_LINE" || code === "tecNO_AUTH" || code === "tecNO_ISSUER") {
|
|
341
|
+
return new (0, _chunk6XTNI2OQcjs.RecipientNotReadyError)(
|
|
342
|
+
`XRPL swap refused: your account needs a trustline for the currency you're swapping INTO before it can hold it. (XRPL: ${code})`,
|
|
343
|
+
{ cause: res }
|
|
344
|
+
);
|
|
345
|
+
}
|
|
346
|
+
if (code === "tecUNFUNDED_PAYMENT" || code === "terINSUF_FEE_B" || code === "tecINSUFF_FEE") {
|
|
347
|
+
return new (0, _chunk6XTNI2OQcjs.InsufficientFundsError)(
|
|
348
|
+
`XRPL swap failed: the account can't cover it \u2014 balance or the 1 XRP base reserve. (XRPL: ${code})`,
|
|
349
|
+
{ cause: res }
|
|
350
|
+
);
|
|
351
|
+
}
|
|
352
|
+
return err;
|
|
353
|
+
}
|
|
354
|
+
|
|
153
355
|
// src/drivers/xrpl/exact.ts
|
|
154
356
|
var _crypto = require('crypto');
|
|
155
357
|
var SECONDS_PER_LEDGER = 4;
|
|
@@ -165,12 +367,12 @@ var MAX_FEE_DROPS = 1e6;
|
|
|
165
367
|
var TF_FULLY_CANONICAL_SIG = 2147483648;
|
|
166
368
|
var TF_PARTIAL_PAYMENT = 131072;
|
|
167
369
|
function feesAreSponsored(accept) {
|
|
168
|
-
return _optionalChain([accept, 'access',
|
|
370
|
+
return _optionalChain([accept, 'access', _8 => _8.extra, 'optionalAccess', _9 => _9.areFeesSponsored]) === true;
|
|
169
371
|
}
|
|
170
372
|
function invoiceIdHash(invoiceId) {
|
|
171
373
|
return _crypto.createHash.call(void 0, "sha256").update(invoiceId, "utf8").digest("hex").toUpperCase();
|
|
172
374
|
}
|
|
173
|
-
function
|
|
375
|
+
function feeForSubmit3(openLedgerFee) {
|
|
174
376
|
const fee = Number(openLedgerFee);
|
|
175
377
|
const chosen = Number.isFinite(fee) && fee > MIN_FEE_DROPS ? Math.ceil(fee) : MIN_FEE_DROPS;
|
|
176
378
|
return String(Math.min(chosen, MAX_FEE_DROPS));
|
|
@@ -178,23 +380,23 @@ function feeForSubmit2(openLedgerFee) {
|
|
|
178
380
|
async function payExactXrpl(input) {
|
|
179
381
|
const { client, wallet, accept } = input;
|
|
180
382
|
if (!isXrpNative(accept.asset)) {
|
|
181
|
-
throw new (0,
|
|
383
|
+
throw new (0, _chunk6XTNI2OQcjs.UnsupportedSchemeError)(
|
|
182
384
|
`XRPL exact currently signs native XRP only \u2014 ${accept.asset} is an issued currency, whose wire amount is a decimal rather than base units and would misprice the spend cap. Pay it via onchain-proof.`
|
|
183
385
|
);
|
|
184
386
|
}
|
|
185
387
|
if (feesAreSponsored(accept)) {
|
|
186
|
-
throw new (0,
|
|
388
|
+
throw new (0, _chunk6XTNI2OQcjs.UnsupportedSchemeError)(
|
|
187
389
|
"XRPL exact rail advertises areFeesSponsored:true, but the XRP Ledger charges the fee to the transaction Account \u2014 the scheme requires false and PipRail cannot honour a sponsor here."
|
|
188
390
|
);
|
|
189
391
|
}
|
|
190
|
-
const method =
|
|
392
|
+
const method = _chunk6ZRAIQXFcjs.exactTransferMethod.call(void 0, accept, "xrpl");
|
|
191
393
|
if (method !== "sequence") {
|
|
192
|
-
throw new (0,
|
|
394
|
+
throw new (0, _chunk6XTNI2OQcjs.UnsupportedSchemeError)(
|
|
193
395
|
`XRPL exact: unsupported assetTransferMethod "${method}". Only "sequence" is signable \u2014 "ticketSequence" needs a Ticket pre-minted on the payer account, which PipRail does not manage.`
|
|
194
396
|
);
|
|
195
397
|
}
|
|
196
398
|
if (!/^[0-9]+$/.test(accept.amount)) {
|
|
197
|
-
throw new (0,
|
|
399
|
+
throw new (0, _chunk6XTNI2OQcjs.UnsupportedSchemeError)(
|
|
198
400
|
`XRPL exact: native amount "${accept.amount}" is not an integer drops string.`
|
|
199
401
|
);
|
|
200
402
|
}
|
|
@@ -209,8 +411,8 @@ async function payExactXrpl(input) {
|
|
|
209
411
|
client.currentLedgerIndex()
|
|
210
412
|
]);
|
|
211
413
|
} catch (err) {
|
|
212
|
-
if (/actNotFound/i.test(String(_nullishCoalesce(_optionalChain([err, 'optionalAccess',
|
|
213
|
-
throw new (0,
|
|
414
|
+
if (/actNotFound/i.test(String(_nullishCoalesce(_optionalChain([err, 'optionalAccess', _10 => _10.message]), () => ( err))))) {
|
|
415
|
+
throw new (0, _chunk6XTNI2OQcjs.InsufficientFundsError)(
|
|
214
416
|
`XRPL exact: the payer account ${wallet.classicAddress} does not exist on the ledger. An XRPL account must hold the base reserve (currently 1 XRP) before it can send anything \u2014 fund it first.`,
|
|
215
417
|
{ cause: err instanceof Error ? err : new Error(String(err)) }
|
|
216
418
|
);
|
|
@@ -224,25 +426,25 @@ async function payExactXrpl(input) {
|
|
|
224
426
|
Amount: accept.amount,
|
|
225
427
|
// integer drops, verbatim from the trusted accept
|
|
226
428
|
Sequence: sequence,
|
|
227
|
-
Fee:
|
|
429
|
+
Fee: feeForSubmit3(openLedgerFee),
|
|
228
430
|
LastLedgerSequence: ledgerIndex + ledgerWindowFor(accept.maxTimeoutSeconds),
|
|
229
431
|
// tfFullyCanonicalSig ON, tfPartialPayment OFF — the shape every other XRPL client sends.
|
|
230
432
|
Flags: TF_FULLY_CANONICAL_SIG
|
|
231
433
|
};
|
|
232
|
-
if (typeof _optionalChain([accept, 'access',
|
|
434
|
+
if (typeof _optionalChain([accept, 'access', _11 => _11.extra, 'optionalAccess', _12 => _12.destinationTag]) === "number") {
|
|
233
435
|
tx.DestinationTag = accept.extra.destinationTag;
|
|
234
436
|
}
|
|
235
|
-
if (typeof _optionalChain([accept, 'access',
|
|
437
|
+
if (typeof _optionalChain([accept, 'access', _13 => _13.extra, 'optionalAccess', _14 => _14.sourceTag]) === "number") {
|
|
236
438
|
tx.SourceTag = accept.extra.sourceTag;
|
|
237
439
|
}
|
|
238
|
-
if (typeof _optionalChain([accept, 'access',
|
|
440
|
+
if (typeof _optionalChain([accept, 'access', _15 => _15.extra, 'optionalAccess', _16 => _16.invoiceId]) === "string" && accept.extra.invoiceId.length > 0) {
|
|
239
441
|
tx.InvoiceID = invoiceIdHash(accept.extra.invoiceId);
|
|
240
442
|
}
|
|
241
443
|
let signed;
|
|
242
444
|
try {
|
|
243
445
|
signed = wallet.sign(tx);
|
|
244
446
|
} catch (err) {
|
|
245
|
-
throw new (0,
|
|
447
|
+
throw new (0, _chunk6XTNI2OQcjs.UnsupportedSchemeError)(
|
|
246
448
|
`XRPL exact: could not sign this rail \u2014 ${err instanceof Error ? err.message : String(err)}`,
|
|
247
449
|
{ cause: err instanceof Error ? err : new Error(String(err)) }
|
|
248
450
|
);
|
|
@@ -262,7 +464,7 @@ async function verifyAndSettleExactXrpl(input) {
|
|
|
262
464
|
const attempts = _nullishCoalesce(input.pollAttempts, () => ( 8));
|
|
263
465
|
const sleep = _nullishCoalesce(input.sleep, () => ( ((ms) => new Promise((r) => setTimeout(r, ms)))));
|
|
264
466
|
if (feesAreSponsored(accept)) {
|
|
265
|
-
throw new (0,
|
|
467
|
+
throw new (0, _chunk6XTNI2OQcjs.SettlementError)("XRPL exact: rail advertises areFeesSponsored:true, which this ledger cannot honour.");
|
|
266
468
|
}
|
|
267
469
|
let tx;
|
|
268
470
|
try {
|
|
@@ -295,10 +497,10 @@ async function verifyAndSettleExactXrpl(input) {
|
|
|
295
497
|
if (tx.Amount !== accept.amount) {
|
|
296
498
|
return fail("amount_too_low", `XRPL exact: Amount ${String(tx.Amount)} \u2260 the rail's ${accept.amount} drops.`);
|
|
297
499
|
}
|
|
298
|
-
if (typeof _optionalChain([accept, 'access',
|
|
500
|
+
if (typeof _optionalChain([accept, 'access', _17 => _17.extra, 'optionalAccess', _18 => _18.destinationTag]) === "number" && tx.DestinationTag !== accept.extra.destinationTag) {
|
|
299
501
|
return fail("signature_invalid", `XRPL exact: DestinationTag ${String(tx.DestinationTag)} \u2260 the rail's ${accept.extra.destinationTag}.`);
|
|
300
502
|
}
|
|
301
|
-
if (typeof _optionalChain([accept, 'access',
|
|
503
|
+
if (typeof _optionalChain([accept, 'access', _19 => _19.extra, 'optionalAccess', _20 => _20.invoiceId]) === "string" && accept.extra.invoiceId.length > 0) {
|
|
302
504
|
const want = invoiceIdHash(accept.extra.invoiceId);
|
|
303
505
|
if (String(_nullishCoalesce(tx.InvoiceID, () => ( ""))).toUpperCase() !== want) {
|
|
304
506
|
return fail("signature_invalid", "XRPL exact: InvoiceID does not bind this challenge.");
|
|
@@ -317,24 +519,24 @@ async function verifyAndSettleExactXrpl(input) {
|
|
|
317
519
|
`XRPL exact: submit rejected \u2014 ${res.engine_result}${res.engine_result_message ? ` (${res.engine_result_message})` : ""}.`
|
|
318
520
|
);
|
|
319
521
|
}
|
|
320
|
-
hash = _nullishCoalesce(_optionalChain([res, 'access',
|
|
522
|
+
hash = _nullishCoalesce(_optionalChain([res, 'access', _21 => _21.tx_json, 'optionalAccess', _22 => _22.hash]), () => ( ""));
|
|
321
523
|
if (!hash) throw new Error("submit returned no transaction hash");
|
|
322
524
|
} catch (err) {
|
|
323
|
-
throw new (0,
|
|
525
|
+
throw new (0, _chunk6XTNI2OQcjs.SettlementError)(`XRPL exact: submit failed (${err instanceof Error ? err.message : String(err)}).`);
|
|
324
526
|
}
|
|
325
527
|
for (let i = 0; i < attempts; i += 1) {
|
|
326
528
|
let record;
|
|
327
529
|
try {
|
|
328
530
|
record = await client.txByHash(hash);
|
|
329
|
-
} catch (
|
|
531
|
+
} catch (e5) {
|
|
330
532
|
record = null;
|
|
331
533
|
}
|
|
332
|
-
if (_optionalChain([record, 'optionalAccess',
|
|
333
|
-
const code = _optionalChain([record, 'access',
|
|
534
|
+
if (_optionalChain([record, 'optionalAccess', _23 => _23.validated])) {
|
|
535
|
+
const code = _optionalChain([record, 'access', _24 => _24.meta, 'optionalAccess', _25 => _25.TransactionResult]);
|
|
334
536
|
if (code !== "tesSUCCESS") {
|
|
335
537
|
return fail("transfer_not_found", `XRPL exact: validated with ${String(code)}, not tesSUCCESS.`);
|
|
336
538
|
}
|
|
337
|
-
const delivered = _optionalChain([record, 'access',
|
|
539
|
+
const delivered = _optionalChain([record, 'access', _26 => _26.meta, 'optionalAccess', _27 => _27.delivered_amount]);
|
|
338
540
|
if (delivered !== void 0 && typeof delivered === "string" && delivered !== accept.amount) {
|
|
339
541
|
return fail("amount_too_low", `XRPL exact: delivered ${delivered} drops, expected ${accept.amount}.`);
|
|
340
542
|
}
|
|
@@ -355,7 +557,7 @@ async function verifyAndSettleExactXrpl(input) {
|
|
|
355
557
|
}
|
|
356
558
|
await sleep(1200);
|
|
357
559
|
}
|
|
358
|
-
throw new (0,
|
|
560
|
+
throw new (0, _chunk6XTNI2OQcjs.SettlementError)(
|
|
359
561
|
`XRPL exact: submitted ${hash} but it was not validated within ${attempts} polls. It may still settle; retry the request.`
|
|
360
562
|
);
|
|
361
563
|
}
|
|
@@ -371,7 +573,7 @@ async function verifyXrpl(params) {
|
|
|
371
573
|
let txs;
|
|
372
574
|
try {
|
|
373
575
|
txs = await reader.transactionsForAccount(accept.payTo, 200);
|
|
374
|
-
} catch (
|
|
576
|
+
} catch (e6) {
|
|
375
577
|
return rpcFailed(nonce);
|
|
376
578
|
}
|
|
377
579
|
const tx = txs.find(
|
|
@@ -435,7 +637,7 @@ async function verifyXrpl(params) {
|
|
|
435
637
|
}
|
|
436
638
|
function hasNonceMemo(memos, wantMemo) {
|
|
437
639
|
if (!memos) return false;
|
|
438
|
-
return memos.some((m) => (_nullishCoalesce(_optionalChain([m, 'access',
|
|
640
|
+
return memos.some((m) => (_nullishCoalesce(_optionalChain([m, 'access', _28 => _28.Memo, 'optionalAccess', _29 => _29.MemoData]), () => ( ""))).toUpperCase() === wantMemo);
|
|
439
641
|
}
|
|
440
642
|
function deliveredBaseUnits(delivered, want, decimals) {
|
|
441
643
|
if (delivered === void 0) return null;
|
|
@@ -449,8 +651,8 @@ function deliveredBaseUnits(delivered, want, decimals) {
|
|
|
449
651
|
return null;
|
|
450
652
|
}
|
|
451
653
|
try {
|
|
452
|
-
return
|
|
453
|
-
} catch (
|
|
654
|
+
return _chunk6XTNI2OQcjs.floorUnits.call(void 0, delivered.value, decimals);
|
|
655
|
+
} catch (e7) {
|
|
454
656
|
return null;
|
|
455
657
|
}
|
|
456
658
|
}
|
|
@@ -473,13 +675,13 @@ function rpcFailed(nonce) {
|
|
|
473
675
|
|
|
474
676
|
function assertXrplWallet(wallet, network) {
|
|
475
677
|
if (typeof wallet !== "object" || wallet === null) {
|
|
476
|
-
throw new (0,
|
|
678
|
+
throw new (0, _chunk6XTNI2OQcjs.WrongFamilyError)(
|
|
477
679
|
`chain ${network} is XRPL; wallet must be { key } (s\u2026 seed) or { wallet }.`
|
|
478
680
|
);
|
|
479
681
|
}
|
|
480
|
-
|
|
682
|
+
_chunk6XTNI2OQcjs.assertNoLegacyWalletKey.call(void 0, wallet, "XRPL");
|
|
481
683
|
if (!("key" in wallet) && !("wallet" in wallet)) {
|
|
482
|
-
throw new (0,
|
|
684
|
+
throw new (0, _chunk6XTNI2OQcjs.WrongFamilyError)(
|
|
483
685
|
`chain ${network} is XRPL; wallet must be { key } (s\u2026 seed) or { wallet }.`
|
|
484
686
|
);
|
|
485
687
|
}
|
|
@@ -489,17 +691,19 @@ function resolveXrplWallet(config) {
|
|
|
489
691
|
if (config.wallet) return config.wallet;
|
|
490
692
|
if (config.key) {
|
|
491
693
|
if (!_xrpl.isValidSecret.call(void 0, config.key)) {
|
|
492
|
-
throw new (0,
|
|
694
|
+
throw new (0, _chunk6XTNI2OQcjs.WrongFamilyError)("XRPL wallet { key } is not a valid s\u2026 secret seed.");
|
|
493
695
|
}
|
|
494
696
|
return _xrpl.Wallet.fromSeed(config.key);
|
|
495
697
|
}
|
|
496
|
-
throw new (0,
|
|
698
|
+
throw new (0, _chunk6XTNI2OQcjs.WrongFamilyError)("XRPL wallet needs { key } (s\u2026 seed) or { wallet }.");
|
|
497
699
|
}
|
|
498
700
|
|
|
499
701
|
// src/drivers/xrpl/index.ts
|
|
500
702
|
function isXrplActNotFound(e) {
|
|
501
|
-
return /actNotFound/i.test(String(_nullishCoalesce(_optionalChain([e, 'optionalAccess',
|
|
703
|
+
return /actNotFound/i.test(String(_nullishCoalesce(_optionalChain([e, 'optionalAccess', _30 => _30.message]), () => ( e))));
|
|
502
704
|
}
|
|
705
|
+
var XRPL_BASE_RESERVE_DROPS = 1000000n;
|
|
706
|
+
var XRPL_OWNER_RESERVE_DROPS = 200000n;
|
|
503
707
|
var xrplDriver = {
|
|
504
708
|
family: "xrpl",
|
|
505
709
|
resolve(opts) {
|
|
@@ -520,11 +724,14 @@ function makeXrplNetwork(preset, rpcUrl) {
|
|
|
520
724
|
const json = await res.json();
|
|
521
725
|
const result = json.result;
|
|
522
726
|
if (!result || result.status === "error" || result.error) {
|
|
523
|
-
throw new Error(`XRPL RPC ${method} error: ${_nullishCoalesce(_optionalChain([result, 'optionalAccess',
|
|
727
|
+
throw new Error(`XRPL RPC ${method} error: ${_nullishCoalesce(_optionalChain([result, 'optionalAccess', _31 => _31.error]), () => ( "unknown"))}`);
|
|
524
728
|
}
|
|
525
729
|
return result;
|
|
526
730
|
}
|
|
527
731
|
const payClient = {
|
|
732
|
+
async pathFind(params) {
|
|
733
|
+
return rpc("ripple_path_find", { ...params, ledger_index: "current" });
|
|
734
|
+
},
|
|
528
735
|
async accountSequence(account) {
|
|
529
736
|
const r = await rpc("account_info", {
|
|
530
737
|
account,
|
|
@@ -549,7 +756,7 @@ function makeXrplNetwork(preset, rpcUrl) {
|
|
|
549
756
|
async txByHash(hash) {
|
|
550
757
|
try {
|
|
551
758
|
return await rpc("tx", { transaction: hash, binary: false });
|
|
552
|
-
} catch (
|
|
759
|
+
} catch (e8) {
|
|
553
760
|
return null;
|
|
554
761
|
}
|
|
555
762
|
}
|
|
@@ -578,7 +785,7 @@ function makeXrplNetwork(preset, rpcUrl) {
|
|
|
578
785
|
const info = preset.tokens[token.toUpperCase()];
|
|
579
786
|
if (!info) {
|
|
580
787
|
const known = Object.keys(preset.tokens).join(", ") || "(none built in)";
|
|
581
|
-
throw new (0,
|
|
788
|
+
throw new (0, _chunk6XTNI2OQcjs.UnknownTokenError)(
|
|
582
789
|
`token "${token}" isn't built in for XRPL (known: ${known}). Pass { issuer, currencyHex, decimals } for a custom IOU, or use 'native'.`
|
|
583
790
|
);
|
|
584
791
|
}
|
|
@@ -588,10 +795,10 @@ function makeXrplNetwork(preset, rpcUrl) {
|
|
|
588
795
|
symbol: info.symbol
|
|
589
796
|
};
|
|
590
797
|
}
|
|
591
|
-
|
|
798
|
+
_chunk6XTNI2OQcjs.rejectForeignToken.call(void 0, token, "xrpl", network);
|
|
592
799
|
const t = token;
|
|
593
800
|
if (!t.issuer || !t.currencyHex || typeof t.decimals !== "number") {
|
|
594
|
-
throw new (0,
|
|
801
|
+
throw new (0, _chunk6XTNI2OQcjs.WrongFamilyError)(
|
|
595
802
|
`chain ${network} is XRPL; a custom token must be { issuer, currencyHex, decimals }.`
|
|
596
803
|
);
|
|
597
804
|
}
|
|
@@ -612,12 +819,12 @@ function makeXrplNetwork(preset, rpcUrl) {
|
|
|
612
819
|
},
|
|
613
820
|
assertValidPayTo(payTo) {
|
|
614
821
|
if (payTo.startsWith("0x")) {
|
|
615
|
-
throw new (0,
|
|
822
|
+
throw new (0, _chunk6XTNI2OQcjs.WrongFamilyError)(
|
|
616
823
|
`chain ${network} is XRPL, but payTo "${payTo}" looks like an EVM address.`
|
|
617
824
|
);
|
|
618
825
|
}
|
|
619
826
|
if (!_xrpl.isValidClassicAddress.call(void 0, payTo)) {
|
|
620
|
-
throw new (0,
|
|
827
|
+
throw new (0, _chunk6XTNI2OQcjs.WrongFamilyError)(
|
|
621
828
|
`chain ${network} is XRPL, but payTo "${payTo}" is not a valid XRPL account (r\u2026).`
|
|
622
829
|
);
|
|
623
830
|
}
|
|
@@ -685,26 +892,26 @@ function makeXrplNetwork(preset, rpcUrl) {
|
|
|
685
892
|
transaction: ref
|
|
686
893
|
});
|
|
687
894
|
if (tx.validated) return { height: String(_nullishCoalesce(tx.ledger_index, () => ( 0))) };
|
|
688
|
-
} catch (
|
|
895
|
+
} catch (e9) {
|
|
689
896
|
}
|
|
690
897
|
await _chunkCQREG5LEcjs.delay.call(void 0, 1500);
|
|
691
898
|
}
|
|
692
|
-
throw new (0,
|
|
899
|
+
throw new (0, _chunk6XTNI2OQcjs.ConfirmationTimeoutError)(`XRPL tx ${ref} not validated on-ledger in time.`);
|
|
693
900
|
},
|
|
694
901
|
async estimateCost() {
|
|
695
902
|
try {
|
|
696
903
|
const drops = await payClient.feeDrops();
|
|
697
904
|
const n = Number(drops);
|
|
698
905
|
const fee = BigInt(Number.isFinite(n) && n > 12 ? Math.ceil(n) : 12);
|
|
699
|
-
return
|
|
906
|
+
return _chunk6XTNI2OQcjs.nativeCost.call(void 0, {
|
|
700
907
|
symbol: XRP_SYMBOL,
|
|
701
908
|
decimals: XRP_DECIMALS,
|
|
702
909
|
fee,
|
|
703
910
|
basis: "estimated",
|
|
704
911
|
detail: `network fee ${fee} drops`
|
|
705
912
|
});
|
|
706
|
-
} catch (
|
|
707
|
-
return
|
|
913
|
+
} catch (e10) {
|
|
914
|
+
return _chunk6XTNI2OQcjs.nativeCost.call(void 0, {
|
|
708
915
|
symbol: XRP_SYMBOL,
|
|
709
916
|
decimals: XRP_DECIMALS,
|
|
710
917
|
fee: 12n,
|
|
@@ -713,24 +920,35 @@ function makeXrplNetwork(preset, rpcUrl) {
|
|
|
713
920
|
});
|
|
714
921
|
}
|
|
715
922
|
},
|
|
923
|
+
/** The bound wallet's own address — where THIS wallet gets paid. Derived from the key
|
|
924
|
+
* material only: no RPC, nothing moved. See {@link ResolvedNetwork.addressOf}. */
|
|
925
|
+
async addressOf(wallet) {
|
|
926
|
+
return resolveXrplWallet(wallet._native).classicAddress;
|
|
927
|
+
},
|
|
716
928
|
async balanceOf(wallet, asset) {
|
|
717
929
|
let owner;
|
|
718
930
|
try {
|
|
719
931
|
owner = resolveXrplWallet(wallet._native).classicAddress;
|
|
720
|
-
} catch (
|
|
932
|
+
} catch (e11) {
|
|
721
933
|
return { token: null, native: null };
|
|
722
934
|
}
|
|
723
935
|
let native = null;
|
|
936
|
+
let ownerCount = 0n;
|
|
724
937
|
try {
|
|
725
938
|
const r = await rpc("account_info", {
|
|
726
939
|
account: owner,
|
|
727
940
|
ledger_index: "validated"
|
|
728
941
|
});
|
|
729
942
|
native = BigInt(r.account_data.Balance);
|
|
943
|
+
ownerCount = BigInt(_nullishCoalesce(r.account_data.OwnerCount, () => ( 0)));
|
|
730
944
|
} catch (e) {
|
|
731
945
|
native = isXrplActNotFound(e) ? 0n : null;
|
|
732
946
|
}
|
|
733
|
-
if (isXrpNative(asset))
|
|
947
|
+
if (isXrpNative(asset)) {
|
|
948
|
+
if (native === null) return { token: null, native };
|
|
949
|
+
const reserve = XRPL_BASE_RESERVE_DROPS + XRPL_OWNER_RESERVE_DROPS * ownerCount;
|
|
950
|
+
return { token: native > reserve ? native - reserve : 0n, native };
|
|
951
|
+
}
|
|
734
952
|
let token = null;
|
|
735
953
|
try {
|
|
736
954
|
const [currencyHex, issuer] = asset.split(":");
|
|
@@ -741,7 +959,7 @@ function makeXrplNetwork(preset, rpcUrl) {
|
|
|
741
959
|
const line = r.lines.find(
|
|
742
960
|
(l) => l.currency.toUpperCase() === (_nullishCoalesce(currencyHex, () => ( ""))).toUpperCase() && l.account === issuer
|
|
743
961
|
);
|
|
744
|
-
token = line ?
|
|
962
|
+
token = line ? _chunk6XTNI2OQcjs.floorUnits.call(void 0, line.balance, XRP_DECIMALS) : 0n;
|
|
745
963
|
} catch (e) {
|
|
746
964
|
token = isXrplActNotFound(e) ? 0n : null;
|
|
747
965
|
}
|
|
@@ -765,10 +983,24 @@ function makeXrplNetwork(preset, rpcUrl) {
|
|
|
765
983
|
(l) => l.currency.toUpperCase() === (_nullishCoalesce(currencyHex, () => ( ""))).toUpperCase() && l.account === issuer
|
|
766
984
|
);
|
|
767
985
|
return has ? { ready: true } : { ready: false, reason: "NO_TRUSTLINE" };
|
|
768
|
-
} catch (
|
|
986
|
+
} catch (e12) {
|
|
769
987
|
return { ready: "unknown" };
|
|
770
988
|
}
|
|
771
989
|
},
|
|
990
|
+
/* ---- swap (OPTIONAL, opt-in): a cross-currency payment to yourself. See ./swap.ts ---- */
|
|
991
|
+
async quoteSwap({ from, to, wantAmount, slippageBps, wallet }) {
|
|
992
|
+
let owner;
|
|
993
|
+
try {
|
|
994
|
+
owner = resolveXrplWallet(wallet._native).classicAddress;
|
|
995
|
+
} catch (e13) {
|
|
996
|
+
return null;
|
|
997
|
+
}
|
|
998
|
+
return quoteXrplSwap({ client: payClient, network, owner, from, to, wantAmount, slippageBps });
|
|
999
|
+
},
|
|
1000
|
+
async swap(wallet, quote) {
|
|
1001
|
+
const w = resolveXrplWallet(wallet._native);
|
|
1002
|
+
return swapXrpl({ client: payClient, wallet: w, quote });
|
|
1003
|
+
},
|
|
772
1004
|
async verify(_ref, accept) {
|
|
773
1005
|
return verifyXrpl({ reader, accept });
|
|
774
1006
|
}
|