Quellcode durchsuchen

feat(apps/price_pusher): add fuel price pusher (#1910)

* update .gitignore

* add fuel

* precommit

* update fuel testnet contract address

* add comment

* bump
Daniel Chew vor 1 Jahr
Ursprung
Commit
853b777d01

+ 1 - 0
apps/price_pusher/.gitignore

@@ -1,3 +1,4 @@
 docker-compose.yaml
 price-config.yaml
 lib
+mnemonic

+ 7 - 0
apps/price_pusher/config.fuel.testnet.sample.json

@@ -0,0 +1,7 @@
+{
+  "endpoint": "https://testnet.fuel.network/v1/graphql",
+  "pyth-contract-address": "0xe31e04946c67fb41923f93d50ee7fc1c6c99d6e07c02860c6bea5f4a13919277",
+  "price-service-endpoint": "https://hermes.pyth.network",
+  "private-key-file": "./mnemonic",
+  "price-config-file": "./price-config.stable.sample.yaml"
+}

+ 8 - 2
apps/price_pusher/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@pythnetwork/price-pusher",
-  "version": "8.0.0",
+  "version": "8.0.1",
   "description": "Pyth Price Pusher",
   "homepage": "https://pyth.network",
   "main": "lib/index.js",
@@ -35,7 +35,11 @@
     "oracle",
     "evm",
     "ethereum",
-    "injective"
+    "injective",
+    "fuel",
+    "aptos",
+    "sui",
+    "near"
   ],
   "license": "Apache-2.0",
   "devDependencies": {
@@ -63,9 +67,11 @@
     "@pythnetwork/pyth-solana-receiver": "workspace:*",
     "@pythnetwork/pyth-sui-js": "workspace:*",
     "@pythnetwork/solana-utils": "workspace:*",
+    "@pythnetwork/pyth-fuel-js": "workspace:*",
     "@solana/web3.js": "^1.93.0",
     "@types/pino": "^7.0.5",
     "aptos": "^1.8.5",
+    "fuels": "^0.94.5",
     "jito-ts": "^3.0.1",
     "joi": "^17.6.0",
     "near-api-js": "^3.0.2",

+ 105 - 0
apps/price_pusher/src/fuel/command.ts

@@ -0,0 +1,105 @@
+import { Options } from "yargs";
+import * as options from "../options";
+import { readPriceConfigFile } from "../price-config";
+import { PriceServiceConnection } from "@pythnetwork/price-service-client";
+import { PythPriceListener } from "../pyth-price-listener";
+import { FuelPriceListener, FuelPricePusher } from "./fuel";
+import { Controller } from "../controller";
+import { Provider, Wallet } from "fuels";
+import fs from "fs";
+import pino from "pino";
+
+export default {
+  command: "fuel",
+  describe: "run price pusher for Fuel",
+  builder: {
+    endpoint: {
+      description: "Fuel RPC API endpoint",
+      type: "string",
+      required: true,
+    } as Options,
+    "private-key-file": {
+      description: "Path to the private key file",
+      type: "string",
+      required: true,
+    } as Options,
+    "pyth-contract-address": {
+      description: "Pyth contract address on Fuel",
+      type: "string",
+      required: true,
+    } as Options,
+    ...options.priceConfigFile,
+    ...options.priceServiceEndpoint,
+    ...options.pushingFrequency,
+    ...options.pollingFrequency,
+    ...options.logLevel,
+    ...options.priceServiceConnectionLogLevel,
+    ...options.controllerLogLevel,
+  },
+  handler: async function (argv: any) {
+    const {
+      endpoint,
+      privateKeyFile,
+      pythContractAddress,
+      priceConfigFile,
+      priceServiceEndpoint,
+      pushingFrequency,
+      pollingFrequency,
+      logLevel,
+      priceServiceConnectionLogLevel,
+      controllerLogLevel,
+    } = argv;
+
+    const logger = pino({ level: logLevel });
+
+    const priceConfigs = readPriceConfigFile(priceConfigFile);
+
+    const priceServiceConnection = new PriceServiceConnection(
+      priceServiceEndpoint,
+      {
+        logger: logger.child(
+          { module: "PriceServiceConnection" },
+          { level: priceServiceConnectionLogLevel }
+        ),
+      }
+    );
+
+    const priceItems = priceConfigs.map(({ id, alias }) => ({ id, alias }));
+
+    const pythListener = new PythPriceListener(
+      priceServiceConnection,
+      priceItems,
+      logger.child({ module: "PythPriceListener" })
+    );
+
+    const provider = await Provider.create(endpoint);
+    const privateKey = fs.readFileSync(privateKeyFile, "utf8").trim();
+    const wallet = Wallet.fromPrivateKey(privateKey, provider);
+
+    const fuelPriceListener = new FuelPriceListener(
+      provider,
+      pythContractAddress,
+      priceItems,
+      logger.child({ module: "FuelPriceListener" }),
+      { pollingFrequency }
+    );
+
+    const fuelPricePusher = new FuelPricePusher(
+      wallet,
+      pythContractAddress,
+      priceServiceConnection,
+      logger.child({ module: "FuelPricePusher" })
+    );
+
+    const controller = new Controller(
+      priceConfigs,
+      pythListener,
+      fuelPriceListener,
+      fuelPricePusher,
+      logger.child({ module: "Controller" }, { level: controllerLogLevel }),
+      { pushingFrequency }
+    );
+
+    await controller.start();
+  },
+};

+ 134 - 0
apps/price_pusher/src/fuel/fuel.ts

@@ -0,0 +1,134 @@
+import { PriceServiceConnection } from "@pythnetwork/price-service-client";
+import {
+  ChainPriceListener,
+  IPricePusher,
+  PriceInfo,
+  PriceItem,
+} from "../interface";
+import { addLeading0x, DurationInSeconds } from "../utils";
+import { 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";
+
+// Convert TAI64 timestamp to Unix timestamp
+function tai64ToUnix(tai64: BN): number {
+  // TAI64 is 2^62 seconds ahead of Unix epoch (1970-01-01)
+  // Additional 10-second offset accounts for TAI being ahead of UTC at Unix epoch
+  const result = BigInt(tai64.toString()) - BigInt(2n ** 62n) - 10n;
+  return Number(result);
+}
+
+export class FuelPriceListener extends ChainPriceListener {
+  private contract: Contract;
+
+  constructor(
+    private provider: Provider,
+    private pythContractId: string,
+    priceItems: PriceItem[],
+    private logger: Logger,
+    config: {
+      pollingFrequency: DurationInSeconds;
+    }
+  ) {
+    super(config.pollingFrequency, priceItems);
+    this.contract = new Contract(
+      this.pythContractId,
+      PYTH_CONTRACT_ABI,
+      this.provider
+    );
+  }
+
+  async getOnChainPriceInfo(priceId: string): Promise<PriceInfo | undefined> {
+    try {
+      const formattedPriceId = addLeading0x(priceId);
+      const priceInfo = await this.contract.functions
+        .price_unsafe(formattedPriceId)
+        .get();
+
+      console.log({
+        conf: priceInfo.value.confidence.toString(),
+        price: priceInfo.value.price.toString(),
+        publishTime: tai64ToUnix(priceInfo.value.publish_time),
+      });
+
+      this.logger.debug(
+        `Polled a Fuel on chain price for feed ${this.priceIdToAlias.get(
+          priceId
+        )} (${priceId}).`
+      );
+
+      return {
+        conf: priceInfo.value.confidence.toString(),
+        price: priceInfo.value.price.toString(),
+        publishTime: tai64ToUnix(priceInfo.value.publish_time),
+      };
+    } catch (err) {
+      this.logger.error({ err, priceId }, `Polling on-chain price failed.`);
+      return undefined;
+    }
+  }
+}
+
+export class FuelPricePusher implements IPricePusher {
+  private contract: Contract;
+
+  constructor(
+    private wallet: Wallet,
+    private pythContractId: string,
+    private priceServiceConnection: PriceServiceConnection,
+    private logger: Logger
+  ) {
+    this.contract = new Contract(
+      this.pythContractId,
+      PYTH_CONTRACT_ABI,
+      this.wallet as Provider
+    );
+  }
+
+  async updatePriceFeed(
+    priceIds: string[],
+    // eslint-disable-next-line @typescript-eslint/no-unused-vars
+    pubTimesToPush: number[]
+  ): Promise<void> {
+    if (priceIds.length === 0) {
+      return;
+    }
+
+    let priceFeedUpdateData: string[];
+    try {
+      priceFeedUpdateData = await this.priceServiceConnection.getLatestVaas(
+        priceIds
+      );
+    } catch (err: any) {
+      this.logger.error(err, "getPriceFeedsUpdateData failed");
+      return;
+    }
+
+    const updateData = priceFeedUpdateData.map((data) =>
+      arrayify(Buffer.from(data, "base64"))
+    );
+
+    try {
+      const updateFee = await this.contract.functions
+        .update_fee(updateData)
+        .get();
+
+      const result = await this.contract.functions
+        .update_price_feeds(updateData)
+        .callParams({
+          forward: [updateFee.value, hexlify(FUEL_ETH_ASSET_ID)],
+        })
+        .call();
+
+      this.logger.info(
+        { transactionId: result.transactionId },
+        "updatePriceFeed successful"
+      );
+    } catch (err: any) {
+      this.logger.error(err, "updatePriceFeed failed");
+    }
+  }
+}

+ 2 - 0
apps/price_pusher/src/index.ts

@@ -7,6 +7,7 @@ import aptos from "./aptos/command";
 import sui from "./sui/command";
 import near from "./near/command";
 import solana from "./solana/command";
+import fuel from "./fuel/command";
 
 yargs(hideBin(process.argv))
   .parserConfiguration({
@@ -15,6 +16,7 @@ yargs(hideBin(process.argv))
   .config("config")
   .global("config")
   .command(evm)
+  .command(fuel)
   .command(injective)
   .command(aptos)
   .command(sui)

+ 37 - 61
pnpm-lock.yaml

@@ -111,7 +111,7 @@ importers:
         version: 4.9.1
       '@cprussin/eslint-config':
         specifier: ^3.0.0
-        version: 3.0.0(@typescript-eslint/eslint-plugin@7.13.1(eslint@9.5.0)(typescript@5.5.2))(jest@29.7.0(@types/node@20.14.7)(ts-node@10.9.2(@types/node@20.14.7)(typescript@5.5.2)))(ts-node@10.9.2(@types/node@20.14.7)(typescript@5.5.2))(typescript@5.5.2)
+        version: 3.0.0(@typescript-eslint/eslint-plugin@7.13.1(@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.5.2))(eslint@9.5.0)(typescript@5.5.2))(@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.5.2))(jest@29.7.0(@types/node@20.14.7)(ts-node@10.9.2(@types/node@20.14.7)(typescript@5.5.2)))(ts-node@10.9.2(@types/node@20.14.7)(typescript@5.5.2))(typescript@5.5.2)
       '@cprussin/jest-config':
         specifier: ^1.4.1
         version: 1.4.1(@babel/core@7.24.7)(@jest/globals@29.7.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(@types/jest@29.5.12)(@types/node@20.14.7)(babel-jest@29.7.0(@babel/core@7.24.7))(bufferutil@4.0.8)(eslint@9.5.0)(ts-node@10.9.2(@types/node@20.14.7)(typescript@5.5.2))(utf-8-validate@5.0.10)
@@ -236,6 +236,9 @@ importers:
       '@pythnetwork/price-service-sdk':
         specifier: workspace:^
         version: link:../../price_service/sdk/js
+      '@pythnetwork/pyth-fuel-js':
+        specifier: workspace:*
+        version: link:../../target_chains/fuel/sdk/js
       '@pythnetwork/pyth-sdk-solidity':
         specifier: workspace:*
         version: link:../../target_chains/ethereum/sdk/solidity
@@ -257,6 +260,9 @@ importers:
       aptos:
         specifier: ^1.8.5
         version: 1.8.5
+      fuels:
+        specifier: ^0.94.5
+        version: 0.94.5(encoding@0.1.13)
       jito-ts:
         specifier: ^3.0.1
         version: 3.0.1(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10)
@@ -402,7 +408,7 @@ importers:
         version: 4.9.1
       '@cprussin/eslint-config':
         specifier: ^3.0.0
-        version: 3.0.0(@typescript-eslint/eslint-plugin@7.13.1(@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.5.4))(eslint@9.9.0(jiti@1.21.0))(typescript@5.5.4))(@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.5.4))(jest@29.7.0(@types/node@22.2.0)(ts-node@10.9.2(@types/node@22.2.0)(typescript@5.5.4)))(ts-node@10.9.2(@types/node@22.2.0)(typescript@5.5.4))(typescript@5.5.4)
+        version: 3.0.0(@typescript-eslint/eslint-plugin@7.13.1(eslint@9.9.0(jiti@1.21.0))(typescript@5.5.4))(jest@29.7.0(@types/node@22.2.0)(ts-node@10.9.2(@types/node@22.2.0)(typescript@5.5.4)))(ts-node@10.9.2(@types/node@22.2.0)(typescript@5.5.4))(typescript@5.5.4)
       '@cprussin/jest-config':
         specifier: ^1.4.1
         version: 1.4.1(@babel/core@7.24.7)(@jest/globals@29.7.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(@types/jest@29.5.12)(@types/node@22.2.0)(babel-jest@29.7.0(@babel/core@7.24.7))(bufferutil@4.0.8)(eslint@9.9.0(jiti@1.21.0))(ts-node@10.9.2(@types/node@22.2.0)(typescript@5.5.4))(utf-8-validate@5.0.10)
@@ -24397,7 +24403,7 @@ snapshots:
     transitivePeerDependencies:
       - debug
 
-  '@cprussin/eslint-config@3.0.0(@typescript-eslint/eslint-plugin@7.13.1(@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.5.4))(eslint@9.9.0(jiti@1.21.0))(typescript@5.5.4))(@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.5.4))(jest@29.7.0(@types/node@22.2.0)(ts-node@10.9.2(@types/node@22.2.0)(typescript@5.5.4)))(ts-node@10.9.2(@types/node@22.2.0)(typescript@5.5.4))(typescript@5.5.4)':
+  '@cprussin/eslint-config@3.0.0(@typescript-eslint/eslint-plugin@7.13.1(@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.5.2))(eslint@9.5.0)(typescript@5.5.2))(@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.5.2))(jest@29.7.0(@types/node@20.14.7)(ts-node@10.9.2(@types/node@20.14.7)(typescript@5.5.2)))(ts-node@10.9.2(@types/node@20.14.7)(typescript@5.5.2))(typescript@5.5.2)':
     dependencies:
       '@babel/core': 7.24.7
       '@babel/eslint-parser': 7.24.7(@babel/core@7.24.7)(eslint@9.5.0)
@@ -24409,22 +24415,22 @@ snapshots:
       eslint: 9.5.0
       eslint-config-prettier: 9.1.0(eslint@9.5.0)
       eslint-config-turbo: 1.13.4(eslint@9.5.0)
-      eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.5.4))(eslint@9.5.0)
-      eslint-plugin-jest: 28.6.0(@typescript-eslint/eslint-plugin@7.13.1(@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.5.4))(eslint@9.9.0(jiti@1.21.0))(typescript@5.5.4))(eslint@9.5.0)(jest@29.7.0(@types/node@22.2.0)(ts-node@10.9.2(@types/node@22.2.0)(typescript@5.5.4)))(typescript@5.5.4)
+      eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.5.2))(eslint@9.5.0)
+      eslint-plugin-jest: 28.6.0(@typescript-eslint/eslint-plugin@7.13.1(@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.5.2))(eslint@9.5.0)(typescript@5.5.2))(eslint@9.5.0)(jest@29.7.0(@types/node@20.14.7)(ts-node@10.9.2(@types/node@20.14.7)(typescript@5.5.2)))(typescript@5.5.2)
       eslint-plugin-jest-dom: 5.4.0(eslint@9.5.0)
       eslint-plugin-jsonc: 2.16.0(eslint@9.5.0)
       eslint-plugin-jsx-a11y: 6.8.0(eslint@9.5.0)
       eslint-plugin-n: 17.9.0(eslint@9.5.0)
       eslint-plugin-react: 7.34.2(eslint@9.5.0)
       eslint-plugin-react-hooks: 4.6.2(eslint@9.5.0)
