@t2000/sdk 0.17.4 → 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/adapters/index.d.cts +1 -1
- package/dist/adapters/index.d.ts +1 -1
- package/dist/{index-BzQsrfrc.d.cts → index-D4cFY__D.d.cts} +4 -0
- package/dist/{index-BzQsrfrc.d.ts → index-D4cFY__D.d.ts} +4 -0
- package/dist/index.cjs +214 -62
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +214 -62
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
@@ -3364,6 +3364,10 @@ var AutoInvestManager = class {
|
|
|
3364
3364
|
this.save();
|
|
3365
3365
|
}
|
|
3366
3366
|
};
|
|
3367
|
+
var LOW_LIQUIDITY_ASSETS = /* @__PURE__ */ new Set(["GOLD"]);
|
|
3368
|
+
function defaultSlippage(asset) {
|
|
3369
|
+
return LOW_LIQUIDITY_ASSETS.has(asset) ? 0.05 : 0.03;
|
|
3370
|
+
}
|
|
3367
3371
|
var DEFAULT_CONFIG_DIR = join(homedir(), ".t2000");
|
|
3368
3372
|
var T2000 = class _T2000 extends EventEmitter {
|
|
3369
3373
|
keypair;
|
|
@@ -4279,7 +4283,7 @@ To sell investment: t2000 invest sell ${params.amount} ${fromAsset}`,
|
|
|
4279
4283
|
from: "USDC",
|
|
4280
4284
|
to: params.asset,
|
|
4281
4285
|
amount: params.usdAmount,
|
|
4282
|
-
maxSlippage: params.maxSlippage ??
|
|
4286
|
+
maxSlippage: params.maxSlippage ?? defaultSlippage(params.asset),
|
|
4283
4287
|
_bypassInvestmentGuard: true
|
|
4284
4288
|
});
|
|
4285
4289
|
if (swapResult.toAmount === 0) {
|
|
@@ -4380,7 +4384,7 @@ To sell investment: t2000 invest sell ${params.amount} ${fromAsset}`,
|
|
|
4380
4384
|
from: params.asset,
|
|
4381
4385
|
to: "USDC",
|
|
4382
4386
|
amount: sellAmountAsset,
|
|
4383
|
-
maxSlippage: params.maxSlippage ??
|
|
4387
|
+
maxSlippage: params.maxSlippage ?? defaultSlippage(params.asset),
|
|
4384
4388
|
_bypassInvestmentGuard: true
|
|
4385
4389
|
});
|
|
4386
4390
|
const price = swapResult.toAmount / sellAmountAsset;
|
|
@@ -4619,50 +4623,90 @@ To sell investment: t2000 invest sell ${params.amount} ${fromAsset}`,
|
|
|
4619
4623
|
if (stratPositions.length === 0) {
|
|
4620
4624
|
throw new T2000Error("INSUFFICIENT_INVESTMENT", `No positions in strategy '${params.strategy}'`);
|
|
4621
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();
|
|
4622
4669
|
const sells = [];
|
|
4623
4670
|
let totalProceeds = 0;
|
|
4624
4671
|
let totalPnL = 0;
|
|
4625
|
-
|
|
4626
|
-
|
|
4627
|
-
|
|
4628
|
-
const fullAmount = pos.totalAmount;
|
|
4629
|
-
const swapAdapter = this.registry.listSwap()[0];
|
|
4630
|
-
let assetPrice = 1;
|
|
4631
|
-
try {
|
|
4632
|
-
if (swapAdapter) {
|
|
4633
|
-
if (pos.asset === "SUI") {
|
|
4634
|
-
assetPrice = await swapAdapter.getPoolPrice();
|
|
4635
|
-
} else {
|
|
4636
|
-
const q = await swapAdapter.getQuote("USDC", pos.asset, 1);
|
|
4637
|
-
assetPrice = q.expectedOutput > 0 ? 1 / q.expectedOutput : 1;
|
|
4638
|
-
}
|
|
4639
|
-
}
|
|
4640
|
-
} catch {
|
|
4641
|
-
}
|
|
4642
|
-
const strategyUsdValue = fullAmount * assetPrice;
|
|
4643
|
-
const result = await this.investSell({
|
|
4644
|
-
asset: pos.asset,
|
|
4645
|
-
usdAmount: strategyUsdValue,
|
|
4646
|
-
_strategyOnly: true
|
|
4647
|
-
});
|
|
4672
|
+
for (const meta of swapMetas) {
|
|
4673
|
+
const usdValue = meta.estimatedOut / 10 ** meta.toDecimals;
|
|
4674
|
+
const price = meta.amount > 0 ? usdValue / meta.amount : 0;
|
|
4648
4675
|
const pnl = this.portfolio.recordStrategySell(params.strategy, {
|
|
4649
|
-
id: `strat_sell_${Date.now()}_${
|
|
4676
|
+
id: `strat_sell_${Date.now()}_${meta.asset}`,
|
|
4650
4677
|
type: "sell",
|
|
4651
|
-
asset:
|
|
4652
|
-
amount:
|
|
4653
|
-
price
|
|
4654
|
-
usdValue
|
|
4655
|
-
fee:
|
|
4656
|
-
tx:
|
|
4657
|
-
timestamp:
|
|
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
|
|
4658
4696
|
});
|
|
4659
|
-
sells.push({ asset:
|
|
4660
|
-
totalProceeds +=
|
|
4697
|
+
sells.push({ asset: meta.asset, amount: meta.amount, usdValue, realizedPnL: pnl, tx: digest });
|
|
4698
|
+
totalProceeds += usdValue;
|
|
4661
4699
|
totalPnL += pnl;
|
|
4662
|
-
totalGas += result.gasCost;
|
|
4663
|
-
gasMethod = result.gasMethod;
|
|
4664
4700
|
}
|
|
4665
|
-
return {
|
|
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
|
+
};
|
|
4666
4710
|
}
|
|
4667
4711
|
async rebalanceStrategy(params) {
|
|
4668
4712
|
this.enforcer.assertNotLocked();
|
|
@@ -4696,8 +4740,9 @@ To sell investment: t2000 invest sell ${params.amount} ${fromAsset}`,
|
|
|
4696
4740
|
currentWeights[pos.asset] = w;
|
|
4697
4741
|
beforeWeights[pos.asset] = w;
|
|
4698
4742
|
}
|
|
4699
|
-
const trades = [];
|
|
4700
4743
|
const threshold = 3;
|
|
4744
|
+
const sellOps = [];
|
|
4745
|
+
const buyOps = [];
|
|
4701
4746
|
for (const [asset, targetPct] of Object.entries(definition.allocations)) {
|
|
4702
4747
|
const currentPct = currentWeights[asset] ?? 0;
|
|
4703
4748
|
const diff = targetPct - currentPct;
|
|
@@ -4705,33 +4750,140 @@ To sell investment: t2000 invest sell ${params.amount} ${fromAsset}`,
|
|
|
4705
4750
|
const usdDiff = totalValue * (Math.abs(diff) / 100);
|
|
4706
4751
|
if (usdDiff < 1) continue;
|
|
4707
4752
|
if (diff > 0) {
|
|
4708
|
-
|
|
4709
|
-
this.portfolio.recordStrategyBuy(params.strategy, {
|
|
4710
|
-
id: `strat_rebal_${Date.now()}_${asset}`,
|
|
4711
|
-
type: "buy",
|
|
4712
|
-
asset,
|
|
4713
|
-
amount: result.amount,
|
|
4714
|
-
price: result.price,
|
|
4715
|
-
usdValue: usdDiff,
|
|
4716
|
-
fee: result.fee,
|
|
4717
|
-
tx: result.tx,
|
|
4718
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
4719
|
-
});
|
|
4720
|
-
trades.push({ action: "buy", asset, usdAmount: usdDiff, amount: result.amount, tx: result.tx });
|
|
4753
|
+
buyOps.push({ asset, usdAmount: usdDiff });
|
|
4721
4754
|
} else {
|
|
4722
|
-
const
|
|
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;
|
|
4723
4838
|
this.portfolio.recordStrategySell(params.strategy, {
|
|
4724
|
-
id: `strat_rebal_${Date.now()}_${asset}`,
|
|
4839
|
+
id: `strat_rebal_${Date.now()}_${meta.asset}`,
|
|
4725
4840
|
type: "sell",
|
|
4726
|
-
asset,
|
|
4727
|
-
amount:
|
|
4728
|
-
price
|
|
4729
|
-
usdValue:
|
|
4730
|
-
fee:
|
|
4731
|
-
tx:
|
|
4732
|
-
timestamp:
|
|
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
|
|
4733
4885
|
});
|
|
4734
|
-
trades.push({ action: "
|
|
4886
|
+
trades.push({ action: "buy", asset: meta.asset, usdAmount: meta.usdAmount, amount, tx: digest });
|
|
4735
4887
|
}
|
|
4736
4888
|
}
|
|
4737
4889
|
const afterWeights = {};
|