@scallop-io/sui-scallop-sdk 2.3.7 → 2.3.9

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scallop-io/sui-scallop-sdk",
3
- "version": "2.3.7",
3
+ "version": "2.3.9",
4
4
  "description": "Typescript sdk for interacting with Scallop contract on SUI",
5
5
  "keywords": [
6
6
  "sui",
@@ -267,6 +267,27 @@ const generateCoreNormalMethod: GenerateCoreNormalMethod = ({
267
267
  [coinType]
268
268
  );
269
269
  },
270
+ liquidate: (obligation, coin, debtCoinName, collateralCoinName) => {
271
+ const debtCoinType = builder.utils.parseCoinType(debtCoinName);
272
+ const collateralCoinType =
273
+ builder.utils.parseCoinType(collateralCoinName);
274
+ const [debtCoin, collateralCoin] = builder.moveCall(
275
+ txBlock,
276
+ `${coreIds.protocolPkg}::liquidate::liquidate`,
277
+ [
278
+ coreIds.version,
279
+ obligation,
280
+ coreIds.market,
281
+ coin,
282
+ coreIds.coinDecimalsRegistry,
283
+ coreIds.xOracle,
284
+ clockObjectRef,
285
+ ],
286
+ [debtCoinType, collateralCoinType]
287
+ );
288
+
289
+ return [debtCoin, collateralCoin] as [NestedResult, NestedResult];
290
+ },
270
291
  };
271
292
  };
272
293
 
@@ -489,6 +510,53 @@ const generateCoreQuickMethod: GenerateCoreQuickMethod = ({
489
510
  updateOracleOptions
490
511
  );
491
512
  },
513
+ liquidateQuick: async (
514
+ amount,
515
+ debtCoinName,
516
+ collateralCoinName,
517
+ obligationId,
518
+ updateOracleOptions
519
+ ) => {
520
+ const sender = requireSender(txBlock);
521
+
522
+ // Update oracle prices for debt and collateral coins
523
+ const updateCoinNames =
524
+ await builder.utils.getObligationCoinNames(obligationId);
525
+
526
+ await updateOracles(
527
+ builder,
528
+ txBlock,
529
+ updateCoinNames,
530
+ updateOracleOptions
531
+ );
532
+
533
+ // Select coins for liquidation
534
+ const { takeCoin, leftCoin } = await builder.selectCoin(
535
+ txBlock,
536
+ debtCoinName,
537
+ amount,
538
+ sender,
539
+ updateOracleOptions?.isSponsoredTx ?? false
540
+ );
541
+
542
+ if (leftCoin) {
543
+ txBlock.transferObjects([leftCoin], sender);
544
+ }
545
+
546
+ // Convert obligation to SharedObjectRef format
547
+ const obligationSharedObject =
548
+ typeof obligationId === 'string'
549
+ ? txBlock.object(obligationId)
550
+ : obligationId;
551
+
552
+ // Execute liquidation
553
+ return txBlock.liquidate(
554
+ obligationSharedObject,
555
+ takeCoin,
556
+ debtCoinName,
557
+ collateralCoinName
558
+ );
559
+ },
492
560
  };
493
561
  };
494
562
 
@@ -32,6 +32,8 @@ type QueryInspectTxnParams = {
32
32
  queryTarget: string;
33
33
  args: SuiObjectArg[];
34
34
  typeArgs?: any[];
35
+ txBlock?: SuiTxBlock;
36
+ keys?: QueryKey;
35
37
  };
36
38
 
