@scallop-io/sui-scallop-sdk 1.4.24-alpha.1 → 1.5.0-alpha.1

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 (52) hide show
  1. package/dist/constants/common.d.ts +4 -4
  2. package/dist/constants/enum.d.ts +2 -2
  3. package/dist/constants/index.d.ts +1 -0
  4. package/dist/constants/xoracle.d.ts +2 -0
  5. package/dist/index.js +580 -685
  6. package/dist/index.js.map +1 -1
  7. package/dist/index.mjs +590 -696
  8. package/dist/index.mjs.map +1 -1
  9. package/dist/models/scallopIndexer.d.ts +1 -0
  10. package/dist/models/scallopPrice.d.ts +0 -0
  11. package/dist/models/scallopQuery.d.ts +30 -13
  12. package/dist/models/scallopUtils.d.ts +2 -2
  13. package/dist/queries/borrowIncentiveQuery.d.ts +0 -2
  14. package/dist/queries/coreQuery.d.ts +1 -1
  15. package/dist/queries/index.d.ts +1 -0
  16. package/dist/queries/poolAddressesQuery.d.ts +1 -1
  17. package/dist/queries/portfolioQuery.d.ts +3 -4
  18. package/dist/queries/priceQuery.d.ts +1 -3
  19. package/dist/queries/sCoinQuery.d.ts +1 -1
  20. package/dist/queries/xOracleQuery.d.ts +13 -0
  21. package/dist/types/address.d.ts +1 -0
  22. package/dist/types/constant/index.d.ts +1 -0
  23. package/dist/types/constant/xOracle.d.ts +9 -0
  24. package/package.json +1 -1
  25. package/src/builders/borrowIncentiveBuilder.ts +11 -25
  26. package/src/builders/coreBuilder.ts +15 -72
  27. package/src/builders/oracle.ts +73 -46
  28. package/src/builders/referralBuilder.ts +9 -20
  29. package/src/builders/spoolBuilder.ts +10 -38
  30. package/src/builders/vescaBuilder.ts +11 -26
  31. package/src/constants/coinGecko.ts +4 -12
  32. package/src/constants/common.ts +0 -2
  33. package/src/constants/enum.ts +10 -13
  34. package/src/constants/index.ts +1 -0
  35. package/src/constants/poolAddress.ts +343 -218
  36. package/src/constants/pyth.ts +0 -1
  37. package/src/constants/testAddress.ts +35 -254
  38. package/src/constants/xoracle.ts +25 -0
  39. package/src/models/scallopIndexer.ts +11 -0
  40. package/src/models/scallopPrice.ts +0 -0
  41. package/src/models/scallopQuery.ts +58 -13
  42. package/src/models/scallopUtils.ts +1 -1
  43. package/src/queries/coreQuery.ts +16 -6
  44. package/src/queries/index.ts +1 -0
  45. package/src/queries/poolAddressesQuery.ts +2 -2
  46. package/src/queries/priceQuery.ts +10 -3
  47. package/src/queries/vescaQuery.ts +8 -17
  48. package/src/queries/xOracleQuery.ts +124 -0
  49. package/src/types/address.ts +1 -0
  50. package/src/types/constant/index.ts +1 -0
  51. package/src/types/constant/xOracle.ts +11 -0
  52. package/src/utils/util.ts +4 -9
@@ -12,3 +12,4 @@ export * from './vescaQuery';
12
12
  export * from './borrowLimitQuery';
13
13
  export * from './poolAddressesQuery';
14
14
  export * from './objectsQuery';
15
+ export * from './xOracleQuery';
@@ -1,10 +1,10 @@
1
- import { PYTH_FEED_IDS } from 'src/constants';
1
+ import { PYTH_FEED_IDS, SUPPORT_POOLS } from 'src/constants';
2
2
  import { ScallopQuery } from 'src/models';
3
3
  import { OptionalKeys, SupportPoolCoins } from 'src/types';
4
4
 
