@scallop-io/sui-scallop-sdk 0.46.39 → 0.46.41
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/builders/loyaltyProgramBuilder.d.ts +1 -1
- package/dist/builders/sCoinBuilder.d.ts +4 -0
- package/dist/constants/common.d.ts +3 -1
- package/dist/constants/enum.d.ts +12 -10
- package/dist/constants/flashloan.d.ts +2 -0
- package/dist/constants/index.d.ts +1 -0
- package/dist/index.js +742 -97
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +739 -92
- package/dist/index.mjs.map +1 -1
- package/dist/models/scallopBuilder.d.ts +16 -1
- package/dist/models/scallopClient.d.ts +5 -0
- package/dist/models/scallopQuery.d.ts +24 -1
- package/dist/models/scallopUtils.d.ts +32 -2
- package/dist/queries/coreQuery.d.ts +7 -0
- package/dist/queries/portfolioQuery.d.ts +1 -1
- package/dist/queries/sCoinQuery.d.ts +27 -0
- package/dist/test.d.ts +1 -0
- package/dist/types/address.d.ts +8 -1
- package/dist/types/builder/core.d.ts +12 -4
- package/dist/types/builder/index.d.ts +6 -1
- package/dist/types/builder/sCoin.d.ts +37 -0
- package/dist/types/builder/spool.d.ts +2 -1
- package/dist/types/constant/common.d.ts +3 -2
- package/dist/types/constant/enum.d.ts +13 -1
- package/dist/types/query/core.d.ts +2 -1
- package/dist/types/query/index.d.ts +1 -0
- package/dist/types/query/portfolio.d.ts +1 -0
- package/dist/types/query/sCoin.d.ts +1 -0
- package/package.json +3 -3
- package/src/builders/coreBuilder.ts +72 -17
- package/src/builders/index.ts +5 -1
- package/src/builders/loyaltyProgramBuilder.ts +1 -1
- package/src/builders/referralBuilder.ts +1 -1
- package/src/builders/sCoinBuilder.ts +119 -0
- package/src/builders/spoolBuilder.ts +1 -1
- package/src/builders/vescaBuilder.ts +3 -3
- package/src/constants/common.ts +19 -5
- package/src/constants/enum.ts +98 -20
- package/src/constants/flashloan.ts +18 -0
- package/src/constants/index.ts +1 -0
- package/src/constants/testAddress.ts +115 -21
- package/src/models/scallopAddress.ts +44 -3
- package/src/models/scallopBuilder.ts +43 -7
- package/src/models/scallopCache.ts +32 -4
- package/src/models/scallopClient.ts +121 -0
- package/src/models/scallopQuery.ts +57 -1
- package/src/models/scallopUtils.ts +56 -2
- package/src/queries/coreQuery.ts +102 -4
- package/src/queries/portfolioQuery.ts +25 -3
- package/src/queries/sCoinQuery.ts +94 -0
- package/src/queries/vescaQuery.ts +0 -1
- package/src/test.ts +19 -0
- package/src/types/address.ts +13 -0
- package/src/types/builder/core.ts +19 -4
- package/src/types/builder/index.ts +11 -3
- package/src/types/builder/sCoin.ts +61 -0
- package/src/types/builder/spool.ts +2 -0
- package/src/types/constant/common.ts +4 -1
- package/src/types/constant/enum.ts +17 -0
- package/src/types/query/core.ts +3 -0
- package/src/types/query/index.ts +1 -0
- package/src/types/query/portfolio.ts +1 -0
- package/src/types/query/sCoin.ts +1 -0
- package/src/utils/builder.ts +1 -1
- package/src/utils/util.ts +13 -17
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { API_BASE_URL,
|
|
1
|
+
import { API_BASE_URL, USE_TEST_ADDRESS } from '../constants';
|
|
2
2
|
import type { NetworkType } from '@scallop-io/sui-kit';
|
|
3
3
|
import type {
|
|
4
4
|
ScallopAddressParams,
|
|
@@ -309,6 +309,47 @@ const EMPTY_ADDRESSES: AddressesInterface = {
|
|
|
309
309
|
rewardPool: '',
|
|
310
310
|
userRewardTableId: '',
|
|
311
311
|
},
|
|
312
|
+
scoin: {
|
|
313
|
+
id: '',
|
|
314
|
+
coins: {
|
|
315
|
+
ssui: {
|
|
316
|
+
coinType: '',
|
|
317
|
+
treasury: '',
|
|
318
|
+
},
|
|
319
|
+
scetus: {
|
|
320
|
+
coinType: '',
|
|
321
|
+
treasury: '',
|
|
322
|
+
},
|
|
323
|
+
ssca: {
|
|
324
|
+
coinType: '',
|
|
325
|
+
treasury: '',
|
|
326
|
+
},
|
|
327
|
+
susdc: {
|
|
328
|
+
coinType: '',
|
|
329
|
+
treasury: '',
|
|
330
|
+
},
|
|
331
|
+
susdt: {
|
|
332
|
+
coinType: '',
|
|
333
|
+
treasury: '',
|
|
334
|
+
},
|
|
335
|
+
seth: {
|
|
336
|
+
coinType: '',
|
|
337
|
+
treasury: '',
|
|
338
|
+
},
|
|
339
|
+
safsui: {
|
|
340
|
+
coinType: '',
|
|
341
|
+
treasury: '',
|
|
342
|
+
},
|
|
343
|
+
shasui: {
|
|
344
|
+
coinType: '',
|
|
345
|
+
treasury: '',
|
|
346
|
+
},
|
|
347
|
+
svsui: {
|
|
348
|
+
coinType: '',
|
|
349
|
+
treasury: '',
|
|
350
|
+
},
|
|
351
|
+
},
|
|
352
|
+
},
|
|
312
353
|
};
|
|
313
354
|
/**
|
|
314
355
|
* @description
|
|
@@ -345,10 +386,10 @@ export class ScallopAddress {
|
|
|
345
386
|
if (auth) this._auth = auth;
|
|
346
387
|
this._id = id;
|
|
347
388
|
this._network = network || 'mainnet';
|
|
348
|
-
this._addressesMap =
|
|
389
|
+
this._addressesMap = USE_TEST_ADDRESS
|
|
349
390
|
? new Map([['mainnet', TEST_ADDRESSES]])
|
|
350
391
|
: new Map();
|
|
351
|
-
if (
|
|
392
|
+
if (USE_TEST_ADDRESS) this._currentAddresses = TEST_ADDRESSES;
|
|
352
393
|
}
|
|
353
394
|
|
|
354
395
|
/**
|
|
@@ -14,6 +14,7 @@ import type {
|
|
|
14
14
|
ScallopTxBlock,
|
|
15
15
|
SupportMarketCoins,
|
|
16
16
|
SupportAssetCoins,
|
|
17
|
+
SupportSCoin,
|
|
17
18
|
} from '../types';
|
|
18
19
|
import { ScallopCache } from './scallopCache';
|
|
19
20
|
import { DEFAULT_CACHE_OPTIONS } from 'src/constants/cache';
|
|
@@ -124,7 +125,7 @@ export class ScallopBuilder {
|
|
|
124
125
|
sender: string
|
|
125
126
|
) {
|
|
126
127
|
const coinType = this.utils.parseCoinType(assetCoinName);
|
|
127
|
-
const coins = await this.utils.
|
|
128
|
+
const coins = await this.utils.selectCoins(amount, coinType, sender);
|
|
128
129
|
const [takeCoin, leftCoin] = txBlock.takeAmountFromCoins(coins, amount);
|
|
129
130
|
return { takeCoin, leftCoin };
|
|
130
131
|
}
|
|
@@ -145,13 +146,48 @@ export class ScallopBuilder {
|
|
|
145
146
|
sender: string
|
|
146
147
|
) {
|
|
147
148
|
const marketCoinType = this.utils.parseMarketCoinType(marketCoinName);
|
|
148
|
-
const coins = await this.utils.
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
149
|
+
const coins = await this.utils.selectCoins(amount, marketCoinType, sender);
|
|
150
|
+
const totalAmount = coins.reduce((prev, coin) => {
|
|
151
|
+
prev += Number(coin.balance);
|
|
152
|
+
return prev;
|
|
153
|
+
}, 0);
|
|
154
|
+
const [takeCoin, leftCoin] = txBlock.takeAmountFromCoins(
|
|
155
|
+
coins,
|
|
156
|
+
Math.min(amount, totalAmount)
|
|
152
157
|
);
|
|
153
|
-
|
|
154
|
-
|
|
158
|
+
return { takeCoin, leftCoin, totalAmount };
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Specifying the sender's amount of sCoins to get coins args from transaction result.
|
|
163
|
+
*
|
|
164
|
+
* @param txBlock - Scallop txBlock or txBlock created by SuiKit .
|
|
165
|
+
* @param marketCoinName - Specific support sCoin name.
|
|
166
|
+
* @param amount - Amount of coins to be selected.
|
|
167
|
+
* @param sender - Sender address.
|
|
168
|
+
* @return Take coin and left coin.
|
|
169
|
+
*/
|
|
170
|
+
public async selectSCoin(
|
|
171
|
+
txBlock: ScallopTxBlock | SuiKitTxBlock,
|
|
172
|
+
sCoinName: SupportSCoin,
|
|
173
|
+
amount: number,
|
|
174
|
+
sender: string
|
|
175
|
+
) {
|
|
176
|
+
const sCoinType = this.utils.parseSCoinType(sCoinName);
|
|
177
|
+
const coins = await this.utils.selectCoins(amount, sCoinType, sender);
|
|
178
|
+
const totalAmount = coins.reduce((prev, coin) => {
|
|
179
|
+
prev += Number(coin.balance);
|
|
180
|
+
return prev;
|
|
181
|
+
}, 0);
|
|
182
|
+
const [takeCoin, leftCoin] = txBlock.takeAmountFromCoins(
|
|
183
|
+
coins,
|
|
184
|
+
Math.min(totalAmount, amount)
|
|
185
|
+
);
|
|
186
|
+
return {
|
|
187
|
+
takeCoin,
|
|
188
|
+
leftCoin,
|
|
189
|
+
totalAmount,
|
|
190
|
+
};
|
|
155
191
|
}
|
|
156
192
|
|
|
157
193
|
/**
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { QueryClient, QueryClientConfig } from '@tanstack/query-core';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
SuiTxArg,
|
|
4
|
+
SuiTxBlock,
|
|
5
|
+
normalizeStructTag,
|
|
6
|
+
normalizeSuiAddress,
|
|
7
|
+
} from '@scallop-io/sui-kit';
|
|
3
8
|
import { SuiKit } from '@scallop-io/sui-kit';
|
|
4
9
|
import type {
|
|
5
10
|
SuiObjectResponse,
|
|
@@ -162,6 +167,7 @@ export class ScallopCache {
|
|
|
162
167
|
objectIds: string[],
|
|
163
168
|
options?: SuiObjectDataOptions
|
|
164
169
|
): Promise<SuiObjectData[]> {
|
|
170
|
+
if (objectIds.length === 0) return [];
|
|
165
171
|
const queryKey = [
|
|
166
172
|
'getObjects',
|
|
167
173
|
JSON.stringify(objectIds),
|
|
@@ -171,7 +177,7 @@ export class ScallopCache {
|
|
|
171
177
|
queryKey.push(JSON.stringify(options));
|
|
172
178
|
}
|
|
173
179
|
return this.queryClient.fetchQuery({
|
|
174
|
-
queryKey,
|
|
180
|
+
queryKey: queryKey,
|
|
175
181
|
queryFn: async () => {
|
|
176
182
|
return await this.suiKit.getObjects(objectIds, options);
|
|
177
183
|
},
|
|
@@ -254,7 +260,7 @@ export class ScallopCache {
|
|
|
254
260
|
const allBalances = await this.suiKit
|
|
255
261
|
.client()
|
|
256
262
|
.getAllBalances({ owner });
|
|
257
|
-
|
|
263
|
+
const balances = allBalances.reduce(
|
|
258
264
|
(acc, coinBalance) => {
|
|
259
265
|
if (coinBalance.totalBalance !== '0') {
|
|
260
266
|
acc[normalizeStructTag(coinBalance.coinType)] =
|
|
@@ -264,12 +270,34 @@ export class ScallopCache {
|
|
|
264
270
|
},
|
|
265
271
|
{} as { [k: string]: string }
|
|
266
272
|
);
|
|
273
|
+
|
|
274
|
+
// Set query data for each coin balance
|
|
275
|
+
for (const coinType in balances) {
|
|
276
|
+
const coinBalanceQueryKey = [
|
|
277
|
+
'getCoinBalance',
|
|
278
|
+
normalizeSuiAddress(owner),
|
|
279
|
+
normalizeStructTag(coinType),
|
|
280
|
+
];
|
|
281
|
+
this.queryClient.setQueryData(
|
|
282
|
+
coinBalanceQueryKey,
|
|
283
|
+
balances[coinType]
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
return balances;
|
|
267
288
|
},
|
|
289
|
+
staleTime: 5000,
|
|
268
290
|
});
|
|
269
291
|
}
|
|
270
292
|
|
|
271
293
|
public async queryGetCoinBalance(input: GetBalanceParams): Promise<string> {
|
|
272
|
-
|
|
294
|
+
if (!input.coinType) return '0';
|
|
295
|
+
|
|
296
|
+
const queryKey = [
|
|
297
|
+
'getCoinBalance',
|
|
298
|
+
normalizeSuiAddress(input.owner),
|
|
299
|
+
normalizeStructTag(input.coinType),
|
|
300
|
+
];
|
|
273
301
|
return this.queryClient.fetchQuery({
|
|
274
302
|
queryKey,
|
|
275
303
|
queryFn: async () => {
|
|
@@ -4,6 +4,8 @@ import {
|
|
|
4
4
|
ADDRESSES_ID,
|
|
5
5
|
SUPPORT_BORROW_INCENTIVE_POOLS,
|
|
6
6
|
SUPPORT_BORROW_INCENTIVE_REWARDS,
|
|
7
|
+
SUPPORT_SCOIN,
|
|
8
|
+
SUPPORT_SPOOLS,
|
|
7
9
|
} from '../constants';
|
|
8
10
|
import { ScallopAddress } from './scallopAddress';
|
|
9
11
|
import { ScallopUtils } from './scallopUtils';
|
|
@@ -23,6 +25,7 @@ import type {
|
|
|
23
25
|
SupportStakeMarketCoins,
|
|
24
26
|
SupportBorrowIncentiveCoins,
|
|
25
27
|
ScallopTxBlock,
|
|
28
|
+
SupportSCoin,
|
|
26
29
|
} from '../types';
|
|
27
30
|
import { ScallopCache } from './scallopCache';
|
|
28
31
|
import { DEFAULT_CACHE_OPTIONS } from 'src/constants/cache';
|
|
@@ -959,6 +962,124 @@ export class ScallopClient {
|
|
|
959
962
|
}
|
|
960
963
|
}
|
|
961
964
|
|
|
965
|
+
/* ==================== Migrate market coin to sCoin method ==================== */
|
|
966
|
+
/**
|
|
967
|
+
* Function to migrate all market coin in user wallet into sCoin
|
|
968
|
+
* @returns Transaction response
|
|
969
|
+
*/
|
|
970
|
+
public async migrateAllMarketCoin<S extends boolean>(
|
|
971
|
+
sign: S = true as S
|
|
972
|
+
): Promise<ScallopClientFnReturnType<S>> {
|
|
973
|
+
const txBlock = this.builder.createTxBlock();
|
|
974
|
+
txBlock.setSender(this.walletAddress);
|
|
975
|
+
|
|
976
|
+
const toTransfer: SuiObjectArg[] = [];
|
|
977
|
+
await Promise.all(
|
|
978
|
+
SUPPORT_SCOIN.map(async (sCoinName) => {
|
|
979
|
+
/**
|
|
980
|
+
* First check marketCoin inside mini wallet
|
|
981
|
+
* Then check stakedMarketCoin inside spool
|
|
982
|
+
*/
|
|
983
|
+
let toDestroyMarketCoin: SuiObjectArg | undefined;
|
|
984
|
+
|
|
985
|
+
// check market coin in mini wallet
|
|
986
|
+
try {
|
|
987
|
+
const marketCoins = await this.utils.selectCoins(
|
|
988
|
+
Number.MAX_SAFE_INTEGER,
|
|
989
|
+
this.utils.parseMarketCoinType(sCoinName as SupportSCoin),
|
|
990
|
+
this.walletAddress
|
|
991
|
+
); // throw error no coins found
|
|
992
|
+
|
|
993
|
+
const mergedMarketCoin = marketCoins[0];
|
|
994
|
+
if (marketCoins.length > 1) {
|
|
995
|
+
txBlock.mergeCoins(mergedMarketCoin, marketCoins.slice(1));
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
toDestroyMarketCoin = mergedMarketCoin;
|
|
999
|
+
} catch (e: any) {
|
|
1000
|
+
// Ignore
|
|
1001
|
+
const errMsg = e.toString() as String;
|
|
1002
|
+
if (!errMsg.includes('No valid coins found for the transaction'))
|
|
1003
|
+
throw e;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
// check for staked market coin in spool
|
|
1007
|
+
if (SUPPORT_SPOOLS.includes(sCoinName as SupportStakeMarketCoins)) {
|
|
1008
|
+
try {
|
|
1009
|
+
const stakedMarketCoins = await txBlock.unstakeQuick(
|
|
1010
|
+
Number.MAX_SAFE_INTEGER,
|
|
1011
|
+
sCoinName as SupportStakeMarketCoins
|
|
1012
|
+
);
|
|
1013
|
+
if (stakedMarketCoins.length > 0) {
|
|
1014
|
+
const mergedStakedMarketCoin = stakedMarketCoins[0];
|
|
1015
|
+
if (stakedMarketCoins.length > 1) {
|
|
1016
|
+
txBlock.mergeCoins(
|
|
1017
|
+
mergedStakedMarketCoin,
|
|
1018
|
+
stakedMarketCoins.slice(1)
|
|
1019
|
+
);
|
|
1020
|
+
}
|
|
1021
|
+
// merge with takeMarketCoin
|
|
1022
|
+
if (toDestroyMarketCoin) {
|
|
1023
|
+
txBlock.mergeCoins(toDestroyMarketCoin, [
|
|
1024
|
+
mergedStakedMarketCoin,
|
|
1025
|
+
]);
|
|
1026
|
+
} else {
|
|
1027
|
+
toDestroyMarketCoin = mergedStakedMarketCoin;
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
} catch (e: any) {
|
|
1031
|
+
// ignore
|
|
1032
|
+
const errMsg = e.toString();
|
|
1033
|
+
if (!errMsg.includes('No stake account found')) throw e;
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
// if market coin found, mint sCoin
|
|
1038
|
+
if (toDestroyMarketCoin) {
|
|
1039
|
+
// mint new sCoin
|
|
1040
|
+
const sCoin = txBlock.mintSCoin(
|
|
1041
|
+
sCoinName as SupportSCoin,
|
|
1042
|
+
toDestroyMarketCoin
|
|
1043
|
+
);
|
|
1044
|
+
|
|
1045
|
+
// check if current sCoin exist
|
|
1046
|
+
try {
|
|
1047
|
+
const existSCoins = await this.utils.selectCoins(
|
|
1048
|
+
Number.MAX_SAFE_INTEGER,
|
|
1049
|
+
this.utils.parseSCoinType(sCoinName as SupportSCoin),
|
|
1050
|
+
this.walletAddress
|
|
1051
|
+
); // throw error on no coins found
|
|
1052
|
+
const mergedSCoin = existSCoins[0];
|
|
1053
|
+
if (existSCoins.length > 1) {
|
|
1054
|
+
txBlock.mergeCoins(mergedSCoin, existSCoins.slice(1));
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
// merge existing sCoin to new sCoin
|
|
1058
|
+
txBlock.mergeCoins(sCoin, [mergedSCoin]);
|
|
1059
|
+
} catch (e: any) {
|
|
1060
|
+
// ignore
|
|
1061
|
+
const errMsg = e.toString() as String;
|
|
1062
|
+
if (!errMsg.includes('No valid coins found for the transaction'))
|
|
1063
|
+
throw e;
|
|
1064
|
+
}
|
|
1065
|
+
toTransfer.push(sCoin);
|
|
1066
|
+
}
|
|
1067
|
+
})
|
|
1068
|
+
);
|
|
1069
|
+
|
|
1070
|
+
if (toTransfer.length > 0) {
|
|
1071
|
+
txBlock.transferObjects(toTransfer, this.walletAddress);
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
if (sign) {
|
|
1075
|
+
return (await this.suiKit.signAndSendTxn(
|
|
1076
|
+
txBlock
|
|
1077
|
+
)) as ScallopClientFnReturnType<S>;
|
|
1078
|
+
} else {
|
|
1079
|
+
return txBlock.txBlock as ScallopClientFnReturnType<S>;
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
|
|
962
1083
|
/* ==================== Other Method ==================== */
|
|
963
1084
|
|
|
964
1085
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SuiKit } from '@scallop-io/sui-kit';
|
|
2
|
-
import { ADDRESSES_ID, SUPPORT_SPOOLS } from '../constants';
|
|
2
|
+
import { ADDRESSES_ID, SUPPORT_POOLS, SUPPORT_SPOOLS } from '../constants';
|
|
3
3
|
import {
|
|
4
4
|
queryMarket,
|
|
5
5
|
getObligations,
|
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
getPythPrices,
|
|
33
33
|
getVeScaTreasuryInfo,
|
|
34
34
|
getLoyaltyProgramInformations,
|
|
35
|
+
getFlashLoanFees,
|
|
35
36
|
} from '../queries';
|
|
36
37
|
import {
|
|
37
38
|
ScallopQueryParams,
|
|
@@ -44,6 +45,7 @@ import {
|
|
|
44
45
|
StakePools,
|
|
45
46
|
StakeRewardPools,
|
|
46
47
|
SupportBorrowIncentiveCoins,
|
|
48
|
+
SupportSCoin,
|
|
47
49
|
} from '../types';
|
|
48
50
|
import { ScallopAddress } from './scallopAddress';
|
|
49
51
|
import { ScallopUtils } from './scallopUtils';
|
|
@@ -51,6 +53,11 @@ import { ScallopIndexer } from './scallopIndexer';
|
|
|
51
53
|
import { ScallopCache } from './scallopCache';
|
|
52
54
|
import { DEFAULT_CACHE_OPTIONS } from 'src/constants/cache';
|
|
53
55
|
import { SuiObjectData } from '@mysten/sui.js/src/client';
|
|
56
|
+
import {
|
|
57
|
+
getSCoinAmount,
|
|
58
|
+
getSCoinAmounts,
|
|
59
|
+
getSCoinTotalSupply,
|
|
60
|
+
} from 'src/queries/sCoinQuery';
|
|
54
61
|
|
|
55
62
|
/**
|
|
56
63
|
* @description
|
|
@@ -593,4 +600,53 @@ export class ScallopQuery {
|
|
|
593
600
|
public async getLoyaltyProgramInfos(veScaKey?: string | SuiObjectData) {
|
|
594
601
|
return await getLoyaltyProgramInformations(this, veScaKey);
|
|
595
602
|
}
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
* Get total supply of sCoin
|
|
606
|
+
* @param sCoinName - Supported sCoin name
|
|
607
|
+
* @returns Total Supply
|
|
608
|
+
*/
|
|
609
|
+
public async getSCoinTotalSupply(sCoinName: SupportSCoin) {
|
|
610
|
+
return await getSCoinTotalSupply(this, sCoinName);
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
/**
|
|
614
|
+
* Get all sCoin amounts.
|
|
615
|
+
*
|
|
616
|
+
* @param sCoinNames - Specific an array of support sCoin name.
|
|
617
|
+
* @param ownerAddress - The owner address.
|
|
618
|
+
* @return All market sCoin amounts.
|
|
619
|
+
*/
|
|
620
|
+
public async getSCoinAmounts(
|
|
621
|
+
sCoinNames?: SupportSCoin[],
|
|
622
|
+
ownerAddress?: string
|
|
623
|
+
) {
|
|
624
|
+
return await getSCoinAmounts(this, sCoinNames, ownerAddress);
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
/**
|
|
628
|
+
* Get sCoin amount.
|
|
629
|
+
*
|
|
630
|
+
* @param coinNames - Specific support sCoin name.
|
|
631
|
+
* @param ownerAddress - The owner address.
|
|
632
|
+
* @return sCoin amount.
|
|
633
|
+
*/
|
|
634
|
+
public async getSCoinAmount(
|
|
635
|
+
sCoinName: SupportSCoin | SupportMarketCoins,
|
|
636
|
+
ownerAddress?: string
|
|
637
|
+
) {
|
|
638
|
+
const parsedSCoinName = this.utils.parseSCoinName(sCoinName);
|
|
639
|
+
return parsedSCoinName
|
|
640
|
+
? await getSCoinAmount(this, parsedSCoinName, ownerAddress)
|
|
641
|
+
: 0;
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
/*
|
|
645
|
+
* Get flashloan fee for specified assets
|
|
646
|
+
*/
|
|
647
|
+
public async getFlashLoanFees(
|
|
648
|
+
assetCoinNames: SupportAssetCoins[] = [...SUPPORT_POOLS]
|
|
649
|
+
) {
|
|
650
|
+
return await getFlashLoanFees(this, assetCoinNames);
|
|
651
|
+
}
|
|
596
652
|
}
|
|
@@ -16,6 +16,8 @@ import {
|
|
|
16
16
|
coinIds,
|
|
17
17
|
UNLOCK_ROUND_DURATION,
|
|
18
18
|
MAX_LOCK_DURATION,
|
|
19
|
+
SUPPORT_SCOIN,
|
|
20
|
+
sCoinIds,
|
|
19
21
|
} from '../constants';
|
|
20
22
|
import { queryObligation } from '../queries';
|
|
21
23
|
import {
|
|
@@ -35,6 +37,7 @@ import type {
|
|
|
35
37
|
CoinPrices,
|
|
36
38
|
PriceMap,
|
|
37
39
|
CoinWrappedType,
|
|
40
|
+
SupportSCoin,
|
|
38
41
|
} from '../types';
|
|
39
42
|
import { PYTH_ENDPOINTS } from 'src/constants/pyth';
|
|
40
43
|
import { ScallopCache } from './scallopCache';
|
|
@@ -170,6 +173,57 @@ export class ScallopUtils {
|
|
|
170
173
|
}
|
|
171
174
|
}
|
|
172
175
|
|
|
176
|
+
/**
|
|
177
|
+
* Convert coin name to sCoin name.
|
|
178
|
+
*
|
|
179
|
+
* @param coinName - Specific support coin name.
|
|
180
|
+
* @return sCoin name.
|
|
181
|
+
*/
|
|
182
|
+
public parseSCoinName<T extends SupportSCoin>(
|
|
183
|
+
coinName: SupportCoins | SupportMarketCoins
|
|
184
|
+
) {
|
|
185
|
+
// need more check because sbtc, ssol and sapt has no sCoin type
|
|
186
|
+
if (
|
|
187
|
+
isMarketCoin(coinName) &&
|
|
188
|
+
SUPPORT_SCOIN.includes(coinName as SupportSCoin)
|
|
189
|
+
) {
|
|
190
|
+
return coinName as T;
|
|
191
|
+
} else {
|
|
192
|
+
const marketCoinName = `s${coinName}`;
|
|
193
|
+
if (SUPPORT_SCOIN.includes(marketCoinName as SupportSCoin)) {
|
|
194
|
+
return marketCoinName as T;
|
|
195
|
+
}
|
|
196
|
+
return undefined;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Convert sCoin name into sCoin type
|
|
201
|
+
* @param sCoinName
|
|
202
|
+
* @returns sCoin type
|
|
203
|
+
*/
|
|
204
|
+
public parseSCoinType(sCoinName: SupportSCoin) {
|
|
205
|
+
return sCoinIds[sCoinName];
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Convert sCoin name into its underlying coin type
|
|
210
|
+
* @param sCoinName
|
|
211
|
+
* @returns coin type
|
|
212
|
+
*/
|
|
213
|
+
public parseUnderlyingSCoinType(sCoinName: SupportSCoin) {
|
|
214
|
+
const coinName = this.parseCoinName(sCoinName);
|
|
215
|
+
return this.parseCoinType(coinName);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Get sCoin treasury id from sCoin name
|
|
220
|
+
* @param sCoinName
|
|
221
|
+
* @returns sCoin treasury id
|
|
222
|
+
*/
|
|
223
|
+
public getSCoinTreasury(sCoinName: SupportSCoin) {
|
|
224
|
+
return this._address.get(`scoin.coins.${sCoinName}.treasury`);
|
|
225
|
+
}
|
|
226
|
+
|
|
173
227
|
/**
|
|
174
228
|
* Convert coin name to market coin type.
|
|
175
229
|
*
|
|
@@ -328,7 +382,7 @@ export class ScallopUtils {
|
|
|
328
382
|
* @param coinType - The coin type, default is 0x2::SUI::SUI.
|
|
329
383
|
* @return The selected transaction coin arguments.
|
|
330
384
|
*/
|
|
331
|
-
public async
|
|
385
|
+
public async selectCoins(
|
|
332
386
|
amount: number,
|
|
333
387
|
coinType: string = SUI_TYPE_ARG,
|
|
334
388
|
ownerAddress?: string
|
|
@@ -339,7 +393,7 @@ export class ScallopUtils {
|
|
|
339
393
|
amount,
|
|
340
394
|
coinType
|
|
341
395
|
);
|
|
342
|
-
return coins
|
|
396
|
+
return coins;
|
|
343
397
|
}
|
|
344
398
|
|
|
345
399
|
/**
|
package/src/queries/coreQuery.ts
CHANGED
|
@@ -4,6 +4,8 @@ import {
|
|
|
4
4
|
PROTOCOL_OBJECT_ID,
|
|
5
5
|
SUPPORT_COLLATERALS,
|
|
6
6
|
BORROW_FEE_PROTOCOL_ID,
|
|
7
|
+
USE_TEST_ADDRESS,
|
|
8
|
+
FlashLoanFeeObjectMap,
|
|
7
9
|
} from '../constants';
|
|
8
10
|
import {
|
|
9
11
|
parseOriginMarketPoolData,
|
|
@@ -404,7 +406,12 @@ export const getMarketPool = async (
|
|
|
404
406
|
}
|
|
405
407
|
}
|
|
406
408
|
|
|
407
|
-
if (
|
|
409
|
+
if (
|
|
410
|
+
balanceSheet &&
|
|
411
|
+
borrowIndex &&
|
|
412
|
+
interestModel &&
|
|
413
|
+
(USE_TEST_ADDRESS || borrowFeeRate)
|
|
414
|
+
) {
|
|
408
415
|
const parsedMarketPoolData = parseOriginMarketPoolData({
|
|
409
416
|
type: interestModel.type.fields,
|
|
410
417
|
maxBorrowRate: interestModel.max_borrow_rate.fields,
|
|
@@ -418,7 +425,7 @@ export const getMarketPool = async (
|
|
|
418
425
|
reserve: balanceSheet.revenue,
|
|
419
426
|
reserveFactor: interestModel.revenue_factor.fields,
|
|
420
427
|
borrowWeight: interestModel.borrow_weight.fields,
|
|
421
|
-
borrowFeeRate: borrowFeeRate,
|
|
428
|
+
borrowFeeRate: borrowFeeRate || { value: '0' },
|
|
422
429
|
baseBorrowRatePerSec: interestModel.base_borrow_rate_per_sec.fields,
|
|
423
430
|
borrowRateOnHighKink: interestModel.borrow_rate_on_high_kink.fields,
|
|
424
431
|
borrowRateOnMidKink: interestModel.borrow_rate_on_mid_kink.fields,
|
|
@@ -474,10 +481,10 @@ export const getMarketCollaterals = async (
|
|
|
474
481
|
collateralCoinNames = collateralCoinNames || [...SUPPORT_COLLATERALS];
|
|
475
482
|
const marketId = query.address.get('core.market');
|
|
476
483
|
const [marketObjectResponse, coinPrices] = await Promise.all([
|
|
477
|
-
query.cache.queryGetObject(marketId, {
|
|
484
|
+
await query.cache.queryGetObject(marketId, {
|
|
478
485
|
showContent: true,
|
|
479
486
|
}),
|
|
480
|
-
query.utils.getCoinPrices(collateralCoinNames ?? []),
|
|
487
|
+
await query.utils.getCoinPrices(collateralCoinNames ?? []),
|
|
481
488
|
]);
|
|
482
489
|
const marketCollaterals: MarketCollaterals = {};
|
|
483
490
|
|
|
@@ -875,3 +882,94 @@ export const getMarketCoinAmount = async (
|
|
|
875
882
|
});
|
|
876
883
|
return BigNumber(amount).toNumber();
|
|
877
884
|
};
|
|
885
|
+
|
|
886
|
+
/**
|
|
887
|
+
* Get flashloan fee for specific asset
|
|
888
|
+
* @param query - The Scallop query instance.
|
|
889
|
+
* @param assetNames - Specific an array of support pool coin name.
|
|
890
|
+
* @returns Record of asset name to flashloan fee in decimal
|
|
891
|
+
*/
|
|
892
|
+
|
|
893
|
+
export const getFlashLoanFees = async (
|
|
894
|
+
query: ScallopQuery,
|
|
895
|
+
assetNames: SupportPoolCoins[]
|
|
896
|
+
): Promise<Record<SupportPoolCoins, number>> => {
|
|
897
|
+
const FEE_RATE = 1e4;
|
|
898
|
+
const missingAssets: SupportPoolCoins[] = [];
|
|
899
|
+
|
|
900
|
+
// create mapping from asset type to asset name
|
|
901
|
+
const assetTypeMap = assetNames.reduce(
|
|
902
|
+
(prev, curr) => {
|
|
903
|
+
const assetType = query.utils.parseCoinType(curr).slice(2);
|
|
904
|
+
prev[assetType] = curr;
|
|
905
|
+
return prev;
|
|
906
|
+
},
|
|
907
|
+
{} as Record<string, SupportPoolCoins>
|
|
908
|
+
);
|
|
909
|
+
|
|
910
|
+
// use the mapped object first
|
|
911
|
+
const objIds = assetNames
|
|
912
|
+
.map((assetName) => {
|
|
913
|
+
if (!FlashLoanFeeObjectMap[assetName]) {
|
|
914
|
+
missingAssets.push(assetName);
|
|
915
|
+
return null;
|
|
916
|
+
} else {
|
|
917
|
+
return FlashLoanFeeObjectMap[assetName];
|
|
918
|
+
}
|
|
919
|
+
})
|
|
920
|
+
.filter((t) => !!t) as string[];
|
|
921
|
+
|
|
922
|
+
const flashloanFeeObjects = await query.cache.queryGetObjects(objIds, {
|
|
923
|
+
showContent: true,
|
|
924
|
+
});
|
|
925
|
+
|
|
926
|
+
if (missingAssets.length > 0) {
|
|
927
|
+
// get market object
|
|
928
|
+
const marketObjectId = query.address.get('core.market');
|
|
929
|
+
const marketObjectRes = await query.cache.queryGetObject(marketObjectId, {
|
|
930
|
+
showContent: true,
|
|
931
|
+
});
|
|
932
|
+
if (marketObjectRes.data?.content?.dataType !== 'moveObject')
|
|
933
|
+
throw new Error('Failed to get market object');
|
|
934
|
+
|
|
935
|
+
// get vault
|
|
936
|
+
const vault = (marketObjectRes.data.content.fields as any).vault;
|
|
937
|
+
|
|
938
|
+
// get vault balance sheet object id
|
|
939
|
+
const flashloanFeesTableId = vault.fields.flash_loan_fees.fields.table
|
|
940
|
+
.fields.id.id as string;
|
|
941
|
+
|
|
942
|
+
// the balance sheet is a VecSet<0x1::type_name::TypeName
|
|
943
|
+
const balanceSheetDynamicFields = await query.cache.queryGetDynamicFields({
|
|
944
|
+
parentId: flashloanFeesTableId,
|
|
945
|
+
limit: 50,
|
|
946
|
+
});
|
|
947
|
+
|
|
948
|
+
// get the dynamic object ids
|
|
949
|
+
const dynamicFieldObjectIds = balanceSheetDynamicFields.data
|
|
950
|
+
.filter((field) => {
|
|
951
|
+
const assetType = (field.name.value as any).name as string;
|
|
952
|
+
return !!assetTypeMap[assetType];
|
|
953
|
+
})
|
|
954
|
+
.map((field) => field.objectId);
|
|
955
|
+
|
|
956
|
+
flashloanFeeObjects.push(
|
|
957
|
+
...(await query.cache.queryGetObjects(dynamicFieldObjectIds, {
|
|
958
|
+
showContent: true,
|
|
959
|
+
}))
|
|
960
|
+
);
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
return flashloanFeeObjects.reduce(
|
|
964
|
+
(prev, curr) => {
|
|
965
|
+
if (curr.content?.dataType === 'moveObject') {
|
|
966
|
+
const objectFields = curr.content.fields as any;
|
|
967
|
+
const assetType = (curr.content.fields as any).name.fields.name;
|
|
968
|
+
const feeNumerator = +objectFields.value;
|
|
969
|
+
prev[assetTypeMap[assetType]] = feeNumerator / FEE_RATE;
|
|
970
|
+
}
|
|
971
|
+
return prev;
|
|
972
|
+
},
|
|
973
|
+
{} as Record<SupportPoolCoins, number>
|
|
974
|
+
);
|
|
975
|
+
};
|