@pythnetwork/price-pusher 10.4.0 → 11.3.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.
package/dist/sui/sui.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /* eslint-disable @typescript-eslint/no-non-null-assertion */ /* eslint-disable @typescript-eslint/no-unsafe-argument */ /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-unsafe-return */ /* eslint-disable @typescript-eslint/restrict-template-expressions */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ "use strict";
1
+ /* biome-ignore-all lint/style/noNonNullAssertion: pre-existing; gas-pool code asserts on Sui RPC results */ /* biome-ignore-all lint/suspicious/noExplicitAny: pre-existing; untyped Sui RPC error/result shapes */ /* biome-ignore-all lint/complexity/noForEach: pre-existing */ /* biome-ignore-all lint/suspicious/useAwait: pre-existing */ "use strict";
2
2
  Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
@@ -14,25 +14,91 @@ _export(exports, {
14
14
  },
15
15
  get SuiPricePusher () {
16
16
  return SuiPricePusher;
17
+ },
18
+ get createSuiProvider () {
19
+ return createSuiProvider;
17
20
  }
18
21
  });
19
- const _client = require("@mysten/sui/client");
22
+ const _grpcjs = require("@grpc/grpc-js");
23
+ const _grpc = require("@mysten/sui/grpc");
24
+ const _jsonRpc = require("@mysten/sui/jsonRpc");
20
25
  const _transactions = require("@mysten/sui/transactions");
26
+ const _grpctransport = require("@protobuf-ts/grpc-transport");
21
27
  const _pythsuijs = require("@pythnetwork/pyth-sui-js");
22
28
  const _interface = require("../interface.cjs");
23
29
  const GAS_FEE_FOR_SPLIT = 2_000_000_000;
24
30
  // TODO: read this from on chain config
25
31
  const MAX_NUM_GAS_OBJECTS_IN_PTB = 256;
26
32
  const MAX_NUM_OBJECTS_IN_ARGUMENT = 510;
