@scallop-io/sui-scallop-sdk 1.3.0-alpha.1 → 1.3.0-alpha.2

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 (41) hide show
  1. package/dist/constants/common.d.ts +6 -4
  2. package/dist/constants/enum.d.ts +1 -0
  3. package/dist/index.js +211 -137
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.mjs +208 -137
  6. package/dist/index.mjs.map +1 -1
  7. package/dist/models/scallopBuilder.d.ts +4 -4
  8. package/dist/models/scallopQuery.d.ts +11 -3
  9. package/dist/models/scallopUtils.d.ts +4 -2
  10. package/dist/queries/borrowIncentiveQuery.d.ts +2 -0
  11. package/dist/queries/coreQuery.d.ts +2 -0
  12. package/dist/queries/portfolioQuery.d.ts +1 -0
  13. package/dist/queries/sCoinQuery.d.ts +1 -1
  14. package/dist/queries/vescaQuery.d.ts +1 -1
  15. package/dist/types/constant/common.d.ts +3 -1
  16. package/dist/types/constant/enum.d.ts +7 -1
  17. package/dist/types/model.d.ts +3 -0
  18. package/dist/utils/index.d.ts +1 -0
  19. package/dist/utils/indexer.d.ts +17 -0
  20. package/dist/utils/util.d.ts +4 -2
  21. package/package.json +6 -6
  22. package/src/builders/coreBuilder.ts +2 -2
  23. package/src/builders/referralBuilder.ts +1 -1
  24. package/src/builders/spoolBuilder.ts +1 -1
  25. package/src/constants/common.ts +15 -1
  26. package/src/constants/enum.ts +13 -0
  27. package/src/models/scallop.ts +1 -0
  28. package/src/models/scallopAddress.ts +13 -1
  29. package/src/models/scallopBuilder.ts +1 -0
  30. package/src/models/scallopClient.ts +6 -4
  31. package/src/models/scallopQuery.ts +42 -2
  32. package/src/models/scallopUtils.ts +54 -23
  33. package/src/queries/coreQuery.ts +0 -1
  34. package/src/queries/spoolQuery.ts +40 -103
  35. package/src/queries/vescaQuery.ts +8 -2
  36. package/src/types/constant/common.ts +4 -0
  37. package/src/types/constant/enum.ts +9 -0
  38. package/src/types/model.ts +3 -0
  39. package/src/utils/index.ts +1 -0
  40. package/src/utils/indexer.ts +39 -0
  41. package/src/utils/util.ts +25 -3
@@ -17,6 +17,7 @@ import {
17
17
  MAX_LOCK_DURATION,
18
18
  SUPPORT_SCOIN,
19
19
  sCoinIds,
20
+ suiBridgeCoins,
20
21
  } from '../constants';
21
22
  import { getPythPrice, queryObligation } from '../queries';
