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

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 (57) 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 +1533 -1378
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.mjs +1499 -1344
  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 +3 -6
  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/index.d.ts +8 -1
  24. package/dist/types/builder/vesca.d.ts +2 -1
  25. package/dist/types/model.d.ts +27 -12
  26. package/dist/types/query/core.d.ts +1 -0
  27. package/dist/utils/query.d.ts +1 -1
  28. package/package.json +1 -1
  29. package/src/builders/borrowIncentiveBuilder.ts +19 -21
  30. package/src/builders/coreBuilder.ts +10 -8
  31. package/src/builders/spoolBuilder.ts +2 -2
  32. package/src/builders/vescaBuilder.ts +12 -4
  33. package/src/constants/common.ts +2 -0
  34. package/src/constants/enum.ts +4 -0
  35. package/src/constants/pyth.ts +2 -2
  36. package/src/models/scallop.ts +14 -20
  37. package/src/models/scallopAddress.ts +15 -5
  38. package/src/models/scallopBuilder.ts +42 -32
  39. package/src/models/scallopCache.ts +2 -2
  40. package/src/models/scallopClient.ts +91 -32
  41. package/src/models/scallopIndexer.ts +15 -8
  42. package/src/models/scallopPrice.ts +0 -0
  43. package/src/models/scallopQuery.ts +47 -25
  44. package/src/models/scallopUtils.ts +75 -74
  45. package/src/queries/borrowIncentiveQuery.ts +40 -29
  46. package/src/queries/coreQuery.ts +40 -26
  47. package/src/queries/portfolioQuery.ts +1 -2
  48. package/src/queries/priceQuery.ts +20 -9
  49. package/src/queries/referralQuery.ts +4 -4
  50. package/src/queries/sCoinQuery.ts +95 -17
  51. package/src/queries/spoolQuery.ts +26 -14
  52. package/src/queries/vescaQuery.ts +32 -26
  53. package/src/types/builder/index.ts +11 -1
  54. package/src/types/builder/vesca.ts +8 -1
  55. package/src/types/model.ts +40 -11
  56. package/src/types/query/core.ts +1 -0
  57. package/src/utils/query.ts +1 -1
package/dist/index.mjs CHANGED
@@ -55,7 +55,9 @@ var SUPPORT_SCOIN = [
55
55
  "svsui",
56
56
  "seth",
57
57
  "ssca",
58
- "scetus"
58
+ "scetus",
59
+ "ssol",
60
+ "sbtc"
59
61
  ];
60
62
  var SUPPORT_SPOOLS_REWARDS = ["sui"];
