@scallop-io/sui-scallop-sdk 2.2.3-pyth-sponsored-transaction-alpha.2 → 2.2.3-pyth-sponsored-transaction-alpha.3

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scallop-io/sui-scallop-sdk",
3
- "version": "2.2.3-pyth-sponsored-transaction-alpha.2",
3
+ "version": "2.2.3-pyth-sponsored-transaction-alpha.3",
4
4
  "description": "Typescript sdk for interacting with Scallop contract on SUI",
5
5
  "keywords": [
6
6
  "sui",
@@ -39,7 +39,7 @@
39
39
  ],
40
40
  "dependencies": {
41
41
  "@mysten/sui": "1.28.2",
42
- "@pythnetwork/pyth-sui-js": "2.1.0",
42
+ "@pythnetwork/pyth-sui-js": "2.2.0",
43
43
  "@scallop-io/sui-kit": "1.4.1",
44
44
  "@tanstack/query-core": "5.59.16",
45
45
  "axios": "^1.9.0",
@@ -146,6 +146,7 @@
146
146
  "scripts": {
147
147
  "clean": "rm -rf tsconfig.tsbuildinfo ./dist",
148
148
  "build": "pnpm run build:tsup",
149
+ "build:sourcemap": "tsup ./src/index.ts --format esm,cjs --sourcemap --dts",
149
150
  "build:tsup": "tsup ./src/index.ts --format esm,cjs --splitting --minify --treeshake --dts",
150
151
  "watch:tsup": "tsup ./src/index.ts --format esm,cjs --clean --splitting --watch",
151
152
  "watch:types": "tsc --watch",
@@ -313,7 +313,8 @@ const generateCoreQuickMethod: GenerateCoreQuickMethod = ({
313
313
  amount,
314
314
  collateralCoinName,
315
315
  obligationId,
316
- obligationKey
316
+ obligationKey,
317
+ isSponsoredTx = false
317
318
  ) => {
318
319
  const obligationInfo = await requireObligationInfo(
319
320
  builder,
@@ -324,7 +325,7 @@ const generateCoreQuickMethod: GenerateCoreQuickMethod = ({
324
325
  const updateCoinNames = await builder.utils.getObligationCoinNames(
325
326
  obligationInfo.obligationId
326
327
  );
327
- await updateOracles(builder, txBlock, updateCoinNames);
328
+ await updateOracles(builder, txBlock, updateCoinNames, { isSponsoredTx });
328
329
  return txBlock.takeCollateral(
329
330
  obligationInfo.obligationId,
330
331
  obligationInfo.obligationKey as SuiObjectArg,
@@ -1,9 +1,82 @@
1
1
  import {
2
+ HexString,
2
3
  SuiPriceServiceConnection,
3
4
  SuiPythClient,
4
5
  } from '@pythnetwork/pyth-sui-js';
5
6
  import { ScallopBuilder } from 'src/models';
6
- import type { SuiTxBlock as SuiKitTxBlock } from '@scallop-io/sui-kit';
7
+ import {
8
+ SUI_CLOCK_OBJECT_ID,
9
+ type SuiTxBlock as SuiKitTxBlock,
10
+ type Transaction,
11
+ } from '@scallop-io/sui-kit';
12
+ import { SuiClient } from '@mysten/sui/client';
13
+
14
+ type ObjectId = string;
15
+ class ScallopPythClient extends SuiPythClient {
16
+ constructor(
17
+ provider: SuiClient,
18
+ pythStateId: ObjectId,
19
+ wormholeStateId: ObjectId,
20
+ private params: {
21
+ // addressId?: string;
22
+ defaultPackageId: ObjectId;
23
+ gasStationId: ObjectId;
24
+ }
25
+ ) {
26
+ super(provider, pythStateId, wormholeStateId);
27
+ }
28
+
29
+ async updatePriceFeedsWithSponsoredBaseUpdateFee(
30
+ tx: Transaction,
31
+ updates: Buffer[],
32
+ feedIds: HexString[]
33
+ ) {
34
+ if (!this.params) throw new Error('Please provide params');
35
+ const { defaultPackageId: scallopSponsorPackage, gasStationId } =
36
+ this.params;
37
+ const packageId = await this.getPythPackageId();
38
+ let priceUpdatesHotPotato = await this.verifyVaasAndGetHotPotato(
39
+ tx,
40
+ updates,
41
+ packageId
42
+ );
43
+
44
+ const priceInfoObjects = [];
45
+ for (const feedId of feedIds) {
46
+ const priceInfoObjectId = await this.getPriceFeedObjectId(feedId);
47
+ if (!priceInfoObjectId) {
48
+ throw new Error(`Price feed object not found for ID: ${feedId}`);
49
+ }
50
+ priceInfoObjects.push(priceInfoObjectId);
51
+ }
52
+
53
+ const clockObjectRef = tx.sharedObjectRef({
54
+ objectId: SUI_CLOCK_OBJECT_ID,
55
+ mutable: false,
56
+ initialSharedVersion: '1',
57
+ });
58
+
59
+ for (let i = 0; i < priceInfoObjects.length; i++) {
60
+ const priceInfoObjectId = priceInfoObjects[i];
61
+ [priceUpdatesHotPotato] = tx.moveCall({
62
+ target: `${scallopSponsorPackage}::pyth_sponsor::update_single_price_feed_with_sponsor`,
63
+ arguments: [
64
+ tx.object(this.pythStateId),
65
+ priceUpdatesHotPotato,
66
+ tx.object(priceInfoObjectId),
67
+ tx.object(gasStationId),
68
+ clockObjectRef,
69
+ ],
70
+ });
71
+ }
72
+
73
+ tx.moveCall({
74
+ target: `${packageId}::hot_potato_vector::destroy`,
75
+ arguments: [priceUpdatesHotPotato],
76
+ typeArguments: [`${packageId}::price_info::PriceInfo`],
77
+ });
78
+ }
79
+ }
7
80
 
8
81
  export const updatePythPriceFeeds = async (
9
82
  builder: ScallopBuilder,
@@ -11,7 +84,7 @@ export const updatePythPriceFeeds = async (
11
84
  txBlock: SuiKitTxBlock,
12
85
  isSponsoredTx: boolean = false
13
86
  ) => {
14
- const pythClient = new SuiPythClient(
87
+ const pythClient = new ScallopPythClient(
15
88
  builder.suiKit.client,
16
89
  builder.address.get('core.oracles.pyth.state'),
17
90
  builder.address.get('core.oracles.pyth.wormholeState'),
@@ -30,19 +103,30 @@ export const updatePythPriceFeeds = async (
30
103
  const endpoints = builder.utils.pythEndpoints ?? [
31
104
  ...builder.constants.whitelist.pythEndpoints,
32
105
  ];
106
+
107
+ // get feed object ids
33
108
  for (const endpoint of endpoints) {
34
109
  try {
35
110
  const pythConnection = new SuiPriceServiceConnection(endpoint);
36
111
  const priceUpdateData =
37
112
  await pythConnection.getPriceFeedsUpdateData(priceIds);
38
- await pythClient.updatePriceFeeds(
39
- txBlock.txBlock,
40
- priceUpdateData,
41
- priceIds,
42
- isSponsoredTx
43
- );
44
113
 
45
- break;
114
+ if (isSponsoredTx) {
115
+ // Use gas station to sponsor the baseFeeUpdate
116
+ await pythClient.updatePriceFeedsWithSponsoredBaseUpdateFee(
117
+ txBlock.txBlock,
118
+ priceUpdateData,
119
+ priceIds
120
+ );
121
+ } else {
122
+ await pythClient.updatePriceFeeds(
123
+ txBlock.txBlock,
124
+ priceUpdateData,
125
+ priceIds
126
+ );
127
+ }
128
+
129
+ return;
46
130
  } catch (e) {
47
131
  console.warn(
48
132
  `Failed to update price feeds with endpoint ${endpoint}: ${e}`
@@ -534,10 +534,7 @@ export const WHITELIST = {
534
534
  suiBridge: new Set(['sbeth', 'sbusdt', 'sbwbtc']),
535
535
  wormhole: new Set(['wusdc', 'wusdt', 'weth', 'wbtc', 'wapt', 'wsol']),
536
536
  oracles: new Set(['pyth', 'supra', 'switchboard']),
537
- pythEndpoints: new Set([
538
- 'https://hermes.pyth.network',
539
- 'https://scallop.rpc.p2p.world',
540
- ]),
537
+ pythEndpoints: new Set(['https://hermes.pyth.network']),
541
538
  deprecated: new Set(['wapt', 'wusdc', 'wusdt', 'weth', 'wbtc']),
542
539
  borrowIncentiveRewards: new Set(['mpoints']),
543
540
  rewardsAsPoint: new Set(['mpoints']),
@@ -31,6 +31,7 @@ class ScallopUtils implements ScallopUtilsInterface {
31
31
  public pythEndpoints: string[];
32
32
  public readonly scallopSuiKit: ScallopSuiKit;
33
33
  public readonly constants: ScallopConstants;
34
+ public readonly timeout: number;
34
35
 
35
36
  constructor(params: ScallopUtilsParams = {}) {
36
37
  this.constants = params.scallopConstants ?? new ScallopConstants(params);
@@ -43,8 +44,9 @@ class ScallopUtils implements ScallopUtilsInterface {
43
44
 
44
45
  this.pythEndpoints = params.pythEndpoints ?? [
45
46
  'https://hermes.pyth.network',
46
- 'https://scallop.rpc.p2p.world',
47
47
  ];
48
+
49
+ this.timeout = params.axiosTimeout ?? 4000;
48
50
  }
49
51
 
50
52
  get walletAddress() {
@@ -539,7 +541,7 @@ class ScallopUtils implements ScallopUtilsInterface {
539
541
 
540
542
  const priceIds = priceIdPairs.map(([_, priceId]) => priceId);
541
543
  const pythConnection = new SuiPriceServiceConnection(endpoint, {
542
- timeout: 4000,
544
+ timeout: this.timeout,
543
545
  });
544
546
 
545
547
  try {
@@ -93,7 +93,8 @@ export type CoreQuickMethods = {
93
93
  amount: number,
94
94
  collateralCoinName: string,
95
95
  obligationId?: SuiObjectArg,
96
- obligationKey?: SuiObjectArg
96
+ obligationKey?: SuiObjectArg,
97
+ isSponsoredTx?: boolean
97
98
  ) => Promise<TransactionResult>;
98
99
  borrowQuick: (
99
100
  amount: number,