5
5
  export const getAllAddresses = async (
6
6
  query: ScallopQuery,
7
- pools: SupportPoolCoins[]
7
+ pools: SupportPoolCoins[] = [...SUPPORT_POOLS]
8
8
  ) => {
9
9
  const results: OptionalKeys<
10
10
  Record<
@@ -133,16 +133,23 @@ export const getPythPrices = async (
133
133
  export const getAllCoinPrices = async (
134
134
  query: ScallopQuery,
135
135
  marketPools?: MarketPools,
136
- coinPrices?: CoinPrices
136
+ coinPrices?: CoinPrices,
137
+ indexer: boolean = false
137
138
  ) => {
138
- coinPrices = coinPrices ?? (await query.utils.getCoinPrices());
139
+ coinPrices =
140
+ coinPrices ??
141
+ (indexer
142
+ ? await query.getCoinPricesByIndexer()
143
+ : await query.utils.getCoinPrices());
144
+
139
145
  marketPools =
140
146
  marketPools ??
141
- (await query.getMarketPools(undefined, { coinPrices })).pools;
147
+ (await query.getMarketPools(undefined, { coinPrices, indexer })).pools;
142
148
 
143
149
  if (!marketPools) {
144
150
  throw new Error(`Failed to fetch market pool for getAllCoinPrices`);
145
151
  }
152
+
146
153
  const sCoinPrices: OptionalKeys<Record<SupportSCoin, number>> = {};
147
154
  SUPPORT_SCOIN.forEach((sCoinName) => {
148
155
  const coinName = query.utils.parseCoinName(sCoinName);
@@ -184,28 +184,19 @@ const getTotalVeScaTreasuryAmount = async (
184
184
  veScaTreasury = veScaTreasury ?? utils.address.get('vesca.treasury');
185
185
 
186
186
  const txb = new SuiTxBlock();
187
+ const clockObjectRef = txb.sharedObjectRef({
188
+ objectId: SUI_CLOCK_OBJECT_ID,
189
+ mutable: false,
190
+ initialSharedVersion: '1',
191
+ });
192
+
187
193
  // refresh query
188
194
  const refreshQueryTarget = `${veScaPkgId}::treasury::refresh`;
189
- const refreshArgs = [
190
- veScaConfig,
191
- veScaTreasury,
192
- txb.sharedObjectRef({
193
- objectId: SUI_CLOCK_OBJECT_ID,
194
- mutable: false,
195
- initialSharedVersion: '1',
196
- }),
197
- ];
195
+ const refreshArgs = [veScaConfig, veScaTreasury, clockObjectRef];
198
196
 
199
197
  // query total veSca amount
200
198
  const veScaAmountQueryTarget = `${veScaPkgId}::treasury::total_ve_sca_amount`;
201
- const veScaAmountArgs = [
202
- veScaTreasury,
203
- txb.sharedObjectRef({
204
- objectId: SUI_CLOCK_OBJECT_ID,
205
- mutable: false,
206
- initialSharedVersion: '1',
207
- }),
208
- ];
199
+ const veScaAmountArgs = [veScaTreasury, clockObjectRef];
209
200
 
210
201
  // resolve each args
211
202
  const resolvedRefreshArgs = await Promise.all(
@@ -0,0 +1,124 @@
1
+ import { SuiObjectResponse } from '@mysten/sui/client';
2
+ import { ScallopAddress, ScallopUtils } from 'src/models';
3
+ import {
4
+ SupportAssetCoins,
5
+ SupportOracleType,
6
+ xOracleRuleType,
7
+ } from 'src/types';
8
+
9
+ const PRIMARY_PRICE_UPDATE_POLICY =
10
+ '0xbcd908d0ee6d63d726e61676f3feeec3d19817f4849bbecf372dd3399f247f6b'; // @TODO: move this constant to api address
11
+ const SECONDARY_PRICE_UPDDATE_POLICY =
12
+ '0x624a6f120777bb30e718b86e836c205ef4229448052377dc3d78272a6662b2c0'; // @TODO: move this constant to api address
13
+
14
+ /**
15
+ * Query the price update policy table ids. Usually the value for these table will be constant.
16
+ * @param query
17
+ * @returns
18
+ */
19
+ export const getPriceUpdatePolicies = async (
20
+ address: ScallopAddress
21
+ ): Promise<{
22
+ primary: SuiObjectResponse | null;
23
+ secondary: SuiObjectResponse | null;
24
+ }> => {
25
+ const priceUpdatePolicyRulesKeyType = `${address.get('core.packages.xOracle.object')}::price_update_policy::PriceUpdatePolicyRulesKey`;
26
+
27
+ const [primaryPriceUpdatePolicyTable, secondaryPriceUpdatePolicyTable] =
28
+ await Promise.all([
29
+ address.cache.queryGetDynamicFieldObject({
30
+ parentId: PRIMARY_PRICE_UPDATE_POLICY,
31
+ name: {
32
+ type: priceUpdatePolicyRulesKeyType,
33
+ value: { dummy_field: false },
34
+ },
35
+ }),
36
+ address.cache.queryGetDynamicFieldObject({
37
+ parentId: SECONDARY_PRICE_UPDDATE_POLICY,
38
+ name: {
39
+ type: priceUpdatePolicyRulesKeyType,
40
+ value: { dummy_field: false },
41
+ },
42
+ }),
43
+ ]);
44
+
45
+ return {
46
+ primary: primaryPriceUpdatePolicyTable,
47
+ secondary: secondaryPriceUpdatePolicyTable,
48
+ };
49
+ };
50
+
51
+ // const PRIMARY_PRICE_UPDATE_POLICY_KEY =
52
+ // '0x856d0930acc36780eda9ea47019c979ca6ad34fd36f158b181eb7350195acc00';
53
+ // const SECONDARY_PRICE_UPDATE_POLICY_KEY =
54
+ // '0x304d226734fa5e376423c9ff0f1d49aeb1e2572d4b617d31e11e2f69865b73ed';
55
+ const PRIMARY_PRICE_UPDATE_POLICY_VECSET_ID =
56
+ '0xfb1330aa028ed6a159b742c71b5a79b3b6824cf71efa40ea82b52486ad209264';
57
+ const SECONDARY_PRICE_UPDATE_POLICY_VECSET_ID =
58
+ '0x4b827acc73f3f53f808dd73a7ee0a60ae61e84322176bece72b26467030b467c';
59
+
60
+ export const getAssetOracles = async (
61
+ utils: ScallopUtils,
62
+ ruleType: xOracleRuleType
63
+ ): Promise<Record<SupportAssetCoins, SupportOracleType[]>> => {
64
+ const ruleTypeNameToOracleType: Record<string, SupportOracleType> = {
65
+ [`${utils.address.get('core.packages.pyth.object')}::rule::Rule`]: 'pyth',
66
+ [`${utils.address.get('core.packages.supra.object')}::rule::Rule`]: 'supra',
67
+ [`${utils.address.get('core.packages.switchboard.object')}::rule::Rule`]:
68
+ 'switchboard',
69
+ };
70
+
71
+ const assetPrimaryOracles = {} as Record<
72
+ SupportAssetCoins,
73
+ SupportOracleType[]
74
+ >;
75
+ let cursor = null;
76
+ do {
77
+ const response = await utils.cache.queryGetDynamicFields({
78
+ parentId:
79
+ ruleType === 'primary'
80
+ ? PRIMARY_PRICE_UPDATE_POLICY_VECSET_ID
81
+ : SECONDARY_PRICE_UPDATE_POLICY_VECSET_ID,
82
+ cursor,
83
+ limit: 10,
84
+ });
85
+ if (!response) break;
86
+ const { data, hasNextPage, nextCursor } = response;
87
+ cursor = nextCursor;
88
+
89
+ // Group object ids
90
+ const objectIds = data.map((dynamicField) => dynamicField.objectId);
91
+
92
+ // batch fetch object responses
93
+ const objectResponses = await utils.cache.queryGetObjects(objectIds);
94
+ objectResponses.forEach((object) => {
95
+ if (!object.content || object.content.dataType !== 'moveObject') return;
96
+ const fields = object.content.fields as any;
97
+ const typeName = (
98
+ fields.name as { type: string; fields: { name: string } }
99
+ ).fields.name;
100
+
101
+ const assetName = utils.parseCoinNameFromType(`0x${typeName}`);
102
+ if (!assetName) throw new Error(`Invalid asset name: ${assetName}`);
103
+ if (!assetPrimaryOracles[assetName]) {
104
+ assetPrimaryOracles[assetName] = [];
105
+ }
106
+
107
+ const value = fields.value as {
108
+ type: string;
109
+ fields: {
110
+ contents: Array<{ type: string; fields: { name: string } }>;
111
+ };
112
+ };
113
+
114
+ value.fields.contents.forEach((content) => {
115
+ assetPrimaryOracles[assetName].push(
116
+ ruleTypeNameToOracleType[`0x${content.fields.name}`]
117
+ );
118
+ });
119
+ });
120
+ if (!hasNextPage) break;
121
+ } while (cursor);
122
+
123
+ return assetPrimaryOracles;
124
+ };
@@ -65,6 +65,7 @@ export interface AddressesInterface {
65
65
  SupportPackageType,
66
66
  {
67
67
  id: string;
68
+ object?: string;
68
69
  upgradeCap: string;
69
70
  }
70
71
  >
@@ -1,2 +1,3 @@
1
1
  export type * from './common';
2
2
  export type * from './enum';
3
+ export type * from './xOracle';
@@ -0,0 +1,11 @@
1
+ import { SupportAssetCoins, SupportOracleType } from './common';
2
+
3
+ export type xOracleRules = {
4
+ primary: SupportOracleType[];
5
+ secondary: SupportOracleType[];
6
+ };
7
+ export type xOracleRuleType = keyof xOracleRules;
8
+
9
+ export type xOracleListType = {
10
+ [key in SupportAssetCoins]: xOracleRules;
11
+ };
package/src/utils/util.ts CHANGED
@@ -55,13 +55,10 @@ export const parseAssetSymbol = (coinName: SupportCoins): string => {
55
55
  return `w${coinName.slice(1).toUpperCase()}`;
56
56
  }
57
57
  if (isSuiBridgeAsset(coinName)) {
58
- switch (coinName) {
59
- case 'sbwbtc':
60
- return 'sbwBTC';
61
- default: {
62
- return `sb${coinName.slice(2).toUpperCase()}`;
63
- }
58
+ if (coinName.startsWith('sbw') && coinName.length > 3) {
59
+ return `sbw${coinName.slice(3).toUpperCase()}`;
64
60
  }
61
+ return `sb${coinName.slice(2).toUpperCase()}`;
65
62
  }
66
63
  if (isMarketCoin(coinName)) {
67
64
  const assetCoinName = coinName.slice(1).toLowerCase() as SupportAssetCoins;
@@ -74,8 +71,6 @@ export const parseAssetSymbol = (coinName: SupportCoins): string => {
74
71
  return 'haSUI';
75
72
  case 'vsui':
76
73
  return 'vSUI';
77
- case 'musd':
78
- return 'mUSD';
79
74
  default:
80
75
  return coinName.toUpperCase();
81
76
  }
@@ -107,7 +102,7 @@ export const parseDataFromPythPriceFeed = (
107
102
  publishTime: Number(feed.price.publishTime) * 10 ** 3,
108
103
  };
109
104
  } else {
110
- throw new Error('Invalid feed id');
105
+ throw new Error(`Invalid feed id: ${feed.id}`);
111
106
  }
112
107
  };
113
108