@scallop-io/sui-scallop-sdk 0.44.27 → 0.45.0

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 (39) hide show
  1. package/dist/builders/borrowIncentiveBuilder.d.ts +0 -7
  2. package/dist/constants/cache.d.ts +8 -0
  3. package/dist/index.js +538 -268
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.mjs +522 -253
  6. package/dist/index.mjs.map +1 -1
  7. package/dist/models/index.d.ts +1 -0
  8. package/dist/models/scallop.d.ts +7 -1
  9. package/dist/models/scallopAddress.d.ts +4 -2
  10. package/dist/models/scallopBuilder.d.ts +2 -0
  11. package/dist/models/scallopCache.d.ts +71 -0
  12. package/dist/models/scallopClient.d.ts +2 -0
  13. package/dist/models/scallopIndexer.d.ts +5 -3
  14. package/dist/models/scallopQuery.d.ts +14 -0
  15. package/dist/models/scallopUtils.d.ts +1 -0
  16. package/dist/queries/borrowIncentiveQuery.d.ts +8 -0
  17. package/dist/types/model.d.ts +2 -0
  18. package/dist/types/query/vesca.d.ts +2 -1
  19. package/package.json +2 -1
  20. package/src/builders/borrowIncentiveBuilder.ts +8 -57
  21. package/src/builders/vescaBuilder.ts +7 -3
  22. package/src/constants/cache.ts +15 -0
  23. package/src/models/index.ts +1 -0
  24. package/src/models/scallop.ts +26 -7
  25. package/src/models/scallopAddress.ts +24 -19
  26. package/src/models/scallopBuilder.ts +14 -4
  27. package/src/models/scallopCache.ts +245 -0
  28. package/src/models/scallopClient.ts +15 -4
  29. package/src/models/scallopIndexer.ts +58 -84
  30. package/src/models/scallopQuery.ts +34 -5
  31. package/src/models/scallopUtils.ts +53 -24
  32. package/src/queries/borrowIncentiveQuery.ts +99 -7
  33. package/src/queries/coreQuery.ts +62 -75
  34. package/src/queries/priceQuery.ts +4 -6
  35. package/src/queries/spoolQuery.ts +12 -15
  36. package/src/queries/vescaQuery.ts +20 -8
  37. package/src/types/model.ts +2 -0
  38. package/src/types/query/borrowIncentive.ts +0 -107
  39. package/src/types/query/vesca.ts +2 -1
package/dist/index.mjs CHANGED
@@ -194,6 +194,197 @@ var MIN_TOP_UP_AMOUNT = 1e9;
194
194
  // src/models/scallop.ts
195
195
  import { SuiKit as SuiKit5 } from "@scallop-io/sui-kit";
196
196
 
197
+ // src/models/scallopCache.ts
198
+ import { QueryClient } from "@tanstack/query-core";
199
+ import { SuiTxBlock } from "@scallop-io/sui-kit";
200
+
201
+ // src/constants/cache.ts
202
+ var DEFAULT_CACHE_OPTIONS = {
203
+ defaultOptions: {
204
+ queries: {
205
+ staleTime: 3e3
206
+ }
207
+ }
208
+ };
209
+
210
+ // src/models/scallopCache.ts
211
+ var ScallopCache = class {
212
+ constructor(cacheOptions, suiKit) {
213
+ this.queryClient = new QueryClient(cacheOptions ?? DEFAULT_CACHE_OPTIONS);
214
+ this._suiKit = suiKit;
215
+ }
216
+ get suiKit() {
217
+ if (!this._suiKit) {
218
+ throw new Error("SuiKit instance is not initialized");
219
+ }
220
+ return this._suiKit;
221
+ }
222
+ /**
223
+ * @description Invalidate cache based on the refetchType parameter
224
+ * @param refetchType Determines the type of queries to be refetched. Defaults to `active`.
225
+ *
226
+ * - `active`: Only queries that match the refetch predicate and are actively being rendered via useQuery and related functions will be refetched in the background.
227
+ * - `inactive`: Only queries that match the refetch predicate and are NOT actively being rendered via useQuery and related functions will be refetched in the background.
228
+ * - `all`: All queries that match the refetch predicate will be refetched in the background.
229
+ * - `none`: No queries will be refetched. Queries that match the refetch predicate will only be marked as invalid.
230
+ */
231
+ invalidateAndRefetchAllCache(refetchType) {
232
+ return this.queryClient.invalidateQueries({
233
+ refetchType
234
+ });
235
+ }
236
+ /**
237
+ * @description Cache protocol config call for 60 seconds.
238
+ * @returns Promise<ProtocolConfig>
239
+ */
240
+ async getProtocolConfig() {
241
+ return await this.queryClient.fetchQuery({
242
+ queryKey: ["getProtocolConfig"],
243
+ queryFn: async () => {
244
+ return await this.suiKit.client().getProtocolConfig();
245
+ },
246
+ staleTime: 3e4
247
+ });
248
+ }
249
+ /**
250
+ * @description Provides cache for inspectTxn of the SuiKit.
251
+ * @param QueryInspectTxnParams
252
+ * @param txBlock
253
+ * @returns Promise<DevInspectResults>
254
+ */
255
+ async queryInspectTxn({
256
+ queryTarget,
257
+ args,
258
+ typeArgs
259
+ }) {
260
+ const txBlock = new SuiTxBlock();
261
+ const resolvedArgs = await Promise.all(
262
+ args.map(async (arg) => {
263
+ if (typeof arg === "string") {
264
+ return (await this.queryGetObject(arg, { showContent: true })).data;
265
+ }
266
+ return arg;
267
+ })
268
+ );
269
+ txBlock.moveCall(queryTarget, resolvedArgs, typeArgs);
270
+ const txBytes = await txBlock.txBlock.build({
271
+ client: this.suiKit.client(),
272
+ onlyTransactionKind: true,
273
+ protocolConfig: await this.getProtocolConfig()
274
+ });
275
+ const query = await this.queryClient.fetchQuery({
276
+ queryKey: typeArgs ? ["inspectTxn", queryTarget, JSON.stringify(args)] : [
277
+ "inspectTxn",
278
+ queryTarget,
279
+ JSON.stringify(args),
280
+ JSON.stringify(typeArgs)
281
+ ],
282
+ queryFn: async () => {
283
+ return await this.suiKit.inspectTxn(txBytes);
284
+ },
285
+ staleTime: 8e3
286
+ // make stale time longer for inspectTxn results
287
+ });
288
+ return query;
289
+ }
290
+ /**
291
+ * @description Provides cache for getObject of the SuiKit.
292
+ * @param objectId
293
+ * @param QueryObjectParams
294
+ * @returns Promise<SuiObjectResponse>
295
+ */
296
+ async queryGetObject(objectId, options) {
297
+ const queryKey = ["getObject", objectId, this.suiKit.currentAddress()];
298
+ if (options) {
299
+ queryKey.push(JSON.stringify(options));
300
+ }
301
+ return this.queryClient.fetchQuery({
302
+ queryKey,
303
+ queryFn: async () => {
304
+ return await this.suiKit.client().getObject({
305
+ id: objectId,
306
+ options
307
+ });
308
+ }
309
+ });
310
+ }
311
+ /**
312
+ * @description Provides cache for getObjects of the SuiKit.
313
+ * @param objectIds
314
+ * @returns Promise<SuiObjectData[]>
315
+ */
316
+ async queryGetObjects(objectIds, options) {
317
+ const queryKey = [
318
+ "getObjects",
319
+ JSON.stringify(objectIds),
320
+ this.suiKit.currentAddress()
321
+ ];
322
+ return this.queryClient.fetchQuery({
323
+ queryKey,
324
+ queryFn: async () => {
325
+ return await this.suiKit.getObjects(objectIds, options);
326
+ }
327
+ });
328
+ }
329
+ /**
330
+ * @description Provides cache for getOwnedObjects of the SuiKit.
331
+ * @param input
332
+ * @returns Promise<PaginatedObjectsResponse>
333
+ */
334
+ async queryGetOwnedObjects(input) {
335
+ const queryKey = ["getOwnedObjects", input.owner];
336
+ if (input.cursor) {
337
+ queryKey.push(JSON.stringify(input.cursor));
338
+ }
339
+ if (input.options) {
340
+ queryKey.push(JSON.stringify(input.options));
341
+ }
342
+ if (input.filter) {
343
+ queryKey.push(JSON.stringify(input.filter));
344
+ }
345
+ if (input.limit) {
346
+ queryKey.push(JSON.stringify(input.limit));
347
+ }
348
+ return this.queryClient.fetchQuery({
349
+ queryKey,
350
+ queryFn: async () => {
351
+ return await this.suiKit.client().getOwnedObjects(input);
352
+ }
353
+ });
354
+ }
355
+ async queryGetDynamicFields(input) {
356
+ const queryKey = ["getDynamicFields", input.parentId];
357
+ if (input.cursor) {
358
+ queryKey.push(JSON.stringify(input.cursor));
359
+ }
360
+ if (input.cursor) {
361
+ queryKey.push(JSON.stringify(input.cursor));
362
+ }
363
+ if (input.limit) {
364
+ queryKey.push(JSON.stringify(input.limit));
365
+ }
366
+ return this.queryClient.fetchQuery({
367
+ queryKey,
368
+ queryFn: async () => {
369
+ return await this.suiKit.client().getDynamicFields(input);
370
+ }
371
+ });
372
+ }
373
+ async queryGetDynamicFieldObject(input) {
374
+ const queryKey = [
375
+ "getDynamicFieldObject",
376
+ input.parentId,
377
+ input.name.value
378
+ ];
379
+ return this.queryClient.fetchQuery({
380
+ queryKey,
381
+ queryFn: async () => {
382
+ return await this.suiKit.client().getDynamicFieldObject(input);
383
+ }
384
+ });
385
+ }
386
+ };
387
+
197
388
  // src/models/scallopAddress.ts
