@suilend/sdk 14.1.0-next.g80e1a5e → 14.2.0-next.ge5d3397
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/package.json +1 -1
- package/strategies.d.ts +4 -2
- package/strategies.js +45 -12
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@suilend/sdk","version":"14.
|
|
1
|
+
{"name":"@suilend/sdk","version":"14.2.0-next.ge5d3397","private":false,"description":"A TypeScript SDK for interacting with the Suilend program","author":"Suilend","license":"MIT","main":"./index.js","exports":{".":"./index.js","./client":"./client.js","./mmt":"./mmt.js","./strategies":"./strategies.js","./api/events":"./api/events.js","./api":"./api/index.js","./lib/constants":"./lib/constants.js","./lib":"./lib/index.js","./lib/initialize":"./lib/initialize.js","./lib/liquidityMining":"./lib/liquidityMining.js","./lib/proCompatible":"./lib/proCompatible.js","./lib/pyth":"./lib/pyth.js","./lib/strategyOwnerCap":"./lib/strategyOwnerCap.js","./lib/transactions":"./lib/transactions.js","./lib/types":"./lib/types.js","./margin":"./margin/index.js","./parsers/apiReserveAssetDataEvent":"./parsers/apiReserveAssetDataEvent.js","./parsers":"./parsers/index.js","./parsers/lendingMarket":"./parsers/lendingMarket.js","./parsers/obligation":"./parsers/obligation.js","./parsers/rateLimiter":"./parsers/rateLimiter.js","./parsers/reserve":"./parsers/reserve.js","./swap":"./swap/index.js","./swap/quote":"./swap/quote.js","./swap/transaction":"./swap/transaction.js","./utils/events":"./utils/events.js","./utils/feedId":"./utils/feedId.js","./utils":"./utils/index.js","./utils/interpolate":"./utils/interpolate.js","./utils/obligation":"./utils/obligation.js","./utils/priceGuard":"./utils/priceGuard.js","./utils/simulate":"./utils/simulate.js","./_generated/_envs":"./_generated/_envs/index.js","./_generated/_envs/mainnet":"./_generated/_envs/mainnet.js","./_generated/_framework/env":"./_generated/_framework/env.js","./_generated/_framework/reified":"./_generated/_framework/reified.js","./_generated/_framework/util":"./_generated/_framework/util.js","./_generated/_framework/vector":"./_generated/_framework/vector.js","./_generated/suilend":"./_generated/suilend/index.js","./margin/margin/admin_cap":"./margin/margin/admin_cap.js","./margin/margin/market":"./margin/margin/market.js","./margin/margin/permissions":"./margin/margin/permissions.js","./margin/margin/position":"./margin/margin/position.js","./margin/margin/router":"./margin/margin/router.js","./margin/margin/version":"./margin/margin/version.js","./margin/utils":"./margin/utils/index.js","./_generated/suilend/cell/structs":"./_generated/suilend/cell/structs.js","./_generated/suilend/decimal/structs":"./_generated/suilend/decimal/structs.js","./_generated/suilend/lending-market/functions":"./_generated/suilend/lending-market/functions.js","./_generated/suilend/lending-market/structs":"./_generated/suilend/lending-market/structs.js","./_generated/suilend/lending-market-registry/functions":"./_generated/suilend/lending-market-registry/functions.js","./_generated/suilend/liquidity-mining/structs":"./_generated/suilend/liquidity-mining/structs.js","./_generated/suilend/obligation/structs":"./_generated/suilend/obligation/structs.js","./_generated/suilend/rate-limiter/functions":"./_generated/suilend/rate-limiter/functions.js","./_generated/suilend/rate-limiter/structs":"./_generated/suilend/rate-limiter/structs.js","./_generated/suilend/reserve/structs":"./_generated/suilend/reserve/structs.js","./_generated/suilend/reserve-config/functions":"./_generated/suilend/reserve-config/functions.js","./_generated/suilend/reserve-config/structs":"./_generated/suilend/reserve-config/structs.js","./_generated/_dependencies/pyth-2/price-identifier/structs":"./_generated/_dependencies/pyth-2/price-identifier/structs.js","./_generated/_dependencies/std/ascii/structs":"./_generated/_dependencies/std/ascii/structs.js","./_generated/_dependencies/std/option/structs":"./_generated/_dependencies/std/option/structs.js","./_generated/_dependencies/std/type-name/structs":"./_generated/_dependencies/std/type-name/structs.js","./_generated/_dependencies/sui/bag/structs":"./_generated/_dependencies/sui/bag/structs.js","./_generated/_dependencies/sui/balance/structs":"./_generated/_dependencies/sui/balance/structs.js","./_generated/_dependencies/sui/object/structs":"./_generated/_dependencies/sui/object/structs.js","./_generated/_dependencies/sui/object-table/structs":"./_generated/_dependencies/sui/object-table/structs.js","./margin/margin/deps/std/type_name":"./margin/margin/deps/std/type_name.js","./margin/margin/deps/sui/vec_set":"./margin/margin/deps/sui/vec_set.js","./margin/margin/deps/suilend/lending_market":"./margin/margin/deps/suilend/lending_market.js"},"types":"./index.d.ts","scripts":{"codegen":"node ./codegen.js","codegen:install":"node ./install-codegen.js","build":"rm -rf ./dist && tsc && node ./fix-esm-imports.js","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.test.json","test":"vitest run","lint:ci":"yarn run typecheck","prettier":"prettier --write src/ tests/","release":"yarn run build && node ./release.js && cd ./dist && npm publish --access public"},"repository":{"type":"git","url":"git+https://github.com/fireflyprotocol/lending-mono.git","directory":"ts/sdks/sdk"},"dependencies":{"@cetusprotocol/aggregator-sdk":"1.7.3","@flowx-finance/sdk":"2.1.0","@pythnetwork/hermes-client":"3.1.0","@pythnetwork/pyth-sui-js":"4.0.0","@suilend/springsui-sdk":"4.1.0","bignumber.js":"11.1.5","bn.js":"5.2.5","crypto-js":"4.2.0","lodash":"4.18.1","p-limit":"7.3.3","uuid":"14.0.2"},"devDependencies":{"@mysten/bcs":"2.1.2","@mysten/sui":"2.35.0","@suilend/sui-core":"2.2.0","@tsconfig/recommended":"1.0.13","@types/bn.js":"5.2.0","@types/lodash":"4.17.26","@types/node":"26.6.5","fast-check":"4.10.2","prettier":"3.9.10","ts-node":"10.9.2","typescript":"6.0.3","vite":"8.3.4","vitest":"5.0.4"},"peerDependencies":{"@mysten/bcs":"^2.1.1","@mysten/sui":">=2.31.3 <3","@suilend/sui-core":"^2.0.1"},"type":"module"}
|
package/strategies.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ import { ParsedObligation, ParsedReserve } from "./parsers";
|
|
|
13
13
|
export declare const STRATEGY_E: number;
|
|
14
14
|
export declare const STRATEGY_FLASH_REPAY_MAX_RESIDUAL_USD = 0.1;
|
|
15
15
|
export declare const STRATEGY_RATE_LIMITED_ERROR_MESSAGE = "This withdrawal exceeds the lending market's outflow limit for now. Withdraw a smaller amount, or wait and try again.";
|
|
16
|
+
export declare const STRATEGY_WITHDRAWN_COIN_CONSUMER_ERROR_MESSAGE = "Failed to use the withdrawn coin";
|
|
16
17
|
/**
|
|
17
18
|
* Below this, a levered position is uneconomic no matter what the slippage
|
|
18
19
|
* tolerance says. The aggregator's dust regime dominates: routes go multi-hop
|
|
@@ -356,9 +357,10 @@ export declare const strategyDepositAndLoopToExposureTx: (reserveMap: Record<str
|
|
|
356
357
|
borrowedAmount: BigNumber;
|
|
357
358
|
transaction: Transaction;
|
|
358
359
|
}>;
|
|
360
|
+
export type StrategyWithdrawnCoinConsumer = (transaction: Transaction, coin: TransactionObjectArgument, estimatedAmount: BigNumber) => Promise<void>;
|
|
359
361
|
export declare const strategyWithdrawTx: (reserveMap: Record<string, ParsedReserve>, lstMap: StrategyLstMap, strategyType: StrategyType, suiGrpcClient: SuiGrpcClient, suilendClient: SuilendClient, cetusSdk: CetusSdk, cetusPartnerId: string, _address: string, strategyOwnerCapId: TransactionObjectInput, obligationId: string, _deposits: StrategyDeposit[], _borrowedAmount: BigNumber, withdraw: StrategyWithdraw, transaction: Transaction, dryRunTransaction: (transaction: Transaction, setGasBudget?: boolean) => Promise<SuiClientTypes.SimulateTransactionResult<{
|
|
360
362
|
commandResults: true;
|
|
361
|
-
}>>, returnWithdrawnCoin?: boolean, rewardsMap?: RewardsMap) => Promise<{
|
|
363
|
+
}>>, returnWithdrawnCoin?: boolean, rewardsMap?: RewardsMap, consumeWithdrawnCoin?: StrategyWithdrawnCoinConsumer) => Promise<{
|
|
362
364
|
deposits: StrategyDeposit[];
|
|
363
365
|
borrowedAmount: BigNumber;
|
|
364
366
|
transaction: Transaction;
|
|
@@ -366,7 +368,7 @@ export declare const strategyWithdrawTx: (reserveMap: Record<string, ParsedReser
|
|
|
366
368
|
}>;
|
|
367
369
|
export declare const strategyMaxWithdrawTx: (reserveMap: Record<string, ParsedReserve>, rewardsMap: RewardsMap, lstMap: StrategyLstMap, strategyType: StrategyType, suiGrpcClient: SuiGrpcClient, suilendClient: SuilendClient, cetusSdk: CetusSdk, cetusPartnerId: string, _address: string, strategyOwnerCapId: TransactionObjectInput, obligationId: string, _deposits: StrategyDeposit[], _borrowedAmount: BigNumber, withdrawCoinType: string, transaction: Transaction, _dryRunTransaction: (transaction: Transaction, setGasBudget?: boolean) => Promise<SuiClientTypes.SimulateTransactionResult<{
|
|
368
370
|
commandResults: true;
|
|
369
|
-
}
|
|
371
|
+
}>>, consumeWithdrawnCoin?: StrategyWithdrawnCoinConsumer) => Promise<{
|
|
370
372
|
deposits: StrategyDeposit[];
|
|
371
373
|
borrowedAmount: BigNumber;
|
|
372
374
|
transaction: Transaction;
|
package/strategies.js
CHANGED
|
@@ -14,6 +14,7 @@ import { bisectionMethod, getWeightedBorrowsUsd } from "./utils/index.js";
|
|
|
14
14
|
export const STRATEGY_E = 10 ** -7;
|
|
15
15
|
export const STRATEGY_FLASH_REPAY_MAX_RESIDUAL_USD = 0.1;
|
|
16
16
|
export const STRATEGY_RATE_LIMITED_ERROR_MESSAGE = "This withdrawal exceeds the lending market's outflow limit for now. Withdraw a smaller amount, or wait and try again.";
|
|
17
|
+
export const STRATEGY_WITHDRAWN_COIN_CONSUMER_ERROR_MESSAGE = "Failed to use the withdrawn coin";
|
|
17
18
|
const isRateLimitExceeded = (err) => /abort code: 2, in '[^']*::rate_limiter::process_qty'/.test(err instanceof Error ? err.message : String(err));
|
|
18
19
|
// Every step dry-runs and rolls back on failure, so the builders only see that
|
|
19
20
|
// no step landed. Recording why lets them name the market's outflow limit
|
|
@@ -2262,6 +2263,31 @@ const isStrategyPositionClosed = (reserveMap, deposits) => deposits.every((d) =>
|
|
|
2262
2263
|
.decimalPlaces(reserve.token.decimals, BigNumber.ROUND_DOWN)
|
|
2263
2264
|
.lte(0));
|
|
2264
2265
|
});
|
|
2266
|
+
const sendStrategyWithdrawnCoin = async (transaction, coin, estimatedAmount, address, consumeWithdrawnCoin, dryRunTransaction) => {
|
|
2267
|
+
if (!consumeWithdrawnCoin) {
|
|
2268
|
+
transaction.transferObjects([coin], address);
|
|
2269
|
+
return;
|
|
2270
|
+
}
|
|
2271
|
+
const transactionBeforeConsumer = Transaction.from(transaction);
|
|
2272
|
+
await consumeWithdrawnCoin(transaction, coin, estimatedAmount);
|
|
2273
|
+
try {
|
|
2274
|
+
await dryRunTransaction(transaction);
|
|
2275
|
+
}
|
|
2276
|
+
catch (err) {
|
|
2277
|
+
transactionBeforeConsumer.transferObjects([coin], address);
|
|
2278
|
+
try {
|
|
2279
|
+
await dryRunTransaction(transactionBeforeConsumer);
|
|
2280
|
+
}
|
|
2281
|
+
catch {
|
|
2282
|
+
return;
|
|
2283
|
+
}
|
|
2284
|
+
console.error(err);
|
|
2285
|
+
throw new Error(STRATEGY_WITHDRAWN_COIN_CONSUMER_ERROR_MESSAGE);
|
|
2286
|
+
}
|
|
2287
|
+
};
|
|
2288
|
+
const getRedeemedSuiAmount = (lstAmount, lst) => lstAmount
|
|
2289
|
+
.times(new BigNumber(lst?.lstToSuiExchangeRate ?? 1).times(1 - +(lst?.redeemFeePercent ?? 0) / 100))
|
|
2290
|
+
.decimalPlaces(SUI_DECIMALS, BigNumber.ROUND_DOWN);
|
|
2265
2291
|
const tryClaimStrategyRewardsToUser = async (strategyType, rewardsMap, strategyOwnerCapId, address, transaction, dryRunTransaction) => {
|
|
2266
2292
|
const transactionBeforeClaim = Transaction.from(transaction);
|
|
2267
2293
|
try {
|
|
@@ -2281,7 +2307,9 @@ export const strategyWithdrawTx = async (
|
|
|
2281
2307
|
// AppContext
|
|
2282
2308
|
reserveMap,
|
|
2283
2309
|
// Strategy
|
|
2284
|
-
lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, _deposits, _borrowedAmount, withdraw, transaction, dryRunTransaction, returnWithdrawnCoin, rewardsMap = {}) => {
|
|
2310
|
+
lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, _deposits, _borrowedAmount, withdraw, transaction, dryRunTransaction, returnWithdrawnCoin, rewardsMap = {}, consumeWithdrawnCoin) => {
|
|
2311
|
+
if (returnWithdrawnCoin && consumeWithdrawnCoin)
|
|
2312
|
+
throw new Error("Pass returnWithdrawnCoin or consumeWithdrawnCoin, not both");
|
|
2285
2313
|
const strategyInfo = STRATEGY_TYPE_INFO_MAP[strategyType];
|
|
2286
2314
|
const lst = strategyInfo.depositLstCoinType !== undefined
|
|
2287
2315
|
? lstMap[strategyInfo.depositLstCoinType]
|
|
@@ -2399,6 +2427,7 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2399
2427
|
newTvlAmountUsd: newTvlAmountUsd.toFixed(20),
|
|
2400
2428
|
}, null, 2));
|
|
2401
2429
|
// 3) Transfer coin to user, or return coin
|
|
2430
|
+
const sendWithdrawnCoin = (coin, estimatedAmount) => sendStrategyWithdrawnCoin(transaction, coin, estimatedAmount, _address, consumeWithdrawnCoin, dryRunTransaction);
|
|
2402
2431
|
if (returnWithdrawnCoin)
|
|
2403
2432
|
return { deposits, borrowedAmount, transaction, withdrawnCoin };
|
|
2404
2433
|
else {
|
|
@@ -2416,7 +2445,8 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2416
2445
|
});
|
|
2417
2446
|
if (!routers)
|
|
2418
2447
|
throw new Error("No swap quote found");
|
|
2419
|
-
const
|
|
2448
|
+
const swappedAmount = new BigNumber(routers.amountOut.toString()).div(10 ** reserveMap[withdraw.coinType].token.decimals);
|
|
2449
|
+
const { slippagePercent } = resolveSwapSlippage(finalWithdrawnAmount, swappedAmount, depositReserve, reserveMap[withdraw.coinType]);
|
|
2420
2450
|
let swappedCoin;
|
|
2421
2451
|
try {
|
|
2422
2452
|
swappedCoin = (await cetusSdk.fixableRouterSwapV3({
|
|
@@ -2430,10 +2460,10 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2430
2460
|
catch (err) {
|
|
2431
2461
|
throw new Error("No swap quote found");
|
|
2432
2462
|
}
|
|
2433
|
-
|
|
2463
|
+
await sendWithdrawnCoin(swappedCoin, swappedAmount);
|
|
2434
2464
|
}
|
|
2435
2465
|
else {
|
|
2436
|
-
|
|
2466
|
+
await sendWithdrawnCoin(withdrawnCoin, finalWithdrawnAmount);
|
|
2437
2467
|
}
|
|
2438
2468
|
}
|
|
2439
2469
|
else {
|
|
@@ -2441,11 +2471,11 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2441
2471
|
// 3.1) Unstake LST for SUI
|
|
2442
2472
|
const suiWithdrawnCoin = lst.client.redeem(transaction, withdrawnCoin);
|
|
2443
2473
|
// 3.2) Transfer SUI to user
|
|
2444
|
-
|
|
2474
|
+
await sendWithdrawnCoin(suiWithdrawnCoin, getRedeemedSuiAmount(finalWithdrawnAmount, lst));
|
|
2445
2475
|
}
|
|
2446
2476
|
else {
|
|
2447
2477
|
// 3.1) Transfer LST to user
|
|
2448
|
-
|
|
2478
|
+
await sendWithdrawnCoin(withdrawnCoin, finalWithdrawnAmount);
|
|
2449
2479
|
}
|
|
2450
2480
|
}
|
|
2451
2481
|
}
|
|
@@ -2458,7 +2488,7 @@ export const strategyMaxWithdrawTx = async (
|
|
|
2458
2488
|
// AppContext
|
|
2459
2489
|
reserveMap, rewardsMap,
|
|
2460
2490
|
// Strategy
|
|
2461
|
-
lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, _deposits, _borrowedAmount, withdrawCoinType, transaction, _dryRunTransaction) => {
|
|
2491
|
+
lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, _deposits, _borrowedAmount, withdrawCoinType, transaction, _dryRunTransaction, consumeWithdrawnCoin) => {
|
|
2462
2492
|
const { rateLimit, dryRunTransaction } = trackRateLimit(_dryRunTransaction);
|
|
2463
2493
|
const strategyInfo = STRATEGY_TYPE_INFO_MAP[strategyType];
|
|
2464
2494
|
const lst = strategyInfo.depositLstCoinType !== undefined
|
|
@@ -2604,6 +2634,7 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2604
2634
|
receipt,
|
|
2605
2635
|
borrowedBalanceA,
|
|
2606
2636
|
remainingCoin: flashLoanBorrowedCoin,
|
|
2637
|
+
borrowedAmount: flashLoanBorrowedAmount,
|
|
2607
2638
|
};
|
|
2608
2639
|
}
|
|
2609
2640
|
const estimatedWithdrawnAmount = deposits.find((d) => d.coinType === depositReserve.coinType)
|
|
@@ -2618,6 +2649,7 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2618
2649
|
})),
|
|
2619
2650
|
borrowedAmount: borrowedAmount.toFixed(20),
|
|
2620
2651
|
}, null, 2));
|
|
2652
|
+
const sendWithdrawnCoin = (coin, estimatedAmount) => sendStrategyWithdrawnCoin(transaction, coin, estimatedAmount, _address, consumeWithdrawnCoin, dryRunTransaction);
|
|
2621
2653
|
// 3) Transfer coin to user
|
|
2622
2654
|
if (depositReserve.coinType === depositReserves.base?.coinType) {
|
|
2623
2655
|
if (withdrawCoinType !== depositReserve.coinType) {
|
|
@@ -2633,7 +2665,8 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2633
2665
|
});
|
|
2634
2666
|
if (!routers)
|
|
2635
2667
|
throw new Error("No swap quote found");
|
|
2636
|
-
const
|
|
2668
|
+
const swappedAmount = new BigNumber(routers.amountOut.toString()).div(10 ** reserveMap[withdrawCoinType].token.decimals);
|
|
2669
|
+
const { slippagePercent } = resolveSwapSlippage(estimatedWithdrawnAmount, swappedAmount, depositReserve, reserveMap[withdrawCoinType]);
|
|
2637
2670
|
let swappedCoin;
|
|
2638
2671
|
try {
|
|
2639
2672
|
swappedCoin = (await cetusSdk.fixableRouterSwapV3({
|
|
@@ -2647,10 +2680,10 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2647
2680
|
catch (err) {
|
|
2648
2681
|
throw new Error("No swap quote found");
|
|
2649
2682
|
}
|
|
2650
|
-
|
|
2683
|
+
await sendWithdrawnCoin(swappedCoin, swappedAmount);
|
|
2651
2684
|
}
|
|
2652
2685
|
else {
|
|
2653
|
-
|
|
2686
|
+
await sendWithdrawnCoin(withdrawnCoin, estimatedWithdrawnAmount);
|
|
2654
2687
|
}
|
|
2655
2688
|
}
|
|
2656
2689
|
else {
|
|
@@ -2686,11 +2719,11 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2686
2719
|
});
|
|
2687
2720
|
}
|
|
2688
2721
|
// 3.3) Transfer SUI to user
|
|
2689
|
-
|
|
2722
|
+
await sendWithdrawnCoin(suiWithdrawnCoin, BigNumber.max(0, getRedeemedSuiAmount(estimatedWithdrawnAmount, lst).minus(flashLoan?.borrowedAmount ?? 0)));
|
|
2690
2723
|
}
|
|
2691
2724
|
else {
|
|
2692
2725
|
// 3.1) Transfer LST to user
|
|
2693
|
-
|
|
2726
|
+
await sendWithdrawnCoin(withdrawnCoin, estimatedWithdrawnAmount);
|
|
2694
2727
|
}
|
|
2695
2728
|
}
|
|
2696
2729
|
// 4) Claim rewards and transfer to user
|