37
39
  export type ScallopSuiKitParams = {
@@ -352,9 +354,9 @@ class ScallopSuiKit extends ScallopQueryClient {
352
354
  queryTarget,
353
355
  args,
354
356
  typeArgs,
357
+ txBlock = new SuiTxBlock(),
358
+ keys,
355
359
  }: QueryInspectTxnParams): Promise<DevInspectResults | null> {
356
- const txBlock = new SuiTxBlock();
357
-
358
360
  const resolvedQueryTarget =
359
361
  await this.queryGetNormalizedMoveFunction(queryTarget);
360
362
  if (!resolvedQueryTarget) throw new Error('Invalid query target');
@@ -372,12 +374,15 @@ class ScallopSuiKit extends ScallopQueryClient {
372
374
  txBlock.moveCall(queryTarget, resolvedArgs, typeArgs);
373
375
 
374
376
  return await this.callWithRateLimiter(
375
- queryKeys.rpc.getInspectTxn({
376
- queryTarget,
377
- args,
378
- typeArgs,
379
- node: this.currentFullNode,
380
- }),
377
+ keys ??
378
+ queryKeys.rpc.getInspectTxn({
379
+ queryTarget,
380
+ args: args.map((arg) =>
381
+ typeof arg === 'object' && 'objectId' in arg ? arg.objectId : arg
382
+ ),
383
+ typeArgs,
384
+ node: this.currentFullNode,
385
+ }),
381
386
  () => this.suiKit.inspectTxn(txBlock)
382
387
  );
383
388
  }
@@ -3,6 +3,7 @@ import {
3
3
  parseOriginBorrowIncentivePoolData,
4
4
  parseOriginBorrowIncentiveAccountData,
5
5
  calculateBorrowIncentivePoolPointData,
6
+ getSharedObjectData,
6
7
  } from 'src/utils';
7
8
  import type {
8
9
  ScallopAddress,
@@ -22,6 +23,8 @@ import type {
22
23
  } from 'src/types';
23
24
  import BigNumber from 'bignumber.js';
24
25
  import { SuiObjectRef } from '@mysten/sui/client';
26
+ import { SuiTxBlock } from '@scallop-io/sui-kit';
27
+ import { queryKeys } from 'src/constants';
25
28
 
26
29
  /**
27
30
  * Query borrow incentive pools data using moveCall
@@ -38,11 +41,24 @@ export const queryBorrowIncentivePools = async ({
38
41
  const queryPkgId = address.get('borrowIncentive.query');
39
42
  const incentivePoolsId = address.get('borrowIncentive.incentivePools');
40
43
 
44
+ const txBlock = new SuiTxBlock();
41
45
  const queryTarget = `${queryPkgId}::incentive_pools_query::incentive_pools_data`;
42
- const args = [incentivePoolsId];
46
+ const args = [
47
+ txBlock.sharedObjectRef({
48
+ objectId: incentivePoolsId,
49
+ initialSharedVersion: '81234462',
50
+ mutable: true,
51
+ }),
52
+ ];
43
53
  const queryResult = await scallopSuiKit.queryInspectTxn({
44
54
  queryTarget,
45
55
  args,
56
+ txBlock,
57
+ keys: queryKeys.rpc.getInspectTxn({
58
+ queryTarget,
59
+ args: [incentivePoolsId],
60
+ node: scallopSuiKit.currentFullNode,
61
+ }),
46
62
  });
47
63
  const borrowIncentivePoolsQueryData = queryResult?.events[0].parsedJson as
48
64
  | BorrowIncentivePoolsQueryInterface
@@ -165,16 +181,33 @@ export const queryBorrowIncentiveAccounts = async (
165
181
  obligationId: string | SuiObjectRef,
166
182
  borrowIncentiveCoinNames: string[] = [...utils.constants.whitelist.lending]
167
183
  ) => {
184
+ const txBlock = new SuiTxBlock();
168
185
  const queryPkgId = utils.address.get('borrowIncentive.query');
169
186
  const incentiveAccountsId = utils.address.get(
170
187
  'borrowIncentive.incentiveAccounts'
171
188
  );
172
189
  const queryTarget = `${queryPkgId}::incentive_account_query::incentive_account_data`;
173
- const args = [incentiveAccountsId, obligationId];
190
+ const args = [
191
+ txBlock.sharedObjectRef({
192
+ objectId: incentiveAccountsId,
193
+ initialSharedVersion: '81234462',
194
+ mutable: true,
195
+ }),
196
+ txBlock.sharedObjectRef({
197
+ ...(await getSharedObjectData(obligationId, utils.scallopSuiKit.client)),
198
+ mutable: true,
199
+ }),
200
+ ];
174
201
 
175
202
  const queryResult = await utils.scallopSuiKit.queryInspectTxn({
176
203
  queryTarget,
177
204
  args,
205
+ txBlock,
206
+ keys: queryKeys.rpc.getInspectTxn({
207
+ queryTarget,
208
+ args: [incentiveAccountsId, obligationId],
209
+ node: utils.scallopSuiKit.currentFullNode,
210
+ }),
178
211
  });
179
212
  const borrowIncentiveAccountsQueryData = queryResult?.events[0]
180
213
  ?.parsedJson as BorrowIncentiveAccountsQueryInterface | undefined;
@@ -12,7 +12,7 @@ import type {
12
12
  SuiObjectData,
13
13
  SuiParsedData,
14
14
  } from '@mysten/sui/client';
15
- import type { SuiObjectArg } from '@scallop-io/sui-kit';
15
+ import { SuiTxBlock, type SuiObjectArg } from '@scallop-io/sui-kit';
16
16
  // import type { ScallopAddress, ScallopCache, ScallopQuery } from '../models';
17
17
  import {
18
18
  Market,
@@ -46,6 +46,8 @@ import {
46
46
  ScallopIndexer,
47
47
  ScallopAddress,
48
48
  } from 'src/models';
49
+ import { getSharedObjectData } from 'src/utils/object';
50
+ import { queryKeys } from 'src/constants';
49
51
 
50
52
  /**
51
53
  * Query market data.
@@ -103,14 +105,27 @@ export const queryMarket = async (
103
105
  };
104
106
  }
105
107
 
108
+ const txBlock = new SuiTxBlock();
106
109
  const packageId = utils.address.get('core.packages.query.id');
107
110
  const marketId = utils.address.get('core.market');
108
111
  const queryTarget = `${packageId}::market_query::market_data`;
109
- const args = [marketId];
112
+ const args = [
113
+ txBlock.sharedObjectRef({
114
+ objectId: marketId,
115
+ initialSharedVersion: '7765848',
116
+ mutable: true,
117
+ }),
118
+ ];
110
119
 
111
120
  const queryResult = await utils.scallopSuiKit.queryInspectTxn({
112
121
  queryTarget,
113
122
  args,
123
+ txBlock,
124
+ keys: queryKeys.rpc.getInspectTxn({
125
+ queryTarget,
126
+ args: [marketId],
127
+ node: utils.scallopSuiKit.currentFullNode,
128
+ }),
114
129
  });
115
130
  const marketData = queryResult?.events[0]?.parsedJson as
116
131
  | MarketQueryInterface
@@ -936,15 +951,27 @@ export const queryObligation = async (
936
951
  },
937
952
  obligationId: SuiObjectArg
938
953
  ) => {
954
+ const txBlock = new SuiTxBlock();
939
955
  const packageId = address.get('core.packages.query.id');
940
956
  const version = address.get('core.version');
941
957
  const market = address.get('core.market');
942
958
  const queryTarget = `${packageId}::obligation_query::obligation_data`;
943
959
 
944
960
  const args = [
945
- version,
946
- market,
947
- obligationId,
961
+ txBlock.sharedObjectRef({
962
+ objectId: version,
963
+ initialSharedVersion: '7765848',
964
+ mutable: false,
965
+ }),
966
+ txBlock.sharedObjectRef({
967
+ objectId: market,
968
+ initialSharedVersion: '7765848',
969
+ mutable: true,
970
+ }),
971
+ txBlock.sharedObjectRef({
972
+ ...(await getSharedObjectData(obligationId, scallopSuiKit.client)),
973
+ mutable: true,
974
+ }),
948
975
  {
949
976
  objectId: SUI_CLOCK_OBJECT_ID,
950
977
  mutable: false,
@@ -953,7 +980,16 @@ export const queryObligation = async (
953
980
  ];
954
981
 
955
982
  const queryResult = await scallopSuiKit.queryInspectTxn(
956
- { queryTarget, args }
983
+ {
984
+ queryTarget,
985
+ args,
986
+ txBlock,
987
+ keys: queryKeys.rpc.getInspectTxn({
988
+ queryTarget,
989
+ args: [version, market, obligationId],
990
+ node: scallopSuiKit.currentFullNode,
991
+ }),
992
+ }
957
993
  // txBlock
958
994
  );
959
995
  return queryResult?.events[0]?.parsedJson as
@@ -1,8 +1,11 @@
1
1
  import { bcs } from '@mysten/sui/bcs';
2
+ import { SuiTxBlock } from '@scallop-io/sui-kit';
2
3
  import assert from 'assert';
3
4
  import BigNumber from 'bignumber.js';
5
+ import { queryKeys } from 'src/constants';
4
6
  import { ScallopQuery, ScallopUtils } from 'src/models';
5
7
  import { OptionalKeys, sCoinBalance } from 'src/types';
8
+ import { getSharedObjectData } from 'src/utils';
6
9
 
7
10
  /**
8
11
  * Get total supply of sCoin
@@ -18,9 +21,16 @@ export const getSCoinTotalSupply = async (
18
21
  },
19
22
  sCoinName: string
20
23
  ): Promise<sCoinBalance> => {
24
+ const txBlock = new SuiTxBlock();
21
25
  const sCoinPkgId = utils.address.get('scoin.id');
22
26
  // get treasury
23
- const args = [utils.getSCoinTreasury(sCoinName)];
27
+ const treasury = utils.getSCoinTreasury(sCoinName);
28
+ const args = [
29
+ txBlock.sharedObjectRef({
30
+ ...(await getSharedObjectData(treasury, utils.scallopSuiKit.client)),
31
+ mutable: false,
32
+ }),
33
+ ];
24
34
  const typeArgs = [
25
35
  utils.parseSCoinType(sCoinName),
26
36
  utils.parseUnderlyingSCoinType(sCoinName),
@@ -30,6 +40,12 @@ export const getSCoinTotalSupply = async (
30
40
  queryTarget,
31
41
  args,
32
42
  typeArgs,
43
+ txBlock,
44
+ keys: queryKeys.rpc.getInspectTxn({
45
+ queryTarget,
46
+ args: [treasury],
47
+ node: utils.scallopSuiKit.currentFullNode,
48
+ }),
33
49
  });
34
50
  const results = queryResults?.results;
35
51
  if (results && results[0]?.returnValues) {
@@ -191,13 +191,34 @@ const getTotalVeScaTreasuryAmount = async (
191
191
  initialSharedVersion: '1',
192
192
  });
193
193
 
194
+ const treasuryRef =
195
+ typeof veScaTreasury === 'string'
196
+ ? txb.sharedObjectRef({
197
+ objectId: veScaTreasury,
198
+ initialSharedVersion: '75353922',
199
+ mutable: true,
200
+ })
201
+ : txb.sharedObjectRef({
202
+ objectId: veScaTreasury.objectId,
203
+ initialSharedVersion: '75353922',
204
+ mutable: true,
205
+ });
206
+
194
207
  // refresh query
195
208
  const refreshQueryTarget = `${veScaPkgId}::treasury::refresh`;
196
- const refreshArgs = [veScaConfig, veScaTreasury, clockObjectRef];
209
+ const refreshArgs = [
210
+ txb.sharedObjectRef({
211
+ objectId: veScaConfig,
212
+ initialSharedVersion: '75353922',
213
+ mutable: false,
214
+ }),
215
+ treasuryRef,
216
+ clockObjectRef,
217
+ ];
197
218
 
198
219
  // query total veSca amount
199
220
  const veScaAmountQueryTarget = `${veScaPkgId}::treasury::total_ve_sca_amount`;
200
- const vescaAmountArgs = [veScaTreasury, clockObjectRef];
221
+ const vescaAmountArgs = [treasuryRef, clockObjectRef];
201
222
 
202
223
  // resolve each args
203
224
  const resolvedRefreshArgs = await Promise.all(
@@ -81,6 +81,12 @@ export type CoreNormalMethods = {
81
81
  loan: SuiObjectArg,
82
82
  poolCoinName: string
83
83
  ) => void;
84
+ liquidate: (
85
+ obligation: SuiObjectArg,
86
+ coin: SuiObjectArg,
87
+ debtCoinName: string,
88
+ collateralCoinName: string
89
+ ) => [NestedResult, NestedResult];
84
90
  };
85
91
 
86
92
  export type CoreQuickMethods = {
@@ -152,6 +158,18 @@ export type CoreQuickMethods = {
152
158
  isSponsoredTx?: boolean;
153
159
  }
154
160
  ) => Promise<void>;
161
+ liquidateQuick: (
162
+ amount: number,
163
+ debtCoinName: string,
164
+ collateralCoinName: string,
165
+ obligationId: SuiObjectArg,
166
+ updateOracleOptions?: {
167
+ usePythPullModel?: boolean;
168
+ useOnChainXOracleList?: boolean;
169
+ sponsoredFeeds?: string[];
170
+ isSponsoredTx?: boolean;
171
+ }
172
+ ) => Promise<[NestedResult, NestedResult]>;
155
173
  };
156
174
 
157
175
  export type SuiTxBlockWithCoreNormalMethods = SuiKitTxBlock &
@@ -3,3 +3,4 @@ export * from './query';
3
3
  export * from './util';
4
4
  export * from './indexer';
5
5
  export * from './core';
6
+ export * from './object';
@@ -0,0 +1,40 @@
1
+ import { getFullnodeUrl, SuiClient, SuiObjectData } from '@mysten/sui/client';
2
+
3
+ const parseObjectData = (data: SuiObjectData) => {
4
+ if (
5
+ typeof data === 'object' &&
6
+ 'objectId' in data &&
7
+ 'owner' in data &&
8
+ data.owner &&
9
+ typeof data.owner === 'object' &&
10
+ 'Shared' in data.owner &&
11
+ 'initial_shared_version' in data.owner.Shared
12
+ ) {
13
+ return {
14
+ objectId: data.objectId,
15
+ initialSharedVersion: data.owner.Shared.initial_shared_version.toString(),
16
+ };
17
+ }
18
+
19
+ throw new Error('Invalid shared object data');
20
+ };
21
+
22
+ export const getSharedObjectData = async (
23
+ object: any,
24
+ client: SuiClient = new SuiClient({
25
+ url: getFullnodeUrl('mainnet'),
26
+ })
27
+ ) => {
28
+ if (typeof object === 'string') {
29
+ const objectData = await client.getObject({
30
+ id: object,
31
+ options: {
32
+ showOwner: true,
33
+ showContent: false,
34
+ },
35
+ });
36
+ return parseObjectData(objectData.data!);
37
+ } else {
38
+ return parseObjectData(object);
39
+ }
40
+ };