From 155aac9cc338811c723cd8c36a0b4c76a7d3417b Mon Sep 17 00:00:00 2001 From: 0xkenj1 <165053496+0xkenj1@users.noreply.github.com> Date: Thu, 22 Aug 2024 18:25:08 -0300 Subject: [PATCH] refactor: replace Service with Provider (#53) ## Description - replace `Service` class names with `Provider` where correspond --- README.md | 2 +- apps/api/package.json | 2 +- apps/api/src/index.ts | 8 +- .../package.json | 2 +- .../src/exceptions/dataDecode.exception.ts | 0 .../src/exceptions/index.ts | 0 .../exceptions/invalidArgument.exception.ts | 0 .../exceptions/multicallNotFound.exception.ts | 0 .../src/exceptions/rpcUrlsEmpty.exception.ts | 0 .../src/external.ts | 2 +- .../src/fixtures/batchRequest.fixture.ts | 0 .../src/index.ts | 0 .../src/internal.ts | 0 .../src/providers/evmProvider.service.ts | 2 +- .../src/providers/index.ts | 0 .../src/providers/zkChainProvider.service.ts | 4 +- .../src/types/index.ts | 0 .../src/types/viem.types.ts | 0 .../providers/evmProvider.service.spec.ts | 42 ++-- .../providers/zkChainProvider.service.spec.ts | 22 +-- .../tsconfig.build.json | 0 .../tsconfig.json | 0 .../vitest.config.ts | 0 packages/metadata/src/external.ts | 4 +- .../src/interfaces/metadata.interface.ts | 2 +- packages/metadata/src/internal.ts | 2 +- .../githubMetadata.provider.ts} | 4 +- packages/metadata/src/providers/index.ts | 2 + .../staticMetadata.provider.ts} | 4 +- packages/metadata/src/services/index.ts | 2 - .../services/staticMetadata.service.spec.ts | 8 +- packages/metrics/package.json | 2 +- packages/metrics/src/l1/l1MetricsService.ts | 8 +- .../test/unit/l1/l1MetricsService.spec.ts | 180 ++++++++---------- packages/pricing/src/external.ts | 4 +- .../src/interfaces/pricing.interface.ts | 2 +- packages/pricing/src/internal.ts | 2 +- .../coingecko.provider.ts} | 4 +- packages/pricing/src/providers/index.ts | 1 + packages/pricing/src/services/index.ts | 1 - .../unit/services/coingecko.service.spec.ts | 6 +- pnpm-lock.yaml | 36 ++-- 42 files changed, 170 insertions(+), 190 deletions(-) rename packages/{providers => chain-providers}/package.json (94%) rename packages/{providers => chain-providers}/src/exceptions/dataDecode.exception.ts (100%) rename packages/{providers => chain-providers}/src/exceptions/index.ts (100%) rename packages/{providers => chain-providers}/src/exceptions/invalidArgument.exception.ts (100%) rename packages/{providers => chain-providers}/src/exceptions/multicallNotFound.exception.ts (100%) rename packages/{providers => chain-providers}/src/exceptions/rpcUrlsEmpty.exception.ts (100%) rename packages/{providers => chain-providers}/src/external.ts (63%) rename packages/{providers => chain-providers}/src/fixtures/batchRequest.fixture.ts (100%) rename packages/{providers => chain-providers}/src/index.ts (100%) rename packages/{providers => chain-providers}/src/internal.ts (100%) rename packages/{providers => chain-providers}/src/providers/evmProvider.service.ts (99%) rename packages/{providers => chain-providers}/src/providers/index.ts (100%) rename packages/{providers => chain-providers}/src/providers/zkChainProvider.service.ts (95%) rename packages/{providers => chain-providers}/src/types/index.ts (100%) rename packages/{providers => chain-providers}/src/types/viem.types.ts (100%) rename packages/{providers => chain-providers}/test/unit/providers/evmProvider.service.spec.ts (87%) rename packages/{providers => chain-providers}/test/unit/providers/zkChainProvider.service.spec.ts (87%) rename packages/{providers => chain-providers}/tsconfig.build.json (100%) rename packages/{providers => chain-providers}/tsconfig.json (100%) rename packages/{providers => chain-providers}/vitest.config.ts (100%) rename packages/metadata/src/{services/githubMetadata.service.ts => providers/githubMetadata.provider.ts} (75%) create mode 100644 packages/metadata/src/providers/index.ts rename packages/metadata/src/{services/staticMetadata.service.ts => providers/staticMetadata.provider.ts} (71%) delete mode 100644 packages/metadata/src/services/index.ts rename packages/pricing/src/{services/coingecko.service.ts => providers/coingecko.provider.ts} (97%) create mode 100644 packages/pricing/src/providers/index.ts delete mode 100644 packages/pricing/src/services/index.ts diff --git a/README.md b/README.md index 0e645ba..7b72213 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ You can fetch metrics from the ZKsync ecosystem and ZK chains from L1 RPC (Ether This repository is a monorepo consisting of 4 packages and 1 app: - [`@zkchainhub/shared`](./packages/shared): A library for shared configurations, constants, types, etc. -- [`@zkchainhub/providers`](./packages/providers): A library that provides abstracted services over Viem providers to query blockchain data +- [`@zkchainhub/chain-providers`](./packages/chain-providers): A library that provides abstracted services over Viem providers to query blockchain data - [`@zkchainhub/pricing`](./packages/pricing): An extensible library that provides Pricing services to fetch token prices. Currently, only Coingecko provider is developed - [`@zkchainhub/metrics`](./packages/metrics): A library that provides different aggregated metrics from the ZKsync ecosystem and ZK chains. - [`@zkchainhub/api`](./apps/api): An Express server that exposes an API where you can fetch information about ZKsync ecosystem and their chains, using the before mentioned libraries diff --git a/apps/api/package.json b/apps/api/package.json index 2f56dc6..08bc78e 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -19,7 +19,7 @@ "dependencies": { "@zkchainhub/metrics": "workspace:*", "@zkchainhub/pricing": "workspace:*", - "@zkchainhub/providers": "workspace:*", + "@zkchainhub/chain-providers": "workspace:*", "@zkchainhub/shared": "workspace:*", "bignumber.js": "9.1.2", "cache-manager": "5.7.6", diff --git a/apps/api/src/index.ts b/apps/api/src/index.ts index 22a04ab..32b0a2c 100644 --- a/apps/api/src/index.ts +++ b/apps/api/src/index.ts @@ -2,10 +2,10 @@ import { inspect } from "util"; import { caching } from "cache-manager"; import { L1MetricsService } from "@zkchainhub/metrics"; -import { CoingeckoService } from "@zkchainhub/pricing"; -import { EvmProviderService } from "@zkchainhub/providers"; +import { CoingeckoProvider } from "@zkchainhub/pricing"; import { Logger } from "@zkchainhub/shared"; +import { EvmProvider } from "../../../packages/chain-providers/dist/src/index.js"; import { App } from "./app.js"; import { config } from "./common/config/index.js"; import { MetricsController, MetricsRouter } from "./metrics/index.js"; @@ -18,8 +18,8 @@ const main = async (): Promise => { ttl: config.pricing.cacheOptions.ttl * 1000 /*milliseconds*/, }); - const evmProvider = new EvmProviderService(config.l1.rpcUrls, config.l1.chain, logger); - const pricingProvider = new CoingeckoService( + const evmProvider = new EvmProvider(config.l1.rpcUrls, config.l1.chain, logger); + const pricingProvider = new CoingeckoProvider( { apiBaseUrl: config.pricing.pricingOptions.apiBaseUrl, apiKey: config.pricing.pricingOptions.apiKey, diff --git a/packages/providers/package.json b/packages/chain-providers/package.json similarity index 94% rename from packages/providers/package.json rename to packages/chain-providers/package.json index 0c6449e..2582727 100644 --- a/packages/providers/package.json +++ b/packages/chain-providers/package.json @@ -1,5 +1,5 @@ { - "name": "@zkchainhub/providers", + "name": "@zkchainhub/chain-providers", "version": "1.0.0", "main": "./dist/src/index.js", "type": "module", diff --git a/packages/providers/src/exceptions/dataDecode.exception.ts b/packages/chain-providers/src/exceptions/dataDecode.exception.ts similarity index 100% rename from packages/providers/src/exceptions/dataDecode.exception.ts rename to packages/chain-providers/src/exceptions/dataDecode.exception.ts diff --git a/packages/providers/src/exceptions/index.ts b/packages/chain-providers/src/exceptions/index.ts similarity index 100% rename from packages/providers/src/exceptions/index.ts rename to packages/chain-providers/src/exceptions/index.ts diff --git a/packages/providers/src/exceptions/invalidArgument.exception.ts b/packages/chain-providers/src/exceptions/invalidArgument.exception.ts similarity index 100% rename from packages/providers/src/exceptions/invalidArgument.exception.ts rename to packages/chain-providers/src/exceptions/invalidArgument.exception.ts diff --git a/packages/providers/src/exceptions/multicallNotFound.exception.ts b/packages/chain-providers/src/exceptions/multicallNotFound.exception.ts similarity index 100% rename from packages/providers/src/exceptions/multicallNotFound.exception.ts rename to packages/chain-providers/src/exceptions/multicallNotFound.exception.ts diff --git a/packages/providers/src/exceptions/rpcUrlsEmpty.exception.ts b/packages/chain-providers/src/exceptions/rpcUrlsEmpty.exception.ts similarity index 100% rename from packages/providers/src/exceptions/rpcUrlsEmpty.exception.ts rename to packages/chain-providers/src/exceptions/rpcUrlsEmpty.exception.ts diff --git a/packages/providers/src/external.ts b/packages/chain-providers/src/external.ts similarity index 63% rename from packages/providers/src/external.ts rename to packages/chain-providers/src/external.ts index 3f3ddee..3bb2392 100644 --- a/packages/providers/src/external.ts +++ b/packages/chain-providers/src/external.ts @@ -5,4 +5,4 @@ export { RpcUrlsEmpty, } from "./internal.js"; -export { EvmProviderService, ZKChainProviderService } from "./internal.js"; +export { EvmProvider, ZKChainProvider } from "./internal.js"; diff --git a/packages/providers/src/fixtures/batchRequest.fixture.ts b/packages/chain-providers/src/fixtures/batchRequest.fixture.ts similarity index 100% rename from packages/providers/src/fixtures/batchRequest.fixture.ts rename to packages/chain-providers/src/fixtures/batchRequest.fixture.ts diff --git a/packages/providers/src/index.ts b/packages/chain-providers/src/index.ts similarity index 100% rename from packages/providers/src/index.ts rename to packages/chain-providers/src/index.ts diff --git a/packages/providers/src/internal.ts b/packages/chain-providers/src/internal.ts similarity index 100% rename from packages/providers/src/internal.ts rename to packages/chain-providers/src/internal.ts diff --git a/packages/providers/src/providers/evmProvider.service.ts b/packages/chain-providers/src/providers/evmProvider.service.ts similarity index 99% rename from packages/providers/src/providers/evmProvider.service.ts rename to packages/chain-providers/src/providers/evmProvider.service.ts index 5ee9f70..74dad52 100644 --- a/packages/providers/src/providers/evmProvider.service.ts +++ b/packages/chain-providers/src/providers/evmProvider.service.ts @@ -37,7 +37,7 @@ import { /** * Acts as a wrapper around Viem library to provide methods to interact with an EVM-based blockchain. */ -export class EvmProviderService { +export class EvmProvider { private client: ReturnType< typeof createPublicClient, Chain> >; diff --git a/packages/providers/src/providers/index.ts b/packages/chain-providers/src/providers/index.ts similarity index 100% rename from packages/providers/src/providers/index.ts rename to packages/chain-providers/src/providers/index.ts diff --git a/packages/providers/src/providers/zkChainProvider.service.ts b/packages/chain-providers/src/providers/zkChainProvider.service.ts similarity index 95% rename from packages/providers/src/providers/zkChainProvider.service.ts rename to packages/chain-providers/src/providers/zkChainProvider.service.ts index 0ae5229..1392f34 100644 --- a/packages/providers/src/providers/zkChainProvider.service.ts +++ b/packages/chain-providers/src/providers/zkChainProvider.service.ts @@ -12,12 +12,12 @@ import { GetL1BatchDetailsReturnType, PublicActionsL2, publicActionsL2 } from "v import { ILogger } from "@zkchainhub/shared"; import { InvalidArgumentException } from "../internal.js"; -import { EvmProviderService } from "./evmProvider.service.js"; +import { EvmProvider } from "./evmProvider.service.js"; /** * Acts as a wrapper around Viem library to provide methods to interact with ZK chains. */ -export class ZKChainProviderService extends EvmProviderService { +export class ZKChainProvider extends EvmProvider { private zkClient: Client< FallbackTransport, Chain, diff --git a/packages/providers/src/types/index.ts b/packages/chain-providers/src/types/index.ts similarity index 100% rename from packages/providers/src/types/index.ts rename to packages/chain-providers/src/types/index.ts diff --git a/packages/providers/src/types/viem.types.ts b/packages/chain-providers/src/types/viem.types.ts similarity index 100% rename from packages/providers/src/types/viem.types.ts rename to packages/chain-providers/src/types/viem.types.ts diff --git a/packages/providers/test/unit/providers/evmProvider.service.spec.ts b/packages/chain-providers/test/unit/providers/evmProvider.service.spec.ts similarity index 87% rename from packages/providers/test/unit/providers/evmProvider.service.spec.ts rename to packages/chain-providers/test/unit/providers/evmProvider.service.spec.ts index 4474484..681b540 100644 --- a/packages/providers/test/unit/providers/evmProvider.service.spec.ts +++ b/packages/chain-providers/test/unit/providers/evmProvider.service.spec.ts @@ -8,7 +8,7 @@ import { ILogger } from "@zkchainhub/shared"; import { arrayAbiFixture, structAbiFixture } from "../../../src/fixtures/batchRequest.fixture.js"; import { DataDecodeException, - EvmProviderService, + EvmProvider, MulticallNotFound, RpcUrlsEmpty, } from "../../../src/internal.js"; @@ -45,8 +45,8 @@ const testAbi = parseAbi([ "function tokenURI(uint256 tokenId) pure returns (string)", ]); -describe("EvmProviderService", () => { - let viemProvider: EvmProviderService | null = null; +describe("EvmProvider", () => { + let viemProvider: EvmProvider | null = null; const defaultMockChain: viem.Chain = vi.mocked({ ...localhost, contracts: { multicall3: undefined }, @@ -60,19 +60,19 @@ describe("EvmProviderService", () => { }); it("has a client property defined", () => { - viemProvider = new EvmProviderService(defaultRpcUrls, defaultMockChain, mockLogger); + viemProvider = new EvmProvider(defaultRpcUrls, defaultMockChain, mockLogger); expect(viemProvider["client"]).toBeDefined(); }); it("throws RpcUrlsEmpty error if rpcUrls is empty", () => { expect(() => { - new EvmProviderService([], defaultMockChain, mockLogger); + new EvmProvider([], defaultMockChain, mockLogger); }).toThrowError(RpcUrlsEmpty); }); describe("getBalance", () => { it("should return the balance of the specified address", async () => { - viemProvider = new EvmProviderService(defaultRpcUrls, defaultMockChain, mockLogger); + viemProvider = new EvmProvider(defaultRpcUrls, defaultMockChain, mockLogger); const address = "0x123456789"; const expectedBalance = 100n; vi.spyOn(mockClient, "getBalance").mockResolvedValue(expectedBalance); @@ -86,7 +86,7 @@ describe("EvmProviderService", () => { describe("getBlockNumber", () => { it("should return the current block number", async () => { - viemProvider = new EvmProviderService(defaultRpcUrls, defaultMockChain, mockLogger); + viemProvider = new EvmProvider(defaultRpcUrls, defaultMockChain, mockLogger); const expectedBlockNumber = 1000n; vi.spyOn(mockClient, "getBlockNumber").mockResolvedValue(expectedBlockNumber); @@ -98,7 +98,7 @@ describe("EvmProviderService", () => { describe("getGasPrice", () => { it("should return the current gas price", async () => { - viemProvider = new EvmProviderService(defaultRpcUrls, defaultMockChain, mockLogger); + viemProvider = new EvmProvider(defaultRpcUrls, defaultMockChain, mockLogger); const expectedGasPrice = BigInt(100); // Mock the getGasPrice method of the Viem client vi.spyOn(mockClient, "getGasPrice").mockResolvedValue(expectedGasPrice); @@ -111,7 +111,7 @@ describe("EvmProviderService", () => { describe("estimateGas", () => { it("return the estimated gas for the given transaction", async () => { - viemProvider = new EvmProviderService(defaultRpcUrls, defaultMockChain, mockLogger); + viemProvider = new EvmProvider(defaultRpcUrls, defaultMockChain, mockLogger); const args = vi.mocked>({ account: "0xffff", to: viem.zeroAddress, @@ -130,7 +130,7 @@ describe("EvmProviderService", () => { describe("getStorageAt", () => { it("should return the value of the storage slot at the given address and slot number", async () => { - viemProvider = new EvmProviderService(defaultRpcUrls, defaultMockChain, mockLogger); + viemProvider = new EvmProvider(defaultRpcUrls, defaultMockChain, mockLogger); const address = "0x123456789"; const slot = 1; const expectedValue = "0xabcdef"; @@ -143,7 +143,7 @@ describe("EvmProviderService", () => { }); it("should return the value of the storage slot at the given address and slot value", async () => { - viemProvider = new EvmProviderService(defaultRpcUrls, defaultMockChain, mockLogger); + viemProvider = new EvmProvider(defaultRpcUrls, defaultMockChain, mockLogger); const address = "0x123456789"; const slot = "0x12"; const expectedValue = "0xabcdef"; @@ -156,7 +156,7 @@ describe("EvmProviderService", () => { }); it("should throw an error if the slot is not a positive integer", async () => { - viemProvider = new EvmProviderService(defaultRpcUrls, defaultMockChain, mockLogger); + viemProvider = new EvmProvider(defaultRpcUrls, defaultMockChain, mockLogger); const address = "0x123456789"; const slot = -1; @@ -168,7 +168,7 @@ describe("EvmProviderService", () => { describe("readContract", () => { it("should call the readContract method of the Viem client with the correct arguments", async () => { - viemProvider = new EvmProviderService(defaultRpcUrls, defaultMockChain, mockLogger); + viemProvider = new EvmProvider(defaultRpcUrls, defaultMockChain, mockLogger); const contractAddress = "0x123456789"; const abi = testAbi; const functionName = "balanceOf"; @@ -188,7 +188,7 @@ describe("EvmProviderService", () => { }); it("should call the readContract method of the Viem client with the correct arguments when args are provided", async () => { - viemProvider = new EvmProviderService(defaultRpcUrls, defaultMockChain, mockLogger); + viemProvider = new EvmProvider(defaultRpcUrls, defaultMockChain, mockLogger); const contractAddress = "0x123456789"; const functionName = "tokenURI"; const args = [1n] as const; @@ -216,7 +216,7 @@ describe("EvmProviderService", () => { describe("batchRequest", () => { it("should properly encode bytecode data and decode return data from batch request call", async () => { - viemProvider = new EvmProviderService(defaultRpcUrls, defaultMockChain, mockLogger); + viemProvider = new EvmProvider(defaultRpcUrls, defaultMockChain, mockLogger); const returnAbiParams = viem.parseAbiParameters([ "TokenData[] returnData", "struct TokenData { uint8 tokenDecimals; string tokenSymbol; string tokenName; }", @@ -245,7 +245,7 @@ describe("EvmProviderService", () => { }); it("should fail if no data is returned", async () => { - viemProvider = new EvmProviderService(defaultRpcUrls, defaultMockChain, mockLogger); + viemProvider = new EvmProvider(defaultRpcUrls, defaultMockChain, mockLogger); const returnAbiParams = viem.parseAbiParameters([ "TokenData[] returnData", "struct TokenData { uint8 tokenDecimals; string tokenSymbol; string tokenName; }", @@ -264,7 +264,7 @@ describe("EvmProviderService", () => { }); it("should fail if decoded data does not match validator (missing struct fields)", async () => { - viemProvider = new EvmProviderService(defaultRpcUrls, defaultMockChain, mockLogger); + viemProvider = new EvmProvider(defaultRpcUrls, defaultMockChain, mockLogger); // this schema is incorrect, it should have 3 fields instead of 2 const returnAbiParams = viem.parseAbiParameters([ "WrongTokenData[] returnData", @@ -286,7 +286,7 @@ describe("EvmProviderService", () => { }); it("should fail if decoded data does not match validator (not struct vs struct)", async () => { - viemProvider = new EvmProviderService(defaultRpcUrls, defaultMockChain, mockLogger); + viemProvider = new EvmProvider(defaultRpcUrls, defaultMockChain, mockLogger); // this schema is incorrect, it should have 3 fields instead of 2 const returnAbiParams = viem.parseAbiParameters("uint8 decimals, address[] owners"); @@ -305,7 +305,7 @@ describe("EvmProviderService", () => { }); it("should properly decode address[]", async () => { - viemProvider = new EvmProviderService(defaultRpcUrls, defaultMockChain, mockLogger); + viemProvider = new EvmProvider(defaultRpcUrls, defaultMockChain, mockLogger); const returnAbiParams = viem.parseAbiParameters("address[]"); vi.spyOn(mockClient, "call").mockResolvedValue({ data: arrayAbiFixture.returnData }); @@ -327,7 +327,7 @@ describe("EvmProviderService", () => { contracts: { multicall3: { address: "0x123456789" } }, }); - viemProvider = new EvmProviderService(defaultRpcUrls, mockChain, mockLogger); + viemProvider = new EvmProvider(defaultRpcUrls, mockChain, mockLogger); const contracts = [ { address: "0x123456789", @@ -363,7 +363,7 @@ describe("EvmProviderService", () => { }); it("throws a MulticallNotFound error if the Multicall contract is not found for the chain", async () => { - viemProvider = new EvmProviderService(defaultRpcUrls, defaultMockChain, mockLogger); + viemProvider = new EvmProvider(defaultRpcUrls, defaultMockChain, mockLogger); const contracts = [ { address: "0x123456789", diff --git a/packages/providers/test/unit/providers/zkChainProvider.service.spec.ts b/packages/chain-providers/test/unit/providers/zkChainProvider.service.spec.ts similarity index 87% rename from packages/providers/test/unit/providers/zkChainProvider.service.spec.ts rename to packages/chain-providers/test/unit/providers/zkChainProvider.service.spec.ts index f64b260..0420adc 100644 --- a/packages/providers/test/unit/providers/zkChainProvider.service.spec.ts +++ b/packages/chain-providers/test/unit/providers/zkChainProvider.service.spec.ts @@ -5,11 +5,7 @@ import { afterEach, describe, expect, it, vi } from "vitest"; import { ILogger } from "@zkchainhub/shared"; -import { - InvalidArgumentException, - RpcUrlsEmpty, - ZKChainProviderService, -} from "../../../src/internal.js"; +import { InvalidArgumentException, RpcUrlsEmpty, ZKChainProvider } from "../../../src/internal.js"; export const mockLogger: ILogger = { info: vi.fn(), @@ -18,8 +14,8 @@ export const mockLogger: ILogger = { debug: vi.fn(), }; -describe("ZKChainProviderService", () => { - let zkProvider: ZKChainProviderService; +describe("ZKChainProvider", () => { + let zkProvider: ZKChainProvider; const defaultMockChain = localhost; const defaultRpcUrls = ["http://localhost:8545"]; @@ -28,19 +24,19 @@ describe("ZKChainProviderService", () => { }); it("has a zkclient property defined", () => { - zkProvider = new ZKChainProviderService(defaultRpcUrls, defaultMockChain, mockLogger); + zkProvider = new ZKChainProvider(defaultRpcUrls, defaultMockChain, mockLogger); expect(zkProvider["zkClient"]).toBeDefined(); }); it("throws RpcUrlsEmpty error if rpcUrls is empty", () => { expect(() => { - new ZKChainProviderService([], localhost, mockLogger); + new ZKChainProvider([], localhost, mockLogger); }).toThrowError(RpcUrlsEmpty); }); describe("avgBlockTime", () => { it("should return the average block time over the given range", async () => { - zkProvider = new ZKChainProviderService(defaultRpcUrls, defaultMockChain, mockLogger); + zkProvider = new ZKChainProvider(defaultRpcUrls, defaultMockChain, mockLogger); const currentBlockNumber = 1000; const range = 100; const currentBlockTimestamp = { timestamp: BigInt(123234345) }; @@ -68,7 +64,7 @@ describe("ZKChainProviderService", () => { }); it("should throw an InvalidArgumentException if the range is less than 1", async () => { - zkProvider = new ZKChainProviderService(defaultRpcUrls, defaultMockChain, mockLogger); + zkProvider = new ZKChainProvider(defaultRpcUrls, defaultMockChain, mockLogger); await expect(zkProvider.avgBlockTime(0)).rejects.toThrowError( new InvalidArgumentException("range for avgBlockTime should be >= 1"), ); @@ -77,7 +73,7 @@ describe("ZKChainProviderService", () => { describe("tps", () => { it("should return the transactions per second (TPS)", async () => { - zkProvider = new ZKChainProviderService(defaultRpcUrls, defaultMockChain, mockLogger); + zkProvider = new ZKChainProvider(defaultRpcUrls, defaultMockChain, mockLogger); const currentBatchNumber = 1000; // 1000 in hexadecimal const currentBatchDetails = { l2TxCount: 200, timestamp: 123234345 }; const prevBatchDetails = { timestamp: 123123123 }; @@ -103,7 +99,7 @@ describe("ZKChainProviderService", () => { }); it("should handle the case when there are no transactions", async () => { - zkProvider = new ZKChainProviderService(defaultRpcUrls, defaultMockChain, mockLogger); + zkProvider = new ZKChainProvider(defaultRpcUrls, defaultMockChain, mockLogger); const currentBatchNumber = 1000; // 1000 in hexadecimal const currentBatchDetails = { l2TxCount: 0, timestamp: 123234345 }; const prevBatchDetails = { timestamp: 123123123 }; diff --git a/packages/providers/tsconfig.build.json b/packages/chain-providers/tsconfig.build.json similarity index 100% rename from packages/providers/tsconfig.build.json rename to packages/chain-providers/tsconfig.build.json diff --git a/packages/providers/tsconfig.json b/packages/chain-providers/tsconfig.json similarity index 100% rename from packages/providers/tsconfig.json rename to packages/chain-providers/tsconfig.json diff --git a/packages/providers/vitest.config.ts b/packages/chain-providers/vitest.config.ts similarity index 100% rename from packages/providers/vitest.config.ts rename to packages/chain-providers/vitest.config.ts diff --git a/packages/metadata/src/external.ts b/packages/metadata/src/external.ts index d309d41..3c84672 100644 --- a/packages/metadata/src/external.ts +++ b/packages/metadata/src/external.ts @@ -1,3 +1,3 @@ -export type { IMetadataService } from "./internal.js"; +export type { IMetadataProvider } from "./internal.js"; -export { StaticMetadataService, GithubMetadataService } from "./internal.js"; +export { StaticMetadataProvider, GithubMetadataProvider } from "./internal.js"; diff --git a/packages/metadata/src/interfaces/metadata.interface.ts b/packages/metadata/src/interfaces/metadata.interface.ts index c1eccea..1313b14 100644 --- a/packages/metadata/src/interfaces/metadata.interface.ts +++ b/packages/metadata/src/interfaces/metadata.interface.ts @@ -1,6 +1,6 @@ import { Token, TokenType, ZKChainMetadata } from "@zkchainhub/shared"; -export interface IMetadataService { +export interface IMetadataProvider { getChainsMetadata(): Promise; getTokensMetadata(): Promise[]>; } diff --git a/packages/metadata/src/internal.ts b/packages/metadata/src/internal.ts index 08c7612..2c8a6ce 100644 --- a/packages/metadata/src/internal.ts +++ b/packages/metadata/src/internal.ts @@ -1,2 +1,2 @@ export * from "./interfaces/index.js"; -export * from "./services/index.js"; +export * from "./providers/index.js"; diff --git a/packages/metadata/src/services/githubMetadata.service.ts b/packages/metadata/src/providers/githubMetadata.provider.ts similarity index 75% rename from packages/metadata/src/services/githubMetadata.service.ts rename to packages/metadata/src/providers/githubMetadata.provider.ts index 1c11e26..427f04e 100644 --- a/packages/metadata/src/services/githubMetadata.service.ts +++ b/packages/metadata/src/providers/githubMetadata.provider.ts @@ -1,8 +1,8 @@ import { Token, TokenType, ZKChainMetadata } from "@zkchainhub/shared"; -import { IMetadataService } from "../interfaces/index.js"; +import { IMetadataProvider } from "../interfaces/index.js"; -export class GithubMetadataService implements IMetadataService { +export class GithubMetadataProvider implements IMetadataProvider { async getChainsMetadata(): Promise { //TODO: Implement this method throw new Error("Method not implemented."); diff --git a/packages/metadata/src/providers/index.ts b/packages/metadata/src/providers/index.ts new file mode 100644 index 0000000..7011ce4 --- /dev/null +++ b/packages/metadata/src/providers/index.ts @@ -0,0 +1,2 @@ +export * from "./githubMetadata.provider.js"; +export * from "./staticMetadata.provider.js"; diff --git a/packages/metadata/src/services/staticMetadata.service.ts b/packages/metadata/src/providers/staticMetadata.provider.ts similarity index 71% rename from packages/metadata/src/services/staticMetadata.service.ts rename to packages/metadata/src/providers/staticMetadata.provider.ts index 7414c03..39b08c4 100644 --- a/packages/metadata/src/services/staticMetadata.service.ts +++ b/packages/metadata/src/providers/staticMetadata.provider.ts @@ -1,8 +1,8 @@ import { Token, tokens, TokenType, ZKChainMetadata, zkChainsMetadata } from "@zkchainhub/shared"; -import { IMetadataService } from "../interfaces/index.js"; +import { IMetadataProvider } from "../interfaces/index.js"; -export class StaticMetadataService implements IMetadataService { +export class StaticMetadataProvider implements IMetadataProvider { async getChainsMetadata(): Promise { return structuredClone(zkChainsMetadata); } diff --git a/packages/metadata/src/services/index.ts b/packages/metadata/src/services/index.ts deleted file mode 100644 index b5d1470..0000000 --- a/packages/metadata/src/services/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./githubMetadata.service.js"; -export * from "./staticMetadata.service.js"; diff --git a/packages/metadata/test/unit/services/staticMetadata.service.spec.ts b/packages/metadata/test/unit/services/staticMetadata.service.spec.ts index 0a5c632..1fa7f0e 100644 --- a/packages/metadata/test/unit/services/staticMetadata.service.spec.ts +++ b/packages/metadata/test/unit/services/staticMetadata.service.spec.ts @@ -2,13 +2,13 @@ import { beforeEach, describe, expect, expectTypeOf, it } from "vitest"; import { Token, TokenType, ZKChainMetadata } from "@zkchainhub/shared"; -import { StaticMetadataService } from "../../../src/internal.js"; +import { StaticMetadataProvider } from "../../../src/internal.js"; -describe("StaticMetadataService", () => { - let metadataService: StaticMetadataService; +describe("StaticMetadataProvider", () => { + let metadataService: StaticMetadataProvider; beforeEach(() => { - metadataService = new StaticMetadataService(); + metadataService = new StaticMetadataProvider(); }); describe("getChainsMetadata", () => { diff --git a/packages/metrics/package.json b/packages/metrics/package.json index 77e81cb..d4200d0 100644 --- a/packages/metrics/package.json +++ b/packages/metrics/package.json @@ -18,7 +18,7 @@ "dependencies": { "@zkchainhub/shared": "workspace:*", "@zkchainhub/pricing": "workspace:*", - "@zkchainhub/providers": "workspace:*", + "@zkchainhub/chain-providers": "workspace:*", "viem": "2.19.6" } } diff --git a/packages/metrics/src/l1/l1MetricsService.ts b/packages/metrics/src/l1/l1MetricsService.ts index fec2bcf..d867a32 100644 --- a/packages/metrics/src/l1/l1MetricsService.ts +++ b/packages/metrics/src/l1/l1MetricsService.ts @@ -11,8 +11,7 @@ import { zeroAddress, } from "viem"; -import { IPricingService } from "@zkchainhub/pricing"; -import { EvmProviderService } from "@zkchainhub/providers"; +import { IPricingProvider } from "@zkchainhub/pricing"; import { BatchesInfo, ChainId, @@ -28,6 +27,7 @@ import { WETH, } from "@zkchainhub/shared"; +import { EvmProvider } from "../../../chain-providers/dist/src/index.js"; import { AssetTvl, bridgeHubAbi, @@ -56,8 +56,8 @@ export class L1MetricsService { private readonly bridgeHubAddress: Address, private readonly sharedBridgeAddress: Address, private readonly stateTransitionManagerAddresses: Address[], - private readonly evmProviderService: EvmProviderService, - private readonly pricingService: IPricingService, + private readonly evmProviderService: EvmProvider, + private readonly pricingService: IPricingProvider, private readonly logger: ILogger, ) {} diff --git a/packages/metrics/test/unit/l1/l1MetricsService.spec.ts b/packages/metrics/test/unit/l1/l1MetricsService.spec.ts index 90615f5..1ae4965 100644 --- a/packages/metrics/test/unit/l1/l1MetricsService.spec.ts +++ b/packages/metrics/test/unit/l1/l1MetricsService.spec.ts @@ -1,8 +1,7 @@ import { Address, encodeFunctionData, erc20Abi, parseEther, zeroAddress } from "viem"; import { afterEach, describe, expect, it, Mocked, vi } from "vitest"; -import { IPricingService } from "@zkchainhub/pricing"; -import { EvmProviderService, MulticallNotFound } from "@zkchainhub/providers"; +import { IPricingProvider } from "@zkchainhub/pricing"; import { BatchesInfo, ChainId, @@ -16,6 +15,7 @@ import { WETH, } from "@zkchainhub/shared"; +import { EvmProvider, MulticallNotFound } from "../../../../chain-providers/dist/src/index.js"; import { bridgeHubAbi, diamondProxyAbi, @@ -97,7 +97,7 @@ const mockMetricsModule = ( mockedSharedBridgeAddress: Address, mockedSTMAddresses: Address[], ) => { - const evmProviderService = { + const evmProvider = { getBlockNumber: vi.fn(), estimateGas: vi.fn(), getGasPrice: vi.fn(), @@ -108,8 +108,8 @@ const mockMetricsModule = ( getStorageAt: vi.fn(), getBlockByNumber: vi.fn(), batchRequest: vi.fn(), - } as unknown as EvmProviderService; - const pricingService: Mocked = { + } as unknown as EvmProvider; + const pricingService: Mocked = { getTokenPrices: vi.fn(), }; @@ -123,12 +123,12 @@ const mockMetricsModule = ( mockedBridgeHubAddress, mockedSharedBridgeAddress, mockedSTMAddresses, - evmProviderService as EvmProviderService, + evmProvider as EvmProvider, pricingService, mockLogger, ); - return { l1Metrics, pricingService, evmProviderService }; + return { l1Metrics, pricingService, evmProvider }; }; describe("l1Metrics", () => { @@ -167,7 +167,7 @@ describe("l1Metrics", () => { describe("l1Tvl", () => { it("return the TVL on L1 Shared Bridge", async () => { - const { l1Metrics, evmProviderService, pricingService } = mockMetricsModule( + const { l1Metrics, evmProvider, pricingService } = mockMetricsModule( mockedBridgeHubAddress, mockedSharedBridgeAddress, mockedSTMAddresses, @@ -180,8 +180,8 @@ describe("l1Metrics", () => { const mockPrices = { "wrapped-bitcoin": 66_129, "usd-coin": 0.999, ethereum: 3_181.09 }; // Mocked prices const multicallAddress = "0x123452"; - vi.spyOn(evmProviderService, "getMulticall3Address").mockReturnValue(multicallAddress); - vi.spyOn(evmProviderService, "multicall").mockResolvedValue(mockMulticallBalances); + vi.spyOn(evmProvider, "getMulticall3Address").mockReturnValue(multicallAddress); + vi.spyOn(evmProvider, "multicall").mockResolvedValue(mockMulticallBalances); vi.spyOn(pricingService, "getTokenPrices").mockResolvedValue(mockPrices); const result = await l1Metrics.l1Tvl(); @@ -225,7 +225,7 @@ describe("l1Metrics", () => { decimals: 8, }, ]); - expect(evmProviderService.multicall).toHaveBeenCalledWith({ + expect(evmProvider.multicall).toHaveBeenCalledWith({ contracts: [ { address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", @@ -253,25 +253,23 @@ describe("l1Metrics", () => { "usd-coin", "wrapped-bitcoin", ]); - expect(evmProviderService.getBalance).not.toHaveBeenCalled(); + expect(evmProvider.getBalance).not.toHaveBeenCalled(); }); it("return the TVL on L1 Shared Bridge without multicall", async () => { - const { l1Metrics, evmProviderService, pricingService } = mockMetricsModule( + const { l1Metrics, evmProvider, pricingService } = mockMetricsModule( mockedBridgeHubAddress, mockedSharedBridgeAddress, mockedSTMAddresses, ); const mockPrices = { "wrapped-bitcoin": 66_129, "usd-coin": 0.999, ethereum: 3_181.09 }; // Mocked prices - vi.spyOn(evmProviderService, "getMulticall3Address").mockReturnValue(undefined); - vi.spyOn(evmProviderService, "multicall").mockRejectedValue(MulticallNotFound); - vi.spyOn(evmProviderService, "readContract") + vi.spyOn(evmProvider, "getMulticall3Address").mockReturnValue(undefined); + vi.spyOn(evmProvider, "multicall").mockRejectedValue(MulticallNotFound); + vi.spyOn(evmProvider, "readContract") .mockResolvedValueOnce(60_841_657_140641n) .mockResolvedValueOnce(135_63005559n); - vi.spyOn(evmProviderService, "getBalance").mockResolvedValue( - 123_803_824374847279970609n, - ); + vi.spyOn(evmProvider, "getBalance").mockResolvedValue(123_803_824374847279970609n); vi.spyOn(pricingService, "getTokenPrices").mockResolvedValue(mockPrices); const result = await l1Metrics.l1Tvl(); @@ -315,24 +313,22 @@ describe("l1Metrics", () => { decimals: 8, }, ]); - expect(evmProviderService.multicall).not.toHaveBeenCalled(); - expect(evmProviderService.readContract).toHaveBeenNthCalledWith( + expect(evmProvider.multicall).not.toHaveBeenCalled(); + expect(evmProvider.readContract).toHaveBeenNthCalledWith( 1, "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", erc20Abi, "balanceOf", [l1Metrics["sharedBridgeAddress"]], ); - expect(evmProviderService.readContract).toHaveBeenNthCalledWith( + expect(evmProvider.readContract).toHaveBeenNthCalledWith( 2, "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599", erc20Abi, "balanceOf", [l1Metrics["sharedBridgeAddress"]], ); - expect(evmProviderService.getBalance).toHaveBeenCalledWith( - l1Metrics["sharedBridgeAddress"], - ); + expect(evmProvider.getBalance).toHaveBeenCalledWith(l1Metrics["sharedBridgeAddress"]); expect(pricingService.getTokenPrices).toHaveBeenCalledWith([ "ethereum", "usd-coin", @@ -341,30 +337,30 @@ describe("l1Metrics", () => { }); it("throws an error if the balances length is invalid", async () => { - const { l1Metrics, evmProviderService } = mockMetricsModule( + const { l1Metrics, evmProvider } = mockMetricsModule( mockedBridgeHubAddress, mockedSharedBridgeAddress, mockedSTMAddresses, ); - vi.spyOn(evmProviderService, "getMulticall3Address").mockReturnValue("0x123452"); - vi.spyOn(evmProviderService, "multicall").mockResolvedValue([]); + vi.spyOn(evmProvider, "getMulticall3Address").mockReturnValue("0x123452"); + vi.spyOn(evmProvider, "multicall").mockResolvedValue([]); await expect(l1Metrics.l1Tvl()).rejects.toThrowError("Invalid balances length"); }); it("throws an error if the prices length is invalid", async () => { - const { l1Metrics, evmProviderService, pricingService } = mockMetricsModule( + const { l1Metrics, evmProvider, pricingService } = mockMetricsModule( mockedBridgeHubAddress, mockedSharedBridgeAddress, mockedSTMAddresses, ); - vi.spyOn(evmProviderService, "multicall").mockResolvedValue([ + vi.spyOn(evmProvider, "multicall").mockResolvedValue([ 60_841_657_140641n, 135_63005559n, 123_803_824374847279970609n, ]); - vi.spyOn(evmProviderService, "getMulticall3Address").mockReturnValue("0x123452"); + vi.spyOn(evmProvider, "getMulticall3Address").mockReturnValue("0x123452"); vi.spyOn(pricingService, "getTokenPrices").mockResolvedValue({ ethereum: 3_181.09, "usd-coin": 0.999, @@ -376,7 +372,7 @@ describe("l1Metrics", () => { describe("getBatchesInfo", () => { it("returns batches info for chain id", async () => { - const { l1Metrics, evmProviderService } = mockMetricsModule( + const { l1Metrics, evmProvider } = mockMetricsModule( mockedBridgeHubAddress, mockedSharedBridgeAddress, mockedSTMAddresses, @@ -392,14 +388,12 @@ describe("l1Metrics", () => { mockBatchesInfo.executed, ]; - vi.spyOn(evmProviderService, "multicall").mockResolvedValue( - batchesInfoMulticallResponse, - ); + vi.spyOn(evmProvider, "multicall").mockResolvedValue(batchesInfoMulticallResponse); const result = await l1Metrics.getBatchesInfo(chainId); expect(result).toEqual(mockBatchesInfo); - expect(evmProviderService.multicall).toHaveBeenCalledWith({ + expect(evmProvider.multicall).toHaveBeenCalledWith({ contracts: [ { address: mockedDiamondProxyAddress, @@ -425,19 +419,19 @@ describe("l1Metrics", () => { }); it("throws if chainId doesn't exist on the ecosystem", async () => { - const { l1Metrics, evmProviderService } = mockMetricsModule( + const { l1Metrics, evmProvider } = mockMetricsModule( mockedBridgeHubAddress, mockedSharedBridgeAddress, mockedSTMAddresses, ); const chainId = 324n; // this is ZKsyncEra chain id l1Metrics["diamondContracts"].clear(); - vi.spyOn(evmProviderService, "readContract").mockResolvedValue(zeroAddress); + vi.spyOn(evmProvider, "readContract").mockResolvedValue(zeroAddress); await expect(l1Metrics.getBatchesInfo(chainId)).rejects.toThrow(InvalidChainId); }); it("fetches and sets diamond proxy if chainId doesn't exists on map", async () => { - const { l1Metrics, evmProviderService } = mockMetricsModule( + const { l1Metrics, evmProvider } = mockMetricsModule( mockedBridgeHubAddress, mockedSharedBridgeAddress, mockedSTMAddresses, @@ -454,24 +448,20 @@ describe("l1Metrics", () => { mockBatchesInfo.executed, ]; - vi.spyOn(evmProviderService, "readContract").mockResolvedValue( - mockedDiamondProxyAddress, - ); - vi.spyOn(evmProviderService, "multicall").mockResolvedValue( - batchesInfoMulticallResponse, - ); + vi.spyOn(evmProvider, "readContract").mockResolvedValue(mockedDiamondProxyAddress); + vi.spyOn(evmProvider, "multicall").mockResolvedValue(batchesInfoMulticallResponse); const result = await l1Metrics.getBatchesInfo(chainId); expect(result).toEqual(mockBatchesInfo); expect(l1Metrics["diamondContracts"].get(chainId)).toEqual(mockedDiamondProxyAddress); - expect(evmProviderService.readContract).toHaveBeenCalledWith( + expect(evmProvider.readContract).toHaveBeenCalledWith( l1Metrics["bridgeHubAddress"], bridgeHubAbi, "getHyperchain", [chainId], ); - expect(evmProviderService.multicall).toHaveBeenCalledWith({ + expect(evmProvider.multicall).toHaveBeenCalledWith({ contracts: [ { address: mockedDiamondProxyAddress, @@ -499,7 +489,7 @@ describe("l1Metrics", () => { describe("fetchDiamondProxyAddress", () => { it("returns address if already exists in the map", async () => { - const { l1Metrics, evmProviderService } = mockMetricsModule( + const { l1Metrics, evmProvider } = mockMetricsModule( mockedBridgeHubAddress, mockedSharedBridgeAddress, mockedSTMAddresses, @@ -509,7 +499,7 @@ describe("l1Metrics", () => { l1Metrics["diamondContracts"].clear(); l1Metrics["diamondContracts"].set(chainId, mockedDiamondProxyAddress); - const readContractSpy = vi.spyOn(evmProviderService, "readContract"); + const readContractSpy = vi.spyOn(evmProvider, "readContract"); const result = await l1Metrics["fetchDiamondProxyAddress"](chainId); expect(result).toEqual(mockedDiamondProxyAddress); @@ -517,7 +507,7 @@ describe("l1Metrics", () => { expect(readContractSpy).toHaveBeenCalledTimes(0); }); it("fetches and sets diamond proxy if chainId doesn't exists on map", async () => { - const { l1Metrics, evmProviderService } = mockMetricsModule( + const { l1Metrics, evmProvider } = mockMetricsModule( mockedBridgeHubAddress, mockedSharedBridgeAddress, mockedSTMAddresses, @@ -527,15 +517,13 @@ describe("l1Metrics", () => { l1Metrics["diamondContracts"].clear(); - vi.spyOn(evmProviderService, "readContract").mockResolvedValue( - mockedDiamondProxyAddress, - ); + vi.spyOn(evmProvider, "readContract").mockResolvedValue(mockedDiamondProxyAddress); const result = await l1Metrics["fetchDiamondProxyAddress"](chainId); expect(result).toEqual(mockedDiamondProxyAddress); expect(l1Metrics["diamondContracts"].get(chainId)).toEqual(mockedDiamondProxyAddress); - expect(evmProviderService.readContract).toHaveBeenCalledWith( + expect(evmProvider.readContract).toHaveBeenCalledWith( l1Metrics["bridgeHubAddress"], bridgeHubAbi, "getHyperchain", @@ -546,7 +534,7 @@ describe("l1Metrics", () => { describe("tvl", () => { it("return the TVL for chain id", async () => { - const { l1Metrics, evmProviderService, pricingService } = mockMetricsModule( + const { l1Metrics, evmProvider, pricingService } = mockMetricsModule( mockedBridgeHubAddress, mockedSharedBridgeAddress, mockedSTMAddresses, @@ -555,7 +543,7 @@ describe("l1Metrics", () => { const mockPrices = { "wrapped-bitcoin": 66_129, "usd-coin": 0.999, ethereum: 3_181.09 }; // Mocked prices const chainId = 324n; // this is ZKsyncEra chain id - vi.spyOn(evmProviderService, "multicall").mockResolvedValue(mockBalances); + vi.spyOn(evmProvider, "multicall").mockResolvedValue(mockBalances); vi.spyOn(pricingService, "getTokenPrices").mockResolvedValue(mockPrices); const result = await l1Metrics.tvl(chainId); @@ -599,7 +587,7 @@ describe("l1Metrics", () => { decimals: 8, }, ]); - expect(evmProviderService.multicall).toHaveBeenCalledWith({ + expect(evmProvider.multicall).toHaveBeenCalledWith({ contracts: [ { address: l1Metrics["sharedBridgeAddress"], @@ -630,13 +618,13 @@ describe("l1Metrics", () => { }); it("throws an error if the prices length is invalid", async () => { - const { l1Metrics, evmProviderService, pricingService } = mockMetricsModule( + const { l1Metrics, evmProvider, pricingService } = mockMetricsModule( mockedBridgeHubAddress, mockedSharedBridgeAddress, mockedSTMAddresses, ); const chainId = 324n; - vi.spyOn(evmProviderService, "multicall").mockResolvedValue([ + vi.spyOn(evmProvider, "multicall").mockResolvedValue([ 60_841_657_140641n, 135_63005559n, 123_803_824374847279970609n, @@ -652,7 +640,7 @@ describe("l1Metrics", () => { describe("chainType", () => { it("returns chainType", async () => { - const { l1Metrics, evmProviderService } = mockMetricsModule( + const { l1Metrics, evmProvider } = mockMetricsModule( mockedBridgeHubAddress, mockedSharedBridgeAddress, mockedSTMAddresses, @@ -663,9 +651,7 @@ describe("l1Metrics", () => { l1Metrics["diamondContracts"].set(chainId, mockedDiamondProxyAddress); const mockChainType: ChainType = "Rollup"; - const readContractSpy = vi - .spyOn(evmProviderService, "readContract") - .mockResolvedValue(0); + const readContractSpy = vi.spyOn(evmProvider, "readContract").mockResolvedValue(0); const result = await l1Metrics.chainType(chainId); @@ -678,7 +664,7 @@ describe("l1Metrics", () => { ); }); it("returns chainType", async () => { - const { l1Metrics, evmProviderService } = mockMetricsModule( + const { l1Metrics, evmProvider } = mockMetricsModule( mockedBridgeHubAddress, mockedSharedBridgeAddress, mockedSTMAddresses, @@ -689,9 +675,7 @@ describe("l1Metrics", () => { l1Metrics["diamondContracts"].set(chainId, mockedDiamondProxyAddress); const mockChainType: ChainType = "Validium"; - const readContractSpy = vi - .spyOn(evmProviderService, "readContract") - .mockResolvedValue(1); + const readContractSpy = vi.spyOn(evmProvider, "readContract").mockResolvedValue(1); const result = await l1Metrics.chainType(chainId); @@ -704,7 +688,7 @@ describe("l1Metrics", () => { ); }); it("throws if blockchain returns an out of bounds index", async () => { - const { l1Metrics, evmProviderService } = mockMetricsModule( + const { l1Metrics, evmProvider } = mockMetricsModule( mockedBridgeHubAddress, mockedSharedBridgeAddress, mockedSTMAddresses, @@ -714,7 +698,7 @@ describe("l1Metrics", () => { l1Metrics["diamondContracts"].set(chainId, mockedDiamondProxyAddress); - vi.spyOn(evmProviderService, "readContract").mockResolvedValue(100); + vi.spyOn(evmProvider, "readContract").mockResolvedValue(100); await expect(l1Metrics.chainType(chainId)).rejects.toThrowError(InvalidChainType); }); @@ -722,16 +706,16 @@ describe("l1Metrics", () => { describe("ethGasInfo", () => { it("returns gas information from L1", async () => { - const { l1Metrics, evmProviderService, pricingService } = mockMetricsModule( + const { l1Metrics, evmProvider, pricingService } = mockMetricsModule( mockedBridgeHubAddress, mockedSharedBridgeAddress, mockedSTMAddresses, ); // Mock the necessary dependencies - const mockEstimateGas = vi.spyOn(evmProviderService, "estimateGas"); + const mockEstimateGas = vi.spyOn(evmProvider, "estimateGas"); mockEstimateGas.mockResolvedValueOnce(BigInt(21000)); // ethTransferGasCost mockEstimateGas.mockResolvedValueOnce(BigInt(65000)); // erc20TransferGasCost' - const mockGetGasPrice = vi.spyOn(evmProviderService, "getGasPrice"); + const mockGetGasPrice = vi.spyOn(evmProvider, "getGasPrice"); mockGetGasPrice.mockResolvedValueOnce(BigInt(50000000000)); // gasPrice const mockGetTokenPrices = vi.spyOn(pricingService, "getTokenPrices"); @@ -770,16 +754,16 @@ describe("l1Metrics", () => { }); it("returns gas information from L1 without ether price", async () => { - const { l1Metrics, evmProviderService, pricingService } = mockMetricsModule( + const { l1Metrics, evmProvider, pricingService } = mockMetricsModule( mockedBridgeHubAddress, mockedSharedBridgeAddress, mockedSTMAddresses, ); - const mockEstimateGas = vi.spyOn(evmProviderService, "estimateGas"); + const mockEstimateGas = vi.spyOn(evmProvider, "estimateGas"); mockEstimateGas.mockResolvedValueOnce(BigInt(21000)); // ethTransferGasCost mockEstimateGas.mockResolvedValueOnce(BigInt(65000)); // erc20TransferGasCost - const mockGetGasPrice = vi.spyOn(evmProviderService, "getGasPrice"); + const mockGetGasPrice = vi.spyOn(evmProvider, "getGasPrice"); mockGetGasPrice.mockResolvedValueOnce(BigInt(50000000000)); // gasPrice const mockGetTokenPrices = vi.spyOn(pricingService, "getTokenPrices"); @@ -817,16 +801,16 @@ describe("l1Metrics", () => { }); it("throws l1MetricsException when estimateGas fails", async () => { - const { l1Metrics, evmProviderService, pricingService } = mockMetricsModule( + const { l1Metrics, evmProvider, pricingService } = mockMetricsModule( mockedBridgeHubAddress, mockedSharedBridgeAddress, mockedSTMAddresses, ); // Mock the necessary dependencies - const mockEstimateGas = vi.spyOn(evmProviderService, "estimateGas"); + const mockEstimateGas = vi.spyOn(evmProvider, "estimateGas"); mockEstimateGas.mockRejectedValueOnce(new Error("Failed to estimate gas")); - const mockGetGasPrice = vi.spyOn(evmProviderService, "getGasPrice"); + const mockGetGasPrice = vi.spyOn(evmProvider, "getGasPrice"); mockGetGasPrice.mockResolvedValueOnce(BigInt(50000000000)); // gasPrice const mockGetTokenPrices = vi.spyOn(pricingService, "getTokenPrices"); @@ -846,17 +830,17 @@ describe("l1Metrics", () => { }); it("throws l1MetricsException when getGasPrice fails", async () => { - const { l1Metrics, evmProviderService, pricingService } = mockMetricsModule( + const { l1Metrics, evmProvider, pricingService } = mockMetricsModule( mockedBridgeHubAddress, mockedSharedBridgeAddress, mockedSTMAddresses, ); // Mock the necessary dependencies - const mockEstimateGas = vi.spyOn(evmProviderService, "estimateGas"); + const mockEstimateGas = vi.spyOn(evmProvider, "estimateGas"); mockEstimateGas.mockResolvedValueOnce(BigInt(21000)); // ethTransferGasCost mockEstimateGas.mockResolvedValueOnce(BigInt(65000)); // erc20TransferGasCost - const mockGetGasPrice = vi.spyOn(evmProviderService, "getGasPrice"); + const mockGetGasPrice = vi.spyOn(evmProvider, "getGasPrice"); mockGetGasPrice.mockRejectedValueOnce(new Error("Failed to get gas price")); const mockGetTokenPrices = vi.spyOn(pricingService, "getTokenPrices"); @@ -890,7 +874,7 @@ describe("l1Metrics", () => { describe("getChainIds", () => { it("returns chainIds", async () => { - const { l1Metrics, evmProviderService } = mockMetricsModule( + const { l1Metrics, evmProvider } = mockMetricsModule( mockedBridgeHubAddress, mockedSharedBridgeAddress, mockedSTMAddresses, @@ -899,7 +883,7 @@ describe("l1Metrics", () => { [1n, 2n, 3n], [4n, 5n, 6n], ]; - vi.spyOn(evmProviderService, "multicall").mockResolvedValue(mockedMulticallReturnValue); + vi.spyOn(evmProvider, "multicall").mockResolvedValue(mockedMulticallReturnValue); const result = await l1Metrics.getChainIds(); @@ -933,19 +917,19 @@ describe("l1Metrics", () => { expect(result).toEqual(mockedChainIds); }); it("throws if multicall throws", async () => { - const { l1Metrics, evmProviderService } = mockMetricsModule( + const { l1Metrics, evmProvider } = mockMetricsModule( mockedBridgeHubAddress, mockedSharedBridgeAddress, mockedSTMAddresses, ); - vi.spyOn(evmProviderService, "multicall").mockRejectedValue(new Error()); + vi.spyOn(evmProvider, "multicall").mockRejectedValue(new Error()); await expect(l1Metrics.getChainIds()).rejects.toThrow(Error); }); }); describe("getBaseTokens", () => { it("returns known tokens", async () => { - const { l1Metrics, evmProviderService } = mockMetricsModule( + const { l1Metrics, evmProvider } = mockMetricsModule( mockedBridgeHubAddress, mockedSharedBridgeAddress, mockedSTMAddresses, @@ -958,7 +942,7 @@ describe("l1Metrics", () => { throw new Error("ERC20 tokens are not defined"); } const mockedMulticallReturnValue = [knownTokenAddress1, knownTokenAddress2]; - vi.spyOn(evmProviderService, "multicall").mockResolvedValue(mockedMulticallReturnValue); + vi.spyOn(evmProvider, "multicall").mockResolvedValue(mockedMulticallReturnValue); const mockedReturnData: Token[] = [ erc20Tokens[knownTokenAddress1 as Address] as Token<"erc20">, erc20Tokens[knownTokenAddress2 as Address] as Token<"erc20">, @@ -970,7 +954,7 @@ describe("l1Metrics", () => { }); it("returns unknown tokens", async () => { - const { l1Metrics, evmProviderService } = mockMetricsModule( + const { l1Metrics, evmProvider } = mockMetricsModule( mockedBridgeHubAddress, mockedSharedBridgeAddress, mockedSTMAddresses, @@ -980,7 +964,7 @@ describe("l1Metrics", () => { "0x1234567890123456789012345678901234567123", "0x1234567890123456789012345678901234567345", ]; - vi.spyOn(evmProviderService, "multicall").mockResolvedValue(mockedMulticallReturnValue); + vi.spyOn(evmProvider, "multicall").mockResolvedValue(mockedMulticallReturnValue); const mockedReturnData: Token[] = [ { contractAddress: "0x1234567890123456789012345678901234567123", @@ -1015,30 +999,30 @@ describe("l1Metrics", () => { expect(result).toEqual([]); }); it("throws if multicall fails", async () => { - const { l1Metrics, evmProviderService } = mockMetricsModule( + const { l1Metrics, evmProvider } = mockMetricsModule( mockedBridgeHubAddress, mockedSharedBridgeAddress, mockedSTMAddresses, ); const mockedChainIds: ChainId[] = [1n, 2n]; - vi.spyOn(evmProviderService, "multicall").mockRejectedValue(new Error()); + vi.spyOn(evmProvider, "multicall").mockRejectedValue(new Error()); await expect(l1Metrics.getBaseTokens(mockedChainIds)).rejects.toThrow(Error); }); it("returns eth token", async () => { - const { l1Metrics, evmProviderService } = mockMetricsModule( + const { l1Metrics, evmProvider } = mockMetricsModule( mockedBridgeHubAddress, mockedSharedBridgeAddress, mockedSTMAddresses, ); const mockedChainIds: ChainId[] = [1n, 2n]; - vi.spyOn(evmProviderService, "multicall").mockRejectedValue(new Error()); + vi.spyOn(evmProvider, "multicall").mockRejectedValue(new Error()); await expect(l1Metrics.getBaseTokens(mockedChainIds)).rejects.toThrow(Error); }); }); describe("feeParams", () => { it("should retrieve the fee parameters for a specific chain", async () => { - const { l1Metrics, evmProviderService } = mockMetricsModule( + const { l1Metrics, evmProvider } = mockMetricsModule( mockedBridgeHubAddress, mockedSharedBridgeAddress, mockedSTMAddresses, @@ -1059,11 +1043,11 @@ describe("l1Metrics", () => { }; l1Metrics["diamondContracts"].set(chainId, mockedDiamondProxyAddress); - vi.spyOn(evmProviderService, "getStorageAt").mockResolvedValue(mockFeeParamsRawData); + vi.spyOn(evmProvider, "getStorageAt").mockResolvedValue(mockFeeParamsRawData); const result = await l1Metrics.feeParams(chainId); - expect(evmProviderService.getStorageAt).toHaveBeenCalledWith( + expect(evmProvider.getStorageAt).toHaveBeenCalledWith( mockedDiamondProxyAddress, `0x26`, ); @@ -1072,7 +1056,7 @@ describe("l1Metrics", () => { }); it("should throw an exception if the fee parameters cannot be retrieved from L1", async () => { - const { l1Metrics, evmProviderService } = mockMetricsModule( + const { l1Metrics, evmProvider } = mockMetricsModule( mockedBridgeHubAddress, mockedSharedBridgeAddress, mockedSTMAddresses, @@ -1082,7 +1066,7 @@ describe("l1Metrics", () => { const mockedDiamondProxyAddress = "0x1234567890123456789012345678901234567890"; l1Metrics["diamondContracts"].set(chainId, mockedDiamondProxyAddress); - vi.spyOn(evmProviderService, "getStorageAt").mockResolvedValue(undefined); + vi.spyOn(evmProvider, "getStorageAt").mockResolvedValue(undefined); await expect(l1Metrics.feeParams(chainId)).rejects.toThrow(L1MetricsServiceException); }); diff --git a/packages/pricing/src/external.ts b/packages/pricing/src/external.ts index 9fe48eb..faef168 100644 --- a/packages/pricing/src/external.ts +++ b/packages/pricing/src/external.ts @@ -1,5 +1,5 @@ -export type { IPricingService } from "./internal.js"; +export type { IPricingProvider } from "./internal.js"; export { RateLimitExceeded, ApiNotAvailable } from "./internal.js"; -export { CoingeckoService } from "./internal.js"; +export { CoingeckoProvider } from "./internal.js"; diff --git a/packages/pricing/src/interfaces/pricing.interface.ts b/packages/pricing/src/interfaces/pricing.interface.ts index 07e3450..04ff56b 100644 --- a/packages/pricing/src/interfaces/pricing.interface.ts +++ b/packages/pricing/src/interfaces/pricing.interface.ts @@ -4,7 +4,7 @@ export type PricingProvider = "coingecko"; /** * Represents a pricing service that retrieves token prices. */ -export interface IPricingService { +export interface IPricingProvider { /** * Retrieves the prices of the specified tokens. * @param tokenIds - An array of token IDs. diff --git a/packages/pricing/src/internal.ts b/packages/pricing/src/internal.ts index 0cb789f..019311e 100644 --- a/packages/pricing/src/internal.ts +++ b/packages/pricing/src/internal.ts @@ -1,4 +1,4 @@ export * from "./types/index.js"; export * from "./interfaces/index.js"; export * from "./exceptions/index.js"; -export * from "./services/index.js"; +export * from "./providers/index.js"; diff --git a/packages/pricing/src/services/coingecko.service.ts b/packages/pricing/src/providers/coingecko.provider.ts similarity index 97% rename from packages/pricing/src/services/coingecko.service.ts rename to packages/pricing/src/providers/coingecko.provider.ts index f867c81..72fef49 100644 --- a/packages/pricing/src/services/coingecko.service.ts +++ b/packages/pricing/src/providers/coingecko.provider.ts @@ -3,7 +3,7 @@ import axios, { AxiosInstance, isAxiosError } from "axios"; import { BASE_CURRENCY, Cache, ILogger } from "@zkchainhub/shared"; -import type { IPricingService, TokenPrices } from "../internal.js"; +import type { IPricingProvider, TokenPrices } from "../internal.js"; import { ApiNotAvailable, RateLimitExceeded } from "../internal.js"; export const AUTH_HEADER = (type: "demo" | "pro") => @@ -21,7 +21,7 @@ interface CoingeckoOptions { * Service for fetching token prices from Coingecko API. * Prices are always denominated in USD. */ -export class CoingeckoService implements IPricingService { +export class CoingeckoProvider implements IPricingProvider { private readonly axios: AxiosInstance; /** diff --git a/packages/pricing/src/providers/index.ts b/packages/pricing/src/providers/index.ts new file mode 100644 index 0000000..7172e08 --- /dev/null +++ b/packages/pricing/src/providers/index.ts @@ -0,0 +1 @@ +export * from "./coingecko.provider.js"; diff --git a/packages/pricing/src/services/index.ts b/packages/pricing/src/services/index.ts deleted file mode 100644 index 9133101..0000000 --- a/packages/pricing/src/services/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./coingecko.service.js"; diff --git a/packages/pricing/test/unit/services/coingecko.service.spec.ts b/packages/pricing/test/unit/services/coingecko.service.spec.ts index 0735943..04a6470 100644 --- a/packages/pricing/test/unit/services/coingecko.service.spec.ts +++ b/packages/pricing/test/unit/services/coingecko.service.spec.ts @@ -5,7 +5,7 @@ import { BASE_CURRENCY, Cache, ILogger } from "@zkchainhub/shared"; import { ApiNotAvailable, - CoingeckoService, + CoingeckoProvider, DECIMALS_PRECISION, RateLimitExceeded, TokenPrices, @@ -45,12 +45,12 @@ function mockServices({ debug: vi.fn(), }; - const service = new CoingeckoService({ apiKey, apiBaseUrl, apiType }, mockCache, mockLogger); + const service = new CoingeckoProvider({ apiKey, apiBaseUrl, apiType }, mockCache, mockLogger); return { service, mockCache, mockLogger }; } -describe("CoingeckoService", () => { +describe("CoingeckoProvider", () => { const apiKey = "COINGECKO_API_KEY"; const apiBaseUrl = "https://api.coingecko.com/api/v3/"; const apiType = "demo"; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e995b08..f8fc392 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -76,15 +76,15 @@ importers: apps/api: dependencies: + "@zkchainhub/chain-providers": + specifier: workspace:* + version: link:../../packages/chain-providers "@zkchainhub/metrics": specifier: workspace:* version: link:../../packages/metrics "@zkchainhub/pricing": specifier: workspace:* version: link:../../packages/pricing - "@zkchainhub/providers": - specifier: workspace:* - version: link:../../packages/providers "@zkchainhub/shared": specifier: workspace:* version: link:../../packages/shared @@ -129,6 +129,18 @@ importers: specifier: 4.17.0 version: 4.17.0 + packages/chain-providers: + dependencies: + "@zkchainhub/shared": + specifier: workspace:* + version: link:../shared + abitype: + specifier: 1.0.6 + version: 1.0.6(typescript@5.1.3)(zod@3.23.8) + viem: + specifier: 2.19.6 + version: 2.19.6(typescript@5.1.3)(zod@3.23.8) + packages/metadata: dependencies: "@zkchainhub/shared": @@ -137,12 +149,12 @@ importers: packages/metrics: dependencies: + "@zkchainhub/chain-providers": + specifier: workspace:* + version: link:../chain-providers "@zkchainhub/pricing": specifier: workspace:* version: link:../pricing - "@zkchainhub/providers": - specifier: workspace:* - version: link:../providers "@zkchainhub/shared": specifier: workspace:* version: link:../shared @@ -163,18 +175,6 @@ importers: specifier: 2.0.0 version: 2.0.0(axios@1.7.4) - packages/providers: - dependencies: - "@zkchainhub/shared": - specifier: workspace:* - version: link:../shared - abitype: - specifier: 1.0.6 - version: 1.0.6(typescript@5.1.3)(zod@3.23.8) - viem: - specifier: 2.19.6 - version: 2.19.6(typescript@5.1.3)(zod@3.23.8) - packages/shared: dependencies: abitype: