@pythnetwork/price-pusher 10.2.0 → 10.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 (127) hide show
  1. package/{lib/aptos/aptos.js → dist/aptos/aptos.cjs} +80 -76
  2. package/{lib → dist}/aptos/aptos.d.ts +5 -5
  3. package/{lib/aptos/balance-tracker.js → dist/aptos/balance-tracker.cjs} +37 -25
  4. package/{lib → dist}/aptos/balance-tracker.d.ts +9 -9
  5. package/dist/aptos/command.cjs +161 -0
  6. package/{lib → dist}/aptos/command.d.ts +1 -2
  7. package/dist/common.cjs +4 -0
  8. package/{lib → dist}/common.d.ts +0 -1
  9. package/{lib/controller.js → dist/controller.cjs} +35 -33
  10. package/{lib → dist}/controller.d.ts +5 -6
  11. package/dist/evm/balance-tracker.cjs +58 -0
  12. package/{lib → dist}/evm/balance-tracker.d.ts +10 -10
  13. package/dist/evm/command.cjs +205 -0
  14. package/{lib → dist}/evm/command.d.ts +1 -2
  15. package/dist/evm/custom-gas-station.cjs +54 -0
  16. package/{lib → dist}/evm/custom-gas-station.d.ts +1 -2
  17. package/dist/evm/evm.cjs +287 -0
  18. package/{lib → dist}/evm/evm.d.ts +8 -7
  19. package/{lib/evm/pyth-abi.js → dist/evm/pyth-abi.cjs} +181 -160
  20. package/{lib → dist}/evm/pyth-abi.d.ts +0 -1
  21. package/dist/evm/pyth-contract.cjs +17 -0
  22. package/{lib → dist}/evm/pyth-contract.d.ts +3 -4
  23. package/dist/evm/super-wallet.cjs +90 -0
  24. package/{lib → dist}/evm/super-wallet.d.ts +1 -2
  25. package/dist/fuel/command.cjs +135 -0
  26. package/{lib → dist}/fuel/command.d.ts +1 -2
  27. package/dist/fuel/fuel.cjs +108 -0
  28. package/{lib → dist}/fuel/fuel.d.ts +5 -5
  29. package/dist/index.cjs +25 -0
  30. package/dist/index.d.ts +1 -0
  31. package/dist/injective/command.cjs +150 -0
  32. package/{lib → dist}/injective/command.d.ts +1 -2
  33. package/{lib/injective/injective.js → dist/injective/injective.cjs} +100 -98
  34. package/{lib → dist}/injective/injective.d.ts +7 -6
  35. package/dist/interface.cjs +142 -0
  36. package/{lib → dist}/interface.d.ts +12 -13
  37. package/dist/metrics.cjs +218 -0
  38. package/{lib → dist}/metrics.d.ts +10 -11
  39. package/dist/near/command.cjs +129 -0
  40. package/{lib → dist}/near/command.d.ts +1 -2
  41. package/dist/near/near.cjs +183 -0
  42. package/{lib → dist}/near/near.d.ts +5 -5
  43. package/dist/options.cjs +132 -0
  44. package/{lib → dist}/options.d.ts +1 -2
  45. package/dist/package.json +1 -0
  46. package/dist/price-config.cjs +104 -0
  47. package/{lib → dist}/price-config.d.ts +5 -6
  48. package/{lib/pyth-price-listener.js → dist/pyth-price-listener.cjs} +30 -24
  49. package/{lib → dist}/pyth-price-listener.d.ts +4 -4
  50. package/dist/solana/balance-tracker.cjs +60 -0
  51. package/{lib → dist}/solana/balance-tracker.d.ts +9 -9
  52. package/dist/solana/command.cjs +259 -0
  53. package/{lib → dist}/solana/command.d.ts +2 -3
  54. package/{lib/solana/solana.js → dist/solana/solana.cjs} +90 -78
  55. package/{lib → dist}/solana/solana.d.ts +6 -6
  56. package/dist/sui/balance-tracker.cjs +58 -0
  57. package/{lib → dist}/sui/balance-tracker.d.ts +9 -9
  58. package/dist/sui/command.cjs +190 -0
  59. package/{lib → dist}/sui/command.d.ts +1 -2
  60. package/{lib/sui/sui.js → dist/sui/sui.cjs} +145 -133
  61. package/{lib → dist}/sui/sui.d.ts +7 -8
  62. package/dist/ton/command.cjs +137 -0
  63. package/{lib → dist}/ton/command.d.ts +1 -2
  64. package/dist/ton/ton.cjs +103 -0
  65. package/{lib → dist}/ton/ton.d.ts +7 -6
  66. package/dist/utils.cjs +102 -0
  67. package/{lib → dist}/utils.d.ts +4 -4
  68. package/package.json +161 -20
  69. package/lib/aptos/aptos.d.ts.map +0 -1
  70. package/lib/aptos/balance-tracker.d.ts.map +0 -1
  71. package/lib/aptos/command.d.ts.map +0 -1
  72. package/lib/aptos/command.js +0 -126
  73. package/lib/common.d.ts.map +0 -1
  74. package/lib/common.js +0 -2
  75. package/lib/controller.d.ts.map +0 -1
  76. package/lib/evm/balance-tracker.d.ts.map +0 -1
  77. package/lib/evm/balance-tracker.js +0 -49
  78. package/lib/evm/command.d.ts.map +0 -1
  79. package/lib/evm/command.js +0 -178
  80. package/lib/evm/custom-gas-station.d.ts.map +0 -1
  81. package/lib/evm/custom-gas-station.js +0 -40
  82. package/lib/evm/evm.d.ts.map +0 -1
  83. package/lib/evm/evm.js +0 -270
  84. package/lib/evm/pyth-abi.d.ts.map +0 -1
  85. package/lib/evm/pyth-contract.d.ts.map +0 -1
  86. package/lib/evm/pyth-contract.js +0 -11
  87. package/lib/evm/super-wallet.d.ts.map +0 -1
  88. package/lib/evm/super-wallet.js +0 -73
  89. package/lib/fuel/command.d.ts.map +0 -1
  90. package/lib/fuel/command.js +0 -98
  91. package/lib/fuel/fuel.d.ts.map +0 -1
  92. package/lib/fuel/fuel.js +0 -101
  93. package/lib/index.d.ts +0 -3
  94. package/lib/index.d.ts.map +0 -1
  95. package/lib/index.js +0 -34
  96. package/lib/injective/command.d.ts.map +0 -1
  97. package/lib/injective/command.js +0 -119
  98. package/lib/injective/injective.d.ts.map +0 -1
  99. package/lib/interface.d.ts.map +0 -1
  100. package/lib/interface.js +0 -122
  101. package/lib/metrics.d.ts.map +0 -1
  102. package/lib/metrics.js +0 -152
  103. package/lib/near/command.d.ts.map +0 -1
  104. package/lib/near/command.js +0 -103
  105. package/lib/near/near.d.ts.map +0 -1
  106. package/lib/near/near.js +0 -168
  107. package/lib/options.d.ts.map +0 -1
  108. package/lib/options.js +0 -84
  109. package/lib/price-config.d.ts.map +0 -1
  110. package/lib/price-config.js +0 -114
  111. package/lib/pyth-price-listener.d.ts.map +0 -1
  112. package/lib/solana/balance-tracker.d.ts.map +0 -1
  113. package/lib/solana/balance-tracker.js +0 -51
  114. package/lib/solana/command.d.ts.map +0 -1
  115. package/lib/solana/command.js +0 -223
  116. package/lib/solana/solana.d.ts.map +0 -1
  117. package/lib/sui/balance-tracker.d.ts.map +0 -1
  118. package/lib/sui/balance-tracker.js +0 -49
  119. package/lib/sui/command.d.ts.map +0 -1
  120. package/lib/sui/command.js +0 -160
  121. package/lib/sui/sui.d.ts.map +0 -1
  122. package/lib/ton/command.d.ts.map +0 -1
  123. package/lib/ton/command.js +0 -99
  124. package/lib/ton/ton.d.ts.map +0 -1
  125. package/lib/ton/ton.js +0 -97
  126. package/lib/utils.d.ts.map +0 -1
  127. package/lib/utils.js +0 -61
