From 7656fd8afd8a6cc4cc2b8bb034965a79ff4a1c86 Mon Sep 17 00:00:00 2001 From: jdevcs Date: Wed, 3 Apr 2024 18:09:41 +0200 Subject: [PATCH 01/16] RequestManagerMiddleware --- packages/web3-core/src/types.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/web3-core/src/types.ts b/packages/web3-core/src/types.ts index 3f4e66d1f52..eba4fbf502a 100644 --- a/packages/web3-core/src/types.ts +++ b/packages/web3-core/src/types.ts @@ -15,7 +15,7 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ -import { HexString, Transaction } from 'web3-types'; +import { HexString, JsonRpcResponse, Transaction, Web3APIMethod, Web3APIRequest, Web3APIReturnType } from 'web3-types'; export type TransactionTypeParser = ( transaction: Transaction, @@ -30,3 +30,14 @@ export interface ExtensionObject { property?: string; methods: Method[]; } + +export interface RequestManagerMiddleware { + processRequest< + Method extends Web3APIMethod + >(request: Web3APIRequest): Promise>; + + processResponse< + Method extends Web3APIMethod, + ResponseType = Web3APIReturnType> + (response: JsonRpcResponse): Promise>; + } \ No newline at end of file From 31af16b75a75a2294776e6adb290f8ed656de89a Mon Sep 17 00:00:00 2001 From: jdevcs Date: Wed, 3 Apr 2024 18:10:01 +0200 Subject: [PATCH 02/16] adding in context --- packages/web3-core/src/web3_context.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/web3-core/src/web3_context.ts b/packages/web3-core/src/web3_context.ts index 76afcaf8875..b50f8ba30f7 100644 --- a/packages/web3-core/src/web3_context.ts +++ b/packages/web3-core/src/web3_context.ts @@ -25,7 +25,7 @@ import { isNullish } from 'web3-utils'; import { BaseTransaction, TransactionFactory } from 'web3-eth-accounts'; import { isSupportedProvider } from './utils.js'; // eslint-disable-next-line import/no-cycle -import { ExtensionObject } from './types.js'; +import { ExtensionObject, RequestManagerMiddleware } from './types.js'; import { Web3BatchRequest } from './web3_batch_request.js'; // eslint-disable-next-line import/no-cycle import { Web3Config, Web3ConfigEvent, Web3ConfigOptions } from './web3_config.js'; @@ -65,6 +65,7 @@ export type Web3ContextInitOptions< registeredSubscriptions?: RegisteredSubs; accountProvider?: Web3AccountProvider; wallet?: Web3BaseWallet; + requestManagerMiddleware?: RequestManagerMiddleware; }; // eslint-disable-next-line no-use-before-define @@ -129,6 +130,7 @@ export class Web3Context< registeredSubscriptions, accountProvider, wallet, + requestManagerMiddleware } = providerOrContext as Web3ContextInitOptions; this.setConfig(config ?? {}); @@ -138,6 +140,7 @@ export class Web3Context< new Web3RequestManager( provider, config?.enableExperimentalFeatures?.useSubscriptionWhenCheckingBlockTimeout, + requestManagerMiddleware ); if (subscriptionManager) { @@ -352,6 +355,11 @@ export class Web3Context< this.provider = provider; return true; } + + public setRequestManagerMiddleware(requestManagerMiddleware: RequestManagerMiddleware){ + this.requestManager.setMiddleware(requestManagerMiddleware); + } + /** * Will return the {@link Web3BatchRequest} constructor. */ From fba04679572bbcc73de6d35cd2486a4e58196cdc Mon Sep 17 00:00:00 2001 From: jdevcs Date: Wed, 3 Apr 2024 18:10:23 +0200 Subject: [PATCH 03/16] request manager support --- .../web3-core/src/web3_request_manager.ts | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/packages/web3-core/src/web3_request_manager.ts b/packages/web3-core/src/web3_request_manager.ts index 3c6cabd0182..5129994b8e3 100644 --- a/packages/web3-core/src/web3_request_manager.ts +++ b/packages/web3-core/src/web3_request_manager.ts @@ -52,6 +52,7 @@ import { isWeb3Provider, } from './utils.js'; import { Web3EventEmitter } from './web3_event_emitter.js'; +import { RequestManagerMiddleware } from './types.js'; export enum Web3RequestManagerEvent { PROVIDER_CHANGED = 'PROVIDER_CHANGED', @@ -73,9 +74,12 @@ export class Web3RequestManager< }> { private _provider?: SupportedProviders; private readonly useRpcCallSpecification?: boolean; + public middleware?: RequestManagerMiddleware; + public constructor( provider?: SupportedProviders | string, useRpcCallSpecification?: boolean, + requestManagerMiddleware?: RequestManagerMiddleware ) { super(); @@ -83,8 +87,12 @@ export class Web3RequestManager< this.setProvider(provider); } this.useRpcCallSpecification = useRpcCallSpecification; - } + if (!isNullish(requestManagerMiddleware)) + this.middleware = requestManagerMiddleware; + + } + /** * Will return all available providers */ @@ -142,6 +150,10 @@ export class Web3RequestManager< return true; } + public setMiddleware(requestManagerMiddleware: RequestManagerMiddleware){ + this.middleware = requestManagerMiddleware; + } + /** * * Will execute a request @@ -155,7 +167,15 @@ export class Web3RequestManager< Method extends Web3APIMethod, ResponseType = Web3APIReturnType, >(request: Web3APIRequest): Promise { - const response = await this._sendRequest(request); + + if (!isNullish(this.middleware)) + request = await this.middleware.processRequest(request); + + let response = await this._sendRequest(request); + + if (!isNullish(this.middleware)) + response = await this.middleware.processResponse(response); + if (jsonRpc.isResponseWithResult(response)) { return response.result; } From b292d012e98983a48e13c773235aa66f059d588a Mon Sep 17 00:00:00 2001 From: jdevcs Date: Wed, 3 Apr 2024 18:10:40 +0200 Subject: [PATCH 04/16] tests --- .../web3-core/test/unit/web3_context.test.ts | 15 +++ .../web3_middleware_request_manager.test.ts | 127 ++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 packages/web3-core/test/unit/web3_middleware_request_manager.test.ts diff --git a/packages/web3-core/test/unit/web3_context.test.ts b/packages/web3-core/test/unit/web3_context.test.ts index 3c433f7259a..09efaaa4514 100644 --- a/packages/web3-core/test/unit/web3_context.test.ts +++ b/packages/web3-core/test/unit/web3_context.test.ts @@ -20,6 +20,8 @@ import { ExistingPluginNamespaceError } from 'web3-errors'; import HttpProvider from 'web3-providers-http'; import { Web3Context, Web3PluginBase } from '../../src/web3_context'; import { Web3RequestManager } from '../../src/web3_request_manager'; +import { EthExecutionAPI, JsonRpcResponse, Web3APIMethod, Web3APIRequest, Web3APIReturnType } from 'web3-types'; +import { RequestManagerMiddleware } from '../../src/types'; // eslint-disable-next-line @typescript-eslint/ban-types class Context1 extends Web3Context<{}> {} @@ -63,6 +65,19 @@ describe('Web3Context', () => { expect(context.currentProvider).toBeInstanceOf(HttpProvider); }); + + it('should set middleware for the request manager', () => { + const context = new Web3Context('http://test.com'); + + let middleware: RequestManagerMiddleware + = { + processRequest: jest.fn(async >(request: Web3APIRequest) => request), + processResponse: jest.fn(async , ResponseType = Web3APIReturnType>(response: JsonRpcResponse) => response), + }; + + context.setRequestManagerMiddleware(middleware); + expect(context.requestManager.middleware).toEqual(middleware); + }); }); describe('getContextObject', () => { diff --git a/packages/web3-core/test/unit/web3_middleware_request_manager.test.ts b/packages/web3-core/test/unit/web3_middleware_request_manager.test.ts new file mode 100644 index 00000000000..f5519d20bf2 --- /dev/null +++ b/packages/web3-core/test/unit/web3_middleware_request_manager.test.ts @@ -0,0 +1,127 @@ + +import { EthExecutionAPI, JsonRpcResponse, Web3APIMethod, Web3APIRequest, Web3APIReturnType } from 'web3-types'; +import { RequestManagerMiddleware } from '../../src/types'; +import { Web3RequestManager } from '../../src/web3_request_manager'; +import { jsonRpc } from 'web3-utils'; + +class Web3Middleware implements RequestManagerMiddleware { + processRequest>( + request: Web3APIRequest + ): Promise> { + // Implement the processRequest logic here + + if (request.method === 'eth_call' && Array.isArray(request.params)) { + request = { + ...request, + params: [...request.params, '0x0', '0x1'], + }; + } + + return Promise.resolve(request); + } + + processResponse< + Method extends Web3APIMethod, + ResponseType = Web3APIReturnType + >( + response: JsonRpcResponse + ): Promise> { + + if (!jsonRpc.isBatchResponse(response) && response.id === 1) { + response = { + ...response, + result: '0x6a756e616964' as any, + }; + } + + return Promise.resolve(response); + } +} + +describe('Request Manager Middleware', () => { + let requestManagerMiddleware: RequestManagerMiddleware; + + beforeAll(() => { + requestManagerMiddleware = { + processRequest: jest.fn(async >(request: Web3APIRequest) => request), + processResponse: jest.fn(async , ResponseType = Web3APIReturnType>(response: JsonRpcResponse) => response), + }; + + }); + + it('should set requestManagerMiddleware via constructor', () => { + let web3RequestManager1: Web3RequestManager; + + web3RequestManager1 = new Web3RequestManager(undefined, true, requestManagerMiddleware); + + expect(web3RequestManager1.middleware).toBeDefined(); + expect(web3RequestManager1.middleware).toEqual(requestManagerMiddleware); + }); + + it('should set requestManagerMiddleware via set method', () => { + + let web3RequestManager2: Web3RequestManager; + + const middleware2: RequestManagerMiddleware = new Web3Middleware(); + web3RequestManager2 = new Web3RequestManager('http://localhost:8181'); + web3RequestManager2.setMiddleware(middleware2); + + expect(web3RequestManager2.middleware).toBeDefined(); + expect(web3RequestManager2.middleware).toEqual(middleware2); + }); + + it('should call processRequest and processResponse functions of requestManagerMiddleware', async () => { + + const web3RequestManager3 = new Web3RequestManager('http://localhost:8080', true, requestManagerMiddleware as RequestManagerMiddleware); + + const expectedResponse: JsonRpcResponse = { + jsonrpc: '2.0', + id: 1, + result: '0x0', + }; + + jest.spyOn(web3RequestManager3 as any, '_sendRequest').mockResolvedValue(expectedResponse); + + const request = { + id: 1, + method: 'eth_call', + params: [], + }; + + await web3RequestManager3.send(request); + + expect(requestManagerMiddleware.processRequest).toHaveBeenCalledWith(request); + expect(requestManagerMiddleware.processResponse).toHaveBeenCalled(); + }); + + it('should allow modification of request and response', async () => { + + const middleware3: RequestManagerMiddleware = new Web3Middleware(); + + const web3RequestManager3 = new Web3RequestManager('http://localhost:8080', true, middleware3); + + const expectedResponse: JsonRpcResponse = { + jsonrpc: '2.0', + id: 1, + result: '0x0', + }; + + const mockSendRequest = jest.spyOn(web3RequestManager3 as any, '_sendRequest'); + mockSendRequest.mockResolvedValue(expectedResponse); + + const request = { + id: 1, + method: 'eth_call', + params: ['0x3'], + }; + + const response = await web3RequestManager3.send(request); + expect(response).toEqual('0x6a756e616964'); + + expect(mockSendRequest).toHaveBeenCalledWith({ + ...request, + params: [...request.params, '0x0', '0x1'], + }); + + }); +}); From fc4649ae38bb98e9f316c782d9652113bf56fc3a Mon Sep 17 00:00:00 2001 From: jdevcs Date: Wed, 3 Apr 2024 18:28:02 +0200 Subject: [PATCH 05/16] lint fix --- .../web3-core/src/web3_request_manager.ts | 6 ++- .../web3-core/test/unit/web3_context.test.ts | 4 +- .../web3_middleware_request_manager.test.ts | 52 ++++++++++++------- 3 files changed, 39 insertions(+), 23 deletions(-) diff --git a/packages/web3-core/src/web3_request_manager.ts b/packages/web3-core/src/web3_request_manager.ts index 5129994b8e3..dc12d919fd0 100644 --- a/packages/web3-core/src/web3_request_manager.ts +++ b/packages/web3-core/src/web3_request_manager.ts @@ -168,10 +168,12 @@ export class Web3RequestManager< ResponseType = Web3APIReturnType, >(request: Web3APIRequest): Promise { + let requestObj = {...request}; + if (!isNullish(this.middleware)) - request = await this.middleware.processRequest(request); + requestObj = await this.middleware.processRequest(requestObj); - let response = await this._sendRequest(request); + let response = await this._sendRequest(requestObj); if (!isNullish(this.middleware)) response = await this.middleware.processResponse(response); diff --git a/packages/web3-core/test/unit/web3_context.test.ts b/packages/web3-core/test/unit/web3_context.test.ts index 09efaaa4514..186122df54e 100644 --- a/packages/web3-core/test/unit/web3_context.test.ts +++ b/packages/web3-core/test/unit/web3_context.test.ts @@ -18,9 +18,9 @@ along with web3.js. If not, see . // eslint-disable-next-line max-classes-per-file import { ExistingPluginNamespaceError } from 'web3-errors'; import HttpProvider from 'web3-providers-http'; +import { EthExecutionAPI, JsonRpcResponse, Web3APIMethod, Web3APIRequest, Web3APIReturnType } from 'web3-types'; import { Web3Context, Web3PluginBase } from '../../src/web3_context'; import { Web3RequestManager } from '../../src/web3_request_manager'; -import { EthExecutionAPI, JsonRpcResponse, Web3APIMethod, Web3APIRequest, Web3APIReturnType } from 'web3-types'; import { RequestManagerMiddleware } from '../../src/types'; // eslint-disable-next-line @typescript-eslint/ban-types @@ -69,7 +69,7 @@ describe('Web3Context', () => { it('should set middleware for the request manager', () => { const context = new Web3Context('http://test.com'); - let middleware: RequestManagerMiddleware + const middleware: RequestManagerMiddleware = { processRequest: jest.fn(async >(request: Web3APIRequest) => request), processResponse: jest.fn(async , ResponseType = Web3APIReturnType>(response: JsonRpcResponse) => response), diff --git a/packages/web3-core/test/unit/web3_middleware_request_manager.test.ts b/packages/web3-core/test/unit/web3_middleware_request_manager.test.ts index f5519d20bf2..8b073be800a 100644 --- a/packages/web3-core/test/unit/web3_middleware_request_manager.test.ts +++ b/packages/web3-core/test/unit/web3_middleware_request_manager.test.ts @@ -1,40 +1,58 @@ - +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ + import { EthExecutionAPI, JsonRpcResponse, Web3APIMethod, Web3APIRequest, Web3APIReturnType } from 'web3-types'; +import { jsonRpc } from 'web3-utils'; import { RequestManagerMiddleware } from '../../src/types'; import { Web3RequestManager } from '../../src/web3_request_manager'; -import { jsonRpc } from 'web3-utils'; class Web3Middleware implements RequestManagerMiddleware { - processRequest>( + public async processRequest>( request: Web3APIRequest ): Promise> { // Implement the processRequest logic here + let requestObj = {...request}; if (request.method === 'eth_call' && Array.isArray(request.params)) { - request = { - ...request, + requestObj = { + ...requestObj, params: [...request.params, '0x0', '0x1'], }; } - return Promise.resolve(request); + return Promise.resolve(requestObj); } - processResponse< + public async processResponse< Method extends Web3APIMethod, ResponseType = Web3APIReturnType >( response: JsonRpcResponse ): Promise> { - if (!jsonRpc.isBatchResponse(response) && response.id === 1) { - response = { - ...response, + let responseObj = {...response}; + if (!jsonRpc.isBatchResponse(responseObj) && responseObj.id === 1) { + responseObj = { + ...responseObj, result: '0x6a756e616964' as any, }; } - return Promise.resolve(response); + return Promise.resolve(responseObj); } } @@ -50,20 +68,16 @@ describe('Request Manager Middleware', () => { }); it('should set requestManagerMiddleware via constructor', () => { - let web3RequestManager1: Web3RequestManager; - - web3RequestManager1 = new Web3RequestManager(undefined, true, requestManagerMiddleware); + const web3RequestManager1: Web3RequestManager = new Web3RequestManager(undefined, true, requestManagerMiddleware); expect(web3RequestManager1.middleware).toBeDefined(); expect(web3RequestManager1.middleware).toEqual(requestManagerMiddleware); }); it('should set requestManagerMiddleware via set method', () => { - - let web3RequestManager2: Web3RequestManager; const middleware2: RequestManagerMiddleware = new Web3Middleware(); - web3RequestManager2 = new Web3RequestManager('http://localhost:8181'); + const web3RequestManager2: Web3RequestManager = new Web3RequestManager('http://localhost:8181'); web3RequestManager2.setMiddleware(middleware2); expect(web3RequestManager2.middleware).toBeDefined(); @@ -72,7 +86,7 @@ describe('Request Manager Middleware', () => { it('should call processRequest and processResponse functions of requestManagerMiddleware', async () => { - const web3RequestManager3 = new Web3RequestManager('http://localhost:8080', true, requestManagerMiddleware as RequestManagerMiddleware); + const web3RequestManager3 = new Web3RequestManager('http://localhost:8080', true, requestManagerMiddleware ); const expectedResponse: JsonRpcResponse = { jsonrpc: '2.0', @@ -116,7 +130,7 @@ describe('Request Manager Middleware', () => { }; const response = await web3RequestManager3.send(request); - expect(response).toEqual('0x6a756e616964'); + expect(response).toBe('0x6a756e616964'); expect(mockSendRequest).toHaveBeenCalledWith({ ...request, From e5c7a80cad31bb6e0a0d30d41ecf81bb30386c78 Mon Sep 17 00:00:00 2001 From: jdevcs Date: Thu, 4 Apr 2024 12:09:40 +0200 Subject: [PATCH 06/16] lint fix --- packages/web3-core/src/types.ts | 8 ++++---- .../test/unit/web3_middleware_request_manager.test.ts | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/web3-core/src/types.ts b/packages/web3-core/src/types.ts index eba4fbf502a..4b0d94191c9 100644 --- a/packages/web3-core/src/types.ts +++ b/packages/web3-core/src/types.ts @@ -33,11 +33,11 @@ export interface ExtensionObject { export interface RequestManagerMiddleware { processRequest< - Method extends Web3APIMethod - >(request: Web3APIRequest): Promise>; + AnotherMethod extends Web3APIMethod + >(request: Web3APIRequest): Promise>; processResponse< - Method extends Web3APIMethod, - ResponseType = Web3APIReturnType> + AnotherMethod extends Web3APIMethod, + ResponseType = Web3APIReturnType> (response: JsonRpcResponse): Promise>; } \ No newline at end of file diff --git a/packages/web3-core/test/unit/web3_middleware_request_manager.test.ts b/packages/web3-core/test/unit/web3_middleware_request_manager.test.ts index 8b073be800a..d240831d91b 100644 --- a/packages/web3-core/test/unit/web3_middleware_request_manager.test.ts +++ b/packages/web3-core/test/unit/web3_middleware_request_manager.test.ts @@ -21,6 +21,8 @@ import { RequestManagerMiddleware } from '../../src/types'; import { Web3RequestManager } from '../../src/web3_request_manager'; class Web3Middleware implements RequestManagerMiddleware { + + // eslint-disable-next-line class-methods-use-this public async processRequest>( request: Web3APIRequest ): Promise> { @@ -37,6 +39,7 @@ class Web3Middleware implements RequestManagerMiddleware { return Promise.resolve(requestObj); } + // eslint-disable-next-line class-methods-use-this public async processResponse< Method extends Web3APIMethod, ResponseType = Web3APIReturnType From ac26275248f71c34e588b65d46972857d069a493 Mon Sep 17 00:00:00 2001 From: jdevcs Date: Thu, 4 Apr 2024 12:26:52 +0200 Subject: [PATCH 07/16] sample middleware --- tools/web3-plugin-example/src/middleware.ts | 41 +++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 tools/web3-plugin-example/src/middleware.ts diff --git a/tools/web3-plugin-example/src/middleware.ts b/tools/web3-plugin-example/src/middleware.ts new file mode 100644 index 00000000000..964ea6048ff --- /dev/null +++ b/tools/web3-plugin-example/src/middleware.ts @@ -0,0 +1,41 @@ +import { RequestManagerMiddleware } from "web3-core"; +import { Web3APIMethod, Web3APIRequest, Web3APIReturnType, JsonRpcResponse } from "web3-types"; +import { jsonRpc } from "web3-utils"; + +export class Web3Middleware implements RequestManagerMiddleware { + + // eslint-disable-next-line class-methods-use-this + processRequest>( + request: Web3APIRequest + ): Promise> { + + // add your custom logic here for processing requests + if (request.method === 'eth_call' && Array.isArray(request.params)) { + request = { + ...request, + params: [...request.params, '0x0', '0x1'], + }; + } + + return Promise.resolve(request); + } + + // eslint-disable-next-line class-methods-use-this + processResponse< + Method extends Web3APIMethod, + ResponseType = Web3APIReturnType + >( + response: JsonRpcResponse + ): Promise> { + + // add your custom logic here for processing responses + if (!jsonRpc.isBatchResponse(response) && response.id === 1) { + response = { + ...response, + result: '0x6a756e616964' as any, + }; + } + + return Promise.resolve(response); + } +} \ No newline at end of file From 2e562178f920461724c02561efb03aba12f273b1 Mon Sep 17 00:00:00 2001 From: jdevcs Date: Thu, 4 Apr 2024 12:27:42 +0200 Subject: [PATCH 08/16] middleware in sample plugin --- .../src/custom_rpc_methods.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tools/web3-plugin-example/src/custom_rpc_methods.ts b/tools/web3-plugin-example/src/custom_rpc_methods.ts index 101816a9c27..601cf5dc31e 100644 --- a/tools/web3-plugin-example/src/custom_rpc_methods.ts +++ b/tools/web3-plugin-example/src/custom_rpc_methods.ts @@ -17,6 +17,7 @@ along with web3.js. If not, see . import { Web3PluginBase } from 'web3-core'; // eslint-disable-next-line require-extensions/require-extensions import { Web3Context } from './reexported_web3_context'; +import { Web3Middleware } from './middleware'; type CustomRpcApi = { custom_rpc_method: () => string; @@ -25,7 +26,24 @@ type CustomRpcApi = { export class CustomRpcMethodsPlugin extends Web3PluginBase { public pluginNamespace = 'customRpcMethods'; + public web3Middleware: Web3Middleware | undefined; + public constructor(testMiddleware = false){ + super(); + + if(testMiddleware) + this.web3Middleware = new Web3Middleware(); + } + +public link(parentContext: Web3Context): void { + + if(this.web3Middleware) + parentContext.requestManager.setMiddleware(this.web3Middleware); + + super.link(parentContext); + } + + public async customRpcMethod() { return this.requestManager.send({ method: 'custom_rpc_method', @@ -39,6 +57,7 @@ export class CustomRpcMethodsPlugin extends Web3PluginBase { params: [parameter1, parameter2], }); } + } // Module Augmentation From 4f59e2d221f74cd004b76720c6c0a560ba3f8def Mon Sep 17 00:00:00 2001 From: jdevcs Date: Thu, 4 Apr 2024 12:28:03 +0200 Subject: [PATCH 09/16] middleware test with plugin --- .../test/unit/middleware.test.ts | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 tools/web3-plugin-example/test/unit/middleware.test.ts diff --git a/tools/web3-plugin-example/test/unit/middleware.test.ts b/tools/web3-plugin-example/test/unit/middleware.test.ts new file mode 100644 index 00000000000..465d73de5dc --- /dev/null +++ b/tools/web3-plugin-example/test/unit/middleware.test.ts @@ -0,0 +1,66 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ + +import Web3, { JsonRpcResponse, TransactionCall } from 'web3'; +import { CustomRpcMethodsPlugin } from '../../src/custom_rpc_methods'; + + +describe('CustomRpcMethodsPlugin', () => { + it('should register the plugin', async () => { + + const web3 = new Web3('http://127.0.0.1:8545'); + const plugin = new CustomRpcMethodsPlugin(true); + + // Test mocks and spy - code block start + const expectedResponse: JsonRpcResponse = { + jsonrpc: '2.0', + id: 1, + result: '0x0', + }; + + const mockSendRequest = jest.spyOn(web3.requestManager as any, '_sendRequest'); + mockSendRequest.mockResolvedValue(expectedResponse); + // Test mocks and spy - code block end + + web3.registerPlugin(plugin); + + const transaction: TransactionCall = { + from: '0xee815C0a7cD0Ab35273Bc5943a3c6839a680Eaf0', + to: '0xe3342ae375e9B02F7D5513a1BB2276438D193e15', + type: '0x0', + data: '0x', + nonce: '0x4', + chain: 'mainnet', + hardfork: 'berlin', + chainId: '0x1', + }; + const result = await web3.eth.call(transaction); + expect(result).toEqual('0x6a756e616964'); // result modified by response processor , so its 0x6a756e616964 insated of 0x0 + + const expectedCall = { + method: "eth_call", + params: [ + {...transaction}, + "latest", + "0x0", // added by middleware by request processor + "0x1", // added by middleware by request processor + ], + }; + expect(mockSendRequest).toHaveBeenCalledWith(expectedCall); + + }); +}); From c26b906b4abb6cc75c25314faf8770dc0feda584 Mon Sep 17 00:00:00 2001 From: jdevcs Date: Thu, 4 Apr 2024 12:28:42 +0200 Subject: [PATCH 10/16] lint fix --- .../src/custom_rpc_methods.ts | 2 +- tools/web3-plugin-example/src/middleware.ts | 20 +++++++++++++++++-- .../test/unit/middleware.test.ts | 2 +- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/tools/web3-plugin-example/src/custom_rpc_methods.ts b/tools/web3-plugin-example/src/custom_rpc_methods.ts index 601cf5dc31e..cbadd9a3149 100644 --- a/tools/web3-plugin-example/src/custom_rpc_methods.ts +++ b/tools/web3-plugin-example/src/custom_rpc_methods.ts @@ -17,7 +17,7 @@ along with web3.js. If not, see . import { Web3PluginBase } from 'web3-core'; // eslint-disable-next-line require-extensions/require-extensions import { Web3Context } from './reexported_web3_context'; -import { Web3Middleware } from './middleware'; +import { Web3Middleware } from './middleware.js'; type CustomRpcApi = { custom_rpc_method: () => string; diff --git a/tools/web3-plugin-example/src/middleware.ts b/tools/web3-plugin-example/src/middleware.ts index 964ea6048ff..fae17acd00e 100644 --- a/tools/web3-plugin-example/src/middleware.ts +++ b/tools/web3-plugin-example/src/middleware.ts @@ -1,3 +1,19 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ import { RequestManagerMiddleware } from "web3-core"; import { Web3APIMethod, Web3APIRequest, Web3APIReturnType, JsonRpcResponse } from "web3-types"; import { jsonRpc } from "web3-utils"; @@ -5,7 +21,7 @@ import { jsonRpc } from "web3-utils"; export class Web3Middleware implements RequestManagerMiddleware { // eslint-disable-next-line class-methods-use-this - processRequest>( + async processRequest>( request: Web3APIRequest ): Promise> { @@ -21,7 +37,7 @@ export class Web3Middleware implements RequestManagerMiddleware { } // eslint-disable-next-line class-methods-use-this - processResponse< + async processResponse< Method extends Web3APIMethod, ResponseType = Web3APIReturnType >( diff --git a/tools/web3-plugin-example/test/unit/middleware.test.ts b/tools/web3-plugin-example/test/unit/middleware.test.ts index 465d73de5dc..3004e26ad8d 100644 --- a/tools/web3-plugin-example/test/unit/middleware.test.ts +++ b/tools/web3-plugin-example/test/unit/middleware.test.ts @@ -49,7 +49,7 @@ describe('CustomRpcMethodsPlugin', () => { chainId: '0x1', }; const result = await web3.eth.call(transaction); - expect(result).toEqual('0x6a756e616964'); // result modified by response processor , so its 0x6a756e616964 insated of 0x0 + expect(result).toBe('0x6a756e616964'); // result modified by response processor , so its 0x6a756e616964 insated of 0x0 const expectedCall = { method: "eth_call", From f6ff7cf1772265f16574159ac08cd7faecaa1f8b Mon Sep 17 00:00:00 2001 From: jdevcs Date: Thu, 4 Apr 2024 12:38:21 +0200 Subject: [PATCH 11/16] updated Web3Middleware --- .../src/custom_rpc_methods.ts | 2 +- tools/web3-plugin-example/src/middleware.ts | 28 +++++++++++-------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/tools/web3-plugin-example/src/custom_rpc_methods.ts b/tools/web3-plugin-example/src/custom_rpc_methods.ts index cbadd9a3149..601cf5dc31e 100644 --- a/tools/web3-plugin-example/src/custom_rpc_methods.ts +++ b/tools/web3-plugin-example/src/custom_rpc_methods.ts @@ -17,7 +17,7 @@ along with web3.js. If not, see . import { Web3PluginBase } from 'web3-core'; // eslint-disable-next-line require-extensions/require-extensions import { Web3Context } from './reexported_web3_context'; -import { Web3Middleware } from './middleware.js'; +import { Web3Middleware } from './middleware'; type CustomRpcApi = { custom_rpc_method: () => string; diff --git a/tools/web3-plugin-example/src/middleware.ts b/tools/web3-plugin-example/src/middleware.ts index fae17acd00e..3af435fd025 100644 --- a/tools/web3-plugin-example/src/middleware.ts +++ b/tools/web3-plugin-example/src/middleware.ts @@ -21,37 +21,41 @@ import { jsonRpc } from "web3-utils"; export class Web3Middleware implements RequestManagerMiddleware { // eslint-disable-next-line class-methods-use-this - async processRequest>( + public async processRequest>( request: Web3APIRequest ): Promise> { // add your custom logic here for processing requests - if (request.method === 'eth_call' && Array.isArray(request.params)) { - request = { - ...request, - params: [...request.params, '0x0', '0x1'], + let reqObj = {...request}; + if (reqObj.method === 'eth_call' && Array.isArray(reqObj.params)) { + reqObj = { + ...reqObj, + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + params: [...reqObj.params, '0x0', '0x1'], }; } - return Promise.resolve(request); + return Promise.resolve(reqObj); } // eslint-disable-next-line class-methods-use-this - async processResponse< + public async processResponse< Method extends Web3APIMethod, ResponseType = Web3APIReturnType >( response: JsonRpcResponse ): Promise> { - // add your custom logic here for processing responses - if (!jsonRpc.isBatchResponse(response) && response.id === 1) { - response = { - ...response, + // add your custom logic here for processing responses, following is just a demo + let resObj = {...response}; + if (!jsonRpc.isBatchResponse(resObj) && resObj.id === 1) { + resObj = { + ...resObj, + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment result: '0x6a756e616964' as any, }; } - return Promise.resolve(response); + return Promise.resolve(resObj); } } \ No newline at end of file From 79bb115f771780aa6acd00a1e30dcfa44979fb56 Mon Sep 17 00:00:00 2001 From: jdevcs Date: Thu, 4 Apr 2024 13:07:07 +0200 Subject: [PATCH 12/16] extensible middleware --- packages/web3-core/src/types.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/packages/web3-core/src/types.ts b/packages/web3-core/src/types.ts index 4b0d94191c9..390c5b5e24a 100644 --- a/packages/web3-core/src/types.ts +++ b/packages/web3-core/src/types.ts @@ -33,11 +33,17 @@ export interface ExtensionObject { export interface RequestManagerMiddleware { processRequest< - AnotherMethod extends Web3APIMethod - >(request: Web3APIRequest): Promise>; + AnotherMethod extends Web3APIMethod + >( + request: Web3APIRequest, + options?: { [key: string]: unknown }) // options for future Extensible Middleware + : Promise>; processResponse< - AnotherMethod extends Web3APIMethod, - ResponseType = Web3APIReturnType> - (response: JsonRpcResponse): Promise>; + AnotherMethod extends Web3APIMethod, + ResponseType = Web3APIReturnType> + ( + response: JsonRpcResponse, + options?: { [key: string]: unknown }) // options for future Extensible Middleware + : Promise>; } \ No newline at end of file From 76a10c1c6f26c789b2324ee1e2810ac39285bffe Mon Sep 17 00:00:00 2001 From: jdevcs Date: Thu, 4 Apr 2024 13:13:07 +0200 Subject: [PATCH 13/16] test update --- tools/web3-plugin-example/test/unit/middleware.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/web3-plugin-example/test/unit/middleware.test.ts b/tools/web3-plugin-example/test/unit/middleware.test.ts index 3004e26ad8d..717ddc8856d 100644 --- a/tools/web3-plugin-example/test/unit/middleware.test.ts +++ b/tools/web3-plugin-example/test/unit/middleware.test.ts @@ -19,8 +19,8 @@ import Web3, { JsonRpcResponse, TransactionCall } from 'web3'; import { CustomRpcMethodsPlugin } from '../../src/custom_rpc_methods'; -describe('CustomRpcMethodsPlugin', () => { - it('should register the plugin', async () => { +describe('CustomRpcMethodsPlugin Middleware', () => { + it('should modify request and response using middleware plugin', async () => { const web3 = new Web3('http://127.0.0.1:8545'); const plugin = new CustomRpcMethodsPlugin(true); @@ -49,7 +49,7 @@ describe('CustomRpcMethodsPlugin', () => { chainId: '0x1', }; const result = await web3.eth.call(transaction); - expect(result).toBe('0x6a756e616964'); // result modified by response processor , so its 0x6a756e616964 insated of 0x0 + expect(result).toBe('0x6a756e616964'); // result modified by response processor , so its 0x6a756e616964 instead of 0x0 const expectedCall = { method: "eth_call", From 929f77c9231623254fc5f459a4b17a6c04548dd4 Mon Sep 17 00:00:00 2001 From: jdevcs Date: Thu, 4 Apr 2024 13:45:12 +0200 Subject: [PATCH 14/16] lint update --- packages/web3-core/src/types.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/web3-core/src/types.ts b/packages/web3-core/src/types.ts index 390c5b5e24a..890a5e20c5a 100644 --- a/packages/web3-core/src/types.ts +++ b/packages/web3-core/src/types.ts @@ -36,14 +36,12 @@ export interface RequestManagerMiddleware { AnotherMethod extends Web3APIMethod >( request: Web3APIRequest, - options?: { [key: string]: unknown }) // options for future Extensible Middleware - : Promise>; + options?: { [key: string]: unknown }): Promise>; processResponse< AnotherMethod extends Web3APIMethod, ResponseType = Web3APIReturnType> ( response: JsonRpcResponse, - options?: { [key: string]: unknown }) // options for future Extensible Middleware - : Promise>; + options?: { [key: string]: unknown }): Promise>; } \ No newline at end of file From bbfcf99d6128302b482ea1698836d04c2ff7971b Mon Sep 17 00:00:00 2001 From: jdevcs Date: Mon, 8 Apr 2024 13:12:29 +0200 Subject: [PATCH 15/16] update --- .../src/custom_rpc_methods.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/tools/web3-plugin-example/src/custom_rpc_methods.ts b/tools/web3-plugin-example/src/custom_rpc_methods.ts index 601cf5dc31e..b4362b68bcf 100644 --- a/tools/web3-plugin-example/src/custom_rpc_methods.ts +++ b/tools/web3-plugin-example/src/custom_rpc_methods.ts @@ -28,22 +28,23 @@ export class CustomRpcMethodsPlugin extends Web3PluginBase { public pluginNamespace = 'customRpcMethods'; public web3Middleware: Web3Middleware | undefined; - public constructor(testMiddleware = false){ + public constructor(testMiddleware = false) { super(); - if(testMiddleware) + if (testMiddleware) { this.web3Middleware = new Web3Middleware(); + } } -public link(parentContext: Web3Context): void { + public link(parentContext: Web3Context): void { - if(this.web3Middleware) - parentContext.requestManager.setMiddleware(this.web3Middleware); + if (this.web3Middleware) + parentContext.requestManager.setMiddleware(this.web3Middleware); + + super.link(parentContext); + } - super.link(parentContext); - } - public async customRpcMethod() { return this.requestManager.send({ method: 'custom_rpc_method', From 87294d17e862f9d36aa51fd2fd560d4818e92aed Mon Sep 17 00:00:00 2001 From: jdevcs Date: Mon, 8 Apr 2024 13:24:04 +0200 Subject: [PATCH 16/16] lint fix --- tools/web3-plugin-example/src/custom_rpc_methods.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/web3-plugin-example/src/custom_rpc_methods.ts b/tools/web3-plugin-example/src/custom_rpc_methods.ts index b4362b68bcf..ed1c2fbee23 100644 --- a/tools/web3-plugin-example/src/custom_rpc_methods.ts +++ b/tools/web3-plugin-example/src/custom_rpc_methods.ts @@ -17,6 +17,7 @@ along with web3.js. If not, see . import { Web3PluginBase } from 'web3-core'; // eslint-disable-next-line require-extensions/require-extensions import { Web3Context } from './reexported_web3_context'; +// eslint-disable-next-line require-extensions/require-extensions import { Web3Middleware } from './middleware'; type CustomRpcApi = {