@scallop-io/sui-scallop-sdk 0.46.55 → 0.46.56

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.
Files changed (53) hide show
  1. package/dist/constants/common.d.ts +1 -1
  2. package/dist/constants/pyth.d.ts +1 -1
  3. package/dist/index.js +1752 -1602
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.mjs +1720 -1570
  6. package/dist/index.mjs.map +1 -1
  7. package/dist/models/scallop.d.ts +1 -1
  8. package/dist/models/scallopAddress.d.ts +4 -4
  9. package/dist/models/scallopBuilder.d.ts +2 -2
  10. package/dist/models/scallopCache.d.ts +2 -2
  11. package/dist/models/scallopClient.d.ts +7 -2
  12. package/dist/models/scallopIndexer.d.ts +3 -3
  13. package/dist/models/scallopPrice.d.ts +0 -0
  14. package/dist/models/scallopQuery.d.ts +10 -4
  15. package/dist/models/scallopUtils.d.ts +8 -7
  16. package/dist/queries/borrowIncentiveQuery.d.ts +10 -4
  17. package/dist/queries/coreQuery.d.ts +8 -4
  18. package/dist/queries/priceQuery.d.ts +7 -3
  19. package/dist/queries/referralQuery.d.ts +2 -2
  20. package/dist/queries/sCoinQuery.d.ts +18 -4
  21. package/dist/queries/spoolQuery.d.ts +10 -4
  22. package/dist/queries/vescaQuery.d.ts +7 -5
  23. package/dist/types/builder/vesca.d.ts +2 -1
  24. package/dist/types/model.d.ts +27 -12
  25. package/dist/types/query/core.d.ts +1 -0
  26. package/package.json +1 -1
  27. package/src/builders/borrowIncentiveBuilder.ts +19 -21
  28. package/src/builders/coreBuilder.ts +10 -8
  29. package/src/builders/spoolBuilder.ts +2 -2
  30. package/src/builders/vescaBuilder.ts +12 -4
  31. package/src/constants/common.ts +2 -0
  32. package/src/constants/enum.ts +4 -0
  33. package/src/constants/pyth.ts +2 -2
  34. package/src/models/scallop.ts +14 -20
  35. package/src/models/scallopAddress.ts +15 -5
  36. package/src/models/scallopBuilder.ts +29 -25
  37. package/src/models/scallopCache.ts +2 -2
  38. package/src/models/scallopClient.ts +91 -32
  39. package/src/models/scallopIndexer.ts +15 -8
  40. package/src/models/scallopPrice.ts +0 -0
  41. package/src/models/scallopQuery.ts +47 -25
  42. package/src/models/scallopUtils.ts +75 -74
  43. package/src/queries/borrowIncentiveQuery.ts +40 -29
  44. package/src/queries/coreQuery.ts +38 -24
  45. package/src/queries/portfolioQuery.ts +1 -2
  46. package/src/queries/priceQuery.ts +20 -9
  47. package/src/queries/referralQuery.ts +4 -4
  48. package/src/queries/sCoinQuery.ts +95 -17
  49. package/src/queries/spoolQuery.ts +26 -14
  50. package/src/queries/vescaQuery.ts +32 -26
  51. package/src/types/builder/vesca.ts +8 -1
  52. package/src/types/model.ts +40 -11
  53. package/src/types/query/core.ts +1 -0
@@ -15,7 +15,7 @@ import {
15
15
  } from '../utils';
16
16
  import type { SuiObjectResponse, SuiObjectData } from '@mysten/sui.js/client';
17
17
  import type { SuiAddressArg } from '@scallop-io/sui-kit';