@@ -0,0 +1,259 @@
1
+ /* eslint-disable @typescript-eslint/no-non-null-assertion */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable @typescript-eslint/no-unsafe-call */ /* eslint-disable @typescript-eslint/restrict-template-expressions */ /* eslint-disable @typescript-eslint/no-unsafe-argument */ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ /* eslint-disable @typescript-eslint/no-explicit-any */ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: Object.getOwnPropertyDescriptor(all, name).get
9
+ });
10
+ }
11
+ _export(exports, {
12
+ get default () {
13
+ return _default;
14
+ },
15
+ get onBundleResult () {
16
+ return onBundleResult;
17
+ }
18
+ });
19
+ const _nodefs = /*#__PURE__*/ _interop_require_default(require("node:fs"));
20
+ const _nodewallet = /*#__PURE__*/ _interop_require_default(require("@coral-xyz/anchor/dist/cjs/nodewallet.js"));
21
+ const _hermesclient = require("@pythnetwork/hermes-client");
22
+ const _pythsolanareceiver = require("@pythnetwork/pyth-solana-receiver");
23
+ const _web3 = require("@solana/web3.js");
24
+ const _searcher = require("jito-ts/dist/sdk/block-engine/searcher");
25
+ const _pino = require("pino");
26
+ const _options = /*#__PURE__*/ _interop_require_wildcard(require("../options.cjs"));
27
+ const _priceconfig = require("../price-config.cjs");
28
+ const _pythpricelistener = require("../pyth-price-listener.cjs");
29
+ const _solana = require("./solana.cjs");
30
+ const _controller = require("../controller.cjs");
31
+ const _metrics = require("../metrics.cjs");
32
+ const _utils = require("../utils.cjs");
33
+ const _balancetracker = require("./balance-tracker.cjs");
34
+ function _interop_require_default(obj) {
35
+ return obj && obj.__esModule ? obj : {
36
+ default: obj
37
+ };
38
+ }
39
+ function _getRequireWildcardCache(nodeInterop) {
40
+ if (typeof WeakMap !== "function") return null;
41
+ var cacheBabelInterop = new WeakMap();
42
+ var cacheNodeInterop = new WeakMap();
43
+ return (_getRequireWildcardCache = function(nodeInterop) {
44
+ return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
45
+ })(nodeInterop);
46
+ }
47
+ function _interop_require_wildcard(obj, nodeInterop) {
48
+ if (!nodeInterop && obj && obj.__esModule) {
49
+ return obj;
50
+ }
51
+ if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
52
+ return {
53
+ default: obj
54
+ };
55
+ }
56
+ var cache = _getRequireWildcardCache(nodeInterop);
57
+ if (cache && cache.has(obj)) {
58
+ return cache.get(obj);
59
+ }
60
+ var newObj = {
61
+ __proto__: null
62
+ };
63
+ var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
64
+ for(var key in obj){
65
+ if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
66
+ var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
67
+ if (desc && (desc.get || desc.set)) {
68
+ Object.defineProperty(newObj, key, desc);
69
+ } else {
70
+ newObj[key] = obj[key];
71
+ }
72
+ }
73
+ }
74
+ newObj.default = obj;
75
+ if (cache) {
76
+ cache.set(obj, newObj);
77
+ }
78
+ return newObj;
79
+ }
80
+ const _default = {
81
+ command: "solana",
82
+ describe: "run price pusher for solana",
83
+ builder: {
84
+ endpoint: {
85
+ description: "Solana RPC API endpoint",
86
+ type: "string",
87
+ required: true
88
+ },
89
+ "keypair-file": {
90
+ description: "Path to a keypair file",
91
+ type: "string",
92
+ required: true
93
+ },
94
+ "shard-id": {
95
+ description: "Shard ID",
96
+ type: "number",
97
+ required: true
98
+ },
99
+ "compute-unit-price-micro-lamports": {
100
+ description: "Priority fee per compute unit",
101
+ type: "number",
102
+ default: 50_000
103
+ },
104
+ "jito-endpoints": {
105
+ description: "Jito endpoint(s) - comma-separated list of endpoints",
106
+ type: "string",
107
+ optional: true
108
+ },
109
+ "jito-keypair-file": {
110
+ description: "Path to the jito keypair file (need for grpc authentication)",
111
+ type: "string",
112
+ optional: true
113
+ },
114
+ "jito-tip-lamports": {
115
+ description: "Lamports to tip the jito builder",
116
+ type: "number",
117
+ optional: true
118
+ },
119
+ "dynamic-jito-tips": {
120
+ description: "Use dynamic jito tips",
121
+ type: "boolean",
122
+ default: false
123
+ },
124
+ "max-jito-tip-lamports": {
125
+ description: "Maximum jito tip lamports",
126
+ type: "number",
127
+ default: _web3.LAMPORTS_PER_SOL / 100
128
+ },
129
+ "jito-bundle-size": {
130
+ description: "Number of transactions in each Jito bundle",
131
+ type: "number",
132
+ default: 5
133
+ },
134
+ "updates-per-jito-bundle": {
135
+ description: "Number of price updates in each Jito bundle",
136
+ type: "number",
137
+ default: 6
138
+ },
139
+ "address-lookup-table-account": {
140
+ description: "The pubkey of the ALT to use when updating price feeds",
141
+ type: "string",
142
+ optional: true
143
+ },
144
+ "treasury-id": {
145
+ description: "The treasuryId to use. Useful when the corresponding treasury account is indexed in the ALT passed to --address-lookup-table-account. This is a tx size optimization and is optional; if not set, a random treasury account will be used.",
146
+ type: "number",
147
+ optional: true
148
+ },
149
+ ..._options.priceConfigFile,
150
+ ..._options.priceServiceEndpoint,
151
+ ..._options.pythContractAddress,
152
+ ..._options.pollingFrequency,
153
+ ..._options.pushingFrequency,
154
+ ..._options.logLevel,
155
+ ..._options.controllerLogLevel,
156
+ ..._options.enableMetrics,
157
+ ..._options.metricsPort
158
+ },
159
+ handler: async function(argv) {
160
+ const { endpoint, keypairFile, shardId, computeUnitPriceMicroLamports, priceConfigFile, priceServiceEndpoint, pythContractAddress, pushingFrequency, pollingFrequency, jitoEndpoints, jitoKeypairFile, jitoTipLamports, dynamicJitoTips, maxJitoTipLamports, updatesPerJitoBundle, addressLookupTableAccount, treasuryId, logLevel, controllerLogLevel, enableMetrics, metricsPort } = argv;
161
+ const logger = (0, _pino.pino)({
162
+ level: logLevel
163
+ });
164
+ const priceConfigs = (0, _priceconfig.readPriceConfigFile)(priceConfigFile);
165
+ const hermesClient = new _hermesclient.HermesClient(priceServiceEndpoint);
166
+ // Initialize metrics if enabled
167
+ let metrics;
168
+ if (enableMetrics) {
169
+ metrics = new _metrics.PricePusherMetrics(logger.child({
170
+ module: "Metrics"
171
+ }));
172
+ metrics.start(metricsPort);
173
+ logger.info(`Metrics server started on port ${metricsPort}`);
174
+ }
175
+ let priceItems = priceConfigs.map(({ id, alias })=>({
176
+ id,
177
+ alias
178
+ }));
179
+ // Better to filter out invalid price items before creating the pyth listener
180
+ const { existingPriceItems, invalidPriceItems } = await (0, _utils.filterInvalidPriceItems)(hermesClient, priceItems);
181
+ if (invalidPriceItems.length > 0) {
182
+ logger.error(`Invalid price id submitted for: ${invalidPriceItems.map(({ alias })=>alias).join(", ")}`);
183
+ }
184
+ priceItems = existingPriceItems;
185
+ const pythListener = new _pythpricelistener.PythPriceListener(hermesClient, priceItems, logger.child({
186
+ module: "PythPriceListener"
187
+ }));
188
+ const keypair = _web3.Keypair.fromSecretKey(Uint8Array.from(JSON.parse(_nodefs.default.readFileSync(keypairFile, "ascii"))));
189
+ const wallet = new _nodewallet.default(keypair);
190
+ const connection = new _web3.Connection(endpoint, "processed");
191
+ const pythSolanaReceiver = new _pythsolanareceiver.PythSolanaReceiver({
192
+ connection,
193
+ wallet,
194
+ pushOracleProgramId: new _web3.PublicKey(pythContractAddress),
195
+ treasuryId: treasuryId
196
+ });
197
+ // Create and start the balance tracker if metrics are enabled
198
+ if (metrics) {
199
+ const balanceTracker = (0, _balancetracker.createSolanaBalanceTracker)({
200
+ connection,
201
+ publicKey: keypair.publicKey,
202
+ network: "solana",
203
+ updateInterval: 60,
204
+ metrics,
205
+ logger
206
+ });
207
+ // Start the balance tracker
208
+ await balanceTracker.start();
209
+ }
210
+ // Fetch the account lookup table if provided
211
+ const lookupTableAccount = addressLookupTableAccount ? await connection.getAddressLookupTable(new _web3.PublicKey(addressLookupTableAccount)).then((result)=>result.value ?? undefined) : undefined;
212
+ let solanaPricePusher;
213
+ if (jitoTipLamports) {
214
+ const jitoKeypair = _web3.Keypair.fromSecretKey(Uint8Array.from(JSON.parse(_nodefs.default.readFileSync(jitoKeypairFile, "ascii"))));
215
+ const jitoEndpointsList = jitoEndpoints.split(",").map((endpoint)=>endpoint.trim());
216
+ const jitoClients = jitoEndpointsList.map((endpoint)=>{
217
+ logger.info(`Constructing Jito searcher client from endpoint ${endpoint}`);
218
+ return (0, _searcher.searcherClient)(endpoint, jitoKeypair);
219
+ });
220
+ solanaPricePusher = new _solana.SolanaPricePusherJito(pythSolanaReceiver, hermesClient, logger.child({
221
+ module: "SolanaPricePusherJito"
222
+ }), shardId, jitoTipLamports, dynamicJitoTips, maxJitoTipLamports, jitoClients, updatesPerJitoBundle, // Set max retry time to pushing frequency, since we want to stop retrying before the next push attempt
223
+ pushingFrequency * 1000, lookupTableAccount);
224
+ for (const [index, client] of jitoClients.entries()){
225
+ onBundleResult(client, logger.child({
226
+ module: `JitoClient-${index}`
227
+ }));
228
+ }
229
+ } else {
230
+ solanaPricePusher = new _solana.SolanaPricePusher(pythSolanaReceiver, hermesClient, logger.child({
231
+ module: "SolanaPricePusher"
232
+ }), shardId, computeUnitPriceMicroLamports, lookupTableAccount);
233
+ }
234
+ const solanaPriceListener = new _solana.SolanaPriceListener(pythSolanaReceiver, shardId, priceItems, logger.child({
235
+ module: "SolanaPriceListener"
236
+ }), {
237
+ pollingFrequency
238
+ });
239
+ const controller = new _controller.Controller(priceConfigs, pythListener, solanaPriceListener, solanaPricePusher, logger.child({
240
+ module: "Controller"
241
+ }, {
242
+ level: controllerLogLevel
243
+ }), {
244
+ pushingFrequency,
245
+ metrics: metrics
246
+ });
247
+ void controller.start();
248
+ }
249
+ };
250
+ const onBundleResult = (c, logger)=>{
251
+ try {
252
+ c.onBundleResult(// eslint-disable-next-line @typescript-eslint/no-empty-function
253
+ ()=>{}, (err)=>{
254
+ logger.error(err, "Error in bundle result");
255
+ });
256
+ } catch (error) {
257
+ logger.error(error, "Exception in bundle result");
258
+ }
259
+ };
@@ -1,6 +1,6 @@
1
- import { Options } from "yargs";
2
1
  import { SearcherClient } from "jito-ts/dist/sdk/block-engine/searcher";
