@t2000/sdk 0.17.5 → 0.17.8

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/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { I as InvestmentTrade, S as StrategyDefinition, A as AutoInvestSchedule, a as AutoInvestStatus, T as T2000Options, b as SendResult, B as BalanceResponse, c as TransactionRecord, D as DepositInfo, L as LendingAdapter, d as SwapAdapter, e as SaveResult, W as WithdrawResult, M as MaxWithdrawResult, f as BorrowResult, R as RepayResult, g as MaxBorrowResult, H as HealthFactorResult, h as SwapResult, i as InvestResult, j as InvestEarnResult, k as StrategyBuyResult, l as StrategySellResult, m as StrategyRebalanceResult, n as StrategyStatusResult, o as AutoInvestRunResult, P as PortfolioResult, p as InvestmentPosition, q as PositionsResult, r as RatesResult, s as LendingRates, t as RebalanceResult, E as EarningsResult, F as FundStatusResult, u as SentinelAgent, v as SentinelAttackResult, G as GasMethod } from './index-BzQsrfrc.cjs';
2
- export { w as AdapterCapability, x as AdapterPositions, y as AdapterTxResult, z as AssetRates, C as CetusAdapter, J as GasReserve, K as HealthInfo, N as NaviAdapter, O as PerpsAdapter, Q as PerpsPosition, U as PositionEntry, V as PositionSide, X as ProtocolDescriptor, Y as ProtocolRegistry, Z as RebalanceStep, _ as SentinelVerdict, $ as SuilendAdapter, a0 as SwapQuote, a1 as TradePositionsResult, a2 as TradeResult, a3 as allDescriptors, a4 as cetusDescriptor, a5 as getSentinelInfo, a6 as listSentinels, a7 as naviDescriptor, a8 as requestAttack, a9 as sentinelAttack, aa as sentinelDescriptor, ab as settleAttack, ac as submitPrompt, ad as suilendDescriptor } from './index-BzQsrfrc.cjs';
1
+ import { I as InvestmentTrade, S as StrategyDefinition, A as AutoInvestSchedule, a as AutoInvestStatus, T as T2000Options, b as SendResult, B as BalanceResponse, c as TransactionRecord, D as DepositInfo, L as LendingAdapter, d as SwapAdapter, e as SaveResult, W as WithdrawResult, M as MaxWithdrawResult, f as BorrowResult, R as RepayResult, g as MaxBorrowResult, H as HealthFactorResult, h as SwapResult, i as InvestResult, j as InvestEarnResult, k as StrategyBuyResult, l as StrategySellResult, m as StrategyRebalanceResult, n as StrategyStatusResult, o as AutoInvestRunResult, P as PortfolioResult, p as InvestmentPosition, q as PositionsResult, r as RatesResult, s as LendingRates, t as RebalanceResult, E as EarningsResult, F as FundStatusResult, u as SentinelAgent, v as SentinelAttackResult, G as GasMethod } from './index-D4cFY__D.cjs';
2
+ export { w as AdapterCapability, x as AdapterPositions, y as AdapterTxResult, z as AssetRates, C as CetusAdapter, J as GasReserve, K as HealthInfo, N as NaviAdapter, O as PerpsAdapter, Q as PerpsPosition, U as PositionEntry, V as PositionSide, X as ProtocolDescriptor, Y as ProtocolRegistry, Z as RebalanceStep, _ as SentinelVerdict, $ as SuilendAdapter, a0 as SwapQuote, a1 as TradePositionsResult, a2 as TradeResult, a3 as allDescriptors, a4 as cetusDescriptor, a5 as getSentinelInfo, a6 as listSentinels, a7 as naviDescriptor, a8 as requestAttack, a9 as sentinelAttack, aa as sentinelDescriptor, ab as settleAttack, ac as submitPrompt, ad as suilendDescriptor } from './index-D4cFY__D.cjs';
3
3
  import { EventEmitter } from 'eventemitter3';
