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