3
- import { Logger } from "pino";
2
+ import type { Logger } from "pino";
3
+ import type { Options } from "yargs";
4
4
  declare const _default: {
5
5
  command: string;
6
6
  describe: string;
@@ -32,4 +32,3 @@ declare const _default: {
32
32
  };
33
33
  export default _default;
34
34
  export declare const onBundleResult: (c: SearcherClient, logger: Logger) => void;
35
- //# sourceMappingURL=command.d.ts.map
@@ -1,20 +1,35 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SolanaPricePusherJito = exports.SolanaPricePusher = exports.SolanaPriceListener = void 0;
4
- const interface_1 = require("../interface");
5
- const solana_utils_1 = require("@pythnetwork/solana-utils");
6
- const price_service_sdk_1 = require("@pythnetwork/price-service-sdk");
7
- const web3_js_1 = require("@solana/web3.js");
1
+ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable @typescript-eslint/no-explicit-any */ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: Object.getOwnPropertyDescriptor(all, name).get
9
+ });
10
+ }
11
+ _export(exports, {
12
+ get SolanaPriceListener () {
13
+ return SolanaPriceListener;
14
+ },
15
+ get SolanaPricePusher () {
16
+ return SolanaPricePusher;
17
+ },
18
+ get SolanaPricePusherJito () {
19
+ return SolanaPricePusherJito;
20
+ }
21
+ });
22
+ const _priceservicesdk = require("@pythnetwork/price-service-sdk");
23
+ const _solanautils = require("@pythnetwork/solana-utils");
24
+ const _web3 = require("@solana/web3.js");
25
+ const _interface = require("../interface.cjs");
8
26
  const HEALTH_CHECK_TIMEOUT_SECONDS = 60;