4
4
  import { SuiJsonRpcClient } from '@mysten/sui/jsonRpc';
5
5
  import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { I as InvestmentTrade, S as StrategyDefinition, A as AutoInvestSchedule, a as AutoInvestStatus, T as T2000Options, b as SendResult, B as BalanceResponse, c as TransactionRecord, D as DepositInfo, L as LendingAdapter, d as SwapAdapter, e as SaveResult, W as WithdrawResult, M as MaxWithdrawResult, f as BorrowResult, R as RepayResult, g as MaxBorrowResult, H as HealthFactorResult, h as SwapResult, i as InvestResult, j as InvestEarnResult, k as StrategyBuyResult, l as StrategySellResult, m as StrategyRebalanceResult, n as StrategyStatusResult, o as AutoInvestRunResult, P as PortfolioResult, p as InvestmentPosition, q as PositionsResult, r as RatesResult, s as LendingRates, t as RebalanceResult, E as EarningsResult, F as FundStatusResult, u as SentinelAgent, v as SentinelAttackResult, G as GasMethod } from './index-BzQsrfrc.js';
2
- export { w as AdapterCapability, x as AdapterPositions, y as AdapterTxResult, z as AssetRates, C as CetusAdapter, J as GasReserve, K as HealthInfo, N as NaviAdapter, O as PerpsAdapter, Q as PerpsPosition, U as PositionEntry, V as PositionSide, X as ProtocolDescriptor, Y as ProtocolRegistry, Z as RebalanceStep, _ as SentinelVerdict, $ as SuilendAdapter, a0 as SwapQuote, a1 as TradePositionsResult, a2 as TradeResult, a3 as allDescriptors, a4 as cetusDescriptor, a5 as getSentinelInfo, a6 as listSentinels, a7 as naviDescriptor, a8 as requestAttack, a9 as sentinelAttack, aa as sentinelDescriptor, ab as settleAttack, ac as submitPrompt, ad as suilendDescriptor } from './index-BzQsrfrc.js';
1
+ import { I as InvestmentTrade, S as StrategyDefinition, A as AutoInvestSchedule, a as AutoInvestStatus, T as T2000Options, b as SendResult, B as BalanceResponse, c as TransactionRecord, D as DepositInfo, L as LendingAdapter, d as SwapAdapter, e as SaveResult, W as WithdrawResult, M as MaxWithdrawResult, f as BorrowResult, R as RepayResult, g as MaxBorrowResult, H as HealthFactorResult, h as SwapResult, i as InvestResult, j as InvestEarnResult, k as StrategyBuyResult, l as StrategySellResult, m as StrategyRebalanceResult, n as StrategyStatusResult, o as AutoInvestRunResult, P as PortfolioResult, p as InvestmentPosition, q as PositionsResult, r as RatesResult, s as LendingRates, t as RebalanceResult, E as EarningsResult, F as FundStatusResult, u as SentinelAgent, v as SentinelAttackResult, G as GasMethod } from './index-D4cFY__D.js';
2
+ export { w as AdapterCapability, x as AdapterPositions, y as AdapterTxResult, z as AssetRates, C as CetusAdapter, J as GasReserve, K as HealthInfo, N as NaviAdapter, O as PerpsAdapter, Q as PerpsPosition, U as PositionEntry, V as PositionSide, X as ProtocolDescriptor, Y as ProtocolRegistry, Z as RebalanceStep, _ as SentinelVerdict, $ as SuilendAdapter, a0 as SwapQuote, a1 as TradePositionsResult, a2 as TradeResult, a3 as allDescriptors, a4 as cetusDescriptor, a5 as getSentinelInfo, a6 as listSentinels, a7 as naviDescriptor, a8 as requestAttack, a9 as sentinelAttack, aa as sentinelDescriptor, ab as settleAttack, ac as submitPrompt, ad as suilendDescriptor } from './index-D4cFY__D.js';
3
3
  import { EventEmitter } from 'eventemitter3';
4
4
  import { SuiJsonRpcClient } from '@mysten/sui/jsonRpc';
