@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.
- package/CHANGELOG.md +343 -0
- package/README.md +1 -0
- package/dist/{algorand-25FMBCT3.js → algorand-HL57PQHE.js} +157 -2
- package/dist/{algorand-Q3TUQLPK.cjs → algorand-W776EEM2.cjs} +205 -50
- 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 +2929 -1444
- package/dist/index.d.cts +625 -13
- package/dist/index.d.ts +625 -13
- package/dist/index.js +2506 -1021
- package/dist/{near-OLKCMTBI.js → near-5X2CQGML.js} +197 -1
- package/dist/{near-5LTTDU6G.cjs → near-XSQXEIHT.cjs} +242 -46
- package/dist/{solana-AI2G7V33.cjs → solana-EBV6PUCU.cjs} +211 -52
- package/dist/{solana-HTKDRTD3.js → solana-O6Q6QILH.js} +167 -8
- package/dist/{stellar-E2KWEV2E.cjs → stellar-5C7FQLPS.cjs} +191 -29
- package/dist/{stellar-EUFZLX6J.js → stellar-YF5LOJEM.js} +163 -1
- 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-GOVHMYYK.js} +222 -5
- package/dist/{xrpl-SVVS445B.cjs → xrpl-YS3IXPLV.cjs} +273 -56
- 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');
|
|
@@ -103,17 +107,17 @@ async function payXrpl(params) {
|
|
|
103
107
|
const code = res.engine_result;
|
|
104
108
|
if (code.startsWith("tes")) return _nullishCoalesce(_optionalChain([res, 'access', _ => _.tx_json, 'optionalAccess', _2 => _2.hash]), () => ( signed.hash));
|
|
105
109
|
const recipientMsg = recipientNotReadyMessage(code);
|
|
106
|
-
if (recipientMsg) throw new (0,
|
|
110
|
+
if (recipientMsg) throw new (0, _chunk6XTNI2OQcjs.RecipientNotReadyError)(recipientMsg, { cause: makeEngineError(res) });
|
|
107
111
|
if (isAffordabilityCode(code)) {
|
|
108
|
-
throw new (0,
|
|
112
|
+
throw new (0, _chunk6XTNI2OQcjs.InsufficientFundsError)(
|
|
109
113
|
`XRPL payment rejected: the sender can't cover it \u2014 balance or the 1 XRP base reserve. (XRPL: ${code})`,
|
|
110
114
|
{ cause: makeEngineError(res) }
|
|
111
115
|
);
|
|
112
116
|
}
|
|
113
117
|
throw makeEngineError(res);
|
|
114
118
|
} catch (err) {
|
|
115
|
-
if (err instanceof
|
|
116
|
-
throw _nullishCoalesce(
|
|
119
|
+
if (err instanceof _chunk6XTNI2OQcjs.InsufficientFundsError || err instanceof _chunk6XTNI2OQcjs.RecipientNotReadyError) throw err;
|
|
120
|
+
throw _nullishCoalesce(_chunk6XTNI2OQcjs.toInsufficientFundsError.call(void 0, err), () => ( err));
|
|
117
121
|
}
|
|
118
122
|
}
|
|
119
123
|
function amountForAccept(accept) {
|
|
@@ -150,6 +154,197 @@ function isAffordabilityCode(code) {
|
|
|
150
154
|
return /^(tecUNFUNDED|tecINSUFF|terINSUF)/.test(code);
|
|
151
155
|
}
|
|
152
156
|
|
|
157
|
+
// src/drivers/xrpl/swap.ts
|
|
158
|
+
var SOURCE = {
|
|
159
|
+
kind: "protocol",
|
|
160
|
+
name: "XRPL DEX + AMM",
|
|
161
|
+
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."
|
|
162
|
+
};
|
|
163
|
+
function toAmount(t, base) {
|
|
164
|
+
if (t.asset === "native") return base.toString();
|
|
165
|
+
const parts = parseXrplAssetId(t.asset);
|
|
166
|
+
if (!parts) throw new Error(`XRPL: malformed asset id "${t.asset}".`);
|
|
167
|
+
return { currency: parts.currencyHex, issuer: parts.issuer, value: _chunk6XTNI2OQcjs.formatUnits.call(void 0, base, t.decimals) };
|
|
168
|
+
}
|
|
169
|
+
function parseCeil(value, decimals) {
|
|
170
|
+
const [whole = "0", frac = ""] = value.trim().split(".");
|
|
171
|
+
const kept = frac.slice(0, decimals).padEnd(decimals, "0");
|
|
172
|
+
const rest = frac.slice(decimals);
|
|
173
|
+
const base = BigInt(whole + kept);
|
|
174
|
+
return /[1-9]/.test(rest) ? base + 1n : base;
|
|
175
|
+
}
|
|
176
|
+
function fromAmount(t, a) {
|
|
177
|
+
if (a == null) return null;
|
|
178
|
+
try {
|
|
179
|
+
return typeof a === "string" ? BigInt(a) : parseCeil(a.value, t.decimals);
|
|
180
|
+
} catch (e2) {
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
function sourceCurrency(t) {
|
|
185
|
+
if (t.asset === "native") return { currency: "XRP" };
|
|
186
|
+
const parts = parseXrplAssetId(t.asset);
|
|
187
|
+
if (!parts) throw new Error(`XRPL: malformed asset id "${t.asset}".`);
|
|
188
|
+
return { currency: parts.currencyHex, issuer: parts.issuer };
|
|
189
|
+
}
|
|
190
|
+
function side(t, amount) {
|
|
191
|
+
return {
|
|
192
|
+
asset: t.asset,
|
|
193
|
+
symbol: _nullishCoalesce(t.symbol, () => ( (t.asset === "native" ? XRP_SYMBOL : t.asset))),
|
|
194
|
+
decimals: t.asset === "native" ? XRP_DECIMALS : t.decimals,
|
|
195
|
+
amount: amount.toString(),
|
|
196
|
+
amountFormatted: _chunk6XTNI2OQcjs.formatUnits.call(void 0, amount, t.asset === "native" ? XRP_DECIMALS : t.decimals)
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
async function quoteXrplSwap(p) {
|
|
200
|
+
if (p.from.asset === p.to.asset) return null;
|
|
201
|
+
if (p.wantAmount <= 0n) return null;
|
|
202
|
+
let alternatives = [];
|
|
203
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
204
|
+
try {
|
|
205
|
+
const res = await p.client.pathFind({
|
|
206
|
+
source_account: p.owner,
|
|
207
|
+
destination_account: p.owner,
|
|
208
|
+
// ← ourselves: this is what makes it a swap
|
|
209
|
+
destination_amount: toAmount(p.to, p.wantAmount),
|
|
210
|
+
source_currencies: [sourceCurrency(p.from)]
|
|
211
|
+
});
|
|
212
|
+
alternatives = _nullishCoalesce(res.alternatives, () => ( []));
|
|
213
|
+
} catch (e3) {
|
|
214
|
+
alternatives = [];
|
|
215
|
+
}
|
|
216
|
+
if (alternatives.length) break;
|
|
217
|
+
if (attempt === 0) await new Promise((r) => setTimeout(r, 600));
|
|
218
|
+
}
|
|
219
|
+
if (!alternatives.length) return null;
|
|
220
|
+
let best = null;
|
|
221
|
+
let bestSpend = null;
|
|
222
|
+
for (const alt of alternatives) {
|
|
223
|
+
const spend = fromAmount(p.from, alt.source_amount);
|
|
224
|
+
if (spend == null || spend <= 0n) continue;
|
|
225
|
+
if (bestSpend == null || spend < bestSpend) {
|
|
226
|
+
bestSpend = spend;
|
|
227
|
+
best = alt;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
if (!best || bestSpend == null) return null;
|
|
231
|
+
const maxSpend = _chunkMZXVXC3Ccjs.applySlippage.call(void 0, bestSpend, p.slippageBps);
|
|
232
|
+
return {
|
|
233
|
+
source: SOURCE,
|
|
234
|
+
network: p.network,
|
|
235
|
+
from: side(p.from, bestSpend),
|
|
236
|
+
to: side(p.to, p.wantAmount),
|
|
237
|
+
maxSpend: maxSpend.toString(),
|
|
238
|
+
maxSpendFormatted: _chunk6XTNI2OQcjs.formatUnits.call(void 0, maxSpend, p.from.asset === "native" ? XRP_DECIMALS : p.from.decimals),
|
|
239
|
+
slippageBps: p.slippageBps,
|
|
240
|
+
// `paths_computed` drops straight into the transaction's Paths field.
|
|
241
|
+
route: { paths: _nullishCoalesce(best.paths_computed, () => ( [])), from: p.from, to: p.to }
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
function sanitizePaths(paths) {
|
|
245
|
+
if (!Array.isArray(paths)) return [];
|
|
246
|
+
return paths.map(
|
|
247
|
+
(path) => (Array.isArray(path) ? path : []).map((raw) => {
|
|
248
|
+
const step = raw;
|
|
249
|
+
const clean = {};
|
|
250
|
+
if (typeof step.account === "string") clean.account = step.account;
|
|
251
|
+
if (typeof step.currency === "string") clean.currency = step.currency;
|
|
252
|
+
if (typeof step.issuer === "string") clean.issuer = step.issuer;
|
|
253
|
+
return clean;
|
|
254
|
+
}).filter((step) => Object.keys(step).length > 0)
|
|
255
|
+
).filter((path) => path.length > 0);
|
|
256
|
+
}
|
|
257
|
+
async function swapXrpl(p) {
|
|
258
|
+
const { client, wallet, quote } = p;
|
|
259
|
+
const route = quote.route;
|
|
260
|
+
if (!_optionalChain([route, 'optionalAccess', _3 => _3.from]) || !_optionalChain([route, 'optionalAccess', _4 => _4.to])) {
|
|
261
|
+
throw new Error("XRPL: swap quote is missing its routing data \u2014 re-quote before swapping.");
|
|
262
|
+
}
|
|
263
|
+
try {
|
|
264
|
+
const [sequence, feeDrops, ledgerIndex] = await Promise.all([
|
|
265
|
+
client.accountSequence(wallet.classicAddress),
|
|
266
|
+
client.feeDrops(),
|
|
267
|
+
client.currentLedgerIndex()
|
|
268
|
+
]);
|
|
269
|
+
const tx = {
|
|
270
|
+
TransactionType: "Payment",
|
|
271
|
+
Account: wallet.classicAddress,
|
|
272
|
+
Destination: wallet.classicAddress,
|
|
273
|
+
// ← ourselves: the ledger's own swap idiom
|
|
274
|
+
Amount: toAmount(route.to, BigInt(quote.to.amount)),
|
|
275
|
+
// exact output
|
|
276
|
+
SendMax: toAmount(route.from, BigInt(quote.maxSpend)),
|
|
277
|
+
// the on-chain slippage cap
|
|
278
|
+
// Sanitized: raw path steps from ripple_path_find can break xrpl.js encoding.
|
|
279
|
+
...sanitizePaths(route.paths).length ? { Paths: sanitizePaths(route.paths) } : {},
|
|
280
|
+
Sequence: sequence,
|
|
281
|
+
Fee: feeForSubmit2(feeDrops),
|
|
282
|
+
LastLedgerSequence: ledgerIndex + 20,
|
|
283
|
+
// NOT tfPartialPayment: we want the full `Amount` delivered or nothing at all.
|
|
284
|
+
Flags: 0
|
|
285
|
+
};
|
|
286
|
+
let signed;
|
|
287
|
+
try {
|
|
288
|
+
signed = wallet.sign(tx);
|
|
289
|
+
} catch (cause) {
|
|
290
|
+
const shape = Object.fromEntries(
|
|
291
|
+
Object.entries(tx).map(([k, v]) => [k, typeof v === "object" ? JSON.stringify(v) : `${typeof v}:${String(v)}`])
|
|
292
|
+
);
|
|
293
|
+
throw new Error(
|
|
294
|
+
`XRPL could not encode the swap transaction: ${String(_nullishCoalesce(_optionalChain([cause, 'optionalAccess', _5 => _5.message]), () => ( cause)))}. Transaction was ${JSON.stringify(shape)}`,
|
|
295
|
+
{ cause }
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
const res = await client.submit(signed.tx_blob);
|
|
299
|
+
const code = res.engine_result;
|
|
300
|
+
if (code.startsWith("tes")) {
|
|
301
|
+
return {
|
|
302
|
+
transaction: _nullishCoalesce(_optionalChain([res, 'access', _6 => _6.tx_json, 'optionalAccess', _7 => _7.hash]), () => ( signed.hash)),
|
|
303
|
+
network: quote.network,
|
|
304
|
+
source: quote.source,
|
|
305
|
+
from: quote.from,
|
|
306
|
+
to: quote.to
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
throw mapEngineResult(code, res);
|
|
310
|
+
} catch (err) {
|
|
311
|
+
if (err instanceof _chunk6XTNI2OQcjs.InsufficientFundsError || err instanceof _chunk6XTNI2OQcjs.RecipientNotReadyError) throw err;
|
|
312
|
+
throw _nullishCoalesce(_chunk6XTNI2OQcjs.toInsufficientFundsError.call(void 0, err), () => ( err));
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
function feeForSubmit2(openLedgerFee) {
|
|
316
|
+
try {
|
|
317
|
+
const f = BigInt(openLedgerFee);
|
|
318
|
+
const padded = f * 2n;
|
|
319
|
+
return (padded < 10n ? 10n : padded).toString();
|
|
320
|
+
} catch (e4) {
|
|
321
|
+
return "12";
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
function mapEngineResult(code, res) {
|
|
325
|
+
const err = new Error(`XRPL swap rejected: ${code}`);
|
|
326
|
+
err.cause = res;
|
|
327
|
+
if (code === "tecPATH_PARTIAL" || code === "tecPATH_DRY") {
|
|
328
|
+
return new (0, _chunk6XTNI2OQcjs.InsufficientFundsError)(
|
|
329
|
+
`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})`,
|
|
330
|
+
{ cause: res }
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
if (code === "tecNO_LINE" || code === "tecNO_AUTH" || code === "tecNO_ISSUER") {
|
|
334
|
+
return new (0, _chunk6XTNI2OQcjs.RecipientNotReadyError)(
|
|
335
|
+
`XRPL swap refused: your account needs a trustline for the currency you're swapping INTO before it can hold it. (XRPL: ${code})`,
|
|
336
|
+
{ cause: res }
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
if (code === "tecUNFUNDED_PAYMENT" || code === "terINSUF_FEE_B" || code === "tecINSUFF_FEE") {
|
|
340
|
+
return new (0, _chunk6XTNI2OQcjs.InsufficientFundsError)(
|
|
341
|
+
`XRPL swap failed: the account can't cover it \u2014 balance or the 1 XRP base reserve. (XRPL: ${code})`,
|
|
342
|
+
{ cause: res }
|
|
343
|
+
);
|
|
344
|
+
}
|
|
345
|
+
return err;
|
|
346
|
+
}
|
|
347
|
+
|
|
153
348
|
// src/drivers/xrpl/exact.ts
|
|
154
349
|
var _crypto = require('crypto');
|
|
155
350
|
var SECONDS_PER_LEDGER = 4;
|
|
@@ -165,12 +360,12 @@ var MAX_FEE_DROPS = 1e6;
|
|
|
165
360
|
var TF_FULLY_CANONICAL_SIG = 2147483648;
|
|
166
361
|
var TF_PARTIAL_PAYMENT = 131072;
|
|
167
362
|
function feesAreSponsored(accept) {
|
|
168
|
-
return _optionalChain([accept, 'access',
|
|
363
|
+
return _optionalChain([accept, 'access', _8 => _8.extra, 'optionalAccess', _9 => _9.areFeesSponsored]) === true;
|
|
169
364
|
}
|
|
170
365
|
function invoiceIdHash(invoiceId) {
|
|
171
366
|
return _crypto.createHash.call(void 0, "sha256").update(invoiceId, "utf8").digest("hex").toUpperCase();
|
|
172
367
|
}
|
|
173
|
-
function
|
|
368
|
+
function feeForSubmit3(openLedgerFee) {
|
|
174
369
|
const fee = Number(openLedgerFee);
|
|
175
370
|
const chosen = Number.isFinite(fee) && fee > MIN_FEE_DROPS ? Math.ceil(fee) : MIN_FEE_DROPS;
|
|
176
371
|
return String(Math.min(chosen, MAX_FEE_DROPS));
|
|
@@ -178,23 +373,23 @@ function feeForSubmit2(openLedgerFee) {
|
|
|
178
373
|
async function payExactXrpl(input) {
|
|
179
374
|
const { client, wallet, accept } = input;
|
|
180
375
|
if (!isXrpNative(accept.asset)) {
|
|
181
|
-
throw new (0,
|
|
376
|
+
throw new (0, _chunk6XTNI2OQcjs.UnsupportedSchemeError)(
|
|
182
377
|
`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
378
|
);
|
|
184
379
|
}
|
|
185
380
|
if (feesAreSponsored(accept)) {
|
|
186
|
-
throw new (0,
|
|
381
|
+
throw new (0, _chunk6XTNI2OQcjs.UnsupportedSchemeError)(
|
|
187
382
|
"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
383
|
);
|
|
189
384
|
}
|
|
190
|
-
const method =
|
|
385
|
+
const method = _chunk6ZRAIQXFcjs.exactTransferMethod.call(void 0, accept, "xrpl");
|
|
191
386
|
if (method !== "sequence") {
|
|
192
|
-
throw new (0,
|
|
387
|
+
throw new (0, _chunk6XTNI2OQcjs.UnsupportedSchemeError)(
|
|
193
388
|
`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
389
|
);
|
|
195
390
|
}
|
|
196
391
|
if (!/^[0-9]+$/.test(accept.amount)) {
|
|
197
|
-
throw new (0,
|
|
392
|
+
throw new (0, _chunk6XTNI2OQcjs.UnsupportedSchemeError)(
|
|
198
393
|
`XRPL exact: native amount "${accept.amount}" is not an integer drops string.`
|
|
199
394
|
);
|
|
200
395
|
}
|
|
@@ -209,8 +404,8 @@ async function payExactXrpl(input) {
|
|
|
209
404
|
client.currentLedgerIndex()
|
|
210
405
|
]);
|
|
211
406
|
} catch (err) {
|
|
212
|
-
if (/actNotFound/i.test(String(_nullishCoalesce(_optionalChain([err, 'optionalAccess',
|
|
213
|
-
throw new (0,
|
|
407
|
+
if (/actNotFound/i.test(String(_nullishCoalesce(_optionalChain([err, 'optionalAccess', _10 => _10.message]), () => ( err))))) {
|
|
408
|
+
throw new (0, _chunk6XTNI2OQcjs.InsufficientFundsError)(
|
|
214
409
|
`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
410
|
{ cause: err instanceof Error ? err : new Error(String(err)) }
|
|
216
411
|
);
|
|
@@ -224,25 +419,25 @@ async function payExactXrpl(input) {
|
|
|
224
419
|
Amount: accept.amount,
|
|
225
420
|
// integer drops, verbatim from the trusted accept
|
|
226
421
|
Sequence: sequence,
|
|
227
|
-
Fee:
|
|
422
|
+
Fee: feeForSubmit3(openLedgerFee),
|
|
228
423
|
LastLedgerSequence: ledgerIndex + ledgerWindowFor(accept.maxTimeoutSeconds),
|
|
229
424
|
// tfFullyCanonicalSig ON, tfPartialPayment OFF — the shape every other XRPL client sends.
|
|
230
425
|
Flags: TF_FULLY_CANONICAL_SIG
|
|
231
426
|
};
|
|
232
|
-
if (typeof _optionalChain([accept, 'access',
|
|
427
|
+
if (typeof _optionalChain([accept, 'access', _11 => _11.extra, 'optionalAccess', _12 => _12.destinationTag]) === "number") {
|
|
233
428
|
tx.DestinationTag = accept.extra.destinationTag;
|
|
234
429
|
}
|
|
235
|
-
if (typeof _optionalChain([accept, 'access',
|
|
430
|
+
if (typeof _optionalChain([accept, 'access', _13 => _13.extra, 'optionalAccess', _14 => _14.sourceTag]) === "number") {
|
|
236
431
|
tx.SourceTag = accept.extra.sourceTag;
|
|
237
432
|
}
|
|
238
|
-
if (typeof _optionalChain([accept, 'access',
|
|
433
|
+
if (typeof _optionalChain([accept, 'access', _15 => _15.extra, 'optionalAccess', _16 => _16.invoiceId]) === "string" && accept.extra.invoiceId.length > 0) {
|
|
239
434
|
tx.InvoiceID = invoiceIdHash(accept.extra.invoiceId);
|
|
240
435
|
}
|
|
241
436
|
let signed;
|
|
242
437
|
try {
|
|
243
438
|
signed = wallet.sign(tx);
|
|
244
439
|
} catch (err) {
|
|
245
|
-
throw new (0,
|
|
440
|
+
throw new (0, _chunk6XTNI2OQcjs.UnsupportedSchemeError)(
|
|
246
441
|
`XRPL exact: could not sign this rail \u2014 ${err instanceof Error ? err.message : String(err)}`,
|
|
247
442
|
{ cause: err instanceof Error ? err : new Error(String(err)) }
|
|
248
443
|
);
|
|
@@ -262,7 +457,7 @@ async function verifyAndSettleExactXrpl(input) {
|
|
|
262
457
|
const attempts = _nullishCoalesce(input.pollAttempts, () => ( 8));
|
|
263
458
|
const sleep = _nullishCoalesce(input.sleep, () => ( ((ms) => new Promise((r) => setTimeout(r, ms)))));
|
|
264
459
|
if (feesAreSponsored(accept)) {
|
|
265
|
-
throw new (0,
|
|
460
|
+
throw new (0, _chunk6XTNI2OQcjs.SettlementError)("XRPL exact: rail advertises areFeesSponsored:true, which this ledger cannot honour.");
|
|
266
461
|
}
|
|
267
462
|
let tx;
|
|
268
463
|
try {
|
|
@@ -295,10 +490,10 @@ async function verifyAndSettleExactXrpl(input) {
|
|
|
295
490
|
if (tx.Amount !== accept.amount) {
|
|
296
491
|
return fail("amount_too_low", `XRPL exact: Amount ${String(tx.Amount)} \u2260 the rail's ${accept.amount} drops.`);
|
|
297
492
|
}
|
|
298
|
-
if (typeof _optionalChain([accept, 'access',
|
|
493
|
+
if (typeof _optionalChain([accept, 'access', _17 => _17.extra, 'optionalAccess', _18 => _18.destinationTag]) === "number" && tx.DestinationTag !== accept.extra.destinationTag) {
|
|
299
494
|
return fail("signature_invalid", `XRPL exact: DestinationTag ${String(tx.DestinationTag)} \u2260 the rail's ${accept.extra.destinationTag}.`);
|
|
300
495
|
}
|
|
301
|
-
if (typeof _optionalChain([accept, 'access',
|
|
496
|
+
if (typeof _optionalChain([accept, 'access', _19 => _19.extra, 'optionalAccess', _20 => _20.invoiceId]) === "string" && accept.extra.invoiceId.length > 0) {
|
|
302
497
|
const want = invoiceIdHash(accept.extra.invoiceId);
|
|
303
498
|
if (String(_nullishCoalesce(tx.InvoiceID, () => ( ""))).toUpperCase() !== want) {
|
|
304
499
|
return fail("signature_invalid", "XRPL exact: InvoiceID does not bind this challenge.");
|
|
@@ -317,24 +512,24 @@ async function verifyAndSettleExactXrpl(input) {
|
|
|
317
512
|
`XRPL exact: submit rejected \u2014 ${res.engine_result}${res.engine_result_message ? ` (${res.engine_result_message})` : ""}.`
|
|
318
513
|
);
|
|
319
514
|
}
|
|
320
|
-
hash = _nullishCoalesce(_optionalChain([res, 'access',
|
|
515
|
+
hash = _nullishCoalesce(_optionalChain([res, 'access', _21 => _21.tx_json, 'optionalAccess', _22 => _22.hash]), () => ( ""));
|
|
321
516
|
if (!hash) throw new Error("submit returned no transaction hash");
|
|
322
517
|
} catch (err) {
|
|
323
|
-
throw new (0,
|
|
518
|
+
throw new (0, _chunk6XTNI2OQcjs.SettlementError)(`XRPL exact: submit failed (${err instanceof Error ? err.message : String(err)}).`);
|
|
324
519
|
}
|
|
325
520
|
for (let i = 0; i < attempts; i += 1) {
|
|
326
521
|
let record;
|
|
327
522
|
try {
|
|
328
523
|
record = await client.txByHash(hash);
|
|
329
|
-
} catch (
|
|
524
|
+
} catch (e5) {
|
|
330
525
|
record = null;
|
|
331
526
|
}
|
|
332
|
-
if (_optionalChain([record, 'optionalAccess',
|
|
333
|
-
const code = _optionalChain([record, 'access',
|
|
527
|
+
if (_optionalChain([record, 'optionalAccess', _23 => _23.validated])) {
|
|
528
|
+
const code = _optionalChain([record, 'access', _24 => _24.meta, 'optionalAccess', _25 => _25.TransactionResult]);
|
|
334
529
|
if (code !== "tesSUCCESS") {
|
|
335
530
|
return fail("transfer_not_found", `XRPL exact: validated with ${String(code)}, not tesSUCCESS.`);
|
|
336
531
|
}
|
|
337
|
-
const delivered = _optionalChain([record, 'access',
|
|
532
|
+
const delivered = _optionalChain([record, 'access', _26 => _26.meta, 'optionalAccess', _27 => _27.delivered_amount]);
|
|
338
533
|
if (delivered !== void 0 && typeof delivered === "string" && delivered !== accept.amount) {
|
|
339
534
|
return fail("amount_too_low", `XRPL exact: delivered ${delivered} drops, expected ${accept.amount}.`);
|
|
340
535
|
}
|
|
@@ -355,7 +550,7 @@ async function verifyAndSettleExactXrpl(input) {
|
|
|
355
550
|
}
|
|
356
551
|
await sleep(1200);
|
|
357
552
|
}
|
|
358
|
-
throw new (0,
|
|
553
|
+
throw new (0, _chunk6XTNI2OQcjs.SettlementError)(
|
|
359
554
|
`XRPL exact: submitted ${hash} but it was not validated within ${attempts} polls. It may still settle; retry the request.`
|
|
360
555
|
);
|
|
361
556
|
}
|
|
@@ -371,7 +566,7 @@ async function verifyXrpl(params) {
|
|
|
371
566
|
let txs;
|
|
372
567
|
try {
|
|
373
568
|
txs = await reader.transactionsForAccount(accept.payTo, 200);
|
|
374
|
-
} catch (
|
|
569
|
+
} catch (e6) {
|
|
375
570
|
return rpcFailed(nonce);
|
|
376
571
|
}
|
|
377
572
|
const tx = txs.find(
|
|
@@ -435,7 +630,7 @@ async function verifyXrpl(params) {
|
|
|
435
630
|
}
|
|
436
631
|
function hasNonceMemo(memos, wantMemo) {
|
|
437
632
|
if (!memos) return false;
|
|
438
|
-
return memos.some((m) => (_nullishCoalesce(_optionalChain([m, 'access',
|
|
633
|
+
return memos.some((m) => (_nullishCoalesce(_optionalChain([m, 'access', _28 => _28.Memo, 'optionalAccess', _29 => _29.MemoData]), () => ( ""))).toUpperCase() === wantMemo);
|
|
439
634
|
}
|
|
440
635
|
function deliveredBaseUnits(delivered, want, decimals) {
|
|
441
636
|
if (delivered === void 0) return null;
|
|
@@ -449,8 +644,8 @@ function deliveredBaseUnits(delivered, want, decimals) {
|
|
|
449
644
|
return null;
|
|
450
645
|
}
|
|
451
646
|
try {
|
|
452
|
-
return
|
|
453
|
-
} catch (
|
|
647
|
+
return _chunk6XTNI2OQcjs.floorUnits.call(void 0, delivered.value, decimals);
|
|
648
|
+
} catch (e7) {
|
|
454
649
|
return null;
|
|
455
650
|
}
|
|
456
651
|
}
|
|
@@ -473,13 +668,13 @@ function rpcFailed(nonce) {
|
|
|
473
668
|
|
|
474
669
|
function assertXrplWallet(wallet, network) {
|
|
475
670
|
if (typeof wallet !== "object" || wallet === null) {
|
|
476
|
-
throw new (0,
|
|
671
|
+
throw new (0, _chunk6XTNI2OQcjs.WrongFamilyError)(
|
|
477
672
|
`chain ${network} is XRPL; wallet must be { key } (s\u2026 seed) or { wallet }.`
|
|
478
673
|
);
|
|
479
674
|
}
|
|
480
|
-
|
|
675
|
+
_chunk6XTNI2OQcjs.assertNoLegacyWalletKey.call(void 0, wallet, "XRPL");
|
|
481
676
|
if (!("key" in wallet) && !("wallet" in wallet)) {
|
|
482
|
-
throw new (0,
|
|
677
|
+
throw new (0, _chunk6XTNI2OQcjs.WrongFamilyError)(
|
|
483
678
|
`chain ${network} is XRPL; wallet must be { key } (s\u2026 seed) or { wallet }.`
|
|
484
679
|
);
|
|
485
680
|
}
|
|
@@ -489,16 +684,16 @@ function resolveXrplWallet(config) {
|
|
|
489
684
|
if (config.wallet) return config.wallet;
|
|
490
685
|
if (config.key) {
|
|
491
686
|
if (!_xrpl.isValidSecret.call(void 0, config.key)) {
|
|
492
|
-
throw new (0,
|
|
687
|
+
throw new (0, _chunk6XTNI2OQcjs.WrongFamilyError)("XRPL wallet { key } is not a valid s\u2026 secret seed.");
|
|
493
688
|
}
|
|
494
689
|
return _xrpl.Wallet.fromSeed(config.key);
|
|
495
690
|
}
|
|
496
|
-
throw new (0,
|
|
691
|
+
throw new (0, _chunk6XTNI2OQcjs.WrongFamilyError)("XRPL wallet needs { key } (s\u2026 seed) or { wallet }.");
|
|
497
692
|
}
|
|
498
693
|
|
|
499
694
|
// src/drivers/xrpl/index.ts
|
|
500
695
|
function isXrplActNotFound(e) {
|
|
501
|
-
return /actNotFound/i.test(String(_nullishCoalesce(_optionalChain([e, 'optionalAccess',
|
|
696
|
+
return /actNotFound/i.test(String(_nullishCoalesce(_optionalChain([e, 'optionalAccess', _30 => _30.message]), () => ( e))));
|
|
502
697
|
}
|
|
503
698
|
var xrplDriver = {
|
|
504
699
|
family: "xrpl",
|
|
@@ -520,11 +715,14 @@ function makeXrplNetwork(preset, rpcUrl) {
|
|
|
520
715
|
const json = await res.json();
|
|
521
716
|
const result = json.result;
|
|
522
717
|
if (!result || result.status === "error" || result.error) {
|
|
523
|
-
throw new Error(`XRPL RPC ${method} error: ${_nullishCoalesce(_optionalChain([result, 'optionalAccess',
|
|
718
|
+
throw new Error(`XRPL RPC ${method} error: ${_nullishCoalesce(_optionalChain([result, 'optionalAccess', _31 => _31.error]), () => ( "unknown"))}`);
|
|
524
719
|
}
|
|
525
720
|
return result;
|
|
526
721
|
}
|
|
527
722
|
const payClient = {
|
|
723
|
+
async pathFind(params) {
|
|
724
|
+
return rpc("ripple_path_find", { ...params, ledger_index: "current" });
|
|
725
|
+
},
|
|
528
726
|
async accountSequence(account) {
|
|
529
727
|
const r = await rpc("account_info", {
|
|
530
728
|
account,
|
|
@@ -549,7 +747,7 @@ function makeXrplNetwork(preset, rpcUrl) {
|
|
|
549
747
|
async txByHash(hash) {
|
|
550
748
|
try {
|
|
551
749
|
return await rpc("tx", { transaction: hash, binary: false });
|
|
552
|
-
} catch (
|
|
750
|
+
} catch (e8) {
|
|
553
751
|
return null;
|
|
554
752
|
}
|
|
555
753
|
}
|
|
@@ -578,7 +776,7 @@ function makeXrplNetwork(preset, rpcUrl) {
|
|
|
578
776
|
const info = preset.tokens[token.toUpperCase()];
|
|
579
777
|
if (!info) {
|
|
580
778
|
const known = Object.keys(preset.tokens).join(", ") || "(none built in)";
|
|
581
|
-
throw new (0,
|
|
779
|
+
throw new (0, _chunk6XTNI2OQcjs.UnknownTokenError)(
|
|
582
780
|
`token "${token}" isn't built in for XRPL (known: ${known}). Pass { issuer, currencyHex, decimals } for a custom IOU, or use 'native'.`
|
|
583
781
|
);
|
|
584
782
|
}
|
|
@@ -588,10 +786,10 @@ function makeXrplNetwork(preset, rpcUrl) {
|
|
|
588
786
|
symbol: info.symbol
|
|
589
787
|
};
|
|
590
788
|
}
|
|
591
|
-
|
|
789
|
+
_chunk6XTNI2OQcjs.rejectForeignToken.call(void 0, token, "xrpl", network);
|
|
592
790
|
const t = token;
|
|
593
791
|
if (!t.issuer || !t.currencyHex || typeof t.decimals !== "number") {
|
|
594
|
-
throw new (0,
|
|
792
|
+
throw new (0, _chunk6XTNI2OQcjs.WrongFamilyError)(
|
|
595
793
|
`chain ${network} is XRPL; a custom token must be { issuer, currencyHex, decimals }.`
|
|
596
794
|
);
|
|
597
795
|
}
|
|
@@ -612,12 +810,12 @@ function makeXrplNetwork(preset, rpcUrl) {
|
|
|
612
810
|
},
|
|
613
811
|
assertValidPayTo(payTo) {
|
|
614
812
|
if (payTo.startsWith("0x")) {
|
|
615
|
-
throw new (0,
|
|
813
|
+
throw new (0, _chunk6XTNI2OQcjs.WrongFamilyError)(
|
|
616
814
|
`chain ${network} is XRPL, but payTo "${payTo}" looks like an EVM address.`
|
|
617
815
|
);
|
|
618
816
|
}
|
|
619
817
|
if (!_xrpl.isValidClassicAddress.call(void 0, payTo)) {
|
|
620
|
-
throw new (0,
|
|
818
|
+
throw new (0, _chunk6XTNI2OQcjs.WrongFamilyError)(
|
|
621
819
|
`chain ${network} is XRPL, but payTo "${payTo}" is not a valid XRPL account (r\u2026).`
|
|
622
820
|
);
|
|
623
821
|
}
|
|
@@ -685,26 +883,26 @@ function makeXrplNetwork(preset, rpcUrl) {
|
|
|
685
883
|
transaction: ref
|
|
686
884
|
});
|
|
687
885
|
if (tx.validated) return { height: String(_nullishCoalesce(tx.ledger_index, () => ( 0))) };
|
|
688
|
-
} catch (
|
|
886
|
+
} catch (e9) {
|
|
689
887
|
}
|
|
690
888
|
await _chunkCQREG5LEcjs.delay.call(void 0, 1500);
|
|
691
889
|
}
|
|
692
|
-
throw new (0,
|
|
890
|
+
throw new (0, _chunk6XTNI2OQcjs.ConfirmationTimeoutError)(`XRPL tx ${ref} not validated on-ledger in time.`);
|
|
693
891
|
},
|
|
694
892
|
async estimateCost() {
|
|
695
893
|
try {
|
|
696
894
|
const drops = await payClient.feeDrops();
|
|
697
895
|
const n = Number(drops);
|
|
698
896
|
const fee = BigInt(Number.isFinite(n) && n > 12 ? Math.ceil(n) : 12);
|
|
699
|
-
return
|
|
897
|
+
return _chunk6XTNI2OQcjs.nativeCost.call(void 0, {
|
|
700
898
|
symbol: XRP_SYMBOL,
|
|
701
899
|
decimals: XRP_DECIMALS,
|
|
702
900
|
fee,
|
|
703
901
|
basis: "estimated",
|
|
704
902
|
detail: `network fee ${fee} drops`
|
|
705
903
|
});
|
|
706
|
-
} catch (
|
|
707
|
-
return
|
|
904
|
+
} catch (e10) {
|
|
905
|
+
return _chunk6XTNI2OQcjs.nativeCost.call(void 0, {
|
|
708
906
|
symbol: XRP_SYMBOL,
|
|
709
907
|
decimals: XRP_DECIMALS,
|
|
710
908
|
fee: 12n,
|
|
@@ -713,11 +911,16 @@ function makeXrplNetwork(preset, rpcUrl) {
|
|
|
713
911
|
});
|
|
714
912
|
}
|
|
715
913
|
},
|
|
914
|
+
/** The bound wallet's own address — where THIS wallet gets paid. Derived from the key
|
|
915
|
+
* material only: no RPC, nothing moved. See {@link ResolvedNetwork.addressOf}. */
|
|
916
|
+
async addressOf(wallet) {
|
|
917
|
+
return resolveXrplWallet(wallet._native).classicAddress;
|
|
918
|
+
},
|
|
716
919
|
async balanceOf(wallet, asset) {
|
|
717
920
|
let owner;
|
|
718
921
|
try {
|
|
719
922
|
owner = resolveXrplWallet(wallet._native).classicAddress;
|
|
720
|
-
} catch (
|
|
923
|
+
} catch (e11) {
|
|
721
924
|
return { token: null, native: null };
|
|
722
925
|
}
|
|
723
926
|
let native = null;
|
|
@@ -741,7 +944,7 @@ function makeXrplNetwork(preset, rpcUrl) {
|
|
|
741
944
|
const line = r.lines.find(
|
|
742
945
|
(l) => l.currency.toUpperCase() === (_nullishCoalesce(currencyHex, () => ( ""))).toUpperCase() && l.account === issuer
|
|
743
946
|
);
|
|
744
|
-
token = line ?
|
|
947
|
+
token = line ? _chunk6XTNI2OQcjs.floorUnits.call(void 0, line.balance, XRP_DECIMALS) : 0n;
|
|
745
948
|
} catch (e) {
|
|
746
949
|
token = isXrplActNotFound(e) ? 0n : null;
|
|
747
950
|
}
|
|
@@ -765,10 +968,24 @@ function makeXrplNetwork(preset, rpcUrl) {
|
|
|
765
968
|
(l) => l.currency.toUpperCase() === (_nullishCoalesce(currencyHex, () => ( ""))).toUpperCase() && l.account === issuer
|
|
766
969
|
);
|
|
767
970
|
return has ? { ready: true } : { ready: false, reason: "NO_TRUSTLINE" };
|
|
768
|
-
} catch (
|
|
971
|
+
} catch (e12) {
|
|
769
972
|
return { ready: "unknown" };
|
|
770
973
|
}
|
|
771
974
|
},
|
|
975
|
+
/* ---- swap (OPTIONAL, opt-in): a cross-currency payment to yourself. See ./swap.ts ---- */
|
|
976
|
+
async quoteSwap({ from, to, wantAmount, slippageBps, wallet }) {
|
|
977
|
+
let owner;
|
|
978
|
+
try {
|
|
979
|
+
owner = resolveXrplWallet(wallet._native).classicAddress;
|
|
980
|
+
} catch (e13) {
|
|
981
|
+
return null;
|
|
982
|
+
}
|
|
983
|
+
return quoteXrplSwap({ client: payClient, network, owner, from, to, wantAmount, slippageBps });
|
|
984
|
+
},
|
|
985
|
+
async swap(wallet, quote) {
|
|
986
|
+
const w = resolveXrplWallet(wallet._native);
|
|
987
|
+
return swapXrpl({ client: payClient, wallet: w, quote });
|
|
988
|
+
},
|
|
772
989
|
async verify(_ref, accept) {
|
|
773
990
|
return verifyXrpl({ reader, accept });
|
|
774
991
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@piprail/sdk",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Accept x402 crypto payments across
|
|
3
|
+
"version": "3.0.0",
|
|
4
|
+
"description": "Accept x402 crypto payments across 30 chains \u2014 every major EVM chain plus Solana, TON, Tron, NEAR, Sui, Aptos, Algorand, Stellar & XRPL \u2014 in a couple of lines. No backend, no database, no fee; payments settle straight to your wallet.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
7
7
|
"module": "./dist/index.js",
|
|
@@ -93,6 +93,8 @@
|
|
|
93
93
|
"@solana/spl-token": "^0.4.0",
|
|
94
94
|
"@solana/web3.js": "^1.95.0",
|
|
95
95
|
"@stellar/stellar-sdk": ">=13 <16",
|
|
96
|
+
"@ston-fi/api": "^0",
|
|
97
|
+
"@ston-fi/sdk": ">=2 <3",
|
|
96
98
|
"@ton/core": ">=0.59 <1",
|
|
97
99
|
"@ton/crypto": ">=3 <4",
|
|
98
100
|
"@ton/ton": ">=15 <17",
|
|
@@ -146,6 +148,12 @@
|
|
|
146
148
|
},
|
|
147
149
|
"borsh": {
|
|
148
150
|
"optional": true
|
|
151
|
+
},
|
|
152
|
+
"@ston-fi/sdk": {
|
|
153
|
+
"optional": true
|
|
154
|
+
},
|
|
155
|
+
"@ston-fi/api": {
|
|
156
|
+
"optional": true
|
|
149
157
|
}
|
|
150
158
|
},
|
|
151
159
|
"devDependencies": {
|
|
@@ -154,6 +162,8 @@
|
|
|
154
162
|
"@solana/spl-token": "^0.4.14",
|
|
155
163
|
"@solana/web3.js": "^1.98.4",
|
|
156
164
|
"@stellar/stellar-sdk": "^15.1.0",
|
|
165
|
+
"@ston-fi/api": "^0.32.0",
|
|
166
|
+
"@ston-fi/sdk": "^2.7.0",
|
|
157
167
|
"@ton/core": "^0.63.1",
|
|
158
168
|
"@ton/crypto": "^3.3.0",
|
|
159
169
|
"@ton/ton": "^16.2.4",
|