@t2000/sdk 0.17.5 → 0.17.9

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,89 @@ 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 slippageBps = LOW_LIQUIDITY_ASSETS.has(pos.asset) ? 500 : 300;
4648
+ const { outputCoin, estimatedOut, toDecimals } = await swapAdapter.addSwapToTx(
4649
+ tx,
4650
+ this._address,
4651
+ splitCoin,
4652
+ pos.asset,
4653
+ "USDC",
4654
+ sellAmount,
4655
+ slippageBps
4656
+ );
4657
+ usdcOutputs.push(outputCoin);
4658
+ swapMetas.push({ asset: pos.asset, amount: sellAmount, estimatedOut, toDecimals });
4659
+ }
4660
+ if (usdcOutputs.length > 1) {
4661
+ tx.mergeCoins(usdcOutputs[0], usdcOutputs.slice(1));
4662
+ }
4663
+ tx.transferObjects([usdcOutputs[0]], this._address);
4664
+ return tx;
4665
+ });
4666
+ const digest = gasResult.digest;
4667
+ const now = (/* @__PURE__ */ new Date()).toISOString();
4626
4668
  const sells = [];
4627
4669
  let totalProceeds = 0;
4628
4670
  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
- });
4671
+ for (const meta of swapMetas) {
4672
+ const usdValue = meta.estimatedOut / 10 ** meta.toDecimals;
4673
+ const price = meta.amount > 0 ? usdValue / meta.amount : 0;
4652
4674
  const pnl = this.portfolio.recordStrategySell(params.strategy, {
4653
- id: `strat_sell_${Date.now()}_${pos.asset}`,
4675
+ id: `strat_sell_${Date.now()}_${meta.asset}`,
4654
4676
  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()
4677
+ asset: meta.asset,
4678
+ amount: meta.amount,
4679
+ price,
4680
+ usdValue,
4681
+ fee: 0,
4682
+ tx: digest,
4683
+ timestamp: now
4684
+ });
4685
+ this.portfolio.recordSell({
4686
+ id: `inv_sell_${Date.now()}_${meta.asset}`,
4687
+ type: "sell",
4688
+ asset: meta.asset,
4689
+ amount: meta.amount,
4690
+ price,
4691
+ usdValue,
4692
+ fee: 0,
4693
+ tx: digest,
4694
+ timestamp: now
4662
4695
  });
4663
- sells.push({ asset: pos.asset, amount: result.amount, usdValue: result.usdValue, realizedPnL: pnl, tx: result.tx });
4664
- totalProceeds += result.usdValue;
4696
+ sells.push({ asset: meta.asset, amount: meta.amount, usdValue, realizedPnL: pnl, tx: digest });
4697
+ totalProceeds += usdValue;
4665
4698
  totalPnL += pnl;
4666
- totalGas += result.gasCost;
4667
- gasMethod = result.gasMethod;
4668
4699
  }
4669
- return { success: true, strategy: params.strategy, totalProceeds, realizedPnL: totalPnL, sells, gasCost: totalGas, gasMethod };
4700
+ return {
4701
+ success: true,
4702
+ strategy: params.strategy,
4703
+ totalProceeds,
4704
+ realizedPnL: totalPnL,
4705
+ sells,
4706
+ gasCost: gasResult.gasCostSui,
4707
+ gasMethod: gasResult.gasMethod
4708
+ };
4670
4709
  }
4671
4710
  async rebalanceStrategy(params) {
4672
4711
  this.enforcer.assertNotLocked();
@@ -4700,8 +4739,9 @@ To sell investment: t2000 invest sell ${params.amount} ${fromAsset}`,
4700
4739
  currentWeights[pos.asset] = w;
4701
4740
  beforeWeights[pos.asset] = w;
4702
4741
  }
4703
- const trades = [];
4704
4742
  const threshold = 3;
4743
+ const sellOps = [];
4744
+ const buyOps = [];
4705
4745
  for (const [asset, targetPct] of Object.entries(definition.allocations)) {
4706
4746
  const currentPct = currentWeights[asset] ?? 0;
4707
4747
  const diff = targetPct - currentPct;
@@ -4709,33 +4749,140 @@ To sell investment: t2000 invest sell ${params.amount} ${fromAsset}`,
4709
4749
  const usdDiff = totalValue * (Math.abs(diff) / 100);
4710
4750
  if (usdDiff < 1) continue;
4711
4751
  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 });