198
389
  import axios from "axios";
199
390
  var EMPTY_ADDRESSES = {
@@ -446,13 +637,9 @@ var EMPTY_ADDRESSES = {
446
637
  }
447
638
  };
448
639
  var ScallopAddress = class {
449
- constructor(params) {
640
+ constructor(params, cache) {
450
641
  const { id, auth, network } = params;
451
- if (auth)
452
- this._auth = auth;
453
- this._id = id;
454
- this._network = network || "mainnet";
455
- this._addressesMap = /* @__PURE__ */ new Map();
642
+ this._cache = cache ?? new ScallopCache(DEFAULT_CACHE_OPTIONS);
456
643
  this._requestClient = axios.create({
457
644
  baseURL: API_BASE_URL,
458
645
  headers: {
@@ -461,6 +648,11 @@ var ScallopAddress = class {
461
648
  },
462
649
  timeout: 3e4
463
650
  });
651
+ if (auth)
652
+ this._auth = auth;
653
+ this._id = id;
654
+ this._network = network || "mainnet";
655
+ this._addressesMap = /* @__PURE__ */ new Map();
464
656
  }
465
657
  /**
466
658
  * Get addresses API id.
@@ -584,7 +776,7 @@ var ScallopAddress = class {
584
776
  this._addressesMap.clear();
585
777
  this.setAddresses(targetAddresses, targetNetwork);
586
778
  const response = await this._requestClient.post(
587
- `${API_BASE_URL}/addresses`,
779
+ `/addresses`,
588
780
  JSON.stringify({ ...Object.fromEntries(this._addressesMap), memo }),
589
781
  {
590
782
  headers: {
@@ -621,14 +813,16 @@ var ScallopAddress = class {
621
813
  async read(id) {
622
814
  const addressesId = id || this._id || void 0;
623
815
  if (addressesId !== void 0) {
624
- const response = await this._requestClient.get(
625
- `${API_BASE_URL}/addresses/${addressesId}`,
626
- {
627
- headers: {
628
- "Content-Type": "application/json"
629
- }
816
+ const response = await this._cache.queryClient.fetchQuery({
817
+ queryKey: ["api-getAddresses", addressesId],
818
+ queryFn: async () => {
819
+ return await this._requestClient.get(`/addresses/${addressesId}`, {
820
+ headers: {
821
+ "Content-Type": "application/json"
822
+ }
823
+ });
630
824
  }
631
- );
825
+ });
632
826
  if (response.status === 200) {
633
827
  for (const [network, addresses] of Object.entries(
634
828
  response.data
@@ -682,7 +876,7 @@ var ScallopAddress = class {
682
876
  }
683
877
  this.setAddresses(targetAddresses, targetNetwork);
684
878
  const response = await this._requestClient.put(
685
- `${API_BASE_URL}/addresses/${targetId}`,
879
+ `/addresses/${targetId}`,
686
880
  JSON.stringify({ ...Object.fromEntries(this._addressesMap), memo }),
687
881
  {
688
882
  headers: {
@@ -724,7 +918,7 @@ var ScallopAddress = class {
724
918
  throw Error("Require specific addresses id to be deleted.");
725
919
  if (apiKey !== void 0) {
726
920
  const response = await this._requestClient.delete(
727
- `${API_BASE_URL}/addresses/${targetId}`,
921
+ `/addresses/${targetId}`,
728
922
  {
729
923
  headers: {
730
924
  "Content-Type": "application/json",
@@ -759,7 +953,6 @@ import { SuiKit } from "@scallop-io/sui-kit";
759
953
 
760
954
  // src/queries/coreQuery.ts
761
955
  import { normalizeStructTag as normalizeStructTag2 } from "@mysten/sui.js/utils";
762
- import { SuiTxBlock as SuiKitTxBlock } from "@scallop-io/sui-kit";
763
956
  import BigNumber2 from "bignumber.js";
764
957
 
765
958
  // src/utils/builder.ts
@@ -1311,10 +1504,12 @@ var findClosestUnlockRound = (unlockAtInSecondTimestamp) => {
1311
1504
  var queryMarket = async (query, indexer = false) => {
1312
1505
  const packageId = query.address.get("core.packages.query.id");
1313
1506
  const marketId = query.address.get("core.market");
1314
- const txBlock = new SuiKitTxBlock();
1315
1507
  const queryTarget = `${packageId}::market_query::market_data`;
1316
- txBlock.moveCall(queryTarget, [marketId]);
1317
- const queryResult = await query.suiKit.inspectTxn(txBlock);
1508
+ const args = [marketId];
1509
+ const queryResult = await query.cache.queryInspectTxn(
1510
+ { queryTarget, args }
1511
+ // txBlock
1512
+ );
1318
1513
  const marketData = queryResult.events[0].parsedJson;
1319
1514
  const coinPrices = await query.utils.getCoinPrices();
1320
1515
  const pools = {};
@@ -1432,11 +1627,8 @@ var queryMarket = async (query, indexer = false) => {
1432
1627
  var getMarketPools = async (query, poolCoinNames, indexer = false) => {
1433
1628
  poolCoinNames = poolCoinNames || [...SUPPORT_POOLS];
1434
1629
  const marketId = query.address.get("core.market");
1435
- const marketObjectResponse = await query.suiKit.client().getObject({
1436
- id: marketId,
1437
- options: {
1438
- showContent: true
1439
- }
1630
+ const marketObjectResponse = await query.cache.queryGetObject(marketId, {
1631
+ showContent: true
1440
1632
  });
1441
1633
  const coinPrices = await query.utils.getCoinPrices(poolCoinNames ?? []);
1442
1634
  const marketPools = {};
@@ -1469,11 +1661,8 @@ var getMarketPools = async (query, poolCoinNames, indexer = false) => {
1469
1661
  };
1470
1662
  var getMarketPool = async (query, poolCoinName, indexer = false, marketObject, coinPrice) => {
1471
1663
  const marketId = query.address.get("core.market");
1472
- marketObject = marketObject || (await query.suiKit.client().getObject({
1473
- id: marketId,
1474
- options: {
1475
- showContent: true
1476
- }
1664
+ marketObject = marketObject || (await query.cache.queryGetObject(marketId, {
1665
+ showContent: true
1477
1666
  })).data;
1478
1667
  coinPrice = coinPrice || (await query.utils.getCoinPrices([poolCoinName]))?.[poolCoinName];
1479
1668
  let marketPool;
@@ -1494,7 +1683,7 @@ var getMarketPool = async (query, poolCoinName, indexer = false, marketObject, c
1494
1683
  const fields = marketObject.content.fields;
1495
1684
  const coinType = query.utils.parseCoinType(poolCoinName);
1496
1685
  const balanceSheetParentId = fields.vault.fields.balance_sheets.fields.table.fields.id.id;
1497
- const balanceSheetDynamicFieldObjectResponse = await query.suiKit.client().getDynamicFieldObject({
1686
+ const balanceSheetDynamicFieldObjectResponse = await query.cache.queryGetDynamicFieldObject({
1498
1687
  parentId: balanceSheetParentId,
1499
1688
  name: {
1500
1689
  type: "0x1::type_name::TypeName",
@@ -1509,7 +1698,7 @@ var getMarketPool = async (query, poolCoinName, indexer = false, marketObject, c
1509
1698
  balanceSheet = dynamicFields.value.fields;
1510
1699
  }
1511
1700
  const borrowIndexParentId = fields.borrow_dynamics.fields.table.fields.id.id;
1512
- const borrowIndexDynamicFieldObjectResponse = await query.suiKit.client().getDynamicFieldObject({
1701
+ const borrowIndexDynamicFieldObjectResponse = await query.cache.queryGetDynamicFieldObject({
1513
1702
  parentId: borrowIndexParentId,
1514
1703
  name: {
1515
1704
  type: "0x1::type_name::TypeName",
@@ -1524,7 +1713,7 @@ var getMarketPool = async (query, poolCoinName, indexer = false, marketObject, c
1524
1713
  borrowIndex = dynamicFields.value.fields;
1525
1714
  }
1526
1715
  const interestModelParentId = fields.interest_models.fields.table.fields.id.id;
1527
- const interestModelDynamicFieldObjectResponse = await query.suiKit.client().getDynamicFieldObject({
1716
+ const interestModelDynamicFieldObjectResponse = await query.cache.queryGetDynamicFieldObject({
1528
1717
  parentId: interestModelParentId,
1529
1718
  name: {
1530
1719
  type: "0x1::type_name::TypeName",
@@ -1538,7 +1727,7 @@ var getMarketPool = async (query, poolCoinName, indexer = false, marketObject, c
1538
1727
  const dynamicFields = interestModelDynamicFieldObject.content.fields;
1539
1728
  interestModel = dynamicFields.value.fields;
1540
1729
  }
1541
- const borrowFeeDynamicFieldObjectResponse = await query.suiKit.client().getDynamicFieldObject({
1730
+ const borrowFeeDynamicFieldObjectResponse = await query.cache.queryGetDynamicFieldObject({
1542
1731
  parentId: marketId,
1543
1732
  name: {
1544
1733
  type: `${BORROW_FEE_PROTOCOL_ID}::market_dynamic_keys::BorrowFeeKey`,
@@ -1605,11 +1794,8 @@ var getMarketPool = async (query, poolCoinName, indexer = false, marketObject, c
1605
1794
  var getMarketCollaterals = async (query, collateralCoinNames, indexer = false) => {
1606
1795
  collateralCoinNames = collateralCoinNames || [...SUPPORT_COLLATERALS];
1607
1796
  const marketId = query.address.get("core.market");
1608
- const marketObjectResponse = await query.suiKit.client().getObject({
1609
- id: marketId,
1610
- options: {
1611
- showContent: true
1612
- }
1797
+ const marketObjectResponse = await query.cache.queryGetObject(marketId, {
1798
+ showContent: true
1613
1799
  });
1614
1800
  const coinPrices = await query.utils.getCoinPrices(collateralCoinNames ?? []);
1615
1801
  const marketCollaterals = {};
@@ -1642,11 +1828,8 @@ var getMarketCollaterals = async (query, collateralCoinNames, indexer = false) =
1642
1828
  };
1643
1829
  var getMarketCollateral = async (query, collateralCoinName, indexer = false, marketObject, coinPrice) => {
1644
1830
  const marketId = query.address.get("core.market");
1645
- marketObject = marketObject || (await query.suiKit.client().getObject({
1646
- id: marketId,
1647
- options: {
1648
- showContent: true
1649
- }
1831
+ marketObject = marketObject || (await query.cache.queryGetObject(marketId, {
1832
+ showContent: true
1650
1833
  })).data;
1651
1834
  coinPrice = coinPrice || (await query.utils.getCoinPrices([collateralCoinName]))?.[collateralCoinName];
1652
1835
  let marketCollateral;
@@ -1665,7 +1848,7 @@ var getMarketCollateral = async (query, collateralCoinName, indexer = false, mar
1665
1848
  const fields = marketObject.content.fields;
1666
1849
  const coinType = query.utils.parseCoinType(collateralCoinName);
1667
1850
  const riskModelParentId = fields.risk_models.fields.table.fields.id.id;
1668
- const riskModelDynamicFieldObjectResponse = await query.suiKit.client().getDynamicFieldObject({
1851
+ const riskModelDynamicFieldObjectResponse = await query.cache.queryGetDynamicFieldObject({
1669
1852
  parentId: riskModelParentId,
1670
1853
  name: {
1671
1854
  type: "0x1::type_name::TypeName",
@@ -1680,7 +1863,7 @@ var getMarketCollateral = async (query, collateralCoinName, indexer = false, mar
1680
1863
  riskModel = dynamicFields.value.fields;
1681
1864
  }
1682
1865
  const collateralStatParentId = fields.collateral_stats.fields.table.fields.id.id;
1683
- const collateralStatDynamicFieldObjectResponse = await query.suiKit.client().getDynamicFieldObject({
1866
+ const collateralStatDynamicFieldObjectResponse = await query.cache.queryGetDynamicFieldObject({
1684
1867
  parentId: collateralStatParentId,
1685
1868
  name: {
1686
1869
  type: "0x1::type_name::TypeName",
@@ -1736,7 +1919,7 @@ var getObligations = async (query, ownerAddress) => {
1736
1919
  let hasNextPage = false;
1737
1920
  let nextCursor = null;
1738
1921
  do {
1739
- const paginatedKeyObjectsResponse = await query.suiKit.client().getOwnedObjects({
1922
+ const paginatedKeyObjectsResponse = await query.cache.queryGetOwnedObjects({
1740
1923
  owner,
1741
1924
  filter: {
1742
1925
  StructType: `${protocolObjectId}::obligation::ObligationKey`
@@ -1752,7 +1935,7 @@ var getObligations = async (query, ownerAddress) => {
1752
1935
  }
1753
1936
  } while (hasNextPage);
1754
1937
  const keyObjectIds = keyObjectsResponse.map((ref) => ref?.data?.objectId).filter((id) => id !== void 0);
1755
- const keyObjects = await query.suiKit.getObjects(keyObjectIds);
1938
+ const keyObjects = await query.cache.queryGetObjects(keyObjectIds);
1756
1939
  const obligations = [];
1757
1940
  for (const keyObject of keyObjects) {
1758
1941
  const keyId = keyObject.objectId;
@@ -1766,12 +1949,10 @@ var getObligations = async (query, ownerAddress) => {
1766
1949
  return obligations;
1767
1950
  };
1768
1951
  var getObligationLocked = async (query, obligationId) => {
1769
- const obligationObjectResponse = await query.suiKit.client().getObject({
1770
- id: obligationId,
1771
- options: {
1772
- showContent: true
1773
- }
1774
- });
1952
+ const obligationObjectResponse = await query.cache.queryGetObject(
1953
+ obligationId,
1954
+ { showContent: true }
1955
+ );
1775
1956
  let obligationLocked = false;
1776
1957
  if (obligationObjectResponse.data && obligationObjectResponse?.data?.content?.dataType === "moveObject" && "lock_key" in obligationObjectResponse.data.content.fields) {
1777
1958
  obligationLocked = Boolean(
@@ -1783,9 +1964,11 @@ var getObligationLocked = async (query, obligationId) => {
1783
1964
  var queryObligation = async (query, obligationId) => {
1784
1965
  const packageId = query.address.get("core.packages.query.id");
1785
1966
  const queryTarget = `${packageId}::obligation_query::obligation_data`;
1786
- const txBlock = new SuiKitTxBlock();
1787
- txBlock.moveCall(queryTarget, [obligationId]);
1788
- const queryResult = await query.suiKit.inspectTxn(txBlock);
1967
+ const args = [obligationId];
1968
+ const queryResult = await query.cache.queryInspectTxn(
1969
+ { queryTarget, args }
1970
+ // txBlock
1971
+ );
1789
1972
  return queryResult.events[0].parsedJson;
1790
1973
  };
1791
1974
  var getCoinAmounts = async (query, assetCoinNames, ownerAddress) => {
@@ -1795,20 +1978,22 @@ var getCoinAmounts = async (query, assetCoinNames, ownerAddress) => {
1795
1978
  let hasNextPage = false;
1796
1979
  let nextCursor = null;
1797
1980
  do {
1798
- const paginatedCoinObjectsResponse = await query.suiKit.client().getOwnedObjects({
1799
- owner,
1800
- filter: {
1801
- MatchAny: assetCoinNames.map((assetCoinName) => {
1802
- const coinType = query.utils.parseCoinType(assetCoinName);
1803
- return { StructType: `0x2::coin::Coin<${coinType}>` };
1804
- })
1805
- },
1806
- options: {
1807
- showType: true,
1808
- showContent: true
1809
- },
1810
- cursor: nextCursor
1811
- });
1981
+ const paginatedCoinObjectsResponse = await query.cache.queryGetOwnedObjects(
1982
+ {
1983
+ owner,
1984
+ filter: {
1985
+ MatchAny: assetCoinNames.map((assetCoinName) => {
1986
+ const coinType = query.utils.parseCoinType(assetCoinName);
1987
+ return { StructType: `0x2::coin::Coin<${coinType}>` };
1988
+ })
1989
+ },
1990
+ options: {
1991
+ showType: true,
1992
+ showContent: true
1993
+ },
1994
+ cursor: nextCursor
1995
+ }
1996
+ );
1812
1997
  coinObjectsResponse.push(...paginatedCoinObjectsResponse.data);
1813
1998
  if (paginatedCoinObjectsResponse.hasNextPage && paginatedCoinObjectsResponse.nextCursor) {
1814
1999
  hasNextPage = true;
@@ -1842,14 +2027,16 @@ var getCoinAmount = async (query, assetCoinName, ownerAddress) => {
1842
2027
  let hasNextPage = false;
1843
2028
  let nextCursor = null;
1844
2029
  do {
1845
- const paginatedCoinObjectsResponse = await query.suiKit.client().getOwnedObjects({
1846
- owner,
1847
- filter: { StructType: `0x2::coin::Coin<${coinType}>` },
1848
- options: {
1849
- showContent: true
1850
- },
1851
- cursor: nextCursor
1852
- });
2030
+ const paginatedCoinObjectsResponse = await query.cache.queryGetOwnedObjects(
2031
+ {
2032
+ owner,
2033
+ filter: { StructType: `0x2::coin::Coin<${coinType}>` },
2034
+ options: {
2035
+ showContent: true
2036
+ },
2037
+ cursor: nextCursor
2038
+ }
2039
+ );
1853
2040
  coinObjectsResponse.push(...paginatedCoinObjectsResponse.data);
1854
2041
  if (paginatedCoinObjectsResponse.hasNextPage && paginatedCoinObjectsResponse.nextCursor) {
1855
2042
  hasNextPage = true;
@@ -1881,7 +2068,7 @@ var getMarketCoinAmounts = async (query, marketCoinNames, ownerAddress) => {
1881
2068
  let hasNextPage = false;
1882
2069
  let nextCursor = null;
1883
2070
  do {
1884
- const paginatedMarketCoinObjectsResponse = await query.suiKit.client().getOwnedObjects({
2071
+ const paginatedMarketCoinObjectsResponse = await query.cache.queryGetOwnedObjects({
1885
2072
  owner,
1886
2073
  filter: {
1887
2074
  MatchAny: marketCoinNames.map((marketCoinName) => {
@@ -1930,7 +2117,7 @@ var getMarketCoinAmount = async (query, marketCoinName, ownerAddress) => {
1930
2117
  let hasNextPage = false;
1931
2118
  let nextCursor = null;
1932
2119
  do {
1933
- const paginatedMarketCoinObjectsResponse = await query.suiKit.client().getOwnedObjects({
2120
+ const paginatedMarketCoinObjectsResponse = await query.cache.queryGetOwnedObjects({
1934
2121
  owner,
1935
2122
  filter: { StructType: `0x2::coin::Coin<${marketCoinType}>` },
1936
2123
  options: {
@@ -2110,7 +2297,7 @@ var getStakeAccounts = async (query, ownerAddress) => {
2110
2297
  let hasNextPage = false;
2111
2298
  let nextCursor = null;
2112
2299
  do {
2113
- const paginatedStakeObjectsResponse = await query.suiKit.client().getOwnedObjects({
2300
+ const paginatedStakeObjectsResponse = await query.cache.queryGetOwnedObjects({
2114
2301
  owner,
2115
2302
  filter: { StructType: stakeAccountType },
2116
2303
  options: {
@@ -2148,7 +2335,7 @@ var getStakeAccounts = async (query, ownerAddress) => {
2148
2335
  {}
2149
2336
  );
2150
2337
  const stakeObjectIds = stakeObjectsResponse.map((ref) => ref?.data?.objectId).filter((id) => id !== void 0);
2151
- const stakeObjects = await query.suiKit.getObjects(stakeObjectIds);
2338
+ const stakeObjects = await query.cache.queryGetObjects(stakeObjectIds);
2152
2339
  for (const stakeObject of stakeObjects) {
2153
2340
  const id = stakeObject.objectId;
2154
2341
  const type = stakeObject.type;
@@ -2256,12 +2443,9 @@ var getStakeAccounts = async (query, ownerAddress) => {
2256
2443
  var getStakePool = async (query, marketCoinName) => {
2257
2444
  const poolId = query.address.get(`spool.pools.${marketCoinName}.id`);
2258
2445
  let stakePool = void 0;
2259
- const stakePoolObjectResponse = await query.suiKit.client().getObject({
2260
- id: poolId,
2261
- options: {
2262
- showContent: true,
2263
- showType: true
2264
- }
2446
+ const stakePoolObjectResponse = await query.cache.queryGetObject(poolId, {
2447
+ showContent: true,
2448
+ showType: true
2265
2449
  });
2266
2450
  if (stakePoolObjectResponse.data) {
2267
2451
  const stakePoolObject = stakePoolObjectResponse.data;
@@ -2302,13 +2486,13 @@ var getStakeRewardPool = async (query, marketCoinName) => {
2302
2486
  `spool.pools.${marketCoinName}.rewardPoolId`
2303
2487
  );
2304
2488
  let stakeRewardPool = void 0;
2305
- const stakeRewardPoolObjectResponse = await query.suiKit.client().getObject({
2306
- id: poolId,
2307
- options: {
2489
+ const stakeRewardPoolObjectResponse = await query.cache.queryGetObject(
2490
+ poolId,
2491
+ {
2308
2492
  showContent: true,
2309
2493
  showType: true
2310
2494
  }
2311
- });
2495
+ );
2312
2496
  if (stakeRewardPoolObjectResponse.data) {
2313
2497
  const stakeRewardPoolObject = stakeRewardPoolObjectResponse.data;
2314
2498
  const id = stakeRewardPoolObject.objectId;
@@ -2338,17 +2522,15 @@ var getStakeRewardPool = async (query, marketCoinName) => {
2338
2522
 
2339
2523
  // src/queries/borrowIncentiveQuery.ts
2340
2524
  import { normalizeStructTag as normalizeStructTag4 } from "@mysten/sui.js/utils";
2341
- import { SuiTxBlock as SuiKitTxBlock2 } from "@scallop-io/sui-kit";
2342
2525
  var queryBorrowIncentivePools = async (query, borrowIncentiveCoinNames, indexer = false) => {
2343
2526
  borrowIncentiveCoinNames = borrowIncentiveCoinNames || [
2344
2527
  ...SUPPORT_BORROW_INCENTIVE_POOLS
2345
2528
  ];
2346
2529
  const queryPkgId = query.address.get("borrowIncentive.query");
2347
2530
  const incentivePoolsId = query.address.get("borrowIncentive.incentivePools");
2348
- const txBlock = new SuiKitTxBlock2();
2349
2531
  const queryTarget = `${queryPkgId}::incentive_pools_query::incentive_pools_data`;
2350
- txBlock.moveCall(queryTarget, [incentivePoolsId]);
2351
- const queryResult = await query.suiKit.inspectTxn(txBlock);
2532
+ const args = [incentivePoolsId];
2533
+ const queryResult = await query.cache.queryInspectTxn({ queryTarget, args });
2352
2534
  const borrowIncentivePoolsQueryData = queryResult.events[0].parsedJson;
2353
2535
  const borrowIncentivePools = {};
2354
2536
  if (indexer) {
@@ -2425,9 +2607,8 @@ var queryBorrowIncentiveAccounts = async (query, obligationId, borrowIncentiveCo
2425
2607
  "borrowIncentive.incentiveAccounts"
2426
2608
  );
2427
2609
  const queryTarget = `${queryPkgId}::incentive_account_query::incentive_account_data`;
2428
- const txBlock = new SuiKitTxBlock2();
2429
- txBlock.moveCall(queryTarget, [incentiveAccountsId, obligationId]);
2430
- const queryResult = await query.suiKit.inspectTxn(txBlock);
2610
+ const args = [incentiveAccountsId, obligationId];
2611
+ const queryResult = await query.cache.queryInspectTxn({ queryTarget, args });
2431
2612
  const borrowIncentiveAccountsQueryData = queryResult.events[0].parsedJson;
2432
2613
  const borrowIncentiveAccounts = Object.values(
2433
2614
  borrowIncentiveAccountsQueryData.pool_records
@@ -2442,18 +2623,73 @@ var queryBorrowIncentiveAccounts = async (query, obligationId, borrowIncentiveCo
2442
2623
  }, {});
2443
2624
  return borrowIncentiveAccounts;
2444
2625
  };
2626
+ var getBindedObligationId = async (query, veScaKeyId) => {
2627
+ const borrowIncentiveObjectId = query.address.get("borrowIncentive.object");
2628
+ const incentivePoolsId = query.address.get("borrowIncentive.incentivePools");
2629
+ const veScaPkgId = IS_VE_SCA_TEST ? "0xb220d034bdf335d77ae5bfbf6daf059c2cc7a1f719b12bfed75d1736fac038c8" : query.address.get("vesca.id");
2630
+ const client = query.suiKit.client();
2631
+ const incentivePoolsResponse = await client.getObject({
2632
+ id: incentivePoolsId,
2633
+ options: {
2634
+ showContent: true
2635
+ }
2636
+ });
2637
+ if (incentivePoolsResponse.data?.content?.dataType !== "moveObject")
2638
+ return null;
2639
+ const incentivePoolFields = incentivePoolsResponse.data.content.fields;
2640
+ const veScaBindTableId = incentivePoolFields.ve_sca_bind.fields.id.id;
2641
+ const keyType = `${borrowIncentiveObjectId}::typed_id::TypedID<${veScaPkgId}::ve_sca::VeScaKey>`;
2642
+ const veScaBindTableResponse = await client.getDynamicFieldObject({
2643
+ parentId: veScaBindTableId,
2644
+ name: {
2645
+ type: keyType,
2646
+ value: veScaKeyId
2647
+ }
2648
+ });
2649
+ if (veScaBindTableResponse.data?.content?.dataType !== "moveObject")
2650
+ return null;
2651
+ const veScaBindTableFields = veScaBindTableResponse.data.content.fields;
2652
+ const obligationId = veScaBindTableFields.value.fields.id;
2653
+ return obligationId;
2654
+ };
2655
+ var getBindedVeScaKey = async (query, obliationId) => {
2656
+ const borrowIncentiveObjectId = query.address.get("borrowIncentive.object");
2657
+ const incentiveAccountsId = query.address.get(
2658
+ "borrowIncentive.incentiveAccounts"
2659
+ );
2660
+ const corePkg = query.address.get("core.object");
2661
+ const client = query.suiKit.client();
2662
+ const incentiveAccountsObject = await client.getObject({
2663
+ id: incentiveAccountsId,
2664
+ options: {
2665
+ showContent: true
2666
+ }
2667
+ });
2668
+ if (incentiveAccountsObject.data?.content?.dataType !== "moveObject")
2669
+ return null;
2670
+ const incentiveAccountsTableId = incentiveAccountsObject.data.content.fields.accounts.fields.id.id;
2671
+ const bindedIncentiveAcc = await client.getDynamicFieldObject({
2672
+ parentId: incentiveAccountsTableId,
2673
+ name: {
2674
+ type: `${borrowIncentiveObjectId}::typed_id::TypedID<${corePkg}::obligation::Obligation>`,
2675
+ value: obliationId
2676
+ }
2677
+ });
2678
+ if (bindedIncentiveAcc.data?.content?.dataType !== "moveObject")
2679
+ return null;
2680
+ const bindedIncentiveAccFields = bindedIncentiveAcc.data.content.fields;
2681
+ return bindedIncentiveAccFields.value.fields.binded_ve_sca_key?.fields.id ?? null;
2682
+ };
2445
2683
 
2446
2684
  // src/queries/priceQuery.ts
2447
2685
  var getPythPrice = async (query, assetCoinName) => {
2448
2686
  const pythFeedObjectId = query.address.get(
2449
2687
  `core.coins.${assetCoinName}.oracle.pyth.feedObject`
2450
2688
  );
2451
- const priceFeedObjectResponse = await query.suiKit.client().getObject({
2452
- id: pythFeedObjectId,
2453
- options: {
2454
- showContent: true
2455
- }
2456
- });
2689
+ const priceFeedObjectResponse = await query.cache.queryGetObject(
2690
+ pythFeedObjectId,
2691
+ { showContent: true }
2692
+ );
2457
2693
  if (priceFeedObjectResponse.data) {
2458
2694
  const priceFeedPoolObject = priceFeedObjectResponse.data;
2459
2695
  if (priceFeedPoolObject.content && "fields" in priceFeedPoolObject.content) {
@@ -3017,7 +3253,7 @@ var getVeSca = async (query, veScaKeyId, ownerAddress) => {
3017
3253
  const tableId = IS_VE_SCA_TEST ? "0xc607241e4a679fe376d1170b2fbe07b64917bfe69100d4825241cda20039d4bd" : query.address.get(`vesca.tableId`);
3018
3254
  veScaKeyId = veScaKeyId || (await getVescaKeys(query, ownerAddress))[0].objectId;
3019
3255
  let vesca = void 0;
3020
- const veScaDynamicFieldObjectResponse = await query.suiKit.client().getDynamicFieldObject({
3256
+ const veScaDynamicFieldObjectResponse = await query.cache.queryGetDynamicFieldObject({
3021
3257
  parentId: tableId,
3022
3258
  name: {
3023
3259
  type: "0x2::object::ID",
@@ -3027,11 +3263,19 @@ var getVeSca = async (query, veScaKeyId, ownerAddress) => {
3027
3263
  const veScaDynamicFieldObject = veScaDynamicFieldObjectResponse.data;
3028
3264
  if (veScaDynamicFieldObject && veScaDynamicFieldObject.content && veScaDynamicFieldObject.content.dataType === "moveObject" && "fields" in veScaDynamicFieldObject.content) {
3029
3265
  const dynamicFields = veScaDynamicFieldObject.content.fields.value.fields;
3266
+ const remainingLockPeriodInMilliseconds = Math.max(
3267
+ +dynamicFields.unlock_at * 1e3 - Date.now(),
3268
+ 0
3269
+ );
3270
+ const lockedScaAmount = String(dynamicFields.locked_sca_amount);
3271
+ const lockedScaCoin = BigNumber4(dynamicFields.locked_sca_amount).shiftedBy(-9).toNumber();
3272
+ const currentVeScaBalance = lockedScaCoin * (Math.floor(remainingLockPeriodInMilliseconds / 1e3) / MAX_LOCK_DURATION);
3030
3273
  vesca = {
3031
3274
  id: veScaDynamicFieldObject.objectId,
3032
3275
  keyId: veScaKeyId,
3033
- lockedScaAmount: BigNumber4(dynamicFields.locked_sca_amount).toNumber(),
3034
- lockedScaCoin: BigNumber4(dynamicFields.locked_sca_amount).shiftedBy(-9).toNumber(),
3276
+ lockedScaAmount,
3277
+ lockedScaCoin,
3278
+ currentVeScaBalance,
3035
3279
  unlockAt: BigNumber4(dynamicFields.unlock_at).toNumber()
3036
3280
  };
3037
3281
  }
@@ -3041,7 +3285,9 @@ var getVeSca = async (query, veScaKeyId, ownerAddress) => {
3041
3285
  // src/models/scallopIndexer.ts
3042
3286
  import axios2 from "axios";
3043
3287
  var ScallopIndexer = class {
3044
- constructor() {
3288
+ constructor(params, instance) {
3289
+ this.params = params;
3290
+ this._cache = instance?.cache ?? new ScallopCache();
3045
3291
  this._requestClient = axios2.create({
3046
3292
  baseURL: SDK_API_BASE_URL,
3047
3293
  headers: {
@@ -3057,7 +3303,12 @@ var ScallopIndexer = class {
3057
3303
  * @return Market data.
3058
3304
  */
3059
3305
  async getMarket() {
3060
- const response = await this._requestClient.get(`${SDK_API_BASE_URL}/api/market`);
3306
+ const response = await this._cache.queryClient.fetchQuery({
3307
+ queryKey: ["market"],
3308
+ queryFn: async () => {
3309
+ return await this._requestClient.get(`/api/market`);
3310
+ }
3311
+ });
3061
3312
  if (response.status === 200) {
3062
3313
  return {
3063
3314
  pools: response.data.pools.reduce((marketPools, marketPool) => {
@@ -3082,15 +3333,8 @@ var ScallopIndexer = class {
3082
3333
  * @return Market pools data.
3083
3334
  */
3084
3335
  async getMarketPools() {
3085
- const response = await this._requestClient.get(`${SDK_API_BASE_URL}/api/market/pools`);
3086
- if (response.status === 200) {
3087
- return response.data.pools.reduce((marketPools, marketPool) => {
3088
- marketPools[marketPool.coinName] = marketPool;
3089
- return marketPools;
3090
- }, {});
3091
- } else {
3092
- throw Error("Failed to getMarketPools.");
3093
- }
3336
+ const response = (await this.getMarket()).pools;
3337
+ return response;
3094
3338
  }
3095
3339
  /**
3096
3340
  * Get market pool index data.
@@ -3098,12 +3342,7 @@ var ScallopIndexer = class {
3098
3342
  * @return Market pool data.
3099
3343
  */
3100
3344
  async getMarketPool(poolCoinName) {
3101
- const response = await this._requestClient.get(`${SDK_API_BASE_URL}/api/market/pool/${poolCoinName}`);
3102
- if (response.status === 200) {
3103
- return response.data.pool;
3104
- } else {
3105
- throw Error("Failed to getMarketPool.");
3106
- }
3345
+ return (await this.getMarketPools())[poolCoinName];
3107
3346
  }
3108
3347
  /**
3109
3348
  * Get market collaterals index data.
@@ -3111,18 +3350,7 @@ var ScallopIndexer = class {
3111
3350
  * @return Market collaterals data.
3112
3351
  */
3113
3352
  async getMarketCollaterals() {
3114
- const response = await this._requestClient.get(`${SDK_API_BASE_URL}/api/market/collaterals`);
3115
- if (response.status === 200) {
3116
- return response.data.collaterals.reduce(
3117
- (marketCollaterals, marketCollateral) => {
3118
- marketCollaterals[marketCollateral.coinName] = marketCollateral;
3119
- return marketCollaterals;
3120
- },
3121
- {}
3122
- );
3123
- } else {
3124
- throw Error("Failed to getMarketCollaterals.");
3125
- }
3353
+ return (await this.getMarket()).collaterals;
3126
3354
  }
3127
3355
  /**
3128
3356
  * Get market collateral index data.
@@ -3130,12 +3358,7 @@ var ScallopIndexer = class {
3130
3358
  * @return Market collateral data.
3131
3359
  */
3132
3360
  async getMarketCollateral(collateralCoinName) {
3133
- const response = await this._requestClient.get(`${SDK_API_BASE_URL}/api/market/collateral/${collateralCoinName}`);
3134
- if (response.status === 200) {
3135
- return response.data.collateral;
3136
- } else {
3137
- throw Error("Failed to getMarketCollateral.");
3138
- }
3361
+ return (await this.getMarketCollaterals())[collateralCoinName];
3139
3362
  }
3140
3363
  /**
3141
3364
  * Get spools index data.
@@ -3143,7 +3366,12 @@ var ScallopIndexer = class {
3143
3366
  * @return Spools data.
3144
3367
  */
3145
3368
  async getSpools() {
3146
- const response = await this._requestClient.get(`${SDK_API_BASE_URL}/api/spools`);
3369
+ const response = await this._cache.queryClient.fetchQuery({
3370
+ queryKey: ["spools"],
3371
+ queryFn: async () => {
3372
+ return await this._requestClient.get(`/api/spools`);
3373
+ }
3374
+ });
3147
3375
  if (response.status === 200) {
3148
3376
  return response.data.spools.reduce((spools, spool) => {
3149
3377
  spools[spool.marketCoinName] = spool;
@@ -3159,12 +3387,7 @@ var ScallopIndexer = class {
3159
3387
  * @return Spool data.
3160
3388
  */
3161
3389
  async getSpool(marketCoinName) {
3162
- const response = await this._requestClient.get(`${SDK_API_BASE_URL}/api/spool/${marketCoinName}`);
3163
- if (response.status === 200) {
3164
- return response.data.spool;
3165
- } else {
3166
- throw Error("Failed to getSpool.");
3167
- }
3390
+ return (await this.getSpools())[marketCoinName];
3168
3391
  }
3169
3392
  /**
3170
3393
  * Get borrow incentive pools index data.
@@ -3172,7 +3395,12 @@ var ScallopIndexer = class {
3172
3395
  * @return Borrow incentive pools data.
3173
3396
  */
3174
3397
  async getBorrowIncentivePools() {
3175
- const response = await this._requestClient.get(`${SDK_API_BASE_URL}/api/borrowIncentivePools`);
3398
+ const response = await this._cache.queryClient.fetchQuery({
3399
+ queryKey: ["borrowIncentivePools"],
3400
+ queryFn: async () => {
3401
+ return await this._requestClient.get(`/api/borrowIncentivePools`);
3402
+ }
3403
+ });
3176
3404
  if (response.status === 200) {
3177
3405
  return response.data.borrowIncentivePools.reduce(
3178
3406
  (borrowIncentivePools, borrowIncentivePool) => {
@@ -3191,14 +3419,7 @@ var ScallopIndexer = class {
3191
3419
  * @return Borrow incentive pool data.
3192
3420
  */
3193
3421
  async getBorrowIncentivePool(borrowIncentiveCoinName) {
3194
- const response = await this._requestClient.get(
3195
- `${SDK_API_BASE_URL}/api/borrowIncentivePool/${borrowIncentiveCoinName}`
3196
- );
3197
- if (response.status === 200) {
3198
- return response.data.borrowIncentivePool;
3199
- } else {
3200
- throw Error("Failed to getSpool.");
3201
- }
3422
+ return (await this.getBorrowIncentivePools())[borrowIncentiveCoinName];
3202
3423
  }
3203
3424
  /**
3204
3425
  * Get total value locked index data.
@@ -3206,7 +3427,12 @@ var ScallopIndexer = class {
3206
3427
  * @return Total value locked.
3207
3428
  */
3208
3429
  async getTotalValueLocked() {
3209
- const response = await this._requestClient.get(`${SDK_API_BASE_URL}/api/market/tvl`);
3430
+ const response = await this._cache.queryClient.fetchQuery({
3431
+ queryKey: ["totalValueLocked"],
3432
+ queryFn: async () => {
3433
+ return await this._requestClient.get(`/api/market/tvl`);
3434
+ }
3435
+ });
3210
3436
  if (response.status === 200) {
3211
3437
  return response.data;
3212
3438
  } else {
@@ -3220,16 +3446,21 @@ var ScallopQuery = class {
3220
3446
  constructor(params, instance) {
3221
3447
  this.params = params;
3222
3448
  this.suiKit = instance?.suiKit ?? new SuiKit(params);
3223
- this.address = instance?.address ?? new ScallopAddress({
3224
- id: params?.addressesId || ADDRESSES_ID,
3225
- network: params?.networkType
3226
- });
3449
+ this.cache = instance?.cache ?? new ScallopCache(DEFAULT_CACHE_OPTIONS, this.suiKit);
3450
+ this.address = instance?.address ?? new ScallopAddress(
3451
+ {
3452
+ id: params?.addressesId || ADDRESSES_ID,
3453
+ network: params?.networkType
3454
+ },
3455
+ this.cache
3456
+ );
3227
3457
  this.utils = instance?.utils ?? new ScallopUtils(this.params, {
3228
3458
  suiKit: this.suiKit,
3229
3459
  address: this.address,
3460
+ cache: this.cache,
3230
3461
  query: this
3231
3462
  });
3232
- this.indexer = new ScallopIndexer();
3463
+ this.indexer = new ScallopIndexer(this.params, { cache: this.cache });
3233
3464
  }
3234
3465
  /**
3235
3466
  * Request the scallop API to initialize data.
@@ -3567,6 +3798,22 @@ var ScallopQuery = class {
3567
3798
  async getTvl(indexer = false) {
3568
3799
  return await getTotalValueLocked(this, indexer);
3569
3800
  }
3801
+ /**
3802
+ * Get binded obligationId from a veScaKey if it exists.
3803
+ * @param veScaKey
3804
+ * @returns obligationId
3805
+ */
3806
+ async getBindedObligationId(veScaKey) {
3807
+ return await getBindedObligationId(this, veScaKey);
3808
+ }
3809
+ /**
3810
+ * Get binded veSCA key from a obligationId if it exists.
3811
+ * @param obligationId
3812
+ * @returns veScaKey
3813
+ */
3814
+ async getBindedVeScaKey(obligationId) {
3815
+ return await getBindedVeScaKey(this, obligationId);
3816
+ }
3570
3817
  };
3571
3818
 
3572
3819
  // src/constants/pyth.ts
@@ -3599,13 +3846,18 @@ var ScallopUtils = class {
3599
3846
  };
3600
3847
  this.params = params;
3601
3848
  this._suiKit = instance?.suiKit ?? new SuiKit2(params);
3602
- this._address = instance?.address ?? new ScallopAddress({
3603
- id: params?.addressesId || ADDRESSES_ID,
3604
- network: params?.networkType
3605
- });
3849
+ this._cache = instance?.cache ?? new ScallopCache(DEFAULT_CACHE_OPTIONS, this._suiKit);
3850
+ this._address = instance?.address ?? new ScallopAddress(
3851
+ {
3852
+ id: params?.addressesId || ADDRESSES_ID,
3853
+ network: params?.networkType
3854
+ },
3855
+ this._cache
3856
+ );
3606
3857
  this._query = instance?.query ?? new ScallopQuery(params, {
3607
3858
  suiKit: this._suiKit,
3608
- address: this._address
3859
+ address: this._address,
3860
+ cache: this._cache
3609
3861
  });
3610
3862
  this.isTestnet = params.networkType ? params.networkType === "testnet" : false;
3611
3863
  }
@@ -3822,33 +4074,52 @@ var ScallopUtils = class {
3822
4074
  }
3823
4075
  if (lackPricesCoinNames.length > 0) {
3824
4076
  const endpoints = this.params.pythEndpoints ?? PYTH_ENDPOINTS[this.isTestnet ? "testnet" : "mainnet"];
3825
- try {
3826
- for (const endpoint of endpoints) {
3827
- try {
3828
- const pythConnection = new SuiPriceServiceConnection(endpoint);
3829
- const priceIds = lackPricesCoinNames.map(
3830
- (coinName) => this._address.get(`core.coins.${coinName}.oracle.pyth.feed`)
4077
+ const failedRequests = new Set(
4078
+ lackPricesCoinNames
4079
+ );
4080
+ for (const endpoint of endpoints) {
4081
+ let hasFailRequest = false;
4082
+ const pythConnection = new SuiPriceServiceConnection(endpoint);
4083
+ const priceIds = Array.from(failedRequests.values()).reduce(
4084
+ (acc, coinName) => {
4085
+ const priceId = this._address.get(
4086
+ `core.coins.${coinName}.oracle.pyth.feed`
3831
4087
  );
3832
- const priceFeeds = await pythConnection.getLatestPriceFeeds(priceIds) || [];
3833
- for (const [index, feed] of priceFeeds.entries()) {
3834
- const data = parseDataFromPythPriceFeed(feed, this._address);
3835
- const coinName = lackPricesCoinNames[index];
4088
+ acc[coinName] = priceId;
4089
+ return acc;
4090
+ },
4091
+ {}
4092
+ );
4093
+ for (const [coinName, priceId] of Object.entries(priceIds)) {
4094
+ try {
4095
+ const feed = await this._cache.queryClient.fetchQuery({
4096
+ queryKey: [priceId],
4097
+ queryFn: async () => {
4098
+ return await pythConnection.getLatestPriceFeeds([priceId]);
4099
+ }
4100
+ // staleTime: 15000,
4101
+ });
4102
+ if (feed) {
4103
+ const data = parseDataFromPythPriceFeed(feed[0], this._address);
3836
4104
  this._priceMap.set(coinName, {
3837
4105
  price: data.price,
3838
4106
  publishTime: data.publishTime
3839
4107
  });
3840
4108
  coinPrices[coinName] = data.price;
3841
4109
  }
3842
- break;
4110
+ failedRequests.delete(coinName);
3843
4111
  } catch (e) {
3844
4112
  console.warn(
3845
- `Failed to update price feeds with endpoint ${endpoint}: ${e}`
4113
+ `Failed to get price ${coinName} feeds with endpoint ${endpoint}: ${e}`
3846
4114
  );
4115
+ hasFailRequest = true;
3847
4116
  }
3848
- throw new Error("Failed to update price feeds with all endpoins");
3849
4117
  }
3850
- } catch (_e) {
3851
- for (const coinName of lackPricesCoinNames) {
4118
+ if (!hasFailRequest)
4119
+ break;
4120
+ }
4121
+ if (failedRequests.size > 0) {
4122
+ for (const coinName of failedRequests.values()) {
3852
4123
  const price = await this._query.getPriceFromPyth(coinName);
3853
4124
  this._priceMap.set(coinName, {
3854
4125
  price,
@@ -3921,7 +4192,7 @@ import { SuiKit as SuiKit3 } from "@scallop-io/sui-kit";
3921
4192
  // src/builders/coreBuilder.ts
3922
4193
  import { TransactionBlock } from "@mysten/sui.js/transactions";
3923
4194
  import { SUI_CLOCK_OBJECT_ID as SUI_CLOCK_OBJECT_ID2 } from "@mysten/sui.js/utils";
3924
- import { SuiTxBlock as SuiKitTxBlock3 } from "@scallop-io/sui-kit";
4195
+ import { SuiTxBlock as SuiKitTxBlock } from "@scallop-io/sui-kit";
3925
4196
 
3926
4197
  // src/builders/oracle.ts
3927
4198
  import { SUI_CLOCK_OBJECT_ID } from "@mysten/sui.js/utils";
@@ -4356,7 +4627,7 @@ var generateCoreQuickMethod = ({
4356
4627
  };
4357
4628
  };
4358
4629
  var newCoreTxBlock = (builder, initTxBlock) => {
4359
- const txBlock = initTxBlock instanceof TransactionBlock ? new SuiKitTxBlock3(initTxBlock) : initTxBlock ? initTxBlock : new SuiKitTxBlock3();
4630
+ const txBlock = initTxBlock instanceof TransactionBlock ? new SuiKitTxBlock(initTxBlock) : initTxBlock ? initTxBlock : new SuiKitTxBlock();
4360
4631
  const normalMethod = generateCoreNormalMethod({
4361
4632
  builder,
4362
4633
  txBlock
@@ -4386,7 +4657,7 @@ var newCoreTxBlock = (builder, initTxBlock) => {
4386
4657
  // src/builders/spoolBuilder.ts
4387
4658
  import { TransactionBlock as TransactionBlock2 } from "@mysten/sui.js/transactions";
4388
4659
  import { SUI_CLOCK_OBJECT_ID as SUI_CLOCK_OBJECT_ID3 } from "@mysten/sui.js/utils";
4389
- import { SuiTxBlock as SuiKitTxBlock4 } from "@scallop-io/sui-kit";
4660
+ import { SuiTxBlock as SuiKitTxBlock2 } from "@scallop-io/sui-kit";
4390
4661
  var requireStakeAccountIds = async (...params) => {
4391
4662
  const [builder, txBlock, stakeMarketCoinName, stakeAccountId] = params;
4392
4663
  if (params.length === 4 && stakeAccountId)
@@ -4544,7 +4815,7 @@ var generateSpoolQuickMethod = ({
4544
4815
  };
4545
4816
  };
4546
4817
  var newSpoolTxBlock = (builder, initTxBlock) => {
4547
- const txBlock = initTxBlock instanceof TransactionBlock2 ? new SuiKitTxBlock4(initTxBlock) : initTxBlock ? initTxBlock : new SuiKitTxBlock4();
4818
+ const txBlock = initTxBlock instanceof TransactionBlock2 ? new SuiKitTxBlock2(initTxBlock) : initTxBlock ? initTxBlock : new SuiKitTxBlock2();
4548
4819
  const normalMethod = generateSpoolNormalMethod({
4549
4820
  builder,
4550
4821
  txBlock
@@ -4574,13 +4845,13 @@ var newSpoolTxBlock = (builder, initTxBlock) => {
4574
4845
  // src/builders/borrowIncentiveBuilder.ts
4575
4846
  import { TransactionBlock as TransactionBlock4 } from "@mysten/sui.js/transactions";
4576
4847
  import { SUI_CLOCK_OBJECT_ID as SUI_CLOCK_OBJECT_ID5 } from "@mysten/sui.js/utils";
4577
- import { SuiTxBlock as SuiKitTxBlock6 } from "@scallop-io/sui-kit";
4848
+ import { SuiTxBlock as SuiKitTxBlock4 } from "@scallop-io/sui-kit";
4578
4849
 
4579
4850
  // src/builders/vescaBuilder.ts
4580
4851
  import {
4581
4852
  SUI_CLOCK_OBJECT_ID as SUI_CLOCK_OBJECT_ID4,
4582
4853
  TransactionBlock as TransactionBlock3,
4583
- SuiTxBlock as SuiKitTxBlock5
4854
+ SuiTxBlock as SuiKitTxBlock3
4584
4855
  } from "@scallop-io/sui-kit";
4585
4856
  var requireVeSca = async (...params) => {
4586
4857
  const [builder, txBlock, veScaKey] = params;
@@ -4596,7 +4867,10 @@ var requireVeSca = async (...params) => {
4596
4867
  if (veScas.length === 0) {
4597
4868
  return void 0;
4598
4869
  }
4599
- return veScas[0];
4870
+ return veScas.reduce(
4871
+ (prev, acc) => acc.currentVeScaBalance > prev.currentVeScaBalance ? acc : prev,
4872
+ veScas[0]
4873
+ );
4600
4874
  };
4601
4875
  var generateNormalVeScaMethod = ({
4602
4876
  builder,
@@ -4730,7 +5004,7 @@ var generateQuickVeScaMethod = ({
4730
5004
  const veScaKey = txBlock.lockSca(scaCoin, newUnlockAt);
4731
5005
  transferObjects.push(veScaKey);
4732
5006
  } else {
4733
- if (veSca.lockedScaAmount !== 0) {
5007
+ if (veSca.lockedScaCoin !== 0) {
4734
5008
  const unlockedSca = txBlock.redeemSca(veSca.keyId);
4735
5009
  transferObjects.push(unlockedSca);
4736
5010
  }
@@ -4790,7 +5064,7 @@ var generateQuickVeScaMethod = ({
4790
5064
  checkRenewExpiredVeSca(scaAmount, lockPeriodInDays, veSca?.unlockAt);
4791
5065
  if (veSca) {
4792
5066
  const transferObjects = [];
4793
- if (veSca.lockedScaAmount !== 0) {
5067
+ if (veSca.lockedScaCoin !== 0) {
4794
5068
  const unlockedSca = txBlock.redeemSca(veSca.keyId);
4795
5069
  transferObjects.push(unlockedSca);
4796
5070
  }
@@ -4820,7 +5094,7 @@ var generateQuickVeScaMethod = ({
4820
5094
  };
4821
5095
  };
4822
5096
  var newVeScaTxBlock = (builder, initTxBlock) => {
4823
- const txBlock = initTxBlock instanceof TransactionBlock3 ? new SuiKitTxBlock5(initTxBlock) : initTxBlock ? initTxBlock : new SuiKitTxBlock5();
5097
+ const txBlock = initTxBlock instanceof TransactionBlock3 ? new SuiKitTxBlock3(initTxBlock) : initTxBlock ? initTxBlock : new SuiKitTxBlock3();
4824
5098
  const normalMethod = generateNormalVeScaMethod({
4825
5099
  builder,
4826
5100
  txBlock
@@ -4871,37 +5145,6 @@ var requireObligationInfo2 = async (...params) => {
4871
5145
  obligationLocked: selectedObligation.locked
4872
5146
  };
4873
5147
  };
4874
- var getBindedObligationId = async (builder, veScaKey) => {
4875
- const borrowIncentiveObjectId = builder.address.get("borrowIncentive.object");
4876
- const incentivePoolsId = builder.address.get(
4877
- "borrowIncentive.incentivePools"
4878
- );
4879
- const veScaPkgId = IS_VE_SCA_TEST ? "0xb220d034bdf335d77ae5bfbf6daf059c2cc7a1f719b12bfed75d1736fac038c8" : builder.address.get("vesca.id");
4880
- const client = builder.suiKit.client();
4881
- const incentivePoolsResponse = await client.getObject({
4882
- id: incentivePoolsId,
4883
- options: {
4884
- showContent: true
4885
- }
4886
- });
4887
- if (incentivePoolsResponse.data?.content?.dataType !== "moveObject")
4888
- return false;
4889
- const incentivePoolFields = incentivePoolsResponse.data.content.fields;
4890
- const veScaBindTableId = incentivePoolFields.ve_sca_bind.fields.id.id;
4891
- const keyType = `${borrowIncentiveObjectId}::typed_id::TypedID<${veScaPkgId}::ve_sca::VeScaKey>`;
4892
- const veScaBindTableResponse = await client.getDynamicFieldObject({
4893
- parentId: veScaBindTableId,
4894
- name: {
4895
- type: keyType,
4896
- value: veScaKey
4897
- }
4898
- });
4899
- if (veScaBindTableResponse.data?.content?.dataType !== "moveObject")
4900
- return false;
4901
- const veScaBindTableFields = veScaBindTableResponse.data.content.fields;
4902
- const obligationId = veScaBindTableFields.value.fields.id;
4903
- return obligationId;
4904
- };
4905
5148
  var generateBorrowIncentiveNormalMethod = ({ builder, txBlock }) => {
4906
5149
  const borrowIncentiveIds = {
4907
5150
  borrowIncentivePkg: IS_VE_SCA_TEST ? "0x4d5a7cefa4147b4ace0ca845b20437d6ac0d32e5f2f855171f745472c2576246" : builder.address.get("borrowIncentive.id"),
@@ -4966,7 +5209,7 @@ var generateBorrowIncentiveNormalMethod = ({ builder, txBlock }) => {
4966
5209
  );
4967
5210
  },
4968
5211
  claimBorrowIncentive: (obligationId, obligationKey, coinName, rewardCoinName) => {
4969
- const rewardCoinNames = borrowIncentiveRewardCoins[coinName];
5212
+ const rewardCoinNames = builder.utils.getBorrowIncentiveRewardCoinName(coinName);
4970
5213
  if (rewardCoinNames.includes(rewardCoinName) === false) {
4971
5214
  throw new Error(`Invalid reward coin name ${rewardCoinName}`);
4972
5215
  }
@@ -5041,7 +5284,7 @@ var generateBorrowIncentiveQuickMethod = ({ builder, txBlock }) => {
5041
5284
  const veSca = await requireVeSca(builder, txBlock, veScaKey);
5042
5285
  if (veSca) {
5043
5286
  const bindedObligationId = await getBindedObligationId(
5044
- builder,
5287
+ builder.query,
5045
5288
  veSca.keyId
5046
5289
  );
5047
5290
  if (!bindedObligationId || bindedObligationId === obligationArg) {
@@ -5093,7 +5336,7 @@ var generateBorrowIncentiveQuickMethod = ({ builder, txBlock }) => {
5093
5336
  };
5094
5337
  };
5095
5338
  var newBorrowIncentiveTxBlock = (builder, initTxBlock) => {
5096
- const txBlock = initTxBlock instanceof TransactionBlock4 ? new SuiKitTxBlock6(initTxBlock) : initTxBlock ? initTxBlock : new SuiKitTxBlock6();
5339
+ const txBlock = initTxBlock instanceof TransactionBlock4 ? new SuiKitTxBlock4(initTxBlock) : initTxBlock ? initTxBlock : new SuiKitTxBlock4();
5097
5340
  const normalMethod = generateBorrowIncentiveNormalMethod({
5098
5341
  builder,
5099
5342
  txBlock
@@ -5148,18 +5391,24 @@ var ScallopBuilder = class {
5148
5391
  constructor(params, instance) {
5149
5392
  this.params = params;
5150
5393
  this.suiKit = instance?.suiKit ?? new SuiKit3(params);
5151
- this.address = instance?.address ?? new ScallopAddress({
5152
- id: params?.addressesId || ADDRESSES_ID,
5153
- network: params?.networkType
5154
- });
5394
+ this.cache = instance?.cache ?? new ScallopCache(DEFAULT_CACHE_OPTIONS, this.suiKit);
5395
+ this.address = instance?.address ?? new ScallopAddress(
5396
+ {
5397
+ id: params?.addressesId || ADDRESSES_ID,
5398
+ network: params?.networkType
5399
+ },
5400
+ this.cache
5401
+ );
5155
5402
  this.query = instance?.query ?? new ScallopQuery(params, {
5156
5403
  suiKit: this.suiKit,
5157
- address: this.address
5404
+ address: this.address,
5405
+ cache: this.cache
5158
5406
  });
5159
5407
  this.utils = instance?.utils ?? new ScallopUtils(this.params, {
5160
5408
  suiKit: this.suiKit,
5161
5409
  address: this.address,
5162
- query: this.query
5410
+ query: this.query,
5411
+ cache: this.cache
5163
5412
  });
5164
5413
  this.walletAddress = normalizeSuiAddress(
5165
5414
  params?.walletAddress || this.suiKit.currentAddress()
@@ -5241,24 +5490,31 @@ var ScallopClient = class {
5241
5490
  constructor(params, instance) {
5242
5491
  this.params = params;
5243
5492
  this.suiKit = instance?.suiKit ?? new SuiKit4(params);
5244
- this.address = instance?.address ?? new ScallopAddress({
5245
- id: params?.addressesId || ADDRESSES_ID,
5246
- network: params?.networkType
5247
- });
5493
+ this.cache = instance?.cache ?? new ScallopCache(DEFAULT_CACHE_OPTIONS, this.suiKit);
5494
+ this.address = instance?.address ?? new ScallopAddress(
5495
+ {
5496
+ id: params?.addressesId || ADDRESSES_ID,
5497
+ network: params?.networkType
5498
+ },
5499
+ this.cache
5500
+ );
5248
5501
  this.query = instance?.query ?? new ScallopQuery(params, {
5249
5502
  suiKit: this.suiKit,
5250
- address: this.address
5503
+ address: this.address,
5504
+ cache: this.cache
5251
5505
  });
5252
5506
  this.utils = instance?.utils ?? new ScallopUtils(params, {
5253
5507
  suiKit: this.suiKit,
5254
5508
  address: this.address,
5255
- query: this.query
5509
+ query: this.query,
5510
+ cache: this.cache
5256
5511
  });
5257
5512
  this.builder = instance?.builder ?? new ScallopBuilder(params, {
5258
5513
  suiKit: this.suiKit,
5259
5514
  address: this.address,
5260
5515
  query: this.query,
5261
- utils: this.utils
5516
+ utils: this.utils,
5517
+ cache: this.cache
5262
5518
  });
5263
5519
  this.walletAddress = normalizeSuiAddress2(
5264
5520
  params?.walletAddress || this.suiKit.currentAddress()
@@ -5764,13 +6020,20 @@ var ScallopClient = class {
5764
6020
 
5765
6021
  // src/models/scallop.ts
5766
6022
  var Scallop = class {
5767
- constructor(params) {
6023
+ constructor(params, cacheOptions) {
5768
6024
  this.params = params;
5769
6025
  this.suiKit = new SuiKit5(params);
5770
- this._address = new ScallopAddress({
5771
- id: params?.addressesId || ADDRESSES_ID,
5772
- network: params?.networkType
5773
- });
6026
+ this.cache = new ScallopCache(
6027
+ cacheOptions ?? DEFAULT_CACHE_OPTIONS,
6028
+ this.suiKit
6029
+ );
6030
+ this._address = new ScallopAddress(
6031
+ {
6032
+ id: params?.addressesId || ADDRESSES_ID,
6033
+ network: params?.networkType
6034
+ },
6035
+ this.cache
6036
+ );
5774
6037
  }
5775
6038
  /**
5776
6039
  * Get a scallop address instance that already has read addresses.
@@ -5792,7 +6055,8 @@ var Scallop = class {
5792
6055
  await this._address.read();
5793
6056
  const scallopBuilder = new ScallopBuilder(this.params, {
5794
6057
  suiKit: this.suiKit,
5795
- address: this._address
6058
+ address: this._address,
6059
+ cache: this.cache
5796
6060
  });
5797
6061
  return scallopBuilder;
5798
6062
  }
@@ -5807,7 +6071,7 @@ var Scallop = class {
5807
6071
  await this._address.read();
5808
6072
  const scallopClient = new ScallopClient(
5809
6073
  { ...this.params, walletAddress },
5810
- { suiKit: this.suiKit, address: this._address }
6074
+ { suiKit: this.suiKit, address: this._address, cache: this.cache }
5811
6075
  );
5812
6076
  return scallopClient;
5813
6077
  }
@@ -5821,7 +6085,8 @@ var Scallop = class {
5821
6085
  await this._address.read();
5822
6086
  const scallopQuery = new ScallopQuery(this.params, {
5823
6087
  suiKit: this.suiKit,
5824
- address: this._address
6088
+ address: this._address,
6089
+ cache: this.cache
5825
6090
  });
5826
6091
  return scallopQuery;
5827
6092
  }
@@ -5831,7 +6096,9 @@ var Scallop = class {
5831
6096
  * @return Scallop Indexer.
5832
6097
  */
5833
6098
  async createScallopIndexer() {
5834
- const scallopIndexer = new ScallopIndexer();
6099
+ const scallopIndexer = new ScallopIndexer(this.params, {
6100
+ cache: this.cache
6101
+ });
5835
6102
  return scallopIndexer;
5836
6103
  }
5837
6104
  /**
@@ -5844,7 +6111,8 @@ var Scallop = class {
5844
6111
  await this._address.read();
5845
6112
  const scallopUtils = new ScallopUtils(this.params, {
5846
6113
  suiKit: this.suiKit,
5847
- address: this._address
6114
+ address: this._address,
6115
+ cache: this.cache
5848
6116
  });
5849
6117
  return scallopUtils;
5850
6118
  }
@@ -5873,6 +6141,7 @@ export {
5873
6141
  Scallop,
5874
6142
  ScallopAddress,
5875
6143
  ScallopBuilder,
6144
+ ScallopCache,
5876
6145
  ScallopClient,
5877
6146
  ScallopIndexer,
5878
6147
  ScallopQuery,