-      eslint-plugin-storybook: 0.8.0(eslint@9.5.0)(typescript@5.5.4)
-      eslint-plugin-tailwindcss: 3.17.3(tailwindcss@3.4.4(ts-node@10.9.2(@types/node@22.2.0)(typescript@5.5.4)))
-      eslint-plugin-testing-library: 6.2.2(eslint@9.5.0)(typescript@5.5.4)
+      eslint-plugin-storybook: 0.8.0(eslint@9.5.0)(typescript@5.5.2)
+      eslint-plugin-tailwindcss: 3.17.3(tailwindcss@3.4.4(ts-node@10.9.2(@types/node@20.14.7)(typescript@5.5.2)))
+      eslint-plugin-testing-library: 6.2.2(eslint@9.5.0)(typescript@5.5.2)
       eslint-plugin-tsdoc: 0.3.0
       eslint-plugin-unicorn: 53.0.0(eslint@9.5.0)
       globals: 15.6.0
-      tailwindcss: 3.4.4(ts-node@10.9.2(@types/node@22.2.0)(typescript@5.5.4))
-      typescript-eslint: 7.13.1(eslint@9.5.0)(typescript@5.5.4)
+      tailwindcss: 3.4.4(ts-node@10.9.2(@types/node@20.14.7)(typescript@5.5.2))
+      typescript-eslint: 7.13.1(eslint@9.5.0)(typescript@5.5.2)
     transitivePeerDependencies:
       - '@testing-library/dom'
       - '@typescript-eslint/eslint-plugin'
