From e29deeac2bb9705d70c839cd825bc34a93cde1b6 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 18 Apr 2024 00:13:53 -0400 Subject: [PATCH 01/32] Release/4.8.0 (#6982) * update changelog * update version to 4.8.0 * update e2e tests * update * update * revert --- CHANGELOG.md | 44 ++++++++++++++++++++++++- packages/web3-eth-abi/CHANGELOG.md | 8 ++++- packages/web3-eth-abi/package.json | 8 ++--- packages/web3-eth-accounts/CHANGELOG.md | 7 +++- packages/web3-eth-accounts/package.json | 8 ++--- packages/web3-eth-contract/CHANGELOG.md | 4 ++- packages/web3-eth-contract/package.json | 12 +++---- packages/web3-eth/CHANGELOG.md | 7 ++++ packages/web3-eth/package.json | 12 +++---- packages/web3-types/CHANGELOG.md | 1 + packages/web3-types/package.json | 2 +- packages/web3-utils/CHANGELOG.md | 6 ++-- packages/web3-utils/package.json | 4 +-- packages/web3/CHANGELOG.md | 42 +++++++++++++++++++++++ packages/web3/package.json | 14 ++++---- packages/web3/src/version.ts | 2 +- 16 files changed, 144 insertions(+), 37 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 34609aba1c0..c007375e541 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2405,4 +2405,46 @@ If there are any bugs, improvements, optimizations or any new feature proposal f - fixed erroneous parsing of big numbers in the `toNumber(...)` function (#6880) -## [Unreleased] \ No newline at end of file +## [4.8.0] + +### Changed + +#### web3-eth-abi + +- Dependencies updated + +#### web3-eth-accounts + +- Dependencies updated + +### Fixed + +#### web3-eth-contract + +- Fix an issue with smart contract function overloading (#6922) + +#### web3-utils + +- fixed toHex incorrectly hexing Uint8Arrays and Buffer (#6957) +- fixed isUint8Array not returning true for Buffer (#6957) + + +### Added + +#### web3-eth-contract + +- Added a console warning in case of an ambiguous call to a solidity method with parameter overloading (#6942) +- Added contract.deploy(...).decodeData(...) and contract.decodeMethodData(...) that decode data based on the ABI (#6950) + +#### web3-eth + +- method `getBlock` now includes properties of eip 4844, 4895, 4788 when returning block (#6933) +- update type `withdrawalsSchema`, `blockSchema` and `blockHeaderSchema` schemas to include properties of eip 4844, 4895, 4788 (#6933) + + +#### web3-types + +- Added `signature` to type `AbiFunctionFragment` (#6922) +- update type `Withdrawals`, `block` and `BlockHeaderOutput` to include properties of eip 4844, 4895, 4788 (#6933) + +## [Unreleased] diff --git a/packages/web3-eth-abi/CHANGELOG.md b/packages/web3-eth-abi/CHANGELOG.md index 6fa52af5287..47f57f4d2a4 100644 --- a/packages/web3-eth-abi/CHANGELOG.md +++ b/packages/web3-eth-abi/CHANGELOG.md @@ -164,4 +164,10 @@ Documentation: - Fixed an issue with detecting Uint8Array (#6486) -## [Unreleased] +## [4.2.1] + +### Changed + +- Dependencies updated + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-eth-abi/package.json b/packages/web3-eth-abi/package.json index 47802dc53c1..e24baf7117b 100644 --- a/packages/web3-eth-abi/package.json +++ b/packages/web3-eth-abi/package.json @@ -1,6 +1,6 @@ { "name": "web3-eth-abi", - "version": "4.2.0", + "version": "4.2.1", "description": "Web3 module encode and decode EVM in/output.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -44,9 +44,9 @@ "dependencies": { "abitype": "0.7.1", "web3-errors": "^1.1.4", - "web3-types": "^1.3.1", - "web3-utils": "^4.1.1", - "web3-validator": "^2.0.4" + "web3-types": "^1.6.0", + "web3-utils": "^4.2.3", + "web3-validator": "^2.0.5" }, "devDependencies": { "@humeris/espresso-shot": "^4.0.0", diff --git a/packages/web3-eth-accounts/CHANGELOG.md b/packages/web3-eth-accounts/CHANGELOG.md index 05682b29954..30514ec972d 100644 --- a/packages/web3-eth-accounts/CHANGELOG.md +++ b/packages/web3-eth-accounts/CHANGELOG.md @@ -156,5 +156,10 @@ Documentation: - Send Transaction config used to be ignored if the passed `common` did not have a `copy()` and the `chainId` was not provided (#6663) - Fixed an issue with detecting Uint8Array (#6486) -## [Unreleased] +## [4.1.2] +### Changed + +- Dependencies updated + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-eth-accounts/package.json b/packages/web3-eth-accounts/package.json index 1906d06b599..06416a260b2 100644 --- a/packages/web3-eth-accounts/package.json +++ b/packages/web3-eth-accounts/package.json @@ -1,6 +1,6 @@ { "name": "web3-eth-accounts", - "version": "4.1.1", + "version": "4.1.2", "description": "Package for managing Ethereum accounts and signing", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -62,8 +62,8 @@ "crc-32": "^1.2.2", "ethereum-cryptography": "^2.0.0", "web3-errors": "^1.1.4", - "web3-types": "^1.3.1", - "web3-utils": "^4.1.1", - "web3-validator": "^2.0.4" + "web3-types": "^1.6.0", + "web3-utils": "^4.2.3", + "web3-validator": "^2.0.5" } } diff --git a/packages/web3-eth-contract/CHANGELOG.md b/packages/web3-eth-contract/CHANGELOG.md index 3aa8afa88e8..2eb9a5ca676 100644 --- a/packages/web3-eth-contract/CHANGELOG.md +++ b/packages/web3-eth-contract/CHANGELOG.md @@ -370,7 +370,7 @@ Documentation: - Types `ContractDeploySend`, `ContractMethodSend`, `Web3PromiEvent` was exported (#6883) -## [Unreleased] +## [4.4.0] ### Fixed @@ -380,3 +380,5 @@ Documentation: - Added a console warning in case of an ambiguous call to a solidity method with parameter overloading (#6942) - Added contract.deploy(...).decodeData(...) and contract.decodeMethodData(...) that decode data based on the ABI (#6950) + +## [Unreleased] diff --git a/packages/web3-eth-contract/package.json b/packages/web3-eth-contract/package.json index 0ccf9536c56..f70734cc090 100644 --- a/packages/web3-eth-contract/package.json +++ b/packages/web3-eth-contract/package.json @@ -1,6 +1,6 @@ { "name": "web3-eth-contract", - "version": "4.3.0", + "version": "4.4.0", "description": "Web3 module to interact with Ethereum smart contracts.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -47,10 +47,10 @@ "dependencies": { "web3-core": "^4.3.2", "web3-errors": "^1.1.4", - "web3-eth": "^4.5.0", - "web3-eth-abi": "^4.2.0", - "web3-types": "^1.5.0", - "web3-utils": "^4.2.2", + "web3-eth": "^4.6.0", + "web3-eth-abi": "^4.2.1", + "web3-types": "^1.6.0", + "web3-utils": "^4.2.3", "web3-validator": "^2.0.5" }, "devDependencies": { @@ -68,7 +68,7 @@ "prettier": "^2.7.1", "ts-jest": "^29.1.1", "typescript": "^4.7.4", - "web3-eth-accounts": "^4.1.1", + "web3-eth-accounts": "^4.1.2", "web3-providers-ws": "^4.0.7" } } diff --git a/packages/web3-eth/CHANGELOG.md b/packages/web3-eth/CHANGELOG.md index 90ad4805704..b4b937ce6ae 100644 --- a/packages/web3-eth/CHANGELOG.md +++ b/packages/web3-eth/CHANGELOG.md @@ -225,4 +225,11 @@ Documentation: - Added `eth.getMaxPriorityFeePerGas` method (#6748) +## [4.6.0] + +### Added + +- method `getBlock` now includes properties of eip 4844, 4895, 4788 when returning block (#6933) +- update type `withdrawalsSchema`, `blockSchema` and `blockHeaderSchema` schemas to include properties of eip 4844, 4895, 4788 (#6933) + ## [Unreleased] \ No newline at end of file diff --git a/packages/web3-eth/package.json b/packages/web3-eth/package.json index 7b53c9df5ab..565de7fed54 100644 --- a/packages/web3-eth/package.json +++ b/packages/web3-eth/package.json @@ -1,6 +1,6 @@ { "name": "web3-eth", - "version": "4.5.0", + "version": "4.6.0", "description": "Web3 module to interact with the Ethereum blockchain and smart contracts.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -65,13 +65,13 @@ "setimmediate": "^1.0.5", "web3-core": "^4.3.2", "web3-errors": "^1.1.4", - "web3-eth-abi": "^4.2.0", - "web3-eth-accounts": "^4.1.1", + "web3-eth-abi": "^4.2.1", + "web3-eth-accounts": "^4.1.2", "web3-net": "^4.0.7", "web3-providers-ws": "^4.0.7", "web3-rpc-methods": "^1.2.0", - "web3-types": "^1.5.0", - "web3-utils": "^4.2.1", - "web3-validator": "^2.0.4" + "web3-types": "^1.6.0", + "web3-utils": "^4.2.3", + "web3-validator": "^2.0.5" } } diff --git a/packages/web3-types/CHANGELOG.md b/packages/web3-types/CHANGELOG.md index 7d1e3042b96..b3a8628c9a5 100644 --- a/packages/web3-types/CHANGELOG.md +++ b/packages/web3-types/CHANGELOG.md @@ -194,3 +194,4 @@ Documentation: ### Added - Added `signature` to type `AbiFunctionFragment` (#6922) +- update type `Withdrawals`, `block` and `BlockHeaderOutput` to include properties of eip 4844, 4895, 4788 (#6933) \ No newline at end of file diff --git a/packages/web3-types/package.json b/packages/web3-types/package.json index a254eb19f19..c89ae9c5b9f 100644 --- a/packages/web3-types/package.json +++ b/packages/web3-types/package.json @@ -1,6 +1,6 @@ { "name": "web3-types", - "version": "1.5.0", + "version": "1.6.0", "description": "Provide the common data structures and interfaces for web3 modules.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", diff --git a/packages/web3-utils/CHANGELOG.md b/packages/web3-utils/CHANGELOG.md index c0ab0335bed..0d18cd22d3b 100644 --- a/packages/web3-utils/CHANGELOG.md +++ b/packages/web3-utils/CHANGELOG.md @@ -205,9 +205,11 @@ Documentation: - fixed erroneous parsing of big numbers in the `toNumber(...)` function (#6880) -## [Unreleased] +## [4.2.3] ### Fixed - fixed toHex incorrectly hexing Uint8Arrays and Buffer (#6957) -- fixed isUint8Array not returning true for Buffer \ No newline at end of file +- fixed isUint8Array not returning true for Buffer (#6957) + +## [Unreleased] diff --git a/packages/web3-utils/package.json b/packages/web3-utils/package.json index 33be7953d0f..c909a1ec735 100644 --- a/packages/web3-utils/package.json +++ b/packages/web3-utils/package.json @@ -1,7 +1,7 @@ { "name": "web3-utils", "sideEffects": false, - "version": "4.2.2", + "version": "4.2.3", "description": "Collection of utility functions used in web3.js.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -66,7 +66,7 @@ "ethereum-cryptography": "^2.0.0", "eventemitter3": "^5.0.1", "web3-errors": "^1.1.4", - "web3-types": "^1.5.0", + "web3-types": "^1.6.0", "web3-validator": "^2.0.5" } } diff --git a/packages/web3/CHANGELOG.md b/packages/web3/CHANGELOG.md index d46d48112b7..5b7242c7ebb 100644 --- a/packages/web3/CHANGELOG.md +++ b/packages/web3/CHANGELOG.md @@ -220,4 +220,46 @@ Documentation: - fixed erroneous parsing of big numbers in the `toNumber(...)` function (#6880) +## [4.8.0] + +### Changed + +#### web3-eth-abi + +- Dependencies updated + +#### web3-eth-accounts + +- Dependencies updated + +### Fixed + +#### web3-eth-contract + +- Fix an issue with smart contract function overloading (#6922) + +#### web3-utils + +- fixed toHex incorrectly hexing Uint8Arrays and Buffer (#6957) +- fixed isUint8Array not returning true for Buffer (#6957) + + +### Added + +#### web3-eth-contract + +- Added a console warning in case of an ambiguous call to a solidity method with parameter overloading (#6942) +- Added contract.deploy(...).decodeData(...) and contract.decodeMethodData(...) that decode data based on the ABI (#6950) + +#### web3-eth + +- method `getBlock` now includes properties of eip 4844, 4895, 4788 when returning block (#6933) +- update type `withdrawalsSchema`, `blockSchema` and `blockHeaderSchema` schemas to include properties of eip 4844, 4895, 4788 (#6933) + + +#### web3-types + +- Added `signature` to type `AbiFunctionFragment` (#6922) +- update type `Withdrawals`, `block` and `BlockHeaderOutput` to include properties of eip 4844, 4895, 4788 (#6933) + ## [Unreleased] \ No newline at end of file diff --git a/packages/web3/package.json b/packages/web3/package.json index 5d20596abe8..5368b3e1bfd 100644 --- a/packages/web3/package.json +++ b/packages/web3/package.json @@ -1,6 +1,6 @@ { "name": "web3", - "version": "4.7.0", + "version": "4.8.0", "description": "Ethereum JavaScript API", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -88,10 +88,10 @@ "dependencies": { "web3-core": "^4.3.2", "web3-errors": "^1.1.4", - "web3-eth": "^4.5.0", - "web3-eth-abi": "^4.2.0", - "web3-eth-accounts": "^4.1.1", - "web3-eth-contract": "^4.3.0", + "web3-eth": "^4.6.0", + "web3-eth-abi": "^4.2.1", + "web3-eth-accounts": "^4.1.2", + "web3-eth-contract": "^4.4.0", "web3-eth-ens": "^4.2.0", "web3-eth-iban": "^4.0.7", "web3-eth-personal": "^4.0.8", @@ -99,8 +99,8 @@ "web3-providers-http": "^4.1.0", "web3-providers-ws": "^4.0.7", "web3-rpc-methods": "^1.2.0", - "web3-types": "^1.5.0", - "web3-utils": "^4.2.2", + "web3-types": "^1.6.0", + "web3-utils": "^4.2.3", "web3-validator": "^2.0.5" } } diff --git a/packages/web3/src/version.ts b/packages/web3/src/version.ts index c6e779f738c..8e4910766d8 100644 --- a/packages/web3/src/version.ts +++ b/packages/web3/src/version.ts @@ -1 +1 @@ -/* eslint-disable header/header */ export const Web3PkgInfo = { version: '4.7.0' }; +/* eslint-disable header/header */ export const Web3PkgInfo = { version: '4.8.0' }; From 1ab7a6b8aa46d5984d41fd69c78103fcf1f0973b Mon Sep 17 00:00:00 2001 From: Junaid <86780488+jdevcs@users.noreply.github.com> Date: Thu, 18 Apr 2024 13:42:08 +0200 Subject: [PATCH 02/32] web3 middleware (#6951) * RequestManagerMiddleware * adding in context * request manager support * tests * lint fix * lint fix * sample middleware * middleware in sample plugin * middleware test with plugin * lint fix * updated Web3Middleware * extensible middleware * test update * lint update * update * lint fix --- packages/web3-core/src/types.ts | 17 ++- packages/web3-core/src/web3_context.ts | 10 +- .../web3-core/src/web3_request_manager.ts | 26 +++- .../web3-core/test/unit/web3_context.test.ts | 15 ++ .../web3_middleware_request_manager.test.ts | 144 ++++++++++++++++++ .../src/custom_rpc_methods.ts | 21 +++ tools/web3-plugin-example/src/middleware.ts | 61 ++++++++ .../test/unit/middleware.test.ts | 66 ++++++++ 8 files changed, 356 insertions(+), 4 deletions(-) create mode 100644 packages/web3-core/test/unit/web3_middleware_request_manager.test.ts create mode 100644 tools/web3-plugin-example/src/middleware.ts create mode 100644 tools/web3-plugin-example/test/unit/middleware.test.ts diff --git a/packages/web3-core/src/types.ts b/packages/web3-core/src/types.ts index 3f4e66d1f52..890a5e20c5a 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,18 @@ export interface ExtensionObject { property?: string; methods: Method[]; } + +export interface RequestManagerMiddleware { + processRequest< + AnotherMethod extends Web3APIMethod + >( + request: Web3APIRequest, + options?: { [key: string]: unknown }): Promise>; + + processResponse< + AnotherMethod extends Web3APIMethod, + ResponseType = Web3APIReturnType> + ( + response: JsonRpcResponse, + options?: { [key: string]: unknown }): Promise>; + } \ 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 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. */ diff --git a/packages/web3-core/src/web3_request_manager.ts b/packages/web3-core/src/web3_request_manager.ts index 3c6cabd0182..dc12d919fd0 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,17 @@ export class Web3RequestManager< Method extends Web3APIMethod, ResponseType = Web3APIReturnType, >(request: Web3APIRequest): Promise { - const response = await this._sendRequest(request); + + let requestObj = {...request}; + + if (!isNullish(this.middleware)) + requestObj = await this.middleware.processRequest(requestObj); + + let response = await this._sendRequest(requestObj); + + if (!isNullish(this.middleware)) + response = await this.middleware.processResponse(response); + if (jsonRpc.isResponseWithResult(response)) { return response.result; } diff --git a/packages/web3-core/test/unit/web3_context.test.ts b/packages/web3-core/test/unit/web3_context.test.ts index 3c433f7259a..186122df54e 100644 --- a/packages/web3-core/test/unit/web3_context.test.ts +++ b/packages/web3-core/test/unit/web3_context.test.ts @@ -18,8 +18,10 @@ 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 { 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'); + + const 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..d240831d91b --- /dev/null +++ b/packages/web3-core/test/unit/web3_middleware_request_manager.test.ts @@ -0,0 +1,144 @@ +/* +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'; + +class Web3Middleware implements RequestManagerMiddleware { + + // eslint-disable-next-line class-methods-use-this + public async processRequest>( + request: Web3APIRequest + ): Promise> { + // Implement the processRequest logic here + + let requestObj = {...request}; + if (request.method === 'eth_call' && Array.isArray(request.params)) { + requestObj = { + ...requestObj, + params: [...request.params, '0x0', '0x1'], + }; + } + + return Promise.resolve(requestObj); + } + + // eslint-disable-next-line class-methods-use-this + public async processResponse< + Method extends Web3APIMethod, + ResponseType = Web3APIReturnType + >( + response: JsonRpcResponse + ): Promise> { + + let responseObj = {...response}; + if (!jsonRpc.isBatchResponse(responseObj) && responseObj.id === 1) { + responseObj = { + ...responseObj, + result: '0x6a756e616964' as any, + }; + } + + return Promise.resolve(responseObj); + } +} + +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', () => { + const web3RequestManager1: Web3RequestManager = new Web3RequestManager(undefined, true, requestManagerMiddleware); + + expect(web3RequestManager1.middleware).toBeDefined(); + expect(web3RequestManager1.middleware).toEqual(requestManagerMiddleware); + }); + + it('should set requestManagerMiddleware via set method', () => { + + const middleware2: RequestManagerMiddleware = new Web3Middleware(); + const web3RequestManager2: Web3RequestManager = 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 ); + + 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).toBe('0x6a756e616964'); + + expect(mockSendRequest).toHaveBeenCalledWith({ + ...request, + params: [...request.params, '0x0', '0x1'], + }); + + }); +}); diff --git a/tools/web3-plugin-example/src/custom_rpc_methods.ts b/tools/web3-plugin-example/src/custom_rpc_methods.ts index 101816a9c27..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,8 @@ 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 = { custom_rpc_method: () => string; @@ -25,6 +27,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({ @@ -39,6 +59,7 @@ export class CustomRpcMethodsPlugin extends Web3PluginBase { params: [parameter1, parameter2], }); } + } // Module Augmentation diff --git a/tools/web3-plugin-example/src/middleware.ts b/tools/web3-plugin-example/src/middleware.ts new file mode 100644 index 00000000000..3af435fd025 --- /dev/null +++ b/tools/web3-plugin-example/src/middleware.ts @@ -0,0 +1,61 @@ +/* +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"; + +export class Web3Middleware implements RequestManagerMiddleware { + + // eslint-disable-next-line class-methods-use-this + public async processRequest>( + request: Web3APIRequest + ): Promise> { + + // add your custom logic here for processing requests + 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(reqObj); + } + + // eslint-disable-next-line class-methods-use-this + public async processResponse< + Method extends Web3APIMethod, + ResponseType = Web3APIReturnType + >( + response: JsonRpcResponse + ): Promise> { + + // 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(resObj); + } +} \ 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/middleware.test.ts new file mode 100644 index 00000000000..717ddc8856d --- /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 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); + + // 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).toBe('0x6a756e616964'); // result modified by response processor , so its 0x6a756e616964 instead 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 93296c2e0ec299c506591d790236e5dd96291757 Mon Sep 17 00:00:00 2001 From: Oleksii Kosynskyi Date: Thu, 18 Apr 2024 10:59:51 -0400 Subject: [PATCH 03/32] Add default return format to the context (#6947) * add default return format * fix ens tests * add format tests * lint fix * add types and docs * fix * fix * add changelog * add changelog * fix tests * fix * fix * fix * fix * fix changelog * fix default * add estimate gas test * add guide to upgrade from 1.x * fix change log * remove changelogs * fix --- CHANGELOG.md | 75 ++++++--- docs/docs/guides/web3_config/index.md | 45 ++++- .../guides/web3_upgrade_guide/1.x/index.md | 3 + packages/web3-core/CHANGELOG.md | 5 +- packages/web3-core/src/web3_config.ts | 20 ++- .../__snapshots__/web3_context.test.ts.snap | 4 + .../web3-core/test/unit/web3_config.test.ts | 2 + .../web3-eth-accounts/test/config/setup.js | 2 +- packages/web3-eth-contract/CHANGELOG.md | 21 ++- packages/web3-eth-contract/src/contract.ts | 152 +++++++++++------ .../test/integration/contract_deploy.test.ts | 57 +++++-- packages/web3-eth-ens/CHANGELOG.md | 5 +- packages/web3-eth-ens/src/ens.ts | 52 +++--- .../test/integration/ens.events.test.ts | 14 +- .../web3-eth-ens/test/integration/ens.test.ts | 14 +- .../test/integration/resolver.test.ts | 18 +- .../web3-eth-ens/test/integration/setup.js | 2 +- packages/web3-eth/CHANGELOG.md | 12 +- packages/web3-eth/src/rpc_method_wrappers.ts | 156 ++++++++++++++---- .../web3-eth/src/utils/get_revert_reason.ts | 9 +- .../web3-eth/src/utils/transaction_builder.ts | 5 +- packages/web3-eth/src/web3_eth.ts | 96 +++++++---- .../web3-eth/test/integration/format.test.ts | 112 +++++++++++++ packages/web3-eth/test/integration/helper.ts | 14 +- .../web3-eth/test/integration/rpc.test.ts | 33 ++-- packages/web3-net/CHANGELOG.md | 5 +- packages/web3-net/src/net.ts | 40 ++--- packages/web3-types/CHANGELOG.md | 2 +- packages/web3-types/src/data_format_types.ts | 5 +- packages/web3-utils/CHANGELOG.md | 12 +- packages/web3-utils/src/formatter.ts | 11 +- packages/web3/src/web3.ts | 47 +++--- .../web3/test/integration/web3.format.test.ts | 107 ++++++++++++ scripts/system_tests_utils.ts | 11 ++ 34 files changed, 845 insertions(+), 323 deletions(-) create mode 100644 packages/web3-eth/test/integration/format.test.ts create mode 100644 packages/web3/test/integration/web3.format.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index c007375e541..dcedf476330 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2120,7 +2120,7 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3-eth - Ensure provider.supportsSubscriptions exists before watching by subscription (#6440) -- Fixed param sent to `checkRevertBeforeSending` in `sendSignedTransaction` +- Fixed param sent to `checkRevertBeforeSending` in `sendSignedTransaction` - Fixed `defaultTransactionBuilder` for value issue (#6509) #### web3-eth-abi @@ -2129,7 +2129,7 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3-eth-accounts -- Fixed `recover` function, `v` will be normalized to value 0,1 (#6344) +- Fixed `recover` function, `v` will be normalized to value 0,1 (#6344) #### web3-providers-http @@ -2252,7 +2252,7 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3-eth-contract -- Will populate `data` for transactions in contract for metamask provider instead of `input` (#6534) +- Will populate `data` for transactions in contract for metamask provider instead of `input` (#6534) ## [4.3.0] @@ -2260,19 +2260,18 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3-core -- Web3config `contractDataInputFill` has been defaulted to `data`, instead of `input`. (#6622) +- Web3config `contractDataInputFill` has been defaulted to `data`, instead of `input`. (#6622) #### web3-eth-contracts -- By default, contracts will fill `data` instead of `input` within method calls (#6622) +- By default, contracts will fill `data` instead of `input` within method calls (#6622) ### Added - #### web3-utils - `SocketProvider` now contains public function `getPendingRequestQueueSize`, `getSentRequestsQueueSize` and `clearQueues` (#6479) -- Added `safeDisconnect` as a `SocketProvider` method to disconnect only when request queue size and send request queue size is 0 (#6479) +- Added `safeDisconnect` as a `SocketProvider` method to disconnect only when request queue size and send request queue size is 0 (#6479) - Add `isContractInitOptions` method (#6555) #### web3 @@ -2305,7 +2304,7 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3-eth-contract -- Allow the `deploy` function to accept parameters, even when no ABI was provided to the `Contract`(#6635) +- Allow the `deploy` function to accept parameters, even when no ABI was provided to the `Contract`(#6635) #### web3 @@ -2324,8 +2323,8 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3-eth-contract -- Fix and error that happen when trying to get past events by calling `contract.getPastEvents` or `contract.events.allEvents()`, if there is no matching events. (#6647) -- Fixed: The Contract is not using the context wallet passed if context was passed at constructor. (#6661) +- Fix and error that happen when trying to get past events by calling `contract.getPastEvents` or `contract.events.allEvents()`, if there is no matching events. (#6647) +- Fixed: The Contract is not using the context wallet passed if context was passed at constructor. (#6661) #### web3-utils @@ -2347,7 +2346,7 @@ If there are any bugs, improvements, optimizations or any new feature proposal f - Adds missing exported type `AbiItem` from 1.x to v4 for compatabiltiy (#6678) -### Changed +### Changed #### web3 @@ -2359,7 +2358,7 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3 -- Added EIP-6963 utility function `requestEIP6963Providers` for multi provider discovery +- Added EIP-6963 utility function `requestEIP6963Providers` for multi provider discovery #### web3-eth @@ -2393,17 +2392,17 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3-eth-ens -- Added function getText and getName in ENS and resolver classes (#6914) +- Added function getText and getName in ENS and resolver classes (#6914) ### fixed #### web3-validator -- Multi-dimensional arrays(with a fix length) are now handled properly when parsing ABIs (#6798) +- Multi-dimensional arrays(with a fix length) are now handled properly when parsing ABIs (#6798) #### web3-utils -- fixed erroneous parsing of big numbers in the `toNumber(...)` function (#6880) +- fixed erroneous parsing of big numbers in the `toNumber(...)` function (#6880) ## [4.8.0] @@ -2421,30 +2420,60 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3-eth-contract -- Fix an issue with smart contract function overloading (#6922) +- Fix an issue with smart contract function overloading (#6922) #### web3-utils -- fixed toHex incorrectly hexing Uint8Arrays and Buffer (#6957) -- fixed isUint8Array not returning true for Buffer (#6957) - +- fixed toHex incorrectly hexing Uint8Arrays and Buffer (#6957) +- fixed isUint8Array not returning true for Buffer (#6957) ### Added #### web3-eth-contract -- Added a console warning in case of an ambiguous call to a solidity method with parameter overloading (#6942) -- Added contract.deploy(...).decodeData(...) and contract.decodeMethodData(...) that decode data based on the ABI (#6950) +- Added a console warning in case of an ambiguous call to a solidity method with parameter overloading (#6942) +- Added contract.deploy(...).decodeData(...) and contract.decodeMethodData(...) that decode data based on the ABI (#6950) #### web3-eth -- method `getBlock` now includes properties of eip 4844, 4895, 4788 when returning block (#6933) +- method `getBlock` now includes properties of eip 4844, 4895, 4788 when returning block (#6933) - update type `withdrawalsSchema`, `blockSchema` and `blockHeaderSchema` schemas to include properties of eip 4844, 4895, 4788 (#6933) - #### web3-types - Added `signature` to type `AbiFunctionFragment` (#6922) - update type `Withdrawals`, `block` and `BlockHeaderOutput` to include properties of eip 4844, 4895, 4788 (#6933) ## [Unreleased] + +### Added + +#### web3-core + +- `defaultReturnFormat` was added to the configuration options. (#6947) + +#### web3-eth + +- `defaultReturnFormat` was added to all methods that have `ReturnType` param. (#6947) + +#### web3-eth-contract + +- `defaultReturnFormat` was added to all methods that have `ReturnType` param. (#6947) + +#### web3-eth-ens + +- `defaultReturnFormat` was added to all methods that have `ReturnType` param. (#6947) + +#### web3-net + +- `defaultReturnFormat` was added to all methods that have `ReturnType` param. (#6947) + +#### web3-types + +- Added `signature` to type `AbiFunctionFragment` (#6922) +- update type `Withdrawals`, `block` and `BlockHeaderOutput` to include properties of eip 4844, 4895, 4788 (#6933) + +### Fixed + +#### web3-validator + diff --git a/docs/docs/guides/web3_config/index.md b/docs/docs/guides/web3_config/index.md index ea061762968..f6d041b6b15 100644 --- a/docs/docs/guides/web3_config/index.md +++ b/docs/docs/guides/web3_config/index.md @@ -27,6 +27,7 @@ There is list of configuration params that can be set for modifying behavior of - [defaultHardfork](/api/web3-core/class/Web3Config#defaultHardfork) - [defaultCommon](/api/web3-core/class/Web3Config#defaultCommon) - [defaultTransactionType](/api/web3-core/class/Web3Config#defaultTransactionType) +- [defaultReturnFormat](/api/web3-core/class/Web3Config#defaultReturnFormat) ## Global level Config @@ -198,4 +199,46 @@ console.log(web3.getContextObject().config) transactionPollingTimeout: 750000, ... */ -``` \ No newline at end of file +``` + + +### defaultReturnFormat +The `defaultReturnFormat` allows users to specify the format in which certain types of data should be returned by default. It is a configuration parameter that can be set at the global level and affects how data is returned across the entire library. +```ts +import { Web3, FMT_NUMBER, FMT_BYTES } from 'web3'; + +web3.defaultReturnFormat = { + number: FMT_NUMBER.BIGINT, + bytes: FMT_BYTES.HEX, +}; + +``` +:::info +The `defaultReturnFormat` can be configured both globally and at the package level: +```ts +import { Web3Eth, FMT_NUMBER, FMT_BYTES } from 'web3-eth'; + +const eth = new Web3Eth() +eth.defaultReturnFormat = { + number: FMT_NUMBER.BIGINT, + bytes: FMT_BYTES.HEX, +}; + +``` +::: +#### All available choices for numeric data: +```ts +export enum FMT_NUMBER { + NUMBER = 'NUMBER_NUMBER', + HEX = 'NUMBER_HEX', + STR = 'NUMBER_STR', + BIGINT = 'NUMBER_BIGINT', +} +``` +#### All available choices for bytes data: +```ts +export enum FMT_BYTES { + HEX = 'BYTES_HEX', + UINT8ARRAY = 'BYTES_UINT8ARRAY', +} +``` diff --git a/docs/docs/guides/web3_upgrade_guide/1.x/index.md b/docs/docs/guides/web3_upgrade_guide/1.x/index.md index 52530284ed2..b375a63974f 100644 --- a/docs/docs/guides/web3_upgrade_guide/1.x/index.md +++ b/docs/docs/guides/web3_upgrade_guide/1.x/index.md @@ -79,6 +79,9 @@ It will not have: - `givenProvider` default value is `undefined` instead of `null` - `currentProvider` default value is `undefined` instead of `null` (if web3 is instantiated without a provider) +:::warning +In version 4.x, all numbers return as BigInt instead of string or number, which constitutes a breaking change for users accustomed to handling numbers as string or number in their code. For instance, web3.eth.getBalance will now return BigInt instead of string or number. If you wish to retain numbers as number or string, you can refer to [this guide](/guides/web3_config/#defaultreturnformat) on how to set returning types in web3js 4.x. +::: ### Web3 BatchRequest ```ts diff --git a/packages/web3-core/CHANGELOG.md b/packages/web3-core/CHANGELOG.md index 39d574bcd43..31f03f1aa62 100644 --- a/packages/web3-core/CHANGELOG.md +++ b/packages/web3-core/CHANGELOG.md @@ -207,4 +207,7 @@ Documentation: - Web3config `contractDataInputFill` has been defaulted to `data`, istead of `input`. (#6622) -## [Unreleased] \ No newline at end of file +## [Unreleased] + +### Added +- `defaultReturnFormat` was added to the configuration options. (#6947) diff --git a/packages/web3-core/src/web3_config.ts b/packages/web3-core/src/web3_config.ts index 772653cfdeb..3c335292c4a 100644 --- a/packages/web3-core/src/web3_config.ts +++ b/packages/web3-core/src/web3_config.ts @@ -15,7 +15,14 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ -import { Numbers, HexString, BlockNumberOrTag, Common } from 'web3-types'; +import { + Numbers, + HexString, + BlockNumberOrTag, + Common, + DEFAULT_RETURN_FORMAT, + DataFormat, +} from 'web3-types'; import { ConfigHardforkMismatchError, ConfigChainMismatchError } from 'web3-errors'; import { isNullish, toHex } from 'web3-utils'; import { TransactionTypeParser } from './types.js'; @@ -52,6 +59,7 @@ export interface Web3ConfigOptions { }; transactionBuilder?: TransactionBuilder; transactionTypeParser?: TransactionTypeParser; + defaultReturnFormat: DataFormat; } type ConfigEvent = P extends unknown @@ -93,6 +101,7 @@ export abstract class Web3Config }, transactionBuilder: undefined, transactionTypeParser: undefined, + defaultReturnFormat: DEFAULT_RETURN_FORMAT, }; public constructor(options?: Partial) { @@ -348,6 +357,15 @@ export abstract class Web3Config this.config.maxListenersWarningThreshold = val; } + public get defaultReturnFormat() { + return this.config.defaultReturnFormat; + } + public set defaultReturnFormat(val) { + this._triggerConfigChange('defaultReturnFormat', val); + + this.config.defaultReturnFormat = val; + } + public get defaultNetworkId() { return this.config.defaultNetworkId; } diff --git a/packages/web3-core/test/unit/__snapshots__/web3_context.test.ts.snap b/packages/web3-core/test/unit/__snapshots__/web3_context.test.ts.snap index 7e9121c85d2..e01ba14a467 100644 --- a/packages/web3-core/test/unit/__snapshots__/web3_context.test.ts.snap +++ b/packages/web3-core/test/unit/__snapshots__/web3_context.test.ts.snap @@ -13,6 +13,10 @@ exports[`Web3Context getContextObject should return correct context object 1`] = "defaultHardfork": "london", "defaultMaxPriorityFeePerGas": "0x9502f900", "defaultNetworkId": undefined, + "defaultReturnFormat": { + "bytes": "BYTES_HEX", + "number": "NUMBER_BIGINT", + }, "defaultTransactionType": "0x2", "enableExperimentalFeatures": { "useRpcCallSpecification": false, diff --git a/packages/web3-core/test/unit/web3_config.test.ts b/packages/web3-core/test/unit/web3_config.test.ts index 32a5fc17ddc..0391eec851a 100644 --- a/packages/web3-core/test/unit/web3_config.test.ts +++ b/packages/web3-core/test/unit/web3_config.test.ts @@ -16,6 +16,7 @@ along with web3.js. If not, see . */ import { toHex } from 'web3-utils'; +import { DEFAULT_RETURN_FORMAT } from 'web3-types'; import { Web3Config, Web3ConfigEvent } from '../../src/web3_config'; class MyConfigObject extends Web3Config {} @@ -44,6 +45,7 @@ const defaultConfig = { transactionConfirmationPollingInterval: undefined, defaultTransactionType: '0x2', defaultMaxPriorityFeePerGas: toHex(2500000000), + defaultReturnFormat: DEFAULT_RETURN_FORMAT, }; const setValue = { string: 'newValue', diff --git a/packages/web3-eth-accounts/test/config/setup.js b/packages/web3-eth-accounts/test/config/setup.js index b3c35155474..36be82ea918 100644 --- a/packages/web3-eth-accounts/test/config/setup.js +++ b/packages/web3-eth-accounts/test/config/setup.js @@ -23,6 +23,6 @@ require('jest-extended'); process.env.NODE_ENV = 'test'; -const jestTimeout = 10000; +const jestTimeout = 15000; jest.setTimeout(jestTimeout); diff --git a/packages/web3-eth-contract/CHANGELOG.md b/packages/web3-eth-contract/CHANGELOG.md index 2eb9a5ca676..8aa7c126ebb 100644 --- a/packages/web3-eth-contract/CHANGELOG.md +++ b/packages/web3-eth-contract/CHANGELOG.md @@ -328,7 +328,6 @@ Documentation: - Added `dataInputFill` as a ContractInitOption, allowing users to have the choice using property `data`, `input` or `both` for contract methods to be sent to the RPC provider. (#6355) - Added to `Web3Config` property `contractDataInputFill` allowing users to have the choice using property `data`, `input` or `both` for contract methods to be sent to the RPC provider when creating contracts. (#6377) - ## [4.1.1] ### Changed @@ -345,24 +344,24 @@ Documentation: ### Fixed -- Will populate `data` for transactions in contract for metamask provider instead of `input` (#6534) +- Will populate `data` for transactions in contract for metamask provider instead of `input` (#6534) ## [4.1.4] ### Changed -- By default, contracts will fill `data` instead of `input` within method calls (#6622) +- By default, contracts will fill `data` instead of `input` within method calls (#6622) ## [4.2.0] ### Changed -- Allow the `deploy` function to accept parameters, even when no ABI was provided to the `Contract`(#6635) +- Allow the `deploy` function to accept parameters, even when no ABI was provided to the `Contract`(#6635) ### Fixed -- Fix and error that happen when trying to get past events by calling `contract.getPastEvents` or `contract.events.allEvents()`, if there is no matching events. (#6647) -- Fixed: The Contract is not using the context wallet passed if context was passed at constructor. (#6661) +- Fix and error that happen when trying to get past events by calling `contract.getPastEvents` or `contract.events.allEvents()`, if there is no matching events. (#6647) +- Fixed: The Contract is not using the context wallet passed if context was passed at constructor. (#6661) ## [4.3.0] @@ -374,11 +373,15 @@ Documentation: ### Fixed -- Fix an issue with smart contract function overloading (#6922) +- Fix an issue with smart contract function overloading (#6922) ### Added -- Added a console warning in case of an ambiguous call to a solidity method with parameter overloading (#6942) -- Added contract.deploy(...).decodeData(...) and contract.decodeMethodData(...) that decode data based on the ABI (#6950) +- Added a console warning in case of an ambiguous call to a solidity method with parameter overloading (#6942) +- Added contract.deploy(...).decodeData(...) and contract.decodeMethodData(...) that decode data based on the ABI (#6950) ## [Unreleased] + +### Added + +- `defaultReturnFormat` was added to all methods that have `ReturnType` param. (#6947) diff --git a/packages/web3-eth-contract/src/contract.ts b/packages/web3-eth-contract/src/contract.ts index 7ebff70a136..c4be775b31f 100644 --- a/packages/web3-eth-contract/src/contract.ts +++ b/packages/web3-eth-contract/src/contract.ts @@ -163,13 +163,13 @@ export type ContractMethodsInterface = { } & { [key: string]: ContractBoundMethod }; export type ContractMethodSend = Web3PromiEvent< - FormatType, - SendTransactionEvents + FormatType, + SendTransactionEvents >; export type ContractDeploySend = Web3PromiEvent< // eslint-disable-next-line no-use-before-define Contract, - SendTransactionEvents + SendTransactionEvents >; /** @@ -334,24 +334,24 @@ const contractSubscriptions = { * Decodes the given ABI-encoded data, revealing both the method name and the parameters used in the smart contract call. * This function reverses the encoding process happens at the method `encodeABI`. * It's particularly useful for debugging and understanding the interactions with and between smart contracts. - * + * * #### Parameters - * + * * - `data` **HexString**: The string of ABI-encoded data that needs to be decoded. This should include the method signature and the encoded parameters. - * + * * #### Returns - * + * * - **Object**: This object combines both the decoded parameters and the method name in a readable format. Specifically, the returned object contains: * - `__method__` **String**: The name of the contract method, reconstructed from the ABI. * - `__length__` **Number**: The number of parameters decoded. * - Additional properties representing each parameter by name, as well as their position and values. - * + * * #### Example - * + * * Given an ABI-encoded string from a transaction, you can decode this data to identify the method called and the parameters passed. * Here's a simplified example: - * - * + * + * * ```typescript * const GreeterAbi = [ * { @@ -368,11 +368,11 @@ const contractSubscriptions = { * }, * ]; * const contract = new Contract(GreeterAbi); // Initialize with your contract's ABI - * + * * // The ABI-encoded data string for "setGreeting('Hello World')" * const encodedData = * '0xa41368620000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000b48656c6c6f20576f726c64000000000000000000000000000000000000000000'; - * + * * try { * const decoded = contract.decodeMethodData(encodedData); * console.log(decoded.__method__); // Outputs: "setGreeting(string)" @@ -388,7 +388,7 @@ const contractSubscriptions = { * console.error(error); * } * ``` - * + * * ### createAccessList * This will create an access list a method execution will access when executed in the EVM. @@ -513,7 +513,11 @@ export class Contract ); public constructor( jsonInterface: Abi, - addressOrOptionsOrContext?: Address | ContractInitOptions | Web3ContractContext | Web3Context, + addressOrOptionsOrContext?: + | Address + | ContractInitOptions + | Web3ContractContext + | Web3Context, optionsOrContextOrReturnFormat?: | ContractInitOptions | Web3ContractContext @@ -539,14 +543,20 @@ export class Contract } let provider; - if (typeof addressOrOptionsOrContext === 'object' && 'provider' in addressOrOptionsOrContext) { + if ( + typeof addressOrOptionsOrContext === 'object' && + 'provider' in addressOrOptionsOrContext + ) { provider = addressOrOptionsOrContext.provider; } else if ( typeof optionsOrContextOrReturnFormat === 'object' && 'provider' in optionsOrContextOrReturnFormat ) { provider = optionsOrContextOrReturnFormat.provider; - } else if (typeof contextOrReturnFormat === 'object' && 'provider' in contextOrReturnFormat) { + } else if ( + typeof contextOrReturnFormat === 'object' && + 'provider' in contextOrReturnFormat + ) { provider = contextOrReturnFormat.provider; } else { provider = Contract.givenProvider; @@ -583,13 +593,17 @@ export class Contract ? contextOrReturnFormat : isDataFormat(optionsOrContextOrReturnFormat) ? optionsOrContextOrReturnFormat - : returnFormat ?? DEFAULT_RETURN_FORMAT; + : returnFormat ?? this.defaultReturnFormat; const address = typeof addressOrOptionsOrContext === 'string' ? addressOrOptionsOrContext : undefined; this.config.contractDataInputFill = (options as ContractInitOptions)?.dataInputFill ?? this.config.contractDataInputFill; this._parseAndSetJsonInterface(jsonInterface, returnDataFormat); + if (this.defaultReturnFormat !== returnDataFormat) { + this.defaultReturnFormat = returnDataFormat; + } + if (!isNullish(address)) { this._parseAndSetAddress(address, returnDataFormat); } @@ -872,7 +886,7 @@ export class Contract }, estimateGas: async ( options?: PayableCallOptions, - returnFormat: ReturnFormat = DEFAULT_RETURN_FORMAT as ReturnFormat, + returnFormat: ReturnFormat = this.defaultReturnFormat as ReturnFormat, ) => { const modifiedOptions = { ...options }; return this._contractMethodEstimateGas({ @@ -887,7 +901,11 @@ export class Contract encodeMethodABI( abi as AbiFunctionFragment, args as unknown[], - format({ format: 'bytes' }, deployData as Bytes, DEFAULT_RETURN_FORMAT), + format( + { format: 'bytes' }, + deployData as Bytes, + this.defaultReturnFormat as typeof DEFAULT_RETURN_FORMAT, + ), ), decodeData: (data: HexString) => ({ ...decodeMethodParams( @@ -979,7 +997,7 @@ export class Contract ? param1 : isDataFormat(param2) ? param2 - : param3 ?? DEFAULT_RETURN_FORMAT; + : param3 ?? this.defaultReturnFormat; const abi = eventName === 'allEvents' || eventName === ALL_EVENTS @@ -1018,7 +1036,8 @@ export class Contract if (Array.isArray(filter[key])) { return (filter[key] as Numbers[]).some( (v: Numbers) => - String(log.returnValues[key]).toUpperCase() === String(v).toUpperCase(), + String(log.returnValues[key]).toUpperCase() === + String(v).toUpperCase(), ); } @@ -1028,7 +1047,10 @@ export class Contract if (hashedIndexedString === String(log.returnValues[key])) return true; } - return String(log.returnValues[key]).toUpperCase() === String(filter[key]).toUpperCase(); + return ( + String(log.returnValues[key]).toUpperCase() === + String(filter[key]).toUpperCase() + ); }); }); } @@ -1036,7 +1058,10 @@ export class Contract return decodedLogs; } - private _parseAndSetAddress(value?: Address, returnFormat: DataFormat = DEFAULT_RETURN_FORMAT) { + private _parseAndSetAddress( + value?: Address, + returnFormat: DataFormat = this.defaultReturnFormat, + ) { this._address = value ? toChecksumAddress(format({ format: 'address' }, value, returnFormat)) : value; @@ -1059,7 +1084,7 @@ export class Contract private _parseAndSetJsonInterface( abis: ContractAbi, - returnFormat: DataFormat = DEFAULT_RETURN_FORMAT, + returnFormat: DataFormat = this.defaultReturnFormat, ) { this._functions = {}; this._methods = {} as ContractMethodsInterface; @@ -1068,7 +1093,9 @@ export class Contract let result: ContractAbi = []; const functionsAbi = abis.filter(abi => abi.type !== 'error'); - const errorsAbi = abis.filter(abi => isAbiErrorFragment(abi)) as unknown as AbiErrorFragment[]; + const errorsAbi = abis.filter(abi => + isAbiErrorFragment(abi), + ) as unknown as AbiErrorFragment[]; for (const a of functionsAbi) { const abi: Mutable = { @@ -1084,7 +1111,9 @@ export class Contract // make constant and payable backwards compatible abi.constant = - abi.stateMutability === 'view' ?? abi.stateMutability === 'pure' ?? abi.constant; + abi.stateMutability === 'view' ?? + abi.stateMutability === 'pure' ?? + abi.constant; abi.payable = abi.stateMutability === 'payable' ?? abi.payable; this._overloadedMethodAbis.set(abi.name, [ @@ -1092,10 +1121,10 @@ export class Contract abi, ]); const abiFragment = this._overloadedMethodAbis.get(abi.name) ?? []; - const contractMethod = this._createContractMethod( - abiFragment, - errorsAbi, - ); + const contractMethod = this._createContractMethod< + typeof abiFragment, + AbiErrorFragment + >(abiFragment, errorsAbi); const exactContractMethod = this._createContractMethod< typeof abiFragment, @@ -1108,7 +1137,8 @@ export class Contract }; // We don't know a particular type of the Abi method so can't type check - this._methods[abi.name as keyof ContractMethodsInterface] = contractMethod as never; + this._methods[abi.name as keyof ContractMethodsInterface] = + contractMethod as never; // We don't know a particular type of the Abi method so can't type check this._methods[methodName as keyof ContractMethodsInterface] = @@ -1184,7 +1214,10 @@ export class Contract for (const _abi of arrayOfAbis) { try { abiParams = this._getAbiParams(_abi, params); - validator.validate(_abi.inputs as unknown as ValidationSchemaInput, abiParams); + validator.validate( + _abi.inputs as unknown as ValidationSchemaInput, + abiParams, + ); applicableMethodAbi.push(_abi); } catch (e) { errors.push(e as Web3ValidationErrorObject); @@ -1200,9 +1233,9 @@ export class Contract } compatible methods: ${JSON.stringify( applicableMethodAbi.map( m => - `${(m as { methodNameWithInputs: string }).methodNameWithInputs} (signature: ${ - (m as { signature: string }).signature - })`, + `${ + (m as { methodNameWithInputs: string }).methodNameWithInputs + } (signature: ${(m as { signature: string }).signature})`, ), )} \n\tThe first one will be used: ${ (methodAbi as { methodNameWithInputs: string }).methodNameWithInputs @@ -1224,14 +1257,22 @@ export class Contract call: async ( options?: PayableCallOptions | NonPayableCallOptions, block?: BlockNumberOrTag, - ) => this._contractMethodCall(methodAbi, abiParams, internalErrorsAbis, options, block), + ) => + this._contractMethodCall( + methodAbi, + abiParams, + internalErrorsAbis, + options, + block, + ), send: (options?: PayableTxOptions | NonPayableTxOptions): ContractMethodSend => this._contractMethodSend(methodAbi, abiParams, internalErrorsAbis, options), estimateGas: async ( options?: PayableCallOptions | NonPayableCallOptions, - returnFormat: ReturnFormat = DEFAULT_RETURN_FORMAT as ReturnFormat, + returnFormat: ReturnFormat = this + .defaultReturnFormat as unknown as ReturnFormat, ) => this._contractMethodEstimateGas({ abi: methodAbi, @@ -1289,7 +1330,12 @@ export class Contract }, }); try { - const result = await call(this, tx, block, DEFAULT_RETURN_FORMAT); + const result = await call( + this, + tx, + block, + this.defaultReturnFormat as typeof DEFAULT_RETURN_FORMAT, + ); return decodeMethodReturn(abi, result); } catch (error: unknown) { if (error instanceof ContractExecutionError) { @@ -1320,7 +1366,7 @@ export class Contract }); try { - return createAccessList(this, tx, block, DEFAULT_RETURN_FORMAT); + return createAccessList(this, tx, block, this.defaultReturnFormat); } catch (error: unknown) { if (error instanceof ContractExecutionError) { // this will parse the error data by trying to decode the ABI error inputs according to EIP-838 @@ -1350,7 +1396,7 @@ export class Contract contractOptions: modifiedContractOptions, }); - const transactionToSend = sendTransaction(this, tx, DEFAULT_RETURN_FORMAT, { + const transactionToSend = sendTransaction(this, tx, this.defaultReturnFormat, { // TODO Should make this configurable by the user checkRevertBeforeSending: false, contractAbi: this._jsonInterface, @@ -1380,10 +1426,10 @@ export class Contract const tx = getSendTxParams({ abi, params, - options: { ...options, dataInputFill: this.config.contractDataInputFill }, + options: { ...options, dataInputFill: this.contractDataInputFill }, contractOptions: modifiedContractOptions, }); - return sendTransaction(this, tx, DEFAULT_RETURN_FORMAT, { + return sendTransaction(this, tx, this.defaultReturnFormat, { transactionResolver: receipt => { if (receipt.status === BigInt(0)) { throw new Web3ContractError("code couldn't be stored", receipt); @@ -1423,16 +1469,20 @@ export class Contract options: { ...options, dataInputFill: this.config.contractDataInputFill }, contractOptions: contractOptions ?? this.options, }); - return estimateGas(this, tx, BlockTags.LATEST, returnFormat); + return estimateGas(this, tx, BlockTags.LATEST, returnFormat ?? this.defaultReturnFormat); } // eslint-disable-next-line class-methods-use-this private _createContractEvent( abi: AbiEventFragment & { signature: HexString }, - returnFormat: DataFormat = DEFAULT_RETURN_FORMAT, + returnFormat: DataFormat = this.defaultReturnFormat, ): ContractBoundEvent { return (...params: unknown[]) => { - const { topics, fromBlock } = encodeEventABI(this.options, abi, params[0] as EventParameters); + const { topics, fromBlock } = encodeEventABI( + this.options, + abi, + params[0] as EventParameters, + ); const sub = new LogsSubscription( { address: this.options.address, @@ -1442,7 +1492,10 @@ export class Contract }, { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - subscriptionManager: this.subscriptionManager as Web3SubscriptionManager, + subscriptionManager: this.subscriptionManager as Web3SubscriptionManager< + unknown, + any + >, returnFormat, }, ); @@ -1455,7 +1508,10 @@ export class Contract } }) .catch((error: Error) => { - sub.emit('error', new SubscriptionError('Failed to get past events.', error)); + sub.emit( + 'error', + new SubscriptionError('Failed to get past events.', error), + ); }); } this.subscriptionManager?.addSubscription(sub).catch((error: Error) => { diff --git a/packages/web3-eth-contract/test/integration/contract_deploy.test.ts b/packages/web3-eth-contract/test/integration/contract_deploy.test.ts index 1d7277fe881..b8036c123a3 100644 --- a/packages/web3-eth-contract/test/integration/contract_deploy.test.ts +++ b/packages/web3-eth-contract/test/integration/contract_deploy.test.ts @@ -15,6 +15,7 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ import { Web3Eth } from 'web3-eth'; +import { FMT_BYTES, FMT_NUMBER } from 'web3-types'; import { Contract } from '../../src'; import { sleep } from '../shared_fixtures/utils'; import { ERC721TokenAbi, ERC721TokenBytecode } from '../shared_fixtures/build/ERC721Token'; @@ -30,7 +31,8 @@ import { sendFewSampleTxs, closeOpenConnection, getSystemTestBackend, - BACKEND + BACKEND, + mapFormatToType, } from '../fixtures/system_test_utils'; describe('contract', () => { @@ -109,8 +111,33 @@ describe('contract', () => { from: acc.address, gas: '1000000', }); + expect(typeof estimatedGas).toBe('bigint'); expect(Number(estimatedGas)).toBeGreaterThan(0); }); + it.each(Object.values(FMT_NUMBER))( + 'should return estimated gas of contract constructor %p with correct type', + async format => { + const returnFormat = { number: format as FMT_NUMBER, bytes: FMT_BYTES.HEX }; + + const estimatedGas = await new Contract( + GreeterAbi, + { + provider: getSystemTestProvider(), + }, + returnFormat, + ) + .deploy({ + data: GreeterBytecode, + arguments: ['My Greeting'], + }) + .estimateGas({ + from: acc.address, + gas: '1000000', + }); + expect(typeof estimatedGas).toBe(mapFormatToType[format as string]); + expect(Number(estimatedGas)).toBeGreaterThan(0); + }, + ); it('should return estimated gas of contract constructor without arguments', async () => { const estimatedGas = await new Contract(ERC721TokenAbi, undefined, { provider: getSystemTestProvider(), @@ -256,7 +283,7 @@ describe('contract', () => { }); it('should fail with errors on "intrinsic gas too low" OOG', async () => { - if (getSystemTestBackend() !== BACKEND.HARDHAT){ + if (getSystemTestBackend() !== BACKEND.HARDHAT) { // eslint-disable-next-line jest/no-conditional-expect await expect( contract.deploy(deployOptions).send({ ...sendOptions, gas: '100' }), @@ -265,7 +292,9 @@ describe('contract', () => { // eslint-disable-next-line jest/no-conditional-expect await expect( contract.deploy(deployOptions).send({ ...sendOptions, gas: '100' }), - ).rejects.toThrow('Returned error: Transaction requires at least 109656 gas but got 100'); + ).rejects.toThrow( + 'Returned error: Transaction requires at least 109656 gas but got 100', + ); } }); @@ -283,7 +312,7 @@ describe('contract', () => { it('should fail with errors on revert', async () => { const revert = new Contract(DeployRevertAbi); revert.provider = getSystemTestProvider(); - if (getSystemTestBackend() !== BACKEND.HARDHAT){ + if (getSystemTestBackend() !== BACKEND.HARDHAT) { // eslint-disable-next-line jest/no-conditional-expect await expect( revert @@ -293,15 +322,17 @@ describe('contract', () => { .send(sendOptions), ).rejects.toThrow("code couldn't be stored"); } else { - // eslint-disable-next-line jest/no-conditional-expect - await expect( - revert - .deploy({ - data: DeployRevertBytecode, - }) - .send(sendOptions), - ).rejects.toThrow("Error happened while trying to execute a function inside a smart contract"); - } + // eslint-disable-next-line jest/no-conditional-expect + await expect( + revert + .deploy({ + data: DeployRevertBytecode, + }) + .send(sendOptions), + ).rejects.toThrow( + 'Error happened while trying to execute a function inside a smart contract', + ); + } }); }); }); diff --git a/packages/web3-eth-ens/CHANGELOG.md b/packages/web3-eth-ens/CHANGELOG.md index c0212f7f121..c40b2727d5e 100644 --- a/packages/web3-eth-ens/CHANGELOG.md +++ b/packages/web3-eth-ens/CHANGELOG.md @@ -153,4 +153,7 @@ Documentation: - Added function getText and getName in ENS and resolver classes (#6914) -## [Unreleased] \ No newline at end of file +## [Unreleased] + +### Added +- `defaultReturnFormat` was added to all methods that have `ReturnType` param. (#6947) diff --git a/packages/web3-eth-ens/src/ens.ts b/packages/web3-eth-ens/src/ens.ts index 88d6ae58c83..254a33bc842 100644 --- a/packages/web3-eth-ens/src/ens.ts +++ b/packages/web3-eth-ens/src/ens.ts @@ -16,13 +16,16 @@ along with web3.js. If not, see . */ import { Web3Context, Web3ContextObject } from 'web3-core'; -import { ENSNetworkNotSyncedError, ENSUnsupportedNetworkError, RevertInstructionError } from 'web3-errors'; +import { + ENSNetworkNotSyncedError, + ENSUnsupportedNetworkError, + RevertInstructionError, +} from 'web3-errors'; import { isSyncing } from 'web3-eth'; import { Contract } from 'web3-eth-contract'; import { getId } from 'web3-net'; import { Address, - DEFAULT_RETURN_FORMAT, EthExecutionAPI, FMT_NUMBER, PayableCallOptions, @@ -37,25 +40,25 @@ import { Resolver } from './resolver.js'; /** * This class is designed to interact with the ENS system on the Ethereum blockchain. -* For using ENS package, first install Web3 package using: `npm i web3` or `yarn add web3` based on your package manager, after that ENS features can be used as mentioned in following snippet. -* ```ts -* -* import { Web3 } from 'web3'; -* -* const web3 = new Web3('https://127.0.0.1:4545'); -* -* console.log(await web3.eth.ens.getAddress('ethereum.eth')) -* ``` -* For using individual package install `web3-eth-ens` packages using: `npm i web3-eth-ens` or `yarn add web3-eth-ens`. This is more efficient approach for building lightweight applications. -* -* ```ts -*import { ENS } from 'web3-eth-ens'; -* -* const ens = new ENS(undefined,'https://127.0.0.1:4545'); -* -* console.log(await ens.getAddress('vitalik.eth')); -* ``` -*/ + * For using ENS package, first install Web3 package using: `npm i web3` or `yarn add web3` based on your package manager, after that ENS features can be used as mentioned in following snippet. + * ```ts + * + * import { Web3 } from 'web3'; + * + * const web3 = new Web3('https://127.0.0.1:4545'); + * + * console.log(await web3.eth.ens.getAddress('ethereum.eth')) + * ``` + * For using individual package install `web3-eth-ens` packages using: `npm i web3-eth-ens` or `yarn add web3-eth-ens`. This is more efficient approach for building lightweight applications. + * + * ```ts + *import { ENS } from 'web3-eth-ens'; + * + * const ens = new ENS(undefined,'https://127.0.0.1:4545'); + * + * console.log(await ens.getAddress('vitalik.eth')); + * ``` + */ export class ENS extends Web3Context { /** * The registryAddress property can be used to define a custom registry address when you are connected to an unknown chain. It defaults to the main registry address. @@ -175,7 +178,6 @@ export class ENS extends Web3Context { return this._resolver.getText(ENSName, key); } - /** * Resolves the name of an ENS node. * @param ENSName - The node to resolve @@ -246,7 +248,7 @@ export class ENS extends Web3Context { return this._detectedAddress; } const networkType = await getId(this, { - ...DEFAULT_RETURN_FORMAT, + ...this.defaultReturnFormat, number: FMT_NUMBER.HEX, }); // get the network from provider const addr = registryAddresses[networkIds[networkType]]; @@ -292,10 +294,10 @@ export class ENS extends Web3Context { * const receipt = await ens.setAddress('web3js.eth','0xe2597eb05cf9a87eb1309e86750c903ec38e527e'); *``` */ - public async setAddress( + public async setAddress( name: string, address: Address, - txConfig: PayableCallOptions + txConfig: PayableCallOptions, ): Promise { return this._resolver.setAddress(name, address, txConfig); } diff --git a/packages/web3-eth-ens/test/integration/ens.events.test.ts b/packages/web3-eth-ens/test/integration/ens.events.test.ts index 8ad10d08bda..4e199597c24 100644 --- a/packages/web3-eth-ens/test/integration/ens.events.test.ts +++ b/packages/web3-eth-ens/test/integration/ens.events.test.ts @@ -18,9 +18,8 @@ along with web3.js. If not, see . /* eslint-disable @typescript-eslint/no-unused-vars */ import { Contract, PayableTxOptions } from 'web3-eth-contract'; import { sha3 } from 'web3-utils'; -import { getBlock } from 'web3-eth'; -import { Address, Bytes, DEFAULT_RETURN_FORMAT } from 'web3-types'; +import { Address, Bytes } from 'web3-types'; // eslint-disable-next-line import/no-extraneous-dependencies import { IpcProvider } from 'web3-providers-ipc'; import { ENS } from '../../src'; @@ -75,7 +74,7 @@ describeIf(isSocket)('ens events', () => { const acc2 = await createTempAccount(); accountOne = acc2.address; - sendOptions = { from: defaultAccount, gas: '10000000' }; + sendOptions = { from: defaultAccount, type: '0x1' }; const Registry = new Contract(ENSRegistryAbi, undefined, { provider: getSystemTestProvider(), @@ -120,15 +119,6 @@ describeIf(isSocket)('ens events', () => { else provider = new ENS.providers.HttpProvider(clientUrl); ens = new ENS(registry.options.address, provider); - - const block = await getBlock(ens, 'latest', false, DEFAULT_RETURN_FORMAT); - const gas = block.gasLimit.toString(); - - // Increase gas for contract calls - sendOptions = { - ...sendOptions, - gas, - }; }); afterAll(async () => { diff --git a/packages/web3-eth-ens/test/integration/ens.test.ts b/packages/web3-eth-ens/test/integration/ens.test.ts index 5683451b66f..bde73e72fc7 100644 --- a/packages/web3-eth-ens/test/integration/ens.test.ts +++ b/packages/web3-eth-ens/test/integration/ens.test.ts @@ -16,9 +16,8 @@ along with web3.js. If not, see . */ /* eslint-disable @typescript-eslint/no-unused-vars */ -import { getBlock } from 'web3-eth'; import { Contract, PayableTxOptions } from 'web3-eth-contract'; -import { Address, Bytes, DEFAULT_RETURN_FORMAT } from 'web3-types'; +import { Address, Bytes } from 'web3-types'; import { sha3, toChecksumAddress } from 'web3-utils'; // eslint-disable-next-line import/no-extraneous-dependencies import { IpcProvider } from 'web3-providers-ipc'; @@ -76,7 +75,7 @@ describe('ens', () => { const acc2 = await createTempAccount(); accountOne = acc2.address; - sendOptions = { from: defaultAccount, gas: '10000000' }; + sendOptions = { from: defaultAccount, type: '0x1' }; const Registry = new Contract(ENSRegistryAbi, undefined, { provider: getSystemTestProvider(), @@ -121,15 +120,6 @@ describe('ens', () => { else provider = new ENS.providers.HttpProvider(clientUrl); ens = new ENS(registry.options.address, provider); - - const block = await getBlock(ens, 'latest', false, DEFAULT_RETURN_FORMAT); - const gas = block.gasLimit.toString(); - - // Increase gas for contract calls - sendOptions = { - ...sendOptions, - gas, - }; }); afterAll(async () => { diff --git a/packages/web3-eth-ens/test/integration/resolver.test.ts b/packages/web3-eth-ens/test/integration/resolver.test.ts index 587ce2e7b29..f6b2e648991 100644 --- a/packages/web3-eth-ens/test/integration/resolver.test.ts +++ b/packages/web3-eth-ens/test/integration/resolver.test.ts @@ -15,12 +15,10 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ -/* eslint-disable @typescript-eslint/no-unused-vars */ -import Web3Eth from 'web3-eth'; import { Contract, PayableTxOptions } from 'web3-eth-contract'; import { sha3 } from 'web3-utils'; -import { Address, Bytes, DEFAULT_RETURN_FORMAT } from 'web3-types'; +import { Address, Bytes } from 'web3-types'; // eslint-disable-next-line import/no-extraneous-dependencies import { IpcProvider } from 'web3-providers-ipc'; import { ENS } from '../../src'; @@ -59,8 +57,6 @@ describe('ens', () => { const node = namehash('resolver'); const label = sha3('resolver') as string; - let web3Eth: Web3Eth; - let ens: ENS; let defaultAccount: string; let accountOne: string; @@ -78,7 +74,7 @@ describe('ens', () => { const acc2 = await createTempAccount(); accountOne = acc2.address; - sendOptions = { from: defaultAccount, gas: '10000000' }; + sendOptions = { from: defaultAccount, type: '0x1' }; const Registry = new Contract(ENSRegistryAbi, undefined, { provider: getSystemTestProvider(), @@ -123,16 +119,6 @@ describe('ens', () => { else provider = new ENS.providers.HttpProvider(clientUrl); ens = new ENS(registry.options.address, provider); - - web3Eth = new Web3Eth(provider); - const block = await web3Eth.getBlock('latest', false, DEFAULT_RETURN_FORMAT); - const gas = block.gasLimit.toString(); - - // Increase gas for contract calls - sendOptions = { - ...sendOptions, - gas, - }; }); afterAll(async () => { diff --git a/packages/web3-eth-ens/test/integration/setup.js b/packages/web3-eth-ens/test/integration/setup.js index 5be1bccf7cc..59b1f904213 100644 --- a/packages/web3-eth-ens/test/integration/setup.js +++ b/packages/web3-eth-ens/test/integration/setup.js @@ -19,6 +19,6 @@ along with web3.js. If not, see . // eslint-disable-next-line @typescript-eslint/no-require-imports require('../config/setup'); -const jestTimeout = 15000; +const jestTimeout = 30000; jest.setTimeout(jestTimeout); diff --git a/packages/web3-eth/CHANGELOG.md b/packages/web3-eth/CHANGELOG.md index b4b937ce6ae..ba7ee38a443 100644 --- a/packages/web3-eth/CHANGELOG.md +++ b/packages/web3-eth/CHANGELOG.md @@ -200,7 +200,7 @@ Documentation: ### Fixed - Ensure provider.supportsSubscriptions exists before watching by subscription (#6440) -- Fixed param sent to `checkRevertBeforeSending` in `sendSignedTransaction` +- Fixed param sent to `checkRevertBeforeSending` in `sendSignedTransaction` - Fixed `defaultTransactionBuilder` for value issue (#6509) ### Added @@ -227,9 +227,13 @@ Documentation: ## [4.6.0] -### Added +### Added -- method `getBlock` now includes properties of eip 4844, 4895, 4788 when returning block (#6933) +- method `getBlock` now includes properties of eip 4844, 4895, 4788 when returning block (#6933) - update type `withdrawalsSchema`, `blockSchema` and `blockHeaderSchema` schemas to include properties of eip 4844, 4895, 4788 (#6933) -## [Unreleased] \ No newline at end of file +## [Unreleased] + +### Added + +- `defaultReturnFormat` was added to all methods that have `ReturnType` param. (#6947) diff --git a/packages/web3-eth/src/rpc_method_wrappers.ts b/packages/web3-eth/src/rpc_method_wrappers.ts index 1a2cac1ffd8..20e832be892 100644 --- a/packages/web3-eth/src/rpc_method_wrappers.ts +++ b/packages/web3-eth/src/rpc_method_wrappers.ts @@ -122,7 +122,11 @@ export async function getHashRate( ) { const response = await ethRpcMethods.getHashRate(web3Context.requestManager); - return format({ format: 'uint' }, response as Numbers, returnFormat); + return format( + { format: 'uint' }, + response as Numbers, + returnFormat ?? web3Context.defaultReturnFormat, + ); } /** @@ -135,7 +139,11 @@ export async function getGasPrice( ) { const response = await ethRpcMethods.getGasPrice(web3Context.requestManager); - return format({ format: 'uint' }, response as Numbers, returnFormat); + return format( + { format: 'uint' }, + response as Numbers, + returnFormat ?? web3Context.defaultReturnFormat, + ); } /** @@ -148,7 +156,11 @@ export async function getMaxPriorityFeePerGas( ) { const response = await ethRpcMethods.getMaxPriorityFeePerGas(web3Context.requestManager); - return format({ format: 'uint' }, response as Numbers, returnFormat); + return format( + { format: 'uint' }, + response as Numbers, + returnFormat ?? web3Context.defaultReturnFormat, + ); } /** * View additional documentations here: {@link Web3Eth.getBlockNumber} @@ -160,7 +172,11 @@ export async function getBlockNumber( ) { const response = await ethRpcMethods.getBlockNumber(web3Context.requestManager); - return format({ format: 'uint' }, response as Numbers, returnFormat); + return format( + { format: 'uint' }, + response as Numbers, + returnFormat ?? web3Context.defaultReturnFormat, + ); } /** @@ -181,7 +197,11 @@ export async function getBalance( address, blockNumberFormatted, ); - return format({ format: 'uint' }, response as Numbers, returnFormat); + return format( + { format: 'uint' }, + response as Numbers, + returnFormat ?? web3Context.defaultReturnFormat, + ); } /** @@ -205,7 +225,11 @@ export async function getStorageAt( storageSlotFormatted, blockNumberFormatted, ); - return format({ format: 'bytes' }, response as Bytes, returnFormat); + return format( + { format: 'bytes' }, + response as Bytes, + returnFormat ?? web3Context.defaultReturnFormat, + ); } /** @@ -226,7 +250,11 @@ export async function getCode( address, blockNumberFormatted, ); - return format({ format: 'bytes' }, response as Bytes, returnFormat); + return format( + { format: 'bytes' }, + response as Bytes, + returnFormat ?? web3Context.defaultReturnFormat, + ); } /** @@ -257,7 +285,11 @@ export async function getBlock( hydrated, ); } - return format(blockSchema, response as unknown as Block, returnFormat); + return format( + blockSchema, + response as unknown as Block, + returnFormat ?? web3Context.defaultReturnFormat, + ); } /** @@ -286,7 +318,11 @@ export async function getBlockTransactionCount( ); } - return format({ format: 'uint' }, response as Numbers, returnFormat); + return format( + { format: 'uint' }, + response as Numbers, + returnFormat ?? web3Context.defaultReturnFormat, + ); } /** @@ -315,7 +351,11 @@ export async function getBlockUncleCount( ); } - return format({ format: 'uint' }, response as Numbers, returnFormat); + return format( + { format: 'uint' }, + response as Numbers, + returnFormat ?? web3Context.defaultReturnFormat, + ); } /** @@ -349,7 +389,11 @@ export async function getUncle( ); } - return format(blockSchema, response as unknown as Block, returnFormat); + return format( + blockSchema, + response as unknown as Block, + returnFormat ?? web3Context.defaultReturnFormat, + ); } /** @@ -359,7 +403,7 @@ export async function getUncle( export async function getTransaction( web3Context: Web3Context, transactionHash: Bytes, - returnFormat: ReturnFormat, + returnFormat: ReturnFormat = web3Context.defaultReturnFormat as ReturnFormat, ) { const transactionHashFormatted = format( { format: 'bytes32' }, @@ -373,7 +417,9 @@ export async function getTransaction( return isNullish(response) ? response - : formatTransaction(response, returnFormat, { fillInputAndData: true }); + : formatTransaction(response, returnFormat, { + fillInputAndData: true, + }); } /** @@ -387,9 +433,13 @@ export async function getPendingTransactions( const response = await ethRpcMethods.getPendingTransactions(web3Context.requestManager); return response.map(transaction => - formatTransaction(transaction as unknown as Transaction, returnFormat, { - fillInputAndData: true, - }), + formatTransaction( + transaction as unknown as Transaction, + returnFormat ?? web3Context.defaultReturnFormat, + { + fillInputAndData: true, + }, + ), ); } @@ -426,7 +476,9 @@ export async function getTransactionFromBlock( return isNullish(response) ? response - : formatTransaction(response, returnFormat, { fillInputAndData: true }); + : formatTransaction(response, returnFormat ?? web3Context.defaultReturnFormat, { + fillInputAndData: true, + }); } /** @@ -453,7 +505,7 @@ export async function getTransactionReceipt( : (format( transactionReceiptSchema, response as unknown as TransactionReceipt, - returnFormat, + returnFormat ?? web3Context.defaultReturnFormat, ) as TransactionReceipt); } @@ -476,7 +528,11 @@ export async function getTransactionCount( blockNumberFormatted, ); - return format({ format: 'uint' }, response as Numbers, returnFormat); + return format( + { format: 'uint' }, + response as Numbers, + returnFormat ?? web3Context.defaultReturnFormat, + ); } /** @@ -519,7 +575,7 @@ export function sendTransaction< }, ETH_DATA_FORMAT, ); - + try { transactionFormatted = await sendTxHelper.populateGasPrice({ transaction, @@ -548,7 +604,7 @@ export function sendTransaction< const transactionHashFormatted = format( { format: 'bytes32' }, transactionHash as Bytes, - returnFormat, + returnFormat ?? web3Context.defaultReturnFormat, ); sendTxHelper.emitSent(transactionFormatted); sendTxHelper.emitTransactionHash( @@ -558,11 +614,15 @@ export function sendTransaction< const transactionReceipt = await waitForTransactionReceipt( web3Context, transactionHash, - returnFormat, + returnFormat ?? web3Context.defaultReturnFormat, ); const transactionReceiptFormatted = sendTxHelper.getReceiptWithEvents( - format(transactionReceiptSchema, transactionReceipt, returnFormat), + format( + transactionReceiptSchema, + transactionReceipt, + returnFormat ?? web3Context.defaultReturnFormat, + ), ); sendTxHelper.emitReceipt(transactionReceiptFormatted); @@ -661,7 +721,7 @@ export function sendSignedTransaction< const transactionHashFormatted = format( { format: 'bytes32' }, transactionHash as Bytes, - returnFormat, + returnFormat ?? web3Context.defaultReturnFormat, ); sendTxHelper.emitTransactionHash( @@ -671,11 +731,15 @@ export function sendSignedTransaction< const transactionReceipt = await waitForTransactionReceipt( web3Context, transactionHash, - returnFormat, + returnFormat ?? web3Context.defaultReturnFormat, ); const transactionReceiptFormatted = sendTxHelper.getReceiptWithEvents( - format(transactionReceiptSchema, transactionReceipt, returnFormat), + format( + transactionReceiptSchema, + transactionReceipt, + returnFormat ?? web3Context.defaultReturnFormat, + ), ); sendTxHelper.emitReceipt(transactionReceiptFormatted); @@ -715,7 +779,7 @@ export async function sign( web3Context: Web3Context, message: Bytes, addressOrIndex: Address | number, - returnFormat: ReturnFormat, + returnFormat: ReturnFormat = web3Context.defaultReturnFormat as ReturnFormat, ) { const messageFormatted = format({ format: 'bytes' }, message, DEFAULT_RETURN_FORMAT); if (web3Context.wallet?.get(addressOrIndex)) { @@ -747,7 +811,7 @@ export async function sign( export async function signTransaction( web3Context: Web3Context, transaction: Transaction, - returnFormat: ReturnFormat, + returnFormat: ReturnFormat = web3Context.defaultReturnFormat as ReturnFormat, ) { const response = await ethRpcMethods.signTransaction( web3Context.requestManager, @@ -781,7 +845,7 @@ export async function call( web3Context: Web3Context, transaction: TransactionCall, blockNumber: BlockNumberOrTag = web3Context.defaultBlock, - returnFormat: ReturnFormat, + returnFormat: ReturnFormat = web3Context.defaultReturnFormat as ReturnFormat, ) { const blockNumberFormatted = isBlockTag(blockNumber as string) ? (blockNumber as BlockTag) @@ -818,7 +882,11 @@ export async function estimateGas( blockNumberFormatted, ); - return format({ format: 'uint' }, response as Numbers, returnFormat); + return format( + { format: 'uint' }, + response as Numbers, + returnFormat ?? web3Context.defaultReturnFormat, + ); } // TODO - Add input formatting to filter @@ -853,7 +921,11 @@ export async function getLogs( return res; } - return format(logSchema, res as unknown as Log, returnFormat); + return format( + logSchema, + res as unknown as Log, + returnFormat ?? web3Context.defaultReturnFormat, + ); }); return result; @@ -873,7 +945,7 @@ export async function getChainId( { format: 'uint' }, // Response is number in hex formatted string response as unknown as number, - returnFormat, + returnFormat ?? web3Context.defaultReturnFormat, ); } @@ -903,7 +975,11 @@ export async function getProof( blockNumberFormatted, ); - return format(accountSchema, response as unknown as AccountObject, returnFormat); + return format( + accountSchema, + response as unknown as AccountObject, + returnFormat ?? web3Context.defaultReturnFormat, + ); } // TODO Throwing an error with Geth, but not Infura @@ -943,7 +1019,11 @@ export async function getFeeHistory( rewardPercentilesFormatted, ); - return format(feeHistorySchema, response as unknown as FeeHistory, returnFormat); + return format( + feeHistorySchema, + response as unknown as FeeHistory, + returnFormat ?? web3Context.defaultReturnFormat, + ); } /** @@ -966,7 +1046,11 @@ export async function createAccessList( blockNumberFormatted, )) as unknown as AccessListResult; - return format(accessListResultSchema, response, returnFormat); + return format( + accessListResultSchema, + response, + returnFormat ?? web3Context.defaultReturnFormat, + ); } /** @@ -987,5 +1071,5 @@ export async function signTypedData( useLegacy, ); - return format({ format: 'bytes' }, response, returnFormat); + return format({ format: 'bytes' }, response, returnFormat ?? web3Context.defaultReturnFormat); } diff --git a/packages/web3-eth/src/utils/get_revert_reason.ts b/packages/web3-eth/src/utils/get_revert_reason.ts index ae4fc32dbfa..6edb2ec52c3 100644 --- a/packages/web3-eth/src/utils/get_revert_reason.ts +++ b/packages/web3-eth/src/utils/get_revert_reason.ts @@ -16,7 +16,12 @@ along with web3.js. If not, see . */ import { Web3Context } from 'web3-core'; -import { ContractExecutionError, Eip838ExecutionError, InvalidResponseError , MultipleErrors } from 'web3-errors'; +import { + ContractExecutionError, + Eip838ExecutionError, + InvalidResponseError, + MultipleErrors, +} from 'web3-errors'; import { decodeContractErrorData, isAbiErrorFragment } from 'web3-eth-abi'; import { AbiErrorFragment, @@ -80,7 +85,7 @@ export async function getRevertReason< web3Context: Web3Context, transaction: TransactionCall, contractAbi?: ContractAbi, - returnFormat: ReturnFormat = DEFAULT_RETURN_FORMAT as ReturnFormat, + returnFormat: ReturnFormat = web3Context.defaultReturnFormat as ReturnFormat, ): Promise { try { await call(web3Context, transaction, web3Context.defaultBlock, returnFormat); diff --git a/packages/web3-eth/src/utils/transaction_builder.ts b/packages/web3-eth/src/utils/transaction_builder.ts index 13edd253330..0d459017b4a 100644 --- a/packages/web3-eth/src/utils/transaction_builder.ts +++ b/packages/web3-eth/src/utils/transaction_builder.ts @@ -29,7 +29,6 @@ import { Web3NetAPI, Numbers, DataFormat, - DEFAULT_RETURN_FORMAT, FormatType, ETH_DATA_FORMAT, } from 'web3-types'; @@ -99,7 +98,7 @@ export const getTransactionFromOrToAttr = ( export const getTransactionNonce = async ( web3Context: Web3Context, address?: Address, - returnFormat: ReturnFormat = DEFAULT_RETURN_FORMAT as ReturnFormat, + returnFormat: ReturnFormat = web3Context.defaultReturnFormat as ReturnFormat, ) => { if (isNullish(address)) { // TODO if (web3.eth.accounts.wallet) use address from local wallet @@ -133,7 +132,7 @@ export async function defaultTransactionBuilder(option let populatedTransaction = format( transactionSchema, options.transaction, - DEFAULT_RETURN_FORMAT, + options.web3Context.defaultReturnFormat, ) as InternalTransaction; if (isNullish(populatedTransaction.from)) { diff --git a/packages/web3-eth/src/web3_eth.ts b/packages/web3-eth/src/web3_eth.ts index 3c1165b0e3c..959a7d5eddc 100644 --- a/packages/web3-eth/src/web3_eth.ts +++ b/packages/web3-eth/src/web3_eth.ts @@ -201,7 +201,8 @@ export class Web3Eth extends Web3Context( - returnFormat: ReturnFormat = DEFAULT_RETURN_FORMAT as ReturnFormat, + returnFormat: ReturnFormat = (this.defaultReturnFormat ?? + DEFAULT_RETURN_FORMAT) as ReturnFormat, ) { return this.getHashRate(returnFormat); } @@ -219,7 +220,7 @@ export class Web3Eth extends Web3Context( - returnFormat: ReturnFormat = DEFAULT_RETURN_FORMAT as ReturnFormat, + returnFormat: ReturnFormat = this.defaultReturnFormat as ReturnFormat, ) { return rpcMethodsWrappers.getHashRate(this, returnFormat); } @@ -237,7 +238,7 @@ export class Web3Eth extends Web3Context( - returnFormat: ReturnFormat = DEFAULT_RETURN_FORMAT as ReturnFormat, + returnFormat: ReturnFormat = this.defaultReturnFormat as ReturnFormat, ) { return rpcMethodsWrappers.getGasPrice(this, returnFormat); } @@ -256,7 +257,7 @@ export class Web3Eth extends Web3Context(returnFormat: ReturnFormat = DEFAULT_RETURN_FORMAT as ReturnFormat) { + >(returnFormat: ReturnFormat = this.defaultReturnFormat as ReturnFormat) { return rpcMethodsWrappers.getMaxPriorityFeePerGas(this, returnFormat); } @@ -300,7 +301,10 @@ export class Web3Eth extends Web3Context(); + gasPrice = await this.getGasPrice<{ + number: FMT_NUMBER.BIGINT; + bytes: FMT_BYTES.HEX; + }>(); } catch (error) { // do nothing } @@ -361,7 +365,7 @@ export class Web3Eth extends Web3Context( - returnFormat: ReturnFormat = DEFAULT_RETURN_FORMAT as ReturnFormat, + returnFormat: ReturnFormat = this.defaultReturnFormat as ReturnFormat, ) { return rpcMethodsWrappers.getBlockNumber(this, returnFormat); } @@ -385,7 +389,7 @@ export class Web3Eth extends Web3Context( address: Address, blockNumber: BlockNumberOrTag = this.defaultBlock, - returnFormat: ReturnFormat = DEFAULT_RETURN_FORMAT as ReturnFormat, + returnFormat: ReturnFormat = this.defaultReturnFormat as ReturnFormat, ) { return rpcMethodsWrappers.getBalance(this, address, blockNumber, returnFormat); } @@ -421,9 +425,15 @@ export class Web3Eth extends Web3Context( address: Address, blockNumber: BlockNumberOrTag = this.defaultBlock, - returnFormat: ReturnFormat = DEFAULT_RETURN_FORMAT as ReturnFormat, + returnFormat: ReturnFormat = this.defaultReturnFormat as ReturnFormat, ) { return rpcMethodsWrappers.getCode(this, address, blockNumber, returnFormat); } @@ -527,7 +537,7 @@ export class Web3Eth extends Web3Context( block: HexString32Bytes | BlockNumberOrTag = this.defaultBlock, hydrated = false, - returnFormat: ReturnFormat = DEFAULT_RETURN_FORMAT as ReturnFormat, + returnFormat: ReturnFormat = this.defaultReturnFormat as ReturnFormat, ) { return rpcMethodsWrappers.getBlock(this, block, hydrated, returnFormat); } @@ -552,7 +562,7 @@ export class Web3Eth extends Web3Context( block: HexString32Bytes | BlockNumberOrTag = this.defaultBlock, - returnFormat: ReturnFormat = DEFAULT_RETURN_FORMAT as ReturnFormat, + returnFormat: ReturnFormat = this.defaultReturnFormat as ReturnFormat, ) { return rpcMethodsWrappers.getBlockTransactionCount(this, block, returnFormat); } @@ -575,7 +585,7 @@ export class Web3Eth extends Web3Context( block: HexString32Bytes | BlockNumberOrTag = this.defaultBlock, - returnFormat: ReturnFormat = DEFAULT_RETURN_FORMAT as ReturnFormat, + returnFormat: ReturnFormat = this.defaultReturnFormat as ReturnFormat, ) { return rpcMethodsWrappers.getBlockUncleCount(this, block, returnFormat); } @@ -646,7 +656,7 @@ export class Web3Eth extends Web3Context( block: HexString32Bytes | BlockNumberOrTag = this.defaultBlock, uncleIndex: Numbers, - returnFormat: ReturnFormat = DEFAULT_RETURN_FORMAT as ReturnFormat, + returnFormat: ReturnFormat = this.defaultReturnFormat as ReturnFormat, ) { return rpcMethodsWrappers.getUncle(this, block, uncleIndex, returnFormat); } @@ -701,9 +711,13 @@ export class Web3Eth extends Web3Context( transactionHash: Bytes, - returnFormat: ReturnFormat = DEFAULT_RETURN_FORMAT as ReturnFormat, + returnFormat: ReturnFormat = this.defaultReturnFormat as ReturnFormat, ) { - const response = await rpcMethodsWrappers.getTransaction(this, transactionHash, returnFormat); + const response = await rpcMethodsWrappers.getTransaction( + this, + transactionHash, + returnFormat, + ); if (!response) throw new TransactionNotFound(); @@ -794,7 +808,7 @@ export class Web3Eth extends Web3Context(returnFormat: ReturnFormat = DEFAULT_RETURN_FORMAT as ReturnFormat) { + >(returnFormat: ReturnFormat = this.defaultReturnFormat as ReturnFormat) { return rpcMethodsWrappers.getPendingTransactions(this, returnFormat); } @@ -853,9 +867,14 @@ export class Web3Eth extends Web3Context( block: HexString32Bytes | BlockNumberOrTag = this.defaultBlock, transactionIndex: Numbers, - returnFormat: ReturnFormat = DEFAULT_RETURN_FORMAT as ReturnFormat, + returnFormat: ReturnFormat = this.defaultReturnFormat as ReturnFormat, ) { - return rpcMethodsWrappers.getTransactionFromBlock(this, block, transactionIndex, returnFormat); + return rpcMethodsWrappers.getTransactionFromBlock( + this, + block, + transactionIndex, + returnFormat, + ); } /** @@ -904,7 +923,10 @@ export class Web3Eth extends Web3Context(transactionHash: Bytes, returnFormat: ReturnFormat = DEFAULT_RETURN_FORMAT as ReturnFormat) { + >( + transactionHash: Bytes, + returnFormat: ReturnFormat = this.defaultReturnFormat as ReturnFormat, + ) { const response = await rpcMethodsWrappers.getTransactionReceipt( this, transactionHash, @@ -934,10 +956,12 @@ export class Web3Eth extends Web3Context 1 * ``` */ - public async getTransactionCount( + public async getTransactionCount< + ReturnFormat extends DataFormat = typeof DEFAULT_RETURN_FORMAT, + >( address: Address, blockNumber: BlockNumberOrTag = this.defaultBlock, - returnFormat: ReturnFormat = DEFAULT_RETURN_FORMAT as ReturnFormat, + returnFormat: ReturnFormat = this.defaultReturnFormat as ReturnFormat, ) { return rpcMethodsWrappers.getTransactionCount(this, address, blockNumber, returnFormat); } @@ -1054,7 +1078,7 @@ export class Web3Eth extends Web3Context( transaction: Bytes, - returnFormat: ReturnFormat = DEFAULT_RETURN_FORMAT as ReturnFormat, + returnFormat: ReturnFormat = this.defaultReturnFormat as ReturnFormat, options?: SendTransactionOptions, ) { return rpcMethodsWrappers.sendSignedTransaction(this, transaction, returnFormat, options); @@ -1182,7 +1206,7 @@ export class Web3Eth extends Web3Context( message: Bytes, addressOrIndex: Address | number, - returnFormat: ReturnFormat = DEFAULT_RETURN_FORMAT as ReturnFormat, + returnFormat: ReturnFormat = this.defaultReturnFormat as ReturnFormat, ) { return rpcMethodsWrappers.sign(this, message, addressOrIndex, returnFormat); } @@ -1240,7 +1264,7 @@ export class Web3Eth extends Web3Context( transaction: Transaction, - returnFormat: ReturnFormat = DEFAULT_RETURN_FORMAT as ReturnFormat, + returnFormat: ReturnFormat = this.defaultReturnFormat as ReturnFormat, ) { return rpcMethodsWrappers.signTransaction(this, transaction, returnFormat); } @@ -1259,7 +1283,7 @@ export class Web3Eth extends Web3Context( transaction: TransactionCall, blockNumber: BlockNumberOrTag = this.defaultBlock, - returnFormat: ReturnFormat = DEFAULT_RETURN_FORMAT as ReturnFormat, + returnFormat: ReturnFormat = this.defaultReturnFormat as ReturnFormat, ) { return rpcMethodsWrappers.call(this, transaction, blockNumber, returnFormat); } @@ -1293,7 +1317,7 @@ export class Web3Eth extends Web3Context( transaction: Transaction, blockNumber: BlockNumberOrTag = this.defaultBlock, - returnFormat: ReturnFormat = DEFAULT_RETURN_FORMAT as ReturnFormat, + returnFormat: ReturnFormat = this.defaultReturnFormat as ReturnFormat, ) { return rpcMethodsWrappers.estimateGas(this, transaction, blockNumber, returnFormat); } @@ -1344,7 +1368,7 @@ export class Web3Eth extends Web3Context( filter: Filter, - returnFormat: ReturnFormat = DEFAULT_RETURN_FORMAT as ReturnFormat, + returnFormat: ReturnFormat = this.defaultReturnFormat as ReturnFormat, ) { return rpcMethodsWrappers.getLogs(this, filter, returnFormat); } @@ -1427,7 +1451,7 @@ export class Web3Eth extends Web3Context( - returnFormat: ReturnFormat = DEFAULT_RETURN_FORMAT as ReturnFormat, + returnFormat: ReturnFormat = this.defaultReturnFormat as ReturnFormat, ) { return rpcMethodsWrappers.getChainId(this, returnFormat); } @@ -1520,7 +1544,7 @@ export class Web3Eth extends Web3Context( transaction: TransactionForAccessList, blockNumber: BlockNumberOrTag = this.defaultBlock, - returnFormat: ReturnFormat = DEFAULT_RETURN_FORMAT as ReturnFormat, + returnFormat: ReturnFormat = this.defaultReturnFormat as ReturnFormat, ) { return rpcMethodsWrappers.createAccessList(this, transaction, blockNumber, returnFormat); } @@ -1653,7 +1677,8 @@ export class Web3Eth extends Web3Context( name: T, args?: ConstructorParameters[0], - returnFormat: ReturnType = DEFAULT_RETURN_FORMAT as ReturnType, + returnFormat: ReturnType = (this.defaultReturnFormat ?? + DEFAULT_RETURN_FORMAT) as ReturnType, ): Promise> { const subscription = await this.subscriptionManager?.subscribe(name, args, returnFormat); if ( diff --git a/packages/web3-eth/test/integration/format.test.ts b/packages/web3-eth/test/integration/format.test.ts new file mode 100644 index 00000000000..b9962c065ff --- /dev/null +++ b/packages/web3-eth/test/integration/format.test.ts @@ -0,0 +1,112 @@ +/* +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 { SupportedProviders, FMT_BYTES, FMT_NUMBER } from 'web3-types'; +// eslint-disable-next-line import/no-extraneous-dependencies +import { Contract } from 'web3-eth-contract'; +import { numberToHex } from 'web3-utils'; +// eslint-disable-next-line import/no-extraneous-dependencies +import { Web3Eth } from '../../src'; + +import { + closeOpenConnection, + getSystemTestProvider, + createNewAccount, + createTempAccount, + mapFormatToType, +} from '../fixtures/system_test_utils'; +import { BasicAbi, BasicBytecode } from '../shared_fixtures/build/Basic'; + +describe('format', () => { + let web3Eth: Web3Eth; + let clientUrl: string | SupportedProviders; + let contractDeployed: Contract; + let contract: Contract; + let deployOptions: Record; + let sendOptions: Record; + let tempAcc: { address: string; privateKey: string }; + beforeAll(async () => { + clientUrl = getSystemTestProvider(); + web3Eth = new Web3Eth({ + provider: clientUrl, + config: { + transactionPollingTimeout: 2000, + }, + }); + contract = new Contract(BasicAbi, undefined, { + provider: clientUrl, + }); + + deployOptions = { + data: BasicBytecode, + arguments: [10, 'string init value'], + }; + tempAcc = await createTempAccount(); + sendOptions = { from: tempAcc.address, gas: '1000000' }; + + contractDeployed = await contract.deploy(deployOptions).send(sendOptions); + }); + + afterAll(async () => { + await closeOpenConnection(web3Eth); + await closeOpenConnection(contract); + }); + + describe('methods', () => { + it.each(Object.values(FMT_NUMBER))('getBlockNumber', async format => { + web3Eth.defaultReturnFormat = { number: format as FMT_NUMBER, bytes: FMT_BYTES.HEX }; + const res = await web3Eth.getBlockNumber(); + expect(typeof res).toBe(mapFormatToType[format as string]); + expect(parseInt(String(res), 16)).toBeGreaterThan(0); + }); + + it.each(Object.values(FMT_NUMBER))('getGasPrice', async format => { + web3Eth.defaultReturnFormat = { number: format as FMT_NUMBER, bytes: FMT_BYTES.HEX }; + const res = await web3Eth.getGasPrice(); + expect(typeof res).toBe(mapFormatToType[format as string]); + expect(parseInt(String(res), 16)).toBeGreaterThan(0); + }); + + it.each(Object.values(FMT_NUMBER))('getBalance', async format => { + web3Eth.defaultReturnFormat = { number: format as FMT_NUMBER, bytes: FMT_BYTES.HEX }; + const value = '0xa'; + const newAccount = await createNewAccount(); + await web3Eth.sendTransaction({ + to: newAccount.address, + value, + from: tempAcc.address, + }); + const res = await web3Eth.getBalance(newAccount.address); + expect(typeof res).toBe(mapFormatToType[format as string]); + expect(numberToHex(res)).toBe(value); + }); + + it.each(Object.values(FMT_BYTES))('getCode', async format => { + web3Eth.defaultReturnFormat = { number: FMT_NUMBER.BIGINT, bytes: format }; + const code = await web3Eth.getCode(contractDeployed?.options?.address as string); + expect(code).toBeDefined(); + expect(typeof code).toBe(mapFormatToType[format as string]); + }); + + it.each(Object.values(FMT_NUMBER))('getChainId', async format => { + web3Eth.defaultReturnFormat = { number: format as FMT_NUMBER, bytes: FMT_BYTES.HEX }; + const res = await web3Eth.getChainId(); + expect(typeof res).toBe(mapFormatToType[format as string]); + expect(Number(res)).toBeGreaterThan(0); + }); + }); +}); diff --git a/packages/web3-eth/test/integration/helper.ts b/packages/web3-eth/test/integration/helper.ts index 46063294702..4a12b288055 100644 --- a/packages/web3-eth/test/integration/helper.ts +++ b/packages/web3-eth/test/integration/helper.ts @@ -14,13 +14,7 @@ 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 { - AbiEventFragment, - Block, - TransactionInfo, - TransactionReceipt, - FMT_NUMBER, -} from 'web3-types'; +import { AbiEventFragment, Block, TransactionInfo, TransactionReceipt } from 'web3-types'; // eslint-disable-next-line import/no-extraneous-dependencies import Web3 from 'web3'; import { BasicAbi } from '../shared_fixtures/build/Basic'; @@ -130,12 +124,6 @@ export const validateReceipt = (r: TransactionReceipt) => { expect(Number(r.gasUsed)).toBeGreaterThan(0); }; -export const mapFormatToType: { [key: string]: string } = { - [FMT_NUMBER.NUMBER]: 'number', - [FMT_NUMBER.HEX]: 'string', - [FMT_NUMBER.STR]: 'string', - [FMT_NUMBER.BIGINT]: 'bigint', -}; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion export const eventAbi: AbiEventFragment = BasicAbi.find((e: any) => { return e.name === 'StringEvent' && (e as AbiEventFragment).type === 'event'; diff --git a/packages/web3-eth/test/integration/rpc.test.ts b/packages/web3-eth/test/integration/rpc.test.ts index d9ca6e5676b..eba6792a2f8 100644 --- a/packages/web3-eth/test/integration/rpc.test.ts +++ b/packages/web3-eth/test/integration/rpc.test.ts @@ -26,7 +26,6 @@ import { // eslint-disable-next-line import/no-extraneous-dependencies import { Contract, decodeEventABI } from 'web3-eth-contract'; import { hexToNumber, hexToString, numberToHex, getStorageSlotNumForLongString } from 'web3-utils'; -// eslint-disable-next-line import/no-extraneous-dependencies import { Web3Eth } from '../../src'; import { @@ -37,16 +36,11 @@ import { itIf, createTempAccount, describeIf, - BACKEND + mapFormatToType, + BACKEND, } from '../fixtures/system_test_utils'; import { BasicAbi, BasicBytecode } from '../shared_fixtures/build/Basic'; -import { - eventAbi, - mapFormatToType, - sendFewTxes, - validateReceipt, - validateTransaction, -} from './helper'; +import { eventAbi, sendFewTxes, validateReceipt, validateTransaction } from './helper'; describe('rpc', () => { let web3Eth: Web3Eth; @@ -86,11 +80,14 @@ describe('rpc', () => { }); describe('methods', () => { - itIf(!['geth', 'hardhat'].includes(getSystemTestBackend()))('getProtocolVersion', async () => { - const version = await web3Eth.getProtocolVersion(); - // eslint-disable-next-line jest/no-standalone-expect - expect(parseInt(version, 16)).toBeGreaterThan(0); - }); + itIf(!['geth', 'hardhat'].includes(getSystemTestBackend()))( + 'getProtocolVersion', + async () => { + const version = await web3Eth.getProtocolVersion(); + // eslint-disable-next-line jest/no-standalone-expect + expect(parseInt(version, 16)).toBeGreaterThan(0); + }, + ); // TODO:in beta, test eth_syncing during sync mode with return obj having ( startingblock, currentBlock, heighestBlock ) it('isSyncing', async () => { @@ -113,20 +110,20 @@ describe('rpc', () => { expect(isMining).toBe(true); }); - describeIf(getSystemTestBackend() !== BACKEND.HARDHAT)('getHashRate', () => { + describeIf(getSystemTestBackend() !== BACKEND.HARDHAT)('getHashRate', () => { it.each(Object.values(FMT_NUMBER))('getHashRate', async format => { const hashRate = await web3Eth.getHashRate({ number: format as FMT_NUMBER, bytes: FMT_BYTES.HEX, }); // eslint-disable-next-line jest/no-standalone-expect - expect(typeof hashRate).toBe(mapFormatToType[format as string]); + expect(typeof hashRate).toBe(mapFormatToType[format as string]); }); - }) + }); it('getAccounts', async () => { // hardhat does not have support importrawkey, so we can't add new accounts rather just check the default 20 accounts - if (getSystemTestBackend() !== BACKEND.HARDHAT) { + if (getSystemTestBackend() !== BACKEND.HARDHAT) { const account = await createNewAccount({ unlock: true }); const accList = await web3Eth.getAccounts(); const accListLowerCase = accList.map((add: string) => add.toLowerCase()); diff --git a/packages/web3-net/CHANGELOG.md b/packages/web3-net/CHANGELOG.md index dd6227ecdd8..d60abde6313 100644 --- a/packages/web3-net/CHANGELOG.md +++ b/packages/web3-net/CHANGELOG.md @@ -141,4 +141,7 @@ Documentation: - Dependencies updated -## [Unreleased] \ No newline at end of file +## [Unreleased] + +### Added +- `defaultReturnFormat` was added to all methods that have `ReturnType` param. (#6947) diff --git a/packages/web3-net/src/net.ts b/packages/web3-net/src/net.ts index eb84e567bb5..ac376e86c5a 100644 --- a/packages/web3-net/src/net.ts +++ b/packages/web3-net/src/net.ts @@ -21,24 +21,24 @@ import * as rpcMethodsWrappers from './rpc_method_wrappers.js'; /** * Net class allows you to interact with an Ethereum node’s network properties. -* For using Net package, first install Web3 package using: `npm i web3` or `yarn add web3` based on your package manager, after that Net features can be used. -* ```ts -* -* import { Web3 } from 'web3'; -* const web3 = new Web3('https://mainnet.infura.io/v3/'); -* -* console.log(await web3.eth.net.getId()); -* -* ``` -* For using individual package install `web3-net` packages using: `npm i web3-net` or `yarn add web3-net`. -* -* ```ts -* import {Net} from 'web3-net'; -* -* const net = new Net('https://mainnet.infura.io/v3/'); -* console.log(await net.getId()); -* ``` -*/ + * For using Net package, first install Web3 package using: `npm i web3` or `yarn add web3` based on your package manager, after that Net features can be used. + * ```ts + * + * import { Web3 } from 'web3'; + * const web3 = new Web3('https://mainnet.infura.io/v3/'); + * + * console.log(await web3.eth.net.getId()); + * + * ``` + * For using individual package install `web3-net` packages using: `npm i web3-net` or `yarn add web3-net`. + * + * ```ts + * import {Net} from 'web3-net'; + * + * const net = new Net('https://mainnet.infura.io/v3/'); + * console.log(await net.getId()); + * ``` + */ export class Net extends Web3Context { /** * Gets the current network ID @@ -53,7 +53,7 @@ export class Net extends Web3Context { * ``` */ public async getId( - returnFormat: ReturnFormat = DEFAULT_RETURN_FORMAT as ReturnFormat, + returnFormat: ReturnFormat = this.defaultReturnFormat as ReturnFormat, ) { return rpcMethodsWrappers.getId(this, returnFormat); } @@ -71,7 +71,7 @@ export class Net extends Web3Context { * ``` */ public async getPeerCount( - returnFormat: ReturnFormat = DEFAULT_RETURN_FORMAT as ReturnFormat, + returnFormat: ReturnFormat = this.defaultReturnFormat as ReturnFormat, ) { return rpcMethodsWrappers.getPeerCount(this, returnFormat); } diff --git a/packages/web3-types/CHANGELOG.md b/packages/web3-types/CHANGELOG.md index b3a8628c9a5..3f96fe9d53d 100644 --- a/packages/web3-types/CHANGELOG.md +++ b/packages/web3-types/CHANGELOG.md @@ -194,4 +194,4 @@ Documentation: ### Added - Added `signature` to type `AbiFunctionFragment` (#6922) -- update type `Withdrawals`, `block` and `BlockHeaderOutput` to include properties of eip 4844, 4895, 4788 (#6933) \ No newline at end of file +- update type `Withdrawals`, `block` and `BlockHeaderOutput` to include properties of eip 4844, 4895, 4788 (#6933) diff --git a/packages/web3-types/src/data_format_types.ts b/packages/web3-types/src/data_format_types.ts index f0ffe3bc8aa..46c1f5352b8 100644 --- a/packages/web3-types/src/data_format_types.ts +++ b/packages/web3-types/src/data_format_types.ts @@ -46,7 +46,10 @@ export type DataFormat = { readonly bytes: FMT_BYTES; }; -export const DEFAULT_RETURN_FORMAT = { number: FMT_NUMBER.BIGINT, bytes: FMT_BYTES.HEX } as const; +export const DEFAULT_RETURN_FORMAT = { + number: FMT_NUMBER.BIGINT, + bytes: FMT_BYTES.HEX, +} as const; export const ETH_DATA_FORMAT = { number: FMT_NUMBER.HEX, bytes: FMT_BYTES.HEX } as const; export type FormatType = number extends Extract diff --git a/packages/web3-utils/CHANGELOG.md b/packages/web3-utils/CHANGELOG.md index 0d18cd22d3b..1ae402166d7 100644 --- a/packages/web3-utils/CHANGELOG.md +++ b/packages/web3-utils/CHANGELOG.md @@ -174,7 +174,7 @@ Documentation: ### Added - `SocketProvider` now contains public function `getPendingRequestQueueSize`, `getSentRequestsQueueSize` and `clearQueues` (#6479) -- Added `safeDisconnect` as a `SocketProvider` method to disconnect only when request queue size and send request queue size is 0 (#6479) +- Added `safeDisconnect` as a `SocketProvider` method to disconnect only when request queue size and send request queue size is 0 (#6479) - Add `isContractInitOptions` method (#6555) ### Fixed @@ -203,13 +203,17 @@ Documentation: ### Fixed -- fixed erroneous parsing of big numbers in the `toNumber(...)` function (#6880) +- fixed erroneous parsing of big numbers in the `toNumber(...)` function (#6880) ## [4.2.3] +### Changed + +- Method `format` was changed. Now it has default value `DEFAULT_RETURN_FORMAT` for `returnFormat` parameter (#6947) + ### Fixed -- fixed toHex incorrectly hexing Uint8Arrays and Buffer (#6957) -- fixed isUint8Array not returning true for Buffer (#6957) +- fixed toHex incorrectly hexing Uint8Arrays and Buffer (#6957) +- fixed isUint8Array not returning true for Buffer (#6957) ## [Unreleased] diff --git a/packages/web3-utils/src/formatter.ts b/packages/web3-utils/src/formatter.ts index 1901e1fde21..0a8ca3b723f 100644 --- a/packages/web3-utils/src/formatter.ts +++ b/packages/web3-utils/src/formatter.ts @@ -15,7 +15,14 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ import { FormatterError } from 'web3-errors'; -import { Bytes, DataFormat, FMT_BYTES, FMT_NUMBER, FormatType } from 'web3-types'; +import { + Bytes, + DataFormat, + FMT_BYTES, + FMT_NUMBER, + FormatType, + DEFAULT_RETURN_FORMAT, +} from 'web3-types'; import { isNullish, isObject, JsonSchema, utils, ValidationSchemaInput } from 'web3-validator'; import { bytesToUint8Array, bytesToHex, numberToHex, toBigInt } from './converters.js'; import { mergeDeep } from './objects.js'; @@ -277,7 +284,7 @@ export const format = < >( schema: ValidationSchemaInput | JsonSchema, data: DataType, - returnFormat: ReturnType, + returnFormat: ReturnType = DEFAULT_RETURN_FORMAT as ReturnType, ): FormatType => { let dataToParse: Record | unknown[] | unknown; diff --git a/packages/web3/src/web3.ts b/packages/web3/src/web3.ts index 2953e67d364..0fda2c10521 100644 --- a/packages/web3/src/web3.ts +++ b/packages/web3/src/web3.ts @@ -20,7 +20,7 @@ import { Web3ContextInitOptions, Web3ContextObject, Web3SubscriptionConstructor, - isSupportedProvider + isSupportedProvider, } from 'web3-core'; import { Web3Eth, RegisteredSubscription, registeredSubscriptions } from 'web3-eth'; import Contract from 'web3-eth-contract'; @@ -37,7 +37,6 @@ import { EthExecutionAPI, SupportedProviders, DataFormat, - DEFAULT_RETURN_FORMAT } from 'web3-types'; import { InvalidMethodParamsError } from 'web3-errors'; import abi from './abi.js'; @@ -122,32 +121,38 @@ export class Web3< class ContractBuilder extends Contract { public constructor(jsonInterface: Abi); - public constructor(jsonInterface: Abi, + public constructor( + jsonInterface: Abi, addressOrOptionsOrContext?: Address | ContractInitOptions | Web3Context, - ); + ); public constructor( jsonInterface: Abi, addressOrOptionsOrContext?: Address | ContractInitOptions | Web3Context, optionsOrContextOrReturnFormat?: ContractInitOptions | Web3Context | DataFormat, ); - public constructor(jsonInterface: Abi, + public constructor( + jsonInterface: Abi, addressOrOptionsOrContext?: Address | ContractInitOptions, optionsOrContextOrReturnFormat?: ContractInitOptions, contextOrReturnFormat?: Web3Context | DataFormat, - ); - public constructor(jsonInterface: Abi, + ); + public constructor( + jsonInterface: Abi, addressOrOptionsOrContext?: Address | ContractInitOptions, optionsOrContextOrReturnFormat?: ContractInitOptions, contextOrReturnFormat?: Web3Context | DataFormat, - ); - public constructor(jsonInterface: Abi, + ); + public constructor( + jsonInterface: Abi, addressOrOptionsOrContext?: Address | ContractInitOptions, optionsOrContextOrReturnFormat?: ContractInitOptions, contextOrReturnFormat?: Web3Context | DataFormat, - returnFormat?: DataFormat - ) - { - if (isContractInitOptions(addressOrOptionsOrContext) && isContractInitOptions(optionsOrContextOrReturnFormat)) { + returnFormat?: DataFormat, + ) { + if ( + isContractInitOptions(addressOrOptionsOrContext) && + isContractInitOptions(optionsOrContextOrReturnFormat) + ) { throw new InvalidMethodParamsError( 'Should not provide options at both 2nd and 3rd parameters', ); @@ -155,22 +160,26 @@ export class Web3< let address: string | undefined; let options: object = {}; let context: Web3ContextObject; - let dataFormat: DataFormat = DEFAULT_RETURN_FORMAT; + let dataFormat: DataFormat | undefined; // add validation so its not a breaking change - if (!isNullish(addressOrOptionsOrContext) && typeof addressOrOptionsOrContext !== 'object' && typeof addressOrOptionsOrContext !== 'string') { + if ( + !isNullish(addressOrOptionsOrContext) && + typeof addressOrOptionsOrContext !== 'object' && + typeof addressOrOptionsOrContext !== 'string' + ) { throw new InvalidMethodParamsError(); } if (typeof addressOrOptionsOrContext === 'string') { address = addressOrOptionsOrContext; } - if (isContractInitOptions(addressOrOptionsOrContext)){ + if (isContractInitOptions(addressOrOptionsOrContext)) { options = addressOrOptionsOrContext as object; } else if (isContractInitOptions(optionsOrContextOrReturnFormat)) { options = optionsOrContextOrReturnFormat as object; } else { - options = {} + options = {}; } if (addressOrOptionsOrContext instanceof Web3Context) { @@ -183,7 +192,7 @@ export class Web3< context = self.getContextObject() as Web3ContextObject; } - if (returnFormat){ + if (returnFormat) { dataFormat = returnFormat; } else if (isDataFormat(optionsOrContextOrReturnFormat)) { dataFormat = optionsOrContextOrReturnFormat as DataFormat; @@ -191,7 +200,7 @@ export class Web3< dataFormat = contextOrReturnFormat; } - super(jsonInterface,address, options, context, dataFormat) + super(jsonInterface, address, options, context, dataFormat); super.subscribeToContextEvents(self); } } diff --git a/packages/web3/test/integration/web3.format.test.ts b/packages/web3/test/integration/web3.format.test.ts new file mode 100644 index 00000000000..5496a9efce1 --- /dev/null +++ b/packages/web3/test/integration/web3.format.test.ts @@ -0,0 +1,107 @@ +/* +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 { SupportedProviders } from 'web3-types'; +import { numberToHex } from 'web3-utils'; +import { Web3, Contract, FMT_BYTES, FMT_NUMBER } from '../../src'; + +import { + closeOpenConnection, + getSystemTestProvider, + createNewAccount, + createTempAccount, + mapFormatToType, +} from '../shared_fixtures/system_tests_utils'; +import { BasicAbi, BasicBytecode } from '../shared_fixtures/build/Basic'; + +describe('format', () => { + let web3: Web3; + let clientUrl: string | SupportedProviders; + let contractDeployed: Contract; + let contract: Contract; + let deployOptions: Record; + let sendOptions: Record; + let tempAcc: { address: string; privateKey: string }; + beforeAll(async () => { + clientUrl = getSystemTestProvider(); + web3 = new Web3({ + provider: clientUrl, + config: { + transactionPollingTimeout: 2000, + }, + }); + contract = new web3.eth.Contract(BasicAbi); + + deployOptions = { + data: BasicBytecode, + arguments: [10, 'string init value'], + }; + tempAcc = await createTempAccount(); + sendOptions = { from: tempAcc.address, gas: '1000000' }; + + contractDeployed = await contract.deploy(deployOptions).send(sendOptions); + }); + + afterAll(async () => { + await closeOpenConnection(web3); + }); + + describe('methods', () => { + it.each(Object.values(FMT_NUMBER))('getBlockNumber', async format => { + web3.defaultReturnFormat = { number: format as FMT_NUMBER, bytes: FMT_BYTES.HEX }; + const res = await web3.eth.getBlockNumber(); + expect(typeof res).toBe(mapFormatToType[format as string]); + expect(parseInt(String(res), 16)).toBeGreaterThan(0); + }); + + it.each(Object.values(FMT_NUMBER))('getGasPrice', async format => { + web3.defaultReturnFormat = { number: format as FMT_NUMBER, bytes: FMT_BYTES.HEX }; + const res = await web3.eth.getGasPrice(); + expect(typeof res).toBe(mapFormatToType[format as string]); + expect(parseInt(String(res), 16)).toBeGreaterThan(0); + }); + + it.each(Object.values(FMT_NUMBER))('getBalance', async format => { + web3.defaultReturnFormat = { number: format as FMT_NUMBER, bytes: FMT_BYTES.HEX }; + const value = '0xa'; + const newAccount = await createNewAccount(); + await web3.eth.sendTransaction({ + to: newAccount.address, + value, + from: tempAcc.address, + }); + const res = await web3.eth.getBalance(newAccount.address); + expect(typeof res).toBe(mapFormatToType[format as string]); + expect(numberToHex(res)).toBe(value); + }); + + it.each(Object.values(FMT_BYTES))('getCode', async format => { + web3.defaultReturnFormat = { number: FMT_NUMBER.BIGINT, bytes: format }; + const code = await web3.eth.getCode(contractDeployed?.options?.address as string); + expect(code).toBeDefined(); + expect(typeof code).toBe(mapFormatToType[format as string]); + }); + + it.each(Object.values(FMT_NUMBER))('getChainId', async format => { + web3.defaultReturnFormat = { number: format as FMT_NUMBER, bytes: FMT_BYTES.HEX }; + + const res = await web3.eth.getChainId(); + expect(typeof res).toBe(mapFormatToType[format as string]); + expect(Number(res)).toBeGreaterThan(0); + }); + }); +}); diff --git a/scripts/system_tests_utils.ts b/scripts/system_tests_utils.ts index a502c44825e..da58fc19d91 100644 --- a/scripts/system_tests_utils.ts +++ b/scripts/system_tests_utils.ts @@ -48,6 +48,8 @@ import { SupportedProviders, Web3APISpec, Web3EthExecutionAPI, + FMT_NUMBER, + FMT_BYTES, } from 'web3-types'; // eslint-disable-next-line import/no-extraneous-dependencies import { Personal } from 'web3-eth-personal'; @@ -504,3 +506,12 @@ export const objectBigintToString = (obj: object): object => // eslint-disable-next-line @typescript-eslint/no-unsafe-return JSON.stringify(obj, (_, value) => (typeof value === 'bigint' ? value.toString() : value)), ); + +export const mapFormatToType: { [key: string]: string } = { + [FMT_NUMBER.NUMBER]: 'number', + [FMT_NUMBER.HEX]: 'string', + [FMT_NUMBER.STR]: 'string', + [FMT_NUMBER.BIGINT]: 'bigint', + [FMT_BYTES.HEX]: 'string', + [FMT_BYTES.UINT8ARRAY]: 'object', +}; From dd172c78daa518778aa2ac07aa2cc2a8bf0aa9e2 Mon Sep 17 00:00:00 2001 From: Santiago Trujillo Zuluaga Date: Thu, 18 Apr 2024 22:32:06 +0300 Subject: [PATCH 04/32] Events guide 6741 (#6983) * changed sidebar position * removed supported subcription and added it to index.md * subcribe to events and node events guide * renamed label * changed js to ts and added unsubscribe function * typos --------- Co-authored-by: Alex --- .../custom_subscriptions.md | 2 +- .../docs/guides/events_subscriptions/index.md | 163 +++++++++++++++++- .../supported_subscriptions.md | 15 -- 3 files changed, 160 insertions(+), 20 deletions(-) delete mode 100644 docs/docs/guides/events_subscriptions/supported_subscriptions.md diff --git a/docs/docs/guides/events_subscriptions/custom_subscriptions.md b/docs/docs/guides/events_subscriptions/custom_subscriptions.md index 6f5826fe902..7dbf1df1990 100644 --- a/docs/docs/guides/events_subscriptions/custom_subscriptions.md +++ b/docs/docs/guides/events_subscriptions/custom_subscriptions.md @@ -1,5 +1,5 @@ --- -sidebar_position: 3 +sidebar_position: 2 sidebar_label: 'Custom Subscriptions' --- diff --git a/docs/docs/guides/events_subscriptions/index.md b/docs/docs/guides/events_subscriptions/index.md index 7bd2f60b958..445e7edc568 100644 --- a/docs/docs/guides/events_subscriptions/index.md +++ b/docs/docs/guides/events_subscriptions/index.md @@ -1,17 +1,172 @@ --- sidebar_position: 1 -sidebar_label: 'Introduction' +sidebar_label: 'Mastering Events Subcriptions' --- # Events Subscription +## Subscribing to smart contracts events + +```ts +import { Web3 } from "web3"; + +// set a provider - MUST be a WebSocket(WSS) provider +const web3 = new Web3("wss://ethereum-rpc.publicnode.com"); + +async function subscribe() { + // create a new contract object, providing the ABI and address + const contract = new web3.eth.Contract(abi, address); + + // subscribe to the smart contract event + const subscription = contract.events.EventName(); + + // new value every time the event is emitted + subscription.on("data", console.log); +} + +// function to unsubscribe from a subscription +async function unsubscribe(subscription) { + await subscription.unsubscribe(); +} + +subscribe(); +unsubscribe(subscription); +``` + + +## Subscribing to node events + A standard Ethereum node like [Geth supports subscribing to specific events](https://geth.ethereum.org/docs/interacting-with-geth/rpc/pubsub#supported-subscriptions). Additionally, there are some Ethereum nodes that provide additional custom subscriptions. As you can find in [Supported Subscriptions](/guides/events_subscriptions/supported_subscriptions) guide, web3.js enables you to subscribe to the standard events out of the box. And it also provides you with the capability to subscribe to custom subscriptions as you can find in the [Custom Subscriptions](/guides/events_subscriptions/custom_subscriptions) guide. :::important If you are the developer who provides custom subscriptions to users. We encourage you to develop a web3.js Plugin after you go through the [Custom Subscription](#custom-subscription) section below. You can find how to develop a plugin at [web3.js Plugin Developer Guide](/guides/web3_plugin_guide/plugin_authors) ::: -## Here are the guides for events subscription -- [Supported Subscriptions Guide](/guides/events_subscriptions/supported_subscriptions) -- [Custom Subscriptions Guide](/guides/events_subscriptions/custom_subscriptions) +- `on("data")` - Fires on each incoming log with the log object as argument. +```ts + subcription.on("data", (data) => console.log(data)); +``` + +- `on("changed")` - Fires on each log which was removed from the blockchain. The log will have the additional property "removed: true". +```ts + subcription.on("changed", (changed) => console.log(changed)); +``` + +- `on("error")` - Fires when an error in the subscription occurs. +```ts + subcription.on("error", (error) => console.log(error)); +``` + +- `on("connected")` - Fires once after the subscription successfully connected. Returns the subscription id. +```ts + subcription.on("connected", (connected) => console.log(connected)); +``` +### Logs + +- `logs`: implemented in the class [`LogsSubscription`](/api/web3-eth/class/LogsSubscription) + +```ts +import { Web3 } from "web3"; + +const web3 = new Web3("wss://ethereum-rpc.publicnode.com"); + +async function subscribe() { + //create subcription + const subcription = await web3.eth.subscribe("logs"); + + //print logs of the latest mined block + subcription.on("data", (data) => console.log(data)); +} + +// function to unsubscribe from a subscription +async function unsubscribe(subscription) { + await subscription.unsubscribe(); +} + +subscribe(); +unsubscribe(subscription); +``` + +### Pending Transactions + +- `newPendingTransactions`: implemented in the class [`NewPendingTransactionsSubscription`](/api/web3-eth/class/NewPendingTransactionsSubscription). +- `pendingTransactions`: same as `newPendingTransactions`. + +```ts +import { Web3 } from "web3"; + +const web3 = new Web3("wss://ethereum-rpc.publicnode.com"); + +async function subscribe() { + //create subcription + const subcription = await web3.eth.subscribe("pendingTransactions"); //or ("newPendingTransactions") + + //print tx hashs of pending transactions + subcription.on("data", (data) => console.log(data)); +} + +// function to unsubscribe from a subscription +async function unsubscribe(subscription) { + await subscription.unsubscribe(); +} + +subscribe(); +unsubscribe(subscription); +``` + +### Block headers + +- `newBlockHeaders`: implemented in the class [`NewHeadsSubscription`](/api/web3-eth/class/NewHeadsSubscription). +- `newHeads` same as `newBlockHeaders`. + +```ts +import { Web3 } from "web3"; + +const web3 = new Web3("wss://ethereum-rpc.publicnode.com"); + +async function subscribe() { + //create subcription + const subcription = await web3.eth.subscribe("newBlockHeaders"); //or ("newHeads") + + //print block header everytime a block is mined + subcription.on("data", (data) => console.log(data)); +} + +// function to unsubscribe from a subscription +async function unsubscribe(subscription) { + await subscription.unsubscribe(); +} + +subscribe(); +unsubscribe(subscription); +``` + +### Syncing + +- `syncing`: implemented in the class [`SyncingSubscription`](/api/web3-eth/class/SyncingSubscription) + +```ts +import { Web3 } from "web3"; + +const web3 = new Web3("wss://ethereum-rpc.publicnode.com"); + +async function subscribe() { + //create subcription + const subcription = await web3.eth.subscribe("syncing"); + + //this will return `true` when the node is syncing + //when it’s finished syncing will return `false`, for the `changed` event. + subcription.on("data", (data) => console.log(data)); +} + +// function to unsubscribe from a subscription +async function unsubscribe(subscription) { + await subscription.unsubscribe(); +} + +subscribe(); +unsubscribe(subscription); +``` + + diff --git a/docs/docs/guides/events_subscriptions/supported_subscriptions.md b/docs/docs/guides/events_subscriptions/supported_subscriptions.md deleted file mode 100644 index bb8b704dd62..00000000000 --- a/docs/docs/guides/events_subscriptions/supported_subscriptions.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -sidebar_position: 2 -sidebar_label: 'Supported Subscriptions' ---- - -# Supported Subscriptions - -web3.js supports the standard Ethereum subscriptions out of the box. And they are the ones registered inside [registeredSubscriptions](/api/web3-eth#registeredSubscriptions) object. Here are a list of them: - -- `logs`: implemented in the class [`LogsSubscription`](/api/web3-eth/class/LogsSubscription). -- `newBlockHeaders`: implemented in the class [`NewHeadsSubscription`](/api/web3-eth/class/NewHeadsSubscription). -- `newHeads` same as `newBlockHeaders`. -- `newPendingTransactions`: implemented in the class [`NewPendingTransactionsSubscription`](/api/web3-eth/class/NewPendingTransactionsSubscription). -- `pendingTransactions`: same as `newPendingTransactions`. -- `syncing`: implemented in the class [`SyncingSubscription`](/api/web3-eth/class/SyncingSubscription) From d4e937d82748f4b1f2e6e6747a64124c7c34d057 Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 19 Apr 2024 00:30:34 -0400 Subject: [PATCH 05/32] Fix towei scientific notation (#6908) * update utils * replace web3 eventemitter for eventemitter3 * update tests * update snapshot * remove connection error test * fix scientific notation * add error * add warnings and address feedback * update * update * add testcases * add more testcases * uses parsednumber * update test case * refactor * update changelog --------- Co-authored-by: Muhammad Altabba <24407834+Muhammad-Altabba@users.noreply.github.com> --- packages/web3-utils/CHANGELOG.md | 12 ++++++++-- packages/web3-utils/src/converters.ts | 22 +++++++++++++++++-- .../web3-utils/test/fixtures/converters.ts | 13 ++++++++++- .../web3-utils/test/unit/converters.test.ts | 14 ++++++++++++ 4 files changed, 56 insertions(+), 5 deletions(-) diff --git a/packages/web3-utils/CHANGELOG.md b/packages/web3-utils/CHANGELOG.md index 1ae402166d7..d0f162613d8 100644 --- a/packages/web3-utils/CHANGELOG.md +++ b/packages/web3-utils/CHANGELOG.md @@ -213,7 +213,15 @@ Documentation: ### Fixed -- fixed toHex incorrectly hexing Uint8Arrays and Buffer (#6957) -- fixed isUint8Array not returning true for Buffer (#6957) +- fixed toHex incorrectly hexing Uint8Arrays and Buffer (#6957) +- fixed isUint8Array not returning true for Buffer (#6957) ## [Unreleased] + +### Added + +- `toWei` add warning when using large numbers or large decimals that may cause precision loss (#6908) + +### Fixed + +- `toWei` support numbers in scientific notation (#6908) \ No newline at end of file diff --git a/packages/web3-utils/src/converters.ts b/packages/web3-utils/src/converters.ts index a8aef7699e7..55143a4277c 100644 --- a/packages/web3-utils/src/converters.ts +++ b/packages/web3-utils/src/converters.ts @@ -77,6 +77,8 @@ export const ethUnitMap = { tether: BigInt('1000000000000000000000000000000'), }; +const PrecisionLossWarning = 'Warning: Using type `number` with values that are large or contain many decimals may cause loss of precision, it is recommended to use type `string` or `BigInt` when using conversion methods'; + export type EtherUnits = keyof typeof ethUnitMap; /** * Convert a value from bytes to Uint8Array @@ -415,7 +417,8 @@ export const toHex = ( */ export const toNumber = (value: Numbers): number | bigint => { if (typeof value === 'number') { - if (value > 1e+20) { + if (value > 1e+20) { + console.warn(PrecisionLossWarning) // JavaScript converts numbers >= 10^21 to scientific notation when coerced to strings, // leading to potential parsing errors and incorrect representations. // For instance, String(10000000000000000000000) yields '1e+22'. @@ -555,17 +558,32 @@ export const toWei = (number: Numbers, unit: EtherUnits): string => { if (!denomination) { throw new InvalidUnitError(unit); } + let parsedNumber = number; + if (typeof parsedNumber === 'number'){ + if (parsedNumber < 1e-15){ + console.warn(PrecisionLossWarning) + } + if (parsedNumber > 1e+20) { + console.warn(PrecisionLossWarning) + parsedNumber = BigInt(parsedNumber); + } else { + // in case there is a decimal point, we need to convert it to string + parsedNumber = parsedNumber.toLocaleString('fullwide', {useGrouping: false, maximumFractionDigits: 20}) + } + } + // if value is decimal e.g. 24.56 extract `integer` and `fraction` part // to avoid `fraction` to be null use `concat` with empty string const [integer, fraction] = String( - typeof number === 'string' && !isHexStrict(number) ? number : toNumber(number), + typeof parsedNumber === 'string' && !isHexStrict(parsedNumber) ? parsedNumber : toNumber(parsedNumber), ) .split('.') .concat(''); // join the value removing `.` from // 24.56 -> 2456 + const value = BigInt(`${integer}${fraction}`); // multiply value with denomination diff --git a/packages/web3-utils/test/fixtures/converters.ts b/packages/web3-utils/test/fixtures/converters.ts index 8cf2c3d9e8d..91f3a76f738 100644 --- a/packages/web3-utils/test/fixtures/converters.ts +++ b/packages/web3-utils/test/fixtures/converters.ts @@ -300,9 +300,20 @@ export const fromWeiValidData: [[Numbers, EtherUnits], string][] = [ [[1.9999999999999991611392e+22, 'ether'], '19999.999999999991611392'], ]; -export const toWeiValidData: [[Numbers, EtherUnits], string][] = [ +export const toWeiValidData: [[Numbers, EtherUnits], Numbers][] = [ ...conversionBaseData, [['255', 'wei'], '0xFF'], + [['100000000000', 'ether'], 0.0000001], + [['1000000000', 'ether'], 0.000000001], + [['1000000', 'ether'], 0.000000000001] + +]; + +export const toWeiValidDataWarnings: [[Numbers, EtherUnits], string][] = [ + [[0.0000000000000000000001, 'ether'], 'Warning: Using type `number` with values that are large or contain many decimals may cause loss of precision, it is recommended to use type `string` or `BigInt` when using conversion methods'], + [[0.0000000000000000000001, 'ether'], 'Warning: Using type `number` with values that are large or contain many decimals may cause loss of precision, it is recommended to use type `string` or `BigInt` when using conversion methods'], + [[1999999000000009900000, 'kwei'], 'Warning: Using type `number` with values that are large or contain many decimals may cause loss of precision, it is recommended to use type `string` or `BigInt` when using conversion methods'], + ]; export const fromWeiInvalidData: [[any, any], string][] = [ diff --git a/packages/web3-utils/test/unit/converters.test.ts b/packages/web3-utils/test/unit/converters.test.ts index cb6fa58caa0..940590f06e7 100644 --- a/packages/web3-utils/test/unit/converters.test.ts +++ b/packages/web3-utils/test/unit/converters.test.ts @@ -63,6 +63,7 @@ import { toHexInvalidData, toWeiInvalidData, toWeiValidData, + toWeiValidDataWarnings, utf8ToHexInvalidData, utf8ToHexValidData, toCheckSumValidData, @@ -365,6 +366,19 @@ describe('converters', () => { expect(() => toWei(input[0], input[1])).toThrow(output); }); }); + describe('test console warnings', () => { + beforeEach(() => { + jest.spyOn(console, 'warn').mockImplementation(() => { + // do nothing + }); + }); + it.each(toWeiValidDataWarnings)('%s', (input, output) => { + toWei(input[0], input[1]); + // expect(() => toWei(input[0], input[1])).toThrow(output); + expect(console.warn).toHaveBeenCalledWith(output) + }); + + }) }); describe('toChecksumAddress', () => { describe('valid cases', () => { From 53e24664e4c660826eb10207b480848e677a73e6 Mon Sep 17 00:00:00 2001 From: Max <82761650+MaxMustermann2@users.noreply.github.com> Date: Mon, 22 Apr 2024 22:21:38 +0530 Subject: [PATCH 06/32] fix(validator): generate abi name if not provided (#6981) * fix(validator): generate abi name if not provided In the case of public mappings, the ABI generated has a blank name set. This results in blank ids for such inputs within the JSON schema. Post 1f81ff097cf548a327fb72537dbabf2126e616d0, the number of unique ids is used to convert the JSON scheme into Zod, and hence the presence of blank ids is a concern. This commit generates the `abiName` if one is not provided to a value equal to the `${level}/${index}`. Fixes #6965. * fix: add validator changes to root CHANGELOG --------- Co-authored-by: Alex --- CHANGELOG.md | 1 + packages/web3-validator/CHANGELOG.md | 2 +- packages/web3-validator/src/utils.ts | 2 +- .../test/fixtures/abi_to_json_schema.ts | 34 +++++++++++++++++++ 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dcedf476330..873afc8c4ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2477,3 +2477,4 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3-validator +- The JSON schema conversion process now correctly assigns an id when the `abi.name` is not available, for example, in the case of public mappings. (#6981) \ No newline at end of file diff --git a/packages/web3-validator/CHANGELOG.md b/packages/web3-validator/CHANGELOG.md index 07ba353112d..dc5834852ca 100644 --- a/packages/web3-validator/CHANGELOG.md +++ b/packages/web3-validator/CHANGELOG.md @@ -172,4 +172,4 @@ Documentation: ### Fixed -- Nodejs Buffer is not recognized as valid bytes value +- The JSON schema conversion process now correctly assigns an id when the `abi.name` is not available, for example, in the case of public mappings. diff --git a/packages/web3-validator/src/utils.ts b/packages/web3-validator/src/utils.ts index 36a65e3f122..6f9fd6f7f55 100644 --- a/packages/web3-validator/src/utils.ts +++ b/packages/web3-validator/src/utils.ts @@ -141,7 +141,7 @@ export const abiSchemaToJsonSchema = ( // e.g. {name: 'a', type: 'uint'} if (isAbiParameterSchema(abi)) { abiType = abi.type; - abiName = abi.name; + abiName = abi.name || `${level}/${index}`; abiComponents = abi.components as FullValidationSchema; // If its short form string value e.g. ['uint'] } else if (typeof abi === 'string') { diff --git a/packages/web3-validator/test/fixtures/abi_to_json_schema.ts b/packages/web3-validator/test/fixtures/abi_to_json_schema.ts index 35ed35bce6f..e9e4391700c 100644 --- a/packages/web3-validator/test/fixtures/abi_to_json_schema.ts +++ b/packages/web3-validator/test/fixtures/abi_to_json_schema.ts @@ -157,6 +157,40 @@ const abiToJsonSchemaCases: AbiToJsonSchemaCase[] = [ }, }, + // this is for public mappings case where the abi has no name + { + title: 'multiple params of different types without name', + abi: { + fullSchema: [ + { name: '', type: 'uint' }, + { name: '', type: 'int' }, + ], + shortSchema: ['uint', 'int'], + data: [12, -1], + }, + json: { + fullSchema: { + type: 'array', + items: [ + { $id: '/0/0', format: 'uint', required: true }, + { $id: '/0/1', format: 'int', required: true }, + ], + minItems: 2, + maxItems: 2, + }, + shortSchema: { + type: 'array', + items: [ + { $id: '/0/0', format: 'uint', required: true }, + { $id: '/0/1', format: 'int', required: true }, + ], + minItems: 2, + maxItems: 2, + }, + data: [12, -1], + }, + }, + { title: 'single param array', abi: { From 7be0060ff457119bdbb642afcafa3bbe651fd31a Mon Sep 17 00:00:00 2001 From: Santiago Trujillo Zuluaga Date: Tue, 23 Apr 2024 11:47:09 +0300 Subject: [PATCH 07/32] Plugin guide 6840 draft (#6941) * renamed to getting started * added eth and utils example * created getting started plugin - THERE ARE SOME `TO DOs` * added other packages * changed requires for import statements * removed initialize a provider --- .../guides/web3_plugin_guide/_category_.yml | 2 +- docs/docs/guides/web3_plugin_guide/index.md | 295 ++++++++++++++++-- 2 files changed, 263 insertions(+), 34 deletions(-) diff --git a/docs/docs/guides/web3_plugin_guide/_category_.yml b/docs/docs/guides/web3_plugin_guide/_category_.yml index afd1de17e96..daec6ebe046 100644 --- a/docs/docs/guides/web3_plugin_guide/_category_.yml +++ b/docs/docs/guides/web3_plugin_guide/_category_.yml @@ -1,4 +1,4 @@ -label: '🧩🛠️ Web3 Plugin' +label: '🛠️ Web3 Plugin🧩' collapsible: true collapsed: true link: null diff --git a/docs/docs/guides/web3_plugin_guide/index.md b/docs/docs/guides/web3_plugin_guide/index.md index 365ca7b82f1..0e23b5a85e7 100644 --- a/docs/docs/guides/web3_plugin_guide/index.md +++ b/docs/docs/guides/web3_plugin_guide/index.md @@ -1,50 +1,279 @@ --- sidebar_position: 1 -sidebar_label: 'Introduction' +sidebar_label: 'Getting started' --- -# Introduction +# Getting Started -Welcome to the web3.js Plugins Guide, an exciting new feature introduced in web3.js v4! In addition to the core web3.js libraries, plugins bring specialized functionalities tailored for end-users (functionalities that you, as a developer, can create). These enhancements may involve creating wrappers for specific contracts, adding extra features to RPC methods, or extending the capabilities of web3.js methods. Dive in and explore this innovative addition to web3.js v4! +Welcome to the Web3 Plugins🧩 Guide, a new feature introduced in web3.js v4. In addition to the core web3.js libraries, plugins bring specialized functionalities tailored for end-users (functionalities, that you, as a developer, can create). These enhancements may involve creating wrappers for specific contracts, adding extra features to RPC methods, adding any external libraries, logic, extending the capabilities of web3.js methods, etc... + +In this guide, you will learn the basics to get started building web3 plugins, setting up providers, importing, and using different web3.js packages. - [Plugin Developer Guide (For Creators)](/guides/web3_plugin_guide/plugin_authors) - [Plugin User Guide (Usage)](/guides/web3_plugin_guide/plugin_users) -- [Plugin List](https://web3js.org/plugins) +- You can find all the web3 plugins🧩 [here](https://web3js.org/plugins) + +- To list your web3 plugin🧩 into the web3js.org/plugins page, you can submit a PR [here](https://github.com/web3/web3js-landing/blob/main/src/pluginList.ts) + +## Create a plugin + +```javascript +//1. import the `Web3PluginBase` module +import { Web3PluginBase } from "web3"; + +//2. Create a Class extending the `Web3Pluginbase` +class MyPlugin extends Web3PluginBase { + + //3. Add a name to the plugin + pluginNamespace = "pluginExample"; + + //4. Create any methods with your desired functionality + async doSomething(){ + console.log("Hello web3!"); + //send transactions + //initialize contracts + //deploy or interact with contracts + //add your own library, logic or functionality + //much more... + } +} + +module.exports = MyPlugin; +``` + +## Use a plugin + +```javascript +//1. import the plugin and web3 module +import { Web3 } from "web3"; +import MyPlugin from "./plugin"; + +//2. Initialize the web3 instance +const web3 = new Web3("https://eth.llamarpc.com"); + +//3. Register plugin to add the current Web3Context +web3.registerPlugin(new MyPlugin()); + +//4. Use the plugin methods +web3.pluginExample.doSomething(); +//--> Hello web3! +``` + +## Using web3 packages on the plugin + +### Use Eth module + +```js +import { FMT_NUMBER, Web3PluginBase, eth } from 'web3'; + +class MyPlugin extends Web3PluginBase { + pluginNamespace = 'pluginExample'; + + async getChainId() { + //`this` is the web3context used when you register the plugin in the usage + return await eth.getChainId(this, { number: FMT_NUMBER.NUMBER }); + } + + async getBlockNumber() { + return await eth.getBlockNumber(this, { number: FMT_NUMBER.NUMBER }); + } + + //more web3.eth. methods... +} + +export default MyPlugin; +``` + +### Use Utils + +```js +import { Web3PluginBase, utils } from 'web3'; + +class MyPlugin extends Web3PluginBase { + pluginNamespace = 'pluginExample'; + + weiToEth(value) { + //`this` is the web3context used when you register the plugin in the usage + return utils.fromWei(value, 'ether'); + } + + //more web3.eth. methods... +} + +export default MyPlugin; + +``` + + +### Use Accounts + + +```js +import { Web3PluginBase, eth } from 'web3'; + +class MyPlugin extends Web3PluginBase { + pluginNamespace = 'pluginExample'; + + async createAccount() { + const account = eth.accounts.create(); + console.log("account:", account); + /* + account: { + address: '0x59E797F2F66AffA9A419a6BC2ED4742b7cBc2570', + privateKey: '0x52a81fc3a7fd6ce9644147c9fb5bfbe1f708f37b4611b3c3310eb9a6dc85ccf4', + signTransaction: [Function: signTransaction], + sign: [Function: sign], + encrypt: [Function: encrypt] + } + */ + } +} + +export default MyPlugin; +``` + +### Use Wallet + + +```js +import { Web3PluginBase, eth } from 'web3'; + +class MyPlugin extends Web3PluginBase { + pluginNamespace = 'pluginExample'; + + async createWallet() { + //1. Create a random account + const accounts = eth.accounts.create(); + //2. Add the account to the wallet + const wallet = this.wallet.add(accounts); + //by creating the wallet, web3.js will use this account to sign TXs under the hood + console.log(wallet); + /* + Wallet(1) [ + { + address: '0x233725561B1430bE2C24Ce9EEabe63E4B46EC9E3', + privateKey: '0x6856adf06dd803e0354450ccf251f829a2c9ef1177ce371f8835bbfb56cd0898', + signTransaction: [Function: signTransaction], + sign: [Function: sign], + encrypt: [Function: encrypt] + }, + _accountProvider: { + create: [Function: createWithContext], + privateKeyToAccount: [Function: privateKeyToAccountWithContext], + decrypt: [Function: decryptWithContext] + }, + _addressMap: Map(1) { '0x233725561b1430be2c24ce9eeabe63e4b46ec9e3' => 0 }, + _defaultKeyName: 'web3js_wallet' + ] + */ + } +} + +export default MyPlugin; +``` + + +### Use Contract + + +```js +import { Web3PluginBase, Contract } from 'web3'; + +class MyPlugin extends Web3PluginBase { + pluginNamespace = 'pluginExample'; + + async interactWithContract() { + //1. Initialize contract + const myContract = new Contract(ABI, ADDRESS); + + //2. Interact with reading functions + const response = myContract.methods.doSomething().call(); + + //3. Interact with writing functions + //You must initialize a wallet to be able to send the TX from wallet[0].address + const txReceipt = myContract.methods.doSomething().send({from: wallet[0].address}) + } +} + +export default MyPlugin; +``` + +### Use ENS + +```js +import { Web3PluginBase } from "web3"; +import { ENS } from "web3-eth-ens"; + +class MyPlugin extends Web3PluginBase { + pluginNamespace = "pluginExample"; + + async getAddressENS() { + const ens = new ENS(undefined, this); //link to current web3Context + return ens.getAddress("ethereum.eth"); + } + +} + +``` +:::info +More ENS methods [here](https://docs.web3js.org/libdocs/ENS#methods) +::: + + +## Web3 requestManager (custom RPC) + +```js +import { Web3PluginBase } from 'web3'; + +class MyPlugin extends Web3PluginBase { + pluginNamespace = 'pluginExample'; + + async customRPC() { + return await this.requestManager.send({ + method: "custom_RPC_call", + params: [], + }); + } -## Plugin Showcase + async getNonce() { + return await this.requestManager.send({ + jsonrpc: "2.0", + method: "eth_getTransactionCount", + params: ["0xEA9eEca67682Cd9c6Ce3DdD1681049D7A897289F", "latest"], + }); + } -### Chainlink Plugin -- [`npm i @chainsafe/web3-plugin-chainlink`](https://www.npmjs.com/package/@chainsafe/web3-plugin-chainlink) -- **Description**: A Web3.js 4.x Plugin for Interacting With Chainlink Smart Contracts -- **Author**: ChainSafe Systems + async getBlockNumber() { + return await this.requestManager.send({ + jsonrpc: "2.0", + method: "eth_blockNumber", + params: [], + }); + } -### Tokens Plugin -- [`npm i @chainsafe/web3-plugin-tokens`](https://www.npmjs.com/package/@chainsafe/web3-plugin-tokens) -- **Description**: Plugin to extend web3.js with additional methods to interact with common token interfaces (ERC20, ERC721, ERC1155...) -- **Author**: Peter Grassberger & ChainSafe +} +``` -### Craftsman Plugin -- [`npm i web3-plugin-craftsman`](https://www.npmjs.com/package/web3-plugin-craftsman) -- **Description**: web3.js plugin allowing instantiation of contract objects directly from Solidity source code -- **Author**: Muhammad-Altabba +:::info +All the Ethereum JSON-RPC API [here](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gettransactioncount) +::: -### Optimism Plugin -- [`npm i @eth-optimism/web3.js-plugin`](https://www.npmjs.com/package/@eth-optimism/web3.js-plugin) -- **Description**: Web3.js plugin for OP-Chain gas estimation -- **Author**: Unknown +## Web3 Config Params -### Near Protocol Plugin -- [`npm i @conx3/web3-plugin-near`](https://npmjs.com/package/@conx3/web3-plugin-near) -- **Description**: web3.js plugin for Near Protocol -- **Author**: Muhammad Altabba +```js +import { Web3PluginBase } from 'web3'; -### Aurora Engine Plugin -- [`npm i @conx3/web3-plugin-aurora`](https://www.npmjs.com/package/@conx3/web3-plugin-aurora) -- **Description**: web3.js plugin for Aurora Engine, an EVM running atop NEAR protocol -- **Author**: Muhammad Altabba +class MyPlugin extends Web3PluginBase { + pluginNamespace = 'pluginExample'; -### Superfluid Plugin -- [`npm i web3-plugin-superfluid`](https://www.npmjs.com/package/web3-plugin-superfluid) -- **Description**: Superfluid Web3.js Plugin -- **Author**: Salman Dabbakuti + async configParams() { + this.config.handleRevert = true; + this.config.defaultTransactionType = 0x1; + //more params... + } +} +``` +:::info +All web3 config params [here](https://docs.web3js.org/guides/web3_config/) +::: \ No newline at end of file From 5fd9dbb2eda58b22c1d83033e6c2d2a263b3b9e6 Mon Sep 17 00:00:00 2001 From: Santiago Trujillo Zuluaga Date: Tue, 23 Apr 2024 17:14:02 +0300 Subject: [PATCH 08/32] Compare package size (wihtout image) (#6994) * Added comaparison for package size * Added advantages over other libraries * added packge size in minified gzipped * Update introduction.md * removed image --------- Co-authored-by: DrParadox! --- docs/docs/guides/getting_started/introduction.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/docs/guides/getting_started/introduction.md b/docs/docs/guides/getting_started/introduction.md index 30a031a5f1f..ab9a303fc84 100644 --- a/docs/docs/guides/getting_started/introduction.md +++ b/docs/docs/guides/getting_started/introduction.md @@ -55,4 +55,12 @@ Web3.js is modular, consisting of several packages, each serving specific functi - **Web3 Errors:** Web3 Errors has error codes and common error classes that are used by other Web3 packages. -- **Web3 RPC Methods:** This is for advanced uses for building more lightweight applications. It has functions for making RPC requests to Ethereum using a given provider. \ No newline at end of file +- **Web3 RPC Methods:** This is for advanced uses for building more lightweight applications. It has functions for making RPC requests to Ethereum using a given provider. + +## Advantages over other libraries + +- **Extensive Documentation and Community**: Being one of the earliest Ethereum libraries, Web3.js benefits from extensive documentation and a large, active community. Web3.js is widely adopted and has been thoroughly tested in various production environments and is compatible with a broad range of other tools and services in the Ethereum ecosystem. + +- **Modular Design**: Web3.js is designed to be modular, meaning it allows developers to use specific packages according to their needs. This may lead to smaller bundle sizes and faster load times for web applications. + +- **Active Development and Support**: Web3.js sees regular updates and active development. This support is crucial for developers needing assurance that the library they're using will keep pace with the evolving Ethereum landscape. From ed2781f3756162ac2ece03a1b5b026f3b4e24401 Mon Sep 17 00:00:00 2001 From: Santiago Trujillo Zuluaga Date: Thu, 25 Apr 2024 16:13:03 +0300 Subject: [PATCH 09/32] fixed broken links (#7005) --- docs/docs/guides/events_subscriptions/custom_subscriptions.md | 2 +- docs/docs/guides/events_subscriptions/index.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docs/guides/events_subscriptions/custom_subscriptions.md b/docs/docs/guides/events_subscriptions/custom_subscriptions.md index 7dbf1df1990..c57def91b7b 100644 --- a/docs/docs/guides/events_subscriptions/custom_subscriptions.md +++ b/docs/docs/guides/events_subscriptions/custom_subscriptions.md @@ -8,7 +8,7 @@ sidebar_label: 'Custom Subscriptions' You can extend the `Web3Subscription` class to create custom subscriptions. This way you can subscribe to custom events emitted by the provider. :::note -This guide is most likely for advanced users who are connecting to a node that provides additional custom subscriptions. For normal users, the standard subscriptions are supported out of the box as you can find in [Supported Subscriptions](/guides/events_subscriptions/supported_subscriptions). +This guide is most likely for advanced users who are connecting to a node that provides additional custom subscriptions. For normal users, the standard subscriptions are supported out of the box as you can find in [Supported Subscriptions](/guides/events_subscriptions/index.md). ::: :::important diff --git a/docs/docs/guides/events_subscriptions/index.md b/docs/docs/guides/events_subscriptions/index.md index 445e7edc568..b17baceec12 100644 --- a/docs/docs/guides/events_subscriptions/index.md +++ b/docs/docs/guides/events_subscriptions/index.md @@ -36,7 +36,7 @@ unsubscribe(subscription); ## Subscribing to node events -A standard Ethereum node like [Geth supports subscribing to specific events](https://geth.ethereum.org/docs/interacting-with-geth/rpc/pubsub#supported-subscriptions). Additionally, there are some Ethereum nodes that provide additional custom subscriptions. As you can find in [Supported Subscriptions](/guides/events_subscriptions/supported_subscriptions) guide, web3.js enables you to subscribe to the standard events out of the box. And it also provides you with the capability to subscribe to custom subscriptions as you can find in the [Custom Subscriptions](/guides/events_subscriptions/custom_subscriptions) guide. +A standard Ethereum node like [Geth supports subscribing to specific events](https://geth.ethereum.org/docs/interacting-with-geth/rpc/pubsub#supported-subscriptions). Additionally, there are some Ethereum nodes that provide additional custom subscriptions. As you can find in this guide, web3.js enables you to subscribe to the standard events out of the box. And it also provides you with the capability to subscribe to custom subscriptions as you can find in the [Custom Subscriptions](/guides/events_subscriptions/custom_subscriptions) guide. :::important If you are the developer who provides custom subscriptions to users. We encourage you to develop a web3.js Plugin after you go through the [Custom Subscription](#custom-subscription) section below. You can find how to develop a plugin at [web3.js Plugin Developer Guide](/guides/web3_plugin_guide/plugin_authors) From 419c8d3eb8e5a66669da2dd6e145faceb5143c5c Mon Sep 17 00:00:00 2001 From: Santiago Trujillo Zuluaga Date: Thu, 25 Apr 2024 18:33:47 +0300 Subject: [PATCH 10/32] Added plugin videos to guide (#7004) * added videos to the guide * added videos to the guide * installed react-player * update links * changed react player for youtube embed * removed react-player and docusaurus * fixed comma --- .../web3_plugin_guide/{index.md => index.mdx} | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) rename docs/docs/guides/web3_plugin_guide/{index.md => index.mdx} (89%) diff --git a/docs/docs/guides/web3_plugin_guide/index.md b/docs/docs/guides/web3_plugin_guide/index.mdx similarity index 89% rename from docs/docs/guides/web3_plugin_guide/index.md rename to docs/docs/guides/web3_plugin_guide/index.mdx index 0e23b5a85e7..69a39859415 100644 --- a/docs/docs/guides/web3_plugin_guide/index.md +++ b/docs/docs/guides/web3_plugin_guide/index.mdx @@ -276,4 +276,16 @@ class MyPlugin extends Web3PluginBase { ``` :::info All web3 config params [here](https://docs.web3js.org/guides/web3_config/) -::: \ No newline at end of file +::: + + +## Videos + +### Create your first plugin in 20 minutes! + + + + +### Chainlink plugin: web3.js, viem, ethers vs web3 plugin🧩 + + From de3e8f881cc12ca6bbeddaf992c18c6c4eb1ede0 Mon Sep 17 00:00:00 2001 From: Santiago Trujillo Zuluaga Date: Fri, 26 Apr 2024 22:22:33 +0300 Subject: [PATCH 11/32] Utils guide (#7008) * added utils guide * reorder sidebar * added args to avoid error when copy/pasting example --- docs/docs/guides/advanced/_category_.yml | 2 +- .../events_subscriptions/_category_.yml | 2 +- docs/docs/guides/feedback/index.md | 2 +- docs/docs/guides/glossary/index.md | 2 +- .../guides/hardhat_tutorial/_category_.yml | 2 +- .../migration_from_other_libs/_category_.yml | 2 +- .../guides/smart_contracts/_category_.yml | 2 +- docs/docs/guides/wagmi_usage/_category_.yml | 2 +- docs/docs/guides/wallet/_category_.yml | 2 +- docs/docs/guides/web3_config/_category_.yml | 2 +- docs/docs/guides/web3_eth/_category_.yml | 4 +- .../guides/web3_plugin_guide/_category_.yml | 4 +- .../web3_providers_guide/_category_.yml | 2 +- .../guides/web3_upgrade_guide/_category_.yml | 2 +- .../guides/web3_utils_module/_category_.yml | 5 + .../web3_utils_module/mastering_web3-utils.md | 241 ++++++++++++++++++ 16 files changed, 262 insertions(+), 16 deletions(-) create mode 100644 docs/docs/guides/web3_utils_module/_category_.yml create mode 100644 docs/docs/guides/web3_utils_module/mastering_web3-utils.md diff --git a/docs/docs/guides/advanced/_category_.yml b/docs/docs/guides/advanced/_category_.yml index 2abe6bbdc6a..dab551977cf 100644 --- a/docs/docs/guides/advanced/_category_.yml +++ b/docs/docs/guides/advanced/_category_.yml @@ -2,4 +2,4 @@ label: '🧠 Advanced' collapsible: true collapsed: true link: null -position: 12 \ No newline at end of file +position: 14 \ No newline at end of file diff --git a/docs/docs/guides/events_subscriptions/_category_.yml b/docs/docs/guides/events_subscriptions/_category_.yml index 528836749db..2f13d5222b4 100644 --- a/docs/docs/guides/events_subscriptions/_category_.yml +++ b/docs/docs/guides/events_subscriptions/_category_.yml @@ -2,4 +2,4 @@ label: '🔔 Events subscription' collapsible: true collapsed: true link: null -position: 6 \ No newline at end of file +position: 7 \ No newline at end of file diff --git a/docs/docs/guides/feedback/index.md b/docs/docs/guides/feedback/index.md index f096d471236..228003d5a6e 100644 --- a/docs/docs/guides/feedback/index.md +++ b/docs/docs/guides/feedback/index.md @@ -1,5 +1,5 @@ --- -sidebar_position: 15 +sidebar_position: 17 sidebar_label: '🗣️ Feedback' --- diff --git a/docs/docs/guides/glossary/index.md b/docs/docs/guides/glossary/index.md index e8962c28966..39294de39ed 100644 --- a/docs/docs/guides/glossary/index.md +++ b/docs/docs/guides/glossary/index.md @@ -1,5 +1,5 @@ --- -sidebar_position: 14 +sidebar_position: 18 sidebar_label: '📖 Glossary' title: Glossary --- diff --git a/docs/docs/guides/hardhat_tutorial/_category_.yml b/docs/docs/guides/hardhat_tutorial/_category_.yml index dfd158abb00..191ad0faa29 100644 --- a/docs/docs/guides/hardhat_tutorial/_category_.yml +++ b/docs/docs/guides/hardhat_tutorial/_category_.yml @@ -2,4 +2,4 @@ label: '⛑️ Hardhat Tutorial' collapsible: true collapsed: true link: null -position: 2 +position: 3 diff --git a/docs/docs/guides/migration_from_other_libs/_category_.yml b/docs/docs/guides/migration_from_other_libs/_category_.yml index dc10487c990..665581166bc 100644 --- a/docs/docs/guides/migration_from_other_libs/_category_.yml +++ b/docs/docs/guides/migration_from_other_libs/_category_.yml @@ -2,4 +2,4 @@ label: '🔄 Migration Guides' collapsible: true collapsed: true link: null -position: 11 \ No newline at end of file +position: 12 \ No newline at end of file diff --git a/docs/docs/guides/smart_contracts/_category_.yml b/docs/docs/guides/smart_contracts/_category_.yml index 6bf6e7694db..fcbba9574a5 100644 --- a/docs/docs/guides/smart_contracts/_category_.yml +++ b/docs/docs/guides/smart_contracts/_category_.yml @@ -2,4 +2,4 @@ label: '📜 Smart Contracts' collapsible: true collapsed: true link: null -position: 4 \ No newline at end of file +position: 6 \ No newline at end of file diff --git a/docs/docs/guides/wagmi_usage/_category_.yml b/docs/docs/guides/wagmi_usage/_category_.yml index a314e00849b..90b55da4312 100644 --- a/docs/docs/guides/wagmi_usage/_category_.yml +++ b/docs/docs/guides/wagmi_usage/_category_.yml @@ -2,4 +2,4 @@ label: '🔄 Wagmi usage' collapsible: true collapsed: true link: null -position: 11 +position: 13 diff --git a/docs/docs/guides/wallet/_category_.yml b/docs/docs/guides/wallet/_category_.yml index d96e556347b..6b079975e01 100644 --- a/docs/docs/guides/wallet/_category_.yml +++ b/docs/docs/guides/wallet/_category_.yml @@ -2,4 +2,4 @@ label: '🔑 Wallet and Accounts ' collapsible: true collapsed: true link: null -position: 3 \ No newline at end of file +position: 5 \ No newline at end of file diff --git a/docs/docs/guides/web3_config/_category_.yml b/docs/docs/guides/web3_config/_category_.yml index 4c1d5ddbd90..dbe4222696b 100644 --- a/docs/docs/guides/web3_config/_category_.yml +++ b/docs/docs/guides/web3_config/_category_.yml @@ -2,4 +2,4 @@ label: '⚙️ Web3 config' collapsible: true collapsed: true link: null -position: 9 \ No newline at end of file +position: 15 \ No newline at end of file diff --git a/docs/docs/guides/web3_eth/_category_.yml b/docs/docs/guides/web3_eth/_category_.yml index f7e09e00d19..197604038d5 100644 --- a/docs/docs/guides/web3_eth/_category_.yml +++ b/docs/docs/guides/web3_eth/_category_.yml @@ -1,5 +1,5 @@ -label: '📦 Web3Eth module' +label: '📦 Web3 Eth module' collapsible: true collapsed: true link: null -position: 7 \ No newline at end of file +position: 8 \ No newline at end of file diff --git a/docs/docs/guides/web3_plugin_guide/_category_.yml b/docs/docs/guides/web3_plugin_guide/_category_.yml index daec6ebe046..42237f7ea38 100644 --- a/docs/docs/guides/web3_plugin_guide/_category_.yml +++ b/docs/docs/guides/web3_plugin_guide/_category_.yml @@ -1,5 +1,5 @@ -label: '🛠️ Web3 Plugin🧩' +label: '🛠️ Web3 Plugin 🧩' collapsible: true collapsed: true link: null -position: 13 \ No newline at end of file +position: 2 \ No newline at end of file diff --git a/docs/docs/guides/web3_providers_guide/_category_.yml b/docs/docs/guides/web3_providers_guide/_category_.yml index 3b85fe4849e..f426dbedf9a 100644 --- a/docs/docs/guides/web3_providers_guide/_category_.yml +++ b/docs/docs/guides/web3_providers_guide/_category_.yml @@ -2,4 +2,4 @@ label: '🔌 Providers' collapsible: true collapsed: true link: null -position: 2 \ No newline at end of file +position: 4 \ No newline at end of file diff --git a/docs/docs/guides/web3_upgrade_guide/_category_.yml b/docs/docs/guides/web3_upgrade_guide/_category_.yml index e3022cfe8fd..aeab3125b26 100644 --- a/docs/docs/guides/web3_upgrade_guide/_category_.yml +++ b/docs/docs/guides/web3_upgrade_guide/_category_.yml @@ -2,4 +2,4 @@ label: '⬆️ Upgrading' collapsible: true collapsed: true link: null -position: 10 \ No newline at end of file +position: 11 \ No newline at end of file diff --git a/docs/docs/guides/web3_utils_module/_category_.yml b/docs/docs/guides/web3_utils_module/_category_.yml new file mode 100644 index 00000000000..95a9529cfce --- /dev/null +++ b/docs/docs/guides/web3_utils_module/_category_.yml @@ -0,0 +1,5 @@ +label: '📦 Web3 Utils module' +collapsible: true +collapsed: true +link: null +position: 10 \ No newline at end of file diff --git a/docs/docs/guides/web3_utils_module/mastering_web3-utils.md b/docs/docs/guides/web3_utils_module/mastering_web3-utils.md new file mode 100644 index 00000000000..7bad9e3b396 --- /dev/null +++ b/docs/docs/guides/web3_utils_module/mastering_web3-utils.md @@ -0,0 +1,241 @@ +# Mastering Utility Functions + +## Introduction +In this guide, you'll learn about the different functions of the web3 utils package, it contains the methods to know how to generate random bytes in different formats, how to perform conversion between Hex values and numbers, hashing functions, addresses, packing padding and in the last part you will see how to compare block numbers. + +## Installation + +Install only the web3 package +```bash +npm i web3-utils +``` + +Or you can install the web3 library as well and then access web3.utils + +```bash +npm i web3 +``` + +## Imports + +There are three different ways to import utils package. + +### Import the entire web3 library + +```js +// import web3 module +import { Web3 } from "web3"; + +// no need to initialize a provider +Web3.utils.toHex("web3"); +//=> 0x77656233 + +// initializing a provider +const web3 = new Web3("https:// eth.llamarpc.com"); + +// access the utils package +web3.utils.toHex("web3"); +//=> 0x77656233 +``` + + +### Import utils module + +```js +// import utils module +import { utils } from "web3"; + +// access the utils package +utils.toWei("1", "ether") +``` + +### Import specific methods + +```js +// import toWei and toHex functions +import { toWei, toHex } from"web3-utils"; + +// usage +toWei("1", "ether") +toHex("") +``` + +## Methods example + +### Random Hex and Bytes + +```js +// Random bytes in hex format and array format + +console.log(web3.utils.randomBytes(32)); +/* => array format +Uint8Array(32) [ + 251, 70, 124, 65, 203, 180, 92, 234, + 210, 236, 72, 154, 83, 219, 171, 223, + 212, 136, 117, 140, 67, 117, 86, 81, + 234, 245, 148, 186, 175, 83, 98, 78 +] +*/ + +console.log(web3.utils.randomHex(32)); +/* => hex string format +0x594386dc9b2e150979416f9b2a093e01f84a37c4f8db5fc1b0d9b1dc83a12c1f +*/ + +``` +:::info +If you don't give any arguments then both of these functions will have a default value as 32. +::: + +### Conversions - Ethereum Denominations + +We've got two different functions to perform conversions between Ethereum denominations. + +```js +console.log(web3.utils.fromWei("1", "ether")); +// 0.000000000000000001 + +console.log(web3.utils.toWei("1", "ether")); +// 1_000_000_000_000_000_000 +``` + +### Conversions to Hex Values + +```js +// most versatile one +console.log(web3.utils.toHex(10)); +// 0xa + +console.log(web3.utils.toHex(true)); +// 0x01 + +console.log(web3.utils.numberToHex(10)); +// 0xa + +console.log(web3.utils.fromDecimal(10)); +// 0xa + +const arr = new Uint8Array([1, 2, 3, 4]); + +console.log(web3.utils.toHex(arr)); +// 0x7b2230223a312c2231223a322c2232223a332c2233223a347d + +console.log(web3.utils.bytesToHex(arr)); +// 0x01020304 +``` + +### Conversions UTF and ASCII + +```js +console.log(web3.utils.utf8ToHex("😊")); +// 0xf09f988a + +console.log(web3.utils.fromUtf8("😊")); +// 0xf09f988a + +console.log(web3.utils.asciiToHex("😊")); +// 0xd83dde0a + +console.log(web3.utils.toUtf8("0xf09f988a")); +// 😊 + +console.log(web3.utils.hexToUtf8("0xf09f988a")); +// 😊 + +console.log(web3.utils.hexToString("0xf09f988a")); +// 😊 + +// emojis are not ASCII character, that's why it won't work +console.log(web3.utils.toAscii("0x4869")); +// Hi + +console.log(web3.utils.hexToAscii("0x4869")); +// Hi +``` + +### Conversions - Numbers and Bigint + +```js +console.log(web3.utils.toNumber("0xa")); +// 10 (number) + +console.log(web3.utils.hexToNumber("0xa")); +// 10 (number) + +console.log(web3.utils.toDecimal("0xa")); +// 10 (number) + +console.log(web3.utils.hexToNumberString("0xa")); +// 10 (string) + +console.log(web3.utils.toBigInt("0xa")); +// 10n (bigint) +``` + +### Hashing Functions + +```js +// both will return undefined if an empty string is passed as an argument +console.log(web3.utils.sha3("hello web3")); +// 0x6c171485a0138b7b0a49d72b570e1d9c589d42a79ae57329d90671d1ac702d74 + +console.log(web3.utils.soliditySha3({ type: "string", value: "hello web3" })); +// 0x6c171485a0138b7b0a49d72b570e1d9c589d42a79ae57329d90671d1ac702d74 +``` + +### Addresses + +```js +// isAddress() is deprecated so we can use toCheckSumAddress() +// to see if the hex string we are passing is a correct ethereum address + +// passing an address with all characters lowercase +console.log(web3.utils.toChecksumAddress("0xa3286628134bad128faeef82f44e99aa64085c94")); +// 0xA3286628134baD128faeef82F44e99AA64085C94 + +// passing an wrong address +console.log(web3.utils.toChecksumAddress("0xa3286628134bad128faeef82f44e99aa64085c9")); +// InvalidAddressError: Invalid value given "0xa286628134bad128faeef82f44e99aa64085c94". Error: invalid ethereum address. +``` + +### Packing and Padding + +```js +// same as abi.encodePacked() in solidity (must be strings) +// converts everything to hex and packs everything without padding +console.log(web3.utils.encodePacked("1", "1", "1")); +// 0x313131 + + +// it will convert the number `10` to hex('a') and add 0s until it's 32 characters long +// the third argument will be the one that will fill/pad the whole hex string, in this case is '0' +console.log(web3.utils.padRight(10, 32, 0)); +// 0xa0000000000000000000000000000000 + +console.log(web3.utils.rightPad(10, 32, 0)); +// 0xa0000000000000000000000000000000 + +console.log(web3.utils.padLeft(10, 32, 0)); +// 0x0000000000000000000000000000000a + +console.log(web3.utils.leftPad(10, 32, 0)); +// 0x0000000000000000000000000000000a +``` + +### Compare Block Numbers + +```js +// accepts numbers and formats as well +console.log(web3.utils.compareBlockNumbers("pending", "latest")); +// 1 + +console.log(web3.utils.compareBlockNumbers("latest", "pending")); +// -1 + +console.log(web3.utils.compareBlockNumbers("latest", "latest")); +// 0 + +console.log(web3.utils.compareBlockNumbers(2, 2)); +// 0 +``` + From ebbbf1e8bb2562708f89de431fc630ea7d665624 Mon Sep 17 00:00:00 2001 From: Junaid <86780488+jdevcs@users.noreply.github.com> Date: Tue, 30 Apr 2024 10:47:48 +0200 Subject: [PATCH 12/32] =?UTF-8?q?Add=20the=20missing=20types=20to=20the=20?= =?UTF-8?q?=E2=80=9Daccounts=E2=80=9C=20(#7011)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * updated types * changelog update --- packages/web3/CHANGELOG.md | 6 +++++- packages/web3/src/types.ts | 3 +++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/web3/CHANGELOG.md b/packages/web3/CHANGELOG.md index 5b7242c7ebb..69473aeb916 100644 --- a/packages/web3/CHANGELOG.md +++ b/packages/web3/CHANGELOG.md @@ -262,4 +262,8 @@ Documentation: - Added `signature` to type `AbiFunctionFragment` (#6922) - update type `Withdrawals`, `block` and `BlockHeaderOutput` to include properties of eip 4844, 4895, 4788 (#6933) -## [Unreleased] \ No newline at end of file +## [Unreleased] + +### added + +- Updated type `Web3EthInterface.accounts` to includes `privateKeyToAccount`,`privateKeyToAddress`,and `privateKeyToPublicKey` (#6762) \ No newline at end of file diff --git a/packages/web3/src/types.ts b/packages/web3/src/types.ts index fb14e6b2e1a..ef9bcc379cf 100644 --- a/packages/web3/src/types.ts +++ b/packages/web3/src/types.ts @@ -90,6 +90,9 @@ export interface Web3EthInterface extends Eth { options?: Record, ) => Promise; wallet: Wallet; + privateKeyToAddress: (privateKey: Bytes) => string; + privateKeyToPublicKey: (privateKey: Bytes, isCompressed: boolean) => string; + parseAndValidatePrivateKey: (data: Bytes, ignoreLength?: boolean) => Uint8Array; }; personal: Personal; } From 7a470c9469c43d607d9120f993518514bc228038 Mon Sep 17 00:00:00 2001 From: Oleksii Kosynskyi Date: Wed, 1 May 2024 19:09:05 -0400 Subject: [PATCH 13/32] Add extra changes to make possibility add eip4844 type as a plugin (#7000) * export utils * add customJsonSchema * fix tests * add changelog --- CHANGELOG.md | 18 +++++++++- packages/web3-eth/CHANGELOG.md | 5 +++ packages/web3-eth/src/index.ts | 5 ++- packages/web3-eth/src/utils/send_tx_helper.ts | 5 ++- .../src/utils/wait_for_transaction_receipt.ts | 35 ++++++++++++------- .../src/utils/watch_transaction_by_polling.ts | 9 ++++- .../watch_transaction_by_subscription.ts | 10 ++++-- .../watch_transaction_for_confirmations.ts | 11 ++++-- .../send_signed_transaction.test.ts | 4 +-- .../send_transaction.test.ts | 1 + packages/web3-rpc-methods/CHANGELOG.md | 6 +++- .../web3-rpc-methods/src/eth_rpc_methods.ts | 4 +-- 12 files changed, 87 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 873afc8c4ea..2f0d422eef6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2455,6 +2455,7 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3-eth - `defaultReturnFormat` was added to all methods that have `ReturnType` param. (#6947) +- `getTransactionFromOrToAttr`, `waitForTransactionReceipt`, `trySendTransaction`, `SendTxHelper` was exported (#7000) #### web3-eth-contract @@ -2473,8 +2474,23 @@ If there are any bugs, improvements, optimizations or any new feature proposal f - Added `signature` to type `AbiFunctionFragment` (#6922) - update type `Withdrawals`, `block` and `BlockHeaderOutput` to include properties of eip 4844, 4895, 4788 (#6933) +#### web3-utils + + ### Fixed +#### web3-utils + + #### web3-validator -- The JSON schema conversion process now correctly assigns an id when the `abi.name` is not available, for example, in the case of public mappings. (#6981) \ No newline at end of file + +### Changed + +#### web3-eth + +- Added parameter `customTransactionReceiptSchema` into methods `emitConfirmation`, `waitForTransactionReceipt`, `watchTransactionByPolling`, `watchTransactionBySubscription`, `watchTransactionForConfirmations` (#7000) + +#### web3-rpc-methods + +- Change `estimateGas` method to add possibility pass Transaction type (#7000) diff --git a/packages/web3-eth/CHANGELOG.md b/packages/web3-eth/CHANGELOG.md index ba7ee38a443..5fb80eef663 100644 --- a/packages/web3-eth/CHANGELOG.md +++ b/packages/web3-eth/CHANGELOG.md @@ -237,3 +237,8 @@ Documentation: ### Added - `defaultReturnFormat` was added to all methods that have `ReturnType` param. (#6947) +- `getTransactionFromOrToAttr`, `waitForTransactionReceipt`, `trySendTransaction`, `SendTxHelper` was exported (#7000) + +### Changed + +- Added parameter `customTransactionReceiptSchema` into methods `emitConfirmation`, `waitForTransactionReceipt`, `watchTransactionByPolling`, `watchTransactionBySubscription`, `watchTransactionForConfirmations` (#7000) diff --git a/packages/web3-eth/src/index.ts b/packages/web3-eth/src/index.ts index d1f1d326832..5e1c4297ffa 100644 --- a/packages/web3-eth/src/index.ts +++ b/packages/web3-eth/src/index.ts @@ -63,6 +63,9 @@ export * from './utils/format_transaction.js'; export * from './utils/prepare_transaction_for_signing.js'; export * from './web3_subscriptions.js'; export { detectTransactionType } from './utils/detect_transaction_type.js'; -export { transactionBuilder } from './utils/transaction_builder.js'; +export { transactionBuilder, getTransactionFromOrToAttr } from './utils/transaction_builder.js'; +export { waitForTransactionReceipt } from './utils/wait_for_transaction_receipt.js'; +export { trySendTransaction } from './utils/try_send_transaction.js'; +export { SendTxHelper } from './utils/send_tx_helper.js'; export default Web3Eth; diff --git a/packages/web3-eth/src/utils/send_tx_helper.ts b/packages/web3-eth/src/utils/send_tx_helper.ts index 2e3385d5d1c..282e778e519 100644 --- a/packages/web3-eth/src/utils/send_tx_helper.ts +++ b/packages/web3-eth/src/utils/send_tx_helper.ts @@ -33,7 +33,7 @@ import { ContractAbiWithSignature, } from 'web3-types'; import { Web3Context, Web3EventEmitter, Web3PromiEvent } from 'web3-core'; -import { isNullish } from 'web3-validator'; +import { isNullish, JsonSchema } from 'web3-validator'; import { ContractExecutionError, InvalidResponseError, @@ -257,9 +257,11 @@ export class SendTxHelper< public emitConfirmation({ receipt, transactionHash, + customTransactionReceiptSchema, }: { receipt: ResolveType; transactionHash: TransactionHash; + customTransactionReceiptSchema?: JsonSchema; }) { if (this.promiEvent.listenerCount('confirmation') > 0) { watchTransactionForConfirmations< @@ -272,6 +274,7 @@ export class SendTxHelper< receipt as unknown as TransactionReceipt, transactionHash, this.returnFormat, + customTransactionReceiptSchema, ); } } diff --git a/packages/web3-eth/src/utils/wait_for_transaction_receipt.ts b/packages/web3-eth/src/utils/wait_for_transaction_receipt.ts index d335683391e..e422b6307a2 100644 --- a/packages/web3-eth/src/utils/wait_for_transaction_receipt.ts +++ b/packages/web3-eth/src/utils/wait_for_transaction_receipt.ts @@ -30,19 +30,30 @@ export async function waitForTransactionReceipt web3Context: Web3Context, transactionHash: Bytes, returnFormat: ReturnFormat, + customGetTransactionReceipt?: ( + web3Context: Web3Context, + transactionHash: Bytes, + returnFormat: ReturnFormat, + ) => Promise, ): Promise { - const pollingInterval = web3Context.transactionReceiptPollingInterval ?? web3Context.transactionPollingInterval; - const [awaitableTransactionReceipt, IntervalId] = pollTillDefinedAndReturnIntervalId(async () => { - try { - return getTransactionReceipt(web3Context, transactionHash, returnFormat); - } catch (error) { - console.warn('An error happen while trying to get the transaction receipt', error); - return undefined; - } - }, pollingInterval); + const [awaitableTransactionReceipt, IntervalId] = pollTillDefinedAndReturnIntervalId( + async () => { + try { + return (customGetTransactionReceipt ?? getTransactionReceipt)( + web3Context, + transactionHash, + returnFormat, + ); + } catch (error) { + console.warn('An error happen while trying to get the transaction receipt', error); + return undefined; + } + }, + pollingInterval, + ); const [timeoutId, rejectOnTimeout] = rejectIfTimeout( web3Context.transactionPollingTimeout, @@ -65,10 +76,8 @@ export async function waitForTransactionReceipt rejectOnBlockTimeout, // this will throw an error on Transaction Block Timeout ]); } finally { - if(timeoutId) - clearTimeout(timeoutId); - if(IntervalId) - clearInterval(IntervalId); + if (timeoutId) clearTimeout(timeoutId); + if (IntervalId) clearInterval(IntervalId); blockTimeoutResourceCleaner.clean(); } } diff --git a/packages/web3-eth/src/utils/watch_transaction_by_polling.ts b/packages/web3-eth/src/utils/watch_transaction_by_polling.ts index 6be3c572742..34e01581422 100644 --- a/packages/web3-eth/src/utils/watch_transaction_by_polling.ts +++ b/packages/web3-eth/src/utils/watch_transaction_by_polling.ts @@ -20,6 +20,7 @@ import { format, numberToHex } from 'web3-utils'; import { ethRpcMethods } from 'web3-rpc-methods'; import { DataFormat } from 'web3-types'; +import { JsonSchema } from 'web3-validator'; import { SendSignedTransactionEvents, SendTransactionEvents } from '../types.js'; import { transactionReceiptSchema } from '../schemas.js'; @@ -30,6 +31,7 @@ export type Web3PromiEventEventTypeBase = export type WaitProps = { web3Context: Web3Context; transactionReceipt: TransactionReceipt; + customTransactionReceiptSchema?: JsonSchema; transactionPromiEvent: Web3PromiEvent>; returnFormat: ReturnFormat; }; @@ -46,6 +48,7 @@ export const watchTransactionByPolling = < web3Context, transactionReceipt, transactionPromiEvent, + customTransactionReceiptSchema, returnFormat, }: WaitProps) => { // Having a transactionReceipt means that the transaction has already been included @@ -67,7 +70,11 @@ export const watchTransactionByPolling = < transactionPromiEvent.emit('confirmation', { confirmations: format({ format: 'uint' }, confirmations, returnFormat), - receipt: format(transactionReceiptSchema, transactionReceipt, returnFormat), + receipt: format( + customTransactionReceiptSchema ?? transactionReceiptSchema, + transactionReceipt, + returnFormat, + ), latestBlockHash: format( { format: 'bytes32' }, nextBlock.hash as Bytes, diff --git a/packages/web3-eth/src/utils/watch_transaction_by_subscription.ts b/packages/web3-eth/src/utils/watch_transaction_by_subscription.ts index d68c39da95d..e7e68adc529 100644 --- a/packages/web3-eth/src/utils/watch_transaction_by_subscription.ts +++ b/packages/web3-eth/src/utils/watch_transaction_by_subscription.ts @@ -21,7 +21,6 @@ import { DataFormat } from 'web3-types'; import { NewHeadsSubscription } from '../web3_subscriptions.js'; import { transactionReceiptSchema } from '../schemas.js'; import { WaitProps, watchTransactionByPolling } from './watch_transaction_by_polling.js'; - /** * This function watches a Transaction by subscribing to new heads. * It is used by `watchTransactionForConfirmations`, in case the provider supports subscription. @@ -33,6 +32,7 @@ export const watchTransactionBySubscription = < web3Context, transactionReceipt, transactionPromiEvent, + customTransactionReceiptSchema, returnFormat, }: WaitProps) => { // The following variable will stay true except if the data arrived, @@ -66,7 +66,11 @@ export const watchTransactionBySubscription = < confirmations as Numbers, returnFormat, ), - receipt: format(transactionReceiptSchema, transactionReceipt, returnFormat), + receipt: format( + customTransactionReceiptSchema ?? transactionReceiptSchema, + transactionReceipt, + returnFormat, + ), latestBlockHash: format( { format: 'bytes32' }, newBlockHeader.parentHash as Bytes, @@ -85,6 +89,7 @@ export const watchTransactionBySubscription = < web3Context, transactionReceipt, transactionPromiEvent, + customTransactionReceiptSchema, returnFormat, }); }); @@ -94,6 +99,7 @@ export const watchTransactionBySubscription = < watchTransactionByPolling({ web3Context, transactionReceipt, + customTransactionReceiptSchema, transactionPromiEvent, returnFormat, }); diff --git a/packages/web3-eth/src/utils/watch_transaction_for_confirmations.ts b/packages/web3-eth/src/utils/watch_transaction_for_confirmations.ts index 60489d59c50..01ca39f8894 100644 --- a/packages/web3-eth/src/utils/watch_transaction_for_confirmations.ts +++ b/packages/web3-eth/src/utils/watch_transaction_for_confirmations.ts @@ -17,7 +17,7 @@ along with web3.js. If not, see . import { Bytes, EthExecutionAPI, Web3BaseProvider, TransactionReceipt } from 'web3-types'; import { Web3Context, Web3PromiEvent } from 'web3-core'; import { format } from 'web3-utils'; -import { isNullish } from 'web3-validator'; +import { isNullish, JsonSchema } from 'web3-validator'; import { TransactionMissingReceiptOrBlockHashError, @@ -41,6 +41,7 @@ export function watchTransactionForConfirmations< transactionReceipt: TransactionReceipt, transactionHash: Bytes, returnFormat: ReturnFormat, + customTransactionReceiptSchema?: JsonSchema, ) { if (isNullish(transactionReceipt) || isNullish(transactionReceipt.blockHash)) throw new TransactionMissingReceiptOrBlockHashError({ @@ -55,7 +56,11 @@ export function watchTransactionForConfirmations< // As we have the receipt, it's the first confirmation that tx is accepted. transactionPromiEvent.emit('confirmation', { confirmations: format({ format: 'uint' }, 1, returnFormat), - receipt: format(transactionReceiptSchema, transactionReceipt, returnFormat), + receipt: format( + customTransactionReceiptSchema ?? transactionReceiptSchema, + transactionReceipt, + returnFormat, + ), latestBlockHash: format({ format: 'bytes32' }, transactionReceipt.blockHash, returnFormat), }); @@ -66,6 +71,7 @@ export function watchTransactionForConfirmations< web3Context, transactionReceipt, transactionPromiEvent, + customTransactionReceiptSchema, returnFormat, }); } else { @@ -73,6 +79,7 @@ export function watchTransactionForConfirmations< web3Context, transactionReceipt, transactionPromiEvent, + customTransactionReceiptSchema, returnFormat, }); } diff --git a/packages/web3-eth/test/unit/rpc_method_wrappers/send_signed_transaction.test.ts b/packages/web3-eth/test/unit/rpc_method_wrappers/send_signed_transaction.test.ts index 4a741c46646..c5a461c7372 100644 --- a/packages/web3-eth/test/unit/rpc_method_wrappers/send_signed_transaction.test.ts +++ b/packages/web3-eth/test/unit/rpc_method_wrappers/send_signed_transaction.test.ts @@ -53,7 +53,7 @@ describe('sendTransaction', () => { WaitForTransactionReceipt.waitForTransactionReceipt as jest.Mock ).mockResolvedValueOnce(expectedTransactionReceipt); - const checkRevertBeforeSendingSpy = jest.fn().mockImplementation((transaction) => { + const checkRevertBeforeSendingSpy = jest.fn().mockImplementation(transaction => { expect(transaction).toBeDefined(); // verify signature part is removed before sending to revert check function @@ -78,7 +78,6 @@ describe('sendTransaction', () => { ); expect(checkRevertBeforeSendingSpy).toHaveBeenCalledTimes(1); - }, ); @@ -300,6 +299,7 @@ describe('sendTransaction', () => { formattedTransactionReceipt, expectedTransactionHash, DEFAULT_RETURN_FORMAT, + undefined, ); }, ); diff --git a/packages/web3-eth/test/unit/rpc_method_wrappers/send_transaction.test.ts b/packages/web3-eth/test/unit/rpc_method_wrappers/send_transaction.test.ts index 3be8182cd33..e9b60f97e74 100644 --- a/packages/web3-eth/test/unit/rpc_method_wrappers/send_transaction.test.ts +++ b/packages/web3-eth/test/unit/rpc_method_wrappers/send_transaction.test.ts @@ -299,6 +299,7 @@ describe('sendTransaction', () => { formattedTransactionReceipt, expectedTransactionHash, DEFAULT_RETURN_FORMAT, + undefined, ); }, ); diff --git a/packages/web3-rpc-methods/CHANGELOG.md b/packages/web3-rpc-methods/CHANGELOG.md index c2385435cac..c57997c5ddc 100644 --- a/packages/web3-rpc-methods/CHANGELOG.md +++ b/packages/web3-rpc-methods/CHANGELOG.md @@ -138,4 +138,8 @@ Documentation: - Added `getMaxPriorityFeePerGas` method (#6748) -## [Unreleased] \ No newline at end of file +## [Unreleased] + +### Changed + +- Change `estimateGas` method to add possibility pass Transaction type (#7000) diff --git a/packages/web3-rpc-methods/src/eth_rpc_methods.ts b/packages/web3-rpc-methods/src/eth_rpc_methods.ts index b33857d7d80..f86240ddccb 100644 --- a/packages/web3-rpc-methods/src/eth_rpc_methods.ts +++ b/packages/web3-rpc-methods/src/eth_rpc_methods.ts @@ -264,9 +264,9 @@ export async function call( } // TODO Not sure how to best validate Partial -export async function estimateGas( +export async function estimateGas( requestManager: Web3RequestManager, - transaction: Partial, + transaction: Partial, blockNumber: BlockNumberOrTag, ) { validator.validate(['blockNumberOrTag'], [blockNumber]); From b413ebd1c4a256ca9c5c391cd290fe253a7df4ca Mon Sep 17 00:00:00 2001 From: Gregory Markou <16929357+GregTheGreek@users.noreply.github.com> Date: Thu, 2 May 2024 10:57:18 +0300 Subject: [PATCH 14/32] add drips funding (#7023) --- FUNDING.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 FUNDING.json diff --git a/FUNDING.json b/FUNDING.json new file mode 100644 index 00000000000..a11415df3a8 --- /dev/null +++ b/FUNDING.json @@ -0,0 +1,7 @@ +{ + "drips": { + "ethereum": { + "ownedBy": "0x689f1278469c6146d835CB99BbfF818fB62989FE" + } + } +} From 88b7e2e22960898d69f7d35d1030edb37dc9d763 Mon Sep 17 00:00:00 2001 From: Oleksii Kosynskyi Date: Thu, 2 May 2024 09:42:15 -0400 Subject: [PATCH 15/32] Tests & ESLint Improvements (#7012) * jest speed up * extra fixes * test * test * revert * eslint speedup * new version * remoce cache * fix * test * fix * try again * + * add token * delete all in once * change cache strategy * fix * add ifs * test multi cache * test * test * done * fix * Update build.yml --- .github/workflows/build.yml | 85 ++++++++++++++++++---- .gitignore | 2 + packages/web3-core/package.json | 2 +- packages/web3-errors/package.json | 2 +- packages/web3-eth-abi/package.json | 2 +- packages/web3-eth-accounts/package.json | 2 +- packages/web3-eth-contract/package.json | 2 +- packages/web3-eth-ens/package.json | 2 +- packages/web3-eth-iban/package.json | 2 +- packages/web3-eth-personal/package.json | 2 +- packages/web3-eth/package.json | 2 +- packages/web3-net/package.json | 2 +- packages/web3-providers-http/package.json | 2 +- packages/web3-providers-ipc/package.json | 2 +- packages/web3-providers-ws/package.json | 2 +- packages/web3-rpc-methods/package.json | 2 +- packages/web3-types/package.json | 2 +- packages/web3-utils/package.json | 2 +- packages/web3-validator/package.json | 2 +- packages/web3/package.json | 2 +- templates/jest.config.js.tmpl | 1 + tools/eslint-config-base-web3/package.json | 2 +- tools/web3-packagetemplate/package.json | 2 +- tools/web3-plugin-example/package.json | 2 +- 24 files changed, 94 insertions(+), 36 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ee95deaf804..f05eac79fd8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,7 +26,7 @@ jobs: - run: yarn install --ignore-scripts - run: npx ts-node scripts/init.ts - run: yarn build:cjs - - uses: actions/cache/save@v3 + - uses: actions/cache/save@v4 with: path: ./ key: web3-${{ matrix.node }}-${{github.sha}} @@ -39,7 +39,7 @@ jobs: - uses: actions/setup-node@v4 with: node-version: 18 - - uses: actions/cache/restore@v3 + - uses: actions/cache/restore@v4 with: path: ./ key: web3-18-${{github.sha}} @@ -52,7 +52,7 @@ jobs: - uses: actions/setup-node@v4 with: node-version: 18 - - uses: actions/cache/restore@v3 + - uses: actions/cache/restore@v4 with: path: ./ key: web3-18-${{github.sha}} @@ -65,12 +65,63 @@ jobs: - uses: actions/setup-node@v4 with: node-version: 18 - - uses: actions/cache/restore@v3 + - uses: actions/cache/restore@v4 with: path: ./ key: web3-18-${{github.sha}} - run: npx ts-node scripts/init.ts + - name: Restore eslint caches + uses: actions/cache/restore@v4 + with: + path: | + packages/web3/.eslintcache + packages/web3-core/.eslintcache + packages/web3-eth/.eslintcache + packages/web3-eth-abi/.eslintcache + packages/web3-eth-accounts/.eslintcache + packages/web3-eth-contract/.eslintcache + packages/web3-eth-ens/.eslintcache + packages/web3-eth-iban/.eslintcache + packages/web3-eth-personal/.eslintcache + packages/web3-net/.eslintcache + packages/web3-providers-http/.eslintcache + packages/web3-providers-ws/.eslintcache + packages/web3-rpc-methods/.eslintcache + packages/web3-types/.eslintcache + packages/web3-utils/.eslintcache + packages/web3-validator/.eslintcache + tools/web3-plugin-example/.eslintcache + key: ${{ runner.os }}-eslintcache + - run: yarn lint + - run: gh cache delete "${{ runner.os }}-eslintcache" + if: github.event_name == 'push' && github.ref == 'refs/heads/4.x' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Save eslint caches + if: github.event_name == 'push' && github.ref == 'refs/heads/4.x' + uses: actions/cache/save@v4 + with: + path: | + packages/web3/.eslintcache + packages/web3-core/.eslintcache + packages/web3-eth/.eslintcache + packages/web3-eth-abi/.eslintcache + packages/web3-eth-accounts/.eslintcache + packages/web3-eth-contract/.eslintcache + packages/web3-eth-ens/.eslintcache + packages/web3-eth-iban/.eslintcache + packages/web3-eth-personal/.eslintcache + packages/web3-net/.eslintcache + packages/web3-providers-http/.eslintcache + packages/web3-providers-ws/.eslintcache + packages/web3-rpc-methods/.eslintcache + packages/web3-types/.eslintcache + packages/web3-utils/.eslintcache + packages/web3-validator/.eslintcache + tools/web3-plugin-example/.eslintcache + key: ${{ runner.os }}-eslintcache build-web: name: Build Web @@ -80,13 +131,13 @@ jobs: - uses: actions/setup-node@v4 with: node-version: 18 - - uses: actions/cache/restore@v3 + - uses: actions/cache/restore@v4 with: path: ./ key: web3-18-${{github.sha}} - name: Restore default branch stats if: github.event_name != 'push' - uses: actions/cache/restore@v3 + uses: actions/cache/restore@v4 with: path: packages/web3/dist/4.x.json key: web3-bundle-stats-4x-${{github.event.pull_request.base.sha}} @@ -101,7 +152,7 @@ jobs: current-stats-json-path: "packages/web3/dist/${{ github.ref_name }}.json" base-stats-json-path: "packages/web3/dist/4.x.json" - name: Cache default branch stats - uses: actions/cache/save@v3 + uses: actions/cache/save@v4 if: github.event_name == 'push' && github.ref == 'refs/heads/4.x' with: path: packages/web3/dist/${{ github.ref_name }}.json @@ -120,7 +171,7 @@ jobs: with: architecture: x64 node-version: ${{ matrix.node }} - - uses: actions/cache/restore@v3 + - uses: actions/cache/restore@v4 with: path: ./ key: web3-${{ matrix.node }}-${{github.sha}} @@ -142,7 +193,7 @@ jobs: - uses: actions/setup-node@v3 with: node-version: 18 - - uses: actions/cache/restore@v3 + - uses: actions/cache/restore@v4 with: path: ./ key: web3-18-${{github.sha}} @@ -165,7 +216,7 @@ jobs: - uses: actions/setup-node@v4 with: node-version: 18 - - uses: actions/cache/restore@v3 + - uses: actions/cache/restore@v4 with: path: ./ key: web3-18-${{github.sha}} @@ -186,7 +237,7 @@ jobs: node-version: 18 - uses: browser-actions/setup-firefox@latest if: matrix.browser == 'firefox' - - uses: actions/cache/restore@v3 + - uses: actions/cache/restore@v4 with: path: ./ key: web3-18-${{github.sha}} @@ -212,7 +263,7 @@ jobs: with: cache: yarn node-version: '18' - - uses: actions/cache/restore@v3 + - uses: actions/cache/restore@v4 with: path: ./ key: web3-18-${{github.sha}} @@ -235,14 +286,14 @@ jobs: - uses: actions/setup-node@v4 with: node-version: 18 - - uses: actions/cache/restore@v3 + - uses: actions/cache/restore@v4 with: path: ./ key: web3-18-${{github.sha}} # @octokit/core not supported on node 16, so I can't add it to the package.json - run: npm install --no-package-lock --no-save --force @octokit/core@5.1.0 - name: Restore main branch benchmark data - uses: actions/cache/restore@v3 + uses: actions/cache/restore@v4 with: path: web3-benchmark-main.json key: ${{ runner.os }}-web3-benchmark-main.json @@ -279,8 +330,12 @@ jobs: # Enable alert commit comment alert-threshold: '200%' comment-always: false + - run: gh cache delete "${{ runner.os }}-web3-benchmark-main.json" + if: github.event_name == 'push' && github.ref == 'refs/heads/4.x' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Save main branch benchmark data - uses: actions/cache/save@v3 + uses: actions/cache/save@v4 if: github.event_name == 'push' && github.ref == 'refs/heads/4.x' with: path: web3-benchmark-main.json diff --git a/.gitignore b/.gitignore index 45c80f83fbd..c22337c0c9a 100644 --- a/.gitignore +++ b/.gitignore @@ -45,3 +45,5 @@ packages/web3/.in3/ # benchmark results benchmark-data.txt + +.eslintcache diff --git a/packages/web3-core/package.json b/packages/web3-core/package.json index 6552a6d8bf4..04fcb06f509 100644 --- a/packages/web3-core/package.json +++ b/packages/web3-core/package.json @@ -30,7 +30,7 @@ "build:esm": "tsc --build tsconfig.esm.json && echo '{\"type\": \"module\"}' > ./lib/esm/package.json", "build:types": "tsc --build tsconfig.types.json", "build:check": "node -e \"require('./lib')\"", - "lint": "eslint --ext .js,.ts .", + "lint": "eslint --cache --cache-strategy content --ext .ts .", "lint:fix": "eslint --fix --ext .js,.ts .", "format": "prettier --write '**/*'", "test": "jest --config=./test/unit/jest.config.js", diff --git a/packages/web3-errors/package.json b/packages/web3-errors/package.json index 89338006efd..08a2b5ebb7f 100644 --- a/packages/web3-errors/package.json +++ b/packages/web3-errors/package.json @@ -30,7 +30,7 @@ "build:esm": "tsc --build tsconfig.esm.json && echo '{\"type\": \"module\"}' > ./lib/esm/package.json", "build:types": "tsc --build tsconfig.types.json", "build:check": "node -e \"require('./lib')\"", - "lint": "eslint --ext .js,.ts .", + "lint": "eslint --cache --cache-strategy content --ext .ts .", "lint:fix": "eslint --fix --ext .js,.ts .", "format": "prettier --write '**/*'", "test": "jest --config=./test/unit/jest.config.js", diff --git a/packages/web3-eth-abi/package.json b/packages/web3-eth-abi/package.json index e24baf7117b..1ed38b13f05 100644 --- a/packages/web3-eth-abi/package.json +++ b/packages/web3-eth-abi/package.json @@ -30,7 +30,7 @@ "build:esm": "tsc --build tsconfig.esm.json && echo '{\"type\": \"module\"}' > ./lib/esm/package.json", "build:types": "tsc --build tsconfig.types.json", "build:check": "node -e \"require('./lib')\"", - "lint": "eslint --ext .js,.ts .", + "lint": "eslint --cache --cache-strategy content --ext .ts .", "lint:fix": "eslint --fix --ext .js,.ts .", "format": "prettier --write '**/*'", "test": "jest --config=./test/unit/jest.config.js", diff --git a/packages/web3-eth-accounts/package.json b/packages/web3-eth-accounts/package.json index 06416a260b2..dbd0a9fc881 100644 --- a/packages/web3-eth-accounts/package.json +++ b/packages/web3-eth-accounts/package.json @@ -30,7 +30,7 @@ "build:esm": "tsc --build tsconfig.esm.json && echo '{\"type\": \"module\"}' > ./lib/esm/package.json", "build:types": "tsc --build tsconfig.types.json", "build:check": "node -e \"require('./lib')\"", - "lint": "eslint --ext .js,.ts .", + "lint": "eslint --cache --cache-strategy content --ext .ts .", "lint:fix": "eslint --fix --ext .js,.ts .", "format": "prettier --write '**/*'", "test": "jest --config=./test/unit/jest.config.js", diff --git a/packages/web3-eth-contract/package.json b/packages/web3-eth-contract/package.json index f70734cc090..0c8cd166675 100644 --- a/packages/web3-eth-contract/package.json +++ b/packages/web3-eth-contract/package.json @@ -30,7 +30,7 @@ "build:esm": "tsc --build tsconfig.esm.json && echo '{\"type\": \"module\"}' > ./lib/esm/package.json", "build:types": "tsc --build tsconfig.types.json", "build:check": "node -e \"require('./lib')\"", - "lint": "eslint --ext .js,.ts .", + "lint": "eslint --cache --cache-strategy content --ext .ts .", "lint:fix": "eslint --fix --ext .js,.ts .", "format": "prettier --write '**/*'", "test": "jest --config=./test/unit/jest.config.js", diff --git a/packages/web3-eth-ens/package.json b/packages/web3-eth-ens/package.json index 994f4427741..db7fc9d2d03 100644 --- a/packages/web3-eth-ens/package.json +++ b/packages/web3-eth-ens/package.json @@ -30,7 +30,7 @@ "build:esm": "tsc --build tsconfig.esm.json && echo '{\"type\": \"module\"}' > ./lib/esm/package.json", "build:types": "tsc --build tsconfig.types.json", "build:check": "node -e \"require('./lib')\"", - "lint": "eslint --ext .js,.ts .", + "lint": "eslint --cache --cache-strategy content --ext .ts .", "lint:fix": "eslint --fix --ext .js,.ts .", "format": "prettier --write '**/*'", "test": "jest --config=./test/unit/jest.config.js", diff --git a/packages/web3-eth-iban/package.json b/packages/web3-eth-iban/package.json index 8a92af70ea6..81e65c298b1 100644 --- a/packages/web3-eth-iban/package.json +++ b/packages/web3-eth-iban/package.json @@ -30,7 +30,7 @@ "build:esm": "tsc --build tsconfig.esm.json && echo '{\"type\": \"module\"}' > ./lib/esm/package.json", "build:types": "tsc --build tsconfig.types.json", "build:check": "node -e \"require('./lib')\"", - "lint": "eslint --ext .js,.ts .", + "lint": "eslint --cache --cache-strategy content --ext .ts .", "lint:fix": "eslint --fix --ext .js,.ts .", "format": "prettier --write '**/*'", "test": "jest --config=./test/unit/jest.config.js", diff --git a/packages/web3-eth-personal/package.json b/packages/web3-eth-personal/package.json index 4be584d822a..8cb5ada7a04 100644 --- a/packages/web3-eth-personal/package.json +++ b/packages/web3-eth-personal/package.json @@ -30,7 +30,7 @@ "build:esm": "tsc --build tsconfig.esm.json && echo '{\"type\": \"module\"}' > ./lib/esm/package.json", "build:types": "tsc --build tsconfig.types.json", "build:check": "node -e \"require('./lib')\"", - "lint": "eslint --ext .js,.ts .", + "lint": "eslint --cache --cache-strategy content --ext .ts .", "lint:fix": "eslint --fix --ext .js,.ts .", "format": "prettier --write '**/*'", "test": "jest --config=./test/unit/jest.config.js", diff --git a/packages/web3-eth/package.json b/packages/web3-eth/package.json index 565de7fed54..767f5697387 100644 --- a/packages/web3-eth/package.json +++ b/packages/web3-eth/package.json @@ -30,7 +30,7 @@ "build:esm": "tsc --build tsconfig.esm.json && echo '{\"type\": \"module\"}' > ./lib/esm/package.json", "build:types": "tsc --build tsconfig.types.json", "build:check": "node -e \"require('./lib')\"", - "lint": "eslint --ext .js,.ts .", + "lint": "eslint --cache --cache-strategy content --ext .ts .", "lint:fix": "eslint --fix --ext .js,.ts .", "format": "prettier --write '**/*'", "test": "jest --config=./test/unit/jest.config.js", diff --git a/packages/web3-net/package.json b/packages/web3-net/package.json index 1397aa44c7a..d3ca4f5a32b 100644 --- a/packages/web3-net/package.json +++ b/packages/web3-net/package.json @@ -30,7 +30,7 @@ "build:esm": "tsc --build tsconfig.esm.json && echo '{\"type\": \"module\"}' > ./lib/esm/package.json", "build:types": "tsc --build tsconfig.types.json", "build:check": "node -e \"require('./lib')\"", - "lint": "eslint --ext .js,.ts .", + "lint": "eslint --cache --cache-strategy content --ext .ts .", "lint:fix": "eslint --fix --ext .js,.ts .", "format": "prettier --write '**/*'", "test": "jest --config=./test/unit/jest.config.js", diff --git a/packages/web3-providers-http/package.json b/packages/web3-providers-http/package.json index f8b1eed8821..75cf3529945 100644 --- a/packages/web3-providers-http/package.json +++ b/packages/web3-providers-http/package.json @@ -30,7 +30,7 @@ "build:esm": "tsc --build tsconfig.esm.json && echo '{\"type\": \"module\"}' > ./lib/esm/package.json", "build:types": "tsc --build tsconfig.types.json", "build:check": "node -e \"require('./lib')\"", - "lint": "eslint --ext .js,.ts .", + "lint": "eslint --cache --cache-strategy content --ext .ts .", "lint:fix": "eslint --fix --ext .js,.ts .", "format": "prettier --write '**/*'", "test": "jest --config=./test/unit/jest.config.js", diff --git a/packages/web3-providers-ipc/package.json b/packages/web3-providers-ipc/package.json index e9a6db2d25b..395156d6598 100644 --- a/packages/web3-providers-ipc/package.json +++ b/packages/web3-providers-ipc/package.json @@ -30,7 +30,7 @@ "build:esm": "tsc --build tsconfig.esm.json && echo '{\"type\": \"module\"}' > ./lib/esm/package.json", "build:types": "tsc --build tsconfig.types.json", "build:check": "node -e \"require('./lib')\"", - "lint": "eslint --ext .js,.ts .", + "lint": "eslint --cache --cache-strategy content --ext .ts .", "lint:fix": "eslint --fix --ext .js,.ts .", "format": "prettier --write '**/*'", "test": "jest --config=./test/unit/jest.config.js", diff --git a/packages/web3-providers-ws/package.json b/packages/web3-providers-ws/package.json index 2df7997c08c..b3612afaa23 100644 --- a/packages/web3-providers-ws/package.json +++ b/packages/web3-providers-ws/package.json @@ -30,7 +30,7 @@ "build:esm": "tsc --build tsconfig.esm.json && echo '{\"type\": \"module\"}' > ./lib/esm/package.json", "build:types": "tsc --build tsconfig.types.json", "build:check": "node -e \"require('./lib')\"", - "lint": "eslint --ext .js,.ts .", + "lint": "eslint --cache --cache-strategy content --ext .ts .", "lint:fix": "eslint --fix --ext .js,.ts .", "format": "prettier --write '**/*'", "test": "jest --config=./test/unit/jest.config.js", diff --git a/packages/web3-rpc-methods/package.json b/packages/web3-rpc-methods/package.json index 9a6605d1939..8e9eec0e597 100644 --- a/packages/web3-rpc-methods/package.json +++ b/packages/web3-rpc-methods/package.json @@ -30,7 +30,7 @@ "build:esm": "tsc --build tsconfig.esm.json && echo '{\"type\": \"module\"}' > ./lib/esm/package.json", "build:types": "tsc --build tsconfig.types.json", "build:check": "node -e \"require('./lib')\"", - "lint": "eslint --ext .js,.ts .", + "lint": "eslint --cache --cache-strategy content --ext .ts .", "lint:fix": "eslint --fix --ext .js,.ts .", "format": "prettier --write '**/*'", "test": "jest --config=./test/unit/jest.config.js", diff --git a/packages/web3-types/package.json b/packages/web3-types/package.json index c89ae9c5b9f..8cec2cee0b0 100644 --- a/packages/web3-types/package.json +++ b/packages/web3-types/package.json @@ -30,7 +30,7 @@ "build:esm": "tsc --build tsconfig.esm.json && echo '{\"type\": \"module\"}' > ./lib/esm/package.json", "build:types": "tsc --build tsconfig.types.json", "build:check": "node -e \"require('./lib')\"", - "lint": "eslint --ext .js,.ts .", + "lint": "eslint --cache --cache-strategy content --ext .ts .", "lint:fix": "eslint --fix --ext .js,.ts .", "format": "prettier --write '**/*'", "test": "jest --config=./test/unit/jest.config.js", diff --git a/packages/web3-utils/package.json b/packages/web3-utils/package.json index c909a1ec735..511ce216fc2 100644 --- a/packages/web3-utils/package.json +++ b/packages/web3-utils/package.json @@ -31,7 +31,7 @@ "build:esm": "tsc --build tsconfig.esm.json && echo '{\"type\": \"module\"}' > ./lib/esm/package.json", "build:types": "tsc --build tsconfig.types.json", "build:check": "node -e \"require('./lib')\"", - "lint": "eslint --ext .js,.ts .", + "lint": "eslint --cache --cache-strategy content --ext .ts .", "lint:fix": "eslint --fix --ext .js,.ts .", "format": "prettier --write '**/*'", "test": "jest --config=./test/unit/jest.config.js", diff --git a/packages/web3-validator/package.json b/packages/web3-validator/package.json index f32cf8d44e4..20e285cce80 100644 --- a/packages/web3-validator/package.json +++ b/packages/web3-validator/package.json @@ -33,7 +33,7 @@ "build:types": "tsc --build tsconfig.types.json", "build:web": "npx webpack", "build:check": "node -e \"require('./lib')\"", - "lint": "eslint --ext .js,.ts .", + "lint": "eslint --cache --cache-strategy content --ext .ts .", "lint:fix": "eslint --fix --ext .js,.ts .", "format": "prettier --write '**/*'", "test": "jest --config=./test/unit/jest.config.js", diff --git a/packages/web3/package.json b/packages/web3/package.json index 5368b3e1bfd..52bb78ce8c8 100644 --- a/packages/web3/package.json +++ b/packages/web3/package.json @@ -40,7 +40,7 @@ "build:web": "npx webpack", "build:web:analyze": "npx webpack --config ./webpack.analyze.js", "build:check": "node -e \"require('./lib')\"", - "lint": "eslint --ext .js,.ts .", + "lint": "eslint --cache --cache-strategy content --ext .ts .", "lint:fix": "eslint --fix --ext .js,.ts .", "format": "prettier --write '**/*'", "test": "jest --config=./test/unit/jest.config.js", diff --git a/templates/jest.config.js.tmpl b/templates/jest.config.js.tmpl index e4d70e55a94..2b65a1760a3 100644 --- a/templates/jest.config.js.tmpl +++ b/templates/jest.config.js.tmpl @@ -26,6 +26,7 @@ module.exports = { 'ts-jest', { tsconfig: './test/tsconfig.json', + isolatedModules: true, }, ], }, diff --git a/tools/eslint-config-base-web3/package.json b/tools/eslint-config-base-web3/package.json index d8487f9f237..0d645c8697f 100644 --- a/tools/eslint-config-base-web3/package.json +++ b/tools/eslint-config-base-web3/package.json @@ -28,7 +28,7 @@ }, "main": "ts.js", "scripts": { - "lint": "eslint --ext .js,.ts .", + "lint": "eslint --cache --cache-strategy content --ext .js,.ts .", "lint:fix": "eslint --fix --ext .js,.ts .", "format": "prettier --write '**/*'" }, diff --git a/tools/web3-packagetemplate/package.json b/tools/web3-packagetemplate/package.json index a329ede3dfe..dab16c29ee0 100644 --- a/tools/web3-packagetemplate/package.json +++ b/tools/web3-packagetemplate/package.json @@ -22,7 +22,7 @@ "build:esm": "tsc --build tsconfig.esm.json", "build:types": "tsc --build tsconfig.types.json", "build:check": "node -e \"require('./lib')\"", - "lint": "eslint --ext .js,.ts .", + "lint": "eslint --cache --cache-strategy content --ext .ts .", "lint:fix": "eslint --fix --ext .js,.ts .", "format": "prettier --write '**/*'", "test": "jest --config=./test/unit/jest.config.js", diff --git a/tools/web3-plugin-example/package.json b/tools/web3-plugin-example/package.json index 8f3a5d6a5f5..3832f5ef30d 100644 --- a/tools/web3-plugin-example/package.json +++ b/tools/web3-plugin-example/package.json @@ -23,7 +23,7 @@ "prebuild": "yarn clean", "build": "tsc --build", "build:check": "node -e \"require('./lib')\"", - "lint": "eslint --ext .js,.ts .", + "lint": "eslint --cache --cache-strategy content --ext .ts .", "lint:fix": "eslint --fix --ext .js,.ts .", "format": "prettier --write '**/*'", "test": "jest --config=./test/unit/jest.config.js", From c62ef79b79b9d86bd59dd68e2773842e49eaedca Mon Sep 17 00:00:00 2001 From: Santiago Trujillo Zuluaga Date: Mon, 6 May 2024 13:15:30 +0300 Subject: [PATCH 16/32] Added troubleshooting example (#7009) * added troubleshooting example * added guide --- .../index.md} | 47 +++++++++++++++++-- 1 file changed, 42 insertions(+), 5 deletions(-) rename docs/docs/guides/{resources/resources.md => resources_and_troubleshooting/index.md} (53%) diff --git a/docs/docs/guides/resources/resources.md b/docs/docs/guides/resources_and_troubleshooting/index.md similarity index 53% rename from docs/docs/guides/resources/resources.md rename to docs/docs/guides/resources_and_troubleshooting/index.md index 0975f4ad3f2..2dd82f1e5b6 100644 --- a/docs/docs/guides/resources/resources.md +++ b/docs/docs/guides/resources_and_troubleshooting/index.md @@ -1,17 +1,54 @@ --- sidebar_position: 16 -sidebar_label: '📚 Resources' +sidebar_label: '📚 Resources & Troubleshooting' --- -# Resources +# Resources & Troubleshooting -## [Web3.js v4 course](https://www.youtube.com/watch?v=3ZO_t-Kyr1g&list=PLPn3rQCo3XrP4LbQcOyyHQR8McV7w3HZT) +## Troubleshooting + +### ReferenceError: Can't find variable: BigInt using React + +Occasionally, users encounter errors in web3.js due to external dependencies, which may seem challenging to resolve within the web3.js framework alone. + +**Resolution Steps:** + +1. Install `rn-nodeify` as a development dependency: +```bash +yarn add --dev rn-nodeify +``` + +2. Add the `big-integer` package: +```bash +yarn add big-integer +``` + +3. Create a file named `shim.js` at the root of your project and include the following polyfill: +```ts +if (typeof BigInt === 'undefined') { + global.BigInt = require('big-integer'); +} +``` + +4. Import shim.js at the top of your App.js: +```ts +// Make sure you use `import` and not `require`! +import './shim.js' +``` + +Additional Info: + +[Facebook/React-native Issue #28492](https://github.com/facebook/react-native/issues/28492#issuecomment-824698934) + +## Resources + +### [Web3.js v4 course](https://www.youtube.com/watch?v=3ZO_t-Kyr1g&list=PLPn3rQCo3XrP4LbQcOyyHQR8McV7w3HZT) This comprehensive 14-part video course from ChainSafe equips you with the skills to conquer the blockchain using web3.js v4. Unlock the potential of web3.js v4 and build cutting-edge dApps. This course caters to all skill levels. [![Web3.js v4 course](https://img.youtube.com/vi/3ZO_t-Kyr1g/0.jpg)](https://www.youtube.com/watch?v=3ZO_t-Kyr1g&list=PLPn3rQCo3XrP4LbQcOyyHQR8McV7w3HZT) -## [Web3.js series](https://www.youtube.com/watch?v=BQ_bDH91S4k&list=PLPn3rQCo3XrNf__8irs4-MjMt4fJqW2I_) +### [Web3.js series](https://www.youtube.com/watch?v=BQ_bDH91S4k&list=PLPn3rQCo3XrNf__8irs4-MjMt4fJqW2I_) This series of 3 videos takes you on a journey through web3.js. Whether you're a complete beginner or want to refine your skills, these videos have something for you: @@ -23,6 +60,6 @@ This series of 3 videos takes you on a journey through web3.js. Whether you're a [![Web3.js series](https://img.youtube.com/vi/BQ_bDH91S4k/0.jpg)](https://www.youtube.com/watch?v=BQ_bDH91S4k&list=PLPn3rQCo3XrNf__8irs4-MjMt4fJqW2I_) -## Hackathons +## Hackathons and Bounties You'll find the latest hackathons opportunities by following [web3js](https://twitter.com/web3_js) on X. From 5d2f2aa2cc628e0d73507687449737dfa419e2e4 Mon Sep 17 00:00:00 2001 From: Oleksii Kosynskyi Date: Mon, 6 May 2024 16:33:44 -0400 Subject: [PATCH 17/32] Implement a way to know which response corresponds to which request in the middleware (#7028) * move request middleware to _sendRequest * lint * change log --- CHANGELOG.md | 8 + packages/web3-core/CHANGELOG.md | 6 + packages/web3-core/src/types.ts | 33 ++- .../web3-core/src/web3_request_manager.ts | 34 ++- .../web3-core/test/unit/web3_context.test.ts | 30 +- .../web3_middleware_request_manager.test.ts | 269 ++++++++++-------- packages/web3/CHANGELOG.md | 4 +- tools/web3-plugin-example/src/middleware.ts | 95 ++++--- .../test/unit/middleware.test.ts | 40 +-- 9 files changed, 301 insertions(+), 218 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f0d422eef6..21a45b6d806 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2448,6 +2448,10 @@ If there are any bugs, improvements, optimizations or any new feature proposal f ### Added +#### web3 + +- Updated type `Web3EthInterface.accounts` to includes `privateKeyToAccount`,`privateKeyToAddress`,and `privateKeyToPublicKey` (#6762) + #### web3-core - `defaultReturnFormat` was added to the configuration options. (#6947) @@ -2487,6 +2491,10 @@ If there are any bugs, improvements, optimizations or any new feature proposal f ### Changed +#### web3-core + +- Interface `RequestManagerMiddleware` was changed (#7003) + #### web3-eth - Added parameter `customTransactionReceiptSchema` into methods `emitConfirmation`, `waitForTransactionReceipt`, `watchTransactionByPolling`, `watchTransactionBySubscription`, `watchTransactionForConfirmations` (#7000) diff --git a/packages/web3-core/CHANGELOG.md b/packages/web3-core/CHANGELOG.md index 31f03f1aa62..d69e71c8cf9 100644 --- a/packages/web3-core/CHANGELOG.md +++ b/packages/web3-core/CHANGELOG.md @@ -210,4 +210,10 @@ Documentation: ## [Unreleased] ### Added + - `defaultReturnFormat` was added to the configuration options. (#6947) + +### Changed + +- Interface `RequestManagerMiddleware` was changed (#7003) + diff --git a/packages/web3-core/src/types.ts b/packages/web3-core/src/types.ts index 890a5e20c5a..b2b655b351a 100644 --- a/packages/web3-core/src/types.ts +++ b/packages/web3-core/src/types.ts @@ -15,11 +15,16 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ -import { HexString, JsonRpcResponse, Transaction, Web3APIMethod, Web3APIRequest, Web3APIReturnType } from 'web3-types'; +import { + HexString, + JsonRpcPayload, + JsonRpcResponse, + Transaction, + Web3APIMethod, + Web3APIReturnType, +} from 'web3-types'; -export type TransactionTypeParser = ( - transaction: Transaction, -) => HexString | undefined; +export type TransactionTypeParser = (transaction: Transaction) => HexString | undefined; export interface Method { name: string; @@ -32,16 +37,16 @@ export interface ExtensionObject { } export interface RequestManagerMiddleware { - processRequest< - AnotherMethod extends Web3APIMethod - >( - request: Web3APIRequest, - options?: { [key: string]: unknown }): Promise>; + processRequest( + request: JsonRpcPayload, + options?: { [key: string]: unknown }, + ): Promise>; processResponse< AnotherMethod extends Web3APIMethod, - ResponseType = Web3APIReturnType> - ( - response: JsonRpcResponse, - options?: { [key: string]: unknown }): Promise>; - } \ No newline at end of file + ResponseType = Web3APIReturnType, + >( + response: JsonRpcResponse, + options?: { [key: string]: unknown }, + ): Promise>; +} diff --git a/packages/web3-core/src/web3_request_manager.ts b/packages/web3-core/src/web3_request_manager.ts index dc12d919fd0..84f4db068f8 100644 --- a/packages/web3-core/src/web3_request_manager.ts +++ b/packages/web3-core/src/web3_request_manager.ts @@ -79,7 +79,7 @@ export class Web3RequestManager< public constructor( provider?: SupportedProviders | string, useRpcCallSpecification?: boolean, - requestManagerMiddleware?: RequestManagerMiddleware + requestManagerMiddleware?: RequestManagerMiddleware, ) { super(); @@ -88,11 +88,9 @@ export class Web3RequestManager< } this.useRpcCallSpecification = useRpcCallSpecification; - if (!isNullish(requestManagerMiddleware)) - this.middleware = requestManagerMiddleware; - + if (!isNullish(requestManagerMiddleware)) this.middleware = requestManagerMiddleware; } - + /** * Will return all available providers */ @@ -150,7 +148,7 @@ export class Web3RequestManager< return true; } - public setMiddleware(requestManagerMiddleware: RequestManagerMiddleware){ + public setMiddleware(requestManagerMiddleware: RequestManagerMiddleware) { this.middleware = requestManagerMiddleware; } @@ -167,16 +165,11 @@ export class Web3RequestManager< Method extends Web3APIMethod, ResponseType = Web3APIReturnType, >(request: Web3APIRequest): Promise { - - let requestObj = {...request}; - - if (!isNullish(this.middleware)) - requestObj = await this.middleware.processRequest(requestObj); + const requestObj = { ...request }; let response = await this._sendRequest(requestObj); - if (!isNullish(this.middleware)) - response = await this.middleware.processResponse(response); + if (!isNullish(this.middleware)) response = await this.middleware.processResponse(response); if (jsonRpc.isResponseWithResult(response)) { return response.result; @@ -210,10 +203,15 @@ export class Web3RequestManager< ); } - const payload = jsonRpc.isBatchRequest(request) - ? jsonRpc.toBatchPayload(request) - : jsonRpc.toPayload(request); + let payload = ( + jsonRpc.isBatchRequest(request) + ? jsonRpc.toBatchPayload(request) + : jsonRpc.toPayload(request) + ) as JsonRpcPayload; + if (!isNullish(this.middleware)) { + payload = (await this.middleware.processRequest(payload)); + } if (isWeb3Provider(provider)) { let response; @@ -447,10 +445,10 @@ export class Web3RequestManager< } else if ((response as unknown) instanceof Error) { error = response as unknown as JsonRpcError; } - + // This message means that there was an error while executing the code of the smart contract // However, more processing will happen at a higher level to decode the error data, - // according to the Error ABI, if it was available as of EIP-838. + // according to the Error ABI, if it was available as of EIP-838. if (error?.message.includes('revert')) throw new ContractExecutionError(error); return false; diff --git a/packages/web3-core/test/unit/web3_context.test.ts b/packages/web3-core/test/unit/web3_context.test.ts index 186122df54e..c235a06cb83 100644 --- a/packages/web3-core/test/unit/web3_context.test.ts +++ b/packages/web3-core/test/unit/web3_context.test.ts @@ -18,7 +18,13 @@ 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 { + EthExecutionAPI, + JsonRpcPayload, + JsonRpcResponse, + Web3APIMethod, + Web3APIReturnType, +} from 'web3-types'; import { Web3Context, Web3PluginBase } from '../../src/web3_context'; import { Web3RequestManager } from '../../src/web3_request_manager'; import { RequestManagerMiddleware } from '../../src/types'; @@ -69,11 +75,19 @@ describe('Web3Context', () => { it('should set middleware for the request manager', () => { const context = new Web3Context('http://test.com'); - const middleware: RequestManagerMiddleware - = { - processRequest: jest.fn(async >(request: Web3APIRequest) => request), - processResponse: jest.fn(async , ResponseType = Web3APIReturnType>(response: JsonRpcResponse) => response), - }; + const middleware: RequestManagerMiddleware = { + processRequest: jest.fn( + async (request: JsonRpcPayload) => request, + ), + processResponse: jest.fn( + async < + Method extends Web3APIMethod, + ResponseType = Web3APIReturnType, + >( + response: JsonRpcResponse, + ) => response, + ), + }; context.setRequestManagerMiddleware(middleware); expect(context.requestManager.middleware).toEqual(middleware); @@ -95,7 +109,9 @@ describe('Web3Context', () => { ).find(s => s.description === 'shapeMode'); if (symbolForShapeMode) { // eslint-disable-next-line @typescript-eslint/no-explicit-any - delete (context.getContextObject().requestManager as any)._emitter[symbolForShapeMode]; + delete (context.getContextObject().requestManager as any)._emitter[ + symbolForShapeMode + ]; } // eslint-disable-next-line @typescript-eslint/no-explicit-any (context.getContextObject().requestManager as any)._emitter = { 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 d240831d91b..7b971883613 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 @@ -15,130 +15,163 @@ 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 { + EthExecutionAPI, + JsonRpcPayload, + JsonRpcRequest, + JsonRpcResponse, + Web3APIMethod, + Web3APIReturnType, +} from 'web3-types'; import { jsonRpc } from 'web3-utils'; 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> { - // Implement the processRequest logic here - - let requestObj = {...request}; - if (request.method === 'eth_call' && Array.isArray(request.params)) { - requestObj = { - ...requestObj, - params: [...request.params, '0x0', '0x1'], - }; - } - - return Promise.resolve(requestObj); - } - - // eslint-disable-next-line class-methods-use-this - public async processResponse< - Method extends Web3APIMethod, - ResponseType = Web3APIReturnType - >( - response: JsonRpcResponse - ): Promise> { - - let responseObj = {...response}; - if (!jsonRpc.isBatchResponse(responseObj) && responseObj.id === 1) { - responseObj = { - ...responseObj, - result: '0x6a756e616964' as any, - }; - } - - return Promise.resolve(responseObj); - } + // eslint-disable-next-line class-methods-use-this + public async processRequest( + request: JsonRpcPayload, + ): Promise> { + // Implement the processRequest logic here + + let requestObj = { ...request }; + if ( + (requestObj as JsonRpcRequest).method === 'eth_call' && + Array.isArray((requestObj as JsonRpcRequest).params) + ) { + (requestObj as JsonRpcRequest) = { + ...(requestObj as JsonRpcRequest), + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + params: [...((requestObj as JsonRpcRequest).params ?? []), '0x0', '0x1'], + }; + } + + return Promise.resolve(requestObj as JsonRpcPayload); + } + + // eslint-disable-next-line class-methods-use-this + public async processResponse< + Method extends Web3APIMethod, + ResponseType = Web3APIReturnType, + >(response: JsonRpcResponse): Promise> { + let responseObj = { ...response }; + if (!jsonRpc.isBatchResponse(responseObj) && responseObj.id === 1) { + responseObj = { + ...responseObj, + result: '0x6a756e616964' as any, + }; + } + + return Promise.resolve(responseObj); + } } 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', () => { - const web3RequestManager1: Web3RequestManager = new Web3RequestManager(undefined, true, requestManagerMiddleware); - - expect(web3RequestManager1.middleware).toBeDefined(); - expect(web3RequestManager1.middleware).toEqual(requestManagerMiddleware); - }); - - it('should set requestManagerMiddleware via set method', () => { - - const middleware2: RequestManagerMiddleware = new Web3Middleware(); - const web3RequestManager2: Web3RequestManager = 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 ); - - 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).toBe('0x6a756e616964'); - - expect(mockSendRequest).toHaveBeenCalledWith({ - ...request, - params: [...request.params, '0x0', '0x1'], - }); - - }); + let requestManagerMiddleware: RequestManagerMiddleware; + + beforeAll(() => { + requestManagerMiddleware = { + processRequest: jest.fn( + async (request: JsonRpcPayload) => request, + ), + processResponse: jest.fn( + async < + Method extends Web3APIMethod, + ResponseType = Web3APIReturnType, + >( + response: JsonRpcResponse, + ) => response, + ), + }; + }); + + it('should set requestManagerMiddleware via constructor', () => { + const web3RequestManager1: Web3RequestManager = new Web3RequestManager( + undefined, + true, + requestManagerMiddleware, + ); + + expect(web3RequestManager1.middleware).toBeDefined(); + expect(web3RequestManager1.middleware).toEqual(requestManagerMiddleware); + }); + + it('should set requestManagerMiddleware via set method', () => { + const middleware2: RequestManagerMiddleware = + new Web3Middleware(); + const web3RequestManager2: Web3RequestManager = 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, + ); + + const expectedResponse: JsonRpcResponse = { + jsonrpc: '2.0', + id: 1, + result: '0x0', + }; + + jest.spyOn(web3RequestManager3.provider as any, 'request').mockResolvedValue( + expectedResponse, + ); + + const request = { + id: 1, + method: 'eth_call', + params: [], + }; + + await web3RequestManager3.send(request); + + expect(requestManagerMiddleware.processRequest).toHaveBeenCalledWith({ + jsonrpc: '2.0', + ...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.provider as any, 'request'); + mockSendRequest.mockResolvedValue(expectedResponse); + + const request = { + id: 1, + method: 'eth_call', + params: ['0x3'], + }; + + const response = await web3RequestManager3.send(request); + expect(response).toBe('0x6a756e616964'); + + expect(mockSendRequest).toHaveBeenCalledWith({ + ...request, + jsonrpc: '2.0', + params: [...request.params, '0x0', '0x1'], + }); + }); }); diff --git a/packages/web3/CHANGELOG.md b/packages/web3/CHANGELOG.md index 69473aeb916..15fca59a531 100644 --- a/packages/web3/CHANGELOG.md +++ b/packages/web3/CHANGELOG.md @@ -264,6 +264,6 @@ Documentation: ## [Unreleased] -### added +### Added -- Updated type `Web3EthInterface.accounts` to includes `privateKeyToAccount`,`privateKeyToAddress`,and `privateKeyToPublicKey` (#6762) \ No newline at end of file +- Updated type `Web3EthInterface.accounts` to includes `privateKeyToAccount`,`privateKeyToAddress`,and `privateKeyToPublicKey` (#6762) diff --git a/tools/web3-plugin-example/src/middleware.ts b/tools/web3-plugin-example/src/middleware.ts index 3af435fd025..bf16bc619f8 100644 --- a/tools/web3-plugin-example/src/middleware.ts +++ b/tools/web3-plugin-example/src/middleware.ts @@ -14,48 +14,63 @@ 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"; +import { RequestManagerMiddleware } from 'web3-core'; +import { + Web3APIMethod, + Web3APIReturnType, + JsonRpcResponse, + JsonRpcPayload, + JsonRpcRequest, +} from 'web3-types'; +import { jsonRpc } from 'web3-utils'; export class Web3Middleware implements RequestManagerMiddleware { + // eslint-disable-next-line class-methods-use-this + public async processRequest( + request: JsonRpcPayload, + ): Promise> { + // add your custom logic here for processing requests + let reqObj = { ...request } as JsonRpcPayload; + if (Array.isArray(reqObj)) { + reqObj = reqObj.map((req: JsonRpcRequest) => { + if (req.method === 'eth_call' && Array.isArray(req.params)) { + return { + ...req, + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + params: [...req.params, '0x0', '0x1'], + }; + } + return req; + }); + } else 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'], + }; + } - // eslint-disable-next-line class-methods-use-this - public async processRequest>( - request: Web3APIRequest - ): Promise> { - - // add your custom logic here for processing requests - 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(reqObj as JsonRpcPayload); + } - return Promise.resolve(reqObj); - } + // eslint-disable-next-line class-methods-use-this + public async processResponse< + Method extends Web3APIMethod, + ResponseType = Web3APIReturnType, + >(response: JsonRpcResponse): Promise> { + // 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, + }; + } - // eslint-disable-next-line class-methods-use-this - public async processResponse< - Method extends Web3APIMethod, - ResponseType = Web3APIReturnType - >( - response: JsonRpcResponse - ): Promise> { - - // 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(resObj); - } -} \ No newline at end of file + return Promise.resolve(resObj); + } +} diff --git a/tools/web3-plugin-example/test/unit/middleware.test.ts b/tools/web3-plugin-example/test/unit/middleware.test.ts index 717ddc8856d..78ce5d7df8b 100644 --- a/tools/web3-plugin-example/test/unit/middleware.test.ts +++ b/tools/web3-plugin-example/test/unit/middleware.test.ts @@ -15,25 +15,26 @@ 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 Web3, { TransactionCall } from 'web3'; +import { jsonRpc } from 'web3-utils'; import { CustomRpcMethodsPlugin } from '../../src/custom_rpc_methods'; - 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); // Test mocks and spy - code block start - const expectedResponse: JsonRpcResponse = { + const expectedResponse = { jsonrpc: '2.0', id: 1, - result: '0x0', - }; - - const mockSendRequest = jest.spyOn(web3.requestManager as any, '_sendRequest'); - mockSendRequest.mockResolvedValue(expectedResponse); + result: '0x6a756e616964', + }; + + jsonRpc.setRequestIdStart(0); + + const mockRequest = jest.spyOn(web3.provider as any, 'request'); + mockRequest.mockResolvedValue(expectedResponse); // Test mocks and spy - code block end web3.registerPlugin(plugin); @@ -52,15 +53,16 @@ describe('CustomRpcMethodsPlugin Middleware', () => { expect(result).toBe('0x6a756e616964'); // result modified by response processor , so its 0x6a756e616964 instead 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); - + jsonrpc: '2.0', + id: 1, + method: 'eth_call', + params: [ + { ...transaction }, + 'latest', + '0x0', // added by middleware by request processor + '0x1', // added by middleware by request processor + ], + }; + expect(mockRequest).toHaveBeenCalledWith(expectedCall); }); }); From f216540e4fd8af19bfc1ec86afbc26076a6769f4 Mon Sep 17 00:00:00 2001 From: Oleksii Kosynskyi Date: Mon, 6 May 2024 16:34:44 -0400 Subject: [PATCH 18/32] Add type checking to unit tests (#7027) --- templates/jest.config.js.tmpl | 1 - 1 file changed, 1 deletion(-) diff --git a/templates/jest.config.js.tmpl b/templates/jest.config.js.tmpl index 2b65a1760a3..e4d70e55a94 100644 --- a/templates/jest.config.js.tmpl +++ b/templates/jest.config.js.tmpl @@ -26,7 +26,6 @@ module.exports = { 'ts-jest', { tsconfig: './test/tsconfig.json', - isolatedModules: true, }, ], }, From f44dc5b6ad00648bff4abfc4339386ed6076275a Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Thu, 9 May 2024 06:35:40 -0700 Subject: [PATCH 19/32] fix(glossary): links (#7034) * fix(glossary): links * Fix broken links --- docs/docs/{guides => }/glossary/index.md | 0 docs/docs/glossary/json_interface.md | 89 ------------------- docs/docusaurus.config.js | 2 +- .../web3-eth-contract/src/log_subscription.ts | 2 +- packages/web3-types/src/eth_contract_types.ts | 2 +- 5 files changed, 3 insertions(+), 92 deletions(-) rename docs/docs/{guides => }/glossary/index.md (100%) delete mode 100644 docs/docs/glossary/json_interface.md diff --git a/docs/docs/guides/glossary/index.md b/docs/docs/glossary/index.md similarity index 100% rename from docs/docs/guides/glossary/index.md rename to docs/docs/glossary/index.md diff --git a/docs/docs/glossary/json_interface.md b/docs/docs/glossary/json_interface.md deleted file mode 100644 index fe6384e060d..00000000000 --- a/docs/docs/glossary/json_interface.md +++ /dev/null @@ -1,89 +0,0 @@ ---- -title: JSON Interface ---- - -The JSON interface is a `JSON` object describing the [Application Binary Interface (ABI)](https://docs.soliditylang.org/en/develop/abi-spec.html) for an Ethereum smart contract. - -Using this JSON interface, web3.js is able to create a JavaScript object representing the smart contract , its methods and events using the `web3.eth.Contract` object. - -### Specification - -#### Functions - -- `type`: `"function"`, `"constructor"` (can be omitted, defaulting to `"function"`; `"fallback"` also possible but not relevant in web3.js); -- `name`: the name of the function (only present for function types); -- `constant`: `true` if function is specified to not modify the blockchain state; -- `payable`: `true` if function accepts ether, defaults to false; -- `stateMutability`: a `string` with one of the following values: `"pure"` (specified to not read blockchain state), `"view"` (same as constant above), `"non-payable"` and `"payable"` (same as payable above); -- `inputs`: an `Array of objects`, each of which contains: - -- `name`: the name of the parameter; - -- `type`: the canonical type of the parameter. -- `outputs`: an `Array of objects`, same as inputs, can be omitted if no outputs exist. - -#### Events - -- `type`: always `"event"` -- `name`: the name of the event; -- `inputs`: an `Array of objects`, each of which contains: - - - `name`: the name of the parameter; - - - `type`: the canonical type of the parameter. - - - `indexed`: `true` if the field is part of the log’s topics, false if it is one of the log’s data segment. - - - `anonymous`: `true` if the event was declared as anonymous. - -#### Example - -```solidity title='Solidity Contract' -pragma solidity ^0.8.4; - -contract Test { - uint256 a; - address d = 0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF; - - constructor(uint256 testInt) { - a = testInt; - } - - event Event(uint256 indexed b, bytes32 c); - - event Event2(uint256 indexed b, bytes32 c); - - function foo(uint256 b, bytes32 c) public returns (address) { - emit Event(b, c); - return d; - } -} - -``` - -```json title='Resulting JSON ABI' -[ - { - "type": "constructor", - "stateMutability": "nonpayable", - "inputs": [{"internalType":"uint256","name":"testInt","type":"uint256"}], - }, - { - "type": "event", - "name": "Event", - "inputs": [{"indexed":true,"internalType":"uint256","name":"b","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"c","type":"bytes32"}], - "anonymous": false, - }, - { - "type": "event", - "name": "Event2", - "inputs": [{"indexed":true,"internalType":"uint256","name":"b","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"c","type":"bytes32"}], - "anonymous": false, - }, - { - "type": "function", - "name": "foo", - "stateMutability": "nonpayable", - "inputs": [{"internalType":"uint256","name":"b","type":"uint256"},{"internalType":"bytes32","name":"c","type":"bytes32"}], - "outputs": [{"internalType":"address","name":"","type":"address"}], - } -] -``` diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index 29c2c66284c..3cf7c9a8443 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -132,7 +132,7 @@ const config = { position: 'left', }, { - to: '/glossary/json_interface', + to: 'glossary', activeBasePath: '/glossary/', label: 'Glossary', position: 'left', diff --git a/packages/web3-eth-contract/src/log_subscription.ts b/packages/web3-eth-contract/src/log_subscription.ts index 6ace1e17478..3cb1a527941 100644 --- a/packages/web3-eth-contract/src/log_subscription.ts +++ b/packages/web3-eth-contract/src/log_subscription.ts @@ -101,7 +101,7 @@ export class LogsSubscription extends Web3Subscription< public readonly topics?: (Topic | Topic[] | null)[]; /** - * The {@doclink glossary/json_interface | JSON Interface} of the event. + * The {@doclink glossary#json-interface-abi | JSON Interface} of the event. */ public readonly abi: AbiEventFragment & { signature: HexString }; diff --git a/packages/web3-types/src/eth_contract_types.ts b/packages/web3-types/src/eth_contract_types.ts index fb34328ce21..00eba77e5ed 100644 --- a/packages/web3-types/src/eth_contract_types.ts +++ b/packages/web3-types/src/eth_contract_types.ts @@ -114,7 +114,7 @@ export interface ContractOptions { readonly data?: Bytes; /** - * The {@doclink glossary/json_interface | json interface} object derived from the [ABI](https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI) of this contract. + * The {@doclink glossary#json-interface-abi | json interface} object derived from the [ABI](https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI) of this contract. * * Re-setting this will regenerate the methods and events of the contract instance. * From 12c251589198129781d24d2327d67ead9f20b3e8 Mon Sep 17 00:00:00 2001 From: Oleksii Kosynskyi Date: Mon, 13 May 2024 10:08:31 -0400 Subject: [PATCH 20/32] add interactive code for tutorials (#7036) --- docs/docs/guides/ens/index.md | 4 +++- .../docs/guides/events_subscriptions/index.md | 1 + docs/docs/guides/getting_started/metamask.md | 5 ++++- docs/docs/guides/web3_eth/eth.md | 2 ++ docs/docs/guides/web3_plugin_guide/index.mdx | 22 ++++++++++--------- .../web3_utils_module/mastering_web3-utils.md | 1 + 6 files changed, 23 insertions(+), 12 deletions(-) diff --git a/docs/docs/guides/ens/index.md b/docs/docs/guides/ens/index.md index 78de32fc4fb..a55f9662799 100644 --- a/docs/docs/guides/ens/index.md +++ b/docs/docs/guides/ens/index.md @@ -6,6 +6,8 @@ title: Mastering the Web3 ENS package # Using web3.js ENS Package + + In this tutorial, we'll explore how to use the web3.js ENS (Ethereum Name Service) package. The Ethereum Name Service (ENS) is a decentralized domain system built on the Ethereum blockchain. It serves as a distributed, secure, and human-readable naming system designed to map Ethereum addresses, smart contracts, and various other services to easily understandable names. ## Installing web3.js @@ -115,4 +117,4 @@ console.log(result); ## Conclusion -In this tutorial, we've covered how to use the web3.js ENS package to interact with Ethereum Name Service. You should now be able to perform various ENS-related operations using web3.js version 4. For more details visit web3.js ENS [documentation](/libdocs/ENS) section. \ No newline at end of file +In this tutorial, we've covered how to use the web3.js ENS package to interact with Ethereum Name Service. You should now be able to perform various ENS-related operations using web3.js version 4. For more details visit web3.js ENS [documentation](/libdocs/ENS) section. diff --git a/docs/docs/guides/events_subscriptions/index.md b/docs/docs/guides/events_subscriptions/index.md index b17baceec12..bd4ed1a3387 100644 --- a/docs/docs/guides/events_subscriptions/index.md +++ b/docs/docs/guides/events_subscriptions/index.md @@ -4,6 +4,7 @@ sidebar_label: 'Mastering Events Subcriptions' --- # Events Subscription + ## Subscribing to smart contracts events diff --git a/docs/docs/guides/getting_started/metamask.md b/docs/docs/guides/getting_started/metamask.md index 714360b9665..e40db544ac6 100644 --- a/docs/docs/guides/getting_started/metamask.md +++ b/docs/docs/guides/getting_started/metamask.md @@ -5,6 +5,9 @@ sidebar_label: Connecting to Metamask # Connecting to Metamask + + + ## React app After creating your react app `npx create-react-app app-name`, and installing web3 `npm i web3` you can go to `src/app.js`, you can clean up the code and import `{Web3}`. It should look like this: @@ -186,4 +189,4 @@ export default App; ``` - \ No newline at end of file + diff --git a/docs/docs/guides/web3_eth/eth.md b/docs/docs/guides/web3_eth/eth.md index cce7370e9a0..5db4eef6919 100644 --- a/docs/docs/guides/web3_eth/eth.md +++ b/docs/docs/guides/web3_eth/eth.md @@ -8,6 +8,8 @@ import TabItem from '@theme/TabItem'; # Getting Started with `eth` Package + + ## Introduction The `web3-eth` package provides a set of powerful functionalities to interact with the Ethereum blockchain and smart contracts. In this tutorial, we will guide you through the basics of using the `web3-eth` package of web3.js version 4. We will be using TypeScript throughout the examples. diff --git a/docs/docs/guides/web3_plugin_guide/index.mdx b/docs/docs/guides/web3_plugin_guide/index.mdx index 69a39859415..ef1942c53fc 100644 --- a/docs/docs/guides/web3_plugin_guide/index.mdx +++ b/docs/docs/guides/web3_plugin_guide/index.mdx @@ -5,14 +5,16 @@ sidebar_label: 'Getting started' # Getting Started -Welcome to the Web3 Plugins🧩 Guide, a new feature introduced in web3.js v4. In addition to the core web3.js libraries, plugins bring specialized functionalities tailored for end-users (functionalities, that you, as a developer, can create). These enhancements may involve creating wrappers for specific contracts, adding extra features to RPC methods, adding any external libraries, logic, extending the capabilities of web3.js methods, etc... + -In this guide, you will learn the basics to get started building web3 plugins, setting up providers, importing, and using different web3.js packages. +Welcome to the Web3 Plugins🧩 Guide, a new feature introduced in web3.js v4. In addition to the core web3.js libraries, plugins bring specialized functionalities tailored for end-users (functionalities, that you, as a developer, can create). These enhancements may involve creating wrappers for specific contracts, adding extra features to RPC methods, adding any external libraries, logic, extending the capabilities of web3.js methods, etc... + +In this guide, you will learn the basics to get started building web3 plugins, setting up providers, importing, and using different web3.js packages. - [Plugin Developer Guide (For Creators)](/guides/web3_plugin_guide/plugin_authors) - [Plugin User Guide (Usage)](/guides/web3_plugin_guide/plugin_users) -- You can find all the web3 plugins🧩 [here](https://web3js.org/plugins) +- You can find all the web3 plugins🧩 [here](https://web3js.org/plugins) - To list your web3 plugin🧩 into the web3js.org/plugins page, you can submit a PR [here](https://github.com/web3/web3js-landing/blob/main/src/pluginList.ts) @@ -24,9 +26,9 @@ import { Web3PluginBase } from "web3"; //2. Create a Class extending the `Web3Pluginbase` class MyPlugin extends Web3PluginBase { - + //3. Add a name to the plugin - pluginNamespace = "pluginExample"; + pluginNamespace = "pluginExample"; //4. Create any methods with your desired functionality async doSomething(){ @@ -118,7 +120,7 @@ class MyPlugin extends Web3PluginBase { async createAccount() { const account = eth.accounts.create(); console.log("account:", account); - /* + /* account: { address: '0x59E797F2F66AffA9A419a6BC2ED4742b7cBc2570', privateKey: '0x52a81fc3a7fd6ce9644147c9fb5bfbe1f708f37b4611b3c3310eb9a6dc85ccf4', @@ -149,7 +151,7 @@ class MyPlugin extends Web3PluginBase { const wallet = this.wallet.add(accounts); //by creating the wallet, web3.js will use this account to sign TXs under the hood console.log(wallet); - /* + /* Wallet(1) [ { address: '0x233725561B1430bE2C24Ce9EEabe63E4B46EC9E3', @@ -186,10 +188,10 @@ class MyPlugin extends Web3PluginBase { async interactWithContract() { //1. Initialize contract const myContract = new Contract(ABI, ADDRESS); - + //2. Interact with reading functions const response = myContract.methods.doSomething().call(); - + //3. Interact with writing functions //You must initialize a wallet to be able to send the TX from wallet[0].address const txReceipt = myContract.methods.doSomething().send({from: wallet[0].address}) @@ -279,7 +281,7 @@ All web3 config params [here](https://docs.web3js.org/guides/web3_config/) ::: -## Videos +## Videos ### Create your first plugin in 20 minutes! diff --git a/docs/docs/guides/web3_utils_module/mastering_web3-utils.md b/docs/docs/guides/web3_utils_module/mastering_web3-utils.md index 7bad9e3b396..c1ea5b833f7 100644 --- a/docs/docs/guides/web3_utils_module/mastering_web3-utils.md +++ b/docs/docs/guides/web3_utils_module/mastering_web3-utils.md @@ -1,6 +1,7 @@ # Mastering Utility Functions ## Introduction + In this guide, you'll learn about the different functions of the web3 utils package, it contains the methods to know how to generate random bytes in different formats, how to perform conversion between Hex values and numbers, hashing functions, addresses, packing padding and in the last part you will see how to compare block numbers. ## Installation From 040812570a6ef68b7123c323a34ea79466154455 Mon Sep 17 00:00:00 2001 From: Petr Knetl Date: Tue, 14 May 2024 01:05:58 +0200 Subject: [PATCH 21/32] fix: web3-validator browser target removed (#7016) * fix: web3-validator browser target removed * fixup! fix: web3-validator browser target removed --- packages/web3-validator/CHANGELOG.md | 1 + packages/web3-validator/package.json | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web3-validator/CHANGELOG.md b/packages/web3-validator/CHANGELOG.md index dc5834852ca..ea8cd0259ff 100644 --- a/packages/web3-validator/CHANGELOG.md +++ b/packages/web3-validator/CHANGELOG.md @@ -173,3 +173,4 @@ Documentation: ### Fixed - The JSON schema conversion process now correctly assigns an id when the `abi.name` is not available, for example, in the case of public mappings. +- `browser` entry point that was pointing to an non-existing bundle file was removed from `package.json` (#7015) diff --git a/packages/web3-validator/package.json b/packages/web3-validator/package.json index 20e285cce80..c416a1fa235 100644 --- a/packages/web3-validator/package.json +++ b/packages/web3-validator/package.json @@ -11,7 +11,6 @@ "require": "./lib/commonjs/index.js" } }, - "browser": "./dist/web3-validator.min.js", "repository": "https://github.com/ChainSafe/web3.js", "author": "ChainSafe Systems", "license": "LGPL-3.0", From 866469dc143d71baa128eae09c0d60b51cfdc28e Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 14 May 2024 07:32:12 -0400 Subject: [PATCH 22/32] catching promise - legacy provider error (#7022) * adding data check for revert util method * fix up tests * fix lint * change legacy request * revert contract changes, add try catch * fix lint * fix changes * update tests * lint and feedback * update test * update test * format --- .../web3-core/src/web3_request_manager.ts | 21 ++++++++++-- .../test/unit/web3_request_manager.test.ts | 33 +++++++++++++++++++ .../web3_eth/send_transaction.test.ts | 29 +++++++++++----- .../external-providers/hardhat.test.ts | 9 +++-- .../integration/external-providers/helper.ts | 28 +++++++++++++++- 5 files changed, 106 insertions(+), 14 deletions(-) diff --git a/packages/web3-core/src/web3_request_manager.ts b/packages/web3-core/src/web3_request_manager.ts index 84f4db068f8..1cbe9377988 100644 --- a/packages/web3-core/src/web3_request_manager.ts +++ b/packages/web3-core/src/web3_request_manager.ts @@ -210,7 +210,7 @@ export class Web3RequestManager< ) as JsonRpcPayload; if (!isNullish(this.middleware)) { - payload = (await this.middleware.processRequest(payload)); + payload = await this.middleware.processRequest(payload); } if (isWeb3Provider(provider)) { let response; @@ -248,7 +248,7 @@ export class Web3RequestManager< // TODO: This could be deprecated and removed. if (isLegacyRequestProvider(provider)) { return new Promise>((resolve, reject) => { - const rejectWithError = (err: unknown) => + const rejectWithError = (err: unknown) => { reject( this._processJsonRpcResponse( payload, @@ -259,6 +259,8 @@ export class Web3RequestManager< }, ), ); + }; + const resolveWithResponse = (response: JsonRpcResponse) => resolve( this._processJsonRpcResponse(payload, response, { @@ -288,7 +290,20 @@ export class Web3RequestManager< const responsePromise = result as unknown as Promise< JsonRpcResponse >; - responsePromise.then(resolveWithResponse).catch(rejectWithError); + responsePromise.then(resolveWithResponse).catch(error => { + try { + // Attempt to process the error response + const processedError = this._processJsonRpcResponse( + payload, + error as JsonRpcResponse, + { legacy: true, error: true }, + ); + reject(processedError); + } catch (processingError) { + // Catch any errors that occur during the error processing + reject(processingError); + } + }); } }); } diff --git a/packages/web3-core/test/unit/web3_request_manager.test.ts b/packages/web3-core/test/unit/web3_request_manager.test.ts index 375e27a5d1e..2db8c010fd8 100644 --- a/packages/web3-core/test/unit/web3_request_manager.test.ts +++ b/packages/web3-core/test/unit/web3_request_manager.test.ts @@ -280,6 +280,7 @@ describe('Web3RequestManager', () => { expect(myProvider.request).toHaveBeenCalledTimes(1); expect(await pr).toBe('test'); }); + it('Got a "nullish" response from provider', async () => { const manager = new Web3RequestManager(undefined, undefined); const myProvider = { @@ -1134,6 +1135,38 @@ describe('Web3RequestManager', () => { expect(myProvider.request).toHaveBeenCalledWith(payload, expect.any(Function)); }); + it('should error in isPromise', async () => { + const manager = new Web3RequestManager(); + const myProvider = { + request: jest + .fn() + .mockImplementation(async () => Promise.reject(errorResponse)), + } as any; + + jest.spyOn(manager, 'provider', 'get').mockReturnValue(myProvider); + + await expect(manager.sendBatch(request)).rejects.toEqual(errorResponse); + expect(myProvider.request).toHaveBeenCalledTimes(1); + expect(myProvider.request).toHaveBeenCalledWith(payload, expect.any(Function)); + }); + + it('should catch error and process json response in isPromise', async () => { + const manager = new Web3RequestManager(); + const myProvider = { + request: jest + .fn() + .mockImplementation(async () => Promise.reject(errorResponse)), + } as any; + jest.spyOn(manager as any, '_processJsonRpcResponse').mockImplementation(() => { + return errorResponse; + }); + jest.spyOn(manager, 'provider', 'get').mockReturnValue(myProvider); + + await expect(manager.sendBatch(request)).rejects.toEqual(errorResponse); + expect(myProvider.request).toHaveBeenCalledTimes(1); + expect(myProvider.request).toHaveBeenCalledWith(payload, expect.any(Function)); + }); + it('should pass request to provider and reject if provider returns error', async () => { const manager = new Web3RequestManager(); const myProvider = { diff --git a/packages/web3-eth/test/integration/web3_eth/send_transaction.test.ts b/packages/web3-eth/test/integration/web3_eth/send_transaction.test.ts index 9018381bd6a..9b0eda360dc 100644 --- a/packages/web3-eth/test/integration/web3_eth/send_transaction.test.ts +++ b/packages/web3-eth/test/integration/web3_eth/send_transaction.test.ts @@ -90,7 +90,9 @@ describe('Web3Eth.sendTransaction', () => { expect(response.status).toBe(BigInt(1)); expect(response.events).toBeUndefined(); - const minedTransactionData = await web3EthWithWallet.getTransaction(response.transactionHash); + const minedTransactionData = await web3EthWithWallet.getTransaction( + response.transactionHash, + ); expect(minedTransactionData).toMatchObject({ from: tempAcc.address, @@ -119,7 +121,9 @@ describe('Web3Eth.sendTransaction', () => { expect(response.status).toBe(BigInt(1)); expect(response.events).toBeUndefined(); - const minedTransactionData = await web3EthWithWallet.getTransaction(response.transactionHash); + const minedTransactionData = await web3EthWithWallet.getTransaction( + response.transactionHash, + ); expect(minedTransactionData).toMatchObject({ from: tempAcc.address, @@ -152,7 +156,9 @@ describe('Web3Eth.sendTransaction', () => { expect(response.status).toBe(BigInt(1)); expect(response.events).toBeUndefined(); - const minedTransactionData = await web3EthWithWallet.getTransaction(response.transactionHash); + const minedTransactionData = await web3EthWithWallet.getTransaction( + response.transactionHash, + ); expect(minedTransactionData).toMatchObject({ from: tempAcc.address, @@ -534,9 +540,12 @@ describe('Web3Eth.sendTransaction', () => { from: tempAcc.address, data: SimpleRevertDeploymentData, }; - simpleRevertDeployTransaction.gas = await web3Eth.estimateGas(simpleRevertDeployTransaction); - simpleRevertContractAddress = (await web3Eth.sendTransaction(simpleRevertDeployTransaction)) - .contractAddress as Address; + simpleRevertDeployTransaction.gas = await web3Eth.estimateGas( + simpleRevertDeployTransaction, + ); + simpleRevertContractAddress = ( + await web3Eth.sendTransaction(simpleRevertDeployTransaction) + ).contractAddress as Address; }); it('Should throw TransactionRevertInstructionError because gas too low', async () => { @@ -578,7 +587,9 @@ describe('Web3Eth.sendTransaction', () => { const transaction: Transaction = { from: tempAcc.address, to: '0x0000000000000000000000000000000000000000', - value: BigInt('99999999999999999999999999999999999999999999999999999999999999999'), + value: BigInt( + '99999999999999999999999999999999999999999999999999999999999999999', + ), }; const expectedThrownError = { @@ -587,7 +598,9 @@ describe('Web3Eth.sendTransaction', () => { code: 402, reason: getSystemTestBackend() === BACKEND.GETH - ? expect.stringContaining('err: insufficient funds for gas * price + value: address') + ? expect.stringContaining( + 'err: insufficient funds for gas * price + value: address', + ) : 'VM Exception while processing transaction: insufficient balance', }; diff --git a/packages/web3/test/integration/external-providers/hardhat.test.ts b/packages/web3/test/integration/external-providers/hardhat.test.ts index 989424199fb..6a4fb6ff28b 100644 --- a/packages/web3/test/integration/external-providers/hardhat.test.ts +++ b/packages/web3/test/integration/external-providers/hardhat.test.ts @@ -18,11 +18,16 @@ along with web3.js. If not, see . // eslint-disable-next-line import/no-extraneous-dependencies import hardhat from 'hardhat'; -import { performBasicRpcCalls } from './helper'; +import { performBasicRpcCalls, failErrorCalls} from './helper'; describe('compatibility with `hardhat` provider', () => { it('should initialize Web3, get accounts & block number and send a transaction', async () => { // use the hardhat provider for web3.js - await performBasicRpcCalls(hardhat.network.provider); + await expect(performBasicRpcCalls(hardhat.network.provider)).resolves.not.toThrow(); }); + it('should throw on error calls', async () => { + const result = failErrorCalls(hardhat.network.provider); + await expect(result).rejects.toThrow(); + + }) }); diff --git a/packages/web3/test/integration/external-providers/helper.ts b/packages/web3/test/integration/external-providers/helper.ts index c1f88dd86b0..d88b1a7c90f 100644 --- a/packages/web3/test/integration/external-providers/helper.ts +++ b/packages/web3/test/integration/external-providers/helper.ts @@ -16,7 +16,9 @@ along with web3.js. If not, see . */ import { SupportedProviders } from 'web3-types'; +import { Contract } from 'web3-eth-contract'; import Web3 from '../../../src/index'; +import { BasicAbi, BasicBytecode } from '../../shared_fixtures/build/Basic'; /** * Performs basic RPC calls (like `eth_accounts`, `eth_blockNumber` and `eth_sendTransaction`) @@ -36,7 +38,7 @@ export async function performBasicRpcCalls(provider: SupportedProviders) { to: accounts[1], from: accounts[0], value: '1', - gas: 21000 + gas: 21000, }); expect(tx.status).toBe(BigInt(1)); @@ -46,3 +48,27 @@ export async function performBasicRpcCalls(provider: SupportedProviders) { // After sending a transaction, the blocknumber is supposed to be greater than or equal the block number before sending the transaction expect(blockNumber1).toBeGreaterThanOrEqual(blockNumber0); } + +export async function failErrorCalls(provider: SupportedProviders) { + let contract: Contract; + const web3 = new Web3(provider); + + contract = new web3.eth.Contract(BasicAbi, undefined, { + provider, + }); + + let deployOptions: Record; + + // eslint-disable-next-line prefer-const + deployOptions = { + data: BasicBytecode, + arguments: [10, 'string init value'], + }; + const accounts = await web3.eth.getAccounts(); + + const sendOptions = { from: accounts[0], gas: '1000000' }; + + contract = await contract.deploy(deployOptions).send(sendOptions); + + await contract.methods.reverts().send({ from: accounts[0] }); +} From 2f73aa5c1de205f30a3961388be27c47c7a28dc5 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 16 May 2024 10:16:22 -0400 Subject: [PATCH 23/32] web3modal documentation (#7041) * add web3modal guide * update docs * update link * update link * update examples * update docs positions * update emoji --- docs/docs/guides/advanced/_category_.yml | 2 +- docs/docs/guides/feedback/index.md | 2 +- .../resources_and_troubleshooting/index.md | 2 +- docs/docs/guides/web3_config/_category_.yml | 2 +- .../guides/web3_modal_guide/_category_.yml | 5 + docs/docs/guides/web3_modal_guide/index.mdx | 130 ++++++++++++++++++ docs/docs/guides/web3_modal_guide/vue.md | 122 ++++++++++++++++ 7 files changed, 261 insertions(+), 4 deletions(-) create mode 100644 docs/docs/guides/web3_modal_guide/_category_.yml create mode 100644 docs/docs/guides/web3_modal_guide/index.mdx create mode 100644 docs/docs/guides/web3_modal_guide/vue.md diff --git a/docs/docs/guides/advanced/_category_.yml b/docs/docs/guides/advanced/_category_.yml index dab551977cf..3131878f18e 100644 --- a/docs/docs/guides/advanced/_category_.yml +++ b/docs/docs/guides/advanced/_category_.yml @@ -2,4 +2,4 @@ label: '🧠 Advanced' collapsible: true collapsed: true link: null -position: 14 \ No newline at end of file +position: 15 \ No newline at end of file diff --git a/docs/docs/guides/feedback/index.md b/docs/docs/guides/feedback/index.md index 228003d5a6e..0118436ec91 100644 --- a/docs/docs/guides/feedback/index.md +++ b/docs/docs/guides/feedback/index.md @@ -1,5 +1,5 @@ --- -sidebar_position: 17 +sidebar_position: 18 sidebar_label: '🗣️ Feedback' --- diff --git a/docs/docs/guides/resources_and_troubleshooting/index.md b/docs/docs/guides/resources_and_troubleshooting/index.md index 2dd82f1e5b6..6426b99d8df 100644 --- a/docs/docs/guides/resources_and_troubleshooting/index.md +++ b/docs/docs/guides/resources_and_troubleshooting/index.md @@ -1,5 +1,5 @@ --- -sidebar_position: 16 +sidebar_position: 17 sidebar_label: '📚 Resources & Troubleshooting' --- # Resources & Troubleshooting diff --git a/docs/docs/guides/web3_config/_category_.yml b/docs/docs/guides/web3_config/_category_.yml index dbe4222696b..d1fd0583848 100644 --- a/docs/docs/guides/web3_config/_category_.yml +++ b/docs/docs/guides/web3_config/_category_.yml @@ -2,4 +2,4 @@ label: '⚙️ Web3 config' collapsible: true collapsed: true link: null -position: 15 \ No newline at end of file +position: 16 \ No newline at end of file diff --git a/docs/docs/guides/web3_modal_guide/_category_.yml b/docs/docs/guides/web3_modal_guide/_category_.yml new file mode 100644 index 00000000000..6744910f3b6 --- /dev/null +++ b/docs/docs/guides/web3_modal_guide/_category_.yml @@ -0,0 +1,5 @@ +label: '📱 WalletConnect Tutorial' +collapsible: true +collapsed: true +link: null +position: 14 \ No newline at end of file diff --git a/docs/docs/guides/web3_modal_guide/index.mdx b/docs/docs/guides/web3_modal_guide/index.mdx new file mode 100644 index 00000000000..a1bef97eb66 --- /dev/null +++ b/docs/docs/guides/web3_modal_guide/index.mdx @@ -0,0 +1,130 @@ +--- +sidebar_position: 1 +sidebar_label: 'Getting started' +--- + +# Getting Started + +Welcome to the Web3modal📱 Guide. + +The Web3Modal SDK allows you to easily connect your Web3 app with wallets. It provides a simple and intuitive interface for requesting actions such as signing transactions and interacting with smart contracts on the blockchain. + +In this guide, you will learn how to set up Walletconnect with web3js. + + + +## Preview +:::info +Switch your browsers if the preview doesn't load. +::: + + + + +## Installation + +```bash +npm install web3modal-web3js web3js +``` + +## Implementation + +```typescript + +import { createWeb3Modal, defaultConfig } from 'web3modal-web3/react' + +// 1. Get projectId, Your Project ID can be obtained from walletconnect.com +const projectId = 'YOUR_PROJECT_ID' + +// 2. Set chains +const mainnet = { + chainId: 1, + name: 'Ethereum', + currency: 'ETH', + explorerUrl: 'https://etherscan.io', + rpcUrl: 'https://cloudflare-eth.com' +} + +// 3. Create a metadata object +const metadata = { + name: 'My Website', + description: 'My Website description', + url: 'https://mywebsite.com', // origin must match your domain & subdomain + icons: ['https://avatars.mywebsite.com/'] +} + +// 4. Create web3 config +const web3Config = defaultConfig({ + /*Required*/ + metadata, + + /*Optional*/ + enableEIP6963: true, // true by default + enableInjected: true, // true by default + enableCoinbase: true, // true by default + rpcUrl: '...', // used for the Coinbase SDK + defaultChainId: 1, // used for the Coinbase SDK +}) + +// 5. Create a Web3Modal instance +createWeb3Modal({ + ethersConfig, + chains: [mainnet], + projectId, + enableAnalytics: true // Optional - defaults to your Cloud configuration +}) + +export default function App() { + return +} +``` + +## Triggering the modal + +```Typescript + +export default function ConnectButton() { + return +} + +``` + +## Smart Contract Interaction + + + +Web3js can help us interact with wallets and smart contracts: + +```Typescript +import Web3 from 'web3'; +import { ERC20ABI } from './contracts/ERC20'; + +const USDTAddress = '0xdac17f958d2ee523a2206206994597c13d831ec7'; + +function Components() { + const { isConnected } = useWeb3ModalAccount() + const { walletProvider } = useWeb3ModalProvider() + const [USDTBalance, setUSDTBalance] = useState(0); + const [smartContractName, setSmartContractName] = useState(''); + + async function getContractInfo() { + if (!isConnected) throw Error('not connected'); + const web3 = new Web3({ + provider: walletProvider, + config: { defaultNetworkId: chainId }, + }); + const contract = new web3.eth.Contract(ERC20ABI, USDTAddress); + const balance = await contract.methods.balanceOf(address).call(); + const name = (await contract.methods.name().call()) as string; + setUSDTBalance(Number(balance)); + setSmartContractName(name); + } + + return <>

Balance: {USDTBalance} smartContractName: {smartContractName}

+} + +``` + +:::info +- To learn how to set up Web3modal with vue, click [here](/guides/web3_modal_guide/vue). +::: \ No newline at end of file diff --git a/docs/docs/guides/web3_modal_guide/vue.md b/docs/docs/guides/web3_modal_guide/vue.md new file mode 100644 index 00000000000..a113d519197 --- /dev/null +++ b/docs/docs/guides/web3_modal_guide/vue.md @@ -0,0 +1,122 @@ +--- +sidebar_position: 1 +sidebar_label: 'Web3Modal with Vue' +--- + +# Web3Modal with Vue and web3js + +## Live code editor + + + + + +## Installation + +For this guide we will be creating a new project will need to install dependancies. We will be using vite to locally host the app, React and web3modal-web3js + +```bash +npm install web3modal-web3js react react-dom +npm install --save-dev vite @vitejs/plugin-react +``` + +## Implementation + +Within the root of the project create `index.html` +```html + + + + + + React Web3 example + + +
+ + + +``` + +Now we will add the Web3modal code within `src/Web3modal.tsx` +```typescript + +import { createWeb3Modal, defaultConfig } from 'web3modal-web3/react' + +// 1. Get projectId, Your Project ID can be obtained from walletconnect.com +const projectId = 'YOUR_PROJECT_ID' + +// 2. Set chains +const mainnet = { + chainId: 1, + name: 'Ethereum', + currency: 'ETH', + explorerUrl: 'https://etherscan.io', + rpcUrl: 'https://cloudflare-eth.com' +} + +// 3. Create a metadata object +const metadata = { + name: 'My Website', + description: 'My Website description', + url: 'https://mywebsite.com', // origin must match your domain & subdomain + icons: ['https://avatars.mywebsite.com/'] +} + +// 4. Create web3 config +const web3Config = defaultConfig({ + /*Required*/ + metadata, + + /*Optional*/ + enableEIP6963: true, // true by default + enableInjected: true, // true by default + enableCoinbase: true, // true by default + rpcUrl: '...', // used for the Coinbase SDK + defaultChainId: 1, // used for the Coinbase SDK +}) + +// 5. Create a Web3Modal instance +createWeb3Modal({ + ethersConfig, + chains: [mainnet], + projectId, + enableAnalytics: true // Optional - defaults to your Cloud configuration +}) + +export default function App() { + return +} +``` + +Set up vite configs within root `vite.config.js` +```javascript +import react from '@vitejs/plugin-react' +import { defineConfig } from 'vite' + +export default defineConfig({ + plugins: [react()] +}) +``` + +And finally add react to the app `src/main.tsx` +```typescript +import React from 'react' +import ReactDOM from 'react-dom/client' +import App from './App.js' + +ReactDOM.createRoot(document.getElementById('app')!).render( + + + +) +``` + +You are finished and have successfully created Web3modal with Vue! + +:::info +- For additional information take a look into the interactive code editor above. +- You can view different examples of setting up walletconnect with web3.js [here](https://github.com/ChainSafe/web3modal/tree/add-examples/examples/vue-web3) +- Learn more about Web3modal [here](https://docs.walletconnect.com/web3modal/about) +::: + From 32b6b296fffc7084f7688a136c6a0eaf6e369012 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 21 May 2024 09:10:57 -0400 Subject: [PATCH 24/32] add gas conditional if simple transaction (#7043) * add gas conditional if simple transaction * update * format and add changelog * format * format * add test * fix test --- packages/web3-eth/CHANGELOG.md | 4 ++++ packages/web3-eth/src/utils/send_tx_helper.ts | 9 +++++++- .../web3-eth/test/unit/send_tx_helper.test.ts | 23 +++++++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/packages/web3-eth/CHANGELOG.md b/packages/web3-eth/CHANGELOG.md index 5fb80eef663..9d9b67b29ca 100644 --- a/packages/web3-eth/CHANGELOG.md +++ b/packages/web3-eth/CHANGELOG.md @@ -242,3 +242,7 @@ Documentation: ### Changed - Added parameter `customTransactionReceiptSchema` into methods `emitConfirmation`, `waitForTransactionReceipt`, `watchTransactionByPolling`, `watchTransactionBySubscription`, `watchTransactionForConfirmations` (#7000) + +### Fixed + +- Fixed issue with simple transactions, Within `checkRevertBeforeSending` if there is no data set in transaction, set gas to be `21000` (#7043) \ No newline at end of file diff --git a/packages/web3-eth/src/utils/send_tx_helper.ts b/packages/web3-eth/src/utils/send_tx_helper.ts index 282e778e519..0037e1051fa 100644 --- a/packages/web3-eth/src/utils/send_tx_helper.ts +++ b/packages/web3-eth/src/utils/send_tx_helper.ts @@ -122,7 +122,14 @@ export class SendTxHelper< public async checkRevertBeforeSending(tx: TransactionCall) { if (this.options.checkRevertBeforeSending !== false) { - const reason = await getRevertReason(this.web3Context, tx, this.options.contractAbi); + let formatTx = tx; + if (isNullish(tx.data) && isNullish(tx.input) && isNullish(tx.gas)) { // eth.call runs into error if data isnt filled and gas is not defined, its a simple transaction so we fill it with 21000 + formatTx = { + ...tx, + gas: 21000 + } + } + const reason = await getRevertReason(this.web3Context, formatTx, this.options.contractAbi); if (reason !== undefined) { throw await getTransactionError( this.web3Context, diff --git a/packages/web3-eth/test/unit/send_tx_helper.test.ts b/packages/web3-eth/test/unit/send_tx_helper.test.ts index 55a482395b8..6b40496f5a6 100644 --- a/packages/web3-eth/test/unit/send_tx_helper.test.ts +++ b/packages/web3-eth/test/unit/send_tx_helper.test.ts @@ -21,6 +21,7 @@ import { JsonRpcResponse, TransactionReceipt, Web3BaseWalletAccount, + TransactionCall } from 'web3-types'; import { Web3Context, Web3EventMap, Web3PromiEvent } from 'web3-core'; import { @@ -151,6 +152,28 @@ describe('sendTxHelper class', () => { expect(f).toHaveBeenCalledWith(error); promiEvent.off('error', f); }); + + it('add gas to simple transaction in checkRevertBeforeSending', async () => { + const _sendTxHelper = new SendTxHelper({ + web3Context, + promiEvent: promiEvent as PromiEvent, + options: { + checkRevertBeforeSending: true, + }, + returnFormat: DEFAULT_RETURN_FORMAT, + }); + + const tx = {from:"0x"} as TransactionCall + + await _sendTxHelper.checkRevertBeforeSending(tx); + + const expectedTx = { + ...tx, + gas: 21000, + }; + expect(utils.getRevertReason).toHaveBeenCalledWith(web3Context, expectedTx, undefined); + + }); it('emit handleError with handleRevert', async () => { const error = new ContractExecutionError({ code: 1, message: 'error' }); web3Context.handleRevert = true; From 553f270e49c35b68adec64454db8d32a03646de7 Mon Sep 17 00:00:00 2001 From: Adam Gordon <3723289+gordon-to@users.noreply.github.com> Date: Tue, 21 May 2024 22:25:09 +0200 Subject: [PATCH 25/32] fix(#7044): toWei trim strings with more than 20 decimal places (#7045) * fix(#7044): fix too many decimals passed to toWei * add test case * add tests and fix fromWei * add changelog and update tests * update test --------- Co-authored-by: Alex Luu --- packages/web3-utils/CHANGELOG.md | 3 +- packages/web3-utils/src/converters.ts | 41 ++++++++++--------- .../web3-utils/test/fixtures/converters.ts | 14 ++++++- 3 files changed, 35 insertions(+), 23 deletions(-) diff --git a/packages/web3-utils/CHANGELOG.md b/packages/web3-utils/CHANGELOG.md index d0f162613d8..2310e93c49e 100644 --- a/packages/web3-utils/CHANGELOG.md +++ b/packages/web3-utils/CHANGELOG.md @@ -224,4 +224,5 @@ Documentation: ### Fixed -- `toWei` support numbers in scientific notation (#6908) \ No newline at end of file +- `toWei` support numbers in scientific notation (#6908) +- `toWei` and `fromWei` trims according to ether unit successfuly (#7044) \ No newline at end of file diff --git a/packages/web3-utils/src/converters.ts b/packages/web3-utils/src/converters.ts index 55143a4277c..3c5b09ed27f 100644 --- a/packages/web3-utils/src/converters.ts +++ b/packages/web3-utils/src/converters.ts @@ -532,8 +532,9 @@ export const fromWei = (number: Numbers, unit: EtherUnits): string => { if (fraction === '') { return integer; } + const updatedValue = `${integer}.${fraction}`; - return `${integer}.${fraction}`; + return updatedValue.slice(0, integer.length + numberOfZerosInDenomination + 1); }; /** @@ -559,50 +560,50 @@ export const toWei = (number: Numbers, unit: EtherUnits): string => { throw new InvalidUnitError(unit); } let parsedNumber = number; - if (typeof parsedNumber === 'number'){ - if (parsedNumber < 1e-15){ - console.warn(PrecisionLossWarning) + if (typeof parsedNumber === 'number') { + if (parsedNumber < 1e-15) { + console.warn(PrecisionLossWarning); } - if (parsedNumber > 1e+20) { - console.warn(PrecisionLossWarning) + if (parsedNumber > 1e20) { + console.warn(PrecisionLossWarning); - parsedNumber = BigInt(parsedNumber); + parsedNumber = BigInt(parsedNumber); } else { // in case there is a decimal point, we need to convert it to string - parsedNumber = parsedNumber.toLocaleString('fullwide', {useGrouping: false, maximumFractionDigits: 20}) + parsedNumber = parsedNumber.toLocaleString('fullwide', { + useGrouping: false, + maximumFractionDigits: 20, + }); } } - + // if value is decimal e.g. 24.56 extract `integer` and `fraction` part // to avoid `fraction` to be null use `concat` with empty string const [integer, fraction] = String( - typeof parsedNumber === 'string' && !isHexStrict(parsedNumber) ? parsedNumber : toNumber(parsedNumber), + typeof parsedNumber === 'string' && !isHexStrict(parsedNumber) + ? parsedNumber + : toNumber(parsedNumber), ) .split('.') .concat(''); // join the value removing `.` from // 24.56 -> 2456 - + const value = BigInt(`${integer}${fraction}`); // multiply value with denomination // 2456 * 1000000 -> 2456000000 const updatedValue = value * denomination; - // count number of zeros in denomination - const numberOfZerosInDenomination = denomination.toString().length - 1; - - // check which either `fraction` or `denomination` have lower number of zeros - const decimals = Math.min(fraction.length, numberOfZerosInDenomination); - + // check if whole number was passed in + const decimals = fraction.length; if (decimals === 0) { return updatedValue.toString(); } - // Add zeros to make length equal to required decimal points - // If string is larger than decimal points required then remove last zeros - return updatedValue.toString().padStart(decimals, '0').slice(0, -decimals); + // trim the value to remove extra zeros + return updatedValue.toString().slice(0, -decimals); }; /** diff --git a/packages/web3-utils/test/fixtures/converters.ts b/packages/web3-utils/test/fixtures/converters.ts index 91f3a76f738..14dc271015e 100644 --- a/packages/web3-utils/test/fixtures/converters.ts +++ b/packages/web3-utils/test/fixtures/converters.ts @@ -292,12 +292,17 @@ const conversionBaseData: [[Numbers, EtherUnits], string][] = [ [['879123456788877661', 'tether'], '0.000000000000879123456788877661'], ]; -export const fromWeiValidData: [[Numbers, EtherUnits], string][] = [ +export const fromWeiValidData: [[Numbers, EtherUnits], Numbers][] = [ ...conversionBaseData, [['0xff', 'wei'], '255'], [[1e+22, 'ether'], '10000'], [[19999999999999991611392, 'ether'], '19999.999999999991611392'], [[1.9999999999999991611392e+22, 'ether'], '19999.999999999991611392'], + [['1000000', 'ether'], '0.000000000001'], + [['1123456789123456789', 'ether'], '1.123456789123456789'], + [['1123', 'kwei'], '1.123'], + [['1234100' ,'kwei'], '1234.1'], + [['3308685546611893', 'ether'], '0.003308685546611893'] ]; export const toWeiValidData: [[Numbers, EtherUnits], Numbers][] = [ @@ -305,7 +310,12 @@ export const toWeiValidData: [[Numbers, EtherUnits], Numbers][] = [ [['255', 'wei'], '0xFF'], [['100000000000', 'ether'], 0.0000001], [['1000000000', 'ether'], 0.000000001], - [['1000000', 'ether'], 0.000000000001] + [['1000000', 'ether'], 0.000000000001], + [['1123456789123456789', 'ether'], '1.123456789123456789123'], + [['1123', 'kwei'], '1.12345'], + [['1234100' ,'kwei'], '1234.1'], + [['3308685546611893', 'ether'], '0.0033086855466118933'], + [['1123', 'kwei'], 1.12345], ]; From 3904a4644e4e06c7192b5f39be8f7df63d0f7e4a Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 21 May 2024 23:35:35 -0400 Subject: [PATCH 26/32] allow fromwei and toWei to accept numbers as units (#7052) * allow fromwei and toWei to accept numbers as units * add error and testcases --- packages/web3-errors/CHANGELOG.md | 6 ++- packages/web3-errors/src/error_codes.ts | 1 + .../web3-errors/src/errors/utils_errors.ts | 10 +++++ packages/web3-utils/CHANGELOG.md | 3 +- packages/web3-utils/src/converters.ts | 37 ++++++++++++++----- .../web3-utils/test/fixtures/converters.ts | 34 +++++++++++++++-- 6 files changed, 77 insertions(+), 14 deletions(-) diff --git a/packages/web3-errors/CHANGELOG.md b/packages/web3-errors/CHANGELOG.md index 06946bb65df..2acbb60bc4f 100644 --- a/packages/web3-errors/CHANGELOG.md +++ b/packages/web3-errors/CHANGELOG.md @@ -166,4 +166,8 @@ Documentation: - Fixed grammar and spelling in `transactionTimeoutHint` (#6559) -## [Unreleased] \ No newline at end of file +## [Unreleased] + +### Added + +- Added `InvalidIntegerError` error for fromWei and toWei (#7052) \ No newline at end of file diff --git a/packages/web3-errors/src/error_codes.ts b/packages/web3-errors/src/error_codes.ts index 1db99b30ea7..16c95ad81cb 100644 --- a/packages/web3-errors/src/error_codes.ts +++ b/packages/web3-errors/src/error_codes.ts @@ -155,6 +155,7 @@ export const ERR_INVALID_LARGE_VALUE = 1011; export const ERR_INVALID_BLOCK = 1012; export const ERR_INVALID_TYPE_ABI = 1013; export const ERR_INVALID_NIBBLE_WIDTH = 1014; +export const ERR_INVALID_INTEGER = 1015; // Validation error codes export const ERR_VALIDATION = 1100; diff --git a/packages/web3-errors/src/errors/utils_errors.ts b/packages/web3-errors/src/errors/utils_errors.ts index b93ff964f38..ca213958b9a 100644 --- a/packages/web3-errors/src/errors/utils_errors.ts +++ b/packages/web3-errors/src/errors/utils_errors.ts @@ -31,6 +31,7 @@ import { ERR_INVALID_TYPE, ERR_INVALID_TYPE_ABI, ERR_INVALID_UNIT, + ERR_INVALID_INTEGER, ERR_INVALID_UNSIGNED_INTEGER, } from '../error_codes.js'; import { InvalidValueError } from '../web3_error_base.js'; @@ -75,6 +76,15 @@ export class InvalidUnitError extends InvalidValueError { } } +export class InvalidIntegerError extends InvalidValueError { + public code = ERR_INVALID_INTEGER; + + public constructor(value: unknown) { + super(value, 'not a valid unit. Must be a positive integer'); + + } +} + export class HexProcessingError extends InvalidValueError { public code = ERR_INVALID_HEX; diff --git a/packages/web3-utils/CHANGELOG.md b/packages/web3-utils/CHANGELOG.md index 2310e93c49e..763f7f1d462 100644 --- a/packages/web3-utils/CHANGELOG.md +++ b/packages/web3-utils/CHANGELOG.md @@ -221,8 +221,9 @@ Documentation: ### Added - `toWei` add warning when using large numbers or large decimals that may cause precision loss (#6908) +- `toWei` and `fromWei` now supports integers as a unit. (#7053) ### Fixed - `toWei` support numbers in scientific notation (#6908) -- `toWei` and `fromWei` trims according to ether unit successfuly (#7044) \ No newline at end of file +- `toWei` and `fromWei` trims according to ether unit successfuly (#7044) diff --git a/packages/web3-utils/src/converters.ts b/packages/web3-utils/src/converters.ts index 3c5b09ed27f..f525150187e 100644 --- a/packages/web3-utils/src/converters.ts +++ b/packages/web3-utils/src/converters.ts @@ -41,6 +41,7 @@ import { InvalidBytesError, InvalidNumberError, InvalidUnitError, + InvalidIntegerError, } from 'web3-errors'; import { isUint8Array } from './uint8array.js'; @@ -492,13 +493,22 @@ export const toBigInt = (value: unknown): bigint => { * > 0.000000001 * ``` */ -export const fromWei = (number: Numbers, unit: EtherUnits): string => { - const denomination = ethUnitMap[unit]; +export const fromWei = (number: Numbers, unit: EtherUnits | number): string => { + let denomination; + if (typeof unit === 'string') { + denomination = ethUnitMap[unit]; - if (!denomination) { - throw new InvalidUnitError(unit); + if (!denomination) { + throw new InvalidUnitError(unit); + } + } else { + if (unit < 0 || !Number.isInteger(unit)) { + throw new InvalidIntegerError(unit); + } + denomination = BigInt(10)**BigInt(unit); } + // value in wei would always be integer // 13456789, 1234 const value = String(toNumber(number)); @@ -551,14 +561,23 @@ export const fromWei = (number: Numbers, unit: EtherUnits): string => { * ``` */ // todo in 1.x unit defaults to 'ether' -export const toWei = (number: Numbers, unit: EtherUnits): string => { +export const toWei = (number: Numbers, unit: EtherUnits | number): string => { validator.validate(['number'], [number]); - const denomination = ethUnitMap[unit]; - - if (!denomination) { - throw new InvalidUnitError(unit); + let denomination; + if (typeof unit === 'string') { + denomination = ethUnitMap[unit]; + if (!denomination) { + throw new InvalidUnitError(unit); + } + } else { + if (unit < 0 || !Number.isInteger(unit)) { + throw new InvalidIntegerError(unit); + } + + denomination = BigInt(10)**BigInt(unit); } + let parsedNumber = number; if (typeof parsedNumber === 'number') { if (parsedNumber < 1e-15) { diff --git a/packages/web3-utils/test/fixtures/converters.ts b/packages/web3-utils/test/fixtures/converters.ts index 14dc271015e..9f0324b68ad 100644 --- a/packages/web3-utils/test/fixtures/converters.ts +++ b/packages/web3-utils/test/fixtures/converters.ts @@ -256,7 +256,7 @@ export const toHexInvalidData: [any, string][] = [ [undefined, 'Invalid value given "undefined". Error: can not be converted to hex.'], ]; -const conversionBaseData: [[Numbers, EtherUnits], string][] = [ +const conversionBaseData: [[Numbers, EtherUnits | number], string][] = [ [[0, 'wei'], '0'], [[123, 'wei'], '123'], [['123', 'wei'], '123'], @@ -290,9 +290,35 @@ const conversionBaseData: [[Numbers, EtherUnits], string][] = [ [['178373938391829348', 'ether'], '0.178373938391829348'], [['879123456788877661', 'gwei'], '879123456.788877661'], [['879123456788877661', 'tether'], '0.000000000000879123456788877661'], + [['1', 0], '1'], + [['1', 1], '0.1'], + [['1', 2], '0.01'], + [['1', 3], '0.001'], + [['1', 4], '0.0001'], + [['1', 5], '0.00001'], + [['1', 6], '0.000001'], + [['1', 7], '0.0000001'], + [['1', 8], '0.00000001'], + [['1', 9], '0.000000001'], + [['1', 10], '0.0000000001'], + [[1, 18], '0.000000000000000001'], + [[100, 2], '1'], + [['100', 2], '1'], + [['1000', 3], '1'], + [['10000', 4], '1'], + [['100000', 5], '1'], + [['1000000', 6], '1'], + [['10000000', 7], '1'], + [['100000000', 8], '1'], + [['1000000000', 9], '1'], + [['10000000000', 10], '1'], + [['100000000000', 11], '1'], + [['1000000000000', 12], '1'], + [['10000000000000', 13], '1'], + [['1000000000000000000', 18], '1'], ]; -export const fromWeiValidData: [[Numbers, EtherUnits], Numbers][] = [ +export const fromWeiValidData: [[Numbers, EtherUnits | number], Numbers][] = [ ...conversionBaseData, [['0xff', 'wei'], '255'], [[1e+22, 'ether'], '10000'], @@ -305,7 +331,7 @@ export const fromWeiValidData: [[Numbers, EtherUnits], Numbers][] = [ [['3308685546611893', 'ether'], '0.003308685546611893'] ]; -export const toWeiValidData: [[Numbers, EtherUnits], Numbers][] = [ +export const toWeiValidData: [[Numbers, EtherUnits | number], Numbers][] = [ ...conversionBaseData, [['255', 'wei'], '0xFF'], [['100000000000', 'ether'], 0.0000001], @@ -336,6 +362,8 @@ export const fromWeiInvalidData: [[any, any], string][] = [ [[{}, 'kwei'], 'Invalid value given "{}". Error: can not parse as number data'], [['data', 'kwei'], 'Invalid value given "data". Error: can not parse as number data.'], [['1234', 'uwei'], 'Invalid value given "uwei". Error: invalid unit.'], + [['1234', -1], 'Invalid value given "-1". Error: not a valid unit. Must be a positive integer.'], + [['1234', 3.3], 'Invalid value given "3.3". Error: not a valid unit. Must be a positive integer.'] ]; export const toWeiInvalidData: [[any, any], string][] = [ From ac2e180c3db5e734c40f994edc39382542afc289 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 22 May 2024 11:33:56 -0400 Subject: [PATCH 27/32] update converters (#7054) --- packages/web3-utils/src/converters.ts | 6 +++--- packages/web3-validator/src/validation/numbers.ts | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/web3-utils/src/converters.ts b/packages/web3-utils/src/converters.ts index f525150187e..6649bef1481 100644 --- a/packages/web3-utils/src/converters.ts +++ b/packages/web3-utils/src/converters.ts @@ -32,6 +32,7 @@ import { utils, utils as validatorUtils, validator, + bigintPower, } from 'web3-validator'; import { @@ -505,7 +506,7 @@ export const fromWei = (number: Numbers, unit: EtherUnits | number): string => { if (unit < 0 || !Number.isInteger(unit)) { throw new InvalidIntegerError(unit); } - denomination = BigInt(10)**BigInt(unit); + denomination = bigintPower(BigInt(10),BigInt(unit)); } @@ -575,7 +576,7 @@ export const toWei = (number: Numbers, unit: EtherUnits | number): string => { throw new InvalidIntegerError(unit); } - denomination = BigInt(10)**BigInt(unit); + denomination = bigintPower(BigInt(10),BigInt(unit)); } let parsedNumber = number; @@ -608,7 +609,6 @@ export const toWei = (number: Numbers, unit: EtherUnits | number): string => { // join the value removing `.` from // 24.56 -> 2456 - const value = BigInt(`${integer}${fraction}`); // multiply value with denomination diff --git a/packages/web3-validator/src/validation/numbers.ts b/packages/web3-validator/src/validation/numbers.ts index 276fb84dd1e..bfaa7372148 100644 --- a/packages/web3-validator/src/validation/numbers.ts +++ b/packages/web3-validator/src/validation/numbers.ts @@ -28,6 +28,10 @@ export const isBigInt = (value: ValidInputTypes): boolean => typeof value === 'b // you can find more at: https://github.com/babel/babel/issues/13109 and https://github.com/web3/web3.js/issues/6187 /** @internal */ export const bigintPower = (base: bigint, expo: bigint) => { + // edge case + if (expo === BigInt(0)) { + return BigInt(1); + } let res = base; for (let index = 1; index < expo; index += 1) { res *= base; From e0fc158e7c18ab97b66e415653faad46491823c0 Mon Sep 17 00:00:00 2001 From: Oleksii Kosynskyi Date: Wed, 22 May 2024 11:57:14 -0400 Subject: [PATCH 28/32] Fix format schema with list of objects (#7040) * Fix format schema with list of objects * cover with test --- packages/web3-utils/src/formatter.ts | 239 +++++++++++------- .../web3-utils/test/unit/formatter.test.ts | 109 ++++++++ .../test/unit/promise_helpers.test.ts | 15 +- 3 files changed, 269 insertions(+), 94 deletions(-) diff --git a/packages/web3-utils/src/formatter.ts b/packages/web3-utils/src/formatter.ts index 0a8ca3b723f..42062add5c6 100644 --- a/packages/web3-utils/src/formatter.ts +++ b/packages/web3-utils/src/formatter.ts @@ -145,6 +145,115 @@ export const convertScalarValue = (value: unknown, ethType: string, format: Data return value; }; + +const convertArray = ({ + value, + schemaProp, + schema, + object, + key, + dataPath, + format, + oneOfPath = [], +}: { + value: unknown; + schemaProp: JsonSchema; + schema: JsonSchema; + object: Record; + key: string; + dataPath: string[]; + format: DataFormat; + oneOfPath: [string, number][]; +}) => { + // If value is an array + if (Array.isArray(value)) { + let _schemaProp = schemaProp; + + // TODO This is a naive approach to solving the issue of + // a schema using oneOf. This chunk of code was intended to handle + // BlockSchema.transactions + // TODO BlockSchema.transactions are not being formatted + if (schemaProp?.oneOf !== undefined) { + // The following code is basically saying: + // if the schema specifies oneOf, then we are to loop + // over each possible schema and check if they type of the schema + // matches the type of value[0], and if so we use the oneOfSchemaProp + // as the schema for formatting + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + schemaProp.oneOf.forEach((oneOfSchemaProp: JsonSchema, index: number) => { + if ( + !Array.isArray(schemaProp?.items) && + ((typeof value[0] === 'object' && + (oneOfSchemaProp?.items as JsonSchema)?.type === 'object') || + (typeof value[0] === 'string' && + (oneOfSchemaProp?.items as JsonSchema)?.type !== 'object')) + ) { + _schemaProp = oneOfSchemaProp; + oneOfPath.push([key, index]); + } + }); + } + + if (isNullish(_schemaProp?.items)) { + // Can not find schema for array item, delete that item + // eslint-disable-next-line no-param-reassign + delete object[key]; + dataPath.pop(); + + return true; + } + + // If schema for array items is a single type + if (isObject(_schemaProp.items) && !isNullish(_schemaProp.items.format)) { + for (let i = 0; i < value.length; i += 1) { + // eslint-disable-next-line no-param-reassign + (object[key] as unknown[])[i] = convertScalarValue( + value[i], + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + _schemaProp?.items?.format, + format, + ); + } + + dataPath.pop(); + return true; + } + + // If schema for array items is an object + if (!Array.isArray(_schemaProp?.items) && _schemaProp?.items?.type === 'object') { + for (const arrObject of value) { + // eslint-disable-next-line no-use-before-define + convert( + arrObject as Record | unknown[], + schema, + dataPath, + format, + oneOfPath, + ); + } + + dataPath.pop(); + return true; + } + + // If schema for array is a tuple + if (Array.isArray(_schemaProp?.items)) { + for (let i = 0; i < value.length; i += 1) { + // eslint-disable-next-line no-param-reassign + (object[key] as unknown[])[i] = convertScalarValue( + value[i], + _schemaProp.items[i].format as string, + format, + ); + } + + dataPath.pop(); + return true; + } + } + return false; +}; + /** * Converts the data to the specified format * @param data - data to convert @@ -167,112 +276,62 @@ export const convert = ( } const object = data as Record; + // case when schema is array and `items` is object + if ( + Array.isArray(object) && + schema?.type === 'array' && + (schema?.items as JsonSchema)?.type === 'object' + ) { + convertArray({ + value: object, + schemaProp: schema, + schema, + object, + key: '', + dataPath, + format, + oneOfPath, + }); + } else { + for (const [key, value] of Object.entries(object)) { + dataPath.push(key); + const schemaProp = findSchemaByDataPath(schema, dataPath, oneOfPath); - for (const [key, value] of Object.entries(object)) { - dataPath.push(key); - const schemaProp = findSchemaByDataPath(schema, dataPath, oneOfPath); - - // If value is a scaler value - if (isNullish(schemaProp)) { - delete object[key]; - dataPath.pop(); - - continue; - } - - // If value is an object, recurse into it - if (isObject(value)) { - convert(value, schema, dataPath, format); - dataPath.pop(); - continue; - } - - // If value is an array - if (Array.isArray(value)) { - let _schemaProp = schemaProp; - - // TODO This is a naive approach to solving the issue of - // a schema using oneOf. This chunk of code was intended to handle - // BlockSchema.transactions - // TODO BlockSchema.transactions are not being formatted - if (schemaProp?.oneOf !== undefined) { - // The following code is basically saying: - // if the schema specifies oneOf, then we are to loop - // over each possible schema and check if they type of the schema - // matches the type of value[0], and if so we use the oneOfSchemaProp - // as the schema for formatting - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - schemaProp.oneOf.forEach((oneOfSchemaProp: JsonSchema, index: number) => { - if ( - !Array.isArray(schemaProp?.items) && - ((typeof value[0] === 'object' && - (oneOfSchemaProp?.items as JsonSchema)?.type === 'object') || - (typeof value[0] === 'string' && - (oneOfSchemaProp?.items as JsonSchema)?.type !== 'object')) - ) { - _schemaProp = oneOfSchemaProp; - oneOfPath.push([key, index]); - } - }); - } - - if (isNullish(_schemaProp?.items)) { - // Can not find schema for array item, delete that item + // If value is a scaler value + if (isNullish(schemaProp)) { delete object[key]; dataPath.pop(); continue; } - // If schema for array items is a single type - if (isObject(_schemaProp.items) && !isNullish(_schemaProp.items.format)) { - for (let i = 0; i < value.length; i += 1) { - (object[key] as unknown[])[i] = convertScalarValue( - value[i], - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - _schemaProp?.items?.format, - format, - ); - } - + // If value is an object, recurse into it + if (isObject(value)) { + convert(value, schema, dataPath, format); dataPath.pop(); continue; } - // If schema for array items is an object - if (!Array.isArray(_schemaProp?.items) && _schemaProp?.items?.type === 'object') { - for (const arrObject of value) { - convert( - arrObject as Record | unknown[], - schema, - dataPath, - format, - oneOfPath, - ); - } - - dataPath.pop(); + // If value is an array + if ( + convertArray({ + value, + schemaProp, + schema, + object, + key, + dataPath, + format, + oneOfPath, + }) + ) { continue; } - // If schema for array is a tuple - if (Array.isArray(_schemaProp?.items)) { - for (let i = 0; i < value.length; i += 1) { - (object[key] as unknown[])[i] = convertScalarValue( - value[i], - _schemaProp.items[i].format as string, - format, - ); - } + object[key] = convertScalarValue(value, schemaProp.format as string, format); - dataPath.pop(); - continue; - } + dataPath.pop(); } - - object[key] = convertScalarValue(value, schemaProp.format as string, format); - - dataPath.pop(); } return object; diff --git a/packages/web3-utils/test/unit/formatter.test.ts b/packages/web3-utils/test/unit/formatter.test.ts index b58f5459584..bed8b55de8e 100644 --- a/packages/web3-utils/test/unit/formatter.test.ts +++ b/packages/web3-utils/test/unit/formatter.test.ts @@ -519,6 +519,115 @@ describe('formatter', () => { ).toEqual(result); }); + it('should format array of objects', () => { + const schema = { + type: 'array', + items: { + type: 'object', + properties: { + prop1: { + format: 'uint', + }, + prop2: { + format: 'bytes', + }, + }, + }, + }; + + const data = [ + { prop1: 10, prop2: new Uint8Array(hexToBytes('FF')) }, + { prop1: 10, prop2: new Uint8Array(hexToBytes('FF')) }, + ]; + + const result = [ + { prop1: '0xa', prop2: '0xff' }, + { prop1: '0xa', prop2: '0xff' }, + ]; + + expect( + format(schema, data, { number: FMT_NUMBER.HEX, bytes: FMT_BYTES.HEX }), + ).toEqual(result); + }); + + it('should format array of objects with oneOf', () => { + const schema = { + type: 'array', + items: { + type: 'object', + properties: { + prop1: { + oneOf: [{ format: 'address' }, { type: 'string' }], + }, + prop2: { + format: 'bytes', + }, + }, + }, + }; + + const data = [ + { + prop1: '0x7ed0e85b8e1e925600b4373e6d108f34ab38a401', + prop2: new Uint8Array(hexToBytes('FF')), + }, + { prop1: 'some string', prop2: new Uint8Array(hexToBytes('FF')) }, + ]; + + const result = [ + { prop1: '0x7ed0e85b8e1e925600b4373e6d108f34ab38a401', prop2: '0xff' }, + { prop1: 'some string', prop2: '0xff' }, + ]; + + expect( + format(schema, data, { number: FMT_NUMBER.HEX, bytes: FMT_BYTES.HEX }), + ).toEqual(result); + }); + + it('should format array of different objects', () => { + const schema = { + type: 'array', + items: [ + { + type: 'object', + properties: { + prop1: { + format: 'uint', + }, + prop2: { + format: 'bytes', + }, + }, + }, + { + type: 'object', + properties: { + prop1: { + format: 'string', + }, + prop2: { + format: 'uint', + }, + }, + }, + ], + }; + + const data = [ + { prop1: 10, prop2: new Uint8Array(hexToBytes('FF')) }, + { prop1: 'test', prop2: 123 }, + ]; + + const result = [ + { prop1: 10, prop2: '0xff' }, + { prop1: 'test', prop2: 123 }, + ]; + + expect( + format(schema, data, { number: FMT_NUMBER.NUMBER, bytes: FMT_BYTES.HEX }), + ).toEqual(result); + }); + it('should format array values with object type', () => { const schema = { type: 'object', diff --git a/packages/web3-utils/test/unit/promise_helpers.test.ts b/packages/web3-utils/test/unit/promise_helpers.test.ts index b18f4f1a5b0..7492c51fc24 100644 --- a/packages/web3-utils/test/unit/promise_helpers.test.ts +++ b/packages/web3-utils/test/unit/promise_helpers.test.ts @@ -147,20 +147,26 @@ describe('promise helpers', () => { }); it('should return interval id if not resolved in specific time', async () => { - let counter = 0; + // eslint-disable-next-line @typescript-eslint/require-await const asyncHelper = async () => { if (counter <= 3000000) { counter += 1; return undefined; } - return "result"; + return 'result'; }; const testError = new Error('Test P2 Error'); - const [neverResolvePromise, intervalId] = pollTillDefinedAndReturnIntervalId(asyncHelper, 100); - const promiCheck = Promise.race([neverResolvePromise, rejectIfTimeout(500,testError)[1]]); + const [neverResolvePromise, intervalId] = pollTillDefinedAndReturnIntervalId( + asyncHelper, + 100, + ); + const promiCheck = Promise.race([ + neverResolvePromise, + rejectIfTimeout(500, testError)[1], + ]); await expect(promiCheck).rejects.toThrow(testError); expect(intervalId).toBeDefined(); @@ -188,6 +194,7 @@ describe('promise helpers', () => { it('reject if later throws', async () => { const dummyError = new Error('error'); let counter = 0; + // eslint-disable-next-line @typescript-eslint/require-await const asyncHelper = async () => { if (counter === 0) { counter += 1; From f4e55bd30441b8e69c822d5ff1c6041291fd5a09 Mon Sep 17 00:00:00 2001 From: Oleksii Kosynskyi Date: Wed, 22 May 2024 12:24:50 -0400 Subject: [PATCH 29/32] 6801 Fill gas price when baseFeePerGas==='0x0' (#7050) * Fix gas price filling * fix * fix build * fix lint * add unit test * add unit test * changelog --- CHANGELOG.md | 5 ++ packages/web3-eth/CHANGELOG.md | 3 +- .../src/utils/get_transaction_gas_pricing.ts | 11 ++-- .../utils/get_transaction_gas_pricing.test.ts | 58 +++++++++++++++++++ 4 files changed, 72 insertions(+), 5 deletions(-) create mode 100644 packages/web3-eth/test/unit/utils/get_transaction_gas_pricing.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 21a45b6d806..94a802644cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2483,6 +2483,10 @@ If there are any bugs, improvements, optimizations or any new feature proposal f ### Fixed +#### web3-eth + +- Fixed issue with simple transactions, Within `checkRevertBeforeSending` if there is no data set in transaction, set gas to be `21000` (#7043) + #### web3-utils @@ -2498,6 +2502,7 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3-eth - Added parameter `customTransactionReceiptSchema` into methods `emitConfirmation`, `waitForTransactionReceipt`, `watchTransactionByPolling`, `watchTransactionBySubscription`, `watchTransactionForConfirmations` (#7000) +- Changed functionality: For networks that returns `baseFeePerGas===0x0` fill `maxPriorityFeePerGas` and `maxFeePerGas` by `getGasPrice` method (#7050) #### web3-rpc-methods diff --git a/packages/web3-eth/CHANGELOG.md b/packages/web3-eth/CHANGELOG.md index 9d9b67b29ca..01294d0b449 100644 --- a/packages/web3-eth/CHANGELOG.md +++ b/packages/web3-eth/CHANGELOG.md @@ -242,7 +242,8 @@ Documentation: ### Changed - Added parameter `customTransactionReceiptSchema` into methods `emitConfirmation`, `waitForTransactionReceipt`, `watchTransactionByPolling`, `watchTransactionBySubscription`, `watchTransactionForConfirmations` (#7000) +- Changed functionality: For networks that returns `baseFeePerGas===0x0` fill `maxPriorityFeePerGas` and `maxFeePerGas` by `getGasPrice` method (#7050) ### Fixed -- Fixed issue with simple transactions, Within `checkRevertBeforeSending` if there is no data set in transaction, set gas to be `21000` (#7043) \ No newline at end of file +- Fixed issue with simple transactions, Within `checkRevertBeforeSending` if there is no data set in transaction, set gas to be `21000` (#7043) diff --git a/packages/web3-eth/src/utils/get_transaction_gas_pricing.ts b/packages/web3-eth/src/utils/get_transaction_gas_pricing.ts index e5bbcdedfd4..95e0a3c411f 100644 --- a/packages/web3-eth/src/utils/get_transaction_gas_pricing.ts +++ b/packages/web3-eth/src/utils/get_transaction_gas_pricing.ts @@ -38,14 +38,17 @@ async function getEip1559GasPricing( web3Context: Web3Context, returnFormat: ReturnFormat, ): Promise> { - const block = await getBlock(web3Context, web3Context.defaultBlock, false, returnFormat); - + const block = await getBlock(web3Context, web3Context.defaultBlock, false, ETH_DATA_FORMAT); if (isNullish(block.baseFeePerGas)) throw new Eip1559NotSupportedError(); - if (!isNullish(transaction.gasPrice)) { + let gasPrice: Numbers | undefined; + if (isNullish(transaction.gasPrice) && BigInt(block.baseFeePerGas) === BigInt(0)) { + gasPrice = await getGasPrice(web3Context, returnFormat); + } + if (!isNullish(transaction.gasPrice) || !isNullish(gasPrice)) { const convertedTransactionGasPrice = format( { format: 'uint' }, - transaction.gasPrice as Numbers, + transaction.gasPrice ?? gasPrice, returnFormat, ); diff --git a/packages/web3-eth/test/unit/utils/get_transaction_gas_pricing.test.ts b/packages/web3-eth/test/unit/utils/get_transaction_gas_pricing.test.ts new file mode 100644 index 00000000000..30d3e5beaf9 --- /dev/null +++ b/packages/web3-eth/test/unit/utils/get_transaction_gas_pricing.test.ts @@ -0,0 +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 { Web3Context } from 'web3-core'; + +import { FMT_BYTES, FMT_NUMBER } from 'web3-types'; +import * as RpcMethodWrappers from '../../../src/rpc_method_wrappers'; +import { getTransactionGasPricing } from '../../../src/utils/get_transaction_gas_pricing'; + +describe('getTransactionGasPricing', () => { + const web3Context = new Web3Context(); + + it('should use the call rpc wrapper', async () => { + const gasPrice = '0x123456'; + const gasPriceSpy = jest + .spyOn(RpcMethodWrappers, 'getGasPrice') + .mockImplementation(async () => gasPrice); + const getBlockSpy = jest + .spyOn(RpcMethodWrappers, 'getBlock') + // @ts-expect-error only for testing purposes + .mockImplementation(async () => ({ + baseFeePerGas: '0x0', + })); + + const transaction = { + from: '0x4fec0a51024b13030d26e70904b066c6d41157a5', + to: '0x36361143b7e2c676f8ccd67743a89d26437f0529', + data: '0x819f48fe', + type: '0x2', + }; + + const res = await getTransactionGasPricing(transaction, web3Context, { + number: FMT_NUMBER.HEX, + bytes: FMT_BYTES.HEX, + }); + + expect(getBlockSpy).toHaveBeenCalled(); + expect(gasPriceSpy).toHaveBeenCalled(); + expect(res).toEqual({ + gasPrice: undefined, + maxPriorityFeePerGas: gasPrice, + maxFeePerGas: gasPrice, + }); + }); +}); From 5db7f8c4be72a09f206bb011a3a528c2d4a2ecb3 Mon Sep 17 00:00:00 2001 From: Alex Luu Date: Wed, 22 May 2024 13:58:38 -0400 Subject: [PATCH 30/32] update changelog and bump versions --- CHANGELOG.md | 18 ++++++++++++++++++ packages/web3-core/CHANGELOG.md | 3 +++ packages/web3-core/package.json | 12 ++++++------ packages/web3-errors/package.json | 4 ++-- packages/web3-eth-abi/CHANGELOG.md | 6 +++++- packages/web3-eth-abi/package.json | 10 +++++----- packages/web3-eth-contract/package.json | 16 ++++++++-------- packages/web3-eth-ens/CHANGELOG.md | 1 + packages/web3-eth-ens/package.json | 18 +++++++++--------- packages/web3-eth/package.json | 18 +++++++++--------- packages/web3-net/CHANGELOG.md | 1 + packages/web3-net/package.json | 10 +++++----- packages/web3-rpc-methods/package.json | 8 ++++---- packages/web3-types/package.json | 2 +- packages/web3-utils/package.json | 8 ++++---- packages/web3-validator/CHANGELOG.md | 2 +- packages/web3-validator/package.json | 6 +++--- packages/web3/package.json | 24 ++++++++++++------------ packages/web3/src/version.ts | 2 +- 19 files changed, 98 insertions(+), 71 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 94a802644cc..9802e056d4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2456,6 +2456,10 @@ If there are any bugs, improvements, optimizations or any new feature proposal f - `defaultReturnFormat` was added to the configuration options. (#6947) +#### web3-errors + +- Added `InvalidIntegerError` error for fromWei and toWei (#7052) + #### web3-eth - `defaultReturnFormat` was added to all methods that have `ReturnType` param. (#6947) @@ -2480,6 +2484,8 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3-utils +- `toWei` add warning when using large numbers or large decimals that may cause precision loss (#6908) +- `toWei` and `fromWei` now supports integers as a unit. (#7053) ### Fixed @@ -2489,9 +2495,17 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3-utils +- `toWei` support numbers in scientific notation (#6908) +- `toWei` and `fromWei` trims according to ether unit successfuly (#7044) #### web3-validator +- The JSON schema conversion process now correctly assigns an id when the `abi.name` is not available, for example, in the case of public mappings. (#6981) +- `browser` entry point that was pointing to an non-existing bundle file was removed from `package.json` (#7015) + +#### web3-core + +- Set a try catch block if processesingError fails (#7022) ### Changed @@ -2504,6 +2518,10 @@ If there are any bugs, improvements, optimizations or any new feature proposal f - Added parameter `customTransactionReceiptSchema` into methods `emitConfirmation`, `waitForTransactionReceipt`, `watchTransactionByPolling`, `watchTransactionBySubscription`, `watchTransactionForConfirmations` (#7000) - Changed functionality: For networks that returns `baseFeePerGas===0x0` fill `maxPriorityFeePerGas` and `maxFeePerGas` by `getGasPrice` method (#7050) +#### web3-eth-abi + +- Dependencies updated + #### web3-rpc-methods - Change `estimateGas` method to add possibility pass Transaction type (#7000) diff --git a/packages/web3-core/CHANGELOG.md b/packages/web3-core/CHANGELOG.md index d69e71c8cf9..0696715231e 100644 --- a/packages/web3-core/CHANGELOG.md +++ b/packages/web3-core/CHANGELOG.md @@ -217,3 +217,6 @@ Documentation: - Interface `RequestManagerMiddleware` was changed (#7003) +### Fixed + +- Set a try catch block if processesingError fails (#7022) \ No newline at end of file diff --git a/packages/web3-core/package.json b/packages/web3-core/package.json index 04fcb06f509..ea5ba28ec63 100644 --- a/packages/web3-core/package.json +++ b/packages/web3-core/package.json @@ -1,6 +1,6 @@ { "name": "web3-core", - "version": "4.3.2", + "version": "4.4.0", "description": "Web3 core tools for sub-packages. This is an internal package.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -42,14 +42,14 @@ "test:integration": "jest --config=./test/integration/jest.config.js --passWithNoTests" }, "dependencies": { - "web3-errors": "^1.1.4", + "web3-errors": "^1.2.0", + "web3-eth-accounts": "^4.1.2", "web3-eth-iban": "^4.0.7", - "web3-eth-accounts": "^4.1.0", "web3-providers-http": "^4.1.0", "web3-providers-ws": "^4.0.7", - "web3-types": "^1.3.1", - "web3-utils": "^4.1.0", - "web3-validator": "^2.0.3" + "web3-types": "^1.7.0", + "web3-utils": "^4.3.0", + "web3-validator": "^2.0.6" }, "optionalDependencies": { "web3-providers-ipc": "^4.0.7" diff --git a/packages/web3-errors/package.json b/packages/web3-errors/package.json index 08a2b5ebb7f..133035f0001 100644 --- a/packages/web3-errors/package.json +++ b/packages/web3-errors/package.json @@ -1,6 +1,6 @@ { "name": "web3-errors", - "version": "1.1.4", + "version": "1.2.0", "description": "This package has web3 error classes", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -41,7 +41,7 @@ "test:integration": "jest --config=./test/integration/jest.config.js --passWithNoTests" }, "dependencies": { - "web3-types": "^1.3.1" + "web3-types": "^1.7.0" }, "devDependencies": { "@types/jest": "^28.1.6", diff --git a/packages/web3-eth-abi/CHANGELOG.md b/packages/web3-eth-abi/CHANGELOG.md index 47f57f4d2a4..c8d36938003 100644 --- a/packages/web3-eth-abi/CHANGELOG.md +++ b/packages/web3-eth-abi/CHANGELOG.md @@ -170,4 +170,8 @@ Documentation: - Dependencies updated -## [Unreleased] \ No newline at end of file +## [Unreleased] + +### Changed + +- Dependencies updated \ No newline at end of file diff --git a/packages/web3-eth-abi/package.json b/packages/web3-eth-abi/package.json index 1ed38b13f05..68ea63612b5 100644 --- a/packages/web3-eth-abi/package.json +++ b/packages/web3-eth-abi/package.json @@ -1,6 +1,6 @@ { "name": "web3-eth-abi", - "version": "4.2.1", + "version": "4.3.0", "description": "Web3 module encode and decode EVM in/output.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -43,10 +43,10 @@ }, "dependencies": { "abitype": "0.7.1", - "web3-errors": "^1.1.4", - "web3-types": "^1.6.0", - "web3-utils": "^4.2.3", - "web3-validator": "^2.0.5" + "web3-errors": "^1.2.0", + "web3-types": "^1.7.0", + "web3-utils": "^4.3.0", + "web3-validator": "^2.0.6" }, "devDependencies": { "@humeris/espresso-shot": "^4.0.0", diff --git a/packages/web3-eth-contract/package.json b/packages/web3-eth-contract/package.json index 0c8cd166675..a3406060551 100644 --- a/packages/web3-eth-contract/package.json +++ b/packages/web3-eth-contract/package.json @@ -1,6 +1,6 @@ { "name": "web3-eth-contract", - "version": "4.4.0", + "version": "4.5.0", "description": "Web3 module to interact with Ethereum smart contracts.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -45,13 +45,13 @@ "test:e2e:firefox": "npx cypress run --headless --browser firefox --env grep='ignore',invert=true" }, "dependencies": { - "web3-core": "^4.3.2", - "web3-errors": "^1.1.4", - "web3-eth": "^4.6.0", - "web3-eth-abi": "^4.2.1", - "web3-types": "^1.6.0", - "web3-utils": "^4.2.3", - "web3-validator": "^2.0.5" + "web3-core": "^4.4.0", + "web3-errors": "^1.2.0", + "web3-eth": "^4.7.0", + "web3-eth-abi": "^4.3.0", + "web3-types": "^1.7.0", + "web3-utils": "^4.3.0", + "web3-validator": "^2.0.6" }, "devDependencies": { "@humeris/espresso-shot": "^4.0.0", diff --git a/packages/web3-eth-ens/CHANGELOG.md b/packages/web3-eth-ens/CHANGELOG.md index c40b2727d5e..55a2c8ef7bb 100644 --- a/packages/web3-eth-ens/CHANGELOG.md +++ b/packages/web3-eth-ens/CHANGELOG.md @@ -156,4 +156,5 @@ Documentation: ## [Unreleased] ### Added + - `defaultReturnFormat` was added to all methods that have `ReturnType` param. (#6947) diff --git a/packages/web3-eth-ens/package.json b/packages/web3-eth-ens/package.json index db7fc9d2d03..6888071ab85 100644 --- a/packages/web3-eth-ens/package.json +++ b/packages/web3-eth-ens/package.json @@ -1,6 +1,6 @@ { "name": "web3-eth-ens", - "version": "4.2.0", + "version": "4.3.0", "description": "This package has ENS functions for interacting with Ethereum Name Service.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -59,13 +59,13 @@ }, "dependencies": { "@adraffy/ens-normalize": "^1.8.8", - "web3-core": "^4.3.2", - "web3-errors": "^1.1.4", - "web3-eth": "^4.5.0", - "web3-eth-contract": "^4.3.0", - "web3-net": "^4.0.7", - "web3-types": "^1.5.0", - "web3-utils": "^4.2.2", - "web3-validator": "^2.0.5" + "web3-core": "^4.4.0", + "web3-errors": "^1.2.0", + "web3-eth": "^4.7.0", + "web3-eth-contract": "^4.5.0", + "web3-net": "^4.1.0", + "web3-types": "^1.7.0", + "web3-utils": "^4.3.0", + "web3-validator": "^2.0.6" } } diff --git a/packages/web3-eth/package.json b/packages/web3-eth/package.json index 767f5697387..a283d932680 100644 --- a/packages/web3-eth/package.json +++ b/packages/web3-eth/package.json @@ -1,6 +1,6 @@ { "name": "web3-eth", - "version": "4.6.0", + "version": "4.7.0", "description": "Web3 module to interact with the Ethereum blockchain and smart contracts.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -63,15 +63,15 @@ }, "dependencies": { "setimmediate": "^1.0.5", - "web3-core": "^4.3.2", - "web3-errors": "^1.1.4", - "web3-eth-abi": "^4.2.1", + "web3-core": "^4.4.0", + "web3-errors": "^1.2.0", + "web3-eth-abi": "^4.3.0", "web3-eth-accounts": "^4.1.2", - "web3-net": "^4.0.7", + "web3-net": "^4.1.0", "web3-providers-ws": "^4.0.7", - "web3-rpc-methods": "^1.2.0", - "web3-types": "^1.6.0", - "web3-utils": "^4.2.3", - "web3-validator": "^2.0.5" + "web3-rpc-methods": "^1.3.0", + "web3-types": "^1.7.0", + "web3-utils": "^4.3.0", + "web3-validator": "^2.0.6" } } diff --git a/packages/web3-net/CHANGELOG.md b/packages/web3-net/CHANGELOG.md index d60abde6313..0c87dc01017 100644 --- a/packages/web3-net/CHANGELOG.md +++ b/packages/web3-net/CHANGELOG.md @@ -144,4 +144,5 @@ Documentation: ## [Unreleased] ### Added + - `defaultReturnFormat` was added to all methods that have `ReturnType` param. (#6947) diff --git a/packages/web3-net/package.json b/packages/web3-net/package.json index d3ca4f5a32b..d4668b4f155 100644 --- a/packages/web3-net/package.json +++ b/packages/web3-net/package.json @@ -1,6 +1,6 @@ { "name": "web3-net", - "version": "4.0.7", + "version": "4.1.0", "description": "Web3 module to interact with the Ethereum nodes networking properties.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -56,9 +56,9 @@ "typescript": "^4.7.4" }, "dependencies": { - "web3-core": "^4.3.0", - "web3-rpc-methods": "^1.1.3", - "web3-types": "^1.3.0", - "web3-utils": "^4.0.7" + "web3-core": "^4.4.0", + "web3-rpc-methods": "^1.3.0", + "web3-types": "^1.7.0", + "web3-utils": "^4.3.0" } } diff --git a/packages/web3-rpc-methods/package.json b/packages/web3-rpc-methods/package.json index 8e9eec0e597..8f088f5fb90 100644 --- a/packages/web3-rpc-methods/package.json +++ b/packages/web3-rpc-methods/package.json @@ -1,6 +1,6 @@ { "name": "web3-rpc-methods", - "version": "1.2.0", + "version": "1.3.0", "description": "Ethereum RPC methods for Web3 4.x.x", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -56,8 +56,8 @@ "typescript": "^4.7.4" }, "dependencies": { - "web3-core": "^4.3.2", - "web3-types": "^1.5.0", - "web3-validator": "^2.0.4" + "web3-core": "^4.4.0", + "web3-types": "^1.7.0", + "web3-validator": "^2.0.6" } } diff --git a/packages/web3-types/package.json b/packages/web3-types/package.json index 8cec2cee0b0..b2e7d7b3ff7 100644 --- a/packages/web3-types/package.json +++ b/packages/web3-types/package.json @@ -1,6 +1,6 @@ { "name": "web3-types", - "version": "1.6.0", + "version": "1.7.0", "description": "Provide the common data structures and interfaces for web3 modules.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", diff --git a/packages/web3-utils/package.json b/packages/web3-utils/package.json index 511ce216fc2..b2c3de0ec3d 100644 --- a/packages/web3-utils/package.json +++ b/packages/web3-utils/package.json @@ -1,7 +1,7 @@ { "name": "web3-utils", "sideEffects": false, - "version": "4.2.3", + "version": "4.3.0", "description": "Collection of utility functions used in web3.js.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -65,8 +65,8 @@ "dependencies": { "ethereum-cryptography": "^2.0.0", "eventemitter3": "^5.0.1", - "web3-errors": "^1.1.4", - "web3-types": "^1.6.0", - "web3-validator": "^2.0.5" + "web3-errors": "^1.2.0", + "web3-types": "^1.7.0", + "web3-validator": "^2.0.6" } } diff --git a/packages/web3-validator/CHANGELOG.md b/packages/web3-validator/CHANGELOG.md index ea8cd0259ff..df246eff017 100644 --- a/packages/web3-validator/CHANGELOG.md +++ b/packages/web3-validator/CHANGELOG.md @@ -172,5 +172,5 @@ Documentation: ### Fixed -- The JSON schema conversion process now correctly assigns an id when the `abi.name` is not available, for example, in the case of public mappings. +- The JSON schema conversion process now correctly assigns an id when the `abi.name` is not available, for example, in the case of public mappings. (#6981) - `browser` entry point that was pointing to an non-existing bundle file was removed from `package.json` (#7015) diff --git a/packages/web3-validator/package.json b/packages/web3-validator/package.json index c416a1fa235..c8ff59d6b16 100644 --- a/packages/web3-validator/package.json +++ b/packages/web3-validator/package.json @@ -1,6 +1,6 @@ { "name": "web3-validator", - "version": "2.0.5", + "version": "2.0.6", "description": "JSON-Schema compatible validator for web3", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -46,8 +46,8 @@ "dependencies": { "ethereum-cryptography": "^2.0.0", "util": "^0.12.5", - "web3-errors": "^1.1.4", - "web3-types": "^1.5.0", + "web3-errors": "^1.2.0", + "web3-types": "^1.7.0", "zod": "^3.21.4" }, "devDependencies": { diff --git a/packages/web3/package.json b/packages/web3/package.json index 52bb78ce8c8..67693b25e24 100644 --- a/packages/web3/package.json +++ b/packages/web3/package.json @@ -1,6 +1,6 @@ { "name": "web3", - "version": "4.8.0", + "version": "4.9.0", "description": "Ethereum JavaScript API", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -86,21 +86,21 @@ "web3-providers-ipc": "^4.0.7" }, "dependencies": { - "web3-core": "^4.3.2", - "web3-errors": "^1.1.4", - "web3-eth": "^4.6.0", - "web3-eth-abi": "^4.2.1", + "web3-core": "^4.4.0", + "web3-errors": "^1.2.0", + "web3-eth": "^4.7.0", + "web3-eth-abi": "^4.3.0", "web3-eth-accounts": "^4.1.2", - "web3-eth-contract": "^4.4.0", - "web3-eth-ens": "^4.2.0", + "web3-eth-contract": "^4.5.0", + "web3-eth-ens": "^4.3.0", "web3-eth-iban": "^4.0.7", "web3-eth-personal": "^4.0.8", - "web3-net": "^4.0.7", + "web3-net": "^4.1.0", "web3-providers-http": "^4.1.0", "web3-providers-ws": "^4.0.7", - "web3-rpc-methods": "^1.2.0", - "web3-types": "^1.6.0", - "web3-utils": "^4.2.3", - "web3-validator": "^2.0.5" + "web3-rpc-methods": "^1.3.0", + "web3-types": "^1.7.0", + "web3-utils": "^4.3.0", + "web3-validator": "^2.0.6" } } diff --git a/packages/web3/src/version.ts b/packages/web3/src/version.ts index 8e4910766d8..4ab9622dba7 100644 --- a/packages/web3/src/version.ts +++ b/packages/web3/src/version.ts @@ -1 +1 @@ -/* eslint-disable header/header */ export const Web3PkgInfo = { version: '4.8.0' }; +/* eslint-disable header/header */ export const Web3PkgInfo = { version: '4.9.0' }; From acf91ede5b2d5dbeb85f8e5134506c8454808657 Mon Sep 17 00:00:00 2001 From: Alex Luu Date: Wed, 22 May 2024 14:30:29 -0400 Subject: [PATCH 31/32] update changelog and revert version bump web3-types --- CHANGELOG.md | 4 +++- packages/web3-core/CHANGELOG.md | 6 ++++-- packages/web3-core/package.json | 2 +- packages/web3-errors/CHANGELOG.md | 6 ++++-- packages/web3-errors/package.json | 2 +- packages/web3-eth-abi/CHANGELOG.md | 6 ++++-- packages/web3-eth-abi/package.json | 2 +- packages/web3-eth-contract/CHANGELOG.md | 4 +++- packages/web3-eth-contract/package.json | 2 +- packages/web3-eth-ens/CHANGELOG.md | 4 +++- packages/web3-eth-ens/package.json | 2 +- packages/web3-eth/CHANGELOG.md | 4 +++- packages/web3-eth/package.json | 2 +- packages/web3-net/CHANGELOG.md | 4 +++- packages/web3-net/package.json | 2 +- packages/web3-rpc-methods/CHANGELOG.md | 4 +++- packages/web3-rpc-methods/package.json | 2 +- packages/web3-types/CHANGELOG.md | 2 +- packages/web3-types/package.json | 2 +- packages/web3-utils/CHANGELOG.md | 4 +++- packages/web3-utils/package.json | 2 +- packages/web3-validator/CHANGELOG.md | 4 +++- packages/web3-validator/package.json | 2 +- packages/web3/CHANGELOG.md | 4 +++- packages/web3/package.json | 2 +- 25 files changed, 52 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9802e056d4f..b756bba2604 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2444,7 +2444,7 @@ If there are any bugs, improvements, optimizations or any new feature proposal f - Added `signature` to type `AbiFunctionFragment` (#6922) - update type `Withdrawals`, `block` and `BlockHeaderOutput` to include properties of eip 4844, 4895, 4788 (#6933) -## [Unreleased] +## [4.9.0] ### Added @@ -2525,3 +2525,5 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3-rpc-methods - Change `estimateGas` method to add possibility pass Transaction type (#7000) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-core/CHANGELOG.md b/packages/web3-core/CHANGELOG.md index 0696715231e..0346e3f74a9 100644 --- a/packages/web3-core/CHANGELOG.md +++ b/packages/web3-core/CHANGELOG.md @@ -207,7 +207,7 @@ Documentation: - Web3config `contractDataInputFill` has been defaulted to `data`, istead of `input`. (#6622) -## [Unreleased] +## [4.4.0] ### Added @@ -219,4 +219,6 @@ Documentation: ### Fixed -- Set a try catch block if processesingError fails (#7022) \ No newline at end of file +- Set a try catch block if processesingError fails (#7022) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-core/package.json b/packages/web3-core/package.json index ea5ba28ec63..865aafd0db6 100644 --- a/packages/web3-core/package.json +++ b/packages/web3-core/package.json @@ -47,7 +47,7 @@ "web3-eth-iban": "^4.0.7", "web3-providers-http": "^4.1.0", "web3-providers-ws": "^4.0.7", - "web3-types": "^1.7.0", + "web3-types": "^1.6.0", "web3-utils": "^4.3.0", "web3-validator": "^2.0.6" }, diff --git a/packages/web3-errors/CHANGELOG.md b/packages/web3-errors/CHANGELOG.md index 2acbb60bc4f..7f9b132283b 100644 --- a/packages/web3-errors/CHANGELOG.md +++ b/packages/web3-errors/CHANGELOG.md @@ -166,8 +166,10 @@ Documentation: - Fixed grammar and spelling in `transactionTimeoutHint` (#6559) -## [Unreleased] +## [1.2.0] ### Added -- Added `InvalidIntegerError` error for fromWei and toWei (#7052) \ No newline at end of file +- Added `InvalidIntegerError` error for fromWei and toWei (#7052) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-errors/package.json b/packages/web3-errors/package.json index 133035f0001..1b8587c81b3 100644 --- a/packages/web3-errors/package.json +++ b/packages/web3-errors/package.json @@ -41,7 +41,7 @@ "test:integration": "jest --config=./test/integration/jest.config.js --passWithNoTests" }, "dependencies": { - "web3-types": "^1.7.0" + "web3-types": "^1.6.0" }, "devDependencies": { "@types/jest": "^28.1.6", diff --git a/packages/web3-eth-abi/CHANGELOG.md b/packages/web3-eth-abi/CHANGELOG.md index c8d36938003..760c4426b7a 100644 --- a/packages/web3-eth-abi/CHANGELOG.md +++ b/packages/web3-eth-abi/CHANGELOG.md @@ -170,8 +170,10 @@ Documentation: - Dependencies updated -## [Unreleased] +## [4.3.0] ### Changed -- Dependencies updated \ No newline at end of file +- Dependencies updated + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-eth-abi/package.json b/packages/web3-eth-abi/package.json index 68ea63612b5..1ef2ca32b23 100644 --- a/packages/web3-eth-abi/package.json +++ b/packages/web3-eth-abi/package.json @@ -44,7 +44,7 @@ "dependencies": { "abitype": "0.7.1", "web3-errors": "^1.2.0", - "web3-types": "^1.7.0", + "web3-types": "^1.6.0", "web3-utils": "^4.3.0", "web3-validator": "^2.0.6" }, diff --git a/packages/web3-eth-contract/CHANGELOG.md b/packages/web3-eth-contract/CHANGELOG.md index 8aa7c126ebb..8e275470925 100644 --- a/packages/web3-eth-contract/CHANGELOG.md +++ b/packages/web3-eth-contract/CHANGELOG.md @@ -380,8 +380,10 @@ Documentation: - Added a console warning in case of an ambiguous call to a solidity method with parameter overloading (#6942) - Added contract.deploy(...).decodeData(...) and contract.decodeMethodData(...) that decode data based on the ABI (#6950) -## [Unreleased] +## [4.5.0] ### Added - `defaultReturnFormat` was added to all methods that have `ReturnType` param. (#6947) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-eth-contract/package.json b/packages/web3-eth-contract/package.json index a3406060551..d7bb7f0dc69 100644 --- a/packages/web3-eth-contract/package.json +++ b/packages/web3-eth-contract/package.json @@ -49,7 +49,7 @@ "web3-errors": "^1.2.0", "web3-eth": "^4.7.0", "web3-eth-abi": "^4.3.0", - "web3-types": "^1.7.0", + "web3-types": "^1.6.0", "web3-utils": "^4.3.0", "web3-validator": "^2.0.6" }, diff --git a/packages/web3-eth-ens/CHANGELOG.md b/packages/web3-eth-ens/CHANGELOG.md index 55a2c8ef7bb..c9be2f93561 100644 --- a/packages/web3-eth-ens/CHANGELOG.md +++ b/packages/web3-eth-ens/CHANGELOG.md @@ -153,8 +153,10 @@ Documentation: - Added function getText and getName in ENS and resolver classes (#6914) -## [Unreleased] +## [4.3.0] ### Added - `defaultReturnFormat` was added to all methods that have `ReturnType` param. (#6947) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-eth-ens/package.json b/packages/web3-eth-ens/package.json index 6888071ab85..4c1865ca983 100644 --- a/packages/web3-eth-ens/package.json +++ b/packages/web3-eth-ens/package.json @@ -64,7 +64,7 @@ "web3-eth": "^4.7.0", "web3-eth-contract": "^4.5.0", "web3-net": "^4.1.0", - "web3-types": "^1.7.0", + "web3-types": "^1.6.0", "web3-utils": "^4.3.0", "web3-validator": "^2.0.6" } diff --git a/packages/web3-eth/CHANGELOG.md b/packages/web3-eth/CHANGELOG.md index 01294d0b449..3d2d36b17c0 100644 --- a/packages/web3-eth/CHANGELOG.md +++ b/packages/web3-eth/CHANGELOG.md @@ -232,7 +232,7 @@ Documentation: - method `getBlock` now includes properties of eip 4844, 4895, 4788 when returning block (#6933) - update type `withdrawalsSchema`, `blockSchema` and `blockHeaderSchema` schemas to include properties of eip 4844, 4895, 4788 (#6933) -## [Unreleased] +## [4.7.0] ### Added @@ -247,3 +247,5 @@ Documentation: ### Fixed - 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 diff --git a/packages/web3-eth/package.json b/packages/web3-eth/package.json index a283d932680..4cdfd0d65fa 100644 --- a/packages/web3-eth/package.json +++ b/packages/web3-eth/package.json @@ -70,7 +70,7 @@ "web3-net": "^4.1.0", "web3-providers-ws": "^4.0.7", "web3-rpc-methods": "^1.3.0", - "web3-types": "^1.7.0", + "web3-types": "^1.6.0", "web3-utils": "^4.3.0", "web3-validator": "^2.0.6" } diff --git a/packages/web3-net/CHANGELOG.md b/packages/web3-net/CHANGELOG.md index 0c87dc01017..5e7ea9073b3 100644 --- a/packages/web3-net/CHANGELOG.md +++ b/packages/web3-net/CHANGELOG.md @@ -141,8 +141,10 @@ Documentation: - Dependencies updated -## [Unreleased] +## [4.1.0] ### Added - `defaultReturnFormat` was added to all methods that have `ReturnType` param. (#6947) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-net/package.json b/packages/web3-net/package.json index d4668b4f155..952457f72be 100644 --- a/packages/web3-net/package.json +++ b/packages/web3-net/package.json @@ -58,7 +58,7 @@ "dependencies": { "web3-core": "^4.4.0", "web3-rpc-methods": "^1.3.0", - "web3-types": "^1.7.0", + "web3-types": "^1.6.0", "web3-utils": "^4.3.0" } } diff --git a/packages/web3-rpc-methods/CHANGELOG.md b/packages/web3-rpc-methods/CHANGELOG.md index c57997c5ddc..050b6451539 100644 --- a/packages/web3-rpc-methods/CHANGELOG.md +++ b/packages/web3-rpc-methods/CHANGELOG.md @@ -138,8 +138,10 @@ Documentation: - Added `getMaxPriorityFeePerGas` method (#6748) -## [Unreleased] +## [1.3.0] ### Changed - Change `estimateGas` method to add possibility pass Transaction type (#7000) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-rpc-methods/package.json b/packages/web3-rpc-methods/package.json index 8f088f5fb90..3a05060f2c2 100644 --- a/packages/web3-rpc-methods/package.json +++ b/packages/web3-rpc-methods/package.json @@ -57,7 +57,7 @@ }, "dependencies": { "web3-core": "^4.4.0", - "web3-types": "^1.7.0", + "web3-types": "^1.6.0", "web3-validator": "^2.0.6" } } diff --git a/packages/web3-types/CHANGELOG.md b/packages/web3-types/CHANGELOG.md index 3f96fe9d53d..638d9616377 100644 --- a/packages/web3-types/CHANGELOG.md +++ b/packages/web3-types/CHANGELOG.md @@ -189,7 +189,7 @@ Documentation: - Type `FeeData` to be filled by `await web3.eth.calculateFeeData()` to be used with EIP-1559 transactions (#6795) -## [Unreleased] +## [1.6.0] ### Added diff --git a/packages/web3-types/package.json b/packages/web3-types/package.json index b2e7d7b3ff7..8cec2cee0b0 100644 --- a/packages/web3-types/package.json +++ b/packages/web3-types/package.json @@ -1,6 +1,6 @@ { "name": "web3-types", - "version": "1.7.0", + "version": "1.6.0", "description": "Provide the common data structures and interfaces for web3 modules.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", diff --git a/packages/web3-utils/CHANGELOG.md b/packages/web3-utils/CHANGELOG.md index 763f7f1d462..5fcf44ccec5 100644 --- a/packages/web3-utils/CHANGELOG.md +++ b/packages/web3-utils/CHANGELOG.md @@ -216,7 +216,7 @@ Documentation: - fixed toHex incorrectly hexing Uint8Arrays and Buffer (#6957) - fixed isUint8Array not returning true for Buffer (#6957) -## [Unreleased] +## [4.3.0] ### Added @@ -227,3 +227,5 @@ Documentation: - `toWei` support numbers in scientific notation (#6908) - `toWei` and `fromWei` trims according to ether unit successfuly (#7044) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-utils/package.json b/packages/web3-utils/package.json index b2c3de0ec3d..c07e9b85821 100644 --- a/packages/web3-utils/package.json +++ b/packages/web3-utils/package.json @@ -66,7 +66,7 @@ "ethereum-cryptography": "^2.0.0", "eventemitter3": "^5.0.1", "web3-errors": "^1.2.0", - "web3-types": "^1.7.0", + "web3-types": "^1.6.0", "web3-validator": "^2.0.6" } } diff --git a/packages/web3-validator/CHANGELOG.md b/packages/web3-validator/CHANGELOG.md index df246eff017..da4cc2c0136 100644 --- a/packages/web3-validator/CHANGELOG.md +++ b/packages/web3-validator/CHANGELOG.md @@ -168,9 +168,11 @@ Documentation: - Multi-dimensional arrays(with a fix length) are now handled properly when parsing ABIs (#6798) -## [Unreleased] +## [2.0.6] ### Fixed - The JSON schema conversion process now correctly assigns an id when the `abi.name` is not available, for example, in the case of public mappings. (#6981) - `browser` entry point that was pointing to an non-existing bundle file was removed from `package.json` (#7015) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-validator/package.json b/packages/web3-validator/package.json index c8ff59d6b16..4a12b604981 100644 --- a/packages/web3-validator/package.json +++ b/packages/web3-validator/package.json @@ -47,7 +47,7 @@ "ethereum-cryptography": "^2.0.0", "util": "^0.12.5", "web3-errors": "^1.2.0", - "web3-types": "^1.7.0", + "web3-types": "^1.6.0", "zod": "^3.21.4" }, "devDependencies": { diff --git a/packages/web3/CHANGELOG.md b/packages/web3/CHANGELOG.md index 15fca59a531..896d0d884f0 100644 --- a/packages/web3/CHANGELOG.md +++ b/packages/web3/CHANGELOG.md @@ -262,8 +262,10 @@ Documentation: - Added `signature` to type `AbiFunctionFragment` (#6922) - update type `Withdrawals`, `block` and `BlockHeaderOutput` to include properties of eip 4844, 4895, 4788 (#6933) -## [Unreleased] +## [4.9.0] ### Added - Updated type `Web3EthInterface.accounts` to includes `privateKeyToAccount`,`privateKeyToAddress`,and `privateKeyToPublicKey` (#6762) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3/package.json b/packages/web3/package.json index 67693b25e24..ee3162c797c 100644 --- a/packages/web3/package.json +++ b/packages/web3/package.json @@ -99,7 +99,7 @@ "web3-providers-http": "^4.1.0", "web3-providers-ws": "^4.0.7", "web3-rpc-methods": "^1.3.0", - "web3-types": "^1.7.0", + "web3-types": "^1.6.0", "web3-utils": "^4.3.0", "web3-validator": "^2.0.6" } From 506799287d70f866a5ff65df611a8be7161fae51 Mon Sep 17 00:00:00 2001 From: Alex Luu Date: Thu, 23 May 2024 09:16:49 -0400 Subject: [PATCH 32/32] change web3-eth-abi package version --- packages/web3-eth-abi/CHANGELOG.md | 2 +- packages/web3-eth-abi/package.json | 2 +- packages/web3-eth-contract/package.json | 2 +- packages/web3-eth/package.json | 2 +- packages/web3/package.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/web3-eth-abi/CHANGELOG.md b/packages/web3-eth-abi/CHANGELOG.md index 760c4426b7a..4a7f1fe8add 100644 --- a/packages/web3-eth-abi/CHANGELOG.md +++ b/packages/web3-eth-abi/CHANGELOG.md @@ -170,7 +170,7 @@ Documentation: - Dependencies updated -## [4.3.0] +## [4.2.2] ### Changed diff --git a/packages/web3-eth-abi/package.json b/packages/web3-eth-abi/package.json index 1ef2ca32b23..4333ba616bb 100644 --- a/packages/web3-eth-abi/package.json +++ b/packages/web3-eth-abi/package.json @@ -1,6 +1,6 @@ { "name": "web3-eth-abi", - "version": "4.3.0", + "version": "4.2.2", "description": "Web3 module encode and decode EVM in/output.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", diff --git a/packages/web3-eth-contract/package.json b/packages/web3-eth-contract/package.json index d7bb7f0dc69..74edee8f90b 100644 --- a/packages/web3-eth-contract/package.json +++ b/packages/web3-eth-contract/package.json @@ -48,7 +48,7 @@ "web3-core": "^4.4.0", "web3-errors": "^1.2.0", "web3-eth": "^4.7.0", - "web3-eth-abi": "^4.3.0", + "web3-eth-abi": "^4.2.2", "web3-types": "^1.6.0", "web3-utils": "^4.3.0", "web3-validator": "^2.0.6" diff --git a/packages/web3-eth/package.json b/packages/web3-eth/package.json index 4cdfd0d65fa..47c188743b2 100644 --- a/packages/web3-eth/package.json +++ b/packages/web3-eth/package.json @@ -65,7 +65,7 @@ "setimmediate": "^1.0.5", "web3-core": "^4.4.0", "web3-errors": "^1.2.0", - "web3-eth-abi": "^4.3.0", + "web3-eth-abi": "^4.2.2", "web3-eth-accounts": "^4.1.2", "web3-net": "^4.1.0", "web3-providers-ws": "^4.0.7", diff --git a/packages/web3/package.json b/packages/web3/package.json index ee3162c797c..668d77e26ff 100644 --- a/packages/web3/package.json +++ b/packages/web3/package.json @@ -89,7 +89,7 @@ "web3-core": "^4.4.0", "web3-errors": "^1.2.0", "web3-eth": "^4.7.0", - "web3-eth-abi": "^4.3.0", + "web3-eth-abi": "^4.2.2", "web3-eth-accounts": "^4.1.2", "web3-eth-contract": "^4.5.0", "web3-eth-ens": "^4.3.0",