@pythnetwork/price-pusher 10.3.1 → 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.
Files changed (58) hide show
  1. package/README.md +28 -7
  2. package/dist/aptos/aptos.cjs +7 -7
  3. package/dist/aptos/aptos.d.ts +1 -1
  4. package/dist/aptos/balance-tracker.cjs +7 -7
  5. package/dist/aptos/balance-tracker.d.ts +1 -1
  6. package/dist/aptos/command.cjs +20 -17
  7. package/dist/aptos/command.d.ts +3 -2
  8. package/dist/common.cjs +0 -3
  9. package/dist/common.d.ts +0 -4
  10. package/dist/controller.cjs +12 -7
  11. package/dist/controller.d.ts +1 -1
  12. package/dist/evm/balance-tracker.cjs +4 -4
  13. package/dist/evm/balance-tracker.d.ts +2 -2
  14. package/dist/evm/command.cjs +89 -40
  15. package/dist/evm/command.d.ts +12 -6
  16. package/dist/evm/evm.cjs +162 -58
  17. package/dist/evm/evm.d.ts +13 -8
  18. package/dist/evm/gas-price.cjs +114 -0
  19. package/dist/evm/gas-price.d.ts +33 -0
  20. package/dist/evm/pyth-contract.cjs +2 -2
  21. package/dist/evm/super-wallet.cjs +4 -4
  22. package/dist/evm/super-wallet.d.ts +1 -1
  23. package/dist/fuel/command.cjs +17 -14
  24. package/dist/fuel/command.d.ts +3 -2
  25. package/dist/fuel/fuel.d.ts +2 -2
  26. package/dist/injective/command.cjs +26 -23
  27. package/dist/injective/command.d.ts +5 -4
  28. package/dist/injective/injective.cjs +11 -11
  29. package/dist/injective/injective.d.ts +2 -3
  30. package/dist/interface.d.ts +1 -1
  31. package/dist/metrics.cjs +57 -35
  32. package/dist/metrics.d.ts +10 -5
  33. package/dist/near/command.cjs +22 -19
  34. package/dist/near/command.d.ts +5 -4
  35. package/dist/near/near.cjs +17 -16
  36. package/dist/near/near.d.ts +1 -1
  37. package/dist/options.cjs +36 -26
  38. package/dist/options.d.ts +3 -0
  39. package/dist/price-config.cjs +15 -15
  40. package/dist/pyth-price-listener.cjs +5 -3
  41. package/dist/pyth-price-listener.d.ts +2 -3
  42. package/dist/solana/balance-tracker.cjs +5 -5
  43. package/dist/solana/balance-tracker.d.ts +2 -2
  44. package/dist/solana/command.cjs +75 -60
  45. package/dist/solana/command.d.ts +13 -10
  46. package/dist/solana/solana.cjs +5 -5
  47. package/dist/solana/solana.d.ts +4 -4
  48. package/dist/sui/balance-tracker.cjs +6 -6
  49. package/dist/sui/balance-tracker.d.ts +5 -5
  50. package/dist/sui/command.cjs +84 -47
  51. package/dist/sui/command.d.ts +10 -6
  52. package/dist/sui/sui.cjs +159 -106
  53. package/dist/sui/sui.d.ts +31 -14
  54. package/dist/ton/command.cjs +17 -14
  55. package/dist/ton/command.d.ts +3 -2
  56. package/dist/ton/ton.d.ts +2 -3
  57. package/dist/utils.d.ts +1 -2
  58. package/package.json +127 -131
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 {
126
+ conf: priceFields.conf,
61
127
  price: negative ? `-${magnitude}` : magnitude,
62
- conf,
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({
209
+ const result = await this.provider.core.signAndExecuteTransaction({
210
+ include: {
211
+ effects: true
212
+ },
170
213
  signer: this.signer,
171
- transaction: tx,
172
- options: {
173
- showEffects: true
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({
249
- owner,
250
- cursor
291
+ const paginatedCoins = await provider.core.listCoins({
292
+ cursor,
293
+ owner
251
294
  });
252
- numCoins += paginatedCoins.data.length;
253
- for (const c of paginatedCoins.data)coins.add(JSON.stringify({
254
- objectId: c.coinObjectId,
255
- version: c.version,
256
- digest: c.digest
295
+ numCoins += paginatedCoins.objects.length;
296
+ for (const c of paginatedCoins.objects)coins.add(JSON.stringify({
297
+ digest: c.digest,
298
+ objectId: c.objectId,
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({
323
+ const result = await provider.core.signAndExecuteTransaction({
324
+ include: {
325
+ effects: true
326
+ },
281
327
  signer,
282
- transaction: tx,
283
- options: {
284
- showEffects: true
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,12 +360,12 @@ class SuiPricePusher {
317
360
  mergeTx.setGasPayment(coins);
318
361
  let mergeResult;
319
362
  try {
320
- mergeResult = await provider.signAndExecuteTransaction({
363
+ mergeResult = await provider.core.signAndExecuteTransaction({
364
+ include: {
365
+ effects: true
366
+ },
321
367
  signer,
322
- transaction: mergeTx,
323
- options: {
324
- showEffects: true
325
- }
368
+ transaction: mergeTx
326
369
  });
327
370
  } catch (error_) {
328
371
  logger.error(error_, "Merge transaction failed with error");
@@ -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,20 +1,43 @@
1
- import type { SuiObjectRef } from "@mysten/sui/client";
2
- import { SuiClient } from "@mysten/sui/client";
3
- import { Ed25519Keypair } from "@mysten/sui/keypairs/ed25519";
4
- import { HermesClient } from "@pythnetwork/hermes-client";
1
+ import type { ClientWithCoreApi } from "@mysten/sui/client";
2
+ import type { SuiObjectRef } from "@mysten/sui/jsonRpc";
3
+ import type { Ed25519Keypair } from "@mysten/sui/keypairs/ed25519";
4
+ import type { HermesClient } from "@pythnetwork/hermes-client";
5
5
  import { SuiPythClient } from "@pythnetwork/pyth-sui-js";
6
6
  import type { Logger } from "pino";
7
7
  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;
@@ -12,12 +12,12 @@ const _nodefs = /*#__PURE__*/ _interop_require_default(require("node:fs"));
12
12
  const _hermesclient = require("@pythnetwork/hermes-client");
13
13
  const _ton = require("@ton/ton");
14
14
  const _pino = require("pino");
15
+ const _controller = require("../controller.cjs");
15
16
  const _options = /*#__PURE__*/ _interop_require_wildcard(require("../options.cjs"));
16
17
  const _priceconfig = require("../price-config.cjs");
17
18
  const _pythpricelistener = require("../pyth-price-listener.cjs");
18
- const _ton1 = require("./ton.cjs");
19
- const _controller = require("../controller.cjs");
20
19
  const _utils = require("../utils.cjs");
20
+ const _ton1 = require("./ton.cjs");
21
21
  function _interop_require_default(obj) {
22
22
  return obj && obj.__esModule ? obj : {
23
23
  default: obj
@@ -65,41 +65,44 @@ function _interop_require_wildcard(obj, nodeInterop) {
65
65
  return newObj;
66
66
  }
67
67
  const _default = {
68
- command: "ton",
69
- describe: "run price pusher for TON",
70
68
  builder: {
71
69
  endpoint: {
72
70
  description: "TON RPC API endpoint",
73
- type: "string",
74
- required: true
71
+ required: true,
72
+ type: "string"
75
73
  },
76
74
  "private-key-file": {
77
75
  description: "Path to the private key file",
78
- type: "string",
79
- required: true
76
+ required: true,
77
+ type: "string"
80
78
  },
81
79
  "pyth-contract-address": {
82
80
  description: "Pyth contract address on TON",
83
- type: "string",
84
- required: true
81
+ required: true,
82
+ type: "string"
85
83
  },
86
84
  ..._options.priceConfigFile,
87
85
  ..._options.priceServiceEndpoint,
86
+ ..._options.hermesAccessToken,
88
87
  ..._options.pushingFrequency,
89
88
  ..._options.pollingFrequency,
90
89
  ..._options.logLevel,
91
90
  ..._options.controllerLogLevel
92
91
  },
92
+ command: "ton",
93
+ describe: "run price pusher for TON",
93
94
  handler: async function(argv) {
94
- const { endpoint, privateKeyFile, pythContractAddress, priceConfigFile, priceServiceEndpoint, pushingFrequency, pollingFrequency, logLevel, controllerLogLevel } = argv;
95
+ const { endpoint, privateKeyFile, pythContractAddress, priceConfigFile, priceServiceEndpoint, hermesAccessToken, pushingFrequency, pollingFrequency, logLevel, controllerLogLevel } = argv;
95
96
  const logger = (0, _pino.pino)({
96
97
  level: logLevel
97
98
  });
98
99
  const priceConfigs = (0, _priceconfig.readPriceConfigFile)(priceConfigFile);
99
- const hermesClient = new _hermesclient.HermesClient(priceServiceEndpoint);
100
+ const hermesClient = new _hermesclient.HermesClient(priceServiceEndpoint, {
101
+ accessToken: hermesAccessToken
102
+ });
100
103
  let priceItems = priceConfigs.map(({ id, alias })=>({
101
- id,
102
- alias
104
+ alias,
105
+ id
103
106
  }));
104
107
  // Better to filter out invalid price items before creating the pyth listener
105
108
  const { existingPriceItems, invalidPriceItems } = await (0, _utils.filterInvalidPriceItems)(hermesClient, priceItems);
@@ -1,18 +1,19 @@
1
1
  import type { Options } from "yargs";
2
2
  declare const _default: {
3
- command: string;
4
- describe: string;
5
3
  builder: {
6
4
  "controller-log-level": Options;
7
5
  "log-level": Options;
8
6
  "polling-frequency": Options;
9
7
  "pushing-frequency": Options;
8
+ "hermes-access-token": Options;
10
9
  "price-service-endpoint": Options;
11
10
  "price-config-file": Options;
12
11
  endpoint: Options;
13
12
  "private-key-file": Options;
14
13
  "pyth-contract-address": Options;
15
14
  };
15
+ command: string;
16
+ describe: string;
16
17
  handler: (argv: any) => Promise<void>;
17
18
  };
18
19
  export default _default;
package/dist/ton/ton.d.ts CHANGED
@@ -1,6 +1,5 @@
1
- import { HermesClient } from "@pythnetwork/hermes-client";
2
- import type { ContractProvider } from "@ton/ton";
3
- import { Address, TonClient } from "@ton/ton";
1
+ import type { HermesClient } from "@pythnetwork/hermes-client";
2
+ import type { Address, ContractProvider, TonClient } from "@ton/ton";
4
3
  import type { Logger } from "pino";
5
4
  import type { IPricePusher, PriceInfo, PriceItem } from "../interface.js";
6
5
  import { ChainPriceListener } from "../interface.js";
package/dist/utils.d.ts CHANGED
@@ -1,5 +1,4 @@
1
- import type { HexString } from "@pythnetwork/hermes-client";
2
- import { HermesClient } from "@pythnetwork/hermes-client";
1
+ import type { HermesClient, HexString } from "@pythnetwork/hermes-client";
3
2
  import type { PriceItem } from "./interface.js";
4
3
  export type PctNumber = number;
5
4
  export type DurationInSeconds = number;