@@ -24475,7 +24481,7 @@ snapshots:
       - ts-node
       - typescript
 
-  '@cprussin/eslint-config@3.0.0(@typescript-eslint/eslint-plugin@7.13.1(eslint@9.5.0)(typescript@5.5.2))(jest@29.7.0(@types/node@20.14.7)(ts-node@10.9.2(@types/node@20.14.7)(typescript@5.5.2)))(ts-node@10.9.2(@types/node@20.14.7)(typescript@5.5.2))(typescript@5.5.2)':
+  '@cprussin/eslint-config@3.0.0(@typescript-eslint/eslint-plugin@7.13.1(eslint@9.9.0(jiti@1.21.0))(typescript@5.5.4))(jest@29.7.0(@types/node@22.2.0)(ts-node@10.9.2(@types/node@22.2.0)(typescript@5.5.4)))(ts-node@10.9.2(@types/node@22.2.0)(typescript@5.5.4))(typescript@5.5.4)':
     dependencies:
       '@babel/core': 7.24.7
       '@babel/eslint-parser': 7.24.7(@babel/core@7.24.7)(eslint@9.5.0)
@@ -24487,22 +24493,22 @@ snapshots:
       eslint: 9.5.0
       eslint-config-prettier: 9.1.0(eslint@9.5.0)
       eslint-config-turbo: 1.13.4(eslint@9.5.0)
