@t2000/sdk 0.17.13 → 0.17.15
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.cjs +318 -3
- package/dist/adapters/index.cjs.map +1 -1
- package/dist/adapters/index.d.cts +1 -1
- package/dist/adapters/index.d.ts +1 -1
- package/dist/adapters/index.js +318 -3
- package/dist/adapters/index.js.map +1 -1
- package/dist/{index-D4cFY__D.d.cts → index-xQEri-Eu.d.cts} +31 -1
- package/dist/{index-D4cFY__D.d.ts → index-xQEri-Eu.d.ts} +31 -1
- package/dist/index.cjs +366 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -3
- package/dist/index.d.ts +5 -3
- package/dist/index.js +366 -3
- 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,
|
|
2
|
-
export {
|
|
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, P as PendingReward, C as ClaimRewardsResult, k as StrategyBuyResult, l as StrategySellResult, m as StrategyRebalanceResult, n as StrategyStatusResult, o as AutoInvestRunResult, p as PortfolioResult, q as InvestmentPosition, r as PositionsResult, s as RatesResult, t as LendingRates, u as RebalanceResult, E as EarningsResult, F as FundStatusResult, v as SentinelAgent, w as SentinelAttackResult, G as GasMethod } from './index-xQEri-Eu.cjs';
|
|
2
|
+
export { x as AdapterCapability, y as AdapterPositions, z as AdapterTxResult, J as AssetRates, K as CetusAdapter, N as GasReserve, O as HealthInfo, Q as NaviAdapter, U as PerpsAdapter, V as PerpsPosition, X as PositionEntry, Y as PositionSide, Z as ProtocolDescriptor, _ as ProtocolRegistry, $ as RebalanceStep, a0 as SentinelVerdict, a1 as SuilendAdapter, a2 as SwapQuote, a3 as TradePositionsResult, a4 as TradeResult, a5 as allDescriptors, a6 as cetusDescriptor, a7 as getSentinelInfo, a8 as listSentinels, a9 as naviDescriptor, aa as requestAttack, ab as sentinelAttack, ac as sentinelDescriptor, ad as settleAttack, ae as submitPrompt, af as suilendDescriptor } from './index-xQEri-Eu.cjs';
|
|
3
3
|
import { EventEmitter } from 'eventemitter3';
|
|
4
4
|
import { SuiJsonRpcClient } from '@mysten/sui/jsonRpc';
|
|
5
5
|
import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';
|
|
@@ -461,6 +461,8 @@ declare class T2000 extends EventEmitter<T2000Events> {
|
|
|
461
461
|
investUnearn(params: {
|
|
462
462
|
asset: InvestmentAsset;
|
|
463
463
|
}): Promise<InvestEarnResult>;
|
|
464
|
+
getPendingRewards(): Promise<PendingReward[]>;
|
|
465
|
+
claimRewards(): Promise<ClaimRewardsResult>;
|
|
464
466
|
investStrategy(params: {
|
|
465
467
|
strategy: string;
|
|
466
468
|
usdAmount: number;
|
|
@@ -643,4 +645,4 @@ interface GasStatusResponse {
|
|
|
643
645
|
}
|
|
644
646
|
declare function getGasStatus(address?: string): Promise<GasStatusResponse>;
|
|
645
647
|
|
|
646
|
-
export { AutoInvestManager, AutoInvestRunResult, AutoInvestSchedule, AutoInvestStatus, type AutoTopUpResult, BPS_DENOMINATOR, BalanceResponse, BorrowResult, CLOCK_ID, type Contact, ContactManager, type ContactMap, DEFAULT_MAX_LEVERAGE, DEFAULT_MAX_POSITION_SIZE, DEFAULT_NETWORK, DEFAULT_SAFEGUARD_CONFIG, DEFAULT_STRATEGIES, DepositInfo, EarningsResult, type FeeOperation, FundStatusResult, GAS_RESERVE_MIN, type GasExecutionResult, GasMethod, type GasRequestType, type GasSponsorResponse, type GasStatusResponse, HealthFactorResult, INVESTMENT_ASSETS, InvestEarnResult, InvestResult, type InvestmentAsset, InvestmentPosition, InvestmentTrade, LendingAdapter, LendingRates, MIST_PER_SUI, MaxBorrowResult, MaxWithdrawResult, OUTBOUND_OPS, PERPS_MARKETS, type PerpsMarket, PortfolioManager, PortfolioResult, PositionsResult, type ProtocolFeeInfo, RatesResult, RebalanceResult, RepayResult, SENTINEL, STABLE_ASSETS, SUI_DECIMALS, SUPPORTED_ASSETS, type SafeguardConfig, SafeguardEnforcer, SafeguardError, type SafeguardErrorDetails, type SafeguardRule, SaveResult, SendResult, SentinelAgent, SentinelAttackResult, type SimulationResult, type StableAsset, StrategyBuyResult, StrategyDefinition, StrategyManager, StrategyRebalanceResult, StrategySellResult, StrategyStatusResult, type SupportedAsset, SwapAdapter, SwapResult, T2000, T2000Error, type T2000ErrorCode, type T2000ErrorData, T2000Options, TransactionRecord, type TxMetadata, USDC_DECIMALS, WithdrawResult, addCollectFeeToTx, calculateFee, executeAutoTopUp, executeWithGas, exportPrivateKey, formatAssetAmount, formatSui, formatUsd, generateKeypair, getAddress, getDecimals, getGasStatus, getPoolPrice, getRates, keypairFromPrivateKey, loadKey, mapMoveAbortCode, mapWalletError, mistToSui, rawToStable, rawToUsdc, saveKey, shouldAutoTopUp, simulateTransaction, solveHashcash, stableToRaw, suiToMist, throwIfSimulationFailed, truncateAddress, usdcToRaw, validateAddress, walletExists };
|
|
648
|
+
export { AutoInvestManager, AutoInvestRunResult, AutoInvestSchedule, AutoInvestStatus, type AutoTopUpResult, BPS_DENOMINATOR, BalanceResponse, BorrowResult, CLOCK_ID, ClaimRewardsResult, type Contact, ContactManager, type ContactMap, DEFAULT_MAX_LEVERAGE, DEFAULT_MAX_POSITION_SIZE, DEFAULT_NETWORK, DEFAULT_SAFEGUARD_CONFIG, DEFAULT_STRATEGIES, DepositInfo, EarningsResult, type FeeOperation, FundStatusResult, GAS_RESERVE_MIN, type GasExecutionResult, GasMethod, type GasRequestType, type GasSponsorResponse, type GasStatusResponse, HealthFactorResult, INVESTMENT_ASSETS, InvestEarnResult, InvestResult, type InvestmentAsset, InvestmentPosition, InvestmentTrade, LendingAdapter, LendingRates, MIST_PER_SUI, MaxBorrowResult, MaxWithdrawResult, OUTBOUND_OPS, PERPS_MARKETS, PendingReward, type PerpsMarket, PortfolioManager, PortfolioResult, PositionsResult, type ProtocolFeeInfo, RatesResult, RebalanceResult, RepayResult, SENTINEL, STABLE_ASSETS, SUI_DECIMALS, SUPPORTED_ASSETS, type SafeguardConfig, SafeguardEnforcer, SafeguardError, type SafeguardErrorDetails, type SafeguardRule, SaveResult, SendResult, SentinelAgent, SentinelAttackResult, type SimulationResult, type StableAsset, StrategyBuyResult, StrategyDefinition, StrategyManager, StrategyRebalanceResult, StrategySellResult, StrategyStatusResult, type SupportedAsset, SwapAdapter, SwapResult, T2000, T2000Error, type T2000ErrorCode, type T2000ErrorData, T2000Options, TransactionRecord, type TxMetadata, USDC_DECIMALS, WithdrawResult, addCollectFeeToTx, calculateFee, executeAutoTopUp, executeWithGas, exportPrivateKey, formatAssetAmount, formatSui, formatUsd, generateKeypair, getAddress, getDecimals, getGasStatus, getPoolPrice, getRates, keypairFromPrivateKey, loadKey, mapMoveAbortCode, mapWalletError, mistToSui, rawToStable, rawToUsdc, saveKey, shouldAutoTopUp, simulateTransaction, solveHashcash, stableToRaw, suiToMist, throwIfSimulationFailed, truncateAddress, usdcToRaw, validateAddress, walletExists };
|
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,
|
|
2
|
-
export {
|
|
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, P as PendingReward, C as ClaimRewardsResult, k as StrategyBuyResult, l as StrategySellResult, m as StrategyRebalanceResult, n as StrategyStatusResult, o as AutoInvestRunResult, p as PortfolioResult, q as InvestmentPosition, r as PositionsResult, s as RatesResult, t as LendingRates, u as RebalanceResult, E as EarningsResult, F as FundStatusResult, v as SentinelAgent, w as SentinelAttackResult, G as GasMethod } from './index-xQEri-Eu.js';
|
|
2
|
+
export { x as AdapterCapability, y as AdapterPositions, z as AdapterTxResult, J as AssetRates, K as CetusAdapter, N as GasReserve, O as HealthInfo, Q as NaviAdapter, U as PerpsAdapter, V as PerpsPosition, X as PositionEntry, Y as PositionSide, Z as ProtocolDescriptor, _ as ProtocolRegistry, $ as RebalanceStep, a0 as SentinelVerdict, a1 as SuilendAdapter, a2 as SwapQuote, a3 as TradePositionsResult, a4 as TradeResult, a5 as allDescriptors, a6 as cetusDescriptor, a7 as getSentinelInfo, a8 as listSentinels, a9 as naviDescriptor, aa as requestAttack, ab as sentinelAttack, ac as sentinelDescriptor, ad as settleAttack, ae as submitPrompt, af as suilendDescriptor } from './index-xQEri-Eu.js';
|
|
3
3
|
import { EventEmitter } from 'eventemitter3';
|
|
4
4
|
import { SuiJsonRpcClient } from '@mysten/sui/jsonRpc';
|
|
5
5
|
import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';
|
|
@@ -461,6 +461,8 @@ declare class T2000 extends EventEmitter<T2000Events> {
|
|
|
461
461
|
investUnearn(params: {
|
|
462
462
|
asset: InvestmentAsset;
|
|
463
463
|
}): Promise<InvestEarnResult>;
|
|
464
|
+
getPendingRewards(): Promise<PendingReward[]>;
|
|
465
|
+
claimRewards(): Promise<ClaimRewardsResult>;
|
|
464
466
|
investStrategy(params: {
|
|
465
467
|
strategy: string;
|
|
466
468
|
usdAmount: number;
|
|
@@ -643,4 +645,4 @@ interface GasStatusResponse {
|
|
|
643
645
|
}
|
|
644
646
|
declare function getGasStatus(address?: string): Promise<GasStatusResponse>;
|
|
645
647
|
|
|
646
|
-
export { AutoInvestManager, AutoInvestRunResult, AutoInvestSchedule, AutoInvestStatus, type AutoTopUpResult, BPS_DENOMINATOR, BalanceResponse, BorrowResult, CLOCK_ID, type Contact, ContactManager, type ContactMap, DEFAULT_MAX_LEVERAGE, DEFAULT_MAX_POSITION_SIZE, DEFAULT_NETWORK, DEFAULT_SAFEGUARD_CONFIG, DEFAULT_STRATEGIES, DepositInfo, EarningsResult, type FeeOperation, FundStatusResult, GAS_RESERVE_MIN, type GasExecutionResult, GasMethod, type GasRequestType, type GasSponsorResponse, type GasStatusResponse, HealthFactorResult, INVESTMENT_ASSETS, InvestEarnResult, InvestResult, type InvestmentAsset, InvestmentPosition, InvestmentTrade, LendingAdapter, LendingRates, MIST_PER_SUI, MaxBorrowResult, MaxWithdrawResult, OUTBOUND_OPS, PERPS_MARKETS, type PerpsMarket, PortfolioManager, PortfolioResult, PositionsResult, type ProtocolFeeInfo, RatesResult, RebalanceResult, RepayResult, SENTINEL, STABLE_ASSETS, SUI_DECIMALS, SUPPORTED_ASSETS, type SafeguardConfig, SafeguardEnforcer, SafeguardError, type SafeguardErrorDetails, type SafeguardRule, SaveResult, SendResult, SentinelAgent, SentinelAttackResult, type SimulationResult, type StableAsset, StrategyBuyResult, StrategyDefinition, StrategyManager, StrategyRebalanceResult, StrategySellResult, StrategyStatusResult, type SupportedAsset, SwapAdapter, SwapResult, T2000, T2000Error, type T2000ErrorCode, type T2000ErrorData, T2000Options, TransactionRecord, type TxMetadata, USDC_DECIMALS, WithdrawResult, addCollectFeeToTx, calculateFee, executeAutoTopUp, executeWithGas, exportPrivateKey, formatAssetAmount, formatSui, formatUsd, generateKeypair, getAddress, getDecimals, getGasStatus, getPoolPrice, getRates, keypairFromPrivateKey, loadKey, mapMoveAbortCode, mapWalletError, mistToSui, rawToStable, rawToUsdc, saveKey, shouldAutoTopUp, simulateTransaction, solveHashcash, stableToRaw, suiToMist, throwIfSimulationFailed, truncateAddress, usdcToRaw, validateAddress, walletExists };
|
|
648
|
+
export { AutoInvestManager, AutoInvestRunResult, AutoInvestSchedule, AutoInvestStatus, type AutoTopUpResult, BPS_DENOMINATOR, BalanceResponse, BorrowResult, CLOCK_ID, ClaimRewardsResult, type Contact, ContactManager, type ContactMap, DEFAULT_MAX_LEVERAGE, DEFAULT_MAX_POSITION_SIZE, DEFAULT_NETWORK, DEFAULT_SAFEGUARD_CONFIG, DEFAULT_STRATEGIES, DepositInfo, EarningsResult, type FeeOperation, FundStatusResult, GAS_RESERVE_MIN, type GasExecutionResult, GasMethod, type GasRequestType, type GasSponsorResponse, type GasStatusResponse, HealthFactorResult, INVESTMENT_ASSETS, InvestEarnResult, InvestResult, type InvestmentAsset, InvestmentPosition, InvestmentTrade, LendingAdapter, LendingRates, MIST_PER_SUI, MaxBorrowResult, MaxWithdrawResult, OUTBOUND_OPS, PERPS_MARKETS, PendingReward, type PerpsMarket, PortfolioManager, PortfolioResult, PositionsResult, type ProtocolFeeInfo, RatesResult, RebalanceResult, RepayResult, SENTINEL, STABLE_ASSETS, SUI_DECIMALS, SUPPORTED_ASSETS, type SafeguardConfig, SafeguardEnforcer, SafeguardError, type SafeguardErrorDetails, type SafeguardRule, SaveResult, SendResult, SentinelAgent, SentinelAttackResult, type SimulationResult, type StableAsset, StrategyBuyResult, StrategyDefinition, StrategyManager, StrategyRebalanceResult, StrategySellResult, StrategyStatusResult, type SupportedAsset, SwapAdapter, SwapResult, T2000, T2000Error, type T2000ErrorCode, type T2000ErrorData, T2000Options, TransactionRecord, type TxMetadata, USDC_DECIMALS, WithdrawResult, addCollectFeeToTx, calculateFee, executeAutoTopUp, executeWithGas, exportPrivateKey, formatAssetAmount, formatSui, formatUsd, generateKeypair, getAddress, getDecimals, getGasStatus, getPoolPrice, getRates, keypairFromPrivateKey, loadKey, mapMoveAbortCode, mapWalletError, mistToSui, rawToStable, rawToUsdc, saveKey, shouldAutoTopUp, simulateTransaction, solveHashcash, stableToRaw, suiToMist, throwIfSimulationFailed, truncateAddress, usdcToRaw, validateAddress, walletExists };
|
package/dist/index.js
CHANGED
|
@@ -493,6 +493,7 @@ async function queryBalance(client, address) {
|
|
|
493
493
|
debt: 0,
|
|
494
494
|
investment: 0,
|
|
495
495
|
investmentPnL: 0,
|
|
496
|
+
pendingRewards: 0,
|
|
496
497
|
gasReserve: {
|
|
497
498
|
sui: suiAmount,
|
|
498
499
|
usdEquiv
|
|
@@ -1176,6 +1177,173 @@ async function maxBorrowAmount(client, addressOrKeypair) {
|
|
|
1176
1177
|
const maxAmount = Math.max(0, hf.supplied * ltv / MIN_HEALTH_FACTOR - hf.borrowed);
|
|
1177
1178
|
return { maxAmount, healthFactorAfter: MIN_HEALTH_FACTOR, currentHF: hf.healthFactor };
|
|
1178
1179
|
}
|
|
1180
|
+
var CERT_TYPE = "0x549e8b69270defbfafd4f94e17ec44cdbdd99820b33bda2278dea3b9a32d3f55::cert::CERT";
|
|
1181
|
+
var DEEP_TYPE = "0xdeeb7a4662eec9f2f3def03fb937a663dddaa2e215b8078a284d026b7946c270::deep::DEEP";
|
|
1182
|
+
var REWARD_FUNDS = {
|
|
1183
|
+
[CERT_TYPE]: "0x7093cf7549d5e5b35bfde2177223d1050f71655c7f676a5e610ee70eb4d93b5c",
|
|
1184
|
+
[DEEP_TYPE]: "0xc889d78b634f954979e80e622a2ae0fece824c0f6d9590044378a2563035f32f"
|
|
1185
|
+
};
|
|
1186
|
+
var REWARD_SYMBOLS = {
|
|
1187
|
+
[CERT_TYPE]: "vSUI",
|
|
1188
|
+
[DEEP_TYPE]: "DEEP"
|
|
1189
|
+
};
|
|
1190
|
+
var incentiveRulesCache = null;
|
|
1191
|
+
async function getIncentiveRules(client) {
|
|
1192
|
+
if (incentiveRulesCache && Date.now() - incentiveRulesCache.ts < CACHE_TTL) {
|
|
1193
|
+
return incentiveRulesCache.data;
|
|
1194
|
+
}
|
|
1195
|
+
const [pools, obj] = await Promise.all([
|
|
1196
|
+
getPools(),
|
|
1197
|
+
client.getObject({
|
|
1198
|
+
id: "0x62982dad27fb10bb314b3384d5de8d2ac2d72ab2dbeae5d801dbdb9efa816c80",
|
|
1199
|
+
options: { showContent: true }
|
|
1200
|
+
})
|
|
1201
|
+
]);
|
|
1202
|
+
const rewardCoinMap = /* @__PURE__ */ new Map();
|
|
1203
|
+
for (const pool of pools) {
|
|
1204
|
+
const ct = (pool.suiCoinType || pool.coinType || "").toLowerCase();
|
|
1205
|
+
const suffix = ct.split("::").slice(1).join("::");
|
|
1206
|
+
const coins = pool.supplyIncentiveApyInfo?.rewardCoin;
|
|
1207
|
+
if (Array.isArray(coins) && coins.length > 0) {
|
|
1208
|
+
rewardCoinMap.set(suffix, coins[0]);
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
const result = /* @__PURE__ */ new Map();
|
|
1212
|
+
if (obj.data?.content?.dataType !== "moveObject") {
|
|
1213
|
+
incentiveRulesCache = { data: result, ts: Date.now() };
|
|
1214
|
+
return result;
|
|
1215
|
+
}
|
|
1216
|
+
const fields = obj.data.content.fields;
|
|
1217
|
+
const poolsObj = fields.pools;
|
|
1218
|
+
const entries = poolsObj?.fields?.contents;
|
|
1219
|
+
if (!Array.isArray(entries)) {
|
|
1220
|
+
incentiveRulesCache = { data: result, ts: Date.now() };
|
|
1221
|
+
return result;
|
|
1222
|
+
}
|
|
1223
|
+
for (const entry of entries) {
|
|
1224
|
+
const ef = entry?.fields;
|
|
1225
|
+
if (!ef) continue;
|
|
1226
|
+
const key = String(ef.key ?? "");
|
|
1227
|
+
const value = ef.value;
|
|
1228
|
+
const rules = value?.fields?.rules;
|
|
1229
|
+
const ruleEntries = rules?.fields?.contents;
|
|
1230
|
+
if (!Array.isArray(ruleEntries)) continue;
|
|
1231
|
+
const ruleIds = ruleEntries.map((re) => {
|
|
1232
|
+
const rf = re?.fields;
|
|
1233
|
+
return String(rf?.key ?? "");
|
|
1234
|
+
}).filter(Boolean);
|
|
1235
|
+
const suffix = key.split("::").slice(1).join("::").toLowerCase();
|
|
1236
|
+
const full = key.toLowerCase();
|
|
1237
|
+
const rewardCoin = rewardCoinMap.get(suffix) ?? rewardCoinMap.get(full) ?? null;
|
|
1238
|
+
result.set(key, { ruleIds, rewardCoinType: rewardCoin });
|
|
1239
|
+
}
|
|
1240
|
+
incentiveRulesCache = { data: result, ts: Date.now() };
|
|
1241
|
+
return result;
|
|
1242
|
+
}
|
|
1243
|
+
function stripPrefix(coinType) {
|
|
1244
|
+
return coinType.replace(/^0x0*/, "");
|
|
1245
|
+
}
|
|
1246
|
+
async function getPendingRewards(client, address) {
|
|
1247
|
+
const [pools, states, rules] = await Promise.all([
|
|
1248
|
+
getPools(),
|
|
1249
|
+
getUserState(client, address),
|
|
1250
|
+
getIncentiveRules(client)
|
|
1251
|
+
]);
|
|
1252
|
+
const rewards = [];
|
|
1253
|
+
const deposited = states.filter((s) => s.supplyBalance > 0n);
|
|
1254
|
+
if (deposited.length === 0) return rewards;
|
|
1255
|
+
const rewardTotals = /* @__PURE__ */ new Map();
|
|
1256
|
+
for (const state of deposited) {
|
|
1257
|
+
const pool = pools.find((p) => p.id === state.assetId);
|
|
1258
|
+
if (!pool) continue;
|
|
1259
|
+
const boostedApr = parseFloat(pool.supplyIncentiveApyInfo?.boostedApr ?? "0");
|
|
1260
|
+
if (boostedApr <= 0) continue;
|
|
1261
|
+
const rewardCoins = pool.supplyIncentiveApyInfo?.rewardCoin;
|
|
1262
|
+
if (!Array.isArray(rewardCoins) || rewardCoins.length === 0) continue;
|
|
1263
|
+
const rewardType = rewardCoins[0];
|
|
1264
|
+
const supplyBal = compoundBalance(state.supplyBalance, pool.currentSupplyIndex, pool);
|
|
1265
|
+
const price = pool.token?.price ?? 0;
|
|
1266
|
+
const depositUsd = supplyBal * price;
|
|
1267
|
+
const annualRewardUsd = depositUsd * (boostedApr / 100);
|
|
1268
|
+
const estimatedUsd = annualRewardUsd / 365;
|
|
1269
|
+
rewardTotals.set(rewardType, (rewardTotals.get(rewardType) ?? 0) + estimatedUsd);
|
|
1270
|
+
}
|
|
1271
|
+
for (const [coinType, dailyUsd] of rewardTotals) {
|
|
1272
|
+
if (dailyUsd < 1e-3) continue;
|
|
1273
|
+
rewards.push({
|
|
1274
|
+
protocol: "navi",
|
|
1275
|
+
coinType,
|
|
1276
|
+
symbol: REWARD_SYMBOLS[coinType] ?? coinType.split("::").pop() ?? "UNKNOWN",
|
|
1277
|
+
amount: 0,
|
|
1278
|
+
estimatedValueUsd: dailyUsd
|
|
1279
|
+
});
|
|
1280
|
+
}
|
|
1281
|
+
return rewards;
|
|
1282
|
+
}
|
|
1283
|
+
async function addClaimRewardsToTx(tx, client, address) {
|
|
1284
|
+
const [config, pools, states, rules] = await Promise.all([
|
|
1285
|
+
getConfig(),
|
|
1286
|
+
getPools(),
|
|
1287
|
+
getUserState(client, address),
|
|
1288
|
+
getIncentiveRules(client)
|
|
1289
|
+
]);
|
|
1290
|
+
const deposited = states.filter((s) => s.supplyBalance > 0n);
|
|
1291
|
+
if (deposited.length === 0) return [];
|
|
1292
|
+
const claimGroups = /* @__PURE__ */ new Map();
|
|
1293
|
+
for (const state of deposited) {
|
|
1294
|
+
const pool = pools.find((p) => p.id === state.assetId);
|
|
1295
|
+
if (!pool) continue;
|
|
1296
|
+
const boostedApr = parseFloat(pool.supplyIncentiveApyInfo?.boostedApr ?? "0");
|
|
1297
|
+
if (boostedApr <= 0) continue;
|
|
1298
|
+
const rewardCoins = pool.supplyIncentiveApyInfo?.rewardCoin;
|
|
1299
|
+
if (!Array.isArray(rewardCoins) || rewardCoins.length === 0) continue;
|
|
1300
|
+
const rewardType = rewardCoins[0];
|
|
1301
|
+
const fundId = REWARD_FUNDS[rewardType];
|
|
1302
|
+
if (!fundId) continue;
|
|
1303
|
+
const coinType = pool.suiCoinType || pool.coinType || "";
|
|
1304
|
+
const strippedType = stripPrefix(coinType);
|
|
1305
|
+
const ruleData = Array.from(rules.entries()).find(
|
|
1306
|
+
([key]) => stripPrefix(key) === strippedType || key.split("::").slice(1).join("::").toLowerCase() === coinType.split("::").slice(1).join("::").toLowerCase()
|
|
1307
|
+
);
|
|
1308
|
+
if (!ruleData || ruleData[1].ruleIds.length === 0) continue;
|
|
1309
|
+
const group = claimGroups.get(rewardType) ?? { assets: [], ruleIds: [] };
|
|
1310
|
+
for (const ruleId of ruleData[1].ruleIds) {
|
|
1311
|
+
group.assets.push(strippedType);
|
|
1312
|
+
group.ruleIds.push(ruleId);
|
|
1313
|
+
}
|
|
1314
|
+
claimGroups.set(rewardType, group);
|
|
1315
|
+
}
|
|
1316
|
+
const claimed = [];
|
|
1317
|
+
for (const [rewardType, { assets, ruleIds }] of claimGroups) {
|
|
1318
|
+
const fundId = REWARD_FUNDS[rewardType];
|
|
1319
|
+
const [balance] = tx.moveCall({
|
|
1320
|
+
target: `${config.package}::incentive_v3::claim_reward`,
|
|
1321
|
+
typeArguments: [rewardType],
|
|
1322
|
+
arguments: [
|
|
1323
|
+
tx.object(CLOCK),
|
|
1324
|
+
tx.object(config.incentiveV3),
|
|
1325
|
+
tx.object(config.storage),
|
|
1326
|
+
tx.object(fundId),
|
|
1327
|
+
tx.pure(bcs.vector(bcs.string()).serialize(assets)),
|
|
1328
|
+
tx.pure(bcs.vector(bcs.Address).serialize(ruleIds))
|
|
1329
|
+
]
|
|
1330
|
+
});
|
|
1331
|
+
const [coin] = tx.moveCall({
|
|
1332
|
+
target: "0x2::coin::from_balance",
|
|
1333
|
+
typeArguments: [rewardType],
|
|
1334
|
+
arguments: [balance]
|
|
1335
|
+
});
|
|
1336
|
+
tx.transferObjects([coin], address);
|
|
1337
|
+
claimed.push({
|
|
1338
|
+
protocol: "navi",
|
|
1339
|
+
coinType: rewardType,
|
|
1340
|
+
symbol: REWARD_SYMBOLS[rewardType] ?? "UNKNOWN",
|
|
1341
|
+
amount: 0,
|
|
1342
|
+
estimatedValueUsd: 0
|
|
1343
|
+
});
|
|
1344
|
+
}
|
|
1345
|
+
return claimed;
|
|
1346
|
+
}
|
|
1179
1347
|
|
|
1180
1348
|
// src/protocols/yieldTracker.ts
|
|
1181
1349
|
async function getEarnings(client, keypair) {
|
|
@@ -1623,6 +1791,12 @@ var NaviAdapter = class {
|
|
|
1623
1791
|
const normalized = normalizeAsset(asset);
|
|
1624
1792
|
return addRepayToTx(tx, this.client, address, coin, { asset: normalized });
|
|
1625
1793
|
}
|
|
1794
|
+
async getPendingRewards(address) {
|
|
1795
|
+
return getPendingRewards(this.client, address);
|
|
1796
|
+
}
|
|
1797
|
+
async addClaimRewardsToTx(tx, address) {
|
|
1798
|
+
return addClaimRewardsToTx(tx, this.client, address);
|
|
1799
|
+
}
|
|
1626
1800
|
};
|
|
1627
1801
|
var DEFAULT_SLIPPAGE_BPS = 300;
|
|
1628
1802
|
function createAggregatorClient(client, signer) {
|
|
@@ -1906,6 +2080,26 @@ function computeRates(reserve) {
|
|
|
1906
2080
|
const depositAprPct = utilizationPct / 100 * (borrowAprPct / 100) * (1 - reserve.spreadFeeBps / 1e4) * 100;
|
|
1907
2081
|
return { borrowAprPct, depositAprPct };
|
|
1908
2082
|
}
|
|
2083
|
+
var MS_PER_YEAR = 365.25 * 24 * 3600 * 1e3;
|
|
2084
|
+
function computeDepositRewardApr(reserve, allReserves) {
|
|
2085
|
+
if (reserve.depositTotalShares <= 0 || reserve.price <= 0) return 0;
|
|
2086
|
+
const totalDepositValue = reserve.depositTotalShares / 10 ** reserve.mintDecimals * reserve.price;
|
|
2087
|
+
if (totalDepositValue <= 0) return 0;
|
|
2088
|
+
const priceMap = /* @__PURE__ */ new Map();
|
|
2089
|
+
for (const r of allReserves) {
|
|
2090
|
+
if (r.price > 0) priceMap.set(r.coinType, { price: r.price, decimals: r.mintDecimals });
|
|
2091
|
+
}
|
|
2092
|
+
let rewardApr = 0;
|
|
2093
|
+
for (const rw of reserve.depositPoolRewards) {
|
|
2094
|
+
const info = priceMap.get(rw.coinType);
|
|
2095
|
+
if (!info || info.price <= 0) continue;
|
|
2096
|
+
const durationMs = rw.endTimeMs - rw.startTimeMs;
|
|
2097
|
+
if (durationMs <= 0) continue;
|
|
2098
|
+
const annualTokens = rw.totalRewards / 10 ** info.decimals * (MS_PER_YEAR / durationMs);
|
|
2099
|
+
rewardApr += annualTokens * info.price / totalDepositValue * 100;
|
|
2100
|
+
}
|
|
2101
|
+
return rewardApr;
|
|
2102
|
+
}
|
|
1909
2103
|
function cTokenRatio(reserve) {
|
|
1910
2104
|
if (reserve.ctokenSupply === 0) return 1;
|
|
1911
2105
|
const totalSupply = reserve.availableAmount + reserve.borrowedAmountWad / WAD - reserve.unclaimedSpreadFeesWad / WAD;
|
|
@@ -1925,6 +2119,20 @@ function parseReserve(raw, index) {
|
|
|
1925
2119
|
const r = f(raw);
|
|
1926
2120
|
const coinTypeField = f(r.coin_type);
|
|
1927
2121
|
const config = f(f(r.config)?.element);
|
|
2122
|
+
const dMgr = f(r.deposits_pool_reward_manager);
|
|
2123
|
+
const rawRewards = Array.isArray(dMgr?.pool_rewards) ? dMgr.pool_rewards : [];
|
|
2124
|
+
const now = Date.now();
|
|
2125
|
+
const depositPoolRewards = rawRewards.map((rw, idx) => {
|
|
2126
|
+
if (rw === null) return null;
|
|
2127
|
+
const rwf = f(rw);
|
|
2128
|
+
return {
|
|
2129
|
+
coinType: str(f(rwf.coin_type)?.name),
|
|
2130
|
+
totalRewards: num(rwf.total_rewards),
|
|
2131
|
+
startTimeMs: num(rwf.start_time_ms),
|
|
2132
|
+
endTimeMs: num(rwf.end_time_ms),
|
|
2133
|
+
rewardIndex: idx
|
|
2134
|
+
};
|
|
2135
|
+
}).filter((rw) => rw !== null && rw.endTimeMs > now && rw.totalRewards > 0);
|
|
1928
2136
|
return {
|
|
1929
2137
|
coinType: str(coinTypeField?.name),
|
|
1930
2138
|
mintDecimals: num(r.mint_decimals),
|
|
@@ -1938,7 +2146,10 @@ function parseReserve(raw, index) {
|
|
|
1938
2146
|
spreadFeeBps: num(config?.spread_fee_bps),
|
|
1939
2147
|
interestRateUtils: Array.isArray(config?.interest_rate_utils) ? config.interest_rate_utils.map(num) : [],
|
|
1940
2148
|
interestRateAprs: Array.isArray(config?.interest_rate_aprs) ? config.interest_rate_aprs.map(num) : [],
|
|
1941
|
-
arrayIndex: index
|
|
2149
|
+
arrayIndex: index,
|
|
2150
|
+
price: num(f(r.price)?.value) / WAD,
|
|
2151
|
+
depositTotalShares: num(dMgr?.total_shares),
|
|
2152
|
+
depositPoolRewards
|
|
1942
2153
|
};
|
|
1943
2154
|
}
|
|
1944
2155
|
function parseObligation(raw) {
|
|
@@ -2083,7 +2294,8 @@ var SuilendAdapter = class {
|
|
|
2083
2294
|
const reserve = this.findReserve(reserves, asset);
|
|
2084
2295
|
if (!reserve) throw new T2000Error("ASSET_NOT_SUPPORTED", `Suilend does not support ${asset}`);
|
|
2085
2296
|
const { borrowAprPct, depositAprPct } = computeRates(reserve);
|
|
2086
|
-
|
|
2297
|
+
const rewardApr = computeDepositRewardApr(reserve, reserves);
|
|
2298
|
+
return { asset, saveApy: depositAprPct + rewardApr, borrowApy: borrowAprPct };
|
|
2087
2299
|
}
|
|
2088
2300
|
async getPositions(address) {
|
|
2089
2301
|
const supplies = [];
|
|
@@ -2100,7 +2312,8 @@ var SuilendAdapter = class {
|
|
|
2100
2312
|
const ratio = cTokenRatio(reserve);
|
|
2101
2313
|
const amount = dep.ctokenAmount * ratio / 10 ** reserve.mintDecimals;
|
|
2102
2314
|
const { depositAprPct } = computeRates(reserve);
|
|
2103
|
-
|
|
2315
|
+
const rewardApr = computeDepositRewardApr(reserve, reserves);
|
|
2316
|
+
supplies.push({ asset: this.resolveSymbol(dep.coinType), amount, apy: depositAprPct + rewardApr });
|
|
2104
2317
|
}
|
|
2105
2318
|
for (const bor of obligation.borrows) {
|
|
2106
2319
|
const reserve = reserves[bor.reserveIdx];
|
|
@@ -2470,6 +2683,109 @@ var SuilendAdapter = class {
|
|
|
2470
2683
|
}
|
|
2471
2684
|
return all;
|
|
2472
2685
|
}
|
|
2686
|
+
// -- Claim Rewards --------------------------------------------------------
|
|
2687
|
+
isClaimableReward(coinType) {
|
|
2688
|
+
const ct = coinType.toLowerCase();
|
|
2689
|
+
return ct.includes("spring_sui") || ct.includes("deep::deep") || ct.includes("cert::cert");
|
|
2690
|
+
}
|
|
2691
|
+
async getPendingRewards(address) {
|
|
2692
|
+
const caps = await this.fetchObligationCaps(address);
|
|
2693
|
+
if (caps.length === 0) return [];
|
|
2694
|
+
const [reserves, obligation] = await Promise.all([
|
|
2695
|
+
this.loadReserves(true),
|
|
2696
|
+
this.fetchObligation(caps[0].obligationId)
|
|
2697
|
+
]);
|
|
2698
|
+
const rewards = [];
|
|
2699
|
+
const rewardEstimates = /* @__PURE__ */ new Map();
|
|
2700
|
+
for (const dep of obligation.deposits) {
|
|
2701
|
+
const reserve = reserves[dep.reserveIdx];
|
|
2702
|
+
if (!reserve) continue;
|
|
2703
|
+
const ratio = cTokenRatio(reserve);
|
|
2704
|
+
const amount = dep.ctokenAmount * ratio / 10 ** reserve.mintDecimals;
|
|
2705
|
+
const price = reserve.price;
|
|
2706
|
+
const depositUsd = amount * price;
|
|
2707
|
+
for (const rw of reserve.depositPoolRewards) {
|
|
2708
|
+
if (!this.isClaimableReward(rw.coinType)) continue;
|
|
2709
|
+
const rewardReserve = reserves.find((r) => {
|
|
2710
|
+
try {
|
|
2711
|
+
return normalizeStructTag(r.coinType) === normalizeStructTag(rw.coinType);
|
|
2712
|
+
} catch {
|
|
2713
|
+
return false;
|
|
2714
|
+
}
|
|
2715
|
+
});
|
|
2716
|
+
const rewardPrice = rewardReserve?.price ?? 0;
|
|
2717
|
+
const rewardDecimals = rewardReserve?.mintDecimals ?? 9;
|
|
2718
|
+
const durationMs = rw.endTimeMs - rw.startTimeMs;
|
|
2719
|
+
if (durationMs <= 0) continue;
|
|
2720
|
+
const annualTokens = rw.totalRewards / 10 ** rewardDecimals * (MS_PER_YEAR / durationMs);
|
|
2721
|
+
const totalDepositValue = reserve.depositTotalShares / 10 ** reserve.mintDecimals * price;
|
|
2722
|
+
if (totalDepositValue <= 0) continue;
|
|
2723
|
+
const userShare = depositUsd / totalDepositValue;
|
|
2724
|
+
const dailyRewardUsd = annualTokens * rewardPrice / 365 * userShare;
|
|
2725
|
+
rewardEstimates.set(rw.coinType, (rewardEstimates.get(rw.coinType) ?? 0) + dailyRewardUsd);
|
|
2726
|
+
}
|
|
2727
|
+
}
|
|
2728
|
+
for (const [coinType, dailyUsd] of rewardEstimates) {
|
|
2729
|
+
if (dailyUsd < 1e-3) continue;
|
|
2730
|
+
const symbol = coinType.includes("spring_sui") ? "SPRING_SUI" : coinType.includes("deep::") ? "DEEP" : coinType.split("::").pop() ?? "UNKNOWN";
|
|
2731
|
+
rewards.push({
|
|
2732
|
+
protocol: "suilend",
|
|
2733
|
+
coinType,
|
|
2734
|
+
symbol,
|
|
2735
|
+
amount: 0,
|
|
2736
|
+
estimatedValueUsd: dailyUsd
|
|
2737
|
+
});
|
|
2738
|
+
}
|
|
2739
|
+
return rewards;
|
|
2740
|
+
}
|
|
2741
|
+
async addClaimRewardsToTx(tx, address) {
|
|
2742
|
+
const caps = await this.fetchObligationCaps(address);
|
|
2743
|
+
if (caps.length === 0) return [];
|
|
2744
|
+
const [pkg, reserves, obligation] = await Promise.all([
|
|
2745
|
+
this.resolvePackage(),
|
|
2746
|
+
this.loadReserves(true),
|
|
2747
|
+
this.fetchObligation(caps[0].obligationId)
|
|
2748
|
+
]);
|
|
2749
|
+
const claimsByToken = /* @__PURE__ */ new Map();
|
|
2750
|
+
const claimed = [];
|
|
2751
|
+
for (const dep of obligation.deposits) {
|
|
2752
|
+
const reserve = reserves[dep.reserveIdx];
|
|
2753
|
+
if (!reserve) continue;
|
|
2754
|
+
for (const rw of reserve.depositPoolRewards) {
|
|
2755
|
+
if (!this.isClaimableReward(rw.coinType)) continue;
|
|
2756
|
+
const [coin] = tx.moveCall({
|
|
2757
|
+
target: `${pkg}::lending_market::claim_rewards`,
|
|
2758
|
+
typeArguments: [LENDING_MARKET_TYPE, rw.coinType],
|
|
2759
|
+
arguments: [
|
|
2760
|
+
tx.object(LENDING_MARKET_ID),
|
|
2761
|
+
tx.object(caps[0].id),
|
|
2762
|
+
tx.object(CLOCK2),
|
|
2763
|
+
tx.pure.u64(reserve.arrayIndex),
|
|
2764
|
+
tx.pure.u64(rw.rewardIndex),
|
|
2765
|
+
tx.pure.bool(true)
|
|
2766
|
+
]
|
|
2767
|
+
});
|
|
2768
|
+
const existing = claimsByToken.get(rw.coinType) ?? [];
|
|
2769
|
+
existing.push(coin);
|
|
2770
|
+
claimsByToken.set(rw.coinType, existing);
|
|
2771
|
+
}
|
|
2772
|
+
}
|
|
2773
|
+
for (const [coinType, coins] of claimsByToken) {
|
|
2774
|
+
if (coins.length > 1) {
|
|
2775
|
+
tx.mergeCoins(coins[0], coins.slice(1));
|
|
2776
|
+
}
|
|
2777
|
+
tx.transferObjects([coins[0]], address);
|
|
2778
|
+
const symbol = coinType.includes("spring_sui") ? "SPRING_SUI" : coinType.includes("deep::") ? "DEEP" : coinType.split("::").pop() ?? "UNKNOWN";
|
|
2779
|
+
claimed.push({
|
|
2780
|
+
protocol: "suilend",
|
|
2781
|
+
coinType,
|
|
2782
|
+
symbol,
|
|
2783
|
+
amount: 0,
|
|
2784
|
+
estimatedValueUsd: 0
|
|
2785
|
+
});
|
|
2786
|
+
}
|
|
2787
|
+
return claimed;
|
|
2788
|
+
}
|
|
2473
2789
|
};
|
|
2474
2790
|
function hasLeadingZeroBits(hash, bits) {
|
|
2475
2791
|
const fullBytes = Math.floor(bits / 8);
|
|
@@ -3595,6 +3911,12 @@ To access invested funds: t2000 invest sell ${params.amount} ${asset}`,
|
|
|
3595
3911
|
bal.investment = 0;
|
|
3596
3912
|
bal.investmentPnL = 0;
|
|
3597
3913
|
}
|
|
3914
|
+
try {
|
|
3915
|
+
const pendingRewards = await this.getPendingRewards();
|
|
3916
|
+
bal.pendingRewards = pendingRewards.reduce((s, r) => s + r.estimatedValueUsd, 0);
|
|
3917
|
+
} catch {
|
|
3918
|
+
bal.pendingRewards = 0;
|
|
3919
|
+
}
|
|
3598
3920
|
bal.total = bal.available + bal.savings - bal.debt + bal.investment + bal.gasReserve.usdEquiv;
|
|
3599
3921
|
return bal;
|
|
3600
3922
|
}
|
|
@@ -4544,6 +4866,47 @@ To sell investment: t2000 invest sell ${params.amount} ${fromAsset}`,
|
|
|
4544
4866
|
gasMethod: gasResult.gasMethod
|
|
4545
4867
|
};
|
|
4546
4868
|
}
|
|
4869
|
+
// -- Claim Rewards --
|
|
4870
|
+
async getPendingRewards() {
|
|
4871
|
+
const adapters = this.registry.listLending();
|
|
4872
|
+
const results = await Promise.allSettled(
|
|
4873
|
+
adapters.filter((a) => a.getPendingRewards).map((a) => a.getPendingRewards(this._address))
|
|
4874
|
+
);
|
|
4875
|
+
const all = [];
|
|
4876
|
+
for (const r of results) {
|
|
4877
|
+
if (r.status === "fulfilled") all.push(...r.value);
|
|
4878
|
+
}
|
|
4879
|
+
return all;
|
|
4880
|
+
}
|
|
4881
|
+
async claimRewards() {
|
|
4882
|
+
this.enforcer.assertNotLocked();
|
|
4883
|
+
const adapters = this.registry.listLending().filter((a) => a.addClaimRewardsToTx);
|
|
4884
|
+
if (adapters.length === 0) {
|
|
4885
|
+
return { success: true, tx: "", rewards: [], totalValueUsd: 0, gasCost: 0, gasMethod: "none" };
|
|
4886
|
+
}
|
|
4887
|
+
const tx = new Transaction();
|
|
4888
|
+
tx.setSender(this._address);
|
|
4889
|
+
const allRewards = [];
|
|
4890
|
+
for (const adapter of adapters) {
|
|
4891
|
+
try {
|
|
4892
|
+
const claimed = await adapter.addClaimRewardsToTx(tx, this._address);
|
|
4893
|
+
allRewards.push(...claimed);
|
|
4894
|
+
} catch {
|
|
4895
|
+
}
|
|
4896
|
+
}
|
|
4897
|
+
if (allRewards.length === 0) {
|
|
4898
|
+
return { success: true, tx: "", rewards: [], totalValueUsd: 0, gasCost: 0, gasMethod: "none" };
|
|
4899
|
+
}
|
|
4900
|
+
const gasResult = await executeWithGas(this.client, this.keypair, async () => tx);
|
|
4901
|
+
return {
|
|
4902
|
+
success: true,
|
|
4903
|
+
tx: gasResult.digest,
|
|
4904
|
+
rewards: allRewards,
|
|
4905
|
+
totalValueUsd: allRewards.reduce((s, r) => s + r.estimatedValueUsd, 0),
|
|
4906
|
+
gasCost: gasResult.gasCostSui,
|
|
4907
|
+
gasMethod: gasResult.gasMethod
|
|
4908
|
+
};
|
|
4909
|
+
}
|
|
4547
4910
|
// -- Strategies --
|
|
4548
4911
|
async investStrategy(params) {
|
|
4549
4912
|
this.enforcer.assertNotLocked();
|