5
5
  import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';
package/dist/index.js CHANGED
@@ -4623,50 +4623,90 @@ To sell investment: t2000 invest sell ${params.amount} ${fromAsset}`,
4623
4623
  if (stratPositions.length === 0) {
4624
4624
  throw new T2000Error("INSUFFICIENT_INVESTMENT", `No positions in strategy '${params.strategy}'`);
4625
4625
  }
4626
+ const swapAdapter = this.registry.listSwap()[0];
4627
+ if (!swapAdapter?.addSwapToTx) {
4628
+ throw new T2000Error("PROTOCOL_UNAVAILABLE", "Swap adapter does not support composable PTB");
4629
+ }
4630
+ let swapMetas = [];
4631
+ const gasResult = await executeWithGas(this.client, this.keypair, async () => {
4632
+ swapMetas = [];
4633
+ const tx = new Transaction();
4634
+ tx.setSender(this._address);
4635
+ const usdcOutputs = [];
4636
+ for (const pos of stratPositions) {
4637
+ const assetInfo = SUPPORTED_ASSETS[pos.asset];
4638
+ const coins = await this._fetchCoins(assetInfo.type);
4639
+ if (coins.length === 0) {
4640
+ throw new T2000Error("INSUFFICIENT_BALANCE", `No ${pos.asset} coins in wallet`);
4641
+ }
4642
+ const merged = this._mergeCoinsInTx(tx, coins);
4643
+ const gasReserve = pos.asset === "SUI" ? GAS_RESERVE_MIN : 0;
4644
+ const sellAmount = Math.max(0, pos.totalAmount - gasReserve);
4645
+ const rawAmount = BigInt(Math.floor(sellAmount * 10 ** assetInfo.decimals));
4646
+ const [splitCoin] = tx.splitCoins(merged, [rawAmount]);
4647
+ const assetUsd = sellAmount * (pos.avgPrice || 1);
4648
+ const slippageBps = LOW_LIQUIDITY_ASSETS.has(pos.asset) ? 500 : 300;
4649
+ const { outputCoin, estimatedOut, toDecimals } = await swapAdapter.addSwapToTx(
4650
+ tx,
4651
+ this._address,
4652
+ splitCoin,
4653
+ pos.asset,
4654
+ "USDC",
4655
+ assetUsd,
4656
+ slippageBps
4657
+ );
4658
+ usdcOutputs.push(outputCoin);
4659
+ swapMetas.push({ asset: pos.asset, amount: sellAmount, estimatedOut, toDecimals });
4660
+ }
4661
+ if (usdcOutputs.length > 1) {
4662
+ tx.mergeCoins(usdcOutputs[0], usdcOutputs.slice(1));
4663
+ }
4664
+ tx.transferObjects([usdcOutputs[0]], this._address);
4665
+ return tx;
4666
+ });
4667
+ const digest = gasResult.digest;
4668
+ const now = (/* @__PURE__ */ new Date()).toISOString();
4626
4669
  const sells = [];
4627
4670
  let totalProceeds = 0;
4628
4671
  let totalPnL = 0;
4629
- let totalGas = 0;
4630
- let gasMethod = "self-funded";
4631
- for (const pos of stratPositions) {
4632
- const fullAmount = pos.totalAmount;
4633
- const swapAdapter = this.registry.listSwap()[0];
4634
- let assetPrice = 1;
4635
- try {
4636
- if (swapAdapter) {
4637
- if (pos.asset === "SUI") {
4638
- assetPrice = await swapAdapter.getPoolPrice();
4639
- } else {
4640
- const q = await swapAdapter.getQuote("USDC", pos.asset, 1);
4641
- assetPrice = q.expectedOutput > 0 ? 1 / q.expectedOutput : 1;
4642
- }
4643
- }
4644
- } catch {
4645
- }
4646
- const strategyUsdValue = fullAmount * assetPrice;
4647
- const result = await this.investSell({
4648
- asset: pos.asset,
4649
- usdAmount: strategyUsdValue,
4650
- _strategyOnly: true
4651
- });
4672
+ for (const meta of swapMetas) {
4673
+ const usdValue = meta.estimatedOut / 10 ** meta.toDecimals;
4674
+ const price = meta.amount > 0 ? usdValue / meta.amount : 0;
4652
4675
  const pnl = this.portfolio.recordStrategySell(params.strategy, {
4653
- id: `strat_sell_${Date.now()}_${pos.asset}`,
4676
+ id: `strat_sell_${Date.now()}_${meta.asset}`,
4654
4677
  type: "sell",
4655
- asset: pos.asset,
4656
- amount: fullAmount,
4657
- price: result.price,
4658
- usdValue: result.usdValue,
4659
- fee: result.fee,
4660
- tx: result.tx,
4661
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
4678
+ asset: meta.asset,
4679
+ amount: meta.amount,
4680
+ price,
4681
+ usdValue,
4682
+ fee: 0,
4683
+ tx: digest,
4684
+ timestamp: now
4685
+ });
4686
+ this.portfolio.recordSell({
4687
+ id: `inv_sell_${Date.now()}_${meta.asset}`,
4688
+ type: "sell",
4689
+ asset: meta.asset,
4690
+ amount: meta.amount,
4691
+ price,
4692
+ usdValue,
4693
+ fee: 0,
4694
+ tx: digest,
4695
+ timestamp: now
4662
4696
  });
4663
- sells.push({ asset: pos.asset, amount: result.amount, usdValue: result.usdValue, realizedPnL: pnl, tx: result.tx });
4664
- totalProceeds += result.usdValue;
4697
+ sells.push({ asset: meta.asset, amount: meta.amount, usdValue, realizedPnL: pnl, tx: digest });
4698
+ totalProceeds += usdValue;
4665
4699
  totalPnL += pnl;
4666
- totalGas += result.gasCost;
4667
- gasMethod = result.gasMethod;
4668
4700
  }
4669
- return { success: true, strategy: params.strategy, totalProceeds, realizedPnL: totalPnL, sells, gasCost: totalGas, gasMethod };
4701
+ return {
4702
+ success: true,
4703
+ strategy: params.strategy,
4704
+ totalProceeds,
4705
+ realizedPnL: totalPnL,
4706
+ sells,
4707
+ gasCost: gasResult.gasCostSui,
4708
+ gasMethod: gasResult.gasMethod
4709
+ };
4670
4710
  }
4671
4711
  async rebalanceStrategy(params) {
4672
4712
  this.enforcer.assertNotLocked();
@@ -4700,8 +4740,9 @@ To sell investment: t2000 invest sell ${params.amount} ${fromAsset}`,
4700
4740
  currentWeights[pos.asset] = w;