-      eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.5.4))(eslint@9.5.0)
-      eslint-plugin-jest: 28.6.0(@typescript-eslint/eslint-plugin@7.13.1(eslint@9.5.0)(typescript@5.5.2))(eslint@9.5.0)(jest@29.7.0(@types/node@20.14.7)(ts-node@10.9.2(@types/node@20.14.7)(typescript@5.5.2)))(typescript@5.5.2)
+      eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.5.2))(eslint@9.5.0)
+      eslint-plugin-jest: 28.6.0(@typescript-eslint/eslint-plugin@7.13.1(@typescript-eslint/parser@8.3.0(eslint@9.9.0(jiti@1.21.0))(typescript@5.5.4))(eslint@9.9.0(jiti@1.21.0))(typescript@5.5.4))(eslint@9.5.0)(jest@29.7.0(@types/node@22.2.0)(ts-node@10.9.2(@types/node@22.2.0)(typescript@5.5.4)))(typescript@5.5.4)
       eslint-plugin-jest-dom: 5.4.0(eslint@9.5.0)
       eslint-plugin-jsonc: 2.16.0(eslint@9.5.0)
       eslint-plugin-jsx-a11y: 6.8.0(eslint@9.5.0)
       eslint-plugin-n: 17.9.0(eslint@9.5.0)
       eslint-plugin-react: 7.34.2(eslint@9.5.0)
       eslint-plugin-react-hooks: 4.6.2(eslint@9.5.0)