9
- class SolanaPriceListener extends interface_1.ChainPriceListener {
27
+ class SolanaPriceListener extends _interface.ChainPriceListener {
10
28
  pythSolanaReceiver;
11
29
  shardId;
12
30
  logger;
13
- constructor(pythSolanaReceiver, shardId, priceItems, logger, config) {
14
- super(config.pollingFrequency, priceItems);
15
- this.pythSolanaReceiver = pythSolanaReceiver;
16
- this.shardId = shardId;
17
- this.logger = logger;
31
+ constructor(pythSolanaReceiver, shardId, priceItems, logger, config){
32
+ super(config.pollingFrequency, priceItems), this.pythSolanaReceiver = pythSolanaReceiver, this.shardId = shardId, this.logger = logger;
18
33
  }
19
34
  // Checking the health of the Solana connection by checking the last block time
20
35
  // and ensuring it is not older than 30 seconds.
@@ -22,44 +37,38 @@ class SolanaPriceListener extends interface_1.ChainPriceListener {
22
37
  const slot = await this.pythSolanaReceiver.connection.getSlot("finalized");
23
38
  try {
24
39
  const blockTime = await this.pythSolanaReceiver.connection.getBlockTime(slot);
25
- if (blockTime === null ||
26
- blockTime < Date.now() / 1000 - HEALTH_CHECK_TIMEOUT_SECONDS) {
27
- if (blockTime !== null) {
28
- this.logger.info(`Solana connection is behind by ${Date.now() / 1000 - blockTime} seconds`);
29
- }
40
+ if ((blockTime === null || blockTime < Date.now() / 1000 - HEALTH_CHECK_TIMEOUT_SECONDS) && blockTime !== null) {
41
+ this.logger.info(`Solana connection is behind by ${(Date.now() / 1000 - blockTime).toString()} seconds`);
30
42
  }
31
- }
32
- catch (err) {
33
- this.logger.error({ err }, "checkHealth failed");
43
+ } catch (error) {
44
+ this.logger.error({
45
+ err: error
46
+ }, "checkHealth failed");
34
47
  }
35
48
  }
36
49
  async start() {
37
50
  // Frequently check the RPC connection to ensure it is healthy
38
- setInterval(this.checkHealth.bind(this), 5000);
51
+ setInterval(()=>void this.checkHealth(), 5000);
39
52
  await super.start();
40
53
  }
41
54
  async getOnChainPriceInfo(priceId) {
42
55
  try {
43
56
  const priceFeedAccount = await this.pythSolanaReceiver.fetchPriceFeedAccount(this.shardId, Buffer.from(priceId, "hex"));
44
- this.logger.debug(`Polled a Solana on chain price for feed ${this.priceIdToAlias.get(priceId)} (${priceId}).`);
45
- if (priceFeedAccount) {
46
- return {
47
- conf: priceFeedAccount.priceMessage.conf.toString(),
48
- price: priceFeedAccount.priceMessage.price.toString(),
49
- publishTime: priceFeedAccount.priceMessage.publishTime.toNumber(),
50
- };
51
- }
52
- else {
53
- return undefined;
54
- }
55
- }
56
- catch (err) {
57
- this.logger.error({ err, priceId }, `Polling on-chain price failed.`);
57
+ this.logger.debug(`Polled a Solana on chain price for feed ${this.priceIdToAlias.get(priceId)?.toString() ?? ""} (${priceId}).`);
58
+ return priceFeedAccount ? {
59
+ conf: priceFeedAccount.priceMessage.conf.toString(),
60
+ price: priceFeedAccount.priceMessage.price.toString(),
61
+ publishTime: priceFeedAccount.priceMessage.publishTime.toNumber()
62
+ } : undefined;
63
+ } catch (error) {
64
+ this.logger.error({
65
+ err: error,
66
+ priceId
67
+ }, `Polling on-chain price failed.`);
58
68
  return undefined;
59
69
  }
60
70
  }
61
71
  }
62
- exports.SolanaPriceListener = SolanaPriceListener;
63
72
  class SolanaPricePusher {
64
73
  pythSolanaReceiver;
65
74
  hermesClient;
@@ -67,7 +76,7 @@ class SolanaPricePusher {
67
76
  shardId;
68
77
  computeUnitPriceMicroLamports;
69
78
  addressLookupTableAccount;
70
- constructor(pythSolanaReceiver, hermesClient, logger, shardId, computeUnitPriceMicroLamports, addressLookupTableAccount) {
79
+ constructor(pythSolanaReceiver, hermesClient, logger, shardId, computeUnitPriceMicroLamports, addressLookupTableAccount){
71
80
  this.pythSolanaReceiver = pythSolanaReceiver;
72
81
  this.hermesClient = hermesClient;
73
82
  this.logger = logger;
@@ -79,43 +88,42 @@ class SolanaPricePusher {
79
88
  if (priceIds.length === 0) {
80
89
  return;
81
90
  }
82
- const shuffledPriceIds = priceIds
83
- .map((x) => {
84
- return { element: x, key: Math.random() };
85
- })
86
- .sort((a, b) => a.key - b.key)
87
- .map((x) => x.element);
91
+ const shuffledPriceIds = priceIds.map((x)=>{
92
+ return {
93
+ element: x,
94
+ key: Math.random()
95
+ };
96
+ }).sort((a, b)=>a.key - b.key).map((x)=>x.element);
88
97
  let priceFeedUpdateData;
89
98
  try {
90
99
  const response = await this.hermesClient.getLatestPriceUpdates(shuffledPriceIds, {
91
100
  encoding: "base64",
92
- ignoreInvalidPriceIds: true,
101
+ ignoreInvalidPriceIds: true
93
102
  });
94
103
  priceFeedUpdateData = response.binary.data;
95
- }
96
- catch (err) {
97
- this.logger.error(err, "getPriceFeedsUpdateData failed:");
104
+ } catch (error) {
105
+ this.logger.error(error, "getPriceFeedsUpdateData failed:");
98
106
  return;
99
107
  }
100
108
  const transactionBuilder = this.pythSolanaReceiver.newTransactionBuilder({
101
- closeUpdateAccounts: true,
109
+ closeUpdateAccounts: true
102
110
  }, this.addressLookupTableAccount);
103
111
  await transactionBuilder.addUpdatePriceFeed(priceFeedUpdateData, this.shardId);
104
112
  const transactions = await transactionBuilder.buildVersionedTransactions({
105
113
  computeUnitPriceMicroLamports: this.computeUnitPriceMicroLamports,
106
- tightComputeBudget: true,
114
+ tightComputeBudget: true
107
115
  });
108
116
  try {
109
- const signatures = await (0, solana_utils_1.sendTransactions)(transactions, this.pythSolanaReceiver.connection, this.pythSolanaReceiver.wallet);
110
- this.logger.info({ signatures }, "updatePriceFeed successful");
111
- }
112
- catch (err) {
113
- this.logger.error(err, "updatePriceFeed failed");
117
+ const signatures = await (0, _solanautils.sendTransactions)(transactions, this.pythSolanaReceiver.connection, this.pythSolanaReceiver.wallet);
118
+ this.logger.info({
119
+ signatures
120
+ }, "updatePriceFeed successful");
121
+ } catch (error) {
122
+ this.logger.error(error, "updatePriceFeed failed");
114
123
  return;
115
124
  }
116
125
  }
117
126
  }
118
- exports.SolanaPricePusher = SolanaPricePusher;
119
127
  class SolanaPricePusherJito {
120
128
  pythSolanaReceiver;
121
129
  hermesClient;
@@ -128,7 +136,7 @@ class SolanaPricePusherJito {
128
136
  updatesPerJitoBundle;
129
137
  maxRetryTimeMs;
130
138
  addressLookupTableAccount;
131
- constructor(pythSolanaReceiver, hermesClient, logger, shardId, defaultJitoTipLamports, dynamicJitoTips, maxJitoTipLamports, searcherClients, updatesPerJitoBundle, maxRetryTimeMs, addressLookupTableAccount) {
139
+ constructor(pythSolanaReceiver, hermesClient, logger, shardId, defaultJitoTipLamports, dynamicJitoTips, maxJitoTipLamports, searcherClients, updatesPerJitoBundle, maxRetryTimeMs, addressLookupTableAccount){
132
140
  this.pythSolanaReceiver = pythSolanaReceiver;
133
141
  this.hermesClient = hermesClient;
134
142
  this.logger = logger;
@@ -145,50 +153,54 @@ class SolanaPricePusherJito {
145
153
  try {
146
154
  const response = await fetch("https://bundles.jito.wtf/api/v1/bundles/tip_floor");
147
155
  if (!response.ok) {
148
- this.logger.error({ status: response.status, statusText: response.statusText }, "getRecentJitoTips http request failed");
156
+ this.logger.error({
157
+ status: response.status,
158
+ statusText: response.statusText
159
+ }, "getRecentJitoTips http request failed");
149
160
  return undefined;
150
161
  }
162
+ // TODO: fix this type here to be more specific
151
163
  const data = await response.json();
152
- return Math.floor(Number(data[0].landed_tips_50th_percentile) * web3_js_1.LAMPORTS_PER_SOL);
153
- }
154
- catch (err) {
155
- this.logger.error({ err }, "getRecentJitoTips failed");
164
+ return Math.floor(Number(data[0].landed_tips_50th_percentile) * _web3.LAMPORTS_PER_SOL);
165
+ } catch (error) {
166
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
167
+ this.logger.error({
168
+ err: error
169
+ }, "getRecentJitoTips failed");
156
170
  return undefined;
157
171
  }
158
172
  }
159
173
  async updatePriceFeed(priceIds) {
160
174
  const recentJitoTip = await this.getRecentJitoTipLamports();
161
- const jitoTip = this.dynamicJitoTips && recentJitoTip !== undefined
162
- ? Math.max(this.defaultJitoTipLamports, recentJitoTip)
163
- : this.defaultJitoTipLamports;
175
+ const jitoTip = this.dynamicJitoTips && recentJitoTip !== undefined ? Math.max(this.defaultJitoTipLamports, recentJitoTip) : this.defaultJitoTipLamports;
164
176
  const cappedJitoTip = Math.min(jitoTip, this.maxJitoTipLamports);
165
- this.logger.info({ cappedJitoTip }, "using jito tip of");
177
+ this.logger.info({
178
+ cappedJitoTip
179
+ }, "using jito tip of");
166
180
  let priceFeedUpdateData;
167
181
  try {
168
182
  const response = await this.hermesClient.getLatestPriceUpdates(priceIds, {
169
- encoding: "base64",
183
+ encoding: "base64"
170
184
  });
171
185
  priceFeedUpdateData = response.binary.data;
172
- }
173
- catch (err) {
174
- this.logger.error(err, "getPriceFeedsUpdateData failed");
186
+ } catch (error) {
187
+ this.logger.error(error, "getPriceFeedsUpdateData failed");
175
188
  return;
176
189
  }
177
- for (let i = 0; i < priceIds.length; i += this.updatesPerJitoBundle) {
190
+ for(let i = 0; i < priceIds.length; i += this.updatesPerJitoBundle){
178
191
  const transactionBuilder = this.pythSolanaReceiver.newTransactionBuilder({
179
- closeUpdateAccounts: true,
192
+ closeUpdateAccounts: true
180
193
  }, this.addressLookupTableAccount);
181
- await transactionBuilder.addUpdatePriceFeed(priceFeedUpdateData.map((x) => {
182
- return (0, price_service_sdk_1.sliceAccumulatorUpdateData)(Buffer.from(x, "base64"), i, i + this.updatesPerJitoBundle).toString("base64");
194
+ await transactionBuilder.addUpdatePriceFeed(priceFeedUpdateData.map((x)=>{
195
+ return (0, _priceservicesdk.sliceAccumulatorUpdateData)(Buffer.from(x, "base64"), i, i + this.updatesPerJitoBundle).toString("base64");
183
196
  }), this.shardId);
184
197
  const transactions = await transactionBuilder.buildVersionedTransactions({
185
198
  jitoTipLamports: cappedJitoTip,
186
- tightComputeBudget: true,
199
+ tightComputeBudget: true
187
200
  });
188
- await (0, solana_utils_1.sendTransactionsJito)(transactions, this.searcherClients, this.pythSolanaReceiver.wallet, {
189
- maxRetryTimeMs: this.maxRetryTimeMs,
201
+ await (0, _solanautils.sendTransactionsJito)(transactions, this.searcherClients, this.pythSolanaReceiver.wallet, {
202
+ maxRetryTimeMs: this.maxRetryTimeMs
190
203
  }, this.logger);
191
204
  }
192
205
  }
193
206
  }
194
- exports.SolanaPricePusherJito = SolanaPricePusherJito;
@@ -1,10 +1,11 @@
1
- import { PythSolanaReceiver } from "@pythnetwork/pyth-solana-receiver";
2
- import { ChainPriceListener, IPricePusher, PriceInfo, PriceItem } from "../interface";
3
- import { DurationInSeconds } from "../utils";
4
1
  import { HermesClient } from "@pythnetwork/hermes-client";
5
- import { SearcherClient } from "jito-ts/dist/sdk/block-engine/searcher";
6
- import { Logger } from "pino";
2
+ import { PythSolanaReceiver } from "@pythnetwork/pyth-solana-receiver";
7
3
  import { AddressLookupTableAccount } from "@solana/web3.js";
4
+ import { SearcherClient } from "jito-ts/dist/sdk/block-engine/searcher";
5
+ import type { Logger } from "pino";
6
+ import type { IPricePusher, PriceInfo, PriceItem } from "../interface.js";
7
+ import { ChainPriceListener } from "../interface.js";
8
+ import type { DurationInSeconds } from "../utils.js";
8
9
  export declare class SolanaPriceListener extends ChainPriceListener {
9
10
  private pythSolanaReceiver;
10
11
  private shardId;
@@ -42,4 +43,3 @@ export declare class SolanaPricePusherJito implements IPricePusher {
42
43
  getRecentJitoTipLamports(): Promise<number | undefined>;
43
44
  updatePriceFeed(priceIds: string[]): Promise<void>;
44
45
  }
45
- //# sourceMappingURL=solana.d.ts.map
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: Object.getOwnPropertyDescriptor(all, name).get
9
+ });
10
+ }
11
+ _export(exports, {
12
+ get SuiBalanceTracker () {
13
+ return SuiBalanceTracker;
14
+ },
15
+ get createSuiBalanceTracker () {
16
+ return createSuiBalanceTracker;
17
+ }
18
+ });
19
+ const _interface = require("../interface.cjs");
20
+ class SuiBalanceTracker extends _interface.BaseBalanceTracker {
21
+ client;
22
+ constructor(config){
23
+ super({
24
+ ...config,
25
+ logger: config.logger.child({
26
+ module: "SuiBalanceTracker"
27
+ })
28
+ });
29
+ this.client = config.client;
30
+ }
31
+ /**
32
+ * Sui-specific implementation of balance update
33
+ */ async updateBalance() {
34
+ try {
35
+ const balance = await this.client.getBalance({
36
+ owner: this.address
37
+ });
38
+ // Convert to a normalized number for reporting (SUI has 9 decimals)
39
+ const normalizedBalance = Number(balance.totalBalance) / 1e9;
40
+ this.metrics.updateWalletBalance(this.address, this.network, normalizedBalance);
41
+ this.logger.debug(`Updated Sui wallet balance: ${this.address} = ${normalizedBalance.toString()} SUI`);
42
+ } catch (error) {
43
+ this.logger.error({
44
+ error
45
+ }, "Error fetching Sui wallet balance for metrics");
46
+ }
47
+ }
48
+ }
49
+ function createSuiBalanceTracker(params) {
50
+ return new SuiBalanceTracker({
51
+ client: params.client,
52
+ address: params.address,
53
+ network: params.network,
54
+ updateInterval: params.updateInterval,
55
+ metrics: params.metrics,
56
+ logger: params.logger
57
+ });
58
+ }
@@ -1,15 +1,16 @@
1
1
  import { SuiClient } from "@mysten/sui/client";
2
- import { BaseBalanceTracker, BaseBalanceTrackerConfig, IBalanceTracker } from "../interface";
3
- import { DurationInSeconds } from "../utils";
4
- import { PricePusherMetrics } from "../metrics";
5
- import { Logger } from "pino";
2
+ import type { Logger } from "pino";
3
+ import type { BaseBalanceTrackerConfig, IBalanceTracker } from "../interface.js";
4
+ import { BaseBalanceTracker } from "../interface.js";
5
+ import { PricePusherMetrics } from "../metrics.js";
6
+ import type { DurationInSeconds } from "../utils.js";
6
7
  /**
7
8
  * Sui-specific configuration for balance tracker
8
9
  */
9
- export interface SuiBalanceTrackerConfig extends BaseBalanceTrackerConfig {
10
+ export type SuiBalanceTrackerConfig = {
10
11
  /** Sui client instance */
11
12
  client: SuiClient;
12
- }
13
+ } & BaseBalanceTrackerConfig;
13
14
  /**
14
15
  * Sui-specific implementation of the balance tracker
15
16
  */
@@ -24,16 +25,15 @@ export declare class SuiBalanceTracker extends BaseBalanceTracker {
24
25
  /**
25
26
  * Parameters for creating a Sui balance tracker
26
27
  */
27
- export interface CreateSuiBalanceTrackerParams {
28
+ export type CreateSuiBalanceTrackerParams = {
28
29
  client: SuiClient;
29
30
  address: string;
30
31
  network: string;
31
32
  updateInterval: DurationInSeconds;
32
33
  metrics: PricePusherMetrics;
33
34
  logger: Logger;
34
- }
35
+ };
35
36
  /**
36
37
  * Factory function to create a balance tracker for Sui chain
37
38
  */
38
39
  export declare function createSuiBalanceTracker(params: CreateSuiBalanceTrackerParams): IBalanceTracker;
39
- //# sourceMappingURL=balance-tracker.d.ts.map