@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,3 +1,6 @@
|
|
|
1
|
+
import {
|
|
2
|
+
applySlippage
|
|
3
|
+
} from "./chunk-GVCGUSTE.js";
|
|
1
4
|
import {
|
|
2
5
|
ConfirmationTimeoutError,
|
|
3
6
|
InsufficientFundsError,
|
|
@@ -7,10 +10,11 @@ import {
|
|
|
7
10
|
UnsupportedSchemeError,
|
|
8
11
|
WrongFamilyError,
|
|
9
12
|
assertNoLegacyWalletKey,
|
|
13
|
+
formatUnits,
|
|
10
14
|
nativeCost,
|
|
11
15
|
rejectForeignToken,
|
|
12
16
|
toInsufficientFundsError
|
|
13
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-5GRBEMCA.js";
|
|
14
18
|
|
|
15
19
|
// src/drivers/near/index.ts
|
|
16
20
|
import { JsonRpcProvider, Account, actions as actions2 } from "near-api-js";
|
|
@@ -435,6 +439,160 @@ function resolveNearWallet(config) {
|
|
|
435
439
|
return { accountId: config.accountId, signer };
|
|
436
440
|
}
|
|
437
441
|
|
|
442
|
+
// src/drivers/near/swap.ts
|
|
443
|
+
var REF_EXCHANGE = "v2.ref-finance.near";
|
|
444
|
+
var WRAP_NEAR = "wrap.near";
|
|
445
|
+
var REF_INDEXER = "https://indexer.ref.finance";
|
|
446
|
+
function sourceFor(feeBps) {
|
|
447
|
+
const fee = feeBps === null ? "the pool's own fee" : `${(feeBps / 100).toFixed(2)}%`;
|
|
448
|
+
return {
|
|
449
|
+
kind: "provider",
|
|
450
|
+
name: "Ref Finance",
|
|
451
|
+
note: `Third-party NEAR AMM (v2.ref-finance.near), used keyless over the chain's own RPC. The swap is one ft_transfer_call receipt chain, so no solver ever takes possession of the funds, which is why this is used instead of an intent network. Pool fee on this route: ${fee}. PipRail adds nothing.`
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
function refToken(t) {
|
|
455
|
+
return t.asset === "native" ? WRAP_NEAR : t.asset;
|
|
456
|
+
}
|
|
457
|
+
function side(t, amount) {
|
|
458
|
+
const decimals = t.asset === "native" ? NEAR_DECIMALS : t.decimals;
|
|
459
|
+
return {
|
|
460
|
+
asset: t.asset,
|
|
461
|
+
symbol: t.symbol ?? (t.asset === "native" ? "NEAR" : t.asset),
|
|
462
|
+
decimals,
|
|
463
|
+
amount: amount.toString(),
|
|
464
|
+
amountFormatted: formatUnits(amount, decimals)
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
async function getJson(url) {
|
|
468
|
+
const ctrl = new AbortController();
|
|
469
|
+
const timer = setTimeout(() => ctrl.abort(), 12e3);
|
|
470
|
+
try {
|
|
471
|
+
const res = await fetch(url, { signal: ctrl.signal });
|
|
472
|
+
if (!res.ok) return null;
|
|
473
|
+
return await res.json();
|
|
474
|
+
} catch {
|
|
475
|
+
return null;
|
|
476
|
+
} finally {
|
|
477
|
+
clearTimeout(timer);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
async function findPools(tokenIn, tokenOut) {
|
|
481
|
+
const all = await getJson(`${REF_INDEXER}/list-top-pools`);
|
|
482
|
+
if (!Array.isArray(all)) return [];
|
|
483
|
+
return all.filter(
|
|
484
|
+
(p) => Array.isArray(p.token_account_ids) && p.token_account_ids.includes(tokenIn) && p.token_account_ids.includes(tokenOut)
|
|
485
|
+
).sort((a, b) => Number(b.tvl ?? 0) - Number(a.tvl ?? 0)).slice(0, 4).map((p) => ({ ...p, id: Number(p.id) }));
|
|
486
|
+
}
|
|
487
|
+
async function quoteNearSwap(p) {
|
|
488
|
+
if (p.wantAmount <= 0n) return null;
|
|
489
|
+
const tokenIn = refToken(p.from);
|
|
490
|
+
const tokenOut = refToken(p.to);
|
|
491
|
+
if (tokenIn === tokenOut) return null;
|
|
492
|
+
const pools = await findPools(tokenIn, tokenOut);
|
|
493
|
+
if (!pools.length) return null;
|
|
494
|
+
const fromDecimals = p.from.asset === "native" ? NEAR_DECIMALS : p.from.decimals;
|
|
495
|
+
const probeIn = 10n ** BigInt(Math.max(fromDecimals - 2, 1));
|
|
496
|
+
const getReturn = async (poolId, amountIn) => {
|
|
497
|
+
try {
|
|
498
|
+
const out = await p.client.view(REF_EXCHANGE, "get_return", {
|
|
499
|
+
pool_id: poolId,
|
|
500
|
+
token_in: tokenIn,
|
|
501
|
+
amount_in: amountIn.toString(),
|
|
502
|
+
token_out: tokenOut
|
|
503
|
+
});
|
|
504
|
+
const s = String(out ?? "");
|
|
505
|
+
return s && /^\d+$/.test(s) ? BigInt(s) : null;
|
|
506
|
+
} catch {
|
|
507
|
+
return null;
|
|
508
|
+
}
|
|
509
|
+
};
|
|
510
|
+
for (const pool of pools) {
|
|
511
|
+
const probeOut = await getReturn(pool.id, probeIn);
|
|
512
|
+
if (probeOut === null || probeOut <= 0n) continue;
|
|
513
|
+
let needIn = (probeIn * p.wantAmount + probeOut - 1n) / probeOut;
|
|
514
|
+
needIn = applySlippage(needIn, p.slippageBps);
|
|
515
|
+
const realOut = await getReturn(pool.id, needIn);
|
|
516
|
+
if (realOut === null) continue;
|
|
517
|
+
if (realOut < p.wantAmount) continue;
|
|
518
|
+
const minOut = p.wantAmount;
|
|
519
|
+
return {
|
|
520
|
+
source: sourceFor(typeof pool.total_fee === "number" ? pool.total_fee : null),
|
|
521
|
+
network: p.network,
|
|
522
|
+
from: side(p.from, needIn),
|
|
523
|
+
to: side(p.to, realOut),
|
|
524
|
+
maxSpend: needIn.toString(),
|
|
525
|
+
maxSpendFormatted: formatUnits(needIn, fromDecimals),
|
|
526
|
+
slippageBps: p.slippageBps,
|
|
527
|
+
route: {
|
|
528
|
+
poolId: pool.id,
|
|
529
|
+
tokenIn,
|
|
530
|
+
tokenOut,
|
|
531
|
+
amountIn: needIn.toString(),
|
|
532
|
+
minAmountOut: minOut.toString()
|
|
533
|
+
}
|
|
534
|
+
};
|
|
535
|
+
}
|
|
536
|
+
return null;
|
|
537
|
+
}
|
|
538
|
+
async function swapNear(p) {
|
|
539
|
+
const route = p.quote.route;
|
|
540
|
+
if (!route?.poolId || !route.tokenIn) {
|
|
541
|
+
throw new Error("NEAR: swap quote is missing its Ref routing data \u2014 re-quote before swapping.");
|
|
542
|
+
}
|
|
543
|
+
const msg = JSON.stringify({
|
|
544
|
+
force: 0,
|
|
545
|
+
actions: [
|
|
546
|
+
{
|
|
547
|
+
pool_id: route.poolId,
|
|
548
|
+
token_in: route.tokenIn,
|
|
549
|
+
token_out: route.tokenOut,
|
|
550
|
+
amount_in: route.amountIn,
|
|
551
|
+
min_amount_out: route.minAmountOut
|
|
552
|
+
}
|
|
553
|
+
]
|
|
554
|
+
});
|
|
555
|
+
try {
|
|
556
|
+
const tx = await p.call({
|
|
557
|
+
contractId: route.tokenIn,
|
|
558
|
+
method: "ft_transfer_call",
|
|
559
|
+
args: { receiver_id: REF_EXCHANGE, amount: route.amountIn, msg },
|
|
560
|
+
// NEP-141 transfer_call into an AMM needs generous gas: 180 TGas.
|
|
561
|
+
gas: 180000000000000n,
|
|
562
|
+
// ft_transfer_call requires exactly 1 yoctoNEAR as a signing assertion.
|
|
563
|
+
deposit: 1n
|
|
564
|
+
});
|
|
565
|
+
return {
|
|
566
|
+
transaction: tx,
|
|
567
|
+
network: p.quote.network,
|
|
568
|
+
source: p.quote.source,
|
|
569
|
+
from: p.quote.from,
|
|
570
|
+
to: p.quote.to
|
|
571
|
+
};
|
|
572
|
+
} catch (err) {
|
|
573
|
+
const msgText = String(err?.message ?? err);
|
|
574
|
+
if (/storage|not registered|NotRegistered/i.test(msgText)) {
|
|
575
|
+
throw new RecipientNotReadyError(
|
|
576
|
+
"NEAR swap refused: your account is not storage-registered on the token you are swapping INTO. Call storage_deposit on that token contract first (about 0.00125 NEAR).",
|
|
577
|
+
{ cause: err }
|
|
578
|
+
);
|
|
579
|
+
}
|
|
580
|
+
if (/ERR_MIN_AMOUNT|slippage/i.test(msgText)) {
|
|
581
|
+
throw new InsufficientFundsError(
|
|
582
|
+
"NEAR swap refused: the pool could not deliver the minimum output, so the tokens were returned. Re-quote and retry.",
|
|
583
|
+
{ cause: err }
|
|
584
|
+
);
|
|
585
|
+
}
|
|
586
|
+
if (/insufficient|balance|exceeded/i.test(msgText)) {
|
|
587
|
+
throw new InsufficientFundsError(
|
|
588
|
+
`NEAR swap failed: the account can't cover it (token balance or NEAR for gas). (${msgText.slice(0, 160)})`,
|
|
589
|
+
{ cause: err }
|
|
590
|
+
);
|
|
591
|
+
}
|
|
592
|
+
throw err;
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
|
|
438
596
|
// src/drivers/near/index.ts
|
|
439
597
|
var nearDriver = {
|
|
440
598
|
family: "near",
|
|
@@ -587,6 +745,11 @@ function makeNearNetwork(preset, rpcUrl) {
|
|
|
587
745
|
detail: "~14 TGas for ft_transfer (\u22480.0015 NEAR) + 1 yoctoNEAR deposit"
|
|
588
746
|
});
|
|
589
747
|
},
|
|
748
|
+
/** The bound wallet's own address — where THIS wallet gets paid. Derived from the key
|
|
749
|
+
* material only: no RPC, nothing moved. See {@link ResolvedNetwork.addressOf}. */
|
|
750
|
+
async addressOf(wallet) {
|
|
751
|
+
return resolveNearWallet(wallet._native).accountId;
|
|
752
|
+
},
|
|
590
753
|
async balanceOf(wallet, asset) {
|
|
591
754
|
let accountId;
|
|
592
755
|
try {
|
|
@@ -637,6 +800,39 @@ function makeNearNetwork(preset, rpcUrl) {
|
|
|
637
800
|
return { ready: "unknown" };
|
|
638
801
|
}
|
|
639
802
|
},
|
|
803
|
+
/* ---- swap (OPTIONAL, opt-in): via Ref Finance, keyless over the chain's own RPC.
|
|
804
|
+
Chosen over NEAR Intents because Intents re-adds a facilitator. See ./swap.ts ---- */
|
|
805
|
+
async quoteSwap({ from, to, wantAmount, slippageBps }) {
|
|
806
|
+
const viewClient = {
|
|
807
|
+
async view(contractId, method, args) {
|
|
808
|
+
const r = await provider.query({
|
|
809
|
+
request_type: "call_function",
|
|
810
|
+
finality: "final",
|
|
811
|
+
account_id: contractId,
|
|
812
|
+
method_name: method,
|
|
813
|
+
args_base64: Buffer.from(JSON.stringify(args)).toString("base64")
|
|
814
|
+
});
|
|
815
|
+
return r.result ? JSON.parse(Buffer.from(r.result).toString()) : null;
|
|
816
|
+
}
|
|
817
|
+
};
|
|
818
|
+
return quoteNearSwap({ client: viewClient, network, from, to, wantAmount, slippageBps });
|
|
819
|
+
},
|
|
820
|
+
async swap(wallet, quote) {
|
|
821
|
+
const { accountId, signer } = resolveNearWallet(wallet._native);
|
|
822
|
+
const account = new Account(accountId, provider, signer);
|
|
823
|
+
return swapNear({
|
|
824
|
+
quote,
|
|
825
|
+
async call({ contractId, method, args, gas, deposit }) {
|
|
826
|
+
const outcome = await account.signAndSendTransaction({
|
|
827
|
+
receiverId: contractId,
|
|
828
|
+
actions: [actions2.functionCall(method, args, gas, deposit)]
|
|
829
|
+
});
|
|
830
|
+
const hash = outcome.transaction?.hash;
|
|
831
|
+
if (!hash) throw new Error("NEAR: signAndSendTransaction returned no tx hash.");
|
|
832
|
+
return hash;
|
|
833
|
+
}
|
|
834
|
+
});
|
|
835
|
+
},
|
|
640
836
|
async verify(ref, accept) {
|
|
641
837
|
const { senderId, hash } = decodeRef(ref);
|
|
642
838
|
return verifyNear({ reader, hash, senderId, accept });
|