@suilend/sdk 2.0.4 → 2.0.5

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/client.js CHANGED
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  };
10
10
  import { SUI_CLOCK_OBJECT_ID, SUI_SYSTEM_STATE_OBJECT_ID, fromBase64, normalizeStructTag, toHex, } from "@mysten/sui/utils";
11
11
  import { SuiPriceServiceConnection, SuiPythClient, } from "@pythnetwork/pyth-sui-js";
12
- import { extractCTokenCoinType, getAllCoins, mergeAllCoins, } from "@suilend/sui-fe";
12
+ import { extractCTokenCoinType, getAllCoins } from "@suilend/sui-fe";
13
13
  import { PriceInfoObject } from "./_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/price-info/structs";
14
14
  import { phantom } from "./_generated/_framework/reified";
15
15
  import { PKG_V10, setPublishedAt } from "./_generated/suilend";
@@ -20,6 +20,7 @@ import { createLendingMarket } from "./_generated/suilend/lending-market-registr
20
20
  import { Obligation } from "./_generated/suilend/obligation/structs";
21
21
  import { newConfig as createRateLimiterConfig, } from "./_generated/suilend/rate-limiter/functions";
22
22
  import { createReserveConfig, } from "./_generated/suilend/reserve-config/functions";
23
+ import { getSpendableCoin } from "./lib/coin";
23
24
  import { PRIMARY_PYTH_ENDPOINT } from "./lib/pyth";
24
25
  import { Side } from "./lib/types";
25
26
  const SUI_COINTYPE = "0x2::sui::SUI";
@@ -221,16 +222,7 @@ export class SuilendClient {
221
222
  }
