diff --git a/packages/web3-core/CHANGELOG.md b/packages/web3-core/CHANGELOG.md index 0346e3f74a9..6c8e6a2a7e2 100644 --- a/packages/web3-core/CHANGELOG.md +++ b/packages/web3-core/CHANGELOG.md @@ -221,4 +221,8 @@ Documentation: - Set a try catch block if processesingError fails (#7022) -## [Unreleased] \ No newline at end of file +## [Unreleased] + +### Added + +- Now when existing packages are added in web3, will be avalible for plugins via context. (#7088) \ No newline at end of file diff --git a/packages/web3-core/src/web3_context.ts b/packages/web3-core/src/web3_context.ts index b50f8ba30f7..867f10f2350 100644 --- a/packages/web3-core/src/web3_context.ts +++ b/packages/web3-core/src/web3_context.ts @@ -219,6 +219,9 @@ export class Web3Context< newContextChild.setConfig({ [event.name]: event.newValue }); }); + // @ts-expect-error No index signature with a parameter of type 'string' was found on type 'Web3Context' + this[ContextRef.name] = newContextChild; + return newContextChild; } diff --git a/packages/web3-eth/CHANGELOG.md b/packages/web3-eth/CHANGELOG.md index 3d2d36b17c0..98dfb42b220 100644 --- a/packages/web3-eth/CHANGELOG.md +++ b/packages/web3-eth/CHANGELOG.md @@ -248,4 +248,10 @@ Documentation: - Fixed issue with simple transactions, Within `checkRevertBeforeSending` if there is no data set in transaction, set gas to be `21000` (#7043) -## [Unreleased] \ No newline at end of file +## [Unreleased] + +### Added + +- `sendTransaction` in `rpc_method_wrappers` accepts optional param of `TransactionMiddleware` (#7088) +- WebEth has `setTransactionMiddleware` and `getTransactionMiddleware` for automatically passing to `sentTransaction` (#7088) +- `TransactionMiddleware` and `TransactionMiddleware` data types are exported (#7088) \ No newline at end of file diff --git a/packages/web3-eth/src/rpc_method_wrappers.ts b/packages/web3-eth/src/rpc_method_wrappers.ts index 20e832be892..336aef3a23d 100644 --- a/packages/web3-eth/src/rpc_method_wrappers.ts +++ b/packages/web3-eth/src/rpc_method_wrappers.ts @@ -70,6 +70,7 @@ import { SendSignedTransactionOptions, SendTransactionEvents, SendTransactionOptions, + TransactionMiddleware, } from './types.js'; // eslint-disable-next-line import/no-cycle import { getTransactionFromOrToAttr } from './utils/transaction_builder.js'; @@ -544,13 +545,14 @@ export function sendTransaction< ResolveType = FormatType, >( web3Context: Web3Context, - transaction: + transactionObj: | Transaction | TransactionWithFromLocalWalletIndex | TransactionWithToLocalWalletIndex | TransactionWithFromAndToLocalWalletIndex, returnFormat: ReturnFormat, options: SendTransactionOptions = { checkRevertBeforeSending: true }, + transactionMiddleware?: TransactionMiddleware ): Web3PromiEvent> { const promiEvent = new Web3PromiEvent>( (resolve, reject) => { @@ -563,6 +565,12 @@ export function sendTransaction< returnFormat, }); + let transaction = {...transactionObj}; + + if(!isNullish(transactionMiddleware)){ + transaction = await transactionMiddleware.processTransaction(transaction); + } + let transactionFormatted: | Transaction | TransactionWithFromLocalWalletIndex diff --git a/packages/web3-eth/src/types.ts b/packages/web3-eth/src/types.ts index e1bba319d69..9ed49badb39 100644 --- a/packages/web3-eth/src/types.ts +++ b/packages/web3-eth/src/types.ts @@ -33,6 +33,9 @@ import { Numbers, Transaction, TransactionReceipt, + TransactionWithFromAndToLocalWalletIndex, + TransactionWithFromLocalWalletIndex, + TransactionWithToLocalWalletIndex, } from 'web3-types'; export type InternalTransaction = FormatType; @@ -88,3 +91,17 @@ export interface RevertReasonWithCustomError extends RevertReason { customErrorDecodedSignature: string; customErrorArguments: Record; } + +export type TransactionMiddlewareData = Transaction +| TransactionWithFromLocalWalletIndex +| TransactionWithToLocalWalletIndex +| TransactionWithFromAndToLocalWalletIndex; + +export interface TransactionMiddleware{ + // for transaction processing before signing + processTransaction( + transaction: TransactionMiddlewareData, + options?: { [key: string]: unknown }, + ): Promise; + +} \ No newline at end of file diff --git a/packages/web3-eth/src/web3_eth.ts b/packages/web3-eth/src/web3_eth.ts index 959a7d5eddc..abce5c2c317 100644 --- a/packages/web3-eth/src/web3_eth.ts +++ b/packages/web3-eth/src/web3_eth.ts @@ -48,7 +48,7 @@ import { toChecksumAddress, isNullish, ethUnitMap } from 'web3-utils'; import { ethRpcMethods } from 'web3-rpc-methods'; import * as rpcMethodsWrappers from './rpc_method_wrappers.js'; -import { SendTransactionOptions } from './types.js'; +import { SendTransactionOptions, TransactionMiddleware } from './types.js'; import { LogsSubscription, NewPendingTransactionsSubscription, @@ -99,6 +99,9 @@ export const registeredSubscriptions = { * ``` */ export class Web3Eth extends Web3Context { + + private transactionMiddleware?: TransactionMiddleware; + public constructor( providerOrContext?: SupportedProviders | Web3ContextInitOptions | string, ) { @@ -126,6 +129,14 @@ export class Web3Eth extends Web3Context. +*/ + +export const blockMockResult = { + "jsonrpc": "2.0", + "id": "a40a81fa-1f8b-4bb2-a0ad-eef9b6d4636f", + "result": { + "baseFeePerGas": "0x44dab2983", + "blobGasUsed": "0x20000", + "difficulty": "0x0", + "excessBlobGas": "0x1c0000", + "extraData": "0x407273796e636275696c646572", + "gasLimit": "0x1c9c380", + "gasUsed": "0xb7a086", + "hash": "0xf2b1729965179032b17165678a1a212fa31cb008e30f4011ffe8ebdddbd02b95", + "logsBloom": "0xc3a70590c1c62524173d1892e33888067101934dc0891c2c9a898252b6f320215084a48906452960820188d32bba6fb82ec989018a0268603a00a4c6432a11276c9a038c676938eb68bc436c9905a9a1b08d238fb4458f48498215808bec81112e2a3a54869ff22422a8e491093da8a40f601d198417041cd22f799f9048865006e0b069ab049b852442b310396248088145e2810f230f9a44000c6868bc73e9afa8832a8ac92fd609007ac53c0a9cba0645ce298080184624e8040831dbc331f5e618072407050250021b3210e542781183a612d4618c1244000d421a6ca9c01a57e86a085402c55ab413f840a001e7117894d0469e20c2304a9655e344f60d", + "miner": "0x1f9090aae28b8a3dceadf281b0f12828e676c326", + "mixHash": "0x787ab1d511b72df60a705bb4cfc4e92e2f9d203e3e007ae3a0f757425951ca24", + "nonce": "0x0000000000000000", + "number": "0x131ad16", + "parentBeaconBlockRoot": "0x03bbca9fd0c7a0a020de04287f489112c79bc268220e9ff8e18957cd0d5c3cad", + "parentHash": "0xb1d8fa7b8346421d373a6d4c28575155516cea17c12a3df7201170c9e561b38c", + "receiptsRoot": "0x4ec500bdcd761ad505b2a989156c9a9628058d415acc93d800487c7c76308c59", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "size": "0xcb90", + "stateRoot": "0xafbb8743c0a5f4740e322217cb1f2780ee5c57c32bcd04e9256b09efc1a70568", + "timestamp": "0x6661ab8b", + "totalDifficulty": "0xc70d815d562d3cfa955", + "transactions": [ + "0x589956b75d19dbaf9911f246c23d4b3327ef234872ec1931c419041b23eb5b41", + "0x4d3793f20c25979bd329cafdd889ba6be015cfc999acce8642d6e757b5192e93", + "0x5ba5618ca5a14bab50862255dc69726a498346f9832bd0fd1394e8834e56790b", + "0x6df9678f350db7e30afc930b7246bf1c144b9acb7fd1d25d7e107d550ed5a061", + "0xb8f48ff2876cc393725ea4162421754dfb74ff2364a12d4d3de2c6269f1958c7", + "0x2e5cf7c0607025038b6ccd871dc9ce85af686fd5fa2c82e605198af9afa92cca", + "0x307fb855836feff5d8d0969fa4a44d3c6ae31d335da6577f48f9496d6fe9e0b9", + "0x1362bed1aa8a30d28b7b76c35c2a8601b257058beffa9490dcb20de12bcb15b2", + "0x234c7cc346c204022b2e5ead6d2e8c02317aeb0ec5ca82bd97c2b5d5e59a280b", + ], + "transactionsRoot": "0xc21a4d667b5f841538430b1e2c002c598f2178628ad1d61ea2fda462d1216607", + "uncles": [], + "withdrawals": [ + { + "address": "0xea97dc2523c0479484076660f150833e264c41e9", + "amount": "0x11b6d8c", + "index": "0x2dbe454", + "validatorIndex": "0x10f646" + }, + { + "address": "0xb3e84b6c6409826dc45432b655d8c9489a14a0d7", + "amount": "0x11b4ce2", + "index": "0x2dbe455", + "validatorIndex": "0x10f647" + }, + { + "address": "0x7e2a2fa2a064f693f0a55c5639476d913ff12d05", + "amount": "0x11ad733", + "index": "0x2dbe456", + "validatorIndex": "0x10f648" + }, + + ], + "withdrawalsRoot": "0x2914fa2f5ed93880ed45b58e8f6d14f20c645988400d83c59109964e2053fe1a" + } +}; + +export const receiptMockResult = { + "jsonrpc": "2.0", + "id": 1, + "result": { + "blockHash": "0xf4ad699b98241caf3930779b7d919a77f1727e67cef6ed1ce2a4c655ba812d54", + "blockNumber": "0x131ad35", + // eslint-disable-next-line no-null/no-null + "contractAddress": null, + "cumulativeGasUsed": "0x8cae7a", + "effectiveGasPrice": "0x4c9bc2d65", + "from": "0xab6fd3a7c6ce9db945889cd018e028e055f3bc2e", + "gasUsed": "0xa145", + "logs": [ + { + "address": "0xdac17f958d2ee523a2206206994597c13d831ec7", + "blockHash": "0xf4ad699b98241caf3930779b7d919a77f1727e67cef6ed1ce2a4c655ba812d54", + "blockNumber": "0x131ad35", + "data": "0x000000000000000000000000000000000000000000000000000000000016e360", + "logIndex": "0xdf", + "removed": false, + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x000000000000000000000000ab6fd3a7c6ce9db945889cd018e028e055f3bc2e", + "0x00000000000000000000000051112f9f08a2174fe3fc96aad8f07e82d1cccd00" + ], + "transactionHash": "0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f", + "transactionIndex": "0x82" + } + ], + "logsBloom": "0x00000000000000000000000002000000000000000000000000000000004000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000400000000000100000000000000000000000000080000000000000000000040000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000400000000000000000000000", + "status": "0x1", + "to": "0xdac17f958d2ee523a2206206994597c13d831ec7", + "transactionHash": "0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f", + "transactionIndex": "0x82", + "type": "0x2" + } +}; \ No newline at end of file diff --git a/packages/web3-eth/test/unit/rpc_method_wrappers/send_transaction_middleware.test.ts b/packages/web3-eth/test/unit/rpc_method_wrappers/send_transaction_middleware.test.ts new file mode 100644 index 00000000000..63dddbb759f --- /dev/null +++ b/packages/web3-eth/test/unit/rpc_method_wrappers/send_transaction_middleware.test.ts @@ -0,0 +1,98 @@ +/* +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 { Web3Context } from "web3-core"; +import { DEFAULT_RETURN_FORMAT, Web3EthExecutionAPI } from "web3-types"; +import {blockMockResult,receiptMockResult } from "../../fixtures/transactions_data"; +import { TransactionMiddleware, sendTransaction } from "../../../src"; + +const mockTransactionMiddleware: TransactionMiddleware = { + processTransaction: jest.fn(async (transaction) => { + const tx = {...transaction} + tx.data = '0x123'; + return Promise.resolve(tx)} +), +}; + +describe('sendTransaction', () => { + let web3Context: Web3Context; + + beforeEach(() => { + let blockNum = 0; + web3Context = new Web3Context('http://127.0.0.1:8545'); + + web3Context.requestManager.send = jest.fn(async (request) => { + blockNum += 1; + + if(request.method === 'eth_getBlockByNumber'){ + + return Promise.resolve(blockMockResult.result); + } + if(request.method === 'eth_call'){ + + return Promise.resolve("0x"); + } + if(request.method === 'eth_blockNumber'){ + + return Promise.resolve(blockNum.toString(16)); + } + if(request.method === 'eth_sendTransaction'){ + + return Promise.resolve("0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f"); + } + if (request.method === 'eth_getTransactionReceipt') { + return Promise.resolve(receiptMockResult.result); + } + + return Promise.resolve("Unknown Request" as any); + }); + }); + + afterEach(() => jest.resetAllMocks()); + + it('should call processTransaction when transactionMiddleware is provided', async () => { + const transaction = { + from: '0x6E599DA0bfF7A6598AC1224E4985430Bf16458a4', + to: '0x6f1DF96865D09d21e8f3f9a7fbA3b17A11c7C53C', + value: '0x1', + data: '0x1' + }; + + await sendTransaction( + web3Context, + transaction, + DEFAULT_RETURN_FORMAT, + {}, + mockTransactionMiddleware, + ); + + expect(mockTransactionMiddleware.processTransaction).toHaveBeenCalledWith(transaction); + }); + + it('should not call processTransaction when transactionMiddleware is not provided', async () => { + const transaction = { + from: '0x6E599DA0bfF7A6598AC1224E4985430Bf16458a4', + to: '0x6f1DF96865D09d21e8f3f9a7fbA3b17A11c7C53C', + value: '0x1', + data: '0x1' + }; + + await sendTransaction(web3Context, transaction, DEFAULT_RETURN_FORMAT); + + expect(mockTransactionMiddleware.processTransaction).not.toHaveBeenCalled(); + }); +}); \ No newline at end of file diff --git a/packages/web3-eth/test/unit/web3_eth_methods_with_parameters.test.ts b/packages/web3-eth/test/unit/web3_eth_methods_with_parameters.test.ts index c2f017b24cf..76d753bde4b 100644 --- a/packages/web3-eth/test/unit/web3_eth_methods_with_parameters.test.ts +++ b/packages/web3-eth/test/unit/web3_eth_methods_with_parameters.test.ts @@ -17,7 +17,7 @@ along with web3.js. If not, see . import { ethRpcMethods } from 'web3-rpc-methods'; import { TransactionInfoAPI } from 'web3-types'; -import Web3Eth from '../../src/index'; +import Web3Eth, { TransactionMiddleware } from '../../src/index'; import * as rpcMethodWrappers from '../../src/rpc_method_wrappers'; import { getBlockNumberValidData, @@ -63,6 +63,20 @@ describe('web3_eth_methods_with_parameters', () => { web3Eth = new Web3Eth('http://127.0.0.1:8545'); }); + it('should set and unset the transactionMiddleware correctly', () => { + const mockTransactionMiddleware: TransactionMiddleware = { + processTransaction: jest.fn(), + }; + + web3Eth.setTransactionMiddleware(mockTransactionMiddleware); + + expect(web3Eth.getTransactionMiddleware()).toBe(mockTransactionMiddleware); + + web3Eth.setTransactionMiddleware(undefined as any); + + expect(web3Eth.getTransactionMiddleware()).toBeUndefined(); + }); + describe('should call RPC method with expected parameters', () => { describe('only has returnFormat parameter', () => { describe('getHashRate', () => { diff --git a/packages/web3/CHANGELOG.md b/packages/web3/CHANGELOG.md index 896d0d884f0..c66601be9ed 100644 --- a/packages/web3/CHANGELOG.md +++ b/packages/web3/CHANGELOG.md @@ -268,4 +268,10 @@ Documentation: - Updated type `Web3EthInterface.accounts` to includes `privateKeyToAccount`,`privateKeyToAddress`,and `privateKeyToPublicKey` (#6762) -## [Unreleased] \ No newline at end of file +## [Unreleased] + +### Added + +#### web3 + +- Now when existing packages are added in web3, will be avalible for plugins via context. (#7088) \ No newline at end of file diff --git a/tools/web3-plugin-example/CHANGELOG.md b/tools/web3-plugin-example/CHANGELOG.md index 65e4434200c..636ba482bed 100644 --- a/tools/web3-plugin-example/CHANGELOG.md +++ b/tools/web3-plugin-example/CHANGELOG.md @@ -88,4 +88,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Dependencies updated -## [Unreleased] \ No newline at end of file +## [Unreleased] + +### Added + +Transaction middleware (#7088) \ No newline at end of file diff --git a/tools/web3-plugin-example/package.json b/tools/web3-plugin-example/package.json index 3832f5ef30d..2e85b5750ce 100644 --- a/tools/web3-plugin-example/package.json +++ b/tools/web3-plugin-example/package.json @@ -57,6 +57,7 @@ "web3-eth-abi": ">= 4.1.1 < 5", "web3-eth-contract": ">= 4.0.5 < 5", "web3-types": ">= 1.1.1 < 5", - "web3-utils": ">= 4.0.5 < 5" + "web3-utils": ">= 4.0.5 < 5", + "web3-eth": ">= 4.7.0 < 5" } } diff --git a/tools/web3-plugin-example/src/custom_rpc_methods.ts b/tools/web3-plugin-example/src/custom_rpc_methods.ts index ed1c2fbee23..d5ff583ddf5 100644 --- a/tools/web3-plugin-example/src/custom_rpc_methods.ts +++ b/tools/web3-plugin-example/src/custom_rpc_methods.ts @@ -18,7 +18,7 @@ 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'; +import { Web3Middleware } from './request_manager_middleware'; type CustomRpcApi = { custom_rpc_method: () => string; diff --git a/tools/web3-plugin-example/src/middleware.ts b/tools/web3-plugin-example/src/request_manager_middleware.ts similarity index 100% rename from tools/web3-plugin-example/src/middleware.ts rename to tools/web3-plugin-example/src/request_manager_middleware.ts diff --git a/tools/web3-plugin-example/src/transaction_middleware.ts b/tools/web3-plugin-example/src/transaction_middleware.ts new file mode 100644 index 00000000000..d38eec8127b --- /dev/null +++ b/tools/web3-plugin-example/src/transaction_middleware.ts @@ -0,0 +1,38 @@ +/* +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 { TransactionMiddleware, TransactionMiddlewareData } from "web3-eth"; + +// Sample Transaction Middleware +export class Web3TransactionMiddleware implements TransactionMiddleware { + + // eslint-disable-next-line class-methods-use-this + public async processTransaction(transaction: TransactionMiddlewareData, + _options?: { [key: string]: unknown } | undefined): + + Promise { + + // eslint-disable-next-line prefer-const + let txObj = { ...transaction }; + + // Add your logic here for transaction modification + txObj.data = '0x123'; + + return Promise.resolve(txObj); + } + +} diff --git a/tools/web3-plugin-example/src/transaction_middleware_plugin.ts b/tools/web3-plugin-example/src/transaction_middleware_plugin.ts new file mode 100644 index 00000000000..3dd86ed7e26 --- /dev/null +++ b/tools/web3-plugin-example/src/transaction_middleware_plugin.ts @@ -0,0 +1,44 @@ +/* +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 { 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 { Web3TransactionMiddleware } from './transaction_middleware'; + +// Sample Transaction middleware plugin +export class TransactionMiddlewarePlugin extends Web3PluginBase { + public pluginNamespace = 'TransactionsPlugIn'; + public txMiddleware: Web3TransactionMiddleware; + + public constructor() { + super(); + this.txMiddleware = new Web3TransactionMiddleware(); + } + + public link(parentContext: Web3Context): void { + + if (this.txMiddleware){ + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + (parentContext as any).Web3Eth.setTransactionMiddleware(this.txMiddleware); + } + + super.link(parentContext); + } + +} + diff --git a/tools/web3-plugin-example/test/unit/fixtures/transactions_data.ts b/tools/web3-plugin-example/test/unit/fixtures/transactions_data.ts new file mode 100644 index 00000000000..189e2135ae4 --- /dev/null +++ b/tools/web3-plugin-example/test/unit/fixtures/transactions_data.ts @@ -0,0 +1,117 @@ +/* +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 . +*/ + +export const blockMockResult = { + "jsonrpc": "2.0", + "id": "a40a81fa-1f8b-4bb2-a0ad-eef9b6d4636f", + "result": { + "baseFeePerGas": "0x44dab2983", + "blobGasUsed": "0x20000", + "difficulty": "0x0", + "excessBlobGas": "0x1c0000", + "extraData": "0x407273796e636275696c646572", + "gasLimit": "0x1c9c380", + "gasUsed": "0xb7a086", + "hash": "0xf2b1729965179032b17165678a1a212fa31cb008e30f4011ffe8ebdddbd02b95", + "logsBloom": "0xc3a70590c1c62524173d1892e33888067101934dc0891c2c9a898252b6f320215084a48906452960820188d32bba6fb82ec989018a0268603a00a4c6432a11276c9a038c676938eb68bc436c9905a9a1b08d238fb4458f48498215808bec81112e2a3a54869ff22422a8e491093da8a40f601d198417041cd22f799f9048865006e0b069ab049b852442b310396248088145e2810f230f9a44000c6868bc73e9afa8832a8ac92fd609007ac53c0a9cba0645ce298080184624e8040831dbc331f5e618072407050250021b3210e542781183a612d4618c1244000d421a6ca9c01a57e86a085402c55ab413f840a001e7117894d0469e20c2304a9655e344f60d", + "miner": "0x1f9090aae28b8a3dceadf281b0f12828e676c326", + "mixHash": "0x787ab1d511b72df60a705bb4cfc4e92e2f9d203e3e007ae3a0f757425951ca24", + "nonce": "0x0000000000000000", + "number": "0x131ad16", + "parentBeaconBlockRoot": "0x03bbca9fd0c7a0a020de04287f489112c79bc268220e9ff8e18957cd0d5c3cad", + "parentHash": "0xb1d8fa7b8346421d373a6d4c28575155516cea17c12a3df7201170c9e561b38c", + "receiptsRoot": "0x4ec500bdcd761ad505b2a989156c9a9628058d415acc93d800487c7c76308c59", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "size": "0xcb90", + "stateRoot": "0xafbb8743c0a5f4740e322217cb1f2780ee5c57c32bcd04e9256b09efc1a70568", + "timestamp": "0x6661ab8b", + "totalDifficulty": "0xc70d815d562d3cfa955", + "transactions": [ + "0x589956b75d19dbaf9911f246c23d4b3327ef234872ec1931c419041b23eb5b41", + "0x4d3793f20c25979bd329cafdd889ba6be015cfc999acce8642d6e757b5192e93", + "0x5ba5618ca5a14bab50862255dc69726a498346f9832bd0fd1394e8834e56790b", + "0x6df9678f350db7e30afc930b7246bf1c144b9acb7fd1d25d7e107d550ed5a061", + "0xb8f48ff2876cc393725ea4162421754dfb74ff2364a12d4d3de2c6269f1958c7", + "0x2e5cf7c0607025038b6ccd871dc9ce85af686fd5fa2c82e605198af9afa92cca", + "0x307fb855836feff5d8d0969fa4a44d3c6ae31d335da6577f48f9496d6fe9e0b9", + "0x1362bed1aa8a30d28b7b76c35c2a8601b257058beffa9490dcb20de12bcb15b2", + "0x234c7cc346c204022b2e5ead6d2e8c02317aeb0ec5ca82bd97c2b5d5e59a280b", + ], + "transactionsRoot": "0xc21a4d667b5f841538430b1e2c002c598f2178628ad1d61ea2fda462d1216607", + "uncles": [], + "withdrawals": [ + { + "address": "0xea97dc2523c0479484076660f150833e264c41e9", + "amount": "0x11b6d8c", + "index": "0x2dbe454", + "validatorIndex": "0x10f646" + }, + { + "address": "0xb3e84b6c6409826dc45432b655d8c9489a14a0d7", + "amount": "0x11b4ce2", + "index": "0x2dbe455", + "validatorIndex": "0x10f647" + }, + { + "address": "0x7e2a2fa2a064f693f0a55c5639476d913ff12d05", + "amount": "0x11ad733", + "index": "0x2dbe456", + "validatorIndex": "0x10f648" + }, + + ], + "withdrawalsRoot": "0x2914fa2f5ed93880ed45b58e8f6d14f20c645988400d83c59109964e2053fe1a" + } +}; + +export const receiptMockResult = { + "jsonrpc": "2.0", + "id": 1, + "result": { + "blockHash": "0xf4ad699b98241caf3930779b7d919a77f1727e67cef6ed1ce2a4c655ba812d54", + "blockNumber": "0x131ad35", + // eslint-disable-next-line no-null/no-null + "contractAddress": null, + "cumulativeGasUsed": "0x8cae7a", + "effectiveGasPrice": "0x4c9bc2d65", + "from": "0xab6fd3a7c6ce9db945889cd018e028e055f3bc2e", + "gasUsed": "0xa145", + "logs": [ + { + "address": "0xdac17f958d2ee523a2206206994597c13d831ec7", + "blockHash": "0xf4ad699b98241caf3930779b7d919a77f1727e67cef6ed1ce2a4c655ba812d54", + "blockNumber": "0x131ad35", + "data": "0x000000000000000000000000000000000000000000000000000000000016e360", + "logIndex": "0xdf", + "removed": false, + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x000000000000000000000000ab6fd3a7c6ce9db945889cd018e028e055f3bc2e", + "0x00000000000000000000000051112f9f08a2174fe3fc96aad8f07e82d1cccd00" + ], + "transactionHash": "0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f", + "transactionIndex": "0x82" + } + ], + "logsBloom": "0x00000000000000000000000002000000000000000000000000000000004000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000400000000000100000000000000000000000000080000000000000000000040000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000400000000000000000000000", + "status": "0x1", + "to": "0xdac17f958d2ee523a2206206994597c13d831ec7", + "transactionHash": "0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f", + "transactionIndex": "0x82", + "type": "0x2" + } +}; \ No newline at end of file diff --git a/tools/web3-plugin-example/test/unit/middleware.test.ts b/tools/web3-plugin-example/test/unit/request_manager_middleware.test.ts similarity index 100% rename from tools/web3-plugin-example/test/unit/middleware.test.ts rename to tools/web3-plugin-example/test/unit/request_manager_middleware.test.ts diff --git a/tools/web3-plugin-example/test/unit/transaction_middleware.test.ts b/tools/web3-plugin-example/test/unit/transaction_middleware.test.ts new file mode 100644 index 00000000000..2009e028283 --- /dev/null +++ b/tools/web3-plugin-example/test/unit/transaction_middleware.test.ts @@ -0,0 +1,76 @@ +/* +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, Transaction } from 'web3'; +import { TransactionMiddlewarePlugin } from '../../src/transaction_middleware_plugin'; +import { blockMockResult, receiptMockResult } from './fixtures/transactions_data'; + +describe('Transaction Middleware', () => { + + // This will allow Transaction modification before signing and gas estimations + it('should modify transaction before signing', async () => { + const web3 = new Web3('http://127.0.0.1:8545'); + const plugin = new TransactionMiddlewarePlugin(); + + /// Mock block starts - Mock web3 internal calls for test + let blockNum = 1000; + + web3.requestManager.send = jest.fn(async (request) => { + blockNum += 1; + + if(request.method === 'eth_getBlockByNumber'){ + + return Promise.resolve(blockMockResult.result); + } + if(request.method === 'eth_call'){ + + return Promise.resolve("0x"); + } + if(request.method === 'eth_blockNumber'){ + + return Promise.resolve(blockNum.toString(16)); + } + if(request.method === 'eth_sendTransaction'){ + + // Test that middleware modified transaction + // eslint-disable-next-line jest/no-conditional-expect + expect((request.params as any)[0].data).toBe("0x123"); + + return Promise.resolve("0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f"); + } + if (request.method === 'eth_getTransactionReceipt') { + return Promise.resolve(receiptMockResult.result); + } + + return Promise.resolve("Unknown Request" as any); + }); + + /// Mock block ends here + + web3.registerPlugin(plugin); + + const transaction: Transaction = { + from: '0x6E599DA0bfF7A6598AC1224E4985430Bf16458a4', + to: '0x6f1DF96865D09d21e8f3f9a7fbA3b17A11c7C53C', + value: '0x1', + data: '0x1' + }; + + await web3.eth.sendTransaction(transaction as any); + + }); +});