@t2000/sdk 0.9.2 → 0.9.4

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.
@@ -503,6 +503,94 @@ async function buildWithdrawTx(client, address, amount, options = {}) {
503
503
  tx.transferObjects([coin], address);
504
504
  return { tx, effectiveAmount };
505
505
  }
506
+ async function addWithdrawToTx(tx, client, address, amount, options = {}) {
507
+ const asset = options.asset ?? "USDC";
508
+ const assetInfo = SUPPORTED_ASSETS[asset];
509
+ const [config, pool, pools, states] = await Promise.all([
510
+ getConfig(),
511
+ getPool(asset),
512
+ getPools(),
513
+ getUserState(client, address)
514
+ ]);
515
+ const assetState = states.find((s) => s.assetId === pool.id);
516
+ const deposited = assetState ? compoundBalance(assetState.supplyBalance, pool.currentSupplyIndex) : 0;
517
+ const effectiveAmount = Math.min(amount, Math.max(0, deposited - WITHDRAW_DUST_BUFFER));
518
+ if (effectiveAmount <= 0) throw new T2000Error("NO_COLLATERAL", `Nothing to withdraw for ${assetInfo.displayName} on NAVI`);
519
+ const rawAmount = Number(stableToRaw(effectiveAmount, assetInfo.decimals));
520
+ addOracleUpdatesForPositions(tx, config, pools, states, pool);
521
+ const [balance] = tx.moveCall({
522
+ target: `${config.package}::incentive_v3::withdraw_v2`,
523
+ arguments: [
524
+ tx.object(CLOCK),
525
+ tx.object(config.oracle.priceOracle),
526
+ tx.object(config.storage),
527
+ tx.object(pool.contract.pool),
528
+ tx.pure.u8(pool.id),
529
+ tx.pure.u64(rawAmount),
530
+ tx.object(config.incentiveV2),
531
+ tx.object(config.incentiveV3),
532
+ tx.object(SUI_SYSTEM_STATE)
533
+ ],
534
+ typeArguments: [pool.suiCoinType]
535
+ });
536
+ const [coin] = tx.moveCall({
537
+ target: "0x2::coin::from_balance",
538
+ arguments: [balance],
539
+ typeArguments: [pool.suiCoinType]
540
+ });
541
+ return { coin, effectiveAmount };
542
+ }
543
+ async function addSaveToTx(tx, _client, _address, coin, options = {}) {
544
+ const asset = options.asset ?? "USDC";
545
+ const [config, pool] = await Promise.all([getConfig(), getPool(asset)]);
546
+ if (options.collectFee) {
547
+ addCollectFeeToTx(tx, coin, "save");
548
+ }
549
+ const [coinValue] = tx.moveCall({
550
+ target: "0x2::coin::value",
551
+ typeArguments: [pool.suiCoinType],
552
+ arguments: [coin]
553
+ });
554
+ tx.moveCall({
555
+ target: `${config.package}::incentive_v3::entry_deposit`,
556
+ arguments: [
557
+ tx.object(CLOCK),
558
+ tx.object(config.storage),
559
+ tx.object(pool.contract.pool),
560
+ tx.pure.u8(pool.id),
561
+ coin,
562
+ coinValue,
563
+ tx.object(config.incentiveV2),
564
+ tx.object(config.incentiveV3)
565
+ ],
566
+ typeArguments: [pool.suiCoinType]
567
+ });
568
+ }
569
+ async function addRepayToTx(tx, client, _address, coin, options = {}) {
570
+ const asset = options.asset ?? "USDC";
571
+ const [config, pool] = await Promise.all([getConfig(), getPool(asset)]);
572
+ addOracleUpdate(tx, config, pool);
573
+ const [coinValue] = tx.moveCall({
574
+ target: "0x2::coin::value",
575
+ typeArguments: [pool.suiCoinType],
576
+ arguments: [coin]
577
+ });
578
+ tx.moveCall({
579
+ target: `${config.package}::incentive_v3::entry_repay`,
580
+ arguments: [
581
+ tx.object(CLOCK),
582
+ tx.object(config.oracle.priceOracle),
583
+ tx.object(config.storage),
584
+ tx.object(pool.contract.pool),
585
+ tx.pure.u8(pool.id),
586
+ coin,
587
+ coinValue,
588
+ tx.object(config.incentiveV2),
589
+ tx.object(config.incentiveV3)
590
+ ],
591
+ typeArguments: [pool.suiCoinType]
592
+ });
593
+ }
506
594
  async function buildBorrowTx(client, address, amount, options = {}) {
507
595
  if (!amount || amount <= 0 || !Number.isFinite(amount)) {
508
596
  throw new T2000Error("INVALID_AMOUNT", "Borrow amount must be a positive number");
@@ -794,6 +882,18 @@ var NaviAdapter = class {
794
882
  async maxBorrow(address, _asset) {
795
883
  return maxBorrowAmount(this.client, address);
796
884
  }
885
+ async addWithdrawToTx(tx, address, amount, asset) {
886
+ const stableAsset = normalizeAsset(asset);
887
+ return addWithdrawToTx(tx, this.client, address, amount, { asset: stableAsset });
888
+ }
889
+ async addSaveToTx(tx, address, coin, asset, options) {
890
+ const stableAsset = normalizeAsset(asset);
891
+ return addSaveToTx(tx, this.client, address, coin, { ...options, asset: stableAsset });
892
+ }
893
+ async addRepayToTx(tx, address, coin, asset) {
894
+ const stableAsset = normalizeAsset(asset);
895
+ return addRepayToTx(tx, this.client, address, coin, { asset: stableAsset });
896
+ }
797
897
  };
798
898
  var DEFAULT_SLIPPAGE_BPS = 300;
799
899
  function createAggregatorClient(client, signer) {
@@ -838,6 +938,41 @@ async function buildSwapTx(params) {
838
938
  toDecimals: toInfo.decimals
839
939
  };
840
940
  }
941
+ async function addSwapToTx(params) {
942
+ const { tx, client, address, inputCoin, fromAsset, toAsset, amount, maxSlippageBps = DEFAULT_SLIPPAGE_BPS } = params;
943
+ const fromInfo = SUPPORTED_ASSETS[fromAsset];
944
+ const toInfo = SUPPORTED_ASSETS[toAsset];
945
+ if (!fromInfo || !toInfo) {
946
+ throw new T2000Error("ASSET_NOT_SUPPORTED", `Swap pair ${fromAsset}/${toAsset} is not supported`);
947
+ }
948
+ const rawAmount = BigInt(Math.floor(amount * 10 ** fromInfo.decimals));
949
+ const aggClient = createAggregatorClient(client, address);
950
+ const result = await aggClient.findRouters({
951
+ from: fromInfo.type,
952
+ target: toInfo.type,
953
+ amount: rawAmount,
954
+ byAmountIn: true
955
+ });
956
+ if (!result || result.insufficientLiquidity) {
957
+ throw new T2000Error(
958
+ "ASSET_NOT_SUPPORTED",
959
+ `No swap route found for ${fromAsset} \u2192 ${toAsset}`
960
+ );
961
+ }
962
+ const slippage = maxSlippageBps / 1e4;
963
+ const outputCoin = await aggClient.routerSwap({
964
+ router: result,
965
+ txb: tx,
966
+ inputCoin,
967
+ slippage
968
+ });
969
+ const estimatedOut = Number(result.amountOut.toString());
970
+ return {
971
+ outputCoin,
972
+ estimatedOut,
973
+ toDecimals: toInfo.decimals
974
+ };
975
+ }
841
976
  async function getPoolPrice(client) {
842
977
  try {
843
978
  const pool = await client.getObject({
@@ -948,6 +1083,18 @@ var CetusAdapter = class {
948
1083
  async getPoolPrice() {
949
1084
  return getPoolPrice(this.client);
950
1085
  }
1086
+ async addSwapToTx(tx, address, inputCoin, from, to, amount, maxSlippageBps) {
1087
+ return addSwapToTx({
1088
+ tx,
1089
+ client: this.client,
1090
+ address,
1091
+ inputCoin,
1092
+ fromAsset: from,
1093
+ toAsset: to,
1094
+ amount,
1095
+ maxSlippageBps
1096
+ });
1097
+ }
951
1098
  };
952
1099
  var WAD = 1e18;
953
1100
  var MIN_HEALTH_FACTOR2 = 1.5;
@@ -1343,6 +1490,95 @@ var SuilendAdapter = class {
1343
1490
  tx.transferObjects([coin], address);
1344
1491
  return { tx, effectiveAmount };
1345
1492
  }
1493
+ async addWithdrawToTx(tx, address, amount, asset) {
1494
+ const assetKey = asset in SUPPORTED_ASSETS ? asset : "USDC";
1495
+ const assetInfo = SUPPORTED_ASSETS[assetKey];
1496
+ const [pkg, reserves] = await Promise.all([this.resolvePackage(), this.loadReserves(true)]);
1497
+ const reserve = this.findReserve(reserves, assetKey);
1498
+ if (!reserve) throw new T2000Error("ASSET_NOT_SUPPORTED", `${assetInfo.displayName} reserve not found on Suilend`);
1499
+ const caps = await this.fetchObligationCaps(address);
1500
+ if (caps.length === 0) throw new T2000Error("NO_COLLATERAL", "No Suilend position found");
1501
+ const positions = await this.getPositions(address);
1502
+ const deposited = positions.supplies.find((s) => s.asset === assetKey)?.amount ?? 0;
1503
+ const effectiveAmount = Math.min(amount, deposited);
1504
+ if (effectiveAmount <= 0) throw new T2000Error("NO_COLLATERAL", `Nothing to withdraw for ${assetInfo.displayName} on Suilend`);
1505
+ const ratio = cTokenRatio(reserve);
1506
+ const ctokenAmount = Math.ceil(effectiveAmount * 10 ** reserve.mintDecimals / ratio);
1507
+ const [ctokens] = tx.moveCall({
1508
+ target: `${pkg}::lending_market::withdraw_ctokens`,
1509
+ typeArguments: [LENDING_MARKET_TYPE, assetInfo.type],
1510
+ arguments: [
1511
+ tx.object(LENDING_MARKET_ID),
1512
+ tx.pure.u64(reserve.arrayIndex),
1513
+ tx.object(caps[0].id),
1514
+ tx.object(CLOCK2),
1515
+ tx.pure.u64(ctokenAmount)
1516
+ ]
1517
+ });
1518
+ const exemptionType = `${SUILEND_PACKAGE}::lending_market::RateLimiterExemption<${LENDING_MARKET_TYPE}, ${assetInfo.type}>`;
1519
+ const [none] = tx.moveCall({
1520
+ target: "0x1::option::none",
1521
+ typeArguments: [exemptionType]
1522
+ });
1523
+ const [coin] = tx.moveCall({
1524
+ target: `${pkg}::lending_market::redeem_ctokens_and_withdraw_liquidity`,
1525
+ typeArguments: [LENDING_MARKET_TYPE, assetInfo.type],
1526
+ arguments: [
1527
+ tx.object(LENDING_MARKET_ID),
1528
+ tx.pure.u64(reserve.arrayIndex),
1529
+ tx.object(CLOCK2),
1530
+ ctokens,
1531
+ none
1532
+ ]
1533
+ });
1534
+ return { coin, effectiveAmount };
1535
+ }
1536
+ async addSaveToTx(tx, address, coin, asset, options) {
1537
+ const assetKey = asset in SUPPORTED_ASSETS ? asset : "USDC";
1538
+ const assetInfo = SUPPORTED_ASSETS[assetKey];
1539
+ const [pkg, reserves] = await Promise.all([this.resolvePackage(), this.loadReserves()]);
1540
+ const reserve = this.findReserve(reserves, assetKey);
1541
+ if (!reserve) throw new T2000Error("ASSET_NOT_SUPPORTED", `${assetInfo.displayName} reserve not found on Suilend`);
1542
+ const caps = await this.fetchObligationCaps(address);
1543
+ let capRef;
1544
+ if (caps.length === 0) {
1545
+ const [newCap] = tx.moveCall({
1546
+ target: `${pkg}::lending_market::create_obligation`,
1547
+ typeArguments: [LENDING_MARKET_TYPE],
1548
+ arguments: [tx.object(LENDING_MARKET_ID)]
1549
+ });
1550
+ capRef = newCap;
1551
+ } else {
1552
+ capRef = caps[0].id;
1553
+ }
1554
+ if (options?.collectFee) {
1555
+ addCollectFeeToTx(tx, coin, "save");
1556
+ }
1557
+ const [ctokens] = tx.moveCall({
1558
+ target: `${pkg}::lending_market::deposit_liquidity_and_mint_ctokens`,
1559
+ typeArguments: [LENDING_MARKET_TYPE, assetInfo.type],
1560
+ arguments: [
1561
+ tx.object(LENDING_MARKET_ID),
1562
+ tx.pure.u64(reserve.arrayIndex),
1563
+ tx.object(CLOCK2),
1564
+ coin
1565
+ ]
1566
+ });
1567
+ tx.moveCall({
1568
+ target: `${pkg}::lending_market::deposit_ctokens_into_obligation`,
1569
+ typeArguments: [LENDING_MARKET_TYPE, assetInfo.type],
1570
+ arguments: [
1571
+ tx.object(LENDING_MARKET_ID),
1572
+ tx.pure.u64(reserve.arrayIndex),
1573
+ typeof capRef === "string" ? tx.object(capRef) : capRef,
1574
+ tx.object(CLOCK2),
1575
+ ctokens
1576
+ ]
1577
+ });
1578
+ if (typeof capRef !== "string") {
1579
+ tx.transferObjects([capRef], address);
1580
+ }
1581
+ }
1346
1582
  async buildBorrowTx(address, amount, asset, options) {
1347
1583
  const assetKey = asset in SUPPORTED_ASSETS ? asset : "USDC";
1348
1584
  const assetInfo = SUPPORTED_ASSETS[assetKey];
@@ -1402,6 +1638,26 @@ var SuilendAdapter = class {
1402
1638
  });
1403
1639
  return { tx };
1404
1640
  }
1641
+ async addRepayToTx(tx, address, coin, asset) {
1642
+ const assetKey = asset in SUPPORTED_ASSETS ? asset : "USDC";
1643
+ const assetInfo = SUPPORTED_ASSETS[assetKey];
1644
+ const [pkg, reserves] = await Promise.all([this.resolvePackage(), this.loadReserves()]);
1645
+ const reserve = this.findReserve(reserves, assetKey);
1646
+ if (!reserve) throw new T2000Error("ASSET_NOT_SUPPORTED", `${assetInfo.displayName} reserve not found on Suilend`);
1647
+ const caps = await this.fetchObligationCaps(address);
1648
+ if (caps.length === 0) throw new T2000Error("NO_COLLATERAL", "No Suilend obligation found");
1649
+ tx.moveCall({
1650
+ target: `${pkg}::lending_market::repay`,
1651
+ typeArguments: [LENDING_MARKET_TYPE, assetInfo.type],
1652
+ arguments: [
1653
+ tx.object(LENDING_MARKET_ID),
1654
+ tx.pure.u64(reserve.arrayIndex),
1655
+ tx.object(caps[0].id),
1656
+ tx.object(CLOCK2),
1657
+ coin
1658
+ ]
1659
+ });
1660
+ }
1405
1661
  async maxWithdraw(address, _asset) {
1406
1662
  const health = await this.getHealth(address);
1407
1663
  let maxAmount;