@scallop-io/sui-scallop-sdk 0.46.38 → 0.46.40

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.
@@ -401,4 +401,8 @@ export declare class ScallopQuery {
401
401
  * @returns Loyalty program information
402
402
  */
403
403
  getLoyaltyProgramInfos(veScaKey?: string | SuiObjectData): Promise<import("../types").LoyaltyProgramInfo | null>;
404
+ /**
405
+ * Get flashloan fee for specified assets
406
+ */
407
+ getFlashLoanFees(assetCoinNames?: SupportAssetCoins[]): Promise<Record<"eth" | "btc" | "usdc" | "usdt" | "sui" | "apt" | "sol" | "cetus" | "afsui" | "hasui" | "vsui" | "sca", number>>;
404
408
  }
@@ -150,3 +150,10 @@ export declare const getMarketCoinAmounts: (query: ScallopQuery, marketCoinNames
150
150
  * @return Owned market coin amount.
151
151
  */
152
152
  export declare const getMarketCoinAmount: (query: ScallopQuery, marketCoinName: SupportMarketCoins, ownerAddress?: string) => Promise<number>;
153
+ /**
154
+ * Get flashloan fee for specific asset
155
+ * @param query - The Scallop query instance.
156
+ * @param assetNames - Specific an array of support pool coin name.
157
+ * @returns Record of asset name to flashloan fee in decimal
158
+ */
159
+ export declare const getFlashLoanFees: (query: ScallopQuery, assetNames: SupportPoolCoins[]) => Promise<Record<SupportPoolCoins, number>>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scallop-io/sui-scallop-sdk",
3
- "version": "0.46.38",
3
+ "version": "0.46.40",
4
4
  "description": "Typescript sdk for interacting with Scallop contract on SUI",
5
5
  "keywords": [
6
6
  "sui",
@@ -0,0 +1,18 @@
1
+ import { OptionalKeys, SupportPoolCoins } from 'src/types';
2
+
3
+ export const FlashLoanFeeObjectMap: OptionalKeys<
4
+ Record<SupportPoolCoins, string>
5
+ > = {
6
+ vsui: '0x0069cddee7a5c0b1d34beb5ef0620f978096525f1830b055f38b110f40d73fbb',
7
+ btc: '0x2078490aa37d8fb42b511e5c95e217cb957d141267e16980bc802d76b42719f7',
8
+ sui: '0x27614284a8f0a699ffd35aae8f2572c937ec76771cb21b0d7930ec4491a76ed4',
9
+ usdt: '0x5b61983a19b5159ca348d291e4b595f42db70ccda32852a2ed85528aa65171e4',
10
+ apt: '0x9d5898edcd1e4abcb044273242293a9d036f6a977bf3fe57ab71f5a87c505ee6',
11
+ afsui: '0xac87fde83d434554ec300c1334c9a622aa5b59e82a04334dc99e1cc1f75d4eae',
12
+ hasui: '0xb9f505d532de1d6c9f3a8522a2d16f2958b75c0ed939d4f80b96f584a2a8ed5e',
13
+ usdc: '0xd241d6a7e44ac11a6689370ed9a98eec389b98b8a6695c61fddede9fa7567b90',
14
+ eth: '0xd252acb058e77877810c1290564e290a8f9fcab5bc9aca2884ede8a38810cf34',
15
+ sca: '0xe04e46471754b6f48d81c549ecfec09de02733715a63bec02364c6ac7c4dd2dc',
16
+ cetus: '0xe65a73d11c31b2d323ad2b9f6b4bb0a3c0df9c1b212eef66c854941186a5ddc7',
17
+ sol: '0xe84bdb35b790fc7bdd1645122ac6ac0fc904531d6772c9e25904fece322c5f34',
18
+ };
@@ -1,3 +1,4 @@
1
1
  export * from './common';
2
2
  export * from './enum';
3
3
  export * from './vesca';
4
+ export * from './flashloan';
@@ -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,
@@ -593,4 +594,13 @@ export class ScallopQuery {
593
594
  public async getLoyaltyProgramInfos(veScaKey?: string | SuiObjectData) {
594
595
  return await getLoyaltyProgramInformations(this, veScaKey);
595
596
  }
597
+
598
+ /**
599
+ * Get flashloan fee for specified assets
600
+ */
601
+ public async getFlashLoanFees(
602
+ assetCoinNames: SupportAssetCoins[] = [...SUPPORT_POOLS]
603
+ ) {
604
+ return await getFlashLoanFees(this, assetCoinNames);
605
+ }
596
606
  }
@@ -4,6 +4,7 @@ import {
4
4
  PROTOCOL_OBJECT_ID,
5
5
  SUPPORT_COLLATERALS,
6
6
  BORROW_FEE_PROTOCOL_ID,
7
+ FlashLoanFeeObjectMap,
7
8
  } from '../constants';
8
9
  import {
9
10
  parseOriginMarketPoolData,
@@ -232,7 +233,7 @@ export const getMarketPools = async (
232
233
  return marketPools;
233
234
  }
234
235
 
235
- Promise.allSettled(
236
+ await Promise.allSettled(
236
237
  poolCoinNames.map(async (poolCoinName) => {
237
238
  const marketPool = await getMarketPool(
238
239
  query,
@@ -268,19 +269,6 @@ export const getMarketPool = async (
268
269
  marketObject?: SuiObjectData | null,
269
270
  coinPrice?: number
270
271
  ) => {
271
- const marketId = query.address.get('core.market');
272
- marketObject =
273
- marketObject ||
274
- (
275
- await query.cache.queryGetObject(marketId, {
276
- showContent: true,
277
- })
278
- ).data;
279
-
280
- coinPrice =
281
- coinPrice ||
282
- (await query.utils.getCoinPrices([poolCoinName]))?.[poolCoinName];
283
-
284
272
  let marketPool: MarketPool | undefined;
285
273
  let balanceSheet: BalanceSheet | undefined;
286
274
  let borrowIndex: BorrowIndex | undefined;
@@ -297,6 +285,19 @@ export const getMarketPool = async (
297
285
  return marketPoolIndexer;
298
286
  }
299
287
 
288
+ const marketId = query.address.get('core.market');
289
+ marketObject =
290
+ marketObject ||
291
+ (
292
+ await query.cache.queryGetObject(marketId, {
293
+ showContent: true,
294
+ })
295
+ ).data;
296
+
297
+ coinPrice =
298
+ coinPrice ||
299
+ (await query.utils.getCoinPrices([poolCoinName]))?.[poolCoinName];
300
+
300
301
  if (marketObject) {
301
302
  if (marketObject.content && 'fields' in marketObject.content) {
302
303
  const fields = marketObject.content.fields as any;
@@ -840,7 +841,7 @@ export const getMarketCoinAmounts = async (
840
841
  const owner = ownerAddress || query.suiKit.currentAddress();
841
842
  const marketCoins = {} as OptionalKeys<Record<SupportMarketCoins, number>>;
842
843
 
843
- Promise.allSettled(
844
+ await Promise.allSettled(
844
845
  marketCoinNames.map(async (marketCoinName) => {
845
846
  const marketCoin = await getMarketCoinAmount(
846
847
  query,
@@ -875,3 +876,94 @@ export const getMarketCoinAmount = async (
875
876
  });
876
877
  return BigNumber(amount).toNumber();
877
878
  };
879
+
880
+ /**
881
+ * Get flashloan fee for specific asset
882
+ * @param query - The Scallop query instance.
883
+ * @param assetNames - Specific an array of support pool coin name.
884
+ * @returns Record of asset name to flashloan fee in decimal
885
+ */
886
+
887
+ export const getFlashLoanFees = async (
888
+ query: ScallopQuery,
889
+ assetNames: SupportPoolCoins[]
890
+ ): Promise<Record<SupportPoolCoins, number>> => {
891
+ const FEE_RATE = 1e4;
892
+ const missingAssets: SupportPoolCoins[] = [];
893
+
894
+ // create mapping from asset type to asset name
895
+ const assetTypeMap = assetNames.reduce(
896
+ (prev, curr) => {
897
+ const assetType = query.utils.parseCoinType(curr).slice(2);
898
+ prev[assetType] = curr;
899
+ return prev;
900
+ },
901
+ {} as Record<string, SupportPoolCoins>
902
+ );
903
+
904
+ // use the mapped object first
905
+ const objIds = assetNames
906
+ .map((assetName) => {
907
+ if (!FlashLoanFeeObjectMap[assetName]) {
908
+ missingAssets.push(assetName);
909
+ return null;
910
+ } else {
911
+ return FlashLoanFeeObjectMap[assetName];
912
+ }
913
+ })
914
+ .filter((t) => !!t) as string[];
915
+
916
+ const flashloanFeeObjects = await query.cache.queryGetObjects(objIds, {
917
+ showContent: true,
918
+ });
919
+
920
+ if (missingAssets.length > 0) {
921
+ // get market object
922
+ const marketObjectId = query.address.get('core.market');
923
+ const marketObjectRes = await query.cache.queryGetObject(marketObjectId, {
924
+ showContent: true,
925
+ });
926
+ if (marketObjectRes.data?.content?.dataType !== 'moveObject')
927
+ throw new Error('Failed to get market object');
928
+
929
+ // get vault
930
+ const vault = (marketObjectRes.data.content.fields as any).vault;
931
+
932
+ // get vault balance sheet object id
933
+ const flashloanFeesTableId = vault.fields.flash_loan_fees.fields.table
934
+ .fields.id.id as string;
935
+
936
+ // the balance sheet is a VecSet<0x1::type_name::TypeName
937
+ const balanceSheetDynamicFields = await query.cache.queryGetDynamicFields({
938
+ parentId: flashloanFeesTableId,
939
+ limit: 50,
940
+ });
941
+
942
+ // get the dynamic object ids
943
+ const dynamicFieldObjectIds = balanceSheetDynamicFields.data
944
+ .filter((field) => {
945
+ const assetType = (field.name.value as any).name as string;
946
+ return !!assetTypeMap[assetType];
947
+ })
948
+ .map((field) => field.objectId);
949
+
950
+ flashloanFeeObjects.push(
951
+ ...(await query.cache.queryGetObjects(dynamicFieldObjectIds, {
952
+ showContent: true,
953
+ }))
954
+ );
955
+ }
956
+
957
+ return flashloanFeeObjects.reduce(
958
+ (prev, curr) => {
959
+ if (curr.content?.dataType === 'moveObject') {
960
+ const objectFields = curr.content.fields as any;
961
+ const assetType = (curr.content.fields as any).name.fields.name;
962
+ const feeNumerator = +objectFields.value;
963
+ prev[assetTypeMap[assetType]] = feeNumerator / FEE_RATE;
964
+ }
965
+ return prev;
966
+ },
967
+ {} as Record<SupportPoolCoins, number>
968
+ );
969
+ };
@@ -28,15 +28,13 @@ export const getVescaKeys = async (
28
28
  let hasNextPage = false;
29
29
  let nextCursor: string | null | undefined = null;
30
30
  do {
31
- const paginatedKeyObjectsResponse = await query.suiKit
32
- .client()
33
- .getOwnedObjects({
34
- owner,
35
- filter: {
36
- StructType: veScaKeyType,
37
- },
38
- cursor: nextCursor,
39
- });
31
+ const paginatedKeyObjectsResponse = await query.cache.queryGetOwnedObjects({
32
+ owner,
33
+ filter: {
34
+ StructType: veScaKeyType,
35
+ },
36
+ cursor: nextCursor,
37
+ });
40
38
  keyObjectsResponse.push(...paginatedKeyObjectsResponse.data);
41
39
  if (
42
40
  paginatedKeyObjectsResponse.hasNextPage &&