4701
4741
  beforeWeights[pos.asset] = w;
4702
4742
  }
4703
- const trades = [];
4704
4743
  const threshold = 3;
4744
+ const sellOps = [];
4745
+ const buyOps = [];
4705
4746
  for (const [asset, targetPct] of Object.entries(definition.allocations)) {
4706
4747
  const currentPct = currentWeights[asset] ?? 0;
4707
4748
  const diff = targetPct - currentPct;
@@ -4709,33 +4750,140 @@ To sell investment: t2000 invest sell ${params.amount} ${fromAsset}`,
4709
4750
  const usdDiff = totalValue * (Math.abs(diff) / 100);
4710
4751
  if (usdDiff < 1) continue;
4711
4752
  if (diff > 0) {
4712
- const result = await this.investBuy({ asset, usdAmount: usdDiff });
4713
- this.portfolio.recordStrategyBuy(params.strategy, {
4714
- id: `strat_rebal_${Date.now()}_${asset}`,
4715
- type: "buy",
4716
- asset,
4717
- amount: result.amount,
4718
- price: result.price,
4719
- usdValue: usdDiff,
4720
- fee: result.fee,
4721
- tx: result.tx,
4722
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
4723
- });
4724
- trades.push({ action: "buy", asset, usdAmount: usdDiff, amount: result.amount, tx: result.tx });
4753
+ buyOps.push({ asset, usdAmount: usdDiff });
4725
4754
  } else {
4726
- const result = await this.investSell({ asset, usdAmount: usdDiff });
4755
+ const price = prices[asset] ?? 1;
4756
+ const assetAmount = price > 0 ? usdDiff / price : 0;
4757
+ sellOps.push({ asset, usdAmount: usdDiff, assetAmount });
4758
+ }
4759
+ }
4760
+ if (sellOps.length === 0 && buyOps.length === 0) {
4761
+ return { success: true, strategy: params.strategy, trades: [], beforeWeights, afterWeights: { ...beforeWeights }, targetWeights: { ...definition.allocations } };
4762
+ }
4763
+ if (!swapAdapter?.addSwapToTx) {
4764
+ throw new T2000Error("PROTOCOL_UNAVAILABLE", "Swap adapter does not support composable PTB");
4765
+ }
4766
+ const tradeMetas = [];
4767
+ const gasResult = await executeWithGas(this.client, this.keypair, async () => {
4768
+ tradeMetas.length = 0;
4769
+ const tx = new Transaction();
4770
+ tx.setSender(this._address);
4771
+ const usdcCoins = [];
4772
+ for (const sell of sellOps) {
4773
+ const assetInfo = SUPPORTED_ASSETS[sell.asset];
4774
+ const coins = await this._fetchCoins(assetInfo.type);
4775
+ if (coins.length === 0) continue;
4776
+ const merged = this._mergeCoinsInTx(tx, coins);
4777
+ const gasReserve = sell.asset === "SUI" ? GAS_RESERVE_MIN : 0;
4778
+ const sellAmount = Math.max(0, sell.assetAmount - gasReserve);
4779
+ const rawAmount = BigInt(Math.floor(sellAmount * 10 ** assetInfo.decimals));
4780
+ const [splitCoin] = tx.splitCoins(merged, [rawAmount]);
4781
+ const slippageBps = LOW_LIQUIDITY_ASSETS.has(sell.asset) ? 500 : 300;
4782
+ const { outputCoin, estimatedOut, toDecimals } = await swapAdapter.addSwapToTx(
4783
+ tx,
4784
+ this._address,
4785
+ splitCoin,
4786
+ sell.asset,
4787
+ "USDC",
4788
+ sell.usdAmount,
4789
+ slippageBps
4790
+ );
4791
+ usdcCoins.push(outputCoin);
4792
+ tradeMetas.push({ action: "sell", asset: sell.asset, usdAmount: sell.usdAmount, estimatedOut, toDecimals });
4793
+ }
4794
+ if (buyOps.length > 0) {
4795
+ const walletUsdc = await this._fetchCoins(SUPPORTED_ASSETS.USDC.type);
4796
+ if (walletUsdc.length > 0) {
4797
+ usdcCoins.push(this._mergeCoinsInTx(tx, walletUsdc));
4798
+ }
4799
+ if (usdcCoins.length === 0) {
4800
+ throw new T2000Error("INSUFFICIENT_BALANCE", "No USDC available for rebalance buys");
4801
+ }
4802
+ if (usdcCoins.length > 1) {
4803
+ tx.mergeCoins(usdcCoins[0], usdcCoins.slice(1));
4804
+ }
4805
+ const mergedUsdc = usdcCoins[0];
4806
+ const splitAmounts = buyOps.map(
4807
+ (b) => BigInt(Math.floor(b.usdAmount * 10 ** SUPPORTED_ASSETS.USDC.decimals))
4808
+ );
4809
+ const splitCoins = tx.splitCoins(mergedUsdc, splitAmounts);
4810
+ const outputCoins = [];
4811
+ for (let i = 0; i < buyOps.length; i++) {
4812
+ const buy = buyOps[i];
4813
+ const slippageBps = LOW_LIQUIDITY_ASSETS.has(buy.asset) ? 500 : 300;
4814
+ const { outputCoin, estimatedOut, toDecimals } = await swapAdapter.addSwapToTx(
4815
+ tx,
4816
+ this._address,
4817
+ splitCoins[i],
4818
+ "USDC",
4819
+ buy.asset,
4820
+ buy.usdAmount,
4821
+ slippageBps
4822
+ );
4823
+ outputCoins.push(outputCoin);
4824
+ tradeMetas.push({ action: "buy", asset: buy.asset, usdAmount: buy.usdAmount, estimatedOut, toDecimals });
4825
+ }
4826
+ tx.transferObjects(outputCoins, this._address);
4827
+ }
4828
+ return tx;
4829
+ });
4830
+ const digest = gasResult.digest;
4831
+ const now = (/* @__PURE__ */ new Date()).toISOString();
4832
+ const trades = [];
4833
+ for (const meta of tradeMetas) {
4834
+ const rawAmount = meta.estimatedOut / 10 ** meta.toDecimals;
4835
+ if (meta.action === "sell") {
4836
+ const price = meta.usdAmount > 0 && rawAmount > 0 ? meta.usdAmount / rawAmount : prices[meta.asset] ?? 0;
4837
+ const assetAmount = prices[meta.asset] > 0 ? meta.usdAmount / prices[meta.asset] : 0;
4727
4838
  this.portfolio.recordStrategySell(params.strategy, {
4728
- id: `strat_rebal_${Date.now()}_${asset}`,
4839
+ id: `strat_rebal_${Date.now()}_${meta.asset}`,
4729
4840
  type: "sell",
4730
- asset,
4731
- amount: result.amount,
4732
- price: result.price,
4733
- usdValue: result.usdValue,
4734
- fee: result.fee,
4735
- tx: result.tx,
4736
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
4841
+ asset: meta.asset,
4842
+ amount: assetAmount,
4843
+ price,
4844
+ usdValue: meta.usdAmount,
4845
+ fee: 0,
4846
+ tx: digest,
4847
+ timestamp: now
4848
+ });
4849
+ this.portfolio.recordSell({
4850
+ id: `inv_rebal_${Date.now()}_${meta.asset}`,
4851
+ type: "sell",
4852
+ asset: meta.asset,
4853
+ amount: assetAmount,
4854
+ price,
4855
+ usdValue: meta.usdAmount,
4856
+ fee: 0,
4857
+ tx: digest,
4858
+ timestamp: now
4859
+ });
4860
+ trades.push({ action: "sell", asset: meta.asset, usdAmount: meta.usdAmount, amount: assetAmount, tx: digest });
4861
+ } else {
4862
+ const amount = rawAmount;
4863
+ const price = meta.usdAmount / amount;
4864
+ this.portfolio.recordBuy({
4865
+ id: `inv_rebal_${Date.now()}_${meta.asset}`,
4866
+ type: "buy",
4867
+ asset: meta.asset,
4868
+ amount,
4869
+ price,
4870
+ usdValue: meta.usdAmount,
4871
+ fee: 0,
4872
+ tx: digest,
4873
+ timestamp: now
4874
+ });
4875
+ this.portfolio.recordStrategyBuy(params.strategy, {
4876
+ id: `strat_rebal_${Date.now()}_${meta.asset}`,
4877
+ type: "buy",
4878
+ asset: meta.asset,
4879
+ amount,
4880
+ price,
4881
+ usdValue: meta.usdAmount,
4882
+ fee: 0,
4883
+ tx: digest,
4884
+ timestamp: now
4737
4885
  });
4738
- trades.push({ action: "sell", asset, usdAmount: result.usdValue, amount: result.amount, tx: result.tx });
4886
+ trades.push({ action: "buy", asset: meta.asset, usdAmount: meta.usdAmount, amount, tx: digest });
4739
4887
  }
4740
4888
  }
4741
4889
  const afterWeights = {};