-      eslint-plugin-storybook: 0.8.0(eslint@9.5.0)(typescript@5.5.2)
-      eslint-plugin-tailwindcss: 3.17.3(tailwindcss@3.4.4(ts-node@10.9.2(@types/node@20.14.7)(typescript@5.5.2)))
-      eslint-plugin-testing-library: 6.2.2(eslint@9.5.0)(typescript@5.5.2)
+      eslint-plugin-storybook: 0.8.0(eslint@9.5.0)(typescript@5.5.4)
+      eslint-plugin-tailwindcss: 3.17.3(tailwindcss@3.4.4(ts-node@10.9.2(@types/node@22.2.0)(typescript@5.5.4)))
+      eslint-plugin-testing-library: 6.2.2(eslint@9.5.0)(typescript@5.5.4)
       eslint-plugin-tsdoc: 0.3.0
       eslint-plugin-unicorn: 53.0.0(eslint@9.5.0)
       globals: 15.6.0
-      tailwindcss: 3.4.4(ts-node@10.9.2(@types/node@20.14.7)(typescript@5.5.2))
-      typescript-eslint: 7.13.1(eslint@9.5.0)(typescript@5.5.2)
+      tailwindcss: 3.4.4(ts-node@10.9.2(@types/node@22.2.0)(typescript@5.5.4))
+      typescript-eslint: 7.13.1(eslint@9.5.0)(typescript@5.5.4)
     transitivePeerDependencies:
       - '@testing-library/dom'
       - '@typescript-eslint/eslint-plugin'
