@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/dist/index.d.mts +10 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +30 -30
- package/dist/index.mjs +4 -4
- package/package.json +1 -1
- package/src/builders/coreBuilder.ts +68 -0
- package/src/models/scallopSuiKit.ts +13 -8
- package/src/queries/borrowIncentiveQuery.ts +35 -2
- package/src/queries/coreQuery.ts +42 -6
- package/src/queries/sCoinQuery.ts +17 -1
- package/src/queries/vescaQuery.ts +23 -2
- package/src/types/builder/core.ts +18 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/object.ts +40 -0
package/package.json
CHANGED
|
@@ -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
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
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 = [
|
|
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 = [
|
|
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;
|
package/src/queries/coreQuery.ts
CHANGED
|
@@ -12,7 +12,7 @@ import type {
|
|
|
12
12
|
SuiObjectData,
|
|
13
13
|
SuiParsedData,
|
|
14
14
|
} from '@mysten/sui/client';
|
|
15
|
-
import type
|
|
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 = [
|
|
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
|
-
|
|
946
|
-
|
|
947
|
-
|
|
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
|
-
{
|
|
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
|
|
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 = [
|
|
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 = [
|
|
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 &
|
package/src/utils/index.ts
CHANGED
|
@@ -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
|
+
};
|