22
23
  import {
@@ -24,6 +25,8 @@ import {
24
25
  isMarketCoin,
25
26
  parseAssetSymbol,
26
27
  findClosestUnlockRound,
28
+ isSuiBridgeAsset,
29
+ isWormholeAsset,
27
30
  } from '../utils';
28
31
  import { PYTH_ENDPOINTS } from 'src/constants/pyth';
29
32
  import { ScallopCache } from './scallopCache';
@@ -40,6 +43,8 @@ import type {
40
43
  CoinWrappedType,
41
44
  SupportSCoin,
42
45
  ScallopUtilsInstanceParams,
46
+ SupportSuiBridgeCoins,
47
+ SupportWormholeCoins,
43
48
  } from '../types';
44
49
  import type { SuiObjectArg, SuiTxArg, SuiTxBlock } from '@scallop-io/sui-kit';
45
50
 
@@ -96,6 +101,7 @@ export class ScallopUtils {
96
101
  {
97
102
  id: params?.addressesId || ADDRESSES_ID,
98
103
  network: params?.networkType,
104
+ forceInterface: params?.forceAddressesInterface,
99
105
  },
100
106
  {
101
107
  cache: this.cache,
@@ -106,6 +112,14 @@ export class ScallopUtils {
106
112
  ? params.networkType === 'testnet'
107
113
  : false;
108
114
  }
115
+ // -------------- TYPE GUARDS --------------
116
+ public isSuiBridgeAsset(coinName: any): coinName is SupportSuiBridgeCoins {
117
+ return isSuiBridgeAsset(coinName);
118
+ }
119
+
120
+ public isWormholeAsset(coinName: any): coinName is SupportWormholeCoins {
121
+ return isWormholeAsset(coinName);
122
+ }
109
123
 
110
124
  /**
111
125
  * Request the scallop API to initialize data.
@@ -128,16 +142,7 @@ export class ScallopUtils {
128
142
  * @return Symbol string.
129
143
  */
130
144
  public parseSymbol(coinName: SupportCoins) {
131
- if (isMarketCoin(coinName)) {
132
- const assetCoinName = coinName
133
- .slice(1)
134
- .toLowerCase() as SupportAssetCoins;
135
- return (
136
- coinName.slice(0, 1).toLowerCase() + parseAssetSymbol(assetCoinName)
137
- );
138
- } else {
139
- return parseAssetSymbol(coinName);
140
- }
145
+ return parseAssetSymbol(coinName);
141
146
  }
142
147
 
143
148
  /**
@@ -173,10 +178,23 @@ export class ScallopUtils {
173
178
  const voloPackageIds = [
174
179
  this.address.get('core.coins.vsui.id') ?? voloCoinIds.vsui,
175
180
  ];
181
+
182
+ const suiBridgePackageIds = Object.values<SupportSuiBridgeCoins>(
183
+ suiBridgeCoins
184
+ ).reduce((curr, coinName) => {
185
+ curr.push(
186
+ this.address.get(`core.coins.${coinName}.id`) ?? coinIds[coinName]
187
+ );
188
+ return curr;
189
+ }, [] as string[]);
176
190
  if (wormHolePackageIds.includes(coinPackageId)) {
177
191
  return `${coinPackageId}::coin::COIN`;
178
192
  } else if (voloPackageIds.includes(coinPackageId)) {
179
193
  return `${coinPackageId}::cert::CERT`;
194
+ } else if (suiBridgePackageIds.includes(coinPackageId)) {
195
+ // handle sui bridge assets
196
+ const typeCoinName = coinName.slice(2);
197
+ return `${coinPackageId}::${typeCoinName}::${typeCoinName.toUpperCase()}`;
180
198
  } else {
181
199
  return `${coinPackageId}::${coinName}::${coinName.toUpperCase()}`;
182
200
  }
@@ -299,9 +317,20 @@ export class ScallopUtils {
299
317
  }::cert::CERT`]: 'vsui',
300
318
  };
301
319
 
320
+ const suiBridgeTypeMap = Object.values<SupportSuiBridgeCoins>(
321
+ suiBridgeCoins
322
+ ).reduce(
323
+ (curr, coinName) => {
324
+ curr[this.parseCoinType(coinName)] = coinName;
325
+ return curr;
326
+ },
327
+ {} as Record<string, SupportSuiBridgeCoins>
328
+ );
329
+
302
330
  const assetCoinName =
303
331
  wormHoleCoinTypeMap[coinType] ||
304
332
  voloCoinTypeMap[coinType] ||
333
+ suiBridgeTypeMap[coinType] ||
305
334
  (coinType.split('::')[2].toLowerCase() as SupportAssetCoins);
306
335
 
307
336
  return isMarketCoinType
@@ -310,7 +339,7 @@ export class ScallopUtils {
310
339
  }
311
340
 
312
341
  /**
313
- * Convert marke coin name to coin name.
342
+ * Convert market coin name to coin name.
314
343
  *
315
344
  * @param marketCoinName - Specific support market coin name.
316
345
  * @return Coin Name.
@@ -370,17 +399,19 @@ export class ScallopUtils {
370
399
  * return Coin wrapped type.
371
400
  */
372
401
  public getCoinWrappedType(assetCoinName: SupportAssetCoins): CoinWrappedType {
373
- return assetCoinName === 'wusdc' ||
374
- assetCoinName === 'wusdt' ||
375
- assetCoinName === 'weth' ||
376
- assetCoinName === 'wbtc' ||
377
- assetCoinName === 'wapt' ||
378
- assetCoinName === 'wsol'
379
- ? {
380
- from: 'Wormhole',
381
- type: 'Portal from Ethereum',
382
- }
383
- : undefined;
402
+ if (this.isSuiBridgeAsset(assetCoinName)) {
403
+ return {
404
+ from: 'Sui Bridge',
405
+ type: 'Asset from Sui Bridge',
406
+ };
407
+ } else if (this.isWormholeAsset(assetCoinName)) {
408
+ return {
409
+ from: 'Wormhole',
410
+ type: 'Portal from Ethereum',
411
+ };
412
+ }
413
+
414
+ return undefined;
384
415
  }
385
416
 
386
417
  /**
@@ -429,7 +460,7 @@ export class ScallopUtils {
429
460
  if (existingCoins.length > 0) {
430
461
  txBlock.mergeCoins(dest, existingCoins.slice(0, 500));
431
462
  }
432
- } catch (e) {
463
+ } catch (_e) {
433
464
  // ignore
434
465
  }
435
466
  }
@@ -324,7 +324,6 @@ export const getMarketPool = async (
324
324
  if (marketObject.content && 'fields' in marketObject.content) {
325
325
  const fields = marketObject.content.fields as any;
326
326
  const coinType = query.utils.parseCoinType(poolCoinName);
327
-
328
327
  // Get balance sheet.
329
328
  const balanceSheetParentId =
330
329
  fields.vault.fields.balance_sheets.fields.table.fields.id.id;
@@ -272,18 +272,13 @@ export const getStakeAccounts = async (
272
272
  }
273
273
  } while (hasNextPage);
274
274
 
275
- const stakeAccounts: StakeAccounts = {
276
- susdc: [],
277
- sweth: [],
278
- ssui: [],
279
- swusdc: [],
280
- swusdt: [],
281
- scetus: [],
282
- safsui: [],
283
- shasui: [],
284
- svsui: [],
285
- // ssca: [],
286
- };
275
+ const stakeAccounts: StakeAccounts = SUPPORT_SPOOLS.reduce(
276
+ (acc, stakeName) => {
277
+ acc[stakeName] = [];
278
+ return acc;
279
+ },
280
+ {} as StakeAccounts
281
+ );
287
282
 
288
283
  const stakeMarketCoinTypes: Record<SupportStakeMarketCoins, string> =
289
284
  Object.keys(stakeAccounts).reduce(
@@ -299,6 +294,16 @@ export const getStakeAccounts = async (
299
294
  {} as Record<SupportStakeMarketCoins, string>
300
295
  );
301
296
 
297
+ // Reverse the mapping
298
+ const reversedStakeMarketCoinTypes: Record<string, SupportStakeMarketCoins> =
299
+ Object.entries(stakeMarketCoinTypes).reduce(
300
+ (reversedTypes, [key, value]) => {
301
+ reversedTypes[value] = key as SupportStakeMarketCoins;
302
+ return reversedTypes;
303
+ },
304
+ {} as Record<string, SupportStakeMarketCoins>
305
+ );
306
+
302
307
  const stakeObjectIds: string[] = stakeObjectsResponse
303
308
  .map((ref: any) => ref?.data?.objectId)
304
309
  .filter((id: any) => id !== undefined);
@@ -317,98 +322,30 @@ export const getStakeAccounts = async (
317
322
  const index = Number(fields.index);
318
323
  const points = Number(fields.points);
319
324
  const totalPoints = Number(fields.total_points);
320
- if (normalizeStructTag(type) === stakeMarketCoinTypes.sweth) {
321
- stakeAccounts.sweth.push({
322
- id,
323
- type: normalizeStructTag(type),
324
- stakePoolId,
325
- stakeType: normalizeStructTag(stakeType),
326
- staked,
327
- index,
328
- points,
329
- totalPoints,
330
- });
331
- } else if (normalizeStructTag(type) === stakeMarketCoinTypes.ssui) {
332
- stakeAccounts.ssui.push({
333
- id,
334
- type: normalizeStructTag(type),
335
- stakePoolId,
336
- stakeType: normalizeStructTag(stakeType),
337
- staked,
338
- index,
339
- points,
340
- totalPoints,
341
- });
342
- } else if (normalizeStructTag(type) === stakeMarketCoinTypes.swusdc) {
343
- stakeAccounts.swusdc.push({
344
- id,
345
- type: normalizeStructTag(type),
346
- stakePoolId,
347
- stakeType: normalizeStructTag(stakeType),
348
- staked,
349
- index,
350
- points,
351
- totalPoints,
352
- });
353
- } else if (normalizeStructTag(type) === stakeMarketCoinTypes.swusdt) {
354
- stakeAccounts.swusdt.push({
355
- id,
356
- type: normalizeStructTag(type),
357
- stakePoolId,
358
- stakeType: normalizeStructTag(stakeType),
359
- staked,
360
- index,
361
- points,
362
- totalPoints,
363
- });
364
- } else if (normalizeStructTag(type) === stakeMarketCoinTypes.scetus) {
365
- stakeAccounts.scetus.push({
366
- id,
367
- type: normalizeStructTag(type),
368
- stakePoolId,
369
- stakeType: normalizeStructTag(stakeType),
370
- staked,
371
- index,
372
- points,
373
- totalPoints,
374
- });
375
- } else if (normalizeStructTag(type) === stakeMarketCoinTypes.safsui) {
376
- stakeAccounts.safsui.push({
377
- id,
378
- type: normalizeStructTag(type),
379
- stakePoolId,
380
- stakeType: normalizeStructTag(stakeType),
381
- staked,
382
- index,
383
- points,
384
- totalPoints,
385
- });
386
- } else if (normalizeStructTag(type) === stakeMarketCoinTypes.shasui) {
387
- stakeAccounts.shasui.push({
388
- id,
389
- type: normalizeStructTag(type),
390
- stakePoolId,
391
- stakeType: normalizeStructTag(stakeType),
392
- staked,
393
- index,
394
- points,
395
- totalPoints,
396
- });
397
- } else if (normalizeStructTag(type) === stakeMarketCoinTypes.svsui) {
398
- stakeAccounts.svsui.push({
399
- id,
400
- type: normalizeStructTag(type),
401
- stakePoolId,
402
- stakeType: normalizeStructTag(stakeType),
403
- staked,
404
- index,
405
- points,
406
- totalPoints,
407
- });
408
- } else if (normalizeStructTag(type) === stakeMarketCoinTypes.susdc) {
409
- stakeAccounts.susdc.push({
325
+
326
+ const stakeMarketCoinTypeMap: Record<
327
+ SupportStakeMarketCoins,
328
+ StakeAccounts[SupportStakeMarketCoins]
329
+ > = {
330
+ sweth: stakeAccounts.sweth,
331
+ ssui: stakeAccounts.ssui,
332
+ swusdc: stakeAccounts.swusdc,
333
+ swusdt: stakeAccounts.swusdt,
334
+ scetus: stakeAccounts.scetus,
335
+ safsui: stakeAccounts.safsui,
336
+ shasui: stakeAccounts.shasui,
337
+ svsui: stakeAccounts.svsui,
338
+ susdc: stakeAccounts.susdc,
339
+ };
340
+
341
+ const normalizedType = normalizeStructTag(type);
342
+ const stakeAccountArray =
343
+ stakeMarketCoinTypeMap[reversedStakeMarketCoinTypes[normalizedType]];
344
+
345
+ if (stakeAccountArray) {
346
+ stakeAccountArray.push({
410
347
  id,
411
- type: normalizeStructTag(type),
348
+ type: normalizedType,
412
349
  stakePoolId,
413
350
  stakeType: normalizeStructTag(stakeType),
414
351
  staked,
@@ -71,7 +71,8 @@ export const getVeScas = async (
71
71
  }: {
72
72
  utils: ScallopUtils;
73
73
  },
74
- ownerAddress?: string
74
+ ownerAddress?: string,
75
+ excludeEmpty?: boolean
75
76
  ) => {
76
77
  const keyObjectDatas = await getVescaKeys(utils, ownerAddress);
77
78
 
@@ -84,9 +85,14 @@ export const getVeScas = async (
84
85
  });
85
86
  await Promise.allSettled(tasks);
86
87
 
87
- return veScas
88
+ const result = veScas
88
89
  .filter(Boolean)
89
90
  .sort((a, b) => b!.currentVeScaBalance - a!.currentVeScaBalance);
91
+
92
+ if (excludeEmpty) {
93
+ return result.filter((v) => v.lockedScaAmount !== '0');
94
+ }
95
+ return result;
90
96
  };
91
97
 
92
98
  const SuiObjectRefZod = zod.object({
@@ -8,6 +8,8 @@ import {
8
8
  SUPPORT_BORROW_INCENTIVE_POOLS,
9
9
  SUPPORT_BORROW_INCENTIVE_REWARDS,
10
10
  SUPPORT_SCOIN,
11
+ SUPPORT_SUI_BRIDGE,
12
+ SUPPORT_WORMHOLE,
11
13
  } from '../../constants';
12
14
 
13
15
  type ParseMarketCoins<T extends string> = `s${T}`;
@@ -29,6 +31,8 @@ export type SupportMarketCoins =
29
31
  | ParseMarketCoins<SupportPoolCoins>
30
32
  | SupportStakeMarketCoins;
31
33
  export type SupportStakeMarketCoins = (typeof SUPPORT_SPOOLS)[number];
34
+ export type SupportSuiBridgeCoins = (typeof SUPPORT_SUI_BRIDGE)[number];
35
+ export type SupportWormholeCoins = (typeof SUPPORT_WORMHOLE)[number];
32
36
  export type SupportStakeCoins = Extract<
33
37
  SupportPoolCoins,
34
38
  ParseCoins<SupportStakeMarketCoins>
@@ -7,6 +7,7 @@ import {
7
7
  SupportBorrowIncentiveCoins,
8
8
  SupportBorrowIncentiveRewardCoins,
9
9
  SupportSCoin,
10
+ SupportSuiBridgeCoins,
10
11
  } from './common';
11
12
 
12
13
  export type Coins = {
@@ -33,6 +34,10 @@ export type StakeRewardCoins = {
33
34
  [key in SupportStakeMarketCoins]: SupportStakeRewardCoins;
34
35
  };
35
36
 
37
+ export type SuiBridgeCoins = {
38
+ [K in SupportSuiBridgeCoins]: K;
39
+ };
40
+
36
41
  export type BorrowIncentiveRewardCoins = {
37
42
  [key in SupportBorrowIncentiveCoins]: SupportBorrowIncentiveRewardCoins[];
38
43
  };
@@ -65,3 +70,7 @@ export type WormholeCoinIds = {
65
70
  export type VoloCoinIds = {
66
71
  [key in PickFromUnion<SupportAssetCoins, 'vsui'>]: string;
67
72
  };
73
+
74
+ export type SuiBridgedCoinPackageIds = {
75
+ [key in SupportSuiBridgeCoins]: string;
76
+ };
@@ -9,6 +9,7 @@ import type {
9
9
  ScallopIndexer,
10
10
  } from '../models';
11
11
  import { ScallopCache } from 'src/models/scallopCache';
12
+ import { AddressesInterface } from './address';
12
13
 
13
14
  export type ScallopClientFnReturnType<T extends boolean> = T extends true
14
15
  ? SuiTransactionBlockResponse
@@ -56,10 +57,12 @@ export type ScallopAddressParams = {
56
57
  id: string;
57
58
  auth?: string;
58
59
  network?: NetworkType;
60
+ forceInterface?: Partial<Record<NetworkType, AddressesInterface>>;
59
61
  };
60
62
 
61
63
  export type ScallopParams = {
62
64
  addressesId?: string;
65
+ forceAddressesInterface?: Partial<Record<NetworkType, AddressesInterface>>;
63
66
  walletAddress?: string;
64
67
  } & SuiKitParams;
65
68
 
@@ -2,3 +2,4 @@ export * from './builder';
2
2
  export * from './query';
3
3
  export * from './util';
4
4
  export * from './tokenBucket';
5
+ export * from './indexer';
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Generic wrapper for methods with indexer fallback.
3
+ *
4
+ * @param method - The method to call with fallback behavior.
5
+ * @param context - The context (`this`) of the class instance.
6
+ * @param args - The arguments to pass to the method.
7
+ * @returns The result of the method call.
8
+ */
9
+ export async function callMethodWithIndexerFallback(
10
+ method: Function,
11
+ context: any,
12
+ ...args: any[]
13
+ ) {
14
+ const indexer = args[args.length - 1]; // Assume last argument is always `indexer`
15
+
16
+ if (indexer) {
17
+ try {
18
+ return await method.apply(context, args);
19
+ } catch (_e) {
20
+ console.warn('Indexer requests failed. Retrying without indexer..');
21
+ return await method.apply(context, [...args.slice(0, -1), false]);
22
+ }
23
+ }
24
+ return await method.apply(context, args);
25
+ }
26
+
27
+ /**
28
+ * This function creates a wrapper for methods that have an indexer parameter.
29
+ * It ensures fallback behavior if indexer fails.
30
+ *
31
+ * @param method - The method to wrap.
32
+ * @returns A function that applies indexer fallback.
33
+ */
34
+ export function withIndexerFallback(method: Function) {
35
+ return (...args: any[]) => {
36
+ // @ts-ignore
37
+ return callMethodWithIndexerFallback(method, this, ...args); // Preserve `this` with arrow function
38
+ };
39
+ }
package/src/utils/util.ts CHANGED
@@ -6,12 +6,16 @@ import {
6
6
  MAX_LOCK_DURATION,
7
7
  SUPPORT_BORROW_INCENTIVE_REWARDS,
8
8
  SUPPORT_SCOIN,
9
+ SUPPORT_SUI_BRIDGE,
10
+ SUPPORT_WORMHOLE,
9
11
  } from '../constants';
10
12
  import type { ScallopAddress } from '../models';
11
13
  import type {
12
14
  SupportAssetCoins,
13
15
  SupportCoins,
14
16
  SupportMarketCoins,
17
+ SupportSuiBridgeCoins,
18
+ SupportWormholeCoins,
15
19
  } from '../types';
16
20
 
17
21
  const COIN_SET = Array.from(
@@ -33,11 +37,29 @@ export const isMarketCoin = (
33
37
  );
34
38
  };
35
39
 
36
- export const parseAssetSymbol = (coinName: SupportAssetCoins): string => {
37
- const isWormhole = coinName.charAt(0) === 'w';
38
- if (isWormhole) {
40
+ export const isSuiBridgeAsset = (
41
+ coinName: any
42
+ ): coinName is SupportSuiBridgeCoins => {
43
+ return SUPPORT_SUI_BRIDGE.includes(coinName);
44
+ };
45
+
46
+ export const isWormholeAsset = (
47
+ coinName: any
48
+ ): coinName is SupportWormholeCoins => {
49
+ return SUPPORT_WORMHOLE.includes(coinName);
50
+ };
51
+
52
+ export const parseAssetSymbol = (coinName: SupportCoins): string => {
53
+ if (isWormholeAsset(coinName)) {
39
54
  return `w${coinName.slice(1).toUpperCase()}`;
40
55
  }
56
+ if (isSuiBridgeAsset(coinName)) {
57
+ return `sb${coinName.slice(2).toUpperCase()}`;
58
+ }
59
+ if (isMarketCoin(coinName)) {
60
+ const assetCoinName = coinName.slice(1).toLowerCase() as SupportAssetCoins;
61
+ return coinName.slice(0, 1).toLowerCase() + parseAssetSymbol(assetCoinName);
62
+ }
41
63
  switch (coinName) {
42
64
  case 'afsui':
43
65
  return 'afSUI';