瀏覽代碼

chore: linting and typechecking yak shaving to the nth degree

benduran 3 周之前
父節點
當前提交
a615b5a17f
共有 100 個文件被更改,包括 1274 次插入1104 次删除
  1. 1 1
      apps/api-reference/package.json
  2. 2 7
      apps/api-reference/tsconfig.build.json
  3. 1 1
      apps/developer-hub/package.json
  4. 2 7
      apps/developer-hub/tsconfig.build.json
  5. 1 1
      apps/entropy-explorer/package.json
  6. 2 7
      apps/entropy-explorer/tsconfig.build.json
  7. 1 1
      apps/entropy-tester/package.json
  8. 2 7
      apps/entropy-tester/tsconfig.build.json
  9. 1 1
      apps/insights/package.json
  10. 2 7
      apps/insights/tsconfig.build.json
  11. 1 1
      apps/price_pusher/package.json
  12. 35 34
      apps/price_pusher/src/aptos/aptos.ts
  13. 11 10
      apps/price_pusher/src/aptos/balance-tracker.ts
  14. 15 8
      apps/price_pusher/src/aptos/command.ts
  15. 7 8
      apps/price_pusher/src/controller.ts
  16. 11 10
      apps/price_pusher/src/evm/balance-tracker.ts
  17. 15 8
      apps/price_pusher/src/evm/command.ts
  18. 11 10
      apps/price_pusher/src/evm/custom-gas-station.ts
  19. 60 63
      apps/price_pusher/src/evm/evm.ts
  20. 3 1
      apps/price_pusher/src/evm/pyth-contract.ts
  21. 13 9
      apps/price_pusher/src/evm/super-wallet.ts
  22. 11 5
      apps/price_pusher/src/fuel/command.ts
  23. 24 15
      apps/price_pusher/src/fuel/fuel.ts
  24. 11 8
      apps/price_pusher/src/index.ts
  25. 12 7
      apps/price_pusher/src/injective/command.ts
  26. 40 37
      apps/price_pusher/src/injective/injective.ts
  27. 13 12
      apps/price_pusher/src/interface.ts
  28. 14 11
      apps/price_pusher/src/metrics.ts
  29. 8 4
      apps/price_pusher/src/near/command.ts
  30. 45 40
      apps/price_pusher/src/near/near.ts
  31. 13 9
      apps/price_pusher/src/price-config.ts
  32. 34 31
      apps/price_pusher/src/pyth-price-listener.ts
  33. 12 11
      apps/price_pusher/src/solana/balance-tracker.ts
  34. 33 19
      apps/price_pusher/src/solana/command.ts
  35. 45 44
      apps/price_pusher/src/solana/solana.ts
  36. 12 11
      apps/price_pusher/src/sui/balance-tracker.ts
  37. 17 10
      apps/price_pusher/src/sui/command.ts
  38. 47 47
      apps/price_pusher/src/sui/sui.ts
  39. 10 5
      apps/price_pusher/src/ton/command.ts
  40. 23 26
      apps/price_pusher/src/ton/ton.ts
  41. 15 7
      apps/price_pusher/src/utils.ts
  42. 1 1
      apps/staking/package.json
  43. 2 7
      apps/staking/tsconfig.build.json
  44. 11 13
      contract_manager/scripts/batchDeployReceivers.ts
  45. 18 13
      contract_manager/scripts/check_proposal.ts
  46. 14 13
      contract_manager/scripts/common.ts
  47. 2 1
      contract_manager/scripts/deploy_cosmwasm.ts
  48. 7 6
      contract_manager/scripts/deploy_evm_contract.ts
  49. 16 15
      contract_manager/scripts/deploy_evm_entropy_contracts.ts
  50. 5 4
      contract_manager/scripts/deploy_evm_executor_contracts.ts
  51. 7 5
      contract_manager/scripts/deploy_evm_lazer_contracts.ts
  52. 6 5
      contract_manager/scripts/deploy_evm_pricefeed_contracts.ts
  53. 8 6
      contract_manager/scripts/deploy_evm_pulse_contracts.ts
  54. 3 2
      contract_manager/scripts/entropy-accept-admin-and-ownership.ts
  55. 9 8
      contract_manager/scripts/entropy_debug_reveal.ts
  56. 11 19
      contract_manager/scripts/execute_vaas.ts
  57. 3 2
      contract_manager/scripts/fetch_account_balance.ts
  58. 4 3
      contract_manager/scripts/fetch_accrued_entropy_dao_fees.ts
  59. 3 2
      contract_manager/scripts/fetch_fees.ts
  60. 3 2
      contract_manager/scripts/generate_evm_lazer_update_trusted_signer_proposal.ts
  61. 2 1
      contract_manager/scripts/generate_governance_set_fee_payload.ts
  62. 4 3
      contract_manager/scripts/generate_upgrade_near_contract_proposal.ts
  63. 8 6
      contract_manager/scripts/generate_upgrade_ton_contract_proposal.ts
  64. 3 2
      contract_manager/scripts/get_entropy_registration.ts
  65. 7 6
      contract_manager/scripts/latency_entropy.ts
  66. 4 3
      contract_manager/scripts/latency_entropy_with_callback.ts
  67. 6 5
      contract_manager/scripts/list_entropy_contracts.ts
  68. 4 3
      contract_manager/scripts/list_evm_contracts.ts
  69. 4 3
      contract_manager/scripts/list_wormhole_contracts.ts
  70. 5 4
      contract_manager/scripts/load_test_entropy.ts
  71. 1 0
      contract_manager/scripts/send_message_to_wormhole.ts
  72. 7 6
      contract_manager/scripts/sync_governance_vaas.ts
  73. 6 5
      contract_manager/scripts/sync_wormhole_guardian_set.ts
  74. 15 14
      contract_manager/scripts/transfer_balance_entropy_chains.ts
  75. 3 2
      contract_manager/scripts/update_all_pricefeeds.ts
  76. 3 2
      contract_manager/scripts/update_pricefeed.ts
  77. 11 10
      contract_manager/scripts/upgrade_evm_entropy_contracts.ts
  78. 8 7
      contract_manager/scripts/upgrade_evm_pricefeed_contracts.ts
  79. 8 5
      contract_manager/scripts/upgrade_ton_contract.ts
  80. 2 1
      contract_manager/scripts/upload_cosmwasm.ts
  81. 4 3
      contract_manager/src/core/base.ts
  82. 43 44
      contract_manager/src/core/chains.ts
  83. 12 10
      contract_manager/src/core/contracts/aptos.ts
  84. 31 29
      contract_manager/src/core/contracts/cosmwasm.ts
  85. 11 9
      contract_manager/src/core/contracts/evm.ts
  86. 2 1
      contract_manager/src/core/contracts/evm_abis.ts
  87. 21 20
      contract_manager/src/core/contracts/fuel.ts
  88. 37 37
      contract_manager/src/core/contracts/iota.ts
  89. 40 39
      contract_manager/src/core/contracts/near.ts
  90. 23 14
      contract_manager/src/core/contracts/starknet.ts
  91. 37 37
      contract_manager/src/core/contracts/sui.ts
  92. 6 4
      contract_manager/src/core/contracts/wormhole.ts
  93. 8 3
      contract_manager/src/core/token.ts
  94. 7 5
      contract_manager/src/node/utils/executor.ts
  95. 62 45
      contract_manager/src/node/utils/governance.ts
  96. 33 23
      contract_manager/src/node/utils/store.ts
  97. 5 3
      contract_manager/src/utils/utils.ts
  98. 4 0
      governance/pyth_staking_sdk/src/utils/transaction.ts
  99. 4 1
      governance/xc_admin/packages/xc_admin_common/src/message_buffer.ts
  100. 4 1
      governance/xc_admin/packages/xc_admin_common/src/multisig.ts

+ 1 - 1
apps/api-reference/package.json

@@ -66,4 +66,4 @@
     "vercel": "catalog:"
   },
   "packageManager": "pnpm@10.19.0"
-}
+}

+ 2 - 7
apps/api-reference/tsconfig.build.json

@@ -5,10 +5,5 @@
     "incremental": false,
     "declaration": true
   },
-  "exclude": [
-    "node_modules",
-    "dist",
-    "examples/",
-    "**/__tests__/*"
-  ]
-}
+  "exclude": ["node_modules", "dist", "examples/", "**/__tests__/*"]
+}

+ 1 - 1
apps/developer-hub/package.json

@@ -74,4 +74,4 @@
     "vercel": "catalog:"
   },
   "packageManager": "pnpm@10.19.0"
-}
+}

+ 2 - 7
apps/developer-hub/tsconfig.build.json

@@ -5,10 +5,5 @@
     "incremental": false,
     "declaration": true
   },
-  "exclude": [
-    "node_modules",
-    "dist",
-    "examples/",
-    "**/__tests__/*"
-  ]
-}
+  "exclude": ["node_modules", "dist", "examples/", "**/__tests__/*"]
+}

+ 1 - 1
apps/entropy-explorer/package.json

@@ -54,4 +54,4 @@
     "vercel": "catalog:"
   },
   "packageManager": "pnpm@10.19.0"
-}
+}

+ 2 - 7
apps/entropy-explorer/tsconfig.build.json

@@ -5,10 +5,5 @@
     "incremental": false,
     "declaration": true
   },
-  "exclude": [
-    "node_modules",
-    "dist",
-    "examples/",
-    "**/__tests__/*"
-  ]
-}
+  "exclude": ["node_modules", "dist", "examples/", "**/__tests__/*"]
+}

+ 1 - 1
apps/entropy-tester/package.json

@@ -67,4 +67,4 @@
     "pnpm": ">=10.19.0"
   },
   "packageManager": "pnpm@10.19.0"
-}
+}

+ 2 - 7
apps/entropy-tester/tsconfig.build.json

@@ -7,10 +7,5 @@
     "declaration": true,
     "isolatedModules": false
   },
-  "exclude": [
-    "node_modules",
-    "dist",
-    "examples/",
-    "**/__tests__/*"
-  ]
-}
+  "exclude": ["node_modules", "dist", "examples/", "**/__tests__/*"]
+}

+ 1 - 1
apps/insights/package.json

@@ -75,4 +75,4 @@
     "vercel": "catalog:"
   },
   "packageManager": "pnpm@10.19.0"
-}
+}

+ 2 - 7
apps/insights/tsconfig.build.json

@@ -5,10 +5,5 @@
     "incremental": false,
     "declaration": true
   },
-  "exclude": [
-    "node_modules",
-    "dist",
-    "examples/",
-    "**/__tests__/*"
-  ]
-}
+  "exclude": ["node_modules", "dist", "examples/", "**/__tests__/*"]
+}

+ 1 - 1
apps/price_pusher/package.json

@@ -233,4 +233,4 @@
     "./package.json": "./package.json"
   },
   "module": "./dist/esm/index.js"
-}
+}

+ 35 - 34
apps/price_pusher/src/aptos/aptos.ts

@@ -1,14 +1,17 @@
-import {
-  ChainPriceListener,
-  type IPricePusher,
-  type PriceInfo,
-  type PriceItem,
-} from "../interface.js";
-import { AptosAccount, AptosClient } from "aptos";
-import type { DurationInSeconds } from "../utils.js";
+/* eslint-disable @typescript-eslint/restrict-template-expressions */
+/* eslint-disable unicorn/no-await-expression-member */
+/* eslint-disable @typescript-eslint/no-unsafe-argument */
+/* eslint-disable @typescript-eslint/no-explicit-any */
+/* eslint-disable @typescript-eslint/no-unsafe-member-access */
+/* eslint-disable @typescript-eslint/no-unsafe-assignment */
 import { HermesClient } from "@pythnetwork/hermes-client";
+import { AptosAccount, AptosClient } from "aptos";
 import type { Logger } from "pino";
 
