@scallop-io/sui-scallop-sdk 0.44.16 → 0.44.18

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.
@@ -30,8 +30,9 @@ export declare class ScallopBuilder {
30
30
  * Request the scallop API to initialize data.
31
31
  *
32
32
  * @param force - Whether to force initialization.
33
+ * @param address - ScallopAddress instance.
33
34
  */
34
- init(force?: boolean): Promise<void>;
35
+ init(force?: boolean, address?: ScallopAddress): Promise<void>;
35
36
  /**
36
37
  * Create a scallop txBlock instance that enhances transaction block.
37
38
  *
@@ -31,9 +31,9 @@ export declare class ScallopClient {
31
31
  /**
32
32
  * Request the scallop API to initialize data.
33
33
  *
34
- * @param forece - Whether to force initialization.
34
+ * @param force - Whether to force initialization.
35
35
  */
36
- init(forece?: boolean): Promise<void>;
36
+ init(force?: boolean): Promise<void>;
37
37
  /**
38
38
  * Query market data.
39
39
  *
@@ -25,9 +25,10 @@ export declare class ScallopQuery {
25
25
  /**
26
26
  * Request the scallop API to initialize data.
27
27
  *
28
- * @param forece - Whether to force initialization.
28
+ * @param force - Whether to force initialization.
29
+ * @param address - ScallopAddress instance.
29
30
  */
30
- init(forece?: boolean): Promise<void>;
31
+ init(force?: boolean, address?: ScallopAddress): Promise<void>;
31
32
  /**
32
33
  * Query market data.
33
34
  * @param indexer - Whether to use indexer.
@@ -148,17 +149,17 @@ export declare class ScallopQuery {
148
149
  * @return All market market coin amounts.
149
150
  */
150
151
  getMarketCoinAmounts(marketCoinNames?: SupportMarketCoins[], ownerAddress?: string): Promise<{
152
+ seth?: number | undefined;
151
153
  ssui?: number | undefined;
152
154
  susdc?: number | undefined;
153
155
  susdt?: number | undefined;
156
+ scetus?: number | undefined;
154
157
  safsui?: number | undefined;
155
158
  shasui?: number | undefined;
156
159
  svsui?: number | undefined;
157
- seth?: number | undefined;
158
160
  sbtc?: number | undefined;
159
161
  sapt?: number | undefined;
160
162
  ssol?: number | undefined;
161
- scetus?: number | undefined;
162
163
  }>;
163
164
  /**
164
165
  * Get market coin amount.
@@ -183,9 +184,11 @@ export declare class ScallopQuery {
183
184
  * @return Spools data.
184
185
  */
185
186
  getSpools(stakeMarketCoinNames?: SupportStakeMarketCoins[], indexer?: boolean): Promise<{
187
+ seth?: import("../types").Spool | undefined;
186
188
  ssui?: import("../types").Spool | undefined;
187
189
  susdc?: import("../types").Spool | undefined;
188
190
  susdt?: import("../types").Spool | undefined;
191
+ scetus?: import("../types").Spool | undefined;
189
192
  safsui?: import("../types").Spool | undefined;
190
193
  shasui?: import("../types").Spool | undefined;
191
194
  svsui?: import("../types").Spool | undefined;
@@ -224,9 +227,11 @@ export declare class ScallopQuery {
224
227
  * @return Stake pools data.
225
228
  */
226
229
  getStakePools(stakeMarketCoinNames?: SupportStakeMarketCoins[]): Promise<{
230
+ seth?: import("../types").StakePool | undefined;
227
231
  ssui?: import("../types").StakePool | undefined;
228
232
  susdc?: import("../types").StakePool | undefined;
229
233
  susdt?: import("../types").StakePool | undefined;
234
+ scetus?: import("../types").StakePool | undefined;
230
235
  safsui?: import("../types").StakePool | undefined;
231
236
  shasui?: import("../types").StakePool | undefined;
232
237
  svsui?: import("../types").StakePool | undefined;
@@ -253,9 +258,11 @@ export declare class ScallopQuery {
253
258
  * @return Stake reward pools data.
254
259
  */
255
260
  getStakeRewardPools(stakeMarketCoinNames?: SupportStakeMarketCoins[]): Promise<{
261
+ seth?: import("../types").StakeRewardPool | undefined;
256
262
  ssui?: import("../types").StakeRewardPool | undefined;
257
263
  susdc?: import("../types").StakeRewardPool | undefined;
258
264
  susdt?: import("../types").StakeRewardPool | undefined;
265
+ scetus?: import("../types").StakeRewardPool | undefined;
259
266
  safsui?: import("../types").StakeRewardPool | undefined;
260
267
  shasui?: import("../types").StakeRewardPool | undefined;
261
268
  svsui?: import("../types").StakeRewardPool | undefined;
@@ -1,4 +1,5 @@
1
1
  import { SuiAddressArg } from '@scallop-io/sui-kit';
2
+ import { ScallopAddress } from './scallopAddress';
2
3
  import type { ScallopUtilsParams, ScallopInstanceParams, SupportCoins, SupportAssetCoins, SupportMarketCoins, SupportStakeMarketCoins, SupportBorrowIncentiveCoins, CoinWrappedType } from '../types';
3
4
  /**
4
5
  * @description
@@ -23,9 +24,10 @@ export declare class ScallopUtils {
23
24
  /**
24
25
  * Request the scallop API to initialize data.
25
26
  *
26
- * @param forece - Whether to force initialization.
27
+ * @param force - Whether to force initialization.
28
+ * @param address - ScallopAddress instance.
27
29
  */
28
- init(forece?: boolean): Promise<void>;
30
+ init(force?: boolean, address?: ScallopAddress): Promise<void>;
29
31
  /**
30
32
  * Convert coin name to symbol.
31
33
  *
@@ -151,17 +151,17 @@ export declare const getCoinAmount: (query: ScallopQuery, assetCoinName: Support
151
151
  * @return All owned market coins amount.
152
152
  */
153
153
  export declare const getMarketCoinAmounts: (query: ScallopQuery, marketCoinNames?: SupportMarketCoins[], ownerAddress?: string) => Promise<{
154
+ seth?: number | undefined;
154
155
  ssui?: number | undefined;
155
156
  susdc?: number | undefined;
156
157
  susdt?: number | undefined;
158
+ scetus?: number | undefined;
157
159
  safsui?: number | undefined;
158
160
  shasui?: number | undefined;
159
161
  svsui?: number | undefined;
160
- seth?: number | undefined;
161
162
  sbtc?: number | undefined;
162
163
  sapt?: number | undefined;
163
164
  ssol?: number | undefined;
164
- scetus?: number | undefined;
165
165
  }>;
166
166
  /**
167
167
  * Query owned market coin (sCoin) amount.
@@ -9,9 +9,11 @@ import type { MarketPool, Spool, StakePool, StakeRewardPool, StakeAccounts, Supp
9
9
  * @return Spools data.
10
10
  */
11
11
  export declare const getSpools: (query: ScallopQuery, stakeMarketCoinNames?: SupportStakeMarketCoins[], indexer?: boolean) => Promise<{
12
+ seth?: Spool | undefined;
12
13
  ssui?: Spool | undefined;
13
14
  susdc?: Spool | undefined;
14
15
  susdt?: Spool | undefined;
16
+ scetus?: Spool | undefined;
15
17
  safsui?: Spool | undefined;
16
18
  shasui?: Spool | undefined;
17
19
  svsui?: Spool | undefined;
@@ -23,6 +23,9 @@ export type ScallopClientParams = ScallopParams & {
23
23
  };
24
24
  export type ScallopBuilderParams = ScallopParams & {
25
25
  walletAddress?: string;
26
+ pythEndpoints?: string[];
26
27
  };
27
28
  export type ScallopQueryParams = ScallopParams;
28
- export type ScallopUtilsParams = ScallopParams;
29
+ export type ScallopUtilsParams = ScallopParams & {
30
+ pythEndpoints?: string[];
31
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scallop-io/sui-scallop-sdk",
3
- "version": "0.44.16",
3
+ "version": "0.44.18",
4
4
  "description": "Typescript sdk for interacting with Scallop contract on SUI",
5
5
  "keywords": [
6
6
  "sui",
@@ -8,6 +8,7 @@ import type { TransactionArgument } from '@mysten/sui.js/transactions';
8
8
  import type { SuiTxBlock as SuiKitTxBlock } from '@scallop-io/sui-kit';
9
9
  import type { ScallopBuilder } from '../models';
10
10
  import type { SupportAssetCoins, SupportOracleType } from '../types';
11
+ import { PYTH_ENDPOINTS } from 'src/constants/pyth';
11
12
 
12
13
  /**
13
14
  * Update the price of the oracle for multiple coin.
@@ -34,18 +35,29 @@ export const updateOracles = async (
34
35
  const priceIds = assetCoinNames.map((assetCoinName) =>
35
36
  builder.address.get(`core.coins.${assetCoinName}.oracle.pyth.feed`)
36
37
  );
37
- const pythConnection = new SuiPriceServiceConnection(
38
- builder.isTestnet
39
- ? 'https://hermes-beta.pyth.network'
40
- : 'https://hermes.pyth.network'
41
- );
42
- const priceUpdateData =
43
- await pythConnection.getPriceFeedsUpdateData(priceIds);
44
- await pythClient.updatePriceFeeds(
45
- txBlock.txBlock,
46
- priceUpdateData,
47
- priceIds
48
- );
38
+
39
+ // iterate through the endpoints
40
+ const endpoints =
41
+ builder.params.pythEndpoints ??
42
+ PYTH_ENDPOINTS[builder.isTestnet ? 'testnet' : 'mainnet'];
43
+ for (const endpoint of endpoints) {
44
+ try {
45
+ const pythConnection = new SuiPriceServiceConnection(endpoint);
46
+ const priceUpdateData =
47
+ await pythConnection.getPriceFeedsUpdateData(priceIds);
48
+ await pythClient.updatePriceFeeds(
49
+ txBlock.txBlock,
50
+ priceUpdateData,
51
+ priceIds
52
+ );
53
+
54
+ break;
55
+ } catch (e) {
56
+ console.warn(
57
+ `Failed to update price feeds with endpoint ${endpoint}: ${e}`
58
+ );
59
+ }
60
+ }
49
61
  }
50
62
 
51
63
  // Remove duplicate coin names.
@@ -38,9 +38,11 @@ export const SUPPORT_COLLATERALS = [
38
38
  ] as const;
39
39
 
40
40
  export const SUPPORT_SPOOLS = [
41
+ 'seth',
41
42
  'ssui',
42
43
  'susdc',
43
44
  'susdt',
45
+ 'scetus',
44
46
  'safsui',
45
47
  'shasui',
46
48
  'svsui',
@@ -64,18 +64,22 @@ export const marketCoins: MarketCoins = {
64
64
  };
65
65
 
66
66
  export const stakeMarketCoins: StakeMarketCoins = {
67
+ seth: 'seth',
67
68
  ssui: 'ssui',
68
69
  susdc: 'susdc',
69
70
  susdt: 'susdt',
71
+ scetus: 'scetus',
70
72
  safsui: 'safsui',
71
73
  shasui: 'shasui',
72
74
  svsui: 'svsui',
73
75
  };
74
76
 
75
77
  export const spoolRewardCoins: StakeRewardCoins = {
78
+ seth: 'sui',
76
79
  ssui: 'sui',
77
80
  susdc: 'sui',
78
81
  susdt: 'sui',
82
+ scetus: 'sui',
79
83
  safsui: 'sui',
80
84
  shasui: 'sui',
81
85
  svsui: 'sui',
@@ -0,0 +1,6 @@
1
+ export const PYTH_ENDPOINTS: {
2
+ [k in 'mainnet' | 'testnet']: Readonly<string[]>;
3
+ } = {
4
+ testnet: ['https://hermes-beta.pyth.network'],
5
+ mainnet: ['https://hermes.pyth.network', 'https://scallop.rpc.p2p.world'],
6
+ } as const;
@@ -191,6 +191,10 @@ const EMPTY_ADDRESSES: AddressesInterface = {
191
191
  adminCap: '',
192
192
  object: '',
193
193
  pools: {
194
+ seth: {
195
+ id: '',
196
+ rewardPoolId: '',
197
+ },
194
198
  ssui: {
195
199
  id: '',
196
200
  rewardPoolId: '',
@@ -203,6 +207,10 @@ const EMPTY_ADDRESSES: AddressesInterface = {
203
207
  id: '',
204
208
  rewardPoolId: '',
205
209
  },
210
+ scetus: {
211
+ id: '',
212
+ rewardPoolId: '',
213
+ },
206
214
  safsui: {
207
215
  id: '',
208
216
  rewardPoolId: '',
@@ -74,13 +74,16 @@ export class ScallopBuilder {
74
74
  * Request the scallop API to initialize data.
75
75
  *
76
76
  * @param force - Whether to force initialization.
77
+ * @param address - ScallopAddress instance.
77
78
  */
78
- public async init(force: boolean = false) {
79
- if (force || !this.address.getAddresses()) {
79
+ public async init(force: boolean = false, address?: ScallopAddress) {
80
+ if (force || !this.address.getAddresses() || !address?.getAddresses()) {
80
81
  await this.address.read();
82
+ } else {
83
+ this.address = address;
81
84
  }
82
- await this.query.init(force);
83
- await this.utils.init(force);
85
+ await this.query.init(force, this.address);
86
+ await this.utils.init(force, this.address);
84
87
  }
85
88
 
86
89
  /**
@@ -84,15 +84,16 @@ export class ScallopClient {
84
84
  /**
85
85
  * Request the scallop API to initialize data.
86
86
  *
87
- * @param forece - Whether to force initialization.
87
+ * @param force - Whether to force initialization.
88
88
  */
89
- public async init(forece: boolean = false) {
90
- if (forece || !this.address.getAddresses()) {
89
+ public async init(force: boolean = false) {
90
+ if (force || !this.address.getAddresses()) {
91
91
  await this.address.read();
92
92
  }
93
- await this.query.init(forece);
94
- await this.utils.init(forece);
95
- await this.builder.init(forece);
93
+
94
+ await this.builder.init(force, this.address);
95
+ await this.query.init(force, this.address);
96
+ await this.utils.init(force, this.address);
96
97
  }
97
98
 
98
99
  /* ==================== Query Method ==================== */
@@ -87,13 +87,17 @@ export class ScallopQuery {
87
87
  /**
88
88
  * Request the scallop API to initialize data.
89
89
  *
90
- * @param forece - Whether to force initialization.
90
+ * @param force - Whether to force initialization.
91
+ * @param address - ScallopAddress instance.
91
92
  */
92
- public async init(forece: boolean = false) {
93
- if (forece || !this.address.getAddresses()) {
93
+ public async init(force: boolean = false, address?: ScallopAddress) {
94
+ if (force || !this.address.getAddresses() || !address?.getAddresses()) {
94
95
  await this.address.read();
96
+ } else {
97
+ this.address = address;
95
98
  }
96
- await this.utils.init(forece);
99
+
100
+ await this.utils.init(force, this.address);
97
101
  }
98
102
 
99
103
  /* ==================== Core Query Methods ==================== */
@@ -33,6 +33,7 @@ import type {
33
33
  PriceMap,
34
34
  CoinWrappedType,
35
35
  } from '../types';
36
+ import { PYTH_ENDPOINTS } from 'src/constants/pyth';
36
37
 
37
38
  /**
38
39
  * @description
@@ -81,13 +82,19 @@ export class ScallopUtils {
81
82
  /**
82
83
  * Request the scallop API to initialize data.
83
84
  *
84
- * @param forece - Whether to force initialization.
85
+ * @param force - Whether to force initialization.
86
+ * @param address - ScallopAddress instance.
85
87
  */
86
- public async init(forece: boolean = false) {
87
- if (forece || !this._address.getAddresses()) {
88
+ public async init(force: boolean = false, address?: ScallopAddress) {
89
+ if (force || !this._address.getAddresses() || !address?.getAddresses()) {
88
90
  await this._address.read();
91
+ } else {
92
+ this._address = address;
93
+ }
94
+
95
+ if (!this._query.address.getAddresses()) {
96
+ await this._query.init(force, this._address);
89
97
  }
90
- await this._query.init(forece);
91
98
  }
92
99
 
93
100
  /**
@@ -391,25 +398,36 @@ export class ScallopUtils {
391
398
  }
392
399
 
393
400
  if (lackPricesCoinNames.length > 0) {
394
- const pythConnection = new SuiPriceServiceConnection(
395
- this.isTestnet
396
- ? 'https://hermes-beta.pyth.network'
397
- : 'https://hermes.pyth.network'
398
- );
399
- const priceIds = lackPricesCoinNames.map((coinName) =>
400
- this._address.get(`core.coins.${coinName}.oracle.pyth.feed`)
401
- );
401
+ const endpoints =
402
+ this.params.pythEndpoints ??
403
+ PYTH_ENDPOINTS[this.isTestnet ? 'testnet' : 'mainnet'];
402
404
  try {
403
- const priceFeeds =
404
- (await pythConnection.getLatestPriceFeeds(priceIds)) || [];
405
- for (const [index, feed] of priceFeeds.entries()) {
406
- const data = parseDataFromPythPriceFeed(feed, this._address);
407
- const coinName = lackPricesCoinNames[index];
408
- this._priceMap.set(coinName, {
409
- price: data.price,
410
- publishTime: data.publishTime,
411
- });
412
- coinPrices[coinName] = data.price;
405
+ for (const endpoint of endpoints) {
406
+ try {
407
+ const pythConnection = new SuiPriceServiceConnection(endpoint);
408
+ const priceIds = lackPricesCoinNames.map((coinName) =>
409
+ this._address.get(`core.coins.${coinName}.oracle.pyth.feed`)
410
+ );
411
+ const priceFeeds =
412
+ (await pythConnection.getLatestPriceFeeds(priceIds)) || [];
413
+ for (const [index, feed] of priceFeeds.entries()) {
414
+ const data = parseDataFromPythPriceFeed(feed, this._address);
415
+ const coinName = lackPricesCoinNames[index];
416
+ this._priceMap.set(coinName, {
417
+ price: data.price,
418
+ publishTime: data.publishTime,
419
+ });
420
+ coinPrices[coinName] = data.price;
421
+ }
422
+
423
+ break;
424
+ } catch (e) {
425
+ console.warn(
426
+ `Failed to update price feeds with endpoint ${endpoint}: ${e}`
427
+ );
428
+ }
429
+
430
+ throw new Error('Failed to update price feeds with all endpoins');
413
431
  }
414
432
  } catch (_e) {
415
433
  for (const coinName of lackPricesCoinNames) {
@@ -269,9 +269,11 @@ export const getStakeAccounts = async (
269
269
  } while (hasNextPage);
270
270
 
271
271
  const stakeAccounts: StakeAccounts = {
272
+ seth: [],
272
273
  ssui: [],
273
274
  susdc: [],
274
275
  susdt: [],
276
+ scetus: [],
275
277
  safsui: [],
276
278
  shasui: [],
277
279
  svsui: [],
@@ -307,7 +309,18 @@ export const getStakeAccounts = async (
307
309
  const index = Number(fields.index);
308
310
  const points = Number(fields.points);
309
311
  const totalPoints = Number(fields.total_points);
310
- if (normalizeStructTag(type) === stakeMarketCoinTypes.ssui) {
312
+ if (normalizeStructTag(type) === stakeMarketCoinTypes.seth) {
313
+ stakeAccounts.seth.push({
314
+ id,
315
+ type: normalizeStructTag(type),
316
+ stakePoolId,
317
+ stakeType: normalizeStructTag(stakeType),
318
+ staked,
319
+ index,
320
+ points,
321
+ totalPoints,
322
+ });
323
+ } else if (normalizeStructTag(type) === stakeMarketCoinTypes.ssui) {
311
324
  stakeAccounts.ssui.push({
312
325
  id,
313
326
  type: normalizeStructTag(type),
@@ -340,6 +353,17 @@ export const getStakeAccounts = async (
340
353
  points,
341
354
  totalPoints,
342
355
  });
356
+ } else if (normalizeStructTag(type) === stakeMarketCoinTypes.scetus) {
357
+ stakeAccounts.scetus.push({
358
+ id,
359
+ type: normalizeStructTag(type),
360
+ stakePoolId,
361
+ stakeType: normalizeStructTag(stakeType),
362
+ staked,
363
+ index,
364
+ points,
365
+ totalPoints,
366
+ });
343
367
  } else if (normalizeStructTag(type) === stakeMarketCoinTypes.safsui) {
344
368
  stakeAccounts.safsui.push({
345
369
  id,
@@ -36,8 +36,11 @@ export type ScallopClientParams = ScallopParams & {
36
36
 
37
37
  export type ScallopBuilderParams = ScallopParams & {
38
38
  walletAddress?: string;
39
+ pythEndpoints?: string[];
39
40
  };
40
41
 
41
42
  export type ScallopQueryParams = ScallopParams;
42
43
 
43
- export type ScallopUtilsParams = ScallopParams;
44
+ export type ScallopUtilsParams = ScallopParams & {
45
+ pythEndpoints?: string[];
46
+ };
@@ -359,12 +359,17 @@ export const calculateSpoolRewardPoolData = (
359
359
  .shiftedBy(-1 * rewardCoinDecimal)
360
360
  .multipliedBy(rateYearFactor)
361
361
  .multipliedBy(rewardCoinPrice);
362
- const rewardRate = rewardValueForYear
362
+
363
+ let rewardRate = rewardValueForYear
363
364
  .dividedBy(calculatedSpoolData.stakedValue)
364
365
  .isFinite()
365
366
  ? rewardValueForYear.dividedBy(calculatedSpoolData.stakedValue).toNumber()
366
367
  : Infinity;
367
368
 
369
+ if (parsedSpoolData.maxPoint === parsedSpoolData.distributedPoint) {
370
+ rewardRate = Infinity;
371
+ }
372
+
368
373
  return {
369
374
  rewardApr: rewardRate,
370
375
  totalRewardAmount: totalRewardAmount.toNumber(),