From d1d0894657f776d4c638b56c11f3618b55807a36 Mon Sep 17 00:00:00 2001 From: Nazar Hussain Date: Mon, 7 Aug 2023 16:32:18 +0200 Subject: [PATCH] Add fixes to support web3.js 4x version --- packages/prover/package.json | 4 +-- packages/prover/src/interfaces.ts | 12 ++++++- packages/prover/src/utils/assertion.ts | 20 ++++++++++- packages/prover/src/web3_provider.ts | 33 ++++++++++++----- .../prover/test/unit/utils/assertion.test.ts | 35 ++++++++++++++++--- .../prover/test/unit/web3_provider.test.ts | 4 +-- 6 files changed, 88 insertions(+), 20 deletions(-) diff --git a/packages/prover/package.json b/packages/prover/package.json index 67af26fb7531..52d68ca94707 100644 --- a/packages/prover/package.json +++ b/packages/prover/package.json @@ -88,8 +88,8 @@ "@types/http-proxy": "^1.17.10", "@types/yargs": "^17.0.24", "axios": "^1.3.4", - "ethers": "^6.4.2", - "web3": "^1.10.0" + "ethers": "^6.7.0", + "web3": "^4.0.3" }, "keywords": [ "ethereum", diff --git a/packages/prover/src/interfaces.ts b/packages/prover/src/interfaces.ts index 30558f149596..1f191be8bf4f 100644 --- a/packages/prover/src/interfaces.ts +++ b/packages/prover/src/interfaces.ts @@ -35,6 +35,10 @@ export interface EIP1193Provider { request: (payload: JsonRpcRequestOrBatch) => Promise; } +export interface Web3jsProvider { + request: (payload: JsonRpcRequest) => Promise; +} + // Some providers uses `request` instead of the `send`. e.g. Ganache export interface RequestProvider { request( @@ -59,7 +63,13 @@ export interface SendAsyncProvider { sendAsync(payload: JsonRpcRequestOrBatch): Promise; } -export type Web3Provider = SendProvider | EthersProvider | SendAsyncProvider | RequestProvider | EIP1193Provider; +export type Web3Provider = + | SendProvider + | EthersProvider + | SendAsyncProvider + | RequestProvider + | EIP1193Provider + | Web3jsProvider; export type ELVerifiedRequestHandlerOpts = { payload: JsonRpcRequest; diff --git a/packages/prover/src/utils/assertion.ts b/packages/prover/src/utils/assertion.ts index 5f7f4dbdf6ef..e302b9a9200a 100644 --- a/packages/prover/src/utils/assertion.ts +++ b/packages/prover/src/utils/assertion.ts @@ -14,8 +14,19 @@ export function assertLightClient(client?: Lightclient): asserts client is Light } } +/** + * Checks if the provider is a web3.js version 4x. + */ +export function isWeb3jsProvider(provider: Web3Provider): provider is EIP1193Provider { + return ( + "isWeb3Provider" in provider.constructor && + (provider.constructor as {isWeb3Provider: (provider: Web3Provider) => boolean}).isWeb3Provider(provider) + ); +} + export function isSendProvider(provider: Web3Provider): provider is SendProvider { return ( + !isWeb3jsProvider(provider) && "send" in provider && typeof provider.send === "function" && provider.send.length > 1 && @@ -25,6 +36,7 @@ export function isSendProvider(provider: Web3Provider): provider is SendProvider export function isEthersProvider(provider: Web3Provider): provider is EthersProvider { return ( + !isWeb3jsProvider(provider) && "send" in provider && typeof provider.send === "function" && provider.send.length > 1 && @@ -33,7 +45,12 @@ export function isEthersProvider(provider: Web3Provider): provider is EthersProv } export function isRequestProvider(provider: Web3Provider): provider is RequestProvider { - return "request" in provider && typeof provider.request === "function" && provider.request.length > 1; + return ( + !isWeb3jsProvider(provider) && + "request" in provider && + typeof provider.request === "function" && + provider.request.length > 1 + ); } export function isSendAsyncProvider(provider: Web3Provider): provider is SendAsyncProvider { @@ -46,6 +63,7 @@ export function isSendAsyncProvider(provider: Web3Provider): provider is SendAsy export function isEIP1193Provider(provider: Web3Provider): provider is EIP1193Provider { return ( + !isWeb3jsProvider(provider) && "request" in provider && typeof provider.request === "function" && provider.request.constructor.name === "AsyncFunction" diff --git a/packages/prover/src/web3_provider.ts b/packages/prover/src/web3_provider.ts index 60601e9f4b89..38dee22cedc7 100644 --- a/packages/prover/src/web3_provider.ts +++ b/packages/prover/src/web3_provider.ts @@ -18,6 +18,7 @@ import { isRequestProvider, isSendAsyncProvider, isSendProvider, + isWeb3jsProvider, } from "./utils/assertion.js"; import {processAndVerifyRequest} from "./utils/process.js"; import {isBatchRequest} from "./utils/json_rpc.js"; @@ -184,14 +185,23 @@ function handleEthersProvider( return {provider: Object.assign(provider, {send: newSend}), rpc}; } - +/** + * + * + * @export + * @template T + * @param {T} provider + * @param {Logger} logger + * @return {*} {Web3ProviderTypeHandler} + */ export function getProviderTypeHandler( provider: T, logger: Logger ): Web3ProviderTypeHandler { - if (isSendProvider(provider)) { - logger.debug("Provider is recognized as legacy provider with 'send' method."); - return handleSendProvider as unknown as Web3ProviderTypeHandler; + if (isWeb3jsProvider(provider)) { + logger.debug("Provider is recognized as 'web3.js' provider."); + // EIP-1193 provider is fully compatible with web3.js#4x provider interface + return handleEIP1193Provider as unknown as Web3ProviderTypeHandler; } if (isEthersProvider(provider)) { @@ -199,6 +209,16 @@ export function getProviderTypeHandler( return handleEthersProvider as unknown as Web3ProviderTypeHandler; } + if (isEIP1193Provider(provider)) { + logger.debug("Provider is recognized as 'EIP1193' provider."); + return handleEIP1193Provider as unknown as Web3ProviderTypeHandler; + } + + if (isSendProvider(provider)) { + logger.debug("Provider is recognized as legacy provider with 'send' method."); + return handleSendProvider as unknown as Web3ProviderTypeHandler; + } + if (isRequestProvider(provider)) { logger.debug("Provider is recognized as legacy provider with 'request' method."); return handleRequestProvider as unknown as Web3ProviderTypeHandler; @@ -209,10 +229,5 @@ export function getProviderTypeHandler( return handleSendAsyncProvider as unknown as Web3ProviderTypeHandler; } - if (isEIP1193Provider(provider)) { - logger.debug("Provider is recognized as 'EIP1193' provider."); - return handleEIP1193Provider as unknown as Web3ProviderTypeHandler; - } - throw new Error("Unsupported provider type"); } diff --git a/packages/prover/test/unit/utils/assertion.test.ts b/packages/prover/test/unit/utils/assertion.test.ts index 1cb9a4b1f4f3..100ad7a6d7c5 100644 --- a/packages/prover/test/unit/utils/assertion.test.ts +++ b/packages/prover/test/unit/utils/assertion.test.ts @@ -1,7 +1,8 @@ import {expect} from "chai"; import {ethers} from "ethers"; import Web3 from "web3"; -import {isSendProvider} from "../../../src/utils/assertion.js"; +import {isSendProvider, isWeb3jsProvider, isEthersProvider} from "../../../src/utils/assertion.js"; +import {Web3Provider} from "../../../src/interfaces.js"; describe("utils/assertion", () => { describe("isSendProvider", () => { @@ -15,13 +16,37 @@ describe("utils/assertion", () => { }); it("should return false for ethers provider", () => { - const provider = new ethers.JsonRpcProvider(""); + const provider = new ethers.JsonRpcProvider("https://lodestar-sepoliarpc.chainsafe.io"); expect(isSendProvider(provider)).to.be.false; }); - it("should return true for web3 provider", () => { - const provider = new Web3.providers.HttpProvider(""); - expect(isSendProvider(provider)).to.be.true; + it("should return false for web3 provider", () => { + const provider = new Web3.providers.HttpProvider("https://lodestar-sepoliarpc.chainsafe.io"); + expect(isSendProvider(provider as Web3Provider)).to.be.false; + }); + }); + + describe("isWeb3jsProvider", () => { + it("should return true if provider is web3.js provider", () => { + const provider = new Web3.providers.HttpProvider("https://lodestar-sepoliarpc.chainsafe.io"); + expect(isWeb3jsProvider(provider as Web3Provider)).to.be.true; + }); + + it("should return false if provider is not web3.js provider", () => { + const provider = new ethers.JsonRpcProvider("https://lodestar-sepoliarpc.chainsafe.io"); + expect(isWeb3jsProvider(provider as Web3Provider)).to.be.false; + }); + }); + + describe("isEthersProvider", () => { + it("should return false if provider is not ethers provider", () => { + const provider = new Web3.providers.HttpProvider("https://lodestar-sepoliarpc.chainsafe.io"); + expect(isEthersProvider(provider as Web3Provider)).to.be.false; + }); + + it("should return true if provider is ethers provider", () => { + const provider = new ethers.JsonRpcProvider("https://lodestar-sepoliarpc.chainsafe.io"); + expect(isEthersProvider(provider as Web3Provider)).to.be.true; }); }); }); diff --git a/packages/prover/test/unit/web3_provider.test.ts b/packages/prover/test/unit/web3_provider.test.ts index e29188503b96..0719c76795f4 100644 --- a/packages/prover/test/unit/web3_provider.test.ts +++ b/packages/prover/test/unit/web3_provider.test.ts @@ -2,7 +2,7 @@ import {expect} from "chai"; import Web3 from "web3"; import {ethers} from "ethers"; import sinon from "sinon"; -import {createVerifiedExecutionProvider, ProofProvider, LCTransport} from "@lodestar/prover/browser"; +import {createVerifiedExecutionProvider, ProofProvider, LCTransport, Web3Provider} from "@lodestar/prover/browser"; import {ELRpc} from "../../src/utils/rpc.js"; describe("web3_provider", () => { @@ -19,7 +19,7 @@ describe("web3_provider", () => { sandbox.stub(ELRpc.prototype, "verifyCompatibility").resolves(); const {provider, proofProvider} = createVerifiedExecutionProvider( - new Web3.providers.HttpProvider("https://lodestar-sepoliarpc.chainsafe.io"), + new Web3.providers.HttpProvider("https://lodestar-sepoliarpc.chainsafe.io") as Web3Provider, { transport: LCTransport.Rest, urls: ["https://lodestar-sepolia.chainsafe.io"],