222
223
  addReward(ownerId_1, lendingMarketOwnerCapId_1, reserveArrayIndex_1, isDepositReward_1, rewardCoinType_1, rewardValue_1, startTimeMs_1, endTimeMs_1, transaction_1) {
223
224
  return __awaiter(this, arguments, void 0, function* (ownerId, lendingMarketOwnerCapId, reserveArrayIndex, isDepositReward, rewardCoinType, rewardValue, startTimeMs, endTimeMs, transaction, mergeCoins = true) {
224
- const coins = (yield this.client.getCoins({
225
- owner: ownerId,
226
- coinType: rewardCoinType,
227
- })).data;
228
- if (coins.length > 1 && !isSui(rewardCoinType) && mergeCoins) {
229
- transaction.mergeCoins(transaction.object(coins[0].coinObjectId), coins.map((c) => transaction.object(c.coinObjectId)).slice(1));
230
- }
231
- const [rewardCoin] = transaction.splitCoins(isSui(rewardCoinType)
232
- ? transaction.gas
233
- : transaction.object(coins[0].coinObjectId), [rewardValue]);
225
+ const rewardCoin = yield getSpendableCoin(this.client, ownerId, rewardCoinType, rewardValue, transaction);
234
226
  return addPoolReward(transaction, [this.lendingMarket.$typeArgs[0], rewardCoinType], {
235
227
  lendingMarketOwnerCap: transaction.object(lendingMarketOwnerCapId),
236
228
  lendingMarket: transaction.object(this.lendingMarket.id),
@@ -454,21 +446,13 @@ export class SuilendClient {
454
446
  }
455
447
  depositIntoObligation(ownerId, coinType, value, transaction, obligationOwnerCap) {
456
448
  return __awaiter(this, void 0, void 0, function* () {
457
- const coins = yield getAllCoins(this.client, ownerId, coinType);
458
- const mergeCoin = mergeAllCoins(coinType, transaction, coins);
459
- const [sendCoin] = transaction.splitCoins(isSui(coinType)
460
- ? transaction.gas
461
- : transaction.object(mergeCoin.coinObjectId), [value]);
449
+ const sendCoin = yield getSpendableCoin(this.client, ownerId, coinType, value, transaction);
462
450
  this.deposit(sendCoin, coinType, obligationOwnerCap, transaction);
463
451
  });
464
452
  }
465
453
  depositLiquidityAndGetCTokens(ownerId, coinType, value, transaction) {
466
454
  return __awaiter(this, void 0, void 0, function* () {
467
- const coins = yield getAllCoins(this.client, ownerId, coinType);
468
- const mergeCoin = mergeAllCoins(coinType, transaction, coins);
469
- const [sendCoin] = transaction.splitCoins(isSui(coinType)
470
- ? transaction.gas
471
- : transaction.object(mergeCoin.coinObjectId), [value]);
455
+ const sendCoin = yield getSpendableCoin(this.client, ownerId, coinType, value, transaction);
472
456
  const [ctokens] = depositLiquidityAndMintCtokens(transaction, [this.lendingMarket.$typeArgs[0], coinType], {
473
457
  lendingMarket: transaction.object(this.lendingMarket.id),
474
458
  reserveArrayIndex: transaction.pure.u64(this.findReserveArrayIndex(coinType)),
@@ -578,11 +562,7 @@ export class SuilendClient {
578
562
  }
579
563
  repayIntoObligation(ownerId, obligationId, coinType, value, transaction) {
580
564
  return __awaiter(this, void 0, void 0, function* () {
581
- const coins = yield getAllCoins(this.client, ownerId, coinType);
582
- const mergeCoin = mergeAllCoins(coinType, transaction, coins);
583
- const [sendCoin] = transaction.splitCoins(isSui(coinType)
584
- ? transaction.gas
585
- : transaction.object(mergeCoin.coinObjectId), [value]);
565
+ const sendCoin = yield getSpendableCoin(this.client, ownerId, coinType, value, transaction);
586
566
  const result = this.repay(obligationId, coinType, sendCoin, transaction);
587
567
  transaction.transferObjects([sendCoin], transaction.pure.address(ownerId));
588
568
  return result;
@@ -637,13 +617,12 @@ export class SuilendClient {
637
617
  }
638
618
  redeemCtokensAndWithdrawLiquidity(ownerId, ctokenCoinTypes, transaction) {
639
619
  return __awaiter(this, void 0, void 0, function* () {
640
- const mergeCoinMap = {};
641
620
  for (const ctokenCoinType of ctokenCoinTypes) {
642
621
  const coins = yield getAllCoins(this.client, ownerId, ctokenCoinType);
643
- const mergeCoin = mergeAllCoins(ctokenCoinType, transaction, coins);
644
- mergeCoinMap[ctokenCoinType] = mergeCoin;
645
- }
646
- for (const [ctokenCoinType, mergeCoin] of Object.entries(mergeCoinMap)) {
622
+ const totalBalance = coins.reduce((sum, c) => sum + BigInt(c.balance), BigInt(0));
623
+ if (totalBalance === BigInt(0))
624
+ throw new Error(`No ${ctokenCoinType} coins found for redeem`);
625
+ const ctokenCoin = yield getSpendableCoin(this.client, ownerId, ctokenCoinType, totalBalance.toString(), transaction);
647
626
  const coinType = extractCTokenCoinType(ctokenCoinType);
648
627
  const [exemption] = transaction.moveCall({
649
628
  target: `0x1::option::none`,
@@ -652,7 +631,7 @@ export class SuilendClient {
652
631
  ],
653
632
  arguments: [],
654
633
  });
655
- const [redeemCoin] = this.redeem(transaction.object(mergeCoin.coinObjectId), coinType, exemption, transaction);
634
+ const [redeemCoin] = this.redeem(ctokenCoin, coinType, exemption, transaction);
656
635
  transaction.transferObjects([redeemCoin], transaction.pure.address(ownerId));
657
636
  }
658
637
  });
package/lib/coin.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import { SuiJsonRpcClient } from "@mysten/sui/jsonRpc";
2
+ import { Transaction, TransactionObjectArgument } from "@mysten/sui/transactions";
3
+ export declare const getSpendableCoin: (suiClient: SuiJsonRpcClient, address: string, coinType: string, value: string, transaction: Transaction) => Promise<TransactionObjectArgument>;
package/lib/coin.js ADDED
@@ -0,0 +1,67 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { getAllCoins, isSui, mergeAllCoins } from "@suilend/sui-fe";
11
+ // Build a spendable coin using owned coin objects, address balance, or both.
12
+ export const getSpendableCoin = (suiClient, address, coinType, value, transaction) => __awaiter(void 0, void 0, void 0, function* () {
13
+ var _a;
14
+ const spendValue = BigInt(value);
15
+ if (spendValue <= BigInt(0)) {
16
+ throw new Error("Spend amount must be positive");
17
+ }
18
+ // Address-balance withdrawals resolve against the transaction sender.
19
+ transaction.setSenderIfNotSet(address);
20
+ const [coins, balance] = yield Promise.all([
21
+ getAllCoins(suiClient, address, coinType),
22
+ suiClient.getBalance({ owner: address, coinType }),
23
+ ]);
24
+ const nonZeroCoins = coins.filter((c) => BigInt(c.balance) > BigInt(0));
25
+ const objectCoinBalance = nonZeroCoins.reduce((sum, c) => sum + BigInt(c.balance), BigInt(0));
26
+ const addressBalanceAvailable = BigInt((_a = balance.fundsInAddressBalance) !== null && _a !== void 0 ? _a : "0");
27
+ const totalAvailable = BigInt(balance.totalBalance);
28
+ if (totalAvailable < spendValue) {
29
+ throw new Error(`Insufficient ${coinType} balance: need ${value}, have ${balance.totalBalance} (${objectCoinBalance.toString()} in coins, ${addressBalanceAvailable.toString()} in address)`);
30
+ }
31
+ const objectCoinSpend = objectCoinBalance >= spendValue ? spendValue : objectCoinBalance;
32
+ const addressBalanceSpend = spendValue - objectCoinSpend;
33
+ console.log(`[getSpendableCoin] ${coinType} requested=${value} coinObjects=${objectCoinSpend.toString()} addressBalance=${addressBalanceSpend.toString()}`);
34
+ // Address balance only.
35
+ if (objectCoinSpend === BigInt(0)) {
36
+ return transaction.moveCall({
37
+ target: "0x2::coin::redeem_funds",
38
+ typeArguments: [coinType],
39
+ arguments: [transaction.withdrawal({ amount: value, type: coinType })],
40
+ });
41
+ }
42
+ const mergedCoin = mergeAllCoins(coinType, transaction, nonZeroCoins);
43
+ const coinSource = isSui(coinType)
44
+ ? transaction.gas
45
+ : transaction.object(mergedCoin.coinObjectId);
46
+ // Coin objects only.
47
+ if (addressBalanceSpend === BigInt(0)) {
48
+ const [sendCoin] = transaction.splitCoins(coinSource, [value]);
49
+ return sendCoin;
50
+ }
51
+ // Mixed: split from coin objects, redeem the rest from address balance, merge.
52
+ const [objectCoin] = transaction.splitCoins(coinSource, [
53
+ objectCoinSpend.toString(),
54
+ ]);
55
+ const addressCoin = transaction.moveCall({
56
+ target: "0x2::coin::redeem_funds",
57
+ typeArguments: [coinType],
58
+ arguments: [
59
+ transaction.withdrawal({
60
+ amount: addressBalanceSpend.toString(),
61
+ type: coinType,
62
+ }),
63
+ ],
64
+ });
65
+ transaction.mergeCoins(objectCoin, [addressCoin]);
66
+ return objectCoin;
67
+ });
package/lib/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export * from "./coin";
1
2
  export * from "./constants";
2
3
  export * from "./initialize";
3
4
  export * from "./liquidityMining";
package/lib/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ export * from "./coin";
1
2
  export * from "./constants";
2
3
  export * from "./initialize";
3
4
  export * from "./liquidityMining";
package/lib/initialize.js CHANGED
@@ -16,7 +16,7 @@ import { parseLendingMarket, parseObligation } from "../parsers";
16
16
  import * as simulate from "../utils/simulate";
17
17
  import { WAD } from "./constants";
18
18
  import { getWorkingPythEndpoint } from "./pyth";
19
- import { STRATEGY_WRAPPER_PACKAGE_ID_V1, } from "./strategyOwnerCap";
19
+ import { STRATEGY_TYPE_INFO_MAP, STRATEGY_WRAPPER_PACKAGE_ID_V1, } from "./strategyOwnerCap";
20
20
  export const RESERVES_CUSTOM_ORDER = {
21
21
  [LENDING_MARKET_ID]: [
22
22
  // MAIN ASSETS
@@ -232,8 +232,9 @@ export const initializeObligations = (suiClient, suilendClient, refreshedRawRese
232
232
  };
233
233
  const [strategyOwnerCaps, obligationOwnerCaps] = yield Promise.all([
234
234
  (() => __awaiter(void 0, void 0, void 0, function* () {
235
- if (suilendClient.lendingMarket.id !== LENDING_MARKET_ID)
236
- return []; // Only main lending market has strategy owner caps
235
+ const hasStrategies = Object.values(STRATEGY_TYPE_INFO_MAP).some((info) => info.lendingMarketId === suilendClient.lendingMarket.id);
236
+ if (!hasStrategies)
237
+ return [];
237
238
  const objects = yield getAllOwnedObjects(suiClient, address, {
238
239
  StructType: `${STRATEGY_WRAPPER_PACKAGE_ID_V1}::strategy_wrapper::StrategyOwnerCap<${suilendClient.lendingMarket.$typeArgs[0]}>`,
239
240
  });
@@ -1,22 +1,27 @@
1
1
  import { AggregatorClient as CetusSdk } from "@cetusprotocol/aggregator-sdk";
2
- import { Transaction, TransactionObjectInput, TransactionResult } from "@mysten/sui/transactions";
2
+ import { Transaction, TransactionObjectArgument, TransactionObjectInput, TransactionResult } from "@mysten/sui/transactions";
3
3
  import BigNumber from "bignumber.js";
4
4
  import { ParsedObligation, ParsedReserve } from "../parsers";
5
5
  import { RewardsMap, StrategyOwnerCap } from "./types";
6
6
  export declare const STRATEGY_WRAPPER_PACKAGE_ID_V1 = "0xba97dc73a07638d03d77ad2161484eb21db577edc9cadcd7035fef4b4f2f6fa1";
7
7
  export declare enum StrategyType {
8
8
  sSUI_SUI_LOOPING = "1",
9
- stratSUI_SUI_LOOPING = "2",
10
9
  USDC_sSUI_SUI_LOOPING = "3",
10
+ USDsui_USDC_LOOPING = "10",
11
+ eEARN_USDC_LOOPING = "11",
11
12
  AUSD_sSUI_SUI_LOOPING = "4",
12
13
  xBTC_sSUI_SUI_LOOPING = "100",// Used to be for Slush Strategies #0
13
14
  xBTC_suiWBTC_LOOPING = "101",// Used to be for Slush Strategies #1
14
15
  suiUSDT_sSUI_SUI_LOOPING = "5",
15
16
  AUSD_USDC_LOOPING = "6",
16
17
  AUSD_suiUSDT_LOOPING = "7",
17
- USDC_suiUSDT_LOOPING = "8"
18
+ USDC_suiUSDT_LOOPING = "8",
19
+ USDsui_sSUI_SUI_LOOPING = "9",
20
+ stratSUI_SUI_LOOPING = "2"
18
21
  }
19
22
  export declare const STRATEGY_TYPE_INFO_MAP: Record<StrategyType, {
23
+ lendingMarketId: string;
24
+ lendingMarketType: string;
20
25
  queryParam: string;
21
26
  header: {
22
27
  coinTypes: string[];
@@ -30,10 +35,10 @@ export declare const STRATEGY_TYPE_INFO_MAP: Record<StrategyType, {
30
35
  currencyCoinTypes: string[];
31
36
  defaultCurrencyCoinType: string;
32
37
  }>;
33
- export declare const strategyDeposit: (coin: TransactionObjectInput, coinType: string, strategyOwnerCap: TransactionObjectInput, reserveArrayIndex: bigint, transaction: Transaction) => TransactionResult;
34
- export declare const strategyBorrow: (coinType: string, strategyOwnerCap: TransactionObjectInput, reserveArrayIndex: bigint, value: bigint, transaction: Transaction) => TransactionResult;
35
- export declare const strategyWithdraw: (coinType: string, strategyOwnerCap: TransactionObjectInput, reserveArrayIndex: bigint, value: bigint, transaction: Transaction) => TransactionResult;
36
- export declare const strategyClaimRewardsAndSwapForCoinType: (address: string, cetusSdk: CetusSdk, cetusPartnerId: string, rewardsMap: RewardsMap, rewardPriceMap: Record<string, BigNumber | undefined>, depositReserve: ParsedReserve, strategyOwnerCap: TransactionObjectInput, isDepositing: boolean, transaction: Transaction) => Promise<void>;
38
+ export declare const strategyDeposit: (strategyType: StrategyType, coin: TransactionObjectInput, coinType: string, strategyOwnerCap: TransactionObjectInput, reserveArrayIndex: bigint, transaction: Transaction) => TransactionResult;
39
+ export declare const strategyBorrow: (strategyType: StrategyType, coinType: string, strategyOwnerCap: TransactionObjectInput, reserveArrayIndex: bigint, value: bigint, transaction: Transaction) => TransactionResult;
40
+ export declare const strategyWithdraw: (strategyType: StrategyType, coinType: string, strategyOwnerCap: TransactionObjectInput, reserveArrayIndex: bigint, value: bigint, transaction: Transaction) => TransactionResult;
41
+ export declare const strategyClaimRewardsAndMergeCoins: (strategyType: StrategyType, rewardsMap: RewardsMap, strategyOwnerCap: TransactionObjectInput, transaction: Transaction) => Record<string, TransactionObjectArgument>;
37
42
  export declare const strategySwapSomeDepositsForCoinType: (strategyType: StrategyType, cetusSdk: CetusSdk, cetusPartnerId: string, obligation: ParsedObligation, noSwapCoinTypes: string[], // coinTypes to not swap for depositReserve.coinType
38
43
  swapPercent: BigNumber, // percent of deposit to swap for depositReserve.coinType (0-100)
39
44
  depositReserve: ParsedReserve, strategyOwnerCap: TransactionObjectInput, transaction: Transaction) => Promise<void>;