33
+ /**
34
+ * Turn a gRPC endpoint into a `@grpc/grpc-js` `host:port` plus channel
35
+ * credentials. Third-party Sui gRPC endpoints (QuikNode `:9000`, Ankr /
36
+ * BlockVision `:443`) serve **native gRPC over HTTP/2**, so the host must be
37
+ * a bare `host:port` with no scheme or path. A `http://` prefix selects an
38
+ * insecure channel (local devnet); anything else uses TLS.
39
+ */ function parseGrpcEndpoint(url) {
40
+ let host = url.trim();
41
+ let insecure = false;
42
+ if (host.startsWith("https://")) {
43
+ host = host.slice("https://".length);
44
+ } else if (host.startsWith("http://")) {
45
+ host = host.slice("http://".length);
46
+ insecure = true;
47
+ }
48
+ // Drop any path/token segment — native gRPC authenticates via metadata, not URL.
49
+ host = host.replace(/\/.*$/, "");
50
+ return {
51
+ credentials: insecure ? _grpcjs.ChannelCredentials.createInsecure() : _grpcjs.ChannelCredentials.createSsl(),
52
+ host
53
+ };
54
+ }
55
+ function createSuiProvider(endpointType, network, url, grpcMetadata) {
56
+ switch(endpointType){
57
+ case "grpc":
58
+ {
59
+ const { host, credentials } = parseGrpcEndpoint(url);
60
+ const transport = new _grpctransport.GrpcTransport({
61
+ channelCredentials: credentials,
62
+ host,
63
+ ...grpcMetadata && {
64
+ meta: grpcMetadata
65
+ }
66
+ });
67
+ return new _grpc.SuiGrpcClient({
68
+ network,
69
+ transport
70
+ });
71
+ }
72
+ case "json-rpc":
73
+ {
74
+ return new _jsonRpc.SuiJsonRpcClient({
75
+ network,
76
+ url
77
+ });
78
+ }
79
+ default:
80
+ {
81
+ throw new Error(`Unknown Sui endpoint type: ${endpointType}`);
82
+ }
83
+ }
84
+ }
85
+ /** Unwrap the executed transaction from the `.core` execution result union. */ function getExecutedTransaction(result) {
86
+ return result.$kind === "Transaction" ? result.Transaction : result.FailedTransaction;
87
+ }
88
+ /** Build an owned-object reference from a `.core` effects changed object. */ function changedObjectToRef(obj) {
89
+ return {
90
+ digest: obj.outputDigest,
91
+ objectId: obj.objectId,
92
+ version: obj.outputVersion
93
+ };
94
+ }
27
95
  class SuiPriceListener extends _interface.ChainPriceListener {
28
96
  pythClient;
29
97
  provider;
30
98
  logger;
31
- constructor(pythStateId, wormholeStateId, endpoint, priceItems, logger, config){
99
+ constructor(pythStateId, wormholeStateId, endpoint, endpointType, network, priceItems, logger, config, grpcMetadata){
32
100
  super(config.pollingFrequency, priceItems);
33
- this.provider = new _client.SuiClient({
34
- url: endpoint
35
- });
101
+ this.provider = createSuiProvider(endpointType, network, endpoint, grpcMetadata);
36
102
  this.pythClient = new _pythsuijs.SuiPythClient(this.provider, pythStateId, wormholeStateId);
37
103
  this.logger = logger;
38
104
  }
@@ -43,24 +109,23 @@ class SuiPriceListener extends _interface.ChainPriceListener {
43
109
  throw new Error("Price not found on chain for price id " + priceId);
44
110
  }
45
111
  // Fetching the price info object for the above priceInfoObjectId
46
- const priceInfoObject = await this.provider.getObject({
47
- id: priceInfoObjectId,
48
- options: {
49
- showContent: true
50
- }
112
+ const { object } = await this.provider.core.getObject({
113
+ include: {
114
+ json: true
115
+ },
116
+ objectId: priceInfoObjectId
51
117
  });
52
- if (!priceInfoObject.data?.content) throw new Error("Price not found on chain for price id " + priceId);
53
- if (priceInfoObject.data.content.dataType !== "moveObject") throw new Error("fetched object datatype should be moveObject");
54
- const priceInfo = // eslint-disable-next-line @typescript-eslint/ban-ts-comment
55
- // @ts-ignore
56
- priceInfoObject.data.content.fields.price_info.fields.price_feed.fields.price.fields;
57
- const { magnitude, negative } = priceInfo.price.fields;
58
- const conf = priceInfo.conf;
59
- const timestamp = priceInfo.timestamp;
118
+ if (!object.json) throw new Error("Price not found on chain for price id " + priceId);
119
+ // PriceInfoObject -> price_info -> price_feed -> price (the `Price` struct,
120
+ // holding the signed `price` magnitude, `conf`, and `timestamp`).
121
+ const priceFields = (0, _pythsuijs.getStructFields)((0, _pythsuijs.getStructFields)((0, _pythsuijs.getStructFields)(object.json.price_info).price_feed).price);
122
+ const magnitudeFields = (0, _pythsuijs.getStructFields)(priceFields.price);
123
+ const magnitude = magnitudeFields.magnitude;
124
+ const negative = magnitudeFields.negative;
60
125
  return {
61
- conf,
126
+ conf: priceFields.conf,
62
127
  price: negative ? `-${magnitude}` : magnitude,
63
- publishTime: Number(timestamp)
128
+ publishTime: Number(priceFields.timestamp)
64
129
  };
65
130
  } catch (error) {
66
131
  this.logger.error(error, `Polling Sui on-chain price for ${priceId} failed.`);
@@ -86,38 +151,13 @@ class SuiPricePusher {
86
151
  this.pythClient = pythClient;
87
152
  }
88
153
  /**
89
- * getPackageId returns the latest package id that the object belongs to. Use this to
90
- * fetch the latest package id for a given object id and handle package upgrades automatically.
91
- * @returns package id
92
- */ static async getPackageId(provider, objectId) {
93
- const state = await provider.getObject({
94
- id: objectId,
95
- options: {
96
- showContent: true
97
- }
98
- }).then((result)=>{
99
- if (result.data?.content?.dataType == "moveObject") {
100
- return result.data.content.fields;
101
- }
102
- throw new Error("not move object");
103
- });
104
- if ("upgrade_cap" in state) {
105
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
106
- // @ts-ignore
107
- return state.upgrade_cap.fields.package;
108
- }
109
- throw new Error("upgrade_cap not found");
110
- }
111
- /**
112
154
  * Create a price pusher with a pool of `numGasObjects` gas coins that will be used to send transactions.
113
155
  * The gas coins of the wallet for the provided keypair will be merged and then evenly split into `numGasObjects`.
114
- */ static async createWithAutomaticGasPool(hermesClient, logger, pythStateId, wormholeStateId, endpoint, keypair, gasBudget, numGasObjects, ignoreGasObjects) {
156
+ */ static async createWithAutomaticGasPool(hermesClient, logger, pythStateId, wormholeStateId, endpoint, endpointType, network, keypair, gasBudget, numGasObjects, ignoreGasObjects, grpcMetadata) {
115
157
  if (numGasObjects > MAX_NUM_OBJECTS_IN_ARGUMENT) {
116
158
  throw new Error(`numGasObjects cannot be greater than ${MAX_NUM_OBJECTS_IN_ARGUMENT} until we implement split chunking`);
117
159
  }
118
- const provider = new _client.SuiClient({
119
- url: endpoint
120
- });
160
+ const provider = createSuiProvider(endpointType, network, endpoint, grpcMetadata);
121
161
  const gasPool = await SuiPricePusher.initializeGasPool(keypair, provider, numGasObjects, ignoreGasObjects, logger);
122
162
  const pythClient = new _pythsuijs.SuiPythClient(provider, pythStateId, wormholeStateId);
123
163
  return new SuiPricePusher(keypair, provider, logger, hermesClient, gasBudget, gasPool, pythClient);
@@ -166,16 +206,27 @@ class SuiPricePusher {
166
206
  gasObject
167
207
  ]);
168
208
  tx.setGasBudget(this.gasBudget);
169
- const result = await this.provider.signAndExecuteTransaction({
170
- options: {
171
- showEffects: true
209
+ const result = await this.provider.core.signAndExecuteTransaction({
210
+ include: {
211
+ effects: true
172
212
  },
173
213
  signer: this.signer,
174
214
  transaction: tx
175
215
  });
176
- nextGasObject = result.effects?.mutated?.map((obj)=>obj.reference).find((ref)=>ref.objectId === gasObject.objectId);
216
+ const executed = getExecutedTransaction(result);
217
+ // The `.core` API returns a `FailedTransaction` for on-chain execution
218
+ // failures rather than throwing, so check the status explicitly — otherwise
219
+ // a failed push would emit the success log below and silently miss updates.
220
+ if (executed.effects.status.error) {
221
+ throw new Error(`Transaction ${executed.digest} failed on-chain: ${JSON.stringify(executed.effects.status.error)}`);
222
+ }
223
+ const gasObjectChange = executed.effects.gasObject;
224
+ nextGasObject = gasObjectChange && gasObjectChange.objectId === gasObject.objectId ? changedObjectToRef(gasObjectChange) : undefined;
225
+ // Keep at INFO: the bundled Grafana "Tx Hash" panel scrapes this message
226
+ // from Loki and extracts {{.hash}}; debug is not emitted under the default
227
+ // log level, which would hide successful Sui hashes from the dashboard.
177
228
  this.logger.info({
178
- hash: result.digest
229
+ hash: executed.digest
179
230
  }, "Successfully updated price with transaction digest");
180
231
  } catch (error) {
181
232
  if (String(error).includes("Balance of gas object") || String(error).includes("GasBalanceTooLow")) {
@@ -204,18 +255,14 @@ class SuiPricePusher {
204
255
  }, "Ignoring some gas objects for coin merging");
205
256
  }
206
257
  const consolidatedCoin = await SuiPricePusher.mergeGasCoinsIntoOne(signer, provider, signerAddress, ignoreGasObjects, logger);
207
- const coinResult = await provider.getObject({
208
- id: consolidatedCoin.objectId,
209
- options: {
210
- showContent: true
211
- }
258
+ const { object } = await provider.core.getObject({
259
+ include: {
260
+ json: true
261
+ },
262
+ objectId: consolidatedCoin.objectId
212
263
  });
213
- let balance;
214
- if (coinResult.data?.content && coinResult.data.content.dataType == "moveObject") {
215
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
216
- // @ts-ignore
217
- balance = coinResult.data.content.fields.balance;
218
- } else throw new Error("Bad coin object");
264
+ if (!object.json) throw new Error("Bad coin object");
265
+ const balance = object.json.balance;
219
266
  const splitAmount = (BigInt(balance) - BigInt(GAS_FEE_FOR_SPLIT)) / BigInt(numGasObjects);
220
267
  const gasPool = await SuiPricePusher.splitGasCoinEqually(signer, provider, signerAddress, Number(splitAmount), numGasObjects, consolidatedCoin);
221
268
  logger.info({
@@ -226,40 +273,36 @@ class SuiPricePusher {
226
273
  // Attempt to refresh the version of the provided object reference to point to the current version
227
274
  // of the object. Throws an error if the object cannot be refreshed.
228
275
  static async tryRefreshObjectReference(provider, ref) {
229
- const objectResponse = await provider.getObject({
230
- id: ref.objectId
276
+ const { object } = await provider.core.getObject({
277
+ objectId: ref.objectId
231
278
  });
232
- if (objectResponse.data === undefined) {
233
- throw new Error("Failed to refresh object reference");
234
- } else {
235
- return {
236
- digest: objectResponse.data.digest,
237
- objectId: objectResponse.data.objectId,
238
- version: objectResponse.data.version
239
- };
240
- }
279
+ return {
280
+ digest: object.digest,
281
+ objectId: object.objectId,
282
+ version: object.version
283
+ };
241
284
  }
242
285
  static async getAllGasCoins(provider, owner) {
243
286
  let hasNextPage = true;
244
- let cursor;
287
+ let cursor = null;
245
288
  const coins = new Set([]);
246
289
  let numCoins = 0;
247
290
  while(hasNextPage){
248
- const paginatedCoins = await provider.getCoins({
291
+ const paginatedCoins = await provider.core.listCoins({
249
292
  cursor,
250
293
  owner
251
294
  });
252
- numCoins += paginatedCoins.data.length;
253
- for (const c of paginatedCoins.data)coins.add(JSON.stringify({
295
+ numCoins += paginatedCoins.objects.length;
296
+ for (const c of paginatedCoins.objects)coins.add(JSON.stringify({
254
297
  digest: c.digest,
255
- objectId: c.coinObjectId,
298
+ objectId: c.objectId,
256
299
  version: c.version
257
300
  }));
258
301
  hasNextPage = paginatedCoins.hasNextPage;
259
- cursor = paginatedCoins.nextCursor;
302
+ cursor = paginatedCoins.cursor;
260
303
  }
261
304
  if (numCoins !== coins.size) {
262
- throw new Error("Unexpected getCoins result: duplicate coins found");
305
+ throw new Error("Unexpected listCoins result: duplicate coins found");
263
306
  }
264
307
  return [
265
308
  ...coins
@@ -277,18 +320,18 @@ class SuiPricePusher {
277
320
  tx.setGasPayment([
278
321
  gasCoin
279
322
  ]);
280
- const result = await provider.signAndExecuteTransaction({
281
- options: {
282
- showEffects: true
323
+ const result = await provider.core.signAndExecuteTransaction({
324
+ include: {
325
+ effects: true
283
326
  },
284
327
  signer,
285
328
  transaction: tx
286
329
  });
287
- const error = result.effects?.status.error;
288
- if (error) {
289
- throw new Error(`Failed to initialize gas pool: ${error}. Try re-running the script`);
330
+ const effects = getExecutedTransaction(result).effects;
331
+ if (effects.status.error) {
332
+ throw new Error(`Failed to initialize gas pool: ${JSON.stringify(effects.status.error)}. Try re-running the script`);
290
333
  }
291
- const newCoins = result.effects.created.map((obj)=>obj.reference);
334
+ const newCoins = effects.changedObjects.filter((obj)=>obj.idOperation === "Created").map(changedObjectToRef);
292
335
  if (newCoins.length !== numGasObjects) {
293
336
  throw new Error(`Failed to initialize gas pool. Expected ${numGasObjects}, got: ${JSON.stringify(newCoins)}`);
294
337
  }
@@ -317,9 +360,9 @@ class SuiPricePusher {
317
360
  mergeTx.setGasPayment(coins);
318
361
  let mergeResult;
319
362
  try {
320
- mergeResult = await provider.signAndExecuteTransaction({
321
- options: {
322
- showEffects: true
363
+ mergeResult = await provider.core.signAndExecuteTransaction({
364
+ include: {
365
+ effects: true
323
366
  },
324
367
  signer,
325
368
  transaction: mergeTx
@@ -340,11 +383,21 @@ class SuiPricePusher {
340
383
  }
341
384
  throw error_;
342
385
  }
343
- const error = mergeResult.effects?.status.error;
344
- if (error) {
345
- throw new Error(`Failed to merge coins when initializing gas pool: ${error}. Try re-running the script`);
386
+ const executed = getExecutedTransaction(mergeResult);
387
+ const effects = executed.effects;
388
+ if (effects.status.error) {
389
+ throw new Error(`Failed to merge coins when initializing gas pool: ${JSON.stringify(effects.status.error)}. Try re-running the script`);
346
390
  }
347
- finalCoin = mergeResult.effects.mutated.map((obj)=>obj.reference)[0];
391
+ finalCoin = changedObjectToRef(effects.gasObject);
392
+ // Block until this merge is observable before the next transaction spends
393
+ // its output (the next chunk's gas, or the subsequent split). gRPC
394
+ // endpoints are load-balanced across fullnodes at different checkpoints,
395
+ // so without this the follow-up tx can be simulated against a backend
396
+ // that has not yet applied this merge and fail with a version conflict.
397
+ // The legacy JSON-RPC path got this for free via WaitForLocalExecution.
398
+ await provider.core.waitForTransaction({
399
+ digest: executed.digest
400
+ });
348
401
  }
349
402
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
350
403
  return finalCoin;
package/dist/sui/sui.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import type { SuiObjectRef } from "@mysten/sui/client";
2
- import { SuiClient } from "@mysten/sui/client";
1
+ import type { ClientWithCoreApi } from "@mysten/sui/client";
2
+ import type { SuiObjectRef } from "@mysten/sui/jsonRpc";
3
3
  import type { Ed25519Keypair } from "@mysten/sui/keypairs/ed25519";
4
4
  import type { HermesClient } from "@pythnetwork/hermes-client";
5
5
  import { SuiPythClient } from "@pythnetwork/pyth-sui-js";
@@ -8,13 +8,36 @@ import type { IPricePusher, PriceInfo, PriceItem } from "../interface.js";
8
8
  import { ChainPriceListener } from "../interface.js";
9
9
  import type { DurationInSeconds } from "../utils.js";
10
10
  type ObjectId = string;
11
+ /**
12
+ * Sui transport selector. `json-rpc` is the legacy default; `grpc` migrates to
13
+ * the transport Sui Foundation is replacing JSON-RPC with (public JSON-RPC
14
+ * endpoints are turned off in July 2026, removed entirely by mid-Oct 2026).
15
+ */
16
+ export type SuiEndpointType = "json-rpc" | "grpc";
17
+ /** Sui network label passed to the `@mysten/sui` v2 clients. */
18
+ export type SuiNetwork = "mainnet" | "testnet" | "devnet" | "localnet";
19
+ /** gRPC request metadata (e.g. `{ "x-token": "<secret>" }`) sent on every call. */
20
+ export type SuiGrpcMetadata = Record<string, string>;
21
+ /**
22
+ * Both the `@mysten/sui` v2 JSON-RPC client (`SuiJsonRpcClient`) and the
23
+ * experimental gRPC client (`SuiGrpcClient`) expose the unified `.core` API.
24
+ * The pusher reads and writes exclusively through `.core` so the same driver
25
+ * works over either transport.
26
+ *
27
+ * `SuiGrpcClient` defaults to a grpc-web (HTTP/1.1) transport, which the Sui
28
+ * providers' native-gRPC (HTTP/2) endpoints reject; it also drops the `meta`
29
+ * option on that default path, so credentials never reach the wire. We
30
+ * therefore build an explicit `@protobuf-ts/grpc-transport` (native gRPC over
31
+ * `@grpc/grpc-js`) and pass the auth header through its `meta`.
32
+ */
33
+ export declare function createSuiProvider(endpointType: SuiEndpointType, network: SuiNetwork, url: string, grpcMetadata?: SuiGrpcMetadata): ClientWithCoreApi;
11
34
  export declare class SuiPriceListener extends ChainPriceListener {
12
35
  private pythClient;
13
36
  private provider;
14
37
  private logger;
15
- constructor(pythStateId: ObjectId, wormholeStateId: ObjectId, endpoint: string, priceItems: PriceItem[], logger: Logger, config: {
38
+ constructor(pythStateId: ObjectId, wormholeStateId: ObjectId, endpoint: string, endpointType: SuiEndpointType, network: SuiNetwork, priceItems: PriceItem[], logger: Logger, config: {
16
39
  pollingFrequency: DurationInSeconds;
17
- });
40
+ }, grpcMetadata?: SuiGrpcMetadata);
18
41
  getOnChainPriceInfo(priceId: string): Promise<PriceInfo | undefined>;
19
42
  }
20
43
  /**
@@ -39,18 +62,12 @@ export declare class SuiPricePusher implements IPricePusher {
39
62
  private gasBudget;
40
63
  private gasPool;
41
64
  private pythClient;
42
- constructor(signer: Ed25519Keypair, provider: SuiClient, logger: Logger, hermesClient: HermesClient, gasBudget: number, gasPool: SuiObjectRef[], pythClient: SuiPythClient);
43
- /**
44
- * getPackageId returns the latest package id that the object belongs to. Use this to
45
- * fetch the latest package id for a given object id and handle package upgrades automatically.
46
- * @returns package id
47
- */
48
- static getPackageId(provider: SuiClient, objectId: ObjectId): Promise<ObjectId>;
65
+ constructor(signer: Ed25519Keypair, provider: ClientWithCoreApi, logger: Logger, hermesClient: HermesClient, gasBudget: number, gasPool: SuiObjectRef[], pythClient: SuiPythClient);
49
66
  /**
50
67
  * Create a price pusher with a pool of `numGasObjects` gas coins that will be used to send transactions.
51
68
  * The gas coins of the wallet for the provided keypair will be merged and then evenly split into `numGasObjects`.
52
69
  */
53
- static createWithAutomaticGasPool(hermesClient: HermesClient, logger: Logger, pythStateId: string, wormholeStateId: string, endpoint: string, keypair: Ed25519Keypair, gasBudget: number, numGasObjects: number, ignoreGasObjects: string[]): Promise<SuiPricePusher>;
70
+ static createWithAutomaticGasPool(hermesClient: HermesClient, logger: Logger, pythStateId: string, wormholeStateId: string, endpoint: string, endpointType: SuiEndpointType, network: SuiNetwork, keypair: Ed25519Keypair, gasBudget: number, numGasObjects: number, ignoreGasObjects: string[], grpcMetadata?: SuiGrpcMetadata): Promise<SuiPricePusher>;
54
71
  updatePriceFeed(priceIds: string[], pubTimesToPush: number[]): Promise<void>;
55
72
  /** Send every transaction in txs in parallel, returning when all transactions have completed. */
56
73
  private sendTransactionBlocks;
package/package.json CHANGED
@@ -5,10 +5,12 @@
5
5
  "dependencies": {
6
6
  "@aptos-labs/ts-sdk": "^1.39.0",
7
7
  "@coral-xyz/anchor": "^0.30.0",
8
+ "@grpc/grpc-js": "^1.13.2",
8
9
  "@injectivelabs/networks": "1.14.47",
9
10
  "@injectivelabs/sdk-ts": "1.14.50",
10
11
  "@injectivelabs/utils": "^1.14.48",
11
- "@mysten/sui": "^1.3.0",
12
+ "@mysten/sui": "^2.7.0",
13
+ "@protobuf-ts/grpc-transport": "^2.11.1",
12
14
  "@solana/web3.js": "^1.93.0",
13
15
  "@ton/core": "^0.59.0",
14
16
  "@ton/crypto": "^3.3.0",
@@ -25,14 +27,14 @@
25
27
  "viem": "^2.19.4",
26
28
  "yaml": "^2.1.1",
27
29
  "yargs": "^17.5.1",
28
- "@pythnetwork/hermes-client": "3.1.0",
29
30
  "@pythnetwork/price-service-sdk": "^1.9.0",
30
31
  "@pythnetwork/pyth-fuel-js": "1.1.0",
32
+ "@pythnetwork/hermes-client": "3.1.0",
31
33
  "@pythnetwork/pyth-solana-receiver": "0.16.0",
32
- "@pythnetwork/pyth-sdk-solidity": "4.3.1",
33
- "@pythnetwork/pyth-sui-js": "3.0.0",
34
+ "@pythnetwork/pyth-sui-js": "4.0.0",
35
+ "@pythnetwork/pyth-ton-js": "0.4.0",
34
36
  "@pythnetwork/solana-utils": "0.6.0",
35
- "@pythnetwork/pyth-ton-js": "0.4.0"
37
+ "@pythnetwork/pyth-sdk-solidity": "4.3.1"
36
38
  },
37
39
  "description": "Pyth Price Pusher",
38
40
  "devDependencies": {
@@ -89,6 +91,10 @@
89
91
  "default": "./dist/evm/evm.cjs",
90
92
  "types": "./dist/evm/evm.d.ts"
91
93
  },
94
+ "./evm/gas-price": {
95
+ "default": "./dist/evm/gas-price.cjs",
96
+ "types": "./dist/evm/gas-price.d.ts"
97
+ },
92
98
  "./evm/pyth-abi": {
93
99
  "default": "./dist/evm/pyth-abi.cjs",
94
100
  "types": "./dist/evm/pyth-abi.d.ts"
@@ -211,12 +217,13 @@
211
217
  },
212
218
  "type": "module",
213
219
  "types": "./dist/index.d.ts",
214
- "version": "10.4.0",
220
+ "version": "11.3.0",
215
221
  "scripts": {
216
222
  "build": "ts-duality --noEsm",
217
223
  "clean": "rm -rf ./dist",
218
224
  "dev": "ts-node src/index.ts",
219
225
  "start": "node dist/index.cjs",
220
- "test:types": "tsc"
226
+ "test:types": "tsc",
227
+ "test:unit": "test-unit"
221
228
  }
222
229
  }