@@ -34106,7 +34112,7 @@ snapshots:
   '@typescript-eslint/eslint-plugin@7.13.1(@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.5.4))(eslint@9.5.0)(typescript@5.5.4)':
     dependencies:
       '@eslint-community/regexpp': 4.10.0
-      '@typescript-eslint/parser': 7.13.1(eslint@9.9.0(jiti@1.21.0))(typescript@5.5.4)
+      '@typescript-eslint/parser': 7.13.1(eslint@9.5.0)(typescript@5.5.4)
       '@typescript-eslint/scope-manager': 7.13.1
       '@typescript-eslint/type-utils': 7.13.1(eslint@9.5.0)(typescript@5.5.4)
       '@typescript-eslint/utils': 7.13.1(eslint@9.5.0)(typescript@5.5.4)
@@ -34121,25 +34127,6 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
-  '@typescript-eslint/eslint-plugin@7.13.1(@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.5.4))(eslint@9.9.0(jiti@1.21.0))(typescript@5.5.4)':
-    dependencies:
-      '@eslint-community/regexpp': 4.10.0
-      '@typescript-eslint/parser': 7.13.1(eslint@9.9.0(jiti@1.21.0))(typescript@5.5.4)
-      '@typescript-eslint/scope-manager': 7.13.1
-      '@typescript-eslint/type-utils': 7.13.1(eslint@9.9.0(jiti@1.21.0))(typescript@5.5.4)
-      '@typescript-eslint/utils': 7.13.1(eslint@9.9.0(jiti@1.21.0))(typescript@5.5.4)
-      '@typescript-eslint/visitor-keys': 7.13.1
-      eslint: 9.9.0(jiti@1.21.0)
-      graphemer: 1.4.0
-      ignore: 5.3.1
-      natural-compare: 1.4.0
-      ts-api-utils: 1.3.0(typescript@5.5.4)
-    optionalDependencies:
-      typescript: 5.5.4
-    transitivePeerDependencies:
-      - supports-color
-    optional: true
-
   '@typescript-eslint/eslint-plugin@7.13.1(@typescript-eslint/parser@8.3.0(eslint@9.9.0(jiti@1.21.0))(typescript@5.5.4))(eslint@9.9.0(jiti@1.21.0))(typescript@5.5.4)':
     dependencies:
       '@eslint-community/regexpp': 4.10.0