61
63
  var SUPPORT_BORROW_INCENTIVE_POOLS = [
@@ -149,7 +151,9 @@ var sCoins = {
149
151
  safsui: "safsui",
150
152
  shasui: "shasui",
151
153
  svsui: "svsui",
152
- ssca: "ssca"
154
+ ssca: "ssca",
155
+ ssol: "ssol",
156
+ sbtc: "sbtc"
153
157
  };
154
158
  var stakeMarketCoins = {
155
159
  seth: "seth",
@@ -215,7 +219,9 @@ var sCoinIds = {
215
219
  seth: "0x67540ceb850d418679e69f1fb6b2093d6df78a2a699ffc733f7646096d552e9b::scallop_wormhole_eth::SCALLOP_WORMHOLE_ETH",
216
220
  safsui: "0x00671b1fa2a124f5be8bdae8b91ee711462c5d9e31bda232e70fd9607b523c88::scallop_af_sui::SCALLOP_AF_SUI",
217
221
  shasui: "0x9a2376943f7d22f88087c259c5889925f332ca4347e669dc37d54c2bf651af3c::scallop_ha_sui::SCALLOP_HA_SUI",
218
- svsui: "0xe1a1cc6bcf0001a015eab84bcc6713393ce20535f55b8b6f35c142e057a25fbe::scallop_v_sui::SCALLOP_V_SUI"
222
+ svsui: "0xe1a1cc6bcf0001a015eab84bcc6713393ce20535f55b8b6f35c142e057a25fbe::scallop_v_sui::SCALLOP_V_SUI",
223
+ ssol: "0x1392650f2eca9e3f6ffae3ff89e42a3590d7102b80e2b430f674730bc30d3259::scallop_wormhole_sol::SCALLOP_WORMHOLE_SOL",
224
+ sbtc: "0x2cf76a9cf5d3337961d1154283234f94da2dcff18544dfe5cbdef65f319591b5::scallop_wormhole_btc::SCALLOP_WORMHOLE_BTC"
219
225
  };
220
226
 
221
227
  // src/constants/vesca.ts
@@ -242,7 +248,10 @@ var FlashLoanFeeObjectMap = {
242
248
  };
243
249
 
244
250
  // src/models/scallop.ts
245
- import { SuiKit as SuiKit5 } from "@scallop-io/sui-kit";
251
+ import { SuiKit as SuiKit7 } from "@scallop-io/sui-kit";
252
+
253
+ // src/models/scallopAddress.ts
254
+ import { SuiKit } from "@scallop-io/sui-kit";
246
255
 
247
256
  // src/models/scallopCache.ts
248
257
  import { QueryClient } from "@tanstack/query-core";
@@ -853,7 +862,7 @@ var callWithRateLimit = async (tokenBucket, fn, retryDelayInMs = DEFAULT_INTERVA
853
862
 
854
863
  // src/models/scallopCache.ts
855
864
  var ScallopCache = class {
856
- constructor(cacheOptions, suiKit, tokenBucket) {
865
+ constructor(suiKit, cacheOptions, tokenBucket) {
857
866
  this.queryClient = new QueryClient(cacheOptions ?? DEFAULT_CACHE_OPTIONS);
858
867
  this._suiKit = suiKit;
859
868
  this.tokenBucket = tokenBucket ?? new TokenBucket(DEFAULT_TOKENS_PER_INTERVAL, DEFAULT_INTERVAL_IN_MS);
@@ -1843,9 +1852,12 @@ var EMPTY_ADDRESSES = {
1843
1852
  }
1844
1853
  };
1845
1854
  var ScallopAddress = class {
1846
- constructor(params, cache) {
1855
+ constructor(params, instance) {
1847
1856
  const { id, auth, network } = params;
1848
- this._cache = cache ?? new ScallopCache(DEFAULT_CACHE_OPTIONS);
1857
+ this.cache = instance?.cache ?? new ScallopCache(
1858
+ instance?.suiKit ?? new SuiKit({}),
1859
+ DEFAULT_CACHE_OPTIONS
1860
+ );
1849
1861
  this._requestClient = axios.create({
1850
1862
  baseURL: API_BASE_URL,
1851
1863
  headers: {
@@ -2021,7 +2033,7 @@ var ScallopAddress = class {
2021
2033
  async read(id) {
2022
2034
  const addressesId = id || this._id || void 0;
2023
2035
  if (addressesId !== void 0) {
2024
- const response = await this._cache.queryClient.fetchQuery({
2036
+ const response = await this.cache.queryClient.fetchQuery({
2025
2037
  queryKey: ["api-getAddresses", addressesId],
2026
2038
  queryFn: async () => {
2027
2039
  return await this._requestClient.get(`/addresses/${addressesId}`, {
@@ -2149,16 +2161,13 @@ var ScallopAddress = class {
2149
2161
 
2150
2162
  // src/models/scallopClient.ts
2151
2163
  import { normalizeSuiAddress as normalizeSuiAddress4 } from "@mysten/sui.js/utils";
2152
- import { SuiKit as SuiKit4 } from "@scallop-io/sui-kit";
2164
+ import { SuiKit as SuiKit6 } from "@scallop-io/sui-kit";
2153
2165
 
2154
2166
  // src/models/scallopUtils.ts
2155
2167
  import { SUI_TYPE_ARG, normalizeStructTag as normalizeStructTag6 } from "@mysten/sui.js/utils";
2156
2168
  import { SuiKit as SuiKit2 } from "@scallop-io/sui-kit";
2157
2169
  import { SuiPriceServiceConnection } from "@pythnetwork/pyth-sui-js";
2158
2170
 
2159
- // src/models/scallopQuery.ts
2160
- import { SuiKit } from "@scallop-io/sui-kit";
2161
-
2162
2171
  // src/queries/coreQuery.ts
2163
2172
  import { normalizeStructTag as normalizeStructTag3 } from "@mysten/sui.js/utils";
2164
2173
  import BigNumber2 from "bignumber.js";
@@ -2226,6 +2235,9 @@ var queryMarket = async (query, indexer = false) => {
2226
2235
  symbol: query.utils.parseSymbol(poolCoinName),
2227
2236
  coinType,
2228
2237
  marketCoinType: query.utils.parseMarketCoinType(poolCoinName),
2238
+ sCoinType: query.utils.parseSCoinType(
2239
+ query.utils.parseMarketCoinName(poolCoinName)
2240
+ ),
2229
2241
  coinWrappedType: query.utils.getCoinWrappedType(poolCoinName),
2230
2242
  coinDecimal: query.utils.getCoinDecimal(poolCoinName),
2231
2243
  coinPrice,
@@ -2444,6 +2456,9 @@ var getMarketPool = async (query, poolCoinName, indexer = false, marketObject, c
2444
2456
  symbol: query.utils.parseSymbol(poolCoinName),
2445
2457
  coinType: query.utils.parseCoinType(poolCoinName),
2446
2458
  marketCoinType: query.utils.parseMarketCoinType(poolCoinName),
2459
+ sCoinType: query.utils.parseSCoinType(
2460
+ query.utils.parseMarketCoinName(poolCoinName)
2461
+ ),
2447
2462
  coinWrappedType: query.utils.getCoinWrappedType(poolCoinName),
2448
2463
  coinDecimal: query.utils.getCoinDecimal(poolCoinName),
2449
2464
  coinPrice: coinPrice ?? 0,
@@ -2588,14 +2603,16 @@ var getMarketCollateral = async (query, collateralCoinName, indexer = false, mar
2588
2603
  }
2589
2604
  return marketCollateral;
2590
2605
  };
2591
- var getObligations = async (query, ownerAddress) => {
2592
- const owner = ownerAddress || query.suiKit.currentAddress();
2593
- const protocolObjectId = query.address.get("core.object") || PROTOCOL_OBJECT_ID;
2606
+ var getObligations = async ({
2607
+ address
2608
+ }, ownerAddress) => {
2609
+ const owner = ownerAddress;
2610
+ const protocolObjectId = address.get("core.object") || PROTOCOL_OBJECT_ID;
2594
2611
  const keyObjectsResponse = [];
2595
2612
  let hasNextPage = false;
2596
2613
  let nextCursor = null;
2597
2614
  do {
2598
- const paginatedKeyObjectsResponse = await query.cache.queryGetOwnedObjects({
2615
+ const paginatedKeyObjectsResponse = await address.cache.queryGetOwnedObjects({
2599
2616
  owner,
2600
2617
  filter: {
2601
2618
  StructType: `${protocolObjectId}::obligation::ObligationKey`
@@ -2603,7 +2620,7 @@ var getObligations = async (query, ownerAddress) => {
2603
2620
  cursor: nextCursor
2604
2621
  });
2605
2622
  if (!paginatedKeyObjectsResponse)
2606
- continue;
2623
+ break;
2607
2624
  keyObjectsResponse.push(...paginatedKeyObjectsResponse.data);
2608
2625
  if (paginatedKeyObjectsResponse.hasNextPage && paginatedKeyObjectsResponse.nextCursor) {
2609
2626
  hasNextPage = true;
@@ -2613,7 +2630,7 @@ var getObligations = async (query, ownerAddress) => {
2613
2630
  }
2614
2631
  } while (hasNextPage);
2615
2632
  const keyObjectIds = keyObjectsResponse.map((ref) => ref?.data?.objectId).filter((id) => id !== void 0);
2616
- const keyObjects = await query.cache.queryGetObjects(keyObjectIds);
2633
+ const keyObjects = await address.cache.queryGetObjects(keyObjectIds);
2617
2634
  const obligations = [];
2618
2635
  await Promise.allSettled(
2619
2636
  keyObjects.map(async (keyObject) => {
@@ -2621,18 +2638,17 @@ var getObligations = async (query, ownerAddress) => {
2621
2638
  if (keyObject.content && "fields" in keyObject.content) {
2622
2639
  const fields = keyObject.content.fields;
2623
2640
  const obligationId = String(fields.ownership.fields.of);
2624
- const locked = await getObligationLocked(query, obligationId);
2641
+ const locked = await getObligationLocked(address.cache, obligationId);
2625
2642
  obligations.push({ id: obligationId, keyId, locked });
2626
2643
  }
2627
2644
  })
2628
2645
  );
2629
2646
  return obligations;
2630
2647
  };
2631
- var getObligationLocked = async (query, obligationId) => {
2632
- const obligationObjectResponse = await query.cache.queryGetObject(
2633
- obligationId,
2634
- { showContent: true }
2635
- );
2648
+ var getObligationLocked = async (cache, obligationId) => {
2649
+ const obligationObjectResponse = await cache.queryGetObject(obligationId, {
2650
+ showContent: true
2651
+ });
2636
2652
  let obligationLocked = false;
2637
2653
  if (obligationObjectResponse?.data && obligationObjectResponse?.data?.content?.dataType === "moveObject" && "lock_key" in obligationObjectResponse.data.content.fields) {
2638
2654
  obligationLocked = Boolean(
@@ -2641,15 +2657,17 @@ var getObligationLocked = async (query, obligationId) => {
2641
2657
  }
2642
2658
  return obligationLocked;
2643
2659
  };
2644
- var queryObligation = async (query, obligationId) => {
2645
- const packageId = query.address.get("core.packages.query.id");
2660
+ var queryObligation = async ({
2661
+ address
2662
+ }, obligationId) => {
2663
+ const packageId = address.get("core.packages.query.id");
2646
2664
  const queryTarget = `${packageId}::obligation_query::obligation_data`;
2647
2665
  const args = [obligationId];
2648
- const queryResult = await query.cache.queryInspectTxn(
2666
+ const queryResult = await address.cache.queryInspectTxn(
2649
2667
  { queryTarget, args }
2650
2668
  // txBlock
2651
2669
  );
2652
- return queryResult?.events[0].parsedJson;
2670
+ return queryResult?.events[0]?.parsedJson;
2653
2671
  };
2654
2672
  var getCoinAmounts = async (query, assetCoinNames, ownerAddress) => {
2655
2673
  assetCoinNames = assetCoinNames || [...SUPPORT_POOLS];
@@ -2732,7 +2750,7 @@ var getFlashLoanFees = async (query, assetNames) => {
2732
2750
  const flashloanFeesTableId = vault.fields.flash_loan_fees.fields.table.fields.id.id;
2733
2751
  const balanceSheetDynamicFields = await query.cache.queryGetDynamicFields({
2734
2752
  parentId: flashloanFeesTableId,
2735
- limit: 50
2753
+ limit: 10
2736
2754
  });
2737
2755
  const dynamicFieldObjectIds = balanceSheetDynamicFields?.data.filter((field) => {
2738
2756
  const assetType = field.name.value.name;
@@ -2899,15 +2917,17 @@ var getSpool = async (query, marketCoinName, indexer = false, marketPool, coinPr
2899
2917
  }
2900
2918
  return spool;
2901
2919
  };
2902
- var getStakeAccounts = async (query, ownerAddress) => {
2903
- const owner = ownerAddress || query.suiKit.currentAddress();
2904
- const spoolObjectId = query.address.get("spool.object");
2920
+ var getStakeAccounts = async ({
2921
+ utils
2922
+ }, ownerAddress) => {
2923
+ const owner = ownerAddress || utils.suiKit.currentAddress();
2924
+ const spoolObjectId = utils.address.get("spool.object");
2905
2925
  const stakeAccountType = `${spoolObjectId}::spool_account::SpoolAccount`;
2906
2926
  const stakeObjectsResponse = [];
2907
2927
  let hasNextPage = false;
2908
2928
  let nextCursor = null;
2909
2929
  do {
2910
- const paginatedStakeObjectsResponse = await query.cache.queryGetOwnedObjects({
2930
+ const paginatedStakeObjectsResponse = await utils.cache.queryGetOwnedObjects({
2911
2931
  owner,
2912
2932
  filter: { StructType: stakeAccountType },
2913
2933
  options: {
@@ -2939,15 +2959,15 @@ var getStakeAccounts = async (query, ownerAddress) => {
2939
2959
  };
2940
2960
  const stakeMarketCoinTypes = Object.keys(stakeAccounts).reduce(
2941
2961
  (types, stakeMarketCoinName) => {
2942
- const stakeCoinName = query.utils.parseCoinName(stakeMarketCoinName);
2943
- const marketCoinType = query.utils.parseMarketCoinType(stakeCoinName);
2962
+ const stakeCoinName = utils.parseCoinName(stakeMarketCoinName);
2963
+ const marketCoinType = utils.parseMarketCoinType(stakeCoinName);
2944
2964
  types[stakeMarketCoinName] = `${spoolObjectId}::spool_account::SpoolAccount<${marketCoinType}>`;
2945
2965
  return types;
2946
2966
  },
2947
2967
  {}
2948
2968
  );
2949
2969
  const stakeObjectIds = stakeObjectsResponse.map((ref) => ref?.data?.objectId).filter((id) => id !== void 0);
2950
- const stakeObjects = await query.cache.queryGetObjects(stakeObjectIds);
2970
+ const stakeObjects = await utils.cache.queryGetObjects(stakeObjectIds);
2951
2971
  for (const stakeObject of stakeObjects) {
2952
2972
  const id = stakeObject.objectId;
2953
2973
  const type = stakeObject.type;
@@ -3052,10 +3072,12 @@ var getStakeAccounts = async (query, ownerAddress) => {
3052
3072
  }
3053
3073
  return stakeAccounts;
3054
3074
  };
3055
- var getStakePool = async (query, marketCoinName) => {
3056
- const poolId = query.address.get(`spool.pools.${marketCoinName}.id`);
3075
+ var getStakePool = async ({
3076
+ utils
3077
+ }, marketCoinName) => {
3078
+ const poolId = utils.address.get(`spool.pools.${marketCoinName}.id`);
3057
3079
  let stakePool = void 0;
3058
- const stakePoolObjectResponse = await query.cache.queryGetObject(poolId, {
3080
+ const stakePoolObjectResponse = await utils.cache.queryGetObject(poolId, {
3059
3081
  showContent: true,
3060
3082
  showType: true
3061
3083
  });
@@ -3093,12 +3115,14 @@ var getStakePool = async (query, marketCoinName) => {
3093
3115
  }
3094
3116
  return stakePool;
3095
3117
  };
3096
- var getStakeRewardPool = async (query, marketCoinName) => {
3097
- const poolId = query.address.get(
3118
+ var getStakeRewardPool = async ({
3119
+ utils
3120
+ }, marketCoinName) => {
3121
+ const poolId = utils.address.get(
3098
3122
  `spool.pools.${marketCoinName}.rewardPoolId`
3099
3123
  );
3100
3124
  let stakeRewardPool = void 0;
3101
- const stakeRewardPoolObjectResponse = await query.cache.queryGetObject(
3125
+ const stakeRewardPoolObjectResponse = await utils.cache.queryGetObject(
3102
3126
  poolId,
3103
3127
  {
3104
3128
  showContent: true,
@@ -3226,24 +3250,26 @@ var queryBorrowIncentivePools = async (query, borrowIncentiveCoinNames, indexer
3226
3250
  }
3227
3251
  return borrowIncentivePools;
3228
3252
  };
3229
- var queryBorrowIncentiveAccounts = async (query, obligationId, borrowIncentiveCoinNames) => {
3253
+ var queryBorrowIncentiveAccounts = async ({
3254
+ utils
3255
+ }, obligationId, borrowIncentiveCoinNames) => {
3230
3256
  borrowIncentiveCoinNames = borrowIncentiveCoinNames || [
3231
3257
  ...SUPPORT_BORROW_INCENTIVE_POOLS
3232
3258
  ];
3233
- const queryPkgId = query.address.get("borrowIncentive.query");
3234
- const incentiveAccountsId = query.address.get(
3259
+ const queryPkgId = utils.address.get("borrowIncentive.query");
3260
+ const incentiveAccountsId = utils.address.get(
3235
3261
  "borrowIncentive.incentiveAccounts"
3236
3262
  );
3237
3263
  const queryTarget = `${queryPkgId}::incentive_account_query::incentive_account_data`;
3238
3264
  const args = [incentiveAccountsId, obligationId];
3239
- const queryResult = await query.cache.queryInspectTxn({ queryTarget, args });
3240
- const borrowIncentiveAccountsQueryData = queryResult?.events[0].parsedJson;
3265
+ const queryResult = await utils.cache.queryInspectTxn({ queryTarget, args });
3266
+ const borrowIncentiveAccountsQueryData = queryResult?.events[0]?.parsedJson;
3241
3267
  const borrowIncentiveAccounts = Object.values(
3242
3268
  borrowIncentiveAccountsQueryData?.pool_records ?? []
3243
3269
  ).reduce((accounts, accountData) => {
3244
3270
  const parsedBorrowIncentiveAccount = parseOriginBorrowIncentiveAccountData(accountData);
3245
3271
  const poolType = parsedBorrowIncentiveAccount.poolType;
3246
- const coinName = query.utils.parseCoinNameFromType(poolType);
3272
+ const coinName = utils.parseCoinNameFromType(poolType);
3247
3273
  if (borrowIncentiveCoinNames && borrowIncentiveCoinNames.includes(coinName)) {
3248
3274
  accounts[coinName] = parsedBorrowIncentiveAccount;
3249
3275
  }
@@ -3251,11 +3277,13 @@ var queryBorrowIncentiveAccounts = async (query, obligationId, borrowIncentiveCo
3251
3277
  }, {});
3252
3278
  return borrowIncentiveAccounts;
3253
3279
  };
3254
- var getBindedObligationId = async (query, veScaKeyId) => {
3255
- const borrowIncentiveObjectId = query.address.get("borrowIncentive.object");
3256
- const incentivePoolsId = query.address.get("borrowIncentive.incentivePools");
3257
- const veScaObjId = query.address.get("vesca.object");
3258
- const incentivePoolsResponse = await query.cache.queryGetObject(
3280
+ var getBindedObligationId = async ({
3281
+ address
3282
+ }, veScaKeyId) => {
3283
+ const borrowIncentiveObjectId = address.get("borrowIncentive.object");
3284
+ const incentivePoolsId = address.get("borrowIncentive.incentivePools");
3285
+ const veScaObjId = address.get("vesca.object");
3286
+ const incentivePoolsResponse = await address.cache.queryGetObject(
3259
3287
  incentivePoolsId,
3260
3288
  {
3261
3289
  showContent: true
@@ -3266,26 +3294,28 @@ var getBindedObligationId = async (query, veScaKeyId) => {
3266
3294
  const incentivePoolFields = incentivePoolsResponse.data.content.fields;
3267
3295
  const veScaBindTableId = incentivePoolFields.ve_sca_bind.fields.id.id;
3268
3296
  const keyType = `${borrowIncentiveObjectId}::typed_id::TypedID<${veScaObjId}::ve_sca::VeScaKey>`;
3269
- const veScaBindTableResponse = await query.cache.queryGetDynamicFieldObject({
3270
- parentId: veScaBindTableId,
3271
- name: {
3272
- type: keyType,
3273
- value: veScaKeyId
3297
+ const veScaBindTableResponse = await address.cache.queryGetDynamicFieldObject(
3298
+ {
3299
+ parentId: veScaBindTableId,
3300
+ name: {
3301
+ type: keyType,
3302
+ value: veScaKeyId
3303
+ }
3274
3304
  }
3275
- });
3305
+ );
3276
3306
  if (veScaBindTableResponse?.data?.content?.dataType !== "moveObject")
3277
3307
  return null;
3278
3308
  const veScaBindTableFields = veScaBindTableResponse.data.content.fields;
3279
3309
  const obligationId = veScaBindTableFields.value.fields.id;
3280
3310
  return obligationId;
3281
3311
  };
3282
- var getBindedVeScaKey = async (query, obliationId) => {
3283
- const borrowIncentiveObjectId = query.address.get("borrowIncentive.object");
3284
- const incentiveAccountsId = query.address.get(
3285
- "borrowIncentive.incentiveAccounts"
3286
- );
3287
- const corePkg = query.address.get("core.object");
3288
- const incentiveAccountsObject = await query.cache.queryGetObject(
3312
+ var getBindedVeScaKey = async ({
3313
+ address
3314
+ }, obliationId) => {
3315
+ const borrowIncentiveObjectId = address.get("borrowIncentive.object");
3316
+ const incentiveAccountsId = address.get("borrowIncentive.incentiveAccounts");
3317
+ const corePkg = address.get("core.object");
3318
+ const incentiveAccountsObject = await address.cache.queryGetObject(
3289
3319
  incentiveAccountsId,
3290
3320
  {
3291
3321
  showContent: true
@@ -3294,7 +3324,7 @@ var getBindedVeScaKey = async (query, obliationId) => {
3294
3324
  if (incentiveAccountsObject?.data?.content?.dataType !== "moveObject")
3295
3325
  return null;
3296
3326
  const incentiveAccountsTableId = incentiveAccountsObject.data.content.fields.accounts.fields.id.id;
3297
- const bindedIncentiveAcc = await query.cache.queryGetDynamicFieldObject({
3327
+ const bindedIncentiveAcc = await address.cache.queryGetDynamicFieldObject({
3298
3328
  parentId: incentiveAccountsTableId,
3299
3329
  name: {
3300
3330
  type: `${borrowIncentiveObjectId}::typed_id::TypedID<${corePkg}::obligation::Obligation>`,
@@ -3308,11 +3338,15 @@ var getBindedVeScaKey = async (query, obliationId) => {
3308
3338
  };
3309
3339
 
3310
3340
  // src/queries/priceQuery.ts
3311
- var getPythPrice = async (query, assetCoinName, priceFeedObject) => {
3312
- const pythFeedObjectId = query.address.get(
3341
+ var getPythPrice = async ({
3342
+ address
3343
+ }, assetCoinName, priceFeedObject) => {
3344
+ const pythFeedObjectId = address.get(
3313
3345
  `core.coins.${assetCoinName}.oracle.pyth.feedObject`
3314
3346
  );
3315
- priceFeedObject = priceFeedObject || (await query.cache.queryGetObject(pythFeedObjectId, { showContent: true }))?.data;
3347
+ priceFeedObject = priceFeedObject || (await address.cache.queryGetObject(pythFeedObjectId, {
3348
+ showContent: true
3349
+ }))?.data;
3316
3350
  if (priceFeedObject) {
3317
3351
  const priceFeedPoolObject = priceFeedObject;
3318
3352
  if (priceFeedPoolObject.content && "fields" in priceFeedPoolObject.content) {
@@ -3334,10 +3368,12 @@ var getPythPrice = async (query, assetCoinName, priceFeedObject) => {
3334
3368
  }
3335
3369
  return 0;
3336
3370
  };
3337
- var getPythPrices = async (query, assetCoinNames) => {
3371
+ var getPythPrices = async ({
3372
+ address
3373
+ }, assetCoinNames) => {
3338
3374
  const pythPriceFeedIds = assetCoinNames.reduce(
3339
3375
  (prev, assetCoinName) => {
3340
- const pythPriceFeed = query.address.get(
3376
+ const pythPriceFeed = address.get(
3341
3377
  `core.coins.${assetCoinName}.oracle.pyth.feedObject`
3342
3378
  );
3343
3379
  if (!prev[pythPriceFeed]) {
@@ -3349,7 +3385,7 @@ var getPythPrices = async (query, assetCoinNames) => {
3349
3385
  },
3350
3386
  {}
3351
3387
  );
3352
- const priceFeedObjects = await query.cache.queryGetObjects(
3388
+ const priceFeedObjects = await address.cache.queryGetObjects(
3353
3389
  Object.keys(pythPriceFeedIds),
3354
3390
  { showContent: true }
3355
3391
  );
@@ -3367,7 +3403,7 @@ var getPythPrices = async (query, assetCoinNames) => {
3367
3403
  async ([assetCoinName, priceFeedObject]) => ({
3368
3404
  coinName: assetCoinName,
3369
3405
  price: await getPythPrice(
3370
- query,
3406
+ { address },
3371
3407
  assetCoinName,
3372
3408
  priceFeedObject
3373
3409
  )
@@ -3384,8 +3420,7 @@ var getPythPrices = async (query, assetCoinNames) => {
3384
3420
 
3385
3421
  // src/queries/portfolioQuery.ts
3386
3422
  import BigNumber4 from "bignumber.js";
3387
- var getLendings = async (query, poolCoinNames, ownerAddress, indexer = false) => {
3388
- poolCoinNames = poolCoinNames || [...SUPPORT_POOLS];
3423
+ var getLendings = async (query, poolCoinNames = [...SUPPORT_POOLS], ownerAddress, indexer = false) => {
3389
3424
  const marketCoinNames = poolCoinNames.map(
3390
3425
  (poolCoinName) => query.utils.parseMarketCoinName(poolCoinName)
3391
3426
  );
@@ -3905,15 +3940,15 @@ import BigNumber5 from "bignumber.js";
3905
3940
  import { SUI_CLOCK_OBJECT_ID, SuiTxBlock as SuiTxBlock2 } from "@scallop-io/sui-kit";
3906
3941
  import { bcs } from "@mysten/sui.js/bcs";
3907
3942
  import { z as zod } from "zod";
3908
- var getVescaKeys = async (query, ownerAddress) => {
3909
- const owner = ownerAddress || query.suiKit.currentAddress();
3910
- const veScaObjId = query.address.get("vesca.object");
3943
+ var getVescaKeys = async (utils, ownerAddress) => {
3944
+ const owner = ownerAddress || utils.suiKit.currentAddress();
3945
+ const veScaObjId = utils.address.get("vesca.object");
3911
3946
  const veScaKeyType = `${veScaObjId}::ve_sca::VeScaKey`;
3912
3947
  const keyObjectsResponse = [];
3913
3948
  let hasNextPage = false;
3914
3949
  let nextCursor = null;
3915
3950
  do {
3916
- const paginatedKeyObjectsResponse = await query.cache.queryGetOwnedObjects({
3951
+ const paginatedKeyObjectsResponse = await utils.cache.queryGetOwnedObjects({
3917
3952
  owner,
3918
3953
  filter: {
3919
3954
  StructType: veScaKeyType
@@ -3933,11 +3968,13 @@ var getVescaKeys = async (query, ownerAddress) => {
3933
3968
  const keyObjectDatas = keyObjectsResponse.map((objResponse) => objResponse.data).filter((data) => !!data);
3934
3969
  return keyObjectDatas;
3935
3970
  };
3936
- var getVeScas = async (query, ownerAddress) => {
3937
- const keyObjectDatas = await getVescaKeys(query, ownerAddress);
3971
+ var getVeScas = async ({
3972
+ utils
3973
+ }, ownerAddress) => {
3974
+ const keyObjectDatas = await getVescaKeys(utils, ownerAddress);
3938
3975
  const veScas = Array(keyObjectDatas.length).fill(null);
3939
3976
  const tasks = keyObjectDatas.map(async (veScaKey, idx) => {
3940
- const veSca = await getVeSca(query, veScaKey);
3977
+ const veSca = await getVeSca(utils, veScaKey);
3941
3978
  if (veSca) {
3942
3979
  veScas[idx] = veSca;
3943
3980
  }
@@ -3950,16 +3987,16 @@ var SuiObjectRefZod = zod.object({
3950
3987
  digest: zod.string(),
3951
3988
  version: zod.string()
3952
3989
  });
3953
- var getVeSca = async (query, veScaKey, ownerAddress) => {
3954
- const tableId = query.address.get(`vesca.tableId`);
3955
- veScaKey = veScaKey || (await getVescaKeys(query, ownerAddress))[0];
3990
+ var getVeSca = async (utils, veScaKey, ownerAddress) => {
3991
+ const tableId = utils.address.get(`vesca.tableId`);
3992
+ veScaKey = veScaKey || (await getVescaKeys(utils, ownerAddress))[0];
3956
3993
  if (!veScaKey)
3957
3994
  return void 0;
3958
3995
  if (typeof veScaKey === "object") {
3959
3996
  veScaKey = SuiObjectRefZod.parse(veScaKey);
3960
3997
  }
3961
3998
  let vesca = void 0;
3962
- const veScaDynamicFieldObjectResponse = await query.cache.queryGetDynamicFieldObject({
3999
+ const veScaDynamicFieldObjectResponse = await utils.cache.queryGetDynamicFieldObject({
3963
4000
  parentId: tableId,
3964
4001
  name: {
3965
4002
  type: "0x2::object::ID",
@@ -3991,10 +4028,10 @@ var getVeSca = async (query, veScaKey, ownerAddress) => {
3991
4028
  }
3992
4029
  return vesca;
3993
4030
  };
3994
- var getTotalVeScaTreasuryAmount = async (query, veScaTreasury) => {
3995
- const veScaPkgId = query.address.get("vesca.id");
3996
- const veScaConfig = query.address.get("vesca.config");
3997
- veScaTreasury = veScaTreasury ?? query.address.get("vesca.treasury");
4031
+ var getTotalVeScaTreasuryAmount = async (utils, veScaTreasury) => {
4032
+ const veScaPkgId = utils.address.get("vesca.id");
4033
+ const veScaConfig = utils.address.get("vesca.config");
4034
+ veScaTreasury = veScaTreasury ?? utils.address.get("vesca.treasury");
3998
4035
  const refreshQueryTarget = `${veScaPkgId}::treasury::refresh`;
3999
4036
  const refreshArgs = [veScaConfig, veScaTreasury, SUI_CLOCK_OBJECT_ID];
4000
4037
  const veScaAmountQueryTarget = `${veScaPkgId}::treasury::total_ve_sca_amount`;
@@ -4002,7 +4039,7 @@ var getTotalVeScaTreasuryAmount = async (query, veScaTreasury) => {
4002
4039
  const resolvedRefreshArgs = await Promise.all(
4003
4040
  refreshArgs.map(async (arg) => {
4004
4041
  if (typeof arg === "string") {
4005
- return (await query.cache.queryGetObject(arg, { showContent: true }))?.data;
4042
+ return (await utils.cache.queryGetObject(arg, { showContent: true }))?.data;
4006
4043
  }
4007
4044
  return arg;
4008
4045
  })
@@ -4010,7 +4047,7 @@ var getTotalVeScaTreasuryAmount = async (query, veScaTreasury) => {
4010
4047
  const resolvedVeScaAmountArgs = await Promise.all(
4011
4048
  veScaAmountArgs.map(async (arg) => {
4012
4049
  if (typeof arg === "string") {
4013
- return (await query.cache.queryGetObject(arg, { showContent: true }))?.data;
4050
+ return (await utils.cache.queryGetObject(arg, { showContent: true }))?.data;
4014
4051
  }
4015
4052
  return arg;
4016
4053
  })
@@ -4019,17 +4056,16 @@ var getTotalVeScaTreasuryAmount = async (query, veScaTreasury) => {
4019
4056
  txb.moveCall(refreshQueryTarget, resolvedRefreshArgs);
4020
4057
  txb.moveCall(veScaAmountQueryTarget, resolvedVeScaAmountArgs);
4021
4058
  const txBytes = await txb.txBlock.build({
4022
- client: query.suiKit.client(),
4023
- onlyTransactionKind: true,
4024
- protocolConfig: await query.cache.getProtocolConfig() ?? void 0
4059
+ client: utils.suiKit.client(),
4060
+ onlyTransactionKind: true
4025
4061
  });
4026
- const res = await query.cache.queryClient.fetchQuery({
4062
+ const res = await utils.cache.queryClient.fetchQuery({
4027
4063
  queryKey: [
4028
4064
  "getTotalVeScaTreasuryAmount",
4029
4065
  JSON.stringify([...refreshArgs, ...veScaAmountArgs])
4030
4066
  ],
4031
4067
  queryFn: async () => {
4032
- return await query.suiKit.inspectTxn(txBytes);
4068
+ return await utils.suiKit.inspectTxn(txBytes);
4033
4069
  }
4034
4070
  });
4035
4071
  const results = res.results;
@@ -4040,9 +4076,9 @@ var getTotalVeScaTreasuryAmount = async (query, veScaTreasury) => {
4040
4076
  }
4041
4077
  return "0";
4042
4078
  };
4043
- var getVeScaTreasuryInfo = async (query) => {
4044
- const veScaTreasuryId = query.address.get("vesca.treasury");
4045
- const veScaTreasury = await query.cache.queryGetObject(veScaTreasuryId, {
4079
+ var getVeScaTreasuryInfo = async (utils) => {
4080
+ const veScaTreasuryId = utils.address.get("vesca.treasury");
4081
+ const veScaTreasury = await utils.cache.queryGetObject(veScaTreasuryId, {
4046
4082
  showContent: true
4047
4083
  });
4048
4084
  if (!veScaTreasury || veScaTreasury.data?.content?.dataType !== "moveObject")
@@ -4052,7 +4088,7 @@ var getVeScaTreasuryInfo = async (query) => {
4052
4088
  treasuryFields.unlock_schedule.fields.locked_sca_amount
4053
4089
  ).shiftedBy(-9).toNumber();
4054
4090
  const totalVeSca = BigNumber5(
4055
- await getTotalVeScaTreasuryAmount(query, veScaTreasury.data) ?? 0
4091
+ await getTotalVeScaTreasuryAmount(utils, veScaTreasury.data) ?? 0
4056
4092
  ).shiftedBy(-9).toNumber();
4057
4093
  const averageLockingPeriod = totalLockedSca > 0 ? totalVeSca / totalLockedSca * 4 : 0;
4058
4094
  const averageLockingPeriodUnit = "year";
@@ -4065,9 +4101,9 @@ var getVeScaTreasuryInfo = async (query) => {
4065
4101
  };
4066
4102
 
4067
4103
  // src/queries/referralQuery.ts
4068
- var queryVeScaKeyIdFromReferralBindings = async (query, refereeAddress) => {
4069
- const referralBindingTableId = query.address.get("referral.bindingTableId");
4070
- const referralBindResponse = await query.cache.queryGetDynamicFieldObject({
4104
+ var queryVeScaKeyIdFromReferralBindings = async (address, refereeAddress) => {
4105
+ const referralBindingTableId = address.get("referral.bindingTableId");
4106
+ const referralBindResponse = await address.cache.queryGetDynamicFieldObject({
4071
4107
  parentId: referralBindingTableId,
4072
4108
  name: {
4073
4109
  type: "address",
@@ -4131,1235 +4167,566 @@ var getLoyaltyProgramInformations = async (query, veScaKey) => {
4131
4167
  return result;
4132
4168
  };
4133
4169
 
4134
- // src/models/scallopIndexer.ts
4135
- import axios2 from "axios";
4136
- var ScallopIndexer = class {
4170
+ // src/constants/pyth.ts
4171
+ var PYTH_ENDPOINTS = {
4172
+ testnet: ["https://hermes-beta.pyth.network"],
4173
+ mainnet: ["https://hermes.pyth.network", "https://scallop.rpc.p2p.world"]
4174
+ };
4175
+
4176
+ // src/models/scallopUtils.ts
4177
+ var ScallopUtils = class {
4137
4178
  constructor(params, instance) {
4138
- this.params = params;
4139
- this._cache = instance?.cache ?? new ScallopCache();
4140
- this._requestClient = axios2.create({
4141
- baseURL: SDK_API_BASE_URL,
4142
- headers: {
4143
- "Content-Type": "application/json",
4144
- Accept: "application/json"
4145
- },
4146
- timeout: 3e4
4147
- });
4148
- }
4149
- /**
4150
- * Get market index data.
4151
- *
4152
- * @return Market data.
4153
- */
4154
- async getMarket() {
4155
- const response = await this._cache.queryClient.fetchQuery({
4156
- queryKey: ["market"],
4157
- queryFn: async () => {
4158
- return await this._requestClient.get(`/api/market`);
4159
- }
4160
- });
4161
- if (response.status === 200) {
4162
- return {
4163
- pools: response.data.pools.reduce((marketPools, marketPool) => {
4164
- marketPools[marketPool.coinName] = marketPool;
4165
- return marketPools;
4166
- }, {}),
4167
- collaterals: response.data.collaterals.reduce(
4168
- (marketCollaterals, marketCollateral) => {
4169
- marketCollaterals[marketCollateral.coinName] = marketCollateral;
4170
- return marketCollaterals;
4171
- },
4172
- {}
4173
- )
4174
- };
4179
+ this._priceMap = /* @__PURE__ */ new Map();
4180
+ /**
4181
+ * Get reward type of spool.
4182
+ *
4183
+ * @param stakeMarketCoinName - Support stake market coin.
4184
+ * @return Spool reward coin name.
4185
+ */
4186
+ this.getSpoolRewardCoinName = (stakeMarketCoinName) => {
4187
+ return spoolRewardCoins[stakeMarketCoinName];
4188
+ };
4189
+ /**
4190
+ * Get reward type of borrow incentive pool.
4191
+ *
4192
+ * @param borrowIncentiveCoinName - Support borrow incentive coin.
4193
+ * @return Borrow incentive reward coin name.
4194
+ */
4195
+ this.getBorrowIncentiveRewardCoinName = (borrowIncentiveCoinName) => {
4196
+ return borrowIncentiveRewardCoins[borrowIncentiveCoinName];
4197
+ };
4198
+ this.params = {
4199
+ pythEndpoints: params.pythEndpoints ?? PYTH_ENDPOINTS["mainnet"],
4200
+ ...params
4201
+ };
4202
+ this.suiKit = instance?.suiKit ?? instance?.address?.cache._suiKit ?? new SuiKit2(params);
4203
+ if (instance?.address) {
4204
+ this.address = instance.address;
4205
+ this.cache = this.address.cache;
4206
+ this.suiKit = this.address.cache._suiKit;
4175
4207
  } else {
4176
- throw Error("Failed to getMarket.");
4208
+ this.cache = new ScallopCache(this.suiKit, DEFAULT_CACHE_OPTIONS);
4209
+ this.address = instance?.address ?? new ScallopAddress(
4210
+ {
4211
+ id: params?.addressesId || ADDRESSES_ID,
4212
+ network: params?.networkType
4213
+ },
4214
+ {
4215
+ cache: this.cache
4216
+ }
4217
+ );
4177
4218
  }
4219
+ this.isTestnet = params.networkType ? params.networkType === "testnet" : false;
4178
4220
  }
4179
4221
  /**
4180
- * Get market pools index data.
4222
+ * Request the scallop API to initialize data.
4181
4223
  *
4182
- * @return Market pools data.
4224
+ * @param force - Whether to force initialization.
4225
+ * @param address - ScallopAddress instance.
4183
4226
  */
4184
- async getMarketPools() {
4185
- const response = (await this.getMarket()).pools;
4186
- return response;
4227
+ async init(force = false, address) {
4228
+ if (force || !this.address.getAddresses() || !address?.getAddresses()) {
4229
+ await this.address.read();
4230
+ } else {
4231
+ this.address = address;
4232
+ }
4187
4233
  }
4188
4234
  /**
4189
- * Get market pool index data.
4235
+ * Convert coin name to symbol.
4190
4236
  *
4191
- * @return Market pool data.
4237
+ * @param coinName - Specific support coin name.
4238
+ * @return Symbol string.
4192
4239
  */
4193
- async getMarketPool(poolCoinName) {
4194
- return (await this.getMarketPools())[poolCoinName];
4240
+ parseSymbol(coinName) {
4241
+ if (isMarketCoin(coinName)) {
4242
+ const assetCoinName = coinName.slice(1).toLowerCase();
4243
+ return coinName.slice(0, 1).toLowerCase() + parseAssetSymbol(assetCoinName);
4244
+ } else {
4245
+ return parseAssetSymbol(coinName);
4246
+ }
4195
4247
  }
4196
4248
  /**
4197
- * Get market collaterals index data.
4249
+ * Convert coin name to coin type.
4198
4250
  *
4199
- * @return Market collaterals data.
4200
- */
4201
- async getMarketCollaterals() {
4202
- return (await this.getMarket()).collaterals;
4203
- }
4204
- /**
4205
- * Get market collateral index data.
4251
+ * @description
4252
+ * The Coin type of wormhole is fixed `coin:Coin`. Here using package id
4253
+ * to determine and return the type.
4206
4254
  *
4207
- * @return Market collateral data.
4255
+ * @param coinPackageId - Package id of coin.
4256
+ * @param coinName - Specific support coin name.
4257
+ * @return Coin type.
4208
4258
  */
4209
- async getMarketCollateral(collateralCoinName) {
4210
- return (await this.getMarketCollaterals())[collateralCoinName];
4259
+ parseCoinType(coinName) {
4260
+ coinName = isMarketCoin(coinName) ? this.parseCoinName(coinName) : coinName;
4261
+ const coinPackageId = this.address.get(`core.coins.${coinName}.id`) || coinIds[coinName] || void 0;
4262
+ if (!coinPackageId) {
4263
+ throw Error(`Coin ${coinName} is not supported`);
4264
+ }
4265
+ if (coinName === "sui")
4266
+ return normalizeStructTag6(`${coinPackageId}::sui::SUI`);
4267
+ const wormHolePackageIds = [
4268
+ this.address.get("core.coins.usdc.id") ?? wormholeCoinIds.usdc,
4269
+ this.address.get("core.coins.usdt.id") ?? wormholeCoinIds.usdt,
4270
+ this.address.get("core.coins.eth.id") ?? wormholeCoinIds.eth,
4271
+ this.address.get("core.coins.btc.id") ?? wormholeCoinIds.btc,
4272
+ this.address.get("core.coins.sol.id") ?? wormholeCoinIds.sol,
4273
+ this.address.get("core.coins.apt.id") ?? wormholeCoinIds.apt
4274
+ ];
4275
+ const voloPackageIds = [
4276
+ this.address.get("core.coins.vsui.id") ?? voloCoinIds.vsui
4277
+ ];
4278
+ if (wormHolePackageIds.includes(coinPackageId)) {
4279
+ return `${coinPackageId}::coin::COIN`;
4280
+ } else if (voloPackageIds.includes(coinPackageId)) {
4281
+ return `${coinPackageId}::cert::CERT`;
4282
+ } else {
4283
+ return `${coinPackageId}::${coinName}::${coinName.toUpperCase()}`;
4284
+ }
4211
4285
  }
4212
4286
  /**
4213
- * Get spools index data.
4287
+ * Convert coin name to sCoin name.
4214
4288
  *
4215
- * @return Spools data.
4289
+ * @param coinName - Specific support coin name.
4290
+ * @return sCoin name.
4216
4291
  */
4217
- async getSpools() {
4218
- const response = await this._cache.queryClient.fetchQuery({
4219
- queryKey: ["spools"],
4220
- queryFn: async () => {
4221
- return await this._requestClient.get(`/api/spools`);
4222
- }
4223
- });
4224
- if (response.status === 200) {
4225
- return response.data.spools.reduce((spools, spool) => {
4226
- spools[spool.marketCoinName] = spool;
4227
- return spools;
4228
- }, {});
4292
+ parseSCoinName(coinName) {
4293
+ if (isMarketCoin(coinName) && SUPPORT_SCOIN.includes(coinName)) {
4294
+ return coinName;
4229
4295
  } else {
4230
- throw Error("Failed to getSpools.");
4296
+ const marketCoinName = `s${coinName}`;
4297
+ if (SUPPORT_SCOIN.includes(marketCoinName)) {
4298
+ return marketCoinName;
4299
+ }
4300
+ return void 0;
4231
4301
  }
4232
4302
  }
4233
4303
  /**
4234
- * Get spool index data.
4235
- *
4236
- * @return Spool data.
4304
+ * Convert sCoin name into sCoin type
4305
+ * @param sCoinName
4306
+ * @returns sCoin type
4237
4307
  */
4238
- async getSpool(marketCoinName) {
4239
- return (await this.getSpools())[marketCoinName];
4308
+ parseSCoinType(sCoinName) {
4309
+ return sCoinIds[sCoinName];
4240
4310
  }
4241
4311
  /**
4242
- * Get borrow incentive pools index data.
4243
- *
4244
- * @return Borrow incentive pools data.
4312
+ * Convert sCoin name into its underlying coin type
4313
+ * @param sCoinName
4314
+ * @returns coin type
4245
4315
  */
4246
- async getBorrowIncentivePools() {
4247
- const response = await this._cache.queryClient.fetchQuery({
4248
- queryKey: ["borrowIncentivePools"],
4249
- queryFn: async () => {
4250
- return await this._requestClient.get(`/api/borrowIncentivePools`);
4251
- }
4252
- });
4253
- if (response.status === 200) {
4254
- return response.data.borrowIncentivePools.reduce(
4255
- (borrowIncentivePools, borrowIncentivePool) => {
4256
- if (Array.isArray(borrowIncentivePool.points)) {
4257
- borrowIncentivePool.points = borrowIncentivePool.points.reduce(
4258
- (prev, curr) => {
4259
- prev[curr.coinName] = curr;
4260
- return prev;
4261
- },
4262
- {}
4263
- );
4264
- }
4265
- borrowIncentivePools[borrowIncentivePool.coinName] = borrowIncentivePool;
4266
- return borrowIncentivePools;
4267
- },
4268
- {}
4269
- );
4270
- } else {
4271
- throw Error("Failed to getBorrowIncentivePools.");
4272
- }
4316
+ parseUnderlyingSCoinType(sCoinName) {
4317
+ const coinName = this.parseCoinName(sCoinName);
4318
+ return this.parseCoinType(coinName);
4273
4319
  }
4274
4320
  /**
4275
- * Get borrow incentive pool index data.
4276
- *
4277
- * @return Borrow incentive pool data.
4321
+ * Get sCoin treasury id from sCoin name
4322
+ * @param sCoinName
4323
+ * @returns sCoin treasury id
4278
4324
  */
4279
- async getBorrowIncentivePool(borrowIncentiveCoinName) {
4280
- return (await this.getBorrowIncentivePools())[borrowIncentiveCoinName];
4325
+ getSCoinTreasury(sCoinName) {
4326
+ return this.address.get(`scoin.coins.${sCoinName}.treasury`);
4281
4327
  }
4282
4328
  /**
4283
- * Get total value locked index data.
4329
+ * Convert coin name to market coin type.
4284
4330
  *
4285
- * @return Total value locked.
4331
+ * @param coinPackageId - Package id of coin.
4332
+ * @param coinName - Specific support coin name.
4333
+ * @return Market coin type.
4286
4334
  */
4287
- async getTotalValueLocked() {
4288
- const response = await this._cache.queryClient.fetchQuery({
4289
- queryKey: ["totalValueLocked"],
4290
- queryFn: async () => {
4291
- return await this._requestClient.get(`/api/market/tvl`);
4292
- }
4293
- });
4294
- if (response.status === 200) {
4295
- return response.data;
4296
- } else {
4297
- throw Error("Failed to getTotalValueLocked.");
4298
- }
4299
- }
4300
- };
4301
-
4302
- // src/queries/sCoinQuery.ts
4303
- import { bcs as bcs2 } from "@mysten/sui.js/bcs";
4304
- import assert from "assert";
4305
- import BigNumber7 from "bignumber.js";
4306
- var getSCoinTotalSupply = async (query, sCoinName) => {
4307
- const sCoinPkgId = query.address.get("scoin.id");
4308
- const args = [query.utils.getSCoinTreasury(sCoinName)];
4309
- const typeArgs = [
4310
- query.utils.parseSCoinType(sCoinName),
4311
- query.utils.parseUnderlyingSCoinType(sCoinName)
4312
- ];
4313
- const queryTarget = `${sCoinPkgId}::s_coin_converter::total_supply`;
4314
- const queryResults = await query.cache.queryInspectTxn({
4315
- queryTarget,
4316
- args,
4317
- typeArgs
4318
- });
4319
- const results = queryResults?.results;
4320
- if (results && results[0].returnValues) {
4321
- const value = Uint8Array.from(results[0].returnValues[0][0]);
4322
- const type = results[0].returnValues[0][1];
4323
- assert(type === "u64", "Result type is not u64");
4324
- return BigNumber7(bcs2.de(type, value)).shiftedBy(
4325
- query.utils.getCoinDecimal(query.utils.parseCoinName(sCoinName))
4326
- ).toNumber();
4327
- }
4328
- return 0;
4329
- };
4330
- var getSCoinAmounts = async (query, sCoinNames, ownerAddress) => {
4331
- sCoinNames = sCoinNames || [...SUPPORT_SCOIN];
4332
- const owner = ownerAddress || query.suiKit.currentAddress();
4333
- const sCoins2 = {};
4334
- await Promise.allSettled(
4335
- sCoinNames.map(async (sCoinName) => {
4336
- const sCoin = await getSCoinAmount(query, sCoinName, owner);
4337
- sCoins2[sCoinName] = sCoin;
4338
- })
4339
- );
4340
- return sCoins2;
4341
- };
4342
- var getSCoinAmount = async (query, sCoinName, ownerAddress) => {
4343
- const owner = ownerAddress || query.suiKit.currentAddress();
4344
- const sCoinType = query.utils.parseSCoinType(sCoinName);
4345
- const amount = await query.cache.queryGetCoinBalance({
4346
- owner,
4347
- coinType: sCoinType
4348
- });
4349
- return BigNumber7(amount).toNumber();
4350
- };
4351
-
4352
- // src/models/scallopQuery.ts
4353
- import { normalizeSuiAddress as normalizeSuiAddress2 } from "@mysten/sui.js/utils";
4354
- var ScallopQuery = class {
4355
- constructor(params, instance) {
4356
- this.params = params;
4357
- this.suiKit = instance?.suiKit ?? new SuiKit(params);
4358
- this.cache = instance?.cache ?? new ScallopCache(DEFAULT_CACHE_OPTIONS, this.suiKit);
4359
- this.address = instance?.address ?? new ScallopAddress(
4360
- {
4361
- id: params?.addressesId || ADDRESSES_ID,
4362
- network: params?.networkType
4363
- },
4364
- this.cache
4365
- );
4366
- this.utils = instance?.utils ?? new ScallopUtils(this.params, {
4367
- suiKit: this.suiKit,
4368
- address: this.address,
4369
- cache: this.cache,
4370
- query: this
4371
- });
4372
- this.indexer = new ScallopIndexer(this.params, { cache: this.cache });
4373
- this.walletAddress = normalizeSuiAddress2(
4374
- params?.walletAddress || this.suiKit.currentAddress()
4375
- );
4376
- }
4377
- /**
4378
- * Request the scallop API to initialize data.
4379
- *
4380
- * @param force - Whether to force initialization.
4381
- * @param address - ScallopAddress instance.
4382
- */
4383
- async init(force = false, address) {
4384
- if (force || !this.address.getAddresses() || !address?.getAddresses()) {
4385
- await this.address.read();
4386
- } else {
4387
- this.address = address;
4388
- }
4389
- await this.utils.init(force, this.address);
4390
- }
4391
- /* ==================== Core Query Methods ==================== */
4392
- /**
4393
- * Query market data.
4394
- * @param indexer - Whether to use indexer.
4395
- * @return Market data.
4396
- */
4397
- async queryMarket(indexer = false) {
4398
- return await queryMarket(this, indexer);
4335
+ parseMarketCoinType(coinName) {
4336
+ const protocolObjectId = this.address.get("core.object") || PROTOCOL_OBJECT_ID;
4337
+ const coinType = this.parseCoinType(coinName);
4338
+ return `${protocolObjectId}::reserve::MarketCoin<${coinType}>`;
4399
4339
  }
4400
- /**
4401
- * Get market pools.
4402
- *
4403
- * @description
4404
- * To obtain all market pools at once, it is recommended to use
4405
- * the `queryMarket` method to reduce time consumption.
4406
- *
4407
- * @param poolCoinNames - Specific an array of support pool coin name.
4408
- * @param indexer - Whether to use indexer.
4409
- * @return Market pools data.
4410
- */
4411
- async getMarketPools(poolCoinNames, indexer = false) {
4412
- return await getMarketPools(this, poolCoinNames, indexer);
4340
+ parseCoinNameFromType(coinType) {
4341
+ coinType = normalizeStructTag6(coinType);
4342
+ const coinTypeRegex = new RegExp(`((0x[^:]+::[^:]+::[^<>]+))(?![^<>]*<)`);
4343
+ const coinTypeMatch = coinType.match(coinTypeRegex);
4344
+ const isMarketCoinType = coinType.includes("reserve::MarketCoin");
4345
+ coinType = coinTypeMatch?.[1] || coinType;
4346
+ const wormHoleCoinTypeMap = {
4347
+ [`${this.address.get("core.coins.usdc.id") ?? wormholeCoinIds.usdc}::coin::COIN`]: "usdc",
4348
+ [`${this.address.get("core.coins.usdt.id") ?? wormholeCoinIds.usdt}::coin::COIN`]: "usdt",
4349
+ [`${this.address.get("core.coins.eth.id") ?? wormholeCoinIds.eth}::coin::COIN`]: "eth",
4350
+ [`${this.address.get("core.coins.btc.id") ?? wormholeCoinIds.btc}::coin::COIN`]: "btc",
4351
+ [`${this.address.get("core.coins.sol.id") ?? wormholeCoinIds.sol}::coin::COIN`]: "sol",
4352
+ [`${this.address.get("core.coins.apt.id") ?? wormholeCoinIds.apt}::coin::COIN`]: "apt"
4353
+ };
4354
+ const voloCoinTypeMap = {
4355
+ [`${this.address.get("core.coins.vsui.id") ?? voloCoinIds.vsui}::cert::CERT`]: "vsui"
4356
+ };
4357
+ const assetCoinName = wormHoleCoinTypeMap[coinType] || voloCoinTypeMap[coinType] || coinType.split("::")[2].toLowerCase();
4358
+ return isMarketCoinType ? this.parseMarketCoinName(assetCoinName) : assetCoinName;
4413
4359
  }
4414
4360
  /**
4415
- * Get market pool
4361
+ * Convert marke coin name to coin name.
4416
4362
  *
4417
- * @param poolCoinName - Specific support pool coin name.
4418
- * @param indexer - Whether to use indexer.
4419
- * @return Market pool data.
4363
+ * @param marketCoinName - Specific support market coin name.
4364
+ * @return Coin Name.
4420
4365
  */
4421
- async getMarketPool(poolCoinName, indexer = false) {
4422
- return await getMarketPool(this, poolCoinName, indexer);
4366
+ parseCoinName(marketCoinName) {
4367
+ return marketCoinName.slice(1);
4423
4368
  }
4424
4369
  /**
4425
- * Get market collaterals.
4426
- *
4427
- * @description
4428
- * To obtain all market collaterals at once, it is recommended to use
4429
- * the `queryMarket` method to reduce time consumption.
4370
+ * Convert coin name to market coin name.
4430
4371
  *
4431
- * @param collateralCoinNames - Specific an array of support collateral coin name.
4432
- * @param indexer - Whether to use indexer.
4433
- * @return Market collaterals data.
4372
+ * @param coinName - Specific support coin name.
4373
+ * @return Market coin name.
4434
4374
  */
4435
- async getMarketCollaterals(collateralCoinNames, indexer = false) {
4436
- return await getMarketCollaterals(this, collateralCoinNames, indexer);
4375
+ parseMarketCoinName(coinName) {
4376
+ return `s${coinName}`;
4437
4377
  }
4438
4378
  /**
4439
- * Get market collateral
4379
+ * Get coin decimal.
4440
4380
  *
4441
- * @param collateralCoinName - Specific support collateral coin name.
4442
- * @param indexer - Whether to use indexer.
4443
- * @return Market collateral data.
4381
+ * return Coin decimal.
4444
4382
  */
4445
- async getMarketCollateral(collateralCoinName, indexer = false) {
4446
- return await getMarketCollateral(this, collateralCoinName, indexer);
4383
+ getCoinDecimal(coinName) {
4384
+ return coinDecimals[coinName];
4447
4385
  }
4448
4386
  /**
4449
- * Get obligations data.
4387
+ * Get coin wrapped type.
4450
4388
  *
4451
- * @param ownerAddress - The owner address.
4452
- * @return Obligations data.
4389
+ * return Coin wrapped type.
4453
4390
  */
4454
- async getObligations(ownerAddress = this.walletAddress) {
4455
- return await getObligations(this, ownerAddress);
4391
+ getCoinWrappedType(assetCoinName) {
4392
+ return assetCoinName === "usdc" || assetCoinName === "usdt" || assetCoinName === "eth" || assetCoinName === "btc" || assetCoinName === "apt" || assetCoinName === "sol" ? {
4393
+ from: "Wormhole",
4394
+ type: "Portal from Ethereum"
4395
+ } : void 0;
4456
4396
  }
4457
4397
  /**
4458
- * Query obligation data.
4398
+ * Select coin id that add up to the given amount as transaction arguments.
4459
4399
  *
4460
- * @param obligationId - The obligation id.
4461
- * @return Obligation data.
4400
+ * @param ownerAddress - The address of the owner.
4401
+ * @param amount - The amount that including coin decimals.
4402
+ * @param coinType - The coin type, default is 0x2::SUI::SUI.
4403
+ * @return The selected transaction coin arguments.
4462
4404
  */
4463
- async queryObligation(obligationId) {
4464
- return queryObligation(this, obligationId);
4405
+ async selectCoins(amount, coinType = SUI_TYPE_ARG, ownerAddress) {
4406
+ ownerAddress = ownerAddress || this.suiKit.currentAddress();
4407
+ const coins = await this.suiKit.suiInteractor.selectCoins(
4408
+ ownerAddress,
4409
+ amount,
4410
+ coinType
4411
+ );
4412
+ return coins;
4465
4413
  }
4466
4414
  /**
4467
- * Get all asset coin amounts.
4468
- *
4469
- * @param assetCoinNames - Specific an array of support asset coin name.
4470
- * @param ownerAddress - The owner address.
4471
- * @return All coin amounts.
4415
+ * Merge coins with type `coinType` to dest
4416
+ * @param txBlock
4417
+ * @param dest
4418
+ * @param coinType
4419
+ * @param sender
4472
4420
  */
4473
- async getCoinAmounts(assetCoinNames, ownerAddress = this.walletAddress) {
4474
- return await getCoinAmounts(this, assetCoinNames, ownerAddress);
4421
+ async mergeSimilarCoins(txBlock, dest, coinType, sender) {
4422
+ try {
4423
+ const existingCoins = await this.selectCoins(
4424
+ Number.MAX_SAFE_INTEGER,
4425
+ coinType,
4426
+ sender
4427
+ );
4428
+ if (existingCoins.length > 0) {
4429
+ txBlock.mergeCoins(dest, existingCoins.slice(0, 500));
4430
+ }
4431
+ } catch (e) {
4432
+ }
4475
4433
  }
4476
4434
  /**
4477
- * Get asset coin amount.
4435
+ * Get all asset coin names in the obligation record by obligation id.
4478
4436
  *
4479
- * @param assetCoinName - Specific support asset coin name.
4480
- * @param ownerAddress - The owner address.
4481
- * @return Coin amount.
4482
- */
4483
- async getCoinAmount(assetCoinName, ownerAddress = this.walletAddress) {
4484
- return await getCoinAmount(this, assetCoinName, ownerAddress);
4485
- }
4486
- /**
4487
- * Get all market coin amounts.
4437
+ * @description
4438
+ * This can often be used to determine which assets in an obligation require
4439
+ * price updates before interacting with specific instructions of the Scallop contract.
4488
4440
  *
4489
- * @param coinNames - Specific an array of support market coin name.
4490
- * @param ownerAddress - The owner address.
4491
- * @return All market market coin amounts.
4441
+ * @param obligationId - The obligation id.
4442
+ * @return Asset coin Names.
4492
4443
  */
4493
- async getMarketCoinAmounts(marketCoinNames, ownerAddress = this.walletAddress) {
4494
- return await getMarketCoinAmounts(this, marketCoinNames, ownerAddress);
4444
+ async getObligationCoinNames(obligationId) {
4445
+ const obligation = await queryObligation(this, obligationId);
4446
+ if (!obligation)
4447
+ return void 0;
4448
+ const collateralCoinTypes = obligation.collaterals.map((collateral) => {
4449
+ return `0x${collateral.type.name}`;
4450
+ });
4451
+ const debtCoinTypes = obligation.debts.map((debt) => {
4452
+ return `0x${debt.type.name}`;
4453
+ });
4454
+ const obligationCoinTypes = [
4455
+ .../* @__PURE__ */ new Set([...collateralCoinTypes, ...debtCoinTypes])
4456
+ ];
4457
+ const obligationCoinNames = obligationCoinTypes.map((coinType) => {
4458
+ return this.parseCoinNameFromType(coinType);
4459
+ });
4460
+ return obligationCoinNames;
4495
4461
  }
4496
4462
  /**
4497
- * Get market coin amount.
4463
+ * Get asset coin price.
4498
4464
  *
4499
- * @param coinNames - Specific support market coin name.
4500
- * @param ownerAddress - The owner address.
4501
- * @return Market market coin amount.
4502
- */
4503
- async getMarketCoinAmount(marketCoinName, ownerAddress = this.walletAddress) {
4504
- return await getMarketCoinAmount(this, marketCoinName, ownerAddress);
4505
- }
4506
- /**
4507
- * Get price from pyth fee object.
4465
+ * @description
4466
+ * The strategy for obtaining the price is to get it through API first,
4467
+ * and then on-chain data if API cannot be retrieved.
4468
+ * Currently, we only support obtaining from pyth protocol, other
4469
+ * oracles will be supported in the future.
4508
4470
  *
4509
- * @param assetCoinName - Specific support asset coin name.
4510
- * @return Asset coin price.
4471
+ * @param assetCoinNames - Specific an array of support asset coin name.
4472
+ * @return Asset coin price.
4511
4473
  */
4512
- async getPriceFromPyth(assetCoinName) {
4513
- return await getPythPrice(this, assetCoinName);
4514
- }
4515
- /**
4516
- * Get prices from pyth fee object.
4517
- *
4518
- * @param assetCoinNames - Array of supported asset coin names.
4519
- * @return Array of asset coin prices.
4520
- */
4521
- async getPricesFromPyth(assetCoinNames) {
4522
- return await getPythPrices(this, assetCoinNames);
4523
- }
4524
- /* ==================== Spool Query Methods ==================== */
4525
- /**
4526
- * Get spools data.
4527
- *
4528
- * @param stakeMarketCoinNames - Specific an array of support stake market coin name.
4529
- * @param indexer - Whether to use indexer.
4530
- * @return Spools data.
4531
- */
4532
- async getSpools(stakeMarketCoinNames, indexer = false) {
4533
- return await getSpools(this, stakeMarketCoinNames, indexer);
4534
- }
4535
- /**
4536
- * Get spool data.
4537
- *
4538
- * @param stakeMarketCoinName - Specific support stake market coin name.
4539
- * @param indexer - Whether to use indexer.
4540
- * @return Spool data.
4541
- */
4542
- async getSpool(stakeMarketCoinName, indexer = false) {
4543
- return await getSpool(this, stakeMarketCoinName, indexer);
4474
+ async getCoinPrices(assetCoinNames) {
4475
+ assetCoinNames = assetCoinNames || [
4476
+ .../* @__PURE__ */ new Set([...SUPPORT_POOLS, ...SUPPORT_COLLATERALS])
4477
+ ];
4478
+ const coinPrices = {};
4479
+ const existPricesCoinNames = [];
4480
+ const lackPricesCoinNames = [];
4481
+ assetCoinNames.forEach((assetCoinName) => {
4482
+ if (this._priceMap.has(assetCoinName) && Date.now() - this._priceMap.get(assetCoinName).publishTime < 1e3 * 60) {
4483
+ existPricesCoinNames.push(assetCoinName);
4484
+ } else {
4485
+ lackPricesCoinNames.push(assetCoinName);
4486
+ }
4487
+ });
4488
+ if (existPricesCoinNames.length > 0) {
4489
+ for (const coinName of existPricesCoinNames) {
4490
+ coinPrices[coinName] = this._priceMap.get(coinName).price;
4491
+ }
4492
+ }
4493
+ if (lackPricesCoinNames.length > 0) {
4494
+ const endpoints = this.params.pythEndpoints ?? PYTH_ENDPOINTS[this.isTestnet ? "testnet" : "mainnet"];
4495
+ const failedRequests = new Set(
4496
+ lackPricesCoinNames
4497
+ );
4498
+ for (const endpoint of endpoints) {
4499
+ const priceIds = Array.from(failedRequests.values()).reduce(
4500
+ (acc, coinName) => {
4501
+ const priceId = this.address.get(
4502
+ `core.coins.${coinName}.oracle.pyth.feed`
4503
+ );
4504
+ acc[coinName] = priceId;
4505
+ return acc;
4506
+ },
4507
+ {}
4508
+ );
4509
+ await Promise.allSettled(
4510
+ Object.entries(priceIds).map(async ([coinName, priceId]) => {
4511
+ const pythConnection = new SuiPriceServiceConnection(endpoint);
4512
+ try {
4513
+ const feed = await this.address.cache.queryClient.fetchQuery({
4514
+ queryKey: [priceId],
4515
+ queryFn: async () => {
4516
+ return await pythConnection.getLatestPriceFeeds([priceId]);
4517
+ }
4518
+ });
4519
+ if (feed) {
4520
+ const data = parseDataFromPythPriceFeed(feed[0], this.address);
4521
+ this._priceMap.set(coinName, {
4522
+ price: data.price,
4523
+ publishTime: data.publishTime
4524
+ });
4525
+ coinPrices[coinName] = data.price;
4526
+ }
4527
+ failedRequests.delete(coinName);
4528
+ } catch (e) {
4529
+ console.warn(
4530
+ `Failed to get price ${coinName} feeds with endpoint ${endpoint}: ${e}`
4531
+ );
4532
+ }
4533
+ })
4534
+ );
4535
+ if (failedRequests.size === 0)
4536
+ break;
4537
+ }
4538
+ if (failedRequests.size > 0) {
4539
+ await Promise.allSettled(
4540
+ Array.from(failedRequests.values()).map(async (coinName) => {
4541
+ const price = await getPythPrice(this, coinName);
4542
+ this._priceMap.set(coinName, {
4543
+ price,
4544
+ publishTime: Date.now()
4545
+ });
4546
+ coinPrices[coinName] = price;
4547
+ })
4548
+ );
4549
+ }
4550
+ }
4551
+ return coinPrices;
4544
4552
  }
4545
4553
  /**
4546
- * Get stake accounts data for all stake pools (spools).
4554
+ * Convert apr to apy.
4547
4555
  *
4548
- * @param ownerAddress - The owner address.
4549
- * @return All Stake accounts data.
4556
+ * @param apr The annual percentage rate (APR).
4557
+ * @param compoundFrequency How often interest is compounded per year. Default is daily (365 times a year).
4558
+ * @return The equivalent annual percentage yield (APY) for the given APR and compounding frequency.
4550
4559
  */
4551
- async getAllStakeAccounts(ownerAddress = this.walletAddress) {
4552
- return await getStakeAccounts(this, ownerAddress);
4560
+ parseAprToApy(apr, compoundFrequency = 365) {
4561
+ return (1 + apr / compoundFrequency) ** compoundFrequency - 1;
4553
4562
  }
4554
4563
  /**
4555
- * Get stake accounts data for specific stake pool (spool).
4564
+ * Convert apr to apy.
4556
4565
  *
4557
- * @param stakeMarketCoinName - Specific support stake market coin name.
4558
- * @param ownerAddress - The owner address.
4559
- * @return Stake accounts data.
4566
+ * @param apr The equivalent annual percentage yield (APY).
4567
+ * @param compoundFrequency How often interest is compounded per year. Default is daily (365 times a year).
4568
+ * @return The equivalent annual percentage rate (APR) for the given APY and compounding frequency.
4560
4569
  */
4561
- async getStakeAccounts(stakeMarketCoinName, ownerAddress = this.walletAddress) {
4562
- const allStakeAccount = await this.getAllStakeAccounts(ownerAddress);
4563
- return allStakeAccount[stakeMarketCoinName] ?? [];
4570
+ parseApyToApr(apy, compoundFrequency = 365) {
4571
+ return ((1 + apy) ** (1 / compoundFrequency) - 1) * compoundFrequency;
4564
4572
  }
4565
4573
  /**
4566
- * Get stake pools (spools) data.
4574
+ * Give extend lock period to get unlock at in seconds timestamp.
4567
4575
  *
4568
4576
  * @description
4569
- * For backward compatible, it is recommended to use `getSpools` method
4570
- * to get all spools data.
4577
+ * - When the user without remaining unlock period, If the extended unlock day is not specified,
4578
+ * the unlock period will be increased by one day by default.
4579
+ * - When the given extended day plus the user's remaining unlock period exceeds the maximum
4580
+ * unlock period, the maximum unlock period is used as unlock period.
4571
4581
  *
4572
- * @param stakeMarketCoinNames - Specific an array of support stake market coin name.
4573
- * @return Stake pools data.
4582
+ * @param extendLockPeriodInDay The extend lock period in day.
4583
+ * @param unlockAtInSecondTimestamp The unlock timestamp from veSca object.
4584
+ * @return New unlock at in seconds timestamp.
4574
4585
  */
4575
- async getStakePools(stakeMarketCoinNames) {
4576
- stakeMarketCoinNames = stakeMarketCoinNames ?? [...SUPPORT_SPOOLS];
4577
- const stakePools = {};
4578
- for (const stakeMarketCoinName of stakeMarketCoinNames) {
4579
- const stakePool = await getStakePool(this, stakeMarketCoinName);
4580
- if (stakePool) {
4581
- stakePools[stakeMarketCoinName] = stakePool;
4582
- }
4586
+ getUnlockAt(extendLockPeriodInDay, unlockAtInMillisTimestamp) {
4587
+ const now = Math.floor((/* @__PURE__ */ new Date()).getTime() / 1e3);
4588
+ const remainingLockPeriod = unlockAtInMillisTimestamp ? Math.max(Math.floor(unlockAtInMillisTimestamp / 1e3) - now, 0) : 0;
4589
+ let newUnlockAtInSecondTimestamp = 0;
4590
+ if (remainingLockPeriod === 0) {
4591
+ const lockPeriod = (extendLockPeriodInDay ?? 1) * UNLOCK_ROUND_DURATION;
4592
+ newUnlockAtInSecondTimestamp = Math.min(
4593
+ now + lockPeriod,
4594
+ now + MAX_LOCK_DURATION
4595
+ );
4596
+ } else {
4597
+ const lockPeriod = Math.min(
4598
+ extendLockPeriodInDay ? extendLockPeriodInDay * UNLOCK_ROUND_DURATION + remainingLockPeriod : remainingLockPeriod,
4599
+ MAX_LOCK_DURATION
4600
+ );
4601
+ newUnlockAtInSecondTimestamp = now + lockPeriod;
4583
4602
  }
4584
- return stakePools;
4585
- }
4586
- /**
4587
- * Get stake pool (spool) data.
4588
- *
4589
- * @description
4590
- * For backward compatible, it is recommended to use `getSpool` method
4591
- * to get all spool data.
4592
- *
4593
- * @param stakeMarketCoinName - Specific support stake market coin name.
4594
- * @return Stake pool data.
4595
- */
4596
- async getStakePool(stakeMarketCoinName) {
4597
- return await getStakePool(this, stakeMarketCoinName);
4603
+ return findClosestUnlockRound(newUnlockAtInSecondTimestamp);
4598
4604
  }
4599
- /**
4600
- * Get stake reward pools data.
4601
- *
4602
- * @description
4603
- * For backward compatible, it is recommended to use `getSpools` method
4604
- * to get all spools data.
4605
- *
4606
- * @param stakeMarketCoinNames - Specific an array of stake market coin name.
4607
- * @return Stake reward pools data.
4608
- */
4609
- async getStakeRewardPools(stakeMarketCoinNames) {
4610
- stakeMarketCoinNames = stakeMarketCoinNames ?? [...SUPPORT_SPOOLS];
4611
- const stakeRewardPools = {};
4612
- await Promise.allSettled(
4613
- stakeMarketCoinNames.map(async (stakeMarketCoinName) => {
4614
- const stakeRewardPool = await getStakeRewardPool(
4615
- this,
4616
- stakeMarketCoinName
4617
- );
4618
- if (stakeRewardPool) {
4619
- stakeRewardPools[stakeMarketCoinName] = stakeRewardPool;
4620
- }
4621
- })
4605
+ };
4606
+
4607
+ // src/models/scallopBuilder.ts
4608
+ import { normalizeSuiAddress as normalizeSuiAddress3 } from "@mysten/sui.js/utils";
4609
+ import { SuiKit as SuiKit5 } from "@scallop-io/sui-kit";
4610
+
4611
+ // src/builders/coreBuilder.ts
4612
+ import { TransactionBlock } from "@mysten/sui.js/transactions";
4613
+ import { SUI_CLOCK_OBJECT_ID as SUI_CLOCK_OBJECT_ID3 } from "@mysten/sui.js/utils";
4614
+ import { SuiTxBlock as SuiKitTxBlock } from "@scallop-io/sui-kit";
4615
+
4616
+ // src/builders/oracle.ts
4617
+ import { SUI_CLOCK_OBJECT_ID as SUI_CLOCK_OBJECT_ID2 } from "@mysten/sui.js/utils";
4618
+ import {
4619
+ SuiPythClient,
4620
+ SuiPriceServiceConnection as SuiPriceServiceConnection2
4621
+ } from "@pythnetwork/pyth-sui-js";
4622
+ var updateOracles = async (builder, txBlock, assetCoinNames) => {
4623
+ assetCoinNames = assetCoinNames ?? [
4624
+ .../* @__PURE__ */ new Set([...SUPPORT_POOLS, ...SUPPORT_COLLATERALS])
4625
+ ];
4626
+ const rules = builder.isTestnet ? ["pyth"] : ["pyth"];
4627
+ if (rules.includes("pyth")) {
4628
+ const pythClient = new SuiPythClient(
4629
+ builder.suiKit.client(),
4630
+ builder.address.get("core.oracles.pyth.state"),
4631
+ builder.address.get("core.oracles.pyth.wormholeState")
4622
4632
  );
4623
- return stakeRewardPools;
4633
+ const priceIds = assetCoinNames.map(
4634
+ (assetCoinName) => builder.address.get(`core.coins.${assetCoinName}.oracle.pyth.feed`)
4635
+ );
4636
+ const endpoints = builder.params.pythEndpoints ?? PYTH_ENDPOINTS[builder.isTestnet ? "testnet" : "mainnet"];
4637
+ for (const endpoint of endpoints) {
4638
+ try {
4639
+ const pythConnection = new SuiPriceServiceConnection2(endpoint);
4640
+ const priceUpdateData = await pythConnection.getPriceFeedsUpdateData(priceIds);
4641
+ await pythClient.updatePriceFeeds(
4642
+ txBlock.txBlock,
4643
+ priceUpdateData,
4644
+ priceIds
4645
+ );
4646
+ break;
4647
+ } catch (e) {
4648
+ console.warn(
4649
+ `Failed to update price feeds with endpoint ${endpoint}: ${e}`
4650
+ );
4651
+ }
4652
+ }
4624
4653
  }
4625
- /**
4626
- * Get stake reward pool data.
4627
- *
4628
- * @description
4629
- * For backward compatible, it is recommended to use `getSpool` method
4630
- * to get spool data.
4631
- *
4632
- * @param marketCoinName - Specific support stake market coin name.
4633
- * @return Stake reward pool data.
4634
- */
4635
- async getStakeRewardPool(stakeMarketCoinName) {
4636
- return await getStakeRewardPool(this, stakeMarketCoinName);
4637
- }
4638
- /**
4639
- * Get borrow incentive pools data.
4640
- *
4641
- * @param coinNames - Specific an array of support borrow incentive coin name.
4642
- * @param indexer - Whether to use indexer.
4643
- * @return Borrow incentive pools data.
4644
- */
4645
- async getBorrowIncentivePools(coinNames, indexer = false) {
4646
- return await queryBorrowIncentivePools(this, coinNames, indexer);
4647
- }
4648
- /**
4649
- * Get borrow incentive accounts data.
4650
- *
4651
- * @param coinNames - Specific support borrow incentive coin name.
4652
- * @param ownerAddress - The owner address.
4653
- * @return Borrow incentive accounts data.
4654
- */
4655
- async getBorrowIncentiveAccounts(obligationId, coinNames) {
4656
- return await queryBorrowIncentiveAccounts(this, obligationId, coinNames);
4657
- }
4658
- /**
4659
- * Get user lending and spool infomation for specific pools.
4660
- *
4661
- * @param poolCoinNames - Specific an array of support pool coin name.
4662
- * @param ownerAddress - The owner address.
4663
- * @param indexer - Whether to use indexer.
4664
- * @return All lending and spool infomation.
4665
- */
4666
- async getLendings(poolCoinNames, ownerAddress = this.walletAddress, indexer = false) {
4667
- return await getLendings(this, poolCoinNames, ownerAddress, indexer);
4668
- }
4669
- /**
4670
- * Get user lending and spool information for specific pool.
4671
- *
4672
- * @param poolCoinName - Specific support pool coin name.
4673
- * @param ownerAddress - The owner address.
4674
- * @param indexer - Whether to use indexer.
4675
- * @return Lending pool data.
4676
- */
4677
- async getLending(poolCoinName, ownerAddress = this.walletAddress, indexer = false) {
4678
- return await getLending(this, poolCoinName, ownerAddress, indexer);
4679
- }
4680
- /**
4681
- * Get user all obligation accounts information.
4682
- *
4683
- * @description
4684
- * All collateral and borrowing information in all obligation accounts owned by the user.
4685
- *
4686
- * @param ownerAddress - The owner address.
4687
- * @param indexer - Whether to use indexer.
4688
- * @return All obligation accounts information.
4689
- */
4690
- async getObligationAccounts(ownerAddress = this.walletAddress, indexer = false) {
4691
- return await getObligationAccounts(this, ownerAddress, indexer);
4654
+ const updateAssetCoinNames = [...new Set(assetCoinNames)];
4655
+ for (const assetCoinName of updateAssetCoinNames) {
4656
+ await updateOracle(builder, txBlock, assetCoinName, rules);
4692
4657
  }
4693
- /**
4694
- * Get obligation account information for specific id.
4695
- *
4696
- * @description
4697
- * borrowing and obligation information for specific pool.
4698
- *
4699
- * @param obligationId - The obligation id.
4700
- * @param ownerAddress - The owner address.
4701
- * @param indexer - Whether to use indexer.
4702
- * @return Borrowing and collateral information.
4703
- */
4704
- async getObligationAccount(obligationId, ownerAddress = this.walletAddress, indexer = false) {
4705
- return await getObligationAccount(
4706
- this,
4707
- obligationId,
4708
- ownerAddress,
4709
- indexer
4658
+ };
4659
+ var updateOracle = async (builder, txBlock, assetCoinName, rules) => {
4660
+ const coinType = builder.utils.parseCoinType(assetCoinName);
4661
+ updatePrice(
4662
+ txBlock,
4663
+ rules,
4664
+ builder.address.get("core.packages.xOracle.id"),
4665
+ builder.address.get("core.oracles.xOracle"),
4666
+ builder.address.get("core.packages.pyth.id"),
4667
+ builder.address.get("core.oracles.pyth.registry"),
4668
+ builder.address.get("core.oracles.pyth.state"),
4669
+ builder.address.get(`core.coins.${assetCoinName}.oracle.pyth.feedObject`),
4670
+ builder.address.get("core.packages.switchboard.id"),
4671
+ builder.address.get("core.oracles.switchboard.registry"),
4672
+ builder.address.get(`core.coins.${assetCoinName}.oracle.switchboard`),
4673
+ builder.address.get("core.packages.supra.id"),
4674
+ builder.address.get("core.oracles.supra.registry"),
4675
+ builder.address.get(`core.oracles.supra.holder`),
4676
+ coinType
4677
+ );
4678
+ };
4679
+ var updatePrice = (txBlock, rules, xOraclePackageId, xOracleId, pythPackageId, pythRegistryId, pythStateId, pythFeedObjectId, switchboardPackageId, switchboardRegistryId, switchboardAggregatorId, supraPackageId, supraRegistryId, supraHolderId, coinType) => {
4680
+ const request = priceUpdateRequest(
4681
+ txBlock,
4682
+ xOraclePackageId,
4683
+ xOracleId,
4684
+ coinType
4685
+ );
4686
+ if (rules.includes("pyth")) {
4687
+ updatePythPrice(
4688
+ txBlock,
4689
+ pythPackageId,
4690
+ request,
4691
+ pythStateId,
4692
+ pythFeedObjectId,
4693
+ pythRegistryId,
4694
+ coinType
4710
4695
  );
4711
4696
  }
4712
- /**
4713
- * Get total value locked.
4714
- *
4715
- * @param indexer - Whether to use indexer.
4716
- * @description
4717
- * Include total supplied value and total borrowed value.
4718
- *
4719
- * @return Total value locked.
4720
- */
4721
- async getTvl(indexer = false) {
4722
- return await getTotalValueLocked(this, indexer);
4723
- }
4724
- /**
4725
- * Get all veSca from walletAdddress
4726
- * @param walletAddress
4727
- * @returns array of veSca
4728
- */
4729
- async getVeScas(walletAddress) {
4730
- return await getVeScas(this, walletAddress);
4731
- }
4732
- /**
4733
- * Get total vesca treasury with movecall
4734
- * @returns Promise<string | undefined>
4735
- */
4736
- async getVeScaTreasuryInfo() {
4737
- return await getVeScaTreasuryInfo(this);
4738
- }
4739
- /**
4740
- * Return binded referrer veScaKeyId of referee walletAddress if exist
4741
- * @param walletAddress
4742
- * @returns veScaKeyId
4743
- */
4744
- async getVeScaKeyIdFromReferralBindings(walletAddress) {
4745
- return await queryVeScaKeyIdFromReferralBindings(this, walletAddress);
4746
- }
4747
- /**
4748
- * Get binded obligationId from a veScaKey if it exists.
4749
- * @param veScaKey
4750
- * @returns obligationId
4751
- */
4752
- async getBindedObligationId(veScaKey) {
4753
- return await getBindedObligationId(this, veScaKey);
4754
- }
4755
- /**
4756
- * Get binded veSCA key from a obligationId if it exists.
4757
- * @param obligationId
4758
- * @returns veScaKey
4759
- */
4760
- async getBindedVeScaKey(obligationId) {
4761
- return await getBindedVeScaKey(this, obligationId);
4762
- }
4763
- /**
4764
- * Get user's veSCA loyalty program informations
4765
- * @param walletAddress
4766
- * @returns Loyalty program information
4767
- */
4768
- async getLoyaltyProgramInfos(veScaKey) {
4769
- return await getLoyaltyProgramInformations(this, veScaKey);
4770
- }
4771
- /**
4772
- * Get total supply of sCoin
4773
- * @param sCoinName - Supported sCoin name
4774
- * @returns Total Supply
4775
- */
4776
- async getSCoinTotalSupply(sCoinName) {
4777
- return await getSCoinTotalSupply(this, sCoinName);
4778
- }
4779
- /**
4780
- * Get all sCoin amounts.
4781
- *
4782
- * @param sCoinNames - Specific an array of support sCoin name.
4783
- * @param ownerAddress - The owner address.
4784
- * @return All market sCoin amounts.
4785
- */
4786
- async getSCoinAmounts(sCoinNames, ownerAddress = this.walletAddress) {
4787
- return await getSCoinAmounts(this, sCoinNames, ownerAddress);
4788
- }
4789
- /**
4790
- * Get sCoin amount.
4791
- *
4792
- * @param coinNames - Specific support sCoin name.
4793
- * @param ownerAddress - The owner address.
4794
- * @return sCoin amount.
4795
- */
4796
- async getSCoinAmount(sCoinName, ownerAddress = this.walletAddress) {
4797
- const parsedSCoinName = this.utils.parseSCoinName(sCoinName);
4798
- return parsedSCoinName ? await getSCoinAmount(this, parsedSCoinName, ownerAddress) : 0;
4697
+ if (rules.includes("switchboard")) {
4698
+ updateSwitchboardPrice(
4699
+ txBlock,
4700
+ switchboardPackageId,
4701
+ request,
4702
+ switchboardAggregatorId,
4703
+ switchboardRegistryId,
4704
+ coinType
4705
+ );
4799
4706
  }
4800
- /*
4801
- * Get flashloan fee for specified assets
4802
- */
4803
- async getFlashLoanFees(assetCoinNames = [...SUPPORT_POOLS]) {
4804
- return await getFlashLoanFees(this, assetCoinNames);
4707
+ if (rules.includes("supra")) {
4708
+ updateSupraPrice(
4709
+ txBlock,
4710
+ supraPackageId,
4711
+ request,
4712
+ supraHolderId,
4713
+ supraRegistryId,
4714
+ coinType
4715
+ );
4805
4716
  }
4717
+ confirmPriceUpdateRequest(
4718
+ txBlock,
4719
+ xOraclePackageId,
4720
+ xOracleId,
4721
+ request,
4722
+ coinType
4723
+ );
4724
+ return txBlock;
4806
4725
  };
4807
-
4808
- // src/constants/pyth.ts
4809
- var PYTH_ENDPOINTS = {
4810
- testnet: ["https://hermes-beta.pyth.network"],
4811
- mainnet: ["https://hermes.pyth.network", "https://scallop.rpc.p2p.world"]
4812
- };
4813
-
4814
- // src/models/scallopUtils.ts
4815
- var ScallopUtils = class {
4816
- constructor(params, instance) {
4817
- this._priceMap = /* @__PURE__ */ new Map();
4818
- /**
4819
- * Get reward type of spool.
4820
- *
4821
- * @param stakeMarketCoinName - Support stake market coin.
4822
- * @return Spool reward coin name.
4823
- */
4824
- this.getSpoolRewardCoinName = (stakeMarketCoinName) => {
4825
- return spoolRewardCoins[stakeMarketCoinName];
4826
- };
4827
- /**
4828
- * Get reward type of borrow incentive pool.
4829
- *
4830
- * @param borrowIncentiveCoinName - Support borrow incentive coin.
4831
- * @return Borrow incentive reward coin name.
4832
- */
4833
- this.getBorrowIncentiveRewardCoinName = (borrowIncentiveCoinName) => {
4834
- return borrowIncentiveRewardCoins[borrowIncentiveCoinName];
4835
- };
4836
- this.params = params;
4837
- this._suiKit = instance?.suiKit ?? new SuiKit2(params);
4838
- this._cache = instance?.cache ?? new ScallopCache(DEFAULT_CACHE_OPTIONS, this._suiKit);
4839
- this._address = instance?.address ?? new ScallopAddress(
4840
- {
4841
- id: params?.addressesId || ADDRESSES_ID,
4842
- network: params?.networkType
4843
- },
4844
- this._cache
4845
- );
4846
- this._query = instance?.query ?? new ScallopQuery(params, {
4847
- suiKit: this._suiKit,
4848
- address: this._address,
4849
- cache: this._cache
4850
- });
4851
- this.isTestnet = params.networkType ? params.networkType === "testnet" : false;
4852
- }
4853
- /**
4854
- * Request the scallop API to initialize data.
4855
- *
4856
- * @param force - Whether to force initialization.
4857
- * @param address - ScallopAddress instance.
4858
- */
4859
- async init(force = false, address) {
4860
- if (force || !this._address.getAddresses() || !address?.getAddresses()) {
4861
- await this._address.read();
4862
- } else {
4863
- this._address = address;
4864
- }
4865
- if (!this._query.address.getAddresses()) {
4866
- await this._query.init(force, this._address);
4867
- }
4868
- }
4869
- /**
4870
- * Convert coin name to symbol.
4871
- *
4872
- * @param coinName - Specific support coin name.
4873
- * @return Symbol string.
4874
- */
4875
- parseSymbol(coinName) {
4876
- if (isMarketCoin(coinName)) {
4877
- const assetCoinName = coinName.slice(1).toLowerCase();
4878
- return coinName.slice(0, 1).toLowerCase() + parseAssetSymbol(assetCoinName);
4879
- } else {
4880
- return parseAssetSymbol(coinName);
4881
- }
4882
- }
4883
- /**
4884
- * Convert coin name to coin type.
4885
- *
4886
- * @description
4887
- * The Coin type of wormhole is fixed `coin:Coin`. Here using package id
4888
- * to determine and return the type.
4889
- *
4890
- * @param coinPackageId - Package id of coin.
4891
- * @param coinName - Specific support coin name.
4892
- * @return Coin type.
4893
- */
4894
- parseCoinType(coinName) {
4895
- coinName = isMarketCoin(coinName) ? this.parseCoinName(coinName) : coinName;
4896
- const coinPackageId = this._address.get(`core.coins.${coinName}.id`) || coinIds[coinName] || void 0;
4897
- if (!coinPackageId) {
4898
- throw Error(`Coin ${coinName} is not supported`);
4899
- }
4900
- if (coinName === "sui")
4901
- return normalizeStructTag6(`${coinPackageId}::sui::SUI`);
4902
- const wormHolePckageIds = [
4903
- this._address.get("core.coins.usdc.id") ?? wormholeCoinIds.usdc,
4904
- this._address.get("core.coins.usdt.id") ?? wormholeCoinIds.usdt,
4905
- this._address.get("core.coins.eth.id") ?? wormholeCoinIds.eth,
4906
- this._address.get("core.coins.btc.id") ?? wormholeCoinIds.btc,
4907
- this._address.get("core.coins.sol.id") ?? wormholeCoinIds.sol,
4908
- this._address.get("core.coins.apt.id") ?? wormholeCoinIds.apt
4909
- ];
4910
- const voloPckageIds = [
4911
- this._address.get("core.coins.vsui.id") ?? voloCoinIds.vsui
4912
- ];
4913
- if (wormHolePckageIds.includes(coinPackageId)) {
4914
- return `${coinPackageId}::coin::COIN`;
4915
- } else if (voloPckageIds.includes(coinPackageId)) {
4916
- return `${coinPackageId}::cert::CERT`;
4917
- } else {
4918
- return `${coinPackageId}::${coinName}::${coinName.toUpperCase()}`;
4919
- }
4920
- }
4921
- /**
4922
- * Convert coin name to sCoin name.
4923
- *
4924
- * @param coinName - Specific support coin name.
4925
- * @return sCoin name.
4926
- */
4927
- parseSCoinName(coinName) {
4928
- if (isMarketCoin(coinName) && SUPPORT_SCOIN.includes(coinName)) {
4929
- return coinName;
4930
- } else {
4931
- const marketCoinName = `s${coinName}`;
4932
- if (SUPPORT_SCOIN.includes(marketCoinName)) {
4933
- return marketCoinName;
4934
- }
4935
- return void 0;
4936
- }
4937
- }
4938
- /**
4939
- * Convert sCoin name into sCoin type
4940
- * @param sCoinName
4941
- * @returns sCoin type
4942
- */
4943
- parseSCoinType(sCoinName) {
4944
- return sCoinIds[sCoinName];
4945
- }
4946
- /**
4947
- * Convert sCoin name into its underlying coin type
4948
- * @param sCoinName
4949
- * @returns coin type
4950
- */
4951
- parseUnderlyingSCoinType(sCoinName) {
4952
- const coinName = this.parseCoinName(sCoinName);
4953
- return this.parseCoinType(coinName);
4954
- }
4955
- /**
4956
- * Get sCoin treasury id from sCoin name
4957
- * @param sCoinName
4958
- * @returns sCoin treasury id
4959
- */
4960
- getSCoinTreasury(sCoinName) {
4961
- return this._address.get(`scoin.coins.${sCoinName}.treasury`);
4962
- }
4963
- /**
4964
- * Convert coin name to market coin type.
4965
- *
4966
- * @param coinPackageId - Package id of coin.
4967
- * @param coinName - Specific support coin name.
4968
- * @return Market coin type.
4969
- */
4970
- parseMarketCoinType(coinName) {
4971
- const protocolObjectId = this._address.get("core.object") || PROTOCOL_OBJECT_ID;
4972
- const coinType = this.parseCoinType(coinName);
4973
- return `${protocolObjectId}::reserve::MarketCoin<${coinType}>`;
4974
- }
4975
- parseCoinNameFromType(coinType) {
4976
- coinType = normalizeStructTag6(coinType);
4977
- const coinTypeRegex = new RegExp(`((0x[^:]+::[^:]+::[^<>]+))(?![^<>]*<)`);
4978
- const coinTypeMatch = coinType.match(coinTypeRegex);
4979
- const isMarketCoinType = coinType.includes("reserve::MarketCoin");
4980
- coinType = coinTypeMatch?.[1] || coinType;
4981
- const wormHoleCoinTypeMap = {
4982
- [`${this._address.get("core.coins.usdc.id") ?? wormholeCoinIds.usdc}::coin::COIN`]: "usdc",
4983
- [`${this._address.get("core.coins.usdt.id") ?? wormholeCoinIds.usdt}::coin::COIN`]: "usdt",
4984
- [`${this._address.get("core.coins.eth.id") ?? wormholeCoinIds.eth}::coin::COIN`]: "eth",
4985
- [`${this._address.get("core.coins.btc.id") ?? wormholeCoinIds.btc}::coin::COIN`]: "btc",
4986
- [`${this._address.get("core.coins.sol.id") ?? wormholeCoinIds.sol}::coin::COIN`]: "sol",
4987
- [`${this._address.get("core.coins.apt.id") ?? wormholeCoinIds.apt}::coin::COIN`]: "apt"
4988
- };
4989
- const voloCoinTypeMap = {
4990
- [`${this._address.get("core.coins.vsui.id") ?? voloCoinIds.vsui}::cert::CERT`]: "vsui"
4991
- };
4992
- const assetCoinName = wormHoleCoinTypeMap[coinType] || voloCoinTypeMap[coinType] || coinType.split("::")[2].toLowerCase();
4993
- return isMarketCoinType ? this.parseMarketCoinName(assetCoinName) : assetCoinName;
4994
- }
4995
- /**
4996
- * Convert marke coin name to coin name.
4997
- *
4998
- * @param marketCoinName - Specific support market coin name.
4999
- * @return Coin Name.
5000
- */
5001
- parseCoinName(marketCoinName) {
5002
- return marketCoinName.slice(1);
5003
- }
5004
- /**
5005
- * Convert coin name to market coin name.
5006
- *
5007
- * @param coinName - Specific support coin name.
5008
- * @return Market coin name.
5009
- */
5010
- parseMarketCoinName(coinName) {
5011
- return `s${coinName}`;
5012
- }
5013
- /**
5014
- * Get coin decimal.
5015
- *
5016
- * return Coin decimal.
5017
- */
5018
- getCoinDecimal(coinName) {
5019
- return coinDecimals[coinName];
5020
- }
5021
- /**
5022
- * Get coin wrapped type.
5023
- *
5024
- * return Coin wrapped type.
5025
- */
5026
- getCoinWrappedType(assetCoinName) {
5027
- return assetCoinName === "usdc" || assetCoinName === "usdt" || assetCoinName === "eth" || assetCoinName === "btc" || assetCoinName === "apt" || assetCoinName === "sol" ? {
5028
- from: "Wormhole",
5029
- type: "Portal from Ethereum"
5030
- } : void 0;
5031
- }
5032
- /**
5033
- * Select coin id that add up to the given amount as transaction arguments.
5034
- *
5035
- * @param ownerAddress - The address of the owner.
5036
- * @param amount - The amount that including coin decimals.
5037
- * @param coinType - The coin type, default is 0x2::SUI::SUI.
5038
- * @return The selected transaction coin arguments.
5039
- */
5040
- async selectCoins(amount, coinType = SUI_TYPE_ARG, ownerAddress) {
5041
- ownerAddress = ownerAddress || this._suiKit.currentAddress();
5042
- const coins = await this._suiKit.suiInteractor.selectCoins(
5043
- ownerAddress,
5044
- amount,
5045
- coinType
5046
- );
5047
- return coins;
5048
- }
5049
- /**
5050
- * Merge coins with type `coinType` to dest
5051
- * @param txBlock
5052
- * @param dest
5053
- * @param coinType
5054
- * @param sender
5055
- */
5056
- async mergeSimilarCoins(txBlock, dest, coinType, sender) {
5057
- try {
5058
- const existingSCoin = await this.selectCoins(
5059
- Number.MAX_SAFE_INTEGER,
5060
- coinType,
5061
- sender
5062
- );
5063
- if (existingSCoin.length > 0) {
5064
- txBlock.mergeCoins(dest, existingSCoin);
5065
- }
5066
- } catch (e) {
5067
- }
5068
- }
5069
- /**
5070
- * Get all asset coin names in the obligation record by obligation id.
5071
- *
5072
- * @description
5073
- * This can often be used to determine which assets in an obligation require
5074
- * price updates before interacting with specific instructions of the Scallop contract.
5075
- *
5076
- * @param obligationId - The obligation id.
5077
- * @return Asset coin Names.
5078
- */
5079
- async getObligationCoinNames(obligationId) {
5080
- const obligation = await queryObligation(this._query, obligationId);
5081
- const collateralCoinTypes = obligation?.collaterals.map((collateral) => {
5082
- return `0x${collateral.type.name}`;
5083
- }) ?? [];
5084
- const debtCoinTypes = obligation?.debts.map((debt) => {
5085
- return `0x${debt.type.name}`;
5086
- }) ?? [];
5087
- const obligationCoinTypes = [
5088
- .../* @__PURE__ */ new Set([...collateralCoinTypes, ...debtCoinTypes])
5089
- ];
5090
- const obligationCoinNames = obligationCoinTypes.map((coinType) => {
5091
- return this.parseCoinNameFromType(coinType);
5092
- });
5093
- return obligationCoinNames;
5094
- }
5095
- /**
5096
- * Get asset coin price.
5097
- *
5098
- * @description
5099
- * The strategy for obtaining the price is to get it through API first,
5100
- * and then on-chain data if API cannot be retrieved.
5101
- * Currently, we only support obtaining from pyth protocol, other
5102
- * oracles will be supported in the future.
5103
- *
5104
- * @param assetCoinNames - Specific an array of support asset coin name.
5105
- * @return Asset coin price.
5106
- */
5107
- async getCoinPrices(assetCoinNames) {
5108
- assetCoinNames = assetCoinNames || [
5109
- .../* @__PURE__ */ new Set([...SUPPORT_POOLS, ...SUPPORT_COLLATERALS])
5110
- ];
5111
- const coinPrices = {};
5112
- const existPricesCoinNames = [];
5113
- const lackPricesCoinNames = [];
5114
- assetCoinNames.forEach((assetCoinName) => {
5115
- if (this._priceMap.has(assetCoinName) && Date.now() - this._priceMap.get(assetCoinName).publishTime < 1e3 * 60) {
5116
- existPricesCoinNames.push(assetCoinName);
5117
- } else {
5118
- lackPricesCoinNames.push(assetCoinName);
5119
- }
5120
- });
5121
- if (existPricesCoinNames.length > 0) {
5122
- for (const coinName of existPricesCoinNames) {
5123
- coinPrices[coinName] = this._priceMap.get(coinName).price;
5124
- }
5125
- }
5126
- if (lackPricesCoinNames.length > 0) {
5127
- const endpoints = this.params.pythEndpoints ?? PYTH_ENDPOINTS[this.isTestnet ? "testnet" : "mainnet"];
5128
- const failedRequests = new Set(
5129
- lackPricesCoinNames
5130
- );
5131
- for (const endpoint of endpoints) {
5132
- const priceIds = Array.from(failedRequests.values()).reduce(
5133
- (acc, coinName) => {
5134
- const priceId = this._address.get(
5135
- `core.coins.${coinName}.oracle.pyth.feed`
5136
- );
5137
- acc[coinName] = priceId;
5138
- return acc;
5139
- },
5140
- {}
5141
- );
5142
- await Promise.allSettled(
5143
- Object.entries(priceIds).map(async ([coinName, priceId]) => {
5144
- const pythConnection = new SuiPriceServiceConnection(endpoint);
5145
- try {
5146
- const feed = await this._cache.queryClient.fetchQuery({
5147
- queryKey: [priceId],
5148
- queryFn: async () => {
5149
- return await pythConnection.getLatestPriceFeeds([priceId]);
5150
- }
5151
- });
5152
- if (feed) {
5153
- const data = parseDataFromPythPriceFeed(feed[0], this._address);
5154
- this._priceMap.set(coinName, {
5155
- price: data.price,
5156
- publishTime: data.publishTime
5157
- });
5158
- coinPrices[coinName] = data.price;
5159
- }
5160
- failedRequests.delete(coinName);
5161
- } catch (e) {
5162
- console.warn(
5163
- `Failed to get price ${coinName} feeds with endpoint ${endpoint}: ${e}`
5164
- );
5165
- }
5166
- })
5167
- );
5168
- if (failedRequests.size === 0)
5169
- break;
5170
- }
5171
- if (failedRequests.size > 0) {
5172
- await Promise.allSettled(
5173
- Array.from(failedRequests.values()).map(async (coinName) => {
5174
- const price = await this._query.getPriceFromPyth(coinName);
5175
- this._priceMap.set(coinName, {
5176
- price,
5177
- publishTime: Date.now()
5178
- });
5179
- coinPrices[coinName] = price;
5180
- })
5181
- );
5182
- }
5183
- }
5184
- return coinPrices;
5185
- }
5186
- /**
5187
- * Convert apr to apy.
5188
- *
5189
- * @param apr The annual percentage rate (APR).
5190
- * @param compoundFrequency How often interest is compounded per year. Default is daily (365 times a year).
5191
- * @return The equivalent annual percentage yield (APY) for the given APR and compounding frequency.
5192
- */
5193
- parseAprToApy(apr, compoundFrequency = 365) {
5194
- return (1 + apr / compoundFrequency) ** compoundFrequency - 1;
5195
- }
5196
- /**
5197
- * Convert apr to apy.
5198
- *
5199
- * @param apr The equivalent annual percentage yield (APY).
5200
- * @param compoundFrequency How often interest is compounded per year. Default is daily (365 times a year).
5201
- * @return The equivalent annual percentage rate (APR) for the given APY and compounding frequency.
5202
- */
5203
- parseApyToApr(apy, compoundFrequency = 365) {
5204
- return ((1 + apy) ** (1 / compoundFrequency) - 1) * compoundFrequency;
5205
- }
5206
- /**
5207
- * Give extend lock period to get unlock at in seconds timestamp.
5208
- *
5209
- * @description
5210
- * - When the user without remaining unlock period, If the extended unlock day is not specified,
5211
- * the unlock period will be increased by one day by default.
5212
- * - When the given extended day plus the user's remaining unlock period exceeds the maximum
5213
- * unlock period, the maximum unlock period is used as unlock period.
5214
- *
5215
- * @param extendLockPeriodInDay The extend lock period in day.
5216
- * @param unlockAtInSecondTimestamp The unlock timestamp from veSca object.
5217
- * @return New unlock at in seconds timestamp.
5218
- */
5219
- getUnlockAt(extendLockPeriodInDay, unlockAtInMillisTimestamp) {
5220
- const now = Math.floor((/* @__PURE__ */ new Date()).getTime() / 1e3);
5221
- const remainingLockPeriod = unlockAtInMillisTimestamp ? Math.max(Math.floor(unlockAtInMillisTimestamp / 1e3) - now, 0) : 0;
5222
- let newUnlockAtInSecondTimestamp = 0;
5223
- if (remainingLockPeriod === 0) {
5224
- const lockPeriod = (extendLockPeriodInDay ?? 1) * UNLOCK_ROUND_DURATION;
5225
- newUnlockAtInSecondTimestamp = Math.min(
5226
- now + lockPeriod,
5227
- now + MAX_LOCK_DURATION
5228
- );
5229
- } else {
5230
- const lockPeriod = Math.min(
5231
- extendLockPeriodInDay ? extendLockPeriodInDay * UNLOCK_ROUND_DURATION + remainingLockPeriod : remainingLockPeriod,
5232
- MAX_LOCK_DURATION
5233
- );
5234
- newUnlockAtInSecondTimestamp = now + lockPeriod;
5235
- }
5236
- return findClosestUnlockRound(newUnlockAtInSecondTimestamp);
5237
- }
5238
- };
5239
-
5240
- // src/models/scallopBuilder.ts
5241
- import { normalizeSuiAddress as normalizeSuiAddress3 } from "@mysten/sui.js/utils";
5242
- import { SuiKit as SuiKit3 } from "@scallop-io/sui-kit";
5243
-
5244
- // src/builders/coreBuilder.ts
5245
- import { TransactionBlock } from "@mysten/sui.js/transactions";
5246
- import { SUI_CLOCK_OBJECT_ID as SUI_CLOCK_OBJECT_ID3 } from "@mysten/sui.js/utils";
5247
- import { SuiTxBlock as SuiKitTxBlock } from "@scallop-io/sui-kit";
5248
-
5249
- // src/builders/oracle.ts
5250
- import { SUI_CLOCK_OBJECT_ID as SUI_CLOCK_OBJECT_ID2 } from "@mysten/sui.js/utils";
5251
- import {
5252
- SuiPythClient,
5253
- SuiPriceServiceConnection as SuiPriceServiceConnection2
5254
- } from "@pythnetwork/pyth-sui-js";
5255
- var updateOracles = async (builder, txBlock, assetCoinNames) => {
5256
- assetCoinNames = assetCoinNames ?? [
5257
- .../* @__PURE__ */ new Set([...SUPPORT_POOLS, ...SUPPORT_COLLATERALS])
5258
- ];
5259
- const rules = builder.isTestnet ? ["pyth"] : ["pyth"];
5260
- if (rules.includes("pyth")) {
5261
- const pythClient = new SuiPythClient(
5262
- builder.suiKit.client(),
5263
- builder.address.get("core.oracles.pyth.state"),
5264
- builder.address.get("core.oracles.pyth.wormholeState")
5265
- );
5266
- const priceIds = assetCoinNames.map(
5267
- (assetCoinName) => builder.address.get(`core.coins.${assetCoinName}.oracle.pyth.feed`)
5268
- );
5269
- const endpoints = builder.params.pythEndpoints ?? PYTH_ENDPOINTS[builder.isTestnet ? "testnet" : "mainnet"];
5270
- for (const endpoint of endpoints) {
5271
- try {
5272
- const pythConnection = new SuiPriceServiceConnection2(endpoint);
5273
- const priceUpdateData = await pythConnection.getPriceFeedsUpdateData(priceIds);
5274
- await pythClient.updatePriceFeeds(
5275
- txBlock.txBlock,
5276
- priceUpdateData,
5277
- priceIds
5278
- );
5279
- break;
5280
- } catch (e) {
5281
- console.warn(
5282
- `Failed to update price feeds with endpoint ${endpoint}: ${e}`
5283
- );
5284
- }
5285
- }
5286
- }
5287
- const updateAssetCoinNames = [...new Set(assetCoinNames)];
5288
- for (const assetCoinName of updateAssetCoinNames) {
5289
- await updateOracle(builder, txBlock, assetCoinName, rules);
5290
- }
5291
- };
5292
- var updateOracle = async (builder, txBlock, assetCoinName, rules) => {
5293
- const coinType = builder.utils.parseCoinType(assetCoinName);
5294
- updatePrice(
5295
- txBlock,
5296
- rules,
5297
- builder.address.get("core.packages.xOracle.id"),
5298
- builder.address.get("core.oracles.xOracle"),
5299
- builder.address.get("core.packages.pyth.id"),
5300
- builder.address.get("core.oracles.pyth.registry"),
5301
- builder.address.get("core.oracles.pyth.state"),
5302
- builder.address.get(`core.coins.${assetCoinName}.oracle.pyth.feedObject`),
5303
- builder.address.get("core.packages.switchboard.id"),
5304
- builder.address.get("core.oracles.switchboard.registry"),
5305
- builder.address.get(`core.coins.${assetCoinName}.oracle.switchboard`),
5306
- builder.address.get("core.packages.supra.id"),
5307
- builder.address.get("core.oracles.supra.registry"),
5308
- builder.address.get(`core.oracles.supra.holder`),
5309
- coinType
5310
- );
5311
- };
5312
- var updatePrice = (txBlock, rules, xOraclePackageId, xOracleId, pythPackageId, pythRegistryId, pythStateId, pythFeedObjectId, switchboardPackageId, switchboardRegistryId, switchboardAggregatorId, supraPackageId, supraRegistryId, supraHolderId, coinType) => {
5313
- const request = priceUpdateRequest(
5314
- txBlock,
5315
- xOraclePackageId,
5316
- xOracleId,
5317
- coinType
5318
- );
5319
- if (rules.includes("pyth")) {
5320
- updatePythPrice(
5321
- txBlock,
5322
- pythPackageId,
5323
- request,
5324
- pythStateId,
5325
- pythFeedObjectId,
5326
- pythRegistryId,
5327
- coinType
5328
- );
5329
- }
5330
- if (rules.includes("switchboard")) {
5331
- updateSwitchboardPrice(
5332
- txBlock,
5333
- switchboardPackageId,
5334
- request,
5335
- switchboardAggregatorId,
5336
- switchboardRegistryId,
5337
- coinType
5338
- );
5339
- }
5340
- if (rules.includes("supra")) {
5341
- updateSupraPrice(
5342
- txBlock,
5343
- supraPackageId,
5344
- request,
5345
- supraHolderId,
5346
- supraRegistryId,
5347
- coinType
5348
- );
5349
- }
5350
- confirmPriceUpdateRequest(
5351
- txBlock,
5352
- xOraclePackageId,
5353
- xOracleId,
5354
- request,
5355
- coinType
5356
- );
5357
- return txBlock;
5358
- };
5359
- var priceUpdateRequest = (txBlock, packageId, xOracleId, coinType) => {
5360
- const target = `${packageId}::x_oracle::price_update_request`;
5361
- const typeArgs = [coinType];
5362
- return txBlock.moveCall(target, [xOracleId], typeArgs);
4726
+ var priceUpdateRequest = (txBlock, packageId, xOracleId, coinType) => {
4727
+ const target = `${packageId}::x_oracle::price_update_request`;
4728
+ const typeArgs = [coinType];
4729
+ return txBlock.moveCall(target, [xOracleId], typeArgs);
5363
4730
  };
5364
4731
  var confirmPriceUpdateRequest = (txBlock, packageId, xOracleId, request, coinType) => {
5365
4732
  const target = `${packageId}::x_oracle::confirm_price_update_request`;
@@ -5397,7 +4764,7 @@ var requireObligationInfo = async (...params) => {
5397
4764
  if (params.length === 4 && obligationId && obligationKey)
5398
4765
  return { obligationId, obligationKey };
5399
4766
  const sender = requireSender(txBlock);
5400
- const obligations = await getObligations(builder.query, sender);
4767
+ const obligations = await getObligations(builder, sender);
5401
4768
  if (obligations.length === 0) {
5402
4769
  throw new Error(`No obligation found for sender ${sender}`);
5403
4770
  }
@@ -5694,8 +5061,8 @@ var generateCoreQuickMethod = ({
5694
5061
  );
5695
5062
  const obligationCoinNames = await builder.utils.getObligationCoinNames(
5696
5063
  obligationInfo.obligationId
5697
- );
5698
- const updateCoinNames = [...obligationCoinNames, poolCoinName];
5064
+ ) ?? [];
5065
+ const updateCoinNames = [...obligationCoinNames ?? [], poolCoinName];
5699
5066
  await updateOracles(builder, txBlock, updateCoinNames);
5700
5067
  return txBlock.borrow(
5701
5068
  obligationInfo.obligationId,
@@ -5713,7 +5080,7 @@ var generateCoreQuickMethod = ({
5713
5080
  );
5714
5081
  const obligationCoinNames = await builder.utils.getObligationCoinNames(
5715
5082
  obligationInfo.obligationId
5716
- );
5083
+ ) ?? [];
5717
5084
  const updateCoinNames = [...obligationCoinNames, poolCoinName];
5718
5085
  await updateOracles(builder, txBlock, updateCoinNames);
5719
5086
  return txBlock.borrowWithReferral(
@@ -5795,7 +5162,7 @@ var requireStakeAccountIds = async (...params) => {
5795
5162
  if (params.length === 4 && stakeAccountId)
5796
5163
  return [stakeAccountId];
5797
5164
  const sender = requireSender(txBlock);
5798
- const stakeAccounts = await getStakeAccounts(builder.query, sender);
5165
+ const stakeAccounts = await getStakeAccounts(builder, sender);
5799
5166
  if (stakeAccounts[stakeMarketCoinName].length === 0) {
5800
5167
  throw new Error(`No stake account id found for sender ${sender}`);
5801
5168
  }
@@ -5804,7 +5171,7 @@ var requireStakeAccountIds = async (...params) => {
5804
5171
  var requireStakeAccounts = async (...params) => {
5805
5172
  const [builder, txBlock, stakeMarketCoinName, stakeAccountId] = params;
5806
5173
  const sender = requireSender(txBlock);
5807
- const stakeAccounts = await getStakeAccounts(builder.query, sender);
5174
+ const stakeAccounts = await getStakeAccounts(builder, sender);
5808
5175
  if (stakeAccounts[stakeMarketCoinName].length === 0) {
5809
5176
  throw new Error(`No stake account found for sender ${sender}`);
5810
5177
  }
@@ -6022,14 +5389,14 @@ import {
6022
5389
  var requireVeSca = async (...params) => {
6023
5390
  const [builder, txBlock, veScaKey] = params;
6024
5391
  if (params.length === 3 && veScaKey && typeof veScaKey === "string") {
6025
- const veSca = await getVeSca(builder.query, veScaKey);
5392
+ const veSca = await getVeSca(builder.utils, veScaKey);
6026
5393
  if (!veSca) {
6027
5394
  return void 0;
6028
5395
  }
6029
5396
  return veSca;
6030
5397
  }
6031
5398
  const sender = requireSender(txBlock);
6032
- const veScas = await getVeScas(builder.query, sender);
5399
+ const veScas = await getVeScas(builder, sender);
6033
5400
  if (veScas.length === 0) {
6034
5401
  return void 0;
6035
5402
  }
@@ -6250,13 +5617,17 @@ var generateQuickVeScaMethod = ({
6250
5617
  txBlock.transferObjects(transferObjects, sender);
6251
5618
  }
6252
5619
  },
6253
- redeemScaQuick: async (veScaKey) => {
5620
+ redeemScaQuick: async (veScaKey, transferSca = true) => {
6254
5621
  const sender = requireSender(txBlock);
6255
5622
  const veSca = await requireVeSca(builder, txBlock, veScaKey);
6256
5623
  checkVesca(veSca?.unlockAt);
6257
5624
  if (veSca) {
6258
5625
  const sca = txBlock.redeemSca(veSca.keyId);
6259
- txBlock.transferObjects([sca], sender);
5626
+ if (transferSca) {
5627
+ txBlock.transferObjects([sca], sender);
5628
+ return;
5629
+ }
5630
+ return sca;
6260
5631
  }
6261
5632
  }
6262
5633
  };
@@ -6294,13 +5665,13 @@ var requireObligationInfo2 = async (...params) => {
6294
5665
  const [builder, txBlock, obligationId, obligationKey] = params;
6295
5666
  if (params.length === 4 && obligationId && obligationKey && typeof obligationId === "string") {
6296
5667
  const obligationLocked = await getObligationLocked(
6297
- builder.query,
5668
+ builder.cache,
6298
5669
  obligationId
6299
5670
  );
6300
5671
  return { obligationId, obligationKey, obligationLocked };
6301
5672
  }
6302
5673
  const sender = requireSender(txBlock);
6303
- const obligations = await getObligations(builder.query, sender);
5674
+ const obligations = await getObligations(builder, sender);
6304
5675
  if (obligations.length === 0) {
6305
5676
  throw new Error(`No obligation found for sender ${sender}`);
6306
5677
  }
@@ -6415,7 +5786,7 @@ var generateBorrowIncentiveQuickMethod = ({ builder, txBlock }) => {
6415
5786
  stakeObligationQuick: async (obligation, obligationKey) => {
6416
5787
  const {
6417
5788
  obligationId: obligationArg,
6418
- obligationKey: obligationtKeyArg,
5789
+ obligationKey: obligationKeyArg,
6419
5790
  obligationLocked
6420
5791
  } = await requireObligationInfo2(
6421
5792
  builder,
@@ -6427,13 +5798,13 @@ var generateBorrowIncentiveQuickMethod = ({ builder, txBlock }) => {
6427
5798
  (txn) => txn.kind === "MoveCall" && (txn.target === `${OLD_BORROW_INCENTIVE_PROTOCOL_ID}::user::unstake` || txn.target === `${builder.address.get("borrowIncentive.id")}::user::unstake`)
6428
5799
  );
6429
5800
  if (!obligationLocked || unstakeObligationBeforeStake) {
6430
- txBlock.stakeObligation(obligationArg, obligationtKeyArg);
5801
+ txBlock.stakeObligation(obligationArg, obligationKeyArg);
6431
5802
  }
6432
5803
  },
6433
5804
  stakeObligationWithVeScaQuick: async (obligation, obligationKey, veScaKey) => {
6434
5805
  const {
6435
5806
  obligationId: obligationArg,
6436
- obligationKey: obligationtKeyArg,
5807
+ obligationKey: obligationKeyArg,
6437
5808
  obligationLocked
6438
5809
  } = await requireObligationInfo2(
6439
5810
  builder,
@@ -6448,27 +5819,27 @@ var generateBorrowIncentiveQuickMethod = ({ builder, txBlock }) => {
6448
5819
  const veSca = await requireVeSca(builder, txBlock, veScaKey);
6449
5820
  if (veSca) {
6450
5821
  const bindedObligationId = await getBindedObligationId(
6451
- builder.query,
5822
+ builder,
6452
5823
  veSca.keyId
6453
5824
  );
6454
5825
  if ((!bindedObligationId || bindedObligationId === obligationArg) && veSca.currentVeScaBalance > 0) {
6455
5826
  txBlock.stakeObligationWithVesca(
6456
5827
  obligationArg,
6457
- obligationtKeyArg,
5828
+ obligationKeyArg,
6458
5829
  veSca.keyId
6459
5830
  );
6460
5831
  } else {
6461
- txBlock.stakeObligation(obligationArg, obligationtKeyArg);
5832
+ txBlock.stakeObligation(obligationArg, obligationKeyArg);
6462
5833
  }
6463
5834
  } else {
6464
- txBlock.stakeObligation(obligationArg, obligationtKeyArg);
5835
+ txBlock.stakeObligation(obligationArg, obligationKeyArg);
6465
5836
  }
6466
5837
  }
6467
5838
  },
6468
5839
  unstakeObligationQuick: async (obligation, obligationKey) => {
6469
5840
  const {
6470
5841
  obligationId: obligationArg,
6471
- obligationKey: obligationtKeyArg,
5842
+ obligationKey: obligationKeyArg,
6472
5843
  obligationLocked
6473
5844
  } = await requireObligationInfo2(
6474
5845
  builder,
@@ -6477,14 +5848,11 @@ var generateBorrowIncentiveQuickMethod = ({ builder, txBlock }) => {
6477
5848
  obligationKey
6478
5849
  );
6479
5850
  if (obligationLocked) {
6480
- txBlock.unstakeObligation(obligationArg, obligationtKeyArg);
5851
+ txBlock.unstakeObligation(obligationArg, obligationKeyArg);
6481
5852
  }
6482
5853
  },
6483
5854
  claimBorrowIncentiveQuick: async (coinName, rewardCoinName, obligation, obligationKey) => {
6484
- const {
6485
- obligationId: obligationArg,
6486
- obligationKey: obligationtKeyArg
6487
- } = await requireObligationInfo2(
5855
+ const { obligationId: obligationArg, obligationKey: obligationKeyArg } = await requireObligationInfo2(
6488
5856
  builder,
6489
5857
  txBlock,
6490
5858
  obligation,
@@ -6492,7 +5860,7 @@ var generateBorrowIncentiveQuickMethod = ({ builder, txBlock }) => {
6492
5860
  );
6493
5861
  return txBlock.claimBorrowIncentive(
6494
5862
  obligationArg,
6495
- obligationtKeyArg,
5863
+ obligationKeyArg,
6496
5864
  coinName,
6497
5865
  rewardCoinName
6498
5866
  );
@@ -6853,38 +6221,783 @@ var newScallopTxBlock = (builder, initTxBlock) => {
6853
6221
  } else if (prop in sCoinTxBlock) {
6854
6222
  return Reflect.get(sCoinTxBlock, prop);
6855
6223
  }
6856
- return Reflect.get(target, prop);
6224
+ return Reflect.get(target, prop);
6225
+ }
6226
+ });
6227
+ };
6228
+
6229
+ // src/models/scallopQuery.ts
6230
+ import { SuiKit as SuiKit4 } from "@scallop-io/sui-kit";
6231
+
6232
+ // src/models/scallopIndexer.ts
6233
+ import axios2 from "axios";
6234
+ import { SuiKit as SuiKit3 } from "@scallop-io/sui-kit";
6235
+ var ScallopIndexer = class {
6236
+ constructor(params, instance) {
6237
+ this.params = params;
6238
+ this.cache = instance?.cache ?? new ScallopCache(new SuiKit3({}), DEFAULT_CACHE_OPTIONS);
6239
+ this._requestClient = axios2.create({
6240
+ baseURL: SDK_API_BASE_URL,
6241
+ headers: {
6242
+ "Content-Type": "application/json",
6243
+ Accept: "application/json"
6244
+ },
6245
+ timeout: 3e4
6246
+ });
6247
+ }
6248
+ /**
6249
+ * Get market index data.
6250
+ *
6251
+ * @return Market data.
6252
+ */
6253
+ async getMarket() {
6254
+ const response = await this.cache.queryClient.fetchQuery({
6255
+ queryKey: ["market"],
6256
+ queryFn: async () => {
6257
+ return await this._requestClient.get(`/api/market`);
6258
+ }
6259
+ });
6260
+ if (response.status === 200) {
6261
+ return {
6262
+ pools: response.data.pools.reduce((marketPools, marketPool) => {
6263
+ marketPools[marketPool.coinName] = marketPool;
6264
+ return marketPools;
6265
+ }, {}),
6266
+ collaterals: response.data.collaterals.reduce(
6267
+ (marketCollaterals, marketCollateral) => {
6268
+ marketCollaterals[marketCollateral.coinName] = marketCollateral;
6269
+ return marketCollaterals;
6270
+ },
6271
+ {}
6272
+ )
6273
+ };
6274
+ } else {
6275
+ throw Error("Failed to getMarket.");
6276
+ }
6277
+ }
6278
+ /**
6279
+ * Get market pools index data.
6280
+ *
6281
+ * @return Market pools data.
6282
+ */
6283
+ async getMarketPools() {
6284
+ const response = (await this.getMarket()).pools;
6285
+ return response;
6286
+ }
6287
+ /**
6288
+ * Get market pool index data.
6289
+ *
6290
+ * @return Market pool data.
6291
+ */
6292
+ async getMarketPool(poolCoinName) {
6293
+ return (await this.getMarketPools())[poolCoinName];
6294
+ }
6295
+ /**
6296
+ * Get market collaterals index data.
6297
+ *
6298
+ * @return Market collaterals data.
6299
+ */
6300
+ async getMarketCollaterals() {
6301
+ return (await this.getMarket()).collaterals;
6302
+ }
6303
+ /**
6304
+ * Get market collateral index data.
6305
+ *
6306
+ * @return Market collateral data.
6307
+ */
6308
+ async getMarketCollateral(collateralCoinName) {
6309
+ return (await this.getMarketCollaterals())[collateralCoinName];
6310
+ }
6311
+ /**
6312
+ * Get spools index data.
6313
+ *
6314
+ * @return Spools data.
6315
+ */
6316
+ async getSpools() {
6317
+ const response = await this.cache.queryClient.fetchQuery({
6318
+ queryKey: ["spools"],
6319
+ queryFn: async () => {
6320
+ return await this._requestClient.get(`/api/spools`);
6321
+ }
6322
+ });
6323
+ if (response.status === 200) {
6324
+ return response.data.spools.reduce((spools, spool) => {
6325
+ spools[spool.marketCoinName] = spool;
6326
+ return spools;
6327
+ }, {});
6328
+ } else {
6329
+ throw Error("Failed to getSpools.");
6330
+ }
6331
+ }
6332
+ /**
6333
+ * Get spool index data.
6334
+ *
6335
+ * @return Spool data.
6336
+ */
6337
+ async getSpool(marketCoinName) {
6338
+ return (await this.getSpools())[marketCoinName];
6339
+ }
6340
+ /**
6341
+ * Get borrow incentive pools index data.
6342
+ *
6343
+ * @return Borrow incentive pools data.
6344
+ */
6345
+ async getBorrowIncentivePools() {
6346
+ const response = await this.cache.queryClient.fetchQuery({
6347
+ queryKey: ["borrowIncentivePools"],
6348
+ queryFn: async () => {
6349
+ return await this._requestClient.get(`/api/borrowIncentivePools`);
6350
+ }
6351
+ });
6352
+ if (response.status === 200) {
6353
+ return response.data.borrowIncentivePools.reduce(
6354
+ (borrowIncentivePools, borrowIncentivePool) => {
6355
+ if (Array.isArray(borrowIncentivePool.points)) {
6356
+ borrowIncentivePool.points = borrowIncentivePool.points.reduce(
6357
+ (prev, curr) => {
6358
+ prev[curr.coinName] = curr;
6359
+ return prev;
6360
+ },
6361
+ {}
6362
+ );
6363
+ }
6364
+ borrowIncentivePools[borrowIncentivePool.coinName] = borrowIncentivePool;
6365
+ return borrowIncentivePools;
6366
+ },
6367
+ {}
6368
+ );
6369
+ } else {
6370
+ throw Error("Failed to getBorrowIncentivePools.");
6371
+ }
6372
+ }
6373
+ /**
6374
+ * Get borrow incentive pool index data.
6375
+ *
6376
+ * @return Borrow incentive pool data.
6377
+ */
6378
+ async getBorrowIncentivePool(borrowIncentiveCoinName) {
6379
+ return (await this.getBorrowIncentivePools())[borrowIncentiveCoinName];
6380
+ }
6381
+ /**
6382
+ * Get total value locked index data.
6383
+ *
6384
+ * @return Total value locked.
6385
+ */
6386
+ async getTotalValueLocked() {
6387
+ const response = await this.cache.queryClient.fetchQuery({
6388
+ queryKey: ["totalValueLocked"],
6389
+ queryFn: async () => {
6390
+ return await this._requestClient.get(`/api/market/tvl`);
6391
+ }
6392
+ });
6393
+ if (response.status === 200) {
6394
+ return response.data;
6395
+ } else {
6396
+ throw Error("Failed to getTotalValueLocked.");
6397
+ }
6398
+ }
6399
+ };
6400
+
6401
+ // src/queries/sCoinQuery.ts
6402
+ import { bcs as bcs2 } from "@mysten/sui.js/bcs";
6403
+ import assert from "assert";
6404
+ import BigNumber7 from "bignumber.js";
6405
+ var getSCoinTotalSupply = async ({
6406
+ utils
6407
+ }, sCoinName) => {
6408
+ const sCoinPkgId = utils.address.get("scoin.id");
6409
+ const args = [utils.getSCoinTreasury(sCoinName)];
6410
+ const typeArgs = [
6411
+ utils.parseSCoinType(sCoinName),
6412
+ utils.parseUnderlyingSCoinType(sCoinName)
6413
+ ];
6414
+ const queryTarget = `${sCoinPkgId}::s_coin_converter::total_supply`;
6415
+ const queryResults = await utils.cache.queryInspectTxn({
6416
+ queryTarget,
6417
+ args,
6418
+ typeArgs
6419
+ });
6420
+ const results = queryResults?.results;
6421
+ if (results && results[0].returnValues) {
6422
+ const value = Uint8Array.from(results[0].returnValues[0][0]);
6423
+ const type = results[0].returnValues[0][1];
6424
+ assert(type === "u64", "Result type is not u64");
6425
+ return BigNumber7(bcs2.de(type, value)).shiftedBy(utils.getCoinDecimal(utils.parseCoinName(sCoinName))).toNumber();
6426
+ }
6427
+ return 0;
6428
+ };
6429
+ var getSCoinAmounts = async ({
6430
+ utils
6431
+ }, sCoinNames, ownerAddress) => {
6432
+ sCoinNames = sCoinNames || [...SUPPORT_SCOIN];
6433
+ const owner = ownerAddress || utils.suiKit.currentAddress();
6434
+ const sCoins2 = {};
6435
+ await Promise.allSettled(
6436
+ sCoinNames.map(async (sCoinName) => {
6437
+ const sCoin = await getSCoinAmount({ utils }, sCoinName, owner);
6438
+ sCoins2[sCoinName] = sCoin;
6439
+ })
6440
+ );
6441
+ return sCoins2;
6442
+ };
6443
+ var getSCoinAmount = async ({
6444
+ utils
6445
+ }, sCoinName, ownerAddress) => {
6446
+ const owner = ownerAddress || utils.suiKit.currentAddress();
6447
+ const sCoinType = utils.parseSCoinType(sCoinName);
6448
+ const amount = await utils.cache.queryGetCoinBalance({
6449
+ owner,
6450
+ coinType: sCoinType
6451
+ });
6452
+ return BigNumber7(amount).toNumber();
6453
+ };
6454
+ var isSupportStakeCoins = (value) => {
6455
+ return SUPPORT_SCOIN.includes(value);
6456
+ };
6457
+ var checkAssetParams = (fromSCoin, toSCoin) => {
6458
+ if (fromSCoin === toSCoin)
6459
+ throw new Error("fromAsset and toAsset must be different");
6460
+ if (!isSupportStakeCoins(fromSCoin))
6461
+ throw new Error("fromAsset is not supported");
6462
+ if (!isSupportStakeCoins(toSCoin)) {
6463
+ throw new Error("toAsset is not supported");
6464
+ }
6465
+ };
6466
+ var getSCoinSwapRate = async (query, fromSCoin, toSCoin, underlyingCoinPrice) => {
6467
+ checkAssetParams(fromSCoin, toSCoin);
6468
+ const fromCoinName = query.utils.parseCoinName(fromSCoin);
6469
+ const toCoinName = query.utils.parseCoinName(toSCoin);
6470
+ const marketPools = await Promise.all([
6471
+ query.getMarketPool(fromCoinName, false),
6472
+ query.getMarketPool(toCoinName, false)
6473
+ ]);
6474
+ if (marketPools.some((pool) => !pool))
6475
+ throw new Error("Failed to fetch the lendings data");
6476
+ if (marketPools.some((pool) => pool?.conversionRate === 0)) {
6477
+ throw new Error("Conversion rate cannot be zero");
6478
+ }
6479
+ const ScoinAToARate = marketPools[0].conversionRate;
6480
+ const BtoSCoinBRate = 1 / marketPools[1].conversionRate;
6481
+ const calcAtoBRate = async () => {
6482
+ const prices = await query.utils.getCoinPrices([fromCoinName, toCoinName]);
6483
+ if (!prices[fromCoinName] || !prices[toCoinName]) {
6484
+ throw new Error("Failed to fetch the coin prices");
6485
+ }
6486
+ if (prices[toCoinName] === 0) {
6487
+ throw new Error("Price of toCoin cannot be zero");
6488
+ }
6489
+ return prices[fromCoinName] / prices[toCoinName];
6490
+ };
6491
+ const AtoBRate = underlyingCoinPrice ?? await calcAtoBRate();
6492
+ return BigNumber7(ScoinAToARate).multipliedBy(AtoBRate).multipliedBy(BtoSCoinBRate).toNumber();
6493
+ };
6494
+
6495
+ // src/models/scallopQuery.ts
6496
+ import { normalizeSuiAddress as normalizeSuiAddress2 } from "@mysten/sui.js/utils";
6497
+ var ScallopQuery = class {
6498
+ constructor(params, instance) {
6499
+ this.params = params;
6500
+ this.suiKit = instance?.suiKit ?? instance?.utils?.suiKit ?? new SuiKit4(params);
6501
+ if (instance?.utils) {
6502
+ this.utils = instance.utils;
6503
+ this.address = instance.utils.address;
6504
+ this.cache = this.address.cache;
6505
+ } else {
6506
+ this.cache = new ScallopCache(this.suiKit, DEFAULT_CACHE_OPTIONS);
6507
+ this.address = new ScallopAddress(
6508
+ {
6509
+ id: params?.addressesId || ADDRESSES_ID,
6510
+ network: params?.networkType
6511
+ },
6512
+ {
6513
+ cache: this.cache
6514
+ }
6515
+ );
6516
+ this.utils = new ScallopUtils(this.params, {
6517
+ address: this.address
6518
+ });
6519
+ }
6520
+ this.indexer = instance?.indexer ?? new ScallopIndexer(this.params, { cache: this.cache });
6521
+ this.walletAddress = normalizeSuiAddress2(
6522
+ params.walletAddress || this.suiKit.currentAddress()
6523
+ );
6524
+ }
6525
+ /**
6526
+ * Request the scallop API to initialize data.
6527
+ *
6528
+ * @param force - Whether to force initialization.
6529
+ * @param address - ScallopAddress instance.
6530
+ */
6531
+ async init(force = false, address) {
6532
+ if (force || !this.address.getAddresses() || !address?.getAddresses()) {
6533
+ await this.address.read();
6534
+ } else {
6535
+ this.address = address;
6536
+ }
6537
+ await this.utils.init(force, this.address);
6538
+ }
6539
+ /* ==================== Core Query Methods ==================== */
6540
+ /**
6541
+ * Query market data.
6542
+ * @param indexer - Whether to use indexer.
6543
+ * @return Market data.
6544
+ */
6545
+ async queryMarket(indexer = false) {
6546
+ return await queryMarket(this, indexer);
6547
+ }
6548
+ /**
6549
+ * Get market pools.
6550
+ *
6551
+ * @description
6552
+ * To obtain all market pools at once, it is recommended to use
6553
+ * the `queryMarket` method to reduce time consumption.
6554
+ *
6555
+ * @param poolCoinNames - Specific an array of support pool coin name.
6556
+ * @param indexer - Whether to use indexer.
6557
+ * @return Market pools data.
6558
+ */
6559
+ async getMarketPools(poolCoinNames, indexer = false) {
6560
+ return await getMarketPools(this, poolCoinNames, indexer);
6561
+ }
6562
+ /**
6563
+ * Get market pool
6564
+ *
6565
+ * @param poolCoinName - Specific support pool coin name.
6566
+ * @param indexer - Whether to use indexer.
6567
+ * @return Market pool data.
6568
+ */
6569
+ async getMarketPool(poolCoinName, indexer = false) {
6570
+ return await getMarketPool(this, poolCoinName, indexer);
6571
+ }
6572
+ /**
6573
+ * Get market collaterals.
6574
+ *
6575
+ * @description
6576
+ * To obtain all market collaterals at once, it is recommended to use
6577
+ * the `queryMarket` method to reduce time consumption.
6578
+ *
6579
+ * @param collateralCoinNames - Specific an array of support collateral coin name.
6580
+ * @param indexer - Whether to use indexer.
6581
+ * @return Market collaterals data.
6582
+ */
6583
+ async getMarketCollaterals(collateralCoinNames, indexer = false) {
6584
+ return await getMarketCollaterals(this, collateralCoinNames, indexer);
6585
+ }
6586
+ /**
6587
+ * Get market collateral
6588
+ *
6589
+ * @param collateralCoinName - Specific support collateral coin name.
6590
+ * @param indexer - Whether to use indexer.
6591
+ * @return Market collateral data.
6592
+ */
6593
+ async getMarketCollateral(collateralCoinName, indexer = false) {
6594
+ return await getMarketCollateral(this, collateralCoinName, indexer);
6595
+ }
6596
+ /**
6597
+ * Get obligations data.
6598
+ *
6599
+ * @param ownerAddress - The owner address.
6600
+ * @return Obligations data.
6601
+ */
6602
+ async getObligations(ownerAddress = this.walletAddress) {
6603
+ return await getObligations(this, ownerAddress);
6604
+ }
6605
+ /**
6606
+ * Query obligation data.
6607
+ *
6608
+ * @param obligationId - The obligation id.
6609
+ * @return Obligation data.
6610
+ */
6611
+ async queryObligation(obligationId) {
6612
+ return queryObligation(this, obligationId);
6613
+ }
6614
+ /**
6615
+ * Get all asset coin amounts.
6616
+ *
6617
+ * @param assetCoinNames - Specific an array of support asset coin name.
6618
+ * @param ownerAddress - The owner address.
6619
+ * @return All coin amounts.
6620
+ */
6621
+ async getCoinAmounts(assetCoinNames, ownerAddress = this.walletAddress) {
6622
+ return await getCoinAmounts(this, assetCoinNames, ownerAddress);
6623
+ }
6624
+ /**
6625
+ * Get asset coin amount.
6626
+ *
6627
+ * @param assetCoinName - Specific support asset coin name.
6628
+ * @param ownerAddress - The owner address.
6629
+ * @return Coin amount.
6630
+ */
6631
+ async getCoinAmount(assetCoinName, ownerAddress = this.walletAddress) {
6632
+ return await getCoinAmount(this, assetCoinName, ownerAddress);
6633
+ }
6634
+ /**
6635
+ * Get all market coin amounts.
6636
+ *
6637
+ * @param coinNames - Specific an array of support market coin name.
6638
+ * @param ownerAddress - The owner address.
6639
+ * @return All market market coin amounts.
6640
+ */
6641
+ async getMarketCoinAmounts(marketCoinNames, ownerAddress = this.walletAddress) {
6642
+ return await getMarketCoinAmounts(this, marketCoinNames, ownerAddress);
6643
+ }
6644
+ /**
6645
+ * Get market coin amount.
6646
+ *
6647
+ * @param coinNames - Specific support market coin name.
6648
+ * @param ownerAddress - The owner address.
6649
+ * @return Market market coin amount.
6650
+ */
6651
+ async getMarketCoinAmount(marketCoinName, ownerAddress = this.walletAddress) {
6652
+ return await getMarketCoinAmount(this, marketCoinName, ownerAddress);
6653
+ }
6654
+ /**
6655
+ * Get price from pyth fee object.
6656
+ *
6657
+ * @param assetCoinName - Specific support asset coin name.
6658
+ * @return Asset coin price.
6659
+ */
6660
+ async getPriceFromPyth(assetCoinName) {
6661
+ return await getPythPrice(this, assetCoinName);
6662
+ }
6663
+ /**
6664
+ * Get prices from pyth fee object.
6665
+ *
6666
+ * @param assetCoinNames - Array of supported asset coin names.
6667
+ * @return Array of asset coin prices.
6668
+ */
6669
+ async getPricesFromPyth(assetCoinNames) {
6670
+ return await getPythPrices(this, assetCoinNames);
6671
+ }
6672
+ /* ==================== Spool Query Methods ==================== */
6673
+ /**
6674
+ * Get spools data.
6675
+ *
6676
+ * @param stakeMarketCoinNames - Specific an array of support stake market coin name.
6677
+ * @param indexer - Whether to use indexer.
6678
+ * @return Spools data.
6679
+ */
6680
+ async getSpools(stakeMarketCoinNames, indexer = false) {
6681
+ return await getSpools(this, stakeMarketCoinNames, indexer);
6682
+ }
6683
+ /**
6684
+ * Get spool data.
6685
+ *
6686
+ * @param stakeMarketCoinName - Specific support stake market coin name.
6687
+ * @param indexer - Whether to use indexer.
6688
+ * @return Spool data.
6689
+ */
6690
+ async getSpool(stakeMarketCoinName, indexer = false) {
6691
+ return await getSpool(this, stakeMarketCoinName, indexer);
6692
+ }
6693
+ /**
6694
+ * Get stake accounts data for all stake pools (spools).
6695
+ *
6696
+ * @param ownerAddress - The owner address.
6697
+ * @return All Stake accounts data.
6698
+ */
6699
+ async getAllStakeAccounts(ownerAddress = this.walletAddress) {
6700
+ return await getStakeAccounts(this, ownerAddress);
6701
+ }
6702
+ /**
6703
+ * Get stake accounts data for specific stake pool (spool).
6704
+ *
6705
+ * @param stakeMarketCoinName - Specific support stake market coin name.
6706
+ * @param ownerAddress - The owner address.
6707
+ * @return Stake accounts data.
6708
+ */
6709
+ async getStakeAccounts(stakeMarketCoinName, ownerAddress = this.walletAddress) {
6710
+ const allStakeAccount = await this.getAllStakeAccounts(ownerAddress);
6711
+ return allStakeAccount[stakeMarketCoinName] ?? [];
6712
+ }
6713
+ /**
6714
+ * Get stake pools (spools) data.
6715
+ *
6716
+ * @description
6717
+ * For backward compatible, it is recommended to use `getSpools` method
6718
+ * to get all spools data.
6719
+ *
6720
+ * @param stakeMarketCoinNames - Specific an array of support stake market coin name.
6721
+ * @return Stake pools data.
6722
+ */
6723
+ async getStakePools(stakeMarketCoinNames = [...SUPPORT_SPOOLS]) {
6724
+ const stakePools = {};
6725
+ for (const stakeMarketCoinName of stakeMarketCoinNames) {
6726
+ const stakePool = await getStakePool(this, stakeMarketCoinName);
6727
+ if (stakePool) {
6728
+ stakePools[stakeMarketCoinName] = stakePool;
6729
+ }
6857
6730
  }
6858
- });
6731
+ return stakePools;
6732
+ }
6733
+ /**
6734
+ * Get stake pool (spool) data.
6735
+ *
6736
+ * @description
6737
+ * For backward compatible, it is recommended to use `getSpool` method
6738
+ * to get all spool data.
6739
+ *
6740
+ * @param stakeMarketCoinName - Specific support stake market coin name.
6741
+ * @return Stake pool data.
6742
+ */
6743
+ async getStakePool(stakeMarketCoinName) {
6744
+ return await getStakePool(this, stakeMarketCoinName);
6745
+ }
6746
+ /**
6747
+ * Get stake reward pools data.
6748
+ *
6749
+ * @description
6750
+ * For backward compatible, it is recommended to use `getSpools` method
6751
+ * to get all spools data.
6752
+ *
6753
+ * @param stakeMarketCoinNames - Specific an array of stake market coin name.
6754
+ * @return Stake reward pools data.
6755
+ */
6756
+ async getStakeRewardPools(stakeMarketCoinNames = [...SUPPORT_SPOOLS]) {
6757
+ const stakeRewardPools = {};
6758
+ await Promise.allSettled(
6759
+ stakeMarketCoinNames.map(async (stakeMarketCoinName) => {
6760
+ const stakeRewardPool = await getStakeRewardPool(
6761
+ this,
6762
+ stakeMarketCoinName
6763
+ );
6764
+ if (stakeRewardPool) {
6765
+ stakeRewardPools[stakeMarketCoinName] = stakeRewardPool;
6766
+ }
6767
+ })
6768
+ );
6769
+ return stakeRewardPools;
6770
+ }
6771
+ /**
6772
+ * Get stake reward pool data.
6773
+ *
6774
+ * @description
6775
+ * For backward compatible, it is recommended to use `getSpool` method
6776
+ * to get spool data.
6777
+ *
6778
+ * @param marketCoinName - Specific support stake market coin name.
6779
+ * @return Stake reward pool data.
6780
+ */
6781
+ async getStakeRewardPool(stakeMarketCoinName) {
6782
+ return await getStakeRewardPool(this, stakeMarketCoinName);
6783
+ }
6784
+ /**
6785
+ * Get borrow incentive pools data.
6786
+ *
6787
+ * @param coinNames - Specific an array of support borrow incentive coin name.
6788
+ * @param indexer - Whether to use indexer.
6789
+ * @return Borrow incentive pools data.
6790
+ */
6791
+ async getBorrowIncentivePools(coinNames, indexer = false) {
6792
+ return await queryBorrowIncentivePools(this, coinNames, indexer);
6793
+ }
6794
+ /**
6795
+ * Get borrow incentive accounts data.
6796
+ *
6797
+ * @param coinNames - Specific support borrow incentive coin name.
6798
+ * @param ownerAddress - The owner address.
6799
+ * @return Borrow incentive accounts data.
6800
+ */
6801
+ async getBorrowIncentiveAccounts(obligationId, coinNames) {
6802
+ return await queryBorrowIncentiveAccounts(this, obligationId, coinNames);
6803
+ }
6804
+ /**
6805
+ * Get user lending and spool infomation for specific pools.
6806
+ *
6807
+ * @param poolCoinNames - Specific an array of support pool coin name.
6808
+ * @param ownerAddress - The owner address.
6809
+ * @param indexer - Whether to use indexer.
6810
+ * @return All lending and spool infomation.
6811
+ */
6812
+ async getLendings(poolCoinNames, ownerAddress = this.walletAddress, indexer = false) {
6813
+ return await getLendings(this, poolCoinNames, ownerAddress, indexer);
6814
+ }
6815
+ /**
6816
+ * Get user lending and spool information for specific pool.
6817
+ *
6818
+ * @param poolCoinName - Specific support pool coin name.
6819
+ * @param ownerAddress - The owner address.
6820
+ * @param indexer - Whether to use indexer.
6821
+ * @return Lending pool data.
6822
+ */
6823
+ async getLending(poolCoinName, ownerAddress = this.walletAddress, indexer = false) {
6824
+ return await getLending(this, poolCoinName, ownerAddress, indexer);
6825
+ }
6826
+ /**
6827
+ * Get user all obligation accounts information.
6828
+ *
6829
+ * @description
6830
+ * All collateral and borrowing information in all obligation accounts owned by the user.
6831
+ *
6832
+ * @param ownerAddress - The owner address.
6833
+ * @param indexer - Whether to use indexer.
6834
+ * @return All obligation accounts information.
6835
+ */
6836
+ async getObligationAccounts(ownerAddress = this.walletAddress, indexer = false) {
6837
+ return await getObligationAccounts(this, ownerAddress, indexer);
6838
+ }
6839
+ /**
6840
+ * Get obligation account information for specific id.
6841
+ *
6842
+ * @description
6843
+ * borrowing and obligation information for specific pool.
6844
+ *
6845
+ * @param obligationId - The obligation id.
6846
+ * @param ownerAddress - The owner address.
6847
+ * @param indexer - Whether to use indexer.
6848
+ * @return Borrowing and collateral information.
6849
+ */
6850
+ async getObligationAccount(obligationId, ownerAddress = this.walletAddress, indexer = false) {
6851
+ return await getObligationAccount(
6852
+ this,
6853
+ obligationId,
6854
+ ownerAddress,
6855
+ indexer
6856
+ );
6857
+ }
6858
+ /**
6859
+ * Get total value locked.
6860
+ *
6861
+ * @param indexer - Whether to use indexer.
6862
+ * @description
6863
+ * Include total supplied value and total borrowed value.
6864
+ *
6865
+ * @return Total value locked.
6866
+ */
6867
+ async getTvl(indexer = false) {
6868
+ return await getTotalValueLocked(this, indexer);
6869
+ }
6870
+ /**
6871
+ * Get all veSca from walletAdddress
6872
+ * @param walletAddress
6873
+ * @returns array of veSca
6874
+ */
6875
+ async getVeScas(walletAddress = this.walletAddress) {
6876
+ return await getVeScas(this, walletAddress);
6877
+ }
6878
+ /**
6879
+ * Get total vesca treasury with movecall
6880
+ * @returns Promise<string | undefined>
6881
+ */
6882
+ async getVeScaTreasuryInfo() {
6883
+ return await getVeScaTreasuryInfo(this.utils);
6884
+ }
6885
+ /**
6886
+ * Return binded referrer veScaKeyId of referee walletAddress if exist
6887
+ * @param walletAddress
6888
+ * @returns veScaKeyId
6889
+ */
6890
+ async getVeScaKeyIdFromReferralBindings(walletAddress = this.walletAddress) {
6891
+ return await queryVeScaKeyIdFromReferralBindings(
6892
+ this.address,
6893
+ walletAddress
6894
+ );
6895
+ }
6896
+ /**
6897
+ * Get binded obligationId from a veScaKey if it exists.
6898
+ * @param veScaKey
6899
+ * @returns obligationId
6900
+ */
6901
+ async getBindedObligationId(veScaKey) {
6902
+ return await getBindedObligationId(this, veScaKey);
6903
+ }
6904
+ /**
6905
+ * Get binded veSCA key from a obligationId if it exists.
6906
+ * @param obligationId
6907
+ * @returns veScaKey
6908
+ */
6909
+ async getBindedVeScaKey(obligationId) {
6910
+ return await getBindedVeScaKey(this, obligationId);
6911
+ }
6912
+ /**
6913
+ * Get user's veSCA loyalty program informations
6914
+ * @param walletAddress
6915
+ * @returns Loyalty program information
6916
+ */
6917
+ async getLoyaltyProgramInfos(veScaKey) {
6918
+ return await getLoyaltyProgramInformations(this, veScaKey);
6919
+ }
6920
+ /**
6921
+ * Get total supply of sCoin
6922
+ * @param sCoinName - Supported sCoin name
6923
+ * @returns Total Supply
6924
+ */
6925
+ async getSCoinTotalSupply(sCoinName) {
6926
+ return await getSCoinTotalSupply(this, sCoinName);
6927
+ }
6928
+ /**
6929
+ * Get all sCoin amounts.
6930
+ *
6931
+ * @param sCoinNames - Specific an array of support sCoin name.
6932
+ * @param ownerAddress - The owner address.
6933
+ * @return All market sCoin amounts.
6934
+ */
6935
+ async getSCoinAmounts(sCoinNames, ownerAddress = this.walletAddress) {
6936
+ return await getSCoinAmounts(this, sCoinNames, ownerAddress);
6937
+ }
6938
+ /**
6939
+ * Get sCoin amount.
6940
+ *
6941
+ * @param coinNames - Specific support sCoin name.
6942
+ * @param ownerAddress - The owner address.
6943
+ * @return sCoin amount.
6944
+ */
6945
+ async getSCoinAmount(sCoinName, ownerAddress = this.walletAddress) {
6946
+ const parsedSCoinName = this.utils.parseSCoinName(sCoinName);
6947
+ return parsedSCoinName ? await getSCoinAmount(this, parsedSCoinName, ownerAddress) : 0;
6948
+ }
6949
+ /**
6950
+ * Get swap rate from sCoin A to sCoin B
6951
+ * @param assetCoinNames
6952
+ * @returns
6953
+ */
6954
+ async getSCoinSwapRate(fromSCoin, toSCoin) {
6955
+ return await getSCoinSwapRate(this, fromSCoin, toSCoin);
6956
+ }
6957
+ /*
6958
+ * Get flashloan fee for specified assets
6959
+ */
6960
+ async getFlashLoanFees(assetCoinNames = [...SUPPORT_POOLS]) {
6961
+ return await getFlashLoanFees(this, assetCoinNames);
6962
+ }
6859
6963
  };
6860
6964
 
6861
6965
  // src/models/scallopBuilder.ts
6862
6966
  var ScallopBuilder = class {
6863
6967
  constructor(params, instance) {
6968
+ this.suiKit = instance?.suiKit ?? new SuiKit5(params);
6864
6969
  this.params = params;
6865
- this.suiKit = instance?.suiKit ?? new SuiKit3(params);
6866
- this.cache = instance?.cache ?? new ScallopCache(DEFAULT_CACHE_OPTIONS, this.suiKit);
6867
- this.address = instance?.address ?? new ScallopAddress(
6868
- {
6869
- id: params?.addressesId || ADDRESSES_ID,
6870
- network: params?.networkType
6871
- },
6872
- this.cache
6873
- );
6874
- this.query = instance?.query ?? new ScallopQuery(params, {
6875
- suiKit: this.suiKit,
6876
- address: this.address,
6877
- cache: this.cache
6878
- });
6879
- this.utils = instance?.utils ?? new ScallopUtils(this.params, {
6880
- suiKit: this.suiKit,
6881
- address: this.address,
6882
- query: this.query,
6883
- cache: this.cache
6884
- });
6885
6970
  this.walletAddress = normalizeSuiAddress3(
6886
6971
  params?.walletAddress || this.suiKit.currentAddress()
6887
6972
  );
6973
+ if (instance?.query) {
6974
+ this.query = instance.query;
6975
+ this.utils = this.query.utils;
6976
+ this.address = this.utils.address;
6977
+ this.cache = this.address.cache;
6978
+ } else {
6979
+ this.cache = new ScallopCache(this.suiKit, DEFAULT_CACHE_OPTIONS);
6980
+ this.address = new ScallopAddress(
6981
+ {
6982
+ id: params?.addressesId || ADDRESSES_ID,
6983
+ network: params?.networkType
6984
+ },
6985
+ {
6986
+ cache: this.cache
6987
+ }
6988
+ );
6989
+ this.utils = new ScallopUtils(this.params, {
6990
+ address: this.address
6991
+ });
6992
+ this.query = new ScallopQuery(
6993
+ {
6994
+ walletAddress: this.walletAddress
6995
+ },
6996
+ {
6997
+ utils: this.utils
6998
+ }
6999
+ );
7000
+ }
6888
7001
  this.isTestnet = params.networkType ? params.networkType === "testnet" : false;
6889
7002
  }
6890
7003
  /**
@@ -6921,10 +7034,15 @@ var ScallopBuilder = class {
6921
7034
  * @return Take coin and left coin.
6922
7035
  */
6923
7036
  async selectCoin(txBlock, assetCoinName, amount, sender = this.walletAddress) {
6924
- const coinType = this.utils.parseCoinType(assetCoinName);
6925
- const coins = await this.utils.selectCoins(amount, coinType, sender);
6926
- const [takeCoin, leftCoin] = txBlock.takeAmountFromCoins(coins, amount);
6927
- return { takeCoin, leftCoin };
7037
+ if (assetCoinName === "sui") {
7038
+ const [takeCoin] = txBlock.splitSUIFromGas([amount]);
7039
+ return { takeCoin };
7040
+ } else {
7041
+ const coinType = this.utils.parseCoinType(assetCoinName);
7042
+ const coins = await this.utils.selectCoins(amount, coinType, sender);
7043
+ const [takeCoin, leftCoin] = txBlock.takeAmountFromCoins(coins, amount);
7044
+ return { takeCoin, leftCoin };
7045
+ }
6928
7046
  }
6929
7047
  /**
6930
7048
  * Specifying the sender's amount of market coins to get coins args from transaction result.
@@ -6990,36 +7108,37 @@ var ScallopBuilder = class {
6990
7108
  var ScallopClient = class {
6991
7109
  constructor(params, instance) {
6992
7110
  this.params = params;
6993
- this.suiKit = instance?.suiKit ?? new SuiKit4(params);
6994
- this.cache = instance?.cache ?? new ScallopCache(DEFAULT_CACHE_OPTIONS, this.suiKit);
6995
- this.address = instance?.address ?? new ScallopAddress(
6996
- {
6997
- id: params?.addressesId || ADDRESSES_ID,
6998
- network: params?.networkType
6999
- },
7000
- this.cache
7001
- );
7002
- this.query = instance?.query ?? new ScallopQuery(params, {
7003
- suiKit: this.suiKit,
7004
- address: this.address,
7005
- cache: this.cache
7006
- });
7007
- this.utils = instance?.utils ?? new ScallopUtils(params, {
7008
- suiKit: this.suiKit,
7009
- address: this.address,
7010
- query: this.query,
7011
- cache: this.cache
7012
- });
7013
- this.builder = instance?.builder ?? new ScallopBuilder(params, {
7014
- suiKit: this.suiKit,
7015
- address: this.address,
7016
- query: this.query,
7017
- utils: this.utils,
7018
- cache: this.cache
7019
- });
7111
+ this.suiKit = instance?.suiKit ?? instance?.builder?.suiKit ?? new SuiKit6(params);
7020
7112
  this.walletAddress = normalizeSuiAddress4(
7021
7113
  params?.walletAddress || this.suiKit.currentAddress()
7022
7114
  );
7115
+ if (instance?.builder) {
7116
+ this.builder = instance.builder;
7117
+ this.query = this.builder.query;
7118
+ this.utils = this.query.utils;
7119
+ this.address = this.utils.address;
7120
+ this.cache = this.address.cache;
7121
+ } else {
7122
+ this.cache = new ScallopCache(this.suiKit, DEFAULT_CACHE_OPTIONS);
7123
+ this.address = new ScallopAddress(
7124
+ {
7125
+ id: params?.addressesId || ADDRESSES_ID,
7126
+ network: params?.networkType
7127
+ },
7128
+ {
7129
+ cache: this.cache
7130
+ }
7131
+ );
7132
+ this.utils = new ScallopUtils(this.params, {
7133
+ address: this.address
7134
+ });
7135
+ this.query = new ScallopQuery(this.params, {
7136
+ utils: this.utils
7137
+ });
7138
+ this.builder = new ScallopBuilder(this.params, {
7139
+ query: this.query
7140
+ });
7141
+ }
7023
7142
  }
7024
7143
  /**
7025
7144
  * Request the scallop API to initialize data.
@@ -7585,6 +7704,48 @@ var ScallopClient = class {
7585
7704
  return txBlock.txBlock;
7586
7705
  }
7587
7706
  }
7707
+ async claimAllUnlockedSca(sign = true) {
7708
+ const veScaKeys = (await this.query.getVeScas(this.walletAddress) ?? []).map(({ keyObject }) => keyObject);
7709
+ if (veScaKeys.length === 0) {
7710
+ throw new Error("No veSCA found in the wallet");
7711
+ }
7712
+ const scaCoins = [];
7713
+ const tx = this.builder.createTxBlock();
7714
+ tx.setSender(this.walletAddress);
7715
+ await Promise.all(
7716
+ veScaKeys.map(async (key) => {
7717
+ try {
7718
+ const scaCoin = await tx.redeemScaQuick(key, false);
7719
+ if (!scaCoin)
7720
+ return;
7721
+ scaCoins.push(scaCoin);
7722
+ } catch (e) {
7723
+ }
7724
+ })
7725
+ );
7726
+ if (scaCoins.length === 0) {
7727
+ throw new Error("No unlocked SCA found in the veSCA accounts");
7728
+ }
7729
+ if (scaCoins.length > 1) {
7730
+ tx.mergeCoins(scaCoins[0], scaCoins.slice(1));
7731
+ }
7732
+ await this.utils.mergeSimilarCoins(
7733
+ tx,
7734
+ scaCoins[0],
7735
+ "sca",
7736
+ this.walletAddress
7737
+ );
7738
+ if (sign) {
7739
+ return await this.suiKit.signAndSendTxn(
7740
+ tx
7741
+ );
7742
+ } else {
7743
+ return {
7744
+ tx: tx.txBlock,
7745
+ scaCoin: scaCoins[0]
7746
+ };
7747
+ }
7748
+ }
7588
7749
  async mintTestCoin(assetCoinName, amount, sign = true, receiveAddress) {
7589
7750
  const isTestnet = this.params.networkType ? this.params.networkType === "testnet" : false;
7590
7751
  if (!isTestnet) {
@@ -7611,18 +7772,18 @@ var ScallopClient = class {
7611
7772
  var Scallop = class {
7612
7773
  constructor(params, cacheOptions, tokenBucket) {
7613
7774
  this.params = params;
7614
- this.suiKit = new SuiKit5(params);
7775
+ this.suiKit = new SuiKit7(params);
7615
7776
  this.cache = new ScallopCache(
7616
- cacheOptions ?? DEFAULT_CACHE_OPTIONS,
7617
7777
  this.suiKit,
7778
+ cacheOptions ?? DEFAULT_CACHE_OPTIONS,
7618
7779
  tokenBucket ?? new TokenBucket(DEFAULT_TOKENS_PER_INTERVAL, DEFAULT_INTERVAL_IN_MS)
7619
7780
  );
7620
- this._address = new ScallopAddress(
7781
+ this.address = new ScallopAddress(
7621
7782
  {
7622
7783
  id: params?.addressesId || ADDRESSES_ID,
7623
7784
  network: params?.networkType
7624
7785
  },
7625
- this.cache
7786
+ { cache: this.cache }
7626
7787
  );
7627
7788
  }
7628
7789
  /**
@@ -7632,8 +7793,8 @@ var Scallop = class {
7632
7793
  * @return Scallop Address.
7633
7794
  */
7634
7795
  async getScallopAddress(id) {
7635
- await this._address.read(id);
7636
- return this._address;
7796
+ await this.address.read(id);
7797
+ return this.address;
7637
7798
  }
7638
7799
  /**
7639
7800
  * Create a scallop builder instance that already has initial data.
@@ -7641,12 +7802,10 @@ var Scallop = class {
7641
7802
  * @return Scallop Builder.
7642
7803
  */
7643
7804
  async createScallopBuilder() {
7644
- if (!this._address.getAddresses())
7645
- await this._address.read();
7805
+ if (!this.address.getAddresses())
7806
+ await this.address.read();
7646
7807
  const scallopBuilder = new ScallopBuilder(this.params, {
7647
- suiKit: this.suiKit,
7648
- address: this._address,
7649
- cache: this.cache
7808
+ query: await this.createScallopQuery()
7650
7809
  });
7651
7810
  return scallopBuilder;
7652
7811
  }
@@ -7657,11 +7816,11 @@ var Scallop = class {
7657
7816
  * @return Scallop Client.
7658
7817
  */
7659
7818
  async createScallopClient(walletAddress) {
7660
- if (!this._address.getAddresses())
7661
- await this._address.read();
7819
+ if (!this.address.getAddresses())
7820
+ await this.address.read();
7662
7821
  const scallopClient = new ScallopClient(
7663
7822
  { ...this.params, walletAddress },
7664
- { suiKit: this.suiKit, address: this._address, cache: this.cache }
7823
+ { builder: await this.createScallopBuilder() }
7665
7824
  );
7666
7825
  return scallopClient;
7667
7826
  }
@@ -7671,12 +7830,10 @@ var Scallop = class {
7671
7830
  * @return Scallop Query.
7672
7831
  */
7673
7832
  async createScallopQuery() {
7674
- if (!this._address.getAddresses())
7675
- await this._address.read();
7833
+ if (!this.address.getAddresses())
7834
+ await this.address.read();
7676
7835
  const scallopQuery = new ScallopQuery(this.params, {
7677
- suiKit: this.suiKit,
7678
- address: this._address,
7679
- cache: this.cache
7836
+ utils: await this.createScallopUtils()
7680
7837
  });
7681
7838
  return scallopQuery;
7682
7839
  }
@@ -7697,12 +7854,10 @@ var Scallop = class {
7697
7854
  * @return Scallop Utils.
7698
7855
  */
7699
7856
  async createScallopUtils() {
7700
- if (!this._address.getAddresses())
7701
- await this._address.read();
7857
+ if (!this.address.getAddresses())
7858
+ await this.address.read();
7702
7859
  const scallopUtils = new ScallopUtils(this.params, {
7703
- suiKit: this.suiKit,
7704
- address: this._address,
7705
- cache: this.cache
7860
+ address: this.address
7706
7861
  });
7707
7862
  return scallopUtils;
7708
7863
  }