+import type { IPricePusher, PriceInfo, PriceItem } from "../interface.js";
+import { ChainPriceListener } from "../interface.js";
+import type { DurationInSeconds } from "../utils.js";
+
 export class AptosPriceListener extends ChainPriceListener {
   constructor(
     private pythModule: string,
@@ -49,9 +52,9 @@ export class AptosPriceListener extends ChainPriceListener {
         multiplier * Number(priceItemRes.price_feed.price.price.magnitude);
 
       this.logger.debug(
-        `Polled an Aptos on-chain price for feed ${this.priceIdToAlias.get(
-          priceId,
-        )} (${priceId}).`,
+        `Polled an Aptos on-chain price for feed ${
+          this.priceIdToAlias.get(priceId) ?? ""
+        } (${priceId}).`,
       );
 
       return {
@@ -59,9 +62,9 @@ export class AptosPriceListener extends ChainPriceListener {
         conf: priceItemRes.price_feed.price.conf,
         publishTime: Number(priceItemRes.price_feed.price.timestamp),
       };
-    } catch (err) {
+    } catch (error) {
       this.logger.error(
-        err,
+        error,
         `Polling Aptos on-chain price for ${priceId} failed.`,
       );
       return undefined;
@@ -104,7 +107,7 @@ export class AptosPricePusher implements IPricePusher {
    * Gets price update data which then can be submitted to the Pyth contract to update the prices.
    * This will throw an axios error if there is a network problem or the price service returns a non-ok response (e.g: Invalid price ids)
    *
-   * @param priceIds Array of hex-encoded price ids.
+   * @param priceIds - Array of hex-encoded price ids.
    * @returns Array of price update data.
    */
   async getPriceFeedsUpdateData(priceIds: string[]): Promise<number[][]> {
@@ -112,9 +115,7 @@ export class AptosPricePusher implements IPricePusher {
       encoding: "base64",
       ignoreInvalidPriceIds: true,
     });
-    return response.binary.data.map((data) =>
-      Array.from(Buffer.from(data, "base64")),
-    );
+    return response.binary.data.map((data) => [...Buffer.from(data, "base64")]);
   }
 
   async updatePriceFeed(
@@ -132,8 +133,8 @@ export class AptosPricePusher implements IPricePusher {
     try {
       // get the latest VAAs for updatePriceFeed and then push them
       priceFeedUpdateData = await this.getPriceFeedsUpdateData(priceIds);
-    } catch (err) {
-      this.logger.error(err, "Error fetching the latest vaas to push.");
+    } catch (error) {
+      this.logger.error(error, "Error fetching the latest vaas to push.");
       return;
     }
 
@@ -152,7 +153,7 @@ export class AptosPricePusher implements IPricePusher {
         arguments: [priceFeedUpdateData],
       },
       {
-        sequence_number: sequenceNumber.toFixed(),
+        sequence_number: sequenceNumber.toFixed(0),
       },
     );
 
@@ -169,11 +170,11 @@ export class AptosPricePusher implements IPricePusher {
       // to go out of sync. Missing transactions are rare and we don't want this check to block
       // the next price update. So we use spawn a promise without awaiting on it to wait for the
       // transaction to be confirmed and if it fails, it resets the sequence number and return.
-      this.waitForTransactionConfirmation(client, pendingTx.hash);
+      void this.waitForTransactionConfirmation(client, pendingTx.hash);
 
       return;
-    } catch (err: any) {
-      this.logger.error(err, "Error executing messages");
+    } catch (error: any) {
+      this.logger.error(error, "Error executing messages");
 
       // Reset the sequence number to re-sync it (in case that was the issue)
       this.lastSequenceNumber = undefined;
@@ -194,9 +195,9 @@ export class AptosPricePusher implements IPricePusher {
       });
 
       this.logger.info({ hash: txHash }, `Transaction confirmed.`);
-    } catch (err) {
+    } catch (error) {
       this.logger.error(
-        { err, hash: txHash },
+        { err: error, hash: txHash },
         `Transaction failed to confirm.`,
       );
 
@@ -211,14 +212,13 @@ export class AptosPricePusher implements IPricePusher {
     client: AptosClient,
     account: AptosAccount,
   ): Promise<number> {
-    if (this.lastSequenceNumber !== undefined) {
-      this.lastSequenceNumber += 1;
-      return this.lastSequenceNumber;
-    } else {
+    if (this.lastSequenceNumber === undefined) {
       // Fetch from the blockchain if we don't have the local cache.
       // Note that this is locked so that only 1 fetch occurs regardless of how many updates
       // happen during that fetch.
-      if (!this.sequenceNumberLocked) {
+      if (this.sequenceNumberLocked) {
+        throw new Error("Waiting for sequence number in another thread.");
+      } else {
         try {
           this.sequenceNumberLocked = true;
           this.lastSequenceNumber = Number(
@@ -228,14 +228,15 @@ export class AptosPricePusher implements IPricePusher {
             `Fetched account sequence number: ${this.lastSequenceNumber}`,
           );
           return this.lastSequenceNumber;
-        } catch (e: any) {
-          throw new Error("Failed to retrieve sequence number" + e);
+        } catch (error: any) {
+          throw new Error(`Failed to retrieve sequence number ${error}`);
         } finally {
           this.sequenceNumberLocked = false;
         }
-      } else {
-        throw new Error("Waiting for sequence number in another thread.");
       }
+    } else {
+      this.lastSequenceNumber += 1;
+      return this.lastSequenceNumber;
     }
   }
 }

+ 11 - 10
apps/price_pusher/src/aptos/balance-tracker.ts

@@ -1,24 +1,25 @@
 import { Aptos, AptosConfig, Network } from "@aptos-labs/ts-sdk";
-import {
-  BaseBalanceTracker,
-  type BaseBalanceTrackerConfig,
-  type IBalanceTracker,
+import type { Logger } from "pino";
+
+import type {
+  BaseBalanceTrackerConfig,
+  IBalanceTracker,
 } from "../interface.js";
-import type { DurationInSeconds } from "../utils.js";
+import { BaseBalanceTracker } from "../interface.js";
 import { PricePusherMetrics } from "../metrics.js";
-import type { Logger } from "pino";
+import type { DurationInSeconds } from "../utils.js";
 
 /**
  * Aptos-specific configuration for balance tracker
  */
-export interface AptosBalanceTrackerConfig extends BaseBalanceTrackerConfig {
+export type AptosBalanceTrackerConfig = {
   /** Aptos node endpoint URL */
   endpoint: string;
   /** Aptos account address */
   address: string;
   /** Optional decimal places for APT token (default: 8) */
   decimals?: number;
-}
+} & BaseBalanceTrackerConfig;
 
 /**
  * Aptos-specific implementation of the balance tracker
@@ -80,7 +81,7 @@ export class AptosBalanceTracker extends BaseBalanceTracker {
 /**
  * Parameters for creating an Aptos balance tracker
  */
-export interface CreateAptosBalanceTrackerParams {
+export type CreateAptosBalanceTrackerParams = {
   endpoint: string;
   address: string;
   network: string;
@@ -88,7 +89,7 @@ export interface CreateAptosBalanceTrackerParams {
   metrics: PricePusherMetrics;
   logger: Logger;
   decimals?: number;
-}
+};
 
 /**
  * Factory function to create a balance tracker for Aptos chain

+ 15 - 8
apps/price_pusher/src/aptos/command.ts

@@ -1,19 +1,26 @@
+/* eslint-disable @typescript-eslint/no-non-null-assertion */
+/* 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 */
+import fs from "node:fs";
+
 import { HermesClient } from "@pythnetwork/hermes-client";
+import { AptosAccount } from "aptos";
+import pino from "pino";
+import type { Options } from "yargs";
+
+import { Controller } from "../controller.js";
+import { PricePusherMetrics } from "../metrics.js";
 import * as options from "../options.js";
 import { readPriceConfigFile } from "../price-config.js";
-import fs from "fs";
 import { PythPriceListener } from "../pyth-price-listener.js";
-import { Controller } from "../controller.js";
-import type { Options } from "yargs";
 import {
   AptosPriceListener,
   AptosPricePusher,
   APTOS_ACCOUNT_HD_PATH,
 } from "./aptos.js";
-import { AptosAccount } from "aptos";
-import pino from "pino";
 import { filterInvalidPriceItems } from "../utils.js";
-import { PricePusherMetrics } from "../metrics.js";
 import { createAptosBalanceTracker } from "./balance-tracker.js";
 
 export default {
@@ -76,7 +83,7 @@ export default {
       logger.info(`Metrics server started on port ${metricsPort}`);
     }
 
-    const mnemonic = fs.readFileSync(mnemonicFile, "utf-8").trim();
+    const mnemonic = fs.readFileSync(mnemonicFile, "utf8").trim();
     const account = AptosAccount.fromDerivePath(
       APTOS_ACCOUNT_HD_PATH,
       mnemonic,
@@ -149,6 +156,6 @@ export default {
       await balanceTracker.start();
     }
 
-    controller.start();
+    void controller.start();
   },
 };

+ 7 - 8
apps/price_pusher/src/controller.ts

@@ -1,13 +1,12 @@
 import type { UnixTimestamp } from "@pythnetwork/hermes-client";
-import { type DurationInSeconds, sleep } from "./utils.js";
-import type { IPriceListener, IPricePusher } from "./interface.js";
-import {
-  type PriceConfig,
-  shouldUpdate,
-  UpdateCondition,
-} from "./price-config.js";
 import type { Logger } from "pino";
+
+import type { IPriceListener, IPricePusher } from "./interface.js";
 import { PricePusherMetrics } from "./metrics.js";
+import type { PriceConfig } from "./price-config.js";
+import { shouldUpdate, UpdateCondition } from "./price-config.js";
+import type { DurationInSeconds } from "./utils.js";
+import { sleep } from "./utils.js";
 
 export class Controller {
   private pushingFrequency: DurationInSeconds;
@@ -94,7 +93,7 @@ export class Controller {
           priceShouldUpdate == UpdateCondition.EARLY
         ) {
           pricesToPush.push(priceConfig);
-          pubTimesToPush.push((targetLatestPrice?.publishTime || 0) + 1);
+          pubTimesToPush.push((targetLatestPrice?.publishTime ?? 0) + 1);
         }
       }
       if (pushThresholdMet) {

+ 11 - 10
apps/price_pusher/src/evm/balance-tracker.ts

@@ -1,22 +1,23 @@
+import type { Logger } from "pino";
+
 import type { SuperWalletClient } from "./super-wallet.js";
-import {
-  BaseBalanceTracker,
-  type BaseBalanceTrackerConfig,
-  type IBalanceTracker,
+import type {
+  BaseBalanceTrackerConfig,
+  IBalanceTracker,
 } from "../interface.js";
-import type { DurationInSeconds } from "../utils.js";
+import { BaseBalanceTracker } from "../interface.js";
 import { PricePusherMetrics } from "../metrics.js";
-import type { Logger } from "pino";
+import type { DurationInSeconds } from "../utils.js";
 
 /**
  * EVM-specific configuration for balance tracker
  */
-export interface EvmBalanceTrackerConfig extends BaseBalanceTrackerConfig {
+export type EvmBalanceTrackerConfig = {
   /** EVM wallet client */
   client: SuperWalletClient;
   /** EVM address with 0x prefix */
   address: `0x${string}`;
-}
+} & BaseBalanceTrackerConfig;
 
 /**
  * EVM-specific implementation of the balance tracker
@@ -60,14 +61,14 @@ export class EvmBalanceTracker extends BaseBalanceTracker {
 /**
  * Parameters for creating an EVM balance tracker
  */
-export interface CreateEvmBalanceTrackerParams {
+export type CreateEvmBalanceTrackerParams = {
   client: SuperWalletClient;
   address: `0x${string}`;
   network: string;
   updateInterval: DurationInSeconds;
   metrics: PricePusherMetrics;
   logger: Logger;
-}
+};
 
 /**
  * Factory function to create a balance tracker for EVM chains

+ 15 - 8
apps/price_pusher/src/evm/command.ts

@@ -1,17 +1,24 @@
+/* eslint-disable @typescript-eslint/no-non-null-assertion */
+/* 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 */
+import fs from "node:fs";
+
 import { HermesClient } from "@pythnetwork/hermes-client";
-import fs from "fs";
+import pino from "pino";
 import type { Options } from "yargs";
+
+import { Controller } from "../controller.js";
 import * as options from "../options.js";
 import { readPriceConfigFile } from "../price-config.js";
 import { PythPriceListener } from "../pyth-price-listener.js";
-import { Controller } from "../controller.js";
-import { EvmPriceListener, EvmPricePusher } from "./evm.js";
 import { getCustomGasStation } from "./custom-gas-station.js";
-import pino from "pino";
-import { createClient } from "./super-wallet.js";
+import { EvmPriceListener, EvmPricePusher } from "./evm.js";
 import { createPythContract } from "./pyth-contract.js";
-import { isWsEndpoint, filterInvalidPriceItems } from "../utils.js";
+import { createClient } from "./super-wallet.js";
 import { PricePusherMetrics } from "../metrics.js";
+import { isWsEndpoint, filterInvalidPriceItems } from "../utils.js";
 import { createEvmBalanceTracker } from "./balance-tracker.js";
 
 export default {
@@ -118,7 +125,7 @@ export default {
     const priceConfigs = readPriceConfigFile(priceConfigFile);
     const hermesClient = new HermesClient(priceServiceEndpoint);
 
-    const mnemonic = fs.readFileSync(mnemonicFile, "utf-8").trim();
+    const mnemonic = fs.readFileSync(mnemonicFile, "utf8").trim();
 
     let priceItems = priceConfigs.map(({ id, alias }) => ({ id, alias }));
 
@@ -217,6 +224,6 @@ export default {
       await balanceTracker.start();
     }
 
-    await controller.start();
+    void controller.start();
   },
 };

+ 11 - 10
apps/price_pusher/src/evm/custom-gas-station.ts

@@ -1,13 +1,14 @@
-import {
-  type CustomGasChainId,
-  type TxSpeed,
-  verifyValidOption,
-  txSpeeds,
-  customGasChainIds,
-} from "../utils.js";
+/* eslint-disable @typescript-eslint/no-explicit-any */
+/* eslint-disable @typescript-eslint/no-unsafe-call */
+/* eslint-disable @typescript-eslint/no-unsafe-argument */
+/* eslint-disable @typescript-eslint/no-unsafe-member-access */
+/* eslint-disable @typescript-eslint/no-unsafe-assignment */
 import type { Logger } from "pino";
 import { parseGwei } from "viem";
 
+import type { CustomGasChainId, TxSpeed } from "../utils.js";
+import { verifyValidOption, txSpeeds, customGasChainIds } from "../utils.js";
+
 type chainMethods = Record<CustomGasChainId, () => Promise<bigint | undefined>>;
 
 export class CustomGasStation {
@@ -34,12 +35,12 @@ export class CustomGasStation {
       const jsonRes = (await res.json()) as any;
       const gasPrice = jsonRes[this.speed].maxFee;
       return parseGwei(gasPrice.toFixed(2));
-    } catch (err) {
+    } catch (error) {
       this.logger.error(
-        err,
+        error,
         "Failed to fetch gas price from Matic mainnet. Returning undefined",
       );
-      return undefined;
+      return;
     }
   }
 }

+ 60 - 63
apps/price_pusher/src/evm/evm.ts

@@ -1,26 +1,13 @@
-import {
-  type IPricePusher,
-  type PriceInfo,
-  ChainPriceListener,
-  type PriceItem,
-} from "../interface.js";
-import {
-  addLeading0x,
-  assertDefined,
-  type DurationInSeconds,
-  removeLeading0x,
-} from "../utils.js";
-import { PythAbi } from "./pyth-abi.js";
+/* eslint-disable @typescript-eslint/no-unsafe-member-access */
+/* eslint-disable @typescript-eslint/no-unsafe-assignment */
+/* eslint-disable @typescript-eslint/no-explicit-any */
+/* eslint-disable @typescript-eslint/restrict-template-expressions */
+/* eslint-disable @typescript-eslint/require-await */
+import type { HexString, UnixTimestamp } from "@pythnetwork/hermes-client";
+import { HermesClient } from "@pythnetwork/hermes-client";
 import type { Logger } from "pino";
+import type { WatchContractEventOnLogsParameter } from "viem";
 import {
-  HermesClient,
-  type HexString,
-  type UnixTimestamp,
-} from "@pythnetwork/hermes-client";
-import { CustomGasStation } from "./custom-gas-station";
-import type { PushAttempt } from "../common.js";
-import {
-  type WatchContractEventOnLogsParameter,
   TransactionExecutionError,
   BaseError,
   ContractFunctionRevertedError,
@@ -30,8 +17,15 @@ import {
   ContractFunctionExecutionError,
 } from "viem";
 
+import type { PushAttempt } from "../common.js";
+import type { IPricePusher, PriceInfo, PriceItem } from "../interface.js";
+import type { DurationInSeconds } from "../utils.js";
+import { CustomGasStation } from "./custom-gas-station";
 import type { PythContract } from "./pyth-contract.js";
+import { addLeading0x, assertDefined, removeLeading0x } from "../utils.js";
+import { PythAbi } from "./pyth-abi.js";
 import type { SuperWalletClient } from "./super-wallet.js";
+import { ChainPriceListener } from "../interface.js";
 
 export class EvmPriceListener extends ChainPriceListener {
   constructor(
@@ -54,7 +48,7 @@ export class EvmPriceListener extends ChainPriceListener {
   override async start() {
     if (this.watchEvents) {
       this.logger.info("Watching target network pyth contract events...");
-      this.startWatching();
+      void this.startWatching();
     } else {
       this.logger.info(
         "The target network RPC endpoint is not Websocket. " +
@@ -104,8 +98,8 @@ export class EvmPriceListener extends ChainPriceListener {
       priceRaw = await this.pythContract.read.getPriceUnsafe([
         addLeading0x(priceId),
       ]);
-    } catch (err) {
-      this.logger.error(err, `Polling on-chain price for ${priceId} failed.`);
+    } catch (error) {
+      this.logger.error(error, `Polling on-chain price for ${priceId} failed.`);
       return undefined;
     }
 
@@ -175,12 +169,12 @@ export class EvmPricePusher implements IPricePusher {
         Math.round(Number(updateFee) * (this.updateFeeMultiplier || 1)),
       );
       this.logger.debug(`Update fee: ${updateFee}`);
-    } catch (e: any) {
+    } catch (error: any) {
       this.logger.error(
-        e,
+        error,
         "An unidentified error has occured when getting the update fee.",
       );
-      throw e;
+      throw error;
     }
 
     // Gas price in networks with transaction type eip1559 represents the
@@ -195,9 +189,7 @@ export class EvmPricePusher implements IPricePusher {
       );
 
     // Try to re-use the same nonce and increase the gas if the last tx is not landed yet.
-    if (this.pusherAddress === undefined) {
-      this.pusherAddress = this.client.account.address;
-    }
+    this.pusherAddress ??= this.client.account.address;
 
     const lastExecutedNonce =
       (await this.client.getTransactionCount({
@@ -229,9 +221,7 @@ export class EvmPricePusher implements IPricePusher {
 
     this.logger.debug(`Using gas price: ${gasPrice} and nonce: ${txNonce}`);
 
-    const pubTimesToPushParam = pubTimesToPush.map((pubTime) =>
-      BigInt(pubTime),
-    );
+    const pubTimesToPushParam = pubTimesToPush.map(BigInt);
 
     const priceIdsWith0x = priceIds.map((priceId) => addLeading0x(priceId));
 
@@ -250,9 +240,9 @@ export class EvmPricePusher implements IPricePusher {
             gasPrice: BigInt(Math.ceil(gasPrice)),
             nonce: txNonce,
             gas:
-              this.gasLimit !== undefined
-                ? BigInt(Math.ceil(this.gasLimit))
-                : undefined,
+              this.gasLimit === undefined
+                ? undefined
+                : BigInt(Math.ceil(this.gasLimit)),
           },
         );
 
@@ -262,13 +252,16 @@ export class EvmPricePusher implements IPricePusher {
 
       this.logger.info({ hash }, "Price update sent");
 
-      this.waitForTransactionReceipt(hash);
-    } catch (err: any) {
-      this.logger.debug({ err }, "Simulating or sending transactions failed.");
+      void this.waitForTransactionReceipt(hash);
+    } catch (error: any) {
+      this.logger.debug(
+        { err: error },
+        "Simulating or sending transactions failed.",
+      );
 
-      if (err instanceof BaseError) {
+      if (error instanceof BaseError) {
         if (
-          err.walk(
+          error.walk(
             (e) =>
               e instanceof ContractFunctionRevertedError &&
               e.data?.errorName === "NoFreshUpdate",
@@ -280,18 +273,18 @@ export class EvmPricePusher implements IPricePusher {
           return;
         }
 
-        if (err.walk((e) => e instanceof InsufficientFundsError)) {
+        if (error.walk((e) => e instanceof InsufficientFundsError)) {
           this.logger.error(
-            { err },
+            { err: error },
             "Wallet doesn't have enough balance. In rare cases, there might be issues with gas price " +
               "calculation in the RPC.",
           );
-          throw err;
+          throw error;
         }
 
         if (
-          err.walk((e) => e instanceof FeeCapTooLowError) ||
-          err.walk(
+          error.walk((e) => e instanceof FeeCapTooLowError) ||
+          error.walk(
             (e) =>
               e instanceof InternalRpcError &&
               e.details.includes("replacement transaction underpriced"),
@@ -307,7 +300,7 @@ export class EvmPricePusher implements IPricePusher {
         }
 
         if (
-          err.walk(
+          error.walk(
             (e) =>
               e instanceof TransactionExecutionError &&
               (e.details.includes("nonce too low") ||
@@ -321,9 +314,9 @@ export class EvmPricePusher implements IPricePusher {
         }
 
         // Sometimes the contract function execution fails in simulation and this error is thrown.
-        if (err.walk((e) => e instanceof ContractFunctionExecutionError)) {
+        if (error.walk((e) => e instanceof ContractFunctionExecutionError)) {
           this.logger.warn(
-            { err },
+            { err: error },
             "The contract function execution failed in simulation. This is an expected behaviour in high frequency or multi-instance setup. " +
               "Please review this error and file an issue if it is a bug. Skipping this push.",
           );
@@ -332,9 +325,9 @@ export class EvmPricePusher implements IPricePusher {
 
         // We normally crash on unknown failures but we believe that this type of error is safe to skip. The other reason is that
         // wometimes we see a TransactionExecutionError because of the nonce without any details and it is not catchable.
-        if (err.walk((e) => e instanceof TransactionExecutionError)) {
+        if (error.walk((e) => e instanceof TransactionExecutionError)) {
           this.logger.error(
-            { err },
+            { err: error },
             "Transaction execution failed. This is an expected behaviour in high frequency or multi-instance setup. " +
               "Please review this error and file an issue if it is a bug. Skipping this push.",
           );
@@ -344,9 +337,9 @@ export class EvmPricePusher implements IPricePusher {
         // The following errors are part of the legacy code and might not work as expected.
         // We are keeping them in case they help with handling what is not covered above.
         if (
-          err.message.includes("the tx doesn't have the correct nonce.") ||
-          err.message.includes("nonce too low") ||
-          err.message.includes("invalid nonce")
+          error.message.includes("the tx doesn't have the correct nonce.") ||
+          error.message.includes("nonce too low") ||
+          error.message.includes("invalid nonce")
         ) {
           this.logger.info(
             "The nonce is incorrect (are multiple users using this account?). Skipping this push.",
@@ -354,7 +347,9 @@ export class EvmPricePusher implements IPricePusher {
           return;
         }
 
-        if (err.message.includes("max fee per gas less than block base fee")) {
+        if (
+          error.message.includes("max fee per gas less than block base fee")
+        ) {
           // We just have to handle this error and return.
           // LastPushAttempt was stored with the class
           // Next time the update will be executing, it will check the last attempt
@@ -367,13 +362,13 @@ export class EvmPricePusher implements IPricePusher {
         }
 
         if (
-          err.message.includes("sender doesn't have enough funds to send tx.")
+          error.message.includes("sender doesn't have enough funds to send tx.")
         ) {
           this.logger.error("Payer is out of balance, please top it up.");
           throw new Error("Please top up the wallet");
         }
 
-        if (err.message.includes("could not replace existing tx")) {
+        if (error.message.includes("could not replace existing tx")) {
           this.logger.error(
             "A transaction with the same nonce has been mined and this one is no longer needed. Skipping this push.",
           );
@@ -383,11 +378,11 @@ export class EvmPricePusher implements IPricePusher {
 
       // If the error is not handled, we will crash the process.
       this.logger.error(
-        { err },
+        { err: error },
         "The transaction failed with an unhandled error. crashing the process. " +
           "Please review this error and file an issue if it is a bug.",
       );
-      throw err;
+      throw error;
     }
   }
 
@@ -398,19 +393,21 @@ export class EvmPricePusher implements IPricePusher {
       });
 
       switch (receipt.status) {
-        case "success":
+        case "success": {
           this.logger.debug({ hash, receipt }, "Price update successful");
           this.logger.info({ hash }, "Price update successful");
           break;
-        default:
+        }
+        default: {
           this.logger.info(
             { hash, receipt },
             "Price update did not succeed or its transaction did not land. " +
               "This is an expected behaviour in high frequency or multi-instance setup.",
           );
+        }
       }
-    } catch (err: any) {
-      this.logger.warn({ err }, "Failed to get transaction receipt");
+    } catch (error: any) {
+      this.logger.warn({ err: error }, "Failed to get transaction receipt");
     }
   }
 

+ 3 - 1
apps/price_pusher/src/evm/pyth-contract.ts

@@ -1,4 +1,6 @@
-import { getContract, type Address, type GetContractReturnType } from "viem";
+import type { Address, GetContractReturnType } from "viem";
+import { getContract } from "viem";
+
 import { PythAbi } from "./pyth-abi.js";
 import type { SuperWalletClient } from "./super-wallet.js";
 

+ 13 - 9
apps/price_pusher/src/evm/super-wallet.ts

@@ -1,22 +1,25 @@
+import type {
+  Account,
+  Chain,
+  Client,
+  RpcSchema,
+  WalletActions,
+  PublicActions,
+  WebSocketTransport,
+  HttpTransport,
+  Transport,
+} from "viem";
 import {
   createPublicClient,
   createWalletClient,
   defineChain,
   http,
   webSocket,
-  type Account,
-  type Chain,
   publicActions,
-  type Client,
-  type RpcSchema,
-  type WalletActions,
-  type PublicActions,
-  type WebSocketTransport,
-  type HttpTransport,
-  type Transport,
 } from "viem";
 import { mnemonicToAccount } from "viem/accounts";
 import * as chains from "viem/chains";
+
 import { isWsEndpoint } from "../utils.js";
 
 const UNKNOWN_CHAIN_CONFIG = {
@@ -50,6 +53,7 @@ const getTransport = (endpoint: string): WebSocketTransport | HttpTransport =>
 // the viem package to support new chains if they don't work as expected with the unknown
 // chain.
 const getChainById = (chainId: number): Chain =>
+  // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
   Object.values(chains).find((chain) => chain.id === chainId) ||
   defineChain({ id: chainId, ...UNKNOWN_CHAIN_CONFIG });
 

+ 11 - 5
apps/price_pusher/src/fuel/command.ts

@@ -1,13 +1,19 @@
+/* eslint-disable @typescript-eslint/no-unsafe-call */
+/* eslint-disable @typescript-eslint/no-unsafe-argument */
+/* eslint-disable @typescript-eslint/no-unsafe-assignment */
+/* eslint-disable @typescript-eslint/no-explicit-any */
+import fs from "node:fs";
+
+import { HermesClient } from "@pythnetwork/hermes-client";
+import { Provider, Wallet } from "fuels";
+import pino from "pino";
 import type { Options } from "yargs";
+
 import * as options from "../options.js";
 import { readPriceConfigFile } from "../price-config.js";
-import { HermesClient } from "@pythnetwork/hermes-client";
 import { PythPriceListener } from "../pyth-price-listener.js";
 import { FuelPriceListener, FuelPricePusher } from "./fuel.js";
 import { Controller } from "../controller.js";
-import { Provider, Wallet } from "fuels";
-import fs from "fs";
-import pino from "pino";
 import { filterInvalidPriceItems } from "../utils.js";
 
 export default {
@@ -107,6 +113,6 @@ export default {
       { pushingFrequency },
     );
 
-    await controller.start();
+    void controller.start();
   },
 };

+ 24 - 15
apps/price_pusher/src/fuel/fuel.ts

@@ -1,17 +1,22 @@
+/* eslint-disable @typescript-eslint/no-explicit-any */
+/* eslint-disable @typescript-eslint/no-unsafe-argument */
+/* 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-assignment */
+/* eslint-disable no-console */
 import { HermesClient } from "@pythnetwork/hermes-client";
-import {
-  ChainPriceListener,
-  type IPricePusher,
-  type PriceInfo,
-  type PriceItem,
-} from "../interface.js";
-import { addLeading0x, type DurationInSeconds } from "../utils.js";
-import type { Logger } from "pino";
-import { Provider, Contract, hexlify, arrayify, Wallet, BN } from "fuels";
 import {
   PYTH_CONTRACT_ABI,
   FUEL_ETH_ASSET_ID,
 } from "@pythnetwork/pyth-fuel-js";
+import { Provider, Contract, hexlify, arrayify, Wallet, BN } from "fuels";
+import type { Logger } from "pino";
+
+import type { IPricePusher, PriceInfo, PriceItem } from "../interface.js";
+import { ChainPriceListener } from "../interface.js";
+import type { DurationInSeconds } from "../utils.js";
+import { addLeading0x } from "../utils.js";
 
 // Convert TAI64 timestamp to Unix timestamp
 function tai64ToUnix(tai64: BN): number {
@@ -65,8 +70,11 @@ export class FuelPriceListener extends ChainPriceListener {
         price: priceInfo?.value.price.toString() ?? "",
         publishTime: tai64ToUnix(priceInfo?.value.publish_time),
       };
-    } catch (err) {
-      this.logger.error({ err, priceId }, `Polling on-chain price failed.`);
+    } catch (error) {
+      this.logger.error(
+        { err: error, priceId },
+        `Polling on-chain price failed.`,
+      );
       return undefined;
     }
   }
@@ -88,6 +96,7 @@ export class FuelPricePusher implements IPricePusher {
     );
   }
 
+  // eslint-disable-next-line @typescript-eslint/no-unused-vars
   async updatePriceFeed(priceIds: string[], _: number[]): Promise<void> {
     if (priceIds.length === 0) {
       return;
@@ -100,8 +109,8 @@ export class FuelPricePusher implements IPricePusher {
         ignoreInvalidPriceIds: true,
       });
       priceFeedUpdateData = response.binary.data;
-    } catch (err: any) {
-      this.logger.error(err, "getPriceFeedsUpdateData failed");
+    } catch (error: any) {
+      this.logger.error(error, "getPriceFeedsUpdateData failed");
       return;
     }
 
@@ -123,8 +132,8 @@ export class FuelPricePusher implements IPricePusher {
         { transactionId: result?.transactionId },
         "updatePriceFeed successful",
       );
-    } catch (err: any) {
-      this.logger.error(err, "updatePriceFeed failed");
+    } catch (error: any) {
+      this.logger.error(error, "updatePriceFeed failed");
     }
   }
 }

+ 11 - 8
apps/price_pusher/src/index.ts

@@ -1,17 +1,20 @@
-#!/usr/bin/env node
-import yargs from "yargs";
+import createCLI from "yargs";
 import { hideBin } from "yargs/helpers";
-import injective from "./injective/command.js";
-import evm from "./evm/command.js";
+
 import aptos from "./aptos/command.js";
-import sui from "./sui/command.js";
+import evm from "./evm/command.js";
+import fuel from "./fuel/command.js";
+import injective from "./injective/command.js";
 import near from "./near/command.js";
+import { enableMetrics, metricsPort } from "./options.js";
 import solana from "./solana/command.js";
-import fuel from "./fuel/command.js";
+import sui from "./sui/command.js";
 import ton from "./ton/command.js";
-import { enableMetrics, metricsPort } from "./options.js";
 
-yargs(hideBin(process.argv))
+const yargs = createCLI(hideBin(process.argv));
+
+// let the application run but don't await on the value here, per existing behavior
+void yargs
   .parserConfiguration({
     "parse-numbers": false,
   })

+ 12 - 7
apps/price_pusher/src/injective/command.ts

@@ -1,13 +1,18 @@
+/* eslint-disable @typescript-eslint/no-unsafe-argument */
+/* eslint-disable @typescript-eslint/no-unsafe-assignment */
+/* eslint-disable @typescript-eslint/no-explicit-any */
+import fs from "node:fs";
+
+import { getNetworkInfo } from "@injectivelabs/networks";
 import { HermesClient } from "@pythnetwork/hermes-client";
+import { pino } from "pino";
+import type { Options } from "yargs";
+
 import * as options from "../options.js";
 import { readPriceConfigFile } from "../price-config.js";
-import fs from "fs";
 import { InjectivePriceListener, InjectivePricePusher } from "./injective.js";
-import { PythPriceListener } from "../pyth-price-listener.js";
 import { Controller } from "../controller.js";
-import type { Options } from "yargs";
-import { getNetworkInfo } from "@injectivelabs/networks";
-import { pino } from "pino";
+import { PythPriceListener } from "../pyth-price-listener.js";
 import { filterInvalidPriceItems } from "../utils.js";
 export default {
   command: "injective",
@@ -75,7 +80,7 @@ export default {
 
     const priceConfigs = readPriceConfigFile(priceConfigFile);
     const hermesClient = new HermesClient(priceServiceEndpoint);
-    const mnemonic = fs.readFileSync(mnemonicFile, "utf-8").trim();
+    const mnemonic = fs.readFileSync(mnemonicFile, "utf8").trim();
 
     let priceItems = priceConfigs.map(({ id, alias }) => ({ id, alias }));
 
@@ -131,6 +136,6 @@ export default {
       { pushingFrequency },
     );
 
-    controller.start();
+    void controller.start();
   },
 };

+ 40 - 37
apps/price_pusher/src/injective/injective.ts

@@ -1,15 +1,11 @@
-import { type HexString, HermesClient } from "@pythnetwork/hermes-client";
+/* eslint-disable @typescript-eslint/no-unsafe-call */
+/* eslint-disable @typescript-eslint/no-unsafe-member-access */
+/* eslint-disable @typescript-eslint/no-explicit-any */
+/* eslint-disable @typescript-eslint/no-unnecessary-condition */
+/* eslint-disable @typescript-eslint/restrict-template-expressions */
+/* eslint-disable @typescript-eslint/no-unsafe-assignment */
+import type { Msgs, Account, TxResponse } from "@injectivelabs/sdk-ts";
 import {
-  type PriceItem,
-  type PriceInfo,
-  type IPricePusher,
-  ChainPriceListener,
-} from "../interface.js";
-import type { DurationInSeconds } from "../utils.js";
-import {
-  type Msgs,
-  type Account,
-  type TxResponse,
   PrivateKey,
   TxGrpcApi,
   ChainGrpcAuthApi,
@@ -18,9 +14,15 @@ import {
   createTransactionFromMsg,
 } from "@injectivelabs/sdk-ts";
 import { splitArrayToChunks } from "@injectivelabs/utils";
+import type { HexString } from "@pythnetwork/hermes-client";
+import { HermesClient } from "@pythnetwork/hermes-client";
 import type { Logger } from "pino";
 
-const DEFAULT_GAS_PRICE = 160000000;
+import type { PriceItem, PriceInfo, IPricePusher } from "../interface.js";
+import { ChainPriceListener } from "../interface.js";
+import type { DurationInSeconds } from "../utils.js";
+
+const DEFAULT_GAS_PRICE = 160_000_000;
 const DEFAULT_GAS_MULTIPLIER = 1.05;
 const DEFAULT_PRICE_IDS_PROCESS_CHUNK_SIZE = -1;
 const INJECTIVE_TESTNET_CHAIN_ID = "injective-888";
@@ -71,8 +73,8 @@ export class InjectivePriceListener extends ChainPriceListener {
 
       const json = Buffer.from(data).toString();
       priceQueryResponse = JSON.parse(json);
-    } catch (err) {
-      this.logger.error(err, `Polling on-chain price for ${priceId} failed.`);
+    } catch (error) {
+      this.logger.error(error, `Polling on-chain price for ${priceId} failed.`);
       return undefined;
     }
 
@@ -93,8 +95,7 @@ export class InjectivePriceListener extends ChainPriceListener {
 export class InjectivePricePusher implements IPricePusher {
   private mnemonic: string;
   private chainConfig: InjectiveConfig;
-  private accounts: Record<string, Account | undefined> =
-    {}; /** { address: Account } */
+  private accounts: Record<string, Account | undefined> = {};
 
   constructor(
     private hermesClient: HermesClient,
@@ -150,6 +151,7 @@ export class InjectivePricePusher implements IPricePusher {
         pubKey: wallet.toPublicKey().toBase64(),
       });
 
+      // eslint-disable-next-line @typescript-eslint/await-thenable
       const sig = await wallet.sign(Buffer.from(signBytes));
 
       /** Append Signatures */
@@ -163,13 +165,13 @@ export class InjectivePricePusher implements IPricePusher {
       account.baseAccount.sequence++;
 
       return txResponse;
-    } catch (e: any) {
+    } catch (error: any) {
       // The sequence number was invalid and hence we will have to fetch it again
-      if (JSON.stringify(e).match(/account sequence mismatch/) !== null) {
+      if (/account sequence mismatch/.exec(JSON.stringify(error)) !== null) {
         this.accounts[injectiveAddress] = undefined;
       }
 
-      throw e;
+      throw error;
     }
   }
 
@@ -224,23 +226,23 @@ export class InjectivePricePusher implements IPricePusher {
         { hash: rs.txHash },
         `Successfully broadcasted txHash for chunk ${chunkIndex}`,
       );
-    } catch (err: any) {
-      if (err.message.match(/account inj[a-zA-Z0-9]+ not found/) !== null) {
-        this.logger.error(err, `Account not found for chunk ${chunkIndex}`);
+    } catch (error: any) {
+      if (error.message.match(/account inj[a-zA-Z0-9]+ not found/) !== null) {
+        this.logger.error(error, `Account not found for chunk ${chunkIndex}`);
 
         throw new Error("Please check the mnemonic");
       }
 
       if (
-        err.message.match(/insufficient/) !== null &&
-        err.message.match(/funds/) !== null
+        error.message.match(/insufficient/) !== null &&
+        error.message.match(/funds/) !== null
       ) {
-        this.logger.error(err, `Insufficient funds for chunk ${chunkIndex}`);
+        this.logger.error(error, `Insufficient funds for chunk ${chunkIndex}`);
         throw new Error("Insufficient funds");
       }
 
       this.logger.error(
-        err,
+        error,
         `Error executing messages for chunk ${chunkIndex}`,
       );
     }
@@ -276,21 +278,21 @@ export class InjectivePricePusher implements IPricePusher {
 
       const gas = (
         result.gasInfo.gasUsed * this.chainConfig.gasMultiplier
-      ).toFixed();
+      ).toFixed(0);
       const fee = {
         amount: [
           {
             denom: "inj",
-            amount: (Number(gas) * this.chainConfig.gasPrice).toFixed(),
+            amount: (Number(gas) * this.chainConfig.gasPrice).toFixed(0),
           },
         ],
         gas,
       };
 
       return fee;
-    } catch (err) {
-      this.logger.error(err, `Error getting std fee`);
-      throw err;
+    } catch (error) {
+      this.logger.error(error, `Error getting std fee`);
+      throw error;
     }
   }
 
@@ -314,9 +316,9 @@ export class InjectivePricePusher implements IPricePusher {
           data: string[];
         };
       };
-    } catch (err) {
-      this.logger.error(err, `Error fetching the latest vaas to push`);
-      throw err;
+    } catch (error) {
+      this.logger.error(error, `Error fetching the latest vaas to push`);
+      throw error;
     }
   }
 
@@ -339,12 +341,13 @@ export class InjectivePricePusher implements IPricePusher {
 
       const json = Buffer.from(data).toString();
 
+      // eslint-disable-next-line @typescript-eslint/no-unsafe-return
       return JSON.parse(json);
-    } catch (err) {
-      this.logger.error(err, `Error fetching update fee.`);
+    } catch (error) {
+      this.logger.error(error, `Error fetching update fee.`);
 
       // Throwing an error because it is likely an RPC issue
-      throw err;
+      throw error;
     }
   }
 }

+ 13 - 12
apps/price_pusher/src/interface.ts

@@ -1,7 +1,8 @@
 import type { HexString, UnixTimestamp } from "@pythnetwork/hermes-client";
-import type { DurationInSeconds } from "./utils.js";
 import type { Logger } from "pino";
+
 import { PricePusherMetrics } from "./metrics.js";
+import type { DurationInSeconds } from "./utils.js";
 
 export type PriceItem = {
   id: HexString;
@@ -14,11 +15,11 @@ export type PriceInfo = {
   publishTime: UnixTimestamp;
 };
 
-export interface IPriceListener {
+export type IPriceListener = {
   // start fetches the latest price initially and then keep updating it
   start(): Promise<void>;
   getLatestPriceInfo(priceId: string): PriceInfo | undefined;
-}
+};
 
 export abstract class ChainPriceListener implements IPriceListener {
   private latestPriceInfo: Map<HexString, PriceInfo>;
@@ -35,7 +36,7 @@ export abstract class ChainPriceListener implements IPriceListener {
   }
 
   async start() {
-    setInterval(this.pollPrices.bind(this), this.pollingFrequency * 1000);
+    setInterval(() => void this.pollPrices(), this.pollingFrequency * 1000);
 
     await this.pollPrices();
   }
@@ -78,17 +79,17 @@ export abstract class ChainPriceListener implements IPriceListener {
   ): Promise<PriceInfo | undefined>;
 }
 
-export interface IPricePusher {
+export type IPricePusher = {
   updatePriceFeed(
     priceIds: string[],
     pubTimesToPush: UnixTimestamp[],
   ): Promise<void>;
-}
+};
 
 /**
  * Common configuration properties for all balance trackers
  */
-export interface BaseBalanceTrackerConfig {
+export type BaseBalanceTrackerConfig = {
   /** Address of the wallet to track */
   address: string;
   /** Name/ID of the network/chain */
@@ -99,13 +100,13 @@ export interface BaseBalanceTrackerConfig {
   metrics: PricePusherMetrics;
   /** Logger instance */
   logger: Logger;
-}
+};
 
 /**
  * Interface for all balance trackers to implement
  * Each chain will have its own implementation of this interface
  */
-export interface IBalanceTracker {
+export type IBalanceTracker = {
   /**
    * Start tracking the wallet balance
    */
@@ -115,7 +116,7 @@ export interface IBalanceTracker {
    * Stop tracking the wallet balance
    */
   stop(): void;
-}
+};
 
 /**
  * Abstract base class that implements common functionality for all balance trackers
@@ -126,7 +127,7 @@ export abstract class BaseBalanceTracker implements IBalanceTracker {
   protected updateInterval: DurationInSeconds;
   protected metrics: PricePusherMetrics;
   protected logger: Logger;
-  protected isRunning: boolean = false;
+  protected isRunning = false;
 
   constructor(config: BaseBalanceTrackerConfig) {
     this.address = config.address;
@@ -147,7 +148,7 @@ export abstract class BaseBalanceTracker implements IBalanceTracker {
     await this.updateBalance();
 
     // Start the update loop
-    this.startUpdateLoop();
+    void this.startUpdateLoop();
   }
 
   private async startUpdateLoop(): Promise<void> {

+ 14 - 11
apps/price_pusher/src/metrics.ts

@@ -1,6 +1,9 @@
-import { Registry, Counter, Gauge } from "prom-client";
+/* eslint-disable @typescript-eslint/restrict-template-expressions */
+/* eslint-disable @typescript-eslint/no-misused-promises */
 import express from "express";
 import type { Logger } from "pino";
+import { Registry, Counter, Gauge } from "prom-client";
+
 import { UpdateCondition } from "./price-config.js";
 
 // Define the metrics we want to track
@@ -10,15 +13,15 @@ export class PricePusherMetrics {
   private logger: Logger;
 
   // Metrics for price feed updates
-  public lastPublishedTime: Gauge<string>;
-  public priceUpdateAttempts: Counter<string>;
-  public priceFeedsTotal: Gauge<string>;
-  public sourceTimestamp: Gauge<string>;
-  public configuredTimeDifference: Gauge<string>;
-  public sourcePriceValue: Gauge<string>;
-  public targetPriceValue: Gauge<string>;
+  public lastPublishedTime: Gauge;
+  public priceUpdateAttempts: Counter;
+  public priceFeedsTotal: Gauge;
+  public sourceTimestamp: Gauge;
+  public configuredTimeDifference: Gauge;
+  public sourcePriceValue: Gauge;
+  public targetPriceValue: Gauge;
   // Wallet metrics
-  public walletBalance: Gauge<string>;
+  public walletBalance: Gauge;
 
   constructor(logger: Logger) {
     this.logger = logger;
@@ -103,7 +106,7 @@ export class PricePusherMetrics {
   public recordPriceUpdate(
     priceId: string,
     alias: string,
-    trigger: string = "yes",
+    trigger = "yes",
   ): void {
     this.priceUpdateAttempts.inc({
       price_id: priceId,
@@ -137,7 +140,7 @@ export class PricePusherMetrics {
   public recordPriceUpdateError(
     priceId: string,
     alias: string,
-    trigger: string = "yes",
+    trigger = "yes",
   ): void {
     this.priceUpdateAttempts.inc({
       price_id: priceId,

+ 8 - 4
apps/price_pusher/src/near/command.ts

@@ -1,11 +1,15 @@
+/* eslint-disable @typescript-eslint/no-unsafe-argument */
+/* eslint-disable @typescript-eslint/no-unsafe-assignment */
+/* eslint-disable @typescript-eslint/no-explicit-any */
 import { HermesClient } from "@pythnetwork/hermes-client";
+import { pino } from "pino";
+import type { Options } from "yargs";
+
+import { Controller } from "../controller";
 import * as options from "../options";
 import { readPriceConfigFile } from "../price-config";
 import { PythPriceListener } from "../pyth-price-listener";
-import { Controller } from "../controller";
-import type { Options } from "yargs";
 import { NearAccount, NearPriceListener, NearPricePusher } from "./near";
-import { pino } from "pino";
 import { filterInvalidPriceItems } from "../utils";
 
 export default {
@@ -116,6 +120,6 @@ export default {
       { pushingFrequency },
     );
 
-    controller.start();
+    void controller.start();
   },
 };

+ 45 - 40
apps/price_pusher/src/near/near.ts

@@ -1,25 +1,28 @@
-import os from "os";
-import path from "path";
-import fs from "fs";
-
-import {
-  type IPricePusher,
-  type PriceInfo,
-  ChainPriceListener,
-  type PriceItem,
-} from "../interface.js";
-import { HermesClient, type HexString } from "@pythnetwork/hermes-client";
-import type { DurationInSeconds } from "../utils.js";
-
+/* eslint-disable @typescript-eslint/no-unsafe-argument */
+/* eslint-disable unicorn/no-array-reduce */
+/* eslint-disable @typescript-eslint/no-explicit-any */
+/* eslint-disable @typescript-eslint/no-unsafe-member-access */
+/* eslint-disable @typescript-eslint/restrict-template-expressions */
+/* eslint-disable @typescript-eslint/no-unsafe-assignment */
+import fs from "node:fs";
+import os from "node:os";
+import path from "node:path";
+
+import type { HexString } from "@pythnetwork/hermes-client";
+import { HermesClient } from "@pythnetwork/hermes-client";
 import { Account, Connection, KeyPair } from "near-api-js";
-import {
-  type ExecutionStatus,
-  ExecutionStatusBasic,
-  type FinalExecutionOutcome,
-} from "near-api-js/lib/providers/provider";
 import { InMemoryKeyStore } from "near-api-js/lib/key_stores";
+import type {
+  ExecutionStatus,
+  FinalExecutionOutcome,
+} from "near-api-js/lib/providers/provider";
+import { ExecutionStatusBasic } from "near-api-js/lib/providers/provider";
 import type { Logger } from "pino";
 
+import type { IPricePusher, PriceInfo, PriceItem } from "../interface.js";
+import { ChainPriceListener } from "../interface.js";
+import type { DurationInSeconds } from "../utils.js";
+
 export class NearPriceListener extends ChainPriceListener {
   constructor(
     private account: NearAccount,
@@ -42,17 +45,18 @@ export class NearPriceListener extends ChainPriceListener {
         )} (${priceId}) ${JSON.stringify(priceRaw)}.`,
       );
 
-      if (priceRaw) {
-        return {
-          conf: priceRaw.conf,
-          price: priceRaw.price,
-          publishTime: priceRaw.publish_time,
-        };
-      } else {
-        return undefined;
-      }
-    } catch (err) {
-      this.logger.error(err, `Polling on-chain price for ${priceId} failed.:`);
+      return priceRaw
+        ? {
+            conf: priceRaw.conf,
+            price: priceRaw.price,
+            publishTime: priceRaw.publish_time,
+          }
+        : undefined;
+    } catch (error) {
+      this.logger.error(
+        error,
+        `Polling on-chain price for ${priceId} failed.:`,
+      );
       return undefined;
     }
   }
@@ -79,8 +83,8 @@ export class NearPricePusher implements IPricePusher {
     let priceFeedUpdateData;
     try {
       priceFeedUpdateData = await this.getPriceFeedsUpdateData(priceIds);
-    } catch (err: any) {
-      this.logger.error(err, "getPriceFeedsUpdateData failed");
+    } catch (error: any) {
+      this.logger.error(error, "getPriceFeedsUpdateData failed");
       return;
     }
 
@@ -89,23 +93,23 @@ export class NearPricePusher implements IPricePusher {
       try {
         updateFee = await this.account.getUpdateFeeEstimate(data);
         this.logger.debug(`Update fee: ${updateFee}`);
-      } catch (err: any) {
-        this.logger.error(err, "getUpdateFeeEstimate failed");
+      } catch (error: any) {
+        this.logger.error(error, "getUpdateFeeEstimate failed");
         continue;
       }
 
       try {
         const outcome = await this.account.updatePriceFeeds(data, updateFee);
         const failureMessages: (ExecutionStatus | ExecutionStatusBasic)[] = [];
-        const is_success = Object.values(outcome["receipts_outcome"]).reduce(
+        const is_success = Object.values(outcome.receipts_outcome).reduce(
           (is_success, receipt) => {
             if (
               Object.prototype.hasOwnProperty.call(
-                receipt["outcome"]["status"],
+                receipt.outcome.status,
                 "Failure",
               )
             ) {
-              failureMessages.push(receipt["outcome"]["status"]);
+              failureMessages.push(receipt.outcome.status);
               return false;
             }
             return is_success;
@@ -114,14 +118,14 @@ export class NearPricePusher implements IPricePusher {
         );
         if (is_success) {
           this.logger.info(
-            { hash: outcome["transaction"]["hash"] },
+            { hash: outcome.transaction.hash },
             "updatePriceFeeds successful.",
           );
         } else {
           this.logger.error({ failureMessages }, "updatePriceFeeds failed");
         }
-      } catch (err: any) {
-        this.logger.error(err, "updatePriceFeeds failed");
+      } catch (error: any) {
+        this.logger.error(error, "updatePriceFeeds failed");
       }
     }
   }
@@ -198,6 +202,7 @@ export class NearAccount {
     privateKeyPath: string | undefined,
   ): Connection {
     const content = fs.readFileSync(
+      // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
       privateKeyPath ||
         path.join(
           os.homedir(),
@@ -214,7 +219,7 @@ export class NearAccount {
     if (accountInfo.account_id && privateKey) {
       const keyPair = KeyPair.fromString(privateKey);
       const keyStore = new InMemoryKeyStore();
-      keyStore.setKey(network, accountInfo.account_id, keyPair);
+      void keyStore.setKey(network, accountInfo.account_id, keyPair);
       return Connection.fromConfig({
         networkId: network,
         provider: { type: "JsonRpcProvider", args: { url: nodeUrl } },

+ 13 - 9
apps/price_pusher/src/price-config.ts

@@ -1,14 +1,18 @@
+/* eslint-disable @typescript-eslint/restrict-template-expressions */
+/* eslint-disable @typescript-eslint/no-explicit-any */
+/* eslint-disable @typescript-eslint/no-unsafe-argument */
+/* eslint-disable @typescript-eslint/no-unsafe-member-access */
+/* eslint-disable @typescript-eslint/no-unsafe-assignment */
+import fs from "node:fs";
+
 import type { HexString } from "@pythnetwork/hermes-client";
 import Joi from "joi";
-import YAML from "yaml";
-import fs from "fs";
 import type { Logger } from "pino";
-import {
-  type DurationInSeconds,
-  type PctNumber,
-  removeLeading0x,
-} from "./utils.js";
+import YAML from "yaml";
+
 import type { PriceInfo } from "./interface.js";
+import type { DurationInSeconds, PctNumber } from "./utils.js";
+import { removeLeading0x } from "./utils.js";
 
 const PriceConfigFileSchema: Joi.Schema = Joi.array()
   .items(
@@ -53,7 +57,7 @@ export type PriceConfig = {
 };
 
 export function readPriceConfigFile(path: string): PriceConfig[] {
-  const priceConfigs = YAML.parse(fs.readFileSync(path, "utf-8"));
+  const priceConfigs = YAML.parse(fs.readFileSync(path, "utf8"));
   const validationResult = PriceConfigFileSchema.validate(priceConfigs);
 
   if (validationResult.error !== undefined) {
@@ -89,7 +93,7 @@ export enum UpdateCondition {
 /**
  * Checks whether on-chain price needs to be updated with the latest pyth price information.
  *
- * @param priceConfig Config of the price feed to check
+ * @param priceConfig - Config of the price feed to check
  * @returns True if the on-chain price needs to be updated.
  */
 export function shouldUpdate(

+ 34 - 31
apps/price_pusher/src/pyth-price-listener.ts

@@ -1,10 +1,12 @@
-import {
-  type HexString,
-  HermesClient,
-  type PriceUpdate,
-} from "@pythnetwork/hermes-client";
-import type { PriceInfo, IPriceListener, PriceItem } from "./interface.js";
+/* eslint-disable no-console */
+/* eslint-disable @typescript-eslint/no-unsafe-argument */
+/* eslint-disable unicorn/prefer-add-event-listener */
+/* eslint-disable @typescript-eslint/restrict-template-expressions */
+import type { HexString, PriceUpdate } from "@pythnetwork/hermes-client";
+import { HermesClient } from "@pythnetwork/hermes-client";
 import type { Logger } from "pino";
+
+import type { PriceInfo, IPriceListener, PriceItem } from "./interface.js";
 import { sleep } from "./utils.js";
 
 type TimestampInMs = number & { readonly _: unique symbol };
@@ -35,7 +37,7 @@ export class PythPriceListener implements IPriceListener {
   // This method should be awaited on and once it finishes it has the latest value
   // for the given price feeds (if they exist).
   async start() {
-    this.startListening();
+    await this.startListening();
 
     // Store health check interval reference
     this.healthCheckInterval = setInterval(() => {
@@ -62,39 +64,40 @@ export class PythPriceListener implements IPriceListener {
     );
     eventSource.onmessage = (event: MessageEvent) => {
       const priceUpdates = JSON.parse(event.data) as PriceUpdate;
-      priceUpdates.parsed?.forEach((priceUpdate) => {
-        this.logger.debug(
-          `Received new price feed update from Pyth price service: ${this.priceIdToAlias.get(
-            priceUpdate.id,
-          )} ${priceUpdate.id}`,
-        );
+      if (priceUpdates.parsed)
+        for (const priceUpdate of priceUpdates.parsed) {
+          this.logger.debug(
+            `Received new price feed update from Pyth price service: ${this.priceIdToAlias.get(
+              priceUpdate.id,
+            )} ${priceUpdate.id}`,
+          );
 
-        // Consider price to be currently available if it is not older than 60s
-        const currentPrice =
-          Date.now() / 1000 - priceUpdate.price.publish_time > 60
-            ? undefined
-            : priceUpdate.price;
-        if (currentPrice === undefined) {
-          this.logger.debug("Price is older than 60s, skipping");
-          return;
-        }
+          // Consider price to be currently available if it is not older than 60s
+          const currentPrice =
+            Date.now() / 1000 - priceUpdate.price.publish_time > 60
+              ? undefined
+              : priceUpdate.price;
+          if (currentPrice === undefined) {
+            this.logger.debug("Price is older than 60s, skipping");
+            continue;
+          }
 
-        const priceInfo: PriceInfo = {
-          conf: currentPrice.conf,
-          price: currentPrice.price,
-          publishTime: currentPrice.publish_time,
-        };
+          const priceInfo: PriceInfo = {
+            conf: currentPrice.conf,
+            price: currentPrice.price,
+            publishTime: currentPrice.publish_time,
+          };
 
-        this.latestPriceInfo.set(priceUpdate.id, priceInfo);
-        this.lastUpdated = Date.now() as TimestampInMs;
-      });
+          this.latestPriceInfo.set(priceUpdate.id, priceInfo);
+          this.lastUpdated = Date.now() as TimestampInMs;
+        }
     };
 
     eventSource.onerror = async (error: Event) => {
       console.error("Error receiving updates from Hermes:", error);
       eventSource.close();
       await sleep(5000); // Wait a bit before trying to reconnect
-      this.startListening(); // Attempt to restart the listener
+      void this.startListening(); // Attempt to restart the listener
     };
   }
 

+ 12 - 11
apps/price_pusher/src/solana/balance-tracker.ts

@@ -1,22 +1,23 @@
 import { Connection, PublicKey, LAMPORTS_PER_SOL } from "@solana/web3.js";
-import {
-  BaseBalanceTracker,
-  type BaseBalanceTrackerConfig,
-  type IBalanceTracker,
+import type { Logger } from "pino";
+
+import type {
+  BaseBalanceTrackerConfig,
+  IBalanceTracker,
 } from "../interface.js";
-import type { DurationInSeconds } from "../utils.js";
+import { BaseBalanceTracker } from "../interface.js";
 import { PricePusherMetrics } from "../metrics.js";
-import type { Logger } from "pino";
+import type { DurationInSeconds } from "../utils.js";
 
 /**
  * Solana-specific configuration for balance tracker
  */
-export interface SolanaBalanceTrackerConfig extends BaseBalanceTrackerConfig {
+export type SolanaBalanceTrackerConfig = {
   /** Solana connection instance */
   connection: Connection;
   /** Solana public key */
   publicKey: PublicKey;
-}
+} & BaseBalanceTrackerConfig;
 
 /**
  * Solana-specific implementation of the balance tracker
@@ -53,7 +54,7 @@ export class SolanaBalanceTracker extends BaseBalanceTracker {
         balanceInSol,
       );
       this.logger.debug(
-        `Updated Solana wallet balance: ${this.address} = ${balanceInSol.toString()} SOL (${balanceInLamports} lamports)`,
+        `Updated Solana wallet balance: ${this.address} = ${balanceInSol.toString()} SOL (${balanceInLamports.toString()} lamports)`,
       );
     } catch (error) {
       this.logger.error(
@@ -67,14 +68,14 @@ export class SolanaBalanceTracker extends BaseBalanceTracker {
 /**
  * Parameters for creating a Solana balance tracker
  */
-export interface CreateSolanaBalanceTrackerParams {
+export type CreateSolanaBalanceTrackerParams = {
   connection: Connection;
   publicKey: PublicKey;
   network: string;
   updateInterval: DurationInSeconds;
   metrics: PricePusherMetrics;
   logger: Logger;
-}
+};
 
 /**
  * Factory function to create a balance tracker for Solana

+ 33 - 19
apps/price_pusher/src/solana/command.ts

@@ -1,4 +1,29 @@
+/* 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 */
+import fs from "node:fs";
+
+import NodeWallet from "@coral-xyz/anchor/dist/cjs/nodewallet.js";
+import { HermesClient } from "@pythnetwork/hermes-client";
+import { PythSolanaReceiver } from "@pythnetwork/pyth-solana-receiver";
+import {
+  Keypair,
+  Connection,
+  LAMPORTS_PER_SOL,
+  PublicKey,
+} from "@solana/web3.js";
+import {
+  searcherClient,
+  SearcherClient,
+} from "jito-ts/dist/sdk/block-engine/searcher";
+import type { Logger } from "pino";
+import { pino } from "pino";
 import type { Options } from "yargs";
+
 import * as options from "../options.js";
 import { readPriceConfigFile } from "../price-config.js";
 import { PythPriceListener } from "../pyth-price-listener.js";
@@ -8,22 +33,10 @@ import {
   SolanaPricePusherJito,
 } from "./solana.js";
 import { Controller } from "../controller.js";
-import { PythSolanaReceiver } from "@pythnetwork/pyth-solana-receiver";
-import { Keypair, Connection, LAMPORTS_PER_SOL } from "@solana/web3.js";
-import fs from "fs";
-import { PublicKey } from "@solana/web3.js";
-import { pino } from "pino";
-import type { Logger } from "pino";
-import { HermesClient } from "@pythnetwork/hermes-client";
-import {
-  searcherClient,
-  SearcherClient,
-} from "jito-ts/dist/sdk/block-engine/searcher";
-import NodeWallet from "@coral-xyz/anchor/dist/cjs/nodewallet.js";
-import { filterInvalidPriceItems } from "../utils.js";
+import type { IBalanceTracker } from "../interface.js";
 import { PricePusherMetrics } from "../metrics.js";
+import { filterInvalidPriceItems } from "../utils.js";
 import { createSolanaBalanceTracker } from "./balance-tracker.js";
-import type { IBalanceTracker } from "../interface.js";
 
 export default {
   command: "solana",
@@ -47,7 +60,7 @@ export default {
     "compute-unit-price-micro-lamports": {
       description: "Priority fee per compute unit",
       type: "number",
-      default: 50000,
+      default: 50_000,
     } as Options,
     "jito-endpoints": {
       description: "Jito endpoint(s) - comma-separated list of endpoints",
@@ -235,9 +248,9 @@ export default {
         lookupTableAccount,
       );
 
-      jitoClients.forEach((client, index) => {
+      for (const [index, client] of jitoClients.entries()) {
         onBundleResult(client, logger.child({ module: `JitoClient-${index}` }));
-      });
+      }
     } else {
       solanaPricePusher = new SolanaPricePusher(
         pythSolanaReceiver,
@@ -269,14 +282,15 @@ export default {
       },
     );
 
-    controller.start();
+    void controller.start();
   },
 };
 
 export const onBundleResult = (c: SearcherClient, logger: Logger) => {
   try {
     c.onBundleResult(
-      () => undefined,
+      // eslint-disable-next-line @typescript-eslint/no-empty-function
+      () => {},
       (err) => {
         logger.error(err, "Error in bundle result");
       },

+ 45 - 44
apps/price_pusher/src/solana/solana.ts

@@ -1,20 +1,19 @@
-import { PythSolanaReceiver } from "@pythnetwork/pyth-solana-receiver";
-import {
-  ChainPriceListener,
-  type IPricePusher,
-  type PriceInfo,
-  type PriceItem,
-} from "../interface.js";
-import type { DurationInSeconds } from "../utils.js";
+/* eslint-disable @typescript-eslint/no-unsafe-member-access */
+/* eslint-disable @typescript-eslint/no-explicit-any */
 import { HermesClient } from "@pythnetwork/hermes-client";
+import { sliceAccumulatorUpdateData } from "@pythnetwork/price-service-sdk";
+import { PythSolanaReceiver } from "@pythnetwork/pyth-solana-receiver";
 import {
   sendTransactions,
   sendTransactionsJito,
 } from "@pythnetwork/solana-utils";
+import { AddressLookupTableAccount, LAMPORTS_PER_SOL } from "@solana/web3.js";
 import { SearcherClient } from "jito-ts/dist/sdk/block-engine/searcher";
-import { sliceAccumulatorUpdateData } from "@pythnetwork/price-service-sdk";
 import type { Logger } from "pino";
-import { AddressLookupTableAccount, LAMPORTS_PER_SOL } from "@solana/web3.js";
+
+import type { IPricePusher, PriceInfo, PriceItem } from "../interface.js";
+import { ChainPriceListener } from "../interface.js";
+import type { DurationInSeconds } from "../utils.js";
 
 const HEALTH_CHECK_TIMEOUT_SECONDS = 60;
 
@@ -39,25 +38,25 @@ export class SolanaPriceListener extends ChainPriceListener {
       const blockTime =
         await this.pythSolanaReceiver.connection.getBlockTime(slot);
       if (
-        blockTime === null ||
-        blockTime < Date.now() / 1000 - HEALTH_CHECK_TIMEOUT_SECONDS
+        (blockTime === null ||
+          blockTime < Date.now() / 1000 - HEALTH_CHECK_TIMEOUT_SECONDS) &&
+        blockTime !== null
       ) {
-        if (blockTime !== null) {
-          this.logger.info(
-            `Solana connection is behind by ${
-              Date.now() / 1000 - blockTime
-            } seconds`,
-          );
-        }
+        this.logger.info(
+          `Solana connection is behind by ${(
+            Date.now() / 1000 -
+            blockTime
+          ).toString()} seconds`,
+        );
       }
-    } catch (err) {
-      this.logger.error({ err }, "checkHealth failed");
+    } catch (error) {
+      this.logger.error({ err: error }, "checkHealth failed");
     }
   }
 
   override async start() {
     // Frequently check the RPC connection to ensure it is healthy
-    setInterval(this.checkHealth.bind(this), 5000);
+    setInterval(() => void this.checkHealth(), 5000);
 
     await super.start();
   }
@@ -70,21 +69,22 @@ export class SolanaPriceListener extends ChainPriceListener {
           Buffer.from(priceId, "hex"),
         );
       this.logger.debug(
-        `Polled a Solana on chain price for feed ${this.priceIdToAlias.get(
-          priceId,
-        )} (${priceId}).`,
+        `Polled a Solana on chain price for feed ${
+          this.priceIdToAlias.get(priceId)?.toString() ?? ""
+        } (${priceId}).`,
+      );
+      return priceFeedAccount
+        ? {
+            conf: priceFeedAccount.priceMessage.conf.toString(),
+            price: priceFeedAccount.priceMessage.price.toString(),
+            publishTime: priceFeedAccount.priceMessage.publishTime.toNumber(),
+          }
+        : undefined;
+    } catch (error) {
+      this.logger.error(
+        { err: error, priceId },
+        `Polling on-chain price failed.`,
       );
-      if (priceFeedAccount) {
-        return {
-          conf: priceFeedAccount.priceMessage.conf.toString(),
-          price: priceFeedAccount.priceMessage.price.toString(),
-          publishTime: priceFeedAccount.priceMessage.publishTime.toNumber(),
-        };
-      } else {
-        return undefined;
-      }
-    } catch (err) {
-      this.logger.error({ err, priceId }, `Polling on-chain price failed.`);
       return undefined;
     }
   }
@@ -122,8 +122,8 @@ export class SolanaPricePusher implements IPricePusher {
         },
       );
       priceFeedUpdateData = response.binary.data;
-    } catch (err: any) {
-      this.logger.error(err, "getPriceFeedsUpdateData failed:");
+    } catch (error: any) {
+      this.logger.error(error, "getPriceFeedsUpdateData failed:");
       return;
     }
 
@@ -150,8 +150,8 @@ export class SolanaPricePusher implements IPricePusher {
         this.pythSolanaReceiver.wallet,
       );
       this.logger.info({ signatures }, "updatePriceFeed successful");
-    } catch (err: any) {
-      this.logger.error(err, "updatePriceFeed failed");
+    } catch (error: any) {
+      this.logger.error(error, "updatePriceFeed failed");
       return;
     }
   }
@@ -189,8 +189,9 @@ export class SolanaPricePusherJito implements IPricePusher {
       return Math.floor(
         Number(data[0].landed_tips_50th_percentile) * LAMPORTS_PER_SOL,
       );
-    } catch (err: any) {
-      this.logger.error({ err }, "getRecentJitoTips failed");
+    } catch (error: any) {
+      // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
+      this.logger.error({ err: error }, "getRecentJitoTips failed");
       return undefined;
     }
   }
@@ -211,8 +212,8 @@ export class SolanaPricePusherJito implements IPricePusher {
         encoding: "base64",
       });
       priceFeedUpdateData = response.binary.data;
-    } catch (err: any) {
-      this.logger.error(err, "getPriceFeedsUpdateData failed");
+    } catch (error: any) {
+      this.logger.error(error, "getPriceFeedsUpdateData failed");
       return;
     }
 

+ 12 - 11
apps/price_pusher/src/sui/balance-tracker.ts

@@ -1,20 +1,21 @@
 import { SuiClient } from "@mysten/sui/client";
-import {
-  BaseBalanceTracker,
-  type BaseBalanceTrackerConfig,
-  type IBalanceTracker,
+import type { Logger } from "pino";
+
+import type {
+  BaseBalanceTrackerConfig,
+  IBalanceTracker,
 } from "../interface.js";
-import type { DurationInSeconds } from "../utils.js";
+import { BaseBalanceTracker } from "../interface.js";
 import { PricePusherMetrics } from "../metrics.js";
-import type { Logger } from "pino";
+import type { DurationInSeconds } from "../utils.js";
 
 /**
  * Sui-specific configuration for balance tracker
  */
-export interface SuiBalanceTrackerConfig extends BaseBalanceTrackerConfig {
+export type SuiBalanceTrackerConfig = {
   /** Sui client instance */
   client: SuiClient;
-}
+} & BaseBalanceTrackerConfig;
 
 /**
  * Sui-specific implementation of the balance tracker
@@ -50,7 +51,7 @@ export class SuiBalanceTracker extends BaseBalanceTracker {
       );
 
       this.logger.debug(
-        `Updated Sui wallet balance: ${this.address} = ${normalizedBalance} SUI`,
+        `Updated Sui wallet balance: ${this.address} = ${normalizedBalance.toString()} SUI`,
       );
     } catch (error) {
       this.logger.error(
@@ -64,14 +65,14 @@ export class SuiBalanceTracker extends BaseBalanceTracker {
 /**
  * Parameters for creating a Sui balance tracker
  */
-export interface CreateSuiBalanceTrackerParams {
+export type CreateSuiBalanceTrackerParams = {
   client: SuiClient;
   address: string;
   network: string;
   updateInterval: DurationInSeconds;
   metrics: PricePusherMetrics;
   logger: Logger;
-}
+};
 
 /**
  * Factory function to create a balance tracker for Sui chain

+ 17 - 10
apps/price_pusher/src/sui/command.ts

@@ -1,17 +1,24 @@
+/* eslint-disable @typescript-eslint/no-non-null-assertion */
+/* 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 */
+import fs from "node:fs";
+
+import { SuiClient } from "@mysten/sui/client";
+import { Ed25519Keypair } from "@mysten/sui/keypairs/ed25519";
 import { HermesClient } from "@pythnetwork/hermes-client";
+import pino from "pino";
+import type { Options } from "yargs";
+
+import { Controller } from "../controller.js";
+import { PricePusherMetrics } from "../metrics.js";
 import * as options from "../options.js";
 import { readPriceConfigFile } from "../price-config";
-import fs from "fs";
 import { PythPriceListener } from "../pyth-price-listener.js";
-import { Controller } from "../controller.js";
-import type { Options } from "yargs";
+import { createSuiBalanceTracker } from "./balance-tracker.js";
 import { SuiPriceListener, SuiPricePusher } from "./sui.js";
-import { Ed25519Keypair } from "@mysten/sui/keypairs/ed25519";
-import pino from "pino";
 import { filterInvalidPriceItems } from "../utils.js";
-import { PricePusherMetrics } from "../metrics.js";
-import { createSuiBalanceTracker } from "./balance-tracker.js";
-import { SuiClient } from "@mysten/sui/client";
 
 export default {
   command: "sui",
@@ -103,7 +110,7 @@ export default {
     const priceConfigs = readPriceConfigFile(priceConfigFile);
     const hermesClient = new HermesClient(priceServiceEndpoint);
 
-    const mnemonic = fs.readFileSync(mnemonicFile, "utf-8").trim();
+    const mnemonic = fs.readFileSync(mnemonicFile, "utf8").trim();
     const keypair = Ed25519Keypair.deriveKeypair(
       mnemonic,
       `m/44'/784'/${accountIndex}'/0'/0'`,
@@ -191,6 +198,6 @@ export default {
       await balanceTracker.start();
     }
 
-    controller.start();
+    void controller.start();
   },
 };

+ 47 - 47
apps/price_pusher/src/sui/sui.ts

@@ -1,20 +1,21 @@
-import {
-  ChainPriceListener,
-  type IPricePusher,
-  type PriceInfo,
-  type PriceItem,
-} from "../interface.js";
-import type { DurationInSeconds } from "../utils.js";
-import { SuiPythClient } from "@pythnetwork/pyth-sui-js";
+/* 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 */
+import type { SuiObjectRef, PaginatedCoins } from "@mysten/sui/client";
+import { SuiClient } from "@mysten/sui/client";
 import { Ed25519Keypair } from "@mysten/sui/keypairs/ed25519";
 import { Transaction } from "@mysten/sui/transactions";
-import {
-  SuiClient,
-  type SuiObjectRef,
-  type PaginatedCoins,
-} from "@mysten/sui/client";
-import type { Logger } from "pino";
 import { HermesClient } from "@pythnetwork/hermes-client";
+import { SuiPythClient } from "@pythnetwork/pyth-sui-js";
+import type { Logger } from "pino";
+
+import type { IPricePusher, PriceInfo, PriceItem } from "../interface.js";
+import { ChainPriceListener } from "../interface.js";
+import type { DurationInSeconds } from "../utils.js";
 const GAS_FEE_FOR_SPLIT = 2_000_000_000;
 // TODO: read this from on chain config
 const MAX_NUM_GAS_OBJECTS_IN_PTB = 256;
@@ -62,7 +63,7 @@ export class SuiPriceListener extends ChainPriceListener {
         options: { showContent: true },
       });
 
-      if (!priceInfoObject.data || !priceInfoObject.data.content)
+      if (!priceInfoObject.data?.content)
         throw new Error("Price not found on chain for price id " + priceId);
 
       if (priceInfoObject.data.content.dataType !== "moveObject")
@@ -80,13 +81,13 @@ export class SuiPriceListener extends ChainPriceListener {
       const timestamp = priceInfo.timestamp;
 
       return {
-        price: negative ? "-" + magnitude : magnitude,
+        price: negative ? `-${magnitude}` : magnitude,
         conf,
         publishTime: Number(timestamp),
       };
-    } catch (err) {
+    } catch (error) {
       this.logger.error(
-        err,
+        error,
         `Polling Sui on-chain price for ${priceId} failed.`,
       );
       return undefined;
@@ -122,8 +123,6 @@ export class SuiPricePusher implements IPricePusher {
   /**
    * getPackageId returns the latest package id that the object belongs to. Use this to
    * fetch the latest package id for a given object id and handle package upgrades automatically.
-   * @param provider
-   * @param objectId
    * @returns package id
    */
   static async getPackageId(
@@ -252,7 +251,7 @@ export class SuiPricePusher implements IPricePusher {
   }
 
   /** Send every transaction in txs in parallel, returning when all transactions have completed. */
-  private async sendTransactionBlocks(txs: Transaction[]): Promise<void[]> {
+  private async sendTransactionBlocks(txs: Transaction[]) {
     return Promise.all(txs.map((tx) => this.sendTransactionBlock(tx)));
   }
 
@@ -284,17 +283,17 @@ export class SuiPricePusher implements IPricePusher {
         { hash: result.digest },
         "Successfully updated price with transaction digest",
       );
-    } catch (err: any) {
+    } catch (error: any) {
       if (
-        String(err).includes("Balance of gas object") ||
-        String(err).includes("GasBalanceTooLow")
+        String(error).includes("Balance of gas object") ||
+        String(error).includes("GasBalanceTooLow")
       ) {
-        this.logger.error(err, "Insufficient gas balance");
+        this.logger.error(error, "Insufficient gas balance");
         // If the error is caused by insufficient gas, we should panic
-        throw err;
+        throw error;
       } else {
         this.logger.error(
-          err,
+          error,
           "Failed to update price. Trying to refresh gas object references.",
         );
         // Refresh the coin object here in case the error is caused by an object version mismatch.
@@ -343,8 +342,7 @@ export class SuiPricePusher implements IPricePusher {
     });
     let balance;
     if (
-      coinResult.data &&
-      coinResult.data.content &&
+      coinResult.data?.content &&
       coinResult.data.content.dataType == "moveObject"
     ) {
       // eslint-disable-next-line @typescript-eslint/ban-ts-comment
@@ -373,14 +371,14 @@ export class SuiPricePusher implements IPricePusher {
     ref: SuiObjectRef,
   ): Promise<SuiObjectRef> {
     const objectResponse = await provider.getObject({ id: ref.objectId });
-    if (objectResponse.data !== undefined) {
+    if (objectResponse.data === undefined) {
+      throw new Error("Failed to refresh object reference");
+    } else {
       return {
         digest: objectResponse.data!.digest,
         objectId: objectResponse.data!.objectId,
         version: objectResponse.data!.version,
       };
-    } else {
-      throw new Error("Failed to refresh object reference");
     }
   }
 
@@ -398,15 +396,14 @@ export class SuiPricePusher implements IPricePusher {
         cursor,
       });
       numCoins += paginatedCoins.data.length;
-      paginatedCoins.data.forEach((c) =>
+      for (const c of paginatedCoins.data)
         coins.add(
           JSON.stringify({
             objectId: c.coinObjectId,
             version: c.version,
             digest: c.digest,
           }),
-        ),
-      );
+        );
       hasNextPage = paginatedCoins.hasNextPage;
       cursor = paginatedCoins.nextCursor;
     }
@@ -442,7 +439,7 @@ export class SuiPricePusher implements IPricePusher {
       transaction: tx,
       options: { showEffects: true },
     });
-    const error = result?.effects?.status.error;
+    const error = result.effects?.status.error;
     if (error) {
       throw new Error(
         `Failed to initialize gas pool: ${error}. Try re-running the script`,
@@ -451,7 +448,7 @@ export class SuiPricePusher implements IPricePusher {
     const newCoins = result.effects!.created!.map((obj) => obj.reference);
     if (newCoins.length !== numGasObjects) {
       throw new Error(
-        `Failed to initialize gas pool. Expected ${numGasObjects}, got: ${newCoins}`,
+        `Failed to initialize gas pool. Expected ${numGasObjects}, got: ${JSON.stringify(newCoins)}`,
       );
     }
     return newCoins;
@@ -475,8 +472,8 @@ export class SuiPricePusher implements IPricePusher {
       MAX_NUM_GAS_OBJECTS_IN_PTB - 2,
     );
     let finalCoin;
-    const lockedAddresses: Set<string> = new Set();
-    initialLockedAddresses.forEach((value) => lockedAddresses.add(value));
+    const lockedAddresses = new Set<string>();
+    for (const value of initialLockedAddresses) lockedAddresses.add(value);
     for (let i = 0; i < gasCoinsChunks.length; i++) {
       const mergeTx = new Transaction();
       let coins = gasCoinsChunks[i];
@@ -493,15 +490,17 @@ export class SuiPricePusher implements IPricePusher {
           transaction: mergeTx,
           options: { showEffects: true },
         });
-      } catch (err) {
-        logger.error(err, "Merge transaction failed with error");
+      } catch (error_) {
+        logger.error(error_, "Merge transaction failed with error");
 
         if (
-          String(err).includes(
+          String(error_).includes(
             "quorum of validators because of locked objects. Retried a conflicting transaction",
           )
         ) {
-          Object.values((err as any).data).forEach((lockedObjects: any) => {
+          // eslint-disable-next-line unicorn/no-array-for-each
+          Object.values((error_ as any).data).forEach((lockedObjects: any) => {
+            // eslint-disable-next-line @typescript-eslint/no-unsafe-call, unicorn/no-array-for-each
             lockedObjects.forEach((lockedObject: [string, number, string]) => {
               lockedAddresses.add(lockedObject[0]);
             });
@@ -510,9 +509,9 @@ export class SuiPricePusher implements IPricePusher {
           i--;
           continue;
         }
-        throw err;
+        throw error_;
       }
-      const error = mergeResult?.effects?.status.error;
+      const error = mergeResult.effects?.status.error;
       if (error) {
         throw new Error(
           `Failed to merge coins when initializing gas pool: ${error}. Try re-running the script`,
@@ -521,11 +520,12 @@ export class SuiPricePusher implements IPricePusher {
       finalCoin = mergeResult.effects!.mutated!.map((obj) => obj.reference)[0];
     }
 
-    return finalCoin as SuiObjectRef;
+    // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
+    return finalCoin!;
   }
 }
 
-function chunkArray<T>(array: Array<T>, size: number): Array<Array<T>> {
+function chunkArray<T>(array: T[], size: number): T[][] {
   const chunked = [];
   let index = 0;
   while (index < array.length) {

+ 10 - 5
apps/price_pusher/src/ton/command.ts

@@ -1,15 +1,20 @@
+/* eslint-disable @typescript-eslint/no-unsafe-argument */
+/* eslint-disable @typescript-eslint/no-unsafe-assignment */
+/* eslint-disable @typescript-eslint/no-explicit-any */
+import fs from "node:fs";
+
+import { HermesClient } from "@pythnetwork/hermes-client";
+import { Address, TonClient } from "@ton/ton";
 import { pino } from "pino";
 import type { Options } from "yargs";
+
+import type { IPriceListener } from "../interface.js";
 import * as options from "../options.js";
 import { readPriceConfigFile } from "../price-config.js";
 import { PythPriceListener } from "../pyth-price-listener.js";
 import { TonPriceListener, TonPricePusher } from "./ton.js";
 import { Controller } from "../controller.js";
-import { Address, TonClient } from "@ton/ton";
-import fs from "fs";
-import { HermesClient } from "@pythnetwork/hermes-client";
 import { filterInvalidPriceItems } from "../utils.js";
-import type { IPriceListener } from "../interface.js";
 
 export default {
   command: "ton",
@@ -109,6 +114,6 @@ export default {
       { pushingFrequency },
     );
 
-    await controller.start();
+    void controller.start();
   },
 };

+ 23 - 26
apps/price_pusher/src/ton/ton.ts

@@ -1,25 +1,18 @@
+/* eslint-disable @typescript-eslint/no-explicit-any */
 import { HermesClient } from "@pythnetwork/hermes-client";
-import {
-  ChainPriceListener,
-  type IPricePusher,
-  type PriceInfo,
-  type PriceItem,
-} from "../interface.js";
-import { addLeading0x, type DurationInSeconds } from "../utils.js";
-import type { Logger } from "pino";
-import {
-  Address,
-  type ContractProvider,
-  type OpenedContract,
-  type Sender,
-  TonClient,
-  WalletContractV4,
-} from "@ton/ton";
-import { keyPairFromSeed } from "@ton/crypto";
 import {
   PythContract,
   calculateUpdatePriceFeedsFee,
 } from "@pythnetwork/pyth-ton-js";
+import { keyPairFromSeed } from "@ton/crypto";
+import type { ContractProvider, OpenedContract, Sender } from "@ton/ton";
+import { Address, TonClient, WalletContractV4 } from "@ton/ton";
+import type { Logger } from "pino";
+
+import type { IPricePusher, PriceInfo, PriceItem } from "../interface.js";
+import { ChainPriceListener } from "../interface.js";
+import type { DurationInSeconds } from "../utils.js";
+import { addLeading0x } from "../utils.js";
 
 export class TonPriceListener extends ChainPriceListener {
   private contract: OpenedContract<PythContract>;
@@ -45,9 +38,9 @@ export class TonPriceListener extends ChainPriceListener {
       const priceInfo = await this.contract.getPriceUnsafe(formattedPriceId);
 
       this.logger.debug(
-        `Polled a TON on chain price for feed ${this.priceIdToAlias.get(
-          priceId,
-        )} (${priceId}).`,
+        `Polled a TON on chain price for feed ${
+          this.priceIdToAlias.get(priceId) ?? ""
+        } (${priceId}).`,
       );
 
       return {
@@ -55,8 +48,11 @@ export class TonPriceListener extends ChainPriceListener {
         price: priceInfo.price.toString(),
         publishTime: priceInfo.publishTime,
       };
-    } catch (err) {
-      this.logger.error({ err, priceId }, `Polling on-chain price failed.`);
+    } catch (error) {
+      this.logger.error(
+        { err: error, priceId },
+        `Polling on-chain price failed.`,
+      );
       return undefined;
     }
   }
@@ -85,6 +81,7 @@ export class TonPricePusher implements IPricePusher {
     this.sender = provider.sender(keyPair.secretKey);
   }
 
+  // eslint-disable-next-line @typescript-eslint/no-unused-vars
   async updatePriceFeed(priceIds: string[], _: number[]): Promise<void> {
     if (priceIds.length === 0) {
       return;
@@ -97,8 +94,8 @@ export class TonPricePusher implements IPricePusher {
         ignoreInvalidPriceIds: true,
       });
       priceFeedUpdateData = response.binary.data;
-    } catch (err: any) {
-      this.logger.error(err, "getPriceFeedsUpdateData failed");
+    } catch (error: any) {
+      this.logger.error(error, "getPriceFeedsUpdateData failed");
       return;
     }
 
@@ -118,8 +115,8 @@ export class TonPricePusher implements IPricePusher {
       }
 
       this.logger.info("updatePriceFeed successful");
-    } catch (err: any) {
-      this.logger.error(err, "updatePriceFeed failed");
+    } catch (error: any) {
+      this.logger.error(error, "updatePriceFeed failed");
     }
   }
 }

+ 15 - 7
apps/price_pusher/src/utils.ts

@@ -1,4 +1,9 @@
-import { HermesClient, type HexString } from "@pythnetwork/hermes-client";
+/* eslint-disable @typescript-eslint/no-unsafe-return */
+/* eslint-disable @typescript-eslint/no-unnecessary-type-parameters */
+/* eslint-disable @typescript-eslint/no-explicit-any */
+import type { HexString } from "@pythnetwork/hermes-client";
+import { HermesClient } from "@pythnetwork/hermes-client";
+
 import type { PriceItem } from "./interface.js";
 
 export type PctNumber = number;
@@ -14,7 +19,7 @@ export async function sleep(ms: number): Promise<void> {
 
 export function removeLeading0x(id: HexString): HexString {
   if (id.startsWith("0x")) {
-    return id.substring(2);
+    return id.slice(2);
   }
   return id;
 }
@@ -37,14 +42,14 @@ export function isWsEndpoint(endpoint: string): boolean {
 }
 
 export function verifyValidOption<
-  options extends Readonly<Array<any>>,
+  options extends readonly any[],
   validOption extends options[number],
 >(option: any, validOptions: options) {
   if (validOptions.includes(option)) {
     return option as validOption;
   }
-  const errorString =
-    option + " is not a valid option. Please choose between " + validOptions;
+  // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+  const errorString = `${option} is not a valid option. Please choose betweeen ${validOptions}`;
   throw new Error(errorString);
 }
 
@@ -64,15 +69,18 @@ export async function filterInvalidPriceItems(
   invalidPriceItems: PriceItem[];
 }> {
   const priceMetadata = await hermesClient.getPriceFeeds();
-  const allPriceIds = priceMetadata.map((priceMetadata) => priceMetadata.id);
+  const allPriceIds = new Set(
+    priceMetadata.map((priceMetadata) => priceMetadata.id),
+  );
 
   // Filter out invalid price ids
+  // eslint-disable-next-line unicorn/no-array-reduce
   const { existingPriceItems, invalidPriceItems } = priceItems.reduce<{
     existingPriceItems: PriceItem[];
     invalidPriceItems: PriceItem[];
   }>(
     (acc, item) => {
-      if (allPriceIds.includes(item.id)) {
+      if (allPriceIds.has(item.id)) {
         acc.existingPriceItems.push(item);
       } else {
         acc.invalidPriceItems.push(item);

+ 1 - 1
apps/staking/package.json

@@ -75,4 +75,4 @@
     "vercel": "catalog:"
   },
   "packageManager": "pnpm@10.19.0"
-}
+}

+ 2 - 7
apps/staking/tsconfig.build.json

@@ -5,10 +5,5 @@
     "incremental": false,
     "declaration": true
   },
-  "exclude": [
-    "node_modules",
-    "dist",
-    "examples/",
-    "**/__tests__/*"
-  ]
-}
+  "exclude": ["node_modules", "dist", "examples/", "**/__tests__/*"]
+}

+ 11 - 13
contract_manager/scripts/batchDeployReceivers.ts

@@ -3,17 +3,19 @@
  * wormhole addresses to the deployed receiver contracts.
  */
 
-import yargs from "yargs";
-import { hideBin } from "yargs/helpers";
+import * as fs from "node:fs";
+
 import {
   DefaultStore,
   EvmChain,
   loadHotWallet,
   EvmWormholeContract,
 } from "@pythnetwork/contract-manager";
-import Web3 from "web3";
 import { CHAINS } from "@pythnetwork/xc-admin-common";
-import * as fs from "fs";
+import Web3 from "web3";
+import yargs from "yargs";
+import { hideBin } from "yargs/helpers";
+
 
 import { getDefaultConfig } from "../../target_chains/ethereum/contracts/scripts/contractManagerConfig";
 
@@ -63,14 +65,14 @@ async function memoize(
 async function main() {
   const argv = await parser.argv;
   const privateKey = argv["private-key"];
-  const network = argv["network"];
+  const network = argv.network;
 
-  const setupInfo = await import(argv["contract"] + "/ReceiverSetup.json");
+  const setupInfo = await import(argv.contract + "/ReceiverSetup.json");
   const implementationInfo = await import(
-    argv["contract"] + "/ReceiverImplementation.json"
+    argv.contract + "/ReceiverImplementation.json"
   );
   const receiverInfo = await import(
-    argv["contract"] + "/WormholeReceiver.json"
+    argv.contract + "/WormholeReceiver.json"
   );
 
   const payloads: Buffer[] = [];
@@ -133,11 +135,7 @@ async function main() {
     }
   }
   let vaultName;
-  if (network === "mainnet") {
-    vaultName = "mainnet-beta_FVQyHcooAtThJ83XFrNnv74BcinbRH3bRmfFamAHBfuj";
-  } else {
-    vaultName = "devnet_6baWtW1zTUVMSJHJQVxDUXWzqrQeYBr6mu31j3bTKwY3";
-  }
+  vaultName = network === "mainnet" ? "mainnet-beta_FVQyHcooAtThJ83XFrNnv74BcinbRH3bRmfFamAHBfuj" : "devnet_6baWtW1zTUVMSJHJQVxDUXWzqrQeYBr6mu31j3bTKwY3";
   const vault = DefaultStore.vaults[vaultName];
   vault.connect(await loadHotWallet(argv["ops-wallet"]));
   await vault.proposeWormholeMessage(payloads);

+ 18 - 13
contract_manager/scripts/check_proposal.ts

@@ -1,8 +1,10 @@
-import yargs from "yargs";
-import { hideBin } from "yargs/helpers";
-import { CosmWasmChain, EvmChain } from "../src/core/chains";
-import { createHash } from "crypto";
-import { DefaultStore } from "../src/node/utils/store";
+import { createHash } from "node:crypto";
+
+import NodeWallet from "@coral-xyz/anchor/dist/cjs/nodewallet";
+import {
+  getPythClusterApiUrl,
+  PythCluster,
+} from "@pythnetwork/client/lib/cluster";
 import {
   CosmosUpgradeContract,
   EvmExecute,
@@ -12,20 +14,23 @@ import {
   MultisigParser,
   WormholeMultisigInstruction,
 } from "@pythnetwork/xc-admin-common";
-import SquadsMesh from "@sqds/mesh";
-import {
-  getPythClusterApiUrl,
-  PythCluster,
-} from "@pythnetwork/client/lib/cluster";
-import NodeWallet from "@coral-xyz/anchor/dist/cjs/nodewallet";
 import { AccountMeta, Keypair, PublicKey } from "@solana/web3.js";
+import SquadsMesh from "@sqds/mesh";
+import Web3 from "web3";
+import yargs from "yargs";
+import { hideBin } from "yargs/helpers";
+
+import { CosmWasmChain, EvmChain } from "../src/core/chains";
 import {
   EvmEntropyContract,
   EvmPriceFeedContract,
   getCodeDigestWithoutAddress,
   EvmWormholeContract,
 } from "../src/core/contracts/evm";
-import Web3 from "web3";
+import { DefaultStore } from "../src/node/utils/store";
+
+
+
 
 const parser = yargs(hideBin(process.argv))
   .usage("Usage: $0 --cluster <cluster_id> --proposal <proposal_address>")
@@ -179,7 +184,7 @@ async function main() {
               .encodeFunctionSignature(invokedMethod)
               .replace("0x", "");
 
-            let newImplementationAddress: string | undefined = undefined;
+            let newImplementationAddress: string | undefined;
             if (calldataHex.startsWith(methodSignature)) {
               newImplementationAddress = web3.eth.abi.decodeParameter(
                 "address",

+ 14 - 13
contract_manager/scripts/common.ts

@@ -1,9 +1,10 @@
-import { DefaultStore } from "../src/node/utils/store";
-import { existsSync, readFileSync, writeFileSync } from "fs";
-import { join } from "path";
+import { existsSync, readFileSync, writeFileSync } from "node:fs";
+import { join } from "node:path";
+
 import Web3 from "web3";
 import { Contract } from "web3-eth-contract";
 import { InferredOptionType } from "yargs";
+
 import { PrivateKey, getDefaultDeploymentConfig } from "../src/core/base";
 import { EvmChain } from "../src/core/chains";
 import {
@@ -11,8 +12,9 @@ import {
   EvmExecutorContract,
   EvmWormholeContract,
 } from "../src/core/contracts";
+import { DefaultStore } from "../src/node/utils/store";
 
-export interface BaseDeployConfig {
+export type BaseDeployConfig = {
   gasMultiplier: number;
   gasPriceMultiplier: number;
   jsonOutputDir: string;
@@ -46,7 +48,7 @@ export async function deployIfNotCached(
     );
 
     // Handle bytecode which can be either a string or an object with an 'object' property
-    let bytecode = artifact["bytecode"];
+    let bytecode = artifact.bytecode;
     if (
       typeof bytecode === "object" &&
       bytecode !== null &&
@@ -63,7 +65,7 @@ export async function deployIfNotCached(
     console.log(`Deploying ${artifactName} on ${chain.getId()}...`);
     const addr = await chain.deploy(
       config.privateKey,
-      artifact["abi"],
+      artifact.abi,
       bytecode,
       deployArgs,
       config.gasMultiplier,
@@ -87,7 +89,7 @@ export function getWeb3Contract(
     ),
   );
   const web3 = new Web3();
-  return new web3.eth.Contract(artifact["abi"], address);
+  return new web3.eth.Contract(artifact.abi, address);
 }
 
 export const COMMON_DEPLOY_OPTIONS = {
@@ -272,11 +274,10 @@ export function findExecutorContract(
   }
 }
 
-export interface DeployWormholeReceiverContractsConfig
-  extends BaseDeployConfig {
+export type DeployWormholeReceiverContractsConfig = {
   saveContract: boolean;
   type: "stable" | "beta";
-}
+} & BaseDeployConfig
 /**
  * Deploys the wormhole receiver contract for a given EVM chain.
  * @param {EvmChain} chain The EVM chain to find the wormhole receiver contract for.
@@ -369,7 +370,7 @@ export async function getOrDeployWormholeContract(
   );
 }
 
-export interface DefaultAddresses {
+export type DefaultAddresses = {
   mainnet: string;
   testnet: string;
 }
@@ -377,7 +378,7 @@ export interface DefaultAddresses {
 export async function topupAccountsIfNecessary(
   chain: EvmChain,
   deploymentConfig: BaseDeployConfig,
-  accounts: Array<[string, DefaultAddresses]>,
+  accounts: [string, DefaultAddresses][],
   minBalance = 0.01,
 ) {
   for (const [accountName, defaultAddresses] of accounts) {
@@ -411,7 +412,7 @@ export async function topupAccountsIfNecessary(
       });
 
       console.log(
-        `Topped up the ${accountName} address. Tx: `,
+        `Topped up the ${accountName} address. Tx:`,
         tx.transactionHash,
       );
     }

+ 2 - 1
contract_manager/scripts/deploy_cosmwasm.ts

@@ -1,10 +1,11 @@
 import yargs from "yargs";
 import { hideBin } from "yargs/helpers";
+
+import { COMMON_DEPLOY_OPTIONS } from "./common";
 import { CosmWasmChain } from "../src/core/chains";
 import { CosmWasmPriceFeedContract } from "../src/core/contracts/cosmwasm";
 import { DefaultStore } from "../src/node/utils/store";
 
-import { COMMON_DEPLOY_OPTIONS } from "./common";
 
 const parser = yargs(hideBin(process.argv))
   .scriptName("deploy_cosmwasm.ts")

+ 7 - 6
contract_manager/scripts/deploy_evm_contract.ts

@@ -1,11 +1,12 @@
+import { readFileSync } from "node:fs";
+
 import yargs from "yargs";
 import { hideBin } from "yargs/helpers";
-import { EvmChain } from "../src/core/chains";
-import { DefaultStore } from "../src/node/utils/store";
-import { readFileSync } from "fs";
-import { toPrivateKey } from "../src/core/base";
 
 import { COMMON_DEPLOY_OPTIONS } from "./common";
+import { toPrivateKey } from "../src/core/base";
+import { EvmChain } from "../src/core/chains";
+import { DefaultStore } from "../src/node/utils/store";
 
 const parser = yargs(hideBin(process.argv))
   .scriptName("deploy_evm_contract.ts")
@@ -37,8 +38,8 @@ async function main() {
   const artifact = JSON.parse(readFileSync(argv["std-output"], "utf8"));
   const address = await chain.deploy(
     toPrivateKey(argv["private-key"]),
-    artifact["abi"],
-    artifact["bytecode"].object, // As per the artifacts generated by forge, bytecode is an object with an 'object' property
+    artifact.abi,
+    artifact.bytecode.object, // As per the artifacts generated by forge, bytecode is an object with an 'object' property
     argv["deploy-args"] || [],
   );
 

+ 16 - 15
contract_manager/scripts/deploy_evm_entropy_contracts.ts

@@ -1,17 +1,6 @@
 import yargs from "yargs";
 import { hideBin } from "yargs/helpers";
-import { EvmChain } from "../src/core/chains";
-import { DefaultStore } from "../src/node/utils/store";
-import {
-  ENTROPY_DEFAULT_KEEPER,
-  ENTROPY_DEFAULT_PROVIDER,
-  EvmEntropyContract,
-} from "../src/core/contracts/evm";
-import {
-  DeploymentType,
-  toDeploymentType,
-  toPrivateKey,
-} from "../src/core/base";
+
 import {
   COMMON_DEPLOY_OPTIONS,
   deployIfNotCached,
@@ -22,11 +11,23 @@ import {
   DefaultAddresses,
 } from "./common";
 import { getOrDeployExecutorContract } from "./deploy_evm_executor_contracts";
+import {
+  DeploymentType,
+  toDeploymentType,
+  toPrivateKey,
+} from "../src/core/base";
+import { EvmChain } from "../src/core/chains";
+import {
+  ENTROPY_DEFAULT_KEEPER,
+  ENTROPY_DEFAULT_PROVIDER,
+  EvmEntropyContract,
+} from "../src/core/contracts/evm";
+import { DefaultStore } from "../src/node/utils/store";
 
-interface DeploymentConfig extends BaseDeployConfig {
+type DeploymentConfig = {
   type: DeploymentType;
   saveContract: boolean;
-}
+} & BaseDeployConfig
 
 const CACHE_FILE = ".cache-deploy-evm-entropy-contracts";
 
@@ -92,7 +93,7 @@ async function topupEntropyAccountsIfNecessary(
   chain: EvmChain,
   deploymentConfig: DeploymentConfig,
 ) {
-  const accounts: Array<[string, DefaultAddresses]> = [
+  const accounts: [string, DefaultAddresses][] = [
     ["keeper", ENTROPY_DEFAULT_KEEPER],
     ["provider", ENTROPY_DEFAULT_PROVIDER],
   ];

+ 5 - 4
contract_manager/scripts/deploy_evm_executor_contracts.ts

@@ -1,6 +1,6 @@
 import yargs from "yargs";
 import { hideBin } from "yargs/helpers";
-import { EvmChain } from "../src/core/chains";
+
 import {
   BaseDeployConfig,
   COMMON_DEPLOY_OPTIONS,
@@ -15,8 +15,9 @@ import {
   toDeploymentType,
   toPrivateKey,
 } from "../src/core/base";
-import { DefaultStore } from "../src/node/utils/store";
+import { EvmChain } from "../src/core/chains";
 import { EvmExecutorContract } from "../src/core/contracts/evm";
+import { DefaultStore } from "../src/node/utils/store";
 
 const CACHE_FILE = ".cache-deploy-evm-executor";
 
@@ -34,10 +35,10 @@ const parser = yargs(hideBin(process.argv))
     },
   });
 
-interface DeploymentConfig extends BaseDeployConfig {
+type DeploymentConfig = {
   type: DeploymentType;
   saveContract: boolean;
-}
+} & BaseDeployConfig
 
 export async function getOrDeployExecutorContract(
   chain: EvmChain,

+ 7 - 5
contract_manager/scripts/deploy_evm_lazer_contracts.ts

@@ -38,14 +38,16 @@
  * - All operations use the chain's RPC URL from the DefaultStore
  */
 
+import { execSync } from "node:child_process";
+import { join } from "node:path";
+
 import yargs from "yargs";
 import { hideBin } from "yargs/helpers";
-import { execSync } from "child_process";
-import { join } from "path";
-import { DefaultStore } from "../src/node/utils/store";
+
+import { toPrivateKey, PrivateKey } from "../src/core/base";
 import { EvmChain } from "../src/core/chains";
 import { EvmLazerContract } from "../src/core/contracts/evm";
-import { toPrivateKey, PrivateKey } from "../src/core/base";
+import { DefaultStore } from "../src/node/utils/store";
 
 const parser = yargs(hideBin(process.argv))
   .usage(
@@ -153,7 +155,7 @@ async function deployPythLazerContract(
     console.log(output);
 
     // Extract proxy address from output
-    const proxyMatch = output.match(/Deployed proxy to: (0x[a-fA-F0-9]{40})/);
+    const proxyMatch = /Deployed proxy to: (0x[a-fA-F0-9]{40})/.exec(output);
     if (!proxyMatch) {
       throw new Error("Could not extract proxy address from deployment output");
     }

+ 6 - 5
contract_manager/scripts/deploy_evm_pricefeed_contracts.ts

@@ -1,5 +1,7 @@
+import { HermesClient } from "@pythnetwork/hermes-client";
 import yargs from "yargs";
 import { hideBin } from "yargs/helpers";
+
 import {
   COMMON_DEPLOY_OPTIONS,
   deployIfNotCached,
@@ -7,7 +9,6 @@ import {
   getOrDeployWormholeContract,
   BaseDeployConfig,
 } from "./common";
-import { HermesClient } from "@pythnetwork/hermes-client";
 import {
   DeploymentType,
   getDefaultDeploymentConfig,
@@ -18,12 +19,12 @@ import { EvmChain } from "../src/core/chains";
 import { EvmPriceFeedContract } from "../src/core/contracts";
 import { DefaultStore } from "../src/node/utils/store";
 
-interface DeploymentConfig extends BaseDeployConfig {
+type DeploymentConfig = {
   type: DeploymentType;
   validTimePeriodSeconds: number;
   singleUpdateFeeInWei: number;
   saveContract: boolean;
-}
+} & BaseDeployConfig
 
 const CACHE_FILE = ".cache-deploy-evm";
 
@@ -115,7 +116,7 @@ async function main() {
   const nativeTokenDecimals = argv["native-token-decimals"];
   if (
     singleUpdateFeeInUsd &&
-    (nativeTokenPriceFeedId == null || nativeTokenDecimals == null)
+    (nativeTokenPriceFeedId == undefined || nativeTokenDecimals == undefined)
   ) {
     throw new Error(
       "native-token-price-feed-id and native-token-decimals are required when single-update-fee-in-usd is provided",
@@ -132,7 +133,7 @@ async function main() {
     );
 
     const price = priceObject.parsed?.[0].price;
-    if (price == null) {
+    if (price == undefined) {
       throw new Error("Failed to get price of the native token");
     }
     const priceInUsd = Number(price.price);

+ 8 - 6
contract_manager/scripts/deploy_evm_pulse_contracts.ts

@@ -1,5 +1,9 @@
+import fs from "node:fs";
+import path from "node:path";
+
 import yargs from "yargs";
 import { hideBin } from "yargs/helpers";
+
 import {
   COMMON_DEPLOY_OPTIONS,
   deployIfNotCached,
@@ -9,8 +13,6 @@ import {
   topupAccountsIfNecessary,
   DefaultAddresses,
 } from "./common";
-import fs from "fs";
-import path from "path";
 import {
   DeploymentType,
   toDeploymentType,
@@ -24,10 +26,10 @@ import {
 } from "../src/core/contracts";
 import { DefaultStore } from "../src/node/utils/store";
 
-interface DeploymentConfig extends BaseDeployConfig {
+type DeploymentConfig = {
   type: DeploymentType;
   saveContract: boolean;
-}
+} & BaseDeployConfig
 
 const CACHE_FILE = ".cache-deploy-evm-pulse-contracts";
 
@@ -112,7 +114,7 @@ async function topupPulseAccountsIfNecessary(
   chain: EvmChain,
   deploymentConfig: DeploymentConfig,
 ) {
-  const accounts: Array<[string, DefaultAddresses]> = [
+  const accounts: [string, DefaultAddresses][] = [
     ["keeper", PULSE_DEFAULT_KEEPER],
     ["provider", PULSE_DEFAULT_PROVIDER],
   ];
@@ -128,7 +130,7 @@ async function main() {
   if (!chain) {
     throw new Error(`Chain ${chainName} not found`);
   } else if (!(chain instanceof EvmChain)) {
-    throw new Error(`Chain ${chainName} is not an EVM chain`);
+    throw new TypeError(`Chain ${chainName} is not an EVM chain`);
   }
 
   const deploymentConfig: DeploymentConfig = {

+ 3 - 2
contract_manager/scripts/entropy-accept-admin-and-ownership.ts

@@ -1,5 +1,6 @@
 import yargs from "yargs";
 import { hideBin } from "yargs/helpers";
+
 import { EvmChain } from "../src/core/chains";
 import { loadHotWallet } from "../src/node/utils/governance";
 import { DefaultStore } from "../src/node/utils/store";
@@ -67,7 +68,7 @@ async function main() {
   const payloads: Buffer[] = [];
   for (const contract of Object.values(DefaultStore.entropy_contracts)) {
     if (selectedChains.includes(contract.chain)) {
-      console.log("Creating payload for chain: ", contract.chain.getId());
+      console.log("Creating payload for chain:", contract.chain.getId());
       const pendingOwner = await contract.getPendingOwner();
       const adminPayload = contract.generateAcceptAdminPayload(pendingOwner);
       const ownerPayload =
@@ -79,7 +80,7 @@ async function main() {
 
   console.log("Using vault at for proposal", vault.getId());
   const wallet = await loadHotWallet(argv["ops-key-path"]);
-  console.log("Using wallet ", wallet.publicKey.toBase58());
+  console.log("Using wallet", wallet.publicKey.toBase58());
   await vault.connect(wallet);
   const proposal = await vault.proposeWormholeMessage(payloads);
   console.log("Proposal address", proposal.address.toBase58());

+ 9 - 8
contract_manager/scripts/entropy_debug_reveal.ts

@@ -1,5 +1,6 @@
 import yargs from "yargs";
 import { hideBin } from "yargs/helpers";
+
 import { COMMON_DEPLOY_OPTIONS, findEntropyContract } from "./common";
 import { toPrivateKey } from "../src/core/base";
 import { EvmChain } from "../src/core/chains";
@@ -58,24 +59,24 @@ async function main() {
     sequenceNumber < endingSequenceNumber;
     sequenceNumber++
   ) {
-    console.log("Revealing request for sequence number: ", sequenceNumber);
+    console.log("Revealing request for sequence number:", sequenceNumber);
     const request = await contract.getRequest(provider, sequenceNumber);
     if (request.sequenceNumber === "0") {
       console.log("Request not found");
       continue;
     }
-    console.log("Request block number: ", request.blockNumber);
+    console.log("Request block number:", request.blockNumber);
     const userRandomNumber = await contract.getUserRandomNumber(
       provider,
       sequenceNumber,
-      parseInt(request.blockNumber),
+      Number.parseInt(request.blockNumber),
     );
-    console.log("User random number: ", userRandomNumber);
+    console.log("User random number:", userRandomNumber);
     const revealUrl = providerInfo.uri + `/revelations/${sequenceNumber}`;
     const fortunaResponse = await fetch(revealUrl);
     if (fortunaResponse.status !== 200) {
-      console.error("Fortuna response status: ", fortunaResponse.status);
-      console.error("Fortuna response body: ", await fortunaResponse.text());
+      console.error("Fortuna response status:", fortunaResponse.status);
+      console.error("Fortuna response body:", await fortunaResponse.text());
       console.error(
         "Refusing to continue the script, please check the Fortuna service first.",
       );
@@ -91,8 +92,8 @@ async function main() {
         sequenceNumber,
         privateKey,
       );
-    } catch (e) {
-      console.error("Error revealing request: ", e);
+    } catch (error) {
+      console.error("Error revealing request:", error);
       continue;
     }
   }

+ 11 - 19
contract_manager/scripts/execute_vaas.ts

@@ -1,12 +1,12 @@
-import yargs from "yargs";
-import { hideBin } from "yargs/helpers";
 import { parseVaa } from "@certusone/wormhole-sdk";
 import { decodeGovernancePayload } from "@pythnetwork/xc-admin-common";
+import yargs from "yargs";
+import { hideBin } from "yargs/helpers";
+
 import { COMMON_DEPLOY_OPTIONS } from "./common";
-import { Vault } from "../src/node/utils/governance";
 import { toPrivateKey } from "../src/core/base";
-import { SubmittedWormholeMessage } from "../src/node/utils/governance";
 import { executeVaa } from "../src/node/utils/executor";
+import { Vault , SubmittedWormholeMessage } from "../src/node/utils/governance";
 import { DefaultStore } from "../src/node/utils/store";
 
 const parser = yargs(hideBin(process.argv))
@@ -49,17 +49,9 @@ const parser = yargs(hideBin(process.argv))
 async function main() {
   const argv = await parser.argv;
   let vault: Vault;
-  if (argv.vault === "mainnet") {
-    vault =
-      DefaultStore.vaults[
+  vault = argv.vault === "mainnet" ? DefaultStore.vaults[
         "mainnet-beta_FVQyHcooAtThJ83XFrNnv74BcinbRH3bRmfFamAHBfuj"
-      ];
-  } else {
-    vault =
-      DefaultStore.vaults[
-        "devnet_6baWtW1zTUVMSJHJQVxDUXWzqrQeYBr6mu31j3bTKwY3"
-      ];
-  }
+      ] : DefaultStore.vaults.devnet_6baWtW1zTUVMSJHJQVxDUXWzqrQeYBr6mu31j3bTKwY3;
   console.log("Executing VAAs for vault", vault.getId());
   console.log(
     "Executing VAAs for emitter",
@@ -72,13 +64,13 @@ async function main() {
   if (argv.sequence !== undefined) {
     startSequenceNumber = argv.sequence;
     endSequenceNumber = argv.sequence;
-  } else if (argv.offset !== undefined) {
+  } else if (argv.offset === undefined) {
+    // this is unreachable but it makes the typescript linter happy.
+    throw new Error("Either --offset or --sequence must be provided");
+  } else {
     const lastSequenceNumber = await vault.getLastSequenceNumber();
     startSequenceNumber = lastSequenceNumber - argv.offset;
     endSequenceNumber = lastSequenceNumber;
-  } else {
-    // this is unreachable but it makes the typescript linter happy.
-    throw new Error("Either --offset or --sequence must be provided");
   }
 
   console.log(
@@ -98,7 +90,7 @@ async function main() {
     const vaa = await submittedWormholeMessage.fetchVaa();
     const decodedAction = decodeGovernancePayload(parseVaa(vaa).payload);
     if (!decodedAction) {
-      console.log("Skipping unknown action for vaa ", seqNumber);
+      console.log("Skipping unknown action for vaa", seqNumber);
       continue;
     }
     console.log("Executing vaa", seqNumber);

+ 3 - 2
contract_manager/scripts/fetch_account_balance.ts

@@ -1,5 +1,6 @@
 import yargs from "yargs";
 import { hideBin } from "yargs/helpers";
+
 import { PrivateKey, toPrivateKey } from "../src/core/base";
 import { DefaultStore } from "../src/node/utils/store";
 
@@ -35,8 +36,8 @@ async function getBalance(
     const balance =
       await DefaultStore.chains[chain].getAccountBalance(privateKey);
     return { chain, address, balance };
-  } catch (e) {
-    console.error(`Error fetching balance for ${chain}`, e);
+  } catch (error) {
+    console.error(`Error fetching balance for ${chain}`, error);
   }
   return { chain, address, balance: undefined };
 }

+ 4 - 3
contract_manager/scripts/fetch_accrued_entropy_dao_fees.ts

@@ -1,9 +1,10 @@
 import yargs from "yargs";
 import { hideBin } from "yargs/helpers";
-import { DefaultStore } from "../src/node/utils/store";
+
+import { findEntropyContract } from "./common";
 import { EvmChain } from "../src/core/chains";
 import { EvmEntropyContract } from "../src/core/contracts";
-import { findEntropyContract } from "./common";
+import { DefaultStore } from "../src/node/utils/store";
 
 const parser = yargs(hideBin(process.argv))
   .usage(
@@ -35,7 +36,7 @@ const parser = yargs(hideBin(process.argv))
     return true;
   });
 
-interface FeeResult {
+type FeeResult = {
   chainId: string;
   contractAddress: string;
   accruedFees: string;

+ 3 - 2
contract_manager/scripts/fetch_fees.ts

@@ -1,5 +1,6 @@
 import yargs from "yargs";
 import { hideBin } from "yargs/helpers";
+
 import {
   AptosPriceFeedContract,
   CosmWasmPriceFeedContract,
@@ -54,8 +55,8 @@ async function main() {
             `${contract.getId()} ${fee.amount} ${fee.denom} ($ value unknown)`,
           );
         }
-      } catch (e) {
-        console.error(`Error fetching fees for ${contract.getId()}`, e);
+      } catch (error) {
+        console.error(`Error fetching fees for ${contract.getId()}`, error);
       }
     }
   }

+ 3 - 2
contract_manager/scripts/generate_evm_lazer_update_trusted_signer_proposal.ts

@@ -1,7 +1,8 @@
 import yargs from "yargs";
 import { hideBin } from "yargs/helpers";
-import { DefaultStore } from "../src/node/utils/store";
+
 import { loadHotWallet } from "../src/node/utils/governance";
+import { DefaultStore } from "../src/node/utils/store";
 
 const parser = yargs(hideBin(process.argv))
   .usage("Usage: $0 --config <path/to/config.json>")
@@ -61,7 +62,7 @@ async function main() {
 
   console.log("Using vault at for proposal", vault.getId());
   const wallet = await loadHotWallet(argv["ops-key-path"]);
-  console.log("Using wallet ", wallet.publicKey.toBase58());
+  console.log("Using wallet", wallet.publicKey.toBase58());
   await vault.connect(wallet);
   const proposal = await vault.proposeWormholeMessage(updatePayloads);
   console.log("Proposal address", proposal.address.toBase58());

+ 2 - 1
contract_manager/scripts/generate_governance_set_fee_payload.ts

@@ -1,7 +1,8 @@
 import yargs from "yargs";
 import { hideBin } from "yargs/helpers";
-import { DefaultStore } from "../src/node/utils/store";
+
 import { loadHotWallet } from "../src/node/utils/governance";
+import { DefaultStore } from "../src/node/utils/store";
 
 const parser = yargs(hideBin(process.argv))
   .usage("Usage: $0 --config <path/to/config.json>")

+ 4 - 3
contract_manager/scripts/generate_upgrade_near_contract_proposal.ts

@@ -1,8 +1,9 @@
 import yargs from "yargs";
 import { hideBin } from "yargs/helpers";
-import { DefaultStore } from "../src/node/utils/store";
-import { loadHotWallet } from "../src/node/utils/governance";
+
 import { NearChain } from "../src/core/chains";
+import { loadHotWallet } from "../src/node/utils/governance";
+import { DefaultStore } from "../src/node/utils/store";
 
 const parser = yargs(hideBin(process.argv))
   .usage(
@@ -55,7 +56,7 @@ async function main() {
 
   // Create and submit governance proposal
   console.log("Using vault for proposal:", vault.getId());
-  const keypair = await loadHotWallet(argv["ops-key-path"] as string);
+  const keypair = await loadHotWallet(argv["ops-key-path"]);
   console.log("Using wallet:", keypair.publicKey.toBase58());
   vault.connect(keypair);
   const proposal = await vault.proposeWormholeMessage([payload]);

+ 8 - 6
contract_manager/scripts/generate_upgrade_ton_contract_proposal.ts

@@ -1,11 +1,13 @@
+import fs from "node:fs";
+import path from "node:path";
+
+import { CHAINS, toChainName } from "@pythnetwork/xc-admin-common";
 import yargs from "yargs";
 import { hideBin } from "yargs/helpers";
-import { DefaultStore } from "../src/node/utils/store";
-import { loadHotWallet } from "../src/node/utils/governance";
+
 import { TonChain } from "../src/core/chains";
-import { CHAINS, toChainName } from "@pythnetwork/xc-admin-common";
-import fs from "fs";
-import path from "path";
+import { loadHotWallet } from "../src/node/utils/governance";
+import { DefaultStore } from "../src/node/utils/store";
 
 const parser = yargs(hideBin(process.argv))
   .usage(
@@ -74,7 +76,7 @@ async function main() {
 
   // Create and submit governance proposal
   console.log("Using vault for proposal:", vault.getId());
-  const keypair = await loadHotWallet(argv["ops-key-path"] as string);
+  const keypair = await loadHotWallet(argv["ops-key-path"]);
   console.log("Using wallet:", keypair.publicKey.toBase58());
   vault.connect(keypair);
   const proposal = await vault.proposeWormholeMessage([payload]);

+ 3 - 2
contract_manager/scripts/get_entropy_registration.ts

@@ -1,5 +1,6 @@
 import yargs from "yargs";
 import { hideBin } from "yargs/helpers";
+
 import { DefaultStore } from "../src/node/utils/store";
 
 function deserializeCommitmentMetadata(data: Buffer) {
@@ -32,8 +33,8 @@ async function main() {
     try {
       provider = await contract.getDefaultProvider();
       providerInfo = await contract.getProviderInfo(provider);
-    } catch (e) {
-      console.error(`Error fetching info for ${contract.getId()}`, e);
+    } catch (error) {
+      console.error(`Error fetching info for ${contract.getId()}`, error);
       continue;
     }
 

+ 7 - 6
contract_manager/scripts/latency_entropy.ts

@@ -1,9 +1,10 @@
 import yargs from "yargs";
 import { hideBin } from "yargs/helpers";
-import { DefaultStore } from "../src/node/utils/store";
-import { EvmChain } from "../src/core/chains";
-import { toPrivateKey } from "../src/core/base";
+
 import { COMMON_DEPLOY_OPTIONS, findEntropyContract } from "./common";
+import { toPrivateKey } from "../src/core/base";
+import { EvmChain } from "../src/core/chains";
+import { DefaultStore } from "../src/node/utils/store";
 
 const parser = yargs(hideBin(process.argv))
   .usage(
@@ -34,12 +35,12 @@ async function main() {
     provider,
     privateKey,
   );
-  console.log("Request tx hash: ", requestResponse.transactionHash);
+  console.log("Request tx hash:", requestResponse.transactionHash);
   const startTime = Date.now();
   const sequenceNumber = providerInfo.sequenceNumber;
   const revealUrl = providerInfo.uri + `/revelations/${sequenceNumber}`;
   console.log("Checking this url for revelation:", revealUrl);
-  // eslint-disable-next-line no-constant-condition
+   
   while (true) {
     const fortunaResponse = await fetch(revealUrl);
     if (fortunaResponse.status === 200) {
@@ -54,7 +55,7 @@ async function main() {
         sequenceNumber,
         privateKey,
       );
-      console.log("Reveal tx hash: ", revealResponse.transactionHash);
+      console.log("Reveal tx hash:", revealResponse.transactionHash);
       break;
     }
     await new Promise((resolve) => setTimeout(resolve, 300));

+ 4 - 3
contract_manager/scripts/latency_entropy_with_callback.ts

@@ -1,10 +1,11 @@
 import yargs from "yargs";
 import { hideBin } from "yargs/helpers";
+
+import { COMMON_DEPLOY_OPTIONS, findEntropyContract } from "./common";
 import { PrivateKey, toPrivateKey } from "../src/core/base";
 import { EvmChain } from "../src/core/chains";
 import { EvmEntropyContract } from "../src/core/contracts";
 import { DefaultStore } from "../src/node/utils/store";
-import { COMMON_DEPLOY_OPTIONS, findEntropyContract } from "./common";
 
 const parser = yargs(hideBin(process.argv))
   .usage(
@@ -57,7 +58,7 @@ async function testLatency(
   const web3 = contract.chain.getWeb3();
   const entropyContract = contract.getContract();
 
-  // eslint-disable-next-line no-constant-condition
+   
   while (true) {
     await new Promise((resolve) => setTimeout(resolve, 1000));
     const currentBlock = await web3.eth.getBlockNumber();
@@ -86,7 +87,7 @@ async function testLatency(
       );
       break;
     }
-    if (Date.now() - startTime > 60000) {
+    if (Date.now() - startTime > 60_000) {
       console.log("Timeout: 60s passed without the callback being called.");
       break;
     }

+ 6 - 5
contract_manager/scripts/list_entropy_contracts.ts

@@ -1,8 +1,9 @@
+import Web3 from "web3";
 import yargs from "yargs";
 import { hideBin } from "yargs/helpers";
-import { DefaultStore } from "../src/node/utils/store";
+
 import { ENTROPY_DEFAULT_KEEPER } from "../src/core/contracts";
-import Web3 from "web3";
+import { DefaultStore } from "../src/node/utils/store";
 
 const parser = yargs(hideBin(process.argv))
   .usage("Usage: $0")
@@ -40,7 +41,7 @@ async function main() {
       let version = "unknown";
       try {
         version = await contract.getVersion();
-      } catch (e) {
+      } catch {
         /* old deployments did not have this method */
       }
       const providerInfo = await contract.getProviderInfo(provider);
@@ -58,8 +59,8 @@ async function main() {
         version,
       });
       console.log(`Fetched info for ${contract.getId()}`);
-    } catch (e) {
-      console.error(`Error fetching info for ${contract.getId()}`, e);
+    } catch (error) {
+      console.error(`Error fetching info for ${contract.getId()}`, error);
     }
   }
   console.table(entries);

+ 4 - 3
contract_manager/scripts/list_evm_contracts.ts

@@ -1,7 +1,8 @@
 import yargs from "yargs";
 import { hideBin } from "yargs/helpers";
-import { DefaultStore } from "../src/node/utils/store";
+
 import { EvmPriceFeedContract } from "../src/core/contracts";
+import { DefaultStore } from "../src/node/utils/store";
 
 const parser = yargs(hideBin(process.argv))
   .usage("Usage: $0")
@@ -31,8 +32,8 @@ async function main() {
           version: version,
         });
         console.log(`Fetched version for ${contract.getId()}`);
-      } catch (e) {
-        console.error(`Error fetching version for ${contract.getId()}`, e);
+      } catch (error) {
+        console.error(`Error fetching version for ${contract.getId()}`, error);
       }
     }
   }

+ 4 - 3
contract_manager/scripts/list_wormhole_contracts.ts

@@ -1,7 +1,8 @@
 import yargs from "yargs";
 import { hideBin } from "yargs/helpers";
-import { DefaultStore } from "../src/node/utils/store";
+
 import { EvmWormholeContract } from "../src/core/contracts";
+import { DefaultStore } from "../src/node/utils/store";
 
 const parser = yargs(hideBin(process.argv))
   .usage("Usage: $0")
@@ -36,8 +37,8 @@ async function main() {
           chainId: chainId,
         });
         console.log(`Fetched contract for ${contract.getId()}`);
-      } catch (e) {
-        console.error(`Error fetching contract for ${contract.getId()}`, e);
+      } catch (error) {
+        console.error(`Error fetching contract for ${contract.getId()}`, error);
       }
     }
   }

+ 5 - 4
contract_manager/scripts/load_test_entropy.ts

@@ -1,9 +1,10 @@
 import yargs from "yargs";
 import { hideBin } from "yargs/helpers";
-import { DefaultStore } from "../src/node/utils/store";
-import { EvmChain } from "../src/core/chains";
-import { toPrivateKey } from "../src/core/base";
+
 import { COMMON_DEPLOY_OPTIONS, findEntropyContract } from "./common";
+import { toPrivateKey } from "../src/core/base";
+import { EvmChain } from "../src/core/chains";
+import { DefaultStore } from "../src/node/utils/store";
 
 const parser = yargs(hideBin(process.argv))
   .usage(
@@ -88,7 +89,7 @@ async function main() {
       value: (fee * totalCount).toString(),
     },
   );
-  console.log("Submitted transaction ", result.transactionHash);
+  console.log("Submitted transaction", result.transactionHash);
 }
 
 main();

+ 1 - 0
contract_manager/scripts/send_message_to_wormhole.ts

@@ -1,5 +1,6 @@
 import yargs from "yargs";
 import { hideBin } from "yargs/helpers";
+
 import { WormholeEmitter, loadHotWallet } from "../src/node/utils/governance";
 
 const parser = yargs(hideBin(process.argv))

+ 7 - 6
contract_manager/scripts/sync_governance_vaas.ts

@@ -1,7 +1,8 @@
-import yargs from "yargs";
-import { hideBin } from "yargs/helpers";
 import { parseVaa } from "@certusone/wormhole-sdk";
 import { decodeGovernancePayload } from "@pythnetwork/xc-admin-common";
+import yargs from "yargs";
+import { hideBin } from "yargs/helpers";
+
 import { toPrivateKey } from "../src/core/base";
 import { SubmittedWormholeMessage, Vault } from "../src/node/utils/governance";
 import { DefaultStore } from "../src/node/utils/store";
@@ -41,7 +42,7 @@ async function main() {
       "mainnet-beta_FVQyHcooAtThJ83XFrNnv74BcinbRH3bRmfFamAHBfuj"
     ];
   const devnetVault =
-    DefaultStore.vaults["devnet_6baWtW1zTUVMSJHJQVxDUXWzqrQeYBr6mu31j3bTKwY3"];
+    DefaultStore.vaults.devnet_6baWtW1zTUVMSJHJQVxDUXWzqrQeYBr6mu31j3bTKwY3;
   let matchedVault: Vault;
   if (
     (await devnetVault.getEmitter()).toBuffer().toString("hex") ===
@@ -67,7 +68,7 @@ async function main() {
     lastExecuted = argv.offset - 1;
   }
   console.log("Starting from sequence number", lastExecuted);
-  // eslint-disable-next-line no-constant-condition
+   
   while (true) {
     const submittedWormholeMessage = new SubmittedWormholeMessage(
       await matchedVault.getEmitter(),
@@ -77,8 +78,8 @@ async function main() {
     let vaa: Buffer;
     try {
       vaa = await submittedWormholeMessage.fetchVaa();
-    } catch (e) {
-      console.log(e);
+    } catch (error) {
+      console.log(error);
       console.log("no vaa found for sequence", lastExecuted + 1);
       break;
     }

+ 6 - 5
contract_manager/scripts/sync_wormhole_guardian_set.ts

@@ -1,5 +1,7 @@
 import yargs from "yargs";
 import { hideBin } from "yargs/helpers";
+
+import { toPrivateKey } from "../src/core/base";
 import {
   AptosWormholeContract,
   CosmWasmPriceFeedContract,
@@ -8,7 +10,6 @@ import {
   SuiWormholeContract,
 } from "../src/core/contracts";
 import { DefaultStore } from "../src/node/utils/store";
-import { toPrivateKey } from "../src/core/base";
 
 const parser = yargs(hideBin(process.argv))
   .usage("Update the guardian set in stable networks. Usage: $0")
@@ -46,8 +47,8 @@ async function main() {
         await contract.syncMainnetGuardianSets(privateKey);
         index = await contract.getCurrentGuardianSetIndex();
         console.log("Guardian Index at End:", index);
-      } catch (e) {
-        console.error(`Error updating Guardianset for ${contract.getId()}`, e);
+      } catch (error) {
+        console.error(`Error updating Guardianset for ${contract.getId()}`, error);
       }
     }
   }
@@ -84,8 +85,8 @@ async function main() {
 
         await wormhole.syncMainnetGuardianSets(privateKey);
         console.log(`Updated Guardianset for ${contract.getId()}`);
-      } catch (e) {
-        console.error(`Error updating Guardianset for ${contract.getId()}`, e);
+      } catch (error) {
+        console.error(`Error updating Guardianset for ${contract.getId()}`, error);
       }
     }
   }

+ 15 - 14
contract_manager/scripts/transfer_balance_entropy_chains.ts

@@ -1,11 +1,12 @@
+import Web3 from "web3";
 import yargs from "yargs";
 import { hideBin } from "yargs/helpers";
-import { DefaultStore } from "../src/node/utils/store";
+
 import { PrivateKey, toPrivateKey } from "../src/core/base";
 import { EvmChain } from "../src/core/chains";
-import Web3 from "web3";
+import { DefaultStore } from "../src/node/utils/store";
 
-interface TransferResult {
+type TransferResult = {
   chain: string;
   success: boolean;
   sourceAddress: string;
@@ -153,9 +154,7 @@ async function transferOnChain(
 
     // Calculate transfer amount
     let transferAmountEth: number;
-    if (transferAmount !== undefined) {
-      transferAmountEth = transferAmount;
-    } else {
+    if (transferAmount === undefined) {
       // transferRatio is guaranteed to be defined at this point
       if (transferRatio === undefined) {
         throw new Error(
@@ -163,6 +162,8 @@ async function transferOnChain(
         );
       }
       transferAmountEth = (balanceEth - gasCostEth) * transferRatio;
+    } else {
+      transferAmountEth = transferAmount;
     }
 
     // Round to 10 decimal places to avoid Web3 conversion errors
@@ -317,7 +318,7 @@ function getSelectedChains(argv: {
       }
       const chain = DefaultStore.chains[chainId];
       if (!(chain instanceof EvmChain)) {
-        throw new Error(`Chain ${chainId} is not an EVM chain`);
+        throw new TypeError(`Chain ${chainId} is not an EVM chain`);
       }
       selectedChains.push(chain);
     }
@@ -326,9 +327,9 @@ function getSelectedChains(argv: {
   if (selectedChains.length === 0) {
     const mode = argv.testnets
       ? "testnet"
-      : argv.mainnets
+      : (argv.mainnets
         ? "mainnet"
-        : "specified";
+        : "specified");
     throw new Error(`No valid ${mode} entropy chains found`);
   }
 
@@ -367,18 +368,18 @@ async function main() {
 
   // Determine transfer method for display
   let transferMethod: string;
-  if (argv.amount !== undefined) {
-    transferMethod = `${argv.amount} ETH (fixed amount)`;
-  } else {
+  if (argv.amount === undefined) {
     if (argv.ratio === undefined) {
       throw new Error("Ratio must be defined when amount is not specified");
     }
     transferMethod = `${(argv.ratio * 100).toFixed(1)}% of available balance`;
+  } else {
+    transferMethod = `${argv.amount} ETH (fixed amount)`;
   }
 
   console.log(`\nConfiguration:`);
   console.log(
-    `   Network: ${argv.testnets ? "Testnet" : argv.mainnets ? "Mainnet" : "Specific chains"}`,
+    `   Network: ${argv.testnets ? "Testnet" : (argv.mainnets ? "Mainnet" : "Specific chains")}`,
   );
   console.log(`   Destination: ${argv.destinationAddress}`);
   console.log(`   Transfer method: ${transferMethod}`);
@@ -418,7 +419,7 @@ async function main() {
   console.log(`Successful transfers: ${successful.length}`);
   console.log(`Failed transfers: ${failed.length}`);
   console.log(
-    `Total transferred: ${successful.reduce((sum, r) => sum + parseFloat(r.transferAmount), 0).toFixed(6)} ETH`,
+    `Total transferred: ${successful.reduce((sum, r) => sum + Number.parseFloat(r.transferAmount), 0).toFixed(6)} ETH`,
   );
 
   if (successful.length > 0) {

+ 3 - 2
contract_manager/scripts/update_all_pricefeeds.ts

@@ -1,8 +1,9 @@
+import { HermesClient, PriceFeedMetadata } from "@pythnetwork/hermes-client";
 import yargs from "yargs";
 import { hideBin } from "yargs/helpers";
-import { HermesClient, PriceFeedMetadata } from "@pythnetwork/hermes-client";
-import { DefaultStore } from "../src/node/utils/store";
+
 import { toPrivateKey } from "../src/core/base";
+import { DefaultStore } from "../src/node/utils/store";
 
 const parser = yargs(hideBin(process.argv))
   .usage("Update the set of price feeds in a network. Usage: $0")

+ 3 - 2
contract_manager/scripts/update_pricefeed.ts

@@ -1,8 +1,9 @@
+import { PriceServiceConnection } from "@pythnetwork/price-service-client";
 import yargs from "yargs";
 import { hideBin } from "yargs/helpers";
-import { DefaultStore } from "../src/node/utils/store";
+
 import { toPrivateKey } from "../src/core/base";
-import { PriceServiceConnection } from "@pythnetwork/price-service-client";
+import { DefaultStore } from "../src/node/utils/store";
 
 const parser = yargs(hideBin(process.argv))
   .usage(

+ 11 - 10
contract_manager/scripts/upgrade_evm_entropy_contracts.ts

@@ -1,16 +1,17 @@
+import { readFileSync } from "node:fs";
+
+import { PythCluster } from "@pythnetwork/client/lib/cluster";
 import yargs from "yargs";
 import { hideBin } from "yargs/helpers";
-import { DefaultStore } from "../src/node/utils/store";
-import { loadHotWallet } from "../src/node/utils/governance";
-import { toPrivateKey } from "../src/core/base";
-import { readFileSync } from "fs";
-import { PythCluster } from "@pythnetwork/client/lib/cluster";
 
 import {
   COMMON_UPGRADE_OPTIONS,
   getSelectedChains,
   makeCacheFunction,
 } from "./common";
+import { toPrivateKey } from "../src/core/base";
+import { loadHotWallet } from "../src/node/utils/governance";
+import { DefaultStore } from "../src/node/utils/store";
 
 const EXECUTOR_CACHE_FILE = ".cache-upgrade-evm-executor-contract";
 const ENTROPY_CACHE_FILE = ".cache-upgrade-evm-entropy-contract";
@@ -74,8 +75,8 @@ async function main() {
           () => {
             return contract.chain.deploy(
               toPrivateKey(argv["private-key"]),
-              artifact["abi"],
-              artifact["bytecode"].object, // As per the artifacts generated by forge, bytecode is an object with an 'object' property
+              artifact.abi,
+              artifact.bytecode.object, // As per the artifacts generated by forge, bytecode is an object with an 'object' property
               [],
               2,
             );
@@ -91,8 +92,8 @@ async function main() {
 
         console.log(payload.toString("hex"));
         payloads.push(payload);
-      } catch (e) {
-        console.log(`error deploying: ${e}`);
+      } catch (error) {
+        console.log(`error deploying: ${error}`);
         failures.push(contract.chain.getId());
       }
     }
@@ -108,7 +109,7 @@ async function main() {
 
   console.log("Using vault at for proposal", vault.getId());
   const wallet = await loadHotWallet(argv["ops-key-path"]);
-  console.log("Using wallet ", wallet.publicKey.toBase58());
+  console.log("Using wallet", wallet.publicKey.toBase58());
   vault.connect(wallet, registry);
   const proposal = await vault.proposeWormholeMessage(payloads);
   console.log("Proposal address", proposal.address.toBase58());

+ 8 - 7
contract_manager/scripts/upgrade_evm_pricefeed_contracts.ts

@@ -1,15 +1,16 @@
+import { readFileSync } from "node:fs";
+
 import yargs from "yargs";
 import { hideBin } from "yargs/helpers";
-import { DefaultStore } from "../src/node/utils/store";
-import { loadHotWallet } from "../src/node/utils/governance";
-import { toPrivateKey } from "../src/core/base";
-import { readFileSync } from "fs";
 
 import {
   COMMON_UPGRADE_OPTIONS,
   getSelectedChains,
   makeCacheFunction,
 } from "./common";
+import { toPrivateKey } from "../src/core/base";
+import { loadHotWallet } from "../src/node/utils/governance";
+import { DefaultStore } from "../src/node/utils/store";
 
 const CACHE_FILE = ".cache-upgrade-evm";
 const runIfNotCached = makeCacheFunction(CACHE_FILE);
@@ -44,8 +45,8 @@ async function main() {
     const address = await runIfNotCached(`deploy-${chain.getId()}`, () => {
       return chain.deploy(
         toPrivateKey(argv["private-key"]),
-        artifact["abi"],
-        artifact["bytecode"].object, // As per the artifacts generated by forge, bytecode is an object with an 'object' property
+        artifact.abi,
+        artifact.bytecode.object, // As per the artifacts generated by forge, bytecode is an object with an 'object' property
         [],
       );
     });
@@ -57,7 +58,7 @@ async function main() {
 
   console.log("Using vault at for proposal", vault.getId());
   const wallet = await loadHotWallet(argv["ops-key-path"]);
-  console.log("Using wallet ", wallet.publicKey.toBase58());
+  console.log("Using wallet", wallet.publicKey.toBase58());
   await vault.connect(wallet);
   const proposal = await vault.proposeWormholeMessage(payloads);
   console.log("Proposal address", proposal.address.toBase58());

+ 8 - 5
contract_manager/scripts/upgrade_ton_contract.ts

@@ -1,11 +1,14 @@
+import fs from "node:fs";
+import path from "node:path";
+
+import { Cell } from "@ton/ton";
 import yargs from "yargs";
 import { hideBin } from "yargs/helpers";
-import { DefaultStore } from "../src/node/utils/store";
-import { TonPriceFeedContract } from "../src/core/contracts";
+
 import { toPrivateKey } from "../src/core/base";
-import fs from "fs";
-import path from "path";
-import { Cell } from "@ton/ton";
+import { TonPriceFeedContract } from "../src/core/contracts";
+import { DefaultStore } from "../src/node/utils/store";
+
 
 // This script upgrades the Pyth contract on TON after the governance has authorized the upgrade
 // If you are starting over, the process is like the following:

+ 2 - 1
contract_manager/scripts/upload_cosmwasm.ts

@@ -1,9 +1,10 @@
 import yargs from "yargs";
 import { hideBin } from "yargs/helpers";
+
+import { toPrivateKey } from "../src/core/base";
 import { CosmWasmChain } from "../src/core/chains";
 import { CosmWasmPriceFeedContract } from "../src/core/contracts";
 import { DefaultStore } from "../src/node/utils/store";
-import { toPrivateKey } from "../src/core/base";
 
 const parser = yargs(hideBin(process.argv))
   .usage(

+ 4 - 3
contract_manager/src/core/base.ts

@@ -1,7 +1,8 @@
 import type { DataSource } from "@pythnetwork/xc-admin-common";
+
 import { Chain } from "./chains";
 
-export interface TxResult {
+export type TxResult = {
   id: string;
   info: unknown; // chain specific info
 }
@@ -45,14 +46,14 @@ export abstract class Storable {
   abstract toJson(): KeyValueConfig;
 }
 
-export interface Price {
+export type Price = {
   price: string;
   conf: string;
   publishTime: string;
   expo: string;
 }
 
-export interface PriceFeed {
+export type PriceFeed = {
   price: Price;
   emaPrice: Price;
 }

+ 43 - 44
contract_manager/src/core/chains.ts

@@ -1,37 +1,6 @@
-import {
-  type KeyValueConfig,
-  type PrivateKey,
-  Storable,
-  type TxResult,
-} from "./base";
-import {
-  type ChainName,
-  SetFee,
-  CosmosUpgradeContract,
-  EvmUpgradeContract,
-  toChainId,
-  SetDataSources,
-  SetValidPeriod,
-  type DataSource,
-  EvmSetWormholeAddress,
-  UpgradeContract256Bit,
-  EvmExecute,
-} from "@pythnetwork/xc-admin-common";
-import { AptosClient, AptosAccount, CoinClient, TxnBuilderTypes } from "aptos";
-import Web3 from "web3";
-import {
-  CosmwasmExecutor,
-  CosmwasmQuerier,
-  InjectiveExecutor,
-} from "@pythnetwork/cosmwasm-deploy-tools";
 import { Network } from "@injectivelabs/networks";
 import { IotaClient } from "@iota/iota-sdk/client";
-import { SuiClient } from "@mysten/sui/client";
 import { Ed25519Keypair as IotaEd25519Keypair } from "@iota/iota-sdk/keypairs/ed25519";
-import { Ed25519Keypair as SuiEd25519Keypair } from "@mysten/sui/keypairs/ed25519";
-import type { TokenId } from "./token";
-import { BN, Provider, Wallet, WalletUnlocked } from "fuels";
-import { FUEL_ETH_ASSET_ID } from "@pythnetwork/pyth-fuel-js";
 import { Contract, RpcProvider, Signer, ec, shortString } from "starknet";
 import {
   TonClient,
@@ -47,13 +16,47 @@ import * as nearAPI from "near-api-js";
 import * as bs58 from "bs58";
 import { MIST_PER_SUI } from "@mysten/sui/utils";
 import { NANOS_PER_IOTA } from "@iota/iota-sdk/utils";
+import { SuiClient } from "@mysten/sui/client";
+import { Ed25519Keypair as SuiEd25519Keypair } from "@mysten/sui/keypairs/ed25519";
+import {
+  CosmwasmExecutor,
+  CosmwasmQuerier,
+  InjectiveExecutor,
+} from "@pythnetwork/cosmwasm-deploy-tools";
+import { FUEL_ETH_ASSET_ID } from "@pythnetwork/pyth-fuel-js";
+import type {ChainName, DataSource} from "@pythnetwork/xc-admin-common";
+import {
+  
+  SetFee,
+  CosmosUpgradeContract,
+  EvmUpgradeContract,
+  toChainId,
+  SetDataSources,
+  SetValidPeriod,
+  
+  EvmSetWormholeAddress,
+  UpgradeContract256Bit,
+  EvmExecute
+} from "@pythnetwork/xc-admin-common";
+import { AptosClient, AptosAccount, CoinClient, TxnBuilderTypes } from "aptos";
+import { BN, Provider, Wallet, WalletUnlocked } from "fuels";
 import * as chains from "viem/chains";
+import Web3 from "web3";
+
+import type {KeyValueConfig, PrivateKey, TxResult} from "./base";
+import {
+  
+  
+  Storable
+  
+} from "./base";
+import type { TokenId } from "./token";
 
 /**
  * Returns the chain rpc url with any environment variables replaced or throws an error if any are missing
  */
 export function parseRpcUrl(rpcUrl: string): string {
-  const envMatches = rpcUrl.match(/\$ENV_\w+/);
+  const envMatches = /\$ENV_\w+/.exec(rpcUrl);
   if (envMatches) {
     for (const envMatch of envMatches) {
       const envName = envMatch.replace("$ENV_", "");
@@ -267,7 +270,7 @@ export class CosmWasmChain extends Chain {
   async getExecutor(
     privateKey: PrivateKey,
   ): Promise<CosmwasmExecutor | InjectiveExecutor> {
-    if (this.getId().indexOf("injective") > -1) {
+    if (this.getId().includes("injective")) {
       return InjectiveExecutor.fromPrivateKey(
         this.isMainnet() ? Network.Mainnet : Network.Testnet,
         privateKey,
@@ -282,11 +285,7 @@ export class CosmWasmChain extends Chain {
 
   async getAccountAddress(privateKey: PrivateKey): Promise<string> {
     const executor = await this.getExecutor(privateKey);
-    if (executor instanceof InjectiveExecutor) {
-      return executor.getAddress();
-    } else {
-      return await executor.getAddress();
-    }
+    return executor instanceof InjectiveExecutor ? executor.getAddress() : (await executor.getAddress());
   }
 
   async getAccountBalance(privateKey: PrivateKey): Promise<number> {
@@ -593,11 +592,11 @@ export class EvmChain extends Chain {
         gasPrice: gasPrice.toString(),
       });
       return deployedContract.options.address;
-    } catch (e) {
+    } catch (error) {
       // RPC errors often have useful information in the non-primary message field. Log the whole error
       // to simplify identifying the problem.
-      console.log(`Error deploying contract: ${JSON.stringify(e)}`);
-      throw e;
+      console.log(`Error deploying contract: ${JSON.stringify(error)}`);
+      throw error;
     }
   }
 
@@ -694,7 +693,7 @@ export class AptosChain extends Chain {
       sender,
       txPayload,
       {
-        maxGasAmount: BigInt(30000),
+        maxGasAmount: BigInt(30_000),
       },
     );
     return { id: result.hash, info: result };
@@ -818,7 +817,7 @@ export class StarknetChain extends Chain {
     const ARGENT_CLASS_HASH =
       "0x029927c8af6bccf3f6fda035981e765a7bdbf18a2dc0d630494f8758aa908e2b";
     const ADDR_BOUND =
-      0x7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00n;
+      0x7_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_00n;
 
     function computeHashOnElements(elements: string[]): string {
       let hash = "0";
@@ -1032,7 +1031,7 @@ export class NearChain extends Chain {
     senderPrivateKey?: PrivateKey,
   ): Promise<nearAPI.Account> {
     const keyStore = new nearAPI.keyStores.InMemoryKeyStore();
-    if (typeof senderPrivateKey !== "undefined") {
+    if (senderPrivateKey !== undefined) {
       const key = bs58.encode(
         new Uint8Array(Buffer.from(senderPrivateKey, "hex")),
       );

+ 12 - 10
contract_manager/src/core/contracts/aptos.ts

@@ -1,14 +1,16 @@
+import type { DataSource } from "@pythnetwork/xc-admin-common";
+import { ApiError, BCS, CoinClient, TxnBuilderTypes } from "aptos";
+
+import type {PriceFeed, PrivateKey, TxResult} from "../base";
 import {
-  PriceFeedContract,
-  type PriceFeed,
-  type PrivateKey,
-  type TxResult,
+  PriceFeedContract
+  
+  
+  
 } from "../base";
-import { ApiError, BCS, CoinClient, TxnBuilderTypes } from "aptos";
 import { AptosChain, Chain } from "../chains";
-import type { DataSource } from "@pythnetwork/xc-admin-common";
-import { WormholeContract } from "./wormhole";
 import type { TokenQty } from "../token";
+import { WormholeContract } from "./wormhole";
 
 type WormholeState = {
   chain_id: { number: string };
@@ -251,10 +253,10 @@ export class AptosPriceFeedContract extends PriceFeedContract {
         price: this.parsePrice(priceItemRes.price_feed.price),
         emaPrice: this.parsePrice(priceItemRes.price_feed.ema_price),
       };
-    } catch (e) {
-      if (e instanceof ApiError && e.errorCode === "table_item_not_found")
+    } catch (error) {
+      if (error instanceof ApiError && error.errorCode === "table_item_not_found")
         return undefined;
-      throw e;
+      throw error;
     }
   }
 

+ 31 - 29
contract_manager/src/core/contracts/cosmwasm.ts

@@ -1,33 +1,37 @@
-import { Chain, CosmWasmChain } from "../chains";
-import { readFileSync } from "fs";
+import { readFileSync } from "node:fs";
+
+import { CosmWasmClient } from "@cosmjs/cosmwasm-stargate";
+import type { Coin } from "@cosmjs/stargate";
+import type {ContractInfoResponse, Price} from "@pythnetwork/cosmwasm-deploy-tools";
 import {
-  type ContractInfoResponse,
+  
   CosmwasmQuerier,
-  type Price,
+  
   PythWrapperExecutor,
-  PythWrapperQuerier,
+  PythWrapperQuerier
 } from "@pythnetwork/cosmwasm-deploy-tools";
-import type { Coin } from "@cosmjs/stargate";
 import type { DataSource } from "@pythnetwork/xc-admin-common";
-import { CosmWasmClient } from "@cosmjs/cosmwasm-stargate";
+
+import type {PrivateKey, TxResult} from "../base";
 import {
   PriceFeedContract,
-  getDefaultDeploymentConfig,
-  type PrivateKey,
-  type TxResult,
+  getDefaultDeploymentConfig
+  
+  
 } from "../base";
-import { WormholeContract } from "./wormhole";
+import { Chain, CosmWasmChain } from "../chains";
 import type { TokenQty } from "../token";
+import { WormholeContract } from "./wormhole";
 
 /**
  * Variables here need to be snake case to match the on-chain contract configs
  */
-export interface WormholeSource {
+export type WormholeSource = {
   emitter: string;
   chain_id: number;
 }
 
-export interface DeploymentConfig {
+export type DeploymentConfig = {
   data_sources: WormholeSource[];
   governance_source: WormholeSource;
   wormhole_contract: string;
@@ -84,24 +88,22 @@ export class CosmWasmWormholeContract extends WormholeContract {
 
   async getCurrentGuardianSetIndex(): Promise<number> {
     const config = await this.getConfig();
-    return JSON.parse(config["\x00\x06config"] ?? "{}")["guardian_set_index"];
+    return JSON.parse(config["\u0000\u0006config"] ?? "{}").guardian_set_index;
   }
 
   async getChainId(): Promise<number> {
     const config = await this.getConfig();
-    return JSON.parse(config["\x00\x06config"] ?? "{}")["chain_id"];
+    return JSON.parse(config["\u0000\u0006config"] ?? "{}").chain_id;
   }
 
   async getGuardianSet(): Promise<string[]> {
     const config = await this.getConfig();
-    const guardianSetIndex = JSON.parse(config["\x00\x06config"] ?? "{}")[
-      "guardian_set_index"
-    ];
-    let key = "\x00\fguardian_set";
+    const guardianSetIndex = JSON.parse(config["\u0000\u0006config"] ?? "{}").guardian_set_index;
+    let key = "\u0000\fguardian_set";
     //append guardianSetIndex as 4 bytes to key string
     key += Buffer.from(guardianSetIndex.toString(16).padStart(8, "0"), "hex");
 
-    const guardianSet = JSON.parse(config[key] ?? "{}")["addresses"];
+    const guardianSet = JSON.parse(config[key] ?? "{}").addresses;
     return guardianSet.map((entry: { bytes: string }) =>
       Buffer.from(entry.bytes, "base64").toString("hex"),
     );
@@ -245,9 +247,9 @@ export class CosmWasmPriceFeedContract extends PriceFeedContract {
       contractAddr: this.address,
     })) as Record<string, string>;
     const config = {
-      config_v1: JSON.parse(allStates["\x00\tconfig_v1"] ?? "{}"),
-      contract_version: allStates["\x00\x10contract_version"]
-        ? JSON.parse(allStates["\x00\x10contract_version"])
+      config_v1: JSON.parse(allStates["\u0000\tconfig_v1"] ?? "{}"),
+      contract_version: allStates["\u0000\u0010contract_version"]
+        ? JSON.parse(allStates["\u0000\u0010contract_version"])
         : undefined,
     };
     return config;
@@ -275,8 +277,8 @@ export class CosmWasmPriceFeedContract extends PriceFeedContract {
         price: this.parsePrice(response.price),
         emaPrice: this.parsePrice(response.ema_price),
       };
-    } catch (e) {
-      return undefined;
+    } catch {
+      return;
     }
   }
 
@@ -285,12 +287,12 @@ export class CosmWasmPriceFeedContract extends PriceFeedContract {
     dataSources2: WormholeSource[],
   ): boolean {
     if (dataSources1.length !== dataSources2.length) return false;
-    for (let i = 0; i < dataSources1.length; i++) {
+    for (const element of dataSources1) {
       let found = false;
-      for (let j = 0; j < dataSources2.length; j++) {
+      for (const element_ of dataSources2) {
         if (
-          dataSources1[i]?.emitter === dataSources2[j]?.emitter &&
-          dataSources1[i]?.chain_id === dataSources2[j]?.chain_id
+          element.emitter === element_.emitter &&
+          element.chain_id === element_.chain_id
         ) {
           found = true;
           break;

+ 11 - 9
contract_manager/src/core/contracts/evm.ts

@@ -1,9 +1,10 @@
+import type { DataSource } from "@pythnetwork/xc-admin-common";
 import Web3 from "web3";
 import type { Contract } from "web3-eth-contract";
-import { PriceFeedContract, type PrivateKey, Storable } from "../base";
+
+import type {PrivateKey} from "../base";
+import { PriceFeedContract,  Storable } from "../base";
 import { Chain, EvmChain } from "../chains";
-import type { DataSource } from "@pythnetwork/xc-admin-common";
-import { WormholeContract } from "./wormhole";
 import type { TokenQty } from "../token";
 import {
   EXECUTOR_ABI,
@@ -13,6 +14,7 @@ import {
   PULSE_UPGRADEABLE_ABI,
   LAZER_ABI,
 } from "./evm_abis";
+import { WormholeContract } from "./wormhole";
 
 /**
  * Returns the keccak256 digest of the contract bytecode at the given address after replacing
@@ -124,7 +126,7 @@ export class EvmWormholeContract extends WormholeContract {
   }
 }
 
-interface EntropyProviderInfo {
+type EntropyProviderInfo = {
   feeInWei: string;
   accruedFeesInWei: string;
   originalCommitment: string;
@@ -138,7 +140,7 @@ interface EntropyProviderInfo {
   feeManager: string;
 }
 
-interface EntropyRequest {
+type EntropyRequest = {
   provider: string;
   sequenceNumber: string;
   numHashes: string;
@@ -586,7 +588,7 @@ export class EvmPriceFeedContract extends PriceFeedContract {
     try {
       web3 = this.chain.getWeb3();
       amount = BigInt(await web3.eth.getBalance(this.address));
-    } catch (error) {
+    } catch {
       console.error(
         "Error getting balance with given RPC, moving to viem default RPC",
       );
@@ -611,7 +613,7 @@ export class EvmPriceFeedContract extends PriceFeedContract {
     const feed = "0x" + feedId;
     const exists = await pythContract.methods.priceFeedExists(feed).call();
     if (!exists) {
-      return undefined;
+      return;
     }
     const [price, conf, expo, publishTime] = await pythContract.methods
       .getPriceUnsafe(feed)
@@ -837,13 +839,13 @@ export class EvmPulseContract extends Storable {
   }
 
   async getFirstActiveRequests(count: number): Promise<{
-    requests: Array<{
+    requests: {
       provider: string;
       publishTime: string;
       priceIds: string[];
       callbackGasLimit: string;
       requester: string;
-    }>;
+    }[];
     actualCount: number;
   }> {
     const contract = this.getContract();

+ 2 - 1
contract_manager/src/core/contracts/evm_abis.ts

@@ -1,5 +1,6 @@
-import PythInterfaceAbi from "@pythnetwork/pyth-sdk-solidity/abis/IPyth.json";
+/* eslint-disable @typescript-eslint/no-unsafe-assignment */
 import EntropyAbi from "@pythnetwork/entropy-sdk-solidity/abis/IEntropy.json";
+import PythInterfaceAbi from "@pythnetwork/pyth-sdk-solidity/abis/IPyth.json";
 
 export const OWNABLE_ABI = [
   {

+ 21 - 20
contract_manager/src/core/contracts/fuel.ts

@@ -1,29 +1,30 @@
-import { Chain, FuelChain } from "../chains";
-import { WormholeContract } from "./wormhole";
+/* eslint-disable @typescript-eslint/no-unsafe-member-access */
+/* eslint-disable @typescript-eslint/no-unsafe-call */
+/* eslint-disable @typescript-eslint/require-await */
+/* eslint-disable @typescript-eslint/no-unnecessary-condition */
+/* eslint-disable @typescript-eslint/prefer-optional-chain */
+/* eslint-disable @typescript-eslint/no-unsafe-return */
+/* eslint-disable unicorn/no-await-expression-member */
+/* eslint-disable @typescript-eslint/no-unsafe-assignment */
+/* eslint-disable @typescript-eslint/restrict-template-expressions */
+/* eslint-disable @typescript-eslint/no-base-to-string */
+import type {
+  PriceFeedOutput,
+  DataSourceOutput,
+} from "@pythnetwork/pyth-fuel-js";
 import {
   PYTH_CONTRACT_ABI as FuelContractAbi,
   FUEL_ETH_ASSET_ID,
-  type PriceFeedOutput,
-  type DataSourceOutput,
 } from "@pythnetwork/pyth-fuel-js";
+import type { DataSource } from "@pythnetwork/xc-admin-common";
+import type { DryRunResult } from "fuels";
+import { Account, Contract, Wallet, arrayify, hexlify } from "fuels";
 
-import {
-  Account,
-  Contract,
-  Wallet,
-  arrayify,
-  hexlify,
-  type DryRunResult,
-} from "fuels";
-import {
-  type PriceFeed,
-  PriceFeedContract,
-  type PrivateKey,
-  type TxResult,
-} from "../base";
-
+import type { PriceFeed, PrivateKey, TxResult } from "../base";
+import { Chain, FuelChain } from "../chains";
+import { WormholeContract } from "./wormhole";
+import { PriceFeedContract } from "../base";
 import type { TokenQty } from "../token";
-import type { DataSource } from "@pythnetwork/xc-admin-common";
 
 export class FuelWormholeContract extends WormholeContract {
   static type = "FuelWormholeContract";

+ 37 - 37
contract_manager/src/core/contracts/iota.ts

@@ -1,12 +1,23 @@
-import { Chain, IotaChain } from "../chains";
-import type { DataSource } from "@pythnetwork/xc-admin-common";
-import { WormholeContract } from "./wormhole";
-import { PriceFeedContract, type PrivateKey, type TxResult } from "../base";
-import { IotaPythClient } from "@pythnetwork/pyth-iota-js";
-import { IOTA_CLOCK_OBJECT_ID } from "@iota/iota-sdk/utils";
+/* eslint-disable @typescript-eslint/no-unsafe-return */
+/* eslint-disable @typescript-eslint/no-unsafe-call */
+/* eslint-disable @typescript-eslint/no-unsafe-assignment */
+/* eslint-disable @typescript-eslint/no-non-null-assertion */
+/* eslint-disable @typescript-eslint/no-unsafe-member-access */
+/* eslint-disable @typescript-eslint/no-unsafe-argument */
+/* eslint-disable @typescript-eslint/require-await */
+/* eslint-disable @typescript-eslint/restrict-template-expressions */
+/* eslint-disable @typescript-eslint/no-base-to-string */
+import { uint8ArrayToBCS } from "@certusone/wormhole-sdk/lib/cjs/sui";
 import { Ed25519Keypair } from "@iota/iota-sdk/keypairs/ed25519";
 import { Transaction } from "@iota/iota-sdk/transactions";
-import { uint8ArrayToBCS } from "@certusone/wormhole-sdk/lib/cjs/sui";
+import { IOTA_CLOCK_OBJECT_ID } from "@iota/iota-sdk/utils";
+import { IotaPythClient } from "@pythnetwork/pyth-iota-js";
+import type { DataSource } from "@pythnetwork/xc-admin-common";
+
+import type { PrivateKey, TxResult } from "../base";
+import { Chain, IotaChain } from "../chains";
+import { WormholeContract } from "./wormhole";
+import { PriceFeedContract } from "../base";
 
 type ObjectId = string;
 
@@ -18,9 +29,9 @@ export class IotaPriceFeedContract extends PriceFeedContract {
    * Given the ids of the pyth state and wormhole state, create a new IotaPriceFeedContract
    * The package ids are derived based on the state ids
    *
-   * @param chain the chain which this contract is deployed on
-   * @param stateId id of the pyth state for the deployed contract
-   * @param wormholeStateId id of the wormhole state for the wormhole contract that pyth binds to
+   * @param chain - the chain which this contract is deployed on
+   * @param stateId - id of the pyth state for the deployed contract
+   * @param wormholeStateId - id of the wormhole state for the wormhole contract that pyth binds to
    */
   constructor(
     public chain: IotaChain,
@@ -69,7 +80,7 @@ export class IotaPriceFeedContract extends PriceFeedContract {
 
   /**
    * Given a objectId, returns the id for the package that the object belongs to.
-   * @param objectId
+   * @param objectId - the object id to get
    */
   async getPackageId(objectId: ObjectId): Promise<ObjectId> {
     return this.client.getPackageId(objectId);
@@ -111,12 +122,12 @@ export class IotaPriceFeedContract extends PriceFeedContract {
   async getPriceFeed(feedId: string) {
     const provider = this.getProvider();
     const priceInfoObjectId = await this.client.getPriceFeedObjectId(feedId);
-    if (!priceInfoObjectId) return undefined;
+    if (!priceInfoObjectId) return;
     const priceInfo = await provider.getObject({
       id: priceInfoObjectId,
       options: { showContent: true },
     });
-    if (!priceInfo.data || !priceInfo.data.content) {
+    if (!priceInfo.data?.content) {
       throw new Error(
         `Price feed ID ${priceInfoObjectId} in price table but object not found!!`,
       );
@@ -144,8 +155,8 @@ export class IotaPriceFeedContract extends PriceFeedContract {
   /**
    * Given a signed VAA, execute the migration instruction on the pyth contract.
    * The payload of the VAA can be obtained from the `getUpgradePackagePayload` method.
-   * @param vaa
-   * @param keypair used to sign the transaction
+   * @param vaa - the vaa payload
+   * @param keypair - used to sign the transaction
    */
   async executeMigrateInstruction(vaa: Buffer, keypair: Ed25519Keypair) {
     const tx = new Transaction();
@@ -260,10 +271,9 @@ export class IotaPriceFeedContract extends PriceFeedContract {
   /**
    * Utility function to get the verification receipt object for a VAA that can be
    * used to authorize a governance instruction.
-   * @param tx
-   * @param packageId pyth package id
-   * @param vaa
-   * @private
+   * @param tx - the transaction
+   * @param packageId - pyth package id
+   * @param vaa - the vaa payload
    */
   async getVaaVerificationReceipt(
     tx: Transaction,
@@ -276,7 +286,7 @@ export class IotaPriceFeedContract extends PriceFeedContract {
       target: `${wormholePackageId}::vaa::parse_and_verify`,
       arguments: [
         tx.object(this.wormholeStateId),
-        tx.pure.arguments(Array.from(vaa)),
+        tx.pure.arguments([...vaa]),
         tx.object(IOTA_CLOCK_OBJECT_ID),
       ],
     });
@@ -291,9 +301,8 @@ export class IotaPriceFeedContract extends PriceFeedContract {
   /**
    * Given a transaction block and a keypair, sign and execute it
    * Sets the gas budget to 2x the estimated gas cost
-   * @param tx
-   * @param keypair
-   * @private
+   * @param tx - the transaction
+   * @param keypair - the keypair
    */
   private async executeTransaction(tx: Transaction, keypair: Ed25519Keypair) {
     const provider = this.getProvider();
@@ -328,7 +337,7 @@ export class IotaPriceFeedContract extends PriceFeedContract {
         value: "data_sources",
       },
     });
-    if (!result.data || !result.data.content) {
+    if (!result.data?.content) {
       throw new Error(
         "Data Sources not found, contract may not be initialized",
       );
@@ -395,11 +404,7 @@ export class IotaPriceFeedContract extends PriceFeedContract {
       id: this.stateId,
       options: { showContent: true },
     });
-    if (
-      !result.data ||
-      !result.data.content ||
-      result.data.content.dataType !== "moveObject"
-    )
+    if (!result.data?.content || result.data.content.dataType !== "moveObject")
       throw new Error("Unable to fetch pyth state object");
     return result.data.content.fields;
   }
@@ -533,11 +538,7 @@ export class IotaWormholeContract extends WormholeContract {
       id: this.stateId,
       options: { showContent: true },
     });
-    if (
-      !result.data ||
-      !result.data.content ||
-      result.data.content.dataType !== "moveObject"
-    )
+    if (!result.data?.content || result.data.content.dataType !== "moveObject")
       throw new Error("Unable to fetch pyth state object");
     return result.data.content.fields;
   }
@@ -545,9 +546,8 @@ export class IotaWormholeContract extends WormholeContract {
   /**
    * Given a transaction block and a keypair, sign and execute it
    * Sets the gas budget to 2x the estimated gas cost
-   * @param tx
-   * @param keypair
-   * @private
+   * @param tx - the transaction
+   * @param keypair - the keypair
    */
   private async executeTransaction(tx: Transaction, keypair: Ed25519Keypair) {
     const provider = this.chain.getProvider();

+ 40 - 39
contract_manager/src/core/contracts/near.ts

@@ -1,14 +1,17 @@
+/* eslint-disable @typescript-eslint/require-await */
+/* eslint-disable @typescript-eslint/no-unsafe-return */
+/* eslint-disable @typescript-eslint/no-non-null-assertion */
+/* eslint-disable @typescript-eslint/no-unsafe-member-access */
+/* eslint-disable @typescript-eslint/no-unsafe-assignment */
+/* eslint-disable @typescript-eslint/restrict-template-expressions */
+/* eslint-disable @typescript-eslint/no-base-to-string */
 import type { DataSource } from "@pythnetwork/xc-admin-common";
-import {
-  type KeyValueConfig,
-  type PriceFeed,
-  PriceFeedContract,
-  type PrivateKey,
-  type TxResult,
-} from "../base";
-import { Chain, NearChain } from "../chains";
-import * as nearAPI from "near-api-js";
 import { BN } from "fuels";
+import * as nearAPI from "near-api-js";
+
+import type { KeyValueConfig, PriceFeed, PrivateKey, TxResult } from "../base";
+import { PriceFeedContract } from "../base";
+import { Chain, NearChain } from "../chains";
 import { WormholeContract } from "./wormhole";
 
 export class NearWormholeContract extends WormholeContract {
@@ -22,7 +25,7 @@ export class NearWormholeContract extends WormholeContract {
   }
 
   getId(): string {
-    return `${this.chain.getId()}__${this.address.replace(/-|\./g, "_")}`;
+    return `${this.chain.getId()}__${this.address.replaceAll(/-|\./g, "_")}`;
   }
 
   getChain(): NearChain {
@@ -101,7 +104,7 @@ export class NearPriceFeedContract extends PriceFeedContract {
   }
 
   getId(): string {
-    return `${this.chain.getId()}__${this.address.replace(/-|\./g, "_")}`;
+    return `${this.chain.getId()}__${this.address.replaceAll(/-|\./g, "_")}`;
   }
 
   getType(): string {
@@ -137,7 +140,7 @@ export class NearPriceFeedContract extends PriceFeedContract {
       throw new Error("Invalid type");
     }
     if (!(chain instanceof NearChain)) {
-      throw new Error(`Wrong chain type ${chain}`);
+      throw new TypeError(`Wrong chain type ${chain}`);
     }
     return new NearPriceFeedContract(
       chain,
@@ -158,10 +161,12 @@ export class NearPriceFeedContract extends PriceFeedContract {
 
   async getValidTimePeriod(): Promise<number> {
     const account = await this.getContractNearAccount();
-    return account.viewFunction({
+    const result = await account.viewFunction({
       contractId: this.address,
       methodName: "get_stale_threshold",
     });
+
+    return Number(result);
   }
 
   async getDataSources(): Promise<DataSource[]> {
@@ -201,24 +206,22 @@ export class NearPriceFeedContract extends PriceFeedContract {
       methodName: "get_ema_price_unsafe",
       args: { price_id: feedId },
     });
-    if (price === null || emaPrice === null) {
-      return undefined;
-    } else {
-      return {
-        price: {
-          price: price.price,
-          conf: price.conf,
-          expo: price.expo.toString(),
-          publishTime: price.publish_time.toString(),
-        },
-        emaPrice: {
-          price: emaPrice.price,
-          conf: emaPrice.conf,
-          expo: emaPrice.expo.toString(),
-          publishTime: emaPrice.publish_time.toString(),
-        },
-      };
-    }
+    return price === null || emaPrice === null
+      ? undefined
+      : {
+          price: {
+            price: price.price,
+            conf: price.conf,
+            expo: price.expo.toString(),
+            publishTime: price.publish_time.toString(),
+          },
+          emaPrice: {
+            price: emaPrice.price,
+            conf: emaPrice.conf,
+            expo: emaPrice.expo.toString(),
+            publishTime: emaPrice.publish_time.toString(),
+          },
+        };
   }
 
   async executeUpdatePriceFeed(
@@ -244,14 +247,12 @@ export class NearPriceFeedContract extends PriceFeedContract {
       });
       results.push({ id: outcome.transaction.hash, info: outcome });
     }
-    if (results.length === 1) {
-      return results[0]!;
-    } else {
-      return {
-        id: results.map((x) => x.id).join(","),
-        info: results.map((x) => x.info),
-      };
-    }
+    return results.length === 1
+      ? results[0]!
+      : {
+          id: results.map((x) => x.id).join(","),
+          info: results.map((x) => x.info),
+        };
   }
 
   async executeGovernanceInstruction(

+ 23 - 14
contract_manager/src/core/contracts/starknet.ts

@@ -1,15 +1,24 @@
+/* eslint-disable unicorn/no-await-expression-member */
+/* eslint-disable @typescript-eslint/no-unsafe-argument */
+/* eslint-disable @typescript-eslint/no-unsafe-member-access */
+/* eslint-disable @typescript-eslint/no-unsafe-return */
+/* eslint-disable @typescript-eslint/no-unsafe-assignment */
+/* eslint-disable @typescript-eslint/no-unsafe-call */
+/* eslint-disable @typescript-eslint/restrict-template-expressions */
+/* eslint-disable @typescript-eslint/no-base-to-string */
+import { ByteBuffer } from "@pythnetwork/pyth-starknet-js";
 import type { DataSource } from "@pythnetwork/xc-admin-common";
-import {
-  type KeyValueConfig,
-  type Price,
-  type PriceFeed,
-  PriceFeedContract,
-  type PrivateKey,
-  type TxResult,
+import { Account, Contract, shortString } from "starknet";
+
+import type {
+  KeyValueConfig,
+  Price,
+  PriceFeed,
+  PrivateKey,
+  TxResult,
 } from "../base";
+import { PriceFeedContract } from "../base";
 import { Chain, StarknetChain } from "../chains";
-import { Account, Contract, shortString } from "starknet";
-import { ByteBuffer } from "@pythnetwork/pyth-starknet-js";
 import { WormholeContract } from "./wormhole";
 
 export class StarknetWormholeContract extends WormholeContract {
@@ -179,7 +188,7 @@ export class StarknetPriceFeedContract extends PriceFeedContract {
 
   /**
    * Returns the single update fee and symbol of the specified token.
-   * @param token hex encoded token address without 0x prefix
+   * @param token - hex encoded token address without 0x prefix
    */
   async getBaseUpdateFeeInToken(
     token: string,
@@ -203,13 +212,13 @@ export class StarknetPriceFeedContract extends PriceFeedContract {
   async getPriceFeed(feedId: string): Promise<PriceFeed | undefined> {
     const contract = await this.getContractClient();
     const result = await contract.query_price_feed_unsafe("0x" + feedId);
-    if (result.Ok !== undefined) {
+    if (result.Ok === undefined) {
+      throw new Error(JSON.stringify(result.Err));
+    } else {
       return {
         price: convertPrice(result.Ok.price),
         emaPrice: convertPrice(result.Ok.ema_price),
       };
-    } else {
-      throw new Error(JSON.stringify(result.Err));
     }
   }
 
@@ -227,7 +236,7 @@ export class StarknetPriceFeedContract extends PriceFeedContract {
     );
     contract.connect(account);
 
-    const feeToken = "0x" + (await this.getFeeTokenAddresses())[0];
+    const feeToken = `0x${(await this.getFeeTokenAddresses())[0]}`;
     const tokenClassData = await provider.getClassAt(feeToken);
     const tokenContract = new Contract(tokenClassData.abi, feeToken, provider);
     tokenContract.connect(account);

+ 37 - 37
contract_manager/src/core/contracts/sui.ts

@@ -1,12 +1,23 @@
-import { Chain, SuiChain } from "../chains";
-import type { DataSource } from "@pythnetwork/xc-admin-common";
-import { WormholeContract } from "./wormhole";
-import { PriceFeedContract, type PrivateKey, type TxResult } from "../base";
-import { SuiPythClient } from "@pythnetwork/pyth-sui-js";
-import { SUI_CLOCK_OBJECT_ID } from "@mysten/sui/utils";
+/* eslint-disable @typescript-eslint/no-unsafe-return */
+/* eslint-disable @typescript-eslint/no-unsafe-call */
+/* eslint-disable @typescript-eslint/no-unsafe-assignment */
+/* eslint-disable @typescript-eslint/no-non-null-assertion */
+/* eslint-disable @typescript-eslint/no-unsafe-member-access */
+/* eslint-disable @typescript-eslint/no-unsafe-argument */
+/* eslint-disable @typescript-eslint/require-await */
+/* eslint-disable @typescript-eslint/restrict-template-expressions */
+/* eslint-disable @typescript-eslint/no-base-to-string */
+import { uint8ArrayToBCS } from "@certusone/wormhole-sdk/lib/cjs/sui";
 import { Ed25519Keypair } from "@mysten/sui/keypairs/ed25519";
 import { Transaction } from "@mysten/sui/transactions";
-import { uint8ArrayToBCS } from "@certusone/wormhole-sdk/lib/cjs/sui";
+import { SUI_CLOCK_OBJECT_ID } from "@mysten/sui/utils";
+import { SuiPythClient } from "@pythnetwork/pyth-sui-js";
+import type { DataSource } from "@pythnetwork/xc-admin-common";
+
+import type { PrivateKey, TxResult } from "../base";
+import { Chain, SuiChain } from "../chains";
+import { WormholeContract } from "./wormhole";
+import { PriceFeedContract } from "../base";
 
 type ObjectId = string;
 
@@ -18,9 +29,9 @@ export class SuiPriceFeedContract extends PriceFeedContract {
    * Given the ids of the pyth state and wormhole state, create a new SuiPriceFeedContract
    * The package ids are derived based on the state ids
    *
-   * @param chain the chain which this contract is deployed on
-   * @param stateId id of the pyth state for the deployed contract
-   * @param wormholeStateId id of the wormhole state for the wormhole contract that pyth binds to
+   * @param chain - the chain which this contract is deployed on
+   * @param stateId - id of the pyth state for the deployed contract
+   * @param wormholeStateId - id of the wormhole state for the wormhole contract that pyth binds to
    */
   constructor(
     public chain: SuiChain,
@@ -69,7 +80,7 @@ export class SuiPriceFeedContract extends PriceFeedContract {
 
   /**
    * Given a objectId, returns the id for the package that the object belongs to.
-   * @param objectId
+   * @param objectId - the object id to get
    */
   async getPackageId(objectId: ObjectId): Promise<ObjectId> {
     return this.client.getPackageId(objectId);
@@ -111,12 +122,12 @@ export class SuiPriceFeedContract extends PriceFeedContract {
   async getPriceFeed(feedId: string) {
     const provider = this.getProvider();
     const priceInfoObjectId = await this.client.getPriceFeedObjectId(feedId);
-    if (!priceInfoObjectId) return undefined;
+    if (!priceInfoObjectId) return;
     const priceInfo = await provider.getObject({
       id: priceInfoObjectId,
       options: { showContent: true },
     });
-    if (!priceInfo.data || !priceInfo.data.content) {
+    if (!priceInfo.data?.content) {
       throw new Error(
         `Price feed ID ${priceInfoObjectId} in price table but object not found!!`,
       );
@@ -144,8 +155,8 @@ export class SuiPriceFeedContract extends PriceFeedContract {
   /**
    * Given a signed VAA, execute the migration instruction on the pyth contract.
    * The payload of the VAA can be obtained from the `getUpgradePackagePayload` method.
-   * @param vaa
-   * @param keypair used to sign the transaction
+   * @param vaa - the vaa payload
+   * @param keypair - used to sign the transaction
    */
   async executeMigrateInstruction(vaa: Buffer, keypair: Ed25519Keypair) {
     const tx = new Transaction();
@@ -260,10 +271,9 @@ export class SuiPriceFeedContract extends PriceFeedContract {
   /**
    * Utility function to get the verification receipt object for a VAA that can be
    * used to authorize a governance instruction.
-   * @param tx
-   * @param packageId pyth package id
-   * @param vaa
-   * @private
+   * @param tx - the transaction
+   * @param packageId - pyth package id
+   * @param vaa - the vaa payload
    */
   async getVaaVerificationReceipt(
     tx: Transaction,
@@ -276,7 +286,7 @@ export class SuiPriceFeedContract extends PriceFeedContract {
       target: `${wormholePackageId}::vaa::parse_and_verify`,
       arguments: [
         tx.object(this.wormholeStateId),
-        tx.pure.arguments(Array.from(vaa)),
+        tx.pure.arguments([...vaa]),
         tx.object(SUI_CLOCK_OBJECT_ID),
       ],
     });
@@ -291,9 +301,8 @@ export class SuiPriceFeedContract extends PriceFeedContract {
   /**
    * Given a transaction block and a keypair, sign and execute it
    * Sets the gas budget to 2x the estimated gas cost
-   * @param tx
-   * @param keypair
-   * @private
+   * @param tx - the transaction
+   * @param keypair - the keypair
    */
   private async executeTransaction(tx: Transaction, keypair: Ed25519Keypair) {
     const provider = this.getProvider();
@@ -328,7 +337,7 @@ export class SuiPriceFeedContract extends PriceFeedContract {
         value: "data_sources",
       },
     });
-    if (!result.data || !result.data.content) {
+    if (!result.data?.content) {
       throw new Error(
         "Data Sources not found, contract may not be initialized",
       );
@@ -395,11 +404,7 @@ export class SuiPriceFeedContract extends PriceFeedContract {
       id: this.stateId,
       options: { showContent: true },
     });
-    if (
-      !result.data ||
-      !result.data.content ||
-      result.data.content.dataType !== "moveObject"
-    )
+    if (!result.data?.content || result.data.content.dataType !== "moveObject")
       throw new Error("Unable to fetch pyth state object");
     return result.data.content.fields;
   }
@@ -532,11 +537,7 @@ export class SuiWormholeContract extends WormholeContract {
       id: this.stateId,
       options: { showContent: true },
     });
-    if (
-      !result.data ||
-      !result.data.content ||
-      result.data.content.dataType !== "moveObject"
-    )
+    if (!result.data?.content || result.data.content.dataType !== "moveObject")
       throw new Error("Unable to fetch pyth state object");
     return result.data.content.fields;
   }
@@ -544,9 +545,8 @@ export class SuiWormholeContract extends WormholeContract {
   /**
    * Given a transaction block and a keypair, sign and execute it
    * Sets the gas budget to 2x the estimated gas cost
-   * @param tx
-   * @param keypair
-   * @private
+   * @param tx - the transaction
+   * @param keypair - the keypair
    */
   private async executeTransaction(tx: Transaction, keypair: Ed25519Keypair) {
     const provider = this.chain.getProvider();

+ 6 - 4
contract_manager/src/core/contracts/wormhole.ts

@@ -1,4 +1,5 @@
-import { type PrivateKey, Storable, type TxResult } from "../base";
+import type { PrivateKey, TxResult } from "../base";
+import { Storable } from "../base";
 
 export abstract class WormholeContract extends Storable {
   abstract getCurrentGuardianSetIndex(): Promise<number>;
@@ -16,8 +17,8 @@ export abstract class WormholeContract extends Storable {
 
   /**
    * Upgrades the guardian set of this contract using an upgrade VAA
-   * @param senderPrivateKey
-   * @param vaa
+   * @param senderPrivateKey - the sender private key
+   * @param vaa - the vaa payload
    */
   abstract upgradeGuardianSets(
     senderPrivateKey: PrivateKey,
@@ -26,7 +27,7 @@ export abstract class WormholeContract extends Storable {
 
   /**
    * Upgrades the guardian set of this contract with the 3 pre-configured VAAs for mainnet assuming this is a mainnet contract
-   * @param senderPrivateKey
+   * @param senderPrivateKey - the sender private key
    */
   async syncMainnetGuardianSets(senderPrivateKey: PrivateKey) {
     const MAINNET_UPGRADE_VAAS = [
@@ -42,6 +43,7 @@ export abstract class WormholeContract extends Storable {
         senderPrivateKey,
         Buffer.from(vaa, "hex"),
       );
+      // eslint-disable-next-line no-console, @typescript-eslint/restrict-template-expressions
       console.log(`Submitted upgrade VAA ${i} with tx id ${result.id}`);
       // make sure the upgrade is complete before continuing
       while ((await this.getCurrentGuardianSetIndex()) <= i) {

+ 8 - 3
contract_manager/src/core/token.ts

@@ -1,5 +1,10 @@
+/* eslint-disable @typescript-eslint/no-unsafe-member-access */
+/* eslint-disable @typescript-eslint/no-unsafe-argument */
+/* eslint-disable @typescript-eslint/no-unsafe-assignment */
 import axios from "axios";
-import { type KeyValueConfig, Storable } from "./base";
+
+import type { KeyValueConfig } from "./base";
+import { Storable } from "./base";
 
 export type TokenId = string;
 /**
@@ -48,7 +53,7 @@ export class Token extends Storable {
 
       // Note that this conversion can lose some precision.
       // We don't really care about that in this application.
-      return parseInt(price.price) * Math.pow(10, price.expo);
+      return Number.parseInt(price.price) * Math.pow(10, price.expo);
     } else {
       // We may support other pricing methodologies in the future but whatever.
       return undefined;
@@ -67,7 +72,7 @@ export class Token extends Storable {
   toJson(): KeyValueConfig {
     return {
       id: this.id,
-      ...(this.pythId !== undefined ? { pythId: this.pythId } : {}),
+      ...(this.pythId === undefined ? {} : { pythId: this.pythId }),
     };
   }
 

+ 7 - 5
contract_manager/src/node/utils/executor.ts

@@ -1,9 +1,11 @@
+/* eslint-disable no-console */
 import { parseVaa } from "@certusone/wormhole-sdk";
+import type { DataSource } from "@pythnetwork/xc-admin-common";
 import {
-  type DataSource,
   EvmExecute,
   decodeGovernancePayload,
 } from "@pythnetwork/xc-admin-common";
+
 import { DefaultStore } from "./store.js";
 import type { PrivateKey, TxResult } from "../../core/base.js";
 import { EvmChain } from "../../core/chains.js";
@@ -11,7 +13,7 @@ import { EvmExecutorContract } from "../../core/contracts/evm.js";
 
 // TODO: A better place for this would be `base.ts`. That will require
 // significant refactor. Todo in separate PR.
-interface GovernanceContract {
+type GovernanceContract = {
   getId(): string;
   getGovernanceDataSource(): Promise<DataSource>;
   getLastExecutedGovernanceSequence(): Promise<number>;
@@ -19,7 +21,7 @@ interface GovernanceContract {
     senderPrivateKey: PrivateKey,
     vaa: Buffer,
   ): Promise<TxResult>;
-}
+};
 
 async function executeForGovernanceContract(
   contract: GovernanceContract,
@@ -51,8 +53,8 @@ async function executeForGovernanceContract(
 
 /**
  * A general executor that tries to find any contract that can execute a given VAA and executes it
- * @param senderPrivateKey the private key to execute the governance instruction with
- * @param vaa the VAA to execute
+ * @param senderPrivateKey - the private key to execute the governance instruction with
+ * @param vaa - src/node/utils/executor.tsthe VAA to execute
  */
 export async function executeVaa(senderPrivateKey: PrivateKey, vaa: Buffer) {
   const parsedVaa = parseVaa(vaa);

+ 62 - 45
contract_manager/src/node/utils/governance.ts

@@ -1,38 +1,49 @@
-import { readFileSync } from "fs";
+/* eslint-disable @typescript-eslint/no-unsafe-argument */
+/* eslint-disable @typescript-eslint/no-explicit-any */
+/* eslint-disable @typescript-eslint/no-unsafe-member-access */
+/* eslint-disable @typescript-eslint/no-unsafe-return */
+/* eslint-disable @typescript-eslint/restrict-template-expressions */
+import { readFileSync } from "node:fs";
 
+import {
+  createWormholeProgramInterface,
+  deriveEmitterSequenceKey,
+  deriveFeeCollectorKey,
+  deriveWormholeBridgeDataKey,
+} from "@certusone/wormhole-sdk/lib/cjs/solana/wormhole/index.js";
+import { AnchorProvider, Wallet } from "@coral-xyz/anchor";
+import NodeWallet from "@coral-xyz/anchor/dist/cjs/nodewallet.js";
+import type { PythCluster } from "@pythnetwork/client";
+import { getPythClusterApiUrl } from "@pythnetwork/client";
+import type { PriorityFeeConfig } from "@pythnetwork/solana-utils";
+import {
+  executeProposal,
+  MultisigVault,
+  WORMHOLE_ADDRESS,
+  WORMHOLE_API_ENDPOINT,
+} from "@pythnetwork/xc-admin-common";
+import type {
+  ParsedInstruction,
+  PartiallyDecodedInstruction,
+} from "@solana/web3.js";
 import {
   Connection,
   Keypair,
-  type ParsedInstruction,
-  type PartiallyDecodedInstruction,
   PublicKey,
   SystemProgram,
   SYSVAR_CLOCK_PUBKEY,
   SYSVAR_RENT_PUBKEY,
   Transaction,
 } from "@solana/web3.js";
-import * as bs58 from "bs58";
-import { getPythClusterApiUrl, type PythCluster } from "@pythnetwork/client";
-import { AnchorProvider, Wallet } from "@coral-xyz/anchor";
-import {
-  executeProposal,
-  MultisigVault,
-  WORMHOLE_ADDRESS,
-  WORMHOLE_API_ENDPOINT,
-} from "@pythnetwork/xc-admin-common";
-import { type KeyValueConfig, Storable } from "../../core/base.js";
-import type { PriorityFeeConfig } from "@pythnetwork/solana-utils";
 import SquadsMesh from "@sqds/mesh";
+import * as bs58 from "bs58";
+
+import type { KeyValueConfig } from "../../core/base.js";
+import { Storable } from "../../core/base.js";
+
 // TODO: this should be migrated to @wormhole-foundation/dsk
 // as such, we cannot publish an ESM variant of the contract_manager
 // until we upgrade
-import {
-  createWormholeProgramInterface,
-  deriveEmitterSequenceKey,
-  deriveFeeCollectorKey,
-  deriveWormholeBridgeDataKey,
-} from "@certusone/wormhole-sdk/lib/cjs/solana/wormhole/index.js";
-import NodeWallet from "@coral-xyz/anchor/dist/cjs/nodewallet.js";
 
 class InvalidTransactionError extends Error {
   constructor(message: string) {
@@ -55,9 +66,9 @@ export class SubmittedWormholeMessage {
    * Attempts to find the emitter and sequence number of a wormhole message from a transaction
    * Parses the transaction and looks for the wormhole postMessage instruction to find the emitter
    * Inspects the transaction logs to find the sequence number
-   * @param signature signature of the transaction to inspect
-   * @param cluster the cluster the transaction was submitted to
-   * @param registry registry of RPC nodes to use for each solana network. Defaults to the Solana public RPCs if not provided.
+   * @param signature - signature of the transaction to inspect
+   * @param cluster - the cluster the transaction was submitted to
+   * @param registry - registry of RPC nodes to use for each solana network. Defaults to the Solana public RPCs if not provided.
    */
   static async fromTransactionSignature(
     signature: string,
@@ -73,8 +84,11 @@ export class SubmittedWormholeMessage {
     );
 
     const sequenceNumber = Number(
-      txLog?.substring(
-        txLog.indexOf(sequenceLogPrefix) + sequenceLogPrefix.length,
+      txLog?.slice(
+        Math.max(
+          0,
+          txLog.indexOf(sequenceLogPrefix) + sequenceLogPrefix.length,
+        ),
       ),
     );
 
@@ -83,17 +97,18 @@ export class SubmittedWormholeMessage {
     let emitter: PublicKey | undefined = undefined;
 
     let allInstructions: (ParsedInstruction | PartiallyDecodedInstruction)[] =
-      txDetails?.transaction?.message?.instructions || [];
-    txDetails?.meta?.innerInstructions?.forEach((instruction) => {
-      allInstructions = allInstructions.concat(instruction.instructions);
-    });
-    allInstructions.forEach((instruction) => {
-      if (!instruction.programId.equals(wormholeAddress)) return;
+      txDetails?.transaction.message.instructions ?? [];
+    if (txDetails?.meta?.innerInstructions)
+      for (const instruction of txDetails.meta.innerInstructions) {
+        allInstructions = [...allInstructions, ...instruction.instructions];
+      }
+    for (const instruction of allInstructions) {
+      if (!instruction.programId.equals(wormholeAddress)) continue;
       // we assume RPC can not parse wormhole instructions and the type is not ParsedInstruction
       const wormholeInstruction = instruction as PartiallyDecodedInstruction;
-      if (bs58.decode(wormholeInstruction.data)[0] !== 1) return; // 1 is wormhole postMessage Instruction discriminator
+      if (bs58.decode(wormholeInstruction.data)[0] !== 1) continue; // 1 is wormhole postMessage Instruction discriminator
       emitter = wormholeInstruction.accounts[2];
-    });
+    }
     if (!emitter)
       throw new InvalidTransactionError(
         "Could not find wormhole postMessage instruction",
@@ -104,7 +119,7 @@ export class SubmittedWormholeMessage {
   /**
    * Tries to fetch the VAA from the wormhole bridge API waiting for a certain amount of time
    * before giving up and throwing an error
-   * @param waitingSeconds how long to wait before giving up
+   * @param waitingSeconds - how long to wait before giving up
    */
   async fetchVaa(waitingSeconds = 1): Promise<Buffer> {
     const rpcUrl = WORMHOLE_API_ENDPOINT[this.cluster];
@@ -156,8 +171,8 @@ export class WormholeEmitter {
 
   /**
    * Send a wormhole message containing payload through wormhole.
-   * @param payload the contents of the message
-   * @param registry registry of RPC nodes to use for each solana network. Defaults to the Solana public RPCs if not provided.
+   * @param payload - the contents of the message
+   * @param registry - registry of RPC nodes to use for each solana network. Defaults to the Solana public RPCs if not provided.
    */
   async sendMessage(
     payload: Buffer,
@@ -252,8 +267,8 @@ export class WormholeMultisigProposal {
             this.cluster,
           ),
         );
-      } catch (e) {
-        if (!(e instanceof InvalidTransactionError)) throw e;
+      } catch (error) {
+        if (!(error instanceof InvalidTransactionError)) throw error;
       }
     }
     if (msgs.length > 0) return msgs;
@@ -305,8 +320,8 @@ export class Vault extends Storable {
   /**
    * Connects the vault to a wallet that can be used to submit proposals
    * The wallet should be a multisig signer of the vault
-   * @param wallet
-   * @param registry registry of RPC nodes to use for each solana network. Defaults to the Solana public RPCs if not provided.
+   * @param wallet - the wallet
+   * @param registry - registry of RPC nodes to use for each solana network. Defaults to the Solana public RPCs if not provided.
    */
   public connect(
     wallet: Wallet,
@@ -322,8 +337,9 @@ export class Vault extends Storable {
 
   /**
    * Gets the emitter address of the vault
-   * @param registry registry of RPC nodes to use for each solana network. Defaults to the Solana public RPCs if not provided.
+   * @param registry - registry of RPC nodes to use for each solana network. Defaults to the Solana public RPCs if not provided.
    */
+  // eslint-disable-next-line @typescript-eslint/require-await
   public async getEmitter(registry: SolanaRpcRegistry = getPythClusterApiUrl) {
     const squad = SquadsMesh.endpoint(
       registry(this.cluster),
@@ -352,8 +368,8 @@ export class Vault extends Storable {
    * Proposes sending an array of wormhole messages to the wormhole bridge
    * Requires a wallet to be connected to the vault
    *
-   * @param payloads the payloads to send to the wormhole bridge
-   * @param proposalAddress if specified, will continue an existing proposal
+   * @param payloads - the payloads to send to the wormhole bridge
+   * @param proposalAddress - if specified, will continue an existing proposal
    */
   public async proposeWormholeMessage(
     payloads: Buffer[],
@@ -381,8 +397,9 @@ export class Vault extends Storable {
 /**
  * Loads a solana wallet from a file. The file should contain the secret key in array of integers format
  * This wallet can be used to connect to a vault and submit proposals
- * @param walletPath path to the wallet file
+ * @param walletPath - - path to the wallet file
  */
+// eslint-disable-next-line @typescript-eslint/require-await
 export async function loadHotWallet(walletPath: string): Promise<Wallet> {
   return new NodeWallet(
     Keypair.fromSecretKey(

+ 33 - 23
contract_manager/src/node/utils/store.ts

@@ -1,3 +1,16 @@
+/* eslint-disable no-empty */
+/* eslint-disable tsdoc/syntax */
+/* eslint-disable unicorn/no-array-for-each */
+/* eslint-disable unicorn/no-array-push-push */
+/* eslint-disable @typescript-eslint/no-non-null-assertion */
+/* eslint-disable @typescript-eslint/no-unsafe-argument */
+/* eslint-disable @typescript-eslint/restrict-template-expressions */
+/* eslint-disable @typescript-eslint/no-unsafe-member-access */
+/* eslint-disable @typescript-eslint/no-unsafe-assignment */
+import { readdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
+
+import { Vault } from "./governance";
+import { PriceFeedContract, Storable } from "../../core/base";
 import {
   AptosChain,
   Chain,
@@ -32,18 +45,15 @@ import {
   EvmExecutorContract,
   EvmLazerContract,
 } from "../../core/contracts";
-import { Token } from "../../core/token";
-import { PriceFeedContract, Storable } from "../../core/base";
-import { readdirSync, readFileSync, statSync, writeFileSync } from "fs";
-import { Vault } from "./governance";
-import {
-  StarknetPriceFeedContract,
-  StarknetWormholeContract,
-} from "../../core/contracts/starknet";
 import {
   NearPriceFeedContract,
   NearWormholeContract,
 } from "../../core/contracts/near";
+import {
+  StarknetPriceFeedContract,
+  StarknetWormholeContract,
+} from "../../core/contracts/starknet";
+import { Token } from "../../core/token";
 
 export class Store {
   public chains: Record<string, Chain> = { global: new GlobalChain() };
@@ -64,24 +74,24 @@ export class Store {
   }
 
   static serialize(obj: Storable) {
-    return JSON.stringify([obj.toJson()], null, 2);
+    return JSON.stringify([obj.toJson()], undefined, 2);
   }
 
   getJsonFiles(path: string) {
     const walk = function (dir: string) {
       let results: string[] = [];
       const list = readdirSync(dir);
-      list.forEach(function (file) {
+      for (let file of list) {
         file = dir + "/" + file;
         const stat = statSync(file);
-        if (stat && stat.isDirectory()) {
+        if (stat.isDirectory()) {
           // Recurse into a subdirectory
-          results = results.concat(walk(file));
+          results = [...results, ...walk(file)];
         } else {
           // Is a file
           results.push(file);
         }
-      });
+      }
       return results;
     };
     return walk(path).filter((file) => file.endsWith(".json"));
@@ -101,8 +111,8 @@ export class Store {
       [IotaChain.type]: IotaChain,
     };
 
-    this.getJsonFiles(`${this.path}/chains/`).forEach((jsonFile) => {
-      const parsedArray = JSON.parse(readFileSync(jsonFile, "utf-8"));
+    for (const jsonFile of this.getJsonFiles(`${this.path}/chains/`)) {
+      const parsedArray = JSON.parse(readFileSync(jsonFile, "utf8"));
       for (const parsed of parsedArray) {
         if (allChainClasses[parsed.type] === undefined) {
           throw new Error(
@@ -116,7 +126,7 @@ export class Store {
         }
         this.chains[id] = chain!;
       }
-    });
+    }
   }
 
   saveAllContracts() {
@@ -137,7 +147,7 @@ export class Store {
         `${this.path}/contracts/${type}s.json`,
         JSON.stringify(
           contracts.map((c) => c.toJson()),
-          null,
+          undefined,
           2,
         ),
       );
@@ -157,7 +167,7 @@ export class Store {
         `${this.path}/chains/${type}s.json`,
         JSON.stringify(
           chains.map((c) => c.toJson()),
-          null,
+          undefined,
           2,
         ),
       );
@@ -189,7 +199,7 @@ export class Store {
       [EvmLazerContract.type]: EvmLazerContract,
     };
     this.getJsonFiles(`${this.path}/contracts/`).forEach((jsonFile) => {
-      const parsedArray = JSON.parse(readFileSync(jsonFile, "utf-8"));
+      const parsedArray = JSON.parse(readFileSync(jsonFile, "utf8"));
       for (const parsed of parsedArray) {
         if (allContractClasses[parsed.type] === undefined) return;
         if (!this.chains[parsed.chain])
@@ -226,7 +236,7 @@ export class Store {
 
   loadAllTokens() {
     this.getJsonFiles(`${this.path}/tokens/`).forEach((jsonFile) => {
-      const parsedArray = JSON.parse(readFileSync(jsonFile, "utf-8"));
+      const parsedArray = JSON.parse(readFileSync(jsonFile, "utf8"));
       for (const parsed of parsedArray) {
         if (parsed.type !== Token.type) return;
 
@@ -240,7 +250,7 @@ export class Store {
 
   loadAllVaults() {
     this.getJsonFiles(`${this.path}/vaults/`).forEach((jsonFile) => {
-      const parsedArray = JSON.parse(readFileSync(jsonFile, "utf-8"));
+      const parsedArray = JSON.parse(readFileSync(jsonFile, "utf8"));
       for (const parsed of parsedArray) {
         if (parsed.type !== Vault.type) return;
 
@@ -254,8 +264,8 @@ export class Store {
 
   /**
    * Returns the chain with the given ID, or throws an error if it doesn't exist or is not of the specified type.
-   * @param chainId The unique identifier of the chain to retrieve
-   * @param ChainClass Optional class to validate the chain type.
+   * @param chainId - The unique identifier of the chain to retrieve
+   * @param ChainClass - Optional class to validate the chain type.
    * @returns The chain instance of type T
    * @throws Error if chain doesn't exist or is not of the specified type
    * @template T Type of chain to return, extends base Chain class

+ 5 - 3
contract_manager/src/utils/utils.ts

@@ -1,7 +1,8 @@
+import * as chains from "viem/chains";
+
 import evmChainsData from "../store/chains/EvmChains.json" with { type: "json" };
 import evmPriceFeedContractsData from "../store/contracts/EvmPriceFeedContracts.json" with { type: "json" };
 import evmWormholeContractsData from "../store/contracts/EvmWormholeContracts.json" with { type: "json" };
-import * as chains from "viem/chains";
 
 export const allEvmChainIds: number[] = evmChainsData.map((c) => c.networkId);
 
@@ -29,7 +30,7 @@ const getContractAddress = (
     if (contract?.address === undefined) {
       return undefined;
     } else if (isZeroXString(contract.address)) {
-      return contract.address as `0x${string}`;
+      return contract.address;
     } else {
       throw new Error(
         `Invariant failed: invalid contract address ${contract.address} for chain ${contract.chain}`,
@@ -50,7 +51,8 @@ export const getEvmChainRpcUrl = (chainId: number): string | undefined => {
       (c) => "id" in c && c.id === Number.parseInt(chain.id, 10),
     );
     if (viemChain && "rpcUrls" in viemChain) {
-      return viemChain?.rpcUrls.default.http[0] ?? chain.rpcUrl;
+      // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
+      return viemChain.rpcUrls.default.http[0] ?? chain.rpcUrl;
     }
     return;
   }

+ 4 - 0
governance/pyth_staking_sdk/src/utils/transaction.ts

@@ -1,3 +1,7 @@
+/* eslint-disable @typescript-eslint/no-unsafe-call */
+/* eslint-disable @typescript-eslint/no-unsafe-assignment */
+/* eslint-disable @typescript-eslint/no-unsafe-member-access */
+/* eslint-disable @typescript-eslint/no-unsafe-argument */
 import { TransactionBuilder } from "@pythnetwork/solana-utils";
 import { Connection, TransactionInstruction } from "@solana/web3.js";
 

+ 4 - 1
governance/xc_admin/packages/xc_admin_common/src/message_buffer.ts

@@ -1,4 +1,7 @@
-import { getPythProgramKeyForCluster, type PythCluster } from "@pythnetwork/client";
+import {
+  getPythProgramKeyForCluster,
+  type PythCluster,
+} from "@pythnetwork/client";
 import { PublicKey } from "@solana/web3.js";
 
 /**

+ 4 - 1
governance/xc_admin/packages/xc_admin_common/src/multisig.ts

@@ -4,7 +4,10 @@ import Squads, {
   getIxPDA,
   getTxPDA,
 } from "@sqds/mesh";
-import { type InstructionAccount, type TransactionAccount } from "@sqds/mesh/lib/types";
+import {
+  type InstructionAccount,
+  type TransactionAccount,
+} from "@sqds/mesh/lib/types";
 import BN from "bn.js";
 import lodash from "lodash";
 

Some files were not shown because too many files changed in this diff