18
- import type { ScallopQuery } from '../models';
18
+ import type { ScallopAddress, ScallopCache, ScallopQuery } from '../models';
19
19
  import {
20
20
  Market,
21
21
  MarketPools,
@@ -129,6 +129,9 @@ export const queryMarket = async (
129
129
  symbol: query.utils.parseSymbol(poolCoinName),
130
130
  coinType: coinType,
131
131
  marketCoinType: query.utils.parseMarketCoinType(poolCoinName),
132
+ sCoinType: query.utils.parseSCoinType(
133
+ query.utils.parseMarketCoinName(poolCoinName)
134
+ ),
132
135
  coinWrappedType: query.utils.getCoinWrappedType(poolCoinName),
133
136
  coinDecimal: query.utils.getCoinDecimal(poolCoinName),
134
137
  coinPrice: coinPrice,
@@ -453,6 +456,9 @@ export const getMarketPool = async (
453
456
  symbol: query.utils.parseSymbol(poolCoinName),
454
457
  coinType: query.utils.parseCoinType(poolCoinName),
455
458
  marketCoinType: query.utils.parseMarketCoinType(poolCoinName),
459
+ sCoinType: query.utils.parseSCoinType(
460
+ query.utils.parseMarketCoinName(poolCoinName)
461
+ ),
456
462
  coinWrappedType: query.utils.getCoinWrappedType(poolCoinName),
457
463
  coinDecimal: query.utils.getCoinDecimal(poolCoinName),
458
464
  coinPrice: coinPrice ?? 0,
@@ -683,24 +689,29 @@ export const getMarketCollateral = async (
683
689
  * @return Owned obligations.
684
690
  */
685
691
  export const getObligations = async (
686
- query: ScallopQuery,
687
- ownerAddress?: string
692
+ {
693
+ address,
694
+ }: {
695
+ address: ScallopAddress;
696
+ },
697
+ ownerAddress: string
688
698
  ) => {
689
- const owner = ownerAddress || query.suiKit.currentAddress();
690
- const protocolObjectId =
691
- query.address.get('core.object') || PROTOCOL_OBJECT_ID;
699
+ const owner = ownerAddress;
700
+ const protocolObjectId = address.get('core.object') || PROTOCOL_OBJECT_ID;
692
701
  const keyObjectsResponse: SuiObjectResponse[] = [];
693
702
  let hasNextPage = false;
694
703
  let nextCursor: string | null | undefined = null;
695
704
  do {
696
- const paginatedKeyObjectsResponse = await query.cache.queryGetOwnedObjects({
697
- owner,
698
- filter: {
699
- StructType: `${protocolObjectId}::obligation::ObligationKey`,
700
- },
701
- cursor: nextCursor,
702
- });
703
- if (!paginatedKeyObjectsResponse) continue;
705
+ const paginatedKeyObjectsResponse =
706
+ await address.cache.queryGetOwnedObjects({
707
+ owner,
708
+ filter: {
709
+ StructType: `${protocolObjectId}::obligation::ObligationKey`,
710
+ },
711
+ cursor: nextCursor,
712
+ });
713
+
714
+ if (!paginatedKeyObjectsResponse) break;
704
715
 
705
716
  keyObjectsResponse.push(...paginatedKeyObjectsResponse.data);
706
717
  if (
@@ -717,7 +728,7 @@ export const getObligations = async (
717
728
  const keyObjectIds: string[] = keyObjectsResponse
718
729
  .map((ref: any) => ref?.data?.objectId)
719
730
  .filter((id: any) => id !== undefined);
720
- const keyObjects = await query.cache.queryGetObjects(keyObjectIds);
731
+ const keyObjects = await address.cache.queryGetObjects(keyObjectIds);
721
732
 
722
733
  const obligations: Obligation[] = [];
723
734
  await Promise.allSettled(
@@ -726,7 +737,7 @@ export const getObligations = async (
726
737
  if (keyObject.content && 'fields' in keyObject.content) {
727
738
  const fields = keyObject.content.fields as any;
728
739
  const obligationId = String(fields.ownership.fields.of);
729
- const locked = await getObligationLocked(query, obligationId);
740
+ const locked = await getObligationLocked(address.cache, obligationId);
730
741
  obligations.push({ id: obligationId, keyId, locked });
731
742
  }
732
743
  })
@@ -743,13 +754,12 @@ export const getObligations = async (
743
754
  * @return Obligation locked status.
744
755
  */
745
756
  export const getObligationLocked = async (
746
- query: ScallopQuery,
757
+ cache: ScallopCache,
747
758
  obligationId: string
748
759
  ) => {
749
- const obligationObjectResponse = await query.cache.queryGetObject(
750
- obligationId,
751
- { showContent: true }
752
- );
760
+ const obligationObjectResponse = await cache.queryGetObject(obligationId, {
761
+ showContent: true,
762
+ });
753
763
  let obligationLocked = false;
754
764
  if (
755
765
  obligationObjectResponse?.data &&
@@ -775,16 +785,20 @@ export const getObligationLocked = async (
775
785
  * @return Obligation data.
776
786
  */
777
787
  export const queryObligation = async (
778
- query: ScallopQuery,
788
+ {
789
+ address,
790
+ }: {
791
+ address: ScallopAddress;
792
+ },
779
793
  obligationId: SuiAddressArg
780
794
  ) => {
781
- const packageId = query.address.get('core.packages.query.id');
795
+ const packageId = address.get('core.packages.query.id');
782
796
  const queryTarget = `${packageId}::obligation_query::obligation_data`;
783
797
  const args = [obligationId];
784
798
 
785
799
  // const txBlock = new SuiKitTxBlock();
786
800
  // txBlock.moveCall(queryTarget, args);
787
- const queryResult = await query.cache.queryInspectTxn(
801
+ const queryResult = await address.cache.queryInspectTxn(
788
802
  { queryTarget, args }
789
803
  // txBlock
790
804
  );
@@ -38,11 +38,10 @@ import type {
38
38
  */
39
39
  export const getLendings = async (
40
40
  query: ScallopQuery,
41
- poolCoinNames?: SupportPoolCoins[],
41
+ poolCoinNames: SupportPoolCoins[] = [...SUPPORT_POOLS],
42
42
  ownerAddress?: string,
43
43
  indexer: boolean = false
44
44
  ) => {
45
- poolCoinNames = poolCoinNames || [...SUPPORT_POOLS];
46
45
  const marketCoinNames = poolCoinNames.map((poolCoinName) =>
47
46
  query.utils.parseMarketCoinName(poolCoinName)
48
47
  );
@@ -1,5 +1,5 @@
1
1
  import { SuiObjectData } from '@mysten/sui.js/client';
2
- import type { ScallopQuery } from '../models';
2
+ import type { ScallopAddress } from '../models';
3
3
  import type { SupportAssetCoins } from '../types';
4
4
 
5
5
  /**
@@ -10,17 +10,24 @@ import type { SupportAssetCoins } from '../types';
10
10
  * @return Asset coin price.
11
11
  */
12
12
  export const getPythPrice = async (
13
- query: ScallopQuery,
13
+ {
14
+ address,
15
+ }: {
16
+ address: ScallopAddress;
17
+ },
14
18
  assetCoinName: SupportAssetCoins,
15
19
  priceFeedObject?: SuiObjectData | null
16
20
  ) => {
17
- const pythFeedObjectId = query.address.get(
21
+ const pythFeedObjectId = address.get(
18
22
  `core.coins.${assetCoinName}.oracle.pyth.feedObject`
19
23
  );
20
24
  priceFeedObject =
21
25
  priceFeedObject ||
22
- (await query.cache.queryGetObject(pythFeedObjectId, { showContent: true }))
23
- ?.data;
26
+ (
27
+ await address.cache.queryGetObject(pythFeedObjectId, {
28
+ showContent: true,
29
+ })
30
+ )?.data;
24
31
 
25
32
  if (priceFeedObject) {
26
33
  const priceFeedPoolObject = priceFeedObject;
@@ -58,12 +65,16 @@ export const getPythPrice = async (
58
65
  };
59
66
 
60
67
  export const getPythPrices = async (
61
- query: ScallopQuery,
68
+ {
69
+ address,
70
+ }: {
71
+ address: ScallopAddress;
72
+ },
62
73
  assetCoinNames: SupportAssetCoins[]
63
74
  ) => {
64
75
  const pythPriceFeedIds = assetCoinNames.reduce(
65
76
  (prev, assetCoinName) => {
66
- const pythPriceFeed = query.address.get(
77
+ const pythPriceFeed = address.get(
67
78
  `core.coins.${assetCoinName}.oracle.pyth.feedObject`
68
79
  );
69
80
  if (!prev[pythPriceFeed]) {
@@ -77,7 +88,7 @@ export const getPythPrices = async (
77
88
  );
78
89
 
79
90
  // Fetch multiple objects at once to save rpc calls
80
- const priceFeedObjects = await query.cache.queryGetObjects(
91
+ const priceFeedObjects = await address.cache.queryGetObjects(
81
92
  Object.keys(pythPriceFeedIds),
82
93
  { showContent: true }
83
94
  );
@@ -98,7 +109,7 @@ export const getPythPrices = async (
98
109
  async ([assetCoinName, priceFeedObject]) => ({
99
110
  coinName: assetCoinName,
100
111
  price: await getPythPrice(
101
- query,
112
+ { address },
102
113
  assetCoinName as SupportAssetCoins,
103
114
  priceFeedObject
104
115
  ),
@@ -1,4 +1,4 @@
1
- import { ScallopQuery } from 'src/models';
1
+ import { ScallopAddress } from 'src/models';
2
2
 
3
3
  /**
4
4
  * Query the veScaKeyId from the referral bindings table using the borrower address
@@ -6,12 +6,12 @@ import { ScallopQuery } from 'src/models';
6
6
  * @returns
7
7
  */
8
8
  export const queryVeScaKeyIdFromReferralBindings = async (
9
- query: ScallopQuery,
9
+ address: ScallopAddress,
10
10
  refereeAddress: string
11
11
  ): Promise<string | null> => {
12
- const referralBindingTableId = query.address.get('referral.bindingTableId');
12
+ const referralBindingTableId = address.get('referral.bindingTableId');
13
13
 
14
- const referralBindResponse = await query.cache.queryGetDynamicFieldObject({
14
+ const referralBindResponse = await address.cache.queryGetDynamicFieldObject({
15
15
  parentId: referralBindingTableId,
16
16
  name: {
17
17
  type: 'address',
@@ -2,7 +2,7 @@ import { bcs } from '@mysten/sui.js/bcs';
2
2
  import assert from 'assert';
3
3
  import BigNumber from 'bignumber.js';
4
4
  import { SUPPORT_SCOIN } from 'src/constants';
5
- import { ScallopQuery } from 'src/models';
5
+ import { ScallopQuery, ScallopUtils } from 'src/models';
6
6
  import { OptionalKeys, SupportSCoin, sCoinBalance } from 'src/types';
7
7
 
8
8
  /**
@@ -12,18 +12,22 @@ import { OptionalKeys, SupportSCoin, sCoinBalance } from 'src/types';
12
12
  * @returns `number`
13
13
  */
14
14
  export const getSCoinTotalSupply = async (
15
- query: ScallopQuery,
15
+ {
16
+ utils,
17
+ }: {
18
+ utils: ScallopUtils;
19
+ },
16
20
  sCoinName: SupportSCoin
17
21
  ): Promise<sCoinBalance> => {
18
- const sCoinPkgId = query.address.get('scoin.id');
22
+ const sCoinPkgId = utils.address.get('scoin.id');
19
23
  // get treasury
20
- const args = [query.utils.getSCoinTreasury(sCoinName)];
24
+ const args = [utils.getSCoinTreasury(sCoinName)];
21
25
  const typeArgs = [
22
- query.utils.parseSCoinType(sCoinName),
23
- query.utils.parseUnderlyingSCoinType(sCoinName),
26
+ utils.parseSCoinType(sCoinName),
27
+ utils.parseUnderlyingSCoinType(sCoinName),
24
28
  ];
25
29
  const queryTarget = `${sCoinPkgId}::s_coin_converter::total_supply`;
26
- const queryResults = await query.cache.queryInspectTxn({
30
+ const queryResults = await utils.cache.queryInspectTxn({
27
31
  queryTarget,
28
32
  args,
29
33
  typeArgs,
@@ -35,9 +39,7 @@ export const getSCoinTotalSupply = async (
35
39
  assert(type === 'u64', 'Result type is not u64');
36
40
 
37
41
  return BigNumber(bcs.de(type, value))
38
- .shiftedBy(
39
- query.utils.getCoinDecimal(query.utils.parseCoinName(sCoinName))
40
- )
42
+ .shiftedBy(utils.getCoinDecimal(utils.parseCoinName(sCoinName)))
41
43
  .toNumber();
42
44
  }
43
45
 
@@ -53,17 +55,21 @@ export const getSCoinTotalSupply = async (
53
55
  * @return All owned sCoins amount.
54
56
  */
55
57
  export const getSCoinAmounts = async (
56
- query: ScallopQuery,
58
+ {
59
+ utils,
60
+ }: {
61
+ utils: ScallopUtils;
62
+ },
57
63
  sCoinNames?: SupportSCoin[],
58
64
  ownerAddress?: string
59
65
  ) => {
60
66
  sCoinNames = sCoinNames || [...SUPPORT_SCOIN];
61
- const owner = ownerAddress || query.suiKit.currentAddress();
67
+ const owner = ownerAddress || utils.suiKit.currentAddress();
62
68
  const sCoins = {} as OptionalKeys<Record<SupportSCoin, number>>;
63
69
 
64
70
  await Promise.allSettled(
65
71
  sCoinNames.map(async (sCoinName) => {
66
- const sCoin = await getSCoinAmount(query, sCoinName, owner);
72
+ const sCoin = await getSCoinAmount({ utils }, sCoinName, owner);
67
73
  sCoins[sCoinName] = sCoin;
68
74
  })
69
75
  );
@@ -80,15 +86,87 @@ export const getSCoinAmounts = async (
80
86
  * @return Owned sCoin amount.
81
87
  */
82
88
  export const getSCoinAmount = async (
83
- query: ScallopQuery,
89
+ {
90
+ utils,
91
+ }: {
92
+ utils: ScallopUtils;
93
+ },
84
94
  sCoinName: SupportSCoin,
85
95
  ownerAddress?: string
86
96
  ) => {
87
- const owner = ownerAddress || query.suiKit.currentAddress();
88
- const sCoinType = query.utils.parseSCoinType(sCoinName);
89
- const amount = await query.cache.queryGetCoinBalance({
97
+ const owner = ownerAddress || utils.suiKit.currentAddress();
98
+ const sCoinType = utils.parseSCoinType(sCoinName);
99
+ const amount = await utils.cache.queryGetCoinBalance({
90
100
  owner,
91
101
  coinType: sCoinType,
92
102
  });
93
103
  return BigNumber(amount).toNumber();
94
104
  };
105
+
106
+ const isSupportStakeCoins = (value: string): value is SupportSCoin => {
107
+ return SUPPORT_SCOIN.includes(value as SupportSCoin);
108
+ };
109
+
110
+ const checkAssetParams = (fromSCoin: SupportSCoin, toSCoin: SupportSCoin) => {
111
+ if (fromSCoin === toSCoin)
112
+ throw new Error('fromAsset and toAsset must be different');
113
+
114
+ if (!isSupportStakeCoins(fromSCoin))
115
+ throw new Error('fromAsset is not supported');
116
+
117
+ if (!isSupportStakeCoins(toSCoin)) {
118
+ throw new Error('toAsset is not supported');
119
+ }
120
+ };
121
+
122
+ /* ==================== Get Swap Rate ==================== */
123
+
124
+ /**
125
+ * Get swap rate from sCoin A to sCoin B.
126
+ * @param fromSCoin
127
+ * @param toSCoin
128
+ * @param underlyingCoinPrice - The price of the underlying coin. For example, if fromSCoin is sSUI and toSCoin is sUSDC, then underlyingCoinPrice represents the price of 1 SUI in USDC.
129
+ * @returns number
130
+ */
131
+ export const getSCoinSwapRate = async (
132
+ query: ScallopQuery,
133
+ fromSCoin: SupportSCoin,
134
+ toSCoin: SupportSCoin,
135
+ underlyingCoinPrice?: number
136
+ ) => {
137
+ checkAssetParams(fromSCoin, toSCoin);
138
+ const fromCoinName = query.utils.parseCoinName(fromSCoin);
139
+ const toCoinName = query.utils.parseCoinName(toSCoin);
140
+
141
+ // Get lending data for both sCoin A and sCoin B
142
+ const marketPools = await Promise.all([
143
+ query.getMarketPool(fromCoinName, false),
144
+ query.getMarketPool(toCoinName, false),
145
+ ]);
146
+ if (marketPools.some((pool) => !pool))
147
+ throw new Error('Failed to fetch the lendings data');
148
+
149
+ if (marketPools.some((pool) => pool?.conversionRate === 0)) {
150
+ throw new Error('Conversion rate cannot be zero');
151
+ }
152
+
153
+ const ScoinAToARate = marketPools[0]!.conversionRate;
154
+ const BtoSCoinBRate = 1 / marketPools[1]!.conversionRate;
155
+
156
+ const calcAtoBRate = async () => {
157
+ const prices = await query.utils.getCoinPrices([fromCoinName, toCoinName]);
158
+ if (!prices[fromCoinName] || !prices[toCoinName]) {
159
+ throw new Error('Failed to fetch the coin prices');
160
+ }
161
+ if (prices[toCoinName] === 0) {
162
+ throw new Error('Price of toCoin cannot be zero');
163
+ }
164
+ return prices[fromCoinName]! / prices[toCoinName]!;
165
+ };
166
+
167
+ const AtoBRate = underlyingCoinPrice ?? (await calcAtoBRate());
168
+ return BigNumber(ScoinAToARate)
169
+ .multipliedBy(AtoBRate)
170
+ .multipliedBy(BtoSCoinBRate)
171
+ .toNumber();
172
+ };
@@ -8,7 +8,7 @@ import {
8
8
  isMarketCoin,
9
9
  } from '../utils';
10
10
  import type { SuiObjectResponse } from '@mysten/sui.js/client';
11
- import type { ScallopQuery } from '../models';
11
+ import type { ScallopQuery, ScallopUtils } from '../models';
12
12
  import type {
13
13
  MarketPool,
14
14
  Spools,
@@ -231,18 +231,22 @@ export const getSpool = async (
231
231
  * @return Stake accounts.
232
232
  */
233
233
  export const getStakeAccounts = async (
234
- query: ScallopQuery,
234
+ {
235
+ utils,
236
+ }: {
237
+ utils: ScallopUtils;
238
+ },
235
239
  ownerAddress?: string
236
240
  ) => {
237
- const owner = ownerAddress || query.suiKit.currentAddress();
238
- const spoolObjectId = query.address.get('spool.object');
241
+ const owner = ownerAddress || utils.suiKit.currentAddress();
242
+ const spoolObjectId = utils.address.get('spool.object');
239
243
  const stakeAccountType = `${spoolObjectId}::spool_account::SpoolAccount`;
240
244
  const stakeObjectsResponse: SuiObjectResponse[] = [];
241
245
  let hasNextPage = false;
242
246
  let nextCursor: string | null | undefined = null;
243
247
  do {
244
248
  const paginatedStakeObjectsResponse =
245
- await query.cache.queryGetOwnedObjects({
249
+ await utils.cache.queryGetOwnedObjects({
246
250
  owner,
247
251
  filter: { StructType: stakeAccountType },
248
252
  options: {
@@ -281,8 +285,8 @@ export const getStakeAccounts = async (
281
285
  Object.keys(stakeAccounts).reduce(
282
286
  (types, stakeMarketCoinName) => {
283
287
  const stakeCoinName =
284
- query.utils.parseCoinName<SupportStakeCoins>(stakeMarketCoinName);
285
- const marketCoinType = query.utils.parseMarketCoinType(stakeCoinName);
288
+ utils.parseCoinName<SupportStakeCoins>(stakeMarketCoinName);
289
+ const marketCoinType = utils.parseMarketCoinType(stakeCoinName);
286
290
 
287
291
  types[
288
292
  stakeMarketCoinName as SupportStakeMarketCoins
@@ -295,7 +299,7 @@ export const getStakeAccounts = async (
295
299
  const stakeObjectIds: string[] = stakeObjectsResponse
296
300
  .map((ref: any) => ref?.data?.objectId)
297
301
  .filter((id: any) => id !== undefined);
298
- const stakeObjects = await query.cache.queryGetObjects(stakeObjectIds);
302
+ const stakeObjects = await utils.cache.queryGetObjects(stakeObjectIds);
299
303
  for (const stakeObject of stakeObjects) {
300
304
  const id = stakeObject.objectId;
301
305
  const type = stakeObject.type!;
@@ -413,12 +417,16 @@ export const getStakeAccounts = async (
413
417
  * @return Stake pool data.
414
418
  */
415
419
  export const getStakePool = async (
416
- query: ScallopQuery,
420
+ {
421
+ utils,
422
+ }: {
423
+ utils: ScallopUtils;
424
+ },
417
425
  marketCoinName: SupportStakeMarketCoins
418
426
  ) => {
419
- const poolId = query.address.get(`spool.pools.${marketCoinName}.id`);
427
+ const poolId = utils.address.get(`spool.pools.${marketCoinName}.id`);
420
428
  let stakePool: StakePool | undefined = undefined;
421
- const stakePoolObjectResponse = await query.cache.queryGetObject(poolId, {
429
+ const stakePoolObjectResponse = await utils.cache.queryGetObject(poolId, {
422
430
  showContent: true,
423
431
  showType: true,
424
432
  });
@@ -469,14 +477,18 @@ export const getStakePool = async (
469
477
  * @return Stake reward pool.
470
478
  */
471
479
  export const getStakeRewardPool = async (
472
- query: ScallopQuery,
480
+ {
481
+ utils,
482
+ }: {
483
+ utils: ScallopUtils;
484
+ },
473
485
  marketCoinName: SupportStakeMarketCoins
474
486
  ) => {
475
- const poolId = query.address.get(
487
+ const poolId = utils.address.get(
476
488
  `spool.pools.${marketCoinName}.rewardPoolId`
477
489
  );
478
490
  let stakeRewardPool: StakeRewardPool | undefined = undefined;
479
- const stakeRewardPoolObjectResponse = await query.cache.queryGetObject(
491
+ const stakeRewardPoolObjectResponse = await utils.cache.queryGetObject(
480
492
  poolId,
481
493
  {
482
494
  showContent: true,
@@ -5,7 +5,7 @@ import {
5
5
  type SuiObjectData,
6
6
  DevInspectResults,
7
7
  } from '@mysten/sui.js/client';
8
- import type { ScallopQuery } from '../models';
8
+ import type { ScallopUtils } from '../models';
9
9
  import { MAX_LOCK_DURATION } from 'src/constants';
10
10
  import { SUI_CLOCK_OBJECT_ID, SuiTxBlock } from '@scallop-io/sui-kit';
11
11
  import { bcs } from '@mysten/sui.js/bcs';
@@ -18,17 +18,17 @@ import { z as zod } from 'zod';
18
18
  * @return Owned veSca key.
19
19
  */
20
20
  export const getVescaKeys = async (
21
- query: ScallopQuery,
21
+ utils: ScallopUtils,
22
22
  ownerAddress?: string
23
23
  ) => {
24
- const owner = ownerAddress || query.suiKit.currentAddress();
25
- const veScaObjId = query.address.get('vesca.object');
24
+ const owner = ownerAddress || utils.suiKit.currentAddress();
25
+ const veScaObjId = utils.address.get('vesca.object');
26
26
  const veScaKeyType = `${veScaObjId}::ve_sca::VeScaKey`;
27
27
  const keyObjectsResponse: SuiObjectResponse[] = [];
28
28
  let hasNextPage = false;
29
29
  let nextCursor: string | null | undefined = null;
30
30
  do {
31
- const paginatedKeyObjectsResponse = await query.cache.queryGetOwnedObjects({
31
+ const paginatedKeyObjectsResponse = await utils.cache.queryGetOwnedObjects({
32
32
  owner,
33
33
  filter: {
34
34
  StructType: veScaKeyType,
@@ -63,12 +63,19 @@ export const getVescaKeys = async (
63
63
  * @param ownerAddress - The owner address.
64
64
  * @return Owned veScas.
65
65
  */
66
- export const getVeScas = async (query: ScallopQuery, ownerAddress?: string) => {
67
- const keyObjectDatas = await getVescaKeys(query, ownerAddress);
66
+ export const getVeScas = async (
67
+ {
68
+ utils,
69
+ }: {
70
+ utils: ScallopUtils;
71
+ },
72
+ ownerAddress?: string
73
+ ) => {
74
+ const keyObjectDatas = await getVescaKeys(utils, ownerAddress);
68
75
 
69
76
  const veScas: Vesca[] = Array(keyObjectDatas.length).fill(null);
70
77
  const tasks = keyObjectDatas.map(async (veScaKey, idx) => {
71
- const veSca = await getVeSca(query, veScaKey);
78
+ const veSca = await getVeSca(utils, veScaKey);
72
79
  if (veSca) {
73
80
  veScas[idx] = veSca;
74
81
  }
@@ -96,12 +103,12 @@ type SuiObjectRefType = zod.infer<typeof SuiObjectRefZod>;
96
103
  * @returns Vesca data.
97
104
  */
98
105
  export const getVeSca = async (
99
- query: ScallopQuery,
106
+ utils: ScallopUtils,
100
107
  veScaKey?: string | SuiObjectData,
101
108
  ownerAddress?: string
102
109
  ) => {
103
- const tableId = query.address.get(`vesca.tableId`);
104
- veScaKey = veScaKey || (await getVescaKeys(query, ownerAddress))[0];
110
+ const tableId = utils.address.get(`vesca.tableId`);
111
+ veScaKey = veScaKey || (await getVescaKeys(utils, ownerAddress))[0];
105
112
 
106
113
  if (!veScaKey) return undefined;
107
114
  if (typeof veScaKey === 'object') {
@@ -111,7 +118,7 @@ export const getVeSca = async (
111
118
  let vesca: Vesca | undefined = undefined;
112
119
 
113
120
  const veScaDynamicFieldObjectResponse =
114
- await query.cache.queryGetDynamicFieldObject({
121
+ await utils.cache.queryGetDynamicFieldObject({
115
122
  parentId: tableId,
116
123
  name: {
117
124
  type: '0x2::object::ID',
@@ -162,12 +169,12 @@ export const getVeSca = async (
162
169
  * Get current total veSca treasury amount.
163
170
  */
164
171
  const getTotalVeScaTreasuryAmount = async (
165
- query: ScallopQuery,
172
+ utils: ScallopUtils,
166
173
  veScaTreasury: SuiObjectData
167
174
  ): Promise<string> => {
168
- const veScaPkgId = query.address.get('vesca.id');
169
- const veScaConfig = query.address.get('vesca.config');
170
- veScaTreasury = veScaTreasury ?? query.address.get('vesca.treasury');
175
+ const veScaPkgId = utils.address.get('vesca.id');
176
+ const veScaConfig = utils.address.get('vesca.config');
177
+ veScaTreasury = veScaTreasury ?? utils.address.get('vesca.treasury');
171
178
 
172
179
  // refresh query
173
180
  const refreshQueryTarget = `${veScaPkgId}::treasury::refresh`;
@@ -181,7 +188,7 @@ const getTotalVeScaTreasuryAmount = async (
181
188
  const resolvedRefreshArgs = await Promise.all(
182
189
  refreshArgs.map(async (arg) => {
183
190
  if (typeof arg === 'string') {
184
- return (await query.cache.queryGetObject(arg, { showContent: true }))
191
+ return (await utils.cache.queryGetObject(arg, { showContent: true }))
185
192
  ?.data;
186
193
  }
187
194
  return arg;
@@ -191,7 +198,7 @@ const getTotalVeScaTreasuryAmount = async (
191
198
  const resolvedVeScaAmountArgs = await Promise.all(
192
199
  veScaAmountArgs.map(async (arg) => {
193
200
  if (typeof arg === 'string') {
194
- return (await query.cache.queryGetObject(arg, { showContent: true }))
201
+ return (await utils.cache.queryGetObject(arg, { showContent: true }))
195
202
  ?.data;
196
203
  }
197
204
  return arg;
@@ -204,19 +211,18 @@ const getTotalVeScaTreasuryAmount = async (
204
211
  txb.moveCall(veScaAmountQueryTarget, resolvedVeScaAmountArgs);
205
212
 
206
213
  const txBytes = await txb.txBlock.build({
207
- client: query.suiKit.client(),
214
+ client: utils.suiKit.client(),
208
215
  onlyTransactionKind: true,
209
- protocolConfig: (await query.cache.getProtocolConfig()) ?? undefined,
210
216
  });
211
217
 
212
218
  // return result
213
- const res = await query.cache.queryClient.fetchQuery<DevInspectResults>({
219
+ const res = await utils.cache.queryClient.fetchQuery<DevInspectResults>({
214
220
  queryKey: [
215
221
  'getTotalVeScaTreasuryAmount',
216
222
  JSON.stringify([...refreshArgs, ...veScaAmountArgs]),
217
223
  ],
218
224
  queryFn: async () => {
219
- return await query.suiKit.inspectTxn(txBytes);
225
+ return await utils.suiKit.inspectTxn(txBytes);
220
226
  },
221
227
  });
222
228
 
@@ -236,10 +242,10 @@ const getTotalVeScaTreasuryAmount = async (
236
242
  * @returns VeScaTreasuryInfo
237
243
  */
238
244
  export const getVeScaTreasuryInfo = async (
239
- query: ScallopQuery
245
+ utils: ScallopUtils
240
246
  ): Promise<VeScaTreasuryInfo | null> => {
241
- const veScaTreasuryId = query.address.get('vesca.treasury');
242
- const veScaTreasury = await query.cache.queryGetObject(veScaTreasuryId, {
247
+ const veScaTreasuryId = utils.address.get('vesca.treasury');
248
+ const veScaTreasury = await utils.cache.queryGetObject(veScaTreasuryId, {
243
249
  showContent: true,
244
250
  });
245
251
 
@@ -255,7 +261,7 @@ export const getVeScaTreasuryInfo = async (
255
261
  .shiftedBy(-9)
256
262
  .toNumber();
257
263
  const totalVeSca = BigNumber(
258
- (await getTotalVeScaTreasuryAmount(query, veScaTreasury.data)) ?? 0
264
+ (await getTotalVeScaTreasuryAmount(utils, veScaTreasury.data)) ?? 0
259
265
  )
260
266
  .shiftedBy(-9)
261
267
  .toNumber();
@@ -32,6 +32,10 @@ export type VeScaNormalMethods = {
32
32
  mintEmptyVeSca: () => TransactionResult;
33
33
  };
34
34
 
35
+ export type RedeemScaQuickReturnType<T extends boolean> = T extends true
36
+ ? void
37
+ : TransactionResult | undefined;
38
+
35
39
  export type VeScaQuickMethods = {
36
40
  /**
37
41
  * Quick methods to automate
@@ -70,7 +74,10 @@ export type VeScaQuickMethods = {
70
74
  veScaKey?: SuiObjectArg,
71
75
  autoCheck?: boolean
72
76
  ) => Promise<void>;
73
- redeemScaQuick: (veScaKey?: SuiObjectArg) => Promise<void>;
77
+ redeemScaQuick: <T extends boolean>(
78
+ veSCaKey?: SuiObjectArg,
79
+ transferSca?: T
80
+ ) => Promise<RedeemScaQuickReturnType<T>>;
74
81
  };
75
82
 
76
83
  export type SuiTxBlockWithVeScaNormalMethods = SuiKitTxBlock &