@@ -34288,14 +34275,14 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
-  '@typescript-eslint/parser@7.13.1(eslint@9.9.0(jiti@1.21.0))(typescript@5.5.4)':
+  '@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.5.4)':
     dependencies:
       '@typescript-eslint/scope-manager': 7.13.1
       '@typescript-eslint/types': 7.13.1
       '@typescript-eslint/typescript-estree': 7.13.1(typescript@5.5.4)
       '@typescript-eslint/visitor-keys': 7.13.1
       debug: 4.3.5
-      eslint: 9.9.0(jiti@1.21.0)
+      eslint: 9.5.0
     optionalDependencies:
       typescript: 5.5.4
     transitivePeerDependencies:
@@ -39654,11 +39641,11 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
-  eslint-module-utils@2.8.1(@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint@9.5.0):
+  eslint-module-utils@2.8.1(@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.5.2))(eslint-import-resolver-node@0.3.9)(eslint@9.5.0):
     dependencies:
       debug: 3.2.7
     optionalDependencies:
-      '@typescript-eslint/parser': 7.13.1(eslint@9.9.0(jiti@1.21.0))(typescript@5.5.4)
+      '@typescript-eslint/parser': 7.13.1(eslint@9.5.0)(typescript@5.5.2)
       eslint: 9.5.0
       eslint-import-resolver-node: 0.3.9
     transitivePeerDependencies:
@@ -39681,7 +39668,7 @@ snapshots:
       eslint: 9.5.0
       eslint-compat-utils: 0.5.1(eslint@9.5.0)
 
-  eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.5.4))(eslint@9.5.0):
+  eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.5.2))(eslint@9.5.0):
     dependencies:
       array-includes: 3.1.8
       array.prototype.findlastindex: 1.2.5
@@ -39691,7 +39678,7 @@ snapshots:
       doctrine: 2.1.0
       eslint: 9.5.0
       eslint-import-resolver-node: 0.3.9
-      eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint@9.5.0)
+      eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.5.2))(eslint-import-resolver-node@0.3.9)(eslint@9.5.0)
       hasown: 2.0.2
       is-core-module: 2.13.1
       is-glob: 4.0.3
@@ -39702,7 +39689,7 @@ snapshots:
       semver: 6.3.1
       tsconfig-paths: 3.15.0
     optionalDependencies:
-      '@typescript-eslint/parser': 7.13.1(eslint@9.9.0(jiti@1.21.0))(typescript@5.5.4)
+      '@typescript-eslint/parser': 7.13.1(eslint@9.5.0)(typescript@5.5.2)
     transitivePeerDependencies:
       - eslint-import-resolver-typescript
       - eslint-import-resolver-webpack