4752
+ buyOps.push({ asset, usdAmount: usdDiff });
4725
4753
  } else {
4726
- const result = await this.investSell({ asset, usdAmount: usdDiff });
4754
+ const price = prices[asset] ?? 1;
4755
+ const assetAmount = price > 0 ? usdDiff / price : 0;
4756
+ sellOps.push({ asset, usdAmount: usdDiff, assetAmount });
4757
+ }
4758
+ }
4759
+ if (sellOps.length === 0 && buyOps.length === 0) {
4760
+ return { success: true, strategy: params.strategy, trades: [], beforeWeights, afterWeights: { ...beforeWeights }, targetWeights: { ...definition.allocations } };
4761
+ }
4762
+ if (!swapAdapter?.addSwapToTx) {
4763
+ throw new T2000Error("PROTOCOL_UNAVAILABLE", "Swap adapter does not support composable PTB");
4764
+ }
4765
+ const tradeMetas = [];
4766
+ const gasResult = await executeWithGas(this.client, this.keypair, async () => {
4767
+ tradeMetas.length = 0;
4768
+ const tx = new Transaction();
4769
+ tx.setSender(this._address);
4770
+ const usdcCoins = [];
4771
+ for (const sell of sellOps) {
4772
+ const assetInfo = SUPPORTED_ASSETS[sell.asset];
4773
+ const coins = await this._fetchCoins(assetInfo.type);
4774
+ if (coins.length === 0) continue;
4775
+ const merged = this._mergeCoinsInTx(tx, coins);
4776
+ const gasReserve = sell.asset === "SUI" ? GAS_RESERVE_MIN : 0;
4777
+ const sellAmount = Math.max(0, sell.assetAmount - gasReserve);
4778
+ const rawAmount = BigInt(Math.floor(sellAmount * 10 ** assetInfo.decimals));
4779
+ const [splitCoin] = tx.splitCoins(merged, [rawAmount]);
4780
+ const slippageBps = LOW_LIQUIDITY_ASSETS.has(sell.asset) ? 500 : 300;
4781
+ const { outputCoin, estimatedOut, toDecimals } = await swapAdapter.addSwapToTx(
4782
+ tx,
4783
+ this._address,
4784
+ splitCoin,
4785
+ sell.asset,
4786
+ "USDC",
4787
+ sellAmount,
4788
+ slippageBps
4789
+ );
4790
+ usdcCoins.push(outputCoin);
4791
+ tradeMetas.push({ action: "sell", asset: sell.asset, usdAmount: sell.usdAmount, estimatedOut, toDecimals });
4792
+ }
4793
+ if (buyOps.length > 0) {
4794
+ const walletUsdc = await this._fetchCoins(SUPPORTED_ASSETS.USDC.type);
4795
+ if (walletUsdc.length > 0) {
4796
+ usdcCoins.push(this._mergeCoinsInTx(tx, walletUsdc));
4797
+ }
4798
+ if (usdcCoins.length === 0) {
4799
+ throw new T2000Error("INSUFFICIENT_BALANCE", "No USDC available for rebalance buys");
4800
+ }
4801
+ if (usdcCoins.length > 1) {
4802
+ tx.mergeCoins(usdcCoins[0], usdcCoins.slice(1));
4803
+ }
4804
+ const mergedUsdc = usdcCoins[0];
4805
+ const splitAmounts = buyOps.map(
4806
+ (b) => BigInt(Math.floor(b.usdAmount * 10 ** SUPPORTED_ASSETS.USDC.decimals))
4807
+ );
4808
+ const splitCoins = tx.splitCoins(mergedUsdc, splitAmounts);
4809
+ const outputCoins = [];
4810
+ for (let i = 0; i < buyOps.length; i++) {
4811
+ const buy = buyOps[i];
4812
+ const slippageBps = LOW_LIQUIDITY_ASSETS.has(buy.asset) ? 500 : 300;
4813
+ const { outputCoin, estimatedOut, toDecimals } = await swapAdapter.addSwapToTx(
4814
+ tx,
4815
+ this._address,
4816
+ splitCoins[i],
4817
+ "USDC",
4818
+ buy.asset,
4819
+ buy.usdAmount,
4820
+ slippageBps
4821
+ );
4822
+ outputCoins.push(outputCoin);
4823
+ tradeMetas.push({ action: "buy", asset: buy.asset, usdAmount: buy.usdAmount, estimatedOut, toDecimals });
4824
+ }
4825
+ tx.transferObjects(outputCoins, this._address);
4826
+ }
4827
+ return tx;
4828
+ });
4829
+ const digest = gasResult.digest;
4830
+ const now = (/* @__PURE__ */ new Date()).toISOString();
4831
+ const trades = [];
4832
+ for (const meta of tradeMetas) {
4833
+ const rawAmount = meta.estimatedOut / 10 ** meta.toDecimals;
4834
+ if (meta.action === "sell") {
4835
+ const price = meta.usdAmount > 0 && rawAmount > 0 ? meta.usdAmount / rawAmount : prices[meta.asset] ?? 0;
4836
+ const assetAmount = prices[meta.asset] > 0 ? meta.usdAmount / prices[meta.asset] : 0;
4727
4837
  this.portfolio.recordStrategySell(params.strategy, {
4728
- id: `strat_rebal_${Date.now()}_${asset}`,
4838
+ id: `strat_rebal_${Date.now()}_${meta.asset}`,
4729
4839
  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()
4840
+ asset: meta.asset,
4841
+ amount: assetAmount,
4842
+ price,
4843
+ usdValue: meta.usdAmount,
4844
+ fee: 0,
4845
+ tx: digest,
4846
+ timestamp: now
4847
+ });
4848
+ this.portfolio.recordSell({
4849
+ id: `inv_rebal_${Date.now()}_${meta.asset}`,
4850
+ type: "sell",
4851
+ asset: meta.asset,
4852
+ amount: assetAmount,
4853
+ price,
4854
+ usdValue: meta.usdAmount,
4855
+ fee: 0,
4856
+ tx: digest,
4857
+ timestamp: now
4858
+ });
4859
+ trades.push({ action: "sell", asset: meta.asset, usdAmount: meta.usdAmount, amount: assetAmount, tx: digest });
4860
+ } else {
4861
+ const amount = rawAmount;
4862
+ const price = meta.usdAmount / amount;
4863
+ this.portfolio.recordBuy({
4864
+ id: `inv_rebal_${Date.now()}_${meta.asset}`,
4865
+ type: "buy",
4866
+ asset: meta.asset,
4867
+ amount,
4868
+ price,
4869
+ usdValue: meta.usdAmount,
4870
+ fee: 0,
4871
+ tx: digest,
4872
+ timestamp: now
4873
+ });
4874
+ this.portfolio.recordStrategyBuy(params.strategy, {
4875
+ id: `strat_rebal_${Date.now()}_${meta.asset}`,
4876
+ type: "buy",
4877
+ asset: meta.asset,
4878
+ amount,
4879
+ price,
4880
+ usdValue: meta.usdAmount,
4881
+ fee: 0,
4882
+ tx: digest,
4883
+ timestamp: now
4737
4884
  });
4738
- trades.push({ action: "sell", asset, usdAmount: result.usdValue, amount: result.amount, tx: result.tx });
4885
+ trades.push({ action: "buy", asset: meta.asset, usdAmount: meta.usdAmount, amount, tx: digest });
4739
4886
  }
4740
4887
  }
4741
4888
  const afterWeights = {};