@@ -39768,13 +39755,13 @@ snapshots:
       eslint: 9.5.0
       requireindex: 1.2.0
 
-  eslint-plugin-jest@28.6.0(@typescript-eslint/eslint-plugin@7.13.1(@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.5.4))(eslint@9.9.0(jiti@1.21.0))(typescript@5.5.4))(eslint@9.5.0)(jest@29.7.0(@types/node@22.2.0)(ts-node@10.9.2(@types/node@22.2.0)(typescript@5.5.4)))(typescript@5.5.4):
+  eslint-plugin-jest@28.6.0(@typescript-eslint/eslint-plugin@7.13.1(@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.5.2))(eslint@9.5.0)(typescript@5.5.2))(eslint@9.5.0)(jest@29.7.0(@types/node@20.14.7)(ts-node@10.9.2(@types/node@20.14.7)(typescript@5.5.2)))(typescript@5.5.2):
     dependencies:
-      '@typescript-eslint/utils': 7.7.1(eslint@9.5.0)(typescript@5.5.4)
+      '@typescript-eslint/utils': 7.7.1(eslint@9.5.0)(typescript@5.5.2)
       eslint: 9.5.0
     optionalDependencies:
-      '@typescript-eslint/eslint-plugin': 7.13.1(@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.5.4))(eslint@9.9.0(jiti@1.21.0))(typescript@5.5.4)
-      jest: 29.7.0(@types/node@22.2.0)(ts-node@10.9.2(@types/node@22.2.0)(typescript@5.5.4))
+      '@typescript-eslint/eslint-plugin': 7.13.1(@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.5.2))(eslint@9.5.0)(typescript@5.5.2)
+      jest: 29.7.0(@types/node@20.14.7)(ts-node@10.9.2(@types/node@20.14.7)(typescript@5.5.2))
     transitivePeerDependencies:
       - supports-color
       - typescript
@@ -39790,17 +39777,6 @@ snapshots:
       - supports-color
       - typescript
 
-  eslint-plugin-jest@28.6.0(@typescript-eslint/eslint-plugin@7.13.1(eslint@9.5.0)(typescript@5.5.2))(eslint@9.5.0)(jest@29.7.0(@types/node@20.14.7)(ts-node@10.9.2(@types/node@20.14.7)(typescript@5.5.2)))(typescript@5.5.2):
-    dependencies:
-      '@typescript-eslint/utils': 7.7.1(eslint@9.5.0)(typescript@5.5.2)
-      eslint: 9.5.0
-    optionalDependencies:
-      '@typescript-eslint/eslint-plugin': 7.13.1(@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.5.2))(eslint@9.5.0)(typescript@5.5.2)
-      jest: 29.7.0(@types/node@20.14.7)(ts-node@10.9.2(@types/node@20.14.7)(typescript@5.5.2))
-    transitivePeerDependencies:
-      - supports-color
-      - typescript
-
   eslint-plugin-jsonc@2.16.0(eslint@9.5.0):
     dependencies:
       '@eslint-community/eslint-utils': 4.4.0(eslint@9.5.0)
@@ -51039,7 +51015,7 @@ snapshots:
   typescript-eslint@7.13.1(eslint@9.5.0)(typescript@5.5.4):
     dependencies:
       '@typescript-eslint/eslint-plugin': 7.13.1(@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.5.4))(eslint@9.5.0)(typescript@5.5.4)
-      '@typescript-eslint/parser': 7.13.1(eslint@9.9.0(jiti@1.21.0))(typescript@5.5.4)
+      '@typescript-eslint/parser': 7.13.1(eslint@9.5.0)(typescript@5.5.4)
       '@typescript-eslint/utils': 7.13.1(eslint@9.5.0)(typescript@5.5.4)
       eslint: 9.5.0
     optionalDependencies: