From 6da73791549ac6d84f343a21a565af20cca55858 Mon Sep 17 00:00:00 2001 From: Oleksii Kosynskyi Date: Fri, 9 Feb 2024 07:36:22 -0500 Subject: [PATCH 001/186] fix yml (#6803) --- .github/workflows/deploy-docs.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy-docs.yaml b/.github/workflows/deploy-docs.yaml index 90fc811671f..ce0ee35cee2 100644 --- a/.github/workflows/deploy-docs.yaml +++ b/.github/workflows/deploy-docs.yaml @@ -1,9 +1,11 @@ name: Docs CloudFlare Deploy on: push: + branches: - "4.x" - tags-ignore: + tags-ignore: - v4* + jobs: deploy: runs-on: ubuntu-latest From d8b64a831defaf52a302002ce6e6051f32edaaaf Mon Sep 17 00:00:00 2001 From: Santiago Trujillo Zuluaga Date: Fri, 9 Feb 2024 16:10:34 +0000 Subject: [PATCH 002/186] Update issue templates (#6800) * Update issue templates * deleted old issue template --- .../issue-template.md} | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) rename .github/{ISSUE_TEMPLATE.md => ISSUE_TEMPLATE/issue-template.md} (72%) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE/issue-template.md similarity index 72% rename from .github/ISSUE_TEMPLATE.md rename to .github/ISSUE_TEMPLATE/issue-template.md index 5b5131e57e2..e9fb9bed99a 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE/issue-template.md @@ -1,3 +1,12 @@ +--- +name: Issue template +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + \ No newline at end of file + From 9d65c38506e405bc029a0e9f0bbd9b3f51d1ef7b Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 12 Feb 2024 08:57:26 -0500 Subject: [PATCH 003/186] Release/4.5.0 (#6802) * update changelog and package.json for release * update script * update changelog * update --- CHANGELOG.md | 18 ++++++++++++++++++ packages/web3-types/CHANGELOG.md | 6 ++++-- packages/web3-types/package.json | 2 +- packages/web3-utils/CHANGELOG.md | 6 ++++-- packages/web3-utils/package.json | 4 ++-- packages/web3/CHANGELOG.md | 4 ++++ packages/web3/package.json | 6 +++--- packages/web3/scripts/black_box_test.sh | 2 +- packages/web3/src/version.ts | 2 +- 9 files changed, 38 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 84176cbefbd..c8cef1e3891 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2335,4 +2335,22 @@ If there are any bugs, improvements, optimizations or any new feature proposal f - Fixed an issue with detecting Uint8Array (#6486) +## [4.5.0] + +### Added + +#### web3-utils + +- Adds missing exported type `AbiItem` from 1.x to v4 for compatabiltiy (#6678) + +#### web3-types + +- Adds missing exported type `AbiItem` from 1.x to v4 for compatabiltiy (#6678) + +### Changed + +#### web3 + +- Dependencies updated + ## [Unreleased] \ No newline at end of file diff --git a/packages/web3-types/CHANGELOG.md b/packages/web3-types/CHANGELOG.md index 2dedcbca907..6de6b636988 100644 --- a/packages/web3-types/CHANGELOG.md +++ b/packages/web3-types/CHANGELOG.md @@ -177,8 +177,10 @@ Documentation: - Interface `MetaMaskProvider` added and is part of `SupportedProviders` (#6534) - `gasPrice` was added to `Transaction1559UnsignedAPI` type. (#6539) -## [Unreleased] +## [1.4.0] ### Added -- Adds missing exported type `AbiItem` from 1.x to v4 for compatabiltiy (#6678) \ No newline at end of file +- Adds missing exported type `AbiItem` from 1.x to v4 for compatabiltiy (#6678) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-types/package.json b/packages/web3-types/package.json index 60756c8dd6b..1f5067ecf87 100644 --- a/packages/web3-types/package.json +++ b/packages/web3-types/package.json @@ -1,6 +1,6 @@ { "name": "web3-types", - "version": "1.3.1", + "version": "1.4.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 1204a73951c..477b9031953 100644 --- a/packages/web3-utils/CHANGELOG.md +++ b/packages/web3-utils/CHANGELOG.md @@ -187,8 +187,10 @@ Documentation: - Fixed an issue with detecting Uint8Array (#6486) -## [Unreleased] +## [4.2.0] ### Added -- Adds missing exported type `AbiItem` from 1.x to v4 for compatabiltiy (#6678) \ No newline at end of file +- Adds missing exported type `AbiItem` from 1.x to v4 for compatabiltiy (#6678) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-utils/package.json b/packages/web3-utils/package.json index 8eacfae6e20..8d5a9296086 100644 --- a/packages/web3-utils/package.json +++ b/packages/web3-utils/package.json @@ -1,7 +1,7 @@ { "name": "web3-utils", "sideEffects": false, - "version": "4.1.1", + "version": "4.2.0", "description": "Collection of utility functions used in web3.js.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -65,7 +65,7 @@ "dependencies": { "ethereum-cryptography": "^2.0.0", "web3-errors": "^1.1.4", - "web3-types": "^1.3.1", + "web3-types": "^1.4.0", "web3-validator": "^2.0.4" } } diff --git a/packages/web3/CHANGELOG.md b/packages/web3/CHANGELOG.md index 5d0b4323625..a9f200cb149 100644 --- a/packages/web3/CHANGELOG.md +++ b/packages/web3/CHANGELOG.md @@ -187,4 +187,8 @@ Documentation: - Dependencies updated ( details are in root changelog ) +## [4.5.0] + +- Dependencies updated ( details are in root changelog ) + ## [Unreleased] \ No newline at end of file diff --git a/packages/web3/package.json b/packages/web3/package.json index dc32d9a2dd2..c72180f8eb2 100644 --- a/packages/web3/package.json +++ b/packages/web3/package.json @@ -1,6 +1,6 @@ { "name": "web3", - "version": "4.4.0", + "version": "4.5.0", "description": "Ethereum JavaScript API", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -99,8 +99,8 @@ "web3-providers-http": "^4.1.0", "web3-providers-ws": "^4.0.7", "web3-rpc-methods": "^1.1.4", - "web3-types": "^1.3.1", - "web3-utils": "^4.1.1", + "web3-types": "^1.4.0", + "web3-utils": "^4.2.0", "web3-validator": "^2.0.4" } } diff --git a/packages/web3/scripts/black_box_test.sh b/packages/web3/scripts/black_box_test.sh index 3b571867064..508f2bd76de 100755 --- a/packages/web3/scripts/black_box_test.sh +++ b/packages/web3/scripts/black_box_test.sh @@ -13,7 +13,7 @@ BACKEND=${ORIGARGS[0]} MODE=${ORIGARGS[1]} PROVIDER_URL=${ORIGARGS[2]} -SUPPORTED_BACKENDS=("geth" "infura", "hardhat") +SUPPORTED_BACKENDS=("geth" "infura" "hardhat") SUPPORTED_MODE=("http" "ws") if [[ ! " ${SUPPORTED_BACKENDS[*]} " =~ " ${BACKEND} " ]]; then diff --git a/packages/web3/src/version.ts b/packages/web3/src/version.ts index fde2e8e160c..21594d54456 100644 --- a/packages/web3/src/version.ts +++ b/packages/web3/src/version.ts @@ -1 +1 @@ -/* eslint-disable header/header */ export const Web3PkgInfo = { version: '4.4.0' }; +/* eslint-disable header/header */ export const Web3PkgInfo = { version: '4.5.0' }; From a0d4d2ea10f2269f61f364e1d5451d44b738c2b9 Mon Sep 17 00:00:00 2001 From: Muhammad Altabba <24407834+Muhammad-Altabba@users.noreply.github.com> Date: Mon, 12 Feb 2024 15:22:55 +0100 Subject: [PATCH 004/186] Resolve test snapshot issue between node 18 vs 20 & 21 (#6794) * resolve snapshot issue between node 18 vs 20 & 21 * update a comment --------- Co-authored-by: Alex --- .../__snapshots__/web3_context.test.ts.snap | 6 ++++-- .../web3-core/test/unit/web3_context.test.ts | 20 +++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) 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 b9f0d4f0c95..b832a1f8200 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 @@ -40,7 +40,7 @@ exports[`Web3Context getContextObject should return correct context object 1`] = }, "registeredSubscriptions": {}, "requestManager": Web3RequestManager { - "_emitter": EventEmitter { + "_emitter": { "_events": { "BEFORE_PROVIDER_CHANGE": [Function], "PROVIDER_CHANGED": [Function], @@ -48,6 +48,7 @@ exports[`Web3Context getContextObject should return correct context object 1`] = "_eventsCount": 2, "_maxListeners": undefined, Symbol(kCapture): false, + Symbol(shapeMode): false, }, "_provider": HttpProvider { "clientUrl": "http://test/abc", @@ -59,7 +60,7 @@ exports[`Web3Context getContextObject should return correct context object 1`] = "_subscriptions": Map {}, "registeredSubscriptions": {}, "requestManager": Web3RequestManager { - "_emitter": EventEmitter { + "_emitter": { "_events": { "BEFORE_PROVIDER_CHANGE": [Function], "PROVIDER_CHANGED": [Function], @@ -67,6 +68,7 @@ exports[`Web3Context getContextObject should return correct context object 1`] = "_eventsCount": 2, "_maxListeners": undefined, Symbol(kCapture): false, + Symbol(shapeMode): false, }, "_provider": HttpProvider { "clientUrl": "http://test/abc", diff --git a/packages/web3-core/test/unit/web3_context.test.ts b/packages/web3-core/test/unit/web3_context.test.ts index 1bedd82ba5b..3c433f7259a 100644 --- a/packages/web3-core/test/unit/web3_context.test.ts +++ b/packages/web3-core/test/unit/web3_context.test.ts @@ -69,6 +69,26 @@ describe('Web3Context', () => { it('should return correct context object', () => { const context = new Context1('http://test/abc'); + // The following is because a specific property is different in node 18 than it is in node 20 and 21 + // So the problematic property is removed from the object and then added to ensure its presence and its location + // And the snapshot is updated to reflect the change. + // Once node 18 is no longer supported, this can be removed. And the snapshot need to be updated then. + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const symbolForShapeMode = Object.getOwnPropertySymbols( + (context.getContextObject().requestManager as any)._emitter, + ).find(s => s.description === 'shapeMode'); + if (symbolForShapeMode) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + delete (context.getContextObject().requestManager as any)._emitter[symbolForShapeMode]; + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (context.getContextObject().requestManager as any)._emitter = { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ...(context.getContextObject().requestManager as any)._emitter, + [Symbol.for('shapeMode')]: false, + }; + expect(context.getContextObject()).toMatchSnapshot(); }); }); From 90235115610d4ab28c8959eb0ad0757f0aaee081 Mon Sep 17 00:00:00 2001 From: Deepak <83352186+Deepak2030@users.noreply.github.com> Date: Mon, 12 Feb 2024 22:00:26 +0530 Subject: [PATCH 005/186] Updated README.md (#6804) * Updated README.md Added the general features of web3.js in the npm package * Put the features on top * Update packages/web3/README.md Co-authored-by: Junaid <86780488+jdevcs@users.noreply.github.com> --------- Co-authored-by: Santiago Trujillo Zuluaga Co-authored-by: Junaid <86780488+jdevcs@users.noreply.github.com> --- packages/web3/README.md | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/packages/web3/README.md b/packages/web3/README.md index bec916e563d..53a0d16c806 100644 --- a/packages/web3/README.md +++ b/packages/web3/README.md @@ -9,9 +9,24 @@ [![NPM Package][npm-image]][npm-url] [![Downloads][downloads-image]][npm-url] -This is the main package of [web3.js](repo). - -`web3` contains the ideal setup for a Web3.js package. +This is the main package of [web3.js](repo), it contains a collection of comprehensive [TypeScript](https://www.typescriptlang.org/) libraries for Interaction with the [Ethereum JSON RPC API](https://ethereum.org/developers/docs/apis/json-rpc) and utility functions. + +## Features + +- **Web3.js Plugins](https://docs.web3js.org/guides/web3_plugin_guide/)**: Enhance or add any functionality by creating scalable web3 plugins for any project. +- **Abstractions over the [JSON-RPC API](https://ethereum.org/en/developers/docs/apis/json-rpc)**: Simplifying interaction for your Developer Experience. +- **Language aligned to the official [Ethereum terminology](https://ethereum.org/en/glossary** +- **Tree-shaking focus**: Include only what you need during bundling for optimized performance. +- **Dynamic contract types and full API in TypeScript**: Enforced with strict types for enhanced security and safety. +- **Complete utilities and functionalities for all your Ethereum needs** +- **More efficient ABI Encoder & Decoder** +- **Extensive [documentation](https://docs.web3js.org/) with guides and APIs** +- **Large collection of test cases** +- **First-class APIs for interacting with [Smart Contracts](https://ethereum.org/en/glossary#smart-contract** +- **ESM and CJS module builds**: Support for both ECMAScript module and CommonJS module builds for flexible integration with various project setups. +- **Contracts dynamic types](https://docs.web3js.org/guides/smart_contracts/infer_contract_types/) & full API in TypeScript** +- **Using native BigInt instead of large BigNumber libraries**: Use native BigInt for improved efficiency compared to using large external BigNumber libraries. +- **Custom Output formatters**: Format any returned value to be a string, number, BigInt, etc., providing flexibility in handling output data. ## Installation From e774646b32c2c090e6ba0886e43e27feba3e865e Mon Sep 17 00:00:00 2001 From: Muhammad Altabba <24407834+Muhammad-Altabba@users.noreply.github.com> Date: Wed, 14 Feb 2024 10:42:54 +0100 Subject: [PATCH 006/186] feat: Add getMaxPriorityFeePerGas method (#6748) * add getMaxPriorityFeePerGas method * update CHANGELOG.md files * add integration test * add a unit test --------- Co-authored-by: Alex --- packages/web3-eth/CHANGELOG.md | 4 + packages/web3-eth/src/rpc_method_wrappers.ts | 12 + packages/web3-eth/src/web3_eth.ts | 305 +++++++++--------- .../web3_eth/send_transaction.test.ts | 117 ++++--- .../web3_eth_methods_no_parameters.test.ts | 5 + packages/web3-rpc-methods/CHANGELOG.md | 3 + .../web3-rpc-methods/src/eth_rpc_methods.ts | 7 + .../get_maxPriorityFeePerGas.ts | 52 +++ .../web3-types/src/apis/eth_execution_api.ts | 6 +- 9 files changed, 304 insertions(+), 207 deletions(-) create mode 100644 packages/web3-rpc-methods/test/unit/eth_rpc_methods/get_maxPriorityFeePerGas.ts diff --git a/packages/web3-eth/CHANGELOG.md b/packages/web3-eth/CHANGELOG.md index 021eb321d59..f1ab3d6b532 100644 --- a/packages/web3-eth/CHANGELOG.md +++ b/packages/web3-eth/CHANGELOG.md @@ -220,3 +220,7 @@ Documentation: - Catch `TransactionPollingTimeoutError` was added to send transaction events (#6623) ## [Unreleased] + +### Added + +- Added `eth.getMaxPriorityFeePerGas` method (#6748) diff --git a/packages/web3-eth/src/rpc_method_wrappers.ts b/packages/web3-eth/src/rpc_method_wrappers.ts index 4dd01805603..1a2cac1ffd8 100644 --- a/packages/web3-eth/src/rpc_method_wrappers.ts +++ b/packages/web3-eth/src/rpc_method_wrappers.ts @@ -138,6 +138,18 @@ export async function getGasPrice( return format({ format: 'uint' }, response as Numbers, returnFormat); } +/** + * View additional documentations here: {@link Web3Eth.getMaxPriorityFeePerGas} + * @param web3Context ({@link Web3Context}) Web3 configuration object that contains things such as the provider, request manager, wallet, etc. + */ +export async function getMaxPriorityFeePerGas( + web3Context: Web3Context, + returnFormat: ReturnFormat, +) { + const response = await ethRpcMethods.getMaxPriorityFeePerGas(web3Context.requestManager); + + return format({ format: 'uint' }, response as Numbers, returnFormat); +} /** * View additional documentations here: {@link Web3Eth.getBlockNumber} * @param web3Context ({@link Web3Context}) Web3 configuration object that contains things such as the provider, request manager, wallet, etc. diff --git a/packages/web3-eth/src/web3_eth.ts b/packages/web3-eth/src/web3_eth.ts index 42ca62e7b54..05fa88926d5 100644 --- a/packages/web3-eth/src/web3_eth.ts +++ b/packages/web3-eth/src/web3_eth.ts @@ -238,6 +238,24 @@ export class Web3Eth extends Web3Context 20000000000n + * + * web3.eth.getMaxPriorityFeePerGas({ number: FMT_NUMBER.HEX , bytes: FMT_BYTES.HEX }).then(console.log); + * > "0x4a817c800" + * ``` + */ + public async getMaxPriorityFeePerGas< + ReturnFormat extends DataFormat = typeof DEFAULT_RETURN_FORMAT, + >(returnFormat: ReturnFormat = DEFAULT_RETURN_FORMAT as ReturnFormat) { + return rpcMethodsWrappers.getMaxPriorityFeePerGas(this, returnFormat); + } + /** * @returns A list of accounts the node controls (addresses are checksummed). * @@ -326,13 +344,7 @@ export class Web3Eth extends Web3Context 1 * ``` */ - public async getTransactionCount< - ReturnFormat extends DataFormat = typeof DEFAULT_RETURN_FORMAT, - >( + public async getTransactionCount( address: Address, blockNumber: BlockNumberOrTag = this.defaultBlock, returnFormat: ReturnFormat = DEFAULT_RETURN_FORMAT as ReturnFormat, @@ -1579,137 +1580,137 @@ export class Web3Eth extends Web3Context console.log(data)); - * logSubscription.on('error', (error: any) => console.log(error)); - * - * ``` - * - * @example **Subscribe to new block headers** - * ```ts - * // Subscribe to `newBlockHeaders` - * const newBlocksSubscription = await web3.eth.subscribe('newBlockHeaders'); - * - * newBlocksSubscription.on('data', async blockhead => { - * console.log('New block header: ', blockhead); - * - * // You do not need the next line, if you like to keep notified for every new block - * await newBlocksSubscription.unsubscribe(); - * console.log('Unsubscribed from new block headers.'); - * }); - * newBlocksSubscription.on('error', error => - * console.log('Error when subscribing to New block header: ', error), - * ); - * ``` - * - * ### subscribe('pendingTransactions') - * - * Subscribes to incoming pending transactions. - * You can subscribe to pending transactions by calling web3.eth.subscribe('pendingTransactions'). - * - * ```ts - * (await web3.eth.subscribe('pendingTransactions')).on('data', console.log); - * ``` - * - * ### subscribe('newHeads') - * ( same as subscribe('newBlockHeaders')) - * Subscribes to incoming block headers. This can be used as timer to check for changes on the blockchain. - * - * The structure of a returned block header is {@link BlockHeaderOutput}: - * - * ```ts - * (await web3.eth.subscribe('newHeads')).on( // 'newBlockHeaders' would work as well - * 'data', - * console.log - * ); - * >{ - * parentHash: '0x9e746a1d906b299def98c75b06f714d62dacadd567c7515d76eeaa8c8074c738', - * sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347', - * miner: '0x0000000000000000000000000000000000000000', - * stateRoot: '0xe0f04b04861ecfa95e82a9310d6a7ef7aef8d7417f5209c182582bfb98a8e307', - * transactionsRoot: '0x31ab4ea571a9e10d3a19aaed07d190595b1dfa34e03960c04293fec565dea536', - * logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - * difficulty: 2n, - * number: 21n, - * gasLimit: 11738125n, - * gasUsed: 830006n, - * timestamp: 1678797237n, - * extraData: '0xd883010b02846765746888676f312e32302e31856c696e757800000000000000e0a6e93cf40e2e71a72e493272210c3f43738ccc7e7d7b14ffd51833797d896c09117e8dc4fbcbc969bd21b42e5af3e276a911524038c001b2109b63b8e0352601', - * nonce: 0n - * } - * ``` - * - * ### subscribe('syncing') - * Subscribe to syncing events. This will return `true` when the node is syncing and when it’s finished syncing will return `false`, for the `changed` event. - * - * ```ts - * (await web3.eth.subscribe('syncing')).on('changed', console.log); - * > `true` // when syncing - * - * (await web3.eth.subscribe('syncing')).on('data', console.log); - * > { - * startingBlock: 0, - * currentBlock: 0, - * highestBlock: 0, - * pulledStates: 0, - * knownStates: 0 - * } - * ``` - * - * ### subscribe('logs', options) - * Subscribes to incoming logs, filtered by the given options. If a valid numerical fromBlock options property is set, web3.js will retrieve logs beginning from this point, backfilling the response as necessary. - * - * options: You can subscribe to logs matching a given filter object, which can take the following parameters: - * - `fromBlock`: (optional, default: 'latest') Integer block number, or `'latest'` for the last mined block or `'pending'`, `'earliest'` for not yet mined transactions. - * - `address`: (optional) Contract address or a list of addresses from which logs should originate. - * - `topics`: (optional) Array of 32 Bytes DATA topics. Topics are order-dependent. Each topic can also be an array of DATA with `or` options. - * - * ```ts - * (await web3.eth.subscribe('logs', { - * address: '0xdac17f958d2ee523a2206206994597c13d831ec7', - * })).on('data', console.log); - * - * > { - * removed: false, - * logIndex: 119n, - * transactionIndex: 58n, - * transactionHash: '0x61533efa77937360215069d5d6cb0be09a22af9721e6dc3df59d957833ed8870', - * blockHash: '0xe32bb97084479d32247f66f8b46d00af2fbc3c2db2bc6e5843fe2e4d1ca9b099', - * blockNumber: 18771966n, - * address: '0xdac17f958d2ee523a2206206994597c13d831ec7', - * data: '0x00000000000000000000000000000000000000000000000000000000d88b2e40', - * topics: [ - * '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', - * '0x0000000000000000000000002fb2457f6ec1865dc0d4e7300c696b69c2a1b989', - * '0x00000000000000000000000027fd43babfbe83a81d14665b1a6fb8030a60c9b4' - * ] - * } - *``` - */ + * Lets you subscribe to specific events in the blockchain. + * + * @param name - The subscription you want to subscribe to. + * @param args - Optional additional parameters, depending on the subscription type. + * @returns A subscription object of type {@link RegisteredSubscription}. The object contains: + * - subscription.id: The subscription id, used to identify and unsubscribing the subscription. + * - subscription.subscribe(): Can be used to re-subscribe with the same parameters. + * - subscription.unsubscribe(): Unsubscribes the subscription and returns TRUE in the callback if successful. + * - subscription.args: The subscription arguments, used when re-subscribing. + * + * + * You can use the subscription object to listen on: + * + * - on("data") - Fires on each incoming log with the log object as argument. + * - on("changed") - Fires on each log which was removed from the blockchain. The log will have the additional property "removed: true". + * - on("error") - Fires when an error in the subscription occurs. + * - on("connected") - Fires once after the subscription successfully connected. Returns the subscription id. + * + * @example **Subscribe to Smart Contract events** + * ```ts + * // Subscribe to `logs` + * const logSubscription = web3.eth.subscribe('logs', { + * address: '0x1234567890123456789012345678901234567890', + * topics: ['0x033456732123ffff2342342dd12342434324234234fd234fd23fd4f23d4234'] + * }); + * logSubscription.on('data', (data: any) => console.log(data)); + * logSubscription.on('error', (error: any) => console.log(error)); + * + * ``` + * + * @example **Subscribe to new block headers** + * ```ts + * // Subscribe to `newBlockHeaders` + * const newBlocksSubscription = await web3.eth.subscribe('newBlockHeaders'); + * + * newBlocksSubscription.on('data', async blockhead => { + * console.log('New block header: ', blockhead); + * + * // You do not need the next line, if you like to keep notified for every new block + * await newBlocksSubscription.unsubscribe(); + * console.log('Unsubscribed from new block headers.'); + * }); + * newBlocksSubscription.on('error', error => + * console.log('Error when subscribing to New block header: ', error), + * ); + * ``` + * + * ### subscribe('pendingTransactions') + * + * Subscribes to incoming pending transactions. + * You can subscribe to pending transactions by calling web3.eth.subscribe('pendingTransactions'). + * + * ```ts + * (await web3.eth.subscribe('pendingTransactions')).on('data', console.log); + * ``` + * + * ### subscribe('newHeads') + * ( same as subscribe('newBlockHeaders')) + * Subscribes to incoming block headers. This can be used as timer to check for changes on the blockchain. + * + * The structure of a returned block header is {@link BlockHeaderOutput}: + * + * ```ts + * (await web3.eth.subscribe('newHeads')).on( // 'newBlockHeaders' would work as well + * 'data', + * console.log + * ); + * >{ + * parentHash: '0x9e746a1d906b299def98c75b06f714d62dacadd567c7515d76eeaa8c8074c738', + * sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347', + * miner: '0x0000000000000000000000000000000000000000', + * stateRoot: '0xe0f04b04861ecfa95e82a9310d6a7ef7aef8d7417f5209c182582bfb98a8e307', + * transactionsRoot: '0x31ab4ea571a9e10d3a19aaed07d190595b1dfa34e03960c04293fec565dea536', + * logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', + * difficulty: 2n, + * number: 21n, + * gasLimit: 11738125n, + * gasUsed: 830006n, + * timestamp: 1678797237n, + * extraData: '0xd883010b02846765746888676f312e32302e31856c696e757800000000000000e0a6e93cf40e2e71a72e493272210c3f43738ccc7e7d7b14ffd51833797d896c09117e8dc4fbcbc969bd21b42e5af3e276a911524038c001b2109b63b8e0352601', + * nonce: 0n + * } + * ``` + * + * ### subscribe('syncing') + * Subscribe to syncing events. This will return `true` when the node is syncing and when it’s finished syncing will return `false`, for the `changed` event. + * + * ```ts + * (await web3.eth.subscribe('syncing')).on('changed', console.log); + * > `true` // when syncing + * + * (await web3.eth.subscribe('syncing')).on('data', console.log); + * > { + * startingBlock: 0, + * currentBlock: 0, + * highestBlock: 0, + * pulledStates: 0, + * knownStates: 0 + * } + * ``` + * + * ### subscribe('logs', options) + * Subscribes to incoming logs, filtered by the given options. If a valid numerical fromBlock options property is set, web3.js will retrieve logs beginning from this point, backfilling the response as necessary. + * + * options: You can subscribe to logs matching a given filter object, which can take the following parameters: + * - `fromBlock`: (optional, default: 'latest') Integer block number, or `'latest'` for the last mined block or `'pending'`, `'earliest'` for not yet mined transactions. + * - `address`: (optional) Contract address or a list of addresses from which logs should originate. + * - `topics`: (optional) Array of 32 Bytes DATA topics. Topics are order-dependent. Each topic can also be an array of DATA with `or` options. + * + * ```ts + * (await web3.eth.subscribe('logs', { + * address: '0xdac17f958d2ee523a2206206994597c13d831ec7', + * })).on('data', console.log); + * + * > { + * removed: false, + * logIndex: 119n, + * transactionIndex: 58n, + * transactionHash: '0x61533efa77937360215069d5d6cb0be09a22af9721e6dc3df59d957833ed8870', + * blockHash: '0xe32bb97084479d32247f66f8b46d00af2fbc3c2db2bc6e5843fe2e4d1ca9b099', + * blockNumber: 18771966n, + * address: '0xdac17f958d2ee523a2206206994597c13d831ec7', + * data: '0x00000000000000000000000000000000000000000000000000000000d88b2e40', + * topics: [ + * '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', + * '0x0000000000000000000000002fb2457f6ec1865dc0d4e7300c696b69c2a1b989', + * '0x00000000000000000000000027fd43babfbe83a81d14665b1a6fb8030a60c9b4' + * ] + * } + *``` + */ public async subscribe< T extends keyof RegisteredSubscription, 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 a5203a93332..de7b7f1edb6 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 @@ -37,8 +37,9 @@ import { createTempAccount, getSystemTestBackend, getSystemTestProvider, + isGeth, itIf, - BACKEND + BACKEND, } from '../../fixtures/system_test_utils'; import { SimpleRevertAbi, SimpleRevertDeploymentData } from '../../fixtures/simple_revert'; @@ -89,9 +90,7 @@ 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, @@ -120,9 +119,7 @@ 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, @@ -155,9 +152,7 @@ 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, @@ -371,6 +366,29 @@ describe('Web3Eth.sendTransaction', () => { expect(minedTransactionData).toMatchObject(transaction); }); + itIf(isGeth)( + 'should send type 0x2 transaction with maxPriorityFeePerGas got from await web3Eth.getMaxPriorityFeePerGas()', + async () => { + const transaction: Transaction = { + from: tempAcc.address, + to: '0x0000000000000000000000000000000000000000', + value: BigInt(1), + maxPriorityFeePerGas: await web3Eth.getMaxPriorityFeePerGas(), + }; + const response = await web3Eth.sendTransaction(transaction); + + // eslint-disable-next-line jest/no-standalone-expect + expect(response.events).toBeUndefined(); + // eslint-disable-next-line jest/no-standalone-expect + expect(response.type).toBe(BigInt(2)); + // eslint-disable-next-line jest/no-standalone-expect + expect(response.status).toBe(BigInt(1)); + const minedTransactionData = await web3Eth.getTransaction(response.transactionHash); + // eslint-disable-next-line jest/no-standalone-expect + expect(minedTransactionData).toMatchObject(transaction); + }, + ); + describe('Transaction PromiEvents', () => { let transaction: Transaction; @@ -476,12 +494,9 @@ 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 () => { @@ -500,51 +515,51 @@ describe('Web3Eth.sendTransaction', () => { ? 'err: intrinsic gas too low: have 1, want 21000 (supplied gas 1)' : 'base fee exceeds gas limit', }; - - if(getSystemTestBackend() !== BACKEND.HARDHAT){ + + if (getSystemTestBackend() !== BACKEND.HARDHAT) { await expect( web3Eth .sendTransaction(transaction) .on('error', error => expect(error).toMatchObject(expectedThrownError)), ).rejects.toMatchObject(expectedThrownError); } else { - try { await web3Eth.sendTransaction(transaction); - } catch (error) { + } catch (error) { expect((error as any).name).toEqual(expectedThrownError.name); expect((error as any).code).toEqual(expectedThrownError.code); expect((error as any).reason).toContain(expectedThrownError.reason); - } + } } }); - itIf(getSystemTestBackend() !== BACKEND.HARDHAT)('Should throw TransactionRevertInstructionError because insufficient funds', async () => { - const transaction: Transaction = { - from: tempAcc.address, - to: '0x0000000000000000000000000000000000000000', - value: BigInt('99999999999999999999999999999999999999999999999999999999999999999'), - }; - - const expectedThrownError = { - name: 'TransactionRevertInstructionError', - message: 'Transaction has been reverted by the EVM', - code: 402, - reason: - getSystemTestBackend() === BACKEND.GETH - ? expect.stringContaining( - 'err: insufficient funds for gas * price + value: address', - ) - : 'VM Exception while processing transaction: insufficient balance', - }; - - // eslint-disable-next-line jest/no-standalone-expect - await expect( - web3Eth - .sendTransaction(transaction) - // eslint-disable-next-line jest/no-standalone-expect - .on('error', error => expect(error).toMatchObject(expectedThrownError)), - ).rejects.toMatchObject(expectedThrownError); - }); + itIf(getSystemTestBackend() !== BACKEND.HARDHAT)( + 'Should throw TransactionRevertInstructionError because insufficient funds', + async () => { + const transaction: Transaction = { + from: tempAcc.address, + to: '0x0000000000000000000000000000000000000000', + value: BigInt('99999999999999999999999999999999999999999999999999999999999999999'), + }; + + const expectedThrownError = { + name: 'TransactionRevertInstructionError', + message: 'Transaction has been reverted by the EVM', + code: 402, + reason: + getSystemTestBackend() === BACKEND.GETH + ? expect.stringContaining('err: insufficient funds for gas * price + value: address') + : 'VM Exception while processing transaction: insufficient balance', + }; + + // eslint-disable-next-line jest/no-standalone-expect + await expect( + web3Eth + .sendTransaction(transaction) + // eslint-disable-next-line jest/no-standalone-expect + .on('error', error => expect(error).toMatchObject(expectedThrownError)), + ).rejects.toMatchObject(expectedThrownError); + }, + ); it('Should throw TransactionRevertInstructionError because of contract revert and return revert reason', async () => { const transaction: Transaction = { @@ -589,7 +604,7 @@ describe('Web3Eth.sendTransaction', () => { reason: getSystemTestBackend() === BACKEND.GETH ? 'execution reverted' - : "Error: VM Exception while processing transaction: reverted with an unrecognized custom error (return data: 0x72090e4d)", + : 'Error: VM Exception while processing transaction: reverted with an unrecognized custom error (return data: 0x72090e4d)', signature: '0x72090e4d', customErrorName: 'ErrorWithNoParams', customErrorDecodedSignature: 'ErrorWithNoParams()', @@ -619,7 +634,7 @@ describe('Web3Eth.sendTransaction', () => { reason: getSystemTestBackend() === BACKEND.GETH ? 'execution reverted' - : "Error: VM Exception while processing transaction: reverted with an unrecognized custom error (return data: 0xc85bda60000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001c5468697320697320616e206572726f72207769746820706172616d7300000000)", + : 'Error: VM Exception while processing transaction: reverted with an unrecognized custom error (return data: 0xc85bda60000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001c5468697320697320616e206572726f72207769746820706172616d7300000000)', signature: '0xc85bda60', data: '000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001c5468697320697320616e206572726f72207769746820706172616d7300000000', customErrorName: 'ErrorWithParams', @@ -657,7 +672,7 @@ describe('Web3Eth.sendTransaction', () => { signature: '0x08c379a0', data: '000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000155468697320697320612073656e64207265766572740000000000000000000000', }; - + await expect( web3Eth .sendTransaction(transaction) diff --git a/packages/web3-eth/test/unit/web3_eth_methods_no_parameters.test.ts b/packages/web3-eth/test/unit/web3_eth_methods_no_parameters.test.ts index 6865188b456..a66a1ecdd46 100644 --- a/packages/web3-eth/test/unit/web3_eth_methods_no_parameters.test.ts +++ b/packages/web3-eth/test/unit/web3_eth_methods_no_parameters.test.ts @@ -76,5 +76,10 @@ describe('web3_eth_methods_no_parameters', () => { await web3Eth.getNodeInfo(); expect(ethRpcMethods.getNodeInfo).toHaveBeenCalledWith(web3Eth.requestManager); }); + + it('getMaxPriorityFeePerGas', async () => { + await web3Eth.getMaxPriorityFeePerGas(); + expect(ethRpcMethods.getMaxPriorityFeePerGas).toHaveBeenCalledWith(web3Eth.requestManager); + }); }); }); diff --git a/packages/web3-rpc-methods/CHANGELOG.md b/packages/web3-rpc-methods/CHANGELOG.md index 29de022b81c..9b2c602e962 100644 --- a/packages/web3-rpc-methods/CHANGELOG.md +++ b/packages/web3-rpc-methods/CHANGELOG.md @@ -134,3 +134,6 @@ Documentation: ## [Unreleased] +### Added + +- Added `getMaxPriorityFeePerGas` method (#6748) diff --git a/packages/web3-rpc-methods/src/eth_rpc_methods.ts b/packages/web3-rpc-methods/src/eth_rpc_methods.ts index 59c269051a4..b33857d7d80 100644 --- a/packages/web3-rpc-methods/src/eth_rpc_methods.ts +++ b/packages/web3-rpc-methods/src/eth_rpc_methods.ts @@ -73,6 +73,13 @@ export async function getGasPrice(requestManager: Web3RequestManager) { }); } +export async function getMaxPriorityFeePerGas(requestManager: Web3RequestManager) { + return requestManager.send({ + method: 'eth_maxPriorityFeePerGas', + params: [], + }); +} + export async function getAccounts(requestManager: Web3RequestManager) { return requestManager.send({ method: 'eth_accounts', diff --git a/packages/web3-rpc-methods/test/unit/eth_rpc_methods/get_maxPriorityFeePerGas.ts b/packages/web3-rpc-methods/test/unit/eth_rpc_methods/get_maxPriorityFeePerGas.ts new file mode 100644 index 00000000000..bafe6a92c03 --- /dev/null +++ b/packages/web3-rpc-methods/test/unit/eth_rpc_methods/get_maxPriorityFeePerGas.ts @@ -0,0 +1,52 @@ +/* +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 . +*/ + +// 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 { Web3RequestManager } from 'web3-core'; + +import { ethRpcMethods } from '../../../src/index'; + +describe('getMaxPriorityFeePerGas', () => { + let requestManagerSendSpy: jest.Mock; + let requestManager: Web3RequestManager; + + beforeAll(() => { + requestManager = new Web3RequestManager('http://127.0.0.1:8545'); + requestManagerSendSpy = jest.fn(); + requestManager.send = requestManagerSendSpy; + }); + + it('should call requestManager.send with getMaxPriorityFeePerGas method', async () => { + await ethRpcMethods.getMaxPriorityFeePerGas(requestManager); + expect(requestManagerSendSpy).toHaveBeenCalledWith({ + method: 'eth_maxPriorityFeePerGas', + params: [], + }); + }); +}); diff --git a/packages/web3-types/src/apis/eth_execution_api.ts b/packages/web3-types/src/apis/eth_execution_api.ts index e015e6b9ed3..3abb0b29af0 100644 --- a/packages/web3-types/src/apis/eth_execution_api.ts +++ b/packages/web3-types/src/apis/eth_execution_api.ts @@ -193,10 +193,7 @@ export type EthExecutionAPI = { eth_getUncleCountByBlockHash: (blockHash: HexString32Bytes) => Uint; eth_getUncleCountByBlockNumber: (blockNumber: BlockNumberOrTag) => Uint; eth_getUncleByBlockHashAndIndex: (blockHash: HexString32Bytes, uncleIndex: Uint) => BlockAPI; - eth_getUncleByBlockNumberAndIndex: ( - blockNumber: BlockNumberOrTag, - uncleIndex: Uint, - ) => BlockAPI; + eth_getUncleByBlockNumberAndIndex: (blockNumber: BlockNumberOrTag, uncleIndex: Uint) => BlockAPI; // https://github.com/ethereum/execution-apis/blob/main/src/eth/transaction.yaml eth_getTransactionByHash: (transactionHash: HexString32Bytes) => TransactionInfoAPI | undefined; @@ -233,6 +230,7 @@ export type EthExecutionAPI = { newestBlock: BlockNumberOrTag, rewardPercentiles: number[], ) => FeeHistoryResultAPI; + eth_maxPriorityFeePerGas: () => Uint; // https://github.com/ethereum/execution-apis/blob/main/src/eth/filter.yaml eth_newFilter: (filter: Filter) => Uint; From f696e47b89d6613dc3a254ec5449f3ceeacf3cd8 Mon Sep 17 00:00:00 2001 From: omahs <73983677+omahs@users.noreply.github.com> Date: Thu, 15 Feb 2024 16:51:11 +0100 Subject: [PATCH 007/186] fix link (#6810) --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 738abd68e23..7ad07339c5c 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,6 +1,6 @@ ## Description -Please include a summary of the changes and be sure to follow our [Contribution Guidelines](https://github.com/web3/web3.js/blob/4.x/CONTRIBUTIONS.md). +Please include a summary of the changes and be sure to follow our [Contribution Guidelines](https://github.com/web3/web3.js/blob/4.x/.github/CONTRIBUTING.md). 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 056/186] 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 057/186] 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 058/186] 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 059/186] 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 060/186] =?UTF-8?q?Add=20the=20missing=20types=20to=20the?= =?UTF-8?q?=20=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 061/186] 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 062/186] 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 063/186] 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 064/186] 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 065/186] 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 066/186] 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 067/186] 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 068/186] 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 069/186] 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 070/186] 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 071/186] 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 072/186] 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 073/186] 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 074/186] 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 075/186] 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 076/186] 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 077/186] 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 fd2982d1afacd6bf89084324b478ec04af18052e Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 23 May 2024 10:56:44 -0400 Subject: [PATCH 078/186] release/v4.9.0 (#7057) * update changelog and bump versions * update changelog and revert version bump web3-types * change web3-eth-abi package version --- CHANGELOG.md | 22 +++++++++++++++++++++- packages/web3-core/CHANGELOG.md | 7 ++++++- packages/web3-core/package.json | 12 ++++++------ packages/web3-errors/CHANGELOG.md | 6 ++++-- packages/web3-errors/package.json | 4 ++-- packages/web3-eth-abi/CHANGELOG.md | 6 ++++++ packages/web3-eth-abi/package.json | 8 ++++---- packages/web3-eth-contract/CHANGELOG.md | 4 +++- packages/web3-eth-contract/package.json | 14 +++++++------- packages/web3-eth-ens/CHANGELOG.md | 5 ++++- packages/web3-eth-ens/package.json | 18 +++++++++--------- packages/web3-eth/CHANGELOG.md | 4 +++- packages/web3-eth/package.json | 16 ++++++++-------- packages/web3-net/CHANGELOG.md | 5 ++++- packages/web3-net/package.json | 10 +++++----- packages/web3-rpc-methods/CHANGELOG.md | 4 +++- packages/web3-rpc-methods/package.json | 8 ++++---- packages/web3-types/CHANGELOG.md | 2 +- packages/web3-utils/CHANGELOG.md | 4 +++- packages/web3-utils/package.json | 6 +++--- packages/web3-validator/CHANGELOG.md | 6 ++++-- packages/web3-validator/package.json | 6 +++--- packages/web3/CHANGELOG.md | 4 +++- packages/web3/package.json | 22 +++++++++++----------- packages/web3/src/version.ts | 2 +- 25 files changed, 128 insertions(+), 77 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 94a802644cc..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 @@ -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,12 @@ 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) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-core/CHANGELOG.md b/packages/web3-core/CHANGELOG.md index d69e71c8cf9..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 @@ -217,3 +217,8 @@ Documentation: - Interface `RequestManagerMiddleware` was changed (#7003) +### Fixed + +- 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 04fcb06f509..865aafd0db6 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.6.0", + "web3-utils": "^4.3.0", + "web3-validator": "^2.0.6" }, "optionalDependencies": { "web3-providers-ipc": "^4.0.7" 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 08a2b5ebb7f..1b8587c81b3 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.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 47f57f4d2a4..4a7f1fe8add 100644 --- a/packages/web3-eth-abi/CHANGELOG.md +++ b/packages/web3-eth-abi/CHANGELOG.md @@ -170,4 +170,10 @@ Documentation: - Dependencies updated +## [4.2.2] + +### 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 1ed38b13f05..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.2.1", + "version": "4.2.2", "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-errors": "^1.2.0", "web3-types": "^1.6.0", - "web3-utils": "^4.2.3", - "web3-validator": "^2.0.5" + "web3-utils": "^4.3.0", + "web3-validator": "^2.0.6" }, "devDependencies": { "@humeris/espresso-shot": "^4.0.0", 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 0c8cd166675..74edee8f90b 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-core": "^4.4.0", + "web3-errors": "^1.2.0", + "web3-eth": "^4.7.0", + "web3-eth-abi": "^4.2.2", "web3-types": "^1.6.0", - "web3-utils": "^4.2.3", - "web3-validator": "^2.0.5" + "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..c9be2f93561 100644 --- a/packages/web3-eth-ens/CHANGELOG.md +++ b/packages/web3-eth-ens/CHANGELOG.md @@ -153,7 +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 db7fc9d2d03..4c1865ca983 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.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 767f5697387..47c188743b2 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.2.2", "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-rpc-methods": "^1.3.0", "web3-types": "^1.6.0", - "web3-utils": "^4.2.3", - "web3-validator": "^2.0.5" + "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..5e7ea9073b3 100644 --- a/packages/web3-net/CHANGELOG.md +++ b/packages/web3-net/CHANGELOG.md @@ -141,7 +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 d3ca4f5a32b..952457f72be 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.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 8e9eec0e597..3a05060f2c2 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.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-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 511ce216fc2..c07e9b85821 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-errors": "^1.2.0", "web3-types": "^1.6.0", - "web3-validator": "^2.0.5" + "web3-validator": "^2.0.6" } } diff --git a/packages/web3-validator/CHANGELOG.md b/packages/web3-validator/CHANGELOG.md index ea8cd0259ff..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. +- 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 c416a1fa235..4a12b604981 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.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 52bb78ce8c8..668d77e26ff 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.2.2", "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-rpc-methods": "^1.3.0", "web3-types": "^1.6.0", - "web3-utils": "^4.2.3", - "web3-validator": "^2.0.5" + "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 7537f03db3a2932a4f5c6f13ada1c3d6ca0217cd Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Thu, 23 May 2024 08:32:25 -0700 Subject: [PATCH 079/186] fix(docs): intro (#7056) * fix(docs): intro - landing page should be Introduction as opposed to Quickstart - improvements to Introduction * Packages Enhancements to package documentation * Tweaks * @luu-alex suggestion * Update docs/docs/guides/getting_started/introduction.md Co-authored-by: Alex --------- Co-authored-by: Alex --- .../guides/getting_started/introduction.md | 66 ++++++++++--------- .../{getting_started.md => quickstart.md} | 1 - 2 files changed, 35 insertions(+), 32 deletions(-) rename docs/docs/guides/getting_started/{getting_started.md => quickstart.md} (99%) diff --git a/docs/docs/guides/getting_started/introduction.md b/docs/docs/guides/getting_started/introduction.md index ab9a303fc84..0e92051b4ce 100644 --- a/docs/docs/guides/getting_started/introduction.md +++ b/docs/docs/guides/getting_started/introduction.md @@ -1,66 +1,70 @@ --- +slug: / sidebar_position: 1 sidebar_label: Introduction --- # Introduction -Welcome to Web3.js Documentation!👋 +Web3.js is a robust and flexible collection of **TypeScript and JavaScript** libraries that allows developers to interact with local or remote [Ethereum](https://ethereum.org/en/) nodes (or **any EVM-compatible blockchain**) over **HTTP, IPC or WebSocket** connections. It is a powerful and efficient toolkit for crafting applications within the Ethereum ecosystem and beyond. -Web3.js is a robust and flexible collection of libraries for **TypeScript and JavaScript** developers. It allows you to interact with a local or remote Ethereum node (or **any EVM-compatible blockchain**) using **HTTP, IPC or WebSocket.** It serves as an essential tool for connecting and crafting applications within the Ethereum ecosystem. - -The following documentation will guide you through different use cases of Web3.js, upgrading from older versions, as well as providing an API reference documentation with examples. +This documentation is the entrypoint to Web3.js for developers. It covers [basic](/guides/getting_started/quickstart) and [advanced](/guides/smart_contracts/) usage with examples, and includes comprehensive [API documentation](/api) as well as guides for common tasks, like [upgrading](/guides/web3_upgrade_guide/x/) from older versions. ## Features of Web3.js v4 -- Web3.js [Plugins Feature](/guides/web3_plugin_guide/) for extending functionality ( [List of Existing Plugins](https://web3js.org/plugins) ) -- ECMAScript (ESM) and CommonJS (CJS) builds -- [Tree shakable with ESM](/guides/advanced/tree_shaking) -- [Contracts dynamic types](/guides/smart_contracts/infer_contract_types/) & full API in TypeScript -- Using native BigInt instead of large BigNumber libraries -- More efficient ABI Encoder & Decoder -- Custom Output formatters -- In compliance with Eth EL API +- Flexible + - ECMAScript (ESM) and CommonJS (CJS) builds + - [Plugins](/guides/web3_plugin_guide/) for extending functionality +- Efficient + - Modular, [package](/#packages)-based design reduces unneeded dependencies + - [Tree shakable with ESM](/guides/advanced/tree_shaking) + - Use of native [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) (instead of large [BigNumber](https://mikemcl.github.io/bignumber.js/) libraries) + - Efficient ABI [encoding](/api/web3-eth-abi/function/encodeFunctionCall) & [decoding](/api/web3-eth-abi/function/decodeParameter) +- Developer-Friendly + - [Dynamic contract types](/guides/smart_contracts/infer_contract_types/) & full API in TypeScript + - Custom output [formatters](https://docs.web3js.org/api/web3-utils/function/format) + - In compliance with the [Ethereum JSON-RPC Specification](https://ethereum.github.io/execution-apis/api-documentation/) ## Packages -Web3.js is modular, consisting of several packages, each serving specific functionalities. If you have specific tasks in mind, you don't need to install the entire Web3 library. Instead, selectively install the package that suits your requirements for a more efficient development experience. Here is an overview of the available packages: +Web3.js is a modular collection of packages, each of which serves a specific needs. This means developers don't need to install the entire Web3 library for most use cases. Instead, necessary packages are selectively installed for a more efficient development experience. Here is an overview of a selection of available packages: + +- [**Web3Eth:**](/libdocs/Web3Eth) The `web3-eth` package is the entrypoint to Web3.js - it's the control center for managing interactions with Ethereum and other EVM-compatible networks. -- [**ABI:**](/libdocs/ABI) The `web3-eth-abi` package simplifies decoding logs and parameters, encoding function calls and signatures, and inferring types for efficient Ethereum **contract interactions.** +- [**Net:**](/libdocs/Net) The `web3-net` package provides discovery and interactions for an **Ethereum node's network properties.** -- [**Accounts:**](/libdocs/Accounts) The `web3-eth-accounts` package has tools for creating Ethereum accounts/wallets and making sure transactions and data are **securely signed.** +- [**Accounts:**](/libdocs/Accounts) The `web3-eth-accounts` package has tools for creating Ethereum accounts and the **secure signing** of transactions and data. -- [**Contract:**](/libdocs/Contract) With the `web3-eth-Contract`, you can interact with Smart contracts. This functionality allows **communication with contracts through JavaScript or TypeScript objects**, simplifying your development and interaction processes. +- [**Personal:**](/libdocs/Personal) Use `web3-eth-personal` for **direct communication about your accounts with the Ethereum node**, which streamlines account management during development. -- [**ENS:**](/libdocs/ENS) The `web3-eth-ens` package helps you communicate with the **Ethereum Name Service (ENS)** on the blockchain. + **NOTE:** *For enhanced security in production and when interacting with public nodes, consider using `web3-eth-accounts` for local signing operations, which keeps your private keys and sensitive information secure on your local machine* -- [**Iban:**](/libdocs/Iban) The `web3-eth-iban` package allows you to switch between **Ethereum addresses and special banking-like addresses** (IBAN or BBAN). It makes the conversion back and forth easier. +- [**Utils:**](/libdocs/Utils) The `web3-utils` package provides helpers to perform a range of essential Ethereum development tasks, including **converting data formats, checking addresses, encoding and decoding data, hashing, handling numbers, and much more.**. -- [**Net:**](/libdocs/Net) The `web3-net` class allows you to talk about and deal with an **Ethereum node's network details.** +- [**Contract:**](/libdocs/Contract) The `web3-eth-contract` package makes it easy to **interact with smart contracts through JavaScript or TypeScript,** which streamlines the development process and makes it less error-prone. -- [**Personal:**](/libdocs/Personal) Use `web3-eth-personal` for **direct communication with the Ethereum node about your accounts**, streamlining account management in your development workflow. - **NOTE:** *For enhanced security when interacting with public nodes, consider using `web3-eth-accounts` for local signing operations, keeping your private keys and sensitive information secure on your local machine* +- [**ABI:**](/libdocs/ABI) The `web3-eth-abi` package simplifies decoding logs and parameters, encoding function calls and signatures, and inferring types for efficient Ethereum **smart contract interactions.** -- [**Utils:**](/libdocs/Utils) With the `web3-utils` package you can perform a range of essential tasks in Ethereum development, including **converting data formats, checking addresses, encoding and decoding, hashing, handling numbers, and much more**, providing versatile utility functions for your applications. +- [**ENS:**](/libdocs/ENS) The `web3-eth-ens` package makes it easy for developers to communicate with the **Ethereum Name Service (ENS).** -- [**Web3Eth:**](/libdocs/Web3Eth) The `web3-eth` is your main tool for interacting with the Ethereum blockchain. It's like the control center for managing your interactions with Ethereum. +- [**Iban:**](/libdocs/Iban) The `web3-eth-iban` package allows you to switch between **Ethereum addresses and special banking-like addresses** (IBAN or BBAN) and simplifies conversion between the types. -### Additional supporting packages +### Additional supporting packages -- **Web3 Types:** This package has common typescript types. +- [**Web3 Core:**](/api/web3-core) subscriptions, request management, and configuration used by other Web3 packages -- **Web3 Validator:** This package offers functionality for validation using provided Schema. +- [**Web3 Types:**](/api/web3-types) data structures, objects, interfaces and types used by Web3 -- **Web3 Core:** Web3 Core has configuration, Subscriptions and Requests management functionality used by other Web3 packages. +- [**Web3 Validator:**](/api/web3-validator) runtime type validation against predefined types or custom schemas -- **Web3 Errors:** Web3 Errors has error codes and common error classes that are used by other Web3 packages. +- [**Web3 Errors:**](/api/web3-errors) 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. +- [**Web3 RPC Methods:**](/api/web3/namespace/rpcMethods) 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. +- **Extensive Documentation and Community**: Web3.js is one of the most established Ethereum libraries, which means it 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. +- **Modular Design**: Web3.js is designed to be modular, which allows developers to use specific packages according to their needs. This leads 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. diff --git a/docs/docs/guides/getting_started/getting_started.md b/docs/docs/guides/getting_started/quickstart.md similarity index 99% rename from docs/docs/guides/getting_started/getting_started.md rename to docs/docs/guides/getting_started/quickstart.md index 18b95035957..d023e01bb9f 100644 --- a/docs/docs/guides/getting_started/getting_started.md +++ b/docs/docs/guides/getting_started/quickstart.md @@ -1,5 +1,4 @@ --- -slug: / sidebar_position: 2 sidebar_label: Quickstart --- From 692987a78dc1690bcd3917c4ff3b3264e6a35274 Mon Sep 17 00:00:00 2001 From: Junaid <86780488+jdevcs@users.noreply.github.com> Date: Fri, 24 May 2024 15:43:47 +0200 Subject: [PATCH 080/186] coverage increase (#7051) * coverage increase * get Uncle tests * lint err fix * correction --- ...as.ts => get_maxPriorityFeePerGas.test.ts} | 0 .../get_uncle_by_block_number.test.ts | 42 +++++ .../personal_rpc_methods/eth_personal.test.ts | 145 ++++++++++++++++++ 3 files changed, 187 insertions(+) rename packages/web3-rpc-methods/test/unit/eth_rpc_methods/{get_maxPriorityFeePerGas.ts => get_maxPriorityFeePerGas.test.ts} (100%) create mode 100644 packages/web3-rpc-methods/test/unit/eth_rpc_methods/get_uncle_by_block_number.test.ts create mode 100644 packages/web3-rpc-methods/test/unit/personal_rpc_methods/eth_personal.test.ts diff --git a/packages/web3-rpc-methods/test/unit/eth_rpc_methods/get_maxPriorityFeePerGas.ts b/packages/web3-rpc-methods/test/unit/eth_rpc_methods/get_maxPriorityFeePerGas.test.ts similarity index 100% rename from packages/web3-rpc-methods/test/unit/eth_rpc_methods/get_maxPriorityFeePerGas.ts rename to packages/web3-rpc-methods/test/unit/eth_rpc_methods/get_maxPriorityFeePerGas.test.ts diff --git a/packages/web3-rpc-methods/test/unit/eth_rpc_methods/get_uncle_by_block_number.test.ts b/packages/web3-rpc-methods/test/unit/eth_rpc_methods/get_uncle_by_block_number.test.ts new file mode 100644 index 00000000000..93e8a633582 --- /dev/null +++ b/packages/web3-rpc-methods/test/unit/eth_rpc_methods/get_uncle_by_block_number.test.ts @@ -0,0 +1,42 @@ +/* +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 { Web3RequestManager } from 'web3-core'; +import { ethRpcMethods } from '../../../src/index'; + +jest.mock('web3-validator'); + +describe('getUncleByBlockNumberAndIndex', () => { + let requestManagerSendSpy: jest.Mock; + let requestManager: Web3RequestManager; + + beforeAll(() => { + requestManager = new Web3RequestManager('http://127.0.0.1:8545'); + requestManagerSendSpy = jest.fn(); + requestManager.send = requestManagerSendSpy; + }); + + it('should call requestManager.send with eth_getUncleByBlockNumberAndIndex method', async () => { + await ethRpcMethods.getUncleByBlockNumberAndIndex(requestManager, 0, '1' ); + expect(requestManagerSendSpy).toHaveBeenCalledWith({ + method: 'eth_getUncleByBlockNumberAndIndex', + params: [0,'1'], + }); + }, + ); + +}); diff --git a/packages/web3-rpc-methods/test/unit/personal_rpc_methods/eth_personal.test.ts b/packages/web3-rpc-methods/test/unit/personal_rpc_methods/eth_personal.test.ts new file mode 100644 index 00000000000..a487df07964 --- /dev/null +++ b/packages/web3-rpc-methods/test/unit/personal_rpc_methods/eth_personal.test.ts @@ -0,0 +1,145 @@ +/* +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 { Web3RequestManager } from 'web3-core'; +import { EthPersonalAPI } from 'web3-types'; +import { personalRpcMethods } from '../../../src/index'; + +describe('Eth Personal', () => { + let requestManagerSendSpy: jest.Mock; + let requestManager: Web3RequestManager; + + beforeAll(() => { + requestManager = new Web3RequestManager('http://127.0.0.1:8545'); + requestManagerSendSpy = jest.fn(); + requestManager.send = requestManagerSendSpy; + }); + + it('should call requestManager.send with personal_listAccounts method', async () => { + await personalRpcMethods.getAccounts(requestManager); + expect(requestManagerSendSpy).toHaveBeenCalledWith({ + method: 'personal_listAccounts', + params: [], + }); + }); + + it('should call requestManager.send with personal_newAccount method', async () => { + const pass = "ABC123"; + await personalRpcMethods.newAccount(requestManager, pass); + expect(requestManagerSendSpy).toHaveBeenCalledWith({ + method: 'personal_newAccount', + params: [pass], + }); + }); + + it('should call requestManager.send with personal_unlockAccount method', async () => { + const pass = "ABC123"; + const address = "0x4106486FB42F3Abf07CC07ef5DEE38f60319e789"; + const duration = 100; + await personalRpcMethods.unlockAccount(requestManager, address, pass, duration); + + expect(requestManagerSendSpy).toHaveBeenCalledWith({ + method: 'personal_unlockAccount', + params: [address, pass, duration], + }); + }); + + it('should call requestManager.send with personal_lockAccount method', async () => { + const address = "0x4106486FB42F3Abf07CC07ef5DEE38f60319e789"; + + await personalRpcMethods.lockAccount(requestManager, address ); + + expect(requestManagerSendSpy).toHaveBeenCalledWith({ + method: 'personal_lockAccount', + params: [address], + }); + }); + + it('should call requestManager.send with personal_importRawKey method', async () => { + const passPhrase = "123456"; + const keyData = "abe40cb08850da918ee951b237fa87946499b2d8643e4aa12b0610b050c731f6"; + await personalRpcMethods.importRawKey(requestManager, keyData, passPhrase ); + + expect(requestManagerSendSpy).toHaveBeenCalledWith({ + method: 'personal_importRawKey', + params: [keyData,passPhrase], + }); + }); + + it('should call requestManager.send with personal_sendTransaction method', async () => { + const passPhrase = "123456"; + const tx = { + from: "0x0d4aa485ecbc499c70860feb7e5aaeaf5fd8172e", + gasPrice: "20000", + gas: "21000", + to: "0x4106486FB42F3Abf07CC07ef5DEE38f60319e789", + value: "1000000", + data: "", + nonce: 0, + }; + await personalRpcMethods.sendTransaction(requestManager, tx, passPhrase ); + + expect(requestManagerSendSpy).toHaveBeenCalledWith({ + method: 'personal_sendTransaction', + params: [tx,passPhrase], + }); + }); + + it('should call requestManager.send with personal_signTransaction method', async () => { + const passPhrase = "123456"; + const tx = { + from: "0x0d4aa485ecbc499c70860feb7e5aaeaf5fd8172e", + gasPrice: "20000", + gas: "21000", + to: "0x4106486FB42F3Abf07CC07ef5DEE38f60319e789", + value: "1000000", + data: "", + nonce: 0, + }; + await personalRpcMethods.signTransaction(requestManager, tx, passPhrase ); + + expect(requestManagerSendSpy).toHaveBeenCalledWith({ + method: 'personal_signTransaction', + params: [tx,passPhrase], + }); + }); + + it('should call requestManager.send with personal_sign method', async () => { + const data = "Hello world"; + const address = "0x0D4Aa485ECbC499c70860fEb7e5AaeAf5fd8172E"; + const pass = "123456"; + + await personalRpcMethods.sign(requestManager, data,address,pass); + + expect(requestManagerSendSpy).toHaveBeenCalledWith({ + method: 'personal_sign', + params: [ data,address,pass], + }); + }); + + it('should call requestManager.send with personal_ecRecover method', async () => { + const data = "Hello world"; + const signature = "0x5d21d01b3198ac34d0585a9d76c4d1c8123e5e06746c8962318a1c08ffb207596e6fce4a6f377b7c0fc98c5f646cd73438c80e8a1a95cbec55a84c2889dca0301b"; + + await personalRpcMethods.ecRecover(requestManager,data, signature); + + expect(requestManagerSendSpy).toHaveBeenCalledWith({ + method: 'personal_ecRecover', + params: [ data, signature], + }); + }); +}); From 962b99fe54ede0d573dff69a7d1667b081ef3fd0 Mon Sep 17 00:00:00 2001 From: Junaid <86780488+jdevcs@users.noreply.github.com> Date: Fri, 24 May 2024 17:37:58 +0200 Subject: [PATCH 081/186] 6992 getText update and getName fix (#7047) * getText with address as input * reverse resolution support * changelog update * fix * lint fix * name update * updated getname test --- packages/web3-eth-ens/CHANGELOG.md | 11 ++++++++++- packages/web3-eth-ens/src/ens.ts | 11 +++++++---- packages/web3-eth-ens/src/resolver.ts | 13 +++++++++---- packages/web3-eth-ens/test/unit/resolver.test.ts | 7 +++++-- 4 files changed, 31 insertions(+), 11 deletions(-) diff --git a/packages/web3-eth-ens/CHANGELOG.md b/packages/web3-eth-ens/CHANGELOG.md index c9be2f93561..e5dea285207 100644 --- a/packages/web3-eth-ens/CHANGELOG.md +++ b/packages/web3-eth-ens/CHANGELOG.md @@ -159,4 +159,13 @@ Documentation: - `defaultReturnFormat` was added to all methods that have `ReturnType` param. (#6947) -## [Unreleased] \ No newline at end of file +## [Unreleased] + +### Added + +- `getText` now supports first param Address +- `getName` has optional second param checkInterfaceSupport + +### Fixed + +- `getName` reverse resolution \ No newline at end of file diff --git a/packages/web3-eth-ens/src/ens.ts b/packages/web3-eth-ens/src/ens.ts index 254a33bc842..8f3e1806127 100644 --- a/packages/web3-eth-ens/src/ens.ts +++ b/packages/web3-eth-ens/src/ens.ts @@ -33,6 +33,7 @@ import { TransactionReceipt, Web3NetAPI, } from 'web3-types'; +import { isAddress } from 'web3-validator'; import { PublicResolverAbi } from './abi/ens/PublicResolver.js'; import { networkIds, registryAddresses } from './config.js'; import { Registry } from './registry.js'; @@ -174,8 +175,10 @@ export class ENS extends Web3Context { * @param key - The key to resolve https://github.com/ethereum/ercs/blob/master/ERCS/erc-634.md#global-keys * @returns - The value content stored in the resolver for the specified key */ - public async getText(ENSName: string, key: string): Promise { - return this._resolver.getText(ENSName, key); + public async getText(ENSNameOrAddr: string | Address, key: string): Promise { + if(isAddress(ENSNameOrAddr)) + return this._resolver.getText(await(this._resolver.getName(ENSNameOrAddr,false)), key); + return this._resolver.getText(ENSNameOrAddr, key); } /** @@ -183,8 +186,8 @@ export class ENS extends Web3Context { * @param ENSName - The node to resolve * @returns - The name */ - public async getName(ENSName: string): Promise { - return this._resolver.getName(ENSName); + public async getName(ENSName: string, checkInterfaceSupport = true): Promise { + return this._resolver.getName(ENSName, checkInterfaceSupport); } /** diff --git a/packages/web3-eth-ens/src/resolver.ts b/packages/web3-eth-ens/src/resolver.ts index c93d150e805..cb345055d95 100644 --- a/packages/web3-eth-ens/src/resolver.ts +++ b/packages/web3-eth-ens/src/resolver.ts @@ -130,12 +130,17 @@ export class Resolver { } public async getName( - address: string + address: string, + checkInterfaceSupport = true ) { - const resolverContract = await this.getResolverContractAdapter(address); - await this.checkInterfaceSupport(resolverContract, methodsInInterface.name); + const reverseName = `${address.toLowerCase().substring(2)}.addr.reverse`; + const resolverContract = await this.getResolverContractAdapter(reverseName); + + if(checkInterfaceSupport) + await this.checkInterfaceSupport(resolverContract, methodsInInterface.name); + return resolverContract.methods - .name(namehash(address)).call() + .name(namehash(reverseName)).call() } } diff --git a/packages/web3-eth-ens/test/unit/resolver.test.ts b/packages/web3-eth-ens/test/unit/resolver.test.ts index f0df74bd2a7..da189e5a45d 100644 --- a/packages/web3-eth-ens/test/unit/resolver.test.ts +++ b/packages/web3-eth-ens/test/unit/resolver.test.ts @@ -239,6 +239,8 @@ describe('resolver', () => { describe('name', () => { it('getName', async () => { + const address = "0x314159265dd8dbb310642f98f50c066173c1259b"; + const supportsInterfaceMock = jest .spyOn(contract.methods, 'supportsInterface') .mockReturnValue({ @@ -255,12 +257,13 @@ describe('resolver', () => { }); }); - await resolver.getName(ENS_NAME); + await resolver.getName(address); expect(supportsInterfaceMock).toHaveBeenCalledWith( interfaceIds[methodsInInterface.name], ); - expect(nameMock).toHaveBeenCalledWith(namehash(ENS_NAME)); + const reverseName = `${address.toLowerCase().substring(2)}.addr.reverse`; + expect(nameMock).toHaveBeenCalledWith(namehash(reverseName)); }) }) From 22c07ad7b00745f1b046e31580a343eca3b59c76 Mon Sep 17 00:00:00 2001 From: Junaid <86780488+jdevcs@users.noreply.github.com> Date: Mon, 27 May 2024 13:58:55 +0200 Subject: [PATCH 082/186] web3 external provider - Quicknode (#7019) * providers package init * types and quick nodes provider * readme update * import fixes and unit tests * lint fix * lint fix * added host and quicknodes provider info * added host * tests * lint * default provider and itests * package dir rename * web3-rpc-providers * web3-rpc-providers in web3 * packagejson updates * rename test file * tests in web3 package * e2e tests update * lint fix * empty provider * empty provider test fix * lint fix * default provider tests update * lint fix --- packages/web3-rpc-providers/.eslintignore | 1 + packages/web3-rpc-providers/.eslintrc.js | 7 + packages/web3-rpc-providers/.gitignore | 0 packages/web3-rpc-providers/.npmignore | 1 + packages/web3-rpc-providers/.npmrc | 1 + packages/web3-rpc-providers/.prettierignore | 1 + packages/web3-rpc-providers/.prettierrc.json | 1 + packages/web3-rpc-providers/CHANGELOG.md | 38 + packages/web3-rpc-providers/README.md | 58 + .../web3-rpc-providers/assets/logo/web3js.ai | 1516 +++++++++++++++++ .../web3-rpc-providers/assets/logo/web3js.jpg | Bin 0 -> 80258 bytes .../web3-rpc-providers/assets/logo/web3js.svg | 33 + packages/web3-rpc-providers/package.json | 64 + packages/web3-rpc-providers/src/index.ts | 25 + packages/web3-rpc-providers/src/types.ts | 44 + .../web3-rpc-providers/src/web3_provider.ts | 135 ++ .../src/web3_provider_quicknode.ts | 91 + packages/web3-rpc-providers/test/.eslintrc.js | 7 + .../test/config/jest.config.js | 1 + .../web3-rpc-providers/test/config/setup.js | 24 + .../test/integration/jest.config.js | 33 + .../test/integration/setup.js | 24 + .../web3-rpc-providers/test/tsconfig.json | 1 + .../test/unit/constructor.test.ts | 62 + .../test/unit/jest.config.js | 9 + .../test/unit/request.test.ts | 81 + packages/web3-rpc-providers/tsconfig.cjs.json | 1 + packages/web3-rpc-providers/tsconfig.esm.json | 1 + .../web3-rpc-providers/tsconfig.types.json | 1 + packages/web3-rpc-providers/tsdoc.json | 4 + packages/web3/package.json | 3 +- packages/web3/src/web3.ts | 5 +- packages/web3/test/integration/web3.test.ts | 10 +- .../test/integration/web3RPCProviders.test.ts | 61 + packages/web3/test/unit/web3.test.ts | 4 +- templates/.eslintignore.tmpl | 5 +- 36 files changed, 2338 insertions(+), 15 deletions(-) create mode 120000 packages/web3-rpc-providers/.eslintignore create mode 100644 packages/web3-rpc-providers/.eslintrc.js create mode 100644 packages/web3-rpc-providers/.gitignore create mode 120000 packages/web3-rpc-providers/.npmignore create mode 120000 packages/web3-rpc-providers/.npmrc create mode 120000 packages/web3-rpc-providers/.prettierignore create mode 120000 packages/web3-rpc-providers/.prettierrc.json create mode 100644 packages/web3-rpc-providers/CHANGELOG.md create mode 100644 packages/web3-rpc-providers/README.md create mode 100644 packages/web3-rpc-providers/assets/logo/web3js.ai create mode 100644 packages/web3-rpc-providers/assets/logo/web3js.jpg create mode 100644 packages/web3-rpc-providers/assets/logo/web3js.svg create mode 100644 packages/web3-rpc-providers/package.json create mode 100644 packages/web3-rpc-providers/src/index.ts create mode 100644 packages/web3-rpc-providers/src/types.ts create mode 100644 packages/web3-rpc-providers/src/web3_provider.ts create mode 100644 packages/web3-rpc-providers/src/web3_provider_quicknode.ts create mode 100644 packages/web3-rpc-providers/test/.eslintrc.js create mode 120000 packages/web3-rpc-providers/test/config/jest.config.js create mode 100644 packages/web3-rpc-providers/test/config/setup.js create mode 100644 packages/web3-rpc-providers/test/integration/jest.config.js create mode 100644 packages/web3-rpc-providers/test/integration/setup.js create mode 120000 packages/web3-rpc-providers/test/tsconfig.json create mode 100644 packages/web3-rpc-providers/test/unit/constructor.test.ts create mode 100644 packages/web3-rpc-providers/test/unit/jest.config.js create mode 100644 packages/web3-rpc-providers/test/unit/request.test.ts create mode 120000 packages/web3-rpc-providers/tsconfig.cjs.json create mode 120000 packages/web3-rpc-providers/tsconfig.esm.json create mode 120000 packages/web3-rpc-providers/tsconfig.types.json create mode 100644 packages/web3-rpc-providers/tsdoc.json create mode 100644 packages/web3/test/integration/web3RPCProviders.test.ts diff --git a/packages/web3-rpc-providers/.eslintignore b/packages/web3-rpc-providers/.eslintignore new file mode 120000 index 00000000000..94760d2888d --- /dev/null +++ b/packages/web3-rpc-providers/.eslintignore @@ -0,0 +1 @@ +../../templates/.eslintignore.tmpl \ No newline at end of file diff --git a/packages/web3-rpc-providers/.eslintrc.js b/packages/web3-rpc-providers/.eslintrc.js new file mode 100644 index 00000000000..12a507e5126 --- /dev/null +++ b/packages/web3-rpc-providers/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + extends: '../../.eslintrc.js', + parserOptions: { + project: './tsconfig.esm.json', + tsconfigRootDir: __dirname, + }, +}; diff --git a/packages/web3-rpc-providers/.gitignore b/packages/web3-rpc-providers/.gitignore new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/web3-rpc-providers/.npmignore b/packages/web3-rpc-providers/.npmignore new file mode 120000 index 00000000000..8a0be70f3ed --- /dev/null +++ b/packages/web3-rpc-providers/.npmignore @@ -0,0 +1 @@ +../../templates/.npmignore.tmpl \ No newline at end of file diff --git a/packages/web3-rpc-providers/.npmrc b/packages/web3-rpc-providers/.npmrc new file mode 120000 index 00000000000..5cc817c4313 --- /dev/null +++ b/packages/web3-rpc-providers/.npmrc @@ -0,0 +1 @@ +../../templates/.npmrc.tmpl \ No newline at end of file diff --git a/packages/web3-rpc-providers/.prettierignore b/packages/web3-rpc-providers/.prettierignore new file mode 120000 index 00000000000..044e4a3df69 --- /dev/null +++ b/packages/web3-rpc-providers/.prettierignore @@ -0,0 +1 @@ +../../templates/.prettierignore.tmpl \ No newline at end of file diff --git a/packages/web3-rpc-providers/.prettierrc.json b/packages/web3-rpc-providers/.prettierrc.json new file mode 120000 index 00000000000..00ecd510aaf --- /dev/null +++ b/packages/web3-rpc-providers/.prettierrc.json @@ -0,0 +1 @@ +../../templates/.prettierrc.json.tmpl \ No newline at end of file diff --git a/packages/web3-rpc-providers/CHANGELOG.md b/packages/web3-rpc-providers/CHANGELOG.md new file mode 100644 index 00000000000..87f56484e8e --- /dev/null +++ b/packages/web3-rpc-providers/CHANGELOG.md @@ -0,0 +1,38 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + + + +## [Unreleased] diff --git a/packages/web3-rpc-providers/README.md b/packages/web3-rpc-providers/README.md new file mode 100644 index 00000000000..59284dbb29b --- /dev/null +++ b/packages/web3-rpc-providers/README.md @@ -0,0 +1,58 @@ +

+ web3.js +

+ +# web3.js - Web3 Providers + +![ES Version](https://img.shields.io/badge/ES-2020-yellow) +![Node Version](https://img.shields.io/badge/node-14.x-green) +[![NPM Package][npm-image]][npm-url] +[![Downloads][downloads-image]][npm-url] + +This is a sub-package of [web3.js][repo]. + + +## Installation + +You can install the package either using [NPM](https://www.npmjs.com/package/web3-rpc-providers) or using [Yarn](https://yarnpkg.com/package/web3-rpc-providers) + +### Using NPM + +```bash +npm install web3-rpc-providers +``` + +### Using Yarn + +```bash +yarn add web3-rpc-providers +``` + +## Getting Started + +- :writing_hand: If you have questions [submit an issue](https://github.com/ChainSafe/web3.js/issues/new) or join us on [Discord](https://discord.gg/yjyvFRP) + ![Discord](https://img.shields.io/discord/593655374469660673.svg?label=Discord&logo=discord) + +## Prerequisites + +- :gear: [NodeJS](https://nodejs.org/) (LTS/Fermium) +- :toolbox: [Yarn](https://yarnpkg.com/)/[Lerna](https://lerna.js.org/) + +## Package.json Scripts + +| Script | Description | +| ---------------- | -------------------------------------------------- | +| clean | Uses `rimraf` to remove `dist/` | +| build | Uses `tsc` to build package and dependent packages | +| lint | Uses `eslint` to lint package | +| lint:fix | Uses `eslint` to check and fix any warnings | +| format | Uses `prettier` to format the code | +| test | Uses `jest` to run unit tests | +| test:integration | Uses `jest` to run tests under `/test/integration` | +| test:unit | Uses `jest` to run tests under `/test/unit` | + +[docs]: https://docs.web3js.org/ +[repo]: https://github.com/web3/web3.js/tree/4.x/tools/web3-rpc-providers +[npm-image]: https://img.shields.io/github/package-json/v/web3/web3.js/4.x?filename=tools%2Fweb3-rpc-providers%2Fpackage.json +[npm-url]: https://npmjs.org/package/web3-rpc-providers +[downloads-image]: https://img.shields.io/npm/dm/web3-rpc-providers?label=npm%20downloads diff --git a/packages/web3-rpc-providers/assets/logo/web3js.ai b/packages/web3-rpc-providers/assets/logo/web3js.ai new file mode 100644 index 00000000000..669ef50e7cd --- /dev/null +++ b/packages/web3-rpc-providers/assets/logo/web3js.ai @@ -0,0 +1,1516 @@ +%PDF-1.5 % +1 0 obj <>/OCGs[5 0 R 6 0 R 29 0 R 30 0 R]>>/Pages 3 0 R/Type/Catalog>> endobj 2 0 obj <>stream + + + + + application/pdf + + + Print + + + + + 2017-01-27T15:51:37Z + 2017-01-27T15:51:37Z + 2017-01-27T14:51:33Z + Adobe Illustrator CS6 (Macintosh) + + + + 256 + 240 + JPEG + /9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgA8AEAAwER AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE 1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp 0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo +DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A7F+an5hy6Ov6F0qTjqMq VubhTvCjDYL4Ow3r2Hz2IQ8x8teevMXl+cvaXBlgdi01pMS8Tk7k0rUMfFTXCr2Xyl+Z/l/X+FvI 31DUWoPqszCjn/iuTYN8tj7YKSzDArsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirs VdirsVdirsVdirsVdirsVdir5W1nUptU1a71CYkvdSvKa9gx2H0DbJIQeKtqrMwVQWZjRVG5JPYY q+ify70jzPpujKmvXrTu4BgtX+NoFp9lpDuT/k9BgKWV4FdirsVdirsVdirsVdirsVdirsVdirsV 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 + + + + + + uuid:394c157d-8cf0-f94e-8261-98ccb840e1bc + xmp.did:106820F817276811822ACF3CAA06C913 + uuid:5D20892493BFDB11914A8590D31508C8 + proof:pdf + + uuid:1898a391-1dba-4249-9e7f-8804d46504b0 + xmp.did:FE7F11740720681183D1839CF7E6F44E + uuid:5D20892493BFDB11914A8590D31508C8 + proof:pdf + + + + + saved + xmp.iid:FE7F11740720681183D1839CF7E6F44E + 2017-01-06T15:27:37Z + Adobe Illustrator CS6 (Macintosh) + / + + + saved + xmp.iid:106820F817276811822ACF3CAA06C913 + 2017-01-27T14:51:33Z + Adobe Illustrator CS6 (Macintosh) + / + + + + + + Document + Print + + + False + False + 1 + + 3840.000000 + 2160.000000 + Pixels + + + + Cyan + Magenta + Yellow + Black + + + + + + Default Swatch Group + 0 + + + + White + RGB + PROCESS + 255 + 255 + 255 + + + Black + RGB + PROCESS + 35 + 31 + 32 + + + CMYK Red + RGB + PROCESS + 237 + 28 + 36 + + + CMYK Yellow + RGB + PROCESS + 255 + 242 + 0 + + + CMYK Green + RGB + PROCESS + 0 + 166 + 81 + + + CMYK Cyan + RGB + PROCESS + 0 + 174 + 239 + + + CMYK Blue + RGB + PROCESS + 46 + 49 + 146 + + + CMYK Magenta + RGB + PROCESS + 236 + 0 + 140 + + + C=15 M=100 Y=90 K=10 + RGB + PROCESS + 190 + 30 + 45 + + + C=0 M=90 Y=85 K=0 + RGB + PROCESS + 239 + 65 + 54 + + + C=0 M=80 Y=95 K=0 + RGB + PROCESS + 241 + 90 + 41 + + + C=0 M=50 Y=100 K=0 + RGB + PROCESS + 247 + 148 + 30 + + + C=0 M=35 Y=85 K=0 + RGB + PROCESS + 251 + 176 + 64 + + + C=5 M=0 Y=90 K=0 + RGB + PROCESS + 249 + 237 + 50 + + + C=20 M=0 Y=100 K=0 + RGB + PROCESS + 215 + 223 + 35 + + + C=50 M=0 Y=100 K=0 + RGB + PROCESS + 141 + 198 + 63 + + + C=75 M=0 Y=100 K=0 + RGB + PROCESS + 57 + 181 + 74 + + + C=85 M=10 Y=100 K=10 + RGB + PROCESS + 0 + 148 + 68 + + + C=90 M=30 Y=95 K=30 + RGB + PROCESS + 0 + 104 + 56 + + + C=75 M=0 Y=75 K=0 + RGB + PROCESS + 43 + 182 + 115 + + + C=80 M=10 Y=45 K=0 + RGB + PROCESS + 0 + 167 + 157 + + + C=70 M=15 Y=0 K=0 + RGB + PROCESS + 39 + 170 + 225 + + + C=85 M=50 Y=0 K=0 + RGB + PROCESS + 28 + 117 + 188 + + + C=100 M=95 Y=5 K=0 + RGB + PROCESS + 43 + 57 + 144 + + + C=100 M=100 Y=25 K=25 + RGB + PROCESS + 38 + 34 + 98 + + + C=75 M=100 Y=0 K=0 + RGB + PROCESS + 102 + 45 + 145 + + + C=50 M=100 Y=0 K=0 + RGB + PROCESS + 146 + 39 + 143 + + + C=35 M=100 Y=35 K=10 + RGB + PROCESS + 158 + 31 + 99 + + + C=10 M=100 Y=50 K=0 + RGB + PROCESS + 218 + 28 + 92 + + + C=0 M=95 Y=20 K=0 + RGB + PROCESS + 238 + 42 + 123 + + + C=25 M=25 Y=40 K=0 + RGB + PROCESS + 194 + 181 + 155 + + + C=40 M=45 Y=50 K=5 + RGB + PROCESS + 155 + 133 + 121 + + + C=50 M=50 Y=60 K=25 + RGB + PROCESS + 114 + 102 + 88 + + + C=55 M=60 Y=65 K=40 + RGB + PROCESS + 89 + 74 + 66 + + + C=25 M=40 Y=65 K=0 + RGB + PROCESS + 196 + 154 + 108 + + + C=30 M=50 Y=75 K=10 + RGB + PROCESS + 169 + 124 + 80 + + + C=35 M=60 Y=80 K=25 + RGB + PROCESS + 139 + 94 + 60 + + + C=40 M=65 Y=90 K=35 + RGB + PROCESS + 117 + 76 + 41 + + + C=40 M=70 Y=100 K=50 + RGB + PROCESS + 96 + 57 + 19 + + + C=50 M=70 Y=80 K=70 + RGB + PROCESS + 60 + 36 + 21 + + + + + + Grays + 1 + + + + C=0 M=0 Y=0 K=100 + RGB + PROCESS + 35 + 31 + 32 + + + C=0 M=0 Y=0 K=90 + RGB + PROCESS + 65 + 64 + 66 + + + C=0 M=0 Y=0 K=80 + RGB + PROCESS + 88 + 89 + 91 + + + C=0 M=0 Y=0 K=70 + RGB + PROCESS + 109 + 110 + 113 + + + C=0 M=0 Y=0 K=60 + RGB + PROCESS + 128 + 130 + 133 + + + C=0 M=0 Y=0 K=50 + RGB + PROCESS + 147 + 149 + 152 + + + C=0 M=0 Y=0 K=40 + RGB + PROCESS + 167 + 169 + 172 + + + C=0 M=0 Y=0 K=30 + RGB + PROCESS + 188 + 190 + 192 + + + C=0 M=0 Y=0 K=20 + RGB + PROCESS + 209 + 211 + 212 + + + C=0 M=0 Y=0 K=10 + RGB + PROCESS + 230 + 231 + 232 + + + C=0 M=0 Y=0 K=5 + RGB + PROCESS + 241 + 242 + 242 + + + + + + Brights + 1 + + + + C=0 M=100 Y=100 K=0 + RGB + PROCESS + 237 + 28 + 36 + + + C=0 M=75 Y=100 K=0 + RGB + PROCESS + 242 + 101 + 34 + + + C=0 M=10 Y=95 K=0 + RGB + PROCESS + 255 + 222 + 23 + + + C=85 M=10 Y=100 K=0 + RGB + PROCESS + 0 + 161 + 75 + + + C=100 M=90 Y=0 K=0 + RGB + PROCESS + 33 + 64 + 154 + + + C=60 M=90 Y=0 K=0 + RGB + PROCESS + 127 + 63 + 152 + + + + + + + + + Adobe PDF library 10.01 + + + + + + + + + + + + + + + + + + + + + + + + + endstream endobj 3 0 obj <> endobj 8 0 obj <>/Resources<>/ExtGState<>/Properties<>>>/Thumb 36 0 R/TrimBox[0.0 0.0 3840.0 2160.0]/Type/Page>> endobj 32 0 obj <>stream +HlVI9 +TK"cN(rh4P@A*n(EJ\A*z/ϑ>Lۯ-RN%7޾[+ELD}~Q_,RC)i%mR=V{uS¡,YHzeۓ Q!5nJ9P5"v[ uWvU7nێ,FP^$$5DDpɁd4ڋۙ90q|dDZ a1439<0}f0{ꖐhE#R 5Y9$ +zX]@~3ϋ̬3L>س|cΏs%sZNVuAcp~Rc阏b^Aй><\I/wP;bJ@|n[fDڍ^ -[D@Dňށ(TIfйkUE'Gx"/Þ!QLwBq:p.RZ[Yh=j{9 ACIY8w;vuu-ӹ2/;@r fdk6z1FMǯk׊x]*C1ylDTAœu&4`pv)5bǸ+ +VEC04,Tp9p)1Rِ9ֿmXѭxhPxʐke&ډAeL9Jl1|)Y|zf*ѷ.G%:o]~Ljh(eMBC#\fch\ij\mr#Jܢo;oَ?I >stream +8;Z]!gMI$9&4O4Loo+g]Y:Y;L9GQ$:@3.,T.n*;fRief@%Sif_3dV)Ok+/'6SR3bl +9q7Fhkme7N\oK:^?"i4k6BkiO2r#nub+]#^#o2T&%;/3"U%t=#DK/;5(hd<.rJl^nXukH^04p_5&"H=J0K1J +F,$ endstream endobj 37 0 obj [/Indexed/DeviceRGB 255 38 0 R] endobj 38 0 obj <>stream +8;X]O>EqN@%''O_@%e@?J;%+8(9e>X=MR6S?i^YgA3=].HDXF.R$lIL@"pJ+EP(%0 +b]6ajmNZn*!='OQZeQ^Y*,=]?C.B+\Ulg9dhD*"iC[;*=3`oP1[!S^)?1)IZ4dup` +E1r!/,*0[*9.aFIR2&b-C#soRZ7Dl%MLY\.?d>Mn +6%Q2oYfNRF$$+ON<+]RUJmC0InDZ4OTs0S!saG>GGKUlQ*Q?45:CI&4J'_2j$XKrcYp0n+Xl_nU*O( +l[$6Nn+Z_Nq0]s7hs]`XX1nZ8&94a\~> endstream endobj 29 0 obj <> endobj 30 0 obj <> endobj 41 0 obj [/View/Design] endobj 42 0 obj <>>> endobj 39 0 obj [/View/Design] endobj 40 0 obj <>>> endobj 35 0 obj <> endobj 34 0 obj [/ICCBased 43 0 R] endobj 43 0 obj <>stream +HyTSwoɞc [5laQIBHADED2mtFOE.c}08׎8GNg9w߽'0 ֠Jb  + 2y.-;!KZ ^i"L0- @8(r;q7Ly&Qq4j|9 +V)gB0iW8#8wթ8_٥ʨQQj@&A)/g>'Kt;\ ӥ$պFZUn(4T%)뫔0C&Zi8bxEB;Pӓ̹A om?W= +x-[0}y)7ta>jT7@tܛ`q2ʀ&6ZLĄ?_yxg)˔zçLU*uSkSeO4?׸c. R ߁-25 S>ӣVd`rn~Y&+`;A4 A9=-tl`;~p Gp| [`L`< "A YA+Cb(R,*T2B- +ꇆnQt}MA0alSx k&^>0|>_',G!"F$H:R!zFQd?r 9\A&G rQ hE]a4zBgE#H *B=0HIpp0MxJ$D1D, VĭKĻYdE"EI2EBGt4MzNr!YK ?%_&#(0J:EAiQ(()ӔWT6U@P+!~mD eԴ!hӦh/']B/ҏӿ?a0nhF!X8܌kc&5S6lIa2cKMA!E#ƒdV(kel }}Cq9 +N')].uJr + wG xR^[oƜchg`>b$*~ :Eb~,m,-ݖ,Y¬*6X[ݱF=3뭷Y~dó ti zf6~`{v.Ng#{}}jc1X6fm;'_9 r:8q:˜O:ϸ8uJqnv=MmR 4 +n3ܣkGݯz=[==<=GTB(/S,]6*-W:#7*e^YDY}UjAyT`#D="b{ų+ʯ:!kJ4Gmt}uC%K7YVfFY .=b?SƕƩȺy چ k5%4m7lqlioZlG+Zz͹mzy]?uuw|"űNwW&e֥ﺱ*|j5kyݭǯg^ykEklD_p߶7Dmo꿻1ml{Mś nLl<9O[$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD-u`ֲK³8%yhYѹJº;.! +zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)Km endstream endobj 33 0 obj <> endobj 44 0 obj <> endobj 45 0 obj <>stream +%!PS-Adobe-3.0 %%Creator: Adobe Illustrator(R) 16.0 %%AI8_CreatorVersion: 16.0.0 %%For: (Ian Meikle) () %%Title: (Web3_70.ai) %%CreationDate: 27/01/2017 15:51 %%Canvassize: 16383 %%BoundingBox: 1170 -1782 2670 -378 %%HiResBoundingBox: 1170 -1781.6396 2670 -378.3604 %%DocumentProcessColors: Cyan Magenta Yellow Black %AI5_FileFormat 12.0 %AI12_BuildNumber: 682 %AI3_ColorUsage: Color %AI7_ImageSettings: 0 %%RGBProcessColor: 0 0 0 ([Registration]) %AI3_Cropmarks: 0 -2160 3840 0 %AI3_TemplateBox: 1920.5 -1080.5 1920.5 -1080.5 %AI3_TileBox: 1517 -1359.5 2300 -800.5 %AI3_DocumentPreview: None %AI5_ArtSize: 14400 14400 %AI5_RulerUnits: 6 %AI9_ColorModel: 1 %AI5_ArtFlags: 0 0 0 1 0 0 1 0 0 %AI5_TargetResolution: 800 %AI5_NumLayers: 2 %AI9_OpenToView: -1717.0015 636.9985 0.3333 2078 1150 18 0 0 32 191 0 0 0 1 1 0 1 1 0 1 %AI5_OpenViewLayers: 77 %%PageOrigin:1614 -1476 %AI7_GridSettings: 72 8 72 8 1 0 0.8 0.8 0.8 0.9 0.9 0.9 %AI9_Flatten: 1 %AI12_CMSettings: 00.MS %%EndComments endstream endobj 46 0 obj <>stream +%%BoundingBox: 1170 -1782 2670 -378 %%HiResBoundingBox: 1170 -1781.6396 2670 -378.3604 %AI7_Thumbnail: 128 120 8 %%BeginData: 14636 Hex Bytes %0000330000660000990000CC0033000033330033660033990033CC0033FF %0066000066330066660066990066CC0066FF009900009933009966009999 %0099CC0099FF00CC0000CC3300CC6600CC9900CCCC00CCFF00FF3300FF66 %00FF9900FFCC3300003300333300663300993300CC3300FF333300333333 %3333663333993333CC3333FF3366003366333366663366993366CC3366FF %3399003399333399663399993399CC3399FF33CC0033CC3333CC6633CC99 %33CCCC33CCFF33FF0033FF3333FF6633FF9933FFCC33FFFF660000660033 %6600666600996600CC6600FF6633006633336633666633996633CC6633FF %6666006666336666666666996666CC6666FF669900669933669966669999 %6699CC6699FF66CC0066CC3366CC6666CC9966CCCC66CCFF66FF0066FF33 %66FF6666FF9966FFCC66FFFF9900009900339900669900999900CC9900FF %9933009933339933669933999933CC9933FF996600996633996666996699 %9966CC9966FF9999009999339999669999999999CC9999FF99CC0099CC33 %99CC6699CC9999CCCC99CCFF99FF0099FF3399FF6699FF9999FFCC99FFFF %CC0000CC0033CC0066CC0099CC00CCCC00FFCC3300CC3333CC3366CC3399 %CC33CCCC33FFCC6600CC6633CC6666CC6699CC66CCCC66FFCC9900CC9933 %CC9966CC9999CC99CCCC99FFCCCC00CCCC33CCCC66CCCC99CCCCCCCCCCFF %CCFF00CCFF33CCFF66CCFF99CCFFCCCCFFFFFF0033FF0066FF0099FF00CC %FF3300FF3333FF3366FF3399FF33CCFF33FFFF6600FF6633FF6666FF6699 %FF66CCFF66FFFF9900FF9933FF9966FF9999FF99CCFF99FFFFCC00FFCC33 %FFCC66FFCC99FFCCCCFFCCFFFFFF33FFFF66FFFF99FFFFCC110000001100 %000011111111220000002200000022222222440000004400000044444444 %550000005500000055555555770000007700000077777777880000008800 %000088888888AA000000AA000000AAAAAAAABB000000BB000000BBBBBBBB %DD000000DD000000DDDDDDDDEE000000EE000000EEEEEEEE0000000000FF %00FF0000FFFFFF0000FF00FFFFFF00FFFFFF %524C45FFFFFFA87D7DFD7CFFA8FD0452A8FD79FFA87D527D527D527DA8FD %77FF7D525352525253525259FD76FF527D527D527D527D527D52A8AFFD72 %FF7D52527D5252527D52525259527DA8FD71FF7D527D527D527D527D527D %527DA8FD72FF52535252525352525253527DA8FD39FFCACAA1C3A0C2A0C2 %A0C3A1CACAFD2DFF7D527D527D527D527D527DA8FD37FFC3C3BBBBBABBB4 %BBB4BBBABB92BBBBBBC2C9CAFD2AFF527D5252527DFD04527DFD35FFA1C2 %98BA92BB92BB92BB98BB92BB98BB92BB92BA92BB99CAFD28FF7D527D527D %527D527D52FD33FFCAC9BBBA92BBBBBB98BBBBBB98BBBBBB98BBBBBB98BB %BBBB98BBB4C2C9FD26FF5252525352525253527DFD0CFFA87D7DFD23FFA0 %BB92BB92BB92BB92BB92BB92BB92BB92BB92BB92BB92BB92BB92BB92BA99 %CAFD24FF7D527D527D527D52537DFD0BFFA87D525352A8FD1FFFCABBBBBA %BBBBBBBABBBBBBBABBBBBBBABBBBBBBABBBBBBBABBBBBBBABBBBBBBABBBA %C9FD23FF5252527D5252527D52A8FD0AFFA852527D5252527DA8FD1BFFCA %C292BB98BB92BB98BB92BB98BB92BB98BB92BB92BB92BB98BB92BB98BB92 %BB98BB92BB92C2CAFD21FF7D527D527D527D5253A8FD0AFF7D527D527D52 %7D52537DFD19FFC2BBB4BB98BBBBBB98BBBBBB98BBBBBB98BBB4BB92BBB4 %BA92BBBBBB98BBBBBB98BBBBBB98BBB4BBCAFD20FF525352525253525252 %A8FD09FFA8525352525253FD05527DA8FD14FFC998BA92BB92BB92BB92BB %92BB92BB92BB92BA99C3C3CAA7C9A0BB92BB92BB92BB92BB92BB92BB92BB %92BBA8FD1FFF7D527D527D527D5259A8FD09FF7D7D527D527D527D527D52 %7D527DFD12FFC9C2B4BBBABBBBBBBABBBBBBBABBBBBBBABBB4C2C9FD08FF %C9BBBBBABBBBBBBABBBBBBBABBBBBBB4C2FD1FFF527D5252527D525252A8 %FD09FF7D527D5252527D5252527D527DA8FD10FFCF9ABA92BB98BB92BB98 %BB92BB98BB92BB92BA98C9FD0BFFCF99BB92BB98BB92BB98BB92BB98BB92 %C3CAFD1DFF7D527D527D527D52527DFD09FF527D527D527D527D527D527D %FD11FFC398BBBABB98BBBBBB98BBBBBB98BBBBBB92BBC2FD0EFFC9B4BB98 %BBBBBB98BBBBBB98BBBBBB92BBBBC2C3CFFD19FF525252535252525352A8 %FD08FFA85952525253525252535252A8FD0FFFA1BB92BB92BB92BB92BB92 %BB92BB92BB92BB92C2A8FD0FFFA1BA92BB92BB92BB92BB92BB92BB92BB92 %BB92BA92C2C3FD17FF7D527D527D527D52527EFD09FF527D527D527D527D %52537DFD0EFFCABBBBBABBBABBBBBBBABBBBBBBABBBBBBBABBBBCAFD10FF %CFC2BABBBABBBBBBBABBBBBBBABBBBBBBABBBBBBBABBBABBBBC9FD15FF52 %52527D5252527D52A8FD08FFA87D5252527D5252525952FD0DFFA8C2B4BA %92BB98BB92BB98BB92BB98BB92BB92BBA0FD11FFCABB92BB98BB92BB98BB %92BB98BB92BB98BB92BB98BB92BB98BB92BBC3FD13FF7D527D527D527D52 %53A8FD09FF527D527D527D527D527DFD0CFFA87D75BBBABB98BBBBBB98BB %BBBB98BBBBBB92C3CFFD11FFC2BBBABB98BBBBBB98BBBBBB98BBBBBB98BB %BBBB98BBBBBB98BBBBBB92BBBBCAFD11FF525352525253525252A8FD08FF %A85252535252525352527DFD0BFF7D525253527698BA92BB92BB92BB92BB %92BA99CAFD11FFC999BA92BB92BB92BB92BB92BB92BB92BB92BB92BB92BB %92BB92BB92BB92BB92BB92C2CAFD0FFF7D527D527D527D5259A8FD09FF52 %7D527D527D527D52A8FD0AFFA87D527D527D537D99BBBABBBABBBBBB92C1 %C9FD11FFCAC2B4BBBABBBBBBBABBBBBBBABBBBBBBABBBBBBBABBBBBBBABB %BBBBBABBBBBBBABBBBBB92C2CAFD0EFF527D5252527D525252A8FD08FFA8 %53527D5252527D52527DFD0AFF7D527D5252527D52535299B4BB92BA98C3 %CAFD11FFC2BA92BB98BB92BB98BB92BB98BB92BB92BA92BB92BB92BA92BB %92BB98BB92BB98BB92BB98BB92BBCAFD0DFF7D527D527D527D52527DFD09 %FF527D527D527D527D52A8FD09FFA8527D527D527D527D5259527C99BBC2 %FD12FFC998BBBABB98BBBBBB98BBBBBB98BBBBBB92BBBBC9C9CFCACAC2C1 %B4BB98BBBBBB98BBBBBB98BBBBBB92BBCAFD0CFF525252535252525352A8 %FD08FFA85952525253FD04527DFD09FF59FD0452535252525352522E7DA8 %FD11FFA1BB92BB92BB92BB92BB92BB92BB92BB92BB92C2A7FD07FFCAC998 %BA92BB92BB92BB92BB92BB92BB92C1FD0CFF7D527D527D527D52527EFD09 %FF527D527D527D527D52A8FD09FF7D527D527D527D527D527D527DFD11FF %CFBBBBBABBBABBBBBBBABBBBBBBABBBBBBBABBBBCAFD0BFFCFFD04BBBABB %BBBBBABBBBBBBABBB4C9FD0BFF5252527D5252527D52A8FD08FFA87D5252 %527DFD04527DFD09FF52595252527D5252527D527DFD10FFCAC292BA92BB %98BB92BB98BB92BB98BB92BB92BBA0FD0EFFC992BB98BB92BB98BB92BB98 %BB92BB99FD0BFF7D527D527D527D5253A8FD09FF527D527D527D527D52A8 %FD08FFA87D527D527D527D527D527DFD10FFC3BB92BBBBBB98BBBBBB98BB %BBBB98BBBBBB92C2CAFD0FFFC3BB98BBBBBB98BBBBBB98BBBBBB92C2FD0B %FF525352525253525252A8FD08FFA85252535252525352527DFD09FF5252 %52535252525352527DFD0EFFCA99BA92BB92BB92BB92BB92BB92BB92BB92 %BA99CAFD10FFA8BB92BB92BB92BB92BB92BB92BB92BA99FD0BFF7D527D52 %7D527D5259A8FD09FF527D527D527D527D52A8FD09FF7D527D527D527D52 %7D52FD0DFFCFC292BBBBBBBABBBBBBBABBBBBBBABBBBBB92BBC9FD11FFCA %C1BABBBABBBBBBBABBBBBBBABBBBBB92C9FD0BFF527D5252527D525252A8 %FD08FFA853527D5252527D52527DFD09FF5252527D5252527D527DFD0EFF %C2BB92BB98BB92BB98BB92BB98BB92BA92C3CAFD11FFC2BB92BB98BB92BB %98BB92BB98BB92BB92BBCAFD0BFF7D527D527D527D52527DFD09FF527D52 %7D527D527D52A8FD08FFA87D527D527D527D52537EFD10FFC398BBBABB98 %BBBBBB98BBBABBBCFD12FFC998BBBABB98BBBBBB98BBBBBB98BBBBBB92BB %CAFD0CFF525252535252525352A8FD08FFA85952525253FD04527DFD09FF %FD055253525252A8FD11FFCA99BA92BB92BB92BA92BBC9FD11FFA1BB92BB %92BB92BB92BB92BB92BB92BB92BB92BBA8FD0DFF7D527D527D527D52527E %FD09FF527D527D527D527D52A8FD08FFA87D527D527D527D5259A8FD13FF %C9C292FD04BBC9FD11FFCFBCBBBABBBABBBBBBBABBBBBBBABBBBBBBABBBB %CAFD0FFF5252527D5252527D52A8FD08FFA87D5252527DFD04527DFD09FF %52595252527D525252A8FD15FFC992BBC2FD11FFCAC392BA92BB98BB92BB %98BB92BB98BB92BB92BBA0FD11FF7D527D527D527D5253A8FD09FF527D52 %7D527D527D52A8FD08FFA87D527D527D527D52527DFD17FFCAFD11FFC3BB %92BBBBBB98BBBBBB98BBBBBB98BBBBBB92C2CAFD12FF7DFD045253525252 %A8FD08FFA85252535252525352527DFD09FF525252535252525352A8FD27 %FFCA99BA92BB92BB92BB92BB92BB92BB92BB92BA99CAFD14FFA8527D527D %527D5259A8FD09FF527D527D527D527D52A8FD09FF7D527D527D527D5252 %7EFD25FFCAC2B4BBBBBBBABBBBBBBABBBBBBBABBBBBBB4BBC3FD16FFA853 %5252527D525252A8FD08FFA853527D5252527D52527DFD09FF5252527D52 %52527D52A8FD24FFA0BB92BB92BB98BB92BB98BB92BB98BB92BB92C2CAFD %18FF527D527D527D52527DFD09FF527D527D527D527D52A8FD08FFA87D52 %7D527D527D5253A8FD22FFCABBBA92BBBBBB98BBBBBB98BBBBBB98BBBABB %BBCFFD1AFF7D525352525253527DA8FD07FFA85952525253FD04527DFD09 %FFFD055253525252A8FD20FFA8BB92BB92BB92BB92BB92BB92BB92BB92BB %92BBC9FD1CFFA87D527D527D527D52FD09FF527D527D527D527D52A8FD08 %FFA87D527D527D527D5259A8FD1FFFA8A8A1C2BABBBABBBBBBBABBBBBBBA %FD04BBC9FD1FFF52535252527D52527DFD07FFA87D5252527DFD04527DFD %09FF52595252527D525252A8FD1EFFA8A87DA87DA199BA92BB98BB92BB98 %BB92BBC2FD21FF7E527D527D527D5252A8FD07FF527D527D527D527D52A8 %FD08FFA87D527D527D527D52527DFD1DFFA8A87DA87EA87EA8A0BBB4BBBB %BB98BBB4C2CAFD22FFA8525253525252535252A8FD05FFA8525253525252 %5352527DFD09FF525252535252525352A8FD08FFA8A8A8FD11FFA8A87DA8 %7DA87DA87DA87DA092BB92BA99C9FD25FF7D7D527D527D527D527DA8FD04 %FFA8527D527D527D527D52A8FD09FF7D527D527D527D52527EFD09FF7EA8 %7EFD11FF7DA87DA884A87DA884A884A799BBC2FD27FFA852595252527DFD %04527DA8A8A85252527D5252527D52527DFD09FF5252527D5252527D52A8 %FD08FFA8A87DA87DA8A8FD0DFF7DA87DA87DA87DA87DA87DA87DA8CAFD29 %FF7E527D527D527D527D5259527D527D527D527D527D527D52A8FD08FFA8 %7D527D527D527D5253A8FD09FF7DA87EA87DA8A8FD0CFFA87DA87EA87DA8 %7EA87DA87DA8FD2BFFA853525352525253525252535252525352525253FD %04527DFD09FFFD055253525252A8FD08FFA8A87DA87DA87DA87DA8A8FD09 %FF7DA87DA87DA87DA87DA87DA8FD2DFFA87D527D527D527D527D527D527D %527D527D527D527D52A8FD08FFA87D527D527D527D5259A8FD09FF7DA884 %A87DA884A87DFD0AFFA87DA884A87DA884A87DA8FD2FFF7DFD04527D5252 %527D5252527D5252527DFD04527DFD09FF52595252527D525252A8FD08FF %A8A87DA87DA87DA87D84A8FD09FF7DA87DA87DA87DA87D84A8FD30FF7D53 %527D527D527D527D527D527D527D527D527D527DFD08FFA87D527D527D52 %7D52527DFD09FF7EA87DA87EA87DA87DFD09FFA8A87DA87DA87EA87DA8A8 %FD32FFFD055253525252535252525352525253525252A8FD08FF52525253 %5252525352A8FD08FFA8A87DA87DA87DA87DA8A8FD09FF7DA87DA87DA87D %A87DA8FD33FF7D52527D527D527D527D527D527D527D527D527D7DFD08FF %7D527D527D527D52527EFD09FF7EA87DA884A87DA87DFD09FFA8A87EA87D %A884A87DA8A8FD34FF7D52527D5252527D5252527D5252527DFD0452A8FD %07FF5252527D5252527D52A8FD08FFA8A87DA87DA87DA87DA8A8FD09FF7D %A87DA87DA87DA87DFD36FFA859527D527D527D527D527D527D527D527D52 %7DA8FD05FFA87D527D527D527D5253A8FD0BFF7DA87DA87EA87DFD0AFFA8 %7DA87EA87DA87EA8A8FD0DFFFD05A8A9A8FD22FFA87DFD05525352525253 %5252525352525259A8FD04FF7D525352525253525252A8FD0CFFA87E7DA8 %7D7EA8FD09FF7DA87DA87DA87DA87DA9FD0CFF7DA87D847DA87D847DA8A8 %FD21FFA85953527D527D527D527D527D527D527D52597DFFFFA8527D527D %527D527D5259A8FD0DFFA8A87DA87DFD0AFFA87DA884A87DA884A8A8FD0B %FF7DA884A87DA884A87DA87DA8A8FD22FFA87DFD0552595252527D525252 %7D5252527D5252527D5252527D525252A8FD10FF7D7DA8FD09FF7DA87DA8 %7DA87DA87DFD0BFF7E847DA87DA87DA87DA87DA87D7E7DFD24FFFD05A87D %527D527D527D527D527D527D527D527D527D527D52527DFD11FFA8FD09FF %A8A87DA87DA87EA87DA8A8FD09FFA8A87EA87DA87EA87DA87EA87DA87EA8 %7DA8A8FD26FF84FD0452535252525352525253525252535252525352A8FD %1CFF7DA87DA87DA87DA87DFD0AFFA87DA87DA87DA87DA87DA87DA87DA87D %A87DA8A8FD26FF7D52527D527D527D527D527D527D527D527D527D5259A8 %FD1BFFA8A87EA87DA884A87DA8A8FD09FFA8A884A87DA884A87DA884A87D %A884A87DA87EA87DFD26FF7D52527D5252527D5252527D5252527D525252 %5952A8FD1CFF7DA87DA87DA87DA87DFD0AFFA87DA87DA87DA87DA87DA87D %A87DA87DA87DA87DA87DA8A8FD24FF7D52527D527D527D527D527D527D52 %7D527D527DFD1DFFA87DA87EA87DA87EA8A8FD09FF7EA87DA87EA87DA87E %A87DA87EA87DA87EA87DA87EA87DA8A8FD24FF7D52525352525253525252 %5352525253525253FD1DFF7DA87DA87DA87DA87DA9FD08FFA8A87DA87DA8 %7DA87DA87DA87DA87DA87DA87DA87DA87DA87DA87DA8A8FD22FF7D7D527D %527D527D527D527D527D527D52A8FD0AFFA8FD12FFA87DA884A87DA884A8 %A8FD09FF7EA87DA884A87DA884A87DA884A87DA884A87DA884A87DA884A8 %7DA8A8FD22FF7D535252527D5252527D5252527D5253A8FD09FFA8847EFD %11FF7DA87DA87DA87DA87DFD09FFA8A87DA87DA87DA87DA87DA87DA87DA8 %7DA87DA87DA87DA87DA87DA87DA87DFD22FFA87D5253527D527D527D527D %5252A8FD0BFF84A87DAFFD0EFFA8A87DA87DA87EA87DA8A8FD09FF7DA87E %A87DA87EA87DA8A8FFA8A87DA87DA87EA87DA87EA87DA87EA87DA87DA8A8 %FD21FFA8525252535252525352527DFD0CFFA87DA87DA8A8FD0DFF7DA87D %A87DA87DA87DFD09FFA8A87DA87DA87DA87D847DFFFFFFA8A87D7E7DA87D %A87DA87DA87DA87DA87DA87DA8FD23FFA87D52595259527D7DFD0DFFA8A8 %7DA87DA8A8FD0BFFA8A87EA87DA884A87DA8A8FD09FF84A884A87DA884A8 %7DFD07FFA8A87DA87DA884A87DA884A87DA884A87DFD26FFA8A87DA8A8FD %0EFFA87DA87DA87D847DA8FD0AFF7DA87DA87DA87DA87DFD0AFFA87DA87D %A87DA87D84A8FD07FFA8A87DA87DA87DA87DA87DA87DA87DA8FD39FFA8A8 %7DA87DA87EA87DFD0AFFA87DA87EA87DA87EA8A8FD09FFA8A87DA87EA87D %A87DFD0BFFA8A87DA87EA87DA87EA87DA87EFD3AFF7DA87DA87DA87D7EA8 %FD09FF7DA87DA87DA87DA87DA9FD0AFF7DA87DA87DA87DA8A8FD0BFFA8A8 %7DA87DA87DA87DA87DA8FD3AFFA87DA87DA884A87DA8FD09FFA87DA884A8 %7DA884A8A8FD0AFFA87DA884A87DA87DA8FD0DFFA87DA87DA884A87DA884 %FD3AFFA8A87DA87DA87DA87DFD09FF7DA87DA87DA87DA87DFD0BFFA8847D %A87DA87DA87DFD0FFF7E847DA87DA87DA8FD3BFF7DA87EA87DA87EA8A8FD %07FFA8A87DA87DA87EA87DA8A8FD0BFF7DA87DA87EA87DA8A8FD0FFFA8A8 %7DA87EA87DFD3BFFA87DA87DA87DA87D7EA8FD07FF7DA87DA87DA87DA87D %FD0CFFA87DA87DA87DA87DA8A8FD10FFA87DA87DA8FD3BFFA8A87EA87DA8 %84A87DA8FD06FFA8A884A87DA884A87DA8A8FD0BFFA8A87DA884A87DA87D %A8A9FD11FFA8A87DFD3CFF7DA87DA87DA87DA87DA8A8FD04FFA87DA87DA8 %7DA87DA87DFD0DFF7E847DA87DA87DA87DA8A8FD11FFA8A8FD3DFF7DA87E %A87DA87EA87DA8A8FFA8FF7DA87DA87EA87DA87EA8A8FD0DFF7DA87DA87E %A87DA87DA8A8FD4FFFA87DA87DA87DA87DA87DA87DA87DA87DA87DA87DA8 %7DA87DA9FD0DFFA87DA87DA87DA87DA87D7E7DA8FD4EFFA87DA87DA884A8 %7DA884A87DA884A87DA884A87DA884A8A8FD0EFFA87DA884A87DA884A87D %A87DA8A8FD4CFFA8A87DA87DA87DA87DA87DA87DA87DA87DA87DA87DA87D %FD0FFFA8A87DA87DA87DA87DA87DA87D7E7DFD4CFFA8A87EA87DA87EA87D %A87EA87DA87EA87DA87EA87DA8A8FD0FFFA8A87DA87EA87DA87EA87DA87E %A87DA8FD4BFF7DA87DA87DA87DA87DA87DA87DA87DA87DA87DA87DFD11FF %A87D7DA87DA87DA87DA87DA87DA87DA8A8FD4AFFA8A87DA884A87DA884A8 %7DA884A87DA884A87DA8FD12FFA8A87EA87DA884A87DA884A87DA87EA8A8 %FD4AFFA87E7DA87DA87DA87DA87DA87DA87DA87D84A8FD13FFA8A87DA87D %A87DA87DA87DA87DA87D7E7DFD4AFFA8A87DA87EA87DA87EA87DA87EA87D %A87DFD15FFA8A87DA87DA87EA87DA87EA87DA87EA8A8FD4AFFA8A87DA87D %A87DA87DA87DA87DA87DA8FD16FFA8A87DA87DA87DA87DA87DA87DA87D7D %7EFD4BFFA87DA87DA884A87DA884A87DA8A8FD18FFA87DA884A87DA884A8 %7DA884A87DA8A8FD4CFF7E847DA87DA87DA87D7EA8FD1AFFA87DA87DA87D %A87DA87DA87DA87DA8FD4DFFA8A87DA87DA87DA8A8FD1DFFA8A87DA87DA8 %7EA87DA87EA87DA8FD4FFFA8FFA8FFA8FD1FFFA8A87DA87DA87DA87DA87D %A87DFD62FFA8FD13FF7DA884A87DA884A87DA8A8FD60FFA8847DA8A8FD11 %FF7DA87DA87DA87DA87DA8FD61FF7DA87DA8A8FD11FF7DA87EA87DA87EA8 %7DFD60FFA8A87DA87DA87DA8FD0FFFA87DA87DA87DA87D7E84FD60FF7EA8 %7DA884A87DA8FD0EFFA8A87EA87DA884A87DA8FD5FFFA8A87DA87DA87DA8 %7DA8A8FD0DFF7DA87DA87DA87DA87DFD60FF7DA87EA87DA87EA87DA87DA9 %FD0BFFA87DA87EA87DA87EA8A8FD5EFFA8A87DA87DA87DA87DA87DA87DA8 %A8FD09FFA87D7DA87DA87DA87DA8FD5FFF7DA884A87DA884A87DA884A87D %A8A8FD09FF7DA884A87DA884A8A8FD5EFFA8A87DA87DA87DA87DA87DA87D %A87DA87DA8A8FD05FFA8847DA87DA87DA87DA8FD5FFF7DA87DA87EA87DA8 %7EA87DA87EA87DA87DA8A8FFFFFFA8A87DA87DA87EA87DA884FD60FF7E7E %7DA87DA87DA87DA87DA87DA87DA87D7E7DA8A8A87DA87DA87DA87DA87DA8 %FD61FFA8A87DA87DA884A87DA884A87DA884A87DA87DA87DA884A87DA884 %A87DA884FD63FFA87D847DA87DA87DA87DA87DA87DA87DA87DA87DA87DA8 %7DA87DA87DA8FD65FFA8A87DA87EA87DA87EA87DA87EA87DA87EA87DA87E %A87DA87EA87DFD66FFA8A87DA87DA87DA87DA87DA87DA87DA87DA87DA87D %A87DA87DA8FD69FFA8A87DA884A87DA884A87DA884A87DA884A87DA884A8 %84FD6AFFA8A87DA87DA87DA87DA87DA87DA87DA87DA87DA87DA8FD6CFFA8 %7DA87EA87DA87EA87DA87EA87DA87EA87DA8A8FD6EFF7DA87DA87DA87DA8 %7DA87DA87DA87DA87DFD70FFA8A87DA884A87DA884A87DA884A87DA9FD72 %FFA87DA87DA87DA87DA87DA87DA8A8FD74FFA8A87DA87DA87DA87DA8FD77 %FFA8FFA8A87DA8A8A8FFFFFFFF %%EndData endstream endobj 47 0 obj <>stream +%AI12_CompressedDataxyu' ;i`2cEo0ʣԲ-c0hPRc6`yVY7\ 4Y~gW_wwMo^;Żw?#.? MO717~xsO'?˿y_~ojO?/~Yi77~?+ÏyÇM߽9ˆ4=~ؾq2o'z͏ݽû'|o7wz݇޽~oC;^ >7wk~[׿|u ^IaEn?-/Mv߽oxv* csw7w}Wfa MygO_$fZWC bOϽVoNdWb)S?O~ȤÇo<܆D+ݏx;\-oB^7MpǷ߾}a0M,}|MY)f_q3W-|ŧOwuzhw-?|E/>;,8"Mz[̿^5ݯ>}>_ݏI7tiywAw7_~zowqvKzi}֯~_^w|{߼*}kv49߲z=7Tzċ^}?ہ˵ ?aywWq_;~{7 7I{ } ˿ޏ߽{훭l$~+?}?G/["rW|?߿{_]}f^ǟ|WaHM_~wx_>-1n_C}oiWXWGL4h7C"kH~=CvcΞOɝ=Iow O×b2Fp8o//?~ߪ0J @eYjr%5ۺF|8N11tx-x:Χssy:392?Um}G/?{>vhhBT!gic9I|ML{LOKӔƔSJ14=f;<׭l-qfpṣ<Ӽ̇4~%/2/rXi4i?H{{a:̇p8ta F#~3yv:BՆoVʝ.|;iG=L3<Ι:a~]iO4nMyJS)Tx;iގa܏(86|mamlvVVz=UzwUgno)δ43u6ЁJt&:b{:lG:vtCtG: [:oc]^xo{oKfoSFiIU Rb#D ñWt`CpޟX i?aOt~mGD*D!K !g?0 aĨiIoTpÉ-m!C +9b)a pp +pKdb1He sm~l`"\mfܹ% iUآm [۾|qۊT3>ofyyN43g|܇TGj왧{cܘA[Ж;ZMMX|y8|O 1 g!Jl%۲yK?i弔3aժmfgҕ?uM]rd&b^NѵeO ;+=vP CGەgWVM-U;6m7'"L4Ҷii(G{38Dfg y8vtDt>\^蘡! O/H N]jq]/9%h=sI0cMhH`J7я!L)WP=C_azWsdx3D "R +oR? / 1ӵ<ߐV{q+{('iç>/qs\>O26K!>QZ>=1X0ʕ=O2H)l7_cE/?Կ{7~ILF~OHi;zWtP,#dJ!Ap!-|l?kS,쬛unvMY/n.O7PH+ٻHiތy)Sq>f7<=cs}V/:i9W@/f A5[QN'@Sس}tcQ Bs{V%L@XR") (_:fJ<P8rPcvȎn¯3i"kGzLvM!4uO'TG`@S>t4Dϑ=@s a@,YYDi"B #i!t0pg~Y}AXuL z";K=K܁od\>M7(CYM^\YZ65hoQsRb_ҢjZżVW녻\% UK6UM8rH3%FCكJG AF,$AL%2|`  ( 4"bHqf D(*`Q +T,Gf zby{@ak m;g5Y<LpbKH$mh192P (İIC 㤉:^;C +8494d[7_*b}LB+l;2} +X 8g nb.2/ c6Ik~G#_ f#F?>ڻ S^ \G6pyˌ[Ŵ%ۣ獡Xay?l-0nɒc1w Է*f]EFt&C^j_:u ?WH-ݥV- Xf-mܴjz5tCpjZ$Ԍس;_mn-+}jc,5Zav+f0?Geծ_̿͠xfoUՂ%Vb(„Yw 5U:{hae.&2l8b]WܻhQU>vWlܿ+0wj ']EYy{z{ݪq얩I>ꊐPZ8o"ն-;9R,1V͗kͩKlWR ^p .pv}c6k[ڡiǪ[:R6򶨚w3[w8򳃓#όکLJ}P>d3$c.86#fvWZ\/uNGb6sj^fsmiX(+mܪ穜נwqY>tFA=Ǭf [5Po Le|~ytJ29=-Kuj̆2Jz^eN1Dܕ3ma|&\٨mz &.\> JTq)>I "OqV+j+oqXZrk̈́wXǤ{j 1OMD Ah,Boi +-D"F`3ρћ39P+TXx̓2sjf.0v`%\PRQ*yú]4Ɗi׶ >i8^T&m`(2v0( 9(LݑjȧG#ҩ*j\4jipqe HZ.N d:H|Ҙ9-N?*l^^~W[Z߯~*YP֎^$E!"h>{өiD،j;KטCX5nG_Ա{ +^v0Ε Sթ2Nj}?ؗض%OmMۍ]nEll&/iKh$uPvv)젒VZ`VWQ+Fp$ΕS >U]?WşS >EԥԈ;37c#Dmui}uvjZ_5-l*40J{1͗ם)fq;ea|ϻ9;`c~b\lS8O^xߑ;݂g?!`I4HGfFI_ٴ7yjas -*~Im*fÜe"Ζ1[~x\0M&J81VYdkp :(s9rʩD;qHH8&Y{}f4ӌpf`VX f о ؝m728@[c>*K?BaJ R9}DѝFw69C{8sw Z +TȾ|aAP),B P uT 8y6ܺmsǹōt[n+[߅®^tʩ"+2A3\j~ %'uXYξ,DFwш١u/s2!uL1LU1v DfΣAyVf`"^,XqvX|jOy X<9uS[9h&Z''<͟l˧=gU̝W{gk4.fZ,^P +uE.dRjhmQU  u,OoSZStX,S[gqYI5$$~7qCO2; =<~褚Ѹ.%hwL*f}iƖy2ļļļļļļļļļļļļļ<_bb^bbSݽr MF +{aIw}(}a[QmNjP}4s͢)d3]Ҭ~a`S<#u<~{f`?;8f&Tl 6uz_0aYT"y*8`/lR#c^"MXxi{dwrK0*ykWf S뱊UaY Vt%_M*\GIUKEkqU8v*ylyTxSv{&YwQ3!M+'J5ह2W2ݥ_!ӷ5_ Ԅƭ- hh k˜aQ@;k8Z'k 46ߚukMxM 6 bU5uXMA64뒍`Ln$ȫ[֩imqYhSV)"0 JY(m* ;IMIcFxIč!MxǶKM#G^iZI==ko6 GNyo7\;ATnUr|,LX@u'dd>bauICͭRF:yRw^ծdu4 +{hiŊT8@COSyMDzCWBU-u+T iTkm8e< +/AMђsf=bȉDP[?Hmj[gx+z= $@4fipɚ W2isdD%m ݊{K,;%cN5L%â})W%~E' ÝYb9lXAXUg4 < (8AhugNp*IY2(>1O)pKړSfRXΜhcW681hEgOǶLDӡ#Cʨ6u\`߬<=wl%AKE/ ^$(zIP%AKE/ ^$(zʟ$(zIP%AKE/ ^$(zIP7To4[e(JQ7=X7VS箱*bfϝXYظWAƓYYI]_:gZj<6QZbx Fj^k Ԡx_X42>Mi#RhR)<雨3A1Ufz[$Hdc1N-mqVkTKU g)l.yoOH]=o„\|$1s!, C {T 4m +YSNhKfY0Кqv,ym*kkz2x[=sytmAW$xiKR$ǁQ}n4$ gp +p$k]Rٞ^pLuV`yX'*@n(BA?U0l>J _})5c Ck8WQl˥ZId&* +s\i 3ZkpsKZoÅdy=ƭQ+mWQkUW+hx]{q4{iy@sB_B;9 ,>+PB4‹l JkchEtk׽a;ָ]a^nWV]ۭ3' iu߬k*kW@+z*?WH:1n8ϙk iOo3ٺds@'ssߋ:[YuVYx8nӴͰeJu ݆X]*]5>Zg2kX%*a53kQ;ƱU{U;.VUڡb蘏+kuٵB%]\y|v.dI&%-\K=( +;SX&]?qOk7gS(;,E F1Q5S+]ccNi+vAg闌ho]_EV(\ :Ա9f>JҶβʣ5*'EFdu%l.S)쯺솵&XpawEl!!#1ZZZe6{UY^WYG,E] ^{c\w{n:|xc#'y3xšLz'6rcl:cJ:4j X.{ 6!C8$a%酬VKp>v~X*ҙ6ѷ?UnS꠹uڹn:Yesc-^iZW~v񧻼?HS ϒ/rf%&YV +z]u#N3KG0vzM^y&y/ hGFĝXȝªX6֡eM5%K^Rjv -s^c]9Q2YEQ}KOKҊ~vDtz#zn-zKMUAעn3Ukѓۇ12D۟FJ;tMhV6.^TNzU;]ŗk/mݗ?_Tu:Om3%ne|uKX݆+QV|NCUɷV|[E=8 bohQƣz^< +z\.k|l.~tW3́Jg\wC(U|\MQЭt5ƍ!PA-e5v 6bYqWA3!zYVz:aY 4.5*+ylV|nVE]d_Tm;m+%8$iݕ$(/m] Z{N:,~m@G?r~)$Z`=6 ᇎЕ!"' +a/3f8d8<}GD0Ý6_O* +qӢE"4EM4<: 6?ReRVs4^Z"@H}8~V@%B$L]+yJͼRz:y,@ +1hPI><<˶ .08k}y/iьk$t&\t'1iG8$/n0SǍOw;{d7^X>@l1E@Xkۖ=m垒X6]6jb]ݶ P;\x^U4hE9=ozjBt i97]<_V0[/º:=+۩-nUWzXWh|UΗyxu}&Oq>SE]k +u*WrKu6k~_ЯklJ:t-e%*/jmuiUl끵,'Z1 ;nbLg>V?ׯV^Ẏm2ӓruW-vYI}$X2Tm"2Xm9kFf l֌2lþXdb(;XF0H]Kć6q[Mp1ϯraY+vu.'kMh=O>Ng Mǥ=m-Zk}~^YVJJ=~ -3\fSLjvs"e5:D +i9c) 2HEd! y+\+Ss UqtW߾^U]oW?}޾T>i7&Դ./fX|CX;GqO~_tw}#`}GW/޴ 6/6Ͽ~ͧ޿Çw>|@Z/׿y_߽7_Kh2 $ +l(q)½!vUHL@DZ(9 #'t7L~Bt3;s2'bc(CeoJ -BS`rlua}F15 }<ѕ|Dm(Z؜S@_5bx>֑Pq$:4Z:AP4~>Ow8 L#$'&jؑ3:w@盤 +[UDD^GMD2н2Sh!";dE<أHfz)ou]#~Rem@O ˅viLCSDJyBI"s?ϐljM!Nȋf & }%/0yDԅg]N+e { /@#Lo t\%=1>~_dH#Qqjj~ÿ9Pfk`uf:ݞ:2.ܣS=mB[D|fkLEFle[.Sd˪qi=Y]gP:Q $Bj~iSk~-{gb/Щ씓x# jLE*21Ȯd)䱡K6Sr0'N z'٩!+o3J)wR 0,g,pC_N_Fe'aj2YHDqۧaJXǙvqLYVֆ-܏LZ +#tv !_٭_4 as3X1zcg%C54;|E𝁴F`9Ww!m4qq "F02)+cU0,AncaL0 ӘZ3YkMUWəăn4z8mżj&#Eb08e:C/] ?qq=wcJ'"j='pK0Ch45j0H++4ud\bj Ĭe J1Ft03C&2B?_ \"zN8uͨDr9`@hKk8"`Gfӓ >uCàr2:CqZP=CO򅠨)K}%MĔ$PG`Lm%͉7zO\黽H6oA#Wf;'ve*d?SwjF@|y6tp%b437lzI]./dD6,;aȖoÁiěu,6~ږwm(r{@=臝$1b=i4s='3t>C\b/ G*ȫf * h:YgLj@ F%9=&Coƶ`N,+zbl&8$K9/aPsym9?h s?ca v/pn9/yvʪҢC5ދ=Ǣ}*saGh.x+&`a1AtHx {կ7bj%" ޤ.Zqldf+k&lϠ P&[LYcE* =XɎ]0w9' ӆ-E\+R- kX&Dy;x+(.DWaҺs)̕0Rf8i bR=.̅\'cMG UF +|hܸBֵ}h$C: pEIFQLLE%Pפ0Ա7UC̓k: չV8zTSe }eF ^t4HM5ebi:k0I˕\60h$EpUs~w #%J"H p\Y]E sq+ؒjq"Ф3vF t}ʕ媏͠2~ChV0M<>_5jpMI<85TYnî|K8ĵ:s7#jfu7csk|~xas$V[G=@1Xá5)Q'U9P:Gi"k4ކ:$$Qc%-7h'QSp yDZ8(ܽbα ]w|w&`3Rgn=p]L\5a./M+FTLuU%7ƸP6FxrNϬ?.+Q-%Ʉ:74F>tˑnrY `DV2\ݐ­r.+bn|Bݞnv4} 2,A]Iqci̸It7ZJyrXnu5McWܨlf]t[wIub67k5xḳ`c*5HLEz)<8 KVkunA`2HC Dx g_Y0M\&a1mL,-CSc7 Rc$.RJO7,7 a}`Ae* ,*SVJej |7|WF|1 *mpإ^ו>+{CJ_{pThF|2+ Q^ ~ E}glr  L.٧6.ƋO|N 3̋ګIT_]ʿ!fA]5Yǯޘ.W 1N{}Kߴc0gb=gc/}f !5$NǩLG(vd/# +G_Wcȏ;\b'7MIGʨKyeM>Q_`Gqeb lAE ; 9(wI,Էi!>Yf-$O~VBV{t`+V-Yh-\.hmp1Yg9|{ sTC/axMOAzhp#$:O >(̬A x%*pvypP\^#: 1lB^ ` YsKcG܋r EyWBӾq`lGJ\l$u/tͼAvuϳ#! Zf{|3@Gl_ v!mpNz H뻼nhH yQ ya1aOU2`MI]Md2M+ l'u r~ea0\`7>촲%hv%,yNׂȺa +m"5%rҍe~lL~lvo+֦jr,Df[Bp t!^(]SmKzo6 V%(`RCW%jD7*!"?F̡C g[81JHlۤzU7U&5xpd6h.Nd!Er5P;3Ũ 6r%v n #jiL>Ǩl臄'3Yp&q`"1p +A'Na8OF2Gq` &G#H8"?8Ѵ||Ҡ%8^l6Xc`[8E~_nϰƼ^P#΍\ffY웯w,=0r-4OAdvOOgxE,&b/y?@>?$mGi4ugC9q9I9Y3~K˵vOr`,pdE~bo8pbb)~9)C$1!^]ѧ<8,z!Y0,w  ^|iJM%kZ{W ꕽj:0]a3B 2|f_-,ڃL_=pe O>bwGZ¶+itD&`LA2b}0VH]-r]l}ʬjYهaTV+o?'" ^MQӾӶXm2~ۭws'rl >]6a⇯}Ow߀,5dhqr@`ydcl1H +@W R#=v:$,Aӡ]D!eֵ J 0̆Kr i 4@OM@4; -ύ#Xf 1]y,O]yuu[{ʣ%\GI/C)pQ6x%Y!Sj=P^ͯhk }tXHWГ4N`pΓX,_O0NUf8I p[SӒ^Ri;DԩyE ,5^ȊBj\ly.oypVMjhevxj9p!5y¦\RAm-5 ~<&5':ySO<<Y-5f,ѧЛ~f9Y%恳MbxK3%#*1@ +ub0Y< {!7y~8y^tr)mT52i+S\1Y0hsdLs2^eB c&C82^V#|zhPd2ܖXl##a9E4d#xR_ /vo6PT!83k \/FWzj +#\|π<"W;]Zt$Hb d_:x>\/isuUF&1WMNJfL~K[Hdq F_G{] +%^5:i&1ҁ2=UPHVM wŗ1[xXFY[f!Z | 5"fCtAǴ@@r!.ꋙ&fh!(KQä +J4M' >fΐĽ^膏0ÙHiK3xX4dO[Ȝڨj'| bɒgC +M7:gG^PcPv}3'TQ.H]p`72{lV·26ۿfX *fZ'Z/ MJ ؒ$ $X2^:+|| +` )u0c`x3I8I*|X.D fptLe%kI'pj`i) 1R';Vˁ9BJ @ N3Lmy7١JAZflL: +-IfciD%Ь$ZP}թM'8F0d* +XVMǂ +-yمbQKS|kayqԒ Uhr|5EB e mB/u!*Kp= 6AvGB̄Pqx8F=]ayS>w]j lҬ=ő\->_l1 qQUƹt%eYBA |2vrМeIUގ9TGS۔XU-o$)P o0QE 31k3|dx,n' ^#I#v2os-|4x09©4@9JI{#!b^'Yfl5a[ShNLtb*p.A5!}I17@^=YpJhui27bF Ӆ@=_I+ ^@8%zPwWd[cmz&oG; %8RLC#-y0&`SnԣqzT7J#<ԈHItscV^YTѴ&E]B>X[4؃vN7F=ɽ PE;c/l_vnq,^-ѣz䵳&B۹qu2lTQU7񠺠BD81J^Z?FBRnﲔ廴*5&yZ\HuVdՈns-f.7Z-^p7љFw{ nt EW2z[*u홦Ԙӵ7VN]}rkXnm07ֺ\Sۨ}6S|-mѮ{Ů]\F\A01 -DG͡ہv8NS22ZW)V1x`h;,U]DCN4XB.Y|X4g%ҏA$:2: 7e )U?eR &7ק| *+mե^~% uH { Дpc$+# GNA3Z*{CM[,Eye$ [|i+ؤ)5L}$?bsy& +UFr2πqD-;Mbdu>zjo^6F%* 5$4PfRt=GoO!>%(GX&Bώe/kh(^(J`J`-CKM6w),詬5:Sn թT~VBV*X%NvQP@Yy@X_$%<榉Lpa̿ QYensX.<)4-]h9.os@CL/L2*`%aŶ$ZUI_)} R}'~Sd\gFL@ iyM"85y3x W ʬ"!j|4p,kN/?\z*Ʌ];D rywd F D$e` ޒ2$ŦҨIӭqXZ@mi`ʖL1ee|Y߅7kƷd޻ѼJϙNcu~h}`D9h& O_9 +:iv'.(抬$5#%{K +$4M$0+L$J)zb$JafNc^cFTeamvd C40])Ur>&Uh4DU ȩ2X $WFe6AK$rp>KTR. g{.9Җ4}AR֩,eBU(X_(sail nZ|(o! +Yu>/<;u|}6i[gwϘff +sf>9LIyMMw% *GUOwEl&R[ +,.X,,j~]QKzqh?"-J>q&VwSU]e]AzT0j{b +r_wHWBK+9o'#5,f3^r|dƅ#$`]C!ٙVE![4 S؃)9 G@$%b59Ұ+9p$Ufr(z/G4jD1dJLI-[աժ*DZs]qq"CM?L*y!jZ55̥fODZmtH9{vZOZL(FJVo(,QXf*Ъyo{'[ hOB+/fB- */EͩUh +.Vʼn4NbT=E}'*6םQxeJZ_*bZG{PKUav dUU_&>AJc"^>R)1g+7GT,[.ŏk25Z2FQJFJfb^ṡv^ کvYJ֋O;!NuCԽܵ +g;o?`//<΋7Ћ;BVx~0qi]\~jKw72_wYJo\hWw+7W/YzʼZ}#yQ{KxkicؤJ\dU P K,t=pu3mddmMv}=*d|'ó +:&CW@C^ `9Nӱa~;\]8eRR:L$2'!h0&((4&V#9#iNC{$AeYѤ>Hrh& 6:?i ?s2cD;`2q\Ye ec kƠ5&8tf ++oPPS1+(e-]$ĔręM4]@G#_c8/]KXBԆʇdnN:$@\\ +$ń1YDУ .&؏LMH+B ~chBqJ¿ δ%ϔ ]Ƞ$Wq\CzIY i$Ey\TPF +IU7LL%I0x(j mj5<:!n%,Xҏde)8I)U &L&x194%|L(d(hUq_LY,0%ba~ijc/~(dž >Dƕ픃l2Q4:'mLOb_g !0-Ś)$PRzQ?25p"D+ a8 ڈˡ"ɞ +}x_JrfODW23(MaQ͔*`/^:^$9M./ebeojOBڈnIu9I/rZv]Mqpθ7&jFFr㴫Zn6m̭܍pW` +Eܧ[]tK~5`Jn<\iA01VfVGztE}\:pKQ' nJZ Z0" x Q gMcE +oL,,C2d7PI җ.ϼif0N{ؒjPʴS^| Q-_Qʪ@v[W] R Nþ{'G H(8ƓK @3⦐EB> #h/zcx$:e7]jp6kYYqF NYUflCGOm~e[XڸM5|uB&-ɵ`%A ,:{AvB>|ko^vn% @r8|l;Oi5_M\x"7c['tBe`vW^'NPk..02S]YTQ,=}ߛøcN +hox" d?Z} 5XmR8nUv]3gQسhƼsD"F$B7o#kӃj30lpRagvZ9hz2xOP"P;YgV:ۀc?Q."/- +Ѧ9840., ^q0Sݕwl߈A6.8߰kS}"2׹BW }-V N֬#81-7B8,w8l b0sRqqzϞt.<\,Z)s92_yjDǨQ +!N=l%1+ڊ3Z:Ioc/&W9TzOT˶*|lItW}h^HVΙݎcTmU(@=Rjb+TN:q/DDw +=-A3/hM:c^))A(߿?b6>lY/{AٓV#9s' @L' %@ !s xoA]6z ( }Ϩ,݁Lh`_pHdT4 HR>c'gc\gSMc +9gI'qW(^=a)T4˹/}H<V$F>7[,Ilôr  $6`y#ٳ+PuLZ6rNԓ +/DQ%"g F~8vO*nۭ:&DqVDGQ|GʝC 6}RKeY\~ LN>J^P4,Wj:enbJl +>ZztMbb3ldM_@%٧VgttӨ3l4,,2XY˚_&H~ _̑ +14B(`;T(솳c3餏VLD=v)~2`eƱ[!,slyȒm)JOy7&+#XFoJ>}f%[*]Ki@ B"1]zx Bu{Dm V^:m-N6Xo>77ָNjn>Ku>;FaZ^t,<g\uΌq#ֈ_y>ȹ|suq9IY3}2ɟ9EC̀be? ~2Rѐ]HtHqRp>yR}eQE[sDN=?'hIZBJ{o׳;r> 03kǙqA HbACt2dY}x룪RKO&}"6<|bժq_O|ly??˾`7%ۨC]*~T,l83iu.EY۾Yb9j@"b!>aqQ5цi 9NŴsoi}8pܲô*' HN;lRm}ځS!vyQӮħS3YGjg$fnY4䩧{6C<_OIfrN%~~yohqȊ9of?7IZ,DC^z{IͪHQY݃J{Se_MX-ߪ5tTVD|Y +YҾr+Uu8T9w:ZDmW9ZFi+kʾ__-\KY@M +gJThg\]]VBDr&p,ɷtChĔ@mRB̘TWhϸc7ڎd + @p͗ܨk.jlb4}i_Zc#A DP'-2CMY[Ьd'?aA@BhP!_l=CCFqIڽU|6 ;Bھ$U@v?xkc*+R.4ۙK!hiM&C/N 3eAa1)`Ō$$2B M + {jNܛ + "'n%Eu  oM4O6/V2?m>5*O1+yF!e<#z<N"K]#׬|QYVX/`k;O$8EҼl8%v@֒$ !jIQMEUjLax*Vc jL\U"uq5!s5k1q)F-E^Xt6-ŬF5X&QK1ojdbگm-&} +Sk1Gحbi6K#8j,XK۬pZ!ga-L{> GZ+ukqQЄ{k1vZ*i>ŅJK+Y%(kc~3=RV3psb)|U|{Ow: (l۴ kWO~?`!aq/H1uX϶NgIJq1nĨ/Mc17-ͼ7 +b˚2/t˸#P}1VW#Ÿ"֮b1n~_Ř&6 cbD]׾_MK"d&\yOdz;+jV:K[2˱Q<1 q1|=nTF&c؉C7kZ H1cz΄l`C17R ӌ%X1ϟr+)Q9%IneTN3FTNb=.r*;rfNTu*!WQkP9˱_G199TN`$l"&ǧp1$tP"&+3&Ǘ/5H19SY\e_J<&P#(ǥѽjž|dd`z^I]mz|#0#2=p t GA 뿈w ~g߮gbcn +6 +j[}wi 2 +b^M[*zvC%!ZA~êLiwIrwZ<=mo Kd0Ry[eETRIeNyrJVT˕7',G]oń:U3\}/[ [1'No-@-))m^1ӗ7EMKM 9kIH^8Yt3Z:X,kʇ.dVuBCCNj=GTqc҄ rn,IG^\vNښ)D +;})5ޕe5 ~%U޼Dd_YX"?|@65푲PBދU?>/+.T-^ׂS }pg"!lP% Ӌ +ŧm@|iN}v9 \@l3m + +u%Ep(!P^}y-ADBU+Iq7D=$1ypٯ^m"-~7ǭ--R-}@shDtQFWWƔ%(会M'%PNzu׬*A@eXLIx^" eNЈ +XWxz;#;u%lƒ:n7͆m6FcGdVZ/X6i!-i'Cg̯5xvkM K܇U4&KTs1K(#TlrUUosĹ8YmZBE)w9u%R~ýZlfXr^4DN؄pY{=UeYWdQ;vRrʣrNp;/kgQA kY-)LfwދkkoPeA[n*|[]?ZgEⵋgz8?RY ~}{e2a*b;i1?'h\*a_I-հUiC}ٍ Qu)(SّQ23}2嫥cC )fm.Wn +I +wQ/kӭ$,7O^@V%-PP?p!:bOl+3_^{w4< +"3x[#zkb^J͝e?st3>oJjsB7r^:!5f /%ƪr}_ų!^ +MqUHvfaSty]>7nqYnl-Yؾʀ +q+ܢ<̺ +-=t{1nGַtd޷2ddPBFXX CV[zB3"`9#+8L~\TgEХgg>NA Q*5iĄ݈Q޴1mPUNcH?}gwu x}CnYHg7eєq(lRF_uٹޤPqShU?$@5~eW{r*wF_Z֯W8(>) ־w{ l@M^;w9G|m|m>[ ?Ƭz]߫`LWb&yX\{~7~q0|r0)oHoWQ0K"BN/j7}[yKgj|MqBז;>= ⵤV@o'+ +FD +8s~#JkPC|8 ՘DaG~㏳S>]\p;^`U_$>=rn[(YPZ!'f0XJ) q!pK`;|G~\lLkD] J'},JkT;-YyX|Iw),߶|+_ooލ|D0ל0礒('Y$<yy1{|ϱ?9N{DwpZ` MϏ"?B>e ye y-[ȳ-[ȳ-[ȧ~l!~l!ݲ<޿@>eyeye  Sϛug[vg+[vOoA>}S[vg[vg[vO-oB[ޢE---S[g[GA~kC^mubW#e]W]W Ⱥ*K^aiϐW[#cA5W[)ljTgemWCSؐW[OwNy5>[/hjt5>j?}G WDkȃjK}5N}ue뫭Oؙ{Aڽ+\JAΫM5E֨ -[= +>sM`o ~J=.fC`S +g/y?OWX?y6j SNe|6,'$ϫF[A'EKLŌ%bFJiFJBb*'$(%b: +StS1TNG)15MG)1QkLQטkL|5kL|5b"S|Ub>*S1uq>2S1ucϜ,ǮhT"S5{G>L4A1EjaFզiM2_?C^ +FF&#'m:ߵuBg ^)NwiP:?K~ .*NwiJ!*NwiPb^=I~J~j*23=4?$Ӣ4U?ֽ)}|½w{=|jL:>cta?Cr&;455bjhES$l99>-_z:JX*]]&+IQ7,𵧟,๵k{ BzWvb4le. ʢqv=IOnmvIߪyFxPyet^Y_ꂲF_2lEv @١ .?p=g4Sey94VO[i i}ce yth][>!,iz=!~ątUI RwMj/㹤Vd]M`%^0R%u* 7i' b쳬ϽՉ,EZ*jY_lx4 X VIKşl=&d^j&bBaQ5{qj%R^ $.>[bVͫ US {ر^ޏuODNITSb;3%niDMJq_nl2XllrF5p;V#(YTa{(=jsְ$4v\3{ֹ|]&ġ+iPWc%\ҝ+O(+/k9H _^4?䀝$wf=gh ՜Z DN0m,pwH6rMR&~ZmCYn4&|޼^4T^Eq'f*HHu1?X;_ +HR|V# YŴ`D,`*FHYNF~yٍՙ_g³܎jyMwYۉuXf@,(l;L~WnYhsVWJ͂Kشƅíj^I޾'Ǒ6Lߙּ6fW5X1B~ew)6O^}S*VKM!zk ́qϙvZDyTwnǶGO1+nd{A4̔S1;#y\% f5 ǪH(VPBeJ_TtcգbL\kVi]]=KvZ=Z?G_LKNBH|2/iM7ZғT7qu3:|wBSK*B3mVzk-I[T'ot%Dw_K2ztQ6~wE&w;p/xݺNrZ$wvZm=l{Yʰ@-R-ŶDe޼찳 uyBF ̀ǼU:њ;*J_)۶7t‡mرy;B=w&fASdQn+HepYELK*#+btrv2iT %u0lV;F}$$7n,.sTuh;7 S"12Zb@(Alg ?}XݿXm592Z|ͣhs۴x7WPZeΐc5NG_jP;`a0M}`pܳ ڼ_f?GŴȄD 7ұbn;`%H' ˆrh]P< OuǷ!o{_ fò*% +ʾXmܣmOrc,5 VpU AQ +Qro3S}sbK@*b ] G*ٯ21wtf#12jE]~ŕ޶Up+y޿0`|Y}'v~Os P}e1Vc/ +?whyhFؑ6عS74MAk*|-!vN;PU\yhg3яXGLߙּ8+=ZEtvEgw?bH Ei~OWa~za~hP4ʛa|Hc)e ֻQ{xCG/`-sι*[uFڦsᒼ#vPq?nLl+CYEy<'QIAފt3C%VC̸fS@%MJha'_4҅x j8|$ڳfK|nK 7 ヨ=ou闎HN0TmցY ot{Zo{Gj|X.YG.;&viR5/V3xo[v;& i8h#[kO`8pH>/&|bc,/,a^|Gƨ{>W?Q3zl|Ϧcw{Ro~_Wo4!uٍ<¢qп7_?W?/_uΎkjE>ᄍ'_? }ϐ_Շ?k>W|__:g_|//~87O/{4o{ }??K?>s(W/d_7tſ?_dos ^³Ȣ/~bR3ަ֟mſ?/~amtm7}њW>m>?%ӟyX3~$/n':tĖ ^g w:fJ6|{aM)1kFoݨy5M{" K"4r e3 SAd;CV+#R2:H*D=b*,Ey 0s;VDH[jkJņBgLע߸Đ4-.|WE; ^`eJm|1b/{#3+BR],JM s("J-Vןr0u BXUϺ&ҮrD wJ}uso$`K@׭ Qh`5Uݻ2AޙxVUS|T+; D2=;#$G%$^74U֕xnCtJ G-Q຺lT HztrWê6%H+fi y|ӻ[h/ld/!{U_U3vw&u8Ԝ$7 ý4.j %k= mՠ(B>Gj7,J(YnuItNJMK-4tD[LhxPL@MF3ӔiC +^قtٽ暠e@Q- 3s^,*· w䪁_-pg<SGQ4l޸k񾏋8~|T$*M#i]G/75W#3ENA /*KjF>],z[|LE%ih8:ST)H~X(uSg,|uQ^1B<)?tw̯{ ^ej!?B5JՉR_Z0"WkcKfMJ$$RG!^24lf4 v| Kn=20.QԽlOF9:0hsoev;zOd7ZΦ5P :{KVd1YZ> >XR0.T yv)"A!۝Gݶnx@SxX>\{dڝZnqBY]86<ֺ3Py\N32E0h@NWt|#'0 +VT 0ovi|dg'E4u0pboD> w˝Na^XFW4KLB %q 3.&'6ĶpIT6^[/~Jdc0]J[\檩Nm7GX|g|Wx +"U.xiN/%8nm*m}u)HaCHujj4( ŎfPlhY%@j/5|P(s4 R5pmܸԽqjNW==Q6 k d@~xY$ܗU^LKmQp,oxμ\ y(%>t1-{7eu6yϰD=@K/ƪ UBEQwZ;6j۳.+t`%5P?#j,A G,74\f/&5Uv;y ೕbWmrS̶.!ӼY,?OAKW`J-fW>"YZf,_ڣ-[nSnY$D$KDӟ>ooPucVtc{]!e>Q*|wai[д_Um͕CZ>z408.YU#"PA^F}UdM҉ʊ40(>!Ij5L6Ym2Q(EZ!R(C"6\ĖOSQDga’zENRbp=ަhR;D~ +ķJGJUQӏ"eU%CI9>kK8e 8lnޑAE4IcgRnfU, +B@ę_#L{crL;Uc= g: +pQDA̰R?Zn직I氓GH]qy\-F J>ՇzO1ڑjK-DZ6v_q+7ahȱ=u𭟄N!"]*@>W¦n:mzz$jAz`(C3[ʿJ'ihLXw-Jř)G\LH,++PF,z3Eqx֖]DX-/Z9V;S?)hшvhE"Hȶ.NOoޭ,ÔHO)\l +reGwLgqU`WI3,njUie}C"&Lue) jP 3*Ӹ|m_Y,'TXa^tAZcT2ڌ8OTJ/);Y ןPTnW8GIW2(lmv8{~VW1\g!lϼ^:`b FQ\*dLgi/,N< + $j{srSWb4.x(5$J󉥳A")ǍlŒ>u+i5)k*RmSTQך#;"> +0釯dSjU9EMzSyCY-}l̛rqlӷY,Zkų6\)πZ$R5A~EY*0?ŷv}{XӔz #eRV0IZ7(̭JL1>\cmWVUD#`KˠOAbdogUN|7AZzNe&-LPB- &Vzq.fTuZV L ,$Zj=l+X>I\$g]l9&=^)1n(RuY)`(ݽTԔ30 MR觊, x_jҶַrȈ(3\|d Q줚{P8׶FpV vl#ekÊ%e4옘/1jӌrEBTnV> 5R': +)KlFt`"Rl%lee]qB0u<t@ 3L. \fZ3^K*ద"]\J' O+*qߧӨSJC<_{x DQD$UIVb;")b\K\F;mA.y0MX܇1ժ3i4|rPI^*b_[8CmPlU/p$R&^UtK9i7Ͽ DhVT:8 W<0oaR;8rgKwZx:2P 8%BY8%3}H|+YoE*1NQ>I60ьؖ)r pɶzsgj{Ж^mN"cLD'~e U-\bXfFڷQyEq(/%&jBҢv@?lb|MRqGg)jr\Ȣ,E9byː9UCN/L²J(+it{S$A;e(R3NʣԶC><3bPӯdΰUi>67_Qh͔1hakW^V\gYi'!*(b,pZ)7}"*py +_8Sf!#@Z*T)nDe&l'T +W/ fzH4ͻqEVҽ +YZcJN\;xת2AbΕݤ ۼ/zBMA tQ 'ޢԲm^dzB( 7&G"SIç{{TV hr^gʕn^k u=Kz r)3a+źSA毾ʍ]m6‚㝹7G]e)K̝30戤f$"$U bw:luO$,XC~%9/r(VUB yWrp7ETJ3>m]BXMnio+,x#wS4nRLlL*_,iL~ OIFo(Nd!Ҙel +?Ũk5>iE[ IsZwE9WS՗/#x][զ( -yzsbJScS+Zt$ +"QI0T%c,MqYf]8W'Z/u^ r;p;NuDԪD!u6YEp~Ir;x +׎:etNk_[*>>?!tՄuD +طn7'Gaz+ڗWVӃM@ͦV! b#"Ztġ#2b^_Umd=mAY= oB"vK4vBWcCeoW%hS:f#ʔHh|S>K=; ^k{VD.n.̲ YVIKKt,;SU0RdKMdYkAќR8JbޗwCN s=i*Vng1vnKڸ `b@qԤa;Ԃ> %1hW!r&R=^QXͫ*wYqea +#]][HKfUYdk"m_ .~}[Fj*DyYt/Nk'ɑaT^0 wJSIxbc)<iKA틗ՑYQU5Eq $WJr+/ʃp ]Pur`K՜bt>,Lb^$?`U4P @J c{"mjiԮi\UIhgqYrJ%ȁJ` [Cu I2P.e }Ϩ$_/Xz6%:_k7QF U(,-JpŬխW3BGH oBqlSVå."BQ/5/hS8W6/3GOdVo-S""KqnTʪF HMpV#جSD03/QNb,CDmWiD;Vvc6f]EK!v,i 2"V)0kWKJNtaNZ.tsi|"P[ M癕kQ#&f% wKVP3B.q6Zٽ4iU",V±mF1NltXC hK/71!RXb٤4 z=Q~ԱLBw'mCT~:` 96Ke/W"oVI +?i|+MfsTę9; ˉs^~Uq.ߌKݽ +Jǽv6}"Пn')S}/sKo-+SEMÅ%CjJ;X +}Qvvks| ZLXp[0U#/FEcJ+^?5*=83H)PUPFZ8vfJ"A_Rau s̲{wz<4Ji!u)ʰiæۊ7YlNtNM+_u Yn]/(i]{H +%n*qK5zU|W,e᠈rzT~=lTz2estVđ2ߴ[u;mM968Ʃ?6YOz+ê"-MTPv;X)L+=0*4t듷ue˄QBV*Y"'Z8QXvqZڏ,^Q2F>/ +GxrZfU$Z8e;G^2iJtWgqJ{RA6)ʥZtjҐau^nC{GAq.9-LVHߢi k"V/Z{G !h%&A6%#Lu$Rc +j'U?WjVp|'/fqu[f9rFy pYbe E4Vsڼq%Ra0wew; ?Z tB 48[#J<0@/>n,YPEvuɢAFkS\ +T4sXͅm//(Sv\z I1Jh~PhT#3zԶ@0L콅H +#x3zXtpMm%@N[ +h_MCDWkct†kbTosy) S_ܣ*)]1КKE򫧯DfjԄɸQjq-Mx(딑@j68MQhC],_,S +P[w{ PdGC%Z\)ȥmjZJi]+Dd< hV€tF4̧t!!ǺFy2if~b$ +Gz~Fl.Bջ`n*D¸:7ɒR|}ZYvÍh@wA=nmWQZ%PyȰ2,{: L։@&>@VR,dȅqI'l=@Fm& w5X@@FE [2ȸ@v`%Z0d\ eayȰ2,3 'GbS3l n {y{LrpdH[GVcd<7 9A&sf#LARf2 Ȱ2+Sx"PhdU2žoYYCi&'S A& à@&X0FrBU:'Y-uFU~҉ eBU?d AeFay#jiY-AvO *sBU5ZA& eDax#Ȱ2,3 AVigdUBA#(??d'd2l Ä ''6 Ȋ;\H +Tw2 AVz12 #@a-d& OYBpDtu[ԷH*w@aDugJ. c&dz( ddis~ǀ +2=dn3LwN{"ȊZY"d@ax!J-3Xs@uÀ Kc ABFY!h="0""IAV +Ba +lX Ɍ +W{#0Nb1"겼d' AV<#ȰM2F OYQa@1L,+U,/ AF΄ C 8!$4"$0Dd:iDc2v #D;&gM2mZl q@A/{ kdidi AVQy!ȪVAVNdoM2h'/80!0"2ɧ#kFUR#, #AVًvLk@mdR&y"dd27 0!Ȫj2iB [<"lL<dm̠PQ7zܻq@/#gB W<"0"vA&"AƳd8A4d`_ʦD6L2ędd&Y=A 0!AFrBU5}2m^2&3 A֍ b2yo`$a dy6tH > d#q"u@ KcȪ6#L/D H CE TH dؓ@H c20a Ye$u{rԙ@V;FYQa&;@v{3 7I m$a A 8d d2< d=02~ +H +"R7S{"i$adfd: H +"@FE c0Ȋ:, #,I r )BD /23 L +xȰN2 LGdEm#H$Z)_2 L Odd:s$_2~D + @@ OE +WdLda Y1}$^BD 6Ⱥe$ V'(tu~Ƌ@&D 2Ȱ dXg,L D R'Y9ۛ@sp|40Ⱥ5d#]@Fu&)8dD#, [@V2o֙@e& dXg,Lgd*wp&uH *Lr iydef`IY:l}$1 dpl&O֙@&D ә/H|$ayȸ@VȠM2Ⱥ5d(|Ȉp de;2KȊGNL #"qH +KXI@VJqT-O2Ⱥ5d%OA ;_2''@&ˋ@&D gM2L #R.': dȊ-#o@V5d^Y'dX«I c9@ "M c d%fYn L #" dčf78L 7L Cv&H$q"H KH K4$Q$q$х8^$AY‰@VA qI tO263&ʚ2 3 @8ȰL2^2 d/&ah {y* #@3ȈldX'd2YG' @\ @VL @F4i =ѱ<ǪO=3Lhq13 ?eacjcܞ7va⏁|ucb3L1?F0l握=ǘf?F:xfX?u2d!2ǔc\Ą7~n?VU<ǘ1*G ?c|1KU~idaL>k?ی?<ǨcD/1?ngQ'9ǰ2T3t u,fC޼,e3̶olP?FcɞcEO?V"'17Ss)f'c%+NJH^3.?~U;~L]I@1B #~ N2w#cE~L'~̚wv1E46?VR4c$oR~EcEnjSm%~ ?=q}?6[B+%*&~?& ?uƏjF7~sƏ)?X1Y' ?8ǔMcX1?eƏዼcEX?FgQ(jc:~̌2"Ό1Y\JN|0N1 }?1Sg9}acU>M:t',OXUsEcUԙ>> c*Bxy>c9Ǫk*>FL X-˃>ƙ3}‘{*]}=(|01Ĥ:ǰ1,oX 9e}xC1oN1]D>c;cc4!>cL})gQiS2J}Hӄ3x?'%^1YG>Vb)F}I3HS~o':l&.Ez>V2V15L1R(oΜcU1>GM*`cU^HS"IBC1z6fo'1h9xǪ(#}=aYH2ǰcXGz&,O#}Z#}L O?{.L1R/XR>1M3>F^}1g^1Rr>&>&B>Fx陎1F >{0ǪFc~T3Ǩ c,/ED|j6~p2&y>/+ʹ1#𱲭3|SW>Fh)0^q$SISj\1F[8dcv>c&|+cu;gS >?x'_/k|do=#{Lu"#{ Ë=&ads14'Um{IdILqvGgu5K;WLRF1ʑ=M1I+cE'z#>JG +V&,z̊Z1Y',zLDQ23x 3z[FYGX۝1c1tF/&F'/XjQx@ucT2(yǬNqDUncce @ͺOtFc*:zdc1 oXQsD5G7zL=& =fC+Rc܍=6X`uP'ro[''Xn 0o`FOc2:Ǩ}cEoO%3zD'@ǤBIq@IqB!:ǰ1Bf'ؽ]zinF>kB =6X%'1u1 3zLz̬#zL =f?+c3zl n XQ8aD=zz4uG{/Ȅ4cuxǴwcTnfz\ی'zdFB3z=fE#z,Sz tBU 71z111yBqq3z='< e ==@'zhB):QcĀg"z,-#žzLE#z=qBac8YOnDե4 豴zL=Vq1[> +$X{@1 =5x'Q'z ۈ#zL'=c21 z =uX{@q@JsD)DQO1Ǥ;Ǫg[G#BcKr1y <<֍NSHӷ=cJ1 yL'yLƁ<cYo5LjN1 nc)`d~T5O䱪‚yL'ycFX7 4yMc$1; 1էy W"AKcǤ7cg8yLcO1<^'yȉ_qQL޵&W{ P3:-$IjyR߀$D㍖eY 2M* y%J 4?F klg +c㸧r\\e>WTVV_=x&y >'g{/_w#!:@~QG6 Ejך1=ȯfY_ zvǸ2 %q̡|?0%ı{&~I;/1=G})m.wKnHϻK|%?W]b| Lgj|V^k]G9HɎ{-нt/;7^Lg| +.fںeOE#:ދ-{-ྲྀjx/z4Y^rq:F {O$bS}+K8RQJ{m5^z{s߽l*}Y9k rKrڋ:NnOd/^m%WMB9/g2(f׻^R.VSA WL'{2MAJJ"{m5^ .]g +KTlzGKLj>SԭK&2^wE%|FzaqZw$L%BuoD/ gxc_⦁26* O BP.==!uKXYtMd^z_uQ.F eܴ.R*ch]?BtM3ZW{=[~x-Ẻ^ %= J@G K&Еi] zȃ֥{B-`к +K8u1 )='TTമF[UcwZU[8 ᵿȸ.-SNEץo,K{PRBgQI|A@]e( X``4mGKoE%%qpЅn@C(_ҹ|.s]2|C0 <:Jw;ṡs;Id.v|r\/.VXW˅73FpU .AO*2EhpH~m. "cX,\(f2_?ں7o s'=ͥ+F,\ +Ruh.'ţ1Ϧ\Vd vsɲP%/( ,m3\A(v(;24\+ɥu\sNjMd=wNKwgISE|a{d.hFggYZi߽Ptzs5RY*ЉY ΙYTe\ ,Zi/ X̨],:ERռfe1Y8YaM8&3digo"1N)Y,T,V@ ENM"[hQl=:0Y@ξ)YpkHgJqrA+k d3_dUU)׆d]*,TbB!,d2$5 d5=}T=Ion HYsv&ɢ@`dRZ,)$Ku: $ l5"';#Km7`3,)ω !1:@cd6QtFΑfdn܌,oƋ>O`m;(Y5//HC@P.,uHegː,ސ,T[$T>nd5}nHVJDT%[dᒨ`@HnE2$ [юpFi@_I,))YkM2CCMצdIKbQLU[,TҀdaE YR,!Y͌dѕ|wCgeH[xwA[tVd>stream +87#K`pȐ,^?f*R!Y($GQ[PP9J:Lɲش-ij9FGARrʲr` ͈݋ʚ1$S9d)~eQ zJ256%AҟdJEؼvAɢ)+(Y~J"MDQP,qƦdq&LR8OPqS,RdJV{"',k)YJ]XFdq&d!,ߢd{غ$(YU37%-kd))w +LYG&d=tKժEiJz[4L h"Ԫ M՜ShJ")YdƘH7>(AZ YX!Y(%1dYB1Yt90%L~ d,2ůgm]AYeNqP>NplLϜ,S)n?6ɢCX!qQe +R,s2*KYŝUW}H`&ܚ-Vs-A1yUލҜ (͸iYPY(,+٩5q=XYYZo V` *뙾bpc@%j%Ё^zgdq>Di諅" 3*Iw5Gd!~➦i΃`dQ?e0W%Y*Fq⳴O FjMYY< D[gq%D SS~-#4c,lpW39#ڌK$PYT9# Aٜ`d9G2$Knb +~ KYXVeFVg3Y[H-:# QuL`[0"V91T,͚ȒYtY԰Pk`dIĒY k!kA$rdsv|^YK(=ddu\0* k ȒY 2 @dIdY),,Y@ûE;LB=~e%"!;x'%BQ/=_1 di/J-Y̑L18! ̬8hS"dIhhքiy'hH,KɚEXZըf,8!f*%3! Q d!沈a9 Ȣcftq2K{pbҥ>w?C45D$Ṉr>wc/6XTTuޒKjౖX[|:DGzc;Ҿ!bv" 7 +& c9E#=2 : c +2NO^E\'ca]imycOj븼+XIIu [ 2mb^B[Lfca@L~hCsX[ 6|s J 8Xf)!tWL;5@pݮM1lj:fRp,6^}E2vLBm=JmִXDN  e:jͺs\@ AȢl<+yFbdMmD:Ê,X['8yy]X4:=40aYk-uP "lPb[baD3Ԟ%f -$m(ҁXn\v'@mn%94, X  XXau; LBa)QF. k#5Z: /Nai^lYv0C?4: +)W!c牺дpޛ{E^m%sܫAY"Y}^A/x +롏mJhu 1JV 9J:vؕBf3XgGLsx +4gЕJ-+ fRxgW-^qux=^ML +-V,bj+؊0?_(T-!V[`+Sd mH;Jeg`~Q.)P+2: +SsċV+Jz΃h0Xt.gu-qT"pVjhe"K8arr^読{K*%X8/VbWx6ʟUhn4UfxwF¶H!.MR{YUPǝcLCy +ŮP" kxwt + ܁cWpWyœˬdaP\4-OX"Wa}rUQh3O\Y'8J#=Wѱ= pۮj+\e,p z\_Fk \Ex]g*V[%-}pſFl4snj +[8[*AVI.U8}'Utk*Ds[Y^ԋtWOlýA3EV1[ RRX$8?FuOHP2jARI~=c0{U[GG¹UK-:^]"Uh89ʖ zŧex$W!U[ v׽TZَ6ӫSW'ZZJW-1UsѫX@VU4)0B7U-ë`Vp(\kYJWhA;S\mV, WIU[ XU^EGk Eҝc*]a1[<Į +)U[ %t'8JEF'tFJ坍wAWXy + ]#,*3%&vbw2*]! u1{aW+ibW U߉]eLN"EnBWYGzuJm2 +Q:stb,2JG1.:$ATHQ]P2:yeeU[tv) v*dC߅BP'u]瘱!e2 +#-]ڢzvJ(plذ$]utK*DN2J-uXɃU ]ZaQ<*qyTYRp\m'q[WѮ`UԼO's}[hailPwָĬp//@V=Vu(@dU)|nv):*]hUK ZXkn_XUjx帿R U}BfUMs:J +mRf\SK;&U |`aʪWEA86jno`Us"rc`O; &59jbr1+&{;1?DV:5>WM%im Mk ]%aR, `5T!g)2oLJV%ZVn9JNvC%q$U3 P[h@XLvg aCj!XoGD=F1NlMWJt|mpjGh⓺vsU\,=sXZZK)oQƒU*5RI J8IgM{>ywVl/ʙVKUg Ic Z DbrXؕcЗxm|GBKU fZ +@E k(ɚn8=OTG?~ +wTD,h^N =QN^% U#g}2UkWnf WX)=*vV27}>JEPImQ8,X廉05a Kc/f)á+j(bueՌwSXx~_2i?Zsb+ܛU-9b#XMb\:U}>Ng1nE˰%󓰐b7}/!K5*UPmцƙ|yUƾ[*[@ +N +ho~KO_硷^\q +'434Rz\բ@sFEl~Oa7:d +}ch[ifl%4AS8[SZ^hK'av#_q[{mMuL߮/BTafF\"b0嫅9DZR[XlUcʇjݽ \J)VJB?=D$aŮF~Y" +։fݡdauFw!F1]?;YS!!ZZ#e>')Rj-BQV$ +#̞,n …jC++΃([2ymRk'qWB_qNU!MFxI"aY@'fFSY{iFqID=Y(D9PXۨ0x\Up&Q*dY1B.X*ٜhۮ۩ѭpp(MyvEwqJp}@^oRӦB9XA]D;e.%IȥmǤ,VT.\[P{Sd+(R^qrDyYSe ^8"ݔz,qQ=R,t*2ч_Y-OumJQ RwMnvϴ =+܊)r46ߜdUk}IXZ iszwbv鱺#-v ]%%you‹#ҮJ<,] +}֙Y8][UG4w8JcP p[zZ>NQWm"dKnR\RFDŽۖTjAZÔo;;i'}uFO_яdq\cC5# 8-f߼{3mBeSgN9KqXMkaλr[ݛ쥙uh/ͽ ) +͜NT!;r"TWLjp|cyʝ ; {Xq ;S<><qC>2R/%[Uo֕R{ +2UsE\^2*Ÿ8_Sg,ؠ/e㖦ID..(7ʹZ P{cN^f eRWfp(EEyRk +jT)R.[wNOGZO!!m)BV\÷]y|l'"uxMQy4 T[Z)2o;7c!MȍFŰBt)f[) lU'rWlFfLJ 3iQ!Z&NFz]G}G@qELZiˣLڄ0E^PÆA"lFRO31)²ZhEwbfjSԔ5%rԴ})Bϓ&7L@~+\Қ%:[d)i Ykgx&8N~Ra |ω)KcH;a ζaazs`.RWw g4!$7.%oEH} "˜*5)_8IKk;)* 3f Im v'l +Z^L*]ߍwK [ib_WZ^O'Xi6_e +ӈGއt5;<յrWܒil.T؂Ʃkqn)8*w͙D`@zXam*JD(IU T[uyid6LT}I"@[PMݕ=*`o/mQ6lL.H50c6ZNSmCǩ;0!,;1&542-iDeo2vKవWe((6HeJBrL@BU56=I|,~k-ޘvC;^LT{ +V"RȤ2@VYpiQs+BUm'P*f[ f봤౓z~ԴϿh{+ ubR1c)7qJH ~ UKN딆)K!=1?{%3'bߘR{핂F(2`wF(@]L<l!gw(Q I6 Qiinwnp]jJ'μ6IY=ķd&\&(+pQёPP*SSB}Zo\lܑKWў}#'F%uy5/j{Tg9[kLD=gPui]cӦ%+:5AUpIܫYU(**j Cn q| PmTAIy)_E֭Z,8R$Q  ,DMO/7^30B4)C;pJS(TTj^T:Pp_YL3AA ,FCA2=5Ǎe`3]ܵ]\0k3xW: F*LC;gT:Zu5$H5XQBi7aŰY?y^7U=\VO/T<*I8u)iu0 +:.bhrza*7*xg:!4~Zl%X-j#@uou?LQXZA : ;AMA_yyHC"W5)18ޛ6lTv8BKd )QOMtb鳀t;fs8S7Se./jG\N禫 l10."k.yrs%c/ Z_~z _3q97ӈT_[ DtK++KM^ٓ|c.tX9Bch'@:=?†==H"BZB%zBDrzRRtV,_E RB{{ aOUU̓C&5Uvf΂1_$ԫې|`ؔe0 WlU bhrAݷ\K4^|8larvJ"mo0JYp + +F 9vU@RK@.z*u1VJNj_]:I[ɒnU Qs}`n9HTD<0Va;mPCM Rh,PlS3 Ħj +}z3)gjIeFǻ`K9oyCn+!'Z;/6P 籓gO Zk춙>WRdܙTP +M @6U>A`-BdvTBiBv$& k %հ5j BUx(?}4ф93 :tU(WRT=v@&i+Z}Ipڨf`* EdNž7L$2=0<vEŜav̊ydd7cQ(k;[x?hYՇ[j\&ؙУ?v\]_Exvk\6-p]7b咽,;#͗X-y NS^UYr$Xi#YӅxކaಈQ kl>;n}>m˻Ϸ6NlZ2a}UW[ k4REC+vzx?¼RNH4_n' {–sX+l; $/vv;9p5 +ڦ ֵn,-A<`+~l㻝r rT`^!o'M>Fc1Po~oFhCà^A }w/"S5$zQ| 7=Nl;zےnjETUb~ڇX f;0PmM15*S`=ƽMr2ք (v^LڝgvOJŬZ}y* %M*Lzu !Q(}#h5b5!/KAS_KEp_ojxQuJP_ oJ8]T%ƽApvB=\4UvߒO8BMXхYskBzVyCRN`ɘݻϴ]i]DA9_ 2@ r[7u?lo0gTWmv˥oT\ h[,Oe~7 $E3g>n% i4] 4QTd%g9o+}ٰyl_:pEx…O },TkQ<81כGTCęktzQ'^>cćO϶|0f޸ uUΣ_Ec[hM{@"?p]uKYZNxj^ +XN3ŵDx,g47_ b (ww!T?i$TXn9XT$\B8kf]Ji;anZcZ>F/=_aV4RK.PfiE)wq`JkNV b*cݴrӚ=he& ʶ" l^Ui + q㚷*|O1R}JKS +;Zџӎ _+ $J2'ۑ7U'ף'afPbrZ=ꍏvI5ˌ)WW m)e5{r +U!*[#=Nv_J<TȬj+41-{5NOmWT{wk>V۶0'imP{z$x|=0@.JmT3?SZET7yh/bOׇ71t]6 m(8Y*eC6dn }-űr48?yqU[6۾_.R]JavP sK]670TP4D.: +<7onIFs`[mǽ6'Sn`7x +7'8rN'\j=|cv#>;\q[饔 TlO@)af +͜3k&`uH^fFS*] Ι;Q[I.E +GX5KW3E3u:o?=yLCyƍά,7VvՀ͜#ΔjfGtN^|9vN4~v^ۣ30F!ŠE!,{gk#*  47uN9L8eeZFL!4;7M R̷ږ(scL} ֶB[U3>,L 8zGFV +qk!+ɸ&'n^ey-T͛ns=}>]DŽTk $*]؅V^e1%#tg̗6 +jyf:Vqzqj'R xs*,Ҳs gw@!y}L(f~s%7dhn5cTJj.H3"WP3/ [PeÅNۅ+ʦ_u.\#qSx6$[շ%7=Hy{ɩ;}@Cm##nvėPup]귿+x>$BeD0yMSR.ˑ>TU6I蓤(w{&{Xn* Bӽ=K]ZJF%%,`Q^E0lDZkm:c1SXxhX<|pVf|heFNZÐPr}T\mY!! {mn24v+Z^*5R-[8ubzX)-4^'Na赎,/*QibD6)7rKč40JY:TZiS( 6 + A em9P3Fz%ncxv +u&{]JQt'ceh5s+6;F:f] A'_^Z+ԁAQ."ye9+pvgV!O6wAUG=9(QJE`Ki׆%^ |(=ᅿ}x6؎̾EY"nBBr+?/bnу<o0yIaÕ="= wI=݌de@:V>U;Kd$O.e.j4.Н>YeJ/{] +l`mqHIKVڴ^s4E r +”7 5cC#Cr7Bcb^YZVS8{@z}jؖ m( (ډӾޢZqZMQ*Zz)iI}Azfv^*v_,5albւê +BEã㪻8D< \2"^xbDӂK#Ux#+rx(K/O";E$/2Cē{=KAT%!)Do"/D$"V*Hw"J?o+D#2܇J!⡌+8CēZxL&I(-D< +o+T'/T"Vu_"=ej_x[D:O/x` Ou%m[x8~xdi +4}xR+OJ% x+P>DN$4 U"wR%:_"RRJēӗ'p*D<\>DD(.DO&♝BēRxRD@~^ģأ}x )ǙD23Sa/O +2/) u̝3 @<|xR+Cb ( (M[Q:I-@< /83OTSxK@%3e &t@<\2OCJſ3/iWx_  +ijxII@G1q% jI@<)_ ɠ|xR++/x{^Ъ񶒁x[ UxM ˖O #fZx[@ GGqQWx= +3+ OC^Q\x[@OD O +%IVV nSWx 'P +3?@<{3OJU J+o+Ɋ~xz+O/BiV & +SaG42@ d ^RoSp7?@<+|xg g~x+ J/)EuIGxxZ}x8TxV%g%%@<*;O_[x[@OOSH Uc)@<)FSxjK@<\?@<L Ϭ2o+UqxXx ?+͎87F;xWx~x<t@<7 Óq/ OJU2\SldPyx}yxBg=ȗ'8,$|yxG|yx9 +oh;A(<<ť*_4< TixVK^ixLK70)E 3 Cã. + ?4<-b* O_?B|CÓzQ48< + cp/8<ݍ#,)Pqx<tYdBAGDVqxtQOߤ?%j!u&]ÓVJXT;B5_BT,_G%ZpxA p"2ѣ'9f^UuGIюã'?8<* p"9_öPT^`"CQ iiB~i4cUefgOiS(4 83\/^ᑡ8< ?8<"X2 +gF8<g^8GN)[qxTS}px:G#ZpxjZ8<;3_^>qx*>8+4< ]1ixԡ~hx* .c&/ Bc /4<&1~hxAÓOY4<) ŅlЬhx8SѻEo\ /GyS᩵ Ek~ix*64Nti^/(4<~ix6.dz.@_X}hx$ _٪u1hx>4\.4<)_*'4  GBf!|XxYxzF+ j BCa + OJe :[~YxcGKaiX4?TS ۗuBe 4?_£䥠|QxRPx|/ +O›QxXXTh;($VBP]`Ap E!JAIf  +oೠ|Qx7ƌ›Gl KjXג(<Qwk@yRnRg8Ix72XSMxD&b$<vN“&!$<w/Hxz,|$$<W^~E£C3,$<å@u1^h`($<$<ۼdueD۪I}%=2 BCL$$}\&4gBJ&m5HxZT$<,D + 6&m!$<2 oD"!M³%e" %I,$PHxfuGC³.L{-$iVvVB7 K) <GZTAx|T᭚(* $^R7V+wlAx'˄/e[Jm5@x[L c <)+ϔ_V3c) eQIEdEt(~WvZqG2rdѓGg(}%"+Iv9 J-S@vڃ]9vl#9ŎZobsyotr8O"ر7OR\FGbiॎsj=&@t{/z߅AˑNG7NN7H~ȘnM݅,Şkuޅkޙ@,F6ŬY@(ao%5ճ<ǵ tR tR|@ה0l@7mǒ@)8z6d`Z.94ʅ?»i @'\,+\fe&- @.? @װKsj??qkohInٶs͢gI=@'8tmPuV]ï!E3݉ A:!ʮ ˨ {簒 ؜9ɽ =}N>}?='aԿp4乓6{.2uwnΉ(wtnc!aD!i{P{3#nnkF9U9Q\9B z*WNlJ+Goʡƈi:83">Gd9=Nwgd9^B&K=7Z{==/{ۗ0X\`9㰱ÒRWOY>ٛLNCog嶒r[  Pž֔]k.ub?,xklbr q Um%`9bf*k*Xt0#s, jy85Mc+qi͓8Ї^S:+_-jPGБjuȝv*#9ZN -6sZr+gD +3Īt!R[ ڗmTSx?-z7'mZ.) -@5B2xgEA`5;iC r[ > q +V *1M3S0ja;J-lw4Ng~m3`9)8OMO ,X E1@Ym%s\9nӟ +|`99X+"V̙,g6AD9-JV"ˑcz ^VE,LK:od<IO,!tfEbd96YW Ʃ[><؛ue7 ,V0 5~d/T3m&5XYoDr͈fN + dPR>o t"L۪Q䚐#*RLP>"'9㸗VomUdMNCyJ3Z$ %AUT[P䶒)r[ ^dZ3Rl} +,9Dn !%g?gjP2F{J99q |)zwm[IUmPNGa̙2@Uo5qf9)kJӑI V2@nk2~ý5*Xp:Jȟ+; < SeZw{g4t^^8|+_4w߶]D8puTGm!Q8eN潑q Uq;l`+޼RIQc"VymXC+'_L`[ؠ9't? O] KLpwg%D69'fiٟkᶐpK 0xsߢ];04 Jm5p'npb pʻY=@pl*3-$-3{)ؼp:=Upڱ]{cᴹ۱]&{ީjoi8$ +@ ۪ᬚ,>j[e0ݖװ#;K}6 +kÌ qd/0k S|`8l`8]~_ +>pIMT2S#"ISep賒Jp +Z`qV2!ޮM#(?C󚷴]p N gi#P(8|TE)d8TM Gq6pVwW4'&}khxV3d[ I^ᰔEG8!c/#:/UǬ\8l}/.JͅLSps gf+n+̅#^Ow hX8 , j$ ~e‘)^aQD%p$I*o˩p.+T8T,*6c2 +Gy+YIPPT}\p7kS%.p( X8;^5p [p6N c(e(w߃YN*NM͡pn@l˒3AAeDf,(f>BX1*)Oi:9ΓGl-NaV8s_φ` 6ͦ41FQ{ߕ̦% !䴟\6 +M1fo %R F[ 1xl?Yql!9͌Q熱)`ib#m#0[N}D2 ƦĆ?c  7MgKUg[p~/RqZIتٔbkQUXlKņB5Xl +>kؤ^4(~3Y)LYl JV|5S[XlzM +FbwbkfnYPl,Ql (6)Z&V+4\XPlLMaCMF{].AJ[=Pl*rؔQûbSQlņ,6TTؤZT&hlRlcvɖW'kt Æu!|IT" AooX+I/Pu3b'5xƆop 8I M*Ecq2M"yظņ4YN՜Ŧ\e [#;b0j4^GL,6XL2{st&bkғ0~~eBM5~DGM{b1 {t'<3L5pM|ih#36͔YlbCe,6)fI1f5k7XM/}VfشYl| bk]YlT+ pvؤlHb2'2ϴI|snJ|i$WE~d DnnYϔuE=7My33gM#;=fm۵`ltoK`l +^ ~? | c3rDVal8͇5h +wpͰUal(` 06dalt=!06\<c[all + +S [YR`l [#rwckdケZ%`l=7ԲBcShc +%p +c÷,6 Ʀe hy0k:czˊj j_i?(ؤZXlT5 휷c#M:hlZ'~ p86xǦ(kc345h86}c3cScӓnQG=Sz<6Z +[`Y5&Dd֊H6- FlGe۴*dӂ&dn}^=ld/DBi3^&nt͂֠uD~oNdSBpd1-eLXK#*hլ3MoRP?HlG޼ 6W: .kDbC(6q +Y ;Ŧ woXcw{h&VPl=EF%%(6zgoWZFj ņ-Pl(/tv:ݭ20DXo8 +kƝHlzbAlf>< 5f2-9U۬ߣsؔxshU8ll m+^,58l֌?qؠ}sXa pP2ob(6z~s(Un"9XauV,F pȚw<=z O+"Q6{8cVx1> 62i s bLŸ +M*AHrDR- b-S@ljaQfJFY bCe  6ÁmsxV9sؔ!6J`8DҴ}EPt?lӯ|ZV$SV)lpK e:э9+Mo9@l +Z(@lWM6#:&Xv^6FoFԇetC9#DmWW`ۃ勫vxv뱙j[hСjy"3 T#="Q4OM||SNSBB(mYjfD'I HGn?B'h*;g4NCZSiK)4Sr ~v.P9i"E,FnT<4z{wSϫZLNSX*rǜ#̚ig4l\v~24,KT<9i[HĴ%0F^R-j2.M_pRKS h1 -M KCJ;n/kW%ѿVm洖yI[bPhpF)X_GHSQ&HP`A ocTgB;Z*Nz/uZs"ѓK4k.DE#Ԯ֬!92 ywg7.|4mY ` ; MlLˏ;rr;u-@ +0@/#!HO?"d5!MO|4y[,|4ml >ЬNI|gѤ! >;/ F_BH+ +exDenҬjHSGSTܼ"m +lѤX%%LG5TB)Пh~u^hK\hRh=FqW:D/s<sc yh]!3x4%Ҽ1TƣI5_ѤLGGbŌGC89P+)JA5D>`ゎ֘ZNlњ$+y:]|1%Ѷp4m,mg:8vqVNGjx 爴 hݖ֦T$M`=#M$ HC it{~^~ݹ93$m{a}fHJfm5i憤iL%3N2HFG}HS,zNdFBn FThJf&iCٞ#PzHj#&z9;# XfInsICEs@Hǭ-Hnd:$MWqxؗ"-EH#~0;i&U!1r}'IG#m!Җ +%wA>8x[!Ѧj'l3 )K`AI},rXMBq"/@Fa8./D2@g +F9GG- L;,kψY!t"ɩy~޶/@Pd=3!L BB~2!M4B(eDujև2k" DV2"-Hu 6i狐FU#! ƙjbGYgBYEw5FsM'"(A3i4q 8"-BH[bdcztHao0..>)O48gG qq/KhࣩviMLG1;h*~fBɯ hwv#no, sM%8m Ā ϙhӹ SE5D{e\q_~w Mu!iR.U +I#O>vL0Բ">Zo?OS "iSZ⛪yE=&ڎ䠳8n;ڤ9Bm;-茸4⌎w*{蛣6?)gFZǂ +х׽Yjj΃uenӮ>Ԛz`sZxj?smÜ,,%՚Q:QM&Bq>+л<h|\?sռ mo,Gn-ޠ +Win!gκt*cXU>J 6ΏpZGVTXq{QR +qdh++TRR`wΨ^rmSfS唵sR8kKyz"mސVLH!OW\69^B#!^dwr]pWyf4kjm_<#M ͭm(lq8_,ը-L0FzKx\6` 1R]ö o)cx11 @OC”!.F5U;F.< b~]mP:T"m5N#0L3_"mRY8Wt!鍦Y _€jQ =Oʩx2 +O"%!mo;|`)ϰ2NͳլD"}UT'CUzԙP? o_ u"t(K+gEێh>'  +x^)*XAfPy~<ޟ +A[ ?gzM?7䣼 s2jjͤCYQ*BL3g޷iACh5˜67{Px?qȤ}VH)-ף_Ri91:P8e~8enTV퍆h[P{C߇LfEYJ\ٓzm*eUDM6~,tx-"RM* T u&t)OX>vjT6Z}3ls+v#Z襤n!IgE- isc+_ 8ž{_V6M׃ŻVc` P^):?޶U%عs_i%M:%tƳq†~uUq"Y.: j$Բ|Я ͤbJKc_RXf1)cf'5WR +hK7l:Kn=[7mi4|,㬵4՛uD]6 o1|SlCA3- 4IUۚJ:g-yWԬlVs43ٺok"V+wVT*{u$\S*Q9eB_VqPX&Zh<0c5ɫNPc7N-T 3`Z[ pV,E®oSH4NK۳cI_Ÿ֒Kљh+a݅`uw)'~ =iP%Ym8P& L8@*vZ6 U"wEq{?#~H9muz,ػL#M՜ٶJfډHySbF`J*[N{tШa+l +RJQ~G0ݴZGOYukۤU(".~yy?tI x4t3`K!G}<>T"+<=^a{ZIҙIp}^0fUG/)4ڀƛt7Ѫi7eݤ oXK6QvC'ΙWGlֱ_>iϒc * AM='dSx&6_NzJ,&̟iM;C_m)vQAqOWb[iqX'y6O6۸F(6RW %2$4>yKǖB.(Zz [L7,l=%~F5FV222b8YI(%˻p"ĻT-xv zە)))jjk5W*ⷚy(yx؃qKAKo#&%ʖ2FmUn#ݒfu)tm!ݤ8ni[)Jweз~s_xXL]ؽrg+ϱ;/UI\z'fYnoL=)+q lf+*!+@h9_wkzcne=udDq){7\NLY_-T"hq`kfk|n_`>i ?}@W>g^ְj*֬yD9%2鮿P. ';maR6bvm!pv3i~6i*$lCH-ndAwg FFg<⡀Gsubz)2WG>։g{]?>kxpR͖eQ,>lKatlYQf$,(,`o+սA*7"[܏ؒr~I4o xŀ禐yUNqTCHUEI(ϹU.Du;7V m <Fd>Y,&O1û$):z7A_=zNV2Mqao![WK0M*iAʣp%じ Po;zB/7)Q"BCQz7I"/ġx2jKZG1"(xd(X +8#*9]u3xF+EN*P3o'Q>OJ'C9B$I>[tACEJ9. *Fi-T5ڈqX{,aa,;]8=P5/#Cxcz2Q|Ukc)6#K涹C( :,"!]$e*'uY3,bna443,>jٖgBe|Ի sRvU>f'I(px lTwʅn3oV>.HѺia,78eޏ +YkK!=1k^, 74Jtͻ#[iCIJԈeJhFYL8feZcR_y yN;fqP2JM=WzU|;z˻=`a_ږ4h=gU4}$ S(߾6K8"y̿Fʂi=cgQ~:TU7+X:Nv͛M4--^❳Dd'QIDыXG]7a?ӌ};9N/b7`}px021i!\@7lCEy2FZy T h"0#}>Opt?YxE;(她r9A90'!F9a^fz% ߞV'͛Z +bE,hfxL "!g8(9t(?2`ڙć=(WEӉf±Ht-YV97P,Sc~"(T98v)Z_m6^;O}=eƆ|عˬqOT&E6F)8ۤ.c!z!v>_:IqϢC.Y̨<6qD {09En3ĆΝS f9 J21〝eNƞsRy.Nn4V1"4B1荐 +|N5z,s(ݎ+YA;U-'r%څ譥݂O$n2ӗ´vLzIǦ/F\(Xs$yw^C=kU| ޤZYk|J^2Zk"3^ HSUŝ^sH2>łE5C4G" f*xt 0v``We)TfkJw<7 E\L# *fEI +R)խ$$h!QhՒMi:2rDsئ6vC$a,]c^NIa9|ˢbwHa.%(;->f2}}HG7=̈́7ܡֵAdN;;9ԎfP'Oj&MXݶ0Ya9o~6NǮvTQ=#$F|Gy序nAʛnCd߈+LS#O\D:TV9X "F])V`h6bj:/6j&TOt-۔,"au'D BZ +"L[Q <^AcC lԒK@WC/{ޤ Sf US Rj$C.2B4R&Ȇ'wB>2ѫt3rtfj^EϾ!"{?Hg{=a4\VDL|wЌAT]9h} IR 6(+@:ɞXSRROD2qz4^UxS>ئU j[E?}n HGFnA,vh8*L,8D $yu,ŘeZ^qv Go`Àظ3c- i sQeFЖ1ptJZjI[.iec|{{4 t)mngm hT[^Im3}bDrXq3TiGΆB=JF}c<)ȯ"II! X%ۣ'ŠEQIOzV飉&ڴ2$.n;\@:Xw=VP_I d0;ClϺtxCż2kwMRfImvo+14V {ѦI*eQ2c.;feYFQ@w[dXL:l A*g*Ըl(mzJ JKh|ֺJv\P:-hCMp˥CTXXFKh_@y<$eAPOddRs:\5]mN1;;tGql+/?_ؙIMBs~bj)YC%UEM*F!jB10I{ۏ YW;R=׬m!'EXB5U&lٶ}#o 9i=ZKU]2Ewex*NNrB}R10!L$ >Z,W/$It-6KsCe> 4* EkJ+:( #qEB-(o'(Y\(y<5PN#3k.fcҀVcc9ɦ`PXNٗ[ĒχM-#w)dbl͸wE@ʴh>PD-KRoƨ;[Vf6}g합h>^;"H/-Ef=L*DCgwq|72,U9g*8<=4;4mrsHv7|ԮdJlK_"(G KA*jSNl֮{Lˏ&[\agmWiF7;2L r4;<w~ޮtx]x7y]睛i`Sގ{쩼GbƎ,䝤H'+Ǎh!6N\¡9iYUG<° [S3\s48W.[igmX +}Wt=ljf'x +1m"+ɸKw=1'K5gew,lϡa&R2pz3N7F|unMjX>EB0N}(mu1hr!7pZF>gZ~9ޫ'= :EB]c[;6w[춱~$gU(mkj H)Tm g\8651Y(H# V?|a]P"A"~(%:2 g:#Xw ~WXo8+)rn.ia;1BT iuY-C%??p1758 +0-3* IsWw>Rid+vi)-7BI$ɉJ{]/֙qy=unqOe h0}Ը}@{k`萯v}mS,x #n)"Dvʅ?cz0t;ކb<(%hFtR5*eBͪaUz~ ,+Qi̴lRoB@ʢߡjnJO:˜N{)kWғ|$<ޓpB.VW pDo8yBf -ik1/cHfc|s 3m|Z0+PVUK w[UnO@|5"sMArkV-5xF,-ᅐri?n<U]Y ְ&bgvq4'xiwQ8w^8f 5Jy)<n)Y\fZBcB0;[ӊ'B /\U`N x1DoAyOfk~-w"5"ϞxR+cDN+/"pD [B jX2P Ǡ"HHςj AHHE1$3B T$s G̳ T$W$c,HExguZxKD%3e"^盈ןQxR2/xDӋe(D0aYxK)D\!"J֣Rx[ "JSESDc\pxo(2OqxR͠ 8F/ru Љ9dD<<<~7On똽+)_yx=2dq#u +2/vxnCI<<ó{.Wx:ޟ#yx]oΫ<<ݍSSx$2O7+ZxxU^?U>/I*<<75 +c.<~óyx7O_cU<+뮒ׅ+<<^o r…yz^ +ì<<+WxxX OK7O7OjuZ@gO5( B4q4eUf/FÓ)oRyx7W^gPTxxi`u:ge)S#yx][9jJ;xx OQSãH'<< +<g8MÓXhx O|1BMÓZixR + Oʛ'𸆅Ma OJ|+ cuae 4 ϔL+'.jI4<)oX7>틆wMÀZhx|Bixzf O@iة4<4<:ף$hnhx<7($yP3 OBIx6)4VFC"Xp%/jAY{/Bh{:H³c}JAq 'eZ/ǂ3 +O&7 +OMD* +r£@C-(<B)SPx +_gETf>0d_(NJ08QxG$5$QxTjQxjF+(< ZPxR* +OG]~A-( +@A :'cH/(oRha:N/rrL/Ndu ͙g)fy [GmciA7*u5-n&Ub S[ΫUk} { 1icJb5sU״~ڳXu.WF53uC.kXSQu\FIFIkF5&|NGL2kj/IuMkcMk'T!zPx׃T'窝T'疜T'ynRuSIupoR]ҹAu2 -:y6^NJ'ěIuRv&IWۤGPakgb5VwBT_MN 稠:{ks9T: 'nͣb}S͸{CNRHOeԩ-#wh5.y1Uϓ{mn+AŠkH l~%\<a,ςj 9v-'GE5!fV{#Yt4j^;JƼr8X<@'&qy]@dz +.=9.QtlTl蒒t[ ]'=uE'z%Ex@'Px+t,bŜtk#8v_J:ML( +&_[n+A@u6W_ax5bxO:ȩMb Zh̳AGé{py4Z)ȇg{νD!ΊR0B5oU` #aZ,] 蚡gEi׬frش9B*ߥ8p: C@'͆R!0?0Cpdߜ>'m$4,.=홆Ö"FWKsC=msXfΝ9d3QJkcn蜖z +sBqoN#sܼ9ͨg?7n#Sisf߬9Ijn 4C@=8s3mȘ9=f䘹&قkT\cc fQ.V^q\ma$h p}3e OPP暈G&xY)saE3'5Ze*q,U3fN?;0sz^%d3טkbD2g)M{Tnm%9m׮6EɭP6/m撒hs[ \3n[9~O5P6mN +E2b6'pPϹis(ZeڜTVЋ6/{k[KI\9>&0DN涒is[ ڜ+n56טG>NO ?_;.P"#yhqs[ɸnyDV*4Z nN͝ ܜtn + jGP{ngSqsM#&7h;m%斺psz)&ők +)>-aBZ(ZeiPFkJ99ҏ8Is\VIsR~Uۤ9sw4z&I9[9)4 NkJ ˜4Bj} =5*9>-ǫP՟FA`W2eZ2wE's.!o1w]]8kS?+aNmuQm? W/ۢfigA) d9yh>kH+'X9}CQP0;mA)L9Wq&m̀r{6%N~O]Ca8r2Fd}9oơN3B(%AN{ޜX窕V΄[Jm5r'nb rʻY\-r +666?NQef8Ell~N|Xe~+McK8 +u评 r[:AB,Yߪ<^](#fA@?KkV9+A3AY7{䤐]+EI䴷=m9]~7$*} X$r9n'#f  s}V"|Akl r +7#ύS>XBq\!(5&BN bF!׭r )v;^2A.PrJ,? υ!GBbșsj!5j[^rP-4Bп!Gaž!`@cbȩR<r9+CNu$C_D G290I ҽr>ir(7@EW>\Q}cX)ne?ǁ¸Ώ7gW~2y?\B-8+,|\jAt^5^sl|beM鼂 e=.|'oPX8 ?K`[dL/`55 +~\͏ӐHߋqrnzC N{1~:z>gi .FkOv?L8 +G6G[P2"[Ҏ\-zf֬GKEc89)q4mjAa=)}4cS*8]EkF(c"3Z^$(MqyOSVayX 8}[}/ 9>'z^8y8,V'_iE]OiuL0q#6]gVh)O85҂j!N ?DϳqZE<yÿ#>_8iZ,X $ذ8箬8}ymT4Xޯ>}̤`zjpNrQWN-"8qZOk`. NM'ʉS9݁')1)Π836(N +CQPՅޛ8O8}ӱQqbdG,>:˙@.<1*\)N}A{߁gPlNϳ~a&) qg#%#4snB]v}'>p-*N5')3o2A}XBiEs2ǩsޘ_yw$d G ;܌Eu||L8@ N&@ Ahĩ +bCip|)5l6% +N TmM@p(2yfƩ1Td$Vij#w)N#h{|YnpBDBO-bn*㙑h$&\}<(xetzFp +M\&?(sp?~SV~Sal~4[70if"Dq^sakr{57M嫟)4|lYo/MIn$o2ue,TBiߞdM#F}/rb@C3-@=J%.QQUs8A{1%ZӜÓqo{h+:M=/۝鼵 z?X1op߼:;z`e|>H_C6 9Nq SQ-)?QooooO8d2g]|76}ۜn +c4 +n ߲$Iv33ʨd6sݎauSK8+v6jW{7nC )@ay0Ώ'U+ +w.@scv9G*MDF+ʍýAnR)vB7Dt@ܔnJ!- ։wথa?nf6=rm AQgbF]ٵmjn_AYmP!8:MmS'?C"9)A"mF2ڦ!iQHM:9V ڦ3M'[5mzmԶ|R-Զu6ж.mCe hnقIcI= жS7MUSeh&9ǽm$-s5c-6T= &Q@$\@$V 631ۚ-Ge5ʷk3ۤxlɓHZlk.H8M{&kؠ!1ۨ:c3۔{\{0(6ffxv^ m }Wf[نB mIlI%,mRX5M<)6W/ 5jr6& )DEmd6."!Jm4^@)vwʏΖm6=%=hrum:ӼmkIR3A<,m*#:m}m56i@ۚ|FIԶMW?mkHMDmHYɢ27m,\&PhbAۚ +mk#oh[.Y6Yچeo-ָPF#Ma'6?~V +h\ ڦqǢqm+ mcBw@Z,h[fesۖhX WV鱉m]`6T +&c3ۤ Ɖ m@3m" aqVjl3RP(Tmdf6jS۔8#cXmt$G6OܮEmΘmQmY6FCXxPۈO j[ekچ՜0mT0Umm(683Cwچg6mXyK2gpQ@e +Gڦ̊YK23AmkDpMfQM_*Ammyj3Mٸ++m@`TqzUqYcG*xuH0#km>QE5tY1XжNgϹmRM0 FYE>چr;nQH`S6v&„mۦ7LmSnf@jL1nG n fj)NI-Ep(ëmJۂ)m%NncXݦ5Nvn#LRa鍠۴೵I4|_|Wd %ӽm ?m]j@50Ͳu ݦnSF +sg5 +imZ[e۴g۔ǣ:&4:C*l\6! f++#z6Ql ن=TlC=SRݙmz6d6$zh %&"8lCQ b1W,4 +꒝&bl۸0T@+ǫMcY2M-8٦*k 7^Ai@l󄋿m(8/#se0"&_abq f8fY>*M->w` ֩w{1:Vm=Efm%C’6gf\of[gia`ۚ نH`%f+%CaI5B0ۺb<MlS+nJF& %!۶61d l}}%%ߋͺ'` = lC-6 l!`lQ6DrL)OmGc Q)PSE/y_Dl#fg")IkElk=ɤyVb4ubƙqbTAl#zy9;TD?U6g;Zg)p=pMa_<ĶX+. l>qm[û`XT$e7BjòVc:ܰ4pHkapsS0aLx;m:m%yMv&r4mTfLZh%d257M=AЍec](fDj32p? :dޔ6b%՝kl۵ kj}k}#lI|;S/yXGWq +],KV9jKh-BV;)JV ޹jǽ{̂U9SgC$0S_֮T-NTz-2OmS# շj. 8ǦWS>>+05a 6aj،4c|VeqۉԶ_J{;7@X!RB8KMIq;IّIj+Hqiho:^'j9۬$5SG㎱Ij\aV]*Xj(22Ks-MVcԴz +RRR6z$Tn 5)'Rk($5rV9 )po% +mRSTܼ"mݳI][Ԓ@j^Z*!@j4Fw gܛN]55%.5^5IO^@#pZ4qQrY_Aq#G+dƃDGM2G:I֬LtTwƉs]hMTFMx +QF1 禨5EyhwIEM3( F FMcx?8jII IM0tZ 2K 09MM6Zd4چ!05}S=Ђݹ3Mm>m%Զ05sԴOfajr'Y0/T>ς)m; Sk Skdk;B5dVp`jRwԤX3g!05>v8M ASk@%˶hjEFSU%R[ZH)QjLz])xPj[(FZ*H8xRQj 2@gF99Agm!L=,뷅H#f .7ϯ)}>V'bC+Kg@iAB)Ȋt.FhvHAWvʯ㚻HK-)`ẙ,5R#ݮ}Buz?FD(5T;K.gD=RèD)PjII(J̒#z-n(<>RS/*L(5T<ϳSccYjK(%Ih9;zxn R3I,5@jtd4@N#9R >n] 5kXm~dǖ1jC=EPT "3Ԉ"P n7"MM2)b4TB}MO[B-1i#:1$gR .Iᕱ;GHGڿI:͍Z'WX~H՞Ll٧x I:*y5#g t[52(qy~#`ȭ/rd{B),P^2ڢ {js:f8''I㰁{O.[^;B + <ҚQ;Ѱ?6 6EP- (Q dV`Hzƹ:HQPbY:ȚM$`路d--Glĩ%OJ>QjT DF1FU(5y:j(ԁұ^`Uc¥Zn! '5d'32}lnat MW. ,΀K$tk6d/"bHʔYoB~q1AzP$VEL-2$ҙ+C`ɍJD֬}O./dRJ>i\#!3g,K'D+1J4D+qTب}2XEGE,<)udLk_L5BÅ]ekl9*~s,BdK! `BYZ-⼾P. \,w d/+FET.<Q^"zO2l ⺤6 (Eg+1Z +R֕ rFyة,D<0,L|-ēwNN/ +3>%qK} E}mCȐ \Ȭ~P +AejSo +lOd\q.x<gxz <"Dz'r+*k t z0DL&.uyԫ pr- D}z t t7V=M5 "rUm渦5OyLu6J'я7Rj'7t:K?',9Yc?7PUJ4Ԅ>hԔG'ֻo֎AC2Bu'0 a! kT< Հq?T*A#N/xׁ y&%N"󳥁JN2> Ggy"JX?]a:Vb6lѕǃln=[G (~H)D[9Vl'k ϊX$2׻0h7X(JM=&D6>1Ь_cK\-if6m]1.,'ZY2Hy z67&gE?#f0:ĝLNP,W(<=|PƯY7dCRY]Qz!r"=\FN٪s. %zKp@Y`Mr ?Ǝ=}zYCkZmSD܄j ds )5&^`Ļ:S,bvdIbNK :kGm{$Cs DG%ਉiEvz ZE]HpIĎD곾 V[u֭ٙlY57J5sˠaPbDڠ\ .ƍ[؃덿Җ &3iZqlIT[b7X:$o<H./Bٶ޲'fh$IbtVi%[L| b3lJEG9D#UÐg!!X TG>m' ..܏i}VFEU{RmSowmZZ[r)nSAC}eOKS`}qX1⠞@^:K\-e#̅2C uZĪIRèWS[/Hԗp MQOH9!9 V\蚮u0Lk/.66?A_e0vi(1BNql"9|l{35y}yړCszzه?%˭f)XƒnM695<+M?@;oB5F۾{?kBdxaKt,"dz6Xё ׈)lXʾ_x6jIBIm;f 4vAZp +(!JpznvM<Ǿv] :\)aFlz,EJ(bmt~  +Ju4fnjs#: /R?FY[MEvSR2s蔨d\ܹE#1KJɦE0= zܖk1k-VI(i; õTg~v*v.vrl7"붨(z(V!u'T! ST@hT \QcxW}K3l,(Zy&!SEC#YSVJTGAaeį^Dp1N-$X+%Ypf%AYv uXw`ny^&N1qQ6Pgf ǀ&"=7Ŏ$|#Rdj6b/3kyU* T\v&MŒx䐛Zv`]Xy}a9' ITDDKvZUĈpٖT 2SȱorTbe .)Q5"ϬT @~hP/4 vɍR}nqAvb՝:(TW]RsfY9kHmE;n# +$ 1H*% ,>ܨǛn9O1 +[uҀ7ԇ@LC(8nE>"Y3'Ņ و6J<Bk@O$lQY[Qwe:i5g.Ԣ Eͱ fm>?5",x^~:]WLQ`Q|;Vt[!6'A$ص԰1|c]< +'y ) ?g0x}VCa.ЪrwFi` Ć_ܺ5r*1N҇%R /Eڀ\PݫKFm1%+- wn)IF4B#$wi *g)|4X\u|TZhoDExaX#:CA@ڣF*xC/̚jЏ{ǃ}To t%YPdLA@t*|jNO)5aAg?"J YYb'ggpv>Kg/jҔ>Q|`qk+^!`F c{쫔m{S+6&{rf1=fOSf凅d YM2m{Kj/{ñaQ.Y1F"\) h$ BX0/Kcdfjևm}x"ǒ롭ݠ^PJThC&)3h dJEOdcu?ނ~( @#Y29t ^?!͍^ L]94%)h'88:YN23n2u℘r͕\' Vz#Rz*;ownTth2mdh_16u͑RʄrȦJQ:C+jAXjM@.XJSNw(ƔHT=c {6+2z k %6k "9J0a{aPY*,I 7W:g"$ѢShцxCE1E&"˙"D\׃чl^7DR`M*5O&KSÓ,g JrWKVJgYUI@F? jQEogAAH/StYiQS\U8pjɭ"ntEBAҲͺfʰ@h )b=A!FղDaAVG3l +RF?_u9d۫9M-b D$IkkD 9Lt2$u=G"(/-yީ͔$ED(`ْ'=(xU'u5FvQbV"݅B/vRe 1fODk!ҕB0dJC3bY<F Nj +/xoO ,&Ӝ^9 I2> +U[K6 7tr0ZΈ}rj6.b֬7M"rcm! a )XE;pYX.}Ja$8RPQ`yYg!lϖdaTU6m2q7Ф%7(ۮrڋP3;Fl[?)6[2Rva?bTRФǓޖƎQzLRANLsb ͫaU7ӝ j֧w8bԞe~}6rQn@|Vx $ކZ"+`zu:esi+4'X0nwf&ƷP=F`jb  Ύ Bf0b6hNO ~; f$BT#+xuԫš8&0O_7?1ީB-B~D(6ַJ c6w*ͶZ_iH;hbg@HNɣ΂e{ dIb{?g0ԕh?_\7O*BNARAX!sK Y.E*[`7l#ZVpb4o 7|7e cPNiԦPhpE-bfmhs_6!do w~L]&IZ-ev!gNѸǍmqmQ9lq4*HUL{E5[<85Z9ŨeH tߏxQR*,2z@̔,M*J TfEp[r^YPKɒNkyry)GB̹׶Fט &ZfB +L[}@RTLj ?j`Dg\"QYM;QBQt5qp״3wBd`B deֽn,9Dm{6kΠmQ2rM`5~G%m+-#[dlf}&s:uCrXJ<z<4a\l.m>(XZ,0 $I/-:VLE(*޲-;z9ng +%])ٴY] Nqf[EBز$,Vnn3E `Q}O't;;_Is)8M -na(n +(skk Lqo-ePMJO5`m<d qPHXC-mҋp-azmPi?8 O5ŖcL8Ks[ΛN77tq|s--#9C']nzl۳ͭ|ٷ e ߗ. [޽BbAKRV/QE3G1eLa*V*kQ~̶umH"ŒLװ`y?[2r4QV [&d~>r c–z$SEq,a"4U MP,C +۫H!xh[M+=s;.Nso;2wl~=Ǫy~Lzdt6 0C}Ze''nBg,χtrwiyq|"*|nڔ҈01DB18~Jd+Qhr|`]~i1:)5 E4ͬTb0:*.7Pc3\n5 nrf{okTV'v4V!h$=`P6*P'k?Y6%+( Ė_VXezkƏ h`}6d/fftZj"Lm!&oԻ[~s?h#g^JlWf3K`yA*?E3 ) 66mE_AV, XƩgoGoy^:̐0: ʂ'lb!QHYKe^c`20b ,8*ۮoEyIw ּ3`شl t| ԧluA6l7-+wL~¤NF3^ö&㭅F4Sk0< R -͹PLłAVj̗}4k>pp 4ػk!/g2[O C#"qLM׾If[@S]r:b'S*h! 1h)6ꍈA7zfNZc (8Y9hs$ _F`1Va5 5Cg@}ѢtF6 ZAhyY~K@5z ـIE-9;X$4h,-2'[ AS~ѥcxط[[9l1Q Ie9qpu%Dc4cϴ6.oњ_˲,2Ibʳvᶢa \g{.k|x)Ӛ\Kh/.*-`z Y)oeɀ])8~>g;R)o nQ˵;3[rH$XFq8-ܓbC'{FNO50rne4{SURE}7Ʌ1"}Fܐ '%.$\y]H9 endstream endobj 49 0 obj <>stream + ĘI/MZ"蹛8;7FrߛiɚMDeO=ii-,G%i8SK>~5[ iiJ69LUG#s%һTh1[nn=ng}dN)ɵg)~Dz?&Z`^q*ol"fk͑r +G9Z3RjY)NFt>6^-ojVh $;FXWe=K(hP;#x\ĀJ)l^nj˵ 2jc +unQݙ5?VՍ]ov+< m`y=7hOwO(Uz5`K6;(&+}z,X#f+Kb ;gov=+'PjB^30 +3ڏgj +%B,HR74kI 邋A9 sCr/PQFgKGBhU8zViy-ZM~ K}~!6xjO dowq`魾@z y^tXC;FrJD2hPhut>W8k5Rp"fQb"$ۆ)/.`>`Ճ RQ4e:vZROVVe\l)Qz?H]`5%An'CfZX6< +\w[!=ɊcE]01پm\|~_g( lc{DA(̔ E,C<ᡟXRk>"O6KJ +l --{ET ۑ5^գ*ݳSMn@d4^3CkP;;ީ8V& hQwk8Oym$֮\r?4䪺}p;?͜-l~PG:LeY0% tMQʢUI@T횗(5X .$+/63̦ +-=4"W& +м2'6".,2j8)Pnvkp 4NǣzzL%DH*сJrpݒ%4dΤnb1 ,!d47^'}+Fy]c.I"2WZq3*YN \u֐ꮥleW^ n+|U@n\Ұ䒡&j~&9lr hT:8lrDюVGһQ':YJ[zoc+ MY&Im-)k3p^zr|Yjږ֟KjA pFO/XN67vD($ro)2& $'ldkh)95Ÿh񚎨Dsb,lc+0۷<:Tj8ƮvN#'* +&P3n&Po)R>D;V<vR0]b Vܡ@nUB,QhŔt,Ze&4B#d\KG4qlds 6[z" K+0"'MP?3eA$6fSRl︣hWdQ-ؖ.]9R7GZ*J7J5H3 %Dg$u3 '03&[ܔ}] +(Q")o|jA`Jo1r1ٳ!GJ.;pf +T6(%Ch!'S5UBdV8Qo7XvMhyl轑 \¯L %kǰbj3? M[.=]uNR3*a}"Ѳ`i,-NbKŏ¬’ ]7lg:QxJLV^|Mh}0ePV8L0[fdŖ@oNL/o:HzU @]?KB(} /*3` c:)warRZvloN(N ! ZI.]G: +l0ciE:\jƖ8ž]r fj r>8člArEKLJAoSE3MҀSN!潷QuuȖFg )(-hPJjI]KT\kfnTzg jvmXs]nt: #S, Ne#vGjbhՙXIV͞ΖVidfFlVN( GDk͌li-}%AEj1g|nQ+A/XT)G9-]qd +إ} IYII:׷zq,[ ̅4 o;ʭ+aS4H14 gt h{ۢ-g Sa_6[6b%)zBGz沚g̢)~,&NRZnE +Lnfé.ECP.G0ֆlC-8-E$6 ѫy8b]²,Jlu9߸4s2eFɃv1B>^1ƭMj4 nnp?Yz8yh|UZM $姬oEP.Ys&VFn1^zl+bHQ"g?7^~ jK,vUO)R%k mNɫ)"O{|-U< +}V6 j_`NIm^>G =_=H5mXn$-46# =hVqzgD^GgznՑփ)vlum\9Xe& 2DaJ㇧ő3m {zkdqD_WQj9m ۖFwk]-Q]j;3B$Gܝs{1TP/۪wP*0X{ UXh@WE@ӿτ)2{ƼD?m} dWh2 7` ]0ώs??Z9Me"e{)Ecj :HM5*vI]^h>ۛxezc⢷v7 r ; юjCޏWW_ +Gq鳿\]f~~<_w߽ďx=W?mI.__]/{0 o.񷟻/۫J{ߞ_gz? ֮kGW_?l=${Ǵ` ~7_՛##3>/ӻwoj>{}IQV}xZѮɇw_vz-žv_`48o.‹mo^=<3w#ܿ}ˋwgwoo_/y(on/?`>k ^]w_?jN]o8֧}[5޾j`7#Yjl;!\K Cq{ʲ<1BnVOq08L\خr?tW)"KlHxl}~t qM^ye'+~r_=|}s z}\8#tؕ'Z]u?[/ɏ׏zxvyu\鐂m +;:ջnoϷ K)voA._|A>\TOP}<[sپJۏh___wߙts^:ڷRwl=^~vi{b|kވwm!>vQ=a9v|lRv=zD?ؕ@S_^]_?[tz}u{y5yG;yCߝgm>?i|^~_ҜvHo\=\}F_x~zپb<1ͻ+Uym[I1Al;Rޚ#MG=Lonl?R~;.^lfKyb2'pخlf`3ۗY?̳_m_ΦpyAnmWp槨`>pgѾGYKe^1p kl?}}{ yrVyW~D"~O!/{\ boY/ۇWS2~ki^Wbɴ'Œ^eg,R"V-փ?ȷ|;ȷovo..vnOn  ^t>Zp Dp*JxDOD姼a64;N[ezp#yy}$ŭ3pv'n+$_5in\~yu蕨S,7~B_Tvl;㚽T͝W\m_LP%˻ljlWw.~UGGyɅlvEzwJ>'\/OO4a`WdFv=qiQϝnrwj#s/$l'vc=t %lHn:ydq{" }'7kz(_Q?ZC>ğ~Z!C>ğg|;_χcc;ğgۏ3MD}'zvAv9b·dg>{Rwuy}}ݶ㻾 zv7/߽TW9.(?nWwݯ|_ݟ>g?8[:[L#7CN=ܘuI/ cg~-fJeny7l3c (AOoM5>`/>b/'~)޲+98sΜ398s6gnętΜeΜp漄|mL}>uUfQDؾŽ~ ;rw|ݵ9x~Xpr® +Wv +WO_~z~I}8Aw=TzUVЏëjo?7wO+,\uɲCR;@<"xm?;Wv]}7O&l_Wl, +KOK(PSK!i-rp쁅oR8?vI^?`=?$t0ڄwWۣ-gƾC=)RG^Vg+u(*da'N?x]&=ҏI/]9CWx_><\vp~աО0}Am?Ơm?G'珔180^GaKmoOB>ۀO+`[`xw +Zk9X{mV G;p* gn=x0f <k4Wg>aDbb>e$;o +ﻻ7_ݟo/qv^ہ:uCUݰpT=`On +7C<Ƌɴ^s{Z+fձ9z׿?O_ۻ| 4}SFܿ-xy2~ -FSP泋'( k<;}-΁=+}ksP=}p]}Sp'-oɾi< +<}9z {n=!ٞ[k<ɵ>yţ%(֯x ZJUWمOV/?Q/t݃"V?ΈۃgAyєTDBnl7:b^P/y#v ;=GӁėg#ON^yeHݧw*%:r߶~k/ʮۯ>'B~ ۈu*qR8_?x:.p ?9O}e('XIM[vGiPIi)%jdf8CRs8щKŅ|ߝTr}ޝyyfΧr$ơt7iUJR׃$9MNC (9Ncr0Vh(.xC >ߗpїܺSWrX4FL }8v$Z4vpuz~̡ΕT)ݩ˱2)9ԏf%auT c0?;c:aX:ޮ].ǘ}4%c}SV;,i.e,w.]t#a9\JJ填0@(mC-WP8D|+ C*%r$-WY]v# Kal>+)LjĒSF+ O.V:%h央Jq~3Rv[ckG/rU _ ĴL\w5cx])WAd*>zLVtk®X຃:OAkpr W;0>kKsN߫jIQJߩ֩NXקJwFW | +qLh~@ﺁSZԅq7-bf &rN5n[U_ +,2aNVIX4>-:B:H|{=]9P¾FIu+IؚSN ҔjMQ5&~g*ac*3ݾjwHUU&ͣ#-nUkWz:= +L :_=1%%Oٙ_%$N/7} k:}k=7lB4$ec Y'| +HԡX Ef`Ufj4P +9Oشi +?nVef> wX\be`(T72_-BՕ)!AbBR <$qDKNb}/*>Cupvv-CoɾvM z(GrZ"=vh{lO sbg%),; 29 lرi qن/U嬎_rtKUçKaW_Yѓ&r7 ֽ$'!u Ӊ)Zd/AzIxegʭ8Y/wpfi;6Z|7p T{B_><cby,O|{4y/>R%_86l9?7G=9#p t4>zA7+YPHGsZUeURxӦ*6įJwWT7E{I15DCJXHXu?˩)'Sㄇ"E #?vYh{_8Aje {:|_-|7$HluAz8ѩZ#:]z +W. $_`*rE#,<3_bGXbV/6Nő1Xl^msEmt3u/"bV箣I +S0h0"Y:u`: ++"Z<E"H+% _8]r&jU DW`63|{ R,PWP{BC:1lE5_3V1~?pcb("Ai!VwH3@?X<p£q_]mr,b!ʷPt6<) R24t!=4WĤϼofYZpSLJD$*B@Hs1!`y8O{qs$UhODj /z9 +vؚT.pB+V.!b{pW xF[_b #l tZZ3iGpʆ;>ZeѡB}L0xci +(|<ίۑ hONyITUSPC@@CC HOWSeA$q Z"!l3O9,-?T;%_Nm',vuC{2>xaVu,BEꂦ0ohHqttr)ӆUxe )$J ^du8C1؛A=,]Tg Yg $VK>pܧ ‹ <àpB-\@58"xqj'/pixh&eqL]\g³QPpPu4jӰEOk=&+Ug~Um@YLY;/4@ $Wł0@PaE4Ep]G ½hqT{Bja]g*J$'P-'іŘrs|T#o$uK 8X†NFqA')ϏH';5S߇+w`AܻNŪ|aMmʤ"B+^?T;wf=ItΔEhO⣔@x%&ߡ _ +20im91k\EՆYNц \N|%.Ԋ^JJS y; Zyh` Xɞ)M*${ AƳz~lxP4_.Bu?K'D=MȪheW-o;6b^( E$qq8V ltM!zb/1@HN@~{ºGK)ObSXrȢ 9l#\dhcHcdVfȅ%aWm|fxQE]̞-qS#7kWnGt.2Ⲅ3LZذ?ROsKwBTFtesA"'R`-Ub ̫a8 t6@SSc:=Ѭ߻Z.b/6d CΘNc =D Txh]X$0a˫_ +M>z -U3ѱzRpO/RQ7 ցf8(AtNi@h ?hAֹ+/08X$`3]4m棇/dяVI*{i4S0f Y(H! +}u x@TQR <ͼY,|U 0  wB;њ`9z> @ 4$M2D?zCZYN&JGi9IFw2I=g%pLrs@ +5X9,j60lT d#nG8$S4Иx@`cz A9@(9Zi@<_E-[ 0{j AsS=$N(JCY#MbghYnP(Po<>J'DV`脂`PggS΅B˘Y6'WV0knNݵ. :?EeaWwNq 5Ԧ(OO V1M}؅AMUq}#W̥kۈS1bvM84}i"@g*LIp- 2ɠP]~@;AHO\"?0NDNR =F4x*P̰fo5Df0*K,ޠzZ HMj8LMь~ɘTMGxxOn1* Je@q`ȋ: +osXyY ꉮ_/6! +)&lZ rG̓Mx27|%+5_KThOCs &9GQ,/3깣 +VARvq>5Mf4xF1sL 5ɕ %ԆB-A;GAރ/&1jlp^6zauPD!(o":;Pay>&C >?Mz-zv A.Y7C83`G :r<[LAq!UNj!!JR`iǁ2,0/ \Eݲ +rcBwPP#fD28Sf9Bd ~%J3(Fdq-Vy)?@ha$fq9[!th" 8%h ݀% 4.@4#1jhEY͠^xi[f,|[ ׂ!s]0l=Nh@`@:ͺ,uT  ADY1G@4KC >DN$Ǯ3ý '% a/6`hK xYz=uNk~[ˠ2= gJܤ !m( xr` 5 AN%P aDP! +{ +v+zl$nqXRr4iQ }E_,&vXT">KH-{:jSQ5 IUiTSxy7Und%SI#M~D AcLưA|tNGrg(p3Sqq\qrdǪ8 nAړ%h!kP݅UgƂJ+@.`rtiݜQaUo[dAzuĴBz תCӜHIp`+EhYylHP,CBXLH&*fF`4uڙHUE̜ 3މ*sQ, +q UAO$A%J|m#6վ~}(趴VaЬSZ9q 9 #ᨔ554gR&L"(Ŷ2C@@DQUEOIYɋj7]Y O1WGduèA߲gbK6Kb<1/pȤP !M^?[yXNr=aԐ1 +륝:$\˚$FM_k_Ym6m˴p$P1EUJj|bwoj IW1jWWOͩG`tD8k&ydʞqVm<۞O_ծ&{"@z:*)T\SM 9yў,Ϳݐ|!~'-CnJ](OY D[*KeWSAzb{Z~p,L> +w f.8u<ٳf{>Z~S 9WXbw'E*Ws'8e v{kXmAĕt"iֆlU{ (RPusJ=K怒/4Lij|+\;)#)4SՆo26}Oj_gzRizC^_=|sۯ.P73HԀ sӊFz(3/wzAOLQՓeQ>`iWҢM:?-*9q #%O:ˮ=9n8sfgQL,ۼY`3ӋɫFa~zmjp+6+W86c|*Z㧟u6w)0lƴQ;yNN6Mq^= 5;yc}:On/;Ir&KU@G^B2ucfX"Ba&߾C Yk^~K桖}:$ٿ'I"C#1kzh#uiE֟rǓ'>qɢ-ps46rc-wl~v4775bNq6Jtѝ隮yFWRu$izGs/8}6^<|['Mg{O> 8>%9Bj]??<\?Y//?^ 绫7rӍ?]\}{ˋj\mɶ k KzWM0R$*K4I P;1L)J8;"K"eF +[M:=1c>ӤXW-R+S8&dOq]GDN{bpG^b >>64`:lcsr~.oϞ[2^7|Dn3=ӯ7E|d:`@GȗZ9w(S jF.˺*=͇[yk˖"d 43ku=n)Y;%/n_"2CRr=Cɕj>8lZ-Hjx ŭP pPW,/ $Ylw/DLRF^Kօqh |aN OUVbRNK +R֬EFf=Z2A<{͡lP28!x+W$.W6՟Ͼ>7uK~_.G OV?}zݽ= p<|§~rqOwdӺ5Y;SQ7rT{VVE9GTP$dS\-,#KZ UyJF+@@ǁbfyKA H$=񒼨\Z[o@SoC~'ʀs$u0)Ld>jvpJD 0]ND*#nKRWF9d-Y]n#Ln#6 %,9ϺBߵ?-X;8A Ay;0}Ctu)'uԣ<$ r#o&q񰉐(I% rchIW~Ah;bRr !1Cܢ Hfc* + +X ӌhVnB v^'Cxl4^wȡ$R.y Ĕs +XX%γ TbQGA }Hl)[ 0 +0D9%bI=,08'p1 +VM e'%Rxc$KTX8,FK%6PTc$uM<ʊcJ"ꍝrPK- б0^,N&rc2|{rri/tQ$yVӖdLƱT^DM$-s5<ݑD0W/iX(⬥lKܬ21UqkO9;9qUp,xDR[̟Ex{bqBxw*$Yj %)xˀaf' ulE>#%E.FZ5`B$sO`DN xsbNTZt.K ^!˜6-2yD +ٞEMzy ܱ&^ R,Idb[NsP"f|fD .!jXAHBaINl"u`Q5sJLͫAn`LY":LvR Y)g#7ZE1ڎ|!ɝ`BBgq >} Ǣ2‚es8-,\D,%e 'UJܷKӫZ;JG]U壐cr5ԤܿGy!p!S%IcͲ-Ł{R8Qrda|trI:5k*dD/* C,ZvA4S98Ѓő !2O_Gp#a`m+;(x͔j +Q3%N2@`9 + 3ZFl$(#Q=ePͧZF)=臤 ):pn8[HfAnₚ;z#P~ofC:ۑ=;я`K7G,UXDb:xskXdU ŢgV d@I=3DQ +#cסgvv= k$ka#2:M5OK2)JH ۽AB"LtBJE٤o)Q{:JL,-CU鎽pݡ]"bl;]aQp$^ot)3&{# ٳt0+%&!/L%b O@P)GY;lȌ-IL*8;Yv/"ASp# +-dubc^ 饤 +\-zX +LK/R efpc^ +ӱ\B 䇪dvȃ(q/u`dHV=$HL!Bz TRׅ] + QWJbzu@wxraαD%mnє[Ga˝2T2Nqzi­̌i'?{_T,C8ݧ,슢"M"!INBzKuum]]8bY :,Z|2MJ9|f,:kZ!I!{FK*Md=J' $+py1g$mdp䞷fz.l TP!=`,.|ܘ i袷,{mt4 *|J",sXw}wBQCrsRg֝sqJւIz٠9{Lx=VL'f?W8՗;#?>-.䛷k_~SIq<5JZI`)t&lNU~:@? %"K|onLV^)mx|?{9<y".#f,Q8v#f0!̡NOppw<"6~tgx0'0E/Y#KPhdq<6~#kE7 +pp @lϧ<84;?!)œ( cv+<npw9sp̓ Om`DQ?7DySJHy%u7 G?Ӥ(0TK69{$)̍XH\h +M9rc< g ƗpE$ԤJMnq~YF?()V0Px΃*oI~@iL)Ih4vhD?.k|o_€^}-p`SMA_p62d$ @1oDP`f A j H1.,]qQ?Pz>CM*;mje҂J$W4N[јdwH[_>HtN( ^0e{!(CR%GZP/P-Z ʒ܂ +£=4-"PcʟbyB7 !hACHp'4?\Q.hMNMcRʟ:`TdP0_B8b&KIrI^ BO\]R~I.rƱ 1$yvK5R% A]ĞDʢ BrD,Hh]A`8|%JFmd1R+;lR@$ agZvL;# φDDJUѧ4J|Y'!dbzByƽ&muK(i `"~ߜ2]uY*HJa;;17jT4a"𜶁BSjtrg)AJbA*{xK7] +lp$T!+SLfZҠxI(q5X7;"D9 hYFGN:&}]PDzGtɝ&hlc䫧)ۓp7r8XaqtRN kԖAV~Q>yr"-=$.q AJyʖU+/+]:`L* dA+.s:IC dz];aaxg(#E,&L) 'R*@ &J0Y!F;`B~aevP4D5B] &z%҃,3 [iQNL[qMiQkL[1.lRN%ҡmnF`:];kw< 6f Mel{/![V @* (aaE+-?zQ;)*}IZt - ȂijO'7pv, Ћ2{"̇+ Dv$@O'FAj젷$BV[h]qD( +8)OcwLTW/:Պ[EjqYV鷐p1)`?IT$.E1aP},ävbuŨ Axt!U[XD 4yIPMrR)X,Y V("Ԕ %'XD +Lv''Ɋ">ҫ +B7"-B +,?^6BhNL5JVšNcU #SӺ_=ojzsܪY ($q<(gYЧ^aYe#@9s(g;;xP4ٜ#'G$ `i 䗅,9˰%B8Eg>M0cŖT$#遙vfqBTr(7PQ9j +cX+PGF,j@Y,h$Εq0{<dފ2ʄď$M +1=9Y-QA yL +Ld#DeTiBbrd\TkH@<@QLV`~pH63;(Il’kh *y4ƸADURpʋ%!(4q" +Ǎ. +,4 "`vSϮP#@tVER9hX2 pidUxÝ#؍n.UVXDJa15k _"{_QXE9,vB5J]U+=H}qnu9l6KhQNX?j]T·werN_ ƷZ&.ݭrZ +Hn Y Av5"ȟla9>JkJwVT})ub.{[@RT@Tң iIz4pYu `-!%NϦ rRv#^p)Y @%M^p$ .i{e /{ _.z(WWɂSMq;ɁC8̙{%#hK"ˁ+;. !|/-BEՕ&YSQ#K$E-.@uivOQ7** b@K +im 0R= (JQШ[##;z+i1\ .C!$MG + .5vB"[ vUn]p)~*jS1AHfIi Ω]\ii,van?qjsspi6 { K]* f] nKRkv^qQٿzHr#VI%߂qx=5Z-|e6MI4! +"yt5 Wm5?>#P 2I S'INcA)]u! V$ZUUb/a> J +`<žՅ1OYD~9uI<@I6-$ FEi $N-3<2)TG7()Jv`Of ,| ؕsddpNbi}]$|~ 2 4oHa۹ z˲6^xuJa986#{\_ܬr i7?XjR5/>H)FIv4Z$:*6Zdlԥ kYfqmְ7|HnTQ.!%PJTJWʎQAV:mE迴ـZQq! O{gr@OyD#2^DHǘ$ѱ;(ņ@t=r ?VQq6F=>ۊ5@vCe/m,$q0QU`D>c&O!Yp(-Oi3@ +3V^@(wS(HP?()epiAᭅ:_ D}NvU.E2 +W@ǜ(&F⍔\Z9k(Վ@ѰKP_Y0 Y@Qs[9OHJ_櫧26L@<!, hδyp!cv݈nf5bZrfNʣ+D*}pW+E8e{~0 -̞2 +NSK2GcQ車O\V܁1@I(2YC zSa 11ihQq;4g@P†:|Ү`gGMrc#!5Įպ6 +L?)G4ƒoʹ>HF: mQg$םZ84 Q5-* iD` )* +&:8jGcZ% J9OOI\0sb +ce恞ވ`^ѩhY +*gl?=ر#@4nLEg{Or* |S;ȷ&|dmˋO=IhwzB ]@1]>JНo6J$ڹA[Yl.1!< =X)t 0ť.d)Ι!3IYjA1ҺD8.yWI V pC3N )Q,,EhC]g>ʤ0ܘ({cD;+ i02dEʴ UaiD|֐r;̃L8 g^y18XV2# ӊ+(Sf ^Fc{a)FTF9D"+8)ԧ!9<)Kw\ (HٱlzU +A@Uht9ɺ":qnL+GB ;GJMV!b'ݙe v療C-hgs^ǘ:!"  & :7TWN/ql6O*zz +A'!1rۙEp0߇`nv_* !9I"E (C^I7() `TU$I$ $ ¿~L{쯞 +\z4pEGWdH] \z$pE1+q-\zL#+RH=&pEjJB+?Ͷ)RH=&pE+h\"H#+R \ej +FNJ#+RH=&pEGW"H#+R \Q#+R \z$pEH8WH5&pEFW,zcʸ \j$pEo9pEFW\DHH[j$pEFW \ GYQiG+RH5"U5pE1+RH5""H +詹 LH5"HTcW \HLDSh6pEFW"u5pEH="HcW \z$pE1+ҿͶ+RH=6pX8 a<Ʊ1kXK5b-U!#V/ΪVTctVtJJJ>&+=TȰl`ahJx +:Xέ썵ң$+݂B+1 &ҭ(ҫ܊Ί.n]TbjbがtX騿V:JFQ+ +$٣Gt6qzU+[J+VzbkG[a`ˬl-(#`+Ո^iHz_ye`F^YZjpA#V:8q'b+Z%[BJYX;YݭZbUt'żSΪVzܪVz Q+Bd[Ͷ +-Y9-P obte(;)z ;DT~Y§>EH$ X +r{K]SɌHH_:K]3O!y+ߔ;dĘ]cg|BtݱYॽ g@ݗZl@[j"]EȖ: Z4eHN5ny4/WRWQfc:K]s, ,Y/\)35:A35Gc}(/t'RgPQoPEn=-ƭi`ېe\!g$`N,OLd$;=Z;=ss>Q ܇gngg!.dtK[/rv:\RyriTD4O菁LڗP@P׬-u,{xgA9§(9RT r+JG PPlÈPa&0ʠ*L`t:$ AAd`\2H"3a2`aE~&\dNﳁQ3J}ng$3JeA%*`ck7h,DЬ@ O ,KF S#Eó7&Q` f!SG5(,¨Az"¤KE(@5H6A Ŗ E +i}`9s!`ԛd*v R,$H &KN'Sq0a/yAF)E)1~vt&¬`60 +VX+ +$PZœ0)s8+({AI9'=kcj9~Dși3GXg7:Sz. +7҇ BѬOvDح :P2VBH,#7i| 5j4QiB,*+X{sp>hPckŅƒwTqhOA + +Ov FM\C +./ɜq):=qf0z/| rr=0\YkdRڎ_UfAdw!4zUےGpB +)9<$p@:nPL^HN䄤iqx[&6JSNPjh י6UgD(87GNb%AD>p +&H. l wOxe_=({`a_WRHUrM(].Ti.+( Ȕ08چɗP *>sd +<_Y_.2\V9-|Gldϔ%GB& `L?. g2 ^z K#xP:t2F7gù IukO)"XwgvIaסhnDXׁ]Joxb +A#!1;uc`)mWܖ +re[yHNe0dpsYS٣(8<S\UbE(!$Ny3UDXIc xeB\uhPJ0rLIm2: '|>lLI"DA%E⑇6!1p$I1jR3C%9,/(K6R"`V{C|BW/R]%h7(CY\ dH f{hU}ZZGfрJ2Z $~^Ŧ$ɷ ՊBO8/ Ei*d!!Ial\iXcM`eJ0 @ #%&e(!Fʇr h}XM &zxspDlP| +GA!t3ߑEǺ!le;Eƺ '"+l;*cL+@gRX$F $u3E^yX A!Rœ7]%S*~k;n E4$yHS 0O kBS~ GC=+C[Fi!+岉kQyDPM=2шbd\AbPC!Vtk^E1ôƔ%& Q $EE?0ʜk9X 9Gg~r#o TgMeI)Ʀ:ԁ*~MFBVP9TGe>,#nK,|*Bl epsP: R@M`+Y`y0?xy,>A1h6 APqW 5^xxJg L ( T( L$a +-e*҇+SD`ZMboq :5xn$f2% l&zT^IFr`31ËV JΠs"3Xtxp4Dzp9>B!XլC Dc*"h8586g./ WJ\A%%9čw< XWw@pf%)?Ģ + c2rVGTg9`H,\Pd ᅙ.,-PI/~칲Q~08/(_ 9ȱxz0g =*:a 22fŏqȔ 2eCN13lU05r,YG`OҷĐL&>`N&+) @XI˚.i| NbƇmr;o2E|RI!Ls NжR45 R6{9oΨDȦX/rpM|`-utPN bzy8S/SI*G@@p\!cJq_eF{AK,S$^5$65Q!X/Xу9"3̤SPr1=!(BI/CP&\EۇLB%D +z +/TjA:AGK)T Oc='`~y=5x(b?=7mFBdMP$n0mzhxQ!f)jECo.QbFPB/懅*C10R +Gp` 䰠29P)m:'cN)>)+Q2̎jȔ)zIIϺ΄q`R2:xx.T6aw7 +2_Q9} ^y-,`  @'D[,1fFe {ZBҫ604|cabf7pct }RLЌo0 D=9jTېQNo1R1!d\r@hci$Msș4,901A/(h]UL>Kjc=(#s@-`:&Z0D2H*LaU4[ hX0P.9$R<M<y< +3SJjJz)OXA-) Xpe?fQ]PWRit=1r( R!LYcxf; !FfSiF!y0@=ӧ"/U,e{(VƯ0 7)`$Ü15)12~rJ _eX4bZ(YYJ>WC-ꠀH2j1gɒg``0ABsPRRQ0rCdW&1K1 Ff 3Vсm!ӛP&H<Z RYI2^p§pFA b-Ѧ}n19rR39?O5b!9@S3|@fC>%316h$é5 !dvԾH!GH~z9@0ߍP*fR2e2 oQfQ@n[0SA +6ު+I*Й$ٲ,8d +F?<㞂6N$ځ Asn + c`kҗ贂Жt0qMiX ~`ROubΤ +(0|p3Ʒp)'CK _a7@ LXwecʜaLDɾ0G2DoOБ(92A씂߁ [a4ø"s9AJ,$aeJ68JbF+SnF"GBׄי)cIZrT -'/m[fTMWP*VK.rCDUVlEaD*PeT.*G Τ&mH92 )@EoDFITJ] &5궀#x$\-R=Z䮣g RwЋ?T4LH)>+m]ls0Ǵ\$,x4NH}<` !YJ[X},ڂٜ[}n  +k)kR\?"ᧈ50^ wҡD mr(<*Ypw_BN;d\ Gkb+I3wN0]pA.'2|(D= دĪ)'lr€?#EFaIL:!55'r:0Iic˵-ppMWR~0ĂFBJ,'QE) +~ +=5i&A ^4iMu+YQqɄFB@em"ŔRBT.)9:7sR`T~J&i"ߕ0$.M"67;=D4XI b=t(9p8``?7p#ѓ^kGjf`g1=z$t\)-9KxH+P1KV `:uHBڢV +d&z)9nʶQL ޞw9? g[,^1!1L%f31R 2+,>(;:3|vnOLB8OiJ.AF-spsAsi.{CtVG0 $]i@3"VTfh%f^ ``뛦^''|%ߏER>yZ."M#QvB0~P6ə`=˱[pxq2Oe+6@"ƫ7<CDq#.F)@Ώn%gk'jY:x1)|B>Jpsu}@q=6Ë0͖P2*  m4LѨS`0惾5XIIC:ݕ+Hx!il*x$8l\R"*'sg^茕 +o@ߨ@9M&|R]<\tS@)=1&P1hȠ JIO,9wIisA[ӂnN/Hs^RBO=Ww`F%*砗47Kb891hئ.Aă]KNo ܁ 4TrI.}:7A r*^lz*b52'HԒ5蘞9ΐ;ΔU+])%RP; +$I?!/5hH #Q2N ]NT›?TFj茛 +xn),s4C2)62I@PxOfzɭс? z=x!~4HE@ekX`0DwJpq~4`NvRȹX}E3=sEDb[r4 JF/*fn34< xnb1OoH(*B7/^ +` |'>\H6eP$Ø^ -z8 0 KvX/ #).^ɩpAΚ:pax?鼠S C,XRx$UBJ)F[!'4Iz :Dѥ RT::(|$:ŐFA4Cb +^+dM@6R + +Hx#W D,W8H٤;.m7֞9WvLK6Pqo 1+ ~% =IsKCZq`To2Nx|a=ƚU4[+ *p \quwi`X﷤qke-Ԟw:~-[j.Qx옑UDMLfP2cfcܿVla;'?l뚊bwڤ6 WhjLyPUV \ 7X:Hpu=@Bn= ,:Zo+@~W9w)Lmt*rK9IR3s|.&2!X[W7by7k/A qJzo =|}Askgsze@J 8D~<)ݢ_~4ߛa^dΧw^z9ЎtxMNVnN|2Y@fgʇI%9=YZkuyzzφۄlu>0ȂfѤݟa}Yi[mD۫qjl?tcx=Hӡ ;{`fFdV2=2?Zꂲ8)~Y( x@",,(g;@A/t{* )ڱ$AvvK ̝b}-b&PGG'j,TPRe2 -`z5sm$VC脺Bz@2 ]Z +3)J3 +b. 9\ۑ(s-RXeaWLɄ;iЅXp+qV,T<ѥse(:(U ze[^YL1 +|P j"Vk% +R2C8rl0~ܺ b*^ir *9i̡&K) +$5^сwO!9uM iƸQ# @7>Cg^*}?}s>5(mgLkHFhv;糿&qT\߮-~U^5Iƙm~kB%(q"ѤdJ3o(!8QmzM (| +J(ȴc(甞ӥ 1dDQie1 ǕSV٣[%$}@IzȔ8FA@rhSM[+a AW;UĚ):4*^WKR"mV!g lr4mjcd斢 3ڡӮEV'FQ(*KzaSA4ڡtJMH;f:~P)v[J(FBܟq4o3J.\ЦfӮ=c~hw*XlY3# eP3Ghk+dD*9ף4 +|`7YCXT$}`9%2 P0(S7* +aF -/!.z^i,Vi2?BWXZ&Md}(`1"HEg3ֲ+Z>l 54h$+.xJpk'W +9DU gwL14:@ShB`K~unۧ'N}ܯ0 q9zxP{7GkxT+Y@Dko1?ol%~*I3\P=#<~sofS4,q:vO~,'~txsP[[y]؁6/`i. Z}}r~Jyy:j}uٖ?xa6uFl6O-c\diE\zBGd13uj\d5_rގe#|ʒ1 16C `zw'eV9qְD?A~s0h~!6j=ް.ye%-yXYwT/O~'Htbl/luJ O _Z`'_ȓDn /-\q_sFĚď s} ^ipǏIsX߯wߜ}y 8J^}¯O0jU za9|fS({ymn&Q[:vk'AKBkǝn{:M[n>l W^6x>N~51[ýn_kx.řmjM i[`6 &pn[7Atmi/YW냝mYm9AvW֖x)<";5rq n'xPl|ЬmAY4칶)|4sf\Cϡ/sꕆ9;q{G|mg}X{i9a~S=C_[!U:4ڧFzxkFD}oEݮ?_[mlax9`T9n/Zy`ϡ$<<33Z33x2ѹ J2^| KykUg}jajk0ww!JQgNw|e<zNjBÀ>Nаrw./ EJ[7hi;n ρ.d.j#[}n ; սvc./lX̥Q ,7,`6B%9)$|nD3As'N YD۰ծwyd{8+۳?+2q5 f= WWEhUSyղ1 &/6B:;HӧvQrV]g-[9>$jk[;G4>OEmTlnyq秃aȓ_RNc&?G #9$q{~oz'΅'ۿpd}1n{>7 c7ִ  J* YrmŋvYC-~"ۆ:chޗjhTɛtB3:P賺3G;4 +#&u!1kqai9]}@|>ڎU']yV cwB˄@K'x(z9uۇkQ$G6:U}hG=H|C +Dؾm5v\4:IDl >Oz|

/hq-(ڱߎ.U'l& n0둹~Fn1`_|>Y0f|N; TBma);;VƦc|es=fv^>z7[]ci|)dtSٷj- +\P[puwqc<+Qe*hj׳ݎۯz4}I3FǦSt~SZSkK6]fᦔIa9hfmxԬXذ?ڀd{B ׀ +jncX;;= #u;5s\/84uwEQZ@7jf0iǬ6Bfz]f0j ΃LoF95[i +'O>vM׍~wmd9IRlo71Eޝږ[FEܘ"ږI0IHa5ɬ{QjN/Dw;Q{\5A)X8]?r.C%8f 磖 hFw$9횵FC('vcClfE޸aP=:=[6peA=agnR3B~G 0lXAl1\ZNxhЫat^❣rؑɗ'q"7d]p8:XP(a=W9Qj' +cAO^c>^uʩ;hw o[32<ϊ.2/v(dc߰A^|9,|#+j ª.$Rݫ7__S&/r(gIH3\T4!;.qp~1,scxI_#TT75C\qIC!ær˚K;+^m$+o~y+OOnv.=\tcJ>?5{`-|sս>^65J]Nɯ>_[}7X< SӋ6/m6oJÑ6_O՛K'՗Sӫýgo-̿8{а/̟\_1}>s`j9_GÕەՆx՗ԏ`ᇮՍKsŧ_v.whS姙덵~6r>޺4^oW>__i^[F~j]_;5vW?]_=Xxy^r.5K[6/ReW;u("ñh {]=YG|n^vz^(XV/G/]q}[~2^xw'Xjj;3m<7?s7.px:Nx `}o-Ut]6gfW7k{k~FܺsMᐱyCv{u8W7>u:GKO?,?^_9xX$kdcr; 7Y~{NeSfͧfgä͗V5O7{[I#6݃֠{%g/o<ռyĜY <|zuz.̬SWdK/v7kųWSӷ'k:zk7O+Z;vW7 {suiݻ{V`Uo]_zz35p+wE$2]Y=X!g/2 4͑{ߏ#I|}ݵ;^wd)uibgzKMvW=z0~{M_a-:|ra2{֟ϼ׺_4\_m\KG/=g|iϪflyg;O&[]X:V vZ[o I}^!};l i +MMƐPXYد~zq)[up2}hkoy߅y؝{ߕdɲȮ9ù{4oFQ{zu땅;7ybygOv^?xb^Iӽd^U|sleݥRy󏖏_7ց?7aX޹vbT<lc[ RǶG7v|֣׿Rӥ̾J܁;3 $w0|7|fCt;X{_dRupiiyf;Y;o-|؉ + >w[ n-Z|^m.5?a1/O5R,R<姧kA <)e^\,|uWaWıv/Qb߾:{}[&3N6=Du".L>}>5ޯkՃՃǧKzqZc=[Q3y8}ljK>Xxbiwsa97:3tik{ևkf_ѝC1׌[G A'f/-~h?^.{y -6glObosC.|)?[n$^dwo>}xWѥq;2/u{{{@ݷb͛fV^ug+;f}߭}4lrk{fo>]ݽr)"{MR1Yl;@\^_YzoTōWgH-vrT-E.'g6APSivscשgwRc%;^}v'2eSW/RV^f(O ]i|f:lL7(.=Y}5\zZyduY._bߎtpR1OVʇսkrvtV>\|nѣ g;sk`f/vC_οY_MF==[7ﷁί>epݾqz}1~4{[t0&s䤿cxM̒qt|H>qT{ry}utOy.Q,d~ +-;W,ھs=y]i8qzoB@BB׏?I6nƔkٌh4ͭyu8-Y,-ns6H1l-R|5$I n͢bf*OQY{"Sz5d~ /c)3#SQB;++Oj#^&cؽ rV"Cg9]Q2k +c.fAFZx}wWXi_Xy3! oTcYI'=gظ>Mq彆=HOymbe3賌[^D7.z +ĜuLyEFwod<>%Ny{rԙKVcvL <F +F1k.5~i,XƌfPuVWDž(pzʌ +E).opZ15mlr8pdbyCxE0A,1gF?=m۩oGXuY*M)fHh,4t\^wx5 5{39Y?O+?i=^_i;Z "8V59W&uc8LTf/aI,C@Q +~j̸ Z2Dkڄǒq=6 yڒy1\fx׌oJcodgY̐ k)m$~K8,bX{?cv`Erh;F:>2gwdt}-O.t5ӫYLm3 ͵w{}/o okGKBPEٗef`C#I5~ndO0^ч!I;WrT#@ +i7e[Hg^dL/h2K`7 FwTRZ)`a*slk-gLYC&bE`;SïON3E&LJk?ګ=BC)HF`9;lcq4Bf·7{@~/::tX`3li˅#91c~ GLckM5/TJgfܥpcw`Os9Bϩ/BHxK!c/)d`/w|QBB\䥙yA__ħp&EPm'3 +,M*g;g\~|q Yl}˂'˧olhaX#P)W%e&}8Q*JT m3s`;~2J@be0IaVc{Jʿky|W|gyǸ=`gL&5=(Z_n||O5Q[_d ï`ʚq;l/i߁Q : 쭆 ~E 8=~6WGzٙ $t@˼,`. +k3`=sRJxcw0d + xm`jS5D,C̷̤u؂L2Eq.*b;!bϺ yO{6Bנi*A6G2O\k}HZzOߜD6xϢDڥs߻-YMǚM28vݟO8 g.3OL?aTi.hKKlRKOZ`>}gEW2@߳[#Nk%@&esV=)jM9?*`}%ZT顭@ͥ 0SH_8wSD)="Ys}0,a>aSˌ:bV$h\̌57bn޶o?|䀲1qt'mSSx웂x3Gz%]`bȉـ[1a\?a _Ukq1Jwcԩ<놘1La; }~ƶD +, +c5aAk +Kt#,mLurmW:VU41͂U6nxش^fEJb39bK#VTYlaG;bI&ZcBgԚ֖Z0IHKƠ Zɬ }m4yݝ6xk3â[~n_mm[ mt?vTF +ʓڟ& mm՟MMN[uFwtL:GݛTׯ)οtЗ.K*\JeXWܺoء,& &^7tdWcЭߓ k+/ɞۆم>Rbd0sTܡ/ַjU*ǬӀNa`;o%ddm61bH_uCvQ[ŰP9c1 ;kʈ&ni9iC`c?q`z[Ec\F{QNm{zu4xh;LcrNSō۔gj?5[(]iUʏLe, +)ί@ xhNgBshEsc]7ɧyVؖ k>&Z)1W*E,iRKչY:d2`EOj!Yƞvhν(Z3n&f>N&}gг7bHfd S[j?[&ڃ[;mGOcG쯎MϞ>d~σT)JWeۡ]7!bs#k;_Gӧ~X:%ze8s[P2ҫ9)6sοϥ-P.<)7tUG, ]@=]u8+N5uKQ| % y3تěEeĔHnu" 8IM62IKv,9}䮤3QT}Myݖ1T՗(P>Fnmk n1is_}FwkӺ;V=?xlKhl2i4]{vvk&^?1y3 Wx?w}־ XfeŎ!~cfpm)W\n/&nG$)~J b50Zz`_AO fYl;_mD#B&Nf3Tt5RRh.B ~:k,Z]|_'u1;d8bYogxۂس}$"oEk>2(яlƨÑ\F#oA-U=o'u> XlZnpSO<=~i{o"P;-O Y]b-J%d)4J;YWy; +35h/\Oto},S |L+C ZY?-oYl}TuuHneH>n曽d7,'lzc1(,ZH\a>9} T7ŭE[XI$ˍYM7{{ommOULd=+T%]5ퟪX_?*Ac}ټwG_{ޚknlֳi}XlokF5h4_Ӧk&z`5вVy)߶%Qwk W7hH ~;9^?M G?GpQ~4*m)Wp[ŸX?i8 ziiW7`_9r6QLFmlqOXD'X=USZޫik֪N>)'3wVUg g^ $}~Uڝ+F}S$ԍa-:Vrq-Z3Y~}w/ƿٲ5]uO|"k}di_s7,-Wtj}4nlXAcϮhcAk?+ ppwx=7"nVKeir8w[[ 2Y0JgCB%?kXA9%[3٢ w[tq'Z R =Q1 +d9{x»)i {ʅ1Lq[d +-̾_`[q +1{x]U@ʠq;ZGP,ύIa֛iܾ}+ĊCğ{m;3w+੏L ß5[3P-鰾J^g_*С*qNwk9l6fF\l,fDGZ:]߅~u7%5J':%+߀$S+}aKWZ%n-r3`2z扩m^o鞂MX\t_Ix&QT{KX|չJ—6¨!Yi6G6dK~DcT)iZ8m S\K Խ`*LJ=hUI2]h?X2&^_FOHV:*i zKtt%ӯJRBW)(Ytn7Jo}EV*`WgXIJ'x>nIW㦹Ej bu(Sia183MAx `VQAo m[}Ld*|Yf(Wi +/[T):5 ~oC&JNRB9ȢA[zd-[6J򢯽,*n_+-Qf&t[JU +t25j2 UvI@AeG岯],#SiߏJ~JO*jGyZ{C݆TmUARC@xҜFS锲&4JISĜ8U +jŕ60S1jOzD }hF0P yWPix +sZ/]i(:Dоu+ &RX S~LװR\T~o[D M,.IǧӒm%N+_!c^]E9ڟ3^ii9_6xP_K=\ʶ>m.Li? 9&|lOmNE&j PנIGitG:3|ܯ1߷>Mӹcy9$zjkQi*8ks]K3S/蟱>2CF1;$(`ۀ,SIoL}Y)\u0sXDG +47N7#\ePZ#땭O O-@;i۽VcE;J:IW~V +_Bdv:%SRwyu^3QURJ^h= *t_aRRdT +r:0Zj _Hs*UZ2Vl +R8B!y\= %1[yoxZs_Mn7Lw*W,cEgW;<M$s3XfGs"[l֡NuR4#@NZ d{)&iX3ũ&H7L>Wږ=s-^µ w*)XKq!@UP`zm3׃Q@<-%I5jȋod[(܁@[N5?LͼDLl4ǯ>~:VFƤzצԏ'P,b5%Q#gf7I'Wlw;%F<gPX.U0-T=\t?3mFZHn6 `v;b-ͻUr$5*:GE[5VgF4A!)WU׫yidFBA-M0@vv-; r>A:)aoޔCmw2_[,9LOF/rE jȶ'W=!&D}wÞ>=0uS| +dlI!3AfpKtw*Snp4(/j@Sj3`Fuؒ|}yx~PDzprA 'ٓ_Pj9Rb).A$YGK8 /).]RU!Q%.Yqk\"ɪ e6]kČnK(uo$qS +'|{DB*~DkGcPҭ +p庯O +d5;^UӛOV`JNbSȁ3*iؔw=cPnZmL"nZ"KYv]΋Ǯ/wxE'!AAҁ{@ih:ƌ85NΖ-t!-K*?~ +YǓ$h6e;uNx*Jy[靅aI>@iTn$ok s&NytT$G嬓os% No[D&d]B3TrDibHg|2F崪b% X vXTh4II0&{T59v޽b]h'H  Fy:k Mq<~(fǥ1HYEQAm]o <qXy}2ՐJ, y(5imjka7)YAV -1P4u:L{Y*<lE'U%Ng jJXd*9U5JD\L.fE.E<΂;|cumtLc85q DЉCwctH'?C'[)Bɢo)#hG0t:NA'@ >SF)o)#Z :l+@б;1t:d] fUSFږG]T4IӛmUʈwæ֯s@ /%ظO!@\XQv7kN18,uCk9y.zno JIR9ؗ@stMZ +: +BǏI6sWu:iT݄:$1cLmk`7O[A[kې @ +#& ".OlQΚdnY)R!7ALux}o%uckå+r6%f8ʚ](0$Ɓ]5TNboM_t<4MlJ_ \bRM:`z0%O-ϿQat:$4;CBī ǮDwhwqL%CK ٲ>m;ߥx9 KpE 1&3V9=vweSٓ# QĵQ8j5B#r6i]w2h]&{% +Yő''핂<\SG,睌Io6V.<"(axnc;0;q|Z\4hD[ y##h EPhp2__V$8&p4$<,a + sw:xdx@q Zq <2rkn\LE6 +aP$nωd] __ L޻t|"tA-x Wwse*թS +HNТ%U˳-Cw2 .<1ux']]=ZG[/+^ +* vhTez>1rT^H=ګ x/T0DλH'^P|*BnmMEpFT5n*کh\LQׂSyлgfJ;"q +R&p+hHt' q}ג)+Id'Zk@5ӯݥ@8%;OD$64}~[tRs.T N'(/餰t"tRxHGt0sVtRrF49 V> M'ҩM'k?g`Njth:);4NtMZ-{tRƩl4IDC=S.4m\4z=? MwnF)bV?M'Ed4i( h:) ܽ>MwdIh3tRg!{|6b7]$2I87Jd0߽es&)ϳ[tn%A$$d^5,T zkIjUrƒ9uSe&IRj>)]QpD QJbse-K)ix\4Is'] +2͝KNUr|2vj(zTQy8c('{8}NѶ{hPD8BEOSj50:yVҩh\GqZo"ܑu %Y]-P$KSe,u7yO%Bu%\u4 u5~Lu4 .[9龧 ? +gF_%U]"Ϙ])|ˎkK`m}[!$2F2ZF.YV6Xy5߫R H".#wr1)-KRӳ2U#bsySj7xasy'@y4[5M< n8-Vp &1 [* <g;+r1 %+[}[;%,hLdʻ'R)Q<)iNKR'ÝRW wjo5ǁg^UkfFC离X+F>zA|aY}=WzH)x2n/v<Vb\f˻.b⟊BaAP:}S cRb2(oScv#Ŏ,)hVPWܶ2hV3+ՀLw_ٹ $As'*"PN k)ܿܚtXyWSuۓ0]٫na=^ɔʛl +u+hjԳƕ(;~ 7RK"p)ݼPRQ[ތm^)[EL6E/<ȵ3 ;RNc8Z*U%L2x8<o Npϫ-9^_RmfK>S\6 W)\JдgR"IU1@s `x1kUR~K97R4W>*Ey9R\RbKtDvjĀ0OְK82QI\=>[qm1-]dkopL*مNe$`ǂNY̮NXtC"I mdF%@̂W2$Cd"3 ~KNt+44ItukX5ݜeQIQZ7Eii J$-㴘\ƊU +ӗ9SJyW__Ϻp^V{3L?r-I2.MZwzhBࣗJ'k+Na$HN27;0'ԛctbu=}eb?u'Uq.L'S#8x"iٔL7a7sk2*Z&Bjެ +ԫrR^Ki|eY:PG0Kfص,:&1VhUycW<;)<|cWı/C.,e29* Bt +Z ?Z Qj1k}7 +P * +;Lqm(@@ȱQ?cu+ +P-#߅i^IW'S푤|]x'Ied{NR>3l||j@Lnoո-X^?c"z< R+p^?e3GFn맜[~TS{}B^?~7 +Җyjy(ߥ+O[)wV):|Jw^V?{o)'}y8%AQ^?Eey,aH^ eV ;)waJOm+7Yʆy8$/pе2S:⠈| ^]ÇViJG|Z7*JP*Ut1&qo,X!12|DK}# ,+{GT;qs}nj(d"@i5;VSbsoqbɌ1˕ݻg43gѹ<{x_6z^4o]<ҷwWx/.zII7fIZ8C}~j5$bLaW7B}+>k$4[y]jM!yRy%L[r0 ee5ݎQCu$9/6tZ3Y:}-}B%lz_m$NjȖnurp Avz[th焻f0:ҚqΟ3ϊP@k؎4V$f\4Y9ܖNs.'*pWgA $JL\xLɰp~tpG3z~g+s3c,@elDe6e#NvaPAw~I;]F< +doO9GswjVdO?SUZ#>3Sк uZlEL6nDe0q1ӴFw?τF%B~gSpD'r$0g=@Sh,>h}P-LdgeʖZS+37ݵ%Ύ xttyYyYSsY_ j\ uWoq`W6nlspsg٪̱8hf=#vd$5̂eYvq,`{R CeBτS²@t]PLb5a$Z LL`*CYX OX,rBx0/OgW,v_:񱗋- 1lιΛ첫o w9xzÍ }a +fz0b^ 1_fhyג! 5=sE<7w3Fy0hރ&zN@c`}ggWmm cAd l6e1:$Aѽp=(-]0 ++$!m05'CWΰw7'+3Ւ.2V}ǡ";T;4Y4XrvTnʼnj~-_Ʌ7SIu~V493\r>]I_x8G 14N.|m_#WLCag sk Mp=vð, im9'r%< C{gktBC-7ӟ+irS|} +@<~8Rɫ1653i%۩1q5&huռes;z.Ov)TԚ--jcK}k;:4=HfffH ON` yF$];h3΁OCg$QC'َ^a?b+q'#,!Nd|O3ΔdV5c+cDBC[Όqtᅬ  KPnq`Կufo @);S +U*YY Z\SSNXK:³r-d8Gz\aBGP[mY5ڒ936@eiGSd~:G'}c9coEM\:VZ ) ҫ@T2[ƈ}c8w)hq5{"4CM4{s2>FDhE+O6ZcƭrA@s/#2QU:-=~5?޺;熟|`IT/Y;_77\MRGwBjt) Wԙk#@d:Y2 ̴N\?fP"HeݹwT6.980/L~cuOtynw!/?Ob2agr21,F_7?Ywɟs2 CC#f΀8GLL18$~@ *⦮ t,% nF3(rVA1NDǵnL^8TQ1}%pGO m6;4koOxof; f旰Id`|22=(c@1?&c%# +c$1Q3-̏Șj% Nels>2ȵ$EȘZْt&ĭBOn)JYru4yu+F-ojYnE%*kn6#."GgGb:4<Lm66P +mB%j3ŭIħ#XӖWV"> oRr˶R[~FQ\%ZkƙbASpP[ӝFi-%W= DV8vyh +`{y?BE`bO?IYCvl]Zo(&[g@goRسR[*ǀC6F0n6&#&l٧2[{yC@!rWs1h'@Y̍(1Dc!!sER%vOZrכ.)Jahs;^?*:o0v>R-[>VXUQKB5v hOp&ή6:RGm C+/vId|' Z._{cXNRh@nیdl@en LM-3nu)ߒɤ-iЋ=Yu zAm;M;j")GD1@I}~Pހ!qA TC:^KWCx}8% N +O8N9) +6Ƈ;Al%zJv7ѐ, µ祜'kfJAR/Art)J? +!|$;>/] +>{I,9 wxyN p(*>7>Ḣ6q$`p/jxCadZDYF5 5ދ.q5I?/陉f LII(n->4$&>x'5!# MN@jq l)K^o=ye@Ddđ+&Mƒ,@wӇS$K3  ^ad#\).7m#NV2BBঘ_<>Cd'f7/$d=g܀ + endstream endobj 50 0 obj <>stream +ā. 8AB&H%XJ 7` X˜W@s%x 8h򿒼Fc@A8h//Ts NISXkN pe@hA!ʅ_L|Sb-4"⨘]0&!酑_B+>]/}:ZbTy$Ey|  +Z{8~_ Cډ8m^>7/T#7VR0T'~}3כ8߂'/_` u1d4 endstream endobj 5 0 obj <> endobj 6 0 obj <> endobj 18 0 obj [/View/Design] endobj 19 0 obj <>>> endobj 16 0 obj [/View/Design] endobj 17 0 obj <>>> endobj 31 0 obj [30 0 R 29 0 R] endobj 51 0 obj <> endobj xref 0 52 0000000004 65535 f +0000000016 00000 n +0000000185 00000 n +0000047379 00000 n +0000000000 00000 f +0000266555 00000 n +0000266625 00000 n +0000000000 00000 f +0000047430 00000 n +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000266816 00000 n +0000266847 00000 n +0000266700 00000 n +0000266731 00000 n +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000050006 00000 n +0000050077 00000 n +0000266932 00000 n +0000047801 00000 n +0000053181 00000 n +0000050498 00000 n +0000050385 00000 n +0000048830 00000 n +0000049445 00000 n +0000049493 00000 n +0000050269 00000 n +0000050300 00000 n +0000050153 00000 n +0000050184 00000 n +0000050533 00000 n +0000053249 00000 n +0000053489 00000 n +0000054522 00000 n +0000069362 00000 n +0000134950 00000 n +0000200538 00000 n +0000266126 00000 n +0000266964 00000 n +trailer <<64A8AB8E858948269A0BCA92EF85B468>]>> startxref 267136 %%EOF \ No newline at end of file diff --git a/packages/web3-rpc-providers/assets/logo/web3js.jpg b/packages/web3-rpc-providers/assets/logo/web3js.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3b4cf23de26173be4d1375647c4864ebd77a4767 GIT binary patch literal 80258 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 + + + + + + + + + + + + + + + diff --git a/packages/web3-rpc-providers/package.json b/packages/web3-rpc-providers/package.json new file mode 100644 index 00000000000..a3046999279 --- /dev/null +++ b/packages/web3-rpc-providers/package.json @@ -0,0 +1,64 @@ +{ + "name": "web3-rpc-providers", + "version": "0.1.0", + "description": "Web3 Providers package", + "main": "./lib/commonjs/index.js", + "module": "./lib/esm/index.js", + "exports": { + ".": { + "types": "./lib/types/index.d.ts", + "import": "./lib/esm/index.js", + "require": "./lib/commonjs/index.js" + } + }, + "repository": "https://github.com/ChainSafe/web3.js", + "author": "ChainSafe Systems", + "license": "LGPL-3.0", + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + }, + "files": [ + "lib/**/*", + "src/**/*", + "dist/**/*" + ], + "scripts": { + "clean": "rimraf dist && rimraf lib", + "prebuild": "yarn clean", + "build": "concurrently --kill-others-on-fail \"yarn:build:*(!check)\"", + "build:cjs": "tsc --build tsconfig.cjs.json && echo '{\"type\": \"commonjs\"}' > ./lib/commonjs/package.json", + "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 --cache --cache-strategy content --ext .ts .", + "lint:fix": "eslint --fix --ext .js,.ts .", + "format": "prettier --write '**/*'", + "test": "jest --config=./test/unit/jest.config.js", + "test:coverage:unit": "jest --config=./test/unit/jest.config.js --coverage=true --coverage-reporters=text", + "test:ci": "jest --coverage=true --coverage-reporters=json --verbose", + "test:watch": "npm test -- --watch", + "test:unit": "jest --config=./test/unit/jest.config.js", + "test:integration": "jest --config=./test/integration/jest.config.js --passWithNoTests" + }, + "devDependencies": { + "@types/jest": "^28.1.6", + "@typescript-eslint/eslint-plugin": "^5.30.7", + "@typescript-eslint/parser": "^5.30.7", + "eslint": "^8.20.0", + "eslint-config-base-web3": "0.1.0", + "eslint-config-prettier": "^8.5.0", + "eslint-plugin-import": "^2.26.0", + "jest": "^29.7.0", + "jest-extended": "^3.0.1", + "prettier": "^2.7.1", + "ts-jest": "^29.1.1", + "typescript": "^4.7.4" + }, + "dependencies": { + "web3-providers-http": "^4.1.0", + "web3-providers-ws": "^4.0.7", + "web3-types": "^1.6.0", + "web3-utils": "^4.2.3" + } +} diff --git a/packages/web3-rpc-providers/src/index.ts b/packages/web3-rpc-providers/src/index.ts new file mode 100644 index 00000000000..eea79f433cb --- /dev/null +++ b/packages/web3-rpc-providers/src/index.ts @@ -0,0 +1,25 @@ +/* +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 { QuickNodeProvider } from './web3_provider_quicknode.js'; + +export * from './types.js'; +export * from './web3_provider_quicknode.js'; +export * from './web3_provider.js'; + +// default providers +export const mainnet = new QuickNodeProvider(); \ No newline at end of file diff --git a/packages/web3-rpc-providers/src/types.ts b/packages/web3-rpc-providers/src/types.ts new file mode 100644 index 00000000000..9da4c1dbfe7 --- /dev/null +++ b/packages/web3-rpc-providers/src/types.ts @@ -0,0 +1,44 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ + +export enum Transport { + HTTPS = "https", + WebSocket = "wss" +}; + +export enum Network { + ETH_MAINNET = "eth_mainnet", + ETH_GOERLI = "eth_goerli", + ETH_SEPOLIA = "eth_sepolia", + ETH_HOLESKY = "eth_holesky", + + POLYGON_MAINNET= "polygon_mainnet", + POLYGON_MUMBAI= "polygon_mumbai", + POLYGON_AMONY= "polygon_amony", + + ARBITRUM_MAINNET = "arbitrum_mainnet", + ARBITRUM_SEPOLIA = "arbitrum_sepolia", + + BASE_MAINNET = "base_mainnet", + BASE_SEPOLIA = "base_sepolia", + + OPTIMISM_MAINNET = "optimism_mainnet", + OPTIMISM_SEPOLIA = "optimism_sepolia", + + BNB_MAINNET = "bnb_mainnet", + BNB_TESTNET = "bnb_testnet" +}; \ No newline at end of file diff --git a/packages/web3-rpc-providers/src/web3_provider.ts b/packages/web3-rpc-providers/src/web3_provider.ts new file mode 100644 index 00000000000..2bba9a7b880 --- /dev/null +++ b/packages/web3-rpc-providers/src/web3_provider.ts @@ -0,0 +1,135 @@ +/* +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 HttpProvider from "web3-providers-http"; +import WebSocketProvider from "web3-providers-ws"; +import { + EthExecutionAPI, JsonRpcResult, ProviderConnectInfo, ProviderMessage, + ProviderRpcError, Web3APIMethod, Web3APIPayload, Web3APIReturnType, Web3APISpec, Web3BaseProvider, + Web3Eip1193ProviderEventCallback, + Web3ProviderEventCallback, + Web3ProviderMessageEventCallback, + Web3ProviderStatus +} from "web3-types"; +import { Eip1193Provider } from "web3-utils"; +import { Transport, Network } from "./types.js"; + +/* +This class can be used to create new providers only when there is custom logic required in each Request method like +checking specific HTTP status codes and performing any action, throwing new error types or setting additional HTTP headers in requests, or even modifying requests. + +Another simpler approach can be a function simply returning URL strings instead of using the following class in case if +no additional logic implementation is required in the provider. +*/ + +export abstract class Web3ExternalProvider < +API extends Web3APISpec = EthExecutionAPI, +> extends Eip1193Provider { + + public provider!: Web3BaseProvider; + public readonly transport: Transport; + + public abstract getRPCURL(network: Network,transport: Transport,token: string, host: string): string; + + public constructor( + network: Network, + transport: Transport, + token: string, + host: string) { + + super(); + + this.transport = transport; + if (transport === Transport.HTTPS) { + this.provider = new HttpProvider(this.getRPCURL(network, transport, token, host)); + } + else if (transport === Transport.WebSocket) { + this.provider = new WebSocketProvider(this.getRPCURL(network, transport, token, host)); + } + } + + public async request< + Method extends Web3APIMethod, + ResultType = Web3APIReturnType, + >( + payload: Web3APIPayload, + requestOptions?: RequestInit, + ): Promise { + + if (this.transport === Transport.HTTPS) { + return ( (this.provider as HttpProvider).request(payload, requestOptions)) as unknown as Promise; + } + + return ( (this.provider as WebSocketProvider).request(payload)) as unknown as Promise; + + } + + public getStatus(): Web3ProviderStatus { + return this.provider.getStatus(); + } + public supportsSubscriptions(): boolean { + return this.provider.supportsSubscriptions(); + } + public once(type: "disconnect", listener: Web3Eip1193ProviderEventCallback): void; + public once(type: string, listener: Web3Eip1193ProviderEventCallback | Web3ProviderEventCallback): void; + public once(type: "connect", listener: Web3Eip1193ProviderEventCallback): void; + public once(type: "chainChanged", listener: Web3Eip1193ProviderEventCallback): void; + public once(type: "accountsChanged", listener: Web3Eip1193ProviderEventCallback): void; + public once(_type: string, _listener: unknown): void { + if (this.provider?.once) + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + this.provider.once(_type, _listener as any); + } + public removeAllListeners?(_type: string): void { + if (this.provider?.removeAllListeners) + this.provider.removeAllListeners(_type); + } + public connect(): void { + if (this.provider?.connect) + this.provider.connect(); + } + public disconnect(_code?: number | undefined, _data?: string | undefined): void { + if (this.provider?.disconnect) + this.provider.disconnect(_code, _data); + } + public reset(): void { + if (this.provider?.reset) + this.provider.reset(); + } + + public on(type: "disconnect", listener: Web3Eip1193ProviderEventCallback): void; + public on(type: string, listener: Web3Eip1193ProviderEventCallback | Web3ProviderMessageEventCallback): void; + public on(type: string, listener: Web3Eip1193ProviderEventCallback | Web3ProviderMessageEventCallback): void; + public on(type: "connect", listener: Web3Eip1193ProviderEventCallback): void; + public on(type: "chainChanged", listener: Web3Eip1193ProviderEventCallback): void; + public on(type: "accountsChanged", listener: Web3Eip1193ProviderEventCallback): void; + public on(_type: unknown, _listener: unknown): void { + if (this.provider) + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + this.provider.on(_type as any, _listener as any); + } + public removeListener(type: "disconnect", listener: Web3Eip1193ProviderEventCallback): void; + public removeListener(type: string, listener: Web3Eip1193ProviderEventCallback | Web3ProviderEventCallback): void; + public removeListener(type: "connect", listener: Web3Eip1193ProviderEventCallback): void; + public removeListener(type: "chainChanged", listener: Web3Eip1193ProviderEventCallback): void; + public removeListener(type: "accountsChanged", listener: Web3Eip1193ProviderEventCallback): void; + public removeListener(_type: unknown, _listener: unknown): void { + if (this.provider) + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + this.provider.removeListener(_type as any, _listener as any); + } +} \ No newline at end of file diff --git a/packages/web3-rpc-providers/src/web3_provider_quicknode.ts b/packages/web3-rpc-providers/src/web3_provider_quicknode.ts new file mode 100644 index 00000000000..a1b66880110 --- /dev/null +++ b/packages/web3-rpc-providers/src/web3_provider_quicknode.ts @@ -0,0 +1,91 @@ +/* +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 { Transport, Network } from "./types.js"; +import { Web3ExternalProvider } from "./web3_provider.js"; + +const isValid = (str: string) => str !== undefined && str.trim().length > 0; + +export class QuickNodeProvider extends Web3ExternalProvider { + + public constructor( + network: Network = Network.ETH_MAINNET, + transport: Transport = Transport.HTTPS, + token = "", + host = "") { + + super(network, transport, token, host); + + } + + // eslint-disable-next-line class-methods-use-this + public getRPCURL(network: Network, + transport: Transport, + _token: string, + _host: string) { + + let host = ""; + let token = ""; + + switch (network) { + case Network.ETH_MAINNET: + host = isValid(_host) ? _host : "powerful-holy-bush.quiknode.pro"; + token = isValid(_token) ? _token : "3240624a343867035925ff7561eb60dfdba2a668"; + break; + case Network.ETH_SEPOLIA: + host = isValid(_host) ? _host : "dimensional-fabled-glitter.ethereum-sepolia.quiknode.pro"; + token = isValid(_token) ? _token : "382a3b5a4b938f2d6e8686c19af4b22921fde2cd"; + break + case Network.ETH_HOLESKY: + host = isValid(_host) ? _host : "yolo-morning-card.ethereum-holesky.quiknode.pro"; + token = isValid(_token) ? _token : "481ebe70638c4dcf176af617a16d02ab866b9af9"; + break; + + case Network.ARBITRUM_MAINNET: + host = isValid(_host) ? _host : "autumn-divine-dinghy.arbitrum-mainnet.quiknode.pro"; + token = isValid(_token) ? _token : "a5d7bfbf60b5ae9ce3628e53d69ef50d529e9a8c"; + break; + case Network.ARBITRUM_SEPOLIA: + host = isValid(_host) ? _host : "few-patient-pond.arbitrum-sepolia.quiknode.pro"; + token = isValid(_token) ? _token : "3be985450970628c860b959c65cd2642dcafe53c"; + break; + + case Network.BNB_MAINNET: + host = isValid(_host) ? _host : "purple-empty-reel.bsc.quiknode.pro"; + token = isValid(_token) ? _token : "ebf6c532961e21f092ff2facce1ec4c89c540158"; + break; + case Network.BNB_TESTNET: + host = isValid(_host) ? _host : "floral-rough-scion.bsc-testnet.quiknode.pro"; + token = isValid(_token) ? _token : "5b297e5acff5f81f4c37ebf6f235f7299b6f9d28"; + break; + + case Network.POLYGON_MAINNET: + host = isValid(_host) ? _host : "small-chaotic-moon.matic.quiknode.pro"; + token = isValid(_token) ? _token : "847569f8a017e84d985e10d0f44365d965a951f1"; + break; + case Network.POLYGON_AMONY: + host = isValid(_host) ? _host : "prettiest-side-shape.matic-amoy.quiknode.pro"; + token = isValid(_token) ? _token : "79a9476eea661d4f82de614db1d8a895b14b881c"; + break; + default: + throw new Error("Network info not avalible."); + } + + return `${transport}://${host}/${token}`; + } +} + diff --git a/packages/web3-rpc-providers/test/.eslintrc.js b/packages/web3-rpc-providers/test/.eslintrc.js new file mode 100644 index 00000000000..a98dfb6d823 --- /dev/null +++ b/packages/web3-rpc-providers/test/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + extends: '../../../.eslintrc.test.js', + parserOptions: { + project: './tsconfig.json', + tsconfigRootDir: __dirname, + }, +}; diff --git a/packages/web3-rpc-providers/test/config/jest.config.js b/packages/web3-rpc-providers/test/config/jest.config.js new file mode 120000 index 00000000000..b875b48129d --- /dev/null +++ b/packages/web3-rpc-providers/test/config/jest.config.js @@ -0,0 +1 @@ +../../../../templates/jest.config.js.tmpl \ No newline at end of file diff --git a/packages/web3-rpc-providers/test/config/setup.js b/packages/web3-rpc-providers/test/config/setup.js new file mode 100644 index 00000000000..0b6b9109ce0 --- /dev/null +++ b/packages/web3-rpc-providers/test/config/setup.js @@ -0,0 +1,24 @@ +/* +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 . +*/ + +// Have to use `require` because of Jest issue https://jestjs.io/docs/ecmascript-modules +// eslint-disable-next-line @typescript-eslint/no-require-imports +require('jest-extended'); + +// @todo extend jest to have "toHaveBeenCalledOnceWith" matcher. + +process.env.NODE_ENV = 'test'; diff --git a/packages/web3-rpc-providers/test/integration/jest.config.js b/packages/web3-rpc-providers/test/integration/jest.config.js new file mode 100644 index 00000000000..1d95890206a --- /dev/null +++ b/packages/web3-rpc-providers/test/integration/jest.config.js @@ -0,0 +1,33 @@ +'use strict'; + +const base = require('../config/jest.config'); + +module.exports = { + ...base, + setupFilesAfterEnv: ['/test/integration/setup.js'], + testMatch: ['/test/integration/**/*.(spec|test).(js|ts)'], + /** + * restoreMocks [boolean] + * + * Default: false + * + * Automatically restore mock state between every test. + * Equivalent to calling jest.restoreAllMocks() between each test. + * This will lead to any mocks having their fake implementations removed + * and restores their initial implementation. + */ + restoreMocks: true, + + /** + * resetModules [boolean] + * + * Default: false + * + * By default, each test file gets its own independent module registry. + * Enabling resetModules goes a step further and resets the module registry before running each individual test. + * This is useful to isolate modules for every test so that local module state doesn't conflict between tests. + * This can be done programmatically using jest.resetModules(). + */ + resetModules: true, + coverageDirectory: '.coverage/integration', +}; diff --git a/packages/web3-rpc-providers/test/integration/setup.js b/packages/web3-rpc-providers/test/integration/setup.js new file mode 100644 index 00000000000..5be1bccf7cc --- /dev/null +++ b/packages/web3-rpc-providers/test/integration/setup.js @@ -0,0 +1,24 @@ +/* +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 . +*/ + +// Have to use `require` because of Jest issue https://jestjs.io/docs/ecmascript-modules +// eslint-disable-next-line @typescript-eslint/no-require-imports +require('../config/setup'); + +const jestTimeout = 15000; + +jest.setTimeout(jestTimeout); diff --git a/packages/web3-rpc-providers/test/tsconfig.json b/packages/web3-rpc-providers/test/tsconfig.json new file mode 120000 index 00000000000..c73c54e77b4 --- /dev/null +++ b/packages/web3-rpc-providers/test/tsconfig.json @@ -0,0 +1 @@ +../../../templates/test/tsconfig.json.tmpl \ No newline at end of file diff --git a/packages/web3-rpc-providers/test/unit/constructor.test.ts b/packages/web3-rpc-providers/test/unit/constructor.test.ts new file mode 100644 index 00000000000..eb64b29163a --- /dev/null +++ b/packages/web3-rpc-providers/test/unit/constructor.test.ts @@ -0,0 +1,62 @@ +/* +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 . +*/ +/* eslint-disable max-classes-per-file */ + +import HttpProvider from 'web3-providers-http'; +import WebSocketProvider from 'web3-providers-ws'; +import { Web3ExternalProvider } from '../../src/web3_provider'; +import { Network, Transport } from '../../src/types'; + +class MockWeb3ExternalProviderA extends Web3ExternalProvider { + public constructor(network: Network, transport: Transport, token: string){ + super(network, transport, token, ""); + } + // eslint-disable-next-line class-methods-use-this + public getRPCURL(_network: Network, _transport: Transport, _token: string, _host=""): string { + let transport = ""; + if (_transport === Transport.HTTPS) + transport = "http://"; + else if (_transport === Transport.WebSocket) + transport = "wss://"; + + return `${transport}example.com/`; + } +} + +describe('Web3ExternalProvider', () => { + it('should initialize the provider correctly', () => { + const network: Network = Network.ETH_MAINNET; + const transport: Transport = Transport.HTTPS; + const token = 'your-token'; + + const provider = new MockWeb3ExternalProviderA(network, transport, token); + + expect(provider.provider).toBeInstanceOf(HttpProvider); + }); + + it('should initialize the provider with WebSocketProvider for WebSocket transport', () => { + const network: Network = Network.ETH_MAINNET; + const transport: Transport = Transport.WebSocket; + const token = 'your-token'; + + const provider = new MockWeb3ExternalProviderA(network, transport, token); + + expect(provider.provider).toBeInstanceOf(WebSocketProvider); + }); + +}); +/* eslint-enable max-classes-per-file */ \ No newline at end of file diff --git a/packages/web3-rpc-providers/test/unit/jest.config.js b/packages/web3-rpc-providers/test/unit/jest.config.js new file mode 100644 index 00000000000..ceac341e332 --- /dev/null +++ b/packages/web3-rpc-providers/test/unit/jest.config.js @@ -0,0 +1,9 @@ +const base = require('../config/jest.config'); + +module.exports = { + ...base, + testMatch: ['/test/unit/**/*.(spec|test).(js|ts)'], + + coverageDirectory: '.coverage/unit', + collectCoverageFrom: ['src/**'], +}; diff --git a/packages/web3-rpc-providers/test/unit/request.test.ts b/packages/web3-rpc-providers/test/unit/request.test.ts new file mode 100644 index 00000000000..ccbaa0f7cc7 --- /dev/null +++ b/packages/web3-rpc-providers/test/unit/request.test.ts @@ -0,0 +1,81 @@ +/* +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 { Web3APIPayload, EthExecutionAPI, Web3APIMethod } from "web3-types"; +import { Network, Transport } from "../../src/types"; +import { Web3ExternalProvider } from "../../src/web3_provider"; + +jest.mock('web3-providers-ws', () => { + return { + __esModule: true, + default: jest.fn().mockImplementation(() => ({ + request: jest.fn().mockResolvedValue({ result: 'mock-result' }), + })), + }; +}); + +class MockWeb3ExternalProvider extends Web3ExternalProvider { + public constructor(network: Network, transport: Transport, token: string){ + super(network, transport, token, ""); + } + // eslint-disable-next-line class-methods-use-this + public getRPCURL(_network: Network, _transport: Transport, _token: string): string { + return 'https://example.com/'; + } + } + +describe('Web3ExternalProvider', () => { + it('should make a request using the HTTPS provider', async () => { + const network: Network = Network.ETH_MAINNET; + const transport: Transport = Transport.HTTPS; + const token = 'your-token'; + + const mockHttpProvider = { + request: jest.fn(), + }; + + const mockResponse = { result: 'mock-result' }; + mockHttpProvider.request.mockResolvedValue(mockResponse); + + const provider = new MockWeb3ExternalProvider(network, transport, token); + (provider as any).provider = mockHttpProvider; + + const payload: Web3APIPayload> = { + method: 'eth_getBalance', + params: ['0x0123456789012345678901234567890123456789', 'latest'], + }; + + const result = await provider.request(payload); + expect(result).toEqual(mockResponse); + }); + + it('should make a request using the WebSocket provider', async () => { + const network: Network = Network.ETH_MAINNET; + const transport: Transport = Transport.WebSocket; + const token = 'your-token'; + + const provider = new MockWeb3ExternalProvider(network, transport, token); + (provider as any).getRPCURL = jest.fn().mockReturnValue('ws://mock-rpc-url.com'); + + const payload: Web3APIPayload> = { + method: 'eth_getBalance', + params: ['0x0123456789012345678901234567890123456789', 'latest'], + }; + + const result = await provider.request(payload); + expect(result).toEqual({ result: 'mock-result' }); + }); +}); \ No newline at end of file diff --git a/packages/web3-rpc-providers/tsconfig.cjs.json b/packages/web3-rpc-providers/tsconfig.cjs.json new file mode 120000 index 00000000000..f8b17044cd5 --- /dev/null +++ b/packages/web3-rpc-providers/tsconfig.cjs.json @@ -0,0 +1 @@ +../../config/tsconfig.cjs.json \ No newline at end of file diff --git a/packages/web3-rpc-providers/tsconfig.esm.json b/packages/web3-rpc-providers/tsconfig.esm.json new file mode 120000 index 00000000000..f5fab722b38 --- /dev/null +++ b/packages/web3-rpc-providers/tsconfig.esm.json @@ -0,0 +1 @@ +../../config/tsconfig.esm.json \ No newline at end of file diff --git a/packages/web3-rpc-providers/tsconfig.types.json b/packages/web3-rpc-providers/tsconfig.types.json new file mode 120000 index 00000000000..c67a7816f18 --- /dev/null +++ b/packages/web3-rpc-providers/tsconfig.types.json @@ -0,0 +1 @@ +../../config/tsconfig.types.json \ No newline at end of file diff --git a/packages/web3-rpc-providers/tsdoc.json b/packages/web3-rpc-providers/tsdoc.json new file mode 100644 index 00000000000..776fc76a3d3 --- /dev/null +++ b/packages/web3-rpc-providers/tsdoc.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", + "extends": ["../../tsdoc.json"] +} diff --git a/packages/web3/package.json b/packages/web3/package.json index 668d77e26ff..7627ff6826b 100644 --- a/packages/web3/package.json +++ b/packages/web3/package.json @@ -101,6 +101,7 @@ "web3-rpc-methods": "^1.3.0", "web3-types": "^1.6.0", "web3-utils": "^4.3.0", - "web3-validator": "^2.0.6" + "web3-validator": "^2.0.6", + "web3-rpc-providers": "^0.1.0" } } diff --git a/packages/web3/src/web3.ts b/packages/web3/src/web3.ts index 0fda2c10521..a3b6b462842 100644 --- a/packages/web3/src/web3.ts +++ b/packages/web3/src/web3.ts @@ -30,6 +30,7 @@ import { Personal } from 'web3-eth-personal'; import { Net } from 'web3-net'; import * as utils from 'web3-utils'; import { isNullish, isDataFormat, isContractInitOptions } from 'web3-utils'; +import { mainnet } from 'web3-rpc-providers'; import { Address, ContractAbi, @@ -67,10 +68,10 @@ export class Web3< public eth: Web3EthInterface; public constructor( - providerOrContext?: + providerOrContext: | string | SupportedProviders - | Web3ContextInitOptions, + | Web3ContextInitOptions = mainnet, ) { if ( isNullish(providerOrContext) || diff --git a/packages/web3/test/integration/web3.test.ts b/packages/web3/test/integration/web3.test.ts index 18a49dd0fcc..37587954bb0 100644 --- a/packages/web3/test/integration/web3.test.ts +++ b/packages/web3/test/integration/web3.test.ts @@ -124,13 +124,13 @@ describe('Web3 instance', () => { expect(typeof web3Instance.eth.currentProvider?.disconnect).toBe('function'); }); - it('should be able use "utils" without provider', () => { + it('should be able use "utils"', () => { web3 = new Web3(); expect(web3.utils.hexToNumber('0x5')).toBe(5); }); - it('should be able use "abi" without provider', () => { + it('should be able use "abi"', () => { web3 = new Web3(); const validData = validEncodeParametersData[0]; @@ -141,12 +141,6 @@ describe('Web3 instance', () => { expect(encodedParameters).toEqual(validData.output); }); - it('should throw error when we make a request when provider not available', async () => { - web3 = new Web3(); - - await expect(web3.eth.getChainId()).rejects.toThrow('Provider not available'); - }); - describeIf(isHttp)('Create Web3 class instance with http string providers', () => { it('should create instance with string provider', () => { web3 = new Web3(provider); diff --git a/packages/web3/test/integration/web3RPCProviders.test.ts b/packages/web3/test/integration/web3RPCProviders.test.ts new file mode 100644 index 00000000000..24bc312610d --- /dev/null +++ b/packages/web3/test/integration/web3RPCProviders.test.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 { mainnet , Network, QuickNodeProvider, Transport } from "web3-rpc-providers"; +import { Web3 } from '../../src/index'; + +describe('Web3 RPC Provider Integration tests', () => { + const transports = Object.values(Transport); + const networks = [Network.ETH_MAINNET, Network.ETH_HOLESKY, Network.ETH_SEPOLIA, + Network.ARBITRUM_MAINNET, Network.ARBITRUM_SEPOLIA, + Network.BNB_MAINNET, Network.BNB_TESTNET, + Network.POLYGON_MAINNET, Network.POLYGON_AMONY]; + + transports.forEach((transport) => { + networks.forEach((network) => { + it(`QuickNodeProvider should work with ${transport} transport and ${network} network`, async () => { + + const provider = new QuickNodeProvider(network, transport); + const web3 = new Web3(provider); + const result = await web3.eth.getBlockNumber() + + expect(typeof result).toBe('bigint'); + expect(result > 0).toBe(true); + + if (transport === Transport.WebSocket) { + web3.provider?.disconnect(); + } + + }); + }); + }); + it(`should work with mainnet provider`, async () => { + const web3 = new Web3(mainnet); + const result = await web3.eth.getBlockNumber() + expect(typeof result).toBe('bigint'); + expect(result > 0).toBe(true); + + }); + + it(`should work with default provider`, async () => { + const web3 = new Web3(); + const result = await web3.eth.getBlockNumber() + expect(typeof result).toBe('bigint'); + expect(result > 0).toBe(true); + + }); +}); \ No newline at end of file diff --git a/packages/web3/test/unit/web3.test.ts b/packages/web3/test/unit/web3.test.ts index 3d520f38e36..3cd00a9e718 100644 --- a/packages/web3/test/unit/web3.test.ts +++ b/packages/web3/test/unit/web3.test.ts @@ -21,9 +21,9 @@ import { Web3 } from '../../src/web3'; describe('Web3 object', () => { it('should be able to set and read web3 providers', () => { - const web3NoProvider = new Web3(); + const web3NoProvider = new Web3(""); expect(web3NoProvider).toBeTruthy(); - expect(web3NoProvider.provider).toBeUndefined(); + expect(web3NoProvider.provider).toBe(""); const web3 = new Web3('http://somenode'); expect(web3).toBeTruthy(); diff --git a/templates/.eslintignore.tmpl b/templates/.eslintignore.tmpl index ffb881be6b5..c2d4ae29304 100644 --- a/templates/.eslintignore.tmpl +++ b/templates/.eslintignore.tmpl @@ -1,9 +1,10 @@ dist lib +hardhat.config.js jest.config.js -.eslintrc.js cypress cypress.config.js +.eslintrc.js src/common/chains/** src/common/eips/** -src/common/hardforks/** \ No newline at end of file +src/common/hardforks/** From 683be62b176e87230c125c7aa52dd25edee80ae7 Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Tue, 28 May 2024 05:49:44 -0700 Subject: [PATCH 083/186] fix(docs): quickstart (#7062) --- .../docs/guides/getting_started/quickstart.md | 72 +++++++++++-------- 1 file changed, 44 insertions(+), 28 deletions(-) diff --git a/docs/docs/guides/getting_started/quickstart.md b/docs/docs/guides/getting_started/quickstart.md index d023e01bb9f..c1db2a9fdc8 100644 --- a/docs/docs/guides/getting_started/quickstart.md +++ b/docs/docs/guides/getting_started/quickstart.md @@ -5,6 +5,7 @@ sidebar_label: Quickstart # Quickstart +Use the live code editor to try Web3.js in your browser now! Keep reading to learn how to use Web3.js in a local development environment. ## Live code editor @@ -12,29 +13,29 @@ sidebar_label: Quickstart ## Installation -If NPM is being used as package manager, use the following for installing the web3.js library. +If NPM is being used as package manager, install Web3.js with the following command: ``` npm i web3 ``` -For installing using yarn package manager: +For projects using Yarn as a package manager, use: ``` yarn add web3 ``` -Note: Installing web3.js in this way will bring in all web3.js sub-packages, if you only need specific packages, it is recommended to install the specific required packages (e.g, if you want the contract package `npm i web3-eth-contract` instead) +Note: Installing Web3.js in this way will bring in all Web3.js sub-[packages](/#packages). If you only need specific packages, it is recommended to install them individually (e.g, if you want the [Contract](/libdocs/Contract) package, use `npm i web3-eth-contract` instead) ## Importing Web3.js -Web3.js v4 supports both CJS ( CommonJS ) and native ESM module imports. For importing the main Web3 class in CJS you can use: +Web3.js v4 supports both CommonJS (CJS) and native ECMAScript module (ESM) imports. For importing the main Web3 class in CJS, use: ``` js const { Web3 } = require('web3'); ``` -and for ESM style imports, you can use: +For ESM-style imports, use: ``` ts import { Web3 } from 'web3'; @@ -42,11 +43,9 @@ import { Web3 } from 'web3'; ## Initialize `Web3` with a provider -Web3.js is in compliance with [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193) so any EIP-1193 provider can be injected in web3.js . There are HTTP, WebSocket and IPC providers also available as web3.js packages for using. +[Providers](/guides/web3_providers_guide/) are objects that are responsible for enabling connectivity with the Ethereum network. The `Web3` object must be initialized with a valid provider to function as intended. Web3.js supports [HTTP](/guides/web3_providers_guide/#http-provider), [WebSocket](/guides/web3_providers_guide/#websocket-provider), and [IPC](/guides/web3_providers_guide/#ipc-provider) providers, and exposes packages for working with each type of provider. -:::warning -You must initialize the `Web3` object with a provider, otherwise, you won't be able to fully use web3.js functionalities. Here is an example of creating a `web3` instance with an HTTP provider: -::: +Web3.js is in compliance with [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193), the Ethereum Provider JavaScript API, so any EIP-1193 provider can be used to initialize the `Web3` object. ``` ts import { Web3 } from 'web3'; @@ -62,7 +61,7 @@ web3.eth.getBlockNumber().then(console.log); ``` ## Querying the blockchain -After instantiating the `web3` instance with a `new Web3 provider`, we can access the `web3.eth` package to fetch data from the blockchain: +After instantiating the `Web3` instance with a provider, the [`web3-eth`](/libdocs/Web3Eth) package can be used to fetch data from the Ethereum network: ```ts // get the balance of an address @@ -88,11 +87,13 @@ await web3.eth.getGasPrice(); ## Setting up a wallet -If you want to write data/interact with contracts or send transactions on the blockchain, you must have an account with funds to cover the gas fees. +To send transactions to the Ethereum network (e.g. [transferring ETH](/guides/getting_started/quickstart#transfer-eth) or [interacting with smart contracts](/guides/getting_started/quickstart#interact-with-smart-contracts)), it's necessary to use an [account](https://ethereum.org/en/developers/docs/accounts/) with funds to cover [gas fees](https://ethereum.org/en/developers/docs/gas/). -The object `Wallet` is an array of accounts, it will allow you to hold several accounts from which you can send transactions `web3.eth.sendTransaction` or interact with contract objects `web3.eth.contract.methods.contractfunction().send()`, when you perform these actions, the `Wallet` object uses the account/s it holds to send the transactions. +The [`Wallet`](/api/web3-eth-accounts/class/Wallet) object is designed to manage a set of accounts that can be used to send transactions with [`web3.eth.sendTransaction`](/api/web3/class/Web3Eth#sendTransaction) or [`web3.eth.contract.methods.contractfunction().send()`](/api/web3-eth-contract/class/Contract). -### Create random wallet +### Create a random account + +Using the `Wallet` to create a random account is a good way to accelerate the development process, but it's not suitable for mainnet or production uses, since random accounts will not have funds to cover gas fees. Use the [`Wallet.create`](/api/web3-eth-accounts/class/Wallet#create) method to create a random account. ```ts //create random wallet with 1 account @@ -118,7 +119,13 @@ Wallet(1) */ ``` -### Add a private key to create a wallet +### Add an account from a private key + +Use the [`Wallet.add`](/api/web3-eth-accounts/class/Wallet#add) method to use a private key to add an existing account to a wallet. + +:::warning +Private keys are sensitive data and should be treated as such. Make sure that private keys are kept private, which includes making sure they are not committed to code repositories. +::: ```ts //the private key must start with the '0x' prefix @@ -131,9 +138,11 @@ console.log(account[0].privateKey); //↳ 0x50d349f5cf627d44858d6fcb6fbf15d27457d35c58ba2d5cfeaf455f25db5bec ``` -### Send transactions +### Transfer ETH + +This is an example of using a private key to add an account to a wallet, and then using that account to transfer ETH: -```ts title='Sending value' +```ts //add an account to a wallet const account = web3.eth.accounts.wallet.add('0x50d349f5cf627d44858d6fcb6fbf15d27457d35c58ba2d5cfeaf455f25db5bec'); @@ -155,15 +164,18 @@ console.log('Tx hash:', txReceipt.transactionHash) ## Interact with smart contracts +[Smart contracts](https://ethereum.org/en/developers/docs/smart-contracts/) are programs that run on the Ethereum network. Keep reading to learn how to use Web3.js to interact with smart contracts. + ### Instantiate a contract -The first step to interact with a contract is to instantiate the contract, for which we will need the ABI and the address of the contract +The first step to interacting with a smart contract is to instantiate it, which requires the [ABI](https://docs.soliditylang.org/en/develop/abi-spec.html) and address of the smart contract. The following examples demonstrates instantiating the [Uniswap](https://uniswap.org/) token smart contract: ```ts -//Uniswap token address in mainnet +//Uniswap token smart contract address (mainnet) const address = '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984' //you can find the complete ABI in etherscan.io +//https://etherscan.io/address/0x1f9840a85d5af5bf1d1762f925bdaddc4201f984#code const ABI = [ { @@ -178,11 +190,13 @@ const ABI = }, ]; -//instantiate the contract +//instantiate the smart contract const uniswapToken = new web3.eth.Contract(abi, address); ``` -### Read-methods +### Read methods + +Since reading data from a smart contract does not consume any gas, it's not necessary to use an account to do so. Here are some examples of reading data from the Uniswap token smart contract: ```ts //make the call to the contract @@ -196,13 +210,11 @@ const totalSupply = await uniswapToken.methods.totalSupply().call(); console.log('Uniswap Total supply:', totalSupply); // ↳ Uniswap Total Supply: 1000000000000000000000000000n - -//use web3 utils to format the units -console.log(web3.utils.fromWei(totalSupply, 'ether')) -// ↳ 1000000000 ``` -### Writing-methods +### Write methods + +Writing data to a smart contract consumes gas and requires the use of an account with funds. The following example demonstrates such an interaction: ```ts //address to send the token @@ -220,6 +232,8 @@ console.log('Tx hash:',txReceipt.transactionHash); ### Query past events +Smart contracts emit [events](https://ethereum.org/en/developers/docs/smart-contracts/anatomy/#events-and-logs) to communicate important interactions. This example demonstrates how to query the Uniswap token smart contract for all `Transfer` events that occurred after a certain block number: + ```ts //get past `Transfer` events from block 18850576 const eventTransfer = await uniswapToken.getPastEvents('Transfer', { fromBlock: 18850576 }); @@ -229,10 +243,12 @@ console.log(eventTransfer); //you can only query logs from the previous 100_000 blocks ``` -### Listening to live events +### Subscribing to events -:::warning -You MUST initialize the `Web3 provider` with a WebSocket endpoint to subscribe to live events +Web3.js allows user to subscribe to events for real-time notification of important contract interactions. Here is an example of creating a subscription to the Uniswap token's `Transfer` event: + +:::note +You MUST initialize the `Web3` object with a [WebSocket](/guides/web3_providers_guide/#websocket-provider) provider to subscribe to live events. ::: ```ts From 70846654d00797a0eb1f23b33710e85a6cf5aacc Mon Sep 17 00:00:00 2001 From: Oleksii Kosynskyi Date: Wed, 29 May 2024 10:54:49 -0400 Subject: [PATCH 084/186] add .snyk file (#7064) --- .snyk | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 .snyk diff --git a/.snyk b/.snyk new file mode 100644 index 00000000000..cb9591ea045 --- /dev/null +++ b/.snyk @@ -0,0 +1,51 @@ +# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities. +version: v1.25.0 +# ignores vulnerabilities until expiry date; change duration by modifying expiry date +ignore: + SNYK-JS-WEB3-174533: + - '*': + reason: Ignore test issue + expires: 3024-06-26T17:16:53.075Z + created: 2024-05-27T17:16:53.080Z + SNYK-JS-BRACES-6838727: + - '*': + reason: Docusaurus issue + expires: 3024-06-26T17:29:07.153Z + created: 2024-05-27T17:29:07.159Z + SNYK-JS-EXPRESS-6474509: + - '*': + reason: Docusaurus issue + expires: 3024-06-26T17:29:31.142Z + created: 2024-05-27T17:29:31.149Z + SNYK-JS-INFLIGHT-6095116: + - '*': + reason: Docusaurus issue + expires: 3024-06-26T17:29:51.622Z + created: 2024-05-27T17:29:51.628Z + SNYK-JS-MICROMATCH-6838728: + - '*': + reason: Docusaurus issue + expires: 3024-06-26T17:30:47.237Z + created: 2024-05-27T17:30:47.240Z + SNYK-JS-SERIALIZEJAVASCRIPT-6147607: + - '*': + reason: Docusaurus issue + expires: 3024-06-26T17:31:06.652Z + created: 2024-05-27T17:31:06.656Z + SNYK-JS-WEBPACKDEVMIDDLEWARE-6476555: + - '*': + reason: Docusaurus issue + expires: 3024-06-26T20:52:00.793Z + created: 2024-05-27T20:52:00.797Z + SNYK-JS-JSON5-3182856: + - '*': + reason: Eslint problem + expires: 3024-06-26T20:53:53.640Z + created: 2024-05-27T20:53:53.644Z + SNYK-JS-SEMVER-3247795: + - '*': + reason: Eslint problem + expires: 3024-06-26T20:54:20.755Z + created: 2024-05-27T20:54:20.759Z + +patch: {} From f687df68be35de271e911f39cddf70abe58ec1f8 Mon Sep 17 00:00:00 2001 From: Oleksii Kosynskyi Date: Wed, 29 May 2024 16:07:06 -0400 Subject: [PATCH 085/186] Use .snyk file for all projects (#7071) --- docs/.snyk | 36 ++++++++++++++++++++ packages/web3/.snyk | 21 ++++++++++++ .snyk => tools/eslint-config-base-web3/.snyk | 12 +------ 3 files changed, 58 insertions(+), 11 deletions(-) create mode 100644 docs/.snyk create mode 100644 packages/web3/.snyk rename .snyk => tools/eslint-config-base-web3/.snyk (78%) diff --git a/docs/.snyk b/docs/.snyk new file mode 100644 index 00000000000..b29b615196e --- /dev/null +++ b/docs/.snyk @@ -0,0 +1,36 @@ +# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities. +version: v1.25.0 +# ignores vulnerabilities until expiry date; change duration by modifying expiry date +ignore: + SNYK-JS-BRACES-6838727: + - '*': + reason: Docusaurus issue + expires: 3024-06-26T17:29:07.153Z + created: 2024-05-27T17:29:07.159Z + SNYK-JS-EXPRESS-6474509: + - '*': + reason: Docusaurus issue + expires: 3024-06-26T17:29:31.142Z + created: 2024-05-27T17:29:31.149Z + SNYK-JS-INFLIGHT-6095116: + - '*': + reason: Docusaurus issue + expires: 3024-06-26T17:29:51.622Z + created: 2024-05-27T17:29:51.628Z + SNYK-JS-MICROMATCH-6838728: + - '*': + reason: Docusaurus issue + expires: 3024-06-26T17:30:47.237Z + created: 2024-05-27T17:30:47.240Z + SNYK-JS-SERIALIZEJAVASCRIPT-6147607: + - '*': + reason: Docusaurus issue + expires: 3024-06-26T17:31:06.652Z + created: 2024-05-27T17:31:06.656Z + SNYK-JS-WEBPACKDEVMIDDLEWARE-6476555: + - '*': + reason: Docusaurus issue + expires: 3024-06-26T20:52:00.793Z + created: 2024-05-27T20:52:00.797Z + +patch: {} diff --git a/packages/web3/.snyk b/packages/web3/.snyk new file mode 100644 index 00000000000..5b289bc1640 --- /dev/null +++ b/packages/web3/.snyk @@ -0,0 +1,21 @@ +# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities. +version: v1.25.0 +# ignores vulnerabilities until expiry date; change duration by modifying expiry date +ignore: + SNYK-JS-WEB3-174533: + - '*': + reason: Ignore test issue + expires: 3024-06-26T17:16:53.075Z + created: 2024-05-27T17:16:53.080Z + SNYK-JS-JSON5-3182856: + - '*': + reason: Eslint problem + expires: 3024-06-26T20:53:53.640Z + created: 2024-05-27T20:53:53.644Z + SNYK-JS-SEMVER-3247795: + - '*': + reason: Eslint problem + expires: 3024-06-26T20:54:20.755Z + created: 2024-05-27T20:54:20.759Z + +patch: {} diff --git a/.snyk b/tools/eslint-config-base-web3/.snyk similarity index 78% rename from .snyk rename to tools/eslint-config-base-web3/.snyk index cb9591ea045..f0ce4e19c9c 100644 --- a/.snyk +++ b/tools/eslint-config-base-web3/.snyk @@ -2,11 +2,6 @@ version: v1.25.0 # ignores vulnerabilities until expiry date; change duration by modifying expiry date ignore: - SNYK-JS-WEB3-174533: - - '*': - reason: Ignore test issue - expires: 3024-06-26T17:16:53.075Z - created: 2024-05-27T17:16:53.080Z SNYK-JS-BRACES-6838727: - '*': reason: Docusaurus issue @@ -24,14 +19,9 @@ ignore: created: 2024-05-27T17:29:51.628Z SNYK-JS-MICROMATCH-6838728: - '*': - reason: Docusaurus issue + reason: Eslint issue expires: 3024-06-26T17:30:47.237Z created: 2024-05-27T17:30:47.240Z - SNYK-JS-SERIALIZEJAVASCRIPT-6147607: - - '*': - reason: Docusaurus issue - expires: 3024-06-26T17:31:06.652Z - created: 2024-05-27T17:31:06.656Z SNYK-JS-WEBPACKDEVMIDDLEWARE-6476555: - '*': reason: Docusaurus issue From b63af9f10c57b9b0dfc920f664ea3123b9ed1c06 Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Thu, 30 May 2024 06:11:17 -0700 Subject: [PATCH 086/186] fix(docs): sidebar (#7063) * Move MetaMask guide to Accounts section * Reorganize sidebar * Fix broken link --- docs/docs/guides/advanced/_category_.yml | 2 +- docs/docs/guides/events_subscriptions/_category_.yml | 2 +- docs/docs/guides/feedback/index.md | 2 +- docs/docs/guides/hardhat_tutorial/_category_.yml | 2 +- docs/docs/guides/migration_from_other_libs/_category_.yml | 2 +- docs/docs/guides/resources_and_troubleshooting/index.md | 2 +- docs/docs/guides/smart_contracts/_category_.yml | 2 +- docs/docs/guides/wagmi_usage/_category_.yml | 2 +- docs/docs/guides/wallet/_category_.yml | 2 +- docs/docs/guides/{getting_started => wallet}/metamask.md | 2 +- docs/docs/guides/wallet/node_wallet.md | 2 +- docs/docs/guides/wallet/signing.md | 2 +- docs/docs/guides/wallet/transactions.md | 2 +- .../guides/{ => wallet}/web3_modal_guide/_category_.yml | 2 +- docs/docs/guides/{ => wallet}/web3_modal_guide/index.mdx | 8 ++++---- docs/docs/guides/{ => wallet}/web3_modal_guide/vue.md | 0 docs/docs/guides/web3_config/_category_.yml | 2 +- docs/docs/guides/web3_plugin_guide/_category_.yml | 2 +- docs/docs/guides/web3_providers_guide/_category_.yml | 2 +- docs/docs/guides/web3_upgrade_guide/_category_.yml | 2 +- 20 files changed, 22 insertions(+), 22 deletions(-) rename docs/docs/guides/{getting_started => wallet}/metamask.md (99%) rename docs/docs/guides/{ => wallet}/web3_modal_guide/_category_.yml (87%) rename docs/docs/guides/{ => wallet}/web3_modal_guide/index.mdx (97%) rename docs/docs/guides/{ => wallet}/web3_modal_guide/vue.md (100%) diff --git a/docs/docs/guides/advanced/_category_.yml b/docs/docs/guides/advanced/_category_.yml index 3131878f18e..c6ab4f48016 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: 15 \ No newline at end of file +position: 11 diff --git a/docs/docs/guides/events_subscriptions/_category_.yml b/docs/docs/guides/events_subscriptions/_category_.yml index 2f13d5222b4..9207b5b28c2 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: 7 \ No newline at end of file +position: 5 diff --git a/docs/docs/guides/feedback/index.md b/docs/docs/guides/feedback/index.md index 0118436ec91..228003d5a6e 100644 --- a/docs/docs/guides/feedback/index.md +++ b/docs/docs/guides/feedback/index.md @@ -1,5 +1,5 @@ --- -sidebar_position: 18 +sidebar_position: 17 sidebar_label: '🗣️ Feedback' --- diff --git a/docs/docs/guides/hardhat_tutorial/_category_.yml b/docs/docs/guides/hardhat_tutorial/_category_.yml index 191ad0faa29..8493ca97d6e 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: 3 +position: 6 diff --git a/docs/docs/guides/migration_from_other_libs/_category_.yml b/docs/docs/guides/migration_from_other_libs/_category_.yml index 665581166bc..59fb5de8cdc 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: 12 \ No newline at end of file +position: 15 diff --git a/docs/docs/guides/resources_and_troubleshooting/index.md b/docs/docs/guides/resources_and_troubleshooting/index.md index 6426b99d8df..2dd82f1e5b6 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: 17 +sidebar_position: 16 sidebar_label: '📚 Resources & Troubleshooting' --- # Resources & Troubleshooting diff --git a/docs/docs/guides/smart_contracts/_category_.yml b/docs/docs/guides/smart_contracts/_category_.yml index fcbba9574a5..8a1d21c75b4 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: 6 \ No newline at end of file +position: 4 diff --git a/docs/docs/guides/wagmi_usage/_category_.yml b/docs/docs/guides/wagmi_usage/_category_.yml index 90b55da4312..ee90c923e38 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: 13 +position: 14 diff --git a/docs/docs/guides/wallet/_category_.yml b/docs/docs/guides/wallet/_category_.yml index 6b079975e01..dde0bddd9ed 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: 5 \ No newline at end of file +position: 3 diff --git a/docs/docs/guides/getting_started/metamask.md b/docs/docs/guides/wallet/metamask.md similarity index 99% rename from docs/docs/guides/getting_started/metamask.md rename to docs/docs/guides/wallet/metamask.md index e40db544ac6..888f5890b1a 100644 --- a/docs/docs/guides/getting_started/metamask.md +++ b/docs/docs/guides/wallet/metamask.md @@ -1,6 +1,6 @@ --- sidebar_position: 4 -sidebar_label: Connecting to Metamask +sidebar_label: 'Tutorial: Connecting to Metamask' --- # Connecting to Metamask diff --git a/docs/docs/guides/wallet/node_wallet.md b/docs/docs/guides/wallet/node_wallet.md index a4adbbab987..7b70ed655a3 100644 --- a/docs/docs/guides/wallet/node_wallet.md +++ b/docs/docs/guides/wallet/node_wallet.md @@ -1,5 +1,5 @@ --- -sidebar_position: 6 +sidebar_position: 8 sidebar_label: 'Tutorial: Node Wallet' --- diff --git a/docs/docs/guides/wallet/signing.md b/docs/docs/guides/wallet/signing.md index 88184c2a7fa..54b3779cd17 100644 --- a/docs/docs/guides/wallet/signing.md +++ b/docs/docs/guides/wallet/signing.md @@ -1,5 +1,5 @@ --- -sidebar_position: 4 +sidebar_position: 6 sidebar_label: 'Tutorial: Signing operations' --- diff --git a/docs/docs/guides/wallet/transactions.md b/docs/docs/guides/wallet/transactions.md index 5129c5057a4..c86da4c9113 100644 --- a/docs/docs/guides/wallet/transactions.md +++ b/docs/docs/guides/wallet/transactions.md @@ -1,5 +1,5 @@ --- -sidebar_position: 5 +sidebar_position: 7 sidebar_label: 'Tutorial: Sending Transactions' --- diff --git a/docs/docs/guides/web3_modal_guide/_category_.yml b/docs/docs/guides/wallet/web3_modal_guide/_category_.yml similarity index 87% rename from docs/docs/guides/web3_modal_guide/_category_.yml rename to docs/docs/guides/wallet/web3_modal_guide/_category_.yml index 6744910f3b6..19d6fe3a639 100644 --- a/docs/docs/guides/web3_modal_guide/_category_.yml +++ b/docs/docs/guides/wallet/web3_modal_guide/_category_.yml @@ -2,4 +2,4 @@ label: '📱 WalletConnect Tutorial' collapsible: true collapsed: true link: null -position: 14 \ No newline at end of file +position: 5 diff --git a/docs/docs/guides/web3_modal_guide/index.mdx b/docs/docs/guides/wallet/web3_modal_guide/index.mdx similarity index 97% rename from docs/docs/guides/web3_modal_guide/index.mdx rename to docs/docs/guides/wallet/web3_modal_guide/index.mdx index a1bef97eb66..2d8b878196f 100644 --- a/docs/docs/guides/web3_modal_guide/index.mdx +++ b/docs/docs/guides/wallet/web3_modal_guide/index.mdx @@ -104,8 +104,8 @@ const USDTAddress = '0xdac17f958d2ee523a2206206994597c13d831ec7'; function Components() { const { isConnected } = useWeb3ModalAccount() const { walletProvider } = useWeb3ModalProvider() - const [USDTBalance, setUSDTBalance] = useState(0); - const [smartContractName, setSmartContractName] = useState(''); + const [USDTBalance, setUSDTBalance] = useState(0); + const [smartContractName, setSmartContractName] = useState(''); async function getContractInfo() { if (!isConnected) throw Error('not connected'); @@ -126,5 +126,5 @@ function Components() { ``` :::info -- To learn how to set up Web3modal with vue, click [here](/guides/web3_modal_guide/vue). -::: \ No newline at end of file +- To learn how to set up Web3modal with vue, click [here](/guides/wallet/web3_modal_guide/vue). +::: diff --git a/docs/docs/guides/web3_modal_guide/vue.md b/docs/docs/guides/wallet/web3_modal_guide/vue.md similarity index 100% rename from docs/docs/guides/web3_modal_guide/vue.md rename to docs/docs/guides/wallet/web3_modal_guide/vue.md diff --git a/docs/docs/guides/web3_config/_category_.yml b/docs/docs/guides/web3_config/_category_.yml index d1fd0583848..6070480ec67 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: 16 \ No newline at end of file +position: 7 diff --git a/docs/docs/guides/web3_plugin_guide/_category_.yml b/docs/docs/guides/web3_plugin_guide/_category_.yml index 42237f7ea38..8ab333571fd 100644 --- a/docs/docs/guides/web3_plugin_guide/_category_.yml +++ b/docs/docs/guides/web3_plugin_guide/_category_.yml @@ -2,4 +2,4 @@ label: '🛠️ Web3 Plugin 🧩' collapsible: true collapsed: true link: null -position: 2 \ No newline at end of file +position: 12 diff --git a/docs/docs/guides/web3_providers_guide/_category_.yml b/docs/docs/guides/web3_providers_guide/_category_.yml index f426dbedf9a..2af69af2ea3 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: 4 \ No newline at end of file +position: 2 diff --git a/docs/docs/guides/web3_upgrade_guide/_category_.yml b/docs/docs/guides/web3_upgrade_guide/_category_.yml index aeab3125b26..8335efbea79 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: 11 \ No newline at end of file +position: 13 From 9086b98f25ef7ab9de0e699c00f462dca3e66f37 Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Thu, 30 May 2024 06:22:53 -0700 Subject: [PATCH 087/186] fix(docs): mastering providers (#7070) * Improvements to Mastering Providers section * Consistent naming of injected providers --- .../docs/guides/getting_started/quickstart.md | 4 +- .../docs/guides/web3_providers_guide/index.md | 365 +++++++----------- 2 files changed, 131 insertions(+), 238 deletions(-) diff --git a/docs/docs/guides/getting_started/quickstart.md b/docs/docs/guides/getting_started/quickstart.md index c1db2a9fdc8..886b2690e19 100644 --- a/docs/docs/guides/getting_started/quickstart.md +++ b/docs/docs/guides/getting_started/quickstart.md @@ -43,7 +43,7 @@ import { Web3 } from 'web3'; ## Initialize `Web3` with a provider -[Providers](/guides/web3_providers_guide/) are objects that are responsible for enabling connectivity with the Ethereum network. The `Web3` object must be initialized with a valid provider to function as intended. Web3.js supports [HTTP](/guides/web3_providers_guide/#http-provider), [WebSocket](/guides/web3_providers_guide/#websocket-provider), and [IPC](/guides/web3_providers_guide/#ipc-provider) providers, and exposes packages for working with each type of provider. +[Providers](/guides/web3_providers_guide/) are services that are responsible for enabling connectivity with the Ethereum network. The `Web3` object must be initialized with a valid provider to function as intended. Web3.js supports [HTTP](/guides/web3_providers_guide/#http-provider), [WebSocket](/guides/web3_providers_guide/#websocket-provider), and [IPC](/guides/web3_providers_guide/#ipc-provider) providers, and exposes packages for working with each type of provider. Web3.js is in compliance with [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193), the Ethereum Provider JavaScript API, so any EIP-1193 provider can be used to initialize the `Web3` object. @@ -248,7 +248,7 @@ console.log(eventTransfer); Web3.js allows user to subscribe to events for real-time notification of important contract interactions. Here is an example of creating a subscription to the Uniswap token's `Transfer` event: :::note -You MUST initialize the `Web3` object with a [WebSocket](/guides/web3_providers_guide/#websocket-provider) provider to subscribe to live events. +HTTP providers do not support real-time event subscriptions. Use one of the other [provider types](/guides/web3_providers_guide/#providers-types) to subscribe to real-time events. ::: ```ts diff --git a/docs/docs/guides/web3_providers_guide/index.md b/docs/docs/guides/web3_providers_guide/index.md index e3ecc880cb0..1c1a0c334cb 100644 --- a/docs/docs/guides/web3_providers_guide/index.md +++ b/docs/docs/guides/web3_providers_guide/index.md @@ -5,20 +5,9 @@ sidebar_label: 'Mastering Providers' # Web3js providers overview +Providers are services that are responsible for enabling Web3.js connectivity with the Ethereum network. Using a provider to connect your application to an Ethereum node is necessary for querying data, sending transactions, and interacting with smart contracts. This guide will explore the different types of Web3.js providers, how to set them up, and how to use them in an application. -## Live code editor - - - -## Introduction - -web3.js providers are objects responsible for enabling connectivity with the Ethereum network in various ways. Connecting your web application to an Ethereum node is necessary for sending transactions, querying data, and interacting with smart contracts on the network. In this guide, we will explore the different types of providers available in web3.js, how to set them up, and how to use them in your code. - -Connecting to a chain happens through a provider. You can pass the provider to the constructor as in the following example: - -:::tip -If you want to subscribe to live events in the blockchain, you should use [`WebSocket provider`](#websocket-provider) or [`IPC provider`](#ipc-provider) -::: +A provider is typically supplied when constructing a new `Web3` object: ```typescript title='Initialize a provider' import { Web3 } from 'web3'; @@ -29,36 +18,38 @@ const web3 = new Web3(/* PROVIDER*/); await web3.eth.getBlockNumber(); ``` -The created `Web3` instance will use the passed provider to interact with the blockchain network. This interaction happens when sending a request and receiving the response, and possibly when listening to provider events (if the provider support this). +The new `Web3` instance will use the supplied provider to interact with the blockchain network. This interaction happens when sending requests and receiving responses, and possibly when listening to provider events (if the provider supports this). ## Providers Types -web3.js supports several types of providers, each with its own unique features or specific use cases. Here are the main types: +Web3.js supports several types of providers for different use cases. Here are the available types: -1. [HTTP Provider](/api/web3-providers-http/class/HttpProvider) -2. [WebSocket Provider](/api/web3-providers-ws/class/WebSocketProvider) -3. [IPC Provider (for Node.js)](/api/web3-providers-ipc/class/IpcProvider) -4. [Third-party Providers (Compliant with EIP 1193)](https://eips.ethereum.org/EIPS/eip-1193) +1. [HTTP Provider](#http-provider) +2. [WebSocket Provider](#websocket-provider) +3. [IPC Provider (for Node.js)](#ipc-provider) +4. [Injected Providers (Compliant with EIP 1193)](#injected-provider) -A string containing string url for `http`/`https` or `ws`/`wss` protocol. And when a string is passed, an instance of the compatible class above will be created accordingly. ex. WebSocketProvider instance will be created for string containing `ws` or `wss`. And you access this instance by calling `web3.provider` to read the provider and possibly register an event listener. +HTTP and WebSocket providers can be supplied as URL strings. All provider types can be supplied by constructing one of the [`SupportedProviders`](/api/web3/namespace/types#SupportedProviders) types. -:::tip -The passed provider can be either type `string` or one of the [`SupportedProviders`](/api/web3-core#SupportedProviders). And if it is passed as a string, then internally the compatible provider object will be created and used. -::: +Keep reading to learn more about the different types of providers and how to use them. ### HTTP Provider -``` ts title='Initialize HTTP Provider' +HTTP is a request-response protocol and does not support persistent connection, which means that HTTP providers are not suitable for use cases that require real-time [event subscriptions](/guides/events_subscriptions/). + +``` ts title='Initialize an HTTP Provider' import { Web3, HttpProvider } from 'web3'; +//supply an HTTP provider as a URL string //highlight-next-line const web3 = new Web3('https://mainnet.infura.io/v3/YOUR_INFURA_ID'); await web3.eth.getBlockNumber() // ↳ 18849658n -// or +// OR +//supply an HTTP provider by constructing a new HttpProvider //highlight-next-line const web3_2 = new Web3(new HttpProvider('https://mainnet.infura.io/v3/YOUR_INFURA_ID')); @@ -66,18 +57,53 @@ await web3.eth.getBlockNumber() // ↳ 18849658n ``` +#### Configuring HTTP Providers + +HTTP providers can be configured by including an [`HttpProviderOptions`](/api/web3-providers-http/interface/HttpProviderOptions/) object in the [`HttpProvider` constructor](/api/web3-providers-http/class/HttpProvider#constructor). The `HttpProviderOptions` type has a single property, `providerOptions`, which is a standard TypeScript [`RequestInit`](https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules_typedoc_node_modules_typescript_lib_lib_dom_d_.requestinit.html) object. + +```ts title='Configuring an HTTP Provider' +import { Web3, HttpProvider } from 'web3'; + +const httpOptions = { + providerOptions: { + body: undefined, + cache: 'force-cache', + credentials: 'same-origin', + headers: { + 'Content-Type': 'application/json', + }, + integrity: undefined, + keepalive: true, + method: 'GET', + mode: 'same-origin', + redirect: 'error', + referrer: undefined, + referrerPolicy: 'same-origin', + signal: undefined, + window: undefined, + } as RequestInit, +}; + +const web3 = new Web3(new HttpProvider('https://eth.llamarpc.com', httpOptions)); +``` + ### WebSocket provider +WebSockets support a persistent connection between a client and a server, which means they are suitable for use cases that require real-time [event subscriptions](/guides/events_subscriptions/). + ``` ts title='Initialize WS Provider' import { Web3, WebSocketProvider } from 'web3'; +//supply a WebSocket provider as a URL string //highlight-next-line const web3 = new Web3('wss://mainnet.infura.io/ws/v3/YOUR_INFURA_ID'); await web3.eth.getBlockNumber(); // ↳ 18849658n -// or +// OR + +//supply a WebSocket provider by constructing a new WebSocketProvider //highlight-next-line const web3_2 = new Web3(new WebSocketProvider('wss://mainnet.infura.io/ws/v3/YOUR_INFURA_ID')); @@ -85,8 +111,43 @@ await web3.eth.getBlockNumber(); // ↳ 18849658n ``` +#### Configuring WebSocket Providers + +The [`WebSocketProvider` constructor](/api/web3-providers-ws/class/WebSocketProvider#constructor) accepts two optional parameters that can be used to configure the behavior of the `WebSocketProvider`: the first parameter must be of type [`ClientRequestArgs`](https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules__types_node_http_d_._http_.clientrequestargs.html) or of [`ClientOptions`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/e5ee5eae6a592198e469ad9f412bab8d223fcbb6/types/ws/index.d.ts#L243) and the second parameter must be of type [`ReconnectOptions`](/api/web3/namespace/utils#ReconnectOptions). + +```ts title='Configuring a WebSocket Provider' +//include both optional parameters +const provider = new WebSocketProvider( + `ws://localhost:8545`, + { + headers: { + //for node services that require an API key in a header + 'x-api-key': '', + }, + }, + { + delay: 500, + autoReconnect: true, + maxAttempts: 10, + } +); + +//OR include only ReconnectOptions +const provider = new WebSocketProvider( + `ws://localhost:8545`, + {}, + { + delay: 500, + autoReconnect: true, + maxAttempts: 10, + } +); +``` + ### IPC Provider +IPC (inter-process communication) providers offer high-performance local communication and provide a faster alternative to HTTP providers. IPC providers are tailored for efficiency and excel in local environments, and also support real-time [event subscriptions](/guides/events_subscriptions/). + ``` ts title='Initialize IPC Provider' import { Web3 } from 'web3'; //highlight-next-line @@ -99,27 +160,49 @@ await web3.eth.getBlockNumber(); // ↳ 18849658n ``` -## Providers Priorities +#### Configuring IPC Providers + +The [`IpcProvider` constructor](/api/web3-providers-ipc/class/IpcProvider#constructor) accepts two optional parameters that can be used to configure the behavior of the `IpcProvider`: the first parameter must be of type [`SocketConstructorOpts`](https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules__types_node_net_d_._net_.socketconstructoropts.html) and the second parameter must be of type [`ReconnectOptions`](/api/web3/namespace/utils#ReconnectOptions). -There are multiple ways to set the provider. -```ts title='Setting a provider' -web3.setProvider(myProvider); -web3.eth.setProvider(myProvider); -web3.Contract.setProvider(myProvider); -contractInstance.setProvider(myProvider); + +```ts title='Configuring an IPC Provider' +//include both optional parameters +const provider = new IpcProvider( + '/Users/myuser/Library/Ethereum/geth.ipc', + { + writable: false, + }, + { + delay: 500, + autoReconnect: true, + maxAttempts: 10, + } +); + +//OR include only ReconnectOptions +const provider = new IpcProvider( + '/Users/myuser/Library/Ethereum/geth.ipc', + {}, + { + delay: 500, + autoReconnect: true, + maxAttempts: 10, + } +); ``` -The key rule for setting provider is as follows: +### Injected Provider -1. Any provider set on the higher level will be applied to all lower levels. e.g. Any provider set using `web3.setProvider` will also be applied to `web3.eth` object. -2. For contracts `web3.Contract.setProvider` can be used to set provider for **all instances** of contracts created by `web3.eth.Contract`. +Injected providers are supplied by an external third-party, most often a wallet or a web browser that is designed to be used with the Ethereum network. In addition to providing network connectivity, injected providers often supply one or more [accounts](/guides/wallet/). Web3.js supports any injected provider that is compliant with [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193). Injected providers support real-time [event subscriptions](/guides/events_subscriptions/). Continue reading for an [example](#injected-provider-1) of using an injected provider. ---- +## Provider Origins + +A provider may be local to an application (i.e. running on the same machine) or remote (i.e. running on a third-party server). Injected providers are a third alternative that are supplied by an external third-party, most often a wallet or a web browser that is designed to be used with the Ethereum network. Keep reading for more examples that illustrate how to work with local, remote, and injected providers. -## Usage Scenarios +### Local Provider -### Local Geth Node +Local providers can usually be accessed via IPC, HTTP, or WebSocket. The following examples demonstrates using a local Geth node to supply the Web3.js provider. ```typescript title='IPC, HTTP and WS provider' import { Web3 } from 'web3'; @@ -144,7 +227,9 @@ web3.setProvider('ws://localhost:8546'); web3.setProvider(new Web3.providers.WebsocketProvider('ws://localhost:8546')); ``` -### Remote Node Provider +### Remote Provider + +Services like [Alchemy](https://www.alchemy.com/), [Infura](https://www.infura.io/), and [QuickNode](https://www.quicknode.com/) offer Ethereum node services that can be accessed via HTTP or Websocket. ```ts title='Alchemy, Infura, etc' // like Alchemy (https://www.alchemyapi.io/supernode) @@ -155,9 +240,11 @@ const web3 = new Web3('https://eth-mainnet.alchemyapi.io/v2/your-api-key'); ### Injected Provider -As stated above, the injected provider should be in compliance with [EIP-1193](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1193.md). And it is tested with Ganache provider, Hardhat provider, and Incubed (IN3) as a provider. +Injected providers are supplied by an external third-party, most often a wallet or a web browser that is designed to be used with the Ethereum network. In addition to providing network connectivity, injected providers often supply one or more [accounts](/guides/wallet/). Web3.js supports any injected provider that is compliant with [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193) and has been tested with multiple EIP-1193 providers, including [MetaMask](https://docs.metamask.io/wallet/reference/provider-api/), [Hardhat](https://hardhat.org/hardhat-runner/docs/advanced/hardhat-runtime-environment), and [Incubed (IN3)](https://in3.readthedocs.io/en/develop/index.html). -The web3.js 4.x Provider specifications are defined in [web3 base provider](https://github.com/ChainSafe/web3.js/blob/4.x/packages/web3-types/src/web3_base_provider.ts) for Injected Providers. +:::note +The following example should be run in a browser with the MetaMask extension installed. +::: ```html title='E.g, Metamask' @@ -186,197 +273,3 @@ The web3.js 4.x Provider specifications are defined in [web3 base provider](http }); ``` - -Note that the above code should be hosted in a web server (that could be a simple local web server), because many browser does not support this feature for static files located on your machine. - -## Provider Options - -There are differences in the objects that could be passed in the Provider constructors. - -### HttpProvider - -The options is of type `HttpProviderOptions`, which is an object with a single key named `providerOptions` and its value is an object of type `RequestInit`. -Regarding `RequestInit` see [microsoft's github](https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules_typedoc_node_modules_typescript_lib_lib_dom_d_.requestinit.html). - -```ts title='HTTP Provider example' -const httpOptions = { - providerOptions: { - body: undefined, - cache: 'force-cache', - credentials: 'same-origin', - headers: { - 'Content-Type': 'application/json', - }, - integrity: 'foo', - keepalive: true, - method: 'GET', - mode: 'same-origin', - redirect: 'error', - referrer: 'foo', - referrerPolicy: 'same-origin', - signal: undefined, - window: undefined, - } as RequestInit, -}; -``` - -### WebSocketProvider - -Use WebSocketProvider to connect to a Node using a WebSocket connection, i.e. over the `ws` or `wss` protocol. - -The options object is of type `ClientRequestArgs` or of `ClientOptions`. See [here](https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules__types_node_http_d_._http_.clientrequestargs.html) for `ClientRequestArgs` and [here](https://github.com/websockets/ws) for `ClientOptions`. - -The second option parameter can be given regarding reconnecting. And here is its type: - -```ts title='WebSocket Provider example' -// this is the same options interface used for both WebSocketProvider and IpcProvider -type ReconnectOptions = { - autoReconnect: boolean, // default: `true` - delay: number, // default: `5000` - maxAttempts: number, // default: `5` -}; - -``` - -```ts title='Instantiation of WebSocket Provider' -const provider = new WebSocketProvider( - `ws://localhost:8545`, - { - headers: { - // to provide the API key if the Node requires the key to be inside the `headers` for example: - 'x-api-key': '', - }, - }, - { - delay: 500, - autoReconnect: true, - maxAttempts: 10, - } -); -``` - -The second and the third parameters are both optional. And, for example, the second parameter could be an empty object or undefined, like in the following example: - -```ts title='Instantiation of WebSocket Provider' -const provider = new WebSocketProvider( - `ws://localhost:8545`, - {}, - { - delay: 500, - autoReconnect: true, - maxAttempts: 10, - } -); -``` - -Below is an example for the passed options: - -```ts title='WS Provider options example' -let clientOptions: ClientOptions = { - // Useful for credentialed urls, e.g: ws://username:password@localhost:8546 - headers: { - authorization: 'Basic username:password', - }, - maxPayload: 100000000, -}; - -const reconnectOptions: ReconnectOptions = { - autoReconnect: true, - delay: 5000, - maxAttempts: 5, -}; -``` - -### IpcProvider - -The IPC Provider could be used in node.js dapps when running a local node. And it provide the most secure connection. - -It accepts a second parameter called `socketOptions`. And, its type is `SocketConstructorOpts`. See [here](https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules__types_node_net_d_._net_.socketconstructoropts.html) for full details. And here is its interface: - -```ts title='IPC Provider options' -// for more check https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules__types_node_net_d_._net_.socketconstructoropts.html -interface SocketConstructorOpts { - fd?: number | undefined; - allowHalfOpen?: boolean | undefined; - readable?: boolean | undefined; - writable?: boolean | undefined; -} -``` - -And, the third parameter is called `reconnectOptions` that is of the type `ReconnectOptions`. It can be given to control: auto-reconnecting, delay and max tries attempts. And here its type: - -```ts -// this is the same options interface used for both WebSocketProvider and IpcProvider -type ReconnectOptions = { - autoReconnect: boolean, // default: `true` - delay: number, // default: `5000` - maxAttempts: number, // default: `5` -}; -``` - -Below is an example for the passed options for each version: - -```ts title='Options Example' -let clientOptions: SocketConstructorOpts = { - allowHalfOpen: false; - readable: true; - writable: true; -}; - -const reconnectOptions: ReconnectOptions = { - autoReconnect: true, - delay: 5000, - maxAttempts: 5, -}; -``` - -And here is a sample instantiation for the `IpcProvider`: - -```ts title='IPC Provider example' -const provider = new IpcProvider( - `path.ipc`, - { - writable: false, - }, - { - delay: 500, - autoReconnect: true, - maxAttempts: 10, - } -); -``` - -The second and the third parameters are both optional. And, for example, the second parameter could be an empty object or undefined. - -```ts title='IPC Provider example' -const provider = new IpcProvider( - `path.ipc`, - {}, - { - delay: 500, - autoReconnect: true, - maxAttempts: 10, - } -); -``` - -:::info -This section applies for both `IpcProvider` and `WebSocketProvider`. -::: - -The error message, for the max reconnect attempts, will contain the value of the variable `maxAttempts` as follows: - -`` `Maximum number of reconnect attempts reached! (${maxAttempts})` `` - -And here is how to catch the error, if max attempts reached when there is auto reconnecting: - -```ts title='Error message for reconnect attempts' -provider.on('error', (error) => { - if (error.message.startsWith('Maximum number of reconnect attempts reached!')) { - // the `error.message` will be `Maximum number of reconnect attempts reached! (${maxAttempts})` - // the `maxAttempts` is equal to the provided value by the user, or the default value `5`. - } -}); -``` - - From 51d216fbe63e35d3792e9508705fa4b0b1612378 Mon Sep 17 00:00:00 2001 From: Oleksii Kosynskyi Date: Sun, 2 Jun 2024 21:54:10 -0400 Subject: [PATCH 088/186] Remove .snyk files (#7073) * add .snyk file * fix snyk scan for all projects * Delete .snyk * Remove snyk files * remove .snyk files --- docs/.snyk | 36 ------------------------- packages/web3/.snyk | 21 --------------- tools/eslint-config-base-web3/.snyk | 41 ----------------------------- 3 files changed, 98 deletions(-) delete mode 100644 docs/.snyk delete mode 100644 packages/web3/.snyk delete mode 100644 tools/eslint-config-base-web3/.snyk diff --git a/docs/.snyk b/docs/.snyk deleted file mode 100644 index b29b615196e..00000000000 --- a/docs/.snyk +++ /dev/null @@ -1,36 +0,0 @@ -# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities. -version: v1.25.0 -# ignores vulnerabilities until expiry date; change duration by modifying expiry date -ignore: - SNYK-JS-BRACES-6838727: - - '*': - reason: Docusaurus issue - expires: 3024-06-26T17:29:07.153Z - created: 2024-05-27T17:29:07.159Z - SNYK-JS-EXPRESS-6474509: - - '*': - reason: Docusaurus issue - expires: 3024-06-26T17:29:31.142Z - created: 2024-05-27T17:29:31.149Z - SNYK-JS-INFLIGHT-6095116: - - '*': - reason: Docusaurus issue - expires: 3024-06-26T17:29:51.622Z - created: 2024-05-27T17:29:51.628Z - SNYK-JS-MICROMATCH-6838728: - - '*': - reason: Docusaurus issue - expires: 3024-06-26T17:30:47.237Z - created: 2024-05-27T17:30:47.240Z - SNYK-JS-SERIALIZEJAVASCRIPT-6147607: - - '*': - reason: Docusaurus issue - expires: 3024-06-26T17:31:06.652Z - created: 2024-05-27T17:31:06.656Z - SNYK-JS-WEBPACKDEVMIDDLEWARE-6476555: - - '*': - reason: Docusaurus issue - expires: 3024-06-26T20:52:00.793Z - created: 2024-05-27T20:52:00.797Z - -patch: {} diff --git a/packages/web3/.snyk b/packages/web3/.snyk deleted file mode 100644 index 5b289bc1640..00000000000 --- a/packages/web3/.snyk +++ /dev/null @@ -1,21 +0,0 @@ -# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities. -version: v1.25.0 -# ignores vulnerabilities until expiry date; change duration by modifying expiry date -ignore: - SNYK-JS-WEB3-174533: - - '*': - reason: Ignore test issue - expires: 3024-06-26T17:16:53.075Z - created: 2024-05-27T17:16:53.080Z - SNYK-JS-JSON5-3182856: - - '*': - reason: Eslint problem - expires: 3024-06-26T20:53:53.640Z - created: 2024-05-27T20:53:53.644Z - SNYK-JS-SEMVER-3247795: - - '*': - reason: Eslint problem - expires: 3024-06-26T20:54:20.755Z - created: 2024-05-27T20:54:20.759Z - -patch: {} diff --git a/tools/eslint-config-base-web3/.snyk b/tools/eslint-config-base-web3/.snyk deleted file mode 100644 index f0ce4e19c9c..00000000000 --- a/tools/eslint-config-base-web3/.snyk +++ /dev/null @@ -1,41 +0,0 @@ -# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities. -version: v1.25.0 -# ignores vulnerabilities until expiry date; change duration by modifying expiry date -ignore: - SNYK-JS-BRACES-6838727: - - '*': - reason: Docusaurus issue - expires: 3024-06-26T17:29:07.153Z - created: 2024-05-27T17:29:07.159Z - SNYK-JS-EXPRESS-6474509: - - '*': - reason: Docusaurus issue - expires: 3024-06-26T17:29:31.142Z - created: 2024-05-27T17:29:31.149Z - SNYK-JS-INFLIGHT-6095116: - - '*': - reason: Docusaurus issue - expires: 3024-06-26T17:29:51.622Z - created: 2024-05-27T17:29:51.628Z - SNYK-JS-MICROMATCH-6838728: - - '*': - reason: Eslint issue - expires: 3024-06-26T17:30:47.237Z - created: 2024-05-27T17:30:47.240Z - SNYK-JS-WEBPACKDEVMIDDLEWARE-6476555: - - '*': - reason: Docusaurus issue - expires: 3024-06-26T20:52:00.793Z - created: 2024-05-27T20:52:00.797Z - SNYK-JS-JSON5-3182856: - - '*': - reason: Eslint problem - expires: 3024-06-26T20:53:53.640Z - created: 2024-05-27T20:53:53.644Z - SNYK-JS-SEMVER-3247795: - - '*': - reason: Eslint problem - expires: 3024-06-26T20:54:20.755Z - created: 2024-05-27T20:54:20.759Z - -patch: {} From 8f627495717df387f4170793d438b134a8e0a08a Mon Sep 17 00:00:00 2001 From: Muhammad Altabba <24407834+Muhammad-Altabba@users.noreply.github.com> Date: Mon, 3 Jun 2024 16:07:20 +0200 Subject: [PATCH 089/186] 100% Coverage web3-utills (#7042) * increase unit tests for SocketProvider * add a test for SocketProvider * add a test for PromiseHelper * add unit tests for utils * remove un visited code branch * fix linting issue * point to a pice of code to investigate * fix linting issue * add coverage to hash * cover json-rpc tests * cover socket provider file * add coverage string manipulation * add coverage to formatters.ts * fix failing tests * update hash * run prettier * remove unintended cases for formatter and convert --------- Co-authored-by: Alex Luu --- .gitignore | 2 + packages/web3-utils/src/converters.ts | 37 +- packages/web3-utils/src/formatter.ts | 12 +- packages/web3-utils/src/hash.ts | 17 +- packages/web3-utils/src/json_rpc.ts | 2 +- packages/web3-utils/src/promise_helpers.ts | 39 +- packages/web3-utils/src/socket_provider.ts | 30 +- .../web3-utils/test/fixtures/converters.ts | 72 ++- .../web3-utils/test/fixtures/formatter.ts | 1 + packages/web3-utils/test/fixtures/hash.ts | 14 +- packages/web3-utils/test/fixtures/json_rpc.ts | 40 ++ .../test/fixtures/string_manipulation.ts | 6 +- .../test/unit/chunk_response_parser.test.ts | 14 + .../web3-utils/test/unit/converters.test.ts | 69 ++- .../web3-utils/test/unit/formatter.test.ts | 23 +- packages/web3-utils/test/unit/hash.test.ts | 8 + packages/web3-utils/test/unit/index.test.ts | 64 +++ .../web3-utils/test/unit/json_rpc.test.ts | 63 ++- packages/web3-utils/test/unit/objects.test.ts | 9 + .../test/unit/promise_helpers.test.ts | 8 + .../test/unit/socket_provider.test.ts | 529 +++++++++++++++++- .../test/unit/web3_deferred_promise.test.ts | 13 + 22 files changed, 959 insertions(+), 113 deletions(-) create mode 100644 packages/web3-utils/test/unit/index.test.ts diff --git a/.gitignore b/.gitignore index c22337c0c9a..72f88324900 100644 --- a/.gitignore +++ b/.gitignore @@ -47,3 +47,5 @@ packages/web3/.in3/ benchmark-data.txt .eslintcache + +.history \ No newline at end of file diff --git a/packages/web3-utils/src/converters.ts b/packages/web3-utils/src/converters.ts index 6649bef1481..9c94a4332b0 100644 --- a/packages/web3-utils/src/converters.ts +++ b/packages/web3-utils/src/converters.ts @@ -79,7 +79,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'; +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; /** @@ -366,7 +367,7 @@ export const toHex = ( return returnType ? 'bigint' : numberToHex(value); } - if(isUint8Array(value)) { + if (isUint8Array(value)) { return returnType ? 'bytes' : bytesToHex(value); } @@ -386,6 +387,15 @@ export const toHex = ( return returnType ? 'bytes' : `0x${value}`; } if (isHex(value) && !isInt(value) && isUInt(value)) { + // This condition seems problematic because meeting + // both conditions `!isInt(value) && isUInt(value)` should be impossible. + // But a value pass for those conditions: "101611154195520776335741463917853444671577865378275924493376429267637792638729" + // Note that according to the docs: it is supposed to be treated as a string (https://docs.web3js.org/guides/web3_upgrade_guide/x/web3_utils_migration_guide#conversion-to-hex) + // In short, the strange is that isInt(value) is false but isUInt(value) is true for the value above. + // TODO: isUInt(value) should be investigated. + + // However, if `toHex('101611154195520776335741463917853444671577865378275924493376429267637792638729', true)` is called, it will return `true`. + // But, if `toHex('101611154195520776335741463917853444671577865378275924493376429267637792638729')` is called, it will throw inside `numberToHex`. return returnType ? 'uint' : numberToHex(value); } @@ -419,14 +429,14 @@ export const toHex = ( */ export const toNumber = (value: Numbers): number | bigint => { if (typeof value === 'number') { - 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'. - // Using BigInt prevents this - return BigInt(value); - } + if (value > 1e20) { + 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'. + // Using BigInt prevents this + return BigInt(value); + } return value; } @@ -506,10 +516,9 @@ export const fromWei = (number: Numbers, unit: EtherUnits | number): string => { if (unit < 0 || !Number.isInteger(unit)) { throw new InvalidIntegerError(unit); } - denomination = bigintPower(BigInt(10),BigInt(unit)); + denomination = bigintPower(BigInt(10), BigInt(unit)); } - // value in wei would always be integer // 13456789, 1234 const value = String(toNumber(number)); @@ -575,8 +584,8 @@ export const toWei = (number: Numbers, unit: EtherUnits | number): string => { if (unit < 0 || !Number.isInteger(unit)) { throw new InvalidIntegerError(unit); } - - denomination = bigintPower(BigInt(10),BigInt(unit)); + + denomination = bigintPower(BigInt(10), BigInt(unit)); } let parsedNumber = number; diff --git a/packages/web3-utils/src/formatter.ts b/packages/web3-utils/src/formatter.ts index 42062add5c6..665965a8eed 100644 --- a/packages/web3-utils/src/formatter.ts +++ b/packages/web3-utils/src/formatter.ts @@ -57,10 +57,8 @@ const findSchemaByDataPath = ( for (const dataPart of dataPath) { if (result.oneOf && previousDataPath) { - const path = oneOfPath.find(function (element: [string, number]) { - return (this as unknown as string) === element[0]; - }, previousDataPath ?? ''); - + const currentDataPath = previousDataPath; + const path = oneOfPath.find(([key]) => key === currentDataPath); if (path && path[0] === previousDataPath) { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access result = result.oneOf[path[1]]; @@ -75,10 +73,6 @@ const findSchemaByDataPath = ( } else if (result.items && (result.items as JsonSchema).properties) { const node = (result.items as JsonSchema).properties as Record; - if (!node) { - return undefined; - } - result = node[dataPart]; } else if (result.items && isObject(result.items)) { result = result.items; @@ -307,7 +301,7 @@ export const convert = ( // If value is an object, recurse into it if (isObject(value)) { - convert(value, schema, dataPath, format); + convert(value, schema, dataPath, format, oneOfPath); dataPath.pop(); continue; } diff --git a/packages/web3-utils/src/hash.ts b/packages/web3-utils/src/hash.ts index 6e498138c29..0289a429a52 100644 --- a/packages/web3-utils/src/hash.ts +++ b/packages/web3-utils/src/hash.ts @@ -17,25 +17,25 @@ along with web3.js. If not, see . /** * This package provides utility functions for Ethereum dapps and other web3.js packages. - * + * * For using Utils functions, first install Web3 package using `npm i web3` or `yarn add web3`. - * After that, Web3 Utils functions will be available as mentioned below. + * After that, Web3 Utils functions will be available as mentioned below. * ```ts * import { Web3 } from 'web3'; * const web3 = new Web3(); - * + * * const value = web3.utils.fromWei("1", "ether") - * + * * ``` - * + * * For using individual package install `web3-utils` package using `npm i web3-utils` or `yarn add web3-utils` and only import required functions. - * This is more efficient approach for building lightweight applications. + * This is more efficient approach for building lightweight applications. * ```ts * import { fromWei, soliditySha3Raw } from 'web3-utils'; - * + * * console.log(fromWei("1", "ether")); * console.log(soliditySha3Raw({ type: "string", value: "helloworld" })) - * + * * ``` * @module Utils */ @@ -172,7 +172,6 @@ const getType = (arg: Sha3Input): [string, EncodingTypes] => { if (Array.isArray(arg)) { throw new Error('Autodetection of array types is not supported.'); } - let type; let value; // if type is given diff --git a/packages/web3-utils/src/json_rpc.ts b/packages/web3-utils/src/json_rpc.ts index 573d39197e3..495a425611f 100644 --- a/packages/web3-utils/src/json_rpc.ts +++ b/packages/web3-utils/src/json_rpc.ts @@ -99,7 +99,7 @@ let requestIdSeed: number | undefined; /** * Optionally use to make the jsonrpc `id` start from a specific number. * Without calling this function, the `id` will be filled with a Uuid. - * But after this being called with a number, the `id` will be a number staring from the provided `start` variable. + * But after this being called with a number, the `id` will be a number starting from the provided `start` variable. * However, if `undefined` was passed to this function, the `id` will be a Uuid again. * @param start - a number to start incrementing from. * Or `undefined` to use a new Uuid (this is the default behavior) diff --git a/packages/web3-utils/src/promise_helpers.ts b/packages/web3-utils/src/promise_helpers.ts index c8e211fbbb7..a2140a2d1c5 100644 --- a/packages/web3-utils/src/promise_helpers.ts +++ b/packages/web3-utils/src/promise_helpers.ts @@ -20,7 +20,6 @@ import { isNullish } from 'web3-validator'; export type Timer = ReturnType; export type Timeout = ReturnType; - /** * An alternative to the node function `isPromise` that exists in `util/types` because it is not available on the browser. * @param object - to check if it is a `Promise` @@ -74,7 +73,6 @@ export async function waitWithTimeout( return result; } - /** * Repeatedly calls an async function with a given interval until the result of the function is defined (not undefined or null), * or until a timeout is reached. It returns promise and intervalId. @@ -85,25 +83,27 @@ export function pollTillDefinedAndReturnIntervalId( func: AsyncFunction, interval: number, ): [Promise>, Timer] { - let intervalId: Timer | undefined; const polledRes = new Promise>((resolve, reject) => { - intervalId = setInterval(function intervalCallbackFunc(){ - (async () => { - try { - const res = await waitWithTimeout(func, interval); - - if (!isNullish(res)) { + intervalId = setInterval( + (function intervalCallbackFunc() { + (async () => { + try { + const res = await waitWithTimeout(func, interval); + + if (!isNullish(res)) { + clearInterval(intervalId); + resolve(res as unknown as Exclude); + } + } catch (error) { clearInterval(intervalId); - resolve(res as unknown as Exclude); + reject(error); } - } catch (error) { - clearInterval(intervalId); - reject(error); - } - })() as unknown; - return intervalCallbackFunc;}() // this will immediate invoke first call - , interval); + })() as unknown; + return intervalCallbackFunc; + })(), // this will immediate invoke first call + interval, + ); }); return [polledRes as unknown as Promise>, intervalId!]; @@ -113,7 +113,7 @@ export function pollTillDefinedAndReturnIntervalId( * Repeatedly calls an async function with a given interval until the result of the function is defined (not undefined or null), * or until a timeout is reached. * pollTillDefinedAndReturnIntervalId() function should be used instead of pollTillDefined if you need IntervalId in result. - * This function will be deprecated in next major release so use pollTillDefinedAndReturnIntervalId(). + * This function will be deprecated in next major release so use pollTillDefinedAndReturnIntervalId(). * @param func - The function to call. * @param interval - The interval in milliseconds. */ @@ -146,7 +146,7 @@ export function rejectIfTimeout(timeout: number, error: Error): [Timer, Promise< /** * Sets an interval that repeatedly executes the given cond function with the specified interval between each call. * If the condition is met, the interval is cleared and a Promise that rejects with the returned value is returned. - * @param cond - The function/confition to call. + * @param cond - The function/condition to call. * @param interval - The interval in milliseconds. * @returns - an array with the interval ID and the Promise. */ @@ -168,4 +168,3 @@ export function rejectIfConditionAtInterval( }); return [intervalId!, rejectIfCondition]; } - diff --git a/packages/web3-utils/src/socket_provider.ts b/packages/web3-utils/src/socket_provider.ts index d847dcbccc9..0a73fb8378f 100644 --- a/packages/web3-utils/src/socket_provider.ts +++ b/packages/web3-utils/src/socket_provider.ts @@ -187,13 +187,13 @@ export abstract class SocketProvider< protected _validateProviderPath(path: string): boolean { return !!path; } - + /** * * @returns the pendingRequestQueue size */ // eslint-disable-next-line class-methods-use-this - public getPendingRequestQueueSize() { + public getPendingRequestQueueSize() { return this._pendingRequestsQueue.size; } @@ -350,32 +350,34 @@ export abstract class SocketProvider< /** * Safely disconnects the socket, async and waits for request size to be 0 before disconnecting - * @param forceDisconnect - If true, will clear queue after 5 attempts of waiting for both pending and sent queue to be 0 + * @param forceDisconnect - If true, will clear queue after 5 attempts of waiting for both pending and sent queue to be 0 * @param ms - Determines the ms of setInterval * @param code - The code to be sent to the server * @param data - The data to be sent to the server */ - public async safeDisconnect(code?: number, data?: string, forceDisconnect = false,ms = 1000) { + public async safeDisconnect(code?: number, data?: string, forceDisconnect = false, ms = 1000) { let retryAttempt = 0; - const checkQueue = async () => + const checkQueue = async () => new Promise(resolve => { const interval = setInterval(() => { - if (forceDisconnect && retryAttempt === 5) { + if (forceDisconnect && retryAttempt >= 5) { this.clearQueues(); } - if (this.getPendingRequestQueueSize() === 0 && this.getSentRequestsQueueSize() === 0) { + if ( + this.getPendingRequestQueueSize() === 0 && + this.getSentRequestsQueueSize() === 0 + ) { clearInterval(interval); resolve(true); } - retryAttempt+=1; - }, ms) - }) - + retryAttempt += 1; + }, ms); + }); + await checkQueue(); this.disconnect(code, data); } - /** * Removes all listeners for the specified event type. * @param type - The event type to remove the listeners for @@ -512,7 +514,7 @@ export abstract class SocketProvider< if (isNullish(responses) || responses.length === 0) { return; } - + for (const response of responses) { if ( jsonRpc.isResponseWithNotification(response as JsonRpcNotification) && @@ -544,7 +546,7 @@ export abstract class SocketProvider< this._sentRequestsQueue.delete(requestId); } } - + public clearQueues(event?: ConnectionEvent) { this._clearQueues(event); } diff --git a/packages/web3-utils/test/fixtures/converters.ts b/packages/web3-utils/test/fixtures/converters.ts index 9f0324b68ad..cecb0b3fafb 100644 --- a/packages/web3-utils/test/fixtures/converters.ts +++ b/packages/web3-utils/test/fixtures/converters.ts @@ -235,21 +235,20 @@ export const toHexValidData: [Numbers | Bytes | Address | boolean, [HexString, V ], ['-0x01', ['-0x1', 'int256']], ['123c', ['0x123c', 'bytes']], - [new Uint8Array([ - 221, 128, 128, 128, 148, 186, 248, - 242, 159, 130, 231, 84, 254, 199, - 252, 69, 21, 58, 104, 102, 201, - 137, 255, 3, 196, 10, 128, 128, - 128, 128 - ]), ['0xdd80808094baf8f29f82e754fec7fc45153a6866c989ff03c40a80808080', 'bytes']], - [Buffer.from([ - 221, 128, 128, 128, 148, 186, 248, - 242, 159, 130, 231, 84, 254, 199, - 252, 69, 21, 58, 104, 102, 201, - 137, 255, 3, 196, 10, 128, 128, - 128, 128 - ]), ['0xdd80808094baf8f29f82e754fec7fc45153a6866c989ff03c40a80808080', 'bytes']] - + [ + new Uint8Array([ + 221, 128, 128, 128, 148, 186, 248, 242, 159, 130, 231, 84, 254, 199, 252, 69, 21, 58, + 104, 102, 201, 137, 255, 3, 196, 10, 128, 128, 128, 128, + ]), + ['0xdd80808094baf8f29f82e754fec7fc45153a6866c989ff03c40a80808080', 'bytes'], + ], + [ + Buffer.from([ + 221, 128, 128, 128, 148, 186, 248, 242, 159, 130, 231, 84, 254, 199, 252, 69, 21, 58, + 104, 102, 201, 137, 255, 3, 196, 10, 128, 128, 128, 128, + ]), + ['0xdd80808094baf8f29f82e754fec7fc45153a6866c989ff03c40a80808080', 'bytes'], + ], ]; export const toHexInvalidData: [any, string][] = [ @@ -320,15 +319,15 @@ const conversionBaseData: [[Numbers, EtherUnits | number], string][] = [ export const fromWeiValidData: [[Numbers, EtherUnits | number], Numbers][] = [ ...conversionBaseData, - [['0xff', 'wei'], '255'], - [[1e+22, 'ether'], '10000'], - [[19999999999999991611392, 'ether'], '19999.999999999991611392'], - [[1.9999999999999991611392e+22, 'ether'], '19999.999999999991611392'], + [['0xff', 'wei'], '255'], + [[1e22, 'ether'], '10000'], + [[19999999999999991611392, 'ether'], '19999.999999999991611392'], + [[1.9999999999999991611392e22, 'ether'], '19999.999999999991611392'], [['1000000', 'ether'], '0.000000000001'], [['1123456789123456789', 'ether'], '1.123456789123456789'], [['1123', 'kwei'], '1.123'], - [['1234100' ,'kwei'], '1234.1'], - [['3308685546611893', 'ether'], '0.003308685546611893'] + [['1234100', 'kwei'], '1234.1'], + [['3308685546611893', 'ether'], '0.003308685546611893'], ]; export const toWeiValidData: [[Numbers, EtherUnits | number], Numbers][] = [ @@ -339,17 +338,24 @@ export const toWeiValidData: [[Numbers, EtherUnits | number], Numbers][] = [ [['1000000', 'ether'], 0.000000000001], [['1123456789123456789', 'ether'], '1.123456789123456789123'], [['1123', 'kwei'], '1.12345'], - [['1234100' ,'kwei'], '1234.1'], + [['1234100', 'kwei'], '1234.1'], [['3308685546611893', 'ether'], '0.0033086855466118933'], [['1123', 'kwei'], 1.12345], - ]; 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'], - + [ + [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][] = [ @@ -362,8 +368,14 @@ 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.'] + [ + ['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][] = [ @@ -374,6 +386,7 @@ export const toWeiInvalidData: [[any, any], string][] = [ [[{}, 'kwei'], 'value "{}" at "/0" must pass "number" validation'], [['data', 'kwei'], 'value "data" at "/0" must pass "number" validation'], [['1234', 'uwei'], 'Invalid value given "uwei". Error: invalid unit.'], + [['123', -1], 'Invalid value given "-1". Error: not a valid unit. Must be a positive integer.'], ]; export const toCheckSumValidData: [string, string][] = [ ['0x0089d53f703f7e0843953d48133f74ce247184c2', '0x0089d53F703f7E0843953D48133f74cE247184c2'], @@ -397,6 +410,7 @@ export const bytesToUint8ArrayValidData: [Bytes, Uint8Array][] = [ ['0x1234', new Uint8Array([18, 52])], ['0x1234', new Uint8Array([18, 52])], [new Uint8Array(hexToBytes('0c12')), new Uint8Array(hexToBytes('0c12'))], + [[72, 12] as any, new Uint8Array([72, 12])], ]; export const toBigIntValidData: [any, bigint][] = [ diff --git a/packages/web3-utils/test/fixtures/formatter.ts b/packages/web3-utils/test/fixtures/formatter.ts index 7437373d708..5d44b05df2d 100644 --- a/packages/web3-utils/test/fixtures/formatter.ts +++ b/packages/web3-utils/test/fixtures/formatter.ts @@ -55,4 +55,5 @@ export const convertScalarValueValid: [[any, any, any], any][] = [ hexToBytes('0x00000000000000000000000000000000000000000000000000000000000000ff'), ), ], + [[255, 'bytes32', { bytes: 'invalidFormat' }], 255], // return original value when erroring ]; diff --git a/packages/web3-utils/test/fixtures/hash.ts b/packages/web3-utils/test/fixtures/hash.ts index 6bfe9f63f33..1869dd10fec 100644 --- a/packages/web3-utils/test/fixtures/hash.ts +++ b/packages/web3-utils/test/fixtures/hash.ts @@ -256,6 +256,7 @@ export const encodePackData: [TypedObject[] | TypedObjectAbbreviated[], any][] = '0x12480000000000000000000000000000000000000000000000000000000000003c69a194aaf415ba5d6afca734660d0a3d45acdc05d54cd1ca89a8988e7625b4', ], [[{ type: 'bytes4[]', value: ['0x11223344', '0x22334455'] }], '0x1122334422334455'], + [[{ type: '', value: '31323334' }], '0x'], ]; export const encodePackedInvalidData: [any, string][] = [ @@ -285,9 +286,13 @@ export const encodePackedInvalidData: [any, string][] = [ { type: 'bytes32', value: '0x1' }, 'Invalid value given "0x1". Error: can not parse as byte data.', ], + [ + [[{ type: 'string', value: '31323334' }], [{ type: '', value: '31323334' }]], + 'Autodetection of array types is not supported.', + ], ]; -export const keccak256ValidData: [string | Uint8Array | bigint, string][] = [ +export const keccak256ValidData: [string | Uint8Array | bigint | number[], string][] = [ ['my data', '0x8e0c48154711500d6fa119cc31df4dec339091e8b426cf4109a769fe89baad31'], [ new Uint8Array(Buffer.from('my data')), @@ -298,6 +303,8 @@ export const keccak256ValidData: [string | Uint8Array | bigint, string][] = [ '0x2d19cd91fbcc44e6412f92c11da7907cdedb1ace04c47447b42a61f1cd63b85a', ], [BigInt(3), '0x2a80e1ef1d7842f27f2e6be0972bb708b9a135c38860dbe73c27c3486c34f4de'], + [[0x3], '0x69c322e3248a5dfc29d73c5b0553b0185a35cd5bb6386747517ef7e53b15e287'], + [new Uint8Array([0x3]), '0x69c322e3248a5dfc29d73c5b0553b0185a35cd5bb6386747517ef7e53b15e287'], ]; export const elementaryNameValidData: [any, string][] = [ @@ -349,3 +356,8 @@ export const soliditySha3BigIntValidData: [Sha3Input[], string][] = [ return keccak256(abi.encodePacked(int(90071992547409))) ;} */ ]; + +export const getStorageSlotNumForLongStringValidData: [string | number, string | undefined][] = [ + [0, '0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563'], + ['0', '0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563'], +]; diff --git a/packages/web3-utils/test/fixtures/json_rpc.ts b/packages/web3-utils/test/fixtures/json_rpc.ts index 516711abceb..d801fa91587 100644 --- a/packages/web3-utils/test/fixtures/json_rpc.ts +++ b/packages/web3-utils/test/fixtures/json_rpc.ts @@ -18,6 +18,7 @@ import { JsonRpcNotification, SubscriptionParams } from 'web3-types'; const responseWithResult = { jsonrpc: '2.0', id: 1, result: '' }; const responseWithError = { jsonrpc: '2.0', id: 1, error: { code: 1, message: 'string' } }; +const responseWithRpcError = { jsonrpc: '2.0', id: 1, error: { code: -32000, message: 'string' } }; const responseWithSubscription = { id: 1, jsonrpc: '2.0', result: '' }; const responseWithNotfication = { jsonrpc: '2.0', @@ -27,11 +28,13 @@ const responseWithNotfication = { export const isResponseWithResultValidTest: [any, boolean][] = [ [responseWithResult, true], [responseWithError, false], + [{ ...responseWithResult, id: '1' }, true], ]; export const isResponseWithErrorValidTest: [any, boolean][] = [ [responseWithResult, false], [responseWithError, true], + [{ ...responseWithError, id: '1' }, true], ]; export const isResponseWithNotificationValidTest: [JsonRpcNotification, boolean][] = [ @@ -63,4 +66,41 @@ export const toPayloadValidTest: [any, any][] = [ params: undefined, }, ], + [ + { method: 'add', jsonrpc: '1.0', id: 1 }, + { + method: 'add', + id: 1, + jsonrpc: '1.0', + params: undefined, + }, + ], +]; + +export const isResponseRpcErrorValidData: [any, boolean][] = [ + [responseWithRpcError, true], + [responseWithError, false], +]; + +export const isBatchRequestValidData: [any, boolean][] = [ + [ + [ + { + method: 'add', + id: 1, + jsonrpc: '1.0', + params: undefined, + }, + ], + true, + ], + [ + { + method: 'add', + id: 1, + jsonrpc: '1.0', + params: undefined, + }, + false, + ], ]; diff --git a/packages/web3-utils/test/fixtures/string_manipulation.ts b/packages/web3-utils/test/fixtures/string_manipulation.ts index be5b298c803..dde49247677 100644 --- a/packages/web3-utils/test/fixtures/string_manipulation.ts +++ b/packages/web3-utils/test/fixtures/string_manipulation.ts @@ -58,7 +58,7 @@ export const padRightData: [[Numbers, number, string], HexString][] = [ [['15.5', 8, '0'], '15.50000'], ]; -export const toTwosComplementData: [[Numbers, number], HexString][] = [ +export const toTwosComplementData: [[Numbers, number | undefined], HexString][] = [ [[13, 32], '0x0000000000000000000000000000000d'], [[256, 30], '0x000000000000000000000000000100'], [[0, 32], '0x00000000000000000000000000000000'], @@ -69,9 +69,10 @@ export const toTwosComplementData: [[Numbers, number], HexString][] = [ [['13', 32], '0x0000000000000000000000000000000d'], [['-13', 32], '0xfffffffffffffffffffffffffffffff3'], [[-16, 2], '0xf0'], + [['0x1', undefined], '0x0000000000000000000000000000000000000000000000000000000000000001'], ]; -export const fromTwosComplementData: [[Numbers, number], number | bigint][] = [ +export const fromTwosComplementData: [[Numbers, number | undefined], number | bigint][] = [ [['0x0000000000000000000000000000000d', 32], 13], [['0x000000000000000000000000000100', 30], 256], [['0x00000000000000000020000000000000', 32], BigInt('9007199254740992')], @@ -81,6 +82,7 @@ export const fromTwosComplementData: [[Numbers, number], number | bigint][] = [ [[1000, 64], 1000], [[-1000, 64], -1000], [[BigInt(9), 1], -7], + [['0x0000000000000000000000000000000000000000000000000000000000000001', undefined], 1], ]; export const toTwosComplementInvalidData: [[Numbers, number], string][] = [ diff --git a/packages/web3-utils/test/unit/chunk_response_parser.test.ts b/packages/web3-utils/test/unit/chunk_response_parser.test.ts index 22100a3e6a8..bb4c70e8f1b 100644 --- a/packages/web3-utils/test/unit/chunk_response_parser.test.ts +++ b/packages/web3-utils/test/unit/chunk_response_parser.test.ts @@ -71,4 +71,18 @@ describe('chunk_response_parser', () => { }), ); }); + + it('lastChunkTimeout return empty when auto reconnect true', async () => { + const p = new ChunkResponseParser(eventEmiter, true); + // @ts-expect-error set private property + p.chunkTimeout = 10; + const result = p.parseResponse( + '{"jsonrpc":"2.0","id":"96aa3f13-077c-4c82-a64a-64b8626f8192","result":"0x141414141', + ); + const onError = jest.fn(); + eventEmiter.on('error', onError); + // eslint-disable-next-line no-promise-executor-return + await new Promise(resolve => setTimeout(resolve, 1000)); + expect(result).toEqual([]); + }); }); diff --git a/packages/web3-utils/test/unit/converters.test.ts b/packages/web3-utils/test/unit/converters.test.ts index 940590f06e7..84073f4a4d7 100644 --- a/packages/web3-utils/test/unit/converters.test.ts +++ b/packages/web3-utils/test/unit/converters.test.ts @@ -15,6 +15,9 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ +import { InvalidBytesError } from 'web3-errors'; +import { validator, utils } from 'web3-validator'; + import { asciiToHex, bytesToHex, @@ -325,6 +328,16 @@ describe('converters', () => { it.each(toHexValidData)('%s', (input, output) => { expect(toHex(input, true)).toEqual(output[1]); }); + + it('an interesting case that needs investigation', () => { + // TODO: This case is to be investigated further + expect( + toHex( + '101611154195520776335741463917853444671577865378275924493376429267637792638729', + true, + ), + ).toBe('uint'); + }); }); describe('invalid cases', () => { @@ -341,6 +354,14 @@ describe('converters', () => { }); describe('fromWei', () => { + beforeEach(() => { + jest.spyOn(console, 'warn').mockImplementation(() => { + // do nothing + }); + }); + afterAll(() => { + jest.restoreAllMocks(); + }); describe('valid cases', () => { it.each(fromWeiValidData)('%s', (input, output) => { expect(fromWei(input[0], input[1])).toEqual(output); @@ -372,13 +393,14 @@ describe('converters', () => { // do nothing }); }); + afterAll(() => { + jest.restoreAllMocks(); + }); it.each(toWeiValidDataWarnings)('%s', (input, output) => { toWei(input[0], input[1]); - // expect(() => toWei(input[0], input[1])).toThrow(output); - expect(console.warn).toHaveBeenCalledWith(output) + expect(console.warn).toHaveBeenCalledWith(output); }); - - }) + }); }); describe('toChecksumAddress', () => { describe('valid cases', () => { @@ -391,6 +413,33 @@ describe('converters', () => { expect(() => toChecksumAddress(input)).toThrow(output); }); }); + it('should return an empty string if hash is nullish', () => { + const address = '0xc1912fee45d61c87cc5ea59dae31190fffff232d'; + + // mock utils.uint8ArrayToHexString to return an empty string + jest.mock('web3-validator'); + jest.spyOn(utils, 'uint8ArrayToHexString').mockReturnValue( + undefined as unknown as string, + ); + + const result = toChecksumAddress(address); + expect(result).toBe(''); + + jest.mock('web3-validator').restoreAllMocks(); + }); + + it('should return an empty string if hash is equal to "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"', () => { + const address = '0xc1912fee45d61c87cc5ea59dae31190fffff232d'; + + // mock utils.uint8ArrayToHexString to return '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470' + jest.mock('web3-validator'); + const hash = '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470'; + jest.spyOn(utils, 'uint8ArrayToHexString').mockReturnValue(hash); + const result = toChecksumAddress(address); + expect(result).toBe(''); + + jest.mock('web3-validator').restoreAllMocks(); + }); }); describe('bytesToUint8Array', () => { describe('bytesToUint8Array', () => { @@ -404,6 +453,18 @@ describe('converters', () => { it.each(bytesToUint8ArrayInvalidData)('%s', (input, output) => { expect(() => bytesToUint8Array(input)).toThrow(output); }); + + it('should throw InvalidBytesError for invalid input even if it passed the validator', () => { + const invalidData = 8; + // the package 'web3-validator' contains `validator`. + // Mock mock the `validator.validate(...)` to not throw an error, but return `false` instead. + jest.mock('web3-validator'); + + jest.spyOn(validator, 'validate').mockReturnValue(undefined); + + expect(() => bytesToUint8Array(invalidData as any)).toThrow(InvalidBytesError); + jest.mock('web3-validator').restoreAllMocks(); + }); }); }); }); diff --git a/packages/web3-utils/test/unit/formatter.test.ts b/packages/web3-utils/test/unit/formatter.test.ts index bed8b55de8e..aa1a14fb6c9 100644 --- a/packages/web3-utils/test/unit/formatter.test.ts +++ b/packages/web3-utils/test/unit/formatter.test.ts @@ -24,9 +24,10 @@ import { HexString, Numbers, } from 'web3-types'; +import { FormatterError } from 'web3-errors'; import { expectTypeOf, typecheck } from '@humeris/espresso-shot'; import { isDataFormatValid, convertScalarValueValid } from '../fixtures/formatter'; -import { format, isDataFormat, convertScalarValue } from '../../src/formatter'; +import { format, isDataFormat, convertScalarValue, convert } from '../../src/formatter'; import { hexToBytes } from '../../src/converters'; type TestTransactionInfoType = { @@ -738,7 +739,6 @@ describe('formatter', () => { ).toEqual(result); }); }); - describe('object values', () => { it('should format simple object', () => { const schema = { @@ -776,6 +776,13 @@ describe('formatter', () => { expect(result).toEqual(expected); }); + it('should throw FormatterError when jsonSchema is invalid', () => { + const invalidSchema1 = {}; + const data = { key: 'value' }; + + expect(() => format(invalidSchema1, data)).toThrow(FormatterError); + }); + it('should format nested objects', () => { const schema = { type: 'object', @@ -846,4 +853,16 @@ describe('formatter', () => { }); }); }); + + describe('convert', () => { + it('should return empty when no properties or items', () => { + const data = { key: 'value' }; + const schema = { + type: 'object', + }; + const f = { number: FMT_NUMBER.NUMBER, bytes: FMT_BYTES.HEX }; + const result = convert(data, schema, [], f, []); + expect(result).toEqual({}); + }); + }); }); diff --git a/packages/web3-utils/test/unit/hash.test.ts b/packages/web3-utils/test/unit/hash.test.ts index d381e3c4240..814dacd45f2 100644 --- a/packages/web3-utils/test/unit/hash.test.ts +++ b/packages/web3-utils/test/unit/hash.test.ts @@ -23,6 +23,7 @@ import { soliditySha3Raw, encodePacked, keccak256 as web3keccak256, + getStorageSlotNumForLongString, } from '../../src/hash'; import { sha3Data, @@ -37,6 +38,7 @@ import { encodePackedInvalidData, keccak256ValidData, soliditySha3BigIntValidData, + getStorageSlotNumForLongStringValidData, } from '../fixtures/hash'; describe('hash', () => { @@ -149,4 +151,10 @@ describe('hash', () => { }); }); }); + + describe('getStorageSlotNumForLongString', () => { + it.each(getStorageSlotNumForLongStringValidData)('%s', (input, output) => { + expect(getStorageSlotNumForLongString(input)).toEqual(output); + }); + }); }); diff --git a/packages/web3-utils/test/unit/index.test.ts b/packages/web3-utils/test/unit/index.test.ts new file mode 100644 index 00000000000..8682408801a --- /dev/null +++ b/packages/web3-utils/test/unit/index.test.ts @@ -0,0 +1,64 @@ +/* +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 * as web3Utils from '../../src'; + +import * as converters from '../../src/converters.js'; +import * as eventEmitter from '../../src/event_emitter.js'; +import * as validation from '../../src/validation.js'; +import * as formatter from '../../src/formatter.js'; +import * as hash from '../../src/hash.js'; +import * as random from '../../src/random.js'; +import * as stringManipulation from '../../src/string_manipulation.js'; +import * as objects from '../../src/objects.js'; +import * as promiseHelpers from '../../src/promise_helpers.js'; +import * as jsonRpc from '../../src/json_rpc.js'; +import * as web3DeferredPromise from '../../src/web3_deferred_promise.js'; +import * as ChunkResponseParser from '../../src/chunk_response_parser.js'; +import * as uuid from '../../src/uuid.js'; +import * as web3Eip1193Provider from '../../src/web3_eip1193_provider.js'; +import * as socketProvider from '../../src/socket_provider.js'; +import * as uint8array from '../../src/uint8array.js'; + +describe('web3-utils exports', () => { + it('should export all modules', () => { + const modules = [ + converters, + eventEmitter, + validation, + formatter, + hash, + random, + stringManipulation, + objects, + promiseHelpers, + jsonRpc, + web3DeferredPromise, + ChunkResponseParser, + uuid, + web3Eip1193Provider, + socketProvider, + uint8array, + ]; + + modules.forEach(module => { + Object.keys(module).forEach((property: string | any[]) => { + expect(web3Utils).toHaveProperty(property); + }); + }); + }); +}); diff --git a/packages/web3-utils/test/unit/json_rpc.test.ts b/packages/web3-utils/test/unit/json_rpc.test.ts index 89261009916..ea16cd646d1 100644 --- a/packages/web3-utils/test/unit/json_rpc.test.ts +++ b/packages/web3-utils/test/unit/json_rpc.test.ts @@ -16,22 +16,28 @@ along with web3.js. If not, see . */ import { + isResponseRpcError, isResponseWithResult, isResponseWithError, isResponseWithNotification, isSubscriptionResult, isValidResponse, isBatchResponse, + setRequestIdStart, + toBatchPayload, + isBatchRequest, toPayload, } from '../../src/json_rpc'; import { isResponseWithResultValidTest, isResponseWithErrorValidTest, + isResponseRpcErrorValidData, isResponseWithNotificationValidTest, isSubscriptionResultValidTest, toPayloadValidTest, isValidResponseValidTest, isBatchResponseValidTest, + isBatchRequestValidData, } from '../fixtures/json_rpc'; describe('json rpc tests', () => { @@ -51,6 +57,14 @@ describe('json rpc tests', () => { }); }); }); + describe('isResponseRpcError', () => { + describe('valid cases', () => { + it.each(isResponseRpcErrorValidData)('%s', (input, output) => { + const result = isResponseRpcError(input); + expect(result).toBe(output); + }); + }); + }); describe('isResponseWithNotification', () => { describe('valid cases', () => { it.each(isResponseWithNotificationValidTest)('should have notify', (input, output) => { @@ -77,18 +91,57 @@ describe('json rpc tests', () => { }); describe('isBatchResponseValid', () => { describe('valid cases', () => { - it.each(isBatchResponseValidTest)('isValidresponse valid test', (input, output) => { - const result = isBatchResponse(input); - expect(result).toBe(output); + it.each(isBatchResponseValidTest)( + 'isBatchResponseValid valid test', + (input, output) => { + const result = isBatchResponse(input); + expect(result).toBe(output); + }, + ); + }); + }); + describe('isBatchRequest', () => { + describe('valid cases', () => { + it.each(isBatchRequestValidData)('isBatchRqeuest valid data', (input, output) => { + expect(isBatchRequest(input)).toBe(output); }); }); }); describe('toPayloadValid', () => { describe('valid cases', () => { - it.each(toPayloadValidTest)('isValidresponse valid test', (input, output) => { - const result = toPayload(input); + beforeEach(() => { + setRequestIdStart(undefined); + }); + it.each(toPayloadValidTest)('toPayload valid test', async (input, output) => { + const result = await new Promise(resolve => { + resolve(toPayload(input)); + }); expect(result).toStrictEqual(output); }); + it('should give payload that has requestid set', async () => { + setRequestIdStart(1); + const result = await new Promise(resolve => { + resolve(toPayload({ method: 'delete' })); + }); + expect(result).toStrictEqual({ + method: 'delete', + id: 2, + params: undefined, + jsonrpc: '2.0', + }); + }); + }); + }); + describe('toBatchPayload', () => { + it('should batch payload', async () => { + setRequestIdStart(0); + const result = await new Promise(resolve => { + resolve(toBatchPayload([{ method: 'delete' }, { method: 'add' }])); + }); + expect(result).toStrictEqual([ + { method: 'delete', id: 1, params: undefined, jsonrpc: '2.0' }, + { method: 'add', id: 2, params: undefined, jsonrpc: '2.0' }, + ]); }); }); }); diff --git a/packages/web3-utils/test/unit/objects.test.ts b/packages/web3-utils/test/unit/objects.test.ts index 1201b3b7345..cca9d46cba9 100644 --- a/packages/web3-utils/test/unit/objects.test.ts +++ b/packages/web3-utils/test/unit/objects.test.ts @@ -79,5 +79,14 @@ describe('objects', () => { expect(result.a).toStrictEqual(new Uint8Array([1, 2])); }); + + it('should return the destination object if it is not iterable', () => { + const destination = 123; // Replace with your desired destination object + const sources: Record[] = []; // Replace with your desired sources array + + const result = mergeDeep(destination as unknown as Record, ...sources); + + expect(result).toBe(destination); + }); }); }); diff --git a/packages/web3-utils/test/unit/promise_helpers.test.ts b/packages/web3-utils/test/unit/promise_helpers.test.ts index 7492c51fc24..14ccc00488d 100644 --- a/packages/web3-utils/test/unit/promise_helpers.test.ts +++ b/packages/web3-utils/test/unit/promise_helpers.test.ts @@ -60,6 +60,14 @@ describe('promise helpers', () => { new Error('time out'), ); }); + it('throws if result is an instance of Error', async () => { + const dummyError = new Error('dummy error'); + const asyncHelper = async () => { + return dummyError; + }; + + await expect(waitWithTimeout(asyncHelper(), 1000)).rejects.toThrow(dummyError); + }); }); describe('rejectIfTimeout', () => { it('%s', async () => { diff --git a/packages/web3-utils/test/unit/socket_provider.test.ts b/packages/web3-utils/test/unit/socket_provider.test.ts index a09f1467ce0..c2c3756c755 100644 --- a/packages/web3-utils/test/unit/socket_provider.test.ts +++ b/packages/web3-utils/test/unit/socket_provider.test.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 { Web3APIPayload, EthExecutionAPI, JsonRpcResponse, Web3ProviderStatus } from 'web3-types'; +import { + Web3APIPayload, + EthExecutionAPI, + JsonRpcResponse, + Web3ProviderStatus, + JsonRpcIdentifier, +} from 'web3-types'; +import { MaxAttemptsReachedOnReconnectingError, InvalidClientError } from 'web3-errors'; import { EventEmitter } from '../../src/event_emitter'; // eslint-disable-next-line import/no-relative-packages import { sleep } from '../../../../fixtures/utils'; @@ -40,8 +47,27 @@ class TestProvider extends SocketProvider { // eslint-disable-next-line protected _sendToSocket(_payload: Web3APIPayload): void {} // eslint-disable-next-line - protected _parseResponses(_event: any): JsonRpcResponse[] { - return [] as JsonRpcResponse[]; + protected _parseResponses(_event: { data: string } | undefined): JsonRpcResponse[] { + if (!_event || !_event.data) { + return []; + } + const returnValues: JsonRpcResponse[] = []; + + // DE-CHUNKER + const dechunkedData = _event.data + .replace(/\}[\n\r]?\{/g, '}|--|{') // }{ + .replace(/\}\][\n\r]?\[\{/g, '}]|--|[{') // }][{ + .replace(/\}[\n\r]?\[\{/g, '}|--|[{') // }[{ + .replace(/\}\][\n\r]?\{/g, '}]|--|{') // }]{ + .split('|--|'); + + dechunkedData.forEach((chunkData: string) => { + const result = JSON.parse(chunkData) as unknown as JsonRpcResponse; + + if (result) returnValues.push(result); + }); + + return returnValues; } public message(_event: any): void { this._onMessage(_event); @@ -74,6 +100,32 @@ describe('SocketProvider', () => { expect(provider).toBeInstanceOf(SocketProvider); expect(provider.SocketConnection).toEqual(dummySocketConnection); }); + it('should call _clearQueues when chunkResponseParser emits an error', async () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + const clearQueuesSpy = jest.spyOn(provider as any, '_clearQueues'); + + try { + // @ts-expect-error access readonly method + provider['chunkResponseParser']['autoReconnect'] = false; + // @ts-expect-error access readonly method + provider['chunkResponseParser']['chunkTimeout'] = 0; + + provider['chunkResponseParser'].parseResponse('invalid-json'); + } catch (error) { + // nothing + } + + // wait 1 second for the timeout to trigger + await sleep(100); + + expect(clearQueuesSpy).toHaveBeenCalled(); + }); + it('should error when failing to _validateProviderPath', () => { + expect(() => { + // eslint-disable-next-line no-new + new TestProvider('', socketOption, { delay: 0 }); + }).toThrow(InvalidClientError); + }); }); describe('testing _reconnect() method', () => { it('should not be called when { autoReconnect: false }', () => { @@ -94,6 +146,111 @@ describe('SocketProvider', () => { // @ts-expect-error run protected method expect(provider._reconnect).not.toHaveBeenCalled(); }); + it('should call _reconnect when isReconnecting is true and an error happens', () => { + const provider = new TestProvider(socketPath, socketOption); + provider['_reconnect'] = jest.fn(); + provider['isReconnecting'] = true; + + provider['_onError']({}); + + expect(provider['_reconnect']).toHaveBeenCalled(); + }); + + it('should call _reconnect when isReconnecting is false and an error happens', () => { + const provider = new TestProvider(socketPath, socketOption); + provider['_reconnect'] = jest.fn(); + provider['isReconnecting'] = false; + + provider['_onError']({}); + expect(provider['_reconnect']).not.toHaveBeenCalled(); + }); + + it('should return if the provider is already isReconnecting', async () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + // just to run the test faster moke `connect` + jest.spyOn(provider, 'connect'); + + // @ts-expect-error access protected method + expect(provider._reconnectAttempts).toBe(0); + provider['_reconnect'](); + // @ts-expect-error access protected method + expect(provider._reconnectAttempts).toBe(1); + + // after the first call provider.isReconnecting will set to true and so the `_reconnectAttempts` will not be incremented + provider['_reconnect'](); + + // @ts-expect-error access protected method + expect(provider._reconnectAttempts).toBe(1); + }); + + it('should reconnect the socket when the number of reconnect attempts is less than the maximum attempts', async () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + // @ts-expect-error access protected method + const openSocketConnectionSpy = jest.spyOn(provider, '_openSocketConnection'); + // @ts-expect-error access protected method + const removeSocketListenersSpy = jest.spyOn(provider, '_removeSocketListeners'); + const connectSpy = jest.spyOn(provider, 'connect'); + + // Set the reconnect attempts to less than the maximum attempts + provider['_reconnectAttempts'] = 2; + + provider['_reconnect'](); + + // wait for the timeout to trigger + await sleep(100); + + expect(openSocketConnectionSpy).toHaveBeenCalled(); + expect(removeSocketListenersSpy).toHaveBeenCalled(); + expect(connectSpy).toHaveBeenCalled(); + }); + + it('should clear the queues and emit an error event when the number of reconnect attempts reaches the maximum attempts', async () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + const clearQueuesSpy = jest.spyOn(provider as any, '_clearQueues'); + // @ts-expect-error access protected method + const removeSocketListenersSpy = jest.spyOn(provider, '_removeSocketListeners'); + const errorEventSpy = jest.spyOn(provider['_eventEmitter'], 'emit'); + + // Set the reconnect attempts to the maximum attempts + provider['_reconnectAttempts'] = 5; + + provider['_reconnect'](); + + // wait for the timeout to trigger + await sleep(100); + + expect(clearQueuesSpy).toHaveBeenCalled(); + expect(removeSocketListenersSpy).toHaveBeenCalled(); + expect(errorEventSpy).toHaveBeenCalledWith( + 'error', + expect.any(MaxAttemptsReachedOnReconnectingError), + ); + }); + + it('should keep pending requests but clear the sent requests queue when reconnecting', async () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + + provider.setStatus('connected'); + // Add a sent request + provider.request({ id: 2, method: 'some_rpc_method' }).catch(() => { + // it will throw with "Connection not open" because no actual connection is used in the test. So ignore the error + }); + // @ts-expect-error run protected method + expect(provider._sentRequestsQueue.size).toBe(1); + + // @ts-expect-error access protected method + const rejectSpy = jest.spyOn(provider['_pendingRequestsQueue'], 'delete'); + const deleteSpy = jest.spyOn(provider['_sentRequestsQueue'], 'delete'); + + const pendingRequestsQueueSize = provider['_pendingRequestsQueue'].size; + const sentRequestsQueueSize = provider['_sentRequestsQueue'].size; + + provider['_reconnect'](); + + expect(provider['_pendingRequestsQueue'].size).toEqual(pendingRequestsQueueSize); + + expect(deleteSpy).toHaveBeenCalledTimes(sentRequestsQueueSize); + }); }); describe('testing connect() method', () => { @@ -298,6 +455,46 @@ describe('SocketProvider', () => { // @ts-expect-error run protected method expect(provider._sentRequestsQueue.get(payload.id).payload).toBe(payload); }); + + it('should add request to the `_sentRequestsQueue` when the status is `connected` for batch requests', () => { + const provider = new TestProvider(socketPath, socketOption); + const payload = [ + { id: 1, method: 'some_rpc_method', jsonrpc: '2.0' as JsonRpcIdentifier }, + { id: 2, method: 'some_rpc_method', jsonrpc: '2.0' as JsonRpcIdentifier }, + ]; + provider.setStatus('connected'); + const reqPromise = provider.request(payload as any); + expect(reqPromise).toBeInstanceOf(Promise); + + // the id of the first request in the batch is the one used to identify the batch request + // @ts-expect-error run protected method + expect(provider._sentRequestsQueue.get(payload[0].id).payload).toBe(payload); + }); + + it('should clear _sentRequestsQueue in case `_sendToSocket` had an error', async () => { + // Create a mock SocketProvider instance + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + + const deleteSpy = jest.spyOn(provider['_sentRequestsQueue'], 'delete'); + + provider.setStatus('connected'); + // Assert that the _sendToSocket method was called with the correct payload + // @ts-expect-error access protected method + provider._sendToSocket = () => { + throw new Error('any error'); + }; + // Call the request method + provider + .request({ id: 1, method: 'some_rpc_method' }) + .then(() => { + // nothing + }) + .catch(() => { + // nothing + }); + + expect(deleteSpy).toHaveBeenCalled(); + }); }); describe('testing _clearQueues() method', () => { @@ -339,4 +536,330 @@ describe('SocketProvider', () => { }); }); }); + + describe('safeDisconnect', () => { + it('should disconnect the socket when there are no pending or sent requests', async () => { + const provider = new TestProvider(socketPath, socketOption); + const disconnectSpy = jest.spyOn(provider, 'disconnect'); + await provider.safeDisconnect(); + expect(disconnectSpy).toHaveBeenCalled(); + }); + + it('should disconnect the socket after waiting for pending and sent requests to be empty', async () => { + const provider = new TestProvider(socketPath, socketOption); + const disconnectSpy = jest.spyOn(provider, 'disconnect'); + + // Add a pending request + provider.request({ id: 1, method: 'some_rpc_method' }).catch(() => { + // it will throw with "Connection not open" because no actual connection is used in the test. So ignore the error + }); + // Add a sent request + provider.request({ id: 2, method: 'some_rpc_method' }).catch(() => { + // it will throw with "Connection not open" because no actual connection is used in the test. So ignore the error + }); + expect(provider.getPendingRequestQueueSize()).toBe(2); + + provider.clearQueues(); + // Call safeDisconnect and wait for the queues to be empty + await provider.safeDisconnect(undefined, undefined, false, 100); + + expect(disconnectSpy).toHaveBeenCalled(); + expect(provider.getPendingRequestQueueSize()).toBe(0); + expect(provider.getSentRequestsQueueSize()).toBe(0); + }); + + it('should force disconnect the socket after waiting for 5 attempts', async () => { + const provider = new TestProvider(socketPath, socketOption); + const disconnectSpy = jest.spyOn(provider, 'disconnect'); + const clearQueuesSpy = jest.spyOn(provider as any, 'clearQueues'); + + // Add a pending request + provider.request({ id: 1, method: 'some_rpc_method' }).catch(() => { + // it will throw with "Connection not open" because no actual connection is used in the test. So ignore the error + }); + expect(provider.getPendingRequestQueueSize()).toBe(1); + + // Add a sent request + provider.request({ id: 2, method: 'some_rpc_method' }).catch(() => { + // it will throw with "Connection not open" because no actual connection is used in the test. So ignore the error + }); + // expect(provider.getSentRequestsQueueSize()).toBe(1); + + // Call safeDisconnect with forceDisconnect set to true and a small interval + await provider.safeDisconnect(undefined, undefined, true, 100); + + expect(disconnectSpy).toHaveBeenCalled(); + expect(clearQueuesSpy).toHaveBeenCalled(); + }); + }); + describe('removeAllListeners', () => { + it('should remove all listeners for the specified event type', () => { + const provider = new TestProvider(socketPath, socketOption); + const listener1 = jest.fn(); + const listener2 = jest.fn(); + const listener3 = jest.fn(); + provider.on('event', listener1); + provider.on('event', listener2); + provider.on('otherEvent', listener3); + + provider.removeAllListeners('event'); + + provider['_eventEmitter'].emit('event'); + provider['_eventEmitter'].emit('otherEvent'); + + expect(listener1).not.toHaveBeenCalled(); + expect(listener2).not.toHaveBeenCalled(); + expect(listener3).toHaveBeenCalled(); + }); + }); + + describe('_sendPendingRequests', () => { + it('should send pending requests to the socket', () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + + const payload1 = { id: 1, method: 'method1', params: [] }; + const payload2 = { id: 2, method: 'method2', params: [] }; + // Add a pending request + provider.request(payload1).catch(() => { + // it will throw with "Connection not open" because no actual connection is used in the test. So ignore the error + }); + // Add a sent request + provider.request(payload2).catch(() => { + // it will throw with "Connection not open" because no actual connection is used in the test. So ignore the error + }); + expect(provider.getPendingRequestQueueSize()).toBe(2); + + provider['_sendToSocket'] = jest.fn(); + + provider['_sendPendingRequests'](); + + expect(provider['_sendToSocket']).toHaveBeenCalledTimes(2); + expect(provider['_sendToSocket']).toHaveBeenCalledWith(payload1); + expect(provider['_sendToSocket']).toHaveBeenCalledWith(payload2); + expect(provider['_pendingRequestsQueue'].size).toBe(0); + expect(provider['_sentRequestsQueue'].size).toBe(2); + }); + + it('should not send any requests if the pending requests queue is empty', () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + provider['_sendToSocket'] = jest.fn(); + + provider['_sendPendingRequests'](); + + expect(provider['_sendToSocket']).not.toHaveBeenCalled(); + expect(provider['_pendingRequestsQueue'].size).toBe(0); + expect(provider['_sentRequestsQueue'].size).toBe(0); + }); + }); + + describe('_onConnect', () => { + beforeEach(() => { + jest.spyOn(console, 'error').mockImplementation(() => { + // do nothing + }); // Spy on console.error to suppress and check calls + }); + + afterEach(() => { + jest.restoreAllMocks(); // Restore all mocks after each test + }); + + it('should set the connection status to "connected"', () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + + // Act + provider['_onConnect'](); + + expect(provider['_connectionStatus']).toBe('connected'); + }); + it('should set _accounts and _chainId when _getAccounts and _getChainId resolve', async () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + jest.spyOn(provider as any, '_getAccounts').mockResolvedValueOnce([123]); + jest.spyOn(provider as any, '_getChainId').mockResolvedValueOnce('1'); + + await new Promise(resolve => { + provider['_onConnect'](); + resolve(''); + }); + expect((provider as any)._chainId).toBe('1'); + expect((provider as any)._accounts).toEqual([123]); + }); + it('chainID should change when connecting twice', async () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + + await new Promise(resolve => { + jest.spyOn(provider as any, '_getAccounts').mockResolvedValueOnce([123]); + jest.spyOn(provider as any, '_getChainId').mockResolvedValueOnce('1'); + provider['_onConnect'](); + resolve(''); + }); + expect((provider as any)._chainId).toBe('1'); + expect((provider as any)._accounts).toEqual([123]); + + await new Promise(resolve => { + jest.spyOn(provider as any, '_getAccounts').mockResolvedValueOnce([123]); + jest.spyOn(provider as any, '_getChainId').mockResolvedValueOnce('2'); + provider['_onConnect'](); + resolve(''); + }); + expect((provider as any)._chainId).toBe('2'); + expect((provider as any)._accounts).toEqual([123]); + }); + it('should catch errors when _getAccounts and _getChainId throws', async () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + jest.spyOn(provider as any, '_getChainId').mockRejectedValueOnce(new Error('')); + jest.spyOn(provider as any, '_getAccounts').mockRejectedValueOnce(new Error('')); + jest.spyOn(provider, 'request').mockReturnValue(new Error() as unknown as Promise); + + await new Promise(resolve => { + provider['_onConnect'](); + resolve(''); + }); + expect((provider as any)._chainId).toBe(''); + expect((provider as any)._accounts).toEqual([]); + }); + it('should catch when connect emit fails', async () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + jest.spyOn(provider as any, '_getChainId').mockResolvedValueOnce(1); + jest.spyOn(provider as any, '_getAccounts').mockResolvedValueOnce([]); + (provider as any)._eventEmitter.emit = jest.fn(() => { + throw new Error('event emitter failed'); + }); + + await new Promise(resolve => { + provider['_onConnect'](); + resolve(''); + }); + // I would check if console.error is called, but facing a race condition + expect((provider as any)._eventEmitter.emit).toHaveBeenCalledTimes(1); + }); + }); + + describe('_getChainId', () => { + it('should return data from the chainId method', async () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + const chainId = 1; + jest.spyOn(provider as any, 'request').mockResolvedValueOnce({ result: chainId }); + const result = await provider['_getChainId'](); + expect(result).toBe(chainId); + }); + + it('should be returning undefined from the chainId method', async () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + jest.spyOn(provider as any, 'request').mockResolvedValueOnce({ result: undefined }); + const result = await provider['_getChainId'](); + expect(result).toBe(''); + }); + + it('should return empty from the chainId method', async () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + jest.spyOn(provider as any, 'request').mockResolvedValueOnce(undefined); + const result = await provider['_getChainId'](); + expect(result).toBe(''); + }); + }); + + describe('_getAccounts', () => { + it('should return data from the _getAccounts method', async () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + const accounts = [1]; + jest.spyOn(provider as any, 'request').mockResolvedValueOnce({ result: accounts }); + const result = await provider['_getAccounts'](); + expect(result).toBe(accounts); + }); + + it('should returning undefined from the _getAccounts method', async () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + jest.spyOn(provider as any, 'request').mockResolvedValueOnce({ result: undefined }); + const result = await provider['_getAccounts'](); + expect(result).toEqual([]); + }); + + it('should return empty from the _getAccounts method', async () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + jest.spyOn(provider as any, 'request').mockResolvedValueOnce(undefined); + const result = await provider['_getAccounts'](); + expect(result).toEqual([]); + }); + }); + + describe('_onMessage', () => { + it('should resolve the deferred promise for valid responses with errors', () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + + const payload1 = { + id: 1, + method: 'method1', + params: [], + jsonrpc: '2.0' as JsonRpcIdentifier, + error: { code: -32601, message: 'Method not found' }, + }; + const event = { + data: JSON.stringify(payload1), + }; + // Add a pending request + provider.request(payload1).catch(() => { + // it will throw with "Connection not open" because no actual connection is used in the test. So ignore the error + }); + expect(provider.getPendingRequestQueueSize()).toBe(1); + + // @ts-expect-error access protected method + provider['_sentRequestsQueue'] = provider['_pendingRequestsQueue']; + + const deferredPromiseResolveSpy = jest.spyOn( + provider['_sentRequestsQueue'].get(1)!.deferredPromise, + 'resolve', + ); + provider['_onMessage']({ + ...event, + }); + + expect(deferredPromiseResolveSpy).toHaveBeenCalledWith(payload1); + }); + + it('should not emit "message" event for invalid responses', () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + const event = { + data: JSON.stringify([ + { id: 1, jsonrpc: '2.0', error: { code: -32601, message: 'Method not found' } }, + { id: 2, jsonrpc: '2.0', error: { code: -32601, message: 'Method not found' } }, + ]), + }; + + const eventEmitterSpy = jest.spyOn(provider['_eventEmitter'], 'emit'); + + provider['_onMessage'](event); + + expect(eventEmitterSpy).not.toHaveBeenCalledWith('message', { + id: 1, + jsonrpc: '2.0', + error: { code: -32601, message: 'Method not found' }, + }); + expect(eventEmitterSpy).not.toHaveBeenCalledWith('message', { + id: 2, + jsonrpc: '2.0', + error: { code: -32601, message: 'Method not found' }, + }); + }); + + it('should emit "message" event for notifications', () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + const event = { + data: JSON.stringify({ + jsonrpc: '2.0', + method: 'notification_1_subscription', + params: {}, + }), + }; + + const eventEmitterSpy = jest.spyOn(provider['_eventEmitter'], 'emit'); + + provider['_onMessage'](event); + + expect(eventEmitterSpy).toHaveBeenCalledWith('message', { + jsonrpc: '2.0', + method: 'notification_1_subscription', + params: {}, + }); + }); + }); }); diff --git a/packages/web3-utils/test/unit/web3_deferred_promise.test.ts b/packages/web3-utils/test/unit/web3_deferred_promise.test.ts index b8180705969..6fe87129e73 100644 --- a/packages/web3-utils/test/unit/web3_deferred_promise.test.ts +++ b/packages/web3-utils/test/unit/web3_deferred_promise.test.ts @@ -53,4 +53,17 @@ describe('Web3DeferredPromise', () => { expect(promise.state).toBe('rejected'); }); }); + + describe('Web3DeferredPromise finally', () => { + it('should execute the callback when the promise is settled', async () => { + const promise = new Web3DeferredPromise(); + let callbackExecuted = false; + promise.resolve(1); + await promise.finally(() => { + callbackExecuted = true; + }); + + expect(callbackExecuted).toBe(true); + }); + }); }); From a7d67c6a08c06fd474ebe9eb5e0a9c516dffb50c Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Tue, 4 Jun 2024 08:30:30 -0700 Subject: [PATCH 090/186] Formatting fixes for recently updated pages (#7072) --- .../guides/getting_started/introduction.md | 4 +- .../docs/guides/getting_started/quickstart.md | 75 +++++++++--------- .../docs/guides/web3_providers_guide/index.md | 77 +++++++++---------- 3 files changed, 79 insertions(+), 77 deletions(-) diff --git a/docs/docs/guides/getting_started/introduction.md b/docs/docs/guides/getting_started/introduction.md index 0e92051b4ce..c32338d324d 100644 --- a/docs/docs/guides/getting_started/introduction.md +++ b/docs/docs/guides/getting_started/introduction.md @@ -49,7 +49,7 @@ Web3.js is a modular collection of packages, each of which serves a specific nee - [**Iban:**](/libdocs/Iban) The `web3-eth-iban` package allows you to switch between **Ethereum addresses and special banking-like addresses** (IBAN or BBAN) and simplifies conversion between the types. -### Additional supporting packages +### Additional Supporting Packages - [**Web3 Core:**](/api/web3-core) subscriptions, request management, and configuration used by other Web3 packages @@ -61,7 +61,7 @@ Web3.js is a modular collection of packages, each of which serves a specific nee - [**Web3 RPC Methods:**](/api/web3/namespace/rpcMethods) functions for making RPC requests to Ethereum using a given provider -## Advantages over other libraries +## Advantages Over Other Libraries - **Extensive Documentation and Community**: Web3.js is one of the most established Ethereum libraries, which means it 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. diff --git a/docs/docs/guides/getting_started/quickstart.md b/docs/docs/guides/getting_started/quickstart.md index 886b2690e19..80551ad735b 100644 --- a/docs/docs/guides/getting_started/quickstart.md +++ b/docs/docs/guides/getting_started/quickstart.md @@ -7,7 +7,7 @@ sidebar_label: Quickstart Use the live code editor to try Web3.js in your browser now! Keep reading to learn how to use Web3.js in a local development environment. -## Live code editor +## Live Code Editor @@ -41,7 +41,7 @@ For ESM-style imports, use: import { Web3 } from 'web3'; ``` -## Initialize `Web3` with a provider +## Initialize `Web3` with a Provider [Providers](/guides/web3_providers_guide/) are services that are responsible for enabling connectivity with the Ethereum network. The `Web3` object must be initialized with a valid provider to function as intended. Web3.js supports [HTTP](/guides/web3_providers_guide/#http-provider), [WebSocket](/guides/web3_providers_guide/#websocket-provider), and [IPC](/guides/web3_providers_guide/#ipc-provider) providers, and exposes packages for working with each type of provider. @@ -50,16 +50,16 @@ Web3.js is in compliance with [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193 ``` ts import { Web3 } from 'web3'; -//private RPC endpoint +// private RPC endpoint const web3 = new Web3('https://mainnet.infura.io/v3/YOUR_INFURA_ID'); -//or public RPC endpoint -//const web3 = new Web3('https://eth.llamarpc.com'); +// or public RPC endpoint +// const web3 = new Web3('https://eth.llamarpc.com'); web3.eth.getBlockNumber().then(console.log); // ↳ 18849658n ``` -## Querying the blockchain +## Querying the Blockchain After instantiating the `Web3` instance with a provider, the [`web3-eth`](/libdocs/Web3Eth) package can be used to fetch data from the Ethereum network: @@ -85,18 +85,18 @@ await web3.eth.getGasPrice(); // ↳ 23879160756n ``` -## Setting up a wallet +## Setting Up a Wallet To send transactions to the Ethereum network (e.g. [transferring ETH](/guides/getting_started/quickstart#transfer-eth) or [interacting with smart contracts](/guides/getting_started/quickstart#interact-with-smart-contracts)), it's necessary to use an [account](https://ethereum.org/en/developers/docs/accounts/) with funds to cover [gas fees](https://ethereum.org/en/developers/docs/gas/). The [`Wallet`](/api/web3-eth-accounts/class/Wallet) object is designed to manage a set of accounts that can be used to send transactions with [`web3.eth.sendTransaction`](/api/web3/class/Web3Eth#sendTransaction) or [`web3.eth.contract.methods.contractfunction().send()`](/api/web3-eth-contract/class/Contract). -### Create a random account +### Create a Random Account Using the `Wallet` to create a random account is a good way to accelerate the development process, but it's not suitable for mainnet or production uses, since random accounts will not have funds to cover gas fees. Use the [`Wallet.create`](/api/web3-eth-accounts/class/Wallet#create) method to create a random account. ```ts -//create random wallet with 1 account +// create random wallet with 1 account web3.eth.accounts.wallet.create(1) /* ↳ Wallet(1) @@ -119,7 +119,7 @@ Wallet(1) */ ``` -### Add an account from a private key +### Add an Account from a Private Key Use the [`Wallet.add`](/api/web3-eth-accounts/class/Wallet#add) method to use a private key to add an existing account to a wallet. @@ -128,7 +128,7 @@ Private keys are sensitive data and should be treated as such. Make sure that pr ::: ```ts -//the private key must start with the '0x' prefix +// the private key must start with the "0x" prefix const account = web3.eth.accounts.wallet.add('0x50d349f5cf627d44858d6fcb6fbf15d27457d35c58ba2d5cfeaf455f25db5bec'); console.log(account[0].address); @@ -143,39 +143,39 @@ console.log(account[0].privateKey); This is an example of using a private key to add an account to a wallet, and then using that account to transfer ETH: ```ts -//add an account to a wallet +// add an account to a wallet const account = web3.eth.accounts.wallet.add('0x50d349f5cf627d44858d6fcb6fbf15d27457d35c58ba2d5cfeaf455f25db5bec'); -//create transaction object to send 1 eth to '0xa32...c94' address from the account[0] +// create transaction object to send 1 eth to '0xa32...c94' address from the account[0] const tx = { from: account[0].address, to: '0xa3286628134bad128faeef82f44e99aa64085c94', value: web3.utils.toWei('1', 'ether') }; -//the `from` address must match the one previously added with wallet.add +// the "from" address must match the one previously added with wallet.add -//send the transaction +// send the transaction const txReceipt = await web3.eth.sendTransaction(tx); console.log('Tx hash:', txReceipt.transactionHash) // ↳ Tx hash: 0x03c844b069646e08af1b6f31519a36e3e08452b198ef9f6ce0f0ccafd5e3ae0e ``` -## Interact with smart contracts +## Interact with Smart Contracts [Smart contracts](https://ethereum.org/en/developers/docs/smart-contracts/) are programs that run on the Ethereum network. Keep reading to learn how to use Web3.js to interact with smart contracts. -### Instantiate a contract +### Instantiate a Smart Contract The first step to interacting with a smart contract is to instantiate it, which requires the [ABI](https://docs.soliditylang.org/en/develop/abi-spec.html) and address of the smart contract. The following examples demonstrates instantiating the [Uniswap](https://uniswap.org/) token smart contract: ```ts -//Uniswap token smart contract address (mainnet) +// Uniswap token smart contract address (Mainnet) const address = '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984' -//you can find the complete ABI in etherscan.io -//https://etherscan.io/address/0x1f9840a85d5af5bf1d1762f925bdaddc4201f984#code +// you can find the complete ABI on etherscan.io +// https://etherscan.io/address/0x1f9840a85d5af5bf1d1762f925bdaddc4201f984#code const ABI = [ { @@ -190,60 +190,63 @@ const ABI = }, ]; -//instantiate the smart contract +// instantiate the smart contract const uniswapToken = new web3.eth.Contract(abi, address); ``` -### Read methods +### Read Methods Since reading data from a smart contract does not consume any gas, it's not necessary to use an account to do so. Here are some examples of reading data from the Uniswap token smart contract: ```ts -//make the call to the contract +// make the call to the contract const symbol = await uniswapToken.methods.symbol().call(); console.log('Uniswap symbol:',symbol); // ↳ Uniswap symbol: UNI -//make the call to the contract +// make the call to the contract const totalSupply = await uniswapToken.methods.totalSupply().call(); console.log('Uniswap Total supply:', totalSupply); // ↳ Uniswap Total Supply: 1000000000000000000000000000n ``` -### Write methods +### Write Methods Writing data to a smart contract consumes gas and requires the use of an account with funds. The following example demonstrates such an interaction: ```ts -//address to send the token +// address to send the token const to = '0xcf185f2F3Fe19D82bFdcee59E3330FD7ba5f27ce'; -//value to transfer (1 with 18 decimals) +// value to transfer (1 with 18 decimals) const value = web3.utils.toWei('1','ether'); -//send the transaction => return the Tx receipt +// send the transaction => return the Tx receipt const txReceipt = await uniswapToken.methods.transfer(to,value).send({from: account[0].address}); console.log('Tx hash:',txReceipt.transactionHash); // ↳ Tx hash: 0x14273c2b5781cc8f1687906c68bfc93482c603026d01b4fd37a04adb6217ad43 ``` -### Query past events +### Query Past Events Smart contracts emit [events](https://ethereum.org/en/developers/docs/smart-contracts/anatomy/#events-and-logs) to communicate important interactions. This example demonstrates how to query the Uniswap token smart contract for all `Transfer` events that occurred after a certain block number: ```ts -//get past `Transfer` events from block 18850576 +// get past `Transfer` events from block 18850576 const eventTransfer = await uniswapToken.getPastEvents('Transfer', { fromBlock: 18850576 }); console.log(eventTransfer); // ↳ [{...},{...}, ...] array with all the events emitted -//you can only query logs from the previous 100_000 blocks ``` -### Subscribing to events +:::note +You can only query logs from the most recent 100,000 blocks. +::: + +### Subscribing to Events Web3.js allows user to subscribe to events for real-time notification of important contract interactions. Here is an example of creating a subscription to the Uniswap token's `Transfer` event: @@ -254,16 +257,16 @@ HTTP providers do not support real-time event subscriptions. Use one of the othe ```ts import { Web3 } from 'web3'; -//WebSocket provider +// WebSocket provider const web3 = new Web3('wss://ethereum.publicnode.com'); -//instantiate contract +// instantiate contract const uniswapToken = new web3.eth.Contract(abi, address) -//create the subcription to all the 'Transfer' events +// create the subscription to all the 'Transfer' events const subscription = uniswapToken.events.Transfer(); -//listen to the events +// listen to the events subscription.on('data',console.log); // ↳ [{...},{...}, ...] live events will be printed in the console ``` diff --git a/docs/docs/guides/web3_providers_guide/index.md b/docs/docs/guides/web3_providers_guide/index.md index 1c1a0c334cb..726ccd8c229 100644 --- a/docs/docs/guides/web3_providers_guide/index.md +++ b/docs/docs/guides/web3_providers_guide/index.md @@ -3,7 +3,7 @@ sidebar_position: 1 sidebar_label: 'Mastering Providers' --- -# Web3js providers overview +# Web3.js Providers Overview Providers are services that are responsible for enabling Web3.js connectivity with the Ethereum network. Using a provider to connect your application to an Ethereum node is necessary for querying data, sending transactions, and interacting with smart contracts. This guide will explore the different types of Web3.js providers, how to set them up, and how to use them in an application. @@ -14,7 +14,7 @@ import { Web3 } from 'web3'; const web3 = new Web3(/* PROVIDER*/); -//calling any method that interact with the network would use the previous passed provider. +// calling any method that interacts with the network will use the supplied provider await web3.eth.getBlockNumber(); ``` @@ -40,8 +40,8 @@ HTTP is a request-response protocol and does not support persistent connection, ``` ts title='Initialize an HTTP Provider' import { Web3, HttpProvider } from 'web3'; -//supply an HTTP provider as a URL string -//highlight-next-line +// supply an HTTP provider as a URL string +// highlight-next-line const web3 = new Web3('https://mainnet.infura.io/v3/YOUR_INFURA_ID'); await web3.eth.getBlockNumber() @@ -49,8 +49,8 @@ await web3.eth.getBlockNumber() // OR -//supply an HTTP provider by constructing a new HttpProvider -//highlight-next-line +// supply an HTTP provider by constructing a new HttpProvider +// highlight-next-line const web3_2 = new Web3(new HttpProvider('https://mainnet.infura.io/v3/YOUR_INFURA_ID')); await web3.eth.getBlockNumber() @@ -87,15 +87,15 @@ const httpOptions = { const web3 = new Web3(new HttpProvider('https://eth.llamarpc.com', httpOptions)); ``` -### WebSocket provider +### WebSocket Provider WebSockets support a persistent connection between a client and a server, which means they are suitable for use cases that require real-time [event subscriptions](/guides/events_subscriptions/). ``` ts title='Initialize WS Provider' import { Web3, WebSocketProvider } from 'web3'; -//supply a WebSocket provider as a URL string -//highlight-next-line +// supply a WebSocket provider as a URL string +// highlight-next-line const web3 = new Web3('wss://mainnet.infura.io/ws/v3/YOUR_INFURA_ID'); await web3.eth.getBlockNumber(); @@ -103,8 +103,8 @@ await web3.eth.getBlockNumber(); // OR -//supply a WebSocket provider by constructing a new WebSocketProvider -//highlight-next-line +// supply a WebSocket provider by constructing a new WebSocketProvider +// highlight-next-line const web3_2 = new Web3(new WebSocketProvider('wss://mainnet.infura.io/ws/v3/YOUR_INFURA_ID')); await web3.eth.getBlockNumber(); @@ -116,12 +116,12 @@ await web3.eth.getBlockNumber(); The [`WebSocketProvider` constructor](/api/web3-providers-ws/class/WebSocketProvider#constructor) accepts two optional parameters that can be used to configure the behavior of the `WebSocketProvider`: the first parameter must be of type [`ClientRequestArgs`](https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules__types_node_http_d_._http_.clientrequestargs.html) or of [`ClientOptions`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/e5ee5eae6a592198e469ad9f412bab8d223fcbb6/types/ws/index.d.ts#L243) and the second parameter must be of type [`ReconnectOptions`](/api/web3/namespace/utils#ReconnectOptions). ```ts title='Configuring a WebSocket Provider' -//include both optional parameters +// include both optional parameters const provider = new WebSocketProvider( `ws://localhost:8545`, { headers: { - //for node services that require an API key in a header + // for node services that require an API key in a header 'x-api-key': '', }, }, @@ -132,7 +132,7 @@ const provider = new WebSocketProvider( } ); -//OR include only ReconnectOptions +// OR include only ReconnectOptions const provider = new WebSocketProvider( `ws://localhost:8545`, {}, @@ -150,10 +150,10 @@ IPC (inter-process communication) providers offer high-performance local communi ``` ts title='Initialize IPC Provider' import { Web3 } from 'web3'; -//highlight-next-line +// highlight-next-line import { IpcProvider } from 'web3-providers-ipc'; -//highlight-next-line +// highlight-next-line const web3 = new Web3(new IpcProvider('/users/myuser/.ethereum/geth.ipc')); await web3.eth.getBlockNumber(); @@ -167,7 +167,7 @@ The [`IpcProvider` constructor](/api/web3-providers-ipc/class/IpcProvider#constr ```ts title='Configuring an IPC Provider' -//include both optional parameters +// include both optional parameters const provider = new IpcProvider( '/Users/myuser/Library/Ethereum/geth.ipc', { @@ -180,7 +180,7 @@ const provider = new IpcProvider( } ); -//OR include only ReconnectOptions +// OR include only ReconnectOptions const provider = new IpcProvider( '/Users/myuser/Library/Ethereum/geth.ipc', {}, @@ -208,22 +208,23 @@ Local providers can usually be accessed via IPC, HTTP, or WebSocket. The followi import { Web3 } from 'web3'; import { IpcProvider } from 'web3-providers-ipc'; -//highlight-next-line -//IPC provider -const web3 = new Web3(new IpcProvider('/Users/myuser/Library/Ethereum/geth.ipc'));//mac os path -// on windows the path is: '\\\\.\\pipe\\geth.ipc' -// on linux the path is: '/users/myuser/.ethereum/geth.ipc' +// highlight-next-line +// IPC provider +const web3 = new Web3(new IpcProvider('/Users/myuser/Library/Ethereum/geth.ipc')); +// the path above is for macOS +// on Windows the path is: '\\\\.\\pipe\\geth.ipc' +// on Linux the path is: '/users/myuser/.ethereum/geth.ipc' -//highlight-next-line -//HTTP provider +// highlight-next-line +// HTTP provider web3.setProvider('http://localhost:8545'); -// or +// OR web3.setProvider(new Web3.providers.HttpProvider('http://localhost:8545')); -//highlight-next-line -//WebSocket provider +// highlight-next-line +// WebSocket provider web3.setProvider('ws://localhost:8546'); -// or +// OR web3.setProvider(new Web3.providers.WebsocketProvider('ws://localhost:8546')); ``` @@ -232,8 +233,6 @@ web3.setProvider(new Web3.providers.WebsocketProvider('ws://localhost:8546')); Services like [Alchemy](https://www.alchemy.com/), [Infura](https://www.infura.io/), and [QuickNode](https://www.quicknode.com/) offer Ethereum node services that can be accessed via HTTP or Websocket. ```ts title='Alchemy, Infura, etc' -// like Alchemy (https://www.alchemyapi.io/supernode) -// or infura (https://mainnet.infura.io/v3/your_infura_key) import { Web3 } from 'web3'; const web3 = new Web3('https://eth-mainnet.alchemyapi.io/v2/your-api-key'); ``` @@ -250,24 +249,24 @@ The following example should be run in a browser with the MetaMask extension ins - - - -``` - -7. Create a new file called `server.js` (inside `web3-browser-injected-providers`). -8. Copy and paste the following code into `server.js`, and save it after: - -```js -const express = require('express'); -const app = express(); -const path = require('path'); - -app.use(express.static(path.join(__dirname, '.'))); - -app.listen(8097, () => { - console.log('Server started on port 8097'); -}); -``` - -9. Start the Node.js server by executing the following command. This will execute the content of `server.js` which will run the server on port 8097: - -```bash -node server.js -``` - -10. Open your web browser and navigate to `http://localhost:8097/`. MetaMask should ask for your approval to connect to your website. Follow the steps and give your consent. -11. If everything is set up properly, you should be able to connect to the Ethereum network with MetaMask and see the logged account address. - -Note that in the above steps you had created a local web server using Node.js and Express, serving your HTML file from the root directory of your project. You needs this local server because many browser does not allow extensions to inject objects for static files located on your machine. However, you can customize the port number and the root directory if needed. - -Now you can start building your Ethereum application with web3.js and MetaMask! diff --git a/docs/docs/guides/web3_providers_guide/ipc.md b/docs/docs/guides/web3_providers_guide/ipc.md deleted file mode 100644 index 1b31eb44f2b..00000000000 --- a/docs/docs/guides/web3_providers_guide/ipc.md +++ /dev/null @@ -1,134 +0,0 @@ ---- -sidebar_position: 6 -sidebar_label: 'Tutorial: IPC Provider' ---- - -# Tutorial: IPC Provider - -The IPC Provider offers high-performance local communication, providing a swift alternative to the straightforward HTTP Provider. Tailored for efficiency, it excels in local environments, enhancing the speed of your web application's connection to the Ethereum network for decentralized applications. - -## Prerequisites - -Before we get started, make sure you have a basic understanding of JavaScript and Ethereum. Additionally, we need to set up our environment by installing the following: - -1. **Node.js** - - Node.js is a JavaScript runtime environment that enables you to run JavaScript on the server-side. You can download it from [https://nodejs.org/en/download/](https://nodejs.org/en/download/). - -2. **npm** - - npm (Node Package Manager) is used to publish and install packages to and from the public npm registry or a private npm registry. You can install it by following the instructions here: [https://docs.npmjs.com/downloading-and-installing-node-js-and-npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm). - - Alternatively, you can use **yarn** instead of **npm** by following the instructions here: [https://classic.yarnpkg.com/lang/en/docs/getting-started/](https://classic.yarnpkg.com/lang/en/docs/getting-started/). - -3. **Geth** (Optional, used only at the IPC provider example) - - Geth (go-ethereum) is an Ethereum execution client meaning it handles transactions, deployment and execution of smart contracts and contains an embedded computer known as the Ethereum Virtual Machine. You can install it by following the instructions here: [https://geth.ethereum.org/docs/getting-started/installing-geth](https://geth.ethereum.org/docs/getting-started/installing-geth) - -## IPC Provider (for Node.js) - -The IPC Provider allows you to connect to an Ethereum node using Inter-Process Communication (IPC) in a Node.js environment. This provider is useful when you have a local Ethereum node running on your machine and want to interact with it using Node.js. - -In the following steps you will run `geth` in development mode and you will run a piece of code that reads the Ethereum accounts and sends a transaction: - -To connect to the Ethereum network using the IPC provider, follow these steps: - -1. Start a `geth` node in development mode by opening a terminal window and navigating to the `geth` executable file. Then, run the following command to create a development chain: - -```bash -geth --dev --ipcpath -``` - -Make sure to replace `` with the desired IPC path. For example: - -```bash -geth --dev --ipcpath /Users/username/Library/Ethereum/geth.ipc -``` - -This will start a `geth` node in development mode with IPC enabled and an IPC path specified. If the command is successful, the `geth` node will be running, and you should see output similar to the following: - -```bash -INFO [12-10|15:10:37.121] IPC endpoint opened url= -INFO [12-10|15:10:37.122] HTTP endpoint opened url=http://localhost:8545 -INFO [12-10|15:10:37.122] WebSocket endpoint opened url=ws://localhost:8546 -INFO [12-10|15:10:37.127] Mapped network port proto=udp extport=0 intport=30303 interface=UPnP(UDP) -``` - -2. Open a command prompt or terminal window and navigate to where you would like to create the folder for this example. -3. Create a new folder and navigate to it: - -```bash -mkdir web3-providers-tutorial -cd web3-providers-tutorial -``` - -4. Install web3.js using npm: - -```bash -npm i web3 -``` - -5. Create a new JavaScript file called `web3-ipc-provider.js` in your code editor. - -6. Copy and paste the following code into your `web3-ipc-provider.js` file and save it: - -```typescript title='IPC Provider' -import { Web3 } from 'web3'; -import { IpcProvider } from 'web3-providers-ipc'; - -// Connect to the Ethereum network using IPC provider -const ipcPath = ''; // Replace with your actual IPC path -const ipcProvider = new IpcProvider(ipcPath); - -const web3 = new Web3(ipcProvider); - -async function main() { - try { - console.log('Does the provider support subscriptions?:', ipcProvider.supportsSubscriptions()); - - // Get the list of accounts in the connected node which is in this case: geth in dev mode. - const accounts = await web3.eth.getAccounts(); - console.log('Accounts:', accounts); - - // Send a transaction to the network - const transactionReceipt = await web3.eth.sendTransaction({ - from: accounts[0], - to: accounts[0], // sending a self-transaction - value: web3.utils.toWei('0.001', 'ether'), - }); - console.log('Transaction Receipt:', transactionReceipt); - } catch (error) { - console.error('An error occurred:', error); - } -} - -main(); -``` - -7. replace `` with the `ipcPath` that you had specified, when starting the `geth` node, in the first step. - -8. Type `node web3-ipc-provider.js` in the command prompt or terminal window and press Enter. This will run your JavaScript file. - -If everything is set up properly, you should see the list of accounts and transaction receipt printed in the console, similar to the following: - -```bash -Do the provider supports subscription?: true -Accounts: [ '0x82333ED0FAA7a883297C4d8e0FDE1E1CFABAeB7D' ] -Transaction Receipt: { - blockHash: '0xd1220a9b6f86083e420da025179593f5aad3732165a687019a89528a4ab2bcd8', - blockNumber: 1n, - cumulativeGasUsed: 21000n, - effectiveGasPrice: 1000000001n, - from: '0x82333ed0faa7a883297c4d8e0fde1e1cfabaeb7d', - gasUsed: 21000n, - logs: [], - logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - status: 1n, - to: '0x82333ed0faa7a883297c4d8e0fde1e1cfabaeb7d', - transactionHash: '0x76c05df78dc5dbfade0d11322b3cadc894c17efe36851856aca29488b47c3fbd', - transactionIndex: 0n, - type: 0n -} -``` - -Keep in mind that using IPC Provider with `geth` in development mode in a production environment is not recommended as it can pose a security risk. diff --git a/docs/docs/guides/web3_providers_guide/truffle.md b/docs/docs/guides/web3_providers_guide/truffle.md deleted file mode 100644 index ba98c3a3335..00000000000 --- a/docs/docs/guides/web3_providers_guide/truffle.md +++ /dev/null @@ -1,84 +0,0 @@ ---- -sidebar_position: 8 -sidebar_label: 'Tutorial: Third Party Provider' ---- - -# Truffle - -The Truffle HDWallet Provider will be used as an example of a third party provider that is EIP 1193 compatible. - -## Prerequisites - -Before we get started, make sure you have a basic understanding of JavaScript and Ethereum. Additionally, we need to set up our environment by installing the following: - -1. **Ganache** - - Ganache is a personal blockchain for Ethereum development that allows you to test how your smart contracts function in real-world scenarios. You can download it from [http://truffleframework.com/ganache](http://truffleframework.com/ganache). - -2. **Node.js** - - Node.js is a JavaScript runtime environment that enables you to run JavaScript on the server-side. You can download it from [https://nodejs.org/en/download/](https://nodejs.org/en/download/). - -3. **npm** - - npm (Node Package Manager) is used to publish and install packages to and from the public npm registry or a private npm registry. You can install it by following the instructions here: [https://docs.npmjs.com/downloading-and-installing-node-js-and-npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm). - - Alternatively, you can use **yarn** instead of **npm** by following the instructions here: [https://classic.yarnpkg.com/lang/en/docs/getting-started/](https://classic.yarnpkg.com/lang/en/docs/getting-started/). - -## Third-party Providers (Compliant with EIP 1193) - -web3.js accepts any provider that is in compliance with [EIP-1193](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1193.md). It has tests written to ensure compatibility with @truffle/hdwallet-provider, Ganache provider, Hardhat provider, and Incubed (IN3) as a provider. The following section, [Browser Injected Ethereum Provider](#browser-injected-ethereum-provider), in this tutorial explains how to use a special case of these third-party providers. - -Here is a step-by-step example and a code snippet to connect your web application to the Ethereum network using `@truffle/hdwallet-provider` as an example of an external provider compliant with EIP 1193. - -1. Open a command prompt or terminal window in a new folder. -2. Type `npm init -y` and press Enter. This will create a `package.json` file in the current directory. -3. Install web3.js and HTTP provider using npm: - -```bash -npm i web3 @truffle/hdwallet-provider bip39 -``` - -4. Create a new JavaScript file, called `index.js`, in your code editor. -5. Copy and paste the following code into your JavaScript file, and then save the file: - -```typescript title='EIP1193 Provider (Truffle)' -import { Web3 } from 'web3'; -import HDWalletProvider from '@truffle/hdwallet-provider'; -import bip39 from 'bip39'; - -const mnemonic: string = bip39.generateMnemonic(); // generates seed phrase -console.log('seed phrase:', mnemonic); - -// Connect to the Ethereum network using an HTTP provider and WalletProvider -const provider: HDWalletProvider = new HDWalletProvider(mnemonic, 'https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID'); -const web3: Web3 = new Web3(provider); - -// Get the current block number from the network -web3.eth - .getBlockNumber() - .then(function (blockNumber: number) { - console.log('Current block number:', blockNumber); - }) - .catch(function (error: any) { - console.log('Error:', error); - }); -``` - -6. Replace `'YOUR_INFURA_PROJECT_ID'` with your own Infura project ID. You can obtain an Infura project ID by signing up for a free account at https://infura.io/register. Alternatively, you can use any other URL that is compatible with HDWalletProvider, such as a local Ganache accessible at `'http://localhost:7545'`. - -7. In the command prompt, run `node index.js` and press Enter. This will execute your JavaScript file and connect to the Ethereum network using HDWalletProvider with Infura. - -If everything is set up properly, you should see the current block number printed in the console similar to the following. - -```bash -seed phrase: remain climb clock valid budget cable tunnel force split level measure repair -Current block number: 17317844n -``` - -:::danger -Your seed phrase gives complete access to your Ethereum account and it should **never** be shared with anyone you don't want to give full access to your account. The seed phrase is `console.log`ed in the code example to show you what it looks like, but you should **never** do this with a seed phrase to an account you plan on using to send real money. -::: - -The sample above connected you to the Ethereum network using truffle HD Wallet-enabled Web3 provider. You can modify it to interact with the network, perform transactions, and read/write data from the Ethereum network. - diff --git a/docs/docs/guides/web3_providers_guide/websocket.md b/docs/docs/guides/web3_providers_guide/websocket.md deleted file mode 100644 index 96288f4e031..00000000000 --- a/docs/docs/guides/web3_providers_guide/websocket.md +++ /dev/null @@ -1,142 +0,0 @@ ---- -sidebar_position: 5 -sidebar_label: 'Tutorial: WebSocket Provider' ---- - -# Tutorial: WebSocket Provider - -The WebSocket Provider provides real-time communication and enhanced performance, offering a dynamic alternative to the simplicity of the HTTP Provider. In comparison to the widely used HTTP Provider, the WebSocket Provider enables your web application to establish a continuous, bidirectional connection, allowing for live updates and faster interactions with the Ethereum network. Incorporate the WebSocket Provider to empower your decentralized applications with real-time capabilities. - -## Prerequisites - -Before we get started, make sure you have a basic understanding of JavaScript and Ethereum. Additionally, we need to set up our environment by installing the following: - -1. **Ganache** - - Ganache is a personal blockchain for Ethereum development that allows you to test how your smart contracts function in real-world scenarios. You can download it from [http://truffleframework.com/ganache](http://truffleframework.com/ganache). - -2. **Node.js** - - Node.js is a JavaScript runtime environment that enables you to run JavaScript on the server-side. You can download it from [https://nodejs.org/en/download/](https://nodejs.org/en/download/). - -3. **npm** - - npm (Node Package Manager) is used to publish and install packages to and from the public npm registry or a private npm registry. You can install it by following the instructions here: [https://docs.npmjs.com/downloading-and-installing-node-js-and-npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm). - - Alternatively, you can use **yarn** instead of **npm** by following the instructions here: [https://classic.yarnpkg.com/lang/en/docs/getting-started/](https://classic.yarnpkg.com/lang/en/docs/getting-started/). - -## WebSocket Provider - -WebSocket Provider allows us to communicate with the Ethereum node via WebSocket protocol, which is useful when we want continuous updates on our subscribed items. This provider is ideal for real-time applications that require constant updates from the Ethereum network. - -Follow these steps to connect to the Ethereum network using WebSocket provider: - -:::tip -The first 3 steps are the same as in the previous section. So, you may skip them if you already executed the previous section. -::: - -1. Open a command prompt or terminal window and navigate to where you would like to create the folder for this example. -2. Create a new folder and navigate to it: - -```bash -mkdir web3-providers-tutorial -cd web3-providers-tutorial -``` - -3. Install web3.js using npm: - -```bash -npm i web3 -``` - -4. Create a new JavaScript file called `web3-websocket-provider.js` in your code editor. - -5. Copy and paste the following code into your `web3-websocket-provider.js` file and save it: - -```typescript title='WebSocket Provider' -import { Web3 } from 'web3'; - -// Connect to the Ethereum network using WebSocket provider -const ganacheUrl = 'ws://localhost:8545'; -const wsProvider = new Web3.providers.WebsocketProvider(ganacheUrl); -const web3 = new Web3(wsProvider); - -async function main() { - try { - console.log('Does the provider support subscriptions?:', wsProvider.supportsSubscriptions()); - - // Subscribe to new block headers - const subscription = await web3.eth.subscribe('newBlockHeaders'); - - subscription.on('data', async (blockhead) => { - console.log('New block header: ', blockhead); - - // You do not need the next line if you like to keep being notified for every new block - await subscription.unsubscribe(); - console.log('Unsubscribed from new block headers.'); - }); - subscription.on('error', (error) => console.log('Error when subscribing to New block header: ', error)); - - // Get the list of accounts in the connected node which is in this case: Ganache. - const accounts = await web3.eth.getAccounts(); - // Send a transaction to the network - const transactionReceipt = await web3.eth.sendTransaction({ - from: accounts[0], - to: accounts[1], - value: web3.utils.toWei('0.001', 'ether'), - }); - console.log('Transaction Receipt:', transactionReceipt); - } catch (error) { - console.error(error); - } -} - -main(); -``` - -6. Ensure that Ganache is running as mentioned in the [Prerequisites](#prerequisites) section. - -7. Type `node web3-websocket-provider.js` in the command prompt or terminal window and press Enter. This will run your JavaScript file. - -If everything is set up properly, you should see the new block headers, transaction hash, and pending transaction printed in the console. The unique feature of WebSocket provider highlighted in this example is that it can subscribe to new block headers and pending transactions to get them in real-time. And by running the sample, you will get something similar to this in your console: - -```bash -Do the provider supports subscription?: true -New block header: { - logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - miner: '0x0000000000000000000000000000000000000000', - difficulty: '0', - totalDifficulty: '0', - extraData: '0x', - gasLimit: 6721975, - gasUsed: 21000, - hash: '0xd315cecf3336640bcd1301930805370b7fe7528c894b931dcf8a3b1c833b68c8', - mixHash: '0x1304070fde1c7bee383f3a59da8bb94d515cbd033b2638046520fb6fb596d827', - nonce: '0x0000000000000000', - number: 40, - parentHash: '0xeb7ce3260911db2596ac843df11dbcbef302e813e1922db413f6f0b2a54d584d', - receiptsRoot: '0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa', - stateRoot: '0x95e416eec0932e725ec253779a4e28b3d014d05e41e63c3369f5da42d26d1240', - timestamp: 1684165088, - transactionsRoot: '0x8f87380cc7acfb6d10633e10f72567136492cb8301f52a41742eaca9449bb378', - sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347', - baseFeePerGas: 4959456, - size: undefined -} -Transaction Receipt: { - transactionHash: '0x0578672e97d072b4b91773c8bfc710e4f777616398b82b276323408e59d11362', - transactionIndex: 0n, - blockNumber: 1n, - blockHash: '0x5c05248fe0fb8f45a8c9b9600904a36c0e5c74dce01495cfc72278c185fe7838', - from: '0x6e599da0bff7a6598ac1224e4985430bf16458a4', - to: '0x6f1df96865d09d21e8f3f9a7fba3b17a11c7c53c', - cumulativeGasUsed: 21000n, - gasUsed: 21000n, - logs: [], - logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - status: 1n, - effectiveGasPrice: 2000000000n, - type: 0n -} -Unsubscribed from new block headers. -``` From b234c1c01f67a414e13a084a7a9c172b5ea1769a Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Mon, 10 Jun 2024 07:12:59 -0700 Subject: [PATCH 097/186] fix(docs): mastering-accounts (#7089) * Updates to Mastering (Introduction to) Accounts & Wallets * Add a note about wallet context --- docs/docs/guides/wallet/image.jpeg | Bin 156303 -> 0 bytes docs/docs/guides/wallet/index.md | 372 +++++++++++++++++------------ 2 files changed, 224 insertions(+), 148 deletions(-) delete mode 100644 docs/docs/guides/wallet/image.jpeg diff --git a/docs/docs/guides/wallet/image.jpeg b/docs/docs/guides/wallet/image.jpeg deleted file mode 100644 index 455abbf9bcf00f698b143b3d1d8a16ecc8e4a622..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 156303 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

bj@$5^GYX@3Oys#JDt%r5LwzkBpW*}UA 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 nEL3)l0!s6II9n diff --git a/docs/docs/guides/wallet/index.md b/docs/docs/guides/wallet/index.md index 9dd38e750b5..0e8858ad530 100644 --- a/docs/docs/guides/wallet/index.md +++ b/docs/docs/guides/wallet/index.md @@ -1,65 +1,118 @@ --- sidebar_position: 1 -sidebar_label: 'Mastering Wallets & Accounts' +sidebar_label: 'Introduction to Accounts & Wallets' --- -# Wallets and Accounts Overview +# Introduction to Accounts & Wallets +The concept of an [account](https://ethereum.org/en/developers/docs/accounts/) is central to Ethereum and it can be used to refer to two types of entities that are native to Ethereum: externally-owned accounts and contract accounts. This document relates _exclusively_ to **externally-owned accounts**. An externally-owned account is associated with a "[key pair](https://ethereum.org/en/developers/docs/accounts/#externally-owned-accounts-and-key-pairs)", which is a general concept that is related to [public-key cryptography](https://en.wikipedia.org/wiki/Public-key_cryptography). The key pair consists of a private key, which must always be kept secret, and a public key, which is used to derive a public identifier (address) for an account. Ethereum accounts have an [ETH](https://ethereum.org/en/developers/docs/intro-to-ethereum/#eth) balance, which can be [transferred](/guides/wallet/transactions) to other accounts or used to pay for interactions with [smart contracts](/guides/smart_contracts/smart_contracts_guide). Anyone with access to an account's private key has the ability to control that account's ETH balance, so it's important that an account's private key is always kept secret. In addition to the general guidelines for [protecting private keys](https://ethereum.org/en/security/#protect-private-keys/), private keys should never be included in client-side code that can be seen by end users and should never be committed to code repositories. -## Live code editor +In the context of this document, the term "wallet" refers to a collection of accounts and should not be confused with [wallet "applications"](https://ethereum.org/en/wallets/). - +## Accounts -## Introduction +The [`web3-eth-accounts`](/api/web3-eth-accounts) package contains functions to generate Ethereum accounts, sign transactions and data, and more. In Web3.js, the [`Web3Account`](/api/web3-eth-accounts/interface/Web3Account) interface is used to represent an externally-owned account. The following snippet demonstrates using Web3.js to generate a new random account and then using that account to sign a message: -A Web3.js `Wallet` is your main entry point if you want to use a private key directly to do any blockchain operations (transactions), also called `Signer` in other libraries. - -Unlike other libraries where a wallet holds just one account, a Web3.js `Wallet` can handle **multiple accounts**. They each have their private key and address. So, whether those keys are in your computer's memory or protected by MetaMask, the Wallet makes Ethereum tasks secure and simple. - -The `web3-eth-accounts` package contains functions to generate Ethereum accounts and sign transactions and data. - -In Ethereum, a private key is a critical part of the cryptographic key pair used to secure and control ownership of Ethereum addresses. Each Ethereum address has a matching set of public and private keys in a public-key cryptography system. This key pair enables you to own an Ethereum address, manage funds, and initiate transactions. - -Learn more about wallets [here](https://ethereum.org/en/wallets/) - -You can sign and send transactions in different ways. +```js +// generate a new random account +const account = web3.eth.accounts.create(); -- [Local wallet](./local_wallet) **(Highly recommended)** -- [Node Wallet](./node_wallet) **(Deprecated)** +console.log(account); +/* ↳ +{ + address: '0x9E82491d1978217d631a3b467BF912933F54788f', + privateKey: '', + signTransaction: [Function: signTransaction], + sign: [Function: sign], + encrypt: [Function: encrypt] +} +*/ -For each of them you can use [Web3PromiEvent](./promi_event) to catch extra transaction's events. +// use the account to sign a message +const signature = account.sign("Hello, Web3.js!"); +/* ↳ +{ + message: 'Hello, Web3.js!', + messageHash: '0xc0f5f7ee704f1473acbb7959f5f925d787a9aa76dccc1b4914cbe77c09fd68d5', + v: '0x1b', + r: '0x129822b685d4404924a595af66c9cdd6367a57c66ac66e2e10fd9915d4772fbd', + s: '0x62db48d6f5e47fe87c64a0991d6d94d23b6024d5d8335348f6686b8c46edb1e9', + signature: '0x129822b685d4404924a595af66c9cdd6367a57c66ac66e2e10fd9915d4772fbd62db48d6f5e47fe87c64a0991d6d94d23b6024d5d8335348f6686b8c46edb1e91b' +} +*/ +``` -## Wallets vs Accounts +Note that many of these values will change each time the code is executed, since a new account is created each time. -An **account** in web3.js is an `object`, it refers to an individual Ethereum address with its associated public and private keys. While a wallet is a higher-level construct for managing multiple accounts, an individual Ethereum address is considered an account. +In addition to generating new random accounts, the Account package can also be used to load an existing account from its private key, as in the following snippet: -```ts title='Create a new account' -const account = web3.eth.accounts.create(); +```js +// load an existing account from its private key +const account = web3.eth.accounts.privateKeyToAccount(""); -console.log(account) -/* ↳ +console.log(account); +/* ↳ { address: '0x9E82491d1978217d631a3b467BF912933F54788f', - privateKey: '0x4651f9c219fc6401fe0b3f82129467c717012287ccb61950d2a8ede0687857ba', + privateKey: '', signTransaction: [Function: signTransaction], sign: [Function: sign], encrypt: [Function: encrypt] } */ + +// use the account to sign a message +const signature = account.sign("Hello, Web3.js!"); +/* ↳ +{ + message: 'Hello, Web3.js!', + messageHash: '0xc0f5f7ee704f1473acbb7959f5f925d787a9aa76dccc1b4914cbe77c09fd68d5', + v: '0x1b', + r: '0x129822b685d4404924a595af66c9cdd6367a57c66ac66e2e10fd9915d4772fbd', + s: '0x62db48d6f5e47fe87c64a0991d6d94d23b6024d5d8335348f6686b8c46edb1e9', + signature: '0x129822b685d4404924a595af66c9cdd6367a57c66ac66e2e10fd9915d4772fbd62db48d6f5e47fe87c64a0991d6d94d23b6024d5d8335348f6686b8c46edb1e91b' +} +*/ ``` -A **wallet** in web3.js is an `array` that holds multiple Ethereum accounts. It provides a convenient way to manage and interact with a collection of accounts. Think of it as a digital wallet that you use to store and organize your various Ethereum addresses. +### Account Methods -```ts title='Create a new wallet' -//create a wallet with `1` random account -const wallet = web3.eth.accounts.wallet.create(1); +The following is a list of [`Accounts`](/libdocs/Accounts) methods in the `web3.eth.accounts` package with descriptions and example usage: + +- [create](/libdocs/Accounts#create) +- [decrypt](/libdocs/Accounts#decrypt) +- [encrypt](/libdocs/Accounts#encrypt) +- [hashMessage](/libdocs/Accounts#hashMessage) +- [parseAndValidatePrivateKey](/libdocs/Accounts#libdocs/Accounts#parseandvalidateprivatekey) +- [privateKeyToAccount](/libdocs/Accounts#privatekeytoaccount) +- [privateKeyToAddress](/libdocs/Accounts#privatekeytoaddress) +- [privateKeyToPublicKey](/libdocs/Accounts#privatekeytopublickey) +- [recover](/libdocs/Accounts#recover) +- [recoverTransaction](/libdocs/Accounts#recovertransaction) +- [sign](/libdocs/Accounts#sign) +- [signTransaction](/libdocs/Accounts#signtransaction) + +## Wallets + +A Web3.js wallet is a collection of accounts and is represented with the [`Wallet`](/api/web3-eth-accounts/class/Wallet) class. When a wallet is used to track an account, that account is added to an internal context (i.e. [`Web3Context`](/api/web3-core/class/Web3Context/)), which makes it easier to use that account in the future - this is described in more detail in the [transactions tutorial](/guides/wallet/transactions). The following snippet demonstrates creating a wallet with 2 new random accounts and using the second account to sign a message: + +```js +// create a wallet with 2 new random accounts +const wallet = web3.eth.accounts.wallet.create(2); console.log(wallet) -/* ↳ -Wallet(1) [ +/* ↳ +Wallet(2) [ + { + address: '0xaaD0d33dc9800258c1265bdDA47b9266472144F7', + privateKey: '', + signTransaction: [Function: signTransaction], + sign: [Function: sign], + encrypt: [Function: encrypt] + }, { - address: '0xB2D5647C03F36cA54f7d783b6Fa5afED297330d4', - privateKey: '0x7b907534ec13b19c67c2a738fdaa69014298c71f2221d7e5dec280232e996610', + address: '0x359caa845324802C64B97544460F31fba4f9B9ba', + privateKey: '', signTransaction: [Function: signTransaction], sign: [Function: sign], encrypt: [Function: encrypt] @@ -69,133 +122,166 @@ Wallet(1) [ privateKeyToAccount: [Function: privateKeyToAccountWithContext], decrypt: [Function: decryptWithContext] }, - _addressMap: Map(1) { '0xb2d5647c03f36ca54f7d783b6fa5afed297330d4' => 0 }, + _addressMap: Map(2) { + '0xaad0d33dc9800258c1265bdda47b9266472144f7' => 0, + '0x359caa845324802c64b97544460f31fba4f9b9ba' => 1 + }, _defaultKeyName: 'web3js_wallet' ] */ -``` - -## Diagram - -![Diagram wallet and accounts](image.jpeg) - -To learn more about the `accounts` methods, please visit [web3.js accounts API](/libdocs/Accounts) - -To learn more about the `wallet` methods, please visit [web3.js wallet API](/libdocs/Wallet) - -## Sending transactions - -The shortest way to do this, is by creating a `Wallet` directly by adding a private key (the private key must start with '0x' and it must have funds to execute the transaction) - -```ts title='Sending a transaction adding a privateKey' -import { Web3 } from 'web3'; - -const web3 = new Web3('https://ethereum-sepolia.publicnode.com'); -//this will create an array `Wallet` with 1 account with this privateKey -//it will generate automatically a public key for it -//make sure you have funds in this accounts -//highlight-next-line -const wallet = web3.eth.accounts.wallet.add('0x152c39c430806985e4dc16fa1d7d87f90a7a1d0a6b3f17efe5158086815652e5'); - -const _to = '0xc7203efeb54846c149f2c79b715a8927f7334e74'; -const _value = '1'; //1 wei - -//the `from` address in the transaction must match the address stored in our `Wallet` array -//that's why we explicitly access it using `wallet[0].address` to ensure accuracy -const receipt = await web3.eth.sendTransaction({ - from: wallet[0].address, - to: _to, - value: _value, -}); -//if you have more than 1 account, you can change the address by accessing to another account -//e.g, `from: wallet[1].address` - -console.log('Tx receipt:', receipt); +// use the second account in the wallet to sign a message +const signature = wallet[1].sign("Hello, Web3.js!"); +// wallet accounts can also be accessed with the "at" and "get" methods +// wallet.at(1).sign("Hello, Web3.js!") +// wallet.get(1).sign("Hello, Web3.js!") +console.log(signature); /* ↳ -Tx receipt: { - blockHash: '0xa43b43b6e13ba47f2283b4afc15271ba07d1bba0430bd0c430f770ba7c98d054', - blockNumber: 4960689n, - cumulativeGasUsed: 7055436n, - effectiveGasPrice: 51964659212n, - from: '0xa3286628134bad128faeef82f44e99aa64085c94', - gasUsed: 21000n, - logs: [], - logsBloom: '0x00000...00000000', - status: 1n, - to: '0xc7203efeb54846c149f2c79b715a8927f7334e74', - transactionHash: '0xb88f3f300f1a168beb3a687abc2d14c389ac9709f18b768c90792c7faef0de7c', - transactionIndex: 41n, - type: 2n +{ + message: 'Hello, Web3.js!', + messageHash: '0xc0f5f7ee704f1473acbb7959f5f925d787a9aa76dccc1b4914cbe77c09fd68d5', + v: '0x1c', + r: '0xd90fc42ff83fdf0ec6778c1c27f3051439de7844eacf06195c761fece19ed77d', + s: '0x729693156c48d07df9f4970772049dbe24ebce979765f788974a13c318b2834a', + signature: '0xd90fc42ff83fdf0ec6778c1c27f3051439de7844eacf06195c761fece19ed77d729693156c48d07df9f4970772049dbe24ebce979765f788974a13c318b2834a1c' } */ ``` -## Interacting with contracts - -### Writing functions +Note that many of these values will change each time the code is executed, since new accounts are created each time. -To interact with functions that modify or update data in smart contracts(writing-functions), we need to create a `Wallet`. This `Wallet` must holds at least 1 account with the necessary funds to execute these operations on the blockchain. +In addition to generating new random accounts, a wallet can also be used to load an existing account from its private key, as in the following snippet: -```ts title='Interacting with writing-functions of a smart contract' -import { Web3 } from 'web3'; +```js +// create a wallet with a single existing account +const wallet = web3.eth.accounts.wallet.add(""); -const web3 = new Web3('https://ethereum-sepolia.publicnode.com'); - -//create a wallet -//highlight-next-line -const wallet = web3.eth.accounts.wallet.add('0x152c39c430806985e4dc16fa1d7d87f90a7a1d0a6b3f17efe5158086815652e5'); - -//this is how we can access to the first account of the wallet -console.log('Account 1:', wallet[0]); +console.log(wallet); /* ↳ -Account 1: { - address: '0x57CaabD59a5436F0F1b2B191b1d070e58E6449AE', - privateKey: '0x152c39c430806985e4dc16fa1d7d87f90a7a1d0a6b3f17efe5158086815652e5', - ... -} +Wallet(1) [ + { + address: '0xC978F87516152f542dc4D6f64C810B0c206b11A8', + privateKey: '', + signTransaction: [Function: signTransaction], + sign: [Function: sign], + encrypt: [Function: encrypt] + }, + _accountProvider: { + create: [Function: createWithContext], + privateKeyToAccount: [Function: privateKeyToAccountWithContext], + decrypt: [Function: decryptWithContext] + }, + _addressMap: Map(1) { '0xc978f87516152f542dc4d6f64c810b0c206b11a8' => 0 }, + _defaultKeyName: 'web3js_wallet' +] */ +``` -//instantiate the contract -const myContract = new web3.eth.Contract(ABI, CONTRACT_ADDRESS); +New accounts can be added to an existing wallet, as is demonstrated by the following code snippet: -//interact with the contract -//wallet[0].address == '0x57CaabD59a5436F0F1b2B191b1d070e58E6449AE' -//highlight-next-line -const txReceipt = await myContract.methods.doSomething().send({ from: wallet[0].address }); +```js +// create a wallet with a single random accounts +const wallet = web3.eth.accounts.wallet.create(1); -console.log('Transaction receipt:', txReceipt); +console.log(wallet); /* ↳ - Transaction receipt: {...} +Wallet(1) [ + { + address: '0x6680D50C2165e8F1841D9CdaA42C2F1b949a39f2', + privateKey: '', + signTransaction: [Function: signTransaction], + sign: [Function: sign], + encrypt: [Function: encrypt] + }, + _accountProvider: { + create: [Function: createWithContext], + privateKeyToAccount: [Function: privateKeyToAccountWithContext], + decrypt: [Function: decryptWithContext] + }, + _addressMap: Map(1) { '0x6680d50c2165e8f1841d9cdaa42c2f1b949a39f2' => 0 }, + _defaultKeyName: 'web3js_wallet' +] */ -``` - -### Reading functions (view) - -To interact with smart contracts `view public/external returns`, we don't need to instantiate a `Wallet`, we can do it just by instantiating the smart contract and the provider. -```ts title='Interacting with reading-functions of a smart contract' -import { Web3 } from 'web3'; +// add a new account to the wallet with the wallet's "create" method +wallet.create(1); -//instantiate the provider -const web3 = new Web3('https://ethereum-sepolia.publicnode.com'); - -//instantiate the contract -const myContract = new web3.eth.Contract(ABI, CONTRACT_ADDRESS); +console.log(wallet); +/* ↳ +Wallet(2) [ + { + address: '0x6680D50C2165e8F1841D9CdaA42C2F1b949a39f2', + privateKey: '', + signTransaction: [Function: signTransaction], + sign: [Function: sign], + encrypt: [Function: encrypt] + }, + { + address: '0x5eD8a3ED6Bb1f32e4B479380cFAcf43C49a5440A', + privateKey: '', + signTransaction: [Function: signTransaction], + sign: [Function: sign], + encrypt: [Function: encrypt] + }, + _accountProvider: { + create: [Function: createWithContext], + privateKeyToAccount: [Function: privateKeyToAccountWithContext], + decrypt: [Function: decryptWithContext] + }, + _addressMap: Map(2) { + '0x6680d50c2165e8f1841d9cdaa42c2f1b949a39f2' => 0, + '0x5ed8a3ed6bb1f32e4b479380cfacf43c49a5440a' => 1 + }, + _defaultKeyName: 'web3js_wallet' +] +*/ -//call the `view function` in the contract -//highlight-next-line -const result = await myContract.methods.doSomething().call(); +// create a new account and add it to the wallet +const newAccount = web3.eth.accounts.create(); +wallet.add(newAccount); -console.log('Result:', result) +console.log(wallet); /* ↳ - Result: ... +Wallet(3) [ + { + address: '0x6680D50C2165e8F1841D9CdaA42C2F1b949a39f2', + privateKey: '', + signTransaction: [Function: signTransaction], + sign: [Function: sign], + encrypt: [Function: encrypt] + }, + { + address: '0x5eD8a3ED6Bb1f32e4B479380cFAcf43C49a5440A', + privateKey: '', + signTransaction: [Function: signTransaction], + sign: [Function: sign], + encrypt: [Function: encrypt] + }, + { + address: '0x3065Cf410Bd6A10c5FF3Df8f60b82fF5Ee5db18a', + privateKey: '', + signTransaction: [Function: signTransaction], + sign: [Function: sign], + encrypt: [Function: encrypt] + }, + _accountProvider: { + create: [Function: createWithContext], + privateKeyToAccount: [Function: privateKeyToAccountWithContext], + decrypt: [Function: decryptWithContext] + }, + _addressMap: Map(3) { + '0x6680d50c2165e8f1841d9cdaa42c2f1b949a39f2' => 0, + '0x5ed8a3ed6bb1f32e4b479380cfacf43c49a5440a' => 1, + '0x3065cf410bd6a10c5ff3df8f60b82ff5ee5db18a' => 2 + }, + _defaultKeyName: 'web3js_wallet' +] */ ``` -## Wallet methods +### Wallet Methods -The following is a list of `Wallet` [methods](/libdocs/Wallet) in the `web3.eth.accounts.wallet` package with description and example usage: +The following is a list of [`Wallet`](/libdocs/Wallet) methods in the `web3.eth.accounts.wallet` package with description and example usage: - [add](/libdocs/Wallet#add) - [clear](/libdocs/Wallet#clear) @@ -208,20 +294,10 @@ The following is a list of `Wallet` [methods](/libdocs/Wallet) in the `web3.eth. - [save](/libdocs/Wallet#save) - [getStorage](/libdocs/Wallet#getStorage) -## Account methods - -The following is a list of `Accounts` [methods](/libdocs/Wallet) in the `web3.eth.accounts` package with description and example usage: +## Next Steps -- [create](/libdocs/Accounts#create) -- [decrypt](/libdocs/Accounts#decrypt) -- [encrypt](/libdocs/Accounts#encrypt) -- [hashMessage](/libdocs/Accounts#hashMessage) -- [parseAndValidatePrivateKey](/libdocs/Accounts#libdocs/Accounts#parseandvalidateprivatekey) -- [privateKeyToAccount](/libdocs/Accounts#privatekeytoaccount) -- [privateKeyToAddress](/libdocs/Accounts#privatekeytoaddress) -- [privateKeyToPublicKey](/libdocs/Accounts#privatekeytopublickey) -- [recover](/libdocs/Accounts#recover) -- [recoverTransaction](/libdocs/Accounts#recovertransaction) -- [sign](/libdocs/Accounts#sign) -- [signTransaction](/libdocs/Accounts#signtransaction) +This document is just an introduction to Web3.js accounts and wallets. Here are some suggestions for what to review next: +- Learn how to [transfer ETH](/guides/wallet/transactions) from one account to another. +- Build a front-end application that uses [injected accounts](/guides/wallet/metamask) from the MetaMask wallet. +- Use an account to [deploy and interact with a smart contract](/guides/smart_contracts/smart_contracts_guide). From 95476430782a30e6a6da80a452b5b2d670d98ce8 Mon Sep 17 00:00:00 2001 From: Junaid <86780488+jdevcs@users.noreply.github.com> Date: Tue, 11 Jun 2024 15:35:32 +0200 Subject: [PATCH 098/186] transaction middleware (#7088) * add web3 packages references in context * call TXM in sendTx * Transaction Middleware * call txm * name fix * name fix 2 * txm example * txm plugin * unit tests * dependency * lint fix * test data * lint fix * fixed lint and unit test * unit tests in eth * changelog udpates --- packages/web3-core/CHANGELOG.md | 6 +- packages/web3-core/src/web3_context.ts | 3 + packages/web3-eth/CHANGELOG.md | 8 +- packages/web3-eth/src/rpc_method_wrappers.ts | 10 +- packages/web3-eth/src/types.ts | 17 +++ packages/web3-eth/src/web3_eth.ts | 15 ++- .../test/fixtures/transactions_data.ts | 117 ++++++++++++++++++ .../send_transaction_middleware.test.ts | 98 +++++++++++++++ .../web3_eth_methods_with_parameters.test.ts | 16 ++- packages/web3/CHANGELOG.md | 8 +- tools/web3-plugin-example/CHANGELOG.md | 6 +- tools/web3-plugin-example/package.json | 3 +- .../src/custom_rpc_methods.ts | 2 +- ...eware.ts => request_manager_middleware.ts} | 0 .../src/transaction_middleware.ts | 38 ++++++ .../src/transaction_middleware_plugin.ts | 44 +++++++ .../test/unit/fixtures/transactions_data.ts | 117 ++++++++++++++++++ ....ts => request_manager_middleware.test.ts} | 0 .../test/unit/transaction_middleware.test.ts | 76 ++++++++++++ 19 files changed, 574 insertions(+), 10 deletions(-) create mode 100644 packages/web3-eth/test/fixtures/transactions_data.ts create mode 100644 packages/web3-eth/test/unit/rpc_method_wrappers/send_transaction_middleware.test.ts rename tools/web3-plugin-example/src/{middleware.ts => request_manager_middleware.ts} (100%) create mode 100644 tools/web3-plugin-example/src/transaction_middleware.ts create mode 100644 tools/web3-plugin-example/src/transaction_middleware_plugin.ts create mode 100644 tools/web3-plugin-example/test/unit/fixtures/transactions_data.ts rename tools/web3-plugin-example/test/unit/{middleware.test.ts => request_manager_middleware.test.ts} (100%) create mode 100644 tools/web3-plugin-example/test/unit/transaction_middleware.test.ts diff --git a/packages/web3-core/CHANGELOG.md b/packages/web3-core/CHANGELOG.md index 0346e3f74a9..6c8e6a2a7e2 100644 --- a/packages/web3-core/CHANGELOG.md +++ b/packages/web3-core/CHANGELOG.md @@ -221,4 +221,8 @@ Documentation: - Set a try catch block if processesingError fails (#7022) -## [Unreleased] \ No newline at end of file +## [Unreleased] + +### Added + +- Now when existing packages are added in web3, will be avalible for plugins via context. (#7088) \ No newline at end of file diff --git a/packages/web3-core/src/web3_context.ts b/packages/web3-core/src/web3_context.ts index b50f8ba30f7..867f10f2350 100644 --- a/packages/web3-core/src/web3_context.ts +++ b/packages/web3-core/src/web3_context.ts @@ -219,6 +219,9 @@ export class Web3Context< newContextChild.setConfig({ [event.name]: event.newValue }); }); + // @ts-expect-error No index signature with a parameter of type 'string' was found on type 'Web3Context' + this[ContextRef.name] = newContextChild; + return newContextChild; } diff --git a/packages/web3-eth/CHANGELOG.md b/packages/web3-eth/CHANGELOG.md index 3d2d36b17c0..98dfb42b220 100644 --- a/packages/web3-eth/CHANGELOG.md +++ b/packages/web3-eth/CHANGELOG.md @@ -248,4 +248,10 @@ Documentation: - Fixed issue with simple transactions, Within `checkRevertBeforeSending` if there is no data set in transaction, set gas to be `21000` (#7043) -## [Unreleased] \ No newline at end of file +## [Unreleased] + +### Added + +- `sendTransaction` in `rpc_method_wrappers` accepts optional param of `TransactionMiddleware` (#7088) +- WebEth has `setTransactionMiddleware` and `getTransactionMiddleware` for automatically passing to `sentTransaction` (#7088) +- `TransactionMiddleware` and `TransactionMiddleware` data types are exported (#7088) \ No newline at end of file diff --git a/packages/web3-eth/src/rpc_method_wrappers.ts b/packages/web3-eth/src/rpc_method_wrappers.ts index 20e832be892..336aef3a23d 100644 --- a/packages/web3-eth/src/rpc_method_wrappers.ts +++ b/packages/web3-eth/src/rpc_method_wrappers.ts @@ -70,6 +70,7 @@ import { SendSignedTransactionOptions, SendTransactionEvents, SendTransactionOptions, + TransactionMiddleware, } from './types.js'; // eslint-disable-next-line import/no-cycle import { getTransactionFromOrToAttr } from './utils/transaction_builder.js'; @@ -544,13 +545,14 @@ export function sendTransaction< ResolveType = FormatType, >( web3Context: Web3Context, - transaction: + transactionObj: | Transaction | TransactionWithFromLocalWalletIndex | TransactionWithToLocalWalletIndex | TransactionWithFromAndToLocalWalletIndex, returnFormat: ReturnFormat, options: SendTransactionOptions = { checkRevertBeforeSending: true }, + transactionMiddleware?: TransactionMiddleware ): Web3PromiEvent> { const promiEvent = new Web3PromiEvent>( (resolve, reject) => { @@ -563,6 +565,12 @@ export function sendTransaction< returnFormat, }); + let transaction = {...transactionObj}; + + if(!isNullish(transactionMiddleware)){ + transaction = await transactionMiddleware.processTransaction(transaction); + } + let transactionFormatted: | Transaction | TransactionWithFromLocalWalletIndex diff --git a/packages/web3-eth/src/types.ts b/packages/web3-eth/src/types.ts index e1bba319d69..9ed49badb39 100644 --- a/packages/web3-eth/src/types.ts +++ b/packages/web3-eth/src/types.ts @@ -33,6 +33,9 @@ import { Numbers, Transaction, TransactionReceipt, + TransactionWithFromAndToLocalWalletIndex, + TransactionWithFromLocalWalletIndex, + TransactionWithToLocalWalletIndex, } from 'web3-types'; export type InternalTransaction = FormatType; @@ -88,3 +91,17 @@ export interface RevertReasonWithCustomError extends RevertReason { customErrorDecodedSignature: string; customErrorArguments: Record; } + +export type TransactionMiddlewareData = Transaction +| TransactionWithFromLocalWalletIndex +| TransactionWithToLocalWalletIndex +| TransactionWithFromAndToLocalWalletIndex; + +export interface TransactionMiddleware{ + // for transaction processing before signing + processTransaction( + transaction: TransactionMiddlewareData, + options?: { [key: string]: unknown }, + ): Promise; + +} \ No newline at end of file diff --git a/packages/web3-eth/src/web3_eth.ts b/packages/web3-eth/src/web3_eth.ts index 959a7d5eddc..abce5c2c317 100644 --- a/packages/web3-eth/src/web3_eth.ts +++ b/packages/web3-eth/src/web3_eth.ts @@ -48,7 +48,7 @@ import { toChecksumAddress, isNullish, ethUnitMap } from 'web3-utils'; import { ethRpcMethods } from 'web3-rpc-methods'; import * as rpcMethodsWrappers from './rpc_method_wrappers.js'; -import { SendTransactionOptions } from './types.js'; +import { SendTransactionOptions, TransactionMiddleware } from './types.js'; import { LogsSubscription, NewPendingTransactionsSubscription, @@ -99,6 +99,9 @@ export const registeredSubscriptions = { * ``` */ export class Web3Eth extends Web3Context { + + private transactionMiddleware?: TransactionMiddleware; + public constructor( providerOrContext?: SupportedProviders | Web3ContextInitOptions | string, ) { @@ -126,6 +129,14 @@ export class Web3Eth extends Web3Context. +*/ + +export const blockMockResult = { + "jsonrpc": "2.0", + "id": "a40a81fa-1f8b-4bb2-a0ad-eef9b6d4636f", + "result": { + "baseFeePerGas": "0x44dab2983", + "blobGasUsed": "0x20000", + "difficulty": "0x0", + "excessBlobGas": "0x1c0000", + "extraData": "0x407273796e636275696c646572", + "gasLimit": "0x1c9c380", + "gasUsed": "0xb7a086", + "hash": "0xf2b1729965179032b17165678a1a212fa31cb008e30f4011ffe8ebdddbd02b95", + "logsBloom": "0xc3a70590c1c62524173d1892e33888067101934dc0891c2c9a898252b6f320215084a48906452960820188d32bba6fb82ec989018a0268603a00a4c6432a11276c9a038c676938eb68bc436c9905a9a1b08d238fb4458f48498215808bec81112e2a3a54869ff22422a8e491093da8a40f601d198417041cd22f799f9048865006e0b069ab049b852442b310396248088145e2810f230f9a44000c6868bc73e9afa8832a8ac92fd609007ac53c0a9cba0645ce298080184624e8040831dbc331f5e618072407050250021b3210e542781183a612d4618c1244000d421a6ca9c01a57e86a085402c55ab413f840a001e7117894d0469e20c2304a9655e344f60d", + "miner": "0x1f9090aae28b8a3dceadf281b0f12828e676c326", + "mixHash": "0x787ab1d511b72df60a705bb4cfc4e92e2f9d203e3e007ae3a0f757425951ca24", + "nonce": "0x0000000000000000", + "number": "0x131ad16", + "parentBeaconBlockRoot": "0x03bbca9fd0c7a0a020de04287f489112c79bc268220e9ff8e18957cd0d5c3cad", + "parentHash": "0xb1d8fa7b8346421d373a6d4c28575155516cea17c12a3df7201170c9e561b38c", + "receiptsRoot": "0x4ec500bdcd761ad505b2a989156c9a9628058d415acc93d800487c7c76308c59", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "size": "0xcb90", + "stateRoot": "0xafbb8743c0a5f4740e322217cb1f2780ee5c57c32bcd04e9256b09efc1a70568", + "timestamp": "0x6661ab8b", + "totalDifficulty": "0xc70d815d562d3cfa955", + "transactions": [ + "0x589956b75d19dbaf9911f246c23d4b3327ef234872ec1931c419041b23eb5b41", + "0x4d3793f20c25979bd329cafdd889ba6be015cfc999acce8642d6e757b5192e93", + "0x5ba5618ca5a14bab50862255dc69726a498346f9832bd0fd1394e8834e56790b", + "0x6df9678f350db7e30afc930b7246bf1c144b9acb7fd1d25d7e107d550ed5a061", + "0xb8f48ff2876cc393725ea4162421754dfb74ff2364a12d4d3de2c6269f1958c7", + "0x2e5cf7c0607025038b6ccd871dc9ce85af686fd5fa2c82e605198af9afa92cca", + "0x307fb855836feff5d8d0969fa4a44d3c6ae31d335da6577f48f9496d6fe9e0b9", + "0x1362bed1aa8a30d28b7b76c35c2a8601b257058beffa9490dcb20de12bcb15b2", + "0x234c7cc346c204022b2e5ead6d2e8c02317aeb0ec5ca82bd97c2b5d5e59a280b", + ], + "transactionsRoot": "0xc21a4d667b5f841538430b1e2c002c598f2178628ad1d61ea2fda462d1216607", + "uncles": [], + "withdrawals": [ + { + "address": "0xea97dc2523c0479484076660f150833e264c41e9", + "amount": "0x11b6d8c", + "index": "0x2dbe454", + "validatorIndex": "0x10f646" + }, + { + "address": "0xb3e84b6c6409826dc45432b655d8c9489a14a0d7", + "amount": "0x11b4ce2", + "index": "0x2dbe455", + "validatorIndex": "0x10f647" + }, + { + "address": "0x7e2a2fa2a064f693f0a55c5639476d913ff12d05", + "amount": "0x11ad733", + "index": "0x2dbe456", + "validatorIndex": "0x10f648" + }, + + ], + "withdrawalsRoot": "0x2914fa2f5ed93880ed45b58e8f6d14f20c645988400d83c59109964e2053fe1a" + } +}; + +export const receiptMockResult = { + "jsonrpc": "2.0", + "id": 1, + "result": { + "blockHash": "0xf4ad699b98241caf3930779b7d919a77f1727e67cef6ed1ce2a4c655ba812d54", + "blockNumber": "0x131ad35", + // eslint-disable-next-line no-null/no-null + "contractAddress": null, + "cumulativeGasUsed": "0x8cae7a", + "effectiveGasPrice": "0x4c9bc2d65", + "from": "0xab6fd3a7c6ce9db945889cd018e028e055f3bc2e", + "gasUsed": "0xa145", + "logs": [ + { + "address": "0xdac17f958d2ee523a2206206994597c13d831ec7", + "blockHash": "0xf4ad699b98241caf3930779b7d919a77f1727e67cef6ed1ce2a4c655ba812d54", + "blockNumber": "0x131ad35", + "data": "0x000000000000000000000000000000000000000000000000000000000016e360", + "logIndex": "0xdf", + "removed": false, + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x000000000000000000000000ab6fd3a7c6ce9db945889cd018e028e055f3bc2e", + "0x00000000000000000000000051112f9f08a2174fe3fc96aad8f07e82d1cccd00" + ], + "transactionHash": "0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f", + "transactionIndex": "0x82" + } + ], + "logsBloom": "0x00000000000000000000000002000000000000000000000000000000004000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000400000000000100000000000000000000000000080000000000000000000040000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000400000000000000000000000", + "status": "0x1", + "to": "0xdac17f958d2ee523a2206206994597c13d831ec7", + "transactionHash": "0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f", + "transactionIndex": "0x82", + "type": "0x2" + } +}; \ No newline at end of file diff --git a/packages/web3-eth/test/unit/rpc_method_wrappers/send_transaction_middleware.test.ts b/packages/web3-eth/test/unit/rpc_method_wrappers/send_transaction_middleware.test.ts new file mode 100644 index 00000000000..63dddbb759f --- /dev/null +++ b/packages/web3-eth/test/unit/rpc_method_wrappers/send_transaction_middleware.test.ts @@ -0,0 +1,98 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ + +import { Web3Context } from "web3-core"; +import { DEFAULT_RETURN_FORMAT, Web3EthExecutionAPI } from "web3-types"; +import {blockMockResult,receiptMockResult } from "../../fixtures/transactions_data"; +import { TransactionMiddleware, sendTransaction } from "../../../src"; + +const mockTransactionMiddleware: TransactionMiddleware = { + processTransaction: jest.fn(async (transaction) => { + const tx = {...transaction} + tx.data = '0x123'; + return Promise.resolve(tx)} +), +}; + +describe('sendTransaction', () => { + let web3Context: Web3Context; + + beforeEach(() => { + let blockNum = 0; + web3Context = new Web3Context('http://127.0.0.1:8545'); + + web3Context.requestManager.send = jest.fn(async (request) => { + blockNum += 1; + + if(request.method === 'eth_getBlockByNumber'){ + + return Promise.resolve(blockMockResult.result); + } + if(request.method === 'eth_call'){ + + return Promise.resolve("0x"); + } + if(request.method === 'eth_blockNumber'){ + + return Promise.resolve(blockNum.toString(16)); + } + if(request.method === 'eth_sendTransaction'){ + + return Promise.resolve("0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f"); + } + if (request.method === 'eth_getTransactionReceipt') { + return Promise.resolve(receiptMockResult.result); + } + + return Promise.resolve("Unknown Request" as any); + }); + }); + + afterEach(() => jest.resetAllMocks()); + + it('should call processTransaction when transactionMiddleware is provided', async () => { + const transaction = { + from: '0x6E599DA0bfF7A6598AC1224E4985430Bf16458a4', + to: '0x6f1DF96865D09d21e8f3f9a7fbA3b17A11c7C53C', + value: '0x1', + data: '0x1' + }; + + await sendTransaction( + web3Context, + transaction, + DEFAULT_RETURN_FORMAT, + {}, + mockTransactionMiddleware, + ); + + expect(mockTransactionMiddleware.processTransaction).toHaveBeenCalledWith(transaction); + }); + + it('should not call processTransaction when transactionMiddleware is not provided', async () => { + const transaction = { + from: '0x6E599DA0bfF7A6598AC1224E4985430Bf16458a4', + to: '0x6f1DF96865D09d21e8f3f9a7fbA3b17A11c7C53C', + value: '0x1', + data: '0x1' + }; + + await sendTransaction(web3Context, transaction, DEFAULT_RETURN_FORMAT); + + expect(mockTransactionMiddleware.processTransaction).not.toHaveBeenCalled(); + }); +}); \ No newline at end of file diff --git a/packages/web3-eth/test/unit/web3_eth_methods_with_parameters.test.ts b/packages/web3-eth/test/unit/web3_eth_methods_with_parameters.test.ts index c2f017b24cf..76d753bde4b 100644 --- a/packages/web3-eth/test/unit/web3_eth_methods_with_parameters.test.ts +++ b/packages/web3-eth/test/unit/web3_eth_methods_with_parameters.test.ts @@ -17,7 +17,7 @@ along with web3.js. If not, see . import { ethRpcMethods } from 'web3-rpc-methods'; import { TransactionInfoAPI } from 'web3-types'; -import Web3Eth from '../../src/index'; +import Web3Eth, { TransactionMiddleware } from '../../src/index'; import * as rpcMethodWrappers from '../../src/rpc_method_wrappers'; import { getBlockNumberValidData, @@ -63,6 +63,20 @@ describe('web3_eth_methods_with_parameters', () => { web3Eth = new Web3Eth('http://127.0.0.1:8545'); }); + it('should set and unset the transactionMiddleware correctly', () => { + const mockTransactionMiddleware: TransactionMiddleware = { + processTransaction: jest.fn(), + }; + + web3Eth.setTransactionMiddleware(mockTransactionMiddleware); + + expect(web3Eth.getTransactionMiddleware()).toBe(mockTransactionMiddleware); + + web3Eth.setTransactionMiddleware(undefined as any); + + expect(web3Eth.getTransactionMiddleware()).toBeUndefined(); + }); + describe('should call RPC method with expected parameters', () => { describe('only has returnFormat parameter', () => { describe('getHashRate', () => { diff --git a/packages/web3/CHANGELOG.md b/packages/web3/CHANGELOG.md index 896d0d884f0..c66601be9ed 100644 --- a/packages/web3/CHANGELOG.md +++ b/packages/web3/CHANGELOG.md @@ -268,4 +268,10 @@ Documentation: - Updated type `Web3EthInterface.accounts` to includes `privateKeyToAccount`,`privateKeyToAddress`,and `privateKeyToPublicKey` (#6762) -## [Unreleased] \ No newline at end of file +## [Unreleased] + +### Added + +#### web3 + +- Now when existing packages are added in web3, will be avalible for plugins via context. (#7088) \ No newline at end of file diff --git a/tools/web3-plugin-example/CHANGELOG.md b/tools/web3-plugin-example/CHANGELOG.md index 65e4434200c..636ba482bed 100644 --- a/tools/web3-plugin-example/CHANGELOG.md +++ b/tools/web3-plugin-example/CHANGELOG.md @@ -88,4 +88,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Dependencies updated -## [Unreleased] \ No newline at end of file +## [Unreleased] + +### Added + +Transaction middleware (#7088) \ No newline at end of file diff --git a/tools/web3-plugin-example/package.json b/tools/web3-plugin-example/package.json index 3832f5ef30d..2e85b5750ce 100644 --- a/tools/web3-plugin-example/package.json +++ b/tools/web3-plugin-example/package.json @@ -57,6 +57,7 @@ "web3-eth-abi": ">= 4.1.1 < 5", "web3-eth-contract": ">= 4.0.5 < 5", "web3-types": ">= 1.1.1 < 5", - "web3-utils": ">= 4.0.5 < 5" + "web3-utils": ">= 4.0.5 < 5", + "web3-eth": ">= 4.7.0 < 5" } } diff --git a/tools/web3-plugin-example/src/custom_rpc_methods.ts b/tools/web3-plugin-example/src/custom_rpc_methods.ts index ed1c2fbee23..d5ff583ddf5 100644 --- a/tools/web3-plugin-example/src/custom_rpc_methods.ts +++ b/tools/web3-plugin-example/src/custom_rpc_methods.ts @@ -18,7 +18,7 @@ import { Web3PluginBase } from 'web3-core'; // eslint-disable-next-line require-extensions/require-extensions import { Web3Context } from './reexported_web3_context'; // eslint-disable-next-line require-extensions/require-extensions -import { Web3Middleware } from './middleware'; +import { Web3Middleware } from './request_manager_middleware'; type CustomRpcApi = { custom_rpc_method: () => string; diff --git a/tools/web3-plugin-example/src/middleware.ts b/tools/web3-plugin-example/src/request_manager_middleware.ts similarity index 100% rename from tools/web3-plugin-example/src/middleware.ts rename to tools/web3-plugin-example/src/request_manager_middleware.ts diff --git a/tools/web3-plugin-example/src/transaction_middleware.ts b/tools/web3-plugin-example/src/transaction_middleware.ts new file mode 100644 index 00000000000..d38eec8127b --- /dev/null +++ b/tools/web3-plugin-example/src/transaction_middleware.ts @@ -0,0 +1,38 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ + +import { TransactionMiddleware, TransactionMiddlewareData } from "web3-eth"; + +// Sample Transaction Middleware +export class Web3TransactionMiddleware implements TransactionMiddleware { + + // eslint-disable-next-line class-methods-use-this + public async processTransaction(transaction: TransactionMiddlewareData, + _options?: { [key: string]: unknown } | undefined): + + Promise { + + // eslint-disable-next-line prefer-const + let txObj = { ...transaction }; + + // Add your logic here for transaction modification + txObj.data = '0x123'; + + return Promise.resolve(txObj); + } + +} diff --git a/tools/web3-plugin-example/src/transaction_middleware_plugin.ts b/tools/web3-plugin-example/src/transaction_middleware_plugin.ts new file mode 100644 index 00000000000..3dd86ed7e26 --- /dev/null +++ b/tools/web3-plugin-example/src/transaction_middleware_plugin.ts @@ -0,0 +1,44 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ +import { Web3PluginBase } from 'web3-core'; +// eslint-disable-next-line require-extensions/require-extensions +import { Web3Context } from './reexported_web3_context'; +// eslint-disable-next-line require-extensions/require-extensions +import { Web3TransactionMiddleware } from './transaction_middleware'; + +// Sample Transaction middleware plugin +export class TransactionMiddlewarePlugin extends Web3PluginBase { + public pluginNamespace = 'TransactionsPlugIn'; + public txMiddleware: Web3TransactionMiddleware; + + public constructor() { + super(); + this.txMiddleware = new Web3TransactionMiddleware(); + } + + public link(parentContext: Web3Context): void { + + if (this.txMiddleware){ + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + (parentContext as any).Web3Eth.setTransactionMiddleware(this.txMiddleware); + } + + super.link(parentContext); + } + +} + diff --git a/tools/web3-plugin-example/test/unit/fixtures/transactions_data.ts b/tools/web3-plugin-example/test/unit/fixtures/transactions_data.ts new file mode 100644 index 00000000000..189e2135ae4 --- /dev/null +++ b/tools/web3-plugin-example/test/unit/fixtures/transactions_data.ts @@ -0,0 +1,117 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ + +export const blockMockResult = { + "jsonrpc": "2.0", + "id": "a40a81fa-1f8b-4bb2-a0ad-eef9b6d4636f", + "result": { + "baseFeePerGas": "0x44dab2983", + "blobGasUsed": "0x20000", + "difficulty": "0x0", + "excessBlobGas": "0x1c0000", + "extraData": "0x407273796e636275696c646572", + "gasLimit": "0x1c9c380", + "gasUsed": "0xb7a086", + "hash": "0xf2b1729965179032b17165678a1a212fa31cb008e30f4011ffe8ebdddbd02b95", + "logsBloom": "0xc3a70590c1c62524173d1892e33888067101934dc0891c2c9a898252b6f320215084a48906452960820188d32bba6fb82ec989018a0268603a00a4c6432a11276c9a038c676938eb68bc436c9905a9a1b08d238fb4458f48498215808bec81112e2a3a54869ff22422a8e491093da8a40f601d198417041cd22f799f9048865006e0b069ab049b852442b310396248088145e2810f230f9a44000c6868bc73e9afa8832a8ac92fd609007ac53c0a9cba0645ce298080184624e8040831dbc331f5e618072407050250021b3210e542781183a612d4618c1244000d421a6ca9c01a57e86a085402c55ab413f840a001e7117894d0469e20c2304a9655e344f60d", + "miner": "0x1f9090aae28b8a3dceadf281b0f12828e676c326", + "mixHash": "0x787ab1d511b72df60a705bb4cfc4e92e2f9d203e3e007ae3a0f757425951ca24", + "nonce": "0x0000000000000000", + "number": "0x131ad16", + "parentBeaconBlockRoot": "0x03bbca9fd0c7a0a020de04287f489112c79bc268220e9ff8e18957cd0d5c3cad", + "parentHash": "0xb1d8fa7b8346421d373a6d4c28575155516cea17c12a3df7201170c9e561b38c", + "receiptsRoot": "0x4ec500bdcd761ad505b2a989156c9a9628058d415acc93d800487c7c76308c59", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "size": "0xcb90", + "stateRoot": "0xafbb8743c0a5f4740e322217cb1f2780ee5c57c32bcd04e9256b09efc1a70568", + "timestamp": "0x6661ab8b", + "totalDifficulty": "0xc70d815d562d3cfa955", + "transactions": [ + "0x589956b75d19dbaf9911f246c23d4b3327ef234872ec1931c419041b23eb5b41", + "0x4d3793f20c25979bd329cafdd889ba6be015cfc999acce8642d6e757b5192e93", + "0x5ba5618ca5a14bab50862255dc69726a498346f9832bd0fd1394e8834e56790b", + "0x6df9678f350db7e30afc930b7246bf1c144b9acb7fd1d25d7e107d550ed5a061", + "0xb8f48ff2876cc393725ea4162421754dfb74ff2364a12d4d3de2c6269f1958c7", + "0x2e5cf7c0607025038b6ccd871dc9ce85af686fd5fa2c82e605198af9afa92cca", + "0x307fb855836feff5d8d0969fa4a44d3c6ae31d335da6577f48f9496d6fe9e0b9", + "0x1362bed1aa8a30d28b7b76c35c2a8601b257058beffa9490dcb20de12bcb15b2", + "0x234c7cc346c204022b2e5ead6d2e8c02317aeb0ec5ca82bd97c2b5d5e59a280b", + ], + "transactionsRoot": "0xc21a4d667b5f841538430b1e2c002c598f2178628ad1d61ea2fda462d1216607", + "uncles": [], + "withdrawals": [ + { + "address": "0xea97dc2523c0479484076660f150833e264c41e9", + "amount": "0x11b6d8c", + "index": "0x2dbe454", + "validatorIndex": "0x10f646" + }, + { + "address": "0xb3e84b6c6409826dc45432b655d8c9489a14a0d7", + "amount": "0x11b4ce2", + "index": "0x2dbe455", + "validatorIndex": "0x10f647" + }, + { + "address": "0x7e2a2fa2a064f693f0a55c5639476d913ff12d05", + "amount": "0x11ad733", + "index": "0x2dbe456", + "validatorIndex": "0x10f648" + }, + + ], + "withdrawalsRoot": "0x2914fa2f5ed93880ed45b58e8f6d14f20c645988400d83c59109964e2053fe1a" + } +}; + +export const receiptMockResult = { + "jsonrpc": "2.0", + "id": 1, + "result": { + "blockHash": "0xf4ad699b98241caf3930779b7d919a77f1727e67cef6ed1ce2a4c655ba812d54", + "blockNumber": "0x131ad35", + // eslint-disable-next-line no-null/no-null + "contractAddress": null, + "cumulativeGasUsed": "0x8cae7a", + "effectiveGasPrice": "0x4c9bc2d65", + "from": "0xab6fd3a7c6ce9db945889cd018e028e055f3bc2e", + "gasUsed": "0xa145", + "logs": [ + { + "address": "0xdac17f958d2ee523a2206206994597c13d831ec7", + "blockHash": "0xf4ad699b98241caf3930779b7d919a77f1727e67cef6ed1ce2a4c655ba812d54", + "blockNumber": "0x131ad35", + "data": "0x000000000000000000000000000000000000000000000000000000000016e360", + "logIndex": "0xdf", + "removed": false, + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x000000000000000000000000ab6fd3a7c6ce9db945889cd018e028e055f3bc2e", + "0x00000000000000000000000051112f9f08a2174fe3fc96aad8f07e82d1cccd00" + ], + "transactionHash": "0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f", + "transactionIndex": "0x82" + } + ], + "logsBloom": "0x00000000000000000000000002000000000000000000000000000000004000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000400000000000100000000000000000000000000080000000000000000000040000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000400000000000000000000000", + "status": "0x1", + "to": "0xdac17f958d2ee523a2206206994597c13d831ec7", + "transactionHash": "0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f", + "transactionIndex": "0x82", + "type": "0x2" + } +}; \ No newline at end of file diff --git a/tools/web3-plugin-example/test/unit/middleware.test.ts b/tools/web3-plugin-example/test/unit/request_manager_middleware.test.ts similarity index 100% rename from tools/web3-plugin-example/test/unit/middleware.test.ts rename to tools/web3-plugin-example/test/unit/request_manager_middleware.test.ts diff --git a/tools/web3-plugin-example/test/unit/transaction_middleware.test.ts b/tools/web3-plugin-example/test/unit/transaction_middleware.test.ts new file mode 100644 index 00000000000..2009e028283 --- /dev/null +++ b/tools/web3-plugin-example/test/unit/transaction_middleware.test.ts @@ -0,0 +1,76 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ + +import { Web3, Transaction } from 'web3'; +import { TransactionMiddlewarePlugin } from '../../src/transaction_middleware_plugin'; +import { blockMockResult, receiptMockResult } from './fixtures/transactions_data'; + +describe('Transaction Middleware', () => { + + // This will allow Transaction modification before signing and gas estimations + it('should modify transaction before signing', async () => { + const web3 = new Web3('http://127.0.0.1:8545'); + const plugin = new TransactionMiddlewarePlugin(); + + /// Mock block starts - Mock web3 internal calls for test + let blockNum = 1000; + + web3.requestManager.send = jest.fn(async (request) => { + blockNum += 1; + + if(request.method === 'eth_getBlockByNumber'){ + + return Promise.resolve(blockMockResult.result); + } + if(request.method === 'eth_call'){ + + return Promise.resolve("0x"); + } + if(request.method === 'eth_blockNumber'){ + + return Promise.resolve(blockNum.toString(16)); + } + if(request.method === 'eth_sendTransaction'){ + + // Test that middleware modified transaction + // eslint-disable-next-line jest/no-conditional-expect + expect((request.params as any)[0].data).toBe("0x123"); + + return Promise.resolve("0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f"); + } + if (request.method === 'eth_getTransactionReceipt') { + return Promise.resolve(receiptMockResult.result); + } + + return Promise.resolve("Unknown Request" as any); + }); + + /// Mock block ends here + + web3.registerPlugin(plugin); + + const transaction: Transaction = { + from: '0x6E599DA0bfF7A6598AC1224E4985430Bf16458a4', + to: '0x6f1DF96865D09d21e8f3f9a7fbA3b17A11c7C53C', + value: '0x1', + data: '0x1' + }; + + await web3.eth.sendTransaction(transaction as any); + + }); +}); From 7a51c33315fea9bc3b8a7daa0d5d4f08dcac12af Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 11 Jun 2024 09:59:16 -0400 Subject: [PATCH 099/186] add test coverage to web3-core (#7091) * add test coverage to web3-core * make types compitable * update * update * update types * update types * update * update tests --- .../web3-core/src/web3_request_manager.ts | 10 -- packages/web3-core/src/web3_subscriptions.ts | 11 -- .../unit/fixtures/custom_transaction_type.ts | 73 +++++++++++ .../unit/fixtures/example_subscription.ts | 5 +- .../fixtures/example_subscription_build.ts | 28 +++++ .../web3-core/test/unit/formatters.test.ts | 118 +++++++++++++++++- .../web3-core/test/unit/web3_config.test.ts | 80 +++++++++++- .../web3-core/test/unit/web3_context.test.ts | 115 ++++++++++++++++- .../test/unit/web3_request_manager.test.ts | 60 +++++++++ .../test/unit/web3_subscription.test.ts | 92 +++++++++++++- .../unit/web3_subscription_manager.test.ts | 44 ++++++- packages/web3-types/src/json_rpc_types.ts | 6 +- 12 files changed, 611 insertions(+), 31 deletions(-) create mode 100644 packages/web3-core/test/unit/fixtures/custom_transaction_type.ts create mode 100644 packages/web3-core/test/unit/fixtures/example_subscription_build.ts diff --git a/packages/web3-core/src/web3_request_manager.ts b/packages/web3-core/src/web3_request_manager.ts index 1cbe9377988..21783229a5f 100644 --- a/packages/web3-core/src/web3_request_manager.ts +++ b/packages/web3-core/src/web3_request_manager.ts @@ -429,7 +429,6 @@ export class Web3RequestManager< ) { return this._buildResponse(payload, response, error); } - if (jsonRpc.isBatchRequest(payload) && !Array.isArray(response)) { throw new ResponseError(response, 'Got normal response for a batch request.'); } @@ -438,15 +437,6 @@ export class Web3RequestManager< throw new ResponseError(response, 'Got batch response for a normal request.'); } - if ( - (jsonRpc.isResponseWithError(response) || jsonRpc.isResponseWithResult(response)) && - !jsonRpc.isBatchRequest(payload) - ) { - if (response.id && payload.id !== response.id) { - throw new InvalidResponseError(response); - } - } - throw new ResponseError(response, 'Invalid response'); } diff --git a/packages/web3-core/src/web3_subscriptions.ts b/packages/web3-core/src/web3_subscriptions.ts index 3cf4cee9f50..21cd4fe21fe 100644 --- a/packages/web3-core/src/web3_subscriptions.ts +++ b/packages/web3-core/src/web3_subscriptions.ts @@ -30,7 +30,6 @@ import { Web3APISpec, } from 'web3-types'; import { jsonRpc } from 'web3-utils'; -import { SubscriptionError } from 'web3-errors'; // eslint-disable-next-line import/no-cycle import { Web3SubscriptionManager } from './web3_subscription_manager.js'; @@ -82,16 +81,6 @@ export abstract class Web3Subscription< super(); const { requestManager } = options as { requestManager: Web3RequestManager }; const { subscriptionManager } = options as { subscriptionManager: Web3SubscriptionManager }; - if (requestManager && subscriptionManager) { - throw new SubscriptionError( - 'Only requestManager or subscriptionManager should be provided at Subscription constructor', - ); - } - if (!requestManager && !subscriptionManager) { - throw new SubscriptionError( - 'Either requestManager or subscriptionManager should be provided at Subscription constructor', - ); - } if (requestManager) { // eslint-disable-next-line deprecation/deprecation this._subscriptionManager = new Web3SubscriptionManager(requestManager, {}, true); diff --git a/packages/web3-core/test/unit/fixtures/custom_transaction_type.ts b/packages/web3-core/test/unit/fixtures/custom_transaction_type.ts new file mode 100644 index 00000000000..12e4789a92d --- /dev/null +++ b/packages/web3-core/test/unit/fixtures/custom_transaction_type.ts @@ -0,0 +1,73 @@ +/* +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 { + BaseTransaction, + TxValuesArray, + AccessListEIP2930ValuesArray, + FeeMarketEIP1559ValuesArray, + JsonTx, +} from 'web3-eth-accounts'; + +export class CustomTransactionType extends BaseTransaction { + // eslint-disable-next-line class-methods-use-this + public getUpfrontCost(): bigint { + throw new Error('Method not implemented.'); + } + // eslint-disable-next-line class-methods-use-this + public raw(): TxValuesArray | AccessListEIP2930ValuesArray | FeeMarketEIP1559ValuesArray { + throw new Error('Method not implemented.'); + } + // eslint-disable-next-line class-methods-use-this + public serialize(): Uint8Array { + throw new Error('Method not implemented.'); + } + public getMessageToSign(hashMessage: false): Uint8Array | Uint8Array[]; + public getMessageToSign(hashMessage?: true | undefined): Uint8Array; + // eslint-disable-next-line class-methods-use-this + public getMessageToSign(): Uint8Array | Uint8Array[] { + throw new Error('Method not implemented.'); + } + // eslint-disable-next-line class-methods-use-this + public hash(): Uint8Array { + throw new Error('Method not implemented.'); + } + // eslint-disable-next-line class-methods-use-this + public getMessageToVerifySignature(): Uint8Array { + throw new Error('Method not implemented.'); + } + // eslint-disable-next-line class-methods-use-this + public getSenderPublicKey(): Uint8Array { + throw new Error('Method not implemented.'); + } + // eslint-disable-next-line class-methods-use-this + public toJSON(): JsonTx { + throw new Error('Method not implemented.'); + } + // eslint-disable-next-line class-methods-use-this + protected _processSignature(): unknown { + throw new Error('Method not implemented.'); + } + // eslint-disable-next-line @typescript-eslint/explicit-member-accessibility, class-methods-use-this + public errorStr(): string { + throw new Error('Method not implemented.'); + } + // eslint-disable-next-line class-methods-use-this + protected _errorMsg(): string { + throw new Error('Method not implemented.'); + } +} diff --git a/packages/web3-core/test/unit/fixtures/example_subscription.ts b/packages/web3-core/test/unit/fixtures/example_subscription.ts index ee23ce2311e..019d4ccccc9 100644 --- a/packages/web3-core/test/unit/fixtures/example_subscription.ts +++ b/packages/web3-core/test/unit/fixtures/example_subscription.ts @@ -14,7 +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 { DataFormat } from 'web3-types'; import { Web3Subscription } from '../../../src'; export class ExampleSubscription extends Web3Subscription< @@ -26,4 +26,7 @@ export class ExampleSubscription extends Web3Subscription< protected _buildSubscriptionParams() { return ['newHeads']; } + public getReturnFormat(): DataFormat { + return this.returnFormat; + } } diff --git a/packages/web3-core/test/unit/fixtures/example_subscription_build.ts b/packages/web3-core/test/unit/fixtures/example_subscription_build.ts new file mode 100644 index 00000000000..88fea953349 --- /dev/null +++ b/packages/web3-core/test/unit/fixtures/example_subscription_build.ts @@ -0,0 +1,28 @@ +/* +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 { Web3Subscription } from '../../../src'; + +// subscription class that exposes buildSubscriptionParams +export class BuildSubscription extends Web3Subscription< + { data: string }, + { param1: string }, + { eth_subscribe: (newHeads: string) => void } +> { + public buildSubscriptionParams() { + this._buildSubscriptionParams(); + } +} diff --git a/packages/web3-core/test/unit/formatters.test.ts b/packages/web3-core/test/unit/formatters.test.ts index 105fb4fcf45..022d87f65cb 100644 --- a/packages/web3-core/test/unit/formatters.test.ts +++ b/packages/web3-core/test/unit/formatters.test.ts @@ -16,8 +16,9 @@ along with web3.js. If not, see . */ import * as utils from 'web3-utils'; -import { BlockTags } from 'web3-types'; +import { BlockTags, TransactionInput, Filter } from 'web3-types'; import { Iban } from 'web3-eth-iban'; +import { FormatterError } from 'web3-errors'; import { inputAddressFormatter, inputBlockNumberFormatter, @@ -268,6 +269,121 @@ describe('formatters', () => { ); }); + describe('inputCallFormatter', () => { + let txInput: any; + + beforeEach(() => { + jest.spyOn(utils, 'isAddress').mockReturnValue(true); + txInput = { + to: '0xabcd', + }; + }); + + it('should format "to" address if provided', () => { + expect(formatters.inputCallFormatter({ ...txInput, to: '0xABCD' })).toEqual( + expect.objectContaining({ to: '0xabcd' }), + ); + }); + + it('should format "from" if defaultAddress is provided', () => { + expect(formatters.inputCallFormatter({ ...txInput, to: '0xABCD' }, '0xABCDE')).toEqual( + expect.objectContaining({ from: '0xabcde', to: '0xabcd' }), + ); + }); + }); + + describe('inputTransactionFormatter', () => { + let txInput: any; + + beforeEach(() => { + jest.spyOn(utils, 'isAddress').mockReturnValue(true); + txInput = { + to: '0xabcd', + }; + }); + it('should format and populate "from"', () => { + expect( + formatters.inputTransactionFormatter({ ...txInput, to: '0xabcd', from: '0xABCDE' }), + ).toEqual(expect.objectContaining({ from: '0xabcde', to: '0xabcd' })); + }); + + it('should throw an error when from is undefined', () => { + expect(() => formatters.inputTransactionFormatter({ ...txInput })).toThrow( + new FormatterError('The send transactions "from" field must be defined!'), + ); + }); + }); + + describe('outputTransactionFormatter', () => { + it('should correctly format blockNumber from hex to number', () => { + const txInput: TransactionInput = { + to: '0x1234567890abcdef', + from: '0xabcdef1234567890', + gas: '0x123456', + gasPrice: '0x987654321', + nonce: '0x1', + value: '0x9876543210', + blockNumber: '0x123', + transactionIndex: '0x1', + maxFeePerGas: '0x87654321', + maxPriorityFeePerGas: '0x7654321', + type: '0x1', + }; + + const formattedTxOutput = formatters.outputTransactionFormatter(txInput); + // should return the mocked values; + expect(formattedTxOutput.blockNumber).toBe(123); + expect(formattedTxOutput.to).toBe('toChecksumAddress'); + expect(formattedTxOutput.from).toBe('toChecksumAddress'); + expect(formattedTxOutput.gas).toBe(123); + expect(formattedTxOutput.nonce).toBe(123); + expect(formattedTxOutput.transactionIndex).toBe(123); + expect(formattedTxOutput.value).toBe(12345); + expect(formattedTxOutput.maxFeePerGas).toBe(12345); + expect(formattedTxOutput.maxPriorityFeePerGas).toBe(12345); + expect(formattedTxOutput.type).toBe(123); + }); + + it('should make "to" property undefined', () => { + const txInput = { gas: '0x', nonce: '1', value: '0x' }; + const formattedTxOutput = formatters.outputTransactionFormatter(txInput); + + expect(formattedTxOutput.to).toBeUndefined(); + }); + }); + + describe('inputLogFormatter', () => { + beforeAll(() => { + const actualUtils = jest.requireActual('web3-utils'); + jest.spyOn(utils, 'mergeDeep').mockImplementation(actualUtils.mergeDeep); + }); + it('should correctly format a filter with all fields provided', () => { + const filter: Filter = { + fromBlock: '0x1', + toBlock: '0x2', + address: '0x1234567890abcdef1234567890abcdef12345678', + topics: ['0x123', ['0x456', '0x789']], + }; + + const formattedFilter = formatters.inputLogFormatter(filter); + + expect(formattedFilter.fromBlock).toBe('0x1'); + expect(formattedFilter.toBlock).toBe('0x2'); + expect(formattedFilter.address).toBe('0x1234567890abcdef1234567890abcdef12345678'); + expect(formattedFilter.topics).toEqual(['0x123', ['0x456', '0x789']]); + }); + it('should correctly format a filter with no fromBlock', () => { + const filter: Filter = { + address: ['0x123', '0x222'], + }; + + const formattedFilter = formatters.inputLogFormatter(filter); + + expect(formattedFilter.fromBlock).toBe('latest'); + expect(formattedFilter.address).toEqual(['0x123', '0x222']); + }); + }); + describe('outputLogFormatter', () => { it('should set log id from "blockHash", "transactionHash" and "logIndex"', () => { const result = outputLogFormatter({ diff --git a/packages/web3-core/test/unit/web3_config.test.ts b/packages/web3-core/test/unit/web3_config.test.ts index 0391eec851a..bd250d6386a 100644 --- a/packages/web3-core/test/unit/web3_config.test.ts +++ b/packages/web3-core/test/unit/web3_config.test.ts @@ -16,7 +16,8 @@ along with web3.js. If not, see . */ import { toHex } from 'web3-utils'; -import { DEFAULT_RETURN_FORMAT } from 'web3-types'; +import { DEFAULT_RETURN_FORMAT, Hardfork, ValidChains } from 'web3-types'; +import { ConfigHardforkMismatchError, ConfigChainMismatchError } from 'web3-errors'; import { Web3Config, Web3ConfigEvent } from '../../src/web3_config'; class MyConfigObject extends Web3Config {} @@ -46,6 +47,8 @@ const defaultConfig = { defaultTransactionType: '0x2', defaultMaxPriorityFeePerGas: toHex(2500000000), defaultReturnFormat: DEFAULT_RETURN_FORMAT, + transactionBuilder: undefined, + transactionTypeParser: undefined, }; const setValue = { string: 'newValue', @@ -123,6 +126,81 @@ describe('Web3Config', () => { ); }); + it('should throw when val does not match config.defaultCommon.defaultHardFork', () => { + const obj = new MyConfigObject(); + const defaultCommon = { + defaultHardfork: 'london' as Hardfork, + customChain: { + networkId: 1, + chainId: 1, + }, + }; + obj.setConfig({ + defaultCommon, + }); + const newDefaultCommon = { + hardfork: 'berlin' as Hardfork, + customChain: { + networkId: 1, + chainId: 1, + }, + }; + expect(() => { + obj.defaultCommon = newDefaultCommon; + }).toThrow( + new ConfigHardforkMismatchError( + defaultCommon.defaultHardfork, + newDefaultCommon.hardfork, + ), + ); + }); + + it('defaulthardfork should throw when val does not match config.defaultCommon.hardfork', () => { + const obj = new MyConfigObject(); + const defaultCommon = { + hardfork: 'london' as Hardfork, + customChain: { + networkId: 1, + chainId: 1, + }, + }; + const hardfork = 'berlin'; + obj.setConfig({ + defaultCommon, + }); + expect(() => { + obj.defaultHardfork = hardfork; + }).toThrow(new ConfigHardforkMismatchError(defaultCommon.hardfork, hardfork)); + }); + + it('should throw when val does not match config.defaultChain', () => { + const obj = new MyConfigObject(); + const defaultCommon = { + defaultHardfork: 'london' as Hardfork, + customChain: { + networkId: 1, + chainId: 1, + }, + defaultChain: 'mainnet', + }; + obj.setConfig({ + defaultCommon, + }); + const newDefaultCommon = { + hardfork: 'london' as Hardfork, + customChain: { + networkId: 1, + chainId: 1, + }, + baseChain: 'sepolia' as ValidChains, + }; + expect(() => { + obj.defaultCommon = newDefaultCommon; + }).toThrow( + new ConfigChainMismatchError(defaultCommon.defaultChain, newDefaultCommon.baseChain), + ); + }); + it('Updating transactionPollingInterval should update transactionReceiptPollingInterval and transactionConfirmationPollingInterval', () => { const obj = new MyConfigObject(); const configChange = jest.fn(); diff --git a/packages/web3-core/test/unit/web3_context.test.ts b/packages/web3-core/test/unit/web3_context.test.ts index c235a06cb83..b50c98e8661 100644 --- a/packages/web3-core/test/unit/web3_context.test.ts +++ b/packages/web3-core/test/unit/web3_context.test.ts @@ -24,10 +24,14 @@ import { JsonRpcResponse, Web3APIMethod, Web3APIReturnType, + Web3AccountProvider, + Web3BaseWalletAccount, + Web3BaseWallet, } from 'web3-types'; -import { Web3Context, Web3PluginBase } from '../../src/web3_context'; +import { Web3Context, Web3PluginBase, Web3ContextObject } from '../../src/web3_context'; import { Web3RequestManager } from '../../src/web3_request_manager'; import { RequestManagerMiddleware } from '../../src/types'; +import { CustomTransactionType } from './fixtures/custom_transaction_type'; // eslint-disable-next-line @typescript-eslint/ban-types class Context1 extends Web3Context<{}> {} @@ -64,13 +68,30 @@ describe('Web3Context', () => { expect(context.currentProvider).toBeInstanceOf(HttpProvider); }); + it('should return undefined when getting givenprovider', () => { + const context = new Web3Context('http://test.com'); + expect(context.givenProvider).toBeUndefined(); + }); it('should set return current provider for the request manager', () => { const context = new Web3Context('http://test.com'); - context.currentProvider = 'http://test/abc'; expect(context.currentProvider).toBeInstanceOf(HttpProvider); }); + it('should set httpProvider', () => { + const context = new Web3Context(); + const url = 'http://test/abc'; + context.setProvider(url); + const httpProvider = new HttpProvider(url); + expect(context.provider).toEqual(httpProvider); + }); + + it('get batch request', () => { + const context = new Web3Context(); + const BatchRequestClass = context.BatchRequest; + + expect(new BatchRequestClass()).toBeInstanceOf(context.BatchRequest); + }); it('should set middleware for the request manager', () => { const context = new Web3Context('http://test.com'); @@ -92,6 +113,82 @@ describe('Web3Context', () => { context.setRequestManagerMiddleware(middleware); expect(context.requestManager.middleware).toEqual(middleware); }); + it('should instantiate a new Web3Context object with provided context object', () => { + const config = { defaultNetworkId: 'my-network-id', defaultHardfork: 'my-fork' }; + const context = { + provider: 'http://test.com', + config, + } as Web3ContextObject; + const newContext = Web3Context.fromContextObject(context); + expect(newContext.currentProvider).toBeInstanceOf(HttpProvider); + expect(newContext.requestManager).toBeInstanceOf(Web3RequestManager); + expect(newContext.config.defaultHardfork).toEqual(config.defaultHardfork); + expect(newContext.config.defaultNetworkId).toEqual(config.defaultNetworkId); + }); + + describe('accountsProvider', () => { + const createAccountProvider = (): Web3AccountProvider => { + const accountProvider = { + privateKeyToAccount: jest.fn().mockImplementation(() => { + return ''; + }), + decrypt: jest.fn(), + create: jest.fn().mockImplementation(() => { + return ''; + }), + }; + return accountProvider; + }; + const accountProvider = createAccountProvider(); + + class WalletExample< + T extends Web3BaseWalletAccount = Web3BaseWalletAccount, + > extends Web3BaseWallet { + public create = jest.fn(() => this); + public add = jest.fn(() => this); + public get = jest.fn(() => { + return { + address: 'mockAddress', + privateKey: 'mockPrivateKey', + signTransaction: jest.fn(), + sign: jest.fn(), + encrypt: jest.fn(), + } as unknown as T; + }); + public remove = jest.fn(() => true); + public clear = jest.fn(() => this); + public encrypt = jest.fn(async () => Promise.resolve([])); + public decrypt = jest.fn(); + public save = jest.fn(); + public load = jest.fn(); + } + + const wallet = new WalletExample(accountProvider); + it('should set wallet in context', () => { + const context = new Web3Context({ + provider: 'http://test.com', + wallet, + }); + + expect(context.wallet).toEqual(wallet); + }); + it('should set the Accountsprovider when creating new context', () => { + const context = new Web3Context({ + provider: 'http://test.com', + accountProvider, + }); + + expect(context.accountProvider).toEqual(accountProvider); + }); + + it('should set wallet', () => { + const context = new Web3Context({ + provider: 'http://test.com', + wallet, + }); + expect(context.wallet).toEqual(wallet); + }); + }); }); describe('getContextObject', () => { @@ -255,6 +352,20 @@ describe('Web3Context', () => { }); describe('registerPlugin', () => { + it('should create a new type using registerNewTransactionType on a custom plugin', () => { + const context = new Context1('http://test/abc'); + const pluginNamespace = 'plugin'; + + class Plugin extends Web3PluginBase { + public constructor() { + super(); + this.registerNewTransactionType(3, CustomTransactionType); + } + public pluginNamespace = pluginNamespace; + } + + expect(() => context.registerPlugin(new Plugin())).not.toThrow(); + }); it('should throw ExistingPluginNamespaceError', () => { const context = new Context1('http://test/abc'); const pluginNamespace = 'plugin'; 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 2db8c010fd8..9bbad51fdc9 100644 --- a/packages/web3-core/test/unit/web3_request_manager.test.ts +++ b/packages/web3-core/test/unit/web3_request_manager.test.ts @@ -730,6 +730,66 @@ describe('Web3RequestManager', () => { expect(myProvider.request).toHaveBeenCalledTimes(1); expect(myProvider.request).toHaveBeenCalledWith(payload); }); + it('should throw an error when payload batch request and response is not an array', async () => { + jest.spyOn(jsonRpc, 'toPayload').mockReturnValue([ + { method: 'my_method', params: [], id: 1, jsonrpc: '2.0' }, + ]); + const manager = new Web3RequestManager(); + + const pr = new Promise(resolve => { + resolve({ response: 'random' }); + }); + const myProvider = { + request: jest.fn().mockImplementation(async () => pr), + } as any; + manager.setProvider(myProvider); + + await expect(manager.send(request)).rejects.toThrow(); + + jest.clearAllMocks(); + }); + it('should throw an error when payload batch request is an array and response is not', async () => { + jest.spyOn(jsonRpc, 'toPayload').mockReturnValue({ + method: 'my_method', + params: [], + id: 1, + jsonrpc: '2.0', + }); + const manager = new Web3RequestManager(); + + const pr = new Promise(resolve => { + resolve([{ response: 'unknown response' }, { response: 'unknown response' }]); + }); + const myProvider = { + request: jest.fn().mockImplementation(async () => pr), + } as any; + manager.setProvider(myProvider); + + await expect(manager.send(request)).rejects.toThrow(); + + jest.clearAllMocks(); + }); + it('should throw an when invalid response', async () => { + jest.spyOn(jsonRpc, 'toPayload').mockReturnValue({ + method: 'my_method', + params: [], + id: 1, + jsonrpc: '2.0', + }); + const manager = new Web3RequestManager(); + + const pr = new Promise(resolve => { + resolve({ response: 'unknown response' }); + }); + const myProvider = { + request: jest.fn().mockImplementation(async () => pr), + } as any; + manager.setProvider(myProvider); + + await expect(manager.send(request)).rejects.toThrow(); + + jest.clearAllMocks(); + }); }); describe('legacy-request-provider', () => { diff --git a/packages/web3-core/test/unit/web3_subscription.test.ts b/packages/web3-core/test/unit/web3_subscription.test.ts index cab940b0f00..f04a8850af1 100644 --- a/packages/web3-core/test/unit/web3_subscription.test.ts +++ b/packages/web3-core/test/unit/web3_subscription.test.ts @@ -14,9 +14,10 @@ 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 { JsonRpcNotification, Log, DEFAULT_RETURN_FORMAT } from 'web3-types'; import { Web3SubscriptionManager } from '../../src'; import { ExampleSubscription } from './fixtures/example_subscription'; +import { BuildSubscription } from './fixtures/example_subscription_build'; const subscriptions = { example: ExampleSubscription as never }; @@ -81,6 +82,10 @@ describe('Web3Subscription', () => { expect.any(Function), ); }); + + it('should return returnFormat', () => { + expect(sub.getReturnFormat()).toBe(DEFAULT_RETURN_FORMAT); + }); }); describe('unsubscribe', () => { @@ -89,6 +94,9 @@ describe('Web3Subscription', () => { sub['_id'] = 'sub-id'; subscriptionManager.subscriptions.set('sub-id', sub); }); + afterEach(() => { + jest.clearAllMocks(); + }); it('should invoke request manager to unsubscribe', async () => { await sub.unsubscribe(); @@ -105,6 +113,28 @@ describe('Web3Subscription', () => { await sub.unsubscribe(); expect(sub.id).toBeUndefined(); }); + it('should only call removeSubscription once after calling unsubscribe twice', async () => { + jest.spyOn(subscriptionManager, 'removeSubscription').mockImplementation(); + const newSub = new ExampleSubscription({ param1: 'value' }, { subscriptionManager }); + expect(newSub.id).toBeUndefined(); + await newSub.unsubscribe(); + expect(subscriptionManager.removeSubscription).toHaveBeenCalledTimes(0); + }); + }); + + describe('resubscribe', () => { + beforeEach(() => { + sub = new ExampleSubscription({ param1: 'value' }, { subscriptionManager }); + sub['_id'] = 'sub-id'; + subscriptionManager.subscriptions.set('sub-id', sub); + }); + it('should resubscribe', async () => { + jest.spyOn(sub, 'subscribe').mockImplementation(); + jest.spyOn(sub, 'unsubscribe').mockImplementation(); + await sub.resubscribe(); + expect(sub.subscribe).toHaveBeenCalledTimes(1); + expect(sub.unsubscribe).toHaveBeenCalledTimes(1); + }); }); }); @@ -156,6 +186,15 @@ describe('Web3Subscription without subscription manager - (deprecated)', () => { expect.any(Function), ); }); + it('should listen on error', () => { + const error = new Error(''); + const errorSpy = jest.fn(); + sub.on('error', errorSpy); + sub._processSubscriptionError(error); + + expect(errorSpy).toHaveBeenCalledTimes(1); + expect(errorSpy).toHaveBeenCalledWith(error); + }); }); describe('unsubscribe', () => { @@ -181,4 +220,55 @@ describe('Web3Subscription without subscription manager - (deprecated)', () => { expect(sub.id).toBeUndefined(); }); }); + + describe('lastblock', () => { + let subscriptionManager: Web3SubscriptionManager; + beforeEach(() => { + subscriptionManager = new Web3SubscriptionManager(requestManager, subscriptions); + sub = new ExampleSubscription({ param1: 'value' }, { subscriptionManager }); + sub['_id'] = 'sub-id'; + }); + it('should get last block', () => { + expect(sub.lastBlock).toBeUndefined(); + }); + }); + + describe('processSubscriptionData', () => { + let subscriptionManager: Web3SubscriptionManager; + beforeEach(() => { + subscriptionManager = new Web3SubscriptionManager(requestManager, subscriptions); + sub = new ExampleSubscription({ param1: 'value' }, { subscriptionManager }); + sub['_id'] = 'sub-id'; + }); + afterEach(() => { + jest.clearAllMocks(); + }); + it('should call _processSubscriptionResult when data is type JsonRpcNotification', () => { + const responseWithNotification: JsonRpcNotification = { + jsonrpc: '2.0', + params: { + subscription: '', + result: { id: '' }, + }, + method: '', + }; + jest.spyOn(sub, '_processSubscriptionResult').mockReturnValue(); + sub.processSubscriptionData(responseWithNotification); + expect(sub._processSubscriptionResult).toHaveBeenCalled(); + }); + }); + + describe('buildSubscriptionParams', () => { + let subscriptionManager: Web3SubscriptionManager; + let buildSub: BuildSubscription; + beforeEach(() => { + buildSub = new BuildSubscription({ param1: 'value' }, { subscriptionManager }); + }); + + it('should _buildSubscriptionParams', () => { + expect(() => { + buildSub.buildSubscriptionParams(); + }).toThrow(); + }); + }); }); diff --git a/packages/web3-core/test/unit/web3_subscription_manager.test.ts b/packages/web3-core/test/unit/web3_subscription_manager.test.ts index 403719b292a..fc671b35a7a 100644 --- a/packages/web3-core/test/unit/web3_subscription_manager.test.ts +++ b/packages/web3-core/test/unit/web3_subscription_manager.test.ts @@ -71,7 +71,6 @@ describe('Web3SubscriptionManager', () => { expect.any(Function), ); }); - it('should register the subscription types', () => { subManager = new Web3SubscriptionManager(requestManager, { example: ExampleSubscription as never, @@ -150,6 +149,12 @@ describe('Web3SubscriptionManager', () => { 'Subscription with id "123" already exists', ); }); + it('should error when there is no sub id', async () => { + (sub as any).id = undefined; + // const subManagers = new Web3SubscriptionManager(requestManager, subscriptions) as any + // // eslint-disable-next-line @typescript-eslint/no-unsafe-call + await expect(subManager.addSubscription(sub)).rejects.toThrow(); + }); it('should try to subscribe the subscription', async () => { sub = new ExampleSubscription( @@ -206,7 +211,18 @@ describe('Web3SubscriptionManager', () => { ); }); - it('should try to unsubscribe the subscription', async () => { + it('should unsubscribe to the subscription by id', async () => { + await subManager.unsubscribe(({ id }) => { + if (id === '123') { + return true; + } + return false; + }); + + expect(subManager.subscriptions).toEqual(new Map()); + }); + + it('should unsubscribe in the subscription under the condition', async () => { await subManager.removeSubscription(sub); expect(sub.sendUnsubscribeRequest).toHaveBeenCalledTimes(1); @@ -221,4 +237,28 @@ describe('Web3SubscriptionManager', () => { expect(subManager.subscriptions).toEqual(new Map()); }); }); + describe('messageListener', () => { + let subscription: ExampleSubscription; + + beforeEach(() => { + subManager = new Web3SubscriptionManager(requestManager, subscriptions); + jest.spyOn(subManager, 'supportsSubscriptions').mockReturnValue(true); + subscription = new ExampleSubscription( + { param1: 'param1' }, + { subscriptionManager: subManager }, + ); + (subscription as any).id = '123'; + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + it('should error when no data is provided', () => { + const subManagers = new Web3SubscriptionManager(requestManager, subscriptions) as any; + expect(() => { + // eslint-disable-next-line @typescript-eslint/no-unsafe-call + subManagers.messageListener(); + }).toThrow(); + }); + }); }); diff --git a/packages/web3-types/src/json_rpc_types.ts b/packages/web3-types/src/json_rpc_types.ts index a361d018700..9cb98648dc8 100644 --- a/packages/web3-types/src/json_rpc_types.ts +++ b/packages/web3-types/src/json_rpc_types.ts @@ -55,8 +55,9 @@ export interface JsonRpcNotification { readonly jsonrpc: JsonRpcIdentifier; readonly method: string; // for subscription readonly params: SubscriptionParams; // for subscription results - readonly result: never; + readonly result?: never; readonly data?: never; + readonly error?: never; } export interface JsonRpcSubscriptionResult { @@ -91,4 +92,5 @@ export type JsonRpcBatchResponse export type JsonRpcResponse = | JsonRpcResponseWithError | JsonRpcResponseWithResult - | JsonRpcBatchResponse; + | JsonRpcBatchResponse + | JsonRpcNotification; From 7f8e504bae5f4c02b8cf1cc09b41a1c3757ddc95 Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Wed, 12 Jun 2024 12:09:47 -0700 Subject: [PATCH 100/186] fix(docs): account-transaction-tutorial (#7094) * fix(docs): account-transaction-tutorial * Fix broken links --- docs/docs/guides/wallet/local_wallet.md | 118 --- docs/docs/guides/wallet/metamask.md | 2 +- docs/docs/guides/wallet/node_wallet.md | 114 --- docs/docs/guides/wallet/promi_event.md | 90 --- docs/docs/guides/wallet/signing.md | 131 ---- docs/docs/guides/wallet/transactions.md | 678 +++++++++++------- .../wallet/web3_modal_guide/_category_.yml | 2 +- 7 files changed, 405 insertions(+), 730 deletions(-) delete mode 100644 docs/docs/guides/wallet/local_wallet.md delete mode 100644 docs/docs/guides/wallet/node_wallet.md delete mode 100644 docs/docs/guides/wallet/promi_event.md delete mode 100644 docs/docs/guides/wallet/signing.md diff --git a/docs/docs/guides/wallet/local_wallet.md b/docs/docs/guides/wallet/local_wallet.md deleted file mode 100644 index cfabf725ccc..00000000000 --- a/docs/docs/guides/wallet/local_wallet.md +++ /dev/null @@ -1,118 +0,0 @@ ---- -sidebar_position: 3 -sidebar_label: 'Tutorial: Local Wallets' ---- - -# Local Wallets - -Local wallets are an in-memory [wallet](/api/web3-eth-accounts/class/Wallet/) that can hold multiple accounts. -Wallets are a convenient way to sign and send transactions in web3.js - -:::warning -If used within the browser, wallets are not saved anywhere and disappear when the page is refreshed. -If used within your application, wallets will disappear after the program is completed. -::: - -## Create a `Wallet` with a random account - -```ts title= Create Wallet with random account -import { Web3 } from "web3"; - -const web3 = new Web3(/* PROVIDER */); - -/* - * creates wallet with 1 account - * @param: number of accounts you want to create within the wallet -*/ -const wallet = web3.eth.accounts.wallet.create(1); -/* ↳ -Wallet(1) [ - { - address: '0xE0A7859c5454B369Ab8089890A11efcB458eA13c', - privateKey: '0x0199829f0c95213670d48aa48abdb36c16c2ec3d11fe20e1fa8c0270ffb64110', - signTransaction: [Function: signTransaction], - sign: [Function: sign], - encrypt: [Function: encrypt] - }, - _accountProvider: { - create: [Function: createWithContext], - privateKeyToAccount: [Function: privateKeyToAccountWithContext], - decrypt: [Function: decryptWithContext] - }, - _addressMap: Map(1) { '0xe0a7859c5454b369ab8089890a11efcb458ea13c' => 0 }, - _defaultKeyName: 'web3js_wallet' -] -*/ -``` - -## Create an account and add it to an empty `Wallet` - -```ts title='Creating an Account and add it to a Wallet' -import { Web3 } from "web3"; - -const web3 = new Web3(/* PROVIDER */); - -// 1st - creating a new account -const account = web3.eth.accounts.create(); -/* ↳ -{ - address: '0x0770B4713B62E0c08C43743bCFcfBAA39Fa703EF', - privateKey: '0x97b0c07e275a0d8d9983331ca1a7ecb1a4a6f7dcdd7657529fe07446fa4dfe23', - signTransaction: [Function: signTransaction], - sign: [Function: sign], - encrypt: [Function: encrypt] -} -*/ - -// 2nd - add the account to the wallet -const wallet = web3.eth.accounts.wallet.add(account); -/* ↳ -Wallet(1) [ - { - address: '0x0770B4713B62E0c08C43743bCFcfBAA39Fa703EF', - privateKey: '0x97b0c07e275a0d8d9983331ca1a7ecb1a4a6f7dcdd7657529fe07446fa4dfe23', - signTransaction: [Function: signTransaction], - sign: [Function: sign], - encrypt: [Function: encrypt] - }, - _accountProvider: { - create: [Function: createWithContext], - privateKeyToAccount: [Function: privateKeyToAccountWithContext], - decrypt: [Function: decryptWithContext] - }, - _addressMap: Map(1) { '0x0770b4713b62e0c08c43743bcfcfbaa39fa703ef' => 0 }, - _defaultKeyName: 'web3js_wallet' -] -*/ -``` - -## Import a privateKey and add it to an empty `Wallet` - -```ts title='Creating a wallet and adding an account with a private key' -import { Web3 } from 'web3'; - -const web3 = new Web3(/* PROVIDER */); - -// add an account to the wallet using a private key -const privateKey = '0x4651f9c219fc6401fe0b3f82129467c717012287ccb61950d2a8ede0687857ba' -const wallet = web3.eth.accounts.wallet.add(privateKey); -/* ↳ -Wallet(1) [ - { - address: '0x9E82491d1978217d631a3b467BF912933F54788f', - privateKey: '0x4651f9c219fc6401fe0b3f82129467c717012287ccb61950d2a8ede0687857ba', - signTransaction: [Function: signTransaction], - sign: [Function: sign], - encrypt: [Function: encrypt] - }, - _accountProvider: { - create: [Function: createWithContext], - privateKeyToAccount: [Function: privateKeyToAccountWithContext], - decrypt: [Function: decryptWithContext] - }, - _addressMap: Map(1) { '0x9e82491d1978217d631a3b467bf912933f54788f' => 0 }, - _defaultKeyName: 'web3js_wallet' -] -*/ -``` - diff --git a/docs/docs/guides/wallet/metamask.md b/docs/docs/guides/wallet/metamask.md index 888f5890b1a..83eae1563fb 100644 --- a/docs/docs/guides/wallet/metamask.md +++ b/docs/docs/guides/wallet/metamask.md @@ -1,5 +1,5 @@ --- -sidebar_position: 4 +sidebar_position: 3 sidebar_label: 'Tutorial: Connecting to Metamask' --- diff --git a/docs/docs/guides/wallet/node_wallet.md b/docs/docs/guides/wallet/node_wallet.md deleted file mode 100644 index 7b70ed655a3..00000000000 --- a/docs/docs/guides/wallet/node_wallet.md +++ /dev/null @@ -1,114 +0,0 @@ ---- -sidebar_position: 8 -sidebar_label: 'Tutorial: Node Wallet' ---- - -# Using Node Wallet - -If Ethereum node has unlocked account in its wallet you can send transaction without need of signing locally in web3.js - -:::danger -Using `web3.eth.personal` is not considered secure and is strongly discouraged. The personal RPC endpoints have been deprecated due to significant security issues. More info: [geth.ethereum.org](https://geth.ethereum.org/docs/interacting-with-geth/rpc/ns-personal) -::: - -## Transaction - -```typescript -// First step: initialize web3 instance -import { Web3 } from 'web3'; -const web3 = new Web3(/* PROVIDER*/); - -// Second step: add an account to the Ethereum node and unlock it -const account = { - privateKey: 'privateKey', - address: '0xe4beef667408b99053dc147ed19592ada0d77f59', -}; - -// if you use ganache backend, use a private key with 0x -await web3.eth.personal.importRawKey(account.privateKey); -// if you use geth backend, use a private key without 0x -await web3.eth.personal.importRawKey(account.privateKey.slice(2)); - -// unlock account -await web3Personal.unlockAccount(account.address, 'anyPassword', 100000000); -// Make sure the account has enough eth on balance to send the transaction - -// Third step: sign and send the transaction -try { - const receipt = await web3.eth.sendTransaction({ - from: account.address, - to: '0xe4beef667408b99053dc147ed19592ada0d77f59', - value: '0x1', - gas: '300000', - // other transaction's params - }); -} catch (error) { - // catch transaction error - console.error(error); -} -``` - -List of references: - -- [eth.sendTransaction](/api/web3-eth/class/Web3Eth#sendTransaction) -- [eth.personal.importRawKey](/api/web3-eth-personal/class/Personal#importRawKey) -- [eth.personal.unlockAccount](/api/web3-eth-personal/class/Personal#unlockAccount) - -## Contract Deployment - -```typescript -// First step: initialize web3 instance -import { Web3 } from 'web3'; -const web3 = new Web3(/* PROVIDER*/); - -// Second step: add an account to the Ethereum node and unlock it -const account = { - privateKey: 'privateKey', - address: '0xe4beef667408b99053dc147ed19592ada0d77f59', -}; - -// if you use ganache backend, use a private key with 0x -await web3.eth.personal.importRawKey(account.privateKey); -// if you use geth backend, use a private key without 0x -await web3.eth.personal.importRawKey(account.privateKey.slice(2)); - -// unlock account -await web3.eth.personal.unlockAccount(account.address, 'anyPassword', 100000000); -// Make sure the account has enough eth on balance to send the transaction - -// Third step: sign and send the transaction -try { - // deploy - const contract = new web3.eth.Contract(ContractAbi); - const contractDeployed = await contract - .deploy({ - input: ContractBytecode, - arguments: ['Constructor param1', 'Constructor param2'], - }) - .send({ - from: account.address, - gas: '1000000', - // other transaction's params - }); - - // call method - await contractDeployed.methods - .transfer('0xe2597eb05cf9a87eb1309e86750c903ec38e527e', '0x1') - .send({ - from: account.address, - gas: '1000000', - // other transaction's params - }); -} catch (error) { - // catch transaction error - console.error(error); -} -``` - -List of references: - -- [eth.Contract](/api/web3-eth-contract/class/Contract) -- [eth.personal.importRawKey](/api/web3-eth-personal/class/Personal#importRawKey) -- [eth.personal.unlockAccount](/api/web3-eth-personal/class/Personal#unlockAccount) -- [contract.deploy](/api/web3-eth-contract/class/Contract#deploy) -- [contract.methods](/api/web3-eth-contract/class/Contract#methods) diff --git a/docs/docs/guides/wallet/promi_event.md b/docs/docs/guides/wallet/promi_event.md deleted file mode 100644 index 6f310c41557..00000000000 --- a/docs/docs/guides/wallet/promi_event.md +++ /dev/null @@ -1,90 +0,0 @@ ---- -sidebar_position: 2 -sidebar_label: 'Transactions Events Listening' ---- - -# Promise Event - -You can use `Web3PromiEvent` when you send transaction via `web3.eth.sendTransaction`, `web3.eth.sendSignedTransaction`, `contractDeployed.methods['methodName'](...methodParams).send` functions - -```ts title='Transaction Promise Events' -web3.eth.sendTransaction({...}) - .on('sending', (sending) => { - // Sending example - // 0x02f86d82053903849502f900849a9a0d16830186a0947ab80aeb6bb488b7f6c41c58e83ef248eb39c8828080c080a0b0fce643a6ca3077ee6b83590b1798d00edef99e2c65c1837daab88d46860887a07ca449a31b2430dbf21310b8c4491386762ade23e48c7cd0b70d315576374c7c - }) - .on('sent', (sent) => { - // Sent example - // 0x02f86d82053903849502f900849a9a0d16830186a0947ab80aeb6bb488b7f6c41c58e83ef248eb39c8828080c080a0b0fce643a6ca3077ee6b83590b1798d00edef99e2c65c1837daab88d46860887a07ca449a31b2430dbf21310b8c4491386762ade23e48c7cd0b70d315576374c7c - }) - .on('transactionHash', (transactionHash) => { - // Transaction hash example - // 0x6d85b2f07e7c8f2a7ce90a5bcfa3100c528f173f0707164434fb42d397d92d50 - }) - .on('confirmation', (confirmation) => { - // Confirmation example - // { - // confirmations: 1n, - // receipt: { - // blockHash: '0x947b8c95dea7f0c643f2be0e9d1c3bec76c7f5146fdf34f5f1efe6d2cab5f568', - // blockNumber: 22n, - // cumulativeGasUsed: 21000n, - // effectiveGasPrice: 2553565308n, - // from: '0xe2597eb05cf9a87eb1309e86750c903ec38e527e', - // gasUsed: 21000n, - // logs: [], - // logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - // status: 1n, - // to: '0x7ab80aeb6bb488b7f6c41c58e83ef248eb39c882', - // transactionHash: '0x3ec198ae10cf289b91210b4fd86a3b22cc9bcef16bca6beee21c35b76a2b7073', - // transactionIndex: 0n, - // type: 2n - // }, - // latestBlockHash: '0x947b8c95dea7f0c643f2be0e9d1c3bec76c7f5146fdf34f5f1efe6d2cab5f568' - // } - - }) - .on('receipt', (receipt) => { - // Receipt example - // { - // blockHash: '0x135d14b724d90b97feec1e96df590ce9af762d424aea49d29e11feaa24fe02f1', - // blockNumber: 23n, - // cumulativeGasUsed: 21000n, - // effectiveGasPrice: 2546893579n, - // from: '0xe2597eb05cf9a87eb1309e86750c903ec38e527e', - // gasUsed: 21000n, - // logs: [], - // logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - // status: 1n, - // to: '0x7ab80aeb6bb488b7f6c41c58e83ef248eb39c882', - // transactionHash: '0x9a6497fe4028d716e66a24ab7dfd3d1bcf136ba2ec26f427719b4ddaaff76fb7', - // transactionIndex: 0n, - // type: 2n - // } - - }) - .on('error', (error) => { - // Error example - // InvalidResponseError: Returned error: exceeds block gas limit - // at Web3RequestManager._processJsonRpcResponse (.../web3_request_manager.js:193:23) - // at Web3RequestManager. (.../web3_request_manager.js:112:29) - // at Generator.next () - // at fulfilled (.../web3_request_manager.js:5:58) - // at processTicksAndRejections (node:internal/process/task_queues:96:5) { - // cause: { code: -32000, message: 'exceeds block gas limit' }, - // code: 101, - // data: undefined, - // request: { - // jsonrpc: '2.0', - // id: 'ea1f8fb4-fe86-4492-9d89-c6e31bf1c036', - // method: 'eth_sendRawTransaction', - // params: [ - // '0x02f86e82053903849502f900849a9a0d168405f7c1f0947ab80aeb6bb488b7f6c41c58e83ef248eb39c8828080c001a0ddd93f5ce9a6a0de130dc660e65d2cdf8784148b8c91b83635b8458e96a767a3a028c48b048bf041e530ded63a0d2198855043f782ef0aa47391a2afa9c50a5ff1' - // ] - // } - }); -``` - -List of references: - -- [Web3PromiEvent](/api/web3-core/class/Web3PromiEvent) diff --git a/docs/docs/guides/wallet/signing.md b/docs/docs/guides/wallet/signing.md deleted file mode 100644 index 54b3779cd17..00000000000 --- a/docs/docs/guides/wallet/signing.md +++ /dev/null @@ -1,131 +0,0 @@ ---- -sidebar_position: 6 -sidebar_label: 'Tutorial: Signing operations' ---- - -# Signing operations - -In this guide, we'll cover how to sign `data` and `transactions` using web3.js. Whether it's signing data with an account, signing transactions, or using wallets and private keys, we'll walk you through the basic steps. Let's get started! - - -## Sign Data With an `Account` - -In this example we are creating a random account `web3.eth.account.create()`, but you can also import a specific account by using `web3.eth.accounts.privateKeyToAccount('0x...')` - -``` ts -import { create } from 'web3-eth-accounts'; - -// the create method returns a `Web3Account` object -// the account contains an `address` and `privateKey` and allows you to be able to encrypt, signData and signTransaction. -const account = create(); //this is the same as web3.eth.accounts.create(); - -/* ↳ -{ -address: '0xbD504f977021b5E5DdccD8741A368b147B3B38bB', -privateKey: 'privateKey', -signTransaction: [Function: signTransaction], -sign: [Function: sign], -encrypt: [AsyncFunction: encrypt] -} -*/ - -account.sign('hello world'); -/* ↳ -{ - message: 'hello world', - messageHash: '0xd9eba16ed0ecae432b71fe008c98cc872bb4cc214d3220a36f365326cf807d68', - v: '0x1b', - r: '0xe4fce466ef18f6cd8b4f4175a9a04cd2872a1a6a8cfc2ff67fb0cfd6d78ec758', - s: '0x37ca3a789976f1854d16e50a04caf2e06ee14b0ac4a5878b43929767f2008288', - signature: '0xe4fce466ef18f6cd8b4f4175a9a04cd2872a1a6a8cfc2ff67fb0cfd6d78ec75837ca3a789976f1854d16e50a04caf2e06ee14b0ac4a5878b43929767f20082881b' -} -*/ -``` - -## Sign a Transaction With an `Account` - -In this example we are importing a specific account by using `web3.eth.accounts.privateKeyToAccount('0x...')` but you can also create a random account by using `web3.eth.account.create()`. - -``` ts -import { Web3 } from 'web3'; - -const web3 = new Web3(/* PROVIDER */); - -const privateKey = '0x4651f9c219fc6401fe0b3f82129467c717012287ccb61950d2a8ede0687857ba' -const account = web3.eth.accounts.privateKeyToAccount(privateKey); - -// Magic happens inside signTransaction. If a transaction is sent from an account that exists in a wallet, it will be automatically signed using that account. -signedTransaction = await account.signTransaction({ - from: account.address, - to: '0xe4beef667408b99053dc147ed19592ada0d77f59', - value: '0x1', - gas: '300000', - gasPrice: await web3.eth.getGasPrice(), -}); - -console.log(signedTransaction); -/* ↳ -{ -messageHash: '0xfad22c3ab5ecbb6eec934a21243ee1866fbbd3786f4e8e8ec631b917ef65174d', -v: '0xf4f6', -r: '0xc0035636d9417f63fdd418bc545190e59b58a4ff921bbf4efebf352dac211f11', -s: '0x4944d746ff12c7bca41f77c8f7d75301cea8b205e021dfde34d09d5bdccc713d', -rawTransaction: - '0xf866808477359400830493e094e4beef667408b99053dc147ed19592ada0d77f59018082f4f6a0c0035636d9417f63fdd418bc545190e59b58a4ff921bbf4efebf352dac211f11a04944d746ff12c7bca41f77c8f7d75301cea8b205e021dfde34d09d5bdccc713d', -transactionHash: '0xa3fed275c97abc4a160cd9bef3ec90206686f32821a8fd4e01a04130bff35c1a', -}; -*/ -``` - -## Signing data/messages using a wallet - -``` ts title='Signing with a wallet' -import { Web3 } from 'web3'; - -const web3 = new Web3(/* PROVIDER */); - -// create a `Wallet` with 1 account inside -const wallet = web3.eth.accounts.wallet.create(1); - -const message = web3.utils.utf8ToHex('Hello world'); // sign only takes hexstrings, so turn message to hexstring - -const signedMessage = web3.eth.sign(message, wallet[0].address); - -console.log(signedMessage); -/* ↳ -{ - message: '0x48656c6c6f20776f726c64', - messageHash: '0x8144a6fa26be252b86456491fbcd43c1de7e022241845ffea1c3df066f7cfede', - v: '0x1c', - r: '0x3a420906f331896cb5db1366cdaeef1f0b14f9f71d72c178e87b76f8b31f3f36', - s: '0x32ffccc78638c1d7e46dbf16041ddaef90ab50a85eeeaa46f8c496a39237831a', - signature: '0x3a420906f331896cb5db1366cdaeef1f0b14f9f71d72c178e87b76f8b31f3f3632ffccc78638c1d7e46dbf16041ddaef90ab50a85eeeaa46f8c496a39237831a1c' -} -*/ -``` - -## Signing data/messages using a privateKey - -```ts title= 'Signing with a private key' -import { Web3 } from 'web3'; - -const web3 = new Web3(/* PROVIDER */); - -const privateKey = '0x4651f9c219fc6401fe0b3f82129467c717012287ccb61950d2a8ede0687857ba'; - -const message = 'Hello world'; -const signedMessage = web3.eth.accounts.sign(message, privateKey); - -console.log(signedMessage); -/* ↳ -{ - message: 'Hello world', - messageHash: '0x8144a6fa26be252b86456491fbcd43c1de7e022241845ffea1c3df066f7cfede', - v: '0x1c', - r: '0xb669ef385082d7c4393522ab2fc37f8684fe948b313fb64b7cb8bee851b765f1', - s: '0x26eec81e9900d25500c13024b273e238cfb2a4d4554b79f74b372e1132b6cb2f', - signature: '0xb669ef385082d7c4393522ab2fc37f8684fe948b313fb64b7cb8bee851b765f126eec81e9900d25500c13024b273e238cfb2a4d4554b79f74b372e1132b6cb2f1c' -} -*/ -``` - diff --git a/docs/docs/guides/wallet/transactions.md b/docs/docs/guides/wallet/transactions.md index c86da4c9113..dfc92765844 100644 --- a/docs/docs/guides/wallet/transactions.md +++ b/docs/docs/guides/wallet/transactions.md @@ -1,347 +1,475 @@ --- -sidebar_position: 7 +sidebar_position: 2 sidebar_label: 'Tutorial: Sending Transactions' --- -# Transactions +# Sending Transactions -This guide provides insights into sending transactions using web3.js, covering various scenarios from utilizing a local wallet to sending raw transactions. +This tutorial will walk through the process of using accounts to send transactions on a [development network](https://ethereum.org/en/developers/docs/development-networks/), including how to subscribe to the events associated with a transaction. The topics covered in this tutorial include basic concepts of [Ethereum](https://ethereum.org/), such as [accounts](/guides/wallet/), [denominations of ether](https://ethereum.org/en/developers/docs/intro-to-ether/#denominations), [transactions](https://ethereum.org/en/developers/docs/transactions/), and [gas fees](https://ethereum.org/en/developers/docs/gas/), as well as the basics of the [Hardhat](https://hardhat.org/) development environment. -## Sending transactions with a local wallet +## Overview -The simplest way to sign and send transactions is using a local wallet: +Here is a high-level overview of the steps we will be taking in this tutorial: -```typescript -// 1st step: initialize `web3` instance -import { Web3 } from 'web3'; +1. Review prerequisites +2. Create a new directory and initialize a new Node.js project +3. Set up Web3.js and Hardhat +4. Send a transaction and review the results +5. Send a transaction and subscribe to its events +6. Send a raw transaction -const web3 = new Web3(/* PROVIDER*/); +:::tip +If you encounter any issues while following this guide or have any questions, don't hesitate to seek assistance. Our friendly community is ready to help you out! Join our [Discord](https://discord.gg/F4NUfaCC) server and head to the **#web3js-general** channel to connect with other developers and get the support you need. +::: -// 2nd step: add an account to wallet -const privateKey = '0x7b907534ec13b19c67c2a738fdaa69014298c71f2221d7e5dec280232e996610'; -const account = web3.eth.accounts.wallet.add(privateKey).get(0); -// Make sure the account has enough eth on balance to send the transaction +## Step 1: Prerequisites -// 3rd step: sign and send the transaction -//highlight-start -// Magic happens inside sendTransaction. If a transaction is sent from an account that exists in a wallet, it will be automatically signed using that account. -const receipt = await web3.eth.sendTransaction({ - from: account?.address, - to: '0xe4beef667408b99053dc147ed19592ada0d77f59', - value: '0x1', - gas: '300000', - // other transaction's params -}); -//highlight-end -``` +This tutorial assumes basic familiarity with the command line as well as familiarity with JavaScript and [Node.js](https://nodejs.org/). Before starting this tutorial, ensure that Node.js and its package manager, npm, are installed. -## Sending a raw transaction - -```ts -import { Web3 } from 'web3'; - -// 1st - initialize the provider -const web3 = new Web3('https://ethereum-sepolia.publicnode.com'); - -// 2nd - create an account -const account = web3.eth.accounts.privateKeyToAccount('0x4651f9c219fc6401fe0b3f82129467c717012287ccb61950d2a8ede0687857ba'); - -// 3rd - create a raw transaction object -const rawTransaction = { - from: account.address, - to: '0x5875da5854c2adadbc1a7a448b5b2a09b26baff8', //random wallet or contract address - value: 1, //optional - value in wei - maxFeePerGas: (await web3.eth.getBlock()).baseFeePerGas * 2n, //updated depending on the network - maxPriorityFeePerGas: 100000, //high - gasLimit: 2000000 - nonce: await web3.eth.getTransactionCount(account.address), //optional - get the current nonce of the account - data: "0x0" //optional - encoded function signature and arguments -}; - -// 4th - sign the raw transaction with the private key -const signedTransaction = await web3.eth.accounts.signTransaction(rawTransaction, account.privateKey); - -// 5th - send the signed transaction -const txReceipt = await web3.eth.sendSignedTransaction(signedTransaction.rawTransaction); - -console.log('Transaction Receipt:', txReceipt); -/* ↳ -Transaction Receipt: { - blockHash: '0xd73a824348ebb8c1895fbe7b2c506c287cfaadc8104628a140e7b39d7e41d50f', - blockNumber: 4972805n, - cumulativeGasUsed: 15266381n, - effectiveGasPrice: 118637814298n, - from: '0xa3286628134bad128faeef82f44e99aa64085c94', - gasUsed: 21000n, - logs: [], - logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - status: 1n, - to: '0x5875da5854c2adadbc1a7a448b5b2a09b26baff8', - transactionHash: '0x247e4540f9b399655da90e8a0c3d9ec165f62a304f6364f45518a4d6a531cd36', - transactionIndex: 156n, - type: 0n -} -*/ +```bash +$: node -v +# your version may be different, but it's best to use the current stable version +v18.16.1 +$: npm -v +9.5.1 ``` -## Sending a transaction with Browser Injection (Metamask) +## Step 2: Create a New Directory and Initialize a New Node.js Project + +First, create a new project directory for the project and navigate into it: -This is an example html file that will send a transaction when the button element is clicked. +```bash +mkdir account-transactions-tutorial +cd account-transactions-tutorial +``` -To run this example you'll need Metamask, the `index.html` file below in your folder and you'll need a local server: +Next, initialize a new Node.js project using npm: ```bash -npm i http-server +npm init -y ``` +This will create a new `package.json` file in your project directory. + +## Step 3: Set Up Web3.js and Hardhat + +Install the required packages with npm: + ```bash -npx http-server +npm i web3 hardhat ``` -Afterwards your file will be served on a local port, which will usually be on `http://127.0.0.1:8080` - -``` html - - - - - - Send Transaction Example - - - - - - - - +Next, initialize the Hardhat project: + +```bash +npx hardhat init ``` +Initializing the Hardhat project will require responding to several prompts - select the default option for each prompt. After the Hardhat project has been initialized, a number of new files and directories will be created. -## Contract Deployment - -```typescript title='Deploy a contract' -// 1st step: initialize `web3` instance -import { Web3 } from 'web3'; - -const web3 = new Web3(/* PROVIDER*/); - -// 2nd step: add an account to wallet -const privateKey = '0x7b907534ec13b19c67c2a738fdaa69014298c71f2221d7e5dec280232e996610'; -const account = web3.eth.accounts.wallet.add(privateKey).get(0); -// Make sure the account has enough eth on balance to send the transaction - -// fill ContractAbi and ContractBytecode with your contract's abi and bytecode - -async function deploy() { - // 3rd step: sign and send the transaction - // In any function where you can pass from the address set address of the account that exists in a wallet, it will be automatically signed. - - try { - // deploy - const contract = new web3.eth.Contract(ContractAbi); - const contractDeployed = await contract - .deploy({ - input: ContractBytecode, - arguments: ['Constructor param1', 'Constructor param2'], - }) - .send({ - from: account?.address, - gas: '1000000', - // other transaction's params - }); - - // call method - await contractDeployed.methods.transfer('0xe2597eb05cf9a87eb1309e86750c903ec38e527e', '0x1').send({ - from: account?.address, - gas: '1000000', - // other transaction's params - }); - } catch (error) { - // catch transaction error - console.error(error); - } -} +To start the Hardhat development network, execute the following command: -(async () => { - await deploy(); -})(); +```bash +npx hardhat node ``` +Executing this command will produce the following output, which provides the URL that can be used to connect to the development network as well as the development network's test accounts: + +```bash +Started HTTP and WebSocket JSON-RPC server at http://127.0.0.1:8545/ + +Accounts +======== + +WARNING: These accounts, and their private keys, are publicly known. +Any funds sent to them on Mainnet or any other live network WILL BE LOST. + +Account #0: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 (10000 ETH) +Private Key: -## Interacting with contract methods +... -``` ts title='Interact with contracts using a wallet under the hood' -// 1st step: initialize `web3` instance -import { Web3 } from 'web3'; +Account #19: 0x8626f6940E2eb28930eFb4CeF49B2d1F2C9C1199 (10000 ETH) +Private Key: -const web3 = new Web3(/* PROVIDER*/); +WARNING: These accounts, and their private keys, are publicly known. +Any funds sent to them on Mainnet or any other live network WILL BE LOST. +``` + +:::info +The Hardhat development network's test accounts are funded with ETH for testing purpose. These accounts will be used in this tutorial to send transactions. +::: -// 2nd step: add an account to wallet -const privateKeyString = '0x4651f9c219fc6401fe0b3f82129467c717012287ccb61950d2a8ede0687857ba'; +The Hardhat development network needs to remain running in the terminal that was used to start it. Open a new terminal instance in the project directory to execute the remaining commands in this tutorial. -const wallet = web3.eth.accounts.wallet.add(privateKeyString); -// Make sure the account has enough eth on balance to send the transaction +Next, create a new file called `index.js` in your project directory and add the following code to it: -async function contractMethod() { - try { - // 3rd step: instantiate the contract with the ABI and contract address - const myContract = new web3.eth.Contract(ABI, CONTRACT_ADDRESS); +```js +const { Web3 } = require("web3"); - // 4th step: call contract method and send the tx - await myContract.methods.doSomething().send({ - from: wallet[0].address, - gas: '1000000', - // other transaction's params - }); - } catch (error) { - // catch transaction error +const web3 = new Web3("http://127.0.0.1:8545/"); + +// Log the chain ID to the console +web3.eth + .getChainId() + .then((result) => { + console.log("Chain ID: " + result); + }) + .catch((error) => { console.error(error); - } + }); +``` + +This code sets up a Web3.js connection to the Hardhat development network and logs the chain ID to the console. + +:::note +This tutorial uses the default URL for the Hardhat development network (http://127.0.0.1:8545/). Make sure to use the actual URL that was provided when the Hardhat development network was started. +::: + +Run the following command to test the connection: + +```bash +node index.js +``` + +If everything is working correctly, the chain ID of the Hardhat development network should be logged to the console: + +```bash +Chain ID: 31337 +``` + +## Step 4: Send a Transaction and Review the Results + +Create a new file called `transaction-receipt.js` in your project directory and add the following code to it: + +:::note +Replace the value of the `privateKey` variable with one of the private keys of the Hardhat development network's test accounts. +::: + +```js +const { Web3 } = require("web3"); + +async function main() { + const web3 = new Web3("http://127.0.0.1:8545/"); + + // create a new Web3.js account object with the private key of a Hardhat test account + const privateKey = ""; + // the account is created with a wallet, which makes it easier to use + const sender = web3.eth.accounts.wallet.add(privateKey)[0]; + + // generate a new random Web3.js account object to receive the transaction + const receiver = web3.eth.accounts.create(); + + // log initial balances + console.log( + "Initial sender balance:", + // account balance in wei + await web3.eth.getBalance(sender.address) + ); + console.log( + "Initial receiver balance:", + // account balance in wei + await web3.eth.getBalance(receiver.address) + ); + + // sign and send the transaction + const receipt = await web3.eth.sendTransaction({ + from: sender.address, + to: receiver.address, + // amount in wei + value: 100, + }); + + // log transaction receipt + console.log(receipt); + + // log final balances + console.log( + "Final sender balance:", + await web3.eth.getBalance(sender.address) + ); + console.log( + "Final receiver balance:", + await web3.eth.getBalance(receiver.address) + ); } -(async () => { - await contractMethod(); -})(); +main(); +``` + +This script uses the [`web3.eth.sendTransaction`](/libdocs/Web3Eth#sendtransaction) function to send the transaction. The parameter to this function is defined by the [`Transaction`](/api/web3-types/interface/Transaction) interface. + +:::note +By default, Web3.js uses the [wei denomination](https://ethereum.org/en/developers/docs/intro-to-ether/#denominations) for account balances and transaction values. The [`web3-utils`](/libdocs/Utils) package has helper functions that can be used to convert other denominations of ether [to](/libdocs/Utils#towei) and [from](/libdocs/Utils#fromwei) wei. +::: + +In this example, the account is created with a `Wallet`, which adds it to the internal Web3.js context (i.e. [`Web3Context`](/api/web3-core/class/Web3Context)). When a transaction is sent from an account that has been created with a `Wallet` and added to the context, Web3.js will automatically use that account's private key to sign the transaction. The steps required to send a transaction from an account that hasn't been created with a wallet and added to the context are described in [Step 6: Send a Raw Transaction](#step-6-send-a-raw-transaction). + +Execute the following command to run the code from `transaction-receipt.js`: + +```bash +node transaction-receipt.js +``` + +The output should look similar to the following: + +``` +Initial sender balance: 10000000000000000000000n +Initial receiver balance: 0n +{ + blockHash: '0x9a7250ca7947b84972bf973da232656280f2bb5eab71777a34fb49c08585a2b2', + blockNumber: 1n, + cumulativeGasUsed: 21000n, + effectiveGasPrice: 3375000000n, + from: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266', + gasUsed: 21000n, + logs: [], + logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', + status: 1n, + to: '0xc14a6278b4a8d4f9eb198b75b7013d58b1de94da', + transactionHash: '0xaf4b89e10c811e3f2c954447e40f7ecac073ca41fa4a896a3a86299cae24b339', + transactionIndex: 0n, + type: 2n +} +Final sender balance: 9999999929124999999900n +Final receiver balance: 100n ``` -## Sending a transaction and listening to the events - -```ts title='Transactions with Web3PromiEvent' -import { Web3 } from 'web3'; - -// 1st - initialize the provider -const web3 = new Web3(/* PROVIDER*/); - -// 2nd - add an account to wallet -const privateKey = '0x4651f9c219fc6401fe0b3f82129467c717012287ccb61950d2a8ede0687857ba'; -const account = web3.eth.accounts.wallet.add(privateKey).get(0); -// Make sure the account has enough eth on balance to send the transaction - -// 3rd - sign and send the transaction -// Magic happens behind sendTransaction. If a transaction is sent from an account that exists in a wallet, it will be automatically signed. -const transaction = web3.eth.sendTransaction({ - from: account?.address, - to: '0xe4beef667408b99053dc147ed19592ada0d77f59', - value: '0x1', - gas: '300000', - // other transaction's params -}); - -// highlight-start -// 4th - listen to the transaction events -transaction - .on('sending', (sending) => { - // Sending example - console.log('Sending:', sending); +Note that the sender's balance has decreased by more than the amount that was transferred to the receiver. This is because the sender's balance is also used to pay for the transaction's [gas fees](https://ethereum.org/en/developers/docs/gas/). The transaction receipt specifies the amount of gas that was used (`cumulativeGasUsed`) and the gas price in wei (`effectiveGasPrice`). The total amount deducted from the sender's balance is equal to the amount transferred plus the cost of the gas fees (`cumulativeGasUsed` multiplied by `effectiveGasPrice`). + +## Step 5: Send a Transaction and Subscribe to Its Events + +In the previous example, the `transaction-receipt.js` script demonstrates sending a transaction to the network and reviewing the results after it has been successfully received. However, there are more stages to the [transaction lifecycle](https://ethereum.org/en/developers/docs/transactions/#transaction-lifecycle) and Web3.js makes it easy to subscribe to these lifecycle stages and create custom handlers for each one. Web3.js supports subscriptions for the following transaction lifecycle events: + +- Sending - Web3.js is preparing to send the transaction to the network +- Sent - the transaction has been sent to the network +- Transaction hash - a hash of the transaction has been generated +- Receipt - the transaction has been included in a block +- Confirmation - the block in which the transaction was included has been [finalized](https://ethereum.org/en/glossary/#finality) +- Error - a problem with the transaction was encountered + +Create a new file called `transaction-events.js` in your project directory and add the following code to it: + +```js +const { Web3 } = require("web3"); + +const web3 = new Web3("http://127.0.0.1:8545/"); + +const privateKey = ""; +const sender = web3.eth.accounts.wallet.add(privateKey)[0]; + +const receiver = web3.eth.accounts.create(); + +web3.eth + .sendTransaction({ + from: sender.address, + to: receiver.address, + value: 100, + }) + .on("sending", (sending) => { + console.log("Sending:", sending); + }) + .on("sent", (sent) => { + console.log("Sent:", sent); }) - .on('sent', (sent) => { - // Sent example - console.log('Sent:', sent); + .on("transactionHash", (transactionHash) => { + console.log("Transaction Hash:", transactionHash); }) - .on('transactionHash', (transactionHash) => { - // Transaction hash example - console.log('Transaction Hash:', transactionHash); + .on("receipt", (receipt) => { + console.log("Receipt:", receipt); }) - .on('confirmation', (confirmation) => { - // Confirmation example - console.log('Confirmation:', confirmation); + .on("confirmation", (confirmation) => { + console.log("Confirmation:", confirmation); + process.exit(0); }) - .on('error', (error) => { - // Error example - console.error('Error:', error); + .on("error", (error) => { + console.log("Error:", error); + process.exit(1); }); -// highlight-end -/* ↳ +``` + +Execute the following command to run the code from `transaction-events.js`: + +```bash +node transaction-events.js +``` + +The output should look similar to the following: + +``` Sending: { - from: '0xA3286628134baD128faeef82F44e99AA64085C94', - to: '0xe4beef667408b99053dc147ed19592ada0d77f59', - value: '0x1', - gas: '0x493e0', + from: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', + to: '0x077bd1F472a0C7eD3214583d4B0fE8b21e4b3b5A', + value: '0x64', gasPrice: undefined, maxPriorityFeePerGas: '0x9502f900', - maxFeePerGas: '0x2b53cf7960' + maxFeePerGas: '0xfd51da80' } Sent: { - from: '0xA3286628134baD128faeef82F44e99AA64085C94', - to: '0xe4beef667408b99053dc147ed19592ada0d77f59', - value: '0x1', - gas: '0x493e0', + from: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', + to: '0x077bd1F472a0C7eD3214583d4B0fE8b21e4b3b5A', + value: '0x64', gasPrice: undefined, maxPriorityFeePerGas: '0x9502f900', - maxFeePerGas: '0x2b53cf7960' + maxFeePerGas: '0xfd51da80' } -Transaction Hash: 0xa7493bc3eb6e7f41b54291cfd19d90111e68ea2cd9718da937ca4dcc1f831dde +Transaction Hash: 0x66b4cd592e82ea09dee4015277aee9299bafce369819a82b4797a06ba010c6b1 Receipt: { - blockHash: '0xe049c2cd2a473dad2af5ccf40c2df788cd42a237616cc84cc3861937f1aa2195', - blockNumber: 4972912n, - cumulativeGasUsed: 1018070n, - effectiveGasPrice: 100635626363n, - from: '0xa3286628134bad128faeef82f44e99aa64085c94', + blockHash: '0xeedfe16bb67dae4cc2064f68ddcef1b83deb4b1eaf19b99c2a175aafaded36b9', + blockNumber: 2n, + cumulativeGasUsed: 21000n, + effectiveGasPrice: 3265778125n, + from: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266', gasUsed: 21000n, logs: [], - logsBloom: '0x...00', + logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', status: 1n, - to: '0xe4beef667408b99053dc147ed19592ada0d77f59', - transactionHash: '0xa7493bc3eb6e7f41b54291cfd19d90111e68ea2cd9718da937ca4dcc1f831dde', - transactionIndex: 15n, + to: '0x077bd1f472a0c7ed3214583d4b0fe8b21e4b3b5a', + transactionHash: '0x66b4cd592e82ea09dee4015277aee9299bafce369819a82b4797a06ba010c6b1', + transactionIndex: 0n, type: 2n } Confirmation: { confirmations: 1n, receipt: { - blockHash: '0xe049c2cd2a473dad2af5ccf40c2df788cd42a237616cc84cc3861937f1aa2195', - blockNumber: 4972912n, - cumulativeGasUsed: 1018070n, - effectiveGasPrice: 100635626363n, - from: '0xa3286628134bad128faeef82f44e99aa64085c94', + blockHash: '0xeedfe16bb67dae4cc2064f68ddcef1b83deb4b1eaf19b99c2a175aafaded36b9', + blockNumber: 2n, + cumulativeGasUsed: 21000n, + effectiveGasPrice: 3265778125n, + from: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266', gasUsed: 21000n, logs: [], - logsBloom: '0x...000', + logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', status: 1n, - to: '0xe4beef667408b99053dc147ed19592ada0d77f59', - transactionHash: '0xa7493bc3eb6e7f41b54291cfd19d90111e68ea2cd9718da937ca4dcc1f831dde', - transactionIndex: 15n, + to: '0x077bd1f472a0c7ed3214583d4b0fe8b21e4b3b5a', + transactionHash: '0x66b4cd592e82ea09dee4015277aee9299bafce369819a82b4797a06ba010c6b1', + transactionIndex: 0n, type: 2n }, - latestBlockHash: '0xe049c2cd2a473dad2af5ccf40c2df788cd42a237616cc84cc3861937f1aa2195' + latestBlockHash: '0xeedfe16bb67dae4cc2064f68ddcef1b83deb4b1eaf19b99c2a175aafaded36b9' } -Confirmation: { - confirmations: 2n, - receipt: {...}, - latestBlockHash: '0xf20261fc59d059c9dfd048e44c7fe1499d45822d9fe804bca70ac56559b54b1b' +``` + +Because the transaction should succeed, the error event should not be logged to the console. To review an error event, use a random account to send the transaction by changing the value of the `sender` variable as follows: + +```js +const sender = web3.eth.accounts.wallet.create(1)[0]; +``` + +This change will cause an error since the new random account does not have a balance that can be used to pay the transaction's gas fees. + +Re-run the updated script as before. The output should look similar to the following: + +``` +Sending: { + from: '0x2F2f42075567cd9823961A4e04171cEbdc45E390', + to: '0xb52F3110C8d3eFDa5137A8A935eE35aACCBB3613', + value: '0x64', + gasPrice: undefined, + maxPriorityFeePerGas: '0x9502f900', + maxFeePerGas: '0xf04caa9a' } -Confirmation: { - confirmations: 3n, - receipt: {...}, - latestBlockHash: '0xb52380054ad2382620615ba7b7b40638021d85c5904a402cd11d00fd4db9fba9' +Error: InvalidResponseError: Returned error: Sender doesn't have enough funds to send tx. The max upfront cost is: 84666712806350 and the sender's balance is: 0. + at Web3RequestManager._processJsonRpcResponse (.../web3-core/lib/commonjs/web3_request_manager.js:281:23) + at Web3RequestManager. (.../web3-core/lib/commonjs/web3_request_manager.js:167:29) + at Generator.next () + at fulfilled (.../web3-core/lib/commonjs/web3_request_manager.js:21:58) + at process.processTicksAndRejections (node:internal/process/task_queues:95:5) { + cause: { + code: -32000, + message: "Sender doesn't have enough funds to send tx. The max upfront cost is: 84666712806350 and the sender's balance is: 0.", + data: { + message: "Sender doesn't have enough funds to send tx. The max upfront cost is: 84666712806350 and the sender's balance is: 0.", + data: null + } + }, + code: 101, + data: { + message: "Sender doesn't have enough funds to send tx. The max upfront cost is: 84666712806350 and the sender's balance is: 0.", + data: null + }, + request: { + jsonrpc: '2.0', + id: 'bf7e8ddd-f2bb-45ab-9168-8c577cd1bcb9', + method: 'eth_sendRawTransaction', + params: [ + '0x02f86c827a6980849502f90084f04caa9a82520994b52f3110c8d3efda5137a8a935ee35aaccbb36136480c080a040b3b5d9a72ced0ec70750157a34972233b51e49a511a813763487f84905841ca06237e4a9b1e00934c6fabd32588ed44b6b55bb4aadb67939410a7a0cb801e2f1' + ] + } +} +``` + +## Step 6: Send a Raw Transaction + +The previous examples have relied on the helpful Web3.js context to automatically sign transactions with accounts that have been created with a `Wallet`. The final example in this tutorial will demonstrate using a non-wallet account to manually sign a transaction. + +Create a new file called `raw-transaction.js` in your project directory and add the following code to it: + +```js +const { Web3 } = require("web3"); + +async function main() { + const web3 = new Web3("http://127.0.0.1:8545/"); + + const privateKey = ""; + // import the Hardhat test account without the use of a wallet + const sender = web3.eth.accounts.privateKeyToAccount(privateKey); + + const receiver = web3.eth.accounts.create(); + + // used to calculate the transaction's maxFeePerGas + const block = await web3.eth.getBlock(); + + const transaction = { + from: sender.address, + to: receiver.address, + value: 100, + // the following two properties must be included in raw transactions + maxFeePerGas: block.baseFeePerGas * 2n, + maxPriorityFeePerGas: 100000, + }; + + const signedTransaction = await web3.eth.accounts.signTransaction( + transaction, + sender.privateKey + ); + const receipt = await web3.eth.sendSignedTransaction( + signedTransaction.rawTransaction + ); + console.log(receipt); } -*/ + +main(); ``` + +In this example, the [`signTransaction`](/api/web3-eth-accounts/function/signTransaction) function is used to manually sign the transaction with the sender's private key before using the [`sendSignedTransaction`](/api/web3-eth/function/sendSignedTransaction) function to send the transaction to the network. Note that, unlike in the previous examples, which relied on the helpful Web3.js context to construct the final transaction, this examples requires the inclusion of the [`maxFeePerGas`](/api/web3-types/interface/Transaction#maxFeePerGas) and [`maxPriorityFeePerGas`](/api/web3-types/interface/Transaction#maxPriorityFeePerGas) properties on the [`Transaction`](/api/web3-types/interface/Transaction) object. The exact meaning of these properties is out of the scope of this tutorial, but notice that `maxFeePerGas` is calculated using an actual value retrieved from the network ([`baseFeePerGas`](/api/web3-types/interface/BlockBase#baseFeePerGas)) while `maxPriorityFeePerGas` is set to a value that is simply deemed to be high enough. + +Execute the following command to run the code from `raw-transaction.js`: + +```bash +node raw-transaction.js +``` + +The output should look similar to the following: + +``` +{ + blockHash: '0xb83ccddddb4e715e51765182e184251d55bd4bc5da982691b169d21e39b62559', + blockNumber: 3n, + cumulativeGasUsed: 21000n, + effectiveGasPrice: 670289871n, + from: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266', + gasUsed: 21000n, + logs: [], + logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', + status: 1n, + to: '0x9f676309956465c7e4d188f58149a9e8f945d477', + transactionHash: '0xe56a9aee0f4927d5ce1eefaf2a323d32eb51e762bcf2ef33989c101302379bfc', + transactionIndex: 0n, + type: 2n +} +``` + +## Conclusion + +This tutorial demonstrated using accounts to send transactions, including how to subscribe to the events associated with a transaction. The easiest way to send a transaction from an account is to create the account with a `Wallet`, which adds that account to the Web3.js context and automates the process of using the account's private key to sign the transaction. However, for non-wallet accounts or in situations where it's necessary to decouple the processes of signing and sending a transaction (e.g. offline signing), Web3.js provides easy interfaces for manually signing a transaction before sending it. diff --git a/docs/docs/guides/wallet/web3_modal_guide/_category_.yml b/docs/docs/guides/wallet/web3_modal_guide/_category_.yml index 19d6fe3a639..c89deac9d4b 100644 --- a/docs/docs/guides/wallet/web3_modal_guide/_category_.yml +++ b/docs/docs/guides/wallet/web3_modal_guide/_category_.yml @@ -2,4 +2,4 @@ label: '📱 WalletConnect Tutorial' collapsible: true collapsed: true link: null -position: 5 +position: 4 From 16252f94cb99bbc4996c559480334c5748df7c01 Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 17 Jun 2024 09:30:17 -0400 Subject: [PATCH 101/186] release v4.10.0 (#7096) * version bump and changelog updates * change rpc-providers version to rc * update changelog --- CHANGELOG.md | 39 +++++++- packages/web3-core/CHANGELOG.md | 6 +- packages/web3-core/package.json | 4 +- packages/web3-eth-ens/CHANGELOG.md | 6 +- packages/web3-eth-ens/package.json | 8 +- packages/web3-eth/CHANGELOG.md | 6 +- packages/web3-eth/package.json | 6 +- packages/web3-rpc-providers/CHANGELOG.md | 6 ++ packages/web3-rpc-providers/package.json | 6 +- packages/web3-types/CHANGELOG.md | 9 ++ packages/web3-types/package.json | 2 +- packages/web3/CHANGELOG.md | 111 ++++++++++++++++++++++- packages/web3/package.json | 14 +-- packages/web3/src/version.ts | 2 +- tools/web3-plugin-example/CHANGELOG.md | 6 +- tools/web3-plugin-example/package.json | 18 ++-- 16 files changed, 207 insertions(+), 42 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b756bba2604..783691404b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2526,4 +2526,41 @@ If there are any bugs, improvements, optimizations or any new feature proposal f - Change `estimateGas` method to add possibility pass Transaction type (#7000) -## [Unreleased] \ No newline at end of file +## [4.10.0] + +### Added + +#### web3 + +- Now when existing packages are added in web3, will be avalible for plugins via context. (#7088) + +#### web3-core + +- Now when existing packages are added in web3, will be avalible for plugins via context. (#7088) + +#### web3-eth + +- `sendTransaction` in `rpc_method_wrappers` accepts optional param of `TransactionMiddleware` (#7088) +- WebEth has `setTransactionMiddleware` and `getTransactionMiddleware` for automatically passing to `sentTransaction` (#7088) + +#### web3-eth-ens + +- `getText` now supports first param Address +- `getName` has optional second param checkInterfaceSupport + +### web3-types + +- Added `result` as optional `never` and `error` as optional `never in type `JsonRpcNotification` (#7091) +- Added `JsonRpcNotfication` as a union type in `JsonRpcResponse` (#7091) + +### web3-rpc-providers + +- RC release + +### Fixed + +#### web3-eth-ens + +- `getName` reverse resolution + +## [Unreleased] diff --git a/packages/web3-core/CHANGELOG.md b/packages/web3-core/CHANGELOG.md index 6c8e6a2a7e2..67ef64ece5b 100644 --- a/packages/web3-core/CHANGELOG.md +++ b/packages/web3-core/CHANGELOG.md @@ -221,8 +221,10 @@ Documentation: - Set a try catch block if processesingError fails (#7022) -## [Unreleased] +## [4.5.0] ### Added -- Now when existing packages are added in web3, will be avalible for plugins via context. (#7088) \ No newline at end of file +- Now when existing packages are added in web3, will be avalible for plugins via context. (#7088) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-core/package.json b/packages/web3-core/package.json index 865aafd0db6..a619cfbbc1c 100644 --- a/packages/web3-core/package.json +++ b/packages/web3-core/package.json @@ -1,6 +1,6 @@ { "name": "web3-core", - "version": "4.4.0", + "version": "4.5.0", "description": "Web3 core tools for sub-packages. This is an internal package.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -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.6.0", + "web3-types": "^1.7.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 e5dea285207..2eb11d79a13 100644 --- a/packages/web3-eth-ens/CHANGELOG.md +++ b/packages/web3-eth-ens/CHANGELOG.md @@ -159,7 +159,7 @@ Documentation: - `defaultReturnFormat` was added to all methods that have `ReturnType` param. (#6947) -## [Unreleased] +## [4.4.0] ### Added @@ -168,4 +168,6 @@ Documentation: ### Fixed -- `getName` reverse resolution \ No newline at end of file +- `getName` reverse resolution + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-eth-ens/package.json b/packages/web3-eth-ens/package.json index 4c1865ca983..e18474e0140 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.3.0", + "version": "4.4.0", "description": "This package has ENS functions for interacting with Ethereum Name Service.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -59,12 +59,12 @@ }, "dependencies": { "@adraffy/ens-normalize": "^1.8.8", - "web3-core": "^4.4.0", + "web3-core": "^4.5.0", "web3-errors": "^1.2.0", - "web3-eth": "^4.7.0", + "web3-eth": "^4.8.0", "web3-eth-contract": "^4.5.0", "web3-net": "^4.1.0", - "web3-types": "^1.6.0", + "web3-types": "^1.7.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 98dfb42b220..2b6c0e08005 100644 --- a/packages/web3-eth/CHANGELOG.md +++ b/packages/web3-eth/CHANGELOG.md @@ -248,10 +248,12 @@ Documentation: - Fixed issue with simple transactions, Within `checkRevertBeforeSending` if there is no data set in transaction, set gas to be `21000` (#7043) -## [Unreleased] +## [4.8.0] ### Added - `sendTransaction` in `rpc_method_wrappers` accepts optional param of `TransactionMiddleware` (#7088) - WebEth has `setTransactionMiddleware` and `getTransactionMiddleware` for automatically passing to `sentTransaction` (#7088) -- `TransactionMiddleware` and `TransactionMiddleware` data types are exported (#7088) \ No newline at end of file +- `TransactionMiddleware` and `TransactionMiddleware` data types are exported (#7088) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-eth/package.json b/packages/web3-eth/package.json index 47c188743b2..336ed74df1e 100644 --- a/packages/web3-eth/package.json +++ b/packages/web3-eth/package.json @@ -1,6 +1,6 @@ { "name": "web3-eth", - "version": "4.7.0", + "version": "4.8.0", "description": "Web3 module to interact with the Ethereum blockchain and smart contracts.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -63,14 +63,14 @@ }, "dependencies": { "setimmediate": "^1.0.5", - "web3-core": "^4.4.0", + "web3-core": "^4.5.0", "web3-errors": "^1.2.0", "web3-eth-abi": "^4.2.2", "web3-eth-accounts": "^4.1.2", "web3-net": "^4.1.0", "web3-providers-ws": "^4.0.7", "web3-rpc-methods": "^1.3.0", - "web3-types": "^1.6.0", + "web3-types": "^1.7.0", "web3-utils": "^4.3.0", "web3-validator": "^2.0.6" } diff --git a/packages/web3-rpc-providers/CHANGELOG.md b/packages/web3-rpc-providers/CHANGELOG.md index 87f56484e8e..1909cc7a509 100644 --- a/packages/web3-rpc-providers/CHANGELOG.md +++ b/packages/web3-rpc-providers/CHANGELOG.md @@ -35,4 +35,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 --> +## [1.0.0.rc.0] + +#### Added + +- RC release + ## [Unreleased] diff --git a/packages/web3-rpc-providers/package.json b/packages/web3-rpc-providers/package.json index a3046999279..6904037773a 100644 --- a/packages/web3-rpc-providers/package.json +++ b/packages/web3-rpc-providers/package.json @@ -1,6 +1,6 @@ { "name": "web3-rpc-providers", - "version": "0.1.0", + "version": "1.0.0-rc.0", "description": "Web3 Providers package", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -58,7 +58,7 @@ "dependencies": { "web3-providers-http": "^4.1.0", "web3-providers-ws": "^4.0.7", - "web3-types": "^1.6.0", - "web3-utils": "^4.2.3" + "web3-types": "^1.7.0", + "web3-utils": "^4.3.0" } } diff --git a/packages/web3-types/CHANGELOG.md b/packages/web3-types/CHANGELOG.md index 638d9616377..9fba5349a3c 100644 --- a/packages/web3-types/CHANGELOG.md +++ b/packages/web3-types/CHANGELOG.md @@ -195,3 +195,12 @@ Documentation: - Added `signature` to type `AbiFunctionFragment` (#6922) - update type `Withdrawals`, `block` and `BlockHeaderOutput` to include properties of eip 4844, 4895, 4788 (#6933) + +## [1.7.0] + +### Added + +- Added `result` as optional `never` and `error` as optional `never in type `JsonRpcNotification` (#7091) +- Added `JsonRpcNotfication` as a union type in `JsonRpcResponse` (#7091) + +## [Unreleased] 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/CHANGELOG.md b/packages/web3/CHANGELOG.md index c66601be9ed..2e649c3ee0f 100644 --- a/packages/web3/CHANGELOG.md +++ b/packages/web3/CHANGELOG.md @@ -266,12 +266,119 @@ Documentation: ### Added +#### web3 + - Updated type `Web3EthInterface.accounts` to includes `privateKeyToAccount`,`privateKeyToAddress`,and `privateKeyToPublicKey` (#6762) -## [Unreleased] +#### web3-core + +- `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) +- `getTransactionFromOrToAttr`, `waitForTransactionReceipt`, `trySendTransaction`, `SendTxHelper` was exported (#7000) + +#### 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) + +#### 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 + +#### 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 + +- `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 + +#### web3-core + +- Interface `RequestManagerMiddleware` was changed (#7003) + +#### 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-eth-abi + +- Dependencies updated + +#### web3-rpc-methods + +- Change `estimateGas` method to add possibility pass Transaction type (#7000) + +## [4.10.0] ### Added #### web3 -- Now when existing packages are added in web3, will be avalible for plugins via context. (#7088) \ No newline at end of file +- Now when existing packages are added in web3, will be avalible for plugins via context. (#7088) + +#### web3-core + +- Now when existing packages are added in web3, will be avalible for plugins via context. (#7088) + +#### web3-eth + +- `sendTransaction` in `rpc_method_wrappers` accepts optional param of `TransactionMiddleware` (#7088) +- WebEth has `setTransactionMiddleware` and `getTransactionMiddleware` for automatically passing to `sentTransaction` (#7088) + +#### web3-eth-ens + +- `getText` now supports first param Address +- `getName` has optional second param checkInterfaceSupport + +### web3-types + +- Added `result` as optional `never` and `error` as optional `never in type `JsonRpcNotification` (#7091) +- Added `JsonRpcNotfication` as a union type in `JsonRpcResponse` (#7091) + +### web3-rpc-providers + +- RC release + +### Fixed + +#### web3-eth-ens + +- `getName` reverse resolution + +## [Unreleased] diff --git a/packages/web3/package.json b/packages/web3/package.json index 7627ff6826b..5d05fa85923 100644 --- a/packages/web3/package.json +++ b/packages/web3/package.json @@ -1,6 +1,6 @@ { "name": "web3", - "version": "4.9.0", + "version": "4.10.0", "description": "Ethereum JavaScript API", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -86,22 +86,22 @@ "web3-providers-ipc": "^4.0.7" }, "dependencies": { - "web3-core": "^4.4.0", + "web3-core": "^4.5.0", "web3-errors": "^1.2.0", - "web3-eth": "^4.7.0", + "web3-eth": "^4.8.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", + "web3-eth-ens": "^4.4.0", "web3-eth-iban": "^4.0.7", "web3-eth-personal": "^4.0.8", "web3-net": "^4.1.0", "web3-providers-http": "^4.1.0", "web3-providers-ws": "^4.0.7", "web3-rpc-methods": "^1.3.0", - "web3-types": "^1.6.0", + "web3-rpc-providers": "^1.0.0-rc.0", + "web3-types": "^1.7.0", "web3-utils": "^4.3.0", - "web3-validator": "^2.0.6", - "web3-rpc-providers": "^0.1.0" + "web3-validator": "^2.0.6" } } diff --git a/packages/web3/src/version.ts b/packages/web3/src/version.ts index 4ab9622dba7..8b07e0d3591 100644 --- a/packages/web3/src/version.ts +++ b/packages/web3/src/version.ts @@ -1 +1 @@ -/* eslint-disable header/header */ export const Web3PkgInfo = { version: '4.9.0' }; +/* eslint-disable header/header */ export const Web3PkgInfo = { version: '4.10.0' }; diff --git a/tools/web3-plugin-example/CHANGELOG.md b/tools/web3-plugin-example/CHANGELOG.md index 636ba482bed..6762e7f8b1b 100644 --- a/tools/web3-plugin-example/CHANGELOG.md +++ b/tools/web3-plugin-example/CHANGELOG.md @@ -88,8 +88,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Dependencies updated -## [Unreleased] - ### Added -Transaction middleware (#7088) \ No newline at end of file +Transaction middleware (#7088) + +## [Unreleased] \ No newline at end of file diff --git a/tools/web3-plugin-example/package.json b/tools/web3-plugin-example/package.json index 2e85b5750ce..c2463255ac8 100644 --- a/tools/web3-plugin-example/package.json +++ b/tools/web3-plugin-example/package.json @@ -1,6 +1,6 @@ { "name": "web3-plugin-example", - "version": "1.0.6", + "version": "1.1.0", "description": "Example implementations of Web3.js' 4.x plugin system", "repository": "https://github.com/ChainSafe/web3.js", "engines": { @@ -45,19 +45,19 @@ "prettier": "^2.7.1", "ts-jest": "^29.1.1", "typescript": "^4.7.4", - "web3": "^4.3.0", - "web3-core": "^4.3.2", - "web3-eth-abi": "^4.1.4", - "web3-eth-contract": "^4.1.4", - "web3-types": "^1.3.1", - "web3-utils": "^4.1.0" + "web3": "^4.10.0", + "web3-core": "^4.5.0", + "web3-eth-abi": "^4.2.2", + "web3-eth-contract": "^4.5.0", + "web3-types": "^1.7.0", + "web3-utils": "^4.3.0" }, "peerDependencies": { "web3-core": ">= 4.1.1 < 5", + "web3-eth": ">= 4.7.0 < 5", "web3-eth-abi": ">= 4.1.1 < 5", "web3-eth-contract": ">= 4.0.5 < 5", "web3-types": ">= 1.1.1 < 5", - "web3-utils": ">= 4.0.5 < 5", - "web3-eth": ">= 4.7.0 < 5" + "web3-utils": ">= 4.0.5 < 5" } } From e47e1da37709c640703ed714fefb9b9469125b8f Mon Sep 17 00:00:00 2001 From: Oleksii Kosynskyi Date: Mon, 17 Jun 2024 12:21:17 -0400 Subject: [PATCH 102/186] EIP 712 fixes (#7095) * Fix encodeData error condition * hash fixes * lint:fix * revert some changes * revert noPreamble * revert recover * fix integration tests * fix integration tests --- packages/web3-eth-abi/src/eip_712.ts | 21 +++--- packages/web3-eth-accounts/src/account.ts | 71 +++++++++--------- .../src/tx/baseTransaction.ts | 6 +- packages/web3-utils/src/hash.ts | 72 +++++++++---------- packages/web3/test/integration/web3.test.ts | 14 ++-- scripts/system_tests_utils.ts | 11 +-- 6 files changed, 100 insertions(+), 95 deletions(-) diff --git a/packages/web3-eth-abi/src/eip_712.ts b/packages/web3-eth-abi/src/eip_712.ts index 5a46df80be4..bb6485b319d 100644 --- a/packages/web3-eth-abi/src/eip_712.ts +++ b/packages/web3-eth-abi/src/eip_712.ts @@ -17,12 +17,12 @@ along with web3.js. If not, see . /** * The web3.eth.abi functions let you encode and decode parameters to ABI (Application Binary Interface) for function calls to the EVM (Ethereum Virtual Machine). - * + * * For using Web3 ABI functions, first install Web3 package using `npm i web3` or `yarn add web3`. - * After that, Web3 ABI functions will be available. + * After that, Web3 ABI functions will be available. * ```ts * import { Web3 } from 'web3'; - * + * * const web3 = new Web3(); * const encoded = web3.eth.abi.encodeFunctionSignature({ * name: 'myMethod', @@ -35,14 +35,14 @@ along with web3.js. If not, see . * name: 'myString' * }] * }); - * + * * ``` - * + * * For using individual package install `web3-eth-abi` package using `npm i web3-eth-abi` or `yarn add web3-eth-abi` and only import required functions. - * This is more efficient approach for building lightweight applications. + * This is more efficient approach for building lightweight applications. * ```ts * import { encodeFunctionSignature } from 'web3-eth-abi'; - * + * * const encoded = encodeFunctionSignature({ * name: 'myMethod', * type: 'function', @@ -54,13 +54,12 @@ along with web3.js. If not, see . * name: 'myString' * }] * }); - * + * * ``` - * + * * @module ABI */ - // This code was taken from: https://github.com/Mrtenz/eip-712/tree/master import { Eip712TypedData } from 'web3-types'; @@ -231,7 +230,7 @@ const encodeData = ( ): string => { const [types, values] = typedData.types[type].reduce<[string[], unknown[]]>( ([_types, _values], field) => { - if (isNullish(data[field.name]) || isNullish(data[field.name])) { + if (isNullish(data[field.name]) || isNullish(field.type)) { throw new AbiError(`Cannot encode data: missing data for '${field.name}'`, { data, field, diff --git a/packages/web3-eth-accounts/src/account.ts b/packages/web3-eth-accounts/src/account.ts index 3bb49217192..a2d1fffe191 100644 --- a/packages/web3-eth-accounts/src/account.ts +++ b/packages/web3-eth-accounts/src/account.ts @@ -17,29 +17,29 @@ along with web3.js. If not, see . /** * The web3 accounts package contains functions to generate Ethereum accounts and sign transactions & data. - * + * * For using accounts functions, first install Web3 package using `npm i web3` or `yarn add web3` based on your package manager usage. - * After that, Accounts functions will be available as mentioned in following snippet. + * After that, Accounts functions will be available as mentioned in following snippet. * ```ts * import {Web3} from 'web3'; - * + * * const web3 = new Web3(); * const account = web3.eth.accounts.create(); * const result = web3.eth.accounts.hashMessage("Test Message"); - * + * * ``` - * + * * For using individual package install `web3-eth-accounts` package using `npm i web3-eth-accounts` or `yarn add web3-eth-accounts` and only import required functions. - * This is more efficient approach for building lightweight applications. + * This is more efficient approach for building lightweight applications. * ```ts * import {create,hashMessage} from 'web3-eth-accounts'; - * + * * const account = create(); * const result = hashMessage("Test Message"); - * + * * ``` * @module Accounts - * + * */ import { @@ -98,24 +98,23 @@ import type { SignResult, } from './types.js'; - /** * Get the private key Uint8Array after the validation. - * Note: This function is not exported through main web3 package, so for using it directly import from accounts package. + * Note: This function is not exported through main web3 package, so for using it directly import from accounts package. * @param data - Private key - * @param ignoreLength - Optional, ignore length check during validation + * @param ignoreLength - Optional, ignore length check during validation * @returns The Uint8Array private key * * ```ts * parseAndValidatePrivateKey("0x08c673022000ece7964ea4db2d9369c50442b2869cbd8fc21baaca59e18f642c") - * + * * > Uint8Array(32) [ * 186, 26, 143, 168, 235, 179, 90, 75, * 101, 63, 84, 221, 152, 150, 30, 203, * 8, 113, 94, 226, 53, 213, 216, 5, * 194, 159, 17, 53, 219, 97, 121, 248 * ] - * + * * ``` */ export const parseAndValidatePrivateKey = (data: Bytes, ignoreLength?: boolean): Uint8Array => { @@ -127,7 +126,7 @@ export const parseAndValidatePrivateKey = (data: Bytes, ignoreLength?: boolean): } try { - privateKeyUint8Array = isUint8Array(data) ? (data ) : bytesToUint8Array(data); + privateKeyUint8Array = isUint8Array(data) ? data : bytesToUint8Array(data); } catch { throw new InvalidPrivateKeyError(); } @@ -149,11 +148,11 @@ export const parseAndValidatePrivateKey = (data: Bytes, ignoreLength?: boolean): * * ```ts * web3.eth.accounts.hashMessage("Hello world") - * + * * > "0x8144a6fa26be252b86456491fbcd43c1de7e022241845ffea1c3df066f7cfede" - * + * * web3.eth.accounts.hashMessage(web3.utils.utf8ToHex("Hello world")) // Will be hex decoded in hashMessage - * + * * > "0x8144a6fa26be252b86456491fbcd43c1de7e022241845ffea1c3df066f7cfede" * ``` */ @@ -228,7 +227,7 @@ export const sign = (data: string, privateKey: Bytes): SignResult => { * Signing a legacy transaction * ```ts * import {signTransaction, Transaction} from 'web3-eth-accounts'; - * + * * signTransaction(new Transaction({ * to: '0x118C2E5F57FD62C2B5b46a5ae9216F4FF4011a07', * value: '0x186A0', @@ -238,7 +237,7 @@ export const sign = (data: string, privateKey: Bytes): SignResult => { * chainId: 1, * nonce: 0 }), * '0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318') - * + * * > { * messageHash: '0x28b7b75f7ba48d588a902c1ff4d5d13cc0ca9ac0aaa39562368146923fb853bf', * v: '0x25', @@ -247,11 +246,11 @@ export const sign = (data: string, privateKey: Bytes): SignResult => { * rawTransaction: '0xf869808609184e72a0008352081294118c2e5f57fd62c2b5b46a5ae9216f4ff4011a07830186a08025a00601b0017b0e20dd0eeda4b895fbc1a9e8968990953482214f880bae593e71b5a0690d984493560552e3ebdcc19a65b9c301ea9ddc82d3ab8cfde60485fd5722ce', * transactionHash: '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470' * ``` - * + * * Signing an eip 1559 transaction * ```ts * import {signTransaction, Transaction} from 'web3-eth-accounts'; - * + * * signTransaction(new Transaction({ * to: '0xF0109fC8DF283027b6285cc889F5aA624EaC1F55', * maxPriorityFeePerGas: '0x3B9ACA00', @@ -271,11 +270,11 @@ export const sign = (data: string, privateKey: Bytes): SignResult => { * transactionHash: '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470' * } * ``` - * + * * Signing an eip 2930 transaction * ```ts * import {signTransaction, Transaction} from 'web3-eth-accounts'; - * + * * signTransaction(new Transaction ({ * chainId: 1, * nonce: 0, @@ -294,7 +293,7 @@ export const sign = (data: string, privateKey: Bytes): SignResult => { * }, * ], * }),"0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318") - * + * * > { * messageHash: '0xc55ea24bdb4c379550a7c9a6818ac39ca33e75bc78ddb862bd82c31cc1c7a073', * v: '0x26', @@ -366,11 +365,11 @@ export const recoverTransaction = (rawTransaction: HexString): Address => { * @param s - S value in signature * @param prefixed - (default: false) If the last parameter is true, the given message will NOT automatically be prefixed with `"\\x19Ethereum Signed Message:\\n" + message.length + message`, and assumed to be already prefixed. * @returns The Ethereum address used to sign this data - * + * * ```ts * const data = 'Some data'; * const sigObj = web3.eth.accounts.sign(data, '0xbe6383dad004f233317e46ddb46ad31b16064d14447a95cc1d8c8d4bc61c3728') - * + * * > { * message: 'Some data', * messageHash: '0x1da44b586eb0729ff70a73c326926f6ed5a25f5b056e7f47fbc6e58d86871655', @@ -379,10 +378,10 @@ export const recoverTransaction = (rawTransaction: HexString): Address => { * s: '0x53e41351267b20d4a89ebfe9c8f03c04de9b345add4a52f15bd026b63c8fb150', * signature: '0xa8037a6116c176a25e6fc224947fde9e79a2deaa0dd8b67b366fbdfdbffc01f953e41351267b20d4a89ebfe9c8f03c04de9b345add4a52f15bd026b63c8fb1501b' * } - * + * * // now recover * web3.eth.accounts.recover(data, sigObj.v, sigObj.r, sigObj.s) - * + * * > 0xEB014f8c8B418Db6b45774c326A0E64C78914dC0 * ``` */ @@ -422,7 +421,7 @@ export const recover = ( const address = toChecksumAddress(`0x${publicHash.slice(-40)}`); return address; -};; +}; /** * Get the ethereum Address from a private key @@ -433,7 +432,7 @@ export const recover = ( * @example * ```ts * web3.eth.accounts.privateKeyToAddress("0xbe6383dad004f233317e46ddb46ad31b16064d14447a95cc1d8c8d4bc61c3728") - * + * * > "0xEB014f8c8B418Db6b45774c326A0E64C78914dC0" * ``` */ @@ -462,7 +461,7 @@ export const privateKeyToAddress = (privateKey: Bytes): string => { * @example * ```ts * web3.eth.accounts.privateKeyToPublicKey("0x1e046a882bb38236b646c9f135cf90ad90a140810f439875f2a6dd8e50fa261f", true) - * + * * > "0x42beb65f179720abaa3ec9a70a539629cbbc5ec65bb57e7fc78977796837e537662dd17042e6449dc843c281067a4d6d8d1a1775a13c41901670d5de7ee6503a" // uncompressed public key * ``` */ @@ -485,7 +484,7 @@ export const privateKeyToPublicKey = (privateKey: Bytes, isCompressed: boolean): * * Encrypt using scrypt options: * ```ts - * + * * web3.eth.accounts.encrypt( * '0x67f476289210e3bef3c1c75e4de993ff0a00663df00def84e73aa7411eac18a6', * '123', @@ -659,7 +658,7 @@ export const encrypt = async ( * * ```ts * web3.eth.accounts.privateKeyToAccount("0x348ce564d427a3311b6536bbcff9390d69395b06ed6c486954e971d960fe8709"); - * + * * > { * address: '0xb8CE9ab6943e0eCED004cDe8e3bBed6568B2Fa01', * privateKey: '0x348ce564d427a3311b6536bbcff9390d69395b06ed6c486954e971d960fe8709', @@ -740,8 +739,8 @@ export const create = (): Web3Account => { * mac: 'efbf6d3409f37c0084a79d5fdf9a6f5d97d11447517ef1ea8374f51e581b7efd' * } * }, '123').then(console.log); - * - * + * + * * > { * address: '0xcdA9A91875fc35c8Ac1320E098e584495d66e47c', * privateKey: '67f476289210e3bef3c1c75e4de993ff0a00663df00def84e73aa7411eac18a6', diff --git a/packages/web3-eth-accounts/src/tx/baseTransaction.ts b/packages/web3-eth-accounts/src/tx/baseTransaction.ts index 3f8da6d4e41..5762b8889e9 100644 --- a/packages/web3-eth-accounts/src/tx/baseTransaction.ts +++ b/packages/web3-eth-accounts/src/tx/baseTransaction.ts @@ -578,7 +578,11 @@ export abstract class BaseTransaction { return postfix; } // eslint-disable-next-line class-methods-use-this - private _ecsign(msgHash: Uint8Array, privateKey: Uint8Array, chainId?: bigint): ECDSASignature { + protected _ecsign( + msgHash: Uint8Array, + privateKey: Uint8Array, + chainId?: bigint, + ): ECDSASignature { const signature = secp256k1.sign(msgHash, privateKey); const signatureBytes = signature.toCompactRawBytes(); diff --git a/packages/web3-utils/src/hash.ts b/packages/web3-utils/src/hash.ts index 0289a429a52..d8d959e4509 100644 --- a/packages/web3-utils/src/hash.ts +++ b/packages/web3-utils/src/hash.ts @@ -73,6 +73,41 @@ import { leftPad, rightPad, toTwosComplement } from './string_manipulation.js'; const SHA3_EMPTY_BYTES = '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470'; +/** + * A wrapper for ethereum-cryptography/keccak256 to allow hashing a `string` and a `bigint` in addition to `UInt8Array` + * @param data - the input to hash + * @returns - the Keccak-256 hash of the input + * + * @example + * ```ts + * console.log(web3.utils.keccak256Wrapper('web3.js')); + * > 0x63667efb1961039c9bb0d6ea7a5abdd223a3aca7daa5044ad894226e1f83919a + * + * console.log(web3.utils.keccak256Wrapper(1)); + * > 0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6 + * + * console.log(web3.utils.keccak256Wrapper(0xaf12fd)); + * > 0x358640fd4719fa923525d74ab5ae80a594301aba5543e3492b052bf4598b794c + * ``` + */ +export const keccak256Wrapper = ( + data: Bytes | Numbers | string | ReadonlyArray, +): string => { + let processedData; + if (typeof data === 'bigint' || typeof data === 'number') { + processedData = utf8ToBytes(data.toString()); + } else if (Array.isArray(data)) { + processedData = new Uint8Array(data); + } else if (typeof data === 'string' && !isHexStrict(data)) { + processedData = utf8ToBytes(data); + } else { + processedData = bytesToUint8Array(data as Bytes); + } + return bytesToHex(keccak256(validatorUtils.ensureIfUint8Array(processedData))); +}; + +export { keccak256Wrapper as keccak256 }; + /** * computes the Keccak-256 hash of the input and returns a hexstring * @param data - the input to hash @@ -99,7 +134,7 @@ export const sha3 = (data: Bytes): string | undefined => { } else { updatedData = data; } - const hash = bytesToHex(keccak256(validatorUtils.ensureIfUint8Array(updatedData))); + const hash = keccak256Wrapper(updatedData); // EIP-1052 if hash is equal to c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470, keccak was given empty data return hash === SHA3_EMPTY_BYTES ? undefined : hash; @@ -128,41 +163,6 @@ export const sha3Raw = (data: Bytes): string => { return hash; }; -/** - * A wrapper for ethereum-cryptography/keccak256 to allow hashing a `string` and a `bigint` in addition to `UInt8Array` - * @param data - the input to hash - * @returns - the Keccak-256 hash of the input - * - * @example - * ```ts - * console.log(web3.utils.keccak256Wrapper('web3.js')); - * > 0x63667efb1961039c9bb0d6ea7a5abdd223a3aca7daa5044ad894226e1f83919a - * - * console.log(web3.utils.keccak256Wrapper(1)); - * > 0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6 - * - * console.log(web3.utils.keccak256Wrapper(0xaf12fd)); - * > 0x358640fd4719fa923525d74ab5ae80a594301aba5543e3492b052bf4598b794c - * ``` - */ -export const keccak256Wrapper = ( - data: Bytes | Numbers | string | ReadonlyArray, -): string => { - let processedData; - if (typeof data === 'bigint' || typeof data === 'number') { - processedData = utf8ToBytes(data.toString()); - } else if (Array.isArray(data)) { - processedData = new Uint8Array(data); - } else if (typeof data === 'string' && !isHexStrict(data)) { - processedData = utf8ToBytes(data); - } else { - processedData = bytesToUint8Array(data as Bytes); - } - return bytesToHex(keccak256(validatorUtils.ensureIfUint8Array(processedData))); -}; - -export { keccak256Wrapper as keccak256 }; - /** * returns type and value * @param arg - the input to return the type and value diff --git a/packages/web3/test/integration/web3.test.ts b/packages/web3/test/integration/web3.test.ts index 37587954bb0..54720890901 100644 --- a/packages/web3/test/integration/web3.test.ts +++ b/packages/web3/test/integration/web3.test.ts @@ -35,7 +35,7 @@ import { isSocket, isWs, itIf, - waitForOpenConnection + waitForOpenConnection, } from '../shared_fixtures/system_tests_utils'; /* eslint-disable jest/no-standalone-expect */ @@ -58,7 +58,7 @@ describe('Web3 instance', () => { try { await closeOpenConnection(web3); } catch (e) { - console.warn("Failed to close open con", e) + console.warn('Failed to close open con', e); } }); @@ -67,7 +67,11 @@ describe('Web3 instance', () => { }); afterEach(async () => { - if (isWs) { + if ( + isWs && + web3?.provider?.supportsSubscriptions && + web3.provider?.supportsSubscriptions() + ) { // make sure we try to close the connection after it is established if ( web3?.provider && @@ -126,7 +130,6 @@ describe('Web3 instance', () => { it('should be able use "utils"', () => { web3 = new Web3(); - expect(web3.utils.hexToNumber('0x5')).toBe(5); }); @@ -312,7 +315,7 @@ describe('Web3 instance', () => { } catch (e) { // ignored } - }) + }); it('should update defaults on contract instance', () => { const hardfork = 'berlin'; @@ -331,6 +334,5 @@ describe('Web3 instance', () => { // ignored } }); - }); }); diff --git a/scripts/system_tests_utils.ts b/scripts/system_tests_utils.ts index da58fc19d91..48ea2129c06 100644 --- a/scripts/system_tests_utils.ts +++ b/scripts/system_tests_utils.ts @@ -154,10 +154,14 @@ export const waitForOpenConnection = async ( }); export const closeOpenConnection = async (web3Context: Web3Context) => { - if (!isSocket || web3Context?.provider instanceof HttpProvider) { + if ( + !isSocket || + web3Context?.provider instanceof HttpProvider || + (web3Context?.provider?.supportsSubscriptions && + !web3Context.provider?.supportsSubscriptions()) + ) { return; } - // make sure we try to close the connection after it is established if ( web3Context?.provider && @@ -165,20 +169,17 @@ export const closeOpenConnection = async (web3Context: Web3Context) => { ) { await waitForOpenConnection(web3Context); } - // If an error happened during closing, that is acceptable at tests, just print a 'warn'. if (web3Context?.provider) { (web3Context.provider as unknown as Web3BaseProvider).on('error', (err: any) => { console.warn('error while trying to close the connection', err); }); } - // Wait a bit to ensure the connection does not have a pending data that // could cause an error if written after closing the connection. await new Promise(resolve => { setTimeout(resolve, 500); }); - if ( web3Context?.provider && 'disconnect' in (web3Context.provider as unknown as Web3BaseProvider) From bfe276956517245d580af53c2c28203825572bc8 Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 17 Jun 2024 22:56:02 -0400 Subject: [PATCH 103/186] add geth fault tolerance tests (#7104) * add geth tests * update tests * update * update scripts --------- Co-authored-by: Oleksii Kosynskyi --- packages/web3-providers-ws/package.json | 3 +- ...e.test.ts => geth_fault_tolerance.test.ts} | 283 +++++++++--------- scripts/geth.sh | 5 +- 3 files changed, 147 insertions(+), 144 deletions(-) rename packages/web3-providers-ws/test/integration/{ganache_fault_tolerance.test.ts => geth_fault_tolerance.test.ts} (62%) diff --git a/packages/web3-providers-ws/package.json b/packages/web3-providers-ws/package.json index b3612afaa23..59153fda4b9 100644 --- a/packages/web3-providers-ws/package.json +++ b/packages/web3-providers-ws/package.json @@ -58,7 +58,8 @@ "jest-extended": "^3.0.1", "prettier": "^2.7.1", "ts-jest": "^29.1.1", - "typescript": "^4.7.4" + "typescript": "^4.7.4", + "web3-providers-http": "^4.1.0" }, "dependencies": { "@types/ws": "8.5.3", diff --git a/packages/web3-providers-ws/test/integration/ganache_fault_tolerance.test.ts b/packages/web3-providers-ws/test/integration/geth_fault_tolerance.test.ts similarity index 62% rename from packages/web3-providers-ws/test/integration/ganache_fault_tolerance.test.ts rename to packages/web3-providers-ws/test/integration/geth_fault_tolerance.test.ts index 30078527ca2..a047666dccb 100644 --- a/packages/web3-providers-ws/test/integration/ganache_fault_tolerance.test.ts +++ b/packages/web3-providers-ws/test/integration/geth_fault_tolerance.test.ts @@ -15,10 +15,11 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ -import { ProviderRpcError } from 'web3-types/src/web3_api_types'; -import ganache from 'ganache'; -import { EthExecutionAPI, Web3APIPayload, SocketRequestItem, JsonRpcResponse } from 'web3-types'; -import { InvalidResponseError, ConnectionNotOpenError } from 'web3-errors'; +import { + HttpProvider +} from 'web3-providers-http'; +import { ConnectionNotOpenError } from 'web3-errors'; +import { EthExecutionAPI, Web3APIPayload, SocketRequestItem, JsonRpcResponse, ProviderRpcError } from 'web3-types'; import { Web3DeferredPromise } from 'web3-utils'; import { waitForSocketConnect, @@ -27,36 +28,60 @@ import { getSystemTestBackend, isWs, } from '../fixtures/system_test_utils'; -import WebSocketProvider from '../../src/index'; - -// create helper functions to open server -describeIf(getSystemTestBackend() === 'ganache' && isWs)('ganache tests', () => { - describe('WebSocketProvider - ganache', () => { - jest.setTimeout(17000); - const port = 7547; - const host = `ws://localhost:${port}`; - const jsonRpcPayload = { - jsonrpc: '2.0', - id: 43, - method: 'eth_mining', - } as Web3APIPayload; - - // simulate abrupt disconnection, ganache server always closes with code 1000 so we need to simulate closing with different error code - const changeCloseCode = async (webSocketProvider: WebSocketProvider) => - new Promise(resolve => { - // @ts-expect-error replace close handler - // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-param-reassign - webSocketProvider._onCloseHandler = (_: CloseEvent) => { - // @ts-expect-error replace close event - webSocketProvider._onCloseEvent({ code: 1003 }); - }; - // @ts-expect-error run protected method - webSocketProvider._removeSocketListeners(); - // @ts-expect-error run protected method - webSocketProvider._addSocketListeners(); - resolve(); - }); +import { WebSocketProvider } from '../../src'; + +describeIf(getSystemTestBackend() === 'geth' && isWs)('geth tests', () => { + const wsProviderUrl = 'ws://127.0.0.1:3333'; + const httpProviderUrl = 'http://127.0.0.1:3333'; + let httpProvider: HttpProvider; + const openServer = async () => { + await httpProvider.request({ + method: 'admin_startWS', + id: '1', + jsonrpc: '2.0' + }) + } + const closeServer = async () => { + await httpProvider.request({ + method: 'admin_stopWS', + id: '2', + jsonrpc: '2.0' + }); + }; + const jsonRpcPayload = { + jsonrpc: '2.0', + id: 43, + method: 'eth_mining', + } as Web3APIPayload; + + // simulate abrupt disconnection, ganache server always closes with code 1000 so we need to simulate closing with different error code + const changeCloseCode = async (webSocketProvider: WebSocketProvider) => + new Promise(resolve => { + // @ts-expect-error replace close handler + // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-param-reassign + webSocketProvider._onCloseHandler = (_: CloseEvent) => { + // @ts-expect-error replace close event + webSocketProvider._onCloseEvent({ code: 1003 }); + }; + // @ts-expect-error run protected method + webSocketProvider._removeSocketListeners(); + // @ts-expect-error run protected method + webSocketProvider._addSocketListeners(); + resolve(); + }); + beforeAll(() => { + httpProvider = new HttpProvider(httpProviderUrl); + }) + beforeEach(async () => { + await openServer(); + }) + afterAll(async() => { + await closeServer(); + }) + + + describe('WebSocketProvider fault tests - geth', () => { it('"error" when there is no connection', async () => { const reconnectionOptions = { delay: 100, @@ -76,48 +101,51 @@ describeIf(getSystemTestBackend() === 'ganache' && isWs)('ganache tests', () => ); }); - it('"error" handler fires if the client closes unilaterally', async () => { - const server = ganache.server(); - await server.listen(port); - const webSocketProvider = new WebSocketProvider(host); + it('"discconect" handler fires if the server closes', async () => { + await openServer(); + const err = jest.fn(); + const webSocketProvider = new WebSocketProvider(wsProviderUrl, {}, { + delay: 100, + autoReconnect: false, + maxAttempts: 1, + }); await waitForSocketConnect(webSocketProvider); - const disconnectPromise = waitForEvent(webSocketProvider, 'disconnect'); - await server.close(); - expect(!!(await disconnectPromise)).toBe(true); + webSocketProvider.on('disconnect', () => { + err(); + }); + const errorPromise = waitForEvent(webSocketProvider, 'disconnect'); + // await server.close(); + await closeServer(); + await errorPromise; + expect(err).toHaveBeenCalled(); webSocketProvider.disconnect(); }); - it('"error" handler *DOES NOT* fire if disconnection is clean', async () => { - const server = ganache.server(); - await server.listen(port); + await openServer(); const reconnectOptions = { autoReconnect: false, }; - const webSocketProvider = new WebSocketProvider(host, {}, reconnectOptions); + const webSocketProvider = new WebSocketProvider(wsProviderUrl, {}, reconnectOptions); await waitForSocketConnect(webSocketProvider); const mockReject = jest.fn(); + const mockDisconnect = jest.fn(); webSocketProvider.once('error', () => { mockReject(); }); + webSocketProvider.once('disconnect', () => { + mockDisconnect(); + }) webSocketProvider.disconnect(); - await new Promise(resolve => { - setTimeout(() => { - resolve(true); - }, 100); - }); expect(mockReject).toHaveBeenCalledTimes(0); - - await server.close(); + expect(mockDisconnect).toHaveBeenCalledTimes(1); }); - it('can connect after being disconnected', async () => { - const server = ganache.server(); - await server.listen(port); + await openServer(); - const webSocketProvider = new WebSocketProvider(host); + const webSocketProvider = new WebSocketProvider(wsProviderUrl); const mockCallback = jest.fn(); const connectPromise = new Promise(resolve => { webSocketProvider.once('connect', () => { @@ -140,51 +168,73 @@ describeIf(getSystemTestBackend() === 'ganache' && isWs)('ganache tests', () => await connectPromise2; webSocketProvider.disconnect(); expect(mockCallback).toHaveBeenCalledTimes(2); - await server.close(); }); - it('webSocketProvider supports subscriptions', async () => { - const server = ganache.server(); - await server.listen(port); - const webSocketProvider = new WebSocketProvider(host); + const webSocketProvider = new WebSocketProvider(wsProviderUrl); await waitForSocketConnect(webSocketProvider); expect(webSocketProvider.supportsSubscriptions()).toBe(true); webSocketProvider.disconnect(); - await server.close(); }); - + // TODO: investigate this test + // it('times out when connection is lost mid-chunk', async () => { + // const reconnectionOptions = { + // delay: 0, + // autoReconnect: false, + // maxAttempts: 0, + // }; + // const webSocketProvider = new WebSocketProvider(wsProviderUrl, {}, reconnectionOptions); + // await waitForSocketConnect(webSocketProvider); + // await closeServer(); + + // const errorPromise = new Promise(resolve => { + // webSocketProvider.on('error', (err: any) => { + // expect(err).toBeInstanceOf(Error); + // if (err.cause.message === 'Chunk timeout') { + // resolve(true); + // } + // }); + // }); + // // send an event to be parsed and fail + // const event = { + // data: 'abc|--|ded', + // type: 'websocket', + // // @ts-expect-error run protected method + // target: webSocketProvider._socketConnection, + // }; + // // @ts-expect-error run protected method + // webSocketProvider._parseResponses(event); // simulate chunks + // await errorPromise; + // expect(true).toBe(true); + // }); it('times out when server is closed', async () => { - const server = ganache.server(); - await server.listen(port); const reconnectionOptions = { delay: 100, autoReconnect: false, maxAttempts: 1, }; - const webSocketProvider = new WebSocketProvider(host, {}, reconnectionOptions); + const webSocketProvider = new WebSocketProvider(wsProviderUrl, {}, reconnectionOptions); const mockCallBack = jest.fn(); const errorPromise = new Promise(resolve => { - webSocketProvider.on('error', (err: unknown) => { - if ((err as ProviderRpcError)?.message.startsWith('connect ECONNREFUSED')) { - mockCallBack(); - resolve(true); - } + webSocketProvider.on('error', () => { + mockCallBack(); + resolve(true); }); }); - await server.close(); + await closeServer(); await errorPromise; expect(mockCallBack).toHaveBeenCalled(); + webSocketProvider.disconnect(); }); - it('with reconnect on, will try to connect until server is open then close', async () => { + await closeServer(); const reconnectionOptions = { delay: 10, autoReconnect: true, maxAttempts: 100, }; - const webSocketProvider = new WebSocketProvider(host, {}, reconnectionOptions); + const webSocketProvider = new WebSocketProvider(wsProviderUrl, {}, reconnectionOptions); const mockCallback = jest.fn(); const connectPromise = new Promise(resolve => { @@ -193,12 +243,9 @@ describeIf(getSystemTestBackend() === 'ganache' && isWs)('ganache tests', () => resolve(true); }); }); - - const server = ganache.server(); - await server.listen(port); + await openServer(); await connectPromise; webSocketProvider.disconnect(); - await server.close(); expect(mockCallback).toHaveBeenCalledTimes(1); }); @@ -208,29 +255,25 @@ describeIf(getSystemTestBackend() === 'ganache' && isWs)('ganache tests', () => autoReconnect: true, maxAttempts: 100, }; - const webSocketProvider = new WebSocketProvider(host, {}, reconnectionOptions); + const webSocketProvider = new WebSocketProvider(wsProviderUrl, {}, reconnectionOptions); const connectPromise = waitForSocketConnect(webSocketProvider); - const server = ganache.server(); - await server.listen(port); await connectPromise; - await server.close(); const disconnectEvent = waitForEvent(webSocketProvider, 'disconnect'); + await closeServer(); webSocketProvider.disconnect(); expect(!!(await disconnectEvent)).toBe(true); }); it('errors when failing to reconnect after data is lost mid-chunk', async () => { - const server = ganache.server(); - await server.listen(port); const reconnectionOptions = { delay: 100, autoReconnect: true, maxAttempts: 1, }; const mockCallBack = jest.fn(); - const webSocketProvider = new WebSocketProvider(host, {}, reconnectionOptions); + const webSocketProvider = new WebSocketProvider(wsProviderUrl, {}, reconnectionOptions); await waitForSocketConnect(webSocketProvider); webSocketProvider.on('error', (err: any) => { @@ -239,7 +282,8 @@ describeIf(getSystemTestBackend() === 'ganache' && isWs)('ganache tests', () => } }); - await server.close(); + // await server.close(); + await closeServer(); // when server is not listening send request, and expect that lib will try to reconnect and at end will throw con not open error await expect( @@ -249,45 +293,9 @@ describeIf(getSystemTestBackend() === 'ganache' && isWs)('ganache tests', () => .rejects.toThrow(ConnectionNotOpenError); expect(mockCallBack).toHaveBeenCalled(); + webSocketProvider.disconnect(); }); - - it('times out when connection is lost mid-chunk', async () => { - const server = ganache.server(); - await server.listen(port); - const reconnectionOptions = { - delay: 0, - autoReconnect: false, - maxAttempts: 0, - }; - const webSocketProvider = new WebSocketProvider(host, {}, reconnectionOptions); - await waitForSocketConnect(webSocketProvider); - - await server.close(); - - const errorPromise = new Promise(resolve => { - webSocketProvider.on('error', (err: any) => { - expect(err).toBeInstanceOf(InvalidResponseError); - if (err.cause.message === 'Chunk timeout') { - resolve(true); - } - }); - }); - // send an event to be parsed and fail - const event = { - data: 'abc|--|ded', - type: 'websocket', - // @ts-expect-error run protected method - target: webSocketProvider._socketConnection, - }; - // @ts-expect-error run protected method - webSocketProvider._parseResponses(event); // simulate chunks - await errorPromise; - expect(true).toBe(true); - }); - it('clears pending requests on maxAttempts failed reconnection', async () => { - const server = ganache.server(); - await server.listen(port); const reconnectionOptions = { delay: 1000, autoReconnect: true, @@ -295,7 +303,7 @@ describeIf(getSystemTestBackend() === 'ganache' && isWs)('ganache tests', () => }; const mockCallBack = jest.fn(); - const webSocketProvider = new WebSocketProvider(host, {}, reconnectionOptions); + const webSocketProvider = new WebSocketProvider(wsProviderUrl, {}, reconnectionOptions); const defPromise = new Web3DeferredPromise>(); // eslint-disable-next-line @typescript-eslint/no-empty-function defPromise.catch(() => {}); @@ -322,23 +330,20 @@ describeIf(getSystemTestBackend() === 'ganache' && isWs)('ganache tests', () => resolve(true); }); }); - - await server.close(); + await closeServer(); await errorPromise; // @ts-expect-error run protected method expect(webSocketProvider._pendingRequestsQueue.size).toBe(0); expect(mockCallBack).toHaveBeenCalled(); + webSocketProvider.disconnect(); }); - it('queues requests made while connection is lost / executes on reconnect', async () => { - const server = ganache.server(); - await server.listen(port); const reconnectionOptions = { delay: 1000, autoReconnect: true, maxAttempts: 3, }; - const webSocketProvider = new WebSocketProvider(host, {}, reconnectionOptions); + const webSocketProvider = new WebSocketProvider(wsProviderUrl, {}, reconnectionOptions); await waitForSocketConnect(webSocketProvider); // simulate abrupt close code @@ -348,14 +353,13 @@ describeIf(getSystemTestBackend() === 'ganache' && isWs)('ganache tests', () => resolve(true); }); }); - await server.close(); + await closeServer(); await errorPromise; // queue a request const requestPromise = webSocketProvider.request(jsonRpcPayload); - const server2 = ganache.server(); - await server2.listen(port); + await openServer(); await waitForSocketConnect(webSocketProvider); @@ -363,19 +367,16 @@ describeIf(getSystemTestBackend() === 'ganache' && isWs)('ganache tests', () => const result = await requestPromise; expect(result.id).toEqual(jsonRpcPayload.id); webSocketProvider.disconnect(); - await server2.close(); }); it('errors when requests continue after socket closed', async () => { - const server = ganache.server(); - await server.listen(port); const reconnectOptions = { autoReconnect: false, }; - const webSocketProvider = new WebSocketProvider(host, {}, reconnectOptions); + const webSocketProvider = new WebSocketProvider(wsProviderUrl, {}, reconnectOptions); await waitForSocketConnect(webSocketProvider); const disconnectPromise = waitForEvent(webSocketProvider, 'disconnect'); - await server.close(); + await closeServer(); await disconnectPromise; const errorPromise = new Promise(resolve => { @@ -389,9 +390,7 @@ describeIf(getSystemTestBackend() === 'ganache' && isWs)('ganache tests', () => await errorPromise; }); it('deferredPromise emits an error when request fails', async () => { - const server = ganache.server(); - await server.listen(port); - const webSocketProvider = new WebSocketProvider(host); + const webSocketProvider = new WebSocketProvider(wsProviderUrl); await waitForSocketConnect(webSocketProvider); // @ts-expect-error replace sendtoSocket so we don't execute request @@ -409,7 +408,7 @@ describeIf(getSystemTestBackend() === 'ganache' && isWs)('ganache tests', () => await request; webSocketProvider.disconnect(); - await server.close(); + await closeServer(); }); }); -}); +}); \ No newline at end of file diff --git a/scripts/geth.sh b/scripts/geth.sh index 62c7213ccfb..5459fc23d31 100755 --- a/scripts/geth.sh +++ b/scripts/geth.sh @@ -20,13 +20,16 @@ start() { docker run -d -p $WEB3_SYSTEM_TEST_PORT:$WEB3_SYSTEM_TEST_PORT ethereum/client-go:v1.13.14-amd64 --nodiscover --nousb --ws --ws.addr 0.0.0.0 --ws.port $WEB3_SYSTEM_TEST_PORT --http --http.addr 0.0.0.0 --http.port $WEB3_SYSTEM_TEST_PORT --allow-insecure-unlock --http.api personal,web3,eth,admin,debug,txpool,net --ws.api personal,web3,eth,admin,debug,miner,txpool,net --dev echo "Waiting for geth..." npx wait-port -t 10000 "$WEB3_SYSTEM_TEST_PORT" + echo "docker run -d -p 3333:3333 ethereum/client-go:v1.13.14-amd64 --nodiscover --nousb --ws --ws.addr 0.0.0.0 --ws.port 3333 --http --http.addr 0.0.0.0 --http.port 3334 --allow-insecure-unlock --http.api personal,web3,eth,admin,debug,txpool,net --ws.api personal,web3,eth,admin,debug,miner,txpool,net --dev" + docker run -d -p 3333:3333 ethereum/client-go:v1.13.14-amd64 --nodiscover --nousb --ws --ws.addr 0.0.0.0 --ws.port 3333 --http --http.addr 0.0.0.0 --http.port 3333 --allow-insecure-unlock --http.api personal,web3,eth,admin,debug,txpool,net --ws.api personal,web3,eth,admin,debug,miner,txpool,net --dev + npx wait-port -t 10000 3333 echo "Geth started" fi } stop() { echo "Stopping geth ..." - docker ps -q --filter ancestor="ethereum/client-go" | xargs -r docker stop + docker ps -a -q --filter ancestor="ethereum/client-go" | xargs -r docker stop } case $1 in From 750411c3f7054b444928be8dc131ab3e1cf54b6c Mon Sep 17 00:00:00 2001 From: Junaid <86780488+jdevcs@users.noreply.github.com> Date: Tue, 25 Jun 2024 14:07:16 +0200 Subject: [PATCH 104/186] watchTransactionBySubscription fallback fix (#7118) * watchTransactionByPolling fix * watchTransactionBySubscription fallback test --- .../src/utils/watch_transaction_by_polling.ts | 4 +- .../watch_transaction_by_subscription.test.ts | 167 +++++++++--------- 2 files changed, 90 insertions(+), 81 deletions(-) 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 34e01581422..a429eabb818 100644 --- a/packages/web3-eth/src/utils/watch_transaction_by_polling.ts +++ b/packages/web3-eth/src/utils/watch_transaction_by_polling.ts @@ -56,8 +56,10 @@ export const watchTransactionByPolling = < let confirmations = 1; const intervalId = setInterval(() => { (async () => { - if (confirmations >= web3Context.transactionConfirmationBlocks) + if (confirmations >= web3Context.transactionConfirmationBlocks){ clearInterval(intervalId); + return; + } const nextBlock = await ethRpcMethods.getBlockByNumber( web3Context.requestManager, diff --git a/packages/web3-eth/test/unit/utils/watch_transaction_by_subscription.test.ts b/packages/web3-eth/test/unit/utils/watch_transaction_by_subscription.test.ts index d7f4169aeaf..23c92c793a6 100644 --- a/packages/web3-eth/test/unit/utils/watch_transaction_by_subscription.test.ts +++ b/packages/web3-eth/test/unit/utils/watch_transaction_by_subscription.test.ts @@ -14,117 +14,124 @@ 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, Web3RequestManager } from 'web3-core'; -import { format } from 'web3-utils'; -import { DEFAULT_RETURN_FORMAT, JsonRpcResponseWithResult, Web3EthExecutionAPI } from 'web3-types'; -import { ethRpcMethods } from 'web3-rpc-methods'; -import { WebSocketProvider } from 'web3-providers-ws'; + +import { Web3Context } from 'web3-core'; +import { DEFAULT_RETURN_FORMAT, Web3EthExecutionAPI } from 'web3-types'; +import WebSocketProvider from 'web3-providers-ws'; + import * as rpcMethodWrappers from '../../../src/rpc_method_wrappers'; -import * as WatchTransactionBySubscription from '../../../src/utils/watch_transaction_by_subscription'; import { expectedTransactionReceipt, expectedTransactionHash, testData, } from '../rpc_method_wrappers/fixtures/send_signed_transaction'; -import { transactionReceiptSchema } from '../../../src/schemas'; -import { registeredSubscriptions } from '../../../src'; +import { blockMockResult } from '../../fixtures/transactions_data'; + -jest.mock('web3-rpc-methods'); jest.mock('web3-providers-ws'); -jest.mock('../../../src/utils/watch_transaction_by_polling'); const testMessage = 'Title: %s\ninputSignedTransaction: %s\nexpectedTransactionHash: %s\nexpectedTransactionReceipt: %s\n'; -async function waitUntilCalled(mock: jest.Mock, timeout = 1000): Promise { - return new Promise((resolve, reject) => { - let timeoutId: NodeJS.Timeout | undefined; - const intervalId = setInterval(() => { - if (mock.mock.calls.length > 0) { - clearInterval(intervalId); - if (timeoutId) { - clearTimeout(timeoutId); - } - resolve(mock); - } - }, 100); - timeoutId = setTimeout(() => { - clearInterval(intervalId); - if (timeoutId) { - clearTimeout(timeoutId); - } - reject(new Error('timeout')); - }, timeout); - }); -} describe('watchTransactionBySubscription', () => { + const CONFIRMATION_BLOCKS = 5; describe('should revert to polling in cases where getting by subscription did not workout', () => { let web3Context: Web3Context; beforeEach(() => { - jest.spyOn(Web3RequestManager.prototype, 'send').mockImplementation(async () => { - return {} as Promise; - }); - jest.spyOn(WebSocketProvider.prototype, 'request').mockImplementation(async () => { - return {} as Promise>; - }); - - (ethRpcMethods.sendRawTransaction as jest.Mock).mockResolvedValue( - expectedTransactionHash, - ); - (ethRpcMethods.getTransactionReceipt as jest.Mock).mockResolvedValue( - expectedTransactionHash, - ); web3Context = new Web3Context({ - // dummy provider that does supports subscription - provider: new WebSocketProvider('ws://localhost:8546'), - registeredSubscriptions, - }); + provider: new WebSocketProvider('wss://localhost:8546'),} + ); + (web3Context.provider as any).supportsSubscriptions = () => true; + web3Context.transactionConfirmationBlocks = CONFIRMATION_BLOCKS; + web3Context.enableExperimentalFeatures.useSubscriptionWhenCheckingBlockTimeout = + true; + }); - afterEach(() => { - // to clear the interval inside the subscription function: - web3Context.transactionConfirmationBlocks = 0; - }); - let counter = 0; - it.each(testData)( - `should call getBlockNumber if blockHeaderTimeout reached\n ${testMessage}`, - async (_, inputTransaction) => { - if (counter > 0) { - return; - } - counter += 1; - const formattedTransactionReceipt = format( - transactionReceiptSchema, - expectedTransactionReceipt, - DEFAULT_RETURN_FORMAT, - ); - web3Context.enableExperimentalFeatures.useSubscriptionWhenCheckingBlockTimeout = - true; - // this will case the function to revert to polling: - web3Context.blockHeaderTimeout = 0; + it.each(testData)( + `should call getBlockByNumber if blockHeaderTimeout reached\n ${testMessage}`, + async (_, inputTransaction,) => { - web3Context.transactionSendTimeout = 2; + let blockNum = 100; + let ethGetBlockByNumberCount = 0; + web3Context.requestManager.send = jest.fn(async (request) => { + + if (request.method === 'eth_getBlockByNumber') { + ethGetBlockByNumberCount += 1; + return Promise.resolve( + { ...blockMockResult.result, + number: (request as any).params[0] + }); + } + if (request.method === 'eth_call') { + + return Promise.resolve("0x"); + } + if (request.method === 'eth_blockNumber') { + blockNum += 1; + return Promise.resolve(blockNum.toString(16)); + } + if (request.method === 'eth_sendRawTransaction') { + return Promise.resolve(expectedTransactionHash); + } + if (request.method === 'eth_getTransactionReceipt') { + return Promise.resolve(expectedTransactionReceipt); + } + + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return Promise.reject(new Error("Unknown Request")) as any; + }); const promiEvent = rpcMethodWrappers.sendSignedTransaction( web3Context, inputTransaction, DEFAULT_RETURN_FORMAT, ); - // await promiEvent; - WatchTransactionBySubscription.watchTransactionBySubscription({ - web3Context, - transactionReceipt: formattedTransactionReceipt, - transactionPromiEvent: promiEvent, - returnFormat: DEFAULT_RETURN_FORMAT, + + let confirmationsCount = 0; + const confirmationPromise = new Promise((resolve, reject) => { + + const handleConfirmation = (confirmation: { confirmations: bigint }) => { + confirmationsCount += 1; + + if (confirmation.confirmations >= CONFIRMATION_BLOCKS) { + resolve(); + } + }; + + const handleError = (_error: any) => { + reject(); + }; + + promiEvent + .on('confirmation', handleConfirmation) + .on('error', handleError) + .then((res) => { + // eslint-disable-next-line jest/no-conditional-expect + expect(res).toBeDefined(); + }) + .catch(reject); + }); + + // Wait for the confirmationPromise to resolve or timeout after 5 seconds + let timeoutId; + const timeout = new Promise((_res, reject) => { + timeoutId = setTimeout(() => reject(new Error('Timeout waiting for confirmations')), 500000); }); - await waitUntilCalled(ethRpcMethods.getBlockNumber as jest.Mock, 5000); - await promiEvent; - }, - 60000, + await Promise.race([confirmationPromise, timeout]); + + clearTimeout(timeoutId); + + expect(confirmationsCount).toBe(CONFIRMATION_BLOCKS); + expect(ethGetBlockByNumberCount).toBe(CONFIRMATION_BLOCKS - 1); // means polling called getblock 4 times as first confirmation is receipt it self + + } ); + + }); }); From 6e4f39d59d3afe0a788a3292565a37fca0e7b29b Mon Sep 17 00:00:00 2001 From: Junaid <86780488+jdevcs@users.noreply.github.com> Date: Tue, 25 Jun 2024 14:08:10 +0200 Subject: [PATCH 105/186] fix: packages/web3-providers-ws/package.json to reduce vulnerabilities (#7109) The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-JS-WS-7266574 Co-authored-by: snyk-bot --- packages/web3-providers-ws/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web3-providers-ws/package.json b/packages/web3-providers-ws/package.json index 59153fda4b9..41a37fba435 100644 --- a/packages/web3-providers-ws/package.json +++ b/packages/web3-providers-ws/package.json @@ -67,6 +67,6 @@ "web3-errors": "^1.1.3", "web3-types": "^1.3.0", "web3-utils": "^4.0.7", - "ws": "^8.8.1" + "ws": "^8.17.1" } } From 8b11192367740b345fbc30ae999fb6904f27fd70 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 25 Jun 2024 09:03:22 -0400 Subject: [PATCH 106/186] Remove tables in codecov (#7123) * remove todo * update codecov yml * trigger codecov * remove test code * remove console log --- codecov.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codecov.yml b/codecov.yml index 04c1e91d8e5..c398f9390da 100644 --- a/codecov.yml +++ b/codecov.yml @@ -73,7 +73,7 @@ component_management: - /packages/web3-validator/src/ comment: - layout: 'header, diff, flags, components' + layout: 'header, diff, flags' behavior: 'default' require_changes: false require_base: no From 4c36f55f2c8e9f8b393d8919b05d7abb46cb2432 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 25 Jun 2024 09:11:45 -0400 Subject: [PATCH 107/186] fix waitingforreceipt error (#7098) * fix waitingforreceipt error * update cach * remove comment * throw other errors * update changelog and text * update linter --- packages/web3-eth/CHANGELOG.md | 6 +++++- packages/web3-eth/src/rpc_method_wrappers.ts | 21 +++++++++++++++----- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/packages/web3-eth/CHANGELOG.md b/packages/web3-eth/CHANGELOG.md index 2b6c0e08005..ba620044bde 100644 --- a/packages/web3-eth/CHANGELOG.md +++ b/packages/web3-eth/CHANGELOG.md @@ -256,4 +256,8 @@ Documentation: - WebEth has `setTransactionMiddleware` and `getTransactionMiddleware` for automatically passing to `sentTransaction` (#7088) - `TransactionMiddleware` and `TransactionMiddleware` data types are exported (#7088) -## [Unreleased] \ No newline at end of file +## [Unreleased] + +### Fixed + +- Fixed geth issue when running a new instance, transactions will index when there are no blocks created (#7098) \ No newline at end of file diff --git a/packages/web3-eth/src/rpc_method_wrappers.ts b/packages/web3-eth/src/rpc_method_wrappers.ts index 336aef3a23d..3a03afe0967 100644 --- a/packages/web3-eth/src/rpc_method_wrappers.ts +++ b/packages/web3-eth/src/rpc_method_wrappers.ts @@ -496,11 +496,22 @@ export async function getTransactionReceipt( transactionHash, DEFAULT_RETURN_FORMAT, ); - const response = await ethRpcMethods.getTransactionReceipt( - web3Context.requestManager, - transactionHashFormatted, - ); - + let response; + try { + response = await ethRpcMethods.getTransactionReceipt( + web3Context.requestManager, + transactionHashFormatted, + ); + } catch (error) { + // geth indexing error, we poll until transactions stopped indexing + if (typeof error === 'object' && !isNullish(error) && 'message' in error && (error as { message: string }).message === 'transaction indexing is in progress') { + console.warn('Transaction indexing is in progress.') + } else { + throw error; + } + + } + return isNullish(response) ? response : (format( From a000b597a861a9d2dd5930f0e1a7d25868411c48 Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Tue, 25 Jun 2024 10:39:41 -0700 Subject: [PATCH 108/186] Updates to MetaMask Tutorial (#7106) --- docs/docs/guides/wallet/metamask.md | 558 +++++++++++++++++++++------- 1 file changed, 423 insertions(+), 135 deletions(-) diff --git a/docs/docs/guides/wallet/metamask.md b/docs/docs/guides/wallet/metamask.md index 83eae1563fb..5bfdded00a5 100644 --- a/docs/docs/guides/wallet/metamask.md +++ b/docs/docs/guides/wallet/metamask.md @@ -5,188 +5,476 @@ sidebar_label: 'Tutorial: Connecting to Metamask' # Connecting to Metamask +[MetaMask](https://metamask.io/) is a powerful [wallet application](https://ethereum.org/en/wallets/) that makes it easy for Ethereum users to securely manage their accounts. Web3.js developers who are building front-end user-facing applications ("[dApps](https://ethereum.org/en/dapps/#what-are-dapps)") can easily integrate their dApp with MetaMask to allow users to safely use their own accounts. This tutorial covers the basics of using Web3.js with MetaMask, including using MetaMask as the Web3.js [provider](/guides/web3_providers_guide/) and using a MetaMask account to [sign](https://ethereum.org/en/glossary/#digital-signatures) a message. - +## Overview -## React app +Here is a high-level overview of the steps we will be taking in this tutorial: -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: +1. Review prerequisites +2. Create a new directory for the tutorial +3. Use MetaMask as the Web3.js provider +4. Request access to the MetaMask accounts +5. Sign a message with a MetaMask account +6. Verify the account used to sign a message -```jsx -import { useState } from 'react'; -import { Web3 } from 'web3'; +:::tip +If you encounter any issues while following this guide or have any questions, don't hesitate to seek assistance. Our friendly community is ready to help you out! Join our [Discord](https://discord.gg/F4NUfaCC) server and head to the **#web3js-general** channel to connect with other developers and get the support you need. +::: -function App() { - return <> ; -} +## Step 1: Prerequisites -export default App; -``` - -Let's divide this into 2 small steps: - -### 1. Create Button to Connect and Display Connected Address -In this step, we'll add a button to the front end for users to connect to Metamask. We'll also include an `

` element to display the connected address once the connection is established. +This tutorial assumes basic familiarity with the command line as well as familiarity with JavaScript and HTML. [Node.js](https://nodejs.org/) is used to run a local HTTP server. Before starting this tutorial, ensure that Node.js and its package manager, npm, are installed. -```jsx -import { useState } from 'react'; -import { Web3 } from 'web3'; - -function App() { - //highlight-start - //react state to store and show the connected account - const [connectedAccount, setConnectedAccount] = useState('null'); - //highlight-end +```bash +$: node -v +# your version may be different, but it's best to use the current stable version +v18.16.1 +$: npm -v +9.5.1 +``` - return ( - <> - //highlight-start - {/* Button to trigger Metamask connection */} - +Make sure that MetaMask is [installed](https://metamask.io/download/) as a browser extension and the steps to create an account (e.g. create a password, review the seed phrase) have been completed. - {/* Display the connected account */} -

{connectedAccount}

- //highlight-end - - ); -} +## Step 2: Create a New Directory for the Tutorial -export default App; -``` +Create a new directory for the tutorial and navigate into it: -### 2. Implement the Function to Connect Metamask -In this step, we'll implement the function that triggers Metamask to prompt the user to connect their wallet. - -```jsx {} -import { useState } from 'react'; -import { Web3 } from 'web3'; - -function App() { - //state to store and show the connected account - const [connectedAccount, setConnectedAccount] = useState('null'); - - //highlight-start - async function connectMetamask() { - //check metamask is installed - if (window.ethereum) { - // instantiate Web3 with the injected provider - const web3 = new Web3(window.ethereum); - - //request user to connect accounts (Metamask will prompt) - await window.ethereum.request({ method: 'eth_requestAccounts' }); - - //get the connected accounts - const accounts = await web3.eth.getAccounts(); - - //show the first connected account in the react page - setConnectedAccount(accounts[0]); - } else { - alert('Please download metamask'); - } - } - //highlight-end - - return ( - <> - {/* Button to trigger Metamask connection */} - - - {/* Display the connected account */} -

{connectedAccount}

- - ); -} - -export default App; +```bash +mkdir web3js-metamask-tutorial +cd web3js-metamask-tutorial ``` -## HTML Single page +## Step 3: Use MetaMask as the Web3.js Provider -### 1. Create an html file and import Web3 from CDN +Create a new file called `index.html` in your project directory and add the following HTML to it: ```html - - + + - //highlight-start - Metamask Connection - - - //highlight-end + + + Web3.js MetaMask Tutorial + + + +
+
+
+
+ ``` -### 2. Create Button to Connect and Display Connected Address +Review the comments in `index.html`. This document imports Web3.js, creates several placeholders that will be used to display network information, and defines a script that checks for an [injected provider](/guides/web3_providers_guide/#injected-provider). If an injected provider is found, it's used to construct a new `Web3` instance and connect to the Ethereum network. A check is performed to ensure that the injected provider is coming from MetaMask and the result of this check is displayed to the user. Once connected through the injected provider, the script updates the placeholders with the chain ID and latest block number, and creates an event subscription to update the block number as new blocks are created. If no injected provider is found, the user is instructed to install MetaMask. + +To start a local HTTP server to serve `index.html`, execute the following command in the project directory: + +```bash +npx watch-http-server . +``` + +The output should look like: + +``` +Websocket Server Listening on Port: 8086 +Starting up http-server, serving . on: http://0.0.0.0:8080 +Hit CTRL-C to stop the server +Scanned working directory. ready for changes.. +``` + +The HTTP server needs to remain running in the terminal that was used to start it. Any changes that are made in the project directory will cause the webpage to automatically refresh. + +Use a MetaMask-enabled web browser to navigate to the URL from the output (http://0.0.0.0:8080 in the example above). If everything is set up correctly, the webpage should state that it is connected to the Ethereum network with MetaMask and list the chain ID (for the default Ethereum Mainnet network this value should be `1`) and latest block number. The latest block number should change when new blocks are created. + +## Step 4: Request Access to the MetaMask Accounts + +Replace the contents of `index.html` with the following (take note of the highlighted sections, which are new): ```html - - + + - Metamask Connection - - + + + Web3.js MetaMask Tutorial + + - //highlight-start -

Metamask Connection

- - - + +
+
+
+ +
+
+ + +
+ +
+ + ``` -### 3. Implement Script to Connect Metamask +The file has been updated to include a placeholder for the MetaMask account, as well as a button that is used to request the accounts from MetaMask. + +Once connected to MetaMask, the script now registers a click event for the new button. The accounts are requested by invoking `window.ethereum.request({ method: ["eth_requestAccounts"] })` and once the request has been approved, the account addresses are available by calling [`web3.eth.getAccounts()`](https://docs.web3js.org/api/web3-eth/class/Web3Eth#getAccounts). MetaMask can be used to manage multiple accounts, but this tutorial only makes use of a single account. More information about the [`window.ethereum.request`](https://docs.metamask.io/wallet/reference/provider-api/#request) function and [`eth_requestAccounts`](https://docs.metamask.io/wallet/reference/eth_requestaccounts/) RPC call can be found in the MetaMask documentation. + +If no Ethereum provider is found, the button to request the MetaMask accounts is disabled. + +Go back to the MetaMask-enabled browser and review the webpage, which should have been automatically refreshed to display the changes. Click the button that says "Request MetaMask Accounts", which should activate MetaMask. After accepting the MetaMask notifications, the address of the MetaMask account should be displayed on the webpage. MetaMask will remember that the webpage has been given permission to access its accounts and it will not be necessary to accept any confirmations when requesting accounts in the future. + +## Step #5: Sign a Message with a MetaMask Account + +Replace the contents of `index.html` with the following (take note of the highlighted sections, which are new): ```html - - + + - Metamask Connection - - + + + Web3.js MetaMask Tutorial + + -

Metamask Connection

+ +
+
+
+
+
+ +
+ +
+ + +
+ + +
+
+ + + + +``` + +`index.html` has been updated to include inputs for signing a message with the MetaMask account. Initially, these inputs are disabled - they will be enabled once the page has access to the MetaMask account. A placeholder has been added for the result of the signing operation. - - +Inside the click event for the "Request MetaMask Accounts" button, the signing inputs are initialized. First, the inputs are enabled. Then, a click event is registered for the "Sign" button. This click event calls the [`web3.eth.personal.sign`](/api/web3-eth-personal/class/Personal#sign) method. The first parameter to this method is the message to be signed, which is taken from the input field. The second parameter is the address of the account to use for signing. The third parameter is the passphrase to decrypt the account, which is not used in this example since MetaMask is managing the account. Once the message has been signed, the placeholder is updated with the signed message. - -

null

+Go back to the MetaMask-enabled browser and review the webpage, which should have been automatically refreshed to display the changes. There should now be disabled input fields below the "Request MetaMask Accounts" button. Click the button to request the accounts (remember, it will not be necessary to accept any MetaMask notifications this time). If everything is working properly, the address of the MetaMask account should be displayed on the webpage and the input fields should become enabled. Type a message (e.g. "Hello, Web3.js!") in the input field and click the "Sign Message" button. If everything is working properly, a MetaMask notification will appear. After the notification has been accepted, the signed message should appear beneath the input fields. - //highlight-start - + + + +
+
+
+
+
+ +
+ +
+ +
+ + +
+
+ + +
+ + + +
+
+ + - //highlight-end + // get chain ID and populate placeholder + document.getElementById("chainId").innerText = + `Chain ID: ${await web3.eth.getChainId()}`; + // get latest block and populate placeholder + document.getElementById("latestBlock").innerText = + `Latest Block: ${await web3.eth.getBlockNumber()}`; + + // subscribe to new blocks and update UI when a new block is created + const blockSubscription = await web3.eth.subscribe("newBlockHeaders"); + blockSubscription.on("data", (block) => { + document.getElementById("latestBlock").innerText = + `Latest Block: ${block.number}`; + }); + + // click event for "Request MetaMask Accounts" button + document + .getElementById("requestAccounts") + .addEventListener("click", async () => { + // request accounts from MetaMask + await window.ethereum.request({ method: "eth_requestAccounts" }); + document.getElementById("requestAccounts").remove(); + + // get list of accounts + const accounts = await web3.eth.getAccounts(); + // get the first account and populate placeholder + document.getElementById("connectedAccount").innerText = + `Account: ${accounts[0]}`; + + // enable signing input + const messageToSign = document.getElementById("messageToSign"); + const sign = document.getElementById("signMessage"); + messageToSign.disabled = false; + sign.disabled = false; + + // click event for "Sign Message" button + sign.addEventListener("click", async () => { + // sign message with first MetaMask account + const signature = await web3.eth.personal.sign( + messageToSign.value, + accounts[0], + "", + ); + + // update placeholder with signed message + document.getElementById("signingResult").innerText = + `Signed Message: ${signature}`; + }); + + // highlight-start + // enable signature verification input + const originalMessage = document.getElementById("originalMessage"); + const signedMessaged = document.getElementById("signedMessage"); + const recoverAccount = document.getElementById("recoverAccount"); + originalMessage.disabled = false; + signedMessaged.disabled = false; + recoverAccount.disabled = false; + + // click event for "Recover Account" button + recoverAccount.addEventListener("click", async () => { + // recover account from signature + const account = await web3.eth.personal.ecRecover( + originalMessage.value, + signedMessaged.value, + ); + + // update placeholder with recovered signature account + document.getElementById("signingAccount").innerText = + `Signing Account: ${account}`; + }); + // highlight-end + }); + } else { + // no Ethereum provider - instruct user to install MetaMask + document.getElementById("warn").innerHTML = + "Please install MetaMask."; + document.getElementById("requestAccounts").disabled = true; + } + ``` - +As in the previous step, `index.html` has been updated to include inputs for recovering the account that was used to sign a message. As before, these inputs are disabled - they will be enabled once the page has access to the MetaMask account. A placeholder has been added for the result of the recovery operation. + +Inside the click event for the "Request MetaMask Accounts" button, the recovery inputs are initialized. First, the inputs are enabled. Then, a click event is registered for the "Recover" button. This click event calls the [`web3.eth.personal.ecRecover`](/api/web3-eth-personal/class/Personal#ecRecover) method. The first parameter to this method is the original unsigned message, which is taken from the first input field. The second parameter is the signed message, which is taken from the second input field. Once the account has been recovered, the placeholder is updated with the address of the account. + +Go back to the MetaMask-enabled browser and review the webpage, which should have been automatically refreshed to display the changes. There should now be additional disabled input fields below those from the previous step. Follow the same steps as before to request the accounts from MetaMask and sign a message, then copy and paste the original message and message signature (starting with the leading `0x` characters) into the new input fields. Click the "Recover Account" button. If everything is working properly, the address of the account that was used to sign the message should appear below the new input fields. This address should match the one that is displayed above the input fields that were used to sign the message. + +## Conclusion + +This tutorial demonstrated using Web3.js with MetaMask, including using the MetaMask injected provider and using a MetaMask account to sign a message. To use the MetaMask injected provider with Web3.js, simply construct a new instance of the `Web3` class with the `window.ethereum` property. To request access to the MetaMask accounts, use `window.ethereum.request({ method: "eth_requestAccounts" })` - once the user has confirmed this request, the MetaMask accounts will be available with `web3.eth.getAccounts()`. When the MetaMask injected provider handles a request that requires the use of a MetaMask account, MetaMask will prompt the user to confirm the request. From 3ec3d49ecbba29e029f1b69d5517099dbb2197a7 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 25 Jun 2024 15:19:14 -0400 Subject: [PATCH 109/186] remove todo (#7121) --- .../web3-eth-contract/test/integration/contract_methods.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web3-eth-contract/test/integration/contract_methods.test.ts b/packages/web3-eth-contract/test/integration/contract_methods.test.ts index 0c138d364dd..7cede74d7d1 100644 --- a/packages/web3-eth-contract/test/integration/contract_methods.test.ts +++ b/packages/web3-eth-contract/test/integration/contract_methods.test.ts @@ -148,7 +148,7 @@ describe('contract', () => { }); it('should returns errors on reverts', async () => { - // TODO hardhat reverts but sends an undefined receipt, needs investigation + // hardhat errors during revert when sending the transaction so no receipt will be returned. if (getSystemTestBackend() === BACKEND.HARDHAT) { // eslint-disable-next-line jest/no-conditional-expect await expect( From 80bd3faaf7a4967f8eb87500a03f4715327fa497 Mon Sep 17 00:00:00 2001 From: Santiago Trujillo Zuluaga Date: Wed, 26 Jun 2024 12:57:12 +0300 Subject: [PATCH 110/186] fixed `vue` for `react` (#7128) --- docs/docs/guides/wallet/web3_modal_guide/index.mdx | 2 +- .../guides/wallet/web3_modal_guide/{vue.md => react.md} | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) rename docs/docs/guides/wallet/web3_modal_guide/{vue.md => react.md} (90%) diff --git a/docs/docs/guides/wallet/web3_modal_guide/index.mdx b/docs/docs/guides/wallet/web3_modal_guide/index.mdx index 2d8b878196f..05d61d087c2 100644 --- a/docs/docs/guides/wallet/web3_modal_guide/index.mdx +++ b/docs/docs/guides/wallet/web3_modal_guide/index.mdx @@ -126,5 +126,5 @@ function Components() { ``` :::info -- To learn how to set up Web3modal with vue, click [here](/guides/wallet/web3_modal_guide/vue). +- To learn how to set up Web3modal with React, click [here](/guides/wallet/web3_modal_guide/react). ::: diff --git a/docs/docs/guides/wallet/web3_modal_guide/vue.md b/docs/docs/guides/wallet/web3_modal_guide/react.md similarity index 90% rename from docs/docs/guides/wallet/web3_modal_guide/vue.md rename to docs/docs/guides/wallet/web3_modal_guide/react.md index a113d519197..3370c65dc57 100644 --- a/docs/docs/guides/wallet/web3_modal_guide/vue.md +++ b/docs/docs/guides/wallet/web3_modal_guide/react.md @@ -1,9 +1,9 @@ --- sidebar_position: 1 -sidebar_label: 'Web3Modal with Vue' +sidebar_label: 'Web3Modal with React' --- -# Web3Modal with Vue and web3js +# Web3Modal with React and web3js ## Live code editor @@ -112,11 +112,10 @@ ReactDOM.createRoot(document.getElementById('app')!).render( ) ``` -You are finished and have successfully created Web3modal with Vue! +You are finished and have successfully created Web3modal with React! :::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 6454202cf9a5f46bd3b5a6f4325c2e528529c4e6 Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Thu, 27 Jun 2024 08:00:18 -0700 Subject: [PATCH 111/186] feat(docs): metamask-react (#7130) * Add MetaMask with React Tutorial * Fix Live Code Editor --- .../guides/getting_started/introduction.md | 2 +- docs/docs/guides/wallet/index.md | 2 +- docs/docs/guides/wallet/metamask-react.md | 626 ++++++++++++++++++ .../{metamask.md => metamask-vanilla.md} | 4 +- 4 files changed, 630 insertions(+), 4 deletions(-) create mode 100644 docs/docs/guides/wallet/metamask-react.md rename docs/docs/guides/wallet/{metamask.md => metamask-vanilla.md} (99%) diff --git a/docs/docs/guides/getting_started/introduction.md b/docs/docs/guides/getting_started/introduction.md index 0ccdbced97e..303401639f9 100644 --- a/docs/docs/guides/getting_started/introduction.md +++ b/docs/docs/guides/getting_started/introduction.md @@ -35,7 +35,7 @@ New Web3.js developers should proceed to the [Quickstart](/guides/getting_starte ### For Intermediate & Advanced Web3.js Developers -If you're already familiar with Ethereum and Web3.js development, you may want to review the Web3.js [package structure](#packages--plugins) and proceed directly to the [package-level documentation](/libdocs/ABI) and [API documentation](/api). Application developers may wish to review the [Web3.js configuration guide](/guides/web3_config/) or learn how to use Web3.js with tools like the [MetaMask](/guides/wallet/metamask) wallet or the [WalletConnect](/guides/wallet/web3_modal_guide/) wallet selection modal. Don't forget to review the [list of available plugins](https://web3js.org/plugins) or even [learn how to build your own Web3.js plugin](/guides/web3_plugin_guide/plugin_authors)! +If you're already familiar with Ethereum and Web3.js development, you may want to review the Web3.js [package structure](#packages--plugins) and proceed directly to the [package-level documentation](/libdocs/ABI) and [API documentation](/api). Application developers may wish to review the [Web3.js configuration guide](/guides/web3_config/) or learn how to use Web3.js with tools like the [MetaMask](/guides/wallet/metamask-react) wallet or the [WalletConnect](/guides/wallet/web3_modal_guide/) wallet selection modal. Don't forget to review the [list of available plugins](https://web3js.org/plugins) or even [learn how to build your own Web3.js plugin](/guides/web3_plugin_guide/plugin_authors)! ## Packages & Plugins diff --git a/docs/docs/guides/wallet/index.md b/docs/docs/guides/wallet/index.md index 0e8858ad530..ef75a663ec8 100644 --- a/docs/docs/guides/wallet/index.md +++ b/docs/docs/guides/wallet/index.md @@ -299,5 +299,5 @@ The following is a list of [`Wallet`](/libdocs/Wallet) methods in the `web3.eth. This document is just an introduction to Web3.js accounts and wallets. Here are some suggestions for what to review next: - Learn how to [transfer ETH](/guides/wallet/transactions) from one account to another. -- Build a front-end application that uses [injected accounts](/guides/wallet/metamask) from the MetaMask wallet. +- Build a front-end application that uses [injected accounts](/guides/wallet/metamask-vanilla) from the MetaMask wallet. - Use an account to [deploy and interact with a smart contract](/guides/smart_contracts/smart_contracts_guide). diff --git a/docs/docs/guides/wallet/metamask-react.md b/docs/docs/guides/wallet/metamask-react.md new file mode 100644 index 00000000000..c8c9a3604ae --- /dev/null +++ b/docs/docs/guides/wallet/metamask-react.md @@ -0,0 +1,626 @@ +--- +sidebar_position: 4 +sidebar_label: 'Tutorial: Connecting to Metamask with React' +--- + +# Connecting to Metamask with React + + + +This tutorial builds on the previous tutorial that used [vanilla JavaScript with Web3.js and MetaMask](/guides/wallet/metamask-vanilla). In this tutorial, [React](https://react.dev/) and TypeScript will be used to implement similar capabilities. + +## Overview + +Here is a high-level overview of the steps we will be taking in this tutorial: + +1. Review prerequisites +2. Initialize a new React project and add Web3.js +3. Use MetaMask as the Web3.js provider +4. Request access to the MetaMask accounts +5. Sign a message with a MetaMask account +6. Verify the account used to sign a message + +:::tip +If you encounter any issues while following this guide or have any questions, don't hesitate to seek assistance. Our friendly community is ready to help you out! Join our [Discord](https://discord.gg/F4NUfaCC) server and head to the **#web3js-general** channel to connect with other developers and get the support you need. +::: + +## Step 1: Prerequisites + +This tutorial assumes basic familiarity with the command line as well as familiarity with React and [Node.js](https://nodejs.org/). Before starting this tutorial, ensure that Node.js and its package manager, npm, are installed. + +```bash +$: node -v +# your version may be different, but it's best to use the current stable version +v18.16.1 +$: npm -v +9.5.1 +``` + +Make sure that MetaMask is [installed](https://metamask.io/download/) as a browser extension and the steps to create an account (e.g. create a password, review the seed phrase) have been completed. + +## Step 2: Initialize a New React Project and Add Web3.js + +Initialize a new React project and navigate into the new project directory: + +```bash +npx create-react-app web3-metamask-react --template typescript +cd web3-metamask-react +``` + +Add Web3.js to the project with the following command: + +```bash +npm i web3 +``` + +## Step 3: Use MetaMask as the Web3.js Provider + +MetaMask will inject the Ethereum provider as an `ethereum` property on the [global `Window` object](https://developer.mozilla.org/en-US/docs/Web/API/Window). To communicate this change to the TypeScript compiler, update `src/react-app-env.d.ts` as follows: + +```ts +import { MetaMaskProvider } from "web3"; + +/// + +declare global { + interface Window { + ethereum: MetaMaskProvider; + } +} +``` + +Replace the contents of `src/App.tsx` with the following: + +```tsx +import { useEffect, useState } from "react"; +import { Web3 } from "web3"; + +function App() { + const [web3, setWeb3] = useState(null); + const [warning, setWarning] = useState(null); + const [provider, setProvider] = useState(null); + const [chainId, setChainId] = useState(null); + const [latestBlock, setLatestBlock] = useState(null); + useEffect(() => { + // ensure that there is an injected the Ethereum provider + if (window.ethereum) { + // use the injected Ethereum provider to initialize Web3.js + setWeb3(new Web3(window.ethereum)); + // check if Ethereum provider comes from MetaMask + if (window.ethereum.isMetaMask) { + setProvider("Connected to Ethereum with MetaMask."); + } else { + setProvider("Non-MetaMask Ethereum provider detected."); + } + } else { + // no Ethereum provider - instruct user to install MetaMask + setWarning("Please install MetaMask"); + } + }, []); + + useEffect(() => { + async function getChainId() { + if (web3 === null) { + return; + } + + // get chain ID and populate placeholder + setChainId(`Chain ID: ${await web3.eth.getChainId()}`); + } + + async function getLatestBlock() { + if (web3 === null) { + return; + } + + // get latest block and populate placeholder + setLatestBlock(`Latest Block: ${await web3.eth.getBlockNumber()}`); + + // subscribe to new blocks and update UI when a new block is created + const blockSubscription = await web3.eth.subscribe("newBlockHeaders"); + blockSubscription.on("data", (block) => { + setLatestBlock(`Latest Block: ${block.number}`); + }); + } + + getChainId(); + getLatestBlock(); + }, [web3]); + return ( + <> +
+ {warning} +
+
{provider}
+
{chainId}
+
{latestBlock}
+ + ); +} + +export default App; +``` + +Review the comments in `src/App.tsx`. This file defines a component with several placeholders that will be used to display network information, and also provides two `useEffect` hooks for populating those placeholders. The first `useEffect` hook checks for an [injected provider](/guides/web3_providers_guide/#injected-provider). If an injected provider is found, it's used to construct a new `Web3` instance and connect to the Ethereum network. A check is performed to ensure that the injected provider is coming from MetaMask and the result of this check is displayed to the user. If no injected provider is found, the user is instructed to install MetaMask. The second `useEffect` hook uses the injected provider to update the placeholders with the chain ID and latest block number, and creates an event subscription to update the block number as new blocks are created. + +To start the React app, execute the following command in the project directory: + +```bash +npm start +``` + +This should automatically open the page in a web browser (make sure it's the browser with the MetaMask extension). If everything is set up correctly, the webpage should state that it is connected to the Ethereum network with MetaMask and list the chain ID (for the default Ethereum Mainnet network this value should be `1`) and latest block number. The latest block number should change when new blocks are created. + +## Step 4: Request Access to the MetaMask Accounts + +Replace the contents of `src/App.tsx` with the following (take note of the highlighted sections, which are new): + +```tsx +import { useEffect, useState } from "react"; +import { Web3 } from "web3"; + +function App() { + const [web3, setWeb3] = useState(null); + const [warning, setWarning] = useState(null); + const [provider, setProvider] = useState(null); + const [chainId, setChainId] = useState(null); + const [latestBlock, setLatestBlock] = useState(null); + // highlight-start + const [accountButtonDisabled, setAccountButtonDisabled] = + useState(false); + const [accounts, setAccounts] = useState(null); + const [connectedAccount, setConnectedAccount] = useState(null); + // highlight-end + useEffect(() => { + // ensure that there is an injected the Ethereum provider + if (window.ethereum) { + // use the injected Ethereum provider to initialize Web3.js + setWeb3(new Web3(window.ethereum)); + // check if Ethereum provider comes from MetaMask + if (window.ethereum.isMetaMask) { + setProvider("Connected to Ethereum with MetaMask."); + } else { + setProvider("Non-MetaMask Ethereum provider detected."); + } + } else { + // no Ethereum provider - instruct user to install MetaMask + setWarning("Please install MetaMask"); + // highlight-next-line + setAccountButtonDisabled(true); + } + }, []); + + useEffect(() => { + async function getChainId() { + if (web3 === null) { + return; + } + + // get chain ID and populate placeholder + setChainId(`Chain ID: ${await web3.eth.getChainId()}`); + } + + async function getLatestBlock() { + if (web3 === null) { + return; + } + + // get latest block and populate placeholder + setLatestBlock(`Latest Block: ${await web3.eth.getBlockNumber()}`); + + // subscribe to new blocks and update UI when a new block is created + const blockSubscription = await web3.eth.subscribe("newBlockHeaders"); + blockSubscription.on("data", (block) => { + setLatestBlock(`Latest Block: ${block.number}`); + }); + } + + getChainId(); + getLatestBlock(); + }, [web3]); + + // highlight-start + // click event for "Request MetaMask Accounts" button + async function requestAccounts() { + if (web3 === null) { + return; + } + + // request accounts from MetaMask + await window.ethereum.request({ method: "eth_requestAccounts" }); + document.getElementById("requestAccounts")?.remove(); + + // get list of accounts + const allAccounts = await web3.eth.getAccounts(); + setAccounts(allAccounts); + // get the first account and populate placeholder + setConnectedAccount(`Account: ${allAccounts[0]}`); + } + // highlight-end + return ( + <> +
+ {warning} +
+
{provider}
+
{chainId}
+
{latestBlock}
+ // highlight-start +
{connectedAccount}
+
+ +
+ // highlight-end + + ); +} + +export default App; +``` + +The component has been updated to include a placeholder for the MetaMask account, as well as a button that is used to request the accounts from MetaMask. If no Ethereum provider is found, the button to request the MetaMask accounts is disabled. + +A function named `requestAccounts` has been defined as the click-handler for the new button. The accounts are requested by invoking `window.ethereum.request({ method: ["eth_requestAccounts"] })` and once the request has been approved, the account addresses are available by calling [`web3.eth.getAccounts()`](https://docs.web3js.org/api/web3-eth/class/Web3Eth#getAccounts). MetaMask can be used to manage multiple accounts, but this tutorial only makes use of a single account. More information about the [`window.ethereum.request`](https://docs.metamask.io/wallet/reference/provider-api/#request) function and [`eth_requestAccounts`](https://docs.metamask.io/wallet/reference/eth_requestaccounts/) RPC call can be found in the MetaMask documentation. + +Go back to the MetaMask-enabled browser and review the webpage, which should have been automatically refreshed to display the changes. Click the button that says "Request MetaMask Accounts", which should activate MetaMask. After accepting the MetaMask notifications, the address of the MetaMask account should be displayed on the webpage. MetaMask will remember that the webpage has been given permission to access its accounts and it will not be necessary to accept any confirmations when requesting accounts in the future. + +## Step #5: Sign a Message with a MetaMask Account + +Replace the contents of `src/App.tsx` with the following (take note of the highlighted sections, which are new): + +```tsx +import { useEffect, useState } from "react"; +import { Web3 } from "web3"; + +function App() { + const [web3, setWeb3] = useState(null); + const [warning, setWarning] = useState(null); + const [provider, setProvider] = useState(null); + const [chainId, setChainId] = useState(null); + const [latestBlock, setLatestBlock] = useState(null); + const [accountButtonDisabled, setAccountButtonDisabled] = + useState(false); + const [accounts, setAccounts] = useState(null); + const [connectedAccount, setConnectedAccount] = useState(null); + // highlight-start + const [messageToSign, setMessageToSign] = useState(null); + const [signingResult, setSigningResult] = useState(null); + // highlight-end + useEffect(() => { + // ensure that there is an injected the Ethereum provider + if (window.ethereum) { + // use the injected Ethereum provider to initialize Web3.js + setWeb3(new Web3(window.ethereum)); + // check if Ethereum provider comes from MetaMask + if (window.ethereum.isMetaMask) { + setProvider("Connected to Ethereum with MetaMask."); + } else { + setProvider("Non-MetaMask Ethereum provider detected."); + } + } else { + // no Ethereum provider - instruct user to install MetaMask + setWarning("Please install MetaMask"); + setAccountButtonDisabled(true); + } + }, []); + + useEffect(() => { + async function getChainId() { + if (web3 === null) { + return; + } + + // get chain ID and populate placeholder + setChainId(`Chain ID: ${await web3.eth.getChainId()}`); + } + + async function getLatestBlock() { + if (web3 === null) { + return; + } + + // get latest block and populate placeholder + setLatestBlock(`Latest Block: ${await web3.eth.getBlockNumber()}`); + + // subscribe to new blocks and update UI when a new block is created + const blockSubscription = await web3.eth.subscribe("newBlockHeaders"); + blockSubscription.on("data", (block) => { + setLatestBlock(`Latest Block: ${block.number}`); + }); + } + + getChainId(); + getLatestBlock(); + }, [web3]); + + // click event for "Request MetaMask Accounts" button + async function requestAccounts() { + if (web3 === null) { + return; + } + + // request accounts from MetaMask + await window.ethereum.request({ method: "eth_requestAccounts" }); + document.getElementById("requestAccounts")?.remove(); + + // get list of accounts + const allAccounts = await web3.eth.getAccounts(); + setAccounts(allAccounts); + // get the first account and populate placeholder + setConnectedAccount(`Account: ${allAccounts[0]}`); + } + + // highlight-start + // click event for "Sign Message" button + async function signMessage() { + if (web3 === null || accounts === null || messageToSign === null) { + return; + } + + // sign message with first MetaMask account + const signature = await web3.eth.personal.sign( + messageToSign, + accounts[0], + "", + ); + + setSigningResult(signature); + } + // highlight-end + return ( + <> +
+ {warning} +
+
{provider}
+
{chainId}
+
{latestBlock}
+
{connectedAccount}
+
+ +
+ // highlight-start +
+ { + setMessageToSign(e.target.value); + }} + id="messageToSign" + placeholder="Message to Sign" + disabled={connectedAccount === null} + /> + +
{signingResult}
+
+ // highlight-end + + ); +} + +export default App; +``` + +`src/App.tsx` has been updated to include inputs for signing a message with the MetaMask account. Initially, these inputs are disabled - they will be enabled once the page has access to the MetaMask account. A placeholder has been added for the result of the signing operation. + +A function named `signMessage` has been defined as the click-handler for the "Sign Message" button. This function calls the [`web3.eth.personal.sign`](/api/web3-eth-personal/class/Personal#sign) method. The first parameter to this method is the message to be signed, which is taken from the input field. The second parameter is the address of the account to use for signing. The third parameter is the passphrase to decrypt the account, which is not used in this example since MetaMask is managing the account. Once the message has been signed, the placeholder is updated with the signed message. + +Go back to the MetaMask-enabled browser and review the webpage, which should have been automatically refreshed to display the changes. There should now be disabled input fields below the "Request MetaMask Accounts" button. Click the button to request the accounts (remember, it will not be necessary to accept any MetaMask notifications this time). If everything is working properly, the address of the MetaMask account should be displayed on the webpage and the input fields should become enabled. Type a message (e.g. "Hello, Web3.js!") in the input field and click the "Sign Message" button. If everything is working properly, a MetaMask notification will appear. After the notification has been accepted, the signed message should appear beneath the input fields. + +## Step #6: Verify the Account Used to Sign a Message + +Replace the contents of `src/App.tsx` with the following (take note of the highlighted sections, which are new): + +```tsx +import { useEffect, useState } from "react"; +import { Web3 } from "web3"; + +function App() { + const [web3, setWeb3] = useState(null); + const [warning, setWarning] = useState(null); + const [provider, setProvider] = useState(null); + const [chainId, setChainId] = useState(null); + const [latestBlock, setLatestBlock] = useState(null); + const [accountButtonDisabled, setAccountButtonDisabled] = + useState(false); + const [accounts, setAccounts] = useState(null); + const [connectedAccount, setConnectedAccount] = useState(null); + const [messageToSign, setMessageToSign] = useState(null); + const [signingResult, setSigningResult] = useState(null); + // highlight-start + const [originalMessage, setOriginalMessage] = useState(null); + const [signedMessage, setSignedMessage] = useState(null); + const [signingAccount, setSigningAccount] = useState(null); + // highlight-end + useEffect(() => { + // ensure that there is an injected the Ethereum provider + if (window.ethereum) { + // use the injected Ethereum provider to initialize Web3.js + setWeb3(new Web3(window.ethereum)); + // check if Ethereum provider comes from MetaMask + if (window.ethereum.isMetaMask) { + setProvider("Connected to Ethereum with MetaMask."); + } else { + setProvider("Non-MetaMask Ethereum provider detected."); + } + } else { + // no Ethereum provider - instruct user to install MetaMask + setWarning("Please install MetaMask"); + setAccountButtonDisabled(true); + } + }, []); + + useEffect(() => { + async function getChainId() { + if (web3 === null) { + return; + } + + // get chain ID and populate placeholder + setChainId(`Chain ID: ${await web3.eth.getChainId()}`); + } + + async function getLatestBlock() { + if (web3 === null) { + return; + } + + // get latest block and populate placeholder + setLatestBlock(`Latest Block: ${await web3.eth.getBlockNumber()}`); + + // subscribe to new blocks and update UI when a new block is created + const blockSubscription = await web3.eth.subscribe("newBlockHeaders"); + blockSubscription.on("data", (block) => { + setLatestBlock(`Latest Block: ${block.number}`); + }); + } + + getChainId(); + getLatestBlock(); + }, [web3]); + + // click event for "Request MetaMask Accounts" button + async function requestAccounts() { + if (web3 === null) { + return; + } + + // request accounts from MetaMask + await window.ethereum.request({ method: "eth_requestAccounts" }); + document.getElementById("requestAccounts")?.remove(); + + // get list of accounts + const allAccounts = await web3.eth.getAccounts(); + setAccounts(allAccounts); + // get the first account and populate placeholder + setConnectedAccount(`Account: ${allAccounts[0]}`); + } + + // click event for "Sign Message" button + async function signMessage() { + if (web3 === null || accounts === null || messageToSign === null) { + return; + } + + // sign message with first MetaMask account + const signature = await web3.eth.personal.sign( + messageToSign, + accounts[0], + "", + ); + + setSigningResult(signature); + } + + // highlight-start + // click event for "Recover Account" button + async function recoverAccount() { + if (web3 === null || originalMessage === null || signedMessage === null) { + return; + } + // recover account from signature + const account = await web3.eth.personal.ecRecover( + originalMessage, + signedMessage, + ); + + setSigningAccount(account); + } + // highlight-end + return ( + <> +
+ {warning} +
+
{provider}
+
{chainId}
+
{latestBlock}
+
{connectedAccount}
+
+ +
+
+ { + setMessageToSign(e.target.value); + }} + id="messageToSign" + placeholder="Message to Sign" + disabled={connectedAccount === null} + /> + +
{signingResult}
+
+ // highlight-start +
+ { + setOriginalMessage(e.target.value); + }} + id="originalMessage" + placeholder="Original Message" + disabled={connectedAccount === null} + /> + { + setSignedMessage(e.target.value); + }} + id="signedMessage" + placeholder="Signed Message" + disabled={connectedAccount === null} + /> + +
{signingAccount}
+
+ // highlight-end + + ); +} + +export default App; +``` + +As in the previous step, `src/App.tsx` has been updated to include inputs for recovering the account that was used to sign a message. As before, these inputs are disabled - they will be enabled once the page has access to the MetaMask account. A placeholder has been added for the result of the recovery operation. + +A function named `recoverAccount` has been defined as the click-handler for the "Recover Account" button. This function calls the [`web3.eth.personal.ecRecover`](/api/web3-eth-personal/class/Personal#ecRecover) method. The first parameter to this method is the original unsigned message, which is taken from the first input field. The second parameter is the signed message, which is taken from the second input field. Once the account has been recovered, the placeholder is updated with the address of the account. + +Go back to the MetaMask-enabled browser and review the webpage, which should have been automatically refreshed to display the changes. There should now be additional disabled input fields below those from the previous step. Follow the same steps as before to request the accounts from MetaMask and sign a message, then copy and paste the original message and message signature (starting with the leading `0x` characters) into the new input fields. Click the "Recover Account" button. If everything is working properly, the address of the account that was used to sign the message should appear below the new input fields. This address should match the one that is displayed above the input fields that were used to sign the message. + +## Conclusion + +This tutorial demonstrated using Web3.js with MetaMask, including using the MetaMask injected provider and using a MetaMask account to sign a message. To use the MetaMask injected provider with Web3.js, simply construct a new instance of the `Web3` class with the `window.ethereum` property. To request access to the MetaMask accounts, use `window.ethereum.request({ method: "eth_requestAccounts" })` - once the user has confirmed this request, the MetaMask accounts will be available with `web3.eth.getAccounts()`. When the MetaMask injected provider handles a request that requires the use of a MetaMask account, MetaMask will prompt the user to confirm the request. diff --git a/docs/docs/guides/wallet/metamask.md b/docs/docs/guides/wallet/metamask-vanilla.md similarity index 99% rename from docs/docs/guides/wallet/metamask.md rename to docs/docs/guides/wallet/metamask-vanilla.md index 5bfdded00a5..da930b07fad 100644 --- a/docs/docs/guides/wallet/metamask.md +++ b/docs/docs/guides/wallet/metamask-vanilla.md @@ -1,9 +1,9 @@ --- sidebar_position: 3 -sidebar_label: 'Tutorial: Connecting to Metamask' +sidebar_label: 'Tutorial: Connecting to Metamask with Vanilla JS' --- -# Connecting to Metamask +# Connecting to Metamask with Vanilla JS [MetaMask](https://metamask.io/) is a powerful [wallet application](https://ethereum.org/en/wallets/) that makes it easy for Ethereum users to securely manage their accounts. Web3.js developers who are building front-end user-facing applications ("[dApps](https://ethereum.org/en/dapps/#what-are-dapps)") can easily integrate their dApp with MetaMask to allow users to safely use their own accounts. This tutorial covers the basics of using Web3.js with MetaMask, including using MetaMask as the Web3.js [provider](/guides/web3_providers_guide/) and using a MetaMask account to [sign](https://ethereum.org/en/glossary/#digital-signatures) a message. From 280b8f03d4cc741a1cad9bf3b419c7fcebf4e0e3 Mon Sep 17 00:00:00 2001 From: Junaid <86780488+jdevcs@users.noreply.github.com> Date: Tue, 2 Jul 2024 10:12:35 +0200 Subject: [PATCH 112/186] create2 create (#7129) * rlp lib * CREATE support * test data * contract deployment & addr test on node * local tests * updated tests * create2ContractAddress * test data * tests --- packages/web3-eth-contract/package.json | 1 + packages/web3-eth-contract/src/utils.ts | 46 +++++- .../web3-eth-contract/test/fixtures/create.ts | 134 ++++++++++++++++++ .../test/fixtures/create2.ts | 70 +++++++++ .../test/integration/contract_deploy.test.ts | 14 +- .../web3-eth-contract/test/unit/utils.test.ts | 94 ++++++++++++ yarn.lock | 46 ++++-- 7 files changed, 394 insertions(+), 11 deletions(-) create mode 100644 packages/web3-eth-contract/test/fixtures/create.ts create mode 100644 packages/web3-eth-contract/test/fixtures/create2.ts create mode 100644 packages/web3-eth-contract/test/unit/utils.test.ts diff --git a/packages/web3-eth-contract/package.json b/packages/web3-eth-contract/package.json index 74edee8f90b..81a3a9f2a3a 100644 --- a/packages/web3-eth-contract/package.json +++ b/packages/web3-eth-contract/package.json @@ -45,6 +45,7 @@ "test:e2e:firefox": "npx cypress run --headless --browser firefox --env grep='ignore',invert=true" }, "dependencies": { + "@ethereumjs/rlp": "^5.0.2", "web3-core": "^4.4.0", "web3-errors": "^1.2.0", "web3-eth": "^4.7.0", diff --git a/packages/web3-eth-contract/src/utils.ts b/packages/web3-eth-contract/src/utils.ts index d2afe72a7b2..748203ffdf7 100644 --- a/packages/web3-eth-contract/src/utils.ts +++ b/packages/web3-eth-contract/src/utils.ts @@ -15,7 +15,8 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ -import { Web3ContractError } from 'web3-errors'; +import { RLP } from '@ethereumjs/rlp'; +import { InvalidAddressError, InvalidMethodParamsError, InvalidNumberError, Web3ContractError } from 'web3-errors'; import { TransactionForAccessList, AbiFunctionFragment, @@ -26,8 +27,10 @@ import { NonPayableCallOptions, PayableCallOptions, ContractOptions, + Numbers, } from 'web3-types'; -import { isNullish, mergeDeep, isContractInitOptions } from 'web3-utils'; +import { isNullish, mergeDeep, isContractInitOptions, keccak256, toChecksumAddress, hexToNumber } from 'web3-utils'; +import { isAddress, isHexString } from 'web3-validator'; import { encodeMethodABI } from './encoding.js'; import { Web3ContractContext } from './types.js'; @@ -210,3 +213,42 @@ export const getCreateAccessListParams = ({ return txParams; }; + + +export const createContractAddress = (from: Address, nonce: Numbers): Address => { + if(!isAddress(from)) + throw new InvalidAddressError(`Invalid address given ${from}`); + + let nonceValue = nonce; + if(typeof nonce === "string" && isHexString(nonce)) + nonceValue = hexToNumber(nonce); + else if(typeof nonce === "string" && !isHexString(nonce)) + throw new InvalidNumberError("Invalid nonce value format"); + + const rlpEncoded = RLP.encode( + [from, nonceValue] + ); + const result = keccak256(rlpEncoded); + + const contractAddress = '0x'.concat(result.substring(26)); + + return toChecksumAddress(contractAddress); +} + +export const create2ContractAddress = (from: Address, salt: HexString, initCode: HexString): Address => { + if(!isAddress(from)) + throw new InvalidAddressError(`Invalid address given ${from}`); + + if(!isHexString(salt)) + throw new InvalidMethodParamsError(`Invalid salt value ${salt}`); + + if(!isHexString(initCode)) + throw new InvalidMethodParamsError(`Invalid initCode value ${initCode}`); + + const initCodeHash = keccak256(initCode); + const initCodeHashPadded = initCodeHash.padStart(64, '0'); // Pad to 32 bytes (64 hex characters) + const create2Params = ['0xff', from, salt, initCodeHashPadded].map(x => x.replace(/0x/, '')); + const create2Address = `0x${ create2Params.join('')}`; + + return toChecksumAddress(`0x${ keccak256(create2Address).slice(26)}`); // Slice to get the last 20 bytes (40 hex characters) & checksum + } \ No newline at end of file diff --git a/packages/web3-eth-contract/test/fixtures/create.ts b/packages/web3-eth-contract/test/fixtures/create.ts new file mode 100644 index 00000000000..0297828e5f1 --- /dev/null +++ b/packages/web3-eth-contract/test/fixtures/create.ts @@ -0,0 +1,134 @@ +/* +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 { Numbers } from "web3-types"; + +export interface CreateTestData { + address: string; + input: { + from: string; + nonce: Numbers; + }; + } + +export const testData: CreateTestData[] = [ + { + address: '0x0C1B54fb6fdf63DEe15e65CAdBA8F2e028E26Bd0', + + input: { + from: '0xe2597eb05cf9a87eb1309e86750c903ec38e527e', + nonce: 0, + } + }, + { + address: '0x0C1B54fb6fdf63DEe15e65CAdBA8F2e028E26Bd0', + + input: { + from: '0xe2597eb05cf9a87eb1309e86750c903ec38e527e', + nonce: BigInt(0), + } + }, + { + address: '0x0C1B54fb6fdf63DEe15e65CAdBA8F2e028E26Bd0', + + input: { + from: '0xe2597eb05cf9a87eb1309e86750c903ec38e527e', + nonce: "0x0", + } + }, + { + address: '0x3474627D4F63A678266BC17171D87f8570936622', + + input: { + from: '0xb2682160c482eb985ec9f3e364eec0a904c44c23', + nonce: 10, + } + }, + + { + address: '0x3474627D4F63A678266BC17171D87f8570936622', + + input: { + from: '0xb2682160c482eb985ec9f3e364eec0a904c44c23', + nonce: "0xa", + } + }, + + { + address: '0x3474627D4F63A678266BC17171D87f8570936622', + + input: { + from: '0xb2682160c482eb985ec9f3e364eec0a904c44c23', + nonce: "0x0a", + } + }, + + { + address: '0x271300790813f82638A8A6A8a86d65df6dF33c17', + + input: { + from: '0x8ba1f109551bd432803012645ac136ddd64dba72', + nonce: "0x200", + } + }, + + { + address: '0x271300790813f82638A8A6A8a86d65df6dF33c17', + + input: { + from: '0x8ba1f109551bd432803012645ac136ddd64dba72', + nonce: "0x0200", + } + }, + + { + address: '0x995C25706C407a1F1E84b3777775e3e619764933', + + input: { + from: '0x8ba1f109551bd432803012645ac136ddd64dba72', + nonce: "0x1d", + } + }, + + { + address: '0x995C25706C407a1F1E84b3777775e3e619764933', + + input: { + from: '0x8ba1f109551bd432803012645ac136ddd64dba72', + nonce: "0x001d", + } + }, + + { + address: '0x995C25706C407a1F1E84b3777775e3e619764933', + + input: { + from: '0x8ba1f109551bd432803012645ac136ddd64dba72', + nonce: 29, + } + }, + + + { + address: '0x0CcCC7507aEDf9FEaF8C8D731421746e16b4d39D', + + input: { + from: '0xc6af6e1a78a6752c7f8cd63877eb789a2adb776c', + nonce: 0 + } + }, +]; \ No newline at end of file diff --git a/packages/web3-eth-contract/test/fixtures/create2.ts b/packages/web3-eth-contract/test/fixtures/create2.ts new file mode 100644 index 00000000000..2cceb34f1bc --- /dev/null +++ b/packages/web3-eth-contract/test/fixtures/create2.ts @@ -0,0 +1,70 @@ +/* +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 { Address, HexString } from "web3-types"; + +export interface Create2TestData { + address: Address; + salt: HexString; + init_code: HexString; + result: Address; + } + + export const create2TestData: Create2TestData[] = [ + { + address: "0x0000000000000000000000000000000000000000", + salt: "0x0000000000000000000000000000000000000000000000000000000000000000", + init_code: "0x00", + result: "0x4D1A2e2bB4F88F0250f26Ffff098B0b30B26BF38" + }, + { + address: "0xdeadbeef00000000000000000000000000000000", + salt: "0x0000000000000000000000000000000000000000000000000000000000000000", + init_code: "0x00", + result: "0xB928f69Bb1D91Cd65274e3c79d8986362984fDA3" + }, + { + address: "0xdeadbeef00000000000000000000000000000000", + salt: "0x000000000000000000000000feed000000000000000000000000000000000000", + init_code: "0x00", + result: "0xD04116cDd17beBE565EB2422F2497E06cC1C9833" + }, + { + address: "0x0000000000000000000000000000000000000000", + salt: "0x0000000000000000000000000000000000000000000000000000000000000000", + init_code: "0xdeadbeef", + result: "0x70f2b2914A2a4b783FaEFb75f459A580616Fcb5e" + }, + { + address: "0x00000000000000000000000000000000deadbeef", + salt: "0x00000000000000000000000000000000000000000000000000000000cafebabe", + init_code: "0xdeadbeef", + result: "0x60f3f640a8508fC6a86d45DF051962668E1e8AC7" + }, + { + address: "0x00000000000000000000000000000000deadbeef", + salt: "0x00000000000000000000000000000000000000000000000000000000cafebabe", + init_code: "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef", + result: "0x1d8bfDC5D46DC4f61D6b6115972536eBE6A8854C" + }, + { + address: "0x0000000000000000000000000000000000000000", + salt: "0x0000000000000000000000000000000000000000000000000000000000000000", + init_code: "0x", + result: "0xE33C0C7F7df4809055C3ebA6c09CFe4BaF1BD9e0" + } + ]; \ No newline at end of file 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 b8036c123a3..2ff87f07177 100644 --- a/packages/web3-eth-contract/test/integration/contract_deploy.test.ts +++ b/packages/web3-eth-contract/test/integration/contract_deploy.test.ts @@ -16,7 +16,7 @@ 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 { Contract, createContractAddress } from '../../src'; import { sleep } from '../shared_fixtures/utils'; import { ERC721TokenAbi, ERC721TokenBytecode } from '../shared_fixtures/build/ERC721Token'; import { GreeterBytecode, GreeterAbi } from '../shared_fixtures/build/Greeter'; @@ -59,6 +59,18 @@ describe('contract', () => { sendOptions = { from: acc.address, gas: '1000000' }; }); + it('should get correct contract address before deploymet using CREATE', async () => { + const nonce = await web3Eth.getTransactionCount(sendOptions.from as string); + + // get contract address before deployment + const address = createContractAddress(sendOptions.from as string, nonce); + + const deployedContract = await contract.deploy(deployOptions).send(sendOptions); + + expect(deployedContract).toBeDefined(); + expect(deployedContract.options.address).toEqual(address); + }); + afterAll(async () => { await closeOpenConnection(web3Eth); }); diff --git a/packages/web3-eth-contract/test/unit/utils.test.ts b/packages/web3-eth-contract/test/unit/utils.test.ts new file mode 100644 index 00000000000..3b0b69a2bfc --- /dev/null +++ b/packages/web3-eth-contract/test/unit/utils.test.ts @@ -0,0 +1,94 @@ +/* +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 { InvalidAddressError, InvalidNumberError } from "web3-errors"; +import { Address, Numbers } from "web3-types"; +import { CreateTestData, testData } from '../fixtures/create'; +import { create2ContractAddress, createContractAddress } from "../../src/utils"; +import { create2TestData } from "../fixtures/create2"; + + +describe('createContractAddress', () => { + + it.each(testData)('creates correct contract address for input: %o', (testCase: CreateTestData) => { + const { address, input } = testCase; + const result = createContractAddress(input.from , input.nonce ); + expect(result).toBe(address); + }); + + it('should throw InvalidAddressError for invalid address', () => { + expect(() => createContractAddress('invalid_address', 1)).toThrow(InvalidAddressError); + }); + + it('should throw Error for invalid nonce', () => { + expect(() => createContractAddress('0xe2597eb05cf9a87eb1309e86750c903ec38e527e', "")).toThrow(InvalidNumberError); + }); + + it('should handle different nonce types correctly', () => { + const from: Address = '0x6ac7ea33f8831ea9dcc53393aaa88b25a785dbf0'; + const testCases: [Numbers, string][] = [ + [1, '0x343c43A37D37dfF08AE8C4A11544c718AbB4fCF8'], + ['0x2', '0xf778B86FA74E846c4f0a1fBd1335FE81c00a0C91'], + [BigInt(3), '0xffFd933A0bC612844eaF0C6Fe3E5b8E9B6C1d19c'], + ]; + + testCases.forEach(([nonce, expectedAddress]) => { + const result = createContractAddress(from, nonce); + expect(result).toBe(expectedAddress); + }); + }); + + it('should create different addresses for different nonces', () => { + const from: Address = '0x6ac7ea33f8831ea9dcc53393aaa88b25a785dbf0'; + const address1 = createContractAddress(from, 0); + const address2 = createContractAddress(from, 1); + + expect(address1).not.toBe(address2); + }); + + it('should create different addresses for different sender addresses', () => { + const from1: Address = '0x6ac7ea33f8831ea9dcc53393aaa88b25a785dbf0'; + const from2: Address = '0x1234567890123456789012345678901234567890'; + const nonce: Numbers = 0; + + const address1 = createContractAddress(from1, nonce); + const address2 = createContractAddress(from2, nonce); + + expect(address1).not.toBe(address2); + }); +}); + +describe('create2ContractAddress', () => { + + it.each(create2TestData)('creates correct contract address for input: %o', (testCase) => { + const result = create2ContractAddress(testCase.address, testCase.salt, testCase.init_code); + expect(result).toBe(testCase.result); + }); + + it('should throw an InvalidAddressError if the from address is invalid', () => { + expect(() => create2ContractAddress('0xinvalidaddress', create2TestData[0].salt, create2TestData[0].init_code)).toThrow('Invalid address given 0xinvalidaddress'); + }); + + it('should throw an InvalidMethodParamsError if the salt is invalid', () => { + expect(() => create2ContractAddress(create2TestData[0].address, '0xinvalidsalt', create2TestData[0].init_code)).toThrow('Invalid salt value 0xinvalidsalt'); + }); + + it('should throw an InvalidMethodParamsError if the initCode is invalid', () => { + expect(() => create2ContractAddress(create2TestData[0].address, create2TestData[0].salt, '0xinvalidcode')).toThrow('Invalid initCode value 0xinvalidcode'); + }); + +}); \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index b0c3fe19f17..e85fa099abb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -507,6 +507,11 @@ resolved "https://registry.yarnpkg.com/@ethereumjs/rlp/-/rlp-4.0.1.tgz#626fabfd9081baab3d0a3074b0c7ecaf674aaa41" integrity sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw== +"@ethereumjs/rlp@^5.0.2": + version "5.0.2" + resolved "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-5.0.2.tgz#c89bd82f2f3bec248ab2d517ae25f5bbc4aac842" + integrity sha512-DziebCdg4JpGlEqEdGgXmjqcFoJi+JGulUXwEjsZGAscAQ7MyD/7LE/GVCP29vEQxKc7AAwjT3A2ywHp2xfoCA== + "@ethereumjs/tx@^3.3.0": version "3.5.2" resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.5.2.tgz#197b9b6299582ad84f9527ca961466fce2296c1c" @@ -11458,7 +11463,7 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -11476,6 +11481,15 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -11522,7 +11536,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -11536,6 +11550,13 @@ strip-ansi@^3.0.0, strip-ansi@^3.0.1: dependencies: ansi-regex "^2.0.0" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" @@ -12622,7 +12643,16 @@ workerpool@6.2.1: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -12721,10 +12751,10 @@ ws@^8.11.0: resolved "https://registry.yarnpkg.com/ws/-/ws-8.14.2.tgz#6c249a806eb2db7a20d26d51e7709eab7b2e6c7f" integrity sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g== -ws@^8.8.1: - version "8.8.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.8.1.tgz#5dbad0feb7ade8ecc99b830c1d77c913d4955ff0" - integrity sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA== +ws@^8.17.1: + version "8.17.1" + resolved "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" + integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== xhr@^2.2.0: version "2.6.0" @@ -12855,4 +12885,4 @@ yocto-queue@^0.1.0: zod@^3.21.4: version "3.22.3" resolved "https://registry.yarnpkg.com/zod/-/zod-3.22.3.tgz#2fbc96118b174290d94e8896371c95629e87a060" - integrity sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug== \ No newline at end of file + integrity sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug== From e9fc019963cd62bcaaae2463057b45844f8077a2 Mon Sep 17 00:00:00 2001 From: Junaid <86780488+jdevcs@users.noreply.github.com> Date: Mon, 8 Jul 2024 16:20:56 +0200 Subject: [PATCH 113/186] Contract Transactions Middleware (#7138) * contract transactionMiddleware * transactionMiddleware setting for contract from eth * contract Tx middleware plugin * contract tx middleware tests * changelog * fix * test import fix * integration patch fix * lint fix * integration tests * middleware in fixture * unit test * lint fix * fixture fix for lint import err via symlink * unit test coverage push * up coverage --- packages/web3-eth-contract/CHANGELOG.md | 6 +- packages/web3-eth-contract/src/contract.ts | 40 ++++-- .../contract_transaction_middleware.ts | 38 ++++++ .../test/unit/contract.test.ts | 67 ++++++++++ packages/web3/CHANGELOG.md | 6 + packages/web3/src/web3.ts | 9 ++ .../test/fixtures/transaction_middleware.ts | 38 ++++++ .../integration/contract-middleware.test.ts | 116 ++++++++++++++++++ .../test/unit/contract-middleware.test.ts | 54 ++++++++ .../src/transaction_middleware_plugin.ts | 2 + .../contract_transaction_middleware.test.ts | 101 +++++++++++++++ .../test/unit/fixtures/Greeter.ts | 58 +++++++++ 12 files changed, 525 insertions(+), 10 deletions(-) create mode 100644 packages/web3-eth-contract/test/fixtures/contract_transaction_middleware.ts create mode 100644 packages/web3/test/fixtures/transaction_middleware.ts create mode 100644 packages/web3/test/integration/contract-middleware.test.ts create mode 100644 packages/web3/test/unit/contract-middleware.test.ts create mode 100644 tools/web3-plugin-example/test/unit/contract_transaction_middleware.test.ts create mode 100644 tools/web3-plugin-example/test/unit/fixtures/Greeter.ts diff --git a/packages/web3-eth-contract/CHANGELOG.md b/packages/web3-eth-contract/CHANGELOG.md index 8e275470925..e0cda223234 100644 --- a/packages/web3-eth-contract/CHANGELOG.md +++ b/packages/web3-eth-contract/CHANGELOG.md @@ -386,4 +386,8 @@ Documentation: - `defaultReturnFormat` was added to all methods that have `ReturnType` param. (#6947) -## [Unreleased] \ No newline at end of file +## [Unreleased] + +### Added + +- Contract has `setTransactionMiddleware` and `getTransactionMiddleware` for automatically passing to `sentTransaction` for `deploy` and `send` functions (#7138) \ No newline at end of file diff --git a/packages/web3-eth-contract/src/contract.ts b/packages/web3-eth-contract/src/contract.ts index c4be775b31f..64f44440472 100644 --- a/packages/web3-eth-contract/src/contract.ts +++ b/packages/web3-eth-contract/src/contract.ts @@ -39,6 +39,8 @@ import { ALL_EVENTS, ALL_EVENTS_ABI, SendTransactionEvents, + TransactionMiddleware, + SendTransactionOptions, } from 'web3-eth'; import { encodeEventSignature, @@ -433,7 +435,7 @@ export class Contract */ public readonly options: ContractOptions; - + private transactionMiddleware?: TransactionMiddleware; /** * Set to true if you want contracts' defaults to sync with global defaults. */ @@ -640,6 +642,14 @@ export class Contract } } + public setTransactionMiddleware(transactionMiddleware: TransactionMiddleware) { + this.transactionMiddleware = transactionMiddleware; + } + + public getTransactionMiddleware() { + return this.transactionMiddleware; + } + /** * Subscribe to an event. * @@ -1396,11 +1406,17 @@ export class Contract contractOptions: modifiedContractOptions, }); - const transactionToSend = sendTransaction(this, tx, this.defaultReturnFormat, { - // TODO Should make this configurable by the user - checkRevertBeforeSending: false, - contractAbi: this._jsonInterface, - }); + const transactionToSend = (isNullish(this.transactionMiddleware)) ? + sendTransaction(this, tx, this.defaultReturnFormat, { + // TODO Should make this configurable by the user + checkRevertBeforeSending: false, + contractAbi: this._jsonInterface, // explicitly not passing middleware so if some one is using old eth package it will not break + }) : + sendTransaction(this, tx, this.defaultReturnFormat, { + // TODO Should make this configurable by the user + checkRevertBeforeSending: false, + contractAbi: this._jsonInterface, + }, this.transactionMiddleware); // eslint-disable-next-line no-void void transactionToSend.on('error', (error: unknown) => { @@ -1429,8 +1445,9 @@ export class Contract options: { ...options, dataInputFill: this.contractDataInputFill }, contractOptions: modifiedContractOptions, }); - return sendTransaction(this, tx, this.defaultReturnFormat, { - transactionResolver: receipt => { + + const returnTxOptions: SendTransactionOptions> = { + transactionResolver: (receipt: TransactionReceipt) => { if (receipt.status === BigInt(0)) { throw new Web3ContractError("code couldn't be stored", receipt); } @@ -1444,7 +1461,12 @@ export class Contract contractAbi: this._jsonInterface, // TODO Should make this configurable by the user checkRevertBeforeSending: false, - }); + }; + + return ( + (isNullish(this.transactionMiddleware)) ? + sendTransaction(this, tx, this.defaultReturnFormat, returnTxOptions) : // not calling this with undefined Middleware because it will not break if Eth package is not updated + sendTransaction(this, tx, this.defaultReturnFormat, returnTxOptions, this.transactionMiddleware)); } private async _contractMethodEstimateGas< diff --git a/packages/web3-eth-contract/test/fixtures/contract_transaction_middleware.ts b/packages/web3-eth-contract/test/fixtures/contract_transaction_middleware.ts new file mode 100644 index 00000000000..9a1ab0f20cf --- /dev/null +++ b/packages/web3-eth-contract/test/fixtures/contract_transaction_middleware.ts @@ -0,0 +1,38 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ + +import { TransactionMiddleware, TransactionMiddlewareData } from "web3-eth"; + +// Sample Transaction Middleware +export class ContractTransactionMiddleware implements TransactionMiddleware { + + // eslint-disable-next-line class-methods-use-this + public async processTransaction(transaction: TransactionMiddlewareData, + _options?: { [key: string]: unknown } | undefined): + + Promise { + + // eslint-disable-next-line prefer-const + let txObj = { ...transaction }; + + // Add your logic here for transaction modification + txObj.data = '0x123'; + + return Promise.resolve(txObj); + } + +} diff --git a/packages/web3-eth-contract/test/unit/contract.test.ts b/packages/web3-eth-contract/test/unit/contract.test.ts index d35dbdefb48..8d5c0445fb2 100644 --- a/packages/web3-eth-contract/test/unit/contract.test.ts +++ b/packages/web3-eth-contract/test/unit/contract.test.ts @@ -35,6 +35,7 @@ import { getSystemTestProvider } from '../fixtures/system_test_utils'; import { erc721Abi } from '../fixtures/erc721'; import { ERC20TokenAbi } from '../shared_fixtures/build/ERC20Token'; import { processAsync } from '../shared_fixtures/utils'; +import { ContractTransactionMiddleware } from "../fixtures/contract_transaction_middleware"; jest.mock('web3-eth', () => { const allAutoMocked = jest.createMockFromModule('web3-eth'); @@ -275,6 +276,61 @@ describe('Contract', () => { sendTransactionSpy.mockClear(); }); + it('should pass middleware to sendTransaction when middleware is there and deploy().send() is called', async () => { + const contract = new Contract(GreeterAbi); + const middleware = new ContractTransactionMiddleware(); + contract.setTransactionMiddleware(middleware) + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const sendTransactionSpy = jest + .spyOn(eth, 'sendTransaction') + .mockImplementation((_objInstance, _tx, _dataFormat, _options, _middleware) => { + + expect(_middleware).toBeDefined(); + const newContract = contract.clone(); + newContract.options.address = deployedAddr; + + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return Promise.resolve(newContract) as any; + }); + + await contract + .deploy({ + input: GreeterBytecode, + arguments: ['My Greeting'], + }) + .send(sendOptions); + + sendTransactionSpy.mockClear(); + }); + + it('should pass middleware to sendTransaction when middleware is there and contract.method.send() is called', async () => { + + const contract = new Contract(GreeterAbi, '0x12264916b10Ae90076dDa6dE756EE1395BB69ec2'); + const middleware = new ContractTransactionMiddleware(); + contract.setTransactionMiddleware(middleware); + + const spyTx = jest + .spyOn(eth, 'sendTransaction') + .mockImplementation((_objInstance, _tx, _dataformat, _options, _middleware) => { + + expect(_middleware).toBeDefined(); + + // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-empty-function + return { status: '0x1', on: () => {} } as any; + + }); + + const receipt = await contract.methods.setGreeting('Hello').send({ + from: '0x12364916b10Ae90076dDa6dE756EE1395BB69ec2', + gas: '1000000' + }); + + expect(receipt.status).toBe('0x1'); + + spyTx.mockClear(); + }); + it('should deploy contract with input property with no ABI', async () => { const input = `${GreeterBytecode}0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000b4d79204772656574696e67000000000000000000000000000000000000000000`; const contract = new Contract([]); @@ -788,6 +844,17 @@ describe('Contract', () => { expect(contract.methods.setGreeting).toBeDefined(); }); + it('should be able to set and get transaction middleware', () => { + const contract = new Contract(sampleStorageContractABI); + const middleware = new ContractTransactionMiddleware(); + + expect(contract.getTransactionMiddleware()).toBeUndefined(); + + contract.setTransactionMiddleware(middleware); + expect(contract.getTransactionMiddleware()).toBeDefined(); + expect(contract.getTransactionMiddleware()).toEqual(middleware); + }); + it('defaults set and get should work', () => { const contract = new Contract([], '0x00000000219ab540356cBB839Cbe05303d7705Fa'); diff --git a/packages/web3/CHANGELOG.md b/packages/web3/CHANGELOG.md index 2e649c3ee0f..fb638a0d56b 100644 --- a/packages/web3/CHANGELOG.md +++ b/packages/web3/CHANGELOG.md @@ -382,3 +382,9 @@ Documentation: - `getName` reverse resolution ## [Unreleased] + +### Added + +#### web3 + +- `web3.eth.Contract` will get transaction middleware and use it, if `web3.eth` has transaction middleware. (#7138) \ No newline at end of file diff --git a/packages/web3/src/web3.ts b/packages/web3/src/web3.ts index a3b6b462842..9b231e7c6eb 100644 --- a/packages/web3/src/web3.ts +++ b/packages/web3/src/web3.ts @@ -203,6 +203,15 @@ export class Web3< super(jsonInterface, address, options, context, dataFormat); super.subscribeToContextEvents(self); + + // eslint-disable-next-line no-use-before-define + if (!isNullish(eth)) { + // eslint-disable-next-line no-use-before-define + const TxMiddleware = eth.getTransactionMiddleware(); + if (!isNullish(TxMiddleware)) { + super.setTransactionMiddleware(TxMiddleware); + } + } } } diff --git a/packages/web3/test/fixtures/transaction_middleware.ts b/packages/web3/test/fixtures/transaction_middleware.ts new file mode 100644 index 00000000000..f2d74a973e0 --- /dev/null +++ b/packages/web3/test/fixtures/transaction_middleware.ts @@ -0,0 +1,38 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ + +import { TransactionMiddleware, TransactionMiddlewareData } from "web3-eth"; + +// Sample Transaction Middleware +export class CTransactionMiddleware implements TransactionMiddleware { + + // eslint-disable-next-line class-methods-use-this + public async processTransaction(transaction: TransactionMiddlewareData, + _options?: { [key: string]: unknown } | undefined): + + Promise { + + // eslint-disable-next-line prefer-const + let txObj = { ...transaction }; + + // Add your logic here for transaction modification + txObj.data = '0x123'; + + return Promise.resolve(txObj); + } + +} diff --git a/packages/web3/test/integration/contract-middleware.test.ts b/packages/web3/test/integration/contract-middleware.test.ts new file mode 100644 index 00000000000..dd8c4b8df1b --- /dev/null +++ b/packages/web3/test/integration/contract-middleware.test.ts @@ -0,0 +1,116 @@ +/* +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 { CTransactionMiddleware } from +// eslint-disable-next-line import/no-relative-packages +"../fixtures/transaction_middleware"; + +import { blockMockResult, receiptMockResult } from +// eslint-disable-next-line import/no-relative-packages +"../../../../tools/web3-plugin-example/test/unit/fixtures/transactions_data"; + +import { Web3 } from '../../src/index'; +import { + ERC20TokenAbi, + // eslint-disable-next-line import/no-relative-packages +} from '../shared_fixtures/contracts/ERC20Token'; + +describe('Contract Middleware', () => { + it('should set transaction middleware in contract new instance if its set at eth package', async () => { + const web3 = new Web3(); + const contractA = new web3.eth.Contract( + ERC20TokenAbi, + '0x7af963cF6D228E564e2A0aA0DdBF06210B38615D', + ); + + expect(web3.eth.getTransactionMiddleware()).toBeUndefined(); + expect(contractA.getTransactionMiddleware()).toBeUndefined(); + + const middleware = new CTransactionMiddleware(); + web3.eth.setTransactionMiddleware(middleware); + + const contractB = new web3.eth.Contract( + ERC20TokenAbi, + '0x7af963cF6D228E564e2A0aA0DdBF06210B38615D', + ); + + expect(web3.eth.getTransactionMiddleware()).toBeDefined(); + expect(contractB.getTransactionMiddleware()).toBeDefined(); + expect(web3.eth.getTransactionMiddleware()).toEqual(contractB.getTransactionMiddleware()); + + }); + + it('should send transaction middleware in contract new instance if its set at eth package', async () => { + const web3 = new Web3(); + + const middleware = new CTransactionMiddleware(); + web3.eth.setTransactionMiddleware(middleware); + + const contract = new web3.eth.Contract( + ERC20TokenAbi, + '0x7af963cF6D228E564e2A0aA0DdBF06210B38615D', + ); + + const sendTransactionSpy = jest.fn(); + const account = web3.eth.accounts.create(); + + let blockNum = 1000; + web3.requestManager.send = jest.fn(async (request) => { + blockNum += 1; + + if (request.method === 'eth_getBlockByNumber') { + + return Promise.resolve(blockMockResult.result); + } + if (request.method === 'eth_call') { + + return Promise.resolve("0x"); + } + if (request.method === 'eth_blockNumber') { + + return Promise.resolve(blockNum.toString(16)); + } + if (request.method === 'eth_sendTransaction') { + + sendTransactionSpy(request.params); + + return Promise.resolve("0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f"); + } + if (request.method === 'eth_getTransactionReceipt') { + return Promise.resolve(receiptMockResult.result); + } + + return Promise.resolve("Unknown Request" as any); + }); + + await contract.methods.transfer(account.address, 100).send({ from: account?.address }); + + // Check that sendTransactionSpy has been called exactly once + expect(sendTransactionSpy).toHaveBeenCalledTimes(1); + + // Check that sendTransactionSpy has been called with a parameter containing data: "0x123" + expect(sendTransactionSpy).toHaveBeenCalledWith( + expect.arrayContaining([ + expect.objectContaining({ + data: "0x123", + from: account.address, + }) + ]) + ); + }); +}); + diff --git a/packages/web3/test/unit/contract-middleware.test.ts b/packages/web3/test/unit/contract-middleware.test.ts new file mode 100644 index 00000000000..1d7f7d2095d --- /dev/null +++ b/packages/web3/test/unit/contract-middleware.test.ts @@ -0,0 +1,54 @@ +/* +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 { CTransactionMiddleware } from +// eslint-disable-next-line import/no-relative-packages +"../fixtures/transaction_middleware"; + +import { Web3 } from '../../src/index'; +import { + ERC20TokenAbi, + // eslint-disable-next-line import/no-relative-packages +} from '../shared_fixtures/contracts/ERC20Token'; + +describe('Contract Middleware', () => { + it('should set transaction middleware in contract new instance if its set at eth package', async () => { + const web3 = new Web3(); + const contractA = new web3.eth.Contract( + ERC20TokenAbi, + '0x7af963cF6D228E564e2A0aA0DdBF06210B38615D', + ); + + expect(web3.eth.getTransactionMiddleware()).toBeUndefined(); + expect(contractA.getTransactionMiddleware()).toBeUndefined(); + + const middleware = new CTransactionMiddleware(); + web3.eth.setTransactionMiddleware(middleware); + + const contractB = new web3.eth.Contract( + ERC20TokenAbi, + '0x7af963cF6D228E564e2A0aA0DdBF06210B38615D', + ); + + expect(web3.eth.getTransactionMiddleware()).toBeDefined(); + expect(contractB.getTransactionMiddleware()).toBeDefined(); + expect(web3.eth.getTransactionMiddleware()).toEqual(contractB.getTransactionMiddleware()); + + }); + +}); + diff --git a/tools/web3-plugin-example/src/transaction_middleware_plugin.ts b/tools/web3-plugin-example/src/transaction_middleware_plugin.ts index 3dd86ed7e26..bd9eca6b848 100644 --- a/tools/web3-plugin-example/src/transaction_middleware_plugin.ts +++ b/tools/web3-plugin-example/src/transaction_middleware_plugin.ts @@ -33,6 +33,8 @@ export class TransactionMiddlewarePlugin extends Web3PluginBase { public link(parentContext: Web3Context): void { if (this.txMiddleware){ + // Following can modify Web3-Eth and also Web3-Eth-Contract packages transactions + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call (parentContext as any).Web3Eth.setTransactionMiddleware(this.txMiddleware); } diff --git a/tools/web3-plugin-example/test/unit/contract_transaction_middleware.test.ts b/tools/web3-plugin-example/test/unit/contract_transaction_middleware.test.ts new file mode 100644 index 00000000000..024e4219d28 --- /dev/null +++ b/tools/web3-plugin-example/test/unit/contract_transaction_middleware.test.ts @@ -0,0 +1,101 @@ +/* +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, Contract } from 'web3'; +import { GreeterAbi, GreeterBytecode } from './fixtures/Greeter'; +import { TransactionMiddlewarePlugin } from '../../src/transaction_middleware_plugin'; +import { blockMockResult, receiptMockResult } from './fixtures/transactions_data'; + +describe('Contract Transaction Middleware', () => { + + it('should modify contracts deployment transaction before signing and sending', async () => { + + // This will allow Contract Transaction modification before signing and gas estimations + + const web3 = new Web3('http://127.0.0.1:8545'); + const plugin: TransactionMiddlewarePlugin = new TransactionMiddlewarePlugin(); + + /// Mock block starts - Mock web3 internal calls for test + let blockNum = 1000; + + // Create a spy for eth_sendTransaction + const sendTransactionSpy = jest.fn(); + + web3.requestManager.send = jest.fn(async (request) => { + blockNum += 1; + + if (request.method === 'eth_getBlockByNumber') { + return Promise.resolve(blockMockResult.result); + } + if (request.method === 'eth_blockNumber') { + return Promise.resolve(blockNum.toString(16)); + } + if (request.method === 'eth_sendTransaction') { + // Call the spy with the request params + sendTransactionSpy(request.params); + return Promise.resolve("0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f"); + } + if (request.method === 'eth_getTransactionReceipt') { + return Promise.resolve(receiptMockResult.result); + } + + return Promise.resolve("Unknown Request" as any); + }); + + /// Mock block ends here + + web3.registerPlugin(plugin); + + const contract: Contract = new web3.eth.Contract(GreeterAbi); + + await contract.deploy( + { + data: GreeterBytecode, + arguments: ['My Greeting'], + } as any) + + .send( + { from: '0x6E599DA0bfF7A6598AC1224E4985430Bf16458a4' } + ); // this should call Tx middleware for contract deploy + + const deployedContract = new web3.eth.Contract(GreeterAbi, "0x5FbDB2315678afecb367f032d93F642f64180aa3"); + await deployedContract.methods.increment().send( + { from: '0x6E599DA0bfF7A6598AC1224E4985430Bf16458a4' }); // this should call Tx middleware for method send + + // First, check the number of calls + expect(sendTransactionSpy).toHaveBeenCalledTimes(2); + + const expectedData = "0x123"; + // Then, check each call individually + expect(sendTransactionSpy.mock.calls[0][0]).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + data: expectedData + }) + ]) + ); + + expect(sendTransactionSpy.mock.calls[1][0]).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + data: expectedData + }) + ]) + ); + }); + +}); diff --git a/tools/web3-plugin-example/test/unit/fixtures/Greeter.ts b/tools/web3-plugin-example/test/unit/fixtures/Greeter.ts new file mode 100644 index 00000000000..3ce6ab1b3dd --- /dev/null +++ b/tools/web3-plugin-example/test/unit/fixtures/Greeter.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 . +*/ +export const GreeterAbi = [ + { + inputs: [{ internalType: 'string', name: '_greeting', type: 'string' }], + stateMutability: 'nonpayable', + type: 'constructor', + }, + { + anonymous: false, + inputs: [{ indexed: false, internalType: 'string', name: 'greeting', type: 'string' }], + name: 'GREETING_CHANGED', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: 'string', name: 'from', type: 'string' }, + { indexed: false, internalType: 'string', name: 'to', type: 'string' }, + ], + name: 'GREETING_CHANGING', + type: 'event', + }, + { + inputs: [], + name: 'greet', + outputs: [{ internalType: 'string', name: '', type: 'string' }], + stateMutability: 'view', + type: 'function', + }, + { inputs: [], name: 'increment', outputs: [], stateMutability: 'nonpayable', type: 'function' }, + { + inputs: [{ internalType: 'string', name: '_greeting', type: 'string' }], + name: 'setGreeting', + outputs: [ + { internalType: 'bool', name: '', type: 'bool' }, + { internalType: 'string', name: '', type: 'string' }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, +] as const; +export const GreeterBytecode = + '0x60806040523480156200001157600080fd5b5060405162000ed038038062000ed08339818101604052810190620000379190620001ea565b806001908162000048919062000486565b5060008081905550506200056d565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b620000c08262000075565b810181811067ffffffffffffffff82111715620000e257620000e162000086565b5b80604052505050565b6000620000f762000057565b9050620001058282620000b5565b919050565b600067ffffffffffffffff82111562000128576200012762000086565b5b620001338262000075565b9050602081019050919050565b60005b838110156200016057808201518184015260208101905062000143565b60008484015250505050565b6000620001836200017d846200010a565b620000eb565b905082815260208101848484011115620001a257620001a162000070565b5b620001af84828562000140565b509392505050565b600082601f830112620001cf57620001ce6200006b565b5b8151620001e18482602086016200016c565b91505092915050565b60006020828403121562000203576200020262000061565b5b600082015167ffffffffffffffff81111562000224576200022362000066565b5b6200023284828501620001b7565b91505092915050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806200028e57607f821691505b602082108103620002a457620002a362000246565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026200030e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82620002cf565b6200031a8683620002cf565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b600062000367620003616200035b8462000332565b6200033c565b62000332565b9050919050565b6000819050919050565b620003838362000346565b6200039b62000392826200036e565b848454620002dc565b825550505050565b600090565b620003b2620003a3565b620003bf81848462000378565b505050565b5b81811015620003e757620003db600082620003a8565b600181019050620003c5565b5050565b601f82111562000436576200040081620002aa565b6200040b84620002bf565b810160208510156200041b578190505b620004336200042a85620002bf565b830182620003c4565b50505b505050565b600082821c905092915050565b60006200045b600019846008026200043b565b1980831691505092915050565b600062000476838362000448565b9150826002028217905092915050565b62000491826200023b565b67ffffffffffffffff811115620004ad57620004ac62000086565b5b620004b9825462000275565b620004c6828285620003eb565b600060209050601f831160018114620004fe5760008415620004e9578287015190505b620004f5858262000468565b86555062000565565b601f1984166200050e86620002aa565b60005b82811015620005385784890151825560018201915060208501945060208101905062000511565b8683101562000558578489015162000554601f89168262000448565b8355505b6001600288020188555050505b505050505050565b610953806200057d6000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c8063a413686214610046578063cfae321714610077578063d09de08a14610095575b600080fd5b610060600480360381019061005b91906103c0565b61009f565b60405161006e9291906104a3565b60405180910390f35b61007f6101bd565b60405161008c91906104d3565b60405180910390f35b61009d61024f565b005b600060607f0d363f2fba46ab11b6db8da0125b0d5484787c44e265b48810735998bab12b756001846040516100d59291906105ee565b60405180910390a182600190816100ec91906107c6565b507f7d7846723bda52976e0286c6efffee937ee9f76817a867ec70531ad29fb1fc0e600160405161011d9190610898565b60405180910390a160018080805461013490610524565b80601f016020809104026020016040519081016040528092919081815260200182805461016090610524565b80156101ad5780601f10610182576101008083540402835291602001916101ad565b820191906000526020600020905b81548152906001019060200180831161019057829003601f168201915b5050505050905091509150915091565b6060600180546101cc90610524565b80601f01602080910402602001604051908101604052809291908181526020018280546101f890610524565b80156102455780601f1061021a57610100808354040283529160200191610245565b820191906000526020600020905b81548152906001019060200180831161022857829003601f168201915b5050505050905090565b600160005461025e91906108e9565b600081905550565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6102cd82610284565b810181811067ffffffffffffffff821117156102ec576102eb610295565b5b80604052505050565b60006102ff610266565b905061030b82826102c4565b919050565b600067ffffffffffffffff82111561032b5761032a610295565b5b61033482610284565b9050602081019050919050565b82818337600083830152505050565b600061036361035e84610310565b6102f5565b90508281526020810184848401111561037f5761037e61027f565b5b61038a848285610341565b509392505050565b600082601f8301126103a7576103a661027a565b5b81356103b7848260208601610350565b91505092915050565b6000602082840312156103d6576103d5610270565b5b600082013567ffffffffffffffff8111156103f4576103f3610275565b5b61040084828501610392565b91505092915050565b60008115159050919050565b61041e81610409565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561045e578082015181840152602081019050610443565b60008484015250505050565b600061047582610424565b61047f818561042f565b935061048f818560208601610440565b61049881610284565b840191505092915050565b60006040820190506104b86000830185610415565b81810360208301526104ca818461046a565b90509392505050565b600060208201905081810360008301526104ed818461046a565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061053c57607f821691505b60208210810361054f5761054e6104f5565b5b50919050565b60008190508160005260206000209050919050565b6000815461057781610524565b610581818661042f565b9450600182166000811461059c57600181146105b2576105e5565b60ff1983168652811515602002860193506105e5565b6105bb85610555565b60005b838110156105dd578154818901526001820191506020810190506105be565b808801955050505b50505092915050565b60006040820190508181036000830152610608818561056a565b9050818103602083015261061c818461046a565b90509392505050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026106727fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82610635565b61067c8683610635565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b60006106c36106be6106b984610694565b61069e565b610694565b9050919050565b6000819050919050565b6106dd836106a8565b6106f16106e9826106ca565b848454610642565b825550505050565b600090565b6107066106f9565b6107118184846106d4565b505050565b5b818110156107355761072a6000826106fe565b600181019050610717565b5050565b601f82111561077a5761074b81610555565b61075484610625565b81016020851015610763578190505b61077761076f85610625565b830182610716565b50505b505050565b600082821c905092915050565b600061079d6000198460080261077f565b1980831691505092915050565b60006107b6838361078c565b9150826002028217905092915050565b6107cf82610424565b67ffffffffffffffff8111156107e8576107e7610295565b5b6107f28254610524565b6107fd828285610739565b600060209050601f831160018114610830576000841561081e578287015190505b61082885826107aa565b865550610890565b601f19841661083e86610555565b60005b8281101561086657848901518255600182019150602085019450602081019050610841565b86831015610883578489015161087f601f89168261078c565b8355505b6001600288020188555050505b505050505050565b600060208201905081810360008301526108b2818461056a565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006108f482610694565b91506108ff83610694565b9250828201905080821115610917576109166108ba565b5b9291505056fea26469706673582212207e5ba44159ffb37af8e8a9e7c5b6fb5ce81ea195b62ae3ac36288f2cf72c18a764736f6c63430008100033'; From 59e67bf9b1ee4b66167e2f41b86967fa8b2d4166 Mon Sep 17 00:00:00 2001 From: Oleksii Kosynskyi Date: Mon, 8 Jul 2024 11:11:49 -0400 Subject: [PATCH 114/186] Zk plugin related fixes (#7124) * Add populate tx method * Update types.ts * fix populate tx * fix lint * add test * changelog * regenerate changelog * fix logs --- CHANGELOG.md | 17 +++ packages/web3-eth-contract/CHANGELOG.md | 4 +- packages/web3-eth-contract/src/contract.ts | 24 +++- packages/web3-eth-contract/src/types.ts | 17 ++- .../test/unit/contract.test.ts | 44 ++++++- packages/web3-types/src/eth_types.ts | 115 +++++++++--------- packages/web3/CHANGELOG.md | 2 +- 7 files changed, 157 insertions(+), 66 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 783691404b9..8eba8930d2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2564,3 +2564,20 @@ If there are any bugs, improvements, optimizations or any new feature proposal f - `getName` reverse resolution ## [Unreleased] + +### Fixed + +#### web3-eth + +- Fixed geth issue when running a new instance, transactions will index when there are no blocks created (#7098) + +### Added + +#### web3 + +- `web3.eth.Contract` will get transaction middleware and use it, if `web3.eth` has transaction middleware. (#7138) + +#### web3-eth-contract + +- `populateTransaction` was added to contract methods (#7124) +- Contract has `setTransactionMiddleware` and `getTransactionMiddleware` for automatically passing to `sentTransaction` for `deploy` and `send` functions (#7138) diff --git a/packages/web3-eth-contract/CHANGELOG.md b/packages/web3-eth-contract/CHANGELOG.md index e0cda223234..a1c4b6f35e5 100644 --- a/packages/web3-eth-contract/CHANGELOG.md +++ b/packages/web3-eth-contract/CHANGELOG.md @@ -390,4 +390,6 @@ Documentation: ### Added -- Contract has `setTransactionMiddleware` and `getTransactionMiddleware` for automatically passing to `sentTransaction` for `deploy` and `send` functions (#7138) \ No newline at end of file +- `populateTransaction` was added to contract methods (#7124) + +- Contract has `setTransactionMiddleware` and `getTransactionMiddleware` for automatically passing to `sentTransaction` for `deploy` and `send` functions (#7138) diff --git a/packages/web3-eth-contract/src/contract.ts b/packages/web3-eth-contract/src/contract.ts index 64f44440472..cba5043df95 100644 --- a/packages/web3-eth-contract/src/contract.ts +++ b/packages/web3-eth-contract/src/contract.ts @@ -1278,7 +1278,29 @@ export class Contract send: (options?: PayableTxOptions | NonPayableTxOptions): ContractMethodSend => this._contractMethodSend(methodAbi, abiParams, internalErrorsAbis, options), - + populateTransaction: ( + options?: PayableTxOptions | NonPayableTxOptions, + contractOptions?: ContractOptions, + ) => { + let modifiedContractOptions = contractOptions ?? this.options; + modifiedContractOptions = { + ...modifiedContractOptions, + input: undefined, + from: modifiedContractOptions?.from ?? this.defaultAccount ?? undefined, + }; + const tx = getSendTxParams({ + abi, + params, + options: { ...options, dataInputFill: this.config.contractDataInputFill }, + contractOptions: modifiedContractOptions, + }); + // @ts-expect-error remove unnecessary field + if (tx.dataInputFill) { + // @ts-expect-error remove unnecessary field + delete tx.dataInputFill; + } + return tx; + }, estimateGas: async ( options?: PayableCallOptions | NonPayableCallOptions, returnFormat: ReturnFormat = this diff --git a/packages/web3-eth-contract/src/types.ts b/packages/web3-eth-contract/src/types.ts index cc2e0c4aec7..8f4bf564ca4 100644 --- a/packages/web3-eth-contract/src/types.ts +++ b/packages/web3-eth-contract/src/types.ts @@ -28,13 +28,15 @@ import { DataFormat, DEFAULT_RETURN_FORMAT, FormatType, + TransactionCall, } from 'web3-types'; import { NewHeadsSubscription, SendTransactionEvents } from 'web3-eth'; +import type { ContractOptions } from 'web3-types'; import { LogsSubscription } from './log_subscription.js'; export type NonPayableTxOptions = NonPayableCallOptions; export type PayableTxOptions = PayableCallOptions; -export { ContractAbiWithSignature, EventLog, ContractOptions } from 'web3-types'; +export type { ContractAbiWithSignature, EventLog, ContractOptions } from 'web3-types'; export interface ContractEventOptions { /** @@ -177,6 +179,10 @@ export interface NonPayableMethodObject FormatType, SendTransactionEvents >; + populateTransaction( + tx?: PayableTxOptions | NonPayableTxOptions, + contractOptions?: ContractOptions, + ): TransactionCall; /** * Returns the amount of gas consumed by executing the method locally without creating a new transaction on the blockchain. @@ -375,6 +381,15 @@ export interface PayableMethodObject { SendTransactionEvents >; + /** + * + * @param tx + * @param contractOptions + */ + populateTransaction( + tx?: PayableTxOptions | NonPayableTxOptions, + contractOptions?: ContractOptions, + ): TransactionCall; /** * Returns the amount of gas consumed by executing the method locally without creating a new transaction on the blockchain. * The returned amount can be used as a gas estimate for executing the transaction publicly. The actual gas used can be diff --git a/packages/web3-eth-contract/test/unit/contract.test.ts b/packages/web3-eth-contract/test/unit/contract.test.ts index 8d5c0445fb2..449280c41a7 100644 --- a/packages/web3-eth-contract/test/unit/contract.test.ts +++ b/packages/web3-eth-contract/test/unit/contract.test.ts @@ -16,13 +16,20 @@ along with web3.js. If not, see . */ import * as eth from 'web3-eth'; -import { ValidChains, Hardfork, AccessListResult, Address, ETH_DATA_FORMAT , DEFAULT_RETURN_FORMAT } from 'web3-types'; +import { + ValidChains, + Hardfork, + AccessListResult, + Address, + ETH_DATA_FORMAT, + DEFAULT_RETURN_FORMAT, +} from 'web3-types'; import { Web3ContractError } from 'web3-errors'; -import { Web3Context , Web3ConfigEvent } from 'web3-core'; +import { Web3Context, Web3ConfigEvent } from 'web3-core'; import { Web3ValidatorError } from 'web3-validator'; import { AbiItem } from 'web3-utils'; import { stringify } from 'flatted'; -import {Abi} from '../fixtures/AbiItem' +import { Abi } from '../fixtures/AbiItem'; import { Contract } from '../../src'; import { sampleStorageContractABI } from '../fixtures/storage'; import { GreeterAbi, GreeterBytecode } from '../shared_fixtures/build/Greeter'; @@ -541,7 +548,7 @@ describe('Contract', () => { // calling with wrong parameters should throw try { // eslint-disable-next-line @typescript-eslint/no-unsafe-call - await(deployedContract.methods.setGreeting as any)(arg, 'test').send(sendOptions); + await (deployedContract.methods.setGreeting as any)(arg, 'test').send(sendOptions); expect(true).toBe(false); } catch (error) { // eslint-disable-next-line jest/no-conditional-expect @@ -555,7 +562,7 @@ describe('Contract', () => { // calling with wrong parameters should throw try { // eslint-disable-next-line @typescript-eslint/no-unsafe-call - await(deployedContract.methods.setGreeting as any)(arg, true, 'test').send( + await (deployedContract.methods.setGreeting as any)(arg, true, 'test').send( sendOptions, ); expect(true).toBe(false); @@ -1909,5 +1916,32 @@ describe('Contract', () => { const contract = new Contract(GreeterAbi, web3Context); expect(contract.config).toStrictEqual(web3Context.config); }); + + it('should populate method to tx object', () => { + const expectedProvider = 'http://127.0.0.1:8545'; + const web3Context = new Web3Context({ + provider: expectedProvider, + config: { handleRevert: true, defaultTransactionType: '0x2' }, + }); + const contract = new Contract( + GreeterAbi, + '0x00000000219ab540356cBB839Cbe05303d7705F1', + web3Context, + ); + + const tx = contract.methods + .greet() + .populateTransaction({ from: '0x00000000219ab540356cBB839Cbe05303d7705F2' }); + expect(tx).toEqual({ + to: '0x00000000219AB540356cBb839cbe05303D7705F1', + gas: undefined, + gasPrice: undefined, + from: '0x00000000219ab540356cBB839Cbe05303d7705F2', + input: undefined, + maxPriorityFeePerGas: undefined, + maxFeePerGas: undefined, + data: '0xcfae3217', + }); + }); }); }); diff --git a/packages/web3-types/src/eth_types.ts b/packages/web3-types/src/eth_types.ts index 5c628994c8d..9c83e92d0d5 100644 --- a/packages/web3-types/src/eth_types.ts +++ b/packages/web3-types/src/eth_types.ts @@ -47,6 +47,7 @@ export enum BlockTags { PENDING = 'pending', SAFE = 'safe', FINALIZED = 'finalized', + COMMITTED = 'committed', } export type BlockTag = `${BlockTags}`; @@ -138,8 +139,8 @@ export interface Withdrawals { } export interface BlockOutput { - readonly gasLimit: bigint | number; - readonly gasUsed: bigint | number; + readonly gasLimit: bigint | number; + readonly gasUsed: bigint | number; readonly size: bigint | number; readonly timestamp: bigint | number; readonly number?: bigint | number; @@ -152,54 +153,54 @@ export interface BlockOutput { // Added properties readonly blobGasUsed?: bigint | number; - readonly excessBlobGas?: bigint | number; - readonly extraData?: Bytes; - readonly hash?: HexString32Bytes; - readonly logsBloom?: Bytes; - readonly nonce?: bigint | number; - readonly parentBeaconBlockRoot?: HexString32Bytes; - readonly receiptsRoot?: HexString32Bytes; - readonly sha3Uncles: HexString32Bytes[]; - readonly stateRoot?: HexString32Bytes; - readonly transactionsRoot?: HexString32Bytes; - readonly withdrawalsRoot?: HexString32Bytes; - readonly mixHash?: HexString32Bytes; - readonly uncles?: Uncles; - readonly withdrawals?: Withdrawals[]; + readonly excessBlobGas?: bigint | number; + readonly extraData?: Bytes; + readonly hash?: HexString32Bytes; + readonly logsBloom?: Bytes; + readonly nonce?: bigint | number; + readonly parentBeaconBlockRoot?: HexString32Bytes; + readonly receiptsRoot?: HexString32Bytes; + readonly sha3Uncles: HexString32Bytes[]; + readonly stateRoot?: HexString32Bytes; + readonly transactionsRoot?: HexString32Bytes; + readonly withdrawalsRoot?: HexString32Bytes; + readonly mixHash?: HexString32Bytes; + readonly uncles?: Uncles; + readonly withdrawals?: Withdrawals[]; } export interface BlockHeaderOutput { - readonly baseFeePerGas?: Numbers; - readonly blobGasUsed?: Numbers; - readonly difficulty?: Numbers; - readonly excessBlobGas?: Numbers; - readonly extraData?: Bytes; - readonly gasLimit: Numbers; - readonly gasUsed: Numbers; - readonly hash?: HexString32Bytes; - readonly logsBloom?: Bytes; - readonly miner?: HexString; - readonly nonce?: Numbers; - readonly number?: Numbers; - readonly parentBeaconBlockRoot?: HexString32Bytes; - readonly parentHash?: HexString32Bytes; - readonly receiptsRoot?: HexString32Bytes; - readonly sha3Uncles: HexString32Bytes[]; - readonly stateRoot?: HexString32Bytes; - readonly timestamp: Numbers; - readonly transactionsRoot?: HexString32Bytes; - readonly withdrawalsRoot?: HexString32Bytes; - - // These fields are returned when the RPC client is Nethermind, - // but aren't available in other clients such as Geth - readonly author?: Address; - readonly totalDifficulty?: Numbers; - readonly size?: Numbers; - readonly excessDataGas?: Numbers; - readonly mixHash?: HexString32Bytes; - readonly transactions?: TransactionOutput[]; - readonly uncles?: Uncles; - readonly withdrawals?: Withdrawals[]; + readonly baseFeePerGas?: Numbers; + readonly blobGasUsed?: Numbers; + readonly difficulty?: Numbers; + readonly excessBlobGas?: Numbers; + readonly extraData?: Bytes; + readonly gasLimit: Numbers; + readonly gasUsed: Numbers; + readonly hash?: HexString32Bytes; + readonly logsBloom?: Bytes; + readonly miner?: HexString; + readonly nonce?: Numbers; + readonly number?: Numbers; + readonly parentBeaconBlockRoot?: HexString32Bytes; + readonly parentHash?: HexString32Bytes; + readonly receiptsRoot?: HexString32Bytes; + readonly sha3Uncles: HexString32Bytes[]; + readonly stateRoot?: HexString32Bytes; + readonly timestamp: Numbers; + readonly transactionsRoot?: HexString32Bytes; + readonly withdrawalsRoot?: HexString32Bytes; + + // These fields are returned when the RPC client is Nethermind, + // but aren't available in other clients such as Geth + readonly author?: Address; + readonly totalDifficulty?: Numbers; + readonly size?: Numbers; + readonly excessDataGas?: Numbers; + readonly mixHash?: HexString32Bytes; + readonly transactions?: TransactionOutput[]; + readonly uncles?: Uncles; + readonly withdrawals?: Withdrawals[]; } export interface ReceiptInput { @@ -553,13 +554,13 @@ export interface Eip712TypedData { /** * To contain the gas Fee Data to be used with EIP-1559 transactions. * EIP-1559 was applied to Ethereum after London hardfork. - * + * * Typically you will only need `maxFeePerGas` and `maxPriorityFeePerGas` for a transaction following EIP-1559. * However, if you want to get informed about the fees of last block, you can use `baseFeePerGas` too. - * - * + * + * * @see https://eips.ethereum.org/EIPS/eip-1559 - * + * */ export interface FeeData { /** @@ -569,20 +570,20 @@ export interface FeeData { /** * The baseFeePerGas returned from the last available block. - * + * * If EIP-1559 is not supported, this will be `undefined` - * - * However, the user will only pay (the future baseFeePerGas + the maxPriorityFeePerGas). + * + * However, the user will only pay (the future baseFeePerGas + the maxPriorityFeePerGas). * And this value is just for getting informed about the fees of last block. */ readonly baseFeePerGas?: Numbers; /** * The maximum fee that the user would be willing to pay per-gas. - * + * * However, the user will only pay (the future baseFeePerGas + the maxPriorityFeePerGas). * And the `maxFeePerGas` could be used to prevent paying more than it, if `baseFeePerGas` went too high. - * + * * If EIP-1559 is not supported, this will be `undefined` */ readonly maxFeePerGas?: Numbers; @@ -593,4 +594,4 @@ export interface FeeData { * If EIP-1559 is not supported, this will be `undefined` */ readonly maxPriorityFeePerGas?: Numbers; -} \ No newline at end of file +} diff --git a/packages/web3/CHANGELOG.md b/packages/web3/CHANGELOG.md index fb638a0d56b..d95a14cc116 100644 --- a/packages/web3/CHANGELOG.md +++ b/packages/web3/CHANGELOG.md @@ -387,4 +387,4 @@ Documentation: #### web3 -- `web3.eth.Contract` will get transaction middleware and use it, if `web3.eth` has transaction middleware. (#7138) \ No newline at end of file +- `web3.eth.Contract` will get transaction middleware and use it, if `web3.eth` has transaction middleware. (#7138) From 38fac0661968e609bf06249286897dcdf9e421a4 Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 8 Jul 2024 12:55:30 -0400 Subject: [PATCH 115/186] catch unhandled error when reconnecting with request queue (#7141) * remove todo * add erorr handling * add tests * fix lint * format * update changelog --------- Co-authored-by: Alex Luu --- packages/web3-utils/CHANGELOG.md | 16 +++++----- packages/web3-utils/src/event_emitter.ts | 6 ++-- packages/web3-utils/src/socket_provider.ts | 14 ++++++--- packages/web3-utils/src/validation.ts | 1 - .../web3-utils/test/fixtures/validation.ts | 15 +++------- .../test/unit/socket_provider.test.ts | 29 ++++++++++++++++++- .../web3-utils/test/unit/validation.test.ts | 22 ++++++-------- 7 files changed, 62 insertions(+), 41 deletions(-) diff --git a/packages/web3-utils/CHANGELOG.md b/packages/web3-utils/CHANGELOG.md index 5fcf44ccec5..20474ce0ab3 100644 --- a/packages/web3-utils/CHANGELOG.md +++ b/packages/web3-utils/CHANGELOG.md @@ -213,19 +213,21 @@ 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) ## [4.3.0] ### 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) +- `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) +- `toWei` support numbers in scientific notation (#6908) +- `toWei` and `fromWei` trims according to ether unit successfuly (#7044) -## [Unreleased] \ No newline at end of file +## [Unreleased] + +- `_sendPendingRequests` will catch unhandled errors from `_sendToSocket` (#6968) diff --git a/packages/web3-utils/src/event_emitter.ts b/packages/web3-utils/src/event_emitter.ts index bc7fee36f04..54a2610da28 100644 --- a/packages/web3-utils/src/event_emitter.ts +++ b/packages/web3-utils/src/event_emitter.ts @@ -16,8 +16,7 @@ along with web3.js. If not, see . */ /* eslint-disable max-classes-per-file */ -import EventEmitter3 from 'eventemitter3'; - +import EventEmitter3 from 'eventemitter3'; /** * This class copy the behavior of Node.js EventEmitter class. @@ -35,5 +34,4 @@ export class EventEmitter extends EventEmitter3 { public getMaxListeners(): number { return this.maxListeners; } - -} \ No newline at end of file +} diff --git a/packages/web3-utils/src/socket_provider.ts b/packages/web3-utils/src/socket_provider.ts index 0a73fb8378f..52154402ccd 100644 --- a/packages/web3-utils/src/socket_provider.ts +++ b/packages/web3-utils/src/socket_provider.ts @@ -426,7 +426,7 @@ export abstract class SocketProvider< this._reconnectAttempts += 1; setTimeout(() => { this._removeSocketListeners(); - this.connect(); + this.connect(); // this can error out this.isReconnecting = false; }, this._reconnectOptions.delay); } else { @@ -503,9 +503,15 @@ export abstract class SocketProvider< private _sendPendingRequests() { for (const [id, value] of this._pendingRequestsQueue.entries()) { - this._sendToSocket(value.payload as Web3APIPayload); - this._pendingRequestsQueue.delete(id); - this._sentRequestsQueue.set(id, value); + try { + this._sendToSocket(value.payload as Web3APIPayload); + this._pendingRequestsQueue.delete(id); + this._sentRequestsQueue.set(id, value); + } catch (error) { + // catches if sendTosocket fails + this._pendingRequestsQueue.delete(id); + this._eventEmitter.emit('error', error); + } } } diff --git a/packages/web3-utils/src/validation.ts b/packages/web3-utils/src/validation.ts index 76f1de97742..57e91aae76d 100644 --- a/packages/web3-utils/src/validation.ts +++ b/packages/web3-utils/src/validation.ts @@ -173,7 +173,6 @@ export const compareBlockNumbers = (blockA: BlockNumberOrTag, blockB: BlockNumbe return 1; }; - export const isContractInitOptions = (options: unknown): options is ContractInitOptions => typeof options === 'object' && !isNullishValidator(options) && diff --git a/packages/web3-utils/test/fixtures/validation.ts b/packages/web3-utils/test/fixtures/validation.ts index 3c216d3ff62..c170f5ed813 100644 --- a/packages/web3-utils/test/fixtures/validation.ts +++ b/packages/web3-utils/test/fixtures/validation.ts @@ -79,16 +79,9 @@ export const isBloomValidData: [any, true][] = [ ]; export const isContractInitValidData: ContractInitOptions[] = [ - {dataInputFill: "data"}, - {syncWithContext: true}, - {gas: "100000", - syncWithContext: true, - dataInputFill: "data", - }, + { dataInputFill: 'data' }, + { syncWithContext: true }, + { gas: '100000', syncWithContext: true, dataInputFill: 'data' }, ]; -export const isContractInitInvalidData: unknown[] = [ - "", - 12, - {} -]; \ No newline at end of file +export const isContractInitInvalidData: unknown[] = ['', 12, {}]; diff --git a/packages/web3-utils/test/unit/socket_provider.test.ts b/packages/web3-utils/test/unit/socket_provider.test.ts index c2c3756c755..19529f4181a 100644 --- a/packages/web3-utils/test/unit/socket_provider.test.ts +++ b/packages/web3-utils/test/unit/socket_provider.test.ts @@ -252,7 +252,6 @@ describe('SocketProvider', () => { expect(deleteSpy).toHaveBeenCalledTimes(sentRequestsQueueSize); }); }); - describe('testing connect() method', () => { it('should call method reconnect in case of error at _openSocketConnection', async () => { const provider = new TestProvider(socketPath, socketOption); @@ -496,6 +495,34 @@ describe('SocketProvider', () => { expect(deleteSpy).toHaveBeenCalled(); }); }); + describe('testing _onConnect() method', () => { + it('should catch error when succesfully connecting with _sendPendingRequests in queue and _sendToSocket throws', async () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + provider.setStatus('connecting'); + const payload1 = { id: 1, method: 'some_rpc_method' }; + const errorEventSpy = jest.fn(); + provider.on('error', errorEventSpy); + + // @ts-expect-error access protected method + provider._sendToSocket = () => { + throw new Error('any error'); + }; + provider + .request(payload1) + .then(() => { + // nothing + }) + .catch(() => { + // nothing + }); + // @ts-expect-error run protected method + provider._onConnect(); + + expect(errorEventSpy).toHaveBeenCalledWith(expect.any(Error)); + expect(provider.getPendingRequestQueueSize()).toBe(0); + expect(provider.getSentRequestsQueueSize()).toBe(0); + }); + }); describe('testing _clearQueues() method', () => { it('should clear queues when called', () => { diff --git a/packages/web3-utils/test/unit/validation.test.ts b/packages/web3-utils/test/unit/validation.test.ts index 9d087e3a2eb..1cbfb389466 100644 --- a/packages/web3-utils/test/unit/validation.test.ts +++ b/packages/web3-utils/test/unit/validation.test.ts @@ -23,7 +23,7 @@ import { compareBlockNumbersInvalidData, compareBlockNumbersValidData, isContractInitValidData, - isContractInitInvalidData + isContractInitInvalidData, } from '../fixtures/validation'; describe('validation', () => { @@ -40,19 +40,15 @@ describe('validation', () => { ); }); describe('isContractInit', () => { - describe('should return true', () => { - it.each([...isContractInitValidData])( - '%s', (input) => { - expect(isContractInitOptions(input)).toBe(true); - } - ) + describe('should return true', () => { + it.each([...isContractInitValidData])('%s', input => { + expect(isContractInitOptions(input)).toBe(true); + }); }); - describe('should return false', () => { - it.each([...isContractInitInvalidData])( - '%s', (input) => { - expect(isContractInitOptions(input)).toBe(false); - } - ) + describe('should return false', () => { + it.each([...isContractInitInvalidData])('%s', input => { + expect(isContractInitOptions(input)).toBe(false); + }); }); }); }); From 1436228817c7e6362e7a82b8f79ec3b2e9c99412 Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 8 Jul 2024 13:42:46 -0400 Subject: [PATCH 116/186] update canary node version (#7142) * update canary * test canary * update * Delete unfinished commit --------- Co-authored-by: Alex Luu --- .github/workflows/canary_release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/canary_release.yml b/.github/workflows/canary_release.yml index c208c943c1a..f7081481f8d 100644 --- a/.github/workflows/canary_release.yml +++ b/.github/workflows/canary_release.yml @@ -12,7 +12,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 18 cache: yarn registry-url: 'https://registry.npmjs.org' - run: yarn install --frozen-lockfile From 89711ab7f6a63d910848807ee77f0a91497aa897 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 9 Jul 2024 21:56:32 -0400 Subject: [PATCH 117/186] update http quicknode rpc-provider (#7102) * update http * update changelog * update web3-rpc-providers * update * update * update * update tests * remove quicknode errors * update imports * change return type of request * update changelog --------- Co-authored-by: Alex Luu --- packages/web3-providers-http/src/index.ts | 7 +++-- packages/web3-rpc-providers/CHANGELOG.md | 2 ++ packages/web3-rpc-providers/package.json | 2 ++ packages/web3-rpc-providers/src/errors.ts | 28 ++++++++++++++++++ .../web3-rpc-providers/src/web3_provider.ts | 20 +++++++++---- .../test/unit/request.test.ts | 29 +++++++++++++++++++ 6 files changed, 80 insertions(+), 8 deletions(-) create mode 100644 packages/web3-rpc-providers/src/errors.ts diff --git a/packages/web3-providers-http/src/index.ts b/packages/web3-providers-http/src/index.ts index 64dadd9895d..bd069dbc14c 100644 --- a/packages/web3-providers-http/src/index.ts +++ b/packages/web3-providers-http/src/index.ts @@ -78,9 +78,10 @@ export default class HttpProvider< }, body: JSON.stringify(payload), }); - - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - if (!response.ok) throw new ResponseError(await response.json()); + if (!response.ok) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + throw new ResponseError(await response.json()) + }; return (await response.json()) as JsonRpcResponseWithResult; } diff --git a/packages/web3-rpc-providers/CHANGELOG.md b/packages/web3-rpc-providers/CHANGELOG.md index 1909cc7a509..78d7c02f440 100644 --- a/packages/web3-rpc-providers/CHANGELOG.md +++ b/packages/web3-rpc-providers/CHANGELOG.md @@ -42,3 +42,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - RC release ## [Unreleased] + - When error is returned with code 429, throw rate limit error (#7102) + - Change request return type `Promise` to `Promise>` (#7102) \ No newline at end of file diff --git a/packages/web3-rpc-providers/package.json b/packages/web3-rpc-providers/package.json index 6904037773a..8aed22fe547 100644 --- a/packages/web3-rpc-providers/package.json +++ b/packages/web3-rpc-providers/package.json @@ -56,8 +56,10 @@ "typescript": "^4.7.4" }, "dependencies": { + "web3-errors": "^1.2.0", "web3-providers-http": "^4.1.0", "web3-providers-ws": "^4.0.7", + "web3-validator": "^2.0.6", "web3-types": "^1.7.0", "web3-utils": "^4.3.0" } diff --git a/packages/web3-rpc-providers/src/errors.ts b/packages/web3-rpc-providers/src/errors.ts new file mode 100644 index 00000000000..dd602fcb05f --- /dev/null +++ b/packages/web3-rpc-providers/src/errors.ts @@ -0,0 +1,28 @@ +/* +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 { BaseWeb3Error } from 'web3-errors'; +import { } from 'web3-types'; + +const ERR_QUICK_NODE_RATE_LIMIT = 1300; +export class QuickNodeRateLimitError extends BaseWeb3Error { + public code = ERR_QUICK_NODE_RATE_LIMIT; + + public constructor() { + super(`Too many requests, Quicknode has reached its rate limit.`); + } +} \ No newline at end of file diff --git a/packages/web3-rpc-providers/src/web3_provider.ts b/packages/web3-rpc-providers/src/web3_provider.ts index 2bba9a7b880..a00034048ef 100644 --- a/packages/web3-rpc-providers/src/web3_provider.ts +++ b/packages/web3-rpc-providers/src/web3_provider.ts @@ -17,16 +17,19 @@ along with web3.js. If not, see . import HttpProvider from "web3-providers-http"; import WebSocketProvider from "web3-providers-ws"; +import { isNullish } from "web3-validator"; import { EthExecutionAPI, JsonRpcResult, ProviderConnectInfo, ProviderMessage, ProviderRpcError, Web3APIMethod, Web3APIPayload, Web3APIReturnType, Web3APISpec, Web3BaseProvider, Web3Eip1193ProviderEventCallback, Web3ProviderEventCallback, Web3ProviderMessageEventCallback, - Web3ProviderStatus + Web3ProviderStatus, + JsonRpcResponseWithResult, } from "web3-types"; import { Eip1193Provider } from "web3-utils"; import { Transport, Network } from "./types.js"; +import { QuickNodeRateLimitError } from './errors.js'; /* This class can be used to create new providers only when there is custom logic required in each Request method like @@ -68,13 +71,20 @@ API extends Web3APISpec = EthExecutionAPI, >( payload: Web3APIPayload, requestOptions?: RequestInit, - ): Promise { + ): Promise> { if (this.transport === Transport.HTTPS) { - return ( (this.provider as HttpProvider).request(payload, requestOptions)) as unknown as Promise; - } + const res = await ( (this.provider as HttpProvider).request(payload, requestOptions)) as unknown as JsonRpcResponseWithResult; + + if (typeof res === 'object' && !isNullish(res) && 'error' in res && !isNullish(res.error) && 'code' in res.error && (res.error as { code: number }).code === 429){ + // rate limiting error by quicknode; + throw new QuickNodeRateLimitError(); + + } + return res; + } - return ( (this.provider as WebSocketProvider).request(payload)) as unknown as Promise; + return (this.provider as WebSocketProvider).request(payload); } diff --git a/packages/web3-rpc-providers/test/unit/request.test.ts b/packages/web3-rpc-providers/test/unit/request.test.ts index ccbaa0f7cc7..d0d38ac5e14 100644 --- a/packages/web3-rpc-providers/test/unit/request.test.ts +++ b/packages/web3-rpc-providers/test/unit/request.test.ts @@ -17,6 +17,7 @@ along with web3.js. If not, see . import { Web3APIPayload, EthExecutionAPI, Web3APIMethod } from "web3-types"; import { Network, Transport } from "../../src/types"; import { Web3ExternalProvider } from "../../src/web3_provider"; +import { QuickNodeRateLimitError } from '../../src/errors'; jest.mock('web3-providers-ws', () => { return { @@ -78,4 +79,32 @@ describe('Web3ExternalProvider', () => { const result = await provider.request(payload); expect(result).toEqual({ result: 'mock-result' }); }); + it('should return a rate limiting error when code is 429', async () => { + const network: Network = Network.ETH_MAINNET; + const transport: Transport = Transport.HTTPS; + const token = 'your-token'; + + const mockHttpProvider = { + request: jest.fn(), + }; + + const mockResponse = { + jsonrpc: '2.0', + id: '458408f4-7e2c-43f1-b61d-1fe09a9ee25a', + error: { + code: 429, + message: 'the method eth_stuff does not exist/is not available' + } + }; + mockHttpProvider.request.mockResolvedValue(mockResponse); + + const provider = new MockWeb3ExternalProvider(network, transport, token); + (provider as any).provider = mockHttpProvider; + + const payload: Web3APIPayload> = { + method: 'eth_getBalance', + params: ['0x0123456789012345678901234567890123456789', 'latest'], + }; + await expect(provider.request(payload)).rejects.toThrow(QuickNodeRateLimitError); + }); }); \ No newline at end of file From 463d070a574a6e09e8c3319bd54fadfd8518d847 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 11 Jul 2024 14:14:33 -0400 Subject: [PATCH 118/186] Release/4.11.0 (#7145) --- .github/workflows/black_box_tests.yml | 4 +- .github/workflows/e2e_network_tests.yml | 4 +- CHANGELOG.md | 51 ++++++++++++++++++++++++ packages/web3-eth-abi/CHANGELOG.md | 6 +++ packages/web3-eth-abi/package.json | 6 +-- packages/web3-eth-accounts/CHANGELOG.md | 6 +++ packages/web3-eth-accounts/package.json | 10 ++--- packages/web3-eth-contract/CHANGELOG.md | 6 ++- packages/web3-eth-contract/package.json | 16 ++++---- packages/web3-eth/CHANGELOG.md | 6 ++- packages/web3-eth/package.json | 10 ++--- packages/web3-providers-ws/CHANGELOG.md | 7 +++- packages/web3-providers-ws/package.json | 8 ++-- packages/web3-rpc-providers/CHANGELOG.md | 14 +++++-- packages/web3-rpc-providers/package.json | 8 ++-- packages/web3-utils/CHANGELOG.md | 6 ++- packages/web3-utils/package.json | 4 +- packages/web3/CHANGELOG.md | 34 +++++++++++++++- packages/web3/package.json | 16 ++++---- packages/web3/src/version.ts | 2 +- tools/web3-plugin-example/CHANGELOG.md | 6 +++ tools/web3-plugin-example/package.json | 10 ++--- 22 files changed, 181 insertions(+), 59 deletions(-) diff --git a/.github/workflows/black_box_tests.yml b/.github/workflows/black_box_tests.yml index 0d87844cb6b..19c84cee6dd 100644 --- a/.github/workflows/black_box_tests.yml +++ b/.github/workflows/black_box_tests.yml @@ -10,7 +10,7 @@ jobs: build: strategy: matrix: - node: [18, 16] + node: [18] name: Build Packages runs-on: ubuntu-latest steps: @@ -36,7 +36,7 @@ jobs: strategy: fail-fast: false matrix: - node: [18, 16] + node: [18] mode: ['http', 'ws'] backend: ['geth', 'infura'] steps: diff --git a/.github/workflows/e2e_network_tests.yml b/.github/workflows/e2e_network_tests.yml index 58adb0ee4bf..508c45caee9 100644 --- a/.github/workflows/e2e_network_tests.yml +++ b/.github/workflows/e2e_network_tests.yml @@ -14,7 +14,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 18 cache: yarn - run: yarn - run: tar -czf /tmp/web3-16.js.tar.gz --exclude="./.git" ./ @@ -41,7 +41,7 @@ jobs: steps: - uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 18 - uses: actions/download-artifact@v3 with: name: web3-16.js.tar.gz diff --git a/CHANGELOG.md b/CHANGELOG.md index 8eba8930d2b..774e4cb4f40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2581,3 +2581,54 @@ If there are any bugs, improvements, optimizations or any new feature proposal f - `populateTransaction` was added to contract methods (#7124) - Contract has `setTransactionMiddleware` and `getTransactionMiddleware` for automatically passing to `sentTransaction` for `deploy` and `send` functions (#7138) + +## [4.11.0] + +### Fixed + +#### web3-eth-abi + +- fix encodedata in EIP-712 (#7095) + +#### web3-utils + +- `_sendPendingRequests` will catch unhandled errors from `_sendToSocket` (#6968) + +#### web3-eth + +- Fixed geth issue when running a new instance, transactions will index when there are no blocks created (#7098) + +### Changed + +#### web3-eth-accounts + +- baseTransaction method updated (#7095) + +#### web3-providers-ws + +- Update dependancies (#7109) + +#### web3-plugin-example + +- Dependencies updated + +#### web3-rpc-providers + + - Change request return type `Promise` to `Promise>` (#7102) + +### Added + +#### web3-eth-contract + +- `populateTransaction` was added to contract methods (#7124) +- Contract has `setTransactionMiddleware` and `getTransactionMiddleware` for automatically passing to `sentTransaction` for `deploy` and `send` functions (#7138) + +#### web3-rpc-providers + + - When error is returned with code 429, throw rate limit error (#7102) + +#### web3 + +- `web3.eth.Contract` will get transaction middleware and use it, if `web3.eth` has transaction middleware. (#7138) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-eth-abi/CHANGELOG.md b/packages/web3-eth-abi/CHANGELOG.md index 4a7f1fe8add..6d04047ddef 100644 --- a/packages/web3-eth-abi/CHANGELOG.md +++ b/packages/web3-eth-abi/CHANGELOG.md @@ -176,4 +176,10 @@ Documentation: - Dependencies updated +## [4.2.3] + +### Fixed + +- fix encodedata in EIP-712 (#7095) + ## [Unreleased] \ No newline at end of file diff --git a/packages/web3-eth-abi/package.json b/packages/web3-eth-abi/package.json index 4333ba616bb..7431abf8f23 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.2", + "version": "4.2.3", "description": "Web3 module encode and decode EVM in/output.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -44,8 +44,8 @@ "dependencies": { "abitype": "0.7.1", "web3-errors": "^1.2.0", - "web3-types": "^1.6.0", - "web3-utils": "^4.3.0", + "web3-types": "^1.7.0", + "web3-utils": "^4.3.1", "web3-validator": "^2.0.6" }, "devDependencies": { diff --git a/packages/web3-eth-accounts/CHANGELOG.md b/packages/web3-eth-accounts/CHANGELOG.md index 30514ec972d..2b5d1c1ca6a 100644 --- a/packages/web3-eth-accounts/CHANGELOG.md +++ b/packages/web3-eth-accounts/CHANGELOG.md @@ -162,4 +162,10 @@ Documentation: - Dependencies updated +## [4.1.3] + +### Changed + +- baseTransaction method updated (#7095) + ## [Unreleased] \ No newline at end of file diff --git a/packages/web3-eth-accounts/package.json b/packages/web3-eth-accounts/package.json index dbd0a9fc881..aa25f89a5dd 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.2", + "version": "4.1.3", "description": "Package for managing Ethereum accounts and signing", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -61,9 +61,9 @@ "@ethereumjs/rlp": "^4.0.1", "crc-32": "^1.2.2", "ethereum-cryptography": "^2.0.0", - "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.1", + "web3-validator": "^2.0.6" } } diff --git a/packages/web3-eth-contract/CHANGELOG.md b/packages/web3-eth-contract/CHANGELOG.md index a1c4b6f35e5..bab02912320 100644 --- a/packages/web3-eth-contract/CHANGELOG.md +++ b/packages/web3-eth-contract/CHANGELOG.md @@ -386,10 +386,12 @@ Documentation: - `defaultReturnFormat` was added to all methods that have `ReturnType` param. (#6947) -## [Unreleased] +## [4.6.0] ### Added - `populateTransaction` was added to contract methods (#7124) - - Contract has `setTransactionMiddleware` and `getTransactionMiddleware` for automatically passing to `sentTransaction` for `deploy` and `send` functions (#7138) + +## [Unreleased] + diff --git a/packages/web3-eth-contract/package.json b/packages/web3-eth-contract/package.json index 81a3a9f2a3a..dcee58738b4 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.5.0", + "version": "4.6.0", "description": "Web3 module to interact with Ethereum smart contracts.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -46,12 +46,12 @@ }, "dependencies": { "@ethereumjs/rlp": "^5.0.2", - "web3-core": "^4.4.0", + "web3-core": "^4.5.0", "web3-errors": "^1.2.0", - "web3-eth": "^4.7.0", - "web3-eth-abi": "^4.2.2", - "web3-types": "^1.6.0", - "web3-utils": "^4.3.0", + "web3-eth": "^4.8.1", + "web3-eth-abi": "^4.2.3", + "web3-types": "^1.7.0", + "web3-utils": "^4.3.1", "web3-validator": "^2.0.6" }, "devDependencies": { @@ -69,7 +69,7 @@ "prettier": "^2.7.1", "ts-jest": "^29.1.1", "typescript": "^4.7.4", - "web3-eth-accounts": "^4.1.2", - "web3-providers-ws": "^4.0.7" + "web3-eth-accounts": "^4.1.3", + "web3-providers-ws": "^4.0.8" } } diff --git a/packages/web3-eth/CHANGELOG.md b/packages/web3-eth/CHANGELOG.md index ba620044bde..f098725ad14 100644 --- a/packages/web3-eth/CHANGELOG.md +++ b/packages/web3-eth/CHANGELOG.md @@ -256,8 +256,10 @@ Documentation: - WebEth has `setTransactionMiddleware` and `getTransactionMiddleware` for automatically passing to `sentTransaction` (#7088) - `TransactionMiddleware` and `TransactionMiddleware` data types are exported (#7088) -## [Unreleased] +## [4.8.1] ### Fixed -- Fixed geth issue when running a new instance, transactions will index when there are no blocks created (#7098) \ No newline at end of file +- Fixed geth issue when running a new instance, transactions will index when there are no blocks created (#7098) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-eth/package.json b/packages/web3-eth/package.json index 336ed74df1e..2de8e03264f 100644 --- a/packages/web3-eth/package.json +++ b/packages/web3-eth/package.json @@ -1,6 +1,6 @@ { "name": "web3-eth", - "version": "4.8.0", + "version": "4.8.1", "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.5.0", "web3-errors": "^1.2.0", - "web3-eth-abi": "^4.2.2", - "web3-eth-accounts": "^4.1.2", + "web3-eth-abi": "^4.2.3", + "web3-eth-accounts": "^4.1.3", "web3-net": "^4.1.0", - "web3-providers-ws": "^4.0.7", + "web3-providers-ws": "^4.0.8", "web3-rpc-methods": "^1.3.0", "web3-types": "^1.7.0", - "web3-utils": "^4.3.0", + "web3-utils": "^4.3.1", "web3-validator": "^2.0.6" } } diff --git a/packages/web3-providers-ws/CHANGELOG.md b/packages/web3-providers-ws/CHANGELOG.md index 8648c09c9d3..3dbc8c54694 100644 --- a/packages/web3-providers-ws/CHANGELOG.md +++ b/packages/web3-providers-ws/CHANGELOG.md @@ -122,11 +122,16 @@ Documentation: - Dependencies updated - ## [4.0.7] ### Fixed - Fixed bug in chunks processing logic (#6496) +## [4.0.8] + +### Changed + +- Update dependancies (#7109) + ## [Unreleased] \ No newline at end of file diff --git a/packages/web3-providers-ws/package.json b/packages/web3-providers-ws/package.json index 41a37fba435..49595cc21df 100644 --- a/packages/web3-providers-ws/package.json +++ b/packages/web3-providers-ws/package.json @@ -1,6 +1,6 @@ { "name": "web3-providers-ws", - "version": "4.0.7", + "version": "4.0.8", "description": "Websocket provider for Web3 4.x.x", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -64,9 +64,9 @@ "dependencies": { "@types/ws": "8.5.3", "isomorphic-ws": "^5.0.0", - "web3-errors": "^1.1.3", - "web3-types": "^1.3.0", - "web3-utils": "^4.0.7", + "web3-errors": "^1.2.0", + "web3-types": "^1.7.0", + "web3-utils": "^4.3.1", "ws": "^8.17.1" } } diff --git a/packages/web3-rpc-providers/CHANGELOG.md b/packages/web3-rpc-providers/CHANGELOG.md index 78d7c02f440..d9fe3235240 100644 --- a/packages/web3-rpc-providers/CHANGELOG.md +++ b/packages/web3-rpc-providers/CHANGELOG.md @@ -37,10 +37,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [1.0.0.rc.0] -#### Added +### Added - RC release -## [Unreleased] +## [1.0.0.rc.1] + + ### Added + - When error is returned with code 429, throw rate limit error (#7102) - - Change request return type `Promise` to `Promise>` (#7102) \ No newline at end of file + + ### Changed + + - Change request return type `Promise` to `Promise>` (#7102) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-rpc-providers/package.json b/packages/web3-rpc-providers/package.json index 8aed22fe547..606ced0ed22 100644 --- a/packages/web3-rpc-providers/package.json +++ b/packages/web3-rpc-providers/package.json @@ -1,6 +1,6 @@ { "name": "web3-rpc-providers", - "version": "1.0.0-rc.0", + "version": "1.0.0-rc.1", "description": "Web3 Providers package", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -58,9 +58,9 @@ "dependencies": { "web3-errors": "^1.2.0", "web3-providers-http": "^4.1.0", - "web3-providers-ws": "^4.0.7", - "web3-validator": "^2.0.6", + "web3-providers-ws": "^4.0.8", "web3-types": "^1.7.0", - "web3-utils": "^4.3.0" + "web3-utils": "^4.3.1", + "web3-validator": "^2.0.6" } } diff --git a/packages/web3-utils/CHANGELOG.md b/packages/web3-utils/CHANGELOG.md index 20474ce0ab3..8f25c4c6b20 100644 --- a/packages/web3-utils/CHANGELOG.md +++ b/packages/web3-utils/CHANGELOG.md @@ -228,6 +228,10 @@ Documentation: - `toWei` support numbers in scientific notation (#6908) - `toWei` and `fromWei` trims according to ether unit successfuly (#7044) -## [Unreleased] +## [4.3.1] + +### Fixed - `_sendPendingRequests` will catch unhandled errors from `_sendToSocket` (#6968) + +## [Unreleased] diff --git a/packages/web3-utils/package.json b/packages/web3-utils/package.json index c07e9b85821..c9c6c6a4ad8 100644 --- a/packages/web3-utils/package.json +++ b/packages/web3-utils/package.json @@ -1,7 +1,7 @@ { "name": "web3-utils", "sideEffects": false, - "version": "4.3.0", + "version": "4.3.1", "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.2.0", - "web3-types": "^1.6.0", + "web3-types": "^1.7.0", "web3-validator": "^2.0.6" } } diff --git a/packages/web3/CHANGELOG.md b/packages/web3/CHANGELOG.md index d95a14cc116..a4585474629 100644 --- a/packages/web3/CHANGELOG.md +++ b/packages/web3/CHANGELOG.md @@ -381,10 +381,42 @@ Documentation: - `getName` reverse resolution -## [Unreleased] + +## [4.11.0] + +### Fixed + +#### web3-eth-abi + +- fix encodedata in EIP-712 (#7095) + +#### web3-utils + +- `_sendPendingRequests` will catch unhandled errors from `_sendToSocket` (#6968) + +#### web3-eth + +- Fixed geth issue when running a new instance, transactions will index when there are no blocks created (#7098) + +### Changed + +#### web3-eth-accounts + +- baseTransaction method updated (#7095) + +#### web3-providers-ws + +- Update dependancies (#7109) ### Added +#### web3-eth-contract + +- `populateTransaction` was added to contract methods (#7124) +- Contract has `setTransactionMiddleware` and `getTransactionMiddleware` for automatically passing to `sentTransaction` for `deploy` and `send` functions (#7138) + #### web3 - `web3.eth.Contract` will get transaction middleware and use it, if `web3.eth` has transaction middleware. (#7138) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3/package.json b/packages/web3/package.json index 5d05fa85923..952b99a7d76 100644 --- a/packages/web3/package.json +++ b/packages/web3/package.json @@ -1,6 +1,6 @@ { "name": "web3", - "version": "4.10.0", + "version": "4.11.0", "description": "Ethereum JavaScript API", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -88,20 +88,20 @@ "dependencies": { "web3-core": "^4.5.0", "web3-errors": "^1.2.0", - "web3-eth": "^4.8.0", - "web3-eth-abi": "^4.2.2", - "web3-eth-accounts": "^4.1.2", - "web3-eth-contract": "^4.5.0", + "web3-eth": "^4.8.1", + "web3-eth-abi": "^4.2.3", + "web3-eth-accounts": "^4.1.3", + "web3-eth-contract": "^4.6.0", "web3-eth-ens": "^4.4.0", "web3-eth-iban": "^4.0.7", "web3-eth-personal": "^4.0.8", "web3-net": "^4.1.0", "web3-providers-http": "^4.1.0", - "web3-providers-ws": "^4.0.7", + "web3-providers-ws": "^4.0.8", "web3-rpc-methods": "^1.3.0", - "web3-rpc-providers": "^1.0.0-rc.0", + "web3-rpc-providers": "^1.0.0-rc.1", "web3-types": "^1.7.0", - "web3-utils": "^4.3.0", + "web3-utils": "^4.3.1", "web3-validator": "^2.0.6" } } diff --git a/packages/web3/src/version.ts b/packages/web3/src/version.ts index 8b07e0d3591..86a46d17625 100644 --- a/packages/web3/src/version.ts +++ b/packages/web3/src/version.ts @@ -1 +1 @@ -/* eslint-disable header/header */ export const Web3PkgInfo = { version: '4.10.0' }; +/* eslint-disable header/header */ export const Web3PkgInfo = { version: '4.11.0' }; diff --git a/tools/web3-plugin-example/CHANGELOG.md b/tools/web3-plugin-example/CHANGELOG.md index 6762e7f8b1b..76e9b8f8b96 100644 --- a/tools/web3-plugin-example/CHANGELOG.md +++ b/tools/web3-plugin-example/CHANGELOG.md @@ -92,4 +92,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 Transaction middleware (#7088) +## [1.1.1] + +### Changed + +- Dependencies updated + ## [Unreleased] \ No newline at end of file diff --git a/tools/web3-plugin-example/package.json b/tools/web3-plugin-example/package.json index c2463255ac8..b44886d5f37 100644 --- a/tools/web3-plugin-example/package.json +++ b/tools/web3-plugin-example/package.json @@ -1,6 +1,6 @@ { "name": "web3-plugin-example", - "version": "1.1.0", + "version": "1.1.1", "description": "Example implementations of Web3.js' 4.x plugin system", "repository": "https://github.com/ChainSafe/web3.js", "engines": { @@ -45,12 +45,12 @@ "prettier": "^2.7.1", "ts-jest": "^29.1.1", "typescript": "^4.7.4", - "web3": "^4.10.0", + "web3": "^4.11.0", "web3-core": "^4.5.0", - "web3-eth-abi": "^4.2.2", - "web3-eth-contract": "^4.5.0", + "web3-eth-abi": "^4.2.3", + "web3-eth-contract": "^4.6.0", "web3-types": "^1.7.0", - "web3-utils": "^4.3.0" + "web3-utils": "^4.3.1" }, "peerDependencies": { "web3-core": ">= 4.1.1 < 5", From 6b80cf0f00fba190eda18ab5c96ee0b110680da7 Mon Sep 17 00:00:00 2001 From: Junaid <86780488+jdevcs@users.noreply.github.com> Date: Fri, 12 Jul 2024 17:01:47 +0200 Subject: [PATCH 119/186] fix(web3-errors): the undefined data in Eip838ExecutionError (#6905) (#7147) * fix(web3-errors): the undefined data in Eip838ExecutionError (#6905) * fix(web3-errors): handle the undefined data in Eip838ExecutionError constructor(#6433) * doc: update changelog * Update CHANGELOG.md * Update CHANGELOG.md --------- Co-authored-by: Muhammad Altabba <24407834+Muhammad-Altabba@users.noreply.github.com> Co-authored-by: Junaid <86780488+jdevcs@users.noreply.github.com> * changelog update --------- Co-authored-by: Xu Jianxiang Co-authored-by: Muhammad Altabba <24407834+Muhammad-Altabba@users.noreply.github.com> Co-authored-by: Oleksii Kosynskyi --- packages/web3-errors/CHANGELOG.md | 6 +++++- packages/web3-errors/src/errors/contract_errors.ts | 2 +- .../test/unit/__snapshots__/errors.test.ts.snap | 11 +++++++++++ packages/web3-errors/test/unit/errors.test.ts | 7 +++++++ 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/packages/web3-errors/CHANGELOG.md b/packages/web3-errors/CHANGELOG.md index 7f9b132283b..25ae481c3df 100644 --- a/packages/web3-errors/CHANGELOG.md +++ b/packages/web3-errors/CHANGELOG.md @@ -172,4 +172,8 @@ Documentation: - Added `InvalidIntegerError` error for fromWei and toWei (#7052) -## [Unreleased] \ No newline at end of file +## [Unreleased] + +### Fixed + +- Fixed the undefined data in `Eip838ExecutionError` constructor (#6905) \ No newline at end of file diff --git a/packages/web3-errors/src/errors/contract_errors.ts b/packages/web3-errors/src/errors/contract_errors.ts index 3710d9f60f0..ccd2b7dd46a 100644 --- a/packages/web3-errors/src/errors/contract_errors.ts +++ b/packages/web3-errors/src/errors/contract_errors.ts @@ -159,7 +159,7 @@ export class Eip838ExecutionError extends Web3ContractError { // error.data, error.data.data or error.data.originalError.data (https://github.com/web3/web3.js/issues/4454#issuecomment-1485953455) if (typeof error.data === 'object') { let originalError: { data: string }; - if ('originalError' in error.data) { + if (error.data && 'originalError' in error.data) { originalError = error.data.originalError; } else { // Ganache has no `originalError` sub-object unlike others diff --git a/packages/web3-errors/test/unit/__snapshots__/errors.test.ts.snap b/packages/web3-errors/test/unit/__snapshots__/errors.test.ts.snap index 2eefbaa0814..22a863812e8 100644 --- a/packages/web3-errors/test/unit/__snapshots__/errors.test.ts.snap +++ b/packages/web3-errors/test/unit/__snapshots__/errors.test.ts.snap @@ -156,6 +156,17 @@ exports[`errors Eip838ExecutionError should get the data from error.data.origina } `; +exports[`errors Eip838ExecutionError should return correctly when data is undefined 1`] = ` +{ + "cause": undefined, + "code": undefined, + "data": undefined, + "innerError": undefined, + "message": "Error", + "name": "Eip838ExecutionError", +} +`; + exports[`errors InvalidConnectionError should have valid json structure 1`] = ` { "cause": undefined, diff --git a/packages/web3-errors/test/unit/errors.test.ts b/packages/web3-errors/test/unit/errors.test.ts index 7428cc9b6b3..0731f4dff37 100644 --- a/packages/web3-errors/test/unit/errors.test.ts +++ b/packages/web3-errors/test/unit/errors.test.ts @@ -329,6 +329,13 @@ describe('errors', () => { } as JsonRpcError).toJSON(), ).toMatchSnapshot(); }); + it('should return correctly when data is undefined', () => { + expect( + new contractErrors.Eip838ExecutionError({ + data: undefined, + } as JsonRpcError).toJSON(), + ).toMatchSnapshot(); + }); }); describe('ResponseError', () => { From 9afaa613ee8792690032c6321acf74c32917732a Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 15 Jul 2024 22:54:38 -0400 Subject: [PATCH 120/186] Fix getblock.transactions (#7151) * add default array to block.transactions * update * update --- packages/web3-eth/CHANGELOG.md | 6 +++- packages/web3-eth/src/rpc_method_wrappers.ts | 12 +++++++- .../rpc_method_wrappers/fixtures/get_block.ts | 4 +++ .../rpc_method_wrappers/get_block.test.ts | 29 ++++++++++++++++++- 4 files changed, 48 insertions(+), 3 deletions(-) diff --git a/packages/web3-eth/CHANGELOG.md b/packages/web3-eth/CHANGELOG.md index f098725ad14..417db4d0837 100644 --- a/packages/web3-eth/CHANGELOG.md +++ b/packages/web3-eth/CHANGELOG.md @@ -262,4 +262,8 @@ Documentation: - Fixed geth issue when running a new instance, transactions will index when there are no blocks created (#7098) -## [Unreleased] \ No newline at end of file +## [Unreleased] + +### Fixed + +- Adds transaction property to be an empty list rather than undefined when no transactions are included in the block (#7151) \ No newline at end of file diff --git a/packages/web3-eth/src/rpc_method_wrappers.ts b/packages/web3-eth/src/rpc_method_wrappers.ts index 3a03afe0967..8195eb58caa 100644 --- a/packages/web3-eth/src/rpc_method_wrappers.ts +++ b/packages/web3-eth/src/rpc_method_wrappers.ts @@ -286,11 +286,21 @@ export async function getBlock( hydrated, ); } - return format( + const res = format( blockSchema, response as unknown as Block, returnFormat ?? web3Context.defaultReturnFormat, ); + + if (!isNullish(res)) { + const result = { + ...res, + transactions: res.transactions ?? [], + } + return result; + } + + return res; } /** diff --git a/packages/web3-eth/test/unit/rpc_method_wrappers/fixtures/get_block.ts b/packages/web3-eth/test/unit/rpc_method_wrappers/fixtures/get_block.ts index 4474bec4972..250f770bd64 100644 --- a/packages/web3-eth/test/unit/rpc_method_wrappers/fixtures/get_block.ts +++ b/packages/web3-eth/test/unit/rpc_method_wrappers/fixtures/get_block.ts @@ -70,6 +70,10 @@ export const mockRpcResponseHydrated: Block = { ...mockRpcResponse, transactions: [hydratedTransaction, hydratedTransaction, hydratedTransaction], }; +export const noTransactionBlock: Block = { + ...mockRpcResponse, + transactions: [], +} /** * Array consists of: diff --git a/packages/web3-eth/test/unit/rpc_method_wrappers/get_block.test.ts b/packages/web3-eth/test/unit/rpc_method_wrappers/get_block.test.ts index 778c6d4d000..365fb09d9ec 100644 --- a/packages/web3-eth/test/unit/rpc_method_wrappers/get_block.test.ts +++ b/packages/web3-eth/test/unit/rpc_method_wrappers/get_block.test.ts @@ -28,7 +28,7 @@ import { isBytes, isNullish } from 'web3-validator'; import { ethRpcMethods } from 'web3-rpc-methods'; import { getBlock } from '../../../src/rpc_method_wrappers'; -import { mockRpcResponse, mockRpcResponseHydrated, testData } from './fixtures/get_block'; +import { mockRpcResponse, mockRpcResponseHydrated, testData, noTransactionBlock } from './fixtures/get_block'; import { blockSchema } from '../../../src/schemas'; jest.mock('web3-rpc-methods'); @@ -84,4 +84,31 @@ describe('getBlock', () => { expect(result).toStrictEqual(expectedFormattedResult); }, ); + + it.each(testData)( + `should format the block to include transactions as an empty array if no transactions are present\nTitle: %s\nInput parameters: %s\n`, + async (_, inputParameters) => { + const [inputBlock] = inputParameters; + const expectedReturnFormat = { number: FMT_NUMBER.STR, bytes: FMT_BYTES.UINT8ARRAY }; + const expectedMockRpcResponse = noTransactionBlock; + // TODO: Fix format to default have a default in oneOf if no schema is matched + const formattedResult = format( + blockSchema, + expectedMockRpcResponse, + expectedReturnFormat, + ); + const expectedFormattedResult = {...formattedResult, + transactions: [] + }; + const inputBlockIsBytes = isBytes(inputBlock as Bytes); + ( + (inputBlockIsBytes + ? ethRpcMethods.getBlockByHash + : ethRpcMethods.getBlockByNumber) as jest.Mock + ).mockResolvedValueOnce(expectedMockRpcResponse); + + const result = await getBlock(web3Context, ...inputParameters, expectedReturnFormat); + expect(result).toStrictEqual(expectedFormattedResult); + }, + ); }); From 5ad7e5bad7c7d2e1794f0ff5024897f3eaddff4c Mon Sep 17 00:00:00 2001 From: Santiago Trujillo Zuluaga Date: Wed, 17 Jul 2024 07:10:18 +0300 Subject: [PATCH 121/186] Tx Types and ERC20 token transaction (#7156) * added tx types and erc20 tx * reordered files * Update docs/docs/guides/wallet/tx-types.md Co-authored-by: Dan Forbes * Update docs/docs/guides/wallet/tx-types.md Co-authored-by: Dan Forbes * Update docs/docs/guides/wallet/tx-types.md Co-authored-by: Dan Forbes * Update docs/docs/guides/wallet/tx-types.md Co-authored-by: Dan Forbes * Update docs/docs/guides/wallet/tx-types.md Co-authored-by: Dan Forbes * Update docs/docs/guides/wallet/tx-types.md Co-authored-by: Dan Forbes * Update docs/docs/guides/wallet/tx-types.md Co-authored-by: Alex * Update docs/docs/guides/wallet/tx-types.md Co-authored-by: Alex --------- Co-authored-by: Dan Forbes Co-authored-by: Alex --- docs/docs/guides/wallet/metamask-react.md | 2 +- docs/docs/guides/wallet/metamask-vanilla.md | 2 +- docs/docs/guides/wallet/tx-types.md | 280 ++++++++++++++++++ .../wallet/web3_modal_guide/_category_.yml | 2 +- 4 files changed, 283 insertions(+), 3 deletions(-) create mode 100644 docs/docs/guides/wallet/tx-types.md diff --git a/docs/docs/guides/wallet/metamask-react.md b/docs/docs/guides/wallet/metamask-react.md index c8c9a3604ae..8cdd7c70ba8 100644 --- a/docs/docs/guides/wallet/metamask-react.md +++ b/docs/docs/guides/wallet/metamask-react.md @@ -1,5 +1,5 @@ --- -sidebar_position: 4 +sidebar_position: 5 sidebar_label: 'Tutorial: Connecting to Metamask with React' --- diff --git a/docs/docs/guides/wallet/metamask-vanilla.md b/docs/docs/guides/wallet/metamask-vanilla.md index da930b07fad..ef55e9bcf8c 100644 --- a/docs/docs/guides/wallet/metamask-vanilla.md +++ b/docs/docs/guides/wallet/metamask-vanilla.md @@ -1,5 +1,5 @@ --- -sidebar_position: 3 +sidebar_position: 4 sidebar_label: 'Tutorial: Connecting to Metamask with Vanilla JS' --- diff --git a/docs/docs/guides/wallet/tx-types.md b/docs/docs/guides/wallet/tx-types.md new file mode 100644 index 00000000000..1e58a6b840a --- /dev/null +++ b/docs/docs/guides/wallet/tx-types.md @@ -0,0 +1,280 @@ +--- +sidebar_position: 3 +sidebar_label: 'Transaction Types' +--- + +# Transactions + +In this tutorial, we will explore how to send different types of [transactions](https://ethereum.org/en/developers/docs/transactions/) using web3.js, focusing on Ethereum's evolving transaction formats. We'll start with [legacy transactions (Transaction Type 0)](#transaction-type-0-legacy). Next, we'll delve into Transaction [Type 1 (EIP-2930)](#transaction-type-1-eip-2930), which introduces access lists to optimize gas usage. Finally, we'll cover [Transaction Type 2 (EIP-1559)](#transaction-type-2-eip-1559), the current default, which allows users to specify maximum fees and priority tips for more efficient and cost-effective transactions. Each section will include practical code examples to demonstrate sending raw transactions and interacting with ERC20 tokens on the Sepolia test network + +:::note +Web3.js uses transaction type 2 by default +::: + +## Transaction Type 0 (Legacy) + +### Raw Transaction + +A Legacy Transaction refers to a transaction that was created using an older version of Ethereum's transaction format, also known as "transaction type 0". This transaction format was used before the EIP-1559 upgrade, which was implemented in August 2021. + +```ts +import { Web3 } from "web3"; + +const web3 = new Web3("https://rpc2.sepolia.org"); // RPC node url + +async function txLegacy() { + const wallet = web3.eth.wallet.add("YOUR_PRIVATE_KEY"); // make sure you have funds + + const sender = wallet[0].address; + const recipient = "0x807BFe4940016B5a7FdA19482042917B02e68359"; + const value = 1; // wei + const nonce = await web3.eth.getTransactionCount(sender); + const gas = 21000; + const gasPrice = await web3.eth.getGasPrice(); + + const tx = { + from: sender, + to: recipient, + value, + nonce, + gas, + gasPrice, + // highlight-next-line + type: 0, + }; + + const txReceipt = await web3.eth.sendTransaction(tx); + console.log("Tx hash", txReceipt.transactionHash); +} + +txLegacy(); +``` + +### ERC20 Interaction + +```ts +import { Web3 } from "web3"; + +const web3 = new Web3("https://rpc2.sepolia.org"); + +//WETH token in Sepolia https://sepolia.etherscan.io/address/0xfff9976782d46cc05630d1f6ebab18b2324d6b14#code +const ADDRESS_WETH_SEPOLIA = "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14"; +const ABI = [ + { + constant: false, + inputs: [ + { + name: "dst", + type: "address", + }, + { + name: "wad", + type: "uint256", + }, + ], + name: "transfer", + outputs: [ + { + name: "", + type: "bool", + }, + ], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, +]; + +async function transfer() { + //initialize wallet + const wallet = web3.eth.accounts.wallet.add("YOUR_PRIVATE_KEY"); //make sure you have WETH tokens in the Sepolia network + //you can swap Sepolia tokens for WETH here https://app.uniswap.org/swap?chain=sepolia + + //initialize WETH contract in sepolia + const myERC20 = new web3.eth.Contract(ABI, ADDRESS_WETH_SEPOLIA); + + const TO = "0xEA9eEca67682Cd9c6Ce3DdD1681049D7A897289F"; //address to send the tokens to + const VALUE = 1; //wei value, dont forget to multiply by decimals + + //send transfer and specify the type + const txReceipt = await myERC20.methods.transfer(TO, VALUE).send({ + from: wallet[0].address, + // highlight-next-line + type: 0, + }); + + console.log(txReceipt.transactionHash); + //=> 0x5f2087c22166f3a1909c40ce537dd564dc3d4c70c5be02f35c6406a628123b16 +} + +transfer(); +``` + +## Transaction Type 1 (EIP-2930) + +This EIP was introduced in April 2021, it introduces a feature called 'Access List.' This improvement allows saving gas on cross-contract calls by declaring in advance which contract and storage slots will be accessed. + +### Raw Transaction + +```ts +import { Web3 } from "web3"; + +const web3 = new Web3("https://rpc2.sepolia.org"); + +async function txEIP2930() { + const wallet = web3.eth.wallet.add("YOUR_PRIVATE_KEY"); + + const sender = wallet[0].address; + const contractAddress1 = "0x..."; + const gas = 500000; //could be higher + const gasPrice = await web3.eth.getGasPrice(); + const data = "0x9a67c8b100000000000000000000000000000000000000000000000000000000000004d0" + + + // highlight-start + //create access list using web3.eth + const accessListData = await web3.eth.createAccessList({ + from: sender, + to: contractAddress1, + data, + }); + // highlight-end + + console.log(accessListData) + /* + => + { + // highlight-start + "accessList": [ + { + "address": "0x15859bdf5aff2080a9968f6a410361e9598df62f", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + // highlight-end + "gasUsed": "0x7671" + } + */ + + const tx = { + from: sender, + to: contractAddress1, //the contract we are calling + data, + gas, + gasPrice, + // highlight-next-line + type: 1, + // highlight-next-line + accessList: accessListData.accessList //access the object `accessList` + }; + + const txReceipt = await web3.eth.sendTransaction(tx); + + console.log("Tx hash", txReceipt.transactionHash); +} + +txEIP2930() +``` + +## Transaction Type 2 (EIP-1559) + +When a user creates an EIP-1559 transaction, they specify the maximum fee they are willing to pay `maxFeePerGas` as well as a tip `maxPriorityFeePerGas` to incentivize the miner. The actual fee paid by the user is then determined by the network based on the current demand for block space and the priority of the transaction. + +### Raw Transaction + +```ts +import { Web3 } from "web3"; + +const web3 = new Web3("https://rpc2.sepolia.org"); + +async function txEIP1559() { + const wallet = web3.eth.wallet.add("YOUR_PRIVATE_KEY"); //make sure you have funds + + const sender = wallet[0].address; + const recipient = "0x807BFe4940016B5a7FdA19482042917B02e68359"; + const value = 1; //wei + const nonce = await web3.eth.getTransactionCount(sender); + const gasLimit = 21000; + const maxFeePerGas = Number((await web3.eth.calculateFeeData()).maxFeePerGas); + const maxPriorityFeePerGas = Number((await web3.eth.calculateFeeData()).maxPriorityFeePerGas); + + const tx = { + from: sender, + to: recipient, + value, + nonce, + gasLimit, + maxFeePerGas, + maxPriorityFeePerGas, + // highlight-next-line + type: 2, + }; + + const txReceipt = await web3.eth.sendTransaction(tx); + console.log("Tx hash", txReceipt.transactionHash); +} + +txEIP1559(); +``` + +### ERC20 Interaction + +```ts +import { Web3 } from "web3"; + +const web3 = new Web3("https://rpc2.sepolia.org"); + +//WETH token in Sepolia https://sepolia.etherscan.io/address/0xfff9976782d46cc05630d1f6ebab18b2324d6b14#code +const ADDRESS_WETH_SEPOLIA = "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14"; +const ABI = [ + { + constant: false, + inputs: [ + { + name: "dst", + type: "address", + }, + { + name: "wad", + type: "uint256", + }, + ], + name: "transfer", + outputs: [ + { + name: "", + type: "bool", + }, + ], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, +]; + +async function transfer() { + //initialize wallet + const wallet = web3.eth.accounts.wallet.add("YOUR_PRIVATE_KEY"); //make sure you have WETH tokens in the Sepolia network + //you can swap Sepolia tokens for WETH here https://app.uniswap.org/swap?chain=sepolia + + //initialize WETH contract in sepolia + const myERC20 = new web3.eth.Contract(ABI, ADDRESS_WETH_SEPOLIA); + + const TO = "0xEA9eEca67682Cd9c6Ce3DdD1681049D7A897289F"; //address to send the tokens to + const VALUE = 1; //wei value, dont forget to multiply by decimals + + //send transfer and specify the type + const txReceipt = await myERC20.methods.transfer(TO, VALUE).send({ + from: wallet[0].address, + // highlight-next-line + type: 2, + }); + + console.log(txReceipt.transactionHash); + //=> 0x174bc88023be4af431fad1693a59f7a41135238510cdcd00f15f6409b5471d77 +} + +transfer(); +``` \ No newline at end of file diff --git a/docs/docs/guides/wallet/web3_modal_guide/_category_.yml b/docs/docs/guides/wallet/web3_modal_guide/_category_.yml index c89deac9d4b..0ce376f6e80 100644 --- a/docs/docs/guides/wallet/web3_modal_guide/_category_.yml +++ b/docs/docs/guides/wallet/web3_modal_guide/_category_.yml @@ -2,4 +2,4 @@ label: '📱 WalletConnect Tutorial' collapsible: true collapsed: true link: null -position: 4 +position: 6 From cbcfc1878502008349f805a2e82e9263a02b717e Mon Sep 17 00:00:00 2001 From: Christopher <43022421+agj017@users.noreply.github.com> Date: Mon, 22 Jul 2024 17:36:25 +0900 Subject: [PATCH 122/186] remove redundant constructor of ContractBuilder (#7150) Co-authored-by: Oleksii Kosynskyi --- packages/web3/src/web3.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/web3/src/web3.ts b/packages/web3/src/web3.ts index 9b231e7c6eb..c3362364f9a 100644 --- a/packages/web3/src/web3.ts +++ b/packages/web3/src/web3.ts @@ -137,12 +137,6 @@ export class Web3< optionsOrContextOrReturnFormat?: ContractInitOptions, contextOrReturnFormat?: Web3Context | DataFormat, ); - public constructor( - jsonInterface: Abi, - addressOrOptionsOrContext?: Address | ContractInitOptions, - optionsOrContextOrReturnFormat?: ContractInitOptions, - contextOrReturnFormat?: Web3Context | DataFormat, - ); public constructor( jsonInterface: Abi, addressOrOptionsOrContext?: Address | ContractInitOptions, From 5f6deebd2b27a6120e3102f4f03fb82b8c1b4674 Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 22 Jul 2024 09:45:47 -0400 Subject: [PATCH 123/186] Fix transaction receipt return type (#7159) * add default array to block.transactions * update * update * update * update changelog --------- Co-authored-by: CI --- packages/web3-eth/CHANGELOG.md | 3 ++- packages/web3-eth/src/rpc_method_wrappers.ts | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/web3-eth/CHANGELOG.md b/packages/web3-eth/CHANGELOG.md index 417db4d0837..b3b98530d82 100644 --- a/packages/web3-eth/CHANGELOG.md +++ b/packages/web3-eth/CHANGELOG.md @@ -266,4 +266,5 @@ Documentation: ### Fixed -- Adds transaction property to be an empty list rather than undefined when no transactions are included in the block (#7151) \ No newline at end of file +- Adds transaction property to be an empty list rather than undefined when no transactions are included in the block (#7151) +- Change method `getTransactionReceipt` to not be casted as `TransactionReceipt` to give proper return type (#7159) \ No newline at end of file diff --git a/packages/web3-eth/src/rpc_method_wrappers.ts b/packages/web3-eth/src/rpc_method_wrappers.ts index 8195eb58caa..02fb9fbb173 100644 --- a/packages/web3-eth/src/rpc_method_wrappers.ts +++ b/packages/web3-eth/src/rpc_method_wrappers.ts @@ -521,14 +521,13 @@ export async function getTransactionReceipt( } } - return isNullish(response) ? response : (format( transactionReceiptSchema, response as unknown as TransactionReceipt, returnFormat ?? web3Context.defaultReturnFormat, - ) as TransactionReceipt); + )); } /** From e5efe49e689b928e2049ff14c160fe3e5819369f Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Mon, 22 Jul 2024 08:16:43 -0700 Subject: [PATCH 124/186] feat/docs/plugin-middleware (#7158) * Add Plugin Middleware Documentation Closes #6963 * Clarify Request Middleware Response Processing --- .../web3_plugin_guide/plugin_authors.md | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/docs/docs/guides/web3_plugin_guide/plugin_authors.md b/docs/docs/guides/web3_plugin_guide/plugin_authors.md index bde1e1e6558..4100882e67f 100644 --- a/docs/docs/guides/web3_plugin_guide/plugin_authors.md +++ b/docs/docs/guides/web3_plugin_guide/plugin_authors.md @@ -233,6 +233,73 @@ public link(parentContext: Web3Context) { } ``` +## Plugin Middleware + +Middleware allows plugins to intercept network interactions and inject custom logic. There are two types of plugin middleware: [request middleware](#request-middleware) and [transaction middleware](#transaction-middleware). In both cases, the middleware is implemented as a new class and registered with the plugin in the plugin's `link` method. Keep reading to learn how to add middleware to a plugin. + +### Request Middleware + +Request middleware allows plugins to modify RPC requests before they are sent to the network and modify RPC responses before they are returned to Web3.js for further internal processing. Request middleware must implement the [`RequestManagerMiddleware`](/api/web3-core/interface/RequestManagerMiddleware) interface, which specifies two functions: [`processRequest`](/api/web3-core/interface/RequestManagerMiddleware#processRequest) and [`processResponse`](/api/web3-core/interface/RequestManagerMiddleware#processResponse). Here is a simple example of request middleware that prints RPC requests and responses to the console: + +```ts +export class RequestMiddleware implements RequestManagerMiddleware { + public async processRequest( + request: JsonRpcPayload + ): Promise> { + const reqObj = { ...request } as JsonRpcPayload; + console.log("Request:", reqObj); + return Promise.resolve(reqObj as JsonRpcPayload); + } + + public async processResponse< + Method extends Web3APIMethod, + ResponseType = Web3APIReturnType + >( + response: JsonRpcResponse + ): Promise> { + const resObj = { ...response }; + console.log("Response:", resObj); + return Promise.resolve(resObj); + } +} +``` + +To add request middleware to a plugin, use the [`Web3RequestManager.setMiddleware`](/api/web3-core/class/Web3RequestManager#setMiddleware) method in the plugin's `link` method as demonstrated below: + +```ts +public link(parentContext: Web3Context): void { + parentContext.requestManager.setMiddleware(new RequestMiddleware()); + super.link(parentContext); +} +``` + +### Transaction Middleware + +Transaction middleware allows plugins to modify transaction data before it is sent to the network. Transaction middleware must implement the [`TransactionMiddleware`](/api/web3-eth/interface/TransactionMiddleware) interface, which specifies one function: [`processTransaction`](/api/web3-eth/interface/TransactionMiddleware#processTransaction). Here is a simple example of transaction middleware that prints transaction data to the console: + +```ts +export class TxnMiddleware implements TransactionMiddleware { + public async processTransaction( + transaction: TransactionMiddlewareData + ): Promise { + const txObj = { ...transaction }; + console.log("Transaction data:", txObj); + return Promise.resolve(txObj); + } +} +``` + +To add transaction middleware to a plugin, use the [`Web3Eth.setTransactionMiddleware`](/api/web3-eth/class/Web3Eth#setTransactionMiddleware) method in the plugin's `link` method as demonstrated below: + +```ts +public link(parentContext: Web3Context): void { + (parentContext as any).Web3Eth.setTransactionMiddleware( + new TxnMiddleware() + ); + super.link(parentContext); +} +``` + ## Setting Up Module Augmentation In order to provide type safety and IntelliSense for your plugin when it's registered by the user, you must [augment](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation) the `Web3Context` module. In simpler terms, you will be making TypeScript aware that you are modifying the interface of the class `Web3Context`, and any class that extends it, to include the interface of your plugin (i.e. your plugin's added methods, properties, etc.). As a result, your plugin object will be accessible within a namespace of your choice, which will be available within any `Web3Context` object. From cbbbd84bac7051b57ec636b857e06adcc3da05f6 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 24 Jul 2024 11:20:44 -0400 Subject: [PATCH 125/186] bump versions (#7166) --- CHANGELOG.md | 17 +++++++++++++++++ packages/web3-errors/CHANGELOG.md | 6 ++++-- packages/web3-errors/package.json | 4 ++-- packages/web3-eth/CHANGELOG.md | 6 ++++-- packages/web3-eth/package.json | 4 ++-- packages/web3/CHANGELOG.md | 17 +++++++++++++++++ packages/web3/package.json | 6 +++--- packages/web3/src/version.ts | 2 +- 8 files changed, 50 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 774e4cb4f40..25645330a25 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2631,4 +2631,21 @@ If there are any bugs, improvements, optimizations or any new feature proposal f - `web3.eth.Contract` will get transaction middleware and use it, if `web3.eth` has transaction middleware. (#7138) +## [4.11.1] + +### Fixed + +#### web3-errors + +- Fixed the undefined data in `Eip838ExecutionError` constructor (#6905) + +#### web3-eth + +- Adds transaction property to be an empty list rather than undefined when no transactions are included in the block (#7151) +- Change method `getTransactionReceipt` to not be casted as `TransactionReceipt` to give proper return type (#7159) + +#### web3 + +- Remove redundant constructor of contractBuilder (#7150) + ## [Unreleased] \ No newline at end of file diff --git a/packages/web3-errors/CHANGELOG.md b/packages/web3-errors/CHANGELOG.md index 25ae481c3df..3ed320c80a1 100644 --- a/packages/web3-errors/CHANGELOG.md +++ b/packages/web3-errors/CHANGELOG.md @@ -172,8 +172,10 @@ Documentation: - Added `InvalidIntegerError` error for fromWei and toWei (#7052) -## [Unreleased] +## [1.2.1] ### Fixed -- Fixed the undefined data in `Eip838ExecutionError` constructor (#6905) \ No newline at end of file +- Fixed the undefined data in `Eip838ExecutionError` constructor (#6905) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-errors/package.json b/packages/web3-errors/package.json index 1b8587c81b3..4d382b35716 100644 --- a/packages/web3-errors/package.json +++ b/packages/web3-errors/package.json @@ -1,6 +1,6 @@ { "name": "web3-errors", - "version": "1.2.0", + "version": "1.2.1", "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.6.0" + "web3-types": "^1.7.0" }, "devDependencies": { "@types/jest": "^28.1.6", diff --git a/packages/web3-eth/CHANGELOG.md b/packages/web3-eth/CHANGELOG.md index b3b98530d82..6be4b4b5797 100644 --- a/packages/web3-eth/CHANGELOG.md +++ b/packages/web3-eth/CHANGELOG.md @@ -262,9 +262,11 @@ Documentation: - Fixed geth issue when running a new instance, transactions will index when there are no blocks created (#7098) -## [Unreleased] +## [4.8.2] ### Fixed - Adds transaction property to be an empty list rather than undefined when no transactions are included in the block (#7151) -- Change method `getTransactionReceipt` to not be casted as `TransactionReceipt` to give proper return type (#7159) \ No newline at end of file +- Change method `getTransactionReceipt` to not be casted as `TransactionReceipt` to give proper return type (#7159) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-eth/package.json b/packages/web3-eth/package.json index 2de8e03264f..75b35059356 100644 --- a/packages/web3-eth/package.json +++ b/packages/web3-eth/package.json @@ -1,6 +1,6 @@ { "name": "web3-eth", - "version": "4.8.1", + "version": "4.8.2", "description": "Web3 module to interact with the Ethereum blockchain and smart contracts.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -64,7 +64,7 @@ "dependencies": { "setimmediate": "^1.0.5", "web3-core": "^4.5.0", - "web3-errors": "^1.2.0", + "web3-errors": "^1.2.1", "web3-eth-abi": "^4.2.3", "web3-eth-accounts": "^4.1.3", "web3-net": "^4.1.0", diff --git a/packages/web3/CHANGELOG.md b/packages/web3/CHANGELOG.md index a4585474629..e8b2d5c705a 100644 --- a/packages/web3/CHANGELOG.md +++ b/packages/web3/CHANGELOG.md @@ -419,4 +419,21 @@ Documentation: - `web3.eth.Contract` will get transaction middleware and use it, if `web3.eth` has transaction middleware. (#7138) +## [4.11.1] + +### Fixed + +#### web3-errors + +- Fixed the undefined data in `Eip838ExecutionError` constructor (#6905) + +#### web3-eth + +- Adds transaction property to be an empty list rather than undefined when no transactions are included in the block (#7151) +- Change method `getTransactionReceipt` to not be casted as `TransactionReceipt` to give proper return type (#7159) + +#### web3 + +- Remove redundant constructor of contractBuilder (#7150) + ## [Unreleased] \ No newline at end of file diff --git a/packages/web3/package.json b/packages/web3/package.json index 952b99a7d76..2b680517e80 100644 --- a/packages/web3/package.json +++ b/packages/web3/package.json @@ -1,6 +1,6 @@ { "name": "web3", - "version": "4.11.0", + "version": "4.11.1", "description": "Ethereum JavaScript API", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -87,8 +87,8 @@ }, "dependencies": { "web3-core": "^4.5.0", - "web3-errors": "^1.2.0", - "web3-eth": "^4.8.1", + "web3-errors": "^1.2.1", + "web3-eth": "^4.8.2", "web3-eth-abi": "^4.2.3", "web3-eth-accounts": "^4.1.3", "web3-eth-contract": "^4.6.0", diff --git a/packages/web3/src/version.ts b/packages/web3/src/version.ts index 86a46d17625..268f69fed23 100644 --- a/packages/web3/src/version.ts +++ b/packages/web3/src/version.ts @@ -1 +1 @@ -/* eslint-disable header/header */ export const Web3PkgInfo = { version: '4.11.0' }; +/* eslint-disable header/header */ export const Web3PkgInfo = { version: '4.11.1' }; From dee14ecf4c4ddb2e7964f465f157a07b05c1101e Mon Sep 17 00:00:00 2001 From: Santiago Trujillo Zuluaga Date: Tue, 30 Jul 2024 19:25:54 +0300 Subject: [PATCH 126/186] Cookbook integration branch (#7178) * feat: Ask Cookbook integration comments for ask cookbook * updated yarn lock * fixed broken link --------- Co-authored-by: Anton Dosta --- docs/docs/guides/web3_eth/methods.md | 2 +- docs/package.json | 1 + docs/src/theme/SearchBar/index.js | 17 + docs/yarn.lock | 5811 +++++++++++++++++--------- 4 files changed, 3752 insertions(+), 2079 deletions(-) create mode 100644 docs/src/theme/SearchBar/index.js diff --git a/docs/docs/guides/web3_eth/methods.md b/docs/docs/guides/web3_eth/methods.md index 36125f0f253..cc0f2f21df0 100644 --- a/docs/docs/guides/web3_eth/methods.md +++ b/docs/docs/guides/web3_eth/methods.md @@ -100,7 +100,7 @@ The [sendTransaction](/api/web3-eth/function/sendTransaction) method is used to :::important Please be cautious when sending transactions, especially when dealing with smart contracts, as they may execute specific functions that can have irreversible effects. Always ensure that the details in your transaction object are accurate and intended. -[Here](guides/wallet/transactions) you can find more examples how to send transaction. +[Here](/guides/wallet/transactions) you can find more examples how to send transaction. ::: ## sign diff --git a/docs/package.json b/docs/package.json index 4df7ece9893..c729ef5a765 100644 --- a/docs/package.json +++ b/docs/package.json @@ -15,6 +15,7 @@ "typecheck": "tsc" }, "dependencies": { + "@cookbookdev/docsbot": "^4.21.1", "@docusaurus/core": "^3.0.1", "@docusaurus/preset-classic": "^3.0.1", "@docusaurus/theme-live-codeblock": "^3.0.1", diff --git a/docs/src/theme/SearchBar/index.js b/docs/src/theme/SearchBar/index.js new file mode 100644 index 00000000000..f592c80e5c1 --- /dev/null +++ b/docs/src/theme/SearchBar/index.js @@ -0,0 +1,17 @@ +import React from 'react'; +import SearchBar from '@theme-original/SearchBar'; +import AskCookbook from '@cookbookdev/docsbot/react'; + +// This is a public key, so it's safe to hardcode it. +// To get a new one or request access to the internal portal (If you work for the Web3JS), contact the cookbook.dev team at tyler@cookbook.dev. +const ASK_COOKBOOK_PUBLIC_KEY = + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI2NjdjNzc3YzNmOGY3Mzk2MGYzZGNiOGYiLCJpYXQiOjE3MTk0MzMwODQsImV4cCI6MjAzNTAwOTA4NH0.OXWVNJMxMuEGG1oWetW_a9005r8hmQ6RbF19wbrpTlk'; + +export default function SearchBarWrapper(props) { + return ( + <> + + + + ); +} diff --git a/docs/yarn.lock b/docs/yarn.lock index 3fbad057881..05de2845cc6 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -2,6 +2,11 @@ # yarn lockfile v1 +"@adraffy/ens-normalize@1.10.0": + version "1.10.0" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz#d2a39395c587e092d77cbbc80acf956a54f38bf7" + integrity sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q== + "@algolia/autocomplete-core@1.9.3": version "1.9.3" resolved "https://registry.yarnpkg.com/@algolia/autocomplete-core/-/autocomplete-core-1.9.3.tgz#1d56482a768c33aae0868c8533049e02e8961be7" @@ -29,220 +34,238 @@ resolved "https://registry.yarnpkg.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.9.3.tgz#2e22e830d36f0a9cf2c0ccd3c7f6d59435b77dfa" integrity sha512-Wnm9E4Ye6Rl6sTTqjoymD+l8DjSTHsHboVRYrKgEt8Q7UHm9nYbqhN/i0fhUYA3OAEH7WA8x3jfpnmJm3rKvaQ== -"@algolia/cache-browser-local-storage@4.22.0": - version "4.22.0" - resolved "https://registry.yarnpkg.com/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.22.0.tgz#548e3f9524988bbe0c14b7fc7b2a66335520eeb7" - integrity sha512-uZ1uZMLDZb4qODLfTSNHxSi4fH9RdrQf7DXEzW01dS8XK7QFtFh29N5NGKa9S+Yudf1vUMIF+/RiL4i/J0pWlQ== +"@algolia/cache-browser-local-storage@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.24.0.tgz#97bc6d067a9fd932b9c922faa6b7fd6e546e1348" + integrity sha512-t63W9BnoXVrGy9iYHBgObNXqYXM3tYXCjDSHeNwnsc324r4o5UiVKUiAB4THQ5z9U5hTj6qUvwg/Ez43ZD85ww== dependencies: - "@algolia/cache-common" "4.22.0" + "@algolia/cache-common" "4.24.0" -"@algolia/cache-common@4.22.0": - version "4.22.0" - resolved "https://registry.yarnpkg.com/@algolia/cache-common/-/cache-common-4.22.0.tgz#83d6111caac74a71bebe5fc050a3b64f3e45d037" - integrity sha512-TPwUMlIGPN16eW67qamNQUmxNiGHg/WBqWcrOoCddhqNTqGDPVqmgfaM85LPbt24t3r1z0zEz/tdsmuq3Q6oaA== +"@algolia/cache-common@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@algolia/cache-common/-/cache-common-4.24.0.tgz#81a8d3a82ceb75302abb9b150a52eba9960c9744" + integrity sha512-emi+v+DmVLpMGhp0V9q9h5CdkURsNmFC+cOS6uK9ndeJm9J4TiqSvPYVu+THUP8P/S08rxf5x2P+p3CfID0Y4g== -"@algolia/cache-in-memory@4.22.0": - version "4.22.0" - resolved "https://registry.yarnpkg.com/@algolia/cache-in-memory/-/cache-in-memory-4.22.0.tgz#ff86b08d8c80a9402f39e5c64cef2ba8299bbe1d" - integrity sha512-kf4Cio9NpPjzp1+uXQgL4jsMDeck7MP89BYThSvXSjf2A6qV/0KeqQf90TL2ECS02ovLOBXkk98P7qVarM+zGA== +"@algolia/cache-in-memory@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@algolia/cache-in-memory/-/cache-in-memory-4.24.0.tgz#ffcf8872f3a10cb85c4f4641bdffd307933a6e44" + integrity sha512-gDrt2so19jW26jY3/MkFg5mEypFIPbPoXsQGQWAi6TrCPsNOSEYepBMPlucqWigsmEy/prp5ug2jy/N3PVG/8w== dependencies: - "@algolia/cache-common" "4.22.0" + "@algolia/cache-common" "4.24.0" -"@algolia/client-account@4.22.0": - version "4.22.0" - resolved "https://registry.yarnpkg.com/@algolia/client-account/-/client-account-4.22.0.tgz#d7fa001dc062dca446f0620281fc0cec7c850487" - integrity sha512-Bjb5UXpWmJT+yGWiqAJL0prkENyEZTBzdC+N1vBuHjwIJcjLMjPB6j1hNBRbT12Lmwi55uzqeMIKS69w+0aPzA== +"@algolia/client-account@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@algolia/client-account/-/client-account-4.24.0.tgz#eba7a921d828e7c8c40a32d4add21206c7fe12f1" + integrity sha512-adcvyJ3KjPZFDybxlqnf+5KgxJtBjwTPTeyG2aOyoJvx0Y8dUQAEOEVOJ/GBxX0WWNbmaSrhDURMhc+QeevDsA== dependencies: - "@algolia/client-common" "4.22.0" - "@algolia/client-search" "4.22.0" - "@algolia/transporter" "4.22.0" + "@algolia/client-common" "4.24.0" + "@algolia/client-search" "4.24.0" + "@algolia/transporter" "4.24.0" -"@algolia/client-analytics@4.22.0": - version "4.22.0" - resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-4.22.0.tgz#ea10e73d649aa1b9a1a25a786300d241fd4ad0d1" - integrity sha512-os2K+kHUcwwRa4ArFl5p/3YbF9lN3TLOPkbXXXxOvDpqFh62n9IRZuzfxpHxMPKAQS3Et1s0BkKavnNP02E9Hg== +"@algolia/client-analytics@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-4.24.0.tgz#9d2576c46a9093a14e668833c505ea697a1a3e30" + integrity sha512-y8jOZt1OjwWU4N2qr8G4AxXAzaa8DBvyHTWlHzX/7Me1LX8OayfgHexqrsL4vSBcoMmVw2XnVW9MhL+Y2ZDJXg== dependencies: - "@algolia/client-common" "4.22.0" - "@algolia/client-search" "4.22.0" - "@algolia/requester-common" "4.22.0" - "@algolia/transporter" "4.22.0" + "@algolia/client-common" "4.24.0" + "@algolia/client-search" "4.24.0" + "@algolia/requester-common" "4.24.0" + "@algolia/transporter" "4.24.0" -"@algolia/client-common@4.22.0": - version "4.22.0" - resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-4.22.0.tgz#4bf298acec78fa988a5b829748e6c488b8a6b570" - integrity sha512-BlbkF4qXVWuwTmYxVWvqtatCR3lzXwxx628p1wj1Q7QP2+LsTmGt1DiUYRuy9jG7iMsnlExby6kRMOOlbhv2Ag== +"@algolia/client-common@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-4.24.0.tgz#77c46eee42b9444a1d1c1583a83f7df4398a649d" + integrity sha512-bc2ROsNL6w6rqpl5jj/UywlIYC21TwSSoFHKl01lYirGMW+9Eek6r02Tocg4gZ8HAw3iBvu6XQiM3BEbmEMoiA== dependencies: - "@algolia/requester-common" "4.22.0" - "@algolia/transporter" "4.22.0" + "@algolia/requester-common" "4.24.0" + "@algolia/transporter" "4.24.0" -"@algolia/client-personalization@4.22.0": - version "4.22.0" - resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-4.22.0.tgz#210c7d196b3c31da45e16db6ed98a7594fcf5e1c" - integrity sha512-pEOftCxeBdG5pL97WngOBi9w5Vxr5KCV2j2D+xMVZH8MuU/JX7CglDSDDb0ffQWYqcUN+40Ry+xtXEYaGXTGow== +"@algolia/client-personalization@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-4.24.0.tgz#8b47789fb1cb0f8efbea0f79295b7c5a3850f6ae" + integrity sha512-l5FRFm/yngztweU0HdUzz1rC4yoWCFo3IF+dVIVTfEPg906eZg5BOd1k0K6rZx5JzyyoP4LdmOikfkfGsKVE9w== dependencies: - "@algolia/client-common" "4.22.0" - "@algolia/requester-common" "4.22.0" - "@algolia/transporter" "4.22.0" + "@algolia/client-common" "4.24.0" + "@algolia/requester-common" "4.24.0" + "@algolia/transporter" "4.24.0" -"@algolia/client-search@4.22.0": - version "4.22.0" - resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-4.22.0.tgz#1113332cf973ce69067b741a17e8f798d71e07db" - integrity sha512-bn4qQiIdRPBGCwsNuuqB8rdHhGKKWIij9OqidM1UkQxnSG8yzxHdb7CujM30pvp5EnV7jTqDZRbxacbjYVW20Q== +"@algolia/client-search@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-4.24.0.tgz#75e6c02d33ef3e0f34afd9962c085b856fc4a55f" + integrity sha512-uRW6EpNapmLAD0mW47OXqTP8eiIx5F6qN9/x/7HHO6owL3N1IXqydGwW5nhDFBrV+ldouro2W1VX3XlcUXEFCA== dependencies: - "@algolia/client-common" "4.22.0" - "@algolia/requester-common" "4.22.0" - "@algolia/transporter" "4.22.0" + "@algolia/client-common" "4.24.0" + "@algolia/requester-common" "4.24.0" + "@algolia/transporter" "4.24.0" "@algolia/events@^4.0.1": version "4.0.1" resolved "https://registry.yarnpkg.com/@algolia/events/-/events-4.0.1.tgz#fd39e7477e7bc703d7f893b556f676c032af3950" integrity sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ== -"@algolia/logger-common@4.22.0": - version "4.22.0" - resolved "https://registry.yarnpkg.com/@algolia/logger-common/-/logger-common-4.22.0.tgz#f9498729ca5b0e9c0bd1b8dd729edd91ddd02b5c" - integrity sha512-HMUQTID0ucxNCXs5d1eBJ5q/HuKg8rFVE/vOiLaM4Abfeq1YnTtGV3+rFEhOPWhRQxNDd+YHa4q864IMc0zHpQ== - -"@algolia/logger-console@4.22.0": - version "4.22.0" - resolved "https://registry.yarnpkg.com/@algolia/logger-console/-/logger-console-4.22.0.tgz#52e62b98fc01b40d6677b0ddf656b342e89f13c2" - integrity sha512-7JKb6hgcY64H7CRm3u6DRAiiEVXMvCJV5gRE672QFOUgDxo4aiDpfU61g6Uzy8NKjlEzHMmgG4e2fklELmPXhQ== - dependencies: - "@algolia/logger-common" "4.22.0" - -"@algolia/requester-browser-xhr@4.22.0": - version "4.22.0" - resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.22.0.tgz#ca16e4c6860458477a00b440a407c81591f14b8a" - integrity sha512-BHfv1h7P9/SyvcDJDaRuIwDu2yrDLlXlYmjvaLZTtPw6Ok/ZVhBR55JqW832XN/Fsl6k3LjdkYHHR7xnsa5Wvg== - dependencies: - "@algolia/requester-common" "4.22.0" - -"@algolia/requester-common@4.22.0": - version "4.22.0" - resolved "https://registry.yarnpkg.com/@algolia/requester-common/-/requester-common-4.22.0.tgz#d7a8283f5b77550eeab353c571a6566adf552fa7" - integrity sha512-Y9cEH/cKjIIZgzvI1aI0ARdtR/xRrOR13g5psCxkdhpgRN0Vcorx+zePhmAa4jdQNqexpxtkUdcKYugBzMZJgQ== - -"@algolia/requester-node-http@4.22.0": - version "4.22.0" - resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-4.22.0.tgz#41d5e7d5dc7adb930e7fe8dcd9d39bfc378cc5f5" - integrity sha512-8xHoGpxVhz3u2MYIieHIB6MsnX+vfd5PS4REgglejJ6lPigftRhTdBCToe6zbwq4p0anZXjjPDvNWMlgK2+xYA== - dependencies: - "@algolia/requester-common" "4.22.0" - -"@algolia/transporter@4.22.0": - version "4.22.0" - resolved "https://registry.yarnpkg.com/@algolia/transporter/-/transporter-4.22.0.tgz#733385f6457408228d2a4d7a4fe4e2b1599a5d33" - integrity sha512-ieO1k8x2o77GNvOoC+vAkFKppydQSVfbjM3YrSjLmgywiBejPTvU1R1nEvG59JIIUvtSLrZsLGPkd6vL14zopA== - dependencies: - "@algolia/cache-common" "4.22.0" - "@algolia/logger-common" "4.22.0" - "@algolia/requester-common" "4.22.0" +"@algolia/logger-common@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@algolia/logger-common/-/logger-common-4.24.0.tgz#28d439976019ec0a46ba7a1a739ef493d4ef8123" + integrity sha512-LLUNjkahj9KtKYrQhFKCzMx0BY3RnNP4FEtO+sBybCjJ73E8jNdaKJ/Dd8A/VA4imVHP5tADZ8pn5B8Ga/wTMA== + +"@algolia/logger-console@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@algolia/logger-console/-/logger-console-4.24.0.tgz#c6ff486036cd90b81d07a95aaba04461da7e1c65" + integrity sha512-X4C8IoHgHfiUROfoRCV+lzSy+LHMgkoEEU1BbKcsfnV0i0S20zyy0NLww9dwVHUWNfPPxdMU+/wKmLGYf96yTg== + dependencies: + "@algolia/logger-common" "4.24.0" + +"@algolia/recommend@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@algolia/recommend/-/recommend-4.24.0.tgz#8a3f78aea471ee0a4836b78fd2aad4e9abcaaf34" + integrity sha512-P9kcgerfVBpfYHDfVZDvvdJv0lEoCvzNlOy2nykyt5bK8TyieYyiD0lguIJdRZZYGre03WIAFf14pgE+V+IBlw== + dependencies: + "@algolia/cache-browser-local-storage" "4.24.0" + "@algolia/cache-common" "4.24.0" + "@algolia/cache-in-memory" "4.24.0" + "@algolia/client-common" "4.24.0" + "@algolia/client-search" "4.24.0" + "@algolia/logger-common" "4.24.0" + "@algolia/logger-console" "4.24.0" + "@algolia/requester-browser-xhr" "4.24.0" + "@algolia/requester-common" "4.24.0" + "@algolia/requester-node-http" "4.24.0" + "@algolia/transporter" "4.24.0" + +"@algolia/requester-browser-xhr@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.24.0.tgz#313c5edab4ed73a052e75803855833b62dd19c16" + integrity sha512-Z2NxZMb6+nVXSjF13YpjYTdvV3032YTBSGm2vnYvYPA6mMxzM3v5rsCiSspndn9rzIW4Qp1lPHBvuoKJV6jnAA== + dependencies: + "@algolia/requester-common" "4.24.0" + +"@algolia/requester-common@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@algolia/requester-common/-/requester-common-4.24.0.tgz#1c60c198031f48fcdb9e34c4057a3ea987b9a436" + integrity sha512-k3CXJ2OVnvgE3HMwcojpvY6d9kgKMPRxs/kVohrwF5WMr2fnqojnycZkxPoEg+bXm8fi5BBfFmOqgYztRtHsQA== + +"@algolia/requester-node-http@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-4.24.0.tgz#4461593714031d02aa7da221c49df675212f482f" + integrity sha512-JF18yTjNOVYvU/L3UosRcvbPMGT9B+/GQWNWnenIImglzNVGpyzChkXLnrSf6uxwVNO6ESGu6oN8MqcGQcjQJw== + dependencies: + "@algolia/requester-common" "4.24.0" + +"@algolia/transporter@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@algolia/transporter/-/transporter-4.24.0.tgz#226bb1f8af62430374c1972b2e5c8580ab275102" + integrity sha512-86nI7w6NzWxd1Zp9q3413dRshDqAzSbsQjhcDhPIatEFiZrL1/TjnHL8S7jVKFePlIMzDsZWXAXwXzcok9c5oA== + dependencies: + "@algolia/cache-common" "4.24.0" + "@algolia/logger-common" "4.24.0" + "@algolia/requester-common" "4.24.0" "@ampproject/remapping@^2.2.0": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630" - integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg== + version "2.3.0" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" + integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== dependencies: - "@jridgewell/gen-mapping" "^0.3.0" - "@jridgewell/trace-mapping" "^0.3.9" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.24" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.22.13", "@babel/code-frame@^7.23.5", "@babel/code-frame@^7.8.3": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" - integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.24.7", "@babel/code-frame@^7.8.3": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465" + integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA== dependencies: - "@babel/highlight" "^7.23.4" - chalk "^2.4.2" + "@babel/highlight" "^7.24.7" + picocolors "^1.0.0" -"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.23.3", "@babel/compat-data@^7.23.5": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.5.tgz#ffb878728bb6bdcb6f4510aa51b1be9afb8cfd98" - integrity sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw== +"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.24.8": + version "7.24.9" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.9.tgz#53eee4e68f1c1d0282aa0eb05ddb02d033fc43a0" + integrity sha512-e701mcfApCJqMMueQI0Fb68Amflj83+dvAvHawoBpAz+GDjCIyGHzNwnefjsWJ3xiYAqqiQFoWbspGYBdb2/ng== -"@babel/core@^7.19.6", "@babel/core@^7.23.3": - version "7.23.7" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.7.tgz#4d8016e06a14b5f92530a13ed0561730b5c6483f" - integrity sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw== +"@babel/core@^7.21.3", "@babel/core@^7.23.3": + version "7.24.9" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.9.tgz#dc07c9d307162c97fa9484ea997ade65841c7c82" + integrity sha512-5e3FI4Q3M3Pbr21+5xJwCv6ZT6KmGkI0vw3Tozy5ODAQFTIWe37iT8Cr7Ice2Ntb+M3iSKCEWMB1MBgKrW3whg== dependencies: "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.23.5" - "@babel/generator" "^7.23.6" - "@babel/helper-compilation-targets" "^7.23.6" - "@babel/helper-module-transforms" "^7.23.3" - "@babel/helpers" "^7.23.7" - "@babel/parser" "^7.23.6" - "@babel/template" "^7.22.15" - "@babel/traverse" "^7.23.7" - "@babel/types" "^7.23.6" + "@babel/code-frame" "^7.24.7" + "@babel/generator" "^7.24.9" + "@babel/helper-compilation-targets" "^7.24.8" + "@babel/helper-module-transforms" "^7.24.9" + "@babel/helpers" "^7.24.8" + "@babel/parser" "^7.24.8" + "@babel/template" "^7.24.7" + "@babel/traverse" "^7.24.8" + "@babel/types" "^7.24.9" convert-source-map "^2.0.0" debug "^4.1.0" gensync "^1.0.0-beta.2" json5 "^2.2.3" semver "^6.3.1" -"@babel/generator@^7.23.3", "@babel/generator@^7.23.6": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz#9e1fca4811c77a10580d17d26b57b036133f3c2e" - integrity sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw== +"@babel/generator@^7.23.3", "@babel/generator@^7.24.8", "@babel/generator@^7.24.9": + version "7.24.10" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.10.tgz#a4ab681ec2a78bbb9ba22a3941195e28a81d8e76" + integrity sha512-o9HBZL1G2129luEUlG1hB4N/nlYNWHnpwlND9eOMclRqqu1YDy2sSYVCFUZwl8I1Gxh+QSRrP2vD7EpUmFVXxg== dependencies: - "@babel/types" "^7.23.6" - "@jridgewell/gen-mapping" "^0.3.2" - "@jridgewell/trace-mapping" "^0.3.17" + "@babel/types" "^7.24.9" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" jsesc "^2.5.1" -"@babel/helper-annotate-as-pure@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882" - integrity sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg== +"@babel/helper-annotate-as-pure@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz#5373c7bc8366b12a033b4be1ac13a206c6656aab" + integrity sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg== dependencies: - "@babel/types" "^7.22.5" + "@babel/types" "^7.24.7" -"@babel/helper-builder-binary-assignment-operator-visitor@^7.22.15": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz#5426b109cf3ad47b91120f8328d8ab1be8b0b956" - integrity sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw== +"@babel/helper-builder-binary-assignment-operator-visitor@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz#37d66feb012024f2422b762b9b2a7cfe27c7fba3" + integrity sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA== dependencies: - "@babel/types" "^7.22.15" + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" -"@babel/helper-compilation-targets@^7.22.15", "@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.23.6": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz#4d79069b16cbcf1461289eccfbbd81501ae39991" - integrity sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ== +"@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.24.7", "@babel/helper-compilation-targets@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.8.tgz#b607c3161cd9d1744977d4f97139572fe778c271" + integrity sha512-oU+UoqCHdp+nWVDkpldqIQL/i/bvAv53tRqLG/s+cOXxe66zOYLU7ar/Xs3LdmBihrUMEUhwu6dMZwbNOYDwvw== dependencies: - "@babel/compat-data" "^7.23.5" - "@babel/helper-validator-option" "^7.23.5" - browserslist "^4.22.2" + "@babel/compat-data" "^7.24.8" + "@babel/helper-validator-option" "^7.24.8" + browserslist "^4.23.1" lru-cache "^5.1.1" semver "^6.3.1" -"@babel/helper-create-class-features-plugin@^7.22.15", "@babel/helper-create-class-features-plugin@^7.23.6": - version "7.23.7" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.7.tgz#b2e6826e0e20d337143655198b79d58fdc9bd43d" - integrity sha512-xCoqR/8+BoNnXOY7RVSgv6X+o7pmT5q1d+gGcRlXYkI+9B31glE4jeejhKVpA04O1AtzOt7OSQ6VYKP5FcRl9g== - dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-function-name" "^7.23.0" - "@babel/helper-member-expression-to-functions" "^7.23.0" - "@babel/helper-optimise-call-expression" "^7.22.5" - "@babel/helper-replace-supers" "^7.22.20" - "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" +"@babel/helper-create-class-features-plugin@^7.24.7", "@babel/helper-create-class-features-plugin@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.8.tgz#47f546408d13c200c0867f9d935184eaa0851b09" + integrity sha512-4f6Oqnmyp2PP3olgUMmOwC3akxSm5aBYraQ6YDdKy7NcAMkDECHWG0DEnV6M2UAkERgIBhYt8S27rURPg7SxWA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-function-name" "^7.24.7" + "@babel/helper-member-expression-to-functions" "^7.24.8" + "@babel/helper-optimise-call-expression" "^7.24.7" + "@babel/helper-replace-supers" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" + "@babel/helper-split-export-declaration" "^7.24.7" semver "^6.3.1" -"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.22.15", "@babel/helper-create-regexp-features-plugin@^7.22.5": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz#5ee90093914ea09639b01c711db0d6775e558be1" - integrity sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w== +"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.24.7.tgz#be4f435a80dc2b053c76eeb4b7d16dd22cfc89da" + integrity sha512-03TCmXy2FtXJEZfbXDTSqq1fRJArk7lX9DOFC/47VthYcxyIOx+eXQmdo6DOQvrbpIix+KfXwvuXdFDZHxt+rA== dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-annotate-as-pure" "^7.24.7" regexpu-core "^5.3.1" semver "^6.3.1" -"@babel/helper-define-polyfill-provider@^0.4.4": - version "0.4.4" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.4.tgz#64df615451cb30e94b59a9696022cffac9a10088" - integrity sha512-QcJMILQCu2jm5TFPGA3lCpJJTeEP+mqeXooG/NZbg/h5FTFi6V0+99ahlRsW8/kRLyb24LZVCCiclDedhLKcBA== +"@babel/helper-define-polyfill-provider@^0.6.1", "@babel/helper-define-polyfill-provider@^0.6.2": + version "0.6.2" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz#18594f789c3594acb24cfdb4a7f7b7d2e8bd912d" + integrity sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ== dependencies: "@babel/helper-compilation-targets" "^7.22.6" "@babel/helper-plugin-utils" "^7.22.5" @@ -250,172 +273,187 @@ lodash.debounce "^4.0.8" resolve "^1.14.2" -"@babel/helper-environment-visitor@^7.22.20": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" - integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== - -"@babel/helper-function-name@^7.22.5", "@babel/helper-function-name@^7.23.0": - version "7.23.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" - integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== - dependencies: - "@babel/template" "^7.22.15" - "@babel/types" "^7.23.0" - -"@babel/helper-hoist-variables@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" - integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== +"@babel/helper-environment-visitor@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz#4b31ba9551d1f90781ba83491dd59cf9b269f7d9" + integrity sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ== dependencies: - "@babel/types" "^7.22.5" + "@babel/types" "^7.24.7" -"@babel/helper-member-expression-to-functions@^7.22.15", "@babel/helper-member-expression-to-functions@^7.23.0": - version "7.23.0" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz#9263e88cc5e41d39ec18c9a3e0eced59a3e7d366" - integrity sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA== +"@babel/helper-function-name@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz#75f1e1725742f39ac6584ee0b16d94513da38dd2" + integrity sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA== dependencies: - "@babel/types" "^7.23.0" - -"@babel/helper-module-imports@^7.22.15": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0" - integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w== - dependencies: - "@babel/types" "^7.22.15" + "@babel/template" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/helper-hoist-variables@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz#b4ede1cde2fd89436397f30dc9376ee06b0f25ee" + integrity sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ== + dependencies: + "@babel/types" "^7.24.7" -"@babel/helper-module-transforms@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz#d7d12c3c5d30af5b3c0fcab2a6d5217773e2d0f1" - integrity sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ== - dependencies: - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-module-imports" "^7.22.15" - "@babel/helper-simple-access" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/helper-validator-identifier" "^7.22.20" - -"@babel/helper-optimise-call-expression@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz#f21531a9ccbff644fdd156b4077c16ff0c3f609e" - integrity sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295" - integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg== - -"@babel/helper-remap-async-to-generator@^7.22.20": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz#7b68e1cb4fa964d2996fd063723fb48eca8498e0" - integrity sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-wrap-function" "^7.22.20" - -"@babel/helper-replace-supers@^7.22.20": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz#e37d367123ca98fe455a9887734ed2e16eb7a793" - integrity sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw== - dependencies: - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-member-expression-to-functions" "^7.22.15" - "@babel/helper-optimise-call-expression" "^7.22.5" - -"@babel/helper-simple-access@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" - integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-skip-transparent-expression-wrappers@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz#007f15240b5751c537c40e77abb4e89eeaaa8847" - integrity sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-split-export-declaration@^7.22.6": - version "7.22.6" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" - integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-string-parser@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83" - integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ== - -"@babel/helper-validator-identifier@^7.22.20": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" - integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== - -"@babel/helper-validator-option@^7.22.15", "@babel/helper-validator-option@^7.23.5": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307" - integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== - -"@babel/helper-wrap-function@^7.22.20": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz#15352b0b9bfb10fc9c76f79f6342c00e3411a569" - integrity sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw== - dependencies: - "@babel/helper-function-name" "^7.22.5" - "@babel/template" "^7.22.15" - "@babel/types" "^7.22.19" - -"@babel/helpers@^7.23.7": - version "7.23.7" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.7.tgz#eb543c36f81da2873e47b76ee032343ac83bba60" - integrity sha512-6AMnjCoC8wjqBzDHkuqpa7jAKwvMo4dC+lr/TFBz+ucfulO1XMpDnwWPGBNwClOKZ8h6xn5N81W/R5OrcKtCbQ== - dependencies: - "@babel/template" "^7.22.15" - "@babel/traverse" "^7.23.7" - "@babel/types" "^7.23.6" - -"@babel/highlight@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b" - integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A== - dependencies: - "@babel/helper-validator-identifier" "^7.22.20" +"@babel/helper-member-expression-to-functions@^7.24.7", "@babel/helper-member-expression-to-functions@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz#6155e079c913357d24a4c20480db7c712a5c3fb6" + integrity sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA== + dependencies: + "@babel/traverse" "^7.24.8" + "@babel/types" "^7.24.8" + +"@babel/helper-module-imports@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz#f2f980392de5b84c3328fc71d38bd81bbb83042b" + integrity sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA== + dependencies: + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/helper-module-transforms@^7.24.7", "@babel/helper-module-transforms@^7.24.8", "@babel/helper-module-transforms@^7.24.9": + version "7.24.9" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.24.9.tgz#e13d26306b89eea569180868e652e7f514de9d29" + integrity sha512-oYbh+rtFKj/HwBQkFlUzvcybzklmVdVV3UU+mN7n2t/q3yGHbuVdNxyFvSBO1tfvjyArpHNcWMAzsSPdyI46hw== + dependencies: + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-module-imports" "^7.24.7" + "@babel/helper-simple-access" "^7.24.7" + "@babel/helper-split-export-declaration" "^7.24.7" + "@babel/helper-validator-identifier" "^7.24.7" + +"@babel/helper-optimise-call-expression@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz#8b0a0456c92f6b323d27cfd00d1d664e76692a0f" + integrity sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A== + dependencies: + "@babel/types" "^7.24.7" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.24.7", "@babel/helper-plugin-utils@^7.24.8", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz#94ee67e8ec0e5d44ea7baeb51e571bd26af07878" + integrity sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg== + +"@babel/helper-remap-async-to-generator@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.24.7.tgz#b3f0f203628522713849d49403f1a414468be4c7" + integrity sha512-9pKLcTlZ92hNZMQfGCHImUpDOlAgkkpqalWEeftW5FBya75k8Li2ilerxkM/uBEj01iBZXcCIB/bwvDYgWyibA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-wrap-function" "^7.24.7" + +"@babel/helper-replace-supers@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.24.7.tgz#f933b7eed81a1c0265740edc91491ce51250f765" + integrity sha512-qTAxxBM81VEyoAY0TtLrx1oAEJc09ZK67Q9ljQToqCnA+55eNwCORaxlKyu+rNfX86o8OXRUSNUnrtsAZXM9sg== + dependencies: + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-member-expression-to-functions" "^7.24.7" + "@babel/helper-optimise-call-expression" "^7.24.7" + +"@babel/helper-simple-access@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz#bcade8da3aec8ed16b9c4953b74e506b51b5edb3" + integrity sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg== + dependencies: + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/helper-skip-transparent-expression-wrappers@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz#5f8fa83b69ed5c27adc56044f8be2b3ea96669d9" + integrity sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ== + dependencies: + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/helper-split-export-declaration@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz#83949436890e07fa3d6873c61a96e3bbf692d856" + integrity sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA== + dependencies: + "@babel/types" "^7.24.7" + +"@babel/helper-string-parser@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz#5b3329c9a58803d5df425e5785865881a81ca48d" + integrity sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ== + +"@babel/helper-validator-identifier@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db" + integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w== + +"@babel/helper-validator-option@^7.24.7", "@babel/helper-validator-option@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz#3725cdeea8b480e86d34df15304806a06975e33d" + integrity sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q== + +"@babel/helper-wrap-function@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.24.7.tgz#52d893af7e42edca7c6d2c6764549826336aae1f" + integrity sha512-N9JIYk3TD+1vq/wn77YnJOqMtfWhNewNE+DJV4puD2X7Ew9J4JvrzrFDfTfyv5EgEXVy9/Wt8QiOErzEmv5Ifw== + dependencies: + "@babel/helper-function-name" "^7.24.7" + "@babel/template" "^7.24.7" + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/helpers@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.8.tgz#2820d64d5d6686cca8789dd15b074cd862795873" + integrity sha512-gV2265Nkcz7weJJfvDoAEVzC1e2OTDpkGbEsebse8koXUJUXPsCMi7sRo/+SPMuMZ9MtUPnGwITTnQnU5YjyaQ== + dependencies: + "@babel/template" "^7.24.7" + "@babel/types" "^7.24.8" + +"@babel/highlight@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.7.tgz#a05ab1df134b286558aae0ed41e6c5f731bf409d" + integrity sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw== + dependencies: + "@babel/helper-validator-identifier" "^7.24.7" chalk "^2.4.2" js-tokens "^4.0.0" + picocolors "^1.0.0" -"@babel/parser@^7.22.15", "@babel/parser@^7.22.7", "@babel/parser@^7.23.6": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.6.tgz#ba1c9e512bda72a47e285ae42aff9d2a635a9e3b" - integrity sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ== +"@babel/parser@^7.24.7", "@babel/parser@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.8.tgz#58a4dbbcad7eb1d48930524a3fd93d93e9084c6f" + integrity sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w== -"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz#5cd1c87ba9380d0afb78469292c954fee5d2411a" - integrity sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ== +"@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.7.tgz#fd059fd27b184ea2b4c7e646868a9a381bbc3055" + integrity sha512-TiT1ss81W80eQsN+722OaeQMY/G4yTb4G9JrqeiDADs3N8lbPMGldWi9x8tyqCW5NLx1Jh2AvkE6r6QvEltMMQ== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz#f6652bb16b94f8f9c20c50941e16e9756898dc5d" - integrity sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ== +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.7.tgz#468096ca44bbcbe8fcc570574e12eb1950e18107" + integrity sha512-unaQgZ/iRu/By6tsjMZzpeBZjChYfLYry6HrEXPoz3KmfF0sVBQ1l8zKMQ4xRGLWVsjuvB8nQfjNP/DcfEOCsg== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" - "@babel/plugin-transform-optional-chaining" "^7.23.3" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.23.7": - version "7.23.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.23.7.tgz#516462a95d10a9618f197d39ad291a9b47ae1d7b" - integrity sha512-LlRT7HgaifEpQA1ZgLVOIJZZFVPWN5iReq/7/JixwBtwcoeVGDBD53ZV28rrsLYOZs1Y/EHhA8N/Z6aazHR8cw== +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz#e4eabdd5109acc399b38d7999b2ef66fc2022f89" + integrity sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ== dependencies: - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" + "@babel/plugin-transform-optional-chaining" "^7.24.7" + +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.7.tgz#71b21bb0286d5810e63a1538aa901c58e87375ec" + integrity sha512-utA4HuR6F4Vvcr+o4DnjL8fCOlgRFGbeeBEGNg3ZTrLFw6VWG5XmUrvcQ0FjIYMU2ST4XcR2Wsp7t9qOAPnxMg== + dependencies: + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2": version "7.21.0-placeholder-for-preset-env.2" @@ -457,19 +495,19 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-syntax-import-assertions@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.23.3.tgz#9c05a7f592982aff1a2768260ad84bcd3f0c77fc" - integrity sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw== +"@babel/plugin-syntax-import-assertions@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz#2a0b406b5871a20a841240586b1300ce2088a778" + integrity sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-syntax-import-attributes@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.23.3.tgz#992aee922cf04512461d7dae3ff6951b90a2dc06" - integrity sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA== +"@babel/plugin-syntax-import-attributes@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz#b4f9ea95a79e6912480c4b626739f86a076624ca" + integrity sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-syntax-import-meta@^7.10.4": version "7.10.4" @@ -485,12 +523,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-jsx@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz#8f2e4f8a9b5f9aa16067e142c1ac9cd9f810f473" - integrity sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg== +"@babel/plugin-syntax-jsx@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz#39a1fa4a7e3d3d7f34e2acc6be585b718d30e02d" + integrity sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-syntax-logical-assignment-operators@^7.10.4": version "7.10.4" @@ -548,12 +586,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-syntax-typescript@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz#24f460c85dbbc983cd2b9c4994178bcc01df958f" - integrity sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ== +"@babel/plugin-syntax-typescript@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz#58d458271b4d3b6bb27ee6ac9525acbb259bad1c" + integrity sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-syntax-unicode-sets-regex@^7.18.6": version "7.18.6" @@ -563,477 +601,476 @@ "@babel/helper-create-regexp-features-plugin" "^7.18.6" "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-arrow-functions@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.23.3.tgz#94c6dcfd731af90f27a79509f9ab7fb2120fc38b" - integrity sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ== +"@babel/plugin-transform-arrow-functions@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz#4f6886c11e423bd69f3ce51dbf42424a5f275514" + integrity sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-async-generator-functions@^7.23.7": - version "7.23.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.7.tgz#3aa0b4f2fa3788b5226ef9346cf6d16ec61f99cd" - integrity sha512-PdxEpL71bJp1byMG0va5gwQcXHxuEYC/BgI/e88mGTtohbZN28O5Yit0Plkkm/dBzCF/BxmbNcses1RH1T+urA== +"@babel/plugin-transform-async-generator-functions@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.7.tgz#7330a5c50e05181ca52351b8fd01642000c96cfd" + integrity sha512-o+iF77e3u7ZS4AoAuJvapz9Fm001PuD2V3Lp6OSE4FYQke+cSewYtnek+THqGRWyQloRCyvWL1OkyfNEl9vr/g== dependencies: - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-remap-async-to-generator" "^7.22.20" + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-remap-async-to-generator" "^7.24.7" "@babel/plugin-syntax-async-generators" "^7.8.4" -"@babel/plugin-transform-async-to-generator@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.23.3.tgz#d1f513c7a8a506d43f47df2bf25f9254b0b051fa" - integrity sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw== +"@babel/plugin-transform-async-to-generator@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz#72a3af6c451d575842a7e9b5a02863414355bdcc" + integrity sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA== dependencies: - "@babel/helper-module-imports" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-remap-async-to-generator" "^7.22.20" + "@babel/helper-module-imports" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-remap-async-to-generator" "^7.24.7" -"@babel/plugin-transform-block-scoped-functions@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.23.3.tgz#fe1177d715fb569663095e04f3598525d98e8c77" - integrity sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A== +"@babel/plugin-transform-block-scoped-functions@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz#a4251d98ea0c0f399dafe1a35801eaba455bbf1f" + integrity sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-block-scoping@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.4.tgz#b2d38589531c6c80fbe25e6b58e763622d2d3cf5" - integrity sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw== +"@babel/plugin-transform-block-scoping@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.7.tgz#42063e4deb850c7bd7c55e626bf4e7ab48e6ce02" + integrity sha512-Nd5CvgMbWc+oWzBsuaMcbwjJWAcp5qzrbg69SZdHSP7AMY0AbWFqFO0WTFCA1jxhMCwodRwvRec8k0QUbZk7RQ== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-class-properties@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.23.3.tgz#35c377db11ca92a785a718b6aa4e3ed1eb65dc48" - integrity sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg== +"@babel/plugin-transform-class-properties@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.7.tgz#256879467b57b0b68c7ddfc5b76584f398cd6834" + integrity sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w== dependencies: - "@babel/helper-create-class-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-create-class-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-class-static-block@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.23.4.tgz#2a202c8787a8964dd11dfcedf994d36bfc844ab5" - integrity sha512-nsWu/1M+ggti1SOALj3hfx5FXzAY06fwPJsUZD4/A5e1bWi46VUIWtD+kOX6/IdhXGsXBWllLFDSnqSCdUNydQ== +"@babel/plugin-transform-class-static-block@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz#c82027ebb7010bc33c116d4b5044fbbf8c05484d" + integrity sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ== dependencies: - "@babel/helper-create-class-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-create-class-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-syntax-class-static-block" "^7.14.5" -"@babel/plugin-transform-classes@^7.23.5": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.5.tgz#e7a75f815e0c534cc4c9a39c56636c84fc0d64f2" - integrity sha512-jvOTR4nicqYC9yzOHIhXG5emiFEOpappSJAl73SDSEDcybD+Puuze8Tnpb9p9qEyYup24tq891gkaygIFvWDqg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-compilation-targets" "^7.22.15" - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-function-name" "^7.23.0" - "@babel/helper-optimise-call-expression" "^7.22.5" - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-replace-supers" "^7.22.20" - "@babel/helper-split-export-declaration" "^7.22.6" +"@babel/plugin-transform-classes@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.8.tgz#ad23301fe5bc153ca4cf7fb572a9bc8b0b711cf7" + integrity sha512-VXy91c47uujj758ud9wx+OMgheXm4qJfyhj1P18YvlrQkNOSrwsteHk+EFS3OMGfhMhpZa0A+81eE7G4QC+3CA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-compilation-targets" "^7.24.8" + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-function-name" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/helper-replace-supers" "^7.24.7" + "@babel/helper-split-export-declaration" "^7.24.7" globals "^11.1.0" -"@babel/plugin-transform-computed-properties@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz#652e69561fcc9d2b50ba4f7ac7f60dcf65e86474" - integrity sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw== +"@babel/plugin-transform-computed-properties@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz#4cab3214e80bc71fae3853238d13d097b004c707" + integrity sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/template" "^7.22.15" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/template" "^7.24.7" -"@babel/plugin-transform-destructuring@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.3.tgz#8c9ee68228b12ae3dff986e56ed1ba4f3c446311" - integrity sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw== +"@babel/plugin-transform-destructuring@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz#c828e814dbe42a2718a838c2a2e16a408e055550" + integrity sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.8" -"@babel/plugin-transform-dotall-regex@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.23.3.tgz#3f7af6054882ede89c378d0cf889b854a993da50" - integrity sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ== +"@babel/plugin-transform-dotall-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz#5f8bf8a680f2116a7207e16288a5f974ad47a7a0" + integrity sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-duplicate-keys@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.23.3.tgz#664706ca0a5dfe8d066537f99032fc1dc8b720ce" - integrity sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA== +"@babel/plugin-transform-duplicate-keys@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz#dd20102897c9a2324e5adfffb67ff3610359a8ee" + integrity sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-dynamic-import@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.23.4.tgz#c7629e7254011ac3630d47d7f34ddd40ca535143" - integrity sha512-V6jIbLhdJK86MaLh4Jpghi8ho5fGzt3imHOBu/x0jlBaPYqDoWz4RDXjmMOfnh+JWNaQleEAByZLV0QzBT4YQQ== +"@babel/plugin-transform-dynamic-import@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz#4d8b95e3bae2b037673091aa09cd33fecd6419f4" + integrity sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-syntax-dynamic-import" "^7.8.3" -"@babel/plugin-transform-exponentiation-operator@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.23.3.tgz#ea0d978f6b9232ba4722f3dbecdd18f450babd18" - integrity sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ== +"@babel/plugin-transform-exponentiation-operator@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz#b629ee22645f412024297d5245bce425c31f9b0d" + integrity sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ== dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-export-namespace-from@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.23.4.tgz#084c7b25e9a5c8271e987a08cf85807b80283191" - integrity sha512-GzuSBcKkx62dGzZI1WVgTWvkkz84FZO5TC5T8dl/Tht/rAla6Dg/Mz9Yhypg+ezVACf/rgDuQt3kbWEv7LdUDQ== +"@babel/plugin-transform-export-namespace-from@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz#176d52d8d8ed516aeae7013ee9556d540c53f197" + integrity sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" -"@babel/plugin-transform-for-of@^7.23.6": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.6.tgz#81c37e24171b37b370ba6aaffa7ac86bcb46f94e" - integrity sha512-aYH4ytZ0qSuBbpfhuofbg/e96oQ7U2w1Aw/UQmKT+1l39uEhUPoFS3fHevDc1G0OvewyDudfMKY1OulczHzWIw== +"@babel/plugin-transform-for-of@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz#f25b33f72df1d8be76399e1b8f3f9d366eb5bc70" + integrity sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" -"@babel/plugin-transform-function-name@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.23.3.tgz#8f424fcd862bf84cb9a1a6b42bc2f47ed630f8dc" - integrity sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw== +"@babel/plugin-transform-function-name@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.7.tgz#6d8601fbffe665c894440ab4470bc721dd9131d6" + integrity sha512-U9FcnA821YoILngSmYkW6FjyQe2TyZD5pHt4EVIhmcTkrJw/3KqcrRSxuOo5tFZJi7TE19iDyI1u+weTI7bn2w== dependencies: - "@babel/helper-compilation-targets" "^7.22.15" - "@babel/helper-function-name" "^7.23.0" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-compilation-targets" "^7.24.7" + "@babel/helper-function-name" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-json-strings@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.23.4.tgz#a871d9b6bd171976efad2e43e694c961ffa3714d" - integrity sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg== +"@babel/plugin-transform-json-strings@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz#f3e9c37c0a373fee86e36880d45b3664cedaf73a" + integrity sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-syntax-json-strings" "^7.8.3" -"@babel/plugin-transform-literals@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.23.3.tgz#8214665f00506ead73de157eba233e7381f3beb4" - integrity sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ== +"@babel/plugin-transform-literals@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.7.tgz#36b505c1e655151a9d7607799a9988fc5467d06c" + integrity sha512-vcwCbb4HDH+hWi8Pqenwnjy+UiklO4Kt1vfspcQYFhJdpthSnW8XvWGyDZWKNVrVbVViI/S7K9PDJZiUmP2fYQ== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-logical-assignment-operators@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.23.4.tgz#e599f82c51d55fac725f62ce55d3a0886279ecb5" - integrity sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg== +"@babel/plugin-transform-logical-assignment-operators@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz#a58fb6eda16c9dc8f9ff1c7b1ba6deb7f4694cb0" + integrity sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" -"@babel/plugin-transform-member-expression-literals@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.23.3.tgz#e37b3f0502289f477ac0e776b05a833d853cabcc" - integrity sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag== +"@babel/plugin-transform-member-expression-literals@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz#3b4454fb0e302e18ba4945ba3246acb1248315df" + integrity sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-modules-amd@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.3.tgz#e19b55436a1416829df0a1afc495deedfae17f7d" - integrity sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw== +"@babel/plugin-transform-modules-amd@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz#65090ed493c4a834976a3ca1cde776e6ccff32d7" + integrity sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg== dependencies: - "@babel/helper-module-transforms" "^7.23.3" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-module-transforms" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-modules-commonjs@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz#661ae831b9577e52be57dd8356b734f9700b53b4" - integrity sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA== +"@babel/plugin-transform-modules-commonjs@^7.24.7", "@babel/plugin-transform-modules-commonjs@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz#ab6421e564b717cb475d6fff70ae7f103536ea3c" + integrity sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA== dependencies: - "@babel/helper-module-transforms" "^7.23.3" - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-simple-access" "^7.22.5" + "@babel/helper-module-transforms" "^7.24.8" + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/helper-simple-access" "^7.24.7" -"@babel/plugin-transform-modules-systemjs@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.3.tgz#fa7e62248931cb15b9404f8052581c302dd9de81" - integrity sha512-ZxyKGTkF9xT9YJuKQRo19ewf3pXpopuYQd8cDXqNzc3mUNbOME0RKMoZxviQk74hwzfQsEe66dE92MaZbdHKNQ== +"@babel/plugin-transform-modules-systemjs@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.7.tgz#f8012316c5098f6e8dee6ecd58e2bc6f003d0ce7" + integrity sha512-GYQE0tW7YoaN13qFh3O1NCY4MPkUiAH3fiF7UcV/I3ajmDKEdG3l+UOcbAm4zUE3gnvUU+Eni7XrVKo9eO9auw== dependencies: - "@babel/helper-hoist-variables" "^7.22.5" - "@babel/helper-module-transforms" "^7.23.3" - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-validator-identifier" "^7.22.20" + "@babel/helper-hoist-variables" "^7.24.7" + "@babel/helper-module-transforms" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-validator-identifier" "^7.24.7" -"@babel/plugin-transform-modules-umd@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.23.3.tgz#5d4395fccd071dfefe6585a4411aa7d6b7d769e9" - integrity sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg== +"@babel/plugin-transform-modules-umd@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz#edd9f43ec549099620df7df24e7ba13b5c76efc8" + integrity sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A== dependencies: - "@babel/helper-module-transforms" "^7.23.3" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-module-transforms" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-named-capturing-groups-regex@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz#67fe18ee8ce02d57c855185e27e3dc959b2e991f" - integrity sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ== +"@babel/plugin-transform-named-capturing-groups-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz#9042e9b856bc6b3688c0c2e4060e9e10b1460923" + integrity sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.22.5" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-new-target@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.23.3.tgz#5491bb78ed6ac87e990957cea367eab781c4d980" - integrity sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ== +"@babel/plugin-transform-new-target@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz#31ff54c4e0555cc549d5816e4ab39241dfb6ab00" + integrity sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-nullish-coalescing-operator@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.23.4.tgz#45556aad123fc6e52189ea749e33ce090637346e" - integrity sha512-jHE9EVVqHKAQx+VePv5LLGHjmHSJR76vawFPTdlxR/LVJPfOEGxREQwQfjuZEOPTwG92X3LINSh3M40Rv4zpVA== +"@babel/plugin-transform-nullish-coalescing-operator@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz#1de4534c590af9596f53d67f52a92f12db984120" + integrity sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" -"@babel/plugin-transform-numeric-separator@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.23.4.tgz#03d08e3691e405804ecdd19dd278a40cca531f29" - integrity sha512-mps6auzgwjRrwKEZA05cOwuDc9FAzoyFS4ZsG/8F43bTLf/TgkJg7QXOrPO1JO599iA3qgK9MXdMGOEC8O1h6Q== +"@babel/plugin-transform-numeric-separator@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz#bea62b538c80605d8a0fac9b40f48e97efa7de63" + integrity sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-syntax-numeric-separator" "^7.10.4" -"@babel/plugin-transform-object-rest-spread@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.23.4.tgz#2b9c2d26bf62710460bdc0d1730d4f1048361b83" - integrity sha512-9x9K1YyeQVw0iOXJlIzwm8ltobIIv7j2iLyP2jIhEbqPRQ7ScNgwQufU2I0Gq11VjyG4gI4yMXt2VFags+1N3g== +"@babel/plugin-transform-object-rest-spread@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz#d13a2b93435aeb8a197e115221cab266ba6e55d6" + integrity sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q== dependencies: - "@babel/compat-data" "^7.23.3" - "@babel/helper-compilation-targets" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-compilation-targets" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.23.3" + "@babel/plugin-transform-parameters" "^7.24.7" -"@babel/plugin-transform-object-super@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.23.3.tgz#81fdb636dcb306dd2e4e8fd80db5b2362ed2ebcd" - integrity sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA== +"@babel/plugin-transform-object-super@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz#66eeaff7830bba945dd8989b632a40c04ed625be" + integrity sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-replace-supers" "^7.22.20" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-replace-supers" "^7.24.7" -"@babel/plugin-transform-optional-catch-binding@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.23.4.tgz#318066de6dacce7d92fa244ae475aa8d91778017" - integrity sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A== +"@babel/plugin-transform-optional-catch-binding@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz#00eabd883d0dd6a60c1c557548785919b6e717b4" + integrity sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" -"@babel/plugin-transform-optional-chaining@^7.23.3", "@babel/plugin-transform-optional-chaining@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.4.tgz#6acf61203bdfc4de9d4e52e64490aeb3e52bd017" - integrity sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA== +"@babel/plugin-transform-optional-chaining@^7.24.7", "@babel/plugin-transform-optional-chaining@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz#bb02a67b60ff0406085c13d104c99a835cdf365d" + integrity sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" "@babel/plugin-syntax-optional-chaining" "^7.8.3" -"@babel/plugin-transform-parameters@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.23.3.tgz#83ef5d1baf4b1072fa6e54b2b0999a7b2527e2af" - integrity sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw== +"@babel/plugin-transform-parameters@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz#5881f0ae21018400e320fc7eb817e529d1254b68" + integrity sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-private-methods@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.23.3.tgz#b2d7a3c97e278bfe59137a978d53b2c2e038c0e4" - integrity sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g== +"@babel/plugin-transform-private-methods@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.7.tgz#e6318746b2ae70a59d023d5cc1344a2ba7a75f5e" + integrity sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ== dependencies: - "@babel/helper-create-class-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-create-class-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-private-property-in-object@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.4.tgz#3ec711d05d6608fd173d9b8de39872d8dbf68bf5" - integrity sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A== +"@babel/plugin-transform-private-property-in-object@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz#4eec6bc701288c1fab5f72e6a4bbc9d67faca061" + integrity sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA== dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-create-class-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-create-class-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-syntax-private-property-in-object" "^7.14.5" -"@babel/plugin-transform-property-literals@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.23.3.tgz#54518f14ac4755d22b92162e4a852d308a560875" - integrity sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw== +"@babel/plugin-transform-property-literals@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz#f0d2ed8380dfbed949c42d4d790266525d63bbdc" + integrity sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-react-constant-elements@^7.18.12": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.23.3.tgz#5efc001d07ef0f7da0d73c3a86c132f73d28e43c" - integrity sha512-zP0QKq/p6O42OL94udMgSfKXyse4RyJ0JqbQ34zDAONWjyrEsghYEyTSK5FIpmXmCpB55SHokL1cRRKHv8L2Qw== +"@babel/plugin-transform-react-constant-elements@^7.21.3": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.24.7.tgz#b85e8f240b14400277f106c9c9b585d9acf608a1" + integrity sha512-7LidzZfUXyfZ8/buRW6qIIHBY8wAZ1OrY9c/wTr8YhZ6vMPo+Uc/CVFLYY1spZrEQlD4w5u8wjqk5NQ3OVqQKA== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-react-display-name@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.23.3.tgz#70529f034dd1e561045ad3c8152a267f0d7b6200" - integrity sha512-GnvhtVfA2OAtzdX58FJxU19rhoGeQzyVndw3GgtdECQvQFXPEZIOVULHVZGAYmOgmqjXpVpfocAbSjh99V/Fqw== +"@babel/plugin-transform-react-display-name@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.7.tgz#9caff79836803bc666bcfe210aeb6626230c293b" + integrity sha512-H/Snz9PFxKsS1JLI4dJLtnJgCJRoo0AUm3chP6NYr+9En1JMKloheEiLIhlp5MDVznWo+H3AAC1Mc8lmUEpsgg== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-react-jsx-development@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.22.5.tgz#e716b6edbef972a92165cd69d92f1255f7e73e87" - integrity sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A== +"@babel/plugin-transform-react-jsx-development@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.24.7.tgz#eaee12f15a93f6496d852509a850085e6361470b" + integrity sha512-QG9EnzoGn+Qar7rxuW+ZOsbWOt56FvvI93xInqsZDC5fsekx1AlIO4KIJ5M+D0p0SqSH156EpmZyXq630B8OlQ== dependencies: - "@babel/plugin-transform-react-jsx" "^7.22.5" + "@babel/plugin-transform-react-jsx" "^7.24.7" -"@babel/plugin-transform-react-jsx@^7.22.15", "@babel/plugin-transform-react-jsx@^7.22.5": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.23.4.tgz#393f99185110cea87184ea47bcb4a7b0c2e39312" - integrity sha512-5xOpoPguCZCRbo/JeHlloSkTA8Bld1J/E1/kLfD1nsuiW1m8tduTA1ERCgIZokDflX/IBzKcqR3l7VlRgiIfHA== +"@babel/plugin-transform-react-jsx@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.24.7.tgz#17cd06b75a9f0e2bd076503400e7c4b99beedac4" + integrity sha512-+Dj06GDZEFRYvclU6k4bme55GKBEWUmByM/eoKuqg4zTNQHiApWRhQph5fxQB2wAEFvRzL1tOEj1RJ19wJrhoA== dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-module-imports" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/plugin-syntax-jsx" "^7.23.3" - "@babel/types" "^7.23.4" + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-module-imports" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-jsx" "^7.24.7" + "@babel/types" "^7.24.7" -"@babel/plugin-transform-react-pure-annotations@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.23.3.tgz#fabedbdb8ee40edf5da96f3ecfc6958e3783b93c" - integrity sha512-qMFdSS+TUhB7Q/3HVPnEdYJDQIk57jkntAwSuz9xfSE4n+3I+vHYCli3HoHawN1Z3RfCz/y1zXA/JXjG6cVImQ== +"@babel/plugin-transform-react-pure-annotations@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.7.tgz#bdd9d140d1c318b4f28b29a00fb94f97ecab1595" + integrity sha512-PLgBVk3fzbmEjBJ/u8kFzOqS9tUeDjiaWud/rRym/yjCo/M9cASPlnrd2ZmmZpQT40fOOrvR8jh+n8jikrOhNA== dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-regenerator@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.23.3.tgz#141afd4a2057298602069fce7f2dc5173e6c561c" - integrity sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ== +"@babel/plugin-transform-regenerator@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz#021562de4534d8b4b1851759fd7af4e05d2c47f8" + integrity sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.7" regenerator-transform "^0.15.2" -"@babel/plugin-transform-reserved-words@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.23.3.tgz#4130dcee12bd3dd5705c587947eb715da12efac8" - integrity sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg== +"@babel/plugin-transform-reserved-words@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz#80037fe4fbf031fc1125022178ff3938bb3743a4" + integrity sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-transform-runtime@^7.22.9": - version "7.23.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.23.7.tgz#52bbd20054855beb9deae3bee9ceb05289c343e6" - integrity sha512-fa0hnfmiXc9fq/weK34MUV0drz2pOL/vfKWvN7Qw127hiUPabFCUMgAbYWcchRzMJit4o5ARsK/s+5h0249pLw== - dependencies: - "@babel/helper-module-imports" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" - babel-plugin-polyfill-corejs2 "^0.4.7" - babel-plugin-polyfill-corejs3 "^0.8.7" - babel-plugin-polyfill-regenerator "^0.5.4" + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.7.tgz#00a5bfaf8c43cf5c8703a8a6e82b59d9c58f38ca" + integrity sha512-YqXjrk4C+a1kZjewqt+Mmu2UuV1s07y8kqcUf4qYLnoqemhR4gRQikhdAhSVJioMjVTu6Mo6pAbaypEA3jY6fw== + dependencies: + "@babel/helper-module-imports" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + babel-plugin-polyfill-corejs2 "^0.4.10" + babel-plugin-polyfill-corejs3 "^0.10.1" + babel-plugin-polyfill-regenerator "^0.6.1" semver "^6.3.1" -"@babel/plugin-transform-shorthand-properties@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.23.3.tgz#97d82a39b0e0c24f8a981568a8ed851745f59210" - integrity sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg== +"@babel/plugin-transform-shorthand-properties@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz#85448c6b996e122fa9e289746140aaa99da64e73" + integrity sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-spread@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.23.3.tgz#41d17aacb12bde55168403c6f2d6bdca563d362c" - integrity sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg== +"@babel/plugin-transform-spread@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz#e8a38c0fde7882e0fb8f160378f74bd885cc7bb3" + integrity sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" -"@babel/plugin-transform-sticky-regex@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.23.3.tgz#dec45588ab4a723cb579c609b294a3d1bd22ff04" - integrity sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg== +"@babel/plugin-transform-sticky-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz#96ae80d7a7e5251f657b5cf18f1ea6bf926f5feb" + integrity sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-template-literals@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.23.3.tgz#5f0f028eb14e50b5d0f76be57f90045757539d07" - integrity sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg== +"@babel/plugin-transform-template-literals@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz#a05debb4a9072ae8f985bcf77f3f215434c8f8c8" + integrity sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-typeof-symbol@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.23.3.tgz#9dfab97acc87495c0c449014eb9c547d8966bca4" - integrity sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ== +"@babel/plugin-transform-typeof-symbol@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz#383dab37fb073f5bfe6e60c654caac309f92ba1c" + integrity sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.8" -"@babel/plugin-transform-typescript@^7.23.3": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.23.6.tgz#aa36a94e5da8d94339ae3a4e22d40ed287feb34c" - integrity sha512-6cBG5mBvUu4VUD04OHKnYzbuHNP8huDsD3EDqqpIpsswTDoqHCjLoHb6+QgsV1WsT2nipRqCPgxD3LXnEO7XfA== +"@babel/plugin-transform-typescript@^7.24.7": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.8.tgz#c104d6286e04bf7e44b8cba1b686d41bad57eb84" + integrity sha512-CgFgtN61BbdOGCP4fLaAMOPkzWUh6yQZNMr5YSt8uz2cZSSiQONCQFWqsE4NeVfOIhqDOlS9CR3WD91FzMeB2Q== dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-create-class-features-plugin" "^7.23.6" - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/plugin-syntax-typescript" "^7.23.3" + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-create-class-features-plugin" "^7.24.8" + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/plugin-syntax-typescript" "^7.24.7" -"@babel/plugin-transform-unicode-escapes@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.23.3.tgz#1f66d16cab01fab98d784867d24f70c1ca65b925" - integrity sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q== +"@babel/plugin-transform-unicode-escapes@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz#2023a82ced1fb4971630a2e079764502c4148e0e" + integrity sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-unicode-property-regex@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.23.3.tgz#19e234129e5ffa7205010feec0d94c251083d7ad" - integrity sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA== +"@babel/plugin-transform-unicode-property-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz#9073a4cd13b86ea71c3264659590ac086605bbcd" + integrity sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-unicode-regex@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.23.3.tgz#26897708d8f42654ca4ce1b73e96140fbad879dc" - integrity sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw== +"@babel/plugin-transform-unicode-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz#dfc3d4a51127108099b19817c0963be6a2adf19f" + integrity sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-unicode-sets-regex@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.23.3.tgz#4fb6f0a719c2c5859d11f6b55a050cc987f3799e" - integrity sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw== +"@babel/plugin-transform-unicode-sets-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.7.tgz#d40705d67523803a576e29c63cef6e516b858ed9" + integrity sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/preset-env@^7.19.4", "@babel/preset-env@^7.22.9": - version "7.23.7" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.23.7.tgz#e5d69b9f14db8a13bae4d8e5ce7f360973626241" - integrity sha512-SY27X/GtTz/L4UryMNJ6p4fH4nsgWbz84y9FE0bQeWJP6O5BhgVCt53CotQKHCOeXJel8VyhlhujhlltKms/CA== +"@babel/preset-env@^7.20.2", "@babel/preset-env@^7.22.9": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.24.8.tgz#e0db94d7f17d6f0e2564e8d29190bc8cdacec2d1" + integrity sha512-vObvMZB6hNWuDxhSaEPTKCwcqkAIuDtE+bQGn4XMXne1DSLzFVY8Vmj1bm+mUQXYNN8NmaQEO+r8MMbzPr1jBQ== dependencies: - "@babel/compat-data" "^7.23.5" - "@babel/helper-compilation-targets" "^7.23.6" - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-validator-option" "^7.23.5" - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.23.3" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.23.3" - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly" "^7.23.7" + "@babel/compat-data" "^7.24.8" + "@babel/helper-compilation-targets" "^7.24.8" + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/helper-validator-option" "^7.24.8" + "@babel/plugin-bugfix-firefox-class-in-computed-class-key" "^7.24.7" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.24.7" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.24.7" + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly" "^7.24.7" "@babel/plugin-proposal-private-property-in-object" "7.21.0-placeholder-for-preset-env.2" "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-syntax-class-properties" "^7.12.13" "@babel/plugin-syntax-class-static-block" "^7.14.5" "@babel/plugin-syntax-dynamic-import" "^7.8.3" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - "@babel/plugin-syntax-import-assertions" "^7.23.3" - "@babel/plugin-syntax-import-attributes" "^7.23.3" + "@babel/plugin-syntax-import-assertions" "^7.24.7" + "@babel/plugin-syntax-import-attributes" "^7.24.7" "@babel/plugin-syntax-import-meta" "^7.10.4" "@babel/plugin-syntax-json-strings" "^7.8.3" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" @@ -1045,59 +1082,59 @@ "@babel/plugin-syntax-private-property-in-object" "^7.14.5" "@babel/plugin-syntax-top-level-await" "^7.14.5" "@babel/plugin-syntax-unicode-sets-regex" "^7.18.6" - "@babel/plugin-transform-arrow-functions" "^7.23.3" - "@babel/plugin-transform-async-generator-functions" "^7.23.7" - "@babel/plugin-transform-async-to-generator" "^7.23.3" - "@babel/plugin-transform-block-scoped-functions" "^7.23.3" - "@babel/plugin-transform-block-scoping" "^7.23.4" - "@babel/plugin-transform-class-properties" "^7.23.3" - "@babel/plugin-transform-class-static-block" "^7.23.4" - "@babel/plugin-transform-classes" "^7.23.5" - "@babel/plugin-transform-computed-properties" "^7.23.3" - "@babel/plugin-transform-destructuring" "^7.23.3" - "@babel/plugin-transform-dotall-regex" "^7.23.3" - "@babel/plugin-transform-duplicate-keys" "^7.23.3" - "@babel/plugin-transform-dynamic-import" "^7.23.4" - "@babel/plugin-transform-exponentiation-operator" "^7.23.3" - "@babel/plugin-transform-export-namespace-from" "^7.23.4" - "@babel/plugin-transform-for-of" "^7.23.6" - "@babel/plugin-transform-function-name" "^7.23.3" - "@babel/plugin-transform-json-strings" "^7.23.4" - "@babel/plugin-transform-literals" "^7.23.3" - "@babel/plugin-transform-logical-assignment-operators" "^7.23.4" - "@babel/plugin-transform-member-expression-literals" "^7.23.3" - "@babel/plugin-transform-modules-amd" "^7.23.3" - "@babel/plugin-transform-modules-commonjs" "^7.23.3" - "@babel/plugin-transform-modules-systemjs" "^7.23.3" - "@babel/plugin-transform-modules-umd" "^7.23.3" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.22.5" - "@babel/plugin-transform-new-target" "^7.23.3" - "@babel/plugin-transform-nullish-coalescing-operator" "^7.23.4" - "@babel/plugin-transform-numeric-separator" "^7.23.4" - "@babel/plugin-transform-object-rest-spread" "^7.23.4" - "@babel/plugin-transform-object-super" "^7.23.3" - "@babel/plugin-transform-optional-catch-binding" "^7.23.4" - "@babel/plugin-transform-optional-chaining" "^7.23.4" - "@babel/plugin-transform-parameters" "^7.23.3" - "@babel/plugin-transform-private-methods" "^7.23.3" - "@babel/plugin-transform-private-property-in-object" "^7.23.4" - "@babel/plugin-transform-property-literals" "^7.23.3" - "@babel/plugin-transform-regenerator" "^7.23.3" - "@babel/plugin-transform-reserved-words" "^7.23.3" - "@babel/plugin-transform-shorthand-properties" "^7.23.3" - "@babel/plugin-transform-spread" "^7.23.3" - "@babel/plugin-transform-sticky-regex" "^7.23.3" - "@babel/plugin-transform-template-literals" "^7.23.3" - "@babel/plugin-transform-typeof-symbol" "^7.23.3" - "@babel/plugin-transform-unicode-escapes" "^7.23.3" - "@babel/plugin-transform-unicode-property-regex" "^7.23.3" - "@babel/plugin-transform-unicode-regex" "^7.23.3" - "@babel/plugin-transform-unicode-sets-regex" "^7.23.3" + "@babel/plugin-transform-arrow-functions" "^7.24.7" + "@babel/plugin-transform-async-generator-functions" "^7.24.7" + "@babel/plugin-transform-async-to-generator" "^7.24.7" + "@babel/plugin-transform-block-scoped-functions" "^7.24.7" + "@babel/plugin-transform-block-scoping" "^7.24.7" + "@babel/plugin-transform-class-properties" "^7.24.7" + "@babel/plugin-transform-class-static-block" "^7.24.7" + "@babel/plugin-transform-classes" "^7.24.8" + "@babel/plugin-transform-computed-properties" "^7.24.7" + "@babel/plugin-transform-destructuring" "^7.24.8" + "@babel/plugin-transform-dotall-regex" "^7.24.7" + "@babel/plugin-transform-duplicate-keys" "^7.24.7" + "@babel/plugin-transform-dynamic-import" "^7.24.7" + "@babel/plugin-transform-exponentiation-operator" "^7.24.7" + "@babel/plugin-transform-export-namespace-from" "^7.24.7" + "@babel/plugin-transform-for-of" "^7.24.7" + "@babel/plugin-transform-function-name" "^7.24.7" + "@babel/plugin-transform-json-strings" "^7.24.7" + "@babel/plugin-transform-literals" "^7.24.7" + "@babel/plugin-transform-logical-assignment-operators" "^7.24.7" + "@babel/plugin-transform-member-expression-literals" "^7.24.7" + "@babel/plugin-transform-modules-amd" "^7.24.7" + "@babel/plugin-transform-modules-commonjs" "^7.24.8" + "@babel/plugin-transform-modules-systemjs" "^7.24.7" + "@babel/plugin-transform-modules-umd" "^7.24.7" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.24.7" + "@babel/plugin-transform-new-target" "^7.24.7" + "@babel/plugin-transform-nullish-coalescing-operator" "^7.24.7" + "@babel/plugin-transform-numeric-separator" "^7.24.7" + "@babel/plugin-transform-object-rest-spread" "^7.24.7" + "@babel/plugin-transform-object-super" "^7.24.7" + "@babel/plugin-transform-optional-catch-binding" "^7.24.7" + "@babel/plugin-transform-optional-chaining" "^7.24.8" + "@babel/plugin-transform-parameters" "^7.24.7" + "@babel/plugin-transform-private-methods" "^7.24.7" + "@babel/plugin-transform-private-property-in-object" "^7.24.7" + "@babel/plugin-transform-property-literals" "^7.24.7" + "@babel/plugin-transform-regenerator" "^7.24.7" + "@babel/plugin-transform-reserved-words" "^7.24.7" + "@babel/plugin-transform-shorthand-properties" "^7.24.7" + "@babel/plugin-transform-spread" "^7.24.7" + "@babel/plugin-transform-sticky-regex" "^7.24.7" + "@babel/plugin-transform-template-literals" "^7.24.7" + "@babel/plugin-transform-typeof-symbol" "^7.24.8" + "@babel/plugin-transform-unicode-escapes" "^7.24.7" + "@babel/plugin-transform-unicode-property-regex" "^7.24.7" + "@babel/plugin-transform-unicode-regex" "^7.24.7" + "@babel/plugin-transform-unicode-sets-regex" "^7.24.7" "@babel/preset-modules" "0.1.6-no-external-plugins" - babel-plugin-polyfill-corejs2 "^0.4.7" - babel-plugin-polyfill-corejs3 "^0.8.7" - babel-plugin-polyfill-regenerator "^0.5.4" - core-js-compat "^3.31.0" + babel-plugin-polyfill-corejs2 "^0.4.10" + babel-plugin-polyfill-corejs3 "^0.10.4" + babel-plugin-polyfill-regenerator "^0.6.1" + core-js-compat "^3.37.1" semver "^6.3.1" "@babel/preset-modules@0.1.6-no-external-plugins": @@ -1110,27 +1147,27 @@ esutils "^2.0.2" "@babel/preset-react@^7.18.6", "@babel/preset-react@^7.22.5": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.23.3.tgz#f73ca07e7590f977db07eb54dbe46538cc015709" - integrity sha512-tbkHOS9axH6Ysf2OUEqoSZ6T3Fa2SrNH6WTWSPBboxKzdxNc9qOICeLXkNG0ZEwbQ1HY8liwOce4aN/Ceyuq6w== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-validator-option" "^7.22.15" - "@babel/plugin-transform-react-display-name" "^7.23.3" - "@babel/plugin-transform-react-jsx" "^7.22.15" - "@babel/plugin-transform-react-jsx-development" "^7.22.5" - "@babel/plugin-transform-react-pure-annotations" "^7.23.3" - -"@babel/preset-typescript@^7.18.6", "@babel/preset-typescript@^7.22.5": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.23.3.tgz#14534b34ed5b6d435aa05f1ae1c5e7adcc01d913" - integrity sha512-17oIGVlqz6CchO9RFYn5U6ZpWRZIngayYCtrPRSgANSwC2V1Jb+iP74nVxzzXJte8b8BYxrL1yY96xfhTBrNNQ== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-validator-option" "^7.22.15" - "@babel/plugin-syntax-jsx" "^7.23.3" - "@babel/plugin-transform-modules-commonjs" "^7.23.3" - "@babel/plugin-transform-typescript" "^7.23.3" + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.24.7.tgz#480aeb389b2a798880bf1f889199e3641cbb22dc" + integrity sha512-AAH4lEkpmzFWrGVlHaxJB7RLH21uPQ9+He+eFLWHmF9IuFQVugz8eAsamaW0DXRrTfco5zj1wWtpdcXJUOfsag== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-validator-option" "^7.24.7" + "@babel/plugin-transform-react-display-name" "^7.24.7" + "@babel/plugin-transform-react-jsx" "^7.24.7" + "@babel/plugin-transform-react-jsx-development" "^7.24.7" + "@babel/plugin-transform-react-pure-annotations" "^7.24.7" + +"@babel/preset-typescript@^7.21.0", "@babel/preset-typescript@^7.22.5": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.24.7.tgz#66cd86ea8f8c014855671d5ea9a737139cbbfef1" + integrity sha512-SyXRe3OdWwIwalxDg5UtJnJQO+YPcTfwiIY2B0Xlddh9o7jpWLvv8X1RthIeDOxQ+O1ML5BLPCONToObyVQVuQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-validator-option" "^7.24.7" + "@babel/plugin-syntax-jsx" "^7.24.7" + "@babel/plugin-transform-modules-commonjs" "^7.24.7" + "@babel/plugin-transform-typescript" "^7.24.7" "@babel/regjsgen@^0.8.0": version "0.8.0" @@ -1138,52 +1175,52 @@ integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== "@babel/runtime-corejs3@^7.22.6": - version "7.23.7" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.23.7.tgz#2c3d323d21569f2950c9126780bfa400632360bd" - integrity sha512-ER55qzLREVA5YxeyQ3Qu48tgsF2ZrFjFjUS6V6wF0cikSw+goBJgB9PBRM1T6+Ah4iiM+sxmfS/Sy/jdzFfhiQ== + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.24.8.tgz#c0ae5a1c380f8442920866d0cc51de8024507e28" + integrity sha512-DXG/BhegtMHhnN7YPIvxWd303/9aXvYFD1TjNL3CD6tUrhI2LVsg3Lck0aql5TRH29n4sj3emcROypkZVUfSuA== dependencies: core-js-pure "^3.30.2" regenerator-runtime "^0.14.0" -"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.22.6", "@babel/runtime@^7.8.4": - version "7.23.7" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.7.tgz#dd7c88deeb218a0f8bd34d5db1aa242e0f203193" - integrity sha512-w06OXVOFso7LcbzMiDGt+3X7Rh7Ho8MmgPoWU3rarH+8upf+wSU/grlGbWzQyr3DkdN6ZeuMFjpdwW0Q+HxobA== +"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.22.6", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.8.tgz#5d958c3827b13cc6d05e038c07fb2e5e3420d82e" + integrity sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA== dependencies: regenerator-runtime "^0.14.0" -"@babel/template@^7.22.15": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38" - integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w== - dependencies: - "@babel/code-frame" "^7.22.13" - "@babel/parser" "^7.22.15" - "@babel/types" "^7.22.15" - -"@babel/traverse@^7.22.8", "@babel/traverse@^7.23.7": - version "7.23.7" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.7.tgz#9a7bf285c928cb99b5ead19c3b1ce5b310c9c305" - integrity sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg== - dependencies: - "@babel/code-frame" "^7.23.5" - "@babel/generator" "^7.23.6" - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-function-name" "^7.23.0" - "@babel/helper-hoist-variables" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/parser" "^7.23.6" - "@babel/types" "^7.23.6" +"@babel/template@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.7.tgz#02efcee317d0609d2c07117cb70ef8fb17ab7315" + integrity sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig== + dependencies: + "@babel/code-frame" "^7.24.7" + "@babel/parser" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/traverse@^7.22.8", "@babel/traverse@^7.24.7", "@babel/traverse@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.8.tgz#6c14ed5232b7549df3371d820fbd9abfcd7dfab7" + integrity sha512-t0P1xxAPzEDcEPmjprAQq19NWum4K0EQPjMwZQZbHt+GiZqvjCHjj755Weq1YRPVzBI+3zSfvScfpnuIecVFJQ== + dependencies: + "@babel/code-frame" "^7.24.7" + "@babel/generator" "^7.24.8" + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-function-name" "^7.24.7" + "@babel/helper-hoist-variables" "^7.24.7" + "@babel/helper-split-export-declaration" "^7.24.7" + "@babel/parser" "^7.24.8" + "@babel/types" "^7.24.8" debug "^4.3.1" globals "^11.1.0" -"@babel/types@^7.20.0", "@babel/types@^7.22.15", "@babel/types@^7.22.19", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.4", "@babel/types@^7.23.6", "@babel/types@^7.4.4": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.6.tgz#be33fdb151e1f5a56877d704492c240fc71c7ccd" - integrity sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg== +"@babel/types@^7.21.3", "@babel/types@^7.24.7", "@babel/types@^7.24.8", "@babel/types@^7.24.9", "@babel/types@^7.4.4": + version "7.24.9" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.9.tgz#228ce953d7b0d16646e755acf204f4cf3d08cc73" + integrity sha512-xm8XrMKz0IlUdocVbYJe0Z9xEgidU7msskG8BbhnTPK/HZ2z/7FP7ykqPgrUH+C+r414mNfNWam1f2vqOjqjYQ== dependencies: - "@babel/helper-string-parser" "^7.23.4" - "@babel/helper-validator-identifier" "^7.22.20" + "@babel/helper-string-parser" "^7.24.8" + "@babel/helper-validator-identifier" "^7.24.7" to-fast-properties "^2.0.0" "@colors/colors@1.5.0": @@ -1191,30 +1228,85 @@ resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== +"@cookbookdev/docsbot@^4.21.1": + version "4.21.1" + resolved "https://registry.yarnpkg.com/@cookbookdev/docsbot/-/docsbot-4.21.1.tgz#cfd9fc24ebff06182106092ea36dca513f537fee" + integrity sha512-RT9K5K021W6HtO5VavH4BP+TNZ0W0fRo6yeyySvCRRnWhOK38nuvVVU9hg09eSD2miE7fGXDrYLlG9WE/j1OEA== + dependencies: + "@headlessui/react" "^1.7.18" + "@headlessui/tailwindcss" "^0.2.0" + "@monaco-editor/react" "^4.6.0" + "@radix-ui/react-avatar" "^1.0.4" + "@radix-ui/react-checkbox" "^1.0.4" + "@radix-ui/react-collapsible" "^1.0.3" + "@radix-ui/react-dialog" "^1.0.5" + "@radix-ui/react-dropdown-menu" "^2.0.6" + "@radix-ui/react-hover-card" "^1.0.7" + "@radix-ui/react-icons" "^1.3.0" + "@radix-ui/react-label" "^2.0.2" + "@radix-ui/react-popover" "^1.0.7" + "@radix-ui/react-scroll-area" "^1.0.5" + "@radix-ui/react-select" "^2.0.0" + "@radix-ui/react-separator" "^1.0.3" + "@radix-ui/react-slider" "^1.1.2" + "@radix-ui/react-slot" "^1.0.2" + "@radix-ui/react-tabs" "^1.0.4" + "@radix-ui/react-toast" "^1.1.5" + "@radix-ui/react-tooltip" "^1.0.7" + "@tailwindcss/line-clamp" "^0.4.4" + "@tanstack/react-table" "^8.11.7" + "@vercel/edge" "^1.1.1" + can-dom-mutate "^2.0.9" + clsx "^2.1.0" + cmdk-react17 "^1.0.0" + color2k "^2.0.3" + fflate "^0.8.2" + file-saver "^2.0.5" + framer-motion "^6.5.1" + idb "^8.0.0" + jszip "^3.10.1" + nanoid "^5.0.5" + posthog-js "^1.136.8" + prop-types "^15.8.1" + react-complex-tree "^2.3.7" + react-markdown "^9.0.1" + react-resizable-panels "2.0.19" + react-syntax-highlighter "^15.5.0" + recharts "^2.12.4" + remark-gfm "^4.0.0" + solc "^0.8.25" + sonner "^1.4.41" + styled-components "^6.1.8" + swr "^2.2.5" + tailwind-merge "^2.2.1" + tailwindcss-animate "^1.0.7" + use-sync-external-store "^1.2.0" + viem "2.9.16" + "@discoveryjs/json-ext@0.5.7": version "0.5.7" resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== -"@docsearch/css@3.5.2": - version "3.5.2" - resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-3.5.2.tgz#610f47b48814ca94041df969d9fcc47b91fc5aac" - integrity sha512-SPiDHaWKQZpwR2siD0KQUwlStvIAnEyK6tAE2h2Wuoq8ue9skzhlyVQ1ddzOxX6khULnAALDiR/isSF3bnuciA== +"@docsearch/css@3.6.1": + version "3.6.1" + resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-3.6.1.tgz#f0a728ecb486c81f2d282650fc1820c914913408" + integrity sha512-VtVb5DS+0hRIprU2CO6ZQjK2Zg4QU5HrDM1+ix6rT0umsYvFvatMAnf97NHZlVWDaaLlx7GRfR/7FikANiM2Fg== "@docsearch/react@^3.5.2": - version "3.5.2" - resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-3.5.2.tgz#2e6bbee00eb67333b64906352734da6aef1232b9" - integrity sha512-9Ahcrs5z2jq/DcAvYtvlqEBHImbm4YJI8M9y0x6Tqg598P40HTEkX7hsMcIuThI+hTFxRGZ9hll0Wygm2yEjng== + version "3.6.1" + resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-3.6.1.tgz#0f826df08693293806d64277d6d9c38636211b97" + integrity sha512-qXZkEPvybVhSXj0K7U3bXc233tk5e8PfhoZ6MhPOiik/qUQxYC+Dn9DnoS7CxHQQhHfCvTiN0eY9M12oRghEXw== dependencies: "@algolia/autocomplete-core" "1.9.3" "@algolia/autocomplete-preset-algolia" "1.9.3" - "@docsearch/css" "3.5.2" + "@docsearch/css" "3.6.1" algoliasearch "^4.19.1" -"@docusaurus/core@3.0.1", "@docusaurus/core@^3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@docusaurus/core/-/core-3.0.1.tgz#ad9a66b20802ea81b25e65db75d4ca952eda7e01" - integrity sha512-CXrLpOnW+dJdSv8M5FAJ3JBwXtL6mhUWxFA8aS0ozK6jBG/wgxERk5uvH28fCeFxOGbAT9v1e9dOMo1X2IEVhQ== +"@docusaurus/core@3.4.0", "@docusaurus/core@^3.0.1": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@docusaurus/core/-/core-3.4.0.tgz#bdbf1af4b2f25d1bf4a5b62ec6137d84c821cb3c" + integrity sha512-g+0wwmN2UJsBqy2fQRQ6fhXruoEa62JDeEa5d8IdTJlMoaDaEDfHh7WjwGRn4opuTQWpjAwP/fbcgyHKlE+64w== dependencies: "@babel/core" "^7.23.3" "@babel/generator" "^7.23.3" @@ -1226,15 +1318,12 @@ "@babel/runtime" "^7.22.6" "@babel/runtime-corejs3" "^7.22.6" "@babel/traverse" "^7.22.8" - "@docusaurus/cssnano-preset" "3.0.1" - "@docusaurus/logger" "3.0.1" - "@docusaurus/mdx-loader" "3.0.1" - "@docusaurus/react-loadable" "5.5.2" - "@docusaurus/utils" "3.0.1" - "@docusaurus/utils-common" "3.0.1" - "@docusaurus/utils-validation" "3.0.1" - "@slorber/static-site-generator-webpack-plugin" "^4.0.7" - "@svgr/webpack" "^6.5.1" + "@docusaurus/cssnano-preset" "3.4.0" + "@docusaurus/logger" "3.4.0" + "@docusaurus/mdx-loader" "3.4.0" + "@docusaurus/utils" "3.4.0" + "@docusaurus/utils-common" "3.4.0" + "@docusaurus/utils-validation" "3.4.0" autoprefixer "^10.4.14" babel-loader "^9.1.3" babel-plugin-dynamic-import-node "^2.3.3" @@ -1248,12 +1337,13 @@ copy-webpack-plugin "^11.0.0" core-js "^3.31.1" css-loader "^6.8.1" - css-minimizer-webpack-plugin "^4.2.2" - cssnano "^5.1.15" + css-minimizer-webpack-plugin "^5.0.1" + cssnano "^6.1.2" del "^6.1.1" detect-port "^1.5.1" escape-html "^1.0.3" eta "^2.2.0" + eval "^0.1.8" file-loader "^6.2.0" fs-extra "^11.1.1" html-minifier-terser "^7.2.0" @@ -1262,12 +1352,13 @@ leven "^3.1.0" lodash "^4.17.21" mini-css-extract-plugin "^2.7.6" + p-map "^4.0.0" postcss "^8.4.26" postcss-loader "^7.3.3" prompts "^2.4.2" react-dev-utils "^12.0.1" react-helmet-async "^1.3.0" - react-loadable "npm:@docusaurus/react-loadable@5.5.2" + react-loadable "npm:@docusaurus/react-loadable@6.0.0" react-loadable-ssr-addon-v5-slorber "^1.0.1" react-router "^5.3.4" react-router-config "^5.1.1" @@ -1286,34 +1377,32 @@ webpack-merge "^5.9.0" webpackbar "^5.0.2" -"@docusaurus/cssnano-preset@3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@docusaurus/cssnano-preset/-/cssnano-preset-3.0.1.tgz#22fbf2e97389e338747864baf011743846e8fd26" - integrity sha512-wjuXzkHMW+ig4BD6Ya1Yevx9UJadO4smNZCEljqBoQfIQrQskTswBs7lZ8InHP7mCt273a/y/rm36EZhqJhknQ== +"@docusaurus/cssnano-preset@3.4.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@docusaurus/cssnano-preset/-/cssnano-preset-3.4.0.tgz#dc7922b3bbeabcefc9b60d0161680d81cf72c368" + integrity sha512-qwLFSz6v/pZHy/UP32IrprmH5ORce86BGtN0eBtG75PpzQJAzp9gefspox+s8IEOr0oZKuQ/nhzZ3xwyc3jYJQ== dependencies: - cssnano-preset-advanced "^5.3.10" - postcss "^8.4.26" - postcss-sort-media-queries "^4.4.1" + cssnano-preset-advanced "^6.1.2" + postcss "^8.4.38" + postcss-sort-media-queries "^5.2.0" tslib "^2.6.0" -"@docusaurus/logger@3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@docusaurus/logger/-/logger-3.0.1.tgz#06f512eef6c6ae4e2da63064257e01b1cdc41a82" - integrity sha512-I5L6Nk8OJzkVA91O2uftmo71LBSxe1vmOn9AMR6JRCzYeEBrqneWMH02AqMvjJ2NpMiviO+t0CyPjyYV7nxCWQ== +"@docusaurus/logger@3.4.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@docusaurus/logger/-/logger-3.4.0.tgz#8b0ac05c7f3dac2009066e2f964dee8209a77403" + integrity sha512-bZwkX+9SJ8lB9kVRkXw+xvHYSMGG4bpYHKGXeXFvyVc79NMeeBSGgzd4TQLHH+DYeOJoCdl8flrFJVxlZ0wo/Q== dependencies: chalk "^4.1.2" tslib "^2.6.0" -"@docusaurus/mdx-loader@3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@docusaurus/mdx-loader/-/mdx-loader-3.0.1.tgz#89f221e5bcc570983fd61d7ab56d6fbe36810b59" - integrity sha512-ldnTmvnvlrONUq45oKESrpy+lXtbnTcTsFkOTIDswe5xx5iWJjt6eSa0f99ZaWlnm24mlojcIGoUWNCS53qVlQ== +"@docusaurus/mdx-loader@3.4.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@docusaurus/mdx-loader/-/mdx-loader-3.4.0.tgz#483d7ab57928fdbb5c8bd1678098721a930fc5f6" + integrity sha512-kSSbrrk4nTjf4d+wtBA9H+FGauf2gCax89kV8SUSJu3qaTdSIKdWERlngsiHaCFgZ7laTJ8a67UFf+xlFPtuTw== dependencies: - "@babel/parser" "^7.22.7" - "@babel/traverse" "^7.22.8" - "@docusaurus/logger" "3.0.1" - "@docusaurus/utils" "3.0.1" - "@docusaurus/utils-validation" "3.0.1" + "@docusaurus/logger" "3.4.0" + "@docusaurus/utils" "3.4.0" + "@docusaurus/utils-validation" "3.4.0" "@mdx-js/mdx" "^3.0.0" "@slorber/remark-comment" "^1.0.0" escape-html "^1.0.3" @@ -1336,32 +1425,31 @@ vfile "^6.0.1" webpack "^5.88.1" -"@docusaurus/module-type-aliases@3.0.1", "@docusaurus/module-type-aliases@^3.0.0": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@docusaurus/module-type-aliases/-/module-type-aliases-3.0.1.tgz#d45990fe377d7ffaa68841cf89401188a5d65293" - integrity sha512-DEHpeqUDsLynl3AhQQiO7AbC7/z/lBra34jTcdYuvp9eGm01pfH1wTVq8YqWZq6Jyx0BgcVl/VJqtE9StRd9Ag== +"@docusaurus/module-type-aliases@3.4.0", "@docusaurus/module-type-aliases@^3.0.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@docusaurus/module-type-aliases/-/module-type-aliases-3.4.0.tgz#2653bde58fc1aa3dbc626a6c08cfb63a37ae1bb8" + integrity sha512-A1AyS8WF5Bkjnb8s+guTDuYmUiwJzNrtchebBHpc0gz0PyHJNMaybUlSrmJjHVcGrya0LKI4YcR3lBDQfXRYLw== dependencies: - "@docusaurus/react-loadable" "5.5.2" - "@docusaurus/types" "3.0.1" + "@docusaurus/types" "3.4.0" "@types/history" "^4.7.11" "@types/react" "*" "@types/react-router-config" "*" "@types/react-router-dom" "*" react-helmet-async "*" - react-loadable "npm:@docusaurus/react-loadable@5.5.2" - -"@docusaurus/plugin-content-blog@3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.0.1.tgz#dee6147187c2d8b634252444d60312d12c9571a6" - integrity sha512-cLOvtvAyaMQFLI8vm4j26svg3ktxMPSXpuUJ7EERKoGbfpJSsgtowNHcRsaBVmfuCsRSk1HZ/yHBsUkTmHFEsg== - dependencies: - "@docusaurus/core" "3.0.1" - "@docusaurus/logger" "3.0.1" - "@docusaurus/mdx-loader" "3.0.1" - "@docusaurus/types" "3.0.1" - "@docusaurus/utils" "3.0.1" - "@docusaurus/utils-common" "3.0.1" - "@docusaurus/utils-validation" "3.0.1" + react-loadable "npm:@docusaurus/react-loadable@6.0.0" + +"@docusaurus/plugin-content-blog@3.4.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.4.0.tgz#6373632fdbababbda73a13c4a08f907d7de8f007" + integrity sha512-vv6ZAj78ibR5Jh7XBUT4ndIjmlAxkijM3Sx5MAAzC1gyv0vupDQNhzuFg1USQmQVj3P5I6bquk12etPV3LJ+Xw== + dependencies: + "@docusaurus/core" "3.4.0" + "@docusaurus/logger" "3.4.0" + "@docusaurus/mdx-loader" "3.4.0" + "@docusaurus/types" "3.4.0" + "@docusaurus/utils" "3.4.0" + "@docusaurus/utils-common" "3.4.0" + "@docusaurus/utils-validation" "3.4.0" cheerio "^1.0.0-rc.12" feed "^4.2.2" fs-extra "^11.1.1" @@ -1373,18 +1461,19 @@ utility-types "^3.10.0" webpack "^5.88.1" -"@docusaurus/plugin-content-docs@3.0.1", "@docusaurus/plugin-content-docs@^3.0.0": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.0.1.tgz#d9b1884562186573d5c4521ac3546b68512c1126" - integrity sha512-dRfAOA5Ivo+sdzzJGXEu33yAtvGg8dlZkvt/NEJ7nwi1F2j4LEdsxtfX2GKeETB2fP6XoGNSQnFXqa2NYGrHFg== - dependencies: - "@docusaurus/core" "3.0.1" - "@docusaurus/logger" "3.0.1" - "@docusaurus/mdx-loader" "3.0.1" - "@docusaurus/module-type-aliases" "3.0.1" - "@docusaurus/types" "3.0.1" - "@docusaurus/utils" "3.0.1" - "@docusaurus/utils-validation" "3.0.1" +"@docusaurus/plugin-content-docs@3.4.0", "@docusaurus/plugin-content-docs@^3.1.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.4.0.tgz#3088973f72169a2a6d533afccec7153c8720d332" + integrity sha512-HkUCZffhBo7ocYheD9oZvMcDloRnGhBMOZRyVcAQRFmZPmNqSyISlXA1tQCIxW+r478fty97XXAGjNYzBjpCsg== + dependencies: + "@docusaurus/core" "3.4.0" + "@docusaurus/logger" "3.4.0" + "@docusaurus/mdx-loader" "3.4.0" + "@docusaurus/module-type-aliases" "3.4.0" + "@docusaurus/types" "3.4.0" + "@docusaurus/utils" "3.4.0" + "@docusaurus/utils-common" "3.4.0" + "@docusaurus/utils-validation" "3.4.0" "@types/react-router-config" "^5.0.7" combine-promises "^1.1.0" fs-extra "^11.1.1" @@ -1394,122 +1483,114 @@ utility-types "^3.10.0" webpack "^5.88.1" -"@docusaurus/plugin-content-pages@3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.0.1.tgz#27e6424c77173f867760efe53f848bbab8849ea6" - integrity sha512-oP7PoYizKAXyEttcvVzfX3OoBIXEmXTMzCdfmC4oSwjG4SPcJsRge3mmI6O8jcZBgUPjIzXD21bVGWEE1iu8gg== - dependencies: - "@docusaurus/core" "3.0.1" - "@docusaurus/mdx-loader" "3.0.1" - "@docusaurus/types" "3.0.1" - "@docusaurus/utils" "3.0.1" - "@docusaurus/utils-validation" "3.0.1" +"@docusaurus/plugin-content-pages@3.4.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.4.0.tgz#1846172ca0355c7d32a67ef8377750ce02bbb8ad" + integrity sha512-h2+VN/0JjpR8fIkDEAoadNjfR3oLzB+v1qSXbIAKjQ46JAHx3X22n9nqS+BWSQnTnp1AjkjSvZyJMekmcwxzxg== + dependencies: + "@docusaurus/core" "3.4.0" + "@docusaurus/mdx-loader" "3.4.0" + "@docusaurus/types" "3.4.0" + "@docusaurus/utils" "3.4.0" + "@docusaurus/utils-validation" "3.4.0" fs-extra "^11.1.1" tslib "^2.6.0" webpack "^5.88.1" -"@docusaurus/plugin-debug@3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-debug/-/plugin-debug-3.0.1.tgz#886b5dd03c066e970484ca251c1b79613df90700" - integrity sha512-09dxZMdATky4qdsZGzhzlUvvC+ilQ2hKbYF+wez+cM2mGo4qHbv8+qKXqxq0CQZyimwlAOWQLoSozIXU0g0i7g== +"@docusaurus/plugin-debug@3.4.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-debug/-/plugin-debug-3.4.0.tgz#74e4ec5686fa314c26f3ac150bacadbba7f06948" + integrity sha512-uV7FDUNXGyDSD3PwUaf5YijX91T5/H9SX4ErEcshzwgzWwBtK37nUWPU3ZLJfeTavX3fycTOqk9TglpOLaWkCg== dependencies: - "@docusaurus/core" "3.0.1" - "@docusaurus/types" "3.0.1" - "@docusaurus/utils" "3.0.1" + "@docusaurus/core" "3.4.0" + "@docusaurus/types" "3.4.0" + "@docusaurus/utils" "3.4.0" fs-extra "^11.1.1" react-json-view-lite "^1.2.0" tslib "^2.6.0" -"@docusaurus/plugin-google-analytics@3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.0.1.tgz#ec69902131ea3aad8b062eeb1d17bf0962986f80" - integrity sha512-jwseSz1E+g9rXQwDdr0ZdYNjn8leZBnKPjjQhMBEiwDoenL3JYFcNW0+p0sWoVF/f2z5t7HkKA+cYObrUh18gg== +"@docusaurus/plugin-google-analytics@3.4.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.4.0.tgz#5f59fc25329a59decc231936f6f9fb5663da3c55" + integrity sha512-mCArluxEGi3cmYHqsgpGGt3IyLCrFBxPsxNZ56Mpur0xSlInnIHoeLDH7FvVVcPJRPSQ9/MfRqLsainRw+BojA== dependencies: - "@docusaurus/core" "3.0.1" - "@docusaurus/types" "3.0.1" - "@docusaurus/utils-validation" "3.0.1" + "@docusaurus/core" "3.4.0" + "@docusaurus/types" "3.4.0" + "@docusaurus/utils-validation" "3.4.0" tslib "^2.6.0" -"@docusaurus/plugin-google-gtag@3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.0.1.tgz#bb5526377d3a324ebec235127846fda386562b05" - integrity sha512-UFTDvXniAWrajsulKUJ1DB6qplui1BlKLQZjX4F7qS/qfJ+qkKqSkhJ/F4VuGQ2JYeZstYb+KaUzUzvaPK1aRQ== +"@docusaurus/plugin-google-gtag@3.4.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.4.0.tgz#42489ac5fe1c83b5523ceedd5ef74f9aa8bc251b" + integrity sha512-Dsgg6PLAqzZw5wZ4QjUYc8Z2KqJqXxHxq3vIoyoBWiLEEfigIs7wHR+oiWUQy3Zk9MIk6JTYj7tMoQU0Jm3nqA== dependencies: - "@docusaurus/core" "3.0.1" - "@docusaurus/types" "3.0.1" - "@docusaurus/utils-validation" "3.0.1" + "@docusaurus/core" "3.4.0" + "@docusaurus/types" "3.4.0" + "@docusaurus/utils-validation" "3.4.0" "@types/gtag.js" "^0.0.12" tslib "^2.6.0" -"@docusaurus/plugin-google-tag-manager@3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.0.1.tgz#4e36d13279cf90c2614b62438aa1109dd4696ec8" - integrity sha512-IPFvuz83aFuheZcWpTlAdiiX1RqWIHM+OH8wS66JgwAKOiQMR3+nLywGjkLV4bp52x7nCnwhNk1rE85Cpy/CIw== +"@docusaurus/plugin-google-tag-manager@3.4.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.4.0.tgz#cebb03a5ffa1e70b37d95601442babea251329ff" + integrity sha512-O9tX1BTwxIhgXpOLpFDueYA9DWk69WCbDRrjYoMQtFHSkTyE7RhNgyjSPREUWJb9i+YUg3OrsvrBYRl64FCPCQ== dependencies: - "@docusaurus/core" "3.0.1" - "@docusaurus/types" "3.0.1" - "@docusaurus/utils-validation" "3.0.1" + "@docusaurus/core" "3.4.0" + "@docusaurus/types" "3.4.0" + "@docusaurus/utils-validation" "3.4.0" tslib "^2.6.0" -"@docusaurus/plugin-sitemap@3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.0.1.tgz#ab55857e90d4500f892e110b30e4bc3289202bd4" - integrity sha512-xARiWnjtVvoEniZudlCq5T9ifnhCu/GAZ5nA7XgyLfPcNpHQa241HZdsTlLtVcecEVVdllevBKOp7qknBBaMGw== - dependencies: - "@docusaurus/core" "3.0.1" - "@docusaurus/logger" "3.0.1" - "@docusaurus/types" "3.0.1" - "@docusaurus/utils" "3.0.1" - "@docusaurus/utils-common" "3.0.1" - "@docusaurus/utils-validation" "3.0.1" +"@docusaurus/plugin-sitemap@3.4.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.4.0.tgz#b091d64d1e3c6c872050189999580187537bcbc6" + integrity sha512-+0VDvx9SmNrFNgwPoeoCha+tRoAjopwT0+pYO1xAbyLcewXSemq+eLxEa46Q1/aoOaJQ0qqHELuQM7iS2gp33Q== + dependencies: + "@docusaurus/core" "3.4.0" + "@docusaurus/logger" "3.4.0" + "@docusaurus/types" "3.4.0" + "@docusaurus/utils" "3.4.0" + "@docusaurus/utils-common" "3.4.0" + "@docusaurus/utils-validation" "3.4.0" fs-extra "^11.1.1" sitemap "^7.1.1" tslib "^2.6.0" "@docusaurus/preset-classic@^3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@docusaurus/preset-classic/-/preset-classic-3.0.1.tgz#d363ac837bba967095ed2a896d13c54f3717d6b5" - integrity sha512-il9m9xZKKjoXn6h0cRcdnt6wce0Pv1y5t4xk2Wx7zBGhKG1idu4IFHtikHlD0QPuZ9fizpXspXcTzjL5FXc1Gw== - dependencies: - "@docusaurus/core" "3.0.1" - "@docusaurus/plugin-content-blog" "3.0.1" - "@docusaurus/plugin-content-docs" "3.0.1" - "@docusaurus/plugin-content-pages" "3.0.1" - "@docusaurus/plugin-debug" "3.0.1" - "@docusaurus/plugin-google-analytics" "3.0.1" - "@docusaurus/plugin-google-gtag" "3.0.1" - "@docusaurus/plugin-google-tag-manager" "3.0.1" - "@docusaurus/plugin-sitemap" "3.0.1" - "@docusaurus/theme-classic" "3.0.1" - "@docusaurus/theme-common" "3.0.1" - "@docusaurus/theme-search-algolia" "3.0.1" - "@docusaurus/types" "3.0.1" - -"@docusaurus/react-loadable@5.5.2", "react-loadable@npm:@docusaurus/react-loadable@5.5.2": - version "5.5.2" - resolved "https://registry.yarnpkg.com/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz#81aae0db81ecafbdaee3651f12804580868fa6ce" - integrity sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ== - dependencies: - "@types/react" "*" - prop-types "^15.6.2" - -"@docusaurus/theme-classic@3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-classic/-/theme-classic-3.0.1.tgz#3ba4dc77553d2c1608e433c0d01bed7c6db14eb9" - integrity sha512-XD1FRXaJiDlmYaiHHdm27PNhhPboUah9rqIH0lMpBt5kYtsGjJzhqa27KuZvHLzOP2OEpqd2+GZ5b6YPq7Q05Q== - dependencies: - "@docusaurus/core" "3.0.1" - "@docusaurus/mdx-loader" "3.0.1" - "@docusaurus/module-type-aliases" "3.0.1" - "@docusaurus/plugin-content-blog" "3.0.1" - "@docusaurus/plugin-content-docs" "3.0.1" - "@docusaurus/plugin-content-pages" "3.0.1" - "@docusaurus/theme-common" "3.0.1" - "@docusaurus/theme-translations" "3.0.1" - "@docusaurus/types" "3.0.1" - "@docusaurus/utils" "3.0.1" - "@docusaurus/utils-common" "3.0.1" - "@docusaurus/utils-validation" "3.0.1" + version "3.4.0" + resolved "https://registry.yarnpkg.com/@docusaurus/preset-classic/-/preset-classic-3.4.0.tgz#6082a32fbb465b0cb2c2a50ebfc277cff2c0f139" + integrity sha512-Ohj6KB7siKqZaQhNJVMBBUzT3Nnp6eTKqO+FXO3qu/n1hJl3YLwVKTWBg28LF7MWrKu46UuYavwMRxud0VyqHg== + dependencies: + "@docusaurus/core" "3.4.0" + "@docusaurus/plugin-content-blog" "3.4.0" + "@docusaurus/plugin-content-docs" "3.4.0" + "@docusaurus/plugin-content-pages" "3.4.0" + "@docusaurus/plugin-debug" "3.4.0" + "@docusaurus/plugin-google-analytics" "3.4.0" + "@docusaurus/plugin-google-gtag" "3.4.0" + "@docusaurus/plugin-google-tag-manager" "3.4.0" + "@docusaurus/plugin-sitemap" "3.4.0" + "@docusaurus/theme-classic" "3.4.0" + "@docusaurus/theme-common" "3.4.0" + "@docusaurus/theme-search-algolia" "3.4.0" + "@docusaurus/types" "3.4.0" + +"@docusaurus/theme-classic@3.4.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-classic/-/theme-classic-3.4.0.tgz#1b0f48edec3e3ec8927843554b9f11e5927b0e52" + integrity sha512-0IPtmxsBYv2adr1GnZRdMkEQt1YW6tpzrUPj02YxNpvJ5+ju4E13J5tB4nfdaen/tfR1hmpSPlTFPvTf4kwy8Q== + dependencies: + "@docusaurus/core" "3.4.0" + "@docusaurus/mdx-loader" "3.4.0" + "@docusaurus/module-type-aliases" "3.4.0" + "@docusaurus/plugin-content-blog" "3.4.0" + "@docusaurus/plugin-content-docs" "3.4.0" + "@docusaurus/plugin-content-pages" "3.4.0" + "@docusaurus/theme-common" "3.4.0" + "@docusaurus/theme-translations" "3.4.0" + "@docusaurus/types" "3.4.0" + "@docusaurus/utils" "3.4.0" + "@docusaurus/utils-common" "3.4.0" + "@docusaurus/utils-validation" "3.4.0" "@mdx-js/react" "^3.0.0" clsx "^2.0.0" copy-text-to-clipboard "^3.2.0" @@ -1524,18 +1605,18 @@ tslib "^2.6.0" utility-types "^3.10.0" -"@docusaurus/theme-common@3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-common/-/theme-common-3.0.1.tgz#29a5bcb286296a52bc10afa5308e360cbed6b49c" - integrity sha512-cr9TOWXuIOL0PUfuXv6L5lPlTgaphKP+22NdVBOYah5jSq5XAAulJTjfe+IfLsEG4L7lJttLbhW7LXDFSAI7Ag== - dependencies: - "@docusaurus/mdx-loader" "3.0.1" - "@docusaurus/module-type-aliases" "3.0.1" - "@docusaurus/plugin-content-blog" "3.0.1" - "@docusaurus/plugin-content-docs" "3.0.1" - "@docusaurus/plugin-content-pages" "3.0.1" - "@docusaurus/utils" "3.0.1" - "@docusaurus/utils-common" "3.0.1" +"@docusaurus/theme-common@3.4.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-common/-/theme-common-3.4.0.tgz#01f2b728de6cb57f6443f52fc30675cf12a5d49f" + integrity sha512-0A27alXuv7ZdCg28oPE8nH/Iz73/IUejVaCazqu9elS4ypjiLhK3KfzdSQBnL/g7YfHSlymZKdiOHEo8fJ0qMA== + dependencies: + "@docusaurus/mdx-loader" "3.4.0" + "@docusaurus/module-type-aliases" "3.4.0" + "@docusaurus/plugin-content-blog" "3.4.0" + "@docusaurus/plugin-content-docs" "3.4.0" + "@docusaurus/plugin-content-pages" "3.4.0" + "@docusaurus/utils" "3.4.0" + "@docusaurus/utils-common" "3.4.0" "@types/history" "^4.7.11" "@types/react" "*" "@types/react-router-config" "*" @@ -1546,33 +1627,33 @@ utility-types "^3.10.0" "@docusaurus/theme-live-codeblock@^3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-live-codeblock/-/theme-live-codeblock-3.0.1.tgz#55624fba479da9816419f80b40d070b67cab364a" - integrity sha512-1NfV6pi7uoFTq7Yj3Rc9NBWMVj3OZbwWxV5tcCY/TNvlJOWerSNZQIz0oF2cqU7QPfw/ZOCPz5imM1uQ4pKN2g== - dependencies: - "@docusaurus/core" "3.0.1" - "@docusaurus/theme-common" "3.0.1" - "@docusaurus/theme-translations" "3.0.1" - "@docusaurus/utils-validation" "3.0.1" + version "3.4.0" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-live-codeblock/-/theme-live-codeblock-3.4.0.tgz#1de96234eea796a031f9455169e7f75151c3d9e4" + integrity sha512-UvsYhN6aTQiQlhY6cd0I4ckNbyZ/pQVKtKNRw3ojr+SPXYqSyXTpFzcuTUYcglKFVz1IK7LeeFymGFnsfkCWmw== + dependencies: + "@docusaurus/core" "3.4.0" + "@docusaurus/theme-common" "3.4.0" + "@docusaurus/theme-translations" "3.4.0" + "@docusaurus/utils-validation" "3.4.0" "@philpl/buble" "^0.19.7" clsx "^2.0.0" fs-extra "^11.1.1" - react-live "^4.1.5" + react-live "^4.1.6" tslib "^2.6.0" -"@docusaurus/theme-search-algolia@3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.0.1.tgz#d8fb6bddca8d8355e4706c4c7d30d3b800217cf4" - integrity sha512-DDiPc0/xmKSEdwFkXNf1/vH1SzJPzuJBar8kMcBbDAZk/SAmo/4lf6GU2drou4Ae60lN2waix+jYWTWcJRahSA== +"@docusaurus/theme-search-algolia@3.4.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.4.0.tgz#c499bad71d668df0d0f15b0e5e33e2fc4e330fcc" + integrity sha512-aiHFx7OCw4Wck1z6IoShVdUWIjntC8FHCw9c5dR8r3q4Ynh+zkS8y2eFFunN/DL6RXPzpnvKCg3vhLQYJDmT9Q== dependencies: "@docsearch/react" "^3.5.2" - "@docusaurus/core" "3.0.1" - "@docusaurus/logger" "3.0.1" - "@docusaurus/plugin-content-docs" "3.0.1" - "@docusaurus/theme-common" "3.0.1" - "@docusaurus/theme-translations" "3.0.1" - "@docusaurus/utils" "3.0.1" - "@docusaurus/utils-validation" "3.0.1" + "@docusaurus/core" "3.4.0" + "@docusaurus/logger" "3.4.0" + "@docusaurus/plugin-content-docs" "3.4.0" + "@docusaurus/theme-common" "3.4.0" + "@docusaurus/theme-translations" "3.4.0" + "@docusaurus/utils" "3.4.0" + "@docusaurus/utils-validation" "3.4.0" algoliasearch "^4.18.0" algoliasearch-helper "^3.13.3" clsx "^2.0.0" @@ -1582,19 +1663,20 @@ tslib "^2.6.0" utility-types "^3.10.0" -"@docusaurus/theme-translations@3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-translations/-/theme-translations-3.0.1.tgz#837a01a166ccd698a3eceaed0c2f798555bc024b" - integrity sha512-6UrbpzCTN6NIJnAtZ6Ne9492vmPVX+7Fsz4kmp+yor3KQwA1+MCzQP7ItDNkP38UmVLnvB/cYk/IvehCUqS3dg== +"@docusaurus/theme-translations@3.4.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-translations/-/theme-translations-3.4.0.tgz#e6355d01352886c67e38e848b2542582ea3070af" + integrity sha512-zSxCSpmQCCdQU5Q4CnX/ID8CSUUI3fvmq4hU/GNP/XoAWtXo9SAVnM3TzpU8Gb//H3WCsT8mJcTfyOk3d9ftNg== dependencies: fs-extra "^11.1.1" tslib "^2.6.0" -"@docusaurus/types@3.0.1", "@docusaurus/types@^3.0.0": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@docusaurus/types/-/types-3.0.1.tgz#4fe306aa10ef7c97dbc07588864f6676a40f3b6f" - integrity sha512-plyX2iU1tcUsF46uQ01pAd4JhexR7n0iiQ5MSnBFX6M6NSJgDYdru/i1/YNPKOnQHBoXGLHv0dNT6OAlDWNjrg== +"@docusaurus/types@3.4.0", "@docusaurus/types@^3.1.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@docusaurus/types/-/types-3.4.0.tgz#237c3f737e9db3f7c1a5935a3ef48d6eadde8292" + integrity sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A== dependencies: + "@mdx-js/mdx" "^3.0.0" "@types/history" "^4.7.11" "@types/react" "*" commander "^5.1.0" @@ -1604,31 +1686,35 @@ webpack "^5.88.1" webpack-merge "^5.9.0" -"@docusaurus/utils-common@3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@docusaurus/utils-common/-/utils-common-3.0.1.tgz#111f450089d5f0a290c0c25f8a574a270d08436f" - integrity sha512-W0AxD6w6T8g6bNro8nBRWf7PeZ/nn7geEWM335qHU2DDDjHuV4UZjgUGP1AQsdcSikPrlIqTJJbKzer1lRSlIg== +"@docusaurus/utils-common@3.4.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@docusaurus/utils-common/-/utils-common-3.4.0.tgz#2a43fefd35b85ab9fcc6833187e66c15f8bfbbc6" + integrity sha512-NVx54Wr4rCEKsjOH5QEVvxIqVvm+9kh7q8aYTU5WzUU9/Hctd6aTrcZ3G0Id4zYJ+AeaG5K5qHA4CY5Kcm2iyQ== dependencies: tslib "^2.6.0" -"@docusaurus/utils-validation@3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@docusaurus/utils-validation/-/utils-validation-3.0.1.tgz#3c5f12941b328a19fc9acb34d070219f3e865ec6" - integrity sha512-ujTnqSfyGQ7/4iZdB4RRuHKY/Nwm58IIb+41s5tCXOv/MBU2wGAjOHq3U+AEyJ8aKQcHbxvTKJaRchNHYUVUQg== +"@docusaurus/utils-validation@3.4.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@docusaurus/utils-validation/-/utils-validation-3.4.0.tgz#0176f6e503ff45f4390ec2ecb69550f55e0b5eb7" + integrity sha512-hYQ9fM+AXYVTWxJOT1EuNaRnrR2WGpRdLDQG07O8UOpsvCPWUVOeo26Rbm0JWY2sGLfzAb+tvJ62yF+8F+TV0g== dependencies: - "@docusaurus/logger" "3.0.1" - "@docusaurus/utils" "3.0.1" + "@docusaurus/logger" "3.4.0" + "@docusaurus/utils" "3.4.0" + "@docusaurus/utils-common" "3.4.0" + fs-extra "^11.2.0" joi "^17.9.2" js-yaml "^4.1.0" + lodash "^4.17.21" tslib "^2.6.0" -"@docusaurus/utils@3.0.1", "@docusaurus/utils@^3.0.0": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@docusaurus/utils/-/utils-3.0.1.tgz#c64f68980a90c5bc6d53a5b8f32deb9026b1e303" - integrity sha512-TwZ33Am0q4IIbvjhUOs+zpjtD/mXNmLmEgeTGuRq01QzulLHuPhaBTTAC/DHu6kFx3wDgmgpAlaRuCHfTcXv8g== +"@docusaurus/utils@3.4.0", "@docusaurus/utils@^3.1.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@docusaurus/utils/-/utils-3.4.0.tgz#c508e20627b7a55e2b541e4a28c95e0637d6a204" + integrity sha512-fRwnu3L3nnWaXOgs88BVBmG1yGjcQqZNHG+vInhEa2Sz2oQB+ZjbEMO5Rh9ePFpZ0YDiDUhpaVjwmS+AU2F14g== dependencies: - "@docusaurus/logger" "3.0.1" - "@svgr/webpack" "^6.5.1" + "@docusaurus/logger" "3.4.0" + "@docusaurus/utils-common" "3.4.0" + "@svgr/webpack" "^8.1.0" escape-string-regexp "^4.0.0" file-loader "^6.2.0" fs-extra "^11.1.1" @@ -1639,24 +1725,95 @@ js-yaml "^4.1.0" lodash "^4.17.21" micromatch "^4.0.5" + prompts "^2.4.2" resolve-pathname "^3.0.0" shelljs "^0.8.5" tslib "^2.6.0" url-loader "^4.1.1" + utility-types "^3.10.0" webpack "^5.88.1" -"@hapi/hoek@^9.0.0": +"@emotion/is-prop-valid@1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz#d4175076679c6a26faa92b03bb786f9e52612337" + integrity sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw== + dependencies: + "@emotion/memoize" "^0.8.1" + +"@emotion/is-prop-valid@^0.8.2": + version "0.8.8" + resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz#db28b1c4368a259b60a97311d6a952d4fd01ac1a" + integrity sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA== + dependencies: + "@emotion/memoize" "0.7.4" + +"@emotion/memoize@0.7.4": + version "0.7.4" + resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb" + integrity sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw== + +"@emotion/memoize@^0.8.1": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.1.tgz#c1ddb040429c6d21d38cc945fe75c818cfb68e17" + integrity sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA== + +"@emotion/unitless@0.8.1": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.8.1.tgz#182b5a4704ef8ad91bde93f7a860a88fd92c79a3" + integrity sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ== + +"@floating-ui/core@^1.6.0": + version "1.6.5" + resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.5.tgz#102335cac0d22035b04d70ca5ff092d2d1a26f2b" + integrity sha512-8GrTWmoFhm5BsMZOTHeGD2/0FLKLQQHvO/ZmQga4tKempYRLz8aqJGqXVuQgisnMObq2YZ2SgkwctN1LOOxcqA== + dependencies: + "@floating-ui/utils" "^0.2.5" + +"@floating-ui/dom@^1.0.0": + version "1.6.8" + resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.8.tgz#45e20532b6d8a061b356a4fb336022cf2609754d" + integrity sha512-kx62rP19VZ767Q653wsP1XZCGIirkE09E0QUGNYTM/ttbbQHqcGPdSfWFxUyyNLc/W6aoJRBajOSXhP6GXjC0Q== + dependencies: + "@floating-ui/core" "^1.6.0" + "@floating-ui/utils" "^0.2.5" + +"@floating-ui/react-dom@^2.0.0": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.1.1.tgz#cca58b6b04fc92b4c39288252e285e0422291fb0" + integrity sha512-4h84MJt3CHrtG18mGsXuLCHMrug49d7DFkU0RMIyshRveBeyV2hmV/pDaF2Uxtu8kgq5r46llp5E5FQiR0K2Yg== + dependencies: + "@floating-ui/dom" "^1.0.0" + +"@floating-ui/utils@^0.2.5": + version "0.2.5" + resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.5.tgz#105c37d9d9620ce69b7f692a20c821bf1ad2cbf9" + integrity sha512-sTcG+QZ6fdEUObICavU+aB3Mp8HY4n14wYHdxK4fXjPmv3PXZZeY5RaguJmGyeH/CJQhX3fqKUtS4qc1LoHwhQ== + +"@hapi/hoek@^9.0.0", "@hapi/hoek@^9.3.0": version "9.3.0" resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ== -"@hapi/topo@^5.0.0": +"@hapi/topo@^5.1.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012" integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg== dependencies: "@hapi/hoek" "^9.0.0" +"@headlessui/react@^1.7.18": + version "1.7.19" + resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-1.7.19.tgz#91c78cf5fcb254f4a0ebe96936d48421caf75f40" + integrity sha512-Ll+8q3OlMJfJbAKM/+/Y2q6PPYbryqNTXDbryx7SXLIDamkF6iQFbriYHga0dY44PvDhvvBWCx1Xj4U5+G4hOw== + dependencies: + "@tanstack/react-virtual" "^3.0.0-beta.60" + client-only "^0.0.1" + +"@headlessui/tailwindcss@^0.2.0": + version "0.2.1" + resolved "https://registry.yarnpkg.com/@headlessui/tailwindcss/-/tailwindcss-0.2.1.tgz#1becc201f69358a40e08bd676acc234b2cabe6e4" + integrity sha512-2+5+NZ+RzMyrVeCZOxdbvkUSssSxGvcUxphkIfSVLpRiKsj+/63T2TOL9dBYMXVfj/CGr6hMxSRInzXv6YY7sA== + "@isaacs/cliui@^8.0.2": version "8.0.2" resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" @@ -1688,55 +1845,55 @@ "@types/yargs" "^17.0.8" chalk "^4.0.0" -"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" - integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== +"@jridgewell/gen-mapping@^0.3.2", "@jridgewell/gen-mapping@^0.3.5": + version "0.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" + integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== dependencies: - "@jridgewell/set-array" "^1.0.1" + "@jridgewell/set-array" "^1.2.1" "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.9" + "@jridgewell/trace-mapping" "^0.3.24" "@jridgewell/resolve-uri@^3.1.0": - version "3.1.1" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" - integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== -"@jridgewell/set-array@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" - integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== +"@jridgewell/set-array@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" + integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== "@jridgewell/source-map@^0.3.3": - version "0.3.5" - resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.5.tgz#a3bb4d5c6825aab0d281268f47f6ad5853431e91" - integrity sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ== + version "0.3.6" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.6.tgz#9d71ca886e32502eb9362c9a74a46787c36df81a" + integrity sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ== dependencies: - "@jridgewell/gen-mapping" "^0.3.0" - "@jridgewell/trace-mapping" "^0.3.9" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" "@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": - version "1.4.15" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" - integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + version "1.5.0" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" + integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== -"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.20", "@jridgewell/trace-mapping@^0.3.9": - version "0.3.20" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz#72e45707cf240fa6b081d0366f8265b0cd10197f" - integrity sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q== +"@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.20", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": + version "0.3.25" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== dependencies: "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" "@leichtgewicht/ip-codec@^2.0.1": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b" - integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A== + version "2.0.5" + resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz#4fc56c15c580b9adb7dc3c333a134e540b44bfb1" + integrity sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw== "@mdx-js/mdx@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@mdx-js/mdx/-/mdx-3.0.0.tgz#37ef87685143fafedf1165f0a79e9fe95fbe5154" - integrity sha512-Icm0TBKBLYqroYbNW3BPnzMGn+7mwpQOK310aZ7+fkCtiU3aqv2cdcX+nd0Ydo3wI5Rx8bX2Z2QmGb/XcAClCw== + version "3.0.1" + resolved "https://registry.yarnpkg.com/@mdx-js/mdx/-/mdx-3.0.1.tgz#617bd2629ae561fdca1bb88e3badd947f5a82191" + integrity sha512-eIQ4QTrOWyL3LWEe/bu6Taqzq2HQvHcyTMaOrI95P2/LmJE7AsfPfgJGuFLPVqBUE1BC1rik3VIhU+s9u72arA== dependencies: "@types/estree" "^1.0.0" "@types/estree-jsx" "^1.0.0" @@ -1763,12 +1920,96 @@ vfile "^6.0.0" "@mdx-js/react@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-3.0.0.tgz#eaccaa8d6a7736b19080aff5a70448a7ba692271" - integrity sha512-nDctevR9KyYFyV+m+/+S4cpzCWHqj+iHDHq3QrsWezcC+B17uZdIWgCguESUkwFhM3n/56KxWVE3V6EokrmONQ== + version "3.0.1" + resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-3.0.1.tgz#997a19b3a5b783d936c75ae7c47cfe62f967f746" + integrity sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A== dependencies: "@types/mdx" "^2.0.0" +"@monaco-editor/loader@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@monaco-editor/loader/-/loader-1.4.0.tgz#f08227057331ec890fa1e903912a5b711a2ad558" + integrity sha512-00ioBig0x642hytVspPl7DbQyaSWRaolYie/UFNjoTdvoKPzo6xrXLhTk9ixgIKcLH5b5vDOjVNiGyY+uDCUlg== + dependencies: + state-local "^1.0.6" + +"@monaco-editor/react@^4.6.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@monaco-editor/react/-/react-4.6.0.tgz#bcc68671e358a21c3814566b865a54b191e24119" + integrity sha512-RFkU9/i7cN2bsq/iTkurMWOEErmYcY6JiQI3Jn+WeR/FGISH8JbHERjpS9oRuSOPvDMJI0Z8nJeKkbOs9sBYQw== + dependencies: + "@monaco-editor/loader" "^1.4.0" + +"@motionone/animation@^10.12.0": + version "10.18.0" + resolved "https://registry.yarnpkg.com/@motionone/animation/-/animation-10.18.0.tgz#868d00b447191816d5d5cf24b1cafa144017922b" + integrity sha512-9z2p5GFGCm0gBsZbi8rVMOAJCtw1WqBTIPw3ozk06gDvZInBPIsQcHgYogEJ4yuHJ+akuW8g1SEIOpTOvYs8hw== + dependencies: + "@motionone/easing" "^10.18.0" + "@motionone/types" "^10.17.1" + "@motionone/utils" "^10.18.0" + tslib "^2.3.1" + +"@motionone/dom@10.12.0": + version "10.12.0" + resolved "https://registry.yarnpkg.com/@motionone/dom/-/dom-10.12.0.tgz#ae30827fd53219efca4e1150a5ff2165c28351ed" + integrity sha512-UdPTtLMAktHiqV0atOczNYyDd/d8Cf5fFsd1tua03PqTwwCe/6lwhLSQ8a7TbnQ5SN0gm44N1slBfj+ORIhrqw== + dependencies: + "@motionone/animation" "^10.12.0" + "@motionone/generators" "^10.12.0" + "@motionone/types" "^10.12.0" + "@motionone/utils" "^10.12.0" + hey-listen "^1.0.8" + tslib "^2.3.1" + +"@motionone/easing@^10.18.0": + version "10.18.0" + resolved "https://registry.yarnpkg.com/@motionone/easing/-/easing-10.18.0.tgz#7b82f6010dfee3a1bb0ee83abfbaff6edae0c708" + integrity sha512-VcjByo7XpdLS4o9T8t99JtgxkdMcNWD3yHU/n6CLEz3bkmKDRZyYQ/wmSf6daum8ZXqfUAgFeCZSpJZIMxaCzg== + dependencies: + "@motionone/utils" "^10.18.0" + tslib "^2.3.1" + +"@motionone/generators@^10.12.0": + version "10.18.0" + resolved "https://registry.yarnpkg.com/@motionone/generators/-/generators-10.18.0.tgz#fe09ab5cfa0fb9a8884097feb7eb60abeb600762" + integrity sha512-+qfkC2DtkDj4tHPu+AFKVfR/C30O1vYdvsGYaR13W/1cczPrrcjdvYCj0VLFuRMN+lP1xvpNZHCRNM4fBzn1jg== + dependencies: + "@motionone/types" "^10.17.1" + "@motionone/utils" "^10.18.0" + tslib "^2.3.1" + +"@motionone/types@^10.12.0", "@motionone/types@^10.17.1": + version "10.17.1" + resolved "https://registry.yarnpkg.com/@motionone/types/-/types-10.17.1.tgz#cf487badbbdc9da0c2cb86ffc1e5d11147c6e6fb" + integrity sha512-KaC4kgiODDz8hswCrS0btrVrzyU2CSQKO7Ps90ibBVSQmjkrt2teqta6/sOG59v7+dPnKMAg13jyqtMKV2yJ7A== + +"@motionone/utils@^10.12.0", "@motionone/utils@^10.18.0": + version "10.18.0" + resolved "https://registry.yarnpkg.com/@motionone/utils/-/utils-10.18.0.tgz#a59ff8932ed9009624bca07c56b28ef2bb2f885e" + integrity sha512-3XVF7sgyTSI2KWvTf6uLlBJ5iAgRgmvp3bpuOiQJvInd4nZ19ET8lX5unn30SlmRH7hXbBbH+Gxd0m0klJ3Xtw== + dependencies: + "@motionone/types" "^10.17.1" + hey-listen "^1.0.8" + tslib "^2.3.1" + +"@noble/curves@1.2.0", "@noble/curves@~1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.2.0.tgz#92d7e12e4e49b23105a2555c6984d41733d65c35" + integrity sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw== + dependencies: + "@noble/hashes" "1.3.2" + +"@noble/hashes@1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39" + integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== + +"@noble/hashes@~1.3.0", "@noble/hashes@~1.3.2": + version "1.3.3" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.3.tgz#39908da56a4adc270147bb07968bf3b16cfe1699" + integrity sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA== + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -1832,14 +2073,627 @@ config-chain "^1.1.11" "@polka/url@^1.0.0-next.24": - version "1.0.0-next.24" - resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.24.tgz#58601079e11784d20f82d0585865bb42305c4df3" - integrity sha512-2LuNTFBIO0m7kKIQvvPHN6UE63VjpmL9rnEEaOOaiSPbZK+zUOYIzBAWcED+3XYzhYsd/0mD57VdxAEqqV52CQ== + version "1.0.0-next.25" + resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.25.tgz#f077fdc0b5d0078d30893396ff4827a13f99e817" + integrity sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ== + +"@radix-ui/number@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/number/-/number-1.1.0.tgz#1e95610461a09cdf8bb05c152e76ca1278d5da46" + integrity sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ== + +"@radix-ui/primitive@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.0.1.tgz#e46f9958b35d10e9f6dc71c497305c22e3e55dbd" + integrity sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/primitive@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.1.0.tgz#42ef83b3b56dccad5d703ae8c42919a68798bbe2" + integrity sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA== + +"@radix-ui/react-arrow@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.1.0.tgz#744f388182d360b86285217e43b6c63633f39e7a" + integrity sha512-FmlW1rCg7hBpEBwFbjHwCW6AmWLQM6g/v0Sn8XbP9NvmSZ2San1FpQeyPtufzOMSIx7Y4dzjlHoifhp+7NkZhw== + dependencies: + "@radix-ui/react-primitive" "2.0.0" + +"@radix-ui/react-avatar@^1.0.4": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-avatar/-/react-avatar-1.1.0.tgz#457c81334c93f4608df15f081e7baa286558d6a2" + integrity sha512-Q/PbuSMk/vyAd/UoIShVGZ7StHHeRFYU7wXmi5GV+8cLXflZAEpHL/F697H1klrzxKXNtZ97vWiC0q3RKUH8UA== + dependencies: + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-layout-effect" "1.1.0" + +"@radix-ui/react-checkbox@^1.0.4": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-checkbox/-/react-checkbox-1.1.1.tgz#a559c4303957d797acee99914480b755aa1f27d6" + integrity sha512-0i/EKJ222Afa1FE0C6pNJxDq1itzcl3HChE9DwskA4th4KRse8ojx8a1nVcOjwJdbpDLcz7uol77yYnQNMHdKw== + dependencies: + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-presence" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-use-controllable-state" "1.1.0" + "@radix-ui/react-use-previous" "1.1.0" + "@radix-ui/react-use-size" "1.1.0" + +"@radix-ui/react-collapsible@^1.0.3": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-collapsible/-/react-collapsible-1.1.0.tgz#4d49ddcc7b7d38f6c82f1fd29674f6fab5353e77" + integrity sha512-zQY7Epa8sTL0mq4ajSJpjgn2YmCgyrG7RsQgLp3C0LQVkG7+Tf6Pv1CeNWZLyqMjhdPkBa5Lx7wYBeSu7uCSTA== + dependencies: + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-presence" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-use-controllable-state" "1.1.0" + "@radix-ui/react-use-layout-effect" "1.1.0" + +"@radix-ui/react-collection@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-1.1.0.tgz#f18af78e46454a2360d103c2251773028b7724ed" + integrity sha512-GZsZslMJEyo1VKm5L1ZJY8tGDxZNPAoUeQUIbKeJfoi7Q4kmig5AsgLMYYuyYbfjd8fBmFORAIwYAkXMnXZgZw== + dependencies: + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-slot" "1.1.0" + +"@radix-ui/react-compose-refs@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz#7ed868b66946aa6030e580b1ffca386dd4d21989" + integrity sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/react-compose-refs@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz#656432461fc8283d7b591dcf0d79152fae9ecc74" + integrity sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw== + +"@radix-ui/react-context@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.0.1.tgz#fe46e67c96b240de59187dcb7a1a50ce3e2ec00c" + integrity sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/react-context@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.1.0.tgz#6df8d983546cfd1999c8512f3a8ad85a6e7fcee8" + integrity sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A== + +"@radix-ui/react-dialog@1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.0.5.tgz#71657b1b116de6c7a0b03242d7d43e01062c7300" + integrity sha512-GjWJX/AUpB703eEBanuBnIWdIXg6NvJFCXcNlSZk4xdszCdhrJgBoUd1cGk67vFO+WdA2pfI/plOpqz/5GUP6Q== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.1" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-context" "1.0.1" + "@radix-ui/react-dismissable-layer" "1.0.5" + "@radix-ui/react-focus-guards" "1.0.1" + "@radix-ui/react-focus-scope" "1.0.4" + "@radix-ui/react-id" "1.0.1" + "@radix-ui/react-portal" "1.0.4" + "@radix-ui/react-presence" "1.0.1" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-slot" "1.0.2" + "@radix-ui/react-use-controllable-state" "1.0.1" + aria-hidden "^1.1.1" + react-remove-scroll "2.5.5" + +"@radix-ui/react-dialog@^1.0.5": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.1.1.tgz#4906507f7b4ad31e22d7dad69d9330c87c431d44" + integrity sha512-zysS+iU4YP3STKNS6USvFVqI4qqx8EpiwmT5TuCApVEBca+eRCbONi4EgzfNSuVnOXvC5UPHHMjs8RXO6DH9Bg== + dependencies: + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-dismissable-layer" "1.1.0" + "@radix-ui/react-focus-guards" "1.1.0" + "@radix-ui/react-focus-scope" "1.1.0" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-portal" "1.1.1" + "@radix-ui/react-presence" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-slot" "1.1.0" + "@radix-ui/react-use-controllable-state" "1.1.0" + aria-hidden "^1.1.1" + react-remove-scroll "2.5.7" + +"@radix-ui/react-direction@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-direction/-/react-direction-1.1.0.tgz#a7d39855f4d077adc2a1922f9c353c5977a09cdc" + integrity sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg== + +"@radix-ui/react-dismissable-layer@1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.5.tgz#3f98425b82b9068dfbab5db5fff3df6ebf48b9d4" + integrity sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.1" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-use-callback-ref" "1.0.1" + "@radix-ui/react-use-escape-keydown" "1.0.3" + +"@radix-ui/react-dismissable-layer@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.0.tgz#2cd0a49a732372513733754e6032d3fb7988834e" + integrity sha512-/UovfmmXGptwGcBQawLzvn2jOfM0t4z3/uKffoBlj724+n3FvBbZ7M0aaBOmkp6pqFYpO4yx8tSVJjx3Fl2jig== + dependencies: + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-escape-keydown" "1.1.0" + +"@radix-ui/react-dropdown-menu@^2.0.6": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.1.tgz#3dc578488688250dbbe109d9ff2ca28a9bca27ec" + integrity sha512-y8E+x9fBq9qvteD2Zwa4397pUVhYsh9iq44b5RD5qu1GMJWBCBuVg1hMyItbc6+zH00TxGRqd9Iot4wzf3OoBQ== + dependencies: + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-menu" "2.1.1" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-use-controllable-state" "1.1.0" + +"@radix-ui/react-focus-guards@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.1.tgz#1ea7e32092216b946397866199d892f71f7f98ad" + integrity sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/react-focus-guards@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.0.tgz#8e9abb472a9a394f59a1b45f3dd26cfe3fc6da13" + integrity sha512-w6XZNUPVv6xCpZUqb/yN9DL6auvpGX3C/ee6Hdi16v2UUy25HV2Q5bcflsiDyT/g5RwbPQ/GIT1vLkeRb+ITBw== + +"@radix-ui/react-focus-scope@1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.4.tgz#2ac45fce8c5bb33eb18419cdc1905ef4f1906525" + integrity sha512-sL04Mgvf+FmyvZeYfNu1EPAaaxD+aw7cYeIB9L9Fvq8+urhltTRaEo5ysKOpHuKPclsZcSUMKlN05x4u+CINpA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-use-callback-ref" "1.0.1" + +"@radix-ui/react-focus-scope@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.0.tgz#ebe2891a298e0a33ad34daab2aad8dea31caf0b2" + integrity sha512-200UD8zylvEyL8Bx+z76RJnASR2gRMuxlgFCPAe/Q/679a/r0eK3MBVYMb7vZODZcffZBdob1EGnky78xmVvcA== + dependencies: + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-use-callback-ref" "1.1.0" + +"@radix-ui/react-hover-card@^1.0.7": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-hover-card/-/react-hover-card-1.1.1.tgz#2982a5a91c7ae5a98e0cacd845fbdfbfdcdab355" + integrity sha512-IwzAOP97hQpDADYVKrEEHUH/b2LA+9MgB0LgdmnbFO2u/3M5hmEofjjr2M6CyzUblaAqJdFm6B7oFtU72DPXrA== + dependencies: + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-dismissable-layer" "1.1.0" + "@radix-ui/react-popper" "1.2.0" + "@radix-ui/react-portal" "1.1.1" + "@radix-ui/react-presence" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-use-controllable-state" "1.1.0" + +"@radix-ui/react-icons@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-icons/-/react-icons-1.3.0.tgz#c61af8f323d87682c5ca76b856d60c2312dbcb69" + integrity sha512-jQxj/0LKgp+j9BiTXz3O3sgs26RNet2iLWmsPyRz2SIcR4q/4SbazXfnYwbAr+vLYKSfc7qxzyGQA1HLlYiuNw== + +"@radix-ui/react-id@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.0.1.tgz#73cdc181f650e4df24f0b6a5b7aa426b912c88c0" + integrity sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-use-layout-effect" "1.0.1" + +"@radix-ui/react-id@1.1.0", "@radix-ui/react-id@^1.0.1": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.1.0.tgz#de47339656594ad722eb87f94a6b25f9cffae0ed" + integrity sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA== + dependencies: + "@radix-ui/react-use-layout-effect" "1.1.0" + +"@radix-ui/react-label@^2.0.2": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-label/-/react-label-2.1.0.tgz#3aa2418d70bb242be37c51ff5e51a2adcbc372e3" + integrity sha512-peLblDlFw/ngk3UWq0VnYaOLy6agTZZ+MUO/WhVfm14vJGML+xH4FAl2XQGLqdefjNb7ApRg6Yn7U42ZhmYXdw== + dependencies: + "@radix-ui/react-primitive" "2.0.0" + +"@radix-ui/react-menu@2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-menu/-/react-menu-2.1.1.tgz#bd623ace0e1ae1ac78023a505fec0541d59fb346" + integrity sha512-oa3mXRRVjHi6DZu/ghuzdylyjaMXLymx83irM7hTxutQbD+7IhPKdMdRHD26Rm+kHRrWcrUkkRPv5pd47a2xFQ== + dependencies: + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-collection" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-direction" "1.1.0" + "@radix-ui/react-dismissable-layer" "1.1.0" + "@radix-ui/react-focus-guards" "1.1.0" + "@radix-ui/react-focus-scope" "1.1.0" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-popper" "1.2.0" + "@radix-ui/react-portal" "1.1.1" + "@radix-ui/react-presence" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-roving-focus" "1.1.0" + "@radix-ui/react-slot" "1.1.0" + "@radix-ui/react-use-callback-ref" "1.1.0" + aria-hidden "^1.1.1" + react-remove-scroll "2.5.7" + +"@radix-ui/react-popover@^1.0.7": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-popover/-/react-popover-1.1.1.tgz#604b783cdb3494ed4f16a58c17f0e81e61ab7775" + integrity sha512-3y1A3isulwnWhvTTwmIreiB8CF4L+qRjZnK1wYLO7pplddzXKby/GnZ2M7OZY3qgnl6p9AodUIHRYGXNah8Y7g== + dependencies: + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-dismissable-layer" "1.1.0" + "@radix-ui/react-focus-guards" "1.1.0" + "@radix-ui/react-focus-scope" "1.1.0" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-popper" "1.2.0" + "@radix-ui/react-portal" "1.1.1" + "@radix-ui/react-presence" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-slot" "1.1.0" + "@radix-ui/react-use-controllable-state" "1.1.0" + aria-hidden "^1.1.1" + react-remove-scroll "2.5.7" + +"@radix-ui/react-popper@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.2.0.tgz#a3e500193d144fe2d8f5d5e60e393d64111f2a7a" + integrity sha512-ZnRMshKF43aBxVWPWvbj21+7TQCvhuULWJ4gNIKYpRlQt5xGRhLx66tMp8pya2UkGHTSlhpXwmjqltDYHhw7Vg== + dependencies: + "@floating-ui/react-dom" "^2.0.0" + "@radix-ui/react-arrow" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-use-rect" "1.1.0" + "@radix-ui/react-use-size" "1.1.0" + "@radix-ui/rect" "1.1.0" + +"@radix-ui/react-portal@1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.0.4.tgz#df4bfd353db3b1e84e639e9c63a5f2565fb00e15" + integrity sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-primitive" "1.0.3" + +"@radix-ui/react-portal@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.1.1.tgz#1957f1eb2e1aedfb4a5475bd6867d67b50b1d15f" + integrity sha512-A3UtLk85UtqhzFqtoC8Q0KvR2GbXF3mtPgACSazajqq6A41mEQgo53iPzY4i6BwDxlIFqWIhiQ2G729n+2aw/g== + dependencies: + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-use-layout-effect" "1.1.0" + +"@radix-ui/react-presence@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.0.1.tgz#491990ba913b8e2a5db1b06b203cb24b5cdef9ba" + integrity sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-use-layout-effect" "1.0.1" + +"@radix-ui/react-presence@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.1.0.tgz#227d84d20ca6bfe7da97104b1a8b48a833bfb478" + integrity sha512-Gq6wuRN/asf9H/E/VzdKoUtT8GC9PQc9z40/vEr0VCJ4u5XvvhWIrSsCB6vD2/cH7ugTdSfYq9fLJCcM00acrQ== + dependencies: + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-use-layout-effect" "1.1.0" + +"@radix-ui/react-primitive@1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz#d49ea0f3f0b2fe3ab1cb5667eb03e8b843b914d0" + integrity sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-slot" "1.0.2" + +"@radix-ui/react-primitive@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz#fe05715faa9203a223ccc0be15dc44b9f9822884" + integrity sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw== + dependencies: + "@radix-ui/react-slot" "1.1.0" + +"@radix-ui/react-roving-focus@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.0.tgz#b30c59daf7e714c748805bfe11c76f96caaac35e" + integrity sha512-EA6AMGeq9AEeQDeSH0aZgG198qkfHSbvWTf1HvoDmOB5bBG/qTxjYMWUKMnYiV6J/iP/J8MEFSuB2zRU2n7ODA== + dependencies: + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-collection" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-direction" "1.1.0" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-controllable-state" "1.1.0" + +"@radix-ui/react-scroll-area@^1.0.5": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-scroll-area/-/react-scroll-area-1.1.0.tgz#50b24b0fc9ada151d176395bcf47b2ec68feada5" + integrity sha512-9ArIZ9HWhsrfqS765h+GZuLoxaRHD/j0ZWOWilsCvYTpYJp8XwCqNG7Dt9Nu/TItKOdgLGkOPCodQvDc+UMwYg== + dependencies: + "@radix-ui/number" "1.1.0" + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-direction" "1.1.0" + "@radix-ui/react-presence" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-layout-effect" "1.1.0" + +"@radix-ui/react-select@^2.0.0": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-select/-/react-select-2.1.1.tgz#df05cb0b29d3deaef83b505917c4042e0e418a9f" + integrity sha512-8iRDfyLtzxlprOo9IicnzvpsO1wNCkuwzzCM+Z5Rb5tNOpCdMvcc2AkzX0Fz+Tz9v6NJ5B/7EEgyZveo4FBRfQ== + dependencies: + "@radix-ui/number" "1.1.0" + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-collection" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-direction" "1.1.0" + "@radix-ui/react-dismissable-layer" "1.1.0" + "@radix-ui/react-focus-guards" "1.1.0" + "@radix-ui/react-focus-scope" "1.1.0" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-popper" "1.2.0" + "@radix-ui/react-portal" "1.1.1" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-slot" "1.1.0" + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-controllable-state" "1.1.0" + "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-use-previous" "1.1.0" + "@radix-ui/react-visually-hidden" "1.1.0" + aria-hidden "^1.1.1" + react-remove-scroll "2.5.7" + +"@radix-ui/react-separator@^1.0.3": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-separator/-/react-separator-1.1.0.tgz#ee0f4d86003b0e3ea7bc6ccab01ea0adee32663e" + integrity sha512-3uBAs+egzvJBDZAzvb/n4NxxOYpnspmWxO2u5NbZ8Y6FM/NdrGSF9bop3Cf6F6C71z1rTSn8KV0Fo2ZVd79lGA== + dependencies: + "@radix-ui/react-primitive" "2.0.0" + +"@radix-ui/react-slider@^1.1.2": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-slider/-/react-slider-1.2.0.tgz#7a4c817d24386b420631a3fdc75563706d743472" + integrity sha512-dAHCDA4/ySXROEPaRtaMV5WHL8+JB/DbtyTbJjYkY0RXmKMO2Ln8DFZhywG5/mVQ4WqHDBc8smc14yPXPqZHYA== + dependencies: + "@radix-ui/number" "1.1.0" + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-collection" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-direction" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-use-controllable-state" "1.1.0" + "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-use-previous" "1.1.0" + "@radix-ui/react-use-size" "1.1.0" + +"@radix-ui/react-slot@1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.0.2.tgz#a9ff4423eade67f501ffb32ec22064bc9d3099ab" + integrity sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-compose-refs" "1.0.1" + +"@radix-ui/react-slot@1.1.0", "@radix-ui/react-slot@^1.0.2": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.1.0.tgz#7c5e48c36ef5496d97b08f1357bb26ed7c714b84" + integrity sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw== + dependencies: + "@radix-ui/react-compose-refs" "1.1.0" + +"@radix-ui/react-tabs@^1.0.4": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-tabs/-/react-tabs-1.1.0.tgz#0a6db1caed56776a1176aae68532060e301cc1c0" + integrity sha512-bZgOKB/LtZIij75FSuPzyEti/XBhJH52ExgtdVqjCIh+Nx/FW+LhnbXtbCzIi34ccyMsyOja8T0thCzoHFXNKA== + dependencies: + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-direction" "1.1.0" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-presence" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-roving-focus" "1.1.0" + "@radix-ui/react-use-controllable-state" "1.1.0" + +"@radix-ui/react-toast@^1.1.5": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-toast/-/react-toast-1.2.1.tgz#4bde231ed27d007dcd0455a446565ca619f92a2d" + integrity sha512-5trl7piMXcZiCq7MW6r8YYmu0bK5qDpTWz+FdEPdKyft2UixkspheYbjbrLXVN5NGKHFbOP7lm8eD0biiSqZqg== + dependencies: + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-collection" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-dismissable-layer" "1.1.0" + "@radix-ui/react-portal" "1.1.1" + "@radix-ui/react-presence" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-controllable-state" "1.1.0" + "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-visually-hidden" "1.1.0" + +"@radix-ui/react-tooltip@^1.0.7": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-tooltip/-/react-tooltip-1.1.2.tgz#c42db2ffd7dcc6ff3d65407c8cb70490288f518d" + integrity sha512-9XRsLwe6Yb9B/tlnYCPVUd/TFS4J7HuOZW345DCeC6vKIxQGMZdx21RK4VoZauPD5frgkXTYVS5y90L+3YBn4w== + dependencies: + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-dismissable-layer" "1.1.0" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-popper" "1.2.0" + "@radix-ui/react-portal" "1.1.1" + "@radix-ui/react-presence" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-slot" "1.1.0" + "@radix-ui/react-use-controllable-state" "1.1.0" + "@radix-ui/react-visually-hidden" "1.1.0" + +"@radix-ui/react-use-callback-ref@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz#f4bb1f27f2023c984e6534317ebc411fc181107a" + integrity sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/react-use-callback-ref@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz#bce938ca413675bc937944b0d01ef6f4a6dc5bf1" + integrity sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw== + +"@radix-ui/react-use-controllable-state@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.1.tgz#ecd2ced34e6330caf89a82854aa2f77e07440286" + integrity sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-use-callback-ref" "1.0.1" + +"@radix-ui/react-use-controllable-state@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz#1321446857bb786917df54c0d4d084877aab04b0" + integrity sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw== + dependencies: + "@radix-ui/react-use-callback-ref" "1.1.0" + +"@radix-ui/react-use-escape-keydown@1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.3.tgz#217b840c250541609c66f67ed7bab2b733620755" + integrity sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-use-callback-ref" "1.0.1" + +"@radix-ui/react-use-escape-keydown@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz#31a5b87c3b726504b74e05dac1edce7437b98754" + integrity sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw== + dependencies: + "@radix-ui/react-use-callback-ref" "1.1.0" + +"@radix-ui/react-use-layout-effect@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.1.tgz#be8c7bc809b0c8934acf6657b577daf948a75399" + integrity sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/react-use-layout-effect@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz#3c2c8ce04827b26a39e442ff4888d9212268bd27" + integrity sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w== + +"@radix-ui/react-use-previous@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-previous/-/react-use-previous-1.1.0.tgz#d4dd37b05520f1d996a384eb469320c2ada8377c" + integrity sha512-Z/e78qg2YFnnXcW88A4JmTtm4ADckLno6F7OXotmkQfeuCVaKuYzqAATPhVzl3delXE7CxIV8shofPn3jPc5Og== -"@sideway/address@^4.1.3": - version "4.1.4" - resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.4.tgz#03dccebc6ea47fdc226f7d3d1ad512955d4783f0" - integrity sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw== +"@radix-ui/react-use-rect@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz#13b25b913bd3e3987cc9b073a1a164bb1cf47b88" + integrity sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ== + dependencies: + "@radix-ui/rect" "1.1.0" + +"@radix-ui/react-use-size@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz#b4dba7fbd3882ee09e8d2a44a3eed3a7e555246b" + integrity sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw== + dependencies: + "@radix-ui/react-use-layout-effect" "1.1.0" + +"@radix-ui/react-visually-hidden@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.0.tgz#ad47a8572580f7034b3807c8e6740cd41038a5a2" + integrity sha512-N8MDZqtgCgG5S3aV60INAB475osJousYpZ4cTJ2cFbMpdHS5Y6loLTH8LPtkj2QN0x93J30HT/M3qJXM0+lyeQ== + dependencies: + "@radix-ui/react-primitive" "2.0.0" + +"@radix-ui/rect@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.1.0.tgz#f817d1d3265ac5415dadc67edab30ae196696438" + integrity sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg== + +"@scure/base@~1.1.0", "@scure/base@~1.1.2": + version "1.1.7" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.7.tgz#fe973311a5c6267846aa131bc72e96c5d40d2b30" + integrity sha512-PPNYBslrLNNUQ/Yad37MHYsNQtK67EhWb6WtSvNLLPo7SdVZgkUjD6Dg+5On7zNwmskf8OX7I7Nx5oN+MIWE0g== + +"@scure/bip32@1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.2.tgz#90e78c027d5e30f0b22c1f8d50ff12f3fb7559f8" + integrity sha512-N1ZhksgwD3OBlwTv3R6KFEcPojl/W4ElJOeCZdi+vuI5QmTFwLq3OFf2zd2ROpKvxFdgZ6hUpb0dx9bVNEwYCA== + dependencies: + "@noble/curves" "~1.2.0" + "@noble/hashes" "~1.3.2" + "@scure/base" "~1.1.2" + +"@scure/bip39@1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.1.tgz#5cee8978656b272a917b7871c981e0541ad6ac2a" + integrity sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg== + dependencies: + "@noble/hashes" "~1.3.0" + "@scure/base" "~1.1.0" + +"@sideway/address@^4.1.5": + version "4.1.5" + resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.5.tgz#4bc149a0076623ced99ca8208ba780d65a99b9d5" + integrity sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q== dependencies: "@hapi/hoek" "^9.0.0" @@ -1877,120 +2731,111 @@ micromark-util-character "^1.1.0" micromark-util-symbol "^1.0.1" -"@slorber/static-site-generator-webpack-plugin@^4.0.7": - version "4.0.7" - resolved "https://registry.yarnpkg.com/@slorber/static-site-generator-webpack-plugin/-/static-site-generator-webpack-plugin-4.0.7.tgz#fc1678bddefab014e2145cbe25b3ce4e1cfc36f3" - integrity sha512-Ug7x6z5lwrz0WqdnNFOMYrDQNTPAprvHLSh6+/fmml3qUiz6l5eq+2MzLKWtn/q5K5NpSiFsZTP/fck/3vjSxA== - dependencies: - eval "^0.1.8" - p-map "^4.0.0" - webpack-sources "^3.2.2" - -"@svgr/babel-plugin-add-jsx-attribute@^6.5.1": - version "6.5.1" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.5.1.tgz#74a5d648bd0347bda99d82409d87b8ca80b9a1ba" - integrity sha512-9PYGcXrAxitycIjRmZB+Q0JaN07GZIWaTBIGQzfaZv+qr1n8X1XUEJ5rZ/vx6OVD9RRYlrNnXWExQXcmZeD/BQ== +"@svgr/babel-plugin-add-jsx-attribute@8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz#4001f5d5dd87fa13303e36ee106e3ff3a7eb8b22" + integrity sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g== -"@svgr/babel-plugin-remove-jsx-attribute@*": +"@svgr/babel-plugin-remove-jsx-attribute@8.0.0": version "8.0.0" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz#69177f7937233caca3a1afb051906698f2f59186" integrity sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA== -"@svgr/babel-plugin-remove-jsx-empty-expression@*": +"@svgr/babel-plugin-remove-jsx-empty-expression@8.0.0": version "8.0.0" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz#c2c48104cfd7dcd557f373b70a56e9e3bdae1d44" integrity sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA== -"@svgr/babel-plugin-replace-jsx-attribute-value@^6.5.1": - version "6.5.1" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.5.1.tgz#fb9d22ea26d2bc5e0a44b763d4c46d5d3f596c60" - integrity sha512-8DPaVVE3fd5JKuIC29dqyMB54sA6mfgki2H2+swh+zNJoynC8pMPzOkidqHOSc6Wj032fhl8Z0TVn1GiPpAiJg== +"@svgr/babel-plugin-replace-jsx-attribute-value@8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz#8fbb6b2e91fa26ac5d4aa25c6b6e4f20f9c0ae27" + integrity sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ== -"@svgr/babel-plugin-svg-dynamic-title@^6.5.1": - version "6.5.1" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.5.1.tgz#01b2024a2b53ffaa5efceaa0bf3e1d5a4c520ce4" - integrity sha512-FwOEi0Il72iAzlkaHrlemVurgSQRDFbk0OC8dSvD5fSBPHltNh7JtLsxmZUhjYBZo2PpcU/RJvvi6Q0l7O7ogw== +"@svgr/babel-plugin-svg-dynamic-title@8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz#1d5ba1d281363fc0f2f29a60d6d936f9bbc657b0" + integrity sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og== -"@svgr/babel-plugin-svg-em-dimensions@^6.5.1": - version "6.5.1" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.5.1.tgz#dd3fa9f5b24eb4f93bcf121c3d40ff5facecb217" - integrity sha512-gWGsiwjb4tw+ITOJ86ndY/DZZ6cuXMNE/SjcDRg+HLuCmwpcjOktwRF9WgAiycTqJD/QXqL2f8IzE2Rzh7aVXA== +"@svgr/babel-plugin-svg-em-dimensions@8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz#35e08df300ea8b1d41cb8f62309c241b0369e501" + integrity sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g== -"@svgr/babel-plugin-transform-react-native-svg@^6.5.1": - version "6.5.1" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.5.1.tgz#1d8e945a03df65b601551097d8f5e34351d3d305" - integrity sha512-2jT3nTayyYP7kI6aGutkyfJ7UMGtuguD72OjeGLwVNyfPRBD8zQthlvL+fAbAKk5n9ZNcvFkp/b1lZ7VsYqVJg== +"@svgr/babel-plugin-transform-react-native-svg@8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz#90a8b63998b688b284f255c6a5248abd5b28d754" + integrity sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q== -"@svgr/babel-plugin-transform-svg-component@^6.5.1": - version "6.5.1" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.5.1.tgz#48620b9e590e25ff95a80f811544218d27f8a250" - integrity sha512-a1p6LF5Jt33O3rZoVRBqdxL350oge54iZWHNI6LJB5tQ7EelvD/Mb1mfBiZNAan0dt4i3VArkFRjA4iObuNykQ== +"@svgr/babel-plugin-transform-svg-component@8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz#013b4bfca88779711f0ed2739f3f7efcefcf4f7e" + integrity sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw== -"@svgr/babel-preset@^6.5.1": - version "6.5.1" - resolved "https://registry.yarnpkg.com/@svgr/babel-preset/-/babel-preset-6.5.1.tgz#b90de7979c8843c5c580c7e2ec71f024b49eb828" - integrity sha512-6127fvO/FF2oi5EzSQOAjo1LE3OtNVh11R+/8FXa+mHx1ptAaS4cknIjnUA7e6j6fwGGJ17NzaTJFUwOV2zwCw== - dependencies: - "@svgr/babel-plugin-add-jsx-attribute" "^6.5.1" - "@svgr/babel-plugin-remove-jsx-attribute" "*" - "@svgr/babel-plugin-remove-jsx-empty-expression" "*" - "@svgr/babel-plugin-replace-jsx-attribute-value" "^6.5.1" - "@svgr/babel-plugin-svg-dynamic-title" "^6.5.1" - "@svgr/babel-plugin-svg-em-dimensions" "^6.5.1" - "@svgr/babel-plugin-transform-react-native-svg" "^6.5.1" - "@svgr/babel-plugin-transform-svg-component" "^6.5.1" - -"@svgr/core@^6.5.1": - version "6.5.1" - resolved "https://registry.yarnpkg.com/@svgr/core/-/core-6.5.1.tgz#d3e8aa9dbe3fbd747f9ee4282c1c77a27410488a" - integrity sha512-/xdLSWxK5QkqG524ONSjvg3V/FkNyCv538OIBdQqPNaAta3AsXj/Bd2FbvR87yMbXO2hFSWiAe/Q6IkVPDw+mw== +"@svgr/babel-preset@8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-preset/-/babel-preset-8.1.0.tgz#0e87119aecdf1c424840b9d4565b7137cabf9ece" + integrity sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug== + dependencies: + "@svgr/babel-plugin-add-jsx-attribute" "8.0.0" + "@svgr/babel-plugin-remove-jsx-attribute" "8.0.0" + "@svgr/babel-plugin-remove-jsx-empty-expression" "8.0.0" + "@svgr/babel-plugin-replace-jsx-attribute-value" "8.0.0" + "@svgr/babel-plugin-svg-dynamic-title" "8.0.0" + "@svgr/babel-plugin-svg-em-dimensions" "8.0.0" + "@svgr/babel-plugin-transform-react-native-svg" "8.1.0" + "@svgr/babel-plugin-transform-svg-component" "8.0.0" + +"@svgr/core@8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@svgr/core/-/core-8.1.0.tgz#41146f9b40b1a10beaf5cc4f361a16a3c1885e88" + integrity sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA== dependencies: - "@babel/core" "^7.19.6" - "@svgr/babel-preset" "^6.5.1" - "@svgr/plugin-jsx" "^6.5.1" + "@babel/core" "^7.21.3" + "@svgr/babel-preset" "8.1.0" camelcase "^6.2.0" - cosmiconfig "^7.0.1" + cosmiconfig "^8.1.3" + snake-case "^3.0.4" -"@svgr/hast-util-to-babel-ast@^6.5.1": - version "6.5.1" - resolved "https://registry.yarnpkg.com/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.5.1.tgz#81800bd09b5bcdb968bf6ee7c863d2288fdb80d2" - integrity sha512-1hnUxxjd83EAxbL4a0JDJoD3Dao3hmjvyvyEV8PzWmLK3B9m9NPlW7GKjFyoWE8nM7HnXzPcmmSyOW8yOddSXw== +"@svgr/hast-util-to-babel-ast@8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz#6952fd9ce0f470e1aded293b792a2705faf4ffd4" + integrity sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q== dependencies: - "@babel/types" "^7.20.0" + "@babel/types" "^7.21.3" entities "^4.4.0" -"@svgr/plugin-jsx@^6.5.1": - version "6.5.1" - resolved "https://registry.yarnpkg.com/@svgr/plugin-jsx/-/plugin-jsx-6.5.1.tgz#0e30d1878e771ca753c94e69581c7971542a7072" - integrity sha512-+UdQxI3jgtSjCykNSlEMuy1jSRQlGC7pqBCPvkG/2dATdWo082zHTTK3uhnAju2/6XpE6B5mZ3z4Z8Ns01S8Gw== +"@svgr/plugin-jsx@8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz#96969f04a24b58b174ee4cd974c60475acbd6928" + integrity sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA== dependencies: - "@babel/core" "^7.19.6" - "@svgr/babel-preset" "^6.5.1" - "@svgr/hast-util-to-babel-ast" "^6.5.1" + "@babel/core" "^7.21.3" + "@svgr/babel-preset" "8.1.0" + "@svgr/hast-util-to-babel-ast" "8.0.0" svg-parser "^2.0.4" -"@svgr/plugin-svgo@^6.5.1": - version "6.5.1" - resolved "https://registry.yarnpkg.com/@svgr/plugin-svgo/-/plugin-svgo-6.5.1.tgz#0f91910e988fc0b842f88e0960c2862e022abe84" - integrity sha512-omvZKf8ixP9z6GWgwbtmP9qQMPX4ODXi+wzbVZgomNFsUIlHA1sf4fThdwTWSsZGgvGAG6yE+b/F5gWUkcZ/iQ== +"@svgr/plugin-svgo@8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@svgr/plugin-svgo/-/plugin-svgo-8.1.0.tgz#b115b7b967b564f89ac58feae89b88c3decd0f00" + integrity sha512-Ywtl837OGO9pTLIN/onoWLmDQ4zFUycI1g76vuKGEz6evR/ZTJlJuz3G/fIkb6OVBJ2g0o6CGJzaEjfmEo3AHA== dependencies: - cosmiconfig "^7.0.1" - deepmerge "^4.2.2" - svgo "^2.8.0" + cosmiconfig "^8.1.3" + deepmerge "^4.3.1" + svgo "^3.0.2" -"@svgr/webpack@^6.5.1": - version "6.5.1" - resolved "https://registry.yarnpkg.com/@svgr/webpack/-/webpack-6.5.1.tgz#ecf027814fc1cb2decc29dc92f39c3cf691e40e8" - integrity sha512-cQ/AsnBkXPkEK8cLbv4Dm7JGXq2XrumKnL1dRpJD9rIO2fTIlJI9a1uCciYG1F2aUsox/hJQyNGbt3soDxSRkA== +"@svgr/webpack@^8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@svgr/webpack/-/webpack-8.1.0.tgz#16f1b5346f102f89fda6ec7338b96a701d8be0c2" + integrity sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA== dependencies: - "@babel/core" "^7.19.6" - "@babel/plugin-transform-react-constant-elements" "^7.18.12" - "@babel/preset-env" "^7.19.4" + "@babel/core" "^7.21.3" + "@babel/plugin-transform-react-constant-elements" "^7.21.3" + "@babel/preset-env" "^7.20.2" "@babel/preset-react" "^7.18.6" - "@babel/preset-typescript" "^7.18.6" - "@svgr/core" "^6.5.1" - "@svgr/plugin-jsx" "^6.5.1" - "@svgr/plugin-svgo" "^6.5.1" + "@babel/preset-typescript" "^7.21.0" + "@svgr/core" "8.1.0" + "@svgr/plugin-jsx" "8.1.0" + "@svgr/plugin-svgo" "8.1.0" "@szmarczak/http-timer@^5.0.1": version "5.0.1" @@ -1999,15 +2844,44 @@ dependencies: defer-to-connect "^2.0.1" +"@tailwindcss/line-clamp@^0.4.4": + version "0.4.4" + resolved "https://registry.yarnpkg.com/@tailwindcss/line-clamp/-/line-clamp-0.4.4.tgz#767cf8e5d528a5d90c9740ca66eb079f5e87d423" + integrity sha512-5U6SY5z8N42VtrCrKlsTAA35gy2VSyYtHWCsg1H87NU1SXnEfekTVlrga9fzUDrrHcGi2Lb5KenUWb4lRQT5/g== + +"@tanstack/react-table@^8.11.7": + version "8.19.3" + resolved "https://registry.yarnpkg.com/@tanstack/react-table/-/react-table-8.19.3.tgz#be1d9ee991ac06b7d4d17cc5c66469ac157bfd8a" + integrity sha512-MtgPZc4y+cCRtU16y1vh1myuyZ2OdkWgMEBzyjYsoMWMicKZGZvcDnub3Zwb6XF2pj9iRMvm1SO1n57lS0vXLw== + dependencies: + "@tanstack/table-core" "8.19.3" + +"@tanstack/react-virtual@^3.0.0-beta.60": + version "3.8.3" + resolved "https://registry.yarnpkg.com/@tanstack/react-virtual/-/react-virtual-3.8.3.tgz#3455fd7e259655ab555ac130b5ac59c3eeae98bc" + integrity sha512-9ICwbDUUzN99CJIGc373i8NLoj6zFTKI2Hlcmo0+lCSAhPQ5mxq4dGOMKmLYoEFyHcGQ64Bd6ZVbnPpM6lNK5w== + dependencies: + "@tanstack/virtual-core" "3.8.3" + +"@tanstack/table-core@8.19.3": + version "8.19.3" + resolved "https://registry.yarnpkg.com/@tanstack/table-core/-/table-core-8.19.3.tgz#669e3eca2179ee3456fc068fed8683df01607c43" + integrity sha512-IqREj9ADoml9zCAouIG/5kCGoyIxPFdqdyoxis9FisXFi5vT+iYfEfLosq4xkU/iDbMcEuAj+X8dWRLvKYDNoQ== + +"@tanstack/virtual-core@3.8.3": + version "3.8.3" + resolved "https://registry.yarnpkg.com/@tanstack/virtual-core/-/virtual-core-3.8.3.tgz#9db61ab2a96e43d9e035b1cfd82eeede6d52f171" + integrity sha512-vd2A2TnM5lbnWZnHi9B+L2gPtkSeOtJOAw358JqokIH1+v2J7vUAzFVPwB/wrye12RFOurffXu33plm4uQ+JBQ== + "@trysound/sax@0.2.0": version "0.2.0" resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad" integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA== "@tsconfig/docusaurus@^2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@tsconfig/docusaurus/-/docusaurus-2.0.2.tgz#f96c7453ce9969ef938284eac74441e2d646efd7" - integrity sha512-12HWfYmgUl4M2o76/TFufGtI68wl2k/b8qPrIrG7ci9YJLrpAtadpy897Bz5v29Mlkr7a1Hq4KHdQTKtU+2rhQ== + version "2.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/docusaurus/-/docusaurus-2.0.3.tgz#08a4a65e038a499fc4154ce32b538913d9f3c90d" + integrity sha512-3l1L5PzWVa7l0691TjnsZ0yOIEwG9DziSqu5IPZPlI5Dowi7z42cEym8Y35GHbgHvPcBfNxfrbxm7Cncn4nByQ== "@types/acorn@^4.0.0": version "4.0.6" @@ -2046,6 +2920,57 @@ dependencies: "@types/node" "*" +"@types/d3-array@^3.0.3": + version "3.2.1" + resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-3.2.1.tgz#1f6658e3d2006c4fceac53fde464166859f8b8c5" + integrity sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg== + +"@types/d3-color@*": + version "3.1.3" + resolved "https://registry.yarnpkg.com/@types/d3-color/-/d3-color-3.1.3.tgz#368c961a18de721da8200e80bf3943fb53136af2" + integrity sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A== + +"@types/d3-ease@^3.0.0": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-ease/-/d3-ease-3.0.2.tgz#e28db1bfbfa617076f7770dd1d9a48eaa3b6c51b" + integrity sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA== + +"@types/d3-interpolate@^3.0.1": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz#412b90e84870285f2ff8a846c6eb60344f12a41c" + integrity sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA== + dependencies: + "@types/d3-color" "*" + +"@types/d3-path@*": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-3.1.0.tgz#2b907adce762a78e98828f0b438eaca339ae410a" + integrity sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ== + +"@types/d3-scale@^4.0.2": + version "4.0.8" + resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-4.0.8.tgz#d409b5f9dcf63074464bf8ddfb8ee5a1f95945bb" + integrity sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ== + dependencies: + "@types/d3-time" "*" + +"@types/d3-shape@^3.1.0": + version "3.1.6" + resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-3.1.6.tgz#65d40d5a548f0a023821773e39012805e6e31a72" + integrity sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA== + dependencies: + "@types/d3-path" "*" + +"@types/d3-time@*", "@types/d3-time@^3.0.0": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-3.0.3.tgz#3c186bbd9d12b9d84253b6be6487ca56b54f88be" + integrity sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw== + +"@types/d3-timer@^3.0.0": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-timer/-/d3-timer-3.0.2.tgz#70bbda77dc23aa727413e22e214afa3f0e852f70" + integrity sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw== + "@types/debug@^4.0.0": version "4.1.12" resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.12.tgz#a155f21690871953410df4b6b6f53187f0500917" @@ -2062,29 +2987,29 @@ "@types/estree" "*" "@types/eslint@*": - version "8.56.1" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.56.1.tgz#988cabb39c973e9200f35fdbb29d17992965bb08" - integrity sha512-18PLWRzhy9glDQp3+wOgfLYRWlhgX0azxgJ63rdpoUHyrC9z0f5CkFburjQx4uD7ZCruw85ZtMt6K+L+R8fLJQ== + version "9.6.0" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-9.6.0.tgz#51d4fe4d0316da9e9f2c80884f2c20ed5fb022ff" + integrity sha512-gi6WQJ7cHRgZxtkQEoyHMppPjq9Kxo5Tjn2prSKDSmZrCz8TZ3jSRCeTJm+WoM+oB0WG37bRqLzaaU3q7JypGg== dependencies: "@types/estree" "*" "@types/json-schema" "*" "@types/estree-jsx@^1.0.0": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@types/estree-jsx/-/estree-jsx-1.0.3.tgz#f8aa833ec986d82b8271a294a92ed1565bf2c66a" - integrity sha512-pvQ+TKeRHeiUGRhvYwRrQ/ISnohKkSJR14fT2yqyZ4e9K5vqc7hrtY2Y1Dw0ZwAzQ6DQsxsaCUuSIIi8v0Cq6w== + version "1.0.5" + resolved "https://registry.yarnpkg.com/@types/estree-jsx/-/estree-jsx-1.0.5.tgz#858a88ea20f34fe65111f005a689fa1ebf70dc18" + integrity sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg== dependencies: "@types/estree" "*" -"@types/estree@*", "@types/estree@^1.0.0": +"@types/estree@*", "@types/estree@^1.0.0", "@types/estree@^1.0.5": version "1.0.5" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== "@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.33": - version "4.17.41" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.41.tgz#5077defa630c2e8d28aa9ffc2c01c157c305bef6" - integrity sha512-OaJ7XLaelTgrvlZD8/aa0vvvxZdUmlCn6MtWeB7TkiKW70BQLc9XEPpDLPdbo52ZhXUCrznlWdCHWxJWtdyajA== + version "4.19.5" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz#218064e321126fcf9048d1ca25dd2465da55d9c6" + integrity sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg== dependencies: "@types/node" "*" "@types/qs" "*" @@ -2107,16 +3032,16 @@ integrity sha512-YQV9bUsemkzG81Ea295/nF/5GijnD2Af7QhEofh7xu+kvCN6RdodgNwwGWXB5GMI3NoyvQo0odNctoH/qLMIpg== "@types/hast@^2.0.0": - version "2.3.9" - resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.9.tgz#a9a1b5bbce46e8a1312e977364bacabc8e93d2cf" - integrity sha512-pTHyNlaMD/oKJmS+ZZUyFUcsZeBZpC0lmGquw98CqRVNgAdJZJeD7GoeLiT6Xbx5rU9VCjSt0RwEvDgzh4obFw== + version "2.3.10" + resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.10.tgz#5c9d9e0b304bbb8879b857225c5ebab2d81d7643" + integrity sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw== dependencies: "@types/unist" "^2" "@types/hast@^3.0.0": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/hast/-/hast-3.0.3.tgz#7f75e6b43bc3f90316046a287d9ad3888309f7e1" - integrity sha512-2fYGlaDy/qyLlhidX42wAH0KBi2TCjKMH8CHmBXgRlJ3Y+OXTiqsPQ6IWarZKwF1JoUcAJdPogv1d4b0COTpmQ== + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/hast/-/hast-3.0.4.tgz#1d6b39993b82cea6ad783945b0508c25903e15aa" + integrity sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ== dependencies: "@types/unist" "*" @@ -2172,21 +3097,16 @@ integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== "@types/mdast@^4.0.0", "@types/mdast@^4.0.2": - version "4.0.3" - resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-4.0.3.tgz#1e011ff013566e919a4232d1701ad30d70cab333" - integrity sha512-LsjtqsyF+d2/yFOYaN22dHZI1Cpwkrj+g06G8+qtUKlhovPW89YhqSnfKtMbkgmEtYpH2gydRNULd6y8mciAFg== + version "4.0.4" + resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-4.0.4.tgz#7ccf72edd2f1aa7dd3437e180c64373585804dd6" + integrity sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA== dependencies: "@types/unist" "*" "@types/mdx@^2.0.0": - version "2.0.10" - resolved "https://registry.yarnpkg.com/@types/mdx/-/mdx-2.0.10.tgz#0d7b57fb1d83e27656156e4ee0dfba96532930e4" - integrity sha512-Rllzc5KHk0Al5/WANwgSPl1/CwjqCy+AZrGd78zuK+jO9aDM6ffblZ+zIjgPNAaEBmlO0RYDvLNh7wD0zKVgEg== - -"@types/mime@*": - version "3.0.4" - resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.4.tgz#2198ac274de6017b44d941e00261d5bc6a0e0a45" - integrity sha512-iJt33IQnVRkqeqC7PzBHPTC6fDlRNRW8vjrgqtScAhrmMwe8c4Eo7+fUGTa+XdWrpEgpyKWMYmi2dIwMAYRzPw== + version "2.0.13" + resolved "https://registry.yarnpkg.com/@types/mdx/-/mdx-2.0.13.tgz#68f6877043d377092890ff5b298152b0a21671bd" + integrity sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw== "@types/mime@^1": version "1.3.5" @@ -2206,9 +3126,9 @@ "@types/node" "*" "@types/node@*": - version "20.10.6" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.10.6.tgz#a3ec84c22965802bf763da55b2394424f22bfbb5" - integrity sha512-Vac8H+NlRNNlAmDfGUP7b5h/KA+AtWIzuXy0E6OyP8f1tCLYAtPvKRRDJjAPqhpCb0t6U2j7/xqAuLEebW2kiw== + version "20.14.12" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.12.tgz#129d7c3a822cb49fc7ff661235f19cfefd422b49" + integrity sha512-r7wNXakLeSsGT0H1AU863vS2wa5wBOK4bWMjZz2wj+8nBx+m5PeIn0k8AloSLpRuiwdRQZwarZqHE4FNArPuJQ== dependencies: undici-types "~5.26.4" @@ -2228,19 +3148,19 @@ integrity sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw== "@types/prismjs@^1.26.0": - version "1.26.3" - resolved "https://registry.yarnpkg.com/@types/prismjs/-/prismjs-1.26.3.tgz#47fe8e784c2dee24fe636cab82e090d3da9b7dec" - integrity sha512-A0D0aTXvjlqJ5ZILMz3rNfDBOx9hHxLZYv2by47Sm/pqW35zzjusrZTryatjN/Rf8Us2gZrJD+KeHbUSTux1Cw== + version "1.26.4" + resolved "https://registry.yarnpkg.com/@types/prismjs/-/prismjs-1.26.4.tgz#1a9e1074619ce1d7322669e5b46fbe823925103a" + integrity sha512-rlAnzkW2sZOjbqZ743IHUhFcvzaGbqijwOu8QZnZCjfQzBqFE3s4lOTJEsxikImav9uzz/42I+O7YUs1mWgMlg== "@types/prop-types@*": - version "15.7.11" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.11.tgz#2596fb352ee96a1379c657734d4b913a613ad563" - integrity sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng== + version "15.7.12" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.12.tgz#12bb1e2be27293c1406acb6af1c3f3a1481d98c6" + integrity sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q== "@types/qs@*": - version "6.9.11" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.11.tgz#208d8a30bc507bd82e03ada29e4732ea46a6bbda" - integrity sha512-oGk0gmhnEJK4Yyk+oI7EfXsLayXatCWPHary1MtcmbAifkobT9cM9yutG/hZKIseOU0MqbIwQ/u2nn/Gb+ltuQ== + version "6.9.15" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.15.tgz#adde8a060ec9c305a82de1babc1056e73bd64dce" + integrity sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg== "@types/range-parser@*": version "1.2.7" @@ -2274,12 +3194,11 @@ "@types/react" "*" "@types/react@*": - version "18.2.46" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.46.tgz#f04d6c528f8f136ea66333bc66abcae46e2680df" - integrity sha512-nNCvVBcZlvX4NU1nRRNV/mFl1nNRuTuslAJglQsq+8ldXe5Xv0Wd2f7WTE3jOxhLH2BFfiZGC6GCp+kHQbgG+w== + version "18.3.3" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.3.tgz#9679020895318b0915d7a3ab004d92d33375c45f" + integrity sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw== dependencies: "@types/prop-types" "*" - "@types/scheduler" "*" csstype "^3.0.2" "@types/retry@0.12.0": @@ -2294,11 +3213,6 @@ dependencies: "@types/node" "*" -"@types/scheduler@*": - version "0.16.8" - resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.8.tgz#ce5ace04cfeabe7ef87c0091e50752e36707deff" - integrity sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A== - "@types/send@*": version "0.17.4" resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.4.tgz#6619cd24e7270793702e4e6a4b958a9010cfc57a" @@ -2315,13 +3229,13 @@ "@types/express" "*" "@types/serve-static@*", "@types/serve-static@^1.13.10": - version "1.15.5" - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.5.tgz#15e67500ec40789a1e8c9defc2d32a896f05b033" - integrity sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ== + version "1.15.7" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.7.tgz#22174bbd74fb97fe303109738e9b5c2f3064f714" + integrity sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw== dependencies: "@types/http-errors" "*" - "@types/mime" "*" "@types/node" "*" + "@types/send" "*" "@types/sockjs@^0.3.33": version "0.3.36" @@ -2330,6 +3244,11 @@ dependencies: "@types/node" "*" +"@types/stylis@4.2.5": + version "4.2.5" + resolved "https://registry.yarnpkg.com/@types/stylis/-/stylis-4.2.5.tgz#1daa6456f40959d06157698a653a9ab0a70281df" + integrity sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw== + "@types/unist@*", "@types/unist@^3.0.0": version "3.0.2" resolved "https://registry.yarnpkg.com/@types/unist/-/unist-3.0.2.tgz#6dd61e43ef60b34086287f83683a5c1b2dc53d20" @@ -2341,9 +3260,9 @@ integrity sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA== "@types/ws@^8.5.5": - version "8.5.10" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.10.tgz#4acfb517970853fa6574a3a6886791d04a396787" - integrity sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A== + version "8.5.11" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.11.tgz#90ad17b3df7719ce3e6bc32f83ff954d38656508" + integrity sha512-4+q7P5h3SpJxaBft0Dzpbr6lmMaqh0Jr2tbhJZ/luAwvD7ohSCniYkwz/pLxuT2h0EOa6QADgJj1Ko+TzRfZ+w== dependencies: "@types/node" "*" @@ -2364,15 +3283,20 @@ resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== +"@vercel/edge@^1.1.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@vercel/edge/-/edge-1.1.2.tgz#b89bc5fa927b9af64c99311afb4dcf48e7b9e87a" + integrity sha512-wt5SnhsMahWX8U9ZZhFUQoiXhMn/CUxA5xeMdZX1cwyOL1ZbDR3rNI8HRT9RSU73nDxeF6jlnqJyp/0Jy0VM2A== + "@vscode/codicons@^0.0.35": version "0.0.35" resolved "https://registry.yarnpkg.com/@vscode/codicons/-/codicons-0.0.35.tgz#7424a647f39c6e71c86c1edf12bfc27196c8fba1" integrity sha512-7iiKdA5wHVYSbO7/Mm0hiHD3i4h+9hKUe1O4hISAe/nHhagMwb2ZbFC8jU6d7Cw+JNT2dWXN2j+WHbkhT5/l2w== -"@webassemblyjs/ast@1.11.6", "@webassemblyjs/ast@^1.11.5": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.6.tgz#db046555d3c413f8966ca50a95176a0e2c642e24" - integrity sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q== +"@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.12.1.tgz#bb16a0e8b1914f979f45864c23819cc3e3f0d4bb" + integrity sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg== dependencies: "@webassemblyjs/helper-numbers" "1.11.6" "@webassemblyjs/helper-wasm-bytecode" "1.11.6" @@ -2387,10 +3311,10 @@ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768" integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q== -"@webassemblyjs/helper-buffer@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz#b66d73c43e296fd5e88006f18524feb0f2c7c093" - integrity sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA== +"@webassemblyjs/helper-buffer@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz#6df20d272ea5439bf20ab3492b7fb70e9bfcb3f6" + integrity sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw== "@webassemblyjs/helper-numbers@1.11.6": version "1.11.6" @@ -2406,15 +3330,15 @@ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9" integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA== -"@webassemblyjs/helper-wasm-section@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz#ff97f3863c55ee7f580fd5c41a381e9def4aa577" - integrity sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g== +"@webassemblyjs/helper-wasm-section@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz#3da623233ae1a60409b509a52ade9bc22a37f7bf" + integrity sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g== dependencies: - "@webassemblyjs/ast" "1.11.6" - "@webassemblyjs/helper-buffer" "1.11.6" + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/wasm-gen" "1.11.6" + "@webassemblyjs/wasm-gen" "1.12.1" "@webassemblyjs/ieee754@1.11.6": version "1.11.6" @@ -2435,59 +3359,59 @@ resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a" integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA== -"@webassemblyjs/wasm-edit@^1.11.5": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz#c72fa8220524c9b416249f3d94c2958dfe70ceab" - integrity sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw== +"@webassemblyjs/wasm-edit@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz#9f9f3ff52a14c980939be0ef9d5df9ebc678ae3b" + integrity sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g== dependencies: - "@webassemblyjs/ast" "1.11.6" - "@webassemblyjs/helper-buffer" "1.11.6" + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/helper-wasm-section" "1.11.6" - "@webassemblyjs/wasm-gen" "1.11.6" - "@webassemblyjs/wasm-opt" "1.11.6" - "@webassemblyjs/wasm-parser" "1.11.6" - "@webassemblyjs/wast-printer" "1.11.6" - -"@webassemblyjs/wasm-gen@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz#fb5283e0e8b4551cc4e9c3c0d7184a65faf7c268" - integrity sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA== - dependencies: - "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/helper-wasm-section" "1.12.1" + "@webassemblyjs/wasm-gen" "1.12.1" + "@webassemblyjs/wasm-opt" "1.12.1" + "@webassemblyjs/wasm-parser" "1.12.1" + "@webassemblyjs/wast-printer" "1.12.1" + +"@webassemblyjs/wasm-gen@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz#a6520601da1b5700448273666a71ad0a45d78547" + integrity sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w== + dependencies: + "@webassemblyjs/ast" "1.12.1" "@webassemblyjs/helper-wasm-bytecode" "1.11.6" "@webassemblyjs/ieee754" "1.11.6" "@webassemblyjs/leb128" "1.11.6" "@webassemblyjs/utf8" "1.11.6" -"@webassemblyjs/wasm-opt@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz#d9a22d651248422ca498b09aa3232a81041487c2" - integrity sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g== +"@webassemblyjs/wasm-opt@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz#9e6e81475dfcfb62dab574ac2dda38226c232bc5" + integrity sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg== dependencies: - "@webassemblyjs/ast" "1.11.6" - "@webassemblyjs/helper-buffer" "1.11.6" - "@webassemblyjs/wasm-gen" "1.11.6" - "@webassemblyjs/wasm-parser" "1.11.6" + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/wasm-gen" "1.12.1" + "@webassemblyjs/wasm-parser" "1.12.1" -"@webassemblyjs/wasm-parser@1.11.6", "@webassemblyjs/wasm-parser@^1.11.5": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz#bb85378c527df824004812bbdb784eea539174a1" - integrity sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ== +"@webassemblyjs/wasm-parser@1.12.1", "@webassemblyjs/wasm-parser@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz#c47acb90e6f083391e3fa61d113650eea1e95937" + integrity sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ== dependencies: - "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/ast" "1.12.1" "@webassemblyjs/helper-api-error" "1.11.6" "@webassemblyjs/helper-wasm-bytecode" "1.11.6" "@webassemblyjs/ieee754" "1.11.6" "@webassemblyjs/leb128" "1.11.6" "@webassemblyjs/utf8" "1.11.6" -"@webassemblyjs/wast-printer@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz#a7bf8dd7e362aeb1668ff43f35cb849f188eff20" - integrity sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A== +"@webassemblyjs/wast-printer@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz#bcecf661d7d1abdaf989d8341a4833e33e2b31ac" + integrity sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA== dependencies: - "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/ast" "1.12.1" "@xtuc/long" "4.2.2" "@xtuc/ieee754@^1.2.0": @@ -2505,6 +3429,11 @@ abbrev@1: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== +abitype@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.0.0.tgz#237176dace81d90d018bebf3a45cb42f2a2d9e97" + integrity sha512-NMeMah//6bJ56H5XRj8QCV4AwuW6hB6zqz2LnhhLdcWVQOsXki6/Pn3APeqxCma62nXIcmZWdu1DlHWS74umVQ== + accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" @@ -2523,10 +3452,10 @@ acorn-dynamic-import@^4.0.0: resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz#482210140582a36b83c3e342e1cfebcaa9240948" integrity sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw== -acorn-import-assertions@^1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" - integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== +acorn-import-attributes@^1.9.5: + version "1.9.5" + resolved "https://registry.yarnpkg.com/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz#7eb1557b1ba05ef18b5ed0ec67591bfab04688ef" + integrity sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ== acorn-jsx@^5.0.0, acorn-jsx@^5.0.1: version "5.3.2" @@ -2534,19 +3463,21 @@ acorn-jsx@^5.0.0, acorn-jsx@^5.0.1: integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== acorn-walk@^8.0.0: - version "8.3.1" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.1.tgz#2f10f5b69329d90ae18c58bf1fa8fccd8b959a43" - integrity sha512-TgUZgYvqZprrl7YldZNoa9OciCAyZR+Ejm9eXzKCmjsF5IKp/wgQ7Z/ZpjpGTIUPwrHQIcYeI8qDh4PsEwxMbw== + version "8.3.3" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.3.tgz#9caeac29eefaa0c41e3d4c65137de4d6f34df43e" + integrity sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw== + dependencies: + acorn "^8.11.0" acorn@^6.1.1: version "6.4.2" resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== -acorn@^8.0.0, acorn@^8.0.4, acorn@^8.7.1, acorn@^8.8.2: - version "8.11.3" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" - integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== +acorn@^8.0.0, acorn@^8.0.4, acorn@^8.11.0, acorn@^8.7.1, acorn@^8.8.2: + version "8.12.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248" + integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg== address@^1.0.1, address@^1.1.2: version "1.2.2" @@ -2591,41 +3522,42 @@ ajv@^6.12.2, ajv@^6.12.5: uri-js "^4.2.2" ajv@^8.0.0, ajv@^8.9.0: - version "8.12.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" - integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== + version "8.17.1" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" + integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== dependencies: - fast-deep-equal "^3.1.1" + fast-deep-equal "^3.1.3" + fast-uri "^3.0.1" json-schema-traverse "^1.0.0" require-from-string "^2.0.2" - uri-js "^4.2.2" algoliasearch-helper@^3.13.3: - version "3.16.1" - resolved "https://registry.yarnpkg.com/algoliasearch-helper/-/algoliasearch-helper-3.16.1.tgz#421e3554ec86e14e60e7e0bf796aef61cf4a06ec" - integrity sha512-qxAHVjjmT7USVvrM8q6gZGaJlCK1fl4APfdAA7o8O6iXEc68G0xMNrzRkxoB/HmhhvyHnoteS/iMTiHiTcQQcg== + version "3.22.3" + resolved "https://registry.yarnpkg.com/algoliasearch-helper/-/algoliasearch-helper-3.22.3.tgz#7c67a1a87c3adb0b52ef726a3de3c0b0edcbb5d1" + integrity sha512-2eoEz8mG4KHE+DzfrBTrCmDPxVXv7aZZWPojAJFtARpxxMO6lkos1dJ+XDCXdPvq7q3tpYWRi6xXmVQikejtpA== dependencies: "@algolia/events" "^4.0.1" algoliasearch@^4.18.0, algoliasearch@^4.19.1: - version "4.22.0" - resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-4.22.0.tgz#9ece4446b5ab0af941ef97553c18ddcd1b8040a5" - integrity sha512-gfceltjkwh7PxXwtkS8KVvdfK+TSNQAWUeNSxf4dA29qW5tf2EGwa8jkJujlT9jLm17cixMVoGNc+GJFO1Mxhg== - dependencies: - "@algolia/cache-browser-local-storage" "4.22.0" - "@algolia/cache-common" "4.22.0" - "@algolia/cache-in-memory" "4.22.0" - "@algolia/client-account" "4.22.0" - "@algolia/client-analytics" "4.22.0" - "@algolia/client-common" "4.22.0" - "@algolia/client-personalization" "4.22.0" - "@algolia/client-search" "4.22.0" - "@algolia/logger-common" "4.22.0" - "@algolia/logger-console" "4.22.0" - "@algolia/requester-browser-xhr" "4.22.0" - "@algolia/requester-common" "4.22.0" - "@algolia/requester-node-http" "4.22.0" - "@algolia/transporter" "4.22.0" + version "4.24.0" + resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-4.24.0.tgz#b953b3e2309ef8f25da9de311b95b994ac918275" + integrity sha512-bf0QV/9jVejssFBmz2HQLxUadxk574t4iwjCKp5E7NBzwKkrDEhKPISIIjAU/p6K5qDx3qoeh4+26zWN1jmw3g== + dependencies: + "@algolia/cache-browser-local-storage" "4.24.0" + "@algolia/cache-common" "4.24.0" + "@algolia/cache-in-memory" "4.24.0" + "@algolia/client-account" "4.24.0" + "@algolia/client-analytics" "4.24.0" + "@algolia/client-common" "4.24.0" + "@algolia/client-personalization" "4.24.0" + "@algolia/client-search" "4.24.0" + "@algolia/logger-common" "4.24.0" + "@algolia/logger-console" "4.24.0" + "@algolia/recommend" "4.24.0" + "@algolia/requester-browser-xhr" "4.24.0" + "@algolia/requester-common" "4.24.0" + "@algolia/requester-node-http" "4.24.0" + "@algolia/transporter" "4.24.0" ansi-align@^3.0.1: version "3.0.1" @@ -2708,6 +3640,13 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== +aria-hidden@^1.1.1: + version "1.2.4" + resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.2.4.tgz#b78e383fdbc04d05762c78b4a25a501e736c4522" + integrity sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A== + dependencies: + tslib "^2.0.0" + array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" @@ -2735,14 +3674,14 @@ autocomplete.js@^0.37.0: dependencies: immediate "^3.2.3" -autoprefixer@^10.4.12, autoprefixer@^10.4.14: - version "10.4.16" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.16.tgz#fad1411024d8670880bdece3970aa72e3572feb8" - integrity sha512-7vd3UC6xKp0HLfua5IjZlcXvGAGy7cBAXTg2lyQ/8WpNhd6SiZ8Be+xm3FyBSYJx5GKcpRCzBh7RH4/0dnY+uQ== +autoprefixer@^10.4.14, autoprefixer@^10.4.19: + version "10.4.19" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.19.tgz#ad25a856e82ee9d7898c59583c1afeb3fa65f89f" + integrity sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew== dependencies: - browserslist "^4.21.10" - caniuse-lite "^1.0.30001538" - fraction.js "^4.3.6" + browserslist "^4.23.0" + caniuse-lite "^1.0.30001599" + fraction.js "^4.3.7" normalize-range "^0.1.2" picocolors "^1.0.0" postcss-value-parser "^4.2.0" @@ -2762,29 +3701,29 @@ babel-plugin-dynamic-import-node@^2.3.3: dependencies: object.assign "^4.1.0" -babel-plugin-polyfill-corejs2@^0.4.7: - version "0.4.7" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.7.tgz#679d1b94bf3360f7682e11f2cb2708828a24fe8c" - integrity sha512-LidDk/tEGDfuHW2DWh/Hgo4rmnw3cduK6ZkOI1NPFceSK3n/yAGeOsNT7FLnSGHkXj3RHGSEVkN3FsCTY6w2CQ== +babel-plugin-polyfill-corejs2@^0.4.10: + version "0.4.11" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz#30320dfe3ffe1a336c15afdcdafd6fd615b25e33" + integrity sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q== dependencies: "@babel/compat-data" "^7.22.6" - "@babel/helper-define-polyfill-provider" "^0.4.4" + "@babel/helper-define-polyfill-provider" "^0.6.2" semver "^6.3.1" -babel-plugin-polyfill-corejs3@^0.8.7: - version "0.8.7" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.7.tgz#941855aa7fdaac06ed24c730a93450d2b2b76d04" - integrity sha512-KyDvZYxAzkC0Aj2dAPyDzi2Ym15e5JKZSK+maI7NAwSqofvuFglbSsxE7wUOvTg9oFVnHMzVzBKcqEb4PJgtOA== +babel-plugin-polyfill-corejs3@^0.10.1, babel-plugin-polyfill-corejs3@^0.10.4: + version "0.10.4" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz#789ac82405ad664c20476d0233b485281deb9c77" + integrity sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg== dependencies: - "@babel/helper-define-polyfill-provider" "^0.4.4" - core-js-compat "^3.33.1" + "@babel/helper-define-polyfill-provider" "^0.6.1" + core-js-compat "^3.36.1" -babel-plugin-polyfill-regenerator@^0.5.4: - version "0.5.4" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.4.tgz#c6fc8eab610d3a11eb475391e52584bacfc020f4" - integrity sha512-S/x2iOCvDaCASLYsOOgWOq4bCfKYVqvO/uxjkaYyZ3rVsVE3CeAI/c84NpyuBBymEgNvHgjEot3a9/Z/kXvqsg== +babel-plugin-polyfill-regenerator@^0.6.1: + version "0.6.2" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz#addc47e240edd1da1058ebda03021f382bba785e" + integrity sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg== dependencies: - "@babel/helper-define-polyfill-provider" "^0.4.4" + "@babel/helper-define-polyfill-provider" "^0.6.2" bail@^1.0.0: version "1.0.5" @@ -2817,17 +3756,17 @@ big.js@^5.2.2: integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== binary-extensions@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" - integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + version "2.3.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== -body-parser@1.20.1: - version "1.20.1" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" - integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== +body-parser@1.20.2: + version "1.20.2" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd" + integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA== dependencies: bytes "3.1.2" - content-type "~1.0.4" + content-type "~1.0.5" debug "2.6.9" depd "2.0.0" destroy "1.2.0" @@ -2835,14 +3774,14 @@ body-parser@1.20.1: iconv-lite "0.4.24" on-finished "2.4.1" qs "6.11.0" - raw-body "2.5.1" + raw-body "2.5.2" type-is "~1.6.18" unpipe "1.0.0" bonjour-service@^1.0.11: - version "1.2.0" - resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.2.0.tgz#1c56da07a76e33b049ba7d865859abee5297f55a" - integrity sha512-xdzMA6JGckxyJzZByjEWRcfKmDxXaGXZWVftah3FkCqdlePNS9DjHSUN5zkP4oEfz/t0EXXlro88EIhzwMB4zA== + version "1.2.1" + resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.2.1.tgz#eb41b3085183df3321da1264719fbada12478d02" + integrity sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw== dependencies: fast-deep-equal "^3.1.3" multicast-dns "^7.2.5" @@ -2895,22 +3834,22 @@ brace-expansion@^2.0.1: dependencies: balanced-match "^1.0.0" -braces@^3.0.2, braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== +braces@^3.0.3, braces@~3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== dependencies: - fill-range "^7.0.1" + fill-range "^7.1.1" -browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.18.1, browserslist@^4.21.10, browserslist@^4.21.4, browserslist@^4.22.2: - version "4.22.2" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.2.tgz#704c4943072bd81ea18997f3bd2180e89c77874b" - integrity sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A== +browserslist@^4.0.0, browserslist@^4.18.1, browserslist@^4.21.10, browserslist@^4.23.0, browserslist@^4.23.1: + version "4.23.2" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.2.tgz#244fe803641f1c19c28c48c4b6ec9736eb3d32ed" + integrity sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA== dependencies: - caniuse-lite "^1.0.30001565" - electron-to-chromium "^1.4.601" + caniuse-lite "^1.0.30001640" + electron-to-chromium "^1.4.820" node-releases "^2.0.14" - update-browserslist-db "^1.0.13" + update-browserslist-db "^1.1.0" buffer-from@^1.0.0: version "1.1.2" @@ -2945,14 +3884,16 @@ cacheable-request@^10.2.8: normalize-url "^8.0.0" responselike "^3.0.0" -call-bind@^1.0.0, call-bind@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.5.tgz#6fa2b7845ce0ea49bf4d8b9ef64727a2c2e2e513" - integrity sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ== +call-bind@^1.0.5, call-bind@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" + integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" function-bind "^1.1.2" - get-intrinsic "^1.2.1" - set-function-length "^1.1.1" + get-intrinsic "^1.2.4" + set-function-length "^1.2.1" callsites@^3.0.0: version "3.1.0" @@ -2977,6 +3918,50 @@ camelcase@^7.0.1: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-7.0.1.tgz#f02e50af9fd7782bc8b88a3558c32fd3a388f048" integrity sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw== +camelize@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.1.tgz#89b7e16884056331a35d6b5ad064332c91daa6c3" + integrity sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ== + +can-dom-mutate@^2.0.9: + version "2.0.9" + resolved "https://registry.yarnpkg.com/can-dom-mutate/-/can-dom-mutate-2.0.9.tgz#8325a059f2dcd2951438ead4dbb9cf6047233762" + integrity sha512-t0CL8uvUu2n8Mx1h8Q6M0oE+F9HwP56H6JzdGspeXZTQR+Lxs72ozr/a+d25Au/fyPCCwga+SygxA+NEsqCu8A== + dependencies: + can-globals "^1.0.0" + can-namespace "1.0.0" + can-reflect "^1.17.6" + can-symbol "^1.6.4" + +can-globals@^1.0.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/can-globals/-/can-globals-1.2.2.tgz#bf6eb3a3ab4ca46dfd0b3a1c8a2cc9932674cb14" + integrity sha512-wcsZoHIHd+pJ7Tx5NExRJggr3NGoOjJ38mRWlfyE6jAwG7N+Ha4opgosczrFBSHcVLeEJTg2WikCWJjOtgIP/w== + dependencies: + can-namespace "^1.0.0" + can-reflect "^1.2.6" + can-symbol "^1.0.0" + +can-namespace@1.0.0, can-namespace@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/can-namespace/-/can-namespace-1.0.0.tgz#0b8fafafbb11352b9ead4222ffe3822405b43e99" + integrity sha512-1sBY/SLwwcmxz3NhyVhLjt2uD/dZ7V1mII82/MIXSDn5QXnslnosJnjlP8+yTx2uTCRvw1jlFDElRs4pX7AG5w== + +can-reflect@^1.17.6, can-reflect@^1.2.6: + version "1.19.2" + resolved "https://registry.yarnpkg.com/can-reflect/-/can-reflect-1.19.2.tgz#a6029322ec18358543216243926bebd9a3d3855c" + integrity sha512-cacR7uz67IscRJzYm5Fqzx/Nzh7xuR4ybiyn/hc2D8CNK37p/YanhGOn00JELnCNAN+DYfjnG+hBlph0jz6jHw== + dependencies: + can-namespace "^1.0.0" + can-symbol "^1.7.0" + +can-symbol@^1.0.0, can-symbol@^1.6.4, can-symbol@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/can-symbol/-/can-symbol-1.7.0.tgz#cdedb95a3e23f7f7ad0d2801afbb083f9f543ec6" + integrity sha512-4drWe3ohkmnk2Z6sOoJ5K7OoHTHzlCAMTPrTAcolUox78Csrlo6qJz9YlyCeskc9Whx+UXmT2tplXvur51k9iw== + dependencies: + can-namespace "^1.0.0" + caniuse-api@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" @@ -2987,10 +3972,10 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001538, caniuse-lite@^1.0.30001565: - version "1.0.30001574" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001574.tgz#fb4f1359c77f6af942510493672e1ec7ec80230c" - integrity sha512-BtYEK4r/iHt/txm81KBudCUcTy7t+s9emrIaHqjYurQ10x71zJ5VQ9x1dYPcz/b+pKSp4y/v1xSI67A+LzpNyg== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001599, caniuse-lite@^1.0.30001640: + version "1.0.30001643" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001643.tgz#9c004caef315de9452ab970c3da71085f8241dbd" + integrity sha512-ERgWGNleEilSrHM6iUz/zJNSQTP8Mr21wDWpdgvRwcTXGAq6jMtOUPP4dqFPTdKqZ2wKTdtB+uucZ3MRpAUSmg== ccount@^2.0.0: version "2.0.1" @@ -3029,16 +4014,31 @@ character-entities-html4@^2.0.0: resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-2.1.0.tgz#1f1adb940c971a4b22ba39ddca6b618dc6e56b2b" integrity sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA== +character-entities-legacy@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz#94bc1845dce70a5bb9d2ecc748725661293d8fc1" + integrity sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA== + character-entities-legacy@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz#76bc83a90738901d7bc223a9e93759fdd560125b" integrity sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ== +character-entities@^1.0.0: + version "1.2.4" + resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.4.tgz#e12c3939b7eaf4e5b15e7ad4c5e28e1d48c5b16b" + integrity sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw== + character-entities@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-2.0.2.tgz#2d09c2e72cd9523076ccb21157dff66ad43fcc22" integrity sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ== +character-reference-invalid@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" + integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== + character-reference-invalid@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz#85c66b041e43b47210faf401278abf808ac45cb9" @@ -3070,9 +4070,9 @@ cheerio@^1.0.0-rc.12: parse5-htmlparser2-tree-adapter "^7.0.0" chokidar@^3.4.2, chokidar@^3.5.3: - version "3.5.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" - integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== dependencies: anymatch "~3.1.2" braces "~3.0.2" @@ -3085,9 +4085,9 @@ chokidar@^3.4.2, chokidar@^3.5.3: fsevents "~2.3.2" chrome-trace-event@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" - integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== + version "1.0.4" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz#05bffd7ff928465093314708c93bdfa9bd1f0f5b" + integrity sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ== ci-info@^3.2.0: version "3.9.0" @@ -3117,14 +4117,19 @@ cli-boxes@^3.0.0: integrity sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g== cli-table3@^0.6.3: - version "0.6.3" - resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.3.tgz#61ab765aac156b52f222954ffc607a6f01dbeeb2" - integrity sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg== + version "0.6.5" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.5.tgz#013b91351762739c16a9567c21a04632e449bf2f" + integrity sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ== dependencies: string-width "^4.2.0" optionalDependencies: "@colors/colors" "1.5.0" +client-only@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" + integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== + clone-deep@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" @@ -3139,10 +4144,20 @@ clsx@^1.2.1: resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== -clsx@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.0.tgz#e851283bcb5c80ee7608db18487433f7b23f77cb" - integrity sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg== +clsx@^2.0.0, clsx@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999" + integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA== + +cmdk-react17@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/cmdk-react17/-/cmdk-react17-1.0.0.tgz#38424086014d6ca66ae74ce01f30c88fd45be34c" + integrity sha512-J83cFOqs/twjFQzN+CciDZ/YBX8K5vGFD5EAfCi3xJDgdCj3/XDi9pv7jYdrSCf7gRkUBV7x3PFBh4AP3Ue+0w== + dependencies: + "@radix-ui/react-dialog" "1.0.5" + "@radix-ui/react-id" "^1.0.1" + "@radix-ui/react-primitive" "1.0.3" + use-sync-external-store "^1.2.0" collapse-white-space@^2.0.0: version "2.1.0" @@ -3178,7 +4193,12 @@ color-support@^1.1.2: resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== -colord@^2.9.1: +color2k@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/color2k/-/color2k-2.0.3.tgz#a771244f6b6285541c82aa65ff0a0c624046e533" + integrity sha512-zW190nQTIoXcGCaU08DvVNFTmQhUpnJfVuAKfWqUQkflXKpaDdpaYoM0iluLS9lgJNHyBF58KKA2FBEwkD7wog== + +colord@^2.9.3: version "2.9.3" resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.3.tgz#4f8ce919de456f1d5c1c368c307fe20f3e59fb43" integrity sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw== @@ -3203,6 +4223,11 @@ comma-separated-tokens@^2.0.0: resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz#4e89c9458acb61bc8fef19f4529973b2392839ee" integrity sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg== +command-exists@^1.2.8: + version "1.2.9" + resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" + integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== + commander@^10.0.0: version "10.0.1" resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" @@ -3228,7 +4253,7 @@ commander@^7.2.0: resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== -commander@^8.3.0: +commander@^8.1.0, commander@^8.3.0: version "8.3.0" resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== @@ -3309,7 +4334,7 @@ content-disposition@0.5.4: dependencies: safe-buffer "5.2.1" -content-type@~1.0.4: +content-type@~1.0.4, content-type@~1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== @@ -3324,10 +4349,10 @@ cookie-signature@1.0.6: resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== -cookie@0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" - integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== +cookie@0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" + integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== copy-text-to-clipboard@^3.2.0: version "3.2.0" @@ -3346,22 +4371,22 @@ copy-webpack-plugin@^11.0.0: schema-utils "^4.0.0" serialize-javascript "^6.0.0" -core-js-compat@^3.31.0, core-js-compat@^3.33.1: - version "3.35.0" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.35.0.tgz#c149a3d1ab51e743bc1da61e39cb51f461a41873" - integrity sha512-5blwFAddknKeNgsjBzilkdQ0+YK8L1PfqPYq40NOYMYFSS38qj+hpTcLLWwpIwA2A5bje/x5jmVn2tzUMg9IVw== +core-js-compat@^3.36.1, core-js-compat@^3.37.1: + version "3.37.1" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.37.1.tgz#c844310c7852f4bdf49b8d339730b97e17ff09ee" + integrity sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg== dependencies: - browserslist "^4.22.2" + browserslist "^4.23.0" core-js-pure@^3.30.2: - version "3.35.0" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.35.0.tgz#4660033304a050215ae82e476bd2513a419fbb34" - integrity sha512-f+eRYmkou59uh7BPcyJ8MC76DiGhspj1KMxVIcF24tzP8NA9HVa1uC7BTW2tgx7E1QVCzDzsgp7kArrzhlz8Ew== + version "3.37.1" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.37.1.tgz#2b4b34281f54db06c9a9a5bd60105046900553bd" + integrity sha512-J/r5JTHSmzTxbiYYrzXg9w1VpqrYt+gexenBE9pugeyhwPZTAEJddyiReJWsLO6uNQ8xJZFbod6XC7KKwatCiA== core-js@^3.31.1: - version "3.35.0" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.35.0.tgz#58e651688484f83c34196ca13f099574ee53d6b4" - integrity sha512-ntakECeqg81KqMueeGJ79Q5ZgQNR+6eaE8sxGCx62zMbAIj65q+uYvatToew3m6eAGdU4gNZwpZ34NMe4GYswg== + version "3.37.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.37.1.tgz#d21751ddb756518ac5a00e4d66499df981a62db9" + integrity sha512-Xn6qmxrQZyB0FFY8E3bgRXei3lWDJHhvI+u0q9TKIYM49G8pAr0FgnnrFRAmsbptZL1yxRADVXn+x5AGsbBfyw== core-util-is@~1.0.0: version "1.0.3" @@ -3379,18 +4404,7 @@ cosmiconfig@^6.0.0: path-type "^4.0.0" yaml "^1.7.2" -cosmiconfig@^7.0.1: - version "7.1.0" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz#1443b9afa596b670082ea46cbd8f6a62b84635f6" - integrity sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA== - dependencies: - "@types/parse-json" "^4.0.0" - import-fresh "^3.2.1" - parse-json "^5.0.0" - path-type "^4.0.0" - yaml "^1.10.0" - -cosmiconfig@^8.3.5: +cosmiconfig@^8.1.3, cosmiconfig@^8.3.5: version "8.3.6" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.3.6.tgz#060a2b871d66dba6c8538ea1118ba1ac16f5fae3" integrity sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA== @@ -3416,36 +4430,41 @@ crypto-random-string@^4.0.0: dependencies: type-fest "^1.0.1" -css-declaration-sorter@^6.3.1: - version "6.4.1" - resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz#28beac7c20bad7f1775be3a7129d7eae409a3a71" - integrity sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g== +css-color-keywords@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/css-color-keywords/-/css-color-keywords-1.0.0.tgz#fea2616dc676b2962686b3af8dbdbe180b244e05" + integrity sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg== + +css-declaration-sorter@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-7.2.0.tgz#6dec1c9523bc4a643e088aab8f09e67a54961024" + integrity sha512-h70rUM+3PNFuaBDTLe8wF/cdWu+dOZmb7pJt8Z2sedYbAcQVQV/tEchueg3GWxwqS0cxtbxmaHEdkNACqcvsow== css-loader@^6.8.1: - version "6.8.1" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.8.1.tgz#0f8f52699f60f5e679eab4ec0fcd68b8e8a50a88" - integrity sha512-xDAXtEVGlD0gJ07iclwWVkLoZOpEvAWaSyf6W18S2pOC//K8+qUDIx8IIT3D+HjnmkJPQeesOPv5aiUaJsCM2g== + version "6.11.0" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.11.0.tgz#33bae3bf6363d0a7c2cf9031c96c744ff54d85ba" + integrity sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g== dependencies: icss-utils "^5.1.0" - postcss "^8.4.21" - postcss-modules-extract-imports "^3.0.0" - postcss-modules-local-by-default "^4.0.3" - postcss-modules-scope "^3.0.0" + postcss "^8.4.33" + postcss-modules-extract-imports "^3.1.0" + postcss-modules-local-by-default "^4.0.5" + postcss-modules-scope "^3.2.0" postcss-modules-values "^4.0.0" postcss-value-parser "^4.2.0" - semver "^7.3.8" + semver "^7.5.4" -css-minimizer-webpack-plugin@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-4.2.2.tgz#79f6199eb5adf1ff7ba57f105e3752d15211eb35" - integrity sha512-s3Of/4jKfw1Hj9CxEO1E5oXhQAxlayuHO2y/ML+C6I9sQ7FdzfEV6QgMLN3vI+qFsjJGIAFLKtQK7t8BOXAIyA== - dependencies: - cssnano "^5.1.8" - jest-worker "^29.1.2" - postcss "^8.4.17" - schema-utils "^4.0.0" - serialize-javascript "^6.0.0" - source-map "^0.6.1" +css-minimizer-webpack-plugin@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-5.0.1.tgz#33effe662edb1a0bf08ad633c32fa75d0f7ec565" + integrity sha512-3caImjKFQkS+ws1TGcFn0V1HyDJFq1Euy589JlD6/3rV2kj+w7r5G9WDMgSHvpvXHNZ2calVypZWuEDQd9wfLg== + dependencies: + "@jridgewell/trace-mapping" "^0.3.18" + cssnano "^6.0.1" + jest-worker "^29.4.3" + postcss "^8.4.24" + schema-utils "^4.0.1" + serialize-javascript "^6.0.1" css-select@^4.1.3: version "4.3.0" @@ -3474,13 +4493,30 @@ css-selector-parser@^1.0.0: resolved "https://registry.yarnpkg.com/css-selector-parser/-/css-selector-parser-1.4.1.tgz#03f9cb8a81c3e5ab2c51684557d5aaf6d2569759" integrity sha512-HYPSb7y/Z7BNDCOrakL4raGO2zltZkbeXyAd6Tg9obzix6QhzxCotdBl6VT0Dv4vZfJGVz3WL/xaEI9Ly3ul0g== -css-tree@^1.1.2, css-tree@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d" - integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q== +css-to-react-native@3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-3.2.0.tgz#cdd8099f71024e149e4f6fe17a7d46ecd55f1e32" + integrity sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ== + dependencies: + camelize "^1.0.0" + css-color-keywords "^1.0.0" + postcss-value-parser "^4.0.2" + +css-tree@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-2.3.1.tgz#10264ce1e5442e8572fc82fbe490644ff54b5c20" + integrity sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw== + dependencies: + mdn-data "2.0.30" + source-map-js "^1.0.1" + +css-tree@~2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-2.2.1.tgz#36115d382d60afd271e377f9c5f67d02bd48c032" + integrity sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA== dependencies: - mdn-data "2.0.14" - source-map "^0.6.1" + mdn-data "2.0.28" + source-map-js "^1.0.1" css-what@^6.0.1, css-what@^6.1.0: version "6.1.0" @@ -3492,79 +4528,151 @@ cssesc@^3.0.0: resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== -cssnano-preset-advanced@^5.3.10: - version "5.3.10" - resolved "https://registry.yarnpkg.com/cssnano-preset-advanced/-/cssnano-preset-advanced-5.3.10.tgz#25558a1fbf3a871fb6429ce71e41be7f5aca6eef" - integrity sha512-fnYJyCS9jgMU+cmHO1rPSPf9axbQyD7iUhLO5Df6O4G+fKIOMps+ZbU0PdGFejFBBZ3Pftf18fn1eG7MAPUSWQ== - dependencies: - autoprefixer "^10.4.12" - cssnano-preset-default "^5.2.14" - postcss-discard-unused "^5.1.0" - postcss-merge-idents "^5.1.1" - postcss-reduce-idents "^5.2.0" - postcss-zindex "^5.1.0" - -cssnano-preset-default@^5.2.14: - version "5.2.14" - resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz#309def4f7b7e16d71ab2438052093330d9ab45d8" - integrity sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A== - dependencies: - css-declaration-sorter "^6.3.1" - cssnano-utils "^3.1.0" - postcss-calc "^8.2.3" - postcss-colormin "^5.3.1" - postcss-convert-values "^5.1.3" - postcss-discard-comments "^5.1.2" - postcss-discard-duplicates "^5.1.0" - postcss-discard-empty "^5.1.1" - postcss-discard-overridden "^5.1.0" - postcss-merge-longhand "^5.1.7" - postcss-merge-rules "^5.1.4" - postcss-minify-font-values "^5.1.0" - postcss-minify-gradients "^5.1.1" - postcss-minify-params "^5.1.4" - postcss-minify-selectors "^5.2.1" - postcss-normalize-charset "^5.1.0" - postcss-normalize-display-values "^5.1.0" - postcss-normalize-positions "^5.1.1" - postcss-normalize-repeat-style "^5.1.1" - postcss-normalize-string "^5.1.0" - postcss-normalize-timing-functions "^5.1.0" - postcss-normalize-unicode "^5.1.1" - postcss-normalize-url "^5.1.0" - postcss-normalize-whitespace "^5.1.1" - postcss-ordered-values "^5.1.3" - postcss-reduce-initial "^5.1.2" - postcss-reduce-transforms "^5.1.0" - postcss-svgo "^5.1.0" - postcss-unique-selectors "^5.1.1" - -cssnano-utils@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-3.1.0.tgz#95684d08c91511edfc70d2636338ca37ef3a6861" - integrity sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA== +cssnano-preset-advanced@^6.1.2: + version "6.1.2" + resolved "https://registry.yarnpkg.com/cssnano-preset-advanced/-/cssnano-preset-advanced-6.1.2.tgz#82b090872b8f98c471f681d541c735acf8b94d3f" + integrity sha512-Nhao7eD8ph2DoHolEzQs5CfRpiEP0xa1HBdnFZ82kvqdmbwVBUr2r1QuQ4t1pi+D1ZpqpcO4T+wy/7RxzJ/WPQ== + dependencies: + autoprefixer "^10.4.19" + browserslist "^4.23.0" + cssnano-preset-default "^6.1.2" + postcss-discard-unused "^6.0.5" + postcss-merge-idents "^6.0.3" + postcss-reduce-idents "^6.0.3" + postcss-zindex "^6.0.2" + +cssnano-preset-default@^6.1.2: + version "6.1.2" + resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-6.1.2.tgz#adf4b89b975aa775f2750c89dbaf199bbd9da35e" + integrity sha512-1C0C+eNaeN8OcHQa193aRgYexyJtU8XwbdieEjClw+J9d94E41LwT6ivKH0WT+fYwYWB0Zp3I3IZ7tI/BbUbrg== + dependencies: + browserslist "^4.23.0" + css-declaration-sorter "^7.2.0" + cssnano-utils "^4.0.2" + postcss-calc "^9.0.1" + postcss-colormin "^6.1.0" + postcss-convert-values "^6.1.0" + postcss-discard-comments "^6.0.2" + postcss-discard-duplicates "^6.0.3" + postcss-discard-empty "^6.0.3" + postcss-discard-overridden "^6.0.2" + postcss-merge-longhand "^6.0.5" + postcss-merge-rules "^6.1.1" + postcss-minify-font-values "^6.1.0" + postcss-minify-gradients "^6.0.3" + postcss-minify-params "^6.1.0" + postcss-minify-selectors "^6.0.4" + postcss-normalize-charset "^6.0.2" + postcss-normalize-display-values "^6.0.2" + postcss-normalize-positions "^6.0.2" + postcss-normalize-repeat-style "^6.0.2" + postcss-normalize-string "^6.0.2" + postcss-normalize-timing-functions "^6.0.2" + postcss-normalize-unicode "^6.1.0" + postcss-normalize-url "^6.0.2" + postcss-normalize-whitespace "^6.0.2" + postcss-ordered-values "^6.0.2" + postcss-reduce-initial "^6.1.0" + postcss-reduce-transforms "^6.0.2" + postcss-svgo "^6.0.3" + postcss-unique-selectors "^6.0.4" + +cssnano-utils@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-4.0.2.tgz#56f61c126cd0f11f2eef1596239d730d9fceff3c" + integrity sha512-ZR1jHg+wZ8o4c3zqf1SIUSTIvm/9mU343FMR6Obe/unskbvpGhZOo1J6d/r8D1pzkRQYuwbcH3hToOuoA2G7oQ== -cssnano@^5.1.15, cssnano@^5.1.8: - version "5.1.15" - resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-5.1.15.tgz#ded66b5480d5127fcb44dac12ea5a983755136bf" - integrity sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw== +cssnano@^6.0.1, cssnano@^6.1.2: + version "6.1.2" + resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-6.1.2.tgz#4bd19e505bd37ee7cf0dc902d3d869f6d79c66b8" + integrity sha512-rYk5UeX7VAM/u0lNqewCdasdtPK81CgX8wJFLEIXHbV2oldWRgJAsZrdhRXkV1NJzA2g850KiFm9mMU2HxNxMA== dependencies: - cssnano-preset-default "^5.2.14" - lilconfig "^2.0.3" - yaml "^1.10.2" + cssnano-preset-default "^6.1.2" + lilconfig "^3.1.1" -csso@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529" - integrity sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA== +csso@^5.0.5: + version "5.0.5" + resolved "https://registry.yarnpkg.com/csso/-/csso-5.0.5.tgz#f9b7fe6cc6ac0b7d90781bb16d5e9874303e2ca6" + integrity sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ== dependencies: - css-tree "^1.1.2" + css-tree "~2.2.0" -csstype@^3.0.2: +csstype@3.1.3, csstype@^3.0.2: version "3.1.3" resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== +"d3-array@2 - 3", "d3-array@2.10.0 - 3", d3-array@^3.1.6: + version "3.2.4" + resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-3.2.4.tgz#15fec33b237f97ac5d7c986dc77da273a8ed0bb5" + integrity sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg== + dependencies: + internmap "1 - 2" + +"d3-color@1 - 3": + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-3.1.0.tgz#395b2833dfac71507f12ac2f7af23bf819de24e2" + integrity sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA== + +d3-ease@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-3.0.1.tgz#9658ac38a2140d59d346160f1f6c30fda0bd12f4" + integrity sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w== + +"d3-format@1 - 3": + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-3.1.0.tgz#9260e23a28ea5cb109e93b21a06e24e2ebd55641" + integrity sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA== + +"d3-interpolate@1.2.0 - 3", d3-interpolate@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d" + integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g== + dependencies: + d3-color "1 - 3" + +d3-path@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-3.1.0.tgz#22df939032fb5a71ae8b1800d61ddb7851c42526" + integrity sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ== + +d3-scale@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-4.0.2.tgz#82b38e8e8ff7080764f8dcec77bd4be393689396" + integrity sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ== + dependencies: + d3-array "2.10.0 - 3" + d3-format "1 - 3" + d3-interpolate "1.2.0 - 3" + d3-time "2.1.1 - 3" + d3-time-format "2 - 4" + +d3-shape@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-3.2.0.tgz#a1a839cbd9ba45f28674c69d7f855bcf91dfc6a5" + integrity sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA== + dependencies: + d3-path "^3.1.0" + +"d3-time-format@2 - 4": + version "4.1.0" + resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-4.1.0.tgz#7ab5257a5041d11ecb4fe70a5c7d16a195bb408a" + integrity sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg== + dependencies: + d3-time "1 - 3" + +"d3-time@1 - 3", "d3-time@2.1.1 - 3", d3-time@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-3.1.0.tgz#9310db56e992e3c0175e1ef385e545e48a9bb5c7" + integrity sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q== + dependencies: + d3-array "2 - 3" + +d3-timer@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-3.0.1.tgz#6284d2a2708285b1abb7e201eda4380af35e63b0" + integrity sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA== + debounce@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.1.tgz#38881d8f4166a5c5848020c11827b834bcb3e0a5" @@ -3578,12 +4686,17 @@ debug@2.6.9, debug@^2.6.0: ms "2.0.0" debug@4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + version "4.3.5" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e" + integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== dependencies: ms "2.1.2" +decimal.js-light@^2.4.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/decimal.js-light/-/decimal.js-light-2.5.1.tgz#134fd32508f19e208f4fb2f8dac0d2626a867934" + integrity sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg== + decode-named-character-reference@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz#daabac9690874c394c81e4162a0304b35d824f0e" @@ -3603,7 +4716,7 @@ deep-extend@^0.6.0: resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== -deepmerge@^4.2.2: +deepmerge@^4.2.2, deepmerge@^4.3.1: version "4.3.1" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== @@ -3620,14 +4733,14 @@ defer-to-connect@^2.0.1: resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== -define-data-property@^1.0.1, define-data-property@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.1.tgz#c35f7cd0ab09883480d12ac5cb213715587800b3" - integrity sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ== +define-data-property@^1.0.1, define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== dependencies: - get-intrinsic "^1.2.1" + es-define-property "^1.0.0" + es-errors "^1.3.0" gopd "^1.0.1" - has-property-descriptors "^1.0.0" define-lazy-prop@^2.0.0: version "2.0.0" @@ -3677,6 +4790,11 @@ destroy@1.2.0: resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== +detect-node-es@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493" + integrity sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ== + detect-node@^2.0.4: version "2.1.0" resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" @@ -3691,9 +4809,9 @@ detect-port-alt@^1.1.6: debug "^2.6.0" detect-port@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.5.1.tgz#451ca9b6eaf20451acb0799b8ab40dff7718727b" - integrity sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ== + version "1.6.1" + resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.6.1.tgz#45e4073997c5f292b957cb678fb0bb8ed4250a67" + integrity sha512-CmnVc+Hek2egPx1PeTFVta2W78xy2K/9Rkf6cC4T59S50tVnzKj+tnx5mmx5lwvCkujZ4uRrpRSuV+IVs3f90Q== dependencies: address "^1.0.1" debug "4" @@ -3725,9 +4843,9 @@ dns-packet@^5.2.2: "@leichtgewicht/ip-codec" "^2.0.1" docusaurus-lunr-search@^3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/docusaurus-lunr-search/-/docusaurus-lunr-search-3.3.1.tgz#4ee77853b21c1f6a652c9545d8ba8dc3bd8b3ab9" - integrity sha512-EWUeHlTf+wVDLYLvgxeqavhww59elc9XfvlC9ZEHdeBT+kEbDdCdcC0CnHHeHVqePbMoHYfA8RhsXKYcLp6qgw== + version "3.4.0" + resolved "https://registry.yarnpkg.com/docusaurus-lunr-search/-/docusaurus-lunr-search-3.4.0.tgz#cefb0f8628f629e780451ae042d3cc35f078826f" + integrity sha512-GfllnNXCLgTSPH9TAKWmbn8VMfwpdOAZ1xl3T2GgX8Pm26qSDLfrrdVwjguaLfMJfzciFL97RKrAJlgrFM48yw== dependencies: autocomplete.js "^0.37.0" clsx "^1.2.1" @@ -3745,17 +4863,17 @@ docusaurus-lunr-search@^3.3.1: unist-util-is "^4.0.2" docusaurus-plugin-typedoc-api@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/docusaurus-plugin-typedoc-api/-/docusaurus-plugin-typedoc-api-4.0.1.tgz#c4051a112608046e7717d7238689c173b4a48d2b" - integrity sha512-mHHqvSz3qEPj1IPYa7Td75CWpWsVd6O0Fwex6XfZgj5kUDjeFCw50arc7j9n8xjXcqC1iIQ1ppz+AWwfSRZ0Kw== + version "4.2.0" + resolved "https://registry.yarnpkg.com/docusaurus-plugin-typedoc-api/-/docusaurus-plugin-typedoc-api-4.2.0.tgz#201a55f53d10a87d532fe4eeab3fbf5580aa6a5f" + integrity sha512-jD31Ro2joo7U8Yyru7oPKnqOrN/Vd6uQQxmbTrTzbTp0Br4Odw1W+YxW4DLqm+CCFryMP3Ru1p4qSLFbq4uj5A== dependencies: - "@docusaurus/plugin-content-docs" "^3.0.0" - "@docusaurus/types" "^3.0.0" - "@docusaurus/utils" "^3.0.0" + "@docusaurus/plugin-content-docs" "^3.1.0" + "@docusaurus/types" "^3.1.0" + "@docusaurus/utils" "^3.1.0" "@vscode/codicons" "^0.0.35" - marked "^9.1.5" - marked-smartypants "^1.1.3" - typedoc "^0.25.3" + marked "^9.1.6" + marked-smartypants "^1.1.5" + typedoc "^0.25.7" dom-converter@^0.2.0: version "0.2.0" @@ -3764,6 +4882,14 @@ dom-converter@^0.2.0: dependencies: utila "~0.4" +dom-helpers@^5.0.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902" + integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA== + dependencies: + "@babel/runtime" "^7.8.7" + csstype "^3.0.2" + dom-serializer@^1.0.1: version "1.4.1" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30" @@ -3849,10 +4975,10 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== -electron-to-chromium@^1.4.601: - version "1.4.620" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.620.tgz#a6481e0703f8df1e6821063fb43c9b818a7a2ef4" - integrity sha512-a2fcSHOHrqBJsPNXtf6ZCEZpXrFCcbK1FBxfX3txoqWzNgtEDG1f3M59M98iwxhRW4iMKESnSjbJ310/rkrp0g== +electron-to-chromium@^1.4.820: + version "1.5.1" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.1.tgz#24640bd4dcfaccb6d82bb4c3f4c7311503241581" + integrity sha512-FKbOCOQ5QRB3VlIbl1LZQefWIYwszlBloaXcY2rbfpu9ioJnNh3TK03YtIDKDo3WKBi8u+YV4+Fn2CkEozgf4w== emoji-regex@^8.0.0: version "8.0.0" @@ -3884,10 +5010,10 @@ encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== -enhanced-resolve@^5.15.0: - version "5.15.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz#1af946c7d93603eb88e9896cee4904dc012e9c35" - integrity sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg== +enhanced-resolve@^5.17.0: + version "5.17.1" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz#67bfbbcc2f81d511be77d686a90267ef7f898a15" + integrity sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg== dependencies: graceful-fs "^4.2.4" tapable "^2.2.0" @@ -3909,15 +5035,27 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" +es-define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" + integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== + dependencies: + get-intrinsic "^1.2.4" + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + es-module-lexer@^1.2.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.4.1.tgz#41ea21b43908fe6a287ffcbe4300f790555331f5" - integrity sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w== + version "1.5.4" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.5.4.tgz#a8efec3a3da991e60efa6b633a7cad6ab8d26b78" + integrity sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw== -escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== +escalade@^3.1.1, escalade@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" + integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== escape-goat@^4.0.0: version "4.0.0" @@ -4006,12 +5144,11 @@ estree-util-to-js@^2.0.0: source-map "^0.7.0" estree-util-value-to-estree@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/estree-util-value-to-estree/-/estree-util-value-to-estree-3.0.1.tgz#0b7b5d6b6a4aaad5c60999ffbc265a985df98ac5" - integrity sha512-b2tdzTurEIbwRh+mKrEcaWfu1wgb8J1hVsgREg7FFiecWwK/PhO8X0kyc+0bIcKNtD4sqxIdNoRy6/p/TvECEA== + version "3.1.2" + resolved "https://registry.yarnpkg.com/estree-util-value-to-estree/-/estree-util-value-to-estree-3.1.2.tgz#d2f0e5d350a6c181673eb7299743325b86a9bf5c" + integrity sha512-S0gW2+XZkmsx00tU2uJ4L9hUT7IFabbml9pHh2WQqFmAbxit++YGZne0sKJbNwkj9Wvg9E4uqWl4nCIFQMmfag== dependencies: "@types/estree" "^1.0.0" - is-plain-obj "^4.0.0" estree-util-visit@^2.0.0: version "2.0.0" @@ -4051,7 +5188,7 @@ eval@^0.1.8: "@types/node" "*" require-like ">= 0.1.1" -eventemitter3@^4.0.0: +eventemitter3@^4.0.0, eventemitter3@^4.0.1: version "4.0.7" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== @@ -4077,16 +5214,16 @@ execa@^5.0.0: strip-final-newline "^2.0.0" express@^4.17.3: - version "4.18.2" - resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" - integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== + version "4.19.2" + resolved "https://registry.yarnpkg.com/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465" + integrity sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q== dependencies: accepts "~1.3.8" array-flatten "1.1.1" - body-parser "1.20.1" + body-parser "1.20.2" content-disposition "0.5.4" content-type "~1.0.4" - cookie "0.5.0" + cookie "0.6.0" cookie-signature "1.0.6" debug "2.6.9" depd "2.0.0" @@ -4130,6 +5267,11 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== +fast-equals@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/fast-equals/-/fast-equals-5.0.1.tgz#a4eefe3c5d1c0d021aeed0bc10ba5e0c12ee405d" + integrity sha512-WF1Wi8PwwSY7/6Kx0vKXtw8RwuSGoM1bvDaJbu7MxDlR1vovZjIAKrnzyrThgAjm6JDTu0fVgWXDlMGspodfoQ== + fast-glob@^3.2.11, fast-glob@^3.2.9, fast-glob@^3.3.0: version "3.3.2" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" @@ -4146,6 +5288,11 @@ fast-json-stable-stringify@^2.0.0: resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== +fast-uri@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.1.tgz#cddd2eecfc83a71c1be2cc2ef2061331be8a7134" + integrity sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw== + fast-url-parser@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/fast-url-parser/-/fast-url-parser-1.1.3.tgz#f4af3ea9f34d8a271cf58ad2b3759f431f0b318d" @@ -4154,12 +5301,19 @@ fast-url-parser@1.1.3: punycode "^1.3.2" fastq@^1.6.0: - version "1.16.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.16.0.tgz#83b9a9375692db77a822df081edb6a9cf6839320" - integrity sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA== + version "1.17.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" + integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== dependencies: reusify "^1.0.4" +fault@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/fault/-/fault-1.0.4.tgz#eafcfc0a6d214fc94601e170df29954a4f842f13" + integrity sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA== + dependencies: + format "^0.2.0" + fault@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/fault/-/fault-2.0.1.tgz#d47ca9f37ca26e4bd38374a7c500b5a384755b6c" @@ -4181,6 +5335,16 @@ feed@^4.2.2: dependencies: xml-js "^1.6.11" +fflate@^0.4.8: + version "0.4.8" + resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.4.8.tgz#f90b82aefbd8ac174213abb338bd7ef848f0f5ae" + integrity sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA== + +fflate@^0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.8.2.tgz#fc8631f5347812ad6028bbe4a2308b2792aa1dea" + integrity sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A== + file-loader@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d" @@ -4189,15 +5353,20 @@ file-loader@^6.2.0: loader-utils "^2.0.0" schema-utils "^3.0.0" +file-saver@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/file-saver/-/file-saver-2.0.5.tgz#d61cfe2ce059f414d899e9dd6d4107ee25670c38" + integrity sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA== + filesize@^8.0.6: version "8.0.7" resolved "https://registry.yarnpkg.com/filesize/-/filesize-8.0.7.tgz#695e70d80f4e47012c132d57a059e80c6b580bd8" integrity sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ== -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== dependencies: to-regex-range "^5.0.1" @@ -4250,15 +5419,15 @@ flat@^5.0.2: resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== -follow-redirects@^1.0.0: +follow-redirects@^1.0.0, follow-redirects@^1.12.1: version "1.15.6" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== foreground-child@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d" - integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg== + version "3.2.1" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.2.1.tgz#767004ccf3a5b30df39bed90718bab43fe0a59f7" + integrity sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA== dependencies: cross-spawn "^7.0.0" signal-exit "^4.0.1" @@ -4297,17 +5466,38 @@ forwarded@0.2.0: resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== -fraction.js@^4.3.6: +fraction.js@^4.3.7: version "4.3.7" resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.3.7.tgz#06ca0085157e42fda7f9e726e79fefc4068840f7" integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew== +framer-motion@^6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-6.5.1.tgz#802448a16a6eb764124bf36d8cbdfa6dd6b931a7" + integrity sha512-o1BGqqposwi7cgDrtg0dNONhkmPsUFDaLcKXigzuTFC5x58mE8iyTazxSudFzmT6MEyJKfjjU8ItoMe3W+3fiw== + dependencies: + "@motionone/dom" "10.12.0" + framesync "6.0.1" + hey-listen "^1.0.8" + popmotion "11.0.3" + style-value-types "5.0.0" + tslib "^2.1.0" + optionalDependencies: + "@emotion/is-prop-valid" "^0.8.2" + +framesync@6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/framesync/-/framesync-6.0.1.tgz#5e32fc01f1c42b39c654c35b16440e07a25d6f20" + integrity sha512-fUY88kXvGiIItgNC7wcTOl0SNRCVXMKSWW2Yzfmn7EKNc+MpCzcz9DhdHcdjbrtN3c6R4H5dTY2jiCpPdysEjA== + dependencies: + tslib "^2.1.0" + fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== -fs-extra@^11.1.1: +fs-extra@^11.1.1, fs-extra@^11.2.0: version "11.2.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.2.0.tgz#e70e17dfad64232287d01929399e0ea7c86b0e5b" integrity sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw== @@ -4327,9 +5517,9 @@ fs-extra@^9.0.0: universalify "^2.0.0" fs-monkey@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.5.tgz#fe450175f0db0d7ea758102e1d84096acb925788" - integrity sha512-8uMbBjrhzW76TYgEV27Y5E//W2f/lTFmx78P2w19FZSxarhI/798APGQyuGCwmkNxgwGRhrLfvWyLBvNtuOmew== + version "1.0.6" + resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.6.tgz#8ead082953e88d992cf3ff844faa907b26756da2" + integrity sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg== fs.realpath@^1.0.0: version "1.0.0" @@ -4366,16 +5556,22 @@ gensync@^1.0.0-beta.2: resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== -get-intrinsic@^1.0.2, get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.2.tgz#281b7622971123e1ef4b3c90fd7539306da93f3b" - integrity sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA== +get-intrinsic@^1.1.3, get-intrinsic@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" + integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== dependencies: + es-errors "^1.3.0" function-bind "^1.1.2" has-proto "^1.0.1" has-symbols "^1.0.3" hasown "^2.0.0" +get-nonce@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-nonce/-/get-nonce-1.0.1.tgz#fdf3f0278073820d2ce9426c18f07481b1e0cdf3" + integrity sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q== + get-own-enumerable-property-symbols@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" @@ -4411,15 +5607,16 @@ glob-to-regexp@^0.4.1: integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== glob@^10.3.10: - version "10.3.10" - resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.10.tgz#0351ebb809fd187fe421ab96af83d3a70715df4b" - integrity sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g== + version "10.4.5" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" + integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== dependencies: foreground-child "^3.1.0" - jackspeak "^2.3.5" - minimatch "^9.0.1" - minipass "^5.0.0 || ^6.0.2 || ^7.0.0" - path-scurry "^1.10.1" + jackspeak "^3.1.2" + minimatch "^9.0.4" + minipass "^7.1.2" + package-json-from-dist "^1.0.0" + path-scurry "^1.11.1" glob@^7.0.0, glob@^7.1.3, glob@^7.1.6: version "7.2.3" @@ -4513,7 +5710,7 @@ graceful-fs@4.2.10: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== -graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -4550,17 +5747,17 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-property-descriptors@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz#52ba30b6c5ec87fd89fa574bc1c39125c6f65340" - integrity sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg== +has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== dependencies: - get-intrinsic "^1.2.2" + es-define-property "^1.0.0" has-proto@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" - integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" + integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== has-symbols@^1.0.3: version "1.0.3" @@ -4577,10 +5774,10 @@ has-yarn@^3.0.0: resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-3.0.0.tgz#c3c21e559730d1d3b57e28af1f30d06fac38147d" integrity sha512-IrsVwUHhEULx3R8f/aA8AHuEzAorplsab/v8HBzEiIukwq5i/EC+xmOW+HfP1OaDP+2JkgT1yILHN2O3UFIbcA== -hasown@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" - integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA== +hasown@^2.0.0, hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== dependencies: function-bind "^1.1.2" @@ -4633,9 +5830,9 @@ hast-util-parse-selector@^4.0.0: "@types/hast" "^3.0.0" hast-util-raw@^9.0.0: - version "9.0.1" - resolved "https://registry.yarnpkg.com/hast-util-raw/-/hast-util-raw-9.0.1.tgz#2ba8510e4ed2a1e541cde2a4ebb5c38ab4c82c2d" - integrity sha512-5m1gmba658Q+lO5uqL5YNGQWeh1MYWZbZmWrM5lncdcuiXuo5E2HT/CIOp0rLF8ksfSwiCVJ3twlgVRyTGThGA== + version "9.0.4" + resolved "https://registry.yarnpkg.com/hast-util-raw/-/hast-util-raw-9.0.4.tgz#2da03e37c46eb1a6f1391f02f9b84ae65818f7ed" + integrity sha512-LHE65TD2YiNsHD3YuXcKPHXPLuYh/gjp12mOfU8jxSrm1f/yJpsb0F/KKljS6U9LJoP0Ux+tCe8iJ2AsPzTdgA== dependencies: "@types/hast" "^3.0.0" "@types/unist" "^3.0.0" @@ -4780,6 +5977,16 @@ he@^1.2.0: resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== +hey-listen@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/hey-listen/-/hey-listen-1.0.8.tgz#8e59561ff724908de1aa924ed6ecc84a56a9aa68" + integrity sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q== + +highlight.js@^10.4.1, highlight.js@~10.7.0: + version "10.7.3" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531" + integrity sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A== + history@^4.9.0: version "4.10.1" resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3" @@ -4818,9 +6025,9 @@ hpack.js@^2.1.6: wbuf "^1.1.0" html-entities@^2.3.2: - version "2.4.0" - resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.4.0.tgz#edd0cee70402584c8c76cc2c0556db09d1f45061" - integrity sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ== + version "2.5.2" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.5.2.tgz#201a3cf95d3a15be7099521620d19dfb4f65359f" + integrity sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA== html-escaper@^2.0.2: version "2.0.2" @@ -4858,6 +6065,11 @@ html-tags@^3.3.1: resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.3.1.tgz#a04026a18c882e4bba8a01a3d39cfe465d40b5ce" integrity sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ== +html-url-attributes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/html-url-attributes/-/html-url-attributes-3.0.0.tgz#fc4abf0c3fb437e2329c678b80abb3c62cff6f08" + integrity sha512-/sXbVCWayk6GDVg3ctOX6nxaVj7So40FcFAnWlWGNAB1LpYKcV5Cd10APjPjW80O7zYW2MsjBV4zZ7IZO5fVow== + html-void-elements@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-3.0.0.tgz#fc9dbd84af9e747249034d4d62602def6517f1d7" @@ -4975,10 +6187,15 @@ icss-utils@^5.0.0, icss-utils@^5.1.0: resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== +idb@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/idb/-/idb-8.0.0.tgz#33d7ed894ed36e23bcb542fb701ad579bfaad41f" + integrity sha512-l//qvlAKGmQO31Qn7xdzagVPPaHTxXx199MhrAFuVBTPqydcPYBWjkrbv4Y0ktB+GmWOiwHl237UUOrLmQxLvw== + ignore@^5.2.0, ignore@^5.2.4: - version "5.3.0" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.0.tgz#67418ae40d34d6999c95ff56016759c718c82f78" - integrity sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg== + version "5.3.1" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" + integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== image-size@^1.0.2: version "1.1.1" @@ -4992,12 +6209,17 @@ immediate@^3.2.3: resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.3.0.tgz#1aef225517836bcdf7f2a2de2600c79ff0269266" integrity sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q== +immediate@~3.0.5: + version "3.0.6" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" + integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ== + immer@^9.0.7: version "9.0.21" resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.21.tgz#1e025ea31a40f24fb064f1fef23e931496330176" integrity sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA== -import-fresh@^3.1.0, import-fresh@^3.2.1, import-fresh@^3.3.0: +import-fresh@^3.1.0, import-fresh@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== @@ -5058,10 +6280,15 @@ inline-style-parser@0.1.1: resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1" integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q== -inline-style-parser@0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.2.2.tgz#d498b4e6de0373458fc610ff793f6b14ebf45633" - integrity sha512-EcKzdTHVe8wFVOGEYXiW9WmJXPjqi1T+234YpJr98RiFYKHV3cdy1+3mkTE+KHTHxFFLH51SfaGOoUdW+v7ViQ== +inline-style-parser@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.2.3.tgz#e35c5fb45f3a83ed7849fe487336eb7efa25971c" + integrity sha512-qlD8YNDqyTKTyuITrDOffsl6Tdhv+UC4hcdAVuQsK4IMQ99nSgd1MIA/Q+jQYoh9r3hVUXhYh7urSRmXPkW04g== + +"internmap@1 - 2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/internmap/-/internmap-2.0.3.tgz#6685f23755e43c524e251d29cbc97248e3061009" + integrity sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg== interpret@^1.0.0: version "1.4.0" @@ -5081,15 +6308,28 @@ ipaddr.js@1.9.1: integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== ipaddr.js@^2.0.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.1.0.tgz#2119bc447ff8c257753b196fc5f1ce08a4cdf39f" - integrity sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ== + version "2.2.0" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.2.0.tgz#d33fa7bac284f4de7af949638c9d68157c6b92e8" + integrity sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA== + +is-alphabetical@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.4.tgz#9e7d6b94916be22153745d184c298cbf986a686d" + integrity sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg== is-alphabetical@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-2.0.1.tgz#01072053ea7c1036df3c7d19a6daaec7f19e789b" integrity sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ== +is-alphanumerical@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz#7eb9a2431f855f6b1ef1a78e326df515696c4dbf" + integrity sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A== + dependencies: + is-alphabetical "^1.0.0" + is-decimal "^1.0.0" + is-alphanumerical@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz#7c03fbe96e3e931113e57f964b0a368cc2dfd875" @@ -5123,11 +6363,16 @@ is-ci@^3.0.1: ci-info "^3.2.0" is-core-module@^2.13.0: - version "2.13.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" - integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== + version "2.15.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.15.0.tgz#71c72ec5442ace7e76b306e9d48db361f22699ea" + integrity sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA== dependencies: - hasown "^2.0.0" + hasown "^2.0.2" + +is-decimal@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5" + integrity sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw== is-decimal@^2.0.0: version "2.0.1" @@ -5161,6 +6406,11 @@ is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" +is-hexadecimal@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7" + integrity sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw== + is-hexadecimal@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz#86b5bf668fca307498d319dfc03289d781a90027" @@ -5226,11 +6476,6 @@ is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" -is-plain-object@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" - integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== - is-reference@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-3.0.2.tgz#154747a01f45cd962404ee89d43837af2cba247c" @@ -5290,10 +6535,15 @@ isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== -jackspeak@^2.3.5: - version "2.3.6" - resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" - integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ== +isows@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/isows/-/isows-1.0.3.tgz#93c1cf0575daf56e7120bab5c8c448b0809d0d74" + integrity sha512-2cKei4vlmg2cxEjm3wVSqn8pcoRF/LX/wpifuuNquFO4SQmPwarClT+SUCA2lt+l581tTeZIPIZuIDo2jWN1fg== + +jackspeak@^3.1.2: + version "3.4.3" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a" + integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw== dependencies: "@isaacs/cliui" "^8.0.2" optionalDependencies: @@ -5320,7 +6570,7 @@ jest-worker@^27.4.5: merge-stream "^2.0.0" supports-color "^8.0.0" -jest-worker@^29.1.2: +jest-worker@^29.4.3: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a" integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== @@ -5331,21 +6581,26 @@ jest-worker@^29.1.2: supports-color "^8.0.0" jiti@^1.20.0: - version "1.21.0" - resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.0.tgz#7c97f8fe045724e136a397f7340475244156105d" - integrity sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q== + version "1.21.6" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.6.tgz#6c7f7398dd4b3142767f9a168af2f317a428d268" + integrity sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w== joi@^17.9.2: - version "17.11.0" - resolved "https://registry.yarnpkg.com/joi/-/joi-17.11.0.tgz#aa9da753578ec7720e6f0ca2c7046996ed04fc1a" - integrity sha512-NgB+lZLNoqISVy1rZocE9PZI36bL/77ie924Ri43yEvi9GUUMPeyVIr8KdFTMUlby1p0PBYMk9spIxEUQYqrJQ== + version "17.13.3" + resolved "https://registry.yarnpkg.com/joi/-/joi-17.13.3.tgz#0f5cc1169c999b30d344366d384b12d92558bcec" + integrity sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA== dependencies: - "@hapi/hoek" "^9.0.0" - "@hapi/topo" "^5.0.0" - "@sideway/address" "^4.1.3" + "@hapi/hoek" "^9.3.0" + "@hapi/topo" "^5.1.0" + "@sideway/address" "^4.1.5" "@sideway/formula" "^3.0.1" "@sideway/pinpoint" "^2.0.0" +js-sha3@0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" + integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== + "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -5402,9 +6657,9 @@ json5@^2.1.2, json5@^2.2.3: integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== jsonc-parser@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76" - integrity sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w== + version "3.3.1" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.3.1.tgz#f2a524b4f7fd11e3d791e559977ad60b98b798b4" + integrity sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ== jsonfile@^6.0.1: version "6.1.0" @@ -5415,6 +6670,16 @@ jsonfile@^6.0.1: optionalDependencies: graceful-fs "^4.1.6" +jszip@^3.10.1: + version "3.10.1" + resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.10.1.tgz#34aee70eb18ea1faec2f589208a157d1feb091c2" + integrity sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g== + dependencies: + lie "~3.3.0" + pako "~1.0.2" + readable-stream "~2.3.6" + setimmediate "^1.0.5" + keyv@^4.5.3: version "4.5.4" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" @@ -5440,9 +6705,9 @@ latest-version@^7.0.0: package-json "^8.1.0" launch-editor@^2.6.0: - version "2.6.1" - resolved "https://registry.yarnpkg.com/launch-editor/-/launch-editor-2.6.1.tgz#f259c9ef95cbc9425620bbbd14b468fcdb4ffe3c" - integrity sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw== + version "2.8.0" + resolved "https://registry.yarnpkg.com/launch-editor/-/launch-editor-2.8.0.tgz#7255d90bdba414448e2138faa770a74f28451305" + integrity sha512-vJranOAJrI/llyWGRQqiDM+adrw+k83fvmmx3+nV47g3+36xM15jE+zyZ6Ffel02+xSvuM0b2GDRosXZkbb6wA== dependencies: picocolors "^1.0.0" shell-quote "^1.8.1" @@ -5452,10 +6717,17 @@ leven@^3.1.0: resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== -lilconfig@^2.0.3: - version "2.1.0" - resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52" - integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ== +lie@~3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/lie/-/lie-3.3.0.tgz#dcf82dee545f46074daf200c7c1c5a08e0f40f6a" + integrity sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ== + dependencies: + immediate "~3.0.5" + +lilconfig@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.2.tgz#e4a7c3cb549e3a606c8dcc32e5ae1005e62c05cb" + integrity sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow== lines-and-columns@^1.1.6: version "1.2.4" @@ -5477,9 +6749,9 @@ loader-utils@^2.0.0: json5 "^2.1.2" loader-utils@^3.2.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-3.2.1.tgz#4fb104b599daafd82ef3e1a41fb9265f87e1f576" - integrity sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw== + version "3.3.1" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-3.3.1.tgz#735b9a19fd63648ca7adbd31c2327dfe281304e5" + integrity sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg== locate-path@^3.0.0: version "3.0.0" @@ -5547,6 +6819,19 @@ lowercase-keys@^3.0.0: resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-3.0.0.tgz#c5e7d442e37ead247ae9db117a9d0a467c89d4f2" integrity sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ== +lowlight@^1.17.0: + version "1.20.0" + resolved "https://registry.yarnpkg.com/lowlight/-/lowlight-1.20.0.tgz#ddb197d33462ad0d93bf19d17b6c301aa3941888" + integrity sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw== + dependencies: + fault "^1.0.0" + highlight.js "~10.7.0" + +lru-cache@^10.2.0: + version "10.4.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" + integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== + lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -5554,18 +6839,6 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -"lru-cache@^9.1.1 || ^10.0.0": - version "10.1.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.1.0.tgz#2098d41c2dc56500e6c88584aa656c84de7d0484" - integrity sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag== - lunr-languages@^1.4.0: version "1.14.0" resolved "https://registry.yarnpkg.com/lunr-languages/-/lunr-languages-1.14.0.tgz#6e97635f434631729dd0e5654daedd291cd6f2d0" @@ -5598,10 +6871,10 @@ markdown-table@^3.0.0: resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-3.0.3.tgz#e6331d30e493127e031dd385488b5bd326e4a6bd" integrity sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw== -marked-smartypants@^1.1.3: - version "1.1.5" - resolved "https://registry.yarnpkg.com/marked-smartypants/-/marked-smartypants-1.1.5.tgz#1ea079764ce47c963843c2f77b5a6cb85664f409" - integrity sha512-gp+IpDsthwcXJ/sWT8si7dGWL6Diag3Iy4+OOoMZnhjFAox9z77cWfqQUmwY9oP9XACWZeiBXvWW1TOjTbvwAw== +marked-smartypants@^1.1.5: + version "1.1.7" + resolved "https://registry.yarnpkg.com/marked-smartypants/-/marked-smartypants-1.1.7.tgz#2a0abcdb68bfcfe402d4c0bc5f5466c59bd7e5b6" + integrity sha512-GXtR6UfyZ3NXkmdwUWnM+MFrmxvF1HA2KzTGB+vGoWc7K829CgSs/wlDOz2MK/peujK866X2650HJhrnXQBpiA== dependencies: smartypants "^0.2.2" @@ -5610,7 +6883,7 @@ marked@^4.3.0: resolved "https://registry.yarnpkg.com/marked/-/marked-4.3.0.tgz#796362821b019f734054582038b116481b456cf3" integrity sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A== -marked@^9.1.5: +marked@^9.1.6: version "9.1.6" resolved "https://registry.yarnpkg.com/marked/-/marked-9.1.6.tgz#5d2a3f8180abfbc5d62e3258a38a1c19c0381695" integrity sha512-jcByLnIFkd5gSXZmjNvS1TlmRhCXZjIzHYlaGkPlLIekG55JDR2Z4va9tZwCiP+/RDERiNhMOFu01xd6O5ct1Q== @@ -5640,9 +6913,9 @@ mdast-util-find-and-replace@^3.0.0, mdast-util-find-and-replace@^3.0.1: unist-util-visit-parents "^6.0.0" mdast-util-from-markdown@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.0.tgz#52f14815ec291ed061f2922fd14d6689c810cb88" - integrity sha512-n7MTOr/z+8NAX/wmhhDji8O3bRvPTV/U0oTCaZJkjhPSKTPhS3xufVhKGF8s1pJ7Ox4QgoIU7KHseh09S+9rTA== + version "2.0.1" + resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.1.tgz#32a6e8f512b416e1f51eb817fc64bd867ebcd9cc" + integrity sha512-aJEUyzZ6TzlsX2s5B4Of7lN7EQtAxvtradMMglCQDyaTFgse6CmtmdJ15ElnVRlCg1vpNyVtbem0PWzlNieZsA== dependencies: "@types/mdast" "^4.0.0" "@types/unist" "^3.0.0" @@ -5747,9 +7020,9 @@ mdast-util-mdx-expression@^2.0.0: mdast-util-to-markdown "^2.0.0" mdast-util-mdx-jsx@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.0.0.tgz#f73631fa5bb7a36712ff1e9cedec0cafed03401c" - integrity sha512-XZuPPzQNBPAlaqsTTgRrcJnyFbSOBovSadFgbFu8SnuNgm+6Bdx1K+IWoitsmj6Lq6MNtI+ytOqwN70n//NaBA== + version "3.1.2" + resolved "https://registry.yarnpkg.com/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.1.2.tgz#daae777c72f9c4a106592e3025aa50fb26068e1b" + integrity sha512-eKMQDeywY2wlHc97k5eD8VC+9ASMjN8ItEZQNGwJ6E0XWKiW/Z0V5/H8pvoXUf+y+Mj0VIgeRRbujBmFn4FTyA== dependencies: "@types/estree-jsx" "^1.0.0" "@types/hast" "^3.0.0" @@ -5789,17 +7062,17 @@ mdast-util-mdxjs-esm@^2.0.0: mdast-util-to-markdown "^2.0.0" mdast-util-phrasing@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/mdast-util-phrasing/-/mdast-util-phrasing-4.0.0.tgz#468cbbb277375523de807248b8ad969feb02a5c7" - integrity sha512-xadSsJayQIucJ9n053dfQwVu1kuXg7jCTdYsMK8rqzKZh52nLfSH/k0sAxE0u+pj/zKZX+o5wB+ML5mRayOxFA== + version "4.1.0" + resolved "https://registry.yarnpkg.com/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz#7cc0a8dec30eaf04b7b1a9661a92adb3382aa6e3" + integrity sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w== dependencies: "@types/mdast" "^4.0.0" unist-util-is "^6.0.0" mdast-util-to-hast@^13.0.0: - version "13.0.2" - resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-13.0.2.tgz#74c0a9f014bb2340cae6118f6fccd75467792be7" - integrity sha512-U5I+500EOOw9e3ZrclN3Is3fRpw8c19SMyNZlZ2IS+7vLsNzb2Om11VpIVOR+/0137GhZsFEF6YiKD5+0Hr2Og== + version "13.2.0" + resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz#5ca58e5b921cc0a3ded1bc02eed79a4fe4fe41f4" + integrity sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA== dependencies: "@types/hast" "^3.0.0" "@types/mdast" "^4.0.0" @@ -5809,6 +7082,7 @@ mdast-util-to-hast@^13.0.0: trim-lines "^3.0.0" unist-util-position "^5.0.0" unist-util-visit "^5.0.0" + vfile "^6.0.0" mdast-util-to-markdown@^2.0.0: version "2.1.0" @@ -5831,10 +7105,15 @@ mdast-util-to-string@^4.0.0: dependencies: "@types/mdast" "^4.0.0" -mdn-data@2.0.14: - version "2.0.14" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" - integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== +mdn-data@2.0.28: + version "2.0.28" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.28.tgz#5ec48e7bef120654539069e1ae4ddc81ca490eba" + integrity sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g== + +mdn-data@2.0.30: + version "2.0.30" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.30.tgz#ce4df6f80af6cfbe218ecd5c552ba13c4dfa08cc" + integrity sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA== media-typer@0.3.0: version "0.3.0" @@ -5848,6 +7127,11 @@ memfs@^3.1.2, memfs@^3.4.3: dependencies: fs-monkey "^1.0.4" +memorystream@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" + integrity sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw== + merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" @@ -5869,9 +7153,9 @@ methods@~1.1.2: integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== micromark-core-commonmark@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-core-commonmark/-/micromark-core-commonmark-2.0.0.tgz#50740201f0ee78c12a675bf3e68ffebc0bf931a3" - integrity sha512-jThOz/pVmAYUtkroV3D5c1osFXAMv9e0ypGDOIZuCeAe91/sD6BoE2Sjzt30yuXtwOYUmySOhMas/PVyh02itA== + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-core-commonmark/-/micromark-core-commonmark-2.0.1.tgz#9a45510557d068605c6e9a80f282b2bb8581e43d" + integrity sha512-CUQyKr1e///ZODyD1U3xit6zXwy1a8q2a1S1HKtIlmgvurrEpaw/Y9y6KSIbF8P59cn/NjzHyO+Q2fAyYLQrAA== dependencies: decode-named-character-reference "^1.0.0" devlop "^1.0.0" @@ -5891,9 +7175,9 @@ micromark-core-commonmark@^2.0.0: micromark-util-types "^2.0.0" micromark-extension-directive@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/micromark-extension-directive/-/micromark-extension-directive-3.0.0.tgz#527869de497a6de9024138479091bc885dae076b" - integrity sha512-61OI07qpQrERc+0wEysLHMvoiO3s2R56x5u7glHq2Yqq6EHbH4dW25G9GfDdGCDYqA21KE6DWgNSzxSwHc2hSg== + version "3.0.1" + resolved "https://registry.yarnpkg.com/micromark-extension-directive/-/micromark-extension-directive-3.0.1.tgz#67b3985bb991a69dbcae52664c57ee54b22f635a" + integrity sha512-VGV2uxUzhEZmaP7NSFo2vtq7M2nUD+WfmYQD+d8i/1nHbzE+rMy9uzTvUybBbNiVbrhOZibg3gbyoARGqgDWyg== dependencies: devlop "^1.0.0" micromark-factory-space "^2.0.0" @@ -5914,9 +7198,9 @@ micromark-extension-frontmatter@^2.0.0: micromark-util-types "^2.0.0" micromark-extension-gfm-autolink-literal@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.0.0.tgz#f1e50b42e67d441528f39a67133eddde2bbabfd9" - integrity sha512-rTHfnpt/Q7dEAK1Y5ii0W8bhfJlVJFnJMHIPisfPK3gpVNuOP0VnRl96+YJ3RYWV/P4gFeQoGKNlT3RhuvpqAg== + version "2.1.0" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz#6286aee9686c4462c1e3552a9d505feddceeb935" + integrity sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw== dependencies: micromark-util-character "^2.0.0" micromark-util-sanitize-uri "^2.0.0" @@ -5924,9 +7208,9 @@ micromark-extension-gfm-autolink-literal@^2.0.0: micromark-util-types "^2.0.0" micromark-extension-gfm-footnote@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.0.0.tgz#91afad310065a94b636ab1e9dab2c60d1aab953c" - integrity sha512-6Rzu0CYRKDv3BfLAUnZsSlzx3ak6HAoI85KTiijuKIz5UxZxbUI+pD6oHgw+6UtQuiRwnGRhzMmPRv4smcz0fg== + version "2.1.0" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz#4dab56d4e398b9853f6fe4efac4fc9361f3e0750" + integrity sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw== dependencies: devlop "^1.0.0" micromark-core-commonmark "^2.0.0" @@ -5938,9 +7222,9 @@ micromark-extension-gfm-footnote@^2.0.0: micromark-util-types "^2.0.0" micromark-extension-gfm-strikethrough@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.0.0.tgz#6917db8e320da70e39ffbf97abdbff83e6783e61" - integrity sha512-c3BR1ClMp5fxxmwP6AoOY2fXO9U8uFMKs4ADD66ahLTNcwzSCyRVU4k7LPV5Nxo/VJiR4TdzxRQY2v3qIUceCw== + version "2.1.0" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz#86106df8b3a692b5f6a92280d3879be6be46d923" + integrity sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw== dependencies: devlop "^1.0.0" micromark-util-chunked "^2.0.0" @@ -5950,9 +7234,9 @@ micromark-extension-gfm-strikethrough@^2.0.0: micromark-util-types "^2.0.0" micromark-extension-gfm-table@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.0.0.tgz#2cf3fe352d9e089b7ef5fff003bdfe0da29649b7" - integrity sha512-PoHlhypg1ItIucOaHmKE8fbin3vTLpDOUg8KAr8gRCF1MOZI9Nquq2i/44wFvviM4WuxJzc3demT8Y3dkfvYrw== + version "2.1.0" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.0.tgz#5cadedfbb29fca7abf752447967003dc3b6583c9" + integrity sha512-Ub2ncQv+fwD70/l4ou27b4YzfNaCJOvyX4HxXU15m7mpYY+rjuWzsLIPZHJL253Z643RpbcP1oeIJlQ/SKW67g== dependencies: devlop "^1.0.0" micromark-factory-space "^2.0.0" @@ -5968,9 +7252,9 @@ micromark-extension-gfm-tagfilter@^2.0.0: micromark-util-types "^2.0.0" micromark-extension-gfm-task-list-item@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.0.1.tgz#ee8b208f1ced1eb9fb11c19a23666e59d86d4838" - integrity sha512-cY5PzGcnULaN5O7T+cOzfMoHjBW7j+T9D2sucA5d/KbsBTPcYdebm9zUd9zzdgJGCwahV+/W78Z3nbulBYVbTw== + version "2.1.0" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz#bcc34d805639829990ec175c3eea12bb5b781f2c" + integrity sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw== dependencies: devlop "^1.0.0" micromark-factory-space "^2.0.0" @@ -6136,9 +7420,9 @@ micromark-util-character@^1.0.0, micromark-util-character@^1.1.0: micromark-util-types "^1.0.0" micromark-util-character@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/micromark-util-character/-/micromark-util-character-2.0.1.tgz#52b824c2e2633b6fb33399d2ec78ee2a90d6b298" - integrity sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw== + version "2.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-character/-/micromark-util-character-2.1.0.tgz#31320ace16b4644316f6bf057531689c71e2aee1" + integrity sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ== dependencies: micromark-util-symbol "^2.0.0" micromark-util-types "^2.0.0" @@ -6232,9 +7516,9 @@ micromark-util-sanitize-uri@^2.0.0: micromark-util-symbol "^2.0.0" micromark-util-subtokenize@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.0.tgz#9f412442d77e0c5789ffdf42377fa8a2bcbdf581" - integrity sha512-vc93L1t+gpR3p8jxeVdaYlbV2jTYteDje19rNSS/H5dlhxUYll5Fy6vJ2cDwP8RnsXi818yGty1ayP55y3W6fg== + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.1.tgz#76129c49ac65da6e479c09d0ec4b5f29ec6eace5" + integrity sha512-jZNtiFl/1aY73yS3UGQkutD0UbhTt68qnRpw2Pifmz5wV9h8gOVsN70v+Lq/f1rKaU/W8pxRe8y8Q9FX1AOe1Q== dependencies: devlop "^1.0.0" micromark-util-chunked "^2.0.0" @@ -6285,18 +7569,23 @@ micromark@^4.0.0: micromark-util-types "^2.0.0" micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5: - version "4.0.5" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + version "4.0.7" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.7.tgz#33e8190d9fe474a9895525f5618eee136d46c2e5" + integrity sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q== dependencies: - braces "^3.0.2" + braces "^3.0.3" picomatch "^2.3.1" -mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": +mime-db@1.52.0: version "1.52.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== +"mime-db@>= 1.43.0 < 2": + version "1.53.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.53.0.tgz#3cb63cd820fc29896d9d4e8c32ab4fcd74ccb447" + integrity sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg== + mime-db@~1.33.0: version "1.33.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" @@ -6337,11 +7626,12 @@ mimic-response@^4.0.0: integrity sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg== mini-css-extract-plugin@^2.7.6: - version "2.7.6" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.6.tgz#282a3d38863fddcd2e0c220aaed5b90bc156564d" - integrity sha512-Qk7HcgaPkGG6eD77mLvZS1nmxlao3j+9PkrT9Uc7HAE1id3F41+DdBRYRYkbyfNRGzm8/YWtzhw7nVPmwhqTQw== + version "2.9.0" + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.0.tgz#c73a1327ccf466f69026ac22a8e8fd707b78a235" + integrity sha512-Zs1YsZVfemekSZG+44vBsYTLQORkPMwnlv+aehcxK/NLKC+EGhDB39/YePYYqx/sTk6NnYpuqikhSn7+JIevTA== dependencies: schema-utils "^4.0.0" + tapable "^2.2.1" minimalistic-assert@^1.0.0: version "1.0.1" @@ -6355,10 +7645,10 @@ minimatch@3.1.2, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1: dependencies: brace-expansion "^1.1.7" -minimatch@^9.0.1, minimatch@^9.0.3: - version "9.0.3" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" - integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== +minimatch@^9.0.3, minimatch@^9.0.4: + version "9.0.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== dependencies: brace-expansion "^2.0.1" @@ -6367,10 +7657,10 @@ minimist@^1.2.0: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== -"minipass@^5.0.0 || ^6.0.2 || ^7.0.0": - version "7.0.4" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c" - integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ== +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" + integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== mkdirp@0.3.0: version "0.3.0" @@ -6419,6 +7709,11 @@ nanoid@^3.3.7: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== +nanoid@^5.0.5: + version "5.0.7" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-5.0.7.tgz#6452e8c5a816861fd9d2b898399f7e5fd6944cc6" + integrity sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ== + negotiator@0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" @@ -6453,9 +7748,9 @@ node-forge@^1: integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== node-releases@^2.0.14: - version "2.0.14" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" - integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== + version "2.0.18" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.18.tgz#f010e8d35e2fe8d6b2944f03f70213ecedc4ca3f" + integrity sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g== nopt@1.0.10: version "1.0.10" @@ -6474,15 +7769,10 @@ normalize-range@^0.1.2: resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA== -normalize-url@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" - integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== - normalize-url@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-8.0.0.tgz#593dbd284f743e8dcf6a5ddf8fadff149c82701a" - integrity sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw== + version "8.0.1" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-8.0.1.tgz#9b7d96af9836577c58f5883e939365fa15623a4a" + integrity sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w== not@^0.1.0: version "0.1.0" @@ -6513,10 +7803,10 @@ object-assign@^4.0.1, object-assign@^4.1.1: resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== -object-inspect@^1.9.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" - integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== +object-inspect@^1.13.1: + version "1.13.2" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.2.tgz#dea0088467fb991e67af4058147a24824a3043ff" + integrity sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g== object-keys@^1.1.1: version "1.1.1" @@ -6583,6 +7873,11 @@ os-homedir@^1.0.1: resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" integrity sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ== +os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== + p-cancelable@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-3.0.0.tgz#63826694b54d61ca1c20ebcb6d3ecf5e14cd8050" @@ -6650,6 +7945,11 @@ p-try@^2.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== +package-json-from-dist@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz#e501cd3094b278495eb4258d4c9f6d5ac3019f00" + integrity sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw== + package-json@^8.1.0: version "8.1.1" resolved "https://registry.yarnpkg.com/package-json/-/package-json-8.1.1.tgz#3e9948e43df40d1e8e78a85485f1070bf8f03dc8" @@ -6660,6 +7960,11 @@ package-json@^8.1.0: registry-url "^6.0.0" semver "^7.3.7" +pako@~1.0.2: + version "1.0.11" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" + integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== + param-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5" @@ -6675,6 +7980,18 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" +parse-entities@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-2.0.0.tgz#53c6eb5b9314a1f4ec99fa0fdf7ce01ecda0cbe8" + integrity sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ== + dependencies: + character-entities "^1.0.0" + character-entities-legacy "^1.0.0" + character-reference-invalid "^1.0.0" + is-alphanumerical "^1.0.0" + is-decimal "^1.0.0" + is-hexadecimal "^1.0.0" + parse-entities@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-4.0.1.tgz#4e2a01111fb1c986549b944af39eeda258fc9e4e" @@ -6772,12 +8089,12 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== -path-scurry@^1.10.1: - version "1.10.1" - resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.10.1.tgz#9ba6bf5aa8500fe9fd67df4f0d9483b2b0bfc698" - integrity sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ== +path-scurry@^1.11.1: + version "1.11.1" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" + integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== dependencies: - lru-cache "^9.1.1 || ^10.0.0" + lru-cache "^10.2.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" path-to-regexp@0.1.7: @@ -6811,10 +8128,10 @@ periscopic@^3.0.0: estree-walker "^3.0.0" is-reference "^3.0.0" -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== +picocolors@^1.0.0, picocolors@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" + integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: version "2.3.1" @@ -6840,58 +8157,68 @@ pkg-up@^3.1.0: dependencies: find-up "^3.0.0" -postcss-calc@^8.2.3: - version "8.2.4" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-8.2.4.tgz#77b9c29bfcbe8a07ff6693dc87050828889739a5" - integrity sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q== +popmotion@11.0.3: + version "11.0.3" + resolved "https://registry.yarnpkg.com/popmotion/-/popmotion-11.0.3.tgz#565c5f6590bbcddab7a33a074bb2ba97e24b0cc9" + integrity sha512-Y55FLdj3UxkR7Vl3s7Qr4e9m0onSnP8W7d/xQLsoJM40vs6UKHFdygs6SWryasTZYqugMjm3BepCF4CWXDiHgA== + dependencies: + framesync "6.0.1" + hey-listen "^1.0.8" + style-value-types "5.0.0" + tslib "^2.1.0" + +postcss-calc@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-9.0.1.tgz#a744fd592438a93d6de0f1434c572670361eb6c6" + integrity sha512-TipgjGyzP5QzEhsOZUaIkeO5mKeMFpebWzRogWG/ysonUlnHcq5aJe0jOjpfzUU8PeSaBQnrE8ehR0QA5vs8PQ== dependencies: - postcss-selector-parser "^6.0.9" + postcss-selector-parser "^6.0.11" postcss-value-parser "^4.2.0" -postcss-colormin@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-5.3.1.tgz#86c27c26ed6ba00d96c79e08f3ffb418d1d1988f" - integrity sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ== +postcss-colormin@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-6.1.0.tgz#076e8d3fb291fbff7b10e6b063be9da42ff6488d" + integrity sha512-x9yX7DOxeMAR+BgGVnNSAxmAj98NX/YxEMNFP+SDCEeNLb2r3i6Hh1ksMsnW8Ub5SLCpbescQqn9YEbE9554Sw== dependencies: - browserslist "^4.21.4" + browserslist "^4.23.0" caniuse-api "^3.0.0" - colord "^2.9.1" + colord "^2.9.3" postcss-value-parser "^4.2.0" -postcss-convert-values@^5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz#04998bb9ba6b65aa31035d669a6af342c5f9d393" - integrity sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA== +postcss-convert-values@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-6.1.0.tgz#3498387f8efedb817cbc63901d45bd1ceaa40f48" + integrity sha512-zx8IwP/ts9WvUM6NkVSkiU902QZL1bwPhaVaLynPtCsOTqp+ZKbNi+s6XJg3rfqpKGA/oc7Oxk5t8pOQJcwl/w== dependencies: - browserslist "^4.21.4" + browserslist "^4.23.0" postcss-value-parser "^4.2.0" -postcss-discard-comments@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz#8df5e81d2925af2780075840c1526f0660e53696" - integrity sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ== +postcss-discard-comments@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-6.0.2.tgz#e768dcfdc33e0216380623652b0a4f69f4678b6c" + integrity sha512-65w/uIqhSBBfQmYnG92FO1mWZjJ4GL5b8atm5Yw2UgrwD7HiNiSSNwJor1eCFGzUgYnN/iIknhNRVqjrrpuglw== -postcss-discard-duplicates@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz#9eb4fe8456706a4eebd6d3b7b777d07bad03e848" - integrity sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw== +postcss-discard-duplicates@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-6.0.3.tgz#d121e893c38dc58a67277f75bb58ba43fce4c3eb" + integrity sha512-+JA0DCvc5XvFAxwx6f/e68gQu/7Z9ud584VLmcgto28eB8FqSFZwtrLwB5Kcp70eIoWP/HXqz4wpo8rD8gpsTw== -postcss-discard-empty@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz#e57762343ff7f503fe53fca553d18d7f0c369c6c" - integrity sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A== +postcss-discard-empty@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-6.0.3.tgz#ee39c327219bb70473a066f772621f81435a79d9" + integrity sha512-znyno9cHKQsK6PtxL5D19Fj9uwSzC2mB74cpT66fhgOadEUPyXFkbgwm5tvc3bt3NAy8ltE5MrghxovZRVnOjQ== -postcss-discard-overridden@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz#7e8c5b53325747e9d90131bb88635282fb4a276e" - integrity sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw== +postcss-discard-overridden@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-6.0.2.tgz#4e9f9c62ecd2df46e8fdb44dc17e189776572e2d" + integrity sha512-j87xzI4LUggC5zND7KdjsI25APtyMuynXZSujByMaav2roV6OZX+8AaCUcZSWqckZpjAjRyFDdpqybgjFO0HJQ== -postcss-discard-unused@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-discard-unused/-/postcss-discard-unused-5.1.0.tgz#8974e9b143d887677304e558c1166d3762501142" - integrity sha512-KwLWymI9hbwXmJa0dkrzpRbSJEh0vVUd7r8t0yOGPcfKzyJJxFM8kLyC5Ev9avji6nY95pOp1W6HqIrfT+0VGw== +postcss-discard-unused@^6.0.5: + version "6.0.5" + resolved "https://registry.yarnpkg.com/postcss-discard-unused/-/postcss-discard-unused-6.0.5.tgz#c1b0e8c032c6054c3fbd22aaddba5b248136f338" + integrity sha512-wHalBlRHkaNnNwfC8z+ppX57VhvS+HWgjW508esjdaEYr3Mx7Gnn2xA4R/CKf5+Z9S5qsqC+Uzh4ueENWwCVUA== dependencies: - postcss-selector-parser "^6.0.5" + postcss-selector-parser "^6.0.16" postcss-loader@^7.3.3: version "7.3.4" @@ -6902,82 +8229,82 @@ postcss-loader@^7.3.3: jiti "^1.20.0" semver "^7.5.4" -postcss-merge-idents@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-merge-idents/-/postcss-merge-idents-5.1.1.tgz#7753817c2e0b75d0853b56f78a89771e15ca04a1" - integrity sha512-pCijL1TREiCoog5nQp7wUe+TUonA2tC2sQ54UGeMmryK3UFGIYKqDyjnqd6RcuI4znFn9hWSLNN8xKE/vWcUQw== +postcss-merge-idents@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/postcss-merge-idents/-/postcss-merge-idents-6.0.3.tgz#7b9c31c7bc823c94bec50f297f04e3c2b838ea65" + integrity sha512-1oIoAsODUs6IHQZkLQGO15uGEbK3EAl5wi9SS8hs45VgsxQfMnxvt+L+zIr7ifZFIH14cfAeVe2uCTa+SPRa3g== dependencies: - cssnano-utils "^3.1.0" + cssnano-utils "^4.0.2" postcss-value-parser "^4.2.0" -postcss-merge-longhand@^5.1.7: - version "5.1.7" - resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz#24a1bdf402d9ef0e70f568f39bdc0344d568fb16" - integrity sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ== +postcss-merge-longhand@^6.0.5: + version "6.0.5" + resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-6.0.5.tgz#ba8a8d473617c34a36abbea8dda2b215750a065a" + integrity sha512-5LOiordeTfi64QhICp07nzzuTDjNSO8g5Ksdibt44d+uvIIAE1oZdRn8y/W5ZtYgRH/lnLDlvi9F8btZcVzu3w== dependencies: postcss-value-parser "^4.2.0" - stylehacks "^5.1.1" + stylehacks "^6.1.1" -postcss-merge-rules@^5.1.4: - version "5.1.4" - resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz#2f26fa5cacb75b1402e213789f6766ae5e40313c" - integrity sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g== +postcss-merge-rules@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-6.1.1.tgz#7aa539dceddab56019469c0edd7d22b64c3dea9d" + integrity sha512-KOdWF0gju31AQPZiD+2Ar9Qjowz1LTChSjFFbS+e2sFgc4uHOp3ZvVX4sNeTlk0w2O31ecFGgrFzhO0RSWbWwQ== dependencies: - browserslist "^4.21.4" + browserslist "^4.23.0" caniuse-api "^3.0.0" - cssnano-utils "^3.1.0" - postcss-selector-parser "^6.0.5" + cssnano-utils "^4.0.2" + postcss-selector-parser "^6.0.16" -postcss-minify-font-values@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz#f1df0014a726083d260d3bd85d7385fb89d1f01b" - integrity sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA== +postcss-minify-font-values@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-6.1.0.tgz#a0e574c02ee3f299be2846369211f3b957ea4c59" + integrity sha512-gklfI/n+9rTh8nYaSJXlCo3nOKqMNkxuGpTn/Qm0gstL3ywTr9/WRKznE+oy6fvfolH6dF+QM4nCo8yPLdvGJg== dependencies: postcss-value-parser "^4.2.0" -postcss-minify-gradients@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz#f1fe1b4f498134a5068240c2f25d46fcd236ba2c" - integrity sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw== +postcss-minify-gradients@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-6.0.3.tgz#ca3eb55a7bdb48a1e187a55c6377be918743dbd6" + integrity sha512-4KXAHrYlzF0Rr7uc4VrfwDJ2ajrtNEpNEuLxFgwkhFZ56/7gaE4Nr49nLsQDZyUe+ds+kEhf+YAUolJiYXF8+Q== dependencies: - colord "^2.9.1" - cssnano-utils "^3.1.0" + colord "^2.9.3" + cssnano-utils "^4.0.2" postcss-value-parser "^4.2.0" -postcss-minify-params@^5.1.4: - version "5.1.4" - resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz#c06a6c787128b3208b38c9364cfc40c8aa5d7352" - integrity sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw== +postcss-minify-params@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-6.1.0.tgz#54551dec77b9a45a29c3cb5953bf7325a399ba08" + integrity sha512-bmSKnDtyyE8ujHQK0RQJDIKhQ20Jq1LYiez54WiaOoBtcSuflfK3Nm596LvbtlFcpipMjgClQGyGr7GAs+H1uA== dependencies: - browserslist "^4.21.4" - cssnano-utils "^3.1.0" + browserslist "^4.23.0" + cssnano-utils "^4.0.2" postcss-value-parser "^4.2.0" -postcss-minify-selectors@^5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz#d4e7e6b46147b8117ea9325a915a801d5fe656c6" - integrity sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg== +postcss-minify-selectors@^6.0.4: + version "6.0.4" + resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-6.0.4.tgz#197f7d72e6dd19eed47916d575d69dc38b396aff" + integrity sha512-L8dZSwNLgK7pjTto9PzWRoMbnLq5vsZSTu8+j1P/2GB8qdtGQfn+K1uSvFgYvgh83cbyxT5m43ZZhUMTJDSClQ== dependencies: - postcss-selector-parser "^6.0.5" + postcss-selector-parser "^6.0.16" -postcss-modules-extract-imports@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz#cda1f047c0ae80c97dbe28c3e76a43b88025741d" - integrity sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw== +postcss-modules-extract-imports@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz#b4497cb85a9c0c4b5aabeb759bb25e8d89f15002" + integrity sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q== -postcss-modules-local-by-default@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.3.tgz#b08eb4f083050708998ba2c6061b50c2870ca524" - integrity sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA== +postcss-modules-local-by-default@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz#f1b9bd757a8edf4d8556e8d0f4f894260e3df78f" + integrity sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw== dependencies: icss-utils "^5.0.0" postcss-selector-parser "^6.0.2" postcss-value-parser "^4.1.0" -postcss-modules-scope@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.1.0.tgz#fbfddfda93a31f310f1d152c2bb4d3f3c5592ee0" - integrity sha512-SaIbK8XW+MZbd0xHPf7kdfA/3eOt7vxJ72IRecn3EzuZVLr1r0orzf0MX/pN8m+NMDoo6X/SQd8oeKqGZd8PXg== +postcss-modules-scope@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz#a43d28289a169ce2c15c00c4e64c0858e43457d5" + integrity sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ== dependencies: postcss-selector-parser "^6.0.4" @@ -6988,147 +8315,169 @@ postcss-modules-values@^4.0.0: dependencies: icss-utils "^5.0.0" -postcss-normalize-charset@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz#9302de0b29094b52c259e9b2cf8dc0879879f0ed" - integrity sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg== +postcss-normalize-charset@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-6.0.2.tgz#1ec25c435057a8001dac942942a95ffe66f721e1" + integrity sha512-a8N9czmdnrjPHa3DeFlwqst5eaL5W8jYu3EBbTTkI5FHkfMhFZh1EGbku6jhHhIzTA6tquI2P42NtZ59M/H/kQ== -postcss-normalize-display-values@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz#72abbae58081960e9edd7200fcf21ab8325c3da8" - integrity sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA== +postcss-normalize-display-values@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-6.0.2.tgz#54f02764fed0b288d5363cbb140d6950dbbdd535" + integrity sha512-8H04Mxsb82ON/aAkPeq8kcBbAtI5Q2a64X/mnRRfPXBq7XeogoQvReqxEfc0B4WPq1KimjezNC8flUtC3Qz6jg== dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-positions@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz#ef97279d894087b59325b45c47f1e863daefbb92" - integrity sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg== +postcss-normalize-positions@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-6.0.2.tgz#e982d284ec878b9b819796266f640852dbbb723a" + integrity sha512-/JFzI441OAB9O7VnLA+RtSNZvQ0NCFZDOtp6QPFo1iIyawyXg0YI3CYM9HBy1WvwCRHnPep/BvI1+dGPKoXx/Q== dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-repeat-style@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz#e9eb96805204f4766df66fd09ed2e13545420fb2" - integrity sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g== +postcss-normalize-repeat-style@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-6.0.2.tgz#f8006942fd0617c73f049dd8b6201c3a3040ecf3" + integrity sha512-YdCgsfHkJ2jEXwR4RR3Tm/iOxSfdRt7jplS6XRh9Js9PyCR/aka/FCb6TuHT2U8gQubbm/mPmF6L7FY9d79VwQ== dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-string@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz#411961169e07308c82c1f8c55f3e8a337757e228" - integrity sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w== +postcss-normalize-string@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-6.0.2.tgz#e3cc6ad5c95581acd1fc8774b309dd7c06e5e363" + integrity sha512-vQZIivlxlfqqMp4L9PZsFE4YUkWniziKjQWUtsxUiVsSSPelQydwS8Wwcuw0+83ZjPWNTl02oxlIvXsmmG+CiQ== dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-timing-functions@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz#d5614410f8f0b2388e9f240aa6011ba6f52dafbb" - integrity sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg== +postcss-normalize-timing-functions@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-6.0.2.tgz#40cb8726cef999de984527cbd9d1db1f3e9062c0" + integrity sha512-a+YrtMox4TBtId/AEwbA03VcJgtyW4dGBizPl7e88cTFULYsprgHWTbfyjSLyHeBcK/Q9JhXkt2ZXiwaVHoMzA== dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-unicode@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz#f67297fca3fea7f17e0d2caa40769afc487aa030" - integrity sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA== +postcss-normalize-unicode@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-6.1.0.tgz#aaf8bbd34c306e230777e80f7f12a4b7d27ce06e" + integrity sha512-QVC5TQHsVj33otj8/JD869Ndr5Xcc/+fwRh4HAsFsAeygQQXm+0PySrKbr/8tkDKzW+EVT3QkqZMfFrGiossDg== dependencies: - browserslist "^4.21.4" + browserslist "^4.23.0" postcss-value-parser "^4.2.0" -postcss-normalize-url@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz#ed9d88ca82e21abef99f743457d3729a042adcdc" - integrity sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew== +postcss-normalize-url@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-6.0.2.tgz#292792386be51a8de9a454cb7b5c58ae22db0f79" + integrity sha512-kVNcWhCeKAzZ8B4pv/DnrU1wNh458zBNp8dh4y5hhxih5RZQ12QWMuQrDgPRw3LRl8mN9vOVfHl7uhvHYMoXsQ== dependencies: - normalize-url "^6.0.1" postcss-value-parser "^4.2.0" -postcss-normalize-whitespace@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz#08a1a0d1ffa17a7cc6efe1e6c9da969cc4493cfa" - integrity sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA== +postcss-normalize-whitespace@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-6.0.2.tgz#fbb009e6ebd312f8b2efb225c2fcc7cf32b400cd" + integrity sha512-sXZ2Nj1icbJOKmdjXVT9pnyHQKiSAyuNQHSgRCUgThn2388Y9cGVDR+E9J9iAYbSbLHI+UUwLVl1Wzco/zgv0Q== dependencies: postcss-value-parser "^4.2.0" -postcss-ordered-values@^5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz#b6fd2bd10f937b23d86bc829c69e7732ce76ea38" - integrity sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ== +postcss-ordered-values@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-6.0.2.tgz#366bb663919707093451ab70c3f99c05672aaae5" + integrity sha512-VRZSOB+JU32RsEAQrO94QPkClGPKJEL/Z9PCBImXMhIeK5KAYo6slP/hBYlLgrCjFxyqvn5VC81tycFEDBLG1Q== dependencies: - cssnano-utils "^3.1.0" + cssnano-utils "^4.0.2" postcss-value-parser "^4.2.0" -postcss-reduce-idents@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/postcss-reduce-idents/-/postcss-reduce-idents-5.2.0.tgz#c89c11336c432ac4b28792f24778859a67dfba95" - integrity sha512-BTrLjICoSB6gxbc58D5mdBK8OhXRDqud/zodYfdSi52qvDHdMwk+9kB9xsM8yJThH/sZU5A6QVSmMmaN001gIg== +postcss-reduce-idents@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/postcss-reduce-idents/-/postcss-reduce-idents-6.0.3.tgz#b0d9c84316d2a547714ebab523ec7d13704cd486" + integrity sha512-G3yCqZDpsNPoQgbDUy3T0E6hqOQ5xigUtBQyrmq3tn2GxlyiL0yyl7H+T8ulQR6kOcHJ9t7/9H4/R2tv8tJbMA== dependencies: postcss-value-parser "^4.2.0" -postcss-reduce-initial@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz#798cd77b3e033eae7105c18c9d371d989e1382d6" - integrity sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg== +postcss-reduce-initial@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-6.1.0.tgz#4401297d8e35cb6e92c8e9586963e267105586ba" + integrity sha512-RarLgBK/CrL1qZags04oKbVbrrVK2wcxhvta3GCxrZO4zveibqbRPmm2VI8sSgCXwoUHEliRSbOfpR0b/VIoiw== dependencies: - browserslist "^4.21.4" + browserslist "^4.23.0" caniuse-api "^3.0.0" -postcss-reduce-transforms@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz#333b70e7758b802f3dd0ddfe98bb1ccfef96b6e9" - integrity sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ== +postcss-reduce-transforms@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-6.0.2.tgz#6fa2c586bdc091a7373caeee4be75a0f3e12965d" + integrity sha512-sB+Ya++3Xj1WaT9+5LOOdirAxP7dJZms3GRcYheSPi1PiTMigsxHAdkrbItHxwYHr4kt1zL7mmcHstgMYT+aiA== dependencies: postcss-value-parser "^4.2.0" -postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5, postcss-selector-parser@^6.0.9: - version "6.0.15" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz#11cc2b21eebc0b99ea374ffb9887174855a01535" - integrity sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw== +postcss-selector-parser@^6.0.11, postcss-selector-parser@^6.0.16, postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4: + version "6.1.1" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.1.1.tgz#5be94b277b8955904476a2400260002ce6c56e38" + integrity sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg== dependencies: cssesc "^3.0.0" util-deprecate "^1.0.2" -postcss-sort-media-queries@^4.4.1: - version "4.4.1" - resolved "https://registry.yarnpkg.com/postcss-sort-media-queries/-/postcss-sort-media-queries-4.4.1.tgz#04a5a78db3921eb78f28a1a781a2e68e65258128" - integrity sha512-QDESFzDDGKgpiIh4GYXsSy6sek2yAwQx1JASl5AxBtU1Lq2JfKBljIPNdil989NcSKRQX1ToiaKphImtBuhXWw== +postcss-sort-media-queries@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/postcss-sort-media-queries/-/postcss-sort-media-queries-5.2.0.tgz#4556b3f982ef27d3bac526b99b6c0d3359a6cf97" + integrity sha512-AZ5fDMLD8SldlAYlvi8NIqo0+Z8xnXU2ia0jxmuhxAU+Lqt9K+AlmLNJ/zWEnE9x+Zx3qL3+1K20ATgNOr3fAA== dependencies: - sort-css-media-queries "2.1.0" + sort-css-media-queries "2.2.0" -postcss-svgo@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-5.1.0.tgz#0a317400ced789f233a28826e77523f15857d80d" - integrity sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA== +postcss-svgo@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-6.0.3.tgz#1d6e180d6df1fa8a3b30b729aaa9161e94f04eaa" + integrity sha512-dlrahRmxP22bX6iKEjOM+c8/1p+81asjKT+V5lrgOH944ryx/OHpclnIbGsKVd3uWOXFLYJwCVf0eEkJGvO96g== dependencies: postcss-value-parser "^4.2.0" - svgo "^2.7.0" + svgo "^3.2.0" -postcss-unique-selectors@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz#a9f273d1eacd09e9aa6088f4b0507b18b1b541b6" - integrity sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA== +postcss-unique-selectors@^6.0.4: + version "6.0.4" + resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-6.0.4.tgz#983ab308896b4bf3f2baaf2336e14e52c11a2088" + integrity sha512-K38OCaIrO8+PzpArzkLKB42dSARtC2tmG6PvD4b1o1Q2E9Os8jzfWFfSy/rixsHwohtsDdFtAWGjFVFUdwYaMg== dependencies: - postcss-selector-parser "^6.0.5" + postcss-selector-parser "^6.0.16" -postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: +postcss-value-parser@^4.0.2, postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== -postcss-zindex@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-5.1.0.tgz#4a5c7e5ff1050bd4c01d95b1847dfdcc58a496ff" - integrity sha512-fgFMf0OtVSBR1va1JNHYgMxYk73yhn/qb4uQDq1DLGYolz8gHCyr/sesEuGUaYs58E3ZJRcpoGuPVoB7Meiq9A== +postcss-zindex@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-6.0.2.tgz#e498304b83a8b165755f53db40e2ea65a99b56e1" + integrity sha512-5BxW9l1evPB/4ZIc+2GobEBoKC+h8gPGCMi+jxsYvd2x0mjq7wazk6DrP71pStqxE9Foxh5TVnonbWpFZzXaYg== -postcss@^8.4.17, postcss@^8.4.21, postcss@^8.4.26: - version "8.4.32" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.32.tgz#1dac6ac51ab19adb21b8b34fd2d93a86440ef6c9" - integrity sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw== +postcss@8.4.38: + version "8.4.38" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.38.tgz#b387d533baf2054288e337066d81c6bee9db9e0e" + integrity sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A== dependencies: nanoid "^3.3.7" picocolors "^1.0.0" - source-map-js "^1.0.2" + source-map-js "^1.2.0" + +postcss@^8.4.21, postcss@^8.4.24, postcss@^8.4.26, postcss@^8.4.33, postcss@^8.4.38: + version "8.4.40" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.40.tgz#eb81f2a4dd7668ed869a6db25999e02e9ad909d8" + integrity sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q== + dependencies: + nanoid "^3.3.7" + picocolors "^1.0.1" + source-map-js "^1.2.0" + +posthog-js@^1.136.8: + version "1.149.2" + resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.149.2.tgz#a7af6038e9355d8e4044c33d4d0ddfef95940331" + integrity sha512-4tNtVJkq3wZ5CvfOEp3Jtl/r3ogZb5To+bdu7JoO5QjkpTY9TV1pfo/Ag4keODpAzRDahC8OaCoIr4mY3dSK4g== + dependencies: + fflate "^0.4.8" + preact "^10.19.3" + web-vitals "^4.0.1" + +preact@^10.19.3: + version "10.23.1" + resolved "https://registry.yarnpkg.com/preact/-/preact-10.23.1.tgz#d400107289bc979881c5212cb5f5cd22cd1dc38c" + integrity sha512-O5UdRsNh4vdZaTieWe3XOgSpdMAmkIYBCT3VhQDlKrzyCm8lUYsk0fmVEvoQQifoOjFRTaHZO69ylrzTW2BH+A== pretty-error@^4.0.0: version "4.0.0" @@ -7151,11 +8500,16 @@ prism-react-renderer@^2.0.6, prism-react-renderer@^2.3.0: "@types/prismjs" "^1.26.0" clsx "^2.0.0" -prismjs@^1.29.0: +prismjs@^1.27.0, prismjs@^1.29.0: version "1.29.0" resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.29.0.tgz#f113555a8fa9b57c35e637bba27509dcf802dd12" integrity sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q== +prismjs@~1.27.0: + version "1.27.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.27.0.tgz#bb6ee3138a0b438a3653dd4d6ce0cc6510a45057" + integrity sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA== + process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" @@ -7169,7 +8523,7 @@ prompts@^2.4.2: kleur "^3.0.3" sisteransi "^1.0.5" -prop-types@^15.6.2, prop-types@^15.7.2: +prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -7186,9 +8540,9 @@ property-information@^5.0.0: xtend "^4.0.0" property-information@^6.0.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/property-information/-/property-information-6.4.0.tgz#6bc4c618b0c2d68b3bb8b552cbb97f8e300a0f82" - integrity sha512-9t5qARVofg2xQqKtytzt+lZ4d1Qvj8t5B8fEwXK6qOfgRLgH/b13QlgEyDh033NOS31nXeFbYv7CLUDG1CeifQ== + version "6.5.0" + resolved "https://registry.yarnpkg.com/property-information/-/property-information-6.5.0.tgz#6212fbb52ba757e92ef4fb9d657563b933b7ffec" + integrity sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig== proto-list@~1.2.1: version "1.2.4" @@ -7261,10 +8615,10 @@ range-parser@^1.2.1, range-parser@~1.2.1: resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -raw-body@2.5.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" - integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== +raw-body@2.5.2: + version "2.5.2" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" + integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== dependencies: bytes "3.1.2" http-errors "2.0.0" @@ -7281,6 +8635,11 @@ rc@1.2.8: minimist "^1.2.0" strip-json-comments "~2.0.1" +react-complex-tree@^2.3.7: + version "2.4.4" + resolved "https://registry.yarnpkg.com/react-complex-tree/-/react-complex-tree-2.4.4.tgz#7395f38e68a5c955d60f390191942bbf05da1839" + integrity sha512-Nltzn7oJMF9NnPxrfxRxVD/4u/ZkCVEnwQ4Em6hmZT+m/DUCorIoPsL3VV86zZXx0D2Rj6LX8dHWnYFrMmYYlw== + react-dev-utils@^12.0.1: version "12.0.1" resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-12.0.1.tgz#ba92edb4a1f379bd46ccd6bcd4e7bc398df33e73" @@ -7312,12 +8671,12 @@ react-dev-utils@^12.0.1: text-table "^0.2.0" react-dom@^18.2.0: - version "18.2.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" - integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== + version "18.3.1" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4" + integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw== dependencies: loose-envify "^1.1.0" - scheduler "^0.23.0" + scheduler "^0.23.2" react-error-overlay@^6.0.11: version "6.0.11" @@ -7330,9 +8689,9 @@ react-fast-compare@^3.2.0, react-fast-compare@^3.2.2: integrity sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ== react-helmet-async@*: - version "2.0.4" - resolved "https://registry.yarnpkg.com/react-helmet-async/-/react-helmet-async-2.0.4.tgz#50a4377778f380ed1d0136303916b38eff1bf153" - integrity sha512-yxjQMWposw+akRfvpl5+8xejl4JtUlHnEBcji6u8/e6oc7ozT+P9PNTWMhCbz2y9tc5zPegw2BvKjQA+NwdEjQ== + version "2.0.5" + resolved "https://registry.yarnpkg.com/react-helmet-async/-/react-helmet-async-2.0.5.tgz#cfc70cd7bb32df7883a8ed55502a1513747223ec" + integrity sha512-rYUYHeus+i27MvFE+Jaa4WsyBKGkL6qVgbJvSBoX8mbsWoABJXdEO0bZyi0F6i+4f0NuIb8AvqPMj3iXFHkMwg== dependencies: invariant "^2.2.4" react-fast-compare "^3.2.2" @@ -7349,20 +8708,20 @@ react-helmet-async@^1.3.0: react-fast-compare "^3.2.0" shallowequal "^1.1.0" -react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0: +react-is@^16.10.2, react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== react-json-view-lite@^1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/react-json-view-lite/-/react-json-view-lite-1.2.1.tgz#c59a0bea4ede394db331d482ee02e293d38f8218" - integrity sha512-Itc0g86fytOmKZoIoJyGgvNqohWSbh3NXIKNgH6W6FT9PC1ck4xas1tT3Rr/b3UlFXyA9Jjaw9QSXdZy2JwGMQ== + version "1.4.0" + resolved "https://registry.yarnpkg.com/react-json-view-lite/-/react-json-view-lite-1.4.0.tgz#0ff493245f4550abe5e1f1836f170fa70bb95914" + integrity sha512-wh6F6uJyYAmQ4fK0e8dSQMEWuvTs2Wr3el3sLD9bambX1+pSWUVXIz1RFaoy3TI1mZ0FqdpKq9YgbgTTgyrmXA== -react-live@^4.1.5: - version "4.1.5" - resolved "https://registry.yarnpkg.com/react-live/-/react-live-4.1.5.tgz#a4fa4cfdcad763503a209a29bace3339764fdfb1" - integrity sha512-ul3Zwvqvh6KTg8j7xGCT26+c8J9vQ+LFUrZCbrrrzEExuVB/39s1GKG3NsywnL+aGAjpfnUTaVCe7KlKIvVPiw== +react-live@^4.1.6: + version "4.1.7" + resolved "https://registry.yarnpkg.com/react-live/-/react-live-4.1.7.tgz#a451054bee78e6c9b4410dfc3940b318d9bc7880" + integrity sha512-NTzl0POOAW3dkp7+QL30duOrIu2Vzf2LHdx4TaQ0BqOAtQcSTKEXujfm9jR2VoCHko0oi35PYp38yKQBXz4mrg== dependencies: prism-react-renderer "^2.0.6" sucrase "^3.31.0" @@ -7375,6 +8734,64 @@ react-loadable-ssr-addon-v5-slorber@^1.0.1: dependencies: "@babel/runtime" "^7.10.3" +"react-loadable@npm:@docusaurus/react-loadable@6.0.0": + version "6.0.0" + resolved "https://registry.yarnpkg.com/@docusaurus/react-loadable/-/react-loadable-6.0.0.tgz#de6c7f73c96542bd70786b8e522d535d69069dc4" + integrity sha512-YMMxTUQV/QFSnbgrP3tjDzLHRg7vsbMn8e9HAa8o/1iXoiomo48b7sk/kkmWEuWNDPJVlKSJRB6Y2fHqdJk+SQ== + dependencies: + "@types/react" "*" + +react-markdown@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/react-markdown/-/react-markdown-9.0.1.tgz#c05ddbff67fd3b3f839f8c648e6fb35d022397d1" + integrity sha512-186Gw/vF1uRkydbsOIkcGXw7aHq0sZOCRFFjGrr7b9+nVZg4UfA4enXCaxm4fUzecU38sWfrNDitGhshuU7rdg== + dependencies: + "@types/hast" "^3.0.0" + devlop "^1.0.0" + hast-util-to-jsx-runtime "^2.0.0" + html-url-attributes "^3.0.0" + mdast-util-to-hast "^13.0.0" + remark-parse "^11.0.0" + remark-rehype "^11.0.0" + unified "^11.0.0" + unist-util-visit "^5.0.0" + vfile "^6.0.0" + +react-remove-scroll-bar@^2.3.3, react-remove-scroll-bar@^2.3.4: + version "2.3.6" + resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.6.tgz#3e585e9d163be84a010180b18721e851ac81a29c" + integrity sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g== + dependencies: + react-style-singleton "^2.2.1" + tslib "^2.0.0" + +react-remove-scroll@2.5.5: + version "2.5.5" + resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz#1e31a1260df08887a8a0e46d09271b52b3a37e77" + integrity sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw== + dependencies: + react-remove-scroll-bar "^2.3.3" + react-style-singleton "^2.2.1" + tslib "^2.1.0" + use-callback-ref "^1.3.0" + use-sidecar "^1.1.2" + +react-remove-scroll@2.5.7: + version "2.5.7" + resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.5.7.tgz#15a1fd038e8497f65a695bf26a4a57970cac1ccb" + integrity sha512-FnrTWO4L7/Bhhf3CYBNArEG/yROV0tKmTv7/3h9QCFvH6sndeFf1wPqOcbFVu5VAulS5dV1wGT3GZZ/1GawqiA== + dependencies: + react-remove-scroll-bar "^2.3.4" + react-style-singleton "^2.2.1" + tslib "^2.1.0" + use-callback-ref "^1.3.0" + use-sidecar "^1.1.2" + +react-resizable-panels@2.0.19: + version "2.0.19" + resolved "https://registry.yarnpkg.com/react-resizable-panels/-/react-resizable-panels-2.0.19.tgz#df259898c682cb774af65c3bc38c1b29c855b99b" + integrity sha512-v3E41kfKSuCPIvJVb4nL4mIZjjKIn/gh6YqZF/gDfQDolv/8XnhJBek4EiV2gOr3hhc5A3kOGOayk3DhanpaQw== + react-router-config@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/react-router-config/-/react-router-config-5.1.1.tgz#0f4263d1a80c6b2dc7b9c1902c9526478194a988" @@ -7410,14 +8827,53 @@ react-router@5.3.4, react-router@^5.3.4: tiny-invariant "^1.0.2" tiny-warning "^1.0.0" +react-smooth@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/react-smooth/-/react-smooth-4.0.1.tgz#6200d8699bfe051ae40ba187988323b1449eab1a" + integrity sha512-OE4hm7XqR0jNOq3Qmk9mFLyd6p2+j6bvbPJ7qlB7+oo0eNcL2l7WQzG6MBnT3EXY6xzkLMUBec3AfewJdA0J8w== + dependencies: + fast-equals "^5.0.1" + prop-types "^15.8.1" + react-transition-group "^4.4.5" + +react-style-singleton@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.2.1.tgz#f99e420492b2d8f34d38308ff660b60d0b1205b4" + integrity sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g== + dependencies: + get-nonce "^1.0.0" + invariant "^2.2.4" + tslib "^2.0.0" + +react-syntax-highlighter@^15.5.0: + version "15.5.0" + resolved "https://registry.yarnpkg.com/react-syntax-highlighter/-/react-syntax-highlighter-15.5.0.tgz#4b3eccc2325fa2ec8eff1e2d6c18fa4a9e07ab20" + integrity sha512-+zq2myprEnQmH5yw6Gqc8lD55QHnpKaU8TOcFeC/Lg/MQSs8UknEA0JC4nTZGFAXC2J2Hyj/ijJ7NlabyPi2gg== + dependencies: + "@babel/runtime" "^7.3.1" + highlight.js "^10.4.1" + lowlight "^1.17.0" + prismjs "^1.27.0" + refractor "^3.6.0" + +react-transition-group@^4.4.5: + version "4.4.5" + resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.5.tgz#e53d4e3f3344da8521489fbef8f2581d42becdd1" + integrity sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g== + dependencies: + "@babel/runtime" "^7.5.5" + dom-helpers "^5.0.1" + loose-envify "^1.4.0" + prop-types "^15.6.2" + react@^18.2.0: - version "18.2.0" - resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" - integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== + version "18.3.1" + resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891" + integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ== dependencies: loose-envify "^1.1.0" -readable-stream@^2.0.1: +readable-stream@^2.0.1, readable-stream@~2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== @@ -7451,6 +8907,27 @@ reading-time@^1.5.0: resolved "https://registry.yarnpkg.com/reading-time/-/reading-time-1.5.0.tgz#d2a7f1b6057cb2e169beaf87113cc3411b5bc5bb" integrity sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg== +recharts-scale@^0.4.4: + version "0.4.5" + resolved "https://registry.yarnpkg.com/recharts-scale/-/recharts-scale-0.4.5.tgz#0969271f14e732e642fcc5bd4ab270d6e87dd1d9" + integrity sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w== + dependencies: + decimal.js-light "^2.4.1" + +recharts@^2.12.4: + version "2.12.7" + resolved "https://registry.yarnpkg.com/recharts/-/recharts-2.12.7.tgz#c7f42f473a257ff88b43d88a92530930b5f9e773" + integrity sha512-hlLJMhPQfv4/3NBSAyq3gzGg4h2v69RJh6KU7b3pXYNNAELs9kEoXOjbkxdXpALqKBoVmVptGfLpxdaVYqjmXQ== + dependencies: + clsx "^2.0.0" + eventemitter3 "^4.0.1" + lodash "^4.17.21" + react-is "^16.10.2" + react-smooth "^4.0.0" + recharts-scale "^0.4.4" + tiny-invariant "^1.3.1" + victory-vendor "^36.6.8" + rechoir@^0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" @@ -7465,6 +8942,15 @@ recursive-readdir@^2.2.2: dependencies: minimatch "^3.0.5" +refractor@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/refractor/-/refractor-3.6.0.tgz#ac318f5a0715ead790fcfb0c71f4dd83d977935a" + integrity sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA== + dependencies: + hastscript "^6.0.0" + parse-entities "^2.0.0" + prismjs "~1.27.0" + regenerate-unicode-properties@^10.1.0: version "10.1.1" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz#6b0e05489d9076b04c436f318d9b067bba459480" @@ -7619,9 +9105,9 @@ remark-gfm@^4.0.0: unified "^11.0.0" remark-mdx@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/remark-mdx/-/remark-mdx-3.0.0.tgz#146905a3925b078970e05fc89b0e16b9cc3bfddd" - integrity sha512-O7yfjuC6ra3NHPbRVxfflafAj3LTwx3b73aBvkEFU5z4PsD6FD4vrqJAkE5iNGLz71GdjXfgRqm3SQ0h0VuE7g== + version "3.0.1" + resolved "https://registry.yarnpkg.com/remark-mdx/-/remark-mdx-3.0.1.tgz#8f73dd635c1874e44426e243f72c0977cf60e212" + integrity sha512-3Pz3yPQ5Rht2pM5R+0J2MrGoBSrzf+tJG94N+t/ilfdh8YLyyKYtidAYwTveB20BoHAcwIopOUqhcmh2F7hGYA== dependencies: mdast-util-mdx "^3.0.0" micromark-extension-mdxjs "^3.0.0" @@ -7637,9 +9123,9 @@ remark-parse@^11.0.0: unified "^11.0.0" remark-rehype@^11.0.0: - version "11.0.0" - resolved "https://registry.yarnpkg.com/remark-rehype/-/remark-rehype-11.0.0.tgz#7f21c08738bde024be5f16e4a8b13e5d7a04cf6b" - integrity sha512-vx8x2MDMcxuE4lBmQ46zYUDfcFMmvg80WYX+UNLeG6ixjdCCLcw1lrgAukwBTuOFsS78eoAedHGn9sNM0w7TPw== + version "11.1.0" + resolved "https://registry.yarnpkg.com/remark-rehype/-/remark-rehype-11.1.0.tgz#d5f264f42bcbd4d300f030975609d01a1697ccdc" + integrity sha512-z3tJrAs2kIs1AqIIy6pzHmAHlF1hWQ+OdY4/hv+Wxe35EhyLKcajL33iUEn3ScxtFox9nUvRufR/Zre8Q08H/g== dependencies: "@types/hast" "^3.0.0" "@types/mdast" "^4.0.0" @@ -7741,9 +9227,9 @@ rtl-detect@^1.0.4: integrity sha512-PGMBq03+TTG/p/cRB7HCLKJ1MgDIi07+QU1faSjiYRfmY5UsAttV9Hs08jDAHVwcOwmVLcSJkpwyfXszVjWfIQ== rtlcss@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/rtlcss/-/rtlcss-4.1.1.tgz#f20409fcc197e47d1925996372be196fee900c0c" - integrity sha512-/oVHgBtnPNcggP2aVXQjSy6N1mMAfHg4GSag0QtZBlD5bdDgAHwr4pydqJGd+SUCu9260+Pjqbjwtvu7EMH1KQ== + version "4.2.0" + resolved "https://registry.yarnpkg.com/rtlcss/-/rtlcss-4.2.0.tgz#627b08806bd6851adb4d0670b63919fb6a3ea038" + integrity sha512-AV+V3oOVvCrqyH5Q/6RuT1IDH1Xy5kJTkEWTWZPN5rdQ3HCFOd8SrbC7c6N5Y8bPpCfZSR6yYbUATXslvfvu5g== dependencies: escalade "^3.1.1" picocolors "^1.0.0" @@ -7773,14 +9259,14 @@ safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.1.0, safe-buffer@~5.2.0: integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== sax@^1.2.4: - version "1.3.0" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.3.0.tgz#a5dbe77db3be05c9d1ee7785dbd3ea9de51593d0" - integrity sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA== + version "1.4.1" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.4.1.tgz#44cc8988377f126304d3b3fc1010c733b929ef0f" + integrity sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg== -scheduler@^0.23.0: - version "0.23.0" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" - integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw== +scheduler@^0.23.2: + version "0.23.2" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.2.tgz#414ba64a3b282892e944cf2108ecc078d115cdc3" + integrity sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ== dependencies: loose-envify "^1.1.0" @@ -7802,7 +9288,7 @@ schema-utils@^3.0.0, schema-utils@^3.1.1, schema-utils@^3.2.0: ajv "^6.12.5" ajv-keywords "^3.5.2" -schema-utils@^4.0.0: +schema-utils@^4.0.0, schema-utils@^4.0.1: version "4.2.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.2.0.tgz#70d7c93e153a273a805801882ebd3bff20d89c8b" integrity sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw== @@ -7840,17 +9326,20 @@ semver-diff@^4.0.0: dependencies: semver "^7.3.5" +semver@^5.5.0: + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + semver@^6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.3.2, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.4: - version "7.5.4" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" - integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== - dependencies: - lru-cache "^6.0.0" +semver@^7.3.2, semver@^7.3.5, semver@^7.3.7, semver@^7.5.4: + version "7.6.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== send@0.18.0: version "0.18.0" @@ -7872,9 +9361,9 @@ send@0.18.0: statuses "2.0.1" serialize-javascript@^6.0.0, serialize-javascript@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.1.tgz#b206efb27c3da0b0ab6b52f48d170b7996458e5c" - integrity sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w== + version "6.0.2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" + integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== dependencies: randombytes "^2.1.0" @@ -7915,15 +9404,22 @@ serve-static@1.15.0: parseurl "~1.3.3" send "0.18.0" -set-function-length@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.1.1.tgz#4bc39fafb0307224a33e106a7d35ca1218d659ed" - integrity sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ== +set-function-length@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== dependencies: - define-data-property "^1.1.1" - get-intrinsic "^1.2.1" + define-data-property "^1.1.4" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" gopd "^1.0.1" - has-property-descriptors "^1.0.0" + has-property-descriptors "^1.0.2" + +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== setprototypeof@1.1.0: version "1.1.0" @@ -7942,7 +9438,7 @@ shallow-clone@^3.0.0: dependencies: kind-of "^6.0.2" -shallowequal@^1.1.0: +shallowequal@1.1.0, shallowequal@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8" integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ== @@ -7984,13 +9480,14 @@ shiki@^0.14.7: vscode-textmate "^8.0.0" side-channel@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" - integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + version "1.0.6" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" + integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== dependencies: - call-bind "^1.0.0" - get-intrinsic "^1.0.2" - object-inspect "^1.9.0" + call-bind "^1.0.7" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + object-inspect "^1.13.1" signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3: version "3.0.7" @@ -8017,9 +9514,9 @@ sisteransi@^1.0.5: integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== sitemap@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/sitemap/-/sitemap-7.1.1.tgz#eeed9ad6d95499161a3eadc60f8c6dce4bea2bef" - integrity sha512-mK3aFtjz4VdJN0igpIJrinf3EO8U8mxOPsTBzSsy06UtjZQJ3YY3o3Xa7zSc5nMqcMrRwlChHZ18Kxg0caiPBg== + version "7.1.2" + resolved "https://registry.yarnpkg.com/sitemap/-/sitemap-7.1.2.tgz#6ce1deb43f6f177c68bc59cf93632f54e3ae6b72" + integrity sha512-ARCqzHJ0p4gWt+j7NlU5eDlIO9+Rkr/JhPFZKKQ1l5GCus7rJH4UdrlVAh0xC/gDS/Qir2UMxqYNHtsKr2rpCw== dependencies: "@types/node" "^17.0.5" "@types/sax" "^1.2.1" @@ -8048,6 +9545,14 @@ smartypants@^0.2.2: resolved "https://registry.yarnpkg.com/smartypants/-/smartypants-0.2.2.tgz#ad7124d8eb9ab437906db1cd7bd7aaf49e5d9a42" integrity sha512-TzobUYoEft/xBtb2voRPryAUIvYguG0V7Tt3de79I1WfXgCwelqVsGuZSnu3GFGRZhXR90AeEYIM+icuB/S06Q== +snake-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-3.0.4.tgz#4f2bbd568e9935abdfd593f34c691dadb49c452c" + integrity sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg== + dependencies: + dot-case "^3.0.4" + tslib "^2.0.3" + sockjs@^0.3.24: version "0.3.24" resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce" @@ -8057,15 +9562,33 @@ sockjs@^0.3.24: uuid "^8.3.2" websocket-driver "^0.7.4" -sort-css-media-queries@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/sort-css-media-queries/-/sort-css-media-queries-2.1.0.tgz#7c85e06f79826baabb232f5560e9745d7a78c4ce" - integrity sha512-IeWvo8NkNiY2vVYdPa27MCQiR0MN0M80johAYFVxWWXQ44KU84WNxjslwBHmc/7ZL2ccwkM7/e6S5aiKZXm7jA== +solc@^0.8.25: + version "0.8.26" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.8.26.tgz#afc78078953f6ab3e727c338a2fefcd80dd5b01a" + integrity sha512-yiPQNVf5rBFHwN6SIf3TUUvVAFKcQqmSUFeq+fb6pNRCo0ZCgpYOZDi3BVoezCPIAcKrVYd/qXlBLUP9wVrZ9g== + dependencies: + command-exists "^1.2.8" + commander "^8.1.0" + follow-redirects "^1.12.1" + js-sha3 "0.8.0" + memorystream "^0.3.1" + semver "^5.5.0" + tmp "0.0.33" -source-map-js@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" - integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== +sonner@^1.4.41: + version "1.5.0" + resolved "https://registry.yarnpkg.com/sonner/-/sonner-1.5.0.tgz#af359f817063318415326b33aab54c5d17c747b7" + integrity sha512-FBjhG/gnnbN6FY0jaNnqZOMmB73R+5IiyYAw8yBj7L54ER7HB3fOSE5OFiQiE2iXWxeXKvg6fIP4LtVppHEdJA== + +sort-css-media-queries@2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/sort-css-media-queries/-/sort-css-media-queries-2.2.0.tgz#aa33cf4a08e0225059448b6c40eddbf9f1c8334c" + integrity sha512-0xtkGhWCC9MGt/EzgnvbbbKhqWjl1+/rncmhTh5qCpbYguXh6S/qwePfv/JQ8jePXXmqingylxoC49pCkSPIbA== + +source-map-js@^1.0.1, source-map-js@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" + integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== source-map-support@~0.5.20: version "0.5.21" @@ -8075,7 +9598,7 @@ source-map-support@~0.5.20: buffer-from "^1.0.0" source-map "^0.6.0" -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0: +source-map@^0.6.0, source-map@~0.6.0: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== @@ -8133,10 +9656,10 @@ srcset@^4.0.0: resolved "https://registry.yarnpkg.com/srcset/-/srcset-4.0.0.tgz#336816b665b14cd013ba545b6fe62357f86e65f4" integrity sha512-wvLeHgcVHKO8Sc/H/5lkGreJQVeYMm9rlmt8PuR1xE31rIuXhuzznUUqAt8MqLhB3MqJdFzlNAfpcWnxiFUcPw== -stable@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" - integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== +state-local@^1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/state-local/-/state-local-1.0.7.tgz#da50211d07f05748d53009bee46307a37db386d5" + integrity sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w== statuses@2.0.1: version "2.0.1" @@ -8153,7 +9676,16 @@ std-env@^3.0.1: resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.7.0.tgz#c9f7386ced6ecf13360b6c6c55b8aaa4ef7481d2" integrity sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg== -"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -8186,9 +9718,9 @@ string_decoder@~1.1.1: safe-buffer "~5.1.0" stringify-entities@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-4.0.3.tgz#cfabd7039d22ad30f3cc435b0ca2c1574fc88ef8" - integrity sha512-BP9nNHMhhfcMbiuQKCqMjhDP5yBCAxsPu4pHFFzJ6Alo9dZgY4VLDPutXqIjpRiMoKdp7Av85Gr73Q5uH9k7+g== + version "4.0.4" + resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-4.0.4.tgz#b3b79ef5f277cc4ac73caeb0236c5ba939b3a4f3" + integrity sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg== dependencies: character-entities-html4 "^2.0.0" character-entities-legacy "^3.0.0" @@ -8202,7 +9734,14 @@ stringify-object@^3.3.0: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -8244,19 +9783,47 @@ style-to-object@^0.4.0: inline-style-parser "0.1.1" style-to-object@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-1.0.5.tgz#5e918349bc3a39eee3a804497d97fcbbf2f0d7c0" - integrity sha512-rDRwHtoDD3UMMrmZ6BzOW0naTjMsVZLIjsGleSKS/0Oz+cgCfAPRspaqJuE8rDzpKha/nEvnM0IF4seEAZUTKQ== + version "1.0.6" + resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-1.0.6.tgz#0c28aed8be1813d166c60d962719b2907c26547b" + integrity sha512-khxq+Qm3xEyZfKd/y9L3oIWQimxuc4STrQKtQn8aSDRHb8mFgpukgX1hdzfrMEW6JCjyJ8p89x+IUMVnCBI1PA== dependencies: - inline-style-parser "0.2.2" + inline-style-parser "0.2.3" -stylehacks@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-5.1.1.tgz#7934a34eb59d7152149fa69d6e9e56f2fc34bcc9" - integrity sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw== +style-value-types@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/style-value-types/-/style-value-types-5.0.0.tgz#76c35f0e579843d523187989da866729411fc8ad" + integrity sha512-08yq36Ikn4kx4YU6RD7jWEv27v4V+PUsOGa4n/as8Et3CuODMJQ00ENeAVXAeydX4Z2j1XHZF1K2sX4mGl18fA== + dependencies: + hey-listen "^1.0.8" + tslib "^2.1.0" + +styled-components@^6.1.8: + version "6.1.12" + resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-6.1.12.tgz#0d9d511aacfb9052936146dcc2856559e6fae4df" + integrity sha512-n/O4PzRPhbYI0k1vKKayfti3C/IGcPf+DqcrOB7O/ab9x4u/zjqraneT5N45+sIe87cxrCApXM8Bna7NYxwoTA== + dependencies: + "@emotion/is-prop-valid" "1.2.2" + "@emotion/unitless" "0.8.1" + "@types/stylis" "4.2.5" + css-to-react-native "3.2.0" + csstype "3.1.3" + postcss "8.4.38" + shallowequal "1.1.0" + stylis "4.3.2" + tslib "2.6.2" + +stylehacks@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-6.1.1.tgz#543f91c10d17d00a440430362d419f79c25545a6" + integrity sha512-gSTTEQ670cJNoaeIp9KX6lZmm8LJ3jPB5yJmX8Zq/wQxOsAFXV3qjWzHas3YYk1qesuVIyYWWUpZ0vSE/dTSGg== dependencies: - browserslist "^4.21.4" - postcss-selector-parser "^6.0.4" + browserslist "^4.23.0" + postcss-selector-parser "^6.0.16" + +stylis@4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.3.2.tgz#8f76b70777dd53eb669c6f58c997bf0a9972e444" + integrity sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg== sucrase@^3.31.0: version "3.35.0" @@ -8302,30 +9869,48 @@ svg-parser@^2.0.4: resolved "https://registry.yarnpkg.com/svg-parser/-/svg-parser-2.0.4.tgz#fdc2e29e13951736140b76cb122c8ee6630eb6b5" integrity sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ== -svgo@^2.7.0, svgo@^2.8.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-2.8.0.tgz#4ff80cce6710dc2795f0c7c74101e6764cfccd24" - integrity sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg== +svgo@^3.0.2, svgo@^3.2.0: + version "3.3.2" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-3.3.2.tgz#ad58002652dffbb5986fc9716afe52d869ecbda8" + integrity sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw== dependencies: "@trysound/sax" "0.2.0" commander "^7.2.0" - css-select "^4.1.3" - css-tree "^1.1.3" - csso "^4.2.0" + css-select "^5.1.0" + css-tree "^2.3.1" + css-what "^6.1.0" + csso "^5.0.5" picocolors "^1.0.0" - stable "^0.1.8" + +swr@^2.2.5: + version "2.2.5" + resolved "https://registry.yarnpkg.com/swr/-/swr-2.2.5.tgz#063eea0e9939f947227d5ca760cc53696f46446b" + integrity sha512-QtxqyclFeAsxEUeZIYmsaQ0UjimSq1RZ9Un7I68/0ClKK/U3LoyQunwkQfJZr2fc22DfIXLNDc2wFyTEikCUpg== + dependencies: + client-only "^0.0.1" + use-sync-external-store "^1.2.0" + +tailwind-merge@^2.2.1: + version "2.4.0" + resolved "https://registry.yarnpkg.com/tailwind-merge/-/tailwind-merge-2.4.0.tgz#1345209dc1f484f15159c9180610130587703042" + integrity sha512-49AwoOQNKdqKPd9CViyH5wJoSKsCDjUlzL8DxuGp3P1FsGY36NJDAa18jLZcaHAUUuTj+JB8IAo8zWgBNvBF7A== + +tailwindcss-animate@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz#318b692c4c42676cc9e67b19b78775742388bef4" + integrity sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA== tapable@^1.0.0: version "1.1.3" resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== -tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0: +tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0, tapable@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== -terser-webpack-plugin@^5.3.7, terser-webpack-plugin@^5.3.9: +terser-webpack-plugin@^5.3.10, terser-webpack-plugin@^5.3.9: version "5.3.10" resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz#904f4c9193c6fd2a03f693a2150c62a92f40d199" integrity sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w== @@ -8337,9 +9922,9 @@ terser-webpack-plugin@^5.3.7, terser-webpack-plugin@^5.3.9: terser "^5.26.0" terser@^5.10.0, terser@^5.15.1, terser@^5.26.0: - version "5.26.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.26.0.tgz#ee9f05d929f4189a9c28a0feb889d96d50126fe1" - integrity sha512-dytTGoE2oHgbNV9nTzgBEPaqAWvcJNl66VZ0BkJqlvp71IjO8CxdBx/ykCNb47cLnCmCvRZ6ZR0tLkqvZCdVBQ== + version "5.31.3" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.31.3.tgz#b24b7beb46062f4653f049eea4f0cd165d0f0c38" + integrity sha512-pAfYn3NIZLyZpa83ZKigvj6Rn9c/vd5KfYGX7cN1mnzqgDcxWvrU5ZtAfIKhEXz9nRecw4z3LXkjaq96/qZqAA== dependencies: "@jridgewell/source-map" "^0.3.3" acorn "^8.8.2" @@ -8370,16 +9955,23 @@ thunky@^1.0.2: resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== -tiny-invariant@^1.0.2: - version "1.3.1" - resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642" - integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw== +tiny-invariant@^1.0.2, tiny-invariant@^1.3.1: + version "1.3.3" + resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.3.tgz#46680b7a873a0d5d10005995eb90a70d74d60127" + integrity sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg== tiny-warning@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== +tmp@0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" @@ -8421,20 +10013,25 @@ trough@^1.0.0: integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA== trough@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/trough/-/trough-2.1.0.tgz#0f7b511a4fde65a46f18477ab38849b22c554876" - integrity sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g== + version "2.2.0" + resolved "https://registry.yarnpkg.com/trough/-/trough-2.2.0.tgz#94a60bd6bd375c152c1df911a4b11d5b0256f50f" + integrity sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw== ts-interface-checker@^0.1.9: version "0.1.13" resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699" integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA== -tslib@^2.0.3, tslib@^2.6.0: +tslib@2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== +tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.1, tslib@^2.6.0: + version "2.6.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0" + integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ== + type-fest@^1.0.1: version "1.4.0" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-1.4.0.tgz#e9fb813fe3bf1744ec359d55d1affefa76f14be1" @@ -8460,10 +10057,10 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" -typedoc@^0.25.3: - version "0.25.6" - resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.25.6.tgz#1505538aecea511dd669652c71d042a2427bd4fc" - integrity sha512-1rdionQMpOkpA58qfym1J+YD+ukyA1IEIa4VZahQI2ZORez7dhOvEyUotQL/8rSoMBopdzOS+vAIsORpQO4cTA== +typedoc@^0.25.7: + version "0.25.13" + resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.25.13.tgz#9a98819e3b2d155a6d78589b46fa4c03768f0922" + integrity sha512-pQqiwiJ+Z4pigfOnnysObszLiU3mVLWAExSPf+Mu06G/qsc3wzbuM56SZQvONhHLncLUhYzOVkjFFpFfL5AzhQ== dependencies: lunr "^2.3.9" marked "^4.3.0" @@ -8509,9 +10106,9 @@ unicode-property-aliases-ecmascript@^2.0.0: integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== unified@^11.0.0, unified@^11.0.3, unified@^11.0.4: - version "11.0.4" - resolved "https://registry.yarnpkg.com/unified/-/unified-11.0.4.tgz#f4be0ac0fe4c88cb873687c07c64c49ed5969015" - integrity sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ== + version "11.0.5" + resolved "https://registry.yarnpkg.com/unified/-/unified-11.0.5.tgz#f66677610a5c0a9ee90cab2b8d4d66037026d9e1" + integrity sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA== dependencies: "@types/unist" "^3.0.0" bail "^2.0.0" @@ -8639,13 +10236,13 @@ unpipe@1.0.0, unpipe@~1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== -update-browserslist-db@^1.0.13: - version "1.0.13" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" - integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== +update-browserslist-db@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz#7ca61c0d8650766090728046e416a8cde682859e" + integrity sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ== dependencies: - escalade "^3.1.1" - picocolors "^1.0.0" + escalade "^3.1.2" + picocolors "^1.0.1" update-notifier@^6.0.2: version "6.0.2" @@ -8683,11 +10280,31 @@ url-loader@^4.1.1: mime-types "^2.1.27" schema-utils "^3.0.0" +use-callback-ref@^1.3.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.2.tgz#6134c7f6ff76e2be0b56c809b17a650c942b1693" + integrity sha512-elOQwe6Q8gqZgDA8mrh44qRTQqpIHDcZ3hXTLjBe1i4ph8XpNJnO+aQf3NaG+lriLopI4HMx9VjQLfPQ6vhnoA== + dependencies: + tslib "^2.0.0" + use-editable@^2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/use-editable/-/use-editable-2.3.3.tgz#a292fe9ba4c291cd28d1cc2728c75a5fc8d9a33f" integrity sha512-7wVD2JbfAFJ3DK0vITvXBdpd9JAz5BcKAAolsnLBuBn6UDDwBGuCIAGvR3yA2BNKm578vAMVHFCWaOcA+BhhiA== +use-sidecar@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.1.2.tgz#2f43126ba2d7d7e117aa5855e5d8f0276dfe73c2" + integrity sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw== + dependencies: + detect-node-es "^1.1.0" + tslib "^2.0.0" + +use-sync-external-store@^1.2.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz#c3b6390f3a30eba13200d2302dcdf1e7b57b2ef9" + integrity sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw== + util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -8699,9 +10316,9 @@ utila@~0.4: integrity sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA== utility-types@^3.10.0: - version "3.10.0" - resolved "https://registry.yarnpkg.com/utility-types/-/utility-types-3.10.0.tgz#ea4148f9a741015f05ed74fd615e1d20e6bed82b" - integrity sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg== + version "3.11.0" + resolved "https://registry.yarnpkg.com/utility-types/-/utility-types-3.11.0.tgz#607c40edb4f258915e901ea7995607fdf319424c" + integrity sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw== utils-merge@1.0.1: version "1.0.1" @@ -8729,9 +10346,9 @@ vfile-location@^3.2.0: integrity sha512-aLEIZKv/oxuCDZ8lkJGhuhztf/BW4M+iHdCwglA/eWc+vtuRFJj8EtgceYFX4LRjOhCAAiNHsKGssC6onJ+jbA== vfile-location@^5.0.0: - version "5.0.2" - resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-5.0.2.tgz#220d9ca1ab6f8b2504a4db398f7ebc149f9cb464" - integrity sha512-NXPYyxyBSH7zB5U6+3uDdd6Nybz6o6/od9rk8bp9H8GR3L+cm/fC0uUTbqBmUTnMCUDslAGBOIKNfvvb+gGlDg== + version "5.0.3" + resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-5.0.3.tgz#cb9eacd20f2b6426d19451e0eafa3d0a846225c3" + integrity sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg== dependencies: "@types/unist" "^3.0.0" vfile "^6.0.0" @@ -8763,14 +10380,48 @@ vfile@^4.0.0: vfile-message "^2.0.0" vfile@^6.0.0, vfile@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/vfile/-/vfile-6.0.1.tgz#1e8327f41eac91947d4fe9d237a2dd9209762536" - integrity sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw== + version "6.0.2" + resolved "https://registry.yarnpkg.com/vfile/-/vfile-6.0.2.tgz#ef49548ea3d270097a67011921411130ceae7deb" + integrity sha512-zND7NlS8rJYb/sPqkb13ZvbbUoExdbi4w3SfRrMq6R3FvnLQmmfpajJNITuuYm6AZ5uao9vy4BAos3EXBPf2rg== dependencies: "@types/unist" "^3.0.0" unist-util-stringify-position "^4.0.0" vfile-message "^4.0.0" +victory-vendor@^36.6.8: + version "36.9.2" + resolved "https://registry.yarnpkg.com/victory-vendor/-/victory-vendor-36.9.2.tgz#668b02a448fa4ea0f788dbf4228b7e64669ff801" + integrity sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ== + dependencies: + "@types/d3-array" "^3.0.3" + "@types/d3-ease" "^3.0.0" + "@types/d3-interpolate" "^3.0.1" + "@types/d3-scale" "^4.0.2" + "@types/d3-shape" "^3.1.0" + "@types/d3-time" "^3.0.0" + "@types/d3-timer" "^3.0.0" + d3-array "^3.1.6" + d3-ease "^3.0.1" + d3-interpolate "^3.0.1" + d3-scale "^4.0.2" + d3-shape "^3.1.0" + d3-time "^3.0.0" + d3-timer "^3.0.1" + +viem@2.9.16: + version "2.9.16" + resolved "https://registry.yarnpkg.com/viem/-/viem-2.9.16.tgz#2127871db1908a70798eddb820024b5f0ddc9152" + integrity sha512-FQRfN4G7uKEUs5DYvVrH/kZmTkwcSDpTBxnadpwG1EEP8nHm57WDpSaGN7PwSPVgJ6rMo5MENT5hgnqaNTlb2w== + dependencies: + "@adraffy/ens-normalize" "1.10.0" + "@noble/curves" "1.2.0" + "@noble/hashes" "1.3.2" + "@scure/bip32" "1.3.2" + "@scure/bip39" "1.2.1" + abitype "1.0.0" + isows "1.0.3" + ws "8.13.0" + vscode-oniguruma@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz#439bfad8fe71abd7798338d1cd3dc53a8beea94b" @@ -8781,10 +10432,10 @@ vscode-textmate@^8.0.0: resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-8.0.0.tgz#2c7a3b1163ef0441097e0b5d6389cd5504b59e5d" integrity sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg== -watchpack@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" - integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== +watchpack@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.1.tgz#29308f2cac150fa8e4c92f90e0ec954a9fed7fff" + integrity sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg== dependencies: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" @@ -8806,10 +10457,15 @@ web-namespaces@^2.0.0: resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-2.0.1.tgz#1010ff7c650eccb2592cebeeaf9a1b253fd40692" integrity sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ== +web-vitals@^4.0.1: + version "4.2.2" + resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-4.2.2.tgz#e883245180b95e175eb75a5ca8903b1a11597d7a" + integrity sha512-nYfoOqb4EmElljyXU2qdeE76KsvoHdftQKY4DzA9Aw8DervCg2bG634pHLrJ/d6+B4mE3nWTSJv8Mo7B2mbZkw== + webpack-bundle-analyzer@^4.9.0: - version "4.10.1" - resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.10.1.tgz#84b7473b630a7b8c21c741f81d8fe4593208b454" - integrity sha512-s3P7pgexgT/HTUSYgxJyn28A+99mmLq4HsJepMPzu0R8ImJc52QNqaFYW1Z2z2uIb1/J3eYgaAWVpaC+v/1aAQ== + version "4.10.2" + resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.10.2.tgz#633af2862c213730be3dbdf40456db171b60d5bd" + integrity sha512-vJptkMm9pk5si4Bv922ZbKLV8UTT4zib4FPgXMhgzUny0bfDDkLXAVQs3ly3fS4/TN9ROFtb0NFrm04UXFE/Vw== dependencies: "@discoveryjs/json-ext" "0.5.7" acorn "^8.0.4" @@ -8819,16 +10475,15 @@ webpack-bundle-analyzer@^4.9.0: escape-string-regexp "^4.0.0" gzip-size "^6.0.0" html-escaper "^2.0.2" - is-plain-object "^5.0.0" opener "^1.5.2" picocolors "^1.0.0" sirv "^2.0.3" ws "^7.3.1" -webpack-dev-middleware@^5.3.1: - version "5.3.3" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz#efae67c2793908e7311f1d9b06f2a08dcc97e51f" - integrity sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA== +webpack-dev-middleware@^5.3.4: + version "5.3.4" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz#eb7b39281cbce10e104eb2b8bf2b63fce49a3517" + integrity sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q== dependencies: colorette "^2.0.10" memfs "^3.4.3" @@ -8837,9 +10492,9 @@ webpack-dev-middleware@^5.3.1: schema-utils "^4.0.0" webpack-dev-server@^4.15.1: - version "4.15.1" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz#8944b29c12760b3a45bdaa70799b17cb91b03df7" - integrity sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA== + version "4.15.2" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz#9e0c70a42a012560860adb186986da1248333173" + integrity sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g== dependencies: "@types/bonjour" "^3.5.9" "@types/connect-history-api-fallback" "^1.3.5" @@ -8869,7 +10524,7 @@ webpack-dev-server@^4.15.1: serve-index "^1.9.1" sockjs "^0.3.24" spdy "^4.0.2" - webpack-dev-middleware "^5.3.1" + webpack-dev-middleware "^5.3.4" ws "^8.13.0" webpack-merge@^5.9.0: @@ -8881,39 +10536,39 @@ webpack-merge@^5.9.0: flat "^5.0.2" wildcard "^2.0.0" -webpack-sources@^3.2.2, webpack-sources@^3.2.3: +webpack-sources@^3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== webpack@^5.88.1: - version "5.89.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.89.0.tgz#56b8bf9a34356e93a6625770006490bf3a7f32dc" - integrity sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw== + version "5.93.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.93.0.tgz#2e89ec7035579bdfba9760d26c63ac5c3462a5e5" + integrity sha512-Y0m5oEY1LRuwly578VqluorkXbvXKh7U3rLoQCEO04M97ScRr44afGVkI0FQFsXzysk5OgFAxjZAb9rsGQVihA== dependencies: "@types/eslint-scope" "^3.7.3" - "@types/estree" "^1.0.0" - "@webassemblyjs/ast" "^1.11.5" - "@webassemblyjs/wasm-edit" "^1.11.5" - "@webassemblyjs/wasm-parser" "^1.11.5" + "@types/estree" "^1.0.5" + "@webassemblyjs/ast" "^1.12.1" + "@webassemblyjs/wasm-edit" "^1.12.1" + "@webassemblyjs/wasm-parser" "^1.12.1" acorn "^8.7.1" - acorn-import-assertions "^1.9.0" - browserslist "^4.14.5" + acorn-import-attributes "^1.9.5" + browserslist "^4.21.10" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.15.0" + enhanced-resolve "^5.17.0" es-module-lexer "^1.2.1" eslint-scope "5.1.1" events "^3.2.0" glob-to-regexp "^0.4.1" - graceful-fs "^4.2.9" + graceful-fs "^4.2.11" json-parse-even-better-errors "^2.3.1" loader-runner "^4.2.0" mime-types "^2.1.27" neo-async "^2.6.2" schema-utils "^3.2.0" tapable "^2.1.1" - terser-webpack-plugin "^5.3.7" - watchpack "^2.4.0" + terser-webpack-plugin "^5.3.10" + watchpack "^2.4.1" webpack-sources "^3.2.3" webpackbar@^5.0.2: @@ -9006,15 +10661,20 @@ write-file-atomic@^3.0.3: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" +ws@8.13.0: + version "8.13.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" + integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== + ws@^7.3.1: - version "7.5.9" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" - integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== + version "7.5.10" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" + integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== ws@^8.13.0: - version "8.16.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.16.0.tgz#d1cd774f36fbc07165066a60e40323eab6446fd4" - integrity sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ== + version "8.18.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" + integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== xdg-basedir@^5.0.1, xdg-basedir@^5.1.0: version "5.1.0" @@ -9038,12 +10698,7 @@ yallist@^3.0.2: resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - -yaml@^1.10.0, yaml@^1.10.2, yaml@^1.7.2: +yaml@^1.7.2: version "1.10.2" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== @@ -9054,9 +10709,9 @@ yocto-queue@^0.1.0: integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== yocto-queue@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.0.0.tgz#7f816433fb2cbc511ec8bf7d263c3b58a1a3c251" - integrity sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g== + version "1.1.1" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.1.1.tgz#fef65ce3ac9f8a32ceac5a634f74e17e5b232110" + integrity sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g== zwitch@^1.0.0: version "1.0.5" From f87ffbe1efc38a33df241adf97d2b82e9cede7c8 Mon Sep 17 00:00:00 2001 From: Emmanuel Yusuf Date: Thu, 1 Aug 2024 18:50:55 +0100 Subject: [PATCH 127/186] feat(glossary): updated glossary (#7168) * updated glossary * chore: change import to ES import * change javascript to typescript * update content based on feedback --------- Co-authored-by: Dan Forbes --- docs/docs/glossary/index.md | 83 +++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/docs/docs/glossary/index.md b/docs/docs/glossary/index.md index 39294de39ed..1af9691a85e 100644 --- a/docs/docs/glossary/index.md +++ b/docs/docs/glossary/index.md @@ -108,3 +108,86 @@ contract Test { } ] ``` + +## Proxy + +A `proxy` in Web3.js serves as an intermediary between your application and an Ethereum node, **facilitating communication** by **forwarding requests and responses**. Configuring a proxy can help overcome network restrictions, enhance security, and improve load balancing. You can set up a proxy using either HttpProvider or WebSocketProvider in Web3.js. + +## HttpProvider + +[HttpProvider](https://docs.web3js.org/guides/web3_providers_guide/#http-provider) in Web3.js connects an application to an Ethereum node over HTTP. It allows for sending transactions, reading blockchain data, and interacting with smart contracts. You create a Web3 instance with the node’s URL to establish the connection. It’s essential for DApps needing blockchain interaction but can block the event loop, so alternatives like `WebSocketProvider` might be used for better performance when real-time communication is needed. + +```typescript +import { Web3 } from 'web3'; +const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')); +``` + +## WebSocketProvider +[WebSocketProvider](https://docs.web3js.org/guides/web3_providers_guide/#websocket-provider) in Web3.js connects your application to an Ethereum node via WebSocket, enabling real-time and asynchronous communication. This provider is ideal for applications needing real-time updates, such as new blocks or smart contract events. It offers better performance for high-throughput applications compared to `HttpProvider`. Ensure secure connections with `wss://` for exposed endpoints. Handle reconnections gracefully for reliable operation. + +```javascript title='WebSocketProvider example' +import { Web3 } from 'web3'; +const web3 = new Web3(new Web3.providers.WebsocketProvider('ws://localhost:8546')); +``` + +## Events + +The `Events` class in Web3.js is a crucial part of the library that enables developers to interact with and listen for events emitted by smart contracts on the Ethereum network. Events in **smart contracts** are similar to `logs` or `messages` that the **contract emits to notify** external applications about specific actions or state changes. Web3.js provides a comprehensive set of tools to handle these events, making it possible to build responsive and interactive decentralized applications (dApps). + +#### Example + +```solidity title='Event in solidity' +contract MyContract { + event Transfer(address indexed from, address indexed to, uint value); + + function transfer(address recipient, uint amount) public { + // ... transfer logic ... + emit Transfer(msg.sender, recipient, amount); + } +} +``` + +```javascript title='Event in web3.js' +import { Web3 } from 'web3'; +const MyContract = require('./MyContract.json'); // Assuming ABI is loaded + +const web3 = new Web3('wss://mainnet.infura.io/v3/YOUR_INFURA_ID'); // Replace with your provider URL +const contractAddress = '0x...'; // Replace with your contract address + +const myContract = new web3.eth.Contract(MyContract.abi, contractAddress); + +const transferEvent = myContract.events.Transfer(); // Access the Transfer event + +transferEvent.on('data', (event) => { + console.log('Transfer Event:', event); + // Process the event data (from, to, value) +}); +``` + +## Event logs + +`Logs` in Web3.js are a part of **Ethereum transactions** that contain **information about events triggered** within smart contracts. They provide a way to record and retrieve significant occurrences within the blockchain. `Event logs` are particularly useful for tracking changes, and debugging. + +#### Example + +```typescript +import { Web3 } from 'web3'; +const web3 = new Web3('https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID'); + +const options = { + fromBlock: 0, + toBlock: 'latest', + address: '0xYourContractAddress', + topics: [ + web3.utils.sha3('Transfer(address,address,uint256)') + ] +}; + +web3.eth.getPastLogs(options) + .then((logs) => { + console.log(logs); + }) + .catch((error) => { + console.error('Error retrieving logs:', error); + }); +` \ No newline at end of file From 61e9e06b10d1188c32e1f7284f0596c4fd08607b Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 2 Aug 2024 09:34:57 -0400 Subject: [PATCH 128/186] fix infura tests and secrets (#7163) * have tests run in pr * update test * update * update secrets * update * remove tests that involve getting blocks that are archived * update storage tests * adding tests * update tests * update package.json * update * update tests * update * update tests * update fee history * update * format * update blackbox tests * update scripts * revert tests * update fixtures * update tests * change back rules --- .github/workflows/black_box_tests.yml | 6 +- .github/workflows/build.yml | 4 +- .github/workflows/e2e_network_tests.yml | 1 - .../test/fixtures/rpc_method_wrappers.ts | 2 +- .../test/unit/rpc_method_wrappers.test.ts | 1 + packages/web3/package.json | 4 +- packages/web3/scripts/black_box_test.sh | 12 +- packages/web3/test/e2e/e2e_utils.ts | 16 +- packages/web3/test/e2e/estimate_gas.test.ts | 16 +- packages/web3/test/e2e/fixtures/sepolia.ts | 199 ++++++++++++++++++ packages/web3/test/e2e/get_balance.test.ts | 9 +- packages/web3/test/e2e/get_block.test.ts | 9 +- .../e2e/get_block_transaction_count.test.ts | 81 +++---- .../test/e2e/get_block_uncle_count.test.ts | 93 ++++---- packages/web3/test/e2e/get_chain_id.test.ts | 6 +- packages/web3/test/e2e/get_id.test.ts | 9 +- packages/web3/test/e2e/get_proof.test.ts | 15 +- .../test/e2e/get_transaction_count.test.ts | 12 +- .../e2e/get_transaction_from_block.test.ts | 10 +- packages/web3/test/e2e/get_uncle.test.ts | 28 +-- .../web3/test/e2e/mainnet/get_code.test.ts | 10 +- .../test/e2e/mainnet/get_storage_at.test.ts | 12 +- .../web3/test/e2e/sepolia/get_code.test.ts | 22 +- .../test/e2e/sepolia/get_storage_at.test.ts | 12 +- 24 files changed, 423 insertions(+), 166 deletions(-) diff --git a/.github/workflows/black_box_tests.yml b/.github/workflows/black_box_tests.yml index 19c84cee6dd..8d26e163264 100644 --- a/.github/workflows/black_box_tests.yml +++ b/.github/workflows/black_box_tests.yml @@ -29,9 +29,9 @@ jobs: needs: build runs-on: ubuntu-latest env: - INFURA_HTTP: ${{ secrets.INFURA_HTTP }} - INFURA_WSS: ${{ secrets.INFURA_WSS }} - INFURA_GOERLI_WS: ${{ secrets.INFURA_GOERLI_WS }} + INFURA_MAINNET_HTTP: ${{ secrets.INFURA_MAINNET_HTTP }} + INFURA_MAINNET_WS: ${{ secrets.INFURA_MAINNET_WS }} + INFURA_SEPOLIA_WS: ${{ secrets.INFURA_SEPOLIA_WS }} MODE: ${{ matrix.mode }} strategy: fail-fast: false diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f05eac79fd8..dd1279159b7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -206,8 +206,8 @@ jobs: needs: build runs-on: ubuntu-latest env: - INFURA_GOERLI_HTTP: ${{ secrets.INFURA_GOERLI_HTTP }} - INFURA_GOERLI_WS: ${{ secrets.INFURA_GOERLI_WS }} + INFURA_SEPOLIA_HTTP: ${{ secrets.INFURA_SEPOLIA_HTTP }} + INFURA_SEPOLIA_WS: ${{ secrets.INFURA_SEPOLIA_WS }} strategy: fail-fast: false matrix: diff --git a/.github/workflows/e2e_network_tests.yml b/.github/workflows/e2e_network_tests.yml index 508c45caee9..8f26d6c5281 100644 --- a/.github/workflows/e2e_network_tests.yml +++ b/.github/workflows/e2e_network_tests.yml @@ -5,7 +5,6 @@ on: - release/** tags: - v4.* - jobs: build: name: Build Packages diff --git a/packages/web3-net/test/fixtures/rpc_method_wrappers.ts b/packages/web3-net/test/fixtures/rpc_method_wrappers.ts index 0e76bcdd39b..701a966e67e 100644 --- a/packages/web3-net/test/fixtures/rpc_method_wrappers.ts +++ b/packages/web3-net/test/fixtures/rpc_method_wrappers.ts @@ -29,4 +29,4 @@ export const getPeerCountValidData: [DataFormat, any, any][] = [ [{ number: FMT_NUMBER.STR, bytes: FMT_BYTES.HEX }, '0x2', '2'], [{ number: FMT_NUMBER.NUMBER, bytes: FMT_BYTES.HEX }, '0x2', 2], [{ number: FMT_NUMBER.BIGINT, bytes: FMT_BYTES.HEX }, '0x2', BigInt('2')], -]; +]; \ No newline at end of file diff --git a/packages/web3-net/test/unit/rpc_method_wrappers.test.ts b/packages/web3-net/test/unit/rpc_method_wrappers.test.ts index 47d014e2b3e..e3f5bb9ad2a 100644 --- a/packages/web3-net/test/unit/rpc_method_wrappers.test.ts +++ b/packages/web3-net/test/unit/rpc_method_wrappers.test.ts @@ -56,6 +56,7 @@ describe('rpc_method_wrappers', () => { }, ); }); + it('isListening', async () => { await isListening(web3Net); diff --git a/packages/web3/package.json b/packages/web3/package.json index 2b680517e80..5740fcc04f4 100644 --- a/packages/web3/package.json +++ b/packages/web3/package.json @@ -46,8 +46,8 @@ "test": "jest --config=./test/unit/jest.config.js", "test:coverage:unit": "jest --config=./test/unit/jest.config.js --coverage=true --coverage-reporters=text", "test:coverage:integration": "jest --config=./test/integration/jest.config.js --forceExit --coverage=true --coverage-reporters=text", - "test:e2e:mainnet": "jest --config=./test/e2e/jest.config.js --forceExit", - "test:e2e:sepolia": "jest --config=./test/e2e/jest.config.js --forceExit", + "test:e2e:mainnet": "jest --config=./test/e2e/jest.config.js --forceExit --runInBand", + "test:e2e:sepolia": "jest --config=./test/e2e/jest.config.js --forceExit --runInBand", "test:sync:integration": "jest --config=./test/integration/jest.config.js ./test/integration/sync.test.ts", "test:ci": "jest --coverage=true --coverage-reporters=json --verbose", "test:watch": "npm test -- --watch", diff --git a/packages/web3/scripts/black_box_test.sh b/packages/web3/scripts/black_box_test.sh index 508f2bd76de..8f942aa3b9a 100755 --- a/packages/web3/scripts/black_box_test.sh +++ b/packages/web3/scripts/black_box_test.sh @@ -36,15 +36,15 @@ yarn if [[ ${BACKEND} == "infura" ]] then - if [ ! $INFURA_HTTP ] || [ ! $INFURA_WSS ] + if [ ! $INFURA_MAINNET_HTTP ] || [ ! $INFURA_MAINNET_WS ] then echo "No Infura provider URL specified" exit 1 elif [ $MODE == "http" ] then - WEB3_SYSTEM_TEST_PROVIDER=$INFURA_HTTP + WEB3_SYSTEM_TEST_PROVIDER=$INFURA_MAINNET_HTTP else - WEB3_SYSTEM_TEST_PROVIDER=$INFURA_WSS + WEB3_SYSTEM_TEST_PROVIDER=$INFURA_MAINNET_WS fi fi yarn "test:$BACKEND:$MODE" @@ -55,15 +55,15 @@ yarn if [[ ${BACKEND} == "infura" ]] then - if [ ! $INFURA_HTTP ] || [ ! $INFURA_WSS ] + if [ ! $INFURA_MAINNET_HTTP ] || [ ! $INFURA_MAINNET_WS ] then echo "No Infura provider URL specified" exit 1 elif [ $MODE == "http" ] then - WEB3_SYSTEM_TEST_PROVIDER=$INFURA_HTTP + WEB3_SYSTEM_TEST_PROVIDER=$INFURA_MAINNET_HTTP else - WEB3_SYSTEM_TEST_PROVIDER=$INFURA_WSS + WEB3_SYSTEM_TEST_PROVIDER=$INFURA_MAINNET_WS fi fi yarn "test:$BACKEND:$MODE" diff --git a/packages/web3/test/e2e/e2e_utils.ts b/packages/web3/test/e2e/e2e_utils.ts index 91165ddd899..23d170cb243 100644 --- a/packages/web3/test/e2e/e2e_utils.ts +++ b/packages/web3/test/e2e/e2e_utils.ts @@ -22,7 +22,6 @@ along with web3.js. If not, see . * copied over to each package's test directory. Because web3 package is the only package * running these E2E tests that use Sepolia and Mainnet, this util exists here for now. */ - import { getSystemTestBackend, BACKEND } from '../shared_fixtures/system_tests_utils'; // eslint-disable-next-line import/no-relative-packages import secrets from '../../../../.secrets.json'; @@ -42,7 +41,10 @@ export const getE2ETestAccountAddress = (): string => { if (process.env.TEST_ACCOUNT_ADDRESS !== undefined) { return process.env.TEST_ACCOUNT_ADDRESS; // eslint-disable-next-line no-else-return - } else if (getSystemTestBackend() === BACKEND.SEPOLIA || getSystemTestBackend() === BACKEND.MAINNET) { + } else if ( + getSystemTestBackend() === BACKEND.SEPOLIA || + getSystemTestBackend() === BACKEND.MAINNET + ) { return secrets[getSystemTestBackend().toUpperCase() as 'SEPOLIA' | 'MAINNET'].ACCOUNT .address; } @@ -64,7 +66,10 @@ export const getAllowedSendTransaction = (): boolean => { return Boolean(process.env.ALLOWED_SEND_TRANSACTION); // eslint-disable-next-line no-else-return - } else if (getSystemTestBackend() === BACKEND.SEPOLIA || getSystemTestBackend() === BACKEND.MAINNET) { + } else if ( + getSystemTestBackend() === BACKEND.SEPOLIA || + getSystemTestBackend() === BACKEND.MAINNET + ) { return secrets[getSystemTestBackend().toUpperCase() as 'SEPOLIA' | 'MAINNET'] .ALLOWED_SEND_TRANSACTION; } @@ -76,7 +81,10 @@ export const getE2ETestAccountPrivateKey = (): string => { if (process.env.TEST_ACCOUNT_PRIVATE_KEY !== undefined) { return process.env.TEST_ACCOUNT_PRIVATE_KEY; // eslint-disable-next-line no-else-return - } else if (getSystemTestBackend() === BACKEND.SEPOLIA || getSystemTestBackend() === BACKEND.MAINNET) { + } else if ( + getSystemTestBackend() === BACKEND.SEPOLIA || + getSystemTestBackend() === BACKEND.MAINNET + ) { return secrets[getSystemTestBackend().toUpperCase() as 'SEPOLIA' | 'MAINNET'].ACCOUNT .privateKey; } diff --git a/packages/web3/test/e2e/estimate_gas.test.ts b/packages/web3/test/e2e/estimate_gas.test.ts index 06a587027fd..bf04a1971f0 100644 --- a/packages/web3/test/e2e/estimate_gas.test.ts +++ b/packages/web3/test/e2e/estimate_gas.test.ts @@ -18,14 +18,19 @@ import { toHex } from 'web3-utils'; import Web3, { FMT_BYTES, FMT_NUMBER, Transaction } from '../../src'; import { getSystemE2ETestProvider } from './e2e_utils'; -import { closeOpenConnection, getSystemTestBackend, BACKEND } from '../shared_fixtures/system_tests_utils'; +import { + closeOpenConnection, + getSystemTestBackend, + BACKEND, +} from '../shared_fixtures/system_tests_utils'; import { toAllVariants } from '../shared_fixtures/utils'; import { mainnetBlockData } from './fixtures/mainnet'; import { sepoliaBlockData } from './fixtures/sepolia'; describe(`${getSystemTestBackend()} tests - estimateGas`, () => { const provider = getSystemE2ETestProvider(); - const blockData = getSystemTestBackend() === BACKEND.SEPOLIA ? sepoliaBlockData : mainnetBlockData; + const blockData = + getSystemTestBackend() === BACKEND.SEPOLIA ? sepoliaBlockData : mainnetBlockData; const simpleEthTransaction: Transaction = { from: '0x0000000000000000000000000000000000000000', to: '0x0000000000000000000000000000000000000000', @@ -37,7 +42,7 @@ describe(`${getSystemTestBackend()} tests - estimateGas`, () => { data: '0x60806040523480156200001157600080fd5b5060405162000a6a38038062000a6a8339818101604052810190620000379190620002a4565b80600090805190602001906200004f92919062000057565b505062000359565b828054620000659062000324565b90600052602060002090601f016020900481019282620000895760008555620000d5565b82601f10620000a457805160ff1916838001178555620000d5565b82800160010185558215620000d5579182015b82811115620000d4578251825591602001919060010190620000b7565b5b509050620000e49190620000e8565b5090565b5b8082111562000103576000816000905550600101620000e9565b5090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b620001708262000125565b810181811067ffffffffffffffff8211171562000192576200019162000136565b5b80604052505050565b6000620001a762000107565b9050620001b5828262000165565b919050565b600067ffffffffffffffff821115620001d857620001d762000136565b5b620001e38262000125565b9050602081019050919050565b60005b8381101562000210578082015181840152602081019050620001f3565b8381111562000220576000848401525b50505050565b60006200023d6200023784620001ba565b6200019b565b9050828152602081018484840111156200025c576200025b62000120565b5b62000269848285620001f0565b509392505050565b600082601f8301126200028957620002886200011b565b5b81516200029b84826020860162000226565b91505092915050565b600060208284031215620002bd57620002bc62000111565b5b600082015167ffffffffffffffff811115620002de57620002dd62000116565b5b620002ec8482850162000271565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806200033d57607f821691505b602082108103620003535762000352620002f5565b5b50919050565b61070180620003696000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063a41368621461003b578063cfae32171461006c575b600080fd5b6100556004803603810190610050919061043f565b61008a565b60405161006392919061052b565b60405180910390f35b6100746101b0565b604051610081919061055b565b60405180910390f35b600060607f0d363f2fba46ab11b6db8da0125b0d5484787c44e265b48810735998bab12b756000846040516100c0929190610672565b60405180910390a182600090805190602001906100de929190610242565b507f7d7846723bda52976e0286c6efffee937ee9f76817a867ec70531ad29fb1fc0e600060405161010f91906106a9565b60405180910390a160016000808054610127906105ac565b80601f0160208091040260200160405190810160405280929190818152602001828054610153906105ac565b80156101a05780601f10610175576101008083540402835291602001916101a0565b820191906000526020600020905b81548152906001019060200180831161018357829003601f168201915b5050505050905091509150915091565b6060600080546101bf906105ac565b80601f01602080910402602001604051908101604052809291908181526020018280546101eb906105ac565b80156102385780601f1061020d57610100808354040283529160200191610238565b820191906000526020600020905b81548152906001019060200180831161021b57829003601f168201915b5050505050905090565b82805461024e906105ac565b90600052602060002090601f01602090048101928261027057600085556102b7565b82601f1061028957805160ff19168380011785556102b7565b828001600101855582156102b7579182015b828111156102b657825182559160200191906001019061029b565b5b5090506102c491906102c8565b5090565b5b808211156102e15760008160009055506001016102c9565b5090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61034c82610303565b810181811067ffffffffffffffff8211171561036b5761036a610314565b5b80604052505050565b600061037e6102e5565b905061038a8282610343565b919050565b600067ffffffffffffffff8211156103aa576103a9610314565b5b6103b382610303565b9050602081019050919050565b82818337600083830152505050565b60006103e26103dd8461038f565b610374565b9050828152602081018484840111156103fe576103fd6102fe565b5b6104098482856103c0565b509392505050565b600082601f830112610426576104256102f9565b5b81356104368482602086016103cf565b91505092915050565b600060208284031215610455576104546102ef565b5b600082013567ffffffffffffffff811115610473576104726102f4565b5b61047f84828501610411565b91505092915050565b60008115159050919050565b61049d81610488565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b838110156104dd5780820151818401526020810190506104c2565b838111156104ec576000848401525b50505050565b60006104fd826104a3565b61050781856104ae565b93506105178185602086016104bf565b61052081610303565b840191505092915050565b60006040820190506105406000830185610494565b818103602083015261055281846104f2565b90509392505050565b6000602082019050818103600083015261057581846104f2565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806105c457607f821691505b6020821081036105d7576105d661057d565b5b50919050565b60008190508160005260206000209050919050565b600081546105ff816105ac565b61060981866104ae565b94506001821660008114610624576001811461063657610669565b60ff1983168652602086019350610669565b61063f856105dd565b60005b8381101561066157815481890152600182019150602081019050610642565b808801955050505b50505092915050565b6000604082019050818103600083015261068c81856105f2565b905081810360208301526106a081846104f2565b90509392505050565b600060208201905081810360008301526106c381846105f2565b90509291505056fea2646970667358221220fe0f28c9f8ef0a13a95934b974e7bc2ca6762b40a5b93ccd6ca2038f454bf52764736f6c634300080e003300000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000017736f6c79656e7420677265656e2069732070656f706c65000000000000000000', }; const expectedContractDeploymentTransactionGas = - getSystemTestBackend() === BACKEND.SEPOLIA ? 475494 : 475494; + getSystemTestBackend() === BACKEND.SEPOLIA ? 480435 : 480435; let web3: Web3; @@ -61,10 +66,7 @@ describe(`${getSystemTestBackend()} tests - estimateGas`, () => { }), )('estimateGas', async ({ transaction, block, format }) => { let _blockData = blockData[block]; - if ( - getSystemTestBackend() === BACKEND.MAINNET && - (block === 'blockHash' || block === 'blockNumber') - ) { + if (block === 'blockHash' || block === 'blockNumber') { /** * @NOTE Getting a block too far back in history * results in a missing trie node error, so diff --git a/packages/web3/test/e2e/fixtures/sepolia.ts b/packages/web3/test/e2e/fixtures/sepolia.ts index 9ab06b665db..6f79a26024c 100644 --- a/packages/web3/test/e2e/fixtures/sepolia.ts +++ b/packages/web3/test/e2e/fixtures/sepolia.ts @@ -636,8 +636,108 @@ export const sepoliaBlockHydrated = { value: '0x143c70de9f84c8', }, ], + transactionsRoot: '0xbd2f86bc39fbe1ac6e24ce390d268404c199da060116437803875d2c0bfe7970', uncles: [], + withdrawals: [ + { + address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', + amount: '0x3112f', + index: '0x3a477e', + validatorIndex: '0x38b', + }, + { + address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', + amount: '0x2ef5d', + index: '0x3a477f', + validatorIndex: '0x38c', + }, + { + address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', + amount: '0x2ef5d', + index: '0x3a4780', + validatorIndex: '0x38d', + }, + { + address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', + amount: '0x23743', + index: '0x3a4781', + validatorIndex: '0x38e', + }, + { + address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', + amount: '0x2ef5d', + index: '0x3a4782', + validatorIndex: '0x38f', + }, + { + address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', + amount: '0x2ef5d', + index: '0x3a4783', + validatorIndex: '0x390', + }, + { + address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', + amount: '0x2ef5d', + index: '0x3a4784', + validatorIndex: '0x391', + }, + { + address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', + amount: '0x2ef5d', + index: '0x3a4785', + validatorIndex: '0x392', + }, + { + address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', + amount: '0x2ef5d', + index: '0x3a4786', + validatorIndex: '0x393', + }, + { + address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', + amount: '0x25915', + index: '0x3a4787', + validatorIndex: '0x394', + }, + { + address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', + amount: '0x2ef5d', + index: '0x3a4788', + validatorIndex: '0x395', + }, + { + address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', + amount: '0x2ef5d', + index: '0x3a4789', + validatorIndex: '0x396', + }, + { + address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', + amount: '0x2ef5d', + index: '0x3a478a', + validatorIndex: '0x397', + }, + { + address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', + amount: '0x2ef5d', + index: '0x3a478b', + validatorIndex: '0x398', + }, + { + address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', + amount: '0x2ef5d', + index: '0x3a478c', + validatorIndex: '0x399', + }, + { + address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', + amount: '0x3112f', + index: '0x3a478d', + validatorIndex: '0x39a', + }, + ], + withdrawalsRoot: '0xb99e42eaca3fc1000aa8be987cf107e08030c0e9ca93dc6ea6b7df69e377f953', }; export const sepoliaBlock = { @@ -694,6 +794,105 @@ export const sepoliaBlock = { ], transactionsRoot: '0xbd2f86bc39fbe1ac6e24ce390d268404c199da060116437803875d2c0bfe7970', uncles: [], + withdrawals: [ + { + address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', + amount: '0x3112f', + index: '0x3a477e', + validatorIndex: '0x38b', + }, + { + address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', + amount: '0x2ef5d', + index: '0x3a477f', + validatorIndex: '0x38c', + }, + { + address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', + amount: '0x2ef5d', + index: '0x3a4780', + validatorIndex: '0x38d', + }, + { + address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', + amount: '0x23743', + index: '0x3a4781', + validatorIndex: '0x38e', + }, + { + address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', + amount: '0x2ef5d', + index: '0x3a4782', + validatorIndex: '0x38f', + }, + { + address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', + amount: '0x2ef5d', + index: '0x3a4783', + validatorIndex: '0x390', + }, + { + address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', + amount: '0x2ef5d', + index: '0x3a4784', + validatorIndex: '0x391', + }, + { + address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', + amount: '0x2ef5d', + index: '0x3a4785', + validatorIndex: '0x392', + }, + { + address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', + amount: '0x2ef5d', + index: '0x3a4786', + validatorIndex: '0x393', + }, + { + address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', + amount: '0x25915', + index: '0x3a4787', + validatorIndex: '0x394', + }, + { + address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', + amount: '0x2ef5d', + index: '0x3a4788', + validatorIndex: '0x395', + }, + { + address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', + amount: '0x2ef5d', + index: '0x3a4789', + validatorIndex: '0x396', + }, + { + address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', + amount: '0x2ef5d', + index: '0x3a478a', + validatorIndex: '0x397', + }, + { + address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', + amount: '0x2ef5d', + index: '0x3a478b', + validatorIndex: '0x398', + }, + { + address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', + amount: '0x2ef5d', + index: '0x3a478c', + validatorIndex: '0x399', + }, + { + address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', + amount: '0x3112f', + index: '0x3a478d', + validatorIndex: '0x39a', + }, + ], + withdrawalsRoot: '0xb99e42eaca3fc1000aa8be987cf107e08030c0e9ca93dc6ea6b7df69e377f953', }; export const sepoliaBlockData: { diff --git a/packages/web3/test/e2e/get_balance.test.ts b/packages/web3/test/e2e/get_balance.test.ts index daba0c6397f..e07f79b83fe 100644 --- a/packages/web3/test/e2e/get_balance.test.ts +++ b/packages/web3/test/e2e/get_balance.test.ts @@ -19,14 +19,19 @@ import { toHex } from 'web3-utils'; import Web3, { FMT_BYTES, FMT_NUMBER } from '../../src'; import { getSystemE2ETestProvider, getE2ETestAccountAddress } from './e2e_utils'; -import { closeOpenConnection, getSystemTestBackend, BACKEND } from '../shared_fixtures/system_tests_utils'; +import { + closeOpenConnection, + getSystemTestBackend, + BACKEND, +} from '../shared_fixtures/system_tests_utils'; import { toAllVariants } from '../shared_fixtures/utils'; import { sepoliaBlockData } from './fixtures/sepolia'; import { mainnetBlockData } from './fixtures/mainnet'; describe(`${getSystemTestBackend()} tests - getBalance`, () => { const provider = getSystemE2ETestProvider(); - const blockData = getSystemTestBackend() === BACKEND.SEPOLIA ? sepoliaBlockData : mainnetBlockData; + const blockData = + getSystemTestBackend() === BACKEND.SEPOLIA ? sepoliaBlockData : mainnetBlockData; const expectedBalance = getSystemTestBackend() === BACKEND.SEPOLIA ? '172530374997217200' : '2099795781954790368'; diff --git a/packages/web3/test/e2e/get_block.test.ts b/packages/web3/test/e2e/get_block.test.ts index bd9753992b6..33d78291b36 100644 --- a/packages/web3/test/e2e/get_block.test.ts +++ b/packages/web3/test/e2e/get_block.test.ts @@ -21,7 +21,11 @@ import { format as formatter } from 'web3-utils'; import Web3, { FMT_BYTES, FMT_NUMBER } from '../../src'; import { getSystemE2ETestProvider } from './e2e_utils'; -import { closeOpenConnection, getSystemTestBackend, BACKEND } from '../shared_fixtures/system_tests_utils'; +import { + closeOpenConnection, + getSystemTestBackend, + BACKEND, +} from '../shared_fixtures/system_tests_utils'; import { toAllVariants } from '../shared_fixtures/utils'; import { sepoliaBlock, sepoliaBlockData, sepoliaBlockHydrated } from './fixtures/sepolia'; import { mainnetBlockHydrated } from './fixtures/mainnet_block_hydrated'; @@ -29,7 +33,8 @@ import { mainnetBlock, mainnetBlockData } from './fixtures/mainnet'; describe(`${getSystemTestBackend()} tests - getBlock`, () => { const provider = getSystemE2ETestProvider(); - const blockData = getSystemTestBackend() === BACKEND.SEPOLIA ? sepoliaBlockData : mainnetBlockData; + const blockData = + getSystemTestBackend() === BACKEND.SEPOLIA ? sepoliaBlockData : mainnetBlockData; let web3: Web3; diff --git a/packages/web3/test/e2e/get_block_transaction_count.test.ts b/packages/web3/test/e2e/get_block_transaction_count.test.ts index ef65b08a2bb..0dea0eb16f7 100644 --- a/packages/web3/test/e2e/get_block_transaction_count.test.ts +++ b/packages/web3/test/e2e/get_block_transaction_count.test.ts @@ -15,19 +15,22 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ import { isBigInt, isHexStrict, isNumber, isString } from 'web3-validator'; -import { toHex } from 'web3-utils'; import Web3, { FMT_BYTES, FMT_NUMBER } from '../../src'; import { getSystemE2ETestProvider } from './e2e_utils'; -import { closeOpenConnection, getSystemTestBackend, BACKEND } from '../shared_fixtures/system_tests_utils'; +import { + closeOpenConnection, + getSystemTestBackend, + BACKEND, +} from '../shared_fixtures/system_tests_utils'; import { toAllVariants } from '../shared_fixtures/utils'; import { sepoliaBlockData } from './fixtures/sepolia'; import { mainnetBlockData } from './fixtures/mainnet'; describe(`${getSystemTestBackend()} tests - getBlockTransactionCount`, () => { const provider = getSystemE2ETestProvider(); - const blockData = getSystemTestBackend() === BACKEND.SEPOLIA ? sepoliaBlockData : mainnetBlockData; - const expectedTransactionCount = getSystemTestBackend() === BACKEND.SEPOLIA ? 30 : 196; + const blockData = + getSystemTestBackend() === BACKEND.SEPOLIA ? sepoliaBlockData : mainnetBlockData; let web3: Web3; @@ -63,53 +66,35 @@ describe(`${getSystemTestBackend()} tests - getBlockTransactionCount`, () => { format: Object.values(FMT_NUMBER), }), )('getBlockTransactionCount', async ({ block, format }) => { - const result = await web3.eth.getBlockTransactionCount(blockData[block], { + let _blockData = blockData[block]; + if (block === 'blockHash' || block === 'blockNumber') { + const latestBlock = await web3.eth.getBlock('finalized'); + _blockData = + block === 'blockHash' ? (latestBlock.hash as string) : Number(latestBlock.number); + } + const result = await web3.eth.getBlockTransactionCount(_blockData, { number: format as FMT_NUMBER, bytes: FMT_BYTES.HEX, }); - - if (block === 'blockHash' || block === 'blockNumber') { - switch (format) { - case 'NUMBER_NUMBER': - // eslint-disable-next-line jest/no-conditional-expect - expect(result).toBe(expectedTransactionCount); - break; - case 'NUMBER_HEX': - // eslint-disable-next-line jest/no-conditional-expect - expect(result).toBe(toHex(expectedTransactionCount)); - break; - case 'NUMBER_STR': - // eslint-disable-next-line jest/no-conditional-expect - expect(result).toBe(`${expectedTransactionCount}`); - break; - case 'NUMBER_BIGINT': - // eslint-disable-next-line jest/no-conditional-expect - expect(result).toBe(BigInt(expectedTransactionCount)); - break; - default: - throw new Error('Unhandled format'); - } - } else { - switch (format) { - case 'NUMBER_NUMBER': - // eslint-disable-next-line jest/no-conditional-expect - expect(isNumber(result)).toBeTruthy(); - break; - case 'NUMBER_HEX': - // eslint-disable-next-line jest/no-conditional-expect - expect(isHexStrict(result)).toBeTruthy(); - break; - case 'NUMBER_STR': - // eslint-disable-next-line jest/no-conditional-expect - expect(isString(result)).toBeTruthy(); - break; - case 'NUMBER_BIGINT': - // eslint-disable-next-line jest/no-conditional-expect - expect(isBigInt(result)).toBeTruthy(); - break; - default: - throw new Error('Unhandled format'); - } + switch (format) { + case 'NUMBER_NUMBER': + // eslint-disable-next-line jest/no-conditional-expect + expect(isNumber(result)).toBeTruthy(); + break; + case 'NUMBER_HEX': + // eslint-disable-next-line jest/no-conditional-expect + expect(isHexStrict(result)).toBeTruthy(); + break; + case 'NUMBER_STR': + // eslint-disable-next-line jest/no-conditional-expect + expect(isString(result)).toBeTruthy(); + break; + case 'NUMBER_BIGINT': + // eslint-disable-next-line jest/no-conditional-expect + expect(isBigInt(result)).toBeTruthy(); + break; + default: + throw new Error('Unhandled format'); } }); }); diff --git a/packages/web3/test/e2e/get_block_uncle_count.test.ts b/packages/web3/test/e2e/get_block_uncle_count.test.ts index eb13f823585..c06f57aec85 100644 --- a/packages/web3/test/e2e/get_block_uncle_count.test.ts +++ b/packages/web3/test/e2e/get_block_uncle_count.test.ts @@ -16,49 +16,66 @@ along with web3.js. If not, see . */ import Web3 from '../../src'; import { getSystemE2ETestProvider } from './e2e_utils'; -import { closeOpenConnection, getSystemTestBackend, describeIf, BACKEND} from '../shared_fixtures/system_tests_utils'; +import { + closeOpenConnection, + getSystemTestBackend, + describeIf, + BACKEND, +} from '../shared_fixtures/system_tests_utils'; import { toAllVariants } from '../shared_fixtures/utils'; import { sepoliaBlockData } from './fixtures/sepolia'; import { mainnetBlockData } from './fixtures/mainnet'; -describeIf(getSystemTestBackend() !== 'hardhat')(`${getSystemTestBackend()} tests - getBlockUncleCount`, () => { - const provider = getSystemE2ETestProvider(); - const blockData = getSystemTestBackend() === BACKEND.SEPOLIA ? sepoliaBlockData : mainnetBlockData; +describeIf(getSystemTestBackend() !== 'hardhat')( + `${getSystemTestBackend()} tests - getBlockUncleCount`, + () => { + const provider = getSystemE2ETestProvider(); + const blockData = + getSystemTestBackend() === BACKEND.SEPOLIA ? sepoliaBlockData : mainnetBlockData; - let web3: Web3; + let web3: Web3; - beforeAll(() => { - web3 = new Web3(provider); - }); + beforeAll(() => { + web3 = new Web3(provider); + }); - afterAll(async () => { - await closeOpenConnection(web3); - }); - // eslint-disable-next-line jest/consistent-test-it - it.each( - toAllVariants<{ - block: - | 'earliest' - | 'latest' - | 'pending' - | 'finalized' - | 'safe' - | 'blockHash' - | 'blockNumber'; - }>({ - block: [ - 'earliest', - 'latest', - 'pending', - 'safe', - 'finalized', - 'blockHash', - 'blockNumber', - ], - }), - )('getBlockUncleCount', async ({ block }) => { - const result = await web3.eth.getBlockUncleCount(blockData[block]); + afterAll(async () => { + await closeOpenConnection(web3); + }); + // eslint-disable-next-line jest/consistent-test-it + it.each( + toAllVariants<{ + block: + | 'earliest' + | 'latest' + | 'pending' + | 'finalized' + | 'safe' + | 'blockHash' + | 'blockNumber'; + }>({ + block: [ + 'earliest', + 'latest', + 'pending', + 'safe', + 'finalized', + 'blockHash', + 'blockNumber', + ], + }), + )('getBlockUncleCount', async ({ block }) => { + let _blockData = blockData[block]; + if (block === 'blockHash' || block === 'blockNumber') { + const latestBlock = await web3.eth.getBlock('finalized'); + _blockData = + block === 'blockHash' + ? (latestBlock.hash as string) + : Number(latestBlock.number); + } + const result = await web3.eth.getBlockUncleCount(_blockData); - expect(result).toBe(BigInt(0)); - }); -}); + expect(result).toBe(BigInt(0)); + }); + }, +); diff --git a/packages/web3/test/e2e/get_chain_id.test.ts b/packages/web3/test/e2e/get_chain_id.test.ts index c58fe360c1b..be29c9928c7 100644 --- a/packages/web3/test/e2e/get_chain_id.test.ts +++ b/packages/web3/test/e2e/get_chain_id.test.ts @@ -18,7 +18,11 @@ import { toHex } from 'web3-utils'; import Web3, { FMT_BYTES, FMT_NUMBER } from '../../src'; import { getSystemE2ETestProvider } from './e2e_utils'; -import { closeOpenConnection, getSystemTestBackend, BACKEND } from '../shared_fixtures/system_tests_utils'; +import { + closeOpenConnection, + getSystemTestBackend, + BACKEND, +} from '../shared_fixtures/system_tests_utils'; import { toAllVariants } from '../shared_fixtures/utils'; describe(`${getSystemTestBackend()} tests - getChainId`, () => { diff --git a/packages/web3/test/e2e/get_id.test.ts b/packages/web3/test/e2e/get_id.test.ts index 191c355340b..21ff5a7e4f7 100644 --- a/packages/web3/test/e2e/get_id.test.ts +++ b/packages/web3/test/e2e/get_id.test.ts @@ -16,11 +16,16 @@ along with web3.js. If not, see . */ import Web3 from '../../src'; import { getSystemE2ETestProvider } from './e2e_utils'; -import { closeOpenConnection, getSystemTestBackend, BACKEND } from '../shared_fixtures/system_tests_utils'; +import { + closeOpenConnection, + getSystemTestBackend, + BACKEND, +} from '../shared_fixtures/system_tests_utils'; describe(`${getSystemTestBackend()} tests - getId`, () => { const provider = getSystemE2ETestProvider(); - const expectedChainId = getSystemTestBackend() === BACKEND.SEPOLIA ? BigInt(11155111) : BigInt(1); + const expectedChainId = + getSystemTestBackend() === BACKEND.SEPOLIA ? BigInt(11155111) : BigInt(1); let web3: Web3; diff --git a/packages/web3/test/e2e/get_proof.test.ts b/packages/web3/test/e2e/get_proof.test.ts index 711abf0fac3..a8c17c6558a 100644 --- a/packages/web3/test/e2e/get_proof.test.ts +++ b/packages/web3/test/e2e/get_proof.test.ts @@ -18,14 +18,19 @@ along with web3.js. If not, see . import Web3, { AccountObject } from '../../src'; import { getSystemE2ETestProvider } from './e2e_utils'; -import { closeOpenConnection, getSystemTestBackend, BACKEND } from '../shared_fixtures/system_tests_utils'; +import { + closeOpenConnection, + getSystemTestBackend, + BACKEND, +} from '../shared_fixtures/system_tests_utils'; import { toAllVariants } from '../shared_fixtures/utils'; import { mainnetBlockData, mainnetProof } from './fixtures/mainnet'; import { sepoliaBlockData, sepoliaProof } from './fixtures/sepolia'; describe(`${getSystemTestBackend()} tests - getProof`, () => { const provider = getSystemE2ETestProvider(); - const blockData = getSystemTestBackend() === BACKEND.SEPOLIA ? sepoliaBlockData : mainnetBlockData; + const blockData = + getSystemTestBackend() === BACKEND.SEPOLIA ? sepoliaBlockData : mainnetBlockData; const expectedProof = getSystemTestBackend() === BACKEND.SEPOLIA ? sepoliaProof : mainnetProof; let web3: Web3; @@ -68,8 +73,7 @@ describe(`${getSystemTestBackend()} tests - getProof`, () => { if (block === 'blockHash' || block === 'blockNumber') { expect(result).toEqual(expectedProof); - } - else if(block === 'pending') { + } else if (block === 'pending') { expect(result).toMatchObject({ balance: expect.any(BigInt), codeHash: expect.any(String), @@ -77,8 +81,7 @@ describe(`${getSystemTestBackend()} tests - getProof`, () => { storageHash: expect.any(String), storageProof: expect.any(Array), }); - } - else { + } else { expect(result).toMatchObject({ accountProof: expect.any(Array), balance: expect.any(BigInt), diff --git a/packages/web3/test/e2e/get_transaction_count.test.ts b/packages/web3/test/e2e/get_transaction_count.test.ts index 7f679ca32c4..89017756181 100644 --- a/packages/web3/test/e2e/get_transaction_count.test.ts +++ b/packages/web3/test/e2e/get_transaction_count.test.ts @@ -16,14 +16,19 @@ along with web3.js. If not, see . */ import Web3 from '../../src'; import { getSystemE2ETestProvider, getE2ETestAccountAddress } from './e2e_utils'; -import { closeOpenConnection, getSystemTestBackend, BACKEND } from '../shared_fixtures/system_tests_utils'; +import { + closeOpenConnection, + getSystemTestBackend, + BACKEND, +} from '../shared_fixtures/system_tests_utils'; import { toAllVariants } from '../shared_fixtures/utils'; import { sepoliaBlockData } from './fixtures/sepolia'; import { mainnetBlockData } from './fixtures/mainnet'; describe(`${getSystemTestBackend()} tests - getTransactionCount`, () => { const provider = getSystemE2ETestProvider(); - const blockData = getSystemTestBackend() === BACKEND.SEPOLIA ? sepoliaBlockData : mainnetBlockData; + const blockData = + getSystemTestBackend() === BACKEND.SEPOLIA ? sepoliaBlockData : mainnetBlockData; let web3: Web3; @@ -63,7 +68,8 @@ describe(`${getSystemTestBackend()} tests - getTransactionCount`, () => { ); if (block === 'blockHash' || block === 'blockNumber') { - const expectedTxCount = getSystemTestBackend() === BACKEND.SEPOLIA ? BigInt(1) : BigInt(11); + const expectedTxCount = + getSystemTestBackend() === BACKEND.SEPOLIA ? BigInt(1) : BigInt(11); // eslint-disable-next-line jest/no-conditional-expect expect(result).toBe(expectedTxCount); } else { diff --git a/packages/web3/test/e2e/get_transaction_from_block.test.ts b/packages/web3/test/e2e/get_transaction_from_block.test.ts index 20fd48b5f4e..7d5c434429c 100644 --- a/packages/web3/test/e2e/get_transaction_from_block.test.ts +++ b/packages/web3/test/e2e/get_transaction_from_block.test.ts @@ -20,15 +20,19 @@ import { Numbers, TransactionInfo } from 'web3-types'; import Web3 from '../../src'; import { getSystemE2ETestProvider } from './e2e_utils'; -import { closeOpenConnection, getSystemTestBackend, BACKEND } from '../shared_fixtures/system_tests_utils'; +import { + closeOpenConnection, + getSystemTestBackend, + BACKEND, +} from '../shared_fixtures/system_tests_utils'; import { toAllVariants } from '../shared_fixtures/utils'; import { sepoliaBlockData, sepoliaTransactionFromBlock } from './fixtures/sepolia'; import { mainnetBlockData, mainnetTransactionFromBlock } from './fixtures/mainnet'; describe(`${getSystemTestBackend()} tests - getTransactionFromBlock`, () => { const provider = getSystemE2ETestProvider(); - const blockData = getSystemTestBackend() === BACKEND.SEPOLIA ? sepoliaBlockData : mainnetBlockData; - + const blockData = + getSystemTestBackend() === BACKEND.SEPOLIA ? sepoliaBlockData : mainnetBlockData; let web3: Web3; beforeAll(() => { diff --git a/packages/web3/test/e2e/get_uncle.test.ts b/packages/web3/test/e2e/get_uncle.test.ts index 586026b82a7..0481706c4a5 100644 --- a/packages/web3/test/e2e/get_uncle.test.ts +++ b/packages/web3/test/e2e/get_uncle.test.ts @@ -18,14 +18,19 @@ import { Numbers } from 'web3-types'; import Web3 from '../../src'; import { getSystemE2ETestProvider } from './e2e_utils'; -import { closeOpenConnection, getSystemTestBackend, BACKEND } from '../shared_fixtures/system_tests_utils'; +import { + closeOpenConnection, + getSystemTestBackend, + BACKEND, +} from '../shared_fixtures/system_tests_utils'; import { toAllVariants } from '../shared_fixtures/utils'; import { mainnetBlockData } from './fixtures/mainnet'; import { sepoliaBlockData } from './fixtures/sepolia'; describe(`${getSystemTestBackend()} tests - getUncle`, () => { const provider = getSystemE2ETestProvider(); - const blockData = getSystemTestBackend() === BACKEND.SEPOLIA ? sepoliaBlockData : mainnetBlockData; + const blockData = + getSystemTestBackend() === BACKEND.SEPOLIA ? sepoliaBlockData : mainnetBlockData; let web3: Web3; @@ -39,25 +44,10 @@ describe(`${getSystemTestBackend()} tests - getUncle`, () => { it.each( toAllVariants<{ - block: - | 'earliest' - | 'latest' - | 'pending' - | 'finalized' - | 'safe' - | 'blockHash' - | 'blockNumber'; + block: 'earliest' | 'latest' | 'pending' | 'finalized' | 'safe'; uncleIndex: Numbers; }>({ - block: [ - 'earliest', - 'latest', - 'pending', - 'safe', - 'finalized', - 'blockHash', - 'blockNumber', - ], + block: ['earliest', 'latest', 'pending', 'safe', 'finalized'], uncleIndex: ['0x1', '1', 1, BigInt(1)], }), )('getUncle', async ({ block, uncleIndex }) => { diff --git a/packages/web3/test/e2e/mainnet/get_code.test.ts b/packages/web3/test/e2e/mainnet/get_code.test.ts index 0bcb6026510..df2ae77d046 100644 --- a/packages/web3/test/e2e/mainnet/get_code.test.ts +++ b/packages/web3/test/e2e/mainnet/get_code.test.ts @@ -14,7 +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 { hexToBytes } from 'web3-utils'; +import { hexToBytes, toHex } from 'web3-utils'; import Web3, { FMT_BYTES, FMT_NUMBER } from '../../../src'; import { @@ -62,7 +62,13 @@ describe(`${getSystemTestBackend()} tests - getCode`, () => { format: Object.values(FMT_BYTES), }), )('should getCode for deployed contract', async ({ block, format }) => { - const result = await web3.eth.getCode(getE2ETestContractAddress(), blockData[block], { + let _blockData = blockData[block]; + if (block === 'blockHash' || block === 'blockNumber') { + const latestBlock = await web3.eth.getBlock('finalized'); + _blockData = + block === 'blockHash' ? (latestBlock.hash as string) : toHex(latestBlock.number); + } + const result = await web3.eth.getCode(getE2ETestContractAddress(), _blockData, { number: FMT_NUMBER.HEX, bytes: format as FMT_BYTES, }); diff --git a/packages/web3/test/e2e/mainnet/get_storage_at.test.ts b/packages/web3/test/e2e/mainnet/get_storage_at.test.ts index 05512d99ec4..7db7017fb1d 100644 --- a/packages/web3/test/e2e/mainnet/get_storage_at.test.ts +++ b/packages/web3/test/e2e/mainnet/get_storage_at.test.ts @@ -60,10 +60,18 @@ describe(`${getSystemTestBackend()} tests - getStorageAt`, () => { ], }), )('getStorageAt', async ({ storageSlot, block }) => { + let blockData = mainnetBlockData[block]; + if (block === 'blockHash' || block === 'blockNumber') { + const blockNumber = await web3.eth.getBlockNumber(); + blockData = Number(blockNumber); + if (block === 'blockHash') { + blockData = (await web3.eth.getBlock(blockNumber)).hash as string; + } + } const result = await web3.eth.getStorageAt( getE2ETestContractAddress(), storageSlot, - mainnetBlockData[block], + blockData, ); if (mainnetBlockData[block] === 'earliest') { @@ -72,7 +80,7 @@ describe(`${getSystemTestBackend()} tests - getStorageAt`, () => { } else if (block === 'blockHash' || block === 'blockNumber') { // eslint-disable-next-line jest/no-conditional-expect expect(result).toBe( - '0x000000000000000000000000000000000000000000000000007d5a864f06b2d5', + '0x00000000000000000000000000000000000000000000000000b8b61e3be91403', ); } else { // eslint-disable-next-line jest/no-conditional-expect diff --git a/packages/web3/test/e2e/sepolia/get_code.test.ts b/packages/web3/test/e2e/sepolia/get_code.test.ts index 43373feb180..c42bd183502 100644 --- a/packages/web3/test/e2e/sepolia/get_code.test.ts +++ b/packages/web3/test/e2e/sepolia/get_code.test.ts @@ -14,8 +14,8 @@ 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 { hexToBytes } from 'web3-utils'; - +import { hexToBytes, toHex } from 'web3-utils'; +import { BlockNumberOrTag } from 'web3-types'; import Web3, { FMT_BYTES, FMT_NUMBER } from '../../../src'; import { closeOpenConnection, @@ -49,14 +49,16 @@ describe(`${getSystemTestBackend()} tests - getCode`, () => { format: Object.values(FMT_BYTES), }), )('should getCode for deployed contract', async ({ block, format }) => { - const result = await web3.eth.getCode( - getE2ETestContractAddress(), - sepoliaBlockData[block], - { - number: FMT_NUMBER.HEX, - bytes: format as FMT_BYTES, - }, - ); + let blockData = sepoliaBlockData[block] as BlockNumberOrTag; + if (block === 'blockHash' || block === 'blockNumber') { + const latestBlock = await web3.eth.getBlock('finalized'); + blockData = + block === 'blockHash' ? (latestBlock.hash as string) : toHex(latestBlock.number); + } + const result = await web3.eth.getCode(getE2ETestContractAddress(), blockData, { + number: FMT_NUMBER.HEX, + bytes: format as FMT_BYTES, + }); switch (format) { case 'BYTES_HEX': diff --git a/packages/web3/test/e2e/sepolia/get_storage_at.test.ts b/packages/web3/test/e2e/sepolia/get_storage_at.test.ts index 7702da89ffb..a9f8e0ddf68 100644 --- a/packages/web3/test/e2e/sepolia/get_storage_at.test.ts +++ b/packages/web3/test/e2e/sepolia/get_storage_at.test.ts @@ -64,12 +64,20 @@ describe(`${getSystemTestBackend()} tests - getStorageAt`, () => { ], }), )('getStorageAt', async ({ storageSlot, block }) => { + let blockData = sepoliaBlockData[block]; + if (block === 'blockHash' || block === 'blockNumber') { + const blockNumber = await web3.eth.getBlockNumber(); + blockData = Number(blockNumber); + if (block === 'blockHash') { + blockData = (await web3.eth.getBlock(blockNumber)).hash as string; + } + } + const result = await web3.eth.getStorageAt( getE2ETestContractAddress(), storageSlot, - sepoliaBlockData[block], + blockData, ); - if (sepoliaBlockData[block] === 'earliest') { // Nethermind returns 0x while Geth returns 0x0000000000000000000000000000000000000000000000000000000000000000 // eslint-disable-next-line jest/no-conditional-expect From 270680596db7e8c2e0ee09148a042233a415c106 Mon Sep 17 00:00:00 2001 From: Oleksii Kosynskyi Date: Fri, 2 Aug 2024 17:31:52 +0300 Subject: [PATCH 129/186] Zk sync plugin related changes (#7174) * Update account.ts * Update CHANGELOG.md * changelog * update * change changelog * update --------- Co-authored-by: luu-alex <98a.lexluu@gmail.com> Co-authored-by: Alex --- CHANGELOG.md | 8 ++++- packages/web3-eth-accounts/CHANGELOG.md | 5 ++- packages/web3-eth-accounts/src/account.ts | 41 ++++++++++++++++------- 3 files changed, 40 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25645330a25..1f9695c527f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2648,4 +2648,10 @@ If there are any bugs, improvements, optimizations or any new feature proposal f - Remove redundant constructor of contractBuilder (#7150) -## [Unreleased] \ No newline at end of file +## [Unreleased] + +### Added + +#### web3-eth-accounts + +- Added public function `signMessageWithPrivateKey` (#7174) diff --git a/packages/web3-eth-accounts/CHANGELOG.md b/packages/web3-eth-accounts/CHANGELOG.md index 2b5d1c1ca6a..b28e2c9b047 100644 --- a/packages/web3-eth-accounts/CHANGELOG.md +++ b/packages/web3-eth-accounts/CHANGELOG.md @@ -168,4 +168,7 @@ Documentation: - baseTransaction method updated (#7095) -## [Unreleased] \ No newline at end of file +## [Unreleased] +### Added + +- Added public function `signMessageWithPrivateKey` (#7174) diff --git a/packages/web3-eth-accounts/src/account.ts b/packages/web3-eth-accounts/src/account.ts index a2d1fffe191..ac8e0adcfc6 100644 --- a/packages/web3-eth-accounts/src/account.ts +++ b/packages/web3-eth-accounts/src/account.ts @@ -170,6 +170,29 @@ export const hashMessage = (message: string): string => { return sha3Raw(ethMessage); // using keccak in web3-utils.sha3Raw instead of SHA3 (NIST Standard) as both are different }; +/** + * Takes a hash of a message and a private key, signs the message using the SECP256k1 elliptic curve algorithm, and returns the signature components. + * @param hash - The hash of the message to be signed, represented as a hexadecimal string. + * @param privateKey - The private key used to sign the message, represented as a byte array. + * @returns - The signature Object containing the message, messageHash, signature r, s, v + */ +export const signMessageWithPrivateKey = (hash: HexString, privateKey: Bytes): SignResult => { + const privateKeyUint8Array = parseAndValidatePrivateKey(privateKey); + + const signature = secp256k1.sign(hash.substring(2), privateKeyUint8Array); + const signatureBytes = signature.toCompactRawBytes(); + const r = signature.r.toString(16).padStart(64, '0'); + const s = signature.s.toString(16).padStart(64, '0'); + const v = signature.recovery! + 27; + + return { + messageHash: hash, + v: numberToHex(v), + r: `0x${r}`, + s: `0x${s}`, + signature: `${bytesToHex(signatureBytes)}${v.toString(16)}`, + }; +}; /** * Signs arbitrary data with a given private key. * :::info @@ -193,23 +216,17 @@ export const hashMessage = (message: string): string => { * ``` */ export const sign = (data: string, privateKey: Bytes): SignResult => { - const privateKeyUint8Array = parseAndValidatePrivateKey(privateKey); - const hash = hashMessage(data); - const signature = secp256k1.sign(hash.substring(2), privateKeyUint8Array); - const signatureBytes = signature.toCompactRawBytes(); - const r = signature.r.toString(16).padStart(64, '0'); - const s = signature.s.toString(16).padStart(64, '0'); - const v = signature.recovery! + 27; + const { messageHash, v, r, s, signature } = signMessageWithPrivateKey(hash, privateKey); return { message: data, - messageHash: hash, - v: numberToHex(v), - r: `0x${r}`, - s: `0x${s}`, - signature: `${bytesToHex(signatureBytes)}${v.toString(16)}`, + messageHash, + v, + r, + s, + signature, }; }; From 5080e80fe3e55494b2871e7906670807b086383b Mon Sep 17 00:00:00 2001 From: Junaid <86780488+jdevcs@users.noreply.github.com> Date: Fri, 2 Aug 2024 17:29:46 +0200 Subject: [PATCH 130/186] 4x tests updates (#7162) * updated config and closeOpenConnection in eth * no default to http and close open con * unit test using local provider instead of default in utils * lint fix * bug fix of maxListenersWarningThreshold * fixes in defaults and sys test utils * lint fix * tests update * timeout chenged for contract tests * DEFAULT_SYSTEM_PROVIDER revert * cypress timout change * reusing waitForCondition * revert tests fix * watch subscription transaction fix * waitForCondition * TransactionBlockTimeoutError tests updates * updates * update * unit test fix * changelog update --- packages/web3-core/CHANGELOG.md | 6 +- packages/web3-core/src/web3_config.ts | 8 + .../test/integration/setup.js | 2 +- .../test/unit/contract.test.ts | 12 +- packages/web3-eth/package.json | 2 +- .../test/integration/defaults.test.ts | 175 ++++++++++-------- .../defaults.transactionBlockTimeout.test.ts | 116 ++++++------ .../integration/get_revert_reason.test.ts | 7 +- .../integration/watch_transaction.test.ts | 15 +- .../web3_eth/send_transaction.test.ts | 6 + scripts/system_tests_utils.ts | 117 +++++++----- templates/cypress.config.js | 1 + 12 files changed, 277 insertions(+), 190 deletions(-) diff --git a/packages/web3-core/CHANGELOG.md b/packages/web3-core/CHANGELOG.md index 67ef64ece5b..8f61b018479 100644 --- a/packages/web3-core/CHANGELOG.md +++ b/packages/web3-core/CHANGELOG.md @@ -227,4 +227,8 @@ Documentation: - Now when existing packages are added in web3, will be avalible for plugins via context. (#7088) -## [Unreleased] \ No newline at end of file +## [Unreleased] + +### Fixed + +- `setConfig()` fix for `setMaxListenerWarningThreshold` fix (#5079) diff --git a/packages/web3-core/src/web3_config.ts b/packages/web3-core/src/web3_config.ts index 3c335292c4a..03e478e9ecd 100644 --- a/packages/web3-core/src/web3_config.ts +++ b/packages/web3-core/src/web3_config.ts @@ -114,6 +114,14 @@ export abstract class Web3Config const keys = Object.keys(options) as (keyof Web3ConfigOptions)[]; for (const key of keys) { this._triggerConfigChange(key, options[key]); + + if(!isNullish(options[key]) && + typeof options[key] === 'number' && + key === 'maxListenersWarningThreshold' ) + { + // additionally set in event emitter + this.setMaxListenerWarningThreshold(Number(options[key])); + } } Object.assign(this.config, options); } diff --git a/packages/web3-eth-contract/test/integration/setup.js b/packages/web3-eth-contract/test/integration/setup.js index 6170e9ca349..26ba888e0cf 100644 --- a/packages/web3-eth-contract/test/integration/setup.js +++ b/packages/web3-eth-contract/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 = String(process.env.WEB3_SYSTEM_TEST_PROVIDER).includes('ipc') ? 35000 : 15000; +const jestTimeout = String(process.env.WEB3_SYSTEM_TEST_PROVIDER).includes('ipc') ? 35000 : 25000; jest.setTimeout(jestTimeout); diff --git a/packages/web3-eth-contract/test/unit/contract.test.ts b/packages/web3-eth-contract/test/unit/contract.test.ts index 449280c41a7..6ae5f055904 100644 --- a/packages/web3-eth-contract/test/unit/contract.test.ts +++ b/packages/web3-eth-contract/test/unit/contract.test.ts @@ -38,7 +38,6 @@ import { GreeterWithOverloadingBytecode, } from '../shared_fixtures/build/GreeterWithOverloading'; import { AllGetPastEventsData, getLogsData, getPastEventsData } from '../fixtures/unitTestFixtures'; -import { getSystemTestProvider } from '../fixtures/system_test_utils'; import { erc721Abi } from '../fixtures/erc721'; import { ERC20TokenAbi } from '../shared_fixtures/build/ERC20Token'; import { processAsync } from '../shared_fixtures/utils'; @@ -150,7 +149,7 @@ describe('Contract', () => { }); it('should set the provider, from options, upon instantiation', () => { - const provider = getSystemTestProvider(); + const provider = "http://127.0.0.1:4545"; const contract = new Contract([], '', { provider, }); @@ -162,7 +161,7 @@ describe('Contract', () => { }); it('should set the provider, from context, upon instantiation', () => { - const provider = getSystemTestProvider(); + const provider = "http://127.0.0.1:4545"; const contract = new Contract( [], '', @@ -816,9 +815,9 @@ describe('Contract', () => { '0x00000000219ab540356cBB839Cbe05303d7705Fa', { gas: '0x97254' }, ); - + contract.maxListenersWarningThreshold = 1000; + const clonnedContract = contract.clone(); - expect(stringify(contract)).toStrictEqual(stringify(clonnedContract)); contract.options.jsonInterface = GreeterAbi; @@ -826,7 +825,8 @@ describe('Contract', () => { it('should clone new contract', () => { const contract = new Contract(sampleStorageContractABI); - + contract.maxListenersWarningThreshold = 1000; + const clonnedContract = contract.clone(); expect(stringify(contract)).toStrictEqual(stringify(clonnedContract)); }); diff --git a/packages/web3-eth/package.json b/packages/web3-eth/package.json index 75b35059356..3f18fcd83d5 100644 --- a/packages/web3-eth/package.json +++ b/packages/web3-eth/package.json @@ -40,7 +40,7 @@ "test:e2e:sepolia": "jest --config=./test/e2e/jest.config.js --forceExit", "test:watch": "npm test -- --watch", "test:unit": "jest --config=./test/unit/jest.config.js", - "test:integration": "jest --config=./test/integration/jest.config.js --runInBand --forceExit", + "test:integration": "jest --config=./test/integration/jest.config.js --runInBand", "test:coverage:integration": "jest --config=./test/integration/jest.config.js --runInBand --forceExit --coverage=true --coverage-reporters=text", "test:e2e:electron": "npx cypress run --headless --browser electron", "test:e2e:chrome": "npx cypress run --headless --browser chrome", diff --git a/packages/web3-eth/test/integration/defaults.test.ts b/packages/web3-eth/test/integration/defaults.test.ts index a9651fa20e3..351152158b4 100644 --- a/packages/web3-eth/test/integration/defaults.test.ts +++ b/packages/web3-eth/test/integration/defaults.test.ts @@ -41,6 +41,7 @@ import { getSystemTestProvider, isIpc, sendFewSampleTxs, + waitForCondition } from '../fixtures/system_test_utils'; import { @@ -51,11 +52,10 @@ import { import { BasicAbi, BasicBytecode } from '../shared_fixtures/build/Basic'; import { MsgSenderAbi, MsgSenderBytecode } from '../shared_fixtures/build/MsgSender'; import { getTransactionGasPricing } from '../../src/utils/get_transaction_gas_pricing'; -import { Resolve, sendFewTxes } from './helper'; +import { sendFewTxes } from './helper'; describe('defaults', () => { let web3Eth: Web3Eth; - let eth2: Web3Eth; let clientUrl: string | SupportedProviders; let contract: Contract; let deployOptions: Record; @@ -76,10 +76,8 @@ describe('defaults', () => { afterEach(async () => { await closeOpenConnection(web3Eth); - await closeOpenConnection(eth2); + await closeOpenConnection(contract); }); - - describe('defaults', () => { it('defaultAccount', async () => { const tempAcc2 = await createTempAccount(); const tempAcc3 = await createTempAccount(); @@ -102,7 +100,7 @@ describe('defaults', () => { expect(web3Eth.defaultAccount).toBe(tempAcc.address); // set by create new instance - eth2 = new Web3Eth({ + const eth2 = new Web3Eth({ config: { defaultAccount: tempAcc3.address, }, @@ -152,6 +150,8 @@ describe('defaults', () => { expect((fromPass2 as unknown as string).toLowerCase()).toBe( tempAcc2.address.toLowerCase(), ); + await closeOpenConnection(eth2); + await closeOpenConnection(contractMsgFrom); }); it('handleRevert', () => { /* @@ -174,7 +174,7 @@ describe('defaults', () => { expect(web3Eth.handleRevert).toBe(true); // set by create new instance - eth2 = new Web3Eth({ + const eth2 = new Web3Eth({ config: { handleRevert: true, }, @@ -203,7 +203,7 @@ describe('defaults', () => { expect(web3Eth.defaultBlock).toBe('earliest'); // set by create new instance - eth2 = new Web3Eth({ + const eth2 = new Web3Eth({ provider: web3Eth.provider, config: { defaultBlock: 'earliest', @@ -266,8 +266,10 @@ describe('defaults', () => { expect(Number(hexToNumber(storageLatest))).toBe(10); expect(transactionCountLatest).toBe(BigInt(1)); expect(Number(balanceLatest)).toBeGreaterThan(0); + await closeOpenConnection(eth2); + await closeOpenConnection(contractDeployed); }); - it('transactionSendTimeout', () => { + it('transactionSendTimeout', async () => { // default expect(web3Eth.transactionSendTimeout).toBe(750 * 1000); @@ -278,13 +280,14 @@ describe('defaults', () => { expect(web3Eth.transactionSendTimeout).toBe(1); // set by create new instance - eth2 = new Web3Eth({ + const eth2 = new Web3Eth({ provider: web3Eth.provider, config: { transactionSendTimeout: 120, }, }); expect(eth2.transactionSendTimeout).toBe(120); + await closeOpenConnection(eth2); }); it('transactionBlockTimeout', () => { // default @@ -297,14 +300,14 @@ describe('defaults', () => { expect(web3Eth.transactionBlockTimeout).toBe(1); // set by create new instance - eth2 = new Web3Eth({ + const eth2 = new Web3Eth({ config: { transactionBlockTimeout: 120, }, }); expect(eth2.transactionBlockTimeout).toBe(120); }); - it('transactionConfirmationBlocks', () => { + it('transactionConfirmationBlocks default change should work', async () => { // default // eslint-disable-next-line jest/no-standalone-expect expect(web3Eth.transactionConfirmationBlocks).toBe(24); @@ -317,23 +320,28 @@ describe('defaults', () => { expect(web3Eth.transactionConfirmationBlocks).toBe(3); // set by create new instance - eth2 = new Web3Eth({ + const eth2 = new Web3Eth({ config: { transactionConfirmationBlocks: 4, }, }); // eslint-disable-next-line jest/no-standalone-expect expect(eth2.transactionConfirmationBlocks).toBe(4); + }); + it('transactionConfirmationBlocks implementation', async () => { const tempAcc2 = await createTempAccount(); const waitConfirmations = 1; - const eth = new Web3Eth(web3Eth.provider); + const eth = new Web3Eth(getSystemTestProvider()); eth.setConfig({ transactionConfirmationBlocks: waitConfirmations }); - + const from = tempAcc.address; const to = tempAcc2.address; const value = `0x1`; + + let confirmationCount = 0; + const sentTx: Web3PromiEvent< TransactionReceipt, SendTransactionEvents @@ -341,35 +349,29 @@ describe('defaults', () => { to, value, from, + }).on('confirmation', (_data) => { + confirmationCount += 1; + if (confirmationCount >= waitConfirmations) { + sentTx.removeAllListeners(); // Clean up listeners + } }); - const receiptPromise = new Promise((resolve: Resolve) => { - // Tx promise is handled separately - // eslint-disable-next-line no-void - void sentTx.on('receipt', (params: TransactionReceipt) => { - expect(Number(params.status)).toBe(1); - resolve(); - }); - }); - let shouldBe = 1; - const confirmationPromise = new Promise((resolve: Resolve) => { - // Tx promise is handled separately - // eslint-disable-next-line no-void - void sentTx.on('confirmation', ({ confirmations }) => { - expect(Number(confirmations)).toBeGreaterThanOrEqual(shouldBe); - shouldBe += 1; - if (shouldBe > waitConfirmations) { - resolve(); - } - }); - }); - await sentTx; - await receiptPromise; - await sendFewSampleTxs(isIpc ? 2 * waitConfirmations : waitConfirmations); - await confirmationPromise; - await closeOpenConnection(eth); + const receipt = await sentTx; + expect(Number(receipt.status)).toBe(1); + + // Optionally send a few sample transactions + await sendFewSampleTxs(isIpc ? 5 * waitConfirmations : 2 * waitConfirmations); + + expect(confirmationCount).toBe(waitConfirmations); + + await waitForCondition( + () => confirmationCount >= waitConfirmations, + async () => { await closeOpenConnection(eth)}, + 10, + 5000); }); - it('transactionPollingInterval and transactionPollingTimeout', () => { + + it('transactionPollingInterval and transactionPollingTimeout', async () => { // default expect(web3Eth.transactionPollingInterval).toBe(1000); expect(web3Eth.transactionPollingTimeout).toBe(750 * 1000); @@ -383,7 +385,7 @@ describe('defaults', () => { expect(web3Eth.transactionPollingTimeout).toBe(10); // set by create new instance - eth2 = new Web3Eth({ + const eth2 = new Web3Eth({ config: { transactionPollingInterval: 400, transactionPollingTimeout: 10, @@ -451,7 +453,7 @@ describe('defaults', () => { expect(web3Eth.transactionConfirmationPollingInterval).toBe(10); // set by create new instance - eth2 = new Web3Eth({ + const eth2 = new Web3Eth({ config: { transactionReceiptPollingInterval: 400, transactionConfirmationPollingInterval: 10, @@ -471,7 +473,7 @@ describe('defaults', () => { expect(web3Eth.blockHeaderTimeout).toBe(3); // set by create new instance - eth2 = new Web3Eth({ + const eth2 = new Web3Eth({ config: { blockHeaderTimeout: 4, }, @@ -497,7 +499,7 @@ describe('defaults', () => { ); // set by create new instance - eth2 = new Web3Eth({ + const eth2 = new Web3Eth({ config: { enableExperimentalFeatures: { useSubscriptionWhenCheckingBlockTimeout: true, @@ -524,7 +526,7 @@ describe('defaults', () => { expect(web3Eth.enableExperimentalFeatures.useRpcCallSpecification).toBe(true); // set by create new instance - eth2 = new Web3Eth({ + const eth2 = new Web3Eth({ config: { enableExperimentalFeatures: { useSubscriptionWhenCheckingBlockTimeout: false, @@ -533,6 +535,7 @@ describe('defaults', () => { }, }); expect(eth2.enableExperimentalFeatures.useRpcCallSpecification).toBe(true); + }); it('should fallback to polling if provider support `on` but `newBlockHeaders` does not arrive in `blockHeaderTimeout` seconds', async () => { @@ -572,6 +575,7 @@ describe('defaults', () => { value, }); + let confirmationCount = 0; const confirmationPromise = new Promise((resolve: (status: bigint) => void) => { // Tx promise is handled separately // eslint-disable-next-line no-void @@ -584,45 +588,47 @@ describe('defaults', () => { confirmations: bigint; receipt: { status: bigint }; }) => { + confirmationCount = Number(confirmations); // Being able to get 2 confirmations means the polling for new blocks works if (confirmations >= 2) { sentTx.removeAllListeners(); resolve(status); } else { - // Send a transaction to cause dev providers creating new blocks to fire the 'confirmation' event again. - await tempEth.sendTransaction({ - from, - to, - value, - }); + // Send few transaction to cause dev providers creating new blocks to fire the 'confirmation' event again. + await sendFewSampleTxs(5); } }, ); }); - await sentTx; + const receipt = await sentTx; + expect(Number(receipt.status)).toBe(1); // Ensure the promise the get the confirmations resolves with no error const status = await confirmationPromise; expect(status).toBe(BigInt(1)); - await closeOpenConnection(tempEth); + + await waitForCondition( + () => confirmationCount >= 2, + async () => { await closeOpenConnection(tempEth)}); }); + it('maxListenersWarningThreshold test default config', () => { // default expect(web3Eth.maxListenersWarningThreshold).toBe(100); }); it('maxListenersWarningThreshold set maxListeners through variable', () => { - eth2 = new Web3Eth({}); + const eth2 = new Web3Eth({}); eth2.maxListenersWarningThreshold = 3; expect(eth2.maxListenersWarningThreshold).toBe(3); expect(eth2.getMaxListeners()).toBe(3); }); it('maxListenersWarningThreshold set config', () => { - const eth = new Web3Eth({}); - eth.setConfig({ + const eth3 = new Web3Eth({}); + eth3.setConfig({ maxListenersWarningThreshold: 3, }); - expect(eth2.maxListenersWarningThreshold).toBe(3); - expect(eth2.getMaxListeners()).toBe(3); + expect(eth3.maxListenersWarningThreshold).toBe(3); + expect(eth3.getMaxListeners()).toBe(3); }); it('defaultNetworkId', async () => { // default @@ -635,7 +641,7 @@ describe('defaults', () => { expect(web3Eth.defaultNetworkId).toBe(3); // set by create new instance - eth2 = new Web3Eth({ + const eth2 = new Web3Eth({ provider: web3Eth.provider, config: { defaultNetworkId: 4, @@ -666,6 +672,8 @@ describe('defaults', () => { }); expect(resWithPassNetworkId.networkId).toBe(BigInt(5)); + + await closeOpenConnection(eth2); }); it('defaultChain', async () => { // default @@ -678,7 +686,7 @@ describe('defaults', () => { expect(web3Eth.defaultChain).toBe('ropsten'); // set by create new instance - eth2 = new Web3Eth({ + const eth2 = new Web3Eth({ provider: web3Eth.provider, config: { defaultChain: 'rinkeby', @@ -695,6 +703,7 @@ describe('defaults', () => { web3Context: eth2 as Web3Context, }); expect(res.chain).toBe('rinkeby'); + await closeOpenConnection(eth2); }); it('defaultHardfork', async () => { // default @@ -707,7 +716,7 @@ describe('defaults', () => { expect(web3Eth.defaultHardfork).toBe('dao'); // set by create new instance - eth2 = new Web3Eth({ + const eth2 = new Web3Eth({ provider: web3Eth.provider, config: { defaultHardfork: 'istanbul', @@ -732,6 +741,7 @@ describe('defaults', () => { eth2, ); expect(res.common.hardfork()).toBe('istanbul'); + await closeOpenConnection(eth2); }); it('defaultCommon', () => { // default @@ -754,13 +764,14 @@ describe('defaults', () => { expect(web3Eth.defaultCommon).toBe(common); // set by create new instance - eth2 = new Web3Eth({ + const eth2 = new Web3Eth({ config: { defaultCommon: common, }, }); expect(eth2.defaultCommon).toBe(common); }); + it('defaultTransactionType', async () => { // default expect(web3Eth.defaultTransactionType).toBe('0x2'); @@ -770,15 +781,20 @@ describe('defaults', () => { }); expect(web3Eth.defaultTransactionType).toBe('0x3'); + // revert back to default + web3Eth.setConfig({ + defaultTransactionType: '0x2', + }); + // set by create new instance - eth2 = new Web3Eth({ - provider: clientUrl, + const eth = new Web3Eth({ + provider: web3Eth.provider, config: { defaultTransactionType: '0x4444', }, }); - expect(eth2.defaultTransactionType).toBe('0x4444'); + expect(eth.defaultTransactionType).toBe('0x4444'); const res = getTransactionType( { @@ -791,7 +807,7 @@ describe('defaults', () => { chainId: '0x1', gasLimit: '0x5208', }, - eth2, + eth, ); expect(res).toBe('0x4444'); @@ -812,7 +828,7 @@ describe('defaults', () => { gasLimit: '0x5208', maxFeePerGas: '0x32', }, - eth2, + eth, ); expect(maxFeePerGasOverride).toBe('0x2'); const maxPriorityFeePerGasOverride = getTransactionType( @@ -827,7 +843,7 @@ describe('defaults', () => { gasLimit: '0x5208', maxPriorityFeePerGas: '0x32', }, - eth2, + eth, ); expect(maxPriorityFeePerGasOverride).toBe('0x2'); const hardforkOverride = getTransactionType( @@ -842,7 +858,7 @@ describe('defaults', () => { gasLimit: '0x5208', hardfork: 'london', }, - eth2, + eth, ); expect(hardforkOverride).toBe('0x2'); const commonOverride = getTransactionType( @@ -860,7 +876,7 @@ describe('defaults', () => { hardfork: 'london', }, }, - eth2, + eth, ); expect(commonOverride).toBe('0x2'); @@ -884,7 +900,7 @@ describe('defaults', () => { }, ], }, - eth2, + eth, ); expect(accessListOverride).toBe('0x1'); @@ -900,7 +916,7 @@ describe('defaults', () => { gasLimit: '0x5208', hardfork: 'berlin', }, - eth2, + eth, ); expect(hardforkBerlinOverride).toBe('0x0'); @@ -919,9 +935,10 @@ describe('defaults', () => { hardfork: 'berlin', }, }, - eth2, + eth, ); expect(commonBerlinOverride).toBe('0x0'); + await closeOpenConnection(eth); }); it('defaultMaxPriorityFeePerGas', async () => { // default @@ -933,7 +950,7 @@ describe('defaults', () => { expect(web3Eth.defaultMaxPriorityFeePerGas).toBe(numberToHex(2100000000)); // set by create new instance - eth2 = new Web3Eth({ + const eth2 = new Web3Eth({ provider: web3Eth.provider, config: { defaultMaxPriorityFeePerGas: numberToHex(1200000000), @@ -976,6 +993,7 @@ describe('defaults', () => { DEFAULT_RETURN_FORMAT, ); expect(resOverride?.maxPriorityFeePerGas).toBe(BigInt('4883362083')); + await closeOpenConnection(eth2); }); it('transactionBuilder', async () => { // default @@ -992,7 +1010,7 @@ describe('defaults', () => { expect(web3Eth.transactionBuilder).toBe(newBuilderMock); // set by create new instance - eth2 = new Web3Eth({ + const eth2 = new Web3Eth({ config: { transactionBuilder: newBuilderMock, }, @@ -1027,7 +1045,7 @@ describe('defaults', () => { expect(web3Eth.transactionTypeParser).toBe(newParserMock); // set by create new instance - eth2 = new Web3Eth({ + const eth2 = new Web3Eth({ config: { transactionTypeParser: newParserMock, }, @@ -1049,5 +1067,4 @@ describe('defaults', () => { ); expect(newParserMock).toHaveBeenCalled(); }); - }); -}); +}); \ No newline at end of file diff --git a/packages/web3-eth/test/integration/defaults.transactionBlockTimeout.test.ts b/packages/web3-eth/test/integration/defaults.transactionBlockTimeout.test.ts index fe679bb0dbe..ba7fd5f15e0 100644 --- a/packages/web3-eth/test/integration/defaults.transactionBlockTimeout.test.ts +++ b/packages/web3-eth/test/integration/defaults.transactionBlockTimeout.test.ts @@ -28,12 +28,12 @@ import { getSystemTestProvider, isSocket, itIf, - waitForOpenConnection, createLocalAccount, sendFewSampleTxs, getSystemTestBackend, describeIf, BACKEND + } from '../fixtures/system_test_utils'; const MAX_32_SIGNED_INTEGER = 2147483647; @@ -45,28 +45,72 @@ describeIf(getSystemTestBackend() !== BACKEND.HARDHAT)('defaults', () => { let clientUrl: string | SupportedProviders; let account1: Web3Account; let account2: Web3Account; + let transactionBlockTimeout: number; + let transactionSendTimeout: number; + let transactionPollingTimeout: number; + let blockHeaderTimeout: number; beforeEach(() => { clientUrl = getSystemTestProvider(); web3 = new Web3(clientUrl); + transactionBlockTimeout = web3.eth.transactionBlockTimeout; + transactionSendTimeout = web3.eth.transactionSendTimeout; + transactionPollingTimeout = web3.eth.transactionPollingTimeout; + blockHeaderTimeout = web3.eth.blockHeaderTimeout; + }); + + afterEach(async () => { + web3.eth.transactionBlockTimeout = transactionBlockTimeout; + web3.eth.transactionSendTimeout = transactionSendTimeout ; + web3.eth.transactionPollingTimeout = transactionPollingTimeout; + web3.eth.blockHeaderTimeout = blockHeaderTimeout; + await closeOpenConnection(web3); + }); + + test('should fail if transaction was not mined within `transactionBlockTimeout` blocks', async () => { + account1 = await createLocalAccount(web3); + account2 = await createLocalAccount(web3); + + const sentTx: Web3PromiEvent< + TransactionReceipt, + SendTransactionEvents + > = web3.eth.sendTransaction({ + from: account1.address, + to: account2.address, + gas, + value: '0x1', + // Give a high nonce so the transaction stuck forever. + // However, make this random to be able to run the test many times without receiving an error that indicate submitting the same transaction twice. + nonce: Number.MAX_SAFE_INTEGER, + }); + + // Some providers (mostly used for development) will make blocks only when there are new transactions + // So, send 2 transactions, one after another, because in this test `transactionBlockTimeout = 2`. + // eslint-disable-next-line no-void + await sendFewSampleTxs(2); + // Increase other timeouts so only `transactionBlockTimeout` would be reached web3.eth.transactionSendTimeout = MAX_32_SIGNED_INTEGER; web3.eth.transactionPollingTimeout = MAX_32_SIGNED_INTEGER; web3.eth.blockHeaderTimeout = MAX_32_SIGNED_INTEGER / 1000; - }); + web3.eth.transactionBlockTimeout = 2; + + await expect(sentTx).rejects.toThrow(/was not mined within [0-9]+ blocks/); + + await expect(sentTx).rejects.toThrow(TransactionBlockTimeoutError); - afterEach(async () => { - web3.eth.transactionBlockTimeout = 50; - await closeOpenConnection(web3.eth); }); - describe('defaults', () => { - it('should fail if transaction was not mined within `transactionBlockTimeout` blocks', async () => { + // The code of this test case is identical to the pervious one except for `eth.enableExperimentalFeatures = true` + // TODO: And this test case will be removed once https://github.com/web3/web3.js/issues/5521 is implemented. + itIf(isSocket)( + 'should fail if transaction was not mined within `transactionBlockTimeout` blocks - when subscription is used', + async () => { account1 = await createLocalAccount(web3); account2 = await createLocalAccount(web3); - // Setting a high `nonce` when sending a transaction, to cause the RPC call to stuck at the Node + // Setting a high `nonce` when sending a transaction, to cause the RPC call to stuck at the Node const sentTx: Web3PromiEvent< TransactionReceipt, SendTransactionEvents @@ -75,6 +119,7 @@ describeIf(getSystemTestBackend() !== BACKEND.HARDHAT)('defaults', () => { to: account2.address, gas, value: '0x1', + type: '0x1', // Give a high nonce so the transaction stuck forever. // However, make this random to be able to run the test many times without receiving an error that indicate submitting the same transaction twice. nonce: Number.MAX_SAFE_INTEGER, @@ -82,58 +127,19 @@ describeIf(getSystemTestBackend() !== BACKEND.HARDHAT)('defaults', () => { // Some providers (mostly used for development) will make blocks only when there are new transactions // So, send 2 transactions, one after another, because in this test `transactionBlockTimeout = 2`. - // eslint-disable-next-line no-void + // eslint-disable-next-line no-void, @typescript-eslint/no-unsafe-call await sendFewSampleTxs(2); - + web3.eth.transactionBlockTimeout = 2; + // using subscription to get the new blocks and fire `TransactionBlockTimeoutError` is currently supported only + // with `enableExperimentalFeatures.useSubscriptionWhenCheckingBlockTimeout` equal true. + web3.eth.enableExperimentalFeatures.useSubscriptionWhenCheckingBlockTimeout = true; + await expect(sentTx).rejects.toThrow(/was not mined within [0-9]+ blocks/); await expect(sentTx).rejects.toThrow(TransactionBlockTimeoutError); - await closeOpenConnection(web3.eth); - }); - - // The code of this test case is identical to the pervious one except for `eth.enableExperimentalFeatures = true` - // TODO: And this test case will be removed once https://github.com/web3/web3.js/issues/5521 is implemented. - itIf(isSocket)( - 'should fail if transaction was not mined within `transactionBlockTimeout` blocks - when subscription is used', - async () => { - account1 = await createLocalAccount(web3); - account2 = await createLocalAccount(web3); - await waitForOpenConnection(web3.eth); - // using subscription to get the new blocks and fire `TransactionBlockTimeoutError` is currently supported only - // with `enableExperimentalFeatures.useSubscriptionWhenCheckingBlockTimeout` equal true. - web3.eth.enableExperimentalFeatures.useSubscriptionWhenCheckingBlockTimeout = true; - - // Setting a high `nonce` when sending a transaction, to cause the RPC call to stuck at the Node - const sentTx: Web3PromiEvent< - TransactionReceipt, - SendTransactionEvents - > = web3.eth.sendTransaction({ - from: account1.address, - to: account2.address, - gas, - value: '0x1', - type: '0x1', - // Give a high nonce so the transaction stuck forever. - // However, make this random to be able to run the test many times without receiving an error that indicate submitting the same transaction twice. - nonce: Number.MAX_SAFE_INTEGER, - }); - - // Some providers (mostly used for development) will make blocks only when there are new transactions - // So, send 2 transactions, one after another, because in this test `transactionBlockTimeout = 2`. - // eslint-disable-next-line no-void, @typescript-eslint/no-unsafe-call - void sendFewSampleTxs(2); - - web3.eth.transactionBlockTimeout = 2; - - await expect(sentTx).rejects.toThrow(/was not mined within [0-9]+ blocks/); - - await expect(sentTx).rejects.toThrow(TransactionBlockTimeoutError); - - await closeOpenConnection(web3.eth); - }, - ); - }); + }, + ); }); diff --git a/packages/web3-eth/test/integration/get_revert_reason.test.ts b/packages/web3-eth/test/integration/get_revert_reason.test.ts index 5318b06400c..4180742a21b 100644 --- a/packages/web3-eth/test/integration/get_revert_reason.test.ts +++ b/packages/web3-eth/test/integration/get_revert_reason.test.ts @@ -26,7 +26,8 @@ import { createTempAccount, getSystemTestBackend, getSystemTestProvider, - BACKEND + BACKEND, + closeOpenConnection } from '../fixtures/system_test_utils'; describe('Web3Eth.getRevertReason', () => { @@ -49,6 +50,10 @@ describe('Web3Eth.getRevertReason', () => { .contractAddress as Address; }); + afterAll(async () => { + await closeOpenConnection(web3Eth); + }); + it('should return reason for a contract call', async () => { const transaction: TransactionCall = { from: tempAccount.address, diff --git a/packages/web3-eth/test/integration/watch_transaction.test.ts b/packages/web3-eth/test/integration/watch_transaction.test.ts index 4aa607c8fdd..733b64a089b 100644 --- a/packages/web3-eth/test/integration/watch_transaction.test.ts +++ b/packages/web3-eth/test/integration/watch_transaction.test.ts @@ -25,11 +25,11 @@ import { describeIf, closeOpenConnection, isSocket, - waitForOpenConnection, createLocalAccount, isIpc, sendFewSampleTxs, createAccount, + waitForCondition, } from '../fixtures/system_test_utils'; const waitConfirmations = 2; @@ -46,7 +46,6 @@ describeIf(isSocket)('watch subscription transaction', () => { web3 = new Web3(clientUrl); account1 = await createLocalAccount(web3); account2 = createAccount(); - await waitForOpenConnection(web3.eth); }); describe('wait for confirmation subscription', () => { it('subscription to heads', async () => { @@ -83,10 +82,18 @@ describeIf(isSocket)('watch subscription transaction', () => { } }); }); + await receiptPromise; await sendFewSampleTxs(isIpc ? 2 * waitConfirmations : waitConfirmations); - await confirmationPromise; - await closeOpenConnection(web3.eth); + + const resourcePromise = waitForCondition( + () => shouldBe >= waitConfirmations, + async () => { + sentTx.removeAllListeners(); + await closeOpenConnection(web3);} + ); + + await Promise.all([confirmationPromise,resourcePromise]); }); }); }); 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 9b0eda360dc..b16479d886b 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 @@ -99,6 +99,8 @@ describe('Web3Eth.sendTransaction', () => { to: '0x0000000000000000000000000000000000000000', value: BigInt(1), }); + + await closeOpenConnection(web3EthWithWallet); }); it('should make a simple value transfer - with local wallet indexed receiver', async () => { @@ -130,6 +132,8 @@ describe('Web3Eth.sendTransaction', () => { to: wallet.get(0)?.address.toLowerCase(), value: BigInt(1), }); + + await closeOpenConnection(web3EthWithWallet); }); it('should make a simple value transfer - with local wallet indexed sender and receiver', async () => { @@ -165,6 +169,8 @@ describe('Web3Eth.sendTransaction', () => { to: wallet.get(1)?.address.toLowerCase(), value: BigInt(1), }); + + await closeOpenConnection(web3EthWithWallet); }); it('should make a transaction with no value transfer', async () => { const transaction: Transaction = { diff --git a/scripts/system_tests_utils.ts b/scripts/system_tests_utils.ts index 48ea2129c06..11f9bcef717 100644 --- a/scripts/system_tests_utils.ts +++ b/scripts/system_tests_utils.ts @@ -50,16 +50,16 @@ import { Web3EthExecutionAPI, FMT_NUMBER, FMT_BYTES, + TransactionReceipt, } from 'web3-types'; // eslint-disable-next-line import/no-extraneous-dependencies import { Personal } from 'web3-eth-personal'; // eslint-disable-next-line import/no-extraneous-dependencies -import Web3 from 'web3'; +import {Web3, WebSocketProvider } from 'web3'; // eslint-disable-next-line import/no-extraneous-dependencies import { NonPayableMethodObject } from 'web3-eth-contract'; -// eslint-disable-next-line import/no-extraneous-dependencies -import HttpProvider from 'web3-providers-http'; + // eslint-disable-next-line import/no-extraneous-dependencies import { IpcProvider } from 'web3-providers-ipc'; import accountsString from './accounts.json'; @@ -83,13 +83,14 @@ export const BACKEND = { MAINNET: 'mainnet', }; -export const getSystemTestProviderUrl = (): string => +export const getSystemTestProviderUrl = (): string => getEnvVar('WEB3_SYSTEM_TEST_PROVIDER') ?? DEFAULT_SYSTEM_PROVIDER; export const getSystemTestProvider = (): | string | SupportedProviders => { const url = getSystemTestProviderUrl(); + if (url.includes('ipc')) { return new IpcProvider(url); } @@ -155,37 +156,21 @@ export const waitForOpenConnection = async ( export const closeOpenConnection = async (web3Context: Web3Context) => { if ( - !isSocket || - web3Context?.provider instanceof HttpProvider || - (web3Context?.provider?.supportsSubscriptions && - !web3Context.provider?.supportsSubscriptions()) - ) { - return; - } - // make sure we try to close the connection after it is established - if ( - web3Context?.provider && - (web3Context.provider as unknown as Web3BaseProvider).getStatus() === 'connecting' - ) { - await waitForOpenConnection(web3Context); - } - // If an error happened during closing, that is acceptable at tests, just print a 'warn'. - if (web3Context?.provider) { - (web3Context.provider as unknown as Web3BaseProvider).on('error', (err: any) => { - console.warn('error while trying to close the connection', err); - }); - } - // Wait a bit to ensure the connection does not have a pending data that - // could cause an error if written after closing the connection. - await new Promise(resolve => { - setTimeout(resolve, 500); - }); - if ( - web3Context?.provider && + web3Context?.provider && ( + web3Context?.provider instanceof WebSocketProvider || + web3Context?.provider instanceof IpcProvider + + ) && 'disconnect' in (web3Context.provider as unknown as Web3BaseProvider) ) { - (web3Context.provider as unknown as Web3BaseProvider).disconnect(1000, ''); - } + + (web3Context.provider as unknown as Web3BaseProvider).reset(); + (web3Context.provider as unknown as Web3BaseProvider).disconnect(); + + await new Promise(resolve => { + setTimeout(resolve, 1000); + }); + } }; export const createAccountProvider = (context: Web3Context) => { @@ -241,11 +226,16 @@ export const createAccountProvider = (context: Web3Context) => export const refillAccount = async (from: string, to: string, value: string | number) => { const web3Eth = new Web3Eth(DEFAULT_SYSTEM_PROVIDER); - await web3Eth.sendTransaction({ + const receipt = await web3Eth.sendTransaction({ from, to, value, }); + + if(receipt.status !== BigInt(1)) + throw new Error("refillAccount failed"); + + await closeOpenConnection(web3Eth); }; let mainAcc: string; @@ -256,6 +246,7 @@ export const createNewAccount = async (config?: { password?: string; doNotImport?: boolean; }): Promise<{ address: string; privateKey: string }> => { + const acc = config?.privateKey ? privateKeyToAccount(config?.privateKey) : _createAccount(); const clientUrl = DEFAULT_SYSTEM_PROVIDER; @@ -267,6 +258,7 @@ export const createNewAccount = async (config?: { await web3.hardhat.impersonateAccount(acc.address); // await impersonateAccount(acc.address); await web3.hardhat.setBalance(acc.address, web3.utils.toHex('100000000')); + await closeOpenConnection(web3); } else { const web3Personal = new Personal(clientUrl); if (!config?.doNotImport) { @@ -279,6 +271,7 @@ export const createNewAccount = async (config?: { } await web3Personal.unlockAccount(acc.address, config.password ?? '123456', 100000000); + await closeOpenConnection(web3Personal); } } @@ -288,17 +281,21 @@ export const createNewAccount = async (config?: { const web3 = new Web3(url); web3.registerPlugin(new HardhatPlugin()); await web3.hardhat.setBalance(acc.address, web3.utils.toHex('100000000')); + await closeOpenConnection(web3); } else { const web3Personal = new Personal(clientUrl); if (!mainAcc) { [mainAcc] = await web3Personal.getAccounts(); } await refillAccount(mainAcc, acc.address, '100000000000000000'); + await closeOpenConnection(web3Personal); } } return { address: acc.address.toLowerCase(), privateKey: acc.privateKey }; }; + + let tempAccountList: { address: string; privateKey: string }[] = []; const walletsOnWorker = 20; @@ -485,16 +482,21 @@ export const sendFewSampleTxs = async (cnt = 1) => { const web3 = new Web3(DEFAULT_SYSTEM_PROVIDER); const fromAcc = await createLocalAccount(web3); const toAcc = createAccount(); - const res = []; + const res: TransactionReceipt[]= []; for (let i = 0; i < cnt; i += 1) { + // eslint-disable-next-line no-await-in-loop + const receipt = await web3.eth.sendTransaction({ + to: toAcc.address, + value: '0x1', + from: fromAcc.address, + gas: '300000', + }); + + if(receipt.status !== BigInt(1)) + throw new Error("sendFewSampleTxs failed "); + res.push( - // eslint-disable-next-line no-await-in-loop - await web3.eth.sendTransaction({ - to: toAcc.address, - value: '0x1', - from: fromAcc.address, - gas: '300000', - }), + receipt ); } await closeOpenConnection(web3); @@ -516,3 +518,34 @@ export const mapFormatToType: { [key: string]: string } = { [FMT_BYTES.HEX]: 'string', [FMT_BYTES.UINT8ARRAY]: 'object', }; + +export const waitForCondition = async ( + conditionFunc: () => boolean, + logicFunc: () => Promise | void, + maxIterations = 10, // 10 times + duration = 8000, // check after each 8 seconds +): Promise => { + return new Promise((resolve, reject) => { + let iterations = 0; + // eslint-disable-next-line @typescript-eslint/no-misused-promises + const interval = setInterval(async () => { + try { + if (iterations > 0 && conditionFunc()) { // wait duration before first check + clearInterval(interval); + await logicFunc(); + resolve(); + } else { + iterations += 1; + if (iterations >= maxIterations) { + clearInterval(interval); + await logicFunc(); + reject(new Error('Condition not met after 10 iterations.')); + } + } + } catch (error) { + clearInterval(interval); + reject(error); + } + }, duration); + }); +}; \ No newline at end of file diff --git a/templates/cypress.config.js b/templates/cypress.config.js index 95874902d93..977e51c90db 100644 --- a/templates/cypress.config.js +++ b/templates/cypress.config.js @@ -25,6 +25,7 @@ const config = { }, specPattern: 'test/integration/**/**/*.test.ts', excludeSpecPattern: ['**/contract_defaults_extra.test.ts'], + defaultCommandTimeout: 120000 }, }; From 8b435c1eaec1557ac71da360b5fb95c94e35ca87 Mon Sep 17 00:00:00 2001 From: Myron <49134743+mmyyrroonn@users.noreply.github.com> Date: Tue, 6 Aug 2024 20:43:22 +0800 Subject: [PATCH 131/186] feat(docs): Expand web3 config guide (#7131) * add doc for `handleRevert` * add doc for defaultAccount * add doc for `defaultBlock` * add doc for transactionBlockTimeout * add doc for transactionConfirmationBlocks * add doc for transactionPollingInterval * add doc for transactionPollingTimeout * add doc for transactionReceiptPollingInterval and improve doc for transactionPollingInterval * add doc for transactionSendTimeout * add doc for transactionConfirmationPollingInterval * add doc for blockHeaderTimeout * add doc for maxListenersWarningThreshold * add doc for contractDataInputFill * add doc for defaultNetworkId * add doc for defaultHardfork, defaultChain and defaultCommon * add doc for defaultTransactionType * add doc for defaultMaxPriorityFeePerGas * refine * add doc for `handleRevert` * add doc for defaultAccount * add doc for `defaultBlock` * add doc for transactionBlockTimeout * add doc for transactionConfirmationBlocks * add doc for transactionPollingInterval * add doc for transactionPollingTimeout * add doc for transactionReceiptPollingInterval and improve doc for transactionPollingInterval * add doc for transactionSendTimeout * add doc for transactionConfirmationPollingInterval * add doc for blockHeaderTimeout * add doc for maxListenersWarningThreshold * add doc for contractDataInputFill * add doc for defaultNetworkId * add doc for defaultHardfork, defaultChain and defaultCommon * add doc for defaultTransactionType * add doc for defaultMaxPriorityFeePerGas * refine * fix semi colons * emphasize the default value and use the original default value in the code snippet * run deploy * revert * add link, fix pr comments * remove redundant global config example * Apply suggestions from code review Co-authored-by: Junaid <86780488+jdevcs@users.noreply.github.com> * resolve review comments * Apply suggestions from code review Co-authored-by: Dan Forbes * remove all example except for transactionPollingInterval, defaultReturnFormat and defaultCommon * Apply suggestions from code review Co-authored-by: Dan Forbes * Update docs/docs/guides/web3_config/index.md --------- Co-authored-by: blackmoshui Co-authored-by: Alex Co-authored-by: luu-alex <98a.lexluu@gmail.com> Co-authored-by: Junaid <86780488+jdevcs@users.noreply.github.com> Co-authored-by: Dan Forbes --- docs/docs/guides/web3_config/index.md | 263 ++++++++++++++++++++++---- packages/web3-core/src/web3_config.ts | 2 +- 2 files changed, 231 insertions(+), 34 deletions(-) diff --git a/docs/docs/guides/web3_config/index.md b/docs/docs/guides/web3_config/index.md index f6d041b6b15..42561aedcbc 100644 --- a/docs/docs/guides/web3_config/index.md +++ b/docs/docs/guides/web3_config/index.md @@ -9,25 +9,26 @@ sidebar_label: 'Web3 Config Guide' There is list of configuration params that can be set for modifying behavior of different functions in web3.js packages. Following is list of configuration options with details: -- [handleRevert]( /api/web3-core/class/Web3Config#handleRevert) -- [defaultAccount](/api/web3-core/class/Web3Config#defaultAccount) -- [defaultBlock](/api/web3-core/class/Web3Config#defaultBlock) -- [transactionBlockTimeout](/api/web3-core/class/Web3Config#transactionBlockTimeout) -- [transactionConfirmationBlocks](/api/web3-core/class/Web3Config#transactionConfirmationBlocks) -- [transactionPollingInterval](/api/web3-core/class/Web3Config#transactionPollingInterval) -- [transactionPollingTimeout](/api/web3-core/class/Web3Config#transactionPollingTimeout) -- [transactionReceiptPollingInterval](/api/web3-core/class/Web3Config#transactionReceiptPollingInterval) -- [transactionSendTimeout](/api/web3-core/class/Web3Config#transactionSendTimeout) -- [transactionConfirmationPollingInterval](/api/web3-core/class/Web3Config#transactionConfirmationPollingInterval) -- [blockHeaderTimeout](/api/web3-core/class/Web3Config#blockHeaderTimeout) -- [maxListenersWarningThreshold](/api/web3-core/class/Web3Config#maxListenersWarningThreshold) -- [contractDataInputFill](/api/web3-core/class/Web3Config#contractDataInputFill) -- [defaultNetworkId](/api/web3-core/class/Web3Config#defaultNetworkId) -- [defaultChain](/api/web3-core/class/Web3Config#defaultChain) -- [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) +- [handleRevert](/guides/web3_config/#handlerevert) +- [defaultAccount](/guides/web3_config/#defaultaccount) +- [defaultBlock](/guides/web3_config/#defaultblock) +- [transactionBlockTimeout](/guides/web3_config/#transactionblocktimeout) +- [transactionConfirmationBlocks](/guides/web3_config/#transactionconfirmationblocks) +- [transactionPollingInterval](/guides/web3_config/#transactionpollinginterval) +- [transactionPollingTimeout](/guides/web3_config/#transactionpollingtimeout) +- [transactionReceiptPollingInterval](/guides/web3_config/#transactionreceiptpollinginterval) +- [transactionSendTimeout](/guides/web3_config/#transactionsendtimeout) +- [[Deprecated] transactionConfirmationPollingInterval](/guides/web3_config/#transactionconfirmationpollinginterval) +- [blockHeaderTimeout](/guides/web3_config/#blockheadertimeout) +- [maxListenersWarningThreshold](/guides/web3_config/#maxlistenerswarningthreshold) +- [contractDataInputFill](/guides/web3_config/#contractdatainputfill) +- [defaultNetworkId](/guides/web3_config/#defaultnetworkid) +- [defaultChain](/guides/web3_config/#defaultchain) +- [defaultHardfork](/guides/web3_config/#defaulthardfork) +- [defaultCommon](/guides/web3_config/#defaultcommon) +- [defaultTransactionType](/guides/web3_config/#defaulttransactiontype) +- [defaultMaxPriorityFeePerGas](/guides/web3_config/#defaultmaxpriorityfeepergas) +- [defaultReturnFormat](/guides/web3_config/#defaultreturnformat) ## Global level Config @@ -201,31 +202,227 @@ console.log(web3.getContextObject().config) */ ``` +## Explanation of Configuration Parameters -### 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. +### [handleRevert](/api/web3-core/class/Web3Config#handleRevert) +The following methods will retrieve specific error types and error messages when `handleRevert` is set to `true`: +- [`web3.eth.sendTransaction()`](/api/web3-eth/function/sendTransaction); +- [`myContract.methods.myMethod().send()`](/libdocs/Contract#send); + +The error type will be one of the following: +- [InvalidResponseError](/api/web3-errors/class/InvalidResponseError) +- [ContractExecutionError](/api/web3-errors/class/ContractExecutionError) +- [TransactionRevertWithCustomError](/api/web3-errors/class/TransactionRevertWithCustomError) +- [TransactionRevertedWithoutReasonError](/api/web3-errors/class/TransactionRevertedWithoutReasonError) +- [TransactionRevertInstructionError](/api/web3-errors/class/TransactionRevertInstructionError) +- [TransactionPollingTimeoutError](/api/web3-errors/class/TransactionPollingTimeoutError) + +For example, the error message could be `TransactionRevertInstructionError('Returned error: invalid argument 0: json: cannot unmarshal invalid hex string into Go struct field TransactionArgs.data of type hexutil.Bytes')`. The `handleRevert` option is only supported for [`sendTransaction`](/api/web3-eth/function/sendTransaction) and not for [`sendSignedTransaction`](/api/web3-eth/function/sendSignedTransaction) for now. + +The default value of `handleRevert` is `false`. + +### [defaultAccount](/api/web3-core/class/Web3Config#defaultAccount) +The `defaultAccount` option is used as the default `from` property, if no `from` property is specified for the following methods: +- [`web3.eth.sendTransaction()`](/api/web3-eth/function/sendTransaction); +- [`web3.eth.call()`](/api/web3-eth/function/call); +- [`myContract.methods.myMethod().call()`](/libdocs/Contract#call); +- [`myContract.methods.myMethod().send()`](/libdocs/Contract#send); + +The default value of `defaultAccount` is `undefined`. + +### [defaultBlock](/api/web3-core/class/Web3Config#defaultBlock) +The following methods accept an optional `blockNumber` parameter, the `defaultBlock` option is used for these methods if no `blockNumber` parameter is provided. +- [`web3.eth.getBalance()`](/api/web3-eth/function/getBalance); +- [`web3.eth.getCode()`](/api/web3-eth/function/getCode); +- [`web3.eth.getTransactionCount()`](/api/web3-eth/function/getTransactionCount); +- [`web3.eth.getStorageAt()`](/api/web3-eth/function/getStorageAt); +- [`web3.eth.call()`](/api/web3-eth/function/call); +- [`myContract.methods.myMethod().call()`](/libdocs/Contract#call); + +If a `blockNumber` parameter is provided to one of the above function calls, it will override this option. + +The default value of `defaultBlock` is "latest". + +#### All available choices for defaultBlock: ```ts -import { Web3, FMT_NUMBER, FMT_BYTES } from 'web3'; +web3.defaultBlock = 20167235; // A block number +web3.defaultBlock = "earliest"; // The genesis block +web3.defaultBlock = "latest"; // The latest block (current head of the blockchain) +web3.defaultBlock = "pending"; // The block pending to be mined (including pending transactions) +web3.defaultBlock = "finalized"; // (For POS networks) The finalized block is one which has been accepted as canonical by greater than 2/3 of validators +web3.defaultBlock = "safe"; // (For POS networks) The safe head block is one which under normal network conditions, is expected to be included in the canonical chain. Under normal network conditions the safe head and the actual tip of the chain will be equivalent (with safe head trailing only by a few seconds). Safe heads will be less likely to be reorged than the proof of work network`s latest blocks. +``` -web3.defaultReturnFormat = { - number: FMT_NUMBER.BIGINT, - bytes: FMT_BYTES.HEX, +### [transactionBlockTimeout](/api/web3-core/class/Web3Config#transactionBlockTimeout) + This option defines the number of new blocks to wait for the **first confirmation**, otherwise the [`PromiEvent`](/api/web3/class/Web3PromiEvent) rejects with a timeout error. + +The default value of `transactionBlockTimeout` is 50. + +### [transactionConfirmationBlocks](/api/web3-core/class/Web3Config#transactionConfirmationBlocks) +This defines the number of blocks required for a transaction to be considered confirmed. Different chains have varying security considerations and requirements for confirmation block numbers. + +The default value of `transactionConfirmationBlocks` is 24. + +### [transactionPollingInterval](/api/web3-core/class/Web3Config#transactionPollingInterval) +This option defines the number of seconds between Web3 calls for a receipt which confirms that a transaction was mined by the network. Modifying this value can reduce the wait time for confirmations or decrease the number of network requests. Setting the `transactionPollingInterval` would also set [`transactionReceiptPollingInterval`](/guides/web3_config/#transactionreceiptpollinginterval) and [`transactionConfirmationPollingInterval`](/guides/web3_config/#transactionconfirmationpollinginterval) to the same value. + +The default value of `transactionPollingInterval` is 1000 ms. + +```ts +import { Web3 } from 'web3'; + +const web3 = new Web3('http://127.0.0.1:7545'); + +web3.transactionPollingInterval = 1000; // 1000 ms = 1 s + +console.log(web3.getContextObject().config); +/* ↳ + ... + transactionPollingInterval: 1000, + transactionPollingTimeout: 750000, + transactionReceiptPollingInterval: 1000, + transactionSendTimeout: 750000, + transactionConfirmationPollingInterval: 1000, + ... +*/ +``` + +### [transactionPollingTimeout](/api/web3-core/class/Web3Config#transactionPollingTimeout) +This option defines the number of seconds Web3 will wait for a receipt which confirms that a transaction was mined by the network. It can be set based on the average transaction confirmation time on the network. Note: If the `transactionPollingTimeout` is exceeded, the transaction may still be pending. + +The default value of `transactionPollingTimeout` is 750 seconds (12.5 minutes). + +### [transactionReceiptPollingInterval](/api/web3-core/class/Web3Config#transactionReceiptPollingInterval) +This option defines the number of seconds between Web3 calls for a receipt which confirms that a transaction was mined by the network. Compared to [`transactionPollingInterval`](/guides/web3_config/#transactionpollinginterval), it takes higher precedence. When this value is set, it will be read first. + +The default value of `transactionReceiptPollingInterval` is `undefined`. + +### [transactionSendTimeout](/api/web3-core/class/Web3Config#transactionSendTimeout) +The `transactionSendTimeout` option is used to specify how long to wait for the network to return the sent transaction result. Note: If the RPC call times out, the transaction may still be pending or even mined by the network. It is recommended that the pending transactions be checked in such a case. + +The default value of `transactionSendTimeout` is 750 seconds (12.5 minutes). + +### [transactionConfirmationPollingInterval](/api/web3-core/class/Web3Config#transactionConfirmationPollingInterval) +The `transactionConfirmationPollingInterval` option is deprecated. Please use [`transactionReceiptPollingInterval`](/guides/web3_config/#transactionreceiptpollinginterval) or [`transactionPollingInterval`](/guides/web3_config/#transactionpollinginterval) instead. + +### [blockHeaderTimeout](/api/web3-core/class/Web3Config#blockHeaderTimeout) +After sending a transaction, Web3 will listen for the appearance of new blocks and proceed with subsequent operations based on the transaction results within them. This option defines the number of seconds Web3 should wait for the appearance of new blocks before reverting to polling to fetch the transaction receipt. + +The default value of `blockHeaderTimeout` is 10 seconds. + +### [maxListenersWarningThreshold](/api/web3-core/class/Web3Config#maxListenersWarningThreshold) +The `maxListenersWarningThreshold` is used to set the `maxListeners` property in [`EventEmitter`](/api/web3-utils/class/EventEmitter). + +The default value of `maxListenersWarningThreshold` is 100. + +### [contractDataInputFill](/api/web3-core/class/Web3Config#contractDataInputFill) +The `contractDataInputFill` option allows users to specify whether the [`data`](/api/web3/namespace/types#data) or [`input`](/api/web3/namespace/types#input) property (or both properties) should be set to the hash of the method signature and encoded parameters. This will affect the contracts [`send`](/libdocs/Contract#send), [`call`](/libdocs/Contract#call) and [`estimateGas`](/libdocs/Contract#estimategas) methods. + +The default value of `contractDataInputFill` is `data`. + +#### All available choices for contractDataInputFill: +```ts +'data' +'input' +'both' +``` + +### [defaultNetworkId](/api/web3-core/class/Web3Config#defaultNetworkId) +Each network has its own [network ID](https://docs.goquorum.consensys.io/concepts/network-and-chain-id). The `defaultNetworkId` option allows users to set the default network ID. If this option is not set, Web3 will fetch the network ID with an RPC request. + +The default value of `defaultNetworkId` is `undefined`. + +### [defaultChain](/api/web3-core/class/Web3Config#defaultChain) +The `defaultChain` option is used to set the [`Common`](/api/web3-eth-contract/class/Contract#defaultCommon) `baseChain` property. The value of this option should be consistent with [`defaultCommon.baseChain`](/guides/web3_config/#defaultcommon) if both options are set. + +The default value of `defaultChain` is `mainnet`. + +#### All available choices for defaultChain: +```ts +'goerli' +'kovan' +'mainnet' +'rinkeby' +'ropsten' +'sepolia' +``` + +### [defaultHardfork](/api/web3-core/class/Web3Config#defaultHardfork) +The `defaultHardfork` option is used to set the [`Common`](/api/web3-eth-contract/class/Contract#defaultCommon) `hardfork` property. The value of this option should be consistent with [`defaultCommon.hardfork`](/guides/web3_config/#defaultcommon) if both options are set. + +The default value of `defaultHardfork` is `london`. + +#### All available choices for defaultHardFork: +```ts +'chainstart' +'frontier' +'homestead' +'dao' +'tangerineWhistle' +'spuriousDragon' +'byzantium' +'constantinople' +'petersburg' +'istanbul' +'muirGlacier' +'berlin' +'london' +'altair' +'arrowGlacier' +'grayGlacier' +'bellatrix' +'merge' +'capella' +'sharding' +``` + +### [defaultCommon](/api/web3-core/class/Web3Config#defaultCommon) +The `defaultCommon` option is used to set the [`defaultCommon`](/libdocs/Contract#defaultcommon) value for smart contract transactions. It should be consistent with the [`defaultHardfork`](/guides/web3_config/#defaulthardfork) and [`defaultChain`](/guides/web3_config/#defaultchain) options if they are set. + +The default value of `defaultCommon` is `undefined`. + +```ts +import { Web3, Hardfork } from 'web3'; + +const web3 = new Web3('http://127.0.0.1:7545'); + +web3.defaultHardfork = 'berlin' +web3.defaultChain = 'goerli' + +web3.defaultCommon = { + baseChain: 'goerli', + hardfork: 'berlin' as Hardfork, + customChain: { + networkId: 1, + chainId: 1, + }, }; +console.log(web3.getContextObject().config); ``` -:::info -The `defaultReturnFormat` can be configured both globally and at the package level: + +### [defaultTransactionType](/api/web3-core/class/Web3Config#defaultTransactionType) +The `defaultTransactionType` option is used to set the transaction type. Transactions with type 0x0 are legacy transactions that use the transaction format that existed before [typed transactions](https://ethereum.org/en/developers/docs/transactions/#typed-transaction-envelope) were introduced in [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718). Transactions with type 0x1 are transactions introduced in [EIP-2930](https://eips.ethereum.org/EIPS/eip-2930). Transactions with type 0x2 are transactions introduced in [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559), included in Ethereum's London fork. + +The default value of `defaultTransactionType` is `0x02`. + +### [defaultMaxPriorityFeePerGas](/api/web3-core/class/Web3Config#defaultMaxPriorityFeePerGas) +The `defaultMaxPriorityFeePerGas` option is used to set the [`defaultMaxPriorityFeePerGas`](/api/web3-eth-contract/class/Contract#defaultMaxPriorityFeePerGas) value for [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) smart contract transactions ([transaction type](#defaulttransactiontype) 0x2). + +The default value of `defaultMaxPriorityFeePerGas` is 2500000000 (2.5gwei) in hexstring format. + +### [defaultReturnFormat](/api/web3-core/class/Web3Config#defaultReturnFormat) +The `defaultReturnFormat` option 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 { Web3Eth, FMT_NUMBER, FMT_BYTES } from 'web3-eth'; +import { Web3, FMT_NUMBER, FMT_BYTES } from 'web3'; -const eth = new Web3Eth() -eth.defaultReturnFormat = { +web3.defaultReturnFormat = { number: FMT_NUMBER.BIGINT, bytes: FMT_BYTES.HEX, }; ``` -::: + #### All available choices for numeric data: ```ts export enum FMT_NUMBER { @@ -233,12 +430,12 @@ export enum FMT_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/packages/web3-core/src/web3_config.ts b/packages/web3-core/src/web3_config.ts index 03e478e9ecd..e647e05a9d5 100644 --- a/packages/web3-core/src/web3_config.ts +++ b/packages/web3-core/src/web3_config.ts @@ -152,7 +152,7 @@ export abstract class Web3Config * The `contractDataInputFill` options property will allow you to set the hash of the method signature and encoded parameters to the property * either `data`, `input` or both within your contract. * This will affect the contracts send, call and estimateGas methods - * Default is `input`. + * Default is `data`. */ public get contractDataInputFill() { return this.config.contractDataInputFill; From 0db2b18418b232d431dd5c2f6a543b66d27451a3 Mon Sep 17 00:00:00 2001 From: Myron <49134743+mmyyrroonn@users.noreply.github.com> Date: Thu, 8 Aug 2024 21:57:12 +0800 Subject: [PATCH 132/186] Fix 7055 one of with scalar value and string (#7173) * code work * add test * add more test * update change log * refine change log * refine test --------- Co-authored-by: Oleksii Kosynskyi --- CHANGELOG.md | 6 ++ packages/web3-utils/src/formatter.ts | 21 ++++++- .../web3-utils/test/unit/formatter.test.ts | 61 +++++++++++++++++++ 3 files changed, 87 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f9695c527f..081fb17b6c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2650,6 +2650,12 @@ If there are any bugs, improvements, optimizations or any new feature proposal f ## [Unreleased] +### Fixed + +#### web3-utils + +- Fixed format schema with `oneOf` doesn't work correctly (#7055) + ### Added #### web3-eth-accounts diff --git a/packages/web3-utils/src/formatter.ts b/packages/web3-utils/src/formatter.ts index 665965a8eed..a25c69c26a4 100644 --- a/packages/web3-utils/src/formatter.ts +++ b/packages/web3-utils/src/formatter.ts @@ -131,6 +131,11 @@ export const convertScalarValue = (value: unknown, ethType: string, format: Data throw new FormatterError(`Invalid format: ${String(format.bytes)}`); } } + + if (baseType === 'string') { + return String(value); + } + } catch (error) { // If someone didn't use `eth` keyword we can return original value // as the scope of this code is formatting not validation @@ -289,7 +294,7 @@ export const convert = ( } else { for (const [key, value] of Object.entries(object)) { dataPath.push(key); - const schemaProp = findSchemaByDataPath(schema, dataPath, oneOfPath); + let schemaProp = findSchemaByDataPath(schema, dataPath, oneOfPath); // If value is a scaler value if (isNullish(schemaProp)) { @@ -322,6 +327,20 @@ export const convert = ( continue; } + // 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 specifies format + // 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 + if ((schemaProp?.format === undefined) && (schemaProp?.oneOf !== undefined)) { + for (const [_index, oneOfSchemaProp] of schemaProp.oneOf.entries()) { + if ((oneOfSchemaProp?.format !== undefined)) { + schemaProp = oneOfSchemaProp; + break; + } + }; + } + object[key] = convertScalarValue(value, schemaProp.format as string, format); dataPath.pop(); diff --git a/packages/web3-utils/test/unit/formatter.test.ts b/packages/web3-utils/test/unit/formatter.test.ts index aa1a14fb6c9..9f2bbfc3f1b 100644 --- a/packages/web3-utils/test/unit/formatter.test.ts +++ b/packages/web3-utils/test/unit/formatter.test.ts @@ -479,6 +479,17 @@ describe('formatter', () => { ).toEqual(new Uint8Array([16, 11, 202])); }); }); + + describe('string', () => { + it('should format string for 123', () => { + expect( + format({ format: 'string' }, 123, { + number: FMT_NUMBER.STR, + bytes: FMT_BYTES.HEX, + }), + ).toBe('123'); + }); + }); }); describe('array values', () => { @@ -827,6 +838,56 @@ describe('formatter', () => { expect(result).toEqual(expected); }); + + it('should format object with oneOf', () => { + const schema = { + type: 'object', + properties: { + from: { + format: 'address', + }, + to: { + oneOf: [{ format: 'string' }, { type: 'null' }], + }, + }, + }; + + const data ={ + from: '0x7ed0e85b8e1e925600b4373e6d108f34ab38a401', + to: 123, + } + ; + + const result = { from: '0x7ed0e85b8e1e925600b4373e6d108f34ab38a401', to: '123' }; + + expect( + format(schema, data, { number: FMT_NUMBER.HEX, bytes: FMT_BYTES.HEX }), + ).toEqual(result); + }); + + it('should format object with oneOf when property is undefined', () => { + const schema = { + type: 'object', + properties: { + from: { + format: 'address', + }, + to: { + oneOf: [{ format: 'string' }, { type: 'null' }], + }, + }, + }; + + const data ={ + from: '0x7ed0e85b8e1e925600b4373e6d108f34ab38a401' + }; + + const result = { from: '0x7ed0e85b8e1e925600b4373e6d108f34ab38a401'}; + + expect( + format(schema, data, { number: FMT_NUMBER.HEX, bytes: FMT_BYTES.HEX }), + ).toEqual(result); + }); }); describe('isDataFormat', () => { describe('valid cases', () => { From d9d0391003f2e1d874d39dd43427e1b18b104d8b Mon Sep 17 00:00:00 2001 From: Junaid <86780488+jdevcs@users.noreply.github.com> Date: Tue, 20 Aug 2024 10:13:14 +0200 Subject: [PATCH 133/186] Quicknode provider update (#7195) * added response status code in response error * statusCode in ResponseError * updated error message and it will throw on status code 429 * updated error test snapshot * updated test * updated test for QN * Quicknode provider error * Web3ExternalProvider update * mock ws * lint fix --- packages/web3-errors/CHANGELOG.md | 6 ++- .../web3-errors/src/errors/response_errors.ts | 5 ++- .../unit/__snapshots__/errors.test.ts.snap | 4 ++ packages/web3-providers-http/CHANGELOG.md | 6 ++- packages/web3-providers-http/src/index.ts | 2 +- packages/web3-rpc-providers/CHANGELOG.md | 10 +++-- packages/web3-rpc-providers/package.json | 1 + packages/web3-rpc-providers/src/errors.ts | 5 +-- packages/web3-rpc-providers/src/index.ts | 1 + .../web3-rpc-providers/src/web3_provider.ts | 25 ++++------- .../src/web3_provider_quicknode.ts | 25 ++++++++++- .../test/unit/constructor.test.ts | 44 +++++++++++++++++-- .../test/unit/request.test.ts | 30 ++++++++++--- 13 files changed, 125 insertions(+), 39 deletions(-) diff --git a/packages/web3-errors/CHANGELOG.md b/packages/web3-errors/CHANGELOG.md index 3ed320c80a1..6dbdd143e42 100644 --- a/packages/web3-errors/CHANGELOG.md +++ b/packages/web3-errors/CHANGELOG.md @@ -178,4 +178,8 @@ Documentation: - Fixed the undefined data in `Eip838ExecutionError` constructor (#6905) -## [Unreleased] \ No newline at end of file +## [Unreleased] + +### Added + +- Added optional `statusCode` property of response in ResponseError. \ No newline at end of file diff --git a/packages/web3-errors/src/errors/response_errors.ts b/packages/web3-errors/src/errors/response_errors.ts index 9fb1f09e172..214bf6652f6 100644 --- a/packages/web3-errors/src/errors/response_errors.ts +++ b/packages/web3-errors/src/errors/response_errors.ts @@ -45,11 +45,13 @@ export class ResponseError extends B public code = ERR_RESPONSE; public data?: ErrorType | ErrorType[]; public request?: JsonRpcPayload; + public statusCode?: number; public constructor( response: JsonRpcResponse, message?: string, request?: JsonRpcPayload, + statusCode?: number ) { super( message ?? @@ -66,6 +68,7 @@ export class ResponseError extends B : response?.error?.data; } + this.statusCode = statusCode; this.request = request; let errorOrErrors: JsonRpcError | JsonRpcError[] | undefined; if (`error` in response) { @@ -82,7 +85,7 @@ export class ResponseError extends B } public toJSON() { - return { ...super.toJSON(), data: this.data, request: this.request }; + return { ...super.toJSON(), data: this.data, request: this.request, statusCode: this.statusCode }; } } diff --git a/packages/web3-errors/test/unit/__snapshots__/errors.test.ts.snap b/packages/web3-errors/test/unit/__snapshots__/errors.test.ts.snap index 22a863812e8..c2f3c9f0131 100644 --- a/packages/web3-errors/test/unit/__snapshots__/errors.test.ts.snap +++ b/packages/web3-errors/test/unit/__snapshots__/errors.test.ts.snap @@ -239,6 +239,7 @@ exports[`errors InvalidResponseError should have valid json structure 1`] = ` "message": "Returned error: error message", "name": "InvalidResponseError", "request": undefined, + "statusCode": undefined, } `; @@ -316,6 +317,7 @@ exports[`errors ResponseError should have valid json structure with data 1`] = ` "message": "Returned error: error message", "name": "ResponseError", "request": undefined, + "statusCode": undefined, } `; @@ -336,6 +338,7 @@ exports[`errors ResponseError should have valid json structure without data 1`] "message": "Returned error: error message", "name": "ResponseError", "request": undefined, + "statusCode": undefined, } `; @@ -357,6 +360,7 @@ exports[`errors ResponseError should include the array of inner errors 1`] = ` "message": "Returned error: error message,error message", "name": "ResponseError", "request": undefined, + "statusCode": undefined, } `; diff --git a/packages/web3-providers-http/CHANGELOG.md b/packages/web3-providers-http/CHANGELOG.md index 6d57af6dcf7..dd20cddf35a 100644 --- a/packages/web3-providers-http/CHANGELOG.md +++ b/packages/web3-providers-http/CHANGELOG.md @@ -129,4 +129,8 @@ Documentation: - Fix issue lquixada/cross-fetch#78, enabling to run web3.js in service worker (#6463) -## [Unreleased] \ No newline at end of file +## [Unreleased] + +### Added + +- Added `statusCode` of response in ResponseError, `statusCode` is optional property in ResponseError. \ No newline at end of file diff --git a/packages/web3-providers-http/src/index.ts b/packages/web3-providers-http/src/index.ts index bd069dbc14c..d596d1251f6 100644 --- a/packages/web3-providers-http/src/index.ts +++ b/packages/web3-providers-http/src/index.ts @@ -80,7 +80,7 @@ export default class HttpProvider< }); if (!response.ok) { // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - throw new ResponseError(await response.json()) + throw new ResponseError(await response.json(), undefined, undefined, response.status); }; return (await response.json()) as JsonRpcResponseWithResult; diff --git a/packages/web3-rpc-providers/CHANGELOG.md b/packages/web3-rpc-providers/CHANGELOG.md index d9fe3235240..52a8508d082 100644 --- a/packages/web3-rpc-providers/CHANGELOG.md +++ b/packages/web3-rpc-providers/CHANGELOG.md @@ -43,12 +43,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [1.0.0.rc.1] - ### Added +### Added - When error is returned with code 429, throw rate limit error (#7102) - ### Changed +### Changed - Change request return type `Promise` to `Promise>` (#7102) -## [Unreleased] \ No newline at end of file +## [Unreleased] + +### Added + +- Updated rate limit error of QuickNode provider for HTTP transport \ No newline at end of file diff --git a/packages/web3-rpc-providers/package.json b/packages/web3-rpc-providers/package.json index 606ced0ed22..3d66382ff51 100644 --- a/packages/web3-rpc-providers/package.json +++ b/packages/web3-rpc-providers/package.json @@ -49,6 +49,7 @@ "eslint-config-base-web3": "0.1.0", "eslint-config-prettier": "^8.5.0", "eslint-plugin-import": "^2.26.0", + "isomorphic-ws": "^5.0.0", "jest": "^29.7.0", "jest-extended": "^3.0.1", "prettier": "^2.7.1", diff --git a/packages/web3-rpc-providers/src/errors.ts b/packages/web3-rpc-providers/src/errors.ts index dd602fcb05f..54ad3094596 100644 --- a/packages/web3-rpc-providers/src/errors.ts +++ b/packages/web3-rpc-providers/src/errors.ts @@ -16,13 +16,12 @@ along with web3.js. If not, see . */ import { BaseWeb3Error } from 'web3-errors'; -import { } from 'web3-types'; const ERR_QUICK_NODE_RATE_LIMIT = 1300; export class QuickNodeRateLimitError extends BaseWeb3Error { public code = ERR_QUICK_NODE_RATE_LIMIT; - public constructor() { - super(`Too many requests, Quicknode has reached its rate limit.`); + public constructor(error?: Error) { + super(`You've reach the rate limit of free RPC calls from our Partner Quick Nodes. There are two options you can either create a paid Quick Nodes account and get 20% off for 2 months using WEB3JS referral code, or use Free public RPC endpoint.`, error); } } \ No newline at end of file diff --git a/packages/web3-rpc-providers/src/index.ts b/packages/web3-rpc-providers/src/index.ts index eea79f433cb..637cdae4cc0 100644 --- a/packages/web3-rpc-providers/src/index.ts +++ b/packages/web3-rpc-providers/src/index.ts @@ -20,6 +20,7 @@ import { QuickNodeProvider } from './web3_provider_quicknode.js'; export * from './types.js'; export * from './web3_provider_quicknode.js'; export * from './web3_provider.js'; +export * from './errors.js'; // default providers export const mainnet = new QuickNodeProvider(); \ No newline at end of file diff --git a/packages/web3-rpc-providers/src/web3_provider.ts b/packages/web3-rpc-providers/src/web3_provider.ts index a00034048ef..dbd50cf9e56 100644 --- a/packages/web3-rpc-providers/src/web3_provider.ts +++ b/packages/web3-rpc-providers/src/web3_provider.ts @@ -17,7 +17,6 @@ along with web3.js. If not, see . import HttpProvider from "web3-providers-http"; import WebSocketProvider from "web3-providers-ws"; -import { isNullish } from "web3-validator"; import { EthExecutionAPI, JsonRpcResult, ProviderConnectInfo, ProviderMessage, ProviderRpcError, Web3APIMethod, Web3APIPayload, Web3APIReturnType, Web3APISpec, Web3BaseProvider, @@ -29,7 +28,6 @@ import { } from "web3-types"; import { Eip1193Provider } from "web3-utils"; import { Transport, Network } from "./types.js"; -import { QuickNodeRateLimitError } from './errors.js'; /* This class can be used to create new providers only when there is custom logic required in each Request method like @@ -39,21 +37,21 @@ Another simpler approach can be a function simply returning URL strings instead no additional logic implementation is required in the provider. */ -export abstract class Web3ExternalProvider < -API extends Web3APISpec = EthExecutionAPI, +export abstract class Web3ExternalProvider< + API extends Web3APISpec = EthExecutionAPI, > extends Eip1193Provider { public provider!: Web3BaseProvider; public readonly transport: Transport; - public abstract getRPCURL(network: Network,transport: Transport,token: string, host: string): string; + public abstract getRPCURL(network: Network, transport: Transport, token: string, host: string): string; public constructor( network: Network, transport: Transport, token: string, host: string) { - + super(); this.transport = transport; @@ -74,18 +72,11 @@ API extends Web3APISpec = EthExecutionAPI, ): Promise> { if (this.transport === Transport.HTTPS) { - const res = await ( (this.provider as HttpProvider).request(payload, requestOptions)) as unknown as JsonRpcResponseWithResult; - - if (typeof res === 'object' && !isNullish(res) && 'error' in res && !isNullish(res.error) && 'code' in res.error && (res.error as { code: number }).code === 429){ - // rate limiting error by quicknode; - throw new QuickNodeRateLimitError(); - - } - return res; - } - + return await ((this.provider as HttpProvider).request(payload, requestOptions)) as unknown as JsonRpcResponseWithResult; + } + return (this.provider as WebSocketProvider).request(payload); - + } public getStatus(): Web3ProviderStatus { diff --git a/packages/web3-rpc-providers/src/web3_provider_quicknode.ts b/packages/web3-rpc-providers/src/web3_provider_quicknode.ts index a1b66880110..4444110afdd 100644 --- a/packages/web3-rpc-providers/src/web3_provider_quicknode.ts +++ b/packages/web3-rpc-providers/src/web3_provider_quicknode.ts @@ -15,12 +15,17 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ +import { EthExecutionAPI, JsonRpcResponseWithResult, Web3APIMethod, Web3APIPayload, Web3APIReturnType, Web3APISpec } from "web3-types"; +import { ResponseError } from "web3-errors"; import { Transport, Network } from "./types.js"; import { Web3ExternalProvider } from "./web3_provider.js"; +import { QuickNodeRateLimitError } from "./errors.js"; const isValid = (str: string) => str !== undefined && str.trim().length > 0; -export class QuickNodeProvider extends Web3ExternalProvider { +export class QuickNodeProvider< +API extends Web3APISpec = EthExecutionAPI, +> extends Web3ExternalProvider { public constructor( network: Network = Network.ETH_MAINNET, @@ -32,6 +37,24 @@ export class QuickNodeProvider extends Web3ExternalProvider { } + public async request< + Method extends Web3APIMethod, + ResultType = Web3APIReturnType, + >( + payload: Web3APIPayload, + requestOptions?: RequestInit, + ): Promise> { + + try { + return await super.request(payload, requestOptions); + } catch (error) { + if (error instanceof ResponseError && error.statusCode === 429){ + throw new QuickNodeRateLimitError(error); + } + throw error; + } + } + // eslint-disable-next-line class-methods-use-this public getRPCURL(network: Network, transport: Transport, diff --git a/packages/web3-rpc-providers/test/unit/constructor.test.ts b/packages/web3-rpc-providers/test/unit/constructor.test.ts index eb64b29163a..0daedb8c77d 100644 --- a/packages/web3-rpc-providers/test/unit/constructor.test.ts +++ b/packages/web3-rpc-providers/test/unit/constructor.test.ts @@ -14,13 +14,51 @@ 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 . */ -/* eslint-disable max-classes-per-file */ + import HttpProvider from 'web3-providers-http'; import WebSocketProvider from 'web3-providers-ws'; +import WebSocket from 'isomorphic-ws'; + import { Web3ExternalProvider } from '../../src/web3_provider'; import { Network, Transport } from '../../src/types'; +// Mock implementation so ws doesnt have openhandle after test exits as it attempts to connects at start +jest.mock('isomorphic-ws', () => { + return { + __esModule: true, + default: jest.fn().mockImplementation(() => { + // eslint-disable-next-line @typescript-eslint/ban-types + const eventListeners: { [key: string]: Function[] } = {}; + + return { + addEventListener: jest.fn((event, handler) => { + if (!eventListeners[event]) { + eventListeners[event] = []; + } + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + eventListeners[event].push(handler); + }), + removeEventListener: jest.fn((event, handler) => { + if (eventListeners[event]) { + eventListeners[event] = eventListeners[event].filter(h => h !== handler); + } + }), + dispatchEvent: jest.fn((event) => { + const eventType = event.type; + if (eventListeners[eventType]) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + eventListeners[eventType].forEach(handler => handler(event)); + } + }), + close: jest.fn(), + send: jest.fn(), + readyState: WebSocket.OPEN, + }; + }), + }; +}); + class MockWeb3ExternalProviderA extends Web3ExternalProvider { public constructor(network: Network, transport: Transport, token: string){ super(network, transport, token, ""); @@ -33,7 +71,7 @@ class MockWeb3ExternalProviderA extends Web3ExternalProvider { else if (_transport === Transport.WebSocket) transport = "wss://"; - return `${transport}example.com/`; + return `${transport}127.0.0.1/`; } } @@ -54,9 +92,7 @@ describe('Web3ExternalProvider', () => { const token = 'your-token'; const provider = new MockWeb3ExternalProviderA(network, transport, token); - expect(provider.provider).toBeInstanceOf(WebSocketProvider); }); }); -/* eslint-enable max-classes-per-file */ \ No newline at end of file diff --git a/packages/web3-rpc-providers/test/unit/request.test.ts b/packages/web3-rpc-providers/test/unit/request.test.ts index d0d38ac5e14..6107949b0f1 100644 --- a/packages/web3-rpc-providers/test/unit/request.test.ts +++ b/packages/web3-rpc-providers/test/unit/request.test.ts @@ -14,10 +14,12 @@ 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 { Web3APIPayload, EthExecutionAPI, Web3APIMethod } from "web3-types"; +import { Web3APIPayload, EthExecutionAPI, Web3APIMethod, JsonRpcResponse } from "web3-types"; +import { ResponseError } from "web3-errors"; import { Network, Transport } from "../../src/types"; import { Web3ExternalProvider } from "../../src/web3_provider"; import { QuickNodeRateLimitError } from '../../src/errors'; +import { QuickNodeProvider } from '../../src/web3_provider_quicknode'; jest.mock('web3-providers-ws', () => { return { @@ -79,7 +81,8 @@ describe('Web3ExternalProvider', () => { const result = await provider.request(payload); expect(result).toEqual({ result: 'mock-result' }); }); - it('should return a rate limiting error when code is 429', async () => { + + it('should throw a rate limiting error when status code is 429', async () => { const network: Network = Network.ETH_MAINNET; const transport: Transport = Transport.HTTPS; const token = 'your-token'; @@ -88,17 +91,29 @@ describe('Web3ExternalProvider', () => { request: jest.fn(), }; - const mockResponse = { + // Create a mock ResponseError with status code 429 + // Create a mock JsonRpcResponse to pass to ResponseError + const mockJsonRpcResponse: JsonRpcResponse = { jsonrpc: '2.0', id: '458408f4-7e2c-43f1-b61d-1fe09a9ee25a', error: { code: 429, - message: 'the method eth_stuff does not exist/is not available' - } + message: 'Rate limit exceeded', + }, }; - mockHttpProvider.request.mockResolvedValue(mockResponse); - const provider = new MockWeb3ExternalProvider(network, transport, token); + // Create a mock ResponseError with status code 429 + const mockError = new ResponseError( + mockJsonRpcResponse, + undefined, + undefined, // request can be undefined + 429 // statusCode + ); + + // Mock the request method to throw the ResponseError + mockHttpProvider.request.mockRejectedValue(mockError); + + const provider = new QuickNodeProvider(network, transport, token); (provider as any).provider = mockHttpProvider; const payload: Web3APIPayload> = { @@ -107,4 +122,5 @@ describe('Web3ExternalProvider', () => { }; await expect(provider.request(payload)).rejects.toThrow(QuickNodeRateLimitError); }); + }); \ No newline at end of file From 2ef694cc5b40cf44f4ec46c60e183970d2f5c18e Mon Sep 17 00:00:00 2001 From: Junaid <86780488+jdevcs@users.noreply.github.com> Date: Wed, 21 Aug 2024 09:11:20 +0200 Subject: [PATCH 134/186] Web3 RPC Providers support of configuration of selected transport (#7205) * SocketOptions type * ProviderConfigOptionsError * providerConfigOptions * tests * changelog --- packages/web3-rpc-providers/CHANGELOG.md | 3 +- packages/web3-rpc-providers/src/errors.ts | 14 ++- packages/web3-rpc-providers/src/types.ts | 9 ++ .../web3-rpc-providers/src/web3_provider.ts | 34 ++++++-- .../src/web3_provider_quicknode.ts | 12 ++- .../test/unit/constructor.test.ts | 87 ++++++++++++++++--- 6 files changed, 132 insertions(+), 27 deletions(-) diff --git a/packages/web3-rpc-providers/CHANGELOG.md b/packages/web3-rpc-providers/CHANGELOG.md index 52a8508d082..d07ba9124a4 100644 --- a/packages/web3-rpc-providers/CHANGELOG.md +++ b/packages/web3-rpc-providers/CHANGELOG.md @@ -55,4 +55,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- Updated rate limit error of QuickNode provider for HTTP transport \ No newline at end of file +- Updated rate limit error of QuickNode provider for HTTP transport +- Added optional `HttpProviderOptions | SocketOptions` in `Web3ExternalProvider` and `QuickNodeProvider` for provider configs \ No newline at end of file diff --git a/packages/web3-rpc-providers/src/errors.ts b/packages/web3-rpc-providers/src/errors.ts index 54ad3094596..d698fbb66ab 100644 --- a/packages/web3-rpc-providers/src/errors.ts +++ b/packages/web3-rpc-providers/src/errors.ts @@ -15,6 +15,8 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ +/* eslint-disable max-classes-per-file */ + import { BaseWeb3Error } from 'web3-errors'; const ERR_QUICK_NODE_RATE_LIMIT = 1300; @@ -24,4 +26,14 @@ export class QuickNodeRateLimitError extends BaseWeb3Error { public constructor(error?: Error) { super(`You've reach the rate limit of free RPC calls from our Partner Quick Nodes. There are two options you can either create a paid Quick Nodes account and get 20% off for 2 months using WEB3JS referral code, or use Free public RPC endpoint.`, error); } -} \ No newline at end of file +} + +const ERR_PROVIDER_CONFIG_OPTIONS = 1301; +export class ProviderConfigOptionsError extends BaseWeb3Error { + public code = ERR_PROVIDER_CONFIG_OPTIONS; + + public constructor(msg: string) { + super(`Invalid provider config options given for ${msg}`); + } +} +/* eslint-enable max-classes-per-file */ \ No newline at end of file diff --git a/packages/web3-rpc-providers/src/types.ts b/packages/web3-rpc-providers/src/types.ts index 9da4c1dbfe7..e23714977c1 100644 --- a/packages/web3-rpc-providers/src/types.ts +++ b/packages/web3-rpc-providers/src/types.ts @@ -15,6 +15,9 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ +import {ClientOptions, ClientRequestArgs} from "web3-providers-ws"; +import { ReconnectOptions } from 'web3-utils'; + export enum Transport { HTTPS = "https", WebSocket = "wss" @@ -41,4 +44,10 @@ export enum Network { BNB_MAINNET = "bnb_mainnet", BNB_TESTNET = "bnb_testnet" +}; + +// Combining the ws types +export type SocketOptions = { + socketOptions?: ClientOptions | ClientRequestArgs; + reconnectOptions?: Partial; }; \ No newline at end of file diff --git a/packages/web3-rpc-providers/src/web3_provider.ts b/packages/web3-rpc-providers/src/web3_provider.ts index dbd50cf9e56..498dec60433 100644 --- a/packages/web3-rpc-providers/src/web3_provider.ts +++ b/packages/web3-rpc-providers/src/web3_provider.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 HttpProvider from "web3-providers-http"; +import HttpProvider, { HttpProviderOptions } from "web3-providers-http"; import WebSocketProvider from "web3-providers-ws"; import { EthExecutionAPI, JsonRpcResult, ProviderConnectInfo, ProviderMessage, @@ -27,7 +27,8 @@ import { JsonRpcResponseWithResult, } from "web3-types"; import { Eip1193Provider } from "web3-utils"; -import { Transport, Network } from "./types.js"; +import { Transport, Network, SocketOptions } from "./types.js"; +import { ProviderConfigOptionsError } from "./errors.js"; /* This class can be used to create new providers only when there is custom logic required in each Request method like @@ -50,16 +51,36 @@ export abstract class Web3ExternalProvider< network: Network, transport: Transport, token: string, - host: string) { + host: string, + providerConfigOptions?: HttpProviderOptions | SocketOptions) { super(); + if(providerConfigOptions!== undefined && + transport === Transport.HTTPS && + !('providerOptions' in providerConfigOptions)){ + + throw new ProviderConfigOptionsError("HTTP Provider"); + } + else if(providerConfigOptions!== undefined && + transport === Transport.WebSocket && + !( 'socketOptions' in providerConfigOptions || + 'reconnectOptions' in providerConfigOptions + )){ + throw new ProviderConfigOptionsError("Websocket Provider"); + } + this.transport = transport; if (transport === Transport.HTTPS) { - this.provider = new HttpProvider(this.getRPCURL(network, transport, token, host)); + this.provider = new HttpProvider( + this.getRPCURL(network, transport, token, host), + providerConfigOptions as HttpProviderOptions); } else if (transport === Transport.WebSocket) { - this.provider = new WebSocketProvider(this.getRPCURL(network, transport, token, host)); + this.provider = new WebSocketProvider( + this.getRPCURL(network, transport, token, host), + (providerConfigOptions as SocketOptions)?.socketOptions, + (providerConfigOptions as SocketOptions)?.reconnectOptions); } } @@ -133,4 +154,5 @@ export abstract class Web3ExternalProvider< // eslint-disable-next-line @typescript-eslint/no-unsafe-argument this.provider.removeListener(_type as any, _listener as any); } -} \ No newline at end of file +} + diff --git a/packages/web3-rpc-providers/src/web3_provider_quicknode.ts b/packages/web3-rpc-providers/src/web3_provider_quicknode.ts index 4444110afdd..459cf5d5d38 100644 --- a/packages/web3-rpc-providers/src/web3_provider_quicknode.ts +++ b/packages/web3-rpc-providers/src/web3_provider_quicknode.ts @@ -17,7 +17,8 @@ along with web3.js. If not, see . import { EthExecutionAPI, JsonRpcResponseWithResult, Web3APIMethod, Web3APIPayload, Web3APIReturnType, Web3APISpec } from "web3-types"; import { ResponseError } from "web3-errors"; -import { Transport, Network } from "./types.js"; +import { HttpProviderOptions } from "web3-providers-http"; +import { Transport, Network, SocketOptions } from "./types.js"; import { Web3ExternalProvider } from "./web3_provider.js"; import { QuickNodeRateLimitError } from "./errors.js"; @@ -27,13 +28,10 @@ export class QuickNodeProvider< API extends Web3APISpec = EthExecutionAPI, > extends Web3ExternalProvider { - public constructor( - network: Network = Network.ETH_MAINNET, - transport: Transport = Transport.HTTPS, - token = "", - host = "") { + // eslint-disable-next-line default-param-last + public constructor( network: Network = Network.ETH_MAINNET, transport: Transport = Transport.HTTPS, token = "", host = "", providerConfigOptions?: HttpProviderOptions | SocketOptions) { - super(network, transport, token, host); + super(network, transport, token, host, providerConfigOptions); } diff --git a/packages/web3-rpc-providers/test/unit/constructor.test.ts b/packages/web3-rpc-providers/test/unit/constructor.test.ts index 0daedb8c77d..16133129d55 100644 --- a/packages/web3-rpc-providers/test/unit/constructor.test.ts +++ b/packages/web3-rpc-providers/test/unit/constructor.test.ts @@ -16,12 +16,13 @@ along with web3.js. If not, see . */ -import HttpProvider from 'web3-providers-http'; +import HttpProvider, { HttpProviderOptions } from 'web3-providers-http'; import WebSocketProvider from 'web3-providers-ws'; import WebSocket from 'isomorphic-ws'; import { Web3ExternalProvider } from '../../src/web3_provider'; -import { Network, Transport } from '../../src/types'; +import { Network, SocketOptions, Transport } from '../../src/types'; +import { ProviderConfigOptionsError } from '../../src/errors'; // Mock implementation so ws doesnt have openhandle after test exits as it attempts to connects at start jest.mock('isomorphic-ws', () => { @@ -60,11 +61,11 @@ jest.mock('isomorphic-ws', () => { }); class MockWeb3ExternalProviderA extends Web3ExternalProvider { - public constructor(network: Network, transport: Transport, token: string){ - super(network, transport, token, ""); + public constructor(network: Network, transport: Transport, token: string, host?: string, providerConfigOptions?: HttpProviderOptions | SocketOptions) { + super(network, transport, token, host ?? "", providerConfigOptions); } // eslint-disable-next-line class-methods-use-this - public getRPCURL(_network: Network, _transport: Transport, _token: string, _host=""): string { + public getRPCURL(_network: Network, _transport: Transport, _token: string, _host = ""): string { let transport = ""; if (_transport === Transport.HTTPS) transport = "http://"; @@ -76,10 +77,12 @@ class MockWeb3ExternalProviderA extends Web3ExternalProvider { } describe('Web3ExternalProvider', () => { + const network: Network = Network.ETH_MAINNET; + const transport: Transport = Transport.HTTPS; + const token = 'test-token'; + const host = 'test-host'; + it('should initialize the provider correctly', () => { - const network: Network = Network.ETH_MAINNET; - const transport: Transport = Transport.HTTPS; - const token = 'your-token'; const provider = new MockWeb3ExternalProviderA(network, transport, token); @@ -87,12 +90,72 @@ describe('Web3ExternalProvider', () => { }); it('should initialize the provider with WebSocketProvider for WebSocket transport', () => { - const network: Network = Network.ETH_MAINNET; - const transport: Transport = Transport.WebSocket; - const token = 'your-token'; + const transport1: Transport = Transport.WebSocket; - const provider = new MockWeb3ExternalProviderA(network, transport, token); + const provider = new MockWeb3ExternalProviderA(network, transport1, token); expect(provider.provider).toBeInstanceOf(WebSocketProvider); }); + it('should throw ProviderConfigOptionsError for HTTP provider with missing providerOptions', () => { + const providerConfigOptions: HttpProviderOptions | SocketOptions = { /* missing providerOptions */ }; + expect(() => new MockWeb3ExternalProviderA(network, transport, token, host, providerConfigOptions)).toThrow(ProviderConfigOptionsError); + }); + + it('should throw ProviderConfigOptionsError for HTTP provider with WS providerOptions', () => { + const providerConfigOptions: SocketOptions = { + socketOptions: { /* options */ }, + reconnectOptions: { /* options */ }, + }; + expect(() => new MockWeb3ExternalProviderA(network, transport, token, host, providerConfigOptions)).toThrow(ProviderConfigOptionsError); + }); + + it('should throw ProviderConfigOptionsError for WebSocket provider with missing socketOptions and reconnectOptions', () => { + const providerConfigOptions: HttpProviderOptions | SocketOptions = { /* missing socketOptions and reconnectOptions */ }; + expect(() => new MockWeb3ExternalProviderA(network, Transport.WebSocket, token, host, providerConfigOptions)).toThrow(ProviderConfigOptionsError); + }); + + it('should throw ProviderConfigOptionsError for WebSocket provider with HTTP options', () => { + const providerConfigOptions: HttpProviderOptions = { providerOptions: { /* options */ } }; + expect(() => new MockWeb3ExternalProviderA(network, Transport.WebSocket, token, host, providerConfigOptions)).toThrow(ProviderConfigOptionsError); + }); + + it('should create provider instance and not throw ProviderConfigOptionsError for WebSocket provider with missing reconnectOptions', () => { + const providerConfigOptions: SocketOptions = { + socketOptions: { /* options */ }, + }; + + // Create an instance of the MockWeb3ExternalProviderA + const provider = new MockWeb3ExternalProviderA(network, Transport.WebSocket, token, host, providerConfigOptions); + + // Expect that the provider is created successfully + expect(provider).toBeInstanceOf(MockWeb3ExternalProviderA); + }); + + it('should create provider instance and not throw ProviderConfigOptionsError for WebSocket provider with missing socketOptions', () => { + const providerConfigOptions: SocketOptions = { + reconnectOptions: { /* options */ }, + }; + + // Create an instance of the MockWeb3ExternalProviderA + const provider = new MockWeb3ExternalProviderA(network, Transport.WebSocket, token, host, providerConfigOptions); + + // Expect that the provider is created successfully + expect(provider).toBeInstanceOf(MockWeb3ExternalProviderA); + }); + + it('should create an HttpProvider with providerOptions', () => { + const providerConfigOptions: HttpProviderOptions = { providerOptions: { /* options */ } }; + const provider = new MockWeb3ExternalProviderA(network, transport, token, host, providerConfigOptions); + expect(provider.provider).toBeInstanceOf(HttpProvider); + }); + + it('should create a WebSocketProvider with socketOptions and reconnectOptions', () => { + const providerConfigOptions: SocketOptions = { + socketOptions: { /* options */ }, + reconnectOptions: { /* options */ }, + }; + const provider = new MockWeb3ExternalProviderA(network, Transport.WebSocket, token, host, providerConfigOptions); + expect(provider.provider).toBeInstanceOf(WebSocketProvider); + }); }); + From 4f8e8ccfb50fc7d76a9712e67a7454004379cbbe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Aug 2024 13:35:50 +0200 Subject: [PATCH 135/186] Bump axios from 1.6.2 to 1.7.4 (#7204) Bumps [axios](https://github.com/axios/axios) from 1.6.2 to 1.7.4. - [Release notes](https://github.com/axios/axios/releases) - [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md) - [Commits](https://github.com/axios/axios/compare/v1.6.2...v1.7.4) --- updated-dependencies: - dependency-name: axios dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/yarn.lock b/yarn.lock index e85fa099abb..e5ac4b827bb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3373,11 +3373,11 @@ aws4@^1.8.0: integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== axios@^1.0.0: - version "1.6.2" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.2.tgz#de67d42c755b571d3e698df1b6504cde9b0ee9f2" - integrity sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A== + version "1.7.4" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.4.tgz#4c8ded1b43683c8dd362973c393f3ede24052aa2" + integrity sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw== dependencies: - follow-redirects "^1.15.0" + follow-redirects "^1.15.6" form-data "^4.0.0" proxy-from-env "^1.1.0" @@ -6072,10 +6072,10 @@ follow-redirects@^1.0.0, follow-redirects@^1.12.1: resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5" integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA== -follow-redirects@^1.15.0: - version "1.15.2" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" - integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== +follow-redirects@^1.15.6: + version "1.15.6" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" + integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== for-each@^0.3.3: version "0.3.3" From 60fc1979820fa7be3b6052ccca8397ee75032631 Mon Sep 17 00:00:00 2001 From: Muhammad Altabba <24407834+Muhammad-Altabba@users.noreply.github.com> Date: Wed, 21 Aug 2024 21:13:21 +0200 Subject: [PATCH 136/186] Refactor some parts of contract and accounts packages (#7197) * add `DeployerMethodClass` * set `extraTxTypes` using global * update CHANGELOG.md files --- packages/web3-eth-accounts/CHANGELOG.md | 3 + .../src/tx/transactionFactory.ts | 10 +- packages/web3-eth-contract/CHANGELOG.md | 8 + .../src/contract-deployer-method-class.ts | 240 +++++++++++++++++ packages/web3-eth-contract/src/contract.ts | 243 ++++-------------- packages/web3-eth-contract/src/index.ts | 1 + packages/web3-eth-contract/src/utils.ts | 5 +- 7 files changed, 310 insertions(+), 200 deletions(-) create mode 100644 packages/web3-eth-contract/src/contract-deployer-method-class.ts diff --git a/packages/web3-eth-accounts/CHANGELOG.md b/packages/web3-eth-accounts/CHANGELOG.md index b28e2c9b047..b682b5e34bb 100644 --- a/packages/web3-eth-accounts/CHANGELOG.md +++ b/packages/web3-eth-accounts/CHANGELOG.md @@ -172,3 +172,6 @@ Documentation: ### Added - Added public function `signMessageWithPrivateKey` (#7174) + +### Fixed +- Fix `TransactionFactory.registerTransactionType` not working, if there is a version mistatch between `web3-eth` and `web3-eth-accounts` by saving `extraTxTypes` at `globals`. (#7197) diff --git a/packages/web3-eth-accounts/src/tx/transactionFactory.ts b/packages/web3-eth-accounts/src/tx/transactionFactory.ts index a677543c64f..98a465c0973 100644 --- a/packages/web3-eth-accounts/src/tx/transactionFactory.ts +++ b/packages/web3-eth-accounts/src/tx/transactionFactory.ts @@ -31,7 +31,15 @@ import type { } from './types.js'; import { BaseTransaction } from './baseTransaction.js'; -const extraTxTypes: Map> = new Map(); +let extraTxTypes: Map>; +// use the global object, to work fine even if web3-eth and web3-eth-accounts was on a different versions: +const typedGlobal = global as unknown as {extraTxTypes: Map>} +if (!typedGlobal.extraTxTypes) { + extraTxTypes = new Map(); + typedGlobal.extraTxTypes = extraTxTypes; +} else { + extraTxTypes = typedGlobal.extraTxTypes; +} // eslint-disable-next-line @typescript-eslint/no-extraneous-class export class TransactionFactory { diff --git a/packages/web3-eth-contract/CHANGELOG.md b/packages/web3-eth-contract/CHANGELOG.md index bab02912320..01e6f2f8a68 100644 --- a/packages/web3-eth-contract/CHANGELOG.md +++ b/packages/web3-eth-contract/CHANGELOG.md @@ -395,3 +395,11 @@ Documentation: ## [Unreleased] +### Added + +- Added `populateTransaction` to the `contract.deploy(...)` properties. (#7197) + +### Changed + +- The returnred properties of `contract.deploy(...)` are structured with a newly created class named `DeployerMethodClass`. (#7197) +- Add a missed accepted type for the `abi` parameter, at `dataInputEncodeMethodHelper` and `getSendTxParams`. (#7197) diff --git a/packages/web3-eth-contract/src/contract-deployer-method-class.ts b/packages/web3-eth-contract/src/contract-deployer-method-class.ts new file mode 100644 index 00000000000..d57f7ae05b2 --- /dev/null +++ b/packages/web3-eth-contract/src/contract-deployer-method-class.ts @@ -0,0 +1,240 @@ +/* +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 { + Web3ContractError, +} from 'web3-errors'; +import { + sendTransaction, + SendTransactionEvents, + SendTransactionOptions, +} from 'web3-eth'; +import { + AbiConstructorFragment, + AbiFunctionFragment, + ContractAbi, + ContractConstructorArgs, + Bytes, + HexString, + PayableCallOptions, + DataFormat, + DEFAULT_RETURN_FORMAT, + ContractOptions, + TransactionReceipt, + TransactionCall, +} from 'web3-types'; +import { + format, +} from 'web3-utils'; +import { + isNullish, +} from 'web3-validator'; +import { Web3PromiEvent } from 'web3-core'; +import { + decodeMethodParams, + encodeMethodABI, +} from './encoding.js'; +import { + NonPayableTxOptions, + PayableTxOptions, +} from './types.js'; +import { + getSendTxParams, +} from './utils.js'; +// eslint-disable-next-line import/no-cycle +import { Contract } from './contract.js'; + +export type ContractDeploySend = Web3PromiEvent< + // eslint-disable-next-line no-use-before-define + Contract, + SendTransactionEvents +>; + +/* + * This class is only supposed to be used for the return of `new Contract(...).deploy(...)` method. + */ +export class DeployerMethodClass { + + protected readonly args: never[] | ContractConstructorArgs; + protected readonly constructorAbi: AbiConstructorFragment; + protected readonly contractOptions: ContractOptions; + protected readonly deployData?: string; + + protected _contractMethodDeploySend( + tx: TransactionCall, + ) { + // eslint-disable-next-line no-use-before-define + const returnTxOptions: SendTransactionOptions> = { + transactionResolver: (receipt: TransactionReceipt) => { + if (receipt.status === BigInt(0)) { + throw new Web3ContractError("code couldn't be stored", receipt); + } + + const newContract = this.parent.clone(); + + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + newContract.options.address = receipt.contractAddress; + return newContract; + }, + + contractAbi: this.parent.options.jsonInterface, + // TODO Should make this configurable by the user + checkRevertBeforeSending: false, + }; + + return isNullish(this.parent.getTransactionMiddleware()) + ? sendTransaction(this.parent, tx, this.parent.defaultReturnFormat, returnTxOptions) // not calling this with undefined Middleware because it will not break if Eth package is not updated + : sendTransaction( + this.parent, + tx, + this.parent.defaultReturnFormat, + returnTxOptions, + this.parent.getTransactionMiddleware(), + ); + } + + public constructor( + // eslint-disable-next-line no-use-before-define + public parent: Contract, + public deployOptions: + | { + /** + * The byte code of the contract. + */ + data?: HexString; + input?: HexString; + /** + * The arguments which get passed to the constructor on deployment. + */ + arguments?: ContractConstructorArgs; + } + | undefined, + ) { + + const { args, abi, contractOptions, deployData} = this.calculateDeployParams(); + + this.args = args; + this.constructorAbi = abi; + this.contractOptions = contractOptions; + this.deployData = deployData; + } + + public send(options?: PayableTxOptions): ContractDeploySend { + const modifiedOptions = { ...options }; + + const tx = this.populateTransaction(modifiedOptions); + + return this._contractMethodDeploySend(tx); + } + + public populateTransaction( + txOptions?: PayableTxOptions | NonPayableTxOptions, + ) { + const modifiedContractOptions = { + ...this.contractOptions, + from: this.contractOptions.from ?? this.parent.defaultAccount ?? undefined, + }; + + // args, abi, contractOptions, deployData + + const tx = getSendTxParams({ + abi: this.constructorAbi, + params: this.args as unknown[], + options: { ...txOptions, dataInputFill: this.parent.contractDataInputFill }, + contractOptions: modifiedContractOptions, + }); + + // @ts-expect-error remove unnecessary field + if (tx.dataInputFill) { + // @ts-expect-error remove unnecessary field + delete tx.dataInputFill; + } + return tx; + } + + protected calculateDeployParams() { + let abi = this.parent.options.jsonInterface.find( + j => j.type === 'constructor', + ) as AbiConstructorFragment; + if (!abi) { + abi = { + type: 'constructor', + stateMutability: '', + } as AbiConstructorFragment; + } + + const _input = format( + { format: 'bytes' }, + this.deployOptions?.input ?? this.parent.options.input, + DEFAULT_RETURN_FORMAT, + ); + + const _data = format( + { format: 'bytes' }, + this.deployOptions?.data ?? this.parent.options.data, + DEFAULT_RETURN_FORMAT, + ); + + if ((!_input || _input.trim() === '0x') && (!_data || _data.trim() === '0x')) { + throw new Web3ContractError('contract creation without any data provided.'); + } + + const args = this.deployOptions?.arguments ?? []; + + const contractOptions: ContractOptions = { + ...this.parent.options, + input: _input, + data: _data, + }; + const deployData = _input ?? _data; + + return { args, abi, contractOptions, deployData} + } + + public async estimateGas( + options?: PayableCallOptions, + returnFormat: ReturnFormat = this.parent.defaultReturnFormat as ReturnFormat, + ) { + const modifiedOptions = { ...options }; + return this.parent.contractMethodEstimateGas({ + abi: this.constructorAbi as AbiFunctionFragment, + params: this.args as unknown[], + returnFormat, + options: modifiedOptions, + contractOptions: this.contractOptions, + }); + } + + public encodeABI() { + return encodeMethodABI( + this.constructorAbi, + this.args as unknown[], + format( + { format: 'bytes' }, + this.deployData as Bytes, + this.parent.defaultReturnFormat as typeof DEFAULT_RETURN_FORMAT, + ), + ); + } + + public decodeData(data: HexString) { + return { + ...decodeMethodParams(this.constructorAbi, data.replace(this.deployData as string, ''), false), + __method__: this.constructorAbi.type, + }; + } +}; diff --git a/packages/web3-eth-contract/src/contract.ts b/packages/web3-eth-contract/src/contract.ts index cba5043df95..906cd3c8794 100644 --- a/packages/web3-eth-contract/src/contract.ts +++ b/packages/web3-eth-contract/src/contract.ts @@ -40,7 +40,6 @@ import { ALL_EVENTS_ABI, SendTransactionEvents, TransactionMiddleware, - SendTransactionOptions, } from 'web3-eth'; import { encodeEventSignature, @@ -52,7 +51,6 @@ import { jsonInterfaceMethodToString, } from 'web3-eth-abi'; import { - AbiConstructorFragment, AbiErrorFragment, AbiEventFragment, AbiFragment, @@ -67,7 +65,6 @@ import { Address, BlockNumberOrTag, BlockTags, - Bytes, EthExecutionAPI, Filter, FilterAbis, @@ -124,6 +121,8 @@ import { getSendTxParams, isWeb3ContractContext, } from './utils.js'; +// eslint-disable-next-line import/no-cycle +import { DeployerMethodClass } from './contract-deployer-method-class.js'; type ContractBoundMethod< Abi extends AbiFunctionFragment, @@ -168,11 +167,6 @@ export type ContractMethodSend = Web3PromiEvent< FormatType, SendTransactionEvents >; -export type ContractDeploySend = Web3PromiEvent< - // eslint-disable-next-line no-use-before-define - Contract, - SendTransactionEvents ->; /** * @hidden @@ -215,6 +209,8 @@ const contractSubscriptions = { newBlockHeaders: NewHeadsSubscription, }; + + /** * The `web3.eth.Contract` makes it easy to interact with smart contracts on the ethereum blockchain. * For using contract package, first install Web3 package using: `npm i web3` or `yarn add web3` based on your package manager, after that contracts features can be used as mentioned in following snippet. @@ -515,11 +511,7 @@ export class Contract ); public constructor( jsonInterface: Abi, - addressOrOptionsOrContext?: - | Address - | ContractInitOptions - | Web3ContractContext - | Web3Context, + addressOrOptionsOrContext?: Address | ContractInitOptions | Web3ContractContext | Web3Context, optionsOrContextOrReturnFormat?: | ContractInitOptions | Web3ContractContext @@ -545,20 +537,14 @@ 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; @@ -852,80 +838,8 @@ export class Contract * The arguments which get passed to the constructor on deployment. */ arguments?: ContractConstructorArgs; - }) { - let abi = this._jsonInterface.find(j => j.type === 'constructor') as AbiConstructorFragment; - if (!abi) { - abi = { - type: 'constructor', - stateMutability: '', - } as AbiConstructorFragment; - } - - const _input = format( - { format: 'bytes' }, - deployOptions?.input ?? this.options.input, - DEFAULT_RETURN_FORMAT, - ); - - const _data = format( - { format: 'bytes' }, - deployOptions?.data ?? this.options.data, - DEFAULT_RETURN_FORMAT, - ); - - if ((!_input || _input.trim() === '0x') && (!_data || _data.trim() === '0x')) { - throw new Web3ContractError('contract creation without any data provided.'); - } - - const args = deployOptions?.arguments ?? []; - - const contractOptions: ContractOptions = { ...this.options, input: _input, data: _data }; - const deployData = _input ?? _data; - return { - arguments: args, - send: (options?: PayableTxOptions): ContractDeploySend => { - const modifiedOptions = { ...options }; - - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return this._contractMethodDeploySend( - abi as AbiFunctionFragment, - args as unknown[], - modifiedOptions, - contractOptions, - ); - }, - estimateGas: async ( - options?: PayableCallOptions, - returnFormat: ReturnFormat = this.defaultReturnFormat as ReturnFormat, - ) => { - const modifiedOptions = { ...options }; - return this._contractMethodEstimateGas({ - abi: abi as AbiFunctionFragment, - params: args as unknown[], - returnFormat, - options: modifiedOptions, - contractOptions, - }); - }, - encodeABI: () => - encodeMethodABI( - abi as AbiFunctionFragment, - args as unknown[], - format( - { format: 'bytes' }, - deployData as Bytes, - this.defaultReturnFormat as typeof DEFAULT_RETURN_FORMAT, - ), - ), - decodeData: (data: HexString) => ({ - ...decodeMethodParams( - abi as AbiFunctionFragment, - data.replace(deployData as string, ''), - false, - ), - __method__: abi.type, // abi.type is constructor - }), - }; + }): DeployerMethodClass { + return new DeployerMethodClass(this, deployOptions); } /** @@ -1046,8 +960,7 @@ 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(), ); } @@ -1057,10 +970,7 @@ 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(); }); }); } @@ -1103,9 +1013,7 @@ 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 = { @@ -1121,9 +1029,7 @@ 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, [ @@ -1131,10 +1037,10 @@ export class Contract abi, ]); const abiFragment = this._overloadedMethodAbis.get(abi.name) ?? []; - const contractMethod = this._createContractMethod< - typeof abiFragment, - AbiErrorFragment - >(abiFragment, errorsAbi); + const contractMethod = this._createContractMethod( + abiFragment, + errorsAbi, + ); const exactContractMethod = this._createContractMethod< typeof abiFragment, @@ -1147,8 +1053,7 @@ 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] = @@ -1224,10 +1129,7 @@ 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); @@ -1243,9 +1145,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 @@ -1267,14 +1169,7 @@ 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), @@ -1303,10 +1198,9 @@ export class Contract }, estimateGas: async ( options?: PayableCallOptions | NonPayableCallOptions, - returnFormat: ReturnFormat = this - .defaultReturnFormat as unknown as ReturnFormat, + returnFormat: ReturnFormat = this.defaultReturnFormat as unknown as ReturnFormat, ) => - this._contractMethodEstimateGas({ + this.contractMethodEstimateGas({ abi: methodAbi, params: abiParams, returnFormat, @@ -1428,17 +1322,23 @@ export class Contract contractOptions: modifiedContractOptions, }); - const transactionToSend = (isNullish(this.transactionMiddleware)) ? - sendTransaction(this, tx, this.defaultReturnFormat, { - // TODO Should make this configurable by the user - checkRevertBeforeSending: false, - contractAbi: this._jsonInterface, // explicitly not passing middleware so if some one is using old eth package it will not break - }) : - sendTransaction(this, tx, this.defaultReturnFormat, { - // TODO Should make this configurable by the user - checkRevertBeforeSending: false, - contractAbi: this._jsonInterface, - }, this.transactionMiddleware); + const transactionToSend = isNullish(this.transactionMiddleware) + ? sendTransaction(this, tx, this.defaultReturnFormat, { + // TODO Should make this configurable by the user + checkRevertBeforeSending: false, + contractAbi: this._jsonInterface, // explicitly not passing middleware so if some one is using old eth package it will not break + }) + : sendTransaction( + this, + tx, + this.defaultReturnFormat, + { + // TODO Should make this configurable by the user + checkRevertBeforeSending: false, + contractAbi: this._jsonInterface, + }, + this.transactionMiddleware, + ); // eslint-disable-next-line no-void void transactionToSend.on('error', (error: unknown) => { @@ -1450,48 +1350,7 @@ export class Contract return transactionToSend; } - private _contractMethodDeploySend( - abi: AbiFunctionFragment, - params: unknown[], - options?: Options, - contractOptions?: ContractOptions, - ) { - let modifiedContractOptions = contractOptions ?? this.options; - modifiedContractOptions = { - ...modifiedContractOptions, - from: modifiedContractOptions.from ?? this.defaultAccount ?? undefined, - }; - const tx = getSendTxParams({ - abi, - params, - options: { ...options, dataInputFill: this.contractDataInputFill }, - contractOptions: modifiedContractOptions, - }); - - const returnTxOptions: SendTransactionOptions> = { - transactionResolver: (receipt: TransactionReceipt) => { - if (receipt.status === BigInt(0)) { - throw new Web3ContractError("code couldn't be stored", receipt); - } - - const newContract = this.clone(); - - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - newContract.options.address = receipt.contractAddress; - return newContract; - }, - contractAbi: this._jsonInterface, - // TODO Should make this configurable by the user - checkRevertBeforeSending: false, - }; - - return ( - (isNullish(this.transactionMiddleware)) ? - sendTransaction(this, tx, this.defaultReturnFormat, returnTxOptions) : // not calling this with undefined Middleware because it will not break if Eth package is not updated - sendTransaction(this, tx, this.defaultReturnFormat, returnTxOptions, this.transactionMiddleware)); - } - - private async _contractMethodEstimateGas< + public async contractMethodEstimateGas< Options extends PayableCallOptions | NonPayableCallOptions, ReturnFormat extends DataFormat, >({ @@ -1522,11 +1381,7 @@ export class Contract 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, @@ -1536,10 +1391,7 @@ export class Contract }, { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - subscriptionManager: this.subscriptionManager as Web3SubscriptionManager< - unknown, - any - >, + subscriptionManager: this.subscriptionManager as Web3SubscriptionManager, returnFormat, }, ); @@ -1552,10 +1404,7 @@ 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/src/index.ts b/packages/web3-eth-contract/src/index.ts index 09052f859a1..ad7b5ab7fb7 100644 --- a/packages/web3-eth-contract/src/index.ts +++ b/packages/web3-eth-contract/src/index.ts @@ -45,6 +45,7 @@ import { Contract } from './contract.js'; export * from './encoding.js'; export * from './contract.js'; +export * from './contract-deployer-method-class.js'; export * from './log_subscription.js'; export * from './types.js'; export * from './utils.js'; diff --git a/packages/web3-eth-contract/src/utils.ts b/packages/web3-eth-contract/src/utils.ts index 748203ffdf7..fc475a5a813 100644 --- a/packages/web3-eth-contract/src/utils.ts +++ b/packages/web3-eth-contract/src/utils.ts @@ -28,6 +28,7 @@ import { PayableCallOptions, ContractOptions, Numbers, + AbiConstructorFragment, } from 'web3-types'; import { isNullish, mergeDeep, isContractInitOptions, keccak256, toChecksumAddress, hexToNumber } from 'web3-utils'; import { isAddress, isHexString } from 'web3-validator'; @@ -36,7 +37,7 @@ import { Web3ContractContext } from './types.js'; const dataInputEncodeMethodHelper = ( txParams: TransactionCall | TransactionForAccessList, - abi: AbiFunctionFragment, + abi: AbiFunctionFragment | AbiConstructorFragment, params: unknown[], dataInputFill?: 'data' | 'input' | 'both', ): { data?: HexString; input?: HexString } => { @@ -60,7 +61,7 @@ export const getSendTxParams = ({ options, contractOptions, }: { - abi: AbiFunctionFragment; + abi: AbiFunctionFragment | AbiConstructorFragment; params: unknown[]; options?: (PayableCallOptions | NonPayableCallOptions) & { input?: HexString; From e746566d4e150787e48bd5ff93e40d21b3b72086 Mon Sep 17 00:00:00 2001 From: Junaid <86780488+jdevcs@users.noreply.github.com> Date: Thu, 22 Aug 2024 18:05:29 +0200 Subject: [PATCH 137/186] Release/4.12.0 (#7207) * changelog updates * version bumps * change log update --- CHANGELOG.md | 39 +++++++++++++++++--- packages/web3-core/CHANGELOG.md | 4 ++- packages/web3-core/package.json | 12 +++---- packages/web3-errors/CHANGELOG.md | 6 ++-- packages/web3-errors/package.json | 2 +- packages/web3-eth-accounts/CHANGELOG.md | 5 ++- packages/web3-eth-accounts/package.json | 4 +-- packages/web3-eth-contract/CHANGELOG.md | 4 ++- packages/web3-eth-contract/package.json | 10 +++--- packages/web3-providers-http/CHANGELOG.md | 6 ++-- packages/web3-providers-http/package.json | 8 ++--- packages/web3-rpc-providers/CHANGELOG.md | 6 ++-- packages/web3-rpc-providers/package.json | 6 ++-- packages/web3/CHANGELOG.md | 43 +++++++++++++++++++++++ packages/web3/package.json | 14 ++++---- packages/web3/src/version.ts | 2 +- 16 files changed, 128 insertions(+), 43 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 081fb17b6c5..f1d03c99583 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2563,8 +2563,6 @@ If there are any bugs, improvements, optimizations or any new feature proposal f - `getName` reverse resolution -## [Unreleased] - ### Fixed #### web3-eth @@ -2648,16 +2646,47 @@ If there are any bugs, improvements, optimizations or any new feature proposal f - Remove redundant constructor of contractBuilder (#7150) -## [Unreleased] + +## [4.12.0] ### Fixed -#### web3-utils +#### web3-core + +- `setConfig()` fix for `setMaxListenerWarningThreshold` fix (#5079) + +#### web3-eth-accounts -- Fixed format schema with `oneOf` doesn't work correctly (#7055) +- Fix `TransactionFactory.registerTransactionType` not working, if there is a version mistatch between `web3-eth` and `web3-eth-accounts` by saving `extraTxTypes` at `globals`. (#7197) ### Added #### web3-eth-accounts - Added public function `signMessageWithPrivateKey` (#7174) + +#### web3-eth-contract + +- Added `populateTransaction` to the `contract.deploy(...)` properties. (#7197) + +#### web3-providers-http + +- Added `statusCode` of response in ResponseError, `statusCode` is optional property in ResponseError. + +#### web3-rpc-providers + +- Updated rate limit error of QuickNode provider for HTTP transport +- Added optional `HttpProviderOptions | SocketOptions` in `Web3ExternalProvider` and `QuickNodeProvider` for provider configs + +#### web3-errors + +- Added optional `statusCode` property of response in ResponseError. + +### Changed + +#### web3-eth-contract + +- The returnred properties of `contract.deploy(...)` are structured with a newly created class named `DeployerMethodClass`. (#7197) +- Add a missed accepted type for the `abi` parameter, at `dataInputEncodeMethodHelper` and `getSendTxParams`. (#7197) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-core/CHANGELOG.md b/packages/web3-core/CHANGELOG.md index 8f61b018479..2864dbd4d8d 100644 --- a/packages/web3-core/CHANGELOG.md +++ b/packages/web3-core/CHANGELOG.md @@ -227,8 +227,10 @@ Documentation: - Now when existing packages are added in web3, will be avalible for plugins via context. (#7088) -## [Unreleased] +## [4.5.1] ### Fixed - `setConfig()` fix for `setMaxListenerWarningThreshold` fix (#5079) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-core/package.json b/packages/web3-core/package.json index a619cfbbc1c..ad4f8d94b83 100644 --- a/packages/web3-core/package.json +++ b/packages/web3-core/package.json @@ -1,6 +1,6 @@ { "name": "web3-core", - "version": "4.5.0", + "version": "4.5.1", "description": "Web3 core tools for sub-packages. This is an internal package.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -42,13 +42,13 @@ "test:integration": "jest --config=./test/integration/jest.config.js --passWithNoTests" }, "dependencies": { - "web3-errors": "^1.2.0", - "web3-eth-accounts": "^4.1.2", + "web3-errors": "^1.3.0", + "web3-eth-accounts": "^4.2.0", "web3-eth-iban": "^4.0.7", - "web3-providers-http": "^4.1.0", - "web3-providers-ws": "^4.0.7", + "web3-providers-http": "^4.2.0", + "web3-providers-ws": "^4.0.8", "web3-types": "^1.7.0", - "web3-utils": "^4.3.0", + "web3-utils": "^4.3.1", "web3-validator": "^2.0.6" }, "optionalDependencies": { diff --git a/packages/web3-errors/CHANGELOG.md b/packages/web3-errors/CHANGELOG.md index 6dbdd143e42..47cb02f3cd3 100644 --- a/packages/web3-errors/CHANGELOG.md +++ b/packages/web3-errors/CHANGELOG.md @@ -178,8 +178,10 @@ Documentation: - Fixed the undefined data in `Eip838ExecutionError` constructor (#6905) -## [Unreleased] +## [1.3.0] ### Added -- Added optional `statusCode` property of response in ResponseError. \ No newline at end of file +- Added optional `statusCode` property of response in ResponseError. + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-errors/package.json b/packages/web3-errors/package.json index 4d382b35716..c20818ca8a2 100644 --- a/packages/web3-errors/package.json +++ b/packages/web3-errors/package.json @@ -1,6 +1,6 @@ { "name": "web3-errors", - "version": "1.2.1", + "version": "1.3.0", "description": "This package has web3 error classes", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", diff --git a/packages/web3-eth-accounts/CHANGELOG.md b/packages/web3-eth-accounts/CHANGELOG.md index b682b5e34bb..5562856ff53 100644 --- a/packages/web3-eth-accounts/CHANGELOG.md +++ b/packages/web3-eth-accounts/CHANGELOG.md @@ -168,10 +168,13 @@ Documentation: - baseTransaction method updated (#7095) -## [Unreleased] +## [4.2.0] + ### Added - Added public function `signMessageWithPrivateKey` (#7174) ### Fixed - Fix `TransactionFactory.registerTransactionType` not working, if there is a version mistatch between `web3-eth` and `web3-eth-accounts` by saving `extraTxTypes` at `globals`. (#7197) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-eth-accounts/package.json b/packages/web3-eth-accounts/package.json index aa25f89a5dd..e7d1f029aaf 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.3", + "version": "4.2.0", "description": "Package for managing Ethereum accounts and signing", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -61,7 +61,7 @@ "@ethereumjs/rlp": "^4.0.1", "crc-32": "^1.2.2", "ethereum-cryptography": "^2.0.0", - "web3-errors": "^1.2.0", + "web3-errors": "^1.3.0", "web3-types": "^1.7.0", "web3-utils": "^4.3.1", "web3-validator": "^2.0.6" diff --git a/packages/web3-eth-contract/CHANGELOG.md b/packages/web3-eth-contract/CHANGELOG.md index 01e6f2f8a68..0d8310b9832 100644 --- a/packages/web3-eth-contract/CHANGELOG.md +++ b/packages/web3-eth-contract/CHANGELOG.md @@ -393,7 +393,7 @@ Documentation: - `populateTransaction` was added to contract methods (#7124) - Contract has `setTransactionMiddleware` and `getTransactionMiddleware` for automatically passing to `sentTransaction` for `deploy` and `send` functions (#7138) -## [Unreleased] +## [4.7.0] ### Added @@ -403,3 +403,5 @@ Documentation: - The returnred properties of `contract.deploy(...)` are structured with a newly created class named `DeployerMethodClass`. (#7197) - Add a missed accepted type for the `abi` parameter, at `dataInputEncodeMethodHelper` and `getSendTxParams`. (#7197) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-eth-contract/package.json b/packages/web3-eth-contract/package.json index dcee58738b4..237e1cec48b 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.6.0", + "version": "4.7.0", "description": "Web3 module to interact with Ethereum smart contracts.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -46,9 +46,9 @@ }, "dependencies": { "@ethereumjs/rlp": "^5.0.2", - "web3-core": "^4.5.0", - "web3-errors": "^1.2.0", - "web3-eth": "^4.8.1", + "web3-core": "^4.5.1", + "web3-errors": "^1.3.0", + "web3-eth": "^4.8.2", "web3-eth-abi": "^4.2.3", "web3-types": "^1.7.0", "web3-utils": "^4.3.1", @@ -69,7 +69,7 @@ "prettier": "^2.7.1", "ts-jest": "^29.1.1", "typescript": "^4.7.4", - "web3-eth-accounts": "^4.1.3", + "web3-eth-accounts": "^4.2.0", "web3-providers-ws": "^4.0.8" } } diff --git a/packages/web3-providers-http/CHANGELOG.md b/packages/web3-providers-http/CHANGELOG.md index dd20cddf35a..2169826c339 100644 --- a/packages/web3-providers-http/CHANGELOG.md +++ b/packages/web3-providers-http/CHANGELOG.md @@ -129,8 +129,10 @@ Documentation: - Fix issue lquixada/cross-fetch#78, enabling to run web3.js in service worker (#6463) -## [Unreleased] +## [4.2.0] ### Added -- Added `statusCode` of response in ResponseError, `statusCode` is optional property in ResponseError. \ No newline at end of file +- Added `statusCode` of response in ResponseError, `statusCode` is optional property in ResponseError. + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-providers-http/package.json b/packages/web3-providers-http/package.json index 75cf3529945..c94d24177e8 100644 --- a/packages/web3-providers-http/package.json +++ b/packages/web3-providers-http/package.json @@ -1,6 +1,6 @@ { "name": "web3-providers-http", - "version": "4.1.0", + "version": "4.2.0", "description": "HTTP provider for Web3 4.x.x", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -61,8 +61,8 @@ }, "dependencies": { "cross-fetch": "^4.0.0", - "web3-errors": "^1.1.3", - "web3-types": "^1.3.0", - "web3-utils": "^4.0.7" + "web3-errors": "^1.3.0", + "web3-types": "^1.7.0", + "web3-utils": "^4.3.1" } } diff --git a/packages/web3-rpc-providers/CHANGELOG.md b/packages/web3-rpc-providers/CHANGELOG.md index d07ba9124a4..4943590a855 100644 --- a/packages/web3-rpc-providers/CHANGELOG.md +++ b/packages/web3-rpc-providers/CHANGELOG.md @@ -51,9 +51,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Change request return type `Promise` to `Promise>` (#7102) -## [Unreleased] +## [1.0.0-rc.2] ### Added - Updated rate limit error of QuickNode provider for HTTP transport -- Added optional `HttpProviderOptions | SocketOptions` in `Web3ExternalProvider` and `QuickNodeProvider` for provider configs \ No newline at end of file +- Added optional `HttpProviderOptions | SocketOptions` in `Web3ExternalProvider` and `QuickNodeProvider` for provider configs + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-rpc-providers/package.json b/packages/web3-rpc-providers/package.json index 3d66382ff51..91da2144b40 100644 --- a/packages/web3-rpc-providers/package.json +++ b/packages/web3-rpc-providers/package.json @@ -1,6 +1,6 @@ { "name": "web3-rpc-providers", - "version": "1.0.0-rc.1", + "version": "1.0.0-rc.2", "description": "Web3 Providers package", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -57,8 +57,8 @@ "typescript": "^4.7.4" }, "dependencies": { - "web3-errors": "^1.2.0", - "web3-providers-http": "^4.1.0", + "web3-errors": "^1.3.0", + "web3-providers-http": "^4.2.0", "web3-providers-ws": "^4.0.8", "web3-types": "^1.7.0", "web3-utils": "^4.3.1", diff --git a/packages/web3/CHANGELOG.md b/packages/web3/CHANGELOG.md index e8b2d5c705a..a4a54471549 100644 --- a/packages/web3/CHANGELOG.md +++ b/packages/web3/CHANGELOG.md @@ -436,4 +436,47 @@ Documentation: - Remove redundant constructor of contractBuilder (#7150) + +## [4.12.0] + +### Fixed + +#### web3-core + +- `setConfig()` fix for `setMaxListenerWarningThreshold` fix (#5079) + +#### web3-eth-accounts + +- Fix `TransactionFactory.registerTransactionType` not working, if there is a version mistatch between `web3-eth` and `web3-eth-accounts` by saving `extraTxTypes` at `globals`. (#7197) + +### Added + +#### web3-eth-accounts + +- Added public function `signMessageWithPrivateKey` (#7174) + +#### web3-eth-contract + +- Added `populateTransaction` to the `contract.deploy(...)` properties. (#7197) + +#### web3-providers-http + +- Added `statusCode` of response in ResponseError, `statusCode` is optional property in ResponseError. + +#### web3-rpc-providers + +- Updated rate limit error of QuickNode provider for HTTP transport +- Added optional `HttpProviderOptions | SocketOptions` in `Web3ExternalProvider` and `QuickNodeProvider` for provider configs + +#### web3-errors + +- Added optional `statusCode` property of response in ResponseError. + +### Changed + +#### web3-eth-contract + +- The returnred properties of `contract.deploy(...)` are structured with a newly created class named `DeployerMethodClass`. (#7197) +- Add a missed accepted type for the `abi` parameter, at `dataInputEncodeMethodHelper` and `getSendTxParams`. (#7197) + ## [Unreleased] \ No newline at end of file diff --git a/packages/web3/package.json b/packages/web3/package.json index 5740fcc04f4..40851d73a3e 100644 --- a/packages/web3/package.json +++ b/packages/web3/package.json @@ -1,6 +1,6 @@ { "name": "web3", - "version": "4.11.1", + "version": "4.12.0", "description": "Ethereum JavaScript API", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -86,20 +86,20 @@ "web3-providers-ipc": "^4.0.7" }, "dependencies": { - "web3-core": "^4.5.0", - "web3-errors": "^1.2.1", + "web3-core": "^4.5.1", + "web3-errors": "^1.3.0", "web3-eth": "^4.8.2", "web3-eth-abi": "^4.2.3", - "web3-eth-accounts": "^4.1.3", - "web3-eth-contract": "^4.6.0", + "web3-eth-accounts": "^4.2.0", + "web3-eth-contract": "^4.7.0", "web3-eth-ens": "^4.4.0", "web3-eth-iban": "^4.0.7", "web3-eth-personal": "^4.0.8", "web3-net": "^4.1.0", - "web3-providers-http": "^4.1.0", + "web3-providers-http": "^4.2.0", "web3-providers-ws": "^4.0.8", "web3-rpc-methods": "^1.3.0", - "web3-rpc-providers": "^1.0.0-rc.1", + "web3-rpc-providers": "^1.0.0-rc.2", "web3-types": "^1.7.0", "web3-utils": "^4.3.1", "web3-validator": "^2.0.6" diff --git a/packages/web3/src/version.ts b/packages/web3/src/version.ts index 268f69fed23..c77bf5eab2c 100644 --- a/packages/web3/src/version.ts +++ b/packages/web3/src/version.ts @@ -1 +1 @@ -/* eslint-disable header/header */ export const Web3PkgInfo = { version: '4.11.1' }; +/* eslint-disable header/header */ export const Web3PkgInfo = { version: '4.12.0' }; From 0b7558969cecfd7600be9a336ac7f157b6cf6c76 Mon Sep 17 00:00:00 2001 From: Oleksii Kosynskyi Date: Fri, 23 Aug 2024 10:20:56 +0300 Subject: [PATCH 138/186] Fix nextjs problem (#7216) * Fix nextjs problem * add changelog --- CHANGELOG.md | 7 ++++++- packages/web3-eth-accounts/CHANGELOG.md | 6 +++++- .../web3-eth-accounts/src/tx/transactionFactory.ts | 12 ++---------- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f1d03c99583..76a773377c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2689,4 +2689,9 @@ If there are any bugs, improvements, optimizations or any new feature proposal f - The returnred properties of `contract.deploy(...)` are structured with a newly created class named `DeployerMethodClass`. (#7197) - Add a missed accepted type for the `abi` parameter, at `dataInputEncodeMethodHelper` and `getSendTxParams`. (#7197) -## [Unreleased] \ No newline at end of file +## [Unreleased] +### Fixed + +#### web3-eth-accounts + +- Revert `TransactionFactory.registerTransactionType` if there is a version mistatch between `web3-eth` and `web3-eth-accounts` and fix nextjs problem. (#7216) diff --git a/packages/web3-eth-accounts/CHANGELOG.md b/packages/web3-eth-accounts/CHANGELOG.md index 5562856ff53..d800a7663f6 100644 --- a/packages/web3-eth-accounts/CHANGELOG.md +++ b/packages/web3-eth-accounts/CHANGELOG.md @@ -177,4 +177,8 @@ Documentation: ### Fixed - Fix `TransactionFactory.registerTransactionType` not working, if there is a version mistatch between `web3-eth` and `web3-eth-accounts` by saving `extraTxTypes` at `globals`. (#7197) -## [Unreleased] \ No newline at end of file +## [Unreleased] + +### Fixed +- Revert `TransactionFactory.registerTransactionType` if there is a version mistatch between `web3-eth` and `web3-eth-accounts` and fix nextjs problem. (#7216) + diff --git a/packages/web3-eth-accounts/src/tx/transactionFactory.ts b/packages/web3-eth-accounts/src/tx/transactionFactory.ts index 98a465c0973..7d3305ec59a 100644 --- a/packages/web3-eth-accounts/src/tx/transactionFactory.ts +++ b/packages/web3-eth-accounts/src/tx/transactionFactory.ts @@ -31,15 +31,7 @@ import type { } from './types.js'; import { BaseTransaction } from './baseTransaction.js'; -let extraTxTypes: Map>; -// use the global object, to work fine even if web3-eth and web3-eth-accounts was on a different versions: -const typedGlobal = global as unknown as {extraTxTypes: Map>} -if (!typedGlobal.extraTxTypes) { - extraTxTypes = new Map(); - typedGlobal.extraTxTypes = extraTxTypes; -} else { - extraTxTypes = typedGlobal.extraTxTypes; -} +const extraTxTypes: Map> = new Map(); // eslint-disable-next-line @typescript-eslint/no-extraneous-class export class TransactionFactory { @@ -145,7 +137,7 @@ export class TransactionFactory { */ public static fromBlockBodyData(data: Uint8Array | Uint8Array[], txOptions: TxOptions = {}) { if (isUint8Array(data)) { - return this.fromSerializedData(data , txOptions); + return this.fromSerializedData(data, txOptions); } if (Array.isArray(data)) { // It is a legacy transaction From f351e003f0649aeccee467f0a4dbcb124d0a90df Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 23 Aug 2024 04:29:59 -0400 Subject: [PATCH 139/186] hotfix to 4.12.1 (#7217) --- CHANGELOG.md | 5 ++++- packages/web3-eth-accounts/CHANGELOG.md | 3 ++- packages/web3-eth-accounts/package.json | 2 +- packages/web3/CHANGELOG.md | 8 ++++++++ packages/web3/package.json | 4 ++-- packages/web3/src/version.ts | 2 +- 6 files changed, 18 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 76a773377c1..4f2e5ea09b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2689,9 +2689,12 @@ If there are any bugs, improvements, optimizations or any new feature proposal f - The returnred properties of `contract.deploy(...)` are structured with a newly created class named `DeployerMethodClass`. (#7197) - Add a missed accepted type for the `abi` parameter, at `dataInputEncodeMethodHelper` and `getSendTxParams`. (#7197) -## [Unreleased] +## [4.12.1] + ### Fixed #### web3-eth-accounts - Revert `TransactionFactory.registerTransactionType` if there is a version mistatch between `web3-eth` and `web3-eth-accounts` and fix nextjs problem. (#7216) + +## [Unreleased] diff --git a/packages/web3-eth-accounts/CHANGELOG.md b/packages/web3-eth-accounts/CHANGELOG.md index d800a7663f6..5a9768477e5 100644 --- a/packages/web3-eth-accounts/CHANGELOG.md +++ b/packages/web3-eth-accounts/CHANGELOG.md @@ -177,8 +177,9 @@ Documentation: ### Fixed - Fix `TransactionFactory.registerTransactionType` not working, if there is a version mistatch between `web3-eth` and `web3-eth-accounts` by saving `extraTxTypes` at `globals`. (#7197) -## [Unreleased] +## [4.2.1] ### Fixed - Revert `TransactionFactory.registerTransactionType` if there is a version mistatch between `web3-eth` and `web3-eth-accounts` and fix nextjs problem. (#7216) +## [Unreleased] diff --git a/packages/web3-eth-accounts/package.json b/packages/web3-eth-accounts/package.json index e7d1f029aaf..cc411137242 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.2.0", + "version": "4.2.1", "description": "Package for managing Ethereum accounts and signing", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", diff --git a/packages/web3/CHANGELOG.md b/packages/web3/CHANGELOG.md index a4a54471549..d03dc239294 100644 --- a/packages/web3/CHANGELOG.md +++ b/packages/web3/CHANGELOG.md @@ -479,4 +479,12 @@ Documentation: - The returnred properties of `contract.deploy(...)` are structured with a newly created class named `DeployerMethodClass`. (#7197) - Add a missed accepted type for the `abi` parameter, at `dataInputEncodeMethodHelper` and `getSendTxParams`. (#7197) +## [4.12.1] + +### Fixed + +#### web3-eth-accounts + +- Revert `TransactionFactory.registerTransactionType` if there is a version mistatch between `web3-eth` and `web3-eth-accounts` and fix nextjs problem. (#7216) + ## [Unreleased] \ No newline at end of file diff --git a/packages/web3/package.json b/packages/web3/package.json index 40851d73a3e..657a261c6ac 100644 --- a/packages/web3/package.json +++ b/packages/web3/package.json @@ -1,6 +1,6 @@ { "name": "web3", - "version": "4.12.0", + "version": "4.12.1", "description": "Ethereum JavaScript API", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -90,7 +90,7 @@ "web3-errors": "^1.3.0", "web3-eth": "^4.8.2", "web3-eth-abi": "^4.2.3", - "web3-eth-accounts": "^4.2.0", + "web3-eth-accounts": "^4.2.1", "web3-eth-contract": "^4.7.0", "web3-eth-ens": "^4.4.0", "web3-eth-iban": "^4.0.7", diff --git a/packages/web3/src/version.ts b/packages/web3/src/version.ts index c77bf5eab2c..e49fd40bc26 100644 --- a/packages/web3/src/version.ts +++ b/packages/web3/src/version.ts @@ -1 +1 @@ -/* eslint-disable header/header */ export const Web3PkgInfo = { version: '4.12.0' }; +/* eslint-disable header/header */ export const Web3PkgInfo = { version: '4.12.1' }; From 9b322052ef266cc57b29080b20053991e0c9a0a9 Mon Sep 17 00:00:00 2001 From: Junaid <86780488+jdevcs@users.noreply.github.com> Date: Wed, 28 Aug 2024 10:39:53 +0200 Subject: [PATCH 140/186] unit tests update (#7221) * timeout update * fixed lockfile deps * timout in setup.js * continue v18 if err on v20 * node 20.17.0 * update nodev * specific ver --- .github/workflows/build.yml | 7 ++++--- packages/web3-core/test/config/jest.config.js | 1 + packages/web3-eth-abi/test/config/jest.config.js | 1 + packages/web3-eth-contract/test/config/jest.config.js | 1 + packages/web3-eth-ens/test/integration/setup.js | 3 --- packages/web3-eth-personal/test/config/jest.config.js | 1 + packages/web3-eth/test/e2e/setup.js | 3 --- packages/web3-net/test/config/jest.config.js | 1 + packages/web3-providers-ipc/test/config/jest.config.js | 1 + packages/web3-types/test/config/jest.config.js | 1 + packages/web3-utils/test/config/jest.config.js | 1 + packages/web3-validator/test/config/jest.config.js | 1 + packages/web3/test/config/jest.config.js | 1 + packages/web3/test/e2e/setup.js | 3 --- packages/web3/test/integration/setup.js | 3 --- packages/web3/test/stress/setup.js | 3 --- templates/jest.config.js.tmpl | 1 + 17 files changed, 15 insertions(+), 18 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index dd1279159b7..b8c0f6647fd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,7 +14,7 @@ jobs: build: strategy: matrix: - node: [18, 20] + node: ['18', '20.17.0'] name: Build CJS runs-on: ubuntu-latest steps: @@ -23,7 +23,7 @@ jobs: with: node-version: ${{ matrix.node }} cache: yarn - - run: yarn install --ignore-scripts + - run: yarn install --ignore-scripts --frozen-lockfile - run: npx ts-node scripts/init.ts - run: yarn build:cjs - uses: actions/cache/save@v4 @@ -165,7 +165,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node: [18, 20] + node: ['18', '20.17.0'] steps: - uses: actions/setup-node@v4 with: @@ -176,6 +176,7 @@ jobs: path: ./ key: web3-${{ matrix.node }}-${{github.sha}} - run: yarn test:unit + continue-on-error: ${{ matrix.node == '20.17.0' }} - name: Upload coverage to Codecov uses: codecov/codecov-action@v3 with: diff --git a/packages/web3-core/test/config/jest.config.js b/packages/web3-core/test/config/jest.config.js index 74597df99d0..28d62955096 100644 --- a/packages/web3-core/test/config/jest.config.js +++ b/packages/web3-core/test/config/jest.config.js @@ -40,4 +40,5 @@ module.exports = { * This can be done programmatically using jest.resetModules(). */ resetModules: true, + testTimeout: 600000, }; diff --git a/packages/web3-eth-abi/test/config/jest.config.js b/packages/web3-eth-abi/test/config/jest.config.js index 74597df99d0..28d62955096 100644 --- a/packages/web3-eth-abi/test/config/jest.config.js +++ b/packages/web3-eth-abi/test/config/jest.config.js @@ -40,4 +40,5 @@ module.exports = { * This can be done programmatically using jest.resetModules(). */ resetModules: true, + testTimeout: 600000, }; diff --git a/packages/web3-eth-contract/test/config/jest.config.js b/packages/web3-eth-contract/test/config/jest.config.js index 74597df99d0..28d62955096 100644 --- a/packages/web3-eth-contract/test/config/jest.config.js +++ b/packages/web3-eth-contract/test/config/jest.config.js @@ -40,4 +40,5 @@ module.exports = { * This can be done programmatically using jest.resetModules(). */ resetModules: true, + testTimeout: 600000, }; diff --git a/packages/web3-eth-ens/test/integration/setup.js b/packages/web3-eth-ens/test/integration/setup.js index 59b1f904213..c480060944a 100644 --- a/packages/web3-eth-ens/test/integration/setup.js +++ b/packages/web3-eth-ens/test/integration/setup.js @@ -19,6 +19,3 @@ along with web3.js. If not, see . // eslint-disable-next-line @typescript-eslint/no-require-imports require('../config/setup'); -const jestTimeout = 30000; - -jest.setTimeout(jestTimeout); diff --git a/packages/web3-eth-personal/test/config/jest.config.js b/packages/web3-eth-personal/test/config/jest.config.js index 74597df99d0..28d62955096 100644 --- a/packages/web3-eth-personal/test/config/jest.config.js +++ b/packages/web3-eth-personal/test/config/jest.config.js @@ -40,4 +40,5 @@ module.exports = { * This can be done programmatically using jest.resetModules(). */ resetModules: true, + testTimeout: 600000, }; diff --git a/packages/web3-eth/test/e2e/setup.js b/packages/web3-eth/test/e2e/setup.js index fddbec59a1e..c480060944a 100644 --- a/packages/web3-eth/test/e2e/setup.js +++ b/packages/web3-eth/test/e2e/setup.js @@ -19,6 +19,3 @@ along with web3.js. If not, see . // eslint-disable-next-line @typescript-eslint/no-require-imports require('../config/setup'); -const jestTimeout = 30000; // Sometimes `in3` takes long time because of its decentralized nature. - -jest.setTimeout(jestTimeout); diff --git a/packages/web3-net/test/config/jest.config.js b/packages/web3-net/test/config/jest.config.js index 74597df99d0..28d62955096 100644 --- a/packages/web3-net/test/config/jest.config.js +++ b/packages/web3-net/test/config/jest.config.js @@ -40,4 +40,5 @@ module.exports = { * This can be done programmatically using jest.resetModules(). */ resetModules: true, + testTimeout: 600000, }; diff --git a/packages/web3-providers-ipc/test/config/jest.config.js b/packages/web3-providers-ipc/test/config/jest.config.js index 068de35aa8e..5fc38b688f1 100644 --- a/packages/web3-providers-ipc/test/config/jest.config.js +++ b/packages/web3-providers-ipc/test/config/jest.config.js @@ -42,4 +42,5 @@ module.exports = { resetModules: true, resetMocks: true, + testTimeout: 600000, }; diff --git a/packages/web3-types/test/config/jest.config.js b/packages/web3-types/test/config/jest.config.js index 7d959c45719..360e22458fb 100644 --- a/packages/web3-types/test/config/jest.config.js +++ b/packages/web3-types/test/config/jest.config.js @@ -37,4 +37,5 @@ module.exports = { * This can be done programmatically using jest.resetModules(). */ resetModules: true, + testTimeout: 600000, }; diff --git a/packages/web3-utils/test/config/jest.config.js b/packages/web3-utils/test/config/jest.config.js index 74597df99d0..28d62955096 100644 --- a/packages/web3-utils/test/config/jest.config.js +++ b/packages/web3-utils/test/config/jest.config.js @@ -40,4 +40,5 @@ module.exports = { * This can be done programmatically using jest.resetModules(). */ resetModules: true, + testTimeout: 600000, }; diff --git a/packages/web3-validator/test/config/jest.config.js b/packages/web3-validator/test/config/jest.config.js index 74597df99d0..28d62955096 100644 --- a/packages/web3-validator/test/config/jest.config.js +++ b/packages/web3-validator/test/config/jest.config.js @@ -40,4 +40,5 @@ module.exports = { * This can be done programmatically using jest.resetModules(). */ resetModules: true, + testTimeout: 600000, }; diff --git a/packages/web3/test/config/jest.config.js b/packages/web3/test/config/jest.config.js index 74597df99d0..d61c13316fa 100644 --- a/packages/web3/test/config/jest.config.js +++ b/packages/web3/test/config/jest.config.js @@ -40,4 +40,5 @@ module.exports = { * This can be done programmatically using jest.resetModules(). */ resetModules: true, + testTimeout: 600000, }; diff --git a/packages/web3/test/e2e/setup.js b/packages/web3/test/e2e/setup.js index fddbec59a1e..c480060944a 100644 --- a/packages/web3/test/e2e/setup.js +++ b/packages/web3/test/e2e/setup.js @@ -19,6 +19,3 @@ along with web3.js. If not, see . // eslint-disable-next-line @typescript-eslint/no-require-imports require('../config/setup'); -const jestTimeout = 30000; // Sometimes `in3` takes long time because of its decentralized nature. - -jest.setTimeout(jestTimeout); diff --git a/packages/web3/test/integration/setup.js b/packages/web3/test/integration/setup.js index fddbec59a1e..c480060944a 100644 --- a/packages/web3/test/integration/setup.js +++ b/packages/web3/test/integration/setup.js @@ -19,6 +19,3 @@ along with web3.js. If not, see . // eslint-disable-next-line @typescript-eslint/no-require-imports require('../config/setup'); -const jestTimeout = 30000; // Sometimes `in3` takes long time because of its decentralized nature. - -jest.setTimeout(jestTimeout); diff --git a/packages/web3/test/stress/setup.js b/packages/web3/test/stress/setup.js index e9757a61e1c..c480060944a 100644 --- a/packages/web3/test/stress/setup.js +++ b/packages/web3/test/stress/setup.js @@ -19,6 +19,3 @@ along with web3.js. If not, see . // eslint-disable-next-line @typescript-eslint/no-require-imports require('../config/setup'); -const jestTimeout = 300000; - -jest.setTimeout(jestTimeout); diff --git a/templates/jest.config.js.tmpl b/templates/jest.config.js.tmpl index e4d70e55a94..d8144cd41e9 100644 --- a/templates/jest.config.js.tmpl +++ b/templates/jest.config.js.tmpl @@ -57,4 +57,5 @@ module.exports = { * This can be done programmatically using jest.resetModules(). */ resetModules: true, + testTimeout: 600000, }; From 7a6e49200949325f69a05b3bf465ce64eb41bb8d Mon Sep 17 00:00:00 2001 From: Muhammad Altabba <24407834+Muhammad-Altabba@users.noreply.github.com> Date: Thu, 5 Sep 2024 16:09:32 +0200 Subject: [PATCH 141/186] Handle common cases for smart contract errors according to EIP 838 (#7155) * handle smart contracts errors `Error(string)` and `Panic(uint256)` * add tests * update CHANGELOG.md --- packages/web3-eth-abi/CHANGELOG.md | 5 ++- .../src/decode_contract_error_data.ts | 30 ++++++++++++++++ packages/web3-eth-abi/test/fixtures/data.ts | 34 +++++++++++++++++++ .../test/unit/decodeContractErrorData.test.ts | 8 ++++- 4 files changed, 75 insertions(+), 2 deletions(-) diff --git a/packages/web3-eth-abi/CHANGELOG.md b/packages/web3-eth-abi/CHANGELOG.md index 6d04047ddef..1bb5910ba18 100644 --- a/packages/web3-eth-abi/CHANGELOG.md +++ b/packages/web3-eth-abi/CHANGELOG.md @@ -182,4 +182,7 @@ Documentation: - fix encodedata in EIP-712 (#7095) -## [Unreleased] \ No newline at end of file +## [Unreleased] + +### Added +- Handle common cases for smart contract errors according to EIP 838: `0x4e487b71` which is the ‘selector’ for `Panic(uint256)` and `0x08c379a0` is the ‘selector’ of `Error(string)`. (7155) diff --git a/packages/web3-eth-abi/src/decode_contract_error_data.ts b/packages/web3-eth-abi/src/decode_contract_error_data.ts index 98eb02d4fd8..11566b79645 100644 --- a/packages/web3-eth-abi/src/decode_contract_error_data.ts +++ b/packages/web3-eth-abi/src/decode_contract_error_data.ts @@ -39,6 +39,36 @@ export const decodeContractErrorData = ( errorSignature = jsonInterfaceMethodToString(errorAbi); // decode abi.inputs according to EIP-838 errorArgs = decodeParameters([...errorAbi.inputs], error.data.substring(10)); + } else if (error.data.startsWith('0x08c379a0')) { + // If ABI was not provided, check for the 2 famous errors: 'Error(string)' or 'Panic(uint256)' + + errorName = 'Error'; + errorSignature = 'Error(string)'; + // decode abi.inputs according to EIP-838 + errorArgs = decodeParameters( + [ + { + name: 'message', + type: 'string', + }, + ], + error.data.substring(10), + ); + } else if (error.data.startsWith('0x4e487b71')) { + errorName = 'Panic'; + errorSignature = 'Panic(uint256)'; + // decode abi.inputs according to EIP-838 + errorArgs = decodeParameters( + [ + { + name: 'code', + type: 'uint256', + }, + ], + error.data.substring(10), + ); + } else { + console.error('No matching error abi found for error data', error.data); } } catch (err) { console.error(err); diff --git a/packages/web3-eth-abi/test/fixtures/data.ts b/packages/web3-eth-abi/test/fixtures/data.ts index 0fe90638f95..f8990a22e86 100644 --- a/packages/web3-eth-abi/test/fixtures/data.ts +++ b/packages/web3-eth-abi/test/fixtures/data.ts @@ -974,6 +974,40 @@ export const validDecodeContractErrorData: { input: any[]; output: any; }[] = [ + { + input: [ + [], + { + code: 12, + message: 'message', + data: '0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000155468697320697320612063616c6c207265766572740000000000000000000000', + }, + ], + output: { + errorName: 'Error', + errorSignature: 'Error(string)', + errorArgs: { + message: 'This is a call revert', + }, + }, + }, + { + input: [ + [], + { + code: 12, + message: 'message', + data: '0x4e487b71000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000', + }, + ], + output: { + errorName: 'Panic', + errorSignature: 'Panic(uint256)', + errorArgs: { + code: 42, + }, + }, + }, { input: [ [ diff --git a/packages/web3-eth-abi/test/unit/decodeContractErrorData.test.ts b/packages/web3-eth-abi/test/unit/decodeContractErrorData.test.ts index 3f6a624ef22..9e99add02f3 100644 --- a/packages/web3-eth-abi/test/unit/decodeContractErrorData.test.ts +++ b/packages/web3-eth-abi/test/unit/decodeContractErrorData.test.ts @@ -32,7 +32,13 @@ describe('decodeContractErrorData', () => { expect(err.errorName).toEqual(output.errorName); expect(err.errorSignature).toEqual(output.errorSignature); expect(err.errorArgs?.message).toEqual(output.errorArgs?.message); - expect(Number(err.errorArgs?.code)).toEqual(output.errorArgs?.code); + + // This ensures they are equal if one was provided + // It also skips if both are not provided + if (err.errorArgs?.code || output.errorArgs?.code) { + // eslint-disable-next-line jest/no-conditional-expect + expect(Number(err.errorArgs?.code)).toEqual(output.errorArgs?.code); + } expect(err.cause?.code).toEqual(output.cause?.code); }, ); From 75df2677caa955ed3d62eac18e3c6a1fad2103b7 Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Mon, 9 Sep 2024 06:39:29 -0700 Subject: [PATCH 142/186] feat(docs): upgrade-bn (#7232) Add a section in "Upgrade from 1.x" for `BN` vs `BigInt` Closes #6705 --- .../1.x/web3_utils_migration_guide.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/docs/guides/web3_upgrade_guide/1.x/web3_utils_migration_guide.md b/docs/docs/guides/web3_upgrade_guide/1.x/web3_utils_migration_guide.md index 0b977890e6e..5282b720823 100644 --- a/docs/docs/guides/web3_upgrade_guide/1.x/web3_utils_migration_guide.md +++ b/docs/docs/guides/web3_upgrade_guide/1.x/web3_utils_migration_guide.md @@ -17,6 +17,18 @@ import web3Utils from 'web3-utils'; import * as web3Utils from 'web3-utils'; ``` +## No `BN` property + +The `web3-utils` package no longer includes a `BN` property for using the [the `bn.js` package](https://github.com/indutny/bn.js/) for working with (big) numbers. In 4.x, [the native JavaScript `BigInt` type](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) is used. + +```ts +// 1.x +new Web3.utils.BN(1); + +// 4.x +BigInt(4); +``` + ## Unit conversion functions The `toWei` does not have an optional second parameter. You have to pass the source unit explicitly. From 2f2424487a6ba2865b5a381f22f83500a3133cda Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Mon, 9 Sep 2024 06:53:01 -0700 Subject: [PATCH 143/186] feat(requestEIP6963Providers): return-type (#7239) * feat(requestEIP6963Providers): return-type Add return type to requestEIP6963Providers function signature. Closes #7238 * Update Changelog --- CHANGELOG.md | 4 ++++ packages/web3/src/web3_eip6963.ts | 8 +++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f2e5ea09b0..48117f4e47c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2697,4 +2697,8 @@ If there are any bugs, improvements, optimizations or any new feature proposal f - Revert `TransactionFactory.registerTransactionType` if there is a version mistatch between `web3-eth` and `web3-eth-accounts` and fix nextjs problem. (#7216) +#### web3 + +- `Web3.providers` namespace exports `type EIP6963ProviderResponse = Map`. Return type for the static `Web3.requestEIP6963Providers` is now `Promise`. (#7239) + ## [Unreleased] diff --git a/packages/web3/src/web3_eip6963.ts b/packages/web3/src/web3_eip6963.ts index 787502a4125..d2169191b5c 100644 --- a/packages/web3/src/web3_eip6963.ts +++ b/packages/web3/src/web3_eip6963.ts @@ -35,6 +35,8 @@ export interface EIP6963ProviderDetail { provider: EIP1193Provider; } +export type EIP6963ProviderResponse = Map; + export interface EIP6963AnnounceProviderEvent extends CustomEvent { type: Eip6963EventName.eip6963announceProvider; detail: EIP6963ProviderDetail; @@ -44,15 +46,15 @@ export interface EIP6963RequestProviderEvent extends Event { type: Eip6963EventName.eip6963requestProvider; } -export const eip6963ProvidersMap: Map = new Map(); +export const eip6963ProvidersMap: EIP6963ProviderResponse = new Map(); export const web3ProvidersMapUpdated = "web3:providersMapUpdated"; export interface EIP6963ProvidersMapUpdateEvent extends CustomEvent { type: string; - detail: Map; + detail: EIP6963ProviderResponse; } -export const requestEIP6963Providers = async () => +export const requestEIP6963Providers = async (): Promise => new Promise((resolve, reject) => { if (typeof window === 'undefined') { reject(new Error("window object not available, EIP-6963 is intended to be used within a browser")); From 973ee809d48a96441cbfd502f12915dcc0cb5dad Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Mon, 9 Sep 2024 07:20:04 -0700 Subject: [PATCH 144/186] feat(docs): extend (#7233) Documentation for `Web3Context.extend` method Closes #6768 --- docs/docs/guides/advanced/custom_RPC.md | 2 +- docs/docs/guides/advanced/extend.md | 38 +++++++++++++++++++++++ docs/docs/guides/advanced/tree_shaking.md | 2 +- 3 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 docs/docs/guides/advanced/extend.md diff --git a/docs/docs/guides/advanced/custom_RPC.md b/docs/docs/guides/advanced/custom_RPC.md index 28ccfeeea63..6874062c814 100644 --- a/docs/docs/guides/advanced/custom_RPC.md +++ b/docs/docs/guides/advanced/custom_RPC.md @@ -13,7 +13,7 @@ import TabItem from '@theme/TabItem'; Web3.js is a popular library for interacting with the Ethereum blockchain. It provides a set of APIs to interact with Ethereum nodes via JSON-RPC calls. For adding new JSON-RPC function calls to the library, you can do so using the plugin feature in web3.js 4.x. This allows you to extend the functionality of Web3.js and add support for new JSON-RPC methods. :::caution -In Web3.js 1.x, `web3.extend()` function could be used to add new JSON-RPC methods. `web3.extend()` is also available in Web3 v4.0.4+ with some breaking changes. However it is recommended to use Web3 Plugin feature for extending web3 functionality if you are developing new feature. +In Web3.js 1.x, `web3.extend()` function could be used to add new JSON-RPC methods. `web3.extend()` is also available in Web3 v4.0.4+ with some breaking changes. However it is recommended to use Web3 Plugin feature for extending web3 functionality if you are developing new feature. Read the ["Extending Web3.js"](/guides/advanced/extend) guide to learn more about the legacy `web3.extend()` method. ::: Following tutorial will guide you through the process of creating a custom plugin to extend the functionality of web3.js 4.x and add support for new RPC methods. diff --git a/docs/docs/guides/advanced/extend.md b/docs/docs/guides/advanced/extend.md new file mode 100644 index 00000000000..4b9d011db73 --- /dev/null +++ b/docs/docs/guides/advanced/extend.md @@ -0,0 +1,38 @@ +--- +sidebar_position: 2 +sidebar_label: Extending Web3.js +--- + +# Extending Web3.js + +Although the preferred way to add custom RPC methods to Web3.js is to [create a plugin](/guides/advanced/custom_RPC), Web3.js also exposes a [legacy `extend` method](/api/web3/class/Web3Context#extend) that can be used for the same purpose. Keep reading to learn how to use the legacy `extend` method to add a custom RPC method to an instance of Web3.js. + +## `ExtensionObject` + +The legacy `extend` method accepts a single parameter that should implement the [`ExtensionObject` interface](/api/web3/namespace/core/#ExtensionObject). An `ExtensionObject` consists of two properties: an optional `string` property named `property` and a required property named `methods` that is an array of objects that implement the [`Method` interface](/api/web3/namespace/core/#Method). The `Method` interface specifies two properties, both of which are required and both of which are strings: `name` and `call`. The `property` property of an `Extension` object can be used to specify the name of the Web3.js member property that will expose the custom RPC methods (if this parameter is omitted, the new RPC methods will be exposed by the "root" Web3.js object). Each element of the `methods` array from the `ExtensionObject` specifies a new custom RPC method - the `name` property is the name of the new function that will be used to call the custom RPC method and the `call` property is the actual RPC endpoint that should be invoked. The new function will accept parameters that will be passed along when invoking the RPC endpoint. + +Here is a complete example of using the legacy `extend` method: + +```js +import { Web3 } from "web3"; + +const web3 = new Web3("https://eth.llamarpc.com"); + +async function main() { + web3.extend({ + property: "BlockReceipts", + methods: [ + { + name: "getBlockReceipts", + // https://www.quicknode.com/docs/ethereum/eth_getBlockReceipts + call: "eth_getBlockReceipts", + }, + ], + }); + + const receipts = await web3.BlockReceipts.getBlockReceipts("latest"); + console.log(receipts); +} + +main(); +``` diff --git a/docs/docs/guides/advanced/tree_shaking.md b/docs/docs/guides/advanced/tree_shaking.md index 46f301e738c..43b4aa8b717 100644 --- a/docs/docs/guides/advanced/tree_shaking.md +++ b/docs/docs/guides/advanced/tree_shaking.md @@ -1,5 +1,5 @@ --- -sidebar_position: 2 +sidebar_position: 3 sidebar_label: Tree Shaking Guide --- From 27155eaf29f8b7a3b36e7958188076aa420c4c46 Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Mon, 9 Sep 2024 07:20:31 -0700 Subject: [PATCH 145/186] fix(onNewProviderDiscovered): callback-parameter (#7242) * fix(onNewProviderDiscovered): callback-parameter Callback for `onNewProviderDiscovered`should have `EIP6963ProvidersMapUpdateEvent` parameter Closes #7241 * Update Changelog * Fix Changelog * Remove Unnecessary Whitespace --- CHANGELOG.md | 1 + packages/web3/src/web3_eip6963.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 48117f4e47c..908ae117acc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2700,5 +2700,6 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3 - `Web3.providers` namespace exports `type EIP6963ProviderResponse = Map`. Return type for the static `Web3.requestEIP6963Providers` is now `Promise`. (#7239) +- The callback function provided to the static `Web3.onNewProviderDiscovered` function expects a parameter of type `EIP6963ProvidersMapUpdateEvent` as opposed to `EIP6963AnnounceProviderEvent`. (#7242) ## [Unreleased] diff --git a/packages/web3/src/web3_eip6963.ts b/packages/web3/src/web3_eip6963.ts index d2169191b5c..5693dea4776 100644 --- a/packages/web3/src/web3_eip6963.ts +++ b/packages/web3/src/web3_eip6963.ts @@ -84,7 +84,7 @@ export const requestEIP6963Providers = async (): Promise void) => { +export const onNewProviderDiscovered = (callback: (providerEvent: EIP6963ProvidersMapUpdateEvent) => void) => { if (typeof window === 'undefined') { throw new Error("window object not available, EIP-6963 is intended to be used within a browser"); } From b86d8cae50d60e56e96bde9d1b836ca01ecd0fbc Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 9 Sep 2024 11:16:29 -0400 Subject: [PATCH 146/186] Format repo, add new rules (#7226) * format all files and fix formatter so it runs on commit * update eslint * pre commit will run prettier on commited files * update * remove prepush --- .eslintrc.js | 15 + .husky/pre-commit | 4 + .husky/pre-push | 4 - CHANGELOG.md | 35 +- docs/docs/guides/advanced/custom_RPC.md | 128 +- docs/docs/guides/advanced/extend.md | 30 +- docs/docs/guides/advanced/tree_shaking.md | 10 +- .../1.x/web3_utils_migration_guide.md | 20 +- fixtures/contracts/Basic.sol | 40 +- fixtures/contracts/GreeterWithOverloading.sol | 12 +- package.json | 9 +- packages/web3-core/CHANGELOG.md | 6 +- packages/web3-core/src/utils.ts | 11 +- packages/web3-core/src/web3_config.ts | 7 +- packages/web3-core/src/web3_context.ts | 21 +- packages/web3-errors/CHANGELOG.md | 8 +- packages/web3-errors/src/error_codes.ts | 1 - .../web3-errors/src/errors/response_errors.ts | 11 +- .../web3-errors/src/errors/schema_errors.ts | 1 - .../web3-errors/src/errors/utils_errors.ts | 1 - packages/web3-errors/src/index.ts | 2 +- packages/web3-errors/test/unit/errors.test.ts | 7 +- packages/web3-eth-abi/CHANGELOG.md | 1 + packages/web3-eth-abi/src/api/errors_api.ts | 2 +- packages/web3-eth-abi/src/api/events_api.ts | 2 +- .../web3-eth-abi/src/api/functions_api.ts | 2 +- packages/web3-eth-abi/src/api/logs_api.ts | 2 +- .../web3-eth-abi/src/api/parameters_api.ts | 3 +- .../src/coders/base/numbersLimits.ts | 4 +- packages/web3-eth-accounts/CHANGELOG.md | 11 +- packages/web3-eth-accounts/src/account.ts | 2 +- .../src/common/chains/goerli.ts | 137 +- .../src/common/chains/mainnet.ts | 152 +- .../src/common/chains/sepolia.ts | 138 +- .../web3-eth-accounts/src/common/eips/1153.ts | 39 +- .../web3-eth-accounts/src/common/eips/1559.ts | 45 +- .../web3-eth-accounts/src/common/eips/2315.ts | 43 +- .../web3-eth-accounts/src/common/eips/2537.ts | 81 +- .../web3-eth-accounts/src/common/eips/2565.ts | 31 +- .../web3-eth-accounts/src/common/eips/2718.ts | 21 +- .../web3-eth-accounts/src/common/eips/2929.ts | 165 +- .../web3-eth-accounts/src/common/eips/2930.ts | 37 +- .../web3-eth-accounts/src/common/eips/3074.ts | 43 +- .../web3-eth-accounts/src/common/eips/3198.ts | 31 +- .../web3-eth-accounts/src/common/eips/3529.ts | 45 +- .../web3-eth-accounts/src/common/eips/3540.ts | 25 +- .../web3-eth-accounts/src/common/eips/3541.ts | 23 +- .../web3-eth-accounts/src/common/eips/3554.ts | 33 +- .../web3-eth-accounts/src/common/eips/3607.ts | 25 +- .../web3-eth-accounts/src/common/eips/3651.ts | 25 +- .../web3-eth-accounts/src/common/eips/3670.ts | 25 +- .../web3-eth-accounts/src/common/eips/3675.ts | 25 +- .../web3-eth-accounts/src/common/eips/3855.ts | 33 +- .../web3-eth-accounts/src/common/eips/3860.ts | 41 +- .../web3-eth-accounts/src/common/eips/4345.ts | 33 +- .../web3-eth-accounts/src/common/eips/4399.ts | 25 +- .../web3-eth-accounts/src/common/eips/4844.ts | 107 +- .../web3-eth-accounts/src/common/eips/4895.ts | 25 +- .../web3-eth-accounts/src/common/eips/5133.ts | 33 +- .../src/common/hardforks/arrowGlacier.ts | 21 +- .../src/common/hardforks/berlin.ts | 13 +- .../src/common/hardforks/byzantium.ts | 109 +- .../src/common/hardforks/chainstart.ts | 685 ++++--- .../src/common/hardforks/constantinople.ts | 109 +- .../src/common/hardforks/dao.ts | 19 +- .../src/common/hardforks/grayGlacier.ts | 21 +- .../src/common/hardforks/homestead.ts | 27 +- .../src/common/hardforks/istanbul.ts | 171 +- .../src/common/hardforks/london.ts | 13 +- .../src/common/hardforks/merge.ts | 21 +- .../common/hardforks/mergeForkIdTransition.ts | 13 +- .../src/common/hardforks/muirGlacier.ts | 29 +- .../src/common/hardforks/petersburg.ts | 64 +- .../src/common/hardforks/shanghai.ts | 14 +- .../src/common/hardforks/sharding.ts | 13 +- .../src/common/hardforks/spuriousDragon.ts | 36 +- .../src/common/hardforks/tangerineWhistle.ts | 83 +- packages/web3-eth-accounts/src/wallet.ts | 12 +- .../test/fixtures/account.ts | 32 +- .../test/unit/account_dom.test.ts | 14 +- packages/web3-eth-contract/CHANGELOG.md | 6 +- .../src/contract-deployer-method-class.ts | 56 +- packages/web3-eth-contract/src/contract.ts | 84 +- packages/web3-eth-contract/src/encoding.ts | 1 - packages/web3-eth-contract/src/utils.ts | 61 +- .../test/fixtures/AbiItem.ts | 162 +- .../contract_transaction_middleware.ts | 17 +- .../web3-eth-contract/test/fixtures/create.ts | 227 ++- .../test/fixtures/create2.ts | 101 +- .../integration/contract_accesslist.test.ts | 2 +- .../test/integration/contract_deploy.test.ts | 2 +- .../test/integration/contract_methods.test.ts | 11 +- .../local_account/contract_deploy.test.ts | 27 +- .../contract_overloaded_methods.test.ts | 5 +- .../test/unit/contract.test.ts | 20 +- .../test/unit/contract_typing.test.ts | 4 +- .../test/unit/function_overloading.test.ts | 10 +- .../web3-eth-contract/test/unit/utils.test.ts | 161 +- packages/web3-eth-ens/CHANGELOG.md | 4 +- packages/web3-eth-ens/src/ens.ts | 4 +- packages/web3-eth-ens/src/resolver.ts | 33 +- .../web3-eth-ens/test/integration/setup.js | 1 - packages/web3-eth-ens/test/unit/ens.test.ts | 6 +- .../web3-eth-ens/test/unit/resolver.test.ts | 67 +- packages/web3-eth-iban/CHANGELOG.md | 2 +- packages/web3-eth-personal/CHANGELOG.md | 2 +- packages/web3-eth-personal/src/personal.ts | 38 +- .../test/integration/personal.test.ts | 2 +- packages/web3-eth/CHANGELOG.md | 4 +- packages/web3-eth/src/rpc_method_wrappers.ts | 28 +- packages/web3-eth/src/schemas.ts | 20 +- packages/web3-eth/src/types.ts | 16 +- .../src/utils/detect_transaction_type.ts | 6 +- .../utils/prepare_transaction_for_signing.ts | 2 +- .../src/utils/reject_if_block_timeout.ts | 35 +- packages/web3-eth/src/utils/send_tx_helper.ts | 13 +- .../src/utils/watch_transaction_by_polling.ts | 2 +- packages/web3-eth/src/web3_eth.ts | 13 +- packages/web3-eth/test/e2e/e2e_utils.ts | 15 +- packages/web3-eth/test/e2e/setup.js | 1 - .../test/fixtures/transactions_data.ts | 194 +- .../integration/block/rpc.getBlock.test.ts | 2 +- .../rpc.getBlockTransactionCount.test.ts | 2 +- .../block/rpc.getBlockUncleCount.test.ts | 2 +- .../integration/block/rpc.getUncle.test.ts | 2 +- .../test/integration/defaults.test.ts | 1764 ++++++++--------- .../defaults.transactionBlockTimeout.test.ts | 15 +- .../integration/get_revert_reason.test.ts | 6 +- .../web3-eth/test/integration/nonce.test.ts | 14 +- .../integration/watch_transaction.test.ts | 11 +- .../web3_eth/createAccessList.test.ts | 2 +- .../integration/web3_eth/estimate_gas.test.ts | 2 +- .../web3_eth/getFeeHistory.test.ts | 2 +- .../web3_eth/send_signed_transaction.test.ts | 2 +- .../test/integration/web3_eth/sign.test.ts | 2 +- .../web3_eth/sign_transaction.test.ts | 2 +- .../integration/web3_eth/submit_work.test.ts | 23 +- .../unit/default_transaction_builder.test.ts | 1 - .../test/unit/detect_transaction_type.test.ts | 1 - .../prepare_transaction_for_signing.test.ts | 7 +- .../rpc_method_wrappers/fixtures/get_block.ts | 2 +- .../rpc_method_wrappers/get_block.test.ts | 11 +- .../send_transaction_middleware.test.ts | 108 +- .../web3-eth/test/unit/send_tx_helper.test.ts | 15 +- .../unit/utils/get_transaction_type.test.ts | 42 +- .../wait_for_transaction_receipt.test.ts | 2 +- .../watch_transaction_by_subscription.test.ts | 74 +- .../unit/web3_eth_calculate_fee_data.test.ts | 6 +- .../web3_eth_methods_no_parameters.test.ts | 4 +- .../web3_eth_methods_with_parameters.test.ts | 8 +- packages/web3-net/CHANGELOG.md | 2 +- .../test/fixtures/rpc_method_wrappers.ts | 2 +- .../test/integration/web3_net.test.ts | 4 +- .../test/unit/rpc_method_wrappers.test.ts | 1 - packages/web3-providers-http/CHANGELOG.md | 4 +- packages/web3-providers-http/src/index.ts | 4 +- packages/web3-providers-ipc/CHANGELOG.md | 2 +- packages/web3-providers-ws/CHANGELOG.md | 2 +- .../integration/geth_fault_tolerance.test.ts | 84 +- .../web_socket_provider_integration.test.ts | 13 +- .../test/unit/__mocks__/isomorphic-ws.ts | 7 +- .../test/unit/check_implementation.test.ts | 6 +- packages/web3-rpc-methods/CHANGELOG.md | 2 +- .../get_uncle_by_block_number.test.ts | 14 +- .../personal_rpc_methods/eth_personal.test.ts | 83 +- packages/web3-rpc-providers/CHANGELOG.md | 8 +- packages/web3-rpc-providers/README.md | 1 - packages/web3-rpc-providers/src/errors.ts | 7 +- packages/web3-rpc-providers/src/index.ts | 2 +- packages/web3-rpc-providers/src/types.ts | 46 +- .../web3-rpc-providers/src/web3_provider.ts | 311 +-- .../src/web3_provider_quicknode.ts | 186 +- .../test/unit/constructor.test.ts | 339 ++-- .../test/unit/request.test.ts | 201 +- packages/web3-types/CHANGELOG.md | 5 +- .../web3-types/src/apis/eth_execution_api.ts | 5 +- packages/web3-types/src/eth_abi_types.ts | 22 +- packages/web3-types/src/web3_base_provider.ts | 2 - packages/web3-utils/src/formatter.ts | 29 +- .../web3-utils/test/unit/formatter.test.ts | 12 +- packages/web3-validator/CHANGELOG.md | 8 +- packages/web3-validator/src/utils.ts | 81 +- .../web3-validator/src/validation/bytes.ts | 4 +- packages/web3-validator/src/validator.ts | 17 +- .../test/fixtures/abi_to_json_schema.ts | 904 ++++----- .../test/fixtures/validation.ts | 1 - .../test/unit/web3_validator.test.ts | 14 +- packages/web3/CHANGELOG.md | 59 +- packages/web3/README.md | 30 +- packages/web3/src/accounts.ts | 10 +- packages/web3/src/providers.exports.ts | 2 +- packages/web3/src/web3_eip6963.ts | 106 +- .../web3/test/cjs_black_box/.eslintrc.cjs | 2 +- .../test/web3-eth-contract/erc20.test.ts | 2 +- packages/web3/test/config/jest.config.js | 2 +- packages/web3/test/e2e/setup.js | 1 - .../test/web3-eth-contract/erc20.test.ts | 2 +- .../test/fixtures/transaction_middleware.ts | 17 +- .../integration/contract-middleware.test.ts | 37 +- .../external-providers/hardhat.test.ts | 5 +- packages/web3/test/integration/setup.js | 1 - .../web3/test/integration/web3.config.test.ts | 34 +- .../test/integration/web3RPCProviders.test.ts | 85 +- packages/web3/test/integration/ws.test.ts | 20 +- .../nodejs_test/long_connection_ws.js | 84 +- packages/web3/test/stress/setup.js | 1 - .../test/unit/contract-middleware.test.ts | 10 +- packages/web3/test/unit/web3.config.test.ts | 278 +-- packages/web3/test/unit/web3.test.ts | 4 +- packages/web3/test/unit/web3eip6963.test.ts | 148 +- scripts/system_tests_utils.ts | 46 +- templates/.prettierignore.tmpl | 1 + templates/cypress.config.js | 2 +- tools/web3-plugin-example/CHANGELOG.md | 4 +- .../src/custom_rpc_methods.ts | 6 +- .../src/request_manager_middleware.ts | 17 +- .../src/transaction_middleware.ts | 17 +- .../src/transaction_middleware_plugin.ts | 7 +- .../contract_transaction_middleware.test.ts | 43 +- .../test/unit/fixtures/transactions_data.ts | 194 +- .../test/unit/transaction_middleware.test.ts | 40 +- yarn.lock | 281 ++- 222 files changed, 5731 insertions(+), 5318 deletions(-) create mode 100755 .husky/pre-commit delete mode 100755 .husky/pre-push diff --git a/.eslintrc.js b/.eslintrc.js index 241a06879e7..28f41cacfb1 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -16,4 +16,19 @@ module.exports = { typescript: {}, // this loads tsconfig.json to eslint }, }, + overrides: [ + { + files: ['*.test.ts'], + rules: { + '@typescript-eslint/no-unsafe-call': 'off', + 'import/no-unresolved': 'off', + }, + }, + { + files: ['*.ts'], + rules: { + 'default-param-last': 'off', + }, + }, + ], }; diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 00000000000..d24fdfc601b --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +npx lint-staged diff --git a/.husky/pre-push b/.husky/pre-push deleted file mode 100755 index 3b614330e02..00000000000 --- a/.husky/pre-push +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" - -yarn run lint diff --git a/CHANGELOG.md b/CHANGELOG.md index 908ae117acc..6edd15446e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2458,7 +2458,7 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3-errors -- Added `InvalidIntegerError` error for fromWei and toWei (#7052) +- Added `InvalidIntegerError` error for fromWei and toWei (#7052) #### web3-eth @@ -2484,8 +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) +- `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 @@ -2495,13 +2495,13 @@ 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) +- `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) +- 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 @@ -2600,7 +2600,7 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3-eth-accounts -- baseTransaction method updated (#7095) +- baseTransaction method updated (#7095) #### web3-providers-ws @@ -2612,7 +2612,7 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3-rpc-providers - - Change request return type `Promise` to `Promise>` (#7102) +- Change request return type `Promise` to `Promise>` (#7102) ### Added @@ -2623,7 +2623,7 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3-rpc-providers - - When error is returned with code 429, throw rate limit error (#7102) +- When error is returned with code 429, throw rate limit error (#7102) #### web3 @@ -2635,7 +2635,7 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3-errors -- Fixed the undefined data in `Eip838ExecutionError` constructor (#6905) +- Fixed the undefined data in `Eip838ExecutionError` constructor (#6905) #### web3-eth @@ -2646,7 +2646,6 @@ If there are any bugs, improvements, optimizations or any new feature proposal f - Remove redundant constructor of contractBuilder (#7150) - ## [4.12.0] ### Fixed @@ -2657,7 +2656,7 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3-eth-accounts -- Fix `TransactionFactory.registerTransactionType` not working, if there is a version mistatch between `web3-eth` and `web3-eth-accounts` by saving `extraTxTypes` at `globals`. (#7197) +- Fix `TransactionFactory.registerTransactionType` not working, if there is a version mistatch between `web3-eth` and `web3-eth-accounts` by saving `extraTxTypes` at `globals`. (#7197) ### Added @@ -2667,11 +2666,11 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3-eth-contract -- Added `populateTransaction` to the `contract.deploy(...)` properties. (#7197) +- Added `populateTransaction` to the `contract.deploy(...)` properties. (#7197) #### web3-providers-http -- Added `statusCode` of response in ResponseError, `statusCode` is optional property in ResponseError. +- Added `statusCode` of response in ResponseError, `statusCode` is optional property in ResponseError. #### web3-rpc-providers @@ -2680,14 +2679,14 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3-errors -- Added optional `statusCode` property of response in ResponseError. +- Added optional `statusCode` property of response in ResponseError. ### Changed #### web3-eth-contract - The returnred properties of `contract.deploy(...)` are structured with a newly created class named `DeployerMethodClass`. (#7197) -- Add a missed accepted type for the `abi` parameter, at `dataInputEncodeMethodHelper` and `getSendTxParams`. (#7197) +- Add a missed accepted type for the `abi` parameter, at `dataInputEncodeMethodHelper` and `getSendTxParams`. (#7197) ## [4.12.1] @@ -2695,7 +2694,7 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3-eth-accounts -- Revert `TransactionFactory.registerTransactionType` if there is a version mistatch between `web3-eth` and `web3-eth-accounts` and fix nextjs problem. (#7216) +- Revert `TransactionFactory.registerTransactionType` if there is a version mistatch between `web3-eth` and `web3-eth-accounts` and fix nextjs problem. (#7216) #### web3 diff --git a/docs/docs/guides/advanced/custom_RPC.md b/docs/docs/guides/advanced/custom_RPC.md index 6874062c814..605a9c61a3e 100644 --- a/docs/docs/guides/advanced/custom_RPC.md +++ b/docs/docs/guides/advanced/custom_RPC.md @@ -30,16 +30,16 @@ This will give your plugin access to [requestManager](/api/web3-core/class/Web3C - + ```javascript const { Web3PluginBase } = require('web3'); //highlight-start class CustomRpcMethodsPlugin extends Web3PluginBase { - // step 1 - // ... + // step 1 + // ... } //highlight-end @@ -56,8 +56,8 @@ import { Web3PluginBase } from 'web3'; //highlight-start export default class CustomRpcMethodsPlugin extends Web3PluginBase { - // step 1 - // ... + // step 1 + // ... } //highlight-end ``` @@ -69,19 +69,18 @@ export default class CustomRpcMethodsPlugin extends Web3PluginBase { 2. After that add public `pluginNamespace` property. This will be used to access your plugin, as mentioned in step number 5 code example. - - + ```javascript const { Web3PluginBase } = require('web3'); class CustomRpcMethodsPlugin extends Web3PluginBase { -//highlight-start - pluginNamespace = 'customRpcMethods'; // step 2 -//highlight-end + //highlight-start + pluginNamespace = 'customRpcMethods'; // step 2 + //highlight-end } module.exports = CustomRpcMethodsPlugin; @@ -96,40 +95,39 @@ module.exports = CustomRpcMethodsPlugin; import { Web3PluginBase } from 'web3'; export default class CustomRpcMethodsPlugin extends Web3PluginBase { - //highlight-start - public pluginNamespace = 'customRpcMethods'; // step 2 -//highlight-end + //highlight-start + public pluginNamespace = 'customRpcMethods'; // step 2 + //highlight-end } ``` - ### Step 3: Creating Custom RPC Methods in the Plugin Class 3. Once plugin class is created using above mentioned steps, its very easy to add new RPC methods like: - + ```javascript const { Web3PluginBase } = require('web3'); class CustomRpcMethodsPlugin extends Web3PluginBase { - pluginNamespace = 'customRpcMethods'; + pluginNamespace = 'customRpcMethods'; //highlight-start - async customRpcMethod() { - // step 3 - return this.requestManager.send({ - // plugin has access to web3.js internal features like request manager - method: 'custom_rpc_method', - params: [], - }); - } + async customRpcMethod() { + // step 3 + return this.requestManager.send({ + // plugin has access to web3.js internal features like request manager + method: 'custom_rpc_method', + params: [], + }); + } //highlight-end } @@ -145,18 +143,18 @@ module.exports = CustomRpcMethodsPlugin; import { Web3PluginBase } from 'web3'; export default class CustomRpcMethodsPlugin extends Web3PluginBase { - public pluginNamespace = 'customRpcMethods'; - - //highlight-start - public async customRpcMethod() { - // step 3 - return this.requestManager.send({ - // plugin has access to web3.js internal features like request manager - method: 'custom_rpc_method', - params: [], - }); - } - //highlight-end + public pluginNamespace = 'customRpcMethods'; + + //highlight-start + public async customRpcMethod() { + // step 3 + return this.requestManager.send({ + // plugin has access to web3.js internal features like request manager + method: 'custom_rpc_method', + params: [], + }); + } + //highlight-end } ``` @@ -169,22 +167,22 @@ export default class CustomRpcMethodsPlugin extends Web3PluginBase { - + ```javascript const { Web3PluginBase } = require('web3'); class CustomRpcMethodsPlugin extends Web3PluginBase { - pluginNamespace = 'customRpcMethods'; - - async customRpcMethod() { - return this.requestManager.send({ - // plugin has access to web3.js internal features like request manager - method: 'custom_rpc_method', - params: [], - }); - } + pluginNamespace = 'customRpcMethods'; + + async customRpcMethod() { + return this.requestManager.send({ + // plugin has access to web3.js internal features like request manager + method: 'custom_rpc_method', + params: [], + }); + } } module.exports = CustomRpcMethodsPlugin; @@ -199,25 +197,25 @@ module.exports = CustomRpcMethodsPlugin; import { Web3PluginBase } from 'web3'; export default class CustomRpcMethodsPlugin extends Web3PluginBase { - public pluginNamespace = 'customRpcMethods'; - - public async customRpcMethod() { - return this.requestManager.send({ - // plugin has access to web3.js internal features like request manager - method: 'custom_rpc_method', - params: [], - }); - } + public pluginNamespace = 'customRpcMethods'; + + public async customRpcMethod() { + return this.requestManager.send({ + // plugin has access to web3.js internal features like request manager + method: 'custom_rpc_method', + params: [], + }); + } } //highlight-start // Module Augmentation declare module 'web3' { - // step 4 + // step 4 - interface Web3Context { - customRpcMethods: CustomRpcMethodsPlugin; - } + interface Web3Context { + customRpcMethods: CustomRpcMethodsPlugin; + } } //highlight-end ``` @@ -237,8 +235,8 @@ Once plugin is registered its custom methods will be available to use. - + ```javascript const { Web3 } = require('web3'); diff --git a/docs/docs/guides/advanced/extend.md b/docs/docs/guides/advanced/extend.md index 4b9d011db73..b1301b2fc03 100644 --- a/docs/docs/guides/advanced/extend.md +++ b/docs/docs/guides/advanced/extend.md @@ -14,24 +14,24 @@ The legacy `extend` method accepts a single parameter that should implement the Here is a complete example of using the legacy `extend` method: ```js -import { Web3 } from "web3"; +import { Web3 } from 'web3'; -const web3 = new Web3("https://eth.llamarpc.com"); +const web3 = new Web3('https://eth.llamarpc.com'); async function main() { - web3.extend({ - property: "BlockReceipts", - methods: [ - { - name: "getBlockReceipts", - // https://www.quicknode.com/docs/ethereum/eth_getBlockReceipts - call: "eth_getBlockReceipts", - }, - ], - }); - - const receipts = await web3.BlockReceipts.getBlockReceipts("latest"); - console.log(receipts); + web3.extend({ + property: 'BlockReceipts', + methods: [ + { + name: 'getBlockReceipts', + // https://www.quicknode.com/docs/ethereum/eth_getBlockReceipts + call: 'eth_getBlockReceipts', + }, + ], + }); + + const receipts = await web3.BlockReceipts.getBlockReceipts('latest'); + console.log(receipts); } main(); diff --git a/docs/docs/guides/advanced/tree_shaking.md b/docs/docs/guides/advanced/tree_shaking.md index 43b4aa8b717..46bd1a32505 100644 --- a/docs/docs/guides/advanced/tree_shaking.md +++ b/docs/docs/guides/advanced/tree_shaking.md @@ -26,7 +26,7 @@ import TabItem from '@theme/TabItem'; :::note For further information about `sideEffects` see [webpack docs](https://webpack.js.org/guides/tree-shaking/) -::: +::: ## Step 3: Set tsconfig Module to ES2015 @@ -44,8 +44,8 @@ For further information about `sideEffects` see [webpack docs](https://webpack.j - + ```javascript const { Web3Eth } = require('web3-eth'); @@ -69,8 +69,8 @@ If you only need a few functions from `web3-utils`: - + ```javascript const { numberToHex, hexToNumber } = require('web3-utils'); diff --git a/docs/docs/guides/web3_upgrade_guide/1.x/web3_utils_migration_guide.md b/docs/docs/guides/web3_upgrade_guide/1.x/web3_utils_migration_guide.md index 5282b720823..cbc68f0eb14 100644 --- a/docs/docs/guides/web3_upgrade_guide/1.x/web3_utils_migration_guide.md +++ b/docs/docs/guides/web3_upgrade_guide/1.x/web3_utils_migration_guide.md @@ -43,20 +43,20 @@ web3.utils.toWei('0.1', 'ether'); ## Conversion to Hex -The `toHex` behave exactly the same in both v1.x and 4.x, except for a string that contains only numbers. In 1.x if a number was provided inside a string like `123` it used to be treated as a number. While in 4.x it will be treated as a string, except if it was prefixed with `0x`. For more clarity, check below: +The `toHex` behave exactly the same in both v1.x and 4.x, except for a string that contains only numbers. In 1.x if a number was provided inside a string like `123` it used to be treated as a number. While in 4.x it will be treated as a string, except if it was prefixed with `0x`. For more clarity, check below: ```ts // 1.x -new Web3().utils.toHex(0x1) // returns 0x1 -new Web3().utils.toHex('0x1') // returns 0x1 -new Web3().utils.toHex(1) // returns 0x1 -new Web3().utils.toHex('1') // returns 0x1 +new Web3().utils.toHex(0x1); // returns 0x1 +new Web3().utils.toHex('0x1'); // returns 0x1 +new Web3().utils.toHex(1); // returns 0x1 +new Web3().utils.toHex('1'); // returns 0x1 // 4.x -new Web3().utils.toHex(0x1) // returns 0x1 -new Web3().utils.toHex('0x1') // returns 0x1 -new Web3().utils.toHex(1) // returns 0x1 -new Web3().utils.toHex('1') // returns 0x31 +new Web3().utils.toHex(0x1); // returns 0x1 +new Web3().utils.toHex('0x1'); // returns 0x1 +new Web3().utils.toHex(1); // returns 0x1 +new Web3().utils.toHex('1'); // returns 0x31 ``` ## Validation functions @@ -92,6 +92,7 @@ isHex('-0x'); // in 1.x used to return `true`. But changed in 4.x to return `fal isHexStrict('-0x'); // in 1.x used to return `true`. But changed in 4.x to return `false` // `false` ``` + ## stripHexPrefix method In 1.x `stripHexPrefix` method is located in the `web3-utils` package, in 4.x this has been moved to `web3-eth-accounts` @@ -100,7 +101,6 @@ In 1.x `stripHexPrefix` method is located in the `web3-utils` package, in 4.x th import { stripHexPrefix } from 'web3-eth-accounts'; console.log(stripHexPrefix('0x123')); // "123" - ``` ## Other functions diff --git a/fixtures/contracts/Basic.sol b/fixtures/contracts/Basic.sol index 89b3a1c8a65..e31573d026b 100644 --- a/fixtures/contracts/Basic.sol +++ b/fixtures/contracts/Basic.sol @@ -10,7 +10,11 @@ contract Basic { event StringEvent(string str); event MultiValueEvent(string str, uint256 val, bool flag); event MultiValueIndexedEvent(string str, uint256 indexed val, bool indexed flag); - event MultiValueIndexedEventWithStringIndexed(string indexed str, uint256 indexed val, bool indexed flag); + event MultiValueIndexedEventWithStringIndexed( + string indexed str, + uint256 indexed val, + bool indexed flag + ); constructor(uint256 _val, string memory _stringValue) { intValue = _val; @@ -29,11 +33,23 @@ contract Basic { return boolValue; } - function getValues() public view returns (uint256, string memory, bool) { + function getValues() + public + view + returns ( + uint256, + string memory, + bool + ) + { return (intValue, stringValue, boolValue); } - function setValues(uint256 _value, string memory _stringValue, bool _boolValue) public { + function setValues( + uint256 _value, + string memory _stringValue, + bool _boolValue + ) public { intValue = _value; stringValue = _stringValue; boolValue = _boolValue; @@ -51,11 +67,19 @@ contract Basic { revert('REVERTED WITH REVERT'); } - function firesMultiValueEvent(string memory str, uint256 val, bool flag) public { + function firesMultiValueEvent( + string memory str, + uint256 val, + bool flag + ) public { emit MultiValueEvent(str, val, flag); } - function firesMultiValueIndexedEvent(string memory str, uint256 val, bool flag) public { + function firesMultiValueIndexedEvent( + string memory str, + uint256 val, + bool flag + ) public { emit MultiValueIndexedEvent(str, val, flag); } @@ -63,7 +87,11 @@ contract Basic { emit StringEvent(_str); } - function firesMultiValueIndexedEventWithStringIndexed(string calldata str, uint256 val, bool flag) public { + function firesMultiValueIndexedEventWithStringIndexed( + string calldata str, + uint256 val, + bool flag + ) public { emit MultiValueIndexedEventWithStringIndexed(str, val, flag); } } diff --git a/fixtures/contracts/GreeterWithOverloading.sol b/fixtures/contracts/GreeterWithOverloading.sol index 384709287b2..4caf4e31df4 100644 --- a/fixtures/contracts/GreeterWithOverloading.sol +++ b/fixtures/contracts/GreeterWithOverloading.sol @@ -25,13 +25,16 @@ contract GreeterWithOverloading { return (true, greeting); } - // function overlading with additional parameter - function setGreeting(string memory _greeting, bool _raiseEvents) public returns (bool, string memory) { - if(_raiseEvents) { + // function overlading with additional parameter + function setGreeting(string memory _greeting, bool _raiseEvents) + public + returns (bool, string memory) + { + if (_raiseEvents) { emit GREETING_CHANGING(greeting, _greeting); } greeting = _greeting; - if(_raiseEvents) { + if (_raiseEvents) { emit GREETING_CHANGED(greeting); } return (true, greeting); @@ -41,4 +44,3 @@ contract GreeterWithOverloading { counter = counter + 1; } } - \ No newline at end of file diff --git a/package.json b/package.json index 1a3d5b6a5d5..8e741afb9f6 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,9 @@ "tools/*" ] }, + "lint-staged": { + "*.{js,jsx,ts,tsx,css,md}": "prettier --write" + }, "scripts": { "version": "yarn run bootstrap && yarn build", "bootstrap": "lerna bootstrap", @@ -93,11 +96,10 @@ "test:blackbox:infura:ws": "yarn pre-blackbox && ./scripts/verdaccio.sh startBackgroundAndPublish && lerna run test:blackbox:infura:ws --stream && yarn post-blackbox", "test:manual:long-connection-ws": "node packages/web3/test/stress/long_ws_tests/nodejs_test/long_connection_ws.js", "test:stress": "yarn test:stress:geth:ws && yarn test:stress:geth:http && yarn test:stress:geth:ipc && yarn test:e2e:stress:geth:ws:chrome", - "husky:install": "husky install", - "husky:uninstall": "husky uninstall", "postinstall": "yarn build", "compile:contracts": "node ./scripts/compile_contracts.js && yarn format && yarn lint:fix", - "publish:canary": "lerna publish --canary --dist-tag dev --preid dev.$(git rev-parse --short HEAD) --exact --graph-type all --force-publish \"*\" --no-verify-access --yes" + "publish:canary": "lerna publish --canary --dist-tag dev --preid dev.$(git rev-parse --short HEAD) --exact --graph-type all --force-publish \"*\" --no-verify-access --yes", + "prepare": "husky install" }, "devDependencies": { "@cypress/webpack-preprocessor": "^5.12.0", @@ -120,6 +122,7 @@ "husky": "^8.0.3", "jest": "^29.7.0", "lerna": "^6.6.2", + "lint-staged": "^15.2.9", "npm-auth-to-token": "^1.0.0", "prettier": "^2.7.1", "prettier-plugin-solidity": "^1.0.0-beta.20", diff --git a/packages/web3-core/CHANGELOG.md b/packages/web3-core/CHANGELOG.md index 2864dbd4d8d..18e3e0bf08a 100644 --- a/packages/web3-core/CHANGELOG.md +++ b/packages/web3-core/CHANGELOG.md @@ -195,7 +195,7 @@ Documentation: ### Fixed -- Fix `Web3Config` to properly update within other web3 packages when `setConfig` is used (#6555) +- Fix `Web3Config` to properly update within other web3 packages when `setConfig` is used (#6555) ### Added @@ -205,7 +205,7 @@ Documentation: ### Changed -- Web3config `contractDataInputFill` has been defaulted to `data`, istead of `input`. (#6622) +- Web3config `contractDataInputFill` has been defaulted to `data`, istead of `input`. (#6622) ## [4.4.0] @@ -233,4 +233,4 @@ Documentation: - `setConfig()` fix for `setMaxListenerWarningThreshold` fix (#5079) -## [Unreleased] \ No newline at end of file +## [Unreleased] diff --git a/packages/web3-core/src/utils.ts b/packages/web3-core/src/utils.ts index 34c5162c488..32b052a7706 100644 --- a/packages/web3-core/src/utils.ts +++ b/packages/web3-core/src/utils.ts @@ -33,10 +33,11 @@ export const isWeb3Provider = ( export const isMetaMaskProvider = ( provider: SupportedProviders, ): provider is MetaMaskProvider => - typeof provider !== 'string' && -'request' in provider && -provider.request.constructor.name === 'AsyncFunction' && 'isMetaMask' in provider && provider.isMetaMask; - + typeof provider !== 'string' && + 'request' in provider && + provider.request.constructor.name === 'AsyncFunction' && + 'isMetaMask' in provider && + provider.isMetaMask; export const isLegacyRequestProvider = ( provider: SupportedProviders, @@ -62,7 +63,7 @@ export const isLegacySendAsyncProvider = ( export const isSupportedProvider = ( provider: SupportedProviders, -): provider is SupportedProviders => +): provider is SupportedProviders => provider && (isWeb3Provider(provider) || isEIP1193Provider(provider) || diff --git a/packages/web3-core/src/web3_config.ts b/packages/web3-core/src/web3_config.ts index e647e05a9d5..f617756ad12 100644 --- a/packages/web3-core/src/web3_config.ts +++ b/packages/web3-core/src/web3_config.ts @@ -115,10 +115,11 @@ export abstract class Web3Config for (const key of keys) { this._triggerConfigChange(key, options[key]); - if(!isNullish(options[key]) && + if ( + !isNullish(options[key]) && typeof options[key] === 'number' && - key === 'maxListenersWarningThreshold' ) - { + key === 'maxListenersWarningThreshold' + ) { // additionally set in event emitter this.setMaxListenerWarningThreshold(Number(options[key])); } diff --git a/packages/web3-core/src/web3_context.ts b/packages/web3-core/src/web3_context.ts index 867f10f2350..207c4a64574 100644 --- a/packages/web3-core/src/web3_context.ts +++ b/packages/web3-core/src/web3_context.ts @@ -18,8 +18,15 @@ along with web3.js. If not, see . import { ExistingPluginNamespaceError } from 'web3-errors'; import { EthExecutionAPI, - HexString, Numbers, SupportedProviders, Transaction, Web3AccountProvider, Web3APISpec, Web3BaseProvider, Web3BaseWallet, - Web3BaseWalletAccount + HexString, + Numbers, + SupportedProviders, + Transaction, + Web3AccountProvider, + Web3APISpec, + Web3BaseProvider, + Web3BaseWallet, + Web3BaseWalletAccount, } from 'web3-types'; import { isNullish } from 'web3-utils'; import { BaseTransaction, TransactionFactory } from 'web3-eth-accounts'; @@ -130,7 +137,7 @@ export class Web3Context< registeredSubscriptions, accountProvider, wallet, - requestManagerMiddleware + requestManagerMiddleware, } = providerOrContext as Web3ContextInitOptions; this.setConfig(config ?? {}); @@ -140,7 +147,7 @@ export class Web3Context< new Web3RequestManager( provider, config?.enableExperimentalFeatures?.useSubscriptionWhenCheckingBlockTimeout, - requestManagerMiddleware + requestManagerMiddleware, ); if (subscriptionManager) { @@ -221,7 +228,7 @@ export class Web3Context< // @ts-expect-error No index signature with a parameter of type 'string' was found on type 'Web3Context' this[ContextRef.name] = newContextChild; - + return newContextChild; } @@ -359,10 +366,10 @@ export class Web3Context< return true; } - public setRequestManagerMiddleware(requestManagerMiddleware: RequestManagerMiddleware){ + public setRequestManagerMiddleware(requestManagerMiddleware: RequestManagerMiddleware) { this.requestManager.setMiddleware(requestManagerMiddleware); } - + /** * Will return the {@link Web3BatchRequest} constructor. */ diff --git a/packages/web3-errors/CHANGELOG.md b/packages/web3-errors/CHANGELOG.md index 47cb02f3cd3..2bcd592fb2d 100644 --- a/packages/web3-errors/CHANGELOG.md +++ b/packages/web3-errors/CHANGELOG.md @@ -170,18 +170,18 @@ Documentation: ### Added -- Added `InvalidIntegerError` error for fromWei and toWei (#7052) +- Added `InvalidIntegerError` error for fromWei and toWei (#7052) ## [1.2.1] ### Fixed -- Fixed the undefined data in `Eip838ExecutionError` constructor (#6905) +- Fixed the undefined data in `Eip838ExecutionError` constructor (#6905) ## [1.3.0] ### Added -- Added optional `statusCode` property of response in ResponseError. +- Added optional `statusCode` property of response in ResponseError. -## [Unreleased] \ No newline at end of file +## [Unreleased] diff --git a/packages/web3-errors/src/error_codes.ts b/packages/web3-errors/src/error_codes.ts index 16c95ad81cb..9950b6a0231 100644 --- a/packages/web3-errors/src/error_codes.ts +++ b/packages/web3-errors/src/error_codes.ts @@ -160,7 +160,6 @@ export const ERR_INVALID_INTEGER = 1015; // Validation error codes export const ERR_VALIDATION = 1100; - // Core error codes export const ERR_CORE_HARDFORK_MISMATCH = 1101; export const ERR_CORE_CHAIN_MISMATCH = 1102; diff --git a/packages/web3-errors/src/errors/response_errors.ts b/packages/web3-errors/src/errors/response_errors.ts index 214bf6652f6..401001973aa 100644 --- a/packages/web3-errors/src/errors/response_errors.ts +++ b/packages/web3-errors/src/errors/response_errors.ts @@ -51,7 +51,7 @@ export class ResponseError extends B response: JsonRpcResponse, message?: string, request?: JsonRpcPayload, - statusCode?: number + statusCode?: number, ) { super( message ?? @@ -85,7 +85,12 @@ export class ResponseError extends B } public toJSON() { - return { ...super.toJSON(), data: this.data, request: this.request, statusCode: this.statusCode }; + return { + ...super.toJSON(), + data: this.data, + request: this.request, + statusCode: this.statusCode, + }; } } @@ -111,4 +116,4 @@ export class InvalidResponseError ex this.cause = errorOrErrors as Error | undefined; } } -} \ No newline at end of file +} diff --git a/packages/web3-errors/src/errors/schema_errors.ts b/packages/web3-errors/src/errors/schema_errors.ts index 4d61684c616..142b970896b 100644 --- a/packages/web3-errors/src/errors/schema_errors.ts +++ b/packages/web3-errors/src/errors/schema_errors.ts @@ -28,5 +28,4 @@ export class SchemaFormatError extends BaseWeb3Error { public toJSON() { return { ...super.toJSON(), type: this.type }; } - } diff --git a/packages/web3-errors/src/errors/utils_errors.ts b/packages/web3-errors/src/errors/utils_errors.ts index ca213958b9a..3c96b847109 100644 --- a/packages/web3-errors/src/errors/utils_errors.ts +++ b/packages/web3-errors/src/errors/utils_errors.ts @@ -81,7 +81,6 @@ export class InvalidIntegerError extends InvalidValueError { public constructor(value: unknown) { super(value, 'not a valid unit. Must be a positive integer'); - } } diff --git a/packages/web3-errors/src/index.ts b/packages/web3-errors/src/index.ts index 2e4ef7abca6..fefa397d7f3 100644 --- a/packages/web3-errors/src/index.ts +++ b/packages/web3-errors/src/index.ts @@ -30,4 +30,4 @@ export * from './errors/response_errors.js'; export * from './errors/core_errors.js'; export * from './errors/rpc_errors.js'; export * from './errors/rpc_error_messages.js'; -export * from './errors/schema_errors.js'; \ No newline at end of file +export * from './errors/schema_errors.js'; diff --git a/packages/web3-errors/test/unit/errors.test.ts b/packages/web3-errors/test/unit/errors.test.ts index 0731f4dff37..a2d7cc2ecd6 100644 --- a/packages/web3-errors/test/unit/errors.test.ts +++ b/packages/web3-errors/test/unit/errors.test.ts @@ -329,7 +329,7 @@ describe('errors', () => { } as JsonRpcError).toJSON(), ).toMatchSnapshot(); }); - it('should return correctly when data is undefined', () => { + it('should return correctly when data is undefined', () => { expect( new contractErrors.Eip838ExecutionError({ data: undefined, @@ -391,10 +391,7 @@ describe('errors', () => { describe('SchemaFormatError', () => { it('should have valid json structure', () => { - expect( - new schemaErrors.SchemaFormatError("unsupported" - ).toJSON(), - ).toMatchSnapshot(); + expect(new schemaErrors.SchemaFormatError('unsupported').toJSON()).toMatchSnapshot(); }); }); }); diff --git a/packages/web3-eth-abi/CHANGELOG.md b/packages/web3-eth-abi/CHANGELOG.md index 1bb5910ba18..c764ff78ff4 100644 --- a/packages/web3-eth-abi/CHANGELOG.md +++ b/packages/web3-eth-abi/CHANGELOG.md @@ -185,4 +185,5 @@ Documentation: ## [Unreleased] ### Added + - Handle common cases for smart contract errors according to EIP 838: `0x4e487b71` which is the ‘selector’ for `Panic(uint256)` and `0x08c379a0` is the ‘selector’ of `Error(string)`. (7155) diff --git a/packages/web3-eth-abi/src/api/errors_api.ts b/packages/web3-eth-abi/src/api/errors_api.ts index 69933f5eb6e..895ea02b2d5 100644 --- a/packages/web3-eth-abi/src/api/errors_api.ts +++ b/packages/web3-eth-abi/src/api/errors_api.ts @@ -16,7 +16,7 @@ along with web3.js. If not, see . */ /** - * + * * @module ABI */ diff --git a/packages/web3-eth-abi/src/api/events_api.ts b/packages/web3-eth-abi/src/api/events_api.ts index 67bb1791432..82d116e6967 100644 --- a/packages/web3-eth-abi/src/api/events_api.ts +++ b/packages/web3-eth-abi/src/api/events_api.ts @@ -16,7 +16,7 @@ along with web3.js. If not, see . */ /** - * + * * @module ABI */ diff --git a/packages/web3-eth-abi/src/api/functions_api.ts b/packages/web3-eth-abi/src/api/functions_api.ts index 776cb084940..7504f352275 100644 --- a/packages/web3-eth-abi/src/api/functions_api.ts +++ b/packages/web3-eth-abi/src/api/functions_api.ts @@ -16,7 +16,7 @@ along with web3.js. If not, see . */ /** - * + * * @module ABI */ import { AbiError } from 'web3-errors'; diff --git a/packages/web3-eth-abi/src/api/logs_api.ts b/packages/web3-eth-abi/src/api/logs_api.ts index f7ebd012d57..678ec6d7129 100644 --- a/packages/web3-eth-abi/src/api/logs_api.ts +++ b/packages/web3-eth-abi/src/api/logs_api.ts @@ -16,7 +16,7 @@ along with web3.js. If not, see . */ /** - * + * * @module ABI */ diff --git a/packages/web3-eth-abi/src/api/parameters_api.ts b/packages/web3-eth-abi/src/api/parameters_api.ts index d9cbd106673..f81a32e9db3 100644 --- a/packages/web3-eth-abi/src/api/parameters_api.ts +++ b/packages/web3-eth-abi/src/api/parameters_api.ts @@ -16,7 +16,7 @@ along with web3.js. If not, see . */ /** - * + * * @module ABI */ @@ -27,7 +27,6 @@ import { encodeParameters } from '../coders/encode.js'; export { encodeParameters, inferTypesAndEncodeParameters } from '../coders/encode.js'; - /** * Encodes a parameter based on its type to its ABI representation. * @param abi - The type of the parameter. See the [Solidity documentation](https://docs.soliditylang.org/en/develop/types.html) for a list of types. diff --git a/packages/web3-eth-abi/src/coders/base/numbersLimits.ts b/packages/web3-eth-abi/src/coders/base/numbersLimits.ts index 29f11462843..4376d9a1a90 100644 --- a/packages/web3-eth-abi/src/coders/base/numbersLimits.ts +++ b/packages/web3-eth-abi/src/coders/base/numbersLimits.ts @@ -15,9 +15,9 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ -/* +/* * this variable contains the precalculated limits for all the numbers for uint and int types -*/ + */ export const numberLimits = new Map(); let base = BigInt(256); // 2 ^ 8 = 256 diff --git a/packages/web3-eth-accounts/CHANGELOG.md b/packages/web3-eth-accounts/CHANGELOG.md index 5a9768477e5..dc08d0cc692 100644 --- a/packages/web3-eth-accounts/CHANGELOG.md +++ b/packages/web3-eth-accounts/CHANGELOG.md @@ -136,7 +136,6 @@ Documentation: - Fixed "The `r` and `s` returned by `sign` to does not always consist of 64 characters" (#6411) - ## [4.1.0] ### Added @@ -147,7 +146,7 @@ Documentation: ### Fixed -- Fixed `recover` function, `v` will be normalized to value 0,1 (#6344) +- Fixed `recover` function, `v` will be normalized to value 0,1 (#6344) ## [4.1.1] @@ -166,7 +165,7 @@ Documentation: ### Changed -- baseTransaction method updated (#7095) +- baseTransaction method updated (#7095) ## [4.2.0] @@ -175,11 +174,13 @@ Documentation: - Added public function `signMessageWithPrivateKey` (#7174) ### Fixed -- Fix `TransactionFactory.registerTransactionType` not working, if there is a version mistatch between `web3-eth` and `web3-eth-accounts` by saving `extraTxTypes` at `globals`. (#7197) + +- Fix `TransactionFactory.registerTransactionType` not working, if there is a version mistatch between `web3-eth` and `web3-eth-accounts` by saving `extraTxTypes` at `globals`. (#7197) ## [4.2.1] ### Fixed -- Revert `TransactionFactory.registerTransactionType` if there is a version mistatch between `web3-eth` and `web3-eth-accounts` and fix nextjs problem. (#7216) + +- Revert `TransactionFactory.registerTransactionType` if there is a version mistatch between `web3-eth` and `web3-eth-accounts` and fix nextjs problem. (#7216) ## [Unreleased] diff --git a/packages/web3-eth-accounts/src/account.ts b/packages/web3-eth-accounts/src/account.ts index ac8e0adcfc6..e928a95f53f 100644 --- a/packages/web3-eth-accounts/src/account.ts +++ b/packages/web3-eth-accounts/src/account.ts @@ -172,7 +172,7 @@ export const hashMessage = (message: string): string => { /** * Takes a hash of a message and a private key, signs the message using the SECP256k1 elliptic curve algorithm, and returns the signature components. - * @param hash - The hash of the message to be signed, represented as a hexadecimal string. + * @param hash - The hash of the message to be signed, represented as a hexadecimal string. * @param privateKey - The private key used to sign the message, represented as a byte array. * @returns - The signature Object containing the message, messageHash, signature r, s, v */ diff --git a/packages/web3-eth-accounts/src/common/chains/goerli.ts b/packages/web3-eth-accounts/src/common/chains/goerli.ts index d09be79d2cc..f49b1f0bc8c 100644 --- a/packages/web3-eth-accounts/src/common/chains/goerli.ts +++ b/packages/web3-eth-accounts/src/common/chains/goerli.ts @@ -1,97 +1,98 @@ export default { - "name": "goerli", - "chainId": 5, - "networkId": 5, - "defaultHardfork": "merge", - "consensus": { - "type": "poa", - "algorithm": "clique", - "clique": { - "period": 15, - "epoch": 30000 - } + name: 'goerli', + chainId: 5, + networkId: 5, + defaultHardfork: 'merge', + consensus: { + type: 'poa', + algorithm: 'clique', + clique: { + period: 15, + epoch: 30000, + }, }, - "comment": "Cross-client PoA test network", - "url": "https://github.com/goerli/testnet", - "genesis": { - "timestamp": "0x5c51a607", - "gasLimit": 10485760, - "difficulty": 1, - "nonce": "0x0000000000000000", - "extraData": "0x22466c6578692069732061207468696e6722202d204166726900000000000000e0a2bd4258d2768837baa26a28fe71dc079f84c70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + comment: 'Cross-client PoA test network', + url: 'https://github.com/goerli/testnet', + genesis: { + timestamp: '0x5c51a607', + gasLimit: 10485760, + difficulty: 1, + nonce: '0x0000000000000000', + extraData: + '0x22466c6578692069732061207468696e6722202d204166726900000000000000e0a2bd4258d2768837baa26a28fe71dc079f84c70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', }, - "hardforks": [ + hardforks: [ { - "name": "chainstart", - "block": 0, - "forkHash": "0xa3f5ab08" + name: 'chainstart', + block: 0, + forkHash: '0xa3f5ab08', }, { - "name": "homestead", - "block": 0, - "forkHash": "0xa3f5ab08" + name: 'homestead', + block: 0, + forkHash: '0xa3f5ab08', }, { - "name": "tangerineWhistle", - "block": 0, - "forkHash": "0xa3f5ab08" + name: 'tangerineWhistle', + block: 0, + forkHash: '0xa3f5ab08', }, { - "name": "spuriousDragon", - "block": 0, - "forkHash": "0xa3f5ab08" + name: 'spuriousDragon', + block: 0, + forkHash: '0xa3f5ab08', }, { - "name": "byzantium", - "block": 0, - "forkHash": "0xa3f5ab08" + name: 'byzantium', + block: 0, + forkHash: '0xa3f5ab08', }, { - "name": "constantinople", - "block": 0, - "forkHash": "0xa3f5ab08" + name: 'constantinople', + block: 0, + forkHash: '0xa3f5ab08', }, { - "name": "petersburg", - "block": 0, - "forkHash": "0xa3f5ab08" + name: 'petersburg', + block: 0, + forkHash: '0xa3f5ab08', }, { - "name": "istanbul", - "block": 1561651, - "forkHash": "0xc25efa5c" + name: 'istanbul', + block: 1561651, + forkHash: '0xc25efa5c', }, { - "name": "berlin", - "block": 4460644, - "forkHash": "0x757a1c47" + name: 'berlin', + block: 4460644, + forkHash: '0x757a1c47', }, { - "name": "london", - "block": 5062605, - "forkHash": "0xb8c6299d" + name: 'london', + block: 5062605, + forkHash: '0xb8c6299d', }, { - "//_comment": "The forkHash will remain same as mergeForkIdTransition is post merge, terminal block: https://goerli.etherscan.io/block/7382818", - "name": "merge", - "ttd": "10790000", - "block": 7382819, - "forkHash": "0xb8c6299d" + '//_comment': + 'The forkHash will remain same as mergeForkIdTransition is post merge, terminal block: https://goerli.etherscan.io/block/7382818', + name: 'merge', + ttd: '10790000', + block: 7382819, + forkHash: '0xb8c6299d', }, { - "name": "mergeForkIdTransition", - "block": null, - "forkHash": null + name: 'mergeForkIdTransition', + block: null, + forkHash: null, }, { - "name": "shanghai", - "block": null, - "forkHash": null - } + name: 'shanghai', + block: null, + forkHash: null, + }, + ], + bootstrapNodes: [], + dnsNetworks: [ + 'enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@all.goerli.ethdisco.net', ], - "bootstrapNodes": [], - "dnsNetworks": [ - "enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@all.goerli.ethdisco.net" - ] -} - ; \ No newline at end of file +}; diff --git a/packages/web3-eth-accounts/src/common/chains/mainnet.ts b/packages/web3-eth-accounts/src/common/chains/mainnet.ts index d18bc733a94..356d6472568 100644 --- a/packages/web3-eth-accounts/src/common/chains/mainnet.ts +++ b/packages/web3-eth-accounts/src/common/chains/mainnet.ts @@ -1,113 +1,113 @@ export default { - "name": "mainnet", - "chainId": 1, - "networkId": 1, - "defaultHardfork": "merge", - "consensus": { - "type": "pow", - "algorithm": "ethash", - "ethash": {} + name: 'mainnet', + chainId: 1, + networkId: 1, + defaultHardfork: 'merge', + consensus: { + type: 'pow', + algorithm: 'ethash', + ethash: {}, }, - "comment": "The Ethereum main chain", - "url": "https://ethstats.net/", - "genesis": { - "gasLimit": 5000, - "difficulty": 17179869184, - "nonce": "0x0000000000000042", - "extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa" + comment: 'The Ethereum main chain', + url: 'https://ethstats.net/', + genesis: { + gasLimit: 5000, + difficulty: 17179869184, + nonce: '0x0000000000000042', + extraData: '0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa', }, - "hardforks": [ + hardforks: [ { - "name": "chainstart", - "block": 0, - "forkHash": "0xfc64ec04" + name: 'chainstart', + block: 0, + forkHash: '0xfc64ec04', }, { - "name": "homestead", - "block": 1150000, - "forkHash": "0x97c2c34c" + name: 'homestead', + block: 1150000, + forkHash: '0x97c2c34c', }, { - "name": "dao", - "block": 1920000, - "forkHash": "0x91d1f948" + name: 'dao', + block: 1920000, + forkHash: '0x91d1f948', }, { - "name": "tangerineWhistle", - "block": 2463000, - "forkHash": "0x7a64da13" + name: 'tangerineWhistle', + block: 2463000, + forkHash: '0x7a64da13', }, { - "name": "spuriousDragon", - "block": 2675000, - "forkHash": "0x3edd5b10" + name: 'spuriousDragon', + block: 2675000, + forkHash: '0x3edd5b10', }, { - "name": "byzantium", - "block": 4370000, - "forkHash": "0xa00bc324" + name: 'byzantium', + block: 4370000, + forkHash: '0xa00bc324', }, { - "name": "constantinople", - "block": 7280000, - "forkHash": "0x668db0af" + name: 'constantinople', + block: 7280000, + forkHash: '0x668db0af', }, { - "name": "petersburg", - "block": 7280000, - "forkHash": "0x668db0af" + name: 'petersburg', + block: 7280000, + forkHash: '0x668db0af', }, { - "name": "istanbul", - "block": 9069000, - "forkHash": "0x879d6e30" + name: 'istanbul', + block: 9069000, + forkHash: '0x879d6e30', }, { - "name": "muirGlacier", - "block": 9200000, - "forkHash": "0xe029e991" + name: 'muirGlacier', + block: 9200000, + forkHash: '0xe029e991', }, { - "name": "berlin", - "block": 12244000, - "forkHash": "0x0eb440f6" + name: 'berlin', + block: 12244000, + forkHash: '0x0eb440f6', }, { - "name": "london", - "block": 12965000, - "forkHash": "0xb715077d" + name: 'london', + block: 12965000, + forkHash: '0xb715077d', }, { - "name": "arrowGlacier", - "block": 13773000, - "forkHash": "0x20c327fc" + name: 'arrowGlacier', + block: 13773000, + forkHash: '0x20c327fc', }, { - "name": "grayGlacier", - "block": 15050000, - "forkHash": "0xf0afd0e3" + name: 'grayGlacier', + block: 15050000, + forkHash: '0xf0afd0e3', }, { - "//_comment": "The forkHash will remain same as mergeForkIdTransition is post merge, terminal block: https://etherscan.io/block/15537393", - "name": "merge", - "ttd": "58750000000000000000000", - "block": 15537394, - "forkHash": "0xf0afd0e3" + '//_comment': + 'The forkHash will remain same as mergeForkIdTransition is post merge, terminal block: https://etherscan.io/block/15537393', + name: 'merge', + ttd: '58750000000000000000000', + block: 15537394, + forkHash: '0xf0afd0e3', }, { - "name": "mergeForkIdTransition", - "block": null, - "forkHash": null + name: 'mergeForkIdTransition', + block: null, + forkHash: null, }, { - "name": "shanghai", - "block": null, - "forkHash": null - } + name: 'shanghai', + block: null, + forkHash: null, + }, + ], + bootstrapNodes: [], + dnsNetworks: [ + 'enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@all.mainnet.ethdisco.net', ], - "bootstrapNodes": [], - "dnsNetworks": [ - "enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@all.mainnet.ethdisco.net" - ] -} - ; \ No newline at end of file +}; diff --git a/packages/web3-eth-accounts/src/common/chains/sepolia.ts b/packages/web3-eth-accounts/src/common/chains/sepolia.ts index 1de20e440ee..f861601d06d 100644 --- a/packages/web3-eth-accounts/src/common/chains/sepolia.ts +++ b/packages/web3-eth-accounts/src/common/chains/sepolia.ts @@ -1,100 +1,100 @@ export default { - "name": "sepolia", - "chainId": 11155111, - "networkId": 11155111, - "defaultHardfork": "merge", - "consensus": { - "type": "pow", - "algorithm": "ethash", - "ethash": {} + name: 'sepolia', + chainId: 11155111, + networkId: 11155111, + defaultHardfork: 'merge', + consensus: { + type: 'pow', + algorithm: 'ethash', + ethash: {}, }, - "comment": "PoW test network to replace Ropsten", - "url": "https://github.com/ethereum/go-ethereum/pull/23730", - "genesis": { - "timestamp": "0x6159af19", - "gasLimit": 30000000, - "difficulty": 131072, - "nonce": "0x0000000000000000", - "extraData": "0x5365706f6c69612c20417468656e732c204174746963612c2047726565636521" + comment: 'PoW test network to replace Ropsten', + url: 'https://github.com/ethereum/go-ethereum/pull/23730', + genesis: { + timestamp: '0x6159af19', + gasLimit: 30000000, + difficulty: 131072, + nonce: '0x0000000000000000', + extraData: '0x5365706f6c69612c20417468656e732c204174746963612c2047726565636521', }, - "hardforks": [ + hardforks: [ { - "name": "chainstart", - "block": 0, - "forkHash": "0xfe3366e7" + name: 'chainstart', + block: 0, + forkHash: '0xfe3366e7', }, { - "name": "homestead", - "block": 0, - "forkHash": "0xfe3366e7" + name: 'homestead', + block: 0, + forkHash: '0xfe3366e7', }, { - "name": "tangerineWhistle", - "block": 0, - "forkHash": "0xfe3366e7" + name: 'tangerineWhistle', + block: 0, + forkHash: '0xfe3366e7', }, { - "name": "spuriousDragon", - "block": 0, - "forkHash": "0xfe3366e7" + name: 'spuriousDragon', + block: 0, + forkHash: '0xfe3366e7', }, { - "name": "byzantium", - "block": 0, - "forkHash": "0xfe3366e7" + name: 'byzantium', + block: 0, + forkHash: '0xfe3366e7', }, { - "name": "constantinople", - "block": 0, - "forkHash": "0xfe3366e7" + name: 'constantinople', + block: 0, + forkHash: '0xfe3366e7', }, { - "name": "petersburg", - "block": 0, - "forkHash": "0xfe3366e7" + name: 'petersburg', + block: 0, + forkHash: '0xfe3366e7', }, { - "name": "istanbul", - "block": 0, - "forkHash": "0xfe3366e7" + name: 'istanbul', + block: 0, + forkHash: '0xfe3366e7', }, { - "name": "muirGlacier", - "block": 0, - "forkHash": "0xfe3366e7" + name: 'muirGlacier', + block: 0, + forkHash: '0xfe3366e7', }, { - "name": "berlin", - "block": 0, - "forkHash": "0xfe3366e7" + name: 'berlin', + block: 0, + forkHash: '0xfe3366e7', }, { - "name": "london", - "block": 0, - "forkHash": "0xfe3366e7" + name: 'london', + block: 0, + forkHash: '0xfe3366e7', }, { - "//_comment": "The forkHash will remain same as mergeForkIdTransition is post merge, terminal block: https://sepolia.etherscan.io/block/1450408", - "name": "merge", - "ttd": "17000000000000000", - "block": 1450409, - "forkHash": "0xfe3366e7" + '//_comment': + 'The forkHash will remain same as mergeForkIdTransition is post merge, terminal block: https://sepolia.etherscan.io/block/1450408', + name: 'merge', + ttd: '17000000000000000', + block: 1450409, + forkHash: '0xfe3366e7', }, { - "name": "mergeForkIdTransition", - "block": 1735371, - "forkHash": "0xb96cbd13" + name: 'mergeForkIdTransition', + block: 1735371, + forkHash: '0xb96cbd13', }, { - "name": "shanghai", - "block": null, - "timestamp": "1677557088", - "forkHash": "0xf7f9bc08" - } + name: 'shanghai', + block: null, + timestamp: '1677557088', + forkHash: '0xf7f9bc08', + }, + ], + bootstrapNodes: [], + dnsNetworks: [ + 'enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@all.sepolia.ethdisco.net', ], - "bootstrapNodes": [], - "dnsNetworks": [ - "enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@all.sepolia.ethdisco.net" - ] -} - ; \ No newline at end of file +}; diff --git a/packages/web3-eth-accounts/src/common/eips/1153.ts b/packages/web3-eth-accounts/src/common/eips/1153.ts index a7440d29d19..ee2a9dbc9e9 100644 --- a/packages/web3-eth-accounts/src/common/eips/1153.ts +++ b/packages/web3-eth-accounts/src/common/eips/1153.ts @@ -1,23 +1,22 @@ export default { - "name": "EIP-1153", - "number": 1153, - "comment": "Transient Storage", - "url": "https://eips.ethereum.org/EIPS/eip-1153", - "status": "Review", - "minimumHardfork": "chainstart", - "requiredEIPs": [], - "gasConfig": {}, - "gasPrices": { - "tstore": { - "v": 100, - "d": "Base fee of the TSTORE opcode" + name: 'EIP-1153', + number: 1153, + comment: 'Transient Storage', + url: 'https://eips.ethereum.org/EIPS/eip-1153', + status: 'Review', + minimumHardfork: 'chainstart', + requiredEIPs: [], + gasConfig: {}, + gasPrices: { + tstore: { + v: 100, + d: 'Base fee of the TSTORE opcode', + }, + tload: { + v: 100, + d: 'Base fee of the TLOAD opcode', }, - "tload": { - "v": 100, - "d": "Base fee of the TLOAD opcode" - } }, - "vm": {}, - "pow": {} -} - ; \ No newline at end of file + vm: {}, + pow: {}, +}; diff --git a/packages/web3-eth-accounts/src/common/eips/1559.ts b/packages/web3-eth-accounts/src/common/eips/1559.ts index ef3f04422e9..3a070138543 100644 --- a/packages/web3-eth-accounts/src/common/eips/1559.ts +++ b/packages/web3-eth-accounts/src/common/eips/1559.ts @@ -1,27 +1,26 @@ export default { - "name": "EIP-1559", - "number": 1559, - "comment": "Fee market change for ETH 1.0 chain", - "url": "https://eips.ethereum.org/EIPS/eip-1559", - "status": "Final", - "minimumHardfork": "berlin", - "requiredEIPs": [2930], - "gasConfig": { - "baseFeeMaxChangeDenominator": { - "v": 8, - "d": "Maximum base fee change denominator" + name: 'EIP-1559', + number: 1559, + comment: 'Fee market change for ETH 1.0 chain', + url: 'https://eips.ethereum.org/EIPS/eip-1559', + status: 'Final', + minimumHardfork: 'berlin', + requiredEIPs: [2930], + gasConfig: { + baseFeeMaxChangeDenominator: { + v: 8, + d: 'Maximum base fee change denominator', }, - "elasticityMultiplier": { - "v": 2, - "d": "Maximum block gas target elasticity" + elasticityMultiplier: { + v: 2, + d: 'Maximum block gas target elasticity', + }, + initialBaseFee: { + v: 1000000000, + d: 'Initial base fee on first EIP1559 block', }, - "initialBaseFee": { - "v": 1000000000, - "d": "Initial base fee on first EIP1559 block" - } }, - "gasPrices": {}, - "vm": {}, - "pow": {} -} - ; \ No newline at end of file + gasPrices: {}, + vm: {}, + pow: {}, +}; diff --git a/packages/web3-eth-accounts/src/common/eips/2315.ts b/packages/web3-eth-accounts/src/common/eips/2315.ts index d29efa3049d..11ed6b5c2fe 100644 --- a/packages/web3-eth-accounts/src/common/eips/2315.ts +++ b/packages/web3-eth-accounts/src/common/eips/2315.ts @@ -1,26 +1,25 @@ export default { - "name": "EIP-2315", - "number": 2315, - "comment": "Simple subroutines for the EVM", - "url": "https://eips.ethereum.org/EIPS/eip-2315", - "status": "Draft", - "minimumHardfork": "istanbul", - "gasConfig": {}, - "gasPrices": { - "beginsub": { - "v": 2, - "d": "Base fee of the BEGINSUB opcode" + name: 'EIP-2315', + number: 2315, + comment: 'Simple subroutines for the EVM', + url: 'https://eips.ethereum.org/EIPS/eip-2315', + status: 'Draft', + minimumHardfork: 'istanbul', + gasConfig: {}, + gasPrices: { + beginsub: { + v: 2, + d: 'Base fee of the BEGINSUB opcode', }, - "returnsub": { - "v": 5, - "d": "Base fee of the RETURNSUB opcode" + returnsub: { + v: 5, + d: 'Base fee of the RETURNSUB opcode', + }, + jumpsub: { + v: 10, + d: 'Base fee of the JUMPSUB opcode', }, - "jumpsub": { - "v": 10, - "d": "Base fee of the JUMPSUB opcode" - } }, - "vm": {}, - "pow": {} -} - ; \ No newline at end of file + vm: {}, + pow: {}, +}; diff --git a/packages/web3-eth-accounts/src/common/eips/2537.ts b/packages/web3-eth-accounts/src/common/eips/2537.ts index 14fa62abdb1..b8cc037a717 100644 --- a/packages/web3-eth-accounts/src/common/eips/2537.ts +++ b/packages/web3-eth-accounts/src/common/eips/2537.ts @@ -1,46 +1,46 @@ export default { - "name": "EIP-2537", - "number": 2537, - "comment": "BLS12-381 precompiles", - "url": "https://eips.ethereum.org/EIPS/eip-2537", - "status": "Draft", - "minimumHardfork": "chainstart", - "gasConfig": {}, - "gasPrices": { - "Bls12381G1AddGas": { - "v": 600, - "d": "Gas cost of a single BLS12-381 G1 addition precompile-call" + name: 'EIP-2537', + number: 2537, + comment: 'BLS12-381 precompiles', + url: 'https://eips.ethereum.org/EIPS/eip-2537', + status: 'Draft', + minimumHardfork: 'chainstart', + gasConfig: {}, + gasPrices: { + Bls12381G1AddGas: { + v: 600, + d: 'Gas cost of a single BLS12-381 G1 addition precompile-call', }, - "Bls12381G1MulGas": { - "v": 12000, - "d": "Gas cost of a single BLS12-381 G1 multiplication precompile-call" + Bls12381G1MulGas: { + v: 12000, + d: 'Gas cost of a single BLS12-381 G1 multiplication precompile-call', }, - "Bls12381G2AddGas": { - "v": 4500, - "d": "Gas cost of a single BLS12-381 G2 addition precompile-call" + Bls12381G2AddGas: { + v: 4500, + d: 'Gas cost of a single BLS12-381 G2 addition precompile-call', }, - "Bls12381G2MulGas": { - "v": 55000, - "d": "Gas cost of a single BLS12-381 G2 multiplication precompile-call" + Bls12381G2MulGas: { + v: 55000, + d: 'Gas cost of a single BLS12-381 G2 multiplication precompile-call', }, - "Bls12381PairingBaseGas": { - "v": 115000, - "d": "Base gas cost of BLS12-381 pairing check" + Bls12381PairingBaseGas: { + v: 115000, + d: 'Base gas cost of BLS12-381 pairing check', }, - "Bls12381PairingPerPairGas": { - "v": 23000, - "d": "Per-pair gas cost of BLS12-381 pairing check" + Bls12381PairingPerPairGas: { + v: 23000, + d: 'Per-pair gas cost of BLS12-381 pairing check', }, - "Bls12381MapG1Gas": { - "v": 5500, - "d": "Gas cost of BLS12-381 map field element to G1" + Bls12381MapG1Gas: { + v: 5500, + d: 'Gas cost of BLS12-381 map field element to G1', }, - "Bls12381MapG2Gas": { - "v": 110000, - "d": "Gas cost of BLS12-381 map field element to G2" + Bls12381MapG2Gas: { + v: 110000, + d: 'Gas cost of BLS12-381 map field element to G2', }, - "Bls12381MultiExpGasDiscount": { - "v": [ + Bls12381MultiExpGasDiscount: { + v: [ [1, 1200], [2, 888], [3, 764], @@ -168,12 +168,11 @@ export default { [125, 176], [126, 176], [127, 175], - [128, 174] + [128, 174], ], - "d": "Discount gas costs of calls to the MultiExp precompiles with `k` (point, scalar) pair" - } + d: 'Discount gas costs of calls to the MultiExp precompiles with `k` (point, scalar) pair', + }, }, - "vm": {}, - "pow": {} -} - ; \ No newline at end of file + vm: {}, + pow: {}, +}; diff --git a/packages/web3-eth-accounts/src/common/eips/2565.ts b/packages/web3-eth-accounts/src/common/eips/2565.ts index 1c1743e9a16..27d223b2ec5 100644 --- a/packages/web3-eth-accounts/src/common/eips/2565.ts +++ b/packages/web3-eth-accounts/src/common/eips/2565.ts @@ -1,18 +1,17 @@ export default { - "name": "EIP-2565", - "number": 2565, - "comment": "ModExp gas cost", - "url": "https://eips.ethereum.org/EIPS/eip-2565", - "status": "Final", - "minimumHardfork": "byzantium", - "gasConfig": {}, - "gasPrices": { - "modexpGquaddivisor": { - "v": 3, - "d": "Gquaddivisor from modexp precompile for gas calculation" - } + name: 'EIP-2565', + number: 2565, + comment: 'ModExp gas cost', + url: 'https://eips.ethereum.org/EIPS/eip-2565', + status: 'Final', + minimumHardfork: 'byzantium', + gasConfig: {}, + gasPrices: { + modexpGquaddivisor: { + v: 3, + d: 'Gquaddivisor from modexp precompile for gas calculation', + }, }, - "vm": {}, - "pow": {} -} - ; \ No newline at end of file + vm: {}, + pow: {}, +}; diff --git a/packages/web3-eth-accounts/src/common/eips/2718.ts b/packages/web3-eth-accounts/src/common/eips/2718.ts index f8815c6d7b1..fe59a38fd85 100644 --- a/packages/web3-eth-accounts/src/common/eips/2718.ts +++ b/packages/web3-eth-accounts/src/common/eips/2718.ts @@ -1,12 +1,11 @@ export default { - "name": "EIP-2718", - "comment": "Typed Transaction Envelope", - "url": "https://eips.ethereum.org/EIPS/eip-2718", - "status": "Final", - "minimumHardfork": "chainstart", - "gasConfig": {}, - "gasPrices": {}, - "vm": {}, - "pow": {} -} - ; \ No newline at end of file + name: 'EIP-2718', + comment: 'Typed Transaction Envelope', + url: 'https://eips.ethereum.org/EIPS/eip-2718', + status: 'Final', + minimumHardfork: 'chainstart', + gasConfig: {}, + gasPrices: {}, + vm: {}, + pow: {}, +}; diff --git a/packages/web3-eth-accounts/src/common/eips/2929.ts b/packages/web3-eth-accounts/src/common/eips/2929.ts index f52dc217d3f..cbd9dc3103b 100644 --- a/packages/web3-eth-accounts/src/common/eips/2929.ts +++ b/packages/web3-eth-accounts/src/common/eips/2929.ts @@ -1,85 +1,84 @@ export default { - "name": "EIP-2929", - "comment": "Gas cost increases for state access opcodes", - "url": "https://eips.ethereum.org/EIPS/eip-2929", - "status": "Final", - "minimumHardfork": "chainstart", - "gasConfig": {}, - "gasPrices": { - "coldsload": { - "v": 2100, - "d": "Gas cost of the first read of storage from a given location (per transaction)" - }, - "coldaccountaccess": { - "v": 2600, - "d": "Gas cost of the first read of a given address (per transaction)" - }, - "warmstorageread": { - "v": 100, - "d": "Gas cost of reading storage locations which have already loaded 'cold'" - }, - "sstoreCleanGasEIP2200": { - "v": 2900, - "d": "Once per SSTORE operation from clean non-zero to something else" - }, - "sstoreNoopGasEIP2200": { - "v": 100, - "d": "Once per SSTORE operation if the value doesn't change" - }, - "sstoreDirtyGasEIP2200": { - "v": 100, - "d": "Once per SSTORE operation if a dirty value is changed" - }, - "sstoreInitRefundEIP2200": { - "v": 19900, - "d": "Once per SSTORE operation for resetting to the original zero value" - }, - "sstoreCleanRefundEIP2200": { - "v": 4900, - "d": "Once per SSTORE operation for resetting to the original non-zero value" - }, - "call": { - "v": 0, - "d": "Base fee of the CALL opcode" - }, - "callcode": { - "v": 0, - "d": "Base fee of the CALLCODE opcode" - }, - "delegatecall": { - "v": 0, - "d": "Base fee of the DELEGATECALL opcode" - }, - "staticcall": { - "v": 0, - "d": "Base fee of the STATICCALL opcode" - }, - "balance": { - "v": 0, - "d": "Base fee of the BALANCE opcode" - }, - "extcodesize": { - "v": 0, - "d": "Base fee of the EXTCODESIZE opcode" - }, - "extcodecopy": { - "v": 0, - "d": "Base fee of the EXTCODECOPY opcode" - }, - "extcodehash": { - "v": 0, - "d": "Base fee of the EXTCODEHASH opcode" - }, - "sload": { - "v": 0, - "d": "Base fee of the SLOAD opcode" - }, - "sstore": { - "v": 0, - "d": "Base fee of the SSTORE opcode" - } + name: 'EIP-2929', + comment: 'Gas cost increases for state access opcodes', + url: 'https://eips.ethereum.org/EIPS/eip-2929', + status: 'Final', + minimumHardfork: 'chainstart', + gasConfig: {}, + gasPrices: { + coldsload: { + v: 2100, + d: 'Gas cost of the first read of storage from a given location (per transaction)', + }, + coldaccountaccess: { + v: 2600, + d: 'Gas cost of the first read of a given address (per transaction)', + }, + warmstorageread: { + v: 100, + d: "Gas cost of reading storage locations which have already loaded 'cold'", + }, + sstoreCleanGasEIP2200: { + v: 2900, + d: 'Once per SSTORE operation from clean non-zero to something else', + }, + sstoreNoopGasEIP2200: { + v: 100, + d: "Once per SSTORE operation if the value doesn't change", + }, + sstoreDirtyGasEIP2200: { + v: 100, + d: 'Once per SSTORE operation if a dirty value is changed', + }, + sstoreInitRefundEIP2200: { + v: 19900, + d: 'Once per SSTORE operation for resetting to the original zero value', + }, + sstoreCleanRefundEIP2200: { + v: 4900, + d: 'Once per SSTORE operation for resetting to the original non-zero value', + }, + call: { + v: 0, + d: 'Base fee of the CALL opcode', + }, + callcode: { + v: 0, + d: 'Base fee of the CALLCODE opcode', + }, + delegatecall: { + v: 0, + d: 'Base fee of the DELEGATECALL opcode', + }, + staticcall: { + v: 0, + d: 'Base fee of the STATICCALL opcode', + }, + balance: { + v: 0, + d: 'Base fee of the BALANCE opcode', + }, + extcodesize: { + v: 0, + d: 'Base fee of the EXTCODESIZE opcode', + }, + extcodecopy: { + v: 0, + d: 'Base fee of the EXTCODECOPY opcode', + }, + extcodehash: { + v: 0, + d: 'Base fee of the EXTCODEHASH opcode', + }, + sload: { + v: 0, + d: 'Base fee of the SLOAD opcode', + }, + sstore: { + v: 0, + d: 'Base fee of the SSTORE opcode', + }, }, - "vm": {}, - "pow": {} -} - ; \ No newline at end of file + vm: {}, + pow: {}, +}; diff --git a/packages/web3-eth-accounts/src/common/eips/2930.ts b/packages/web3-eth-accounts/src/common/eips/2930.ts index 52500d0c94a..0ea09e49d40 100644 --- a/packages/web3-eth-accounts/src/common/eips/2930.ts +++ b/packages/web3-eth-accounts/src/common/eips/2930.ts @@ -1,22 +1,21 @@ export default { - "name": "EIP-2930", - "comment": "Optional access lists", - "url": "https://eips.ethereum.org/EIPS/eip-2930", - "status": "Final", - "minimumHardfork": "istanbul", - "requiredEIPs": [2718, 2929], - "gasConfig": {}, - "gasPrices": { - "accessListStorageKeyCost": { - "v": 1900, - "d": "Gas cost per storage key in an Access List transaction" + name: 'EIP-2930', + comment: 'Optional access lists', + url: 'https://eips.ethereum.org/EIPS/eip-2930', + status: 'Final', + minimumHardfork: 'istanbul', + requiredEIPs: [2718, 2929], + gasConfig: {}, + gasPrices: { + accessListStorageKeyCost: { + v: 1900, + d: 'Gas cost per storage key in an Access List transaction', + }, + accessListAddressCost: { + v: 2400, + d: 'Gas cost per storage key in an Access List transaction', }, - "accessListAddressCost": { - "v": 2400, - "d": "Gas cost per storage key in an Access List transaction" - } }, - "vm": {}, - "pow": {} -} - ; \ No newline at end of file + vm: {}, + pow: {}, +}; diff --git a/packages/web3-eth-accounts/src/common/eips/3074.ts b/packages/web3-eth-accounts/src/common/eips/3074.ts index 538b0569819..92cfc955aa9 100644 --- a/packages/web3-eth-accounts/src/common/eips/3074.ts +++ b/packages/web3-eth-accounts/src/common/eips/3074.ts @@ -1,26 +1,25 @@ export default { - "name": "EIP-3074", - "number": 3074, - "comment": "AUTH and AUTHCALL opcodes", - "url": "https://eips.ethereum.org/EIPS/eip-3074", - "status": "Review", - "minimumHardfork": "london", - "gasConfig": {}, - "gasPrices": { - "auth": { - "v": 3100, - "d": "Gas cost of the AUTH opcode" + name: 'EIP-3074', + number: 3074, + comment: 'AUTH and AUTHCALL opcodes', + url: 'https://eips.ethereum.org/EIPS/eip-3074', + status: 'Review', + minimumHardfork: 'london', + gasConfig: {}, + gasPrices: { + auth: { + v: 3100, + d: 'Gas cost of the AUTH opcode', }, - "authcall": { - "v": 0, - "d": "Gas cost of the AUTHCALL opcode" + authcall: { + v: 0, + d: 'Gas cost of the AUTHCALL opcode', + }, + authcallValueTransfer: { + v: 6700, + d: 'Paid for CALL when the value transfer is non-zero', }, - "authcallValueTransfer": { - "v": 6700, - "d": "Paid for CALL when the value transfer is non-zero" - } }, - "vm": {}, - "pow": {} -} - ; \ No newline at end of file + vm: {}, + pow: {}, +}; diff --git a/packages/web3-eth-accounts/src/common/eips/3198.ts b/packages/web3-eth-accounts/src/common/eips/3198.ts index d949d976359..73c55d3ac49 100644 --- a/packages/web3-eth-accounts/src/common/eips/3198.ts +++ b/packages/web3-eth-accounts/src/common/eips/3198.ts @@ -1,18 +1,17 @@ export default { - "name": "EIP-3198", - "number": 3198, - "comment": "BASEFEE opcode", - "url": "https://eips.ethereum.org/EIPS/eip-3198", - "status": "Final", - "minimumHardfork": "london", - "gasConfig": {}, - "gasPrices": { - "basefee": { - "v": 2, - "d": "Gas cost of the BASEFEE opcode" - } + name: 'EIP-3198', + number: 3198, + comment: 'BASEFEE opcode', + url: 'https://eips.ethereum.org/EIPS/eip-3198', + status: 'Final', + minimumHardfork: 'london', + gasConfig: {}, + gasPrices: { + basefee: { + v: 2, + d: 'Gas cost of the BASEFEE opcode', + }, }, - "vm": {}, - "pow": {} -} - ; \ No newline at end of file + vm: {}, + pow: {}, +}; diff --git a/packages/web3-eth-accounts/src/common/eips/3529.ts b/packages/web3-eth-accounts/src/common/eips/3529.ts index 2e8b0e39888..9e935b4ab07 100644 --- a/packages/web3-eth-accounts/src/common/eips/3529.ts +++ b/packages/web3-eth-accounts/src/common/eips/3529.ts @@ -1,27 +1,26 @@ export default { - "name": "EIP-3529", - "comment": "Reduction in refunds", - "url": "https://eips.ethereum.org/EIPS/eip-3529", - "status": "Final", - "minimumHardfork": "berlin", - "requiredEIPs": [2929], - "gasConfig": { - "maxRefundQuotient": { - "v": 5, - "d": "Maximum refund quotient; max tx refund is min(tx.gasUsed/maxRefundQuotient, tx.gasRefund)" - } + name: 'EIP-3529', + comment: 'Reduction in refunds', + url: 'https://eips.ethereum.org/EIPS/eip-3529', + status: 'Final', + minimumHardfork: 'berlin', + requiredEIPs: [2929], + gasConfig: { + maxRefundQuotient: { + v: 5, + d: 'Maximum refund quotient; max tx refund is min(tx.gasUsed/maxRefundQuotient, tx.gasRefund)', + }, }, - "gasPrices": { - "selfdestructRefund": { - "v": 0, - "d": "Refunded following a selfdestruct operation" + gasPrices: { + selfdestructRefund: { + v: 0, + d: 'Refunded following a selfdestruct operation', + }, + sstoreClearRefundEIP2200: { + v: 4800, + d: 'Once per SSTORE operation for clearing an originally existing storage slot', }, - "sstoreClearRefundEIP2200": { - "v": 4800, - "d": "Once per SSTORE operation for clearing an originally existing storage slot" - } }, - "vm": {}, - "pow": {} -} - ; \ No newline at end of file + vm: {}, + pow: {}, +}; diff --git a/packages/web3-eth-accounts/src/common/eips/3540.ts b/packages/web3-eth-accounts/src/common/eips/3540.ts index 39fdb91ee43..498e6ac3094 100644 --- a/packages/web3-eth-accounts/src/common/eips/3540.ts +++ b/packages/web3-eth-accounts/src/common/eips/3540.ts @@ -1,14 +1,13 @@ export default { - "name": "EIP-3540", - "number": 3540, - "comment": "EVM Object Format (EOF) v1", - "url": "https://eips.ethereum.org/EIPS/eip-3540", - "status": "Review", - "minimumHardfork": "london", - "requiredEIPs": [3541], - "gasConfig": {}, - "gasPrices": {}, - "vm": {}, - "pow": {} -} - ; \ No newline at end of file + name: 'EIP-3540', + number: 3540, + comment: 'EVM Object Format (EOF) v1', + url: 'https://eips.ethereum.org/EIPS/eip-3540', + status: 'Review', + minimumHardfork: 'london', + requiredEIPs: [3541], + gasConfig: {}, + gasPrices: {}, + vm: {}, + pow: {}, +}; diff --git a/packages/web3-eth-accounts/src/common/eips/3541.ts b/packages/web3-eth-accounts/src/common/eips/3541.ts index b3e7a0ce823..372b886834f 100644 --- a/packages/web3-eth-accounts/src/common/eips/3541.ts +++ b/packages/web3-eth-accounts/src/common/eips/3541.ts @@ -1,13 +1,12 @@ export default { - "name": "EIP-3541", - "comment": "Reject new contracts starting with the 0xEF byte", - "url": "https://eips.ethereum.org/EIPS/eip-3541", - "status": "Final", - "minimumHardfork": "berlin", - "requiredEIPs": [], - "gasConfig": {}, - "gasPrices": {}, - "vm": {}, - "pow": {} -} - ; \ No newline at end of file + name: 'EIP-3541', + comment: 'Reject new contracts starting with the 0xEF byte', + url: 'https://eips.ethereum.org/EIPS/eip-3541', + status: 'Final', + minimumHardfork: 'berlin', + requiredEIPs: [], + gasConfig: {}, + gasPrices: {}, + vm: {}, + pow: {}, +}; diff --git a/packages/web3-eth-accounts/src/common/eips/3554.ts b/packages/web3-eth-accounts/src/common/eips/3554.ts index 36a9d16ecf2..6f8c04a2ec4 100644 --- a/packages/web3-eth-accounts/src/common/eips/3554.ts +++ b/packages/web3-eth-accounts/src/common/eips/3554.ts @@ -1,18 +1,17 @@ export default { - "name": "EIP-3554", - "comment": "Reduction in refunds", - "url": "Difficulty Bomb Delay to December 1st 2021", - "status": "Final", - "minimumHardfork": "muirGlacier", - "requiredEIPs": [], - "gasConfig": {}, - "gasPrices": {}, - "vm": {}, - "pow": { - "difficultyBombDelay": { - "v": 9500000, - "d": "the amount of blocks to delay the difficulty bomb with" - } - } -} - ; \ No newline at end of file + name: 'EIP-3554', + comment: 'Reduction in refunds', + url: 'Difficulty Bomb Delay to December 1st 2021', + status: 'Final', + minimumHardfork: 'muirGlacier', + requiredEIPs: [], + gasConfig: {}, + gasPrices: {}, + vm: {}, + pow: { + difficultyBombDelay: { + v: 9500000, + d: 'the amount of blocks to delay the difficulty bomb with', + }, + }, +}; diff --git a/packages/web3-eth-accounts/src/common/eips/3607.ts b/packages/web3-eth-accounts/src/common/eips/3607.ts index 6c122728e68..90607ec697f 100644 --- a/packages/web3-eth-accounts/src/common/eips/3607.ts +++ b/packages/web3-eth-accounts/src/common/eips/3607.ts @@ -1,14 +1,13 @@ export default { - "name": "EIP-3607", - "number": 3607, - "comment": "Reject transactions from senders with deployed code", - "url": "https://eips.ethereum.org/EIPS/eip-3607", - "status": "Final", - "minimumHardfork": "chainstart", - "requiredEIPs": [], - "gasConfig": {}, - "gasPrices": {}, - "vm": {}, - "pow": {} -} - ; \ No newline at end of file + name: 'EIP-3607', + number: 3607, + comment: 'Reject transactions from senders with deployed code', + url: 'https://eips.ethereum.org/EIPS/eip-3607', + status: 'Final', + minimumHardfork: 'chainstart', + requiredEIPs: [], + gasConfig: {}, + gasPrices: {}, + vm: {}, + pow: {}, +}; diff --git a/packages/web3-eth-accounts/src/common/eips/3651.ts b/packages/web3-eth-accounts/src/common/eips/3651.ts index c6ebe81da92..65855ca18fb 100644 --- a/packages/web3-eth-accounts/src/common/eips/3651.ts +++ b/packages/web3-eth-accounts/src/common/eips/3651.ts @@ -1,14 +1,13 @@ export default { - "name": "EIP-3651", - "number": 3198, - "comment": "Warm COINBASE", - "url": "https://eips.ethereum.org/EIPS/eip-3651", - "status": "Review", - "minimumHardfork": "london", - "requiredEIPs": [2929], - "gasConfig": {}, - "gasPrices": {}, - "vm": {}, - "pow": {} -} - ; \ No newline at end of file + name: 'EIP-3651', + number: 3198, + comment: 'Warm COINBASE', + url: 'https://eips.ethereum.org/EIPS/eip-3651', + status: 'Review', + minimumHardfork: 'london', + requiredEIPs: [2929], + gasConfig: {}, + gasPrices: {}, + vm: {}, + pow: {}, +}; diff --git a/packages/web3-eth-accounts/src/common/eips/3670.ts b/packages/web3-eth-accounts/src/common/eips/3670.ts index 5b36d99b71f..6edc09bb2bf 100644 --- a/packages/web3-eth-accounts/src/common/eips/3670.ts +++ b/packages/web3-eth-accounts/src/common/eips/3670.ts @@ -1,14 +1,13 @@ export default { - "name": "EIP-3670", - "number": 3670, - "comment": "EOF - Code Validation", - "url": "https://eips.ethereum.org/EIPS/eip-3670", - "status": "Review", - "minimumHardfork": "london", - "requiredEIPs": [3540], - "gasConfig": {}, - "gasPrices": {}, - "vm": {}, - "pow": {} -} - ; \ No newline at end of file + name: 'EIP-3670', + number: 3670, + comment: 'EOF - Code Validation', + url: 'https://eips.ethereum.org/EIPS/eip-3670', + status: 'Review', + minimumHardfork: 'london', + requiredEIPs: [3540], + gasConfig: {}, + gasPrices: {}, + vm: {}, + pow: {}, +}; diff --git a/packages/web3-eth-accounts/src/common/eips/3675.ts b/packages/web3-eth-accounts/src/common/eips/3675.ts index a80350300c7..74d89ebb1f7 100644 --- a/packages/web3-eth-accounts/src/common/eips/3675.ts +++ b/packages/web3-eth-accounts/src/common/eips/3675.ts @@ -1,14 +1,13 @@ export default { - "name": "EIP-3675", - "number": 3675, - "comment": "Upgrade consensus to Proof-of-Stake", - "url": "https://eips.ethereum.org/EIPS/eip-3675", - "status": "Final", - "minimumHardfork": "london", - "requiredEIPs": [], - "gasConfig": {}, - "gasPrices": {}, - "vm": {}, - "pow": {} -} - ; \ No newline at end of file + name: 'EIP-3675', + number: 3675, + comment: 'Upgrade consensus to Proof-of-Stake', + url: 'https://eips.ethereum.org/EIPS/eip-3675', + status: 'Final', + minimumHardfork: 'london', + requiredEIPs: [], + gasConfig: {}, + gasPrices: {}, + vm: {}, + pow: {}, +}; diff --git a/packages/web3-eth-accounts/src/common/eips/3855.ts b/packages/web3-eth-accounts/src/common/eips/3855.ts index 2f5ac0641a5..b1733b4dd9a 100644 --- a/packages/web3-eth-accounts/src/common/eips/3855.ts +++ b/packages/web3-eth-accounts/src/common/eips/3855.ts @@ -1,19 +1,18 @@ export default { - "name": "EIP-3855", - "number": 3855, - "comment": "PUSH0 instruction", - "url": "https://eips.ethereum.org/EIPS/eip-3855", - "status": "Review", - "minimumHardfork": "chainstart", - "requiredEIPs": [], - "gasConfig": {}, - "gasPrices": { - "push0": { - "v": 2, - "d": "Base fee of the PUSH0 opcode" - } + name: 'EIP-3855', + number: 3855, + comment: 'PUSH0 instruction', + url: 'https://eips.ethereum.org/EIPS/eip-3855', + status: 'Review', + minimumHardfork: 'chainstart', + requiredEIPs: [], + gasConfig: {}, + gasPrices: { + push0: { + v: 2, + d: 'Base fee of the PUSH0 opcode', + }, }, - "vm": {}, - "pow": {} -} - ; \ No newline at end of file + vm: {}, + pow: {}, +}; diff --git a/packages/web3-eth-accounts/src/common/eips/3860.ts b/packages/web3-eth-accounts/src/common/eips/3860.ts index 0e1aeb999db..8206e041e18 100644 --- a/packages/web3-eth-accounts/src/common/eips/3860.ts +++ b/packages/web3-eth-accounts/src/common/eips/3860.ts @@ -1,24 +1,23 @@ export default { - "name": "EIP-3860", - "number": 3860, - "comment": "Limit and meter initcode", - "url": "https://eips.ethereum.org/EIPS/eip-3860", - "status": "Review", - "minimumHardfork": "spuriousDragon", - "requiredEIPs": [], - "gasConfig": {}, - "gasPrices": { - "initCodeWordCost": { - "v": 2, - "d": "Gas to pay for each word (32 bytes) of initcode when creating a contract" - } + name: 'EIP-3860', + number: 3860, + comment: 'Limit and meter initcode', + url: 'https://eips.ethereum.org/EIPS/eip-3860', + status: 'Review', + minimumHardfork: 'spuriousDragon', + requiredEIPs: [], + gasConfig: {}, + gasPrices: { + initCodeWordCost: { + v: 2, + d: 'Gas to pay for each word (32 bytes) of initcode when creating a contract', + }, }, - "vm": { - "maxInitCodeSize": { - "v": 49152, - "d": "Maximum length of initialization code when creating a contract" - } + vm: { + maxInitCodeSize: { + v: 49152, + d: 'Maximum length of initialization code when creating a contract', + }, }, - "pow": {} -} - ; \ No newline at end of file + pow: {}, +}; diff --git a/packages/web3-eth-accounts/src/common/eips/4345.ts b/packages/web3-eth-accounts/src/common/eips/4345.ts index 0e571b327c2..2977bf1b194 100644 --- a/packages/web3-eth-accounts/src/common/eips/4345.ts +++ b/packages/web3-eth-accounts/src/common/eips/4345.ts @@ -1,18 +1,17 @@ export default { - "name": "EIP-4345", - "number": 4345, - "comment": "Difficulty Bomb Delay to June 2022", - "url": "https://eips.ethereum.org/EIPS/eip-4345", - "status": "Final", - "minimumHardfork": "london", - "gasConfig": {}, - "gasPrices": {}, - "vm": {}, - "pow": { - "difficultyBombDelay": { - "v": 10700000, - "d": "the amount of blocks to delay the difficulty bomb with" - } - } -} - ; \ No newline at end of file + name: 'EIP-4345', + number: 4345, + comment: 'Difficulty Bomb Delay to June 2022', + url: 'https://eips.ethereum.org/EIPS/eip-4345', + status: 'Final', + minimumHardfork: 'london', + gasConfig: {}, + gasPrices: {}, + vm: {}, + pow: { + difficultyBombDelay: { + v: 10700000, + d: 'the amount of blocks to delay the difficulty bomb with', + }, + }, +}; diff --git a/packages/web3-eth-accounts/src/common/eips/4399.ts b/packages/web3-eth-accounts/src/common/eips/4399.ts index ed948d629de..c06bb9f8db3 100644 --- a/packages/web3-eth-accounts/src/common/eips/4399.ts +++ b/packages/web3-eth-accounts/src/common/eips/4399.ts @@ -1,14 +1,13 @@ export default { - "name": "EIP-4399", - "number": 4399, - "comment": "Supplant DIFFICULTY opcode with PREVRANDAO", - "url": "https://eips.ethereum.org/EIPS/eip-4399", - "status": "Review", - "minimumHardfork": "london", - "requiredEIPs": [], - "gasConfig": {}, - "gasPrices": {}, - "vm": {}, - "pow": {} -} - ; \ No newline at end of file + name: 'EIP-4399', + number: 4399, + comment: 'Supplant DIFFICULTY opcode with PREVRANDAO', + url: 'https://eips.ethereum.org/EIPS/eip-4399', + status: 'Review', + minimumHardfork: 'london', + requiredEIPs: [], + gasConfig: {}, + gasPrices: {}, + vm: {}, + pow: {}, +}; diff --git a/packages/web3-eth-accounts/src/common/eips/4844.ts b/packages/web3-eth-accounts/src/common/eips/4844.ts index 2795067c841..8d4944761fd 100644 --- a/packages/web3-eth-accounts/src/common/eips/4844.ts +++ b/packages/web3-eth-accounts/src/common/eips/4844.ts @@ -1,58 +1,57 @@ export default { - "name": "EIP-4844", - "number": 4844, - "comment": "Shard Blob Transactions", - "url": "https://eips.ethereum.org/EIPS/eip-4844", - "status": "Draft", - "minimumHardfork": "merge", - "requiredEIPs": [1559, 2718, 2930, 4895], - "gasConfig": { - "dataGasPerBlob": { - "v": 131072, - "d": "The base fee for data gas per blob" - }, - "targetDataGasPerBlock": { - "v": 262144, - "d": "The target data gas consumed per block" - }, - "maxDataGasPerBlock": { - "v": 524288, - "d": "The max data gas allowable per block" - }, - "dataGasPriceUpdateFraction": { - "v": 2225652, - "d": "The denominator used in the exponential when calculating a data gas price" - } + name: 'EIP-4844', + number: 4844, + comment: 'Shard Blob Transactions', + url: 'https://eips.ethereum.org/EIPS/eip-4844', + status: 'Draft', + minimumHardfork: 'merge', + requiredEIPs: [1559, 2718, 2930, 4895], + gasConfig: { + dataGasPerBlob: { + v: 131072, + d: 'The base fee for data gas per blob', + }, + targetDataGasPerBlock: { + v: 262144, + d: 'The target data gas consumed per block', + }, + maxDataGasPerBlock: { + v: 524288, + d: 'The max data gas allowable per block', + }, + dataGasPriceUpdateFraction: { + v: 2225652, + d: 'The denominator used in the exponential when calculating a data gas price', + }, }, - "gasPrices": { - "simpleGasPerBlob": { - "v": 12000, - "d": "The basic gas fee for each blob" - }, - "minDataGasPrice": { - "v": 1, - "d": "The minimum fee per data gas" - }, - "kzgPointEvaluationGasPrecompilePrice": { - "v": 50000, - "d": "The fee associated with the point evaluation precompile" - }, - "datahash": { - "v": 3, - "d": "Base fee of the DATAHASH opcode" - } + gasPrices: { + simpleGasPerBlob: { + v: 12000, + d: 'The basic gas fee for each blob', + }, + minDataGasPrice: { + v: 1, + d: 'The minimum fee per data gas', + }, + kzgPointEvaluationGasPrecompilePrice: { + v: 50000, + d: 'The fee associated with the point evaluation precompile', + }, + datahash: { + v: 3, + d: 'Base fee of the DATAHASH opcode', + }, }, - "sharding": { - "blobCommitmentVersionKzg": { - "v": 1, - "d": "The number indicated a versioned hash is a KZG commitment" - }, - "fieldElementsPerBlob": { - "v": 4096, - "d": "The number of field elements allowed per blob" - } + sharding: { + blobCommitmentVersionKzg: { + v: 1, + d: 'The number indicated a versioned hash is a KZG commitment', + }, + fieldElementsPerBlob: { + v: 4096, + d: 'The number of field elements allowed per blob', + }, }, - "vm": {}, - "pow": {} -} - ; \ No newline at end of file + vm: {}, + pow: {}, +}; diff --git a/packages/web3-eth-accounts/src/common/eips/4895.ts b/packages/web3-eth-accounts/src/common/eips/4895.ts index f70f2ec3b35..63bef6b9fce 100644 --- a/packages/web3-eth-accounts/src/common/eips/4895.ts +++ b/packages/web3-eth-accounts/src/common/eips/4895.ts @@ -1,14 +1,13 @@ export default { - "name": "EIP-4895", - "number": 4895, - "comment": "Beacon chain push withdrawals as operations", - "url": "https://eips.ethereum.org/EIPS/eip-4895", - "status": "Review", - "minimumHardfork": "merge", - "requiredEIPs": [], - "gasConfig": {}, - "gasPrices": {}, - "vm": {}, - "pow": {} -} - ; \ No newline at end of file + name: 'EIP-4895', + number: 4895, + comment: 'Beacon chain push withdrawals as operations', + url: 'https://eips.ethereum.org/EIPS/eip-4895', + status: 'Review', + minimumHardfork: 'merge', + requiredEIPs: [], + gasConfig: {}, + gasPrices: {}, + vm: {}, + pow: {}, +}; diff --git a/packages/web3-eth-accounts/src/common/eips/5133.ts b/packages/web3-eth-accounts/src/common/eips/5133.ts index de3b55c9721..c6041029b9b 100644 --- a/packages/web3-eth-accounts/src/common/eips/5133.ts +++ b/packages/web3-eth-accounts/src/common/eips/5133.ts @@ -1,18 +1,17 @@ export default { - "name": "EIP-5133", - "number": 5133, - "comment": "Delaying Difficulty Bomb to mid-September 2022", - "url": "https://eips.ethereum.org/EIPS/eip-5133", - "status": "Draft", - "minimumHardfork": "grayGlacier", - "gasConfig": {}, - "gasPrices": {}, - "vm": {}, - "pow": { - "difficultyBombDelay": { - "v": 11400000, - "d": "the amount of blocks to delay the difficulty bomb with" - } - } -} - ; \ No newline at end of file + name: 'EIP-5133', + number: 5133, + comment: 'Delaying Difficulty Bomb to mid-September 2022', + url: 'https://eips.ethereum.org/EIPS/eip-5133', + status: 'Draft', + minimumHardfork: 'grayGlacier', + gasConfig: {}, + gasPrices: {}, + vm: {}, + pow: { + difficultyBombDelay: { + v: 11400000, + d: 'the amount of blocks to delay the difficulty bomb with', + }, + }, +}; diff --git a/packages/web3-eth-accounts/src/common/hardforks/arrowGlacier.ts b/packages/web3-eth-accounts/src/common/hardforks/arrowGlacier.ts index e38f1782855..901ceaddb6a 100644 --- a/packages/web3-eth-accounts/src/common/hardforks/arrowGlacier.ts +++ b/packages/web3-eth-accounts/src/common/hardforks/arrowGlacier.ts @@ -1,12 +1,11 @@ export default { - "name": "arrowGlacier", - "comment": "HF to delay the difficulty bomb", - "url": "https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/arrow-glacier.md", - "status": "Final", - "eips": [4345], - "gasConfig": {}, - "gasPrices": {}, - "vm": {}, - "pow": {} -} - ; \ No newline at end of file + name: 'arrowGlacier', + comment: 'HF to delay the difficulty bomb', + url: 'https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/arrow-glacier.md', + status: 'Final', + eips: [4345], + gasConfig: {}, + gasPrices: {}, + vm: {}, + pow: {}, +}; diff --git a/packages/web3-eth-accounts/src/common/hardforks/berlin.ts b/packages/web3-eth-accounts/src/common/hardforks/berlin.ts index df30229fb2e..d76c7629520 100644 --- a/packages/web3-eth-accounts/src/common/hardforks/berlin.ts +++ b/packages/web3-eth-accounts/src/common/hardforks/berlin.ts @@ -1,8 +1,7 @@ export default { - "name": "berlin", - "comment": "HF targeted for July 2020 following the Muir Glacier HF", - "url": "https://eips.ethereum.org/EIPS/eip-2070", - "status": "Final", - "eips": [2565, 2929, 2718, 2930] -} - ; \ No newline at end of file + name: 'berlin', + comment: 'HF targeted for July 2020 following the Muir Glacier HF', + url: 'https://eips.ethereum.org/EIPS/eip-2070', + status: 'Final', + eips: [2565, 2929, 2718, 2930], +}; diff --git a/packages/web3-eth-accounts/src/common/hardforks/byzantium.ts b/packages/web3-eth-accounts/src/common/hardforks/byzantium.ts index 2c358c8f6ff..eb9a00a07c4 100644 --- a/packages/web3-eth-accounts/src/common/hardforks/byzantium.ts +++ b/packages/web3-eth-accounts/src/common/hardforks/byzantium.ts @@ -1,57 +1,56 @@ export default { - "name": "byzantium", - "comment": "Hardfork with new precompiles, instructions and other protocol changes", - "url": "https://eips.ethereum.org/EIPS/eip-609", - "status": "Final", - "gasConfig": {}, - "gasPrices": { - "modexpGquaddivisor": { - "v": 20, - "d": "Gquaddivisor from modexp precompile for gas calculation" - }, - "ecAdd": { - "v": 500, - "d": "Gas costs for curve addition precompile" - }, - "ecMul": { - "v": 40000, - "d": "Gas costs for curve multiplication precompile" - }, - "ecPairing": { - "v": 100000, - "d": "Base gas costs for curve pairing precompile" - }, - "ecPairingWord": { - "v": 80000, - "d": "Gas costs regarding curve pairing precompile input length" - }, - "revert": { - "v": 0, - "d": "Base fee of the REVERT opcode" - }, - "staticcall": { - "v": 700, - "d": "Base fee of the STATICCALL opcode" - }, - "returndatasize": { - "v": 2, - "d": "Base fee of the RETURNDATASIZE opcode" - }, - "returndatacopy": { - "v": 3, - "d": "Base fee of the RETURNDATACOPY opcode" - } + name: 'byzantium', + comment: 'Hardfork with new precompiles, instructions and other protocol changes', + url: 'https://eips.ethereum.org/EIPS/eip-609', + status: 'Final', + gasConfig: {}, + gasPrices: { + modexpGquaddivisor: { + v: 20, + d: 'Gquaddivisor from modexp precompile for gas calculation', + }, + ecAdd: { + v: 500, + d: 'Gas costs for curve addition precompile', + }, + ecMul: { + v: 40000, + d: 'Gas costs for curve multiplication precompile', + }, + ecPairing: { + v: 100000, + d: 'Base gas costs for curve pairing precompile', + }, + ecPairingWord: { + v: 80000, + d: 'Gas costs regarding curve pairing precompile input length', + }, + revert: { + v: 0, + d: 'Base fee of the REVERT opcode', + }, + staticcall: { + v: 700, + d: 'Base fee of the STATICCALL opcode', + }, + returndatasize: { + v: 2, + d: 'Base fee of the RETURNDATASIZE opcode', + }, + returndatacopy: { + v: 3, + d: 'Base fee of the RETURNDATACOPY opcode', + }, + }, + vm: {}, + pow: { + minerReward: { + v: '3000000000000000000', + d: 'the amount a miner get rewarded for mining a block', + }, + difficultyBombDelay: { + v: 3000000, + d: 'the amount of blocks to delay the difficulty bomb with', + }, }, - "vm": {}, - "pow": { - "minerReward": { - "v": "3000000000000000000", - "d": "the amount a miner get rewarded for mining a block" - }, - "difficultyBombDelay": { - "v": 3000000, - "d": "the amount of blocks to delay the difficulty bomb with" - } - } -} - ; \ No newline at end of file +}; diff --git a/packages/web3-eth-accounts/src/common/hardforks/chainstart.ts b/packages/web3-eth-accounts/src/common/hardforks/chainstart.ts index 32f5630b5ff..030366fcc78 100644 --- a/packages/web3-eth-accounts/src/common/hardforks/chainstart.ts +++ b/packages/web3-eth-accounts/src/common/hardforks/chainstart.ts @@ -1,439 +1,438 @@ export default { - "name": "chainstart", - "comment": "Start of the Ethereum main chain", - "url": "", - "status": "", - "gasConfig": { - "minGasLimit": { - "v": 5000, - "d": "Minimum the gas limit may ever be" - }, - "gasLimitBoundDivisor": { - "v": 1024, - "d": "The bound divisor of the gas limit, used in update calculations" - }, - "maxRefundQuotient": { - "v": 2, - "d": "Maximum refund quotient; max tx refund is min(tx.gasUsed/maxRefundQuotient, tx.gasRefund)" - } + name: 'chainstart', + comment: 'Start of the Ethereum main chain', + url: '', + status: '', + gasConfig: { + minGasLimit: { + v: 5000, + d: 'Minimum the gas limit may ever be', + }, + gasLimitBoundDivisor: { + v: 1024, + d: 'The bound divisor of the gas limit, used in update calculations', + }, + maxRefundQuotient: { + v: 2, + d: 'Maximum refund quotient; max tx refund is min(tx.gasUsed/maxRefundQuotient, tx.gasRefund)', + }, }, - "gasPrices": { - "base": { - "v": 2, - "d": "Gas base cost, used e.g. for ChainID opcode (Istanbul)" + gasPrices: { + base: { + v: 2, + d: 'Gas base cost, used e.g. for ChainID opcode (Istanbul)', + }, + tierStep: { + v: [0, 2, 3, 5, 8, 10, 20], + d: 'Once per operation, for a selection of them', }, - "tierStep": { - "v": [0, 2, 3, 5, 8, 10, 20], - "d": "Once per operation, for a selection of them" + exp: { + v: 10, + d: 'Base fee of the EXP opcode', }, - "exp": { - "v": 10, - "d": "Base fee of the EXP opcode" + expByte: { + v: 10, + d: 'Times ceil(log256(exponent)) for the EXP instruction', }, - "expByte": { - "v": 10, - "d": "Times ceil(log256(exponent)) for the EXP instruction" + sha3: { + v: 30, + d: 'Base fee of the SHA3 opcode', }, - "sha3": { - "v": 30, - "d": "Base fee of the SHA3 opcode" + sha3Word: { + v: 6, + d: "Once per word of the SHA3 operation's data", }, - "sha3Word": { - "v": 6, - "d": "Once per word of the SHA3 operation's data" + sload: { + v: 50, + d: 'Base fee of the SLOAD opcode', }, - "sload": { - "v": 50, - "d": "Base fee of the SLOAD opcode" + sstoreSet: { + v: 20000, + d: 'Once per SSTORE operation if the zeroness changes from zero', }, - "sstoreSet": { - "v": 20000, - "d": "Once per SSTORE operation if the zeroness changes from zero" + sstoreReset: { + v: 5000, + d: 'Once per SSTORE operation if the zeroness does not change from zero', }, - "sstoreReset": { - "v": 5000, - "d": "Once per SSTORE operation if the zeroness does not change from zero" + sstoreRefund: { + v: 15000, + d: 'Once per SSTORE operation if the zeroness changes to zero', }, - "sstoreRefund": { - "v": 15000, - "d": "Once per SSTORE operation if the zeroness changes to zero" + jumpdest: { + v: 1, + d: 'Base fee of the JUMPDEST opcode', }, - "jumpdest": { - "v": 1, - "d": "Base fee of the JUMPDEST opcode" + log: { + v: 375, + d: 'Base fee of the LOG opcode', }, - "log": { - "v": 375, - "d": "Base fee of the LOG opcode" + logData: { + v: 8, + d: "Per byte in a LOG* operation's data", }, - "logData": { - "v": 8, - "d": "Per byte in a LOG* operation's data" + logTopic: { + v: 375, + d: 'Multiplied by the * of the LOG*, per LOG transaction. e.g. LOG0 incurs 0 * c_txLogTopicGas, LOG4 incurs 4 * c_txLogTopicGas', }, - "logTopic": { - "v": 375, - "d": "Multiplied by the * of the LOG*, per LOG transaction. e.g. LOG0 incurs 0 * c_txLogTopicGas, LOG4 incurs 4 * c_txLogTopicGas" + create: { + v: 32000, + d: 'Base fee of the CREATE opcode', }, - "create": { - "v": 32000, - "d": "Base fee of the CREATE opcode" + call: { + v: 40, + d: 'Base fee of the CALL opcode', }, - "call": { - "v": 40, - "d": "Base fee of the CALL opcode" + callStipend: { + v: 2300, + d: 'Free gas given at beginning of call', }, - "callStipend": { - "v": 2300, - "d": "Free gas given at beginning of call" + callValueTransfer: { + v: 9000, + d: 'Paid for CALL when the value transfor is non-zero', }, - "callValueTransfer": { - "v": 9000, - "d": "Paid for CALL when the value transfor is non-zero" + callNewAccount: { + v: 25000, + d: "Paid for CALL when the destination address didn't exist prior", }, - "callNewAccount": { - "v": 25000, - "d": "Paid for CALL when the destination address didn't exist prior" + selfdestructRefund: { + v: 24000, + d: 'Refunded following a selfdestruct operation', }, - "selfdestructRefund": { - "v": 24000, - "d": "Refunded following a selfdestruct operation" + memory: { + v: 3, + d: 'Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL', }, - "memory": { - "v": 3, - "d": "Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL" + quadCoeffDiv: { + v: 512, + d: 'Divisor for the quadratic particle of the memory cost equation', }, - "quadCoeffDiv": { - "v": 512, - "d": "Divisor for the quadratic particle of the memory cost equation" + createData: { + v: 200, + d: '', }, - "createData": { - "v": 200, - "d": "" + tx: { + v: 21000, + d: 'Per transaction. NOTE: Not payable on data of calls between transactions', }, - "tx": { - "v": 21000, - "d": "Per transaction. NOTE: Not payable on data of calls between transactions" + txCreation: { + v: 32000, + d: 'The cost of creating a contract via tx', }, - "txCreation": { - "v": 32000, - "d": "The cost of creating a contract via tx" + txDataZero: { + v: 4, + d: 'Per byte of data attached to a transaction that equals zero. NOTE: Not payable on data of calls between transactions', }, - "txDataZero": { - "v": 4, - "d": "Per byte of data attached to a transaction that equals zero. NOTE: Not payable on data of calls between transactions" + txDataNonZero: { + v: 68, + d: 'Per byte of data attached to a transaction that is not equal to zero. NOTE: Not payable on data of calls between transactions', }, - "txDataNonZero": { - "v": 68, - "d": "Per byte of data attached to a transaction that is not equal to zero. NOTE: Not payable on data of calls between transactions" + copy: { + v: 3, + d: 'Multiplied by the number of 32-byte words that are copied (round up) for any *COPY operation and added', }, - "copy": { - "v": 3, - "d": "Multiplied by the number of 32-byte words that are copied (round up) for any *COPY operation and added" + ecRecover: { + v: 3000, + d: '', }, - "ecRecover": { - "v": 3000, - "d": "" + sha256: { + v: 60, + d: '', }, - "sha256": { - "v": 60, - "d": "" + sha256Word: { + v: 12, + d: '', }, - "sha256Word": { - "v": 12, - "d": "" + ripemd160: { + v: 600, + d: '', }, - "ripemd160": { - "v": 600, - "d": "" + ripemd160Word: { + v: 120, + d: '', }, - "ripemd160Word": { - "v": 120, - "d": "" + identity: { + v: 15, + d: '', }, - "identity": { - "v": 15, - "d": "" + identityWord: { + v: 3, + d: '', }, - "identityWord": { - "v": 3, - "d": "" + stop: { + v: 0, + d: 'Base fee of the STOP opcode', }, - "stop": { - "v": 0, - "d": "Base fee of the STOP opcode" + add: { + v: 3, + d: 'Base fee of the ADD opcode', }, - "add": { - "v": 3, - "d": "Base fee of the ADD opcode" + mul: { + v: 5, + d: 'Base fee of the MUL opcode', }, - "mul": { - "v": 5, - "d": "Base fee of the MUL opcode" + sub: { + v: 3, + d: 'Base fee of the SUB opcode', }, - "sub": { - "v": 3, - "d": "Base fee of the SUB opcode" + div: { + v: 5, + d: 'Base fee of the DIV opcode', }, - "div": { - "v": 5, - "d": "Base fee of the DIV opcode" + sdiv: { + v: 5, + d: 'Base fee of the SDIV opcode', }, - "sdiv": { - "v": 5, - "d": "Base fee of the SDIV opcode" + mod: { + v: 5, + d: 'Base fee of the MOD opcode', }, - "mod": { - "v": 5, - "d": "Base fee of the MOD opcode" + smod: { + v: 5, + d: 'Base fee of the SMOD opcode', }, - "smod": { - "v": 5, - "d": "Base fee of the SMOD opcode" + addmod: { + v: 8, + d: 'Base fee of the ADDMOD opcode', }, - "addmod": { - "v": 8, - "d": "Base fee of the ADDMOD opcode" + mulmod: { + v: 8, + d: 'Base fee of the MULMOD opcode', }, - "mulmod": { - "v": 8, - "d": "Base fee of the MULMOD opcode" + signextend: { + v: 5, + d: 'Base fee of the SIGNEXTEND opcode', }, - "signextend": { - "v": 5, - "d": "Base fee of the SIGNEXTEND opcode" + lt: { + v: 3, + d: 'Base fee of the LT opcode', }, - "lt": { - "v": 3, - "d": "Base fee of the LT opcode" + gt: { + v: 3, + d: 'Base fee of the GT opcode', }, - "gt": { - "v": 3, - "d": "Base fee of the GT opcode" + slt: { + v: 3, + d: 'Base fee of the SLT opcode', }, - "slt": { - "v": 3, - "d": "Base fee of the SLT opcode" + sgt: { + v: 3, + d: 'Base fee of the SGT opcode', }, - "sgt": { - "v": 3, - "d": "Base fee of the SGT opcode" + eq: { + v: 3, + d: 'Base fee of the EQ opcode', }, - "eq": { - "v": 3, - "d": "Base fee of the EQ opcode" + iszero: { + v: 3, + d: 'Base fee of the ISZERO opcode', }, - "iszero": { - "v": 3, - "d": "Base fee of the ISZERO opcode" + and: { + v: 3, + d: 'Base fee of the AND opcode', }, - "and": { - "v": 3, - "d": "Base fee of the AND opcode" + or: { + v: 3, + d: 'Base fee of the OR opcode', }, - "or": { - "v": 3, - "d": "Base fee of the OR opcode" + xor: { + v: 3, + d: 'Base fee of the XOR opcode', }, - "xor": { - "v": 3, - "d": "Base fee of the XOR opcode" + not: { + v: 3, + d: 'Base fee of the NOT opcode', }, - "not": { - "v": 3, - "d": "Base fee of the NOT opcode" + byte: { + v: 3, + d: 'Base fee of the BYTE opcode', }, - "byte": { - "v": 3, - "d": "Base fee of the BYTE opcode" + address: { + v: 2, + d: 'Base fee of the ADDRESS opcode', }, - "address": { - "v": 2, - "d": "Base fee of the ADDRESS opcode" + balance: { + v: 20, + d: 'Base fee of the BALANCE opcode', }, - "balance": { - "v": 20, - "d": "Base fee of the BALANCE opcode" + origin: { + v: 2, + d: 'Base fee of the ORIGIN opcode', }, - "origin": { - "v": 2, - "d": "Base fee of the ORIGIN opcode" + caller: { + v: 2, + d: 'Base fee of the CALLER opcode', }, - "caller": { - "v": 2, - "d": "Base fee of the CALLER opcode" + callvalue: { + v: 2, + d: 'Base fee of the CALLVALUE opcode', }, - "callvalue": { - "v": 2, - "d": "Base fee of the CALLVALUE opcode" + calldataload: { + v: 3, + d: 'Base fee of the CALLDATALOAD opcode', }, - "calldataload": { - "v": 3, - "d": "Base fee of the CALLDATALOAD opcode" + calldatasize: { + v: 2, + d: 'Base fee of the CALLDATASIZE opcode', }, - "calldatasize": { - "v": 2, - "d": "Base fee of the CALLDATASIZE opcode" + calldatacopy: { + v: 3, + d: 'Base fee of the CALLDATACOPY opcode', }, - "calldatacopy": { - "v": 3, - "d": "Base fee of the CALLDATACOPY opcode" + codesize: { + v: 2, + d: 'Base fee of the CODESIZE opcode', }, - "codesize": { - "v": 2, - "d": "Base fee of the CODESIZE opcode" + codecopy: { + v: 3, + d: 'Base fee of the CODECOPY opcode', }, - "codecopy": { - "v": 3, - "d": "Base fee of the CODECOPY opcode" + gasprice: { + v: 2, + d: 'Base fee of the GASPRICE opcode', }, - "gasprice": { - "v": 2, - "d": "Base fee of the GASPRICE opcode" + extcodesize: { + v: 20, + d: 'Base fee of the EXTCODESIZE opcode', }, - "extcodesize": { - "v": 20, - "d": "Base fee of the EXTCODESIZE opcode" + extcodecopy: { + v: 20, + d: 'Base fee of the EXTCODECOPY opcode', }, - "extcodecopy": { - "v": 20, - "d": "Base fee of the EXTCODECOPY opcode" + blockhash: { + v: 20, + d: 'Base fee of the BLOCKHASH opcode', }, - "blockhash": { - "v": 20, - "d": "Base fee of the BLOCKHASH opcode" + coinbase: { + v: 2, + d: 'Base fee of the COINBASE opcode', }, - "coinbase": { - "v": 2, - "d": "Base fee of the COINBASE opcode" + timestamp: { + v: 2, + d: 'Base fee of the TIMESTAMP opcode', }, - "timestamp": { - "v": 2, - "d": "Base fee of the TIMESTAMP opcode" + number: { + v: 2, + d: 'Base fee of the NUMBER opcode', }, - "number": { - "v": 2, - "d": "Base fee of the NUMBER opcode" + difficulty: { + v: 2, + d: 'Base fee of the DIFFICULTY opcode', }, - "difficulty": { - "v": 2, - "d": "Base fee of the DIFFICULTY opcode" + gaslimit: { + v: 2, + d: 'Base fee of the GASLIMIT opcode', }, - "gaslimit": { - "v": 2, - "d": "Base fee of the GASLIMIT opcode" + pop: { + v: 2, + d: 'Base fee of the POP opcode', }, - "pop": { - "v": 2, - "d": "Base fee of the POP opcode" + mload: { + v: 3, + d: 'Base fee of the MLOAD opcode', }, - "mload": { - "v": 3, - "d": "Base fee of the MLOAD opcode" + mstore: { + v: 3, + d: 'Base fee of the MSTORE opcode', }, - "mstore": { - "v": 3, - "d": "Base fee of the MSTORE opcode" + mstore8: { + v: 3, + d: 'Base fee of the MSTORE8 opcode', }, - "mstore8": { - "v": 3, - "d": "Base fee of the MSTORE8 opcode" + sstore: { + v: 0, + d: 'Base fee of the SSTORE opcode', }, - "sstore": { - "v": 0, - "d": "Base fee of the SSTORE opcode" + jump: { + v: 8, + d: 'Base fee of the JUMP opcode', }, - "jump": { - "v": 8, - "d": "Base fee of the JUMP opcode" + jumpi: { + v: 10, + d: 'Base fee of the JUMPI opcode', }, - "jumpi": { - "v": 10, - "d": "Base fee of the JUMPI opcode" + pc: { + v: 2, + d: 'Base fee of the PC opcode', }, - "pc": { - "v": 2, - "d": "Base fee of the PC opcode" + msize: { + v: 2, + d: 'Base fee of the MSIZE opcode', }, - "msize": { - "v": 2, - "d": "Base fee of the MSIZE opcode" + gas: { + v: 2, + d: 'Base fee of the GAS opcode', }, - "gas": { - "v": 2, - "d": "Base fee of the GAS opcode" + push: { + v: 3, + d: 'Base fee of the PUSH opcode', }, - "push": { - "v": 3, - "d": "Base fee of the PUSH opcode" + dup: { + v: 3, + d: 'Base fee of the DUP opcode', }, - "dup": { - "v": 3, - "d": "Base fee of the DUP opcode" + swap: { + v: 3, + d: 'Base fee of the SWAP opcode', }, - "swap": { - "v": 3, - "d": "Base fee of the SWAP opcode" + callcode: { + v: 40, + d: 'Base fee of the CALLCODE opcode', }, - "callcode": { - "v": 40, - "d": "Base fee of the CALLCODE opcode" + return: { + v: 0, + d: 'Base fee of the RETURN opcode', }, - "return": { - "v": 0, - "d": "Base fee of the RETURN opcode" + invalid: { + v: 0, + d: 'Base fee of the INVALID opcode', }, - "invalid": { - "v": 0, - "d": "Base fee of the INVALID opcode" + selfdestruct: { + v: 0, + d: 'Base fee of the SELFDESTRUCT opcode', }, - "selfdestruct": { - "v": 0, - "d": "Base fee of the SELFDESTRUCT opcode" - } }, - "vm": { - "stackLimit": { - "v": 1024, - "d": "Maximum size of VM stack allowed" - }, - "callCreateDepth": { - "v": 1024, - "d": "Maximum depth of call/create stack" - }, - "maxExtraDataSize": { - "v": 32, - "d": "Maximum size extra data may be after Genesis" - } + vm: { + stackLimit: { + v: 1024, + d: 'Maximum size of VM stack allowed', + }, + callCreateDepth: { + v: 1024, + d: 'Maximum depth of call/create stack', + }, + maxExtraDataSize: { + v: 32, + d: 'Maximum size extra data may be after Genesis', + }, + }, + pow: { + minimumDifficulty: { + v: 131072, + d: 'The minimum that the difficulty may ever be', + }, + difficultyBoundDivisor: { + v: 2048, + d: 'The bound divisor of the difficulty, used in the update calculations', + }, + durationLimit: { + v: 13, + d: 'The decision boundary on the blocktime duration used to determine whether difficulty should go up or not', + }, + epochDuration: { + v: 30000, + d: 'Duration between proof-of-work epochs', + }, + timebombPeriod: { + v: 100000, + d: 'Exponential difficulty timebomb period', + }, + minerReward: { + v: '5000000000000000000', + d: 'the amount a miner get rewarded for mining a block', + }, + difficultyBombDelay: { + v: 0, + d: 'the amount of blocks to delay the difficulty bomb with', + }, }, - "pow": { - "minimumDifficulty": { - "v": 131072, - "d": "The minimum that the difficulty may ever be" - }, - "difficultyBoundDivisor": { - "v": 2048, - "d": "The bound divisor of the difficulty, used in the update calculations" - }, - "durationLimit": { - "v": 13, - "d": "The decision boundary on the blocktime duration used to determine whether difficulty should go up or not" - }, - "epochDuration": { - "v": 30000, - "d": "Duration between proof-of-work epochs" - }, - "timebombPeriod": { - "v": 100000, - "d": "Exponential difficulty timebomb period" - }, - "minerReward": { - "v": "5000000000000000000", - "d": "the amount a miner get rewarded for mining a block" - }, - "difficultyBombDelay": { - "v": 0, - "d": "the amount of blocks to delay the difficulty bomb with" - } - } -} - ; \ No newline at end of file +}; diff --git a/packages/web3-eth-accounts/src/common/hardforks/constantinople.ts b/packages/web3-eth-accounts/src/common/hardforks/constantinople.ts index dd576fe1575..5401a1d7b58 100644 --- a/packages/web3-eth-accounts/src/common/hardforks/constantinople.ts +++ b/packages/web3-eth-accounts/src/common/hardforks/constantinople.ts @@ -1,69 +1,68 @@ export default { - "name": "constantinople", - "comment": "Postponed hardfork including EIP-1283 (SSTORE gas metering changes)", - "url": "https://eips.ethereum.org/EIPS/eip-1013", - "status": "Final", - "gasConfig": {}, - "gasPrices": { - "netSstoreNoopGas": { - "v": 200, - "d": "Once per SSTORE operation if the value doesn't change" + name: 'constantinople', + comment: 'Postponed hardfork including EIP-1283 (SSTORE gas metering changes)', + url: 'https://eips.ethereum.org/EIPS/eip-1013', + status: 'Final', + gasConfig: {}, + gasPrices: { + netSstoreNoopGas: { + v: 200, + d: "Once per SSTORE operation if the value doesn't change", }, - "netSstoreInitGas": { - "v": 20000, - "d": "Once per SSTORE operation from clean zero" + netSstoreInitGas: { + v: 20000, + d: 'Once per SSTORE operation from clean zero', }, - "netSstoreCleanGas": { - "v": 5000, - "d": "Once per SSTORE operation from clean non-zero" + netSstoreCleanGas: { + v: 5000, + d: 'Once per SSTORE operation from clean non-zero', }, - "netSstoreDirtyGas": { - "v": 200, - "d": "Once per SSTORE operation from dirty" + netSstoreDirtyGas: { + v: 200, + d: 'Once per SSTORE operation from dirty', }, - "netSstoreClearRefund": { - "v": 15000, - "d": "Once per SSTORE operation for clearing an originally existing storage slot" + netSstoreClearRefund: { + v: 15000, + d: 'Once per SSTORE operation for clearing an originally existing storage slot', }, - "netSstoreResetRefund": { - "v": 4800, - "d": "Once per SSTORE operation for resetting to the original non-zero value" + netSstoreResetRefund: { + v: 4800, + d: 'Once per SSTORE operation for resetting to the original non-zero value', }, - "netSstoreResetClearRefund": { - "v": 19800, - "d": "Once per SSTORE operation for resetting to the original zero value" + netSstoreResetClearRefund: { + v: 19800, + d: 'Once per SSTORE operation for resetting to the original zero value', }, - "shl": { - "v": 3, - "d": "Base fee of the SHL opcode" + shl: { + v: 3, + d: 'Base fee of the SHL opcode', }, - "shr": { - "v": 3, - "d": "Base fee of the SHR opcode" + shr: { + v: 3, + d: 'Base fee of the SHR opcode', }, - "sar": { - "v": 3, - "d": "Base fee of the SAR opcode" + sar: { + v: 3, + d: 'Base fee of the SAR opcode', }, - "extcodehash": { - "v": 400, - "d": "Base fee of the EXTCODEHASH opcode" + extcodehash: { + v: 400, + d: 'Base fee of the EXTCODEHASH opcode', + }, + create2: { + v: 32000, + d: 'Base fee of the CREATE2 opcode', }, - "create2": { - "v": 32000, - "d": "Base fee of the CREATE2 opcode" - } }, - "vm": {}, - "pow": { - "minerReward": { - "v": "2000000000000000000", - "d": "The amount a miner gets rewarded for mining a block" + vm: {}, + pow: { + minerReward: { + v: '2000000000000000000', + d: 'The amount a miner gets rewarded for mining a block', + }, + difficultyBombDelay: { + v: 5000000, + d: 'the amount of blocks to delay the difficulty bomb with', }, - "difficultyBombDelay": { - "v": 5000000, - "d": "the amount of blocks to delay the difficulty bomb with" - } - } -} - ; \ No newline at end of file + }, +}; diff --git a/packages/web3-eth-accounts/src/common/hardforks/dao.ts b/packages/web3-eth-accounts/src/common/hardforks/dao.ts index a565ec89a42..601858bce47 100644 --- a/packages/web3-eth-accounts/src/common/hardforks/dao.ts +++ b/packages/web3-eth-accounts/src/common/hardforks/dao.ts @@ -1,11 +1,10 @@ export default { - "name": "dao", - "comment": "DAO rescue hardfork", - "url": "https://eips.ethereum.org/EIPS/eip-779", - "status": "Final", - "gasConfig": {}, - "gasPrices": {}, - "vm": {}, - "pow": {} -} - ; \ No newline at end of file + name: 'dao', + comment: 'DAO rescue hardfork', + url: 'https://eips.ethereum.org/EIPS/eip-779', + status: 'Final', + gasConfig: {}, + gasPrices: {}, + vm: {}, + pow: {}, +}; diff --git a/packages/web3-eth-accounts/src/common/hardforks/grayGlacier.ts b/packages/web3-eth-accounts/src/common/hardforks/grayGlacier.ts index 3c67d73e7af..51490fed3e1 100644 --- a/packages/web3-eth-accounts/src/common/hardforks/grayGlacier.ts +++ b/packages/web3-eth-accounts/src/common/hardforks/grayGlacier.ts @@ -1,12 +1,11 @@ export default { - "name": "grayGlacier", - "comment": "Delaying the difficulty bomb to Mid September 2022", - "url": "https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/gray-glacier.md", - "status": "Draft", - "eips": [5133], - "gasConfig": {}, - "gasPrices": {}, - "vm": {}, - "pow": {} -} - ; \ No newline at end of file + name: 'grayGlacier', + comment: 'Delaying the difficulty bomb to Mid September 2022', + url: 'https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/gray-glacier.md', + status: 'Draft', + eips: [5133], + gasConfig: {}, + gasPrices: {}, + vm: {}, + pow: {}, +}; diff --git a/packages/web3-eth-accounts/src/common/hardforks/homestead.ts b/packages/web3-eth-accounts/src/common/hardforks/homestead.ts index e6521fc46ab..6cdbdec928f 100644 --- a/packages/web3-eth-accounts/src/common/hardforks/homestead.ts +++ b/packages/web3-eth-accounts/src/common/hardforks/homestead.ts @@ -1,16 +1,15 @@ export default { - "name": "homestead", - "comment": "Homestead hardfork with protocol and network changes", - "url": "https://eips.ethereum.org/EIPS/eip-606", - "status": "Final", - "gasConfig": {}, - "gasPrices": { - "delegatecall": { - "v": 40, - "d": "Base fee of the DELEGATECALL opcode" - } + name: 'homestead', + comment: 'Homestead hardfork with protocol and network changes', + url: 'https://eips.ethereum.org/EIPS/eip-606', + status: 'Final', + gasConfig: {}, + gasPrices: { + delegatecall: { + v: 40, + d: 'Base fee of the DELEGATECALL opcode', + }, }, - "vm": {}, - "pow": {} -} - ; \ No newline at end of file + vm: {}, + pow: {}, +}; diff --git a/packages/web3-eth-accounts/src/common/hardforks/istanbul.ts b/packages/web3-eth-accounts/src/common/hardforks/istanbul.ts index 96f3a66c598..33fb5b7fd92 100644 --- a/packages/web3-eth-accounts/src/common/hardforks/istanbul.ts +++ b/packages/web3-eth-accounts/src/common/hardforks/istanbul.ts @@ -1,88 +1,87 @@ export default { - "name": "istanbul", - "comment": "HF targeted for December 2019 following the Constantinople/Petersburg HF", - "url": "https://eips.ethereum.org/EIPS/eip-1679", - "status": "Final", - "gasConfig": {}, - "gasPrices": { - "blake2Round": { - "v": 1, - "d": "Gas cost per round for the Blake2 F precompile" - }, - "ecAdd": { - "v": 150, - "d": "Gas costs for curve addition precompile" - }, - "ecMul": { - "v": 6000, - "d": "Gas costs for curve multiplication precompile" - }, - "ecPairing": { - "v": 45000, - "d": "Base gas costs for curve pairing precompile" - }, - "ecPairingWord": { - "v": 34000, - "d": "Gas costs regarding curve pairing precompile input length" - }, - "txDataNonZero": { - "v": 16, - "d": "Per byte of data attached to a transaction that is not equal to zero. NOTE: Not payable on data of calls between transactions" - }, - "sstoreSentryGasEIP2200": { - "v": 2300, - "d": "Minimum gas required to be present for an SSTORE call, not consumed" - }, - "sstoreNoopGasEIP2200": { - "v": 800, - "d": "Once per SSTORE operation if the value doesn't change" - }, - "sstoreDirtyGasEIP2200": { - "v": 800, - "d": "Once per SSTORE operation if a dirty value is changed" - }, - "sstoreInitGasEIP2200": { - "v": 20000, - "d": "Once per SSTORE operation from clean zero to non-zero" - }, - "sstoreInitRefundEIP2200": { - "v": 19200, - "d": "Once per SSTORE operation for resetting to the original zero value" - }, - "sstoreCleanGasEIP2200": { - "v": 5000, - "d": "Once per SSTORE operation from clean non-zero to something else" - }, - "sstoreCleanRefundEIP2200": { - "v": 4200, - "d": "Once per SSTORE operation for resetting to the original non-zero value" - }, - "sstoreClearRefundEIP2200": { - "v": 15000, - "d": "Once per SSTORE operation for clearing an originally existing storage slot" - }, - "balance": { - "v": 700, - "d": "Base fee of the BALANCE opcode" - }, - "extcodehash": { - "v": 700, - "d": "Base fee of the EXTCODEHASH opcode" - }, - "chainid": { - "v": 2, - "d": "Base fee of the CHAINID opcode" - }, - "selfbalance": { - "v": 5, - "d": "Base fee of the SELFBALANCE opcode" - }, - "sload": { - "v": 800, - "d": "Base fee of the SLOAD opcode" - } + name: 'istanbul', + comment: 'HF targeted for December 2019 following the Constantinople/Petersburg HF', + url: 'https://eips.ethereum.org/EIPS/eip-1679', + status: 'Final', + gasConfig: {}, + gasPrices: { + blake2Round: { + v: 1, + d: 'Gas cost per round for the Blake2 F precompile', + }, + ecAdd: { + v: 150, + d: 'Gas costs for curve addition precompile', + }, + ecMul: { + v: 6000, + d: 'Gas costs for curve multiplication precompile', + }, + ecPairing: { + v: 45000, + d: 'Base gas costs for curve pairing precompile', + }, + ecPairingWord: { + v: 34000, + d: 'Gas costs regarding curve pairing precompile input length', + }, + txDataNonZero: { + v: 16, + d: 'Per byte of data attached to a transaction that is not equal to zero. NOTE: Not payable on data of calls between transactions', + }, + sstoreSentryGasEIP2200: { + v: 2300, + d: 'Minimum gas required to be present for an SSTORE call, not consumed', + }, + sstoreNoopGasEIP2200: { + v: 800, + d: "Once per SSTORE operation if the value doesn't change", + }, + sstoreDirtyGasEIP2200: { + v: 800, + d: 'Once per SSTORE operation if a dirty value is changed', + }, + sstoreInitGasEIP2200: { + v: 20000, + d: 'Once per SSTORE operation from clean zero to non-zero', + }, + sstoreInitRefundEIP2200: { + v: 19200, + d: 'Once per SSTORE operation for resetting to the original zero value', + }, + sstoreCleanGasEIP2200: { + v: 5000, + d: 'Once per SSTORE operation from clean non-zero to something else', + }, + sstoreCleanRefundEIP2200: { + v: 4200, + d: 'Once per SSTORE operation for resetting to the original non-zero value', + }, + sstoreClearRefundEIP2200: { + v: 15000, + d: 'Once per SSTORE operation for clearing an originally existing storage slot', + }, + balance: { + v: 700, + d: 'Base fee of the BALANCE opcode', + }, + extcodehash: { + v: 700, + d: 'Base fee of the EXTCODEHASH opcode', + }, + chainid: { + v: 2, + d: 'Base fee of the CHAINID opcode', + }, + selfbalance: { + v: 5, + d: 'Base fee of the SELFBALANCE opcode', + }, + sload: { + v: 800, + d: 'Base fee of the SLOAD opcode', + }, }, - "vm": {}, - "pow": {} -} - ; \ No newline at end of file + vm: {}, + pow: {}, +}; diff --git a/packages/web3-eth-accounts/src/common/hardforks/london.ts b/packages/web3-eth-accounts/src/common/hardforks/london.ts index 6d0ec4a4468..6b55207e434 100644 --- a/packages/web3-eth-accounts/src/common/hardforks/london.ts +++ b/packages/web3-eth-accounts/src/common/hardforks/london.ts @@ -1,8 +1,7 @@ export default { - "name": "london", - "comment": "HF targeted for July 2021 following the Berlin fork", - "url": "https://github.com/ethereum/eth1.0-specs/blob/master/network-upgrades/mainnet-upgrades/london.md", - "status": "Final", - "eips": [1559, 3198, 3529, 3541] -} - ; \ No newline at end of file + name: 'london', + comment: 'HF targeted for July 2021 following the Berlin fork', + url: 'https://github.com/ethereum/eth1.0-specs/blob/master/network-upgrades/mainnet-upgrades/london.md', + status: 'Final', + eips: [1559, 3198, 3529, 3541], +}; diff --git a/packages/web3-eth-accounts/src/common/hardforks/merge.ts b/packages/web3-eth-accounts/src/common/hardforks/merge.ts index db48aa32509..f574f678656 100644 --- a/packages/web3-eth-accounts/src/common/hardforks/merge.ts +++ b/packages/web3-eth-accounts/src/common/hardforks/merge.ts @@ -1,13 +1,12 @@ export default { - "name": "merge", - "comment": "Hardfork to upgrade the consensus mechanism to Proof-of-Stake", - "url": "https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/merge.md", - "status": "Final", - "consensus": { - "type": "pos", - "algorithm": "casper", - "casper": {} + name: 'merge', + comment: 'Hardfork to upgrade the consensus mechanism to Proof-of-Stake', + url: 'https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/merge.md', + status: 'Final', + consensus: { + type: 'pos', + algorithm: 'casper', + casper: {}, }, - "eips": [3675, 4399] -} - ; \ No newline at end of file + eips: [3675, 4399], +}; diff --git a/packages/web3-eth-accounts/src/common/hardforks/mergeForkIdTransition.ts b/packages/web3-eth-accounts/src/common/hardforks/mergeForkIdTransition.ts index f4df67bd2d2..08d6a2b9dcf 100644 --- a/packages/web3-eth-accounts/src/common/hardforks/mergeForkIdTransition.ts +++ b/packages/web3-eth-accounts/src/common/hardforks/mergeForkIdTransition.ts @@ -1,8 +1,7 @@ export default { - "name": "mergeForkIdTransition", - "comment": "Pre-merge hardfork to fork off non-upgraded clients", - "url": "https://eips.ethereum.org/EIPS/eip-3675", - "status": "Draft", - "eips": [] -} - ; \ No newline at end of file + name: 'mergeForkIdTransition', + comment: 'Pre-merge hardfork to fork off non-upgraded clients', + url: 'https://eips.ethereum.org/EIPS/eip-3675', + status: 'Draft', + eips: [], +}; diff --git a/packages/web3-eth-accounts/src/common/hardforks/muirGlacier.ts b/packages/web3-eth-accounts/src/common/hardforks/muirGlacier.ts index a7d02c6147e..8b3469e329a 100644 --- a/packages/web3-eth-accounts/src/common/hardforks/muirGlacier.ts +++ b/packages/web3-eth-accounts/src/common/hardforks/muirGlacier.ts @@ -1,16 +1,15 @@ export default { - "name": "muirGlacier", - "comment": "HF to delay the difficulty bomb", - "url": "https://eips.ethereum.org/EIPS/eip-2384", - "status": "Final", - "gasConfig": {}, - "gasPrices": {}, - "vm": {}, - "pow": { - "difficultyBombDelay": { - "v": 9000000, - "d": "the amount of blocks to delay the difficulty bomb with" - } - } -} - ; \ No newline at end of file + name: 'muirGlacier', + comment: 'HF to delay the difficulty bomb', + url: 'https://eips.ethereum.org/EIPS/eip-2384', + status: 'Final', + gasConfig: {}, + gasPrices: {}, + vm: {}, + pow: { + difficultyBombDelay: { + v: 9000000, + d: 'the amount of blocks to delay the difficulty bomb with', + }, + }, +}; diff --git a/packages/web3-eth-accounts/src/common/hardforks/petersburg.ts b/packages/web3-eth-accounts/src/common/hardforks/petersburg.ts index cca4005f893..fd392f6a9ed 100644 --- a/packages/web3-eth-accounts/src/common/hardforks/petersburg.ts +++ b/packages/web3-eth-accounts/src/common/hardforks/petersburg.ts @@ -1,40 +1,40 @@ export default { - "name": "petersburg", - "comment": "Aka constantinopleFix, removes EIP-1283, activate together with or after constantinople", - "url": "https://eips.ethereum.org/EIPS/eip-1716", - "status": "Final", - "gasConfig": {}, - "gasPrices": { - "netSstoreNoopGas": { - "v": null, - "d": "Removed along EIP-1283" + name: 'petersburg', + comment: + 'Aka constantinopleFix, removes EIP-1283, activate together with or after constantinople', + url: 'https://eips.ethereum.org/EIPS/eip-1716', + status: 'Final', + gasConfig: {}, + gasPrices: { + netSstoreNoopGas: { + v: null, + d: 'Removed along EIP-1283', }, - "netSstoreInitGas": { - "v": null, - "d": "Removed along EIP-1283" + netSstoreInitGas: { + v: null, + d: 'Removed along EIP-1283', }, - "netSstoreCleanGas": { - "v": null, - "d": "Removed along EIP-1283" + netSstoreCleanGas: { + v: null, + d: 'Removed along EIP-1283', }, - "netSstoreDirtyGas": { - "v": null, - "d": "Removed along EIP-1283" + netSstoreDirtyGas: { + v: null, + d: 'Removed along EIP-1283', }, - "netSstoreClearRefund": { - "v": null, - "d": "Removed along EIP-1283" + netSstoreClearRefund: { + v: null, + d: 'Removed along EIP-1283', }, - "netSstoreResetRefund": { - "v": null, - "d": "Removed along EIP-1283" + netSstoreResetRefund: { + v: null, + d: 'Removed along EIP-1283', + }, + netSstoreResetClearRefund: { + v: null, + d: 'Removed along EIP-1283', }, - "netSstoreResetClearRefund": { - "v": null, - "d": "Removed along EIP-1283" - } }, - "vm": {}, - "pow": {} -} - ; \ No newline at end of file + vm: {}, + pow: {}, +}; diff --git a/packages/web3-eth-accounts/src/common/hardforks/shanghai.ts b/packages/web3-eth-accounts/src/common/hardforks/shanghai.ts index 736e331a89e..3854e3aa65d 100644 --- a/packages/web3-eth-accounts/src/common/hardforks/shanghai.ts +++ b/packages/web3-eth-accounts/src/common/hardforks/shanghai.ts @@ -1,8 +1,8 @@ export default { - "name": "shanghai", - "comment": "Next feature hardfork after the merge hardfork having withdrawals, warm coinbase, push0, limit/meter initcode", - "url": "https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/shanghai.md", - "status": "Final", - "eips": [3651, 3855, 3860, 4895] -} - ; \ No newline at end of file + name: 'shanghai', + comment: + 'Next feature hardfork after the merge hardfork having withdrawals, warm coinbase, push0, limit/meter initcode', + url: 'https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/shanghai.md', + status: 'Final', + eips: [3651, 3855, 3860, 4895], +}; diff --git a/packages/web3-eth-accounts/src/common/hardforks/sharding.ts b/packages/web3-eth-accounts/src/common/hardforks/sharding.ts index e164e5f84d7..53d668b562f 100644 --- a/packages/web3-eth-accounts/src/common/hardforks/sharding.ts +++ b/packages/web3-eth-accounts/src/common/hardforks/sharding.ts @@ -1,8 +1,7 @@ export default { - "name": "shardingFork", - "comment": "Internal hardfork to test proto-danksharding (do not use in production)", - "url": "https://eips.ethereum.org/EIPS/eip-4844", - "status": "Experimental", - "eips": [4844] -} - ; \ No newline at end of file + name: 'shardingFork', + comment: 'Internal hardfork to test proto-danksharding (do not use in production)', + url: 'https://eips.ethereum.org/EIPS/eip-4844', + status: 'Experimental', + eips: [4844], +}; diff --git a/packages/web3-eth-accounts/src/common/hardforks/spuriousDragon.ts b/packages/web3-eth-accounts/src/common/hardforks/spuriousDragon.ts index e1ed0eda36c..2ed301b1a41 100644 --- a/packages/web3-eth-accounts/src/common/hardforks/spuriousDragon.ts +++ b/packages/web3-eth-accounts/src/common/hardforks/spuriousDragon.ts @@ -1,21 +1,21 @@ export default { - "name": "spuriousDragon", - "comment": "HF with EIPs for simple replay attack protection, EXP cost increase, state trie clearing, contract code size limit", - "url": "https://eips.ethereum.org/EIPS/eip-607", - "status": "Final", - "gasConfig": {}, - "gasPrices": { - "expByte": { - "v": 50, - "d": "Times ceil(log256(exponent)) for the EXP instruction" - } + name: 'spuriousDragon', + comment: + 'HF with EIPs for simple replay attack protection, EXP cost increase, state trie clearing, contract code size limit', + url: 'https://eips.ethereum.org/EIPS/eip-607', + status: 'Final', + gasConfig: {}, + gasPrices: { + expByte: { + v: 50, + d: 'Times ceil(log256(exponent)) for the EXP instruction', + }, }, - "vm": { - "maxCodeSize": { - "v": 24576, - "d": "Maximum length of contract code" - } + vm: { + maxCodeSize: { + v: 24576, + d: 'Maximum length of contract code', + }, }, - "pow": {} -} - ; \ No newline at end of file + pow: {}, +}; diff --git a/packages/web3-eth-accounts/src/common/hardforks/tangerineWhistle.ts b/packages/web3-eth-accounts/src/common/hardforks/tangerineWhistle.ts index ffb2bf43594..ccfc1044ccd 100644 --- a/packages/web3-eth-accounts/src/common/hardforks/tangerineWhistle.ts +++ b/packages/web3-eth-accounts/src/common/hardforks/tangerineWhistle.ts @@ -1,44 +1,43 @@ export default { - "name": "tangerineWhistle", - "comment": "Hardfork with gas cost changes for IO-heavy operations", - "url": "https://eips.ethereum.org/EIPS/eip-608", - "status": "Final", - "gasConfig": {}, - "gasPrices": { - "sload": { - "v": 200, - "d": "Once per SLOAD operation" - }, - "call": { - "v": 700, - "d": "Once per CALL operation & message call transaction" - }, - "extcodesize": { - "v": 700, - "d": "Base fee of the EXTCODESIZE opcode" - }, - "extcodecopy": { - "v": 700, - "d": "Base fee of the EXTCODECOPY opcode" - }, - "balance": { - "v": 400, - "d": "Base fee of the BALANCE opcode" - }, - "delegatecall": { - "v": 700, - "d": "Base fee of the DELEGATECALL opcode" - }, - "callcode": { - "v": 700, - "d": "Base fee of the CALLCODE opcode" - }, - "selfdestruct": { - "v": 5000, - "d": "Base fee of the SELFDESTRUCT opcode" - } + name: 'tangerineWhistle', + comment: 'Hardfork with gas cost changes for IO-heavy operations', + url: 'https://eips.ethereum.org/EIPS/eip-608', + status: 'Final', + gasConfig: {}, + gasPrices: { + sload: { + v: 200, + d: 'Once per SLOAD operation', + }, + call: { + v: 700, + d: 'Once per CALL operation & message call transaction', + }, + extcodesize: { + v: 700, + d: 'Base fee of the EXTCODESIZE opcode', + }, + extcodecopy: { + v: 700, + d: 'Base fee of the EXTCODECOPY opcode', + }, + balance: { + v: 400, + d: 'Base fee of the BALANCE opcode', + }, + delegatecall: { + v: 700, + d: 'Base fee of the DELEGATECALL opcode', + }, + callcode: { + v: 700, + d: 'Base fee of the CALLCODE opcode', + }, + selfdestruct: { + v: 5000, + d: 'Base fee of the SELFDESTRUCT opcode', + }, }, - "vm": {}, - "pow": {} -} - ; \ No newline at end of file + vm: {}, + pow: {}, +}; diff --git a/packages/web3-eth-accounts/src/wallet.ts b/packages/web3-eth-accounts/src/wallet.ts index 1e189fe4cbc..d69f6e5ddc6 100644 --- a/packages/web3-eth-accounts/src/wallet.ts +++ b/packages/web3-eth-accounts/src/wallet.ts @@ -26,18 +26,18 @@ type BrowserError = { code: number; name: string }; * These accounts can be used when using web3.eth.sendTransaction() or web3.eth.contract.methods.contractfunction().send(); * * For using Wallet functionality, install Web3 package using `npm i web3` or `yarn add web3`. - * After that, Wallet functionality will be available as mentioned below. - * + * After that, Wallet functionality will be available as mentioned below. + * * ```ts * import { Web3 } from 'web3'; * const web3 = new Web3('http://127.0.0.1:7545'); - * + * * const wallet = await web3.eth.accounts.wallet.create(2); - * + * * const signature = wallet.at(0).sign("Test Data"); // use wallet - * + * * // fund account before sending following transaction ... - * + * * const receipt = await web3.eth.sendTransaction({ // internally sign transaction using wallet * from: wallet.at(0).address, * to: "0xdAC17F958D2ee523a2206206994597C13D831ec7", diff --git a/packages/web3-eth-accounts/test/fixtures/account.ts b/packages/web3-eth-accounts/test/fixtures/account.ts index 104b5688e97..08c6a19ef54 100644 --- a/packages/web3-eth-accounts/test/fixtures/account.ts +++ b/packages/web3-eth-accounts/test/fixtures/account.ts @@ -222,27 +222,29 @@ export const invalidPrivateKeytoAccountData: [ ]; export const validPrivateKeyToPublicKeyData: [ - Bytes, boolean, string // private key, isCompressed, public key + Bytes, + boolean, + string, // private key, isCompressed, public key ][] = [ [ - "0x1e046a882bb38236b646c9f135cf90ad90a140810f439875f2a6dd8e50fa261f", // test string to uncompressed publickey + '0x1e046a882bb38236b646c9f135cf90ad90a140810f439875f2a6dd8e50fa261f', // test string to uncompressed publickey false, - "0x42beb65f179720abaa3ec9a70a539629cbbc5ec65bb57e7fc78977796837e537662dd17042e6449dc843c281067a4d6d8d1a1775a13c41901670d5de7ee6503a", + '0x42beb65f179720abaa3ec9a70a539629cbbc5ec65bb57e7fc78977796837e537662dd17042e6449dc843c281067a4d6d8d1a1775a13c41901670d5de7ee6503a', ], [ - "0x1e046a882bb38236b646c9f135cf90ad90a140810f439875f2a6dd8e50fa261f", // test string to compressed publickey + '0x1e046a882bb38236b646c9f135cf90ad90a140810f439875f2a6dd8e50fa261f', // test string to compressed publickey true, - "0x42beb65f179720abaa3ec9a70a539629cbbc5ec65bb57e7fc78977796837e537", + '0x42beb65f179720abaa3ec9a70a539629cbbc5ec65bb57e7fc78977796837e537', ], [ - hexToBytes("0xd933beabed94a9f23917576596b2bc64ffeacfe5ded09a99c0feee8369bd295d"), // test uint8array to uncompressed publickey + hexToBytes('0xd933beabed94a9f23917576596b2bc64ffeacfe5ded09a99c0feee8369bd295d'), // test uint8array to uncompressed publickey false, - "0x7891db4ed2d26584b0fa87329c40b398c940c08e7dbeb8e3dad83f34dba284c933fb14b1edd8893fa89af3823fd827ee59044033ca068803030afc294de5f390", + '0x7891db4ed2d26584b0fa87329c40b398c940c08e7dbeb8e3dad83f34dba284c933fb14b1edd8893fa89af3823fd827ee59044033ca068803030afc294de5f390', ], [ - hexToBytes("0xd933beabed94a9f23917576596b2bc64ffeacfe5ded09a99c0feee8369bd295d"), // test uint8array to compressed publickey + hexToBytes('0xd933beabed94a9f23917576596b2bc64ffeacfe5ded09a99c0feee8369bd295d'), // test uint8array to compressed publickey true, - "0x7891db4ed2d26584b0fa87329c40b398c940c08e7dbeb8e3dad83f34dba284c9", + '0x7891db4ed2d26584b0fa87329c40b398c940c08e7dbeb8e3dad83f34dba284c9', ], ]; @@ -407,9 +409,15 @@ export const invalidEncryptData: [ ]; export const validRecover: [string, string][] = [ - [ "I hereby confirm that I am the sole beneficial owner of the assets involved in the business relationship with Fiat24. \nI hereby undertake to inform Fiat24 proactively of any changes to the information contained herein.", "0xec4f73260ac14882e65995a09359896a0ae8f16bd0d28b0d9171655b4e85271e07cda040be059fdcbf52709e3c993eb50a89ce33f41617dc090dc80a583e3c4f00",], // v < 27 - ["test", "0xefb42c22baa0143b322e93b24b0903a0ef47a64b716fbb77debbea55a93dec3e4417aff7dce845723240916c6e34cf17c674828b3addfb0afad966334df5b6311b"] // v >= 27 -] + [ + 'I hereby confirm that I am the sole beneficial owner of the assets involved in the business relationship with Fiat24. \nI hereby undertake to inform Fiat24 proactively of any changes to the information contained herein.', + '0xec4f73260ac14882e65995a09359896a0ae8f16bd0d28b0d9171655b4e85271e07cda040be059fdcbf52709e3c993eb50a89ce33f41617dc090dc80a583e3c4f00', + ], // v < 27 + [ + 'test', + '0xefb42c22baa0143b322e93b24b0903a0ef47a64b716fbb77debbea55a93dec3e4417aff7dce845723240916c6e34cf17c674828b3addfb0afad966334df5b6311b', + ], // v >= 27 +]; export const invalidKeyStore: [[any, string]][] = [ [ diff --git a/packages/web3-eth-accounts/test/unit/account_dom.test.ts b/packages/web3-eth-accounts/test/unit/account_dom.test.ts index 587996a721c..799fc4f2f8e 100644 --- a/packages/web3-eth-accounts/test/unit/account_dom.test.ts +++ b/packages/web3-eth-accounts/test/unit/account_dom.test.ts @@ -98,9 +98,9 @@ describe('accounts', () => { describe('privateKeyToAccount', () => { describe('valid cases', () => { it.each(validPrivateKeytoAccountData)('%s', (input, output) => { - expect(JSON.stringify(privateKeyToAccount(input.address, input.ignoreLength))).toEqual( - JSON.stringify(output), - ); + expect( + JSON.stringify(privateKeyToAccount(input.address, input.ignoreLength)), + ).toEqual(JSON.stringify(output)); }); }); @@ -213,13 +213,17 @@ describe('accounts', () => { // make sure decrypt does not throw invalid password error const result = await decrypt(keystore, input[1]); - expect(JSON.stringify(result)).toEqual(JSON.stringify(privateKeyToAccount(input[3]))); + expect(JSON.stringify(result)).toEqual( + JSON.stringify(privateKeyToAccount(input[3])), + ); const keystoreString = JSON.stringify(keystore); const stringResult = await decrypt(keystoreString, input[1], true); - expect(JSON.stringify(stringResult)).toEqual(JSON.stringify(privateKeyToAccount(input[3]))); + expect(JSON.stringify(stringResult)).toEqual( + JSON.stringify(privateKeyToAccount(input[3])), + ); }); }); diff --git a/packages/web3-eth-contract/CHANGELOG.md b/packages/web3-eth-contract/CHANGELOG.md index 0d8310b9832..318816b7941 100644 --- a/packages/web3-eth-contract/CHANGELOG.md +++ b/packages/web3-eth-contract/CHANGELOG.md @@ -397,11 +397,11 @@ Documentation: ### Added -- Added `populateTransaction` to the `contract.deploy(...)` properties. (#7197) +- Added `populateTransaction` to the `contract.deploy(...)` properties. (#7197) ### Changed - The returnred properties of `contract.deploy(...)` are structured with a newly created class named `DeployerMethodClass`. (#7197) -- Add a missed accepted type for the `abi` parameter, at `dataInputEncodeMethodHelper` and `getSendTxParams`. (#7197) +- Add a missed accepted type for the `abi` parameter, at `dataInputEncodeMethodHelper` and `getSendTxParams`. (#7197) -## [Unreleased] \ No newline at end of file +## [Unreleased] diff --git a/packages/web3-eth-contract/src/contract-deployer-method-class.ts b/packages/web3-eth-contract/src/contract-deployer-method-class.ts index d57f7ae05b2..33018541390 100644 --- a/packages/web3-eth-contract/src/contract-deployer-method-class.ts +++ b/packages/web3-eth-contract/src/contract-deployer-method-class.ts @@ -15,14 +15,8 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ -import { - Web3ContractError, -} from 'web3-errors'; -import { - sendTransaction, - SendTransactionEvents, - SendTransactionOptions, -} from 'web3-eth'; +import { Web3ContractError } from 'web3-errors'; +import { sendTransaction, SendTransactionEvents, SendTransactionOptions } from 'web3-eth'; import { AbiConstructorFragment, AbiFunctionFragment, @@ -37,24 +31,12 @@ import { TransactionReceipt, TransactionCall, } from 'web3-types'; -import { - format, -} from 'web3-utils'; -import { - isNullish, -} from 'web3-validator'; +import { format } from 'web3-utils'; +import { isNullish } from 'web3-validator'; import { Web3PromiEvent } from 'web3-core'; -import { - decodeMethodParams, - encodeMethodABI, -} from './encoding.js'; -import { - NonPayableTxOptions, - PayableTxOptions, -} from './types.js'; -import { - getSendTxParams, -} from './utils.js'; +import { decodeMethodParams, encodeMethodABI } from './encoding.js'; +import { NonPayableTxOptions, PayableTxOptions } from './types.js'; +import { getSendTxParams } from './utils.js'; // eslint-disable-next-line import/no-cycle import { Contract } from './contract.js'; @@ -68,15 +50,12 @@ export type ContractDeploySend = Web3PromiEvent< * This class is only supposed to be used for the return of `new Contract(...).deploy(...)` method. */ export class DeployerMethodClass { - protected readonly args: never[] | ContractConstructorArgs; protected readonly constructorAbi: AbiConstructorFragment; protected readonly contractOptions: ContractOptions; protected readonly deployData?: string; - protected _contractMethodDeploySend( - tx: TransactionCall, - ) { + protected _contractMethodDeploySend(tx: TransactionCall) { // eslint-disable-next-line no-use-before-define const returnTxOptions: SendTransactionOptions> = { transactionResolver: (receipt: TransactionReceipt) => { @@ -90,7 +69,7 @@ export class DeployerMethodClass { newContract.options.address = receipt.contractAddress; return newContract; }, - + contractAbi: this.parent.options.jsonInterface, // TODO Should make this configurable by the user checkRevertBeforeSending: false, @@ -124,8 +103,7 @@ export class DeployerMethodClass { } | undefined, ) { - - const { args, abi, contractOptions, deployData} = this.calculateDeployParams(); + const { args, abi, contractOptions, deployData } = this.calculateDeployParams(); this.args = args; this.constructorAbi = abi; @@ -141,9 +119,7 @@ export class DeployerMethodClass { return this._contractMethodDeploySend(tx); } - public populateTransaction( - txOptions?: PayableTxOptions | NonPayableTxOptions, - ) { + public populateTransaction(txOptions?: PayableTxOptions | NonPayableTxOptions) { const modifiedContractOptions = { ...this.contractOptions, from: this.contractOptions.from ?? this.parent.defaultAccount ?? undefined, @@ -202,7 +178,7 @@ export class DeployerMethodClass { }; const deployData = _input ?? _data; - return { args, abi, contractOptions, deployData} + return { args, abi, contractOptions, deployData }; } public async estimateGas( @@ -233,8 +209,12 @@ export class DeployerMethodClass { public decodeData(data: HexString) { return { - ...decodeMethodParams(this.constructorAbi, data.replace(this.deployData as string, ''), false), + ...decodeMethodParams( + this.constructorAbi, + data.replace(this.deployData as string, ''), + false, + ), __method__: this.constructorAbi.type, }; } -}; +} diff --git a/packages/web3-eth-contract/src/contract.ts b/packages/web3-eth-contract/src/contract.ts index 906cd3c8794..5566d0840bf 100644 --- a/packages/web3-eth-contract/src/contract.ts +++ b/packages/web3-eth-contract/src/contract.ts @@ -209,8 +209,6 @@ const contractSubscriptions = { newBlockHeaders: NewHeadsSubscription, }; - - /** * The `web3.eth.Contract` makes it easy to interact with smart contracts on the ethereum blockchain. * For using contract package, first install Web3 package using: `npm i web3` or `yarn add web3` based on your package manager, after that contracts features can be used as mentioned in following snippet. @@ -511,7 +509,11 @@ export class Contract ); public constructor( jsonInterface: Abi, - addressOrOptionsOrContext?: Address | ContractInitOptions | Web3ContractContext | Web3Context, + addressOrOptionsOrContext?: + | Address + | ContractInitOptions + | Web3ContractContext + | Web3Context, optionsOrContextOrReturnFormat?: | ContractInitOptions | Web3ContractContext @@ -537,14 +539,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; @@ -960,7 +968,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(), ); } @@ -970,7 +979,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() + ); }); }); } @@ -1013,7 +1025,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 = { @@ -1029,7 +1043,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, [ @@ -1037,10 +1053,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, @@ -1053,7 +1069,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] = @@ -1129,7 +1146,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); @@ -1145,9 +1165,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 @@ -1169,7 +1189,14 @@ 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), @@ -1198,7 +1225,8 @@ export class Contract }, estimateGas: async ( options?: PayableCallOptions | NonPayableCallOptions, - returnFormat: ReturnFormat = this.defaultReturnFormat as unknown as ReturnFormat, + returnFormat: ReturnFormat = this + .defaultReturnFormat as unknown as ReturnFormat, ) => this.contractMethodEstimateGas({ abi: methodAbi, @@ -1381,7 +1409,11 @@ export class Contract 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, @@ -1391,7 +1423,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, }, ); @@ -1404,7 +1439,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/src/encoding.ts b/packages/web3-eth-contract/src/encoding.ts index f57a9d7b4c5..48531277518 100644 --- a/packages/web3-eth-contract/src/encoding.ts +++ b/packages/web3-eth-contract/src/encoding.ts @@ -137,7 +137,6 @@ export const encodeMethodABI = ( params = inferTypesAndEncodeParameters(args).replace('0x', ''); } - if (isAbiConstructorFragment(abi)) { if (!deployData) throw new Web3ContractError( diff --git a/packages/web3-eth-contract/src/utils.ts b/packages/web3-eth-contract/src/utils.ts index fc475a5a813..5ef2de6d594 100644 --- a/packages/web3-eth-contract/src/utils.ts +++ b/packages/web3-eth-contract/src/utils.ts @@ -16,7 +16,12 @@ along with web3.js. If not, see . */ import { RLP } from '@ethereumjs/rlp'; -import { InvalidAddressError, InvalidMethodParamsError, InvalidNumberError, Web3ContractError } from 'web3-errors'; +import { + InvalidAddressError, + InvalidMethodParamsError, + InvalidNumberError, + Web3ContractError, +} from 'web3-errors'; import { TransactionForAccessList, AbiFunctionFragment, @@ -30,7 +35,14 @@ import { Numbers, AbiConstructorFragment, } from 'web3-types'; -import { isNullish, mergeDeep, isContractInitOptions, keccak256, toChecksumAddress, hexToNumber } from 'web3-utils'; +import { + isNullish, + mergeDeep, + isContractInitOptions, + keccak256, + toChecksumAddress, + hexToNumber, +} from 'web3-utils'; import { isAddress, isHexString } from 'web3-validator'; import { encodeMethodABI } from './encoding.js'; import { Web3ContractContext } from './types.js'; @@ -215,41 +227,38 @@ export const getCreateAccessListParams = ({ return txParams; }; - export const createContractAddress = (from: Address, nonce: Numbers): Address => { - if(!isAddress(from)) - throw new InvalidAddressError(`Invalid address given ${from}`); + if (!isAddress(from)) throw new InvalidAddressError(`Invalid address given ${from}`); let nonceValue = nonce; - if(typeof nonce === "string" && isHexString(nonce)) - nonceValue = hexToNumber(nonce); - else if(typeof nonce === "string" && !isHexString(nonce)) - throw new InvalidNumberError("Invalid nonce value format"); + if (typeof nonce === 'string' && isHexString(nonce)) nonceValue = hexToNumber(nonce); + else if (typeof nonce === 'string' && !isHexString(nonce)) + throw new InvalidNumberError('Invalid nonce value format'); - const rlpEncoded = RLP.encode( - [from, nonceValue] - ); - const result = keccak256(rlpEncoded); + const rlpEncoded = RLP.encode([from, nonceValue]); + const result = keccak256(rlpEncoded); - const contractAddress = '0x'.concat(result.substring(26)); + const contractAddress = '0x'.concat(result.substring(26)); - return toChecksumAddress(contractAddress); -} + return toChecksumAddress(contractAddress); +}; -export const create2ContractAddress = (from: Address, salt: HexString, initCode: HexString): Address => { - if(!isAddress(from)) - throw new InvalidAddressError(`Invalid address given ${from}`); +export const create2ContractAddress = ( + from: Address, + salt: HexString, + initCode: HexString, +): Address => { + if (!isAddress(from)) throw new InvalidAddressError(`Invalid address given ${from}`); - if(!isHexString(salt)) - throw new InvalidMethodParamsError(`Invalid salt value ${salt}`); + if (!isHexString(salt)) throw new InvalidMethodParamsError(`Invalid salt value ${salt}`); - if(!isHexString(initCode)) - throw new InvalidMethodParamsError(`Invalid initCode value ${initCode}`); + if (!isHexString(initCode)) + throw new InvalidMethodParamsError(`Invalid initCode value ${initCode}`); const initCodeHash = keccak256(initCode); const initCodeHashPadded = initCodeHash.padStart(64, '0'); // Pad to 32 bytes (64 hex characters) const create2Params = ['0xff', from, salt, initCodeHashPadded].map(x => x.replace(/0x/, '')); - const create2Address = `0x${ create2Params.join('')}`; + const create2Address = `0x${create2Params.join('')}`; - return toChecksumAddress(`0x${ keccak256(create2Address).slice(26)}`); // Slice to get the last 20 bytes (40 hex characters) & checksum - } \ No newline at end of file + return toChecksumAddress(`0x${keccak256(create2Address).slice(26)}`); // Slice to get the last 20 bytes (40 hex characters) & checksum +}; diff --git a/packages/web3-eth-contract/test/fixtures/AbiItem.ts b/packages/web3-eth-contract/test/fixtures/AbiItem.ts index bcc94ce4b02..7b112ef2e80 100644 --- a/packages/web3-eth-contract/test/fixtures/AbiItem.ts +++ b/packages/web3-eth-contract/test/fixtures/AbiItem.ts @@ -16,84 +16,84 @@ along with web3.js. If not, see . */ export const Abi = { - anonymous: false, - constant: true, - inputs: [ - { - name: 'testMe', - type: 'uint256[3]' - }, - { - name: 'inputA', - type: 'tuple', - components: [ - { - name: 'a', - type: 'uint8' - }, - { - name: 'b', - type: 'uint8' - } - ] - }, - { - name: 'inputB', - type: 'tuple[]', - components: [ - { - name: 'a1', - type: 'uint256' - }, - { - name: 'a2', - type: 'uint256' - } - ] - }, - { - name: 'inputC', - type: 'uint8', - indexed: false - } - ], - name: "testName", - outputs: [ - { - name: "test", - type: "uint256" - }, - { - name: 'outputA', - type: 'tuple', - components: [ - { - name: 'a', - type: 'uint8' - }, - { - name: 'b', - type: 'uint8' - } - ] - }, - { - name: 'outputB', - type: 'tuple[]', - components: [ - { - name: 'a1', - type: 'uint256' - }, - { - name: 'a2', - type: 'uint256' - } - ] - } - ], - payable: false, - stateMutability: "pure", - type: "function", - gas: 175875 -} \ No newline at end of file + anonymous: false, + constant: true, + inputs: [ + { + name: 'testMe', + type: 'uint256[3]', + }, + { + name: 'inputA', + type: 'tuple', + components: [ + { + name: 'a', + type: 'uint8', + }, + { + name: 'b', + type: 'uint8', + }, + ], + }, + { + name: 'inputB', + type: 'tuple[]', + components: [ + { + name: 'a1', + type: 'uint256', + }, + { + name: 'a2', + type: 'uint256', + }, + ], + }, + { + name: 'inputC', + type: 'uint8', + indexed: false, + }, + ], + name: 'testName', + outputs: [ + { + name: 'test', + type: 'uint256', + }, + { + name: 'outputA', + type: 'tuple', + components: [ + { + name: 'a', + type: 'uint8', + }, + { + name: 'b', + type: 'uint8', + }, + ], + }, + { + name: 'outputB', + type: 'tuple[]', + components: [ + { + name: 'a1', + type: 'uint256', + }, + { + name: 'a2', + type: 'uint256', + }, + ], + }, + ], + payable: false, + stateMutability: 'pure', + type: 'function', + gas: 175875, +}; diff --git a/packages/web3-eth-contract/test/fixtures/contract_transaction_middleware.ts b/packages/web3-eth-contract/test/fixtures/contract_transaction_middleware.ts index 9a1ab0f20cf..0a3d1819809 100644 --- a/packages/web3-eth-contract/test/fixtures/contract_transaction_middleware.ts +++ b/packages/web3-eth-contract/test/fixtures/contract_transaction_middleware.ts @@ -15,24 +15,21 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ -import { TransactionMiddleware, TransactionMiddlewareData } from "web3-eth"; +import { TransactionMiddleware, TransactionMiddlewareData } from 'web3-eth'; -// Sample Transaction Middleware +// Sample Transaction Middleware export class ContractTransactionMiddleware implements TransactionMiddleware { - // eslint-disable-next-line class-methods-use-this - public async processTransaction(transaction: TransactionMiddlewareData, - _options?: { [key: string]: unknown } | undefined): - - Promise { - + public async processTransaction( + transaction: TransactionMiddlewareData, + _options?: { [key: string]: unknown } | undefined, + ): Promise { // eslint-disable-next-line prefer-const let txObj = { ...transaction }; - // Add your logic here for transaction modification + // Add your logic here for transaction modification txObj.data = '0x123'; return Promise.resolve(txObj); } - } diff --git a/packages/web3-eth-contract/test/fixtures/create.ts b/packages/web3-eth-contract/test/fixtures/create.ts index 0297828e5f1..4262b53e68d 100644 --- a/packages/web3-eth-contract/test/fixtures/create.ts +++ b/packages/web3-eth-contract/test/fixtures/create.ts @@ -15,120 +15,119 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ -import { Numbers } from "web3-types"; +import { Numbers } from 'web3-types'; export interface CreateTestData { - address: string; - input: { - from: string; - nonce: Numbers; - }; - } - + address: string; + input: { + from: string; + nonce: Numbers; + }; +} + export const testData: CreateTestData[] = [ - { - address: '0x0C1B54fb6fdf63DEe15e65CAdBA8F2e028E26Bd0', - - input: { - from: '0xe2597eb05cf9a87eb1309e86750c903ec38e527e', - nonce: 0, - } - }, - { - address: '0x0C1B54fb6fdf63DEe15e65CAdBA8F2e028E26Bd0', - - input: { - from: '0xe2597eb05cf9a87eb1309e86750c903ec38e527e', - nonce: BigInt(0), - } - }, - { - address: '0x0C1B54fb6fdf63DEe15e65CAdBA8F2e028E26Bd0', - - input: { - from: '0xe2597eb05cf9a87eb1309e86750c903ec38e527e', - nonce: "0x0", - } - }, - { - address: '0x3474627D4F63A678266BC17171D87f8570936622', - - input: { - from: '0xb2682160c482eb985ec9f3e364eec0a904c44c23', - nonce: 10, - } - }, - - { - address: '0x3474627D4F63A678266BC17171D87f8570936622', - - input: { - from: '0xb2682160c482eb985ec9f3e364eec0a904c44c23', - nonce: "0xa", - } - }, - - { - address: '0x3474627D4F63A678266BC17171D87f8570936622', - - input: { - from: '0xb2682160c482eb985ec9f3e364eec0a904c44c23', - nonce: "0x0a", - } - }, - - { - address: '0x271300790813f82638A8A6A8a86d65df6dF33c17', - - input: { - from: '0x8ba1f109551bd432803012645ac136ddd64dba72', - nonce: "0x200", - } - }, - - { - address: '0x271300790813f82638A8A6A8a86d65df6dF33c17', - - input: { - from: '0x8ba1f109551bd432803012645ac136ddd64dba72', - nonce: "0x0200", - } - }, - - { - address: '0x995C25706C407a1F1E84b3777775e3e619764933', - - input: { - from: '0x8ba1f109551bd432803012645ac136ddd64dba72', - nonce: "0x1d", - } - }, - - { - address: '0x995C25706C407a1F1E84b3777775e3e619764933', - - input: { - from: '0x8ba1f109551bd432803012645ac136ddd64dba72', - nonce: "0x001d", - } - }, - - { - address: '0x995C25706C407a1F1E84b3777775e3e619764933', - - input: { - from: '0x8ba1f109551bd432803012645ac136ddd64dba72', - nonce: 29, - } - }, - - - { - address: '0x0CcCC7507aEDf9FEaF8C8D731421746e16b4d39D', - - input: { - from: '0xc6af6e1a78a6752c7f8cd63877eb789a2adb776c', - nonce: 0 - } - }, -]; \ No newline at end of file + { + address: '0x0C1B54fb6fdf63DEe15e65CAdBA8F2e028E26Bd0', + + input: { + from: '0xe2597eb05cf9a87eb1309e86750c903ec38e527e', + nonce: 0, + }, + }, + { + address: '0x0C1B54fb6fdf63DEe15e65CAdBA8F2e028E26Bd0', + + input: { + from: '0xe2597eb05cf9a87eb1309e86750c903ec38e527e', + nonce: BigInt(0), + }, + }, + { + address: '0x0C1B54fb6fdf63DEe15e65CAdBA8F2e028E26Bd0', + + input: { + from: '0xe2597eb05cf9a87eb1309e86750c903ec38e527e', + nonce: '0x0', + }, + }, + { + address: '0x3474627D4F63A678266BC17171D87f8570936622', + + input: { + from: '0xb2682160c482eb985ec9f3e364eec0a904c44c23', + nonce: 10, + }, + }, + + { + address: '0x3474627D4F63A678266BC17171D87f8570936622', + + input: { + from: '0xb2682160c482eb985ec9f3e364eec0a904c44c23', + nonce: '0xa', + }, + }, + + { + address: '0x3474627D4F63A678266BC17171D87f8570936622', + + input: { + from: '0xb2682160c482eb985ec9f3e364eec0a904c44c23', + nonce: '0x0a', + }, + }, + + { + address: '0x271300790813f82638A8A6A8a86d65df6dF33c17', + + input: { + from: '0x8ba1f109551bd432803012645ac136ddd64dba72', + nonce: '0x200', + }, + }, + + { + address: '0x271300790813f82638A8A6A8a86d65df6dF33c17', + + input: { + from: '0x8ba1f109551bd432803012645ac136ddd64dba72', + nonce: '0x0200', + }, + }, + + { + address: '0x995C25706C407a1F1E84b3777775e3e619764933', + + input: { + from: '0x8ba1f109551bd432803012645ac136ddd64dba72', + nonce: '0x1d', + }, + }, + + { + address: '0x995C25706C407a1F1E84b3777775e3e619764933', + + input: { + from: '0x8ba1f109551bd432803012645ac136ddd64dba72', + nonce: '0x001d', + }, + }, + + { + address: '0x995C25706C407a1F1E84b3777775e3e619764933', + + input: { + from: '0x8ba1f109551bd432803012645ac136ddd64dba72', + nonce: 29, + }, + }, + + { + address: '0x0CcCC7507aEDf9FEaF8C8D731421746e16b4d39D', + + input: { + from: '0xc6af6e1a78a6752c7f8cd63877eb789a2adb776c', + nonce: 0, + }, + }, +]; diff --git a/packages/web3-eth-contract/test/fixtures/create2.ts b/packages/web3-eth-contract/test/fixtures/create2.ts index 2cceb34f1bc..95bbb616983 100644 --- a/packages/web3-eth-contract/test/fixtures/create2.ts +++ b/packages/web3-eth-contract/test/fixtures/create2.ts @@ -15,56 +15,57 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ -import { Address, HexString } from "web3-types"; +import { Address, HexString } from 'web3-types'; export interface Create2TestData { - address: Address; - salt: HexString; - init_code: HexString; - result: Address; - } + address: Address; + salt: HexString; + init_code: HexString; + result: Address; +} - export const create2TestData: Create2TestData[] = [ - { - address: "0x0000000000000000000000000000000000000000", - salt: "0x0000000000000000000000000000000000000000000000000000000000000000", - init_code: "0x00", - result: "0x4D1A2e2bB4F88F0250f26Ffff098B0b30B26BF38" - }, - { - address: "0xdeadbeef00000000000000000000000000000000", - salt: "0x0000000000000000000000000000000000000000000000000000000000000000", - init_code: "0x00", - result: "0xB928f69Bb1D91Cd65274e3c79d8986362984fDA3" - }, - { - address: "0xdeadbeef00000000000000000000000000000000", - salt: "0x000000000000000000000000feed000000000000000000000000000000000000", - init_code: "0x00", - result: "0xD04116cDd17beBE565EB2422F2497E06cC1C9833" - }, - { - address: "0x0000000000000000000000000000000000000000", - salt: "0x0000000000000000000000000000000000000000000000000000000000000000", - init_code: "0xdeadbeef", - result: "0x70f2b2914A2a4b783FaEFb75f459A580616Fcb5e" - }, - { - address: "0x00000000000000000000000000000000deadbeef", - salt: "0x00000000000000000000000000000000000000000000000000000000cafebabe", - init_code: "0xdeadbeef", - result: "0x60f3f640a8508fC6a86d45DF051962668E1e8AC7" - }, - { - address: "0x00000000000000000000000000000000deadbeef", - salt: "0x00000000000000000000000000000000000000000000000000000000cafebabe", - init_code: "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef", - result: "0x1d8bfDC5D46DC4f61D6b6115972536eBE6A8854C" - }, - { - address: "0x0000000000000000000000000000000000000000", - salt: "0x0000000000000000000000000000000000000000000000000000000000000000", - init_code: "0x", - result: "0xE33C0C7F7df4809055C3ebA6c09CFe4BaF1BD9e0" - } - ]; \ No newline at end of file +export const create2TestData: Create2TestData[] = [ + { + address: '0x0000000000000000000000000000000000000000', + salt: '0x0000000000000000000000000000000000000000000000000000000000000000', + init_code: '0x00', + result: '0x4D1A2e2bB4F88F0250f26Ffff098B0b30B26BF38', + }, + { + address: '0xdeadbeef00000000000000000000000000000000', + salt: '0x0000000000000000000000000000000000000000000000000000000000000000', + init_code: '0x00', + result: '0xB928f69Bb1D91Cd65274e3c79d8986362984fDA3', + }, + { + address: '0xdeadbeef00000000000000000000000000000000', + salt: '0x000000000000000000000000feed000000000000000000000000000000000000', + init_code: '0x00', + result: '0xD04116cDd17beBE565EB2422F2497E06cC1C9833', + }, + { + address: '0x0000000000000000000000000000000000000000', + salt: '0x0000000000000000000000000000000000000000000000000000000000000000', + init_code: '0xdeadbeef', + result: '0x70f2b2914A2a4b783FaEFb75f459A580616Fcb5e', + }, + { + address: '0x00000000000000000000000000000000deadbeef', + salt: '0x00000000000000000000000000000000000000000000000000000000cafebabe', + init_code: '0xdeadbeef', + result: '0x60f3f640a8508fC6a86d45DF051962668E1e8AC7', + }, + { + address: '0x00000000000000000000000000000000deadbeef', + salt: '0x00000000000000000000000000000000000000000000000000000000cafebabe', + init_code: + '0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef', + result: '0x1d8bfDC5D46DC4f61D6b6115972536eBE6A8854C', + }, + { + address: '0x0000000000000000000000000000000000000000', + salt: '0x0000000000000000000000000000000000000000000000000000000000000000', + init_code: '0x', + result: '0xE33C0C7F7df4809055C3ebA6c09CFe4BaF1BD9e0', + }, +]; diff --git a/packages/web3-eth-contract/test/integration/contract_accesslist.test.ts b/packages/web3-eth-contract/test/integration/contract_accesslist.test.ts index 23934b05016..3173f452c33 100644 --- a/packages/web3-eth-contract/test/integration/contract_accesslist.test.ts +++ b/packages/web3-eth-contract/test/integration/contract_accesslist.test.ts @@ -22,7 +22,7 @@ import { createTempAccount, describeIf, getSystemTestBackend, - BACKEND + BACKEND, } from '../fixtures/system_test_utils'; describe('contract', () => { 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 2ff87f07177..b54ed63b41d 100644 --- a/packages/web3-eth-contract/test/integration/contract_deploy.test.ts +++ b/packages/web3-eth-contract/test/integration/contract_deploy.test.ts @@ -64,7 +64,7 @@ describe('contract', () => { // get contract address before deployment const address = createContractAddress(sendOptions.from as string, nonce); - + const deployedContract = await contract.deploy(deployOptions).send(sendOptions); expect(deployedContract).toBeDefined(); diff --git a/packages/web3-eth-contract/test/integration/contract_methods.test.ts b/packages/web3-eth-contract/test/integration/contract_methods.test.ts index 7cede74d7d1..46a1490c119 100644 --- a/packages/web3-eth-contract/test/integration/contract_methods.test.ts +++ b/packages/web3-eth-contract/test/integration/contract_methods.test.ts @@ -17,7 +17,12 @@ along with web3.js. If not, see . import { ContractExecutionError } from 'web3-errors'; import { Contract } from '../../src'; import { BasicAbi, BasicBytecode } from '../shared_fixtures/build/Basic'; -import { getSystemTestProvider, createTempAccount, getSystemTestBackend, BACKEND} from '../fixtures/system_test_utils'; +import { + getSystemTestProvider, + createTempAccount, + getSystemTestBackend, + BACKEND, +} from '../fixtures/system_test_utils'; describe('contract', () => { let contract: Contract; @@ -154,8 +159,8 @@ describe('contract', () => { await expect( contractDeployed.methods.reverts().send(sendOptions), ).rejects.toMatchObject({ - "name": "ContractExecutionError", - "receipt": undefined, + name: 'ContractExecutionError', + receipt: undefined, }); } else { // eslint-disable-next-line jest/no-conditional-expect diff --git a/packages/web3-eth-contract/test/integration/local_account/contract_deploy.test.ts b/packages/web3-eth-contract/test/integration/local_account/contract_deploy.test.ts index 7938636d8cb..821101ca225 100644 --- a/packages/web3-eth-contract/test/integration/local_account/contract_deploy.test.ts +++ b/packages/web3-eth-contract/test/integration/local_account/contract_deploy.test.ts @@ -117,22 +117,21 @@ describe('contract', () => { it('should emit the "confirmation" event', async () => { const confirmationHandler = jest.fn(); - const promievent = contract - .deploy(deployOptions) - .send(sendOptions); - const receiptPromise = new Promise((resolve) => { - // eslint-disable-next-line @typescript-eslint/no-floating-promises - promievent - .on('receipt', () => { - resolve() - }) - }) + const promievent = contract.deploy(deployOptions).send(sendOptions); + const receiptPromise = new Promise(resolve => { + // eslint-disable-next-line @typescript-eslint/no-floating-promises + promievent.on('receipt', () => { + resolve(); + }); + }); - const confirmationPRomise = new Promise((resolve) => { + const confirmationPRomise = new Promise(resolve => { // eslint-disable-next-line @typescript-eslint/no-floating-promises - promievent - .on('confirmation', () => {confirmationHandler(); resolve();}) - }) + promievent.on('confirmation', () => { + confirmationHandler(); + resolve(); + }); + }); await promievent; await receiptPromise; diff --git a/packages/web3-eth-contract/test/integration/local_account/contract_overloaded_methods.test.ts b/packages/web3-eth-contract/test/integration/local_account/contract_overloaded_methods.test.ts index 35ca056cbab..96985cda3a7 100644 --- a/packages/web3-eth-contract/test/integration/local_account/contract_overloaded_methods.test.ts +++ b/packages/web3-eth-contract/test/integration/local_account/contract_overloaded_methods.test.ts @@ -102,10 +102,7 @@ describe('contract ERC721 overloaded functions', () => { }); it('transferFrom with 3 invalid arguments', () => { - expect(() => - contractDeployed.methods - .safeTransferFrom(1, 2, 3), - ).toThrow('Web3 validator'); + expect(() => contractDeployed.methods.safeTransferFrom(1, 2, 3)).toThrow('Web3 validator'); }); it('transferFrom with 2 arguments', () => { diff --git a/packages/web3-eth-contract/test/unit/contract.test.ts b/packages/web3-eth-contract/test/unit/contract.test.ts index 6ae5f055904..a87a3455c2b 100644 --- a/packages/web3-eth-contract/test/unit/contract.test.ts +++ b/packages/web3-eth-contract/test/unit/contract.test.ts @@ -41,7 +41,7 @@ import { AllGetPastEventsData, getLogsData, getPastEventsData } from '../fixture import { erc721Abi } from '../fixtures/erc721'; import { ERC20TokenAbi } from '../shared_fixtures/build/ERC20Token'; import { processAsync } from '../shared_fixtures/utils'; -import { ContractTransactionMiddleware } from "../fixtures/contract_transaction_middleware"; +import { ContractTransactionMiddleware } from '../fixtures/contract_transaction_middleware'; jest.mock('web3-eth', () => { const allAutoMocked = jest.createMockFromModule('web3-eth'); @@ -149,7 +149,7 @@ describe('Contract', () => { }); it('should set the provider, from options, upon instantiation', () => { - const provider = "http://127.0.0.1:4545"; + const provider = 'http://127.0.0.1:4545'; const contract = new Contract([], '', { provider, }); @@ -161,7 +161,7 @@ describe('Contract', () => { }); it('should set the provider, from context, upon instantiation', () => { - const provider = "http://127.0.0.1:4545"; + const provider = 'http://127.0.0.1:4545'; const contract = new Contract( [], '', @@ -285,13 +285,12 @@ describe('Contract', () => { it('should pass middleware to sendTransaction when middleware is there and deploy().send() is called', async () => { const contract = new Contract(GreeterAbi); const middleware = new ContractTransactionMiddleware(); - contract.setTransactionMiddleware(middleware) + contract.setTransactionMiddleware(middleware); // eslint-disable-next-line @typescript-eslint/no-unused-vars const sendTransactionSpy = jest .spyOn(eth, 'sendTransaction') .mockImplementation((_objInstance, _tx, _dataFormat, _options, _middleware) => { - expect(_middleware).toBeDefined(); const newContract = contract.clone(); newContract.options.address = deployedAddr; @@ -306,12 +305,11 @@ describe('Contract', () => { arguments: ['My Greeting'], }) .send(sendOptions); - + sendTransactionSpy.mockClear(); }); it('should pass middleware to sendTransaction when middleware is there and contract.method.send() is called', async () => { - const contract = new Contract(GreeterAbi, '0x12264916b10Ae90076dDa6dE756EE1395BB69ec2'); const middleware = new ContractTransactionMiddleware(); contract.setTransactionMiddleware(middleware); @@ -319,17 +317,15 @@ describe('Contract', () => { const spyTx = jest .spyOn(eth, 'sendTransaction') .mockImplementation((_objInstance, _tx, _dataformat, _options, _middleware) => { - expect(_middleware).toBeDefined(); // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-empty-function return { status: '0x1', on: () => {} } as any; - }); const receipt = await contract.methods.setGreeting('Hello').send({ from: '0x12364916b10Ae90076dDa6dE756EE1395BB69ec2', - gas: '1000000' + gas: '1000000', }); expect(receipt.status).toBe('0x1'); @@ -816,7 +812,7 @@ describe('Contract', () => { { gas: '0x97254' }, ); contract.maxListenersWarningThreshold = 1000; - + const clonnedContract = contract.clone(); expect(stringify(contract)).toStrictEqual(stringify(clonnedContract)); @@ -826,7 +822,7 @@ describe('Contract', () => { it('should clone new contract', () => { const contract = new Contract(sampleStorageContractABI); contract.maxListenersWarningThreshold = 1000; - + const clonnedContract = contract.clone(); expect(stringify(contract)).toStrictEqual(stringify(clonnedContract)); }); diff --git a/packages/web3-eth-contract/test/unit/contract_typing.test.ts b/packages/web3-eth-contract/test/unit/contract_typing.test.ts index e0bc6b9afcb..79f66bdca29 100644 --- a/packages/web3-eth-contract/test/unit/contract_typing.test.ts +++ b/packages/web3-eth-contract/test/unit/contract_typing.test.ts @@ -25,7 +25,6 @@ import { erc721Abi, Erc721Interface } from '../fixtures/erc721'; import { NonPayableMethodObject, PayableMethodObject } from '../../src'; describe('contract typing', () => { - describe('no abi type', () => { const defaultContractInstance = new Contract([]); // when using new web3.eth.Contract generic is any[] instead of never @@ -41,8 +40,7 @@ describe('contract typing', () => { expectTypeOf>().toBe(), expectTypeOf>().toBe(), ]); - - }) + }); describe('custom abi', () => { const abi = [ { diff --git a/packages/web3-eth-contract/test/unit/function_overloading.test.ts b/packages/web3-eth-contract/test/unit/function_overloading.test.ts index 6533aea84e2..146ae703f84 100644 --- a/packages/web3-eth-contract/test/unit/function_overloading.test.ts +++ b/packages/web3-eth-contract/test/unit/function_overloading.test.ts @@ -218,7 +218,9 @@ describe('test Params Overloading', () => { it('should call the first one when the signature is not passed but also show a warning', async () => { const originalWarn = console.warn; console.warn = function (message: string) { - expect(message).toMatch('Multiple methods found that is compatible with the given inputs.'); + expect(message).toMatch( + 'Multiple methods found that is compatible with the given inputs.', + ); }; const abi = contract.methods['funcWithParamsOverloading_pure']( '0x12eca7a3959a42973ef4452e44948650be8b8610', @@ -258,7 +260,8 @@ describe('test Params Overloading', () => { }); it('uint8', async () => { - const abi = contract.methods['funcWithParamsOverloading_pure(uint8)']('0x12').encodeABI(); + const abi = + contract.methods['funcWithParamsOverloading_pure(uint8)']('0x12').encodeABI(); expect(abi.substring(0, 10)).toBe('0xf2f11ccd'); }); }); @@ -279,7 +282,8 @@ describe('test Params Overloading', () => { }); it('uint8', async () => { - const abi = contract.methods['funcWithParamsOverloading_view(uint8)']('0x12').encodeABI(); + const abi = + contract.methods['funcWithParamsOverloading_view(uint8)']('0x12').encodeABI(); expect(abi.substring(0, 10)).toBe('0xda202a6f'); }); diff --git a/packages/web3-eth-contract/test/unit/utils.test.ts b/packages/web3-eth-contract/test/unit/utils.test.ts index 3b0b69a2bfc..d2cef819183 100644 --- a/packages/web3-eth-contract/test/unit/utils.test.ts +++ b/packages/web3-eth-contract/test/unit/utils.test.ts @@ -15,80 +15,99 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ -import { InvalidAddressError, InvalidNumberError } from "web3-errors"; -import { Address, Numbers } from "web3-types"; +import { InvalidAddressError, InvalidNumberError } from 'web3-errors'; +import { Address, Numbers } from 'web3-types'; import { CreateTestData, testData } from '../fixtures/create'; -import { create2ContractAddress, createContractAddress } from "../../src/utils"; -import { create2TestData } from "../fixtures/create2"; - +import { create2ContractAddress, createContractAddress } from '../../src/utils'; +import { create2TestData } from '../fixtures/create2'; describe('createContractAddress', () => { - - it.each(testData)('creates correct contract address for input: %o', (testCase: CreateTestData) => { - const { address, input } = testCase; - const result = createContractAddress(input.from , input.nonce ); - expect(result).toBe(address); - }); - - it('should throw InvalidAddressError for invalid address', () => { - expect(() => createContractAddress('invalid_address', 1)).toThrow(InvalidAddressError); - }); - - it('should throw Error for invalid nonce', () => { - expect(() => createContractAddress('0xe2597eb05cf9a87eb1309e86750c903ec38e527e', "")).toThrow(InvalidNumberError); - }); - - it('should handle different nonce types correctly', () => { - const from: Address = '0x6ac7ea33f8831ea9dcc53393aaa88b25a785dbf0'; - const testCases: [Numbers, string][] = [ - [1, '0x343c43A37D37dfF08AE8C4A11544c718AbB4fCF8'], - ['0x2', '0xf778B86FA74E846c4f0a1fBd1335FE81c00a0C91'], - [BigInt(3), '0xffFd933A0bC612844eaF0C6Fe3E5b8E9B6C1d19c'], - ]; - - testCases.forEach(([nonce, expectedAddress]) => { - const result = createContractAddress(from, nonce); - expect(result).toBe(expectedAddress); - }); - }); - - it('should create different addresses for different nonces', () => { - const from: Address = '0x6ac7ea33f8831ea9dcc53393aaa88b25a785dbf0'; - const address1 = createContractAddress(from, 0); - const address2 = createContractAddress(from, 1); - - expect(address1).not.toBe(address2); - }); - - it('should create different addresses for different sender addresses', () => { - const from1: Address = '0x6ac7ea33f8831ea9dcc53393aaa88b25a785dbf0'; - const from2: Address = '0x1234567890123456789012345678901234567890'; - const nonce: Numbers = 0; - - const address1 = createContractAddress(from1, nonce); - const address2 = createContractAddress(from2, nonce); - - expect(address1).not.toBe(address2); - }); + it.each(testData)( + 'creates correct contract address for input: %o', + (testCase: CreateTestData) => { + const { address, input } = testCase; + const result = createContractAddress(input.from, input.nonce); + expect(result).toBe(address); + }, + ); + + it('should throw InvalidAddressError for invalid address', () => { + expect(() => createContractAddress('invalid_address', 1)).toThrow(InvalidAddressError); + }); + + it('should throw Error for invalid nonce', () => { + expect(() => + createContractAddress('0xe2597eb05cf9a87eb1309e86750c903ec38e527e', ''), + ).toThrow(InvalidNumberError); + }); + + it('should handle different nonce types correctly', () => { + const from: Address = '0x6ac7ea33f8831ea9dcc53393aaa88b25a785dbf0'; + const testCases: [Numbers, string][] = [ + [1, '0x343c43A37D37dfF08AE8C4A11544c718AbB4fCF8'], + ['0x2', '0xf778B86FA74E846c4f0a1fBd1335FE81c00a0C91'], + [BigInt(3), '0xffFd933A0bC612844eaF0C6Fe3E5b8E9B6C1d19c'], + ]; + + testCases.forEach(([nonce, expectedAddress]) => { + const result = createContractAddress(from, nonce); + expect(result).toBe(expectedAddress); + }); + }); + + it('should create different addresses for different nonces', () => { + const from: Address = '0x6ac7ea33f8831ea9dcc53393aaa88b25a785dbf0'; + const address1 = createContractAddress(from, 0); + const address2 = createContractAddress(from, 1); + + expect(address1).not.toBe(address2); + }); + + it('should create different addresses for different sender addresses', () => { + const from1: Address = '0x6ac7ea33f8831ea9dcc53393aaa88b25a785dbf0'; + const from2: Address = '0x1234567890123456789012345678901234567890'; + const nonce: Numbers = 0; + + const address1 = createContractAddress(from1, nonce); + const address2 = createContractAddress(from2, nonce); + + expect(address1).not.toBe(address2); + }); }); describe('create2ContractAddress', () => { - - it.each(create2TestData)('creates correct contract address for input: %o', (testCase) => { - const result = create2ContractAddress(testCase.address, testCase.salt, testCase.init_code); - expect(result).toBe(testCase.result); - }); - - it('should throw an InvalidAddressError if the from address is invalid', () => { - expect(() => create2ContractAddress('0xinvalidaddress', create2TestData[0].salt, create2TestData[0].init_code)).toThrow('Invalid address given 0xinvalidaddress'); - }); - - it('should throw an InvalidMethodParamsError if the salt is invalid', () => { - expect(() => create2ContractAddress(create2TestData[0].address, '0xinvalidsalt', create2TestData[0].init_code)).toThrow('Invalid salt value 0xinvalidsalt'); - }); - - it('should throw an InvalidMethodParamsError if the initCode is invalid', () => { - expect(() => create2ContractAddress(create2TestData[0].address, create2TestData[0].salt, '0xinvalidcode')).toThrow('Invalid initCode value 0xinvalidcode'); - }); - -}); \ No newline at end of file + it.each(create2TestData)('creates correct contract address for input: %o', testCase => { + const result = create2ContractAddress(testCase.address, testCase.salt, testCase.init_code); + expect(result).toBe(testCase.result); + }); + + it('should throw an InvalidAddressError if the from address is invalid', () => { + expect(() => + create2ContractAddress( + '0xinvalidaddress', + create2TestData[0].salt, + create2TestData[0].init_code, + ), + ).toThrow('Invalid address given 0xinvalidaddress'); + }); + + it('should throw an InvalidMethodParamsError if the salt is invalid', () => { + expect(() => + create2ContractAddress( + create2TestData[0].address, + '0xinvalidsalt', + create2TestData[0].init_code, + ), + ).toThrow('Invalid salt value 0xinvalidsalt'); + }); + + it('should throw an InvalidMethodParamsError if the initCode is invalid', () => { + expect(() => + create2ContractAddress( + create2TestData[0].address, + create2TestData[0].salt, + '0xinvalidcode', + ), + ).toThrow('Invalid initCode value 0xinvalidcode'); + }); +}); diff --git a/packages/web3-eth-ens/CHANGELOG.md b/packages/web3-eth-ens/CHANGELOG.md index 2eb11d79a13..73454c83b59 100644 --- a/packages/web3-eth-ens/CHANGELOG.md +++ b/packages/web3-eth-ens/CHANGELOG.md @@ -151,7 +151,7 @@ Documentation: ### Add -- Added function getText and getName in ENS and resolver classes (#6914) +- Added function getText and getName in ENS and resolver classes (#6914) ## [4.3.0] @@ -170,4 +170,4 @@ Documentation: - `getName` reverse resolution -## [Unreleased] \ No newline at end of file +## [Unreleased] diff --git a/packages/web3-eth-ens/src/ens.ts b/packages/web3-eth-ens/src/ens.ts index 8f3e1806127..2a74d0f3051 100644 --- a/packages/web3-eth-ens/src/ens.ts +++ b/packages/web3-eth-ens/src/ens.ts @@ -176,8 +176,8 @@ export class ENS extends Web3Context { * @returns - The value content stored in the resolver for the specified key */ public async getText(ENSNameOrAddr: string | Address, key: string): Promise { - if(isAddress(ENSNameOrAddr)) - return this._resolver.getText(await(this._resolver.getName(ENSNameOrAddr,false)), key); + if (isAddress(ENSNameOrAddr)) + return this._resolver.getText(await this._resolver.getName(ENSNameOrAddr, false), key); return this._resolver.getText(ENSNameOrAddr, key); } diff --git a/packages/web3-eth-ens/src/resolver.ts b/packages/web3-eth-ens/src/resolver.ts index cb345055d95..d0b4f5f20ea 100644 --- a/packages/web3-eth-ens/src/resolver.ts +++ b/packages/web3-eth-ens/src/resolver.ts @@ -25,7 +25,6 @@ import { interfaceIds, methodsInInterface } from './config.js'; import { Registry } from './registry.js'; import { namehash } from './utils.js'; - // Default public resolver // https://github.com/ensdomains/resolvers/blob/master/contracts/PublicResolver.sol @@ -105,42 +104,28 @@ export class Resolver { return resolverContract.methods.contenthash(namehash(ENSName)).call(); } - public async setAddress( - ENSName: string, - address: Address, - txConfig: PayableCallOptions, - ) { + public async setAddress(ENSName: string, address: Address, txConfig: PayableCallOptions) { const resolverContract = await this.getResolverContractAdapter(ENSName); await this.checkInterfaceSupport(resolverContract, methodsInInterface.setAddr); - return resolverContract.methods - .setAddr(namehash(ENSName), address) - .send(txConfig); + return resolverContract.methods.setAddr(namehash(ENSName), address).send(txConfig); } - public async getText( - ENSName: string, - key: string, - ) { + public async getText(ENSName: string, key: string) { const resolverContract = await this.getResolverContractAdapter(ENSName); await this.checkInterfaceSupport(resolverContract, methodsInInterface.text); - return resolverContract.methods - .text(namehash(ENSName), key).call() + return resolverContract.methods.text(namehash(ENSName), key).call(); } - public async getName( - address: string, - checkInterfaceSupport = true - ) { + public async getName(address: string, checkInterfaceSupport = true) { const reverseName = `${address.toLowerCase().substring(2)}.addr.reverse`; const resolverContract = await this.getResolverContractAdapter(reverseName); - - if(checkInterfaceSupport) + + if (checkInterfaceSupport) await this.checkInterfaceSupport(resolverContract, methodsInInterface.name); - - return resolverContract.methods - .name(namehash(reverseName)).call() + + return resolverContract.methods.name(namehash(reverseName)).call(); } } diff --git a/packages/web3-eth-ens/test/integration/setup.js b/packages/web3-eth-ens/test/integration/setup.js index c480060944a..d527ad558d3 100644 --- a/packages/web3-eth-ens/test/integration/setup.js +++ b/packages/web3-eth-ens/test/integration/setup.js @@ -18,4 +18,3 @@ along with web3.js. If not, see . // Have to use `require` because of Jest issue https://jestjs.io/docs/ecmascript-modules // eslint-disable-next-line @typescript-eslint/no-require-imports require('../config/setup'); - diff --git a/packages/web3-eth-ens/test/unit/ens.test.ts b/packages/web3-eth-ens/test/unit/ens.test.ts index 1c860d72c38..82932a2ff5b 100644 --- a/packages/web3-eth-ens/test/unit/ens.test.ts +++ b/packages/web3-eth-ens/test/unit/ens.test.ts @@ -120,11 +120,7 @@ describe('ens', () => { const sendOptions = { from: mockAddress }; await ens.setAddress(ENS_NAME, mockAddress, sendOptions); - expect(setAddressMock).toHaveBeenCalledWith( - ENS_NAME, - mockAddress, - sendOptions, - ); + expect(setAddressMock).toHaveBeenCalledWith(ENS_NAME, mockAddress, sendOptions); }); it('getAddress', async () => { // eslint-disable-next-line @typescript-eslint/no-empty-function diff --git a/packages/web3-eth-ens/test/unit/resolver.test.ts b/packages/web3-eth-ens/test/unit/resolver.test.ts index da189e5a45d..e3753dfe4e7 100644 --- a/packages/web3-eth-ens/test/unit/resolver.test.ts +++ b/packages/web3-eth-ens/test/unit/resolver.test.ts @@ -219,27 +219,27 @@ describe('resolver', () => { call: async () => Promise.resolve(true), } as unknown as NonPayableMethodObject); - const textMock = jest.spyOn(contract.methods, 'text').mockReturnValue({ - call: jest.fn(), - } as unknown as NonPayableMethodObject); + const textMock = jest.spyOn(contract.methods, 'text').mockReturnValue({ + call: jest.fn(), + } as unknown as NonPayableMethodObject); - jest.spyOn(registry, 'getResolver').mockImplementation(async () => { - return new Promise(resolve => { - resolve(contract); - }); + jest.spyOn(registry, 'getResolver').mockImplementation(async () => { + return new Promise(resolve => { + resolve(contract); }); - - await resolver.getText(ENS_NAME, "key"); - expect(supportsInterfaceMock).toHaveBeenCalledWith( - interfaceIds[methodsInInterface.text], - ); - expect(textMock).toHaveBeenCalledWith(namehash(ENS_NAME), "key"); - }) -}) + }); + + await resolver.getText(ENS_NAME, 'key'); + expect(supportsInterfaceMock).toHaveBeenCalledWith( + interfaceIds[methodsInInterface.text], + ); + expect(textMock).toHaveBeenCalledWith(namehash(ENS_NAME), 'key'); + }); + }); describe('name', () => { it('getName', async () => { - const address = "0x314159265dd8dbb310642f98f50c066173c1259b"; + const address = '0x314159265dd8dbb310642f98f50c066173c1259b'; const supportsInterfaceMock = jest .spyOn(contract.methods, 'supportsInterface') @@ -247,26 +247,25 @@ describe('resolver', () => { call: async () => Promise.resolve(true), } as unknown as NonPayableMethodObject); - const nameMock = jest.spyOn(contract.methods, 'name').mockReturnValue({ - call: jest.fn(), - } as unknown as NonPayableMethodObject); + const nameMock = jest.spyOn(contract.methods, 'name').mockReturnValue({ + call: jest.fn(), + } as unknown as NonPayableMethodObject); - jest.spyOn(registry, 'getResolver').mockImplementation(async () => { - return new Promise(resolve => { - resolve(contract); - }); + jest.spyOn(registry, 'getResolver').mockImplementation(async () => { + return new Promise(resolve => { + resolve(contract); }); - - await resolver.getName(address); - expect(supportsInterfaceMock).toHaveBeenCalledWith( - interfaceIds[methodsInInterface.name], - ); - - const reverseName = `${address.toLowerCase().substring(2)}.addr.reverse`; - expect(nameMock).toHaveBeenCalledWith(namehash(reverseName)); - }) - }) - + }); + + await resolver.getName(address); + expect(supportsInterfaceMock).toHaveBeenCalledWith( + interfaceIds[methodsInInterface.name], + ); + + const reverseName = `${address.toLowerCase().substring(2)}.addr.reverse`; + expect(nameMock).toHaveBeenCalledWith(namehash(reverseName)); + }); + }); describe('supportsInterface', () => { it('check supportsInterface for non strict hex id', async () => { diff --git a/packages/web3-eth-iban/CHANGELOG.md b/packages/web3-eth-iban/CHANGELOG.md index 797f4ffe29f..5904a58763d 100644 --- a/packages/web3-eth-iban/CHANGELOG.md +++ b/packages/web3-eth-iban/CHANGELOG.md @@ -125,4 +125,4 @@ Documentation: - Dependencies updated -## [Unreleased] \ No newline at end of file +## [Unreleased] diff --git a/packages/web3-eth-personal/CHANGELOG.md b/packages/web3-eth-personal/CHANGELOG.md index aba75cae036..33f479b4ef5 100644 --- a/packages/web3-eth-personal/CHANGELOG.md +++ b/packages/web3-eth-personal/CHANGELOG.md @@ -147,4 +147,4 @@ Documentation: - Dependencies updated -## [Unreleased] \ No newline at end of file +## [Unreleased] diff --git a/packages/web3-eth-personal/src/personal.ts b/packages/web3-eth-personal/src/personal.ts index 14bee669d6f..db8d2656703 100644 --- a/packages/web3-eth-personal/src/personal.ts +++ b/packages/web3-eth-personal/src/personal.ts @@ -21,25 +21,25 @@ import { Address, EthPersonalAPI, HexString, Transaction } from 'web3-types'; import * as rpcWrappers from './rpc_method_wrappers.js'; /** -* Eth Personal allows you to interact with the Ethereum node’s accounts. -* For using Eth Personal package, first install Web3 package using: `npm i web3` or `yarn add web3` based on your package manager. -* ```ts -* -*import { Web3 } from 'web3'; -* const web3 = new Web3('http://127.0.0.1:7545'); -* -* console.log(await web3.eth.personal.getAccounts()); -* -* ``` -* For using individual package install `web3-eth-personal` packages using: `npm i web3-eth-personal` or `yarn add web3-eth-personal`. -* -* ```ts -* import {Personal} from 'web3-eth-personal'; -* -* const personal = new Personal('http://127.0.0.1:7545'); -* console.log(await personal.getAccounts()); -* ``` -*/ + * Eth Personal allows you to interact with the Ethereum node’s accounts. + * For using Eth Personal package, first install Web3 package using: `npm i web3` or `yarn add web3` based on your package manager. + * ```ts + * + *import { Web3 } from 'web3'; + * const web3 = new Web3('http://127.0.0.1:7545'); + * + * console.log(await web3.eth.personal.getAccounts()); + * + * ``` + * For using individual package install `web3-eth-personal` packages using: `npm i web3-eth-personal` or `yarn add web3-eth-personal`. + * + * ```ts + * import {Personal} from 'web3-eth-personal'; + * + * const personal = new Personal('http://127.0.0.1:7545'); + * console.log(await personal.getAccounts()); + * ``` + */ export class Personal extends Web3Context { /** *Returns a list of accounts the node controls by using the provider and calling the RPC method personal_listAccounts. Using `web3.eth.accounts.create()` will not add accounts into this list. For that use `web3.eth.personal.newAccount()`. diff --git a/packages/web3-eth-personal/test/integration/personal.test.ts b/packages/web3-eth-personal/test/integration/personal.test.ts index d650bdc6e8b..27c0e33c2f7 100644 --- a/packages/web3-eth-personal/test/integration/personal.test.ts +++ b/packages/web3-eth-personal/test/integration/personal.test.ts @@ -27,7 +27,7 @@ import { getSystemTestProvider, itIf, describeIf, - BACKEND + BACKEND, } from '../fixtures/system_test_utils'; // hardhat does not support personal diff --git a/packages/web3-eth/CHANGELOG.md b/packages/web3-eth/CHANGELOG.md index 6be4b4b5797..9005985b2b2 100644 --- a/packages/web3-eth/CHANGELOG.md +++ b/packages/web3-eth/CHANGELOG.md @@ -254,7 +254,7 @@ Documentation: - `sendTransaction` in `rpc_method_wrappers` accepts optional param of `TransactionMiddleware` (#7088) - WebEth has `setTransactionMiddleware` and `getTransactionMiddleware` for automatically passing to `sentTransaction` (#7088) -- `TransactionMiddleware` and `TransactionMiddleware` data types are exported (#7088) +- `TransactionMiddleware` and `TransactionMiddleware` data types are exported (#7088) ## [4.8.1] @@ -269,4 +269,4 @@ Documentation: - Adds transaction property to be an empty list rather than undefined when no transactions are included in the block (#7151) - Change method `getTransactionReceipt` to not be casted as `TransactionReceipt` to give proper return type (#7159) -## [Unreleased] \ No newline at end of file +## [Unreleased] diff --git a/packages/web3-eth/src/rpc_method_wrappers.ts b/packages/web3-eth/src/rpc_method_wrappers.ts index 02fb9fbb173..e5ffe9baf64 100644 --- a/packages/web3-eth/src/rpc_method_wrappers.ts +++ b/packages/web3-eth/src/rpc_method_wrappers.ts @@ -296,10 +296,10 @@ export async function getBlock( const result = { ...res, transactions: res.transactions ?? [], - } + }; return result; } - + return res; } @@ -508,26 +508,30 @@ export async function getTransactionReceipt( ); let response; try { - response = await ethRpcMethods.getTransactionReceipt( + response = await ethRpcMethods.getTransactionReceipt( web3Context.requestManager, transactionHashFormatted, ); } catch (error) { // geth indexing error, we poll until transactions stopped indexing - if (typeof error === 'object' && !isNullish(error) && 'message' in error && (error as { message: string }).message === 'transaction indexing is in progress') { - console.warn('Transaction indexing is in progress.') + if ( + typeof error === 'object' && + !isNullish(error) && + 'message' in error && + (error as { message: string }).message === 'transaction indexing is in progress' + ) { + console.warn('Transaction indexing is in progress.'); } else { throw error; } - } return isNullish(response) ? response - : (format( + : format( transactionReceiptSchema, response as unknown as TransactionReceipt, returnFormat ?? web3Context.defaultReturnFormat, - )); + ); } /** @@ -572,7 +576,7 @@ export function sendTransaction< | TransactionWithFromAndToLocalWalletIndex, returnFormat: ReturnFormat, options: SendTransactionOptions = { checkRevertBeforeSending: true }, - transactionMiddleware?: TransactionMiddleware + transactionMiddleware?: TransactionMiddleware, ): Web3PromiEvent> { const promiEvent = new Web3PromiEvent>( (resolve, reject) => { @@ -585,9 +589,9 @@ export function sendTransaction< returnFormat, }); - let transaction = {...transactionObj}; - - if(!isNullish(transactionMiddleware)){ + let transaction = { ...transactionObj }; + + if (!isNullish(transactionMiddleware)) { transaction = await transactionMiddleware.processTransaction(transaction); } diff --git a/packages/web3-eth/src/schemas.ts b/packages/web3-eth/src/schemas.ts index 244e1260b53..e27140cdcf3 100644 --- a/packages/web3-eth/src/schemas.ts +++ b/packages/web3-eth/src/schemas.ts @@ -257,10 +257,10 @@ export const withdrawalsSchema = { export const blockSchema = { type: 'object', properties: { - baseFeePerGas: { + baseFeePerGas: { format: 'uint', }, - blobGasUsed: { + blobGasUsed: { format: 'uint', }, difficulty: { @@ -345,13 +345,13 @@ export const blockSchema = { format: 'bytes32', }, }, - withdrawals: { + withdrawals: { type: 'array', items: { ...withdrawalsSchema, }, }, - withdrawalsRoot: { + withdrawalsRoot: { format: 'bytes32', }, }, @@ -360,16 +360,16 @@ export const blockSchema = { export const blockHeaderSchema = { type: 'object', properties: { - author: { + author: { format: 'bytes32', }, - excessDataGas: { + excessDataGas: { format: 'uint', }, - baseFeePerGas: { + baseFeePerGas: { format: 'uint', }, - blobGasUsed: { + blobGasUsed: { format: 'uint', }, difficulty: { @@ -444,13 +444,13 @@ export const blockHeaderSchema = { format: 'bytes32', }, }, - withdrawals: { + withdrawals: { type: 'array', items: { ...withdrawalsSchema, }, }, - withdrawalsRoot: { + withdrawalsRoot: { format: 'bytes32', }, }, diff --git a/packages/web3-eth/src/types.ts b/packages/web3-eth/src/types.ts index 9ed49badb39..9f9de0ec14a 100644 --- a/packages/web3-eth/src/types.ts +++ b/packages/web3-eth/src/types.ts @@ -92,16 +92,16 @@ export interface RevertReasonWithCustomError extends RevertReason { customErrorArguments: Record; } -export type TransactionMiddlewareData = Transaction -| TransactionWithFromLocalWalletIndex -| TransactionWithToLocalWalletIndex -| TransactionWithFromAndToLocalWalletIndex; +export type TransactionMiddlewareData = + | Transaction + | TransactionWithFromLocalWalletIndex + | TransactionWithToLocalWalletIndex + | TransactionWithFromAndToLocalWalletIndex; -export interface TransactionMiddleware{ +export interface TransactionMiddleware { // for transaction processing before signing processTransaction( - transaction: TransactionMiddlewareData, + transaction: TransactionMiddlewareData, options?: { [key: string]: unknown }, ): Promise; - -} \ No newline at end of file +} diff --git a/packages/web3-eth/src/utils/detect_transaction_type.ts b/packages/web3-eth/src/utils/detect_transaction_type.ts index ec5539b375a..171a7597f3d 100644 --- a/packages/web3-eth/src/utils/detect_transaction_type.ts +++ b/packages/web3-eth/src/utils/detect_transaction_type.ts @@ -75,9 +75,7 @@ const validateTxTypeAndHandleErrors = ( } }; -export const defaultTransactionTypeParser: TransactionTypeParser = ( - transaction -) => { +export const defaultTransactionTypeParser: TransactionTypeParser = transaction => { const tx = transaction as unknown as Transaction; if (!isNullish(tx.type)) { let txSchema; @@ -139,7 +137,7 @@ export const detectTransactionType = ( web3Context?: Web3Context, ) => (web3Context?.transactionTypeParser ?? defaultTransactionTypeParser)( - transaction as unknown as Record + transaction as unknown as Record, ); export const detectRawTransactionType = (transaction: Uint8Array) => diff --git a/packages/web3-eth/src/utils/prepare_transaction_for_signing.ts b/packages/web3-eth/src/utils/prepare_transaction_for_signing.ts index fe761ada1f6..5213e66c778 100644 --- a/packages/web3-eth/src/utils/prepare_transaction_for_signing.ts +++ b/packages/web3-eth/src/utils/prepare_transaction_for_signing.ts @@ -141,7 +141,7 @@ export const prepareTransactionForSigning = async ( validateTransactionForSigning( formattedTransaction as unknown as FormatType, ); - + return TransactionFactory.fromTxData( getEthereumjsTxDataFromTransaction(formattedTransaction), getEthereumjsTransactionOptions(formattedTransaction, web3Context), diff --git a/packages/web3-eth/src/utils/reject_if_block_timeout.ts b/packages/web3-eth/src/utils/reject_if_block_timeout.ts index 2019ce3380d..e3563ca2a1a 100644 --- a/packages/web3-eth/src/utils/reject_if_block_timeout.ts +++ b/packages/web3-eth/src/utils/reject_if_block_timeout.ts @@ -34,25 +34,24 @@ function resolveByPolling( transactionHash?: Bytes, ): [Promise, ResourceCleaner] { const pollingInterval = web3Context.transactionPollingInterval; - const [intervalId, promiseToError] = - rejectIfConditionAtInterval(async () => { - let lastBlockNumber; - try { - lastBlockNumber = await getBlockNumber(web3Context, NUMBER_DATA_FORMAT); - } catch (error) { - console.warn('An error happen while trying to get the block number', error); - return undefined; - } - const numberOfBlocks = lastBlockNumber - starterBlockNumber; - if (numberOfBlocks >= web3Context.transactionBlockTimeout) { - return new TransactionBlockTimeoutError({ - starterBlockNumber, - numberOfBlocks, - transactionHash, - }); - } + const [intervalId, promiseToError] = rejectIfConditionAtInterval(async () => { + let lastBlockNumber; + try { + lastBlockNumber = await getBlockNumber(web3Context, NUMBER_DATA_FORMAT); + } catch (error) { + console.warn('An error happen while trying to get the block number', error); return undefined; - }, pollingInterval); + } + const numberOfBlocks = lastBlockNumber - starterBlockNumber; + if (numberOfBlocks >= web3Context.transactionBlockTimeout) { + return new TransactionBlockTimeoutError({ + starterBlockNumber, + numberOfBlocks, + transactionHash, + }); + } + return undefined; + }, pollingInterval); const clean = () => { clearInterval(intervalId); diff --git a/packages/web3-eth/src/utils/send_tx_helper.ts b/packages/web3-eth/src/utils/send_tx_helper.ts index 0037e1051fa..fbe48c0e868 100644 --- a/packages/web3-eth/src/utils/send_tx_helper.ts +++ b/packages/web3-eth/src/utils/send_tx_helper.ts @@ -123,13 +123,18 @@ export class SendTxHelper< public async checkRevertBeforeSending(tx: TransactionCall) { if (this.options.checkRevertBeforeSending !== false) { 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 + 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 - } + gas: 21000, + }; } - const reason = await getRevertReason(this.web3Context, formatTx, this.options.contractAbi); + const reason = await getRevertReason( + this.web3Context, + formatTx, + this.options.contractAbi, + ); if (reason !== undefined) { throw await getTransactionError( this.web3Context, 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 a429eabb818..3c249c8298a 100644 --- a/packages/web3-eth/src/utils/watch_transaction_by_polling.ts +++ b/packages/web3-eth/src/utils/watch_transaction_by_polling.ts @@ -56,7 +56,7 @@ export const watchTransactionByPolling = < let confirmations = 1; const intervalId = setInterval(() => { (async () => { - if (confirmations >= web3Context.transactionConfirmationBlocks){ + if (confirmations >= web3Context.transactionConfirmationBlocks) { clearInterval(intervalId); return; } diff --git a/packages/web3-eth/src/web3_eth.ts b/packages/web3-eth/src/web3_eth.ts index abce5c2c317..a9db13d5abb 100644 --- a/packages/web3-eth/src/web3_eth.ts +++ b/packages/web3-eth/src/web3_eth.ts @@ -99,7 +99,6 @@ export const registeredSubscriptions = { * ``` */ export class Web3Eth extends Web3Context { - private transactionMiddleware?: TransactionMiddleware; public constructor( @@ -129,11 +128,11 @@ export class Web3Eth extends Web3Context { if (process.env.TEST_ACCOUNT_ADDRESS !== undefined) { return process.env.TEST_ACCOUNT_ADDRESS; // eslint-disable-next-line no-else-return - } else if (getSystemTestBackend() === BACKEND.SEPOLIA || getSystemTestBackend() === BACKEND.MAINNET) { + } else if ( + getSystemTestBackend() === BACKEND.SEPOLIA || + getSystemTestBackend() === BACKEND.MAINNET + ) { return secrets[getSystemTestBackend().toUpperCase() as 'SEPOLIA' | 'MAINNET'].ACCOUNT .address; } @@ -64,7 +67,10 @@ export const getAllowedSendTransaction = (): boolean => { return Boolean(process.env.ALLOWED_SEND_TRANSACTION); // eslint-disable-next-line no-else-return - } else if (getSystemTestBackend() === BACKEND.SEPOLIA || getSystemTestBackend() === BACKEND.MAINNET) { + } else if ( + getSystemTestBackend() === BACKEND.SEPOLIA || + getSystemTestBackend() === BACKEND.MAINNET + ) { return secrets[getSystemTestBackend().toUpperCase() as 'SEPOLIA' | 'MAINNET'] .ALLOWED_SEND_TRANSACTION; } @@ -76,7 +82,10 @@ export const getE2ETestAccountPrivateKey = (): string => { if (process.env.TEST_ACCOUNT_PRIVATE_KEY !== undefined) { return process.env.TEST_ACCOUNT_PRIVATE_KEY; // eslint-disable-next-line no-else-return - } else if (getSystemTestBackend() === BACKEND.SEPOLIA || getSystemTestBackend() === BACKEND.MAINNET) { + } else if ( + getSystemTestBackend() === BACKEND.SEPOLIA || + getSystemTestBackend() === BACKEND.MAINNET + ) { return secrets[getSystemTestBackend().toUpperCase() as 'SEPOLIA' | 'MAINNET'].ACCOUNT .privateKey; } diff --git a/packages/web3-eth/test/e2e/setup.js b/packages/web3-eth/test/e2e/setup.js index c480060944a..d527ad558d3 100644 --- a/packages/web3-eth/test/e2e/setup.js +++ b/packages/web3-eth/test/e2e/setup.js @@ -18,4 +18,3 @@ along with web3.js. If not, see . // Have to use `require` because of Jest issue https://jestjs.io/docs/ecmascript-modules // eslint-disable-next-line @typescript-eslint/no-require-imports require('../config/setup'); - diff --git a/packages/web3-eth/test/fixtures/transactions_data.ts b/packages/web3-eth/test/fixtures/transactions_data.ts index 189e2135ae4..5daf37d9bb9 100644 --- a/packages/web3-eth/test/fixtures/transactions_data.ts +++ b/packages/web3-eth/test/fixtures/transactions_data.ts @@ -16,102 +16,104 @@ along with web3.js. If not, see . */ export const blockMockResult = { - "jsonrpc": "2.0", - "id": "a40a81fa-1f8b-4bb2-a0ad-eef9b6d4636f", - "result": { - "baseFeePerGas": "0x44dab2983", - "blobGasUsed": "0x20000", - "difficulty": "0x0", - "excessBlobGas": "0x1c0000", - "extraData": "0x407273796e636275696c646572", - "gasLimit": "0x1c9c380", - "gasUsed": "0xb7a086", - "hash": "0xf2b1729965179032b17165678a1a212fa31cb008e30f4011ffe8ebdddbd02b95", - "logsBloom": "0xc3a70590c1c62524173d1892e33888067101934dc0891c2c9a898252b6f320215084a48906452960820188d32bba6fb82ec989018a0268603a00a4c6432a11276c9a038c676938eb68bc436c9905a9a1b08d238fb4458f48498215808bec81112e2a3a54869ff22422a8e491093da8a40f601d198417041cd22f799f9048865006e0b069ab049b852442b310396248088145e2810f230f9a44000c6868bc73e9afa8832a8ac92fd609007ac53c0a9cba0645ce298080184624e8040831dbc331f5e618072407050250021b3210e542781183a612d4618c1244000d421a6ca9c01a57e86a085402c55ab413f840a001e7117894d0469e20c2304a9655e344f60d", - "miner": "0x1f9090aae28b8a3dceadf281b0f12828e676c326", - "mixHash": "0x787ab1d511b72df60a705bb4cfc4e92e2f9d203e3e007ae3a0f757425951ca24", - "nonce": "0x0000000000000000", - "number": "0x131ad16", - "parentBeaconBlockRoot": "0x03bbca9fd0c7a0a020de04287f489112c79bc268220e9ff8e18957cd0d5c3cad", - "parentHash": "0xb1d8fa7b8346421d373a6d4c28575155516cea17c12a3df7201170c9e561b38c", - "receiptsRoot": "0x4ec500bdcd761ad505b2a989156c9a9628058d415acc93d800487c7c76308c59", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0xcb90", - "stateRoot": "0xafbb8743c0a5f4740e322217cb1f2780ee5c57c32bcd04e9256b09efc1a70568", - "timestamp": "0x6661ab8b", - "totalDifficulty": "0xc70d815d562d3cfa955", - "transactions": [ - "0x589956b75d19dbaf9911f246c23d4b3327ef234872ec1931c419041b23eb5b41", - "0x4d3793f20c25979bd329cafdd889ba6be015cfc999acce8642d6e757b5192e93", - "0x5ba5618ca5a14bab50862255dc69726a498346f9832bd0fd1394e8834e56790b", - "0x6df9678f350db7e30afc930b7246bf1c144b9acb7fd1d25d7e107d550ed5a061", - "0xb8f48ff2876cc393725ea4162421754dfb74ff2364a12d4d3de2c6269f1958c7", - "0x2e5cf7c0607025038b6ccd871dc9ce85af686fd5fa2c82e605198af9afa92cca", - "0x307fb855836feff5d8d0969fa4a44d3c6ae31d335da6577f48f9496d6fe9e0b9", - "0x1362bed1aa8a30d28b7b76c35c2a8601b257058beffa9490dcb20de12bcb15b2", - "0x234c7cc346c204022b2e5ead6d2e8c02317aeb0ec5ca82bd97c2b5d5e59a280b", - ], - "transactionsRoot": "0xc21a4d667b5f841538430b1e2c002c598f2178628ad1d61ea2fda462d1216607", - "uncles": [], - "withdrawals": [ - { - "address": "0xea97dc2523c0479484076660f150833e264c41e9", - "amount": "0x11b6d8c", - "index": "0x2dbe454", - "validatorIndex": "0x10f646" - }, - { - "address": "0xb3e84b6c6409826dc45432b655d8c9489a14a0d7", - "amount": "0x11b4ce2", - "index": "0x2dbe455", - "validatorIndex": "0x10f647" - }, - { - "address": "0x7e2a2fa2a064f693f0a55c5639476d913ff12d05", - "amount": "0x11ad733", - "index": "0x2dbe456", - "validatorIndex": "0x10f648" - }, - - ], - "withdrawalsRoot": "0x2914fa2f5ed93880ed45b58e8f6d14f20c645988400d83c59109964e2053fe1a" - } + jsonrpc: '2.0', + id: 'a40a81fa-1f8b-4bb2-a0ad-eef9b6d4636f', + result: { + baseFeePerGas: '0x44dab2983', + blobGasUsed: '0x20000', + difficulty: '0x0', + excessBlobGas: '0x1c0000', + extraData: '0x407273796e636275696c646572', + gasLimit: '0x1c9c380', + gasUsed: '0xb7a086', + hash: '0xf2b1729965179032b17165678a1a212fa31cb008e30f4011ffe8ebdddbd02b95', + logsBloom: + '0xc3a70590c1c62524173d1892e33888067101934dc0891c2c9a898252b6f320215084a48906452960820188d32bba6fb82ec989018a0268603a00a4c6432a11276c9a038c676938eb68bc436c9905a9a1b08d238fb4458f48498215808bec81112e2a3a54869ff22422a8e491093da8a40f601d198417041cd22f799f9048865006e0b069ab049b852442b310396248088145e2810f230f9a44000c6868bc73e9afa8832a8ac92fd609007ac53c0a9cba0645ce298080184624e8040831dbc331f5e618072407050250021b3210e542781183a612d4618c1244000d421a6ca9c01a57e86a085402c55ab413f840a001e7117894d0469e20c2304a9655e344f60d', + miner: '0x1f9090aae28b8a3dceadf281b0f12828e676c326', + mixHash: '0x787ab1d511b72df60a705bb4cfc4e92e2f9d203e3e007ae3a0f757425951ca24', + nonce: '0x0000000000000000', + number: '0x131ad16', + parentBeaconBlockRoot: '0x03bbca9fd0c7a0a020de04287f489112c79bc268220e9ff8e18957cd0d5c3cad', + parentHash: '0xb1d8fa7b8346421d373a6d4c28575155516cea17c12a3df7201170c9e561b38c', + receiptsRoot: '0x4ec500bdcd761ad505b2a989156c9a9628058d415acc93d800487c7c76308c59', + sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347', + size: '0xcb90', + stateRoot: '0xafbb8743c0a5f4740e322217cb1f2780ee5c57c32bcd04e9256b09efc1a70568', + timestamp: '0x6661ab8b', + totalDifficulty: '0xc70d815d562d3cfa955', + transactions: [ + '0x589956b75d19dbaf9911f246c23d4b3327ef234872ec1931c419041b23eb5b41', + '0x4d3793f20c25979bd329cafdd889ba6be015cfc999acce8642d6e757b5192e93', + '0x5ba5618ca5a14bab50862255dc69726a498346f9832bd0fd1394e8834e56790b', + '0x6df9678f350db7e30afc930b7246bf1c144b9acb7fd1d25d7e107d550ed5a061', + '0xb8f48ff2876cc393725ea4162421754dfb74ff2364a12d4d3de2c6269f1958c7', + '0x2e5cf7c0607025038b6ccd871dc9ce85af686fd5fa2c82e605198af9afa92cca', + '0x307fb855836feff5d8d0969fa4a44d3c6ae31d335da6577f48f9496d6fe9e0b9', + '0x1362bed1aa8a30d28b7b76c35c2a8601b257058beffa9490dcb20de12bcb15b2', + '0x234c7cc346c204022b2e5ead6d2e8c02317aeb0ec5ca82bd97c2b5d5e59a280b', + ], + transactionsRoot: '0xc21a4d667b5f841538430b1e2c002c598f2178628ad1d61ea2fda462d1216607', + uncles: [], + withdrawals: [ + { + address: '0xea97dc2523c0479484076660f150833e264c41e9', + amount: '0x11b6d8c', + index: '0x2dbe454', + validatorIndex: '0x10f646', + }, + { + address: '0xb3e84b6c6409826dc45432b655d8c9489a14a0d7', + amount: '0x11b4ce2', + index: '0x2dbe455', + validatorIndex: '0x10f647', + }, + { + address: '0x7e2a2fa2a064f693f0a55c5639476d913ff12d05', + amount: '0x11ad733', + index: '0x2dbe456', + validatorIndex: '0x10f648', + }, + ], + withdrawalsRoot: '0x2914fa2f5ed93880ed45b58e8f6d14f20c645988400d83c59109964e2053fe1a', + }, }; export const receiptMockResult = { - "jsonrpc": "2.0", - "id": 1, - "result": { - "blockHash": "0xf4ad699b98241caf3930779b7d919a77f1727e67cef6ed1ce2a4c655ba812d54", - "blockNumber": "0x131ad35", - // eslint-disable-next-line no-null/no-null - "contractAddress": null, - "cumulativeGasUsed": "0x8cae7a", - "effectiveGasPrice": "0x4c9bc2d65", - "from": "0xab6fd3a7c6ce9db945889cd018e028e055f3bc2e", - "gasUsed": "0xa145", - "logs": [ - { - "address": "0xdac17f958d2ee523a2206206994597c13d831ec7", - "blockHash": "0xf4ad699b98241caf3930779b7d919a77f1727e67cef6ed1ce2a4c655ba812d54", - "blockNumber": "0x131ad35", - "data": "0x000000000000000000000000000000000000000000000000000000000016e360", - "logIndex": "0xdf", - "removed": false, - "topics": [ - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x000000000000000000000000ab6fd3a7c6ce9db945889cd018e028e055f3bc2e", - "0x00000000000000000000000051112f9f08a2174fe3fc96aad8f07e82d1cccd00" - ], - "transactionHash": "0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f", - "transactionIndex": "0x82" - } - ], - "logsBloom": "0x00000000000000000000000002000000000000000000000000000000004000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000400000000000100000000000000000000000000080000000000000000000040000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000400000000000000000000000", - "status": "0x1", - "to": "0xdac17f958d2ee523a2206206994597c13d831ec7", - "transactionHash": "0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f", - "transactionIndex": "0x82", - "type": "0x2" - } -}; \ No newline at end of file + jsonrpc: '2.0', + id: 1, + result: { + blockHash: '0xf4ad699b98241caf3930779b7d919a77f1727e67cef6ed1ce2a4c655ba812d54', + blockNumber: '0x131ad35', + // eslint-disable-next-line no-null/no-null + contractAddress: null, + cumulativeGasUsed: '0x8cae7a', + effectiveGasPrice: '0x4c9bc2d65', + from: '0xab6fd3a7c6ce9db945889cd018e028e055f3bc2e', + gasUsed: '0xa145', + logs: [ + { + address: '0xdac17f958d2ee523a2206206994597c13d831ec7', + blockHash: '0xf4ad699b98241caf3930779b7d919a77f1727e67cef6ed1ce2a4c655ba812d54', + blockNumber: '0x131ad35', + data: '0x000000000000000000000000000000000000000000000000000000000016e360', + logIndex: '0xdf', + removed: false, + topics: [ + '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', + '0x000000000000000000000000ab6fd3a7c6ce9db945889cd018e028e055f3bc2e', + '0x00000000000000000000000051112f9f08a2174fe3fc96aad8f07e82d1cccd00', + ], + transactionHash: + '0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f', + transactionIndex: '0x82', + }, + ], + logsBloom: + '0x00000000000000000000000002000000000000000000000000000000004000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000400000000000100000000000000000000000000080000000000000000000040000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000400000000000000000000000', + status: '0x1', + to: '0xdac17f958d2ee523a2206206994597c13d831ec7', + transactionHash: '0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f', + transactionIndex: '0x82', + type: '0x2', + }, +}; diff --git a/packages/web3-eth/test/integration/block/rpc.getBlock.test.ts b/packages/web3-eth/test/integration/block/rpc.getBlock.test.ts index 50731193bcc..77b1b5742d2 100644 --- a/packages/web3-eth/test/integration/block/rpc.getBlock.test.ts +++ b/packages/web3-eth/test/integration/block/rpc.getBlock.test.ts @@ -33,7 +33,7 @@ import { describeIf, createNewAccount, refillAccount, - BACKEND + BACKEND, } from '../../fixtures/system_test_utils'; import { BasicAbi, BasicBytecode } from '../../shared_fixtures/build/Basic'; import { toAllVariants } from '../../shared_fixtures/utils'; diff --git a/packages/web3-eth/test/integration/block/rpc.getBlockTransactionCount.test.ts b/packages/web3-eth/test/integration/block/rpc.getBlockTransactionCount.test.ts index ce4ad2e26a1..ece1091e937 100644 --- a/packages/web3-eth/test/integration/block/rpc.getBlockTransactionCount.test.ts +++ b/packages/web3-eth/test/integration/block/rpc.getBlockTransactionCount.test.ts @@ -99,7 +99,7 @@ describe('rpc with block', () => { )('getBlockTransactionCount', async ({ block }) => { const res = await web3Eth.getBlockTransactionCount(blockData[block]); const shouldBe = ['earliest', 'pending'].includes(String(blockData[block])) ? 0 : 1; - + expect(Number(res)).toBe(shouldBe); }); }); diff --git a/packages/web3-eth/test/integration/block/rpc.getBlockUncleCount.test.ts b/packages/web3-eth/test/integration/block/rpc.getBlockUncleCount.test.ts index ae822a99a5a..a777eee29c5 100644 --- a/packages/web3-eth/test/integration/block/rpc.getBlockUncleCount.test.ts +++ b/packages/web3-eth/test/integration/block/rpc.getBlockUncleCount.test.ts @@ -24,7 +24,7 @@ import { closeOpenConnection, describeIf, getSystemTestBackend, - BACKEND + BACKEND, } from '../../fixtures/system_test_utils'; import { BasicAbi, BasicBytecode } from '../../shared_fixtures/build/Basic'; import { toAllVariants } from '../../shared_fixtures/utils'; diff --git a/packages/web3-eth/test/integration/block/rpc.getUncle.test.ts b/packages/web3-eth/test/integration/block/rpc.getUncle.test.ts index 9b820fd9077..07882d8524a 100644 --- a/packages/web3-eth/test/integration/block/rpc.getUncle.test.ts +++ b/packages/web3-eth/test/integration/block/rpc.getUncle.test.ts @@ -26,7 +26,7 @@ import { closeOpenConnection, describeIf, getSystemTestBackend, - BACKEND + BACKEND, } from '../../fixtures/system_test_utils'; import { BasicAbi, BasicBytecode } from '../../shared_fixtures/build/Basic'; import { toAllVariants } from '../../shared_fixtures/utils'; diff --git a/packages/web3-eth/test/integration/defaults.test.ts b/packages/web3-eth/test/integration/defaults.test.ts index 351152158b4..b52934e386a 100644 --- a/packages/web3-eth/test/integration/defaults.test.ts +++ b/packages/web3-eth/test/integration/defaults.test.ts @@ -41,7 +41,7 @@ import { getSystemTestProvider, isIpc, sendFewSampleTxs, - waitForCondition + waitForCondition, } from '../fixtures/system_test_utils'; import { @@ -78,83 +78,72 @@ describe('defaults', () => { await closeOpenConnection(web3Eth); await closeOpenConnection(contract); }); - it('defaultAccount', async () => { - const tempAcc2 = await createTempAccount(); - const tempAcc3 = await createTempAccount(); - const contractMsgFrom = await new Contract( - MsgSenderAbi, - web3Eth.getContextObject() as any, - ) - .deploy({ - data: MsgSenderBytecode, - arguments: ['test'], - }) - .send({ from: tempAcc2.address, gas: '2700000' }); - // default - expect(web3Eth.defaultAccount).toBeUndefined(); - - // after set - web3Eth.setConfig({ - defaultAccount: tempAcc.address, - }); - expect(web3Eth.defaultAccount).toBe(tempAcc.address); + it('defaultAccount', async () => { + const tempAcc2 = await createTempAccount(); + const tempAcc3 = await createTempAccount(); + const contractMsgFrom = await new Contract(MsgSenderAbi, web3Eth.getContextObject() as any) + .deploy({ + data: MsgSenderBytecode, + arguments: ['test'], + }) + .send({ from: tempAcc2.address, gas: '2700000' }); + // default + expect(web3Eth.defaultAccount).toBeUndefined(); + + // after set + web3Eth.setConfig({ + defaultAccount: tempAcc.address, + }); + expect(web3Eth.defaultAccount).toBe(tempAcc.address); - // set by create new instance - const eth2 = new Web3Eth({ - config: { - defaultAccount: tempAcc3.address, - }, - }); - expect(eth2.defaultAccount).toBe(tempAcc3.address); - - // check utils - expect(getTransactionFromOrToAttr('from', eth2)).toBe(tempAcc3.address); - // TODO: after handleRevert implementation https://github.com/ChainSafe/web3.js/issues/5069 add following tests in future release - // set handleRevert true and test following functions with invalid input tx data and see revert reason present in error details: - contractMsgFrom.setConfig({ - defaultAccount: tempAcc.address, - }); + // set by create new instance + const eth2 = new Web3Eth({ + config: { + defaultAccount: tempAcc3.address, + }, + }); + expect(eth2.defaultAccount).toBe(tempAcc3.address); + + // check utils + expect(getTransactionFromOrToAttr('from', eth2)).toBe(tempAcc3.address); + // TODO: after handleRevert implementation https://github.com/ChainSafe/web3.js/issues/5069 add following tests in future release + // set handleRevert true and test following functions with invalid input tx data and see revert reason present in error details: + contractMsgFrom.setConfig({ + defaultAccount: tempAcc.address, + }); - const tx = await contractMsgFrom.methods - .setTestString('test2') - .send({ gas: '1000000' }); - const txSend = await web3Eth.sendTransaction({ - to: tempAcc2.address, - value: '0x1', - }); - expect(tx.from).toBe(tempAcc.address.toLowerCase()); - expect(txSend.from).toBe(tempAcc.address.toLowerCase()); + const tx = await contractMsgFrom.methods.setTestString('test2').send({ gas: '1000000' }); + const txSend = await web3Eth.sendTransaction({ + to: tempAcc2.address, + value: '0x1', + }); + expect(tx.from).toBe(tempAcc.address.toLowerCase()); + expect(txSend.from).toBe(tempAcc.address.toLowerCase()); - const tx2 = await contractMsgFrom.methods.setTestString('test3').send({ - from: tempAcc2.address, - }); - const tx2Send = await web3Eth.sendTransaction({ - to: tempAcc.address, - value: '0x1', - from: tempAcc2.address, - }); - expect(tx2.from).toBe(tempAcc2.address.toLowerCase()); - expect(tx2Send.from).toBe(tempAcc2.address.toLowerCase()); - - const fromDefault = await contractMsgFrom.methods?.from().call(); - const fromPass = await contractMsgFrom.methods?.from().call({ from: tempAcc.address }); - const fromPass2 = await contractMsgFrom.methods - ?.from() - .call({ from: tempAcc2.address }); - expect((fromDefault as unknown as string).toLowerCase()).toBe( - tempAcc.address.toLowerCase(), - ); - expect((fromPass as unknown as string).toLowerCase()).toBe( - tempAcc.address.toLowerCase(), - ); - expect((fromPass2 as unknown as string).toLowerCase()).toBe( - tempAcc2.address.toLowerCase(), - ); - await closeOpenConnection(eth2); - await closeOpenConnection(contractMsgFrom); + const tx2 = await contractMsgFrom.methods.setTestString('test3').send({ + from: tempAcc2.address, + }); + const tx2Send = await web3Eth.sendTransaction({ + to: tempAcc.address, + value: '0x1', + from: tempAcc2.address, }); - it('handleRevert', () => { - /* + expect(tx2.from).toBe(tempAcc2.address.toLowerCase()); + expect(tx2Send.from).toBe(tempAcc2.address.toLowerCase()); + + const fromDefault = await contractMsgFrom.methods?.from().call(); + const fromPass = await contractMsgFrom.methods?.from().call({ from: tempAcc.address }); + const fromPass2 = await contractMsgFrom.methods?.from().call({ from: tempAcc2.address }); + expect((fromDefault as unknown as string).toLowerCase()).toBe( + tempAcc.address.toLowerCase(), + ); + expect((fromPass as unknown as string).toLowerCase()).toBe(tempAcc.address.toLowerCase()); + expect((fromPass2 as unknown as string).toLowerCase()).toBe(tempAcc2.address.toLowerCase()); + await closeOpenConnection(eth2); + await closeOpenConnection(contractMsgFrom); + }); + it('handleRevert', () => { + /* //TO DO: after handleRevert implementation https://github.com/ChainSafe/web3.js/issues/5069 add following tests in future release /* set handleRevert true and test following functions with invalid input tx data and see revert reason present in error details: @@ -164,907 +153,908 @@ describe('defaults', () => { contract.methods.myMethod(…).call(…) */ - // default - expect(web3Eth.handleRevert).toBe(false); + // default + expect(web3Eth.handleRevert).toBe(false); - // after set - web3Eth.setConfig({ + // after set + web3Eth.setConfig({ + handleRevert: true, + }); + expect(web3Eth.handleRevert).toBe(true); + + // set by create new instance + const eth2 = new Web3Eth({ + config: { handleRevert: true, - }); - expect(web3Eth.handleRevert).toBe(true); + }, + }); + expect(eth2.handleRevert).toBe(true); + }); + it('defaultBlock', async () => { + const contractDeployed = await contract.deploy(deployOptions).send(sendOptions); + // default + expect(web3Eth.defaultBlock).toBe('latest'); - // set by create new instance - const eth2 = new Web3Eth({ - config: { - handleRevert: true, - }, - }); - expect(eth2.handleRevert).toBe(true); + web3Eth.setConfig({ + defaultBlock: 'safe', }); - it('defaultBlock', async () => { - const contractDeployed = await contract.deploy(deployOptions).send(sendOptions); - // default - expect(web3Eth.defaultBlock).toBe('latest'); + expect(web3Eth.defaultBlock).toBe('safe'); - web3Eth.setConfig({ - defaultBlock: 'safe', - }); - expect(web3Eth.defaultBlock).toBe('safe'); + web3Eth.setConfig({ + defaultBlock: 'finalized', + }); + expect(web3Eth.defaultBlock).toBe('finalized'); - web3Eth.setConfig({ - defaultBlock: 'finalized', - }); - expect(web3Eth.defaultBlock).toBe('finalized'); + // after set + web3Eth.setConfig({ + defaultBlock: 'earliest', + }); + expect(web3Eth.defaultBlock).toBe('earliest'); - // after set - web3Eth.setConfig({ + // set by create new instance + const eth2 = new Web3Eth({ + provider: web3Eth.provider, + config: { defaultBlock: 'earliest', - }); - expect(web3Eth.defaultBlock).toBe('earliest'); - - // set by create new instance - const eth2 = new Web3Eth({ - provider: web3Eth.provider, - config: { - defaultBlock: 'earliest', - }, - }); - expect(eth2.defaultBlock).toBe('earliest'); + }, + }); + expect(eth2.defaultBlock).toBe('earliest'); - // check implementation - const acc = await createNewAccount({ refill: true, unlock: true }); + // check implementation + const acc = await createNewAccount({ refill: true, unlock: true }); - await sendFewTxes({ - from: acc.address, - times: 1, - value: '0x1', - }); - const balance = await eth2.getBalance(acc.address); - const code = await eth2.getCode(contractDeployed?.options?.address as string); - const storage = await eth2.getStorageAt( - contractDeployed?.options?.address as string, - 0, - ); - const transactionCount = await eth2.getTransactionCount(acc.address); - expect(storage === '0x' ? 0 : Number(hexToNumber(storage))).toBe(0); - expect(code).toBe('0x'); - expect(balance).toBe(BigInt(0)); - expect(transactionCount).toBe(BigInt(0)); - - // pass blockNumber to rewrite defaultBlockNumber - const balanceWithBlockNumber = await eth2.getBalance(acc.address, 'latest'); - const transactionCountWithBlockNumber = await eth2.getTransactionCount( - acc.address, - 'latest', - ); - const codeWithBlockNumber = await eth2.getCode( - contractDeployed?.options?.address as string, - 'latest', - ); - const storageWithBlockNumber = await eth2.getStorageAt( - contractDeployed?.options?.address as string, - 0, - 'latest', - ); - expect(Number(hexToNumber(storageWithBlockNumber))).toBe(10); - expect(transactionCountWithBlockNumber).toBe(BigInt(1)); - expect(Number(balanceWithBlockNumber)).toBeGreaterThan(0); - expect(codeWithBlockNumber.startsWith(BasicBytecode.slice(0, 10))).toBe(true); - - // set new default block to config - eth2.setConfig({ - defaultBlock: 'latest', - }); - const balanceLatest = await eth2.getBalance(acc.address); - const codeLatest = await eth2.getCode(contractDeployed?.options?.address as string); - const storageLatest = await eth2.getStorageAt( - contractDeployed?.options?.address as string, - 0, - ); - const transactionCountLatest = await eth2.getTransactionCount(acc.address); - expect(codeLatest.startsWith(BasicBytecode.slice(0, 10))).toBe(true); - expect(Number(hexToNumber(storageLatest))).toBe(10); - expect(transactionCountLatest).toBe(BigInt(1)); - expect(Number(balanceLatest)).toBeGreaterThan(0); - await closeOpenConnection(eth2); - await closeOpenConnection(contractDeployed); + await sendFewTxes({ + from: acc.address, + times: 1, + value: '0x1', }); - it('transactionSendTimeout', async () => { - // default - expect(web3Eth.transactionSendTimeout).toBe(750 * 1000); - - // after set - web3Eth.setConfig({ - transactionSendTimeout: 1, - }); - expect(web3Eth.transactionSendTimeout).toBe(1); + const balance = await eth2.getBalance(acc.address); + const code = await eth2.getCode(contractDeployed?.options?.address as string); + const storage = await eth2.getStorageAt(contractDeployed?.options?.address as string, 0); + const transactionCount = await eth2.getTransactionCount(acc.address); + expect(storage === '0x' ? 0 : Number(hexToNumber(storage))).toBe(0); + expect(code).toBe('0x'); + expect(balance).toBe(BigInt(0)); + expect(transactionCount).toBe(BigInt(0)); + + // pass blockNumber to rewrite defaultBlockNumber + const balanceWithBlockNumber = await eth2.getBalance(acc.address, 'latest'); + const transactionCountWithBlockNumber = await eth2.getTransactionCount( + acc.address, + 'latest', + ); + const codeWithBlockNumber = await eth2.getCode( + contractDeployed?.options?.address as string, + 'latest', + ); + const storageWithBlockNumber = await eth2.getStorageAt( + contractDeployed?.options?.address as string, + 0, + 'latest', + ); + expect(Number(hexToNumber(storageWithBlockNumber))).toBe(10); + expect(transactionCountWithBlockNumber).toBe(BigInt(1)); + expect(Number(balanceWithBlockNumber)).toBeGreaterThan(0); + expect(codeWithBlockNumber.startsWith(BasicBytecode.slice(0, 10))).toBe(true); + + // set new default block to config + eth2.setConfig({ + defaultBlock: 'latest', + }); + const balanceLatest = await eth2.getBalance(acc.address); + const codeLatest = await eth2.getCode(contractDeployed?.options?.address as string); + const storageLatest = await eth2.getStorageAt( + contractDeployed?.options?.address as string, + 0, + ); + const transactionCountLatest = await eth2.getTransactionCount(acc.address); + expect(codeLatest.startsWith(BasicBytecode.slice(0, 10))).toBe(true); + expect(Number(hexToNumber(storageLatest))).toBe(10); + expect(transactionCountLatest).toBe(BigInt(1)); + expect(Number(balanceLatest)).toBeGreaterThan(0); + await closeOpenConnection(eth2); + await closeOpenConnection(contractDeployed); + }); + it('transactionSendTimeout', async () => { + // default + expect(web3Eth.transactionSendTimeout).toBe(750 * 1000); - // set by create new instance - const eth2 = new Web3Eth({ - provider: web3Eth.provider, - config: { - transactionSendTimeout: 120, - }, - }); - expect(eth2.transactionSendTimeout).toBe(120); - await closeOpenConnection(eth2); + // after set + web3Eth.setConfig({ + transactionSendTimeout: 1, + }); + expect(web3Eth.transactionSendTimeout).toBe(1); + + // set by create new instance + const eth2 = new Web3Eth({ + provider: web3Eth.provider, + config: { + transactionSendTimeout: 120, + }, }); - it('transactionBlockTimeout', () => { - // default - expect(web3Eth.transactionBlockTimeout).toBe(50); + expect(eth2.transactionSendTimeout).toBe(120); + await closeOpenConnection(eth2); + }); + it('transactionBlockTimeout', () => { + // default + expect(web3Eth.transactionBlockTimeout).toBe(50); - // after set - web3Eth.setConfig({ - transactionBlockTimeout: 1, - }); - expect(web3Eth.transactionBlockTimeout).toBe(1); + // after set + web3Eth.setConfig({ + transactionBlockTimeout: 1, + }); + expect(web3Eth.transactionBlockTimeout).toBe(1); - // set by create new instance - const eth2 = new Web3Eth({ - config: { - transactionBlockTimeout: 120, - }, - }); - expect(eth2.transactionBlockTimeout).toBe(120); + // set by create new instance + const eth2 = new Web3Eth({ + config: { + transactionBlockTimeout: 120, + }, }); - it('transactionConfirmationBlocks default change should work', async () => { - // default - // eslint-disable-next-line jest/no-standalone-expect - expect(web3Eth.transactionConfirmationBlocks).toBe(24); - - // after set - web3Eth.setConfig({ - transactionConfirmationBlocks: 3, - }); - // eslint-disable-next-line jest/no-standalone-expect - expect(web3Eth.transactionConfirmationBlocks).toBe(3); + expect(eth2.transactionBlockTimeout).toBe(120); + }); + it('transactionConfirmationBlocks default change should work', async () => { + // default + // eslint-disable-next-line jest/no-standalone-expect + expect(web3Eth.transactionConfirmationBlocks).toBe(24); + + // after set + web3Eth.setConfig({ + transactionConfirmationBlocks: 3, + }); + // eslint-disable-next-line jest/no-standalone-expect + expect(web3Eth.transactionConfirmationBlocks).toBe(3); + + // set by create new instance + const eth2 = new Web3Eth({ + config: { + transactionConfirmationBlocks: 4, + }, + }); + // eslint-disable-next-line jest/no-standalone-expect + expect(eth2.transactionConfirmationBlocks).toBe(4); + }); - // set by create new instance - const eth2 = new Web3Eth({ - config: { - transactionConfirmationBlocks: 4, - }, - }); - // eslint-disable-next-line jest/no-standalone-expect - expect(eth2.transactionConfirmationBlocks).toBe(4); + it('transactionConfirmationBlocks implementation', async () => { + const tempAcc2 = await createTempAccount(); + const waitConfirmations = 1; + const eth = new Web3Eth(getSystemTestProvider()); + eth.setConfig({ transactionConfirmationBlocks: waitConfirmations }); - }); + const from = tempAcc.address; + const to = tempAcc2.address; + const value = `0x1`; + + let confirmationCount = 0; - it('transactionConfirmationBlocks implementation', async () => { - const tempAcc2 = await createTempAccount(); - const waitConfirmations = 1; - const eth = new Web3Eth(getSystemTestProvider()); - eth.setConfig({ transactionConfirmationBlocks: waitConfirmations }); - - const from = tempAcc.address; - const to = tempAcc2.address; - const value = `0x1`; - - let confirmationCount = 0; - - const sentTx: Web3PromiEvent< - TransactionReceipt, - SendTransactionEvents - > = eth.sendTransaction({ + const sentTx: Web3PromiEvent< + TransactionReceipt, + SendTransactionEvents + > = eth + .sendTransaction({ to, value, from, - }).on('confirmation', (_data) => { + }) + .on('confirmation', _data => { confirmationCount += 1; if (confirmationCount >= waitConfirmations) { - sentTx.removeAllListeners(); // Clean up listeners + sentTx.removeAllListeners(); // Clean up listeners } }); - const receipt = await sentTx; - expect(Number(receipt.status)).toBe(1); + const receipt = await sentTx; + expect(Number(receipt.status)).toBe(1); - // Optionally send a few sample transactions - await sendFewSampleTxs(isIpc ? 5 * waitConfirmations : 2 * waitConfirmations); - - expect(confirmationCount).toBe(waitConfirmations); + // Optionally send a few sample transactions + await sendFewSampleTxs(isIpc ? 5 * waitConfirmations : 2 * waitConfirmations); - await waitForCondition( - () => confirmationCount >= waitConfirmations, - async () => { await closeOpenConnection(eth)}, - 10, - 5000); - }); + expect(confirmationCount).toBe(waitConfirmations); + + await waitForCondition( + () => confirmationCount >= waitConfirmations, + async () => { + await closeOpenConnection(eth); + }, + 10, + 5000, + ); + }); - it('transactionPollingInterval and transactionPollingTimeout', async () => { - // default - expect(web3Eth.transactionPollingInterval).toBe(1000); - expect(web3Eth.transactionPollingTimeout).toBe(750 * 1000); + it('transactionPollingInterval and transactionPollingTimeout', async () => { + // default + expect(web3Eth.transactionPollingInterval).toBe(1000); + expect(web3Eth.transactionPollingTimeout).toBe(750 * 1000); - // after set - web3Eth.setConfig({ - transactionPollingInterval: 3, + // after set + web3Eth.setConfig({ + transactionPollingInterval: 3, + transactionPollingTimeout: 10, + }); + expect(web3Eth.transactionPollingInterval).toBe(3); + expect(web3Eth.transactionPollingTimeout).toBe(10); + + // set by create new instance + const eth2 = new Web3Eth({ + config: { + transactionPollingInterval: 400, transactionPollingTimeout: 10, - }); - expect(web3Eth.transactionPollingInterval).toBe(3); - expect(web3Eth.transactionPollingTimeout).toBe(10); - - // set by create new instance - const eth2 = new Web3Eth({ - config: { - transactionPollingInterval: 400, - transactionPollingTimeout: 10, - }, - }); - expect(eth2.transactionPollingInterval).toBe(400); - expect(eth2.transactionPollingTimeout).toBe(10); + }, + }); + expect(eth2.transactionPollingInterval).toBe(400); + expect(eth2.transactionPollingTimeout).toBe(10); + }); + // todo will work with not instance mining + // itIf(isHttp)('transactionReceiptPollingInterval and transactionConfirmationPollingInterval implementation', async () => { + // eth2 = new Web3Eth({ + // provider: web3Eth.provider, + // config: { + // transactionPollingInterval: 400, + // transactionPollingTimeout: 10, + // }, + // }); + // + // const sentTx: Web3PromiEvent = eth2.sendTransaction({ + // to: tempAcc2.address, + // value: '0x1', + // from: tempAcc.address, + // }); + // + // const res = await Promise.race([ + // new Promise((resolve) => setTimeout(resolve, 410)), + // new Promise((resolve: Resolve) => { + // sentTx.on('receipt', (params: TransactionReceipt) => { + // expect(params.status).toBe(BigInt(1)); + // resolve(params); + // }); + // }), + // ]); + // expect((res as TransactionReceipt).status).toBe(BigInt(1)); + // + // const sentTx2: Web3PromiEvent = eth2.sendTransaction({ + // to: tempAcc2.address, + // value: '0x1', + // from: tempAcc.address, + // }); + // const res2 = await Promise.race([ + // new Promise((resolve) => setTimeout(()=>resolve(false), 300)), + // new Promise((resolve: Resolve) => { + // sentTx2.on('receipt', (params: TransactionReceipt) => { + // expect(params.status).toBe(BigInt(1)); + // resolve(params); + // }); + // }), + // ]); + // expect((res2 as boolean)).toBe(false); + // + // + // }); + it('transactionReceiptPollingInterval and transactionConfirmationPollingInterval', () => { + // default + expect(web3Eth.transactionReceiptPollingInterval).toBeUndefined(); + expect(web3Eth.transactionConfirmationPollingInterval).toBeUndefined(); + + // after set + web3Eth.setConfig({ + transactionReceiptPollingInterval: 3, + transactionConfirmationPollingInterval: 10, }); - // todo will work with not instance mining - // itIf(isHttp)('transactionReceiptPollingInterval and transactionConfirmationPollingInterval implementation', async () => { - // eth2 = new Web3Eth({ - // provider: web3Eth.provider, - // config: { - // transactionPollingInterval: 400, - // transactionPollingTimeout: 10, - // }, - // }); - // - // const sentTx: Web3PromiEvent = eth2.sendTransaction({ - // to: tempAcc2.address, - // value: '0x1', - // from: tempAcc.address, - // }); - // - // const res = await Promise.race([ - // new Promise((resolve) => setTimeout(resolve, 410)), - // new Promise((resolve: Resolve) => { - // sentTx.on('receipt', (params: TransactionReceipt) => { - // expect(params.status).toBe(BigInt(1)); - // resolve(params); - // }); - // }), - // ]); - // expect((res as TransactionReceipt).status).toBe(BigInt(1)); - // - // const sentTx2: Web3PromiEvent = eth2.sendTransaction({ - // to: tempAcc2.address, - // value: '0x1', - // from: tempAcc.address, - // }); - // const res2 = await Promise.race([ - // new Promise((resolve) => setTimeout(()=>resolve(false), 300)), - // new Promise((resolve: Resolve) => { - // sentTx2.on('receipt', (params: TransactionReceipt) => { - // expect(params.status).toBe(BigInt(1)); - // resolve(params); - // }); - // }), - // ]); - // expect((res2 as boolean)).toBe(false); - // - // - // }); - it('transactionReceiptPollingInterval and transactionConfirmationPollingInterval', () => { - // default - expect(web3Eth.transactionReceiptPollingInterval).toBeUndefined(); - expect(web3Eth.transactionConfirmationPollingInterval).toBeUndefined(); - - // after set - web3Eth.setConfig({ - transactionReceiptPollingInterval: 3, + expect(web3Eth.transactionReceiptPollingInterval).toBe(3); + expect(web3Eth.transactionConfirmationPollingInterval).toBe(10); + + // set by create new instance + const eth2 = new Web3Eth({ + config: { + transactionReceiptPollingInterval: 400, transactionConfirmationPollingInterval: 10, - }); - expect(web3Eth.transactionReceiptPollingInterval).toBe(3); - expect(web3Eth.transactionConfirmationPollingInterval).toBe(10); - - // set by create new instance - const eth2 = new Web3Eth({ - config: { - transactionReceiptPollingInterval: 400, - transactionConfirmationPollingInterval: 10, - }, - }); - expect(eth2.transactionReceiptPollingInterval).toBe(400); - expect(eth2.transactionConfirmationPollingInterval).toBe(10); + }, }); - it('blockHeaderTimeout', () => { - // default - expect(web3Eth.blockHeaderTimeout).toBe(10); + expect(eth2.transactionReceiptPollingInterval).toBe(400); + expect(eth2.transactionConfirmationPollingInterval).toBe(10); + }); + it('blockHeaderTimeout', () => { + // default + expect(web3Eth.blockHeaderTimeout).toBe(10); - // after set - web3Eth.setConfig({ - blockHeaderTimeout: 3, - }); - expect(web3Eth.blockHeaderTimeout).toBe(3); + // after set + web3Eth.setConfig({ + blockHeaderTimeout: 3, + }); + expect(web3Eth.blockHeaderTimeout).toBe(3); - // set by create new instance - const eth2 = new Web3Eth({ - config: { - blockHeaderTimeout: 4, - }, - }); - expect(eth2.blockHeaderTimeout).toBe(4); + // set by create new instance + const eth2 = new Web3Eth({ + config: { + blockHeaderTimeout: 4, + }, }); + expect(eth2.blockHeaderTimeout).toBe(4); + }); - it('enableExperimentalFeatures useSubscriptionWhenCheckingBlockTimeout', () => { - // default - expect(web3Eth.enableExperimentalFeatures.useSubscriptionWhenCheckingBlockTimeout).toBe( - false, - ); + it('enableExperimentalFeatures useSubscriptionWhenCheckingBlockTimeout', () => { + // default + expect(web3Eth.enableExperimentalFeatures.useSubscriptionWhenCheckingBlockTimeout).toBe( + false, + ); + + // after set + web3Eth.setConfig({ + enableExperimentalFeatures: { + useSubscriptionWhenCheckingBlockTimeout: true, + useRpcCallSpecification: false, + }, + }); + expect(web3Eth.enableExperimentalFeatures.useSubscriptionWhenCheckingBlockTimeout).toBe( + true, + ); - // after set - web3Eth.setConfig({ + // set by create new instance + const eth2 = new Web3Eth({ + config: { enableExperimentalFeatures: { useSubscriptionWhenCheckingBlockTimeout: true, useRpcCallSpecification: false, }, - }); - expect(web3Eth.enableExperimentalFeatures.useSubscriptionWhenCheckingBlockTimeout).toBe( - true, - ); - - // set by create new instance - const eth2 = new Web3Eth({ - config: { - enableExperimentalFeatures: { - useSubscriptionWhenCheckingBlockTimeout: true, - useRpcCallSpecification: false, - }, - }, - }); - expect(eth2.enableExperimentalFeatures.useSubscriptionWhenCheckingBlockTimeout).toBe( - true, - ); + }, }); + expect(eth2.enableExperimentalFeatures.useSubscriptionWhenCheckingBlockTimeout).toBe(true); + }); - it('enableExperimentalFeatures useRpcCallSpecification', () => { - // default - expect(web3Eth.enableExperimentalFeatures.useRpcCallSpecification).toBe(false); + it('enableExperimentalFeatures useRpcCallSpecification', () => { + // default + expect(web3Eth.enableExperimentalFeatures.useRpcCallSpecification).toBe(false); - // after set - web3Eth.setConfig({ + // after set + web3Eth.setConfig({ + enableExperimentalFeatures: { + useSubscriptionWhenCheckingBlockTimeout: false, + useRpcCallSpecification: true, + }, + }); + expect(web3Eth.enableExperimentalFeatures.useRpcCallSpecification).toBe(true); + + // set by create new instance + const eth2 = new Web3Eth({ + config: { enableExperimentalFeatures: { useSubscriptionWhenCheckingBlockTimeout: false, useRpcCallSpecification: true, }, - }); - expect(web3Eth.enableExperimentalFeatures.useRpcCallSpecification).toBe(true); - - // set by create new instance - const eth2 = new Web3Eth({ - config: { - enableExperimentalFeatures: { - useSubscriptionWhenCheckingBlockTimeout: false, - useRpcCallSpecification: true, - }, - }, - }); - expect(eth2.enableExperimentalFeatures.useRpcCallSpecification).toBe(true); - + }, }); + expect(eth2.enableExperimentalFeatures.useRpcCallSpecification).toBe(true); + }); - it('should fallback to polling if provider support `on` but `newBlockHeaders` does not arrive in `blockHeaderTimeout` seconds', async () => { - const tempAcc2 = await createTempAccount(); - - const tempEth: Web3Eth = new Web3Eth(clientUrl); - // Ensure the provider supports subscriptions to simulate the test scenario - // It will cause providers that does not support subscriptions (like http) to throw exception when subscribing. - // This case is tested to ensure that even if an error happen at subscription, - // polling will still get the data from next blocks. - (tempEth.provider as Web3BaseProvider).supportsSubscriptions = () => true; - - // Cause the events to take a long time (more than blockHeaderTimeout), - // to ensure that polling of new blocks works in such cases. - // This will cause the providers that supports subscription (like WebSocket) - // to never return data through listening to new events - - // eslint-disable-next-line @typescript-eslint/no-misused-promises - (tempEth.provider as Web3BaseProvider).on = async () => { - await new Promise(res => { - setTimeout(res, 1000000); - }); - }; - - // Make the test run faster by casing the polling to start after 1 second - tempEth.blockHeaderTimeout = 1; - const from = tempAcc2.address; - const to = tempAcc.address; - const value = `0x1`; - - const sentTx: Web3PromiEvent< - TransactionReceipt, - SendTransactionEvents - > = tempEth.sendTransaction({ - from, - to, - value, + it('should fallback to polling if provider support `on` but `newBlockHeaders` does not arrive in `blockHeaderTimeout` seconds', async () => { + const tempAcc2 = await createTempAccount(); + + const tempEth: Web3Eth = new Web3Eth(clientUrl); + // Ensure the provider supports subscriptions to simulate the test scenario + // It will cause providers that does not support subscriptions (like http) to throw exception when subscribing. + // This case is tested to ensure that even if an error happen at subscription, + // polling will still get the data from next blocks. + (tempEth.provider as Web3BaseProvider).supportsSubscriptions = () => true; + + // Cause the events to take a long time (more than blockHeaderTimeout), + // to ensure that polling of new blocks works in such cases. + // This will cause the providers that supports subscription (like WebSocket) + // to never return data through listening to new events + + // eslint-disable-next-line @typescript-eslint/no-misused-promises + (tempEth.provider as Web3BaseProvider).on = async () => { + await new Promise(res => { + setTimeout(res, 1000000); }); + }; - let confirmationCount = 0; - const confirmationPromise = new Promise((resolve: (status: bigint) => void) => { - // Tx promise is handled separately - // eslint-disable-next-line no-void - void sentTx.on( - 'confirmation', - async ({ - confirmations, - receipt: { status }, - }: { - confirmations: bigint; - receipt: { status: bigint }; - }) => { - confirmationCount = Number(confirmations); - // Being able to get 2 confirmations means the polling for new blocks works - if (confirmations >= 2) { - sentTx.removeAllListeners(); - resolve(status); - } else { - // Send few transaction to cause dev providers creating new blocks to fire the 'confirmation' event again. - await sendFewSampleTxs(5); - } - }, - ); - }); - const receipt = await sentTx; - expect(Number(receipt.status)).toBe(1); + // Make the test run faster by casing the polling to start after 1 second + tempEth.blockHeaderTimeout = 1; + const from = tempAcc2.address; + const to = tempAcc.address; + const value = `0x1`; + + const sentTx: Web3PromiEvent< + TransactionReceipt, + SendTransactionEvents + > = tempEth.sendTransaction({ + from, + to, + value, + }); - // Ensure the promise the get the confirmations resolves with no error - const status = await confirmationPromise; - expect(status).toBe(BigInt(1)); + let confirmationCount = 0; + const confirmationPromise = new Promise((resolve: (status: bigint) => void) => { + // Tx promise is handled separately + // eslint-disable-next-line no-void + void sentTx.on( + 'confirmation', + async ({ + confirmations, + receipt: { status }, + }: { + confirmations: bigint; + receipt: { status: bigint }; + }) => { + confirmationCount = Number(confirmations); + // Being able to get 2 confirmations means the polling for new blocks works + if (confirmations >= 2) { + sentTx.removeAllListeners(); + resolve(status); + } else { + // Send few transaction to cause dev providers creating new blocks to fire the 'confirmation' event again. + await sendFewSampleTxs(5); + } + }, + ); + }); + const receipt = await sentTx; + expect(Number(receipt.status)).toBe(1); + + // Ensure the promise the get the confirmations resolves with no error + const status = await confirmationPromise; + expect(status).toBe(BigInt(1)); + + await waitForCondition( + () => confirmationCount >= 2, + async () => { + await closeOpenConnection(tempEth); + }, + ); + }); - await waitForCondition( - () => confirmationCount >= 2, - async () => { await closeOpenConnection(tempEth)}); + it('maxListenersWarningThreshold test default config', () => { + // default + expect(web3Eth.maxListenersWarningThreshold).toBe(100); + }); + it('maxListenersWarningThreshold set maxListeners through variable', () => { + const eth2 = new Web3Eth({}); + eth2.maxListenersWarningThreshold = 3; + expect(eth2.maxListenersWarningThreshold).toBe(3); + expect(eth2.getMaxListeners()).toBe(3); + }); + it('maxListenersWarningThreshold set config', () => { + const eth3 = new Web3Eth({}); + eth3.setConfig({ + maxListenersWarningThreshold: 3, }); + expect(eth3.maxListenersWarningThreshold).toBe(3); + expect(eth3.getMaxListeners()).toBe(3); + }); + it('defaultNetworkId', async () => { + // default + expect(web3Eth.defaultNetworkId).toBeUndefined(); - it('maxListenersWarningThreshold test default config', () => { - // default - expect(web3Eth.maxListenersWarningThreshold).toBe(100); + // after set + web3Eth.setConfig({ + defaultNetworkId: 3, }); - it('maxListenersWarningThreshold set maxListeners through variable', () => { - const eth2 = new Web3Eth({}); - eth2.maxListenersWarningThreshold = 3; - expect(eth2.maxListenersWarningThreshold).toBe(3); - expect(eth2.getMaxListeners()).toBe(3); + expect(web3Eth.defaultNetworkId).toBe(3); + + // set by create new instance + const eth2 = new Web3Eth({ + provider: web3Eth.provider, + config: { + defaultNetworkId: 4, + }, }); - it('maxListenersWarningThreshold set config', () => { - const eth3 = new Web3Eth({}); - eth3.setConfig({ - maxListenersWarningThreshold: 3, - }); - expect(eth3.maxListenersWarningThreshold).toBe(3); - expect(eth3.getMaxListeners()).toBe(3); + expect(eth2.defaultNetworkId).toBe(4); + const res = await defaultTransactionBuilder({ + transaction: { + from: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', + to: '0x3535353535353535353535353535353535353535', + value: '0x174876e800', + gas: '0x5208', + }, + web3Context: eth2 as Web3Context, + }); + expect(res.networkId).toBe(4); + + // pass network id + const resWithPassNetworkId = await defaultTransactionBuilder({ + transaction: { + from: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', + to: '0x3535353535353535353535353535353535353535', + value: '0x174876e800', + gas: '0x5208', + networkId: 5, + }, + web3Context: eth2 as Web3Context, }); - it('defaultNetworkId', async () => { - // default - expect(web3Eth.defaultNetworkId).toBeUndefined(); - - // after set - web3Eth.setConfig({ - defaultNetworkId: 3, - }); - expect(web3Eth.defaultNetworkId).toBe(3); - // set by create new instance - const eth2 = new Web3Eth({ - provider: web3Eth.provider, - config: { - defaultNetworkId: 4, - }, - }); - expect(eth2.defaultNetworkId).toBe(4); - const res = await defaultTransactionBuilder({ - transaction: { - from: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', - to: '0x3535353535353535353535353535353535353535', - value: '0x174876e800', - gas: '0x5208', - }, - web3Context: eth2 as Web3Context, - }); - expect(res.networkId).toBe(4); - - // pass network id - const resWithPassNetworkId = await defaultTransactionBuilder({ - transaction: { - from: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', - to: '0x3535353535353535353535353535353535353535', - value: '0x174876e800', - gas: '0x5208', - networkId: 5, - }, - web3Context: eth2 as Web3Context, - }); + expect(resWithPassNetworkId.networkId).toBe(BigInt(5)); - expect(resWithPassNetworkId.networkId).toBe(BigInt(5)); + await closeOpenConnection(eth2); + }); + it('defaultChain', async () => { + // default + expect(web3Eth.defaultChain).toBe('mainnet'); - await closeOpenConnection(eth2); + // after set + web3Eth.setConfig({ + defaultChain: 'ropsten', + }); + expect(web3Eth.defaultChain).toBe('ropsten'); + + // set by create new instance + const eth2 = new Web3Eth({ + provider: web3Eth.provider, + config: { + defaultChain: 'rinkeby', + }, }); - it('defaultChain', async () => { - // default - expect(web3Eth.defaultChain).toBe('mainnet'); + expect(eth2.defaultChain).toBe('rinkeby'); + const res = await defaultTransactionBuilder({ + transaction: { + from: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', + to: '0x3535353535353535353535353535353535353535', + value: '0x174876e800', + gas: '0x5208', + }, + web3Context: eth2 as Web3Context, + }); + expect(res.chain).toBe('rinkeby'); + await closeOpenConnection(eth2); + }); + it('defaultHardfork', async () => { + // default + expect(web3Eth.defaultHardfork).toBe('london'); - // after set - web3Eth.setConfig({ - defaultChain: 'ropsten', - }); - expect(web3Eth.defaultChain).toBe('ropsten'); + // after set + web3Eth.setConfig({ + defaultHardfork: 'dao', + }); + expect(web3Eth.defaultHardfork).toBe('dao'); + + // set by create new instance + const eth2 = new Web3Eth({ + provider: web3Eth.provider, + config: { + defaultHardfork: 'istanbul', + defaultTransactionType: '0x0', + }, + }); + expect(eth2.defaultHardfork).toBe('istanbul'); + expect(eth2.defaultTransactionType).toBe('0x0'); + + const res = await prepareTransactionForSigning( + { + from: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', + to: '0x3535353535353535353535353535353535353535', + value: '0x174876e800', + gas: '0x5208', + gasPrice: '0x4a817c800', + data: '0x0', + nonce: '0x4', + chainId: '0x1', + gasLimit: '0x5208', + }, + eth2, + ); + expect(res.common.hardfork()).toBe('istanbul'); + await closeOpenConnection(eth2); + }); + it('defaultCommon', () => { + // default + expect(web3Eth.defaultCommon).toBeUndefined(); + const baseChain: ValidChains = 'mainnet'; + const hardfork: Hardfork = 'dao'; + const common = { + customChain: { + name: 'test', + networkId: 123, + chainId: 1234, + }, + baseChain, + hardfork, + }; + // after set + web3Eth.setConfig({ + defaultCommon: common, + }); + expect(web3Eth.defaultCommon).toBe(common); - // set by create new instance - const eth2 = new Web3Eth({ - provider: web3Eth.provider, - config: { - defaultChain: 'rinkeby', - }, - }); - expect(eth2.defaultChain).toBe('rinkeby'); - const res = await defaultTransactionBuilder({ - transaction: { - from: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', - to: '0x3535353535353535353535353535353535353535', - value: '0x174876e800', - gas: '0x5208', - }, - web3Context: eth2 as Web3Context, - }); - expect(res.chain).toBe('rinkeby'); - await closeOpenConnection(eth2); + // set by create new instance + const eth2 = new Web3Eth({ + config: { + defaultCommon: common, + }, }); - it('defaultHardfork', async () => { - // default - expect(web3Eth.defaultHardfork).toBe('london'); + expect(eth2.defaultCommon).toBe(common); + }); - // after set - web3Eth.setConfig({ - defaultHardfork: 'dao', - }); - expect(web3Eth.defaultHardfork).toBe('dao'); - - // set by create new instance - const eth2 = new Web3Eth({ - provider: web3Eth.provider, - config: { - defaultHardfork: 'istanbul', - defaultTransactionType: '0x0', - }, - }); - expect(eth2.defaultHardfork).toBe('istanbul'); - expect(eth2.defaultTransactionType).toBe('0x0'); - - const res = await prepareTransactionForSigning( - { - from: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', - to: '0x3535353535353535353535353535353535353535', - value: '0x174876e800', - gas: '0x5208', - gasPrice: '0x4a817c800', - data: '0x0', - nonce: '0x4', - chainId: '0x1', - gasLimit: '0x5208', - }, - eth2, - ); - expect(res.common.hardfork()).toBe('istanbul'); - await closeOpenConnection(eth2); + it('defaultTransactionType', async () => { + // default + expect(web3Eth.defaultTransactionType).toBe('0x2'); + // after set + web3Eth.setConfig({ + defaultTransactionType: '0x3', }); - it('defaultCommon', () => { - // default - expect(web3Eth.defaultCommon).toBeUndefined(); - const baseChain: ValidChains = 'mainnet'; - const hardfork: Hardfork = 'dao'; - const common = { - customChain: { - name: 'test', - networkId: 123, - chainId: 1234, - }, - baseChain, - hardfork, - }; - // after set - web3Eth.setConfig({ - defaultCommon: common, - }); - expect(web3Eth.defaultCommon).toBe(common); + expect(web3Eth.defaultTransactionType).toBe('0x3'); - // set by create new instance - const eth2 = new Web3Eth({ - config: { - defaultCommon: common, - }, - }); - expect(eth2.defaultCommon).toBe(common); + // revert back to default + web3Eth.setConfig({ + defaultTransactionType: '0x2', }); - - it('defaultTransactionType', async () => { - // default - expect(web3Eth.defaultTransactionType).toBe('0x2'); - // after set - web3Eth.setConfig({ - defaultTransactionType: '0x3', - }); - expect(web3Eth.defaultTransactionType).toBe('0x3'); - // revert back to default - web3Eth.setConfig({ - defaultTransactionType: '0x2', - }); + // set by create new instance + const eth = new Web3Eth({ + provider: web3Eth.provider, + config: { + defaultTransactionType: '0x4444', + }, + }); - // set by create new instance - const eth = new Web3Eth({ - provider: web3Eth.provider, - config: { - defaultTransactionType: '0x4444', - }, - }); - - expect(eth.defaultTransactionType).toBe('0x4444'); - - const res = getTransactionType( - { - from: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', - to: '0x3535353535353535353535353535353535353535', - value: '0x174876e800', - gas: '0x5208', - data: '0x0', - nonce: '0x4', - chainId: '0x1', - gasLimit: '0x5208', - }, - eth, - ); - expect(res).toBe('0x4444'); - - // test override to 0x2 if: - // tx.maxFeePerGas !== undefined || - // tx.maxPriorityFeePerGas !== undefined || - // tx.hardfork === 'london' || - // tx.common?.hardfork === 'london' - const maxFeePerGasOverride = getTransactionType( - { - from: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', - to: '0x3535353535353535353535353535353535353535', - value: '0x174876e800', - gas: '0x5208', - data: '0x0', - nonce: '0x4', - chainId: '0x1', - gasLimit: '0x5208', - maxFeePerGas: '0x32', - }, - eth, - ); - expect(maxFeePerGasOverride).toBe('0x2'); - const maxPriorityFeePerGasOverride = getTransactionType( - { - from: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', - to: '0x3535353535353535353535353535353535353535', - value: '0x174876e800', - gas: '0x5208', - data: '0x0', - nonce: '0x4', - chainId: '0x1', - gasLimit: '0x5208', - maxPriorityFeePerGas: '0x32', - }, - eth, - ); - expect(maxPriorityFeePerGasOverride).toBe('0x2'); - const hardforkOverride = getTransactionType( - { - from: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', - to: '0x3535353535353535353535353535353535353535', - value: '0x174876e800', - gas: '0x5208', - data: '0x0', - nonce: '0x4', - chainId: '0x1', - gasLimit: '0x5208', + expect(eth.defaultTransactionType).toBe('0x4444'); + + const res = getTransactionType( + { + from: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', + to: '0x3535353535353535353535353535353535353535', + value: '0x174876e800', + gas: '0x5208', + data: '0x0', + nonce: '0x4', + chainId: '0x1', + gasLimit: '0x5208', + }, + eth, + ); + expect(res).toBe('0x4444'); + + // test override to 0x2 if: + // tx.maxFeePerGas !== undefined || + // tx.maxPriorityFeePerGas !== undefined || + // tx.hardfork === 'london' || + // tx.common?.hardfork === 'london' + const maxFeePerGasOverride = getTransactionType( + { + from: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', + to: '0x3535353535353535353535353535353535353535', + value: '0x174876e800', + gas: '0x5208', + data: '0x0', + nonce: '0x4', + chainId: '0x1', + gasLimit: '0x5208', + maxFeePerGas: '0x32', + }, + eth, + ); + expect(maxFeePerGasOverride).toBe('0x2'); + const maxPriorityFeePerGasOverride = getTransactionType( + { + from: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', + to: '0x3535353535353535353535353535353535353535', + value: '0x174876e800', + gas: '0x5208', + data: '0x0', + nonce: '0x4', + chainId: '0x1', + gasLimit: '0x5208', + maxPriorityFeePerGas: '0x32', + }, + eth, + ); + expect(maxPriorityFeePerGasOverride).toBe('0x2'); + const hardforkOverride = getTransactionType( + { + from: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', + to: '0x3535353535353535353535353535353535353535', + value: '0x174876e800', + gas: '0x5208', + data: '0x0', + nonce: '0x4', + chainId: '0x1', + gasLimit: '0x5208', + hardfork: 'london', + }, + eth, + ); + expect(hardforkOverride).toBe('0x2'); + const commonOverride = getTransactionType( + { + from: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', + to: '0x3535353535353535353535353535353535353535', + value: '0x174876e800', + gas: '0x5208', + data: '0x0', + nonce: '0x4', + chainId: '0x1', + gasLimit: '0x5208', + common: { + customChain: { name: 'ropsten', networkId: '2', chainId: '0x1' }, hardfork: 'london', }, - eth, - ); - expect(hardforkOverride).toBe('0x2'); - const commonOverride = getTransactionType( - { - from: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', - to: '0x3535353535353535353535353535353535353535', - value: '0x174876e800', - gas: '0x5208', - data: '0x0', - nonce: '0x4', - chainId: '0x1', - gasLimit: '0x5208', - common: { - customChain: { name: 'ropsten', networkId: '2', chainId: '0x1' }, - hardfork: 'london', + }, + eth, + ); + expect(commonOverride).toBe('0x2'); + + // override to 0x1 if: + // tx.accessList !== undefined || tx.hardfork === 'berlin' || tx.common?.hardfork === 'berlin' + + const accessListOverride = getTransactionType( + { + from: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', + to: '0x3535353535353535353535353535353535353535', + value: '0x174876e800', + gas: '0x5208', + data: '0x0', + nonce: '0x4', + chainId: '0x1', + gasLimit: '0x5208', + accessList: [ + { + address: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', + storageKeys: ['0x3535353535353535353535353535353535353535'], }, - }, - eth, - ); - expect(commonOverride).toBe('0x2'); - - // override to 0x1 if: - // tx.accessList !== undefined || tx.hardfork === 'berlin' || tx.common?.hardfork === 'berlin' - - const accessListOverride = getTransactionType( - { - from: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', - to: '0x3535353535353535353535353535353535353535', - value: '0x174876e800', - gas: '0x5208', - data: '0x0', - nonce: '0x4', - chainId: '0x1', - gasLimit: '0x5208', - accessList: [ - { - address: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', - storageKeys: ['0x3535353535353535353535353535353535353535'], - }, - ], - }, - eth, - ); - expect(accessListOverride).toBe('0x1'); - - const hardforkBerlinOverride = getTransactionType( - { - from: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', - to: '0x3535353535353535353535353535353535353535', - value: '0x174876e800', - gas: '0x5208', - data: '0x0', - nonce: '0x4', - chainId: '0x1', - gasLimit: '0x5208', + ], + }, + eth, + ); + expect(accessListOverride).toBe('0x1'); + + const hardforkBerlinOverride = getTransactionType( + { + from: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', + to: '0x3535353535353535353535353535353535353535', + value: '0x174876e800', + gas: '0x5208', + data: '0x0', + nonce: '0x4', + chainId: '0x1', + gasLimit: '0x5208', + hardfork: 'berlin', + }, + eth, + ); + expect(hardforkBerlinOverride).toBe('0x0'); + + const commonBerlinOverride = getTransactionType( + { + from: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', + to: '0x3535353535353535353535353535353535353535', + value: '0x174876e800', + gas: '0x5208', + data: '0x0', + nonce: '0x4', + chainId: '0x1', + gasLimit: '0x5208', + common: { + customChain: { name: 'ropsten', networkId: '2', chainId: '0x1' }, hardfork: 'berlin', }, - eth, - ); - expect(hardforkBerlinOverride).toBe('0x0'); - - const commonBerlinOverride = getTransactionType( - { - from: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', - to: '0x3535353535353535353535353535353535353535', - value: '0x174876e800', - gas: '0x5208', - data: '0x0', - nonce: '0x4', - chainId: '0x1', - gasLimit: '0x5208', - common: { - customChain: { name: 'ropsten', networkId: '2', chainId: '0x1' }, - hardfork: 'berlin', - }, - }, - eth, - ); - expect(commonBerlinOverride).toBe('0x0'); - await closeOpenConnection(eth); + }, + eth, + ); + expect(commonBerlinOverride).toBe('0x0'); + await closeOpenConnection(eth); + }); + it('defaultMaxPriorityFeePerGas', async () => { + // default + expect(web3Eth.defaultMaxPriorityFeePerGas).toBe(numberToHex(2500000000)); + // after set + web3Eth.setConfig({ + defaultMaxPriorityFeePerGas: numberToHex(2100000000), }); - it('defaultMaxPriorityFeePerGas', async () => { - // default - expect(web3Eth.defaultMaxPriorityFeePerGas).toBe(numberToHex(2500000000)); - // after set - web3Eth.setConfig({ - defaultMaxPriorityFeePerGas: numberToHex(2100000000), - }); - expect(web3Eth.defaultMaxPriorityFeePerGas).toBe(numberToHex(2100000000)); - - // set by create new instance - const eth2 = new Web3Eth({ - provider: web3Eth.provider, - config: { - defaultMaxPriorityFeePerGas: numberToHex(1200000000), - }, - }); - expect(eth2.defaultMaxPriorityFeePerGas).toBe(numberToHex(1200000000)); - - const res = await getTransactionGasPricing( - { - from: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', - to: '0x3535353535353535353535353535353535353535', - value: '0x174876e800', - type: '0x2', - gas: '0x5208', - data: '0x0', - nonce: '0x4', - chainId: '0x1', - gasLimit: '0x5208', - }, - eth2, - DEFAULT_RETURN_FORMAT, - ); - expect(res?.maxPriorityFeePerGas).toBe(BigInt(1200000000)); - - // override test - const resOverride = await getTransactionGasPricing( - { - from: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', - to: '0x3535353535353535353535353535353535353535', - value: '0x174876e800', - type: '0x2', - gas: '0x5208', - data: '0x0', - nonce: '0x4', - chainId: '0x1', - gasLimit: '0x5208', - maxPriorityFeePerGas: '0x123123123', - }, - eth2, - DEFAULT_RETURN_FORMAT, - ); - expect(resOverride?.maxPriorityFeePerGas).toBe(BigInt('4883362083')); - await closeOpenConnection(eth2); + expect(web3Eth.defaultMaxPriorityFeePerGas).toBe(numberToHex(2100000000)); + + // set by create new instance + const eth2 = new Web3Eth({ + provider: web3Eth.provider, + config: { + defaultMaxPriorityFeePerGas: numberToHex(1200000000), + }, }); - it('transactionBuilder', async () => { - // default - expect(web3Eth.transactionBuilder).toBeUndefined(); + expect(eth2.defaultMaxPriorityFeePerGas).toBe(numberToHex(1200000000)); + + const res = await getTransactionGasPricing( + { + from: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', + to: '0x3535353535353535353535353535353535353535', + value: '0x174876e800', + type: '0x2', + gas: '0x5208', + data: '0x0', + nonce: '0x4', + chainId: '0x1', + gasLimit: '0x5208', + }, + eth2, + DEFAULT_RETURN_FORMAT, + ); + expect(res?.maxPriorityFeePerGas).toBe(BigInt(1200000000)); + + // override test + const resOverride = await getTransactionGasPricing( + { + from: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', + to: '0x3535353535353535353535353535353535353535', + value: '0x174876e800', + type: '0x2', + gas: '0x5208', + data: '0x0', + nonce: '0x4', + chainId: '0x1', + gasLimit: '0x5208', + maxPriorityFeePerGas: '0x123123123', + }, + eth2, + DEFAULT_RETURN_FORMAT, + ); + expect(resOverride?.maxPriorityFeePerGas).toBe(BigInt('4883362083')); + await closeOpenConnection(eth2); + }); + it('transactionBuilder', async () => { + // default + expect(web3Eth.transactionBuilder).toBeUndefined(); - // default - expect(web3Eth.transactionBuilder).toBeUndefined(); + // default + expect(web3Eth.transactionBuilder).toBeUndefined(); - const newBuilderMock = jest.fn() as unknown as TransactionBuilder; + const newBuilderMock = jest.fn() as unknown as TransactionBuilder; - web3Eth.setConfig({ - transactionBuilder: newBuilderMock, - }); - expect(web3Eth.transactionBuilder).toBe(newBuilderMock); + web3Eth.setConfig({ + transactionBuilder: newBuilderMock, + }); + expect(web3Eth.transactionBuilder).toBe(newBuilderMock); - // set by create new instance - const eth2 = new Web3Eth({ - config: { - transactionBuilder: newBuilderMock, - }, - }); - expect(eth2.transactionBuilder).toBe(newBuilderMock); - - await transactionBuilder({ - transaction: { - from: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', - to: '0x3535353535353535353535353535353535353535', - value: '0x174876e800', - gas: '0x5208', - gasPrice: '0x4a817c800', - data: '0x0', - nonce: '0x4', - chainId: '0x1', - gasLimit: '0x5208', - }, - web3Context: eth2, - }); - expect(newBuilderMock).toHaveBeenCalled(); + // set by create new instance + const eth2 = new Web3Eth({ + config: { + transactionBuilder: newBuilderMock, + }, + }); + expect(eth2.transactionBuilder).toBe(newBuilderMock); + + await transactionBuilder({ + transaction: { + from: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', + to: '0x3535353535353535353535353535353535353535', + value: '0x174876e800', + gas: '0x5208', + gasPrice: '0x4a817c800', + data: '0x0', + nonce: '0x4', + chainId: '0x1', + gasLimit: '0x5208', + }, + web3Context: eth2, }); - it('transactionTypeParser', () => { - // default - expect(web3Eth.transactionTypeParser).toBeUndefined(); + expect(newBuilderMock).toHaveBeenCalled(); + }); + it('transactionTypeParser', () => { + // default + expect(web3Eth.transactionTypeParser).toBeUndefined(); - const newParserMock = jest.fn() as unknown as TransactionTypeParser; + const newParserMock = jest.fn() as unknown as TransactionTypeParser; - web3Eth.setConfig({ - transactionTypeParser: newParserMock, - }); - expect(web3Eth.transactionTypeParser).toBe(newParserMock); + web3Eth.setConfig({ + transactionTypeParser: newParserMock, + }); + expect(web3Eth.transactionTypeParser).toBe(newParserMock); - // set by create new instance - const eth2 = new Web3Eth({ - config: { - transactionTypeParser: newParserMock, - }, - }); - expect(eth2.transactionTypeParser).toBe(newParserMock); - detectTransactionType( - { - from: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', - to: '0x3535353535353535353535353535353535353535', - value: '0x174876e800', - gas: '0x5208', - gasPrice: '0x4a817c800', - data: '0x0', - nonce: '0x4', - chainId: '0x1', - gasLimit: '0x5208', - }, - eth2, - ); - expect(newParserMock).toHaveBeenCalled(); + // set by create new instance + const eth2 = new Web3Eth({ + config: { + transactionTypeParser: newParserMock, + }, }); -}); \ No newline at end of file + expect(eth2.transactionTypeParser).toBe(newParserMock); + detectTransactionType( + { + from: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', + to: '0x3535353535353535353535353535353535353535', + value: '0x174876e800', + gas: '0x5208', + gasPrice: '0x4a817c800', + data: '0x0', + nonce: '0x4', + chainId: '0x1', + gasLimit: '0x5208', + }, + eth2, + ); + expect(newParserMock).toHaveBeenCalled(); + }); +}); diff --git a/packages/web3-eth/test/integration/defaults.transactionBlockTimeout.test.ts b/packages/web3-eth/test/integration/defaults.transactionBlockTimeout.test.ts index ba7fd5f15e0..15eb401ea51 100644 --- a/packages/web3-eth/test/integration/defaults.transactionBlockTimeout.test.ts +++ b/packages/web3-eth/test/integration/defaults.transactionBlockTimeout.test.ts @@ -32,8 +32,7 @@ import { sendFewSampleTxs, getSystemTestBackend, describeIf, - BACKEND - + BACKEND, } from '../fixtures/system_test_utils'; const MAX_32_SIGNED_INTEGER = 2147483647; @@ -45,9 +44,9 @@ describeIf(getSystemTestBackend() !== BACKEND.HARDHAT)('defaults', () => { let clientUrl: string | SupportedProviders; let account1: Web3Account; let account2: Web3Account; - let transactionBlockTimeout: number; - let transactionSendTimeout: number; - let transactionPollingTimeout: number; + let transactionBlockTimeout: number; + let transactionSendTimeout: number; + let transactionPollingTimeout: number; let blockHeaderTimeout: number; beforeEach(() => { @@ -62,7 +61,7 @@ describeIf(getSystemTestBackend() !== BACKEND.HARDHAT)('defaults', () => { afterEach(async () => { web3.eth.transactionBlockTimeout = transactionBlockTimeout; - web3.eth.transactionSendTimeout = transactionSendTimeout ; + web3.eth.transactionSendTimeout = transactionSendTimeout; web3.eth.transactionPollingTimeout = transactionPollingTimeout; web3.eth.blockHeaderTimeout = blockHeaderTimeout; await closeOpenConnection(web3); @@ -89,7 +88,7 @@ describeIf(getSystemTestBackend() !== BACKEND.HARDHAT)('defaults', () => { // So, send 2 transactions, one after another, because in this test `transactionBlockTimeout = 2`. // eslint-disable-next-line no-void await sendFewSampleTxs(2); - + // Increase other timeouts so only `transactionBlockTimeout` would be reached web3.eth.transactionSendTimeout = MAX_32_SIGNED_INTEGER; web3.eth.transactionPollingTimeout = MAX_32_SIGNED_INTEGER; @@ -99,7 +98,6 @@ describeIf(getSystemTestBackend() !== BACKEND.HARDHAT)('defaults', () => { await expect(sentTx).rejects.toThrow(/was not mined within [0-9]+ blocks/); await expect(sentTx).rejects.toThrow(TransactionBlockTimeoutError); - }); // The code of this test case is identical to the pervious one except for `eth.enableExperimentalFeatures = true` @@ -139,7 +137,6 @@ describeIf(getSystemTestBackend() !== BACKEND.HARDHAT)('defaults', () => { await expect(sentTx).rejects.toThrow(/was not mined within [0-9]+ blocks/); await expect(sentTx).rejects.toThrow(TransactionBlockTimeoutError); - }, ); }); diff --git a/packages/web3-eth/test/integration/get_revert_reason.test.ts b/packages/web3-eth/test/integration/get_revert_reason.test.ts index 4180742a21b..664b9569cf9 100644 --- a/packages/web3-eth/test/integration/get_revert_reason.test.ts +++ b/packages/web3-eth/test/integration/get_revert_reason.test.ts @@ -27,7 +27,7 @@ import { getSystemTestBackend, getSystemTestProvider, BACKEND, - closeOpenConnection + closeOpenConnection, } from '../fixtures/system_test_utils'; describe('Web3Eth.getRevertReason', () => { @@ -163,7 +163,7 @@ describe('Web3Eth.getRevertReason', () => { case BACKEND.HARDHAT: expect(response).toMatchObject({ data: '', - reason: "Error: VM Exception while processing transaction: reverted with an unrecognized custom error (return data: 0x72090e4d)", + reason: 'Error: VM Exception while processing transaction: reverted with an unrecognized custom error (return data: 0x72090e4d)', signature: '0x72090e4d', customErrorName: 'ErrorWithNoParams', customErrorDecodedSignature: 'ErrorWithNoParams()', @@ -202,7 +202,7 @@ describe('Web3Eth.getRevertReason', () => { case BACKEND.HARDHAT: expect(response).toMatchObject({ data: '000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001c5468697320697320616e206572726f72207769746820706172616d7300000000', - reason: "Error: VM Exception while processing transaction: reverted with an unrecognized custom error (return data: 0xc85bda60000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001c5468697320697320616e206572726f72207769746820706172616d7300000000)", + reason: 'Error: VM Exception while processing transaction: reverted with an unrecognized custom error (return data: 0xc85bda60000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001c5468697320697320616e206572726f72207769746820706172616d7300000000)', signature: '0xc85bda60', customErrorName: 'ErrorWithParams', customErrorDecodedSignature: 'ErrorWithParams(uint256,string)', diff --git a/packages/web3-eth/test/integration/nonce.test.ts b/packages/web3-eth/test/integration/nonce.test.ts index 201c0728d5f..96621c97b54 100644 --- a/packages/web3-eth/test/integration/nonce.test.ts +++ b/packages/web3-eth/test/integration/nonce.test.ts @@ -26,7 +26,7 @@ import { createLocalAccount, getSystemTestBackend, getSystemTestProvider, - BACKEND + BACKEND, } from '../fixtures/system_test_utils'; const gas = 30000; @@ -86,13 +86,13 @@ describe('defaults', () => { web3Eth.transactionPollingTimeout / 1000 } seconds`, ); - } else if (getSystemTestBackend() === BACKEND.HARDHAT){ + } else if (getSystemTestBackend() === BACKEND.HARDHAT) { // eslint-disable-next-line jest/no-conditional-expect - expect((error as any).message).toContain("Nonce too high") - } else { - throw error; + expect((error as any).message).toContain('Nonce too high'); + } else { + throw error; + } } - } - }); + }); }); }); diff --git a/packages/web3-eth/test/integration/watch_transaction.test.ts b/packages/web3-eth/test/integration/watch_transaction.test.ts index 733b64a089b..63b27374366 100644 --- a/packages/web3-eth/test/integration/watch_transaction.test.ts +++ b/packages/web3-eth/test/integration/watch_transaction.test.ts @@ -86,14 +86,15 @@ describeIf(isSocket)('watch subscription transaction', () => { await receiptPromise; await sendFewSampleTxs(isIpc ? 2 * waitConfirmations : waitConfirmations); - const resourcePromise = waitForCondition( - () => shouldBe >= waitConfirmations, + const resourcePromise = waitForCondition( + () => shouldBe >= waitConfirmations, async () => { sentTx.removeAllListeners(); - await closeOpenConnection(web3);} - ); + await closeOpenConnection(web3); + }, + ); - await Promise.all([confirmationPromise,resourcePromise]); + await Promise.all([confirmationPromise, resourcePromise]); }); }); }); diff --git a/packages/web3-eth/test/integration/web3_eth/createAccessList.test.ts b/packages/web3-eth/test/integration/web3_eth/createAccessList.test.ts index 3e1186c3cda..2f102be3b57 100644 --- a/packages/web3-eth/test/integration/web3_eth/createAccessList.test.ts +++ b/packages/web3-eth/test/integration/web3_eth/createAccessList.test.ts @@ -22,7 +22,7 @@ import { describeIf, getSystemTestBackend, getSystemTestProvider, - BACKEND + BACKEND, } from '../../fixtures/system_test_utils'; describeIf(getSystemTestBackend() === BACKEND.GETH)('Web3Eth.createAccessList', () => { diff --git a/packages/web3-eth/test/integration/web3_eth/estimate_gas.test.ts b/packages/web3-eth/test/integration/web3_eth/estimate_gas.test.ts index e26de249a3e..96951950f3a 100644 --- a/packages/web3-eth/test/integration/web3_eth/estimate_gas.test.ts +++ b/packages/web3-eth/test/integration/web3_eth/estimate_gas.test.ts @@ -24,7 +24,7 @@ import { itIf, isGeth, getSystemTestBackend, - BACKEND + BACKEND, } from '../../fixtures/system_test_utils'; describe('Web3Eth.estimateGas', () => { diff --git a/packages/web3-eth/test/integration/web3_eth/getFeeHistory.test.ts b/packages/web3-eth/test/integration/web3_eth/getFeeHistory.test.ts index fd8aec67383..0cbd85fc752 100644 --- a/packages/web3-eth/test/integration/web3_eth/getFeeHistory.test.ts +++ b/packages/web3-eth/test/integration/web3_eth/getFeeHistory.test.ts @@ -22,7 +22,7 @@ import { describeIf, getSystemTestBackend, closeOpenConnection, - BACKEND + BACKEND, } from '../../fixtures/system_test_utils'; import { feeHistorySchema } from '../../../src/schemas'; diff --git a/packages/web3-eth/test/integration/web3_eth/send_signed_transaction.test.ts b/packages/web3-eth/test/integration/web3_eth/send_signed_transaction.test.ts index f74a12938ac..fccd63dcc1b 100644 --- a/packages/web3-eth/test/integration/web3_eth/send_signed_transaction.test.ts +++ b/packages/web3-eth/test/integration/web3_eth/send_signed_transaction.test.ts @@ -38,7 +38,7 @@ import { getSystemTestBackend, getSystemTestProvider, describeIf, - BACKEND + BACKEND, } from '../../fixtures/system_test_utils'; import { getTransactionGasPricing } from '../../../src/utils/get_transaction_gas_pricing'; import { SimpleRevertAbi, SimpleRevertDeploymentData } from '../../fixtures/simple_revert'; diff --git a/packages/web3-eth/test/integration/web3_eth/sign.test.ts b/packages/web3-eth/test/integration/web3_eth/sign.test.ts index b468dbb1cb0..a46a5ca28f1 100644 --- a/packages/web3-eth/test/integration/web3_eth/sign.test.ts +++ b/packages/web3-eth/test/integration/web3_eth/sign.test.ts @@ -23,7 +23,7 @@ import { createTempAccount, getSystemTestBackend, getSystemTestProvider, - BACKEND + BACKEND, } from '../../fixtures/system_test_utils'; describe('Web3Eth.sign', () => { diff --git a/packages/web3-eth/test/integration/web3_eth/sign_transaction.test.ts b/packages/web3-eth/test/integration/web3_eth/sign_transaction.test.ts index 630a67cfba2..97d865b2c8d 100644 --- a/packages/web3-eth/test/integration/web3_eth/sign_transaction.test.ts +++ b/packages/web3-eth/test/integration/web3_eth/sign_transaction.test.ts @@ -23,7 +23,7 @@ import { getSystemTestProvider, describeIf, getSystemTestBackend, - BACKEND + BACKEND, } from '../../fixtures/system_test_utils'; // hardhat does not support eth_signtransaction diff --git a/packages/web3-eth/test/integration/web3_eth/submit_work.test.ts b/packages/web3-eth/test/integration/web3_eth/submit_work.test.ts index d3817d551b4..c1728fda297 100644 --- a/packages/web3-eth/test/integration/web3_eth/submit_work.test.ts +++ b/packages/web3-eth/test/integration/web3_eth/submit_work.test.ts @@ -21,7 +21,7 @@ import { getSystemTestBackend, getSystemTestProvider, itIf, - BACKEND + BACKEND, } from '../../fixtures/system_test_utils'; describe('Web3Eth.submitWork', () => { @@ -36,13 +36,16 @@ describe('Web3Eth.submitWork', () => { }); // Hardhat and Geth doesn't support eth_submitWork - itIf(getSystemTestBackend() !== BACKEND.GETH && getSystemTestBackend() !== BACKEND.HARDHAT)('should submit work', async () => { - const response = await web3Eth.submitWork( - '0x0000000000000001', - '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef', - '0xD1FE5700000000000000000000000000D1FE5700000000000000000000000000', - ); - // eslint-disable-next-line jest/no-standalone-expect - expect(response).toBe(false); - }); + itIf(getSystemTestBackend() !== BACKEND.GETH && getSystemTestBackend() !== BACKEND.HARDHAT)( + 'should submit work', + async () => { + const response = await web3Eth.submitWork( + '0x0000000000000001', + '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef', + '0xD1FE5700000000000000000000000000D1FE5700000000000000000000000000', + ); + // eslint-disable-next-line jest/no-standalone-expect + expect(response).toBe(false); + }, + ); }); diff --git a/packages/web3-eth/test/unit/default_transaction_builder.test.ts b/packages/web3-eth/test/unit/default_transaction_builder.test.ts index 0e065806393..5d8e9b34b39 100644 --- a/packages/web3-eth/test/unit/default_transaction_builder.test.ts +++ b/packages/web3-eth/test/unit/default_transaction_builder.test.ts @@ -242,7 +242,6 @@ describe('defaultTransactionBuilder', () => { expect(result.value).toBe('0x0'); }); - it('should not populate with 0x0 if provided', async () => { const input = { ...transaction }; delete input.maxPriorityFeePerGas; diff --git a/packages/web3-eth/test/unit/detect_transaction_type.test.ts b/packages/web3-eth/test/unit/detect_transaction_type.test.ts index 4d583bbad17..094bbebff68 100644 --- a/packages/web3-eth/test/unit/detect_transaction_type.test.ts +++ b/packages/web3-eth/test/unit/detect_transaction_type.test.ts @@ -28,7 +28,6 @@ import { transactionTypeValidationError, } from '../fixtures/detect_transaction_type'; - jest.mock('../../src/rpc_method_wrappers'); describe('detectTransactionType', () => { diff --git a/packages/web3-eth/test/unit/prepare_transaction_for_signing.test.ts b/packages/web3-eth/test/unit/prepare_transaction_for_signing.test.ts index d53785c2e36..ce83a505d17 100644 --- a/packages/web3-eth/test/unit/prepare_transaction_for_signing.test.ts +++ b/packages/web3-eth/test/unit/prepare_transaction_for_signing.test.ts @@ -15,12 +15,7 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ -import { - EthExecutionAPI, - HexString, - Web3NetAPI, - Transaction as TransactionType, -} from 'web3-types'; +import { EthExecutionAPI, HexString, Web3NetAPI, Transaction as TransactionType } from 'web3-types'; import { Web3Context } from 'web3-core'; import HttpProvider from 'web3-providers-http'; import { isNullish } from 'web3-validator'; diff --git a/packages/web3-eth/test/unit/rpc_method_wrappers/fixtures/get_block.ts b/packages/web3-eth/test/unit/rpc_method_wrappers/fixtures/get_block.ts index 250f770bd64..b129ab368b3 100644 --- a/packages/web3-eth/test/unit/rpc_method_wrappers/fixtures/get_block.ts +++ b/packages/web3-eth/test/unit/rpc_method_wrappers/fixtures/get_block.ts @@ -73,7 +73,7 @@ export const mockRpcResponseHydrated: Block = { export const noTransactionBlock: Block = { ...mockRpcResponse, transactions: [], -} +}; /** * Array consists of: diff --git a/packages/web3-eth/test/unit/rpc_method_wrappers/get_block.test.ts b/packages/web3-eth/test/unit/rpc_method_wrappers/get_block.test.ts index 365fb09d9ec..9e5d6540ed4 100644 --- a/packages/web3-eth/test/unit/rpc_method_wrappers/get_block.test.ts +++ b/packages/web3-eth/test/unit/rpc_method_wrappers/get_block.test.ts @@ -28,7 +28,12 @@ import { isBytes, isNullish } from 'web3-validator'; import { ethRpcMethods } from 'web3-rpc-methods'; import { getBlock } from '../../../src/rpc_method_wrappers'; -import { mockRpcResponse, mockRpcResponseHydrated, testData, noTransactionBlock } from './fixtures/get_block'; +import { + mockRpcResponse, + mockRpcResponseHydrated, + testData, + noTransactionBlock, +} from './fixtures/get_block'; import { blockSchema } from '../../../src/schemas'; jest.mock('web3-rpc-methods'); @@ -97,9 +102,7 @@ describe('getBlock', () => { expectedMockRpcResponse, expectedReturnFormat, ); - const expectedFormattedResult = {...formattedResult, - transactions: [] - }; + const expectedFormattedResult = { ...formattedResult, transactions: [] }; const inputBlockIsBytes = isBytes(inputBlock as Bytes); ( (inputBlockIsBytes diff --git a/packages/web3-eth/test/unit/rpc_method_wrappers/send_transaction_middleware.test.ts b/packages/web3-eth/test/unit/rpc_method_wrappers/send_transaction_middleware.test.ts index 63dddbb759f..aa289605788 100644 --- a/packages/web3-eth/test/unit/rpc_method_wrappers/send_transaction_middleware.test.ts +++ b/packages/web3-eth/test/unit/rpc_method_wrappers/send_transaction_middleware.test.ts @@ -15,84 +15,82 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ -import { Web3Context } from "web3-core"; -import { DEFAULT_RETURN_FORMAT, Web3EthExecutionAPI } from "web3-types"; -import {blockMockResult,receiptMockResult } from "../../fixtures/transactions_data"; -import { TransactionMiddleware, sendTransaction } from "../../../src"; +import { Web3Context } from 'web3-core'; +import { DEFAULT_RETURN_FORMAT, Web3EthExecutionAPI } from 'web3-types'; +import { blockMockResult, receiptMockResult } from '../../fixtures/transactions_data'; +import { TransactionMiddleware, sendTransaction } from '../../../src'; const mockTransactionMiddleware: TransactionMiddleware = { - processTransaction: jest.fn(async (transaction) => { - const tx = {...transaction} - tx.data = '0x123'; - return Promise.resolve(tx)} -), + processTransaction: jest.fn(async transaction => { + const tx = { ...transaction }; + tx.data = '0x123'; + return Promise.resolve(tx); + }), }; describe('sendTransaction', () => { let web3Context: Web3Context; - + beforeEach(() => { let blockNum = 0; web3Context = new Web3Context('http://127.0.0.1:8545'); - web3Context.requestManager.send = jest.fn(async (request) => { + web3Context.requestManager.send = jest.fn(async request => { blockNum += 1; - if(request.method === 'eth_getBlockByNumber'){ - + if (request.method === 'eth_getBlockByNumber') { return Promise.resolve(blockMockResult.result); } - if(request.method === 'eth_call'){ - - return Promise.resolve("0x"); + if (request.method === 'eth_call') { + return Promise.resolve('0x'); } - if(request.method === 'eth_blockNumber'){ - + if (request.method === 'eth_blockNumber') { return Promise.resolve(blockNum.toString(16)); } - if(request.method === 'eth_sendTransaction'){ - - return Promise.resolve("0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f"); + if (request.method === 'eth_sendTransaction') { + return Promise.resolve( + '0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f', + ); } if (request.method === 'eth_getTransactionReceipt') { return Promise.resolve(receiptMockResult.result); } - - return Promise.resolve("Unknown Request" as any); + + return Promise.resolve('Unknown Request' as any); }); }); afterEach(() => jest.resetAllMocks()); - it('should call processTransaction when transactionMiddleware is provided', async () => { - const transaction = { - from: '0x6E599DA0bfF7A6598AC1224E4985430Bf16458a4', - to: '0x6f1DF96865D09d21e8f3f9a7fbA3b17A11c7C53C', - value: '0x1', - data: '0x1' - }; - - await sendTransaction( - web3Context, - transaction, - DEFAULT_RETURN_FORMAT, - {}, - mockTransactionMiddleware, - ); - - expect(mockTransactionMiddleware.processTransaction).toHaveBeenCalledWith(transaction); - }); - - it('should not call processTransaction when transactionMiddleware is not provided', async () => { - const transaction = { - from: '0x6E599DA0bfF7A6598AC1224E4985430Bf16458a4', - to: '0x6f1DF96865D09d21e8f3f9a7fbA3b17A11c7C53C', - value: '0x1', - data: '0x1' - }; - - await sendTransaction(web3Context, transaction, DEFAULT_RETURN_FORMAT); - - expect(mockTransactionMiddleware.processTransaction).not.toHaveBeenCalled(); - }); -}); \ No newline at end of file + it('should call processTransaction when transactionMiddleware is provided', async () => { + const transaction = { + from: '0x6E599DA0bfF7A6598AC1224E4985430Bf16458a4', + to: '0x6f1DF96865D09d21e8f3f9a7fbA3b17A11c7C53C', + value: '0x1', + data: '0x1', + }; + + await sendTransaction( + web3Context, + transaction, + DEFAULT_RETURN_FORMAT, + {}, + mockTransactionMiddleware, + ); + + expect(mockTransactionMiddleware.processTransaction).toHaveBeenCalledWith(transaction); + }); + + it('should not call processTransaction when transactionMiddleware is not provided', async () => { + const transaction = { + from: '0x6E599DA0bfF7A6598AC1224E4985430Bf16458a4', + to: '0x6f1DF96865D09d21e8f3f9a7fbA3b17A11c7C53C', + value: '0x1', + data: '0x1', + }; + + await sendTransaction(web3Context, transaction, DEFAULT_RETURN_FORMAT); + + expect(mockTransactionMiddleware.processTransaction).not.toHaveBeenCalled(); + }); +}); 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 6b40496f5a6..23e0d2aa526 100644 --- a/packages/web3-eth/test/unit/send_tx_helper.test.ts +++ b/packages/web3-eth/test/unit/send_tx_helper.test.ts @@ -21,7 +21,7 @@ import { JsonRpcResponse, TransactionReceipt, Web3BaseWalletAccount, - TransactionCall + TransactionCall, } from 'web3-types'; import { Web3Context, Web3EventMap, Web3PromiEvent } from 'web3-core'; import { @@ -163,16 +163,15 @@ describe('sendTxHelper class', () => { returnFormat: DEFAULT_RETURN_FORMAT, }); - const tx = {from:"0x"} as TransactionCall + const tx = { from: '0x' } as TransactionCall; - await _sendTxHelper.checkRevertBeforeSending(tx); + await _sendTxHelper.checkRevertBeforeSending(tx); - const expectedTx = { - ...tx, - gas: 21000, - }; + 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' }); diff --git a/packages/web3-eth/test/unit/utils/get_transaction_type.test.ts b/packages/web3-eth/test/unit/utils/get_transaction_type.test.ts index 73111b42067..203dcdfc4ec 100644 --- a/packages/web3-eth/test/unit/utils/get_transaction_type.test.ts +++ b/packages/web3-eth/test/unit/utils/get_transaction_type.test.ts @@ -23,32 +23,30 @@ import { format } from 'web3-utils'; import { transactionSchema } from '../../../src/schemas'; import { getTransactionType } from '../../../src/utils/transaction_builder'; - describe('getTransactionType', () => { const expectedFrom = '0xb8CE9ab6943e0eCED004cDe8e3bBed6568B2Fa01'; - const transaction: Transaction = { - from: expectedFrom, - to: '0x3535353535353535353535353535353535353535', - value: '0x174876e800', - gas: BigInt(21000), - data: '0x', - nonce: 0x42, - chain: 'mainnet', - chainId: 0x1, - networkId: 0x4, - }; - const formattedTransaction = format(transactionSchema, transaction, ETH_DATA_FORMAT); - - const web3Context = new Web3Context({ - provider: new HttpProvider('http://127.0.0.1:80'), - config: { - defaultAccount: expectedFrom, - }, - }); - - it('should default to 0x2 when transaction type cannot be inferred and use default transaction type', async () => { + const transaction: Transaction = { + from: expectedFrom, + to: '0x3535353535353535353535353535353535353535', + value: '0x174876e800', + gas: BigInt(21000), + data: '0x', + nonce: 0x42, + chain: 'mainnet', + chainId: 0x1, + networkId: 0x4, + }; + const formattedTransaction = format(transactionSchema, transaction, ETH_DATA_FORMAT); + + const web3Context = new Web3Context({ + provider: new HttpProvider('http://127.0.0.1:80'), + config: { + defaultAccount: expectedFrom, + }, + }); + it('should default to 0x2 when transaction type cannot be inferred and use default transaction type', async () => { const transactionType = getTransactionType(formattedTransaction, web3Context); expect(transactionType).toBe('0x2'); }); diff --git a/packages/web3-eth/test/unit/utils/wait_for_transaction_receipt.test.ts b/packages/web3-eth/test/unit/utils/wait_for_transaction_receipt.test.ts index 4a598a00fe7..5e8d4f601d3 100644 --- a/packages/web3-eth/test/unit/utils/wait_for_transaction_receipt.test.ts +++ b/packages/web3-eth/test/unit/utils/wait_for_transaction_receipt.test.ts @@ -173,4 +173,4 @@ describe('waitForTransactionReceipt unit test', () => { expect(res.transactionHash).toStrictEqual(txHash); expect(res.blockHash).toStrictEqual(blockHash); }); -}); \ No newline at end of file +}); diff --git a/packages/web3-eth/test/unit/utils/watch_transaction_by_subscription.test.ts b/packages/web3-eth/test/unit/utils/watch_transaction_by_subscription.test.ts index 23c92c793a6..0b027b9dc14 100644 --- a/packages/web3-eth/test/unit/utils/watch_transaction_by_subscription.test.ts +++ b/packages/web3-eth/test/unit/utils/watch_transaction_by_subscription.test.ts @@ -27,13 +27,11 @@ import { } from '../rpc_method_wrappers/fixtures/send_signed_transaction'; import { blockMockResult } from '../../fixtures/transactions_data'; - jest.mock('web3-providers-ws'); const testMessage = 'Title: %s\ninputSignedTransaction: %s\nexpectedTransactionHash: %s\nexpectedTransactionReceipt: %s\n'; - describe('watchTransactionBySubscription', () => { const CONFIRMATION_BLOCKS = 5; describe('should revert to polling in cases where getting by subscription did not workout', () => { @@ -41,34 +39,29 @@ describe('watchTransactionBySubscription', () => { beforeEach(() => { web3Context = new Web3Context({ - provider: new WebSocketProvider('wss://localhost:8546'),} - ); + provider: new WebSocketProvider('wss://localhost:8546'), + }); (web3Context.provider as any).supportsSubscriptions = () => true; web3Context.transactionConfirmationBlocks = CONFIRMATION_BLOCKS; - web3Context.enableExperimentalFeatures.useSubscriptionWhenCheckingBlockTimeout = - true; - + web3Context.enableExperimentalFeatures.useSubscriptionWhenCheckingBlockTimeout = true; }); it.each(testData)( `should call getBlockByNumber if blockHeaderTimeout reached\n ${testMessage}`, - async (_, inputTransaction,) => { - + async (_, inputTransaction) => { let blockNum = 100; let ethGetBlockByNumberCount = 0; - web3Context.requestManager.send = jest.fn(async (request) => { - + web3Context.requestManager.send = jest.fn(async request => { if (request.method === 'eth_getBlockByNumber') { ethGetBlockByNumberCount += 1; - return Promise.resolve( - { ...blockMockResult.result, - number: (request as any).params[0] - }); + return Promise.resolve({ + ...blockMockResult.result, + number: (request as any).params[0], + }); } if (request.method === 'eth_call') { - - return Promise.resolve("0x"); + return Promise.resolve('0x'); } if (request.method === 'eth_blockNumber') { blockNum += 1; @@ -80,9 +73,9 @@ describe('watchTransactionBySubscription', () => { if (request.method === 'eth_getTransactionReceipt') { return Promise.resolve(expectedTransactionReceipt); } - + // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return Promise.reject(new Error("Unknown Request")) as any; + return Promise.reject(new Error('Unknown Request')) as any; }); const promiEvent = rpcMethodWrappers.sendSignedTransaction( @@ -93,33 +86,35 @@ describe('watchTransactionBySubscription', () => { let confirmationsCount = 0; const confirmationPromise = new Promise((resolve, reject) => { - const handleConfirmation = (confirmation: { confirmations: bigint }) => { - confirmationsCount += 1; - - if (confirmation.confirmations >= CONFIRMATION_BLOCKS) { - resolve(); - } + confirmationsCount += 1; + + if (confirmation.confirmations >= CONFIRMATION_BLOCKS) { + resolve(); + } }; - + const handleError = (_error: any) => { - reject(); + reject(); }; - + promiEvent - .on('confirmation', handleConfirmation) - .on('error', handleError) - .then((res) => { - // eslint-disable-next-line jest/no-conditional-expect - expect(res).toBeDefined(); - }) - .catch(reject); - }); + .on('confirmation', handleConfirmation) + .on('error', handleError) + .then(res => { + // eslint-disable-next-line jest/no-conditional-expect + expect(res).toBeDefined(); + }) + .catch(reject); + }); // Wait for the confirmationPromise to resolve or timeout after 5 seconds let timeoutId; const timeout = new Promise((_res, reject) => { - timeoutId = setTimeout(() => reject(new Error('Timeout waiting for confirmations')), 500000); + timeoutId = setTimeout( + () => reject(new Error('Timeout waiting for confirmations')), + 500000, + ); }); await Promise.race([confirmationPromise, timeout]); @@ -128,10 +123,7 @@ describe('watchTransactionBySubscription', () => { expect(confirmationsCount).toBe(CONFIRMATION_BLOCKS); expect(ethGetBlockByNumberCount).toBe(CONFIRMATION_BLOCKS - 1); // means polling called getblock 4 times as first confirmation is receipt it self - - } + }, ); - - }); }); diff --git a/packages/web3-eth/test/unit/web3_eth_calculate_fee_data.test.ts b/packages/web3-eth/test/unit/web3_eth_calculate_fee_data.test.ts index ed1b504a3be..58cf6deb6fd 100644 --- a/packages/web3-eth/test/unit/web3_eth_calculate_fee_data.test.ts +++ b/packages/web3-eth/test/unit/web3_eth_calculate_fee_data.test.ts @@ -49,9 +49,9 @@ describe('Web3Eth.calculateFeeData', () => { jest.spyOn(ethRpcMethods, 'getBlockByNumber').mockReturnValueOnce({ baseFeePerGas } as any); jest.spyOn(ethRpcMethods, 'getGasPrice').mockReturnValueOnce(gasPrice as any); // eslint-disable-next-line @typescript-eslint/no-unsafe-call - jest - .spyOn(ethRpcMethods, 'getMaxPriorityFeePerGas') - .mockReturnValueOnce(maxPriorityFeePerGas as any); + jest.spyOn(ethRpcMethods, 'getMaxPriorityFeePerGas').mockReturnValueOnce( + maxPriorityFeePerGas as any, + ); const feeData = await web3Eth.calculateFeeData(baseFeePerGasFactor, maxPriorityFeePerGas); expect(feeData).toMatchObject({ diff --git a/packages/web3-eth/test/unit/web3_eth_methods_no_parameters.test.ts b/packages/web3-eth/test/unit/web3_eth_methods_no_parameters.test.ts index a66a1ecdd46..c01ae8f0fc6 100644 --- a/packages/web3-eth/test/unit/web3_eth_methods_no_parameters.test.ts +++ b/packages/web3-eth/test/unit/web3_eth_methods_no_parameters.test.ts @@ -79,7 +79,9 @@ describe('web3_eth_methods_no_parameters', () => { it('getMaxPriorityFeePerGas', async () => { await web3Eth.getMaxPriorityFeePerGas(); - expect(ethRpcMethods.getMaxPriorityFeePerGas).toHaveBeenCalledWith(web3Eth.requestManager); + expect(ethRpcMethods.getMaxPriorityFeePerGas).toHaveBeenCalledWith( + web3Eth.requestManager, + ); }); }); }); diff --git a/packages/web3-eth/test/unit/web3_eth_methods_with_parameters.test.ts b/packages/web3-eth/test/unit/web3_eth_methods_with_parameters.test.ts index 76d753bde4b..7186e2e63de 100644 --- a/packages/web3-eth/test/unit/web3_eth_methods_with_parameters.test.ts +++ b/packages/web3-eth/test/unit/web3_eth_methods_with_parameters.test.ts @@ -65,17 +65,17 @@ describe('web3_eth_methods_with_parameters', () => { it('should set and unset the transactionMiddleware correctly', () => { const mockTransactionMiddleware: TransactionMiddleware = { - processTransaction: jest.fn(), + processTransaction: jest.fn(), }; - + web3Eth.setTransactionMiddleware(mockTransactionMiddleware); - + expect(web3Eth.getTransactionMiddleware()).toBe(mockTransactionMiddleware); web3Eth.setTransactionMiddleware(undefined as any); expect(web3Eth.getTransactionMiddleware()).toBeUndefined(); - }); + }); describe('should call RPC method with expected parameters', () => { describe('only has returnFormat parameter', () => { diff --git a/packages/web3-net/CHANGELOG.md b/packages/web3-net/CHANGELOG.md index 5e7ea9073b3..ff3ca87f519 100644 --- a/packages/web3-net/CHANGELOG.md +++ b/packages/web3-net/CHANGELOG.md @@ -147,4 +147,4 @@ Documentation: - `defaultReturnFormat` was added to all methods that have `ReturnType` param. (#6947) -## [Unreleased] \ No newline at end of file +## [Unreleased] diff --git a/packages/web3-net/test/fixtures/rpc_method_wrappers.ts b/packages/web3-net/test/fixtures/rpc_method_wrappers.ts index 701a966e67e..0e76bcdd39b 100644 --- a/packages/web3-net/test/fixtures/rpc_method_wrappers.ts +++ b/packages/web3-net/test/fixtures/rpc_method_wrappers.ts @@ -29,4 +29,4 @@ export const getPeerCountValidData: [DataFormat, any, any][] = [ [{ number: FMT_NUMBER.STR, bytes: FMT_BYTES.HEX }, '0x2', '2'], [{ number: FMT_NUMBER.NUMBER, bytes: FMT_BYTES.HEX }, '0x2', 2], [{ number: FMT_NUMBER.BIGINT, bytes: FMT_BYTES.HEX }, '0x2', BigInt('2')], -]; \ No newline at end of file +]; diff --git a/packages/web3-net/test/integration/web3_net.test.ts b/packages/web3-net/test/integration/web3_net.test.ts index 60b0438f555..1d79a06b29d 100644 --- a/packages/web3-net/test/integration/web3_net.test.ts +++ b/packages/web3-net/test/integration/web3_net.test.ts @@ -40,8 +40,8 @@ describe('Web3 net', () => { it('should be able to get id', async () => { const networkId = await web3Net.getId(); - // eslint-disable-next-line jest/no-conditional-expect - expect(networkId).toBe(BigInt(1337)); + // eslint-disable-next-line jest/no-conditional-expect + expect(networkId).toBe(BigInt(1337)); }); it('should be able to listen', async () => { diff --git a/packages/web3-net/test/unit/rpc_method_wrappers.test.ts b/packages/web3-net/test/unit/rpc_method_wrappers.test.ts index e3f5bb9ad2a..47d014e2b3e 100644 --- a/packages/web3-net/test/unit/rpc_method_wrappers.test.ts +++ b/packages/web3-net/test/unit/rpc_method_wrappers.test.ts @@ -56,7 +56,6 @@ describe('rpc_method_wrappers', () => { }, ); }); - it('isListening', async () => { await isListening(web3Net); diff --git a/packages/web3-providers-http/CHANGELOG.md b/packages/web3-providers-http/CHANGELOG.md index 2169826c339..5705b0ae18d 100644 --- a/packages/web3-providers-http/CHANGELOG.md +++ b/packages/web3-providers-http/CHANGELOG.md @@ -133,6 +133,6 @@ Documentation: ### Added -- Added `statusCode` of response in ResponseError, `statusCode` is optional property in ResponseError. +- Added `statusCode` of response in ResponseError, `statusCode` is optional property in ResponseError. -## [Unreleased] \ No newline at end of file +## [Unreleased] diff --git a/packages/web3-providers-http/src/index.ts b/packages/web3-providers-http/src/index.ts index d596d1251f6..984be60033b 100644 --- a/packages/web3-providers-http/src/index.ts +++ b/packages/web3-providers-http/src/index.ts @@ -78,10 +78,10 @@ export default class HttpProvider< }, body: JSON.stringify(payload), }); - if (!response.ok) { + if (!response.ok) { // eslint-disable-next-line @typescript-eslint/no-unsafe-argument throw new ResponseError(await response.json(), undefined, undefined, response.status); - }; + } return (await response.json()) as JsonRpcResponseWithResult; } diff --git a/packages/web3-providers-ipc/CHANGELOG.md b/packages/web3-providers-ipc/CHANGELOG.md index 6f75b93995e..263a1241ea5 100644 --- a/packages/web3-providers-ipc/CHANGELOG.md +++ b/packages/web3-providers-ipc/CHANGELOG.md @@ -135,4 +135,4 @@ Documentation: - Fixed bug in chunks processing logic (#6496) -## [Unreleased] \ No newline at end of file +## [Unreleased] diff --git a/packages/web3-providers-ws/CHANGELOG.md b/packages/web3-providers-ws/CHANGELOG.md index 3dbc8c54694..61047ecb90a 100644 --- a/packages/web3-providers-ws/CHANGELOG.md +++ b/packages/web3-providers-ws/CHANGELOG.md @@ -134,4 +134,4 @@ Documentation: - Update dependancies (#7109) -## [Unreleased] \ No newline at end of file +## [Unreleased] diff --git a/packages/web3-providers-ws/test/integration/geth_fault_tolerance.test.ts b/packages/web3-providers-ws/test/integration/geth_fault_tolerance.test.ts index a047666dccb..fc9cb89d2ea 100644 --- a/packages/web3-providers-ws/test/integration/geth_fault_tolerance.test.ts +++ b/packages/web3-providers-ws/test/integration/geth_fault_tolerance.test.ts @@ -15,11 +15,15 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ -import { - HttpProvider -} from 'web3-providers-http'; +import { HttpProvider } from 'web3-providers-http'; import { ConnectionNotOpenError } from 'web3-errors'; -import { EthExecutionAPI, Web3APIPayload, SocketRequestItem, JsonRpcResponse, ProviderRpcError } from 'web3-types'; +import { + EthExecutionAPI, + Web3APIPayload, + SocketRequestItem, + JsonRpcResponse, + ProviderRpcError, +} from 'web3-types'; import { Web3DeferredPromise } from 'web3-utils'; import { waitForSocketConnect, @@ -38,14 +42,14 @@ describeIf(getSystemTestBackend() === 'geth' && isWs)('geth tests', () => { await httpProvider.request({ method: 'admin_startWS', id: '1', - jsonrpc: '2.0' - }) - } + jsonrpc: '2.0', + }); + }; const closeServer = async () => { await httpProvider.request({ method: 'admin_stopWS', id: '2', - jsonrpc: '2.0' + jsonrpc: '2.0', }); }; const jsonRpcPayload = { @@ -56,30 +60,29 @@ describeIf(getSystemTestBackend() === 'geth' && isWs)('geth tests', () => { // simulate abrupt disconnection, ganache server always closes with code 1000 so we need to simulate closing with different error code const changeCloseCode = async (webSocketProvider: WebSocketProvider) => - new Promise(resolve => { - // @ts-expect-error replace close handler - // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-param-reassign - webSocketProvider._onCloseHandler = (_: CloseEvent) => { - // @ts-expect-error replace close event - webSocketProvider._onCloseEvent({ code: 1003 }); - }; - // @ts-expect-error run protected method - webSocketProvider._removeSocketListeners(); - // @ts-expect-error run protected method - webSocketProvider._addSocketListeners(); - resolve(); - }); + new Promise(resolve => { + // @ts-expect-error replace close handler + // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-param-reassign + webSocketProvider._onCloseHandler = (_: CloseEvent) => { + // @ts-expect-error replace close event + webSocketProvider._onCloseEvent({ code: 1003 }); + }; + // @ts-expect-error run protected method + webSocketProvider._removeSocketListeners(); + // @ts-expect-error run protected method + webSocketProvider._addSocketListeners(); + resolve(); + }); beforeAll(() => { httpProvider = new HttpProvider(httpProviderUrl); - }) + }); beforeEach(async () => { await openServer(); - }) - afterAll(async() => { + }); + afterAll(async () => { await closeServer(); - }) - + }); describe('WebSocketProvider fault tests - geth', () => { it('"error" when there is no connection', async () => { @@ -104,11 +107,15 @@ describeIf(getSystemTestBackend() === 'geth' && isWs)('geth tests', () => { it('"discconect" handler fires if the server closes', async () => { await openServer(); const err = jest.fn(); - const webSocketProvider = new WebSocketProvider(wsProviderUrl, {}, { - delay: 100, - autoReconnect: false, - maxAttempts: 1, - }); + const webSocketProvider = new WebSocketProvider( + wsProviderUrl, + {}, + { + delay: 100, + autoReconnect: false, + maxAttempts: 1, + }, + ); await waitForSocketConnect(webSocketProvider); @@ -137,7 +144,7 @@ describeIf(getSystemTestBackend() === 'geth' && isWs)('geth tests', () => { }); webSocketProvider.once('disconnect', () => { mockDisconnect(); - }) + }); webSocketProvider.disconnect(); expect(mockReject).toHaveBeenCalledTimes(0); expect(mockDisconnect).toHaveBeenCalledTimes(1); @@ -287,10 +294,13 @@ describeIf(getSystemTestBackend() === 'geth' && isWs)('geth tests', () => { // when server is not listening send request, and expect that lib will try to reconnect and at end will throw con not open error await expect( - webSocketProvider.request( - {"method":"eth_getBlockByNumber","params":["0xc5043f",false],"id":1,"jsonrpc":"2.0"} - )) - .rejects.toThrow(ConnectionNotOpenError); + webSocketProvider.request({ + method: 'eth_getBlockByNumber', + params: ['0xc5043f', false], + id: 1, + jsonrpc: '2.0', + }), + ).rejects.toThrow(ConnectionNotOpenError); expect(mockCallBack).toHaveBeenCalled(); webSocketProvider.disconnect(); @@ -411,4 +421,4 @@ describeIf(getSystemTestBackend() === 'geth' && isWs)('geth tests', () => { await closeServer(); }); }); -}); \ No newline at end of file +}); diff --git a/packages/web3-providers-ws/test/integration/web_socket_provider_integration.test.ts b/packages/web3-providers-ws/test/integration/web_socket_provider_integration.test.ts index ccc1a97714f..3ca823acb6b 100644 --- a/packages/web3-providers-ws/test/integration/web_socket_provider_integration.test.ts +++ b/packages/web3-providers-ws/test/integration/web_socket_provider_integration.test.ts @@ -139,15 +139,18 @@ describeIf(isWs)('WebSocketProvider - implemented methods', () => { }); it('should error when no connection is established', async () => { - const wsProvider = new WebSocketProvider("ws://localhost:999",{}, { autoReconnect: false }); + const wsProvider = new WebSocketProvider( + 'ws://localhost:999', + {}, + { autoReconnect: false }, + ); let errored = false; - try{ + try { await wsProvider.request(jsonRpcPayload); // should not be able to reach here - - }catch(e){ + } catch (e) { // eslint-disable-next-line jest/no-conditional-expect - expect((e as any).message).toBe('Connection not open') + expect((e as any).message).toBe('Connection not open'); errored = true; } expect(errored).toBe(true); diff --git a/packages/web3-providers-ws/test/unit/__mocks__/isomorphic-ws.ts b/packages/web3-providers-ws/test/unit/__mocks__/isomorphic-ws.ts index d5e9d79cef9..0f5f07cbb7f 100644 --- a/packages/web3-providers-ws/test/unit/__mocks__/isomorphic-ws.ts +++ b/packages/web3-providers-ws/test/unit/__mocks__/isomorphic-ws.ts @@ -24,7 +24,7 @@ export default class WebSocket extends EventEmitter { public OPEN = 1; public constructor() { - super() + super(); // eslint-disable-next-line @typescript-eslint/no-unsafe-call // Connected state this.readyState = 1; @@ -43,11 +43,10 @@ export default class WebSocket extends EventEmitter { } public addEventListener(_event: any, _cb: () => void) { - this.on(_event, _cb) - + this.on(_event, _cb); } public removeEventListener(_event: any, _cb: () => void) { - this.off(_event, _cb) + this.off(_event, _cb); } } diff --git a/packages/web3-providers-ws/test/unit/check_implementation.test.ts b/packages/web3-providers-ws/test/unit/check_implementation.test.ts index 138855b9509..a437b1c7488 100644 --- a/packages/web3-providers-ws/test/unit/check_implementation.test.ts +++ b/packages/web3-providers-ws/test/unit/check_implementation.test.ts @@ -92,7 +92,7 @@ describe('WebSocketProvider', () => { const _onDisconnect = jest.fn(); // @ts-expect-error mock method ws._socketConnection.close = jest.fn(); - + // @ts-expect-error mock method ws._clearQueues = _clearQueues; // @ts-expect-error mock method @@ -126,7 +126,7 @@ describe('WebSocketProvider', () => { const ws = new WebSocketProvider('ws://localhost:8545'); // @ts-expect-error mock method ws._socketConnection.listeners = () => { - throw new Error('error'); + throw new Error('error'); }; const addEventListener = jest.fn(); // @ts-expect-error mock method @@ -147,6 +147,6 @@ describe('WebSocketProvider', () => { expect(removeEventListener).toHaveBeenCalledWith('open', ws._onOpenHandler); // @ts-expect-error mock method expect(removeEventListener).toHaveBeenCalledWith('close', ws._onCloseHandler); - }); + }); }); }); diff --git a/packages/web3-rpc-methods/CHANGELOG.md b/packages/web3-rpc-methods/CHANGELOG.md index 050b6451539..5cb444b1a83 100644 --- a/packages/web3-rpc-methods/CHANGELOG.md +++ b/packages/web3-rpc-methods/CHANGELOG.md @@ -144,4 +144,4 @@ Documentation: - Change `estimateGas` method to add possibility pass Transaction type (#7000) -## [Unreleased] \ No newline at end of file +## [Unreleased] diff --git a/packages/web3-rpc-methods/test/unit/eth_rpc_methods/get_uncle_by_block_number.test.ts b/packages/web3-rpc-methods/test/unit/eth_rpc_methods/get_uncle_by_block_number.test.ts index 93e8a633582..208a39ce5e1 100644 --- a/packages/web3-rpc-methods/test/unit/eth_rpc_methods/get_uncle_by_block_number.test.ts +++ b/packages/web3-rpc-methods/test/unit/eth_rpc_methods/get_uncle_by_block_number.test.ts @@ -31,12 +31,10 @@ describe('getUncleByBlockNumberAndIndex', () => { }); it('should call requestManager.send with eth_getUncleByBlockNumberAndIndex method', async () => { - await ethRpcMethods.getUncleByBlockNumberAndIndex(requestManager, 0, '1' ); - expect(requestManagerSendSpy).toHaveBeenCalledWith({ - method: 'eth_getUncleByBlockNumberAndIndex', - params: [0,'1'], - }); - }, - ); - + await ethRpcMethods.getUncleByBlockNumberAndIndex(requestManager, 0, '1'); + expect(requestManagerSendSpy).toHaveBeenCalledWith({ + method: 'eth_getUncleByBlockNumberAndIndex', + params: [0, '1'], + }); + }); }); diff --git a/packages/web3-rpc-methods/test/unit/personal_rpc_methods/eth_personal.test.ts b/packages/web3-rpc-methods/test/unit/personal_rpc_methods/eth_personal.test.ts index a487df07964..73bbe20eb4e 100644 --- a/packages/web3-rpc-methods/test/unit/personal_rpc_methods/eth_personal.test.ts +++ b/packages/web3-rpc-methods/test/unit/personal_rpc_methods/eth_personal.test.ts @@ -38,7 +38,7 @@ describe('Eth Personal', () => { }); it('should call requestManager.send with personal_newAccount method', async () => { - const pass = "ABC123"; + const pass = 'ABC123'; await personalRpcMethods.newAccount(requestManager, pass); expect(requestManagerSendSpy).toHaveBeenCalledWith({ method: 'personal_newAccount', @@ -47,8 +47,8 @@ describe('Eth Personal', () => { }); it('should call requestManager.send with personal_unlockAccount method', async () => { - const pass = "ABC123"; - const address = "0x4106486FB42F3Abf07CC07ef5DEE38f60319e789"; + const pass = 'ABC123'; + const address = '0x4106486FB42F3Abf07CC07ef5DEE38f60319e789'; const duration = 100; await personalRpcMethods.unlockAccount(requestManager, address, pass, duration); @@ -59,9 +59,9 @@ describe('Eth Personal', () => { }); it('should call requestManager.send with personal_lockAccount method', async () => { - const address = "0x4106486FB42F3Abf07CC07ef5DEE38f60319e789"; + const address = '0x4106486FB42F3Abf07CC07ef5DEE38f60319e789'; - await personalRpcMethods.lockAccount(requestManager, address ); + await personalRpcMethods.lockAccount(requestManager, address); expect(requestManagerSendSpy).toHaveBeenCalledWith({ method: 'personal_lockAccount', @@ -70,76 +70,77 @@ describe('Eth Personal', () => { }); it('should call requestManager.send with personal_importRawKey method', async () => { - const passPhrase = "123456"; - const keyData = "abe40cb08850da918ee951b237fa87946499b2d8643e4aa12b0610b050c731f6"; - await personalRpcMethods.importRawKey(requestManager, keyData, passPhrase ); + const passPhrase = '123456'; + const keyData = 'abe40cb08850da918ee951b237fa87946499b2d8643e4aa12b0610b050c731f6'; + await personalRpcMethods.importRawKey(requestManager, keyData, passPhrase); expect(requestManagerSendSpy).toHaveBeenCalledWith({ method: 'personal_importRawKey', - params: [keyData,passPhrase], + params: [keyData, passPhrase], }); }); it('should call requestManager.send with personal_sendTransaction method', async () => { - const passPhrase = "123456"; + const passPhrase = '123456'; const tx = { - from: "0x0d4aa485ecbc499c70860feb7e5aaeaf5fd8172e", - gasPrice: "20000", - gas: "21000", - to: "0x4106486FB42F3Abf07CC07ef5DEE38f60319e789", - value: "1000000", - data: "", - nonce: 0, - }; - await personalRpcMethods.sendTransaction(requestManager, tx, passPhrase ); + from: '0x0d4aa485ecbc499c70860feb7e5aaeaf5fd8172e', + gasPrice: '20000', + gas: '21000', + to: '0x4106486FB42F3Abf07CC07ef5DEE38f60319e789', + value: '1000000', + data: '', + nonce: 0, + }; + await personalRpcMethods.sendTransaction(requestManager, tx, passPhrase); expect(requestManagerSendSpy).toHaveBeenCalledWith({ method: 'personal_sendTransaction', - params: [tx,passPhrase], + params: [tx, passPhrase], }); }); it('should call requestManager.send with personal_signTransaction method', async () => { - const passPhrase = "123456"; + const passPhrase = '123456'; const tx = { - from: "0x0d4aa485ecbc499c70860feb7e5aaeaf5fd8172e", - gasPrice: "20000", - gas: "21000", - to: "0x4106486FB42F3Abf07CC07ef5DEE38f60319e789", - value: "1000000", - data: "", - nonce: 0, - }; - await personalRpcMethods.signTransaction(requestManager, tx, passPhrase ); + from: '0x0d4aa485ecbc499c70860feb7e5aaeaf5fd8172e', + gasPrice: '20000', + gas: '21000', + to: '0x4106486FB42F3Abf07CC07ef5DEE38f60319e789', + value: '1000000', + data: '', + nonce: 0, + }; + await personalRpcMethods.signTransaction(requestManager, tx, passPhrase); expect(requestManagerSendSpy).toHaveBeenCalledWith({ method: 'personal_signTransaction', - params: [tx,passPhrase], + params: [tx, passPhrase], }); }); it('should call requestManager.send with personal_sign method', async () => { - const data = "Hello world"; - const address = "0x0D4Aa485ECbC499c70860fEb7e5AaeAf5fd8172E"; - const pass = "123456"; + const data = 'Hello world'; + const address = '0x0D4Aa485ECbC499c70860fEb7e5AaeAf5fd8172E'; + const pass = '123456'; - await personalRpcMethods.sign(requestManager, data,address,pass); + await personalRpcMethods.sign(requestManager, data, address, pass); expect(requestManagerSendSpy).toHaveBeenCalledWith({ method: 'personal_sign', - params: [ data,address,pass], + params: [data, address, pass], }); }); it('should call requestManager.send with personal_ecRecover method', async () => { - const data = "Hello world"; - const signature = "0x5d21d01b3198ac34d0585a9d76c4d1c8123e5e06746c8962318a1c08ffb207596e6fce4a6f377b7c0fc98c5f646cd73438c80e8a1a95cbec55a84c2889dca0301b"; - - await personalRpcMethods.ecRecover(requestManager,data, signature); + const data = 'Hello world'; + const signature = + '0x5d21d01b3198ac34d0585a9d76c4d1c8123e5e06746c8962318a1c08ffb207596e6fce4a6f377b7c0fc98c5f646cd73438c80e8a1a95cbec55a84c2889dca0301b'; + + await personalRpcMethods.ecRecover(requestManager, data, signature); expect(requestManagerSendSpy).toHaveBeenCalledWith({ method: 'personal_ecRecover', - params: [ data, signature], + params: [data, signature], }); }); }); diff --git a/packages/web3-rpc-providers/CHANGELOG.md b/packages/web3-rpc-providers/CHANGELOG.md index 4943590a855..a9e2c2a8b79 100644 --- a/packages/web3-rpc-providers/CHANGELOG.md +++ b/packages/web3-rpc-providers/CHANGELOG.md @@ -39,17 +39,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- RC release +- RC release ## [1.0.0.rc.1] ### Added - - When error is returned with code 429, throw rate limit error (#7102) +- When error is returned with code 429, throw rate limit error (#7102) ### Changed - - Change request return type `Promise` to `Promise>` (#7102) +- Change request return type `Promise` to `Promise>` (#7102) ## [1.0.0-rc.2] @@ -58,4 +58,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Updated rate limit error of QuickNode provider for HTTP transport - Added optional `HttpProviderOptions | SocketOptions` in `Web3ExternalProvider` and `QuickNodeProvider` for provider configs -## [Unreleased] \ No newline at end of file +## [Unreleased] diff --git a/packages/web3-rpc-providers/README.md b/packages/web3-rpc-providers/README.md index 59284dbb29b..66ba07a4f87 100644 --- a/packages/web3-rpc-providers/README.md +++ b/packages/web3-rpc-providers/README.md @@ -11,7 +11,6 @@ This is a sub-package of [web3.js][repo]. - ## Installation You can install the package either using [NPM](https://www.npmjs.com/package/web3-rpc-providers) or using [Yarn](https://yarnpkg.com/package/web3-rpc-providers) diff --git a/packages/web3-rpc-providers/src/errors.ts b/packages/web3-rpc-providers/src/errors.ts index d698fbb66ab..0d849789f00 100644 --- a/packages/web3-rpc-providers/src/errors.ts +++ b/packages/web3-rpc-providers/src/errors.ts @@ -24,7 +24,10 @@ export class QuickNodeRateLimitError extends BaseWeb3Error { public code = ERR_QUICK_NODE_RATE_LIMIT; public constructor(error?: Error) { - super(`You've reach the rate limit of free RPC calls from our Partner Quick Nodes. There are two options you can either create a paid Quick Nodes account and get 20% off for 2 months using WEB3JS referral code, or use Free public RPC endpoint.`, error); + super( + `You've reach the rate limit of free RPC calls from our Partner Quick Nodes. There are two options you can either create a paid Quick Nodes account and get 20% off for 2 months using WEB3JS referral code, or use Free public RPC endpoint.`, + error, + ); } } @@ -36,4 +39,4 @@ export class ProviderConfigOptionsError extends BaseWeb3Error { super(`Invalid provider config options given for ${msg}`); } } -/* eslint-enable max-classes-per-file */ \ No newline at end of file +/* eslint-enable max-classes-per-file */ diff --git a/packages/web3-rpc-providers/src/index.ts b/packages/web3-rpc-providers/src/index.ts index 637cdae4cc0..577d8e6b960 100644 --- a/packages/web3-rpc-providers/src/index.ts +++ b/packages/web3-rpc-providers/src/index.ts @@ -23,4 +23,4 @@ export * from './web3_provider.js'; export * from './errors.js'; // default providers -export const mainnet = new QuickNodeProvider(); \ No newline at end of file +export const mainnet = new QuickNodeProvider(); diff --git a/packages/web3-rpc-providers/src/types.ts b/packages/web3-rpc-providers/src/types.ts index e23714977c1..9fda306ae0d 100644 --- a/packages/web3-rpc-providers/src/types.ts +++ b/packages/web3-rpc-providers/src/types.ts @@ -15,39 +15,39 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ -import {ClientOptions, ClientRequestArgs} from "web3-providers-ws"; +import { ClientOptions, ClientRequestArgs } from 'web3-providers-ws'; import { ReconnectOptions } from 'web3-utils'; export enum Transport { - HTTPS = "https", - WebSocket = "wss" -}; + HTTPS = 'https', + WebSocket = 'wss', +} export enum Network { - ETH_MAINNET = "eth_mainnet", - ETH_GOERLI = "eth_goerli", - ETH_SEPOLIA = "eth_sepolia", - ETH_HOLESKY = "eth_holesky", + ETH_MAINNET = 'eth_mainnet', + ETH_GOERLI = 'eth_goerli', + ETH_SEPOLIA = 'eth_sepolia', + ETH_HOLESKY = 'eth_holesky', - POLYGON_MAINNET= "polygon_mainnet", - POLYGON_MUMBAI= "polygon_mumbai", - POLYGON_AMONY= "polygon_amony", + POLYGON_MAINNET = 'polygon_mainnet', + POLYGON_MUMBAI = 'polygon_mumbai', + POLYGON_AMONY = 'polygon_amony', - ARBITRUM_MAINNET = "arbitrum_mainnet", - ARBITRUM_SEPOLIA = "arbitrum_sepolia", + ARBITRUM_MAINNET = 'arbitrum_mainnet', + ARBITRUM_SEPOLIA = 'arbitrum_sepolia', - BASE_MAINNET = "base_mainnet", - BASE_SEPOLIA = "base_sepolia", + BASE_MAINNET = 'base_mainnet', + BASE_SEPOLIA = 'base_sepolia', - OPTIMISM_MAINNET = "optimism_mainnet", - OPTIMISM_SEPOLIA = "optimism_sepolia", + OPTIMISM_MAINNET = 'optimism_mainnet', + OPTIMISM_SEPOLIA = 'optimism_sepolia', - BNB_MAINNET = "bnb_mainnet", - BNB_TESTNET = "bnb_testnet" -}; + BNB_MAINNET = 'bnb_mainnet', + BNB_TESTNET = 'bnb_testnet', +} // Combining the ws types export type SocketOptions = { - socketOptions?: ClientOptions | ClientRequestArgs; - reconnectOptions?: Partial; -}; \ No newline at end of file + socketOptions?: ClientOptions | ClientRequestArgs; + reconnectOptions?: Partial; +}; diff --git a/packages/web3-rpc-providers/src/web3_provider.ts b/packages/web3-rpc-providers/src/web3_provider.ts index 498dec60433..922d8217256 100644 --- a/packages/web3-rpc-providers/src/web3_provider.ts +++ b/packages/web3-rpc-providers/src/web3_provider.ts @@ -15,20 +15,28 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ -import HttpProvider, { HttpProviderOptions } from "web3-providers-http"; -import WebSocketProvider from "web3-providers-ws"; +import HttpProvider, { HttpProviderOptions } from 'web3-providers-http'; +import WebSocketProvider from 'web3-providers-ws'; import { - EthExecutionAPI, JsonRpcResult, ProviderConnectInfo, ProviderMessage, - ProviderRpcError, Web3APIMethod, Web3APIPayload, Web3APIReturnType, Web3APISpec, Web3BaseProvider, - Web3Eip1193ProviderEventCallback, - Web3ProviderEventCallback, - Web3ProviderMessageEventCallback, - Web3ProviderStatus, - JsonRpcResponseWithResult, -} from "web3-types"; -import { Eip1193Provider } from "web3-utils"; -import { Transport, Network, SocketOptions } from "./types.js"; -import { ProviderConfigOptionsError } from "./errors.js"; + EthExecutionAPI, + JsonRpcResult, + ProviderConnectInfo, + ProviderMessage, + ProviderRpcError, + Web3APIMethod, + Web3APIPayload, + Web3APIReturnType, + Web3APISpec, + Web3BaseProvider, + Web3Eip1193ProviderEventCallback, + Web3ProviderEventCallback, + Web3ProviderMessageEventCallback, + Web3ProviderStatus, + JsonRpcResponseWithResult, +} from 'web3-types'; +import { Eip1193Provider } from 'web3-utils'; +import { Transport, Network, SocketOptions } from './types.js'; +import { ProviderConfigOptionsError } from './errors.js'; /* This class can be used to create new providers only when there is custom logic required in each Request method like @@ -39,120 +47,167 @@ no additional logic implementation is required in the provider. */ export abstract class Web3ExternalProvider< - API extends Web3APISpec = EthExecutionAPI, + API extends Web3APISpec = EthExecutionAPI, > extends Eip1193Provider { - - public provider!: Web3BaseProvider; - public readonly transport: Transport; - - public abstract getRPCURL(network: Network, transport: Transport, token: string, host: string): string; - - public constructor( - network: Network, - transport: Transport, - token: string, - host: string, - providerConfigOptions?: HttpProviderOptions | SocketOptions) { - - super(); - - if(providerConfigOptions!== undefined && - transport === Transport.HTTPS && - !('providerOptions' in providerConfigOptions)){ - - throw new ProviderConfigOptionsError("HTTP Provider"); - } - else if(providerConfigOptions!== undefined && - transport === Transport.WebSocket && - !( 'socketOptions' in providerConfigOptions || - 'reconnectOptions' in providerConfigOptions - )){ - throw new ProviderConfigOptionsError("Websocket Provider"); - } - - this.transport = transport; - if (transport === Transport.HTTPS) { - this.provider = new HttpProvider( - this.getRPCURL(network, transport, token, host), - providerConfigOptions as HttpProviderOptions); - } - else if (transport === Transport.WebSocket) { - this.provider = new WebSocketProvider( - this.getRPCURL(network, transport, token, host), - (providerConfigOptions as SocketOptions)?.socketOptions, - (providerConfigOptions as SocketOptions)?.reconnectOptions); - } - } - - public async request< - Method extends Web3APIMethod, - ResultType = Web3APIReturnType, - >( - payload: Web3APIPayload, - requestOptions?: RequestInit, - ): Promise> { - - if (this.transport === Transport.HTTPS) { - return await ((this.provider as HttpProvider).request(payload, requestOptions)) as unknown as JsonRpcResponseWithResult; - } - - return (this.provider as WebSocketProvider).request(payload); - - } - - public getStatus(): Web3ProviderStatus { - return this.provider.getStatus(); - } - public supportsSubscriptions(): boolean { - return this.provider.supportsSubscriptions(); - } - public once(type: "disconnect", listener: Web3Eip1193ProviderEventCallback): void; - public once(type: string, listener: Web3Eip1193ProviderEventCallback | Web3ProviderEventCallback): void; - public once(type: "connect", listener: Web3Eip1193ProviderEventCallback): void; - public once(type: "chainChanged", listener: Web3Eip1193ProviderEventCallback): void; - public once(type: "accountsChanged", listener: Web3Eip1193ProviderEventCallback): void; - public once(_type: string, _listener: unknown): void { - if (this.provider?.once) - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - this.provider.once(_type, _listener as any); - } - public removeAllListeners?(_type: string): void { - if (this.provider?.removeAllListeners) - this.provider.removeAllListeners(_type); - } - public connect(): void { - if (this.provider?.connect) - this.provider.connect(); - } - public disconnect(_code?: number | undefined, _data?: string | undefined): void { - if (this.provider?.disconnect) - this.provider.disconnect(_code, _data); - } - public reset(): void { - if (this.provider?.reset) - this.provider.reset(); - } - - public on(type: "disconnect", listener: Web3Eip1193ProviderEventCallback): void; - public on(type: string, listener: Web3Eip1193ProviderEventCallback | Web3ProviderMessageEventCallback): void; - public on(type: string, listener: Web3Eip1193ProviderEventCallback | Web3ProviderMessageEventCallback): void; - public on(type: "connect", listener: Web3Eip1193ProviderEventCallback): void; - public on(type: "chainChanged", listener: Web3Eip1193ProviderEventCallback): void; - public on(type: "accountsChanged", listener: Web3Eip1193ProviderEventCallback): void; - public on(_type: unknown, _listener: unknown): void { - if (this.provider) - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - this.provider.on(_type as any, _listener as any); - } - public removeListener(type: "disconnect", listener: Web3Eip1193ProviderEventCallback): void; - public removeListener(type: string, listener: Web3Eip1193ProviderEventCallback | Web3ProviderEventCallback): void; - public removeListener(type: "connect", listener: Web3Eip1193ProviderEventCallback): void; - public removeListener(type: "chainChanged", listener: Web3Eip1193ProviderEventCallback): void; - public removeListener(type: "accountsChanged", listener: Web3Eip1193ProviderEventCallback): void; - public removeListener(_type: unknown, _listener: unknown): void { - if (this.provider) - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - this.provider.removeListener(_type as any, _listener as any); - } + public provider!: Web3BaseProvider; + public readonly transport: Transport; + + public abstract getRPCURL( + network: Network, + transport: Transport, + token: string, + host: string, + ): string; + + public constructor( + network: Network, + transport: Transport, + token: string, + host: string, + providerConfigOptions?: HttpProviderOptions | SocketOptions, + ) { + super(); + + if ( + providerConfigOptions !== undefined && + transport === Transport.HTTPS && + !('providerOptions' in providerConfigOptions) + ) { + throw new ProviderConfigOptionsError('HTTP Provider'); + } else if ( + providerConfigOptions !== undefined && + transport === Transport.WebSocket && + !( + 'socketOptions' in providerConfigOptions || + 'reconnectOptions' in providerConfigOptions + ) + ) { + throw new ProviderConfigOptionsError('Websocket Provider'); + } + + this.transport = transport; + if (transport === Transport.HTTPS) { + this.provider = new HttpProvider( + this.getRPCURL(network, transport, token, host), + providerConfigOptions as HttpProviderOptions, + ); + } else if (transport === Transport.WebSocket) { + this.provider = new WebSocketProvider( + this.getRPCURL(network, transport, token, host), + (providerConfigOptions as SocketOptions)?.socketOptions, + (providerConfigOptions as SocketOptions)?.reconnectOptions, + ); + } + } + + public async request< + Method extends Web3APIMethod, + ResultType = Web3APIReturnType, + >( + payload: Web3APIPayload, + requestOptions?: RequestInit, + ): Promise> { + if (this.transport === Transport.HTTPS) { + return (await (this.provider as HttpProvider).request( + payload, + requestOptions, + )) as unknown as JsonRpcResponseWithResult; + } + + return (this.provider as WebSocketProvider).request(payload); + } + + public getStatus(): Web3ProviderStatus { + return this.provider.getStatus(); + } + public supportsSubscriptions(): boolean { + return this.provider.supportsSubscriptions(); + } + public once( + type: 'disconnect', + listener: Web3Eip1193ProviderEventCallback, + ): void; + public once( + type: string, + listener: Web3Eip1193ProviderEventCallback | Web3ProviderEventCallback, + ): void; + public once( + type: 'connect', + listener: Web3Eip1193ProviderEventCallback, + ): void; + public once(type: 'chainChanged', listener: Web3Eip1193ProviderEventCallback): void; + public once( + type: 'accountsChanged', + listener: Web3Eip1193ProviderEventCallback, + ): void; + public once(_type: string, _listener: unknown): void { + if (this.provider?.once) + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + this.provider.once(_type, _listener as any); + } + public removeAllListeners?(_type: string): void { + if (this.provider?.removeAllListeners) this.provider.removeAllListeners(_type); + } + public connect(): void { + if (this.provider?.connect) this.provider.connect(); + } + public disconnect(_code?: number | undefined, _data?: string | undefined): void { + if (this.provider?.disconnect) this.provider.disconnect(_code, _data); + } + public reset(): void { + if (this.provider?.reset) this.provider.reset(); + } + + public on( + type: 'disconnect', + listener: Web3Eip1193ProviderEventCallback, + ): void; + public on( + type: string, + listener: + | Web3Eip1193ProviderEventCallback + | Web3ProviderMessageEventCallback, + ): void; + public on( + type: string, + listener: + | Web3Eip1193ProviderEventCallback + | Web3ProviderMessageEventCallback, + ): void; + public on( + type: 'connect', + listener: Web3Eip1193ProviderEventCallback, + ): void; + public on(type: 'chainChanged', listener: Web3Eip1193ProviderEventCallback): void; + public on(type: 'accountsChanged', listener: Web3Eip1193ProviderEventCallback): void; + public on(_type: unknown, _listener: unknown): void { + if (this.provider) + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + this.provider.on(_type as any, _listener as any); + } + public removeListener( + type: 'disconnect', + listener: Web3Eip1193ProviderEventCallback, + ): void; + public removeListener( + type: string, + listener: Web3Eip1193ProviderEventCallback | Web3ProviderEventCallback, + ): void; + public removeListener( + type: 'connect', + listener: Web3Eip1193ProviderEventCallback, + ): void; + public removeListener( + type: 'chainChanged', + listener: Web3Eip1193ProviderEventCallback, + ): void; + public removeListener( + type: 'accountsChanged', + listener: Web3Eip1193ProviderEventCallback, + ): void; + public removeListener(_type: unknown, _listener: unknown): void { + if (this.provider) + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + this.provider.removeListener(_type as any, _listener as any); + } } - diff --git a/packages/web3-rpc-providers/src/web3_provider_quicknode.ts b/packages/web3-rpc-providers/src/web3_provider_quicknode.ts index 459cf5d5d38..ae74fa49860 100644 --- a/packages/web3-rpc-providers/src/web3_provider_quicknode.ts +++ b/packages/web3-rpc-providers/src/web3_provider_quicknode.ts @@ -15,98 +15,106 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ -import { EthExecutionAPI, JsonRpcResponseWithResult, Web3APIMethod, Web3APIPayload, Web3APIReturnType, Web3APISpec } from "web3-types"; -import { ResponseError } from "web3-errors"; -import { HttpProviderOptions } from "web3-providers-http"; -import { Transport, Network, SocketOptions } from "./types.js"; -import { Web3ExternalProvider } from "./web3_provider.js"; -import { QuickNodeRateLimitError } from "./errors.js"; +import { + EthExecutionAPI, + JsonRpcResponseWithResult, + Web3APIMethod, + Web3APIPayload, + Web3APIReturnType, + Web3APISpec, +} from 'web3-types'; +import { ResponseError } from 'web3-errors'; +import { HttpProviderOptions } from 'web3-providers-http'; +import { Transport, Network, SocketOptions } from './types.js'; +import { Web3ExternalProvider } from './web3_provider.js'; +import { QuickNodeRateLimitError } from './errors.js'; const isValid = (str: string) => str !== undefined && str.trim().length > 0; export class QuickNodeProvider< -API extends Web3APISpec = EthExecutionAPI, + API extends Web3APISpec = EthExecutionAPI, > extends Web3ExternalProvider { - - // eslint-disable-next-line default-param-last - public constructor( network: Network = Network.ETH_MAINNET, transport: Transport = Transport.HTTPS, token = "", host = "", providerConfigOptions?: HttpProviderOptions | SocketOptions) { - - super(network, transport, token, host, providerConfigOptions); - - } - - public async request< - Method extends Web3APIMethod, - ResultType = Web3APIReturnType, - >( - payload: Web3APIPayload, - requestOptions?: RequestInit, - ): Promise> { - - try { - return await super.request(payload, requestOptions); - } catch (error) { - if (error instanceof ResponseError && error.statusCode === 429){ - throw new QuickNodeRateLimitError(error); - } - throw error; - } - } - - // eslint-disable-next-line class-methods-use-this - public getRPCURL(network: Network, - transport: Transport, - _token: string, - _host: string) { - - let host = ""; - let token = ""; - - switch (network) { - case Network.ETH_MAINNET: - host = isValid(_host) ? _host : "powerful-holy-bush.quiknode.pro"; - token = isValid(_token) ? _token : "3240624a343867035925ff7561eb60dfdba2a668"; - break; - case Network.ETH_SEPOLIA: - host = isValid(_host) ? _host : "dimensional-fabled-glitter.ethereum-sepolia.quiknode.pro"; - token = isValid(_token) ? _token : "382a3b5a4b938f2d6e8686c19af4b22921fde2cd"; - break - case Network.ETH_HOLESKY: - host = isValid(_host) ? _host : "yolo-morning-card.ethereum-holesky.quiknode.pro"; - token = isValid(_token) ? _token : "481ebe70638c4dcf176af617a16d02ab866b9af9"; - break; - - case Network.ARBITRUM_MAINNET: - host = isValid(_host) ? _host : "autumn-divine-dinghy.arbitrum-mainnet.quiknode.pro"; - token = isValid(_token) ? _token : "a5d7bfbf60b5ae9ce3628e53d69ef50d529e9a8c"; - break; - case Network.ARBITRUM_SEPOLIA: - host = isValid(_host) ? _host : "few-patient-pond.arbitrum-sepolia.quiknode.pro"; - token = isValid(_token) ? _token : "3be985450970628c860b959c65cd2642dcafe53c"; - break; - - case Network.BNB_MAINNET: - host = isValid(_host) ? _host : "purple-empty-reel.bsc.quiknode.pro"; - token = isValid(_token) ? _token : "ebf6c532961e21f092ff2facce1ec4c89c540158"; - break; - case Network.BNB_TESTNET: - host = isValid(_host) ? _host : "floral-rough-scion.bsc-testnet.quiknode.pro"; - token = isValid(_token) ? _token : "5b297e5acff5f81f4c37ebf6f235f7299b6f9d28"; - break; - - case Network.POLYGON_MAINNET: - host = isValid(_host) ? _host : "small-chaotic-moon.matic.quiknode.pro"; - token = isValid(_token) ? _token : "847569f8a017e84d985e10d0f44365d965a951f1"; - break; - case Network.POLYGON_AMONY: - host = isValid(_host) ? _host : "prettiest-side-shape.matic-amoy.quiknode.pro"; - token = isValid(_token) ? _token : "79a9476eea661d4f82de614db1d8a895b14b881c"; - break; - default: - throw new Error("Network info not avalible."); - } - - return `${transport}://${host}/${token}`; - } + // eslint-disable-next-line default-param-last + public constructor( + network: Network = Network.ETH_MAINNET, + transport: Transport = Transport.HTTPS, + token = '', + host = '', + providerConfigOptions?: HttpProviderOptions | SocketOptions, + ) { + super(network, transport, token, host, providerConfigOptions); + } + + public async request< + Method extends Web3APIMethod, + ResultType = Web3APIReturnType, + >( + payload: Web3APIPayload, + requestOptions?: RequestInit, + ): Promise> { + try { + return await super.request(payload, requestOptions); + } catch (error) { + if (error instanceof ResponseError && error.statusCode === 429) { + throw new QuickNodeRateLimitError(error); + } + throw error; + } + } + + // eslint-disable-next-line class-methods-use-this + public getRPCURL(network: Network, transport: Transport, _token: string, _host: string) { + let host = ''; + let token = ''; + + switch (network) { + case Network.ETH_MAINNET: + host = isValid(_host) ? _host : 'powerful-holy-bush.quiknode.pro'; + token = isValid(_token) ? _token : '3240624a343867035925ff7561eb60dfdba2a668'; + break; + case Network.ETH_SEPOLIA: + host = isValid(_host) + ? _host + : 'dimensional-fabled-glitter.ethereum-sepolia.quiknode.pro'; + token = isValid(_token) ? _token : '382a3b5a4b938f2d6e8686c19af4b22921fde2cd'; + break; + case Network.ETH_HOLESKY: + host = isValid(_host) ? _host : 'yolo-morning-card.ethereum-holesky.quiknode.pro'; + token = isValid(_token) ? _token : '481ebe70638c4dcf176af617a16d02ab866b9af9'; + break; + + case Network.ARBITRUM_MAINNET: + host = isValid(_host) + ? _host + : 'autumn-divine-dinghy.arbitrum-mainnet.quiknode.pro'; + token = isValid(_token) ? _token : 'a5d7bfbf60b5ae9ce3628e53d69ef50d529e9a8c'; + break; + case Network.ARBITRUM_SEPOLIA: + host = isValid(_host) ? _host : 'few-patient-pond.arbitrum-sepolia.quiknode.pro'; + token = isValid(_token) ? _token : '3be985450970628c860b959c65cd2642dcafe53c'; + break; + + case Network.BNB_MAINNET: + host = isValid(_host) ? _host : 'purple-empty-reel.bsc.quiknode.pro'; + token = isValid(_token) ? _token : 'ebf6c532961e21f092ff2facce1ec4c89c540158'; + break; + case Network.BNB_TESTNET: + host = isValid(_host) ? _host : 'floral-rough-scion.bsc-testnet.quiknode.pro'; + token = isValid(_token) ? _token : '5b297e5acff5f81f4c37ebf6f235f7299b6f9d28'; + break; + + case Network.POLYGON_MAINNET: + host = isValid(_host) ? _host : 'small-chaotic-moon.matic.quiknode.pro'; + token = isValid(_token) ? _token : '847569f8a017e84d985e10d0f44365d965a951f1'; + break; + case Network.POLYGON_AMONY: + host = isValid(_host) ? _host : 'prettiest-side-shape.matic-amoy.quiknode.pro'; + token = isValid(_token) ? _token : '79a9476eea661d4f82de614db1d8a895b14b881c'; + break; + default: + throw new Error('Network info not avalible.'); + } + + return `${transport}://${host}/${token}`; + } } - diff --git a/packages/web3-rpc-providers/test/unit/constructor.test.ts b/packages/web3-rpc-providers/test/unit/constructor.test.ts index 16133129d55..cc34cb1fcd3 100644 --- a/packages/web3-rpc-providers/test/unit/constructor.test.ts +++ b/packages/web3-rpc-providers/test/unit/constructor.test.ts @@ -15,7 +15,6 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ - import HttpProvider, { HttpProviderOptions } from 'web3-providers-http'; import WebSocketProvider from 'web3-providers-ws'; import WebSocket from 'isomorphic-ws'; @@ -26,136 +25,222 @@ import { ProviderConfigOptionsError } from '../../src/errors'; // Mock implementation so ws doesnt have openhandle after test exits as it attempts to connects at start jest.mock('isomorphic-ws', () => { - return { - __esModule: true, - default: jest.fn().mockImplementation(() => { - // eslint-disable-next-line @typescript-eslint/ban-types - const eventListeners: { [key: string]: Function[] } = {}; - - return { - addEventListener: jest.fn((event, handler) => { - if (!eventListeners[event]) { - eventListeners[event] = []; - } - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - eventListeners[event].push(handler); - }), - removeEventListener: jest.fn((event, handler) => { - if (eventListeners[event]) { - eventListeners[event] = eventListeners[event].filter(h => h !== handler); - } - }), - dispatchEvent: jest.fn((event) => { - const eventType = event.type; - if (eventListeners[eventType]) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - eventListeners[eventType].forEach(handler => handler(event)); - } - }), - close: jest.fn(), - send: jest.fn(), - readyState: WebSocket.OPEN, - }; - }), - }; + return { + __esModule: true, + default: jest.fn().mockImplementation(() => { + // eslint-disable-next-line @typescript-eslint/ban-types + const eventListeners: { [key: string]: Function[] } = {}; + + return { + addEventListener: jest.fn((event, handler) => { + if (!eventListeners[event]) { + eventListeners[event] = []; + } + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + eventListeners[event].push(handler); + }), + removeEventListener: jest.fn((event, handler) => { + if (eventListeners[event]) { + eventListeners[event] = eventListeners[event].filter(h => h !== handler); + } + }), + dispatchEvent: jest.fn(event => { + const eventType = event.type; + if (eventListeners[eventType]) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + eventListeners[eventType].forEach(handler => handler(event)); + } + }), + close: jest.fn(), + send: jest.fn(), + readyState: WebSocket.OPEN, + }; + }), + }; }); class MockWeb3ExternalProviderA extends Web3ExternalProvider { - public constructor(network: Network, transport: Transport, token: string, host?: string, providerConfigOptions?: HttpProviderOptions | SocketOptions) { - super(network, transport, token, host ?? "", providerConfigOptions); - } - // eslint-disable-next-line class-methods-use-this - public getRPCURL(_network: Network, _transport: Transport, _token: string, _host = ""): string { - let transport = ""; - if (_transport === Transport.HTTPS) - transport = "http://"; - else if (_transport === Transport.WebSocket) - transport = "wss://"; - - return `${transport}127.0.0.1/`; - } + public constructor( + network: Network, + transport: Transport, + token: string, + host?: string, + providerConfigOptions?: HttpProviderOptions | SocketOptions, + ) { + super(network, transport, token, host ?? '', providerConfigOptions); + } + // eslint-disable-next-line class-methods-use-this + public getRPCURL(_network: Network, _transport: Transport, _token: string, _host = ''): string { + let transport = ''; + if (_transport === Transport.HTTPS) transport = 'http://'; + else if (_transport === Transport.WebSocket) transport = 'wss://'; + + return `${transport}127.0.0.1/`; + } } describe('Web3ExternalProvider', () => { - const network: Network = Network.ETH_MAINNET; - const transport: Transport = Transport.HTTPS; - const token = 'test-token'; - const host = 'test-host'; - - it('should initialize the provider correctly', () => { - - const provider = new MockWeb3ExternalProviderA(network, transport, token); - - expect(provider.provider).toBeInstanceOf(HttpProvider); - }); - - it('should initialize the provider with WebSocketProvider for WebSocket transport', () => { - const transport1: Transport = Transport.WebSocket; - - const provider = new MockWeb3ExternalProviderA(network, transport1, token); - expect(provider.provider).toBeInstanceOf(WebSocketProvider); - }); - - it('should throw ProviderConfigOptionsError for HTTP provider with missing providerOptions', () => { - const providerConfigOptions: HttpProviderOptions | SocketOptions = { /* missing providerOptions */ }; - expect(() => new MockWeb3ExternalProviderA(network, transport, token, host, providerConfigOptions)).toThrow(ProviderConfigOptionsError); - }); - - it('should throw ProviderConfigOptionsError for HTTP provider with WS providerOptions', () => { - const providerConfigOptions: SocketOptions = { - socketOptions: { /* options */ }, - reconnectOptions: { /* options */ }, - }; - expect(() => new MockWeb3ExternalProviderA(network, transport, token, host, providerConfigOptions)).toThrow(ProviderConfigOptionsError); - }); - - it('should throw ProviderConfigOptionsError for WebSocket provider with missing socketOptions and reconnectOptions', () => { - const providerConfigOptions: HttpProviderOptions | SocketOptions = { /* missing socketOptions and reconnectOptions */ }; - expect(() => new MockWeb3ExternalProviderA(network, Transport.WebSocket, token, host, providerConfigOptions)).toThrow(ProviderConfigOptionsError); - }); - - it('should throw ProviderConfigOptionsError for WebSocket provider with HTTP options', () => { - const providerConfigOptions: HttpProviderOptions = { providerOptions: { /* options */ } }; - expect(() => new MockWeb3ExternalProviderA(network, Transport.WebSocket, token, host, providerConfigOptions)).toThrow(ProviderConfigOptionsError); - }); - - it('should create provider instance and not throw ProviderConfigOptionsError for WebSocket provider with missing reconnectOptions', () => { - const providerConfigOptions: SocketOptions = { - socketOptions: { /* options */ }, - }; - - // Create an instance of the MockWeb3ExternalProviderA - const provider = new MockWeb3ExternalProviderA(network, Transport.WebSocket, token, host, providerConfigOptions); - - // Expect that the provider is created successfully - expect(provider).toBeInstanceOf(MockWeb3ExternalProviderA); - }); - - it('should create provider instance and not throw ProviderConfigOptionsError for WebSocket provider with missing socketOptions', () => { - const providerConfigOptions: SocketOptions = { - reconnectOptions: { /* options */ }, - }; - - // Create an instance of the MockWeb3ExternalProviderA - const provider = new MockWeb3ExternalProviderA(network, Transport.WebSocket, token, host, providerConfigOptions); - - // Expect that the provider is created successfully - expect(provider).toBeInstanceOf(MockWeb3ExternalProviderA); - }); - - it('should create an HttpProvider with providerOptions', () => { - const providerConfigOptions: HttpProviderOptions = { providerOptions: { /* options */ } }; - const provider = new MockWeb3ExternalProviderA(network, transport, token, host, providerConfigOptions); - expect(provider.provider).toBeInstanceOf(HttpProvider); - }); - - it('should create a WebSocketProvider with socketOptions and reconnectOptions', () => { - const providerConfigOptions: SocketOptions = { - socketOptions: { /* options */ }, - reconnectOptions: { /* options */ }, - }; - const provider = new MockWeb3ExternalProviderA(network, Transport.WebSocket, token, host, providerConfigOptions); - expect(provider.provider).toBeInstanceOf(WebSocketProvider); - }); + const network: Network = Network.ETH_MAINNET; + const transport: Transport = Transport.HTTPS; + const token = 'test-token'; + const host = 'test-host'; + + it('should initialize the provider correctly', () => { + const provider = new MockWeb3ExternalProviderA(network, transport, token); + + expect(provider.provider).toBeInstanceOf(HttpProvider); + }); + + it('should initialize the provider with WebSocketProvider for WebSocket transport', () => { + const transport1: Transport = Transport.WebSocket; + + const provider = new MockWeb3ExternalProviderA(network, transport1, token); + expect(provider.provider).toBeInstanceOf(WebSocketProvider); + }); + + it('should throw ProviderConfigOptionsError for HTTP provider with missing providerOptions', () => { + const providerConfigOptions: HttpProviderOptions | SocketOptions = { + /* missing providerOptions */ + }; + expect( + () => + new MockWeb3ExternalProviderA( + network, + transport, + token, + host, + providerConfigOptions, + ), + ).toThrow(ProviderConfigOptionsError); + }); + + it('should throw ProviderConfigOptionsError for HTTP provider with WS providerOptions', () => { + const providerConfigOptions: SocketOptions = { + socketOptions: { + /* options */ + }, + reconnectOptions: { + /* options */ + }, + }; + expect( + () => + new MockWeb3ExternalProviderA( + network, + transport, + token, + host, + providerConfigOptions, + ), + ).toThrow(ProviderConfigOptionsError); + }); + + it('should throw ProviderConfigOptionsError for WebSocket provider with missing socketOptions and reconnectOptions', () => { + const providerConfigOptions: HttpProviderOptions | SocketOptions = { + /* missing socketOptions and reconnectOptions */ + }; + expect( + () => + new MockWeb3ExternalProviderA( + network, + Transport.WebSocket, + token, + host, + providerConfigOptions, + ), + ).toThrow(ProviderConfigOptionsError); + }); + + it('should throw ProviderConfigOptionsError for WebSocket provider with HTTP options', () => { + const providerConfigOptions: HttpProviderOptions = { + providerOptions: { + /* options */ + }, + }; + expect( + () => + new MockWeb3ExternalProviderA( + network, + Transport.WebSocket, + token, + host, + providerConfigOptions, + ), + ).toThrow(ProviderConfigOptionsError); + }); + + it('should create provider instance and not throw ProviderConfigOptionsError for WebSocket provider with missing reconnectOptions', () => { + const providerConfigOptions: SocketOptions = { + socketOptions: { + /* options */ + }, + }; + + // Create an instance of the MockWeb3ExternalProviderA + const provider = new MockWeb3ExternalProviderA( + network, + Transport.WebSocket, + token, + host, + providerConfigOptions, + ); + + // Expect that the provider is created successfully + expect(provider).toBeInstanceOf(MockWeb3ExternalProviderA); + }); + + it('should create provider instance and not throw ProviderConfigOptionsError for WebSocket provider with missing socketOptions', () => { + const providerConfigOptions: SocketOptions = { + reconnectOptions: { + /* options */ + }, + }; + + // Create an instance of the MockWeb3ExternalProviderA + const provider = new MockWeb3ExternalProviderA( + network, + Transport.WebSocket, + token, + host, + providerConfigOptions, + ); + + // Expect that the provider is created successfully + expect(provider).toBeInstanceOf(MockWeb3ExternalProviderA); + }); + + it('should create an HttpProvider with providerOptions', () => { + const providerConfigOptions: HttpProviderOptions = { + providerOptions: { + /* options */ + }, + }; + const provider = new MockWeb3ExternalProviderA( + network, + transport, + token, + host, + providerConfigOptions, + ); + expect(provider.provider).toBeInstanceOf(HttpProvider); + }); + + it('should create a WebSocketProvider with socketOptions and reconnectOptions', () => { + const providerConfigOptions: SocketOptions = { + socketOptions: { + /* options */ + }, + reconnectOptions: { + /* options */ + }, + }; + const provider = new MockWeb3ExternalProviderA( + network, + Transport.WebSocket, + token, + host, + providerConfigOptions, + ); + expect(provider.provider).toBeInstanceOf(WebSocketProvider); + }); }); - diff --git a/packages/web3-rpc-providers/test/unit/request.test.ts b/packages/web3-rpc-providers/test/unit/request.test.ts index 6107949b0f1..3de14fc0513 100644 --- a/packages/web3-rpc-providers/test/unit/request.test.ts +++ b/packages/web3-rpc-providers/test/unit/request.test.ts @@ -14,113 +14,112 @@ 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 { Web3APIPayload, EthExecutionAPI, Web3APIMethod, JsonRpcResponse } from "web3-types"; -import { ResponseError } from "web3-errors"; -import { Network, Transport } from "../../src/types"; -import { Web3ExternalProvider } from "../../src/web3_provider"; +import { Web3APIPayload, EthExecutionAPI, Web3APIMethod, JsonRpcResponse } from 'web3-types'; +import { ResponseError } from 'web3-errors'; +import { Network, Transport } from '../../src/types'; +import { Web3ExternalProvider } from '../../src/web3_provider'; import { QuickNodeRateLimitError } from '../../src/errors'; import { QuickNodeProvider } from '../../src/web3_provider_quicknode'; jest.mock('web3-providers-ws', () => { - return { - __esModule: true, - default: jest.fn().mockImplementation(() => ({ - request: jest.fn().mockResolvedValue({ result: 'mock-result' }), - })), - }; + return { + __esModule: true, + default: jest.fn().mockImplementation(() => ({ + request: jest.fn().mockResolvedValue({ result: 'mock-result' }), + })), + }; }); class MockWeb3ExternalProvider extends Web3ExternalProvider { - public constructor(network: Network, transport: Transport, token: string){ - super(network, transport, token, ""); - } - // eslint-disable-next-line class-methods-use-this - public getRPCURL(_network: Network, _transport: Transport, _token: string): string { - return 'https://example.com/'; - } - } + public constructor(network: Network, transport: Transport, token: string) { + super(network, transport, token, ''); + } + // eslint-disable-next-line class-methods-use-this + public getRPCURL(_network: Network, _transport: Transport, _token: string): string { + return 'https://example.com/'; + } +} describe('Web3ExternalProvider', () => { - it('should make a request using the HTTPS provider', async () => { - const network: Network = Network.ETH_MAINNET; - const transport: Transport = Transport.HTTPS; - const token = 'your-token'; - - const mockHttpProvider = { - request: jest.fn(), - }; - - const mockResponse = { result: 'mock-result' }; - mockHttpProvider.request.mockResolvedValue(mockResponse); - - const provider = new MockWeb3ExternalProvider(network, transport, token); - (provider as any).provider = mockHttpProvider; - - const payload: Web3APIPayload> = { - method: 'eth_getBalance', - params: ['0x0123456789012345678901234567890123456789', 'latest'], - }; - - const result = await provider.request(payload); - expect(result).toEqual(mockResponse); - }); - - it('should make a request using the WebSocket provider', async () => { - const network: Network = Network.ETH_MAINNET; - const transport: Transport = Transport.WebSocket; - const token = 'your-token'; - - const provider = new MockWeb3ExternalProvider(network, transport, token); - (provider as any).getRPCURL = jest.fn().mockReturnValue('ws://mock-rpc-url.com'); - - const payload: Web3APIPayload> = { - method: 'eth_getBalance', - params: ['0x0123456789012345678901234567890123456789', 'latest'], - }; - - const result = await provider.request(payload); - expect(result).toEqual({ result: 'mock-result' }); - }); - - it('should throw a rate limiting error when status code is 429', async () => { - const network: Network = Network.ETH_MAINNET; - const transport: Transport = Transport.HTTPS; - const token = 'your-token'; - - const mockHttpProvider = { - request: jest.fn(), - }; - - // Create a mock ResponseError with status code 429 - // Create a mock JsonRpcResponse to pass to ResponseError - const mockJsonRpcResponse: JsonRpcResponse = { - jsonrpc: '2.0', - id: '458408f4-7e2c-43f1-b61d-1fe09a9ee25a', - error: { - code: 429, - message: 'Rate limit exceeded', - }, - }; - - // Create a mock ResponseError with status code 429 - const mockError = new ResponseError( - mockJsonRpcResponse, - undefined, - undefined, // request can be undefined - 429 // statusCode - ); - - // Mock the request method to throw the ResponseError - mockHttpProvider.request.mockRejectedValue(mockError); - - const provider = new QuickNodeProvider(network, transport, token); - (provider as any).provider = mockHttpProvider; - - const payload: Web3APIPayload> = { - method: 'eth_getBalance', - params: ['0x0123456789012345678901234567890123456789', 'latest'], - }; - await expect(provider.request(payload)).rejects.toThrow(QuickNodeRateLimitError); - }); - -}); \ No newline at end of file + it('should make a request using the HTTPS provider', async () => { + const network: Network = Network.ETH_MAINNET; + const transport: Transport = Transport.HTTPS; + const token = 'your-token'; + + const mockHttpProvider = { + request: jest.fn(), + }; + + const mockResponse = { result: 'mock-result' }; + mockHttpProvider.request.mockResolvedValue(mockResponse); + + const provider = new MockWeb3ExternalProvider(network, transport, token); + (provider as any).provider = mockHttpProvider; + + const payload: Web3APIPayload> = { + method: 'eth_getBalance', + params: ['0x0123456789012345678901234567890123456789', 'latest'], + }; + + const result = await provider.request(payload); + expect(result).toEqual(mockResponse); + }); + + it('should make a request using the WebSocket provider', async () => { + const network: Network = Network.ETH_MAINNET; + const transport: Transport = Transport.WebSocket; + const token = 'your-token'; + + const provider = new MockWeb3ExternalProvider(network, transport, token); + (provider as any).getRPCURL = jest.fn().mockReturnValue('ws://mock-rpc-url.com'); + + const payload: Web3APIPayload> = { + method: 'eth_getBalance', + params: ['0x0123456789012345678901234567890123456789', 'latest'], + }; + + const result = await provider.request(payload); + expect(result).toEqual({ result: 'mock-result' }); + }); + + it('should throw a rate limiting error when status code is 429', async () => { + const network: Network = Network.ETH_MAINNET; + const transport: Transport = Transport.HTTPS; + const token = 'your-token'; + + const mockHttpProvider = { + request: jest.fn(), + }; + + // Create a mock ResponseError with status code 429 + // Create a mock JsonRpcResponse to pass to ResponseError + const mockJsonRpcResponse: JsonRpcResponse = { + jsonrpc: '2.0', + id: '458408f4-7e2c-43f1-b61d-1fe09a9ee25a', + error: { + code: 429, + message: 'Rate limit exceeded', + }, + }; + + // Create a mock ResponseError with status code 429 + const mockError = new ResponseError( + mockJsonRpcResponse, + undefined, + undefined, // request can be undefined + 429, // statusCode + ); + + // Mock the request method to throw the ResponseError + mockHttpProvider.request.mockRejectedValue(mockError); + + const provider = new QuickNodeProvider(network, transport, token); + (provider as any).provider = mockHttpProvider; + + const payload: Web3APIPayload> = { + method: 'eth_getBalance', + params: ['0x0123456789012345678901234567890123456789', 'latest'], + }; + await expect(provider.request(payload)).rejects.toThrow(QuickNodeRateLimitError); + }); +}); diff --git a/packages/web3-types/CHANGELOG.md b/packages/web3-types/CHANGELOG.md index 9fba5349a3c..281d77fb528 100644 --- a/packages/web3-types/CHANGELOG.md +++ b/packages/web3-types/CHANGELOG.md @@ -163,7 +163,6 @@ Documentation: - add `asEIP1193Provider` to `Web3BaseProvider` so every inherited class can have the returned value of `request` method, fully compatible with EIP-1193. (#6407) - ## [1.3.0] ### Added @@ -200,7 +199,7 @@ Documentation: ### Added -- Added `result` as optional `never` and `error` as optional `never in type `JsonRpcNotification` (#7091) -- Added `JsonRpcNotfication` as a union type in `JsonRpcResponse` (#7091) +- Added `result` as optional `never` and `error` as optional `never in type `JsonRpcNotification` (#7091) +- Added `JsonRpcNotfication` as a union type in `JsonRpcResponse` (#7091) ## [Unreleased] diff --git a/packages/web3-types/src/apis/eth_execution_api.ts b/packages/web3-types/src/apis/eth_execution_api.ts index 3abb0b29af0..a2ee39bb767 100644 --- a/packages/web3-types/src/apis/eth_execution_api.ts +++ b/packages/web3-types/src/apis/eth_execution_api.ts @@ -193,7 +193,10 @@ export type EthExecutionAPI = { eth_getUncleCountByBlockHash: (blockHash: HexString32Bytes) => Uint; eth_getUncleCountByBlockNumber: (blockNumber: BlockNumberOrTag) => Uint; eth_getUncleByBlockHashAndIndex: (blockHash: HexString32Bytes, uncleIndex: Uint) => BlockAPI; - eth_getUncleByBlockNumberAndIndex: (blockNumber: BlockNumberOrTag, uncleIndex: Uint) => BlockAPI; + eth_getUncleByBlockNumberAndIndex: ( + blockNumber: BlockNumberOrTag, + uncleIndex: Uint, + ) => BlockAPI; // https://github.com/ethereum/execution-apis/blob/main/src/eth/transaction.yaml eth_getTransactionByHash: (transactionHash: HexString32Bytes) => TransactionInfoAPI | undefined; diff --git a/packages/web3-types/src/eth_abi_types.ts b/packages/web3-types/src/eth_abi_types.ts index e46b79e8498..0daaa2db877 100644 --- a/packages/web3-types/src/eth_abi_types.ts +++ b/packages/web3-types/src/eth_abi_types.ts @@ -142,7 +142,6 @@ export type AbiErrorFragment = AbiBaseFragment & { readonly inputs?: ReadonlyArray; }; - export type AbiInput = | string | AbiParameter @@ -155,14 +154,12 @@ export type AbiInput = } | { readonly [key: string]: unknown }; - export interface AbiOutput { - name: string; - type: string; - components?: AbiOutput[]; - internalType?: string; - } - - +export interface AbiOutput { + name: string; + type: string; + components?: AbiOutput[]; + internalType?: string; +} // https://docs.soliditylang.org/en/latest/abi-spec.html#json export type AbiFragment = @@ -170,12 +167,11 @@ export type AbiFragment = | AbiFunctionFragment | AbiEventFragment | AbiErrorFragment - | AbiFallbackFragment + | AbiFallbackFragment; // to be compatible with web3js v1 -export type AbiItem = AbiFragment -export type ContractAbi = ReadonlyArray | ReadonlyArray - +export type AbiItem = AbiFragment; +export type ContractAbi = ReadonlyArray | ReadonlyArray; // https://docs.soliditylang.org/en/develop/abi-spec.html#json export type JsonFunctionInterface = { diff --git a/packages/web3-types/src/web3_base_provider.ts b/packages/web3-types/src/web3_base_provider.ts index 5f840aa7488..5a9e9899d13 100644 --- a/packages/web3-types/src/web3_base_provider.ts +++ b/packages/web3-types/src/web3_base_provider.ts @@ -112,7 +112,6 @@ export type ProviderChainId = string; export type ProviderAccounts = string[]; - export type Eip1193EventName = | 'connect' | 'disconnect' @@ -149,7 +148,6 @@ export interface MetaMaskProvider extends SimpleProvide isMetaMask: boolean; } - export type Eip1193Compatible = Omit< // eslint-disable-next-line no-use-before-define Omit, diff --git a/packages/web3-utils/src/formatter.ts b/packages/web3-utils/src/formatter.ts index a25c69c26a4..5050a26ef7d 100644 --- a/packages/web3-utils/src/formatter.ts +++ b/packages/web3-utils/src/formatter.ts @@ -133,9 +133,8 @@ export const convertScalarValue = (value: unknown, ethType: string, format: Data } if (baseType === 'string') { - return String(value); - } - + return String(value); + } } catch (error) { // If someone didn't use `eth` keyword we can return original value // as the scope of this code is formatting not validation @@ -328,18 +327,18 @@ export const convert = ( } // 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 specifies format - // 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 - if ((schemaProp?.format === undefined) && (schemaProp?.oneOf !== undefined)) { - for (const [_index, oneOfSchemaProp] of schemaProp.oneOf.entries()) { - if ((oneOfSchemaProp?.format !== undefined)) { - schemaProp = oneOfSchemaProp; - break; - } - }; - } + // if the schema specifies oneOf, then we are to loop + // over each possible schema and check if they type of the schema specifies format + // 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 + if (schemaProp?.format === undefined && schemaProp?.oneOf !== undefined) { + for (const [_index, oneOfSchemaProp] of schemaProp.oneOf.entries()) { + if (oneOfSchemaProp?.format !== undefined) { + schemaProp = oneOfSchemaProp; + break; + } + } + } object[key] = convertScalarValue(value, schemaProp.format as string, format); diff --git a/packages/web3-utils/test/unit/formatter.test.ts b/packages/web3-utils/test/unit/formatter.test.ts index 9f2bbfc3f1b..041f148abec 100644 --- a/packages/web3-utils/test/unit/formatter.test.ts +++ b/packages/web3-utils/test/unit/formatter.test.ts @@ -852,12 +852,10 @@ describe('formatter', () => { }, }; - const data ={ + const data = { from: '0x7ed0e85b8e1e925600b4373e6d108f34ab38a401', to: 123, - } - ; - + }; const result = { from: '0x7ed0e85b8e1e925600b4373e6d108f34ab38a401', to: '123' }; expect( @@ -878,11 +876,11 @@ describe('formatter', () => { }, }; - const data ={ - from: '0x7ed0e85b8e1e925600b4373e6d108f34ab38a401' + const data = { + from: '0x7ed0e85b8e1e925600b4373e6d108f34ab38a401', }; - const result = { from: '0x7ed0e85b8e1e925600b4373e6d108f34ab38a401'}; + const result = { from: '0x7ed0e85b8e1e925600b4373e6d108f34ab38a401' }; expect( format(schema, data, { number: FMT_NUMBER.HEX, bytes: FMT_BYTES.HEX }), diff --git a/packages/web3-validator/CHANGELOG.md b/packages/web3-validator/CHANGELOG.md index da4cc2c0136..8410b156c08 100644 --- a/packages/web3-validator/CHANGELOG.md +++ b/packages/web3-validator/CHANGELOG.md @@ -166,13 +166,13 @@ Documentation: ### Fixed -- 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) ## [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) +- 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 +## [Unreleased] diff --git a/packages/web3-validator/src/utils.ts b/packages/web3-validator/src/utils.ts index 6f9fd6f7f55..2e025022816 100644 --- a/packages/web3-validator/src/utils.ts +++ b/packages/web3-validator/src/utils.ts @@ -206,25 +206,25 @@ export const abiSchemaToJsonSchema = ( nestedTuple.$id = abiName; (lastSchema.items as JsonSchema[]).push(nestedTuple); } else if (baseType === 'tuple' && isArray) { - const arraySize = arraySizes[0]; - const item: JsonSchema = { - type: 'array', - $id: abiName, - items: abiSchemaToJsonSchema(abiComponents, abiName), - ...(arraySize >= 0 && { minItems: arraySize, maxItems: arraySize }), - }; - - (lastSchema.items as JsonSchema[]).push(item); + const arraySize = arraySizes[0]; + const item: JsonSchema = { + type: 'array', + $id: abiName, + items: abiSchemaToJsonSchema(abiComponents, abiName), + ...(arraySize >= 0 && { minItems: arraySize, maxItems: arraySize }), + }; + + (lastSchema.items as JsonSchema[]).push(item); } else if (isArray) { - const arraySize = arraySizes[0]; - const item: JsonSchema = { - type: 'array', - $id: abiName, - items: convertEthType(abiType), - ...(arraySize >= 0 && { minItems: arraySize, maxItems: arraySize }), - }; - - (lastSchema.items as JsonSchema[]).push(item); + const arraySize = arraySizes[0]; + const item: JsonSchema = { + type: 'array', + $id: abiName, + items: convertEthType(abiType), + ...(arraySize >= 0 && { minItems: arraySize, maxItems: arraySize }), + }; + + (lastSchema.items as JsonSchema[]).push(item); } else if (Array.isArray(lastSchema.items)) { // Array of non-tuple items lastSchema.items.push({ $id: abiName, ...convertEthType(abiType) }); @@ -446,17 +446,14 @@ const charCodeMap = { F: 70, a: 97, f: 102, - } as const - - function charCodeToBase16(char: number) { - if (char >= charCodeMap.zero && char <= charCodeMap.nine) - return char - charCodeMap.zero - if (char >= charCodeMap.A && char <= charCodeMap.F) - return char - (charCodeMap.A - 10) - if (char >= charCodeMap.a && char <= charCodeMap.f) - return char - (charCodeMap.a - 10) - return undefined - } +} as const; + +function charCodeToBase16(char: number) { + if (char >= charCodeMap.zero && char <= charCodeMap.nine) return char - charCodeMap.zero; + if (char >= charCodeMap.A && char <= charCodeMap.F) return char - (charCodeMap.A - 10); + if (char >= charCodeMap.a && char <= charCodeMap.f) return char - (charCodeMap.a - 10); + return undefined; +} export function hexToUint8Array(hex: string): Uint8Array { let offset = 0; @@ -468,21 +465,19 @@ export function hexToUint8Array(hex: string): Uint8Array { } const length = (hex.length - offset) / 2; const bytes = new Uint8Array(length); - for (let index = 0, j = offset; index < length; index+=1) { - // eslint-disable-next-line no-plusplus - const nibbleLeft = charCodeToBase16(hex.charCodeAt(j++)) - // eslint-disable-next-line no-plusplus - const nibbleRight = charCodeToBase16(hex.charCodeAt(j++)) - if (nibbleLeft === undefined || nibbleRight === undefined) { - throw new InvalidBytesError( - `Invalid byte sequence ("${hex[j - 2]}${ - hex[j - 1] - }" in "${hex}").`, - ) - } - bytes[index] = nibbleLeft * 16 + nibbleRight + for (let index = 0, j = offset; index < length; index += 1) { + // eslint-disable-next-line no-plusplus + const nibbleLeft = charCodeToBase16(hex.charCodeAt(j++)); + // eslint-disable-next-line no-plusplus + const nibbleRight = charCodeToBase16(hex.charCodeAt(j++)); + if (nibbleLeft === undefined || nibbleRight === undefined) { + throw new InvalidBytesError( + `Invalid byte sequence ("${hex[j - 2]}${hex[j - 1]}" in "${hex}").`, + ); + } + bytes[index] = nibbleLeft * 16 + nibbleRight; } - return bytes + return bytes; } // @TODO: Remove this function and its usages once all sub dependencies uses version 1.3.3 or above of @noble/hashes diff --git a/packages/web3-validator/src/validation/bytes.ts b/packages/web3-validator/src/validation/bytes.ts index 928efec6982..c05b666526b 100644 --- a/packages/web3-validator/src/validation/bytes.ts +++ b/packages/web3-validator/src/validation/bytes.ts @@ -23,7 +23,9 @@ import { isHexStrict } from './string.js'; * checks input if typeof data is valid Uint8Array input */ export const isUint8Array = (data: ValidInputTypes): data is Uint8Array => - data instanceof Uint8Array || data?.constructor?.name === 'Uint8Array' || data?.constructor?.name === 'Buffer'; + data instanceof Uint8Array || + data?.constructor?.name === 'Uint8Array' || + data?.constructor?.name === 'Buffer'; export const isBytes = ( value: ValidInputTypes | Uint8Array | number[], diff --git a/packages/web3-validator/src/validator.ts b/packages/web3-validator/src/validator.ts index 82d7a596052..c2e49d8c253 100644 --- a/packages/web3-validator/src/validator.ts +++ b/packages/web3-validator/src/validator.ts @@ -44,9 +44,12 @@ const convertToZod = (schema: JsonSchema): ZodType => { } if (schema?.type === 'array' && schema?.items) { - if (Array.isArray(schema.items) && schema.items.length > 1 - && schema.maxItems !== undefined - && new Set(schema.items.map((item: JsonSchema) => item.$id)).size === schema.items.length) { + if ( + Array.isArray(schema.items) && + schema.items.length > 1 && + schema.maxItems !== undefined && + new Set(schema.items.map((item: JsonSchema) => item.$id)).size === schema.items.length + ) { const arr: Partial<[ZodTypeAny, ...ZodTypeAny[]]> = []; for (const item of schema.items) { const zItem = convertToZod(item); @@ -57,10 +60,12 @@ const convertToZod = (schema: JsonSchema): ZodType => { return z.tuple(arr as [ZodTypeAny, ...ZodTypeAny[]]); } const nextSchema = Array.isArray(schema.items) ? schema.items[0] : schema.items; - let zodArraySchema = z.array(convertToZod(nextSchema)); + let zodArraySchema = z.array(convertToZod(nextSchema)); - zodArraySchema = schema.minItems !== undefined ? zodArraySchema.min(schema.minItems) : zodArraySchema; - zodArraySchema = schema.maxItems !== undefined ? zodArraySchema.max(schema.maxItems) : zodArraySchema; + zodArraySchema = + schema.minItems !== undefined ? zodArraySchema.min(schema.minItems) : zodArraySchema; + zodArraySchema = + schema.maxItems !== undefined ? zodArraySchema.max(schema.maxItems) : zodArraySchema; return zodArraySchema; } 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 e9e4391700c..99bfcc8e7bd 100644 --- a/packages/web3-validator/test/fixtures/abi_to_json_schema.ts +++ b/packages/web3-validator/test/fixtures/abi_to_json_schema.ts @@ -746,55 +746,55 @@ const abiToJsonSchemaCases: AbiToJsonSchemaCase[] = [ }, json: { fullSchema: { - type: 'array', - items: [ - { - type: 'array', - $id: 'a', - items: [ - { - type: 'array', - $id: 'a', - items: { - format: 'uint', - required: true, - }, - minItems: 2, - maxItems: 2, - } - ], - maxItems: 3, - minItems: 3, - } - ], - maxItems: 1, - minItems: 1, - }, + type: 'array', + items: [ + { + type: 'array', + $id: 'a', + items: [ + { + type: 'array', + $id: 'a', + items: { + format: 'uint', + required: true, + }, + minItems: 2, + maxItems: 2, + }, + ], + maxItems: 3, + minItems: 3, + }, + ], + maxItems: 1, + minItems: 1, + }, shortSchema: { - type: 'array', - items: [ - { - type: 'array', - $id: '/0/0', - items: [ - { - type: 'array', - $id: '/0/0', - items: { - format: 'uint', - required: true, - }, - minItems: 2, - maxItems: 2, - } - ], - maxItems: 3, - minItems: 3, - } - ], - maxItems: 1, - minItems: 1, - }, + type: 'array', + items: [ + { + type: 'array', + $id: '/0/0', + items: [ + { + type: 'array', + $id: '/0/0', + items: { + format: 'uint', + required: true, + }, + minItems: 2, + maxItems: 2, + }, + ], + maxItems: 3, + minItems: 3, + }, + ], + maxItems: 1, + minItems: 1, + }, data: [ [ [1, 1], @@ -825,51 +825,51 @@ const abiToJsonSchemaCases: AbiToJsonSchemaCase[] = [ }, json: { fullSchema: { - type: 'array', - items: [ - { - type: 'array', - $id: 'a', - items: [ - { - type: 'array', - $id: 'a', - items: { - format: 'uint', - required: true, - } - } - ], - maxItems: 3, - minItems: 3, - } - ], - maxItems: 1, - minItems: 1, - }, + type: 'array', + items: [ + { + type: 'array', + $id: 'a', + items: [ + { + type: 'array', + $id: 'a', + items: { + format: 'uint', + required: true, + }, + }, + ], + maxItems: 3, + minItems: 3, + }, + ], + maxItems: 1, + minItems: 1, + }, shortSchema: { - type: 'array', - items: [ - { - type: 'array', - $id: '/0/0', - items: [ - { - type: 'array', - $id: '/0/0', - items: { - format: 'uint', - required: true, - } - } - ], - maxItems: 3, - minItems: 3, - } - ], - maxItems: 1, - minItems: 1, - }, + type: 'array', + items: [ + { + type: 'array', + $id: '/0/0', + items: [ + { + type: 'array', + $id: '/0/0', + items: { + format: 'uint', + required: true, + }, + }, + ], + maxItems: 3, + minItems: 3, + }, + ], + maxItems: 1, + minItems: 1, + }, data: [ [ [1, 1], @@ -924,77 +924,77 @@ const abiToJsonSchemaCases: AbiToJsonSchemaCase[] = [ }, json: { fullSchema: { - type: 'array', - items: [ - { - type: 'array', - $id: 'a', - items: [ - { - type: 'array', - $id: 'a', - items: { - type: 'array', - items: [ - { - $id: 'level', - format: 'uint', - required: true, - }, - { - $id: 'message', - format: 'string', - required: true, - } - ], - maxItems: 2, - minItems: 2, - } - } - ], - maxItems: 3, - minItems: 3, - } - ], - maxItems: 1, - minItems: 1 - }, + type: 'array', + items: [ + { + type: 'array', + $id: 'a', + items: [ + { + type: 'array', + $id: 'a', + items: { + type: 'array', + items: [ + { + $id: 'level', + format: 'uint', + required: true, + }, + { + $id: 'message', + format: 'string', + required: true, + }, + ], + maxItems: 2, + minItems: 2, + }, + }, + ], + maxItems: 3, + minItems: 3, + }, + ], + maxItems: 1, + minItems: 1, + }, shortSchema: { - type: 'array', - items: [ - { - type: 'array', - $id: '/0/0', - items: [ - { - type: 'array', - $id: '/0/0', - items: { - type: 'array', - items: [ - { - $id: '/0/0/0', - format: 'uint', - required: true, - }, - { - $id: '/0/0/1', - format: 'string', - required: true, - } - ], - maxItems: 2, - minItems: 2, - } - } - ], - maxItems: 3, - minItems: 3, - } - ], - maxItems: 1, - minItems: 1 - }, + type: 'array', + items: [ + { + type: 'array', + $id: '/0/0', + items: [ + { + type: 'array', + $id: '/0/0', + items: { + type: 'array', + items: [ + { + $id: '/0/0/0', + format: 'uint', + required: true, + }, + { + $id: '/0/0/1', + format: 'string', + required: true, + }, + ], + maxItems: 2, + minItems: 2, + }, + }, + ], + maxItems: 3, + minItems: 3, + }, + ], + maxItems: 1, + minItems: 1, + }, data: [ [ [ @@ -1071,81 +1071,81 @@ const abiToJsonSchemaCases: AbiToJsonSchemaCase[] = [ }, json: { fullSchema: { - type: 'array', - items: [ - { - type: 'array', - $id: 'a', - items: [ - { - type: 'array', - $id: 'a', - items: { - type: 'array', - items: [ - { - $id: 'level', - format: 'uint', - required: true, - }, - { - $id: 'message', - format: 'string', - required: true, - } - ], - maxItems: 2, - minItems: 2, - }, - minItems: 3, - maxItems: 3, - } - ], - maxItems: 5, - minItems: 5, - } - ], - maxItems: 1, - minItems: 1, - }, + type: 'array', + items: [ + { + type: 'array', + $id: 'a', + items: [ + { + type: 'array', + $id: 'a', + items: { + type: 'array', + items: [ + { + $id: 'level', + format: 'uint', + required: true, + }, + { + $id: 'message', + format: 'string', + required: true, + }, + ], + maxItems: 2, + minItems: 2, + }, + minItems: 3, + maxItems: 3, + }, + ], + maxItems: 5, + minItems: 5, + }, + ], + maxItems: 1, + minItems: 1, + }, shortSchema: { - type: 'array', - items: [ - { - type: 'array', - $id: '/0/0', - items: [ - { - type: 'array', - $id: '/0/0', - items: { - type: 'array', - items: [ - { - $id: '/0/0/0', - format: 'uint', - required: true, - }, - { - $id: '/0/0/1', - format: 'string', - required: true, - } - ], - maxItems: 2, - minItems: 2, - }, - minItems: 3, - maxItems: 3, - } - ], - maxItems: 5, - minItems: 5, - } - ], - maxItems: 1, - minItems: 1, - }, + type: 'array', + items: [ + { + type: 'array', + $id: '/0/0', + items: [ + { + type: 'array', + $id: '/0/0', + items: { + type: 'array', + items: [ + { + $id: '/0/0/0', + format: 'uint', + required: true, + }, + { + $id: '/0/0/1', + format: 'string', + required: true, + }, + ], + maxItems: 2, + minItems: 2, + }, + minItems: 3, + maxItems: 3, + }, + ], + maxItems: 5, + minItems: 5, + }, + ], + maxItems: 1, + minItems: 1, + }, data: [ [ [ @@ -1433,186 +1433,186 @@ const abiToJsonSchemaCases: AbiToJsonSchemaCase[] = [ 'bool', ], data: [ - [ - [ - [ - [0, 0], - [1, 1], - ], - [ - [2, 2], - [3, 3], - ], - ], - [ - [ - [0, 0], - [-1, -1], - ], - [ - [-2, -2], - [-3, -3], - ], - [ - [-4, -4], - [-5, -5], - ], - ], - [ - [ - [4, 4], - [5, 5], - ], - ] - ], - 123, - true, - ], + [ + [ + [ + [0, 0], + [1, 1], + ], + [ + [2, 2], + [3, 3], + ], + ], + [ + [ + [0, 0], + [-1, -1], + ], + [ + [-2, -2], + [-3, -3], + ], + [ + [-4, -4], + [-5, -5], + ], + ], + [ + [ + [4, 4], + [5, 5], + ], + ], + ], + 123, + true, + ], }, json: { fullSchema: { - type: 'array', - items: [ - { - type: 'array', - $id: 'rects', - items: [ - { - type: 'array', - $id: 'rects', - items: { - type: 'array', - items: [ - { - type: 'array', - items: [ - { - $id: 'x', - format: 'int256', - required: true, - }, - { - $id: 'y', - format: 'int256', - required: true - } - ], - maxItems: 2, - minItems: 2, - $id: 'start', - }, - { - type: 'array', - items: [ - { - $id: 'x', - format: 'int256', - required: true, - }, - { - $id: 'y', - format: 'int256', - required: true, - } - ], - maxItems: 2, - minItems: 2, - $id: 'end', - } - ], - maxItems: 2, - minItems: 2, - } - } - ], - maxItems: 3, - minItems: 3, - }, - { - $id: 'numberValue', - format: 'uint256', - required: true, - }, - { - $id: 'boolValue', - format: 'bool', - required: true, - } - ], - maxItems: 3, - minItems: 3, - }, + type: 'array', + items: [ + { + type: 'array', + $id: 'rects', + items: [ + { + type: 'array', + $id: 'rects', + items: { + type: 'array', + items: [ + { + type: 'array', + items: [ + { + $id: 'x', + format: 'int256', + required: true, + }, + { + $id: 'y', + format: 'int256', + required: true, + }, + ], + maxItems: 2, + minItems: 2, + $id: 'start', + }, + { + type: 'array', + items: [ + { + $id: 'x', + format: 'int256', + required: true, + }, + { + $id: 'y', + format: 'int256', + required: true, + }, + ], + maxItems: 2, + minItems: 2, + $id: 'end', + }, + ], + maxItems: 2, + minItems: 2, + }, + }, + ], + maxItems: 3, + minItems: 3, + }, + { + $id: 'numberValue', + format: 'uint256', + required: true, + }, + { + $id: 'boolValue', + format: 'bool', + required: true, + }, + ], + maxItems: 3, + minItems: 3, + }, shortSchema: { type: 'array', - items: [ - { - type: 'array', - $id: '/0/0', - items: [ - { - type: 'array', - $id: '/0/0', - items: { - type: 'array', - items: [ - { - type: 'array', - items: [ - { - $id: '/0/0/0/0', - format: 'int256', - required: true, - }, - { - $id: '/0/0/0/1', - format: 'int256', - required: true, - } - ], - maxItems: 2, - minItems: 2, - $id: '/0/0/0', - }, - { - type: 'array', - items: [ - { - $id: '/0/0/1/0', - format: 'int256', - required: true, - }, - { - $id: '/0/0/1/1', - format: 'int256', - required: true, - } - ], - maxItems: 2, - minItems: 2, - $id: '/0/0/1', - } - ], - maxItems: 2, - minItems: 2, - } - } - ], - maxItems: 3, - minItems: 3, - }, - { - $id: '/0/1', - format: 'uint256', - required: true, - }, - { - $id: '/0/2', - format: 'bool', - required: true, - } - ], - maxItems: 3, - minItems: 3, + items: [ + { + type: 'array', + $id: '/0/0', + items: [ + { + type: 'array', + $id: '/0/0', + items: { + type: 'array', + items: [ + { + type: 'array', + items: [ + { + $id: '/0/0/0/0', + format: 'int256', + required: true, + }, + { + $id: '/0/0/0/1', + format: 'int256', + required: true, + }, + ], + maxItems: 2, + minItems: 2, + $id: '/0/0/0', + }, + { + type: 'array', + items: [ + { + $id: '/0/0/1/0', + format: 'int256', + required: true, + }, + { + $id: '/0/0/1/1', + format: 'int256', + required: true, + }, + ], + maxItems: 2, + minItems: 2, + $id: '/0/0/1', + }, + ], + maxItems: 2, + minItems: 2, + }, + }, + ], + maxItems: 3, + minItems: 3, + }, + { + $id: '/0/1', + format: 'uint256', + required: true, + }, + { + $id: '/0/2', + format: 'bool', + required: true, + }, + ], + maxItems: 3, + minItems: 3, }, data: [ [ @@ -1685,50 +1685,50 @@ const abiToJsonSchemaCases: AbiToJsonSchemaCase[] = [ }, json: { fullSchema: { - type: 'array', - items: [ - { - type: 'array', - $id: 'x1', - items: [ - { - type: 'array', - $id: 'x1', - items: { - format: 'uint256', - required: true, - } - } - ] - }, - { - type: 'array', - $id: 'x2', - items: [ - { - type: 'array', - $id: 'x2', - items: { - format: 'uint256', - required: true, - } - } - ] - }, - { - $id: 'x3', - format: 'uint256', - required: true, - } - ], - maxItems: 3, - minItems: 3, - }, + type: 'array', + items: [ + { + type: 'array', + $id: 'x1', + items: [ + { + type: 'array', + $id: 'x1', + items: { + format: 'uint256', + required: true, + }, + }, + ], + }, + { + type: 'array', + $id: 'x2', + items: [ + { + type: 'array', + $id: 'x2', + items: { + format: 'uint256', + required: true, + }, + }, + ], + }, + { + $id: 'x3', + format: 'uint256', + required: true, + }, + ], + maxItems: 3, + minItems: 3, + }, shortSchema: { type: 'array', items: [ { - $id: '/0/0', + $id: '/0/0', type: 'array', items: [ { @@ -1742,7 +1742,7 @@ const abiToJsonSchemaCases: AbiToJsonSchemaCase[] = [ ], }, { - $id: '/0/1', + $id: '/0/1', type: 'array', items: [ { diff --git a/packages/web3-validator/test/fixtures/validation.ts b/packages/web3-validator/test/fixtures/validation.ts index 8619145308a..fee254d818b 100644 --- a/packages/web3-validator/test/fixtures/validation.ts +++ b/packages/web3-validator/test/fixtures/validation.ts @@ -648,7 +648,6 @@ export const validBytesData: any[] = [ new Uint8Array(hexToBytes('abce')), new Uint8Array([0x91, 0x92]), Buffer.from([0x91, 0x92]), - ]; export const validBytesDataWithSize: [any, number][] = [ diff --git a/packages/web3-validator/test/unit/web3_validator.test.ts b/packages/web3-validator/test/unit/web3_validator.test.ts index ae04d036762..616d5c19a26 100644 --- a/packages/web3-validator/test/unit/web3_validator.test.ts +++ b/packages/web3-validator/test/unit/web3_validator.test.ts @@ -14,7 +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 { SchemaFormatError } from 'web3-errors' +import { SchemaFormatError } from 'web3-errors'; import { abiToJsonSchemaCases } from '../fixtures/abi_to_json_schema'; import { Web3Validator } from '../../src/web3_validator'; import { Web3ValidatorError } from '../../src/errors'; @@ -33,12 +33,12 @@ describe('web3-validator', () => { }); describe('validate', () => { - describe('should pass for valid data', () => { - it.each(abiToJsonSchemaCases)('$title', ({ abi }) => { - const arrayData: ReadonlyArray = abi.data as Array; - expect(validator.validate(abi.fullSchema, arrayData)).toBeUndefined(); - }); - }) + describe('should pass for valid data', () => { + it.each(abiToJsonSchemaCases)('$title', ({ abi }) => { + const arrayData: ReadonlyArray = abi.data as Array; + expect(validator.validate(abi.fullSchema, arrayData)).toBeUndefined(); + }); + }); it('should raise error with empty value', () => { expect(() => validator.validate(['string'], [])).toThrow( diff --git a/packages/web3/CHANGELOG.md b/packages/web3/CHANGELOG.md index d03dc239294..f22108d5fd4 100644 --- a/packages/web3/CHANGELOG.md +++ b/packages/web3/CHANGELOG.md @@ -177,7 +177,7 @@ Documentation: ### Added -- Added methods (privateKeyToAddress, parseAndValidatePrivateKey, and privateKeyToPublicKey) to web3.eth.accounts (#6620) +- Added methods (privateKeyToAddress, parseAndValidatePrivateKey, and privateKeyToPublicKey) to web3.eth.accounts (#6620) ### Changed @@ -197,7 +197,6 @@ Documentation: - Added EIP-6963 utility function `requestEIP6963Providers` for multi provider discovery ( other details are in root changelog ) - ## [4.7.0] ### added @@ -208,17 +207,17 @@ Documentation: #### 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] @@ -236,27 +235,25 @@ Documentation: #### 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) @@ -276,7 +273,7 @@ Documentation: #### web3-errors -- Added `InvalidIntegerError` error for fromWei and toWei (#7052) +- Added `InvalidIntegerError` error for fromWei and toWei (#7052) #### web3-eth @@ -302,8 +299,8 @@ Documentation: #### 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) +- `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 @@ -313,13 +310,13 @@ Documentation: #### web3-utils -- `toWei` support numbers in scientific notation (#6908) -- `toWei` and `fromWei` trims according to ether unit successfuly (#7044) +- `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) +- 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 @@ -373,7 +370,7 @@ Documentation: ### web3-rpc-providers -- RC release +- RC release ### Fixed @@ -381,7 +378,6 @@ Documentation: - `getName` reverse resolution - ## [4.11.0] ### Fixed @@ -402,7 +398,7 @@ Documentation: #### web3-eth-accounts -- baseTransaction method updated (#7095) +- baseTransaction method updated (#7095) #### web3-providers-ws @@ -425,7 +421,7 @@ Documentation: #### web3-errors -- Fixed the undefined data in `Eip838ExecutionError` constructor (#6905) +- Fixed the undefined data in `Eip838ExecutionError` constructor (#6905) #### web3-eth @@ -436,7 +432,6 @@ Documentation: - Remove redundant constructor of contractBuilder (#7150) - ## [4.12.0] ### Fixed @@ -447,7 +442,7 @@ Documentation: #### web3-eth-accounts -- Fix `TransactionFactory.registerTransactionType` not working, if there is a version mistatch between `web3-eth` and `web3-eth-accounts` by saving `extraTxTypes` at `globals`. (#7197) +- Fix `TransactionFactory.registerTransactionType` not working, if there is a version mistatch between `web3-eth` and `web3-eth-accounts` by saving `extraTxTypes` at `globals`. (#7197) ### Added @@ -457,11 +452,11 @@ Documentation: #### web3-eth-contract -- Added `populateTransaction` to the `contract.deploy(...)` properties. (#7197) +- Added `populateTransaction` to the `contract.deploy(...)` properties. (#7197) #### web3-providers-http -- Added `statusCode` of response in ResponseError, `statusCode` is optional property in ResponseError. +- Added `statusCode` of response in ResponseError, `statusCode` is optional property in ResponseError. #### web3-rpc-providers @@ -470,14 +465,14 @@ Documentation: #### web3-errors -- Added optional `statusCode` property of response in ResponseError. +- Added optional `statusCode` property of response in ResponseError. ### Changed #### web3-eth-contract - The returnred properties of `contract.deploy(...)` are structured with a newly created class named `DeployerMethodClass`. (#7197) -- Add a missed accepted type for the `abi` parameter, at `dataInputEncodeMethodHelper` and `getSendTxParams`. (#7197) +- Add a missed accepted type for the `abi` parameter, at `dataInputEncodeMethodHelper` and `getSendTxParams`. (#7197) ## [4.12.1] @@ -485,6 +480,6 @@ Documentation: #### web3-eth-accounts -- Revert `TransactionFactory.registerTransactionType` if there is a version mistatch between `web3-eth` and `web3-eth-accounts` and fix nextjs problem. (#7216) +- Revert `TransactionFactory.registerTransactionType` if there is a version mistatch between `web3-eth` and `web3-eth-accounts` and fix nextjs problem. (#7216) -## [Unreleased] \ No newline at end of file +## [Unreleased] diff --git a/packages/web3/README.md b/packages/web3/README.md index e83698ec2f8..efab77af94e 100644 --- a/packages/web3/README.md +++ b/packages/web3/README.md @@ -9,24 +9,24 @@ [![NPM Package][npm-image]][npm-url] [![Downloads][downloads-image]][npm-url] -This is the main package of [web3.js](repo), it contains a collection of comprehensive [TypeScript](https://www.typescriptlang.org/) libraries for Interaction with the [Ethereum JSON RPC API](https://ethereum.org/developers/docs/apis/json-rpc) and utility functions. +This is the main package of [web3.js](repo), it contains a collection of comprehensive [TypeScript](https://www.typescriptlang.org/) libraries for Interaction with the [Ethereum JSON RPC API](https://ethereum.org/developers/docs/apis/json-rpc) and utility functions. ## Features -- **[Web3.js Plugins🧩](https://docs.web3js.org/guides/web3_plugin_guide/)**: Enhance or add any functionality by creating scalable web3 plugins for any project. -- **Abstractions over the [JSON-RPC API](https://ethereum.org/en/developers/docs/apis/json-rpc)**: Simplifying interaction for your Developer Experience. -- **Language aligned to the official [Ethereum terminology](https://ethereum.org/en/glossary)** -- **Tree-shaking focus**: Include only what you need during bundling for optimized performance. -- **Dynamic contract types and full API in TypeScript**: Enforced with strict types for enhanced security and safety. -- **Complete utilities and functionalities for all your Ethereum needs** -- **More efficient ABI Encoder & Decoder** -- **Extensive [documentation](https://docs.web3js.org/) with guides and APIs** -- **Large collection of test cases** -- **First-class APIs for interacting with [Smart Contracts](https://ethereum.org/en/glossary#smart-contract)** -- **ESM and CJS module builds**: Support for both ECMAScript module and CommonJS module builds for flexible integration with various project setups. -- **[Contracts dynamic types](https://docs.web3js.org/guides/smart_contracts/infer_contract_types/) & full API in TypeScript** -- **Using native BigInt instead of large BigNumber libraries**: Use native BigInt for improved efficiency compared to using large external BigNumber libraries. -- **Custom Output formatters**: Format any returned value to be a string, number, BigInt, etc., providing flexibility in handling output data. +- **[Web3.js Plugins🧩](https://docs.web3js.org/guides/web3_plugin_guide/)**: Enhance or add any functionality by creating scalable web3 plugins for any project. +- **Abstractions over the [JSON-RPC API](https://ethereum.org/en/developers/docs/apis/json-rpc)**: Simplifying interaction for your Developer Experience. +- **Language aligned to the official [Ethereum terminology](https://ethereum.org/en/glossary)** +- **Tree-shaking focus**: Include only what you need during bundling for optimized performance. +- **Dynamic contract types and full API in TypeScript**: Enforced with strict types for enhanced security and safety. +- **Complete utilities and functionalities for all your Ethereum needs** +- **More efficient ABI Encoder & Decoder** +- **Extensive [documentation](https://docs.web3js.org/) with guides and APIs** +- **Large collection of test cases** +- **First-class APIs for interacting with [Smart Contracts](https://ethereum.org/en/glossary#smart-contract)** +- **ESM and CJS module builds**: Support for both ECMAScript module and CommonJS module builds for flexible integration with various project setups. +- **[Contracts dynamic types](https://docs.web3js.org/guides/smart_contracts/infer_contract_types/) & full API in TypeScript** +- **Using native BigInt instead of large BigNumber libraries**: Use native BigInt for improved efficiency compared to using large external BigNumber libraries. +- **Custom Output formatters**: Format any returned value to be a string, number, BigInt, etc., providing flexibility in handling output data. ## Installation diff --git a/packages/web3/src/accounts.ts b/packages/web3/src/accounts.ts index b0c2765257f..ed64927be54 100644 --- a/packages/web3/src/accounts.ts +++ b/packages/web3/src/accounts.ts @@ -30,8 +30,8 @@ import { signTransaction, sign, Wallet, - privateKeyToAddress, - parseAndValidatePrivateKey, + privateKeyToAddress, + parseAndValidatePrivateKey, privateKeyToPublicKey, } from 'web3-eth-accounts'; @@ -102,8 +102,8 @@ export const initAccountsForContext = (context: Web3Context) => recover, encrypt, wallet, - privateKeyToAddress, - parseAndValidatePrivateKey, + privateKeyToAddress, + parseAndValidatePrivateKey, privateKeyToPublicKey, - } + }; }; diff --git a/packages/web3/src/providers.exports.ts b/packages/web3/src/providers.exports.ts index c3d8bfcba08..3d20b0116b9 100644 --- a/packages/web3/src/providers.exports.ts +++ b/packages/web3/src/providers.exports.ts @@ -19,4 +19,4 @@ export { Eip1193Provider, SocketProvider } from 'web3-utils'; export * as http from 'web3-providers-http'; export * as ws from 'web3-providers-ws'; -export * from './web3_eip6963.js'; \ No newline at end of file +export * from './web3_eip6963.js'; diff --git a/packages/web3/src/web3_eip6963.ts b/packages/web3/src/web3_eip6963.ts index 5693dea4776..2e9a2a391f8 100644 --- a/packages/web3/src/web3_eip6963.ts +++ b/packages/web3/src/web3_eip6963.ts @@ -15,79 +15,79 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ -import { Web3APISpec, EIP1193Provider } from "web3-types"; - +import { Web3APISpec, EIP1193Provider } from 'web3-types'; export enum Eip6963EventName { - eip6963announceProvider = 'eip6963:announceProvider', - eip6963requestProvider = 'eip6963:requestProvider', -}; + eip6963announceProvider = 'eip6963:announceProvider', + eip6963requestProvider = 'eip6963:requestProvider', +} export interface EIP6963ProviderInfo { - uuid: string; - name: string; - icon: string; - rdns: string; + uuid: string; + name: string; + icon: string; + rdns: string; } export interface EIP6963ProviderDetail { - info: EIP6963ProviderInfo; - provider: EIP1193Provider; + info: EIP6963ProviderInfo; + provider: EIP1193Provider; } export type EIP6963ProviderResponse = Map; export interface EIP6963AnnounceProviderEvent extends CustomEvent { - type: Eip6963EventName.eip6963announceProvider; - detail: EIP6963ProviderDetail; + type: Eip6963EventName.eip6963announceProvider; + detail: EIP6963ProviderDetail; } export interface EIP6963RequestProviderEvent extends Event { - type: Eip6963EventName.eip6963requestProvider; + type: Eip6963EventName.eip6963requestProvider; } export const eip6963ProvidersMap: EIP6963ProviderResponse = new Map(); -export const web3ProvidersMapUpdated = "web3:providersMapUpdated"; +export const web3ProvidersMapUpdated = 'web3:providersMapUpdated'; export interface EIP6963ProvidersMapUpdateEvent extends CustomEvent { - type: string; - detail: EIP6963ProviderResponse; + type: string; + detail: EIP6963ProviderResponse; } export const requestEIP6963Providers = async (): Promise => - new Promise((resolve, reject) => { - if (typeof window === 'undefined') { - reject(new Error("window object not available, EIP-6963 is intended to be used within a browser")); - } - - window.addEventListener( - Eip6963EventName.eip6963announceProvider as any, - (event: EIP6963AnnounceProviderEvent) => { - - eip6963ProvidersMap.set( - event.detail.info.uuid, - event.detail); - - const newEvent: EIP6963ProvidersMapUpdateEvent = new CustomEvent( - web3ProvidersMapUpdated, - { detail: eip6963ProvidersMap } - ); - - window.dispatchEvent(newEvent); - resolve(eip6963ProvidersMap); - - } - ); - - window.dispatchEvent(new Event(Eip6963EventName.eip6963requestProvider)); - - }); - - -export const onNewProviderDiscovered = (callback: (providerEvent: EIP6963ProvidersMapUpdateEvent) => void) => { - if (typeof window === 'undefined') { - throw new Error("window object not available, EIP-6963 is intended to be used within a browser"); - } - window.addEventListener(web3ProvidersMapUpdated as any, callback ); -} - + new Promise((resolve, reject) => { + if (typeof window === 'undefined') { + reject( + new Error( + 'window object not available, EIP-6963 is intended to be used within a browser', + ), + ); + } + + window.addEventListener( + Eip6963EventName.eip6963announceProvider as any, + (event: EIP6963AnnounceProviderEvent) => { + eip6963ProvidersMap.set(event.detail.info.uuid, event.detail); + + const newEvent: EIP6963ProvidersMapUpdateEvent = new CustomEvent( + web3ProvidersMapUpdated, + { detail: eip6963ProvidersMap }, + ); + + window.dispatchEvent(newEvent); + resolve(eip6963ProvidersMap); + }, + ); + + window.dispatchEvent(new Event(Eip6963EventName.eip6963requestProvider)); + }); + +export const onNewProviderDiscovered = ( + callback: (providerEvent: EIP6963ProvidersMapUpdateEvent) => void, +) => { + if (typeof window === 'undefined') { + throw new Error( + 'window object not available, EIP-6963 is intended to be used within a browser', + ); + } + window.addEventListener(web3ProvidersMapUpdated as any, callback); +}; diff --git a/packages/web3/test/cjs_black_box/.eslintrc.cjs b/packages/web3/test/cjs_black_box/.eslintrc.cjs index 88d28e7e786..b95638b5c51 100644 --- a/packages/web3/test/cjs_black_box/.eslintrc.cjs +++ b/packages/web3/test/cjs_black_box/.eslintrc.cjs @@ -7,6 +7,6 @@ module.exports = { parserOptions: { project: './tsconfig.json', tsconfigRootDir: __dirname, - ecmaVersion: 12 + ecmaVersion: 12, }, }; diff --git a/packages/web3/test/cjs_black_box/test/web3-eth-contract/erc20.test.ts b/packages/web3/test/cjs_black_box/test/web3-eth-contract/erc20.test.ts index 3f8f88238e0..64b3b4809f1 100644 --- a/packages/web3/test/cjs_black_box/test/web3-eth-contract/erc20.test.ts +++ b/packages/web3/test/cjs_black_box/test/web3-eth-contract/erc20.test.ts @@ -22,7 +22,7 @@ import { isWs, getSystemTestProvider, createNewAccount, - BACKEND + BACKEND, // eslint-disable-next-line import/no-relative-packages } from '../../../shared_fixtures/system_tests_utils'; import { diff --git a/packages/web3/test/config/jest.config.js b/packages/web3/test/config/jest.config.js index d61c13316fa..28d62955096 100644 --- a/packages/web3/test/config/jest.config.js +++ b/packages/web3/test/config/jest.config.js @@ -40,5 +40,5 @@ module.exports = { * This can be done programmatically using jest.resetModules(). */ resetModules: true, - testTimeout: 600000, + testTimeout: 600000, }; diff --git a/packages/web3/test/e2e/setup.js b/packages/web3/test/e2e/setup.js index c480060944a..d527ad558d3 100644 --- a/packages/web3/test/e2e/setup.js +++ b/packages/web3/test/e2e/setup.js @@ -18,4 +18,3 @@ along with web3.js. If not, see . // Have to use `require` because of Jest issue https://jestjs.io/docs/ecmascript-modules // eslint-disable-next-line @typescript-eslint/no-require-imports require('../config/setup'); - diff --git a/packages/web3/test/esm_black_box/test/web3-eth-contract/erc20.test.ts b/packages/web3/test/esm_black_box/test/web3-eth-contract/erc20.test.ts index dda2509ac97..ab52726b29e 100644 --- a/packages/web3/test/esm_black_box/test/web3-eth-contract/erc20.test.ts +++ b/packages/web3/test/esm_black_box/test/web3-eth-contract/erc20.test.ts @@ -25,7 +25,7 @@ import { isWs, getSystemTestProvider, createNewAccount, - BACKEND + BACKEND, } from '../../../shared_fixtures/system_tests_utils'; import { ERC20TokenAbi, ERC20TokenBytecode } from '../../../shared_fixtures/contracts/ERC20Token'; diff --git a/packages/web3/test/fixtures/transaction_middleware.ts b/packages/web3/test/fixtures/transaction_middleware.ts index f2d74a973e0..0bfa79d9563 100644 --- a/packages/web3/test/fixtures/transaction_middleware.ts +++ b/packages/web3/test/fixtures/transaction_middleware.ts @@ -15,24 +15,21 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ -import { TransactionMiddleware, TransactionMiddlewareData } from "web3-eth"; +import { TransactionMiddleware, TransactionMiddlewareData } from 'web3-eth'; -// Sample Transaction Middleware +// Sample Transaction Middleware export class CTransactionMiddleware implements TransactionMiddleware { - // eslint-disable-next-line class-methods-use-this - public async processTransaction(transaction: TransactionMiddlewareData, - _options?: { [key: string]: unknown } | undefined): - - Promise { - + public async processTransaction( + transaction: TransactionMiddlewareData, + _options?: { [key: string]: unknown } | undefined, + ): Promise { // eslint-disable-next-line prefer-const let txObj = { ...transaction }; - // Add your logic here for transaction modification + // Add your logic here for transaction modification txObj.data = '0x123'; return Promise.resolve(txObj); } - } diff --git a/packages/web3/test/integration/contract-middleware.test.ts b/packages/web3/test/integration/contract-middleware.test.ts index dd8c4b8df1b..789f7e3c6f7 100644 --- a/packages/web3/test/integration/contract-middleware.test.ts +++ b/packages/web3/test/integration/contract-middleware.test.ts @@ -15,13 +15,16 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ -import { CTransactionMiddleware } from -// eslint-disable-next-line import/no-relative-packages -"../fixtures/transaction_middleware"; +import { + CTransactionMiddleware, + // eslint-disable-next-line import/no-relative-packages +} from '../fixtures/transaction_middleware'; -import { blockMockResult, receiptMockResult } from -// eslint-disable-next-line import/no-relative-packages -"../../../../tools/web3-plugin-example/test/unit/fixtures/transactions_data"; +import { + blockMockResult, + receiptMockResult, + // eslint-disable-next-line import/no-relative-packages +} from '../../../../tools/web3-plugin-example/test/unit/fixtures/transactions_data'; import { Web3 } from '../../src/index'; import { @@ -51,7 +54,6 @@ describe('Contract Middleware', () => { expect(web3.eth.getTransactionMiddleware()).toBeDefined(); expect(contractB.getTransactionMiddleware()).toBeDefined(); expect(web3.eth.getTransactionMiddleware()).toEqual(contractB.getTransactionMiddleware()); - }); it('should send transaction middleware in contract new instance if its set at eth package', async () => { @@ -69,32 +71,30 @@ describe('Contract Middleware', () => { const account = web3.eth.accounts.create(); let blockNum = 1000; - web3.requestManager.send = jest.fn(async (request) => { + web3.requestManager.send = jest.fn(async request => { blockNum += 1; if (request.method === 'eth_getBlockByNumber') { - return Promise.resolve(blockMockResult.result); } if (request.method === 'eth_call') { - - return Promise.resolve("0x"); + return Promise.resolve('0x'); } if (request.method === 'eth_blockNumber') { - return Promise.resolve(blockNum.toString(16)); } if (request.method === 'eth_sendTransaction') { - sendTransactionSpy(request.params); - return Promise.resolve("0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f"); + return Promise.resolve( + '0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f', + ); } if (request.method === 'eth_getTransactionReceipt') { return Promise.resolve(receiptMockResult.result); } - return Promise.resolve("Unknown Request" as any); + return Promise.resolve('Unknown Request' as any); }); await contract.methods.transfer(account.address, 100).send({ from: account?.address }); @@ -106,11 +106,10 @@ describe('Contract Middleware', () => { expect(sendTransactionSpy).toHaveBeenCalledWith( expect.arrayContaining([ expect.objectContaining({ - data: "0x123", + data: '0x123', from: account.address, - }) - ]) + }), + ]), ); }); }); - diff --git a/packages/web3/test/integration/external-providers/hardhat.test.ts b/packages/web3/test/integration/external-providers/hardhat.test.ts index 6a4fb6ff28b..3bc154988c9 100644 --- a/packages/web3/test/integration/external-providers/hardhat.test.ts +++ b/packages/web3/test/integration/external-providers/hardhat.test.ts @@ -18,7 +18,7 @@ along with web3.js. If not, see . // eslint-disable-next-line import/no-extraneous-dependencies import hardhat from 'hardhat'; -import { performBasicRpcCalls, failErrorCalls} 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 () => { @@ -28,6 +28,5 @@ describe('compatibility with `hardhat` provider', () => { 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/setup.js b/packages/web3/test/integration/setup.js index c480060944a..d527ad558d3 100644 --- a/packages/web3/test/integration/setup.js +++ b/packages/web3/test/integration/setup.js @@ -18,4 +18,3 @@ along with web3.js. If not, see . // Have to use `require` because of Jest issue https://jestjs.io/docs/ecmascript-modules // eslint-disable-next-line @typescript-eslint/no-require-imports require('../config/setup'); - diff --git a/packages/web3/test/integration/web3.config.test.ts b/packages/web3/test/integration/web3.config.test.ts index 33a3e8e2ad0..0baf0d5f969 100644 --- a/packages/web3/test/integration/web3.config.test.ts +++ b/packages/web3/test/integration/web3.config.test.ts @@ -30,7 +30,7 @@ describe('Web3 instance', () => { let web3: Web3; let currentAttempt = 0; - beforeEach(() => { + beforeEach(() => { currentAttempt = 0; }); @@ -45,11 +45,11 @@ describe('Web3 instance', () => { try { await closeOpenConnection(web3); } catch (e) { - console.warn("Failed to close open con", e) + console.warn('Failed to close open con', e); } }); - afterEach(async () => { + afterEach(async () => { if (isWs) { // make sure we try to close the connection after it is established if ( @@ -65,19 +65,19 @@ describe('Web3 instance', () => { } }); - it('should be send transaction, change for defaultTransactionType and successfully send transaction with different type', async () => { + it('should be send transaction, change for defaultTransactionType and successfully send transaction with different type', async () => { const transaction = { - from: accounts[0], - to: accounts[0], - value: 100000, - } - - const receipt = await web3.eth.sendTransaction(transaction); - expect(receipt.type).toEqual(BigInt(2)) + from: accounts[0], + to: accounts[0], + value: 100000, + }; - web3.setConfig({defaultTransactionType: "0x0"}); - - const receipt2 = await web3.eth.sendTransaction(transaction); - expect(receipt2.type).toEqual(BigInt(0)) - }) -}) \ No newline at end of file + const receipt = await web3.eth.sendTransaction(transaction); + expect(receipt.type).toEqual(BigInt(2)); + + web3.setConfig({ defaultTransactionType: '0x0' }); + + const receipt2 = await web3.eth.sendTransaction(transaction); + expect(receipt2.type).toEqual(BigInt(0)); + }); +}); diff --git a/packages/web3/test/integration/web3RPCProviders.test.ts b/packages/web3/test/integration/web3RPCProviders.test.ts index 24bc312610d..1faeffad452 100644 --- a/packages/web3/test/integration/web3RPCProviders.test.ts +++ b/packages/web3/test/integration/web3RPCProviders.test.ts @@ -15,47 +15,50 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ -import { mainnet , Network, QuickNodeProvider, Transport } from "web3-rpc-providers"; +import { mainnet, Network, QuickNodeProvider, Transport } from 'web3-rpc-providers'; import { Web3 } from '../../src/index'; describe('Web3 RPC Provider Integration tests', () => { - const transports = Object.values(Transport); - const networks = [Network.ETH_MAINNET, Network.ETH_HOLESKY, Network.ETH_SEPOLIA, - Network.ARBITRUM_MAINNET, Network.ARBITRUM_SEPOLIA, - Network.BNB_MAINNET, Network.BNB_TESTNET, - Network.POLYGON_MAINNET, Network.POLYGON_AMONY]; - - transports.forEach((transport) => { - networks.forEach((network) => { - it(`QuickNodeProvider should work with ${transport} transport and ${network} network`, async () => { - - const provider = new QuickNodeProvider(network, transport); - const web3 = new Web3(provider); - const result = await web3.eth.getBlockNumber() - - expect(typeof result).toBe('bigint'); - expect(result > 0).toBe(true); - - if (transport === Transport.WebSocket) { - web3.provider?.disconnect(); - } - - }); - }); - }); - it(`should work with mainnet provider`, async () => { - const web3 = new Web3(mainnet); - const result = await web3.eth.getBlockNumber() - expect(typeof result).toBe('bigint'); - expect(result > 0).toBe(true); - - }); - - it(`should work with default provider`, async () => { - const web3 = new Web3(); - const result = await web3.eth.getBlockNumber() - expect(typeof result).toBe('bigint'); - expect(result > 0).toBe(true); - - }); -}); \ No newline at end of file + const transports = Object.values(Transport); + const networks = [ + Network.ETH_MAINNET, + Network.ETH_HOLESKY, + Network.ETH_SEPOLIA, + Network.ARBITRUM_MAINNET, + Network.ARBITRUM_SEPOLIA, + Network.BNB_MAINNET, + Network.BNB_TESTNET, + Network.POLYGON_MAINNET, + Network.POLYGON_AMONY, + ]; + + transports.forEach(transport => { + networks.forEach(network => { + it(`QuickNodeProvider should work with ${transport} transport and ${network} network`, async () => { + const provider = new QuickNodeProvider(network, transport); + const web3 = new Web3(provider); + const result = await web3.eth.getBlockNumber(); + + expect(typeof result).toBe('bigint'); + expect(result > 0).toBe(true); + + if (transport === Transport.WebSocket) { + web3.provider?.disconnect(); + } + }); + }); + }); + it(`should work with mainnet provider`, async () => { + const web3 = new Web3(mainnet); + const result = await web3.eth.getBlockNumber(); + expect(typeof result).toBe('bigint'); + expect(result > 0).toBe(true); + }); + + it(`should work with default provider`, async () => { + const web3 = new Web3(); + const result = await web3.eth.getBlockNumber(); + expect(typeof result).toBe('bigint'); + expect(result > 0).toBe(true); + }); +}); diff --git a/packages/web3/test/integration/ws.test.ts b/packages/web3/test/integration/ws.test.ts index 7a11403fb32..0aa70152553 100644 --- a/packages/web3/test/integration/ws.test.ts +++ b/packages/web3/test/integration/ws.test.ts @@ -16,13 +16,9 @@ along with web3.js. If not, see . */ import { WebSocketProvider } from 'web3-providers-ws'; -import { - describeIf, getSystemTestProvider, isWs, -} from '../shared_fixtures/system_tests_utils'; +import { describeIf, getSystemTestProvider, isWs } from '../shared_fixtures/system_tests_utils'; import Web3 from '../../src/index'; - - describe('Web3 instance', () => { let web3: Web3; @@ -33,11 +29,13 @@ describe('Web3 instance', () => { describeIf(isWs)('web3 ws tests', () => { it('should connect and disconnect using safe disconnect subscription successfully', async () => { - const subscription = await web3.eth.subscribe("newBlockHeaders"); - // eslint-disable-next-line - subscription.unsubscribe(); - // eslint-disable-next-line - await expect((web3.currentProvider as WebSocketProvider).safeDisconnect()).resolves.not.toThrow(); + const subscription = await web3.eth.subscribe('newBlockHeaders'); + // eslint-disable-next-line + subscription.unsubscribe(); + // eslint-disable-next-line + await expect( + (web3.currentProvider as WebSocketProvider).safeDisconnect(), + ).resolves.not.toThrow(); }); }); -}); \ No newline at end of file +}); diff --git a/packages/web3/test/stress/long_ws_tests/nodejs_test/long_connection_ws.js b/packages/web3/test/stress/long_ws_tests/nodejs_test/long_connection_ws.js index 6d7a60a04cb..39770ed6def 100644 --- a/packages/web3/test/stress/long_ws_tests/nodejs_test/long_connection_ws.js +++ b/packages/web3/test/stress/long_ws_tests/nodejs_test/long_connection_ws.js @@ -16,7 +16,7 @@ along with web3.js. If not, see . */ /* eslint-disable */ const { Web3 } = require('../../../../lib/commonjs'); -const secrets = require('../../../../../../.secrets.json'); +const secrets = require('../../../../../../.secrets.json'); let web3; let attempt = 0; @@ -26,45 +26,51 @@ let end; // constantly send requests through WS for 10 hours const sendRequests = () => { - start = new Date(); - console.log("start:",start) - return new Promise((resolve, reject) => { - // send a request in intervals of 10 minutes - intervalId = setInterval( async() => { - try{ - const block = await web3.eth.getBlock() - attempt++; - console.log(block) - console.log("successful calls:", attempt, "has ran for:", attempt*10, "minutes") - if (attempt === 144) { // after 10 hours - clearInterval(intervalId); - resolve(""); - } - } catch (error) { - clearInterval(intervalId); - reject(error); - } - },600000) // every 10 minutes - }) - -} + start = new Date(); + console.log('start:', start); + return new Promise((resolve, reject) => { + // send a request in intervals of 10 minutes + intervalId = setInterval(async () => { + try { + const block = await web3.eth.getBlock(); + attempt++; + console.log(block); + console.log('successful calls:', attempt, 'has ran for:', attempt * 10, 'minutes'); + if (attempt === 144) { + // after 10 hours + clearInterval(intervalId); + resolve(''); + } + } catch (error) { + clearInterval(intervalId); + reject(error); + } + }, 600000); // every 10 minutes + }); +}; const main = async () => { - - try { - // You will need to set mainnet infura provider - const provider = secrets.MAINNET.WS; - web3 = new Web3(provider); - const promise = sendRequests(); - await promise; - end = new Date(); - console.log("websocket test successful") - } catch (e) { - console.warn("error occurred during ws test, on attempt: ", attempt, "program ran for: ", attempt ,"minutes with error: ", e) - } - console.log("start", start) - console.log("end", end) - process.exit(); -} + try { + // You will need to set mainnet infura provider + const provider = secrets.MAINNET.WS; + web3 = new Web3(provider); + const promise = sendRequests(); + await promise; + end = new Date(); + console.log('websocket test successful'); + } catch (e) { + console.warn( + 'error occurred during ws test, on attempt: ', + attempt, + 'program ran for: ', + attempt, + 'minutes with error: ', + e, + ); + } + console.log('start', start); + console.log('end', end); + process.exit(); +}; main(); diff --git a/packages/web3/test/stress/setup.js b/packages/web3/test/stress/setup.js index c480060944a..d527ad558d3 100644 --- a/packages/web3/test/stress/setup.js +++ b/packages/web3/test/stress/setup.js @@ -18,4 +18,3 @@ along with web3.js. If not, see . // Have to use `require` because of Jest issue https://jestjs.io/docs/ecmascript-modules // eslint-disable-next-line @typescript-eslint/no-require-imports require('../config/setup'); - diff --git a/packages/web3/test/unit/contract-middleware.test.ts b/packages/web3/test/unit/contract-middleware.test.ts index 1d7f7d2095d..cf178bef3ad 100644 --- a/packages/web3/test/unit/contract-middleware.test.ts +++ b/packages/web3/test/unit/contract-middleware.test.ts @@ -15,9 +15,10 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ -import { CTransactionMiddleware } from -// eslint-disable-next-line import/no-relative-packages -"../fixtures/transaction_middleware"; +import { + CTransactionMiddleware, + // eslint-disable-next-line import/no-relative-packages +} from '../fixtures/transaction_middleware'; import { Web3 } from '../../src/index'; import { @@ -47,8 +48,5 @@ describe('Contract Middleware', () => { expect(web3.eth.getTransactionMiddleware()).toBeDefined(); expect(contractB.getTransactionMiddleware()).toBeDefined(); expect(web3.eth.getTransactionMiddleware()).toEqual(contractB.getTransactionMiddleware()); - }); - }); - diff --git a/packages/web3/test/unit/web3.config.test.ts b/packages/web3/test/unit/web3.config.test.ts index dbe6682c391..3478d83c8e9 100644 --- a/packages/web3/test/unit/web3.config.test.ts +++ b/packages/web3/test/unit/web3.config.test.ts @@ -16,137 +16,155 @@ along with web3.js. If not, see . */ import { ETH_DATA_FORMAT } from 'web3-types'; -import {Web3Context} from 'web3-core'; +import { Web3Context } from 'web3-core'; import { Web3 } from '../../src'; describe('web3config web3 tests', () => { - - describe('web3config contract', () => { - - it('create web3context with configs and should set it for web3', async () => { - const context = new Web3Context("http://127.0.0.1:8545"); - context.setConfig({defaultTransactionType: "0x0"}); - const web3 = new Web3(context); - expect(web3.getContextObject().config.defaultTransactionType).toBe("0x0"); - expect(web3.config.defaultTransactionType).toBe("0x0"); - expect(web3.eth.getContextObject().config.defaultTransactionType).toBe("0x0") - }); - - it('should be able to create web3 and setconfig for contracts', async () => { - const web3 = new Web3("http://127.0.0.1:8545"); - web3.setConfig({defaultTransactionType: "0x0"}); - expect(web3.getContextObject().config.defaultTransactionType).toBe("0x0"); - expect(web3.config.defaultTransactionType).toBe("0x0"); - expect(web3.eth.getContextObject().config.defaultTransactionType).toBe("0x0") - - const contract = new web3.eth.Contract([], ""); - expect(contract.config.defaultTransactionType).toBe("0x0") - expect(contract.getContextObject().config.defaultTransactionType).toBe("0x0"); - - contract.setConfig({contractDataInputFill:"both"}); - expect(contract.getContextObject().config.contractDataInputFill).toBe("both"); - - // web3 config shouldn't change - expect(web3.getContextObject().config.contractDataInputFill).toBe("data"); - expect(web3.config.contractDataInputFill).toBe("data"); - expect(web3.eth.getContextObject().config.contractDataInputFill).toBe("data") - }); - it('should change web3 config context but not contract config context', async () => { - const web3 = new Web3("http://127.0.0.1:8545"); - const contract = new web3.eth.Contract([]) - web3.setConfig({defaultTransactionType:"0x0"}); - expect(contract.getContextObject().config.defaultTransactionType).toBe("0x2") - expect(web3.getContextObject().config.defaultTransactionType).toBe("0x0"); - }); - - it('should not change web3config when changing contract config context', async () => { - const web3 = new Web3("http://127.0.0.1:8545"); - const contract = new web3.eth.Contract([]) - contract.setConfig({defaultTransactionType:"0x0"}); - expect(contract.getContextObject().config.defaultTransactionType).toBe("0x0") - expect(web3.getContextObject().config.defaultTransactionType).toBe("0x2"); - }); - - it('should create two contracts with different configs', () => { - const web3 = new Web3('http://127.0.0.1:8545'); - - web3.setConfig({ contractDataInputFill: "data" }); - const c1 = new web3.eth.Contract([], '') - - const c2 = new web3.eth.Contract([], new Web3Context({config: {contractDataInputFill: "input"}})) - - const c3 = new web3.eth.Contract([], {dataInputFill: "input"}) - expect(web3.config.contractDataInputFill).toBe("data") - expect(c1.config.contractDataInputFill).toBe("data") - expect(c2.config.contractDataInputFill).toBe("input"); - expect(c3.config.contractDataInputFill).toBe("input"); - - }); - - it('should create a contract with context and returnFormat properly with different parameters', () => { - const web3 = new Web3('http://127.0.0.1:8545'); - web3.setConfig({ contractDataInputFill: "data" }); - - // create contract with context in second param - const c1 = new web3.eth.Contract([], new Web3Context({config: {contractDataInputFill: "input"}})) - - // create contract with context in third param - const c2 = new web3.eth.Contract([], "", new Web3Context({config: {contractDataInputFill: "both"}})) - - // create contract with context in fourth param - const c3 = new web3.eth.Contract([], "", {gas: "gas"}, new Web3Context({config: {contractDataInputFill: "both"}})) - - expect(c1.config.contractDataInputFill).toBe("input") - expect(c1.getContextObject().config.contractDataInputFill).toBe("input"); - - expect(c2.config.contractDataInputFill).toBe("both") - expect(c2.getContextObject().config.contractDataInputFill).toBe("both"); - - expect(c3.config.contractDataInputFill).toBe("both") - expect(c3.getContextObject().config.contractDataInputFill).toBe("both"); - - // create contract with returnFormat in fourth param - const c4 = new web3.eth.Contract([], "", {gas: "gas"}, ETH_DATA_FORMAT); - - // create contract with returnFormat in fifth param - const c5 = new web3.eth.Contract([], "", {gas: "gas"}, new Web3Context({config: {contractDataInputFill: "data"}}), ETH_DATA_FORMAT) - - expect(c4.config.contractDataInputFill).toBe("data") - expect(c4.getContextObject().config.contractDataInputFill).toBe("data"); - - expect(c5.config.contractDataInputFill).toBe("data") - expect(c5.getContextObject().config.contractDataInputFill).toBe("data"); - }) - - it('should create contracts with different ways to configure', () => { - const web3 = new Web3('http://127.0.0.1:8545'); - web3.setConfig({ contractDataInputFill: "data" }); - - const c1 = new web3.eth.Contract([], '') - - const c2 = new web3.eth.Contract([], new Web3Context({config: {contractDataInputFill: "input"}})) - - const c3 = new web3.eth.Contract([], {dataInputFill: "input"}) - - expect(web3.config.contractDataInputFill).toBe("data") - expect(c1.config.contractDataInputFill).toBe("data") - expect(c2.config.contractDataInputFill).toBe("input"); - expect(c3.config.contractDataInputFill).toBe("input"); - - }); - - it('should populate dataInputFill properly', () => { - const web3 = new Web3("http://127.0.0.1:8545"); - // create a contract with options as second parameter - const c1 = new web3.eth.Contract([], {dataInputFill: "both"}); - expect((c1.config.contractDataInputFill)).toBe("both"); - - // create a contract with options as third parameter - const c2 = new web3.eth.Contract([], "", {dataInputFill: "both"}); - expect((c2.config.contractDataInputFill)).toBe("both"); - - }); - }) - // TODO: finish config unit tests - + describe('web3config contract', () => { + it('create web3context with configs and should set it for web3', async () => { + const context = new Web3Context('http://127.0.0.1:8545'); + context.setConfig({ defaultTransactionType: '0x0' }); + const web3 = new Web3(context); + expect(web3.getContextObject().config.defaultTransactionType).toBe('0x0'); + expect(web3.config.defaultTransactionType).toBe('0x0'); + expect(web3.eth.getContextObject().config.defaultTransactionType).toBe('0x0'); + }); + + it('should be able to create web3 and setconfig for contracts', async () => { + const web3 = new Web3('http://127.0.0.1:8545'); + web3.setConfig({ defaultTransactionType: '0x0' }); + expect(web3.getContextObject().config.defaultTransactionType).toBe('0x0'); + expect(web3.config.defaultTransactionType).toBe('0x0'); + expect(web3.eth.getContextObject().config.defaultTransactionType).toBe('0x0'); + + const contract = new web3.eth.Contract([], ''); + expect(contract.config.defaultTransactionType).toBe('0x0'); + expect(contract.getContextObject().config.defaultTransactionType).toBe('0x0'); + + contract.setConfig({ contractDataInputFill: 'both' }); + expect(contract.getContextObject().config.contractDataInputFill).toBe('both'); + + // web3 config shouldn't change + expect(web3.getContextObject().config.contractDataInputFill).toBe('data'); + expect(web3.config.contractDataInputFill).toBe('data'); + expect(web3.eth.getContextObject().config.contractDataInputFill).toBe('data'); + }); + it('should change web3 config context but not contract config context', async () => { + const web3 = new Web3('http://127.0.0.1:8545'); + const contract = new web3.eth.Contract([]); + web3.setConfig({ defaultTransactionType: '0x0' }); + expect(contract.getContextObject().config.defaultTransactionType).toBe('0x2'); + expect(web3.getContextObject().config.defaultTransactionType).toBe('0x0'); + }); + + it('should not change web3config when changing contract config context', async () => { + const web3 = new Web3('http://127.0.0.1:8545'); + const contract = new web3.eth.Contract([]); + contract.setConfig({ defaultTransactionType: '0x0' }); + expect(contract.getContextObject().config.defaultTransactionType).toBe('0x0'); + expect(web3.getContextObject().config.defaultTransactionType).toBe('0x2'); + }); + + it('should create two contracts with different configs', () => { + const web3 = new Web3('http://127.0.0.1:8545'); + + web3.setConfig({ contractDataInputFill: 'data' }); + const c1 = new web3.eth.Contract([], ''); + + const c2 = new web3.eth.Contract( + [], + new Web3Context({ config: { contractDataInputFill: 'input' } }), + ); + + const c3 = new web3.eth.Contract([], { dataInputFill: 'input' }); + expect(web3.config.contractDataInputFill).toBe('data'); + expect(c1.config.contractDataInputFill).toBe('data'); + expect(c2.config.contractDataInputFill).toBe('input'); + expect(c3.config.contractDataInputFill).toBe('input'); + }); + + it('should create a contract with context and returnFormat properly with different parameters', () => { + const web3 = new Web3('http://127.0.0.1:8545'); + web3.setConfig({ contractDataInputFill: 'data' }); + + // create contract with context in second param + const c1 = new web3.eth.Contract( + [], + new Web3Context({ config: { contractDataInputFill: 'input' } }), + ); + + // create contract with context in third param + const c2 = new web3.eth.Contract( + [], + '', + new Web3Context({ config: { contractDataInputFill: 'both' } }), + ); + + // create contract with context in fourth param + const c3 = new web3.eth.Contract( + [], + '', + { gas: 'gas' }, + new Web3Context({ config: { contractDataInputFill: 'both' } }), + ); + + expect(c1.config.contractDataInputFill).toBe('input'); + expect(c1.getContextObject().config.contractDataInputFill).toBe('input'); + + expect(c2.config.contractDataInputFill).toBe('both'); + expect(c2.getContextObject().config.contractDataInputFill).toBe('both'); + + expect(c3.config.contractDataInputFill).toBe('both'); + expect(c3.getContextObject().config.contractDataInputFill).toBe('both'); + + // create contract with returnFormat in fourth param + const c4 = new web3.eth.Contract([], '', { gas: 'gas' }, ETH_DATA_FORMAT); + + // create contract with returnFormat in fifth param + const c5 = new web3.eth.Contract( + [], + '', + { gas: 'gas' }, + new Web3Context({ config: { contractDataInputFill: 'data' } }), + ETH_DATA_FORMAT, + ); + + expect(c4.config.contractDataInputFill).toBe('data'); + expect(c4.getContextObject().config.contractDataInputFill).toBe('data'); + + expect(c5.config.contractDataInputFill).toBe('data'); + expect(c5.getContextObject().config.contractDataInputFill).toBe('data'); + }); + + it('should create contracts with different ways to configure', () => { + const web3 = new Web3('http://127.0.0.1:8545'); + web3.setConfig({ contractDataInputFill: 'data' }); + + const c1 = new web3.eth.Contract([], ''); + + const c2 = new web3.eth.Contract( + [], + new Web3Context({ config: { contractDataInputFill: 'input' } }), + ); + + const c3 = new web3.eth.Contract([], { dataInputFill: 'input' }); + + expect(web3.config.contractDataInputFill).toBe('data'); + expect(c1.config.contractDataInputFill).toBe('data'); + expect(c2.config.contractDataInputFill).toBe('input'); + expect(c3.config.contractDataInputFill).toBe('input'); + }); + + it('should populate dataInputFill properly', () => { + const web3 = new Web3('http://127.0.0.1:8545'); + // create a contract with options as second parameter + const c1 = new web3.eth.Contract([], { dataInputFill: 'both' }); + expect(c1.config.contractDataInputFill).toBe('both'); + + // create a contract with options as third parameter + const c2 = new web3.eth.Contract([], '', { dataInputFill: 'both' }); + expect(c2.config.contractDataInputFill).toBe('both'); + }); + }); + // TODO: finish config unit tests }); diff --git a/packages/web3/test/unit/web3.test.ts b/packages/web3/test/unit/web3.test.ts index 3cd00a9e718..fdd20f8a6b0 100644 --- a/packages/web3/test/unit/web3.test.ts +++ b/packages/web3/test/unit/web3.test.ts @@ -21,9 +21,9 @@ import { Web3 } from '../../src/web3'; describe('Web3 object', () => { it('should be able to set and read web3 providers', () => { - const web3NoProvider = new Web3(""); + const web3NoProvider = new Web3(''); expect(web3NoProvider).toBeTruthy(); - expect(web3NoProvider.provider).toBe(""); + expect(web3NoProvider.provider).toBe(''); const web3 = new Web3('http://somenode'); expect(web3).toBeTruthy(); diff --git a/packages/web3/test/unit/web3eip6963.test.ts b/packages/web3/test/unit/web3eip6963.test.ts index 1f465aba124..e9e719e7552 100644 --- a/packages/web3/test/unit/web3eip6963.test.ts +++ b/packages/web3/test/unit/web3eip6963.test.ts @@ -15,77 +15,81 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ -import { - onNewProviderDiscovered, - requestEIP6963Providers -} from "../../src/web3_eip6963"; +import { onNewProviderDiscovered, requestEIP6963Providers } from '../../src/web3_eip6963'; describe('requestEIP6963Providers', () => { - it('should reject with an error if window object is not available', async () => { - // Mocking window object absence - (global as any).window = undefined; - - // eslint-disable-next-line @typescript-eslint/no-unsafe-call - await expect(requestEIP6963Providers()).rejects.toThrow("window object not available, EIP-6963 is intended to be used within a browser"); - }); - - it('should resolve with updated providers map when events are triggered', async () => { - class CustomEventPolyfill extends Event { - public detail: any; - public constructor(eventType: string, eventInitDict: any) { - super(eventType, eventInitDict); - this.detail = eventInitDict.detail; - } - } - - (global as any).CustomEvent = CustomEventPolyfill; - - const mockProviderDetail = { - info: { uuid: 'test-uuid', name: 'Test Provider', icon: 'test-icon', rdns: 'test-rdns' }, - provider: {} // Mock provider object - }; - - const mockEvent = { - type: 'eip6963:announceProvider', - detail: mockProviderDetail - }; - - // Mock window methods - (global as any).window = { - addEventListener: jest.fn().mockImplementation( - - (_event, callback) => callback(mockEvent)), // eslint-disable-line - dispatchEvent: jest.fn() - }; - - const result = await requestEIP6963Providers(); - - expect(result).toEqual(new Map([['test-uuid', mockProviderDetail]])); - }); - - it('onNewProviderDiscovered should throw an error if window object is not available', () => { - // Mock the window object not being available - (global as any).window = undefined; - - // Expect an error to be thrown - expect(() => { - // eslint-disable-next-line @typescript-eslint/no-empty-function - onNewProviderDiscovered((_providerEvent) => {}); - }).toThrow("window object not available, EIP-6963 is intended to be used within a browser"); - - - }); - - it('onNewProviderDiscovered should add an event listener when window object is available', () => { - (global as any).window = { - addEventListener: jest.fn(), - }; - - const callback = jest.fn(); - onNewProviderDiscovered(callback); - - // Expect the callback to have been called when the event listener is added - expect(global.window.addEventListener).toHaveBeenCalledWith('web3:providersMapUpdated', callback); - }); - -}); \ No newline at end of file + it('should reject with an error if window object is not available', async () => { + // Mocking window object absence + (global as any).window = undefined; + + // eslint-disable-next-line @typescript-eslint/no-unsafe-call + await expect(requestEIP6963Providers()).rejects.toThrow( + 'window object not available, EIP-6963 is intended to be used within a browser', + ); + }); + + it('should resolve with updated providers map when events are triggered', async () => { + class CustomEventPolyfill extends Event { + public detail: any; + public constructor(eventType: string, eventInitDict: any) { + super(eventType, eventInitDict); + this.detail = eventInitDict.detail; + } + } + + (global as any).CustomEvent = CustomEventPolyfill; + + const mockProviderDetail = { + info: { + uuid: 'test-uuid', + name: 'Test Provider', + icon: 'test-icon', + rdns: 'test-rdns', + }, + provider: {}, // Mock provider object + }; + + const mockEvent = { + type: 'eip6963:announceProvider', + detail: mockProviderDetail, + }; + + // Mock window methods + (global as any).window = { + addEventListener: jest + .fn() + .mockImplementation((_event, callback) => callback(mockEvent)), // eslint-disable-line + dispatchEvent: jest.fn(), + }; + + const result = await requestEIP6963Providers(); + + expect(result).toEqual(new Map([['test-uuid', mockProviderDetail]])); + }); + + it('onNewProviderDiscovered should throw an error if window object is not available', () => { + // Mock the window object not being available + (global as any).window = undefined; + + // Expect an error to be thrown + expect(() => { + // eslint-disable-next-line @typescript-eslint/no-empty-function + onNewProviderDiscovered(_providerEvent => {}); + }).toThrow('window object not available, EIP-6963 is intended to be used within a browser'); + }); + + it('onNewProviderDiscovered should add an event listener when window object is available', () => { + (global as any).window = { + addEventListener: jest.fn(), + }; + + const callback = jest.fn(); + onNewProviderDiscovered(callback); + + // Expect the callback to have been called when the event listener is added + expect(global.window.addEventListener).toHaveBeenCalledWith( + 'web3:providersMapUpdated', + callback, + ); + }); +}); diff --git a/scripts/system_tests_utils.ts b/scripts/system_tests_utils.ts index 11f9bcef717..e634b98a35b 100644 --- a/scripts/system_tests_utils.ts +++ b/scripts/system_tests_utils.ts @@ -55,7 +55,7 @@ import { // eslint-disable-next-line import/no-extraneous-dependencies import { Personal } from 'web3-eth-personal'; // eslint-disable-next-line import/no-extraneous-dependencies -import {Web3, WebSocketProvider } from 'web3'; +import { Web3, WebSocketProvider } from 'web3'; // eslint-disable-next-line import/no-extraneous-dependencies import { NonPayableMethodObject } from 'web3-eth-contract'; @@ -83,7 +83,7 @@ export const BACKEND = { MAINNET: 'mainnet', }; -export const getSystemTestProviderUrl = (): string => +export const getSystemTestProviderUrl = (): string => getEnvVar('WEB3_SYSTEM_TEST_PROVIDER') ?? DEFAULT_SYSTEM_PROVIDER; export const getSystemTestProvider = (): @@ -156,21 +156,18 @@ export const waitForOpenConnection = async ( export const closeOpenConnection = async (web3Context: Web3Context) => { if ( - web3Context?.provider && ( - web3Context?.provider instanceof WebSocketProvider || - web3Context?.provider instanceof IpcProvider - - ) && + web3Context?.provider && + (web3Context?.provider instanceof WebSocketProvider || + web3Context?.provider instanceof IpcProvider) && 'disconnect' in (web3Context.provider as unknown as Web3BaseProvider) ) { - - (web3Context.provider as unknown as Web3BaseProvider).reset(); - (web3Context.provider as unknown as Web3BaseProvider).disconnect(); + (web3Context.provider as unknown as Web3BaseProvider).reset(); + (web3Context.provider as unknown as Web3BaseProvider).disconnect(); - await new Promise(resolve => { - setTimeout(resolve, 1000); - }); - } + await new Promise(resolve => { + setTimeout(resolve, 1000); + }); + } }; export const createAccountProvider = (context: Web3Context) => { @@ -232,8 +229,7 @@ export const refillAccount = async (from: string, to: string, value: string | nu value, }); - if(receipt.status !== BigInt(1)) - throw new Error("refillAccount failed"); + if (receipt.status !== BigInt(1)) throw new Error('refillAccount failed'); await closeOpenConnection(web3Eth); }; @@ -246,7 +242,6 @@ export const createNewAccount = async (config?: { password?: string; doNotImport?: boolean; }): Promise<{ address: string; privateKey: string }> => { - const acc = config?.privateKey ? privateKeyToAccount(config?.privateKey) : _createAccount(); const clientUrl = DEFAULT_SYSTEM_PROVIDER; @@ -295,7 +290,6 @@ export const createNewAccount = async (config?: { return { address: acc.address.toLowerCase(), privateKey: acc.privateKey }; }; - let tempAccountList: { address: string; privateKey: string }[] = []; const walletsOnWorker = 20; @@ -482,7 +476,7 @@ export const sendFewSampleTxs = async (cnt = 1) => { const web3 = new Web3(DEFAULT_SYSTEM_PROVIDER); const fromAcc = await createLocalAccount(web3); const toAcc = createAccount(); - const res: TransactionReceipt[]= []; + const res: TransactionReceipt[] = []; for (let i = 0; i < cnt; i += 1) { // eslint-disable-next-line no-await-in-loop const receipt = await web3.eth.sendTransaction({ @@ -492,12 +486,9 @@ export const sendFewSampleTxs = async (cnt = 1) => { gas: '300000', }); - if(receipt.status !== BigInt(1)) - throw new Error("sendFewSampleTxs failed "); + if (receipt.status !== BigInt(1)) throw new Error('sendFewSampleTxs failed '); - res.push( - receipt - ); + res.push(receipt); } await closeOpenConnection(web3); return res; @@ -523,14 +514,15 @@ export const waitForCondition = async ( conditionFunc: () => boolean, logicFunc: () => Promise | void, maxIterations = 10, // 10 times - duration = 8000, // check after each 8 seconds + duration = 8000, // check after each 8 seconds ): Promise => { return new Promise((resolve, reject) => { let iterations = 0; // eslint-disable-next-line @typescript-eslint/no-misused-promises const interval = setInterval(async () => { try { - if (iterations > 0 && conditionFunc()) { // wait duration before first check + if (iterations > 0 && conditionFunc()) { + // wait duration before first check clearInterval(interval); await logicFunc(); resolve(); @@ -548,4 +540,4 @@ export const waitForCondition = async ( } }, duration); }); -}; \ No newline at end of file +}; diff --git a/templates/.prettierignore.tmpl b/templates/.prettierignore.tmpl index 76075e77df3..32e43f51bd7 100644 --- a/templates/.prettierignore.tmpl +++ b/templates/.prettierignore.tmpl @@ -4,6 +4,7 @@ LICENSE mocha.opts .DS_Store REVISION +.eslintcache # rc files .*rc diff --git a/templates/cypress.config.js b/templates/cypress.config.js index 977e51c90db..2b000caf46e 100644 --- a/templates/cypress.config.js +++ b/templates/cypress.config.js @@ -25,7 +25,7 @@ const config = { }, specPattern: 'test/integration/**/**/*.test.ts', excludeSpecPattern: ['**/contract_defaults_extra.test.ts'], - defaultCommandTimeout: 120000 + defaultCommandTimeout: 120000, }, }; diff --git a/tools/web3-plugin-example/CHANGELOG.md b/tools/web3-plugin-example/CHANGELOG.md index 76e9b8f8b96..f2a7f07a098 100644 --- a/tools/web3-plugin-example/CHANGELOG.md +++ b/tools/web3-plugin-example/CHANGELOG.md @@ -94,8 +94,8 @@ Transaction middleware (#7088) ## [1.1.1] -### Changed +### Changed - Dependencies updated -## [Unreleased] \ No newline at end of file +## [Unreleased] diff --git a/tools/web3-plugin-example/src/custom_rpc_methods.ts b/tools/web3-plugin-example/src/custom_rpc_methods.ts index d5ff583ddf5..80af3e76e2e 100644 --- a/tools/web3-plugin-example/src/custom_rpc_methods.ts +++ b/tools/web3-plugin-example/src/custom_rpc_methods.ts @@ -38,14 +38,11 @@ export class CustomRpcMethodsPlugin extends Web3PluginBase { } public link(parentContext: Web3Context): void { - - if (this.web3Middleware) - parentContext.requestManager.setMiddleware(this.web3Middleware); + if (this.web3Middleware) parentContext.requestManager.setMiddleware(this.web3Middleware); super.link(parentContext); } - public async customRpcMethod() { return this.requestManager.send({ method: 'custom_rpc_method', @@ -59,7 +56,6 @@ export class CustomRpcMethodsPlugin extends Web3PluginBase { params: [parameter1, parameter2], }); } - } // Module Augmentation diff --git a/tools/web3-plugin-example/src/request_manager_middleware.ts b/tools/web3-plugin-example/src/request_manager_middleware.ts index bf16bc619f8..6557b836651 100644 --- a/tools/web3-plugin-example/src/request_manager_middleware.ts +++ b/tools/web3-plugin-example/src/request_manager_middleware.ts @@ -42,16 +42,13 @@ export class Web3Middleware implements RequestManagerMiddleware { } 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'], - }; - } + } 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'], + }; + } return Promise.resolve(reqObj as JsonRpcPayload); } diff --git a/tools/web3-plugin-example/src/transaction_middleware.ts b/tools/web3-plugin-example/src/transaction_middleware.ts index d38eec8127b..736f1fed6ff 100644 --- a/tools/web3-plugin-example/src/transaction_middleware.ts +++ b/tools/web3-plugin-example/src/transaction_middleware.ts @@ -15,24 +15,21 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ -import { TransactionMiddleware, TransactionMiddlewareData } from "web3-eth"; +import { TransactionMiddleware, TransactionMiddlewareData } from 'web3-eth'; -// Sample Transaction Middleware +// Sample Transaction Middleware export class Web3TransactionMiddleware implements TransactionMiddleware { - // eslint-disable-next-line class-methods-use-this - public async processTransaction(transaction: TransactionMiddlewareData, - _options?: { [key: string]: unknown } | undefined): - - Promise { - + public async processTransaction( + transaction: TransactionMiddlewareData, + _options?: { [key: string]: unknown } | undefined, + ): Promise { // eslint-disable-next-line prefer-const let txObj = { ...transaction }; - // Add your logic here for transaction modification + // Add your logic here for transaction modification txObj.data = '0x123'; return Promise.resolve(txObj); } - } diff --git a/tools/web3-plugin-example/src/transaction_middleware_plugin.ts b/tools/web3-plugin-example/src/transaction_middleware_plugin.ts index bd9eca6b848..69fbc52adf9 100644 --- a/tools/web3-plugin-example/src/transaction_middleware_plugin.ts +++ b/tools/web3-plugin-example/src/transaction_middleware_plugin.ts @@ -31,16 +31,13 @@ export class TransactionMiddlewarePlugin extends Web3PluginBase { } public link(parentContext: Web3Context): void { - - if (this.txMiddleware){ + if (this.txMiddleware) { // Following can modify Web3-Eth and also Web3-Eth-Contract packages transactions - + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call (parentContext as any).Web3Eth.setTransactionMiddleware(this.txMiddleware); } super.link(parentContext); } - } - diff --git a/tools/web3-plugin-example/test/unit/contract_transaction_middleware.test.ts b/tools/web3-plugin-example/test/unit/contract_transaction_middleware.test.ts index 024e4219d28..201a8b040e6 100644 --- a/tools/web3-plugin-example/test/unit/contract_transaction_middleware.test.ts +++ b/tools/web3-plugin-example/test/unit/contract_transaction_middleware.test.ts @@ -21,9 +21,7 @@ import { TransactionMiddlewarePlugin } from '../../src/transaction_middleware_pl import { blockMockResult, receiptMockResult } from './fixtures/transactions_data'; describe('Contract Transaction Middleware', () => { - it('should modify contracts deployment transaction before signing and sending', async () => { - // This will allow Contract Transaction modification before signing and gas estimations const web3 = new Web3('http://127.0.0.1:8545'); @@ -35,7 +33,7 @@ describe('Contract Transaction Middleware', () => { // Create a spy for eth_sendTransaction const sendTransactionSpy = jest.fn(); - web3.requestManager.send = jest.fn(async (request) => { + web3.requestManager.send = jest.fn(async request => { blockNum += 1; if (request.method === 'eth_getBlockByNumber') { @@ -47,13 +45,15 @@ describe('Contract Transaction Middleware', () => { if (request.method === 'eth_sendTransaction') { // Call the spy with the request params sendTransactionSpy(request.params); - return Promise.resolve("0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f"); + return Promise.resolve( + '0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f', + ); } if (request.method === 'eth_getTransactionReceipt') { return Promise.resolve(receiptMockResult.result); } - return Promise.resolve("Unknown Request" as any); + return Promise.resolve('Unknown Request' as any); }); /// Mock block ends here @@ -62,40 +62,41 @@ describe('Contract Transaction Middleware', () => { const contract: Contract = new web3.eth.Contract(GreeterAbi); - await contract.deploy( - { + await contract + .deploy({ data: GreeterBytecode, arguments: ['My Greeting'], } as any) - .send( - { from: '0x6E599DA0bfF7A6598AC1224E4985430Bf16458a4' } - ); // this should call Tx middleware for contract deploy + .send({ from: '0x6E599DA0bfF7A6598AC1224E4985430Bf16458a4' }); // this should call Tx middleware for contract deploy - const deployedContract = new web3.eth.Contract(GreeterAbi, "0x5FbDB2315678afecb367f032d93F642f64180aa3"); - await deployedContract.methods.increment().send( - { from: '0x6E599DA0bfF7A6598AC1224E4985430Bf16458a4' }); // this should call Tx middleware for method send + const deployedContract = new web3.eth.Contract( + GreeterAbi, + '0x5FbDB2315678afecb367f032d93F642f64180aa3', + ); + await deployedContract.methods + .increment() + .send({ from: '0x6E599DA0bfF7A6598AC1224E4985430Bf16458a4' }); // this should call Tx middleware for method send // First, check the number of calls expect(sendTransactionSpy).toHaveBeenCalledTimes(2); - const expectedData = "0x123"; + const expectedData = '0x123'; // Then, check each call individually expect(sendTransactionSpy.mock.calls[0][0]).toEqual( expect.arrayContaining([ expect.objectContaining({ - data: expectedData - }) - ]) + data: expectedData, + }), + ]), ); expect(sendTransactionSpy.mock.calls[1][0]).toEqual( expect.arrayContaining([ expect.objectContaining({ - data: expectedData - }) - ]) + data: expectedData, + }), + ]), ); }); - }); diff --git a/tools/web3-plugin-example/test/unit/fixtures/transactions_data.ts b/tools/web3-plugin-example/test/unit/fixtures/transactions_data.ts index 189e2135ae4..5daf37d9bb9 100644 --- a/tools/web3-plugin-example/test/unit/fixtures/transactions_data.ts +++ b/tools/web3-plugin-example/test/unit/fixtures/transactions_data.ts @@ -16,102 +16,104 @@ along with web3.js. If not, see . */ export const blockMockResult = { - "jsonrpc": "2.0", - "id": "a40a81fa-1f8b-4bb2-a0ad-eef9b6d4636f", - "result": { - "baseFeePerGas": "0x44dab2983", - "blobGasUsed": "0x20000", - "difficulty": "0x0", - "excessBlobGas": "0x1c0000", - "extraData": "0x407273796e636275696c646572", - "gasLimit": "0x1c9c380", - "gasUsed": "0xb7a086", - "hash": "0xf2b1729965179032b17165678a1a212fa31cb008e30f4011ffe8ebdddbd02b95", - "logsBloom": "0xc3a70590c1c62524173d1892e33888067101934dc0891c2c9a898252b6f320215084a48906452960820188d32bba6fb82ec989018a0268603a00a4c6432a11276c9a038c676938eb68bc436c9905a9a1b08d238fb4458f48498215808bec81112e2a3a54869ff22422a8e491093da8a40f601d198417041cd22f799f9048865006e0b069ab049b852442b310396248088145e2810f230f9a44000c6868bc73e9afa8832a8ac92fd609007ac53c0a9cba0645ce298080184624e8040831dbc331f5e618072407050250021b3210e542781183a612d4618c1244000d421a6ca9c01a57e86a085402c55ab413f840a001e7117894d0469e20c2304a9655e344f60d", - "miner": "0x1f9090aae28b8a3dceadf281b0f12828e676c326", - "mixHash": "0x787ab1d511b72df60a705bb4cfc4e92e2f9d203e3e007ae3a0f757425951ca24", - "nonce": "0x0000000000000000", - "number": "0x131ad16", - "parentBeaconBlockRoot": "0x03bbca9fd0c7a0a020de04287f489112c79bc268220e9ff8e18957cd0d5c3cad", - "parentHash": "0xb1d8fa7b8346421d373a6d4c28575155516cea17c12a3df7201170c9e561b38c", - "receiptsRoot": "0x4ec500bdcd761ad505b2a989156c9a9628058d415acc93d800487c7c76308c59", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0xcb90", - "stateRoot": "0xafbb8743c0a5f4740e322217cb1f2780ee5c57c32bcd04e9256b09efc1a70568", - "timestamp": "0x6661ab8b", - "totalDifficulty": "0xc70d815d562d3cfa955", - "transactions": [ - "0x589956b75d19dbaf9911f246c23d4b3327ef234872ec1931c419041b23eb5b41", - "0x4d3793f20c25979bd329cafdd889ba6be015cfc999acce8642d6e757b5192e93", - "0x5ba5618ca5a14bab50862255dc69726a498346f9832bd0fd1394e8834e56790b", - "0x6df9678f350db7e30afc930b7246bf1c144b9acb7fd1d25d7e107d550ed5a061", - "0xb8f48ff2876cc393725ea4162421754dfb74ff2364a12d4d3de2c6269f1958c7", - "0x2e5cf7c0607025038b6ccd871dc9ce85af686fd5fa2c82e605198af9afa92cca", - "0x307fb855836feff5d8d0969fa4a44d3c6ae31d335da6577f48f9496d6fe9e0b9", - "0x1362bed1aa8a30d28b7b76c35c2a8601b257058beffa9490dcb20de12bcb15b2", - "0x234c7cc346c204022b2e5ead6d2e8c02317aeb0ec5ca82bd97c2b5d5e59a280b", - ], - "transactionsRoot": "0xc21a4d667b5f841538430b1e2c002c598f2178628ad1d61ea2fda462d1216607", - "uncles": [], - "withdrawals": [ - { - "address": "0xea97dc2523c0479484076660f150833e264c41e9", - "amount": "0x11b6d8c", - "index": "0x2dbe454", - "validatorIndex": "0x10f646" - }, - { - "address": "0xb3e84b6c6409826dc45432b655d8c9489a14a0d7", - "amount": "0x11b4ce2", - "index": "0x2dbe455", - "validatorIndex": "0x10f647" - }, - { - "address": "0x7e2a2fa2a064f693f0a55c5639476d913ff12d05", - "amount": "0x11ad733", - "index": "0x2dbe456", - "validatorIndex": "0x10f648" - }, - - ], - "withdrawalsRoot": "0x2914fa2f5ed93880ed45b58e8f6d14f20c645988400d83c59109964e2053fe1a" - } + jsonrpc: '2.0', + id: 'a40a81fa-1f8b-4bb2-a0ad-eef9b6d4636f', + result: { + baseFeePerGas: '0x44dab2983', + blobGasUsed: '0x20000', + difficulty: '0x0', + excessBlobGas: '0x1c0000', + extraData: '0x407273796e636275696c646572', + gasLimit: '0x1c9c380', + gasUsed: '0xb7a086', + hash: '0xf2b1729965179032b17165678a1a212fa31cb008e30f4011ffe8ebdddbd02b95', + logsBloom: + '0xc3a70590c1c62524173d1892e33888067101934dc0891c2c9a898252b6f320215084a48906452960820188d32bba6fb82ec989018a0268603a00a4c6432a11276c9a038c676938eb68bc436c9905a9a1b08d238fb4458f48498215808bec81112e2a3a54869ff22422a8e491093da8a40f601d198417041cd22f799f9048865006e0b069ab049b852442b310396248088145e2810f230f9a44000c6868bc73e9afa8832a8ac92fd609007ac53c0a9cba0645ce298080184624e8040831dbc331f5e618072407050250021b3210e542781183a612d4618c1244000d421a6ca9c01a57e86a085402c55ab413f840a001e7117894d0469e20c2304a9655e344f60d', + miner: '0x1f9090aae28b8a3dceadf281b0f12828e676c326', + mixHash: '0x787ab1d511b72df60a705bb4cfc4e92e2f9d203e3e007ae3a0f757425951ca24', + nonce: '0x0000000000000000', + number: '0x131ad16', + parentBeaconBlockRoot: '0x03bbca9fd0c7a0a020de04287f489112c79bc268220e9ff8e18957cd0d5c3cad', + parentHash: '0xb1d8fa7b8346421d373a6d4c28575155516cea17c12a3df7201170c9e561b38c', + receiptsRoot: '0x4ec500bdcd761ad505b2a989156c9a9628058d415acc93d800487c7c76308c59', + sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347', + size: '0xcb90', + stateRoot: '0xafbb8743c0a5f4740e322217cb1f2780ee5c57c32bcd04e9256b09efc1a70568', + timestamp: '0x6661ab8b', + totalDifficulty: '0xc70d815d562d3cfa955', + transactions: [ + '0x589956b75d19dbaf9911f246c23d4b3327ef234872ec1931c419041b23eb5b41', + '0x4d3793f20c25979bd329cafdd889ba6be015cfc999acce8642d6e757b5192e93', + '0x5ba5618ca5a14bab50862255dc69726a498346f9832bd0fd1394e8834e56790b', + '0x6df9678f350db7e30afc930b7246bf1c144b9acb7fd1d25d7e107d550ed5a061', + '0xb8f48ff2876cc393725ea4162421754dfb74ff2364a12d4d3de2c6269f1958c7', + '0x2e5cf7c0607025038b6ccd871dc9ce85af686fd5fa2c82e605198af9afa92cca', + '0x307fb855836feff5d8d0969fa4a44d3c6ae31d335da6577f48f9496d6fe9e0b9', + '0x1362bed1aa8a30d28b7b76c35c2a8601b257058beffa9490dcb20de12bcb15b2', + '0x234c7cc346c204022b2e5ead6d2e8c02317aeb0ec5ca82bd97c2b5d5e59a280b', + ], + transactionsRoot: '0xc21a4d667b5f841538430b1e2c002c598f2178628ad1d61ea2fda462d1216607', + uncles: [], + withdrawals: [ + { + address: '0xea97dc2523c0479484076660f150833e264c41e9', + amount: '0x11b6d8c', + index: '0x2dbe454', + validatorIndex: '0x10f646', + }, + { + address: '0xb3e84b6c6409826dc45432b655d8c9489a14a0d7', + amount: '0x11b4ce2', + index: '0x2dbe455', + validatorIndex: '0x10f647', + }, + { + address: '0x7e2a2fa2a064f693f0a55c5639476d913ff12d05', + amount: '0x11ad733', + index: '0x2dbe456', + validatorIndex: '0x10f648', + }, + ], + withdrawalsRoot: '0x2914fa2f5ed93880ed45b58e8f6d14f20c645988400d83c59109964e2053fe1a', + }, }; export const receiptMockResult = { - "jsonrpc": "2.0", - "id": 1, - "result": { - "blockHash": "0xf4ad699b98241caf3930779b7d919a77f1727e67cef6ed1ce2a4c655ba812d54", - "blockNumber": "0x131ad35", - // eslint-disable-next-line no-null/no-null - "contractAddress": null, - "cumulativeGasUsed": "0x8cae7a", - "effectiveGasPrice": "0x4c9bc2d65", - "from": "0xab6fd3a7c6ce9db945889cd018e028e055f3bc2e", - "gasUsed": "0xa145", - "logs": [ - { - "address": "0xdac17f958d2ee523a2206206994597c13d831ec7", - "blockHash": "0xf4ad699b98241caf3930779b7d919a77f1727e67cef6ed1ce2a4c655ba812d54", - "blockNumber": "0x131ad35", - "data": "0x000000000000000000000000000000000000000000000000000000000016e360", - "logIndex": "0xdf", - "removed": false, - "topics": [ - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x000000000000000000000000ab6fd3a7c6ce9db945889cd018e028e055f3bc2e", - "0x00000000000000000000000051112f9f08a2174fe3fc96aad8f07e82d1cccd00" - ], - "transactionHash": "0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f", - "transactionIndex": "0x82" - } - ], - "logsBloom": "0x00000000000000000000000002000000000000000000000000000000004000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000400000000000100000000000000000000000000080000000000000000000040000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000400000000000000000000000", - "status": "0x1", - "to": "0xdac17f958d2ee523a2206206994597c13d831ec7", - "transactionHash": "0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f", - "transactionIndex": "0x82", - "type": "0x2" - } -}; \ No newline at end of file + jsonrpc: '2.0', + id: 1, + result: { + blockHash: '0xf4ad699b98241caf3930779b7d919a77f1727e67cef6ed1ce2a4c655ba812d54', + blockNumber: '0x131ad35', + // eslint-disable-next-line no-null/no-null + contractAddress: null, + cumulativeGasUsed: '0x8cae7a', + effectiveGasPrice: '0x4c9bc2d65', + from: '0xab6fd3a7c6ce9db945889cd018e028e055f3bc2e', + gasUsed: '0xa145', + logs: [ + { + address: '0xdac17f958d2ee523a2206206994597c13d831ec7', + blockHash: '0xf4ad699b98241caf3930779b7d919a77f1727e67cef6ed1ce2a4c655ba812d54', + blockNumber: '0x131ad35', + data: '0x000000000000000000000000000000000000000000000000000000000016e360', + logIndex: '0xdf', + removed: false, + topics: [ + '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', + '0x000000000000000000000000ab6fd3a7c6ce9db945889cd018e028e055f3bc2e', + '0x00000000000000000000000051112f9f08a2174fe3fc96aad8f07e82d1cccd00', + ], + transactionHash: + '0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f', + transactionIndex: '0x82', + }, + ], + logsBloom: + '0x00000000000000000000000002000000000000000000000000000000004000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000400000000000100000000000000000000000000080000000000000000000040000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000400000000000000000000000', + status: '0x1', + to: '0xdac17f958d2ee523a2206206994597c13d831ec7', + transactionHash: '0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f', + transactionIndex: '0x82', + type: '0x2', + }, +}; diff --git a/tools/web3-plugin-example/test/unit/transaction_middleware.test.ts b/tools/web3-plugin-example/test/unit/transaction_middleware.test.ts index 2009e028283..40a71a4fb1e 100644 --- a/tools/web3-plugin-example/test/unit/transaction_middleware.test.ts +++ b/tools/web3-plugin-example/test/unit/transaction_middleware.test.ts @@ -20,8 +20,7 @@ import { TransactionMiddlewarePlugin } from '../../src/transaction_middleware_pl import { blockMockResult, receiptMockResult } from './fixtures/transactions_data'; describe('Transaction Middleware', () => { - - // This will allow Transaction modification before signing and gas estimations + // This will allow Transaction modification before signing and gas estimations it('should modify transaction before signing', async () => { const web3 = new Web3('http://127.0.0.1:8545'); const plugin = new TransactionMiddlewarePlugin(); @@ -29,34 +28,32 @@ describe('Transaction Middleware', () => { /// Mock block starts - Mock web3 internal calls for test let blockNum = 1000; - web3.requestManager.send = jest.fn(async (request) => { + web3.requestManager.send = jest.fn(async request => { blockNum += 1; - if(request.method === 'eth_getBlockByNumber'){ - + if (request.method === 'eth_getBlockByNumber') { return Promise.resolve(blockMockResult.result); } - if(request.method === 'eth_call'){ - - return Promise.resolve("0x"); + if (request.method === 'eth_call') { + return Promise.resolve('0x'); } - if(request.method === 'eth_blockNumber'){ - + if (request.method === 'eth_blockNumber') { return Promise.resolve(blockNum.toString(16)); } - if(request.method === 'eth_sendTransaction'){ - - // Test that middleware modified transaction - // eslint-disable-next-line jest/no-conditional-expect - expect((request.params as any)[0].data).toBe("0x123"); - - return Promise.resolve("0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f"); + if (request.method === 'eth_sendTransaction') { + // Test that middleware modified transaction + // eslint-disable-next-line jest/no-conditional-expect + expect((request.params as any)[0].data).toBe('0x123'); + + return Promise.resolve( + '0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f', + ); } if (request.method === 'eth_getTransactionReceipt') { return Promise.resolve(receiptMockResult.result); } - - return Promise.resolve("Unknown Request" as any); + + return Promise.resolve('Unknown Request' as any); }); /// Mock block ends here @@ -67,10 +64,9 @@ describe('Transaction Middleware', () => { from: '0x6E599DA0bfF7A6598AC1224E4985430Bf16458a4', to: '0x6f1DF96865D09d21e8f3f9a7fbA3b17A11c7C53C', value: '0x1', - data: '0x1' + data: '0x1', }; - - await web3.eth.sendTransaction(transaction as any); + await web3.eth.sendTransaction(transaction as any); }); }); diff --git a/yarn.lock b/yarn.lock index e5ac4b827bb..0884fd08293 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3083,6 +3083,13 @@ ansi-escapes@^4.2.1, ansi-escapes@^4.3.0: dependencies: type-fest "^0.21.3" +ansi-escapes@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-7.0.0.tgz#00fc19f491bbb18e1d481b97868204f92109bfe7" + integrity sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw== + dependencies: + environment "^1.0.0" + ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" @@ -3127,7 +3134,7 @@ ansi-styles@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== -ansi-styles@^6.1.0: +ansi-styles@^6.0.0, ansi-styles@^6.1.0, ansi-styles@^6.2.1: version "6.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== @@ -3651,6 +3658,13 @@ braces@^3.0.2, braces@~3.0.2: dependencies: fill-range "^7.0.1" +braces@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + brorand@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" @@ -3931,6 +3945,11 @@ chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2: ansi-styles "^4.1.0" supports-color "^7.1.0" +chalk@~5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385" + integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== + char-regex@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" @@ -4041,6 +4060,13 @@ cli-cursor@3.1.0, cli-cursor@^3.1.0: dependencies: restore-cursor "^3.1.0" +cli-cursor@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-5.0.0.tgz#24a4831ecf5a6b01ddeb32fb71a4b2088b0dce38" + integrity sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw== + dependencies: + restore-cursor "^5.0.0" + cli-spinners@2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.6.1.tgz#adc954ebe281c37a6319bfa401e6dd2488ffb70d" @@ -4051,6 +4077,14 @@ cli-spinners@^2.5.0: resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.7.0.tgz#f815fd30b5f9eaac02db604c7a231ed7cb2f797a" integrity sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw== +cli-truncate@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-4.0.0.tgz#6cc28a2924fee9e25ce91e973db56c7066e6172a" + integrity sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA== + dependencies: + slice-ansi "^5.0.0" + string-width "^7.0.0" + cli-width@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" @@ -4162,6 +4196,11 @@ colorette@^2.0.14: resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== +colorette@^2.0.20: + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== + columnify@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/columnify/-/columnify-1.6.0.tgz#6989531713c9008bb29735e61e37acf5bd553cf3" @@ -4202,6 +4241,11 @@ commander@^8.1.0: resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== +commander@~12.1.0: + version "12.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3" + integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA== + common-ancestor-path@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz#4f7d2d1394d91b7abdf51871c62f71eadb0182a7" @@ -4601,6 +4645,13 @@ debug@^3.2.7: dependencies: ms "^2.1.1" +debug@~4.3.6: + version "4.3.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.6.tgz#2ab2c38fbaffebf8aa95fdfe6d88438c7a13c52b" + integrity sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg== + dependencies: + ms "2.1.2" + decamelize-keys@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" @@ -4933,6 +4984,11 @@ emoji-regex@^10.1.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.1.0.tgz#d50e383743c0f7a5945c47087295afc112e3cf66" integrity sha512-xAEnNCT3w2Tg6MA7ly6QqYJvEoY1tm9iIjJ3yMKK9JPlWuRHAMoe5iETwQnx3M9TVbFMfsrBgWKR+IsmswwNjg== +emoji-regex@^10.3.0: + version "10.4.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.4.0.tgz#03553afea80b3975749cfcb36f776ca268e413d4" + integrity sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw== + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -5000,6 +5056,11 @@ envinfo@^7.7.3, envinfo@^7.7.4: resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475" integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw== +environment@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/environment/-/environment-1.1.0.tgz#8e86c66b180f363c7ab311787e0259665f45a9f1" + integrity sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q== + err-code@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9" @@ -5744,6 +5805,21 @@ execa@^7.1.1: signal-exit "^3.0.7" strip-final-newline "^3.0.0" +execa@~8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-8.0.1.tgz#51f6a5943b580f963c3ca9c6321796db8cc39b8c" + integrity sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^8.0.1" + human-signals "^5.0.0" + is-stream "^3.0.0" + merge-stream "^2.0.0" + npm-run-path "^5.1.0" + onetime "^6.0.0" + signal-exit "^4.1.0" + strip-final-newline "^3.0.0" + exit@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" @@ -6008,6 +6084,13 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + finalhandler@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" @@ -6329,6 +6412,11 @@ get-caller-file@^2.0.5: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== +get-east-asian-width@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz#5e6ebd9baee6fb8b7b6bd505221065f0cd91f64e" + integrity sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA== + get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.2.tgz#336975123e05ad0b7ba41f152ee4aadbea6cf598" @@ -6368,6 +6456,11 @@ get-stream@^6.0.0, get-stream@^6.0.1: resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== +get-stream@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-8.0.1.tgz#def9dfd71742cd7754a7761ed43749a27d02eca2" + integrity sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA== + get-symbol-description@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" @@ -6929,6 +7022,11 @@ human-signals@^4.3.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-4.3.1.tgz#ab7f811e851fca97ffbd2c1fe9a958964de321b2" integrity sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ== +human-signals@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-5.0.0.tgz#42665a284f9ae0dade3ba41ebc37eb4b852f3a28" + integrity sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ== + humanize-ms@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" @@ -7276,6 +7374,18 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== +is-fullwidth-code-point@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz#fae3167c729e7463f8461ce512b080a49268aa88" + integrity sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ== + +is-fullwidth-code-point@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz#9609efced7c2f97da7b60145ef481c787c7ba704" + integrity sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA== + dependencies: + get-east-asian-width "^1.0.0" + is-function@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.2.tgz#4f097f30abf6efadac9833b17ca5dc03f8144e08" @@ -8606,6 +8716,11 @@ libnpmpublish@7.1.4: sigstore "^1.4.0" ssri "^10.0.1" +lilconfig@~3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.2.tgz#e4a7c3cb549e3a606c8dcc32e5ae1005e62c05cb" + integrity sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow== + lines-and-columns@^1.1.6: version "1.2.4" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" @@ -8616,6 +8731,34 @@ lines-and-columns@~2.0.3: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-2.0.3.tgz#b2f0badedb556b747020ab8ea7f0373e22efac1b" integrity sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w== +lint-staged@^15.2.9: + version "15.2.9" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-15.2.9.tgz#bf70d40b6b192df6ad756fb89822211615e0f4da" + integrity sha512-BZAt8Lk3sEnxw7tfxM7jeZlPRuT4M68O0/CwZhhaw6eeWu0Lz5eERE3m386InivXB64fp/mDID452h48tvKlRQ== + dependencies: + chalk "~5.3.0" + commander "~12.1.0" + debug "~4.3.6" + execa "~8.0.1" + lilconfig "~3.1.2" + listr2 "~8.2.4" + micromatch "~4.0.7" + pidtree "~0.6.0" + string-argv "~0.3.2" + yaml "~2.5.0" + +listr2@~8.2.4: + version "8.2.4" + resolved "https://registry.yarnpkg.com/listr2/-/listr2-8.2.4.tgz#486b51cbdb41889108cb7e2c90eeb44519f5a77f" + integrity sha512-opevsywziHd3zHCVQGAj8zu+Z3yHNkkoYhWIGnq54RrCVwLz0MozotJEDnKsIBLvkfLGN6BLOyAeRrYI0pKA4g== + dependencies: + cli-truncate "^4.0.0" + colorette "^2.0.20" + eventemitter3 "^5.0.1" + log-update "^6.1.0" + rfdc "^1.4.1" + wrap-ansi "^9.0.0" + load-json-file@6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-6.2.0.tgz#5c7770b42cafa97074ca2848707c61662f4251a1" @@ -8696,6 +8839,17 @@ log-symbols@4.1.0, log-symbols@^4.1.0: chalk "^4.1.0" is-unicode-supported "^0.1.0" +log-update@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/log-update/-/log-update-6.1.0.tgz#1a04ff38166f94647ae1af562f4bd6a15b1b7cd4" + integrity sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w== + dependencies: + ansi-escapes "^7.0.0" + cli-cursor "^5.0.0" + slice-ansi "^7.1.0" + strip-ansi "^7.1.0" + wrap-ansi "^9.0.0" + lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -8955,6 +9109,14 @@ micromatch@^4.0.0, micromatch@^4.0.2, micromatch@^4.0.4: braces "^3.0.2" picomatch "^2.3.1" +micromatch@~4.0.7: + version "4.0.8" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== + dependencies: + braces "^3.0.3" + picomatch "^2.3.1" + mime-db@1.52.0: version "1.52.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" @@ -8982,6 +9144,11 @@ mimic-fn@^4.0.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== +mimic-function@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/mimic-function/-/mimic-function-5.0.1.tgz#acbe2b3349f99b9deaca7fb70e48b83e94e67076" + integrity sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA== + min-document@^2.19.0: version "2.19.0" resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" @@ -9810,6 +9977,13 @@ onetime@^6.0.0: dependencies: mimic-fn "^4.0.0" +onetime@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-7.0.0.tgz#9f16c92d8c9ef5120e3acd9dd9957cceecc1ab60" + integrity sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ== + dependencies: + mimic-function "^5.0.0" + open@^8.4.0: version "8.4.0" resolved "https://registry.yarnpkg.com/open/-/open-8.4.0.tgz#345321ae18f8138f82565a910fdc6b39e8c244f8" @@ -10189,6 +10363,11 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +pidtree@~0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.6.0.tgz#90ad7b6d42d5841e69e0a2419ef38f8883aa057c" + integrity sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g== + pify@5.0.0, pify@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/pify/-/pify-5.0.0.tgz#1f5eca3f5e87ebec28cc6d54a0e4aaf00acc127f" @@ -10804,6 +10983,14 @@ restore-cursor@^3.1.0: onetime "^5.1.0" signal-exit "^3.0.2" +restore-cursor@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-5.1.0.tgz#0766d95699efacb14150993f55baf0953ea1ebe7" + integrity sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA== + dependencies: + onetime "^7.0.0" + signal-exit "^4.1.0" + ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" @@ -10824,6 +11011,11 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== +rfdc@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.4.1.tgz#778f76c4fb731d93414e8f925fbecf64cce7f6ca" + integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA== + rimraf@^2.2.8, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" @@ -11151,6 +11343,11 @@ signal-exit@^4.0.1: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.0.2.tgz#ff55bb1d9ff2114c13b400688fa544ac63c36967" integrity sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q== +signal-exit@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + sigstore@^1.0.0, sigstore@^1.3.0, sigstore@^1.4.0: version "1.5.2" resolved "https://registry.yarnpkg.com/sigstore/-/sigstore-1.5.2.tgz#8d4c2a549341211cb08c687999843edc48c1a94c" @@ -11189,6 +11386,22 @@ slash@^4.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== +slice-ansi@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-5.0.0.tgz#b73063c57aa96f9cd881654b15294d95d285c42a" + integrity sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ== + dependencies: + ansi-styles "^6.0.0" + is-fullwidth-code-point "^4.0.0" + +slice-ansi@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-7.1.0.tgz#cd6b4655e298a8d1bdeb04250a433094b347b9a9" + integrity sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg== + dependencies: + ansi-styles "^6.2.1" + is-fullwidth-code-point "^5.0.0" + slide@^1.1.3: version "1.1.6" resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" @@ -11455,6 +11668,11 @@ statuses@2.0.1: resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== +string-argv@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6" + integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q== + string-length@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" @@ -11463,7 +11681,7 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -"string-width-cjs@npm:string-width@^4.2.0": +"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -11481,15 +11699,6 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -11499,6 +11708,15 @@ string-width@^5.0.1, string-width@^5.1.2: emoji-regex "^9.2.2" strip-ansi "^7.0.1" +string-width@^7.0.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-7.2.0.tgz#b5bb8e2165ce275d4d43476dd2700ad9091db6dc" + integrity sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ== + dependencies: + emoji-regex "^10.3.0" + get-east-asian-width "^1.0.0" + strip-ansi "^7.1.0" + string.prototype.trimend@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz#914a65baaab25fbdd4ee291ca7dde57e869cb8d0" @@ -11536,7 +11754,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -11550,13 +11768,6 @@ strip-ansi@^3.0.0, strip-ansi@^3.0.1: dependencies: ansi-regex "^2.0.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" @@ -11564,6 +11775,13 @@ strip-ansi@^7.0.1: dependencies: ansi-regex "^6.0.1" +strip-ansi@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" + integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== + dependencies: + ansi-regex "^6.0.1" + strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" @@ -12643,16 +12861,7 @@ workerpool@6.2.1: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -12670,6 +12879,15 @@ wrap-ansi@^8.1.0: string-width "^5.0.1" strip-ansi "^7.0.1" +wrap-ansi@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-9.0.0.tgz#1a3dc8b70d85eeb8398ddfb1e4a02cd186e58b3e" + integrity sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q== + dependencies: + ansi-styles "^6.2.1" + string-width "^7.0.0" + strip-ansi "^7.1.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -12808,6 +13026,11 @@ yaml@^1.10.0: resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== +yaml@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.5.0.tgz#c6165a721cf8000e91c36490a41d7be25176cf5d" + integrity sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw== + yargs-parser@20.2.4: version "20.2.4" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" From b3cb1b782cc2c62bd87909c7cdc426ed43a49c1c Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Fri, 13 Sep 2024 04:32:43 -0700 Subject: [PATCH 147/186] Document Formatting (#7222) * Document Formatting * Add More Example with `getBlockNumber` --- .../guides/getting_started/return-formats.md | 121 ++++++++++++++++++ .../web3_utils_module/mastering_web3-utils.md | 67 ++++++++++ packages/web3-types/src/data_format_types.ts | 5 + packages/web3-utils/src/formatter.ts | 21 +++ 4 files changed, 214 insertions(+) create mode 100644 docs/docs/guides/getting_started/return-formats.md diff --git a/docs/docs/guides/getting_started/return-formats.md b/docs/docs/guides/getting_started/return-formats.md new file mode 100644 index 00000000000..ae4287a8336 --- /dev/null +++ b/docs/docs/guides/getting_started/return-formats.md @@ -0,0 +1,121 @@ +--- +sidebar_position: 3 +sidebar_label: Return Formats +--- + +# Return Formats + +By default, Web3.js formats byte values as hexadecimal strings (e.g. `"0x221`") and number values as [`BigInt`s](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt). The default formats can be configured at the global level by updating the [`defaultReturnFormat` configuration option](/guides/web3_config/#defaultreturnformat). Many Web3.js functions (e.g. [`getBlock`](/api/web3-eth/function/getBlock), [`sendTransaction`](/api/web3-eth/function/sendTransaction)) accept an optional parameter named `returnFormat` of the [type `DataFormat`](/api/web3-types#DataFormat) that can be used to configure the format for data returned by that single function invocation. + +The following example demonstrates working with return formats: + +```ts +import { Block, FMT_BYTES, FMT_NUMBER, Numbers, Web3 } from "web3"; + +const web3 = new Web3("https://eth.llamarpc.com"); + +// use the default return format +web3.eth.getBlock().then((block: Block) => { + console.log(`Block #${block.number} Hash: ${block.hash}`); +}); +// ↳ Block #20735255 Hash: 0xbaea6dbd46fa810a27be4c9eac782602f8efe7512fb30a8455c127b101a23e22 + +// specify the return format for a single function invocation +web3.eth + .getBlockNumber({ + bytes: FMT_BYTES.HEX, + number: FMT_NUMBER.HEX, + }) + .then((blockNumber: Numbers) => { + console.log(`Block #${blockNumber}`); + }); +// ↳ Block #0x13c6517 + +// configure default return format for the web3-eth package +web3.eth.defaultReturnFormat = { + bytes: FMT_BYTES.UINT8ARRAY, + number: FMT_NUMBER.HEX, +}; + +web3.eth.getBlock().then((block: Block) => { + console.log(`Block #${block.number} Hash: [${block.hash}]`); +}); +// ↳ Block #0x13c6517 Hash: [186,234,109,...,162,62,34] +``` + +The supported return formats are: + +- Bytes + - [`FMT_BYTES.HEX`](/api/web3-types/enum/FMT_BYTES#HEX): hexadecimal [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) (e.g. `"0xdd"`) + ```ts + web3.eth + .getBlock(undefined, undefined, { + bytes: FMT_BYTES.HEX, + number: FMT_NUMBER.BIGINT, + }) + .then((block: Block) => { + console.log(`Block hash: ${block.hash}`); + }); + // ↳ Block hash: 0xbaea6dbd46fa810a27be4c9eac782602f8efe7512fb30a8455c127b101a23e22 + ``` + - [`FMT_BYTES.UINT8ARRAY`](/api/web3-types/enum/FMT_BYTES#UINT8ARRAY): [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) (e.g. `[ 2, 33 ]`) + ```ts + web3.eth + .getBlock(undefined, undefined, { + bytes: FMT_BYTES.UINT8ARRAY, + number: FMT_NUMBER.BIGINT, + }) + .then((block: Block) => { + console.log(`Block hash: [${block.hash}]`); + }); + // ↳ Block hash: [186,234,109,...,162,62,34] + ``` +- Numbers + - [`FMT_NUMBER.BIGINT`](/api/web3-types/enum/FMT_NUMBER#BIGINT): [`BigInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) (e.g. `221n`) + ```ts + web3.eth + .getBlockNumber({ + bytes: FMT_BYTES.HEX, + number: FMT_NUMBER.BIGINT, + }) + .then((blockNumber: Numbers) => { + console.log(`Block #${blockNumber}`); + }); + // ↳ Block #20735255 + ``` + - [`FMT_NUMBER.HEX`](/api/web3-types/enum/FMT_NUMBER#HEX): hexadecimal [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) (e.g. `"0xdd"`) + ```ts + web3.eth + .getBlockNumber({ + bytes: FMT_BYTES.HEX, + number: FMT_NUMBER.HEX, + }) + .then((blockNumber: Numbers) => { + console.log(`Block #${blockNumber}`); + }); + // ↳ Block #0x13c6517 + ``` + - [`FMT_NUMBER.NUMBER`](/api/web3-types/enum/FMT_NUMBER#NUMBER): [`Number`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number) (e.g. `221`) + ```ts + web3.eth + .getBlockNumber({ + bytes: FMT_BYTES.HEX, + number: FMT_NUMBER.NUMBER, + }) + .then((blockNumber: Numbers) => { + console.log(`Block #${blockNumber}`); + }); + // ↳ Block #20735255 + ``` + - [`FMT_NUMBER.STR`](/api/web3-types/enum/FMT_NUMBER#STR): [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) (e.g. `"221"`) + ```ts + web3.eth + .getBlockNumber({ + bytes: FMT_BYTES.HEX, + number: FMT_NUMBER.STR, + }) + .then((blockNumber: Numbers) => { + console.log(`Block #${blockNumber}`); + }); + // ↳ Block #20735255 + ``` 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 c1ea5b833f7..b60d2a50deb 100644 --- a/docs/docs/guides/web3_utils_module/mastering_web3-utils.md +++ b/docs/docs/guides/web3_utils_module/mastering_web3-utils.md @@ -240,3 +240,70 @@ console.log(web3.utils.compareBlockNumbers(2, 2)); // 0 ``` +### Formatting + +The [`format` function](/api/web3-utils/function/format) in the `web3-utils` package is used to convert data between equivalent formats. For example, bytes that are represented as a [`Uint8Array` type](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) can be formatted as a hexademical string (e.g. `"0xdd"`) or primitive JavaScript [`Number` types](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number) can be formatted as [`BigInt` types](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt). The `format` function expects two required parameters, `schema` and `data`, and accepts a third optional parameter, `returnFormat`. The `schema` parameter is used to describe how the data should be interpreted. The `data` parameter represents the data that is to be formatted. The [`returnFormat` parameter](#return-formats) specifies how the data should be formatted. + +Here are some example that demonstrate the use of the `format` function: + +```js +import { format } from "web3-utils"; +import { FMT_BYTES, FMT_NUMBER } from "web3-types"; + +// format a primitive number as a hexidecimal string +console.log(format({ format: "uint" }, 221, { number: FMT_NUMBER.HEX })); +// ↳ 0xdd + +// format a primitive number as a BigInt +console.log(format({ format: "uint" }, 221, { number: FMT_NUMBER.BIGINT })); +// ↳ 221n + +// format a stringified number as a hexidecimal string +console.log(format({ format: "uint" }, "221", { number: FMT_NUMBER.HEX })); +// ↳ 0xdd + +// format a Uint8Array of bytes as a hexidecimal string +console.log( + format({ format: "bytes" }, new Uint8Array([2, 33]), { + bytes: FMT_BYTES.HEX, + }), +); +// ↳ 0x0221 + +// format an array of values +console.log( + format({ type: "array", items: { format: "uint" } }, ["221", 1983], { + number: FMT_NUMBER.HEX, + }), +); +// ↳ [ '0xdd', '0x7bf' ] + +// format an object with multiple properties +console.log( + format( + { + type: "object", + properties: { + aNumber: { format: "uint" }, + someBytes: { format: "bytes" }, + }, + }, + { aNumber: "221", someBytes: new Uint8Array([2, 33]) }, + { bytes: FMT_BYTES.UINT8ARRAY, number: FMT_NUMBER.HEX }, + ), +); +// ↳ { aNumber: '0xdd', someBytes: Uint8Array(2) [ 2, 33 ] } +``` + +#### Return Formats + +The following return formats are supported: + +- Bytes + - [`FMT_BYTES.HEX`](/api/web3-types/enum/FMT_BYTES#HEX): hexadecimal [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) (e.g. `"0xdd"`) + - [`FMT_BYTES.UINT8ARRAY`](/api/web3-types/enum/FMT_BYTES#UINT8ARRAY): [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) (e.g. `[ 2, 33 ]`) +- Numbers + - [`FMT_NUMBER.BIGINT`](/api/web3-types/enum/FMT_NUMBER#BIGINT): [`BigInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) (e.g. `221n`) + - [`FMT_NUMBER.HEX`](/api/web3-types/enum/FMT_NUMBER#HEX): hexadecimal [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) (e.g. `"0xdd"`) + - [`FMT_NUMBER.NUMBER`](/api/web3-types/enum/FMT_NUMBER#NUMBER): [`Number`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number) (e.g. `221`) + - [`FMT_NUMBER.STR`](/api/web3-types/enum/FMT_NUMBER#STR): [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) (e.g. `"221"`) diff --git a/packages/web3-types/src/data_format_types.ts b/packages/web3-types/src/data_format_types.ts index 46c1f5352b8..b94521b935e 100644 --- a/packages/web3-types/src/data_format_types.ts +++ b/packages/web3-types/src/data_format_types.ts @@ -41,6 +41,11 @@ export type ByteTypes = { [FMT_BYTES.UINT8ARRAY]: Uint8Array; }; +/** + * Used to specify how data should be formatted. Bytes can be formatted as hexadecimal strings or + * Uint8Arrays. Numbers can be formatted as BigInts, hexadecimal strings, primitive numbers, or + * strings. + */ export type DataFormat = { readonly number: FMT_NUMBER; readonly bytes: FMT_BYTES; diff --git a/packages/web3-utils/src/formatter.ts b/packages/web3-utils/src/formatter.ts index 5050a26ef7d..9457d7e78c3 100644 --- a/packages/web3-utils/src/formatter.ts +++ b/packages/web3-utils/src/formatter.ts @@ -349,6 +349,27 @@ export const convert = ( return object; }; +/** + * Given data that can be interpreted according to the provided schema, returns equivalent data that has been formatted + * according to the provided return format. + * + * @param schema - how to interpret the data + * @param data - data to be formatted + * @param returnFormat - how to format the data + * @returns - formatted data + * + * @example + * + * ```js + * import { FMT_NUMBER, utils } from "web3"; + * + * console.log( + * utils.format({ format: "uint" }, "221", { number: FMT_NUMBER.HEX }), + * ); + * // 0xdd + * ``` + * + */ export const format = < DataType extends Record | unknown[] | unknown, ReturnType extends DataFormat, From a21078b9c5bec437340296f519133b0ddbbc83ce Mon Sep 17 00:00:00 2001 From: Nicolas Brugneaux Date: Tue, 17 Sep 2024 18:49:55 +0200 Subject: [PATCH 148/186] feat: add custom transaction schema to formatTransaction (#7227) * feat: add custom transaction schema to formatTransaction * docs: add entries to changelogs * tests: initial tests * fix: unused vars * tests: lint issues * refactor: pr review * fix: type errors * fix: dependency cycle * refactor: revert whitespaces changes * fix: types * fix: types * test: fix web3-eth-personal tests * refactor: remove config from manager * fix: types * fix: build issue * fix: CustomTransactionSchema type --- CHANGELOG.md | 21 ++++++++++++ docs/docs/guides/web3_config/index.md | 4 +++ packages/web3-core/CHANGELOG.md | 5 +++ packages/web3-core/src/types.ts | 6 ++++ packages/web3-core/src/web3_config.ts | 13 ++++++- .../__snapshots__/web3_context.test.ts.snap | 1 + .../web3-core/test/unit/web3_config.test.ts | 1 + packages/web3-eth-personal/CHANGELOG.md | 4 +++ packages/web3-eth-personal/src/personal.ts | 4 +-- .../src/rpc_method_wrappers.ts | 12 +++++-- .../test/unit/eth_personal.test.ts | 12 +++++-- packages/web3-eth/CHANGELOG.md | 8 +++++ packages/web3-eth/src/rpc_method_wrappers.ts | 23 ++++++++++--- packages/web3-eth/src/types.ts | 6 ++++ .../src/utils/decode_signed_transaction.ts | 10 ++++-- .../web3-eth/src/utils/format_transaction.ts | 5 +-- .../utils/prepare_transaction_for_signing.ts | 12 ++++--- packages/web3-eth/src/validation.ts | 17 ++++++++-- .../test/fixtures/format_transaction.ts | 34 +++++++++++++++++++ .../test/unit/format_transaction.test.ts | 26 ++++++++++++++ .../get_transaction.test.ts | 8 +++-- 21 files changed, 207 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6edd15446e5..e4a9943a1e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2702,3 +2702,24 @@ If there are any bugs, improvements, optimizations or any new feature proposal f - The callback function provided to the static `Web3.onNewProviderDiscovered` function expects a parameter of type `EIP6963ProvidersMapUpdateEvent` as opposed to `EIP6963AnnounceProviderEvent`. (#7242) ## [Unreleased] + +### Added + +#### web3-core + +- Adds a new property (`customTransactionSchema`) to `Web3ConfigOptions` +- Adds a new property (`config`) to `Web3RequestManager` + +#### web3-eth + +- Adds the same `{transactionSchema?: ValidationSchemaInput}` that exists in `formatTransaction` to `validateTransactionForSigning` + +### Changed + +#### web3-eth + +- Forwards the new `web3Context.config.customTransactionSchema` to `formatTransaction` + +#### web3-eth-personal + +- Forwards the new `web3Context.config.customTransactionSchema` to `formatTransaction` diff --git a/docs/docs/guides/web3_config/index.md b/docs/docs/guides/web3_config/index.md index 42561aedcbc..32f645a465a 100644 --- a/docs/docs/guides/web3_config/index.md +++ b/docs/docs/guides/web3_config/index.md @@ -28,6 +28,7 @@ There is list of configuration params that can be set for modifying behavior of - [defaultCommon](/guides/web3_config/#defaultcommon) - [defaultTransactionType](/guides/web3_config/#defaulttransactiontype) - [defaultMaxPriorityFeePerGas](/guides/web3_config/#defaultmaxpriorityfeepergas) +- [customTransactionSchema](/guides/web3_config/#customTransactionSchema) - [defaultReturnFormat](/guides/web3_config/#defaultreturnformat) ## Global level Config @@ -411,6 +412,9 @@ The `defaultMaxPriorityFeePerGas` option is used to set the [`defaultMaxPriority The default value of `defaultMaxPriorityFeePerGas` is 2500000000 (2.5gwei) in hexstring format. +### [customTransactionSchema](/api/web3-core/class/Web3Config#customTransactionSchema) +The `customTransactionSchema` option is used to allow [`formatTransaction`](/api/web3-eth/function/formatTransaction) to accept a custom schema to validate transactions. A use-case could be: your chain has an extra field in its transactions and you want to write a plugin that makes sending these transactions easier. + ### [defaultReturnFormat](/api/web3-core/class/Web3Config#defaultReturnFormat) The `defaultReturnFormat` option 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 diff --git a/packages/web3-core/CHANGELOG.md b/packages/web3-core/CHANGELOG.md index 18e3e0bf08a..ca126e01d03 100644 --- a/packages/web3-core/CHANGELOG.md +++ b/packages/web3-core/CHANGELOG.md @@ -234,3 +234,8 @@ Documentation: - `setConfig()` fix for `setMaxListenerWarningThreshold` fix (#5079) ## [Unreleased] + +### Added + +- Adds a new property (`customTransactionSchema`) to `Web3ConfigOptions` +- Adds a new property (`config`) to `Web3RequestManager` diff --git a/packages/web3-core/src/types.ts b/packages/web3-core/src/types.ts index b2b655b351a..b6b7d402584 100644 --- a/packages/web3-core/src/types.ts +++ b/packages/web3-core/src/types.ts @@ -23,6 +23,7 @@ import { Web3APIMethod, Web3APIReturnType, } from 'web3-types'; +import { Schema } from 'web3-validator'; export type TransactionTypeParser = (transaction: Transaction) => HexString | undefined; @@ -50,3 +51,8 @@ export interface RequestManagerMiddleware { options?: { [key: string]: unknown }, ): Promise>; } + +export type CustomTransactionSchema = { + type: string; + properties: Record; +}; diff --git a/packages/web3-core/src/web3_config.ts b/packages/web3-core/src/web3_config.ts index f617756ad12..ee397ea9daf 100644 --- a/packages/web3-core/src/web3_config.ts +++ b/packages/web3-core/src/web3_config.ts @@ -25,7 +25,7 @@ import { } from 'web3-types'; import { ConfigHardforkMismatchError, ConfigChainMismatchError } from 'web3-errors'; import { isNullish, toHex } from 'web3-utils'; -import { TransactionTypeParser } from './types.js'; +import { CustomTransactionSchema, TransactionTypeParser } from './types.js'; // eslint-disable-next-line import/no-cycle import { TransactionBuilder } from './web3_context.js'; import { Web3EventEmitter } from './web3_event_emitter.js'; @@ -59,6 +59,7 @@ export interface Web3ConfigOptions { }; transactionBuilder?: TransactionBuilder; transactionTypeParser?: TransactionTypeParser; + customTransactionSchema?: CustomTransactionSchema; defaultReturnFormat: DataFormat; } @@ -101,6 +102,7 @@ export abstract class Web3Config }, transactionBuilder: undefined, transactionTypeParser: undefined, + customTransactionSchema: undefined, defaultReturnFormat: DEFAULT_RETURN_FORMAT, }; @@ -520,6 +522,15 @@ export abstract class Web3Config this.config.transactionTypeParser = val; } + public get customTransactionSchema(): CustomTransactionSchema | undefined { + return this.config.customTransactionSchema; + } + + public set customTransactionSchema(schema: CustomTransactionSchema | undefined) { + this._triggerConfigChange('customTransactionSchema', schema); + this.config.customTransactionSchema = schema; + } + private _triggerConfigChange( config: K, newValue: Web3ConfigOptions[K], 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 e01ba14a467..7d280405bfb 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 @@ -6,6 +6,7 @@ exports[`Web3Context getContextObject should return correct context object 1`] = "config": { "blockHeaderTimeout": 10, "contractDataInputFill": "data", + "customTransactionSchema": undefined, "defaultAccount": undefined, "defaultBlock": "latest", "defaultChain": "mainnet", diff --git a/packages/web3-core/test/unit/web3_config.test.ts b/packages/web3-core/test/unit/web3_config.test.ts index bd250d6386a..7238c1fcb33 100644 --- a/packages/web3-core/test/unit/web3_config.test.ts +++ b/packages/web3-core/test/unit/web3_config.test.ts @@ -49,6 +49,7 @@ const defaultConfig = { defaultReturnFormat: DEFAULT_RETURN_FORMAT, transactionBuilder: undefined, transactionTypeParser: undefined, + customTransactionSchema: undefined, }; const setValue = { string: 'newValue', diff --git a/packages/web3-eth-personal/CHANGELOG.md b/packages/web3-eth-personal/CHANGELOG.md index 33f479b4ef5..abc79b58850 100644 --- a/packages/web3-eth-personal/CHANGELOG.md +++ b/packages/web3-eth-personal/CHANGELOG.md @@ -148,3 +148,7 @@ Documentation: - Dependencies updated ## [Unreleased] + +### Changed + +- Forwards the new `web3Context.config.customTransactionSchema` to `formatTransaction` diff --git a/packages/web3-eth-personal/src/personal.ts b/packages/web3-eth-personal/src/personal.ts index db8d2656703..012a0738803 100644 --- a/packages/web3-eth-personal/src/personal.ts +++ b/packages/web3-eth-personal/src/personal.ts @@ -159,7 +159,7 @@ export class Personal extends Web3Context { * ``` */ public async sendTransaction(tx: Transaction, passphrase: string) { - return rpcWrappers.sendTransaction(this.requestManager, tx, passphrase); + return rpcWrappers.sendTransaction(this.requestManager, tx, passphrase, this.config); } /** * Signs a transaction. This account needs to be unlocked. @@ -204,7 +204,7 @@ export class Personal extends Web3Context { * ``` */ public async signTransaction(tx: Transaction, passphrase: string) { - return rpcWrappers.signTransaction(this.requestManager, tx, passphrase); + return rpcWrappers.signTransaction(this.requestManager, tx, passphrase, this.config); } /** * Calculates an Ethereum specific signature with: diff --git a/packages/web3-eth-personal/src/rpc_method_wrappers.ts b/packages/web3-eth-personal/src/rpc_method_wrappers.ts index 51491714881..451b15074d9 100644 --- a/packages/web3-eth-personal/src/rpc_method_wrappers.ts +++ b/packages/web3-eth-personal/src/rpc_method_wrappers.ts @@ -14,7 +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 { Web3RequestManager } from 'web3-core'; +import { Web3RequestManager, Web3ConfigOptions } from 'web3-core'; import { toChecksumAddress, utf8ToHex } from 'web3-utils'; import { formatTransaction } from 'web3-eth'; import { Address, EthPersonalAPI, ETH_DATA_FORMAT, HexString, Transaction } from 'web3-types'; @@ -72,8 +72,11 @@ export const sendTransaction = async ( requestManager: Web3RequestManager, tx: Transaction, passphrase: string, + config?: Web3ConfigOptions, ) => { - const formattedTx = formatTransaction(tx, ETH_DATA_FORMAT); + const formattedTx = formatTransaction(tx, ETH_DATA_FORMAT, { + transactionSchema: config?.customTransactionSchema, + }); return personalRpcMethods.sendTransaction(requestManager, formattedTx, passphrase); }; @@ -82,8 +85,11 @@ export const signTransaction = async ( requestManager: Web3RequestManager, tx: Transaction, passphrase: string, + config?: Web3ConfigOptions, ) => { - const formattedTx = formatTransaction(tx, ETH_DATA_FORMAT); + const formattedTx = formatTransaction(tx, ETH_DATA_FORMAT, { + transactionSchema: config?.customTransactionSchema, + }); return personalRpcMethods.signTransaction(requestManager, formattedTx, passphrase); }; diff --git a/packages/web3-eth-personal/test/unit/eth_personal.test.ts b/packages/web3-eth-personal/test/unit/eth_personal.test.ts index fc2d545da10..45104d82d2d 100644 --- a/packages/web3-eth-personal/test/unit/eth_personal.test.ts +++ b/packages/web3-eth-personal/test/unit/eth_personal.test.ts @@ -185,7 +185,11 @@ describe('Personal', () => { await personal.sendTransaction(tx, 'password'); expect(eth.formatTransaction).toHaveBeenCalledTimes(1); - expect(eth.formatTransaction).toHaveBeenCalledWith(tx, ETH_DATA_FORMAT); + expect(eth.formatTransaction).toHaveBeenCalledWith( + tx, + ETH_DATA_FORMAT, + expect.anything(), + ); }); }); @@ -215,7 +219,11 @@ describe('Personal', () => { await personal.signTransaction(tx, 'password'); expect(eth.formatTransaction).toHaveBeenCalledTimes(1); - expect(eth.formatTransaction).toHaveBeenCalledWith(tx, ETH_DATA_FORMAT); + expect(eth.formatTransaction).toHaveBeenCalledWith( + tx, + ETH_DATA_FORMAT, + expect.anything(), + ); }); }); diff --git a/packages/web3-eth/CHANGELOG.md b/packages/web3-eth/CHANGELOG.md index 9005985b2b2..7d1470f593d 100644 --- a/packages/web3-eth/CHANGELOG.md +++ b/packages/web3-eth/CHANGELOG.md @@ -270,3 +270,11 @@ Documentation: - Change method `getTransactionReceipt` to not be casted as `TransactionReceipt` to give proper return type (#7159) ## [Unreleased] + +### Changed + +- Forwards the new `web3Context.config.customTransactionSchema` to `formatTransaction` + +### Added + +- Adds the same `{transactionSchema?: ValidationSchemaInput}` that exists in `formatTransaction` to `validateTransactionForSigning` diff --git a/packages/web3-eth/src/rpc_method_wrappers.ts b/packages/web3-eth/src/rpc_method_wrappers.ts index e5ffe9baf64..9931c56364f 100644 --- a/packages/web3-eth/src/rpc_method_wrappers.ts +++ b/packages/web3-eth/src/rpc_method_wrappers.ts @@ -429,6 +429,7 @@ export async function getTransaction( return isNullish(response) ? response : formatTransaction(response, returnFormat, { + transactionSchema: web3Context.config.customTransactionSchema, fillInputAndData: true, }); } @@ -448,6 +449,7 @@ export async function getPendingTransactions( transaction as unknown as Transaction, returnFormat ?? web3Context.defaultReturnFormat, { + transactionSchema: web3Context.config.customTransactionSchema, fillInputAndData: true, }, ), @@ -488,6 +490,7 @@ export async function getTransactionFromBlock( return isNullish(response) ? response : formatTransaction(response, returnFormat ?? web3Context.defaultReturnFormat, { + transactionSchema: web3Context.config.customTransactionSchema, fillInputAndData: true, }); } @@ -606,6 +609,9 @@ export function sendTransaction< to: getTransactionFromOrToAttr('to', web3Context, transaction), }, ETH_DATA_FORMAT, + { + transactionSchema: web3Context.config.customTransactionSchema, + }, ); try { @@ -847,7 +853,9 @@ export async function signTransaction( ) { const response = await ethRpcMethods.signTransaction( web3Context.requestManager, - formatTransaction(transaction, ETH_DATA_FORMAT), + formatTransaction(transaction, ETH_DATA_FORMAT, { + transactionSchema: web3Context.config.customTransactionSchema, + }), ); // Some clients only return the encoded signed transaction (e.g. Ganache) // while clients such as Geth return the desired SignedTransactionInfoAPI object @@ -862,6 +870,7 @@ export async function signTransaction( returnFormat, ), tx: formatTransaction((response as SignedTransactionInfoAPI).tx, returnFormat, { + transactionSchema: web3Context.config.customTransactionSchema, fillInputAndData: true, }), }; @@ -885,7 +894,9 @@ export async function call( const response = await ethRpcMethods.call( web3Context.requestManager, - formatTransaction(transaction, ETH_DATA_FORMAT), + formatTransaction(transaction, ETH_DATA_FORMAT, { + transactionSchema: web3Context.config.customTransactionSchema, + }), blockNumberFormatted, ); @@ -903,7 +914,9 @@ export async function estimateGas( blockNumber: BlockNumberOrTag = web3Context.defaultBlock, returnFormat: ReturnFormat, ) { - const transactionFormatted = formatTransaction(transaction, ETH_DATA_FORMAT); + const transactionFormatted = formatTransaction(transaction, ETH_DATA_FORMAT, { + transactionSchema: web3Context.config.customTransactionSchema, + }); const blockNumberFormatted = isBlockTag(blockNumber as string) ? (blockNumber as BlockTag) : format({ format: 'uint' }, blockNumber as Numbers, ETH_DATA_FORMAT); @@ -1074,7 +1087,9 @@ export async function createAccessList( const response = (await ethRpcMethods.createAccessList( web3Context.requestManager, - formatTransaction(transaction, ETH_DATA_FORMAT), + formatTransaction(transaction, ETH_DATA_FORMAT, { + transactionSchema: web3Context.config.customTransactionSchema, + }), blockNumberFormatted, )) as unknown as AccessListResult; diff --git a/packages/web3-eth/src/types.ts b/packages/web3-eth/src/types.ts index 9f9de0ec14a..cc3c86cd2ee 100644 --- a/packages/web3-eth/src/types.ts +++ b/packages/web3-eth/src/types.ts @@ -37,6 +37,7 @@ import { TransactionWithFromLocalWalletIndex, TransactionWithToLocalWalletIndex, } from 'web3-types'; +import { Schema } from 'web3-validator'; export type InternalTransaction = FormatType; @@ -105,3 +106,8 @@ export interface TransactionMiddleware { options?: { [key: string]: unknown }, ): Promise; } + +export type CustomTransactionSchema = { + type: string; + properties: Record; +}; diff --git a/packages/web3-eth/src/utils/decode_signed_transaction.ts b/packages/web3-eth/src/utils/decode_signed_transaction.ts index 943ea188e2c..6a313f9b775 100644 --- a/packages/web3-eth/src/utils/decode_signed_transaction.ts +++ b/packages/web3-eth/src/utils/decode_signed_transaction.ts @@ -24,6 +24,7 @@ import { bytesToHex, format, hexToBytes, keccak256 } from 'web3-utils'; import { TransactionFactory } from 'web3-eth-accounts'; import { detectRawTransactionType } from './detect_transaction_type.js'; import { formatTransaction } from './format_transaction.js'; +import { type CustomTransactionSchema } from '../types.js'; /** * Decodes an [RLP](https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp/#top) encoded transaction. @@ -35,7 +36,9 @@ import { formatTransaction } from './format_transaction.js'; export function decodeSignedTransaction( encodedSignedTransaction: HexStringBytes, returnFormat: ReturnFormat, - options: { fillInputAndData?: boolean } = { fillInputAndData: false }, + options: { fillInputAndData?: boolean; transactionSchema?: CustomTransactionSchema } = { + fillInputAndData: false, + }, ): SignedTransactionInfoAPI { return { raw: format({ format: 'bytes' }, encodedSignedTransaction, returnFormat), @@ -48,7 +51,10 @@ export function decodeSignedTransaction( type: detectRawTransactionType(hexToBytes(encodedSignedTransaction)), } as TransactionSignedAPI, returnFormat, - { fillInputAndData: options.fillInputAndData }, + { + fillInputAndData: options.fillInputAndData, + transactionSchema: options.transactionSchema, + }, ), }; } diff --git a/packages/web3-eth/src/utils/format_transaction.ts b/packages/web3-eth/src/utils/format_transaction.ts index 5333254db60..53d29659bbe 100644 --- a/packages/web3-eth/src/utils/format_transaction.ts +++ b/packages/web3-eth/src/utils/format_transaction.ts @@ -20,7 +20,8 @@ import { isNullish, ValidationSchemaInput } from 'web3-validator'; import { mergeDeep, format, bytesToHex, toHex } from 'web3-utils'; import { TransactionDataAndInputError } from 'web3-errors'; -import { transactionInfoSchema, transactionSchema } from '../schemas.js'; +import { transactionInfoSchema } from '../schemas.js'; +import { type CustomTransactionSchema } from '../types.js'; export function formatTransaction< ReturnFormat extends DataFormat = typeof DEFAULT_RETURN_FORMAT, @@ -29,7 +30,7 @@ export function formatTransaction< transaction: TransactionType, returnFormat: ReturnFormat = DEFAULT_RETURN_FORMAT as ReturnFormat, options: { - transactionSchema?: ValidationSchemaInput | typeof transactionSchema; + transactionSchema?: ValidationSchemaInput | CustomTransactionSchema | undefined; fillInputAndData?: boolean; } = { transactionSchema: transactionInfoSchema, diff --git a/packages/web3-eth/src/utils/prepare_transaction_for_signing.ts b/packages/web3-eth/src/utils/prepare_transaction_for_signing.ts index 5213e66c778..cd70e1e265c 100644 --- a/packages/web3-eth/src/utils/prepare_transaction_for_signing.ts +++ b/packages/web3-eth/src/utils/prepare_transaction_for_signing.ts @@ -134,12 +134,16 @@ export const prepareTransactionForSigning = async ( fillGasPrice, fillGasLimit, })) as unknown as PopulatedUnsignedTransaction; - const formattedTransaction = formatTransaction( - populatedTransaction, - ETH_DATA_FORMAT, - ) as unknown as FormatType; + const formattedTransaction = formatTransaction(populatedTransaction, ETH_DATA_FORMAT, { + transactionSchema: web3Context.config.customTransactionSchema, + }) as unknown as FormatType; + validateTransactionForSigning( formattedTransaction as unknown as FormatType, + undefined, + { + transactionSchema: web3Context.config.customTransactionSchema, + }, ); return TransactionFactory.fromTxData( diff --git a/packages/web3-eth/src/validation.ts b/packages/web3-eth/src/validation.ts index a818cc66c10..b318e16dd41 100644 --- a/packages/web3-eth/src/validation.ts +++ b/packages/web3-eth/src/validation.ts @@ -27,7 +27,13 @@ import { TransactionWithSenderAPI, ETH_DATA_FORMAT, } from 'web3-types'; -import { isAddress, isHexStrict, isHexString32Bytes, isNullish, isUInt } from 'web3-validator'; +import { + isAddress, + isHexStrict, + isHexString32Bytes, + isNullish, + isUInt, +} from 'web3-validator'; import { ChainMismatchError, HardforkMismatchError, @@ -48,7 +54,7 @@ import { UnsupportedFeeMarketError, } from 'web3-errors'; import { formatTransaction } from './utils/format_transaction.js'; -import { InternalTransaction } from './types.js'; +import { CustomTransactionSchema, InternalTransaction } from './types.js'; export function isBaseTransaction(value: BaseTransactionAPI): boolean { if (!isNullish(value.to) && !isAddress(value.to)) return false; @@ -282,6 +288,9 @@ export const validateGas = (transaction: InternalTransaction) => { export const validateTransactionForSigning = ( transaction: InternalTransaction, overrideMethod?: (transaction: InternalTransaction) => void, + options: { + transactionSchema?: CustomTransactionSchema; + } = { transactionSchema: undefined }, ) => { if (!isNullish(overrideMethod)) { overrideMethod(transaction); @@ -296,7 +305,9 @@ export const validateTransactionForSigning = ( validateBaseChain(transaction); validateHardfork(transaction); - const formattedTransaction = formatTransaction(transaction as Transaction, ETH_DATA_FORMAT); + const formattedTransaction = formatTransaction(transaction as Transaction, ETH_DATA_FORMAT, { + transactionSchema: options.transactionSchema, + }); validateGas(formattedTransaction); if ( diff --git a/packages/web3-eth/test/fixtures/format_transaction.ts b/packages/web3-eth/test/fixtures/format_transaction.ts index dc91dc7c823..6ab3fa0a9d2 100644 --- a/packages/web3-eth/test/fixtures/format_transaction.ts +++ b/packages/web3-eth/test/fixtures/format_transaction.ts @@ -210,6 +210,40 @@ export const numbersAsBigIntTransaction: FormatType< s: '0x7e1941b264348e80c78c4027afc65a87b0a5e43e86742b8ca0823584c6788fd0', }; +export type CustomFieldTransaction = Transaction & { feeCurrency: `0x${string}` }; +export const customFieldTransaction: FormatType< + CustomFieldTransaction, + { number: FMT_NUMBER.BIGINT; bytes: typeof DEFAULT_RETURN_FORMAT.bytes } +> = { + from: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', + to: '0x3535353535353535353535353535353535353535', + value: BigInt(100000000000), + gas: BigInt(21000), + gasPrice: BigInt(20000000000), + type: BigInt(0), + maxFeePerGas: BigInt(78000000000), + maxPriorityFeePerGas: BigInt(1230000000), + data: '0x', + nonce: BigInt(4), + chain: 'mainnet', + hardfork: 'berlin', + chainId: BigInt(1), + common: { + customChain: { + name: 'foo', + networkId: BigInt(4), + chainId: BigInt(66), + }, + baseChain: 'mainnet', + hardfork: 'berlin', + }, + gasLimit: BigInt(21000), + v: BigInt(37), + r: '0x4f4c17305743700648bc4f6cd3038ec6f6af0df73e31757007b7f59df7bee88d', + s: '0x7e1941b264348e80c78c4027afc65a87b0a5e43e86742b8ca0823584c6788fd0', + feeCurrency: '0x4242424242424242424242424242424242424242', +}; + const dummyTransaction: Transaction = { from: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', to: '0x3535353535353535353535353535353535353535', diff --git a/packages/web3-eth/test/unit/format_transaction.test.ts b/packages/web3-eth/test/unit/format_transaction.test.ts index 9ce83aaa941..d3c86c077bd 100644 --- a/packages/web3-eth/test/unit/format_transaction.test.ts +++ b/packages/web3-eth/test/unit/format_transaction.test.ts @@ -25,8 +25,11 @@ import { numbersAsStringTransaction, numbersAsNumberTransaction, bytesAsUint8ArrayTransaction, + customFieldTransaction, + CustomFieldTransaction, } from '../fixtures/format_transaction'; import { objectBigintToString } from '../fixtures/system_test_utils'; +import { transactionSchema } from '../../src'; const transactionsDataForNumberTypes: Record> = { [FMT_NUMBER.BIGINT]: numbersAsBigIntTransaction, @@ -116,4 +119,27 @@ describe('formatTransaction', () => { }), ); }); + + it('Accepts a custom schema', () => { + expect( + formatTransaction( + customFieldTransaction, + ).feeCurrency, + ).toBeUndefined(); + expect( + formatTransaction( + customFieldTransaction, + undefined, + { + transactionSchema: { + type: 'object', + properties: { + ...transactionSchema.properties, + feeCurrency: { format: 'address' }, + }, + }, + }, + ).feeCurrency, + ).toBeDefined(); + }); }); diff --git a/packages/web3-eth/test/unit/rpc_method_wrappers/get_transaction.test.ts b/packages/web3-eth/test/unit/rpc_method_wrappers/get_transaction.test.ts index 225a9e106ef..cb1315c56b1 100644 --- a/packages/web3-eth/test/unit/rpc_method_wrappers/get_transaction.test.ts +++ b/packages/web3-eth/test/unit/rpc_method_wrappers/get_transaction.test.ts @@ -21,7 +21,11 @@ import { ethRpcMethods } from 'web3-rpc-methods'; import { getTransaction } from '../../../src/rpc_method_wrappers'; import { mockRpcResponse, testData } from './fixtures/get_transaction'; -import { formatTransaction, transactionInfoSchema } from '../../../src'; +import { + type CustomTransactionSchema, + formatTransaction, + transactionInfoSchema, +} from '../../../src'; jest.mock('web3-rpc-methods'); @@ -57,7 +61,7 @@ describe('getTransaction', () => { const expectedFormattedResult = formatTransaction( mockRpcResponse, expectedReturnFormat, - { transactionSchema: transactionInfoSchema }, + { transactionSchema: transactionInfoSchema as CustomTransactionSchema }, ); (ethRpcMethods.getTransactionByHash as jest.Mock).mockResolvedValueOnce( mockRpcResponse, From 5a7e302a8f45ad9685366d4f102615d7ec5b434c Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 18 Sep 2024 13:12:11 -0400 Subject: [PATCH 149/186] release/4.13.0 (#7264) * bump versions * address feedback * bump web3-types version --- CHANGELOG.md | 21 +++++++++++++-------- packages/web3-core/CHANGELOG.md | 7 ++++--- packages/web3-core/package.json | 6 +++--- packages/web3-eth-abi/CHANGELOG.md | 4 +++- packages/web3-eth-abi/package.json | 6 +++--- packages/web3-eth-personal/CHANGELOG.md | 4 +++- packages/web3-eth-personal/package.json | 16 ++++++++-------- packages/web3-eth/CHANGELOG.md | 4 +++- packages/web3-eth/package.json | 14 +++++++------- packages/web3-types/CHANGELOG.md | 6 ++++++ packages/web3-types/package.json | 2 +- packages/web3/CHANGELOG.md | 7 +++++++ packages/web3/package.json | 12 ++++++------ packages/web3/src/version.ts | 2 +- 14 files changed, 68 insertions(+), 43 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4a9943a1e2..47e05ff01fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2696,24 +2696,22 @@ If there are any bugs, improvements, optimizations or any new feature proposal f - Revert `TransactionFactory.registerTransactionType` if there is a version mistatch between `web3-eth` and `web3-eth-accounts` and fix nextjs problem. (#7216) -#### web3 - -- `Web3.providers` namespace exports `type EIP6963ProviderResponse = Map`. Return type for the static `Web3.requestEIP6963Providers` is now `Promise`. (#7239) -- The callback function provided to the static `Web3.onNewProviderDiscovered` function expects a parameter of type `EIP6963ProvidersMapUpdateEvent` as opposed to `EIP6963AnnounceProviderEvent`. (#7242) - -## [Unreleased] +## [4.13.0] ### Added #### web3-core -- Adds a new property (`customTransactionSchema`) to `Web3ConfigOptions` -- Adds a new property (`config`) to `Web3RequestManager` +- Adds a new property (`customTransactionSchema`) to `Web3ConfigOptions` (#7227) #### web3-eth - Adds the same `{transactionSchema?: ValidationSchemaInput}` that exists in `formatTransaction` to `validateTransactionForSigning` +#### web3-types + +- Add COMMITTED to BlockTags (#7124) + ### Changed #### web3-eth @@ -2723,3 +2721,10 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3-eth-personal - Forwards the new `web3Context.config.customTransactionSchema` to `formatTransaction` + +#### web3 + +- `Web3.providers` namespace exports `type EIP6963ProviderResponse = Map`. Return type for the static `Web3.requestEIP6963Providers` is now `Promise`. (#7239) +- The callback function provided to the static `Web3.onNewProviderDiscovered` function expects a parameter of type `EIP6963ProvidersMapUpdateEvent` as opposed to `EIP6963AnnounceProviderEvent`. (#7242) + +## [Unreleased] diff --git a/packages/web3-core/CHANGELOG.md b/packages/web3-core/CHANGELOG.md index ca126e01d03..0ea27e97e22 100644 --- a/packages/web3-core/CHANGELOG.md +++ b/packages/web3-core/CHANGELOG.md @@ -233,9 +233,10 @@ Documentation: - `setConfig()` fix for `setMaxListenerWarningThreshold` fix (#5079) -## [Unreleased] +## [4.6.0] ### Added -- Adds a new property (`customTransactionSchema`) to `Web3ConfigOptions` -- Adds a new property (`config`) to `Web3RequestManager` +- Adds a new property (`customTransactionSchema`) to `Web3ConfigOptions`(#7227) + +## [Unreleased] diff --git a/packages/web3-core/package.json b/packages/web3-core/package.json index ad4f8d94b83..2f99bf7d3de 100644 --- a/packages/web3-core/package.json +++ b/packages/web3-core/package.json @@ -1,6 +1,6 @@ { "name": "web3-core", - "version": "4.5.1", + "version": "4.6.0", "description": "Web3 core tools for sub-packages. This is an internal package.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -43,11 +43,11 @@ }, "dependencies": { "web3-errors": "^1.3.0", - "web3-eth-accounts": "^4.2.0", + "web3-eth-accounts": "^4.2.1", "web3-eth-iban": "^4.0.7", "web3-providers-http": "^4.2.0", "web3-providers-ws": "^4.0.8", - "web3-types": "^1.7.0", + "web3-types": "^1.8.0", "web3-utils": "^4.3.1", "web3-validator": "^2.0.6" }, diff --git a/packages/web3-eth-abi/CHANGELOG.md b/packages/web3-eth-abi/CHANGELOG.md index c764ff78ff4..0b7990b7034 100644 --- a/packages/web3-eth-abi/CHANGELOG.md +++ b/packages/web3-eth-abi/CHANGELOG.md @@ -182,8 +182,10 @@ Documentation: - fix encodedata in EIP-712 (#7095) -## [Unreleased] +## [4.2.4] ### Added - Handle common cases for smart contract errors according to EIP 838: `0x4e487b71` which is the ‘selector’ for `Panic(uint256)` and `0x08c379a0` is the ‘selector’ of `Error(string)`. (7155) + +## [Unreleased] diff --git a/packages/web3-eth-abi/package.json b/packages/web3-eth-abi/package.json index 7431abf8f23..3331a9603b4 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.3", + "version": "4.2.4", "description": "Web3 module encode and decode EVM in/output.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -43,8 +43,8 @@ }, "dependencies": { "abitype": "0.7.1", - "web3-errors": "^1.2.0", - "web3-types": "^1.7.0", + "web3-errors": "^1.3.0", + "web3-types": "^1.8.0", "web3-utils": "^4.3.1", "web3-validator": "^2.0.6" }, diff --git a/packages/web3-eth-personal/CHANGELOG.md b/packages/web3-eth-personal/CHANGELOG.md index abc79b58850..597437ad224 100644 --- a/packages/web3-eth-personal/CHANGELOG.md +++ b/packages/web3-eth-personal/CHANGELOG.md @@ -147,8 +147,10 @@ Documentation: - Dependencies updated -## [Unreleased] +## [4.1.0] ### Changed - Forwards the new `web3Context.config.customTransactionSchema` to `formatTransaction` + +## [Unreleased] diff --git a/packages/web3-eth-personal/package.json b/packages/web3-eth-personal/package.json index 8cb5ada7a04..2a1f3000308 100644 --- a/packages/web3-eth-personal/package.json +++ b/packages/web3-eth-personal/package.json @@ -1,6 +1,6 @@ { "name": "web3-eth-personal", - "version": "4.0.8", + "version": "4.1.0", "description": "Web3 module to interact with the Ethereum blockchain accounts stored in the node.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -42,12 +42,12 @@ "test:integration": "jest --config=./test/integration/jest.config.js" }, "dependencies": { - "web3-core": "^4.3.0", - "web3-eth": "^4.3.1", - "web3-rpc-methods": "^1.1.3", - "web3-types": "^1.3.0", - "web3-utils": "^4.0.7", - "web3-validator": "^2.0.3" + "web3-core": "^4.6.0", + "web3-eth": "^4.9.0", + "web3-rpc-methods": "^1.3.0", + "web3-types": "^1.8.0", + "web3-utils": "^4.3.1", + "web3-validator": "^2.0.6" }, "devDependencies": { "@types/jest": "^28.1.6", @@ -62,6 +62,6 @@ "prettier": "^2.7.1", "ts-jest": "^29.1.1", "typescript": "^4.7.4", - "web3-providers-ws": "^4.0.7" + "web3-providers-ws": "^4.0.8" } } diff --git a/packages/web3-eth/CHANGELOG.md b/packages/web3-eth/CHANGELOG.md index 7d1470f593d..e75b0f867b2 100644 --- a/packages/web3-eth/CHANGELOG.md +++ b/packages/web3-eth/CHANGELOG.md @@ -269,7 +269,7 @@ Documentation: - Adds transaction property to be an empty list rather than undefined when no transactions are included in the block (#7151) - Change method `getTransactionReceipt` to not be casted as `TransactionReceipt` to give proper return type (#7159) -## [Unreleased] +## [4.9.0] ### Changed @@ -278,3 +278,5 @@ Documentation: ### Added - Adds the same `{transactionSchema?: ValidationSchemaInput}` that exists in `formatTransaction` to `validateTransactionForSigning` + +## [Unreleased] diff --git a/packages/web3-eth/package.json b/packages/web3-eth/package.json index 3f18fcd83d5..66cf22b8852 100644 --- a/packages/web3-eth/package.json +++ b/packages/web3-eth/package.json @@ -1,6 +1,6 @@ { "name": "web3-eth", - "version": "4.8.2", + "version": "4.9.0", "description": "Web3 module to interact with the Ethereum blockchain and smart contracts.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -59,18 +59,18 @@ "prettier": "^2.7.1", "ts-jest": "^29.1.1", "typescript": "^4.7.4", - "web3-providers-http": "^4.1.0" + "web3-providers-http": "^4.2.0" }, "dependencies": { "setimmediate": "^1.0.5", - "web3-core": "^4.5.0", - "web3-errors": "^1.2.1", - "web3-eth-abi": "^4.2.3", - "web3-eth-accounts": "^4.1.3", + "web3-core": "^4.6.0", + "web3-errors": "^1.3.0", + "web3-eth-abi": "^4.2.4", + "web3-eth-accounts": "^4.2.1", "web3-net": "^4.1.0", "web3-providers-ws": "^4.0.8", "web3-rpc-methods": "^1.3.0", - "web3-types": "^1.7.0", + "web3-types": "^1.8.0", "web3-utils": "^4.3.1", "web3-validator": "^2.0.6" } diff --git a/packages/web3-types/CHANGELOG.md b/packages/web3-types/CHANGELOG.md index 281d77fb528..e38c479f914 100644 --- a/packages/web3-types/CHANGELOG.md +++ b/packages/web3-types/CHANGELOG.md @@ -202,4 +202,10 @@ Documentation: - Added `result` as optional `never` and `error` as optional `never in type `JsonRpcNotification` (#7091) - Added `JsonRpcNotfication` as a union type in `JsonRpcResponse` (#7091) +## [1.8.0] + +### Added + +- Add COMMITTED to BlockTags (#7124) + ## [Unreleased] diff --git a/packages/web3-types/package.json b/packages/web3-types/package.json index b2e7d7b3ff7..85a069f1984 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.8.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/CHANGELOG.md b/packages/web3/CHANGELOG.md index f22108d5fd4..6e027ff3d8a 100644 --- a/packages/web3/CHANGELOG.md +++ b/packages/web3/CHANGELOG.md @@ -482,4 +482,11 @@ Documentation: - Revert `TransactionFactory.registerTransactionType` if there is a version mistatch between `web3-eth` and `web3-eth-accounts` and fix nextjs problem. (#7216) +## [4.13.0] + +### Changed + +- `Web3.providers` namespace exports `type EIP6963ProviderResponse = Map`. Return type for the static `Web3.requestEIP6963Providers` is now `Promise`. (#7239) +- The callback function provided to the static `Web3.onNewProviderDiscovered` function expects a parameter of type `EIP6963ProvidersMapUpdateEvent` as opposed to `EIP6963AnnounceProviderEvent`. (#7242) + ## [Unreleased] diff --git a/packages/web3/package.json b/packages/web3/package.json index 657a261c6ac..596d82d1b35 100644 --- a/packages/web3/package.json +++ b/packages/web3/package.json @@ -1,6 +1,6 @@ { "name": "web3", - "version": "4.12.1", + "version": "4.13.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.5.1", + "web3-core": "^4.6.0", "web3-errors": "^1.3.0", - "web3-eth": "^4.8.2", - "web3-eth-abi": "^4.2.3", + "web3-eth": "^4.9.0", + "web3-eth-abi": "^4.2.4", "web3-eth-accounts": "^4.2.1", "web3-eth-contract": "^4.7.0", "web3-eth-ens": "^4.4.0", "web3-eth-iban": "^4.0.7", - "web3-eth-personal": "^4.0.8", + "web3-eth-personal": "^4.1.0", "web3-net": "^4.1.0", "web3-providers-http": "^4.2.0", "web3-providers-ws": "^4.0.8", "web3-rpc-methods": "^1.3.0", "web3-rpc-providers": "^1.0.0-rc.2", - "web3-types": "^1.7.0", + "web3-types": "^1.8.0", "web3-utils": "^4.3.1", "web3-validator": "^2.0.6" } diff --git a/packages/web3/src/version.ts b/packages/web3/src/version.ts index e49fd40bc26..82d0ac0dfb9 100644 --- a/packages/web3/src/version.ts +++ b/packages/web3/src/version.ts @@ -1 +1 @@ -/* eslint-disable header/header */ export const Web3PkgInfo = { version: '4.12.1' }; +/* eslint-disable header/header */ export const Web3PkgInfo = { version: '4.13.0' }; From 6f9a485e0715a70170bf170ca1e1d1b26b43f6c3 Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Thu, 19 Sep 2024 09:07:08 -0700 Subject: [PATCH 150/186] Fix CHANGELOG for PR 7239 (#7271) * Fix CHANGELOG for PR 7239 * Update web3 CHANGELOG --- CHANGELOG.md | 2 +- packages/web3/CHANGELOG.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 47e05ff01fc..e7f1fcb646d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2724,7 +2724,7 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3 -- `Web3.providers` namespace exports `type EIP6963ProviderResponse = Map`. Return type for the static `Web3.requestEIP6963Providers` is now `Promise`. (#7239) +- Return type for the static `Web3.requestEIP6963Providers` function is now `Promise`. (#7239) - The callback function provided to the static `Web3.onNewProviderDiscovered` function expects a parameter of type `EIP6963ProvidersMapUpdateEvent` as opposed to `EIP6963AnnounceProviderEvent`. (#7242) ## [Unreleased] diff --git a/packages/web3/CHANGELOG.md b/packages/web3/CHANGELOG.md index 6e027ff3d8a..6e246997608 100644 --- a/packages/web3/CHANGELOG.md +++ b/packages/web3/CHANGELOG.md @@ -486,7 +486,7 @@ Documentation: ### Changed -- `Web3.providers` namespace exports `type EIP6963ProviderResponse = Map`. Return type for the static `Web3.requestEIP6963Providers` is now `Promise`. (#7239) +- Return type for the static `Web3.requestEIP6963Providers` function is now `Promise`. (#7239) - The callback function provided to the static `Web3.onNewProviderDiscovered` function expects a parameter of type `EIP6963ProvidersMapUpdateEvent` as opposed to `EIP6963AnnounceProviderEvent`. (#7242) ## [Unreleased] From d6baee6ca3b729d06cb262211a572fbe2361bf68 Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Mon, 23 Sep 2024 11:46:11 -0700 Subject: [PATCH 151/186] Fix Typos in Docs (#7283) * Fix Link to Contributing Guide Closes #7266 * Fix Wrong Param Name in Web3Modal Docs Replaces #7275 --- README.md | 2 +- docs/docs/guides/wallet/web3_modal_guide/index.mdx | 2 +- docs/docs/guides/wallet/web3_modal_guide/react.md | 2 +- packages/web3/README.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 95fbc065035..adf5ec07574 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ yarn add web3 ## Migration Guide - [Migration Guide from Web3.js 1.x to 4.x](https://docs.web3js.org/guides/web3_upgrade_guide/x/) - Breaking changes are listed in migration guide and its first step for migrating from Web3.js 1.x to 4.x. If there is any question or discussion feel free to ask in [Discord](https://discord.gg/yjyvFRP), and in case of any bug or new feature request [open issue](https://github.com/web3/web3.js/issues/new) or create a pull request for [contributions](https://github.com/web3/web3.js/blob/4.x/CONTRIBUTIONS.md). + Breaking changes are listed in migration guide and its first step for migrating from Web3.js 1.x to 4.x. If there is any question or discussion feel free to ask in [Discord](https://discord.gg/yjyvFRP), and in case of any bug or new feature request [open issue](https://github.com/web3/web3.js/issues/new) or create a pull request for [contributions](https://github.com/web3/web3.js/blob/4.x/.github/CONTRIBUTING.md). ## Useful links diff --git a/docs/docs/guides/wallet/web3_modal_guide/index.mdx b/docs/docs/guides/wallet/web3_modal_guide/index.mdx index 05d61d087c2..7e6f077b1a9 100644 --- a/docs/docs/guides/wallet/web3_modal_guide/index.mdx +++ b/docs/docs/guides/wallet/web3_modal_guide/index.mdx @@ -68,7 +68,7 @@ const web3Config = defaultConfig({ // 5. Create a Web3Modal instance createWeb3Modal({ - ethersConfig, + web3Config, chains: [mainnet], projectId, enableAnalytics: true // Optional - defaults to your Cloud configuration diff --git a/docs/docs/guides/wallet/web3_modal_guide/react.md b/docs/docs/guides/wallet/web3_modal_guide/react.md index 3370c65dc57..1bcc69c6af7 100644 --- a/docs/docs/guides/wallet/web3_modal_guide/react.md +++ b/docs/docs/guides/wallet/web3_modal_guide/react.md @@ -78,7 +78,7 @@ const web3Config = defaultConfig({ // 5. Create a Web3Modal instance createWeb3Modal({ - ethersConfig, + web3Config, chains: [mainnet], projectId, enableAnalytics: true // Optional - defaults to your Cloud configuration diff --git a/packages/web3/README.md b/packages/web3/README.md index efab77af94e..d9397a73a3f 100644 --- a/packages/web3/README.md +++ b/packages/web3/README.md @@ -57,7 +57,7 @@ yarn add web3 ## Migration Guide - [Migration Guide from Web3.js 1.x to 4.x](https://docs.web3js.org/docs/guides/web3_migration_guide) - Breaking changes are listed in migration guide and its first step for migrating from Web3.js 1.x to 4.x. If there is any question or discussion feel free to ask in discord, and in case of any bug or new feature request [open issue](https://github.com/web3/web3.js/issues/new) or create a pull request for [contributions](https://github.com/web3/web3.js/blob/4.x/CONTRIBUTIONS.md). + Breaking changes are listed in migration guide and its first step for migrating from Web3.js 1.x to 4.x. If there is any question or discussion feel free to ask in discord, and in case of any bug or new feature request [open issue](https://github.com/web3/web3.js/issues/new) or create a pull request for [contributions](https://github.com/web3/web3.js/blob/4.x/.github/CONTRIBUTING.md). ## Package.json Scripts From d45b712d794aba3a3e8fb6ac3eeae047bfc446c4 Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Tue, 24 Sep 2024 05:40:00 -0700 Subject: [PATCH 152/186] Revert CHANGELOG Changes from #7271 (#7274) --- CHANGELOG.md | 2 +- packages/web3/CHANGELOG.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e7f1fcb646d..6714ae042fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2724,7 +2724,7 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3 -- Return type for the static `Web3.requestEIP6963Providers` function is now `Promise`. (#7239) +- `Web3.providers` namespace exports `type EIP6963ProviderResponse = Map`. Return type for the static `Web3.requestEIP6963Providers` function is now `Promise`. (#7239) - The callback function provided to the static `Web3.onNewProviderDiscovered` function expects a parameter of type `EIP6963ProvidersMapUpdateEvent` as opposed to `EIP6963AnnounceProviderEvent`. (#7242) ## [Unreleased] diff --git a/packages/web3/CHANGELOG.md b/packages/web3/CHANGELOG.md index 6e246997608..a9ad657d1c3 100644 --- a/packages/web3/CHANGELOG.md +++ b/packages/web3/CHANGELOG.md @@ -486,7 +486,7 @@ Documentation: ### Changed -- Return type for the static `Web3.requestEIP6963Providers` function is now `Promise`. (#7239) +- `Web3.providers` namespace exports `type EIP6963ProviderResponse = Map`. Return type for the static `Web3.requestEIP6963Providers` function is now `Promise`. (#7239) - The callback function provided to the static `Web3.onNewProviderDiscovered` function expects a parameter of type `EIP6963ProvidersMapUpdateEvent` as opposed to `EIP6963AnnounceProviderEvent`. (#7242) ## [Unreleased] From 61babcc58ae00bbb21101b794f621fccf30a8f66 Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Tue, 24 Sep 2024 05:42:11 -0700 Subject: [PATCH 153/186] Add Note About create-hardhat-web3 to Hardhat Guide (#7281) Closes #7251 --- docs/docs/guides/hardhat_tutorial/index.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/docs/guides/hardhat_tutorial/index.md b/docs/docs/guides/hardhat_tutorial/index.md index 9109004467c..ea97d80e9b4 100644 --- a/docs/docs/guides/hardhat_tutorial/index.md +++ b/docs/docs/guides/hardhat_tutorial/index.md @@ -10,6 +10,10 @@ Following the recent compatibility update of Hardhat plugin [hardhat-web3-v4](ht This tutorial will guide you through using Web3js as a plugin to interact with the Blockchain. +:::info +This tutorial explains how to create a Web3.js + Hardhat project from scratch. The [`create-hardhat-web3`](https://github.com/web3/hardhat-web3) command line utility was created to automate many of the steps in this tutorial and make it easier to quickly bootstrap a new Web3.js + Hardhat project. +::: + ## Pre-requisite This tutorial assumes you have previous knowledge of writing Smart contracts, and are convenient working with JavaScript/TypeScript. You should have [NodeJS](https://nodejs.org/en) version greater than v16 installed. From aa471e7d4f749baa63f1d16df6f0c9da725780f4 Mon Sep 17 00:00:00 2001 From: Muhammad Altabba <24407834+Muhammad-Altabba@users.noreply.github.com> Date: Tue, 24 Sep 2024 16:07:09 +0200 Subject: [PATCH 154/186] fix padRight validation failure on large uint (#7265) * fix padRight validation failure on large uint * update CHANGELOG.md --- packages/web3-utils/CHANGELOG.md | 4 ++++ packages/web3-utils/src/string_manipulation.ts | 6 +++--- packages/web3-utils/test/fixtures/string_manipulation.ts | 8 ++++++++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/packages/web3-utils/CHANGELOG.md b/packages/web3-utils/CHANGELOG.md index 8f25c4c6b20..45439db666e 100644 --- a/packages/web3-utils/CHANGELOG.md +++ b/packages/web3-utils/CHANGELOG.md @@ -235,3 +235,7 @@ Documentation: - `_sendPendingRequests` will catch unhandled errors from `_sendToSocket` (#6968) ## [Unreleased] + +### Fixed + +- fix `padRight` validation failure on large `uint` (#7265) diff --git a/packages/web3-utils/src/string_manipulation.ts b/packages/web3-utils/src/string_manipulation.ts index 88a0a9a5534..37e82b04b3a 100644 --- a/packages/web3-utils/src/string_manipulation.ts +++ b/packages/web3-utils/src/string_manipulation.ts @@ -75,11 +75,11 @@ export const padRight = (value: Numbers, characterAmount: number, sign = '0'): s return value.padEnd(characterAmount, sign); } - validator.validate(['int'], [value]); - const hexString = typeof value === 'string' && isHexStrict(value) ? value : numberToHex(value); - const prefixLength = hexString.startsWith('-') ? 3 : 2; + + validator.validate([hexString.startsWith('-') ? 'int' : 'uint'], [value]); + return hexString.padEnd(characterAmount + prefixLength, sign); }; diff --git a/packages/web3-utils/test/fixtures/string_manipulation.ts b/packages/web3-utils/test/fixtures/string_manipulation.ts index dde49247677..77cbdfac8e9 100644 --- a/packages/web3-utils/test/fixtures/string_manipulation.ts +++ b/packages/web3-utils/test/fixtures/string_manipulation.ts @@ -56,6 +56,14 @@ export const padRightData: [[Numbers, number, string], HexString][] = [ [[BigInt(10000), 8, '0'], '0x27100000'], [[BigInt(-14), 8, '0'], '-0xe0000000'], [['15.5', 8, '0'], '15.50000'], + [ + ['0x05e2e7de3cd95eb48fa9ff77e7860cf249fe05f726abea45a0a44e62b4bf52b2', 64, '0'], + '0x05e2e7de3cd95eb48fa9ff77e7860cf249fe05f726abea45a0a44e62b4bf52b2', + ], + [ + ['0xb5e2e7de3cd95eb48fa9ff77e7860cf249fe05f726abea45a0a44e62b4bf52b2', 64, '0'], + '0xb5e2e7de3cd95eb48fa9ff77e7860cf249fe05f726abea45a0a44e62b4bf52b2', + ], ]; export const toTwosComplementData: [[Numbers, number | undefined], HexString][] = [ From c602fc6fd3058862a24b9b9e6b267a1a45c12b46 Mon Sep 17 00:00:00 2001 From: Oleksii Kosynskyi Date: Tue, 24 Sep 2024 16:57:30 -0400 Subject: [PATCH 155/186] Ok/6984 update e2e network tests (#7276) * Update get_proof.test.ts * test * fix get storage * Update e2e_network_tests.yml * fix GA file * done * revert --- .github/workflows/e2e_network_tests.yml | 20 +++++++++++-------- packages/web3/test/e2e/get_proof.test.ts | 4 ++-- .../test/e2e/mainnet/get_storage_at.test.ts | 9 ++++----- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/.github/workflows/e2e_network_tests.yml b/.github/workflows/e2e_network_tests.yml index 8f26d6c5281..d036fc62467 100644 --- a/.github/workflows/e2e_network_tests.yml +++ b/.github/workflows/e2e_network_tests.yml @@ -5,6 +5,12 @@ on: - release/** tags: - v4.* + +# For test purpose only: +# pull_request: +# branches: +# - '4.x' +# types: [ opened, reopened, synchronize ] jobs: build: name: Build Packages @@ -16,11 +22,10 @@ jobs: node-version: 18 cache: yarn - run: yarn - - run: tar -czf /tmp/web3-16.js.tar.gz --exclude="./.git" ./ - - uses: actions/upload-artifact@v3 + - uses: actions/cache/save@v4 with: - name: web3-16.js.tar.gz - path: /tmp/web3-16.js.tar.gz + path: ./ + key: web3-e2e-18-${{github.sha}} e2e: name: E2E Network Tests needs: build @@ -41,11 +46,10 @@ jobs: - uses: actions/setup-node@v3 with: node-version: 18 - - uses: actions/download-artifact@v3 + - uses: actions/cache/restore@v4 with: - name: web3-16.js.tar.gz - path: /tmp - - run: tar -xf /tmp/web3-16.js.tar.gz -C ./ + path: ./ + key: web3-e2e-18-${{github.sha}} - run: | yarn test:e2e:${{ matrix.network }}:${{ matrix.mode }} shell: bash diff --git a/packages/web3/test/e2e/get_proof.test.ts b/packages/web3/test/e2e/get_proof.test.ts index a8c17c6558a..a9a449c28eb 100644 --- a/packages/web3/test/e2e/get_proof.test.ts +++ b/packages/web3/test/e2e/get_proof.test.ts @@ -55,9 +55,9 @@ describe(`${getSystemTestBackend()} tests - getProof`, () => { | 'blockNumber'; }>({ block: [ - 'earliest', + // 'earliest', block is earlier than 128 blocks ago "Returned error: missing trie node" 'latest', - 'pending', + // 'pending', block is not available "Returned error: missing trie node" 'safe', 'finalized', 'blockHash', diff --git a/packages/web3/test/e2e/mainnet/get_storage_at.test.ts b/packages/web3/test/e2e/mainnet/get_storage_at.test.ts index 7db7017fb1d..9839a6db75f 100644 --- a/packages/web3/test/e2e/mainnet/get_storage_at.test.ts +++ b/packages/web3/test/e2e/mainnet/get_storage_at.test.ts @@ -39,10 +39,9 @@ describe(`${getSystemTestBackend()} tests - getStorageAt`, () => { it.each( toAllVariants<{ storageSlot: Numbers; - block: - | 'earliest' - | 'latest' - | 'pending' + block: // | 'earliest' + | 'latest' + // | 'pending' | 'finalized' | 'safe' | 'blockHash' @@ -80,7 +79,7 @@ describe(`${getSystemTestBackend()} tests - getStorageAt`, () => { } else if (block === 'blockHash' || block === 'blockNumber') { // eslint-disable-next-line jest/no-conditional-expect expect(result).toBe( - '0x00000000000000000000000000000000000000000000000000b8b61e3be91403', + '0x00000000000000000000000000000000000000000000000000c354b137cba7ba', ); } else { // eslint-disable-next-line jest/no-conditional-expect From cc99825d31ae4d1d0c6615aa3648486a591a645c Mon Sep 17 00:00:00 2001 From: Nicolas Brugneaux Date: Thu, 26 Sep 2024 10:34:05 +0200 Subject: [PATCH 156/186] feat: make getEthereumjsTxDataFromTransaction not trim extra fields (#7282) * feat: make getEthereumjsTxDataFromTransaction not trim extra fields * fix: lint issues * fix: tests * fix: revert the changes and just spread extra fields * chore: changelog --- CHANGELOG.md | 6 +++ packages/web3-eth/CHANGELOG.md | 4 ++ .../utils/prepare_transaction_for_signing.ts | 1 + .../prepare_transaction_for_signing.test.ts | 52 +++++++++++++++++++ .../web3/test/fixtures/tx-type-15/index.ts | 50 +++++++++++++----- .../integration/web3-plugin-add-tx.test.ts | 28 +++++++--- 6 files changed, 122 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6714ae042fa..46c0eefe645 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2728,3 +2728,9 @@ If there are any bugs, improvements, optimizations or any new feature proposal f - The callback function provided to the static `Web3.onNewProviderDiscovered` function expects a parameter of type `EIP6963ProvidersMapUpdateEvent` as opposed to `EIP6963AnnounceProviderEvent`. (#7242) ## [Unreleased] + +### Changed + +#### web3-eth + +- Allow `getEthereumjsTxDataFrom` to return additional fields that may be passed if using a `customTransactionSchema`. diff --git a/packages/web3-eth/CHANGELOG.md b/packages/web3-eth/CHANGELOG.md index e75b0f867b2..71fd65e4f9e 100644 --- a/packages/web3-eth/CHANGELOG.md +++ b/packages/web3-eth/CHANGELOG.md @@ -280,3 +280,7 @@ Documentation: - Adds the same `{transactionSchema?: ValidationSchemaInput}` that exists in `formatTransaction` to `validateTransactionForSigning` ## [Unreleased] + +### Changed + +- Allow `getEthereumjsTxDataFrom` to return additional fields that may be passed if using a `customTransactionSchema`. diff --git a/packages/web3-eth/src/utils/prepare_transaction_for_signing.ts b/packages/web3-eth/src/utils/prepare_transaction_for_signing.ts index cd70e1e265c..a90ce32173d 100644 --- a/packages/web3-eth/src/utils/prepare_transaction_for_signing.ts +++ b/packages/web3-eth/src/utils/prepare_transaction_for_signing.ts @@ -37,6 +37,7 @@ import { transactionBuilder } from './transaction_builder.js'; const getEthereumjsTxDataFromTransaction = ( transaction: FormatType, ) => ({ + ...transaction, nonce: transaction.nonce, gasPrice: transaction.gasPrice, gasLimit: transaction.gasLimit ?? transaction.gas, diff --git a/packages/web3-eth/test/unit/prepare_transaction_for_signing.test.ts b/packages/web3-eth/test/unit/prepare_transaction_for_signing.test.ts index ce83a505d17..e0955db8fac 100644 --- a/packages/web3-eth/test/unit/prepare_transaction_for_signing.test.ts +++ b/packages/web3-eth/test/unit/prepare_transaction_for_signing.test.ts @@ -28,9 +28,13 @@ import { FeeMarketEIP1559Transaction, Transaction, Hardfork, + TypedTransaction, + TransactionFactory, } from 'web3-eth-accounts'; import { prepareTransactionForSigning } from '../../src/utils/prepare_transaction_for_signing'; import { validTransactions } from '../fixtures/prepare_transaction_for_signing'; +import { transactionSchema } from '../../src/schemas'; +import { CustomFieldTransaction } from '../fixtures/format_transaction'; describe('prepareTransactionForSigning', () => { const web3Context = new Web3Context({ @@ -317,4 +321,52 @@ describe('prepareTransactionForSigning', () => { }, ); }); + + it('should not remove extra fields when using a custom schema', async () => { + const context = new Web3Context({ + provider: new HttpProvider('http://127.0.0.1'), + config: { + defaultNetworkId: '0x1', + customTransactionSchema: { + type: 'object', + properties: { + ...transactionSchema.properties, + feeCurrency: { format: 'address' }, + }, + }, + }, + }); + + async function transactionBuilder(options: { + transaction: TransactionType; + web3Context: Web3Context; + privateKey?: HexString | Uint8Array; + fillGasPrice?: boolean; + fillGasLimit?: boolean; + }): Promise { + const tx = { ...options.transaction }; + return tx as unknown as ReturnType; + } + + context.transactionBuilder = transactionBuilder; + + const spy = jest.spyOn(TransactionFactory, 'fromTxData'); + (await prepareTransactionForSigning( + { + chainId: 1458, + nonce: 1, + gasPrice: BigInt(20000000000), + gasLimit: BigInt(21000), + to: '0xF0109fC8DF283027b6285cc889F5aA624EaC1F55', + from: '0x2c7536E3605D9C16a7a3D7b1898e529396a65c23', + value: '1000000000', + input: '', + feeCurrency: '0x1234567890123456789012345678901234567890', + } as CustomFieldTransaction, + context, + )) as TypedTransaction & { feeCurrency: string }; + + // @ts-expect-error feeCurrency is a custom field for testing here + expect(spy.mock.lastCall[0].feeCurrency).toBe('0x1234567890123456789012345678901234567890'); + }); }); diff --git a/packages/web3/test/fixtures/tx-type-15/index.ts b/packages/web3/test/fixtures/tx-type-15/index.ts index 8dd34b35e25..1d7dd778067 100644 --- a/packages/web3/test/fixtures/tx-type-15/index.ts +++ b/packages/web3/test/fixtures/tx-type-15/index.ts @@ -32,9 +32,9 @@ import { AccessList, AccessListUint8Array, FeeMarketEIP1559TxData, - FeeMarketEIP1559ValuesArray, JsonTx, TxOptions, + TxValuesArray, } from 'web3-eth-accounts'; const { getAccessListData, getAccessListJSON, getDataFeeEIP2930, verifyAccessList } = txUtils; @@ -43,6 +43,26 @@ const MAX_INTEGER = BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffff export const TRANSACTION_TYPE = 15; const TRANSACTION_TYPE_UINT8ARRAY = hexToBytes(TRANSACTION_TYPE.toString(16).padStart(2, '0')); +type CustomFieldTxValuesArray = [ + Uint8Array, + Uint8Array, + Uint8Array, + Uint8Array, + Uint8Array, + Uint8Array, + Uint8Array, + Uint8Array, + AccessListUint8Array, + Uint8Array, + Uint8Array?, + Uint8Array?, + Uint8Array?, +]; + +type SomeNewTxTypeTxData = FeeMarketEIP1559TxData & { + customTestField: bigint; +}; + /** * Typed transaction with a new gas fee market mechanism * @@ -50,12 +70,13 @@ const TRANSACTION_TYPE_UINT8ARRAY = hexToBytes(TRANSACTION_TYPE.toString(16).pad * - EIP: [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) */ // eslint-disable-next-line no-use-before-define -export class SomeNewTxTypeTransaction extends BaseTransaction { +export class SomeNewTxTypeTransaction extends BaseTransaction { public readonly chainId: bigint; public readonly accessList: AccessListUint8Array; public readonly AccessListJSON: AccessList; public readonly maxPriorityFeePerGas: bigint; public readonly maxFeePerGas: bigint; + public readonly customTestField: bigint; public readonly common: Common; @@ -77,7 +98,7 @@ export class SomeNewTxTypeTransaction extends BaseTransaction. /* eslint-disable @typescript-eslint/no-magic-numbers */ import { Transaction, Web3Account } from 'web3-eth-accounts'; +import { transactionSchema } from 'web3-eth'; import { SupportedProviders, Web3, Web3PluginBase } from '../../src'; import { createAccount, @@ -51,6 +52,14 @@ describe('Add New Tx as a Plugin', () => { }); it('should receive correct type of tx', async () => { web3.registerPlugin(new Eip4844Plugin()); + web3.config.customTransactionSchema = { + type: 'object', + properties: { + ...transactionSchema.properties, + customField: { format: 'string' }, + }, + }; + web3.eth.config.customTransactionSchema = web3.config.customTransactionSchema; const tx = { from: account1.address, to: account2.address, @@ -58,16 +67,21 @@ describe('Add New Tx as a Plugin', () => { type: TRANSACTION_TYPE, maxPriorityFeePerGas: BigInt(5000000), maxFeePerGas: BigInt(5000000), + customField: BigInt(42), }; const sub = web3.eth.sendTransaction(tx); - const waitForEvent: Promise = new Promise(resolve => { - // eslint-disable-next-line @typescript-eslint/no-floating-promises - sub.on('sending', txData => { - resolve(txData as unknown as Transaction); - }); - }); - expect(Number((await waitForEvent).type)).toBe(TRANSACTION_TYPE); + const waitForEvent: Promise = new Promise( + resolve => { + // eslint-disable-next-line @typescript-eslint/no-floating-promises + sub.on('sending', txData => { + resolve(txData as unknown as Transaction & { customField: bigint }); + }); + }, + ); + const { type, customField } = await waitForEvent; + expect(Number(type)).toBe(TRANSACTION_TYPE); + expect(BigInt(customField)).toBe(BigInt(42)); await expect(sub).rejects.toThrow(); }); }); From dcd9d6a0803ad232003cb7e935057711c5b7e381 Mon Sep 17 00:00:00 2001 From: Junaid <86780488+jdevcs@users.noreply.github.com> Date: Wed, 2 Oct 2024 16:21:48 +0200 Subject: [PATCH 157/186] 7136 decodeparams update (#7288) * decodeParametersWith update * decodeParameters update * unit test decodeParameters * decodeLog update * decodeLog unit test * changelog update --- packages/web3-eth-abi/CHANGELOG.md | 4 ++ packages/web3-eth-abi/src/api/logs_api.ts | 2 +- .../web3-eth-abi/src/api/parameters_api.ts | 4 +- packages/web3-eth-abi/src/coders/decode.ts | 2 +- .../test/unit/api/logs_api.test.ts | 40 +++++++++++++++++++ .../test/unit/encodeDecodeParams.test.ts | 19 +++++++++ 6 files changed, 67 insertions(+), 4 deletions(-) diff --git a/packages/web3-eth-abi/CHANGELOG.md b/packages/web3-eth-abi/CHANGELOG.md index 0b7990b7034..cc8ab72306d 100644 --- a/packages/web3-eth-abi/CHANGELOG.md +++ b/packages/web3-eth-abi/CHANGELOG.md @@ -189,3 +189,7 @@ Documentation: - Handle common cases for smart contract errors according to EIP 838: `0x4e487b71` which is the ‘selector’ for `Panic(uint256)` and `0x08c379a0` is the ‘selector’ of `Error(string)`. (7155) ## [Unreleased] + +### Fixed + +- `decodeLog` , `decodeParametersWith` , `decodeParameters` and `decodeParameters` now accepts first immutable param as well (#7288) diff --git a/packages/web3-eth-abi/src/api/logs_api.ts b/packages/web3-eth-abi/src/api/logs_api.ts index 678ec6d7129..0f936ca6931 100644 --- a/packages/web3-eth-abi/src/api/logs_api.ts +++ b/packages/web3-eth-abi/src/api/logs_api.ts @@ -72,7 +72,7 @@ const _decodeParameter = (inputType: string, clonedTopic: string) => * ``` */ export const decodeLog = ( - inputs: Array, + inputs: Array | ReadonlyArray, data: HexString, topics: string | string[], ) => { diff --git a/packages/web3-eth-abi/src/api/parameters_api.ts b/packages/web3-eth-abi/src/api/parameters_api.ts index f81a32e9db3..3bfef281580 100644 --- a/packages/web3-eth-abi/src/api/parameters_api.ts +++ b/packages/web3-eth-abi/src/api/parameters_api.ts @@ -89,7 +89,7 @@ export const encodeParameter = (abi: AbiInput, param: unknown): string => * Should be used to decode list of params */ export const decodeParametersWith = ( - abis: AbiInput[], + abis: AbiInput[] | ReadonlyArray, bytes: HexString, loose: boolean, ): { [key: string]: unknown; __length__: number } => { @@ -216,7 +216,7 @@ export const decodeParametersWith = ( * ``` */ export const decodeParameters = ( - abi: AbiInput[], + abi: AbiInput[] | ReadonlyArray, bytes: HexString, ): { [key: string]: unknown; __length__: number } => decodeParametersWith(abi, bytes, false); diff --git a/packages/web3-eth-abi/src/coders/decode.ts b/packages/web3-eth-abi/src/coders/decode.ts index adc84ad93bb..9a67d89e810 100644 --- a/packages/web3-eth-abi/src/coders/decode.ts +++ b/packages/web3-eth-abi/src/coders/decode.ts @@ -21,7 +21,7 @@ import { decodeTuple } from './base/tuple.js'; import { toAbiParams } from './utils.js'; export function decodeParameters( - abis: AbiInput[], + abis: AbiInput[] | ReadonlyArray, bytes: HexString, _loose: boolean, ): { [key: string]: unknown; __length__: number } { diff --git a/packages/web3-eth-abi/test/unit/api/logs_api.test.ts b/packages/web3-eth-abi/test/unit/api/logs_api.test.ts index 972cec3fd3b..357ddea37c2 100644 --- a/packages/web3-eth-abi/test/unit/api/logs_api.test.ts +++ b/packages/web3-eth-abi/test/unit/api/logs_api.test.ts @@ -29,5 +29,45 @@ describe('logs_api', () => { }, ); }); + + it('decodeLog with first immutable param', () => { + const abi = [ + { + type: 'string', + name: 'myString', + }, + { + type: 'uint256', + name: 'myNumber', + indexed: true, + }, + { + type: 'uint8', + name: 'mySmallNumber', + indexed: true, + }, + ] as const; + + const data = + '0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000748656c6c6f252100000000000000000000000000000000000000000000000000'; + + const topics = [ + '0x000000000000000000000000000000000000000000000000000000000000f310', + '0x0000000000000000000000000000000000000000000000000000000000000010', + ]; + + const result = { + '0': 'Hello%!', + '1': '62224', + '2': '16', + __length__: 3, + myString: 'Hello%!', + myNumber: '62224', + mySmallNumber: '16', + }; + + const expected = decodeLog(abi, data, topics); + expect(JSON.parse(JSON.stringify(expected))).toEqual(result); + }); }); }); diff --git a/packages/web3-eth-abi/test/unit/encodeDecodeParams.test.ts b/packages/web3-eth-abi/test/unit/encodeDecodeParams.test.ts index 184ed0fcf4a..c36b1594a47 100644 --- a/packages/web3-eth-abi/test/unit/encodeDecodeParams.test.ts +++ b/packages/web3-eth-abi/test/unit/encodeDecodeParams.test.ts @@ -47,4 +47,23 @@ describe('encodeParameters decodeParameters tests should pass', () => { expect(deepEqualTolerateBigInt(decodedResult[0], decoderTestObj.value)).toBeTruthy(); }); + + it('unit test of decodeParameters with first immutable param', () => { + const bytes = + '0x0000000000000000000000000000000000000000000000000000000000000020000000000000000015a828c295b2bea094b70a05e96ae19c876417adf3a9083500000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040729a97ba5090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000634d6f6f20c3a9f09f9a80c3a96f4d6f206f20c3a9204d4dc3a9f09f9a802020c3a96f4df09f9a806ff09f9a804df09f9a806fc3a920f09f9a80c3a94df09f9a80f09f9a8020c3a920f09f9a8020c3a9c3a96f4d6fc3a96fc3a94dc3a94dc3a96f6f4d6f0000000000000000000000000000000000000000000000000000000000'; + + const result = [ + '531024955072740163537488200975830992725163050550575040565', + [ + 'Moo é🚀éoMo o é MMé🚀 éoM🚀o🚀M🚀oé 🚀éM🚀🚀 é 🚀 ééoMoéoéMéMéooMo', + '0x729a97ba5090', + ], + ]; + const readonlyArray = ['(uint192,(string,bytes6))'] as const; // should allow immutable array as first param + + const decodedResult = decodeParameters(readonlyArray, bytes); + + removeKey(decodedResult[0], '__length__'); + expect(deepEqualTolerateBigInt(decodedResult[0], result)).toBeTruthy(); + }); }); From adf483fc088e066a3f6c79cbeeee2fb49a93f395 Mon Sep 17 00:00:00 2001 From: Redwan Date: Fri, 4 Oct 2024 21:26:24 +0300 Subject: [PATCH 158/186] Update FUNDING.json (#7304) We had issue with the previous multisig address so we decided to create a specifi EOA owned by Redwan and will share the PK or transfer the funds to Web3js multisig after. --- FUNDING.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FUNDING.json b/FUNDING.json index a11415df3a8..c9df9ba5e72 100644 --- a/FUNDING.json +++ b/FUNDING.json @@ -1,7 +1,7 @@ { "drips": { "ethereum": { - "ownedBy": "0x689f1278469c6146d835CB99BbfF818fB62989FE" + "ownedBy": "0x04E504Acb5f6A9CB387fa37ec5Fc457A9D36D371" } } } From 76c468ad490ba7a50229acb12690e0239870d8fb Mon Sep 17 00:00:00 2001 From: Oleksii Kosynskyi Date: Fri, 4 Oct 2024 18:12:06 -0400 Subject: [PATCH 159/186] Fix e2e test error "project ID request rate exceeded" (#7290) * e2e tests fixes * test e2e GA * fix get storage test * add comments * done testing * test with new keys * Update get_block_transaction_count.test.ts * done * Update e2e_network_tests.yml * Update e2e_network_tests.yml --- .github/workflows/e2e_network_tests.yml | 4 +- packages/web3/test/e2e/fixtures/mainnet.ts | 544 +- .../e2e/fixtures/mainnet_block_hydrated.ts | 5791 +++++++---------- packages/web3/test/e2e/fixtures/sepolia.ts | 1994 ++++-- packages/web3/test/e2e/get_balance.test.ts | 25 +- .../e2e/get_block_transaction_count.test.ts | 51 +- .../test/e2e/get_block_uncle_count.test.ts | 6 +- .../web3/test/e2e/get_fee_history.test.ts | 2 +- packages/web3/test/e2e/get_proof.test.ts | 8 +- .../test/e2e/get_transaction_count.test.ts | 18 +- .../test/e2e/mainnet/get_storage_at.test.ts | 20 +- .../test/e2e/mainnet/get_transaction.test.ts | 47 +- .../mainnet/get_transaction_receipt.test.ts | 156 +- .../test/e2e/sepolia/get_past_logs.test.ts | 4 +- .../test/e2e/sepolia/get_storage_at.test.ts | 11 +- .../test/e2e/sepolia/get_transaction.test.ts | 44 +- .../sepolia/get_transaction_receipt.test.ts | 52 +- 17 files changed, 4189 insertions(+), 4588 deletions(-) diff --git a/.github/workflows/e2e_network_tests.yml b/.github/workflows/e2e_network_tests.yml index d036fc62467..232420fca12 100644 --- a/.github/workflows/e2e_network_tests.yml +++ b/.github/workflows/e2e_network_tests.yml @@ -31,8 +31,8 @@ jobs: needs: build runs-on: ubuntu-latest env: - INFURA_SEPOLIA_HTTP: ${{ secrets.INFURA_SEPOLIA_HTTP }} - INFURA_MAINNET_HTTP: ${{ secrets.INFURA_MAINNET_HTTP }} + INFURA_SEPOLIA_HTTP: ${{ secrets.CS_ETH_SEPOLIA }} + INFURA_MAINNET_HTTP: ${{ secrets.CS_ETH_MAINNET }} MODE: ${{ matrix.mode }} TEST_ACCOUNT_ADDRESS: ${{ fromJSON('{"sepolia":"0xa127C5E6a7E3600Ac34A9a9928E52521677e7211","mainnet":"0x98AF911164f9d4E0f5983ed114949c3Bfe3ADc9d"}')[matrix.network] }} ALLOWED_SEND_TRANSACTION: ${{ secrets.E2E_TESTS_ALLOWED_SEND_TRANSACTION }} diff --git a/packages/web3/test/e2e/fixtures/mainnet.ts b/packages/web3/test/e2e/fixtures/mainnet.ts index 2d858a6c9a1..6031a88c82a 100644 --- a/packages/web3/test/e2e/fixtures/mainnet.ts +++ b/packages/web3/test/e2e/fixtures/mainnet.ts @@ -15,225 +15,251 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ export const mainnetBlock = { - baseFeePerGas: '0x474472184', + baseFeePerGas: '0x1e059ce23', + blobGasUsed: '0x0', difficulty: '0x0', - extraData: '0xd883010b05846765746888676f312e32302e32856c696e7578', + excessBlobGas: '0x0', + extraData: '0x6265617665726275696c642e6f7267', gasLimit: '0x1c9c380', - gasUsed: '0x143f430', - hash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', + gasUsed: '0xc191f6', + hash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', logsBloom: - '0x4df74c536feb5b9b15f957639771c6a373e719164f8593a74f9bbea57eaafd57bc3713cc5f12770cff1397fa4347c99e0f7d1e2edb5aedd4bf21d5e21ea43963fd767ad75fefcb3dffefe37b5d3a0879e29b14a80deefa730dd29ccd9e7134833aa03fb27b97d98982427405ac0abedd425a3bd70b7d5ff34f5d2cda3e7fd29fcf23d71d0a4c370005d82dfe53be067656d2bce157469cf97ff5ab7ce330166f9ed87d5717a46a3b603affe5b13cedca2b5a46bdeab6abab0dd72c3f14e2fdda4e38bd6e5e0b3e5bc04edb366cef95faf8f96edba7fb645a770e3daeca8de47f54736b5881078d85882d16ada151ea84e6779b30cb7ca4d68f8dbf31f296fc87', - miner: '0x4675c7e5baafbffbca748158becba61ef3b0a263', - mixHash: '0x4ec3b909884d099f633243913328e65d659c646e349c14ced389280fefab41c3', + '0x8b2340222300318705080cd0fcf01103390180800e211050189f44e117b398ea22c33464eafd46900e413aba8f0fdb848a3bc6e0b802f6b409d22ec1122b5693053c810e5640bb6d68a5763aa06040fc842716b349f64c03e02210049b2c0ae13f00621297f409390d7e4c94109d6f5637224d2b03c697245a000d95184d1c48b4644271145760e1aa6db0c80b360847012926836334894ed41926534d92080c8fbf0f9433ba33902e54d0ee49d2bd6c84e5a5f23740604507622520a40a537d479b329a90902b706280c420227f18d613132e0687233cf705047022f272e11635516ac188308f29c3c631b6c64508c78a09762c9c1873d989faa0bc7c74346b', + miner: '0x95222290dd7278aa3ddd389cc1e1d165cc4bafe5', + mixHash: '0xca757a869b451781a0bfd1253e74e20bc6d41013cf53335c1713d754f81588fb', nonce: '0x0', - number: '0x103dab0', - parentHash: '0x28ad78b5598691f1eb3aee2a17540496b539fb4f72ca5eaa461a331791cfc7cd', - receiptsRoot: '0x78017242efd230482ca0a6ca47a5c3bed5a275b6e3b09223ff8e2354f3136772', + number: '0x13e6595', + parentBeaconBlockRoot: '0x377d6a6271304c814d336cb087cc30ca17bbf1e07dece5ea33d6327cce88566f', + parentHash: '0xa29691d149e15630b582c27cc4fe900359536d6c872fc57578167b0c694fd1dc', + receiptsRoot: '0xb3426824a79dc6d684d3a7a17350475eec7103499fa1e4298bdba5e57dc4d1b0', sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347', - size: '0x493d0', - stateRoot: '0x637b62addfc277cb5ae4aac3c8b3bfc8e49ebe9369d07d9757c5f1f2ec937306', - timestamp: '0x64363eef', + size: '0x1011d', + stateRoot: '0x977fa00c772e3127c0c47bfe9226222adbc186d5199a67e21f77f6c34ee62a5c', + timestamp: '0x66fb25a7', totalDifficulty: '0xc70d815d562d3cfa955', transactions: [ - '0xfe87d41469efbea299780c8e218590753e0893ee2d2d65f867d9c9c7b9ed591f', - '0x603caf7d4be62e5946268fa1b594029c40fab23826d388729367c37649ea3967', - '0x4f8da807b7f0f44a4fd67eaa16cc4ef6f1071a0d8ae06349bef904f8f14f0903', - '0x199eb2a37faf1af74c752de5f378859c40a8929c52af1402bf98c9acc309438e', - '0x9775612f318528221f773a926a72c758f5b6d1eb7871b7a4309fe2d870ea1452', - '0xdc7f7a7c4d7017c13c795fc303c5b24814e27f102f908bcb33b8f5b7e943a8e4', - '0x19d1a0d3ec5c0edb9f5e92fb5f8707ae92b56505093e602bea42be92a07e44af', - '0x9c3c1a113ed268ea222e7d9c35ce0abf5bd15f7f7dd4c00b31fd4de1a9cb57dd', - '0x2ad8b77960551ee3fa86b1ede54219db9490e5320bb479a467be1563f49070fa', - '0xee84b1ac8feb236190b84717a4d186b92278939d36346c81a0ee35c316763900', - '0x1789d5fc0756c57f5035cf7e0776c908d20350a2474b6a24f06d0c0f5aec9671', - '0xc6b456b175dd46508260658d2730e30f92a79ffc5be7310098a45dd70e4292fa', - '0x94e1c3b9a52d7a5e1c6c79dff79ef48d6b9e66aebebbc416a70f006c4382fb23', - '0x7aa9ab138d57ba3ca97edde17570ec90bad03e5c0e2e39ef6f2d57b06906e947', - '0x0aa9988e0a851495beb7ea8d0f48e30042167dd98d932cf32535ea60c7c39e2b', - '0x1752d428626dd31ea7546beb62e2c5d6a27ef9f37e14954a8e6d2e4e290b8d92', - '0xdaa6805bdf1f554cfc744fe22a6661642c87141467b7f14edd0f946c9cb0f8ce', - '0x3fd6e1a5c50cf84d53f9b6809db62d919121259b0de6869a8ee3ff9622c75806', - '0x608372f0608f5466eeb44c5b28408a80af6e1feb410bfe57fa5f6c6e267bec3d', - '0x9295f62e92616619793b77a3b7577b2b6617a3cd21dd13f87164689c444d64f5', - '0x11b54c9e279fcbb97484fbf4a27860f9c13768ca21f11e4df82041b0ca33df8f', - '0x2c8a744c0124abfe06295471c805dd0cfbb6a42675cf56d54c1ba851fa8dc3a2', - '0x90cb790f159d0a8fb4de0bf9c53d95ce48748251da20e254591c8a29960ddd23', - '0xc94887918fa6e72ecb1e92297b4e6d8bd157dda8be8e71d21015bef1c5da2758', - '0x7c9a5723528a8c953a6d89d5a3e11d939bb22073763cfaa9b67f23bc643754b5', - '0x75d304122e20c4e61e1be6f10e8a2bfd7172a3d2f44f123ce439e2697adc37c3', - '0x5b0805bcb55a457729c0e23541205aace38077d5d0ec38f8c4981b6ac10ad444', - '0x87a851cef867e8b76c0f00049bccf3eb95f41a4e0ed5f2656d3f029ec321aefd', - '0xc4fb4a90055b52891b9ee9ea13e59bfa08fedd2521212a2538a54ac15948694c', - '0x9a6210559642f06ad096806f546af798f6b9d1a69f246f830a23ba96df23c70e', - '0xc36c5f21974222581b9626833fe32d99e1953be7a84f8de99289799b6c28cfdc', - '0x5555125fe67d3a36555050d41b8ca19ff036d6a338add7c285eef925100b7d49', - '0xc9b0ffd52b2d3179cab61f22302eed123144dca2367455f0b26cbd57a54d6d6f', - '0xb47865548d28112a9b37e3909fe2310918a4a70054b2e10f0a25b81ad2bfd695', - '0xeba0d7487248cc40f7a9784f20c879cc358231ac73cb56900629b11a2de6ef23', - '0x77fab2e3ef8460a5259e7107cf0cbc1a1e31678d112aaf248b2108159b4416a3', - '0x216b046ab639e61930add4323bf64b76d91db121963350632ed82f26bb6de7e6', - '0xd39d9a75f852bcb051393709ddb894ee043b7ea18bc21ce4ebd5a3560142b60c', - '0xb7f3dbb72b2f8fe579b81a3ec11a56008b09d90f2a5267180fd8f966a1b76cce', - '0x2bb7f5e1d071f0dc7040fc1ae745274a456e25610cfcfcd38e9cb3205f227222', - '0x6c53f5e35d76bfaab1d1eaa75b553da7bed8fe046f90961441474c6852b0469f', - '0x346d0ad3d6a351797184f880b08b913dd095d12f36ade9e75eb7cba6980dbf34', - '0x209624ade75ef69c5b0b1c8d85ebb1be2a084380f3eff7fb15fafc6d607da908', - '0xc76320b5a1943478674adc1c81ec441e0798525ff8c5aba49a13e0feccfbb6b3', - '0x79474757728de960eb4e7da5bd14cd3bbaa342a1f15a0e02920020bc17293e98', - '0xcbd72caf3b24a675faac5188b7bc15768c2bdd4e6a2a8c60ce79f1875b36b4e8', - '0x2350e1d8dbaaef1c51429dd50f319f7ae0c60681b17e925abe7f6b79b85bdf6c', - '0x76c881e0add6fbe11dfc4396ff8f373f2bb1cc27db929b95a21cd64b7dc41e11', - '0x3ec134ed1e10df2b1b78311fcd38325b2da8e5da5ecfb60573909450a04693e4', - '0x8587b3eb001a4d9c367b44d3c66d864bd086f7def58681fa568c25c1632197fe', - '0x4e52482e36a15ab65b1ee34d20f93b54cd1873e1b596c874364c59125dd23b62', - '0x5512e2f3ae0e44b1993cbfcea2f91fbc8e6cf2ef6bc73b606f19db051935c30b', - '0x47effec3066af633b7b8e31eb958720b3c26101a660b68294cfd5d1da9df660e', - '0xd6356b5d6aba735dad22a19dc1c6f1e90dc5b9cae6981e3242b551da32a56420', - '0xd2ae45072ed92e1c0f0dc9770700e2aea61c564c3cf9966043fcb4ff503e6bc5', - '0x3a9d565f5193dbfd7bdae074e6405d6cd0d6334a99b23d4780afdf70730ea265', - '0xe3a4f72856bfda9647b3699182bd386445ac649dcc8b1ce16e00ffcfbf4ab7ed', - '0xd8640e034189ad0e1c19c56cc4283d58a6fb953eb4b07490f1908de722939c36', - '0x52afd7942b5e6b188b162fbef65fea001d87904a218a1863cd55e35c38152d32', - '0xb261c0e8b9db2323039cd792af63941d6891e59f9a47fb920a1cfa70188284a3', - '0x545a0dafc33502a9e74440ffe4aaeb896a6c2248c1d5e02b2a211936f97fe375', - '0x5e48f0c28319b84d3ea08d316b91dc23d6ddcff46c4064760d2f83d848ede467', - '0x848514cee29d37999e27991e25c2cd58edc0486fdbcd2bf673a14d0e37bc3d12', - '0x5c1464d4fd1ef55d3fc1c1e9338917273b1d2280fd06fe04afa607557ab9c9d9', - '0x461702cf4d7d04f70337251a6ce8aa386f96a55214eae9e71697ad2e3d686acf', - '0x4d0b6bd0b7dc8b332fc7f80c3c5774c467080976fa2460d85a9c032a3e230d94', - '0x06ad8cefc9d677ea422fedbbc23fe323f830070fbc93ee394abf986453026dc5', - '0xd77ad6002fc4ccec33de15972123777c0e036cf8f2ce5e1a4d858dd99b11cbd3', - '0x3c829847832f898dd18a8674e81eba1e7179912397f48a53e31b6d98ad79026d', - '0xd90e21f60f14d0d6734a06a08ea72718c0da1dde84d927578f8bc3817eec2cfa', - '0x6d6269d0e0c72d8683f741cfb76b0d5e9f2dad7fe0a31cd84a655a5f48e2a3fa', - '0x16405e445187de6e1282740494fc6af3a25cdfdea2de89014ace9a91f68ba6c3', - '0xe622306295b723bf0da62a8946e0c624a3375096669cd379bc437ba3a0e2b6b1', - '0x804e7b2c8b74700c58f930f56e09e49a037b9dc454245ed87e469af5d73d7db6', - '0x9944ff3b953f8a03d29719d2f1921d2f7ad23f28435aabc7a1cc16633c4c3efc', - '0xb6b4ef98d38a6a05809d1bf3f54ad65ce4c5b5ed5ae5bb77efc9448b46809735', - '0x93b1efe0e8e99c39e0196bd596d4558863ffa78edc8c3b7a223a6a12a7b39ad4', - '0xa7665ef46de3416737bb9768e48908a625d89395dfe14e47f863da8fea76db6f', - '0x28d9b81fe5974728f846e2c752a43dae559687dfa4aa5732c184e25e65dde89f', - '0x2ed95ae311604dda2a370282bd6f3449cc1a4f2756f118f1aeb1d60c98c90ebc', - '0x04bff1f526355878a5a79105a6fa4a4947ec23a6267afb8a2e7c7ce40fa2eda7', - '0x78e4f8d6d388ebaf4a1b43f3232b97a5f25655ab2e18b2c8cf509940f0a57a62', - '0x39fc3a2f506b038e3b502727345edcf6c42127bd97c906bf5cd69c1d5e9ceec4', - '0x9c850596d23bfc226f4177a827d27cbfd13373ab3c6c8f083de69da4d4aba82a', - '0x30f4c85342e02c43297d2720b034d8b724f38281d34a7c2dfb84328317da549b', - '0xbc83390bc39958798cb3066bf330a5611945aa5ca5112a55b92d6c689554ad60', - '0xf0a99df33c3ab18658dd8625fd41cf41dc83dc44f19688f3cf17f04514a0d4cb', - '0x080d36e7596e73af440400f2542d2b93c0b3cf3af6cfe400ac3fd469d958b338', - '0xc27d72675970b34668bea3e241a10e3f8e963a9bbae7b69f1cf27dc6aecbcbe5', - '0xf062f350fcb7ceb7eda9cb8265e9a5922249ceddcb1a40b67ba1af43bb5c8597', - '0x76a287becd9daa920e1d26b9ee1843d03ce6df36b5434076738b90c323ba3a82', - '0x51bfb597e154b9df1dfab45885c8219dd3ba99c0fa80631acba6b635471f74a5', - '0x0d7b43abc4b92337b064b74f7e2ff87c337cf0a5690a54dac34f2edf555d0733', - '0x6d9cf19ee0ca152ae9c5634caae877ab6011a70ee330225d9546589d74b3e087', - '0x1fef29d91355611b129ff67f970f6d1da96104df0310bd3b72237367723757d8', - '0xa1ad417520e8fc7d9c8d480e98b929487614daac0c8864879182dfad732054ef', - '0x7fcdfa9acd5255dafc8ddff55a2d8f06c93476eed34b511b7f504fc3eb0a4fa1', - '0x69297bc8fafd076c18fa178358ebf0782730e1efe1c5d0dc057c4a42c7d13bc7', - '0x885dedc7616cefc16490d6dbec79b7ccc7dd1615367d2c4101084d60f2fdbea1', - '0x03a87bf75fb7637fff63350513f286fdf23a5c0c5a561122f1e768c76ec6ea2b', - '0xf76389acc92906f1290f3a854aa7bdff09ee6b7194a6cdbe3867b3b2f7b16fc3', - '0xa7cecd23fab592aa7f3aa37045b16a35c73b2bcfa51d9d5a7a7d15424b78e4af', - '0x0fb59a5f28f25c78c39c72e0232934bd6b8646064ddd4d66e8c8b5695fa8184b', - '0x2343a15826c2683c027de01886924efeef1418ca43eef7f1e386e1e691cc14a4', - '0xe69e2160e90c6ef7f1a72c8bf4bdaf8e04fd679990acbacf1e9d9942eb2e21e3', - '0x0853356e276a49527201727e5e994403d7071fd8c20c4fe3513be09eb26422da', - '0x5c9d87e4015d92c11f2153f8133f8709294a3aedcf446523b48d8ca9f90cf999', - '0x410a2d3073786f43ba1c0dcd5715031940b1eac224ddfbc09a2533b98e1961ce', - '0xd074a2e071d48cd543a4c2f78cbb494a5f5b7e205d2f9f16b749d3e79fc744c1', - '0xfc7ae9cd5806dcc1bd8521581ce0187472dd6d2551e512e7a5d99e31692ce753', - '0x90910adfad4d375b9f1fe068c38cfb61fa27f8f3fffd5449a056410db031af0e', - '0xd4b42ed78389a43e47061ee844c2b68ed631da72ceea389363a9bab05cc8e5e8', - '0x504e3f22373700cb294db5b5b5402f45d8c4a02d7e996e52b51a0502a6b7cc87', - '0x96b93b9a250a2c76261558470c0242115dc1ebda5e1a5206489ee033fb31284a', - '0x0d16cbef0f3df967f3dd0a10606785c4d7ae9bb6cc4ae8018402a5a839a1f497', - '0xf80ba14af91cdf4a398fc6d7ab439f721af496428eb789749cb2da23eaf31052', - '0xb8c7acb46336a721893b6171ce9ae326e8b861913ee8502560798dc03a4b428a', - '0x585f52cc267bc31ed76456e10e26462e8ba898419cc8b9d59f6f76c5869e4b41', - '0x07158ecabeaa23e23a2b4af3bf54be3f29da81f282cd031358c66addaff2e8d5', - '0xbe213bb3cf09088600a8a4d6dcaa6e43e22c730a2b79686b99cb2dd23c89b0ac', - '0x16c47e6331c4356d92def58627a88982ba34e0fdc5d38a0967a79faa2ba59c28', - '0xa7eb4f13bd122d16890db32cc95498c41c899d90db6ded546595635be8afd65f', - '0x0f306416f5f9ba69fcc20348dce199ad14402c5d0956c34d1d68535b7b456a6f', - '0xc8ca24a0da8b3403305b9cadb26dadcf547d8f23487b5ad1f8d63269786ff46e', - '0xef8be164d94c0eb5f2bdee4e23897d7992cf6eed26ea29543070ee2798f7469e', - '0x3fbd6a8181c0fbfb48689db9bc12e4615ca4afc49607a06c8899c5eace3c087c', - '0x446b5bd934e67d7c6549077efee4b02f439fd2e1115914173ed449f223b45aee', - '0xe65b6bec825c8ce3df9456cdd55390cbc09fc5f86c20e19455d67968339ac0e8', - '0x9aa4c2aebcb87337eaafd0768324e964af29fe34948a73c3f65205578874faa6', - '0xef8f8c6d22ee2165d735ed573e867e701dda02189a7ab991b788ccaaa132f8d0', - '0x260725511b21a06d2232db5c7f6f88ea5bbdacccec4b78569a818927a80d839b', - '0xd8b7c50d281e37dc01810fbd1c3cf314d707d175feb50f1c94e5cd07722a8e6c', - '0xa78b1dbfda5a5cc59a760c03e3e38064db95dfcb7f6b8d5d5810ecd31f445335', - '0x5470c161462213629f4d2b7402fdfda71a6fd3721d6bd5d699dcb9bc24c50d21', - '0x0943c536186591acb818e8ace6fcfd4af0df06b8853c30ddf185f78ae54ccbef', - '0x66fd0cb4264aa2e61fa2e4abc224f9682d09092865e1025974a4bde51ad906d8', - '0x13e1fddea8ffcfb5847041614af2e1502a7be4f0507645fa5216ed8b661e6c23', - '0xdf214d4148f2ac955b0c1097b2c633b5dfae2751a965cd9260b12874ae12bfd9', - '0x9e0b6d88702128b00efba753c85fdedf93c4c91e242f8610e539571bca485932', - '0xffc4ee5481e35cf09f5675a05593f8bcd1fbe3c0bfd742ba64655bfbfe5cdc59', - '0x8628c214d87f83b8b6325d648383d3a34a9abc54d7be64606b9e9393c5bb2c87', - '0x57840573da6aee90a1df7c054e694cea1bdbbcc0ce5504a4c47296bf93b75301', - '0x7495e9e0cf9f848a202fc3e051bce519b26967c4933ea9f4a3744d75964124b3', - '0xff7d2273873f7b16e131755ed47ed8de55e540a4bb8d47449d84127ddd3a8bb5', - '0x2dd3225299367625b920766f718ecd62d0d66738ece52fd44c4adb0f8f794c75', - '0xd600a0365ebc112528c0464dd4562de2a74eb692004be7a08b60a821c8dddd19', - '0xdb05f67a2e1f965826ca9aae165d96ec1883129ba84718da14f7c35a6e1e342d', - '0x50734d83880b3f249d60c15226df34c22e222faa5079c3d7ed7665dddc906ece', - '0x6173d906ffd35d3b326a3e750b6d663d2955fdc6deeab20e409af5385cf8e4c8', - '0x00c1a4dc51c377b6bb00af16bb30526543f727c11a6370741191979c471d1ffc', - '0x8c7518bea80f39a803930123b6782845ce8f8d99a782163aadfa924cbb28ee91', - '0x4ceca9cf5bff5da1d3d1837fb77f1f576767b8a9d6d4062de0eee706b7773d6a', - '0x03f236728362e5cfc12a712b822a3ab1d79e0eb0268ea771dac94c17750283f1', - '0x57574acd1a26c9e233f2ba2c5a7c8b81f6dc05ac9b80b1f87a586937322df147', - '0x2f51883b48c322148fc624e8c4c974f4ffe960cc65bdd9bed9085c899eed8926', - '0xa335d36a424727d3d6a533abd8c1d55c1647272140e20590852266f66bb21055', - '0xab5f09775f84c67c0105a2a0708a0d8e0944f6104357944074efc7e0933fbcf3', - '0xfc344b84da81960aa983cbeed2a393d9b1fa7aabb0d844e6f82a5f6c94a3c086', - '0xe64be15aecd91f995ace79f4019a9527a8abe979a3468b35600da437a1478c70', - '0x004a9a2ab277e27f7004aa54b28981e62cdc495d3186fb06e158e8424cf5967c', - '0x684e32bbc27f76e759dc9f785c98be14d26f6e1010ef75cc025c70945f530fce', - '0xddc2aba98e71ea83790e0d5cbab037f6e70bf5a58d9790364cab6f4d852ae897', - '0x2fe22d7a6493b92654f01e5ded1cb917c5c2924a38e663128046a7952a2c93ec', - '0x7fcbb7a587ba7d0165a58b5e6e3020988dd4920b318ba340080b1ad762998f0e', - '0x86b6bcf0ceb9b60090994f3dd76788cef71d348ca69fffdab38754815b73e85c', - '0x8eadb42b3a03ff3e8523f5830f6c95a3264fb9276317ddbc3e8cc97fc189db1d', - '0x022ac2d203c97313448c6439f25af381448c5fb250067c96abad48c52ea63b25', - '0xe71bed152a7e265fcdc08eb8f6f5217141c1660c79e0a2315801b48a17de9443', - '0xbe2db43eb64a29a1305510cee016accf743960735aed99bb4aeb831956531f5b', - '0x80f00d868b70689d383cdab459c9c68f606de18d4d5a4fc25258870e42aa65ae', - '0x2a69d29b4302deff2515e87041b722bb229603429ea4d31fe81c878efed67f81', - '0x6323bd97a58dab264aaeea1aa12ece39b5eef1a1488e65f813609e1c47fdc66f', - '0x9ff09456b9098544e68e8e27cd3f1445d8606fdfcdebfa74d24d1bc87a9c2462', - '0x8d7f6f64c5cbdb533b579647746392c50db5fd0247981c7b430f4fe206bad302', - '0xb94ff102a30dcdcf8c2b1385246a2f205f4a7937b58182b7df04e38dc4fba63a', - '0x61ca13084a53b8edfc2beb3d1f967fdfca93359043a5da9c3678889b012ad0f3', - '0x76a199229278cdd8e6dd40093b64e7664626618e7c36fd623ab630786b6dfac5', - '0x74d69e566e8bd62900e891081905009a1c2ed074165d15c0e0a096b63b1b49a7', - '0x14036d43579058171105216738457b35167820a7effb8d9386c65e20d236eb77', - '0x25c1684f6966caff802e85749b550d9be2934820d5c91c6f62487287675a629e', - '0x9c00826fd016714e191a685e31c918e5f9151d807d1b5b955a3ea514ffcd19de', - '0xe04b3af4d15e1edcae6e981f5f1d9d75af4f7cd06f12c73ee42e51c00ef14364', - '0x0357d246c9ddd57f05170a038ddb04c4c2554371a5cd1e1d7bdda50b6080939f', - '0x002ec16d799ba0c7c3251ba82a68151016066f4c49ea22c6441711184aff4799', - '0x2393a72f9b086878d13a8dae1e44607cb9033fd94d4777ea907dc457db3dbc44', - '0x870c8c1508aecd4147d0f9e6cd1a84227b743ed2589d013e18d481674ca8f42e', - '0x91af138e974e7f4c84f22362bc8f7247ec806baaa7d6cbc68a67e9689955e78b', - '0xf37b9efe2a4130127072a2f6a3ae5c7311e48bf3022a1433b7dba6423bf977d3', - '0x241263ac0c3c04d623485fb5d4e7a2af103a7db5eabfe0b2d2afe0506585e509', - '0x8df5d0fcd95081999a6c417f8be98633d1bc3d0f6fcb6795eeb600ca9e676f8f', - '0x4176e756b40466a7126aef4fa046a728ad62f51266a2a3b4a92b15366ac688b1', - '0xbd6b5651c5c324e8c2ebe6e89c633bf3b33ca9bcd2c5d730608d3fecd11bf031', - '0x0f48823439c41ab6b36752bb865cc156d1f56d9e5284eb0c9d0b0177f298f79f', - '0x12d7dbfb0bee81eb327e32170b201fbc8445ce3d780f446b50cc10b2c6a08ed2', - '0xc6f78588f68038b676f7a0ca3324f2c6b24618bf43b5c6e68704262e3fceba4a', - '0xfaeaf9b4a6c5fcac8005239112a27f9c059e7aeb436f31f192a80c1691c29f29', + '0x5771987837eb244c287a714f36d5738726d472a6b3a46deae2e1d4ef0965a1b0', + '0xdcc36c7c0f1ec3ed4a2290819adde014f1866bba041244297d4dd26b8ad7a677', + '0xee0003228eef79a57b7cd7ed3af7731975cfd03960742f9c913f2145378783f2', + '0xce0140df7c5a13652c604946936996558a7b6ec3b5d87a6ce423a7bc94297cda', + '0x90f9c51bf847a60f73a9b776629822733e2298f1927c0ae03d63f53ee31012a7', + '0xd1681df399f4f39400bd73afabcfc07dda96ac80d97ed4d13a62dc28d127c871', + '0x79fd3cd0c84acfbb1b9c8f2ab33517626eceb8cb42c21f1c21439ce36e0e6cab', + '0x98bd6c18c9a40ae4f1e6c12dc40173be751cf1cab68826e266aa9c854b91022e', + '0x78930161632382a4a85465cb643898c748980d3e302c720ef87e938e1e8067fc', + '0x7df40bcfc939178a451a97fe73bbbc1919ecacf1e82fc0c6a477c74cdce96c44', + '0xee72ee26a30d266273173fc50c498a87d690b4728f11b2bfeb88c3a65830e5ee', + '0x0bd388895c3746fba476fe54d3e03b3b541f673dcad2f8c22db88370ca8737a2', + '0x3100f0c75bed957f6dd0a032b08a809431a2e90b887bb5533e49d90c74f5436e', + '0xa09dc1486ca6715911aa3f78dfa894eb4e12ed4a2c87f50a0f68cc9fe790c048', + '0xa7a0f5692591c91286b872a20149f82aee2bb8fe0628adbe5a9656168936b28a', + '0x70ab00c16c6b9d4c6d2c3e385fbd19b2cda0b38d887ed8eade2b3b4fcf0a0c3a', + '0xbf4f04f76f5915455ce951e0b491901f2299d47de4bc9a1648c7befd210ef342', + '0x5dcbc082b249db57486fd7c07c5ac216cdb4a41fa2eef1db0df0265f600caabc', + '0xd7380daf59f9b56d1956ce6454c226c70da6b69cf794cfe244e36e95279be489', + '0x71a4672d1336fb1c60b67ec80c5cab5f484f713165a152732d65449f9d0c0515', + '0x91fb16f5fb7a319cf1d2f0b156f6d1fe4a4e6fdaefe7b8aca18791d76f52ce73', + '0xcac130c48fc8a647cfed37d83f66428b35b37e26ef9818576f8f7b2571ec90b9', + '0x4b8d7d87fdf6443d6756d37d0bdbe4470ed090e25a640d66f8017bc403a9df14', + '0xa1d4d8c1f210acf9cff439e1c4507ee1fcace172fb56bfead537fbf4038a1bd5', + '0x7a384c750acb5458fc07525005cdc4808820f6c0a027a21cf9e219d2256eec17', + '0xa45d400b6cd4dc40fb5c010bd0211d305b9418612aec827a958b896a037665b2', + '0xb392bc0e47075d16a9f9257635c878a70c435759be7169b315211789f5c57596', + '0xa8c2d6478fec54e7dd3a3e0209b42611ec0b3706fa09c452b9095feb02445fd0', + '0xb4def4daaabf6ca2dfbebd6c8a441fded38defa10a10b5d46a531a405255d1aa', + '0xb2c0f6026e5b51fe951a84d415140676400013f01e289e839a69dbe8b11c1eb7', + '0xf93510911a3eda491e29c5f04c4afd0d69e1377275110ac2cd17934c566ecd38', + '0x23e61859fe8a80e468e0a3245fb4cc58ec16d435a3bca86e2d408687c08ca070', + '0xba6c4057ca0038a489946446e9e3d386ff7b5b07048a04d515db65a9796ab9cf', + '0x6ec7b0619ede7805b1794f4453bfed7ea0a200035d12c461a04e9a44c5926259', + '0xfc3f0a738258301939f329633bdf619cf699f64d46ee46b1ca8842f2715130ed', + '0xac90a64a9c747bfc03ebb82158f6b9660b26b93d154193546291738fc5b163e4', + '0x2c8f6836d4e5018b833f7994ed96cb877c7665f732637ba241a7178fb7ae358c', + '0x86ae40dbde02d7f87e8d79d4dce1a50e09a7c0b3d701c42c0b5826aea607bbee', + '0x705f084a5cb516c9b5170a592b40a8f9e544d319cc26aac5823aad6dcc713983', + '0x1fcb229b1e8812bd04201a4c8ee1ba4b4c9924ff7bb00fe85e0fb55d5f184ebc', + '0xa669602d5fc23384386ee05919a58597a3b8baf076ff05180c22d4172cd500a3', + '0xd27a6a61c34ba2c013edebf18af692db423e12c72bfad81a3b9e79cfa140a0a4', + '0x8d3c220a5ddd846f638447ad29bee5c1d10abdeca329f0e2b0139fe60960a561', + '0xf0ae50a850e3a19b7ee125f6a925c18899de2dbb68f2a5f1ab91d8c9a71985b7', + '0x0337f05748fda0f12f67ee9e66fbd64f0d8747201ff97fe9fa62cc8e43224c28', + '0x97e22f8d634ad84031659e8305240d6b30e5c38a5d4decedfedcc67378dc3c28', + '0xba44bfb96a9805965e4ac11529ea2d3e7e5e0b88880c7db012eae3544fcc83de', + '0xfa31110a4d634fac73ab00a04e3f64f6f3a9bfe82579bb0cfbc887c234575445', + '0x8df0a1bb53ea6cc3596a05c452d7b0f1cb7d605ad9becefbda542c8fc56986e7', + '0x3c161640067fdb42954e6a13a66b41faac10dd2b4bdb9387ef6066526413f58a', + '0x069bfd72ad2f8e3c5aeb35fda21dbf5b0ef48fdfe318a2f037c5e916d5b85982', + '0xc23c5bc63ae7bc038673e3258d0217b9849ed6c5c44a3ab8bf5057ada773995e', + '0x47c7e4c8b818b655a0d210a4ccfd9d01c144c424b546f0d8060d9df760cd4fcf', + '0x17b23e825ef1a9a3d8bb1be42c4c814a6e331c60d79de5c50b42e5c197257e76', + '0x8af817b25c16ad3a3c7bfe68c5165a2314aef37e7b485a68fc7102df805162ff', + '0x87c5830b100585cdc5c29644bba54eda44d1508c32d5c6c5fa0321e986cfaea4', + '0xabf04b2329ea6738ead1f4bb34305b753e7b525a0481e8555ec3e5ccbdc951fd', + '0x257dfbb34339d74bb45c8dd8115ca42794ef9ac83ccf9d8f0b9351674909390e', + '0x1dd04b7e7904d38fd46feb593b734037aa67d29fe19c25b038befe5af56a646b', + '0x586848dbb2925f9035ed9a59a73382e6d4b043948c59b6c092a0a9e8c2a9c055', + '0xc25c4f94958047698905f548fac93ab1d018e46d58aad05effc102317a8bc1ac', + '0x340811e390f205b3c117d12f7c76b72b61a72c499dcd1e6232523fa42cc400f3', + '0xebfbff2ed1b70fbea0e6ecd723b4425827a16e6a321c19d110b856744ae998f2', + '0xe0538be140f6fba190704ebc37c3567564279ee638b87aaa14eaaa7815193270', + '0x3fd9147c1bcaf43b7f377afb4f1c67e95a20d47bad4f97766ef7ec438d49d689', + '0xe26912b3b9d4625115f58fad050b140bb6630c5ff120ac92c688bfc4c7f38526', + '0xe3e0657e22b40ecba21f74c9e3ea7a036ca20581b3ecbfc648530d31c0c00fa5', + '0xce117c5845d75b0c4a74c59d947c07dedef0a24626b423a71a327a3793aabaed', + '0x54fe77ad2080cc402bde9568bea9ac57439809212def927b1917cfca95c2ba97', + '0x3d47f76f93b099d79cc26dd3839ed5f9d69f3fd00817347825482a854a756cad', + '0x9fcefad5998ab0e843643b3a79f506aa5531562cc5edb296987cdb23448de1ea', + '0x62e57e308fc738015e6859d61a9226f51c7c67e118bb8b07499f91a4c5f6640d', + '0x88b8eb85f23733828a14797654e882e1c29db7f657ae4609a8f70cd2e909d74b', + '0x0569d15422b0d1d03859250b39446d4cb27d211b8fe9452103e8f920c0921ad0', + '0xf26d4a25e1e3e5e01236e2dd6b2da4fc9088e3ad63296d68101623ee8fa0cb1b', + '0x93c2d382309bb0436e5a1ca083ed47c7839a6936c86c5efe52867fc474a82b16', + '0xaa4bef9afa20f46633c4f0b731f026aace7a0c29d813ac149aedb6a95a829922', + '0x71deb87c646c3c361b5da49dceb2accf33dbd24b271a75a5f896701cd0843777', + '0x77690af18a59a9f02461afc08ef49524511b1e79006537f690ad8708f31f0c8a', + '0xb962355d3deceae05f63d90328c0aa992de4b92f94deb37aa7092bc71102d7f3', + '0xce14fc05c5273c396817f5ac373d79dbfed8e3f5edb32f9c2bcb5678e82eb45d', + '0x5ce9475d32da021dfa09beb2c8a506ad7fa3371aa505b7f4fa97b0b9d7e7b84c', + '0x45bacefba1cd0fc3c285d823fcfb13a7e5f351338549b869c40100bdf95e1d7d', + '0xe64e91d4698ccab2020a6403a91de9f18a41f0e2403ff165ebd8d84a29838a67', + '0xfaf15332c9509c54ae901d75aaf50536cf7ca73829fbe85112f38a03436ad963', + '0x784c652cb876ade81893278211aa6f75200d0c4d4743fc7d9f71a2f971768c9c', + '0xac86e6844958d835266d2343d16ef58e7974d0d627316c229046d4b2b2349a06', + '0x195865c2f47abace48f0fc6cef4c8069766f03ffefed03bd29e2c54e5d2e6387', + '0xcd7e94609b6509c3077849af898feb955501cc0473eda70a2e1b8f71645c1b43', + '0x9242328fa911035d390d9024b83e47c452419fb27c50901b572edb4a3c3ffa03', + '0x8bf3fc9155fae9fd342ab892eab592c50c6d7792ab36ff5ab04876d0919840a1', + '0x317dce199297ad295eb9f86a0eca73370bf973eb3b1c8a5bc51192b352463c63', + '0x6679fafdcad99aa47f89b5c9622bce3607b554f361c930c243ef9f7c730896b0', + '0xaa09171d7192b3e2c15448473df9303fdfbb2924ffac97b1622cbcc244bc611d', + '0xec4b17733c6b209ffc7c1a0cf52a81b58c0ced7fa7dd9a517f333c31b43b4737', + '0xac268b9788cf5573d20613aa95055d753ec4aeac18dff58cec30becba94c20a7', + '0xf13b4b6ccaa0dc5f5a0b6222ffc2e8828bf76c1322f5ea7edb2f9f1f11e2a8d4', + '0x2eaca14d3b8767f53e804fe1df66462b1d019fc14aef1e9d332fc3f1b6281d15', + '0x2ee7746a27c3534a9f1e8c3e0c82c3586912802972541b282c6d690fc2c6148b', + '0xcfa49a01f1d297950088cbf3edd1553afde08ee4a48c1352928d42e706ce7e60', + '0x63d73c66684216c3b390b722c17bb91319fb37f46728af97a52524c68d5cce98', + '0xe41808098865c3328b93d3b933b150f628530bb55e3f547b650e21c81d8f6b78', + '0x3a0f37c359e45e99aa5a4eb7f4589f99fc4eaede3dcf92791dea1ccd997a4e28', + '0x090dff6a83c38b80f4c90e126807aafc3df7ef3383e3f762188f1d5c436a2d3e', + '0x9bbaf55032c96579275fcbd54dd02671ced1ffe1729e2dc6f86904047fe7e86d', + '0x405dda79e62ca02cde3cc9c61f228585d202e339b187a9cafc7ce78b19e3a3a2', + '0xc95603610d088c508fa1e558a69b5b7dce048047681b6aadc0f38bf6b828d2e6', + '0xaf3aa64caed406e4f3ef916a73a57b7e0e2422eb0c10901688aee84a8fc43658', + '0x161e7067588208d17b7c436b05189dd5a9fc6f03b69a7b986857768139cace0f', + '0x15406b7097b2c943bd7cbadbd6655b5f904aae8b487a5498f2df1834f328ee43', + '0x12ae4dfa36d9e0632ef111787fa87df8d3cf00eb307fef2c29c25eb3f83d2766', + '0x8928a5a20d8799547b46a5f9f4417aceab1eec4f3b32368d9c6118d500c24435', + '0xc5b949c37ffb3889b6f259170ce0cf5db0b2455e2526dfd051624da15677e331', + '0x1c35fe8540ddb3a80d0726f17dee3938ec63004081c0dbb0de543e5347824f29', + '0xb390e14e9ced4f0e55565e64c92cc0733fcdf493d7a5607c20cb2dfaa598d38a', + '0xe3b84037c08bb7c5ac3954825d85d124c41d1fceb3792877a3afbde0cc6014c1', + '0x82bd69e948636e2e219d14a8b0a70a065c0cecf2c73f1376bd89b03ed4ae6eca', + '0x3387d9f901d54e22f0945d44f625747336f7973bdc971c64f65ff2c9d6d68ef5', + '0xdb41e036f0976e7f654af6bd32dbb55f1cb104cb3fa3e7d8d629bbf9194822ea', + '0x81bf92f05529a802bfcfbe3e2b8faf7ecf8e7334dce01cf8eeeb92271be5e828', ], - transactionsRoot: '0x2b0f787500743395385ad4a4142693bffd51d508cae1fdd675d269842b9bc2b0', + transactionsRoot: '0xfd003b6a8672be4629cb504525088d8e9c864716ca0f1ccc4f6179971c82df6c', uncles: [], + withdrawals: [ + { + index: '0x3a76c3b', + validatorIndex: '0xc9c3c', + address: '0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f', + amount: '0x124beab', + }, + { + index: '0x3a76c3c', + validatorIndex: '0xc9c3d', + address: '0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f', + amount: '0x124857f', + }, + { + index: '0x3a76c3d', + validatorIndex: '0xc9c3e', + address: '0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f', + amount: '0x125dc43', + }, + { + index: '0x3a76c3e', + validatorIndex: '0xc9c3f', + address: '0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f', + amount: '0x125f412', + }, + { + index: '0x3a76c3f', + validatorIndex: '0xc9c40', + address: '0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f', + amount: '0x125d2ff', + }, + { + index: '0x3a76c40', + validatorIndex: '0xc9c41', + address: '0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f', + amount: '0x1259b85', + }, + { + index: '0x3a76c41', + validatorIndex: '0xc9c42', + address: '0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f', + amount: '0x3e86c00', + }, + { + index: '0x3a76c42', + validatorIndex: '0xc9c43', + address: '0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f', + amount: '0x1260675', + }, + { + index: '0x3a76c43', + validatorIndex: '0xc9c44', + address: '0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f', + amount: '0x1265658', + }, + { + index: '0x3a76c44', + validatorIndex: '0xc9c4c', + address: '0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f', + amount: '0x1261797', + }, + { + index: '0x3a76c45', + validatorIndex: '0xc9c4d', + address: '0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f', + amount: '0x125bdf1', + }, + { + index: '0x3a76c46', + validatorIndex: '0xc9c4e', + address: '0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f', + amount: '0x125da93', + }, + { + index: '0x3a76c47', + validatorIndex: '0xc9c4f', + address: '0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f', + amount: '0x125e4cc', + }, + { + index: '0x3a76c48', + validatorIndex: '0xc9c50', + address: '0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f', + amount: '0x125fca2', + }, + { + index: '0x3a76c49', + validatorIndex: '0xc9c51', + address: '0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f', + amount: '0x125409e', + }, + { + index: '0x3a76c4a', + validatorIndex: '0xc9c52', + address: '0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f', + amount: '0x125f393', + }, + ], + withdrawalsRoot: '0x3efa15d064b679b07a7b1403e9d4ba485144661bb788dbf26e4f60d4bcd3d01b', }; export const mainnetBlockData: { @@ -250,25 +276,25 @@ export const mainnetBlockData: { pending: 'pending', finalized: 'finalized', safe: 'safe', - blockNumber: 17029808, - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', + blockNumber: 20866453, + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', }; export const mainnetProof = { accountProof: [ - '0xf90211a061a42629d4371789fb5c083c33fbb0a212366d19b5b418b482200b4eac0503cda0921eeb15c07b42918862c7669a33a2f64ac87fd76865ac27ffd47fc442296dd6a020fc23de86ad57edf44fc277658e7c51027b013997fbdf257813ae0483a9424aa08650d9f1b91cb0453a89de3c28934c33bbda62490a3b139960f5dc8696edee50a0938ae249d931088e1418698eef515883741002e4eb7630e5ae7c1065ca91d452a06e28819dfc085c8eb967b35b29940a2bf8b1e724cd4ea28b798161664f9091afa012d5225b6862724fe95cc27ed50629263e92d28044f1366964168c91e415cc86a03732489e3d9a4708cd5bd9985dcac215ed8104492f9e6b6e58d3a57718abc323a092e057e0b1f1c83a62b12483cb6816d3e8105d15108f990a78d98ded473b67d6a0ef6ec99e06a731a8a16b6d27ae505fa92c7078dd4e91cee5a6d6e2ce78c8a0bda073110a92b87d5f004fa8222c9bf298cb3a4974c34dd724c147ae72cb6e9f2af5a0af556072c40c1e93cfae2c11f630250049a1738977d8614aabf48ac48d4ceaa1a0e49322e3a8c8273d277bce7c075f28e809fe9fba975ff0a68b4c19a2086f6c10a090dc4797623b5e1c1df464cf68165cb250363c529e70884c033d789a9fb535c6a083d55b28d20db57407779adce1e5f3297ce6333c2db058d4b9e730b69cde535ea0fd6d0de8e61255d5165318f4d2e0747944a97bec1b472e77519bc1246f285e2f80', - '0xf90211a013b0863f23ec7ba9005f61eaf0c0e6466672ee3d13984f66639613773e63ae82a0c698de006df5eb411649fa119d350fe2cdcf6e0bcd50d5caca18173929570ec5a094a13b12f3724a211533f38a1bc56f837897a571b6672cbcbe4e07588ae887e0a089af3d2fcd47e0d524b5bdddcf8c188818c888ce71c968b20b0daf3f69979edfa00edd32eb159f02fe50999f9dc8adebb5dd9c48f1dbc3cff2026428ca05c5f471a00819550c6855bd618c9713d677a97ede25cf36fe09e045c0b1cc93a1b505b08da0eafcb8050d2a14bf7e6fcb07268fd40243183c24865a4e74d56940e2799c0e80a0991ccc5e472da616ed0ab870b4c8702e8e2bafaf6efde1bfaa81cf112dc8ef54a052785d9dbf1232d67ac025bf782bd9f9e619e75783b39fc8ea8f4f7b670813daa0dbc8204ab52d4420c62c1777133eafbea8cf868327ca9646a2872a43ee3613e6a00bf50322cb36599d21aed1aa81849ea3642159ed4b432bedc2ada82111866877a03fdc880ef977282a7396f6d5badee955e7c476a7da12ebec0766c4f0a00b5ed7a06927da4c320d8d36551479cf6c8634f6ae1876065a6d98656c9ad5148750fa35a0652010f361c5ccc80e4b80cbb0a8e17abef8ad7ecb520eca45d74fe5b810ad28a0a1cbb1d8e9fc8a447535f4aa0f3eb568f484be5aa7ab47c89a55280ce0285e3ca079c75ec928e6b992a9b6e943e5f696ac4a0911459e0d92d8166983dcb30261e780', - '0xf90211a0906d3fa01a6131a7f8b1b7b1021a9b03cead0061a0fb78b48e563f94e143b912a0c3bef88301ebbee8ee60d6d776c15f4f285f91077d220f794bd7ed391de1887aa08929f87db85fbc2686425225014b861df6835290f5fc922d26112b17c281d563a0aff6ded52e896cd26ab3298a84f5a2042e9983c50f47e219db834e02b923ebffa081467a1e2b5e7e98f3f2e91c50262fe3d152f9e18fa7019b9882deca0f11c227a0a1eda943a62beca8423f07ae31227cb8480a334982b66eceb8c5fb33b504a92ba09e355f61268c67f4d90bc94f1da49e5cb1a5555af643e5e41d474cc21198e0c4a02fd628b96d10a7b1174dddf2db933151dfbeeb2bea8599508fa5050ee9807029a0e304e1af1fc7f7a8bde11525b3962540e63ab6768629fb589be7b66a364b2c49a0434c3fd226f8b07a712a2908c22d132fa20ca536aebcf7036e135de1c9053959a00d1752d6848a2b0858f42ce0b34270e11d35191627d82953d9a4e04eb5109431a0cd9328b0c001a9bba15a9451a5e04e8f39e92f1498d9e5e140aca53bd853c3bba031faf17595f51f9d67a4ebad0bca3dc04681acb6cafc15be3bc340eb56ecf248a0817b6a339a574f6a12bc528c0800c2aa35c2766d0c1bece3654c0952cf94c7bba0d01ea4603336af9083b15f18d178d7051b74928bc1c2af2409d0649d9d367018a0ea65ae8a236519a85d7b56bac8d61f7e924409f587b47cb90aeb5eba23286f8f80', - '0xf90211a03ea22514219f296232ec043cc9be748640d4179974bfc579013738669fa6c1cba0c786b901e1677b1c828383db755df4759225421afeaea3de3c6ef799a7ba1655a03c4759afd6725715e5e3cab40b07a6ac3cc63b3cbf771a589ad9b50c695a2d1fa08b11fd26f0e921cd3cb55e7b3a4664a3ebeca818a4e69a633eee1cfbf7c22afba0c23177bf3c8a4f0d6bd1165e7402189338c25cc99fa27d7ae7479fbf7f8faa1ea02b90384b9f669b9ea73251ac7f889063bc8ed939ad23f059015a996e561dbdf1a0ad19658ea306c0cf9364e13138111c747e2d20b873f74696ab07bd35ebeb8822a09fac5b614101deee5129bff38028cb022439b7d2bf6add205c9e6f0b336c6da5a08017980585eb89c0ae157808040d231e36cc51ad0aea07ee9281f4481aaa3239a0b1322e1fe5f7632d8f5c5b9f8c23601d3820b591f2ebfd1b24254bdf1badfaeea05527e4c9c1930123bee9262149ad7f966d7249f533bc18b09a398213885e5285a083ea949b3c88fc1b2720993d4ab9465b1e07c39faa2102f991ddd58d4b9d21fba04209281a3ceb6f985957619d6901e61be7dfcaae0aa836d83de4e7e77d3c31bca0ad5021570629b773143685a343a93c9a46428c6bc19707cf61eaee477b3dc5e7a01da1a77a07f6020e670df0f739f053d7e3b3ec1a16279b52a0a594c4ed111856a041741f7de82565d93d05006e3abaa5cbf0026a36dca2fd785371151fb6922a3080', - '0xf90211a0c5922554164fd80e50dd9aa0e947d3cbec6f7ec1e905e7993a02a0ad6b63b428a03e8934fb021a44636cfdee14738bdefd52bf2cb877221d62a902dda4c9e20af2a0e60f11787f7d63ae9fbd87c90ebd33bb24c933d307fbc657d844a143288d871ea04a4737d77380e7517f2e54fafbb14ce71e4161dec871076f6dc2fafa4a372af8a05c011c4181c90849e4293bd2ca6d4c66d5eb30de23bc23202c1b9faf5a3dc80ea01e5b26350fb090cf79adabe4a49f07983beb2520ff0b3fda578a6a6a8513668da061096fee35ea62dfe1272dc2ed693f2a4609d1444eca46dd002df24bc6da01bea0c2366e8b160756be7b4ecf8f4e16e36f7e8f6b9c4ede78442d2e5b9bfd229b08a0e1a4e9ab4aa65c7aa7de1a9f0131bc6df85a4ee26543afd973ca0770b6a48b77a0074c7f93753cd5b3a2708253a78b8f7d208c8e6bc17b0517b3ed54385efbe44da07e9b01e890594903f9ca5c976630f71cc33c2d89d6f4cb590a8a45835f802894a0471cf580a1a9512b3611d237930598450b878532b14627ff1744bfcf022928b8a01f69dd332c5f488cdbdeec5e3d9d9f3f89f8ed8e4b2494c958ed494b4569f2a9a025523d65f51a0c24e4e2c5c7cba8bf07d93419929dd3e462b33078ed5c1a1b5aa098d2b8f2f925cbafea85d99674e3c46a9c3d891693ba02a2ed910bc8e94778e0a03a92aa841b80df9db77b6119a94b765311901a0e7f7c1f569da587ab41c0fe6c80', - '0xf90211a0d4cab5a47d8043340092eba307d3b479837e51edf2975224c46b78fa5d9f2bdea0ba8ac3bfa7a33f5d711782f010d55b300c0291356ac7a5df0c7926bc6debb839a0adfea25bac8862fb080a091f6e19a00bd137427f7a0886c8f50aeb4a3872c5a0a08179a51d62c8ee0f3ad5eb3535c56dd975a9e52260c202c36e159129779448a4a0c0f682c90f18feaa067339a7a42b583f305a79503b16d61a56f10551132773c0a028df3d931fa6fad2f30a3c471ac1a79f038980e262287030b0699bffba133ea4a0e2b138a12ce1b81f04de0f18c5cda2c1e6aedc3aa492a851f4d74d02fb8eb938a0e377cd14019780bea727694e4aaf3f354fc0dfc6635cb501b562447c90366311a0651f49adb9572e81a082469d2823d728b9d40755534c997057f0085d464cd5aca0b7d9e9ca48f3c7beae701128ecd079dc62071464d505015ac54ccda9bad97216a003a0946cf1ced04b70824b889e5d78198d87948e4b039bec65a2414924df8144a0e434d71446bc0e7e57212c6e9c51404aeaef72793a78573d11b5b52ea93364eea003b39a423c7ce0663d5fa748919a7039b7f4fcbcd00db13582de55435f5d0d0da0ebfd28715bfd53b7d382584d359028ffda90da7708131a666701a4703f258ca8a03768dc2f979daec77db519b61c2629389fe2f9f71940d04fc6d5af2f6ce5f2c7a0b4d261157f8b020cf954cdb60cd3fa1744bcb61f8da0cd49e7f91165fd83a07380', - '0xf9011180a03464dee21bd9b7f1712c25a7bf48517d93f6cd02bc5e069e85ca98eef103792b80a0ac233ce7e7018541d154a3abf88a2d3d564777b116c94fec994ce36d0ae1582ba0fd874c87366c0aaaf7fccf6065684b0745c3dcb1632d64ebb023cfe15512924e808080a02073bcfe0a91dc4b71e13226cefc82d938a69b86d682b838f1db53f367510f8f80a040c3c8f7a9522d6df5c0028d90d360f73c5169b4cf434d95350beed43e167390a0ce16551be1e0a52b73b88c006ac4f69cd4ddfa15d94f885ca37f46f2eeb84037a0a856e72e69c2131a5d4e0ac7b583725e9a400db1263a6f0b13fd298c5df84327a0598f8e0f6c6ea52b62e04c655de5e5494597c2902078b98091861dd0bf237873808080', - '0xf85180808080a06cb96634150a4bf19ad1cd1d29ead274d327b6c478fe4624570e3b7f848fea318080a014b2529162240ccb5e3b71491dcb7e3c043f6a82627f349d4cdcbcea92e6a8e7808080808080808080', - '0xf8709d20ae81a58eb98d9c78de4a1fd7fd9535fc953ed2be602daaa41767312ab850f84e808a0272380c74083753ca3ba056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470', + '0xf90211a0357a5b22fb425f5b1360deed9d26b81da132dc806b1a3d0c706efd4926e82948a087766feea405a250df48cb5e56194e125e9e03491725c0db9cc41059ddd2e6aba081c2e45f3980708974ea28d17240f43ae9a1f2229fdcaaf25c0c1dd8c91a8122a07fef16203986c02509c0b32b7803d7705eaa826782d921f954aa0398781178bea03c7d5249e2a806b52745a56c06cec5bdc3e636d04165bd9ef6b10c74bb6eceb3a09f480921eb55ba9e33805d46122dff85e29f39290ad309534bc3a677f32acb7ca060188e17d3be51fdec6117de7282f0bf5569b899a1a70ed405179d5ef19017ffa0ce0a532a54522957b0e95242ae79b53d8483dcd4c2e06c1267042381cdff5047a0f000e3892ff0d108ddf69bf71c9e5784b465beaf4ddab428840d6ebaca588c34a0253e22058875c3467dab7b7f6191c6cfa32f266d38a3fadda575680e4d569e69a09312f031b3881654a91888d5de7f0ff483e228bdc94123ef5edb73dbcc2c32eea087aaa13183d9a58f5a51b4a854b3d2d96938f9111de32f7926727f18fe2af834a0ad8b60776dd4a10d5500522cbd0c91c3f6cc9df7f63dfd81f2f2ba9e0536e1c7a02a6ffa4565860831985bb55500f7ecca24a661d5c30b55981c18942a127caf7da0250e136d471446aa68102597ae459f041459c3f164e3261e2770979b8d27efcda0a1b480f87c80c3cbf9a39b8993cb9da61fdb1c1137e74ec7368fd97c674b4aec80', + '0xf90211a0180bab613e150a739f3c13c32359cce2ba4d4a508dc44ad450f068c98c560742a00a4aec865781a92196f8cbe15c1e0aac382211f860ade175a918766fd9a8d7d8a04a4961270deb5d691a579902f9865a499723884099768693e6578338c23ad040a05d0f858e913aeabb214701c5d34eed6ebb1adaf7e0e9542a57c9fe650e124191a0547a4b92cf7e8ba83c6f3a60e7b378209e52ff301995f468c52bc689ce7ab016a0aa20af9149d1bf55c0a88a0d808f0d7f578c59e699061e4509ff13b72c594de6a0c64c0976c2562191bcabfb448dbe78675f79c79445847027d1f8037ff1d1ae2ba0731787d5a2e0ae6fa776ecd8917ab44ee770662301230d776e3bcce432e999b5a0792448520d9f64751eafad9f5345c5dd264d3f788732e2645aaa2b3b57d0a12aa0e5fac0d8151a3f5b5697cfad4d8add505c6b0735cc5d941dac5a767be36cf980a05398cd0c40e3c715c2c5b75b34d4829cacbf6fb31747bc8591d4ea16be2dff77a033f4ac3a619febd8c76ad2244ed6f8f8633c4ebbcf430fa731f8292729ac8657a0bb1e0114ee70b0252aced1f8367d93999d88f456ef00f535aa8a25dc656f919da0ffac8df32fb790ee81e9aa1812d4871b6c08398eb34471dc87a9950f35bc4cafa02cfd08476099337a64eca575077d18be3cdd94a2d5e9f16baa8e93071c00a9b2a061819bfadccc3e23eac906a12fd9049aa731a862c778d51b50b56c106a7c248f80', + '0xf90211a014ff80720228ae5b0a54b6bce328bfe993717f2cace92f74120a62600d9ff748a064393040d9fe346a11d82546a4c3731d57a472c04aa2e787e241bf1766459616a023199d6c2aa7691aeae5acd71d784cf2b607fa1f1ec486b0342f1228bea91601a08ce26d8fdfb104ccdcc007de38b8e4db6da96d4277e5b66d0dbaeef8f9d9f713a058bcb460fa9d39da829f5ef33cea928cca1b8aff2af3a24351ae9f1289a5dbd6a0623ad5025430c3f2eb748843e26893c0852782d5a5abb145cac847021f4595bda038a923edb954691f10c493103dd06e463f940f363bf9a266ca2bc97df4292bb5a0236856dcc223f66f5e18ab23336cdbf6fd28cbd0024a2de4e107f48596581783a0289940a821f8273cd304fbe61f76b319c5dc40d743280b9c39084aa2c84c2adea05d2c0560b81cca248feff91533827dfc23ef6beee3ff87e5ff8c2e816dce5413a03b58ed46e46d5862f6a480ee39b30f8062e28a656a99cf3df4e650ed1a391656a0d8ff5d7218cfaaf8eb96b614cfb3fded8e1d59fcdf68c5159d97315551b82ffea09bcd6249744f4248048fdf5a9950994064ce3ae3b6701190e24c8a6027165225a0c6d692bf21e5b7ec81360705eb5ab593677270c67bb4f35dd68ea89a800eb15ca0087eab6522c09ee8175591cbb6c4ad9b60bc9fd586304c8d5f987c0b5d68c6ada0cb061a737a054f16737650b67004dd3a7c3be8b3d2cd4db6796088f6888d31d980', + '0xf90211a0620ed8ed9eeabbaa7fa5a07f6623d78522ea9a4ea8027c3a8d456e539d50bf6ba05f8b9f2c8cfc4e9015ddf8f501e95168543ba4bbfae1e8fff7efec4ee19c796fa049fb77538ad05c085f0f20bb6e690054623c52fabfd4d132bbe8357cb9ad630ea08d0f9ecdb8c9fefe836cfbb1338b951b525a069f61b6d6da1ecfcfc3262684a3a0c770e769123b7fe059d8b47230e0a45d03c53666186a9adc79b35abfdc477328a0f391f9ae709b41a35c0ae92586225cc8ee233f19c6eb72a4ef30a274fcd77361a060e0617146949032eb86f86b9490a255f658b33c4f4084d9abaf6da7bf8311d6a0064e7e34b0f0b96830256ef0fc38f39c21430239d4cf8b0c917b400e72a18cd7a06d086b7fa75d0cad9efd27ac9a3944aefd2c1f997e92fac32f94040703f069a0a0db3cd09240bb0f959d5f9c9dc48f342758102072713dc1c4052f068fc225cd71a0ec276a9736174634160ecdd2f375409c60d6375f3a8d71cc4f99e9c687a9d4e6a007d6554681c12d6ca2df8e11aad891c48f99e1500c5b6c5ab4a9fca9c44bfa94a0607c837c516ac7643e511df04d2d392d76470a2047b285361f3c6d2e166ac13fa006be20cd4bd95621b3baf1e0751efa14aa8aa595b98ee556ac53bd29c6d5f705a051bc9e10f8c20efa7c93012843f419e2e0577fe6451a57b4f2e97e72fc586436a077c6b47181a1d6bf9318e040efb603a0aa33aee3e06528765a09cdd3855ca30480', + '0xf90211a0cb01852abc210b719e2010737d10f4267c0aa41ec3dc1bd23946bb1f5d5f55eba02d186391ef2f20d3139193b56f6a5912f339946265ff835b218f95dddb7561eda0b4a4d53cafd0a612bb8985fbd78d131709d21a39cd8dffa478569c4416a44908a04d9c04ff5524819d7cb473488c844cfca03c2fa3d8963fe4489c7f1f5b3c26c7a0cfc67897e95b551699e355b321cb87c6ecf1b961da4b4d3e2c37e189277de70ba0478715079310dcc2c96536931907dcb4bc7355f79e37b84dbf15b176ee0ea683a026949bd95978dc745b57ae542ebf05f5b8f4dc6cdadc99ec127ffe663696ad61a060cda170c099dd0e81e3b2db9b34069b4091597568dba78e852a110c5071db85a03070caf7f9c89860d001ab1b2f3132fcd42513a40eed4b75a14bfeb9e56aec03a0d2847b541355660ea7d35794ff0ebe2628d17120b10e13e2372b01f348791f5aa030ad063d59eec69a4e8f4fe74c5cbed7cafd730300ae29a44c2685c2c433a035a0aef71ecaec6d4af168121a724679ada20bdbf5d672867ae1c5ee1c68f235176fa08ed84bdf9cd18ba3362710a237e0ea9ddc032b06a56bc3b8f993600b48c2031ea042633256b93c976d7571f3a1f6d93f0c33f1c6f0af7a5eccb312ea991a85a248a0c4701a37bdcd334c54066c25dedaa97e01756620184ba200d50d5caef3bc9097a01a9861b44b0a2644485897693b39ce710d320aaf255fe6fb7a64365d36559edc80', + '0xf90211a062d84de21ebb8c7cbd8b3faa0a7d6d19756e747fe26df8293b969f1e35e337daa017bc34752d04526818d8840628a36af475a7648d3313a345450328eb836ff909a0d59cb165a1f61a2a8ad8fe7a32307432958ec4078fec5897c47cffa29a024b55a0ebde649d40670d42c046c2b042aef3261eb476a4642efc5711542befd6377f12a0cd605d8a40f14b10c860fe4353c4d5a8117482912cd983e463f2e9bb26f05e80a00cab56a990f258ce577eb26ae139cea6b3e166982f7e13294de11535d2114d0ba0e73701842791f8348c4783246f580657c170e19b329de8d9404a29bec9045002a09a50bda330a4d1ad53e18f2ef07d5cf62a68849de494638eec98348ca23b5f08a062934219e1f1a702815cd14afe306814526255dbb3debdf6a809e4b54afdf893a0a148fb69fd472ea2e782043711dcf16a2081ab9b095c9b03f2456e78e7d11723a025d0e469e02a86197ec5440323863585e2057eed630eb4ac79c61fe3d4b4ec40a034e73ea6200e02b804b14fdf69ff3bffc0e0119b49d68c6c91cf7adc273fe884a0a078dbec871434a6feb1ec2b2119307de22753d1537ef1973c525bc2b687603fa0461b806cca71045384b49382b6fb3e7f09261a5617155574d0e66666f69f5cb7a0091a4bf529a06b252961f45a38a9ef72ceeccd9e142d6cbb4d127c3a83e20857a0a3417d518bc88b9d83ff479f7f4244fa15be4909509c3ec804ec31aebd83818780', + '0xf9013180a03464dee21bd9b7f1712c25a7bf48517d93f6cd02bc5e069e85ca98eef103792ba0deca4fbc53762b7160e0e09cb594600b2c54f381f5d14a9454af44ffed380470a0ac233ce7e7018541d154a3abf88a2d3d564777b116c94fec994ce36d0ae1582ba0fd874c87366c0aaaf7fccf6065684b0745c3dcb1632d64ebb023cfe15512924e808080a07c8955af929f885d3c7a852723690ee3b39fc4f823f3a34d0de5fc850359a24180a040c3c8f7a9522d6df5c0028d90d360f73c5169b4cf434d95350beed43e167390a0f12d474b6d497c70999cd1079ec143f90a90c2efcb053202fa48513af9c75966a0a856e72e69c2131a5d4e0ac7b583725e9a400db1263a6f0b13fd298c5df84327a0a36c3da8cac00e01f7732dd98e7f7bc6a96e256ee48aa5776d144838dad268da808080', + '0xf85180808080a06cb96634150a4bf19ad1cd1d29ead274d327b6c478fe4624570e3b7f848fea318080a03281c0c672313b034e911b3667f54de0377a60c5289f2809b0bb8e827d4bfd96808080808080808080', + '0xf8709d20ae81a58eb98d9c78de4a1fd7fd9535fc953ed2be602daaa41767312ab850f84e808a02d5bd2d1efeb58aceada056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470', ], - balance: BigInt('11551700520686660602427'), + balance: BigInt('0x2d5bd2d1efeb58acead'), codeHash: '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470', - nonce: BigInt(0), + nonce: BigInt('0x0'), storageHash: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421', storageProof: [], }; @@ -277,24 +303,56 @@ export const mainnetCode = '0x606060405260043610610196576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde031461019b5780630753c30c14610229578063095ea7b3146102625780630e136b19146102a45780630ecb93c0146102d157806318160ddd1461030a57806323b872dd1461033357806326976e3f1461039457806327e235e3146103e9578063313ce56714610436578063353907141461045f5780633eaaf86b146104885780633f4ba83a146104b157806359bf1abe146104c65780635c658165146105175780635c975abb1461058357806370a08231146105b05780638456cb59146105fd578063893d20e8146106125780638da5cb5b1461066757806395d89b41146106bc578063a9059cbb1461074a578063c0324c771461078c578063cc872b66146107b8578063db006a75146107db578063dd62ed3e146107fe578063dd644f721461086a578063e47d606014610893578063e4997dc5146108e4578063e5b5019a1461091d578063f2fde38b14610946578063f3bdc2281461097f575b600080fd5b34156101a657600080fd5b6101ae6109b8565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101ee5780820151818401526020810190506101d3565b50505050905090810190601f16801561021b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561023457600080fd5b610260600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610a56565b005b341561026d57600080fd5b6102a2600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610b73565b005b34156102af57600080fd5b6102b7610cc1565b604051808215151515815260200191505060405180910390f35b34156102dc57600080fd5b610308600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610cd4565b005b341561031557600080fd5b61031d610ded565b6040518082815260200191505060405180910390f35b341561033e57600080fd5b610392600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610ebd565b005b341561039f57600080fd5b6103a761109d565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156103f457600080fd5b610420600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506110c3565b6040518082815260200191505060405180910390f35b341561044157600080fd5b6104496110db565b6040518082815260200191505060405180910390f35b341561046a57600080fd5b6104726110e1565b6040518082815260200191505060405180910390f35b341561049357600080fd5b61049b6110e7565b6040518082815260200191505060405180910390f35b34156104bc57600080fd5b6104c46110ed565b005b34156104d157600080fd5b6104fd600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506111ab565b604051808215151515815260200191505060405180910390f35b341561052257600080fd5b61056d600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611201565b6040518082815260200191505060405180910390f35b341561058e57600080fd5b610596611226565b604051808215151515815260200191505060405180910390f35b34156105bb57600080fd5b6105e7600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611239565b6040518082815260200191505060405180910390f35b341561060857600080fd5b610610611348565b005b341561061d57600080fd5b610625611408565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561067257600080fd5b61067a611431565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156106c757600080fd5b6106cf611456565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561070f5780820151818401526020810190506106f4565b50505050905090810190601f16801561073c5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561075557600080fd5b61078a600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506114f4565b005b341561079757600080fd5b6107b6600480803590602001909190803590602001909190505061169e565b005b34156107c357600080fd5b6107d96004808035906020019091905050611783565b005b34156107e657600080fd5b6107fc600480803590602001909190505061197a565b005b341561080957600080fd5b610854600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611b0d565b6040518082815260200191505060405180910390f35b341561087557600080fd5b61087d611c52565b6040518082815260200191505060405180910390f35b341561089e57600080fd5b6108ca600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611c58565b604051808215151515815260200191505060405180910390f35b34156108ef57600080fd5b61091b600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611c78565b005b341561092857600080fd5b610930611d91565b6040518082815260200191505060405180910390f35b341561095157600080fd5b61097d600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611db5565b005b341561098a57600080fd5b6109b6600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611e8a565b005b60078054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610a4e5780601f10610a2357610100808354040283529160200191610a4e565b820191906000526020600020905b815481529060010190602001808311610a3157829003601f168201915b505050505081565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610ab157600080fd5b6001600a60146101000a81548160ff02191690831515021790555080600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fcc358699805e9a8b7f77b522628c7cb9abd07d9efb86b6fb616af1609036a99e81604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b604060048101600036905010151515610b8b57600080fd5b600a60149054906101000a900460ff1615610cb157600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663aee92d333385856040518463ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050600060405180830381600087803b1515610c9857600080fd5b6102c65a03f11515610ca957600080fd5b505050610cbc565b610cbb838361200e565b5b505050565b600a60149054906101000a900460ff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610d2f57600080fd5b6001600660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507f42e160154868087d6bfdc0ca23d96a1c1cfa32f1b72ba9ba27b69b98a0d819dc81604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b6000600a60149054906101000a900460ff1615610eb457600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166318160ddd6000604051602001526040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b1515610e9257600080fd5b6102c65a03f11515610ea357600080fd5b505050604051805190509050610eba565b60015490505b90565b600060149054906101000a900460ff16151515610ed957600080fd5b600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151515610f3257600080fd5b600a60149054906101000a900460ff161561108c57600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638b477adb338585856040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001945050505050600060405180830381600087803b151561107357600080fd5b6102c65a03f1151561108457600080fd5b505050611098565b6110978383836121ab565b5b505050565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60026020528060005260406000206000915090505481565b60095481565b60045481565b60015481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561114857600080fd5b600060149054906101000a900460ff16151561116357600080fd5b60008060146101000a81548160ff0219169083151502179055507f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b3360405160405180910390a1565b6000600660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b6005602052816000526040600020602052806000526040600020600091509150505481565b600060149054906101000a900460ff1681565b6000600a60149054906101000a900460ff161561133757600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231836000604051602001526040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b151561131557600080fd5b6102c65a03f1151561132657600080fd5b505050604051805190509050611343565b61134082612652565b90505b919050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156113a357600080fd5b600060149054906101000a900460ff161515156113bf57600080fd5b6001600060146101000a81548160ff0219169083151502179055507f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff62560405160405180910390a1565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156114ec5780601f106114c1576101008083540402835291602001916114ec565b820191906000526020600020905b8154815290600101906020018083116114cf57829003601f168201915b505050505081565b600060149054906101000a900460ff1615151561151057600080fd5b600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615151561156957600080fd5b600a60149054906101000a900460ff161561168f57600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636e18980a3384846040518463ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050600060405180830381600087803b151561167657600080fd5b6102c65a03f1151561168757600080fd5b50505061169a565b611699828261269b565b5b5050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156116f957600080fd5b60148210151561170857600080fd5b60328110151561171757600080fd5b81600381905550611736600954600a0a82612a0390919063ffffffff16565b6004819055507fb044a1e409eac5c48e5af22d4af52670dd1a99059537a78b31b48c6500a6354e600354600454604051808381526020018281526020019250505060405180910390a15050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156117de57600080fd5b60015481600154011115156117f257600080fd5b600260008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205481600260008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054011115156118c257600080fd5b80600260008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550806001600082825401925050819055507fcb8241adb0c3fdb35b70c24ce35c5eb0c17af7431c99f827d44a445ca624176a816040518082815260200191505060405180910390a150565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156119d557600080fd5b80600154101515156119e657600080fd5b80600260008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515611a5557600080fd5b8060016000828254039250508190555080600260008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055507f702d5967f45f6513a38ffc42d6ba9bf230bd40e8f53b16363c7eb4fd2deb9a44816040518082815260200191505060405180910390a150565b6000600a60149054906101000a900460ff1615611c3f57600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e84846000604051602001526040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200192505050602060405180830381600087803b1515611c1d57600080fd5b6102c65a03f11515611c2e57600080fd5b505050604051805190509050611c4c565b611c498383612a3e565b90505b92915050565b60035481565b60066020528060005260406000206000915054906101000a900460ff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515611cd357600080fd5b6000600660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fd7e9ec6e6ecd65492dce6bf513cd6867560d49544421d0783ddf06e76c24470c81604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515611e1057600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141515611e8757806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b50565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515611ee757600080fd5b600660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515611f3f57600080fd5b611f4882611239565b90506000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550806001600082825403925050819055507f61e6e66b0d6339b2980aecc6ccc0039736791f0ccde9ed512e789a7fbdd698c68282604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a15050565b60406004810160003690501015151561202657600080fd5b600082141580156120b457506000600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414155b1515156120c057600080fd5b81600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a3505050565b60008060006060600481016000369050101515156121c857600080fd5b600560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054935061227061271061226260035488612a0390919063ffffffff16565b612ac590919063ffffffff16565b92506004548311156122825760045492505b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84101561233e576122bd8585612ae090919063ffffffff16565b600560008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b6123518386612ae090919063ffffffff16565b91506123a585600260008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612ae090919063ffffffff16565b600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061243a82600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612af990919063ffffffff16565b600260008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555060008311156125e4576124f983600260008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612af990919063ffffffff16565b600260008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a35b8573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a350505050505050565b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000806040600481016000369050101515156126b657600080fd5b6126df6127106126d160035487612a0390919063ffffffff16565b612ac590919063ffffffff16565b92506004548311156126f15760045492505b6127048385612ae090919063ffffffff16565b915061275884600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612ae090919063ffffffff16565b600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506127ed82600260008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612af990919063ffffffff16565b600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506000831115612997576128ac83600260008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612af990919063ffffffff16565b600260008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a35b8473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a35050505050565b6000806000841415612a185760009150612a37565b8284029050828482811515612a2957fe5b04141515612a3357fe5b8091505b5092915050565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b6000808284811515612ad357fe5b0490508091505092915050565b6000828211151515612aee57fe5b818303905092915050565b6000808284019050838110151515612b0d57fe5b80915050929150505600a165627a7a72305820645ee12d73db47fd78ba77fa1f824c3c8f9184061b3b10386beb4dc9236abb280029'; export const mainnetTransactionFromBlock = { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: BigInt(17029808), - chainId: BigInt(1), - from: '0x38abab9766e0b27d2912718a884292b8e7eb2803', - gas: BigInt(500000), - gasPrice: BigInt(44546465904), - hash: '0x603caf7d4be62e5946268fa1b594029c40fab23826d388729367c37649ea3967', - data: '0x3df021240000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000043c33c1937564800000000000000000000000000000000000000000000000000427a6327d90554fc361', - input: '0x3df021240000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000043c33c1937564800000000000000000000000000000000000000000000000000427a6327d90554fc361', - maxFeePerGas: BigInt(108571383800), - maxPriorityFeePerGas: BigInt(25415778028), - nonce: BigInt(6346), - r: '0x601ab6acc74820bf5d8d8675ed0828447937869c985ec46bf8010de898aabbcb', - s: '0x17da59e605337ada87592aac2952cbf731575a8eb0fe4bdefd4fa8ce35260bde', - to: '0x3f1b0278a9ee595635b61817630cc19de792f506', - transactionIndex: BigInt(1), - type: BigInt(2), - v: BigInt(0), - value: BigInt(0), + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: BigInt('0x13e6595'), + from: '0x4ac6268385851b23ebe22f91630d7d0f61e7b74d', + gas: BigInt('0xc351b'), + gasPrice: BigInt('0x5c7a12944'), + maxFeePerGas: BigInt('0x649530233'), + maxPriorityFeePerGas: BigInt('0x3e7475b21'), + hash: '0xdcc36c7c0f1ec3ed4a2290819adde014f1866bba041244297d4dd26b8ad7a677', + input: '0x2a0aad11000000000000000000000000d43b29aaf8ad938cff4f478a0756defffb329d0700000000000000000000000000000000000000000000000001401ca3de486ee000000000000000000000000000000000000000000050b005b7c2ad880000000000000000000000000000000000000000000000000051432ec4166364000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c750359cba44ad5214f0ccd99900b99099dc92f1', + nonce: BigInt('0x1f39'), + to: '0x7176f0f071379fee51668eb6387dda9129e5ca6b', + transactionIndex: BigInt('0x1'), + value: BigInt('0x0'), + type: BigInt('0x2'), + accessList: [ + { + address: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', + storageKeys: [ + '0x246b6fbb62dd356a54402357031cbb467f367a61b7888c050cb6c7bb3ab09af5', + '0x0e172d98b879678a3ee0f92abe00ac1abb5704e2202ab541abde74b1c29fa6f2', + ], + }, + { + address: '0x7176f0f071379fee51668eb6387dda9129e5ca6b', + storageKeys: ['0x1eacdd914ccc11e96dc3a80463b6f0fc6803a1c34c181447e291c8a617ab02e9'], + }, + { + address: '0xd43b29aaf8ad938cff4f478a0756defffb329d07', + storageKeys: [ + '0x0000000000000000000000000000000000000000000000000000000000000000', + '0x0000000000000000000000000000000000000000000000000000000000000004', + '0x0000000000000000000000000000000000000000000000000000000000000002', + '0x09d630f44b7f555eed07fae2912a5dc3cb8482d08fd0bb5516ec577adbc2708d', + '0x000000000000000000000000000000000000000000000000000000000000000b', + '0x000000000000000000000000000000000000000000000000000000000000000c', + ], + }, + { + address: '0x662b67d00a13faf93254714dd601f5ed49ef2f51', + storageKeys: [ + '0xdbc70cebf038526dc74f312a95b8b2bbe9b31bad7ab204377adc12f259b8ecb4', + '0x1cdb6b5e8ca27cc663a219e40c950ba60826d12d2811ff4e5355f51c833974e7', + '0x8f1ae5d9fa039fb04c99033e2c69ddd4cb30f8b7c00cfc9111e11d7250eb29ad', + '0x7ff2e0ef776e42618d5979459155347a3f53c31df06de580f2f8a6b029de6859', + ], + }, + ], + chainId: BigInt('0x1'), + v: BigInt('0x0'), + r: '0x86c5a957bb87e42a131c60293f7b4dbe465ffd2ef982893bdd8e167719de423f', + s: '0x6d34667725848de46dcb357d098266662e5e48383baafbb2c6f9b52e9f2c3908', + data: '0x2a0aad11000000000000000000000000d43b29aaf8ad938cff4f478a0756defffb329d0700000000000000000000000000000000000000000000000001401ca3de486ee000000000000000000000000000000000000000000050b005b7c2ad880000000000000000000000000000000000000000000000000051432ec4166364000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c750359cba44ad5214f0ccd99900b99099dc92f1', }; diff --git a/packages/web3/test/e2e/fixtures/mainnet_block_hydrated.ts b/packages/web3/test/e2e/fixtures/mainnet_block_hydrated.ts index a736f79412c..02240cf5b59 100644 --- a/packages/web3/test/e2e/fixtures/mainnet_block_hydrated.ts +++ b/packages/web3/test/e2e/fixtures/mainnet_block_hydrated.ts @@ -15,4099 +15,2872 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ export const mainnetBlockHydrated = { - baseFeePerGas: '0x474472184', + baseFeePerGas: '0x1e059ce23', + blobGasUsed: '0x0', difficulty: '0x0', - extraData: '0xd883010b05846765746888676f312e32302e32856c696e7578', + excessBlobGas: '0x0', + extraData: '0x6265617665726275696c642e6f7267', gasLimit: '0x1c9c380', - gasUsed: '0x143f430', - hash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', + gasUsed: '0xc191f6', + hash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', logsBloom: - '0x4df74c536feb5b9b15f957639771c6a373e719164f8593a74f9bbea57eaafd57bc3713cc5f12770cff1397fa4347c99e0f7d1e2edb5aedd4bf21d5e21ea43963fd767ad75fefcb3dffefe37b5d3a0879e29b14a80deefa730dd29ccd9e7134833aa03fb27b97d98982427405ac0abedd425a3bd70b7d5ff34f5d2cda3e7fd29fcf23d71d0a4c370005d82dfe53be067656d2bce157469cf97ff5ab7ce330166f9ed87d5717a46a3b603affe5b13cedca2b5a46bdeab6abab0dd72c3f14e2fdda4e38bd6e5e0b3e5bc04edb366cef95faf8f96edba7fb645a770e3daeca8de47f54736b5881078d85882d16ada151ea84e6779b30cb7ca4d68f8dbf31f296fc87', - miner: '0x4675c7e5baafbffbca748158becba61ef3b0a263', - mixHash: '0x4ec3b909884d099f633243913328e65d659c646e349c14ced389280fefab41c3', + '0x8b2340222300318705080cd0fcf01103390180800e211050189f44e117b398ea22c33464eafd46900e413aba8f0fdb848a3bc6e0b802f6b409d22ec1122b5693053c810e5640bb6d68a5763aa06040fc842716b349f64c03e02210049b2c0ae13f00621297f409390d7e4c94109d6f5637224d2b03c697245a000d95184d1c48b4644271145760e1aa6db0c80b360847012926836334894ed41926534d92080c8fbf0f9433ba33902e54d0ee49d2bd6c84e5a5f23740604507622520a40a537d479b329a90902b706280c420227f18d613132e0687233cf705047022f272e11635516ac188308f29c3c631b6c64508c78a09762c9c1873d989faa0bc7c74346b', + miner: '0x95222290dd7278aa3ddd389cc1e1d165cc4bafe5', + mixHash: '0xca757a869b451781a0bfd1253e74e20bc6d41013cf53335c1713d754f81588fb', nonce: '0x0', - number: '0x103dab0', - parentHash: '0x28ad78b5598691f1eb3aee2a17540496b539fb4f72ca5eaa461a331791cfc7cd', - receiptsRoot: '0x78017242efd230482ca0a6ca47a5c3bed5a275b6e3b09223ff8e2354f3136772', + number: '0x13e6595', + parentBeaconBlockRoot: '0x377d6a6271304c814d336cb087cc30ca17bbf1e07dece5ea33d6327cce88566f', + parentHash: '0xa29691d149e15630b582c27cc4fe900359536d6c872fc57578167b0c694fd1dc', + receiptsRoot: '0xb3426824a79dc6d684d3a7a17350475eec7103499fa1e4298bdba5e57dc4d1b0', sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347', - size: '0x493d0', - stateRoot: '0x637b62addfc277cb5ae4aac3c8b3bfc8e49ebe9369d07d9757c5f1f2ec937306', - timestamp: '0x64363eef', + size: '0x1011d', + stateRoot: '0x977fa00c772e3127c0c47bfe9226222adbc186d5199a67e21f77f6c34ee62a5c', + timestamp: '0x66fb25a7', totalDifficulty: '0xc70d815d562d3cfa955', transactions: [ { - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x0df433e890793b488c13d18f5d113cf194ddf7ec', - gas: '0xfde8', - gasPrice: '0xd8111c400', - hash: '0xfe87d41469efbea299780c8e218590753e0893ee2d2d65f867d9c9c7b9ed591f', - input: '0xa9059cbb000000000000000000000000913cec99a2afb5ec7008831998bf4eebf1ddb830000000000000000000000000000000000000000000000a39bd57ecedc547b000', - nonce: '0xf8', - r: '0xf511d0f14c7ad3fbd118136e006dd7327ffd0614cb415e41bf2dddea1c733251', - s: '0x1174d5a1e42be8c4ca43acbad607a33d4fa39dca036dd7c7a981f3fceb465c77', - to: '0xd04e772bc0d591fbd288f2e2a86afa3d3cb647f8', - transactionIndex: '0x0', - type: '0x0', - v: '0x25', - value: '0x0', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x38abab9766e0b27d2912718a884292b8e7eb2803', - gas: '0x7a120', - gasPrice: '0xa5f2d2070', - hash: '0x603caf7d4be62e5946268fa1b594029c40fab23826d388729367c37649ea3967', - input: '0x3df021240000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000043c33c1937564800000000000000000000000000000000000000000000000000427a6327d90554fc361', - maxFeePerGas: '0x19475bd7f8', - maxPriorityFeePerGas: '0x5eae5feec', - nonce: '0x18ca', - r: '0x601ab6acc74820bf5d8d8675ed0828447937869c985ec46bf8010de898aabbcb', - s: '0x17da59e605337ada87592aac2952cbf731575a8eb0fe4bdefd4fa8ce35260bde', - to: '0x3f1b0278a9ee595635b61817630cc19de792f506', - transactionIndex: '0x1', - type: '0x2', - v: '0x0', - value: '0x0', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0xa0bc68a45bca874f2a7195fd0e946041ccd2ba92', - gas: '0xd6d8', - gasPrice: '0x8aeec0f9c', - hash: '0x4f8da807b7f0f44a4fd67eaa16cc4ef6f1071a0d8ae06349bef904f8f14f0903', - input: '0xa9059cbb0000000000000000000000000fd5b4633eda5b1daaa6a2cd6b852167318aad990000000000000000000000000000000000000000000000000000012687e02a00', - maxFeePerGas: '0x8aeec0f9c', - maxPriorityFeePerGas: '0x8aeec0f9c', - nonce: '0x2a', - r: '0x66d297d50616d83c4f46b2ecb07bfe58785ddc1f412565c1fa19175841f314e3', - s: '0x42d0bbf71e2de38a839d0016c5e2fd9a387621c8fd511d83f554aef09c94a3af', - to: '0x15d4c048f83bd7e37d49ea4c83a07267ec4203da', - transactionIndex: '0x2', - type: '0x2', - v: '0x1', - value: '0x0', - }, - { - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0xae45a8240147e6179ec7c9f92c5a18f9a97b3fca', - gas: '0x5208', - gasPrice: '0x70cfb96cf', - hash: '0x199eb2a37faf1af74c752de5f378859c40a8929c52af1402bf98c9acc309438e', - input: '0x', - nonce: '0x1e5511', - r: '0x209ef9dbdeaf6807ab08d3191c00af17727ea4ae22ed8fc127a55cfb287b0672', - s: '0x51551c439baf3cab9a8b93cd1502e3a40a9b4cdef927fbd274d40d0dfcdc9329', - to: '0x7a408b5230d123574eb8c057904e4f364b980770', - transactionIndex: '0x3', - type: '0x0', - v: '0x25', - value: '0x5a119fe21ed87', - }, - { - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0xae45a8240147e6179ec7c9f92c5a18f9a97b3fca', - gas: '0x5208', - gasPrice: '0x70cfb96cf', - hash: '0x9775612f318528221f773a926a72c758f5b6d1eb7871b7a4309fe2d870ea1452', - input: '0x', - nonce: '0x1e5512', - r: '0x4f68a9a02c74f6ac4059d3dda87db886050847822b1a3fde4fcde65c175a8f38', - s: '0x3ce0ec0d5a776d84f835a6eed0f2cdf59356ffe6d014af9b283ac84e2c5ad362', - to: '0x40fc4596608b20c97244922060dcfd2de7fdf9ea', - transactionIndex: '0x4', - type: '0x0', - v: '0x26', - value: '0x8f90791f1038e', - }, - { - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0xae45a8240147e6179ec7c9f92c5a18f9a97b3fca', - gas: '0x5208', - gasPrice: '0x70cfb96cf', - hash: '0xdc7f7a7c4d7017c13c795fc303c5b24814e27f102f908bcb33b8f5b7e943a8e4', - input: '0x', - nonce: '0x1e5513', - r: '0x644543ff07aa6aa3197b93f8a6f333860c1f6a51889113c9b984c4cfe53ddd84', - s: '0x6cb061b61f1bb84e5435927a904884b0196b43c93a872822e1abd35caf38ec1a', - to: '0x0d2895a34520624ad6171476d62837b5e285d8f1', - transactionIndex: '0x5', - type: '0x0', - v: '0x25', - value: '0x9451e0bec42d1', - }, - { - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x37b94141bca7000241b87b4b361f155197181002', - gas: '0x1fbd0', - gasPrice: '0x6fc23ac00', - hash: '0x19d1a0d3ec5c0edb9f5e92fb5f8707ae92b56505093e602bea42be92a07e44af', - input: '0x23b872dd000000000000000000000000381e840f4ebe33d0153e9a312105554594a98c420000000000000000000000002d68d9aa1ff311406593887999d14db57aaf14ba000000000000000000000000000000000000000000000000000000bdc1c91600', - nonce: '0x2e3e5', - r: '0x4b06ba58fc3f9dc92be0055c55cddad9205e16c7d29bb6dede6787559e858b2e', - s: '0x2b4b4f8ad723577860d89b6311573260e450a74461b1324b727097cb1ea3f0f6', - to: '0x15d4c048f83bd7e37d49ea4c83a07267ec4203da', - transactionIndex: '0x6', - type: '0x0', - v: '0x26', - value: '0x0', - }, - { - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0xc6e282c9f4981b2036da4ca3f4fef3d68e66f75a', - gas: '0x249f0', - gasPrice: '0x6fc23ac00', - hash: '0x9c3c1a113ed268ea222e7d9c35ce0abf5bd15f7f7dd4c00b31fd4de1a9cb57dd', - input: '0xa9059cbb00000000000000000000000067de33ebc8252df671330939ee02d70d27df265a00000000000000000000000000000000000000000000000347e512f272760000', - nonce: '0x2cb4', - r: '0xfeced6d2b4be2108e88d961423c3ddbade22425464538f63c047829bf1d8c2a5', - s: '0x7ee24854c7c79582649d25c66bc1b462c57ecb73925d94881b081577ffa04920', - to: '0x795dbf627484f8248d3d6c09c309825c1563e873', - transactionIndex: '0x7', - type: '0x0', - v: '0x25', - value: '0x0', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0xb01cb49fe0d6d6e47edf3a072d15dfe73155331c', - gas: '0x15f90', - gasPrice: '0x5d9e7dd84', - hash: '0x2ad8b77960551ee3fa86b1ede54219db9490e5320bb479a467be1563f49070fa', - input: '0x', - maxFeePerGas: '0x45d964b800', - maxPriorityFeePerGas: '0x165a0bc00', - nonce: '0xa669f', - r: '0xa89f7f812e3b621a89a218f2c22da423d87dc0c2eac90505799a1b63fcea6337', - s: '0x449f43dfc141d298f61728c3f160c536ef741d4295453fc19fb22588faca1965', - to: '0x5ebe4a90a99d8d02204552079572ff962ce554ba', - transactionIndex: '0x8', - type: '0x2', - v: '0x0', - value: '0x6a94d74f430000', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x62ebc97e159e60915948a4f226f18d7460f9a80b', - gas: '0xaafbc', - gasPrice: '0x5d21dba00', - hash: '0xee84b1ac8feb236190b84717a4d186b92278939d36346c81a0ee35c316763900', - input: '0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000643645df00000000000000000000000000000000000000000000000000000000000000030b090c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000214e88de46721510000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000004351bb9127d783b9a00000000000000000000000000000000000000000000000000000214e88de467215100000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000bfbcd9b16d0a55e8b0070551271180e0b7b8388e000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x5d21dba00', - maxPriorityFeePerGas: '0x1836e2100', - nonce: '0x389', - r: '0x201f89c979366c6789dc138b8d36047fc0ebd78956ddd1fcff547d982ce74af8', - s: '0x4b469d49d4dcdb1f8f91c8f75713a77851c020d7d19e6e9a9859896a277ffb23', - to: '0xef1c6e67703c7bd7107eed8303fbe6ec2554bf6b', - transactionIndex: '0x9', - type: '0x2', - v: '0x0', - value: '0x214e88de4672151', - }, - { - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x5436aa53d2b25190d2e54c4dd9117a14eb1d3d6f', - gas: '0x5208', - gasPrice: '0x5c8ad1ad2', - hash: '0x1789d5fc0756c57f5035cf7e0776c908d20350a2474b6a24f06d0c0f5aec9671', - input: '0x', - nonce: '0x1', - r: '0xc2886750f2308b50265de5c28daf2d7d05087103d8879a63064e454031fa7f9a', - s: '0x3026bc52e581f4ba9233eaca623d7ab55463466fa5cfcab568e6e86b153c0b72', - to: '0xa28c1a1330d7634c9bc5a04cb2a3b64cb866f19e', - transactionIndex: '0xa', - type: '0x0', - v: '0x25', - value: '0xfd9728a9242400', - }, - { - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x3e9df16ac4dd2738c9ffa5eb2981cefd04d8cea3', - gas: '0x5208', - gasPrice: '0x5b6b2af00', - hash: '0xc6b456b175dd46508260658d2730e30f92a79ffc5be7310098a45dd70e4292fa', - input: '0x', - nonce: '0x0', - r: '0x965cd3cc650e1592528d8acdf957f1c588c327513a1ae1380c996d3e129099c7', - s: '0x263967109771cb590a72b9383d8822183b452114e8fee7800184857b15b979b0', - to: '0x6dfc34609a05bc22319fa4cce1d1e2929548c0d7', - transactionIndex: '0xb', - type: '0x0', - v: '0x25', - value: '0x5d2c45892ec400', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x112200eaa6d57120c86b8b51a8b6049d56b82211', - gas: '0x7a1200', - gasPrice: '0x59e4d1384', - hash: '0x94e1c3b9a52d7a5e1c6c79dff79ef48d6b9e66aebebbc416a70f006c4382fb23', - input: '0x0c4dd810000000000000000000000000000000000000000000000000000000000000383b0c799eec0c8269e6f66433183bf6c37f7e2234fad4e8619a9372c537e1919cc9000000000000000000000000000000000000000000000000000000000082663d00000000000000000000000000000000000000000000000000000000000000109d7468151d8ce8d8cebd40a39adfd37c97df96ccd5be350407ebe07aafe0ed07be59bbd66be38ea02192e92e3620ac73fe74a4ba782333f6912a6cfc2720480e0000000000000000000000000000000000000000000000000000000064363da0536f4cde074ebf59770fcd0c104be5abf522c7b45d6304fb78b204926cf10301000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000383c0000000000000000000000000000000000000000000000000000000064363dfb000000000000000000000000000000000000000000000000000000000082689a86740d370d5ddebe0d02c0213b810e4c7743c3f93d5374c8cdf053a9d428e991000000000000000000000000000000000000000000000000000000000000001b819ce85261f50be1de19276f26e5ca11a848228ee6210c25cb59dc36f351dc360ff93be68c9ff97a26ef6bec24bd43f19b98490ef6e53e3d25a9b095e0cac0e80000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000990000000000000000000000000000000000000000000000000000000000000157e000000000000000000000000000000000000000000000000000000000000162c0000000000000000000000000000000000000000000000000000000000001648000000000000000000000000000000000000000000000000000000000000097440000025d60c4d13fd5e61e8002cedae0b934a332f744aabb60ab2c4045c0bbdb0579e8ee00000000000000000000000000000000000000000000000000000000000000018abc516ed905f4cd2f75e529e5e37e29e9289343fde880ae66b24b0f565853ae0000000000000000000000000000000000000000000000000000000000000001be76ea648005e24e93088e8d659cbbeb2b35d2faab5c9ca93a19244a6be3d12c0000000000000000000000000000000000000000000000000000000000000006ca2b2246ce791549583c2223e325fc09370d1bc3ab8a7fb90fe95d7f84c18b9b0000000000000000000000000000000000000000000000000000000000000001032fcb196b9985790ce5d010f9ad1d3ed1098603297a45bebb94a4243d5bf81c0000000000000000000000000000000000000000000000000000000000000004b4e0299791aa0f9f1b27a66dfbb346e10181ff7bc2f1e0dd3ce1533b205ce30c000000000000000000000000000000000000000000000000000000000000000111a306f44c250416ee4e6f836b7e8f4f39d68850b32043fdffedfd02b6cfa9540000000000000000000000000000000000000000000000000000000000000001802346705a406cfd46fb98940d21d0a55708d1d2a2bacfc1e51563885e440fe40000000000000000000000000000000000000000000000000000000000000001d747b73d89ce8e9562906c6ceaaef75e663cf4bb9417e2020dcc7e61fb70649b0000000000000000000000000000000000000000000000000000000000000001dd249cc6e1d54c058fa10b0a8eb3efa2abe97e7337383a9c063ad713d9ba13f00000000000000000000000000000000000000000000000000000000000000003501c8b17b08592ef77746faf27ce73e4bda08f1cd34258cc84a898975ecfe2f800000000000000000000000000000000000000000000000000000000000000019b32991c1904bd3fec1e827fa2cbd2cf95fb60a1933575375ac662d94f531f340000000000000000000000000000000000000000000000000000000000000001fd354efb5ae3a973112f4661c3a0738be9828c7c3b38cca9c4347542417d7956000000000000000000000000000000000000000000000000000000000000000221ebcda1219518a7ef173346adb7085d22d5ceac869e3c2dbebdfa98f33c49380000000000000000000000000000000000000000000000000000000000000001efb54ced7b1332e89eb3f543d10d5cc7ea920b27a5bbde793f94bafedb2df9a0000000000000000000000000000000000000000000000000000000000000000152c0c38ce38aaa444503c1176163a7ddbb34adee20f1718a5a2fc72df56113990000000000000000000000000000000000000000000000000000000000000001000bbd8d1d92156fbe8958c81e7c544053675cc73392204f998dd02f66b31d190000000000000000000000000000000000000000000000000000000000000001060d5ef2d198303e44fd97bc33f038852fc53780d9a8221a556b1c671d358b6a0000000000000000000000000000000000000000000000000000000000000003e567182bc48dcef99fccb7044d5c2451e32fe8461b2f26c00b5674600078415a0000000000000000000000000000000000000000000000000000000000000001d02b2774b947ffd572c255da723d08b2660838e8173d7c7938f1431660bd40cd000000000000000000000000000000000000000000000000000000000000000186735298a63049fd790ee7ea2b312fcbf59889e147153b445061c59cb58449120000000000000000000000000000000000000000000000000021706fde04f800a73475f474aad72020b5b750b134f58cdd13ac9b0f7fc04aa155776a7ffeba3e000000000000000000000000000000000000000000000000008ebf301b8c84765c79d51c54d3539ff139330c3148948e11bc6d228b1b08d6c0be0dc4ed935d5e000000000000000000000000000000000000000000000000044e090e4db9661ad939b110fec3b904a308b2ff6ee56654fc8209f989724e63bcfe853fb2d56ebd00000000000000000000000000000000000000000000000000217112d94550001fefaa527022cff5885aab179784ea4aac29fe488d8f67bff3460e946c213567000000000000000000000000000000000000000000000000004981720467200002acd1eeb97c30be87feeda1372ee36d83b85c3ce931afd2e27b5057f16393120000000000000000000000000000000000000000000000000040543876f2b00996a26f6ed760f665efa6f5d10ba47673e2c525c376f226865884b6b727c1103a00000000000000000000000000000000000000000000000000b9798958eb98c635f474747e31bf6372044cd1a296a239774d49934f0b0a8bf2f8747180ab66c800000000000000000000000000000000000000000000000000b199a3e0526000d29bf2e0f2fb05525980d8d48972280bdee43e8f7211db5a6331539d704e0bc200000000000000000000000000000000000000000000000003aa35ab6a48e87afa349a81830c2f303df48abbb66a29c3c20320c464fc6b4ffb3cec7d91be44ef00000000000000000000000000000000000000000000000000bd3dbbe7c2cc90029b691b3026b8f65f1fcc7ac7d08039e9ed360ec4e6184f278ed85f8776564f0000000000000000000000000000000000000000000000000041d063ac76d00a3a75345e199693e329dc9df746ffa04cdbb5c2a4972ee2589074425573fee5c4000000000000000000000000000000000000000000000000009cacb762984000c09cd23372820611a27a87e215f18b5567f919b703d3a14c8c3bc09c5b9496f700000000000000000000000000000000000000000000000000d5cd14fb0e8476f2da5be34629960152c21b34dc2beb35f2f3f442a45d237c5371c4246d67b53b0000000000000000000000000000000000000000000000000047b5724d257f6c51c7064ba3282a34a19e8e0620eefcc6163b2d098fc1ce2ffcbf8d59c89de98800000000000000000000000000000000000000000000000009e1fa9df2addc61b17e807aa6a031d771c0be552a8855ae48e828a01873d31d122f80e38fb3870b000000000000000000000000000000000000000000000000003604a9a590669678dbd0ec8c7fb535f3a3005b303d04132b4103932f6b2ea8e42fb0c946ae3cff00000000000000000000000000000000000000000000000000242b05af6dc3ee73fe8cc3b3981107f063f10e0f429a6e0440148921a434550692b6e740704b89000000000000000000000000000000000000000000000000004ad2e2810e40b2e9c567c483bf77a57deaf9f0b8596671e446b11f8e101231d0314d51ff5a6695000000000000000000000000000000000000000000000000003983c4b860e177fb08d0b312a0de3f311b2d33d46cd48f25a9029c98cafdcb9c275b4a41eee30f00000000000000000000000000000000000000000000000001805f06c9388c5f9e90532d68eadc90dc2dc0c9bb3dc65b30ec673afa239b3c5f4e7c3245b83ae3000000000000000000000000000000000000000000000000004193740543a00803a706e02c4f6982f728dbbf9f06b3dd4315678f0765bda2034ac001e43714b900000000000000000000000000000000000000000000000001aaff37a904e1777d81a06e3d4f1145f08dcb7e2c5a1b0bc07c049b7ee4b294de50eacceaf20004000000000000000000000000000000000000000000000000005724fedbb2100837e2575fd4309d637bb9f7f8d68d3d6513a6c06ddca1acfa7142115e0f22ea230000000000000000000000000000000000000000000000000011ba60e96de274ded310bf19530f83dd14b4c9104b86d92905a23ad48781eb5555e92e36238a3d00000000000000000000000000000000000000000000000000adb21affb6b025122ce1fd6dafaace345a6e8e8053288852c2804d829fa0b2f53dacc822293a35000000000000000000000000000000000000000000000000010ce6b40483a177744adf0702b12168006ed31d0ae5059bad72c218445d69fb1cd849ffa9553e75000000000000000000000000000000000000000000000000002bd225d092ee3882b345b5454e16c7d778917c214cc21a704ad18effc433ab76b3742f818776180000000000000000000000000000000000000000000000000039fb34ea4e5ef6967d6923ed83e1edf338abc3db62ca170836b6805d034f1c8aa9be3f173759a8000000000000000000000000000000000000000000000000003ecf8ea01a447655553bd9d902714e1a6a68355ffd2a48c0f05bcff2d7275133ee53a68c11fb4100000000000000000000000000000000000000000000000000a2cc89b2f602c34a99726bc821373dca937c2e1e1a04e729e24cd6416ce1a6c7946659a08655a400000000000000000000000000000000000000000000000000b5ec0ab42518c6f4b90caed20cf03f677275ad7f39a49c3e2c4957e4877f6d6a35bb894987a5d60c799eec0c8269e6f66433183bf6c37f7e2234fad4e8619a9372c537e1919cc9ec74508765aee93de110aefc09270ee9fb53f1999f29fc5ebc24dd0ede2c3a7500000000000000000000000000000000000000000000000000000000000000016c621809c6ca711a4d6b302551121c359ff76f7c4d5a320a16f341b56c79669e0000000000000000000000000000000000000000000000000000000000000001d80cff06f9ec1f38bed97afc84f89bdef6d82be0392af92ea32ef38ffbe1182c0000000000000000000000000000000000000000000000000000000000000001e4a233e169bee20c990f4d9c9c7a6bbcb843eecbb9ccc98358c16bedcc8dd66a00000000000000000000000000000000000000000000000000000000000000010f8b24c7e20ebf5e83a1f1de070860220742571115555dc952e9c62b95781b20000000000000000000000000000000000000000000000000000000000000532521a74e15bd64217fff71d34ea4bce501c76025371d9658f1d91c94e18a437ebb0000000000000000000000000000000000c097ce7bc90715b34b9f10000000007d6f2a52f218804936029c26e0e001a02da3bdcfddf634a63fa219e0825e912d0000000000000000000000000000000000000000000000000000000000000002c1d6d9ea700c86529fc733cf35e6cfeb3f385a62ae5ba56c306e301e75b691fe0000000000000000000000000000000000000000000000000000000000005327a3547bcb69c7cdde770097cff6c3057413a48c8908bf09738429448e7335bd4b0000000000000000000000000000000000000000000000000000000000000001dd6fe47e73fdd91b61539ecc3a7d7c694b7a3cc037fec9454e23747d6fe5ffeb0000000000000000000000000000000000c097ce7bc90715b34b9f1000000000c04a7afdfef05f20990cb7f77bba23955f9cbfafb1c843dd21713c72b18ee6b600000000000000000000000000000000000000000000000000000000000053266f3af6c93ffe6f128ac3807149259a66e8c2e2ea135191d30f4e9eb3f89237580000000000000000000000000000000000c097ce7bc90715b34b9f1000000000c3fa4ce9f2ef06c073e4bcb5cad193a4a60ddcfcca818bf7602e556a08167fca0000000000000000000000001bbd33384869b30a323e15868ce46013c82b86fbe19a1805d2343e0bdf763c94738363a08b6226b211a527531a5afc61efdf47920000000000000000000000001181d7be04d80a8ae096641ee1a87f7d557c6aeb3073ca8c7b2d587def01896e8450fffe2ed9425db7d6feb6db29b22fb221bce20000000000000000000000000000000000c097ce7bc90715b34b9f10000000007f641b3caed3e1b14310e3906ded619543a8d5d8730acaa16379dff5e35f72730000000000000000000000000000000000000000000000000000000000000001a95d63f25941c77119899ad7caf9be8bb51766a4680dfe0a01367c3d3fd8ac780000000000000000000000000000000000000000000000000000000000000001d05b36c39d6b6639c18998a2c3520c301a8fd557cdc4c0a6c35a30a1bad40a4a00000000000000000000000000000000000000000000000000000000000000017dcafe000bcfe104b30ff5b7b1e64e1beda4639c4b7aa20cfcb6d8277b026b630000000000000000000000000000000000000000000000000000000000000001239b3f3a3532fd99cd898aecc9f2e864b06a0ad4c1cc5d8a577ab2050d96bbcf0000000000000000000000000000000000c097ce7bc90715b34b9f10000000002832f0b95cde62d42470c34e942dfbf7c0887f821b6c2c266e4c52597a486d0d0000000000000000000000000000000000c097ce7bc90715b34b9f100000000032ad0072320054479e49136cb6b90c3c4c5ccf28146486dbf2b08786224533a20000000000000000000000001181d7be04d80a8ae096641ee1a87f7d557c6aebd1b813f59e366147c60432977ecf25dea77ea7778fd50742abd1ed9f600121cc000000000000000000000000000000000000000000000000000000000000532375aecf25407ed718ee36486846ac75e4783d6b3694e2f46158317122c49d65fd0000000000000000000000000000000000c097ce7bc90715b34b9f10000000000895bf9e8adf5d538599804c19b4b119dd5fbcb901aa3c61ed5c6c315fba10c90000000000000000000000000000000000000000000000000000000000000001bf5c1efc0fa728c1b241e677e4f0113c57e97ab8c989251d107f31ed381c2cfb0000000000000000000000000000000000c097ce7bc90715b34b9f1000000000186ad8718a785ba5ffadc8b82e7b306ef412529a789bedde9a3af932d92959860000000000000000000000001bbd33384869b30a323e15868ce46013c82b86fbc11189fd192e49260d5a6a467e532ee12a352ce84da8d8b431bcbdd9bdbd831b0000000000000000000000000000000000c097ce7bc90715b34b9f100000000092a0c7ab913202406cb3535446b840c0abd5ebb7dac53b1ad7eb9c52a50905510000000000000000000000001bbd33384869b30a323e15868ce46013c82b86fb22d813e55679668e7dae5e0fb78ebab1ad7a0126f7d6708a661ce8a0c15b9f1c0000000000000000000000001181d7be04d80a8ae096641ee1a87f7d557c6aeb0c8d990122d0e605658ba102420eb2e7bca22950d1af75f4ca95e8426b46704c000000000000000000000000000000000000000000000000000000000000000164fe36456c72f3e73fcac704a7eb35c7f6fec0ea2992749a89634e7d54fef6d10000000000000000000000000000000000000000000000000000000000005324f5a5261cc6dbb7e205e22024cdda8dda3e3df110e2073b795620fdf262db607a0000000000000000000000001181d7be04d80a8ae096641ee1a87f7d557c6aeb000122eadb4be54a3873e8173e1793025d6fbc481246f4b19d678634eb40508e0000000000000000000000000000000000000000000000000000000000005328e4a10d5c41a83b4373f6a30eb989e5d1cc6261221d107adc598e2a16813f91470000000000000000000000000000000000c097ce7bc90715b34b9f1000000000b4ac1da6748b6fa2d2eff40f16873f196cf57a034a791dd45235a93fd262c2890000000000000000000000000000000000c097ce7bc90715b34b9f1000000000de18e3d3c16a5d7b49c9379881f4c53f3394812be05471d3a26f992f1548dbb3000000000000000000000000000000000000000000000000000000000000000154a0255bc06d95a5f483d2ed8f8cc979503e3398dafebec5cb937bc4895aaff30000000000000000000000000000000000000000000000000000000000000001c4582d2c56c952de46681cfb4a3d6b3560a3a7ede9a7b62a3ed045d544bed6ef00000000000000000000000034e1f1dc7914e31b40a261bf4a059daffdcee2b0aa6e8a1925227edc9d2dcca29ae0dce28dad8d8a7a18cb88096ceb806f7acbe000000000000000000000000085d50ab0ca08766295aa66e960ffe87454093ef0055648334a815a05a4a403e23ebd966a52d4febda73603f3513cb8b50907af2100000000000000000000000066f1c3daf78feb6611a269dc9361290d1fbd7cb39be7d12f40ae5897052a8c4c64c29fd53756c85e4bc5ea5e1d0d74aa9a471c230000000000000000000000007f68a6610ce77e77d843ef6ef9edd63abf12ae40a0853462274d1dbc0d3987bb50812a1b0fdab4ccef332329a9f43ecfef699c44000000000000000000000000de1f048761425969bd5295e24fd2c462018e167f71be57b5f95615201bbe2c0890c2438a2fe15d8982a25a161b7d1d61fe8cc114000000000000000000000000ee8ab75f6e1d5247ad7abc7b8e8f0fbc6a45d5330d1c6c8f9c71da5e255a2c72823172eaba41e48765c53ed0051f1a3c4146eba5000000000000000000000000ca4039046f0e9a34f86b5376ba76f2d5e5a2709ef3ed0f048f3081fed52ab9f5824bd7b3b0cdd32160c636807c032dcf3368b0fa000000000000000000000000d0886275a97757676f051b29d3b636badcb1acb532f1870ebc983cac8ddcaf500f22e99c16bb224fc84d5fefaf77be5a476c7bad0000000000000000000000000000000000000000000000000000000000000001355c4181a1f385cd951e3e85512f85180eac48e86dd87f63bad6fc3b66a112c40000000000000000000000000000000000c097ce7bc90715b34b9f1000000000601883d52eea5c0f070804d3a3b570ab791cec8fdf60af57ef7689cf80ea4d2e0000000000000000000000000000000000000000000000000000000000000002f739116597fba66958a8ae7320e536f4923a98940096ea44b42b34cb3c274942000000000000000000000000000000000000000000000000000000000000000131480590300340fbda02744a999d41b561f4b1783ca7ecf37533f1db5585bb150000000000000000000000000000000000000000000000000000000000000001cd7662cb630c3bce57f358c7f18521ca7ebbac87d2b277e90922d44580cd07220000000000000000000000000000000000000000000000000000000000000001258f0071c2b94862666a92b9ade2035e2b81bc5d4628ed15ee350c4494b393760000000000000000000000000000000000000000000000000000000000005329d772f6921d2e16c1b1d06fca2880bfa70f0dd5af8fc0ffce3e6194328a4a67a90000000000000000000000000000000000c097ce7bc90715b34b9f1000000000519f80024a1b0fa173429d48ad2956521b22b80eba0145cad116dc163247dc90000000000000000000000000000000000000000000000000000000000000000121ee69fa01f5edb77053d977f2e35e653a35263f869b042636e0ed5a7761009000000000000000000000000000000000000000000000000000000000000000013f0ba6e7fc6bf2b4376bb6e59679a6e284082bd149bbcddca5402e9ea2db148f0000000000000000000000000000000000000000000000000000000000000001c932f8ee79a3d0d6c47143ac27233e3a4cbcc75e77d10b0fb71b1d58b9fef8260000000000000000000000000000000000000000000000000000000000000001a24fb3177314e8d21aed8f00da95ec8d93285b5782905fd3695148c10927cf130000000000000000000000000000000000c097ce7bc90715b34b9f1000000000190860ece26801259777b27e911a8c6cf84b71442a89bafac0c87e9695f7f0bd0000000000000000000000000000000000000000000000000000000000000001d758e9de19dd3aae54bdb580ea083a47c00fb7489dc2d0aa7c57dafb9d29e1870000000000000000000000000000000000000000000000000000000000000001a936a7af23bda6667f6d1701ebf8db01f8fd92bc17d2a141f4bc047ef1fe349f0000000000000000000000000000000000c097ce7bc90715b34b9f1000000000e53af2a22c23acf8ffdd7f89671ed7bca96a85f3ac09853b1e24abd331f5a52d0000000000000000000000001bbd33384869b30a323e15868ce46013c82b86fb7f88a4b07198da13302eca3727d25f2443e06d2c74f3f4564c5a9954da31b3870000000000000000000000000000000000c097ce7bc90715b34b9f100000000038c91f2f8ee91af9030d79078e67193af7776c541561f3a5c04a8fd672c8f56d0000000000000000000000000000000000000000000000000000000000000001c868a7872fb51d1bc8d3722633ce972ad77eae13992ffe658499c68bbb98acab0000000000000000000000001bbd33384869b30a323e15868ce46013c82b86fbfd3eedcf3857ce47d69930858115ebafb1597fed0fdb4eedda1941f83105f9b20000000000000000000000001181d7be04d80a8ae096641ee1a87f7d557c6aeb8a77e7189c7823b8409c80844c8c2ec67b279cd000ff7fcfc78afa87f8fa6ecb0000000000000000000000000000000000c097ce7bc90715b34b9f10000000001897ddffb22f42ef8d458a588604ebaf3fce2f0cf5bff631daf30dcb4ec6600400000000000000000000000000000000000000000000000000000000000053228d71897e54088e8d69d9be15f84180c23674caf2e94ba817fe17632116360d010000000000000000000000004f790f2289c46e45ed197bce7763c84591e1f223885c1867c12fb315aa3a20b25b33884ad89f1a61e298feac4091c38727585e9d0000000000000000000000000000000000000000000000000000000069d9d87bf7b47579072c0e5d88d41b03a212acba091cf55a2a3ed13817b1aeb30798be2a0000000000000000000000000000000000000000000000000000000000000001c78a47a92380c8dbf37310759f082b97ff66ab05c324fffae22e36aec594b7460000000000000000000000000000000000000000000000000000000064363dfb4b0ba283d3637db427313ef64fcb7d8e7048a4094034ec5615a79009f9dda2f100000000000000000000000000000000000000000000000000000000000136bb155fdded8547f39194ea063fc8162e38dc7681ef9bb608031c7d57cc17167d080000000000000000000000000000000000000000000000000000000064363dfb1fa6925db7ad574f041ba2b1120737ae5523f4e0c985de9a5286ca539acf4199746167732e7a6b0000000000000000000000000000000000000000000000000ec28b78b9a6cc048b9e448d7252ceb0bf19733bfae675783e1c94a8ca48cc5340000000000000000000000000000000000000000000000000000000006617717b090256300cb97bd4459eb2b17446b9cd9e2ddd18b40136b0abee0632466a5fc4000000000000000000000000000000000000000000000000000000006617717b4dc07bbc50d9368cbe3a65ed14bf69dc9c42e2664e553df808a8970b9910c7ed000000000000000000000000000000000000000000000000000000006617717b43b93274c939f90a2ca713911c929042393d717d1bebcb752999ae734b810a710000000000000000000000000000000000000000000000000000000069d9d87b75408f7853d73646871fe0770433167946ec4246cb30c474d1fb19def29dffb300000000000000000000000000000000000000000000000000000000000136ba5dce6e9652f05bda38f6fa178fa00ea88a6ead8e7a26462c1f7f2fb38fc0a4c200000000000000000000000029ab060bd02cd22e4042095679cfc5118098d46c0799ddd86d56ff7a585393097d4a81eca304ce6da5aa4e54b1f86224729ece300000000000000000000000000000000000000000000000000000000000000001ba24ead0f5db6db5ea050b324c8ad172e063ba117eec1ed8a721d8fce19ba85e00000000000000000000000000000000000000000000000000000000000136b9c2289ebea213d7254c6ef728943c6c612bb2cb418c78b160f1411ceb3fe374470000000000000000000000000000000000000000000000000000000000000001e8828539bcdd93d3b84912dfbc88158f0984827860ce590b71e5dfc76aa9dfd10000000000000000000000000000000000000000000000000000000064363dfb916e3e21ed153df4d663f64eb114213b5be8073d740ab7538c7f1f38b5ecd83a000000000000000000000000c93d85b91dbe985400f41a81755ee842132848f711319507b731730a059906232ac8e3eba32e0b0d0329c8db128f63ee28a9fe070000000000000000000000000000000000000000000000000000000000000001e412c7ecfca70aa5de8d51b67e16ce0b6a7ab01f340d7cdde589e4df73034ccca7c7eb2f3f1b9f43cf927bfab2e8246db35e5765c6c8ac050224d53a7ab796af1f2e0fbc0ff4b698c8c86960936f324893b6ef6d786bd7bb80044cfff10cd363d3379c30e4c7b8a24443e23afa9272bac62d5dfcdac5aeebdea3ef70b7d7b9c4417d1ea2925a68dc3e7519b099bff6fbfcfbea2c9f6bc7501271f2ba69e69d96d82ca3b18d89bb6022e1547d6e4bfd9489b2a9c994579bdaac61c72c30c4a6e04ae320275846ba7fd1a649dc68e1e9a4980e8806c2ab6c100bd08535f60adeefca94efed4891bbba446ba73a989209b8cfcc282dbfd42e9bb380b8cca056fbfdb4a893f44ba48cd2b09fb0d9d1b82f11c541d1c8b2f3f2e652ef64106648b650fb42070b36bf61425b6319a9ef8464060bf5c749de4d5c420c9408d4267180891768027fca9ed429742dffc5700584bf3ba189b49f226d87208a2d66e16841f747ea769a77acd9536510b935e5f4214f4a3750b272bcc3f0c5b609a2c48ba2fcef54787fd3962f4d55b0ca87813a163ff8bab696ba2a58fb4c1c845bf155118a6a3030303000000000000000000000000000000000000000000000000000000a42bf46ca4942ad411d5efd6053fc72758e806e11bd4f4c5057eed5e0461d6be869747379696e67746f6e672e7a6b00000000000000000000000000000000001c99954d9dd84c9a8304a73a05b645bef88010ab5d10a5b569f1c120422c0ca5d5000000000000000000000000000000000000000000000000000000006617717b4f7a864a85e42cbf20158fc1b4e85cfc43a44a09d3e5a7126084e68536c37b0a0000000000000000000000000000000000000000000000000000000064363dfb3cc34c2a528abb8ac6d7b5e239fd36d1519068d9c6d868fec805b5077707715b000000000000000000000000491237018f89a5e7ddd694cf913f6c520268df68e2335a2b8b2d5c40481717c1a314c65f375c160b785fbedb8ef3a16899102b986c6f73746769726c2e7a6b00000000000000000000000000000000000000001687cda33238e453efa1e565c1c1f06c61677aee60d0b31f755b84bd1f0cd2052d0000000000000000000000000000000000000000000000000000000064363dfb00ba6a13414748b1ef36b6b171b5f19cbf88fe7b300e5af3aef2c4fdcfe4ad816c6f73746769726c0000000000000000000000000000000000000000000000107f67f2c7782ebcd3b3ff8ebf366d6dd2dc5ab7c88f76eb778b48ed52f4df78070000000000000000000000000000000000000000000000000000000000000001d5c0cb57a330b31225c11b0f53707564e8f1a14409a00772b0b148b9bc9f389a00000000000000000000000000000000000000000000000000000000000136b86daaa96f059f166dc407aad6278b5af15efe4fe10a3cd31a98974ffb5f30095273686d696e742e7a6b0000000000000000000000000000000000000000000012ef729f80464970381eb9145f866dfc283ff8b556e78697d92a834fc2018a124d73686d696e74000000000000000000000000000000000000000000000000000cea64b6adaa40952850ec2c35667d9f747617a546205498b4ae0fa6dcf92c388e0000000000000000000000000000000000000000000000000000000064363dfbe8706c847a174d16cfdc986ee037fb7f63bd5e00dbefcdcdf426cf5abf4dbd8d6a303030302e7a6b0000000000000000000000000000000000000000000000100d7235a25bcb0486ffa3af6c17ec67031c81f5cf2a91220e9a5510173acb4ab00000000000000000000000006924da629a9fd4c6f0e0c903e3254cb4e79bde7573cdc6d962cd4f23e714a51747ab1f643f4af7304b9b3ad7858dc974d9b4b0e000000000000000000000000000000000000000000000000000000000000136b70f594d11e78d366f73c65f16e85addc51f08a7cce0dc4311938b71b9d4282fb87461677300000000000000000000000000000000000000000000000000000008af297cbf23f7c4ef4cddc43d9c26270b9f7491178802f720dcd2800e3cdd9c3469747379696e67746f6e67000000000000000000000000000000000000000016b8a1cd86dcfe7e9acd8c0abeb6a210b0af6675adf5430ee4a7d554fcfc341abb000000000000000000000000e1240ffc4816af172f8fec0e9b705088e34964dc8fb262251decff49f605258f6f35161dc7ce936e6e6042ef9305a204ba971c077965736368726973746f6679657300000000000000000000000000000000001cd428a8cc57a462e1d8f27713893aed6f2be39178338fa3440d9ee06120b40d787965736368726973746f667965732e7a6b000000000000000000000000000022d7e70cf11ee325dca919a6a31b651049f214804fbae4cbdc4a817dd69baa747100000000000000000000000000000000000000000000000000000000000136bc9d4ed2097103f70dcc6fc6ecf4f29056f511985f365c0d264b036799aabb8229000000000000000000000000000000000000000000000008a0d48bb155d2517eb58c151666030ba908c1e368c855bfcf7d3ebf76171c03950e64f86b70d7d3d1000000000000000000000000000000000000000000000000000000005b0cd4ba3cf750cb637a033dedf97562e377a4d97385cbb531ea2ca8ba1578ff79834e640000000000000000000000000000000000000000000000000000000950269753c346491b306a599e06c9b42537432b230aa21106b707ad0c61dd13ec6c8d16c90000000000000000000000000000000000000000000000000000001d1a7898e5bb9c76e26838b78f745025b92a2a36a9584fa5e376507a4120b24750b6cde1760000000000000000000000000000000000000000000000000de0eef7f7e47c9bd02873f330e5cd67197d88043fb5255d082c85c2c1604b6b1981f11d407e86c50000000000000000000000000000000000000000000000000000000cf36b232a3388e98088472b674a08a86ab4aeae60d4d0d6d7451a247d80572fd11f7a45950000000000000000000000000000000000000000000000000000000001406f405ff1d3d1ab630cb88dbc07f4253dad9497a74275866ad99ec1976aa3cc0d03eb0000000000000000000000000000000000000000000000000de0eef7f7e47c9b336dc688158fd77d159351d9b51e1777d68331bf46092e4f5788e45d37f90d020000000000000000000000000000000000000000000000000000000002b0fd7bb0de2b55a8dea9e6e71ea9016a6d90bdec82a33319f76c88486fb58a4a89e09e000000000000000000000000000000000000000000000000000000000026259f6dd2e16d9b0cd56071419ae152d97435e5642eaee5f49aad2dfbc4d87800688e00000000000000000000000000000000000000000000000000000000017d783fdb57d2cfcb157fb367ec66e4c8324067317997d9a198f0bd4962233da333dc5300000000000000000000000000000000000000000000000000000000046a0cfabb83cc7091c1b9a042c99e726d285387219e21679236362f46444bfae0cd0b3a000000000000000000000000000000000000000000000000000000000a1d684ccb6534715527fdce0a23dbe2ee275a140be8097fa11e84459f6b3a02c1f1cf0f00000000000000000000000000000000000000000000000000000000000a957b1ebea139b1dcfde4ff4e6dade88ef3672dc0dd6f21853d7b5b4fac86e78424f000000000000000000000000000000000000000000000000000000000003e5b670b5006588117c35063b903588558c5bc040c9fd0003898416bedc3783f41a18200000000000000000000000000000000000000000000000000000000017d783fd65fd101d4bd179939f3decba3b9befc15103d766bd579f2d7552553a132b27100000000000000000000000000000000000000000000000000000000013959c72f6cbb181ddb6d13bd8a579bc42e4e82b4e65a988f6698c6aafe7e04b2af7d95000000000000000000000000000000000000000000000000000000000053b2c2f5cdd6305f23335ad6a7c3e2881139c02423c7ef14317c86189ebde8c90d899600000000000000000000000000000000000000000000000000000000000000011080bb9e1ba16709eb3903c52245e42b38bb67c296c2dcb9cf4d235150899d3f00000000000000000000000000000000000000000000000027b967efd738733800e22b650554b0cfd471177516b0b6d4a6684a639f69654f5333bb775d037eb60000000000000000000000003637b5a0a7bfe3045e0d96533d6dbedbc04ca93231720c657e95008736d6e155350b1bb22caec9e6572b4424f7cb3805dbd36ad400000000000000000000000000000000000000000000000000000000000000017f4d2bbbe9dc9c1519b105ad5cf3d226b7c8aa26b7122944f45ccc3ce4dbcbcf00000000000000000000000000000000000000000000000000000000000000012d10026f0ef46edb66759cb64fde8b145cdfcfe0f1be0c094e3e0eb12418af8c00000000000000000000000080115c708e12edd42e504c1cd52aea96c547c05cbe6f6a400f5d4927f923ba57f56b79135dbc76afa8a2919429a2615ecaf2b0d500000000000000000000000080115c708e12edd42e504c1cd52aea96c547c05c06b0be10f5614c5ce73af5efb84ab4b2bb4cd6e339198a97def095cf211273b600000000000000000000000000000000000000000000000000000000000000018dd7f6399a34b75fdb4bdedb5eaaa13ecc71422e2942b8b58a154d1670595e9b00000000000000000000000080115c708e12edd42e504c1cd52aea96c547c05c8d8fbd660b1f9bbef4e5c37d2f8c146fc79e1d33a340786babc75df5af222b150000000000000000000000000000000000000000000000000000000000000001070842ffbb3b588c880aa5498b712add6ffb379e749f45544e1089cd89e3c33e00000000000000000000000080115c708e12edd42e504c1cd52aea96c547c05cb25f80a852cd29e9638707bb3c3644d41a19fcb988c14c03bafedf59b67bebd000000000000000000000000000000000000000000000000000000000000000017040a4c342f27e4438da71afc92c45cf119b79f8e66be57041c90a5bfea60ed700000000000000000000000000000000000000000000000000000000000000013ca743c2b0ff637e016bf03f48fe69107b9f4f3ce061f3beb874b338bf968b34000000000000000000000000000000000000000000000000000000000000000184f999f18c5fc86ad5127ed162dc6e44ed0c805c2e5fb61f3f2e88a41e48af1f00000000000000000000000000000000000000000000000000000000000000019a9e639e0f11dfe7cba571283d6ffa33448471b41e765f484c0c61339f0279dd00000000000000000000000000000000000000000000000000000000000000017d79b34588a5f2b46a9a044bcf17548b73ae483cf7390ce8a0b5c05292b9bf7a00000000000000000000000000000000000000000000000000000000000000018d12a7c285824d5e9c387937842b8844b94f4cd431af43259fe188385f9dc0040000000000000000000000000000000000000000000000000000000000000001b233ba95d46f75cac29ea63fa9db25ff39f770a6d493ee10352f5cd0237c1843000000000000000000000000000000000000000000000000000000000000000100cd9b9f33ad3f67f9e8484907d8ad60deda0b85ce48778ef7f910a8ce42bf7100000000000000000000000000000000000000000000000000000000000000019b6fd8a07ba9acdd0bf5715c1158c7a5f8884fe681edbc7b140ad41f665693fd00000000000000000000000080115c708e12edd42e504c1cd52aea96c547c05cfafc88cfd45e24ea176dde65c19a1d5e417b2cf7b3d3340d560e39f27f1c019600000000000000000000000069b9a2eface47419d496d9a550a162185999ace5492b0d203b0786612b9560ca2781f60d8f38d83cd9b9d67bf11a3311dd04f3fe00000000000000000000000000000000000000000000000000000000000000016507d45886c3612c2f7c6ce8522a3a32175d82df803dc207fc38766c6b51de2100000000000000000000000080115c708e12edd42e504c1cd52aea96c547c05c70096f976f8bd50ac2b995ca1f43aaf4e24a97639a5b1af1fbc8300334a7cc7100000000000000000000000080115c708e12edd42e504c1cd52aea96c547c05c4cb7eeec2940d0d28503add7d427aa40078ac2fca00b6e1e790787539fda3a400000000000000000000000000000000000000000000000000000000000000001449ece3c3c13f80ae4ba5e02be7615a9383f840f5b8ba6be82177e39174fadff0000000000000000000000000000000000000000000000000000000000000001bff8d7879923b12e94084d53d755dd177e051e0ece0f430bde3dd0564ffecade0000000000000000000000000000000000000000000000000000000000000001e5ed14855c6e3f0bcfdd2519135e0cc9fa25a94cd93d02e021602969ab5093b000000000000000000000000080115c708e12edd42e504c1cd52aea96c547c05c3dc0901c79b419f72c4e302e4e0c49e8d45e1edea4981a068711744133f3f38000000000000000000000000000000000000000000000000000000000000000014a9b577b99a8bbd3e5d01edd52e6dae62d38e707cdeb812a5b45a748153423d5000000000000000000000000000000000000000000000000000000000000000128851093ee8c0ff564aa1df9845bef45afc818194dd01927eaada0c498616d69000000000000000000000000000000000000000000000000000000000000000132a1ac55686ea3afb0f7855e1e4c445f618d97178defbf354ee2feb28bccbb3e0000000000000000000000000000000000000000000000000000000000000001432cac2f5e7b5e0f34494c1d075f520d06f20e720d54c2fbf4ad50436a027f180000000000000000000000000000000000000000000000000000000000000001bd7df1df2177af71bc906fe09362eb2435410230f1f1ccc74c2593a251617ce500000000000000000000000080115c708e12edd42e504c1cd52aea96c547c05c96f308c51169961294223a9847026d5aab947578021457838e1a1dc98bbe4c7300000000000000000000000080115c708e12edd42e504c1cd52aea96c547c05cca520a736c615efda99ac4f297542760c45dae3260fa41bda9cd3be9d033acc400000000000000000000000000000000000000000000000000000000000000010a2e315343568c54d8310a3ab86ba8240c2cb23e2d13bd22e79e29c31f131b9f00000000000000000000000080115c708e12edd42e504c1cd52aea96c547c05ce9d31e439b3f9fd501afdfa1aa9d184cf810f214f5fbbe22630531598277010b000000000000000000000000d0dfdbc1eb17555480b4f5168b3cb31303d37e01183cd7ab63c4c86f9f08cee2a6644a7476267a85e8904f8d2cf65de2a00e92b100000000000000000000000000000000000000000000000000000000000000019b71e8d29ae1c6c5b3aceb05fea362ca9a0032aaf65072506d6f0d7801987b0700000000000000000000000080115c708e12edd42e504c1cd52aea96c547c05c115bbeaef2fb9bada249ab20cbc8a242d548165fa0ff265a765a85306baf31c500000000000000000000000000000000000000000000000000000000000000011fb243e2559396c24473e7bbd4e13b71d3adbe872cb2b07946d5259fbd5b0744000000000000000000000000000000000000000000000000000000000000000116663a83addd52602c78a2b350afaa8b206a080fc782ace28bbb10f1f35233380000000000000000000000000000000000000000000000000000000000000001111717afbc66ebad9c17adc192d484a20a67581859695fff119e6aefae1892f4000000000000000000000000a929cf2f30ce13e9ee0c498719d53add892be1b3c8b30c3affefe6af167f681ab039189bb97662440fa6e387689a5516a9aa58f200000000000000000000000000000000000000000000000000000000000000012fbfacef1042ff172442c7433cd799f84abfad65647dd0964a21e5677c72a93a0000000000000000000000000000000000000000000000000000000000000001a64b6e191381dd2bd86d8c02b0a3b2dbf48c849991c00d1b1c4a18feee7974050000000000000000000000000000000000000000000000000000000000000001bbae4730b9312a44ab28f0024866154b1a7c61715096e1ba173382daeff28d6d0000000000000000000000000000000000000000000000000000000000000001bc68b3f28ae5f7c3bf4677b63a0373da8aaa4a0c650245ea56dc609352ed02cb00000000000000000000000080115c708e12edd42e504c1cd52aea96c547c05c64faece2bff31bfe42f12cfb5ed3e958d8ee35875c5a5d5939cc36b7916e84dd00000000000000000000000000000000000000000000000000000000035504e16306007254348ece09b745fffef010f00639c02ca5eb9b4284427b4c897d230e000000000000000000000000000000000000000000000000000000020ee3e5436cdd57696054672795aa6cc505844b8268801b3846aaa8d847f756dae6f2b0dcffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9d8dece7e5182a55eb430b97cf5422d9dcbabd99e2613d5323d6739f5ac6932b000000000000000000000000000000000000000000000000000000000284ba72a90a198c8ebc3933237cbd63b295cdf66ae488ffdf64e3ff245e49e6ab43bfc5ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdb3283fbc9c56f2e3c11e8804586e0df655caf519a8223bd4030a4daa9e1337d0000000000000000000000000000000000000000000000000000000006a60e163207dfc1e8d0c4963c2b7c7c5bc7f6373a922404f8f50eeec8f7de13261e736dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1da871809d2fa74a9d214541b963c751929b57dcc92f9ad3ead774cbf2d5b13000000000000000000000000000000000000000000000000000000183962ee807d688df259319002bf0a69cf84a38f5a9a1952d9e5ed495535008b39190b7a5f00000000000000000000000000000000000000000000000000000000009bc1a9dd453aac4697b8706c5060edc8bd0d1d0e5f675cc0923a12a9ea9e3a7a01a2880000000000000000000000000000000000000000000000000000000000b71b004880fb40bf49bbf83b60cac573e6637b1ba756d97fa2ee04e5387493fb07b77fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff54c9d6e990ad1008d80dfaae1d1c856bcb69f179c5cb5f088f0765694ae1bcca0000000000000000000000000000000000000000000000000000000000000012f96e7744bd6fe6ce572de9ad582918ed3911204099ae26879bbd79bb43a8e67100000000000000000000000000000000000000000000000000000000000443db454b9b7a26427c4185c1f0827da16fb538e51d523ae6d04199b7796ea115a4ce00000000000000000000000000000000000000000000000000000000000000581aa5622fab5a3e709f7e98a26e41f9e5da5ca0afaecb495717dbdf596b61fa16fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbe313355d07e97c9fda15836821e96d035d44449381d73a06710a7c436c49060000000000000000000000000000000000000000000000000000000016381c3023386afc4c43b1d726330cf3c35d494f9547459cc9b371a09ef3b5d1ceabcf800000000000000000000000000000000000000000000000000000000000000025bcfe44bddab639d880b15e8d430dd8a2da39adbc10d4f2d05140f4e9d45eeabfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82d748678e71427173a35a26e9a70cc1b14d08b03578e8d875284e846a005cdf0000000000000000000000000000000000000000000000000000000000000004542e5ca8b4243a8c184b75a34dd8c4ebb3460c41afb8dc5b10d658139fe28e380000000000000000000000000000000000000000000000000000000001ab6908f37c751b39cd0155e40d0d6aad76f4be2ff99040aeeacff914b06057e8fce86200000000000000000000000000000000000000000000000000000000086486feba2db460b23097cab83b67f4f10fda4258f7330aa10af44bb34810d032840b380000000000000000000000000000000000000000204fce5e3e25026110000000bd04f03ee6c35fbd639c07e07a4116a67d3d13dbd6899819dc7387e0c24a581700000000000000000000000000000000000000000000000000000000000dfc4b67eb334d4b97e2457787035f007ff4459a47abb92a3e769c346f2dce86bed50f00000000000000000000000000000000000000000000000000000000002dc6c098f13f115bd0f0ec805999f7117db96a2992cc48a6352f2dfdfcec3495874e7c00000000000000000000000000000000000000000000000000000000001c4f51e4f6e80987d9809a3f0e88f78358f7c548baa94826b4f6897e42b15ad997df57000000000000000000000000000000000000000000000000000000000336f22fb7e98fada23bc141f459eb3b32f8115178141fac1b04ce555e85ba0fe0efa181000000000000000000000000000000000000000000000000000000001ded65bb13eded76a409afc6e9c197ea3e3714bd81fb917bfe9fb8c443720f8a79b6d61d00000000000000000000000000000000000000000000000000000000061a5228564cb166b1a8b3097730929560761f077f70921161db5d0f1c70cebaa96d49fc000000000000000000000000000000000000000000000000000000000165b323b738c905125decd48083c07704b8924eb44d958839dfc2527476d0b56504b95a00000000000000000000000000000000000000000000000000000000003d10144ba3e9c5e152b80efe5d40641419ff4eb2ea9092b45aa6ed5d691a4c3223b2b2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff07fb8aba2402591917486138102ef47ba79233b3200b8c3cfb0a7b528599acae0000000000000000000000000000000000000000000000000000000000989680befd7795b606cebcf6c0b6bce64c6593e1e47d450dfe93bf7d3effa6f42c9fc7000000000000000000000000000000000000000000000000000000000234e081e7f3132e569ad81e88b5818fd06552747ed81a1287ed86b35d79f2f559987e6a00000000000000000000000000000000000000000000000000000000017d99aa97caa6ccf2340a919921e962edb2a6d9c716a4068e8d80dd7bef78ce960333d2000000000000000000000000000000000000000000000000000000002c1b810005aad69ac436239e900702ca2ad47b2277cf027ebb5650d68baa59d0e3f42538000000000000000000000000000000000000000000000000000000000024a0f52892544af5a50730f8f909f5b4ce01376433d4a4e6817e25b8e8e2f0bd21af7400000000000000000000000000000000000000000000000000000000040d9900026458645a448f61b61036c5136cedcfb55e0d81d295c7602a59d7f9d10d83f800000000000000000000000000000000000000000000000000000000011b30ef199aa67233dfdadf5e4ceb8c1156527ade36b63cbeac6da34a13a6e6310c3adb0000000000000000000000000000000000000000000000000000000006314ee0eb961797cb90071e7191d6b4466b5e2b606e1104fda6cdd2f9cccfc01aa71ac3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff68d248a23fe1400fbcd2a477b106d0b82646049faf48b48970be24ec02725c7d000000000000000000000000000000000000000000000000000000001dcbde60fb19997b52f731d5f90ccb9d682d0b7ebd59c336598d394b11a349820e99e5b10000000000000000000000000000000000000000000000000000000005f5e1009c116e232db078e5b7226f3fd40787462bfe06dda11d873ec63761bfa0b4f58200000000000000000000000000000000000000000000000000000000000eb810ab77a453d345bf9e41a8bfbea3b9661f1980b6737224eb2f3dbc70e79b15404300000000000000000000000000000000000000000000000000000000011ae2210147b9ab7773f865e390ea675d7d05a98cae7b9cf1d6cae650c324df85337bb900000000000000000000000000000000000000000000000000000000002391bbd428c841c5c8ba399dc36a509ec2175ea6e17d4df3fff18cde8d9b5b110b926d00000000000000000000000000000000000000000000000000000000038d7eb20541434e4ee56219e2299e72637983e033efb2e6f5b1ff7cee7497bb1cc30d99000000000000000000000000000000000000000000000000000000000e60633d33926fa187a645acc07cc8eedb970630389c8a9adabc56fe0331c507281f3decffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2c6da1d8719f79378a3a37a03ede9b81aced3ede24dcb5147fba7015bbe351f50000000000000000000000000000000000000000000000000000000000706dea0c1fd3a973a0f6b080ede1fd30e52be6ef3c032de26656f573d05f52f188de73ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd22f0f7e0493705ce3560a397ef02ae22fa8a31a68f16b3aeef11271aae95d870000000000000000000000000000000000000000000000000000000000389a34d1f375de24007d700c831525bcd9cf36b4ab7f2fe83f0a6c9b4e713adb62fd7800000000000000000000000000000000000000000000000000000000048e173938eafe27c0926cdb1eb4bd00b565a45cd8ef8994b5ba1ef296fb99fc47d32126000000000000000000000000000000000000000000000000000000002133bf489d3a6aed6fcf373bb30e89515898032c0206a22df27a9af6c4246b0dfe9b2b60000000000000000000000000000000000000000000000000000000003a52ee845fe470195bc23095cdfe237b35f24e0436718ca6d320844811a55bfbb3befb6f00000000000000000000000000000000000000000000000005f9f4fa86b8b15a1387ff6556991f162dcd99d4752bbeded7e5f306b5abeec1d83e291fd387bc8700000000000000000000000000000000000000000000000000290334f34980000a2ba3647f6c3061cf88fe057bee5ae089004645f5c660802e47c1c5f4c0bf150000000000000000000000000000000000000000000000080f62f31ae992deff340f038bed5bf7bd990976869f0c5d7be3d3de17eb2328c922391314b1cd78a000000000000000000000000090a8b2e9afef2d2f0b2c5b60de6225dd41d70e32fd86d5a104ca901259ac4ba6f8542baa4798d1ad0cf405f356ae9a58038cd3a9000000000000000000000000000000000000000000000000000000000001dab4e281c7fbddba7c76a0d1227f92faaf35f329626e1d4689742e792bc9bbc3a59a000000000000000000000000000000000000000000000000000000000001dab47a1d8982db7449b61fd05a4da88c1988c63918fdb0ecde16b0cc9b3d940b2e4b000000000000000000000000000000000000000000000000000000000001daaf2f170f5acf9a9a20fbff27a10fadb19ac3f69bb4cbf9bef29d3301d2681d0c21000000000000000000000000000000000000000000000000000000000000006b418c13fcb615d4e98e77ec583e6fab70cb4c289e8a63ddf77409e904f21b39ef697066733a2f2f516d51726a4266374a42594d6477316a68366e5a4e706e315184f2204c782eddf23758beef8ee3fc6968148046d2bdc79022f3a443e816ef0e3631473943734d4869437453657779323273795848000000000000000000000001f0aa36249b6f86e438743643ff6c7749442a5f302b75ba4ba64c95db614c1a000000000000000000000000cf55389a4d1050f6a4cd04d58e93a12bfa24c280b3e75fdf7a0633602dc3ff20e64021622b0ec76e5e25bb4a24a75a51bbd72f3d000000000000000000000000000000000000000000000000000000000000000156a4e6f05f9da48ffabf7adb812fc139fee6c0e38186e347c94c982a83ecb4bd000000000000000000000000615b274fd1a404fe5f6c59f0b8310cc7f889a9cf6322221a731487570e52c59c6356b30ca6793138fb5057a78687ccc28343db550000000000000000000000000000000000000000000000000000000000000001e47ed93d4ee2a4413be008500eaa7c18d080ced0f1cbbe46f295f70a86a0bf4f000000000000000000000000000000000000000000000000000000000001dab2274106fb5a1dd25a012daee1a1ccd4ff6db087a4234e214a09e06f8a87d833a9000000000000000000000000000000000000000000000000000000000000000132219137078879d95ff985e03d465872cca065501f2811f1e6575b0fee0d5bd0000000000000000000000000000000000000000000000000000000000000006b5832730fe590ba3eb8139c479b82dc3f474f84bc10f6e1e000d30992358b5fc0000000000000000000000000000000000000000000000000000000000001dab12241d81014290ab4adc60f6df90ee000cf326aea602363870f7c66ad770346c5697066733a2f2f516d517a4c50597a73546239536a4a6d77447333444671487083dcc535156d005c386ce2f86005ee38ff25012a40c106d7a64d7ec851468d9f59624c784e3539636f63375437757931397233313900000000000000000000006bb21e8ed55fbd7460d9fed88404f77a54b62c47f1b15cc98b4301841acec7500000000000000000000000000000000000000000000000000000000000000001447708768b8f4bba7fc8beb2ec34581eb9045f8a99e953af24437160d89a5a54697066733a2f2f516d664564576175514b476f5a32386e6351504b63766b415121af26c1a16d25a2d304ab22ce3324e0f28168345053a0cf1cd94bea5cfc96e64271467a5a455a706f635363483943644e646845640000000000000000000000cb2e42f1580a4e5ef5819f18029c9742566b637a56c4083135fa11f5cfe3fce9000000000000000000000000000000000000000000000000000000000000006b5b666c0a2b32a203383c486c5eaa87297701e2ad393a461d5ec5d04e7972723900000000000000000000000000000000000000000000000000000000000000019f292e0e63bcd3a35b64595743e53b5b48a394eff1162eae0c1eb512460472b7697066733a2f2f516d5869396a576a6d677652524e4c614757747845354d3643d69e37be41e9344994575065af5376d964e49c7444375a7dbbd511e9f55e513869724754397948766e57666f7835363237775748360000000000000000000000f286d67dcc76d3aa235bcbc4cd423be38d05b2a08261b5b33e89d628193e2502000000000000000000000000000000000000000000000000000000000000006bbfca2069b2536d97a0f74cb941dba11f1ff937227bcb4740de8aef45b9144658000000000000000000000000000000000000000000000000000000000001dab34f421e6f3cf73ab338ffc938e965a4f4f0f0569fcb3e31c7cc4fec18764d7844000000000000000000000000000000000000000000000000000000000001daaf5826d6f848519571158dec0b34273d6c89d478cc16cb8158465069fd6a9d5cbd000000000000000000000000000000000000000000000000000000000001daad6fe9a71ee8e6a9c9bbadbb0bf46390660e7e4b9936268e65551dba249a4b63e600000000000000000000000008c03472c4a8fa35d79f43766a7c0ea38269fcea1d41d72b50504c018693e07bb235012f10d0208e392f050e6601c48ce7e34121000000000000000000000000615b274fd1a404fe5f6c59f0b8310cc7f889a9cf217df1cf42d1acb52803199663204d54943bf64ea21126d97fee3c276768727b697066733a2f2f516d64766e433752766d71596f5944475a5a31746572767262a74b5061fd800f1f448b66fb0b3069df4b886f0b70238d78357674f428708a1951396934354e5133644e766576397164737a786b720000000000000000000000154ebdc05d67a719e5c948ea28f75a4ba5890c2fbcd44ead9d13990780f3bf9b000000000000000000000000486e3cd0b5711b0c5120d774e3f269e8c6aab5e7ff95914b031210921491028388c1ea0c3bf85a6bd60fb1209cc35f35384b8ad0697066733a2f2f516d546a4532724573666a31656d46593762575a346242636ed3cb27b641da24b2240e89588ce7e16b3417c0bd2dbfda41dc0b1c80eaa68f9e62514b47376d6139787865655357316d7965416f4c00000000000000000000007cc0aa209011b08ea3bfd39d454a508bf1c16ee5e46c9acf230201bd9b1c942a000000000000000000000000000000000000000000000000000000000001dab23f650c2dff8ca48dbed79d4948743fb185a8202b1fd09b66fc94049c6ef643cb000000000000000000000000000000000000000000000000000000000000006b9912032952100ff1ef8f17f9bf8d113787774dc71bf335d3a7e107b5c422e14d000000000000000000000000000000000000000000000000000000000001dab195b1f2a3da752f8daa2129c546c7b6b2413cb79f52542d2b39be124bafb1a730000000000000000000000000000000000000000000000000000000000001dab354a46a435ff514bb414c3126a417648a793a5f6696895e0c69820302e40f557100000000000000000000000000000000000000000000000000000000000000019d133f372d432c8d1f0ca801c379e63a95162f215500da14c7e2477a3b74eabe0000000000000000000000000000000000000000000000000000000000000001705f4484f0725f2555c00892226b2aeca30a7a603c746177048ec6ab51909896000000000000000000000000ab56da5518e70688a1fe993c11e56497a8a207d2b30e53c914ebf102c98dacba176c4d57735d17de61979523b87f59deca63840d000000000000000000000000000000000000000000000000000000000000006b7d82f83e2738656d176e26c31ed37875929477dc6bc094c6667caf5607ecee48000000000000000000000000000000000000000000000000000000000000006be1f91535d4b33f4b27e55c14d04407922421b9da2e17bc575cdd7ba671c9f30f000000000000000000000000000000000000000000000000000000000001dab0db3776011bed59227e43025995f32b0662114a8f78216031465ee99bfce6eed8697066733a2f2f516d5466316779596442424531564868504c6a474578687976719f629886079feaeeb42a9e0205134254e6380941d075ffe26a2160207ddc8a316a716932513766766d323368693367427434416b00000000000000000000006e628674fe9bd2e64322cf7b94f8474db3fd7562617ebe4b4b8b1f898e203969000000000000000000000000000000000000000000000000000000000001daae57ce0d04fac4b6e42cac71810e4bcb951a4fed2dff6fbb1d42add4f33613058700000000000000000000000000000000000000000000000000000000000000015bf9841ea08265792a33ef68f0b767d87a60017e852b6866c2bf54e07028b753000000000000000000000000000000000000000000000000000000000000006b5d255b3819502bf5af779d9608516d47a9b877fc111f449654c91ddbf832c175000000000000000000000000000000000000000000000000000000000001d7623914410bebfa4bdee56e73a4a60bf999b0efd42d038cdd01aae334fda32250140000000000000000000000000000000000000000000000000000000000000002154db85c127f5d160acb53b5b153ef9510bf65e3eaf542772e14ff9a19a45edf000000000000000000000000000000000000000000000000000000000001dab0f0dba6a4b9b66fc6e88a172d4bbb344cff6a8fa2579dff31e3debdadf86ebfdb000000000000000000000000000000000000000000000000000000000001daae29be4473d26823213b234936c60b4d98d2de6564ac99c3faaa04b53a9b4b7b1e000000000000000000000000000000000000000000000000000000000001dab5ba585759fa154cdd0669bb285bd3e0953f4517a449807b3ca7842bc8c4d4d934000000000000000000000000000000000000000000000000000000000001daaefbf885fe6e9ac05ac5513891e24e8dcbce1c825405d4ef80eb7e1be7cd9a0e76000000000000000000000000000000000000000000000000000000000001daafd91ccda355f70aabafd7a3931bcd0d60992dd3fc3cb1264c7362b28975b0f201000000000000000000000000000000000000000000000000000000000001dab08d6986b664316ac0f26c48d0b03ee7d3af99a45cb643d9e8782d9bfdbfe2dda5000000000000000000000000000000000000000000000000000000000001dab1d216a3ac2241ec8d95178e85c54e381a7cc8ea97b3b6658135526e50f18b9db6000000000000000000000000000000000000000000000000000000000001dab27850f4000af6f820b967284a0b38270faae8504a0e4eb4c886cab73599f578a7000000000000000000000000000000000000000000000000000000000001dab36068b9d7204b8d6e2b0c61c7e596d5bc078467e1dd617b6df1fff7d715fb6065000000000000000000000000000000000000000000000000000000000001dab40793cd4db51c203bd3463359fd6b2ea97a9ead7904bc3a9dc1f0f41aac486b09000000000000000000000000000000000000000000000000000000000001dab54ddaec608ac0a67a9b79161d78c881747556e45539e61955fa5a3f653828dc5d00000000000000000000000049934f40b765cce756c708f8874170ac91c0eee9e05eda535268e76a318737e29faf8080fa0745c2cdd011c6029505e2a1d68ef2697066733a2f2f516d53345659524166524c3744774a4c46727973733842363513cd1f39d9b675d61c321eddc8aeb8a18a4be8fed6cfe73bb41bdb15afb51d8756556438695373684b55354a6364586a33366541640000000000000000000000960c21432e15d8f9083e89ec04ecea5d6064314b0d17ed3419b0cd1d46096fa200000000000000000000000000000000000000000000000000000000000000012ee4bd11690bb4b9e41f0f318724a6f724297422bbeda4218b2806dccdd328aa0000000000000000000000000000000000000000000000000074d007d42d04eecfb16b5513470ec1617e2fbed660c0e2292ac0ead57023de89b7dabb7b9b461200000000000000000000000000000000000000000000000000071afd498d00004e72f3304740c0a5099286cac6ca65a6b3afe53edf139ea55c515868e10aaa1cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff759285d661b4a9286be9dbb7a2c4868f531eee4854b84b10b1dfe0148906df0000000000000000000000000000000000000000000000000000000000000000013bfe3db4e15cc11b3dad0f873880e6ab50687800b9b9a5113d5faedec9fc75960000000000000000000000000000000000000000000000000000000000000001a6a9cf1eea046ec92f28fe2793297346d939c7b5aff2ce8235e2c8feceb546a9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff245b5f50b6c75a2578cdbce4a282edd6ee4c9fe6f48b80baf0b77bd4576af32800000000000000000000000000000000000000000000000000038d7ea4c680002b462fbbad15533dd420fd0080d7171bc5aaf9d7d012eb09bb6773ce92b577a90000000000000000000000000000000000000000000000175407376ca75d7844257b363e7d0d55c54ab580f8d7d0b4f7c0c63c828b3a3560bb426e47bd124c840000000000000000000000000000000000000000000000015af1d78b58c4000023b5f931d07d4f0b943dc4ea514dd0f27c68e68d0df6a3ea2db4231e172461700000000000000000000000000000000000000000000000000805597d6796e76edc5b9b7e6cb2644ec9da21e8053385d16a8f1529e1148844d13905c28707564f0000000000000000000000000000000000000000000000000186cc6acd4b000021f66497e3b8ec695b91ee3401a8dfcf0fe73b6eebddce893a68060480b9dd6b0000000000000000000000000000000000000000000000083effb3774288be7f99ad8f5d76198e8f27ee9c6791b924cf81ca2fa35b1e11e67bd38c6392cc1ccb00000000000000000000000000000000000000000000000000000000000000014630da00c532bd8de7aa413e437ff1233c4dc007eebb718938e09c6402cd78bf0000000000000000000000000000000000000000000000000000000000000001b70712003d04fef9179708b8cf503ab833c9cb9c51315b5d5ab4220c676d8aa50000000000000000000000000000000000000000000000000000000000000001c8492e35fbd402e5e0300364f25f3503985564204ed2692e195cd29bad37d34b00000000000000000000000000000000000000000000000000000000000000010db94ea815f121e2810e096d4ed9c021af5bdfdd4fb69c7c8a14376267b191bb000000000000000000000000000000000000000000000000000000000000000122e8974e2b35aa50bd8d939b6f42d95b03693d3c5688c6bae34c07461aaa4085000000000000000000000000000000000000000000000000000000000000000173510ea76ff5bfff623082a04d1dd6168823d4ad400f118301128ea5987f43e1000000000000000000000000000000000000000000000000000000000000000108253b704153ecd592ef787984abfaa4de466bd2223b57d43b1002c540a5f273000000000000000000000000000000000000000000000000000b027736ea84965dbb0629e1540fa7e9819a1950af87e99ccde7bcf8335e1ba22eb81da95778c00000000000000000000000000000000000000000000000000000000000000001a70ac0b4c917cd9af5980aba2f38ac437c04c8d76137ef17e6723691f3833bb300000000000000006435934836a13c33f16ad3a8ed11e3908449624cf50b7793aed53590927076a800b19bf05606bad23435a5b3903681792bbf0aedd54c4ee70000000000000000000000000000000000000000000000000000000000000001fdc0387fea715fd361486e5fb86ee3412c004e756ff5e5f6900e37bbb53245bd00000000000000006435934836a13c33f16ad3a8ed11e3908449624cf50b7793e5a4a486ee5fa301fd6b7493141e94b662febf652a31d487554da78356fbc26b000000020000000064363dfb10a1db5d3a971cf1e565b28a86d5ce9e576a7b81e216912df44290b84fecab9f5959d5d4f3f17db1bc0d9e1028e75ff2e2c2d0db0000000000000000000000000000000000000000000000000000000000000001d1f0fb8ec50177e83b4c116142dee46a65480afedc3532fc5b84e1575e185a88ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5433d7f5840d783b98c4ce547cf65157167973a86859b01518732a44ce93f0c800000000000000000000000000000000000000000000000000000979b3d480175611f6a641908f05d0c5884cc4ebcfb6a64a2bf8e6fb5a00574e47dc0ce23b3b0000000000000000000000000000000000000000000000000000005f5d9ebcbb08b5b7009a9ae73898471d00154e1a86dfde83e192271b7d6a14fc73a4d6b33c0000000000000000000000000000000000000000000000000000000000000001622ea98de859bfd562a14874ecf7729d92ffe6571093221dcfe5d1943c7402810000000000000000000000000000000000000000000000000000000000000001db5e3734a8b796dc60773b7500ea60ad6c0ddf323cac766cb1abecd13c5ea43700000000000000000000000000000000000000000000000000000000000000012d55a6f5ece4f1c978fe6b9045db805e726d5ed423af7eee4115fbda839ba5dd0000000000000000000000000000000000000000000000000000000000000001d915358e3206c0e32908bb454e9a9ddbdc0de52497c16f7dc3a213413820a9f3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff42aa56c450312dd3ed4e31ba04e986837abaaa2067e91c1c70ad21735fdf87a2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff154ed46f5f69f73bd1f0a2c8a34d78496aa764f382663dd9d58939ba007c6e6d0000000000000000000000000000000000000000000000000000003a346804720045988c6cb0684e8354009f337ad2808955148601a7161f74e2f7e3a9577720000000000000000000000000000000000000000000000000000021a5c8bf74f2660681a983965ecc6d20f3b2c8fed925d3c9a341b37355a14e6d33d5a8facc680000000000000000000000000000000000000000000000000000000000000001d852c5c784e44e8d140f0f7f7eaa724f0db0e8740e1c214e9c3bce9b26fe976effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff974be7b513959fd455b764a3c21b5fde7b42f69645f371aa4c9645e5e78f3c8f0000000000000000000000000000000000000000000000000000000079aad093a1fbc865ddfaf0b8954f170e7034fd783e256d0946c68361b004720cdf462a02fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff43c5e9af77b21fd6add8046d1bcf5f5bd45408dbe1577a230f52c6ad4cb3d50fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd36160c3ace9179a08183d5e23eff874b90e3420b25ea1968fb77008082739300000000000000000000000000000000000000000000000000000009e1beb70b29ac836ed73b9bb2e021d44b0bd2e1677acd38481fd66d872fcdee12d43f7a8e000000000000000000000000000000000000000000000000000000000001ac90b332f712b93ff6b17d51f9f79a0a935a42c9232cbbe32e3cba4b1c63a569177f000000000000000000000000000000000000000000000000000000382ffe8c9dad1bf17c83c255269c9f63feb559c94bd93ccb1eaf6d691c8420d5dd7f852a41ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9a647aeecee771edc136f7e932bfae9db257ef8c8b2d252304d5e6964a1770c2000000000000000000000000000000000000000000000000000000000000000191e06a9399b708e8044b7a6e5b6bcf786ab69005e614ff394778ce4a08d20ef90000000000000000000000000000000000000000000000000000004c9dcba2ee50fa9c86b6316d4783161a922f7b3f20260ea10af9e087a20087718e0fbf5f780000000000000000000000000000000000000000000000000000000082c63275edf33b9b65a61ed1664e2b2fa4b05eaea73ec6b91347bc47cf9df128279a018f0000000000000000000000000000000000000000000000000000000000000001da34ae09177da263b07168355e12bcbc34379e1f432e70ee0fea8d3036b7c3c50000000000000000000000000000000000000000000000000000001b57b51bf8ec68f5289d5dd78dce9cf82cfe97348165a386da555da0f36cf0e47e27618057ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff976f218301b14856f9da925532ddabea8929c3dd9eca063b5ffba7ab06fa3cbb0000000000000000000000000000000000000000000000000000000000000001328a66f33490ad40a42eb8b7ea0537ebc9788b5194b95e92f859e498eb8ef73d00000000000000000000000000000000000000000000000000000026403c0e54220ad0c7753aa82ea9816c8af8d0dde9a181111acd4f0b1017166ead11efafbf0000000000000000000000000000000000000000000000000000006847e89169cdd503362c765037dfd77b4e73639d3af73a8cae506078a1af86746c6864874e0000000000000000000000000000000000000000000000000000001989e90aa4e119bcc6bcddd5140e32504510e1dcff59b9d1eaefd5d607a002b822e958f23fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc5273391ddaea235ffb036e826068ccca0ac156762d098d2f757190f21f533070000000000000000000000000000000000000000000000000000000000006930f933626a73f0cb84760bb2e8f3b83cccf28c8544b4c83155bb4b1e85cb6ff285fffffffffffffffffffffffffffffffffffffffffffffffffffc7d38d5cca86c98b6c741e2c3e00534122d7ba8c5d078e9df105643172e94ebd205b804c6d11000000000000000000000000000000000000000000000000000000000000007d94b7526ba7f81a43d722dd299d3cca9dc8dbf4eb561ada0284ad054905f52cfa20000000000000000000000000000000000000000000000000000000fe9ef6e42ceb8cca94928c269cf8146940e0af9ccf1a5bc598e0c281639fe957260f08b620000000000000000000000008c4188fc25dc437021a7c0ed5457d9d0605edcde81b5086e5c239b37388b0e150bda92b23a5539fb2e815c9031e08c0db12b92e0000000000000000000000000000000000000000000000ba58e545582d4600000ce6b2f11b3ae72cbdcb257753abdf44dc7cea8a0e1945229fb0eaf14774b56f10000000000000000000000000000000000000000000000001bc16d674ec800002e91a5c679b9fa430ed0d01e3fa2a6a4a60edc49e4adce9d84bf867f47871d79ca94efed4891bbba446ba73a989209b8cfcc282dbfd42e9bb380b8cca056fbfdabcbd28c2557d9ed7a2e368dcaf1873a23636ccfecab01d56384cf2404c2e1a62ac251a3c64e8801e28b563ad5c82b9df8b98005914704bc5355fc9fe126bdb79d7bbe80a951f2b44e2c91cf0b0c5eda08d542e04c0ae198d8c5f228e29d2f70e1240ffc4816af172f8fec0e9b705088e34964dc000000000000000000000028c4b4a1271c67cd4233a0172f79336555ced41b93a309fb4296b9ba8182df881f29ab060bd02cd22e4042095679cfc5118098d46c00000000000000000000002873114f54fbb6e9a20816121128de3f1e5f5986f75fedd7a4d22293049c2a95040000000000000000000000006924da629a9fd4c6f0e0c903e3254cb4e79bde751aa1b77255084f5fd8f20a5015ea0fb0990771de124936ef4adb2e91442d21af6a696c73616e6465722e7a6b0000000000000000000000000000000000000018777c7c0f9bbcdfd3a23efcdce0415edd89d9f6b6aa1b2d3744a36b110892d6e0a7c7eb2f3f1b9f43cf927bfab2e8246db35e5765c6c8ac050224d53a7ab796afb2b95bf54049a5daeee501ebe016a4ba5e0ed96ad4ddaf3cdd603b0aea68a25369747379696e67746f6e672e7a6b00000000000000000000000000000000001c13ecd5760eafa3f0f53d3d2ab124696ef0032f58ebac150315e346e71b504a71000000000000000000000000c93d85b91dbe985400f41a81755ee842132848f7a1b6bd9ab8f6a220a487f732fa642d54948940cf27aa6ee1211756296e1288a900000000000000000000000013692c356dcb8532e48bde836de80a48b4215782321b955e9ba83fd1dd499b5eec1de0204af5c9dff7c04ec29c374941070361f7491237018f89a5e7ddd694cf913f6c520268df680000000000000000000000288888039f32c864c8743f59e505c33ef9b7a27ea93a8aa9b5603a9a11694fd09fc93d85b91dbe985400f41a81755ee842132848f70000000000000000000000284c8cba0fae28b7836fb7b3656a357a432c01081dcbb5c39c14019af07160c0506924da629a9fd4c6f0e0c903e3254cb4e79bde75000000000000000000000028c6e6cf1f22804dd91ce7ef3842c3ef6007f15cec932d39ebec58be02db08c45f000000000000000000000000fb7be4c6065920beae195e7fc1ce1982f8dbfe7f8e0d92b64f3cd20e39111ef8e9992be1fcae2e87b0fc4054cc18c829a0f7e98baf02d1249a76e1fcce695e9e7f4130d0661950c696d13c22068a90d2e7eccb02c406fcf6629531b8e342b4d23b0a9f904dfc7ef54a44d3cd97fa7386fe6a3d9c4f790f2289c46e45ed197bce7763c84591e1f223000000000000000000000028775cebf88977d079f93407da9f8225208109f5a5fad4f7edcd70a5900d9ff5506a303030302e7a6b00000000000000000000000000000000000000000000001086f9a1e2215dd7e1514a55494846b4f114344ce2bb9e1b86d97c342773c956127b7c156aa685986fd8f0ae95e2e8cf70ccce6b0dc04b10b509ba6dd09667344479e86e49f9b04626ef3fce564009dff0808ad450991aada3ed704c5d273d0d1d00000000000000000000000029ab060bd02cd22e4042095679cfc5118098d46ca884106b21f85a320e12378bc55e459de3c5444b100b065682f53d0d01415af9626f7963727970746f2e7a6b000000000000000000000000000000000000001832d0db2d901b97843fd4be1aaa8aacc2bb886a0fee1fd337fdbe2dd203af39861fae860de50a501e36b55482c26ee64036236b5ce30c166688706f9ebdd4d8a16d77303b71f19ec9606033b1c903ad9fc72daa7a45dd42ff977a67e107c122fae7f34476be06fcda2e32e13d498fbcb76c8708419b8d0b3debfddb129668cfc856ff8c840341bd46c601a0e9489a26887ee6e80fe04fca92e2d3b516f34c445d881f55d3e130ad793c205ad7fdfcfb66a5d573bfed4a09a95158baecfa300b24896b2337514081113a8fb38da80d1e2b1d7f44132c9db2d288f842475fad36020000000000000000000000000000000000000000000000000000004d75ee126571a463dee9e08c756395eeaa929f3ccf8432b3b390358839ca30c60d85525b09000000000000000000000000000000000000000000000000000000000000000144023035317343017fce6ee8c2dd42a1139d7bae95a0d665892d1d99a1e5c05d00000000000000000000000036f649e8c5418de722d9f5f56d0d74f22ecaeaedb09efed3e44795d803c98f845da16961af84184fe8e9955762c112c0b723a0f70000000000000000000000000000000000000000000000015af1d78b58c40000b500066e2ee083d0db3a86e508ea0200ba969e269f488f678957d1540a00c15300000000000000000000000000000000000000000000003045dafcdf1d9e7abf9793b949e040d3021bfc7c687daf29fcdc6ff7691a96b21c5efeccd811b077c50000000000000000000000000000000000000000000000000000000064363dfb0cb01fb508dc3371b61576fb6a7bc2d230065ffe426ff01c25fe9da81047946f0000000000000000000000000000000000000000000000083effb3774288be7ffc2fc554b15de579d344c1f6b46b6bce558a645bf2d771126253ade98432c876000000000000000000000000000000000000000000000125b7dd33e5dceec9f51d7f362e9600b52105ba43e7de5767597135efb92775a17c40e74d94abcd44de0000000000000000000000000000000000000000000000000000000064363dfb72dca86aa47226da664c099e1be87e2902b520e34b1fb7d20e438bedca79ceaa00000000000000000000000000000000000000000000000000000000000000013ac357bf78ae43d2af28e82136c96d08955e1eff9ea57e61d4a8cab6fc1f9f830000000000000000000000006c272d134ab69ce9d9fb7f6ac770fe815a3112eec4d6c4bddd08d475f222e71c9051f74cdc613466e890ea695b5e3eefaf63cd670000000000000000000000000000000000000000000000000000000064363dfb7cd447b95586077f3e7bd13ed6015a0b3289ce20901a9343cf7a0144f2593c4f00000000000000000000000000000000000000000000000002a2f8f1255067f456a27c1a7e4044b8c2ad74f81ac0210b4242ee993156026b1a536427229a39850000000000000000000000000000000000000000000000000000000064363dfb4216d7a62ad15dbd2cdf714d03a2222442788a63342a43ab29a4b2998a98d2c3000000000000000000000000000000000000000000047600ddf32e866e941e97c29c2cef0da413a9dab698abaabeeeb53449f9ade5818996d829124dfe8c79740000000000000000000000000000000000000000000000000000000064363dfb7bd97bf7f2a4098f035df1a863fdecc9f08ff09d42e26ad832e25693844e60b200000000000000000000000000000000000000a7d8c00000016d0000643be340ef6a46aeb1c25ea0e5b29e275b0efbafea888a37c9587c5e6313e0f41f5302460000000000000000000000000000000000000000000000000000000000000001336e880f4e64033dcea460c6d9d870dd534842b11d360ae61ca074866466e98e000000000000000000000000000000000000000000000000000000000000000153b2f1f237095a1fb82415f065a94131f1cde50da5bc43f1e0d54a2e9ccb03db00000000000000000000000000000000000000000000640af523345e9583681cbc195d46938d86add94c36b00f405c424721b908c1653acb8792af053e0111bb0000002b7e02316a0000000064363dfb0000000070ef63ca0000000861c46800c9110b4c010ff89cd6adf0a027b043f27f3578fd349fe1dff67220525c844f7c0000000000000000000000000000000000000000000000000000003b4cbcccba5a007dcb8f1a747edcdb80332dce1c36688ab003dbe3ece99a5bd690e46af9090000000000000000000000000000000000000000000000000000000532e6df44450fcd4cee5297e3eec1710f563804521e11855e0519a3722ba6277bcab76d3600000000000000000000000000000000000000000000000000000060a98236e6407b1cb76f0c066d9dc268315643c8b094d85cabf244ae4acd65d8845863162800000000000000000000000000000000000000000000000000000b53403d592c13e8e616ced7a28ca279ca4916a320cb159a6e4c477aae618bc6a6813445997e00000000000000000000000000000000000000000000000000000007b29d6b4291e4aa7e2aff6a7b35ca3d19f5565a53a2f2a54c307aa6784267196d5ad1a03e00000000000000000000000000000000000000000000000000000000000000013e1b1670ceea56c529315359efa41851259e2987f3818736d8c6f8ee4435db39000000000000000000000000000000000000000000000000000000000000000104981732c9d3a7ed59ecc5b54b2db70fb2a2df73d048950fa8ac47286abf78260000000000000000000000000000000000000000000000000000000014c419ed65d46e620597c33c77669fedf8b8d1216511fb70aad2638688780fcea9ef22b8ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefb67037e6ba08c269abed12af1302ec0d2588616dfdd5fb077435594a11a9d800000000000000000000000000000000000000000000000049bdb27b890cd2cd31197404ff35991fbadfc5844f1efa98d14b7a0bc4eb14feb693878cf610e32b0000000000000000000000000000000000000000000000000000000000000004a7ead4d564d2638d3e032f4ed63e5ccb6e55b8087397aa9f121591dfd61169ae00000000000000000000000029ab060bd02cd22e4042095679cfc5118098d46c1dbf57fb3e3b200b5131320214bb615bca30d742514079d60feb2c9fbc1b11be000000000000000000000000a37fe7e6447c204b5debf9489f2d5635ac078bd6bf1d592dea02aeb90da8fe647f4efd4e9a0d2c1208b783e8f456c88a94c7316c000000000000000000000000c93d85b91dbe985400f41a81755ee842132848f7f1e382d11af04eb8155b32b96ccff44f1c4a74797901d44d3ecebbc1fe0fd564000000000000000000000000a37fe7e6447c204b5debf9489f2d5635ac078bd644e3fbae2f29736fc6783945f08183d37979b7e7ab4a221ce10765c89ee0fb450000000000000000000000006924da629a9fd4c6f0e0c903e3254cb4e79bde753a5f1907cc7134f6d5f15d4e222c2164d048f977c697e166882c86bd50b726ce000000000000000000000000a37fe7e6447c204b5debf9489f2d5635ac078bd62a3d31574ebe1e0469e086ee84d38dfe6a5c49bb7de1782518c9d77caf451bca000000000000000000000000491237018f89a5e7ddd694cf913f6c520268df68b40f7cb544524f55c409aea5df5bf29d00e0dd0f3d91a089cd2531fe737b35d9000000000000000000000000a37fe7e6447c204b5debf9489f2d5635ac078bd69a7cf5b7099eeeece78e9eecba0ad3df33d0c4ab40effe50c3bba63e342aa14a0000000000000000000000004f790f2289c46e45ed197bce7763c84591e1f2237f2feb05dccc8e3baf8487f924cde31436df52447007c5d8f4559307f2755cf1000000000000000000000000a37fe7e6447c204b5debf9489f2d5635ac078bd67b0b5d35031bb62d6a4d3ed3261a22116c9327c7c4d94a98a7eddd7005ba6910000000000000000000000000e1240ffc4816af172f8fec0e9b705088e34964dc4734144681b608439e5b29200052b53f35ae90a859346023d0eeb8b615e5284d000000000000000000000000a37fe7e6447c204b5debf9489f2d5635ac078bd6457cebe2896ce6666d3082f4447b77bcc8a3df18b125b442204e3f38b6c570220000000000000000000000000000000000000000000000000000000000000001ad7f8765478f5c8de2847be4f24603eb1fb77fc6ad255178e292c7a32234279f00000000000000000000000000000000000000000000007423491c5aa4a88101794b0015bfdf4be933927f0d171fac631a213fb8d74c8aee9ef78d5f03e23eba000000000000000000000000000000000000000000000000000000008a061af3e55ed7b70c5cbce4c05319f5f1b3a7c66e1909f09823124b6572de26c41fc4de0000000000000000000000002a2f171bdb7b7ed6a93ee3302ed763d27e03f0c286d22a600d534dc699ac1a1c212746a585b8e9e265b0c16d38f7683e26fd46210000000000000000000000000000000000000000000000000000000000070955cc96280321f391858c82f55015bc685d21f25393bc0b96a1f9066faaa55d4ff700000000000000000000000028c1908f8af53340b5b2414721a40af7862c5e5afa09fdb7726f7164ef2031b63678dd1d9b46c6276a0f7ebcd2eb637580444320000000000000000000000000000000000000000000000000000000000000383c7a045e8b4eba83f1828cf238e2a1df5953497984f6f85533b239a6ffdceaef4c00000000000000000000000000000000000000000000000000000035ea628716f66be3274640e8c6e119915ba4e5c35286b762ac4cc953947f240c0cbd315d62000000000000000000000000000000000000000000000000000000000000383c700ac49dbeb225fb64775662b34fde5703ca1be10d08cfd26c4ffd7352ab58fc000000000000000000000000000000000000000000000000000000000000383c3631645b0ad9d2016669704d42b34ccd0ee037fc059d19abb0ba316caea8d57c000000000000000000000000000000000000000000000000000000000000000178ead8bb607e5b1ce85ea22070208b3e607a21820515ee5551f8caf1e89208180000000000000000000000000000000000000000000000000000035ae28f3384f3f760c0a811faaf40d41dd57e44e5de437dfd8c88abbb6e720d801043a7bce70000000000000000000000000000000000000000000000000000000000000001fb1b578bb65229c585aad09b2dacfc2cbd0cf818f5191a935b76d964c0252446000000000000000000000000000000000000000000000000000000000000383ca07b3b474538b2aa4d7ba8f35f8172c6d7fd3f36d85c686a2dea6f07f9695561000000000000000000000000000000000000000000000000000000008a02952fda02b9dafbfdf677ce9c3ae29cfe0ee0255319db90da6ae9062407da851ea0910000000000000000000000000000000000000000000000000000035ae15f67e0e98ed3efaa8fbcc6ce4cec2aa0333d4c9e2eb2294587c1dad96deeff9d800cec0000000000000000000000000000000000000000000000000000035ae15f67e06b31959cf77a38fb2f32293e4ef999cf2f3a2dfcef11f8b3e733efded1d9804a000000000000000000000000000000000000000000000000000000000000383cc688711fc0063ab0b0b354558d495b2872f707b3cc77770f949ff28f16e196c4000000000000000000000000000000000000000000000000000000008a061af32fce53d2ed05ae6c93f6609696b9110552701ca48d0af15146442d11e0f08d5700000000000000000000000000000000000000000000007423491c5aa4a881016da9126e31bbc4d2b8d71968efc219c372c28ab5c8d501f3ac96f420f6d78efb000000000000000000000000000000000000000000000000000000000000383cbae3dd70bc82a2ecec583970cc0af678e5961f9ec3fbd11f263539263edb2807000000000000000000000000000000000000000000000000000000000290cb03c667fa7f8c471f96615acaeae2c1dbcbff7ac37946f198ab010c75c40c1a36190000000000000000000000006ac625d107ceee595a35c464ed4c113cdbf20fede103eca9ee6ed87e24519f6722db2d0ce8fa7b995d30d2c2c5151a83f12ca3fd0000000000000000000000000000000000000000000000000000035ae27c9ab3fb081bb525c9c66877c9461cd0317b3e0ae7494e69a21cd83f0b6f5c483a84500000000000000000000000000000000000000000000000000000000283188669146c97aaab58459120487370ff4961138d852783f7d8a7a46cbcf005e064f2e700000000000000000000000000000000000000000000000000000035ea6287166956094754d6e421dae05ce6cf31c06600af75ba8337e74337b8b976eaecf847000000000000000000000000000000000000000000000074234e107f0108680813980fc2eac42418188c5687f5cc1e5bcf0ead80cae9e3a5d573d6cc2928d70800000000000000000000000000000000000000000000000000000000000000010010d44d3c8c7db2ef26a554d9aac519ac32f96ea1c17eeca8fcc5a4c5de8e210000000000000000000000000000000000000000000000000000035ae27c9ab3528f7e932cf1b5dac72ac6dc4067626ec848e8112f2b6fac0be0b77ed5e6e1e200000000000000000000000028a48ed0fffed9c574f35ea87ae50ef50cbe18b3435c2e53eae09f13265045b7b6220f3e310c7f025f02520db68c7fade2a0b802000000000000000000000000000000000000000000000000000000000290cb03a903f52d9b77df3d67471ae48c4846c9d25e8b97cd01d05e54efac9dd7335cb0000000000000000000000000000000000000000000000000000000000000383c1328dabbbd8db77f42fa541437e9bd11a7e7adf7a00a224ef1694ac64b7233c0000000000000000000000000000000000000000000000074234a7a33f70108d254962eaeeb85132e75ded7014b12a469deb3eeddf6067fc1eb69657c81c68bc600000000000000000000000000000000000000000000000000000000000000011c4b284244d50c12ac7617fb10f178b20cb112e54ba2598b4be40cf1202779a2000000000000000000000000000000000000000000000000000000000000006c4d7241644c801884f92bb9e3710b7f939a80845c7646bf95fbb64d3edb3b66b3000000000000000000000000a82749bcb138d6c0ae8e096e26c63ef42e74aef8b74de169571690d2cc90c666a1b89483ebfcdcd04f1af53a731b358200875b1a000000000000000000000000000000000000000000000000000000008a02952f7452372bcf78ca1b3440a6d97a7034a630d01e609e86c4fa605d125850dc4864000000000000000000000000000000000000000000000074234a7a33f70108d29168feeafcff9494f3b1cbb1a8ec8132d4c6d2d8373d1f5e9d376e33715c5cea0000000000000000000000000000000000000000000000000000ed935bbbe49acf4362fbe525d2657a21a61d85ff292cf5a2f6377467546af770c03005ec701100000000000000000000000000000000000000000000000000142fbfb79d2000e14e6a2beb6d6d07232ab12875d19eb9c2a5d5470ddc4e305925d203b246fe4b000000000000000000000000000000000000000000000000001476b081e800005f4a8dbf39f8b8d868041c8b75bda68ca51be057ece3cfb51c01c2d6ef2ef9250000000000000000000000000000000000000000000000000449ab4dc788000082a84780b4115e37ab86330a79a539e790da6ff8a6a5fe772cb47945abcf7bfc000000000000000000000000000000000000000000000000008f3ed38d580000d277388966326d8597752e47678aaf1d7d08e060c526adeca99d6f8dac1df2180000000000000000000000000000000000000000000000000008dac8663f6300ebed5cfb3eaea4e5c2516abec2b05d1e84b0e43f9efa1c97b5088656d4fac7f30000000000000000000000000000000000000000000000000731ba0dab90000033a858b6016f3327d8a2c78c10731712fe2a7d2cd2272fdeafefd173f2eb07f900000000000000000000000000000000000000000000000006646ee6ed377000943bf09f3a3027407e1be6a435ed90ed0a24d4acaf296e9fecaa79a7f7d623a70000000000000000000000000000000000000000000000000731ba0dab9000005a18065086a11de6a3fc65ddbf55a096a5dd884e4c5e65174833bc1dbdf6411600000000000000000000000000000000000000000000000006646ee6ed37700032b6346140eeafa17a38dbd1e82032f3a49e2135e0c48d2c73246b4f469118c60000000000000000000000000000000000000000000000000265e8af39300000b29ee8ea349b9298d9679000141a2c6ea2edec33e21c50b99c0c49640120573a000000000000000000000000000000000000000000000000001476b081e800003afa1dcd1e0b897312b05b3182004d9fb439da940bfd93871b6e167870d40c4f0000000000000000000000000000000000000000000000000066517289880000f24b6f9b8cd4aa4260ce8216513f41a41a6ddb3a785c3d59e17153da29e0b26f0000000000000000000000000000000000000000000000000031495668e1a08078203473274e6d079068ec03088b6994204a6f2c28aaf10e192394980b605f9e000000000000000000000000000000000000000000000000001476b081e80000377029ac0f40bc3b1fb8417c3b1913749f5c1f58029acbc87446e9aeba35a7f3000000000000000000000000000000000000000000000000001476b081e800003c5c66ffd2f5128c82c7f7ff3cc0d6a3f49f19c328c5f8c5b21c41fbd5701db40000000000000000000000000000000000000000000000000479f69c6ac0000003fe90a39af0b7f5090fd7418eebc3b568e7c1f8badaa8e0da026aaae0c1b23800000000000000000000000000000000000000000000000005728a99f65ca7007837d59fec13acb5a73d786a5f5087c6a449d0a34e678add10ffbdc4a35ffd5200000000000000000000000000000000000000000000000005728a99f65ca7009c8d3599ff77c190dd0f59ed2962f67e104463451daacc56ea5a3d50ab33d6c200000000000000000000000000000000000000000000000000e1c6c67f3680002047452c9bc170aab4073d31fd58aafabded2cdcaabcb99a7564d56962e8ea890000000000000000000000000000000000000000000000000449ab4dc7880000182734d5d350064423409f67be643cd08466afd6cf174820734e03f5caf2ad6c00000000000000000000000000000000000000000000000000044280bc34a200a93d4cf2f8f0ddc95882b7d198d61f03d4e70c5cbbc1d2040b7ff4549688049b00000000000000000000000000000000000000000000000000312edcdc2c5100a541f02f506acb32ed4b9074a05395406046a83585aff3567afaac02757b6ae500000000000000000000000000000000000000000000000007fe5cf2bea00000e7b141148e5bcd950e1a9cc0545034bf21a962b8432cb83026bfab4ee3e585a1000000000000000000000000000000000000000000000000001476b081e800007b62333ce03a624fcaac16d1210083d663ff4b27f476bf47cdb91580f941ea7b00000000000000000000000000000000000000000000000000142fbfb79d20006990bcdf5c403ac8af74286be8f9ba4bb1540da89e658dcc1c90689a6cde4fb40000000000000000000000000000000000000000000000011494299bc3a00000f0871a4bc721ed54fa123eaf0ec06b03d4d1f7f06c83dde6e544b5ab39e40a5c00000000000000000000000000000000000000000000000029f767fa68c80000e4e1bb0616cee12764f6d1b66a4a7c511e88619cc61ffc3aa0532607ff826b52000000000000000000000000000000000000000000000000048333c2dbc83080daeb764c4084fc16dff9e9daf2effdf303810613b4fb88eef33bf7db01eea89f000000000000000000000000000000000000000000000000006a4d9d45324200e2341fe2c4e83fd3f4baf6d20168fd2a515e643cb0ce6b5a34b796c78ebd62ee00000000000000000000000000000000000000000000000003470244ce280000ed46c467b5d42fec63cf77408f111729f160c582d80c12f7d2e343f69653c1e700000000000000000000000000000000000000000000000028c473a2cc300000846f3b8c38b8656c5c9dd17e75e800d8d2bce928d63358d0309d789f6fc724840000000000000000000000000000000000000000000000000265e8af39300000e85a72b3c98d16256b46fbdd6c2b38dffa7e2e65204dadb19d4e7c3ae580c4f20000000000000000000000000000000000000000000000000019945ca2620000e07b55ae6fa7ac8a7f1479fdcafdd658847307de69fa931edc08ffc3026d68b20000000000000000000000000000000000000000000000000479f69c6ac00000823863af36c5b192269ff2ea09de9c84a64228226222337440732a6f7c0948700000000000000000000000000000000000000000000000000066517289880000d0c6e07f96489aad02aa67d09b63225ac0a45804e52c3a5a65d0c771a65d9a6600000000000000000000000000000000000000000000000096eb55be0f000000a4237428331a440d2d2bc6b8157d43133c63c82423e1c637ecbd2672238abf6000000000000000000000000000000000000000000000000029f767fa68c800009600cfffdae22bd61f13511f6a6f025720d350b6da5d7b500c93829af3193233000000000000000000000000000000000000000000000000001476b081e800007b6b6b008272524289c98babc54251d67cfca6e47cdcec4cf5abc7356fc71e1200000000000000000000000000000000000000000000000007fe5cf2bea000009a606210db5a3aec4efb20472f3d94397705300b4a5de03d7cadd6f0e654610500000000000000000000000000000000000000000000000003716da573a3c5006b651e57ce215f28d11d41d94c5b2615389b991f5a0dbd4b6ac7e5b183b29e240000000000000000000000000000000000000000000000000ffcb9e57d40000004838a665bd8e93f060926a6f3dcbf4c09dd3d67c7d413264613c1b2f0fa761100000000000000000000000000000000000000000000000010ab850928330000a40eccac501f866cb12531573f6443bb00e2ef8e2254b22153ae77ee2c42f0a6000000000000000000000000000000000000000000000000001476b081e800004ac7dcf01022b60ce4561921f6e4ee89c3fd22a65cc8811b666be8fa853f6691000000000000000000000000000000000000000000000000001476b081e80000895b9525e6c5572f2db651167c2648e8445055ddceb8a52d63f1f8b854831653000000000000000000000000000000000000000000000000006a4d9d45324200d6f9272f823d460bf5b9155a61e59bf93eb7eaa3a779bd9e8d8f4dfc612bd48000000000000000000000000000000000000000000000000000cca2e5131000004fe5fedd65c9adecaeb35a6fe8beed34fd5611944b444193196dfb8e19f1532400000000000000000000000000000000000000000000000003716da573a3c500d610b76d137f82b07231cc32f3b3b546c7bbff3ef87cc85c6c8a0f8bd97dae00000000000000000000000000000000000000000000000000000a3b5840f40000893bf48adb1c25d46e6702fcc1c37cd0f7d91e6ebf3acbc14dee3d4d769a0e9300000000000000000000000000000000000000000000000003470244ce280000382cda9a5a521c7b3d4da194c3d21e2231866866192b8ac5de76c49a4af7e6d900000000000000000000000000000000000000000000000000044280bc34a2008a0eff893c6295616f3929ad1436ad95275964690d20de4f3ef422d8fdbdf84f000000000000000000000000000000000000000000000000008f3ed38d5800006c1a65030553cb64bcf15ec4a427d28edd208cb18ff1b48800bbcf17beb6e32400000000000000000000000000000000000000000000000000e1c6c67f36800022b86b0674647d5fbd6cda793ed6271f029423dff7a53bc6505690b3304a24ef00000000000000000000000000000000000000000000000028c473a2cc3000002d66c9884c3742512e59ef4a94b10c7e3b945929cfce46f1842f4d22376e2dc30000000000000000000000000000000000000000000000000008dac8663f63009832334c45f37d42d77c3ee43b69a51ef3fd784fefe7bec752bf38eada8b7742000000000000000000000000000000000000000000000000000a3b5840f40000ab4f36254d622ebae64d8115f77c2b5c186d1dd52a872799fa463e602ffc486900000000000000000000000000000000000000000000000002ea11e32ad500001c35181f375d81b83d2a584e6145ad8f8599d0a15d85f0408bf3f7b7bcd4309a00000000000000000000000000000000000000000000000096eb55be0f000000bb4173746ba713b30b708edd5a767093e58ba7552e35fb43562eeae5814a668700000000000000000000000000000000000000000000000000312edcdc2c5100ef6a01e04793478e5126665710382ea7d71dd5293cad59463b2f57b8b3817eaf00000000000000000000000000000000000000000000000010ab850928330000edc977314640762057dcd9fcec1f985221a1d09ea8b26066ad8f03bc6049b5ca0000000000000000000000000000000000000000000000011494299bc3a00000571ad3df0993c393824406d6206e1e1e2016164f4e260b493cf3b94eebcd85810000000000000000000000000000000000000000000000000031495668e1a080b192b4354f71c264720b5922994fb620790efc3613ec8ee769b8711351e0e9ae00000000000000000000000000000000000000000000000000cca2e51310000092ff94fd20220ec44975163aef565f9639fc951296a66b5571f3b8d5e2e9d739000000000000000000000000000000000000000000000000048333c2dbc830801fe3316e2f828e3a2731d75bb786a10cfb57b2ac6f1b6c4453fcf4094a9b1e5400000000000000000000000000000000000000000000000002ea11e32ad50000ea12a8a476441d437758dd76042c83c9812551378f1e332687bdbda4bff8b73f0000000000000000000000000000000000000000000000000ffcb9e57d4000001894503da320552e38151748fa7e092e2a20bcfb865d22b96f766a35c1537d370000000000000000000000000000000000000000000000000019945ca2620000cc63dd7ff2c9dba450953d981bac9b211204aadad5ed2a095da35a099ddda812000000020000000064363dfbcc7d0e5411dc82f9302e8ed2453d908bbc8670f38bbef1adad6f4a7c3933f57ce6f4655272b20da9f57acbb0760bd80fbcbe82b5000000000000000064356eb0f5912370c56c12ab5a074bfb4bc09f65ce20a78a1675c41371fd82beb25cdbfb09d1768cee0607aa9dffd7432fc81f962c5e1f380000000000000000000000000000000000000000000000000000000000000001897011b2ec9ee7d7ccab48b833d89e8f69fcefb2ce84092445de06e8a620653b00000000000000000000000000000000000000000000000000000000000000013542e7ea54ebbb98bec3c50987f3b59c88d05bca29c8be88870a141662757fe8000000020000000064363dfbbbc0e91ab31d766c649f4a958d70cbc6cac718781a8a0b8d4d73354bf2f1abf110590a06ed6fa81e549455ba4d04c149cce539d8000000000000000000000000000000000000000000000000000000000000000150f88c7890afaf00d847789882225e5375549b744218183ccee10cf3a55eb522000000000000000000000000000000000000000000000000000000000000014ce846dc707bfd4b3ca500e64a6f2a28cc3b16854d9b21e2eb39e16275914c566d00000000000000000000000047377e35ebf039fda09655a528e78de3d918c54ed7192783d73f1c4155e7a9ea3c727cfb57bfec0d1ba07f1520bf02bda65160ee0000000000000000000000000000000000000000000000000000000000a7d8c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bea4000004c400000000003cab3f000000000000000000000000000000000000000000000000000000000000000c0000000000752f90000000000000000000000000000000000000000000000000000000000000000f0000000000003567000000000000000000000000000000000000000000000000000000000000bac80000000000825f3600000000000000000000000000000000000000000000000000000000000000020000000000375275000000000000000000000000000000000000000000000000000000000000000c0000000000824ca2000000000000000000000000000000000000000000000000000000000000000d0000000000226cda000000000000000000000000000000000000000000000000000000000000000d000000000082641a00000000000000000000000000000000000000000000000000000000000000030000000000825cd2000000000000000000000000000000000000000000000000000000000000000500000000008248220000000000000000000000000000000000000000000000000000000000000008000000000000501500000000000000000000000000000000000000000000000000000000000000bf000000000022fecf000000000000000000000000000000000000000000000000000000000000000700000000008255ad0000000000000000000000000000000000000000000000000000000000000006000000000082584b00000000000000000000000000000000000000000000000000000000000000100000000000034014000000000000000000000000000000000000000000000000000000000000001200000000008211df0000000000000000000000000000000000000000000000000000000000000021000000000052983a0000000000000000000000000000000000000000000000000000000000000020000000000081dbb1000000000000000000000000000000000000000000000000000000000000000c000000000082641c0000000000000000000000000000000000000000000000000000000000000003000000000024e9c8000000000000000000000000000000000000000000000000000000000000001c000000000081dbb2000000000000000000000000000000000000000000000000000000000000000a000000000082584d000000000000000000000000000000000000000000000000000000000000000200000000003e25bb000000000000000000000000000000000000000000000000000000000000001300000000005c5c890000000000000000000000000000000000000000000000000000000000000030000000000058fc3100000000000000000000000000000000000000000000000000000000000000100000000000004125000000000000000000000000000000000000000000000000000000000000000700000000001b75530000000000000000000000000000000000000000000000000000000000000053000000000035940f0000000000000000000000000000000000000000000000000000000000000044000000000019d516000000000000000000000000000000000000000000000000000000000000001f000000000025f1f000000000000000000000000000000000000000000000000000000000000000250000000000825a88000000000000000000000000000000000000000000000000000000000000000e000000000026ea620000000000000000000000000000000000000000000000000000000000000036000000000081bdc0000000000000000000000000000000000000000000000000000000000000000300000000000b098c000000000000000000000000000000000000000000000000000000000000001400000000002e4e1f000000000000000000000000000000000000000000000000000000000000000a000000000043bf150000000000000000000000000000000000000000000000000000000000000006000000000060d74a000000000000000000000000000000000000000000000000000000000000001a00000000004bfdd300000000000000000000000000000000000000000000000000000000000000120000000000822ec200000000000000000000000000000000000000000000000000000000000000070000000000715d4f000000000000000000000000000000000000000000000000000000000000000f0000000000639380000000000000000000000000000000000000000000000000000000000000000d0000000000025e6b000000000000000000000000000000000000000000000000000000000000000f00000000007b55d300000000000000000000000000000000000000000000000000000000000000070000000000028ea0000000000000000000000000000000000000000000000000000000000000006e000000000006b1cc000000000000000000000000000000000000000000000000000000000000003f000000000014436a000000000000000000000000000000000000000000000000000000000000002400000000005e9f5400000000000000000000000000000000000000000000000000000000000000100000000000756bc40000000000000000000000000000000000000000000000000000000000000008000000000066183c000000000000000000000000000000000000000000000000000000000000001b00000000004e8701000000000000000000000000000000000000000000000000000000000000000a00000000006d41ea000000000000000000000000000000000000000000000000000000000000001900000000007d217500000000000000000000000000000000000000000000000000000000000000100000000000824ca7000000000000000000000000000000000000000000000000000000000000000d00000000002944bf0000000000000000000000000000000000000000000000000000000000000016000000000023114b000000000000000000000000000000000000000000000000000000000000000900000000002e485d000000000000000000000000000000000000000000000000000000000000000a0000000000230362000000000000000000000000000000000000000000000000000000000000000800000000004e769300000000000000000000000000000000000000000000000000000000000000080000000000213e9f000000000000000000000000000000000000000000000000000000000000001f000000000079a5660000000000000000000000000000000000000000000000000000000000000006000000000081e3de000000000000000000000000000000000000000000000000000000000000000f00000000002313b5000000000000000000000000000000000000000000000000000000000000000300000000000e6229000000000000000000000000000000000000000000000000000000000000002b0000000000501592000000000000000000000000000000000000000000000000000000000000000d000000000012d5df00000000000000000000000000000000000000000000000000000000000000150000000000145df70000000000000000000000000000000000000000000000000000000000000016000000000064ec090000000000000000000000000000000000000000000000000000000000000007000000000081b162000000000000000000000000000000000000000000000000000000000000000600000000008233bf0000000000000000000000000000000000000000000000000000000000000009000000000025724e000000000000000000000000000000000000000000000000000000000000000600000000003e824d00000000000000000000000000000000000000000000000000000000000000160000000000825cda0000000000000000000000000000000000000000000000000000000000000004000000000008f4a5000000000000000000000000000000000000000000000000000000000000003a000000000032ddbb00000000000000000000000000000000000000000000000000000000000000070000000000825853000000000000000000000000000000000000000000000000000000000000001300000000006340d600000000000000000000000000000000000000000000000000000000000000110000000000823ada0000000000000000000000000000000000000000000000000000000000000006000000000062c15b000000000000000000000000000000000000000000000000000000000000006b0000000000232c35000000000000000000000000000000000000000000000000000000000000000a000000000082641f000000000000000000000000000000000000000000000000000000000000000600000000007a08de000000000000000000000000000000000000000000000000000000000000000c0000000000124c20000000000000000000000000000000000000000000000000000000000000002a000000000082642000000000000000000000000000000000000000000000000000000000000000020000000000826421000000000000000000000000000000000000000000000000000000000000000200000000008264220000000000000000000000000000000000000000000000000000000000000006000000000057f03a000000000000000000000000000000000000000000000000000000000000001200000000005ae7d200000000000000000000000000000000000000000000000000000000000000030000000000077b09000000000000000000000000000000000000000000000000000000000000004f000000000011dbb00000000000000000000000000000000000000000000000000000000000000036000000000002bc0300000000000000000000000000000000000000000000000000000000000000cb000000000026ffe7000000000000000000000000000000000000000000000000000000000000001a0000000000574f070000000000000000000000000000000000000000000000000000000000000020000000000082458c0000000000000000000000000000000000000000000000000000000000000005000000000080b128000000000000000000000000000000000000000000000000000000000000000b0000000000825cdd00000000000000000000000000000000000000000000000000000000000000090000000000536799000000000000000000000000000000000000000000000000000000000000003f0000000000296721000000000000000000000000000000000000000000000000000000000000000e00000000005bc3280000000000000000000000000000000000000000000000000000000000000004000000000082642300000000000000000000000000000000000000000000000000000000000000040000000000825cde000000000000000000000000000000000000000000000000000000000000000f00000000007fb65d00000000000000000000000000000000000000000000000000000000000000130000000000301cb4000000000000000000000000000000000000000000000000000000000000000700000000007f980a000000000000000000000000000000000000000000000000000000000000001700000000005dc4e6000000000000000000000000000000000000000000000000000000000000000a00000000007b5805000000000000000000000000000000000000000000000000000000000000000700000000002d913a0000000000000000000000000000000000000000000000000000000000000011000000000009542200000000000000000000000000000001000000000000000000000000000000280000000000815fa0000000000000000000000000000000000000000000000000000000000000005d00000000001268ea00000000000000000000000000000000000000000000000000000000000000070000000000826192000000000000000000000000000000000000000000000000000000000000000500000000000163cf000000000000000000000000000000000000000000000000000000000000003c00000000006b3814000000000000000000000000000000000000000000000000000000000000000400000000001f4ede000000000000000000000000000000000000000000000000000000000000001900000000004bad69000000000000000000000000000000000000000000000000000000000000004b0000000000774216000000000000000000000000000000000000000000000000000000000000002600000000000043ae0000000000000000000000000000000000000000000000000000000000000022000000000000c6e0000000000000000000000000000000000000000000000000000000000000004400000000000a4683000000000000000000000000000000000000000000000000000000000000000b0000000000001fa30000000000000000000000000000000000000000000000000000000000026e6d00000000008207be000000000000000000000000000000000000000000000000000000000000000500000000007cb86e00000000000000000000000000000000000000000000000000000000000000040000000000825ce000000000000000000000000000000000000000000000000000000000000000030000000000826195000000000000000000000000000000000000000000000000000000000000000900000000004a0c4e000000000000000000000000000000000000000000000000000000000000000a00000000002255dc0000000000000000000000000000000000000000000000000000000000000013000000000006964d00000000000000000000000000000000000000000000000000000000000000ea00000000001ff13900000000000000000000000000000000000000000000000000000000000000170000000000529d40000000000000000000000000000000000000000000000000000000000000000a00000000007a78f2000000000000000000000000000000000000000000000000000000000000000f000000000012d5e800000000000000000000000000000000000000000000000000000000000000130000000000826197000000000000000000000000000000000000000000000000000000000000000500000000002702b600000000000000000000000000000000000000000000000000000000000000120000000000021d8a000000000000000000000000000000000000000000000000000000000000005a000000000032163f000000000000000000000000000000000000000000000000000000000000001f000000000014464500000000000000000000000000000000000000000000000000000000000000180000000000010084000000000000000000000000000000000000000000000000000000000000003800000000005634d5000000000000000000000000000000000000000000000000000000000000000d00000000007a07870000000000000000000000000000000000000000000000000000000000000007000000000076e2b70000000000000000000000000000000000000000000000000000000000000004000000000082514f00000000000000000000000000000000000000000000000000000000000000110000000000126a47000000000000000000000000000000000000000000000000000000000000000600000000002c3ca6000000000000000000000000000000000000000000000000000000000000003500000000005d4e95000000000000000000000000000000000000000000000000000000000000003b000000000082585b000000000000000000000000000000000000000000000000000000000000000800000000005e7cff0000000000000000000000000000000000000000000000000000000000000007000000000000502a00000000000000000000000000000000000000000000000000000000000000ba000000000052d2e5000000000000000000000000000000000000000000000000000000000000000d00000000001087e40000000000000000000000000000000000000000000000000000000000000051000000000076d3e7000000000000000000000000000000000000000000000000000000000000000c0000000000826198000000000000000000000000000000000000000000000000000000000000000400000000005c89a60000000000000000000000000000000000000000000000000000000000000010000000000067d9a0000000000000000000000000000000000000000000000000000000000000002a00000000004cf32e000000000000000000000000000000000000000000000000000000000000000400000000004230fb00000000000000000000000000000000000000000000000000000000000000280000000000824316000000000000000000000000000000000000000000000000000000000000001c00000000005f856f000000000000000000000000000000030000000000000000000000000000059f00000000003512c6000000000000000000000000000000000000000000000000000000000000000f000000000082619a0000000000000000000000000000000000000000000000000000000000000003000000000082619b00000000000000000000000000000000000000000000000000000000000000060000000000824cb1000000000000000000000000000000000000000000000000000000000000000c00000000005de9fe000000000000000000000000000000000000000000000000000000000000000a000000000029e881000000000000000000000000000000000000000000000000000000000000001700000000008253b200000000000000000000000000000000000000000000000000000000000000050000000000824f03000000000000000000000000000000000000000000000000000000000000000e00000000003b2bbf000000000000000000000000000000000000000000000000000000000000003200000000006395b90000000000000000000000000000000000000000000000000000000000000039000000000022908e000000000000000000000000000000000000000000000000000000000000000800000000004b08f6000000000000000000000000000000000000000000000000000000000000000a0000000000190376000000000000000000000000000000000000000000000000000000000000000a0000000000099812000000000000000000000000000000000000000000000000000000000000004b00000000000351f5000000000000000000000000000000000000000000000000000000000000001f00000000006d0d32000000000000000000000000000000000000000000000000000000000000000500000000007dc80200000000000000000000000000000000000000000000000000000000000000050000000000108c760000000000000000000000000000000000000000000000000000000000000020000000000082482d00000000000000000000000000000000000000000000000000000000000000070000000000001fa4000000000000000000000000000000000000000000000000000000000002751200000000000c68b80000000000000000000000000000000000000000000000000000000000000030000000000082585e000000000000000000000000000000000000000000000000000000000000000b00000000002aaece00000000000000000000000000000000000000000000000000000000000000160000000000131549000000000000000000000000000000000000000000000000000000000000000d0000000000019a0f00000000000000000000000000000000000000000000000000000000000000330000000000825a9d00000000000000000000000000000000000000000000000000000000000000060000000000825f430000000000000000000000000000000000000000000000000000000000000003000000000048a952000000000000000000000000000000000000000000000000000000000000001600000000007e18e200000000000000000000000000000000000000000000000000000000000000160000000000822c6a000000000000000000000000000000000000000000000000000000000000000a0000000000126a4f0000000000000000000000000000000000000000000000000000000000000006000000000082619c000000000000000000000000000000000000000000000000000000000000000400000000002e4b5000000000000000000000000000000000000000000000000000000000000000200000000000822a3d0000000000000000000000000000000000000000000000000000000000000009000000000081bb7c000000000000000000000000000000000000000000000000000000000000000a000000000082215e000000000000000000000000000000000000000000000000000000000000000400000000000c3fcb0000000000000000000000000000000000000000000000000000000000000067000000000081e1ce000000000000000000000000000000000000000000000000000000000000000f0000000000824f08000000000000000000000000000000000000000000000000000000000000000500000000007b66070000000000000000000000000000000000000000000000000000000000000009000000000047c716000000000000000000000000000000000000000000000000000000000000001a000000000000252700000000000000000000000000000000000000000000000000000000000058fe000000000081e412000000000000000000000000000000000000000000000000000000000000001000000000008240ae000000000000000000000000000000000000000000000000000000000000000f0000000000126a50000000000000000000000000000000000000000000000000000000000000000600000000006b1cd0000000000000000000000000000000000000000000000000000000000000000d000000000075695b0000000000000000000000000000000000000000000000000000000000000022000000000011dde60000000000000000000000000000000000000000000000000000000000000008000000000003052b000000000000000000000000000000000000000000000000000000000000002100000000007ce2bc000000000000000000000000000000000000000000000000000000000000000400000000001a540c000000000000000000000000000000000000000000000000000000000000000d00000000002cc4bf000000000000000000000000000000000000000000000000000000000000001600000000002f029d0000000000000000000000000000000000000000000000000000000000000011000000000008bfae000000000000000000000000000000000000000000000000000000000000008e000000000000d0cf000000000000000000000000000000000000000000000000000000000000004b00000000007a078b000000000000000000000000000000000000000000000000000000000000000700000000007e2822000000000000000000000000000000000000000000000000000000000000000f00000000005779bc000000000000000000000000000000000000000000000000000000000000001900000000002f9b44000000000000000000000000000000000000000000000000000000000000000800000000002db242000000000000000000000000000000000000000000000000000000000000004d000000000003f44c000000000000000000000000000000000000000000000000000000000000002300000000005de2b4000000000000000000000000000000000000000000000000000000000000000f00000000008261a0000000000000000000000000000000000000000000000000000000000000000800000000004b27a800000000000000000000000000000000000000000000000000000000000000210000000000006f740000000000000000000000000000000000000000000000000000000000000055000000000075f4ce0000000000000000000000000000000000000000000000000000000000000007000000000043bb5300000000000000000000000000000000000000000000000000000000000002280000000000820a5f000000000000000000000000000000000000000000000000000000000000000700000000004e3f9c00000000000000000000000000000000000000000000000000000000000000090000000000825ce600000000000000000000000000000000000000000000000000000000000000090000000000575d75000000000000000000000000000000000000000000000000000000000000000c000000000028acc4000000000000000000000000000000000000000000000000000000000000003500000000008253b40000000000000000000000000000000000000000000000000000000000000013000000000071857c0000000000000000000000000000000000000000000000000000000000000004000000000037d7e7000000000000000000000000000000000000000000000000000000000000000600000000007b30a50000000000000000000000000000000000000000000000000000000000000002000000000039edae000000000000000000000000000000000000000000000000000000000000000500000000005bfaea000000000000000000000000000000000000000000000000000000000000000700000000002aaed300000000000000000000000000000000000000000000000000000000000000180000000000513a09000000000000000000000000000000000000000000000000000000000000000b00000000007b55e20000000000000000000000000000000000000000000000000000000000000007000000000082515a00000000000000000000000000000000000000000000000000000000000000130000000000825aa4000000000000000000000000000000000000000000000000000000000000000d0000000000824cb4000000000000000000000000000000000000000000000000000000000000000d000000000081e41f000000000000000000000000000000000000000000000000000000000000000f0000000000251142000000000000000000000000000000000000000000000000000000000000003600000000000793e10000000000000000000000000000000000000000000000000000000000004a0c00000000008261a300000000000000000000000000000000000000000000000000000000000000040000000000059d2c00000000000000000000000000000000000000000000000000000000000000090000000000825ce700000000000000000000000000000000000000000000000000000000000000070000000000821ba3000000000000000000000000000000000000000000000000000000000000000900000000006dae180000000000000000000000000000000000000000000000000000000000000021000000000000038d0000000000000000000000000000000000000000000000000000000000005296000000000052f5bc000000000000000000000000000000000000000000000000000000000000001000000000000d932d000000000000000000000000000000000000000000000000000000000000001900000000008261a40000000000000000000000000000000000000000000000000000000000000005000000000001315200000000000000000000000000000000000000000000000000000000000000230000000000210d5e000000000000000000000000000000000000000000000000000000000000000200000000008255c6000000000000000000000000000000000000000000000000000000000000000a00000000002dcaf8000000000000000000000000000000000000000000000000000000000000000300000000008255c7000000000000000000000000000000000000000000000000000000000000001200000000008261a50000000000000000000000000000000000000000000000000000000000000006000000000045ef66000000000000000000000000000000000000000000000000000000000000000a00000000003df8b2000000000000000000000000000000000000000000000000000000000000000c00000000007f7a72000000000000000000000000000000000000000000000000000000000000001900000000007a078f0000000000000000000000000000000000000000000000000000000000000007000000000014e56b000000000000000000000000000000000000000000000000000000000000002000000000001e99580000000000000000000000000000000000000000000000000000000000000021000000000055b5eb000000000000000000000000000000000000000000000000000000000000000300000000006927b000000000000000000000000000000000000000000000000000000000000000040000000000821202000000000000000000000000000000000000000000000000000000000000000300000000000412a800000000000000000000000000000000000000000000000000000000000000440000000000824cb6000000000000000000000000000000000000000000000000000000000000000d00000000000b06c90000000000000000000000000000000000000000000000000000000000000014000000000043775e000000000000000000000000000000000000000000000000000000000000000d0000000000825f4d000000000000000000000000000000000000000000000000000000000000000500000000001df736000000000000000000000000000000000000000000000000000000000000002800000000002ca8b5000000000000000000000000000000000000000000000000000000000000001000000000000a774c0000000000000000000000000000000000000000000000000000000000000034000000000000002f000000000000000000000000000000000000000000000dd5c05263e62cd67458000000000020dfe90000000000000000000000000000000000000000000000000289fef3a8e5c9a1000000000075244400000000000000000000000000000000000000000000000000261710b55d180a00000000000026a60000000000000000000000000000000000000000000000000c4973000968ba9200000000007e2d34000000000000000000000000000000000000000000000000001b7fc42d9f37ae000000000010fa71000000000000000000000000000000000000000000000000003f2e11b22ff1a50000000000374dc300000000000000000000000000000000000000000000000000521e5d257ca3e00000000000824329000000000000000000000000000000000000000000000000004095d45c5a584b000000000022658c0000000000000000000000000000000000000000000000000048b89f4fb1932400000000008261a70000000000000000000000000000000000000000000000000299dfbba42fe8620000000000825aaa0000000000000000000000000000000000000000000000000146e8a1b746183c000000000082459e0000000000000000000000000000000000000000000000000003c7d6491a6ae40000000000004848000000000000000000000000000000000000000000000000000bbf291a18cbf2000000000022ff070000000000000000000000000000000000000000000000000732c087bcebb47b00000000007d94880000000000000000000000000000000000000000000000000054af43f880efa4000000000081fb1800000000000000000000000000000000000000000000000000791dbe8698d60d0000000000032d5000000000000000000000000000000000000000000000000000de81390662505600000000005cb57e000000000000000000000000000000000000000000000000018b591a84c813d8000000000052939c000000000000000000000000000000000000000000000000006ed65bfb18c8f500000000008264260000000000000000000000000000000000000000000000000001138837d67057000000000081d20c00000000000000000000000000000000000000000000000006f5abd5f3a124740000000000323a900000000000000000000000000000000000000000000000000299307caa12730000000000008261aa000000000000000000000000000000000000000000000000044fa71ecf38709c000000000024bf26000000000000000000000000000000000000000000000000006f77cb3a947e35000000000081d20d0000000000000000000000000000000000000000000000000023f574499af807000000000060578f000000000000000000000000000000000000000000000000005c0e5447ade21700000000001a112f000000000000000000000000000000000000000000000000004c23f55466404a00000000005c4c3a00000000000000000000000000000000000000000000000000f8c73e6d5ec6b8000000000058e4aa000000000000000000000000000000000000000000000000001c8acb6935f7ce0000000000042cc3000000000000000000000000000000000000000000000000005c5030c84a678500000000008225340000000000000000000000000000000000000000000000000061ace89a58a2d00000000000003f000000000000000000000000000000000000000000000000000005d7c6cea0399200000000001acb6b0000000000000000000000000000000000000000000000000584ee826687c2bc0000000000358e2d00000000000000000000000000000000000000000000000003549610044d96a5000000000019d27900000000000000000000000000000000000000000000000001304c0e5e090f050000000000175b4a00000000000000000000000000000000000000000000000000f5451f3c2ccb32000000000025efb40000000000000000000000000000000000000000000000000125783ba897c365000000000081ecec00000000000000000000000000000000000000000000000000bb277d2bbd07bb000000000013880600000000000000000000000000000000000000000000000001ae58857a28e385000000000081b1750000000000000000000000000000000000000000000000000012dfeca48afd3e000000000003e9b400000000000000000000000000000000000000000000001d4139fcd0d9be67b000000000000b047600000000000000000000000000000000000000000000000003c28752fa83cef70000000000826427000000000000000000000000000000000000000000000000001cfac37692aa1600000000002e4b6c00000000000000000000000000000000000000000000000000f3ba0b4493ef8d0000000000436f8c0000000000000000000000000000000000000000000000000022d23716759080000000000060d5f50000000000000000000000000000000000000000000000000024d71c5db951f100000000004bc66b0000000000000000000000000000000000000000000000000020716415d775590000000000822c7f000000000000000000000000000000000000000000000000057292e43a9f373d0000000000714a85000000000000000000000000000000000000000000000000001f1a4490c239a7000000000068ace20000000000000000000000000000000000000000000000000079f6f87ec6383f0000000000638ef3000000000000000000000000000000000000000000000000009d8b70b32714310000000000025c730000000000000000000000000000000000000000000000000115d1b73b05749800000000007aee54000000000000000000000000000000000000000000000000001db56b86a99d80000000000061799c0000000000000000000000000000000000000000000000000ef884545c8090f40000000000002062000000000000000000000000000000000000000000000003f943784f5bc96775000000000006af6300000000000000000000000000000000000000000000000002d55ce881b73a0400000000000a0edc0000000000000000000000000000000000000000000000000001282fd6e01dca00000000005cdd4100000000000000000000000000000000000000000000000000981b0f869634310000000000753989000000000000000000000000000000000000000000000000034b48c3073476ae00000000000b94f3000000000000000000000000000000000000000000000000001337b6ddad4aaf00000000004e83210000000000000000000000000000000000000000000000000123f7cb374984eb00000000006ca7d10000000000000000000000000000000000000000000000000af71f870d7a1fc300000000007ced6e00000000000000000000000000000000000000000000000000f8284167fb5a88000000000082432c0000000000000000000000000000000000000000000000000040a714e5e67c430000000000139edb00000000000000000000000000000000000000000000000000438e0aa9b5fe6d0000000000230f090000000000000000000000000000000000000000000000000687effda6131f1f00000000002df4a4000000000000000000000000000000000000000000000000005bd3280b16224d000000000023038e00000000000000000000000000000000000000000000000006bd3150f73314ed00000000004e60540000000000000000000000000000000000000000000000000307eafbd78df55f0000000000212bec00000000000000000000000000000000000000000000000000470409151844f6000000000050911b000000000000000000000000000000000000000000000000006c6a8c03ce467500000000006c1ce5000000000000000000000000000000000000000000000000002aa3d1ca3788f6000000000081defe000000000000000000000000000000000000000000000000003709e49ff3606000000000001519f1000000000000000000000000000000000000000000000000000a0f45aa708ca9000000000000255600000000000000000000000000000000000000000000001e54b773954a7adf5e00000000000e5564000000000000000000000000000000000000000000000000000e324a4001b99c0000000000500b57000000000000000000000000000000000000000000000000019cf12461da4d20000000000012b68e000000000000000000000000000000000000000000000000001ea21508d318b6000000000009b5a1000000000000000000000000000000000000000000000000003f3e3da2a0c9c60000000000630f1f0000000000000000000000000000000000000000000000000040280f4027db54000000000082642a0000000000000000000000000000000000000000000000000001138837d67057000000000081a9870000000000000000000000000000000000000000000000000016c5533eccfd2b0000000000822ee600000000000000000000000000000000000000000000000000191a33e7b75e5a00000000002567be00000000000000000000000000000000000000000000000000e204e8fc787b98000000000000214d000000000000000000000000000000000000000000000292a6dafe2ec4c484a300000000004ecda800000000000000000000000000000000000000000000000001adc09ff8938cae00000000003e54720000000000000000000000000000000000000000000000000009dd8a44ee02c600000000007d92370000000000000000000000000000000000000000000000000021038f788d20f6000000000008ba1f00000000000000000000000000000000000000000000000003dce2989577495000000000002d33d600000000000000000000000000000000000000000000000000239e0ff1773cb900000000008253cd000000000000000000000000000000000000000000000000067ff4dfa61d416c0000000000825cee000000000000000000000000000000000000000000000000017b9fe8ac20a5d7000000000082642b00000000000000000000000000000000000000000000000000ce34db63283a8800000000006339bb0000000000000000000000000000000000000000000000000221e0a8fe20ee33000000000080d221000000000000000000000000000000000000000000000000007e6265f5102c1c000000000062bf270000000000000000000000000000000000000000000000000563aefd37e2c4d40000000000007a1c0000000000000000000000000000000000000000000000120728e35fe44a9a26000000000023278d0000000000000000000000000000000000000000000000000004e6fffe7be2a300000000008255d300000000000000000000000000000000000000000000000000416bc9ed4c6d0b00000000007a057d0000000000000000000000000000000000000000000000000179f6eceb00bd2400000000001247a00000000000000000000000000000000000000000000000000016870a9b7796960000000000825ab400000000000000000000000000000000000000000000000000031f3d897e3e270000000000825ab60000000000000000000000000000000000000000000000000015dac9ae88ec500000000000821baf0000000000000000000000000000000000000000000000001c711df07561c7c4000000000082642e00000000000000000000000000000000000000000000000005779b273fe53c32000000000057eb83000000000000000000000000000000000000000000000000000054b0244cf3000000000000136c4b0000000000000000000000000000000000000000000000000bc7bd93fd1c6920000000000002111600000000000000000000000000000000000000000000000001cb45f3630910ae00000000001067e60000000000000000000000000000000000000000000000000025e722d888177e000000000002b8020000000000000000000000000000000000000000000000000eea192d5688ed4c0000000000210682000000000000000000000000000000000000000000000000001e69a1fd66405a0000000000574cfc000000000000000000000000000000000000000000000000001d01ee00793dd900000000007e68e60000000000000000000000000000000000000000000000000019e688d9801f2700000000007b6f85000000000000000000000000000000000000000000000000000523e0b2ef0cd4000000000082587a000000000000000000000000000000000000000000000000082ff988238ed6e5000000000053655e000000000000000000000000000000000000000000000000019d0cb159707c45000000000028bbfb0000000000000000000000000000000000000000000000000045acf85aa5abf80000000000459eaf000000000000000000000000000000000000000000000000000a3ba277ef03c700000000008261b400000000000000000000000000000000000000000000000000873d231eed1fcc000000000082587b0000000000000000000000000000000000000000000000000193c7025a914c010000000000046bc90000000000000000000000000000000000000000000000001b5e60a8f9be4cbc00000000007fb67a00000000000000000000000000000000000000000000000000053acfae3cef4b000000000002f28f00000000000000000000000000000000000000000000000000c632c8f0ce175b0000000000300f94000000000000000000000000000000000000000000000000000b5696c2665e9400000000007f884e00000000000000000000000000000000000000000000000000072fedb062e38000000000005d2503000000000000000000000000000000000000000000000000003bb5cf507d1ae700000000006913260000000000000000000000000000000000000000000000000012599c692b2fc000000000007aee7c000000000000000000000000000000000000000000000000001cc2e505e39a80000000000066c3e400000000000000000000000000000000000000000000000001ddbe4470b36820000000000010c4200000000000000000000000000000000000000000000000000039ac370e5dcd12000000000008f004000000000000000000000000000000000000000000000000003deca4c3db5229000000000082642f0000000000000000000000000000000000000000000000000001138837d670570000000000814f6c0000000000000000000000000000000000000000000000000086d6fadcd618790000000000125ba000000000000000000000000000000000000000000000000000518214f781843900000000000d24ef000000000000000000000000000000000000000000000000006b9f395e2cba350000000000824cc600000000000000000000000000000000000000000000000000346cc05becdede0000000000014c26000000000000000000000000000000000000000000000000003a77d1dbac4bd70000000000421d650000000000000000000000000000000000000000000000000018918507df067600000000001ee1bd000000000000000000000000000000000000000000000000001b443f2d03310000000000004b73e6000000000000000000000000000000000000000000000000000a6a2a277891b10000000000825cf30000000000000000000000000000000000000000000000004d27098c9af7f3c30000000000773e96000000000000000000000000000000000000000000000000002113428add9b8000000000000035c600000000000000000000000000000000000000000000000000155b6c409ded88000000000000c1960000000000000000000000000000000000000000000000000018c07c83ac24d5000000000002130c000000000000000000000000000000000000000000000000046f3bf1a5d7709f000000000008734f0000000000000000000000000000000000000000000000000005853c4a2073040000000000001fa50000000000000000000000000000000000000000000000047eb310d1ea4fae1400000000007b581e00000000000000000000000000000000000000000000000000558ae99f3ebe5f00000000007cb882000000000000000000000000000000000000000000000000001116854a4f7534000000000082433900000000000000000000000000000000000000000000000000190c8402fdc868000000000081f60300000000000000000000000000000000000000000000000000411e256a53f1370000000000498efe000000000000000000000000000000000000000000000000016ebcd546b147d40000000000028ab60000000000000000000000000000000000000000000000000028580e5ef1c93000000000000691ad0000000000000000000000000000000000000000000000000c9a2aec3641a8cd000000000081bde600000000000000000000000000000000000000000000000000ab20308653559000000000001ff167000000000000000000000000000000000000000000000000008fe92af19ffa8100000000000b215d000000000000000000000000000000000000000000000000004a773d8479c87c00000000004d4cf7000000000000000000000000000000000000000000000000003d5680e74baf8800000000007a6e1e000000000000000000000000000000000000000000000000004fa7a6c2dcb5c3000000000005b42d000000000000000000000000000000000000000000000000004333d8ebd1872100000000007d842e0000000000000000000000000000000000000000000000000005c6354f021954000000000013620d000000000000000000000000000000000000000000000000000b43deacff99890000000000021bfb00000000000000000000000000000000000000000000000002152a30b128a7b600000000008264310000000000000000000000000000000000000000000000000001138837d67057000000000031148300000000000000000000000000000000000000000000000000088589c07b390000000000008264320000000000000000000000000000000000000000000000000010c2faba43f98500000000001440fc000000000000000000000000000000000000000000000000020f6a8c0227ec9c000000000000f86d0000000000000000000000000000000000000000000000000001c82ee58a83350000000000563117000000000000000000000000000000000000000000000000004c092a00ec20860000000000285a98000000000000000000000000000000000000000000000000008702d0d129080400000000006b0abf0000000000000000000000000000000000000000000000000019fa67cb80061a000000000001e66200000000000000000000000000000000000000000000000000b113f3712701cb0000000000824ab1000000000000000000000000000000000000000000000000001d67c7c85b02680000000000125dcc0000000000000000000000000000000000000000000000000053bfd8dcf5159b0000000000002a3b000000000000000000000000000000000000000000000009aa621e5ca3114ea000000000002b42bf0000000000000000000000000000000000000000000000000054c8bb8a9b268600000000005d43ef000000000000000000000000000000000000000000000000017bc4b5ba09ef2f00000000008245ae00000000000000000000000000000000000000000000000000235552d025f5f100000000005e7b13000000000000000000000000000000000000000000000000000f43a2e1a353000000000000004f7e00000000000000000000000000000000000000000000000002109e20ed74c87f000000000052cb8000000000000000000000000000000000000000000000000001fffb7323b9a12300000000000313d9000000000000000000000000000000000000000000000000002b73f694d86e40000000000076c9be0000000000000000000000000000000000000000000000000002fd36a8b152280000000000825f5c00000000000000000000000000000000000000000000000000667691e20fc60f00000000005c70610000000000000000000000000000000000000000000000000071d331e35986c0000000000067c57b000000000000000000000000000000000000000000000000002cb264839f558000000000004ce6bd0000000000000000000000000000000000000000000000000002b3d23e3597550000000000422cf00000000000000000000000000000000000000000000000000017bcc54cc9c6fc0000000000823c230000000000000000000000000000000000000000000000000048bf4c3dfbbb5500000000005f3a33000000000000000000000000000000000000000000000000017e46d23503f83d00000000003510aa0000000000000000000000000000000000000000000000000014692d4340025d00000000007f6b2000000000000000000000000000000000000000000000000000056b6c9bffc57a00000000008255e4000000000000000000000000000000000000000000000000000e23e115c8c1ae000000000082433b000000000000000000000000000000000000000000000000002006318e1e4ecb00000000005d72de0000000000000000000000000000000000000000000000000029af78df0fad6d00000000002693ed00000000000000000000000000000000000000000000000000134d551c950e25000000000082643600000000000000000000000000000000000000000000000000adda50d4fb766d0000000000824f2100000000000000000000000000000000000000000000000000a95293759ad9660000000000824ab40000000000000000000000000000000000000000000000000075600edbeba87d000000000035f8c000000000000000000000000000000000000000000000000001273a0f1ee9fdb100000000006371980000000000000000000000000000000000000000000000000a1770ad54af71990000000000225e66000000000000000000000000000000000000000000000000002acf5a995db05600000000004af5ce000000000000000000000000000000000000000000000000004430b2cb531b7500000000001903a9000000000000000000000000000000000000000000000000002dc9edfbd9dc27000000000009670b00000000000000000000000000000000000000000000000000c281098d4f522300000000001fd624000000000000000000000000000000000000000000000000009d27622bf7b3f5000000000001f3c900000000000000000000000000000000000000000000000000629f9f8d079f5e00000000006951b8000000000000000000000000000000000000000000000000000cb77b0c197ee000000000008225460000000000000000000000000000000000000000000000000b1c1c14fc61bd3400000000007a66d100000000000000000000000000000000000000000000000002b4a966adc03f400000000000108825000000000000000000000000000000000000000000000000021d021f2115f687000000000073ce0f000000000000000000000000000000000000000000000000003f64a688db435b0000000000256a470000000000000000000000000000000000000000000000000182933c3c676d480000000000001e0b00000000000000000000000000000000000000000000000a685df5f30e5927060000000000823c2400000000000000000000000000000000000000000000000005d3d306a027307000000000000c65fe0000000000000000000000000000000000000000000000000075cd24502eb33c00000000008255e5000000000000000000000000000000000000000000000000515e336ed9a7f81100000000008253dc000000000000000000000000000000000000000000000000014061de709aa4e30000000000024182000000000000000000000000000000000000000000000000001ac683d1b6fd5200000000001312e400000000000000000000000000000000000000000000000000565e1d3dee59fe00000000007b4531000000000000000000000000000000000000000000000000000c2c32a512fd860000000000825cf6000000000000000000000000000000000000000000000000006309dc5ce017800000000000010cd8000000000000000000000000000000000000000000000000017863ff18a298ef00000000008258890000000000000000000000000000000000000000000000000004f257f856e9b40000000000825172000000000000000000000000000000000000000000000000000813ab87a8b08200000000004894230000000000000000000000000000000000000000000000000258ecded62853650000000000550ca900000000000000000000000000000000000000000000000000181d32ae40c03a000000000082254900000000000000000000000000000000000000000000000000610c7998c2608e0000000000125dd30000000000000000000000000000000000000000000000000053bfa73a39b9d30000000000825f5d0000000000000000000000000000000000000000000000000055341d8ab9f3a400000000002ea0c200000000000000000000000000000000000000000000000000be3ad056017d3d00000000002e42f6000000000000000000000000000000000000000000000000000317a809b48d7a000000000081f431000000000000000000000000000000000000000000000000000390686ab8109a000000000081b93200000000000000000000000000000000000000000000000000004a6b99a9d4000000000000826437000000000000000000000000000000000000000000000000005f224902d20816000000000081d962000000000000000000000000000000000000000000000000004af4f9c403bc6e00000000000c3af9000000000000000000000000000000000000000000000000005578d4cc1cae800000000000183dc10000000000000000000000000000000000000000000000000304530312b05406000000000081dbd90000000000000000000000000000000000000000000000000037d0c95703fede0000000000757521000000000000000000000000000000000000000000000000008fecc9520ffbb900000000007b650f000000000000000000000000000000000000000000000000001f76d5522f570b000000000047bfbc0000000000000000000000000000000000000000000000000069877390ecf67d00000000000020f3000000000000000000000000000000000000000000000000340f6b0c3245e36a000000000081e1e90000000000000000000000000000000000000000000000000036eab25e70ac7500000000007ed7230000000000000000000000000000000000000000000000000022d975e1dcacb40000000000125bb40000000000000000000000000000000000000000000000000053b4af91cf3a19000000000066f7d1000000000000000000000000000000000000000000000000000a93b439220c74000000000073855f00000000000000000000000000000000000000000000000000219d46cfe945de000000000000003e0000000000000000000000000000000000000000000000000f3d416b9d2e2494000000000011d72b0000000000000000000000000000000000000000000000000022b2dad0c1f2530000000000003b100000000000000000000000000000000000000000000000000057ec8a61c22b6d00000000007cd091000000000000000000000000000000000000000000000000001fc4423aabfe9100000000001a4c90000000000000000000000000000000000000000000000000005c146c6bc916e000000000000fce7b000000000000000000000000000000000000000000000000003c05e8eb81666a00000000002229b6000000000000000000000000000000000000000000000000005a04dd2cb33502000000000082643900000000000000000000000000000000000000000000000007990d524f4e179c00000000002260da0000000000000000000000000000000000000000000000000114985a03cf4123000000000008bfdc0000000000000000000000000000000000000000000000000018ca5f7178a631000000000000b05200000000000000000000000000000000000000000000000007b79dc46af399c900000000006af30f000000000000000000000000000000000000000000000000001647c55315477500000000007dd10b000000000000000000000000000000000000000000000000013b37832b75672e000000000000406500000000000000000000000000000000000000000000035f798ec2aeec63af9b00000000002e3414000000000000000000000000000000000000000000000000001208de1721fad600000000002f5da3000000000000000000000000000000000000000000000000037efc2485adf03200000000002da6c1000000000000000000000000000000000000000000000000002b22ca23131e6c00000000000389d3000000000000000000000000000000000000000000000000005fa4121b9d0ed50000000000566b02000000000000000000000000000000000000000000000000000895298e141834000000000081ed0b000000000000000000000000000000000000000000000000006343aabfae04f4000000000017591700000000000000000000000000000000000000000000000000fadb997100343200000000004a586700000000000000000000000000000000000000000000000063d8acc60a6a4b8500000000000065a5000000000000000000000000000000000000000000000000068f12d1d0bf14db000000000075ccb7000000000000000000000000000000000000000000000000002dc066a2a68a00000000000043b7900000000000000000000000000000000000000000000000000ddff10432bbb68f00000000007b651300000000000000000000000000000000000000000000000000144ff5f08f98d0000000000082643b00000000000000000000000000000000000000000000000011580100e80b600500000000004e399000000000000000000000000000000000000000000000000000071d289fd389360000000000825894000000000000000000000000000000000000000000000000002f0b9ed4ce38e5000000000057578f000000000000000000000000000000000000000000000000002cf66f1644a9b1000000000023a478000000000000000000000000000000000000000000000000001c200bf825a54f0000000000824cd8000000000000000000000000000000000000000000000000014e57b53c7d0e6700000000006478dd000000000000000000000000000000000000000000000000000af9e5bd55ea47000000000037cc5c000000000000000000000000000000000000000000000000000af5a69cde00b000000000000077fc000000000000000000000000000000000000000000000000d642957badd8107e000000000072ffa40000000000000000000000000000000000000000000000000008804c7ff869c2000000000036f0bc000000000000000000000000000000000000000000000000013b4254f67e525a000000000081ef880000000000000000000000000000000000000000000000000f3ebd28d901443c0000000000824f2d000000000000000000000000000000000000000000000000000b140fd6862e0c00000000005be372000000000000000000000000000000000000000000000000000df350c7416f4700000000002a6fb60000000000000000000000000000000000000000000000000018a0abd7d0d8aa0000000000513a370000000000000000000000000000000000000000000000000008c3b79171d88400000000007aeedc000000000000000000000000000000000000000000000000001be12e91ad81000000000000824f2f00000000000000000000000000000000000000000000000050740119fd81fbdb000000000082643f0000000000000000000000000000000000000000000000000011c44531ec3ae300000000002c82fc00000000000000000000000000000000000000000000000003b4aa0d75c2483600000000008258970000000000000000000000000000000000000000000000000134a073947d03e800000000008243440000000000000000000000000000000000000000000000000040a719bab25bc3000000000081dbe2000000000000000000000000000000000000000000000000003645e31904b2e50000000000116d6c00000000000000000000000000000000000000000000000001a1af8cddebb3d9000000000001e42e000000000000000000000000000000000000000000000000004a6eaa4d7b249b0000000000076ff800000000000000000000000000000000000000000000000003754e4be0f649b100000000001903b900000000000000000000000000000000000000000000000000366c04f943940000000000008253e20000000000000000000000000000000000000000000000000119cbf69df653e3000000000005931400000000000000000000000000000000000000000000000000174a99f50c029200000000008004910000000000000000000000000000000000000000000000000279958544b845ef000000000082025f000000000000000000000000000000000000000000000000002b0da27beab7f100000000006d9e420000000000000000000000000000000000000000000000000200ac03dc5fe5d3000000000000015e00000000000000000000000000000000000000000000000001eabb31f25e1b8800000000004e22f6000000000000000000000000000000000000000000000000004533b9958358a500000000000ce49d00000000000000000000000000000000000000000000000001ea40aa2bdd8334000000000021869a00000000000000000000000000000000000000000000000000150c8a37cc09330000000000824cdd000000000000000000000000000000000000000000000000003f471dac4d89e6000000000000275500000000000000000000000000000000000000000000000000277ba121873ddb0000000000195883000000000000000000000000000000000000000000000000009126371343ab24000000000082364900000000000000000000000000000000000000000000000006ac78944579a663000000000000543e000000000000000000000000000000000000000000000000005eababb37ef2150000000000824cde00000000000000000000000000000000000000000000000000b967d59aad888800000000008233fe000000000000000000000000000000000000000000000000001fa5ae1c8e230e000000000045df5f0000000000000000000000000000000000000000000000000044d2aa6072f946000000000076b1760000000000000000000000000000000000000000000000000bbdf09aefd7e1b100000000003dd2f1000000000000000000000000000000000000000000000000003651061a412e1b00000000007f761300000000000000000000000000000000000000000000000000761b18de587b5b00000000006b0ad500000000000000000000000000000000000000000000000000193205c12fe1ac000000000014d50b0000000000000000000000000000000000000000000000000a8d9a8f8438ff9e000000000017a7e70000000000000000000000000000000000000000000000000b1349c781c81eee0000000000559bb300000000000000000000000000000000000000000000000000386f052f025b8000000000006925e000000000000000000000000000000000000000000000000000745c9085fe1ad00000000000682971000000000000000000000000000000000000000000000000239afa2090a8e424000000000000780b000000000000000000000000000000000000000000000000051b102cb446b3df0000000000824348000000000000000000000000000000000000000000000000004095d5dfc8794b00000000000b04b600000000000000000000000000000000000000000000000003c1a104409e9a0f00000000006e16360000000000000000000000000000000000000000000000000022e5dd381b2b00000000000043757a000000000000000000000000000000000000000000000000016f826212592cf30000000000821f0c00000000000000000000000000000000000000000000000010e07b07ce11544f00000000001de69700000000000000000000000000000000000000000000000000196109e91e089c000000000011c066000000000000000000000000000000000000000000000000001a104f9d97e72200000000000909a00000000000000000000000000000000000000000000000000063dd33620d770f00000000000000240000000000000000000000000000383c00000000000000000000000064363dfb000000000005383f000000000000000000000000000000000000000000000000000000000000532a000000000003e2320000383c00000000000000000000000000c097ce7bc90715b34b9f1000000000000000000003e2350000383c00000000000000000000000000c097ce7bc90715b34b9f1000000000000000000003e2380000383c00000000000000000000000000c097ce7bc90715b34b9f1000000000000000000000e5b30000000000000000000000000000000000000000000000022eb9a0853267ec39000000000000e5b4000000000000000000000000000000000000000003de3e7570899859a58eacf1000000000000e5b50000000000000000000000000000000000000000000000000000000064363dfb000000000000e807000000000000000000000000000000000000000000289041ae9c3515732282a4000000000000e80800000000000000000000000000000000000048ba1c953d3c97a283061346333e000000000000e80900000000000000000000000000000000000000000000000000000f78bfebf54e00000000001735e964363e27000000000000000000000000000000000888904ac863400064363dfb0000000000007a5a00000000000000000000000000000000000000000000000000000000000136bd00000000008258d900000000000000000000000000000000000000000000000000000000000000050000000000824f9a0000000000000000000000000000000000000000000000000000000000000002000000000000215000000000000000000000000000000000000000000001209d154b77c34c4e2b93000000000003dfee000000000000000000000000000000000000000000000000000000000000383c000000000003dfef0000000000000000000000000000000000000000000000000de0eef7f7e47c9b000000000005388900000000000000000000000000000000000000000000000000000041d298132e000000000026383200000000000000000000000000000000000000000000000000000000025dd50700000000000535ff00000000000000000000000000000000000000000000000000125f48c7b703ea00000000003bcdd4000000000000000000000000000000000000000000000000000000000000000000000000003bcdd50000000000000000000000000000000000000000000000000de0eef7f7e47c9b00000000001733cb64363e27000000000000000000000000000000000834b83797b0400064363dfb0000000000079494000000000000000000000000000000000000000000000000000000000000005a00000000005e14ad00000000000000000000000000000000000000000000000000000013765feaf000000000005e14ae00000000000000000000000000000000000000000000000000000012f0ebdc250000000000172dbe64363e27000000000000000000000000000000653af6f13fed31000064363dfb000000000062ca5b00000000000000000000000000000000000000000000000013773666d4fb1db1000000000062ca5c000000000000000000000000000000000000000000000000000000009c7110c7000000000003dff9000000000000000000000000000000000000000000000000000000000000383c000000000003ea55000000000000000000000000000000000000000000000000000002743c1772b300000000007cc1f000000000000000000000000000000000000000000000000000000016b29a31bb00000000007cc1f10000000000000000000000000000000000000000000000000000603096836ed0000000000082623a000000000000000000000000000000000000000000000000000000000000002600000000008264a1000000000000000000000000000000000000000000000000000000000000000000000000008264a20000000000000000000000000000000000000000000000000000000000000000000000000082623b0000000000000000000000000000000000000000000000000000000000000049000000000077b37700000000000000000000000000000000000000000000015fed4499039083eb7e00000000008264a300000000000000000000000000000000000000000000000000000000000000000000000000825d520000000000000000000000000000000000000000000000000000000000000012000000000052ea9100000000000000000000000000000000000000000000a294a1a0cd1d6cbbc6a400000000007f2298000000000000000000000000000000000000000000000002074e822eda11d75900000000008264a40000000000000000000000000000000000000000000000000000000000000049000000000082544900000000000000000000000000000000000000000000000000000000000000120000000000172a5464363e2700000000000000000000000000000657a4ca3b1e6e16000064363dfb00000000001c22cb000000000000000000000000000000000000000000009cb049ac684587be9d1d00000000001c27cdfffffffffffffffffffffffffffffffffffffffffffffd80174ad2257a89a48400000000001c2507000000000000000000000000000000000000000000000000000000000000000000000000002cc587000000000000000000000000000000000000000000000000000000000000000200000000008264d9000000000000000000000000000000000000000000000000000000000000000100000000001fb5930000000000000000000000000000000000000000000000000000001386342bbb000000000023237900000000000000000000000000000000000000000000005867ca083cff01300000000000005502ae0000000000000000000000000000000000000000000000000000000154ad472400000000005502af0000000000000000000000000000000000000000000000000e26142a88784e3600000000005502b00000000000000000000000000000000000000000000000000000000064363dfb00000000005506dc000000000000000000000000000000000000000000000000000946f331a9cbe500000000005506dd000000000000000000000000000000000000000000006237eab346d4f7879dda0000000000001f3e00000000000000000000000000000000000000000000000000004194a5f3be680000000000084ea0000000000000000000000000000000000000000000000000000000000000000000000000000d5c8d0000000000000000000000000000000000000000000000000000000000000000000000000001674d000000000000000000000000000000000000000000000000000000000000000000000000004dda400000000000000000000000000000000000000000000000000000000000a7d8de0000000000825b7d00000000000000000000000000000000000000000000000000000000000000000000000000213fc500000000000000000000000000000000000000000000000000000000008e4694000000000052a08200000000000000000000000000000000000000000000000000000000047672cc00000000008264e10000000000000000000000000000000000000000000000000000000000000007000000000019e5b200000000000000000000000000000000000000000000000000000000033a9e4f000000000081d6a4000000000000000000000000000000000000000000000000000000000000003800000000007f7b470000000000000000000000000000000000000000000000000000000000b8b0550000000000824152000000000000000000000000000000000000000000000000000000000000cd01000000000075544d00000000000000000000000000000000000000000000000000000001df4143bd00000000001447330000000000000000000000000000000000000000000000000000000000a390b600000000007a10c5000000000000000000000000000000000000000000000000000000000427e5350000000000577a7b00000000000000000000000000000000000000000000000000000000002b468e0000000000145f010000000000000000000000000000000000000000000000000000000003407333000000000048a9fc000000000000000000000000000000000000000000000000000000000645898800000000007a7df5000000000000000000000000000000000000000000000000000000000791cd63000000000046083400000000000000000000000000000000000000000000000000000778cfb1e4a3000000000082601e000000000000000000000000000000000000000000000000000000000e60633d0000000000235d2b0000000000000000000000000000000000000000000000000000000000000025000000000000219f0000000000000000000000000000000000000000000000000000042013959852000000000082626d000000000000000000000000000000000000000000000000000000000daa267000000000004b058b000000000000000000000000000000000000000000000000000000028c5c43f30000000000059e1f000000000000000000000000000000000000000000000000000000000053cc0200000000000050c300000000000000000000000000000000000000000000000000000000005111ea00000000007516eb0000000000000000000000000000000000000000204fce5e3e25026103d6f12800000000001a5804000000000000000000000000000000000000000000000000000000000000003500000000008254740000000000000000000000000000000000000000000000000000000000e4e1c00000000000190450000000000000000000000000000000000000000000000000000000000000002d00000000005bfba600000000000000000000000000000000000000000000000000000000009cfade0000000000826270000000000000000000000000000000000000000000000000000000000102dde800000000002c9f4c000000000000000000000000000000000000000000000000000000001d22cb480000000000825b8a00000000000000000000000000000000000000000000000000000002700c5d8e0000000000826273000000000000000000000000000000000000000000000000000000000000000000000000005dcf0b0000000000000000000000000000000000000000000000000000000000000058000000000082627400000000000000000000000000000000000000000000000000000000009d818b00000000005d4f57000000000000000000000000000000000000000000000000000000000000003e000000000047b96700000000000000000000000000000000000000000000000000000000011b307d0000000000136576000000000000000000000000000000000000000000000000000000d7fb590c1c000000000008f5ff000000000000000000000000000000000000000000000000000000000000000000000000002aafcc0000000000000000000000000000000000000000000000000000000000447fad000000000081b2360000000000000000000000000000000000000000000000000000000000000004000000000042319e00000000000000000000000000000000000000000000000000000000d1c7a2310000000000825b900000000000000000000000000000000000000000000000000000000023894d9600000000000021d100000000000000000000000000000000000000000000000000000006d2dc20dc0000000000825d98000000000000000000000000000000000000000000000000000000000000003f00000000008264ee00000000000000000000000000000000000000000000000000000000000000000000000000442786000000000000000000000000000000000000000000000000000000000000005e00000000002605e10000000000000000000000000000000000000000000000000000000000000009000000000081d83b0000000000000000000000000000000000000000000000000000000000000038000000000082627a0000000000000000000000000000000000000000000000000003f28cb5d1c82b00000000000c69cc000000000000000000000000000000000000000000000000000000001498f6b7000000000043ab570000000000000000000000000000000000000000000000000000000000101b8a000000000082627d0000000000000000000000000000000000000000000000000000000000000000000000000007797f00000000000000000000000000000000000000000000000000000009f925d01100000000000b0a9b000000000000000000000000000000000000000000000000000000000003e1c700000000007be23d000000000000000000000000000000000000000000000000000000001fe15f6200000000003b2ce5000000000000000000000000000000000000000000000000000000000000cd01000000000081dd590000000000000000000000000000000000000000000000000000000000000029000000000082627f000000000000000000000000000000000000000000000000000000000e009fa70000000000825b97000000000000000000000000000000000000000000000000000000003e6dd13700000000001d1dc000000000000000000000000000000000000000000000000000000000001f0e93000000000026a1cd0000000000000000000000000000000000000000000000000000000010bb833d00000000000b0d02000000000000000000000000000000000000000000000000000000000004f5d6000000000035f71d0000000000000000000000000000000000000000000000000000005fa42c94d00000000000536b1400000000000000000000000000000000000000000000000000000000000000490000000000162489000000000000000000000000000000000000000000000000000000006d6ac542000000000043a93c000000000000000000000000000000000000000000000000000000000000078800000000008264f2000000000000000000000000000000000000000000000000000000001738dd2900000000004d86a50000000000000000000000000000000000000000000000000000020a6ca9dd0000000000008264f4000000000000000000000000000000000000000000000000000000000e009fa700000000000999480000000000000000000000000000000000000000000000000000000001f6d5db00000000003e27040000000000000000000000000000000000000000000000000000000000e28e63000000000054bb4d00000000000000000000000000000000000000000000000000000001c139bbc400000000008264f50000000000000000000000000000000000000000000000000000000000706dea000000000080b23f0000000000000000000000000000000000000000000000000000000004d6299c00000000008264f6000000000000000000000000000000000000000000000000000000003a2bbd2800000000008234a000000000000000000000000000000000000000000000000000000000006df6a6000000000024ea9f00000000000000000000000000000000000000000000000000000000000000510000000000824b68000000000000000000000000000000000000000000000000000000000234e0810000000000633e2f00000000000000000000000000000000000000000000000000000000001f4a2a000000000044619200000000000000000000000000000000000000000000000000000000007194600000000000077c0800000000000000000000000000000000000000000000000000000002261d97690000000000760088000000000000000000000000000000000000000000000000000000000055bee300000000000083300000000000000000000000000000000000000000000000000000000145e9d49400000000007a09870000000000000000000000000000000000000000000000000000000000000000000000000081ebd000000000000000000000000000000000000000000000000000000002288dcc2500000000007e309c000000000000000000000000000000000000000000000000000000000000000000000000003074360000000000000000000000000000000000000000000000000000000006428e1e0000000000825b9f000000000000000000000000000000000000000000000000000000003e6dd13700000000008264fc0000000000000000000000000000000000000000000000000000000000000000000000000082602f00000000000000000000000000000000000000000000000000000000000000160000000000822b1500000000000000000000000000000000000000000000000000000000000c4da5000000000082628a000000000000000000000000000000000000000000000000000000000000000000000000001ea48b000000000000000000000000000000000000000000000000000000000000001a00000000005dc5e4000000000000000000000000000000000000000000000000000000000005eb01000000000082628b00000000000000000000000000000000000000000000000000000000038d7eb20000000000532384ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000008264fe0000000000000000000000000000000000000000000000000000000001a7207100000000004a0d620000000000000000000000000000000000000000000000000000000000000000000000000001d3c600000000000000000000000000000000000000000000000000000000000000000000000000359ade000000000000000000000000000000000000000000000000000000000000002500000000008264ff000000000000000000000000000000000000000000000000000000001d258c40000000000030718d0000000000000000000000000000000000000000000000000000000006428e1e00000000006b38f40000000000000000000000000000000000000000000000000000000000445b490000000000826500000000000000000000000000000000000000000000000000000000000000002d0000000000301df20000000000000000000000000000000000000000000000000000000000a822db00000000000040a600000000000000000000000000000000000000000000000000001c3106fdc9d20000000000826501000000000000000000000000000000000000000000000000000000001738dd2900000000003df9cc0000000000000000000000000000000000000000000000000000000000a2c94d000000000011e11600000000000000000000000000000000000000000000000000000000000dfc4b00000000007e292d00000000000000000000000000000000000000000000000000000000023663a600000000001d1ae000000000000000000000000000000000000000000000000000000000001f131f0000000000529e2000000000000000000000000000000000000000000000000000000000000000470000000000824b7100000000000000000000000000000000000000000000000000000000008de44200000000007a07f70000000000000000000000000000000000000000000000000000000000c6b9b800000000003e8399000000000000000000000000000000000000000000000000000000000048fae300000000006d42e000000000000000000000000000000000000000000000000000000000177e1666000000000082134e000000000000000000000000000000000000000000000000000000000000000000000000007ce38800000000000000000000000000000000000000000000000000000000002189e20000000000820b8c0000000000000000000000000000000000000000000000000000000006314ee0000000000081e7b00000000000000000000000000000000000000000000000000000000000000029000000000008c0f9000000000000000000000000000000000000000000000000000000000000004c00000000005e19980000000000000000000000000000000000000000000000000000000004da63ee00000000007f9fa30000000000000000000000000000000000000000000000000000000001312d0000000000008260390000000000000000000000000000000000000000000000000000000023d21fbe00000000001d1dd600000000000000000000000000000000000000000000000000000000001f0e5a00000000000d941c0000000000000000000000000000000000000000000000000000000000c6faf3000000000037d8e70000000000000000000000000000000000000000000000000000000005f5378d0000000000025f94000000000000000000000000000000000000000000000000000000000117b5b4000000000071862d0000000000000000000000000000000000000000000000000000000001682e880000000000575e7300000000000000000000000000000000000000000000000000000000048e13bc0000000000825db0000000000000000000000000000000000000000000000000000000000238f6af00000000007cb92100000000000000000000000000000000000000000000000000000000001627cb000000000082629400000000000000000000000000000000000000000000000000000000000994f500000000008265030000000000000000000000000000000000000000000000000000000000000000000000000064ed3b000000000000000000000000000000000000000000000000000000000000003a000000000012566300000000000000000000000000000000000000000000000000000000035502650000000000822fb500000000000000000000000000000000000000000000000000000000013400990000000000371cba000000000000000000000000000000000000000000000000000000000000000000000000008254940000000000000000000000000000000000000000000000000000000000000000000000000082650400000000000000000000000000000000000000000000000000000000086486fe000000000082650500000000000000000000000000000000000000000000000000000000000000000000000000661941000000000000000000000000000000000000000000000000000000000000dee20000000000821ca4000000000000000000000000000000000000000000000000000000000098ba7e000000000082650600000000000000000000000000000000000000000000000000000000000000070000000000825bae00000000000000000000000000000000000000000000000000000000000c8a8100000000008259810000000000000000000000000000000000000000000000000000000001a533f20000000000211d84000000000000000000000000000000000000000000000000000000000004f5d600000000000049f000000000000000000000000000000000000000000000000000000001804fff2b000000000026060a0000000000000000000000000000000000000000000000000000000037876de800000000001abe4d000000000000000000000000000000000000000000000000000000000d0554ac000000000059676a000000000000000000000000000000000000000000000000000000000000005e00000000000536b2000000000000000000000000000000000000000000000000000000aeff910b1200000000000e68b2000000000000000000000000000000000000000000000000000000000007f0ed00000000004bb0720000000000000000000000000000000000000000000000000000000002fe02fe000000000082492c000000000000000000000000000000000000000000000000000000000000000000000000002db31b000000000000000000000000000000000000000000000000000000000000002f00000000007a08020000000000000000000000000000000000000000000000000000000000a6c22f000000000033544e000000000000000000000000000000000000000000000000000000000000001a0000000000368fb50000000000000000000000000000000000000000000000000000000003c15c1a00000000005502ec0000000000000000000000000000000000000000000000000000000154ad4724000000000082650a000000000000000000000000000000000000000000000000000000000000000000000000002a6e170000000000000000000000000000000000000000000000000000000010c2a6250000000000251260000000000000000000000000000000000000000000000000000000000000000000000000008262a4000000000000000000000000000000000000000000000000000000000010a9ac00000000005635c40000000000000000000000000000000000000000000000000000000002a3443200000000005bc423000000000000000000000000000000000000000000000000000000000026285500000000004427c0000000000000000000000000000000000000000000000000000000000000005e000000000081dd730000000000000000000000000000000000000000000000000000000037de06ca000000000082650b000000000000000000000000000000000000000000000000000000000000000000000000007e2e470000000000000000000000000000000000000000000000000000000000000000000000000082650c000000000000000000000000000000000000000000000000000000000daa267000000000000024ee0000000000000000000000000000000000000000000000000000030366ae227100000000008045e900000000000000000000000000000000000000000000000000000000075873af0000000000824b8100000000000000000000000000000000000000000000000000000000061501b1000000000006906a0000000000000000000000000000000000000000000000000000000000ee103e0000000000824933000000000000000000000000000000000000000000000000000000000000000000000000006bc9c5000000000000000000000000000000000000000000000000000000000000003a000000000082598c00000000000000000000000000000000000000000000000000000000000994f5000000000019507200000000000000000000000000000000000000000000000000000012d91cf57f00000000000415b60000000000000000000000000000000000000000000000000000000000000000000000000082501f0000000000000000000000000000000000000000000000000000000003151b3000000000007a08080000000000000000000000000000000000000000000000000000000000ac87f500000000000413dd0000000000000000000000000000000000000000000000000000000000000000000000000082598e000000000000000000000000000000000000000000000000000000000000001600000000001b3d4a0000000000000000000000000000000000000000000000000000006c954a38c0000000000012d74d00000000000000000000000000000000000000000000000000000000154dc9a100000000001d1afe00000000000000000000000000000000000000000000000000000000001f11390000000000211d95000000000000000000000000000000000000000000000000000000000003e1c700000000001365c864363dfb00000000001ad778f53cc6f64bdc000000000000000000d7fb590c1c0000000000138c09000000000000000000000002b06a18a2968b9798d28d0621496a676cc00ee49a0000000000138c0a00000000000000000000000000000000000000a5b904cf3f50a9fb8bfc5d0ace000000000080f093000000000000000000000000000000000000000000000000000006b09aece2dc000000000053449a00000000000000000000000000000000000000000000000df0b2473deda3b73c000000000080ee7e00000000000000000000000000000000000000000000000df0b2473deda3b73c000000000080ee7f000000000000000000000000000000000000000000000000000037287bb9c68c000000000081337d0000000000000000000000000000000000000000000000000000000007b0091f0000000000649e990000000000000000000000000000000000000000000000000000000007b0091f00000000002ff2aa000000000000000000000000000000000000000000000000000006b09aece2dc00000000001a6671000000000000000000000000000000000000000000000000000037287bb9c68c000000000022f40a000000000000000000000000000000000000000000024b36903bc7ee818787c800000000001e7c870000000000000000000000000000000000000000001af4ff4ebb7dd4abe11b6800000000001eb1db0000000000000000000000000000000000000000000026f683bc4df2b3a66c6000000000008262c100000000000000000000000000000000000000000000000000290334f34980000000000000513d9d00000000000000000000000000000000000000000000000000000000000000000000000000246ee0000000000000000000000000000000000000000000004219a208b499fa2648fd00000000001eb46a00000000000000000000000000000000000000000000b5057d581bca740396d000000000001eb46cffffffffffffffffffffffffffffffffffffffffffffe8c09ee6402ad072fb54000000000076ade6000000000000000000000000000000000000000000000000f56c779bb61e6308000000000039fd31000000000000000000000000000000000000000000000000007857b6b89d8e42000000000060da5e000000000000000000000000000000000000000000000000000000000000000000000000000039e6000000000000000000000000000000000000000000000000000000000001dab500000000000039e8000000000000000000000000000000000000000000000000000000000001dab50000000000826525000000000000000000000000000000000000000000000000000000000000000000000000008257200000000000000000000000000000000000000000000000000000000000000001000000000032fd87000000000000000000000000000000000000000000000000000000000000000000000000008259ad0000000000000000000000000000000000000000000000000000000000000002000000000081aae50000000000000000000000001e144b9b431926eeeab6146c1382e2ca672dd67c000000000082653700000000000000000000000000000000000000000000000000000000000000020000000000002156000000000000000000000000000000000000000000000292a6dafe2ec4c484a3000000000003420a000000000000000000000000000000000000000000000000000000000000000000000000004608840000000000000000000000000000000000000000000000eed99f2838b2a9e17700000000001c238a00000000000000000000000000000000000000000000000cadd86dac27eb7001000000000054a6d400000000000000000000000000000000000000000000002df6a64a0ea7cc512b00000000000021a3000000000000000000000000000000000000000000000083d36cefce65cd6ced000000000013664a00000000000000000000000000000000000000000000001ad778f53cc6f64bdc00000000007973270000000000000000000000000000000000000000000000000000000000000000000000000082505700000000000000000000000000000000000000000000000000206cdaa9cdeb8000000000000023f7000000000000000000000000000000000000000000000000ddb00a376882239b000000000000e6ba0000000000000000000000000000000000000000000000022eb9a0853267ec3900000000007b31cf000000000000000000000000000000000000000000000000001e112e791ff29e0000000000547fa700000000000000000000000000000000000000000000000037892834cac8416d0000000000009e8e0000000000000000000000000000000000000000000000001732cae65919879100000000002dd059000000000000000000000000000000000000000000000000000000000000000000000000005dc88d00000000000000000000000000000000000000000000000000000000000000410000000000246f1900000000000000000000000000000000000000000000000367d349178c49ce93000000000000e8fa0000000000000000000000000000000000000000000000001c24fd7fcd79e7b000000000005cb6d90000000000000000000000000000000000000000000000000000000000000000000000000000215700000000000000000000000000000000000000000000002dbae41b21f2577d71000000000054bbaf000000000000000000000000000000000000000000000000d6b2ad78f665c3250000000000826310000000000000000000000000000000000000000000000000000000000000001900000000000024f1000000000000000000000000000000000000000000000000b009dfbe1f0c873500000000005503380000000000000000000000000000000000000000000000000e26142a88784e3600000000000024f20000000000000000000000000000000000000000000000604f67cbf343ab63ac0000000000825e43000000000000000000000000000000000000000000000000000000000000000000000000005a974b000000000000000000000000000000000000000000000000000000000ba6e08100000000005a974c000000000000000000000000000000000000000000000053cc526f7f6716988400000000000040fe00000000000000000000000000000000000000000000035f798ec2aeec63af9b00000000005e15ae00000000000000000000000000000000000000000000000000000013765feaf000000000000040ff000000000000000000000000000000000000000000000355dd849816815d2d71000000000063423900000000000000000000000000000000000000000000023c99e13804769c63b600000000005e15af000000000000000000000000000000000000000000000000000000138ef125f800000000002fc8fb0000000000000000000000000000000000000000000035e392f6087438029d6000000000004f7bdf000000000000000000000000000000000000000000000000000000000c35dbfa000000000000410000000000000000000000000000000000000000000000000000001ac6a7fb1bd300000000000b4f8500000000000000000000000000000000000000000000000220a56828f21d790b000000000062cb65000000000000000000000000000000000000000000000000000000009c7110c7000000000052ebc3000000000000000000000000000000000000000000009cffea1947d748dcd08b00000000005e15b000000000000000000000000000000000000000000000000000000012f0ebdc2500000000000b4f8600000000000000000000000000000000000000000000000c676161174c6d80ba00000000007cc2b60000000000000000000000000000000000000000000000000000603096836ed000000000007cc2b70000000000000000000000000000000000000000000000000000603096836ed000000000002fc8fc000000000000000000000000000000000000000000006f97038be93aa59b1f8a000000000052ebc4000000000000000000000000000000000000000000000000000000e5d172c476000000000054c33d0000000000000000000000000000000000000000000000bf8a850202f20ab59600000000002fc8fd000000000000000000000000000000000000000000000000000000231bee6107000000000030075f000000000000000000000000000000000000000000000004ad2e6702482371f0000000000063423a00000000000000000000000000000000000000000000000000000002744013e400000000005a9752000000000000000000000000000000000000000000000000000000000ba6e081000000000052ebc500000000000000000000000000000000000000000000a294a1a0cd1d6cbbc6a4000000000000410100000000000000000000000000000000000000000000000000001c3106fdc9d200000000000b4f8700000000000000000000000000000000000000000000000c581a2a219240431f00000000005a9753000000000000000000000000000000000000000000000053cc526f7f6716988400000000007cc2b800000000000000000000000000000000000000000000000000000016b29a31bb00000000004f7be000000000000000000000000000000000000000000000000008cced662252a75400000000003007600000000000000000000000000000000000000000000039a582640956d5559ac8000000000062cb6600000000000000000000000000000000000000000000000013773666d4fb1db10000000000300766000000000000000000000000000000000000000000000004ad2e6702482371f000000000003007670000000000000000000000000000000000000000000039a582640956d5559ac8000000000052ebc600000000000000000000000000000000000000000000b009f78c3c4382452aba000000000052ebc7000000000000000000000000000000000000000000009cffea1947d748dcd08b000000000052ebc8000000000000000000000000000000000000000000000000000000e5d172c476000000000052ebc9000000000000000000000000000000000000000000016e034eba5aa2c5adea13000000000053452d000000000000000000000000000000000000000000000051195470f56c4f02ee00000000001eb50f00000000000000000000000000000000000000000000b5057d581bca740388ee00000000001eb510000000000000000000000000000000000000000000002b924b6031dc0396887c00000000001eb5110000000000000000000000000000000000000000000037254fbabec0354f8b8f0000000000826548000000000000000000000000000000000000000000000000000000000000000000000000001eb7e2000000000000000000000000000000000000000000000beaa356ee1ffed588ab00000000005f100c00000000000000000000000000000000000000000000000410d586a20a4c0000000000000023185700000000000000000000000000000000000000000000495aa07cca1caa86026300000000002332300000000000000000000000000000000000000000000017a3718b4be7af5ea21b000000000082654a0000000000000000000000000000000000000000000000000000000000000000000000000082654b0000000000000000000000000000000000000000000000000000000000000000000000000082654c0000000000000000000000000000000000000000000000000000000000000000000000000082654d000000000000000000000000000000000000000000000000000000000000000000000000002332310000000000000000000000000000000000000000000008460157275de3c77cc800000000007643f30000000000000000000000000000000000000000000000000000000000000000000000000082654e0000000000000000000000000000000000000000000000000000000000000000000000000082654f00000000000000000000000000000000000000000000000000000000000000000000000000826557000000000000000000000000000000000000000000000000000000000000000c00000000000b4f8a00000000000000000000000000000000000000000000000c676161174c6d80ba0000000000826558000000000000000000000000000000000000000000000000000000000000000c00000000007fa90d000000000000000000000000000000000000000000000258000000000000022f0000000000817966000000020000000064363dfbbd857ed6015781d666fcf6f0e4fc1847ca301213000000000000410400000000000000000000000000000000000000000000000008f6cb239ded15ad000000000000410500000000000000000000000000000000000000000000000000001ac6a7fb1bd30000000000004106000000000000000000000000000000000000000000000355dd849816815d2d710000000000004107000000000000000000000000000000000000000000000000097349a827a312e1000000000082655a0000000000000000000000000000000000000000000000000000000000000000000000000082655c0000000000000000000000000000000000000000000000000000000000000000000000000019e9430000000000000000000000000000000000000000000000000000000000000000000000000013b4e6000000000000000000000000000000000000000000000000000001daff0384bc000000000023030e000000000000000000000000000000000000000000000000000000000000000000000000001aa07d000000000000000000000000000000000000000000000000000000000000000000000000000771f5000000000000000000000000000000000000000000000000000000000000000000000000001a672800000000000000000000000000000000000000000000000000087e5db4d062bd0000000000231319000000000000000000000000000000000000000000000000000000000000000000000000006b2276000000000000000000000000000000000000000000000000000001b8e3a84faf0000000000823a0200000000000000000000000000000000000000000000000000000000000000000000000000177ab600000000000000000000000000000000000000000000000000001605fc4ce38300000000002307950000000000000000000000000000000000000000000000000000000000000000000000000054a70a00000000000000000000000000000000000000000000002df6a64a0ea7cc512b000000000054a70b00000000000000000000000000000000000000000009fbf38c74a42b70e765e2000000000054a70c0000000000000000000000000000000000000000000000000000000064363dfb000000000054ba210000000000000000000000000000000000000000014c50447167d420e19b2176000000000054ba2200000000000000000000000000000000000000432a18b7079e386d59b9649bae00000000001b3e710000000000000000000000000000000000000000000000000000006c954a38c000000000001cb83900000000000000000000000000000000000000000000447ce3dffd6b1c4cdf8900000000001cb83a000000000000000000000000000000000000000000000038481c6443b4c0ad9b00000000007840100000000000000000000000000000000000000000000000000000000000000000000000000054e670000000000000000000000000000000000000000000000000000000000000000000000000008213b80000000000000000000000000000000000000000000000000000000000000000000000000054c3730000000000000000000000000000000000000000000000bf8a850202f20ab59600000000005503610000000000000000000000000000000000000000000000000000000000000000000000000054a71100000000000000000000000000000000000000000009fbf38c74a42b70e765e200000000006342590000000000000000000000000000000000000000000000000000000000000000000000000054e42d000000000000000000000000000000000000000000000000000000000000000000000000006b30e40000000000000000000000000000000000000000000000000000000000000000000000000055b787000000000000000000000000000000000000000000000000000000000000000000000000006d3f120000000000000000000000000000000000000000000000000000000000000000000000000054bc44000000000000000000000000000000000000000000002c6f71127755853922e600000000006a329e000000000000000000000000000000000000000000000000000000000014c98e00000000004ce5e000000000000f424000000000f12d17ae00000000000000000000020a6ca9dd000000000000553f7e000000000000000000000000000000000000000000002c6bf44fa0e3d2ecc23a0000000000553f80000000000000000000000000000000000000000000000000d6a742f5de3bdfb400000000000b4fa900000000000000000000000000000000000000000000000220a56828f21d790b00000000000b4faa00000000000000000000000000000000000000000000000c581a2a219240431f000000000047dc2b00000000000000000000000000000000000000000000000000000000000007d9000000000082657a000000000000000000000000000000000000000000000000000d7df30cc7848f000000000082657b0000000000000000000000000000000000000000000000000000000fe9ef6e4100000000005e15f600000000000000000000000000000000000000000000000452a8f765c9f728fb00000000008125020000000000000000000000008aaaf6e6167825829ab29f260f246afe742fb2430000000000812503000000000000000000000000000000000000000000000000011c37937e080000000000000000266a00000000000000000000000000000000000000000000001e5493eca2dab9df5e0000000000826583d82ca3b18d89bb6022e1547d6e4bfd9489b2a9c994579bdaac61c72c30c4a6e0000000000082658bacde630a7fa322a76c2490a548e3bc1fa710b50e1bdf455fd3b1fb6d770cce10000000000082658d73686d696e742e7a6b00000000000000000000000000000000000000000000120000000000077aa7000000000000000000000000000000000000000000006f38d83306d38b1ba80000000000002fc94600000000000000000000000000000000000000000000000000bf80c88a05ab2e00000000002fc947000000000000000000000000000000000000000000000000000000231bee610700000000002fc9480000000000000000000000000000000000000000000035e392f6087438029d6000000000002fc94900000000000000000000000000000000000000000000000002b7f3e97ba4f8ba00000000002ff3600000000000000000000000000000000000000000000000000007dbd9e789125200000000006909e400000000000000000000000000000000000000000000021a71b8e3b5cbe7dd8000000000004d77c000000000000000000000000000000000000000000000000002a2f8f1255067f400000000004d77c100000000000000000000000000000000000000000000000002a2f8f1255067f400000000004d77c200000000000000000000000000000000000000000000000000000000000006d8000000000054bc5c0000000000000000000000000000000000000000000000000000000064363dfb0000000000553fa300000000000000000000000000000000000000000000000000000000000006a1000000000054bc5e0000000000000000000000000000000000000000000000000000000064363dfb00000000005541f6000000000000000000000000000000000000000000047600ddf32e866e941e9700000000008265a70000000000000000000000000000000000000000000000000000000000000000000000000054bc5f0000000000000000000000000000000000000000000000000000000064363dfb00000000008265ac000000000000000000000000000000000000000000000000000000000000000200000000008265ad000000000000000000000000000000000000000000000000000000000000000000000000002305470000000000000000000000000000000000000000000153cf34e2d2fcd1f6026300000000001ebad60000000000000000000000000000000000000000000000000000000064363dfb0000000000231896000000000000000000000000000000000000000000004b6d262b1c9e479fcac1000000000022ab7d0000000000000000000000000000000000000000000000000000000000000cfc0000000000231d710000000000000000000000000000000000000000000000000000000064363dfb00000000002342b2000000000000000000000000000000000000057450909be535381bbd41ecfa4d000000000000216f00000000000000000000000000000000000000000001209d154b77c34c4e2b93000000000000217000000000000000000000000000000000000000000000002dbae41b21f2577d7100000000000021710000000000000000000000000000000000000000000000000000000064363dfb00000000000021d400000000000000000000000000000000000000145b677d2349437baa516ea9f800000000000021d500000000000000000000000000000000000000000329445fb9a36c2f6dcfd3c100000000000024f4000000000000000000000000000000000000000000000000000fcc14c4ca760b000000000000e708000000000000000000000000000000000000000003de3e7570899859a58eacf1000000000007960e000000000000000000000000000000000000000000000000000000000225510000000000004608fb00000000000000000000000000000000000000000000000002a3ecd5bc592a3500000000004608fe00000000000000000000000000000000000000000000000000000778cfb1e4a300000000004608ff0000000000000000000000000000000000000000000000eed99f2838b2a9e17700000000004609000000000000000000000000000000000000000000000000000000000064363dfb000000000054801e0000000000000000000000000000000000000000000000002e954dc08c97ef30000000000054801f000000000000000000000000000000000000000005caef3c482c1172a902ec5b00000000004d77de00000000000000000000000000000000000000000000000002a2f8f1255067f4000000000082272100000000000000000000000000000000000000000000000000000000000000000000000000822be3000000000000000000000000000000000000000000000000000000000000000000000000008265c50000000000000000000000000000000000000000005be8b1658c6b810cb0d95200000000007cc9fb0000000000000000000000000000000043b55eb3910fa136fa77720066370d1800000000007cc3320000000000000000000000000000000000000000000000000000603096836ed000000000007ccbe5fffffffffffffffffffffffffffffffffffffffffffffffffffa2057e53d011700000000007cc334000000000000000000000000000000000000000000000000002321d435e354bb00000000000024f50000000000000000000000000000000000000000000000000106dabc0aff69c200000000000024fa64363dfb0000000000604f67cbf343ab63ac0000000000000000030366ae227100000000000026750000000000000000000000032b2479deaf1a557ca4d19f9e4330657016335a93000000000000267600000000000000000000000000000000000000bfd1222b23e5abf163f6d3acaa00000000000024fb0000000000000000000000000000000000012235bbc56b6a41077b83752b6c5600000000001460340000000000000000000000000000000000000000000000000000000000000000000000000017b32c00000000000000000000000000000000000000000000000000019e0e9265555f000000000025263f0000000000000000000000000000000000000000000000000000000000000000000000000081ec57000000000000000000000000000000000000000000000000000000000000000000000000006342ac0000000000000000000000000000000000000000000000000000009b2b3ebfb200000000006342ad00000000000000000000000000000000000000000000023c99e13804769c63b600000000006342ae00000000000000000000000000000000000000000000000000000002744013e400000000006342af00000000000000000000000000000000000000000000000000257c7bbc983ce90000000000649f5b000000000000000000000000000000000000000000000000000000001c6f864c00000000006e321b000000000000000000000000000000000000000000000002b2dd16ff127b8ab400000000008265ce000000000000000000000000000000000000000000000000000000000000000000000000005df095000000000000000000000000000000000000000000000000000000000000000400000000002fc958000000000000000000000000000000000000000000006f97038be93aa59b1f8a00000000000021ab00000000000000000000000000000000000000000000000001751e95ff44ff7000000000000021b2000000000000000000000000000000000000000000000000000004201395985200000000000021b3000000000000000000000000000000000000000000000083d36cefce65cd6ced00000000000021b40000000000000000000000000000000000000000000000000000000064363dfb00000000000021da0000000000000000000000000000000000000000000000004ccba03dfe89db6200000000000021db000000000000000000000000000000000000000009bbc288832710c24ef15d2900000000000021dc0000000000000000000000000000000000000000000000000000035ae28f6f060000000000002408000000000000000000000000000000000000000000000074234f6ae41eada22400000000000260880000000000000000000000000000000000000000000000000000000000000002000000000002608f0000000000000000000000000000000000000000000000000000035ae28f6f060000000000002fbd000000000000000000000000000000000000000000000074234f6ae41eada224000000000002609000000000000000000000000000000000000000000000000000000000000000000000000000002fc30000000000000000000000000000000000000000000000000000035ae28f6f060000000000026091000000000000000000000000000000000000000000000074234f6ae41eada2240000000000002fc90000000000000000000000000000000000000000000000000000000000002943000000000073ada70000000000000000000000000000000000000000000031a375ee981463164f7000000000008265ed0000000000000000000000000000000000000000000000000a01038c9240920000000000008263bb000000000000000000000000000000000000000000000000024d57875290d000000000000081de9f0000000000000000000000000000000000000000000000013ab635af2363c000000000000081dea10000000000000000000000000000000000000000000000013ab635af2363c00000000000007733d30000000000000000000000000000000000000000000000a028340e28f0abed100000000000825eda0000000000000000000000000000000000000000000000002df81d6691789fb2000000000082556b000000000000000000000000000000000000000000000000056dec66b09257e40000000000825c780000000000000000000000000000000000000000000000003328b944c40000000000000000788b650000000000000000000000000000000000000000000000000cc94f7daf07b00000000000008263c000000000000000000000000000000000000000000000000011b9cc6d07f07b00000000000081b36d00000000000000000000000000000000000000000000000000da896b90658000000000000078eeb0000000000000000000000000000000000000000000000000003b1ee6bdb5100000000000008265f2000000000000000000000000000000000000000000000000285a032d3e9d8a00000000000078eeb1000000000000000000000000000000000000000000000000003b1ee6bdb51000000000000082556e000000000000000000000000000000000000000000000000056dec66b09257e40000000000825ee200000000000000000000000000000000000000000000000fe7c9cdba96bc4000000000000082405b0000000000000000000000000000000000000000000000003dc9bf42bd78c000000000000077ad47000000000000000000000000000000000000000000000003b98532106d9874eb0000000000824549000000000000000000000000000000000000000000000000015b1abd3afce1800000000000821b69000000000000000000000000000000000000000000000007bd76d18d4c83270000000000008265f500000000000000000000000000000000000000000000000000989959c11095800000000000825ee90000000000000000000000000000000000000000000000006e590313a497e000000000000081deaa00000000000000000000000000000000000000000000000118dc2ae7ab8b200000000000008265f90000000000000000000000000000000000000000000000010d6dea21e754f00000000000008265fb0000000000000000000000000000000000000000000000000a01038c9240920000000000007733eb0000000000000000000000000000000000000000000000a028340e28f0abed100000000000826601000000000000000000000000000000000000000000000000285a032d3e9d8a00000000000081deb500000000000000000000000000000000000000000000000118dc2ae7ab8b20000000000000825c96000000000000000000000000000000000000000000000001f3939d1e4eda10000000000000825ef600000000000000000000000000000000000000000000000004c091e8a1042000000000000082406c0000000000000000000000000000000000000000000000003dc9bf42bd78c00000000000007fb935000000000000000000000000000000000000000000000000017e4dcd9eea31000000000000825ca10000000000000000000000000000000000000000000000003328b944c4000000000000000082660700000000000000000000000000000000000000000000000000989959c11095800000000000826608000000000000000000000000000000000000000000000000021faf62444e350000000000007b485b0000000000000000000000000000000000000000000000017127a36ab18391340000000000825f040000000000000000000000000000000000000000000000000484f0bb39fdc000000000000081b38b00000000000000000000000000000000000000000000000000da896b906580000000000000825f050000000000000000000000000000000000000000000000002df81d6691789fb200000000008263e6000000000000000000000000000000000000000000000000024d57875290d00000000000007a0fd400000000000000000000000000000000000000000000000581293e53128c7000000000000082536f0000000000000000000000000000000000000000000000002bd9d5d32f9feb0000000000008253700000000000000000000000000000000000000000000000002bd9d5d32f9feb0000000000007fb93d000000000000000000000000000000000000000000000000017e4dcd9eea31000000000000825f0900000000000000000000000000000000000000000000000004c091e8a10420000000000000821b77000000000000000000000000000000000000000000000007bd76d18d4c83270000000000007c163e0000000000000000000000000000000000000000000000011c03ac0da5ed24000000000000825f0d0000000000000000000000000000000000000000000000006e590313a497e00000000000007a0fe000000000000000000000000000000000000000000000000581293e53128c700000000000007de4e100000000000000000000000000000000000000000000000012fe36476ac49d6a000000000081d6f00000000000000000000000000000000000000000000000009a3bfa8f91c98000000000000073ada90000000000000000000000000000000000000000000031a375ee981463164f7000000000007a3f22000000000000000000000000000000000000000000000000bf709da72e6fb00000000000007b485f0000000000000000000000000000000000000000000000017127a36ab183913400000000007de4e500000000000000000000000000000000000000000000000012fe36476ac49d6a0000000000825f1b0000000000000000000000000000000000000000000000000484f0bb39fdc000000000000082384800000000000000000000000000000000000000000000000008a7885b80e510000000000000825f1c00000000000000000000000000000000000000000000000fe7c9cdba96bc4000000000000082384e00000000000000000000000000000000000000000000000008a7885b80e51000000000000082661d0000000000000000000000000000000000000000000000003dfd0c84a94a0180000000000082661e0000000000000000000000000000000000000000000000003dfd0c84a94a018000000000007c16740000000000000000000000000000000000000000000000011c03ac0da5ed240000000000008266220000000000000000000000000000000000000000000000010d6dea21e754f000000000000082456d000000000000000000000000000000000000000000000000015b1abd3afce1800000000000825cc0000000000000000000000000000000000000000000000001f3939d1e4eda1000000000000082640400000000000000000000000000000000000000000000000011b9cc6d07f07b0000000000007a3f36000000000000000000000000000000000000000000000000bf709da72e6fb0000000000000788ba00000000000000000000000000000000000000000000000000cc94f7daf07b0000000000000826627000000000000000000000000000000000000000000000000021faf62444e3500000000000081d6f60000000000000000000000000000000000000000000000009a3bfa8f91c98000000000000077ad97000000000000000000000000000000000000000000000003b98532106d9874eb00000000004f7cab000000000000000000000000000000000000000000000000000000000c35dbfa00000000004f7cac00000000000000000000000000000000000000000000000008cced662252a754000000000055401100000000000000000000000000000000000000000000000000000001c139b38400000000005540120000000000000000000000000000000000000000000000003789272cfac7ebeb00000000007ef0ce0000000000000000000000000000000000000000000001bc00000000000001ad00000000007efc1a000000000000000000000000000000000000000000000000000000000000000800000000001c23fe00000000000000000000000000000000000000000000029b8c5a73dceec8dc9500000000001c23ff64363dfb00000000000cadd86dac27eb7001000000009cb049ac684587be9d1d00000000001c27130000000000000000000000000000000002e68fd71261410edf4c4bd43f2fc85300000000001c271400000000000000000000000000008fb3c4899df802cc6a71d2850c21394567d300000000001c24000000000000000000000000000007c2ab0dbcfd70322c01f28d3b620e911a4d1d00000000003a6c06000000000000000000000000000000000000000000000000000000000000027b000000000039fe2600000000000000000000000000000000000000000000014c08624d700b68ccf700000000001c29a20000000000000000000000000000000000000000000000047b409a74d8d04d9c00000000006e1ac60000000000000000000000000000000000000000000000030000000000000002000000000082457700000000000000000000000000000000000000000000000000000000000000000000000000825f30000000000000000000000000000000000000000000000000000000000000000000000000006e7139000000020000000064363dfb0e8e857d9874c31dc1236a8cf97ae66e2549726b00000000007851c1000000020000000064363dfbd820e2750ae3d163882d8a18bde16c0665a2a43e00000000003a012500000000000000000000000000000000000000000000a650854ecfc08cec427000000000003a01260000000000000000000000000000000000000000000000028904b30b599b541200000000003a6c0d000000000000000000000000000000000000000000000005cac75b5eea3da72800000000003a6c0e00000000000000000000000000000000000000000000034431ec79a94feb751500000000003b16010000000000000000000000000000000000000000000000e346d1c5a8f23f3fc500000000003b19ed00000000000000000000000000000000000000000000000002c8dbf0e3270d1c000000000060dcae00000000000000000000000000000000000000000000000000012297c2e81665000000000060dcaf00000000000000000000000000000000000000000000003d212dfbd575591c4e000000000039c1de0000000000000000000000000000000000000000000000000000000064363dfb00000000003a015e0000000000000000000000000000000000000000000000000000834d504bfee4000000000039feb900000000000000000000000000000000000000000000014c08624d700b68ccf7000000000039c6b20000000000000000000000000000000000000000000000000000000064363dfb00000000003a06ee00000000000000000000000000000000000000000000000030fa89443898b14a000000000039feba000000000000000000000000000000000000000000000000007857b6b89d8e4200000000001b4443000000000000000000000000000000000000000000000000000000000000014c00000000004d88070000000000000000000000000000000000000000000000000000020a6ca9dd00000000000024713f64363dfb00000000000367d349178c49ce93000000004219a208b499fa2648fd00000000002793ab0000000000000000000000000000000000f839e12d33b59818ef2c75ad6cb62600000000002793ac00000000000000000000000000015b276619b7e44b88581c3b3ec8c73105dbdd000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000aac0000001f00000000000000000000000000000000000000000000800b0000000000000000000000000000000000000000000000000000000064363dfb0c799eec0c8269e6f66433183bf6c37f7e2234fad4e8619a9372c537e1919cc9000100000000000000000000000000000000000000008001c03b33a8add9c7d31e3233f60e0c693b42d934fb0d3f52bddab5333ea0e279240000000000000000000000000000000000000000000000000000000000000001000100010000000000000000000000000000000000008001f7f4833dc97c132294428efeec422636ce1c239bce5bf02e636880857dcd3e7e0000000000000000000000000000000000000000000000000000000000000001000100020000000000000000000000000000000000008001975be6534935da63cb520e30c8a9674feb305536e7cbae0736e1c5dc31145c47000000000000000000000000000000000000000000000000000000000000000100010003000000000000000000000000000000000000800159f59282ad1c7590cb1526beffcda45a315accdbdcdb0a5b7bde54b03ae7fb75000000000000000000000000000000000000000000000000000000000000000100010004000000000000000000000000000000000000800171546ea868c52cba8983fe98c452f2f4048163ebc93f62fdb24bfedc4ed986a600000000000000000000000000000000000000000000000000000000000000010001004a0000000000000000000000000000000000008008000000000000000000000000000000000000000000000000000000000000800af872dd3e6a02ebeda4ba3deafc051cd84f7589d62ebd8e7fbcf7c73ea51c9dca0001007c00000000000000000000000000000000000080012963987791446a9a1058ac351feb16420deac2b985d28e115eca5f10dce666b400000000000000000000000000000000000000000000000000000000000000010001007d00000000000000000000000000000000000080015cd3a005f0904bca3af40f994d5de14e58d2315bb5422bca81c1e742857a510500000000000000000000000000000000000000000000000000000000000000010001007e0000000000000000000000000000000000008001fba597fd840795242426cb836d79b47b73bfa4a0aeeed075ca8b5a6e0640080800000000000000000000000000000000000000000000000000000000000000010001007f00000000000000000000000000000000000080017c6e5a48c6fc660047c525a4604536863abccddf9ef782a2caefaf8a539f4eef0000000000000000000000000000000000000000000000000000000000000001000100af0000000000000000000000000000000000008001e00c0902f17bebd8dcb0f957c663c2ebed77e035e56eeef005120598a37408df0000000000000000000000000000000000000000000000000000000000000001000100b00000000000000000000000000000000000008001c8fab4d4a01713e89a1e1f88ccd60656025137cf1bb270d9a94a1f13c7bd40e00000000000000000000000000000000000000000000000000000000000000001000100b100000000000000000000000000000000000080011eddcd8a2b51a7cae7f21f7aeda4415a7eccf7b927f4a5faaad03a67317fa3ff0000000000000000000000000000000000000000000000000000000000000001000100b200000000000000000000000000000000000080014f624f9bef0b037e57c770f7d6f52bbab01dc8963c42ddb9a0df431c2b7ddc080000000000000000000000000000000000000000000000000000000000000001000100b300000000000000000000000000000000000080016dc40a41bc043fea35c416748c077c040b8d06c32e2b526915d2c9b6631fe8b80000000000000000000000000000000000000000000000000000000000000001000100e400000000000000000000000000000000000080019239609296398f27dcf3a37832dfd9e1ae6fd027a7295c28e706b094dd3c2d260000000000000000000000000000000000000000000000000000000000000001000100e50000000000000000000000000000000000008001f77444a11c97a6ef1f5b30e03bf54987fc3130dc434183caf5ba83433adfa4910000000000000000000000000000000000000000000000000000000000000001000101380000000000000000000000000000000000008001770985e53debc8d564ca5b526f481d70a6923f54d101f8536d39052ea6a73f52000000000000000000000000000000000000000000000000000000000000000100010139000000000000000000000000000000000000800154b2ad76d78ddb6e0eda879d19e5f6d8ef664b079279ff4d5a7ccfaa237da4b300000000000000000000000000000000000000000000000000000000000000010001013a00000000000000000000000000000000000080015c038eac451eb63f8228043052e2da8f6b179cc1037853ea383dcef9f783e18d00000000000000000000000000000000000000000000000000000000000000010001016200000000000000000000000000000000000080011059b4af132470b41a8cbbe00bf8cec579af3d2b92e3eb53f3f40c0170534e0f0000000000000000000000000000000000000000000000000000000000000001000101630000000000000000000000000000000000008001039b3db807b4064349c2eeae9505c8feabb6cd6df246de52fcc5224daca8dc5b00000000000000000000000000000000000000000000000000000000000000010001016400000000000000000000000000000000000080016ecc8fe04ac2ec406e6cc4dda464e527314faf6b6820bfa23b1d0890187cdffb00000000000000000000000000000000000000000000000000000000000000010001017c0000000000000000000000000000000000008008000000000000000000000000000000000000000000000000000000000000800aafa525a5601ad6b13b4af46ee182408bdf274fff952906d8e96384295da873f8000101a7000000000000000000000000000000000000800800000000000000000000000011f943b2c77b743ab90f4a0ae7d5a4e7fca3e102c0529a669e67a5b046aa1953a8cb653709c50fd578d44458697057bd9afcab7f000101ae00000000000000000000000000000000000080010069271e837be755eb1acd27f8bda5f7e70ce9a7f3282f08bbd83466ba9905630000000000000000000000000000000000000000000000000000000000000001000101af0000000000000000000000000000000000008001f4cce52bae043ef682e0205cca5506f68691acaaa2a1ca9eb1377ad7e58870040000000000000000000000000000000000000000000000000000000000000001000101b00000000000000000000000000000000000008001869fc245dcc1222f3de063ef076585c13e7b7da9e1aa603649e0c67f12d9d3640000000000000000000000000000000000000000000000000000000000000001000101b10000000000000000000000000000000000008001ac5ef41f6c56d8fe802391ebf021fa8b4c3eff8e8f1465ecf8f6fa77f7f4c3640000000000000000000000000000000000000000000000000000000000000001000101e900000000000000000000000000000000000080014cd602db8143a019049a222b0f72d9c0174891ee29f52c82b71059d613ca131e000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000386c0960f908cd937b3f1ede7c1aeefe72d26de8437582712400000000000000000000000000000000000000000000000002c68af0bb140000000000000000000000000000000000000000000000000000000000000000000000000000000000386c0960f9e167792774202aa62eece5e445327f35cec4572200000000000000000000000000000000000000000000000000038d7ea4c680000000000000000000000000000000000000000000000000000000000000000000000000000000004c11a2ccc14afdbcabcc441b61ac0b036e30722c7d763f3cc2a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000c4b2010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x63335c163', - maxPriorityFeePerGas: '0x12a05f200', - nonce: '0x7349', - r: '0x97ade2e1fe48c2c35194fbb64becbe062f0db4efb96dfd12e578d35a034b8d98', - s: '0x55ac6721ff4947496e861c50990600dd8c0d108d848c6cd84c0c0745a4f09f58', - to: '0x3db52ce065f728011ac6732222270b3f2360d919', - transactionIndex: '0xc', - type: '0x2', - v: '0x0', - value: '0x0', - }, - { - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x133d3eaae97b599d7d7d3538b81c0b393bd00620', - gas: '0x5208', - gasPrice: '0x595e276a3', - hash: '0x7aa9ab138d57ba3ca97edde17570ec90bad03e5c0e2e39ef6f2d57b06906e947', - input: '0x', - nonce: '0xed', - r: '0x86b3a704ae340159752e67577fe3ddada1e797fc1b73108377f42ef6f33d3406', - s: '0x6cc32eba9bb9d489399e4c91a9d08225462de2235e12652b1f9474fe67e479d9', - to: '0xcbd6832ebc203e49e2b771897067fce3c58575ac', - transactionIndex: '0xd', - type: '0x0', - v: '0x25', - value: '0xebba65a5bc3344', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x2b6ad3b0a4ad782a553fe9ae179219f877bd0c47', - gas: '0x5208', - gasPrice: '0x57ae1ff95', - hash: '0x0aa9988e0a851495beb7ea8d0f48e30042167dd98d932cf32535ea60c7c39e2b', - input: '0x', - maxFeePerGas: '0x57ae1ff95', - maxPriorityFeePerGas: '0x57ae1ff95', - nonce: '0x26', - r: '0xc517daac09fdfa297b8ba5c19a6edf0c6c84321134384505f3cddc759eb11e18', - s: '0x441ba8e95813878382988533fbd81f8e3bec9425d7c721679306e74aac434517', - to: '0xf34b40c1e9fd13f3aef7e31b69926b2ae97cc5f0', - transactionIndex: '0xe', - type: '0x2', - v: '0x1', - value: '0x2302bf1686f0de2', - }, - { - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0xc2978441f46a76c60e0cd59e986498b75a40572d', - gas: '0x1fe9b', - gasPrice: '0x55ae82600', - hash: '0x1752d428626dd31ea7546beb62e2c5d6a27ef9f37e14954a8e6d2e4e290b8d92', - input: '0x0ce28dc4', - nonce: '0x3437', - r: '0x230800eb5628222c1b97d09d1cb91e26e2e4e003cea1b1061d3f35d0e340f770', - s: '0x250c820942d9a1138a731a5de121921ca1d2a328e64bd35c42531b02f2836790', - to: '0x52a494dbf47107cc0c624ee10703abecaf586776', - transactionIndex: '0xf', - type: '0x0', - v: '0x25', - value: '0x58d15e176280000', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0xec30d02f10353f8efc9601371f56e808751f396f', - gas: '0x186a0', - gasPrice: '0x513db5909', - hash: '0xdaa6805bdf1f554cfc744fe22a6661642c87141467b7f14edd0f946c9cb0f8ce', - input: '0xa9059cbb000000000000000000000000735d8715bc1b4a404f19236fed05744ab6da094200000000000000000000000000000000000000000000000000000000e6fb16b1', - maxFeePerGas: '0xad83f8d9a', - maxPriorityFeePerGas: '0x9f943785', - nonce: '0x873bb', - r: '0x81f54732c008f3fd03812f57a6deb5822533e3b5e9b50b97574d84c3e31a40e0', - s: '0x25ac62ba0d877945882f4430861effec04ce0e69903b04fd38124c881c395d2e', - to: '0xdac17f958d2ee523a2206206994597c13d831ec7', - transactionIndex: '0x10', - type: '0x2', - v: '0x0', - value: '0x0', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0xf16e9b0d03470827a95cdfd0cb8a8a3b46969b91', - gas: '0x186a0', - gasPrice: '0x513db5909', - hash: '0x3fd6e1a5c50cf84d53f9b6809db62d919121259b0de6869a8ee3ff9622c75806', - input: '0xa9059cbb0000000000000000000000008c897cfe223374d2ba76cf9562283647efa842e100000000000000000000000000000000000000000000079e4e62fe1916184000', - maxFeePerGas: '0xad83f8d9a', - maxPriorityFeePerGas: '0x9f943785', - nonce: '0x1ae4ee', - r: '0xdb8d01754137e016371d9b69b1516509ac98eea529e2b027d853be60fe3fb0b4', - s: '0x7818762d95b751f04d905e25843191891c8047d7bd3ad3a3d11366aac70cda1c', - to: '0x4a527d8fc13c5203ab24ba0944f4cb14658d1db6', - transactionIndex: '0x11', - type: '0x2', - v: '0x0', - value: '0x0', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0xcbec560dae217b1d6303f23e25e547ce008d10bd', - gas: '0x2aee5', - gasPrice: '0x5094a1a84', - hash: '0x608372f0608f5466eeb44c5b28408a80af6e1feb410bfe57fa5f6c6e267bec3d', - input: '0xe2bbb15800000000000000000000000000000000000000000000000000354a6ba7a180000619a3f4a80e465251b5ab251d36993b9b2d074b539fb1041a69f9cccb3f20ef', - maxFeePerGas: '0x91d3fadf6', - maxPriorityFeePerGas: '0x9502f900', - nonce: '0x271', - r: '0xe04214b243d0671e37a53582b0eab23c8b313f6391805053a8ec1bc5d3494c3a', - s: '0x76174f10b93f6cb35ad6d51e2931b0eb3841353ae17ad0583b4a78ea2a4428e4', - to: '0xae0ee0a63a2ce6baeeffe56e7714fb4efe48d419', - transactionIndex: '0x12', - type: '0x2', - v: '0x1', - value: '0x36e7825f3e4e4c', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x46e0ebb66c75743ea7cf223830b6d01d26c9d2e5', - gas: '0x2aee5', - gasPrice: '0x5094a1a84', - hash: '0x9295f62e92616619793b77a3b7577b2b6617a3cd21dd13f87164689c444d64f5', - input: '0xe2bbb15800000000000000000000000000000000000000000000000000038d7ea4c680000441f477690a582f4f52b0380bc84e65830e76fcd3bdf8079bb13c8bc3abd6c6', - maxFeePerGas: '0x99315cec6', - maxPriorityFeePerGas: '0x9502f900', - nonce: '0x42', - r: '0xd19f281c9210eff7c37c0bfbbf22837cb6fd997e8aa3544d9ef310abf139f4ba', - s: '0x260e9f08a252f6333a8a6ab4bc604a56864c7baf0262270e4d1e90f851a4fc06', - to: '0xae0ee0a63a2ce6baeeffe56e7714fb4efe48d419', - transactionIndex: '0x13', - type: '0x2', - v: '0x1', - value: '0x51fc9fd45496f', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x8d456f39cca30dfd46f9be8e2fb38d396a3bb986', - gas: '0x2c08e', - gasPrice: '0x5094a1a84', - hash: '0x11b54c9e279fcbb97484fbf4a27860f9c13768ca21f11e4df82041b0ca33df8f', - input: '0xa1fba2c7', - maxFeePerGas: '0x9b078d0f6', - maxPriorityFeePerGas: '0x9502f900', - nonce: '0x8', - r: '0x5f9624fb030af3719a6e80a5ec7acfe618c5c69cc339e1ee6981deb160beb577', - s: '0x024061ab760e7608b5354782d67bddae9efa30b4a9046380db24c53734cf33da', - to: '0x1785982cb0386d9862ec1968e0152656d44d14de', - transactionIndex: '0x14', - type: '0x2', - v: '0x1', - value: '0x5543df729c0000', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0xfb53f899904110fdc3235531b0cf86676064db0d', - gas: '0x2aed3', - gasPrice: '0x5094a1a84', - hash: '0x2c8a744c0124abfe06295471c805dd0cfbb6a42675cf56d54c1ba851fa8dc3a2', - input: '0xe2bbb158000000000000000000000000000000000000000000000000006d6c6fd3150000017158a89a490a43c8482e8d04d68d0c796de7d1309f32e0a086646979119e0f', - maxFeePerGas: '0xa2e1a1790', - maxPriorityFeePerGas: '0x9502f900', - nonce: '0x0', - r: '0xf1c2dcc6602bda7edeb16a34321c9eacc2d8501a4ffcd9cce95e143ce41f3ca3', - s: '0x4729ae054e94b1460aeea560cf6809203d61aeb2f6ef64c052eea07e4b0a421b', - to: '0xae0ee0a63a2ce6baeeffe56e7714fb4efe48d419', - transactionIndex: '0x15', - type: '0x2', - v: '0x1', - value: '0x6f09868ab1ce4c', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x345dc49ee5636a43395687a898bc0c3c9ee5ff0b', - gas: '0x2a234', - gasPrice: '0x5094a1a84', - hash: '0x90cb790f159d0a8fb4de0bf9c53d95ce48748251da20e254591c8a29960ddd23', - input: '0x7ba0e2e7000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000416097a47543c8d60cd5bf5cafe3ee94e07ed04747405d965d1ff864c6aef2fd177a6ee6b9f8286d9f37bdd0eb63d4b2cfef30f253fa850ffc4b062a4d13c216b91b00000000000000000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x91d3fadf6', - maxPriorityFeePerGas: '0x9502f900', - nonce: '0x5', - r: '0xb3360d4cd6c110385f6e6416239ddfd53ba09a49425090d899b6fa286f062a17', - s: '0x038ed6befae17a39a04d0da0c11541a8ae3e34a81d5e0218c2cd59f2fc106db5', - to: '0x85c4209f7965d36742291f9222bd2cdb104df75c', - transactionIndex: '0x16', - type: '0x2', - v: '0x1', - value: '0x0', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0xa077f842d93c51b7b951c2f9935d33251d7fd774', - gas: '0x2a234', - gasPrice: '0x5094a1a84', - hash: '0xc94887918fa6e72ecb1e92297b4e6d8bd157dda8be8e71d21015bef1c5da2758', - input: '0x7ba0e2e700000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000041cdc740e94dc367f680e9f3206f8981512af64d2abbcd486762c803a993b49f3b7d2358851f6acbd6fb2035ea06f026cd707cd66483b32dae34d34599d8d601ac1b00000000000000000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x91d3fadf6', - maxPriorityFeePerGas: '0x9502f900', - nonce: '0x5', - r: '0x8776838f6f0b5880ad1f47d293a59784fdfc1da6a213afaa394dc39c819f66ca', - s: '0x5e06ead719af63b45434941b53a7235820e6392652968f704f47f7ac88a54da3', - to: '0x85c4209f7965d36742291f9222bd2cdb104df75c', - transactionIndex: '0x17', - type: '0x2', - v: '0x0', - value: '0x0', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x22d3a981255bd90994b8acbe3d92a0a7a32f5120', - gas: '0x2a234', - gasPrice: '0x5094a1a84', - hash: '0x7c9a5723528a8c953a6d89d5a3e11d939bb22073763cfaa9b67f23bc643754b5', - input: '0x7ba0e2e700000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000041faad3bab3c95fe38e7dbc756151801f249731190c6a2b5a8d8d2625e0f3abc684d85d460d453db0b9faa5a3186c17394495e4d51e59faa3f4a43de038ed32ac21b00000000000000000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x91d3fadf6', - maxPriorityFeePerGas: '0x9502f900', - nonce: '0x5', - r: '0x77576eb7635253c0111415988d87d125cccc034e3e0a5537d45f542dc6d9fb17', - s: '0x51a3782c39cfd538278762b099ae388da8e4563110cafb577e14387e7bb5bf8a', - to: '0x85c4209f7965d36742291f9222bd2cdb104df75c', - transactionIndex: '0x18', - type: '0x2', - v: '0x1', - value: '0x0', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0xc956aee2bdf34512a2f770d1d38e63f1f40710ee', - gas: '0x2a25c', - gasPrice: '0x5094a1a84', - hash: '0x75d304122e20c4e61e1be6f10e8a2bfd7172a3d2f44f123ce439e2697adc37c3', - input: '0x7ba0e2e70000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004188f77ebc61cf68343a92f7c4b74709787bf867ad808c8c7c1c3b0b30a25d50e23e6685adcdbf01ba9e0796ec8c4764f2afe3dd3f2cc34d3106a3cba7371132921c00000000000000000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x9b078d0f6', - maxPriorityFeePerGas: '0x9502f900', - nonce: '0x5', - r: '0x77cbab6be06d2c0d7e7e281e6b74bf86d54b1e6eb0d25164e34f74ffc4b13491', - s: '0x76ddd4fe48f97b00c8222b87d281531a8602657c5fa47b1b1e3beb0a68f76db0', - to: '0x85c4209f7965d36742291f9222bd2cdb104df75c', - transactionIndex: '0x19', - type: '0x2', - v: '0x1', - value: '0x0', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x9a41a21ee7ea7337dd60d05f39ae3bd5d265dbe2', - gas: '0x31165', - gasPrice: '0x5094a1a84', - hash: '0x5b0805bcb55a457729c0e23541205aace38077d5d0ec38f8c4981b6ac10ad444', - input: '0xf0300d60', - maxFeePerGas: '0x9ae3aec86', - maxPriorityFeePerGas: '0x9502f900', - nonce: '0x1ce', - r: '0xdee01e58066f39f49053a1caec721704b27d4455cb7f66051567babff2eb0207', - s: '0x5d57933f7f188c8bc3df76c4eddfed42952b24852cb5e99cc46c021d032635d6', - to: '0x5e9dc0b770db326612bb31605bb928ad125c95b3', - transactionIndex: '0x1a', - type: '0x2', - v: '0x1', - value: '0x0', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0xb253c877efad2a87b18fba1687d41456141891a5', - gas: '0x2a244', - gasPrice: '0x5094a1a84', - hash: '0x87a851cef867e8b76c0f00049bccf3eb95f41a4e0ed5f2656d3f029ec321aefd', - input: '0x7ba0e2e7000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000413b8f759048704a4af30717de9e4ad5fa72c6412d7689d2bb73b40c01bcc020301a36256724ee3be2d7ccee88bcbc25e2388ed2d01383bea4397c94a44b00cdc51c00000000000000000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x9b078d0f6', - maxPriorityFeePerGas: '0x9502f900', - nonce: '0x5', - r: '0xef7fa2775201d5e1f5101efde47666dbfc1263000898b2ccb39302b5f57b0cf5', - s: '0x0c36ff2062572a18a4ac9452b0530737d655c4cb0a688c5219a8f2b40a94ef1e', - to: '0x85c4209f7965d36742291f9222bd2cdb104df75c', - transactionIndex: '0x1b', - type: '0x2', - v: '0x0', - value: '0x0', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x7050b357db12b47c03380d5786950214677cb4a0', - gas: '0x2aee5', - gasPrice: '0x5094a1a84', - hash: '0xc4fb4a90055b52891b9ee9ea13e59bfa08fedd2521212a2538a54ac15948694c', - input: '0xe2bbb158000000000000000000000000000000000000000000000000010a741a462780000100c4bce2633a97e0e5325143024b3070c458d89194d53a6fcc18d780a36b22', - maxFeePerGas: '0xa2e1a1790', - maxPriorityFeePerGas: '0x9502f900', - nonce: '0x3', - r: '0x27e5b0cdb7348293f5deacfb04ae58a846bf98f175a10eb24739e972012365e5', - s: '0x3226f6635c7c552345d376494cdfb148e5a055f4ecb0cc478de88ff8786ea6d8', - to: '0xae0ee0a63a2ce6baeeffe56e7714fb4efe48d419', - transactionIndex: '0x1c', - type: '0x2', - v: '0x0', - value: '0x10c1130fdc44e50', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x48231a84eb1d70ac7cc33aa8cb6069332ce56ec9', - gas: '0x2aee5', - gasPrice: '0x5094a1a84', - hash: '0x9a6210559642f06ad096806f546af798f6b9d1a69f246f830a23ba96df23c70e', - input: '0xe2bbb15800000000000000000000000000000000000000000000000000677d94a64ea0000250cd770ed0fb0328249c83c6ca6b96041eaa60f240fb3f1c0ccb54a7287169', - maxFeePerGas: '0x9ae3aec86', - maxPriorityFeePerGas: '0x9502f900', - nonce: '0x0', - r: '0x04702957442572f72da0ae712be49cc269bb8f2974b340a7df77394d4ca8e853', - s: '0x20cee42bc08f88c23a9a1ebe77475786f1f3459a3d14a783caa38e4484066d39', - to: '0xae0ee0a63a2ce6baeeffe56e7714fb4efe48d419', - transactionIndex: '0x1d', - type: '0x2', - v: '0x1', - value: '0x691aab5deb6e4c', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x4184bc5e5444f250767e8d33a49817a9b4fb0df3', - gas: '0x2a234', - gasPrice: '0x5094a1a84', - hash: '0xc36c5f21974222581b9626833fe32d99e1953be7a84f8de99289799b6c28cfdc', - input: '0x7ba0e2e7000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000410b166aab505f074b7a0719c22c6e910af13c500c439dadf57e05b7d02197f1526e851f81f4e0788cb80b9486810f59d741d836f8bac1752e4eb4d65c401c8ec21b00000000000000000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x91d3fadf6', - maxPriorityFeePerGas: '0x9502f900', - nonce: '0x4a', - r: '0x2ce125ff66ac8118b1f129c2588ab2ea350a8c63c5b66fdfdc95a0910f92ab1c', - s: '0x317975d171208e5d462074dd336c22f95b81cce40e9689f9f4df9249327335bb', - to: '0x85c4209f7965d36742291f9222bd2cdb104df75c', - transactionIndex: '0x1e', - type: '0x2', - v: '0x0', - value: '0x0', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x151b381058f91cf871e7ea1ee83c45326f61e96d', - gas: '0x5208', - gasPrice: '0x4eb8bf7c4', - hash: '0x5555125fe67d3a36555050d41b8ca19ff036d6a338add7c285eef925100b7d49', - input: '0x', - maxFeePerGas: '0xaf75aedb8', - maxPriorityFeePerGas: '0x7744d640', - nonce: '0x74102', - r: '0xc4935d7c1a6ea5a50d1c66a75518c30b60646f6bfd1891aef7d58f0fab97353a', - s: '0x03a60cb1ceb8d9a92e170cbf290c99a9b97492b471f33f92e0cdcf7299e9f33f', - to: '0x29d0b29472432459eeb43003876bc3124334cdc5', - transactionIndex: '0x1f', - type: '0x2', - v: '0x1', - value: '0x3e6aaf5ee5cc000', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x59e0cda5922efba00a57794faf09bf6252d64126', - gas: '0x1d4c0', - gasPrice: '0x4eb8bf7c4', - hash: '0xc9b0ffd52b2d3179cab61f22302eed123144dca2367455f0b26cbd57a54d6d6f', - input: '0xa9059cbb0000000000000000000000006767526a362ec6c6b1df185478e4f01506b73ff300000000000000000000000000000000000000000000000007caa2b492b20000', - maxFeePerGas: '0xaf75aedb8', - maxPriorityFeePerGas: '0x7744d640', - nonce: '0x6c27', - r: '0x58746264bcce9d42ce4d35a4677aa1adddc9996e9be421dbaa99f3d2a20aa391', - s: '0x334e4d5cea9d1860d914e7796cf68f97677c87772b3885e0f93f7a4379abafdd', - to: '0x0bc529c00c6401aef6d220be8c6ea1667f6ad93e', - transactionIndex: '0x20', - type: '0x2', - v: '0x0', - value: '0x0', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x867bfa133d64fad734c89f886d2a169b6504ab2b', - gas: '0xc350', - gasPrice: '0x4eb8bf7c4', - hash: '0xb47865548d28112a9b37e3909fe2310918a4a70054b2e10f0a25b81ad2bfd695', - input: '0x', - maxFeePerGas: '0xe8990a4600', - maxPriorityFeePerGas: '0x7744d640', - nonce: '0x1227b', - r: '0x59b0898abc04ad8077c95c705e2df2ae6824b40685159f03107f68188ea5361c', - s: '0x4a1e52473086dc9cb96768bdd8b02cc153aa6b0bdd9f08e12c047c176b800ae8', - to: '0x99383ffe2031379e1e829e106e29a785c9f7f498', - transactionIndex: '0x21', - type: '0x2', - v: '0x1', - value: '0x22ddf7aac722000', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x5ab96bd81c33a620dba024c797a78b02b3964849', - gas: '0x5208', - gasPrice: '0x4eb7cb584', - hash: '0xeba0d7487248cc40f7a9784f20c879cc358231ac73cb56900629b11a2de6ef23', - input: '0x', - maxFeePerGas: '0x684ee1800', - maxPriorityFeePerGas: '0x77359400', - nonce: '0xa', - r: '0x41643f403bbe3262d39ee6c1449d33d96bdd1227f2d6967ab193a53f1f0bfc48', - s: '0x31ae8fa9994acb3d17ce5ac4028f139999a674732a0cd9e095d6dea890d0c550', - to: '0x1164c6c18b6de4831305050f5b32e2807e2bfc32', - transactionIndex: '0x22', - type: '0x2', - v: '0x1', - value: '0x263bee6bf38e8', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0xc5a93444cc4da6efb9e6fc6e5d3cb55a53b52396', - gas: '0x5208', - gasPrice: '0x4eb7cb584', - hash: '0x77fab2e3ef8460a5259e7107cf0cbc1a1e31678d112aaf248b2108159b4416a3', - input: '0x', - maxFeePerGas: '0x9c7652400', - maxPriorityFeePerGas: '0x77359400', - nonce: '0x13403f', - r: '0x673b786b4a389f7fb0df5862ab0703e3685ca0081d321b8ac8b8c2ecbf7ee412', - s: '0x6be2172fda36ea57d7c77dcc46de306545d4f3abf96e7db6e24a3c9e44427974', - to: '0xc8898aba27d521c47055ed2c493cbfd6b95a31d4', - transactionIndex: '0x23', - type: '0x2', - v: '0x1', - value: '0x11e7da71ab0000', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x28c6c06298d514db089934071355e5743bf21d60', - gas: '0x32918', - gasPrice: '0x4eb7cb584', - hash: '0x216b046ab639e61930add4323bf64b76d91db121963350632ed82f26bb6de7e6', - input: '0xa9059cbb0000000000000000000000007f263315e03eeef6c03ee385b15695bdf87cbeb1000000000000000000000000000000000000000000000012f5e3653d5caf6000', - maxFeePerGas: '0x17bfac7c00', - maxPriorityFeePerGas: '0x77359400', - nonce: '0x62108f', - r: '0x93f820e51bbd9cee9f3f1b94fe8f7676d4346fe9eacd549a2d07e434ab807cb6', - s: '0x030da66baf90a7e72379224c0863eb3b4e31cc94b0d86177b91950d644c8f406', - to: '0xc18360217d8f7ab5e7c516566761ea12ce7f9d72', - transactionIndex: '0x24', - type: '0x2', - v: '0x1', - value: '0x0', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x56eddb7aa87536c09ccc2793473599fd21a8b17f', - gas: '0x32918', - gasPrice: '0x4eb7cb584', - hash: '0xd39d9a75f852bcb051393709ddb894ee043b7ea18bc21ce4ebd5a3560142b60c', - input: '0x', - maxFeePerGas: '0x17bfac7c00', - maxPriorityFeePerGas: '0x77359400', - nonce: '0x46e01c', - r: '0xee36304a0224b72a556eb71ff13d8cc1d3bdf6d864c6ee0ab0e9b832d556185f', - s: '0x50e293db57ca81487fc0f896665b4e9d5802a15c24fa0dce5803e1e663a84c10', - to: '0x69f1918cf0661b1b8dce3aa2137e4659d8493e79', - transactionIndex: '0x25', - type: '0x2', - v: '0x1', - value: '0x70f9ee77db8000', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x575cc48e711d8faacf051502a757b90c11f8547d', - gas: '0x30d40', - gasPrice: '0x4eb7cb584', - hash: '0xb7f3dbb72b2f8fe579b81a3ec11a56008b09d90f2a5267180fd8f966a1b76cce', - input: '0x23b872dd000000000000000000000000a2afeae98f8ad0d8c30be323ca461754380fce49000000000000000000000000d1cd4e06e6034c31bd9392013a55d954e6fdcb740000000000000000000000000000000000000000000000000000000024bb178a', - maxFeePerGas: '0xa104cb290', - maxPriorityFeePerGas: '0x77359400', - nonce: '0x90b', - r: '0x0a45e7222c8203898f7f894dfa7ade58603a8d7d4332697d37ac69a7a027cd75', - s: '0x06ff5b1b6e1fce12a9ff1f52acaa153fcf89d4fb6ee4e6afcbbc146630707c40', - to: '0xdac17f958d2ee523a2206206994597c13d831ec7', - transactionIndex: '0x26', - type: '0x2', - v: '0x0', - value: '0x0', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0xd1ff134d20fc3a224bd9bc0877bb24a23784dd56', - gas: '0x5208', - gasPrice: '0x4eb7cb584', - hash: '0x2bb7f5e1d071f0dc7040fc1ae745274a456e25610cfcfcd38e9cb3205f227222', - input: '0x', - maxFeePerGas: '0x5d21dba00', - maxPriorityFeePerGas: '0x77359400', - nonce: '0xb', - r: '0x4b287ee6e4333f64742044706f5c8c00e6e60d7501682c1314cb5211b8c8bf4e', - s: '0x37f5eaba2b575d587d019257d29b5bc097705571aa6280526a9007c2ae8aece1', - to: '0x8412abafccf6f5756684f14e0aabd23834af7789', - transactionIndex: '0x27', - type: '0x2', - v: '0x0', - value: '0x1301c7dd343156', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0xf89d7b9c864f589bbf53a82105107622b35eaa40', - gas: '0x15f90', - gasPrice: '0x4eb7cb584', - hash: '0x6c53f5e35d76bfaab1d1eaa75b553da7bed8fe046f90961441474c6852b0469f', - input: '0xa9059cbb0000000000000000000000000cca85946f37dfb7d7af154155c1eff595479e530000000000000000000000000000000000000000000000dad417aeaff88fc000', - maxFeePerGas: '0x174876e800', - maxPriorityFeePerGas: '0x77359400', - nonce: '0xb2615', - r: '0x6faa89b9d6e984f3df4d9c1fefd468f54099081ae3aa06de5fc80a9251ccdb55', - s: '0x293017e31f66be92bdfd04c3302a0c2ed173751ceec4fd14b9c4ef64656f8c62', - to: '0x6de037ef9ad2725eb40118bb1702ebb27e4aeb24', - transactionIndex: '0x28', - type: '0x2', - v: '0x1', - value: '0x0', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x28c6c06298d514db089934071355e5743bf21d60', - gas: '0x32918', - gasPrice: '0x4eb7cb584', - hash: '0x346d0ad3d6a351797184f880b08b913dd095d12f36ade9e75eb7cba6980dbf34', - input: '0x', - maxFeePerGas: '0x17bfac7c00', - maxPriorityFeePerGas: '0x77359400', - nonce: '0x621090', - r: '0x883dbc540ae0a26dabcc4463651a74b8d2782a590e0bf0de731df0572429b928', - s: '0x207fd537c0809bbc87d42cf79f08f7f73795c7ae21ef01c79479485519a415fa', - to: '0xfed930b2dbbc52996b2e107f1396d82256f41c41', - transactionIndex: '0x29', - type: '0x2', - v: '0x0', - value: '0xe26ea512c27000', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x56eddb7aa87536c09ccc2793473599fd21a8b17f', - gas: '0x32918', - gasPrice: '0x4eb7cb584', - hash: '0x209624ade75ef69c5b0b1c8d85ebb1be2a084380f3eff7fb15fafc6d607da908', - input: '0xa9059cbb0000000000000000000000000f380d4a0afb298faa4cf6d1d16534470140480f00000000000000000000000000000000000000000000000000000004a817c800', - maxFeePerGas: '0x17bfac7c00', - maxPriorityFeePerGas: '0x77359400', - nonce: '0x46e01d', - r: '0x78a34604e863d7e6467d40f21d161d99794bcf9424b95d5bc6f942c6d2e7d5f4', - s: '0x3d4a493c0aba95406299f7afbf026ca87e9c21fd9d864d16884ee777979c54c5', - to: '0xdac17f958d2ee523a2206206994597c13d831ec7', - transactionIndex: '0x2a', - type: '0x2', - v: '0x1', - value: '0x0', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0xdfd5293d8e347dfe59e90efd55b2956a1343963d', - gas: '0x32918', - gasPrice: '0x4eb7cb584', - hash: '0xc76320b5a1943478674adc1c81ec441e0798525ff8c5aba49a13e0feccfbb6b3', - input: '0xa9059cbb0000000000000000000000008fef490d614fce8b93bd6f28835dd35a8b3229a900000000000000000000000000000000000000000000000000000e789541059e', - maxFeePerGas: '0x17bfac7c00', - maxPriorityFeePerGas: '0x77359400', - nonce: '0x599696', - r: '0x7cbc768027ad0dee1b9d3d31f2d2d9f95c116c24ec80efc69fda640fcac35705', - s: '0x6d0cf162a13339f2caf1a4f323671a88684ddd29d7a8fb554e45abb00599fea4', - to: '0xb64ef51c888972c908cfacf59b47c1afbc0ab8ac', - transactionIndex: '0x2b', - type: '0x2', - v: '0x1', - value: '0x0', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x4976a4a02f38326660d17bf34b431dc6e2eb2327', - gas: '0x32918', - gasPrice: '0x4eb7cb584', - hash: '0x79474757728de960eb4e7da5bd14cd3bbaa342a1f15a0e02920020bc17293e98', - input: '0x', - maxFeePerGas: '0x17bfac7c00', - maxPriorityFeePerGas: '0x77359400', - nonce: '0x264d0a', - r: '0x27451446f19d4db1ec9a7523ba550878049af134e6e91bb4cfc706bab8ac9df0', - s: '0x2924823e0512b4ac49c5eb479231ad53d15459f4a78309d7c669bab355e27086', - to: '0x8bb27f2b2240f2ee95648a216bda95e7d7ad59a9', - transactionIndex: '0x2c', - type: '0x2', - v: '0x0', - value: '0xd6f06df0e94000', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x3ab28ecedea6cdb6feed398e93ae8c7b316b1182', - gas: '0x2934c', - gasPrice: '0x4eb7cb584', - hash: '0xcbd72caf3b24a675faac5188b7bc15768c2bdd4e6a2a8c60ce79f1875b36b4e8', - input: '0xa9059cbb00000000000000000000000019697dfab84c1982138419a3be21eaaa7c05c1c700000000000000000000000000000000000000000000000527c712237ba60000', - maxFeePerGas: '0xe2d17967f', - maxPriorityFeePerGas: '0x77359400', - nonce: '0x59e4f', - r: '0x58e964390fae81b120e526d35bdafca451d00d77f72cabcadaa63b2141ec3eb0', - s: '0x2fdc669bc14bc9903b59ac152858f082f534624a501f2f0009dd0a956918be0d', - to: '0xba11d00c5f74255f56a5e366f4f77f5a186d7f55', - transactionIndex: '0x2d', - type: '0x2', - v: '0x1', - value: '0x0', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x21a31ee1afc51d94c2efccaa2092ad1028285549', - gas: '0x32918', - gasPrice: '0x4eb7cb584', - hash: '0x2350e1d8dbaaef1c51429dd50f319f7ae0c60681b17e925abe7f6b79b85bdf6c', - input: '0xa9059cbb0000000000000000000000008263a4b989d756babaf651a9cbf171231466666600000000000000000000000000000000000000000000000000000000b2d05e00', - maxFeePerGas: '0x17bfac7c00', - maxPriorityFeePerGas: '0x77359400', - nonce: '0x5e0f0e', - r: '0x3a36d0faf9eb3c59ca4e7bbed74a3491b5fd2d05c17c34fa02d84cee2071c7b2', - s: '0x64bdeda9880342582fab87c9b05e98823fa49bb8dfbd772dc2a246fc863b7bc6', - to: '0xdac17f958d2ee523a2206206994597c13d831ec7', - transactionIndex: '0x2e', - type: '0x2', - v: '0x0', - value: '0x0', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0xdfd5293d8e347dfe59e90efd55b2956a1343963d', - gas: '0x32918', - gasPrice: '0x4eb7cb584', - hash: '0x76c881e0add6fbe11dfc4396ff8f373f2bb1cc27db929b95a21cd64b7dc41e11', - input: '0x', - maxFeePerGas: '0x17bfac7c00', - maxPriorityFeePerGas: '0x77359400', - nonce: '0x599697', - r: '0x6e69d854012faf58c3ade90b0953359b8d8f3f7619960e9fc6a745be6afad0cc', - s: '0x74473994719dd6c24c8d850b1dabcd7a8a993217c16d542ed7f4a1ec34a8906e', - to: '0x655da9d1fdba5d7cbe0738f71022918ad75144f8', - transactionIndex: '0x2f', - type: '0x2', - v: '0x0', - value: '0x859d63b3453e6000', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0xbd310c947981b291a1abb439ab0713f6a6018f35', - gas: '0xfbac', - gasPrice: '0x4eb7cb584', - hash: '0x3ec134ed1e10df2b1b78311fcd38325b2da8e5da5ecfb60573909450a04693e4', - input: '0x095ea7b3000000000000000000000000e66b31678d6c16e9ebf358268a790b763c133750ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', - maxFeePerGas: '0x649534e00', - maxPriorityFeePerGas: '0x77359400', - nonce: '0x0', - r: '0xafbb17abe38e32f14f34cfa09f93876fddfe80b07f2bc54b27cf5ff6093e3bf2', - s: '0x553821eca4f13c424737eac999b1a7997295252802abe049884554766202fc68', - to: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', - transactionIndex: '0x30', - type: '0x2', - v: '0x0', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x4eb8769a89b91b60a14ad1d30f2b136d9cf61b18', + gas: '0xc351b', + gasPrice: '0x17b617f7e5', + maxFeePerGas: '0x1837c9d0d4', + maxPriorityFeePerGas: '0x15d5be29c2', + hash: '0x5771987837eb244c287a714f36d5738726d472a6b3a46deae2e1d4ef0965a1b0', + input: '0x2a0aad110000000000000000000000009bdc7dfd19b75b023e28bbb8e197295c51ce55e40000000000000000000000000000000000000000000000000a081bcc665c6b000000000000000000000000000000000000000000013149ec222a8ae00000000000000000000000000000000000000000000000000138a3a129518aa0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000abd69d0fac4b0851dafe100979df808eb7fb81a9', + nonce: '0x1706d', + to: '0x7176f0f071379fee51668eb6387dda9129e5ca6b', + transactionIndex: '0x0', value: '0x0', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0xbd310c947981b291a1abb439ab0713f6a6018f35', - gas: '0x460af', - gasPrice: '0x4eb7cb584', - hash: '0x8587b3eb001a4d9c367b44d3c66d864bd086f7def58681fa568c25c1632197fe', - input: '0x5cf5402600000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000000000000000000000000000000000000bcd3d800000000000000000000000002b591e99afe9f32eaa6214f7b7629768c40eeb3900000000000000000000000000000000000000000000000000000000001e848000000000000000000000000000000000000000000000000000000000000001286af479b20000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000bcd3d800000000000000000000000000000000000000000000000000000003e2b71f0900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002ba0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000bb82b591e99afe9f32eaa6214f7b7629768c40eeb39000000000000000000000000000000000000000000869584cd000000000000000000000000382ffce2287252f930e1c8dc9328dac5bf282ba100000000000000000000000000000000000000000000006acdf8f63164363ecf000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x649534e00', - maxPriorityFeePerGas: '0x77359400', - nonce: '0x1', - r: '0x5da32c14819244d81966203f8ece7d4330dfc90d43237b769679b89e308ef01d', - s: '0x0bb911307432a6dd7acc0155a43f398a66865e941202c8f37fa31f87a7be5748', - to: '0xe66b31678d6c16e9ebf358268a790b763c133750', - transactionIndex: '0x31', type: '0x2', - v: '0x1', - value: '0x0', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', + accessList: [ + { + address: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', + storageKeys: [ + '0x0e172d98b879678a3ee0f92abe00ac1abb5704e2202ab541abde74b1c29fa6f2', + '0xe48bc08c8ce04355ce1379b42464b6258666bd2a783f94767a9ba43cc827f3ba', + ], + }, + { + address: '0xc555d55279023e732ccd32d812114caf5838fd46', + storageKeys: [ + '0x000000000000000000000000000000000000000000000000000000000000000c', + '0x0000000000000000000000000000000000000000000000000000000000000008', + '0x0000000000000000000000000000000000000000000000000000000000000006', + '0x0000000000000000000000000000000000000000000000000000000000000007', + ], + }, + { + address: '0x812ba41e071c7b7fa4ebcfb62df5f45f6fa853ee', + storageKeys: [ + '0x55bd389fee2ec1512750c0175b3ae345be73d2aa52d1f1db2744f6cc252cc424', + '0x4e823913d43be38662c8211c9c13b24022f2db9d6cccabca7d35c085a77dfee7', + '0x000000000000000000000000000000000000000000000000000000000000000f', + '0x000000000000000000000000000000000000000000000000000000000000000a', + '0x0000000000000000000000000000000000000000000000000000000000000012', + '0xaf966f6b828e97290407430bea5318af1afff056aa2506c6d8554a37e28038fe', + '0x0000000000000000000000000000000000000000000000000000000000000000', + '0x000000000000000000000000000000000000000000000000000000000000000c', + '0x0000000000000000000000000000000000000000000000000000000000000007', + '0xb04a1206ea6c7e1296f87734b85431b4368ffeced6bc420853a025149ce1e7c5', + '0x0000000000000000000000000000000000000000000000000000000000000016', + '0x61619f4ff8176f9002dd5ab3523e6aa4aa7eea503fc92d6effaf2faab13e8016', + '0x0000000000000000000000000000000000000000000000000000000000000013', + '0x0d4c6c6cc76cc27519c6cca57eface03a9fa0749bf9cd30c10f1d3afcbf6fda7', + '0x0000000000000000000000000000000000000000000000000000000000000019', + ], + }, + ], chainId: '0x1', - from: '0xcbf04eac5a3443941ce6a41ff38d7e238406f0e4', - gas: '0x186a0', - gasPrice: '0x4eb7cb584', - hash: '0x4e52482e36a15ab65b1ee34d20f93b54cd1873e1b596c874364c59125dd23b62', - input: '0xa9059cbb0000000000000000000000006cc5f688a315f3dc28a7781717a9a798a59fda7b0000000000000000000000000000000000000000000000258a3df7f069706400', - maxFeePerGas: '0xa3e9ab800', - maxPriorityFeePerGas: '0x77359400', - nonce: '0x1260', - r: '0x526cda6518d213796112450510e637aab66ca0e7cf37e17ba16c95b05e799bb6', - s: '0x24e98f8aae7e8393654d1c5d6ca56d07776bba3985d930fc13753729a8b53fff', - to: '0x0b38210ea11411557c13457d4da7dc6ea731b88a', - transactionIndex: '0x32', - type: '0x2', v: '0x0', - value: '0x0', + r: '0x9427f9eb2c3f47ec66c674e8c73cd65b8e46d552453b0651e8dd697800090caf', + s: '0x37156a4d254e7ee813fe53c058938f75806527cf54f472f984d391a89249de81', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x89e51fa8ca5d66cd220baed62ed01e8951aa7c40', - gas: '0x7a120', - gasPrice: '0x4eb7cb584', - hash: '0x5512e2f3ae0e44b1993cbfcea2f91fbc8e6cf2ef6bc73b606f19db051935c30b', - input: '0xa9059cbb00000000000000000000000016c9d209a906bbf06bd29c233c7f45b76e42a5180000000000000000000000000000000000000000000000000000000002dbf090', - maxFeePerGas: '0x1329a0487f', - maxPriorityFeePerGas: '0x77359400', - nonce: '0x16cd82', - r: '0x60a123cc67d102617f60161435641e16dcaea9dde4c80fc1a1c4b3324f8c57f2', - s: '0x4dfb246eebc7ca04821a922fca1177f453462a2ae8803e33e87285fbd5f8eb9d', - to: '0xdac17f958d2ee523a2206206994597c13d831ec7', - transactionIndex: '0x33', - type: '0x2', - v: '0x0', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x4ac6268385851b23ebe22f91630d7d0f61e7b74d', + gas: '0xc351b', + gasPrice: '0x5c7a12944', + maxFeePerGas: '0x649530233', + maxPriorityFeePerGas: '0x3e7475b21', + hash: '0xdcc36c7c0f1ec3ed4a2290819adde014f1866bba041244297d4dd26b8ad7a677', + input: '0x2a0aad11000000000000000000000000d43b29aaf8ad938cff4f478a0756defffb329d0700000000000000000000000000000000000000000000000001401ca3de486ee000000000000000000000000000000000000000000050b005b7c2ad880000000000000000000000000000000000000000000000000051432ec4166364000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c750359cba44ad5214f0ccd99900b99099dc92f1', + nonce: '0x1f39', + to: '0x7176f0f071379fee51668eb6387dda9129e5ca6b', + transactionIndex: '0x1', value: '0x0', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x3ab28ecedea6cdb6feed398e93ae8c7b316b1182', - gas: '0x107a5', - gasPrice: '0x4eb7cb584', - hash: '0x47effec3066af633b7b8e31eb958720b3c26101a660b68294cfd5d1da9df660e', - input: '0xa9059cbb00000000000000000000000019697dfab84c1982138419a3be21eaaa7c05c1c700000000000000000000000000000000000000000000009c8315610cda546000', - maxFeePerGas: '0xe2d17967f', - maxPriorityFeePerGas: '0x77359400', - nonce: '0x59e50', - r: '0xed0cc2008fa60ceef899c73967869cabfe3ca8aaaa9abf6c94fa0c7f211fd82b', - s: '0x6644f22c84aedc9f50595a80c99641db7ed63487cef46bc98324f214b1ac1088', - to: '0x3593d125a4f7849a1b059e64f4517a86dd60c95d', - transactionIndex: '0x34', type: '0x2', - v: '0x0', - value: '0x0', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', + accessList: [ + { + address: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', + storageKeys: [ + '0x246b6fbb62dd356a54402357031cbb467f367a61b7888c050cb6c7bb3ab09af5', + '0x0e172d98b879678a3ee0f92abe00ac1abb5704e2202ab541abde74b1c29fa6f2', + ], + }, + { + address: '0x7176f0f071379fee51668eb6387dda9129e5ca6b', + storageKeys: [ + '0x1eacdd914ccc11e96dc3a80463b6f0fc6803a1c34c181447e291c8a617ab02e9', + ], + }, + { + address: '0xd43b29aaf8ad938cff4f478a0756defffb329d07', + storageKeys: [ + '0x0000000000000000000000000000000000000000000000000000000000000000', + '0x0000000000000000000000000000000000000000000000000000000000000004', + '0x0000000000000000000000000000000000000000000000000000000000000002', + '0x09d630f44b7f555eed07fae2912a5dc3cb8482d08fd0bb5516ec577adbc2708d', + '0x000000000000000000000000000000000000000000000000000000000000000b', + '0x000000000000000000000000000000000000000000000000000000000000000c', + ], + }, + { + address: '0x662b67d00a13faf93254714dd601f5ed49ef2f51', + storageKeys: [ + '0xdbc70cebf038526dc74f312a95b8b2bbe9b31bad7ab204377adc12f259b8ecb4', + '0x1cdb6b5e8ca27cc663a219e40c950ba60826d12d2811ff4e5355f51c833974e7', + '0x8f1ae5d9fa039fb04c99033e2c69ddd4cb30f8b7c00cfc9111e11d7250eb29ad', + '0x7ff2e0ef776e42618d5979459155347a3f53c31df06de580f2f8a6b029de6859', + ], + }, + ], chainId: '0x1', - from: '0x56eddb7aa87536c09ccc2793473599fd21a8b17f', - gas: '0x32918', - gasPrice: '0x4eb7cb584', - hash: '0xd6356b5d6aba735dad22a19dc1c6f1e90dc5b9cae6981e3242b551da32a56420', - input: '0x', - maxFeePerGas: '0x17bfac7c00', - maxPriorityFeePerGas: '0x77359400', - nonce: '0x46e01e', - r: '0xf9f8024c8a5a8d315e8a0ccf510e8547d62c69b9636919f377ee842232859567', - s: '0x5390ff89bea1d8b8266a335008feec1c358b4bd1becf0dffde1786ccdc31201a', - to: '0xf229c5f132d805bc540347f4f09cae4beb1ce2fc', - transactionIndex: '0x35', - type: '0x2', v: '0x0', - value: '0x44913f6c2a40000', + r: '0x86c5a957bb87e42a131c60293f7b4dbe465ffd2ef982893bdd8e167719de423f', + s: '0x6d34667725848de46dcb357d098266662e5e48383baafbb2c6f9b52e9f2c3908', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x21a31ee1afc51d94c2efccaa2092ad1028285549', - gas: '0x32918', - gasPrice: '0x4eb7cb584', - hash: '0xd2ae45072ed92e1c0f0dc9770700e2aea61c564c3cf9966043fcb4ff503e6bc5', - input: '0x', - maxFeePerGas: '0x17bfac7c00', - maxPriorityFeePerGas: '0x77359400', - nonce: '0x5e0f0f', - r: '0x7ef2595e0b05eb9a2780638182a91cf79fa9a4176f9664c429812813729fca60', - s: '0x46cb312550a3e0f046798aff756ab0ac2517a1e44272e2928351d0ecc2192359', - to: '0xd5e7c8051bb55471e65c77735246037b88887794', - transactionIndex: '0x36', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x9d5e64c022119046d3674a878318bc0596424398', + gas: '0x511a2', + gasPrice: '0xd84954223', + maxFeePerGas: '0xe042d1ce4', + maxPriorityFeePerGas: '0xba43b7400', + hash: '0xee0003228eef79a57b7cd7ed3af7731975cfd03960742f9c913f2145378783f2', + input: '0x3d0e3ec500000000000000000000000000000000000000000000000000501274c9e471fe000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000009d5e64c022119046d3674a878318bc05964243980000000000000000000000000000000000000000000000000000000066fb25a80000000000000000000000005c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f00000000000000000000000000000000000000000000000000000000000000020000000000000000000000006ec85a586f5dde2874d259e1d6ebaea4fde1da32000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', + nonce: '0x1c', + to: '0x80a64c6d7f12c47b7c66c5b4e20e72bc1fcd5d9e', + transactionIndex: '0x2', + value: '0x0', type: '0x2', - v: '0x0', - value: '0x7357ed86abd800', - }, - { accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x4976a4a02f38326660d17bf34b431dc6e2eb2327', - gas: '0x32918', - gasPrice: '0x4eb7cb584', - hash: '0x3a9d565f5193dbfd7bdae074e6405d6cd0d6334a99b23d4780afdf70730ea265', - input: '0x', - maxFeePerGas: '0x17bfac7c00', - maxPriorityFeePerGas: '0x77359400', - nonce: '0x264d0b', - r: '0x014efa044805a0b57331d02fdc260ed97eddd05a65671ca559349f0740c02f5d', - s: '0x5acb03bf01c45c1d54cc92048c16cfb0c1502e37977351dfeffab81516b3d530', - to: '0x7959c8788c426988cb5dc3d7d164458af8ffc1d6', - transactionIndex: '0x37', - type: '0x2', v: '0x0', - value: '0x109e2955efd8000', + r: '0x6216bf20997cc53776408ca5067e92e105432d988c0b1d9fb641d521f7569825', + s: '0x255ba3b7dc37130ab2da6840c756e54439fb3261f18905d964f64cdb0cfe9a92', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x9696f59e4d72e237be84ffd425dcad154bf96976', - gas: '0x32918', - gasPrice: '0x4eb7cb584', - hash: '0xe3a4f72856bfda9647b3699182bd386445ac649dcc8b1ce16e00ffcfbf4ab7ed', - input: '0x', - maxFeePerGas: '0x17bfac7c00', - maxPriorityFeePerGas: '0x77359400', - nonce: '0x41987b', - r: '0x26586b1e9ee91d0d5a1a67c115e3ef25af632bd04f669dabd629cc2ff73b7bad', - s: '0x5a5f39c4da031bff3bc027f717750ca4aee70a2fcba228fd3cf89a15eb1208e0', - to: '0xe0b27a0f1bae4128dd35cd1cd9591e2c9e25c14e', - transactionIndex: '0x38', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xaa0dfbd28d284542280a8eb3b94317d25cbc3d15', + gas: '0x52b6d', + gasPrice: '0xa06836c23', + maxFeePerGas: '0xa861b46e4', + maxPriorityFeePerGas: '0x826299e00', + hash: '0xce0140df7c5a13652c604946936996558a7b6ec3b5d87a6ce423a7bc94297cda', + input: '0x3d0e3ec5000000000000000000000000000000000000000000000000000433fd86790f5200000000000000000000000000000000000000000000000001188ccd4e5b656a00000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000aa0dfbd28d284542280a8eb3b94317d25cbc3d150000000000000000000000000000000000000000000000000000000066fb25a80000000000000000000000005c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000f039e70f3a4a405ec8e1977e67ab39b338671e97000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', + nonce: '0xfb', + to: '0x80a64c6d7f12c47b7c66c5b4e20e72bc1fcd5d9e', + transactionIndex: '0x3', + value: '0x0', type: '0x2', - v: '0x1', - value: '0x124d2084a70f6800', - }, - { accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x3dce71f75f239acf6d96e21185b171113997cb94', - gas: '0xc350', - gasPrice: '0x4eb7cb584', - hash: '0xd8640e034189ad0e1c19c56cc4283d58a6fb953eb4b07490f1908de722939c36', - input: '0x095ea7b30000000000000000000000003018018c44338b9728d02be12d632c6691e020d1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', - maxFeePerGas: '0x773594000', - maxPriorityFeePerGas: '0x77359400', - nonce: '0x0', - r: '0x06a9fade08677d36f80060a150829cf89b6a5d93a6bd49125ed445c06e8a2070', - s: '0x71caad84e2b4ad5abf4f0e7819a0c75b78d82cec724bc00f9871c6cff20cc1ee', - to: '0xdac17f958d2ee523a2206206994597c13d831ec7', - transactionIndex: '0x39', - type: '0x2', v: '0x1', - value: '0x0', + r: '0xb8bf5f6c789b1fb303ec461dfda5c18b0c5d15d16633c8e53fbb302a3a730473', + s: '0x4a51b7e4ef7e64d647d01c899f15acdfe3afd364c4aea01e931c2ff61f3dd99b', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0xf51cd688b8744b1bfd2fba70d050de85ec4fb9fb', - gas: '0x33450', - gasPrice: '0x4eb7cb584', - hash: '0x52afd7942b5e6b188b162fbef65fea001d87904a218a1863cd55e35c38152d32', - input: '0x', - maxFeePerGas: '0x5d21dba000', - maxPriorityFeePerGas: '0x77359400', - nonce: '0x1106f', - r: '0x71ed70b9d1c74ae1ad4feb6b4df85667ffdb140cd33598a671ce6132b4705023', - s: '0x522d3672a3ccd0d19a9219b07cfa50330016c40eb6747a3b0d01d429de6b9162', - to: '0x53d583a2e9d318f770355a502730e074a77704a5', - transactionIndex: '0x3a', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xea3575fa834d06a78b0528adf9ec5da209e0c69b', + gas: '0x4e304', + gasPrice: '0x345fa8a23', + maxFeePerGas: '0x3c59264e4', + maxPriorityFeePerGas: '0x165a0bc00', + hash: '0x90f9c51bf847a60f73a9b776629822733e2298f1927c0ae03d63f53ee31012a7', + input: '0x3d0e3ec50000000000000000000000000000000000000000000000000a95ac686e27ff33000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000ea3575fa834d06a78b0528adf9ec5da209e0c69b0000000000000000000000000000000000000000000000000000000066fb25a80000000000000000000000005c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000b9612ce2807de435a562b40a5ba9200ab86065e1000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', + nonce: '0x1d5', + to: '0x80a64c6d7f12c47b7c66c5b4e20e72bc1fcd5d9e', + transactionIndex: '0x4', + value: '0x0', type: '0x2', - v: '0x1', - value: '0x1aa535d3d0c0000', - }, - { accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0xf51cd688b8744b1bfd2fba70d050de85ec4fb9fb', - gas: '0x33450', - gasPrice: '0x4eb7cb584', - hash: '0xb261c0e8b9db2323039cd792af63941d6891e59f9a47fb920a1cfa70188284a3', - input: '0x', - maxFeePerGas: '0x5d21dba000', - maxPriorityFeePerGas: '0x77359400', - nonce: '0x11070', - r: '0x79abe4e602462702a701e8e8dafb766b49e1d0b5090f7d07067e8712d0fc1d79', - s: '0x68fae44682a2c1eb0f4c61013f26716b3146e0874b46ca5f3956c882d577c3a0', - to: '0x6a53202a46f1d598bb3e1bd75e76325be9e85a62', - transactionIndex: '0x3b', - type: '0x2', v: '0x0', - value: '0xd2c6806d3c0000', + r: '0x1394e039581ccb84b217ccfe3a9c426c0710a25341088d174f64d0f993bfd4d7', + s: '0x794898434b2d325255176ce2e3b12a87ece99de3ba79bd7e9a78a36ba48f2683', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0xf60c2ea62edbfe808163751dd0d8693dcb30019c', - gas: '0x32918', - gasPrice: '0x4eb7cb584', - hash: '0x545a0dafc33502a9e74440ffe4aaeb896a6c2248c1d5e02b2a211936f97fe375', - input: '0xa9059cbb000000000000000000000000e64fe3abefb9ef257a5468e3af3ce839d2801ad2000000000000000000000000000000000000000000000000000000001af6d8e8', - maxFeePerGas: '0xdf8475800', - maxPriorityFeePerGas: '0x77359400', - nonce: '0x19015b', - r: '0xdccc9185a0dabffd612a8e3e7965e7e3e1827ea11375eeca23fa17f0e313f092', - s: '0x242f817d6ac64b27ce324d57167990b12050ce197d875b7a77407dfaee1fe34a', - to: '0xdac17f958d2ee523a2206206994597c13d831ec7', - transactionIndex: '0x3c', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x5bc0dfbbac955890f3a649b66c3a1fa410bf7ace', + gas: '0x4768e', + gasPrice: '0x30a5fc023', + maxFeePerGas: '0x389f79ae4', + maxPriorityFeePerGas: '0x12a05f200', + hash: '0xd1681df399f4f39400bd73afabcfc07dda96ac80d97ed4d13a62dc28d127c871', + input: '0x088890dc0000000000000000000000000000000000000000000000000570296aafeaa26800000000000000000000000000000000000000000000000000000000000000a00000000000000000000000005bc0dfbbac955890f3a649b66c3a1fa410bf7ace0000000000000000000000000000000000000000000000000000000066fb25a80000000000000000000000005c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000037c0d73d510f6f289414c81dd36e2d8a1ad7e819', + nonce: '0x40', + to: '0x80a64c6d7f12c47b7c66c5b4e20e72bc1fcd5d9e', + transactionIndex: '0x5', + value: '0x214e8348c4f0000', type: '0x2', - v: '0x1', - value: '0x0', - }, - { accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0xdfd5293d8e347dfe59e90efd55b2956a1343963d', - gas: '0x32918', - gasPrice: '0x4eb7cb584', - hash: '0x5e48f0c28319b84d3ea08d316b91dc23d6ddcff46c4064760d2f83d848ede467', - input: '0xa9059cbb000000000000000000000000df90abe5ed346a74977b5d92ac6a264e25a9c51f0000000000000000000000000000000000000000000000008ae2b2e0ac12e000', - maxFeePerGas: '0x17bfac7c00', - maxPriorityFeePerGas: '0x77359400', - nonce: '0x599698', - r: '0xd42ab7d5efa8e62fc0aeb51c5f9b674f936d282c31f601fe51bc4cb00d958f59', - s: '0x04b83091ca937fc4f64b29c36406d4fed6b47f6c247ca86b5c0b4b3eec3110bd', - to: '0x0bc529c00c6401aef6d220be8c6ea1667f6ad93e', - transactionIndex: '0x3d', - type: '0x2', v: '0x1', - value: '0x0', + r: '0x0ec5a4a74a6a6467ec2032bf2e495e683e748be369f2c66a39fd49932b0459ee', + s: '0x69c4e8d02a9e552b4adfd6ea57b86b857aee3315d09d88da913bf729e5ae03ee', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x56eddb7aa87536c09ccc2793473599fd21a8b17f', - gas: '0x32918', - gasPrice: '0x4eb7cb584', - hash: '0x848514cee29d37999e27991e25c2cd58edc0486fdbcd2bf673a14d0e37bc3d12', - input: '0x', - maxFeePerGas: '0x17bfac7c00', - maxPriorityFeePerGas: '0x77359400', - nonce: '0x46e01f', - r: '0xc30f5f8b8d05b1a5c3b74669ff383d2588fa86c0f35d5066e2815b144a61199d', - s: '0x16b0c495b6cf1d01675d907a480460a57e715da42365140dba84cd035629a213', - to: '0xa294cca691e4c83b1fc0c8d63d9a3eef0a196de1', - transactionIndex: '0x3e', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xbbff54095b09940a4046e21ed5053f1ea2a1c581', + gas: '0x4e304', + gasPrice: '0x2932a2c23', + maxFeePerGas: '0x312c206e4', + maxPriorityFeePerGas: '0xb2d05e00', + hash: '0x79fd3cd0c84acfbb1b9c8f2ab33517626eceb8cb42c21f1c21439ce36e0e6cab', + input: '0x3d0e3ec50000000000000000000000000000000000000000000000001a33261efb6495ca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000bbff54095b09940a4046e21ed5053f1ea2a1c5810000000000000000000000000000000000000000000000000000000066fb25a80000000000000000000000005c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000b9612ce2807de435a562b40a5ba9200ab86065e1000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', + nonce: '0x3d9', + to: '0x80a64c6d7f12c47b7c66c5b4e20e72bc1fcd5d9e', + transactionIndex: '0x6', + value: '0x0', type: '0x2', - v: '0x0', - value: '0x31e0da46bd4a88000', - }, - { accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x28c6c06298d514db089934071355e5743bf21d60', - gas: '0x32918', - gasPrice: '0x4eb7cb584', - hash: '0x5c1464d4fd1ef55d3fc1c1e9338917273b1d2280fd06fe04afa607557ab9c9d9', - input: '0xa9059cbb0000000000000000000000003aff86656a65f3d81b3e0b4c4f8d4199f3b3fbde0000000000000000000000000000000000000000000003825cc1b4837cd61c00', - maxFeePerGas: '0x17bfac7c00', - maxPriorityFeePerGas: '0x77359400', - nonce: '0x621091', - r: '0x3d047d1e1b05d563adc9206ffa9c210d01018ec50bf674c50783a6428347bc9b', - s: '0x3063c3dc89bba20743758230f5015d30926c7da5ecaa150bd969d8fc80d1981c', - to: '0x0f5d2fb29fb7d3cfee444a200298f468908cc942', - transactionIndex: '0x3f', - type: '0x2', v: '0x1', - value: '0x0', + r: '0xac126c6ad95a7a8970ce4ca34d61a3a2245e8d7f11bde871dd66ac43435405c6', + s: '0x1beeda8ed32586243281807ee42d8e524d5050bd7f224f62e5dce812472ecee5', }, { - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xe75ed6f453c602bd696ce27af11565edc9b46b0d', + gas: '0xad653', + gasPrice: '0x327f0419c', + maxFeePerGas: '0x327f0419c', + maxPriorityFeePerGas: '0x327f0419c', + hash: '0x98bd6c18c9a40ae4f1e6c12dc40173be751cf1cab68826e266aa9c854b91022e', + input: '0x952271200ea8a9c99f6adc600a8ccda5440b5740f37f3d3c2cfc000000000000018ba8e7000000002406f6683e39fddadc3d220aa5d4a0789667c01fcfba90017efb873c050b8ca51e07b9f30e29061d45e45382effd0e379d18973df12c02010acf0d3c84ff56261800240ebcf4dc76ac6e81e81930822d1b1b1f50eef67a5b849e6c77d33e001f0f32c555d55279023e732ccd32d812114caf5838fd4601115da13c07b9750874e6fb8dca30ce41d445e4baf8c76971f912013f089f3c0d8716771a00240ebcdd9abb2bbf29ac56e9718e768043114e46c6130dbc66773b1e001f0f32c555d55279023e732ccd32d812114caf5838fd4601450ff73c006d', + nonce: '0x2f0d8', + to: '0x00000000009e50a7ddb7a7b0e2ee6604fd120e49', + transactionIndex: '0x7', + value: '0x18ba8e7', + type: '0x2', + accessList: [ + { + address: '0x812ba41e071c7b7fa4ebcfb62df5f45f6fa853ee', + storageKeys: [ + '0x000000000000000000000000000000000000000000000000000000000000000f', + '0x000000000000000000000000000000000000000000000000000000000000000b', + '0xb04a1206ea6c7e1296f87734b85431b4368ffeced6bc420853a025149ce1e7c5', + '0x0000000000000000000000000000000000000000000000000000000000000014', + '0xf6ab36bec72a5a6fb46bdad2ab27972aea416d58b02d7ed3c4b69f89f34af92f', + '0x000000000000000000000000000000000000000000000000000000000000000a', + '0x0000000000000000000000000000000000000000000000000000000000000007', + '0x000000000000000000000000000000000000000000000000000000000000000d', + '0x4e823913d43be38662c8211c9c13b24022f2db9d6cccabca7d35c085a77dfee7', + '0xfb8777cd9b0c0df04170425c299a5a8573399e279f552c382514b98466a87481', + '0x0000000000000000000000000000000000000000000000000000000000000000', + '0x000000000000000000000000000000000000000000000000000000000000000c', + '0x8c9b81a98cbf4d0292b994f480011101d1f84a7fcde2dfc72caae39c57c59efc', + '0x55bd389fee2ec1512750c0175b3ae345be73d2aa52d1f1db2744f6cc252cc424', + '0x0000000000000000000000000000000000000000000000000000000000000019', + '0x31391b1a81c9468111d2fff255bd8f3af28cf11bbfb2451f8aa2e16bfad02ef8', + ], + }, + { + address: '0x750874e6fb8dca30ce41d445e4baf8c76971f912', + storageKeys: [ + '0x000000000000000000000000000000000000000000000000000000000000000a', + '0x000000000000000000000000000000000000000000000000000000000000000c', + '0x0000000000000000000000000000000000000000000000000000000000000008', + '0x0000000000000000000000000000000000000000000000000000000000000006', + '0x0000000000000000000000000000000000000000000000000000000000000007', + '0x0000000000000000000000000000000000000000000000000000000000000009', + ], + }, + { + address: '0x683e39fddadc3d220aa5d4a0789667c01fcfba90', + storageKeys: [ + '0x000000000000000000000000000000000000000000000000000000000000000c', + '0x0000000000000000000000000000000000000000000000000000000000000008', + '0x0000000000000000000000000000000000000000000000000000000000000006', + '0x0000000000000000000000000000000000000000000000000000000000000007', + '0x0000000000000000000000000000000000000000000000000000000000000009', + '0x000000000000000000000000000000000000000000000000000000000000000a', + ], + }, + { + address: '0xf30e29061d45e45382effd0e379d18973df12c02', + storageKeys: [ + '0x0000000000000000000000000000000000000000000000000000000000000009', + '0x000000000000000000000000000000000000000000000000000000000000000a', + '0x000000000000000000000000000000000000000000000000000000000000000c', + '0x0000000000000000000000000000000000000000000000000000000000000008', + '0x0000000000000000000000000000000000000000000000000000000000000006', + '0x0000000000000000000000000000000000000000000000000000000000000007', + ], + }, + { + address: '0xf4dc76ac6e81e81930822d1b1b1f50eef67a5b84', + storageKeys: [ + '0x0000000000000000000000000000000000000000000000000000000000000009', + '0x000000000000000000000000000000000000000000000000000000000000000a', + '0x000000000000000000000000000000000000000000000000000000000000000c', + '0x0000000000000000000000000000000000000000000000000000000000000008', + '0x0000000000000000000000000000000000000000000000000000000000000006', + '0x0000000000000000000000000000000000000000000000000000000000000007', + ], + }, + { + address: '0x3739426e21d912b604c106f852d136ba58f61517', + storageKeys: [ + '0x62a8f1eda425118931952cf1eb3d435bde7a6579a6c643f9d4b6516acf370f2f', + '0x680913d55151412298e3952b1537663fefcf86e575575feb267d0246af890016', + ], + }, + { + address: '0xc555d55279023e732ccd32d812114caf5838fd46', + storageKeys: [ + '0x000000000000000000000000000000000000000000000000000000000000000c', + '0x0000000000000000000000000000000000000000000000000000000000000008', + '0x0000000000000000000000000000000000000000000000000000000000000006', + '0x0000000000000000000000000000000000000000000000000000000000000007', + '0x0000000000000000000000000000000000000000000000000000000000000009', + '0x000000000000000000000000000000000000000000000000000000000000000a', + ], + }, + { + address: '0x8baf5d75cae25c7df6d1e0d26c52d19ee848301a', + storageKeys: [ + '0x60177e4bd920b03867708ce63b09ac1779158cb9d3aff57df7f90c2a57ecb05d', + '0x24eb64c0ea1d8c958332350702eef14f8f54e6fa5698d6a65c40706203861ba8', + '0x4ee13f8a600ee5b220e9653c3583d2e58d8e086db32a31c43644ccc927dd66d0', + '0x000000000000000000000000000000000000000000000000000000000000000b', + '0x0000000000000000000000000000000000000000000000000000000000000005', + '0x94f33b3c2527a1965ee091af77384a01b1cbb517a59e901c17db0d5351e08b75', + '0x562e03f0ef04d7eee09aea760066264315d82514e5b29d556f5897f729ab9834', + '0x0000000000000000000000000000000000000000000000000000000000000010', + '0xa2419f055dc7815b5e46cd1712b1fefe09508dccc64bf72dfb59fbb6e7ed0da2', + '0x0000000000000000000000000000000000000000000000000000000000000009', + '0xc62360d4c73998b8f963082202c5e8ff4627df51c05fc972d5dbf424a67dd634', + '0x000000000000000000000000000000000000000000000000000000000000001d', + '0xf08a829b01f863dd4fd548b79975809523acd75c2311a3788978f42abac48049', + '0x0eb91146122b19d7be6e4e277c7d20f3c1e03ea395c1edd91fd4a3f205f1c185', + ], + }, + { + address: '0xdd9abb2bbf29ac56e9718e768043114e46c6130d', + storageKeys: [ + '0x000000000000000000000000000000000000000000000000000000000000000c', + '0x0000000000000000000000000000000000000000000000000000000000000008', + '0x0000000000000000000000000000000000000000000000000000000000000006', + '0x0000000000000000000000000000000000000000000000000000000000000007', + '0x0000000000000000000000000000000000000000000000000000000000000009', + '0x000000000000000000000000000000000000000000000000000000000000000a', + ], + }, + { + address: '0x0ea8a9c99f6adc600a8ccda5440b5740f37f3d3c', + storageKeys: [ + '0x0000000000000000000000000000000000000000000000000000000000000000', + '0x0000000000000000000000000000000000000000000000000000000000000004', + '0x0000000000000000000000000000000000000000000000000000000000000001', + '0x3e5fec24aa4dc4e5aee2e025e51e1392c72a2500577559fae9665c6d52bd6a31', + '0x0000000000000000000000000000000000000000000000000000000000000008', + ], + }, + { + address: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', + storageKeys: [ + '0xe48bc08c8ce04355ce1379b42464b6258666bd2a783f94767a9ba43cc827f3ba', + '0xd06b641b2455ec971fcd9193ac18a362f8aa0ca0f7e3a201214d6f563b202601', + '0x183b74f0c947f6f400ea1572b660576be5228d83d47a7c2a8823058f626adee6', + '0x7bc913c661f71064cc80d5dff39efa8510e3bbf72c891a4fa1cbfe224edf9c35', + '0x5a5c3a8c2ed5e63e50f2255a3450eed532f8728e8f4ee4fcc375c3049af1973d', + '0x56f373e9d6cead7892678a24f7c3788d34dde7a0f956c9f66bb02254e258b4a6', + ], + }, + { + address: '0x6de73ced5dd4c33235f9f4bf5de47b5d33c6392a', + storageKeys: [ + '0x7d36e4a930ebd89f5a5ead568aea5265678129d78a43add6687316e9db5ad20b', + '0xa7fac94f492efbc3a4f11963e4ff48a118ab6e9430380fbed955555a2af1c070', + '0x0000000000000000000000000000000000000000000000000000000000000009', + '0xf54f45b40ebb722093dae161c18fc43d42dd70ce0d46b53eac7031e7ea5c6cef', + '0x000000000000000000000000000000000000000000000000000000000000000c', + '0xedc49973017be83d356f8812338163d296cbd9eed650e9136ce4bb81eb55e2c1', + '0x1838d98a4a23c80322c60a17fbd575bd68d422eff790af69966886924644e895', + '0x0000000000000000000000000000000000000000000000000000000000000010', + '0xd5b09859cd164e1aff4477adba2017a2dd8643059cd3507f50862eff4df0d619', + '0x000000000000000000000000000000000000000000000000000000000000000f', + '0x000000000000000000000000000000000000000000000000000000000000000d', + '0xa64a098cc65ff1d1c6bcec8a4e3c3aff7116981660f7087bca40bfd4dca93e11', + '0xca36686ef5bff56fd29ce46db9d2182cf6c0b5b3307931c5c62ec800d63c1254', + '0x0000000000000000000000000000000000000000000000000000000000000005', + '0x000000000000000000000000000000000000000000000000000000000000000e', + ], + }, + ], chainId: '0x1', - from: '0x9d98180089adfe81f4a6c76e6b978284bd2bb3f5', - gas: '0x5208', - gasPrice: '0x4e3b29200', - hash: '0x461702cf4d7d04f70337251a6ce8aa386f96a55214eae9e71697ad2e3d686acf', - input: '0x', - nonce: '0xbb', - r: '0xdc70f934495c5a38a3e2418e0d075223094a899dea70cf95f10f1c5facbb772b', - s: '0x063b2d0f20585b959447460b5daa22c5bd0696c074ded4d31d4078b0dcae653a', - to: '0x6d1ea4bd89865bbd8c675261585ae566dcda9d53', - transactionIndex: '0x40', - type: '0x0', - v: '0x26', - value: '0x2386f26fc10000', + v: '0x1', + r: '0xff91e352c5a47a779c917b0be295886a39aa6d29c4240fcd292b5aaea073dc69', + s: '0x5c957a2d80790755cb204f4ef218c4dde164dac6ae47a06921f2b2235d737dce', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x98abe8b8c7a0c22f2d17c8e007e4bd4777e8d116', + gas: '0x4def2', + gasPrice: '0x492929523', + maxFeePerGas: '0x174876e800', + maxPriorityFeePerGas: '0x2b238c700', + hash: '0x78930161632382a4a85465cb643898c748980d3e302c720ef87e938e1e8067fc', + input: '0x791ac9470000000000000000000000000000000000000000000000000c6293141e887050000000000000000000000000000000000000000000000000015d7884e94074d100000000000000000000000000000000000000000000000000000000000000a000000000000000000000000098abe8b8c7a0c22f2d17c8e007e4bd4777e8d1160000000000000000000000000000000000000000000000000000000066fb25b5000000000000000000000000000000000000000000000000000000000000000200000000000000000000000076a30c79b0ef3c28913404531c0eaacb577ca1d1000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', + nonce: '0x65b', + to: '0x7a250d5630b4cf539739df2c5dacb4c659f2488d', + transactionIndex: '0x8', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x8f339591b959e8fe2e6127124812613e482f84ab', - gas: '0x73f68', - gasPrice: '0x4e3b29200', - hash: '0x4d0b6bd0b7dc8b332fc7f80c3c5774c467080976fa2460d85a9c032a3e230d94', - input: '0xeb6724190000000000000000000000008f339591b959e8fe2e6127124812613e482f84ab000000000000000000000000000000000000000000000000002aa1efb94dffff00000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000b54a3000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000001000000000000000000000000008f339591b959e8fe2e6127124812613e482f84ab00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x4e3b29200', - maxPriorityFeePerGas: '0xacda7d00', - nonce: '0x0', - r: '0xd96426125d5a851dccec746787824af395da54613e62f1a5d53ce45754c2d00a', - s: '0x7a089b28b3426eb5624136e3fb7c7336eabf8d3a7b4f10f11cd1d3c86bea8967', - to: '0x32400084c286cf3e17e7b677ea9583e60a000324', - transactionIndex: '0x41', - type: '0x2', v: '0x1', - value: '0x2c732b36ea6937', + r: '0xf0c3a414b777fccb04d0eff4d565d3b0b24c08b5009b8e628a38462976419ef5', + s: '0x4bad399d77b3d2e8307cbc0e3e88b306d34fb1b459e10540964e30a247edec5b', }, { - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x670bb2fa1231550fccaec308e6ed03b98d2f90fa', - gas: '0x3f13b', - gasPrice: '0x4e3b29200', - hash: '0x06ad8cefc9d677ea422fedbbc23fe323f830070fbc93ee394abf986453026dc5', - input: '0xac9650d8000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000084fc6f78650000000000000000000000000000000000000000000000000000000000076d3e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff00000000000000000000000000000000ffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004449404b7c00000000000000000000000000000000000000000000000002b2c9dcaace8ec1000000000000000000000000670bb2fa1231550fccaec308e6ed03b98d2f90fa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064df2ab5bb00000000000000000000000080f0c1c49891dcfdd40b6e0f960f84e6042bcb6f0000000000000000000000000000000000000000000000009be96c72185d79e7000000000000000000000000670bb2fa1231550fccaec308e6ed03b98d2f90fa00000000000000000000000000000000000000000000000000000000', - nonce: '0x12b', - r: '0x6364548a5358fd5fd6a6d7693261455e859e9e6e12bc1571d67e894992c31836', - s: '0x377afabdffa95ce2f6b7738a9663500e128046be8f7ff08cf53e1a7fa54f9f13', - to: '0xc36442b4a4522e871399cd717abdd847ab11fe88', - transactionIndex: '0x42', - type: '0x0', - v: '0x26', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x555ce236c0220695b68341bc48c68d52210cc35b', + gas: '0x713f6', + gasPrice: '0x28b142987', + maxFeePerGas: '0x2d7a4cf79', + maxPriorityFeePerGas: '0xaaba5b64', + hash: '0x7df40bcfc939178a451a97fe73bbbc1919ecacf1e82fc0c6a477c74cdce96c44', + input: '0xc7a76969000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000060ac28000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000e7351fd770a37282b91d153ee690b63579d6dd7f00000000000000000000000000000000000000000000000000000000000005e071424c97041a808a4b60339bb68f1634eaea6c4e91cdb8b11b0dcc61bab3c20e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111111254eeb25477b68fb85ed929f73a96058200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000085374a6a8f65db000000000000000000000000555ce236c0220695b68341bc48c68d52210cc35b000000000000000000000000000000000000000000000000000000000000040812aa3caf000000000000000000000000e37e799d5077682fa0a244d46e5649f71457bd09000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee000000000000000000000000e37e799d5077682fa0a244d46e5649f71457bd09000000000000000000000000663dc15d3c1ac63ff12e45ab68fea3f0a883c25100000000000000000000000000000000000000000000000000000000060ac28000000000000000000000000000000000000000000000000000888f0f0b6ab9270000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000026200024c0002105120111111125421ca6dc452d289314280a0f8842a65a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480124cc713a0448bfedf6435ccb835e6d310d42e74aa8251e9533393c3c26c0a3c00d10487118000000000000000000000000807cf9a772d5a3f9cefbc1192e939d62f0d9bd380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000089f02e2fd752f600000000000000000000000000000000000000000000000000000000060ac280000000000000000000000000000001fcf10066fb25cd000000000000000000000000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041531fe96c84b58e995905ff89d2d50d73acf68d98f6734b15f547f9e404a11e4a2d177511da6cb7736955cc4b0000c68210d0c6c811bdfb1420ff0ebf66559c7f1c000000000000000000000000000000000000000000000000000000000000004101c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200042e1a7d4d0000000000000000000000000000000000000000000000000000000000000000c0611111111254eeb25477b68fb85ed929f73a960582fef84ee90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000464c358547e00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000085374a6a8f65db71424c97041a808a4b60339bb68f1634eaea6c4e91cdb8b11b0dcc61bab3c20e0000000000000000000000000000000000000000000000000000000000000440000000000000000000000000555ce236c0220695b68341bc48c68d52210cc35b00000000000000000000000000000000000000000000000000000192450907fc00000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000736f6c00000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000006804254000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000085374a6a8f65db000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000000204a930d99f75a8796cbc7a8361c3dccfbe4241f943f77889d732dc925e5229f990000000000000000000000000000000000000000000000000000000000000020c6fa7af3bedbad3a3d65f36aabc97431b1bbe4c2d2f6e0e47ca60203452f5d61000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014beff486ff699f2f05bd0f11cf0bd49be86018faa00000000000000000000000000000000000000000000000000000000000000000000000000000000000000204a930d99f75a8796cbc7a8361c3dccfbe4241f943f77889d732dc925e5229f990000000000000000000000000000000000000000000000000000000000000014beff486ff699f2f05bd0f11cf0bd49be86018faa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', + nonce: '0x1c5d4', + to: '0x663dc15d3c1ac63ff12e45ab68fea3f0a883c251', + transactionIndex: '0x9', value: '0x0', + type: '0x2', + accessList: [], + chainId: '0x1', + v: '0x0', + r: '0x5719291b61a39f046a758b5225010d50e6303f83a14cde18b559181919a47b2b', + s: '0x7129b20c70935b89427152c111ff7105b9ed0ce4a90f520f112a7eb43e3d3e01', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x392a8e864174a05f9065bbd2e142b8a1c1165fef', + gas: '0x45241', + gasPrice: '0x32230c3f5', + maxFeePerGas: '0x32230c3f5', + maxPriorityFeePerGas: '0x1f0aa775b', + hash: '0xee72ee26a30d266273173fc50c498a87d690b4728f11b2bfeb88c3a65830e5ee', + input: '0x68cdab9c0000000000000000000000000000000000000000000000000000000066fb25e8000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000e4472b43f300000000000000000000000000000000000000000000000000948101a55692d800000000000000000000000000000000000000000000000000426b86e61cbb4400000000000000000000000000000000000000000000000000000000000000800000000000000000000000005c9321e92ba4eb43f2901c4952358e132163a85a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000b9612ce2807de435a562b40a5ba9200ab86065e1000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000849b2c0a370000000000000000000000000000000000000000000000000000000000000005000000000000000000000000392a8e864174a05f9065bbd2e142b8a1c1165fef000000000000000000000000000000000000000000000000000000000000004600000000000000000000000027b9c20f64920eb7fbf64491423a54df9594188c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000026e61000000000000000000000000000000000000000000000000000000000000', + nonce: '0x3c', + to: '0x5c9321e92ba4eb43f2901c4952358e132163a85a', + transactionIndex: '0xa', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0xa50c14352cce7a143afa38555fdc7354dd78c379', - gas: '0x24a50', - gasPrice: '0x4cdaf5084', - hash: '0xd77ad6002fc4ccec33de15972123777c0e036cf8f2ce5e1a4d858dd99b11cbd3', - input: '0xeb672419000000000000000000000000a50c14352cce7a143afa38555fdc7354dd78c379000000000000000000000000000000000000000000000000006ab07fb082640000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000b54a300000000000000000000000000000000000000000000000000000000000003200000000000000000000000000000000000000000000000000000000000000100000000000000000000000000a50c14352cce7a143afa38555fdc7354dd78c37900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x78c3985ec', - maxPriorityFeePerGas: '0x59682f00', - nonce: '0x0', - r: '0xd3a28cbf01498f92e51523725981c11a34f07b11ac6a7ef89de5ce17e4b868d5', - s: '0x779ba46af5a72f75f32fda1d33f9f7bd8330e75dada67021deb98b72785820f8', - to: '0x32400084c286cf3e17e7b677ea9583e60a000324', - transactionIndex: '0x43', - type: '0x2', - v: '0x1', - value: '0x6c81bb2e1ecd38', + v: '0x0', + r: '0x42e31a4f1249c26870afbf3921be8daac88c255a9f942676985661b6bde84518', + s: '0x4ac9646e10b4254cac0e44bf5121c380866c171aa1b8254ae70add6e7413db4e', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xd41cda97e6e62bde017a72d29637024667894d6b', + gas: '0x6f95d', + gasPrice: '0x30a5fc023', + maxFeePerGas: '0x43465b223', + maxPriorityFeePerGas: '0x12a05f200', + hash: '0x0bd388895c3746fba476fe54d3e03b3b541f673dcad2f8c22db88370ca8737a2', + input: '0x0162e2d000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001600000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000750000000000000000000000000000000000000000000000000000000066fb25a7000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000005e72936829f451000000000000000000000000000000000000000000000000004b27bb0879642f8157500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000005de63b91781bbecdb5def6a308f7225bd287fbbc', + nonce: '0x37c', + to: '0x3328f7f4a1d1c57c35df56bbf0c9dcafca309c49', + transactionIndex: '0xb', + value: '0x16345785d8a0000', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0xf4c0d5993b8c5ebc8857e631b1fa659c8c665421', - gas: '0x24a41', - gasPrice: '0x4cdaf5084', - hash: '0x3c829847832f898dd18a8674e81eba1e7179912397f48a53e31b6d98ad79026d', - input: '0xeb672419000000000000000000000000f4c0d5993b8c5ebc8857e631b1fa659c8c66542100000000000000000000000000000000000000000000000000b1a2bc2ec5000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000b54a300000000000000000000000000000000000000000000000000000000000003200000000000000000000000000000000000000000000000000000000000000100000000000000000000000000f4c0d5993b8c5ebc8857e631b1fa659c8c66542100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x78c3985ec', - maxPriorityFeePerGas: '0x59682f00', - nonce: '0x8', - r: '0x958ac379821e137003d336592f95d3d095e2fc38b02de6284bd4a3958fbe0f84', - s: '0x1c654cd5b76f2e9ab14e2f1b13d7c9b80a05176667e13ed741b77bb6605d445c', - to: '0x32400084c286cf3e17e7b677ea9583e60a000324', - transactionIndex: '0x44', - type: '0x2', v: '0x0', - value: '0xb373f7ac616938', + r: '0xcd0696b4641f5eedd9aeccb36ffa36e46845e2afd6bcb99942494b5792f09552', + s: '0x138eeb874a069b6ae889d2be617c719245455fc55dff0401de4f68fb9ee40f50', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x646c14ed9fb840f57065fa85e9195f185a29f4b3', + gas: '0x534c2', + gasPrice: '0x246b849b6', + maxFeePerGas: '0x2f7e80093', + maxPriorityFeePerGas: '0x665e7b93', + hash: '0x3100f0c75bed957f6dd0a032b08a809431a2e90b887bb5533e49d90c74f5436e', + input: '0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000066fb27db000000000000000000000000000000000000000000000000000000000000000400080604000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000001000000000000000000000000008580a7b63d48190775c7ceb13eda5dd4cc01a6e2000000000000000000000000000000000000000000000000000000006192a340000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002bdac17f958d2ee523a2206206994597c13d831ec7000064c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0a5b5deed8600000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000fefe157c9d0ae025213092ff9a5cb56ab492bab80000000000000000000000000000000000000000000000000000000000000060000000000000000000000000fefe157c9d0ae025213092ff9a5cb56ab492bab8000000000000000000000000000000fee13a103a10d593b9ae06b3e05f2e7e1c00000000000000000000000000000000000000000000000000000000000000190000000000000000000000000000000000000000000000000000000000000060000000000000000000000000fefe157c9d0ae025213092ff9a5cb56ab492bab800000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000a0a5b5deed86', + nonce: '0x7d', + to: '0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad', + transactionIndex: '0xc', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x3651317060a0005dac1084a6f71a7285de1b6886', - gas: '0x15f90', - gasPrice: '0x4cdaf5084', - hash: '0xd90e21f60f14d0d6734a06a08ea72718c0da1dde84d927578f8bc3817eec2cfa', - input: '0xa9059cbb00000000000000000000000049a2fcfcf2b2025c667732ef0435f548aa6cd9dd000000000000000000000000000000000000000000000000000000001a6f45e0', - maxFeePerGas: '0x72c5225a5', - maxPriorityFeePerGas: '0x59682f00', - nonce: '0x3', - r: '0x5bfb19d897e19784d61a740277f615f275a80e32252d643860ade726d304feee', - s: '0x6d43017d363606b8a2cdf87f79c4becc33358b9cb8da6cc472470bfce3cee39d', - to: '0xdac17f958d2ee523a2206206994597c13d831ec7', - transactionIndex: '0x45', - type: '0x2', v: '0x0', - value: '0x0', + r: '0x34d11eaeb84c30119b5b75874bb9ea7bd0d66001ed18457c5b78784cb4f54838', + s: '0x0bc6a3de4fa4d88718a2f6b054fbe83551bc8f67670d7b1ca45cd45592725840', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x581b74f39a66d4159881f2fb9ab6427efb380e99', + gas: '0x2d0370', + gasPrice: '0x1ed798bbe', + maxFeePerGas: '0x1ed798bbe', + maxPriorityFeePerGas: '0x3b9aca00', + hash: '0xa09dc1486ca6715911aa3f78dfa894eb4e12ed4a2c87f50a0f68cc9fe790c048', + input: '0x60806040525f60095f6101000a81548160ff0219169083151502179055505f600960016101000a81548160ff021916908315150217905550348015610042575f5ffd5b506040516121a33803806121a38339818101604052810190610064919061021c565b5f61007361018460201b60201c565b9050805f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff165f73ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350600180819055508560025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555084600381905550836005819055508260068190555081600781905550806008819055505050505050506102a5565b5f33905090565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6101b88261018f565b9050919050565b6101c8816101ae565b81146101d2575f5ffd5b50565b5f815190506101e3816101bf565b92915050565b5f819050919050565b6101fb816101e9565b8114610205575f5ffd5b50565b5f81519050610216816101f2565b92915050565b5f5f5f5f5f5f60c087890312156102365761023561018b565b5b5f61024389828a016101d5565b965050602061025489828a01610208565b955050604061026589828a01610208565b945050606061027689828a01610208565b935050608061028789828a01610208565b92505060a061029889828a01610208565b9150509295509295509295565b611ef1806102b25f395ff3fe608060405260043610610122575f3560e01c80637e1c0c091161009f578063c8bdbfb611610063578063c8bdbfb6146103d2578063cbdd69b5146103e8578063d0febe4c14610412578063f2fde38b1461041c578063fc0c546a1461044457610162565b80637e1c0c09146103165780637e3d1cf51461034057806388770cb01461036a5780638da5cb5b14610392578063a0a6e940146103bc57610162565b8063518ab2a8116100e6578063518ab2a8146102585780636d49809314610282578063715018a6146102ac57806378e97925146102c25780637b1b1de6146102ec57610162565b80630d5cda701461019d5780630f6ca1a8146101c557806324600fc3146102025780633197cbb61461021857806348c54b9d1461024257610162565b36610162576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610159906114bd565b60405180910390fd5b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101949061154b565b60405180910390fd5b3480156101a8575f5ffd5b506101c360048036038101906101be91906115a0565b61046e565b005b3480156101d0575f5ffd5b506101eb60048036038101906101e69190611638565b610515565b6040516101f9929190611672565b60405180910390f35b34801561020d575f5ffd5b50610216610535565b005b348015610223575f5ffd5b5061022c6106c3565b6040516102399190611699565b60405180910390f35b34801561024d575f5ffd5b506102566106c9565b005b348015610263575f5ffd5b5061026c610952565b6040516102799190611699565b60405180910390f35b34801561028d575f5ffd5b50610296610958565b6040516102a391906116cc565b60405180910390f35b3480156102b7575f5ffd5b506102c061096b565b005b3480156102cd575f5ffd5b506102d6610abb565b6040516102e39190611699565b60405180910390f35b3480156102f7575f5ffd5b50610300610ac1565b60405161030d9190611699565b60405180910390f35b348015610321575f5ffd5b5061032a610ac7565b6040516103379190611699565b60405180910390f35b34801561034b575f5ffd5b50610354610acd565b60405161036191906116cc565b60405180910390f35b348015610375575f5ffd5b50610390600480360381019061038b91906116e5565b610adf565b005b34801561039d575f5ffd5b506103a6610c12565b6040516103b3919061171f565b60405180910390f35b3480156103c7575f5ffd5b506103d0610c39565b005b3480156103dd575f5ffd5b506103e6610d58565b005b3480156103f3575f5ffd5b506103fc610ff2565b6040516104099190611699565b60405180910390f35b61041a610ff8565b005b348015610427575f5ffd5b50610442600480360381019061043d9190611638565b611229565b005b34801561044f575f5ffd5b506104586113e8565b6040516104659190611793565b60405180910390f35b61047661140d565b73ffffffffffffffffffffffffffffffffffffffff165f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610503576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104fa906117f6565b60405180910390fd5b81600581905550806006819055505050565b600a602052805f5260405f205f91509050805f0154908060010154905082565b61053d61140d565b73ffffffffffffffffffffffffffffffffffffffff165f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146105ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105c1906117f6565b60405180910390fd5b6105d2611414565b5f4790505f8111610618576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161060f9061185e565b60405180910390fd5b610620610c12565b73ffffffffffffffffffffffffffffffffffffffff166108fc8290811502906040515f60405180830381858888f19350505050158015610662573d5f5f3e3d5ffd5b5061066b610c12565b73ffffffffffffffffffffffffffffffffffffffff167feaff4b37086828766ad3268786972c0cd24259d4c87a80f9d3963a3c3d999b0d826040516106b09190611699565b60405180910390a2506106c161145a565b565b60085481565b6106d1611414565b600960019054906101000a900460ff1680156106f8575060095f9054906101000a900460ff165b610737576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161072e906118ec565b60405180910390fd5b5f600a5f61074361140d565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206001015490505f81116107c4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107bb90611954565b60405180910390fd5b5f600a5f6107d061140d565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206001018190555060025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb61085561140d565b836040518363ffffffff1660e01b8152600401610873929190611992565b6020604051808303815f875af115801561088f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108b391906119e3565b6108f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e990611a58565b60405180910390fd5b6108fa61140d565b73ffffffffffffffffffffffffffffffffffffffff167f896e034966eaaf1adc54acc0f257056febbd300c9e47182cf761982cf1f5e4308260405161093f9190611699565b60405180910390a25061095061145a565b565b60045481565b600960019054906101000a900460ff1681565b61097361140d565b73ffffffffffffffffffffffffffffffffffffffff165f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610a00576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109f7906117f6565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff165f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35f5f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60075481565b60055481565b60035481565b60095f9054906101000a900460ff1681565b610ae761140d565b73ffffffffffffffffffffffffffffffffffffffff165f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610b74576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b6b906117f6565b60405180910390fd5b600960019054906101000a900460ff1615610bc4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bbb90611ac0565b60405180910390fd5b6008548111610c08576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bff90611b4e565b60405180910390fd5b8060088190555050565b5f5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b610c4161140d565b73ffffffffffffffffffffffffffffffffffffffff165f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610cce576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cc5906117f6565b60405180910390fd5b600960019054906101000a900460ff1615610d1e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d1590611ac0565b60405180910390fd5b6001600960016101000a81548160ff0219169083151502179055505f6004541160095f6101000a81548160ff021916908315150217905550565b610d6061140d565b73ffffffffffffffffffffffffffffffffffffffff165f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610ded576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610de4906117f6565b60405180910390fd5b610df5611414565b600960019054906101000a900460ff168015610e1c575060095f9054906101000a900460ff165b610e5b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e52906118ec565b60405180910390fd5b5f600454600354610e6c9190611b99565b90505f8111610eb0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ea790611c16565b60405180910390fd5b60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb610ef5610c12565b836040518363ffffffff1660e01b8152600401610f13929190611c34565b6020604051808303815f875af1158015610f2f573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f5391906119e3565b610f92576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f8990611a58565b60405180910390fd5b610f9a610c12565b73ffffffffffffffffffffffffffffffffffffffff167f328a7cca57e89d3b52f56190ef4e06d91c987e3ef2640db3be95d65f818e2d1282604051610fdf9190611699565b60405180910390a250610ff061145a565b565b60065481565b600754421015801561100c57506008544211155b61104b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161104290611ca5565b60405180910390fd5b611053611414565b5f3411611095576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161108c90611d0d565b60405180910390fd5b5f600654346110a49190611d2b565b9050600354816004546110b79190611d6c565b11156110f8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110ef90611e0f565b60405180910390fd5b34600a5f61110461140d565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f015f82825461114d9190611d6c565b9250508190555080600a5f61116061140d565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206001015f8282546111aa9190611d6c565b925050819055508060045f8282546111c29190611d6c565b925050819055506111d161140d565b73ffffffffffffffffffffffffffffffffffffffff167f8f28852646c20cc973d3a8218f7eefed58c25c909f78f0265af4818c3d4dc271826040516112169190611699565b60405180910390a25061122761145a565b565b61123161140d565b73ffffffffffffffffffffffffffffffffffffffff165f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146112be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112b5906117f6565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361132c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161132390611e9d565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff165f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3805f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f33905090565b600260015403611450576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600181905550565b60018081905550565b5f82825260208201905092915050565b7f44697265637420455448207472616e7366657273206e6f7420616c6c6f7765645f82015250565b5f6114a7602083611463565b91506114b282611473565b602082019050919050565b5f6020820190508181035f8301526114d48161149b565b9050919050565b7f46616c6c6261636b2066756e6374696f6e207472696767657265642c206e6f205f8201527f64697265637420455448207472616e736665727320616c6c6f77656400000000602082015250565b5f611535603c83611463565b9150611540826114db565b604082019050919050565b5f6020820190508181035f83015261156281611529565b9050919050565b5f5ffd5b5f819050919050565b61157f8161156d565b8114611589575f5ffd5b50565b5f8135905061159a81611576565b92915050565b5f5f604083850312156115b6576115b5611569565b5b5f6115c38582860161158c565b92505060206115d48582860161158c565b9150509250929050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f611607826115de565b9050919050565b611617816115fd565b8114611621575f5ffd5b50565b5f813590506116328161160e565b92915050565b5f6020828403121561164d5761164c611569565b5b5f61165a84828501611624565b91505092915050565b61166c8161156d565b82525050565b5f6040820190506116855f830185611663565b6116926020830184611663565b9392505050565b5f6020820190506116ac5f830184611663565b92915050565b5f8115159050919050565b6116c6816116b2565b82525050565b5f6020820190506116df5f8301846116bd565b92915050565b5f602082840312156116fa576116f9611569565b5b5f6117078482850161158c565b91505092915050565b611719816115fd565b82525050565b5f6020820190506117325f830184611710565b92915050565b5f819050919050565b5f61175b611756611751846115de565b611738565b6115de565b9050919050565b5f61176c82611741565b9050919050565b5f61177d82611762565b9050919050565b61178d81611773565b82525050565b5f6020820190506117a65f830184611784565b92915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65725f82015250565b5f6117e0602083611463565b91506117eb826117ac565b602082019050919050565b5f6020820190508181035f83015261180d816117d4565b9050919050565b7f4e6f2066756e647320746f2077697468647261770000000000000000000000005f82015250565b5f611848601483611463565b915061185382611814565b602082019050919050565b5f6020820190508181035f8301526118758161183c565b9050919050565b7f50726573616c65206e6f74207375636365737366756c206f72206e6f742066695f8201527f6e616c697a656400000000000000000000000000000000000000000000000000602082015250565b5f6118d6602783611463565b91506118e18261187c565b604082019050919050565b5f6020820190508181035f830152611903816118ca565b9050919050565b7f4e6f20746f6b656e7320746f20636c61696d00000000000000000000000000005f82015250565b5f61193e601283611463565b91506119498261190a565b602082019050919050565b5f6020820190508181035f83015261196b81611932565b9050919050565b5f61197c82611762565b9050919050565b61198c81611972565b82525050565b5f6040820190506119a55f830185611983565b6119b26020830184611663565b9392505050565b6119c2816116b2565b81146119cc575f5ffd5b50565b5f815190506119dd816119b9565b92915050565b5f602082840312156119f8576119f7611569565b5b5f611a05848285016119cf565b91505092915050565b7f546f6b656e207472616e73666572206661696c656400000000000000000000005f82015250565b5f611a42601583611463565b9150611a4d82611a0e565b602082019050919050565b5f6020820190508181035f830152611a6f81611a36565b9050919050565b7f50726573616c6520616c72656164792066696e616c697a6564000000000000005f82015250565b5f611aaa601983611463565b9150611ab582611a76565b602082019050919050565b5f6020820190508181035f830152611ad781611a9e565b9050919050565b7f4e657720656e642074696d65206d7573742062652067726561746572207468615f8201527f6e2063757272656e7420656e642074696d650000000000000000000000000000602082015250565b5f611b38603283611463565b9150611b4382611ade565b604082019050919050565b5f6020820190508181035f830152611b6581611b2c565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f611ba38261156d565b9150611bae8361156d565b9250828203905081811115611bc657611bc5611b6c565b5b92915050565b7f4e6f20756e736f6c6420746f6b656e73206c65667400000000000000000000005f82015250565b5f611c00601583611463565b9150611c0b82611bcc565b602082019050919050565b5f6020820190508181035f830152611c2d81611bf4565b9050919050565b5f604082019050611c475f830185611710565b611c546020830184611663565b9392505050565b7f50726573616c65206e6f742061637469766500000000000000000000000000005f82015250565b5f611c8f601283611463565b9150611c9a82611c5b565b602082019050919050565b5f6020820190508181035f830152611cbc81611c83565b9050919050565b7f596f75206d7573742073656e642045544820746f2062757920746f6b656e73005f82015250565b5f611cf7601f83611463565b9150611d0282611cc3565b602082019050919050565b5f6020820190508181035f830152611d2481611ceb565b9050919050565b5f611d358261156d565b9150611d408361156d565b9250828202611d4e8161156d565b91508282048414831517611d6557611d64611b6c565b5b5092915050565b5f611d768261156d565b9150611d818361156d565b9250828201905080821115611d9957611d98611b6c565b5b92915050565b7f4e6f7420656e6f75676820746f6b656e73206c65667420746f2066756c66696c5f8201527f6c20746865207075726368617365000000000000000000000000000000000000602082015250565b5f611df9602e83611463565b9150611e0482611d9f565b604082019050919050565b5f6020820190508181035f830152611e2681611ded565b9050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f20615f8201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b5f611e87602683611463565b9150611e9282611e2d565b604082019050919050565b5f6020820190508181035f830152611eb481611e7b565b905091905056fea26469706673582212200bc134f808dcbe3d0f86b4b209ed22f2ba58166e5d7366a9d4e5680e9c8ae32764736f6c634300081b0033000000000000000000000000fbf2d0931ae85173e09f769b509a4719700126ec0000000000000000000000000000000000000000002caaf1dd9f3a1ff6000000000000000000000000000000000000000000000000000000000003628faea7a0000000000000000000000000000000000000000000003b34865993332e1ab0000000000000000000000000000000000000000000000000000000000066fb04fc00000000000000000000000000000000000000000000000000000000670e91d0', + nonce: '0x4', + // eslint-disable-next-line no-null/no-null + to: null, + transactionIndex: '0xd', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0xa09bd3fb7924fbad29ce3f9d7bc6cadc7bf050a6', - gas: '0x5208', - gasPrice: '0x4c5efac04', - hash: '0x6d6269d0e0c72d8683f741cfb76b0d5e9f2dad7fe0a31cd84a655a5f48e2a3fa', - input: '0x', - maxFeePerGas: '0x62cb71600', - maxPriorityFeePerGas: '0x51a88a80', - nonce: '0x18', - r: '0x73c8c63f06b84cc19a11072e7a94b969625a0d11057268cba1cb7c464b3ca61b', - s: '0x6e8f89b8254a2ca4af5b97fd25d331c6aaf334872dc7b3af13982ebaeedd9576', - to: '0xbe8d2aea314be080df55bc01d79e98259bec836e', - transactionIndex: '0x46', - type: '0x2', v: '0x1', - value: '0x38d7ea4c68000', + r: '0xf67645c24ff369972523e81131f9ffe0f29cab10a80671dec4f490824a10a934', + s: '0x774ac80b46722e97858c5d42b07c02779f078731d568a916c0a2184b694a276a', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x4b900b7d20c981c30b202b30bffad1d78c465575', + gas: '0x360f1', + gasPrice: '0x27d34472b', + maxFeePerGas: '0x2d4448e21', + maxPriorityFeePerGas: '0x9cda7908', + hash: '0xa7a0f5692591c91286b872a20149f82aee2bb8fe0628adbe5a9656168936b28a', + input: '0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000019245207b03000000000000000000000000000000000000000000000000000000000000000308060c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000073aef1b5323e800000000000000000000000000000000000000000000000001e547c3b99278bc00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c289c2d57e2ba371f40d594705dbf9331a2da47d000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000000000000000060000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000000000fee13a103a10d593b9ae06b3e05f2e7e1c000000000000000000000000000000000000000000000000000000000000001900000000000000000000000000000000000000000000000000000000000000400000000000000000000000004b900b7d20c981c30b202b30bffad1d78c46557500000000000000000000000000000000000000000000000001e4112f6544aa590b', + nonce: '0x6d', + to: '0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad', + transactionIndex: '0xe', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x5565b5362ff9f468ba2f144f38b87187c9a010a8', - gas: '0xb4aa0', - gasPrice: '0x4b8d2bd04', - hash: '0x16405e445187de6e1282740494fc6af3a25cdfdea2de89014ace9a91f68ba6c3', - input: '0xc9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000480010100010100010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000004efab6bc6b8f34ca595ba160e7d99ac0000e9ac06050f0312090211100a06080b01040d070e0c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000001300000000000000000000000000000000000000000000000000000010622b851b000000000000000000000000000000000000000000000000000000106260fc80000000000000000000000000000000000000000000000000000000106260fc800000000000000000000000000000000000000000000000000000001063b0ae000000000000000000000000000000000000000000000000000000001064c356800000000000000000000000000000000000000000000000000000001064c356800000000000000000000000000000000000000000000000000000001064c356800000000000000000000000000000000000000000000000000000001064c3568000000000000000000000000000000000000000000000000000000010657dcce0000000000000000000000000000000000000000000000000000000106640cec0000000000000000000000000000000000000000000000000000000106650110000000000000000000000000000000000000000000000000000000010665011000000000000000000000000000000000000000000000000000000001066f7e9c0000000000000000000000000000000000000000000000000000000106762b980000000000000000000000000000000000000000000000000000000106762b980000000000000000000000000000000000000000000000000000000106762b980000000000000000000000000000000000000000000000000000000106884a440000000000000000000000000000000000000000000000000000000106daa1aa8000000000000000000000000000000000000000000000000000000106e379dff000000000000000000000000000000000000000000000000000000000000000716291fd074f7de8fa92346545486f1dd995174dbe082996a7f0070b390de1e3e8b6a944decd2a3e9667049ce16489bf299b9f557e25dbaea206ff5cbc6223bf44133d275dbeab4b6ac419d309e6ef432249fb601dddef3250e2c399ce70ae4a98b470c2a9f473fd67b1e1f82767e021cbb31bcbb012b52b2b20248d1aecf6e458159922125614956f06004f4a7c48093748141d402146613d8621bb0dc8be128195e7ea4bc57cd50acbd2580433388724587941ac374bdbe1e39965dec28d47bd9253b0d64a175286d2e124985256ef7d3e18491f8ac2f92812f50c1afd48ccb00000000000000000000000000000000000000000000000000000000000000076a5840595a11b5bca0e9a0f3c3229401d9ad633639697002c528561a48496951557690ceb40c387dda55305b362f70116883c67528075d3e21f63118a6b911340ef0f068c83ffaeae51608c7469ce6bf3669b7332929dd526f206adddfcc151d0eaa18655434b9a1c6945bd6a6fdd073b2d74ca04aac93a9920fc20532c5a7a1630071172c65a953750d254e632cc43bf16ee417cd4f79b332c97a25c0726a7d732239bf5df083d299d2312ecc7539f6e8d634faa6f80989ce2627766b58974823a1bbeccfcf0ae22dbebadc6cccd896888c42badaf2bd2cb764556de10bce50', - maxFeePerGas: '0xaa4aaa893', - maxPriorityFeePerGas: '0x448b9b80', - nonce: '0x11bc2', - r: '0x471c79d7bcb68cfe81aca71eaca7fc70a90dfcb9ca8669687266add051625b44', - s: '0x4e284dab507e32122c3fbc9f46801f3790af234597bc420f063e1f4f3e76bb83', - to: '0x908edc7e1974ecab1ca7164424bc4cac287d83ad', - transactionIndex: '0x47', - type: '0x2', v: '0x1', - value: '0x0', + r: '0xdd6c4235efc90dd6a4f829487603e0dfac5089ee5ccd150b003f8f67f9116ece', + s: '0x2406e597b1b7577d7c19805136ca398d23ddc0903abbe51fe6328a794048f66c', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x3dde0217fbceb6f2f179bfdcbc4f140766ad29f0', + gas: '0x524c0', + gasPrice: '0x246b849b6', + maxFeePerGas: '0x32a455ec7', + maxPriorityFeePerGas: '0x665e7b93', + hash: '0x70ab00c16c6b9d4c6d2c3e385fbd19b2cda0b38d887ed8eade2b3b4fcf0a0c3a', + input: '0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000066fb27f3000000000000000000000000000000000000000000000000000000000000000408000604000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000002b5e3af16b1880000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000004dfae3690b93c47470b03036a17b23c1be05127c000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000253608f400000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc20001f4dac17f958d2ee523a2206206994597c13d831ec70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7000000000000000000000000000000fee13a103a10d593b9ae06b3e05f2e7e1c00000000000000000000000000000000000000000000000000000000000000190000000000000000000000000000000000000000000000000000000000000060000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000253608f4', + nonce: '0x1f9', + to: '0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad', + transactionIndex: '0xf', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x79672062c5a45e3808d6b784129cf3ecf59d4224', - gas: '0x1e848', - gasPrice: '0x4b53bf297', - hash: '0xe622306295b723bf0da62a8946e0c624a3375096669cd379bc437ba3a0e2b6b1', - input: '0xa9059cbb0000000000000000000000008a900d289a028cd59cae6cebacfd932c60978df3000000000000000000000000000000000000000000000000000000000bebc200', - maxFeePerGas: '0xe056b8297', - maxPriorityFeePerGas: '0x40f4d113', - nonce: '0x20779', - r: '0x8cf782f3d4aa7d417fcd9b0c9347b4f7539db2cff70b07ccd35974cc1e1c0acb', - s: '0x56d09c40b55fcdd1d62fa826aca514daa096571286ac77dcf05f00734dde69f8', - to: '0xdac17f958d2ee523a2206206994597c13d831ec7', - transactionIndex: '0x48', - type: '0x2', - v: '0x0', - value: '0x0', + v: '0x1', + r: '0xe1f2656936c067a10e3f3cb6e08ba92313be5e905e86201e7dc57516e8d811f7', + s: '0x07ebe31e6a571680bd52d7778e41dd654bf7c17f631b121f24cd8b7bd99d325c', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x67846ced6221d8a3c1e4d64f16fd606d82b70a4a', + gas: '0x5854b', + gasPrice: '0x249e2cc37', + maxFeePerGas: '0x31c4983a9', + maxPriorityFeePerGas: '0x6988fe14', + hash: '0xbf4f04f76f5915455ce951e0b491901f2299d47de4bc9a1648c7befd210ef342', + input: '0x334043960000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000067846ced6221d8a3c1e4d64f16fd606d82b70a4a0000000000000000000000005b9b3cf0202a1a3dc8f527257b7e6002d23d8c8500000000000000000000000067846ced6221d8a3c1e4d64f16fd606d82b70a4a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000138003100000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000acb55c530acdb2849e6d4f36992cd8c9d50ed8f70000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000005f68e8131ecf80000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000ec53bf9167f50cdeb3ae105f56099aaab9061f830000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001', + nonce: '0x2ed', + to: '0x39053d51b77dc0d36036fc1fcc8cb819df8ef37a', + transactionIndex: '0x10', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0xd007058e9b58e74c33c6bf6fbcd38baab813cbb6', - gas: '0x3002c', - gasPrice: '0x4b2dcdc04', - hash: '0x804e7b2c8b74700c58f930f56e09e49a037b9dc454245ed87e469af5d73d7db6', - input: '0xac9650d8000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000c4219f5d170000000000000000000000000000000000000000000000000000000000076e40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004aae0a5d29921ff595000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004aae0a5d29921ff59500000000000000000000000000000000000000000000000000000000643645c700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000412210e8a00000000000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x18727cda00', - maxPriorityFeePerGas: '0x3e95ba80', - nonce: '0x102b', - r: '0x7527fd3053f801b20b55ae53a479a4fa15ce6fc6fe85f8f651995f65921d2c0a', - s: '0x7cfbe3d717d5e8db13d0a72c30e6716a81ae3f79dd209b9fda4a10c38f43a0fd', - to: '0xc36442b4a4522e871399cd717abdd847ab11fe88', - transactionIndex: '0x49', - type: '0x2', v: '0x1', - value: '0x4aae0a5d29921ff595', + r: '0x364fadfa77923a7300664239b9ce89d51c59494c31909c81d458e665a9faa320', + s: '0x019a25b3465b0d4490feb4e2a604e80455adf3bcec9f509e14baed2df204e314', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x8ec5a458c9dc17b9e2b74a9182e8a79fe4c1c3f4', + gas: '0x3393e', + gasPrice: '0x246b849b6', + maxFeePerGas: '0x2f7e80093', + maxPriorityFeePerGas: '0x665e7b93', + hash: '0x5dcbc082b249db57486fd7c07c5ac216cdb4a41fa2eef1db0df0265f600caabc', + input: '0xda815cb5000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000003800000000000000000000000001ea27bce786a81022dfc156059771e8d3279a9a6000000000000000000000000ba30e5f9bb24caa003e9f2f0497ad287fdf956231888a4c6dc17fafa3ec09e2a54e00963055135e169c96710038c19b54efca6d200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000068dd8b18000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005d81fd4566ffb7411e25d33a652400b900000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000a858ddc0445d8131dac4d1de01f834ffcba52ef1000000000000000000000000000000000000000000000000000000000000003200000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000004b7ec32d7a2000000000000000000000000000000000000000000000000000000000000000001d9000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041446fb242b2c2998a8232cfa8054fc5dcb3f6e11af4b1a2483709e95327a240504df872d8db9067762f014b5249f437210a177ac07f7cc9e50d50634a26cabc881c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000059c56fa251d46cd2a3052c431ffa78045d30d9f7c2b4ac1fa31fbb53c9b8777b2b6222d51414bb7500cf17d52889b2b5eeafbfaa57eaae61fe5394a574bb340c791c013e65936af68e5d010513ff70a3aaed9afeb8661116e6ce00000000000000', + nonce: '0x20b', + to: '0xb2ecfe4e4d61f8790bbb9de2d1259b9e2410cea5', + transactionIndex: '0x11', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0xb1bb676c7d99e64e8aa95a7a2a22b962596e041f', - gas: '0x272a4', - gasPrice: '0x4afe1eb84', - hash: '0x9944ff3b953f8a03d29719d2f1921d2f7ad23f28435aabc7a1cc16633c4c3efc', - input: '0x1249c58b', - maxFeePerGas: '0x5a9bf167b', - maxPriorityFeePerGas: '0x3b9aca00', - nonce: '0x12', - r: '0xe8c011f8dffc52c797faa8deac946b39ffca8bf3ab44126a40bb506f1cf02386', - s: '0x5313b99bfba1bad60fe829b008341fbd8269cea4d4fb5843ac7f4b1d130088f6', - to: '0x5f5cf9f5eb0e1dbb2b9ec771e015575d2e80eb6e', - transactionIndex: '0x4a', - type: '0x2', v: '0x0', - value: '0x2c68af0bb140000', + r: '0x435ea2cbaffe5b0a6fe46ec49de41a80da6407413c4fc62c71470a6ce681c522', + s: '0x1ab6e87c0816442b3320a5fdfd56de45bb66897b79029dd64694002e26e8f72a', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x973e21e5c9f2962c7ef6195071407c90c03370d8', + gas: '0x43047', + gasPrice: '0x246b849b6', + maxFeePerGas: '0x2f7e80093', + maxPriorityFeePerGas: '0x665e7b93', + hash: '0xd7380daf59f9b56d1956ce6454c226c70da6b69cf794cfe244e36e95279be489', + input: '0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000066fb27db00000000000000000000000000000000000000000000000000000000000000040a08060c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000160000000000000000000000000fefe157c9d0ae025213092ff9a5cb56ab492bab8000000000000000000000000ffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000006722b28c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fc91a3afd70395cd496c647d5a6cc9d4b2b7fad0000000000000000000000000000000000000000000000000000000066fb2c9400000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000041aaa15249269de36b54a48f316035f0072ded7e505f597884d32d81b1cb123d9607872506373b96386df2150eebc2e50d091318f261c9c4ec33e12a159bb04c621b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000006cc896d3e22200000000000000000000000000000000000000000000000005a908b36ee7beef00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000fefe157c9d0ae025213092ff9a5cb56ab492bab8000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000000000000000060000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000000000fee13a103a10d593b9ae06b3e05f2e7e1c00000000000000000000000000000000000000000000000000000000000000190000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000005a56951b4635392', + nonce: '0x54', + to: '0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad', + transactionIndex: '0x12', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0xeb5730d84f55206cdb742379c22c7c6abfc88ae9', - gas: '0xcaf8', - gasPrice: '0x4afe1eb84', - hash: '0xb6b4ef98d38a6a05809d1bf3f54ad65ce4c5b5ed5ae5bb77efc9448b46809735', - input: '0xa9059cbb000000000000000000000000a0d139723d6b9ddd967055e9af10734faf6daca600000000000000000000000000000000000000000000130ee8e7179044400000', - maxFeePerGas: '0x5fddbdc56', - maxPriorityFeePerGas: '0x3b9aca00', - nonce: '0x4', - r: '0xb73372f12b0891276107875cbf41880a5d908b33cfa4e7951f193de4876c16b5', - s: '0x058df26ec5a80b5b8796524849e637c97bb08e9168f5f86b68eafad64b1b4f5d', - to: '0xa1f7c9c6d19e2d0bf20729cb0bf03338a90bed9b', - transactionIndex: '0x4b', - type: '0x2', v: '0x0', - value: '0x0', + r: '0xea49731c43fde8c55c1c2f6334fb87ab61736b636fb6e94cfc46c3b8ebe24c72', + s: '0x1f4e706d7eebb51a4190d5c1f65670f496610680f5a9d790f772d85ee5d29545', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xa0643ffb77ead3c4cbf89c5ae8f9e8d73b758d94', + gas: '0x20981', + gasPrice: '0x246b849b6', + maxFeePerGas: '0x33159ab95', + maxPriorityFeePerGas: '0x665e7b93', + hash: '0x71a4672d1336fb1c60b67ec80c5cab5f484f713165a152732d65449f9d0c0515', + input: '0x2f52ebb7000000000000000000000000000000000000000000000000b34821f0542759680000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000e448f4f5887722030ff794497e962edeb692ebceea9ff7c587308e9a5ad01f473fd70e6501af180c287d2fe85c12d3d95466f2376fa9b18076629d7aa6a011b4b52d6418132f95470595d523c9865e78ec3596a0fe75a322a1cd01635f42955a5fc8d2e5f1794d65c5b086632398c2975c4e97e68b29359ac9b08d6d04c216ad8e006afca83612ae10c6a36f3380fca31ca76942c2242b5033bab83608999dfd7dce4fe50a944f4263dcd48749da323d4c634d407c8c3ce52dba901c389df3f73d760c8c7258b515634ff8930078d753436e4f0195314702e6d0350098a5d538dc478f0a20c43e889ea7a0116b0d7c0c5e742c1b682202f3c2ef1a8dcc6050859a4a2b8aade4f484a227a9efe5f856477275f1b77919c001687be0b33f7bfa8e0d6aba77988bb7f531021b75b36e397cb540bfd64ebf77a24d07a2edd32d4b1ca0ce7915c3f332710ef9396272c694f66cd99088bebf09d3f053e0207c46dc58b20ea963f6c3eff294a198d0da48b112794e7752acc21ff82e7823952dfd3d5d8e967e2229e2c41fdec843df0992953d9a6cb9c077b57f9dc78334f17a9df8b5e00e339b1d65e2a731e7de64445dfc0f73eca389e9f97a94179645b963ec028ec', + nonce: '0xe', + to: '0xecf2bcb2342d8157d4fb4f4bdc1edf74fbf759b3', + transactionIndex: '0x13', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x80c67432656d59144ceff962e8faf8926599bcf8', - gas: '0x186a0', - gasPrice: '0x4afe1eb84', - hash: '0x93b1efe0e8e99c39e0196bd596d4558863ffa78edc8c3b7a223a6a12a7b39ad4', - input: '0x', - maxFeePerGas: '0x45d964b800', - maxPriorityFeePerGas: '0x3b9aca00', - nonce: '0x41192', - r: '0xbf67e3864f000307e7af8acbbfc7961a3fd0b6b1372eb29d42de824a161068b8', - s: '0x018ddbd9adc27937567010cb339711b2730e534f81e34744e989489246c3a01a', - to: '0x585e94276ead330002fa0c51f3952be45404e1e8', - transactionIndex: '0x4c', - type: '0x2', v: '0x0', - value: '0x1342a7adc76503d', + r: '0x22f232fec8cb5a26f7ccc68f9cdee44b0fe27614e182f13b6d1e62da153a4142', + s: '0x54df4704e365c123a73b7bc490990f72666f6602fba801b3062cb089cbf95648', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x7467f36061e3a5e07b8b9c7605bc2e0f930912c4', + gas: '0x2d0d6', + gasPrice: '0x246b849b6', + maxFeePerGas: '0x2f7e80093', + maxPriorityFeePerGas: '0x665e7b93', + hash: '0x91fb16f5fb7a319cf1d2f0b156f6d1fe4a4e6fdaefe7b8aca18791d76f52ce73', + input: '0x1de26e16d4cfd6821e0815305195843e252b4c7ce30e229b2673403a62209a870aab889300000000000000000000000000000000000000000000000000071afd498d0000', + nonce: '0x19', + to: '0x83cb71d80078bf670b3efec6ad9e5e6407cd0fd1', + transactionIndex: '0x14', + value: '0x71afd498d0000', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0xcfc0f98f30742b6d880f90155d4ebb885e55ab33', - gas: '0x5208', - gasPrice: '0x4afe1eb84', - hash: '0xa7665ef46de3416737bb9768e48908a625d89395dfe14e47f863da8fea76db6f', - input: '0x', - maxFeePerGas: '0xabbb0e178', - maxPriorityFeePerGas: '0x3b9aca00', - nonce: '0x42473', - r: '0x759cf933d5eaa4ae2424d1b0a3f738e6426f46aae34fbfb728fcc5d44bad86d4', - s: '0x48ba7d2d59c11b2924f4c5cec339a13f2e488a30167db2d5f5e0e66c9dcd4f45', - to: '0x88c5f536d1514800dfd328d1e8dc2d8f3b4d60e4', - transactionIndex: '0x4d', - type: '0x2', v: '0x1', - value: '0x320ec7c4e2a000', + r: '0xd2f340ec62aa8fe1179be3cc9f317b6785df26446fda9541ebcc03464c715ffc', + s: '0x26560b9f5c3571bab91a10049ce6bb1cafbae1535b3cf1dc30d1b7769e6ddf5b', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xff82bf5238637b7e5e345888bab9cd99f5ebe331', + gas: '0x37c58', + gasPrice: '0x1e059ce23', + maxFeePerGas: '0x2d086b534', + maxPriorityFeePerGas: '0x0', + hash: '0xcac130c48fc8a647cfed37d83f66428b35b37e26ef9818576f8f7b2571ec90b9', + input: '0x78e111f60000000000000000000000002c6e668d3a4b25c557ce40b134a65eb36cfc222900000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000144c22b60750000000000000000000000006ada49aeccf6e556bb7a35ef0119cc8ca795294a0000000000000000000000004691937a7508860f876c9c0a2a617e7d9e945d4b000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000029dcbf8d891f2c00000000000000000000000000000000000000000000000026924a8d86356e0000000000000000000000000000000000000000000d4e93a66e8f738000000000000000000000000000000000000000000000000000001074a705cfad42000000000000000000000000000000000000000000000000000000000046ad34554e620000000000000000000000000000000000000000000000000000000066fb25a77f0000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000', + nonce: '0x32e7e', + to: '0xa69babef1ca67a37ffaf7a485dfff3382056e78c', + transactionIndex: '0x15', + value: '0xd0c600', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0xe4edb277e41dc89ab076a1f049f4a3efa700bce8', - gas: '0x186a0', - gasPrice: '0x4afe1eb84', - hash: '0x28d9b81fe5974728f846e2c752a43dae559687dfa4aa5732c184e25e65dde89f', - input: '0x', - maxFeePerGas: '0x45d964b800', - maxPriorityFeePerGas: '0x3b9aca00', - nonce: '0x10a8f', - r: '0xe52632ff849af71f4d046b96682c9dbb1ce0991c424db42d45b013275f8ae538', - s: '0x09bbb3a4b6135e7b48116ebfaeb37c92fbfadf5a5ba590e11e4cc96095110326', - to: '0x72cd4e3777e0df0a53a991f55fe816329d9f7c21', - transactionIndex: '0x4e', - type: '0x2', - v: '0x1', - value: '0x12312e6a272a00c', + v: '0x0', + r: '0xc536c5fe8d5e49c69904646059e28d5833b7dffc78b0283c2e979522622c1470', + s: '0x4d0eef56b365843039df7329af732345f88634b04989d0767441560c898ca8a9', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x03c290369b3589d57d916780f255bb30c0e028da', + gas: '0xc085', + gasPrice: '0x2865d3cdd', + maxFeePerGas: '0x4ce1446fb', + maxPriorityFeePerGas: '0xa6036eba', + hash: '0x4b8d7d87fdf6443d6756d37d0bdbe4470ed090e25a640d66f8017bc403a9df14', + input: '0x095ea7b3000000000000000000000000881d40237659c251811cec9c364ef91dc08d300cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', + nonce: '0x0', + to: '0xdac17f958d2ee523a2206206994597c13d831ec7', + transactionIndex: '0x16', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x80c67432656d59144ceff962e8faf8926599bcf8', - gas: '0x186a0', - gasPrice: '0x4afe1eb84', - hash: '0x2ed95ae311604dda2a370282bd6f3449cc1a4f2756f118f1aeb1d60c98c90ebc', - input: '0x', - maxFeePerGas: '0x45d964b800', - maxPriorityFeePerGas: '0x3b9aca00', - nonce: '0x41193', - r: '0x41f1b4ea4b9948a5bdd2e92f0f51922c450c6fa334d9fce39d27207799d1c2dc', - s: '0x2f09fd651476778e7eb470b5c1b1f5987690b09c4140b95b601b0f89d37cfe95', - to: '0x5eca6ce07dc82e150f23a988d2f6b29631ae2dbc', - transactionIndex: '0x4f', - type: '0x2', v: '0x0', - value: '0xd889b3bb0f602d', + r: '0xdda9612ac62d231dbbfb94806d4a21c974ddec4bc066a39225324aec4e915043', + s: '0x20f90f95e29c8f183be9ef3e63fa0ad7e1854ea179641d9e1a0a437be1f00053', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x160e4f09b67b08f3f5ff83d76eeca05ca274d2ad', + gas: '0x130c8', + gasPrice: '0x28a9b26ea', + maxFeePerGas: '0x528399b40', + maxPriorityFeePerGas: '0xaa4158c7', + hash: '0xa1d4d8c1f210acf9cff439e1c4507ee1fcace172fb56bfead537fbf4038a1bd5', + input: '0xa9059cbb000000000000000000000000836fd4a5c79b7ab3a916b3e224a4778a173c56e30000000000000000000000000000000000000000000000456bc06cb861f4cea1', + nonce: '0xa', + to: '0x6b175474e89094c44da98b954eedeac495271d0f', + transactionIndex: '0x17', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x4c9af439b1a6761b8e549d8d226a468a6b2803a8', - gas: '0x5208', - gasPrice: '0x4afe1eb84', - hash: '0x04bff1f526355878a5a79105a6fa4a4947ec23a6267afb8a2e7c7ce40fa2eda7', - input: '0x', - maxFeePerGas: '0xabbb0e178', - maxPriorityFeePerGas: '0x3b9aca00', - nonce: '0x33c48', - r: '0x56198513035d28dd33b6f52996425678e19068c5aa465426b217e317ed060ccd', - s: '0x34774b646c8d2767ceb4ae3eed4d1c4a7ffabb76a3abd516500dbd3ad92574a1', - to: '0x6bc39906da272535c3cda74aada15366c44badd0', - transactionIndex: '0x50', - type: '0x2', v: '0x0', - value: '0x57979784eff000', + r: '0x9562bfd7566d76132450bfc8d901614194af1f556dbe1f94e1622761358bd71e', + s: '0x144142b050807da496939cb2d32dc65d2976c0a38962b287b5a38f817a9b6379', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x17fb84a661d2f5f353d257a6fafc3d38b97da83a', - gas: '0x4878a', - gasPrice: '0x4afe1eb84', - hash: '0x78e4f8d6d388ebaf4a1b43f3232b97a5f25655ab2e18b2c8cf509940f0a57a62', - input: '0xf2d12b12000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000000000000000000000000000000000000c8000000000000000000000000017fb84a661d2f5f353d257a6fafc3d38b97da83a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000004e000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000fe080f9d773f7bc4d00cfdbc84408712536927c9000000000000000000000000000000e7ec00e7b300774b00001314b8610022b80000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000064363b9c0000000000000000000000000000000000000000000000000000000064436a9d000000000000000000000000000000000000000000000000000000000000000072db8c0b000000000000000000000000000000000000000055796030a90137f00000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001b71d8b8e3d000000000000000000000000000000000000000000000000000001b71d8b8e3d000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000004000000000000000000000000be9371326f91345777b04394448c23e2bfeaa8265c704b53dbf792236eed1b294a4576c12e61685bf06bbc766717138bf1e7edd500000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003000000000000000000000000fe080f9d773f7bc4d00cfdbc84408712536927c90000000000000000000000000000000000000000000000000000000000000040b3f1402e9455208c9664fd784ffc4995d08c39bad48c8994574c55031a432c553546f016378f00b18a2af71bb14547baf60b6531e2b3846f66de01b61d5e1eec000000000000000000000000000000000000000000000000000000000000007e0017fb84a661d2f5f353d257a6fafc3d38b97da83a0000000064363fa714b3694381555bc394cc0dfba14401a2e6e2a103af5e6ecd7d47f1cbb4242256807c5b993754489be391ffac8291f413f2270fca507c36a485e77c30a6cbc1c1000000000000000000000000000000000000000000000000000000000000011dd2000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000017fb84a661d2f5f353d257a6fafc3d38b97da83a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000064363b9c0000000000000000000000000000000000000000000000000000000064436a9d0000000000000000000000000000000000000000000000000000000000000000360c6ebe0000000000000000000000000000000000000000faf73bc19aab78a80000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000be9371326f91345777b04394448c23e2bfeaa8260000000000000000000000000000000000000000000000000000000000011dd20000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000925f2e84bf000000000000000000000000000000000000000000000000000000925f2e84bf000000000000000000000000000017fb84a661d2f5f353d257a6fafc3d38b97da83a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011dd200000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000011173ab0545f5b0f66005dc939c112d62517cd3c7af924ea3de2acdfb153ac7d79ac6498b24ed19f9d7e28267807f9745320c104d38388de01d723f540a41f0599f667ee66f59f02f291e822b78cc5afdcbe5fe0ae9837edfb5fb7b05aa4741d8279f6165f5fbe78cfc64738fc31c2b07d67d6e62984a87b8bd9cd5b54cd1e19d8ad2097c33b2f3b9ddb8d17ae1a4c46db08358602cefcec18e9ee88f4442f88a4bf122b8e37844f6a89a4f1c65a23c56a5755227f515e72deb64a600fdc4b059174aad4416d2a179bc57f8b84ba9ed2667a2befd75280091d8a861b0d3aca6119c8c0c1588ffa4f9a4caefc9532dc7aa31f711da2b112fe6b5a7bf29101df6fb34cfddda642fe5466fe08397bca3da9de8238622cce70b493e9f9d382b677c0bf65fb1c7f600e101b72c1eb4de0dc9e78c11c5b93b730fc37160b79d6e4a680f3faaea664643ed4cda9c0b98b402920642aaf8c3f43f50660cbf24f4830f1914a952b4ef4945010d54e4648b15b9c60b61fbb9c369b0a88e0dacce742f413424e86f655bd8a1adbbe325db62c241e236560b22bdee51b0c4891d9b98f892facef3d02a4de31bb51dc0c2d6566babfd3b6a24bb45f453a7d44ca41200fe6ad2fa6e29bccd4586238fcfe090bf77dfcd81c40788ad6a3b2bf6850917f5652f6d667fdcca82aaf7113b1cf7e93b45bfe3c42643711581ebf8cb4de854d92cb17fae64184487b4716217f80905633831ca5c512c3286ecceb89a409168ddb344c3a32000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000360c6ebe', - maxFeePerGas: '0x5b122c283', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xb2924a6a374072e0e950e93812302a20f82c8200', + gas: '0x64a0d', + gasPrice: '0x21bf49823', + maxFeePerGas: '0x29a8fe24d', maxPriorityFeePerGas: '0x3b9aca00', - nonce: '0x290', - r: '0x0ffb80eb321c5882261b75971226c4ea3280e4e7f13b699ac3655b1a918ceb92', - s: '0x12b0f3cdf17d32f848d129e17af8a6fb1ed15fbdd089bccb9c119b4ddbc16c56', - to: '0x00000000000001ad428e4906ae43d8f9852d0dd6', - transactionIndex: '0x51', - type: '0x2', - v: '0x1', + hash: '0x7a384c750acb5458fc07525005cdc4808820f6c0a027a21cf9e219d2256eec17', + input: '0x049639fb0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee000000000000000000000000000000000000000000000000fb60af3412ce87930000000000000000000000000000000000000000000000000123f38e5639d96e00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000c80502b1c5000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca000000000000000000000000000000000000000000000000fb60af3412ce87930000000000000000000000000000000000000000000000000123f38e5639d96e0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000100000000000000003b6d03408b59be2fc6fccc2256cc4841843a13ce29da16bdc4e3736f000000000000000000000000000000000000000000000000', + nonce: '0x9', + to: '0x3c11f6265ddec22f4d049dde480615735f451646', + transactionIndex: '0x18', value: '0x0', - }, - { + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0xb976d01275b809333e3efd76d1d31fe9264466d0', - gas: '0xb4aa0', - gasPrice: '0x4afe1eb84', - hash: '0x39fc3a2f506b038e3b502727345edcf6c42127bd97c906bf5cd69c1d5e9ceec4', - input: '0xc9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000003200000000000000000000000000000000000000000000000000000000000000400010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002800000000000000000000000caafb4c342b69dadd6d791c56ba7d1b000000be8010f010c0b030009070a02050e04060d08000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000019b1f4200000000000000000000000000000000000000000000000000000000019b452800000000000000000000000000000000000000000000000000000000019b52d400000000000000000000000000000000000000000000000000000000019b5c4300000000000000000000000000000000000000000000000000000000019b5c4f00000000000000000000000000000000000000000000000000000000019b5ec200000000000000000000000000000000000000000000000000000000019b5ec200000000000000000000000000000000000000000000000000000000019b608000000000000000000000000000000000000000000000000000000000019b608000000000000000000000000000000000000000000000000000000000019b697700000000000000000000000000000000000000000000000000000000019b70aa00000000000000000000000000000000000000000000000000000000019b879000000000000000000000000000000000000000000000000000000000019b9b9500000000000000000000000000000000000000000000000000000000019be57700000000000000000000000000000000000000000000000000000000019c035c00000000000000000000000000000000000000000000000000000000019c394000000000000000000000000000000000000000000000000000000000000000066e66d4d238abf2a84f5fc465a2e41735d21c720bc516264bcb846d423ed9efeaad22d072207791393fbd6ce8ed4a4365e8b24f93f4141483c4bb929cf68488ec49cac06d656d22b921a569e39b94de94ec68fdaca2274ffcc97cfc60a11f012702cb49c28a4d286875512b500bc4ae3bc2ded30381fb4bb050457302292c7f0f60b5a478972e9a36e306fba6a8464f4c4c1e1ab47dc59601df9caecbb82d544f692563216de85072ae876992de6b9fa1ad8c40e7104e51375a50350a673d44530000000000000000000000000000000000000000000000000000000000000006618235e5c012f1fd7489d13b278a66b678a3ac29a196bd40681ee39ed3dfa7111b6255c44008a68b2aa5e2ed7b7e6129989edbb66017570b23e1ba6f3fb6625d44996832badcc32a6b4057181b1e171f84c05d5d7469b557b870980d32807d930a1549998782d5637e4ae74f6d371b8324f7abb1590a12ca961454fd26945f8735cbd4b5a079631be754fce2cc0f24da5a0cbc010ee0f98a4ef46b39045df0d00db817ce3c076fcbc70e3d85e9c4bea1eb5a33dea5b19dad02ca8d2e102e1902', - maxFeePerGas: '0x6b5cedf1e', - maxPriorityFeePerGas: '0x3b9aca00', - nonce: '0x1b09f', - r: '0x7e01f3f231b2d8a9fb7e56043e21e8896ce19fbeb33517d407427d87631e7655', - s: '0x16f1192dd60fd55c7f917ba2a9fd6e7241f9330e795d08a4a38881145f3107a4', - to: '0x98e3f1be8e0609ac8a7681f23e15b696f8e8204d', - transactionIndex: '0x52', - type: '0x2', v: '0x1', - value: '0x0', + r: '0x11c92e53006a62b3debd85b584eb8926c54c8588693a73c9158d033e3a4a7b0e', + s: '0x5a293b47ffe866201f06f3a4a9d9b58b9c3e13f5e4484b97308dfe231087203c', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xc3accb14a8ad33b8248f63d60a699c83e0e02e72', + gas: '0x16a0b', + gasPrice: '0x24c3c36a3', + maxFeePerGas: '0x2fb891680', + maxPriorityFeePerGas: '0x6be26880', + hash: '0xa45d400b6cd4dc40fb5c010bd0211d305b9418612aec827a958b896a037665b2', + input: '0x4641257d', + nonce: '0x1d', + to: '0x17737cd358489928fac4e95c85710aff414bf69d', + transactionIndex: '0x19', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0xcfc0f98f30742b6d880f90155d4ebb885e55ab33', - gas: '0x5208', - gasPrice: '0x4afe1eb84', - hash: '0x9c850596d23bfc226f4177a827d27cbfd13373ab3c6c8f083de69da4d4aba82a', - input: '0x', - maxFeePerGas: '0xa9b736ffb', - maxPriorityFeePerGas: '0x3b9aca00', - nonce: '0x42474', - r: '0x915fabc6157bd8cd9a68c1014f8b732ba10e45933c47132b6d8d2ed13ca7a3f2', - s: '0x4f83e6070627d7255faf3ff9bd831a78f7704b2155263edfeec7008eff435ba9', - to: '0xedcb80a23f36923377ca239aecb6e582ef6362c7', - transactionIndex: '0x53', - type: '0x2', - v: '0x0', - value: '0x21afacba393a400', + v: '0x1', + r: '0x97baf781f3c020c6e972aebb7cf6ed935b6ff88ccf3b14900e7421d74271a86f', + s: '0x4a63693d02cf919ab768567de0b6a96ded3cd9ffbd74ae76bab5be129755918d', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xe596607344348723aa3e9a1a8551577dcca6c5b5', + gas: '0xb6c5', + gasPrice: '0x246b849b6', + maxFeePerGas: '0x2f7e80093', + maxPriorityFeePerGas: '0x665e7b93', + hash: '0xb392bc0e47075d16a9f9257635c878a70c435759be7169b315211789f5c57596', + input: '0x095ea7b3000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff00000000000000000000000000000000000000000000003400d24c6b0024ef80', + nonce: '0x1a9', + to: '0xfe0c30065b384f05761f15d0cc899d4f9f9cc0eb', + transactionIndex: '0x1a', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0xe4edb277e41dc89ab076a1f049f4a3efa700bce8', - gas: '0x186a0', - gasPrice: '0x4afe1eb84', - hash: '0x30f4c85342e02c43297d2720b034d8b724f38281d34a7c2dfb84328317da549b', - input: '0x', - maxFeePerGas: '0x45d964b800', - maxPriorityFeePerGas: '0x3b9aca00', - nonce: '0x10a90', - r: '0x0eb75546ed9b0a261b663e095c7f93f10bdc8900a2cf9fb0a1cb4afb0e40a966', - s: '0x76961fa9c1f5c5054339c79950581cc8b32c5fe15e9730ac2af740cddc9b2d98', - to: '0xd44f54bd8cacb0bbf5f568be436f3ebb5204022e', - transactionIndex: '0x54', - type: '0x2', v: '0x0', - value: '0x11ba60e96de00d', + r: '0xeb1cb7d6b23d173c7cf3bea08c20049f45347a8010e58b8a14a8a083df2f3d4d', + s: '0x1b93110b363afcd65e471d6e685bfba5bdee1fa3f5a81f1374fb0f17735e3915', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xe6816d6bfc21d3e76a2d6718060fe24b460ce0a0', + gas: '0x11056', + gasPrice: '0x246b849b6', + maxFeePerGas: '0x3062331a8', + maxPriorityFeePerGas: '0x665e7b93', + hash: '0xa8c2d6478fec54e7dd3a3e0209b42611ec0b3706fa09c452b9095feb02445fd0', + input: '0xa9059cbb0000000000000000000000001b1c5e5b952b5108a6e8b609c79c36beaaf82f0b0000000000000000000000000000000000000000000000000000000005f5e100', + nonce: '0x7', + to: '0xdac17f958d2ee523a2206206994597c13d831ec7', + transactionIndex: '0x1b', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x11f813a59d746eb051f1249e17c01ed4ecb7637a', - gas: '0x1e7ff', - gasPrice: '0x4afe1eb84', - hash: '0xbc83390bc39958798cb3066bf330a5611945aa5ca5112a55b92d6c689554ad60', - input: '0x5c11d7950000000000000000000000000000000000000000000000fae266e7ce1bd00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000005f3dcfa04bd883e89de8970424a77504fc9e4a390000000000000000000000000000000000000000000000000000000064363f7b0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000675bbc7514013e2073db7a919f6e4cbef576de37000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', - maxFeePerGas: '0xb7f54b003', - maxPriorityFeePerGas: '0x3b9aca00', - nonce: '0x186', - r: '0x300c8ab86d498fa6ca5368659b988ca063d6795c0708ebd6797c7932d10671ef', - s: '0x4cf593213a0c878c0ee7faad552d0c5916162a5a2d2a64c335b75f6194ca9403', - to: '0x7a250d5630b4cf539739df2c5dacb4c659f2488d', - transactionIndex: '0x55', - type: '0x2', v: '0x0', - value: '0x0', + r: '0x85414198218927feb72f7e393be9c40a4016b75d9523046899c66c982912a109', + s: '0x5533a0cc6b4b825ef88acc658cd758e93c92174b264bb05fad05610410ed8cbf', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x30a465f4dd49105cc535e6607b4e47d124c3ed1f', - gas: '0x1afee', - gasPrice: '0x4afe1eb84', - hash: '0xf0a99df33c3ab18658dd8625fd41cf41dc83dc44f19688f3cf17f04514a0d4cb', - input: '0x44bc937b000000000000000000000000f65c1595b64e73dcb551bd7eedcb43eb2c769be200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011c37937e0800000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000006436426400000000000000000000000000000000000000000000000000000000000000413d3a424e422e424e423a626e6231356d6e366d766a3364636c6c6b6c3268776c3676633439797565756c3661656d6573733432713a323037393138323a74653a3000000000000000000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x63ce38e90', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x000000629fbcf27a347d1aeba658435230d74a5f', + gas: '0x2dc6c1', + gasPrice: '0x21bf49823', + maxFeePerGas: '0x423940eee', maxPriorityFeePerGas: '0x3b9aca00', - nonce: '0x2', - r: '0xa453f3a177d595a27298500aa7e77787bc20907c9b00f30826c998ee7c1dff85', - s: '0x7369e5b46c440dfad01acefe6f26c5b708b19210b52d31af4be4d73b262b1d3f', - to: '0xd37bbe5744d730a1d98d8dc97c42f0ca46ad7146', - transactionIndex: '0x56', - type: '0x2', - v: '0x0', + hash: '0xb4def4daaabf6ca2dfbebd6c8a441fded38defa10a10b5d46a531a405255d1aa', + input: '0x10d008bd0000000000000000000000000000000000000000000000000000000000067c7200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000320048c991041f2db34126de07b24f0888251ffcc6f6b72250e1b98e2c7b1331aea65ca386b9bb5e14ff91decf8a070d2049d5b4635edd60df7ca743f764ef6452401e151f03839002c87c61190ed1c6c9d28564adadbf6420c6cc451a8944b59cc302e31382e302d64657600000000000000000000000000000000000000000000569e75fc77c1a856f6daaf9e69d8a9566ca34aa47f9133711ce065a571af0cfd000000000000000000000000000000633b68f5d8d3a86593ebb815b4663bcbe00000000000000000000000000000000000000000000000000000000000067c72000000000000000000000000000000000000000000000000000000000e4e1c000000000000000000000000000000000000000000000000000000000066fb254700000000000000000000000000000000000000000000000000000000013e658c00000000000000000000000000000000000000000000000000000000000000c80000000000000000000000000000000000000000000000000000000000000001acbf7ff83593107e34e92916a61c2cf0ae2953975baf1a576c5880f96404afc100000000000000000000000068d30f47f19c07bccef4ac7fae2dc12fca3e0dc9c03de8c90c8fd43ec3046a8fa25f26c892d9c3f8eef2902208bc821e9344fb50d284d5ade0dbe14dcae51128a1abfc21bbff0d8166d505eb3f5a8e7fa0e98f0ac21128fb021322ca17ff6658b2f3631e517ee50ca3ae6fe0980ab5563f989d9f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000c80000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005900000004f02099f42d499028ca52a5205d4e21001f5e3525a6733d96e57e33d95964d99286c843b201da1f45bf630de410c4d909305dbdb42d06d69bf86daefeed8e1cf9513b3a80de22920338e00cb23ea3fcf2d9fb94fb1c00000000000000', + nonce: '0x65d25', + to: '0x68d30f47f19c07bccef4ac7fae2dc12fca3e0dc9', + transactionIndex: '0x1c', value: '0x0', - }, - { + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0xcfc0f98f30742b6d880f90155d4ebb885e55ab33', - gas: '0x1d4c0', - gasPrice: '0x4afe1eb84', - hash: '0x080d36e7596e73af440400f2542d2b93c0b3cf3af6cfe400ac3fd469d958b338', - input: '0xa9059cbb000000000000000000000000cdcedde8f0690fa8da7cdacdbcce7c8550bdce390000000000000000000000000000000000000000000000000000000006bb7af0', - maxFeePerGas: '0xa9b736ffb', - maxPriorityFeePerGas: '0x3b9aca00', - nonce: '0x42475', - r: '0xfd42464897da80d7e801c323400d9fd9023320a8b3d4f0567793443d8348f4ab', - s: '0x40e14c1cc01cb5170ab3f0a1add8b2b2d65b7da65e29480d3c87df1ee67c3d77', - to: '0xdac17f958d2ee523a2206206994597c13d831ec7', - transactionIndex: '0x57', - type: '0x2', v: '0x1', - value: '0x0', + r: '0xaeac37dcfe850c607bd7f64952357a73358d306c96ae0ed1720f8f794e3671aa', + s: '0x7d9ec6f40435a8d743243ea282b8959cd156bbeeeffbd0cbf1e4ac6904e50e9f', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xf4ce3f01788a6066d38145ca5995f68ed9128e61', + gas: '0xa44d', + gasPrice: '0x246b849b6', + maxFeePerGas: '0x2f7e80093', + maxPriorityFeePerGas: '0x665e7b93', + hash: '0xb2c0f6026e5b51fe951a84d415140676400013f01e289e839a69dbe8b11c1eb7', + input: '0xd0e30db0', + nonce: '0x1037', + to: '0x0000000000a39bb272e79075ade125fd351887ac', + transactionIndex: '0x1d', + value: '0x522810a26e50000', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0xddeb598fe902a13cc523aaff5240e9988edce170', - gas: '0xb4aa0', - gasPrice: '0x4a8badd84', - hash: '0xc27d72675970b34668bea3e241a10e3f8e963a9bbae7b69f1cf27dc6aecbcbe5', - input: '0xc98075390000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000004000000000101010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028000000000000000000000008b1e35ccde892fe56c722420bdc588160000e9c401020106050e0c08070a0903000f040b0d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000878155e000000000000000000000000000000000000000000000000000000000878cc79000000000000000000000000000000000000000000000000000000000878cc790000000000000000000000000000000000000000000000000000000008795e140000000000000000000000000000000000000000000000000000000008795e1400000000000000000000000000000000000000000000000000000000087ae02300000000000000000000000000000000000000000000000000000000087ae02300000000000000000000000000000000000000000000000000000000087bce3d00000000000000000000000000000000000000000000000000000000087e54f100000000000000000000000000000000000000000000000000000000088009a000000000000000000000000000000000000000000000000000000000088009a000000000000000000000000000000000000000000000000000000000088215d80000000000000000000000000000000000000000000000000000000008828818000000000000000000000000000000000000000000000000000000000882bfc4000000000000000000000000000000000000000000000000000000000884a230000000000000000000000000000000000000000000000000000000000888fde4000000000000000000000000000000000000000000000000000000000000000697b49b869116d98c339ccec078201a086eeff8a1079a0ad8cf549e03e5116eae935d24b28b7999659595eaaadf4cff5e3196f5682ac22ca1ddcebb39026b69d9865d7c0f6553fa9c551b03d4f8a641755ea3347ca4c6a65162759d51df61c821223e39ebde460b257af0d8ada9bacba166054fb28dd7c0111e708ba749e8a808fc8da138d00e279ae2779606d364348d5c46ba6f37d5e8521ccfce6d940c24273990bd131c37ce33e29b82bb5551c7efd38aac7dfdf8d08090b76566ae18bcf000000000000000000000000000000000000000000000000000000000000000063d03f6364fd18561ca03cef54f44484f61bb3b620f99adfddef40d6565ffe5be7bf8aaec763d43f79fcbe7319c620ba4a407a7e49c9b7ec6093e60b5bf1a772d62999830f88b3d844988b09e5228487fde2ee2b3fd12abf54e7cbbf97221b74830e567ff8d676921f7275bd9a446e16287c1a82fabaa1b4272f35915eb03bd432a3647b9125bf089a81c231c97bdbee706fa68e43173cc9fa3e6a39b8ba825573d107a84d20a0db4e61fa881aba7c527cd83fd37b3de86dbaf6cfafd69de400b', - maxFeePerGas: '0xefa4ff21e', - maxPriorityFeePerGas: '0x3473bc00', - nonce: '0xe555', - r: '0xeb2632aa69af6c352644493291a00b9ed63fc8eb439b138bf9dd298bc5ff2545', - s: '0x405b026b89862bc6b824067d2c6a6e1ae354ab735d1dc3b47c159d6449fd3a22', - to: '0x34b41725cf934866a4b89d65395f15af2cb9ae89', - transactionIndex: '0x58', - type: '0x2', v: '0x0', - value: '0x0', + r: '0xd26aec93cdac2aad6524b045e6c0f18f2e04aca4ce3a002d3f11bcbf09887b26', + s: '0x7e97bd479f0e16a698a3c04c69b89af99c3fc3378f425df81c23ddac3508c76c', }, { - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0xa4e5961b58dbe487639929643dcb1dc3848daf5e', - gas: '0x55f0', - gasPrice: '0x4a817c800', - hash: '0xf062f350fcb7ceb7eda9cb8265e9a5922249ceddcb1a40b67ba1af43bb5c8597', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xd2b8fe9c76ed15e4ffd683300d7b669ba086dfb7', + gas: '0x5208', + gasPrice: '0x249e2cc37', + maxFeePerGas: '0x32bd67899', + maxPriorityFeePerGas: '0x6988fe14', + hash: '0xf93510911a3eda491e29c5f04c4afd0d69e1377275110ac2cd17934c566ecd38', input: '0x', - nonce: '0xc89e2', - r: '0x49b22ad44cbe9b0775944b6153021b501f2bb5a4aacf9a10ee8da7df87ccdfcb', - s: '0x0dee73e0614bdfdb0e5d2e6b30d4d2f53a96be5f1421bb9d903e814989790ed6', - to: '0x2c3113d1a6433d6c88ae92888346cf7f23fcb171', - transactionIndex: '0x59', - type: '0x0', - v: '0x26', - value: '0x9ff516e65e000', - }, - { - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', + nonce: '0x2', + to: '0x484d5e1eb3a94a06c590337a60a8db6a6f107c45', + transactionIndex: '0x1e', + value: '0x18de76816d80000', + type: '0x2', + accessList: [], chainId: '0x1', - from: '0x48c04ed5691981c42154c6167398f95e8f38a7ff', - gas: '0x2bf20', - gasPrice: '0x4a817c800', - hash: '0x76a287becd9daa920e1d26b9ee1843d03ce6df36b5434076738b90c323ba3a82', - input: '0xa9059cbb0000000000000000000000002c20b005df1d28e09d35b2d2b683779faa3e06cf0000000000000000000000000000000000000000000000000000000005fb7191', - nonce: '0x97e97', - r: '0x316288aa6f36438a65c22bd08bfcc8a6ac6f038e17f5b704b0ef00d770fbe83f', - s: '0x2263c2789374197fde54cd758502ca6b2b58de839d0be37a3ef2537b415329d2', - to: '0xdac17f958d2ee523a2206206994597c13d831ec7', - transactionIndex: '0x5a', - type: '0x0', - v: '0x26', - value: '0x0', + v: '0x1', + r: '0xe389eef868f18cd57ec0825a4d5c0ac7bb16bc295c9d606496d92e045ea5ce3f', + s: '0x73de6ad521c387382a1bfd57444bc54625596c7fe898bbee19771f9dbb37f933', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x4c9afc379737c7005e077fb89e54f1538aef8152', + gas: '0x5208', + gasPrice: '0x246b849b6', + maxFeePerGas: '0x2f7e80093', + maxPriorityFeePerGas: '0x665e7b93', + hash: '0x23e61859fe8a80e468e0a3245fb4cc58ec16d435a3bca86e2d408687c08ca070', + input: '0x', + nonce: '0x1c', + to: '0xcbab89a8bd32b3ae8868ebf19559140748bd55d6', + transactionIndex: '0x1f', + value: '0x8998bad426a000', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x876543cc6549d633de96b62a51f79160a904273d', - gas: '0x18b33', - gasPrice: '0x4a817c800', - hash: '0x51bfb597e154b9df1dfab45885c8219dd3ba99c0fa80631acba6b635471f74a5', - input: '0x6a761202000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000044a9059cbb0000000000000000000000004c15ed742031843d43d4495ad4285bf6323efa3c000000000000000000000000000000000000000000000000000000000744a820000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082000000000000000000000000876543cc6549d633de96b62a51f79160a904273d000000000000000000000000000000000000000000000000000000000000000001569d1270ca49270c51a5a43fe149d858171ac371537a8b5dc3a97116fe33c0ba7dc8d9bda9230591b7f10e2bdbe37c00771c631ed5fd3dcffd8d501e9f5fcc1a1f000000000000000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x4a817c800', - maxPriorityFeePerGas: '0x59682f00', - nonce: '0x7', - r: '0xf3d9a7ab2185b2d61daa3e9b5aa4536817f94f496509a849ea882fb716c58f87', - s: '0x6633d928531f98b3f501f137a52bf139918608181de3957efc41238b60b6fdb6', - to: '0xec5f4829854d1f0478b5b7a1c6f7dc50c4545fc0', - transactionIndex: '0x5b', - type: '0x2', v: '0x0', - value: '0x0', - }, - { - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x490ac3d62b3e71621687724ad894b2f15eee1167', - gas: '0xda8f', - gasPrice: '0x4a2fbf519', - hash: '0x0d7b43abc4b92337b064b74f7e2ff87c337cf0a5690a54dac34f2edf555d0733', - input: '0x095ea7b30000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', - nonce: '0x2ee', - r: '0x932266958a75019c8b5b922453b1a17acd707cc942d51fc9f569aeb256f44b82', - s: '0x2378e8c4aa7059f894ff3dc7ac65108d6649c75d347ac99de96997486a931bcd', - to: '0xee8253a7c009fad5fe047af648d29586c24d56d3', - transactionIndex: '0x5c', - type: '0x0', - v: '0x26', - value: '0x0', + r: '0xdee2237e94bc52fb97727d1ef92b35c844aeaa5061d09140e5cea8f102562425', + s: '0x510b060b00ab362dba35433ee7433e3a3aefe31804e566820658911c310df9ad', }, { - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x8cd94a71532f1f361f79a715f862c3ac621a9ceb', - gas: '0x10231', - gasPrice: '0x498586792', - hash: '0x6d9cf19ee0ca152ae9c5634caae877ab6011a70ee330225d9546589d74b3e087', - input: '0xa9059cbb000000000000000000000000b8001c3ec9aa1985f6c747e25c28324e4a361ec1000000000000000000000000000000000000000000000000000000001bb75640', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x0f7d3da2ecf36640c0660725c8457934601d94d1', + gas: '0x5208', + gasPrice: '0x246b849b6', + maxFeePerGas: '0x2f7e80093', + maxPriorityFeePerGas: '0x665e7b93', + hash: '0xba6c4057ca0038a489946446e9e3d386ff7b5b07048a04d515db65a9796ab9cf', + input: '0x', nonce: '0x0', - r: '0x2e518bb0c931b43e236d7c56ed2526fd9b0842a8add6ece75acc76380237a762', - s: '0x2b411dd4544bd94c7dce7f65c4dc0eef761568f12cb56a9da80a847545d6ac55', - to: '0xdac17f958d2ee523a2206206994597c13d831ec7', - transactionIndex: '0x5d', - type: '0x0', - v: '0x26', - value: '0x0', - }, - { - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', + to: '0x430f4919d679b02dca4572579caabb7676d65f1e', + transactionIndex: '0x20', + value: '0x10a741a46278000', + type: '0x2', + accessList: [], chainId: '0x1', - from: '0xd29a9fd180fb8da993576959bc9965962d7112b8', - gas: '0x10231', - gasPrice: '0x498586792', - hash: '0x1fef29d91355611b129ff67f970f6d1da96104df0310bd3b72237367723757d8', - input: '0xa9059cbb000000000000000000000000b8001c3ec9aa1985f6c747e25c28324e4a361ec1000000000000000000000000000000000000000000000000000000019b45a500', - nonce: '0x29', - r: '0x486be4009aab14d1968cc4f6ea0f60bf2e60333737051ec4c16be637ad9f92be', - s: '0x3fdaee939cae609f0d789d54d5bf5ab5edbfbf927a83bd4e5f5376b9898cb594', - to: '0xdac17f958d2ee523a2206206994597c13d831ec7', - transactionIndex: '0x5e', - type: '0x0', - v: '0x25', - value: '0x0', + v: '0x0', + r: '0x59e03a5a7b8ee7e7ba583b4c30cc22c4b27999d4601d1c1dece388f1a30cc4d8', + s: '0x22666c30fda82c6fdb2e0004bc4a11b94983bf35cd3d0bdbfb1ccbc070b7ed7c', }, { - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0xbdac639e17f40fe595a6f683fb031d5d14e454e2', - gas: '0x10225', - gasPrice: '0x498586792', - hash: '0xa1ad417520e8fc7d9c8d480e98b929487614daac0c8864879182dfad732054ef', - input: '0xa9059cbb000000000000000000000000b8001c3ec9aa1985f6c747e25c28324e4a361ec1000000000000000000000000000000000000000000000000000000003b9aca00', - nonce: '0x0', - r: '0x50e569b6a8052f1a7f8c142dcb5e9a6f0b0a9bc008020551cb095c413b8cd0d1', - s: '0x5e8e22aea92826c27fc90b46d5f104b95ec52613d3352efa56af8023eed21cd0', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xcf3c6afd97053c05a5ff5c8a03b17827598bd78b', + gas: '0x17740', + gasPrice: '0x21bf49823', + maxFeePerGas: '0x29396c028', + maxPriorityFeePerGas: '0x3b9aca00', + hash: '0x6ec7b0619ede7805b1794f4453bfed7ea0a200035d12c461a04e9a44c5926259', + input: '0xa9059cbb0000000000000000000000008140bf67dbee1c920fa90c9bac3a052214b2a0490000000000000000000000000000000000000000000000000000000248202200', + nonce: '0x33', to: '0xdac17f958d2ee523a2206206994597c13d831ec7', - transactionIndex: '0x5f', - type: '0x0', - v: '0x26', + transactionIndex: '0x21', value: '0x0', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0xf87acd73088f39c8fcaa77a036d9bdf3671cf0db', - gas: '0x2be83', - gasPrice: '0x497104f79', - hash: '0x7fcdfa9acd5255dafc8ddff55a2d8f06c93476eed34b511b7f504fc3eb0a4fa1', - input: '0xe449022e0000000000000000000000000000000000000000000001b1ae4d6e2ef500000000000000000000000000000000000000000000000000000000000000e4235bd900000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000371a0985d104c706cafa26ffb990f55ba55bf6c5e26b9977', - maxFeePerGas: '0x60cc725d8', - maxPriorityFeePerGas: '0x22c92df5', - nonce: '0x20a8', - r: '0x28ba948112aa8cee0b471ca955055a4825f6f563ea34d36a9da0e6e146a2c433', - s: '0x03b1bb8df287aab578a3dd40f302faeb043ac5e5c2f34b22ab9e0d27e73b11b1', - to: '0x1111111254eeb25477b68fb85ed929f73a960582', - transactionIndex: '0x60', type: '0x2', - v: '0x0', - value: '0x0', - }, - { accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x03aec61b209f8017a6a8aa974dce8252c69296ca', - gas: '0x13615', - gasPrice: '0x492148684', - hash: '0x69297bc8fafd076c18fa178358ebf0782730e1efe1c5d0dc057c4a42c7d13bc7', - input: '0xa9059cbb000000000000000000000000343821d3226c9f2f9a988c3d95c98c8c93cb75090000000000000000000000000000000000000000000000000000000005f5e100', - maxFeePerGas: '0x979be1ff0', - maxPriorityFeePerGas: '0x1dcd6500', - nonce: '0x6', - r: '0xd9d01006b01c45425b865e62f65c7c8cddc2816681ccbb29a08ec5287b49ea43', - s: '0x7127820875586008d07fafecdbd55103e102d921d203c095e9992efd51cef753', - to: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', - transactionIndex: '0x61', - type: '0x2', - v: '0x0', - value: '0x0', + v: '0x1', + r: '0x77a14332f19f9ad8bde2af7a4fd956bb9366eabb3856503a9f691f273927bc11', + s: '0x5cece50c77ea50b21ba08ebfcfb80a8be32e983f7e459296aec08ccedf84a07d', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x55824087db3e0f877e555cdcc60768ea1f4b8cd0', + gas: '0x2dfc6', + gasPrice: '0x1ec459023', + maxFeePerGas: '0x226069460', + maxPriorityFeePerGas: '0xbebc200', + hash: '0xfc3f0a738258301939f329633bdf619cf699f64d46ee46b1ca8842f2715130ed', + input: '0xb930370100000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000192450ad086000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000012f200000000000000000000000000000000000000000000000000000000000003600000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d88f61a98cf7b4000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000d4fe08fbc76000000000000000000000000000000000000000000000000000000000000000210500000000000000000000000000000000000000000000000000000000000001a000000000000000000000000055824087db3e0f877e555cdcc60768ea1f4b8cd000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001455824087db3e0f877e555cdcc60768ea1f4b8cd0000000000000000000000000000000000000000000000000000000000000000000000000000000000000001455824087db3e0f877e555cdcc60768ea1f4b8cd00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000420101010000ecf8d9f6006503000000000000000000000000000060c7fb08fed400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', + nonce: '0x1e7', + to: '0xef4fb24ad0916217251f553c0596f8edc630eb66', + transactionIndex: '0x22', + value: '0xdc1ce04e5377b4', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x57e65e1099ff2e2f1878ba820deb2a59377ac79c', - gas: '0x2bff5', - gasPrice: '0x492148684', - hash: '0x885dedc7616cefc16490d6dbec79b7ccc7dd1615367d2c4101084d60f2fdbea1', - input: '0xfb0f3ee10000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004d975d41e5000000000000000000000000000593afcc8ba197e8c1ff17cfd2f1a94e8119e79c0000000000000000000000000004c00500000ad104d7dbd00e3ae0a5c00560c0000000000000000000000000079f725f5c91384615270135d113efc7adcd8ee390000000000000000000000000000000000000000000000000000000000000776000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064362d6800000000000000000000000000000000000000000000000000000000645dba680000000000000000000000000000000000000000000000000000000000000000360c6ebe000000000000000000000000000000000000000037b453c98f8a79a90000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f00000000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f00000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000001fd5129130000000000000000000000000000000a26b00c1f0df003000390027140000faa71900000000000000000000000000000000000000000000000000000000000000633b5706d50a116101ac05ae95e2183168bb41cdfa3ded99a4e155291e6d6674462e6131fb77cd79a066548742049e828bc322115be1d9e5449d717febef7985ff00000073f8473e961ce955c014453147c9b5f24f0199ad5210ca60aab99b5b0f1394770000000000000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x5057e4dc0', - maxPriorityFeePerGas: '0x1dcd6500', - nonce: '0x5', - r: '0xb58385ce65a6a3cb5669f5f1ab1f6f2256ecfa7518ec314ec41eb98bc0837e60', - s: '0x29ea698c40672c0dbd004d705439542f22791af7a1c1e37dcbe83b56b9e7c9be', - to: '0x00000000000001ad428e4906ae43d8f9852d0dd6', - transactionIndex: '0x62', - type: '0x2', v: '0x1', - value: '0x4f94ae6af8000', + r: '0x708ec0f46fb15639d42fb6500872b3662356ff5087435a0a62e6efe69e69a10e', + s: '0x28e13ce47c44bd8284dccab70d55ed1f16e269d16e011a4fb638c9f43f44cfd8', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x749e365657816d14208da1c8c3797af35ff1a813', + gas: '0x8709', + gasPrice: '0x24c3c36a3', + maxFeePerGas: '0x2fb891680', + maxPriorityFeePerGas: '0x6be26880', + hash: '0xac90a64a9c747bfc03ebb82158f6b9660b26b93d154193546291738fc5b163e4', + input: '0x095ea7b3000000000000000000000000dc5593c653d21e7870efb99a748fc605afa30b840000000000000000000000000000000000000000000000000000000000000000', + nonce: '0x2', + to: '0xdac17f958d2ee523a2206206994597c13d831ec7', + transactionIndex: '0x23', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x231d3839825cbfa5887d5539fb297539627d74c8', + v: '0x0', + r: '0xf8b41bdaf32a719fc4d54a807c3052360ed6b6ff1bfdc0aa80c82e79ba43aadd', + s: '0x552b6b4d72667b0ebaf00d7bcbc614a104fed437eb1a608594c4274f439c24a1', + }, + { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xbc57ffe1bdbf3f599116a7c81327422b72688bba', gas: '0x5208', - gasPrice: '0x492148684', - hash: '0x03a87bf75fb7637fff63350513f286fdf23a5c0c5a561122f1e768c76ec6ea2b', + gasPrice: '0x263625475', + maxFeePerGas: '0x263625475', + maxPriorityFeePerGas: '0x263625475', + hash: '0x2c8f6836d4e5018b833f7994ed96cb877c7665f732637ba241a7178fb7ae358c', input: '0x', - maxFeePerGas: '0x9474decf6', - maxPriorityFeePerGas: '0x1dcd6500', - nonce: '0x13', - r: '0xb43ba165e5311936a02abdd5ce68b320deaa86957455f2b81493e7814266ea34', - s: '0x4e607d1700fec1e31441aa8b1f5c6b0df6604dea4e2008503bece4fc892f82ba', - to: '0x599f79493f478a8899c9e0b9ce986030e40b8192', - transactionIndex: '0x63', + nonce: '0xf3', + to: '0xdb1415c92039b7d9a1ff06b56c049f69bde94ff4', + transactionIndex: '0x24', + value: '0x97addd9857fd30', type: '0x2', + accessList: [], + chainId: '0x1', v: '0x1', - value: '0x2c68af0bb140000', + r: '0x4126bffeac1a9191d4aa1f3f2e1f87ec7f0c41482825b8c73a4345922212c2b5', + s: '0x75cc6431a7c56367b4f194bdefe46a1d2c34a010baf2d33dacb2227184d27036', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xadee9344a0c8b2e200f69c6e95b7ddc18d4a598b', + gas: '0x11056', + gasPrice: '0x21bf49823', + maxFeePerGas: '0x263625475', + maxPriorityFeePerGas: '0x3b9aca00', + hash: '0x86ae40dbde02d7f87e8d79d4dce1a50e09a7c0b3d701c42c0b5826aea607bbee', + input: '0xa9059cbb0000000000000000000000004da109363127f56a558fc31e82616ee822fd88cf000000000000000000000000000000000000000000000000000000003400c5c4', + nonce: '0x147', + to: '0xdac17f958d2ee523a2206206994597c13d831ec7', + transactionIndex: '0x25', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0xcc175d966ea179dddf2cd2d2a79973da5ce387f1', - gas: '0x15f90', - gasPrice: '0x491f600d5', - hash: '0xf76389acc92906f1290f3a854aa7bdff09ee6b7194a6cdbe3867b3b2f7b16fc3', - input: '0x2d2da806000000000000000000000000cc175d966ea179dddf2cd2d2a79973da5ce387f1', - maxFeePerGas: '0x491f600d5', - maxPriorityFeePerGas: '0x491f600d5', - nonce: '0x14', - r: '0xc529468d6f5ac6d3a93472c2342c571a7e173217fb2545fbe84d9698965b87dd', - s: '0x4f2bbee0e0b09d3030df61f434611ca2c7c6fcbd3a2172a0f787a1e3bee3bb40', - to: '0xabea9132b05a70803a4e85094fd0e1800777fbef', - transactionIndex: '0x64', - type: '0x2', v: '0x1', - value: '0x1b9ac619e7a000', + r: '0x59374f7cf2e6b884cb3cbc946dc7ab4e36195fafddd009ce455dd7c67c611847', + s: '0x157aa83f7d00353562368fdf76038abbd1d37f23ed91c7a9ec01e0390d484d45', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x66aa29c0d03bf1577c69748faac2c74b2b7b5176', - gas: '0x5208', - gasPrice: '0x49147ae63', - hash: '0xa7cecd23fab592aa7f3aa37045b16a35c73b2bcfa51d9d5a7a7d15424b78e4af', - input: '0x', - maxFeePerGas: '0x4e3b29200', - maxPriorityFeePerGas: '0x1d008cdf', - nonce: '0x2', - r: '0x7a738a0fd33a5d35321d30e38e983c559b4959da75b4047b6a24a7b39aad42a3', - s: '0x133773f7173e767f09f91abbc05c0189ea2b4523f4a0be0ba0cb608fa1bb2ecc', - to: '0x98bc423fbfd9935ab439c70eaa2f503d193b8827', - transactionIndex: '0x65', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x3b25d8e0801df1264a3d3a5f0bb79bbc292a09fb', + gas: '0x445c0', + gasPrice: '0x1e059ce23', + maxFeePerGas: '0x1e059ce23', + maxPriorityFeePerGas: '0x0', + hash: '0x705f084a5cb516c9b5170a592b40a8f9e544d319cc26aac5823aad6dcc713983', + input: '0x00000000013e65950000000100c600000000000000fea1039e8ea32840011dc4472dcd0e42ffccc1dbb0b9b3855688c22f3a0f008b020a77060e9d098db2ec7abcd5786d402896b54f5b50000000000000000000010479b65bc5d214e0b469cb3eda0ece9e425cfeda4df986a55ea9f888e0b469cb3eda0ece9e425cfeda4df986a55ea9f80000242e1a7d4d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000163f8c2467924be0ae7b5347228cabf260318753001cfee2199a', + nonce: '0x8c47', + to: '0xe6b1de575e7e610889ea21024834e120f92033a3', + transactionIndex: '0x26', + value: '0x0', type: '0x2', + accessList: [ + { + address: '0x163f8c2467924be0ae7b5347228cabf260318753', + storageKeys: [ + '0x3d2a5be9749cfe3ec60d14ef2f842725bb2978bf65d11d28555ee7f0598365ec', + '0xa3d49dd6f4959a9a7ce4676a7669cf1db4d20dd55049e1fc6bee399c0ddbe852', + ], + }, + { + address: '0x2d723f60ad8da76286b2ac120498a5ea6babc792', + storageKeys: [ + '0x0000000000000000000000000000000000000000000000000000000000000002', + ], + }, + { + address: '0x77060e9d098db2ec7abcd5786d402896b54f5b50', + storageKeys: [ + '0x0000000000000000000000000000000000000000000000000000000000000005', + '0x0000000000000000000000000000000000000000000000000000000000000006', + '0x0000000000000000000000000000000000000000000000000000000000000007', + '0x0000000000000000000000000000000000000000000000000000000000000008', + '0x0000000000000000000000000000000000000000000000000000000000000009', + '0x000000000000000000000000000000000000000000000000000000000000000a', + '0x000000000000000000000000000000000000000000000000000000000000000c', + ], + }, + { + address: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', + storageKeys: [ + '0x3b7f6fa3080fd35132045610d9dcd0399ece57a7a7462fef5421ae02227d47b6', + '0x3da19cbbddb7791ab46d3933c60df3c8be398aa24c48fdc578537dc4fbd5bccb', + ], + }, + { + address: '0xc4472dcd0e42ffccc1dbb0b9b3855688c22f3a0f', + storageKeys: [ + '0x0000000000000000000000000000000000000000000000000000000000000000', + '0x0000000000000000000000000000000000000000000000000000000000000002', + '0x0000000000000000000000000000000000000000000000000000000000000004', + '0x0000000000000000000000000000000000000000000000000000000000000008', + '0x4a6f485c1c32cc07b41a962ff745e1d2a15f32520f92181d93f06ac057458486', + ], + }, + { + address: '0xe0b469cb3eda0ece9e425cfeda4df986a55ea9f8', + storageKeys: [ + '0x3b7f6fa3080fd35132045610d9dcd0399ece57a7a7462fef5421ae02227d47b6', + '0x3c0689acb0ec5bc74f5a92aa799e39c0a84cdd47d50bba1ced45a97851caf92b', + '0x9a019fa77256656605296bcd55456823d455f6a3e958a5cfcafb48b0c557e5c8', + ], + }, + ], + chainId: '0x1', v: '0x0', - value: '0x18b5d979b5acc8', + r: '0x73ad7f3db0764288aa8fa4f463889becc70487bef37a6c7e9d0cc59930f7708c', + s: '0x33e4a266b15c463ff23e436411c2aa8398bb72a85ad308eaa1685da4f1678813', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x7c2125840304f5568f578c770e3e4bc2d6b1587d', + gas: '0x5208', + gasPrice: '0x21bf49823', + maxFeePerGas: '0x26f538dc2', + maxPriorityFeePerGas: '0x3b9aca00', + hash: '0x1fcb229b1e8812bd04201a4c8ee1ba4b4c9924ff7bb00fe85e0fb55d5f184ebc', + input: '0x', + nonce: '0x4d', + to: '0xe2b9e04fb000e610d1974680443d49b7284522eb', + transactionIndex: '0x27', + value: '0x1772aa3f848000', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x8264e9e0f4cbcbbbb3f8ecaec0a625b590ae790e', - gas: '0x9ac1', - gasPrice: '0x48628c484', - hash: '0x0fb59a5f28f25c78c39c72e0232934bd6b8646064ddd4d66e8c8b5695fa8184b', - input: '0x2e1a7d4d000000000000000000000000000000000000000000000000016345785d8a0000', - maxFeePerGas: '0x7527ba338', - maxPriorityFeePerGas: '0x11e1a300', - nonce: '0x2311', - r: '0x4d9cd6af35da7055ec9f7666a8775974617c78416497d26b607a4e00e6e24df0', - s: '0x0473e36c9a23e1f51baf6e937153de71c26c04be9d2d3086941ad041afb53160', - to: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', - transactionIndex: '0x66', - type: '0x2', v: '0x0', - value: '0x0', + r: '0xb9d4b1440e55b45460f67e08e6b80fbc52709bf69601e5b3ae6e27800083b482', + s: '0x475adbacd3fcda871904eb11792e5b023cfadcfe28e1a98fdfae4f5f9fe01b68', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xe15a8a7e5f84331f6fbfb19bee6471c31eea281a', + gas: '0x5208', + gasPrice: '0x21bf49823', + maxFeePerGas: '0x26f538dc2', + maxPriorityFeePerGas: '0x3b9aca00', + hash: '0xa669602d5fc23384386ee05919a58597a3b8baf076ff05180c22d4172cd500a3', + input: '0x', + nonce: '0x513', + to: '0x6e801eab6aed05ffcaa3f597b7ec5b518602f8a6', + transactionIndex: '0x28', + value: '0xd02ab486cedc0000', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0xba973782ea45705bbf3d9146d1d0c7085ea67d09', - gas: '0x3e51d', - gasPrice: '0x48628c484', - hash: '0x2343a15826c2683c027de01886924efeef1418ca43eef7f1e386e1e691cc14a4', - input: '0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000643645d300000000000000000000000000000000000000000000000000000000000000010800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000006f05b59d3b20000000000000000000000000000000000000000000000195350072d49c51359cebc00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000308516e6daac88d719af5a6d7ea2a82d8c8e7356', - maxFeePerGas: '0x83a687cfb', - maxPriorityFeePerGas: '0x11e1a300', - nonce: '0x78', - r: '0xffe855a41faa47c558849944f960e16ec0b51b50d7232588df35649a53d3c8d2', - s: '0x780adf86a100a512bcb52d4d5b7942a0c2ffca51f888f606b0ff57da3182af65', - to: '0xef1c6e67703c7bd7107eed8303fbe6ec2554bf6b', - transactionIndex: '0x67', - type: '0x2', v: '0x1', - value: '0x0', + r: '0x1d50df55d14f6745d1be6254e4cc8b5150070e3f4ffc7903e353d183e876ef8f', + s: '0x6f73eaf9ea5a369c96a04e53807e687ae85abb6830d94a99f295258a0cb6ec8e', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x0aff835ad5997f6b73acf8bb1e74ff496dc4fd03', + gas: '0x5208', + gasPrice: '0x21bf49823', + maxFeePerGas: '0x29396c028', + maxPriorityFeePerGas: '0x3b9aca00', + hash: '0xd27a6a61c34ba2c013edebf18af692db423e12c72bfad81a3b9e79cfa140a0a4', + input: '0x', + nonce: '0x17', + to: '0x0fa3a7d86bbcf418e77f8ae5b03faf64d243ac79', + transactionIndex: '0x29', + value: '0x13fbe85edc90000', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x7b229afc19d062e215426cd6ccddae15eec72bd2', - gas: '0x20fc6', - gasPrice: '0x48628c484', - hash: '0xe69e2160e90c6ef7f1a72c8bf4bdaf8e04fd679990acbacf1e9d9942eb2e21e3', - input: '0xeb6724190000000000000000000000007b229afc19d062e215426cd6ccddae15eec72bd20000000000000000000000000000000000000000000000000226abadc42f800000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000ab5b4000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000001000000000000000000000000007b229afc19d062e215426cd6ccddae15eec72bd200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x7cf9f675e', - maxPriorityFeePerGas: '0x11e1a300', - nonce: '0x14', - r: '0x5913f6ba1e292387d9edbd31c42cea5781ef507a54f5f0ff9b24d9e51324ae1b', - s: '0x0062fb9c767a87c8bc796bf3d813d8a078f6a4a1c34edb566910d0c5b853d16a', - to: '0x32400084c286cf3e17e7b677ea9583e60a000324', - transactionIndex: '0x68', - type: '0x2', - v: '0x0', - value: '0x2284df9f711176c', + v: '0x1', + r: '0x7a67dd5960686e9f5c7d180646e520aeb54a439e70ba66acfbc4a5a89554590b', + s: '0x73e456ba4bfafb3e35ff7cd2963b20a67abbf918bfbbd7c1f7849cbf749e8842', }, { - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xe76b6c50f156df392d030f3dc1e4655c4eaf6799', + gas: '0x33450', + gasPrice: '0x1ef188cfe', + hash: '0x8d3c220a5ddd846f638447ad29bee5c1d10abdeca329f0e2b0139fe60960a561', + input: '0xa9059cbb000000000000000000000000974caa59e49682cda0ad2bbe82983419a2ecc400000000000000000000000000000000000000000000000000000000001bf03253', + nonce: '0x9', + to: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', + transactionIndex: '0x2a', + value: '0x0', + type: '0x0', chainId: '0x1', - from: '0x00873b5fa9dc2a7336bd7d9d9ec187235d75f65c', + v: '0x26', + r: '0x068c13419bdb63e4c8f8f1669c7372964c070d11d8ac3dc366f847909384b6b8', + s: '0x65da03c99b32ba5453863b4cce31ae7c428c244694922f332bfdd51df536958f', + }, + { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x10cf76ee8e024a53ad65f97b868093232a95e2d5', gas: '0x5208', - gasPrice: '0x4846371f5', - hash: '0x0853356e276a49527201727e5e994403d7071fd8c20c4fe3513be09eb26422da', + gasPrice: '0x1f40be4b7', + hash: '0xf0ae50a850e3a19b7ee125f6a925c18899de2dbb68f2a5f1ab91d8c9a71985b7', input: '0x', - nonce: '0x4f', - r: '0x6e20c681c7547f14baa4b1d4433abdaaa06f8df72dd0266e81f0d5748e71f7cf', - s: '0x4a388342be339075192c0f59bd1cde4e18adf73cf794fc74fd04c00b7d465eef', + nonce: '0x7c', to: '0x974caa59e49682cda0ad2bbe82983419a2ecc400', - transactionIndex: '0x69', + transactionIndex: '0x2b', + value: '0x3a14827b19dbc3', type: '0x0', - v: '0x26', - value: '0xb2c858de4655390', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x00bdb5699745f5b860228c8f939abf1b9ae374ed', - gas: '0x27a42', - gasPrice: '0x483db8aca', - hash: '0x5c9d87e4015d92c11f2153f8133f8709294a3aedcf446523b48d8ca9f90cf999', - input: '0xfb90b3200000000000000000000000001522900b6dafac587d499a862861c0869be6e428000000000000000000000000000000000000000000000000000000000005f930', - maxFeePerGas: '0x897d11e3c', - maxPriorityFeePerGas: '0xf946946', - nonce: '0x18ada3', - r: '0x41d5426a523b9e1045201a5145cd78109077cc1fc2f9d5882f6b58d5f691a3b1', - s: '0x2a79396d96f9c362f0dd287b9fdfd6f39367a8964b3b96895a3f9737b1f67b80', - to: '0xffa397285ce46fb78c588a9e993286aac68c37cd', - transactionIndex: '0x6a', - type: '0x2', - v: '0x0', + v: '0x25', + r: '0x63558e2c8476c5fe914b58a8f51097f42266fec410d1f97c16d06c82a020fb02', + s: '0x3a51937467a4ffccb8f98ace3612149d42754d6d23e18a7241b0235d19b9ce02', + }, + { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x2d386e1ecc996fff96dc34aa335cd904d81ab1ad', + gas: '0x5474e', + gasPrice: '0x1e06ce0f3', + maxFeePerGas: '0x2919c97cf', + maxPriorityFeePerGas: '0x1312d0', + hash: '0x0337f05748fda0f12f67ee9e66fbd64f0d8747201ff97fe9fa62cc8e43224c28', + input: '0x415565b00000000000000000000000008802269d1283cdb2a5a329649e5cb4cdcee91ab6000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee000000000000000000000000000000000000000000000000000008e9a9dd174800000000000000000000000000000000000000000000000000d464a8cde7f20e00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000042000000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000005c0000000000000000000000000000000000000000000000000000000000000002100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008802269d1283cdb2a5a329649e5cb4cdcee91ab6000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000000000000000000000000000000008e9a9dd1748000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000002556e6973776170563200000000000000000000000000000000000000000000000000000000000000000008e9a9dd174800000000000000000000000000000000000000000000000000d636ca02680fe2000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000f164fc0ec4e93095b804a4795bbe1e041497b92a000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000008802269d1283cdb2a5a329649e5cb4cdcee91ab6000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000000001d22134801dd40000000000000000000000007afa9d836d2fccf172b66622625e56404e465dbd000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000008802269d1283cdb2a5a329649e5cb4cdcee91ab60000000000000000000000000000000000000000000000000000000000000000869584cd0000000000000000000000007afa9d836d2fccf172b66622625e56404e465dbd0000000000000000000000000000000000000000ba26e0443626a992948bf6b6', + nonce: '0x29', + to: '0xdef1c0ded9bec7f1a1670819833240f027b25eff', + transactionIndex: '0x2c', value: '0x0', - }, - { + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x00bdb5699745f5b860228c8f939abf1b9ae374ed', - gas: '0x27a42', - gasPrice: '0x483db8aca', - hash: '0x410a2d3073786f43ba1c0dcd5715031940b1eac224ddfbc09a2533b98e1961ce', - input: '0xfb90b3200000000000000000000000001522900b6dafac587d499a862861c0869be6e428000000000000000000000000000000000000000000000000000000000005f931', - maxFeePerGas: '0x897d11e3c', - maxPriorityFeePerGas: '0xf946946', - nonce: '0x18ada4', - r: '0x13cbb4f6a61b5bdcb4950e324769b71a02eb937594c8aa09769b27f0d88594e9', - s: '0x261f42e105031f0b934b7253f3886c1e89e698443f33244429195ee5a7f07746', - to: '0xffa397285ce46fb78c588a9e993286aac68c37cd', - transactionIndex: '0x6b', - type: '0x2', v: '0x0', - value: '0x0', + r: '0x6ab58b40e9870fc240455df2294db3f9afb982f03191865a94369a6c8f91c7cd', + s: '0x58faed25bd6bf87d77d21c9280c8339a968ea2e71a534c1f3ca06131ecf79e2e', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x3fa93695ba4c0317fc000a949d2412a233d478d3', + gas: '0x3603c', + gasPrice: '0x1e0691063', + maxFeePerGas: '0x2580b3868', + maxPriorityFeePerGas: '0xf4240', + hash: '0x97e22f8d634ad84031659e8305240d6b30e5c38a5d4decedfedcc67378dc3c28', + input: '0xc7276f86000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000009609b540e5dedddb147abbf9812ade06b1e61b2c000000000000000000000000000000000000000000000000001c6bf52634000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000068175accdc0000000000000000000000003fa93695ba4c0317fc000a949d2412a233d478d30000000000000000000000000000000000000000000010fd5795ff3848473b3200000000000000003b6d03402a7ae6e345841e0e58ec80e78ccb6491170f92faf9338bcb000000000000000000000000000000000000000000000000', + nonce: '0x36', + to: '0xb300000b72deaeb607a12d5f54773d1c19c7028d', + transactionIndex: '0x2d', + value: '0x1c6bf526340000', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x00bdb5699745f5b860228c8f939abf1b9ae374ed', - gas: '0x27a42', - gasPrice: '0x488d769c4', - hash: '0xd074a2e071d48cd543a4c2f78cbb494a5f5b7e205d2f9f16b749d3e79fc744c1', - input: '0xfb90b3200000000000000000000000001522900b6dafac587d499a862861c0869be6e428000000000000000000000000000000000000000000000000000000000005f932', - maxFeePerGas: '0x9ada766d0', - maxPriorityFeePerGas: '0x14904840', - nonce: '0x18ada5', - r: '0x052804f66111beebc748bcd7926ebe9d4b6a9d0a793656213b15c33415eb4112', - s: '0x6e27a106d4b2d72152ceb54be11b71538539fc8c58101722bc91da558d8d8858', - to: '0xffa397285ce46fb78c588a9e993286aac68c37cd', - transactionIndex: '0x6c', - type: '0x2', - v: '0x0', - value: '0x0', + v: '0x1', + r: '0x331887a32dfd198d6d48e650afacc928a678da813c010021e027573301dd1f8a', + s: '0x08f1ed40f8dd3f7d4f85df5233c22a797fcb96457309408bb7e9d01f2cb5eac8', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x5cc83e3067c6e1955696e31e10e2f0413ba3b46d', + gas: '0x2dcbf', + gasPrice: '0x1e0691063', + maxFeePerGas: '0x1f016cbd0', + maxPriorityFeePerGas: '0xf4240', + hash: '0xba44bfb96a9805965e4ac11529ea2d3e7e5e0b88880c7db012eae3544fcc83de', + input: '0x12aa3caf000000000000000000000000e37e799d5077682fa0a244d46e5649f71457bd09000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee00000000000000000000000068a47fe1cf42eba4a030a10cd4d6a1031ca3ca0a000000000000000000000000e37e799d5077682fa0a244d46e5649f71457bd090000000000000000000000005cc83e3067c6e1955696e31e10e2f0413ba3b46d000000000000000000000000000000000000000000000000050d9d35a55f11d200000000000000000000000000000000000000000000000000000002003571150000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011b0000000000000000000000000000000000000000fd00006e00005400004e802026678dcd0000000000000000000000000000000000000000382ffce2287252f930e1c8dc9328dac5bf282ba1000000000000000000000000000000000000000000000000000cefa6efbbd4a800206b4be0b94041c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2d0e30db00c20c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2efdf4dfc4e817197851266acf0082a80dab18b246ae4071138002dc6c0efdf4dfc4e817197851266acf0082a80dab18b241111111254eeb25477b68fb85ed929f73a9605820000000000000000000000000000000000000000000000000000000200357115c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000009a635db5', + nonce: '0xa5', + to: '0x1111111254eeb25477b68fb85ed929f73a960582', + transactionIndex: '0x2e', + value: '0x50d9d35a55f11d2', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x00bdb5699745f5b860228c8f939abf1b9ae374ed', - gas: '0x27a42', - gasPrice: '0x488d769c4', - hash: '0xfc7ae9cd5806dcc1bd8521581ce0187472dd6d2551e512e7a5d99e31692ce753', - input: '0xfb90b3200000000000000000000000001522900b6dafac587d499a862861c0869be6e428000000000000000000000000000000000000000000000000000000000005f933', - maxFeePerGas: '0x9ada766d0', - maxPriorityFeePerGas: '0x14904840', - nonce: '0x18ada6', - r: '0x1162bd0ef817cd7729fa1bf0ebef928242f0a63ddf13de691cb9d930c250107c', - s: '0x4486854997407eab272e2af97e6a7515ea40f5ff7d21710b413c6526c5052bd6', - to: '0xffa397285ce46fb78c588a9e993286aac68c37cd', - transactionIndex: '0x6d', - type: '0x2', - v: '0x0', - value: '0x0', + v: '0x1', + r: '0x187b0ca02cdb684f64facc2146d9b53934642bf273bc30af3bb86787e05c18b4', + s: '0x6cf11ddfef609ac99bb78de25e18c44b955d146883dd0420d6d0afc49d002178', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x49eb578be25160bfa4fad68ced88c2602a261057', + gas: '0x24d6a', + gasPrice: '0x1e0691063', + maxFeePerGas: '0x20ff6b8ca', + maxPriorityFeePerGas: '0xf4240', + hash: '0xfa31110a4d634fac73ab00a04e3f64f6f3a9bfe82579bb0cfbc887c234575445', + input: '0x2e4dbe8f000000000000000000000000000000000000000000000000000000000004d7f5000000000000000000000000f6b3cc9a23095c1acbf076cb560bbb56c19504e2000000000000000000000000000000000000000000000000000000003ee39506000000000000000000000000000000000000000000000000000000000004d7f500000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000041b4d0c532ccad28eddff275631ed6efbb25f6b6a926fbf7884252188c6fe775605c46c06ec62d9e7cc93679734b4ca885ea477d5cd8eaf2826236d1133b937c171c00000000000000000000000000000000000000000000000000000000000000', + nonce: '0x4c', + to: '0x75cda57917e9f73705dc8bcf8a6b2f99adbdc5a5', + transactionIndex: '0x2f', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x00bdb5699745f5b860228c8f939abf1b9ae374ed', - gas: '0x27a42', - gasPrice: '0x48631cdc8', - hash: '0x90910adfad4d375b9f1fe068c38cfb61fa27f8f3fffd5449a056410db031af0e', - input: '0xfb90b3200000000000000000000000001522900b6dafac587d499a862861c0869be6e428000000000000000000000000000000000000000000000000000000000005f934', - maxFeePerGas: '0x92b229fca', - maxPriorityFeePerGas: '0x11eaac44', - nonce: '0x18ada7', - r: '0x4fe0a6957957717c5ad46c067e30a0902e445cb77f908a033dbd79b98b9888d6', - s: '0x392ce598e7c79cb36da56f19ec951194cc1d8941c53664dbabf14c9e3fa5d11e', - to: '0xffa397285ce46fb78c588a9e993286aac68c37cd', - transactionIndex: '0x6e', - type: '0x2', - v: '0x1', - value: '0x0', + v: '0x0', + r: '0xb51ee52e13eabc668ae2cbd2e9f4b893bf40d4d51599354c6a553a40d2cdc23f', + s: '0x0d77ee8e00bb6c794505db5d868f998f03937d644fab78bd18814c9e3c39bea6', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xac411ce0f1a294544eee0922bfdfb64459301822', + gas: '0x6b19b', + gasPrice: '0x30af856a3', + maxFeePerGas: '0x75cbd01fc', + maxPriorityFeePerGas: '0x12a9e8880', + hash: '0x8df0a1bb53ea6cc3596a05c452d7b0f1cb7d605ad9becefbda542c8fc56986e7', + input: '0x6ac56d4ea7adcdd82eb19df563a0c9fba082c4ca651ae7b42c9531acd9ad5d8b344aa3f900000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000100e4d1290113b8eea72bf54ebc3d449db962860c1f2e052091f06c0fafff88e727357b7ccfe9bb0f93ffdd0f9810d3bbfdb4844dc7858a2091f06c0fafff88e775e412f2cfe9bb0a9fb15561d782219b3667746b85471fd40a2c11f2b648d3e54bcca94a2e7e9256ce7f0085d4b6ccf8cca875877fa869cd7fef74efba838d61608013b01528c49f129fb04274974b6c1797e8aaab0694e791f008cf8555b155561a9ff8c1b5f42d75685d5da3dbeb6a856a2d2219081db1e29f716c37011d5d4e3c7ae382f9bb0a9fb15561d6b7296a8ed27f6b96858a2091f06c0fafff88e775bbf5b4b6e01a0f02ed90baf055da432ce4c625904a704f06ac1cbebe9ff28c61', + nonce: '0x5170', + to: '0x767af52d988d1241a346851a1b39ccd11357376e', + transactionIndex: '0x30', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x00bdb5699745f5b860228c8f939abf1b9ae374ed', - gas: '0x27a42', - gasPrice: '0x48631cdc8', - hash: '0xd4b42ed78389a43e47061ee844c2b68ed631da72ceea389363a9bab05cc8e5e8', - input: '0xfb90b3200000000000000000000000001522900b6dafac587d499a862861c0869be6e428000000000000000000000000000000000000000000000000000000000005f935', - maxFeePerGas: '0x92b229fca', - maxPriorityFeePerGas: '0x11eaac44', - nonce: '0x18ada8', - r: '0x650a4b34cdcd4631c7829a32a134a4c4fddda05d6ce3740febc8b65181fcaf0a', - s: '0x5704562d0e2b28f1513637b6162897b6f9b0b7b5127642970fd053f761d178d7', - to: '0xffa397285ce46fb78c588a9e993286aac68c37cd', - transactionIndex: '0x6f', - type: '0x2', v: '0x0', - value: '0x0', + r: '0xa702c259137950c08b9150598a6e428de6814cba646a77e7f59281b23cf4788f', + s: '0x6b74df881da60b4761a90d382b034fcda0f1f3411e110d78ef02c4d3fd7dc06f', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x098678135822f61ddf76879a397e7c8b0e708ff2', + gas: '0x2f7c8', + gasPrice: '0x299200d23', + maxFeePerGas: '0x496f758fc', + maxPriorityFeePerGas: '0xb8c63f00', + hash: '0x3c161640067fdb42954e6a13a66b41faac10dd2b4bdb9387ef6066526413f58a', + input: '0x24856bc30000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000020b080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000009d434efcb7ff8000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000009d434efcb7ff8000000000000000000000000000000000000000000000000001223e4a47f88dfe00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006ba3d4b6ac8437cf03e815b31daf8112ba8da32a', + nonce: '0x7e', + to: '0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad', + transactionIndex: '0x31', + value: '0x9d434efcb7ff80', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x41aa3c59e2d0023765c972ef25067de147095e90', - gas: '0x2aef7', - gasPrice: '0x4832dd404', - hash: '0x504e3f22373700cb294db5b5b5402f45d8c4a02d7e996e52b51a0502a6b7cc87', - input: '0xe2bbb15800000000000000000000000000000000000000000000000001bc16d674ec800007f17690441d1ee627275ba60f1909e51840326e8b087a917a030ef1a58df575', - maxFeePerGas: '0x91d3fadf6', - maxPriorityFeePerGas: '0xee6b280', - nonce: '0x3', - r: '0x15bc32bb35846cd316ea4b2ef352cbde5c4db3e90118a155f7d6d9d56ac42047', - s: '0x332c8e70d2d73246da61880965b6a8e18e2a49029d5c9f44d70a757a40632347', - to: '0xae0ee0a63a2ce6baeeffe56e7714fb4efe48d419', - transactionIndex: '0x70', - type: '0x2', v: '0x1', - value: '0x1bdb3ed2c894e50', + r: '0x3540a0718ab96df554cd2024a5623ea604f9a4bc0032e5e6c307041b4fc189cb', + s: '0x6c2833902fd62cb6676c2505ee0dcc142ed45714a99c66b29b757f7a70efce7f', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xb1a8f7dc879664a929051666887e9a977e7059e9', + gas: '0x374b5', + gasPrice: '0x299200d23', + maxFeePerGas: '0x496f758fc', + maxPriorityFeePerGas: '0xb8c63f00', + hash: '0x069bfd72ad2f8e3c5aeb35fda21dbf5b0ef48fdfe318a2f037c5e916d5b85982', + input: '0x24856bc30000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000030a080c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001600000000000000000000000006ba3d4b6ac8437cf03e815b31daf8112ba8da32a000000000000000000000000ffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000066fb26d000000000000000000000000000000000000000000000000000000000000000110000000000000000000000003fc91a3afd70395cd496c647d5a6cc9d4b2b7fad0000000000000000000000000000000000000000000000000000000066fb26d000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000410e2d2fd06c695e6550cd2fd03fad147f7ba3c98e72abb7c3e26ef365f46fb9fc0440a0220610d13a0d79fdb8b3efc4fa57f3f7a87b38b5caa6c186b033bb60291b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000008dc1dfc3f692bda00000000000000000000000000000000000000000000000003e3705bea291b0000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000006ba3d4b6ac8437cf03e815b31daf8112ba8da32a000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000', + nonce: '0x54', + to: '0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad', + transactionIndex: '0x32', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0xe370cf76e4aa132b2709a842f6db1978e13493da', - gas: '0xc612', - gasPrice: '0x481641084', - hash: '0x96b93b9a250a2c76261558470c0242115dc1ebda5e1a5206489ee033fb31284a', - input: '0xa9059cbb000000000000000000000000bfa08b5ca8ca1acb8a118725759d0bd6c8039f75000000000000000000000000000000000000000000000000000000000bebc200', - maxFeePerGas: '0x57339f031', - maxPriorityFeePerGas: '0xd1cef00', - nonce: '0xc', - r: '0x4f09c205bc80daf565372757b4dea13e8f38b49f6d61f59e59dc244e2237e9f3', - s: '0x09856fc5ff01fe8b4f8771d78e7d3793db60b112cbb01fa113dced14f6d8d587', - to: '0xdac17f958d2ee523a2206206994597c13d831ec7', - transactionIndex: '0x71', - type: '0x2', v: '0x0', - value: '0x0', + r: '0x7c9488657438cf8578f8b0a34236e8d848ca1d19af6317865858d85e9aaf859e', + s: '0x667160d1986fe927c747b626ed1ac4287ec829a6ad1af0c72d7856c78ad6bea1', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x347c070b2e7d831d26ba004c4710362f64a91a41', + gas: '0xe572', + gasPrice: '0x2932a2c23', + maxFeePerGas: '0x2a1d9a8be', + maxPriorityFeePerGas: '0xb2d05e00', + hash: '0xc23c5bc63ae7bc038673e3258d0217b9849ed6c5c44a3ab8bf5057ada773995e', + input: '0x095ea7b3000000000000000000000000b86e490e72f050c424383d514362dc61dabb1cc3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', + nonce: '0x47e', + to: '0x6de73ced5dd4c33235f9f4bf5de47b5d33c6392a', + transactionIndex: '0x33', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x1990bbc7bf55ca3836910bb8064af5aea1aa3990', - gas: '0x12496', - gasPrice: '0x47a3d0284', - hash: '0x0d16cbef0f3df967f3dd0a10606785c4d7ae9bb6cc4ae8018402a5a839a1f497', - input: '0xfd9f1e100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000001990bbc7bf55ca3836910bb8064af5aea1aa3990000000000000000000000000000000e7ec00e7b300774b00001314b8610022b80000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000064363ea600000000000000000000000000000000000000000000000000000000643f791d0000000000000000000000000000000000000000000000000000000000000000360c6ebe00000000000000000000000000000000000000002d7e65655d5e24100000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000096fd865af440000000000000000000000000000000000000000000000000000096fd865af44000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000f7d1f4f8a7818ca3d92b1ca01b8051520b054d578e88c852463068f49131297f1cae4402df7b3d67c920a72a48897a5a4a347c03000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000001990bbc7bf55ca3836910bb8064af5aea1aa39900000000000000000000000000000000000000000000000000000000000000001000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003c6568f12e8000000000000000000000000000000000000000000000000000003c6568f12e80000000000000000000000000000000a26b00c1f0df003000390027140000faa71900000000360c6ebe', - maxFeePerGas: '0x5c8520e5a', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x17c', - r: '0xef833814a5f922ffb7809d56150f90cfc1ce6d151c7620447ff9e8670b10193e', - s: '0x236c8b6eedb771851d6d7de5a93f6ecf039250754e169f1caee2a45687b253d9', - to: '0x00000000000001ad428e4906ae43d8f9852d0dd6', - transactionIndex: '0x72', - type: '0x2', - v: '0x0', - value: '0x0', + v: '0x1', + r: '0x6708316c74dc8bb87c944667d4c8d29a7976537a260406b51460af44c98822bf', + s: '0x66b05cffe76db2cf38c7a35af74d0f4894b0696dfd4de9f17e59fa8ccb82b1ff', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xa040f16187782dcd5797bac30d7f9bc7bdd06f49', + gas: '0x5208', + gasPrice: '0x2932a2c23', + maxFeePerGas: '0x35981ff61', + maxPriorityFeePerGas: '0xb2d05e00', + hash: '0x47c7e4c8b818b655a0d210a4ccfd9d01c144c424b546f0d8060d9df760cd4fcf', + input: '0x', + nonce: '0x4', + to: '0x0abbc482fbd91dbf413e3d6cc5622e03552ac13a', + transactionIndex: '0x34', + value: '0xb853b691a241e0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x91cfe6dbb2b98ce6fb549cb3334a90dd3a69e584', - gas: '0x14f43', - gasPrice: '0x47a3d0284', - hash: '0xf80ba14af91cdf4a398fc6d7ab439f721af496428eb789749cb2da23eaf31052', - input: '0xa9059cbb00000000000000000000000008f918c66d54f4c51f9a76cb9a956faab2d49abe000000000000000000000000000000000000000000000000487ef0daa63d5ba1', - maxFeePerGas: '0x5c8520e5a', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x3e', - r: '0x6b04df15be2426dca5090d73052f6eb01d4b495d869ebff7da8f85298cb5868c', - s: '0x2f25a9a6120c3b912ccad0d7ce8eedda62ef4e7bc82fc5557a06f74ed1c27582', - to: '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984', - transactionIndex: '0x73', - type: '0x2', v: '0x1', - value: '0x0', + r: '0x6cd3d06506120c22d248237b62421810eef880862a42319ecd45039acf8aa6c2', + s: '0x05e0c12f42f6b5f3f8f9d1a5c7045d7f30187e7012c3c9fdaf5f9b391d93c640', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xa616f8abd716846e712c8c10581c0720d286a36e', + gas: '0x5232c', + gasPrice: '0x289b6ac8a', + maxFeePerGas: '0x3bbd89fa2', + maxPriorityFeePerGas: '0xa95cde67', + hash: '0x17b23e825ef1a9a3d8bb1be42c4c814a6e331c60d79de5c50b42e5c197257e76', + input: '0xa9059cbb0000000000000000000000009489e4f28130482bce472c4d661e891a177c46a0000000000000000000000000000000000000000000000006f5c98b0edd3c1080', + nonce: '0x8e', + to: '0xec53bf9167f50cdeb3ae105f56099aaab9061f83', + transactionIndex: '0x35', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0xc7d255accc1b4dc16c2856ac4c5193bfe29801f6', - gas: '0x5208', - gasPrice: '0x47a3d0284', - hash: '0xb8c7acb46336a721893b6171ce9ae326e8b861913ee8502560798dc03a4b428a', - input: '0x', - maxFeePerGas: '0x62bb2392d', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x2', - r: '0xc09606be9f624ec8f63206c830e3f769e7af2bb6084f63961a786996e408d252', - s: '0x1953afb0eb09319d8aca73c6afc537db8965a79a8751e398c2627ccf70e79737', - to: '0x7ab9889cf7f17ab6303d2992c874bc583f125a2e', - transactionIndex: '0x74', - type: '0x2', v: '0x0', - value: '0x1c288e25fbbf52d', + r: '0x271c264a9c5875fee11538100c98a93ae27e8413d18e31cfaa13104ecfce301b', + s: '0x4f0d447431b83279137cf2963054dbdf86b06942a497141cb7b1f38c714989ec', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x595d91b452e4301088be318755f05155f93a7345', + gas: '0x5232c', + gasPrice: '0x289b6ac8a', + maxFeePerGas: '0x3bbd89fa2', + maxPriorityFeePerGas: '0xa95cde67', + hash: '0x8af817b25c16ad3a3c7bfe68c5165a2314aef37e7b485a68fc7102df805162ff', + input: '0xa9059cbb000000000000000000000000b96258ffa0408d1ced1f9f3c3e39400afd7fcffa00000000000000000000000000000000000000000000000635c90e4b5d58d4f8', + nonce: '0x19', + to: '0xec53bf9167f50cdeb3ae105f56099aaab9061f83', + transactionIndex: '0x36', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x06bda28316d3681cc513d3fb6820b6837e838be2', - gas: '0xed72', - gasPrice: '0x47a3d0284', - hash: '0x585f52cc267bc31ed76456e10e26462e8ba898419cc8b9d59f6f76c5869e4b41', - input: '0xa22cb4650000000000000000000000001e0049783f008a0085193e00003d00cd54003c710000000000000000000000000000000000000000000000000000000000000001', - maxFeePerGas: '0x62bb2392d', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x29f', - r: '0xc6422e0c8c19d97517db3a0e4e791ea556c8fc1a1eaa5fe4548b06df398d8cad', - s: '0x1da6feebf8207e3c861173dd64f96e636ca0681383fae3953ef5bd9885b3e9ec', - to: '0xd44078705456c4f4517a659953f5296e5328f8b8', - transactionIndex: '0x75', - type: '0x2', v: '0x0', - value: '0x0', + r: '0x2c13892bff83a241483d3a709df7a469578eb6882447a7f5c4b5c6fff0e527f6', + s: '0x611374f0613e033da9ea903b49f6d2c22ace68e4efd19c1bbc0575678d1bc9d7', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x98dfe43567e18e36e37da97b5c6864de81e406ee', + gas: '0x40a66', + gasPrice: '0x2865d3cdd', + maxFeePerGas: '0x4ce1446fb', + maxPriorityFeePerGas: '0xa6036eba', + hash: '0x87c5830b100585cdc5c29644bba54eda44d1508c32d5c6c5fa0321e986cfaea4', + input: '0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000066fb27cf00000000000000000000000000000000000000000000000000000000000000050b0105040c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000507168b8932f1eda0000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000003804e0a60000000000000000000000000000000000000000000000000507168b8932f1eda00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002ba0b86991c6218b36c1d19d4a2e9eb0ce3606eb480001f4c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000027213e28d7fda5c57fe9e5dd923818dbccf71c4700000000000000000000000000000000000000000000000000000000023c34600000000000000000000000000000000000000000000000000000000000000060000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000037e11d600000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000', + nonce: '0xd1', + to: '0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad', + transactionIndex: '0x37', + value: '0x507168b8932f1eda', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x067872abb9a5ebb9435bedc994d5e276b82c2e00', - gas: '0x81a8', - gasPrice: '0x47a3d0284', - hash: '0x07158ecabeaa23e23a2b4af3bf54be3f29da81f282cd031358c66addaff2e8d5', - input: '0xd0e30db0', - maxFeePerGas: '0x5c8520e5a', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x6a8', - r: '0x560aa95ec05030c84f9edb33ffa6a64f14e95c7edf902b9762c8393e424ee8d4', - s: '0x4fdf9270b586f36d185097e54832e318f1f1e2dbdec3a5b70b678c6c98374387', - to: '0x0000000000a39bb272e79075ade125fd351887ac', - transactionIndex: '0x76', - type: '0x2', v: '0x1', - value: '0x1aa535d3d0c0000', + r: '0xdc17fd763bd1179048b067b66a48417bb8d73e35928ad63dd63dcfaba7a17aa3', + s: '0x47175b8f9c3409db288d3100cf3b9885d352e86fad0a6a351328e5b286e89fef', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x9f123754dc9cf15acaec06fddd301b4439117919', + gas: '0xb5d0', + gasPrice: '0x2865d3cdd', + maxFeePerGas: '0x4c797381c', + maxPriorityFeePerGas: '0xa6036eba', + hash: '0xabf04b2329ea6738ead1f4bb34305b753e7b525a0481e8555ec3e5ccbdc951fd', + input: '0x095ea7b3000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', + nonce: '0x173', + to: '0xc4058f6a829ddd684e1b7589b33312827f0a47bb', + transactionIndex: '0x38', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0xf464720e933a4818e332005f65e85ca38198ed0e', - gas: '0xeb04', - gasPrice: '0x47a3d0284', - hash: '0xbe213bb3cf09088600a8a4d6dcaa6e43e22c730a2b79686b99cb2dd23c89b0ac', - input: '0x095ea7b30000000000000000000000001e0049783f008a0085193e00003d00cd54003c71000000000000000000000000000000000000000000000000001ff973cafa8000', - maxFeePerGas: '0x62bb2392d', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x39', - r: '0xd41571e5da0691205d0ac01a2752e6ebd93adb2ab3ee49fc8eca982a5a59eb34', - s: '0x1ef672723869b506f46d903606f702b642a499958642962e358cc3633488dde5', - to: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', - transactionIndex: '0x77', + v: '0x1', + r: '0xae71506fbaa0409421f12e4220cc7c59d0d9162f79c0e1969121232594996815', + s: '0x519e8f00bb7561786db8842bb6542ad86c07c99ec741aa0d0cd67dc76aeb1294', + }, + { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x0f2b20ab27c376fa8a0a723d2a3b001b397a65ee', + gas: '0x41f14', + gasPrice: '0x27473fe51', + maxFeePerGas: '0x2dcdd2a12', + maxPriorityFeePerGas: '0x941a302e', + hash: '0x257dfbb34339d74bb45c8dd8115ca42794ef9ac83ccf9d8f0b9351674909390e', + input: '0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000001924520791700000000000000000000000000000000000000000000000000000000000000040b000604000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000002386f26fc1000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000002386f26fc1000000000000000000000000000000000000000000000000000000000078c13aad8a00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc20027106de73ced5dd4c33235f9f4bf5de47b5d33c6392a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000006de73ced5dd4c33235f9f4bf5de47b5d33c6392a000000000000000000000000000000fee13a103a10d593b9ae06b3e05f2e7e1c000000000000000000000000000000000000000000000000000000000000001900000000000000000000000000000000000000000000000000000000000000600000000000000000000000006de73ced5dd4c33235f9f4bf5de47b5d33c6392a0000000000000000000000000f2b20ab27c376fa8a0a723d2a3b001b397a65ee00000000000000000000000000000000000000000000000000000078c13aad8a0b', + nonce: '0x8', + to: '0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad', + transactionIndex: '0x39', + value: '0x2386f26fc10000', type: '0x2', + accessList: [], + chainId: '0x1', v: '0x0', - value: '0x0', + r: '0xe57fcd7cb9fdce32f538297521e42ac044016481e73fb7067a341a3e1c8d800a', + s: '0x6aa2c79fbcbbe353cf8dc41ba536563ecbc4bdd00a8221a0fea7961139d3a38a', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x53b83839636d085a47a2f093fb7a136d06890b55', + gas: '0x5208', + gasPrice: '0x2710edde5', + hash: '0x1dd04b7e7904d38fd46feb593b734037aa67d29fe19c25b038befe5af56a646b', + input: '0x', + nonce: '0x0', + to: '0xf1d9ba74a13b91459cc2e826e0443469384576c1', + transactionIndex: '0x3a', + value: '0x2ec3dada13549920', + type: '0x0', chainId: '0x1', - from: '0x2d7fdca2a80343dc46ad0129856e8b82ead945cb', - gas: '0xd7aa', - gasPrice: '0x47a3d0284', - hash: '0x16c47e6331c4356d92def58627a88982ba34e0fdc5d38a0967a79faa2ba59c28', - input: '0xa22cb4650000000000000000000000001e0049783f008a0085193e00003d00cd54003c710000000000000000000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x62bb2392d', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0xe44', - r: '0xf65542a721d9f35f30d90288e4e416fed7c107a802adc0d626d732937e3beb42', - s: '0x0cbb23391c0657b540dd143d84d54430d05accf1391a192dce9d4971b165becd', - to: '0x2969fed452f73ea8a87ca427e27b13a40fc390ee', - transactionIndex: '0x78', - type: '0x2', - v: '0x1', - value: '0x0', + v: '0x25', + r: '0x92398a15492a4bab8928cca9457083f371c4660a0ff31af08d6935e2f7796d68', + s: '0x7df1ae562a06b5c44627f102e5d6354948d5013e88961beb8b5d67f377dbbdc2', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xe09a8fb43b5ced5be7df43d0c5909bde3da2048a', + gas: '0xbcac', + gasPrice: '0x26adeb03d', + hash: '0x586848dbb2925f9035ed9a59a73382e6d4b043948c59b6c092a0a9e8c2a9c055', + input: '0x', + nonce: '0x104e', + to: '0x982258add546a2a1bcc86e12b2c793a9bd68c88a', + transactionIndex: '0x3b', + value: '0x374103afc33a7', + type: '0x0', chainId: '0x1', - from: '0x5c8e20a9b79c9e25597994fb868b98f92097de33', - gas: '0x38673', - gasPrice: '0x47a3d0284', - hash: '0xa7eb4f13bd122d16890db32cc95498c41c899d90db6ded546595635be8afd65f', - input: '0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000064363f6700000000000000000000000000000000000000000000000000000000000000020b080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000214e8348c4f0000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000214e8348c4f000000000000000000000000000000000000000000000000000002b6d6556409d58500000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000f1e029ae5743fd4a324132a0be6eeebc81060f55', - maxFeePerGas: '0x5c8520e5a', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x39', - r: '0x6ebc6fa0e15b11f8b528105d10e0a5036d80a65b5492ad55c15682e096bfb62c', - s: '0x742cc33888a16df24ed65b2e6c29df694a2ada7e217b2f350ba01598ac641430', - to: '0xef1c6e67703c7bd7107eed8303fbe6ec2554bf6b', - transactionIndex: '0x79', - type: '0x2', - v: '0x1', - value: '0x214e8348c4f0000', + v: '0x26', + r: '0x270fee0b3b8badb54f779595ac8d8936d0ae2aa5b4e20c1bcb0658289c92a0ad', + s: '0x48d225db08a6d1b20c0de9c62a7b000398b1a82a2ea1b8b00ad85d83738d5c4b', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x16210e7685e20ac1b2b6277553641f432ce35541', + gas: '0x16db3', + gasPrice: '0x26adeb03d', + hash: '0xc25c4f94958047698905f548fac93ab1d018e46d58aad05effc102317a8bc1ac', + input: '0xa9059cbb0000000000000000000000008fd05d946402ea4beb1a98c82c23b832ad8f8857000000000000000000000000000000000000000000000000000000000ea9dcbd', + nonce: '0x1', + to: '0xdac17f958d2ee523a2206206994597c13d831ec7', + transactionIndex: '0x3c', + value: '0x0', + type: '0x0', chainId: '0x1', - from: '0xcb280c6b371d3f872d791e5bee09dc4a0670892b', - gas: '0x1fe9b', - gasPrice: '0x47a3d0284', - hash: '0x0f306416f5f9ba69fcc20348dce199ad14402c5d0956c34d1d68535b7b456a6f', - input: '0x0ce28dc4', - maxFeePerGas: '0x5c2f99757', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0xb', - r: '0xaa5a9f7a4e46e240de1a97541c078bdec6c38d01385a12c7417a43a9535879ab', - s: '0x0f9668132ff0306a7713e6d6caa3f37d2b24208cb1574d72707e3cc7d0786531', - to: '0x52a494dbf47107cc0c624ee10703abecaf586776', - transactionIndex: '0x7a', - type: '0x2', - v: '0x0', - value: '0x1dc104a3fe70000', + v: '0x25', + r: '0x8da6618104831415d6fef55af7a978f40480567f851ea8977818d6251f4199af', + s: '0x67177a73fb2fb3bb2d8c72f1d096a34e62e82a227caff58204d6dac7ec82a7d7', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xb01cbd9543c5f17bbe981feea82c3c3338a73968', + gas: '0x16db3', + gasPrice: '0x26adeb03d', + hash: '0x340811e390f205b3c117d12f7c76b72b61a72c499dcd1e6232523fa42cc400f3', + input: '0xa9059cbb0000000000000000000000008fd05d946402ea4beb1a98c82c23b832ad8f8857000000000000000000000000000000000000000000000000000000000df4acaa', + nonce: '0x3', + to: '0xdac17f958d2ee523a2206206994597c13d831ec7', + transactionIndex: '0x3d', + value: '0x0', + type: '0x0', chainId: '0x1', - from: '0xec2a9a192929ed1f280f7fd8935b881e3a649dc0', - gas: '0x5208', - gasPrice: '0x47a3d0284', - hash: '0xc8ca24a0da8b3403305b9cadb26dadcf547d8f23487b5ad1f8d63269786ff46e', - input: '0x', - maxFeePerGas: '0x5c8520e5a', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0xb80', - r: '0xf6675a6518006fec1f26f7b84c188c7d59d8f41f9c289cf7805733be3c36078a', - s: '0x5996c346dfa0606e2a9982990428f1da60bb5af13cb3ff213530061533fd6f84', - to: '0x32b30adef7c9dcb888d97f7b743db457e67f2142', - transactionIndex: '0x7b', - type: '0x2', - v: '0x0', - value: '0xb1310c5a2c30000', + v: '0x25', + r: '0x3620dd5098c4f6fc16b59ac38005994e89445859230a3ad7a7aecbf4db1c34e7', + s: '0x2c9a39c21683e71f3c374f96515d0e5aad1fd74016c87a4907e1adc81a731928', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x36bd54a9db13d13b9ba29003b53b6df2a5160b5c', + gas: '0x16db3', + gasPrice: '0x26adeb03d', + hash: '0xebfbff2ed1b70fbea0e6ecd723b4425827a16e6a321c19d110b856744ae998f2', + input: '0xa9059cbb0000000000000000000000008fd05d946402ea4beb1a98c82c23b832ad8f8857000000000000000000000000000000000000000000000000000000000deb688a', + nonce: '0x2', + to: '0xdac17f958d2ee523a2206206994597c13d831ec7', + transactionIndex: '0x3e', + value: '0x0', + type: '0x0', chainId: '0x1', - from: '0xf14cbf8d2c9913169ece7d9b38ed562cc3601065', - gas: '0x12c78', - gasPrice: '0x47a3d0284', - hash: '0xef8be164d94c0eb5f2bdee4e23897d7992cf6eed26ea29543070ee2798f7469e', - input: '0xa9059cbb0000000000000000000000006c4d1d6d66ded59850bc86b3421501e51cf02e3000000000000000000000000000000000000000000000021e19e0c9bab2400000', - maxFeePerGas: '0x62bb2392d', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x33', - r: '0x25181587b27718980f719f401a5f6013cd6925827d16c2ad44be78edd2235590', - s: '0x601f289cfde285f95add07c1c6248a3257f08683ed100d58cb2816edc5619e91', - to: '0x090185f2135308bad17527004364ebcc2d37e5f6', - transactionIndex: '0x7c', + v: '0x26', + r: '0x0ce7c9c5f608064f1a8ce9aa2da23dadbe7d7d36ddc005e94862a21b0d7bf894', + s: '0x5838b9f8c9e74f5964b5a368f5078e5eb0ceb22350359602c438f6724857f209', + }, + { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xa926414d5dfa0d84568e0c5b8f56e7f7e3efa586', + gas: '0x99cf0', + gasPrice: '0x26638c43d', + maxFeePerGas: '0x26638c43d', + maxPriorityFeePerGas: '0x26638c43d', + hash: '0xe0538be140f6fba190704ebc37c3567564279ee638b87aaa14eaaa7815193270', + input: '0xbc4a02e4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011f84b9aa48e5f8aa8b9897600006289be00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000004c0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001000000000000000000000000004449cd34d1eb1fedcf02a1be3834ffde8e6a6180000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000f43fc2c04ee00000000000000000000000000000000000000000000000000000f43fc2c04ee000000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000042000000000000000000000000000000011f84b9aa48e5f8aa8b9897600006289be000000000000000000000000f2fe30dc99d372d0a01536ac33f08d9f84e93bec04683224e167e4eee5fe44c6ea1ae04e7428672652c36434362ef87420e04f010000000000000000000000000000000000000000000000000000000066fb26c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000095ad61b0a150d79219dcf64e1e6cc01f0b64c4ce0000000000000000000000000000000000000000008418fcc49d238e7e0221420000000000000000000000000000000000000000008241bb19137d5a9502c252000000000000000000000000f2fe30dc99d372d0a01536ac33f08d9f84e93bec00000000000000000000000095ad61b0a150d79219dcf64e1e6cc01f0b64c4ce0000000000000000000000000000000000000000000054c11d5d6d296b76b3bb000000000000000000000000000000000000000000005392c12f870d0f215ecd000000000000000000000000000000fee13a103a10d593b9ae06b3e05f2e7e1c0000000000000000000000000000000000000000000000000000000066fb25b00000000000000000000000000000000000000000000000000000000066fb25ec000000000000000000000000225a38bc71102999dd13478bfabd7c4d53f2dc170000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000843cae18d3073e94894c450000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004187c692839afd56822dd7dd7dae860cb41cda2004d36f96ba6c396d9b88d6a6a15ae5c67e8e3532799310754d66c86e519092908d4590802cf2e484fd3c11c3c91b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041c3b4f7a7f5e8c535bb4cb0af3121afc4985b15ef956eca830c31b70e5519ec6e550b7af59265047fb8883370a56ec0acd7541e5c088ad37426517db0944b29be1b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000f43fc2c04ee000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000095ad61b0a150d79219dcf64e1e6cc01f0b64c4ce00000000000000000000000095ad61b0a150d79219dcf64e1e6cc01f0b64c4ce0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000843cae18d3073e94894c450000000000000000000000000000000000000000000054c11d5d6d296b76b3bb', + nonce: '0x69e8', + to: '0x225a38bc71102999dd13478bfabd7c4d53f2dc17', + transactionIndex: '0x3f', + value: '0x0', type: '0x2', + accessList: [], + chainId: '0x1', v: '0x0', - value: '0x0', + r: '0x63047ae61ab2312d68373a0e6438a537b9843373944046806797fe18d0c1db68', + s: '0x3603b41d56c4135c18cd5b6acd97bbff8a72681851e98b5a141188368e0174e2', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xa57e4d659e6fb88317a68ea19d18cb8784908157', + gas: '0x7aa97', + gasPrice: '0x259818801', + hash: '0x3fd9147c1bcaf43b7f377afb4f1c67e95a20d47bad4f97766ef7ec438d49d689', + input: '0xa415bcad000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7000000000000000000000000000000000000000000000000000000006553f10000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a57e4d659e6fb88317a68ea19d18cb8784908157', + nonce: '0x18', + to: '0x87870bca3f3fd6335c3f4ce8392d69350b4fa4e2', + transactionIndex: '0x40', + value: '0x0', + type: '0x0', chainId: '0x1', - from: '0xeaced7279d1afb93ec00a7990a45a8a1b2996ddb', - gas: '0x267f4', - gasPrice: '0x47a3d0284', - hash: '0x3fbd6a8181c0fbfb48689db9bc12e4615ca4afc49607a06c8899c5eace3c087c', - input: '0x4488c7cd000000000000000000000000000000000000000000000000000000000000038c0000000000000000000000000000000000000000000000000000000000000002', - maxFeePerGas: '0x5c8520e5a', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x8', - r: '0x8b5040ac315a9c89b115670c17f8535b9598e5bc87342a7f5c3071aa637c793d', - s: '0x77d5b8dfcb4f235dd14f1cee059c49e7d8218c7190782a969912c68172f1ab25', - to: '0x4623900e6d0495cca743665dce8fd815b0433e5b', - transactionIndex: '0x7d', - type: '0x2', - v: '0x1', + v: '0x25', + r: '0xacaa477fc67750994fbda09ed28a9959472fa07571eb940ee174568e3a10afc7', + s: '0x0ca3e6ef7ed44e2159e5bc8f078d0f1ffb2f67c8f50ce8ce7a84af01ec27e6c7', + }, + { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x5c0cc5eedda1fe884162457a942c474dcb8398c8', + gas: '0x86470', + gasPrice: '0x2592a7616', + hash: '0xe26912b3b9d4625115f58fad050b140bb6630c5ff120ac92c688bfc4c7f38526', + input: '0x8803dbee000000000000000000000000000000000000000000000000000149772210a81f00000000000000000000000000000000000000000000000005243dee1f80a05d00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000005c0cc5eedda1fe884162457a942c474dcb8398c80000000000000000000000000000000000000000000000000000000066fb29890000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000b3912b20b3abc78c15e85e13ec0bf334fbb924f7', + nonce: '0x4a', + to: '0x7a250d5630b4cf539739df2c5dacb4c659f2488d', + transactionIndex: '0x41', value: '0x0', + type: '0x0', + chainId: '0x1', + v: '0x26', + r: '0xe600e8a1d719c762179776df83361c4d4753a3c1792c8ac507f3bf7807f807be', + s: '0x27707140518917f432c4823c0615eac72b2d1a4a24ade59f031a75665e1b2001', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xb7ac691c96705f310e728e9d48b4da6fa97510a9', + gas: '0x101d0', + gasPrice: '0x2578f6223', + maxFeePerGas: '0x25bdacac0', + maxPriorityFeePerGas: '0x77359400', + hash: '0xe3e0657e22b40ecba21f74c9e3ea7a036ca20581b3ecbfc648530d31c0c00fa5', + input: '0xa9059cbb0000000000000000000000005041ed759dd4afc3a72b8192c143f72f4724081a000000000000000000000000000000000000000000000000000000000c61b550', + nonce: '0x1360', + to: '0xdac17f958d2ee523a2206206994597c13d831ec7', + transactionIndex: '0x42', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x250e1215ee94b57caa6dc759bd8d09572e953e1a', - gas: '0xf01f', - gasPrice: '0x47a3d0284', - hash: '0x446b5bd934e67d7c6549077efee4b02f439fd2e1115914173ed449f223b45aee', - input: '0xf90a82c800000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000011da', - maxFeePerGas: '0x5c8520e5a', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0xfb', - r: '0xe679055f660c0595492297288a7e9503f489383c7a74849d849a125b153fc770', - s: '0x4aafb347706a36f9be7196c27531f8c43b2d07c0a51af60da89532a33f37e22e', - to: '0x39ee2c7b3cb80254225884ca001f57118c8f21b6', - transactionIndex: '0x7e', - type: '0x2', v: '0x0', - value: '0x0', + r: '0x5fb606ca3ef1d41ab25487102967f3091a30e54ea8e9992fbaf2ff697a2e7f51', + s: '0x3f6f5b851ff5799611cc04b45074bfa5325605c6d2d1da66961a179b654af29b', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x33bbc0aad1db164e9ffb58a04a176e509f995441', + gas: '0xb090', + gasPrice: '0x2578f6223', + maxFeePerGas: '0x25bdacac0', + maxPriorityFeePerGas: '0x77359400', + hash: '0xce117c5845d75b0c4a74c59d947c07dedef0a24626b423a71a327a3793aabaed', + input: '0xa9059cbb0000000000000000000000006cc5f688a315f3dc28a7781717a9a798a59fda7b0000000000000000000000000000000000000000000001eb8842e3130e9d0000', + nonce: '0x4', + to: '0xdefa4e8a7bcba345f687a2f1456f5edd9ce97202', + transactionIndex: '0x43', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0xb9ba3f911fe7f16413da6d9b8e4726f7ad31bd77', - gas: '0x17fc6', - gasPrice: '0x47a3d0284', - hash: '0xe65b6bec825c8ce3df9456cdd55390cbc09fc5f86c20e19455d67968339ac0e8', - input: '0x441a3e7003b89c46295889c5aadce5b73ae8551f3dbf83530ce27c345d6fe94fc43f337e016807a4e2986bc9d4c2c6a2fff6b2c6f351989c0f7a6d2164377848aac7c5d5', - maxFeePerGas: '0x62bb2392d', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x1a', - r: '0xf347daef28fd1489cf97fb24456ac33928ff5138d8f607957d0001e341d37f33', - s: '0x3a14d4de05e89b99eb732b60ba9aa187bd71898ac7e941ed370efbb8e49b2021', - to: '0x5fdcca53617f4d2b9134b29090c87d01058e27e9', - transactionIndex: '0x7f', - type: '0x2', v: '0x1', - value: '0x0', + r: '0xaeff633801201a7d96b40313943b1abed16f8b1339c8f256375c7a8147ec2918', + s: '0x3cb1303c73b3dcb1b3c2e6597a183901e168c93b824f2f8c9a82d50a18306fae', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x6587d861b7cea89e0e78ae4897a1a757bb40cee5', - gas: '0x517cf', - gasPrice: '0x47a3d0284', - hash: '0x9aa4c2aebcb87337eaafd0768324e964af29fe34948a73c3f65205578874faa6', - input: '0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000064363f2b00000000000000000000000000000000000000000000000000000000000000010800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000043c33c19375648000000000000000000000000000000000000000000000000000000000000006510e0700000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000138c2f1123cf3f82e4596d097c118eac6684940b000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7', - maxFeePerGas: '0x5c8520e5a', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x64', - r: '0xbfe992343bd6b9596ab42bc31ee97e82f4bf9c80c63c67ca0cc96b708c3cd032', - s: '0x4bc0740e037b12397c1611036fbff0c71179edc73db0f9089d6f8e886b1214ca', - to: '0xef1c6e67703c7bd7107eed8303fbe6ec2554bf6b', - transactionIndex: '0x80', - type: '0x2', - v: '0x0', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x218b5a7861dbf368d09a84e0dbff6c6ddbf99db8', + gas: '0xb71b0', + gasPrice: '0x2578f6223', + maxFeePerGas: '0x390296648', + maxPriorityFeePerGas: '0x77359400', + hash: '0x54fe77ad2080cc402bde9568bea9ac57439809212def927b1917cfca95c2ba97', + input: '0x6fadcf7200000000000000000000000083ce6dbda88d4b59b370d765567d2cab460bbdc900000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000424b1dc65a40001b93c825faf654197289be3dad4790f537f6f3f8514ee101d781bfb14e7d200000000000000000000000000000000000000000000000000000000002e6d068f95f9328a537dbf96a2e020043b28041f9d0e5bfb99013ad59323ef3d3e4ed800000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000380010001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000066fb25920004050901020306070800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000bd14e106736291fbb000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000242862b3d0000000000000000000000000000000000000000000000000000000242862b3d0000000000000000000000000000000000000000000000000000000242862b3d0000000000000000000000000000000000000000000000000000000242862b3d0000000000000000000000000000000000000000000000000000000242862b3d0000000000000000000000000000000000000000000000000000000242862b3d0000000000000000000000000000000000000000000000000000000242862b3d0000000000000000000000000000000000000000000000000000000242862b3d0000000000000000000000000000000000000000000000000000000242862b3d0000000000000000000000000000000000000000000000000000000242862b3d0000000000000000000000000000000000000000000000000000000000000004a604429b87ac448485c4d9fc0998a706421929cddcb0dd573cf785cac2953bb795cf734eea00b28f7509d3cfdea7e87534f4ef6fce3618553d280ea32e36703cf9bd42360be6f65e64b5befde6661cc07d68fd167feb5e6ee4c6b9b10218ddddc871103ae7253bee671237d0922841db3277dd3d5298da0d9dc666909dc64ce8000000000000000000000000000000000000000000000000000000000000000436b64d15953325ce07131631174c1c402cad140c6d1fed84139f107962adabd4653d7fdb75b235c51abdb91e0b8ae08185fb14fd537c1eb2cf8e9f3320e007381aab007fd4b5f84ebc22b4c0bd5bc97f63bf508678437935eeb65f2ab8d13ec65a10a2d9a3458eeede4dfbb5bef03c52f798a128aac79216c90e576facd06a7700000000000000000000000000000000000000000000000000000000', + nonce: '0x1f5c7', + to: '0x7a13cd97d442856ff5387d55a7b3f09bf680102b', + transactionIndex: '0x44', value: '0x0', - }, - { + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0xfa756425b596a6f602460320c1447902457be9cb', - gas: '0x3b699', - gasPrice: '0x47a3d0284', - hash: '0xef8f8c6d22ee2165d735ed573e867e701dda02189a7ab991b788ccaaa132f8d0', - input: '0x5f5755290000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000470de4df82000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000017616972737761704c696768743346656544796e616d696300000000000000000000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000007aeadc0000000000000000000000000000000000000000000000000000000064363f85000000000000000000000000b3c839dbde6b96d37c56ee4f9dad3390d49310aa0000000000000000000000007d1afa7b718fb893db30a3abc0cfc608aacfebb0000000000000000000000000000000000000000000000001d750cac918e850000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004686be3d4b5000000000000000000000000000000000000000000000000000000000000000001cbcd6a8d79453d9080adad1120abd9f94ba6fb23ce2828e5a434247ad8679971918bded729941b84e7090a75edd53f3d553aebd05d4a193f306b4ac1ce369103200000000000000000000000000000000000000000000000000008726a236b000000000000000000000000000f326e4de8f66a0bdc0970b79e0924e33c79f19150000000000000000000000000000000000000000000000000000000000000000d4', - maxFeePerGas: '0x5c8520e5a', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x2', - r: '0xbd79bee27f16a4031e0e63d950fdce905c6252022690654106987e87b7307dde', - s: '0x13a1b7292f7bd63906e40c7545fc3dece31bba4423b475e5c113109e1996a532', - to: '0x881d40237659c251811cec9c364ef91dc08d300c', - transactionIndex: '0x81', - type: '0x2', v: '0x1', - value: '0x470de4df820000', + r: '0x668415108726913dbcd30a4085b179ca19c69dd7ce0a7f708f3184886accdd74', + s: '0x747c3a776a48d22d9c2700e17d6977e322575cc25f22a350e3af4265ebd18f9d', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xef4423303644c771357eca0afa214df89a5ea633', + gas: '0x101d0', + gasPrice: '0x2578f6223', + maxFeePerGas: '0x25bdacac0', + maxPriorityFeePerGas: '0x77359400', + hash: '0x3d47f76f93b099d79cc26dd3839ed5f9d69f3fd00817347825482a854a756cad', + input: '0xa9059cbb0000000000000000000000005041ed759dd4afc3a72b8192c143f72f4724081a000000000000000000000000000000000000000000000000000000000632ea00', + nonce: '0xf', + to: '0xdac17f958d2ee523a2206206994597c13d831ec7', + transactionIndex: '0x45', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x65a8f07bd9a8598e1b5b6c0a88f4779dbc077675', - gas: '0x249b3', - gasPrice: '0x47a3d0284', - hash: '0x260725511b21a06d2232db5c7f6f88ea5bbdacccec4b78569a818927a80d839b', - input: '0x0b86a4c10000000000000000000000000335a7610d817aeca1bebbefbd392ecc2ed587b8000000000000000000000000000000000000000000001159db99924a0b63247a00000000000000000000000000000000000000000000000003d335486200732c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001000000000000000000004de473465ca7f47e82033303e5d0aa0f49700e960eae', - maxFeePerGas: '0x5c8520e5a', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x133f0', - r: '0x7ab0c2b5c6dc410da3f42d236a3d94c7da6c12c182465c26fa0c17b430e6c956', - s: '0x6618d10da00ede136502805d6375a2596085183a79fe6e508024d9cf3d2c3550', - to: '0xdef171fe48cf0115b1d80b88dc8eab59176fee57', - transactionIndex: '0x82', - type: '0x2', v: '0x0', - value: '0x0', + r: '0xe6c0dc89c42a18a373835616e90e329459d26cd2c06d69cda324956d4376e579', + s: '0x1f5cf985bcff88c255c873963fa427227ca6794ceeb1f2a023074877f3b1fb45', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x0d29bc8f8e5ca0bf78727f83ab9b577414abed0d', - gas: '0x5208', - gasPrice: '0x47a3d0284', - hash: '0xd8b7c50d281e37dc01810fbd1c3cf314d707d175feb50f1c94e5cd07722a8e6c', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xbf94f0ac752c739f623c463b5210a7fb2cbb420b', + gas: '0x33450', + gasPrice: '0x2578f6223', + maxFeePerGas: '0x74e1881c00', + maxPriorityFeePerGas: '0x77359400', + hash: '0x9fcefad5998ab0e843643b3a79f506aa5531562cc5edb296987cdb23448de1ea', input: '0x', - maxFeePerGas: '0x5c8520e5a', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x6', - r: '0xd4c34b8c853fc0ec5a5e6684de1b416439162be033d48b3d01abd294005b6c9f', - s: '0x6fbb55f270eb517a4eddc48c57f912188b7d95ec7803df7f943486022a5cfea7', - to: '0xab22705c4adae6503edfc3077b2884ea1761b7db', - transactionIndex: '0x83', + nonce: '0x176bde', + to: '0x001248658714bfec2e8b72ca884d9e15182984d8', + transactionIndex: '0x46', + value: '0x2f7ff1b4a5a000', type: '0x2', - v: '0x0', - value: '0x20c0169a35ac5ef', - }, - { accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x7d8859caf443181d2bb13ac2dfea8b44cb663166', - gas: '0x183ac', - gasPrice: '0x47a3d0284', - hash: '0xa78b1dbfda5a5cc59a760c03e3e38064db95dfcb7f6b8d5d5810ecd31f445335', - input: '0xa9059cbb000000000000000000000000bb34867d3e8129223fd1c5369099b1c89302185c00000000000000000000000000000000000000000000000000000000a2308de3', - maxFeePerGas: '0x67cf7f4cd', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x7b', - r: '0x171001f29b776d199fbba9586b240043d587102d654a8b9e9e5f06131dd89a60', - s: '0x152d296ccb9c487edb05e4276c2796414c5a8929c7f127a3d08d09fb3e8219e6', - to: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', - transactionIndex: '0x84', - type: '0x2', v: '0x0', - value: '0x0', + r: '0x003876de464626eafe48277d24a3bd9374032602175a89b213127f95c1a259c6', + s: '0x208436b756e26190d99860ad104efd7142b67899770dabb7c786b80d925d3e56', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x22d2df0ce76a61aeb1a8a75582220d67da14226a', - gas: '0x16843', - gasPrice: '0x47a3d0284', - hash: '0x5470c161462213629f4d2b7402fdfda71a6fd3721d6bd5d699dcb9bc24c50d21', - input: '0x439370b1', - maxFeePerGas: '0x5c8520e5a', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x0', - r: '0x12e091f6e84b915b7c343453731b4ac8a8225aab24f57fae2e37b0fdc9eb7625', - s: '0x3f14a8cf96eaafc238eaff987ee29e462b790d83ff7aeeb65c0635d82f94f8ca', - to: '0xc4448b71118c9071bcb9734a0eac55d18a153949', - transactionIndex: '0x85', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xbf94f0ac752c739f623c463b5210a7fb2cbb420b', + gas: '0x33450', + gasPrice: '0x2578f6223', + maxFeePerGas: '0x74e1881c00', + maxPriorityFeePerGas: '0x77359400', + hash: '0x62e57e308fc738015e6859d61a9226f51c7c67e118bb8b07499f91a4c5f6640d', + input: '0x', + nonce: '0x176bdf', + to: '0x178e861ee7b17b5abc493bdfd000f3e8c853c318', + transactionIndex: '0x47', + value: '0x23c69c94e36000', type: '0x2', - v: '0x1', - value: '0x38d7ea4c680000', - }, - { accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x6b1a08b839e9e0b17654cb136cf6bc256da482d8', - gas: '0x3a02f', - gasPrice: '0x47a3d0284', - hash: '0x0943c536186591acb818e8ace6fcfd4af0df06b8853c30ddf185f78ae54ccbef', - input: '0x5ae401dc000000000000000000000000000000000000000000000000000000006436437b00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000e404e45aaf000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700000000000000000000000000000000000000000000000000000000000001f40000000000000000000000006b1a08b839e9e0b17654cb136cf6bc256da482d80000000000000000000000000000000000000000000000000035c63d009cfebd0000000000000000000000000000000000000000000000000000000001acaebe000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x5c8520e5a', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x6', - r: '0xe28a0a218e0699a8c592d5468c915ec4088659ce637c0969533bd8a32f00deca', - s: '0x401ef72021a21de34b623e75fb01293d335e6f0ebf4389eba6b1a38076e74d9a', - to: '0x13f4ea83d0bd40e75c8222255bc855a974568dd4', - transactionIndex: '0x86', - type: '0x2', v: '0x0', - value: '0x35c63d009cfebd', + r: '0x33892fe953d14800b0143f14f8c736beaded6aeaa637ed7a90e2cb071181f835', + s: '0x271577809d6fdbf837af852e7f3bfa202d789aa2087ce87889195c7a9eea682b', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xdfd5293d8e347dfe59e90efd55b2956a1343963d', + gas: '0x32918', + gasPrice: '0x2578f6223', + maxFeePerGas: '0x17bfac7c00', + maxPriorityFeePerGas: '0x77359400', + hash: '0x88b8eb85f23733828a14797654e882e1c29db7f657ae4609a8f70cd2e909d74b', + input: '0xa9059cbb0000000000000000000000007f2acd33144c7133b38109485b358e9d9342e1a8000000000000000000000000000000000000000000000539f009b44b845f5c00', + nonce: '0x95168e', + to: '0x0f5d2fb29fb7d3cfee444a200298f468908cc942', + transactionIndex: '0x48', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x296fa974a8a4e3d749a4d4e3b9ccca7bbcad423c', - gas: '0x4d4b0', - gasPrice: '0x47a3d0284', - hash: '0x66fd0cb4264aa2e61fa2e4abc224f9682d09092865e1025974a4bde51ad906d8', - input: '0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000643645d300000000000000000000000000000000000000000000000000000000000000020b080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000044c5662810cd9d000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000044c5662810cd9d0000000000000000000000000000000000000000003a9ee6b1a463c311449d4300000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000f0bef9840e4f7166e52c7af2d72ec566bbf39bdb', - maxFeePerGas: '0x5c8520e5a', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x6f', - r: '0xfa9298dfdecc4b63821071e864c0cca273ff63f0d8ad3bcdfd03dc9883d7d905', - s: '0x0d234fb1b27f627e25edded27bacff2946b348c29e5c89f268a405765a7ff65f', - to: '0xef1c6e67703c7bd7107eed8303fbe6ec2554bf6b', - transactionIndex: '0x87', - type: '0x2', v: '0x1', - value: '0x44c5662810cd9d', + r: '0x40bbba1996f7b5ebe6fa825309e5050cd18dd54b6b5577ea5bd5303a1a207939', + s: '0x4eec227220a44d4e215c03b2d14223f053065b48ebd7e3eb2e9aaab1e36270c0', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x9696f59e4d72e237be84ffd425dcad154bf96976', + gas: '0x35d14', + gasPrice: '0x2578f6223', + maxFeePerGas: '0x17bfac7c00', + maxPriorityFeePerGas: '0x77359400', + hash: '0x0569d15422b0d1d03859250b39446d4cb27d211b8fe9452103e8f920c0921ad0', + input: '0xa9059cbb000000000000000000000000f42175b8e41fa02a842a60c659d7c886c22cf910000000000000000000000000000000000000000000000000000000001dcfaf1e', + nonce: '0x684bcc', + to: '0xdac17f958d2ee523a2206206994597c13d831ec7', + transactionIndex: '0x49', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0xa4026608c63744182f8b07de8379fd689e2826f9', - gas: '0xfe52', - gasPrice: '0x47a3d0284', - hash: '0x13e1fddea8ffcfb5847041614af2e1502a7be4f0507645fa5216ed8b661e6c23', - input: '0x42842e0e000000000000000000000000a4026608c63744182f8b07de8379fd689e2826f90000000000000000000000007adb81180ac5a676a2030520d5a5fc3e81421003000000000000000000000000000000000000000000000000000000000003fcec', - maxFeePerGas: '0x6807f15a2', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x94', - r: '0x089406d0133a909552145bb4b3b9088117aa3fc80fba3d91e760a649c2529a3d', - s: '0x5ba6c1e240821b42d1faa648e9324421a51053e5c06659a2a727d196f6ec9b8e', - to: '0xe42cad6fc883877a76a26a16ed92444ab177e306', - transactionIndex: '0x88', - type: '0x2', v: '0x0', - value: '0x0', + r: '0xc37cd0cad3eb77f278144108a7e80008892ac59cf4cade3427049b0e62090b4b', + s: '0x07ce91f6ebc8bd427266b89dba5af9a1da6c6f1b095686ce9bf084857781e62c', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x4c949d612269b654e7e18990752cb3b1d3878113', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xb6c8c2074c212549003db919dae8f661eda29a15', gas: '0x5208', - gasPrice: '0x47a3d0284', - hash: '0xdf214d4148f2ac955b0c1097b2c633b5dfae2751a965cd9260b12874ae12bfd9', + gasPrice: '0x2578f6223', + maxFeePerGas: '0x2578f6223', + maxPriorityFeePerGas: '0x77359400', + hash: '0xf26d4a25e1e3e5e01236e2dd6b2da4fc9088e3ad63296d68101623ee8fa0cb1b', input: '0x', - maxFeePerGas: '0x6807f15a2', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x12', - r: '0xe844d08332e69f6dd257146dee8d95648c43056b5163ac81eca2f5773b9c3852', - s: '0x04dd4396702a1dc05e74ca5e5cd39b506d991d0f5dced3fc3bc3c0d5080325d7', - to: '0x3c19a291b31f92ef45b847a89fe5d21acfacc632', - transactionIndex: '0x89', + nonce: '0x0', + to: '0xa1280ba719747c88eab200f6d9b5f34b95c64ea8', + transactionIndex: '0x4a', + value: '0x64cd726843a8c0', type: '0x2', - v: '0x0', - value: '0x853a0d2313c0000', - }, - { accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x7fbb9dfa7bda66a9f2ef19ee8392fbde244cca0b', - gas: '0x18100', - gasPrice: '0x47a3d0284', - hash: '0x9e0b6d88702128b00efba753c85fdedf93c4c91e242f8610e539571bca485932', - input: '0xa9059cbb00000000000000000000000035369b9f5643d3fde9e392c7e2e2ce263664024400000000000000000000000000000000000000000000006c6b935b8bbd400000', - maxFeePerGas: '0x5c8520e5a', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0xb', - r: '0xf472e0c5841a33dd6b12f27e3a0280f41beb8807d57b21166d4cf4049a8e523b', - s: '0x6c9ffdb00da3b3afae3b7a197eec25eb71ef0fec9a77b2b21ba1e5e537fb5326', - to: '0xd1420af453fd7bf940573431d416cace7ff8280c', - transactionIndex: '0x8a', - type: '0x2', v: '0x1', - value: '0x0', - }, - { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x08be4c9c14aa9a39cd07bb4310559b3ae503ff1e', - gas: '0x3cfc1', - gasPrice: '0x47a3d0284', - hash: '0xffc4ee5481e35cf09f5675a05593f8bcd1fbe3c0bfd742ba64655bfbfe5cdc59', - input: '0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000643645df00000000000000000000000000000000000000000000000000000000000000020b080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000b1a2bc2ec500000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000b1a2bc2ec50000000000000000000000000000000000000000000000000000000001ae5f29d27e00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000dde90a7dd65f0eee5cb61cfb973d735208308bad', - maxFeePerGas: '0x6807f15a2', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x45e', - r: '0xf48152acd401687a6273974d723be29405c3ad5001f0330f2967d87e88685120', - s: '0x70d0ecf89b9d2b8351e6ccd728034add7a9ffdbe1ffa70a20862e1c30a2941ac', - to: '0xef1c6e67703c7bd7107eed8303fbe6ec2554bf6b', - transactionIndex: '0x8b', - type: '0x2', - v: '0x0', - value: '0xb1a2bc2ec50000', + r: '0xc2f894b3f4110147d7f0b27c017c8098aa8c8caabb0301c0fc43c531572b9653', + s: '0x5ccc2f89395643e70540e6d8bb2250dc9eec98aedec70ed9bef1c4a75200b49d', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x22d44bb13a8935af45a9d85be518be256a2f5ec7', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xbb1f8f10a60de15ab1c77cc6c5b5e6d091309456', gas: '0x5208', - gasPrice: '0x47a3d0284', - hash: '0x8628c214d87f83b8b6325d648383d3a34a9abc54d7be64606b9e9393c5bb2c87', + gasPrice: '0x2578f6223', + maxFeePerGas: '0x2578f6223', + maxPriorityFeePerGas: '0x77359400', + hash: '0x93c2d382309bb0436e5a1ca083ed47c7839a6936c86c5efe52867fc474a82b16', input: '0x', - maxFeePerGas: '0x5c8520e5a', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0xc8', - r: '0x39287564d388296ef932ad463ef6be1d3cd70e421c3db343f2622f814e848eba', - s: '0x6b0e433c0f0577aca309ddcc2144d28da94a9033fa3fa10846195dc3a602afa3', - to: '0x22769f975be0632bccc29392a66bcdd353246f74', - transactionIndex: '0x8c', + nonce: '0x0', + to: '0xa1280ba719747c88eab200f6d9b5f34b95c64ea8', + transactionIndex: '0x4b', + value: '0x348a4cfdb738e8', type: '0x2', - v: '0x0', - value: '0x30d98d59a960000', - }, - { accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x941dcc59efdae9570c7618fddb351c657d0643c3', - gas: '0x27111', - gasPrice: '0x47a3d0284', - hash: '0x57840573da6aee90a1df7c054e694cea1bdbbcc0ce5504a4c47296bf93b75301', - input: '0x9ff054df00000000000000000000000000000000000000000000000000000000000001c1', - maxFeePerGas: '0x5c8520e5a', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x0', - r: '0xc6d1fe1d09c919751d1938a970e92553bd0ce6fdbc5a257607b22fcddf2792f5', - s: '0x16f43b2fbf8d7a5e555d56707e3b8cd91b7a4fa29d046da608c07ebd5f437f40', - to: '0x06450dee7fd2fb8e39061434babcfc05599a6fb8', - transactionIndex: '0x8d', - type: '0x2', v: '0x0', - value: '0x0', + r: '0x94f9222e57b8280a77608e608e1dc1fcf17c09ee2318eeda89d59a81392da72c', + s: '0x38b2f70820af04b3fdf0f5f15be4b49c43838265a806582a6e786b8584dcd682', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x3d9aa2631c4c10654bbfe03208a572dbf0b40b7a', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x0c4bf85f782303a98af1fe00d5b08039b295522e', gas: '0x5208', - gasPrice: '0x47a3d0284', - hash: '0x7495e9e0cf9f848a202fc3e051bce519b26967c4933ea9f4a3744d75964124b3', + gasPrice: '0x2578f6223', + maxFeePerGas: '0x2578f6223', + maxPriorityFeePerGas: '0x77359400', + hash: '0xaa4bef9afa20f46633c4f0b731f026aace7a0c29d813ac149aedb6a95a829922', input: '0x', - maxFeePerGas: '0x5c8520e5a', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x2', - r: '0xd2d2622af6f8847b9d4cae57e2432e51186f916ad83fca7e596b862c1d3b779a', - s: '0x5c1a52734132e091d26f17eb9f28d2379b2b19b67b0d0f763e269374acb852fe', - to: '0xc5b1f58cea87704cc87510320d8390964b6fe88c', - transactionIndex: '0x8e', + nonce: '0x0', + to: '0x9a10da8ce77f26231860764a2caab36e70584c4b', + transactionIndex: '0x4c', + value: '0x5fe18230c544e8', type: '0x2', + accessList: [], + chainId: '0x1', v: '0x0', - value: '0x1caf12ad1c106c0', + r: '0x465a35bf73786706b06b8c435af6dfbeeea5a59bd250e0b35b1ea85218fdb584', + s: '0x2eae30d64bca61397be3baa6d2e015ce8f178511e7d43b1d80d4f1990c035861', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xe7178ad747f2c12ab1f8332e61cf6e756815d5c6', + gas: '0x13227', + gasPrice: '0x2578f6223', + maxFeePerGas: '0x869c11cf7', + maxPriorityFeePerGas: '0x77359400', + hash: '0x71deb87c646c3c361b5da49dceb2accf33dbd24b271a75a5f896701cd0843777', + input: '0x23b872dd000000000000000000000000e96de4040f138f3de055ed62000e87acf770e66b000000000000000000000000e7178ad747f2c12ab1f8332e61cf6e756815d5c600000000000000000000000000000000000000000000000ed26a979427497c00', + nonce: '0x2fe9', + to: '0x221657776846890989a759ba2973e427dff5c9bb', + transactionIndex: '0x4d', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x9ceab4d15f394e3074239fe6f761dfaed566422b', - gas: '0x7016', - gasPrice: '0x47a3d0284', - hash: '0xff7d2273873f7b16e131755ed47ed8de55e540a4bb8d47449d84127ddd3a8bb5', - input: '0xe56461ad00000000000000000000000000000000000000000000000000000000000000890000000000000000000000009ceab4d15f394e3074239fe6f761dfaed566422b', - maxFeePerGas: '0x6807f15a2', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0xb', - r: '0x307eb7a3dc0fcdcea16fe4cf43e3be64ae57ee1700b95712d065a771bf5b135a', - s: '0x134b00a67f5d7188ed38752373ce88f4e81226b2fbd514cca6c418d94e8e46df', - to: '0xb584d4be1a5470ca1a8778e9b86c81e165204599', - transactionIndex: '0x8f', - type: '0x2', v: '0x1', - value: '0xeebe0b40e8000', + r: '0x3347876971007b97bbb628bbfb37563affec3063aac40955f92efa70294c2af2', + s: '0x27abe3633fe698fe7341e13b09ca3b9fc754beb256baf1ae63d4a94451ef6967', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x5acaf7c064f609c1ac40648f200d1160cb3b054f', + gas: '0x24677', + gasPrice: '0x2561342a6', + maxFeePerGas: '0x45db2b971', + maxPriorityFeePerGas: '0x75b97483', + hash: '0x77690af18a59a9f02461afc08ef49524511b1e79006537f690ad8708f31f0c8a', + input: '0x39125215000000000000000000000000ec84631e6562bdc8e14476afe0d43477c0076d4a00000000000000000000000000000000000000000000000007c16cd4cd11940000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000067046014000000000000000000000000000000000000000000000000000000000000dfc400000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041ed642f138ac1ed129d837900f4c3b454541159e82908c838b0124ef9e6c0e6347d169ca19c69c60f4d9bf2bf847b4ac91608c182d40440e08c539d4fb087dc641c00000000000000000000000000000000000000000000000000000000000000', + nonce: '0x10a88', + to: '0x3db76cc3673fef9b454562df53188ac3147826f8', + transactionIndex: '0x4e', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x399b15d63ee62bf2f07a14069d3256bd656a1f90', - gas: '0x3ee36', - gasPrice: '0x47a3d0284', - hash: '0x2dd3225299367625b920766f718ecd62d0d66738ece52fd44c4adb0f8f794c75', - input: '0x5ae401dc00000000000000000000000000000000000000000000000000000000643645af00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000e4472b43f3000000000000000000000000000000000000000000000000017fb16d83be00000000000000000000000000000000000000000000000000000000206f9e7348ad0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000399b15d63ee62bf2f07a14069d3256bd656a1f900000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000da4dd9586d27202a338843dd6b9824d26700678300000000000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x5c8520e5a', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x1', - r: '0x156cb4ab98cba596713e343fd3ab2f8a90203f8cd7d316bd375d111895f92ae1', - s: '0x2117eff2c33ae5e1103367254bb32efb37abeec4cf598dfddd663c1cb0c2fd32', - to: '0x68b3465833fb72a70ecdf485e0e4c7bd8665fc45', - transactionIndex: '0x90', - type: '0x2', v: '0x0', - value: '0x17fb16d83be0000', + r: '0x69e5ba635da804f4f1e84e9f989fd4702314ff45ee2b7756e05d8dd3bedaed90', + s: '0x6d853508b800dbff3010055323958bd340876c2e6961b6fd6a7258e37050bad1', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xfe500c274f72f1d1a9978c903d97e6d45cd9121b', + gas: '0x124f8', + gasPrice: '0x2540be400', + hash: '0xb962355d3deceae05f63d90328c0aa992de4b92f94deb37aa7092bc71102d7f3', + input: '0x', + nonce: '0x9a38', + to: '0xf587ef2f4ab1095d79ee2dc1e3d81a2e6389117a', + transactionIndex: '0x4f', + value: '0x4c93ae84926a9aa0', + type: '0x0', chainId: '0x1', - from: '0xfa4535d38843f78788edb2188485663db5a1c273', - gas: '0x42273', - gasPrice: '0x47a3d0284', - hash: '0xd600a0365ebc112528c0464dd4562de2a74eb692004be7a08b60a821c8dddd19', - input: '0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000643645d30000000000000000000000000000000000000000000000000000000000000002080c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000003913517ebd3c0c650000000000000000000000000000000000000000000000000000000c49b43985820d5200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000308516e6daac88d719af5a6d7ea2a82d8c8e7356000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000c49b43985820d52', - maxFeePerGas: '0x5c8520e5a', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0xa2', - r: '0xd1d608c88b68bd71672371bdfe112966a15d6244cceed691388e836a0e6c5259', - s: '0x2e6d9e638035e9e493f0edbd874205e1d1d4c4d7a8d0d826e98e7e1dc92b5c83', - to: '0xef1c6e67703c7bd7107eed8303fbe6ec2554bf6b', - transactionIndex: '0x91', - type: '0x2', - v: '0x1', - value: '0x0', + v: '0x25', + r: '0x6200bee3ca1caa0d7ad52f80707991335e08ba2109b20ef740efd7f759ce6596', + s: '0x7f7e66fe1c833f26d2ae6853bf7f0a5318e023624967b0557236cdb64d5708e5', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x264bd8291fae1d75db2c5f573b07faa6715997b5', + gas: '0x7a120', + gasPrice: '0x2540be400', + hash: '0xce14fc05c5273c396817f5ac373d79dbfed8e3f5edb32f9c2bcb5678e82eb45d', + input: '0x', + nonce: '0x16fc35', + to: '0x366330c987232726f3f4a2ff602eea8f12597f6a', + transactionIndex: '0x50', + value: '0x16b090b240ba000', + type: '0x1', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x61098ee5109aa530c2fd73c059465ebf813fbdd4', - gas: '0x31418', - gasPrice: '0x47a3d0284', - hash: '0xdb05f67a2e1f965826ca9aae165d96ec1883129ba84718da14f7c35a6e1e342d', - input: '0x6933e79a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000cda72070e455bb31c7690a170224ce43623d0b6f000000000000000000000000000000000000000000000000000000000000003c516d525976506b32726935417836734b4577734144466362316377365a4e53704d376965627654444337713757672f6d657461646174612e6a736f6e00000000', - maxFeePerGas: '0x5c8520e5a', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x6a', - r: '0x128e7fe55747469b4be913e4706a22b206f994208b64aabc39d3825606c00555', - s: '0x185f45cb1c7c6d16f30ffaabd347b5b2cfe7c2c0f17f4e48b3e9a6654a132ce6', - to: '0x2791b93591de3fad825e41bd593c53481f407f82', - transactionIndex: '0x92', - type: '0x2', v: '0x0', - value: '0x0', + r: '0x3448d9201370056c3a7eb327a92f2d0caf506f7a5c4f18035cc03446c3b7dcd6', + s: '0x4d8e75d48d3e95c10ab30e5d1c682503e054cd7ab2f44c47cde53ce76eecd4f8', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x264bd8291fae1d75db2c5f573b07faa6715997b5', + gas: '0x7a120', + gasPrice: '0x2540be400', + hash: '0x5ce9475d32da021dfa09beb2c8a506ad7fa3371aa505b7f4fa97b0b9d7e7b84c', + input: '0x', + nonce: '0x16fc36', + to: '0xf2b5475c33a7cf160f1d046bb4d69b10c469d52f', + transactionIndex: '0x51', + value: '0xcc4e706bbfa800', + type: '0x1', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0xade95db92eb86329b08f1c67bee2636fe922f9aa', + v: '0x0', + r: '0xad846f80c56e692f5471f9d6af8254f3c192270f0eb786b533d370c2e95a9cdf', + s: '0x3baa55e6161e8aa6df6353f3060992bc7577a8c914c1480b9861a3933a75fb03', + }, + { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x0000081778b25d85ff65b796dfe7643436d9b654', gas: '0x5208', - gasPrice: '0x47a3d0284', - hash: '0x50734d83880b3f249d60c15226df34c22e222faa5079c3d7ed7665dddc906ece', + gasPrice: '0x2540be400', + hash: '0x45bacefba1cd0fc3c285d823fcfb13a7e5f351338549b869c40100bdf95e1d7d', input: '0x', - maxFeePerGas: '0x6807f15a2', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x2', - r: '0x69d4b620c6a3d91efadbc9b3e3d8be839e226d0636eca2b3b472a07404d22630', - s: '0x1dd6083f4de1ab299ea3afb89aca0fbe749bf4654f0b1595caf2dd36ee49cb8f', - to: '0x9d281056b1591889c481b48c9ada12afbaedb758', - transactionIndex: '0x93', + nonce: '0xde3', + to: '0x08e06810195d642b9319bccb7edebe4876d3f9e1', + transactionIndex: '0x52', + value: '0xbf15b7de0800', + type: '0x0', + chainId: '0x1', + v: '0x26', + r: '0xb340c038ecc7bbcb5a444a8338f37116d33b539c9937e524b117cb6d4c23e863', + s: '0x527659e00b59daf9fb01eac10456a900b5e8f1ae28f0954953240feb941f439f', + }, + { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x05cdb1526f6e224e02919a4c018d9784ea25eb3d', + gas: '0x1daf4', + gasPrice: '0x253643035', + hash: '0xe64e91d4698ccab2020a6403a91de9f18a41f0e2403ff165ebd8d84a29838a67', + input: '0x1be19560000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7', + nonce: '0x3039d', + to: '0x0d511a60c91932fe22d5234c939bbc2dec8a3db0', + transactionIndex: '0x53', + value: '0x0', + type: '0x0', + chainId: '0x1', + v: '0x25', + r: '0x3e25261b445244d25d73cd5f9f625bf41c233937d4ba3659c510405e7bee7ac4', + s: '0x1f3d4c1143350701e26e933a965deb8524ac66f63ab2ecd6179c1eae86b5581d', + }, + { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xc413c9b56a787484ae3d603dd614d7d444f443bc', + gas: '0x1c46b', + gasPrice: '0x249e2cc37', + maxFeePerGas: '0x2f5a4c92a', + maxPriorityFeePerGas: '0x6988fe14', + hash: '0xfaf15332c9509c54ae901d75aaf50536cf7ca73829fbe85112f38a03436ad963', + input: '0xf3fef3a3000000000000000000000000f951e335afb289353dc249e82926178eac7ded780000000000000000000000000000000000000000000000000d3812c03ae3acdb', + nonce: '0x15b', + to: '0xf047ab4c75cebf0eb9ed34ae2c186f3611aeafa6', + transactionIndex: '0x54', + value: '0x0', type: '0x2', + accessList: [], + chainId: '0x1', v: '0x0', - value: '0x449c9dce3988000', + r: '0x40e5e0aa2c2180fc5cc5319615f87b7d81670465e62d3d3c417bdcc2fd7707ef', + s: '0x7b8c116870c3bc0dc2aa7d062387339810b7dafcbe1593578dbf578943d8db3a', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x99eb76f70df2342298ab44e9a9f31c374ba666c7', + gas: '0x5208', + gasPrice: '0x249e2cc37', + maxFeePerGas: '0x2da1871e1', + maxPriorityFeePerGas: '0x6988fe14', + hash: '0x784c652cb876ade81893278211aa6f75200d0c4d4743fc7d9f71a2f971768c9c', + input: '0x', + nonce: '0xcd', + to: '0xad7368905c7669153582e8b66d1a4d73ca542bc6', + transactionIndex: '0x55', + value: '0x56e8a9d088df9', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x9ffb5f8a0f2c4ae6538e531bb1e5ae44847a3c40', - gas: '0x396cf', - gasPrice: '0x47a3d0284', - hash: '0x6173d906ffd35d3b326a3e750b6d663d2955fdc6deeab20e409af5385cf8e4c8', - input: '0xfb0f3ee10000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005e18405b53e50000000000000000000000000000968a15596c0f760a3813b79fa85d442a35760a95000000000000000000000000004c00500000ad104d7dbd00e3ae0a5c00560c00000000000000000000000000769272677fab02575e84945f03eca517acc544cc00000000000000000000000000000000000000000000000000000000000017c40000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000643639070000000000000000000000000000000000000000000000000000000064378a870000000000000000000000000000000000000000000000000000000000000000360c6ebe0000000000000000000000000000000000000000ef0b1e2cff64c8340000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000027f7d0bdb9200000000000000000000000000000000a26b00c1f0df003000390027140000faa7190000000000000000000000000000000000000000000000000353cc731f590000000000000000000000000000cf398a1ed09a38613d2c76366e9a4b2cf21eb03f000000000000000000000000000000000000000000000000000000000000004006ea7ad410c362854f8903280b5650fb214f8ccc0cc9dfbd0ddd4f1cd7b0251fd239906faaec755675273f21b5389ea77b09d432257ae26b006898e2cfffcc511f6e66746e657264732e61691f', - maxFeePerGas: '0x5c8520e5a', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x3a', - r: '0xe14680f20870065765c3c1e48dba3ff8fefb013b84a98a9eb0bfd11e8b535d45', - s: '0x5ac7f29ac66342e710db290258958d7f9dabfc475cf71e2ec01a92cf91e0b47d', - to: '0x00000000000001ad428e4906ae43d8f9852d0dd6', - transactionIndex: '0x94', - type: '0x2', v: '0x1', - value: '0x63eb89da4ed00000', + r: '0x99605d3966dd9df78436a19e1794d8882bf2b88b40c0734caa57f5df51e69ac9', + s: '0x31b224168df028d61066f2c420726d965cf4ad9b0afec9f6eaca9a557f4f3c16', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0xab234769c7b777736fe0296190e9b6f69dcf6ddc', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xfba17c53a5154f60b3570476f74db090e93bcd80', gas: '0x5208', - gasPrice: '0x47a3d0284', - hash: '0x00c1a4dc51c377b6bb00af16bb30526543f727c11a6370741191979c471d1ffc', + gasPrice: '0x249e2cc37', + maxFeePerGas: '0x2da1871e1', + maxPriorityFeePerGas: '0x6988fe14', + hash: '0xac86e6844958d835266d2343d16ef58e7974d0d627316c229046d4b2b2349a06', input: '0x', - maxFeePerGas: '0x5c8520e5a', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x4e1', - r: '0xc83c53992ea82dc9ca2b48702930f9e296fcf84c6cddc12dd36f5cb36f771143', - s: '0x52e4d4b69c01b5a39874c92c78ccddbd47afc5b8b72cc6053c88b6ac1985b555', - to: '0x5b235e2844eab73c073a54f6928b7f8358e51e32', - transactionIndex: '0x95', + nonce: '0x59', + to: '0x0b2c45c300da6cc7a4ce3b58312dceea04b8b2ee', + transactionIndex: '0x56', + value: '0x1cc13905a69c000', type: '0x2', + accessList: [], + chainId: '0x1', v: '0x0', - value: '0xbfbd6dd6872000', + r: '0x9e7b4ef3b26740289c2603327598dfd699ba28ed94788aa51f2d7d534f4d75d4', + s: '0x43518fb468bc7138be700642608dbb3a0f50d452fd253bdd0f068d12dcfcd8ea', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x31ed28c2549e0195c4a405b71e4f18efb935be6f', + gas: '0x7a1200', + gasPrice: '0x249e2cc37', + maxFeePerGas: '0x2589248d2', + maxPriorityFeePerGas: '0x6988fe14', + hash: '0x195865c2f47abace48f0fc6cef4c8069766f03ffefed03bd29e2c54e5d2e6387', + input: '0xb1dc65a40001b728806c50675d907f631fb922ee3658492327dfb556b5638ce5ac48a3290000000000000000000000000000000000000000000000000000000000354c03539c2570c7d24ba3f4d662e9212421837cd84e0387d59edf3aeafedaa32c865b00000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000003400000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000064d029850f1a0971000000000000000000000000006488a1d667000000000000000000000f97d78e0000000000000000000000000000000000000000000000000000000000000006450cd5262d1f06f2a9f4061baf987e233c3147acea32cbca1539c00fd8d433781162f484d43540fe92d76dbd0cacb33b9b84af480826c00a8e6f5e283b456976baae96d272162e277d81061f07fcd5cf26ad7a1872d215ae41e089ba6da4a071f6f850f5bf248d83f387b4144d0e9a5a0933449f414297c33ae0e831c9a4b0f8f085872f06eb6a0d27c6f1c34371f8c03af16df248481c859ab694c08ae2be86590a4b9114b00e8da8580680ae4086d2c6aa0c350eacc664633f2c6a2b63935b00000000000000000000000000000000000000000000000000000000000000060ea94412e7604aaa8be4651252f0e8a9a5bcc8df09b3ff41ea90bd1b1e33248b25d6d1fed177803f59900f2a7fe588cdbd0aa617ca35a7ac76190f5c6935c78507d3505bf9894a99d00bb262ad26c1b359269c68f9a63da35af712db4d3cf7e92b09e75baf5f9b08e60320996f7a164e6e00f2b8a3446ca5c7663c1e8cacda7312b3c17377bdf448c0321caf88062302b10e3ea37a2c93f7aa56bc58092a214859c25e1c4ec38fee03a1fee93e8e678faf6a77507f8b1ad2b27a0494cfe703e5', + nonce: '0x5a62', + to: '0x2aa101bf99caef7fc1355d4c493a1fe187a007ce', + transactionIndex: '0x57', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x5c91a8f7147e6ab2765e6cae4a283c0055e2ee8d', - gas: '0x5208', - gasPrice: '0x47a3d0284', - hash: '0x8c7518bea80f39a803930123b6782845ce8f8d99a782163aadfa924cbb28ee91', - input: '0x', - maxFeePerGas: '0x5c8520e5a', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x7', - r: '0x3f518ed2dbd15a13948873b15a61e35a685a2819d330c17a6c896fb577887f92', - s: '0x209ab4820a10c06cfc24ae4dc64fe98106eece4bf69c5ef0c26ee6524f1b88d8', - to: '0x036b16b5067a1c0c6923c9526bf76fb125619a9d', - transactionIndex: '0x96', - type: '0x2', v: '0x0', - value: '0x214e8348c4f0000', + r: '0x52dfe083e471cc8f959662a10833daa8df8d3261aec7e094219056a7e7a1a9aa', + s: '0x69c5a939a141f1d27f4bb4b8dbd025958d5a3816ae3a2df514544f76a0cdf5e6', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x445c7eed59328d8a25aa9be4624edf62f6430129', + gas: '0x39183', + gasPrice: '0x249e2cc37', + maxFeePerGas: '0x2ff086469', + maxPriorityFeePerGas: '0x6988fe14', + hash: '0xcd7e94609b6509c3077849af898feb955501cc0473eda70a2e1b8f71645c1b43', + input: '0x0d5f0e3b000000000000000000000000445c7eed59328d8a25aa9be4624edf62f64301290000000000000000000000000000000000000000000004ba54072578be5a9f4f00000000000000000000000000000000000000000000000005c6f9f4287d055a00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000001200000000000000000000000fa5a486ec5a12307f94fd26125109652ea42b2b7', + nonce: '0x702', + to: '0xf3de3c0d654fda23dad170f0f320a92172509127', + transactionIndex: '0x58', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x609946cccb57a391dc7cce2cff8cbe8a29343d0a', - gas: '0x52c11', - gasPrice: '0x47a3d0284', - hash: '0x4ceca9cf5bff5da1d3d1837fb77f1f576767b8a9d6d4062de0eee706b7773d6a', - input: '0x8af033fb000000000000000000000000555b6ee8fab3dfdbcca9121721c435fd4c7a1fd10000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000006400000000000000000000000002d886570a0da04885bfd6eb48ed8b8ff01a0eb7e000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000609946cccb57a391dc7cce2cff8cbe8a29343d0a000000000000000000000000000000000000000000000000000006406d04bd1c000000000000000000000000000000000000000000000000007f6ed61eb47df2000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000064364371000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000000010000000000000000000000003beeab9d5624e487045e01d12332975204a04a8a0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000006406d04bd1c0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000040d07961740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000003beeab9d5624e487045e01d12332975204a04a8a0000000000000000000000002d886570a0da04885bfd6eb48ed8b8ff01a0eb7e000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000555b6ee8fab3dfdbcca9121721c435fd4c7a1fd100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001f87b22536f75726365223a226b7962657273776170222c22416d6f756e74496e555344223a2236332e3337383736343437373833333236222c22416d6f756e744f7574555344223a2237312e3232333835333933393134343833222c22526566657272616c223a22222c22466c616773223a332c22496e74656772697479496e666f223a7b224b65794944223a2231222c225369676e6174757265223a22625a6658774a7632434643422f5767677736704c39536c6f776e6c305368684c34725a416e346b784a2f2f39385935584c6f34354f585a72424b387746423076786673356b576f753374334b76322f6c7a734952352f3039445a3566696132567169743970632b644c324f6e663052766948716949636f5a5172707a6a64414538747171586967743761543354723045584b465855373078466559427157426e6144536d436774636a696b566a666f452f6376314a686234716b4f6e626338307530744b4258487279525a3576412b4133373656614f70776c5531315a665275773567734b3963626171735a61487831674f596b52547658786337524c4939326b73324c386175787631756943574a5653574b44446254335059594d4c6c623046492f66396e5a694638345048376f706c48512f69686875724d4879444531774868383430665845422f6b4347674a4451592f7771673d3d227d7d0000000000000000', - maxFeePerGas: '0x62bb2392d', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x32', - r: '0xfb775bca5c6dc8f9920b24e4108bb822cd272a68e46c22ca9599d234a309e572', - s: '0x6a9a15cac84e1b5f1cc71130261b746317ef68066b46806e783324ada7583854', - to: '0x6131b5fae19ea4f9d964eac0408e4408b66337b5', - transactionIndex: '0x97', - type: '0x2', v: '0x1', - value: '0x0', + r: '0xacc9239c180259036770f6e6117ad56826d3180cdfaf13679a1d29abcab6114f', + s: '0x2e6417f2b64628199fa514b6515c89fc187722307a46589d0f83a04c7e99e2ea', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x21a9e6680cf19b95052534f502eb530795941339', + gas: '0x2cbeb', + gasPrice: '0x249e2cc37', + maxFeePerGas: '0x31a94bbb2', + maxPriorityFeePerGas: '0x6988fe14', + hash: '0x9242328fa911035d390d9024b83e47c452419fb27c50901b572edb4a3c3ffa03', + input: '0x9871efa40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000019de1e447f0139000000000000000000000000000000000000000000000000000108e62b40c028600000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000001b0000000000000003b6d0340782cdb39c77c74d66e9b9e7ea319fd364554d663', + nonce: '0x0', + to: '0xf3de3c0d654fda23dad170f0f320a92172509127', + transactionIndex: '0x59', + value: '0x19de1e447f01390', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x92265f4c85619ec8b70bb179ff1f86c56e54d348', - gas: '0x36a70', - gasPrice: '0x47a3d0284', - hash: '0x03f236728362e5cfc12a712b822a3ab1d79e0eb0268ea771dac94c17750283f1', - input: '0x00000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017d074e88292000000000000000000000000000ed7c461fb6569c1e462d9da7f3ac2e99285f268d000000000000000000000000004c00500000ad104d7dbd00e3ae0a5c00560c000000000000000000000000002969fed452f73ea8a87ca427e27b13a40fc390ee0000000000000000000000000000000000000000000000000000000000001175000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064363c4c000000000000000000000000000000000000000000000000000000006436400c0000000000000000000000000000000000000000000000000000000000000000360c6ebe000000000000000000000000000000000000000098a48709306da1660000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f00000000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f00000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000009c51c4521e0000000000000000000000000000000a26b00c1f0df003000390027140000faa7190000000000000000000000000000000000000000000000000000000000000040551bdcf4ed7c88982d6e5142da8d2cdd76cb0176504a2db01df6faaceb0880c6ca1b733e4434382965114c4aa595080f087f132036a1bd56c40e32493640a5f900000000360c6ebe', - maxFeePerGas: '0x6807f15a2', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0xda', - r: '0x7755f3a5db7f2d6c3bbfca52413d7231f949b00cad3ca483f570d7da82d2b58a', - s: '0x7f7853211ea73c04bdd968bab6856533ad10b6aef7c972796ed816ec817f3f44', - to: '0x00000000000001ad428e4906ae43d8f9852d0dd6', - transactionIndex: '0x98', - type: '0x2', - v: '0x1', - value: '0x186cc6acd4b0000', + v: '0x0', + r: '0x899592eed64ba591d9bf7742387ebbed636159ecde07fcd6112a6823ed7b9327', + s: '0x6c7caf5c3615a57c3cffbaacd8f15e0beb08ea7c85c9b6dee463d6be04342109', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xa0358b0caaa8d3e21f79f746feba4642596282ea', + gas: '0xb998', + gasPrice: '0x246b849b6', + maxFeePerGas: '0x2f7e80093', + maxPriorityFeePerGas: '0x665e7b93', + hash: '0x8bf3fc9155fae9fd342ab892eab592c50c6d7792ab36ff5ab04876d0919840a1', + input: '0x095ea7b3000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', + nonce: '0x7c', + to: '0xf87d5e87143eea0c6051a9db71be0e3fdefc870d', + transactionIndex: '0x5a', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x224030f891006c76ef26b3a768d7792e8c89a960', - gas: '0xfdfe', - gasPrice: '0x47a3d0284', - hash: '0x57574acd1a26c9e233f2ba2c5a7c8b81f6dc05ac9b80b1f87a586937322df147', - input: '0xa9059cbb000000000000000000000000f31ea0f0704545c68e9faa02e8d27d59990d40970000000000000000000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x6807f15a2', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x7', - r: '0xdd2f51f56265814170f0f1829001633009f61a04a79158242ba614804a60f925', - s: '0x24e18bddb2120817f0a86f22a729a249ad74f88f846c86dd616e9c57d1f7c3f6', - to: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', - transactionIndex: '0x99', - type: '0x2', v: '0x1', - value: '0x0', + r: '0xed9f08b8999f53f6398fbe892266d3717090a3d5b58070017b9a2b07fd14065e', + s: '0x265b4adc9efcaa7be3124c5031931a432e4f101bb3fbd88a09dd5e349c17f0fb', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xd2178bc161223d7d1c39c52c4820116321d3ae97', + gas: '0xf7fb', + gasPrice: '0x246b849b6', + maxFeePerGas: '0x33159ab95', + maxPriorityFeePerGas: '0x665e7b93', + hash: '0x317dce199297ad295eb9f86a0eca73370bf973eb3b1c8a5bc51192b352463c63', + input: '0xa9059cbb0000000000000000000000002e0223b98e1e2e8f6546e1002e543673908caef700000000000000000000000000000000000000000000000000000000d03b6045', + nonce: '0x220', + to: '0xdac17f958d2ee523a2206206994597c13d831ec7', + transactionIndex: '0x5b', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0xd6bbc0a9dd616c806e05e281955982f2f561bf3b', - gas: '0x120b7', - gasPrice: '0x47a3d0284', - hash: '0x2f51883b48c322148fc624e8c4c974f4ffe960cc65bdd9bed9085c899eed8926', - input: '0xf242432a000000000000000000000000d6bbc0a9dd616c806e05e281955982f2f561bf3b000000000000000000000000a52687331bf9548f01409cbd819176cb79e9e1e20000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000b00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000360c6ebe', - maxFeePerGas: '0x5c8520e5a', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x204', - r: '0xce97b3a6b4fb2bda791367c6566290d8ee38a5d39625ec5260cfb21eb3dbe73f', - s: '0x2f50aeaced4b502f667f2ca74d6e929a0b4be6350f4090a4364d58c8281a0514', - to: '0x4faab2f1851b58c26028ab7ba2873ff3c7b52d4c', - transactionIndex: '0x9a', - type: '0x2', v: '0x1', - value: '0x0', + r: '0xc87a6ab948b8ace6a25f82d990842f2f61809bb91c6987c90f501ff5301e0837', + s: '0x7674ab28b68906d91c7a81b738413041b63615c7bf7736a0d55745a3d954416d', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x4960a0a36bd3623b221d818131f00aedde96c1a7', + gas: '0x5208', + gasPrice: '0x246b849b6', + maxFeePerGas: '0x33159ab95', + maxPriorityFeePerGas: '0x665e7b93', + hash: '0x6679fafdcad99aa47f89b5c9622bce3607b554f361c930c243ef9f7c730896b0', + input: '0x', + nonce: '0x1', + to: '0x13bbdfb8576fc2dd1e3b6a7581e72674645931ca', + transactionIndex: '0x5c', + value: '0x8e1bc9bf040000', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x98784a6f846289821f3cd18fc053be007b3a3a82', - gas: '0x2b75b', - gasPrice: '0x47a3d0284', - hash: '0xa335d36a424727d3d6a533abd8c1d55c1647272140e20590852266f66bb21055', - input: '0x000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014ad425897c0000000000000000000000000001faeffe0ef6020ce181e6ff14f3824cc114020cd000000000000000000000000004c00500000ad104d7dbd00e3ae0a5c00560c00000000000000000000000000dcb1cdfe2b5f592e7bdc2696b7a68c6e866c4cc200000000000000000000000000000000000000000000000000000000000009fb000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064361c2b00000000000000000000000000000000000000000000000000000000645da92b0000000000000000000000000000000000000000000000000000000000000000360c6ebe0000000000000000000000000000000000000000675eb253775aa98d0000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f00000000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f00000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000886c98b760000000000000000000000000000000a26b00c1f0df003000390027140000faa71900000000000000000000000000000000000000000000000000001b48eb57e000000000000000000000000000531a0dd30906366fa738acc2d48e790de54bd33e000000000000000000000000000000000000000000000000000000000000004022815c7a06981c9c774bab95b640d57b0f7e7501cdaf5c0e579c52d79385b8dd7221abb8312af27d27e6951cb7cd5177ee7eee435c77398d532f1db2f6acf0d400000000360c6ebe', - maxFeePerGas: '0x6807f15a2', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0xbb', - r: '0x49c82cf38ce3a5299818ea25b4e6ecddaf08763b39dc9c280625ee6ef154321c', - s: '0x0de8fb753fbdffec681cc6803a71f93783a6a1a8f2189870e70db2e6cfe30559', - to: '0x00000000000001ad428e4906ae43d8f9852d0dd6', - transactionIndex: '0x9b', - type: '0x2', - v: '0x1', - value: '0x1550f7dca70000', + v: '0x0', + r: '0x46fcfbc0863d33ac0a2edac2d87211eeb7b792aceae3fbe1ed1bde2cee06f39a', + s: '0x60e105bffdbf95a3ba07a0093c57cc7f98865798f852f231c11a9ac908a4566d', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xf626e9a2fddbf55b0b1a87c56128a7ba6723a85a', + gas: '0x13d7c', + gasPrice: '0x246b849b6', + maxFeePerGas: '0x2f7e80093', + maxPriorityFeePerGas: '0x665e7b93', + hash: '0xaa09171d7192b3e2c15448473df9303fdfbb2924ffac97b1622cbcc244bc611d', + input: '0x095ea7b300000000000000000000000019b5cc75846bf6286d599ec116536a333c4c2c140000000000000000000000000000000000000000000000000175c9f1c96e258c', + nonce: '0x1e1', + to: '0xd5f7838f5c461feff7fe49ea5ebaf7728bb0adfa', + transactionIndex: '0x5d', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x77964f036e1b7bf6d06e0948146f10653891b4ca', - gas: '0x42c19', - gasPrice: '0x47a3d0284', - hash: '0xab5f09775f84c67c0105a2a0708a0d8e0944f6104357944074efc7e0933fbcf3', - input: '0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000643645c700000000000000000000000000000000000000000000000000000000000000020b080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000dbd2fc137a30000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000dbd2fc137a3000000000000000000000000000000000000000000000000035be3ef062482df432200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000054b8d105aa09342fad6b352d41a0bad3e1a9aa9d', - maxFeePerGas: '0x5c8520e5a', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x0', - r: '0x4e8f50c8c6a483fb296f7c10525d1ae2ccf45cd1156cc6c4a04931fbf89adfc3', - s: '0x4ad31852b9fc33f8cdd02ac393de63af02542aba2dbf1cc80c5d410c26594356', - to: '0xef1c6e67703c7bd7107eed8303fbe6ec2554bf6b', - transactionIndex: '0x9c', - type: '0x2', - v: '0x0', - value: '0xdbd2fc137a30000', + v: '0x1', + r: '0x99510ec1906100e28aeb0e9b4b63ec7003c3e2301f159f4a886d03094f3c6dd0', + s: '0x4e4136a77e44d754bfb9114262cd01b2497f7908e8f26ec6954da6e3c25d5ddd', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x439073d7825011f0d581c77cffd8c1bfda85f8e7', + gas: '0x50739', + gasPrice: '0x246b849b6', + maxFeePerGas: '0x33159ab95', + maxPriorityFeePerGas: '0x665e7b93', + hash: '0xec4b17733c6b209ffc7c1a0cf52a81b58c0ced7fa7dd9a517f333c31b43b4737', + input: '0x8d03f456000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000003200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002d5db43e43c1bd0000000000000000000000000000000000000000000000000000000066ff1a1a000000000000000000000000000000000000000000000000002d5db43e43c1bd0000000000000000000000000000000000000000000000000000000066ff1a1a000000000000000000000000b8901acb165ed027e32754e0ffe830802919727f000000000000000000000000710bda329b2a6224e4b44833de30f38e7f81d564000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002641be2221fde6c2d66803a5918e01e47785ecc3517009ac45efbb6e0d2819a20000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000439073d7825011f0d581c77cffd8c1bfda85f8e7000000000000000000000000000000000000000000000000002daa8510c2bfa70000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003686f700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a676e6f7369732d7061790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000c02ffcdd914dba646704439c6090babad521d04c000000000000000000000000c02ffcdd914dba646704439c6090babad521d04c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002dae00806a9f0e00000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000006474ef98d90000000000000000000000000000000000000000000000000000037b6fa7df670000000000000000000000000000000000000000000000000000000000000064000000000000000000000000439073d7825011f0d581c77cffd8c1bfda85f8e700000000000000000000000000000000000000000000000000000000', + nonce: '0x2b', + to: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + transactionIndex: '0x5e', + value: '0x2dae00806a9f0e', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x05c250120ce07ba6fe361b39ac344148435c25ca', - gas: '0x286ea', - gasPrice: '0x47a3d0284', - hash: '0xfc344b84da81960aa983cbeed2a393d9b1fa7aabb0d844e6f82a5f6c94a3c086', - input: '0x357a150b0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000004800000000000000000000000000000000000000000000000000003d3f39a68d44300000000000000000000000000000000000000000000000000000000643669090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005c250120ce07ba6fe361b39ac344148435c25ca0000000000000000000000000000000000000000000000000000000000000000614b494a645ca1534a5d114f720c85e71c2931a1b0be75fc36875b9bc272c4172042345e6d1af8c10e6a2ba3e9a842015bc766d23af0abfcad29d4394e1b0c54000000000000000000000000000000000000000000000000000000000000001b0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000133ac9b351b069cf4fbac6240ae74b9a000000000000000000000000c92b2d2dfd0083aaa38ff07d543e2b3a937edcd400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000645dcb24000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001c0d9ebc70c37844d0f729f054bdad42e09782252866dbf15f847bb31818da7a317128963519528264e89d394d6bd813ecf9ef501e92c5f3c547618a50768bb436d000000000000000000000000000000000000000000000000000000000000001b0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000d71b0fe0a28e00000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000ed5af388653567af2f388e6224dc7c4b3241c544000000000000000000000000000000000000000000000000000000000000090300000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d71b0fe0a28e000078d1f73e7e9d57b89b236154f0d04434bb5c8e241111656c94dd04f9b3721b35000000000000000000000000f849de01b080adc3a814fabe1e2087475cf2e3540000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x6807f15a2', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x39e', - r: '0xe77bef1808fb6fe5657d92b672e75390856cab77a4e3bb6fc8e5651d262f077e', - s: '0x303f114a56069f8248e68b97a1f567f06c8329658413e66d6a1eca8f331fae29', - to: '0x74312363e45dcaba76c59ec49a7aa8a65a67eed3', - transactionIndex: '0x9d', - type: '0x2', v: '0x0', - value: '0xd71b0fe0a28e0000', + r: '0xdb7f269208a89c9bbfff65b016133759c68623050e7ccfaafef073f95513476c', + s: '0x21199adc0437ac3710b5ce327f39706b9c977aa0426ece4e4877a6bc16fc72a2', }, { - accessList: [ - { - address: '0xca37a2f2d84867dcaa7f6ef07dc06ae3e7fc06a4', - storageKeys: [ - '0x0000000000000000000000000000000000000000000000000000000000000000', - ], - }, - { - address: '0x498c00e1ccc2afff80f6cc6144eaeb95c46cc3b5', - storageKeys: [ - '0x0000000000000000000000000000000000000000000000000000000000000008', - ], - }, - ], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x1cac7a07e8cb87b73d94747028845638d55d3fde', - gas: '0x29b6c', - gasPrice: '0x47a3d0284', - hash: '0xe64be15aecd91f995ace79f4019a9527a8abe979a3468b35600da437a1478c70', - input: '0x8119c065001300010000000000000000000000000000000000000040fdaee81f16de231d5f18ea482ad5cc6bc65803817c99f477043dce850001000100000000000f1b30ca37a2f2d84867dcaa7f6ef07dc06ae3e7fc06a40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20100040000000000000f3688498c00e1ccc2afff80f6cc6144eaeb95c46cc3b50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x6807f15a2', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x221f', - r: '0xf8b669d3e358375cf0dd8d88497bdf4769b2ce9897468657d91a96b884bdec63', - s: '0x36236400a44bf6bd812afefa5deaf53450bd3597e57932c019a7e831ac05e224', - to: '0xd6fca65266adac7a35d679ad53dd3aea1f94b95f', - transactionIndex: '0x9e', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x933611322bacc3ac6a77f268f76932a423496b64', + gas: '0x5208', + gasPrice: '0x246b849b6', + maxFeePerGas: '0x2f7e80093', + maxPriorityFeePerGas: '0x665e7b93', + hash: '0xac268b9788cf5573d20613aa95055d753ec4aeac18dff58cec30becba94c20a7', + input: '0x', + nonce: '0x1', + to: '0x8b24a194ffc049069469dfd0574026591b3a0624', + transactionIndex: '0x5f', + value: '0x4d6eb08d6a0f1d60', type: '0x2', - v: '0x1', - value: '0x0', - }, - { accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0xd17fb9fb5a0f3f4f3e6e921ba6029bd267e32bab', - gas: '0x748c9', - gasPrice: '0x47a3d0284', - hash: '0x004a9a2ab277e27f7004aa54b28981e62cdc495d3186fb06e158e8424cf5967c', - input: '0x883164560000000000000000000000005f18ea482ad5cc6bc65803817c99f477043dce85000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000000000000002710fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea6b0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffebee800000000000000000000000000000000000000000000021e19e0c9bab23ffff6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000021e19e0c9bab23ffff60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d17fb9fb5a0f3f4f3e6e921ba6029bd267e32bab00000000000000000000000000000000000000000000000000000000643645df', - maxFeePerGas: '0x6807f15a2', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x48', - r: '0x43e933dbf91ec15bc5918ae2859f34eea3377a27c6c9ae4b03fe54e7d8e68970', - s: '0x57de9c8cefd00fabf794f6902d9b3fa572e4ef7d89bb963476893cd2a0fb475b', - to: '0xc36442b4a4522e871399cd717abdd847ab11fe88', - transactionIndex: '0x9f', - type: '0x2', v: '0x1', - value: '0x0', + r: '0xb3bb29e958ca5ab237b3256d3d75978bf7ce29de755aea19fb751a85ab638d22', + s: '0x66825c9a8f8097270de86766d29ed5c39cbd99b6440aa3448a772f491a69b751', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x4e2d8c65ab9fa2c793c32dceacb83e97f3736de1', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x49a36555b1670f9230f360679e814a5184315808', gas: '0x5208', - gasPrice: '0x47a3d0284', - hash: '0x684e32bbc27f76e759dc9f785c98be14d26f6e1010ef75cc025c70945f530fce', + gasPrice: '0x246b849b6', + maxFeePerGas: '0x33159ab95', + maxPriorityFeePerGas: '0x665e7b93', + hash: '0xf13b4b6ccaa0dc5f5a0b6222ffc2e8828bf76c1322f5ea7edb2f9f1f11e2a8d4', input: '0x', - maxFeePerGas: '0x55ae82600', - maxPriorityFeePerGas: '0x5f5e100', nonce: '0x1d', - r: '0x77f429777d123871ff3684cd1270b395776660622b5418337126c8b25e252e6b', - s: '0x313052affd142ecc6d29050bea16d93f419c6f03f42a2bf36d05c770b43bab4b', - to: '0xa456dbd1bedee6467ef103fc58b079b0f790335d', - transactionIndex: '0xa0', + to: '0x515b95f2bf43779301c2300eaee8b5f1900ac8d0', + transactionIndex: '0x60', + value: '0x2c68af0bb140000', type: '0x2', - v: '0x0', - value: '0x4e0ee6386378e9', + accessList: [], + chainId: '0x1', + v: '0x1', + r: '0xf6375fa058f624e7bc17d0c7a47b889380654904f7dfa0ad5314b701d9966dc0', + s: '0x7a66c95751dd8ef2a1ff7655698365e5e52d78fcd11d6459397162e0161c27a7', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x2b285ae12a85afbd34ff5eca2b93e976b8183b03', + gas: '0x2439f', + gasPrice: '0x2422a4100', + maxFeePerGas: '0x2422a4100', + maxPriorityFeePerGas: '0x665e7b93', + hash: '0x2eaca14d3b8767f53e804fe1df66462b1d019fc14aef1e9d332fc3f1b6281d15', + input: '0x2e7ba6ef00000000000000000000000000000000000000000000000000000000000063ff0000000000000000000000002b285ae12a85afbd34ff5eca2b93e976b8183b030000000000000000000000000000000000000000000000013363054c287323c8000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000118aa75018c1e1bfd6411890c07e1753628cf5b9e737e54e2b1ef26133f132a2712804d0ddc0b2431a01d6380dba38924003e38734282e8e8aac5fa246ef45fdb25caed1f2b60638348f81d0c2a0a4909e2045fdaf121689082a116714d50e0a5d972d3aab79afa18d6b1633acd847ce601995bba5d39105ae3c1d8923d7cd0ecf01fe2c7e769ae5fad4f7cf9c47f80603e420bf5b1210734f64c08a9b625c6034c12d70403a9a7857c860cce880cee67ffaa1ed3936395552b341b9182aad2a09e8129da018a72a51c64f43388524467b692bcea741a315f958ec4c330368b7892900f76e5fd6456ac302ff764e534e2686bf6cd8ad7b8ac564622fa50e3e54b5b86cf08a2fd600590666009df03340c8b5ae6206007ac2fe5cc59341a93a25773dfba81d4cf138ba21b043ce1f26e454e21c89e6c3de4a372dc252c42cab0edef7b517f777c1d93cec3761979cb5622ee30c4781e6ff99579a1fd7fde43c323b06469c5cae75324e20be2541ab3e697d41ae76cbee63944d17942f428ffd36d87fe54f1a7ad175d1358c482702fda8a161e716e49e8b4c11f0013a827fad38e9c127fdf48f8b9a85a9ca67d768ec9308ef451081b37b77ff2d00549d3ad3f34a2585444efd30c73c7dd699f5efcb45e17f908c16289f71b596fc22bec812e99dd2d8e0cc69cb80ea1b74c13db4a2c930a4f49f20aa66115b8cd89cbaa5dd8fc74a93cb39f92cd0effd10166e9f44bafd2475983f34dc954d2cff1c812f61b24a', + nonce: '0x17', + to: '0xbd456973dfd5b00b07ce5307110c77e3f228ca3c', + transactionIndex: '0x61', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x91cfe6dbb2b98ce6fb549cb3334a90dd3a69e584', - gas: '0x14079', - gasPrice: '0x47a3d0284', - hash: '0xddc2aba98e71ea83790e0d5cbab037f6e70bf5a58d9790364cab6f4d852ae897', - input: '0xa9059cbb00000000000000000000000008f918c66d54f4c51f9a76cb9a956faab2d49abe000000000000000000000000000000000000000000000009cc9419a32267574d', - maxFeePerGas: '0x5c8520e5a', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x3f', - r: '0x744a97f9d54ffe6b867fb382b4f0aa3424b65d7681d6c21d9e5357686a5c18f3', - s: '0x44a8ee67be7916293e2e9aa0c739741026bb4d3f8a4b902258548e99b2b14f21', - to: '0xf063fe1ab7a291c5d06a86e14730b00bf24cb589', - transactionIndex: '0xa1', - type: '0x2', v: '0x0', - value: '0x0', + r: '0xfd454f63b5ae89e131b172f68cf52802c9d4912f2f9e1d5b33ca5c521173cc3e', + s: '0x57adf72bdb7f91b07fdc906cdd2ec6a4cad43c811b41e5aa30b691e094ae1379', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0xc50ab42130bc706b7d191451a7ef34ad3eec2a16', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x384c68e6f43c9ab0f888921203a227f6ddb82cba', gas: '0x5208', - gasPrice: '0x47a3d0284', - hash: '0x2fe22d7a6493b92654f01e5ded1cb917c5c2924a38e663128046a7952a2c93ec', + gasPrice: '0x239c1fd23', + maxFeePerGas: '0x312c206e4', + maxPriorityFeePerGas: '0x59682f00', + hash: '0x2ee7746a27c3534a9f1e8c3e0c82c3586912802972541b282c6d690fc2c6148b', input: '0x', - maxFeePerGas: '0x6807f15a2', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x19b5', - r: '0x83d760f376a400bb79c0f72c49d735ded55eaf3052823d309f46b823001d12fd', - s: '0x58744ee0289fafd6b66b7284defc673650cd37b56802b96a6ed786140fa504a2', - to: '0x8fe4243374d944921e7e2409763b558e217c7467', - transactionIndex: '0xa2', + nonce: '0x1e3', + to: '0xb0999731f7c2581844658a9d2ced1be0077b7397', + transactionIndex: '0x62', + value: '0x2386f26fc10000', type: '0x2', - v: '0x0', - value: '0x1587a89f94ac2000', - }, - { accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0xede7a7548c40cfed7d4449ace8a5803bc0ca15be', + v: '0x1', + r: '0x8023a37e802564f22ffbaeabe9d49e8c45e97dfaeaa3e4e53a281b6bc30dd93f', + s: '0x2662f6abf0d3c883f2cad17f9a69bfac9f3b736935f5d540213913c64aaae40e', + }, + { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x8a9ec2bc9081f9abbf34cd9e93d32d08f585d088', gas: '0x5208', - gasPrice: '0x47a3d0284', - hash: '0x7fcbb7a587ba7d0165a58b5e6e3020988dd4920b318ba340080b1ad762998f0e', + gasPrice: '0x235b43045', + maxFeePerGas: '0x235b43045', + maxPriorityFeePerGas: '0x235b43045', + hash: '0xcfa49a01f1d297950088cbf3edd1553afde08ee4a48c1352928d42e706ce7e60', input: '0x', - maxFeePerGas: '0x5c8520e5a', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0xa1d', - r: '0x9861b090ae2e89e38637a8bad32fe050497210a735651e5289796cb5366f1c15', - s: '0x014545f75104bc56668f7a4ad21417ea7c75f4b38b3592b7701d232177fe231e', - to: '0x73d7385bdd6493e88e348b3b6c0b02bcb77779a4', - transactionIndex: '0xa3', + nonce: '0x5', + to: '0x8013db69276fabe3e276495fcf9c989e3de2feb4', + transactionIndex: '0x63', + value: '0xf70dc2dfed23', type: '0x2', - v: '0x0', - value: '0x7b3c18f3a578000', - }, - { accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0xa99d4976eddb861137802bfd210550fb054ad62f', - gas: '0x1526e', - gasPrice: '0x47a3d0284', - hash: '0x86b6bcf0ceb9b60090994f3dd76788cef71d348ca69fffdab38754815b73e85c', - input: '0xb88d4fde000000000000000000000000a99d4976eddb861137802bfd210550fb054ad62f0000000000000000000000009e027ca9b35b1dad472200c27660545246953c4c0000000000000000000000000000000000000000000000000000000000013abe00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000360c6ebe', - maxFeePerGas: '0x6807f15a2', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0xdb', - r: '0x69a986ebcab6f5c0f19b849353b3de5e576c866e72577d1ed8a92f3358e4b6a8', - s: '0x70d0b38161ae8f4098b59b26d6f3fd613cef0fea5c8b08b33d5cff5fa00de22a', - to: '0x5b1085136a811e55b2bb2ca1ea456ba82126a376', - transactionIndex: '0xa4', - type: '0x2', v: '0x0', - value: '0x0', + r: '0x39e77b0d347cd80d3ba908dceb60f3317b370ba4897f9fc2abac343a62e93a97', + s: '0x798e0b664e281dc0a8b7894de7af444d2440473f07c979c2f443fa5fd7bfe741', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x78a3e8804f97618b5aa5b35f5a0caccc8c91adb0', - gas: '0x49d40', - gasPrice: '0x47a3d0284', - hash: '0x8eadb42b3a03ff3e8523f5830f6c95a3264fb9276317ddbc3e8cc97fc189db1d', - input: '0x6ab49a5b0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000004b2000000000000000000000000000000000000000000000000000000000000071700000000000000000000000000000000000000000000000000000000000007330000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000090c0000000000000000000000000000000000000000000000000000000000000fc10000000000000000000000000000000000000000000000000000000000000fd90000000000000000000000000000000000000000000000000000000000000fd80000000000000000000000000000000000000000000000000000000000000fd70000000000000000000000000000000000000000000000000000000000000fcf0000000000000000000000000000000000000000000000000000000000000fcc0000000000000000000000000000000000000000000000000000000000000fc70000000000000000000000000000000000000000000000000000000000000fda0000000000000000000000000000000000000000000000000000000000000ff20000000000000000000000000000000000000000000000000000000000001165000000000000000000000000000000000000000000000000000000000000123700000000000000000000000000000000000000000000000000000000000012da00000000000000000000000000000000000000000000000000000000000012db00000000000000000000000000000000000000000000000000000000000013ce00000000000000000000000000000000000000000000000000000000000012dc', - maxFeePerGas: '0x6807f15a2', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x5', - r: '0x42b676d851eee42c7402532a95e6bd3c19cb6f97f5372110cfa2caa965d8723b', - s: '0x7106db6691b9bd61e380e5f9b9931e54f94355aa4a93314e1875ecc4059ce445', - to: '0x06f841244907a2c886f1e292ca19bd0c3e20fe4c', - transactionIndex: '0xa5', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x528294d35d2e59389d8a0c8aa529900e191ce312', + gas: '0x5208', + gasPrice: '0x22aa414be', + maxFeePerGas: '0x22aa414be', + maxPriorityFeePerGas: '0x22aa414be', + hash: '0x63d73c66684216c3b390b722c17bb91319fb37f46728af97a52524c68d5cce98', + input: '0x', + nonce: '0x0', + to: '0xdfbd0cd592b4c6c02ca3319eb9b4e8b4c098df76', + transactionIndex: '0x64', + value: '0x51b0f460a0cbe10', type: '0x2', - v: '0x1', - value: '0x0', - }, - { accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x038e2f8244de9561e81eb4504062372aba7b3c4a', - gas: '0x5c176', - gasPrice: '0x47a3d0284', - hash: '0x022ac2d203c97313448c6439f25af381448c5fb250067c96abad48c52ea63b25', - input: '0x893419ca00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000011c37937e08000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000038e2f8244de9561e81eb4504062372aba7b3c4a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000064372cc400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020aa443a4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000008dd05800000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001f40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x62a2ed895', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x11', - r: '0xe913c42b7e398941841f07b7c89b4016000b164e8794f71d66e6caac0493ef4f', - s: '0x7433145cbf40a5b8c40e79c1ec6b78761ca2fa8e00f8c1d288afad0cac8bb795', - to: '0xa9cc6d2b54cade299c5a86d959eeb8efc80df773', - transactionIndex: '0xa6', - type: '0x2', v: '0x1', - value: '0x11c37937e08000', + r: '0x51665a1594e141c2e7bac90a33d7581dd64ec3d79db1f2b45bbc5698bdf1201b', + s: '0x0dbf9036db9be9cb31f83590da99da670e78752dc1ac6d7e3731ca8667c02670', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xc6662eb7fc6042f14903d96609352485879a8a71', + gas: '0x493e0', + gasPrice: '0x21bf49824', + maxFeePerGas: '0x419ad5f7d', + maxPriorityFeePerGas: '0x3b9aca01', + hash: '0xe41808098865c3328b93d3b933b150f628530bb55e3f547b650e21c81d8f6b78', + input: '0x6869', + nonce: '0x3ed', + to: '0x1000000000000000000000000000000000001337', + transactionIndex: '0x65', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0xc39434996553087bc8dd76c55a5ef6b4caaa43da', - gas: '0x122a9', - gasPrice: '0x47a3d0284', - hash: '0xe71bed152a7e265fcdc08eb8f6f5217141c1660c79e0a2315801b48a17de9443', - input: '0xf242432a000000000000000000000000c39434996553087bc8dd76c55a5ef6b4caaa43da00000000000000000000000036ecf53bf3a9023122e8f6d94217cf4f2e32fae02218e854019d3ac7989333470e8cf7bda8b930f30000000000046a0000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000360c6ebe', - maxFeePerGas: '0x6807f15a2', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x1d', - r: '0xbec77779f6740f8b0cc2b3bf3541136da1011d8e6c9823110696501aa6b4ac65', - s: '0x5796326ce663e67c69f9d1da51c610c25e4c28fb254344342333c7402386f268', - to: '0x495f947276749ce646f68ac8c248420045cb7b5e', - transactionIndex: '0xa7', - type: '0x2', v: '0x1', - value: '0x0', + r: '0x595e7815d1daf329990512a26e85edff762ffcb404df8465e35cb574f20000c6', + s: '0x108ca1ad7ca8f73b3fb3722d9de84fbe64470e3ac749f168cf52c5bd2ac55df8', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xcfc0f98f30742b6d880f90155d4ebb885e55ab33', + gas: '0x5208', + gasPrice: '0x21bf49823', + maxFeePerGas: '0x29768abf8', + maxPriorityFeePerGas: '0x3b9aca00', + hash: '0x3a0f37c359e45e99aa5a4eb7f4589f99fc4eaede3dcf92791dea1ccd997a4e28', + input: '0x', + nonce: '0x14abe5', + to: '0x0f0269cfcb8217bca11aa671b8d740cb1023ca1c', + transactionIndex: '0x66', + value: '0x1fe4c524bd3934', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x284861646298b1424f22543adf3cac028ac7af31', - gas: '0x37317', - gasPrice: '0x47a3d0284', - hash: '0xbe2db43eb64a29a1305510cee016accf743960735aed99bb4aeb831956531f5b', - input: '0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000643645df00000000000000000000000000000000000000000000000000000000000000020b080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000027f7d0bdb92000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000027f7d0bdb920000000000000000000000000000000000000000000000000b93d99b22a768d419a300000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006aa40d02115090d40dc33c7c5f3cf05112fa4f83', - maxFeePerGas: '0x62a2ed895', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0xb', - r: '0x17eeaea751accb34ab696825afed4cf5852c84836306c73b89cbc4dcec7f2e6d', - s: '0x040b0bcba55c653c094ed116f2fd453770843b3cdbc6ed861f3a09084cc5149b', - to: '0xef1c6e67703c7bd7107eed8303fbe6ec2554bf6b', - transactionIndex: '0xa8', - type: '0x2', v: '0x0', - value: '0x27f7d0bdb920000', + r: '0xfbaf16f161f85f4ac9d9b0d53f659c0c0a43b586506375f22b61c7cfea0af492', + s: '0x2eaaedb7aa59920a7d30e586c6ad414241e1a6da5986377a3fd2a9642d7896e6', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xab782bc7d4a2b306825de5a7730034f8f63ee1bc', + gas: '0xf33d', + gasPrice: '0x21bf49823', + maxFeePerGas: '0x29768abf8', + maxPriorityFeePerGas: '0x3b9aca00', + hash: '0x090dff6a83c38b80f4c90e126807aafc3df7ef3383e3f762188f1d5c436a2d3e', + input: '0xa9059cbb00000000000000000000000029984d1f9055cafb02dcdd53c54b727902e4497500000000000000000000000000000000000000000000007ff94b2e79b0a60000', + nonce: '0x6717a', + to: '0x6985884c4392d348587b19cb9eaaf157f13271cd', + transactionIndex: '0x67', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x8bd2830aeed8c79ba6bfae868f005618b470429c', - gas: '0x1ab29', - gasPrice: '0x47a3d0284', - hash: '0x80f00d868b70689d383cdab459c9c68f606de18d4d5a4fc25258870e42aa65ae', - input: '0xdeace8f500000000000000000000000000000000000000000000000000000000000000890000000000000000000000008bd2830aeed8c79ba6bfae868f005618b470429c000000000000000000000000000000000000000000000000000000001e19b040000000000000000000000000000000000000000000000000000000001deff18300000000000000000000000000000000000000000000000000000000643f7965000000000000000000000000a6a688f107851131f0e1dce493ebbebfaf99203e0000000000000000000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x62a2ed895', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x15', - r: '0xdbe15946cfad124c7f3dc5d895e874ccd4431168738359cc4346f0b97ee7fb32', - s: '0x1ca6cd3b3433aa8051c582e77fc199c7db72cc5e82380d4eabc5b9afb90c9c70', - to: '0x3666f603cc164936c1b87e207f36beba4ac5f18a', - transactionIndex: '0xa9', - type: '0x2', v: '0x1', - value: '0x0', + r: '0xb0364e363e90434985ec02da131eee546a2824da9f33f6bed499ecf1326fe9cd', + s: '0x7c079a699df6207ea5a50a5c68f962b4b84a97b8fe712e32e8653709830da71a', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x69968ce0e92d9c101bad81de55efbcb69603cfe3', + gas: '0x156da', + gasPrice: '0x21bf49823', + maxFeePerGas: '0x423940eee', + maxPriorityFeePerGas: '0x3b9aca00', + hash: '0x9bbaf55032c96579275fcbd54dd02671ced1ffe1729e2dc6f86904047fe7e86d', + input: '0x9aaab648bea49adb648fa2dee4c409fdb899aa361386f50662a68d1a0dbfa1441e170de7000000000000000000000000000000000000000000000000000000000126a740b257f28d373966bef6251fcaee37dfe7b5f3309f07da0af75bbd7875eea8d01b00000000000000000000000000000000000000000000000000000000013e658e', + nonce: '0x29ea', + to: '0xa38d0c4e6319f9045f20318ba5f04cde94208608', + transactionIndex: '0x68', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x631a717b14ae7de2305b5a3d6051984ffac61707', - gas: '0x2542c', - gasPrice: '0x47a3d0284', - hash: '0x2a69d29b4302deff2515e87041b722bb229603429ea4d31fe81c878efed67f81', - input: '0xb1a1a8820000000000000000000000000000000000000000000000000000000000030d4000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x62a2ed895', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x7e', - r: '0xa992964c4535a1200cfba38f056d0700fadd5c5e0a8e5b0789a260fd3c669aa2', - s: '0x618b195d75a3d2a791d0e4b75040408edd888eab7c165e92ab22fb20a9ad0b59', - to: '0x99c9fc46f92e8a1c0dec1b1747d010903e884be1', - transactionIndex: '0xaa', - type: '0x2', v: '0x0', - value: '0x6a94d74f430000', + r: '0x4794a96292bc9351b6111fe9379a0ca248dadf26c3ace75717109c83ef344eb7', + s: '0x0c2a0a8b19b23488d4f09edcfb2cad557bda57790449ee2bcc83d19bcb6d8665', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x8216874887415e2650d12d53ff53516f04a74fd7', + gas: '0x5208', + gasPrice: '0x21bf49823', + maxFeePerGas: '0x286d095ea', + maxPriorityFeePerGas: '0x3b9aca00', + hash: '0x405dda79e62ca02cde3cc9c61f228585d202e339b187a9cafc7ce78b19e3a3a2', + input: '0x', + nonce: '0x12d281', + to: '0xb5ebc2438a5ae9f480205273755fb024acf905ca', + transactionIndex: '0x69', + value: '0xf79fc7dcd84000', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0xeeaa1e883c352edb52e583f341a7f1067f0bc8b5', - gas: '0x29476', - gasPrice: '0x47a3d0284', - hash: '0x6323bd97a58dab264aaeea1aa12ece39b5eef1a1488e65f813609e1c47fdc66f', - input: '0xa9059cbb000000000000000000000000d2954377b6b13aae5bbcb88c8523ca648c5ad91f0000000000000000000000000000000000000000000000008ac7230489e80000', - maxFeePerGas: '0x5c8520e5a', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x74', - r: '0xe09dc226594df121c0d40a9652e941282a521edb26ed138e3def76954a990141', - s: '0x2f7c710c8d3e3dbf9915a1607e223cb0ba78f27be41f89261f7e3b2d1885b089', - to: '0xba11d00c5f74255f56a5e366f4f77f5a186d7f55', - transactionIndex: '0xab', - type: '0x2', v: '0x0', - value: '0x0', + r: '0x7c181ff56d1e772cfb1d4e7eee036a909174bec19d482cf17b23611baa4ef262', + s: '0x3a9d5e62b183d9472dcc579c53cd555f8b87617ba00ced41905f74dda253d69c', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x974caa59e49682cda0ad2bbe82983419a2ecc400', + gas: '0x5208', + gasPrice: '0x1f40be4b7', + hash: '0xc95603610d088c508fa1e558a69b5b7dce048047681b6aadc0f38bf6b828d2e6', + input: '0x', + nonce: '0x31ecaf', + to: '0x934932e70cd4435ead18e287fe82ac91580720db', + transactionIndex: '0x6a', + value: '0x3e97379b3073e0', + type: '0x0', chainId: '0x1', - from: '0xab954aca1a699b10db15bc027a17c9c57aace3f3', - gas: '0xb1b1d', - gasPrice: '0x47a3d0284', - hash: '0x9ff09456b9098544e68e8e27cd3f1445d8606fdfcdebfa74d24d1bc87a9c2462', - input: '0xac9650d800000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000005200000000000000000000000000000000000000000000000000000000000000224e962172a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000006b175474e89094c44da98b954eedeac495271d0f0000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000128d9627aa400000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000007aad0aad8063df7800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f869584cd00000000000000000000000010000000000000000000000000000000000000110000000000000000000000000000000000000000000000ddb71cddca64363df5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000224e962172a0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000007aad0aad8063df78000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000128d9627aa400000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000007aad0aad8063df7800000000000000000000000000000000000000000000000000000000007fc58f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48869584cd00000000000000000000000010000000000000000000000000000000000000110000000000000000000000000000000000000000000000d4a6ce8f8b64363e52000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000224e962172a000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007fc58f000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000128d9627aa4000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000007fc58f000000000000000000000000000000000000000000000000000f1aeace3dbdf300000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee869584cd000000000000000000000000100000000000000000000000000000000000001100000000000000000000000000000000000000000000003ef84ccf4964363ed600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x5c8520e5a', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x4ea', - r: '0x068326fe3e2ef5f98b8661ac64adc95a38ae966bdeaf3b29f00a82d9ea6d9557', - s: '0x1f6b5b58f58cb4aa7c2491ec73fbbac5bd357d8fd41cb1602f602c9f60083114', - to: '0x5724b5bc7f54a52f4014e5f496ae380f89c881a1', - transactionIndex: '0xac', - type: '0x2', - v: '0x1', - value: '0x11c37937e08000', + v: '0x26', + r: '0x265786547980d36d21687ec2be24afcf6720afa2b02eea989211864505ff79d5', + s: '0x0ee9fcd4ed9ffd0ba1e9e283316bfb9b738c0d257c752070c3c6913b4cbfe4ca', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x63b92f8341dab844c801e0f733911491b256aad8', + gas: '0x5208', + gasPrice: '0x1f40be4b7', + hash: '0xaf3aa64caed406e4f3ef916a73a57b7e0e2422eb0c10901688aee84a8fc43658', + input: '0x', + nonce: '0x56', + to: '0x974caa59e49682cda0ad2bbe82983419a2ecc400', + transactionIndex: '0x6b', + value: '0x3a1499a2d4de3f', + type: '0x0', chainId: '0x1', - from: '0x9f0bc974937f37d61ddf909d4124e9631a6986ea', - gas: '0x2b496', - gasPrice: '0x47a3d0284', - hash: '0x8d7f6f64c5cbdb533b579647746392c50db5fd0247981c7b430f4fe206bad302', - input: '0x6933e79a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000cda72070e455bb31c7690a170224ce43623d0b6f000000000000000000000000000000000000000000000000000000000000003c516d553678534c61556655616e5768554e32325236794459754245657861657278664b7266355844594c4e6371362f6d657461646174612e6a736f6e00000000', - maxFeePerGas: '0x62a2ed895', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x3b', - r: '0x7c1fec91a460221ac132cbe6f3cc850734e3e825f4391fe25313d2447c3a9724', - s: '0x3c1881ef1d6d43dafa41cc91572fe3f4526ff1f19007e85e98d4c6df2c16147a', - to: '0x626eb7f29d179e0e1e9deb97b3e5938a646616c9', - transactionIndex: '0xad', - type: '0x2', - v: '0x0', - value: '0x0', + v: '0x25', + r: '0x9efe6578a56ce9a6452a3b77021ee4389771b1da791e75137597d268cb65c05c', + s: '0x1747f8cea6beaa0544b0f062603d558abc66f07b9a00cff65cc9f0ee6fc37383', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x32b41c5459c5e0bca244a73f5fa80fe52a2d8228', + gas: '0x5208', + gasPrice: '0x1f40be4b7', + hash: '0x161e7067588208d17b7c436b05189dd5a9fc6f03b69a7b986857768139cace0f', + input: '0x', + nonce: '0x7', + to: '0x974caa59e49682cda0ad2bbe82983419a2ecc400', + transactionIndex: '0x6c', + value: '0x3a1bc0d384e2b8', + type: '0x0', chainId: '0x1', - from: '0xce3f52a81d998f37692ac85e6aa26029a3faf24d', - gas: '0x161b3', - gasPrice: '0x47a3d0284', - hash: '0xb94ff102a30dcdcf8c2b1385246a2f205f4a7937b58182b7df04e38dc4fba63a', - input: '0xb88d4fde000000000000000000000000ce3f52a81d998f37692ac85e6aa26029a3faf24d00000000000000000000000095d8bdb4a91f446d4ff00f95d42dd0f1f146a2c8000000000000000000000000000000000000000000000000000000000000010900000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000360c6ebe', - maxFeePerGas: '0x62a2ed895', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x2cf', - r: '0x64fb24029162079701a1163f1957f15aa7bc1160f13450c19d4f7ef69441441b', - s: '0x4856e9bb26f1c490a9866ed11ee160ea127d80861662b5555aff436ecf889180', - to: '0x92c93fafc20fe882a448f86e594d9667259c42c8', - transactionIndex: '0xae', - type: '0x2', - v: '0x1', - value: '0x0', + v: '0x26', + r: '0x0948867092a8558c9cbd23d08665267426ed96d7070df553c369d5590c63735a', + s: '0x34dd39e508bd13a526d7972f021d98b6c1fdc365f516df095742199d4377c7b0', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x58aea486186fb1c6f93d38b9a7916750bd59c1ac', - gas: '0x32529', - gasPrice: '0x47a3d0284', - hash: '0x61ca13084a53b8edfc2beb3d1f967fdfca93359043a5da9c3678889b012ad0f3', - input: '0x21938f7500000000000000000000000000000000000000000000000000a1609b560d93cc00000000000000000000000000000000000000000000000001e7a5fb25a0b80400000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000058aea486186fb1c6f93d38b9a7916750bd59c1ac000000000000000000000000000000000000000000000000000000000000000200000000000000000000000083a48a032a0de0d84e3c01882148364e41f57934000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000000000000000000000000000000000000000000010000000000000000000000001a75f7db182ce7fca969f029e1ef573f7aee9cb5', - maxFeePerGas: '0x6807f15a2', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x15b', - r: '0x90a309abfe52ff76a25c3ab1fc5d38c53eaf9c4f3ef9728c9a88a168dacf365b', - s: '0x3b1af0c97a0f88c6c4800b29549eff3b757b6145074726ad4c20f29efd2b7ff3', - to: '0x8967ba97f39334c9e6f8e34b8a3d7556306af568', - transactionIndex: '0xaf', - type: '0x2', - v: '0x1', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xb457317e9dbc79d2f2bdf373c7cc22f35dc5a104', + gas: '0x33450', + gasPrice: '0x1ef188cfe', + hash: '0x15406b7097b2c943bd7cbadbd6655b5f904aae8b487a5498f2df1834f328ee43', + input: '0xa9059cbb000000000000000000000000974caa59e49682cda0ad2bbe82983419a2ecc4000000000000000000000000000000000000000000000000000000000017854406', + nonce: '0x34', + to: '0xdac17f958d2ee523a2206206994597c13d831ec7', + transactionIndex: '0x6d', value: '0x0', + type: '0x0', + chainId: '0x1', + v: '0x25', + r: '0x16d15afa059ece2c0debc47e9e51b927622f97665b0a17c6427617226d59455c', + s: '0x2626a6873806a74bd516715346fc316634f0e746c86ea066beb4409ef00ddb6f', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x2c6fb912d9658100b8686bca700ae855f8e5f2bb', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x1c727a55ea3c11b0ab7d3a361fe0f3c47ce6de5d', gas: '0x5208', - gasPrice: '0x47a3d0284', - hash: '0x76a199229278cdd8e6dd40093b64e7664626618e7c36fd623ab630786b6dfac5', + gasPrice: '0x1ef188cfe', + hash: '0x12ae4dfa36d9e0632ef111787fa87df8d3cf00eb307fef2c29c25eb3f83d2766', input: '0x', - maxFeePerGas: '0x6807f15a2', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x2', - r: '0xbcf5af6296d751ce07bae4d289e54c3c9bdbe0629de6d170bce00f546a24cdbe', - s: '0x7a18cc73b88f984a846a03026e0ba64acf3a0e6d892065cc01a51ccab4a5c76b', - to: '0x86b050c27d689ba91917377de4a39310e79c2b74', - transactionIndex: '0xb0', + nonce: '0xca4a5', + to: '0xb0b965025ae57dbbf16140f6f5255a6b57f92bde', + transactionIndex: '0x6e', + value: '0x136e1738a52be5', + type: '0x0', + chainId: '0x1', + v: '0x25', + r: '0x0a7ff318ac7c01e56b690ab34534206fd8ca4ae57d8a4f06af4740bc953900bd', + s: '0x51709d160f20358e37222fc03c4669a7130572020435aec256433d477a45f7ae', + }, + { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xa009fa1ac416ec02f6f902a3a4a584b092ae6123', + gas: '0xaae60', + gasPrice: '0x1ed77330a', + maxFeePerGas: '0x27fa52780', + maxPriorityFeePerGas: '0xd1d64e7', + hash: '0x8928a5a20d8799547b46a5f9f4417aceab1eec4f3b32368d9c6118d500c24435', + input: '0x000000330000000000000000000000004347983e483ea47099e8cbca160c92599791b76a000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000006442a14b135000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000005e00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000004c0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001000000000000000000000000004449cd34d1eb1fedcf02a1be3834ffde8e6a6180000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000011fba7d70000000000000000000000000000000000000000000000000000000011fba7d700000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000042000000000000000000000000000000011f84b9aa48e5f8aa8b9897600006289be000000000000000000000000183b41eeafe4046cc4cc2bdab9f256e934d180070468323adce339e661f958840ccc14e162b6afb3e7c76b90a9b7cfd28eb314040000000000000000000000000000000000000000000000000000000066fb26c3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000193af80284a440b00000000000000000000000000000000000000000000000001846fcbb83a870b000000000000000000000000183b41eeafe4046cc4cc2bdab9f256e934d180070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000103019aba40540000000000000000000000000000000000000000000000000000f938f8c331bd000000000000000000000000000000fee13a103a10d593b9ae06b3e05f2e7e1c0000000000000000000000000000000000000000000000000000000066fb25ba0000000000000000000000000000000000000000000000000000000066fb25f6000000000000000000000000fbeedcfe378866dab6abbafd8b2986f5c17687370000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000001944a73e11bf19c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041360c0b06d82e52bd58b1dd1b14de9233589ef13968700d00b79c9f226c18989f57daef290a03ee3fbe6db06ec9d11ade35dbb7ca5c7276b9f20397d4fd7a0d751b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000414621b8e716056ea5145508a55c0b51d4fce77f7493091f593164dcc9f0f319a55bab837f1bee62d2abe5fdcb9258a7c29c424fde9c21ccba31ba8bd62724e70a1c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000011fba7d700000000000000000000000000000000000000000000000001954d757bd631f000000000000000000000000000000000000000000000000000000000', + nonce: '0x48cb8', + to: '0xfbeedcfe378866dab6abbafd8b2986f5c1768737', + transactionIndex: '0x6f', + value: '0x0', type: '0x2', - v: '0x0', - value: '0x1d1f2a3bd7d7020', + accessList: [], + chainId: '0x1', + v: '0x1', + r: '0xe68e9828965a89e7b7c90845768f68aebe7664b960d0c7a12bdf9b82bfb580e7', + s: '0x360d2b8042d6c456628d2cec04272d07c982b026b7e0b8d38fc726cb439093eb', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x05520d064aeecc56614db042f069cc04c09aeb4c', + gas: '0x493e0', + gasPrice: '0x1e64faf24', + maxFeePerGas: '0x3e408767d', + maxPriorityFeePerGas: '0x5f5e101', + hash: '0xc5b949c37ffb3889b6f259170ce0cf5db0b2455e2526dfd051624da15677e331', + input: '0x6869', + nonce: '0x422', + to: '0x1000000000000000000000000000000000001337', + transactionIndex: '0x70', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x9d5efcee1119e47f53a216a6b9289e0e7fb6a2a0', - gas: '0x71af', - gasPrice: '0x47a3d0284', - hash: '0x74d69e566e8bd62900e891081905009a1c2ed074165d15c0e0a096b63b1b49a7', - input: '0x095ea7b300000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc450000000000000000000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x62a2ed895', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x4', - r: '0x2b8aa171ca6a259fa65f52c397cc13c5a9fbd2b295402251139ae33a3a28fd24', - s: '0x3bdf546fa3d5a7c07869a23c90539137322d30cd1ac6614d8566386629b4afa7', - to: '0xcfcffe432a48db53f59c301422d2edd77b2a88d7', - transactionIndex: '0xb1', - type: '0x2', v: '0x0', - value: '0x0', + r: '0xce96545375725cd715b7dfae561f4cfc68f727c3c8c88fd520b0e1369d1a8bb8', + s: '0x42cb40650ed2554994b734dc6387e45b458251bb4def6087431a8f2da5dbe87e', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x6781debd2bcaeed5905deb2582fd1507a6af82db', + gas: '0x14c39', + gasPrice: '0x1e4676723', + maxFeePerGas: '0x24eae9980', + maxPriorityFeePerGas: '0x40d9900', + hash: '0x1c35fe8540ddb3a80d0726f17dee3938ec63004081c0dbb0de543e5347824f29', + input: '0xa9059cbb00000000000000000000000005d28b833ddeb5641a241ebd7ee46f2042fd48b5000000000000000000000000000000000000000000000000000163f381eacf5d', + nonce: '0x2', + to: '0x6de73ced5dd4c33235f9f4bf5de47b5d33c6392a', + transactionIndex: '0x71', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x79fd0a95523b4287b5717d02e256c3861f68f9d7', - gas: '0x38690', - gasPrice: '0x47a3d0284', - hash: '0x14036d43579058171105216738457b35167820a7effb8d9386c65e20d236eb77', - input: '0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000064363f7f00000000000000000000000000000000000000000000000000000000000000020b080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000019adace86241a0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000019adace86241a00000000000000000000000000000000000000000000000000021ad6b9519056cb00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000f1e029ae5743fd4a324132a0be6eeebc81060f55', - maxFeePerGas: '0x6807f15a2', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x28', - r: '0xd4238279c5197a8e85d0bf2f68f7b73fcd25002e5d8b692dc6a7b53521bdf075', - s: '0x7ed6c80b5bbda6257d52f9b74989880865942dcd324f30f8defc231b1ee5cc2c', - to: '0xef1c6e67703c7bd7107eed8303fbe6ec2554bf6b', - transactionIndex: '0xb2', - type: '0x2', v: '0x0', - value: '0x19adace86241a00', + r: '0xce6d46e138a6597282653ca73501ddc5a015e94488d56b8233fe76d9e6198166', + s: '0x06bce35c1ce38c90c791ea4826aa140e470f374ef8c712453be7a0112078c048', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x9d31bb77a9bfd236e2734fbb77903b8e9ea5ddf5', + gas: '0x102c4', + gasPrice: '0x1e393e6d9', + maxFeePerGas: '0x2f4a26884', + maxPriorityFeePerGas: '0x33a18b6', + hash: '0xb390e14e9ced4f0e55565e64c92cc0733fcdf493d7a5607c20cb2dfaa598d38a', + input: '0xa9059cbb0000000000000000000000004b39caf4640d01bb873ab61d3e893058340e028e00000000000000000000000000000000000000000000000000000000060c9d50', + nonce: '0xec', + to: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', + transactionIndex: '0x72', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x9680f3957510cf85751a096c2194520c36a4a003', - gas: '0x3f787', - gasPrice: '0x47a3d0284', - hash: '0x25c1684f6966caff802e85749b550d9be2934820d5c91c6f62487287675a629e', - input: '0x9b6528e2000000000000000000000000e23cedadbba887bf6bbb6f161ff9281f6c39b5eb', - maxFeePerGas: '0x6807f15a2', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x530', - r: '0xaf5eac6b32b9d2d8c4b0273bffa0f32b180c4beed468f92379d56ad407d58138', - s: '0x620e4931e4c0cd991109e04f223ee4f3fbcf5630fc4945d418dfe9ed3a9561a1', - to: '0x9c4c49c3c3bd7ab49d91576d0103a25514cad1d6', - transactionIndex: '0xb3', - type: '0x2', v: '0x1', - value: '0x0', + r: '0xa0c854a383ec9df926bf3feadb302dec04c89654d9c6f1f0becef05c9d690368', + s: '0x6485d6938a7efcf55892e178d3edccbccb8135f24c8fcec1353050693614415f', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xd60bcf7c621816d689dc6b76bc0c2b8d7f8b2cb5', + gas: '0x60d43', + gasPrice: '0x1e354bea3', + maxFeePerGas: '0x1faa3b500', + maxPriorityFeePerGas: '0x2faf080', + hash: '0xe3b84037c08bb7c5ac3954825d85d124c41d1fceb3792877a3afbde0cc6014c1', + input: '0x334043960000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000d60bcf7c621816d689dc6b76bc0c2b8d7f8b2cb50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d60bcf7c621816d689dc6b76bc0c2b8d7f8b2cb5000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000013da0af00000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000acb55c530acdb2849e6d4f36992cd8c9d50ed8f700000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000062e449b6987b6ef95000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000ec53bf9167f50cdeb3ae105f56099aaab9061f830000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001', + nonce: '0x68', + to: '0x39053d51b77dc0d36036fc1fcc8cb819df8ef37a', + transactionIndex: '0x73', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0xadb7c1e5cdb6e92d816b4a86f25f9da5baea95d9', + v: '0x1', + r: '0x9aaee5a6adf2c0019188717b64ab30036dc6e3887ce35549274e6d308912be8f', + s: '0x4556f30356f5b7e6fb031e0a200ab5cb4d0cc0b325a8a5a0db62f9f973ae0a41', + }, + { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x1ab8744a3008cf89ae4e6d08388458ac38bb3b18', gas: '0x5208', - gasPrice: '0x47a3d0284', - hash: '0x9c00826fd016714e191a685e31c918e5f9151d807d1b5b955a3ea514ffcd19de', + gasPrice: '0x1e354bea3', + maxFeePerGas: '0x1f4add400', + maxPriorityFeePerGas: '0x2faf080', + hash: '0x82bd69e948636e2e219d14a8b0a70a065c0cecf2c73f1376bd89b03ed4ae6eca', input: '0x', - maxFeePerGas: '0x62a2ed895', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x2', - r: '0x7fc9b2ff15c31daa91ea1875de068e4e12a7a7e86a4ad0f281c3f3b2c3c8f2c5', - s: '0x1650b4c74cd44f7e317837bc36c7b3652312adf404835f60053ed18bddd70af5', - to: '0xabf7d7b1a434b684541aea4d6bf2e65b57b1aadf', - transactionIndex: '0xb4', + nonce: '0x6', + to: '0x45a946acf08b6c79ef563882f2946e72c8dc2304', + transactionIndex: '0x74', + value: '0x2d4c0eb4e2e0000', type: '0x2', + accessList: [], + chainId: '0x1', v: '0x0', - value: '0xe35fa931a0000', + r: '0x2c48236c69ac4561b733c966487fc7db730ee976912a3166fd37be54848a671b', + s: '0x3ea3ba77394d1e3971bd49eaefdfbd8077549b95bba1ca52e3923b1dfe5f68ab', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xb556575e8c28bab34d1dae7735b78111ec46936d', + gas: '0x22898', + gasPrice: '0x1e354bea3', + maxFeePerGas: '0x1f4add400', + maxPriorityFeePerGas: '0x2faf080', + hash: '0x3387d9f901d54e22f0945d44f625747336f7973bdc971c64f65ff2c9d6d68ef5', + input: '0x2e7ba6ef0000000000000000000000000000000000000000000000000000000000002f87000000000000000000000000b556575e8c28bab34d1dae7735b78111ec46936d000000000000000000000000000000000000000000000002b5c3db52c04c3dc4000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000112c44074a23e61e229f0cb3fdc922b3e1cdca00d8f812ebb3e78ba4dd3071ae951d9d54b87a6a3b82828acd1bf3a6bac7fba4740c7657a490bd753a9654f57185fab91d260a91c840aebb1350aa1d235679697ff9bd7e9669921fb3436152545df80a981b5ae3da3ab8bd0163c9182134647028dfc238f3a2b7ffa4d3849e8e72917588f646ecccfada4bfdf9152774757d83bf4d22cac9bf9a0dbfed162ea57beef7dc48f67d8172779fb63247fd18aa73f7f36dcc2ca38559081db24903d917202ab79bf5c15198f22ecbb25def50382ee33e0e8645fcfca7a87de31e5844533bf94e27f68da4ed7f03347dadcdf87b9c55533e7187efdab202c70681808947d945dbf033adeb2c45088140a118850a23faa240c1ea1723b7c0d8ac73540267fd6b71966d0e7815b3613bcd61a1e7b5e4fc5fbb00ac3258d8b52cc7752ef55434994e96490ee92ef349925aea30846d3a167ec5c2252faa60183e0a6fb94c6cfc29667d0aa1742a76f12e8374839251724f6e3e0570a93e96916d669fe97c78ed35839e22af7a6aed5857dc926da0ec867a1364995f28e47d06975ea19f38e6287336071316c9fce07360813b98a5ba81d860e4534e3860147ae00479f61102798cf223e025ca87efe70f15d1021b868f55ca33aad808718d9815c98a6f38a4e0569e4d9ddf8f5f95dd5458d985a600a9242e4a63b87e94a1abbcb5b313a2972ebc888bc57c97dc237811bf1efa6dd3deeb816e1d58c78eb04e84eb95fd7d8f', + nonce: '0x6b', + to: '0x2ec90ef34e312a855becf74762d198d8369eece1', + transactionIndex: '0x75', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x75a50269c66e6ba81c5062fc84ef199e86a317dc', - gas: '0x2d10d', - gasPrice: '0x47a3d0284', - hash: '0xe04b3af4d15e1edcae6e981f5f1d9d75af4f7cd06f12c73ee42e51c00ef14364', - input: '0xbaa2abde0000000000000000000000009992ec3cf6a55b00978cddf2b27bc6882d88d1ec000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7000000000000000000000000000000000000000000000000000000df31a0928400000000000000000000000000000000000000000000002f38c2775b77862166000000000000000000000000000000000000000000000000000000000b03b76400000000000000000000000075a50269c66e6ba81c5062fc84ef199e86a317dc00000000000000000000000000000000000000000000000000000000643645f0', - maxFeePerGas: '0x62a2ed895', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x50', - r: '0x9bf9c27d293970699ecccca63a6e691fe6be4095e348bd7c06df516a609471be', - s: '0x09113c049db4b93fd9129b188fe3980727b1f16ff32353e2dea5ac40b63d3ffa', - to: '0x9a5132e149c547f254c73226da7f770d43d9ea44', - transactionIndex: '0xb5', - type: '0x2', - v: '0x1', - value: '0x0', + v: '0x0', + r: '0x26cf1f7cc5eeec7def6bac91a3b13e2d9449ffec94fc79f5b79d60c8f7151798', + s: '0x308276dd9474669fc4482548418b4aff083e31e86a3f425db7039e5de1ce38d7', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0xa4fe7d359d5e8a9d5ac0265b9d468b289438aff5', + gas: '0x493e0', + gasPrice: '0x1e0f264a4', + maxFeePerGas: '0x3deab2bfd', + maxPriorityFeePerGas: '0x989681', + hash: '0xdb41e036f0976e7f654af6bd32dbb55f1cb104cb3fa3e7d8d629bbf9194822ea', + input: '0x6869', + nonce: '0x402', + to: '0x1000000000000000000000000000000000001337', + transactionIndex: '0x76', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0xb84688d617ce18b7f8865b6417cd771d0d42e509', - gas: '0x27c06', - gasPrice: '0x47a3d0284', - hash: '0x0357d246c9ddd57f05170a038ddb04c4c2554371a5cd1e1d7bdda50b6080939f', - input: '0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000643645d300000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000046ebe6d0000000000000000000000000000000000000000000000000000001702dca3b100000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002ba0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000bb82b591e99afe9f32eaa6214f7b7629768c40eeb39000000000000000000000000000000000000000000', - maxFeePerGas: '0x4a817c800', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0xd', - r: '0xe7393a07e07f04a9b43a841014852cd12ebc1079a4290276e67b7c01bd38a4b1', - s: '0x2e74e7c66a3f46e2ce31018771b811d16c1544fb3df6664588420111ee36fcad', - to: '0xef1c6e67703c7bd7107eed8303fbe6ec2554bf6b', - transactionIndex: '0xb6', - type: '0x2', v: '0x1', - value: '0x0', + r: '0x16f6de69390b98d8611882525376be455fbf43387f77f12a6fd5df375519d39c', + s: '0x636a8c8bbac2208b2d906a96f71e4d8583388a221209f2854e3ef8d5ad020645', }, { + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: '0x13e6595', + from: '0x95222290dd7278aa3ddd389cc1e1d165cc4bafe5', + gas: '0xb376', + gasPrice: '0x1e059ce23', + maxFeePerGas: '0x1e059ce23', + maxPriorityFeePerGas: '0x0', + hash: '0x81bf92f05529a802bfcfbe3e2b8faf7ecf8e7334dce01cf8eeeb92271be5e828', + input: '0x', + nonce: '0x166fbb', + to: '0xdd2a0e78da596bf380e899ca7c89b39857122ae6', + transactionIndex: '0x77', + value: '0xa3bbf38e7ab3f4', + type: '0x2', accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', chainId: '0x1', - from: '0x5405161f081f773c4bf97a2f086d358ebc643b3e', - gas: '0xbec5', - gasPrice: '0x47a3d0284', - hash: '0x002ec16d799ba0c7c3251ba82a68151016066f4c49ea22c6441711184aff4799', - input: '0x095ea7b3000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3000000000000000000000000000000000000000000000000000000001661ace0', - maxFeePerGas: '0x5c2f99757', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x19', - r: '0x51e49b423093e8f7d580d349423b5a6ff02b8677999d96c60a106b9f155cd571', - s: '0x7556ea05a4035a9863f0758c2a9ded646edaf9a76e2a7810dc7b276421288ee9', - to: '0xdac17f958d2ee523a2206206994597c13d831ec7', - transactionIndex: '0xb7', - type: '0x2', v: '0x1', - value: '0x0', + r: '0x3962657266fc33f863ec81edccec8e692f00c5c10d45e8fc8ca2347a81be70ab', + s: '0x1039fbd1be62f4c7ad00aac0ff8d425c1a69db805754c2e15161aeeb32678787', }, + ], + transactionsRoot: '0xfd003b6a8672be4629cb504525088d8e9c864716ca0f1ccc4f6179971c82df6c', + uncles: [], + withdrawals: [ { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0xc44fd102415ff62769a4e37c70dea27033a5291f', - gas: '0x493e0', - gasPrice: '0x47a3d0284', - hash: '0x2393a72f9b086878d13a8dae1e44607cb9033fd94d4777ea907dc457db3dbc44', - input: '0xe8eda9df000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000005d20728484000000000000000000000000c44fd102415ff62769a4e37c70dea27033a5291f0000000000000000000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x62a2ed895', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x579', - r: '0xe9eeed92f4dd20c08048f7a1ab85d4a998cfe54fbc4f8b1ecf3d152a4ec87648', - s: '0x3e9e7796691c23617522a914b7d00375fe239d7e006a107906bd576c1eb0feb6', - to: '0x7d2768de32b0b80b7a3454c06bdac94a69ddc7a9', - transactionIndex: '0xb8', - type: '0x2', - v: '0x0', - value: '0x0', + index: '0x3a76c3b', + validatorIndex: '0xc9c3c', + address: '0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f', + amount: '0x124beab', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0xf3b9b75178f29d551a9c7fa4ef53840871ea662d', - gas: '0x6210d', - gasPrice: '0x47a3d0284', - hash: '0x870c8c1508aecd4147d0f9e6cd1a84227b743ed2589d013e18d481674ca8f42e', - input: '0xf2d12b1200000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000ae00000000000000000000000000000000000000000000000000000000000000da0000000000000000000000000f3b9b75178f29d551a9c7fa4ef53840871ea662d00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000066000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000520000000000000000000000000000000000000000000000000000000000000058000000000000000000000000042c8eaf9e2469423637f3e4a96c42774cb7b8cdb000000000000000000000000000000e7ec00e7b300774b00001314b8610022b8000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000006434db7300000000000000000000000000000000000000000000000000000000643e15d60000000000000000000000000000000000000000000000000000000000000000360c6ebe00000000000000000000000000000000000000009d6d9ce40da95cd60000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000161513f82e9a0000000000000000000000000000000000000000000000000000161513f82e9a000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000040000000000000000000000006609e542e0626bc3fc2110f0ead172030fbe97abf7dbbb663c28d9c3594629d993b73cf35c403e1bc89beeeb37d1ea21c9e538860000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000500000000000000000000000042c8eaf9e2469423637f3e4a96c42774cb7b8cdb0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008d53b3012a4000000000000000000000000000000000000000000000000000008d53b3012a4000000000000000000000000000000a26b00c1f0df003000390027140000faa7190000000000000000000000000000000000000000000000000000000000000001000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008d53b3012a4000000000000000000000000000000000000000000000000000008d53b3012a400000000000000000000000000c71df678a0026861d1975ebd7478e73f3845a2ce0000000000000000000000000000000000000000000000000000000000000040674d4e33d5ff9fb69a7bac2986d02709192a5209920599cfce618fdd85c8c0122af5d7f5dc9529f9036dddbda213e1d32869a9df89490709b6cdb16ffaa58a33000000000000000000000000000000000000000000000000000000000000007e00f3b9b75178f29d551a9c7fa4ef53840871ea662d0000000064364012ab2e3169b84b421a4c96a4fde49759e07d37688b9cc9775d0cfbfe0e6929ac7f4f3e5bb465fdf4361e02d3fa2c9abd3085fedc49b3abf2db542976ef26b4f2b800000000000000000000000000000000000000000000000000000000000000281b000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000003c0000000000000000000000000f3b9b75178f29d551a9c7fa4ef53840871ea662d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000006434db7300000000000000000000000000000000000000000000000000000000643e15d60000000000000000000000000000000000000000000000000000000000000000360c6ebe0000000000000000000000000000000000000000c899523fcdd7c7670000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f00000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000006609e542e0626bc3fc2110f0ead172030fbe97ab000000000000000000000000000000000000000000000000000000000000281b0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000043215b6d5a78000000000000000000000000000000000000000000000000000043215b6d5a7800000000000000000000000000f3b9b75178f29d551a9c7fa4ef53840871ea662d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000281b00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000e554fc02a54272a5f7b40a973422fefebe357092b947802df3e5be9bd190c7e7f6386478b4538994ede9ab9e3a4b208fd15fbb1b64954ab09d34db832383b5b518507d4ee55d74fc16c96194955e4a39ed0480a373163df26f37a6eafcf74217d642f78b8908d37fd99f0ea6910481dada63087f2c494967287d24b8ae7fbd87c47006333c80d092cc6bddb77c298cb7df8d43bcc41470a27a05567b54d449ab6c31650f73c091e5fce34389fa80ef01351e4f27dacf4b30a2d7ccf5c342ccfc8e20d80f8f1d4532156017c00282a0666cc64098f56729cb5bfd065461a742598bf25d4121c849fee257393892c1c7c400c617ab8550bfcab713abc57b52ff9dccca07dd79dc95adef44e1ec131b1d71201253936d696c7d232ac0a5d78b8085d43a0b88bc4601eb528e73a14d7937f5159d6994f986723702be764f6cb3d3d5e48424dbd6d4a1ce490f9ebbdf1aac5530975f1a6644e535534d77094ef1c2bd1f73116f2689900115b4b2b14c8cdf812ea29856e0b743b4c5f5e8660344212b065e2bdb776f0631ef5f923db94d2c5bdc6121b772e277388d7963a860e0f5c8b06622a17818abc8df6876e8d1a71b814b4117825427187b1ca5ea39953c65fcf00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000360c6ebe', - maxFeePerGas: '0x6807f15a2', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x4b8', - r: '0x78a596b319d9980c3397d80f55a2fcc69453cc762174334eae561ed558364894', - s: '0x39f35a020f30acf5b2911165f8fcbaf9504cdf11013715316e8a7041e450a17a', - to: '0x00000000000001ad428e4906ae43d8f9852d0dd6', - transactionIndex: '0xb9', - type: '0x2', - v: '0x0', - value: '0x0', + index: '0x3a76c3c', + validatorIndex: '0xc9c3d', + address: '0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f', + amount: '0x124857f', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x96a00d569fddcd6570f39365592d0115d27765df', - gas: '0x22ef8', - gasPrice: '0x47a3d0284', - hash: '0x91af138e974e7f4c84f22362bc8f7247ec806baaa7d6cbc68a67e9689955e78b', - input: '0x3eca9c0a000000000000000000000000000000000000000064363f4b00000000001ce41c0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000b3c839dbde6b96d37c56ee4f9dad3390d49310aa00000000000000000000000096a00d569fddcd6570f39365592d0115d27765df0000000000000000000000000000000000000000000000000fee30738cbaa00000000000000000000000000000000000000000000000000000022f56d8897000000000000000000000000000000000000000000000000000000000000000012050000000000000000000000000000000000000000000000000022e6e03e4600000000000000000000000000000000000000000000000000000000000000000451c0b7518dd48654f03558b9cac8608e0e481d961570e4da2d7878b2b6d2efd41fc75e9648bbf16ac155f2ab2f1a41c1c2f2d3b3cc2958638134b3553bdbe45d73264363ed3000000000000000000000000000000000000000000000000000000e26b9977', - maxFeePerGas: '0x6807f15a2', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x0', - r: '0x6c57bedc3293558c09a4ba971650c9e9c334d9d30afd1af7f8b3afda4b774bda', - s: '0x4c73428de95a5847aa1d9cee18d65ce3c87c65d118460901240058fe0e531036', - to: '0x1111111254eeb25477b68fb85ed929f73a960582', - transactionIndex: '0xba', - type: '0x2', - v: '0x1', - value: '0x22e6e03e46000', + index: '0x3a76c3d', + validatorIndex: '0xc9c3e', + address: '0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f', + amount: '0x125dc43', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x6541fc8b4d1fd2961241a982b40d8ae0fbd7433c', - gas: '0x27105', - gasPrice: '0x47a3d0284', - hash: '0xf37b9efe2a4130127072a2f6a3ae5c7311e48bf3022a1433b7dba6423bf977d3', - input: '0x9ff054df0000000000000000000000000000000000000000000000000000000000000077', - maxFeePerGas: '0x6807f15a2', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x0', - r: '0x60734366ba975b8870db2c22d943cc0cca3e255f4a28833794549e2146be2561', - s: '0x18ac390f8fee9fa30c6ec211b36a3a4196008e52cbe862eecf4de33f3f244ef1', - to: '0x06450dee7fd2fb8e39061434babcfc05599a6fb8', - transactionIndex: '0xbb', - type: '0x2', - v: '0x1', - value: '0x0', + index: '0x3a76c3e', + validatorIndex: '0xc9c3f', + address: '0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f', + amount: '0x125f412', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x6abfc4629e609a1482878346c338f6e2007531af', - gas: '0x16843', - gasPrice: '0x47a3d0284', - hash: '0x241263ac0c3c04d623485fb5d4e7a2af103a7db5eabfe0b2d2afe0506585e509', - input: '0x439370b1', - maxFeePerGas: '0x6807f15a2', - maxPriorityFeePerGas: '0x5f5e100', - nonce: '0x35', - r: '0x18a1cae998156ebab7452e1a352a6ddf9c89c25c13c7cf329a37e7ed92b5c6e4', - s: '0x1dc0a408aa000e858bebbf484c3ac1bc3cf31791d5d9fa03bb9e3c48c84aaa28', - to: '0xc4448b71118c9071bcb9734a0eac55d18a153949', - transactionIndex: '0xbc', - type: '0x2', - v: '0x1', - value: '0x354a6ba7a18000', + index: '0x3a76c3f', + validatorIndex: '0xc9c40', + address: '0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f', + amount: '0x125d2ff', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x3843845731be3cadaf77307cbbfd92323fefbcab', - gas: '0x506df', - gasPrice: '0x479e17504', - hash: '0x8df5d0fcd95081999a6c417f8be98633d1bc3d0f6fcb6795eeb600ca9e676f8f', - input: '0x9a1fc3a7000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000103daab0000000000000000000000003843845731be3cadaf77307cbbfd92323fefbcab00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000b92d5d043faf7cecf7e2ee6aaed232000000000000000000000000aa462106da447c0440a4be29614c19387a59a331000000000000000000000000000000000000000000000000000000000000200500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000a39bb272e79075ade125fd351887ac000000000000000000000000000000000000000000000000006a94d74f4300000000000000000000000000000000000000000000000000000000000063f67f2b0000000000000000000000000000000000000000000000000000000064364cc400000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000dd874e7cc83b21cbb9da54913c9cc83200000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000001b14b1c63748e26c2eb32d7376053a63dc0affa64038b3dfb1c9e3f339f64eceb327eddca1a30b3c3cc88ab5255a43016de7eab3dc701b8df6f67b56f9e8a2ec7b00000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000001b8b296b0b8f9cf8ee244f391c2fea09f79fc0229a7ff61ec4cb6d90f653da259d77dfc2c29be714db8babc1e85b8e44093f4cba1b6f83ebf61723b9b57491e8ee00000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000103daab000000000000000000000000286a2103ddf789b5414c684a055bce98847f776e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b92d5d043faf7cecf7e2ee6aaed232000000000000000000000000aa462106da447c0440a4be29614c19387a59a331000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000a39bb272e79075ade125fd351887ac000000000000000000000000000000000000000000000000006a94d74f4300000000000000000000000000000000000000000000000000000000000063f67f2a0000000000000000000000000000000000000000000000000000000065d7b2a900000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000de35910b8089671968b0bc3481af2ec500000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001bb4e687d7e252aebe5636542f4848a9476529df218d37174c7c497445ad4d78005825ee792de917c3f69ce0dbaf175f2f06eb095d9c0ca30030f13dbc92fd778500000000000000000000000000000000000000000000000000000000000000050ce7b713dd7348ae4628b782afe05c072f8d0c06949cd25476af96f50c17a41cb7411e43d03b61a3035f12cbe47f27c99e2e379322d8786828b6b66ab45df0babb5da7165a28ad190feb007f60c85072381fd4de3f0d85c23797283b76daee40c1d0ede1bb1ac1243bbe201ffaa94f693e95c32ee01cd0befcd4e931cd9170b053cd365a69daf6b52e6526d164641a34833a08afa3486ca113446ee07f99049c', - maxFeePerGas: '0x4d225e2c8', - maxPriorityFeePerGas: '0x59a5380', - nonce: '0xe3', - r: '0x2a379538c84ab1c570861f806c4d18a8d99a00c0787aa4ddf9194389008af4d7', - s: '0x6810427871577c34d495eb563158587559e2380811740130c1342c3d44845b35', - to: '0x000000000000ad05ccc4f10045630fb830b95127', - transactionIndex: '0xbd', - type: '0x2', - v: '0x1', - value: '0x0', + index: '0x3a76c40', + validatorIndex: '0xc9c41', + address: '0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f', + amount: '0x1259b85', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x9ee50074bb69897e77ebadceac4c03e3ec5898b8', - gas: '0xb71c', - gasPrice: '0x479e17504', - hash: '0x4176e756b40466a7126aef4fa046a728ad62f51266a2a3b4a92b15366ac688b1', - input: '0xa22cb4650000000000000000000000001e0049783f008a0085193e00003d00cd54003c710000000000000000000000000000000000000000000000000000000000000001', - maxFeePerGas: '0x4d225e2c8', - maxPriorityFeePerGas: '0x59a5380', - nonce: '0x2', - r: '0xd5502ed0648a8a7a02cae26729c382602009560990d904686de10e00e45c4250', - s: '0x70587220f358a55dbc4529f918ebfc7f823fc4dce3f09b0d1d4a7144f9497b48', - to: '0xf2665d9fb3a0ad17a7454da077bec9cc159f644a', - transactionIndex: '0xbe', - type: '0x2', - v: '0x1', - value: '0x0', + index: '0x3a76c41', + validatorIndex: '0xc9c42', + address: '0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f', + amount: '0x3e86c00', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0xc1b634853cb333d3ad8663715b08f41a3aec47cc', - gas: '0x1ca4cc', - gasPrice: '0x479a12896', - hash: '0xbd6b5651c5c324e8c2ebe6e89c633bf3b33ca9bcd2c5d730608d3fecd11bf031', - input: '0x8f111f3c000000000000000000000000000000000000000000000000000000000002359900000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000b9181000000000000000000000000e64a54e2533fd126c2e452c5fab544d80e2e4eb500000000000000000000000000000000000000000000000000000000036b620c00000000000000000000000000000000000000000000000000000000036b630a0000000000000000000000000000000000000000000000000000000000018085005baf09c588447d08d0081d3ee73d8073fbcf89ee9090a144b4544bb5a48284a494c2ffff996afda2312c10f0889c99cddc9826856fb4844259eb06a1d0b09767819da33d94f760dd240fcfa1e4eeaeae2a9922281b12a9484fc832274a9c10abbbeabe079028400120a84537680980e8d180f6520338736224b4d21ec64d01a86acf125ddd13a3339655280794350933226c9e857a532a801b9ad51b9ae0ec3914f4032ff7839b41db1fb477f3f797f73b4a98cc8f2f7feefcee57d2d9af143ebf170ac6fccf594c2bdc25213e45444af35bad159559cc3e37c2b91cdb4654e42c0aa1cad4a8ac66dc9fe7b41cd139a0e174bbe260626cf8c432e3a0316098edea1e24100806f4cba0a3150a796e8c2a6f418a884140fe33148da8be9cf33bf5fd3031290cc9f0492b1cde126ee34485d22fa25b468648cc03448d202e5405268182c6b96a5686c080c69b643cbfb1d4955d43f825ca9e7d49196fff1df5e1d794160e1c06f7dea35680942e6a0e2e9e871955bee513603ad3bee235afe569c95c9ed5288b23a9a4d9b1d77d127c28e4058c1555de0213930b7901c500d77da0681cf39b1caac9b46b975a7b3ff14aa5f7c4bccd6b6e5622b688eef202d1dc85539042e186044c51606ac9d4a9a37e080ca40c146e79c2fd89ad9a1aa69670dd65ed652e5e786ea6e86f2b7412b59714f80260acf93f1d0f81b42b1b32de1d8a4239124bbf39bfe2fd732fa83da0e316d52b107b71098c2ec3cf34e6fc47709e9c3751209d2b8ebd3809281bea2c9ded610e44b3aa366dd6fe162d64eaa2ba9d90ee38c292307daf578e8703b22e85e42b48f95b183ce4501e51a427f48db41c5bbcd1f68fa7b5ad69da6839977ce166abc05740718fcb3ab4b63fb96d2535d5a1c0899fa53d3a7b9dee5310aa15ce3c2cf0bd97ec1c477a05e9e10f1898ff2573d01bc9646c8d9a1d68f39cd217e27bce13ea2c3d227ac03404651c7147f78d08e96d88b43db129ff8a539b03468d329abb5077026455035c68a2700aaaf323fc9d59486bb5e046e002537c8960d41e3a031cef7dc20005996a60f5c907212e4e4d6fafdfb7a5cf82d2e52b6169d36598e84a5493a24c6812fcf140ee00aadebd96a496786fcb67a803341401d0655a77ce35b49f4dd165c5ba82b97f986f9f7d8a6b3e0ea1e01c71ff02f99105689baaaadd4f371df0f2ffeb2c8ce59f498a7849a672e0c17ed1f8b3f4c5f7b58f41cd2df4f93a4a543306f6f110148d819698838b6470fef39be3dc0569afd179089eeb5420ad6044778c8734dee991998fdde7d874d88fcd07c94e665eb3858d2c8dd511f1e4b20f713d9340e63f86c7daadfbf80a83f3d6c3424b53cace4a9a1fc9ea42053b2a5fb7636605c9be326a1a97a7f09d558f062bc601e79d1314d2ca07d8a6ebf28fc9e9bf52600bd18a02c216829aa5b33eb0ed7685012ccf52c68f27e6096a3e7926c36ca6fa6ecaaafc4219d3c2d2e49f5f4d3c6261401f38e881ea405fa01ad1e8ed9018787a3450f4f782a61cfc50be9d237a22d51da64d0ed528abb41eca8d8c881e98135af660f0f15773fa179acecb1ae55b7b7c3022a15aeaf077e120a663b06d6f1b0ce11f2a441288bff267deecefd4c830803aaf211549643f95aee67b6c09feea5a1aeaf6bb9100b2240ce9549087dba5eaddd0c53cbac7976877b578d38a13032e0b38e265d8b334905309319ee3a4308ce8bb7ca311d8a62eef076d8f0cc8edbc43dd2ad6321b06364c026475388cdd45c4c5d31e1ae299e6af872fe807c8d41f23c744e009701f812470b89002dafa49384aed94fb5a6d98ac10196628eacaaef759937507881a45988520f5161da10f5acef5e589fd49189f37e6f734076daab59b552a65a5b0a87a4dd7469cca43fd3fa342dbf541c72fca7bda617bdf62be853c9ced26e06c9bcc85a5a13876884c0e567437aecce5c2cc02aa38c7dfdf562f3bdb14b71185bfb4b295f87da387464f83be3c2e0517d067b86ba517f4d91d1aadfeb3012e713be77a697011197354732bb907a2f8ec561893de419a80dcf83736849f1a14110d568c053aae8a7c987edb5862a876d5fcd19ba32aee96e5642609aebc836fdcba3247e4025073a4288bfc1f50984303e6df6a4ba273ca0e56bec77d8d330e647b03cb4e13f740a34130201008040281c5a19017b05054790b620cece3212806f660be870e7f253ba7f04a2821afdafcbc7a669ca548821591d9aa9023018cb385a4facff5b07b2c7404c65fb5e5231fc91250262953e02917373dd1161bd831990259ec27d514a41b21e4094ebad0a5f4c8581413fda435ba5ba477e57f76a4b144ea713fab622802e093664ed61f6423e627cc498170d25d5744ecdc38fb8f666c69718cbdd87dd0012686cbe6f6cb79d5f95c43fde4c148c47c14e03e9a1bcb3aea11e6da76192c818ff86877d0e73fd1e89aa90f09d3a017f89603cc71efb92b10ae7a5359e90732bd53a38d4e844774c7c83d0b6b80301fa716afbed3765af3d05c6cc68887f0fda809375d33b794c808f6350452a2b54f73fb2085428761e56b104e65f39f86565b616c446555dad9d1fdf3fd0b7b9288c204c9d41de26b0a80c0af668388ba1651262b09bb6c325eda7bb78bad941facdb44a9798ed6823be730674f7d9a699935e1fc17efc391e449190a46b54bf151367304e1bf662ab65cb73a5647eb220032b4e48fc2b840aae15d1d781264ea50ef5f7b73dfc726fe9d2236574156f829f8d41a0df05ce717c90f09fe87d7c8ad183c7fb7fc5b508904cf285cd3322ddaf3e75601019560b1e4aa43f01a2831b7cf991384097e9078eab83bf76121fe4d9332594e33650849b0a03f650ddfa3b48193cfb60a54803e499416b25d97144e571b99a94b6bf6cfc9b6fac66270446527b27484d15a9d14486e1265080c84bef20f30c39776b8de86cbd80a9cd1c1a9c436ef61218ed51b922b0cb4e96800d8b3b278deac8393ffb0de72257e992e6dcb5f92c7b0d34a6f716c85eeb47a9cf5c034e7ab9880447dba697d779beb317ce4d8051979733046a268055a5d6546fecd5886380d671f94285d02da072de52758b18946b5199768859850b4927bc4914507113bb9b34846973bd9643b864701acf9e072c5e6df6d8faf359aca2da7b594015a61b3d177fa27a1ada4110d0c635be0ecc74837de5b68e881cb7412fa9f436b56a7c9e49f4fb56545c4f13b9df28846fe34c9fc6ba400e63e00e64a469fe0be2271d2c82299202c0d5353c323b1c86d5689ba688a5181448b8b7a3ed3dad87a142cd8e43e23837a9e3a8e35af81c4ec7979a771ce09484d38471628bf00da874f6a8805ba695573b0c26697a654a7ba9c0c6dc6104d4ac148064ce228fe2495f11b175c00bfb7993b9922eaf4ff02198e54a65e921fde7b669c4dfbdefbb6a8d1c60fd3577cbedd50c8737b54794b14f83e06dedb50e23ba6134d45bc99a345f1d1c51164bf8a61f5c5f2fd11db16cf3adc36a25be6cbd7a1d9b39042eb266140436060baa834c6848ed7fb47436cdde2bdf5a0a8a6b5211bbdc04ff70371daaf6905aa40789e42cdd078d3a1982df7079d80717efc1fb8d5803fd55d7c08b25c48a7fafc3d1081c443368f837d45e4d7885f1eb287d01a22e23d50bca64933ff364d53aa1ac848dca3fe6abee21e0bfd590ca60389875dedd5a6b4d08cadd6120539923c3d22ab38bbe0896caabeba77cf2485a1a78f1e4874e393f298ec5a074c93fa4fb2278ed82df38b13858a25efad677d531aed01a95de5ec1b00f77e68956fe344c7ca3992ce222cf1dc89bf51aacb2ca15008c5f85b151c5ac54730c1df26f9a3bc7859167f73d01c172480d3752a9c70e4a3d5fbb5fee829e4b1ed032ad3014a963500a36aa6430ceca9046b594733de38296993168d8318541ef668821155343fa4bc2818700fda4708ca8311ca83e15d370a62f904351d0cddf71c83162966cab5a49ff0c255ade9d7564fd07fb482113d90b1a87620e67c2039b9068023dc14018458147876321c64b8c8b0926123c34946888c30093a901f1ed281e0a48aa108a089eacb63e759baad028f8c549fb2726b15e2ad8669c6be3055d9b4314a517b0820c05ef47139df64ab3f5f769dc1ad1bc8e607ad77f7588ada3b0ce82eb9fa8b2926d9648b198f50aff6fe021fab65ba94bac02f495901fbf876f9067ffb75960fbcf97f9ba4f2041c86ac0321abb3838d84424ff879063ad35c0cc79d7854095d3949433b3647118501a8f914bb66a679b8b24e0b21f18d176f384f7bb525971401329435bccae921d9532565c87bf1f22d340802da072de5af7eb592f2e9d874527ad5c9d6dcf813bfc0a4229d0ce17877b2b05b28fd5abe06744ae96a8f0c6224f8f6f55ffa7e1494a9494530c67cbf119de0cc1dc921dc91e363fa4221cf9e51e52de0f2f12f4db05e8739bef4df7e5acee58c9f93543d40b95bbd69f8a5261250428dbefdffab1b113104068829cd2f92c6eb68299de65a29bbfdedffb5ee66c1d57b3d9a6f1846e8971d12039c3ee81c1ed2b197544f5bcf1c8891567efb5fe76ed24c9076ba1dd79d63c67a41201008c477ac56e873533484903a4632a30e144dd03d94232c6feece2e19cb0fd734fdeae49c627afbc54b25a25ba606b6b8cfa3b4012518592ba393daf08f7db4983ab2e7e2e1d2e75c90b52aaad84842f03d67318bfc7d42e7fab1cd7292195df3e6eae7ff4d4de465df6f2d1ccb1d9cda532784135c81701f4c6b46be5423c1fae7be795926cec5b97f39caf708817482fc2e5350257a3e3a980bfa02668bd2c77ccebcc2a5c0409393245766f916dbea26c08f77ce5ad355950caba91cd13da6d4bc94e124a2c2625614f6dc16f315aa988c7b3bd4822753f1c03caecbbd3ac768f7e00b6253aa8ca6f95ba145ffda782cdc4e66ce6f8efece5aafe312cc24fccf71f84129ad1f6b06da5a6bc3273ef07fbf2744a1bbbb9848fe648adbbc6a7e4d763dd3de7c19bdd0d00f94a8eed8d6cb39fba5569e6fe48b3b007b1b913449a1990fee0e54e94ced070a67decd5b61c198f2b097a8d9c5df83f69d5682f3127a8ecc155110dd1f6f3346265cce67b7a727a3cd54b51d954fb4d3ca7ec5c6a8569175326d60531d4c3fbbead23795267bf6ce4c237f2ba44d7e761f62888cde11eb13a431ed87b7dc96015992a4eb44a400e60f014ab6b37e39dcae8917d7c58ddeb66afc6544f0b4eca1e9a6e78076bda9d0f77b8924540909941c63ef8b4ee662d7c2f96f3da4cf738422e5bf4e40225f7dd7b76c0662e4a79e5a454bfacc7166ae42606a2aab89486d856b740d6636182af63a80bc1bcc0292d630a793961e7047128535f3a47707cb0a9f3f8fee86052d3207ac31d051c6f0b50073435fc0ecd1906be4c07d870ee75ff3bafe3f419fefed3a2fcd305f7d780ab239e1af3c3a570f1dc40afa512b5ba12aadfb947c33176e26243e4e33f572651220498ef2acb5cebf91bea66ba4976169a03e2bfc8f719b94b55445ff17dc5ac61ee04eb40420175d62049bc7cc2d1957640d594eb698e79967abef7cf1e51bd614f0cbf67cd379cbbad6f342ed7793376a39b59f5e9d1d9bb1fdec8a02a13e0d1096cb7574f698cabffe4a37e8afd6e71b761f8216783ce24c0b097c73ff333714012cddacbce6b9cf32712bcee83c36fdc797494a574360e03c43447c689228d50503663c75416ab79e859dc6624c541d669a8d40ce11064cf8982085fd843c488f1c0402814020982228e405262faabc258a852006dedb50229b390800870648e4182777a3b37a2d4e99d4a5b7389ee123c14e2b3745f4c0d034eafcdf0759d5c0a64f9c66098b4252eca3d935dd3d96cde74b5c9b1b4bdcf409b1d5d7773281c35ace9f98f35f26dd34cd62036b30766cefb519e987496d5f66526e7c90fc1592e638f241a67ee6bfe439d85dfe3f3e883e1b01c2e2283ecd3d941a3a28ce557a1b3eb1840840e00cb90e0a6810594cf665e885824bec381df1e99fa3e8d78871cb061afcabe0bb3b64bbdf0ce2b4f5f8ecfb1119188fb280878081204f5f06ffbe6ab716b2142cf89d31b563b28d1cae6d936dfe774df0a5146a29452dd2df859b2c85fcf03633162deecafbdb6ae0226be1e4367ff1e3c01dcafe314fb30d0f5e6c42ab1e91e35626b752720ffac49a4f816bd9dcd5f303df6e65fd84200a11b54ad3cdaab1abb968289ed7437f4ae0667db5779425caef81b6258c30c464f7d7fd040fc4733bf1af0c35e5d091969ccc802f1bb7a872f40e2db5ab2aec86531a35593077e51f718714ee633a1ca5648ec2a7bb81bc2aba431b0f2fc5c9cd8d07edd0a00b7b2cdda4751e27e398cd687c109f94e8feddb7d6d320146e8d76d0dc6b085f143212dd178a0f6b1367f44eac0fa6d4e107deb3d7dc025c1aa4e5b4ba98bf794bab6d659b979ce4c24c2e414829c12cd38b209a97aec6d1cf4fbb18bb86ada68ab2b1431180fb7fa7e28a5123833f2e0b32c930254b4b02ecd11f5f9e331a8abefb5bf1147c03b4178addf94f6eefe6d7510c2d085eeed5167240b49fd57e5f26e9f24faf3972f6c06983604020100804825985bec02c46a3b7c3c4c0d3a381a21badd473f043f976ea95c9da50e73a18c2b246d02fd41692f9646af9ffcd4a28e90571a20d68cd08ff1527ed7de5e832c6feddc8e014799fbf1982435641aee0b3da0f3951ac23cbb197014e619d2483514c8dcbbf7f4d6838c5790b8c45d71fba1c859c255ed065bf3e890779b99521d00532740a43790f3ea24e8ccc303536d24047f4f38c2b5d92dfed69ad46ed5017173ea7eac34080ba5c47dff0a2c47f67c65a2fffafe68ad6a8c3adb76f250eef82b97df6f2141a0e7f87f757b928c84a8c70e10c28463e2e05148d70b291737b32b2dafac92584a7a312dbc17243c0a4f94c3a22c680f9aa7c080c70fcfd728123ba7bf2b894ead4cf2d543c8cdd83c5ed3184cf87277b1ebee6bd0e185f3036d398bd66e204ab7eb6e8dbdcaf9bcf7fd33d5866adb20dbfabd7e2ef380447fb1b3557742471b61823273ee79eb0dce3e74a174594ba1652aad759035c3b67306743e6eed059c42558e3ab542664386f36972fcbcf4d84b46f35396298cf67bb7848dae85535b50df2b910d60911af87597964da0778eeb872b1cae111347bcb13daf01859b214ec5a724acdb00ea36f34a60a2dd90c935f3bc920f20e93b105e6f4bf7e9d64c391494aac526e435d1560dcaa480de184bf98fd8c0a8c719ca5f426849c6b7de8f75f4fc67a42cb7f5294919af23ea78fc5f163626e9a830d08aaa637ee4b97904516f74a821467c0f50cc25a470bd6c21e912335809b213df7f21192d708832d09a3d9a80bbfa027dde8b77bf925b616f4def794fe1ea84aab4e3544009e24d483d973d2428605f6aa01c7fc6be2f8fd4a7c7df855a55e338c87b17de500c713967e41ee3576f312ebb7c6b6a6527fb97fb03f245b92e62aa27b27932bd0e11aff65c9fe14e48b11906b18ccad7bc0b7db3cbe8e6863ac806a317168b3c1ba95b1e7106983ac60e9c2ef60fa1dd8af3f2ffe3395c5650d3c7ff89678ca32db2cce408dfb408d03c518e589dfda376ae551661d366ee378fddd7d51cd66def89f3f1e11db9e1e647edd0a004188d9699d5e285caf0e80facecfa69b991292cda6bb8689ac963a290be1155f983a0bca05ccc7f67a4257a49e4863ecb24f9ccb2ea77ab085de31496101438ffce35d5385f4840a49e8fba0157543a8569bd5465d83d03566dad2401167e5b1230e116ceddb709d16b6d30ee13a208412cf04721ea5efc89950bceb6fd3f430c1cc865f388b5f0aeda52feeea4b9330676f93826d3b12c2510f31007d2ca74d9cdfffacb5a17921bc5a5e475998e9ef724e889e567d012aa0016b6b7e7df4ff5dba52f9f5e72407924e15b85573e5351210792eeb6aeee0ed816ba8e8cb367318ee8330c7183ab083626cb56f41d1d8f81b39dfa86e6e63fa677fd3a5dec797973e52a72e8b49c443be622d9b788d779f60e2cc339d5035f77fa10f834a82ea5429fa36514c4f36ccc96a5aae2e398f204b6c59ce93f4ff34060e4892708e4b154360e060770fe4f097f4c6c0fc07b520010a1724108f7ce41677585231330927e1a20e302d728567fdfaf4f7a26ab3dedcb0381653bba8c700ac35f5eba07d152c3fac085b20416075994e9d3ea7cfa41c993de8bee5c3b4ffe07c2ee0f95b35fe02734468a05268e9438b82eb862abc8785d65751ce8da1daff70864da7cae9f8494d7aa6dc255cfe4bbf5abea7d2e3723ac4f886eac45e23b45ac99fb605ef286c4976eadad05eb1ae36bf14ea19ef61a23b19bfe5a343e7dd430302981d72fe4b8c70c295440c171d51b55c759a10fabca5a44d24d1193169ebc3a1c296523dd811f31d4ae88106458a95dcb4a2fdd935a9157e31a6dad8e284bf9331972f78533bb66f0f8d327b287e3f45a2bbdab33d976db191142c2a9a5f0b511e554ac403ae1fb7792afdea83562bed0be46d435a215faa64116b8ab9acc2a9182084269ccc7cc772366bd5df8d8998f9f26dabb8d84a7ccf56eae2d49fa1f33507f6694ea0b588c0a098d3900e7733fe778343394434ca7ff25f13184168b6ade4df9c8ca93444e59ef5951abbac59fb4a5f3692a01ee002e84dc162d4c26c93b95304bf145061caebdf7c461412303beb45aad1e5da953183b9f00f761c7b87b012126bbad9747dc094feb046bc9ca81aa344a19c7087c9e08f279e2ca2170cfb11f41e346ea8b41b3eba71836dd3a2e258d5fa42b1462cc40119cc4e45a273c5aa30633af1cb0f4b7fd0fb8ed6d1d030eb9ddcd38ada7c178500b89b9dd69f9b02154b9b66d5cd2eb246ca6413c3835f2a8ac2a45655d0d775f9e04a75a71ddf61daef9f72ee8e4ee829c77caa3af97ec85b0a21c9a51c6e6272c29ff6015930db0335d37f15b96f09d8aa6c41299654144935f09e8abfd2f5f716ede97e1b2b4f5c6ee1ab2596911a3c228f9ee152b7cc31ee7274753d7bebba97adfc5840786e2ab32a9c6ee935a9ee2506de6aebf7c7863706fe975c3609356bae4a47eed6053361c7f32085d784e45694358d3be953bcfb3c12e7e7f5c8db4fd103a129fd86f1cf907042585ea0c99ce1353580ec23c1e84ccfe82f13956b132c1265fcd948f16e1aa216969f6e08984258f3e35845c6e294709095c1d42a8ebf87b46262080c64e09b2961906866fa2cb89c9ae41648669b561a420bcf301dcd0e2ebe697f0d0560c88fe65b7f6b6170eb53721e1e7ec3ed680edc7fc45e9709046fb74c9c766c88bdd14fbafa9b6bb57987f65d11bb71f0177072483d0f4f65cef0ba6b919538e16f37944102d4a25091360a195a8b25df2eff5a53662ffcb7deac87129f1f4e2304c5f192f2beb27e198359eccbd42d6bff8b4a43682269947ff1bb9846bee80fa61635c0c8a01a92bbe478c2b388cfff92adbc7c66f089f050518a50bef40de59d79b2f56225783f4dbabaad66b72d32888de67431782e8a4b0e9a9b31007ac03663a697f42c04a5ed4080bb35c9a44fb638ea821a1ffb09b5839dd14b438f35368d7a44056ad08eac091b6d85539017a16f021097e19ba0d11b8b07908223a97e59ddb44eb0b62ce18777163179af9b3db3b9c162b41bbef926027119fe31624d1a3c0c22591e8a00aea2b97c3ace9da9a3878a84aaf351ceef682ae3e2c25a70630f45cb559f76b400620f59a7904e0f4ff736bda4ee0276e5d1e54738f4cd3126182b95c853f81fdf7bc005a519d6efc6f898810cc9dfed66b579d80d714a60a2d4bc171f1c93b89337b23becb14c3dec5dcd7ac82e0224abc831ecc2fb8e55b7646d2b5d57f1cd213698ac2dd3fb93b37b983f6928dfc905ad5ef8bc5804472c6f31f261424e5a975de0d31513db108e51fc3bef7af8dfc3c24ace6213a33b44aa078c547b75a9701affae7f0c21a6cdab682923173e9f4a84601ea9962130b0e1cb21cf4017d543625733f5bdcb6a28c03cb250e254ab66bb77365d9a93b911084b889ec7ea4ea983f98e18e37dbf65d93f26b2101684f7e313177aec2bd90975b71fa8014a7e84ad4178ecfd776817c2853066e52818e1a5376d79559300aed5361545915777a711c0e715d10a238be80dea1edf0a0dd26cc978ff6972a21d382d7573c9d59a42df29808c9c32453e10638e7cce84f8145f604e86c3a34bf43078d2fcd83591ec8a74ad07ea0282018140c54404c2431fe3267511800a04f428b18f09ce85e09f9b28bb548318baf0608d1c5f2157a34ace1af3ad1edd5514a9dff18683dbc10d3580019b7a390bf16ef1abf6717c47e336c9ec719680969eef2cebeb8c64acdec2795240a0209d69b07266fb3ec1c42a3617099c05ae0432e460fc74e320f6f7bf9c1e44d87c2c01e93212a65f8eb7150bdf574b92da20aa7f8c920bbf4cf10def3668cb583888fee040fdb19f43a81ede81d60eee1ebe566c965e568e7c5bd4133542d225e495fa96fe8639ca0fb024876f9665866eed677a4da934fe5bca3c06785c4952676430282137d392bd7433c75ddf5cb82670f8b2de09576cb71d4762bd954dd0e77ae7a74db3108735e4c334599632d3d1abcad5f8d5f64dbbf8091831a4d0a8e70ae4c69e7a08e5512faf1c43f3bd3b93a802425da88b9dab3aee6a260e1dee475a44eac8ffa1cc011eacdf274b6312137b8c241ac7de46111fa6e03e43ab54a4fa5592b65fb23c0a70043bfcffe8150d6b4b1011e3cf9b038a164504e5c08880fe67313d20db45bf6b7b0a2070567493ea4724c38020206466691032b3c41018b88bbe1d1320fb8a52e0956148f5f2376c6fbfc0a38b0355f6221e8f11c2331e057013edfc7a087069def45db4ee104a247475fef8e86cdc2bc5623217ceab96790281402050349ee2906cec2cc82b1c57f7bb7ed216be59ebb2da960b662c4a107c9c14ad048a2475f1760b48b1e55ceaa200a514913f719d342b437d86560f0433338e5e4f02ed117ab55c57fb7ac1d7ab31198a9910a1dfd1205fe8b357342c6f430ce6e1575034ebc4500e1559d092f8c272d04bfe080d3d558c1f2b1c016c02fc505335dc434e1fbda83b141b8f22b8638ac66ef2a2e21e5915ef18101eafd6ba7791313a6da991b21900d205e35f7c2d2b4e8d50ad2bb992edf27fa0130407ec26fdd066c79468047124b8afec81429e3baee2e568b33d3f04aa925a84bf81e6b4a1176a7da729194eb65bc28bc6de7f99433a5a91f2f90417d0a7b92a012d533db3dbbf7841f9b10758b5f05fa485666a4e3ca6e9eb57fe28e10eb5b5a3e92ff3bda07f72760b00f3b473f7661a65525b5a28a5a513e79885f7693e828fdaf2e8556f25cf3bbc074c012ae542e663670eb60da4beb4dab835774e8f1ffac9ffb26ee9ef3b9a3e538fb61deecc2dd188249c7dd0972f2e2e732f70034addcc5ca57648607e5d5be8d07fdff9d396f7ddd18283bfcb1c731008689b8ae9230a9a3605ffc3ff1a839431b76744bea7365e5d13d230183d638fd703253774efce6958fee7e50e4db64e757facae567ed2ffe7c76235ef9570fa0697806a751ae11e71a2588803d27d11e53cf73651554b112eaa59ff2db1fbd360e10dc75570fe18518af649ff063051d2fbc624eb2b77c605109e8a162af5cde09512c496c4f19e3254f0c598ec7c78503ba054d1e4808170bfb2cdac51c39f9625aa9bd094adb50477cf2f3773f790313ca0b3187289519246a7d2e0d8681fd1bfc33e9a98a40cff4adfb0245621b0fbae60ddf3f5cc71c4757c214da0c78a684c7d6a49fff7373e133bec26aa96a0ebe010cf413f7efe5f0d18be2b772b69794922d96c6fdf2e7d4ca87cf40812ff5f2ef81c95629fa74dd959c875f86997e86a69a07d34ded8c316d751546a2bbaca8ee20457809e9e658849de7f738816bfa4ed86f46fbab012cd4af68952c6f8e209cd6b819bf35a95b2bd6ee745188ef983a9dac6c87f574bcb4d72051a896e63e59188b7f1bbc0424aefb472fb170dade866ecd0c8fc17e3359b0798c4baed6b4b6e8be286fdf91635afdafcd6778ec92f27e9421a5fa62f9566b432b9bf43296491d623b59df55a7f917b1bf90ff08e0fd889c72d8d5484697b27af5743453b338cc4f24322ed7d8da85342576117ae623c9e0591be00734ee9f3b596eb0da40a09aada7deebd65089bbf353b1a0bfa8761b373d72016e13036436000dde8fb4114a575a12f3a7e5ab5729e9a77ddbdbfb7e927ec26c2969e2f7c219b8046775174e4e45f20e12189e0a4d8c445dc60915a844828d38c747d5b09feeaa80711130403028140201068150a795e8c2a6f8982df8e8841b8598a8846be25ce49cb2de84ab5e4ffc7decf717789e5010c061856c583eb4eb090b591ff97449fda671ad5c6e29ec016d926da6ac563f954ab91059dd1897178997b5f21c029d5059d16ab69d216a33885905528b957d325d452ba099a61027775218ba1ab552104d017080e4d55fe779098881caafcc60101fef8328b3dd4524f8d4805bf6ca9e37898d4b0f28908500fb89ce50772aef488343cf859b2b3ea2bd21fe4fc98e43fd532189ab790933be27d342201979b10ed9c509f03c89262b149d12baa2b11ebc4d00bc5749c64a68d1fdf129eb1838de762c49f854f9712fa31a9bc443eff6d1dd120536cff619016a502223268d9ec43f0e215aff3a34af8f8550ad0acff443b5287f5764eafad1e6a3abf4f44a3824fa722a6b099f9f24ee1a7f5474fc507faec190dcbdb98bcda951ede22cbff4303bff47154769bf4421f45fbbe2ac7e31461f6b546fca0bc5bff3f6bd199ed50e42e354b4e6c63cb85d803432b668d9a4b84a692e9ee2f2d807f48545ee93848fabe9b88268ca7126b06fdf74c1cf8ed50457f864ba56c46027efab8900855c2343d1401e0f5fee3baea6afdfe03ed81e3b0e2a872b447e1564c8d21d10ef239f3d76d5b2b20e135463cdeba79f81351c775ef73dad1d6534e7e49937660bc411251014a91154c47165bcc4a1f79257f05aa9421f137c1a4ed7bf89b6ec868ea01ce1b01f5f356c8485b1d4daf8d4a09809ab6683aeb13f9f89d302f78598557928189e5eab3cce9438a240ceaebbb7e14abc010405f60709aad7f0725d2a8c8d195d645b58d1421afb292a20ae903be2431fa7bc6c3a83aaa47b365f440cae17ee9370b007599d7348ea8396abdb44a092a131a7b5bd11eb42c8d5a00e6a3209bb85be756a81ab26d573b6658f5813b5ad80fc94ed12e58e124b37569d9347f39b40a64810ab3833f4457f0a5e8d4cae7fea3d3ae60f425a164b55e8450340bd43572ee68fe98d60921f02750fa44ca811b903f384140e521e8c241409063a83772b70b3a8252fe211bf773b7cc8357757a735b7004747345ca537d805aadd34a40a5fbda29c919e05de09da5cb52691893aab83652fecc8c10d377d11b059b50388a6b2066f12e069373a25c78e07739df722948393582f5bea1caed07d62d6be3ea3098f64b229c200459037ffc528908be8c621fb4e2022a784d1a4ee75725911f0dbeba113821a097b51c40b3dad1101e537c8f48b3025470d67f8755b50b07d88a7e56a6fc28df788bb2c86f7597e158934289a239c2ee5e03959bce802a1f6e0c3f741b42dc2aa48db47ea38922a62e71aed088bce9b4a94f4f8a91b4607bd20c38631faafbeb092f3a2910851a61a46a259b1e303f2fb3f0dc3ea8672bb063ce2256da756c010e269e4cecd98883096a61a27eedbfedadeedd0941a7f8e3f5e23701366c5ae9050a336106d8ba9f6bdc5ed78ddf213f1eb486cf1c3e73880abae858c9b5cb4445f9859cf0657ef9a46f3f39809fe8fd570d5bd5c8d0212230d49eb65da8ad95235d840b2cc58fff192ea13c478466979740a152918e91eca08cae5d1d4524deafd1d075bf33e403b1830c69c06287faa8df5756da265cd79a622d20d6b9b7457fa8ee628c7d2566c4d9d4c88fc5bd727454448490c102fa5fdf1cbb1c1ef4218af19f3db6f631a25f7e805b17c83ae3f42dde1cd2801eb00c1b2e750ac80255ec1604780a4523104cf30327e980f1623f096758dd53ca6255afc7aeca672cff9748e490e1f92268934215b33504ac322a483c0c818132526d8193ef76f2e0dc6fab14ae653df137fa36f19f0e3f665dd52b6e8a0f2e8110fbdfeace6db9fb602f388aed9423d7d9cc0d74ee2c62a2e9a35751cd2d8384f353ef84429e5ba3ca5bd82bef5a44a13dcfa92e132a13141c5b42ca87e5337f40e191c8d77f758db95037daa782a5cef18d4f1ff72431dfdf3f87839065b3c55b0da0b3a534606d45e9d2e726f22b7cfc1aa63cc43946397ab8953193a1da9aa07dd003f603c18040201008d42aa75e6894857121a56b903d0efb3eda40eb32373d218ec7b5a9719a0591534886c040bb1526e0b459e41f7f2b650d25944e537d2131bd2c5d223ebb112e3f75068501b24833ac31a6be2066fc5636da76bbe064c7a6a66058498b9c83854e21338391a327d0bb0c7ff323472e3fe1dded735ee4c4c5fdb7805fffe9fe8175e4785e1b883b45f0f6b1b7b17467b3f57100595dba7f4f71f11d547a638f02fdf3e72e1c540df9e0d66e65d4781bf7ff795ddac5309c28adfa3c543b8a83d9205ddca083dfe5832f44db1108bd7f0e31dff9ab47e5430e258076af8df35c0169189859d1eee6e97e122e973dd0bf2028e4057a1355dea079708044f91e116df76f28a764dbed7e8b70ba3f21764d0ff1d3571b28e7d9cf881e68acb9be2e232192299af412aefaa4895f95426484da17a9f44263a05dda4e3b33bbc2cc4c5ba0b102e5b0fa47d8ee6eb68a6ed60e7abc72b6b632816e96ae8ed620ab3a4c9484ec1c40829de3bc4826f03f7bde078b6d67521e586240f4cb5f5d5df9dd8eb267d5d3ad9aaa5389f84d76dbeda30c8e10c831940371c0aa1569ea131bbf24211aeddbb3fdcfd2e7acb6fff84ea6e35905f2475076a34fc85596c21b0db964a95ed6906a15a3a28eb99243d02424069db78122b1bfeef8ab5e31bf9e3ff568647300bb0ef322456be649799cb90120a82481b3038d6801b26a3263b2eab3f29a3492a0f2b7e6d31e324ca20b5edbeb9704670c3606ca4614aaba690c68c8121313134be7ba55c7bf33bddb6c8bf149280f7670dff6d42966be83acc536a33827825a72ab90dbef46dce3ef8982cc714aeb1b04433f23bc65befe6411c463774f03c247cbf50afcab9b2dee12ceb033edb378e91cd472eea6825c2446748a3a5a3b7b6094538d8bb1933e0eb42ca6ef88f0c91c63d1283b5839490382ee5ca8151a3f9f096e62566e1f098951ca22bacb5de53d8776eb934f8dbf61e20d95d393c802660e8d5f0a891a6803d0d665e6785f5299f840adf73fa4013f8f0ce196d3d14156eb6df8c4e2dd9c4e3ce077828b17c62c9833ceffb161604de5d63b70c875cce11f02035bbf2e25ed969de3ee8d7a63d3103ce1bfb3917cdfae92f0e61c207435d970530768730d6d3e011a94778a222b39f29a5629f717cb5dad5aec4ab8bdc10cc3b92920100804023dd608db6641404b6c22a2ab74b59e83c5f3814a2a19d2831017074567d95aef07f2d0d7e91bc54d95905a385ae93672a4e5ed5c86b16896f7f2d41e73403a9e427e580750ccb2c2b8c5a555911d9e0e8bc8adf9669991440fda345fee33a5fd22ab525b83d0dce3903f6e730aa80457921e91c10edbdc3caeb16f5859c52af0757afa4273aee626f6efdb779f3c8fa75f72be08788a453c202b291a8a00506dffeafad565e6ca53157acbfd2c8a0afbf28d5f1db3c84c73ef69d03447bb10401aaf7a31d9ef4486eefd593b1c3b4fea3b8c2c31a4b377e3596baaa609c92e3d7aeb37cbc9734ee8797d6ae2cd72e8ea9cf2c8477730bc3d53d9dbe7e6548d49b70e550b73f4eeeb29c02ca555cae918b8bb7b1ccac51e715591790a25ad53d3db190ed69a4f07151bd6e94e7fbc32010a798e29fc2b11cca4dd8a023038e6b9909bf6bb6f0acd9c7a00298240d250046040f56c2c1378478bc64002bfab3dca8c97269a50e945fb44c429e4c3ee51f11b30a46b2047c1e8548b473cb8d8352c25dfa25b337b6974c4236129ac540e7f45038140201008620c85bc40f4a2ca5bc822621090ff0c45132e8273f0e6055a3ad482be7184b43a86b166539e49afd5c683f3cb2fa2f1d37bc027b1579b8d201008644b707723f249704bb2d6995132cdcd8cddc52c7ee39f59a3fbc30f34852a339cb5e0ae8a399005188bab0c367cb6a57f0800441c4a3bbe8ca4dc453c3fbd4d2ac07cb3a6928e8b875127b0be78ee82250d8b8f168c890a2a8ec89d441927a34b1e2f5d2f982ff57aa85cfa13f2fd855408347844638270ce1b94f92a0934fb204122007691e4dff019c7b54ff77f7f7b74157a7cc7a1bcf51ab1405d0da22b06368f590176ec9f6d813dce0f53c5c20421b5a465bd89ba5a8ba3dc17a78d24f01a13eec23de080b07ff516e873631464a7e5d4408d8bfc25472f6c48f5bbcb754cc1edbb234aad0c78e41a4f33a25bc6e064d9242a8c60cc96efe02f6f598f2c1652bed82da55a444b72cec49e383e6b6b38b455cb748254f4f446b5bbfea5d6142003427d38747e12f79189dcd236457a39e9faa50a1cf5777b7e16cd5449abb98dfda12b3ba090e796bc3f3febd82c082fa44d4974b5178b8a8a8a2a35b95c3637c917f050d573be9bd2ee7061e8d9a9b16ae19df97a2c40ff1bbf3b0f5b35fa7b52aa121922eb4ca5f3044d29eb0abff6334ad02c35226440bd7d9baf6647d167fc02fe8b2efc6f9b43b05c0f9828039307c659350aca1a8370b354c7b7c524760e39ee43c6a1ef3a26ab09e7aba17adfebabd31dbf1c7296f244511a563d729efb1aeefa7b56e41f907b93eeea35610afe94021417f2da0bddf1a695cf70b4377a7db2b6f3f2c62a4c0ed4aae162336b080cd4e868fff073b43758cff19ef1156f65636b4a8004e30411e3f6cf6b4f9bb540016c54361a7ee6249aeee2587d75c07744705ae33d5abd6308f3549e28f425d6ac07ec0382be80dda3a8aec2e48b8d8e16c839cd920a42ba3c673dbeba262738c00d818dc3b589e8014377c4280b0c68f048c4b324ac063ca4bda62acebc7273f8cd1934fe2a631894358166a32c81ac56d9f089a3b9f04c2a7972a9c65d4467c17882a2da297c13bfec90e3dd6fa73f4437a87d56b3b0e6f40fbc5b9effa7e8d138169bbe511fbba9ae36ca7708b0ece353b48386c1c3579c56fc2a24401766825820b5cdf64b2c1accc55713443f0df9051a4c1d942d6677eb54432c709703eba12b5efffcd31eaf9b495511bad48faddda348d2af2e29606aeb956006309210a68dedb9d2bc97b9f2d8d8c597a8c6055e73eac3a8bcc3ebbbc220fcf4c3df34a70a6bddf40ea24c3186b3f9d179e4bf4ed7c5cad620b505756245247010f15344120ed92a213ec7da8e700a87b660c4fc8479cbca4780b398359da434de4b21b7e2af478b730718a6dd5b45ecbe5ac5179a0c597f34b3e662aebdec2ddda1300dd66278bfdbe5f680cd3c7f651114f29c5fff488a28abce8194f5fe5584f91184cc7c074266be0121335f839099af40c8cce72064e69f2064e63d1032f3ee5004209fed941bcb77a78af9caa88801be2df33bd1d2f4f634cf5abd4083d16025b307d83e2a3e675450cc892a05e0deab43318d6fd7a2f8b1ca126cd734928390bd3836fa897111024cacb5c715e445e4887e827ff9ead080a43968f1b42d9cff3d07316a3389aa49c8b28ad7df3ddaef48d0d882db727f18695dd609f351e0fd8362ebbcf7863c392132daf8e42365d683d54ef41fc3c3706ac0691177cca96fac19e16eb2dfd1e04e01d17e2e7bc6685812b186a8900d1733874a494a69bf3bd7898535cd4f55a9f6023d107e1c9b8ed58f1255ad1603b73d32f41df388c64f11cb6143ea185c0168c14429f2b873ad6a50530427e1886e1ba45eb834902595c24ddc97cb9c2842d8f0e5a5474508f9f514c864f411b443c8252dc825c128e34360e008a5ea2f4aa84af9484a33d9d58e0a86209961aa1d758baa959b9c7f32064e07404ff115214d7137b8fbbb5cb8c3522aba6d82ea9b2d762ef21ce40fa416bb7db8796e84871930947b1c02ac4e8e61e04687dc719aa47a580195a6f2897479042ce34391d67313d5aa370c3aa6ebfef9df76a1c9e4afbc2d100457193588e05d7ecc4fe855b7a2281423077c4967dee948fa12542f537b0beb811e4ab778cbe50680d38e410566f978902fbbc274321e9d7f3ca6ee7baef2c9e85895b3cba57571389f0928130a794e8d2a6f813dfa30e0eea88b516f5c6e4258d32da3b78bfce2c531d361f16b9dc44963093c8a31c1520686c0406cd0e20161dae6924d4479224b47a755bf89a9c0c75ad96837b920a747c325087047ea7d8e74382b3a3d44205c4794c237fd92fd8b5d8a3f9296931aa4f7df6fb8074615040302b132190a798ebf3d4911671539e0b2e27299fee432cde532cde6324d271253f05004a08c259d384a877cdbfbae2aa95c19e621f6922f9532a0fc1b730c7618c3fc7e1b087874f0e9f8849c4324bd2db1e577a3ed4c1fc3774e4606a7a17cf71511f2ae06028140a0a89af21cf371ef364a6d5addd45e17c738591edddcd1bd4840e319afab359a271768dabe23b44412ce3ee8fb59fec6272bf3ea4f2511c87fbabec73e5d72ef2a30088838b99223a7f5d618b6ae6503ccd29c70f185e44aa885f3d697d7df8abf1aa29e45f40fa1235f5a540e6e46f79b4a7067222abb6519242cc40cd8f89d4c39c490ed94e6c5fc8b54fd32dfee94d064f94fbe70113d6019812b7cc113080fed676bcee31cc1507cc9317e2b730d7e5c6beb5fbe1ffff23076ca7c589659a643ffa61e7e302783acb6d8f0c9669ae0f23b5037235062a74f5c58e00291c5c444040ed98ed823a3db82b0af75e9d21ddf6f9f0edc3f793589e9466aabb586e4b422875bcf5f826831c52479e85077df57d6a9e306d0c0fa3cab4cea669e6f18ed4df22c758005fdef6f64fdecbb0e96a6cffd2c783f399c893efeadc1c0671bf5d022ccf91bd57b2e0e4901e7c1f82d65be7c8305ccbb1c150b58ec98015611f0b729d9efe6ca32fd8325a7f10451be6b1b65793d3050de6c3d1590052aa12c3010910d9ff8ec474f2a1864300ac84881f9df41e700eac929e540a0998c0a06612e05c0c03a5d8a73d4ee82aaad6ece2b0c3f06a9a004b3f86dcdcc5988b50e7e985b4dd0025d039827fe81c25004103ad5493fe58cd13f869fe5cf3fb9cf6a5114b4d59057c02ba6f4f741dde2d910e00e0d0a5ab3aadab08d2094061f98c26344063fe039d43a7e48aabfa69c256df7c03da5874e752e7e5f9945418ef4bebce51066bd7a9040ec37a5571b6153016d2e7e716633a15b6782885f9ebfcd5f467eb6f6cbaf0d5ef00f13c197961ff8d5826fa673a1b1414cdcdde60ad94a27734200f598b7ae85f2dff4969527ea2b1acdd478cdbdcf2be672ab11e3ec553ec4419b0c7aa038d01728461445492c4407f904147d72389423b76f770b23dd51543f1afad2f63764716e98f26b440f4cf97484afe0d143da314981dcc27509332c5c7047eccf11b1cb0f82f023ecf457f9790428edb28f6f11a866e06011413050387804c86781a2a002236d38b8a78557370fc367ec980cb669a608e3a2ae2f6344f20237ae07824349a2d683edad3fb927e293a49bfcaa1e24b65579d49a874736ae0ada47bd430c20aec42fb725e7e8fe4148d2ec8e8d556177b1f938fbdb4188b4658096e67abbe32673be45febd1a675cb1dda912a56c7f63af379166288371c68bcef1a6b3d6138619f7bbf7ab46a754326b467c0faf91dcb7704f85b4c8f1d70c7a5fbb581f3008c4577ca87588036c5bd75a3d8ce4ee71dc33dc45c8d5662cc672f94c1b856f8220fee984cc96d408acfb8f075f6986f41bc5b9a511d5d1c6ef619626fff22badd9ecedcd8d363c7adc7709f411492bea03f35a4a6fff1eede409377f66f4393437e1a27f1730d641e77f04edc8f9fa94a4d1b77f6142d0e57043e563b2d65ecb0cce340e4844469d58027e7ae063fb67ca6449a86a638d4149677d4645a88406cc976d3a4dcf4b15402667fabebaef349d2dcfa4f16751104b13f693d4149267fae779c14ca863c488755c5e6906d8ad45f81bed9cae924212ec592a465775e83b5a59916b8ec0e57f72df60f71f800dd6e925690cd76660c7c21ca46c8a6ec89d8f74c26dfba58e03802730537e74e28c5f93ad071441775b226108c5517f8925dec033b17d727380532e98f7f21730c70910765b4c080272446a8fcc7ee2dd4d1d8af86c23604bb0358a2b3a73963112df63472d5c0ee117d4f825e7a27d3aef76fc844c833ad4f248eb14b19632290fcc610061d18793842697fed35ec875be91189333f66efb3e24eb78d5784b22814048744360e03f35f3e8b5bf0d6260614979d74f86881a56ec5992f529e1c6c26a815f88b625004b382473dd126d718fbb39fa8856a44e0ad516ee997194b7ebb75a915b1657440f326af56976bfa36b4514ac872fde43314057edc68ed7b0e7ebed8a4ff7bccedcaf1471b44301612f54e167c87f0941dc99f51966a04079a3388d963f9f5029e7a22f163522aeeeb7ee7e0ae03efa36cadebde0903f8e7a020ce72d074d063cd460e64e4c90817361ddb5fd838a658109fd3ff01f5da64e0298d6b0948b9896bb0b1796f25d8626e48cca3a08e7dbdaf8f2fb8f9f3ae1655d2f8aceff0c575706819184b30f9f8983380041905db56fc979f78010b3e11c8da7f565113f52eb93c062ce3e0c9aa4a95326604d945f385958cea72cdfcf6e2d6da79aa4a444aec9eef53579a8b6d4f76ce44c98b3b749d1ac7fd461e6a1acd3aacb161a123ff78a19b0267482278fb884aa13b1e89ddd09eaf98b01aac3ce4638edbe160fff3ae2f82a4c8911c4050dad893d356e8eea4d96d9f4b0cdd63313447b1c92ebcf1cd4c71f5b8676bee2e0d9885fae23683506d4297208b6188655f8a8000c10dbc81459e9ef97c4c455538456639f5b5b36ffcaa2629ef620dff87bfb93c10550f4137fe5853182ab4592a38093c3fbb2a6126a1cdf41af73ac80abbd2982710d3e242c0914f2028b3f2956c5e8f16f2d75e4480e8a254fdd501259d3e8d16ea1d122751fc276dc68026422e9a60f874df640cb43205a461f52d71ba93676a2d60cbfd4329acd2742a7788d56401668ac5da70850bba63e91e020d46c128fe81ef651a90ad3c5245d19de2903748c9a642c16396cf4e41614d8478f4f5f4babd5f77a9b0aeb1522ccb774607ee66f8158439b21df4116d6a19a25c138028daf14fc1bd66bc03368fc4812f4460812b26be857196cf8a4b9ea12d2fd0296e9c4ba0f1212a089ad423cf6fb04576a1176a34b44bbca54652b89c8f97e973e8619507103a230e0bf87dac6febff653c73e901fbd907083a9bcdd7dbdac6da984a8ec1cbd6cad1cbd6ca842f13fd6156f75b10e58a8e6067ba946701be18d679beb44fb5f16cb643bcb68d367b29420966283c6a6fdcf633b7e04b149c6a0bf947d21bdeef43b9f6f4df8fbf078ccc7a92bdba090e7a66892a8bad389a8e898f34fcb3fb2315f3c9273976e6f876907018584dc30a25be6a8afc50064c5c350046063663b1b10b35430e1a36fbe46318cfbe9c5717ece566840abd4c05e40533f13f0d547774dd5d36f40704f002e9ae0ccf8c9924f5946250c2dd01eb2dc8977660d611f4e846158c8db790da042d68d69f97c7cd1c7477af0ffb03b8b118e336734b113cefbe2ddc09f243fcc8f2974f7657166f1af0a107c6abbb031c94f6bc698aced781f781eb91c0dc0e0faee0218ed8767be81df8c59764d89447cf006870ce8fcbc494210fa475c308bb31e3e7a205c20181008040281da6fa9c4eb61080c602df86bb676b8c7f4b2ff90f3b7cc1c22d86793e0fda1fd69c3d547d356820a1910fa4dff3751a9d3d2541a55f988e1204db3217c93718223230ce61fc49c811fcd30d52036999b12545eee67948dfeb25a82cbb506ded58ce55a171b4fc0c5cbba6af97f16523f81421300e76c9160f9ac7fe1e5a918b98fd492a872dfc736e0ef52855af52fa16dd4f24dcef3d1b59e3da6fcda5e27fa9c93ab56ff13d2a9c266bfb21bc587af7faa40fd67f11c5e9321f3de7c832ef57c1546f517a51731556e0758aeb6f48a5b10220adf8571d8f3741956fd342277036086cf162734178e133e711afbbe138a07e5a988dd343aa229e39b25dedb774e682b70b27f29cf331f7787488683225614c786876c2c21710b8c33bddf7c817a362a41c2c4712623a86a48c2d9077d059437ce36af0839525063c72e34ec4b43922c0c4c0f395492fc2f3c66577e30779207984e9a3c8b7c0b4bd46cee9f662cb47c88dc963d3f8f8679834588bd18fbc1f40be6eca9cf372d371add6eea667f2ddb1426ed50f1ffd8a36e3af998c2f2ff3e9d4895cbfd313300640213242583247a86cb9f29e3f3e392cdfb7efb1c74b8afdcf705df492787b4d0b248fa5602e1bf678a898c030dc8d4863dbc19066fa44445fee4c388bfac9acafe2fbcbd26ee81f97df1a92f30ad51b420f9e3b86d49c39c6f991d3e3ed4db1b096f5bdc9f0c842d28e5223af9eb0019da0b869e28010abdd1f7a1f259b472aea6761fc80ba668b63dbeb6e402cdf60f15c97f5d00b1aef4cefb9456a1f412ee46d48785e384e761079b91f4988df97bcecf704f2d43f927f3716a282a2c1b89f9811aad94c1d5109eb4dad520d5c1f1c5a3596e86a6b424bfbe9c6d47415993edc49ce941a740ec08fd936610785db1a869372c944e933afdded73fff89388803521a9fe71b573c72a709753f8e5fefcd109ad13cbb66361aeb3ddc56617469da0152adcf17e892526d6f1999c4681f4cfcabd81e73867d5728fb191ad849d37e859f4cd6d316c56ef8bbc35860801ddd90c3935fc4e107fde0417c8183c620fcb1ed7e4bc6f47fcbbb5694dd5f8014491c6a1d22cba3e41f2f2ec4fadac5149d9ee6ae081dc2dd8efac22041536ec64837f1eb7ed7df5ecd9b5d640b95d9495a4cb03e4b9ae7fc8dcd8d7617dcc1917957f44f7bfc14f08cba9721fc2571c5b50367ca92608b0c13534f6ca1ea849282b284fc7f39c47fac775eda2cc5bf0dd7a51a30545e67080ca0390409397c75cbb1c1ee21e1d9f4e4bd5b6db7448b19cc5ce1ec417504447101f7ef1a6026dcff47c040b4269f8cd6a76c27b4f819c1b3bd42af5dd25b49a33431772ce585e6e37eacfdf49f666bf87ae16a4be50fce63087180f01d3e841e3be72bfaed93a2ff029270f6414b7e2edb334cc57cb1f68babb24ad5be0bbcd9c41db3c020415f45e7b5466fcfb21580761ba1a895fbb9b6dc5438deecffb90c9bf8b7051e5a1feaeafc8615c3c8e8497e7381b5a02f60b528eedb1899e4a288681565891c87363903ee37af2ab4f987d88393c98138db7fb29ce5047a62d464e986949a42ca15f79527bda6406b497e3c28106a2c39f6844d87da7dccfe37339a3bb9f330c24690e0ed8e32e2b4ef2aeff1eb0bbed4ad22cdbb29aa7e6123656a06fa3739ae55b64e2d79c1ce0ff8be17201036f3266fba340b17c6292454792d3bce6f9ca9f0ae7d7a9fe9365f7621a3574c8c608b128f7faf14dffb64676cfce3b8c3aa07e5e367435e3972890a7a91ab80002870e31af7c77b3160785aa20341609f557bf2532c24d18efe267ab03a86b2c7a46a6515e7bce7d2d096378236413e9ee0b1cfa1c99e982b8d0dd8774b68614438d524818825767cabb80f97de7c440b17af0402a9bf8756921c0130eca732722df652a32242c15c01bcdf92cffe0cd0fb6085bfe3fdae94eab78a061cedbe26b49cfc1c8122fc4fdd72a869ba2266d4fb4adebaaccbed96f853fef6b007fd7f8e3607bca7dd24e7641ae91e3b81198c706e4c7f9e916d2d24fab3a721382392940f4b154311002c359f1ef8df775ef05784ae2bcf540042d4f9afaaad2d71a479d6e4cb4d4d1a40786e869b1a7999a012f4ec3046d043f885e0eee3dfe3fd022db6f6c29fa0413dc3ab99ac000d64db2c2822ae8f5b4d0ebf9deb4cdea992b445d7a54cd6464ce6a9e13e651661df0a8ffc4937e9af9a92cd938fddcf474922b18cb06db1cc727907338f6ade09cd7236d280d458ea86e45633e2fee16b119ec1b3fef1347dba1bb95082818567744da18d2557c0ac42a72db40128a0e9b7314eef6d0d73a0ac51971037b8b411305bcf5f72e6d68a40a92454190ccaa2fe48a7db61ad54fd2043f5bc942d2c82edc8c2bfadb36883cc52352682ff9d388803e2f8fdc658f0a45a42227af39c17d8ac935749a2fc70d65f48cabcc5c4c4ccca000fc1d3b93d1a8e011949f6b81fdcde144c471c9cf080d6a58475cfbaa42d8daf33c91e5b94ccf27ba5bcecae56feddeec4b20bbcb23fe7002d565c908121ce63dbafc8ff32c16cd85a8480fcebdeb5e3819d86400f945596408f67f8b59929fc96321eb60d2830974ae054a8fe71944495a03bd0e7f23587c283577e3149c4d0fda481dc7822931d25cf27e48745a962dee9bbf24f792761ceff7df580cfcf79df48ba76fb2761c98bd455be10e1498d7f8f24d187e3421513613bc5ff612e1bf552a675ce74c58433432ab82ef7fad66d3518122c1a180807a56a359f69d04a3809fe0e681f3ec5422c80e9734c42e65246eb8bf997f0fa7fde637d45de220ae7bc34f1c7c89adae83c1fe09ece714bffcae674d232704bdb4e5cbde6f75a598e8f1eb7008703238b3b4fc0d5e15ea19017b8c7be04830af86fe511d19cbf027218ed7ff595d4ea63d673b334c52baf86bd140950c4e370b093a7c1d8f5c0c55cffa89a3f0f50520f960f01450152dc4dc1c1ee67bc229f0ec2fb5fd04b0092049794947020901f829648011b8082047cfdc080692556a0b9c16c52acf5f95280cfc92236271c994595d1c92f1634cff99b840d9f5826ccc819d3be46c7e6a64f209c55bcd69fa3ff73fe76e36d336d0ef95e7379598d761f64b0ce5cd74fc20937f153e9c779b12b4a880e29534499c11fc5830759582b53414dd821aa23f0124ee0d718f404bf5e104e4fd45a025978f7518720ad11a7520f91e91430cd9072aaa143503808be0f91c643a5b3e1cfc0025fe792649273ae99b980ab11c10fde87c2244143e0529c6f23bd0022e1c42ebc4b99bc6f873c335ec92cff94d6970cb77573c6e69f40402aaeb00016d46dfd5e9022135df8f64e46dc61d1af89e33f8fb3f5311b5041457d9169edc88c63a81a8c1f11e6a3553b3be60317363811d62afc2983360786da3b05f680f6e1536f88035aac1144ac247ff5aee583b61ead6f258b477ef14a1f259ffc8604ade46809b2004c0cebf31caf458c24fc980e675fe0564e3ddbcdc7b2c386dd7f3f05c9ff2794ea5dc4cd11b4185c5a950dbe4114e4f32a721a29e666891aa7030bcae94abac3fbd7ff9908e3d8e296d7f51241665ac67415145c3dd46720d7bed7a621e5e173a6c7ba8dabc480f84f5eff4b57ce7817afdd152d44610209536113312777bac2036f1eb79fbe65b3c76e13235766df8589db9946f4c7efab72fa6149880330c0bcf7790e317d15a3fd071b57f7bb756b77b2ab9de74f64de040912d373878f554015af71e1ccacfca418ba4b9cdaf199354da24796179ee599c5cf9cd15ac5f0b1c3a4516d523a9c2a2f7953ada18302efccb6bd227b49e271afeca149a0b73dad2d7c0230b2f80c140134cf040fe1a98d70eeb3e8e67b7dfe51cb26dc29f3895ed2dee3817981bdc68586397b9b94a997488abee032a91cb3a4e3a4ff1a74f956e76470423769798c5d3292e0c6a3f268b22403d8e6ad09726f7b477860f3567d62fad3fe6ffb7b0e6a70197e969d630caf0592780fec5cf571b1bbc99a8f93fe562f4b785de950c28bd5c2b7695101c11656e29cbe51b50a959b78aa5d523a24a1ec83f682a107b911c942916358ba7cd612367e2797f6186e12fba94111611b109296b6bb50011c87d466c40f5d563e2c1fae0378f4c325f6223dc5ec268f4a8c333dbce0ba8e0ce5c503bf8be34998b655bbc524d25575730f2b62afdafeff8fd74f4caeefbbda278c7af3d544045f46617c52432c40f5a7cb41131e411ef2c77617ae4184d8323b30bbe8e79d684a7abe48f9ef1fd2004c7c46fb719c75fd3c3d7bf2d0ad4af2e11f88f2df1ef5ca03643955a70d946fb0cbd3c90fd93e7c2b76fbb3c1a5580216837c68e3041244fca13e013cb4441276ad7282f29fcc2394985885e2752950d29151abfc1d9d4855c711944aa6e3c86dd334684f0139608bf1e3e270f8f35c4f40b6af32e5443bd14cbb6f1455db2a9ff49f3b7971fcd3344d830f0b69c368d27bbc8dca2e2763bc338ac30b8c2f7ab7a668721db4f07cce5413f647c1670bb60832b429fe628e7436770a78bbe374de99e47252312fda2cf7dcff87b8ca3b2d709b3920adcbdab99f881c3aafc285a01d4f70cf65d0f4cbceed505533bf77f72c43ca81ffcac3fbb77567b89fe61f71af360e1b03a4fe2ea484f05c8b57f84ac3ac05a546b7bbfa64ef2b8a755d00daca0a735543107a0d61d303f03daffe2e3a1def0f0f84c98610588b6ce7c68955ebb1277ce5ff521c6578c6d583810f3bbd1b811e16aa1af97a69228a6f250ba200efb876d1d74bdca564a64b62e4037cf553058d49f47717fb031279c8267faac23dc6aff61d77cd8eae0331b975879b6faac69c3f735b62227f72cffcf2d0024805e75a025dfaa2882de1d03ff591e58d962fc766b95ccb9fa1f2fa71edfe9b250facfb20b0c63208ff12875ecca82fe09c60dd08d40336f94f4fcd482c9facf5756c60c59d22ba4fbe9fbbf45244b6ac45bfbe5b84b8826504f79ef65e45cc0bf3c5ccaf312d2bce39b3b78d7348f593f00c142767c8421596ce809d459e098a804cf2024c42823b2147fde7ed9791bb4f9686af632e89ab83711582b6b83b0e908ae93c1e3309e3f5a85780e39b5dcf61e9b479d89e615fa39f0b3e56702039fcf691f89814acda5f90621cc4069de93029c98c7f06b82075a96717bd36eb75f23243a9c6a56b471f6a4c55ef8afccc1af83477e642a1bb546b40bb7eda9eb8d4a9777eaef6294bf8bc09fa69e436206b3f115949b1c4f02c2c601e3b744cc664c47f7c518fbb465922e4825af1f3277928ff1e84f2b40cdc7782830579aca91cc599f5ed046579cbc01d0cf3ad683df7828fcf7671f3bd4a1537a01e9418867c9f1a9005e9837c2a64097d70b126341c98ec492a9f429b38f5123d155813d801096b0d1209093270a0439004eddf367a6ef4b0b2cf2b6f2e32bd4383cbb16a7e2f70d288a11bc48faf13c6a1c310689063ac02c572a08213d0310ade35e225a56b85550d6a719f10173448721d82ac1a8253e6b960a74f2c1188627de05b80dfeee19a74b5d581d67f2edcc390e831eff3ed3861eb5b22ccae42cda1f3db22b06a0d2ca4e1f966b31159c714d6b02624c0398a0d4b1171c7fbccb72dc692549dfa261301ebcd0331c7453887400f075b3710a060531d260e3774938431fc052850920823b2dd5e8de105d31e4d02d69fb10d8b9b7b30ba58984e1e729fcc0dd9032c26c75c82e72b0a3e44c9d5ea38f04c0fd075e8933672bb5a11b2006deb9b7823629fa3e0d8ff7693f40939f2f8342ec116ccd050fec0b90fbe5cbb1407029a4ea7f79cbea15a42a9f8632fe1f9d2c74a9be75419b73aa70c5f0b2328cd4428dfbda7ab9ea06fdb059112f6db0f41e174028f293055a7a0d7a10e52b50bbe8dfc5e8c290e8359201d9c0048fe39d55db6c668830d9fc4b981c4c1a19e1b48738050b3ef27a9a77dbe545cce483bfe93694ff68bb0eec09fd5829ac05131633f2de18a6a987db9d16f0b0e19067f82c261e5fdfea92de1657b1866f848c9577ec36f7ef0f3ff5dc01f4311408dbfe45586a593f16ffe6f040a7a3905dc98424f315a94f7764eba0d21c88a4200c36b77d65a6debb58bbfe4f87caf7637ddc4cfc0bdf490bfd1ad5fe40d739fb5bbbd40d06737708e7957112f30724c663671be764598bf9c987f4c3f93d13219e38cc6830dffbb3d314c6ddcfdae4f961eeccf2bb9318b058194567a4a39090b7d0b7f48e8e40c5fa704dda42d01e8cfb3937ca91330b18496d602fea3cb57a64a06a1740ffb77ba9200ea4242fbea9f15505dd04abca7c1de4387cad38908bb2861453e3857fc630973a0a45377386edc010b442c0a306b9c14acdffaebaf6f24742b85366d338b78bf44b4a8c02ec7fc57f857e7ca8f3460bf8d5fe46c7f913d876865aa9730ead4416c17cbcd754b7ef0ba32d82de1adf2d754b3931602a7660b1591533aed4b533b8f1cabc5bccb2c0f9779c55385e1319643a15a28c7d30f7614dc3722134c2f30bbc5e419bd863e77331d347c30a653cc68f5bd71505857ed9ba57bdcf2e3c8d4292c803ffbf4051d3e58552e522aa39ccba2f0cbaab7a64036f4ea8bc785dff6721d520facee809579b0ea44807950eaade5441d74cf6f223d66a3c8684dc4fc2289c354b84c8ae8819e881c0b7f802c74d9e890f2476f1081b20adf3c23bb38da394ada587af8d87a81142295d52fc3e2dcef7cf4f9fc77c151fa8b6fd9ca2f0577b5463742a61a92407e84b459531be0f1113c04696a743a0cd80c5dd09bb137e1e39ec31b70503c6ae75c3ddb37a3fe462740ca7fd2f2e0b98334a7731b9ee62102b8b6b15934dce64f7f44ba8f57c48f5899afda2ebf9a59e71f4cac33e8232a7d71d71af5f9ad99d10d7bef79fcc5d6a29943f51059f1b0ac05fa2c66679faaa80a5aca27bee65e4216281c1942095c189a793fd1964fd8544dc1af36838e0c6df900864bc46d36188c83bbc79e9eefa1bbdafa58ba5a7a3bb35a7939dad8db12474311403364e487c520ba2df2d12d41dd53cb4c045ebb9eab3ee65689e30db9a7fd376a40359d56aa7516af0aa2b5388b608fb153dce96f118df961ca712a54dcf649142f0a0aee41deae47e2dea2c006e000ad7b19e7ba9a2d61d2c30c4aa29b049fc2d5b88e12323eebe633531ec6b553ac2c678ea189c017b4ce65f8fc952a118da85e66d81d963784935b408a2508fd94fcf5291662012eedbdfe8afb3ef44e12bda797aaecaed7e1aaed5b89c61be7c31c7279e99fa7800a667589b87178799c8a1fcd13081b13c3b44503f3c2677bf60757899c54032e5cfc6203f07943d07a9871aeb7d912c61e33e31791b2804aa2fd2324952b28b8f8b8ac7d69c142a0d9d10e5cd9d4527db9fa76f1cb6b5a72f3636830f59900d9d6df6fe8be435bb8f66bd74618dbe49f46062508624e44ec49758d259eba3f9e2175fafcfda76d1f7fa365ec0d4fdc0e60f18daae8defd8f2aea667ceff97f746ba4ad4331b5e670663f1f62b7e6429168020b5620905ce16998b45d7a30f0a425087c141695afc1976e1f2e5a30257cf267582d2b0ce20fe5b3f81c5521b464515fb57be0feb49fa7a438e0da5d858f992a7da14398df1c85bd7fa34bf2146b868352d3f3682978dfbc0f50cfe13ccafcb617aa2be16a7761f179e285c4368b301a9ee9f84d3d471ce16ab807d137816f03080f61d09b2ce07c53064b98f4308b0625100f3193c2c8721dfbc7b89cc051c44260b9073e0bdeaeec1b3a4612cceb6c64dd8aefcb27142b520651c8899ad89c71dce055d4f7f26a4863c932c55bef7f3845d8d1b9179b373f5908717a581b96e1bbe13699017c5a29158803849f3973bb043c6ebfe90ad62bf18f7f6ad0f3be20771f73587e5430adea6db1a43f8157434f9b833e6bf347b0b853e9865ffec826fb413409cadaf9c84b7895194c55087c29801416b0bb3efb94d2f61c6d0d3004a3942975d4a95138c2116c16bc9e047c048afacfa685882fe8f7c7a9cafd6ac0a95679bda787d3776744ce2979bc94ea9eb5f94dc609d03e68c93f7c87defb50bb216d33672c44c324d2947888e4da56207d233275f3323007f403b03361058ceb16f259a7148ca05812dbaa0ac3c0330d995f7725e789e4af7063e4c2107fe81718bca8f216f8b6f1f5b89e4e7dcddff4e83d7c11e7168293018813f35138746bc01e5211790e1cbb98d2fd3d3a1882a9f740e8bac4504f146e5dce50d3882004fe347a085d38c0addd6228026884fdd1e29a8bf799caf053728feed793651ba6ded4d238b7bbbcd1f3e79f83d900ca640f7975c23cf552fe1d1393e52a1c01c80358458ef0837f4b483a697c60ab0e5f0edffb3b372c0ff58894ba9b56954b9dc1d28b228aa81fd29a334996b699d29e98ca2f5a073a732e7c1df9382937d6d77d7f70efaa20770fa25c8f2048467d72469be7e7b4d3560c3e8468ea125558b4a812d0e1f3bfa339d59e2d428299909f64d663a09b8f639cb36ea19c08d561309fbf3475666e9d46b0a0a2fa319e1dc26b0c5d9635163bbb271ac73006faa3def74f65c46607c3c8df834a04571cd39126e786559726dbbde25befde6a2e53c4a796a657e9cb26e808b0d370bf6eaf973e759cba0749c7550b9cdc74502c693d3034b4d6dcfa1f183dc2dddf36808469e13016465af8d2b04b598dd3da4df005e265f7e0c989943039af67922c9c67316d2341699f1a9e4560aed8d9f1e83e4a31b0168f89f01898d33662fb7af24660f9a5c3ca3684a1db8cd97500bcc2d7fb59c08f4ff81ebc68492ab124c48c720b3fcdd99eb830311f885a302974bde190761d616f9894a15a645fe30a0a107a0671b978ef7e8d20fa22ccd6e1dcd85f229518f9e7736afc746ba26c3a194e0f92e53006d987d9bb0f0e466e9a49786f4dab9b299eb0a5d36e65c8e2c7f20260847744d8a5fa64b088c1c10736e6fd0f20a944bbeeaf3e9481c50228c58c2e5bb83104fb7e91ae89bd661b8f73df40c7a8493d612f7fe2792609a19b20f664e709d7adb12437361b1242fbfd4d69009e62010ce01330edd4c65c937023042cc7924aff62b35d76adb7d917ecef635fe33c34de03549295b686d88513aa1979d3440c3248cc48baad56996843508308a3a18c7009e262731b40c6b470bf712c114b52daed1e9809e39bdb89623dbf1496d209657acb1a06c5c6bb35b819094afbd4f12cbc2ea7dea8aec1d18ae67225ab452bb1708b696f98491c5e4f734be59b0c15e14277588c37156ca1de28cb84d24a833155190a71100bf4e73e7cd59bbecb74d2abc8612fb52ceebe0706a5cc34650fbd6b5dc719e69601729aaa06fe4472f9a1ffe16abe3095e45962738f08189693f4be085c94fb416bc461173755d5e46d0f9a0579d57a58577dc991fcb7722a50ad86c534f1713ce4833f7b4a3a0db27c1afa363b8208a6b15a13dbeaf22e98ca81f4bfc92e1a490e96350ff2326bf3ee2bfd80bd6b5d18cf90c104cccd7c0441ccfa01ba14a91423bba4674ddbe5248d203c333680123b9996d76d29c6fe29eaf6e3e827a92f425c6acad6ea12d87fd07cc6294f2b76a4589cdc8c04a57d1a78162ce01dcdf63fe22885d8d54b53e03110ebe7a9378b8d020b7c4d289fdb14b70c5d7e147c6f2102934776c5ec380f9c9db87aefd23b4961d07cd6818d92a2e977c2f2f782ff37cf747c3546bb76c30d121fcab4faa26a59808fbdb66ee6497266517291709babd9b5a92401f6d72e10915b90d067062c82ad1ee8e6542e94970efc2ec5a170a11602033071169bb216cbd08f0bdd8b1c09a1a64f9e79ffa4339028028908be8c621f3ec5421c00fc375a71d9505cd2f6c697314a32244f09eae1aa4d7aeb14b03e1ada2936a00050a2046d056541480f66d00c412fd5352f579b4ff9614be3c552bfb402689709e1a2371b40c5b47c8feac4d0df4d4b24df6e689c3d744472397f2e14047231cf52f6c7874261b1dd8c04a57d9a781686a8174d3e74f768852376176a60ee7c10258d36266f18621eae676c0b0c15754ae3c53e5c21f9f49ef224e158a8c1b3ea7b3fbf19e28069cbbad79ba4f2a148e8c8d0a39e5959ed3f8cbe93391f5a394ace9dcc1f45b0fc4e205a8f2e5cfff5e73c2fc5eaa1f1c05e1ca49211f22fba848c9dbfdefe7f40550fae059f01cc1bf405e6291abd1ded263ff39643f7e79578e867fd755e09500f4c0c2c420ed9a1e2bdd74d6b192c606044ca75933aad7d19edcaaf64d171662c779a4415088aa3be30f22c710391d3811e8c7effd140625388a05b1f75db17b236d9feaaf3b2af88e28203450bac9b78b5d2ddb68455ed87362247f936e82f030d88d5fbb0955b065961c34a7e316da081edf8750498e302c4610d22f96199c9fa3a93b4aab4255b3e2945e747d61604b665bccef460b30647cff764a001fe46afda605ef68ba1c483b56e99346a631c0aa51ed214ae7feb21240bcac52de28da246908c2778c68be8020d5964f7ccceec56fb5b3315d60777958b6efe2b45b86c3ea48daf05a9bf0b497102bb2aa628b9cc08df877f01b27ca0be374536051e92d33b7f0cfa3fcfe511f14078ea7c748d54eff84e175e7dca4c98e4f0a7a106d7f96785a4338f7fb9466ff1c6d5c11cd017300bed53ca6c08ba1e7306ccfb84e9305664788ef10e7bfb8af935f582ed23bac73cd36938646b6037f4ddadbc1556ffe841d629823902db6fdc4598dbd09f85e14a864b25502ebd4989f9ae1d4012594abaa9336db229b03b18d6c057b3a6db4d390b9957136b03782e0c6ca3e76af8d01708b6d3c40c8314a585839cee2069e7ec8ff30d1393d7e0fa8f171b8ee60287b8af1d31e812a01e7079f0af25c9230c0e785acece442bdde52469a7531a54c7e63b78d3f8cf78017cc27a3e07a63d15f044275239f834a5a302b27e9f4edd4a4e17d95492603f2cd98d4e35e44e3a7b13d8c7b778b0d3fe9fc24be99cd0103d1086c70a789595151c44040bc068c9afac74c3eb52eef429b730a730126b4f5585156e9f84f5e73f3151c78fdde6d30ec092e6f9e10d714f73e076d6199bcd82b3f80582bd452366b72c676054bf26744625b8affaa46ae7f0997fb00c33232587b87e84421b4b5bda776a2982847e39dac3d6e5231ee6fa3fdfe36e7f0f586686ba4fc5719afd4461b2333708b62ed2fe9feac53d7f586d8793c7d0c8c1eef0bfb7fc58ca8550b65aed45f4c7dafaf12b60c8de09e70f57329344ce2e6c68f746dc1734a01a6f4956117491e831f0f802ad9818020333bae53f0e5464f5b54885f278faefbf1c0f609b0ef9b0480116df6a662e335a00b782cfeb4df87cce1cb135a4e2558745c330b5b4e6a1a3be9fe462c83a5bf17e6b31ec65cc8625c49a266de3e97afdcd697cc1986c837e04a80756a607363a8bf9289ce62905d5dbdddad9d6e7e7ead0b8aa5f360a96ecd47fa0b4d2da356c620bd92989cf3a6c76236459b4f7ea46e5bb61d30ee611c5f6febd05b01e577c419b14c43db0e7090cb45cb90fd789428f48b86be842557f12ca21c8a6cd9d187f92ebe9b99144fa23dc1f40b77aea80236c50fda990c1d5e49b366b0b036459ec189dc19ac8bdd01a2cb8dc17ca66f9a4a72a7a972d0381e2d3cee38f123ebb6becc9b45d3232676d498f81e3bdffd65ca1de076a3f2a30961a8622009cb5fa09b50ab7cb0b9465b8dda8cda42085c116c831e47375f187a306fe9529e07c7758d8166f7fcbfc25e3c8e42d2aa9bb9ba4d2e16b563edfa9a56d619bcc6770c5ac36808e69a56f7534c5248dfec7139a116f85b890239ecd5137b184e7cc5fb77ddc52db60b819094afbb4e968106e75de18a5c23651998a2aedd44e18c654c32c4ddab875bfaf282564e80aeea5b1b9acd397ffedc6ac0f47d348388908d4d3f37bdf626f60b6bd3b8f0e100dd0e7fdd7f113c9dfe3fe4bf3aba89f80e68b9709003c996fb1869c89f1ee9a820c870351f6e55b9df1bb394a4e21bc26c38284125b73ad4ce7fbc858d017305a147940ccf0ee7b5d34464e614e15b6769fe75e19ec4a7433fbc81e3e8baae09fe488ee72b06fcbd830631d21c719409ddc684245344bbc25a0171a8c193452e50edfa02f5270eb489fc8308ac9b8aa9f12defa5f5361e8ce7e361dab37468b707110b5c8c79a447b175cf3ff4b2a942bdf78738ec0d0fc920627ce445c0896a963931f7f02bf98bf8e0bbc23e13bbf3d26c97ecdf0d1fdeb72c9a9492c678e027cd402383466aef2878e6904828a2af546c704ab423d18d43988e617c7c3d387873ab85509cecd873832964756bc93ccecfe0bea5884d47874a8abd2197c1283a4f1ff87acca1e4817c8efaa967d65a8bec9edc0faa5564ced12894031996da971d6fb7a3578a53c3c119c1eae509ac5db65848f0353b572c8a7698c60e9cf1315000bf4dbd1e92b00e7cf199b5b505a1694871a7946e5936c30270033f461215049792e8ca885570c3b27457e97ede330493c9bc851cfb6c2e53f104bafdbca73c1704e80cbb941f7f75e051117fae7ec60146f31a8a551ab01dfea5998fdc1bd5cf755528198e9abcfc47f635e404dcdb3cf035f7ff0d41b2fe1c1f7a464bfe4cce561b2ca28de078d07f907757d0f5ce4cdb318d293251b42c08581115af5260c8f1838b51c3ef01f4ebfcc8a207ca0f4709ca9389eb0f87b94abea643fe70668f7b1fe60ebdbdc8432a8cfc1d22a11cc6206e0c86362280268abaef61c9bfae5733ab67ff9923c99dac96e6e353d6682398f9e57626df03f08a0f03ff58991bb12975a8efe25d015fb1f06d196c840a9f47a53ef018b5d1fe5375c1a8a7a0c4aed40af8280f355132c603e61304138c8aef7cefec4a4ca1e071354d645df95a0a0922883c12cb88ea77458170c6460e8fede5b93bcc116ea5710dbeaba1834d530c6c4cfa2bcdaf3c1512a0342309329e29701359726c23bd90b3e8118a79aa4d3dc300b865820d48d91dec27f1a7545e9eb0cafb0342a5dc84ad5427889429a02c29a231bf25f9e30000a79f69902230c84cbfb37674c447e141832997eb598ab4fdaf04311c073e245288bf3b30c878e2722e9ccdf9d069649fff0fbaf7bc2894e913c8b134e00fd1fb41b223edd3aa573a3b6fae6449e7edb68946574991484a760bfcbc413ef1ed8d4def99f890014f202e58e2a6f613b9216296afb7386237ea58ae881999a6100d4050f94f905194da24681ba1ed11a6eca65e2ff0f7ac3fe6d8536b646bb4714ffafd0bf83cdb118478d6d8e8f89512e42c8bf911c82c0b32000fe7468d95156d58bca19045207016f5df3702077614e46f765d9b05ed719e12bdbcbc00317acdc63bc5e98bb0b24b8ce546d94e6c2543d6afae7c4adc3bd73beb24694ce596148dea59ef5cab3d0d0b411a1a00e7020d51cfcdf1b04f15b8b09a840be1a8511f41fdceb5247316a381784dffdfb7508c21c508a97fcac1b78c7bfdebc3a40b03d18e8ce60a5ac570d5f73b5fba8de4ad69d160354438342b4ce1d7f37105a5320b0af8856dbdb5a678a9e05c805869f61592146ebca2828e439ac934a83c63316c5ba2c1beae74bf86e94cba0597d697ae561fcd62f6f2c730f70c3dcfbc79ee5b17688f3291f5dc4865efff1aecafe1ef801f84f12168815e1301aaca887be0cfdae734c0c7d8b2aad5517b9ed106cea9437877d21aa0a0d6d35fc9969ced001538529c67182eea1b04df5a14010d48108140f95b619ef038114d1a98d652b2d278118ef612885528c0ff267acfacf3f0a4a5b0d6922170e4500095a8fe982b843d3e47ffa93047c700a4c8ff71295dc3e604ae4ff0a25d1e0b7003cd51767468427036550337caa0be2eca18c0d3bfe343f64232d6e89217e5bb41ec8290806c413de4121cfd7d98216499e5772de60a3bc88ee187da1fd48a4f3604404ffaf214f1cfc844df43450f79566da708c150d4063003544539ca4791f8a0024c2aafe0271ef1cfbd4b1697ba489357d0268d935a3a661acd5f5c1978fadb300ce4881b9d0bfafa9abe113b9e2aedc6df881072e7f7bd7fd44c45ffa82167826412010080402bf4daa13bc2b4d740f6fabe7df1f5a86e8dae0c22175c043cc02b682899f459341a5c0ec855fbd034d0c9d07a0e352c5500410c6f0ca64636251b177a01994bfd980e192696e1defdd5ab46a40d2b03ffe710a087fa51bb1e8271724fffd725196a982c6fb5be791f7a077cff69fea40c7cb7e05fc97db2924923c66899eb7ce38f9cf8de44389f9e6d4ac6ef327755b8e78be3aa7ce9a4e386392b4a1aa14c0a8920f4437b9451f82124488584dfd988e62b757de393852d9c96dca3ae0c32d3bca99e07da1232e8298f78e785769dad731656a041bb1011e8a007652afb584bfb4f439797cb64f4a1017758ad1074d54183d7a8f79efc9c7d5ec022c7351cd57c45e9e8781baa1bdb9b5c9840e1f1feb9286787fd657ac2b2d37bd550989c8c23b82ab5a77cf6b113f6a2667d4e35f3c012680b5fe7cab937a20d03fba7f731e4e12fb04b6488fa606fe7789d1211c3d4a2fb802551aca7ed60838fa995d2e5376218e7a8cbb926fe4b54d84ae1b4379d43cc65767fecf62586884dd3e21dd3a3f94ba7f56cd68222a65e9c49f3c88a1284793f47f2a2f5539c53c5cd32f33a952663d6a52bd1dc27ad548d6b70448aebe2e3e8ed60e968e6e7cc339f9ba7ad87ab1d906583b58baa18aa108a0682568673245e22dec7f09c12cdbec05e31359e913f246d417af1307b0e2b410e095c08fbcd1d6996fbc3134fc302019b45120e8fc3df94ca43e9bbda20adb747477ec42c0f2cb6d57c4840f97adab218eca9f17abb3d7e72cdb4ffdcff15c784f62cdda8224c4ca6051bcc9d6510a9eafd4960331e87a5b33def1ff3177e00e9a87487cd9b20ca0f71caed70c5fa531956df49981b787ea53b3129bc704acba6243e5370dccd1fd1e78483ee2a361435fa0e8510a0377c1fd160ceb8a39adc8cbaca26c4656b1d42bc1a2577ab905173645cb6cbd00bc327fbcfa512e9ed03752059178ab970f0bcf4bfe232e10181c0c07038583c0222280e0995421dd1f5da9bb6e8eda1e847b320a4a8d2d051929b5f0d92a5da9e3e15f08db54c59661a107049fa531c732fbb5b92b6adf1797e4642ed5f251c4b9ab60e0868d8a74f435c6332b28953d924f39682d2685c6778dc06926748e3106ce9e2c2610a386665e47158fa54e5931eeee70f7a29a5975b3ea535368158990dc4f07fe4e7943eece7afc96e8d334bcfb3a9a67d9121c35e78d5689f368da863e2875a54a0c6fdf355f35070281407c85d7d4f296f7c6734670f2a15e86f55c7eef8a57163dd86931504af43a5d788d8cf4101cbfa74bd67d32eb5d8668e1949b714015049f53b7666a62517f4921e2fc355ed3ab35fdf594a85970efbd5ffc3aaaac33603a5f304379b751a3a569bb8f241da6e1191a10968d7f7d730bafd91566ba6c3df8a2f5f7cff9265385edcaa51af2479d0444a27788afbfbcfeb588b81a2b10d1d79ca13bc51e671542463ae77943070c67a9f4d9f0a70e77a881e249aa1dde87bf1f908bf39497e63c56693b55e24672217b97bd40361ff4cba17c0d79062927b639a33652ede55a6cf1d89fe63d830636e5eb30df13e221c24d90d5c3bb1e884d7d9ec626642870ce56095a4c7339609b044e1b3d508d06ba2fd40abd854d8ff16135e0ce2fb8d7133531edca78b7282d32d483ceb62aebffb61d0511920a7f969e71b210d48d65d2d2c599052d57fd548a77e9beea14733c32af5468b3c7a974565ef224b2e1134f0159ed866251a22569b8180203b672703f15b99af0bf49c6d38cf038d090389bbdef9f8cd1f5e7b3609a7f6a3d07b41bb910bb2afcfa117ec87f2c17c148f611d7d7551e472edac96ef794444c0c74878092d485449a304cd34360a0ab783b26139abaf08ca874218fc9496a396ff72c4bea44ea8d137f048359dd0ed8fcc56178e8d2b40e147c6654014b9ed986db0ed91f3ee4c7398313131efda97ba0233d055e8cbeedd190239657a91ef0507f1e8988b76a7ec78c48ebfcde310fdfcd484b8d548610f0f879a4d7683bd48dc959b8b860cd821b80f48cf2a50babf4b90f1e2452114ddef0e6d89761d028b717ed5e17fd37f73fdbe27427005b07f3a93e17c754a83699cfbfb43856d6ca5623de681f1cbe9199cf598f9cfe3be5bff44721d9cf60d69eb618076060cb726e11a5d9815e267b5557cc7f1ea370ee9423a8940d51eaa5ba6bcf7bd40d30aa602b7857e1548f17730b236992ff08fd5cd4d1d111db49fd7f84f2e918ff8639af45d77c6e982a7f7d2122c24f595f30480c817908cb65881487c0a58c10d8c89c65fbcc50674d9fa37e0d2206ef4c0a313d57c52fe8a25fa7c7f500fe7257c3be4238df89d139cbe218b79d38378d632a9dbaaaeefe01e2380a7944716f274dfe64c01323956b54585f36d1282df4110ebe5a78a5bd5581b465c0d532e04cfab9fbbe325a04431500fe8f7da4eee2521c9e8734ff44dbf75661ff1cf3c7f81c5d2ada9014036d8dbc009b5f166ccd1fc9c81f94d4ff3907bee73e9b621dc351fe329a69940ce745107f32cc92186c526e30c79e1f1f595625922ac9246480bceb667e93e7c9164df62ab87dbefef9c641811ef915f0b8fc42e9b7f551107697eba4b33343f70f13f68f5bd17756b4dd9e99c7dfba8d93b6adc1ab3ca011a0c92325e8ea0b8706e25bd571641b77b079997eb6abf7c8773ee4cfe798087d2e72e6eef4f24669b856bec48c75397b47d0c56048e4d4136f85f90560049df7a47025bc2d076b1bf659b2308d7f9ff39535f5ba5c4dfba2c664f1fd18f68b08421e6bc09b7ed95176b2722532d924e8db6df2e73c20f29fb53ea2c4ac70d94675ecf37b629408ff6a880318be6ad045f4420d6902f5566620ed9e685a01a3f76c26de9a5d9dc7e27fb165009e9e394fb31ea759b651917e90a36d8bf014dbba30c9d50132bc8806ac5c368dd8a8a30a8af789fd32759cf097489df2962877a2422758f1f4bcc0a7b0a1de97046f20dada0bda0471e0b4c69ba1a71d6b4f04f0d95b1a9bfbc2f0894850d0dcb79db5ddb25567c54243728e9f7f107010652ef5b7274cf817c764bbc2f5d84d9300ec3953c1afcd89d0179cb1e3a09b865f3dbd2af6097fc80bb9231326ca859a51570adfdbb6bf38ca6c24e2b2d1ad50b26376cd182a152a118ea654b8f67d8c6b029b94d225fdf42df55f25f1b543aea6ea32ae1ddc25129701efc20d4d7bd166f8a52ffa52b4a1ff8fda7964acd70be7d6ba6fe06e2465bc1c7a202393f357dbc6ad7b754fab37c861a7c74c13a5e66aea5ab2c541b9edc30aabcc37455fa49c7d897acd153395df56cb4e8cae114b7cfdb941563c0c4500d31d979546723b956ab88bf907cf8b7e6409e8e3081fa52f23dab23a2f469c5900af5ec874126b7cc72f424d01daa71a8dad5d66de80f286e479c4c5da92eedcbc09f3eeb9f99ab66481192c875d30c75158c23fad81b714ee3adccb5b065bd673655b1fc80f06075b0f41a3e3da1a0e99d6914affc26d1ef6a1d54febea74b71debc2f034030615b4e8ac322d25cfe839cdff1054abb4082bc70d97d388d549e82c323c37ef6162bc930ca2205f868713febec705fb225c9d8d0c49efe9a49f215e5240f1e2e21442f98a7f1e3818e42728a937489cd2843de9007ea6f8d897c6178bbdd6448daeed9d164bd878089dbd02653000c3a089d5051ed7485267a43eade7dfde3479db764537622c85fa09b5a81e8eb61ec84c82d784a8d7ef6c31919d71ce2fb6a84eaf8d952338ae1078abf308f36fb333597a92824f062e955e83196b36580ac880ca61c9483859f449ba885672e58f7d5ab1f1d0e09266d394fe2c7d71698a9a7d75390385d363653da817a132e48c9e803196cd8480ecd73128fc0cb2402bf6aa350937a88e31e160c3df680e172a299d872280576e522f537ada7fa64ddfae25865379499264f262e1ee7b68d339878c36bc25007d45137c132b1f98deb66a691754c5495d2bd2f5af2813eac1d92cbb2ad4457f7ba00f27c3c40bf99ab7e873d9d6e7e6b95f537ce96a946c0c4aa1548a8475bc25e2c80653ec08e5cdec97878b87d20a22a2edd8a7da5e7c3b771160d5fe51daaabead4dd41138af009ca6db304458f11f67e767146eff6b6419adbe7768df5878481e5f7eddd7bad38079205de338ee592ef6eb3a70c2dfbe41d7635449df12f57f9173bff1ee3491d8057bb492754235dcf2a70fc76277c9cfddd7d6f05d89b139712d480466d0319c98d90567f559eb446f8ea19141d04c06a04a8550898f40cba312461797cfa48b0455951c4462fbbaf08f69ca68b05efe920b115807c243f6d2392f94764eb378d1fe17f7ff48f369e5e20e2529146f1c2f43db96b166bbdf53121505dfc32942932f1feeb8149a25863347ba4f849eed6b925c9d0a68830d9fd89230be8a07ee81be41d113d6decce80612176cd51bc8420e39b299cb1b7bece855edcbbc29cf9643c4aec3b05f3949c96ee93e586bb90e8201ece67ef739a1166d4cd86acb958ef38f2f95185d4e86eb7c046458058548974e502e6f5a4e482aeefa95845c3e1f15ee7f79e1788b8923104687fe7536189173ef8dac7cbe7a9250f6e133bb431cb05f6e2c4b6fd4417e50f92b033d3ac427c2820239cd51d97c633da1dafc20a614e0f95c4b83146132c7aaf5a544315e0f7ebf09d9e42c47abb06ec036b15744f0819998c1b9c8c6ebbe20ebbd01e6608149ed3e47bb3975c0832b38f86b5782fb7441f074ecb297557c8de115afec27c11ea4135b77511b600dd64043298082725dc20a6bfb5432f0a05b09d3393c492b5f25243c3b12e2b5702e9806b4243dd025280264480a8c9b10c7a82bf6fded8f7fbc5307e82f06e21b58fb0df6b1b825375018daf7215153d41f5390d378798a95c50f1ab788670d09d581c612436a14e6b74e6b3d99ecd655727e9b6dc6dbdb3b6fe06c744d8cbd76a87fba52b8fd9953a1761d698b0fba4080ee1c2d10c682fd1814d50b46397502b23aa7f249f28bfa6df21e40d7105feba49b0d96ddd552a8fd00dda314f1921a48c1062735117f868587a6426af549b2a0eb8f0c575d66f682ea5f1bd27b06f3a859e8421b47f45b30580069430d5e560f81001f43194f473b0e4d2d25654b1f01dbef93a0a83d4813452181e6cc210367e9b18e70e6d241bba83d701b659ccb830ca1cef9babb127ef880be81ae31e81e0a3e075df188b36273edc91030c6600d9cc522c809ef50ac015d2905c88f40f7a0d0063ac7e0633c05a9e0302c788fab62080c7052854a57be4ff997c7fc8f7dac26c2f81cac92aca59090cbead8d1e2843cf10d50793d3c041f22f05094745bc6f493f67fe09691c0672494b33ba2bfe8ec9550b1b209fa5c0f2d5d586f6404ab03584bf9b0e8fc91fce803f3595d77f8dc4ea6802fe4b473a7f042c3ba79eb1bbb513ab211c639e20080be2d355a49f8f25cc4cabdc672a1aff8cb65a3a120ba0fb0ea4a83530fe3c1a2121cd4b2d8e15b01ee85db3476cfeafb045e19d7f193e2218f7d16a8a4f27d22e8e1a40bff8c88dc9afdbe4c36c05d514da38679a2f13620116222284df621ed3d288a1fa36badc7c49e3b26f0b95b923d32a5b4e193780c9c8a38cd1b4c2dd1884c18197f69b5fc84a313bd9c70f47b061ef8230ff0cb6c1a2cf67bbc8f63f57946c708b8714b220099a0586e1d857006c1d3457d45730ebc13a9a20ee5087982e8f546e898ff0029bc51f82aa08b280b030fde41f301ab08ab4b6a62cab8a2c947633e29dde2cbc2bf959e887ad870dbd936a08eb40144efa0e0e69096774368fd5d40ca63585e5e79b0161018cb2c4f82ce956ca5223df15f1c986930fe94edbf8c1ad601dc4349d72929efd259915419ffba977aff67275e1385f3e9edfa44ed0e545984c1be7a37f93f03dea0893a62c4f35ff81e72c49d7dac34c56f799bbe6eb25bda2af4a8ccf819a37b8cf8e2cb80bcfae31fa8825b52bb3b2dceee28e97f57d39a3f221f7acd0f84b6a6ef2396451c09a7df007ffc6e057304867d7913d393f386dcd0457635ea50e384679b5e09fb7a4d9cd41e481b08060402814020302ff405cc190d23101acb9671b5088a01635547e460ae33c06f9f6101b7fa58d272c82fd2b40fc25d11dd63fa6ac383201008442e5ec53762e21b1049140f781acf87086cf8c4deff347cf8009d8765c3418b03418b0be93193b1946f690cd3ee199f71417bf826aa41d2294ef6a22af8967bc0b1e24f6e901b880a0f304d4c1e9f9d7921abeacb6119c37f45a27abf9af1b927c4356b982ec1a4b2ec13da7062eb403dfd13eec5dc5e438a963b274134cd17beaa3645cfc760cfec9c453f2a7744fb1ec27ff523447e1e5a5c4e64f161ac5e1ba4eef9bd9faf49015d122fb1c2444dbfd4bdbe06fe1d014285d7448befc6c5e8969e0d0922ac20bd38297f3edb68c367fd9f140afcc3418011346890581bde1d8a00e63fc1486c49d79c65637a7a44de5cb793cd702848849f0951735f38be0cabab00ee5c56fa39721ea193bea26276ff26c8ee505aa5522ddd275a1694718d26778a7b60fd40d017584f70726938ac0b3feabb1e54b00800d5e0c24a2dffdc6bc3e37e233cf24e236da2fe5a5e5c95028902b70e3c2572c063317f6b0991fe08321e128cf4a704030b82fc0141da40904f083f0e894b190ffa7beef1100f4d0a727ff6affd749c16bf11fbf016889cd3875edb9c0e4a9b4e6e2811abf93a51f4a9e79274e845e780117f0cdaf4f93e3db2b47e86363e85f8be08d662341e719026caf3cae05c007da3c77a684141cb1283db63457cd0e91481b57019cc5645ac5c14ebf63744635a001ec4ded2cdc6d2c5cec7c1d6cacbdddfcd3ec035c0cd1144801bda8df70827b027e37d0f49554c58e5e92b4b93cf5f080857099fcb74343b8f492b476b717bb906de9944922015fce5f8467f31f24ec3153233d11e07642ac16ed4711f2395ea5d88e7fd1b8a565d8425a62698a0ef8f903ac19240c7cb2fef81bca2cc77c34b8a6f30967911f4d9f299785afd0ccbd761fa831adc6ee064c29e02f46485ff112c03e4ff17f83bf6160fb1e945684ef2dad0731f3eef39ffac12b4b2d8b54968b958ec0197a8e74f90a01a9c35d27bc7bb315b993e50791359012c4bca7540b32d706c46cffef31b005f866dc2a8eb8af12561c504b51a607068c044ecc30bd30ca5f26ace5248a9d159d52a1693289ed8604725a9d7c68363cbb146a0364d7c726f8582af7b7c98525777e010a8db465ee571dc78206314e84ab72af5b90c566dede7e59f9d90f9a50596424b59fa63c3dd6ff45e40b1c1916e86f94fd2116b6a31f982c137fb57298fc51970790e62bcd705a83445ff962227e8caf07b736a6cd3d2f829b1790b36d22548bc578b87330eebca4cb0213712d31cb8d9d128729b68e7e84dde4516f041677807a82a4b7f11bc6092ea492bdea435771a3ee3437b8930a15e9263f52b60a2b7eff1481f124f6092aea1a40184fb6cb923717969495d6ba9d8a54d18f527e07b53dd184ecb9d430935b4b4d585ed4fab2aa6690c518d4644f05a2fe563112f4311c0e02d0947bcc370cf333790476437e414fc2396e2b1466e4e7715d3916ad861163042be8fbef567c7fa8c4770303d5437771ba9ba8c1958c39d2ae9897d5c9ae3d8831de78286789b3a64500318a0afce084cb329cd14ee3724ae119376d2fd6e06cf4cb68029c989d8ba9763420ff8209189dc469678c8fc6890fac75d372e928333c8852029178048b4a8524421862b57a090e7ef4d97a5f890769e7380a1f23ab7c97ca7da7391f3df3f2fec6b4cd6a3ecd7cb172d891a134a4fd96a540d92d8f57afffa7b11411e11ebfb3f7a5092996305f793d80b878d3d80eb8d1cab7d16811fa68cfefc402cd26ebc4e945074ce99b2bfb81285a3c2ba9f8f81e6c983a0993360a89a262129187de8448fe881d20c3b94d4e8418b040228231bf41121324a051bc208a2e0e9289acd67633a6b1b38c1632d5aca62c3275b0aca68fb23c12485cacd1b1a22caffd9b726fe6a1b0c678d1cc1f6ab09eeefcda0c38fac69b4753435fd5b1c82475f7dd3fa5d1949835d92b4db04a6bd2f58a80edd1209150ef28b04b480c5b40b066146f82b729df6cb05d4f1498f8b12b7d6b16b660e37237e58a68c1ff8187564f74b5384277e448e622ca8122acfe4dc97a4e3909b7c7abd84c14d8784485d40e9919f25439b19377691f91429b3fa705074bec58f2dba6570c2e176208ab21d8cec90aafe03d7df5a5c5da31cbe539771d620a447b8255b7b5b4d942d8e0fdcdc0408ce194f8a3a9e693d60a8d496c92448fc4d069f6a0ba34fec000bd67fba0dc479e6bdab9a9336b4f2b0eb06102c041d44d49e0fcb8d157f1baedf7bc76303eb1531311401a8c3edc09efd578cf8d4c89ec63322e9f1ec7cab2c20b37f4d12a147018b43c70918d3c6a0595bc1dfb704ca7f446547a9fe339ec3d6e48bb8c528fd3598e3c419c84f074917fa82a4198dde8e994ed09e18f018e64abb7b0d453ce932cac949b038987846c43a31345e24d0789090892ee80c17ede454ff39f3bab4c8349608158f8df37404acef09c82d460ac23ab0e083f3164706047b62fceda3fdac091c67016bf2aa4d9eaaad931ecd1427e138183c080e7dbc5f73d9fa97bd9944a32216bb0e9c46e10ec6a46065ef096061f096c428e86a8390a23a7d30245c0984a51afaf6d6455776e5df1fb39f3323801def35cef4681a1675ddb079f8c428e7379b1cadc633f9cbcdba06629387b643c01ab17701ec6e5a493e5010de0fb2a8b53d6cf8cc14275220bb359785a6ed8a0b28d72051914ac57760312f8c1c1dd1eca817c70e5c3719a074e101daff7f65b902d5cfd4395de11aaabe81912a512fccef312ec519a4194229b99dba744ea77cf1115248a03d098ef0050e8fa2070e0bf20287068e46244cebb9e806d2350884f7c4c000495cba9760fcccfdab8a8824986512127f40ff3b7e5100e6b702a9534b10fe09d7383dbb16b7f9aa0ce2a05a2271f33c45e84d458030202510ce87ac4e6ff1bd30401818de14f884d552dc88f6ee175898e7a21c5ce612f45d89a13cdf707d24cd939c01e51c318d676b60ef4eab81f868aac871a4d9e11f7f6a6d2e73d5adf558191ec3a391ea2375db9f402b785207af2478550204fb30c13c923bf823d629c687a71797a1c64bea9e52a16431f77b3038434fad8c64c614485393a33db4f0c92b8ecf0639f36c7c54abd193bbb1e65ea7bf5f77d7fceb03da0f811f9463b85d69cbba2cd3f9588ac74cb042fd3f1182900edeee9f523bf09578b2b7fe0dd8e55dfd9e6b1cf2fc92d3f0a897e6d53cc1f5684e462ccc221af54076e2e9dc3e848e6e1a33df342c6940dced1ba4de5d980f533c2440dcc69d015cfef7a19eb7728c74deb578ce30e55cb5ed62aca2b94472a5315a0f0135c96bec0391b503199bf80e9aff63497febef5ce055eb777e7476f8b4b344ca751f3374666e125a043f1fa1bbc73e73047677b547438b9eb78eeccb7ee70357e634e57869eac20f6a20c6944fc254fc4e0d2906937b359e493ab3bfa3ba8bd808719a69cb35dc20a79d97e6f695c41db84bc13c92eefa9ffb9b941e8c3dc7009be4d3dd5a9c3c5796021e5790124b8fd92ea1caca7e4ee2421bbac4b792c7c22387f06486ad149a812f015d14230c08b48d40c765f203fa44ab912c73b2259eea58be3755c5c2046f626bcabfda8bfc03b61aa4465201bf0abd6aa2737cb816f9f30d71340b51b4d6dffe16ad228d3ccdb38692092bb5a8048747f2571764a2aeefa662a58372904aa35460abd4f583b49d9250ec39a3abbd7e3cc48343d2757feab5f480a18d1c7fbbf5682573d5fefd1a9d059b83e7a765c7d799835361bfcc8cf593d1b79f0e3bb7265183d6c5fec84db9e6d8ffa35e483a906471080c9086ffce73c33d9afe20b659d89f3feb1df4e840de5f68a7c99f6587097e705b0674c2db838d0795a51ee1991d1e4679fc938c5de8a0e31ff67d4247b5d99a9f1e7b202e9d5fdb24507542feb11f923f970a2d6fa59e723028bc66bac21199ba7984566e172c6745f0b3a91b001176dad715217ac5a3bbbb5fc42f59bd5fb84f39481b4455a6ce1888b419c13fc9a5c2e7d058743c77aae1caadb71d8a005843066904f055e9fb38d2f48a9bf8d27546d8fff18e89be315c657dd088270d00320efb220f04ab26035e17d897f2fa29c74534c174db792abc2562db8dd93c4cc86abca80e72e60c50c81508396f9b8a3f41e145a373ac6e2d8643b2ddbb761087886e19db7f02bd417430d8e87623d940af191f2fb7315b69ee392e4a073fc50d2975fdf3afb1a87d9b39897cfba1b5241db1667b6a57764b3355950e40831b06a9af4a502ed195d884c28aeb66a49da6dc7e915e26c934319259d467f4c0b20639beb53c9781ddfdbed931feb15ba88b1b53b4f845b3fd770e135db8029e497a23b8cfbe64faff62cbf0b0769fb778c56c331705f508815c6362550c4500ec24b7f50f9f49e796f358c02b01b64e9187e6ca162d381604e6e398aee24477807b10ca4e8cf8435c195f68d06367319edfe7ee8d4545a1d9d1a629e9bf260786e45b77804a72f9cf05cae139706bed9fe0f2b7bc6ccfee3c3e986af6c277895f6f91055006f5db00faeabc9255f90ade4fffdfde291d9f2ca842be6230ee677eab503df1ca6fd3eec76248f3dcd990aae0fb458b38c89e3976abe8ac881ef09856df60feb4d341ff4ad5f1bbc18b63506df160c60abf3266b7838b2b396881751b21d96af836244fbed06df8f49070b9bfd2a78b674aae3d5394c5fc5606872f5047ad06d3db24c8594ab1f488e0bf953ffec2a2e2aa180203d604019757c28285138323776b1d481cb97419bbde595ff0c81e944c1cfe27ea011ca35a3291a90f037f7f6322e426157bfe93127c9f9a7835b20c5ad1b772832c087ba59fae5b28a834911882c127ef06c6a67a60f74ba5067c7190bed682f7d093219dbedc622611303f529dbe85c2c132466bc37e064834bdfacc12f1cd72c6a2a8ec193bdc704269946d5c0f44c34c387f0690936067455e37f237fda508ac62bb80a7d0b641490486a8c069e80a0bc8f7ff001afb0fb26574d77d7e633829e83658ecdf86dbd26d9d15cfc7a29a9189871dd8658852f52cc5fe218dc202c5512a512b2566008f41e7befc0612368ee2f8dad3574704cc345425c1ab78df0dd96ec60dd351b73cc269b7e1dad8110bb1c0fbcca261572fe74f9f1dc60966be340c95d61add024859093c546fe71b16761440d6c2fc5f8b2148ead0395f52df537d65d8599602e11b9fa960ec50e139029c3304acce63d91284793e14ca2f185f31c561ea0ee7b23752565fa55138d2661734dab729c567a554969cff9900c26868f1f0dbc2e1fb2f94398df39b474dfe6b84c887a1420bf5717d9f3f51126cd09f51930db90a6b0c3c4262c42f3ec1683cecbf3976a25948440f048196b287a32feb2ff1aa1e7360558424b637d6a53137960924cb3d69117683e6953a7158c9b0c32680d2f6b0b769f69a92bda8b047efd04fe47636c3cf1138d805f76bf0677d485823050e2ed3ae2b5a2f4bca57293fb55d01ebda3b9f467af93f0ada743a00f991a05f4bf9581414d4161bfe0c64f9a70a314b7e8d741df5d55f410cf4b65f041caf3109c354efea02adc5b9b34d06dcd716ba2601116816a3416d816b2894b857bc866dc6822fe2db53234088f229edcfe323e74ffe436000a5b5309810992a4b8ea7f2f6f8666548507cbf5516e97c9d7d2043534ed2640810fef8440cb7ad96a691798a4edfd6c92822963280cb3d6e3be9e4da6e909e6a07028158092d2aca5035cf949b779c97292967ffd6f35de13b18b76513396137adce10dffd5a3fbe36ecbce981d2e81cdf13a31b8cb8a6f54418d8207a6cd606f71f37dbb7ae8be0e0f0c739f19572bf114073cb0c9d8a75b7ae1eb1b9a02b768198bfae73d23481247100aa7458041889104616ea9301bf71cb06728b8a0bb169156f51fb0d81f19e32e802edae2c579a11116a5f0b3529d67881210fef05dfc904d9855063680829fd511bbeaca7aab592487c47a9d3ee8c8f254793811e328377518fda49b762bc519ba21ec770128f88264bcc842dfb2e3ecb49e657664750380a26828adbc1fb893a3f1a5599047d523de9d238e2c9df927a20f837854a5695579f7715af8387e805d6aa3b644e44063104feeb7faaee5d511d83a242befa729dfd878fab4ad1e7e2c92fbd59b51770652471ddbd7a05c440a862a078dd5ae2e37a9485aca3ed5f15c1ee692f569cb20b0bf31eb28fe345f91e700e08fa024e8fbac989796eed3276d5424eac4bc7e8ece067364a46211ba5b2173e916bcc339c8586d332ea2bd2a4801bc249d07e333da2680e34fc3ee115dd2b33e49811c98f22e75f58e14dd489d579601893da6071398f6bc444d062c729e26da91f0b4c8f8215bec1727a1bc3ba661316955e0beeec0b3fa058c9d93c7aa6fff58ad8ae2479c57fdbc713ef89dcf62dd370b55dd75dedaaf499528adecf1d6319c58086aa2125c1dc1af2cb0bb6ed0a729369345dcbaeb16ebe6929446632d641aeba07f2d80a59d53f8558c3c19df957fc2dd3213120d35c87901f785b41837c475cc5ab7c6cd535d5462d8fd3a415cf7892869866104ee518e964fda0570c8101865845de4fc7b09fadb349b11b70b796d7d373d32628a2ed849462aead79f51801af6a167ab9c3e377bbcd01948037799b3f92045351df94792cbc96ad87fd53bc7b9e59b6064a4ea87becce34297502e98a8a5317552bb8b1f12c5b0b5d7c0b20cb00f323f76b06c37f86cb1993131ae6800d0186ce13c3822a88288870995ec35393cfdc7df94fac9e1b46deb01be27f471dad0eb43ab17fddeae6362e273ea9c4e24bb3faedba97a07595071091ba61fab1935327dff897464d22aa314638ad1513287e42e4f903193e97cfee817c02415f2039f0ede709a60f78f96470e6d9213104aa5d9e32eed0e42f99044f5c7c28f037f739e5534d75cb39a0ef2f28355c8075d4110d9c5c6b3090fa5b48e2dc46a0a3d784f0f98e73e1f268a77694cb9449633b37733bd21b5885a8e3284d2bbc75685e59002804e7f2a3335457e8cc9add058aa6c34b8c55d4c0535868649ad5ccb127130cf6c0c866ff651b57d5b35b45d3d85f10bab67b724fa06a73433a19b192ac2189b15eff987dd3fb4651c78689f9029cf1e672dfc183542d53c35441f38e2ad6020b6f6a08b45f3eca7f990e6dc4671a886ffd3049fab2539a58e3f8bd98e661c3ff17fc90c0de92c93ea0ea6e334b1f51142d7f3b80047adf45fc79c6f7e9127688b6b976822aa8e1e11778de9c13e14255d77c0e8e2d24411e36246e3b5d14663db0767de5b9bdc8451e7abd13e209f02038fa61593170de81a3a022c32e072051c55004b07fbdf9fa31b302ab44202b92f317bea76cab2a9afc6f742ae53c49133397e61820f0c9c4bb3f025a1172a94ba64f2720273910e567ec35b2f725ede8bfcce0ea22d84ef3f3630b1a1ce1a32420908d26f1bd52ff17174ca35acebc2e984567dbeb76ec846d8cd535a6a28b383a420bb097acca455f1c00a9a96744de4e676da5ef254c7a542c1428b77e72ebdccf0c02eba37c9c58955b3db0f0b21c26d870384b238c0a5f0f2888c702308d969b7b8f2bd2d3713087c292a4594f44faef08df07cc4e38e16214a1fc92384fd3211427dd549fbdb5f2e8d9c48d98923cb2b9e5cd2479fc7f6a851df9019481479ae998837fe28e620b7fe56bdbae47e2e93d80a3363875d061a6272719c86b5369dd286dd9be5abb8ef29b2967f7f7417c38ab172bd920dd2d7ebb3aaaa51fd43d821119b32be9120bfa96a0a3141c0aad36f626f111a3f6c412e1927e2c3ea486e99ba930cae251b87b604d274e7a13b295e7e1fdb856d59fd4467de160e99db6f65e4c35dcddf177da01c03310ed1289d945b3b4f658d8a5eff0c8b7f1d8542c3fc695adf7224377e4127b600841030e70c51865d226ea72457b6846e0a3b0b07c858eef21bd6a0853c2f12682d6b5f1dc672f65948eac9d4e079120dffd01f7a7fd3c763fb7fdf65c8e7dd20de9eb6bfd55bbe32b9a0755cf1fdfbd65744af4c25c36af0cc09cead37cf439d3b216bac2b0371567bced755a072563ed215c00cffadb4f69f5849eeb82eb2cde59ec6e0ae6e36e7293fd0f634e10d7f60cf1dd48c77c077e5a545042a521cdbc68fb3031bdfe2f24e16c83a6e253080d5d76d20186fd5cefdff7dc80609dff0e9d70a8f5a2520b215f49a7b9af0179d1fac07ff2696c2e5ad85e1b4b2256acbb5f8665cee664f04dc4f43f51841ce780cd831e2f1a2638ae43d6fb35be91accdfa96a6514e2749db77da3e885a8425c4223540f8513ddd01fe8a6264bedc4c39724cf7c2dc611044691a0c03824584c2c3b10da090afbfd729c6f28222d4771767a33c899222340345e8cc68d000111f105c6028a48297a3cc2bfaa0e6a7dbe2b00dd1cbb563a7e2fb17e48b26a785cae6895095198c73366a38d8d67d4b40a8222c55786135fce694a831aa7a1a48673ff9afc9a091340fa532a9e0b709af5374e981da66088a909bf917e0f019fd5bd8dc42588606de15267af25ece7823133b4b9e52a0b1d6898c63ef8494874bbec424080402e1cbbcb6ca7dad1761a7419b7c4476435f27dc86114171d585b1ada1b5d156f481c8ab13b011bf877ff5350d2e4912fc92f8b06b66658fc7005fc5a775d006dafcad41f6407695d1cbc190c28f6a2697fa63b081311df20fc268530d3590331cf9e682d3eaf845bde32fa6bc988042f1b7b92745199a56ad4c1f1e8a5d75058d240649c4422c4094f8fddb9151ae9376bc350d830bed31262125fed8d71bd5600e81df21e1e98b8000492658ec53555cc56fa6437d5363aef1d124d81f1e898ab826c9e3ad9e76b9e097429e01af719b31a95b73100b9cd5688d45742224bf22b11d63bde3db738e2022c0c36fa24da450b8e033534f04b0e869cdfe8e6f1ada75a5629fb4974f791665729cca974b57d61d21a164f0052e7d745e24fbdfb83f6c9cfb1b5023f0dffd1ae03083323ae57445bb681f357480db391027a94a2a81b3a0ef2f8c14fd71bba4f0b3ad09f3814559b14c958e11bb00e1afab0d8696b4cc9c4f96a672510f9c9639001b5fd95785c6afd3dfcf7dea755e9ae9744e012b7f900699f16764712c32a6fa1e38cc9b17f58aa6e57497a33bfd3c2f534d3864f1e5f4e2f4475c29e5aed4b5b08806adc002e6c65780b6410750e5376d5908c353385604b477ab6a8e0a8b9337ae50b99ea7e67f3666f95bab1d6a03dc1ab435f0b9a5a9b63c02bbc60eb19ac8cfb757cd2c7de9afb882c5a22a37792ef0edc744cdb2dbb697f2b7736c9cc9d8ca6007e7e311defce4caa4f8116a1f5e5bd8f15fdf5508c77266137038dbfcd3698509e4615fff14e87774bb7a759081da75c59b8f479a508b9457a312863065c38173cdc893c2de4de32e7546f1d71411b707f52f8caa30f3231bd9d36fc6231ffb71ee1bd13b0958724a35efe48824a18da7b0449d34dc21c6832c434c33830bf813d0fc8d2347ac120e50d065f0832a8622807b95bfb73277461adfc2b3954560742a52fac534fe8efcbd30a6891212a6093c0514f54398f2d011ccdc78199d457532496a0e8fa6d368317497f2be3f56cebf2f92b93052af645a5a2c4e9cf44e14ce43277e3b67fba06356636d5908c3be46a16122d8e4b72200d03668268591754b86860902665e319ecc03c82483b2849a5d74f045939f47c8008c3cdf5a801d0e74949684fc1a70c85ff5fe1fd38c1d0ee15d3aa1cffe0f6ee837393e51d41e18cfba6a947f311f772e098abe9642df02e96afd9ec4695f65276b99ef3ea3bb2e2e4c788ba7ca9d8d908423b417c8af2473ee34de1c9fdae3bba079be622eec7523eaf7a9d894fa76883ff86d8258055014c7dc431bc671b08dff6afd8951bdf74c49cc6fcb9ca6661e044f24925b29237c2b9fcd8481bfadf3d23953deefb32b3a8f156ea05f183d680f14a4ad32a92855bd40766fc783916e049589ecda872d0ba2b5aaaad3909e95703eacfbc7d6fc44b705b985b3a65346ec4e7703295ada62c3272dbe5a35180a1a5e2e88c8ebb8a862080c9c8a9ec2b1a932dea9b44ec0350c90da987e4d84c7c80c177235cf4597901578004ca1170fa2f4f983cd7561a275c7f6cd651a29fd19a27f1013ab40183b4c8c07f0b71a7f7e448fbeb4e9bd5098c347539f4b828be3d40d8abe695753c262f851b599d54ae03d21247dfdb976bd2254264ad69ed3ffd2adbecf13d508aed21789445fe942bdd5aec3a9152798e218c0fb0ceea2fe916d913c4285f3708b49a3c1e87d3af23a46b53cfaaf19565a87bb072a6a544c077f55c4e2ddee107582d62acc94512941576ad061037d86a638ccafa1c483abbd4985e971fc523f2f44e04e7e13c6127535072ddaa0a7b523bcd688362aa50b10da6732041e04de0281d3b51ef29126c008492f9d7a927057d7d6c3a7e0aecc06ca5ed9493b4690b0123b74684d46c28dffa06ab4341742506f5df1a6066d755ba6a3c244e9a1f714ff6fd25ebd7fa1f59070b4e3890adcbd3adb25d3cfa9cf853df48c16e44544002e6a33f45b4364af4b7a4117cfdf5d23806f15c717ce3dda328d86827fa7ff94d25c11fc6c951943f7cc33fd5565e4053b00989f64921a3795ae7362be62391d5cb5e4efb7e4eede6c07e85d2dd8a9043dc847c180bb734050c8737a54794b14c420220601b9a26f2e1e699f5b93150eae35355ba5791f2720fb500be46d514494ffef782f9022b866b23c14010ccb32adf41ef30b7ff60423c6ac960a2ff0fb2f0d729e675692f531767e0f7702586f876946beab666607bf8e38277b0e09e54408cf8931ca6cc5be959df08638f7803b1b602522f638c478b69c27eb572ed6f1d46b8328add7f7d3078533eb4e6ee88b2567c7ebe1e7f2972d9bdf43126932089dd6fc1d1f0b1f95d774bfa7ce63e221da5db21df1dc5e142276a754ab97035a7ae644a48446da4b8010180513e491bf0be8684b19784df7a12a3a927853ca6e4bca85b4635301531f606282b6a81c158a9138a0e7ae39f540ddcd7dc5aa9935be4ab13dd912055b1fdeda75d69db7a7fbce9b0080b309743cc079fbf5bdb494e9125dae7f452c09b1d95447cfc7914e9e7deae1aafb1e14ffb3c5afd1df5e1007f43b38086b058feec79709ba2bfab09299db38ac48735d695828d8a2b3d7f8c0005e9f8b68e79a2bb8407de1c8d2fcdd2223efc604538bfb249fec26ac8d506992f36722f0f0ba10618d85379ee07e6c28f1ac0b022b7efdbff9cf8ac9de3e0ffd37ebff2669169885fd7c330820f5f7d08c0530c0bf92399ec9856ffcbfe679270c05e1c5b31279312645fc8bae4c5acce8262909e091f34c046b4356fe722705edbb8015cbcda88bb4568958b4c189fcd3fe4df627b99aca3680a3e728c8d626386d796209490b7454487f6703e1edc5944178832130737dbbe136427fe7e12d7c60044355f258e6b79372fd1acd13d02d4935c444964b7185388805089d9808f88e14aa2fd43c43dbce11d00ed1c99e08fb57b7ebd5e0d5d2bffde805ac8bc16cbe8415833830979ecada038d38076b5829c24c6416569464e823887bc0443c2857310fd7f8753739cf02cdd4648da85e46a700b9afbd0c286ed972318dedf88fff7bf5dad02008681b34957fd7f3de22689fce2822e7df8d6b56c228de596c6a4b6e4edf2778d760e16ee2071889be2ba4a63000cf9f267998348a31a9ca6c586d03880e98e26eb19842b6addcc8a9a39d5757f0c7cbfdbf7e096b37af529bbee18c467f1dfb3e901e6b24796045b3eb1d5df0f6cea60330bd235090eddd9749e6d165c609750b20d95ef8347dff64c78780f3a77f1c9bbe07aa0e82018140201008ec0785bc803da3ca5ba2e0772262106e9622a271543873f84e5ddad3951ed18eeea91e1c40e6b51e69240176a56dfb6d7faf3a95f6f595491f88ba32c499f4d6df8123334b8b9ccaa376d35b4860b53291b396c76ce7b31115e41a10a612162f9e55f13e5d13d5a2ebd98333687dc230e8b1f2af360aa59a6e6dfa1e4cb2a52d966765a9210e400f36127121332adfb358f0f00972d0de92a60994b878215c635fe4b42f0b7a00d4fb4e8df2b4d06b9f09230c593fa45c605db2c88aadba636e57506f2d036054c81965b682f0dce93256c1738ea1e7f5aed27148f899d3139e779809e19fc5a008cef1226803afed0e8aab031551a95d21810165b2df4a94950eef1f3f160df827b18ecbffab232ba9fca8e0e87343dfe7341372754a7eccb429f2df8257762e309c8b8d0927f24f84252203b864c13600d3c3d59c3d214d3fb736f30edbb063b51a5271846c91d1d30155c74a72ed0f571048cd8222a19a30a807f036ab0a8d59b6a54b06bb9131cdd7817adfc96c3a72a9716a843c005826775df8e5d0fab7f8ead095dde10336aed8b7bdaa5dfba4a490ce1ea123574f20fcceeaf5ddb48208754c90db8b7c885d7ad4dbedcbafdf18d6b85b0582f4aa353d68362018100804028140b950c8736654790b634c2ee40514035cf781a291dbae72083c905ee9450db82256537c372c6aec223db5aa23ca1dd142104120d0521de021303070dabafde917cdcbd3d15a47b184e0d3c6b7d96b42e4ffcd46b86d87193bc2fe0066f5e0d5f77177c2fba7bbbd3f84ab81857efe75d235efaec2b48b8d259391a1e24f6f5d02db8d589749db1c72307ca31b6af97f2ccd213ffa1308bf606b2efa60638e21a5240c1c3d74aa210ed04e80d1278144ceed29925f3c92128b182a25a3311efdfbf4f651ee90e17279017073ff6e4f7ef426bc9988de7172fea3ccb92d5ffb3361da4641992a4bfb5138998e2e47db774d4231ad8b66a05822756d265034627c44ce9ee30eeddf758aaade15888829971f29afa8e8f9dd4650972c31bc2a5ca46e399fdf41e694fc108cd81bc4f069dbf806bafa26b898271cf9448d6f1955915e8c0d17bf5291ab00564575dc5301dbedb2dfd6b440610c4ce7ca64096d25585a796d826aaaeaf90c5cecdf067001b2e5094e5ba15842d2035d885f00590611b735a10cf63b86cbcb3b135a2480ec19866a3f73538c637f5002563e2f4ee9bf01df3f01f51a443f0ea0dc05ff877d4aa3dd6ba4c1491f70c30f205e2f59290221ba73f49a0ae8b22701b8f72f267effc90d759dde69fea211c9ffc1c262d4a8c46eb82f0d0ea452a8d1cf9ddf36800790d193701a55c91292fee90d10c7a3457403e35089a3159e0047a8197319371d618cd1b6a2f652438b4563a6a10b6cfdec9d03639696f427f033f1c63d6a5e763c18439f8e60e3a4bd9b068df4ae2001741255744f30a273b85a0d7d871dd9d5a9ac441a1097cffdbb0d60cbb27668f3fe2379eefe517e1d25cd7a2f4d7914345e965a28e16c001f20b3e1e1344b9e25242dd4bf7797415405fd288303f2e0f23de38416d50d2e83a1dac3e661d4bd0aa4e47de095f8cf5b4178ebe8788bacd868b75c4dfd4d494768290c4bef12571617342031daa26a141a32b88f44a02b8305f0d8c65273337fdb70e6ebe1f4de66a92d6727058b0a36e2ded0772b0affa54fbbe68c1547d4b78882f39093e482d382621f123e7923aacad72cf1eae56f954204f58410964e8749d988d07566cd4adca04e16338e8766429579543bc33240ccfa8ff0a6ad2ab544339a686164e0375218c727a30a9deb0d18b5f0f1d916a4319bda00014076b6c369c73b4b48da67804508b6a6e8e14b734b9d3421bdc007eb2d3c05e2debabb7138394e83adf55567c260ad60e8f4926fc592c88ec5fe8c1e8a245e63d1e571196760e8dba42e36838d08dc8d306018fd9e6c3a4a97d1579150ed7c64fb6251e8f97618090494aa7f96a777b11f60a2afb1e52cab19bfe7ec8e8feed1c2e56304f109ca89c3060801b27a124eab2a5942d23e43743808de67e61f6b3b3f1314ad0ebf931d0802e3b58e4471d286f7bd318297a0a16b3ccdaf5b12e52523fbc9ae87bad2693ca2a86a82ee5792a5f2def5a0a358394ccb2f5c729234b041b994e46f930ae2c8135810963e05acce2f2dd7c6ff3ef646ceeef3f37c4a783ffdab4d7978c3cea548e571936b395f66e5bab1f5eee1364004907946719a7fd412921e1aa50b96c4a11c2b85d7e1fad2c361ed79b90b4327d9dde397d7f0f9262e4c7c7275192925edd36510e44f743d612ce0f92ee43134465b09364cea2be8cec94582d848dc0f617e4456820074db4aefef26342655cd444dcf5103cd3a701762b4136a23aaa7997fdc85a971900bc1c983604c237627957db4a8e0722717c1d14989e76008efd8e2330b1c648884245e43deb5a81edea727a2f4516c3d0ebb44572c42c699c9cf761d8cfc6d00aad56910e568f2ef44cd2e3cd6fb69e17a5ebe6d6f200ee9b15a5eb93b895450cbc0779560d41790cb1df3d5113f108645acb745a448d6d5ff63e9312390aee6345ae0c50620c67f05b9f941b0278272cd6f1714df1a8f3c9da4dcee45db423e0719b1fdf0570fea83e17034e8674ff95f5b68d6db174bb2a9c2102fcf4b372c06733cdc3f420f3d638a6c99a3454af101622d51a7987f7ee6ada3faaca3bf12647e950f7e9afe0d9387ff2cd3fc3f15d710b9f02657bcc0eb0f4b9db647fe99bb02e4df9cc6c313fd574c05817ae04ecd928f6ec17c144ef9e480e361e965e9ed6fe9f1df5a830339747a1277183c32d6908c83740e33b28ad875eeef9213a20b53de04faef44854afaa8cd920f918c828eb5cc3e62fcf19325f3259b8f1f263512d1b5bc2e247847918ad115011ad18fcc86149bfd1de0d152368b980adbd5cd99eb05ba365c105b196e9202332c1ea3365bf74db04302f1748f4fa515125699455d8005b17ad60889b59b4a502d2b507dea824110f82dbec5e2ff958165176a6b321fde41540a1aee1514e21996446f451d1303446e9532d7ffade4be00cae15d7b21a839111b358bfd0c84f471875b7f535b3c0beb702ec9298e38c707c13d5fd9000940b6b7c469db4b4b48fa679c3eea59c27d15543c569ba394298a41ac131e63a4affe57953c5913217e1610c6ae80a1b244f83d49cb5d5512cbca3ec18327fcf807eb4408c9502cb0fed74f055bbde11bce7f667e28838a23f63ccdd4d8eb7a92a6ca783c02e2ed2210d49c316f6e2e7fba553fdab6dbde409a6504750a399d739c06712467986a65d00648615a539680f843d0f2e1bb4961fd16af92d2efc3b244b9586a02f027ede709a6d09575460253ff15b74b91c4ec0c5b22398df6e2ec6f7804359383f73c0a5c06b32485732bdf07f6ce965c7e124af4c58a3f491a3e1571eccaaacf998522261cd99ab501ee8936f34d35d50d65a5838c574724e99453a52fcb1c3d89ad346c84821515a83d10eea61028af300d176c9aa19a030f24138e525d2ad1c6c05629a5ac3c641d64ae941c851ea6a7e8732922f8328a6df82416e28086dbb33ae70eaffd38117ca38f8b7e63dd110fe5819cb5c97498255d2234ff73803d2ade910fa19ba9736391228417f9155e08d7803600af0935eca6a54329d80b01dd6eaf00e7d90fb26ce71158b472f21beef032e592ec667b8e1fbb2f245489568a7313044eeaac9c062dc0541e236298ff88c5f92f52b025c2cc33f9bded8dd190649b37caee3d091d1045aa0be8fa5a0c34a0df0e4529ff2b425df56d3eb5edfb3750157df3228c55d53ba713e2d892bb290eed2f78165aa1bdc4b05adf9e6f834592fadda1edb66b3aef02b6ef3589d2a923249f54b72c88cc40ef183040eb301fb4bdf3299de4d11778e650f84cbe3531a0183fcfd93958881ff45fa107c20e820181402010681866446e23606a4e0bd32200e76d891661661e74222cb1ddaa4d9eb985435017263dcb4b3f7d8e42523634a96416d09f4ccaf20dc6c1dea104e503ebbcc92ede1df78f2a9b41f27bad164ff53bdaa5321a68eae845df274b185b00f6fe4ca76fc473ee82d593f063f79c4d8192f33530b9c3a91af13322d70372dde0eb5f5f480e2771be2ecf42dba761114db5adca6f9ea8f40037dae9574774f9f86fe4f1aff0025918572673ad102258c0b5359d8fbca4d1f583b0293f24e0aa2fd1361b5b799a17b3bce1db54902388a907a2a54971a0a9ebfcc83b346cdb89b870611327a15bec19f2dbe3a76b8df04102dae7a93abc1f436343531e9d2ff28f3e684a2ae2c92ae86bd8e6667a58dfb15fefe75e615e074aa3ae947b40afb793f87c3d6e71bf42ad9c25e6c682bee3a37f25e6b3caefbd0b4dab0f4f1e71685ea11ab9d10c548b2cd3133933c5f44c8fe83e89de08b8002d6a6ed9fe5f7bbff037997db0e5e33fe8ebec2cc81a31b05ec4fb5c8c3b293dd0f97ed4756e52e93c4e114018f6173843f18c1922d743f2f51ee3f5741ae023789dcc6c80b604a1350c715dfcec49d7884db9f5a5cbed1d0e5ba8815f7c0c88a9bdd07bae7c022fe8b33b47571122ecfaef6f149e616f8805ec393f497f461112576c952a33cace8dd95633034c12c6460acc0fab27b94643013436d986cb2471b616e725784edd4f50c9b0e73fea9e122197945879461765aeb30bb15aab7b982d5656278b855860e61d892bbc048ba45ee7a2c8e68e6e8a8d4f9c482d48b8025e42bbfe58987f021040ccc4fe5eeaefc3c6fcc533b2d924a8dbc12b924de84657ed24eeece98b2d2278f344e7c4e40ad6ef87f796117d7aaba1716c45cdcc29e61642f4ce89f0104d4d3df635a5c3020be6c1b0959700ed978fc302573fb1f048305f1423f877f493be032e9367dbd596d7b6829ad379389120b91000951bbb6c62ab4d17349c5a7a0ef02b0bef65a1a8d909dea38255fc04b323b9dd9d02eac0bc3028b20c7299f59633eb0ef2c7c75ea53c04066014212e02f25f5dbfc1752989b9423df4cde2046bfb9c9b252ef2bd4c59aa5d0177ee27bfb87fadcb2d6a6cd979ccb5d81a94553c290861aca8207d55a90ac56f3db0c520181068c99b6a42a2d130c2dfbde520a46c3efee1d3b212a15a4dc683dd7d8f43d980f643fde160d947473adf7333a8860840f800e5e091f33f2acb358fea8bd86ac701d1b57b4fde8e3e8fdadfb958de3f85801c7458ac8afb8225189ee68283768196a2311700f3f127832d356087672af6b1983fe03ab8aa7234ccd72c04ccdb93180b326015282d972f1d0c56c5a4d868a9565f2ee2df3572f44b5d8a8fdbfdf4efc277dfed46699df694079f0a1729611d9fc8dfb449d5bb7bcf34f81ef377753607b4c8cbb2a3f95558f5e4b60c6f11c0d6ff0ff0e795c22fec28867c7d903970123431c0472095f3212821c940a862ea4e331800afe90602d30d1cbdd5f9002f30f673ec079e292914a41efc3f7cb76a64b92f16cce096e924bbbfbf8f13ef633102708fc33a635317b72ca85f8545869db56ed0fa5b28e2dc86ff2457fe5ffe4cda13cf910b6c2fd3cc225ff4da1aff7c6b45000cfffb6d7d7398e03223401998448a5b1ef0772fd5256ec84a097114ea7aa8b8e8dce6ccc25b3c27cc82e8ce7b64e5f3ed857305e4bafaf1e0b7112a6d6d0e6d9dd87fad9ff270910b30216b72bb165e8e0a2b11dd31e31b3320304826b92862c8237fcae7682dd45c14de58b2e1d3ae80a10153338213aa7e30c6c521cf92158a7b9b30a5f81ceb8ff3f88244406614895da6ff8f674c8a7f43f5cb85d417d6a5a57fe32091137381ab5d7dfe76ae7b15385983f03941b84dc6f807d81e43d4a03d2e67b1958888f160669b2af8eb0cfe018141d358855499816c2662d894d7256a075a66d0405aa31ae924b6d85e2632f21220fa7d5d2e2d2ab59d1a74db26addb5016a1deec00c6e8b3e96956b545633223ec817dbd44cf048bee69371d3962ce1c94dbedaa172f1c9930a8df667f68c929bd43cbf07e1163bf5b04b67352583f9d91fb2dd93670b5c81b53a8b7fef472d119ae4360a0211d03352a9bde7ca212b91fbfb46c8657f6cb9e21e3113e7a7e868fb31c0d3ba0bcbbb0a4e7abaab0f987eb15ecb3e39aa29a9a264c9aa110d76ce84b75a9138d55209ad017886a4f3061611df45875b32d27dc58821181539d78ea8a83235b1f1a5d9ff43fdba771c9bac014cdca5662900060454e40279ef833bf2df096db3ceb34801744c895a5114f3ce50f85802459d8dc07e7119402c32991dae6e217597979fd332b5e8a257b83743534a8191b2d44a42b90f85e2b685dda74c27224e36e0a2a9509e46a4e2b7fed1b7f4b44502721fdb020ffc4ac0db1a2458b54f659b9e11a8cca8f565021e2096633c6670bd540d6fa2f3f0021e1b2234a573ae6db775d4d497a87500ba6af573f3eb8aedafe3b6821cea1a7a012b273f3aaba3e28c23048a3a9c62cf4ea11cc309b95c9005b08d6c205b028c8dd64540ad6ce78b7182e3a8855a9ddc138fb799c6730bd458d3770ee1706b12420c5f73fe6e7d39546d8e924adfb5e5ad7738fca9b756fefaf394c5948e57ef4fca93007c2d7af4ed7c1eb7e7c93c4dcd2abf129ae35579b93395abfe9fd95473b81f0ba1cd3afc4ea792c282dd3ee5e2d0217218c3802c89f45588dec1b5c478616343d9c0ee68f07ae9028e989ae527e3e37e4ccc0b0bf0d9190d4fd8f7a03f13eb72716f246f3155352d492c8c51c06a04b037bb69562eb9520fcb338eb06b9f8a5237c84d63aa6da3128b5ad56edd902ecf8c5b222687d0efddc11c7b7e95c758dc43373ecf71afffd4602f704db9378ccd140fe8388f4966171e26d96b1926f0afe54b21581f74b5dbee56591044298089580d962ec8abcda14e08ad4c4598ec515d59eb59270cc076ae88193687611dcf2813d31305c762391ee81d14ff1a1d357f3396cdfb0f97ee8109a01d5a94558ceb495da6c8fd8f050029a82414d7c280509d410073096af43fd348650f6190517ea94fc64859fa5bac9c621b93f414175438329dc80864465afe273c3bfe096155f32f7b1af9771fc58393ef32386a3a7e912855dbce0dd847330110d4244d79666c855fb6cf4311ed76a32836a62ca7d691e0ae1a5f25859f9ca957ff848287e2e3812e072201946d7230953b0b4758c5eacc8d661a903b253dadb12efeb7a5362f645dfc8bebaff8dbed58cf0b8584bb24e48a6680e3e029b6763036400198f029f712a2c22a9ff86dbc5f7f1caad24f1cf986dcd6f12fba854008f7be22f5ca4bffd921007d04e3ac1f7ba221a2a48ca4047e973cef6c4f34f5609077bc441ef364f92266300866511c1dd043d3edc315d78f7beebccf3ffdaf7e4effc4317e207a3a9be6eca98be95d5fa9e4d51bf2f9fa05b05516aa579f80fd9e087a62894bab9bfc691c915eb30eed44fb0cb9ec878b6819bb029fa2b44fd5c2de83af6328dbefeeaba827afcd92d7c627cf44fc1202bfc45a03fca21f73a0011b5f2407a796c77c2c86ae710acfe4a40ffc90d96368f9c96a29ec973752cf99baf01271dc7dc62f8e2e49cf0174e73edd4a74bbf4b055c9a921558422f1b0bb6bfbc07e30db4780c449dca1f776b5ccafd2afc215195c218b27c365ae10173b7c0e42fd44c1fd16e6ccfaa00c809e747f83c688a5ec7812315427d04735ce7c855653bf159dbd7782c901f5ec00db872f68c189f0467af96cc44f0500480ccd352ede87b187c70b13ca506718dbe958f49cf2b94beb94dc4b98d2ab8ce0198e5bea288712e09c6d6ac175bf02905afbb62d04d59fecba06862b609ea43510693a04979d5c0ef62f55bac2ecf0bb39b6e4ba46d85510f4c943fd72059157071a4ea24cacbe5b28f88e0cb28b6413329be54708db576c6d18137f6eac4b8833710bd2d6e80379cb14d92c11e69a375fc0dc81cd2f490887345411bc229b1343ed7760d486a146a05e7bb55fbe0d00df8c9f5c087b5a44af8360b52a072035908e764d3cb59e07f42aaf27f08c555fd9d1af1fa669e7972813e3263f53f9944175f4344b68ea1a3bb9ee70fc0ef51336f2efe68e11d3970c2a8972b5aca8be24c4b8f34f623c8cc6f53e10ac37d48b85e28e405ae231c2d859bf984171b3d5165cefeedd0fed6e0e46d993d02613497c40d7dabd947440f9c82a4ae6db3801aef45db83983b3732e49b0732e28ec5fe9e7b63e5d0f50f28b480c4ae2541450ace3a90cf280a8c05ba128ed63a46b036bc1b1186621dd7210722c3088a45edc1f45324c490db780f2c5d37c742d1f0f6fe318771746a25a1b631b11409a98154b85ab34d0bdf6b19b93b94419c55abe4d0021ad83dc88fa41c3850181c39fd9fa2ca79e016378acb8d99a716158d9861f4be4b217f048b43ec72f9b862922a55bcd9bdb0289959326df8c4f287c0806124368c367e8cb1ba6aee8b4a49c3456343f1c9b6666264c7278802d52f6c1a4092cb788f854e6573c55299f63f7bbab4e5a6c752b468a504bbf767cfe7b5abca27d899883f7361bf5dfe02dbfb04b5d4790ab81e32b9ef074d80d5117d621ce261db032b5bef82fd289cc439155c6b0d6a4164cdf183bfe306624c0d90121fd7a7f9e2264980d72a0c43cf1d206225b2a9e0821f870d776116075a585a5c0047fd6cb00d08ccd7249184e473aebfae82b64b73d1718b7611471dfde05e1ac6349047f63e5ef6b0a404ed23fb171d6c08fa9135bac5804c65576c040d45001878ea3cecebf13435d9ea2e5f3b0ef3ed3a62a93dc3bf7a2d0dc9feaf6735c50094cad9a36e26b02dbadddbfc168910c6bff2b16d30710f9afe12a73464853fbd139e39c7880837f0104193b522d6f16fb3020f301f8583b706d27c416fad547d38a774c7a943d6514a57e6990a9a8af54061c5e9ed030444e04ffb751cf2be45fddbe6ef7a4963e51923581dba758b7f3eb4c0507c8fc6d40253eb38fa7c07080dbcd6c220db6794fa4abca245668f3124e89e877c170e873da81e81041fe6bca6bcdabcec028d4c53962ae9d7a74a320c063a323cd3187109b40fb7ca34e319135720053dd8665893aa2153a64b2cf747a6a7d00b3c46010b47821b3fdf6013ff7e8e14648776fc5e150b20f30b3513e461b9cb580bb123db14b67f7d6c110e0e28c8d3e79645e0ab1bab0424fe6a132fe8287b15e4771852ee2b5567e90d4f7c08bf4d9009f047a11f8ca4f480c7413020100884c7854121cf4171bdf3fbb3eae95f7c258a4648f6c8c190f4e701615afdc6fe9c0c557d67d8e96e4d5a8c6ff9d2cf360e02c5ec386bc90d81017a6ee85bd593b041e69b8cc89b0426d2a6f68d4d59f5494e5b6a479ff6037c12104aad71e55a2531f6a9252e5f8dd36d2a7898e559ecef9da83ba257ff11c4565cf893ee320322df658ca7eb1cefb0261c38f29fe9d00f956a0aa3efdab1baffa610d1e7b7ff59a3a0b83fce01d24812eedf1b96379d40431140300f61cbf2afdfdb44f9ee3e931a620dd8489e6262bf7abf2826e3b6311f1753027c63f0239fb6318413dc4abec2d13e53a29390d856f255a7d9f52d7e5cf2d10c4541213d30f787936ba08be87da8c0cf90a29a7499b80281aa314c1d716eee87c040386c76d9cc57fac4c8519e92a8e4e129f558eb0339bf38691adaf105230b9b76c022c9867b3eb5cbdb7cb1ce4fba158f162e499cf41fd8946c056bfa80b07138e3904df623a49a05c5e8c7682d34391a9ef28545f34e26a4e52de807d1f50f64966865c40c085d4a62080cf45d1999187ec9cf9440b494e53f80084129a7f677e7fa8614e0fd14f68ff5e601bf6c465b8adb3111b6fb41f70e15e5489dd2ee51395656864eb5924ab3db9f4ee44d8fdfba5110abf26ce1a037fe9d4dfd790296c9d09c3b073dda9240d8cf992d7d550c810169899145ebcea68def10a5a52645a9c56a7185df2cf305fc63cdc1a1f7bd925f015fd14593e67d3e265b9a4bd8ad7631ba5384de9b32bc85f7eb005fb68f0fbe3b84ecb80b673d0c18bd1c4e96730b423fecc0623c32af6526949a969dc993260323af5edd41dd6411f97742809342f2f559121f27e6542aa5f6e3917fe72036f524f1ceebe7192c549b882abb6e3f10f4d92b1a96b7657023bbf4228b4d24f4f82dd5955b173d8c48840edf868c2f01b1f3a752da04684482dd2fcb113857e358835263a5406e5f4f60b1edbb50f48d6f7ea44cd4eded13a9711ec0c3d3c752ca5dfa52b9804caadf26f1da421b3d0bfa50ffabd79427023268f0e988ad91da40538b2a58040cea6709d10639d9fb93c442536beb5b8dfb736608ee0f55f39fa5ef92147d0fef96d4853340e0351e03a689d2f2717e1491f2ee4f7a4951bfe8c915db1f1718b90504f0e3703d30bbcd08059b95d1150eeb49fbc1febf987c06021f8585e59b00f1e454cced53c29d49438bc5cf25f1ddd2f2ff9b6a9ba455a2ad9800ee4ffb798c7a9615e02a3640d9ef65fe635c5fb724be89dea02df6cd5a30658eadbb219b22148044c92dcbc7c8e5df578a321fdb70fce2905146ef078422d6ea3704bf90173f4333c3a629dc004dbe0dcd1f8d6bc7b77bf268bf704230b82887ebb5c24f408931e815b5f904e188e7ffabb348e6c8c49bc64f3e082316d57691eb5a8e108ddd20838b80ddf53fc7c9378968f5cc9f8881e6ef122af7aced3cc7e4724c69ce8ac3b9114b3d60bc395fcbc6580a1e0dd38b19679c2007bb995802813669476c405f3e089746ddf1c52d37a2bb9c93be44c55a3db2ba3275b80aecc6dd1397a9bcd9a294f8aef7d133143ad56dfa248bfc93e7e7ce2162e574e4aa7ca1109a44321f24c4786de5f0318b6ed5b76a3827f7c622295b743a1a82a108c0275b9afbac4db4bb329cda90607100d53e01f140f9738545916f5995c0df351fc0970805603145f8ac9fefd3bf2316c87cd9df29489bd4959d9298fc29b24c6ab5071c02820181371060a7943d2dca3e07ff1f8859ceed5262fb8cff9ff2e94460f6de803b04275211caa10f6e2ce67b96655ccf7cc439d318c35c04495af8dbafd638edd2e9599a9913c25ec0ecca2028879458afb04ed58cbacba4ac4b56aef7a141aca8c893205a6096a68329ced26dd22c30f4277dcf870e8bb407dbee8b1755a4f632f4e4edb5c82cffe51eb7ec6e1a9d9ac71cb03300fc242e65678a2f6ed197a2727faa39fe8b8525471c96914908521d17b368ecd13018e0c9b7d900b9a66c20c598712ade6c09490b73500658560ac70c466283cbc341131a96f51213868ed7ad5ba2b099d05b1abfde38344cd0e69fda901014175d6e000cf7a70e88f256f43f6d5ef2d623f438b005a6c50a1d1097c7261b6302f63ff3e71382d62857759a50155b936a3768af69aeb8c8ad6ca89a8f37af94742917a895e306f67ef7310dd1f81b777e1274e1404832ce9b351174fc4c2a628ebfebdf2679238d2234348f4d754940b0b07667aa68fd5d80ca6b787fad274613daa272fe3ac1a7a2cd88735e00394a8b56f61b1be48fe80b6c06041ea55c6de274ebf10239eeb5ebfe287b6cc15e03cc076497c4a552382b45fb64efa1b58cf9e886b4d8e865c4e8a1c589959fa9275cf83b7e518505aabde78799c1e8d2be84e3471fb8d8ced5782e10633003a494d6f1d6ff24df8e78e30d67bb5c24f64c7dc08ae905a1f94fdcf80819583873a527f4d92de2beb9d308e442393271bb037f982935a4e82a84b973bc50e7027fa0c62bdea4a459a8a1472ae3e2c7b31b0ec19a329a281732e49a59a644ebf1ce15bd380164ed997dc64f16fc1b707c0c0714ae423458efbb051f5ca2c1aada9efa1db4a0115413d362be2d6adc1e28e99d3b608385c78b06ebbbe8fd33a536451ae16976e32d2a4f36566429410335b4da12699ec33e47fc73d5f9937f7f16c437e0282d94c1b1fce6d2670e16110c03854580c03730889fa58e1f7f3f083f7e32d60fdd8f9fe3da70f1739afdebb8bf284ef0b05b9f1c72fba4b7ac4d0994203a7940b00ff843d8d4fff800c35c42d76b7eb9caf034f5c484dc893952bdb41360d840b97c12898af0ff5e6683d38a437b54109925d4c3fbb69db95b89cd07fe7dc738f3d5fee803248536fa9d60ae11b732a4a832f1285ca4f18dfc7ea722c9faf79cf2708a8637acffe9bbbab9e8c64d679f2ca7616b4ba9566c53002398c32f798412040281f0653e1c8f21ead8752ce794c15063978ca293d0ebf8047cc0f065b67ee33183a14e948df13566e86604761a28f58cc7dbdfcbd9a0dbee7dfd89e8af24bf5dbfb399a9b75c7013a036043ee772ed22d61bf8fc83ac95c0beb8d6571d3af0656af88b0f7ec5d239817365dfd3b7f982feef914a7bdeeefe3a8ecd5d36f9c805e2c3d1391856e24ac3cd85f2452b57d2c76a51ff5d76b6c60de43bd513bfa26725a093bb1fc57500bc30e69194954c6ed05876c0613cb024a42b4599c01b2e6bec979c9daabb8c570fc4140403028140a08133550d4f014635bba69a924d19604a1b2c8ef6f4e12bed148f43e2203a5de2d40556ce1da3a993ebcd1b0203927edb8f44c2145dd59dfb9c7c8271ee89ac66ffb84760b87fd1613dfbf5dbb400dab0050d82312b169984903a3776c7e156b5ab59ea05c74f7c46d244c5ba435f853f66a6d4a1821a228038e29933d21a6d3ebd6336b2f3c41162ee68cc214497d78b484674ef163ab973807066c77325ade7e945fea21ed9cfd59e92a92bf853cb22f94ec790e0c9982831989e826d513593cecb7f479ec3dc8fef44cae389acd63f1e607f38c0e6d167f977d8bbf0d058cc7e1436adb7022e3eeb9611aad3bd8952f4d13f0682b8694b95beb065c349d4429ed7926c6e7c7b203a20181008040281c0dc50c80b982daabc4528220601f9cf503426cc738e7758134ee6587117e147dd603cdc12b168fd8b21d1ab6ea6cc73f6b883622509fa682cb78a148b177bdb35e08468d77e059ba145706dcfa63bb9afc1b44b020a517d1d0d3a24c4b624be295ec1563760555c690eb84685c176a9d6a8f9ffc4cdcce7b2806993cbef394a2a878d7b7b436040a7438c5ed16b478be0ed773069a35aeaa2c1fb670b050e84bb61b2aff0794ff5004dd96879dd546ecb205c05bfdcd9132dd1ff20136088a6b88f88f509d32129130ebfc55eb20c6cb57be2e697e997ce2870e7323e66effec49c2936699a9f7fc0e6a529dda956f4769f91e5522537b0ccfd19b2ea438dcb009c410bad64a9bd1041a1065b64712a43dcb04ecc893f1dad147c577df9def750bc09bc2e5f337feaa8e3000cac28b50dc92bc3820971908c971a4f3161d6c7515fb8778f957568b3f188e123009bd5ef9259f2de8b67a19ce2b4c7417de6d763fb197d07e4e346cc93613f70d3b1d90bea55e86310131d40bfb07a9e8ce24b1f8d104a8c624d8f07ad0009fcec2f46ea59959bbced333fa5cfebe4d7edf9008d894da500028ced1155ddbb683335e567ff04d7d1986f4f1e300bfd39a374113fa1a6195cb0fc7c4c2394fa09c111852e587db63a3f6408ba35552682c760860a1b7f695b42115687c6a665072ca8e3372c81ea3b9468fd2d14716ec34ff995166f2e2c7b70824872fe85b8ed944ced898dd2e0e0e02b910db8b785e4436001da64ba51ee4bdcdfb9b61a1943cb13f057e50a22aaf61dfe83d81131e50d1808580c29da9b0da91a31ccb71671a67ee78cdfed9bd3f841f5d16f2a95973d1099c119ea59d4f09fc76256cdaf65850d6f4ec75e2d8b1db3a6750c62bf8c5a1298cc23b16f84779d3f1848ee976f98ab955907b440a7260be315789ccff96386a2d94a1b3eb12fcedf3c5d788ab1a0c119be335bc6721ceff382d114e010cd23c87887ff2a931df621de8da66b6f6f4a1ab284fe9ecbfaff9b9fd36d7528365b205ad9233409adab75d222bb437a7733c1207fbdb9c717f9fff6db57a1fc22e7399a6880039ba05bc151a70a574baa688d0f8a2de6d1b0e33a1a86ddee1f0036c57e7a636f12dd0d5f185adddd98fb2c5aec349b6c4ef25bf6ef8f5c174633b23777026d8be193197346644acd0b9496380277d716222c046cd8f92d7f2082ce0e73cbc5bc998ab2c49f749d7a0c54d2a73b6ea4ab453f7b74f327b268ec91c7cc8f10e5dd788561b8fdab0d48fa628b8094021dbe324d79a6a5d8d93dd9a73bf79726b17c234e87662e0e6176a783a0cfc95831f0de8612d178c71639dc9f64f263db5d3c1dafcd70f3e3a6d2668c99a922caf726b8ac40201068793e4c32c61f6189cd91143c1f659c92c2f781f4a3e7b4fd4b8c04fd5e7ce47e7a7dc59cba09c534809b77b75b795feb0d27d8e5f879cabe783e5013b15ebe87ee33b6ed00a48775bebb19047dae478a817d3c04454f9e3ae836eae37018070443bc621854b29ac47cb9c3175f13f34e02868b24f66fd46dc7bfd26c32fe0e05d0bc3f632798ee3c9e30d06c9b704b8cda2d6f86be157e15ae6fa5155fce528f7ac345044640dadfb849ce49a48fbd17d93f62e2687cd2b88b3d4c2180a2884d329178be599175df566b246240be6a0a6ae42a272666f341aafe18cfcfd8bfbadefca2cd724ee03594c0cecefabe6943ba3e0ec41cef4256b39974ac2fc71355d97b142d54b70b0bbeba3317ecb3ee0bd83de21916faccab2d12a88622ad64157221052a852681c356073dfe54ff2f76f5b87a313c9f77da6156e9e6473df258883db7bdb3c524e2ea576e510052b09b5b1c73f7651911ff5003cce0578a0c2df0b7a6fc7f2ec45bf0edcbaccd33de046cc48db290386f1614e39949c0d795d0eb4c79d6d031571601a66bc757c337f45d07789015505e9f65e4a9fe9e2ed8f608ef4b14a58cfc6f84acdf8f97aef3af7a59c541ed4ec780b783f4caf4c6c8d23099306f4c3c35dd43c24de681a984be057e7de1b839ffb363dbd0cc8f26ac2aeedb01b7aac8725f5a33c6c5271327bcb1c32bf1570c2251a1fd332bea869943fc7c3613258995f6158fd20400cdfc7d388ea51064ac0bebfe822b0ae5e722babdb3a5d034f96172ff699da1b807e6007910ef6b42dcf4d7080beff7853e75850a45a5bdc5271fc8656c49bcae367b1b37e9378c6f78feb40ff7c968585452d8d8382dbbf94b3a8df7bac6301f5afea221acf2e6fe74dfc7ffa58668c9d83fdabd27fb5b67183c028a5984e9d113f6278b4d411640d430042eb55155eba89a2abd916a796ea5f2abac8aa401a4b2f560c7a3f30247f0963600552736d9efb4fcfd18761d20331ba210e1a445e0a1ffd4c1bb58f01a1b80bdf9240155945d69f83f5fc76940583aee0ccdc7c0777192e82d51c2f2ae95bec25ac34989b91eb436a6b6dbc91caf5e9ebd1e21d47e0dd07e25cb436040e96e60a1bef327fe5e8bd8e154e9175f99f6a260fccd64ffa501b53e6d6a4329c0acd79374558c4d02742d2054c0237215f41945352c273987b062ce243c1412d003c9b803a73814c902e4796e64080ca4af337abb17a3a37ed1af86fd53f8259d9bca169226e82a806008fdc75cb5d208e02fa468cb81686d5a9e8fc4590804e263d716ba12f98df7e82e576f09859e5a4f28763735d372f7b03c901b7a76222548fa12fa5746fcbee1cb682776ebfc9de97a0bea27218967734938dba04579fd2243a770107e4f49f7d1e59131142ce9e1141d5675e15c2b7ae40e73765d0488a253c306e5bc22c9be9234126c88a17fa2e9befa434e2d6e59220b0da1c73b1276ca3f08e2c38ea13df44576580812aae61ddc93f07b2fdf4dbd14616fe8fe9a66f45d6ab676e2bc87fcee69080c7878ffc450cba23266f80561d4fb041e7479449bd53afa229c007979e84a393e0790fc3f2117d978f350d0ff458c423c9151c4fbfeb5107cfa1df53b6a59c7a41d530f4c1908062442c92b6389d47cab97df1f0abe7f6796c2264e7c7a79eaa647c8a4cf164c2dad40b4fe168a38b7e1e7b37e41de87be60e4b39338624bc0b790c78429c1b45833de72e34b032eec4cd1077e009f8ea195ba9abef417d66c7ec7f3d48dc437e7f8c3acf5cddf79291f8eed8d5ab8e2f90eaee0648b3e7597391aa030e53f3e7e77cc94c1a3e2ec68156b7e989d1c0ef9833f7d05ea7e05fccfa7ad528d26844f5f19977e3062cd5422dbbe69c8440c54b8c4f2fabd4e009c794ff16c9ec815f5263f38e453f3767e791ecdc6cf91bdd5f6741e143b1057c4bec38386804ed5f104fbecb5288c2efcf67c9fdf661c3c9fa4fc34aef055bfb51b660a0e45e88838a46dd3005a7f1710e53d8bad1edc18f612c3d1a7d404bdd9460a59cc5d43d59cf1797f5bff84b309c5035405f2470cee6e4b3c51f516d0b5547e842b8f214508135c2bd90dfbe8c5868ce251ebe258ae8ad062ba25df4093f26016d3b9b2ac5cbad4721b1073f475767cf692d8c978fc57fce6c3592b947fc34dbb48d8d7fa4fb13de7da8572152f99472f0e7dcd87364ea735a34f11eb021ab7bf075c4d9d4f25fb99c0eb0c85415f90a2d8cd0e63cd1cad513ea2f72bf5c9c481a85737ad5d1f02a2af8430415c04f24c09992b6bff7234e15391de9a69c8b43572b477c401da868fbb551cf0c33845010aab7abf6cc322fdb6d882b2a100337e316b9553415360b4b5f7fd1dd0e7052f091b10346dbf499889b052f74847900a55b6ca8b74927ec9cfbf459bed818906c180402050b952ff25c8e14ee88585536d350c93548782cc3cd632a538138060bb207ea55681b1a91ed8592b3df51c639b8f23b7c03bcc1231fac1a3e9775015431180b4a240bcc7c349ca976b4d5bb9b1b55fbc04b1dfb81779e078d57c7fd52345c800e2ecd2de0c6996c6f173dadfded88635a63a7757d9b60dc4eabfa3696ec2cadce271ffa190e79732f6152a01b069b29c9c68f805898deb6da23b0632feef59b0cea7bcd022f816223cdff2c30118700c8c3d0d25e0aef7961514bda71df67ffb7d811af56fa872ec9aaa1d2eb2ee2f80c03deb59ca6ddfe78a50f873ba70541f4b84f501bbd47e6f5451eaf1fbf88fd2aa61298057954ef4b77a37cfca713093e2936c8d811aff5de415cdd10e50eaacd842b851b3a5f793568f195106ccfc9f46809b70f8eca8e8eb03fec9a17cce7657ed09b940e978815cf31b872aabe7502f670f58e8b997e0b4ead8c967b14f4702cabb789654a277a8a3e48cd3b41e3d258aadf7da78a36c16c5a1e118712c59d686019699d0dcf010f1d0b4989aa5dd63c645d3eb4a30cb368b9ef81f8a14df451f38f00a14e4a714b653d7557024c8ea04acd9fd0eaf50a5fb170e0981e511ca26a031803a98ab81b06fa51d8e84cec0d26dc008f08d56198a0145996bfbf99f2ebe8e627dd2ccaa6e9a4f18948033abd5a3eaedc04c64f3c03b47400d395253b98424e26d342201eb3a2104f57718f5180b7180b7eba78fde2e7f251e22895efe1f219e2bcefb12155b47c49b8e17076249d75780a3fbc23c2973a0ba1e41b4d757ffd3b8b85f12435258bf09956d32441781d125548243d3ef1c018f8d82acdca0af9fca4a6db8cd1c9fcc75226ca8a6ac3ddce99ea81540aff0c42833026797dacf2a405ee1a3fc127712cec41ef3f73fe8a2fc4afa0932a8a9f6415f846cc2fa901f0930abf13f01f4e7f2c8971a622223d9b95e755b1895665f93bf6031e6c904715fa93eab6037221766250fe6bb0d5074f30ad21f0ea77e729690b4cf041d0c9a58a3f963fc34bc41c1f1f4f303be102ded24857f903a90b33571df8eec8299868a1e5bfda18cc7976136742b3039d8b096a6951c032a882bbd801f64e5f6f5dbfaff5d1fbf14538b7b62d3ca963daca193b53d47effbc2066030829957ac4578267a81796a721cced64b968fab4cce4798f53c25db121931ebd8384c0eed5aa1878d8269aa10f58b34010ec2ef311a4ca7a7ae40949cd9fc0abc9f7b7560540ee5f7540ae5df8fb4bf216811070e4f90a72dce046b220df986d7dbcbca80ff64c3000d8a6b0bdc2a0b55513348bc185108ce67b71a96548ed845f51dd36bf6184d114226c7776d837da28bf84a0fc1ff5178780be2eb7b82a701634a3a420fb4074e9ae0c7bdc943b503982080e06f003aa1feb45fc7e14069cc15c27687dda67f8741baaec7521d16da24f93b8d346022e5386a1aebe20a08a1b6e5c3e199ff043fa1cfcb5132592eaa406f7abec8c9b2c43a9d1f288b67d003337be18e9cec8c156015e139c9ff27043cdd444e5ae0944510c33bd9a85660e65429e967bea5dead88f26b5f9af2fa842f1ce241833bbf1ea42323be6146efef5d06b984f1106e01f46e8f4e021c4311404377426cb1d9c5aac8ef7dba235f6367ce863f961dcffa55019ffc5496869fb900343fbffa52afdf985d1c526765e1df48d04b336e76cfc6be76419137114fd3de412010089590eec417475b35acb2850f797ee2408b2854d82f83c7fdfd85a108378555116958df2a9e2a172d44621d4b0d7d6583205cc05270b38049243ad66cd4551c8906177d1a8b3da5719f17be3ae6b66dd95dce332bcddb215982cdc5a507cd51cd1e257ffc65df49698a16537444e9586dbead81d523385cc9bc5f2233925120b4f52d1dd232666632b78c8490dfbc4bf962b7cee93176ac124dd99cf554bea19df23cffa0aabaa9607a168108a80d7a195a1a1269834fbc3feac19ae82befce0bd58f110eb671b9c580c5a7cb1e6483938c7b79406633f8bb2e0854c0e69e7863a884c3a8f8fe3e570b8cd6f5dd4451cdbc14c7bdd276ddc2c11ef83188efc52734966ece0043c5f4e46cbc37f868267fc7b409b8fd8a7919b3f8c5cbd8e2e9ad8abe3fa6b6c917edd6d243fe5dba30eb595ef14e83aa78fa318d40986b136b17dfafc9df7e73d40b4eed566df789c4b597945c11f1ec562ca83dc4dbd5cc9dc968fd2d14716ec3cb58000344add5f9bb512a818f86cb62e977f3b2855cc9975e1c89740b025f3bb69a7f8100df9ee26b41bbdf155b5915063aa31a4383f9c9a6d1fa2521912d82ef5f11e1bbc0b590610394cfa72095ac71aa7c6d09b10b53f58e28839432328901c6c360c267e465c7488493e3fd35737d39e836da3c06e84562c14e43658d5f6e106e95ab68bce5005ddf4e44e243633c821a62816f51a8667eac37dadcd5df9d6e3c309a5d4da450fe999d94f008589ab3410016809f6eacecbe73dafcc77f27f67c3fd0bfed32b1ff432f1f130dbb668c7bfcc14a5c590c853c1774474fca31ab81f9b6cb883058559c6caf3b1766f907c958188a2875357b4175cb27dc1d694493d7ffd368575380631affd7646f3415d3de03fd0fc0087b992ceb22b1822dbd50dee11ceeb44ddbc643f7addaa17d6f3a92b058d0199d03e986be40dab1c7bbf78b43becfe67f4d17a45aa6d670d6d1b4fe2f89dba3741d6a8aaaa5ea444ba2495b2746d4f4dc2063da6ee3a3f5ab6b06e4d8b94375ad21c45a03139dbfa35ed089eccfea9e19518f4faac325e916de23fb752396c7705275670e685079a702afcde8337740d5fa9ffd4af0b2a824c9ad77efd2a0ebd26d3155e6929f1bcbf2f2093d5a21fbab67409f53a3b09b02f1c00c376b9d13ce3ef6fe99347f1172f5ed36ce33438e0a9b8c36a21caa75656bd3c7818768313f9dff49d1880af4abc72f691cba086171bed418f973f629d8f84b6e0fa44fc660314bd607c09afabd14d9afc67dd8a1e95b936e7fdbfdc0208aeecb68786799eca1ed670cc91ea4ea2efa8bdd4dc33cdcc512fe4689d63a001aabf1fabaec8c6b3281014efd4d7a6b253238e0696e0e32340884b30d9a434ea9b96edbbb864f9de8562a46fea062bff27f650781bb6ee1b99dee28bb90971bc07298dfe63ccca79be0bfcf07e9751111ea4f6c676600810474bc2b843129fcedc744cd1ac4421c90e92651f3e0c412eba3f2723dec3bf4dfc6d853ef4fea550116ff02852a7e1236c06a42939bfefbb7b5ff77932652d8f0a8fb7a4bd428e745f327b94b9d1ee1725b70913a1ba00268e4393847b66309490bccf4752b3d61393ba9db49f752658045125fc95cc4df701bd46f35a16191e1c861e844fa2cedea355cfb1add71be2462eae166fda21a81fc32021134537d9fff6b52c3365c1005c73657b41e8eff09c5384bdb1acf025ebd80e01dd24184a43f343ab2e0a5eb08159f1d78bf096d926a5745cb0cdf9e8a9b0e70e7b70d50033468089c8392b084a47de699899e456cd9311a786d3e4ab1b17cedcae131b09359e767968d436c33983d57df1c330ddde4b33e635cfda5d8ba169eb836574225f1f830b5931f1dedc67049628d5716fd98ee571edd2dc57b49641d8c2ef73314e265f0d4ba065888d01356d29fde7cc20a803ac71ebc5d6cce0d71a9600cb5821d6f501dbeac828db5505e6b5e765af48d1575331e09d3034f5e31f6314ba5d010b6cf42b27252e84f468900af2e40dbf0b137c402c4121a3bcb05bd069e1bb98fa5e3350f6ecfcb282cffa872106cf4253ece3d3f034ea2ad86dfd46ddf2d50a3fb82c0db9cdb28b7b2a4af7979301a69235fc5b9574bb2e76ce581c3f2c0818f8d82ad6850b81e34dbe662990fc0d6b201a649a77b82224c09fb00c79346bff5a2def3b94a4c603ea881090555e0d21811eb153e463d907fe93cea13307ceaf1af87d5eb7ab99a90fd30ff843c6efd235cc0e05b3e3e00a5fbf21ec5361d552ff088ccc0c626537ab260fea705f1e03fa0972ffb80b89f4c58b4c9bafa5ccaa7fffad46a54e28e83844ff84cfd3bb39b6cf5716358e13020005b22ac34d8ba0c08fc0a0fe173a5df693ff251a9f7d5b28c1efa51f326bc52f65069be3beaad4c8f954dd0e77ab4b0d72ca46d014511f585d25959b9e6fe17a19743dc8a12be4f0c7df2bfc68f057df1905fb79a729c6d7ff918b5f6b7ff37f60c011aff4a1505cf0c4247439dd9dae1efff011954f31f84255f31fb237ee94bfa8ec73ccd54b5399c7d940ce16ac8bb0c2e5fa0125c70eaac2e5bb193f585e1e8f9ce629d4acc4857569c299bacbfa2063c7e571fe5dd2174f8af92fb0112b2c52a66b4cf7b538f9428c660766ed33870cbf0ae30f1f2fe14586360020feb5e1d43a7dbfd0762b836c665d832538cdd52a49ae3c2ac53334e2476bc8519ff95d097caaefb78524813015132fe2633e6142186cde640daeb64bdd9a62a64278e572876ca46606f488e07c0eb11b5308439e38424633ce14290b36213ca6baf324637ddf7ac1eb55936aa7b30eb7756828d0e5455dd2e1cc2c03e735317677ea6159a13cdef813534f7497768f685934d9ceaee647a9f1bddb44557740079abd23a0f446d18f02bfa80a0fd8a89a10840ef41ad90c957f5eb8899c9aa2f062144185a54a541fad9525c86492c9913640bf810757ca540e5c7182578bcb682ef7ffc1c6d3a8ea624c52622a1f8e1ec77fb13c166190bf872861fdeb0d620ebe841bfb022ddaa5fc0115eb07d42b8156aa9fe4e739c30027429091ed2b2753bb4fe2e40f9b7c3bea852852323fba40fe5a3f8d8c0980b3534af605b7166db5bab93a5b36900ba76295135527fa74f52e3a4ef67c3fab741d8c17343455652dd5487a71d469810ca101e4b2c1ea00baae174d012fbffc8e95ff24a1849e957c0d2118a18ad1bacb602d1fa5b28e2dc869ff263fc2b3c1e792e21c152f8e9b1719eab2fef07e2e3b399e341db09f99d62d43e02c09f918ce8deae3a6429a8b5ac8978cf16164fc371b4c95367733deb68a056f2a3121eda997ef6c74743e58d0533c1de817ed572b4c046b135165eaf4a4026621eb9d400817ae06214ff4456788cdd15315c348e8d280b46097d1d4f9f3c1dfb727d6eeabe640739487891021bde9d61ef13ee32e8d4b7a2acd250f2c2e4f0c81a11153bcc9c9622c0493c4f8a6fab4b288347b715466313b249c810e79a24140b0da64f82ff7b66fd72cd45e09a0c6ec7aa3d938496a4160171d7f09590940e775be58afe902b1b09a353d91b346993a0bb10e4ba156213a8150b95f24d40fb28055df016f21ce9ca978af3a78d821f8f45f06a400a8bac6de4ee32af68d88850d002b28d22801d8a004971090403b9465b436262280228e4582375ed739d78481e2e9a1126f9f57552911476018faa496cf18b3374c005608e273b142cc94ca26d53c9fc3c3044f3eddb7cf0066739fdad9f3298d48bf30bb9f476ea6928750529388751813a2bc8bd2470c8fadb0ae63243591950ee557a329730086e834fd02634caa392240c9d98c5fc52075e85d04888c25a42e4e3cc99602d0613e135a2ef6978affa7965effb4b224a7eee46ac501a5dad53fd540858b71a6bda1f08875ba3370510398e55c8d9e21393484d87db3fa105af298159633e5eda36797ac0bd8c38c059e0c74223bfd8f9ff7aa3730c93cdf0c5bdcea27efc25f3f7a3e69adb9705eea3c5b6e1234a40329996f397ce6eb0f8887f82ec87ad4946e4d6e1af8f3c651d98074b811a4103b9e385a49877081a2021a20b0eda8f92428b7f312a4d051d44ace59b82a3644adb0f328493b42bb66123288e38c053c619806415ca607129602afd90bd059fcc4759ac754fc1b75dbcc0212c622834c26dd4036ba2dfa14dd6376c21ff87179ff286202a998cf9398d541307020d6176ff7d60c46fb84d05b3470edb25002652c8ea0710b193074a3e215ffbe175b7b90cb6e020a6beb5ca293c55b81d26ef619d801d4ff082c387e8a7c9497fe6bbecd4068e89edbf5f99f51470c05941f3516ab4427b89235ab4f84e0220f577212a8fe4bc19423dc45a5ad51d72782b07d6514d25f4dc3cbffced0655b6331a3f3305d84c438d2bbfa8eef51d98c40e46c71597aebfc33e6a2f307d7a9a3f6beaec5ce453ef87429ebba3ca5b4c93fdbf7786bcae33a7c7b4a3c57ec3cc154a15f2f16a0997adb0ecf9188748a0e60580ba65b4ab6b61a826a9cbe867dd96e3a108603dc4be60796961d196b0f6cec6cd0e6b25d7475737ac728f2897b35c56677016704433558e04fd6fc272ecdd16f5cc589cbc4b3acbe3feab72ea2f1cdbb2667d0be61a437983f93809d0f2f7363ff34ca8fd8f002cbb0d1536126f54894676b41736c83764b2ebf32009651b347b3ef57c80fe2fa62e91e070b7cee7fe1a5f82971f9fa9528cf1714fc5244058db2880e41e12c7a2d7f3ba9e57810127dcc3e110de4a93e99dad758ae1bfecaf86bff335e85cc31f7dc5d6459bed7ddd99fc6d496c57ce2e126e2ca98922d3e8d0d3112ead7301fe6455fc840093699d0608d126ed9ea38fd4106363cc7593d2a6ec8a3bd458719fec8bfd1f60b3a4dfa2bf450cf0f6c47b51f0c931358859f59ee03b702d39505d6e84b199f152d1b23d988fb1a612fc236fc2b15d152e348541957e3d1d57f306c556b3f27da969218898ffb11338736441f3440e22ba8cd7f62255075f6b13b44e804eee6b902219a91ac1f11ca5eaf0ff194dbcd812f5e0c06d41bc5e796676979d11d60a5a576b36c945b7ef248a08df84ba4e31b0e2017dc917582196d01fe1a0a07c799d0da32f8606a2f7a0985821e646c26fa56bc513b9d076466038fd1d69cfb1c8631917fe4759776690f19fb4676fee2d211ee5a96acb8d027f4050ccd080965704f05ee77a8d2d9b3a66619c1ad8bc35e07404577dffb6a09ee401d06181144bf3f6705f21ee365052ef0364937845c537b52772b0e351dee28ff01e588a507f466024876d91d0b6c90c6715689b1cfc3a9e90de94d8ee8a2a134fec33effc4f06b1000678263b18d9fae469bf3c8539bc49f0fed06ad32013b7d8ab6d182bae5f018ba103c23ba86e3821f7f5eaa197b2eff5e13518aabb2a8cf7bf4ad85ec72ef099983f230ff2370f72fbd8284853ede783764dd76a28e9d81a382d4745f1380d41dbd9ff4f1fa00c413dceeed920e46eb27ee0a3fca7ce08d8ee5b185bb764b09a4fcb628a0cfe0998eeacd9c98118cfac48a66d1c8016997d1943dd13d1f90b58fb4f90e31bff21a684f48910ba393943d1d30def38f9ea23e7c4cd7e1efb4500e399e8e70c351cea0464381695b4bbe1fa0b5017569ac2cd500f6b5367815d9216edb0302a97d3511cec072248084bcc55280a2baee93c13fd9f74a4230c9cac2dab28c1fd6296b20727d1aed93c40d62ec1edeacd3b53fa98482b36a205233ab15d063dcc95492a9c854e37c3b9b40766fb32e97870dcac8882385fa24c0ae335286747bb83453a22e6ea6d594d91ff5c629e3a087622a23b46654dcbd23fc121508faa9025dc293087a8905ad99797c5c9435754e75e7e12d019a40e96a10820a881ae55638884a5c7b9837aab4f99a12cb4dc4679c5278e9c4dd150f9ffbb2b805b269adde2c3984a7831144511aa19d42dfa6d669271e8c9fab464034ff68a0c4c9d059bd42c0727bf670276e62bd27a934ca586d479a742c9820642c2af23ac70c2daec3ac8654d1380bcf0f2180c93cbad01bb64757fdee43f0604067319a8b06c75b5d8ce9e363bb012bc7d6e3ad62ae07e34cdb8871e0feba4b8e3cf5b608b19515b088cf24a205eca5dc27d9a5376410c568eb7a8a05098c1b484f07cee4e7d2d6c1408c3ecbe2899ffa00cf7a3976dc440a6fc9320952843118055e6ebeea9f452584cf5bbcb2f148d348c0518f5bf9469ab40af560cb9e19f3380261aac9331d34bfea64fb229376dba9599f858ea917efabdb3eefcb93f3ba1a7075934dd69f1cea1aebafee2ab8581953735893bbf38f8062a639504fbf16cfc6a100b45f0580cd82e1b9995d9f5ce09ec6279fb2dfc74c9b23b7c1a4232929f8fadc32943706bfee13a50904cc26344edfe56a4b6fb589ce5f5641334242f48ab93eb4cb619a8d112ac93bcb3dee06f167d8166d4c1e5e94ba6768960085618fbd10dea20579278c3a47da16c392dca4fdba2643e80edc8b06f19cd1c9d9bbd266b55aeafdbcb077ddd197be69fb9dc9abab2ca5e78fd647e0b7dbe8e46d76cbc8e0dfc2e0005ec51a889ae050f7fdafd033ae6afabf7fbeb6c5ab4aaf71180a8e974d50611c197516cc347e5e3801c83d7d47fa885fafedd38d326415a99b963e03f0d18b79fa4094451c806d5924bedf389250c7567762495dda015634a3e98f31f72485e1c2059ce2bc6f26f49f98be13a3acb86abaaf238d9346de0e0f41170ed12760a9c8c2e85159e83c4a2060110d019923f3e592f7da8b88d63ae21388ed93ff3b9d644f7fb157bf734a2d96dc4a38ca0b999d5f43b5efadb317dd757c8b5c7e802a1f6327b6fdc77ae4f120b5752095e90e05c1ced7c6d5d40b347005980be83130548352cc4aa638570e8ee854c508708ce4699c614c8990268e8e6c817ec4fe319898591d450e7af2dc55f018844780b6bd81e7518b44e786c451c238952c51018f83fe25b91181dda13039e78618691a68685ff71a56fb53746e2a43262b41baa03e0763a72c746ad44a50a7e26d77a3386e86769e887df4d9ac8a66c087f75e61945c851dd5afccd718aba0d77ff0f05ed258527f7891923d9f9f70d540cec1e95d79bbe4344a0a9934e05a0d594cdcb837e1a2f4f23efd4153ad40cde69294c09fa350fa1e308cd817db9438c9c76f6cbd9ef9fbc57174bf049b8990c8f6dea8e7fb5dffbf4f910ee9df2e10e86c0c060fc55a5b787f92a4ed28d5de1589a95f3dcf0ed4206f1ac108d51c590ec4c34c04e8ea6b4997e83ff8583d9359dced43d5745c1019f329eb3be4429dcd78e33350a06dc03d97b46e6bf2364f9fb1e2a08dccf9ad0b7ad186bf46cb96e13944f15e91dbb8716cd2c8cb70b8e75d9dc60222f1852fe23f2b7adf4424a7c88e2c1afda46eff705d614381ead694ddac63e229899a237c0d2e9a73263c050110d8744ea4e14243254a0a945c3f27d4da7b81586e29e6e1e9cce5844f5fa4254f47d2348c881bd94ff79ddae25b3fe45e754b5e71c5c698fb1108426016eddb8b8f109ef6be25db604cc96e94fbfc371dd8bb19b0616ee8e77b354ac2f752288ee981e07e093021de1c805ebffba5fc05a51e52d449d456f315ebe604e0ddcbdc02c65a449bff254d0c26787a9b0e7cd5b34e309475711e451771d7f4719c9e0506435f6ef90f2eb311b0462644ef831c3cbdf6ec6ec8a605ab37864cb5230c0dbf5521169c22d24dcabaae1516b6da1157975f84dfbed3e54e9fc61dfd7f64f0f0c6abb0d946b998f1346d63a9f6188d31cc267ec93661ad94fbf6383aef5fccb4b61f0d8fc1a96f3e82109651b3ec6421c00eef85c6d853ca5dc3fe57b7b3b02a1ea235ac92e681416fd4b9182dd4ee7f01f70f53f7626c3503a1e2736f14d2ff411f81cf961579a31a16d9bff2abf74033243d010b797e6d7e36824ea419eee89eb6c4a98c0b8e5a94a2f2d2349026f7ea26aefe44660f1065ce8cdfa54c003e788c304d285c5c4503e12e44058abf8b7986d9b73f41ed5fa5f15cbb948fcf799775a38c2d5505a142c80e4ebe7959c0d0a4eb1eb53168141de58aa0a1f4eab01daa40f371123f82e5f06f0bba6af4b9a31177c4948308ade5013803e6ae01f071eb88d7dabbad1d49770dd3182eac0fced24f95b042028b44b759bfee56958fd1faaa8d1f9d5bb05adbad5dde9e156ed4aa99a0814d103813fabc691b7943538d4a044bb974f02f160c8e766d62994821864ecd0d5e9f901697083b527c8330a09ff8464f7e7085c5062fe66ee065a7f17e0de8f46a04940e1d23ee1f28e090f716b1144a7b0044b9b22393f3b5fde27c4874403043e1e491881d5775f0ba406dcd3b246ba39dffb6dd8fe62e6bd9e4a5d4ab8604c9344e1d1c64804c0b2b94ac2b624cebb278e834f1413748bfa28a3608299756921976203d2a2e500685418461b7d17663255ee6b3ea12db5395d257b50e060ecb5a97be17b9df1d045c1807b9a9e861c0ee988f4a84ae65ae644e3ef03a849d5f740a877f393a17fe1299401b3f958f794f0ca53fe95f5d96f90ba1b8c631df096a49ae716045f02780c32f91223284d80af8af351c81a7f8d0dd671cc20dbaa33db5be6e2ed5d1ddbfaa700f89335144613a6b8f506cc4761e1ad30fd3facb854129ea7748fb4da7e32e19ecaa6768f49dd9a58c0e1fc525f4304feb49f475544931b960739556aff75d0b4e440161e12a2e0504cfc1744cfd735dce76c9b3a031087d193810e85576c6e3fa9fbd5cfaaca7c551fa8bf17e805f2412d49cd6e98dd59a0cef50904445a737409ada3590406e6ee21649334f884dee8f98ac7d78fb1a955f86651b76f522cf6bbc73a76a78c2438e0161f8d52cb31c6abe79698ad7a1f500862f9dcdf8e4c8cf75df25459ef3c1f2343a3ab1901bc46d22c654effbe99d083f402820181402010088917fa82c4198dde3ea773ed8a01cffdcd36206bad8e4dda12daa31611a72648a11490c228189db50dc49ac250d425581fa2ff263bd0fdf32d604843f7816197738c4244b53cfafbd9b620a2e885c286515fa8362f2ba321dc0c4874ec74709bca3b18f60c7cb2dd009c4599b35ef6b8aecffffc7da741e78f5403f805f433697e398d4b551a9b26d464ffdab4621b84e387173daa39738f95cd81029c8ed1d749b06f3bf826ccd70a2605af88693d1ff3a375a98e3f33e0120a74c880e0a06ff1562b8946d79a1925b3f40ee1b25edf9496b0a97723f6974f33965fa701c94d0e7d63aaf78ff052c5cfd7446e228389d451a3d0d10c6de4ed0e4be1b9b68808e0abe580ea5107c1a067e77def74dfb1d011fcccaf6fb53119df76d31f9d3f478644444444444444e401fc67b5db9e5b00dfe05df6619f12c9ea4f2a68d8610a2c3d57af9229eaff042a3bcb7c65bd19bc810b3ac80efc51308601422de680777248ece6e09985c5f76b4d9c5da2920c2d43a0bb31b8aedc14e9ffcde2060373f3db2c33d62fed5fda7ca273db21743245c86640952052a25deffef508974b8ffa70c3b0874bf88323b7de41d4f77ade3ee10a74e0a6d949b2b3c2b2243fbb6c7fa5779454354c30ec872fa51b1c8efa2b6dd06d6e44444484815e9f33b0c62fb006143db03a2fb09ae0e84fc716f66d5d1de4f6732d0cd00de994302e905863cd08aa565683067d6615ff8eaf9ec2beada704a2efa56056c1f8377cfa3f6849c4df84fcba1741212e0f2ad72f7dda0f4b725efbbc4aa46c7e0a0968ebbac78ef9015d2bcdb01d357513bd2695ae4611e2fb9d9e2cef8edac38b387e1074e97f2cd06b1ab567839c2f412c5f5497530ed53b1e63940d63c961766fa34cc8da7148ddd7b387aa70c6468531950148a15a2b024e4d10472913b13ae108863c713c76c330f778cc1a52a0656c1f90ddce4b738b14089e257ec71821c447e173d152849dace8ce669660078a03c0129e40ebd031dba8436637cce7837a6fa9f7d719e6bd34b5853a7a6e5439cf16e19810bee06dabfc05506694935dbdb475cc87467d6d13df5bcddd41fc1461f5b4e40482358119e052f7a187dbb656d0425b5712348b8e6861d48cedf9d6fedc6023775d0a3cfc1f46de63853b219d461f6ea7d771ffa1b1ef28d95f59000292aef9decbc5b79f56fc5daa230f9732a4d6928f5c7a76aae390f8c587db6cd536cecf556fb26a7ac43c2cac5239ad420e741a5089ec646199d9cb48308455e5e0df68dfba87c040f8c78f892b9524e5e21d0c2ecfcd3f6be3667f16f92f8c4b30f394d8c9b5eb5f002bdd668263277c06b193d2fd72138d0efd934d3fd7a8fc0cf2e1ccaf1f9cf2553dc85aa5f2adff3403c6ee9e817584004dff84d69ac61f67d823c4b8eafe408eb06b8db75780d3c104371b0a6734696984898d38f32f1f051a18b76665a96f7d58b041da320abc9706b10006ba9683478b24ec1f185293fd3918714b6c39e858f4a3b7b9b3f0e4b2835ffd0500aa1726faa59af4ca9b486b0afc7e6cd04635976d03397b48c5eb75c95d88823f6f1dec0714f202fb5a22a804343fda8a1d36e6476d4cd8745eb427e5f7ad92920cd7c61af5e512daf182e3ffc99d130f333bfebe20439f6e63808a074ce1f7502e272c2dff656f4c8350cba8453e9696faadc70250303ee9659976c7ceb7e26cfe0346847d65a75dd448d3801de311c6946200e87b8e1832e7818d4db19ea022d63c9481c92a7be146b04aa373df84237cb9fbc47aaebe7fadcf8ec96e89353a6f42f050890be2e24bd4244311801d8a8a06fdedd7242959e9bf1f35bfc23c3a0deb136766bf8e769351c8f3a03f018e51a837355f6d511e7fa185fe8a899e16fe021dc15cc70f78a79731a567c9e8438a73f7f13d0b441613213f1053c4d59a760fbf75b18d597397ea082517cb703ee034b8ebcc491bf88b6207d043c9a6d31c93e7c608c0321dd4f9a282ff7c05147f86906ee32cf9498e8dcfe2f381f186bec0b847798ac7205f6250bc136082a68defac881e18a894758f392af05513437a5940faced4e0be2de08cc07a145c5e3fd8ceedaf2ae7c4dea7f894d473da3f6cf66affca11f893dca6cb1a93dc09c40cf5a0428ee82eedcc7b6723864f07be05e276e4ce7b458e0ee83b842628fbf78f840249be6b157c7592a581e9b2bb59ac7970d5682a7d262fa609e47813e1d9349dffb7ac10fee3640821748a7594874054db789f681b8f048a2707f7f02c74735cf7e1490c3aa7302ea4c09ef06ea4e3af1ed325b501f9ea5c9ba731717cbe255e3418d3f30876041300141b7ab3fe22ff5101b391b1f51377b091d61da40d47407828b920b480d6c8d583651bc5ff0c301ea12f18b7d1e8ed74390ff5832498adbba81831c1d4747e92b0894d98d2a76c21a62f69ddf41f878fecf088886315f4fa1e835ecf63644e17660e372a98616233033df03f6d9d41ab3c995331508ce811b0b9204d6104820a2f4882b969ffb7b6f2bc803981625b4b2b940f7a67f7a68da4902f3656c6cb331a5d02e79d0351e219f92e09c180937f854f8dd87d50b816d6eafc56d9cd7fe7eea21d5617c4ca0339d8f8275f12c0b39d07cdb9c6e5b29ebefaaca0bfb9422bf277cb13ed5c9c11c719bb1a7b723d5063e5899e58ddcadf5187fc83cbe389f5089fba13cde43e9f9c27d8ddae36ff00f81e34616a96640d2d960e3ef11e0cde4624f8e185d3dc7dbc8ba2e5eca0ca0b0b3c8ccbf7591bcde4ef2080dfb6b596c5be1b9010d7f5f27badaa732846c2e42f00756e36671e377c5b0aa6be2df585111caf7010298de7038b88937f715851c95f01567a78aa0474e754535144ef0503d285a0aeacc91e1fed77084ed711dce06b21f0c1adf632ea4c4014c97d6b9c4bc5e7f1a33eb894c40eca2be8a2e6e187e549131191f4ffff1e12acf302d604f6607fbeb96e067eb1e6019809c9bedaca6add0192fb051fef1620325b36732c80b8f62a6294f90922b2f3fdc5f6e7bb6fee8cac4f6775102aaba857530eacaf3fc0d4475b4bb3e567a426658d986d431e6bd6245051631c657b712fc58f8db6570e549f343f3d0ee431663b24e39bdcd787afb1f7c2f9231e2dfc633491642474d500e26b76a224d533f129ce0f7f18a3c06ecd24297b94e7f442ffe2ad9e1e5d4e8903ae1b736f70f17b356f8a9f9fdfd4e372d672466f66c1cc3f58e595d66d1afaa380e9bc1c680ae146ac150cc1da85441dd4a4c44db5dcc024ada337e74d6b209f0f78b7d288f6eed6b6a449f7969eac99ba8419a73a29cca649b2ffce2c6e594eee0e84b4ef8de049d92adf7efed94275d39a4fed543f994fe15cc77c6cfa0bf49dcf09e8aa4b3b23932bcfa19550e87a3799ce6ed1f963194675e62f5773b14436c8221f11710c3e6f64ec17640c8a1e649417644470b4efd7939c975302fbfffc7ce81f045d356a20e1f2492ec6f897817b7505825961af15013df796206cbf3202e1171518992934997cfa2c896b4029725e0216cca3e900bb0a41c8a1c8c1ca910890a0a8c04800a03ffbd217c47727783d474ac16b2e26b2afe7afe5f82a74af3dd1277e06c37d4be47889820037c0eb7f367a079fff30c76729a0e3e70159e00b96fd2e7efb4f4e55535518435196eb83b776ad2e8d018fdf462f005c80b20c9a57cba768c8eef877f430377c0a8baa3d81e1229f3c98fb31bae4c188e7a21c09198b898aaba3cdcc3346ff5c3af57dab863edf67eb1025b88fc1d4344dba3410d1c8a3a828d5d135cd6953ce2b057d1dd86e1ec27a8194ece19de6c32c8ba697e02c94d03b0f8c0ca18be254e6d3158c2f130134dfc57105dd54f050c31e4be3b2ff4316a07bf85364b984d42739109fdb2713c5aab52864d433fa86a3f522e19b7716f48b0d544c4cc2b7179210075d5777e0555e2e8240f6ae5eb6aeee3eb6d20e968e6e8a3604766e2e8e565e965e817ab65ede8eee6e60776b77371f2f4b6b1f491b1b2f5b6f6f9d2f7ae7c1d5daddcdced1cbd5d2c7d1ddcd1bc7c1cac5ddda59cdd7d5912380d39283cbc6aad3d6165fc0ff7282cfa0e8590ad8dcb81c8b40a57dd55e80f1ba1592742dc8080abbdf5c19d8287e78f7d52ab6058e5dc37ac0c11874828b12c1206ca9e0714463c3270ee0fa9fb7aecda34a8e39baa7bf472320f09ecdf95b15b9b006c23b2fcded2b89baa1fadb9908e4980b6ec65a8445b2d0c5c240ef3fb2e002f48c4a021e56322f90732eff624b32c989e35c93e5f8e2ec379bddc0c6255bd14da58073c75f7fbf1fc16d95011692de47f48fe7352accccfea335058309f42a2d1c5f935e7f549d84e3cca8268237c268270657e8a61fdef1d63e2f56864680f9619d03a3656c9b0e5905efd6f551636491040b2ce888b0b5f906b45f3e76ff5398b715f673c295d2c8c9a98ac86293eb3a0369890009cdb77bac00d6dd8363c0a5787db2ec9e16493b2030b7d162c22f0cdbb06399f901a100aee4677415c3561d13365030934c95af759766b42e4626d823e70254937fa6f9c5ac2da9b1e52620fe7f6077530041f9b43a35c726182ec4070a4daae515967729e1745e03316294f58ea61729edad7840112d05d7711ac543551fd40d183e1fa6b0dbe18949fca4eca1a9fd26c611b30187fe526ddb9fd623a2ef10b3ef51345a1a9adca4ada6f736487ec087ad717797572d74c656169ea33cac6e0848159e57949d4a3697aef3a0fda21313958fd112898d47121611ceddfe2ff6083b2fb721f5fd895c851916dd6c87c4b35a1cf04ff29f6dc0b93642274e90048f6eb607e9eb05dd5718ec6cdb1b0f0e719f2d93d56d39a877ac6681ff856ea5293dd8a82daa9ca90f86f24d63e7ddb15454dde3d9b4a672a9e27193eb79b8ad1d3bdca1440e8f64013a1fdc98359629dbdfabe41fdfc9889fe59a6659d600d33844ad452a51ce41e2d6fbe7c64ec9af28c6fffa2ea9bdd3e0e05d7ec6211e5af89737a1e5bc51951203a8dec3454dd9cb01a7eb9cdaeefccb2e0d912973c313af6de3a4baa8bcb9e392c7d6e33c872280bf79d4aebee2260704073f7fdd869a7bda301a6668dedacce7ddf951eee0799400745a710c90bf229780fbcf02a9f4a8d9426ed6ef91d67e95c6a2b8ba157175cce42abc5e30b3fbb5a29a09440b2aa38dcf0219dcfdd8eadf22cfd58b17d596bd6ea2bf596dd6ca141791ca4278b1bba77e8f22f9192331605761ff3679c8fbb5ebe1c4ffe660a15fb14166a621fdc4bac2d9dc1dead97e5de1f8e3699e5e4362fda7cbd270817ed66a84bffcb429c5db105eba505fbdd366a83108c08ad5a18b1c7f4fbebbc1067daf4bc6bedf5cd324536aef5059d5b15d093ef1cf0fa311003ec38fd26272ce0545643bee7de6a5c66f90409865b46ee1da83344458e2b6fef7719ead9e3de44fe86deaa6abf1cc215a2e7fd89d1396ebd79f0bbbdda97824c12fa3f5e8d48b05686847e397c46cb1630c211f05fae562565bcb133a750f23fec028e5a3ef98bce3f5599603e3ca4faa9b9d45840bd1fab4f74b8b5c5d7035a98f7f6f0bf4dd2440a10fd957851613b45f3e26c237ff7f71fee507173e59a106b1845bb522b6b9215929bc4ba36c64bdfcb38d06806509b955399354a8981efedfc07383b27581a9f5322e65510ffa0ee81dd617df1ef831ff2d8714d5742448ddc121969a042a144714bcc64dfe5b68104d3622dfcdaf184bc9fcc62d85aa3eb014a0dfc2998652335b993e1cd13233adcd13a9bf87a61ac0c0893f424904b7f26ca966420b679590a453ee4b7626456dfa3371d188faaffb5a40a1c58324909d7b199f14a53b38d367f9472237d978b5d8994abc28013544a884cce0740a3750934bc85e0c7e1eed8922511ed664dd90c135787f61c04f20791a973ffe8ade596988b034abbcdb5d3d148b208de28f50888ee5f438d1d0cf12696c30806562d8e891f6a4f9d3e6a62a97729a6cddec777ba2e41730ce953c5ecc79f81f5642fe9d608e2742b969a2deaf6dbdbe364800c7cd39cd2b83406dbe929ac4f9ee4fe0649d824ae78b13d6ab018bba01af04f98c7306a6a433a58f62aea8b611019088e81d680fa7c7b050f8c18adacee37fedffc1e61a77c25d226a64879818020324fa677b8b29d1af0fa116b2c3c63cb59a691e26ffd6597efef9c70b11a03816005891aa72a2ba2bb93272031a18f95de614b8e17ecdf384ff292b0875cd9fcb3a452538f85e5ed56fe65bc2218b89989b837986f82fab16c5af941527eabce7325c179f4bd3098af27ed9a40f5feeedca43f3d4f0c1ac91f185544864c7e43ad6638244005444ec2477e7b9dfbfc97357186f0ade1501276916cd8a241d188a94450bc9f8806c73917ee3f9e4b229a7dc2c2fc1d9be5ead9b010de736aa00db9a2abad48b760f3408ecb8b0abc2e90bb81360c38d9e5c4cdcb7dc4953d4cf180152e470bea2f108edd2d86dad6f2bafd2b09a442639f2351a988daec2f9468f530aff5979040d8ef084cd1de1730b1c20194af50bc1cbfafa847ce70e7614b5d77ea07669ae1075404e5a3d9ce240e0bfe30f382275e8100b606050ba070ff21c9d94a519c2fe289cb099b56718caebc8af797b5b1df70f25f827a0f06b54627f2276e2ee9f30a59ed6040173074d3a7b10a788d6c45d9e38e55c3c78bd6e1018e309f64e8a12abbae0e6d4f5772657f29bb85bde9ce8f07f6d06fe5b02ece78fe506adbf0b88f26d787d3bd7b0b5e7eda9ccacc2ff37bf972d36f28dcdddd40f4aa2b5f10ce8db036e9325e36e05e50a0616cb1c197b74b6ee78cad195e860e788d7b97e98455b4df83b085f82a06457b320158eebf926a85b26d42589b18015af450aeed3b6189dbaacd2ab4f8b92d9a16a6f41c09cd5e61f67c3c9f15a1b4042e514313dec191ec9d79e718d6125bcd1afa7b064d3ccebf3961b49580dfa500fc4b5371f9b6c6a5648fe0bcea1d8fc9813b092f89fff4f0ae6b2d38ad10bdf29aec88d63145eed59672680500310e21d675789407ae3e6d860cbf1e3a7cc8811e398739ca535952c47f27a04bd355f8151a2d48ed0043ca27d9bac2e05c7014ef95fb207880d24e4be450bea998af14af977251b760c2e30d90eb89767e51da91d80ddce7a3e8541bd7fc46840eb1a2d8a4551c2b0b0d832329df122f1d8bd395508fc614e0ab66efbf0371a596ce2f7ca1ffadb1c69af9696ecbc4d25fcb5a10f9dc58e5183b202c4cb4721732fd9e65f1f23fd6aa69aa4d255003547ecf0baa5c6aa6538698ccef2bd5b81d4f340f58210653984dc083955f497a86df598f73c49b8fa71fed24ae5c1cb7dd27cca3f0ffa3f07fd0c76d82d75aef1c14c33bcb31973633d99ca956badfe51ad1f250f38a1266038d5a9ac2c956e26117bf78b47f4126adcc725e0407fec7dc341281a23bf35a3baa49ffa86449807c94f85097fbab05f8ae2079ee62413957a735959469cc0f4e9ce96237e1300199597ab374ffb71d444b69359c9c36cd427ba0fbfe3e01bb85ff363a5a0f0ad1e78437cf06e7404be1b789145c734da157367029c89e3d264bf2622d43b5fcc7f7b1d2a2fd6463461bd47145e08dfb372fc338e683d71955bd9af649487cdae9fe3bb9f973d73a6ee77a52bb159a785f2ad9d3e914283df4a59a786583bd19299af14268be1827eaad37fb3a42b7b37b2072078d11e7a59c4071cf2aa2afc0e41c7c7161354181558e9912edf283ddf0033b2676e7e64e121b27c30bc74a53c6d18c60118e0e64cfeaef17d6327d88721affa78fae866e84867a06f85ea954be05c2310a00224bb52fe8221628e24fdb0c96c177f08ceb104e3912379ed68e1a713637faffbb1ffa2b704f14add2c18f643ed396a8a9339859f7006c62f0545c268e22b283db502c2395785dbd758eebc7d6fb9a5e7d7e8ed1246fc7f8efc32ee1550288b903775ce2315583d4efe5c29f812637f6a03a070b9db071c35a61ac439fcea7c343d6aa573b97315534ac7c138b49a239e5d205755e02f4249a05f467df289c1eef7cf48a60a78de42d8b36f4d7dfbdc80751a82aa3d68d6c06aa2398748740406ec3b8426b0aac0eff73c7a13374fcdb78b232adfb7e63ad71b34b2b0288ef4955a42f8176a1c1e4fc01cfe270fd130ec9dc6f6467336c3dbd240c6a28ae8f42d10767fb14f91f824590171120b8cae1817a30dafbc53d4a36e522b0da9cedd696dc687926373ee8a260d6968af017ad282dfbf25b61d7dab220d53714c4e741c9a61a470ed0e609a7ff4841123b8ef81d9036f5afc73a02e2460bc15d88efe444392018f24e93712f80af642eb5743b9b4db1812c7fe7c932327cbbf219b83448e1a7e0130b6770fe294b82f9b9ed8fde7d32f4c1cf3c808ddebc658db0d32c0e30b01c64204700efce1b969db5f831b3c4fd0f8065f2e4feb91d845ffeff299e3b3b2e4082804b08a9c105657e3a85da14cbf7d374119689af2249fd4acdc9de11acf479425e504cf04df5220e9549d18f70d59fb8fca8fb933bac708923897210fae76d41b0566f7cb9073c86953605396ddad89a6dd1b886b88bbfe10ae63452aaff1a98a643ae4421cd9694dfc074c1c34e677f61c02b4619ac4846fa890e93727e0573c8e70ea36579cf5e5867080904c696665d6df5231a0e6f07b4ae4d62ff53f9b5b99067d4ed6bdfffa13f9fb1ef90f175e1882c72d361e7c570bc961d1c853b75344f91f1def907dbbb8a654d12d16df6a8b0e3ca0a3107336d1b9ef5769f851878a088d0b3b07f0b1f20536ae33504b141605d3f6c7f1e28fe41acb87ea0a0092b28423fc577ff43252ee59d036e63c050c8a2d89ebaec3ba83f4e452c7c735ccc45aec6eda96ef1f7277880526520daae9211d7e3db6fec8f1cff4213d3fef0ac2b6b35f3b36db03a59ab675000842cf44d647014bb707a42d6723d1d3c8b73e829a9d0415ca26501f965d968999f882bc4e8172e05d88ea9b4732661366089f8ea5b0206263fcc1499c1dd0d96a054651e0b10bcd5553e933fbcbeef6e52caf12bea27caaaa9129ac96f4918d3d614995ffa0f27de2a7293461cb45899f5539aea39af6dda26cc3b5474b0dd761edfb4ec860a7006c4cf7686d8b5778bf261e2c35312707cbaecf396ef8fc24bbdc5b3723589734645266286f361f772c09f597e5ccf86ea4ccab746fc58bcda9b0f558285e26d7beebdcf171b1a42824e16c83a6fc86f2242dfcf624bcd58f8c1c790e8afbc7d96511b74ec20d47889a30a63d2e3c0044801bfbe900b7f6b7f4bc9d43e2b260f1e7184375e49c3f4b81b61aa050e4627c741c6de80b8e7a1474f6aaf3e23e4571c949addae890e7100a37630d5b3e66d9ec8d1412958ee8c13e21f908cc2fd6855fbee39ff5ac0c831792daa559e004e0117515a201cab1da286c1b1496782f46a7af821021d77329a8cfb9758a5681eff92a8697adb5a4a59fad1eb79c8a96ad87e58cd1810a40829a1584ac2305c98f405d60d629d86405906dc0d229b0b6180021a8d591da039730b7cc6063041b9f19610b4908b9d2a030107c0c05af47c8d6b1cc7323763f6e8bdba2ac3431bfd8b5e205efc3a1eaa0bbf6d02702bf46c49d7bbfb8ddf8f57d1fa940ecaf950d0c01e44f88a05357a23be0348609b20f20030b5bc641eb0809994e808ed5a805fcf91cc2f87c827a1dae8df67f46a67331985b48be200b6c9b208569a6d30162e2b6e39b43c6d6ce51dbd2cfd66b41044d6658a6aa3dffc4623d4820a87d957e6da4ec32485a72b402ddf5354bf9d60cbd7e89ee3bea828fd9a480eec224cd67f387e9bdc839dbf6e5fc1aea86debb0c46291cd185b81787d87f1dd838627d72a92e8704f11fa8012ac31297996d565b5c91f6105efa061d2308595d423e83ee4b1ac31abf98df8b27905d6a56a3fc40ed1f61b375223b20032d7fe89a8403c8fa6487e1dddfa324a177372e2e993edb8761f421cd5ba8c711ab6f3d96ee5a0f7d09850622d3ea7026745e2b35be835864845e958aaf718b349ce788b060e94948c0b21c056b25b518d57b760e3b0e64100ee12020597a1ea72c18faf26242f4af761a8c98d3450d1345e0ea8a67120f50d0a3c7fc4cabbc6a32c3b35cb2c90690be25eed391e821b4bb0b1d2ab277906a98b59672ff5db00c59fccf14695c37da1d0dca4c9c423299665799cdf4e0f530d887e03fca8685cdf4d68f89d7e5fc3784479670cf57c6ffd76ef5c3c53f084a2e60f651f79ac835e13c30947130f69fea20903e902f2c8866b1a5b49f0d4571fcbe27ae4a367b8553848958880068b578b1d1106fbe3abd50fe583d71086c28c8b142ada0de99ade6428c1f5ebf006c48261b68f71a97107785f211984c73d02a92ef431d3d680ddc9c8d113e4d7ac22b97bde591397e70d443692565284f04a79c0d75693bdd133dc794b2d15c52c39df1a5a973999946bfdb61479fd12fa4d46c41cca4f029ea0df9913e29ffbcce4052d1874b9f985f451094dc880979cc9c8311ea34baf57500ad81e7dfc33be4d7c404712fe3f6dd3d0a8223b2074abfaad6fb597e1e76a98663bebad61a7d68f144d7fe0111d2f5ecd845c4df1cc6611a61ad840372a98fa4675db4a07fe5dd15a934fcdb8880fc50af9e472c87f12ba6cc8a657ac7fcfbef420e4dee7f928f2b4317837b6c7d3db0fc6fa6e618ef697d43395b01cf0a9fb164f5e2a11241f2859eff1698ded3d194506cba489986f9c18117755b89d8395c0d06c50fde7619142972a54e5d08557e7dd58a70de1936d2341e1f95f7959f102b2907c9d73f11544a26e12a330a7e5180282a12f152f107fd6fdcc391173deaa6d0ba42a397663607b1740f8d15ce5c4172c13897bd80d1570122e2653c9423c61c5b56faa1277acf0513bfff12687b96ed70f5aef911dde5998ebad544025dafe33043f1b6be098baac331edc7f754d613a91f3336e28154436060a8e1e29cb5ae9ae8155f5ae5a9e203fb5873e8ef5725642b48ce6682ad8c6d3040093b7f4a29c1506b3b8b5eb9170a4bc9c590d96eff48df20844bd3f1f4677089cf0c46170a7981d1882a6f61cf849833d7f4a16fde881e48864f2273904dd24805554060dfcc63bb7bd8baa95bdb5aba653e4c88c30bd038202b9400f83896a0946310727fe27460776c8b653e4c39a0b1fe88db6a6499ff029f0e910005414277fd46937fa3bd5664759ec60d4a4e28f014d2639a657e74d13b56872200ead8c1fda03fbe62577471de185e2ac21e33ee8265d38ae75e2c6197323c795b808d4116c283e2963059284d4f17b2bca27dc49a6178c8afa0edd950a6af9d5451e5b991f3b712962a84fcd591e6cbfe9953f25abe1e15c797b9de3404ea815607eedd2fb3e1e1cda92bd23bcf88ff5679c76ddaaac24a8e8fa6a1bbdc99e2dc6f06b2da1868d656a6afd0b144a7b304342aa2f43a183849b37f5cde43011760f09f6990171064160489cc9dfd9f0d3105818f6a3e1500f81eaa40f1ab790196eeed382f83b74c76fadc9154b584d2e59fb821b32d5120fc96b9f1049a5bb4de0cdcb1f41ecc91d9ac53d57f379f0b4e6b5336a03c1b3eb115439d3b35fb1e2459a35de1b4c70f45d31972cce7ecba36c1ad95f15dd57f37e085d92e15adcd19bccf1e309a4faa5cd5e3e8600d49accad275f0c67c91457fe99e3271a7951ac3015a5abc6a3da7a29af42229ae66c35d2f0ac5fff3d2e9c0f5e713435583784218cfeacb1392c8f5e270bbd3093c2601887562e803a2ec1906276986af642b25cf583a3ffa412b7790de09384dd586856c5aef1d04382d89b95d9f180a0e4dbc9882e192df9296c2ff597f241ff6d32d728a8922cc42daefbcda458142ac8b451c5ad19f8e8031ec171ce3450186a09ceebeb2c4c73659fa9cea099aa45fe828036e148567bce48147f2c003378c42e5734b340cfc318fbacd3a1f2c7e32b46e08a7c2ee78edd887e2f174622bcc0d724740ada3f88900e4ff7cd9fb34f592070dd12fa434e343b931869172f3d9be6c34598047e539e305947d6348164afefa58dec77447162282b7cb44fe9f9d7e9b8e9041b9e6311b308e82827be0e5f67f3c5f519ccc33feb336276cbcd119b0996ffc4f61cf7cfd7436bd286eb59f28f9ab71d592b52bf135e2476714baf24799c1a9915566025f99ed52bc3db8a222906c97bfd4cb84f45186747214354400a1e5158c524a0379ea394ce8c5c5b90927c4969d95ddf322643af0097846ce8a006311854deb2686f399d273498c81280ecb573babf8439bcd842eb308db94b319045b26c54e25bb30d22a5e80e3786ffbc365387ad956c71aa91210540af3560eaf22a84906917e2e0f53cc7f35087a5d32b85ffcb97330629a05b97ffdf9bb8f9009939503a03eda09794e2f97ef9b759546468de890d0ff34a9cacdc3e765fb9bb4c26faab10726d05b0c5bd47988580db1c063b6c1fdc2eb9f7652c84a482dfca574eadd573d1eb5d9c58b14a11155a34f7d80d88e11b37dfff5c2a408ec9af1a9a5387741bc96a03e18f9b70d9da062d2aabbb1974f0b190169c66acc420275c1c8afc6f74bb9f5db9f4efbdafa3f8caf8234bad576f2356f2ee0fbe6829c7b579016a09d6421bde4eb9efc1a77771d9a829c691c20ab4d9f1d4b9dadc089317143da05ef95a51c385780d25f68341db0bf3b60c27716ca9f338a08e6a13caba0f9cbb4eb2cd8900623ffc6a1931a782b3788574460c33925ce60165c656c035f1b6395d8dfa5f8fbaf490412baf04c0556c301f08b48934f0a0249ce6667d40c5b5a93b79ffe3894739e5788060ae02e9c62006177f2d08bc437bc902101871f7e1fbc3362c2a7b9fa5e8e70d7ad6da75ffcb77aa021873ef5bf50c8f35d54798bdd716c8bc468833935ad7a5311dd31640b7c4e1dd2c24b01266508d88b8921309092b530e569af351b90796354f8ece27461f125af2d107f835a79a4421f39920d30671329fde8bae27cfba04edcf976a4f573579ab2cfea91eedaeb6b93656b4d9e04826c194f709ccf9306ad0b0839a8ec0b59c38de3901b947286966704e5bfb014210e38a489a907ed740b259cc3f02fa5caf7206cf5adb194e739caa060685081db780b72e864359add2294e10a433fbd408140445fae2f3fba8bacb0a824a4c881077bd174777fa93c9d212b2b8272fe994963f68fd4eb9ad689b1d796a85eb45d2fad6165623bdfc67f5aaa3fdbcb689df47c1a99fb68eb11803a9f54150798f7e563d4ff44ee620c4da4b75ff9de55a916f8c4fe043fdd384286b0e2cb5b0fe81c529c6d7d17cca63ed2d5ac425841011fec65d35a9f811c925ed568a4b87e44c180bb434050c8b3939527e7b82d4800e1876b140a5fe13df3c0351f071a6ce25f9578a87764b487037f201001dc8871c7eda2a1ec7401fa8eea01d8a37ffb6cb985e2eb675cd4137961f7e10d0025b7761753a6b7b09107d7cf90acba3f3321b3ec3f5ece9dfbadda32520f5129ebd26bf1bbe999d60b1e970d7c78cc8ad3dbb1b57a6185e04e3b172db57b5f3e636d2c1a65e46716401d3d0fb61a1ecbe6b5dc6f766bc793dff4bdbda792ff4870c0bb34dbed67663fbf690df12c2f6eeb3f5cc2e8a678ef2d8885bc97ee36ddac6d5a298a47fa0ecebfb57f32da7758b1bbe90ffc2e8ad301eb7400e8089bb37ec681f057bb9fcbaae997cf444513cc0c557de3f93f8808be8cc2680d3d7b57dc4bb384447f5390bca2f9650a97e3a5f8f98f8d0328a4973abfdbc2fd130434a42b2b51963ccd43c9595658d26b546efcfb039dd53c86dc2e33849efcc9a5a0dec0b40cd8683e2afa96861d6f05be6c3be6b6e5b6233e3fe5e4d93c771a201a930aaa0312ada187de5ecb2be57a4c0466c37474afbc9643fd283d5e72387c94a699ebb8d437c41df0ce15f8c50be2f42f7e821bb04283d001eafbd2db330a1be55f38f6cd2acffe41b9a1f9b82f7c82a1b7188c9e46521eedebf8375b6d06f538b541123f17aaeb8f50bfc08345128ee8b18f8bdfe3c4baee8ec6ad27b34457347f1cc3cf18a74e1be5b7d6e43f48fed9c3b476002c926e8d6eae9dc73134f05f0f6edba4ce0f049802e99b87be2a0c88e3e8785374b78382772656c2429fa02bc0d052794a55562e62ed6c92418d4004e4cbec627fee21ba5f47d9e4d0a128d4784e07c355c731eff1f1fc679435bf288f7b9d9572a8c0275740f455e770e2a8dce7a535a169a8ee6893ac6fd991376c4129cda701c538f8bfffadb89984cb9c9fdf36409fa61e90a3cb381d69b684a5051609a003f4802a039a171d62e692b8e1364cbed88446f3ddeac008ae7abd0e0898d47f51522fabf6d1f5f816774fd0edfda4e0a97d8d302ef3edeb70b65a7b43523f51552664c5e9ade4acc4f0e101792400fc047744d719812b89b5752466403d5d5ecbc1ad119fb4d6d2ab9c6eaa7c9343b1bb1999977bb43fff920a1be3c88388bac6bca2d280f6e502ecab1c1113f822df3786913603d030e8b11f7a50c905bfccc9ffa5b8ab4b9a2bb39ab7d5ab6c295744fa62b761de3a5647efad02906ba9fe249a63167855ae8fa4e407cf097142e952a19f0eb3d1871ebc304cbe40bdb169597a667d217b6944d512eafef7ef5127d916c6cf564947fe7fe6d5d5852b523e2f20d1bacb399dce30749dd211a4a86e1bfb954b41d563e2669e3e26a3bfd6cc6348e8a2720034670a39dc42ca7c1732e66ecb8a4a8868589ab5de8ef967db29dcba120861e15507ae0d11fa61216e737ad7060d3d4f94de3c86b41e51022387fcda1beed919a3afa98a2f1b22c081cebcca73ac7d911fcddf555485d57f0fdd9f017a5a951e4d5e15dccaa4f9a5bd44afe6b7f654ca9163b80cdebd8cbd8c4db109b86f9f039b9178f8953a93c9ff85ad7e02c3efb3f934b8868b61c1c628aada27cf526adaf7ff79a6c1f40311753821f19242c19bff21d093f0e1acc444412b72859a57e382e9d7e6ab7ccd9c8a188dd20ff526a675fcb75e52e50f34b388af3b2cc6c734f4e4e327e74215fbc936917555ff539f0aa061d04b5cd45b0c1fdd7edcaa7fe968e21e40631fba500ce6ef35f4dbdd7ac6d1dddefda2c40d70ff3fbd8a3417eefbb1e4c78f781b2bf5f1d17e4cbde1ff4b3a2b942fb23168b967c69e7a53d35251c8d4f199c05dadbda230094f3035f6b98faef35874be9cf614c79a67dd9c05d4f9a48658806eaca7453671c82ec2a549f0b7e82d663dc8bcc0794e7a288ef558b282105b00a0cdc81a28379f327c5375dde440588ef7f727b1b79dc73b3cbca6deedb6537123e0e768b1bb9999971d78abcffc9529d3e6ee2868a7e2740e1dce7215fdc6d084936e7a87154ee83044a0ce6ff297ca556ecbb107304b200fde5352b1dd1f696dc9f0d06f6ae8694c92c170db8803cc969dd50848cb42e954bf1d4233d04fde35dec4e96d2edcfaa3741a8c7e143ff3194079a02f508e68f47606abdf237ca5fe4bedb183c688a8b31112978733f17a202b8c557bb44c8459666272d0e12068c917a1dcd7172728224ece84bc2a657d3c522b5369ac2c6d886b696bb03e0b650a51657472d9047fb4aacbeaff7fbe27dc864f2c0b86daae9bdb993c15a75f5c0d51a78ec57726e8bc2d9fe2b6079bb2860807d4a37719f227e9c21aff664d36db2794ea4b229c76511d97552d7607ee76393adcf7f6bcf500d181b0c66204383bda2e3ff9fdf54a01afb13eec11fa1c85501554315f5a366c84ea74c45f55a5d38aa1d4b856fc13b3bb5d4406f6c15bd8a5935a5598d7e10d6f88fd001a9c49cfd845b36be1becdcb82ec638f87d978dacbc0c39d59f035fdff7c7eafc345fa3ef2f329e5c3157b6113d40397c93237afd9798434aa2f2a3f8d2840378efbfffa3ec3305fd06e237cfa817dcb05ea9b9b7bf1f91958f972e8737370abeb0bf21af01a26f563e9a2068308aee3c3e25004f0bb390456719094798c0b8ef01269c1a943847d4de04795fad586f103916e123910ae3541935b382dacaca89acc47487715a28e2489c54fc64462e32163c08e7f5320aa36c0783f07947a459ca963b484a57f5619add07e5af9bf978711144e54457dbf34cd25ac67e85cd2a44dabda32422381a16b6e2d809c29c0f5a04d1cd6cca37597a48f235a7609a120b601c1675d358d37200e33dbebf0c24ea3fc8e115f2bd0bb52ff1a83735f0e102f9b750999291352c08563ae8e63de6e3ae8c03dab479de02718d705cb1ad0f440b01e2b61b3db86c04095527c5d7114131b413a4892c02e29d01f8f34c19c80cb4f85ecfa903bfc3d8708a97cb6cf5b4271d6b49c76cb2caa3e23de512503a44e8d5e5a777a0604e42ef145db711fb18d36bc23cc953f2aa06951edd57f4c10640c22fb5a09553c0702f3b044c443be014067bd9257cab31744c0b033e1af46eae7d642949c2a24d0c3287409ba318c4a5052a3583a7a001b181dac98d6bffd06e4c994a56b413d366cde2830ae155eba06f4a95f3f90d5f06a9567cf6878cae1dc46de5972e19cfc9cf64aac68a21ca1921ffca6ba6a9b2a1dbdd0789d99b3e7ed66cc879d7ac5fccc4d95cc999198e1c63cf9534986ededb1da5a7c61a41a5e190f03fe9ac6578071ee5c34d963b01b1312ac6b6b6cdd81ee995df3bc9a398599902151bcb686dd03e9f210d8d1b2224a4a2c8cecffd23d29fc60cefb17e720b7eae6336264dcfcb269648c0326f5c3881e888c51743505fa0d65c092fa661ada370eb7cc90e5b8df0c06256c9f474e982986b290f40ec4f01726c2e9757deb3eba05ff9fbeb57c8209f9d15bafe700d25ac795e1527f6346e3eee1568b843acfe28a9ff879f57fe6e0211ba836b8499bf8c2859fa718a784a78a17520fc9aa71c4337d46cbc43d2b13e74d16cc7432ace31e44e137bbdf869f531bc8470fc20fe71cb53cc109e1c5be9e141c077ee379976914ca177aa6d1d420f3ae7fd250c62858de4ff99904c124852dfe824fda28d88246c9b5d804c686680a60e8be637931a8cb7a80e190bbf82647fa72b620f5eef2308d17bdff31448739092d1522e9acaa748a261df7b8122c7ae4243348b1edebc510ba8187b86f120cb08efdefcf6e843229cf1802d1accb8642fe6abed2bdfbb3bbb88b5e9c83efbb2467fabb7113bc57721e9eadb0248d7b4a5e3be9ad78ff62761a5ecd3ef36ca56d26b800471a23ce7e72f9621a3185c6b3153cd7b55ab8fb2c76b05b6048ed9ca4cab355d7d90d23d0c7e55bcf3e59602e73c007cfd65350a7f64c14bd70f0eb26d434b6dc83e7b1f1653970dc13b548565868ebeee4a50cff0dbfeeff8e256af6bdcbbb8d12b3082e4203e9666bb0ca98870898e90be762259d41c305028edc198d4678256b52e26f36d38305073eb5f8f36375fb883a5a2df03e49313c82723d280e6fc339c965bce31b276c1068863b965d9b489ba8709ab28be73de39d2ee67491611e303cbf78763f7fbbe487b44f12b376dc9845c481c8be42d5f248ad3d160ff908b100064c9f413b2aebd154bd1cec175ff257bef3d7aa9d853f82b8361419c9a135e2e400cb7f1f79a6f1be4fb667539901334b41fa9f33458bbfc92d2ca982783814493de19ea4a49e89523b50da6d70a60dc702365e800922eaf49565af03b7fb3bb9c57589ca8071765f98b994f2b80de5419ad018570a17182accad6aa3e92adca725562d390dd95f3df0db89c2c4422c80c7b21a4abd380319ff8d3498ebd597a0778385d94e7db75ef7aa1d74d0e3600770815c09417c5ad812a398c006d7f868a8103f47250391f76380d413ac8af320bc771673c02eb492bf95ef3bff18314d063cb6fcdb0ed209a8d36c0dbbea713a582b6ab7346cd4de21fa6f5df55cccc4a218b7b080d6a2f36253e276e398b83bc818a318c39b0cfecd393b3064c4bb0acf546015172f64ea5eaad1587a8444e7f19c74bc2aa4eb9e4226c8b6f9cc7b0054a8dc731c104d55b1231b534a91a7a3db90b86cb1abae88de9287a9e3710e0dea93759a55ed81158197506c27ce622b10a0d290cc26a586fb7cba878558c35969b6ad3266ab5232227ea7498c71bbe3de823a911b753011d0340204fab2baef0fe5af98d0e78b0ef401d600fbc4ecbc7f03b8a861487e5de919a821024812f22be9b89b477a784a9aaa88b18caebe80d9fa7e37a9963e1b80f8d3e7290da085e9833d5674b3c3beb91f87ca7d18b0b0b24de551e131fb336b4e85838d9df5045ed06777c19c9010519c0bfe98ef38c97fe61d5992f56fb830beb085acdde67faaea5a5f5099006e6f28f1be26e2504b0140bb4dd55f6e94b1ea4c1cac5048ce908552cdb5d906fbcff62c1f1bebfd15e3b74264ceab0b34889335d4649271859f03e64f6151f976ac648ad7b21a53ba4d244f462b92a726cea74dc67256bc11838f726141309df6eb9424c601befb37f5fd7503779ebcd85d8f363929c3477ddfc4cdbe74c69e1e588ed637f601a128e8f5ad3144b35b186b71776d5244bc28414a4b94ba6a6434fc34b04737783df002b1e8db64cb4b5ef28b35fca240ac16bae391c33fa73b2813f0e002167aa952d91882556ed04acf7800ddb648a7afe2e04a224751fcf17c7d5382eda97f0a176d7bd9d774223176cd95e2bdee4d701de6d885a088cbd1458aa0c9da09f7937fff78980ab1d15a4f29f8da263bcdfd277cf6e9483ba2654fd1eb37a4d35d487b3f055b2d523874a0647e912b897f88eb1aa15a90797612f77cf5aebe5030095207e0a9e6392be3324d0ced3b187269517f6dfb041e7bc704406f4d7e07e45f7f7a74c5afd96a5afdd2ff6d2ea2923fcba4a9861041e61d902ef82ac20839b2c6656113b5e45f78010d8396e29f4d1870e7bae02df15f3b642fe4b9a8a5d28c5d7980f65b3e7f38f20f833f45800bc2207f6340ecd58514c6f78fa6d929ea32cb6cbf944818a6fca8af3c9670cf6e8f619082b202d764a6f1f4ee3f56539b8eadcba2fd3aaa2925adfcf9941ae5c3f1e58806a528df0da4d32da4700ec3afe13516e859cf2ec2ffe4f803436a0e0f25c815a15fcda7e13ba3f127a4c2b9407594101a80199bd17f3e71b183417a6c599dfc8f7447485aad6d7fb69a9e08b69b19356e6e0f341e0403028140a064cf11705b8c7e7494c30efbebd304b1058a2d7552c98dc54caff54e5a00bf447b108febe9dd1caadd544e7a1413be06b70be93cb9d2ba48d39909b745b4d9c9213cc8d20cdbe0a15bda517f47480f1642699de2fcdd98180203601f1759de68fc388f9fb4ff4e726e353e0c7fd026669d8f714a569d6a0cde7600aa19015f14459251e6b62e89dc3ee5b1d943c9eb7e43088a528b8a8f84c9dea1124adcfe5822331d248c2ec44c4be0530366f3ee623db4deb201f7fb08e4b4ece7e5141ddae9164a3887e157cfa327586f7ad377b2baa31b65aecaf2b3cf7b55cec8ed129369c29787ece43286024470f94c96573f62f5cb7cb649bf7e061fd1ac9dafe97259e738517f3f9f6d7d724d64fa40c878170e5ff82d4de2000c30eebd9c8612f40794b82ad9b3eb86b9b36eb3299ea35b7ad6daa309e55fa59a03cca3b9bd7a5fe79815aeb9c9cee1afdf19071fe337d36126743df4d61d40f66bcaca1728e4f9d123b525b59771689facc2420923f64aeda7686acad7ad807efe59b0e93fbdd75db1c02755755233826126c091757f87f9c5f43a0e434fb0ff97df1ec76c15ea754a982f228ab3fbb3223f507ed273bbdcf295536ce14a5926f021fe921540cc29948adf2846c9a42030244f0f028140a0fed7007015e9ec7b2e1f5833f6a77190dae9401d0b9cdc50048039f019de2db874342604d8ab79096ddf5221de9f5ce9cce42ded606e63541e06a423711d44c5d6107cbd1cbb4e04d5cc1cc3b5531e5358e9719dcd7b2ec366c77be0034130201008043adeb3c9b66046f67e2d9dfb4c0dde4fbdcfaf52bd55fb2b7868b4084b6b24e09c959cf4c553986d10c06cfcc2dbd84b262ec5ae673cc64384aa36abda69bc8e9115df37525458bcf19b3152b3fd95f6bd7fc49632917387d5d77642a351a2903e74a0fe27d67044ed4003228bf73542a630a03aac8bc6d7eff2dbe6ae1c6e64b50e9dc28958d1b387693e60e082ad70e86d9a3151b3e3555baf9437fffbbfff612779e8e6ffda2390beba9484fd08fe871df4add0d789467d71b20d08a5cec2e6367c7930916da70149cd1a2aee23af2e793ebff95e7dcd6eeb80fc878b6665066cf71e077f539e9367ce98a6b4af39d4dc4773cc5772e1126a2ca88926bc1a74439415a3edbd08d0595f20779cbd9eec5ec49824cbcf6c6b054650cbe4101878b454ba97e4c9bbfeaf8a7fb924683a477aebd235e7e9591ebbe95f374ea2520108877d4287fb81d8e29704ab78546ff3efcc4d6b476f6ae78710aaa6694bcfb74c027580e9c0a44257d4b8be7ea9fbbdff112c12a458c1a29ad54659bc48fa7fcdde8fb4f01bd93eb1d88c2671eaacfd2f6b507dc4f21c23d66c4d12061f010821c41fc01a437c5085158a42badb175ca7fd1bd20c335fcccbca29ec9e46aa8e75e436ca18a9d9199085f241c5829421bac1735f03ed2f14a1896f6ad9399b78054c3e6ac12d3469fd9a0c80e1a8395519f173767a9b559568f13f904b3676826221d96ae458c4af12ba2358f82e0cd51d4362ccbc7af917a0d840b1a4e409cffda6b72eb023db9123a132735a247d13bab075d727502205f07bc989c2ab3460ee73fea493955961580de1465df822692fd976a45a699aa7582ffe6db12bb087642016283ddcabf333b934d0a9edbcc535b31b67b60c0ef0a8f36cfa556985b3d409f9069073f8dbf287c153e29725b709ba7989aaeb33a7e929313ab5b1e5852efa1d5e88fa6ed3c279d68b5a98cb222588d72fc5dbb5e9e4a1fafe851d8aeb51e226462ef853bd12d030e8e53129c61ab6c7b9faa37969f58bd9bd1ee9c1bcf8d63ee7f65d8d387ab1249b5cf2db1260b54a32951e7c8e61fdb79a61ba365efee7c337d7c94e589c859f01e9f6ee03f63d10af036782c5a2f5ee826ed3143e29dffd87a2e78764b3c056c761da96d04f4e8e143a21cd1f07083a03485b3ebb3c1d805692b67ae2db936ae5b785dafc6fc1c2c7cceef79b15332be0fab6be63e6e3753133cf167b422254432ca06c334b6b3c52405d0593326b1534a98c9dd3ab7b3026e94c7b7a70a6fe7d770e08a57312fdbadf25a92f29be8f2eacacc2100bef396cbdb66a449bdfa3758b50002f863602be69248dc24b2f3ecdf185a5dd568fc8408a01e2a024502ca11808240a9ad70189e471afff91f8eed75ad3f33580a0e2df95c85cbafd16998b49cc2956ee1c2c2a7766c6e5d2fb6f09e01dec5248b5c1891effa2b4e1b5bf6587f18a74ca9d1a8b2cce9e137e96fb9376c23613896631ccf307040c5de7dddda051d07d3d9d6a456904e5f3690f8c0c54a28a1cc6c650b8be42e3dfe95c8f104c3b3b3481a160bea32409fda416e10f4c82d139d50e2376e37af39e5e8bbaf403aca35406f554310406043e1895f71ae2f860e624027eeca629b4c6c5deb6c1d1592e9065d652e451440221946be35c863759a1914467b576cb2b3298273fd4d6e6126c6cad2798ab5c88c4049344b9b9f938756eccfe3c60886e30e9f2adf28cf98156e9e3781901ff5ffb917d4be20f5b823e925086414b7952b16064cf972ece7a4529efc70f245c79057d04d2fd5ff19f073cb71eea8b1f00f01c73e322097640e9e5aeb6dcda9eed0deca703714489aa85c84526b5ac363cf8651153788c6a00037312bbfde73e7d1d6d9d7348c287063f1d6ffcff302b4b7fdd6ee4a0f99a36400b849b7913caa26f66ed47ecca4ffcfd1ad48d7fefe52f3eec59d5afa0d10aa17581d903da626f38c85e0d794d7dd7ad380ff7fc4a02b23a65c6a8aeeeff55e435bc734938b5b2b09fd5e21900123d2e1d99de3cfc1f5b8b5bf3c14fb34e7cdc34e43c8f636d856b9e031fc32710d4f79956ff8fbd4bfa6ea6fea1b28e99078cb020584497821f4588bb094ebca943f565a58086414b79fdeb20065453b385d10695c1822d29ac381fa5f836d91ac1acaad4fc108443720041d52a8cb038497724b8248fbdc2202e05efab74ff8043921a9eca6211e63e3eccd8db637fe85c4900f080d0cca12c87f7a134a1c443d575c3cad9fca9a2d822e1c9dbb00b208db318047c5cd13c3656e898b4027c166eabb36b5c00d5d550a1f8b26694102acdf41b0a513ef0be1e201822699908bce7577bc2e9d8f0a70e68e5ec1b7b1d65f2707d7ccf19defbb2b61d5680a2d349193bb5ef9c00cd2768c78779f95d0d4307c56208c99133fca2025f9a642016104167032aa0eb3ffcb2fe7d75faa31bd9f7a65956baff07bbc8e3ea7426c4951e50bc149e12e2ddc2d74611e123be5c31ee9aaf6c78124ebfba6cf943ec09e27980f241f3719f127468a4769af67d31f7e35fc84f2b17b55857fa5ca0475935f0374e3e48231b4938c3a0e77b4234d3fd880ca26b73b451e988a72d845b3f44cff6cc54fcf8415871e25df351470c0810b4ba59ae9ad66c06fdac3a35c361c33ce8d6533c3eb426e1e297114bb2f3ec41417bbc313bc0e15d552423ecba8cf9f54fce339f6fbd4d99d416158f0371d09b3380fe35f543730335c1dcc87da6e3630c309fbbeb26b4598db2c0c037763b019afcd02e2b2ef7c4fe3309f197b8582ef1f813d9c7a4ca62c3276d530dd2f5c913d00d1779996deaba75df5440f733f95362a82bc2c5621e0b11c07d509747a54e8ebb69c0082ed3d0e7df68c1ccdf614b0f81987184ac078e7b6320c010ef339595b5ac01fd2ead6e79b0f6b304adc1407bc8c19854a84deac383269560a279b004f7f644fe3a775003bb37aa3c2a247eaef099f6ba22c7e9d4847f31ffbe79c45188fdfaf5d6c12cd2e7b2c7c4436b75475272730ff761e682152a68be1cbac7ea539dec33c239abdfa094b07376f9bf399b56488558a24aa0496ccf1fe3bafcefbaf0bf3d11d5f14b28bc98c7094356fa076cd43a7b42dab112d0fec1279f4d030a7f53b90b4871fc5fde66763b180a7ae889d0d40dfd3e4c2bd83cd9fe7dae4d84f7ae9f9366c6678f72c206cb36486382eda7cada5409d6af6f5df6eacb66d44d9941226c8e4f453b5162f9e88a500b03e5f6234b6c41f990396cb887c87e9e9e097f791b636221027014fe476f70c25657f439e5eea84c14cb09013bed6cd10292641c88e6fe8b1c07084f04a59e517d0bf0b623529d73c3dae9c6a70f8615c43b1ee76730a9e086ed86e7b0f8f2c804c72132fc6f97a7be8506d6e482e9cf7167af499b6ffce707687b50322f6dbe634a0d7199a96b10c431cb90f6f38474ba8756828081eba89e8f12fae34c7fc970aea8f1927b3163eaf191ee6d34d2a719c9086b3649005ee5e9e9ff8e18f065e90ce9b2873da90dd5cf66e307c32616fba7f72ad994f21ee8f449019bb92f395f0b9cfd32db77f74b82f1f1af29bcdd329f5888e824514e443a63482d0994d55c29538fc1e16812ab48adcfc7597ceb3241a1f8a433f7639050e767e60708c6658d6df48df2f237e4bd03135d090dea06aef3702a946ded2245c8c3bb85247621a3cbc975ee00c501616523859f2c2ed6294186f5aff20db41136d84f6a013271ee753bc2ae2b1d734d8e7a0bd342a1b5bfec3da6249eac25c91cd79df1960ad874a9f6bd2ab0aa1c34be2eb37c04340c5aca7b551126d6cf877daaf34e6cd2c3cc145a3d31d036f8bb9b635d8eae725fac1408686c80cbd7229c415abe0fdf1402c45813a19082ea0fdd8ac4f529463e91184498b1a7dcd2b45cdfe2dc51a6e30ddb0d5f035f209ba3728a19bb53e199b6f80c474e4c06010297f125813ada869e9366985d765913c687bcfdd43dbd167318915b7a138f84475ea7657fab6f7175004e2771fa86c3dae36f7fafe6c6a6af6768ab96bc9ad356d3dc0f843e457ab8f7506f655afedf4f46a18e4d4eb7dad70a3e0bf5737ed9e781be7fbbc0f28cd0d1ff85c82780444b7953960881292c8987f898edbb63c918f3e6dc4718b511fd49dcd076917ca9809f8030c58c873c28d751a17f5f9f9efba32d40e950e26a90db31b918c78d425c6d06360910f9519b05059733f90c82052327ca7adbeef777c08562fd76080c2c4c7f02c01588bc3347685a0cc2dcd39bacd088720847b7d42e2c2779c69b3de0ae75ce86b6ab9338c0db43fe318f37b1b80683b11cfc552d8beba5e037f6737c77262863f98866bd5a37cfd1d56bc218ce73fb868c8d95fba5097bffd29f78813707e97ea3f3b2ebf90460a3b7910879e6fcd082d14753fe97f4c753d44684c7edc9f7cfb26acd204e000f5d11558210b6f12b19ceb256e45e318ec3d1975cb530c1c192959347c501ebdc3a5b6df9e300d47f33adad639be80c1fa50ab0488ff077dd4dab5ef139e1675596930a37cc44d9f3d93840c3a035f4e475bae2ff51d0cd424c3b783e89d6415a79ae71e0bfad7abfa758c3b0a05dcc00502574bef59a0b4409bc584fdc5d2cc89b9863725c180de6ddff51f16c386a13c316875628af861c8ffc9a5aa4ff09615b51d85ac26fc70923fd6437361531cdc28fd948d341a57280e5d6a7844a2903f8656724243277bc11055f73410b722c1097a70bae8f4a6d0b0f1823358737a27bffc548fdd085e289bd2ae03f5d048a1d42be4380fd5660a219753ff66bd5cc6715608b12394b5fbb4d3f3e6d9225942a262288ef1d21cb4d52fcda0cfdd8a9bedf634cd41cd9710e037100d510621a7b73817aee8b4b1386f9da760f4c1c26fc279445ec9a95254f5fb64980e9f375809737aa5da6cc2c9b34cdb262a6f7c2794e8079ef12e2117341326103780c3cfd7120c0b9a9e3d5de47ce70573d4ddd51c38d65fd1ad199a480a93aa1d9ce28c7e6a65f70806a1d5904c89c88a95471946f647caefb9cc47d59a1f98aef91ede4c437c5edf7080ee3442f2702b6510a2ec51e85eb4fbd4dc7065355cad8fa88a9bc0aac31dc4e1133f55358cc4e18bb84803822832abafc81c417a76c6b9bf3b46d00bdb9f6b322823cddeedfefbcfa45cfd62157b4a9a4643113dfddead9d14bff6769e53614f2bc9e8c8e401cc1d77f0bce9c60aeee3b21ae5e57ba96616548e4beab5c399c55af636252d2985559b74a120406741ed0854b501ca84527887bdd8df3a80e021ed53f7bf5a0b382cd5fcc32a86400db649a2df942754b4cad97826130f1897f3f9360f74056835be3caa9ffd4373746291f351f278dc654f1cc0fab2bd913ac56896cda3e5ea80d193afae4b73b9ca45324bf990224a10cc3a76125164865d368ce45ffaa1dc4483814dd5ff12b0927f29869657dfbeb3d8d66be267b2a00b370cbeacaf99e0bcfc734d956c034f74afed08dc92357fa892bf8f1a458b8a307ec0f82018140a04940f998f9d85ae562370dff3c6b965e2ddd795682fc7271dd16c9ffa0995073f71fb1b6c06860dbd11375b702faa3db2ec40d926508df90153873bedcc18790ff9d966aee698ca78b450d71409f408a52f4da91319aaa4ecab0480b738486788a1e4b474ced27099a25d4b2054081cdb4206e48d851006e5736b1b3de76583fd80d3e3f55cf87ae38e30965f1528ff386429edd9f4e260cb713eec93ea756ab64f1676985b031e347e46b5e34d9b5e4896c448c9ae716ebbb007b5dd4f0b1a41df902ece44c95d2d4a77454a91ec74ad942bfe201c4a6604d2d3c4068fd2bfb400de1b0418f35012bed004c3343a487114d71763fcff7692e2a998e56edc47bc489c04255d06c82ae4e4115edbf11871e6e66b41e1c8e84fe301f2f94b84b528b5b3cf7ac954c8d93b1aa12d28053fb20929ee9134ba41d95d5925ef97782ef3ce42e186443e79da2ddb86c5b06f6989c726bf3b06b8c401d34cd0bde6ace771d7c98304efc3e14c1c5dfa08f7280a2303785fab441834038c3a0971cf97b6bdad064bf455172067d670ec32c1feced9188973566faac1e9594b7e978e90d04fe391b33f414f88d626cf073185b7af07f43390281d3fdbe3280a2a7bc78d202bfc88166c06b7619390c21476ab698e6fa7f3b38f6d719bdd24fcf0f4992b76fbc12fb45bcfda1b87db97a3e8397331984781d5760498e99eb4d5ce00a6efb55c03daa15faad221c99a1c313e077e889104712fbbf3e59deb9ecd015184c947600c7f0a0a99cd4f303c2d90f7e8d2974f516a67c7ce077fd3a93aa87cd12ce8cbb9b8080d1b9eec2b74a56d16b71d0daefce5fd6f7f8a24944200868183ec5412c0017feb2e70742ce42667abed4a64497f942f9f51f6d38ed027f11623743d970022096c71f326ce46f4cd9a1b63be0894ec78bff179fd197bcce9abb27d8c7a03634245e66b112b0eb0b29a0b41a6f1518c224928bd31fc8952f31e09571b76fdbf73d098e690917e03c320b0d450077d5c2ae43674fdef30c555a3c3e7317daec5e2f3f3fc56aa10721d435c1877201b2d612a28478c4e5ccbb8c3e925559c3e31f472d877c08b15ad583e7db2bb45bdd7ea076a4b0450ab940c0a2499887905ea1fbc4acf84073f8d814bf34463733a9fc0d90142e49170b8d842bab75fc828ed5aaf338643f1b34142f782ecb312132be60a32503eee3f6e75dda7d48132ef0f998ff0fdf0f6375630c2f6d35c3f87dab585a82b67a109c172b5b9c78524b0d7100f1974390198f17813493ee17a668f2bd9d87f6ebe187c8eb021aefb71e84afdc4088db7e73870b557f09fee956fbfc5552d8b9e777756775117b7c6832dba16903ccd8dbe4e4f658fe4b9ca3dfa297b70ceb8305fc2b88a11153da7856c79b9a1b3faeb4b0f958c8970029e1fae9b1d0efc908f543b47f77f0361a83636190f6217b28e7e88293abd89670c59d6703cc80322b065f66c858c4a8ff07ba8f789bcec333311385d175f70f165ad4b2a43bd1568828090bfc94b4d7a34dfe7a4ffe4fd1313b411153e7e7387a6783c8d3c6ade3691fd8ffd40c22f5afc826015144d7f8ba1284cc94edc80ea4845a96a7ad6e2d1c20f9dda1391e0f28e042b7ab4335a12f5055f41397a6f5297d727fee668de88139c9f53990e7132863b8693fb8a648c6f433ee0f69b8aecfbfebce1dce07ca6b0fe6feaa2144f83a524d78bc1f3423a01218e5d8b640b278c2ff1003a0288afb95367cd9b0491c5fa6ac6dd4563abeb3c1c87e577620f82bea51c90ae3a3248eddd6c158c287976671cdfbcdec511cd8033b6c215c82962329a0613c05816cf824de403dac7700c994e30ddd93deb8c4454c45266ddfe6c66be26273baf8f9e91d1b23fb4d73a73ddc11e4cd95d7c4e518d04dd4e8dfde95737c23a4ae1faf3261f24483f32fcdad0c84992244bed2b533e881df591f8232618ad0bbcd58e728396a9d2edf3cec83d03827b857f2b5ced3708986a88848e14e602641b6f0b02375d04310a068f6706e28427c4923e91388d1a54aa709d85a8f123008fc3ec14297aa332c8d49c4dd218ba353b0b3f23866343106313104065c2e53a01d01bd9679efc4b3fedd25d50254bab897d729d2926fe53f5d0c6201005e5d48a28f58af1286ba196e5472632aa6fa2b632d4f39d9f0e42a9e5a374c13dcb1970db0006aed6ef85ad39b452cf5ff1733e3ed8a3d635498d0c1c35a776bb8f0d0e390218ec122c74598b3388805fc8131c0683a82f6d3ccf18f84ef7c28afe1032ea3afebc5fcedb37f6bbe7dd20404fe2dec6d63c01cf489fc68ce4ce1ff645bf4d4134c93c0889a5b941d1b2f73858a9f58a7546242f936c78e6e554c3f21eed0dc6044c56e5b322ee1e009c74607e8a34f5286849f1de04d1a73feb5e58e5bdc78bbf397e5184500d13e97220f784757d477c3fdddec007611b601564025a588af24162d62a9ff8e2ed21a1c1572015778f137ac409188ada9292c4f15bd210e085e106fb232ccfa7668bedd1b26acdae922694b63b59b9ee8fae3331193be7e18a0dd7a06031d74fcfff37a61f2b8a95492aab046128b9d374689a896ba7463e4fa2ad5f45ba69de3e56bdb115a7de2e21c8e1bad7f7edb6f3defbd9817174a9ef19b1edc0ccb1824421c7064899061dafae72e7b90d9dc7df8329a3b38d1e32e1c11535c3f960479fb0b1b40b6d51a16b4cc3cd75da5ae65bd44693be44fdb4264c8332f4ca50c2bf9c98febef075231939f6f47286c63297d806401bd84e8c082d905d0368be3747c0787d04a7284f33351bf4e50efeb0af9df3a7bc9644daae24c41b28a35e84c4d1e47fc12807a727d970418a8fc7435ca7fef69aaffcd61ad63b9b3a8b79b3ddff22745bde9df2c2187def47daf3fd0e74b0b8b249daa96b3ce717655f3036db49ed766ea912ea576b77d893fa211396efa3c09db980921a5ae3410bde51a0eeeab2f0f1190ae6c12dcbcfedebe8f5a1f577f872c58c789acce6094f6287aee012eced56f290a184f959d1b0309bbf84321626e3fea514849840d61ff89d19690f5c034bb297ec00575c95cb031f22329a4c9b325ac2a2bbd78b028f74989436995415de5899a6bb86c524affa83501bc866a9e5c3c13b6d8f09dc1da995a47503df260f08bbd6530659f76ddbf985572219f2f7f817c4a47292fc37ac613dc6be2dcbcd354e747fcaad52ccdd79b28736daeada18a31a1e31be61682455e17f1b7b410f440920c504e7741295fa7229cdac3a7edee60d7444bfd09b142e770d9a31eab9a546b7a4e3ef03c6e14b00ed22694d3d8e487c0fc94e1fcf6e4c7d1689aa97b8f5c18516a6c2ab73c1500af487973c29bbc29cf69ab5a42d224df616939743731aa07c11f2ff24726c5b35ecb675da261b8e51fdc7ed5a61b0203f9ddfcca376992edc89bdfa654797a2283709c428de4b29ed2f6b130fdfb715f00fc8211023296c6fa7ac7659516ffe08df679c5e5663386b73d99f39fca56548a3d30df4fe9b87c0877c2febe886949e609d179f627e74a124bae7d8c3eccc3f047f7796dfa8b358fac855f9f89dcfe777dfb8ac9c9c7ca2c2466f739e45e5d774d0fbf4f758f0c4b21a26341cd9aafcb3f305b9c126dd5f1d71ca09e20c79d9f60d85b86f2fb5f9f7df6ed1d3ce6f3810bcf85f89593d42a4217a10aded7e249a96e9b4b2f80a05247fc906a077527960342c4103d7256a508bb62706da321eb9afa5657526d4c1a70f3b5ef522a8b4b94c6d0e3a53015e313150571888539ebaf04b866d47056a921a2fedb1bfe7e74bf15afc5dc03feaef50f71d6cd6fa57f8e7f6e4640e42f44e23e9f010396f76089b7954f03d30a244a8e64dd20263fc23b5789280d77a4d84f209d43167e81411792139721d3e731eb1204814c2500b090ae44d408124de21a0e844f7160825f5642b403d5ead4bc7ba1a12210dcdd0016c4fab396885648459d1ad81f5c61dad58598a689abbb29b6320eda8cc9af86c9aea1dc66e07701f7d70d556aa794d3375f07a7c9b0e6160bf9dcad4dbe452fd5c77f1c30451b13117c19c5307cda1de2808657be9e099800484c0caa90c4ffdd5e796a82b8ecc0725e1dd148436ee745274067ab43253c4766898d9baad19a3f5b91c947eb09012e7562c026ce3c91ac7d9a99303b8166517355cae51838291689d45ca128df534df9fdb39486b5d8213df5c7e98ac01a570b19d6ef15de3cb295ee0f730d0415c402ddb74b9f620d121b7a37d9b1aacc2914c57f1a221e8ce1e711c694089869a88a02943fcc5d3f29859a118696fc61285610dd148479bb816375cdadf2ad79b13afa268f8621d0652f30d8b711f90fbb8683275057b1c25e8490f21e937a062115571a68c7054ea686e401b9350552d4c357e9dd7badd90a75c509abcb88cf80422a694409502ff84007e4fa31eadd04c6032990c372c0d357d03193b8e3b0cd020eaafbb1f61a592bbce3982c0e45001333ea2fa5364908a26d0a840926ddeb0aed4332623b21d53a44922d696f9db780b136e68b1d2bcb880fe365b4c0224c2607f64a512ff637bc21b2266e01d5dfa43d9070afd46cd1f6d909af14bfdcd05abdd2514481b5507f68bf43df4217ca5bc36918a14860ca083725fcb5015096ca0066f05977f8f99d047645d958067ba089a48e55dc3a59f351d3a22ff0d2014a0efe6cd2b3b98f3cccdd281e8bead9ebf4849ca5cf53da5cb824c422b74aa8d462df51c0ef0c4c5c1289a6fc048a7a4cfc298e2f3364a08ff55b6340cfa30b96c46f7b873ea416ffef0293e691a43f8d259ef9ca45a3e10f3c7d1aaf1e701e0e2f87dbf2c89aa3fd7a88cdbba8a49a1845189394213080e3097198235b290e66258b31fba2cde16fe2e315986687e4cf8ccbe34ebf5208b0e73edfc56a0b94902755c8b76f8ea55632484cf9a760ac8f12f2b7bd35c5fb0eced468e6937888fc47198225cde8b31b0605f44c5a4d13bc5f6a04dba739345c32ecc1d60492137fb97905416981824ef0be9120b9dac82a07f86adb5b796741ef3ee383fd4b2373b551e733b8a97511a5dddf6a30f49716ec519a31bb1d9adde385810380e74eec64edd9935441f2eeee25c9b21a21cf88fb1166c58e28dab161bb8e73d1032902055d4e40dcc00b7c3fa6f90b843bd8aca7c9509343d3e1ea98a1ed2d2f9483cf46e2dc2dd10f67a9848f0413d4fd3509f16ff5901e49c1e3b5afda3a085f904eb790c2390cbf12629c13691a8fcb0b83fd93f9e00dc23332cb56465356398f55c4cc817a7966061cc0fb27782f4f7b5e0cf95d847e13a810893f444eaeee7bf8d0c4548cf5974e648c82011f95536e673e1e08738a5f7864ad5049e20d9f871739e1385cbc0a39c2cefd770c5fa810eb22288d142cbd666eb58c91a4f0d17e5237d1cfb7ef98368e08b143ef2a4dcefae5aafc62705db867bd6c2d3a72629f8b557448313ef70ace941f6a5052cb0f1a98e6f7299e1477658f11b27aae7881b41fccb6261a8ff573c4264c3819f833851d9d21ad18e4a0ca547e444b2dbffdb9b34c652c17a7bbfe19f52971a1f26f1bbcbbdacb3e3f93e982b6d2435aa51b544fb54846b0f94528009fb86ed03c76a3cf4ce11edaf56e00dee657a7e39fdab4ff776073e45a5e69ed87860db001f2cb16a7dfb796b0b4cf9a4508117aa5f21d4bb99b44a1d6529d889a7848dbf43eaa05e9380d11d63caefb2faf8aa1abcd7c54614f0b3056b1067e95c223af3ff48cc8f2ac3f3b695ac314f999dbf0b5ed90f92b69fa7f932ab4406497356bbe10f9cf19f29f0103c062391cce3ae39bd4e4468d0f0f51cc50d6bfbeae39cda0f7b53387818def3b639bb40f5eaee7473224fb97b4ea823f0d1fb89545fc566d0971a8c09ef10f58b3d23a5aa6f1fc0b10b15ea77ccec2e924237d404e4591dfff34f874c79f7c560b8ab162a88f9351be3cb6bc1f140a6f05e435b63018c313742c00777e5f67c1b7834a3060181180c3727568cab78674d0f5295a372549860b6e7546e7541d8cbcd21b15fcd14b7f8e2974a2c7986bac495d4c22f530ff7f2df6382f386feba40e8e2b4222babb7edefb419d375cc3488e8d2da65f2d167fb530bd7ce101fe6eef85d96bb11a4906a0b54ebcac37b6e5b3fa3873b893899c7b358f8278fbd73ccf584bc09dabbf9ba6eaf62c0317acc25b8cf66b2567775078556bb6fb57d19bd587d90e7f1f813eaab86ac6562127130c5ca8626afa3698bbb13a04068ccf12db43d0f24a16a9071ccb4d4e90f78d788b3fbfd851454ed8f1963da36f01644671d12b43ff0cfef292b082e1cb94df89b5dc786338267eb3e7a308959f6f6d506dd2e1c5c9ad2de2efef26fddf084e6560039dc2c75cc37323cec4f08a563884dd12b5538df21d406e16edf596997d4641fdb0aefe3b182f4643489e94df04baf8a3dd9db7d0c2a707293dd681faf09ce3b756a2039f1641aa1b82ff09cd575d8227eaf86fedb67a5e699865ae6c462272b895b06b3e93bf6e9620358fefa14098db75f9ba80ca0bb9b1b2842ad9eab528d1f22dc5a3ae06706850eb4560bcac15ca5dd9956ae0e04fefa323b8a49f5216a4ff9b791a908406d7662aa6b18fe80611024ad927ce94835ac2d2a25c4aff2a30b152121db7a954aea4e0da92745a0cec28a585a03a3b7449ccfe7b37449f5d19f9f1ebc13b471c3ddc2f56e8983f56aa2cf9555abefe94b64886e200b8f0282c9ed0aec3765ed285d2feae0d82332ed8b598358702a578737e92153ac0488cef17c78f0ae614ed7698b2efc32e878f98520e54acaa1a87b924c69399a6d800c7f60594ce759ce968b784a5877994c49c923185fb701df5785c36679f64d3f01d5dea09dbe3d3d0d09c0b37905ca112d61095efbb3ab0dde7b0b1ff23d72380dcda3b81581d75b679216b9ee91c0f19a41c84d0072f3a9cb4fbe281072b98d7cfe71a84f9081800ccd46bc92ae18fade501912999e1e5e874ae1fe6ba3661237e42a6f334ed3d67526c054626109b05c5e8361b2434f93142a5aa59838b7c37069a94c1ae6fe8f1e5a09ade82e2c4f37b2802a878b0e394385b90d2e561fc6cabd8d5be8c764db51a484a1a83199d50fa3d66bbf4a7c2c46ac5ba9c20e222464252fec492e4564a51e4d13d3111078ab2cdb1765c3aab0ff074da063801459d89336a4e4bd821900da8068fcc7dc3dedbf1af12b47bd566b0bf0baeefc11dd6039324e858de8d93f8f4ff99ef2edb5fcef8c79489e623dab20e40438f4636b768e961207b2add43a04880d709b5ce2b82fa2fbc77da9deff22003944d80637624bd92153423e9e649237ebd82ef20a4caebc1f9aee56896bc1c86ad9edbd9a263fc0fb1100b38f79066abab4eeffda053f383bedeb00c0b261a3f5a241bbee55767da94ddfa00e8222938dc1e6d1f35560a4ba2d2dc82ce534646ff9e60689377a330ee71548dc56fee7c33c0c84da33f5e56b49e0f1e674320ed8be2a7393433f4f874453b2764783e76013197f9df39a5b115d135eda522520a3f53a08385287e05b2b55be9b1507f07480f7681b04e71fe6e4c0c818118ff0d4461655f50b95b8ecf1dbc056f4bdf58a3af884bf63ec514780dd6261910a7bad82c03c722fee3be84c2cb4c50a576ab99f236294ea5cecd7f2af1f22313b777a29e8b523b509c3538e3c4b180dd3b021344d606f57bb55f85f130748d8cb8197045089501a8448d520db06346d5f7bac4458dd29688e83e6cad441664028c26c71f30ab3a73f62a33470e69edfdf97bba0970a30c78e1ed6e7ec1576584622c29b4b429677d3ff0baeb57dc62e3e22163eee981bb3bfce47ca69ec67dd0deffa141d2083178e38c21dc12668fb66428c6011e4638303779ae9ea8987e866ccc255879eab3d3dfa4110efb8b6eb893f515e693157ff597f2cf3880b2a75d48684cff0cca51d95e64f61bd03a4e81f28a1f6e5672b65621eb618d973f75066384b3f622ca791d359134cfaf261ddb2301d261f1a80d4e7f0256b70b927f75e362977b5a93b2709f1bbcedd658265bbc978d39bca5dec9ea312f7b1575c612135be988dd8501dacc8423eaa8f305df41492ad9772f8ca0d1b353785a048006d1f3db78865edaaca386d1fcd16f8b4adfabbda312ac700e3aba2fa5139f8277e5951bb3536a9391b63959d36609a9210238f1ec70933ddeebc0454deb55e42146c839a862e0f13d903997ac221c6ec9d207d028b7ecfbfd8558ca3543924598ac683d8c0d4ecf8a591922965df0e6aecd3461e61ef5ce56f7cac6ab5ea9bc40e53e3b96d6a06b792bf198faf2ecf49c2d3f9437428d935544ad24f2da081833cd5c08f7acb985255cf94ddb13fb6cdd5b04bcfe9f12d71d4169a3b2ac34ee412704c18040201008047d86be401f6063eeba6e25cb134bce3d971f89bdb0612bf9df1fd50de5aa01c3ac7f10e371359e76abe8b41e684c370a7b830b0c32d005327437b899af22be17768d09a595c1864f650e6b1aeaeb089abe6cf038620e2406eb3070ba8f80701a634d03fefd22326237048751ab88fd4f4f39ab88fdbf55bc4726bb7e123dc62899ce64b563cfbfc1391c3e91478ca531f2726984059a47b0171b201d3a3f8e2de6677651c00f819db7fcd924dfd0faf4f75ed2d6bf8030346d31075deb1d6a5d83176f77f2e4b7045f2000d5e1c68fdbdaa7568bf700ead07a93e06611578c71c561a8e9c37f1c96c9017478e50eb72cf2ffc599a631cef6f2999c6d168a8f42ee4a61ffd1e9f44d04e15cd9398e7b39e05d5d4e111a1c8bd190bfd8163675ba53bd4aeac162fff95373f6f5bf1add9029ea2e7851b25e7e92fb4c716a0f7fbbb252d4fb822bde02cb733a56742ecbe19082d87f52b2d4a40bb73400766b758ea01dde8ed6736ce84e40cb1bf7a9761118cdc1771f780de6fb072d87bdbc62033c02394080d3c1024b58da67c72204ab93fcbc11a0d1994421d992c44c487888e36a0d4a36799c06ab6b38c0e9bbd262a8c456ab9458a8575bb624a284359c67d20e9edbd1888558609fe2fa826262d2188fbc9a970867033ff1ab5df3675e576d4a33849192495636406b10bc1b853e6b4fee6e790a952fd36b0cbdb78552e82de73134423710f13ec3addf36c00b287a779cd1c75bc2d23e7b3a1c240f79fd357e4cb2fe925ba71b6212c45a8b6426737fe2d73679d4931f1174623643f567ee8b8f99df12c33f9e9e9711b9bdc7d9ad2837e2200e10f5be658bd70e8ae73509d02faefdf0226378fcc6c87c07f9ac814425fef44d1b086e5c61e56bb2a93fb14dfda97f6a1752198e85f1bbfc573296b96ae9fe4de5890aebe9364172f831a054b78cf0f204c4e4825b7106c5142a69525cbfcee56134ac30d36b9d5e6f41c710a3133add7da8ee06a20e33e05b37b7f703c8e32abebe25b9520c17fc977a0f9c4bed58486893f361dd57736fdda3350892ebc15c781ec106f88039b384d159264b585ae8401944419272191c00c6e533fc092d8a586686a1929dc666529ff1362b64324fa3c40d2bd1edc370430db140da016ca5e6871b6eb8b04b532a5dd2ddb271fd9d4ce438a0f62443fafbaec914a032dcb31ad4c7d35e7af966dc36dc2642b7fc3bb4540ec4a2d81fd0731e0d2522501c5e448bdead6be730b897bf70b6bbff1c835aaa8ad535eae8fe4f8ee7e730db897e1251411c8049f38f9c163b70b18b4962fa065e389f70b7c5c27461a426778014f3e738de04a0f38d061fbe904237f8cb7f2b77cee4232b34ed9cfdfa771fa3f174a6dd8ad3efc66d77a8e7a7d41514731fc69801ad60f70ac1211ba5395206b8b95bcecc45b5a0fea0f7ef30a1e1e6ff8dc8d08d8877827265597e8a2973ac14ba99893bef16c377ca5bd7b84c283cb11913f0e9e1af4aa4d4c3fd0eca30afc244ee66b860b312f1bb0050dd5e989ba3bd39dfb4b1bfd97264d187e1700f2129888c75699bde7f44d9f3c3dc6e4801172cefedc9de2f839ef085d501d1cce65beec1a3ce8d8c05a485fea453253c30e384f347b4eb30a0989869cf19e722fc91bfcabf398e8542e1b3e9229223b063415ec04c01db3947b1bbb99a973b69e28c45f0369727200ceb965cba6c1ce8ada10fe89dff51a3c974631b30fcc50e0322f81be0648c563d984b4bd027aacba5bb83ffb272ddff5e3d69de07336a7fcdf7a1a74d66914f6a3159cc94e8f082334ddefccb5751e703c83b23f251ad03b2ef123fe0ca6caede35d81d452a368f8d1e57102f090a2ee9ff37c8aa41fb0cfa626cc600e56ee665c7cbaf18a160ac16fb77bdde224e7ac7d1e25742a2695437ab5b8ab6f5b8bac71740c3a035f474c5157b4e8675c40647a3a38af7a151247c09c182af925de1d5aae4ba840ffb0ab0e43512ff481e48bc7a9ed601f5b7f774701927f975c240c99d326debe97e6f74d44f99d6e760b87ef182648132bdd02ff17a1c359c396814bd13e6769f35fd8aa37b794f01192dc5919d53902e5fae9c322ecc62de760ab44522d8d197bdccabc3710148f3c7ff5d403d0f2dfef114cecc7faaea0da1e56be1f3f66f1f922617ccabdaafb9adb314a746ab8035a02f60952a15bf9e8474afaa114e917e6889fe4c2b5021152d7a3d7d1dc599db32d4c98a9d815888057e4f5ca1bfc348e9523e9531a51983f5ea2202ddcbc3c95382030d675d76dd7a00734749b0ec1921f7c978a56dfec5c1a83d23ada78bd558b3017d607c6e5d4319dc433ad304eea90f07ef3428fed5bd5d9ceef35ac2ecd191c31393e60e0f439fe3b5a69a272ae2a42d0d7309ea998bac7f9519faa2f4b329823b39bc30cbcc9cce89398338b0440d7a3293012cdd6279da38c3a9fde2213767ec0eb1c0a52c7a456d6c09abe71569b4fc973fc17c9241625bd5113898f11b8faf20e66f80c9f89b241e57614a5c2c1cd58ca6112a4a9a7390c5620b32474d70820afc74d63b2633d1f278891bcb81b8804df81a3bc84fea2ddd5bbcc60162fe97fe93210ce97f22f16fa772c7d845e78aedf87ea0689b7a6b02dee066e2356cf7e8e78b8dcfe06e70dc299c298256dc7de819dd67c0292e4e1d6c0e4be871184d2f87f52ca0cc6957f4f0f9e7c5d9fe42817637a95c2335985f3fe43fe8c6d102cbd808b5632d62be5f6bb79e267fdd10a4227504da6d844f3f306f597b561f4d4e556b5977594e4b5d3e3b55430e2e015ed304d16efad9241d8ce03a1e134360e0f32f07570641d1478872645ed33496c03cf7875aba11e6c2f2ef099592a3141820acb66f826a1d9b79bd4237aff67d53fb5f4b143cbdce7fe5d6638d73317160007eecf933a03461a0748de477b75773e088c31e62ada896a8d429e0d3eed7f4a3d4b2b7c9c674b6c57ca6fc3f820f0e8abf858c8804ca39f3acab31913a42bd776b0f9688697b3942a7ab7a00591999b7903941a9e791af025e0c1b28e6ed995c529e64587525a4a8852ecbcd986b8694bb8f008f55f6feae543b5395ccf8326a132ab6c29c95db2f65443d32ffa33357e581761fc72a5f80641f21d48b9e6b5644641ab35f608aa2cb08a68bdc2cacd1dd6bf6edc8ef6d9bc677f39069b9d6955d145410efb105a20a469a8ee0326ccd9a4cf0585935f5477527ff3a2903340c7aec93e28e8a8350e5fea3a80bc7bfc772dfcd55631771752bd82962360c4bde52ad5eff0381943b43b438e0d3e1a3dbd89d613598aeb03e431b4196635c485ba0df8e41620f62e30307362008c8935c9c9eea5ac2d243274af099ed5b0607f2e3fa07dd615d554582a1b26887f33e4ea2bb3db012fef1d06fd9a1fd91b38b1ae280271b5b1b2253fb14dd4b469e4e4c8c09fef0bd93cca149430d8d7606512f15072038d7d4eb057ceeae12dd73e7201838746b476b316bd990b76760d868b38e3e02b379b345cfdb215e453d4691a42f38806c04d6d2b587343e4b1bae0ec63b43dde9536b99fc869b0c533040ae41ff5b05cbf5da2dcb868d143601d2d798a6623814f3f3cb43404ce956fe0347ccd853ee3502ea8d95fcddafb7393c99745e7d87cf5185e10a71fde39262023f3e1d3a167c6a8241d90c04fce2628da31e891b72df211b4ba77a44ffea674367e30e4d37f17c747b360a37e1b6e9362004c80f659c7e2e5bc2d24267ca8085f2b52073a9a3701bf2a5724263a13b0e61a86c869ebaf8ebd35d29798f5b8afe914d00140e9324462c2057778fad8a1d9ed637f1758d0edb71a7e6a544178efdd81e6f307a5e7404790ae0383b291d69a66dfbcd7dc68cd7cd243954b290cb081f1e6acac029ac9af5f9a1073e5beff3a0c4d5a0e5d2ec0e7142c171999c1f039721a20786c09fc2a37253ea29e96b3c742540b993f56e4d800a25e1050babeb2f1a7a75421b38af5684b81aa12b7c6a2b524f85d2b0d8bfa67f4f61786b2afa443508f2376e02749254fd808c1e3d09f412226f64c9bc509fa55461e4791843c6ca255de47446301fd0dd91b1d8154f5eaf3f570fc98b5a8cbb8694d81233615078676338f85c6d10d213adbc6ae18c31ce3ed038202da7bcb28005df86c58f673230040610bfddf914489dd8389aa92338c29e5f87cf45bf61186ffc95711b686faba1c806bc817d92a13c9788abe7cf73d2a842e4fa447211f41cc3aa0d30b96f743b3a6d04add8ddbccdc7fd4ba36eab1b669754eacbcf91eed95a7637175b26571e329c73d63aeeb9a299419384330cdae4177ffca44ad1a7ac0a37da67c6d2428f46972052bf84c6d54e7e13b62ac1ff2904c0daa8e49eeaa2a0b4b9abc60ed67babfca64b71902da845a10a37b942b9f09c043bf694fb58dee1aa588803e89f0a18f68a8b6c872f3ae88c856bd1bdf94867ad075e281ae42e6ebc5782ed0155b90b1a7b3a14f7119dc022947295ccb387d6b91f518870c6a32e2335af684ce225442cc7d0853ad05b81c941a20b2e1ef0e2da45a9b74e1aeefba397d4b83346d01b7da7466343c378b23b53266f701285b805f0c4372deb35734a9c79b17d9c17abfc05ffe5e05ac3b099a690a0e2a5f04c0556f23b7c9ebbce383bfbe10e63f205956283a5d7e38fb384542d9bc33e158753485313e0ae0d530cb0d5d3f336b98585f1eb393754a4e7fd760ea383a15f3ca79d93aa2fae940af4747a369a6471759c92f2d1a357b99e27dfd2f690b598c35676c44ccca6ba7419e09aaa890bfd747b65fdd38174fa8f0e8004cac6ce0a50a85012f64e13a0e5c2ac0b531d74ada1b52008af4238f5784ff46860ba1c5747918a3826c7d81b23135f06d9ced8fc293fd73ec3b6709af7c5c0f2277e5f95c0683fc2f2bc18cc0211fa669ebce1175c04802c5893fff96b262af1df1f739d4cc5c6bd90f7418a573842e5e62a5cc2fc925c588fdc082d4b37a373afeefa8331e02d96533bc3a514b9cec3957109f868c21f7fcabfc780edb68c237d7c71009675c10e69536ecbef4f51655a8fc30716e087f3f66e43d395ed5a1c2639cacf7531e5d1901555be405e6f221cc320be6a4ec4eba67a2036152a6fd49d1e5de0da441e1f0717e3efaa18a10bd0a766c62c362e6c4c0147047a35475724081a3e9f21e34dc68b8c27190f32ee64dcc8b8927121e34cc6898c23190732f63161371401f43b45d268b44cd6c7fb39321bf5a55e11ffbea7c87b2b8f4784fbeda82d83eb5bca8572b52097d22d736ec8428bd5d473daf513bd9beb070f65d24990912c079eb88b133620fc9609c843428c1e185ac3d2c24dca80723b3197b984feb80d3e5e9fd028f76384183a86e1cdf3af1e15d7d4d5130fcfdf2551cd8d9ac3d8fb8fee632c7a78f73f7609ce90c0592c0f672765ef563733c49b35de4e4c39f28180b56ce6e3e7bb10f7ca0b3283d9b82413427006a7ee05abec860d2c8be84bf80063a4e6f449c7deef855be83c6f9aebbffb340c8b1278f9e3740777d00bf59191e65c9273b53fc219503280eb64828974efb2ce53a33535fe3136b6b02725066a9a2342b789bc1632ae806354b2dcf5a5ae9e1045695433730482ad62dcc7582053fcad3a2cede277829d88279116d64068cbaa49699b3d11a941a1218990df28f2d0b72f492f4497dd95d0efd1d8b7f2d928cbce109b9c79f165eff7c67aff2be2f4ebc75c0086d5eeff1d3f7126a7ab045b67dbf325a1f1d297ea61206cb559e73fcdbf82ff280150efd26097416952fb5f14fee3e2ed776ce97f3d9a2876cd59f372bf7d1e187346b90d9cc8452b457edc430ea1fa997eb5cd19cc049a6bf896739b036818f4d8cbafb9f44d832beb7b405f6c2401a955d401427ac9d71fb45bd32ad9f6bc228207100087c0ee66a4513c01753f7bd7faf7791e7cde51c02d3b753fe1f5c84658559a19cb61751aab23411f0e355c875b62850b05555b03d015c5205b64a482979fb1badaeb3d076d2471f6a3655c30a1cdd1382f5d5e6424480c1dc4500948419f7f6210080f289f22cb7e8a39602ba8c91dcfc10902ca8c43a4850fead5c10e5628005171f319b69ca23011eb4eedd8842f77a3c3a8e277431d309d28351e0ca82709dc901f4928583ccee55e311401680afef7b683ad8fe6645df19d354e8255941a6439e361a7c2f9efa92fea2cae0ad8a0e638ff50925bd3b9bbf5d2bb99eb80813557cfb3b6c4d9d727d12d6605495ce898def69e4dd0e7fa52609c70d1c82c79bf9f151f05447f1cd823242bbf7b88fa1bab27bf335b1c3a99f3af3dd6b02a99bf85780e928528743c30866955fc3a3f014952c1d39b2e1d8c6f3abba24b9b0789f7fa7db9ae3141732a970495dc119b51df31974529f71df85d96f5a568101c98d85a6da38d2525e7febdfe44b75eccd01942cec89f73d5e0882222f8328a61d04a886ffc0e303716c5b1e2376269183eb5ff2d650717d29888fb262a11e3763a9c9c01d70703089b9a0d72ef59bf96580cbefcb4b091b5e9cf346a8cbf79cab14dadb23df0325755b8b4d711f0e309ee9f330f87343992e5955dc5fb0d7647f5e8cfd9c9eaecf76ee578850d371ba1bfa505c18dccdf8074ba0b59d4ebad9444df1e08dd2c233e65358994d5e0dbe34fb76f20bea43187f5ae6a716501419fef8f1c30ae7f4594057f8be021976ad8e59b1efbfadbe61baa86b2ca8fc04d053f252c85c71a0b1140484b9344d08482458b7f5a40c5a8fc61fba7cea71e32f96179cbbe853ebd440f007134ddacc88cc58ed0b7fa926e3f2e06d9ba94cb12e7fee79fce0a6670f3c8099550dcfbca0e8ce591b3d71eeb238951e48f990e530ea9239c81eb611599a1e0690073eb51a827da9acfc674b6c46451b77f014a07dfe0d984134dbd56cf5743bd1c5925fc6ec11f2bff4861167ff557b3a0de542c36cf13a9c0028eb99ae6bfbd953a31ca73c3bd9f82e69fb006195ebe8c6c3fae0802b6003e543f15e565e0382de8f3bb912dd0cbd2c454b42d6435886258d031e7c7e5fc7ee361665f10a4b3b8a470943fa3ca73ee6e40b3ac4f43590fdd04b44a0ae297a18476591e4fb873b867c5baf42007d6aefb345aa418d96b023c200a0afe7d87c8cfbb7d446ef1ff0f5a755afed95dff3de7f321af0fa0624b80a8fafc55da06f392144e2e7f0f656ce1f760272d1802eeb77a5c4b725058991f1e6443085dc60cfffa0121e4eb3e7afec976626e83eb195cbe350472990bfaf7e05ee9d023383f865ad81ed8e56b1ab638179c8557430fc37777a529bb55239856d9086a26a2391c81b8efc82e6295c1296c0f52e7a55c804a47c193d18ecf4799ddff7c1800d2d62f1d14e9fb8d2bfbe266b64ec879ae17cae72defe0462cc401e9f33e7c25d0ca3096f0413fa210c1467b06b75f6798d9bce1d42b4935dd0000b8baef2dabfdd238b58fddc4feafa2fe4fe2651a8f027eeb75ca3554f099e6379cb81b06d48b50ea04722a1ca7d3e216b07b45a0b3fc3a49048aafb40c70bdb5e4198c2a82cb6f71131aaeaff5104377e658363431b22a720011483de20528f0cfaf2cb59be4f5999350627d558a73fb72e037a964ec91abcd392268934eff7b30e91bc69a19a0a6349721d17cbd39968c381134127934dd2e89fe3b2954a2733b3b3e94feb0320a06dc1db64f7104363872af5e5731d1130494181100490f4210f9160b87c0d697871a05843f14e7e77bb54b30e65c3a1d08b8eacdaa806afcee0c7a6104f5a7dd3106a35e74fafa56079ff7c63a61a49b8a37a61ab5881ec44af7c9c5896c03a280fc3ac6e937b2252c3d2ca024aae39729fc09d7918dc765d5a503160297f09a9bf2b9a7ddd07cc83bb21127c2e4c5f95f908e37e691bcae9667f00821e6349b6e72c86e4b99277bc5e02b5822fdfeb591d873d0fb3cf3534b4a63466a7cd421342b06d0bf2d4c874015489fe523321fcc192aeb11dd0911b57995c3ff1dfb349e5726c3bb2743488e3f5483372c324afe709dd94add32cfc16a36117f736f7e752dac8e6333a60d09ff42b30ea4631414a944dcb48eb7a702d13205b69cfe592f0d8760403855572a7f14110e16bf4872556a454ae52e9ff0afeca764e9f9f43dd79e7558c0affe2cdaca59152eed87a60ef3ebf102c5eec03420cb216b13e465b955ecbbdad8636d40ecb80df49437cea7c82d61e9e1274a905e8990c160225cc7791e97d3fb8958086c5715039ccfcf6443a36fa9fd99145329fae575b4365691f1eb85c437541e01ccb64e692b94a4381794b828317377b43ca05cf989cc0fb0849123662d6612cc433348febc617409409efece5d30e8150d82290a0d493e5ee86dd7fd3b2c0c94edb7535c042a89bb7b10438244b001f118b7412eefe374a9df1276a04491b2b0d4ff952336c476ebc0fa4bf3a80c303e11b6190c3787cb3bbb131ac6d71a15431706f36dbd5aba324a27a1c7f6affcb0e9c90cd912517f6fdf07531490747db4c84df4ca3e89a311e36677c8a8b9c5af46096d1420a5025a76a0668febd654e53f87f87b26ba554432c4d8458b49fb4bdb1fbfa6f3ecdbeb1297d27e02fb95192b632ba770718fecd061f941c4420490c8b71464f6a965b366d3ad81623433d4777ce921837e6f3bc63fdb9f632dc91bc0bcfe26b2fca0eda6838d8570d9a9148e9170f712c07ec5966fc90c79611d218257811b2be8ac4534a1f19c8a44f26611dd53ad867d90e6ccd765ba4e914800f5d09d3df6e746d75c52d9db92a87b08aa92c35354b9e4e4e683f9bb4d3cb0650372dd2626909ce8b7cbbbfb9f981037d9c36bc5951478ade77288439ef9f632329254992c2fff491ef3e3c2cf1fd72081ac3501f95c83bdd0237e8b7fb8542cef5f275a586cffdc2eaf3c719b67d179e2d84fc78ab9e9648b0be1217925bf2e8bceb24940615169610d5507e233552c0e76aa0aa92456227b761b6c21f404a028e0cc7f92c458278013c361b06df77516cb97b2f8661fce6b663aa1e881d70d2f8ff549c19ccd8e7bd890fab9d3dc1e8107ce654859b48733e1b60dfdb2584c1d4fe5eeff015caeef0415c7cf4dedf921529fb1a2869e7ee2c999e4051482c950ff90b19ffa435871ac2c99a296208ca6a84c255724520071ba6e838f535bdadacc335c10ac8bc640230837c683ab7c17291b0f32cca5cf97c533429beddf16cb3080728b6505c3fc34ecdf2514ed70f24032389eff537e563f05ff765e3010d2f4b9a5260a43b615e6c3a575684e5cdd85aa18798f3c0c49a58470cd536a0708f37a557b98bcc90aa8ad399d9242b8f85fa13a9b100e5dc3d6a4f39cc80838efde004121cfcb51e52d8c31860eeca018db92812de717a1ea7b6c768c53fabec30f5623d7538c6c944dd33686413cd52c862280ef8cbd5c8490375af32b6ad661ad352647d5ae23ab07e7c34a499abe82af730680446619542fa93960d2f8792468b17c592f92d5b615f370aaec132ec5fb8298770f9c100806f47758c7cff34b0bd65136b6a6aafaa7ee908b1effa50ffe1de9f4cff0bf2018738fe25ac4d69424591be4eb9037b0dd854822808e613412f4360046ec1026a30e7110856995ddf19d459b36c375731a2bb1ab02b53620f1fa17c8b9588ccecb5ac3d2c22dca002ad308c85cb0286e83f0532734a8cc510a43e741b78125a53874b3956094561197565a45a87687f2a3428cebe7f31a44b862fba39ff83f5a7893edb51ffe59fb33a4b5e5578d93ff052851221edbca3eff4c5da7137d767d4788199b7a8d84edd7c14e067b87a9ad9f90e555e11e97ff2ec3256ee7a8af44165482cd7a60f5d4beb9da82f078eaebef12908c2c703730fd5cd997bf7f3df434d16af7de5b69a3e43bdaaf57b2ee93a354481ce7d636c4a19c5b8f09101b100dbcb4bd1bfe383c1d4795650a54b83430982c5da9da88ab284acdb65e8257064c4e08ae18af3cbce7687dc8a20c0dcc4f948b765f7cd7f4d9a89a7a62cb9d92e8222d165830dd4ecb3a06e87bf9149b1336547ed0a161aab1ccaff97af9d241e5bc944befe501d5144ff75d83b1f0ad00718e6e960363521b8dae8221d40c27539227d3b0e02acd794f917d4bde3c79a207d51a04030281402010722ef40539331abdbd1db0b72a06ac6cdc96638b8a4ce3648bb63e0844045641706b0fe4b61ec6aef69042e615e84941fc1b23ba84438b0a23f1ff09cfe989110cc31292d26e58692210ff51c3cce8876f3d81de3394ac536488a2fd0e0c61dd63a4c7893fffabed20231edbe8b63ec394af6a6a117feb2310ba3e951304522373d249f2bf6b124114c01c3101e4a6b8e5c70f6b83be3c4a768bdc6e652780e7d18f93e9ac1b571e6ce9e8f7c6cf9d36ec7c8c20396303ba77e1df53390c5b40bbef33dcfd606587ca94cb8ede7bc8dde4e156df69dbfcd066c6e7bfb6794f66809e5e32a446b5ec1ef1b2b816a1a1d263ec2e53440a85e57e9f2c62f096040d3fa2799efcbfa704e7bc803381e6fb08dfc62e389c6bb9d1244121a7fc5593bc50bb235f73051458320b033775e0384e5b74ff7d5740e4682282043e28bedecf42bee627a708ebf887712f63d23890ede63fc5f0f97ca20949fbdb5f925f5453a59fad104303e54b1702b0daba99ff010cd7846d6f2f4cf62ef99db39f5a49790d8d2752550b26b8e9ecbf7d4b25b7930748917039f2f53b07e3867410c8cc9b1a3c1dbae27954880dad405529215c0e9240452113d184c914be0e43cea1f18a54a4c01d640f9fe2579101e96b8ef552fc36f0b9f24489f4a8ea934655ed797bb46429c40c9c51fad3d7c187dc99f7b130eb17a0ba3d57f5a6bb0de4d8cbf552abf06a4e39b0a55d3b003463948e7fd475113000c92f1c43caa499051cf6457d4fb863c7fe692b5ce44914e8369a296165c71d62001eec97cc67292024067e278a7ce8eff142ec51540316108bc439d4a6b442a105acd688e0213d5208fcfcfab47bce4ebb1bae374ae6e0b55b053f9b3aa49e35740dd085da128d93db6dc4eaf6242df27c34f710c1b4c2b5e8aa7d9f70f68c1a380266621fc0eebcc06e52f4c0ae425e6017c1d13e249e4538ba14a163351b2410f2814e017a1d12d010e1f30d83351de404091a6a50f34411f8925c61c2558ffcbfcea7b04721581e74bc5fdaa499d9bc4f9fe215b73e39e7d4d997e4ddcbb24e9ffe0ada1a6fb2e066a539d526d6acecfa4b8a1c0f83e01f12a5370f77636cb8d20a326419ec889ec6d630abf81cfcb6ec55fc61c605089f79551a9420ef50b3185f84a3b0dc4b1ea5e4842eb85088fcc73f7924ed24515d7c79010b954a99b49e131e3214d3da5bc66c01d97efdda76ab030ba296176e2580688d38ab9ea87fe0fa9fb7d6f6ef853d04ecd4e80243f631e5f6fef554ac3cec5be2971663b63ac67eea43fc19f72085cfbc6c14c4c27aa32aaa07fa87f0c68c459f0b292f7beb60d41fb784a67a594d7ff01dbdefeae1f1af42c9148f59d794a95df70a0a405dba77fa52be1f6bd5a7d095c615293196794e766cf1a7a0c7f9e6638266d902ced133b6e65bd503b339f4b78f9900fe45f8cc7060a6f9af01af5278ef7ace33342e4f15a25c746b48c1a9c3492ff113ce85a750596ab0047ca44d9daa34e84c81733525ae2b30be79c0e3f1096bd9f4ffa8ff3a78708f5e1c2c5381d1ee00061a529d62515ac702f8f5a2cebc35b668c2ba179405f543ec0c8dd1668d8d20b6005552b2499f5568b0e45e53c62ffbceb60c1dac99ac74577d38433cc25ba7b9c20ba05937573c5fc2a7afa259b460799a7e9ee0fd02291f3d64f6eb35b87cbdcb8c61e0efac06363e79b7d55597b2d658781362826d704d9bb67ea8ee3ae385c6b9b699ceca849d2e7b073fdb0884c91389d206880ac234b59a088d669976b3a22b627990f07a37df5fe3be141758937f5a7a5fef818cad67fc341da5121bf2b7189fc82473fca641b95f16eddac7e0e3426bb741171dd03f75c8fa3127213b04601cbc90fa9ffd714f24faf1f0c8b22b6ae7a64c3cd0802c8d208b1ef9bbe1521edefd01520867f370dad73464ee425b38cf3cce6518c28edbdb58dfc247a3e40144fd2085c67ccbdba414d92c8ff3ef3c267691baca3f1c0d1b49e21786be55e62f9c006a19774bcfd9e7302872e14ffb506a91f5b14622ab5872f6854fa5f6e36f6b81e6b279859f22ccdc1d8081d0fe8f9b6337f3a093f9d9cf704d63a0e697cc21dae9c6fe6470ebb5c8d2542b606089d3d2392976e9f281b72fb9dfd80061736b4db2765af9db8afa21f1d598e4a734c37f294c1257fe44fd0c812b7c41afa25e428af3270135c6de0adec1d7f5c59f3417bee3074322edf00137fa0add5e9705804bfce0933c8aeec353153431a277fdad74c9e644e06ff2e8b4a4ef1697215f3cbe5c79f8cfc0140f073d06f737e1e16463344d87aa16ee6bfa56bcf9880676443b9ce1fbc54a1f0b2624ebd07836b6d4bf6c24026f560d07e597bf1b016fdbf4f7c712388c4eb0ee49b2865e69e42624257b25d880fa176cae00ba9ade5f1e71b9389fb3af7cd6e95a2244f34807aa62dec689f7b77a605bf4d9c78418415f207a518819d7a7ea111af08b47f0cfebf1ae08363e0c14a01ef049d51d054da9d0bfce042013aea303100549d3ee3d6688883a66830b4ec2fe8dc88b2266d2fd2c113339c5e829178c21f9f6771da1a8eb44f7605567945ecf94ce0f53eb2cbf9af40e1dd39d5b88a11fc1ce72ce8d78ea36ae87054e47a12da2a5550d0c8b5bac163f997db517712db65d7a627a4e4258de2fd84fd5cbd0652293e39506005b8eb2eb198765ae85f68ce74f313790934a82c000ea22236618d33b32ade827e5bbc535cf1bf23a92b01c1484c992520e8e94efa600a1ec427e8438ffbaf8dca17005d6897bcdfc4f1e99d5d89a14ae697276868348aa6cd12f7c2f35c401728f561426cec2ee10e5955922bea73d2a6d17e7e13f49b43bb52926b1df5566004111940f9f48efd0a52081ecd85ed5b6bab6c6573c340db1f3b8a2a093e35342f1938e451dfbee10015061db3fe2337e4ff5337c9cdd690adca69ab927a37837e3116e28ea210f81b3042451f90fddafb90f4e74980c77903fa2cd9bda8d79634d3fed511ae8752a990c068b73ddb0794f4c522f45a907e835659caf415bc0beff0a90403bc84316205383deaa0729d9432625e3c7ff525170cfdfdcf530c82ee266d2bb0cd4be7ae5992b3b8cdbb0acc6139a3a687a0843170fcf2534d3db4241218ac5adb8261bef86c964c1566751ed9784b845f823cac250385fa6b78d7bbc7aba25d9b43aef03503cd9780e7675b5c0585ee78f4e74a753c4508b453c4136a7d7b02a3f95f27705597c1ebb2765733bd89645fed8f38d5318bf66aa3e647167a52b8e625659ade410e255b547df3784fbdc441c6147ab0fde58578cc85ad12997282c75ca29daf8dba3f01cd509f5b079d0a9a03ecad59344a14de6475fa3fff3abb163924c95af6397e86b086341f2332b977b284e03ad1304abf8ff9c13d0da6ee0eee169888ba2d017823cef9fbe28e2b510e63e35c3e7043157ffedd6be0db2b6054027a40aa05fad49dc244bf40e792bb588ecba2d52dd809580dcdb970669546b343905c8f540dc36ce59e0c787bc80bfe7976f58c4a48c4d28a0fd365ab52a54125d2ceb4f6ee093b28b2e3556339432e22c136d9f2f50a13b34a4ac33a336b8bbff9421e3eb04c59accd63ed9d6041b7b2f603e05611ab77457413f43f62e6f103c1a53c51018f043b318a6c83995f024e9c9eec18973b97e6b3fa43f66fd99888bfc3f1b43610a409d3ac9b278429b51b67f3a3ac0be32ad4bed4db234fcdcaea93ab8d8a033d42a2e4d5c2584b5e56097fd3746263a09b21d6f4360e0eb635e9bd310c65727d376de37bed27d96182e8bb533c68323dca690856bb24940c70eeb970d272eee8aff8e777bc0eccaf3cc7d5905eb8ab865bd66caa464bb790f321c080604028140a09f81a26934cd427629f0ebe0a14910f4aa8d01860c0b614253171ab749f342908e351f12e2a2b7df2c4ca1bb83586069e08a11ed2d3a662556dfb6a215bd97a981521a4f5f2a8a32284746f8cc1e17087cc62e433ab7e3408cf2907848cd6c4d57a228fa4ae54059c0f573a00e70f2fef6eb403d8356581445aba549619618320ede04925e456d8f01c9697bd2526783b64ad2243534f14cf213249d1f3b7722b5fa03c878f7d2d9ff2f4c17264342a24d6e0cd436c9e95e4c01f8af8c7e3cd3e4dbc8a6e639e9235b0d4a2bf585bb589deda24663b4689a54dce422f0bc3f0247347afb4f29403897f7ec4760b3157e0cf98319a0845b80126681d18a11eea038e100d0349640a18f03bbf702bb1d451171ebf927422e5aaa4bec412b24be0dfdbf56c710e8d6b3d0679681a1072a4b23ee6607b45ac8ad673250dea7421df7846e1547fc2eb80c5b033a1ffcb543a95fcaee0e3fff9d372147f9618c6952fd4ef9d1cd370343724e4b117fbc1ed8172dbb58f7797a828c89141ba77bbbe064a97f9bc8c9328b464cebba622ce32d71124050e67aaf8b55fb7313c2df87412043d1971f059d48f0047ea4cb095670c913a5d7ea08b2667a03727088b40c5b0ef2f8fa56116f25004970d5132bc12f3f4265c1511521d8390a7d6149f973c3c439bf19ba940307011971da04eefa89c36b3b946878fef50c79be759522405fdd3b5900cd7c2f4d68dbed256da9eae1f703dcfcabed83fca55eb44eb0f13c6c5c49041daa7267d697ba7ef34fd6c545ceb3063aaa3fa07f2a23d8256c3e7a3ec94fff9a18cc8108efb74d41dfd0c6ccc31a7ddc1c30ce86df0667eb979995b63b0e70bc647a8d53b668a1e3589c9442a364404424f5a5500bcf96ddf0b5c8c42b593601ca82429ed34e4d5f4cb414c5391753a6320b6f58d91ec1984ff00322973ced6baf11e5fe5ca5bc8a718f729ede01e664f628d8c7fd3c1afb25bb0192fa213050f8c26209662c2f07cbb19f968b7cff4d9be5f25c7377c193f397a1dc4a154508e0b193a1e26aeb79528651c3b99a191f085e76bc90853719beec52108cce45eae981b106c18008f1bbb1e03294aca6a01e2c47f32f6fc39d37f97742448e0cb16ebe61d739883dcd1562b21a141fc9352aa0eedfab58253d422b01965e0cb5159134520be6bdb1c920138fc09dfe6491b0d08f0d1491a7ffa4e804544280c0921d45eb46c1fc4b26e178827b6f1564b226ff6294c9a57021d7a2deb8192f02a99c7bfac14a223a484fba77af463944cfd04eb750c2390caf7627305091f04d8514fdc5b7abfdc08c4b051825c0820bb9694910252ab6dd7cace8b300c466870724029f354ba5ad196d1ff77f5188b57e5fd211c5ee7f4e5401bfbfe147c180bbdb40d0e733b67cc1281221a9291e70bb9d7e6fbe1838d395e1f7ed4c96136a70f0bc798434596630dac9f0100758e8f84f89b9cdcdb736796406a144e60ebb9acc4fab7cf132fdb1d837f505830f305ac020cb23e8b8a4b0e77c2b7d678b1996bc991ed5417c01b95536ea90e2cdf6c0fff8dfb08d096c3a6201eae6eb2055a3339b0c5db5b337334378af3c072c8dbab3881c7c6164789191ffb38249e371e1e9a7779be4b88eeda3bac47f968d9e99b202661e3c06530491758009192e8d5f10d141d07467ea207633d9907b05d653cd2995940c2acdf5409e8b05eadb1935d448b3a52ca4100fc342423d0ea39e6221164064961a4e9f482c359e133709121bcc3a525e0d95dd9de2686786ef50a1ff5909d02ebd424642fe46ff70da45ef329c09932728d1799dfc42f4fd5b25539a1519187ee2d6678015eeb1787673b58b241dfb4547be982e5fd2cf1d74c769fa33383fb23e3b768d4abfbe23ec34f049f9855f95f3866832bfc9bd0f5ac27616556e5099a7f3895a92d663714c1b4623b000ec8e933b80aef0ff5e97b4e25150df0daa31994a2ef3efdf207dbe41b104e1a92e1bcf81f95ed190ebfa7cd90d0bcd92361b90da54313de1924379fb5c583d21517a0178eb669cc7ecaceb3663f9b9f5d35973bd77cee945b368a41c45eb9faa92286a4c9cb7d806f94b2c51ff9ef42d2bcd5a144dc3d209b97482f6c8017d265e86c000f19385cd8d294ecf36c9a2164f340d6d46e20cdc218fba449559dd82cdab9414405d399937b551bb4d5fe23524b533475ac4b6ac6732431e34fbf9fee419cd8fb1bb0394cae31950b7664140653d2941dad8f02f63eca1dfedc505a569ecca54ed4d0d7faef6c993e7bc72271b2d1ad733ae84f084099951a23c36002712bace587fcfc3e95f4ea87cb069a9e3f41372c68aaa90a04cac6dbabae4d003a1ecf859514718e92ed2e2660ea85a0a26c95e0eef6f4d98d53318b382cf3f2a2a93824b0da782c83acb0edf2775ab0ba46f0849ec9871dd8c00bbcb9923dea3fb5fcc833e4237f23f7fdaa76fe84d6a67d788bdec4e3f58a0b3c9967fa53f0b0570877d3e4a8f6c249a60fcca9e7c3d4670fd05a477dee1601738e9894ec29f1d8650d4ba86a6d23ba5d5edb3e5b1355c0d6d6459a6a8334ca2beda4994a5d8f74df30e4cc850d0139f0afa5e3eebfe1b6a9ddf57e1b847fda10d34ef536b441793a82b4bb726a779012f13645ef31300ec714597f37f7bed326fd1bdaed6c0d044ecc4b671bd553cc26263c533fd3f7d07ae5cf55520f0b7985053372725d85c1ea2f9beca7d1c855b6378fd671ab4954b78e317bf0396fd08474d946ada01c909ea9d64d27cb424fcfffde779c9e30d1f408a65799a63aedac92588b984c24a75c13d001dda57b7839a5425e24de3bd8922a3d6daa9bbd14965ec767faf7fefa712f1e83d907d100c0804028140a06c28e4393daabce5b7a782fe8ecd011f1d5abd16e235256571414e9162a9f387f61f3f27d65b8c0face3213050b9b5fb460332e7b5fa70eb5591e28852f1209f45f88df82249bd6812b488210db8b7f06f10f233e0d1ca536c92a53f776dbb7810d99c927174fca997eec465094121647d4bdce31093e472263b5316d19d503f5fa3da7cc8c1ca2cbbfe561447f01721459cd40481fbcf56aca93a040686418c39a3c3068995ab0cc156fd957f728a4512f5e4e4e63486a31774cad403012422d977ec998c1aaf50be6af724d6aa2a18f1afe26ef0fd5a593ca76bf2fdab8868f357ae28849fcd28a8e658e7dc71926c2f599ccbe0e472ff4702023ffa659d09ff8d6dc5c3fee8c4dbd3bcdc4d2c3bdb6a547fc68ada1d3ef50787835c52fe673878db2e87bf2b320abee17e7a42f4b65540bf7b49fae70a907f3bcdbf1738c0f764e8376b8af5c8e29fd2c491e8eee976387ae1bf09ae1fe97e59f11c0feb4689e4ce0693c0d047cdd1c14c5490fa8931b6f8f74a859ab53251023da72ca23b86e0fe7fea0d4b006ffc8ef964ff6e61080c901f9c4b932d75d4cb952b7a5c9b39f5d62905eef4a54cd3a490f2f1947dd7b0038233fd6c39e3fe0d5724fd79f2af354c888e83b2e9729648a5146d3a5a592059fc5201b12b11816cd58220510d1c2cb5f85004801f77ac522a53daad58152094537eaa14b812162dbaadf3654c71dc1ec7818d0c107c3f90faa3e2f85216c3534a1ad9d9a7c17021e83d3f0d1cfc0dbccfd0afad8757d9318a1f627f2afc8c2961fcf277305a8614ffc98834af2916ad707a725dc470a57de6ee65a6823ecdecf9217175080c48a639155a1a952e3d16528d5bd1edd198c556db067f9d3b540c433b8b754d97034246833bfcbc2a9cd2c838f824e677bae15fde55910b30fc0ee59fffba762c8f24ac95727ff3b15d7f0e0f8550c4786fa4cba5970a4cabac54e9a86dc12afbd6ee3ec1f1f6e4fa20097d18810b35f1d0a4501e5a8a210e4f61a1d3364155f8e73154cc2de037d6e4a365146a062a11e09461f683966601a691166955181e0dc5a747705abbf669784e56a7ad889460b807ad99cf04b103fa82d8128dde2ef3547938a428f737d7d72aa28c1f3582398c275e11c1a04ac4c30b8a6717a3c1ea6304e4330d41a090956faeff5c78e9177889cf005ee8059e1f1c0d83bb72bb8dfe0ffc7beb41278b5e55c5f8db7ead0ee1cbd458e2dc72a94419b307ba37022d8322fcdfcc35e5d0e35e73968e3faa8b31067d6d0c90b1435c2358d53146c03fe44ff40b1ccb0bd834c3fbbe233ec7004a82bb70ab433b13ca1e4d19ff1d93a88534932a16c30c4d0b845360e9a69ede0ecffb850c8b25ed92c8302b2b5806989659fdb8381958841f12ece12d8975ac0eb1e0fd8cd17b36c889fc95755a0312199efaa6eb08a0f3749afa36e3bf95fe2a74554a93ddd52325834195188d1e0f70c641b729678d9a6d0a01368bc15a16ba03b97ffdda75db37593cbf27d788b3eda82550cfda2b7990d5eb796f7b6a7a79c9a89617dfa54f37dc368397c7aed9a9daf38a4a55ca3f737b0fd15eed995d2cbb40dd79256f2722b473bce549fc9b541a2f39eff6dd7df5e602e45e8f36f827f7d1c444b47bd5067d467c0ffc70432cc402bf71b1682851fbf9142c251dff0fd99574e9b30ec586a738dbc6e019cda9289000e6dfbedcd5c23ffe58ab1838bd87f727cb691bd134ad24608b7fa17d7f4e62e6807b2dc506647de002b93c8dd3a56a4b585ae84219e09403e73217c50ab741178a131a4ec5d31f4397a4bd2cdc0f43cc1a8efaae81a344a3d42c23f19da8cf1b75d3d7e9d7d3dcb32d7e28b3018bdd40782c8538aa3bdfdf1f978bb9f64a00d68c06b32e023b4be4fb86e6a2fbeb5b61cf6f506ff9d177916fcffd1fb7bff7166c38a6f9d5858bdf968e3aee7cea464fab7c3df2089a71d5f2e711e4fe1ebf0819e421594bff1c2f812ad20353fc5f82fdff011a3ef8f1d2a9f7b3d32f716a08bfbfff58f401e3e47618edb4cf554f095b0fd8185bb73f7322d686d7fd75d22e157795500724bf14c17cad2afc639b6a2b78470d2b55ed41d1f98295eb85848a5bf341df03247ca1452d4e65bc66d7d4184979bb0869801eb1e52c8d293c942fc807e0d82498b4ab974d28fb8e27c874d96d65c7c2ebd1837a06820181402010a8297058377efa374f03b78a353d5aa27825820199206b304e48839c3c365af8b4965a6783cca6db457d41cd43d8764d05a05af51f9f688e9cbca50dd62be01573675127e1c863add0faa49fff5625336135e336d8362007c8f7489cbe4d5ac2d23fd7847a78d6a9ed47d3ee87f951ba74ee1ef91f8fa1e768cb552c4ed64e63b297d9f42c183ae38abf56fc534e5e1350b43301c5fa450117824ac99f22cefe8afb23853f79257ed8c31426ff084533bf8ce6d25fb8314b652dbf2f05308e7ba2baad5c4870c6c4c0c953f846413e17ae797ad7b58971f069ecff392e195747d084be20a806677747383269ad9e2cfd32e14fee53fe9ccb69b9b10f33b7eed071762125f8babf19f585820b4702570ffd0c19183210326012a0a2d47d9079277342e698cc1199433207647e90d927b3476697cc0e996d325b6436c96c905927b3466695cc0a9965324b6416c97c27b340669ecc1c9959323364a6c94c9199243341669ccc18995132236486c90c91f94662b0289fcac97c25f3854c1919804c2999cf644ac8149329225348e653206bd1a2fed034cff4f2b7d37d7982e1d1c7f587388e628e97820573dc43be9fe37bea6743003b1b15a387df4c2341ee173cd278bd32ed80bb43d39e3a230fd60b12749d794c99d060a80f30adb92daa0dcaa7d26240eafd1b82e0e545767d638b0d7ca7c2c4d27849145f3a0aa061d0ba5bd491f9dcdff20e87c056e24ca8b8d87be47934f5611f5c66c47749c77f3b2c9208588a1b0ff3b73c68afdfe6e9ad374dfefa4fc5fdffbfb085be91bcf5b7e69f2e5e3db01ba77bd3905015b4389e36d9a9bc3fde09b5d0869e2f332c43ebdc318c3f43714b6c821f7376dfdb9b88d7e1177240c5e18a8951c5da9ab12cceca09d836ec519cb27638ae1918444da552a88df2802b30ff1c44179a10e66b708525d2372343e355c6dee4e374c39d3425c41ff697f37f80b3ff221e0481f015fccebc6a1b3e534db440dfcb27f9090ff4a20fd1b9fe1ce5b96da58be4c2a063fdd8f19b7434f132b6fca17f55ef0fa8c5782c8e2c6059cd28484ebb40f514630c956f12f28197cd078dafa64ac7485a15f20a7d81fc8d0c78221c89889ba2bcff1b427c30f66a9af4ec1266525b53d0bff1ca8704ca1113aadf4d117a3b1375d8f29cf90f1bc6c2aff7303ef986339644d28de49b832bf99908eb72c3b3231600e44f53a009a7efa17481b5b77e19cff7f4a7b7e9ce9582842908d19f0d6f89e032e9e01cae00c366c41fd52c2aca1215d940938df68af8d9f5a6e1fc544e0ea543ce07decccf78780f90709485f5bcbdeab30ee5e9b8fa2c56972ccc274b86528af61de26724676305dc578ae06a41c02daf34d85296b179afc1da1817ff3de9c993f14e88e77e4d02b09a08f9db1b16a856ce59252c69dcf10e826591639bca7bedd4ceb6bf16357f7f9467e18e5ed2b24cb31c24d3c8d2fa8b9bf6c44104004334fe479853a8953f24ddc33f4c4d05d5ca9282c60eae307d3c8cb02bed9b01603fc0f2151d37a4f907e66dc50ae31389d2a426f2e48b75cc8d27d5724e98e984e4d77023a781d9d25eac49566b0e7420380df86761dfce520a26f72ea7ce9f7615b2f86703c4dd91180eace16f90baf2feb3be9987383aba974fbd88f7e2dbaa944d051bd36edeb42c9e013a96422dc8cf8c1ec776dd80f00f0a8f9e747541be0ad0bf8fd7b264045f82eb1e68a8c157864021cf0163725a309cc1cec27a1de6f0dd0b08728e95601b4edefdd9955da224a482522780c1362794af351f40f98633daf840811f1496c33d184cdb0f32106d6582b5a4e1a61fbe7ef4128626d1801372c73d51d587ec2d32529bd79aa16ee75916ecbe1bd6ff2ce63e8fa6755f3d98d329ea034d0bd6cbc80559ca7e80661cae9759a373051302aa545b26cefdd9a11a554e5f26c236c340e62f32ede73c9bbf7bda755051cdee8e25bbc536a678d6946f189bf17c2122fab100aa34750c7efa7815ce0585db5fa22398c62b2174b69d3074c441789bc729991f80f7ed7a7a5d306aad7125969f5ccaff30863debacb9b627a46a343b4d5cb2f69c9707febb1c7c9b597af419558bc4909c9c1fdb8ed646f480632a7ad6331fc14414772397450755cd96fb7b58486b7ef5af341b3ef1ed35d5d6ecea20d5f2ff862315dcb3524ec6f9e50fb65b796e11fbe4f4de8704091d187088062c65f91d6234bc3871f9cd77d785d52ca01ac06ebb7f9971d2061b46620cd6ce93e14b7c61e3f684dbb65ffd916314c81c7962ccb24f7d90691de95ccf0a750e784a55ee5f2df1edc0f0337f46d91f3af3bed9fc23b3a7774d0768183e0dab71c0c6e41e2cab4db9dfe687058d22a6cbdfb84f3798fe75be44c3f0158a4e472a6100efe8988d8160da29112f8f9604cac59aeef45a1c2a74803b72d4d9b295f371bb07b3050403028140b75e6d401e500a8471a670d8129616ba3d275306e1c730a1ccf57dc06d84619a092dfcdea185a1b339d048fde68a77273b184bf3c520426c1dce2a10e54f4b9e3f31ad7d0747eff333e89f9c3e436720b10da93934de26ce2aacb738e340202502d3ddbf067bd712271f5bfe63c179b9cee72f606f22f96f46123fa06f29b0793a9ae25eb0011bfa34e4b5206ffe726f91e01d809ffe4d386fa41f512dc5a78b63287e665806400ae47001527bda304a332c5beafd49718e0145ccc6281a53289a12ebfbfb1da321aa810fd794078f805fca13f90da8fb9d89f69ae3316003e0442b3a673b8afb5ee04e190b0ceb11aa3330e4a201ad07a4ca22b8a015ce52cb5a944c2bee54fffd73658e362afe2b570d0b5fca7b1e03a7a73c38cd155160c1d3ff7a50fa578af69b8ce8813df1ea1db45345ba535f7fa2b8b055cb710e11673d215d31b80cbc9a4ae22b0de915ad76502dd35055f638ef70c674095a8f43642de0c82aa60affd9c5e19c14f5a64203819623d44d260462b503de57e8ca31f9f93502c39dee256760bbf1c0f85f78375d5440d76fdb7dc280461fa690f308eb7a66c44e5a7f4c31faefb12e84a5f2271a39a56bccb6678d60ca808e1546d23ad089f80318c78bb23700b0aad0c0a34b6bfa8a0530b04106b1d964977cd5e2380b9b8aa61b86cd65b7c6b021fffbaf6684de54cc6300306ee33c03ffbaeaa925eb9cf03b632c0a305f540a5af73412508a77b733b450e64ad80ee80bec6b8d84823b04a2e8990d2b73d81f1165854272f17126471f62b303aa638fee806ace94f81ed0ca4005176f9fb9527f701bfa343fa1a99047a8c19884b2106e70e951e5a245bf61d0e7a691d093c4faa0cd37a3c7e0a75571be52755f0998c2574a4bcb805f43cdc6859fcf5945ca4bc39d57c61beb9461b89061bd4aef6401da9da39e47c13dfaf4e0928c0a450df5126bb0a113cc5febfedafdfa161d1f370b3712888e8ced8c965e410ec0053af9ddfd597cc43fff9f113ce8ee9d1aee3a73894b7fe062bc6e0a3a667bec8143bb6e63038a80b2b20367567958c2d2410fe61e06a208d37df8c25e18e1ae877fe3510d03f9663784a1ea1085674c7639d630288a8ec9def20f48b2afdc470d7180c88f9c5de6fae36509d34a8b29e306ab9226ecc2c5ed55ebaaa01183236a4a47807121b27ced96a9d4fe0b486eccfe843d94b9ddfd932147c40d56d7c5c57757557879dc57cbcc41326bf977577ad7ad070aa153e74ad62b71534c0a1ab1ec48f13f22e4b367357ea3861ccaaa58ed4ba4f0871668cdd6f62e8121446dc739f2b745b5812eb60380cab544de5d928be481f8eb1353108437d290c981257cf60f1ae4a548baf187a18e0d6586b0bccf02498328278ffa5b380c0351c94675876b8f2cbec2d52aca7836fa7b35e4dab6be8e9dc0c3ea864b1ec6fbc6434f6193f53d938fd2aa1e1b1154b8d44036007db20ac54775137ccdd35fd53c37a558af54891be12bbe7755c6c6e37365b6f07146c4cf5f9657ddafac734e494ddecb4419bafaf3d87022e48fb90d69c05cb7bd4fc0ad82dcd6c126109203dca576b59f52e7058d15c6c1ffc8b3adf61d175306cb8148feaeb0cb6801000000000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x99e7125a2', - maxPriorityFeePerGas: '0x55a0712', - nonce: '0x16d54', - r: '0x2526349ebcb7239ed6f66843a7368519723cc3316abd509c7cef841783f81ab2', - s: '0x0c7d6950bdd3fcf6045dfb4455b93930587822ebdda88377f3df852e0c8736a1', - to: '0x1c479675ad559dc151f6ec7ed3fbf8cee79582b6', - transactionIndex: '0xbf', - type: '0x2', - v: '0x1', - value: '0x0', + index: '0x3a76c42', + validatorIndex: '0xc9c43', + address: '0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f', + amount: '0x1260675', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x6887246668a3b87f54deb3b94ba47a6f63f32985', - gas: '0xcc579', - gasPrice: '0x479a12896', - hash: '0x0f48823439c41ab6b36752bb865cc156d1f56d9e5284eb0c9d0b0177f298f79f', - input: '0xd0f8934400055279680000d20000060000000000000000000000000000000000002d0000000064363eb8000103da790000160000000064363eb8000103da7b00003f0000000064363ec7000103da7b0000180000000064363ec7000103da7c0000380000000064363ed6000103da7c789cecfd0558964bf3388e3f0fdddd252022208da4743788744a97840a28d22d29ca4387378a8a84084897484bb748838020ddedff7af1785e3d2f701f8f9ef7f39edff73fd7e585f7b33bbbb3353b3b3b330b812c6c7ff2c326e5f1c353f1f6837ef684012d5cc30eb2a43d37694db45c990ecf62d5d47b7917fb4b6f5f52859c0e36ef75714853345010f0968bc616f5d795e553614f53420943ea5a1b3eccf3335b82e063c0acb121f5c36c5d87d3ce9de7ab967d1b346224638799748d6dad5e08f97962f202fee64b3748d956dc4c5f25ded88913b683a468d0d80b48cf38498cc420f5296801948f518709568910779d15441967b11d1b989a580f6d759d4d2d0a0d261123a821d0ee1d68c7553f6c71513f78fe5b3036c499f87af2ab18e667439297afbe2d351d8cb81d04e5b4e20f1e882d819a2915d3da7c4b224347f22b3174f8ee6e3c6d5ce307e584049178a420adb23f3d190a820e9a01fa93f481152f0a9281e067ebe403f8b04389943b18baaed93f93ae8fa8c67726b5ae42aed47d944dd9a6cbaa212c0ce00ed75e6a0468e842f1abe644b6696e0b6220aef6905a18618fd758dfd634178640d177a028e47ed832f87ee8333b30df2ce60fc25c5682da958a43a2b186373354d775bc8bd3201909c1dfd61cb832268e419faebd4f2dc023354cc613788f64ea2f751204026db84c4ceddddfa1f51904c07bc3f220de56b9e5d95698c521f7ce4211eb5363daac416fbe9017e98eac1acfd22301b38a4bab1db3af3f20f4ba15698a89da84349fe1c0b27f619a9f4cc003f34b6c85409e6f3fe3f3c3418cf44d128589ff671de2dec592cf1193cabefd8d5228fc52bb6676ea6b1a7ae3f2266e8a844132a193da8a4b695946fe1202e105ac794be1daf3b0b435ace5ec9bd7ce1177535fd50f2a233379a597939ce20dcf0870d44935cea9bebf5d2f45fa2a15763fa6be79e4eaa4bd63a1f459e2c330150c7508c476dbda17faf26841a23c71820541decf73e7dcdb0e23aa58160b726a16728e7fe5ed1f2bb647cb0b54e5e30d1a60a138d55440ca1bb7f22448c2af74a4e4e2d1e5bc4551bc39592d0ed0a699cda463ed847239455ab96cbe6333291cbb5591aa7fdde20082d076f30a3604e2b06de707ffe8c65175d04000f6f451bee6f57b39616d8e33f790aeb3514cddf74008c22dbd3a6b374ee3cd070ced5af83373c21fdceb9b22761c32cbf4519ec00eb71ba9a9567e119b3cc360007816f9d08c5013a13e71159e26bb57e9b87d518ecf17219ccec0ce0f7e48c2f8d1d158e8ffab3adf0f73302f7d17c572821d8bc4bb7eeea972186f896b88908f198ba7cd34ea1a9d22f0f68e428af06775bb0dd282044f9b33b2c4e844bc4058d6b96dd9f2802d199dbb6edd6d58f4e76bdb112f73dd850f1ae046f27230750724ac1da53e6fda6e2cf9bebcca55c42f0943f5e5a061978d4f86e64d87bdb3780f81646ca74b1c750d9cdcf29f9d389f3e62c32552c0055e4809717c36c5e18eb4c9fce2043ae1261af85cd0294521bc807a176b0d19f99b4bba6e186d97053cb216d4fd1304874423891ebf7cc858af8d0d883e82d6531a25f8500ebfb274603437eb1a3cdcd491016230bc1f16b6a4b567403054763014fdb0c9748f762ed4596798cfcc83a9e710c1eac62a0d6b00fb62a181f34b62ef12f40fe7d8dcc098a8c5b71f8c0e1adb7b0c1fe28ab53bcadf230d68e4358bc49e8a0d5544491d205b8c10bc2edb18ed75d9a3009eb90043273a8c3dad78724fbd18e7fdb2d6846ba5ec07f828394d91b55778ab46a6c5e3d5eca9ebe7f177670b30821df90110fa5e9f9e8c0e820eb97a7a329a37083e02483afccfd50f05691f58f5d08b3b500ec0ce88260b98342b0ea25f9ac614e8225ed716de24f15c103f9081d56fd5c269017e51cb10355c1ef373ca8f92e227523cf1c84877a1bedd2f7a3c7d4807726f6b005cf4e88a0ad666872f34b52fb8a5f593a47a92bc94607a635da7aecc5e13f9ae0920b21721750aee5ac7e81532c7dab3c18b30a5478adcd24115d24c47dedaed3407cca7913e686601cdc96f532bb0653d26aae3e1af2697c23525df8e10c1cf1de206e8e617af20cc2aad633d1a56ee9792984ff3a299e6565fd2e389107ee01b452e03d40dbfe872254a88e0df7d6eb16bf9a9b4c6437e2ab4eace47d6540525016efe4980e64c89db2a527d24f2f961d7cead7ab70f13fa575fa13d31e9f089fd1431344000e8f20bb1855d5434bc871080d4916a78e69949ef4be0a96f03ea7d74c317ed5746bd7f03904efd06e00876e070016f4903693d631201f2270d2952d6db7a88f1677b87c2d2488af3de5c38e03c2b0584bff02674e38c90eca33df7f85e2ce1b06a60df759dd4cc25f1647f7b77bee768805f89f368f36bf719151e39459dac94e461e7e9cccb573b990994ecc487f51dfc00f706b77aab4546ce46e574cf54a1f7b1e18f77cba0915c930d46fcfd36d56b8d8063d7ccd9ddfddac5f09889d019339d14149c013363e530ba3e21129c372db93020591435ee7d757f2543e492ac889cf68e978ee539cded9c1ef1b70e38b792c4090031572734e43a0ead5707c5e6ca81dcf0f3a21406098a99ea2667cf09a76862d001e59126525dd4d96d7625be37db3b149e47bc40c19cb47ba8b89f4f4eb81b3ca209c838f00cddc866bceb2d44b1725dc744de719dabf0ee7309d4ee3ca2cae859cd0c409d206f2339ca2035de43e3159cd4aed412c1cd4ea1684a26f57483e857ab4f2d806798cdb725663377b6a2d966222a4d360f44d6f36782c4136e5de110b6ca72c707169a6b7663fd463edf1fa608ceab68b1741c3cef64bd21fd79191bcd246f8b621518be295a4176474e830dd2da849bf3388aa4d61dfd6c344ef1bd745d22864fce9180ae8199e77398dd9bb91be7270b9c76776dea88e365ca02ab8294e7424cb8bb1a81a8574687b8bcf14914d9e5f645dcba8bee04968d51d0a4fbea36061d94f5aace80b9c863e71ebadef946a3f74fce505d3c2065fea4c7a760dc4c2be36aff80de65f607e60fe2fb1dc47eea12c4ee1dc40ea85f422eb4e43f18321c04f255d23cfa8bf32fc1f677d913e79842ff2d98a21cfda3fe433ac251a1df6481fcb1b4ff602b0cdfa21c5501776cbedf8a81fb57b9bf1546edfd1d2e350407e2fd7b3b20df26fc46ce0e42dd7622ec652fdc2cdf8291d2eab4cfa1bdd8c3d5188ebe0bdba6c0f0aa5a36f94463a2f59b9756fbbce119d1179ead98d6a612316ce82a6d9ccd5ffa6ebf408de1428a3511ee85c368b82b9b0adb2b7f15170bb6a1404eca80c43c7975ade7a137645b1bf6e80ef323a5aeb07195820d7f059d8033f0432bbee3c0284d2d615144970673532c9edc2413a240f934ca1db4b1bdb5adf00262f98b5127578db090baeaab36b33d0053ba995d74a1669827d862a163398fc01f9a7a7b621c7859cfb96144457e8959c8779deac375db57afb1b10dfc5b73aac5b4c98b9defa81483b50aecac022606d082e4802aa29c5ec0f6004c57fd50ede2475c69bb2b16fe267e9c82d1123879e380b2d822fe9860ef98a4595001dd416dc866d6ea3564a5acc1d1c202a757cc3ed2a04d730049076b1ac1b71fc7cdba133111cc447a224ddfed40054e18b6d98a0523ba34a208954bebca10c6b0f84bb4bc36d961da0dc3cfaf87a837cff9fee762ff23fc71e9fe115e7df983820fb1389674871f16d94e9e2bbf2f001020386ed99d94797be0d8953e0e5828d3bbba8fe04a0fef973ce95e1f31267e98849b671d105f863a1db82e4e7ce1a7e7c54992d7dfd2cc13014c3e440449071500f9802b3af05e599f1d2b2c3a036de69f8597328bd520dbdd2aa6be316a2c749f668806800e21288a359cb74aa49b87268db5d6f54b49a760e9de24f6c33115c49b789f0a81646d67f80e4a1d1d8082d5fff4c9f98a8854bfba7d2c23769c9a048bf7d91680349ef00432e1682bbcf8af3b62879303baa678eaad3d63026c95704b4f2f611be3185406db256ff98663ca50f5ed601d02448e6f37a72f3fdd0adefafcb82b5809b75c8632d5fce232acaeeeb5fcb55af25e085cf70e5c87e397e39ab13b8cc42a32e1ddd28ba003ec725becdbb1baf33845a5417037c3e9a6a821257066714f67a3403a11847b42c7befdf2777b7899952d8bd13258218461e03122adab633448f9ffc700059beb27b3a9dfbaf15b583c067e86ba5b50e66767b5e7de0b18d5be43b3cc6768a976dff244972f4e2dbdb69eaa8ee3f296f2b9d5cf940f8140c4e20edd88f55572c42f885c7d27e6b0dbde9b36366f55efa459f002638a78a1bfdd2615aa2697d0c1dadda22658df08c5559cd83e584400aa5434da17609b580ee42015f001674307fd6e98e43e6b7c7e36993d653028db58b052734f8ce2dc4a50ebf324615a40587af8d2856c4fec87cac9c34cb2726a1f28435bb69635b84221fe82e367d81c20d09b3b5047f2a3598d44e60d437be8ab88f84c45ebce159b100c4b0ebff41ba3eb41704cfdd1ef145d4aa0082fd8374fee75687d959ae9c9935a204b31c8ef71583948a312befdd0bf5c1da7b5ac201ca0138daaa8bea87da95bb2f847d2ff028c8165e003289e329dcf6dde621c5f24594a88126c587d5dd1567f6dc81bcd3156c4f115441c5041d4f2716e7741047a58a5b369eaa4d10bcec822eac61d88bf88dca552443d73a4a5ba72a4a5ea483c494b856af82cffdb7a8fdbd0c0b49fbc801b76c450e2547900c7353f2f32d2f0771f46f3716a85f25503aff0b11922a1840132678d3b2dd4a0e70cd7103de50865b591f346f29ebb9b340ef3a224ccd9c61c7cbdb1e0fd053716f675d89474d50a739d8542012e0b68eb98e43e07fdf8480d67e8a76274ac19ae3780e01380e1f302581e38b3162c244fee842af97571104713c59d4b7efe14355cf23aba4e8f6ec84580a934623f7c4e6867a06fc1bca87767baaa82ebf64eb48df455a0bbf15ae99dd75fdbcbf72bdadba8922a3ecb69ed2e4c03443bc8e9058eb18729282d8c09c6fbea4876ad3b9faa65fc577bc1f079814d1655bc1484b734a109a2ca718a6549b5d02e2fc765ea31d3c778f4f763bbee029a9fe8f9d726e8deba84ab7cd4bab0dad441983f92f6968ac28f60ee5da12c5df0d7f6f2ff8af632bbed5eccb953bf5999de13cde221d3aefa2132fb9c72668d5a9ce3c1c8bb67bb60ed05c3e705184d550284ec023ad9b25b6fb092a02479acaef5477d8087081a31984b7e58780b601cb84cf6f56f977e92533ecb52d426fd7cfcfd5afc83b23b0ada566f6982ef661dad3de80faebdc032538270e21ea9852b714bf41988552ec37a3aa73504d9c7898317184b7eecd6c9334aa169e027971d24ad432c76a972e5c93e15ff45377f57461d4c8087c777d2e433a336feb9d0bb09efda97fa8a59278b361a0c1157e262f9a3929dbe884814977e579fc35ea26440b492f0915f2e31cb250c84844d45681f2322693d2079caaef556ce6986c6ec9c90c9b05fa3b2dc69e46230dd1ee3038466c8c57d5ae03dc628a31734b9dd443a1b5e15b1120b8eb2380c91752a2d400115d79277460e84f89dd22fa6dab17525aecdddf0a47921cfab59ca921be5fb010782b6b683b67cd4b77ee84d4eb0507ebbd1483b8d0b6c71e933fd12c3daad980fb083302ac898dc6caa4ad0fccd1d84cc402604981e13041d0a26cd83c9b960004600c8f115820692fed7e9434b775bbcf2032aa3bf0660f481100076d90905d98ce1c1c6f7bb74916715c09a1be9a309d1e90aac42ea4db50f673141f0c1c69742cc252a66b7366f168abced9d4d307fc310d2f3a4ca2d3fec216d024151e0388f030f42b49a7c42c7c29d6e8669fbabc1191b4be31cfc8dfa77aeb63d73eeed980729ff8706d031d084d5ae24924f0f87c5b5198f04e65520f7fcc4ccbf647e80aeafef64f863ce77482762a2a5585767ac9f6ec2a03ed40452ff5f3f827c81efe8ffa1fefd02600ab2eff81b58ff1cc74e41ca07691f981ae07b638ae3f6ca9fab1fdc1ae357c29597e1158e9c6e6e8f8bee3a34c5b9350574dd30f936fd87f9030e33207147dd5e8cdb4649ca5cc6d5dc414149474653f6f69fa608ec1e0e0e4451070736bfe140d2c1f6a793d7e79f2bff6701ac7c90f50586fe63fceb732c9a31a040912a7b314dc4e0c315e18a41fd4610fc9301ed41d56b3e0926905cbf947fcd57cab80cf961ec3311e044313a79cdad4db9df03c1ff21fe05d63f60ebef18006bdf77f4f9e6c8497a84204f564457606aaea989a98994e67e9b7edcfae6054623157c6485495fb96debcb4e92d1de6a40f3e35869d9bed1a09b3612f520dc14b0baf4b0c94c76441223df846e1ca937fb70cfc663c2eee388525288ad957c41fd17c5a0f76f8ac14858a0f2e8322c2d567162d33c6380351c714127b8f96f540ca2db7a12b1fbc8d7ca31043ae95d840a635fecfe59c5d5df0cffeb8a41cb120c26d3a8fd6057d63726e7326ed0da32bb5b9a1a71b0d124c2bff9f042ab83f5d9cf940f8140c47c9ae3b3cd941eaef5bc501c69f0becf9a97295294d6412f934effa9927a4ebffcb632a5ff806a5030f2d8350b125be3b3cfd307d9ad5d246dc5b6e6e396053ed3538054c0071ca04f40cea50a6a18784cb759e393a7debd438138f95ca761257acff4cea80e0b606aae9a8565653abb30f96e90b60563657cc9a1f7aae5f201201d88c0749fe2fd57b580c0af500b742f4d273957f45539ea954875a77a8aedbd6e4164bfb0e87e9ee1129159586508083e01183e1fc043841dde5687da1aa9b6c8ae26d7b35dded438ee6a06e7d38bc7fc1c25e6fa1d8050fe323ef9dcde5854e119e6896d571b1631ff34bafa6b673587d82ef3e7f97f3e32c6c2fa72d09ebd01539a4bb91f6612fc84b9c7fa6dbdda0d373731e62eef62494932614710624f9cbcf0f9f7748b9a6d76f90075c4e480b9c82ce518e88670a7727c31e275341c3f59a9e75d08ef856aab21ea0089c98c87b4e5482260e4fe6272287ac439ab9da1022be2ed93d24a76b941f88aaf8373e9570cce6e15f32e757c148d8239a65fc1dcd273daf105179c7331b7b025a6b81059c6c18ee80460f87c00752bc36367a44ed7cfde5c1bb11e229a1b64b3db9a650a616ff547d84dd898e701cb0ff6f5f556d3f74239f59c9b7ddec9f826a9346c962ddad389bfcae6190e423cd2d9901ce96c0a6660232d18a835059bb3aceb2462e77acd422c26d5e28ed1d91c3784a7b684cab4990f7892bcecfeeaa36502796a9db18cc755a55e266b8a33c333963becb604d15287fd804e518adbe777be17fcf39a3e798fca0ea90de735715fdc3f98c09a4f2ac594e887405977a017fca097bfec08c8a9d4b0744a3a791202e9b09bca7a62d0ad92d775b7d2f7bd8b6b85f0d275bfad5f94109eaed54528371e9f36c76dd7acd29a21ffd49b3f6442f5f697aaac6fa768d53059a3784242ee907a6fca065ad6a6eac1878d3cb645f58c3bfd0601996efdb464a4fcda5339b519efbd0d5e007f779b6ee066e5a306cf49ccf4def3dbc57bc94c7468d46182ed23c538236e3c802b5322145f9f7d2f2d7dcf48d0de7d470f4e3f5e3009353eac1fab7fddab72e08b492a1cdd970d740b07e648af74eb6143a97345435fc81c7b1264a2ae6ac5db5ff9fa000b1ff02091be5fa0b5fbf144ffc8627db072445fad7a071d331d46d59de7339c07af0a0019ca5c03dbb83b1f09724afc732344cc433568e3864c6ea3ac3250a69e417dfd0c0209de0e423caa8ba5fe350c76aec4cc241786e56cdaeaa26ec68e6d734b16d13bed296c5fe08446e38876d5447d8cd3ede40332fb1185b485bbfc1f2137965f3d1b47b9aec8d4cf925736fa22e04c4732ea9987004a488084c3680046fdc3043f3ec38c687a2ce7b0cda77e4a28b5ef14c936242620700a3b70b2c447f37a61161679cbdcace0d6763c2a0bf1a433a7d67c98c65d44ef12e8071b17bcef04595fece1811cdd34833dd9fdb72dc5757367e05fd09e38487fea9c0f6a74fe0f0728881e1114c4befdf8a1feff4a01483a2ff0ec29d638ef41931c712983eaf04ec7016741c1f910af1994653712a9aaa10e2a80c6566bed43994a70ea85ea29aec26a9b21f190ec4033d7b5b17cb8b6cab9294b08b46b07da6efcc5d58275f058578bc0738135a2cf8b8ef1b4e036d0c654e4dc777febacc633b72582daa213550a42b3ddcf35f9c794037f813eb0e2413d2d7eb64e3e807fa9b816d99388fd8ac75dd21462e1290193f6617ba5612fb8fcc4311995223b806163a3412f995d209b6f72bc06ce6192d0a36c9a4b88ae7d7b70665baeddfff6979d1eab4bfd57ecf4870fe6b71d51976a998a43baeb6e0f75fabe1799bcf10ebf00fb95a1c0434e8224b0fe90c028ff78fe7aa9515a6fc1d6331ecddc475cfb0bcd15461d888a6485a8113a0ff980bec72c89b73eab529f6f68a24344c45c6fbd4b769e21a07ee9d1e6a121174c5e1ed04756368d6fe76b0a7de5f5beed01bd93b5a09db288e4cdfe560dc587bd0b19a11048e6f6735f38b9239e18defe3377a3a735c58d4266990f407e1862e0937adfd349c4e4cc1305da7bca07d03025fed28e0ba2667e01d3d83c005e90e0eb8b9f4c64d117899fc6308c6a37c80597ee3185c3a9b0b437baa3e8201c098dc85f84c636d84942e34459aef69f9e33c70136c7142f60d8c86548e0b4acf1a826634b26911f7d8bf590925a29003f243b7981873ebb15a03d57a6516bab18a397bca3bfdfcb187bfb011e6a4ec15ac3b595388438bdfe9123210aeb175c3a9f462ab18686172fa0f736f7aee82bf9279202f891576f4ea52c5c63d456a861b05e732950ac7a898c025cd993f3a71712f8d851eb7fa6b8feadf07d63e3e07b8321fbaacf70fc84d804de1fd10aff37d30ad1f372e4039e6d6735cede7a326d3f48d4782985ecc6044ce3fdec5556bbd4828033aa1fd82080c88bc58d0564b42214aed8b3314e0bb876de0456c51c1ead8e938a070a13188310c8dbed46b8a34980f824f258bb33ef62b3a03caa7d90613e951fa22c777eb78b9bbfcba8bc21414db1962d3d68356a8381105258c007200d6d2f0a1138ce17368a389211ade9c63db5a31918156208fbe4fd763dc3d801b87a19c95ca04110a91f9d6783585d22c2807b21b13f0ba77798e55d16afee79c9a38e57f841ff99191991c55714411af05bb1ebba6ac581086dcc03a7b50569a8999917403326aad561440be561bfd4d0b8be07bb46389a64dd32b6dd84e89b61dc3a800bb02d0a083f401e7506184b280aadfb91f30f2f31c711acabd27b3fd0d6840f5dfe7a0a12fc15bc5102f671d8140d673103161be9e5e92f2f192076e9511591eab530ded08bb5734a20f80460f8bcc007433ccf988fa967f0e79e5814dbfb0a3fbcaa4b95a3f5ae1c853829813fd92305907a4abce0e39f84763553de8f0385d1097bec6d440edefabdce8535a0112f4aeceb5ea0f1cf3892b3b2ec5b0ca606c51708395b380cf059345199c26e9c8f444f7f91363a9fffb10420bcaf1d8dcf16f7ea1d0346bc84d5c32b45dae7c23012d4c9b1011be11c5fc728087cfb0e7c8b1f3699de5183c5a11b27b81cc19bfd0997a3efa41d47b268c73b709159a191f9d75322a6f2707850fc4ec5c6334569dd3f7fa197b928702df3ce75757a7201ac2c6d27b6fca03ea6d88857d6c1f96360e920f4815d05387dfb759c61f097148503884d32399175c32578a1439917ba50b3cc98d173259210871f6ef3cf5fdffc8dd73b50598ae1a2add37220499980e8c930347f31517f8039f3d35291a4b5fb4fc707bd1e02238060239c6477c9d799b07b0fad0caa43dbf4a05c1d1f0ce924e0038a64c6f6b71defaefa188945aad9d554ad53c1e1b20e2fb56acad9d6f304b2c8025c3ca93c06ce5eecab527587946fd4702c6a486a6bc2b6c20e5fe46abfcfc48f8620a8ec2028fa6193e91fad688d9bbd27ade83fe344f8732b9a785c5669d6108f3588de17adc9e576e6c0334a4614e9115477e3142e82abc5ac2f2f5583a583d007367adf295f4e59d187ff98158de8f9138a04f0154de349e5797a1962937fbdfe3f010893a7964fe32729797a013fbfa22b5f9023c192e1859e32940aebae5ad6cc88ca2980217d03276a82d052b6e19f99119dfff6b7ca62d5d26edad159b11b5ec3fee6677b3d9fb2197f9bfe23572f08b44954ce03b267befd8d1780397022864fdcdd5cd9101ca678adc0d3e4fe4c9fd718e92e908041a8c484870d08236990ead318ae25e4a760badfe1d244b1ef281c3fb04450a9dd96cf5831ab3f3a81a17f511df695c30443cde1b4da0b566f6cc56f4cbc9a568d4a25433ce6a480617c31f37508554ecdc450826ec7d93294f7813560a6b47c4064f07555ab87814151a595d7f62ed77b771725f461e04f25167273d056b952a803c6d08e4a7b1a2631be095f32ca61c66d978edb24b0e50082db1c0ace83174925bf0a709aff0481950fc8b849715fc9369bdb2a38a3c64e7e9015b5c7066723c439c8c792db76f7d11976409cb6d19f4bdc1cea071147d34bec758ab52a63e53ec092f57ff912d7d8b587e16b7bb5fe19a6b413025c936d4ae83b5d93c9f7a8926ef4f195ab5e7239781bf87a31874acfca47197028d209bb212fdbe463a3da2f7a4da23611e5058ba35f6e147be0449386edd985afedd5fe275ccbf002a5f245751e320491e5726e3700bab9d94fb7a5d3ea5e2bbca7a3f3fab8d743df016864020879b80c8eeb8e0c5d15a416cd9fee7aafbd6d3428404fcac04043176a8340c377a0213ed35f548e4fcfc392f0a2a222111949733834d6c9d789b0bb2d6c1cbc4ba074ebc416ef4e23166e77f924c604e512b61837dc253e29c6c157f8ce92e389a03a25a13ed2d37d744cf139fa6c27827675b7d390cd78c40840caff6ee303b3843ace9309a47c082f7009be53f96cfd83dd74e84dc62806347b2d5f542c1d26fa555c6ac2be518cc7910011d1eb47b64b532156072e156b4fb8b761ac2edeafdaea92aa82313cefa235b4ff7e6032f81507a6ef6cbffeca8149d13eb824ed0a2b1bc902d9455a1c1a2b9ef503f5cf13821f0fed09223ebeca05c0d241e8fb350726349568883d378baf73c6e4d81b51a587569b6d63fe0595f9c37f8b7805666f0a96fe57815f439bf3dcdca8eccb933240fd4a2ef19f3badcbe1765f776cff3dd41d015f928aefc9862b50bff52e3957b0327e5ebcb21f2ca2362c41b4284b8b2e454f74d42cad17b90b867412f0025897521a32669a4b1248ef23a568cac8360ebbad56fb78e44a0488b04c90575b0312d5be236f98de1846d55e2280a503d1b7449a994a17bb3e290faee6ea7f0c533f52c7d1fecdca7008eb0a2d1f10c975b561ffc6b29536614d4f0f7cabec05ec0bc3af9437fd9faa3c7e6cff7ed40ed011962bc6e6155ef09e1167675555dd0cc6ba93a9b8f3226fefae79b9e4dc80f2efdcc7f07f82fbd06a3fd6e65481f3d9a3cab978c79da78d1d7ecff396701a7d2815abd061802013583a087dbf8afbc4fc7f81fb205187ba15eaea9c640d0cca7d2050ae71fc82538d51e10cb20bff2a797f0698d73ef89e9c0abd88632e031aede0a7b98f751ee67d58129700ea4d98b7a35078f8a4b3013d18d249c0075c3a409433727b6f7026c16b3be735c6e55b439729c9e5283250a6a879e0f4465d01c90946464b27b25a0a4af8e04e441c94a4104aa303a9e2f5a02580f122bd2bf277968d55d4ff6d97e70cdbcd1b54c896031406995230a31a513c9f34b6bfda1bff1df85fb76cb40ec92766cf1b9a93a442e81a6d615fa931bfb21a1e6125b06d5fae7ac1c0d2e34ec1cf940f8140c438759934e3a983f5490786e6af5058dcf558ecaabca780103564f470204b922a4fe6e5f6f2033a7a96807c62792ce4ac686a65ece54334a4784d850b4db28a1aea60968dbc008719960491ecdd5b9cd975ddd7741daac4c5736dca309e668bf5c6959b3ea06005ae653624bf1668afb0b6e91e272015f6a66fc0970d10293b3c97bb2c9b6a7b7ef7bf60e9178e4c4973e5722b2fc0d42564287ed6f135fd3b63da37827e45a24c352e83ecf10f5b0b3bb9559afbf9012a2328f76b5b3525eb6222ad8a8e006b5f29335c6c14c5bcaa50abf2e004ca3c085cd40e5ce4177b25e4cfcf8ebd5d0c823252c3f5d52596c0d13dacc201bb6504898ff9631ac07a211b72d10481c4d09558a9ead2b133f5e6c9574e43464d8f7639353d892f1ca47a1097889f66c23f0b60a646c71d347fe49e84e047fbfc8fc007b846f073f6614d8538dd8d19a9901c79b05a397279311eb6b68aadc0c4d1eb3101a833f88e2365e2959aabdc126ce5a59fe0ec5a5a122e6979149013942f57c7420681aaed4055be6c0c48a9f1b05749ca5650a7498e6634afb54ced9ca69be146a141ad4454ebab5289c51f70095ac1a4a9ef26a5ba279caa5a9ca4ddd07df6ba49467abb61cc854f20f8271f5c9ae70f57c94f61cb6f67b6c3b122418a871080d1c407e4db2920571bb314d52f08d8e6128cf4d350277359df6557136dcb2e7b3b96bb0be045293fb1a14e17dbaba60ebc9468b63de6cc5f816d48760b82f6ec5d4a2cb3d7d7eb6ca17f86a94f89685de273315b236ffef0e6c4f437321464d75c1039da880524cbb3c27dac2b01868cf2ac6645490f3e6b8db55bfc9f71a8b09ef17cde4acfd8783cddbf4fc3660f4160de4160d43c9a4408c604b0028d858da16d23f1b6a5333cec4f987022349eaa7b97c0d77247692a82900bb6e64e552598f188f482e0c381f9e982e183a4838945203ced7bf3c6e37cc4bf4dffd128b96606cd1920f47fc7bf8e1bc753cbe791ca03291fecee5cac29e5ed0ad7cd0ab5b45b659030b16ce5e9c574f882e1f94f15d22f81a5c714cd3c738dc5d0216118e66322435beaa6ed7b2f6d1d20c5946baaf7ef0ea3ad12bc00133b4e07b03d0984bfb33c1a0749075bee60aa32b0fd45fcf83963f61e07925461803c8c315f6f6cbc1fd5df04c14c8540cc7edc119417b0528aa3087a782ed8a6269868b1ed3057fe8e510a5777ab88ce9bd2473e699794004a9bab24e5fe9f2d5684df86cf7cc4ea7d32ddf81cba123e7966d50f3b5caac7ff2b7b14fe15ecd185cdee8914fc6c14ea80a1e864f34088f238bf73bcfccb255b71772b431c691b107c02307c5ea05adf36d005ee9c86c29589aaeb172e2277ddeca6924ac0887e1a9fc4bc1944420ae83a70563cb281f64956bdbb8619ef7bb589974cc9e70261bbfac6470eb3e754255f2f1374fe19713934df876f49852008125ca343ce5448b4ba7d48ca1228c2d1b4505352e07ab18308909af82cb84dab75c6d053cb8d1c219278353f57b920d43606fbe193958296c08b47aa2e2e3fcc32c07794eecfc6029b9eaceb9e6d69877772f22ae27ac222fde8b52bff096da09328d578cf9229748b0f10ef79dee3a896247aee8d3d51e8bd82718b2441615fc38292a7be85519a1a49b400cacaf0ed838cc0b56151fba414c5bab22d2bf48b07b95cd138d261d899680c6f8f8e106e5fe25c5c7f09732d0fede5942c0f490a3baf9ac0a2c5a39ace75d3bb58f27346df936f290814bd428628c0e25c838b7a1faf6b62a0a77ae57485aa4ccb061f70463f793920209d82b59a33b70b61eb6c4481654ec4e2448207b98bf9cdb2d9db004aa2c8640d464f232c56c4cdb1ae955547c36b5c749a97658d658551866242ff885884df4388fc4925a2f5309f9991935625be1699bfd741a4514273cea9f6de2873fbe27c00c7c1c785ed00b9ed62698feb6f201b0b5c055e1e1b1261e9a3d3bb7bddb5e8aa00995a8a60512e1eee5c1f6bfa6c8aef396659baf67c1ab4ebfce2c3010351591610b8073b70f77e3befac771f7bde0944d5abe28a0df973c79dbf7c883b2edd038126487a388d2bf03a69709773b43c4d68d2a9e1ace0354fb7578057e303dbfaff9f3feefc689fff11788118be2651946111aa122c172a4ce2a54bc44eb12ac64835d43938fc6f2f9663b702fccd7a0b0ca9ce06929b5dfbb2fd76a10eabee688cb3db1e3ab43532dcee9f038f5690e29715843a040b7360585d79dce8851d151ad3e54c3de04cd53870cc0a22f2144f6dc85418e3357b44cb94a5b5b1e92c890b462c1f50a66242b49e0ea42b25d20c0e3eb1b7bf51132eccc2206f29c36197902d53150cd0ad7524dee4c9976bdefe24b018aa12aca768d2c91f63389e4958fa98ba3d05070299df9ef3c3ead2fd15fb863cfd7c4b1f64694308eeee5b29265cbe3cf7fb129dcb21510398089564b4926f41f009c0f0791f92a8703ecd037cf43f49a03eb187b954c5c694f5d178f5ed73dd6ac98de9ea03b097af48d832d2506555a493d6693a0de4f4908638cf6438e43d21c5e0c079c30281846e07fbc2557e3946c05f85b9ca1b73875b49e9a8c086285f329dbba0274b90ed9db6f5eca49586395698ffccec5f1c8c175882edf9e60ae2cc2c228cd78e0d74935b5a6d2b2d61d4453b2347213f4ed92700f48dda575c85145f4b51007111624c0698a6615b197aa16f6ab5c2eebc7632cd86c0bdd881cbf4a5733a2287dd5c1f46943e60ff51f89e7976638b3ab3e095b2e94d444fef123849d64d87b66fc920e1aa3435e3916afed724380a0c04f7fddae5dba6d97798fb1c552796c4ac4f73238c634aca0ba4f7c182ef809d2aa841e4bcefe82bd449ec36c1c36cc094154d0c41b97b1719112c3608289cc426c82229f347cc7fcac91d1a74738a1d2cf8c0cf8298377d37150adcebcb1db12a489d322facec26a76be20d68d9c9691779f46e1929d3079acb4418e605e232bca083db55d2cdad1e64e8514474f6ae44b5a7d9d3ca068bffc80bdc71dc747113a58ed5a38893819fad855f255cb99d3a7d4d1921abed3a3f5afe2c70c375c191b42cd44214a3ca2a74427a4ac14db35b7d27db0767d20e43b38420e0ab94a9f72bb8054507825795214c8f6851902c31f33dcadaeecd4ee4ed4273ed61efa847abf26b20f80460f87c00177a98013169d1cbd8a66e1616fcdd8dcb940f50fb3d082ec1ab91854a9d679900e00438f99a11773f9c39ccec550be148caf473f3a16dc7655da55ee40876f1fa5dc922f28fe08e001a5387d246b10d4d645379085b5952381a29d3250a53f1b10ddfd59788a4286f01f70ff79f3272228ab76a192190dfc1c9225f2adf37b825d08fdd3619f6c841fc01041e7f071ee78b8b12f2857dd84227c9d8fdc5b199dd944f894a45c497ef69361306213fc3bcf80e8094c0a521cd687de7ca087605f14327c1dfaa0181d3b99260e377218f120a85f4d3ef26e2081b85dc48e5ea31e18f6ffa5981ef3b810bab2b136bffa9dc3e66a6c9656d14ff6a6c197129107c30818e6ec920f324e7e23fdb4760d74c60fa12b03ef88eb38385a5faf561a1a0a7baa5f301708fe1f9a3c5cc791deac5ccc6a35a6cedca096b7cddb3d7f6a35089fcad3b42015e4fe2b35a420dcdc1f47448b205cff9f0291e48265d8b3d545510b1d6875fcf8720e7ed20e7f8c2151cad0bdc7c6f182e2e2e9eba0bf69dfc1533aec5e7ec62f4439df1de25c8b2ee706adf55be6c2ddf92022327b6272e597a207c7da6384fe60e4863c162187e3798c7c996dfa6832d4830fa62916ec5df9db8c4aae2e4d5d615cbe633faccacef04c2c8c93ef44d2c9dc204e17339e1741ae640c408b018813feb2382187a7292120491170234cde8cb7efd09f9e4c8e888a810787208803cf5fab83011705b10b83208dc35089442829d8f329f7ae88a38eae7a88ba10c54816f344b51874fa311a57f400f4247974f86f1edaf7f612efd107c3e08365deadcb75135bb2b67104da9661a177e0e04e587e2611d37572fd3a772be2fc41bd42fd94fa8a5075a68742f9edd693a9645208059859e02f08fc4b122749e1b8afd487b7eb4bfcd04fb8441caffdbad42e14e1c1128195dd339990d9e45d3ea29c8fe19ce18a97b894ce78112ca7e2b0a51eab164c4e3aa13831ecbcd1158c93cc00cc621272e0de85b08340202158140544e26f75f40f0488df088dc73cc159fef5fb7bea53751a036ffd0d227277a66f3d8d9443db79215113c87362e8c0d6f2aafb2ca0da7e648776c3f4b7abc81ffce80076c34ac56bcf7dbac78ac2222fd97b9d95318abd0a8c102ea9fceaa701f7fe7fc0136dbeea3aff6623f19233840b2709032f6edc9740fed3ab9fbe01e28295cc470913feabe809a33bbbc489d2db3bde7006c0a0f79465c67c5e39af333a3fddaf8b82df184cca76f15ed8bee287c8044ee045a276de1dc67b1094add476a0113af62f36f0770d81d2e0ed3cf5561a4000a3886fb6995be8376d7c8d5d7ed51ab531880e171a38a92c307b24196d7bb2dbf3c256af8579f120d992dedfa6c8410f82aa410f1004e1a40ead43dd5d9e8bffd94e85fa00fac78d000173f5b272f508a312b3362ad05e0a53d469b09bac031142a35a1d9a05c144a1ad264be25990a3854644cabe23b8cb0cb2b3013ec72efaf29e1e314c6b698dfd12a0e7ea7ad58f8f500aaff4f082fcf077c644f8ccfee5b8f3346cd5f67ee531df4e622a354c28bba80acfd56472c2aa716a080d59aab5a4d539958bdd9bd63e4d5eb6aa1de66b2187205c9b355fc6aa5462204817507e1822f14ffcbedc1a1e0b14732ef12f8da3f9ec5c0ee757f540e176c8d0333283d55b4136ce6bbf1edf739e9ecf3892f927b2c62e6453398a2a7d008dbc1c21bffd27bf18db61d28c5b96827572f3e8aaca57de86d6e03b07b6bb0f211224dd198bffd059fb772289976bed2c56e05b1c9849ff691abe9776dfcd563f46762989e964865d1022a62fc2a7890d67c08c1271476eccadda903dc3e856474fcd537a1be425a2604e1542f5b2a8b96ef44c0bfa1ff7fca23961760eb7b231a6ab12547fc44167d694c3352352199a9ca19bde3dec05566c00dde10e086cc1baa7240ca35148887f4b033560b1e5d88c5bfe757196e3d38178df266e6b7177bebbf5c3f44b4c35048710b219561cb93eabad83b62faa849e40187defe787275a1bc004e3aafb575caa11f4fd6de9b6bd86e2fb67a9d9409227197a11d96f8791269d38055757964ce755456bf585573151967600259b696694083af1ebe19913b1ac5e9ffd8e417ed45f9742abdaf2642b2c58d01cc5e3eb71b9ffec74393fdaf9bfc36a5b336c94fd619f594d82ff2bf7764419c1a41e9bddfdc9ccba2269424ca6b5190f633e5432010b1c8bbf41b9637b66c1babe6a17bd5f762da6a286fa16e079876200f11ae868b8f8a3f93afb614dd1eb9818f4641e331ff46d42f3284ef62ab669c6b3bfd59dd976be05aee211984e55101692bfcb82bd8b91b3060e1216941131d1346eb476e23426e2929000d6dfa16c303f4f5b51185a876bc4d69ff078fb6daf72165f5374dcfd64f634d42a09c3b5036822f4b88b413b6eebd16c6639751cb6e50eb9f977d47ce6119632ee8ec833a41da0e4871ad3a66ef774c9f29a1472d478cc564690b05c3ff9a5a552245ca7d109ac1743e206ee21026f6dbe216dcec6216dc521725793824f9d939244cd9c54ca5c4cd4df8243938b9a4b824cda5a53878c4f84eeab4e7974566f1e41d1ae1bd1de349a8c85f055050395cc7edfe3c40ccdac1a4765801a00d356f294895453ddc75376997dcafaa26e9fe98eecf80e0fa6ca1d057ad83e5c82003e14bd04de4e30c32908eb9f4e461a2276634297b5aaf33f7917af50c71551a1129b867b5912095ab79da451b5bddb040aaebe9a5d88ace872de28d8192d72e9b50ea5f080798d0382953bb1aedce583e467c710b1634e37eb0bac98d458fb7ae3a32c2664170442bd2df1c2f0aaaf78c9017e8fbeccc8430f4541ac6b9cb1f5041c891dd015b2dabda51d65d247a5e006dbb0d9ccd3c08d8e5e7dde7d593d975685fdb0ab7ba919deab0535f5cdb24a230e56ef3f50a42f45748bc414f070bb563eedf1f9f6e742de17cdd33cde37433fede2555acac62b5077748c1a47902307c5ec03db3e5d267bd068abeb6ab74ae968dd1b3eb33c46dcf9d87345999372e4b89b7020654789d24b25d699dcfa7345b2c466ec3751ce21d6422f0abbdf9b8e95d21b20a416bdf416bf1c326333a6a301eeee513fcc2d0cc1051605420147f77a6a38d7d51c1c71b947a7518f3e175551f599728f1d30340c07744bed7c5214dd14041c05b2e1a5bd45f57964f853d4d09250ca96b6df830cfcf6c09b3c686d40fb3751d4e3b779eaf5af66dd088918c1d66d235b6b57a21e4e709e623f5dd7616ff2e54ac34dff3ddd2545da8c643b59ea728c92091e050c1ec2940d251c054ff604f3efce4cbe260570f602f1a40ae6c5f06d4f2de790e20631fdad261554237286aa10d561e18092137970a5f316a19cde3fef69e3690f3e961f4dc6651f02d74c1e76b94ae1537491372de151b5d313f30be6cfde923ef8f3fbc0d8112ec4071bd018269e3491c02aa8ed0b9766f8b44cb105bc9e73d2aa45b770e059c253d0d91d5019cb99a3621824e55ca2ba4124b58071730f15e4f5e184c239be613c013ff64ef0ebc74707a416b6a38782da5a35b1fdd59bb7ae062ffb9e6b714f9386a1dfab678ebc053563fd31525c6f88789e9b646f4330d196f22a9a349d816441ab07dcb36285801b8fa4f7ec22be34b53c30275b467051f38b8dc858d52893b9b22f5631c006d4b40c5a4466a5529036422e06d48d9f585f7f7d7a2b85559a6b048e1b66645946c65817787d27baa885349c57808b475c9e1fe75db660d360d29571ce744514a7cdbbc00ccc5db166ad63a13d49a7442e596c094e365e19265c03c2393c3ebb5091e4def8f772012e90e12117509121edc0e1216d48f8871e6b8d768e18e84baaffe7e383810d1af8f501ffdfb1dc3fb3795b3e8d78fdf9e9efe237c7bc580f30dee7f3e3dfd7bd10c907fabb3e17e7b7a5af4987c4755237c797afadb16fc3b2b0e0407c7fb5b2cea3f0abd3b88f0db8930c20bc9d843a2af639cbdb4d02e7f805528c084557ff4e9e9e318ca77198ee388204afd39ac93890bd31b9ffa34efa1d7a9725ddc83ca7f6d189ee0f5561e23951e355a63434dc9b9bf9d3808645b1bd6caca43dbe3d730146074636a6e77a8f756d6ed573ff32ef695d6be3aceebb4db3b7ff55d6cb02baf9f7d175b13e4d40fdf01eab172fad6f3bffb6ef67737643fb4bf2bf327e7c7dc373cf1b573b067b3419b06b675197cf9434600b139967007d0e69c3c687358ff1ab572d871456cfb03efce3415ab715c5c30e6735c804b36766c2e1278fab49c833cc18c3e782f79230174d47e6c218366f84f386ac09f0030f9030cc05e2c82f20298ef3b0239e5272a0938b5068be611ddb37be208f35135700814c7422e23c26800640b7c2b9a85a6759ebab6e2f318845d0e5223992b398ee34ef877ecc86d625a8e543247115f7dd550602bfdc45efcd66bdbaace67aa7765de32090033d841f0e19e69f5de106f5e60328e79e0f5b3bbae3897af95279270dcbc8cf8cc97c33d633f942546ee392d5c0220dbf608ae0cf902f11c32b2655d54fd5dffcf1751485e1822b430dd65b3cd9a708640afec4055bf3adb351deb6c7717b53d11df3f4694ebc7bdedde98d4ddef2fa551abddb88e3f1642cbd2fa7c830704ffc4a1466dbbbee6537527eec4f4ea0fb0015b35d0d8546034f102bcf68fd71766df4f73d6ab8c859a61cb12ae09140e970be139110477d3e56dae02c670a32981981d9e15ca0f42999092e6f4d34b5063d657ddd2433b97f9289823be789f717e318c82c0fd5f7a9f7d00c1ff47799f816958ff82f7591908fddfb5ef2f789fd580940fea7d26c95227f5d1f90e81d8de47e3275b9a634592686e150cc67d3ccc12142ff56c8ce96f7f4e5576885bc076cf334b21cc1119c8b970dde19afb79a47326b96a8587e2601ab0d3e1e7bccfb0a6f34e12efaf0b7e524187f225518294ffb3de673ac7cf99e3bdcfa0ebc7de69a317abd6ddd0917bbadcc07a4ddeec0c1d42c27d8f97cdbf25f3015e338c3abb9c8a7b0c87407ae4b9e6f312167aab99834f39da9eae3fd7177f5a05dc9843b4bda7b412581d512b883be5b25ad3be4cdb6a816b795ec5df0b25c228e8abd246ec57286d0e9422de701c84276fde1a78afb22bad593a2ca95a6bc692e13546c63614e37106049f000c9f17f07fa3fce17ef16e18672fdea6bb145b21f992a46de5a16d587767b3bbee988e09804825f029435777ed1d5127aae04ee7468c0fdd27ab446f19297437a75ad3c3c1afed15ff15ed1db7a35077c4a45530a135b6812bdfec3e288fab7dc69193f0de16ae0689be002c222dc1f55c05aacf67b39e8fbfbff712f75da370927615ca4d7aa5a8e0aa73e6e60464597c40f646dd7e3fae574a5fd8132afbfcf625c10c7703ce2140a95f24b5f3bd9c3a0b200710f0b43efd5442222bc3b7d04e399b12b2485bc4d0ecbff43903ff23ab9adf918b87cfc2df1c6949c68511991790525063a333a265d3a2f6d1bbe0ea906bf1d97c1d55f5ca0331528ce537c16b2100b796cb9dee034b22eb0c0268a1e9fbce5eeee597d17e0eb18ced28fd5106fbd647c4a2f9b1d4bff6837b51f967a3b43f9fc7db2ca65e3fe87b296f1eabddec392929b0741ab18bbe500a3e00c3e333ad6e6d3f7cc0169c67ac9007db93bab094b767e2c887caea18b0adb203006354921a696281382e5daa01e2cbf873be623e95ca112db8960bddc36b3ae77bbff8a360934afc829964a1d4d5592559ef3ee38a51b2fbac2abfb7f4caf6b4825712138ac87dfd8ce08915b0990486cffb10405de117223d2cf219b28dc6455ed4116827ecbeb3d385c1b2c9afe744550aa058b921675f6eef6f23f43da3f90cdd22e920fc435e47f8d875854fbafaa9ad461028cb0e94c997aaed48b220a2c6814120915810644cef48a24848d7cbc8422f0c1c55efe25a138f5e9b7f4bbbd05ee3124ca5cdcee398db71e37b1cb73b0e171542e8da8477b8415d0961be60af352f413771752d4215820a211c190fb07373ce5cafaed8097caf4c71edb6599f28040542e0e7be428c1f3732b3e175e0c2e269876a2db04574427ff20195f507fe23237794d752e4ea7257efe42c9ace57d91acfb1ad5fbc9902ddbcb60a088e06d007cb37db7b4c2c6caa97042aa137c4ddbc6fec9392a0eef1f889098ef857fb0f837fc2f4e00394b2cd7374f010df0b85d214eb142d7d0a8ff7d13f7f1315d72e8b76ae58d64200c0a4ce446814c97a366029dba18a7947bb31af2ab74539065142fda1e3e8799794a39b0aa1233e1376f3cff2193c8e91c20da794cd366b8947cea9dd33b20ecaa7c6c3a414e5a9e0038c600f514a2e38f63ac05b613e7cd3efb9067d045b41b3e956bb4d3c20d0c4450c30d3cbb05251c058935315518a55b7d4f90f8bbd1fa065100e1155915bf47e8087c0e7efc0bf84f3c3efa3f6c3cabc0863b49c294bced0c2cde262ce0952e8f1dc49e4a30e82ca1b21da24f595c04b2e8e3e6b3dbd83c14415d0c31f98286101927eaaf61b297fe2f4e033d0c58e6f3f8feb8ed3ab870713d540444d50510fc49801f41d2c900138fdbd5ca4fe756990f2a98514b0cf7c6abb3c2660d9b666ffb1f2289cb4198f702a7c9d0df67dd2a06c107c82585fe4d2041426c7a827cd7517912c44544a3b0f4170bec3ff0b0620dfe1cfceb43d1e197a1227e35dbaaf93d897308ce2f14b1f11e0030a5f087cbc407dfb55dc6eec064ebac1d4427659e3a7ca91d11d66d8a5fe1eff40809ac8872b53489dfeaaf6a7e59164b16523da98715326ee8101778b46f257622a5fec24cd7eb393bcf2a376926e4abaa49b996d2c23d4fd2384ca44ac3bf9cd6044ff57ed24ff027d60c583da49fe6c9d7c404eb7392135121f83bc606e622336a3070b26baa5b9e052655bfa4de8540dc52c8036fbda4d622d5ae0c299d1c8b0a19633f39c67e4e22749d00d8b1d62946603d68ef68d2325906fbbc29fdd376a0cb20b55f1e6b562aed80e042abfbb2550ee547b1a9df0cfdba8798172e1ba79d4a0730fc208e3bccd9e594bbea45a789dfed2065e10e56690edfa462f4095b05e4465121445bd17797d62ccd4ed1aaaa3787a1286717d1a3dd2c7488c775f0f0f92ff0ca7c2a4201473b889f444ddddc6f7186d6924706cac2cf63888dd6725cae00b241f3a0304b7506ec6545f6a9c273acfcc5b43207f87ca38d43a0765313b0a728fdda873120269d97eeb8b547bb4e4b00aa4619217aca3ee60e6244b4b245cd7f4ca9c6eb6decbf12e360b58d62d38de04628f5973c087b405e7e499481589605909e18128684929ab9fe2f6c00bf0745cc6b14eb14345ae77c452f3530bb49b923547617d77b902239c49097dd40aa04623080dce8b474772173e4028810a2dbab4db3da133dc5b32e941f07539f08040b177a018beabd4bfbf92a992497ee94a79e7797ece377468eca4ecc90fd3a8bd8b9f8e33be2a86278440210ce771767a611867f14dcda533e3d4b865af0e4d380f661f7b528742cea39dc7394ef83c6e52134021e8c5e7718e93498f138191cc46350ee78b51a08f6c70e0b5085e7fe911e49b55089def0cc3505bd9425b4da6d5a3b8e9e6667c2cf314852b0aacf7580201f103ed47db28e3180b9f6a7ddd3be8228a9026d2b0e337647cd3ea862d58b783bf8dc287a217f1bf16858f2eeb8cfcb0bd9621328fedad3802aff31164e74f55e1de781fab726aba4cd40148f5ffcf87a5f8d13eff23f002ea08e79d973fcf0da7af5505fb4923a6934fb8a3140985d61646f42e733b466d0304f6d66aad5451566bda552db3c3076506ba22fb4be614d9bb0d577518a868c2beac538c2f1b3de57398c0d91d09120294b95a3a5c9bad22570c5873ec13efe2f47ff1f5f314043da75103a5903d352ee31f61fd3ed3a3f958f15e4324e77ea2c5b187e32d7b3f6b671bcc0794bd0aa894f5edbf4ba555dab8a7d6b4534ab8bb4042b8998830b2e46d7735b40130b9f2b044a2196594b1943cc7af3b3be9a3701db22e515d8069517414052be7e6d12689fac5644d0c769cfef0984df2c8cf65314ffd56e1bd62c301c62d8118c41323015f64d37a2c3360d8ca0bbc7b84ca14a9eee6c40ad9d2a2cf552f7d563bee9e6c427a50edd7469de73b1f07908ebde98f8f0da0224b1f86246bb4ecc1b5733d7cca81e09bcc18af7eaff853c1976b1dc4d3af7508b28d71310685d57ffc5a077e8a434644ca0aa5322db3abd4d2c91f87d1b90804ff44e19e208b77050de176c989e9f7aba7474bb9ef81944f0046131f20c8e0e2569f3c12477f49f9da07ca9b920c258ba5ee3a38f9f6aeeb1ee82e360e80c0ae890c477bb5bd2179407e6cef9b8c575e027e3a3ad0a63a8218c54eaebb32475773085fafe6da66e65b13357795e1b993e79283bb1f2b3058b4076171ef46914120debcc0fbe7d94af6f39b4dabf5d40ffdcbfd560478ef96e06de70edabfcde7acb9b8f218e0781103b0458796a438ed1110d98d5af1ebb6a4eaa44ec747e814e391873e55ffaabc30fc6798f2c9aebdf72fb731c6be8d69496eded514f334da832600f3c0b3b2cb75233e7aaf0db8f184868ce6e5f2f228d94e1efd64deab616a557a1cd9302497edb794bb7125d8df86ce4da7fc5b42e7be9afdd072d15b9a0f48d7b23b2ba6bb6cb9eee2513eb8dbd3f5e44ca1ae4382f3801c8f59b4b0992b39c0b328a10793a4a8ad9ab147666f7d3e55ee1186ef7a4dd5c208817a4dc5bcc5170225d98112fab2f27d799a930902cbdde4c818b670ae6d09676b1acca35816e8f58ff22eceb936236320be1345eb1d7a3183f0ea48e3c1eb549927b16677d59817e0e34837bd64e313984624a979cf49a074d847a46b553f5646364468a9bbd7bf133d105874486ec6233c0741e8e16c3c8eed1d27e9a0d1f4a8491c271d7142a110cea378e810c8bff21c27f7f002d3894458280cf7554d186e654df3b369e2db301ddebeb059f3b2b3fa4a72d5fa5d40dc365058d9de5ec75abf8fe173c36b78f807cb8f2b1e1a67ceb8f04ae6d6d1cc412059db19be83d2473d13ac2efa67c3ad61e6153111f598254a9b6ebca17b53fa2205f371fe49234c4c41f4ca22d8a19e1c9889d7a65459ed5a0198ef5dbe2b368afeccf485cddbab29ecd67054aff1afcb750067b3831a15fbfd2882ca43e8de3169a7ede0e54fe55ae4f56478f55fc87c36d4f4db93faf09dc3bf3fa9efb749a7f0cec504373c66e0698f0aeae867827cac639ed47f5dab603d4005e439e87dcc59a80e095b64203bf9cd3d241ebadb3ef7fac8e6d4df6d3b6425e1f46e0df349be4ffbe04144a125e9704d2f5b91537bfb4ac089f890a17496b853628922ca28eed2879f126b0f1a7473c1f2022f306056923153636656d8ce2e9b88d7fee92a11565316d49efe45ca1ea0cdfbb21fb04397306eda5fb8a86bec3dbee94177b9597b6ad9db764328c5c5d6d3af2209fd2b5f32fa67dc56794b754687143d6143874621e622f258cfb7c8fab86b3f32d2bcc51dcfddb2b30a5cfb44b338e9dcde4012ec609dc4a0ee9fb2fd840809cd721661f010eb0a0a05ed97a871eabf458d6b383e6adcb96e235b12823f279e833c6dfe63e239a589abe7cafa657ee227baee6993a23b9b93c11ea7623fda613c3d9de1ff1f241b04ff87fbfc0fc007e85e0fc3201196fe5c7ebd7d03c3b7274216553dc4682d4c8683073ba12fd29b1620c25a1df0868b5a8c8a2dc88fc776bb23ff187b079f642033d52676614cbfbe1982dabe83dae2874d76f56815a679ee9c60f78efa67ecdebf13ee7ed8ee9da5fe35584468b088cf20f47da7b936a8a3789bcf4b6c8ccc58c07af1d39b5bcc3c1a34a7a3a3fca4dd3b32989106481492bfdbee1d6cc51dd9bda3df8d5a39ff8c5294bc9a772864ddcac95a4ab2844a519f2598b5241f819ce3e557bbf7971b9433913157764706af2a8beb0b8cd319489b9e6b64b4307913bccbe9b938f717ecde21f9dbb9dec0fd84b39710ed64e5b3b87b91b61b0a47e52af788f9ae52aa526d99bc26e531c6043aeff32b0d6ee1a7bedc33c1d5d2bd559bfb60872645833060979f4106569438085c7845d9607d36a060ff9942df356c32712c090dcf029301758cc757e34487d25581bdbafb3895651f3a8305eeb74b1670479d1d5b13edbec44bda2e868f0134bdd106e09b3d782a29e2d2fc171ca9d37b1eb1843cc787de9cb851f9923bb6e5a2546aa2f7bfe1079a87e8b683789bba04d16907f13ad40f2b2fea1bb374d1effff7bb59fa77269fffe64838df67f7867c6f92eefd6ff689f0db7fbfcd72bc59faefc0f087ef93ccd2bf609f66964e0dc1f9639ca82f8aeedfcbd841b0d84e3cdea2f407cdd2e7d75739655f8a56df7f53fc4160dbf279889d4d1ca86137480612966d6d18b107cfe0c47932a541a677ec4abe26112534fd913f63f90de9c8a8eafd54f3cfb5fc66a907a30084f96e0f1c2b0bfe0f587e7fb7e7ffd80e57b593b2b593f87f6ef97de925c4fe2f5a7e1fb782bea490b0fc172dbf4117f25f58e9470d00859fb5fb0695c8f980847013f8ad42d23b56e902a2ebae728274412264e1def9b309f050219120c52c40be626498286d59a87545caf2a618a72a2272d375f9dce236422da1f383a9ec185fec21a047f61068c503c7db43a0bced3ff880effadfb18700f34604bb6638191f692344340fc4cb0457f2bbd7c9fe3f680f01e24d708a3d0432d9c1ff8fbdb78eab6a5d1e87f7a6bb1ba40405e9dc1b1024a5a4a453ba3b0569101409e986058834228874a89420a1a08494a0221d922af27e84e37d8fe70aeb7ad07bcef9feeefca11fd6b3679e59cf7a62669e0959102dedab3f84d4350f1ce82cb5ff509bd5bef7a029bfc8234452c536257b14b03871a2c2e867e1899ba7b9dc44aea278b785f895b44d1c5d4ce20ff83ff0db5f810f0a70a070a572fd6a15e13d6168318c893c00e28e84658e79873baa1491bc7afc52ba0d80d03aaf5c1cf21cdda950ca2e56b7f6bcd725b812c59ba8f5fe38ab1b16390faabf1a430c7fca6d74feba6d04ca03c7bb91729fd3aeae8e1b5d54e178cf4b332f78933d2b20d8d803049f080c1f06b47d2ce65363ea515e9c9b48365171c6c5edb6557b4bd1db8e7a292fac775799101095af10bf5ee775e5b47955fff01dfff94048709cd75e55a4cae9da04b4e2cf2a10843b3b08c5fefb6f8b80131ff73de7b150ea88bcebf8fe901a04d15af3861410ae0f5f258a13f896ef8e565d4df98599562165ed2ca891b657fb5d98115dfacad1de9c96224fa4bb6b77b57b5a7746196c95820528fc90a20306ea46a318e4de1068faa7f113296f650516a97cf20ffdf16fc37834dcbafb33f9fb0ea01899383bb8b8fc697c5c6b373b47336776b3cb269646f61666fff6833eeccf8be3258dcbd7b9e74fd60e37bcd4db263ab515e8997bd656c8090ee8c5b5eb87b5169c67228b60371ce461dd286b79e5fdc83ea2b98456ebf9a50fa50027c76baedd88d712179134284c55461f9f64074862297604fa893debabf247bcbeae50a39fb1427ba202e96ba7f4c6e2c2ad6e07ea2920aecb95f610113b16757fb4ea4062f96403824f04860f0386a7b1a98658ee6f212ff62c3eb52021357b9bd4b2cdebf3d006be18481cecab087041f50c5f1277c56cc0219e12bc1773d258885f89f5934a5929b128907a25964010e27610a203defce64fe0fe77f327e00e93ea5b3e179b9aeb7f1a87520cee7e612ae2e85ce9490947af81c47e4e90eeff9f3758fef098ff01e0c02e6e46fd0ba84154dcdc20fff4cd8ef57b33e570d61a44ea1ba7270a64eb23e6009a8c0aaa11a9de53d2e102d7463ab3f19ddd9f9fd9c47adc822f13b0ac5dee6cffaf02ce467f8b02ce6035968e59c3e96715704efcbf50c01904c0cbc7073b205bdd38ead617e1d329a77bbf86bb7d80df1f71d43bb4151a5c586d6d079aaaebd8059cf71a7acf51050d0b93dfaaeaaf4b29d46e177d72a8d70418c080f1049b9ad01826bf0a5e6eccc4394e844b917c02b6d519978b5caa4dcfefc2de02e63988b948ecf9ef158d43e6de77e257d074649258c6b22d8f2a3ee92218e0a6f8d78a36fe5bac68b02a62c7ac52f6b35674d27f71458329507f5ac1225bb2805e2112a2f87eeba9b9e4590fbd8888738747803552ebf92cc61e116602759b78e178446156817a3fed813fdab37f8f9f5763edb773783b1a51abbfe3d3c3f933cac9ce908d391c1ff25356747df6f59147a72a1565153295289e0a870dbfd63909867418c0013a0b929eeb8d619704d2f88591b88b8cebf1303ba596622f6eb423a65f3a0dab016463fafaf92910260cd2cf104666e34112053fe63ba67fb8195f99a99a8333d405813edb81f6e21ff8fcb1bffcae737f0863c823d182aaeff8f62fb1df87a5505d7d1d1a95df5d912c6953f93895158467909bf09febdbff27f803230feadb7fdc3e6180035638b7b697c42410e16d4e90281c2c64e4cf1028eaca1daede41934ed954005c78a4dab8279ccf26e55919ecc3bebab2c744a782a75cbace05bf654a70f9523504a17807a100fd20e966585edca376550445b1215e739726adba284b8ba74b105cff1a04496b77826f26ecf77ef7a746e95f003a5cff7000bd8695c4d6e2f8261e99d44e62305b8e10d69e604ad508cd978c97309001ebe4180c7ee3d9ef7ef57c83c1cc65b86dddc6a618b194fec3061eb05c08a09dc3012419f101740eb7934fcc3d6ff6b517de651473e5a8aa69b641968c86719dc227024e87c4a7e172dc7d82a1b64b194b30694cf9aad64e6399c44886485cff3995cfee81373cdedfd51bfe951cc71616896edb7d3d029b5d7762efe5f7ad59472123af79e21dd93e370a9201e47fdaeb8f8ef91f010eac95c3241f48cdb944c6c0d7438af899515157b5dbece0b72391d1673969b0730105e1ec02111a23bfc95e3481e4b94d6581b295ad76175f0749ea16246cf250eb7ddf54f203dfd4970387f9a64ed5dd05c9c00802d4265d306081fd7eb1cd1b8917db7ece62563b94988a4adc5e0ef29765c2df78af56d55d7700f4f9a5dc9fa24a0c06896f72148fb1aa3c6c343d59ff022348b5c4dac2886b23f65f82b9c9df423007cb7b7fccbcfa3f4b304ffebfa06a63781a1586e15b1ea68b0aa86b4a2bfb5de53adc607632c0c765eac83b57a961d3ea3fcbde7f00c81cf49e879bc4212743d61c8e4cda0ef92982f9fbb0351c8b94f63b5c4a0ed41a19a5f6aac2fd4726fa390a6000e75a6a69ee7c7266ebb9425657e47b142110e6c730cba9a2b7bdd343bd86d427018c66ea886146d20aad13dc544f1a9fbcd76ed4dcc97f5038147d33f0d6b5cebb6f2010db6d6be8d7c003049811e20652f25c598aa6dab5754e1a35137feb6be89a590c8b1dafd2fc6180668e74002a859fab532e2379ff234ac26d847c243548f78adfe3c5228d526a3400499b8a0627f45ddcee5e53f91cbca5bd2071fba3fa5e412347ab9b8cb77e27ef5f9ca71de582bc8a1fb248c3ce53f6f1b31aadb9f31e8b067f76f0ff3bf0f7cfd3de46b6b31c6160187deae6d2200adacd7bdcd62e3a7e4fb8b3a8b0ea6ed848aa815f261f0d62780e439fdfbf2608823d9e85cef75cb3121cd972722e4d2a49a92528a589322bd0593a435c5876b94cad743af49d90113aa06f9b874b0cebf67448d22335d9dd05cfd38ee65c4b2bfafaba9f97fbc6798abaedced4b8be9575dd886004cfbecfcd588639004df8481c47fd2dd2dc0b6e37e2c3dc4a1fee098b27cad389ee266a6f49316e701dc444418f8e8982aaa105c9912a4efe784cd48ceabc79cf2c6b6ced3abb4cb01a6d5ea557209895f8f0f25b17274ca445af1f5a0d12aac296e5efbbf411843e11184f30a07991c22ed75dc7edae7166cc5e0911fa07bb971c4b13c99d55095d78498e8e26c0e5a8a292f14a51938fcdda54e3f89bb9d9352e9df22905c8a3e9ea3e5194cb025fafd78c7fc6f51aa1b4e0342b9d4ffb5913a4dd41dc68f7cf0bf8b192320bb6fd7b7e369bfca960093888c0f061c0ca20065b9ec5fc0c037174d8f0bb07025d8f676b19954b27abd3d0d8c33b336a003a95990a08f6f5bde79b08814caaf7d9589e13ba49e25f6bbd7eed247cdd305cf2dbf48cee3439b6e75406fbdb06effb4edfe3d340171fdc0c45c9eb7892917fde1f06e8cad8b768f3267cbe778d4ce4f374933cbd4e94ed89b84fbe8957cad046cc78a080358f285b5a13dcf35495738c01b7b883f16a9c36db64bbe9786da86ecfdb288e6f7662a39b71218a132b71b7122f4c6d9a150eb347202f6a5feffa853bf1b99c33269fc93f24bf87eab015c2f9891a6d6e9e06a1ff17c3df7e272ef4b9244c24bf5ca21fc1dcf5f8fd226d5bdccea0343bd4b0eb0cfd38e2ed7aa5c6e3d0ffb213d35e3b3922bd24d85dce3a661649814c9bc4f6e0c5bc7c8ec5a31e0786fe018c47981c4ffb6da29fbd4dee9c18d3e5e723b0a29b9b15b1751ac4c3a84070551d66a502e9000e04f7af726027e3784d69b43e78a7142318516f6cf670fc1cbc6750b9497ecf300b501c4066beae23fb60a282bdd1a60e251b9f74b045dfb0b33ccc689e31345457040275de813a1c14a942a1f08fc3c80cbc809ca7a4e9a56a1d8665c11594ef3cb11e62c77963b5cbbd068a54cab979c4a0a393c978371dda0a6535bd4d9072b71fe49dbef15179d8db9f76bb6b83bee723ab2f92c61bac20b512aa1f69ff1300165f008103d27679365c4d9bfa8c74235abb25629a7e414d133b61c44deb4be351d41c5cd701ebddf1e461eb193a7a8ae8312742b913a36d06e8b39553cc4ade986e7ce72b8621484a3b48178270294cf7776a7597e7876985af7fb95648fa4a4622eedd980906de52615ce24d3fdf6039c9ab6242d94d24cab6e1b01bbc2d730a60ed20fc816900df14013e422b4cf9c76885c8be7fd6bc0aae1562dc1e7abe75a49705d1ba0d5810cc71001a7972f5083b1946fe9525d55f7f01db584a8912978e287c9ba9564467cde2d18ca8ac3c18d2efe05006d1f17709af71c57d23ee0d9094bf7db41bb7594d327266a8d96d89dbd9f89ba3f747eabdd2577abc0da2ecfbc6530c0e54ac388e647f767f80857e4d3e1e783aef83457d2fc655023695a8c8559b9fec062865c7219645579fb55ff3ba6c799d37de83410b8b12c2bbf8f8731ed567e44fe70e8413a7df8413efffb670127c2553859da398d9e2ba7c18d3700e32bda723588dd5bf18feeec28955d849adb911c14b2d431816154c4f1e786ff962ca5567d5daae67a9e1b9779e28b03c0efd2fc289e70e914587fb732499e1cf752961e2e5e8a5dda8b16fd7d556e0db0e8f510632a8c4b19353bdc553853f2e0709265cd0b8f86c0376ab7204fb03559e3dc36b982fb89af826ff3cd34c06d750c26d1dfb9da470d74fb6ba1f8966aa4ab38cd31e8b32273403a7ace488c4d294ea824a2cdb94e1f0fbcae867cbf09d76fb142b6542f3bad3d2ff653d35fb5b584f3b94b2c467b9adbc45e880780759dd9049ce707985c5c9b3c981da92cfd6ddce82b583f0f7b3aca7a9ff9873f2cf8380ba863681945dd5111eb7af36b771378fa201adbf86f5533d8aff00b49fc9168fa03f455e5eb60242e2f8e7249c65fd0527dedd96915398174856ed36941ff6fd6909190e7857e22c5624b2da479bf7297a1024afa396073c9659af8c7665bcd0e668e9810c70989f7d27da2459816cf2ee8c3edb4eedba852ffae656c54b7177fa7ba8b9e25bff5ad1e67f8b15fda189f5036d722c9dbc197650e5dc7201fdab45773cc6040f5c89373cc86caf4cc1da41f8fb592b3aed7f2b1a0281d08dba5aa88a3d3e8286783aa5fbf62fe16e1f90560bd007bc0e6da67b955f723942e8681ac75fd1f161c3773e5720245ede33d3adae722e44ea343bd438090630e053cd331a76bc9ba2a97b6ec6c332509d4e5b62e4e43c2ab66cf3216891d85922c02dc321d82c1e76279691ecfe25df5503998c33f906934b9e243ebe77da29b3cc0eb2901afed92ca4feca90c1181f8c5edbcb5eb67e542511f09e127d10a6ffab5948ff047f60e4413d958edb271cb05c603ccde26e70436f53549f07776acb8fa3104b6494bcfdf104f946e216a506a0251147717b339a64b6d4b0b7d86dfb235ff07936e7a9a40e3bd4332ed12ffa0abe9a924dfe196501b84e20db9d2e17beb8221fd7f32c7120b3ffe4de658adeb18eba5b0a827c85ad290087efd28747ca5bf216a2f9dc88bacf1caa923767d6d20c83463355b56202ae681fe84f0807fa53a84a5c77d2b894cd49e1c04849f2792a067125802d9428143d32ccdef997e84fb7daa98685a32d22a557b25f9d9e22b2d41029021b95bf188ea13ffd368cbf875f61dce5664ef1f2ed8ebc9c81c5f139d7bf669da519f30e7154498ec8597a07cb33dab6c7a1ff457f0a6b7c8f703f588a11f55aa8cfe3a79f6b3d9f525b3719bca04109f454e198d6c373f7f02fd7961e532a3c713b9ce0de1ce7c615c9c267865e2b2455e1f4379f4a818a61704086c9349dee34c070a186d341cd7409f5169482268dee755fbd647e5548807d38009d44e80d25dbe2bc87c7bf8596bbbe53892e11ad4fc4de087ff6fe839acee78c7f495b167f0b69ab7ff96d9a5bc38b2647dd1aa9fe2c5fb18fcd4f90395996bc4f3309919886378681b583f0f7b3a4adf4ff495bfff33ef90d88ce2ece73df516aedadf0741b22c33aed3dae809406867418c0817c4cced5f270e21cf3332f59c2b9dc3f842013e26d7e140edbb60ce812aa26a3047835b021e6b8e22677a7bbc93f65f3e45fe529e7d33bd16ada25b1d1d9efc3aaf6af156df9b758d172a7169ebc802c6f08235ceb943a830f2ff78e9678ba12163b8c8dd448412fd909d60ec2dfcf5ad119ffc5150d36a58ee3340cd6358efa72d3cc51bf60d114af3d9a863a5811bce30146eb91e73a8bb1fefad1048ebfa275684613735bc2a39b78c4b1951a9e5ed6bccb1509867418c000cdda114a8f6e0bf77c7ec1bb5a0a995e3c05cd12679c4a0d9d8b7436d95348ae019c3ef9e7c884177d57953b70101fcb56d2873abfa811111c48dbd4796218646c702079daff55967b5ba57c8ef2992c3c71262a18717b990a570e1b4806b7bf1afefe96fbca4b5c39e984f402967a9ed6a70daba970e3c9acb122ea249d0202ac0957d08f1b1d29c6be42a48baea9c094b3c52dbb141e1e889728b3c733f3ce40d7bb77e8514ad034c9e5ba4a82b2d69286e8eee76f3078960ad80c4e663e7737b573dcb822a12a2d0566b98703845eef5b958d36e771f8ceb6055e90996c21a3131c49988795d9c5301ac6561b01674d6ff33a94652ad213990e5ca982893ed7d3e57b8fdd556797fc9258dfe54d17047a7107aa84fe9b8357f2771dbc42697407aed823a7feb87f972f7f4a2e2aa642c767b52a0f61dc06b4d07455b0773a5c92a1e6be7739f18835438d85cdc24906421e4204c6130cd04b11ad0a95607da74ff4ea8347dfc78dabfc78860f96d86aaad5a32cb0b950af037266c1f0b17096dec8ad7982f2916445468624b39066197e81b4bb3a92ac3607a54130f6fd9dfa527f55e93a64755f00067c2ed0dfeedd89742e709e88b9bfcb8438c033756fd7bb38fdd21db6891755d9f180738f286a8b7137b387b052be23d3c51977f1bc498d4df451819910b727c6450fbe1a104c7f8201c18ec610bff2de0499e1d06deee19c20aba0627391824f0bf6f71ed76c2d44c42b80d468418080e1c38153f43776d361fa84c218eb0f2af0214451d32ed9a48199f4ce21ae01819f87c501a91b1df6e32b3c241cb45617f3d4a1bb2fba60e119caddd9fedee48e2a4a64195f4ba148fd0c830999d4ed7eb58e8dcfad8457cfc0bbcf351662cb639dae8c650f8f27d844a49b04cbb34504860f07425dbcacc222c3879bbd068376a333a49a155cab8b05ceca42bdedbc0b9584df008c2e92dcd4fcb99751aeba4619bfce85c7dfe56be97b7fe3eac7d78a30d2f7b6ef20a87776508b837029acf65fd85b99f110411455f2970ba2f451f960c55f8e595c0644e840f9c621fd084134f3bf28881eaf1d8ff548dd6febccbb2b87b7225d9ad3ca38d28f19994f0d24c20de3dcd1edc78587c547b522f3d3dd3e1afff882e80d01bb899b76ea2c1c49f9338312635addd8313f10d589f88d18a7bc24bb1c3c3a924a0d7525e9193d253e20d30d16240192cd0f74fa189ef7d4bc74c999df5dcbd88d5393879347495380ef0762aec006080da41dac00fcaf0eb63b66b56d503df18772551eb3dcddb79053dc1225ac05e6fdfae7c5f003f8867fc7106376bb9a9b705d3c36cf2e02b238bf4ad902107cb06b941faa56fe27d622d8fb7dc3df772b64fd0ec0d62f0c30533bb1155814f20e96ecf37966d86dc1ec2eefbb22b4a6acd949a134177ab776006bf23d6ae2f49b6b231a45f3daf7ea937a67216dbc372e7bab2e4c7fea183f4ffd2fd391f5cf301d7de3ffff674c476025588f59e2f5e7988e2057f921e6e671bcb8cdb4ad6f6bcc2c8285b327a0e53dd4f7ffaf998e20bd34da721d47fd8045cf0c24de40fda716c8fc37c068e73baa99c522a0fc6802c73fb169aedd4c36261a10a8189e6e7394bc6aac4be772030ce93080018f583e2006299a5af737b29fbcfdf293c079d17cabd8f3ada54101d0f4c9ad8668006d16eec84c9679eda3afa138da385a9a8de90a6ffbc206fa2bdc538b838a659fbfea1ce7ff19f13eababeac53d77bd3a12023267b9ca1613539d5d652c6d3004df422fcdd6cfdb53007c8c962eafebfa1d898dbc9def5c6619d8c0bfada83747ddd23350215e41aac1b91ff9ad7010f98dd91b17eec0b4b69ad3e1871b7b23e1991bedb01b75c7f0771460125ff1acf622f949986936fd9962cd8d4d3749fcc3de026a2275593feccbc7d11ff2e9c2f03cabc391364fdac0d04482caada81c379a1584681ad8b8888ab503e8f20723d3ccebde7a22f1c43a5bbd59a21e41f8f2a79af8539bfafc1c69a798f121f8ac3bf8cc0765bfbc88cfc4c1ccd2fc3bda1d1a67c4cbb8dee1e24aa9330cb1fad7e0b5c4223de605195b90a87e64b0a87f3000b964029344a0202113082059131040f84700e91f01a47fb0e4c38820fd2382f48f08d23f1248ff4820fd2381498284aa9ef6ae9666ae5697d994cd9c1dd9dcb9d8b94150fe87ff3ffcffcbf83c3f827fccfd0f6cff02dd7fc0f60f90fec1f67f1490fe5140fa4705e91faca40f3a48ffe820fd6380ed7fc19e26f8df24a8d72e439d9d8bba5e66d5722e4a2a4881f3aa087ff2f7eb31ffff00d2c7af847fe35ff9a6736ea95c68f1f54f11a6c372a3f7e407aa23ff49fc7faf2cf63f89ff8788591ccce13322925b033a4adab7849b3ed32afc93f827cc8c7bbdf20a8f8ac83487ae2b9ff8918256e5f03f897f5d9b79cf59edc28766a94b869fb1d1ae9ebfb11df24fe21f553e8afc53f48bf2791522111a325b60acda5ffc9fc43fba685981ad01658ee0120f45663c66f9edb58f8cff24fe7180f4c47b680a57639916e4b7e77b339e643b9cf827f1cf95659606e01af9868cbaeb9ac6dd99c1d049a3f827f19ff4a4de99aad980298b314ed80a3155a0d19a6ef6efcc7fb15ce6376e4f2c42f7da829a5a4fa62244732dbdbffb8c483ae230a79b4d7aa7c784743583878785fc7a3005ace7d67effe07bfc1f36ee7756cb9cd019ac0eaf76fb1f385ac200e2d917cc55178b2e53c858165f62c48825e1fe744e27ad58d383b7e1fab9823b5d80c1a926f3d1e59eac4b9a72a2ac673646146374ae9cb3b2e059c952c959f2b9781602b1dc3647d9f76d18f388cbe9a0a1614c7afe514d7a580738c75597b73a46e71f4c20db7a0306687bdc7fed81e4be45d89ec1ed99b1cd9424cd5251bdc4e56b58be8c1fdae2c20848d32fe0cd3f87bd55747a38c687fe31cbd5ea06fd1c23ce4b8570ebea01dc1302fb66249403872b56846314b73e12c228f33961c033bb9112c2c5a567725c01137a9b1aa16e1be225bc748402a616776fe32c30de05ec6f54ec84df15564653bc8fcb219796f8a803b7b38e50fa094eeaf835c2c17779fbcc4aee338be95416e7597fe339b7647d585af869e514364d7ee57c1e17ff6ac938c7b286df773ed6b339499b1e14587c77e09a616e32aacde8e8913142509fcba230a0f72145c45294cddd3a22589a8615a2773814ea2bc5353451f1316fb35ce5e51ac057f596074b2b1893e83afc84e20a04a76dd1b0e2dcfb0c33b919b6c59c9e04ba7d079583a2ecbd3cffa9834adabb308da7b49c10236d91ad1254394a2748dce1a595bf08f73e09fa30202aa25b51ab1e35d58231f4faf5d053b4b90d38dc5883167811ba568edd21fa5d00072b1bd16e5d426d95815ccfb9a153461b8a1e185637988693b508fd263939632090ceed8e7d5e8390f2fdbf9bdbd4bfda34b49c1a2ca7e9d156795dbf6f66d1e65443daadb7f3952c34bb94c8d9fac14e1c420fe00065c5d9400bd2eb1908a196ac2445066aeaa776ef4811001eded68ab06003d362e002a6144fa568dababfd2d08a017ed0733d0a01c4803e769d05822b185cd5419dfb03bf5fe53b30e0d27f3af09615e7b5783e3ae7e174af5f9d7cddde1062f60934900c0ed42c1b2ade7c73f38e44374f3d917c841893c8d094f5bc21ed1d2cb3fbf62f61f1802c4b6cb58273a124838b3ad9541d0b53711f3a8dbea5a9de4d2e94cb0d76f10f2090a2ed824028fb3eb7c30171237890b4067dd431ac853623a34fb1838f21d859df9b2604b1b1379199c9ef70a9af53ae93e0f69b5b1f5a8890c8d58c77f872083f1cc0cc444ba3230e8dd63e43817f3de3836727477837a7596b97681c79613ac67b7e4020d6fca57070c9dc8b114dc94cbebb53c91fdd6e66eeb1fa17e1c42e5e51be217650411d11e94757602f5f6ff1fa5a8fabbaa1e9f3136ac86f6e4c9f3edab3555893160630cc3b25203b4799c75bf1a0f85c97c09e969076b86770859e3baab6fdf2b8e138204f29e839e06e88cdb58291c0989daa369990b2a2fa9aa9ed4173e6f394a8fcbc0376a1650746727cc7ff742e5cb5ad7cd4d598c14ec72c682a97b5c37f7609ffdd51dc62a1639c840318cd495458a6f3973fe5e561abd7c557f89f7ab047de523953e55f696068549f0058b05c7661d32deb1ec475c2454f4f8d324aee83f66f5dcef77c599749001b10d99fb798fb3321a2f75779b441d846146040da4bb55eedacfa06bdd36d66e54fd2f1a473a6f25f8b79c3919996fcb3375fa900ec97ab1c0d4b3edfc070df996994a3f89813b5da9bdad2635bea389afdb2f341c4d7db16e97f467931283744f8d48ba4a567aa92332f04bd8576426ea2847db0a148e5f308405fd591044c56334a4517505b1dbd6fbebfb056e5aacde6421c8a769e22fb254d443e97eec131891a4448d0f72b8fc91bb3a42430e0791c3756d3f5ac7a6913d1e00fbb8e750bc4be9721fe74cfce5e20a06b68dd84014289f40201d40a2dcaaf021f741b3b0e27cd105b5194260db1193e3d45f600dff4205535ee4161f8bdbcbf5baa6a4216375cf856c4a51a35c70d9eabacd2d79be5b48f42265557f73bb25d49ef2248f7ffcfa7aafed131ff23c080a48f40de93ca0f6f5c65da48dfb5e24bac69e8744e302306929c0cb0ccc832b103b8cff2153cccf421b590a4f343471ee97f169bcbe36de462eda96ef974d56cd0617f09053cfec51ebb2452f07218504dafd4a8cd9bb490556934a93a8d24d294b494942d3bda691a5a7cbe86eff37dc01620dbb974f36490f7345e919e979a29493e1a0c97d5d1f55ef23b16cc76e382834004e85f95df7059a6a555b59bef83636d490a0c19db9f0816970bfa8dfe52f8bb0722f817be68f3d7273defa3624c6e82511c56b8baa28ebbd016a2a78a8c5fb33a8ce723701cfa1008448c8a54ba734ce97c91a45ef07d31555d43ae6dc1f3ba3a05adee443db6c1d18d0df4d10f5dc8cec6b5bd48deeb29290e7220eeb922e2fee2448d7496a056de06391d58082c0c183aebd77636a69af3b59b6ff199d0f60a15ae661fc05065b8daf2bdd0ba53b806c09461fae6b354d54d9b53a73967a3ef602abc5c1bb2202a4d378cb48ebfc1a75ef1f5d496f927f8a1c3007915195a96402f2fb1be2731646704477224edd91cd861ad7016dec7b27e73f4c0090f37882f51284ffc867db10ad96d2653cb9b8f642ae3d5dc722ac2cbee9a891cd48d31fc937563f6644d78e27db89797bdc3252b046e92d3157734800dcad1cd3f371bc39fe00f8c3c683686e3f609039c152ff6142e08a4a5b57af5d53b140a1060e4a586f804d24df487d366f047140058bc5cd979efd83f14898ee72f694c6020fa0e06566a54f0abdaf45e972781a04220f6dbb6416830c1afb96e5f97b1ab926864a9cbc06c44b870641ebabac49f0a454d8969a52e83f8c3009532093df244fd92097b83ae74710cd7cbd6599644a9c64da822b138847453b9000be9fbeb1b22f792a2b34e4fb9cc2c585f671f6fb9dbf7606b59843d37a2e3243204eab003b50d8272f9065107fb075d90178d0b2c667d2dc2637956abf1c2a868a2814ba1f2bab67f0d14e9feddfb8f7effbac49465549eeb2ab62705645ea4970a84a43ea982817d833fd90eb5fd64904fd686005696e04830e53f77ec540b70e0913b7312f5724c5d7ba1325bc42b6ddac7271494f1bde033af521c9df4a2afd1025718cc07c87b6c73337adced7b486687bba767c832836d5f53693975a62f7ec8ffcd28f5aba5edf9717738d0376df65e1bc2d45054c451225882e1de34aab7e49de401cd6397a52bb831e509b0ddc53b7197022f96312bfc0cfd9d00131569a34136b119d747f9343c416344f11068e90eb4281041657f9b41c6458dbb689c6cb44545c568da5a480f63bd5bf321a356c4bf062ae9ce95019650d590e05d1e9f83a12c9a49b279421e11b26f50831457e3f0bc09eae855a1f010ca6386fd431838e1e63c3073011e366e5323381b2fccd89ccd88df889f0d2660ccc70de3e3e38173ff7b25dcff1cc444c4900b71c28ca3ddfa93cc4d8d197dc84b2f6f3c86c2b6724bcaafa066d9f9c98f5531dcf58bdf24985b94099dbdd178d581d727c7b65b60b362f9a662ca562cf829c81681265fe62b4e607ce1f4aa0acee32c07f4e16b1e3ecce2afd1f85655961c9601ced7c4d67b35f3bc39e1657e3dd979d76aa091fd51eefcd04f76f9643c59be1b5f4f41d99fa1bb863156b3d26d50739e55d37addfb5849567296cf134968ce2993861b29f6e6c5232ac1ed03d1b56773eb9c2be91b44cba788b69b46b1046e24b6d2584f9bb56b5561d2599627c2818bb72ff293f125a3bb63b4dc5fde4988ecb85bd615a91612f8a0afbec36ce31103c085946f5384b2920a10cb8d3ecfd52a291158b737875bd54e0df92f77bfddb284a0beda411d0f2433da9fa0af5f35c7f9e70062ad33518d7205591295c5bef85b61f764a035a81e4f1089a27ecf1d98e9ff7b6e7c202f0ca6e9fc90a3fcbf034ac5170288d8906d80faea39e58e2c2a6561c4b814cbdb8ffc35c7c48c7c86a02d75f99a4a14e2fc231771d401b70b1fb55a65128b95661942dbf8955fe7f7ce5b683e95bae1d50d81a66c5366d93a098a2471763df9c47dfd1de3e4e97399571536f0a56ee75ce50dbf6b6afccabaeba5ba4368fa3337a5cb08585ee7232c96d9b7a8063bea56d3b0e549a008a1f7718d3f21da3f627329658d735ee52a2a28085be3df8179ba184c2f3c8ebbcd4f80ac6d7e26f485c20db373752fa58df21333e72ff61450ea8b2bed92e45b5a4090ee51bc754de68de9b27d98d0440f8bbee3cb92040f3539734b6da2a2888c2334849261876c442faf8f94a79c9eaf35760cab14f19955429e6edab9dd930b9b9b541094119eb77a6fa9f95ca59fde0a2db1a0aa68af0a51637e5c54667fe6a4d1509e5b3214f06c900c308d96dbccce1ad6bf8612aae08cd6238c43d746272e1ae31a3e07417b7f75b5da9395693381c3e5c395d653dbd398d838f9956b582a121988fd7720b9a71f7df2d8cdc820622c88a8d579510e0ce69927a3d754623a285cdab1e71b9d8060a084fb28b05f8d507bec3165e62db86c41f4368c0326ab8bb0423e9346887bc251d96f4cfaf620b1bbc5e640ac5868201cc35d8e596351e17dc7f5c1331772fa422098eb0630e58170e5a19bd26f4db2a22ac8afc40f6131ddf0d7221ae3bd980c7fcecf284da18399e7010f8fb3c12c16a9af512b8cb852ebdaa997e257e8c6e599058362592ebe7226ed50e62b48ba9d94dc9310352b752f7a9dfc2317ce8586fb43a378fea7ce5d3f85aa9a14d85ac94ce3c82ccc841a553ce038e75bd395f2184fbc6118098aed2c4e987b51aa6ccdfb3e85b05600a5e01d537f2adddca2b556e8a7362dda7785fa22a5ea7342e9a63ca392d7af57b7c93e44559856de28ef35ea651a362fbf1102c5d53016134d94eca53af134c06db3d3e7020af5f25ecd3acaa3c72f9a9f775d63b9c25e9ee171562bb2b1fa5d8b08da2ccda5cc9df357c49b5f3c6beea6597db4f5e023042f8f8d9cbbb313c7d94c0ecdcb32fe266fadc1e391c6f0cb82a718d82ebbc97dbc892c09bf42c50c30bf16fe58956e70fd74fce04e1e9e380a69c77aae8399afb51d94a0a6b76bd135593e459b746875cc8b4e6b9e21f113594aae07fec0960bdbd83d6eaba0f2400a36460ed4e1fa9b8defa7551f3b67ddfe702b03ebd3ebb89ec5d95a748829bfc8e0fe52a3d8ee3ef9b028faa407a7076623106104d11b03922464de6f2e75a927c09bebf61d958853928da0cadc9a32104408140245802043d29110a26a6505f97cbbdfca3c2774bb25d543556379226b0eff8d71251f7d6e7fa85f12cd4d3befcfb19b64fe4a27de654093e7fa51169be9fb4f628a0421bf8f2efbb231099bd0ecef24e46f5681bdbdbded2fcff88d29f753a490932edb7ed90550bfc64d7d65f977ffbff82391afcfdf36d33ec85235aff2ccef709c3443e0d7ec080fac66d32af87cd532e116a23c12f1c2d8333bd957f9abe3b1eef3f3cd02248bef5c24bd09d49f3dbf4e19d3a3490a814058039ee2ece79c46c520c4f98d39564fa6acfdfc3028ef72acbf3087fc35e8e510e65803faeeefef75a8e87567be3e6ff3146d149d7ce2f721abb82c72fa4305ba7a56e208f5c3c4224261058921fbb77b46b214b1f80463ab0d01d2dd94a6846e5b995a8c0476e66afea1e77977317abebc7428c193fd449b4865c3db5f47ceffcec3fd0140f4a478f585390208044279d4c885528691ec13a949a4fefa3cc21bdd8920324cda744673fc253783c860b22629ca1d41cb226b37e98c5c86bd60eb570df7393103bc972e8d4fdd1e213fed86885d69a41b77cb6c4368004db9f24b9f9b3c7e195f9443925845eadf98a31c3bd5b92fd5e4de1adf979ebe7c56f4ef316792fda4e88f44be3e571372baf530c655e15c6f801c6bf7edad665c266129bfa0429716eaf4e552447980518537f19cd20447d465343e71d79cbbf36d4b1237de25f549bdabb4c9fafc6f42f16fcc7df7f8faee673d0a60802b8e40fe9dc4d017eeed76a9e3069308b7190749bb7dc49639ce206a5d35c260022cc8edd87893db479325e8efa93faa85cf358e8c3eed6ab3f6a1c72f29beb5fbe2b7337e0cf587cff8efb9a7fdbe5da9a0be0fa777c1ac43e2446616a922a7995b7c14c8fbfcb7ce78d59e6c0207267d7d9b0d2d6b2ee75e31212dd522e38a0b941f6424ec7b364d6f21597a0a345c6e5bb876e616199f71b91a0d364c792f4f790c7a6fc36b5bbc20158a2088fd9ce3765ae9181f3462c8c3fdf3898e135b6552c10ee7faab1d3223b01a64dd4495ae69ad3b0afa4b3919bf31e5363bf5e221b1dbd3e526a99dcbceef120a58214872ca8af7ac994217dd654fd9052fec468f876bc62d1979916b20f59f7bdcc7c2705165a799e69d50ee62ff1b942a7559cb7cbafacdc2bc0777cf1a72efc592b1724051a4ca34640c6baeada848b27904f4f73fcbaa133899d9b4306ac9103608c4d5e61b950d593c799fd83a5febabed5e14629bdcb15d1c351ff6fac5fb2cdbc753255c10b4f7844fad741c17356faa3d2cbc762a1ea7ee63e55501821ab10b49be6b9dd24212acfc8849cdc3b4456b1a2f1af434f52457e2c8995aa31266fb1bae08b77b8e5241301ae41bbd6fefb1d7ad5312d3a8217b9f70f7333f798b41dcf3044115a47f4d7a59b388d4a078d1968a8adcc58c5de15adf35b6f681c07caea7653dae5cfe53a2c6504ce9f4feac5b508fddbc0e17a42ccb94bb38b1f7eba814671c91709bc442fde62a5c537716bcb18d13d2cebdfdacde29b8469912a051a000d30f926cb2a0445db28260a530cf72659c9d2ba2df149224296334508d6a665eeeeceab5a9cd8f67904c0e3f2d6dfc9ca6260b994188deb7a99b4a270cd7554e37df7b63ccb6d251d5e4290d047bdcc4536a435afdf36bde22a5cd25276eaf69db415337f3e83920f0e4a710960dd1b32edca1b76ea65a5f31725ca6625f2690a5d0157e87703aeba2ab4f4cdc730b28ce46b7c39521d505dd1eb7b214aa41f5244a794e7b8559319613d4321e66d131d1124324f37c5c4f0563d377a2676eb93b5261293af9166b5855899f86087f4ac986e0364bc73c36cddc2a0d5fb6a948881c7eb8dea8a8cd835ebbaab42c6b4f9132b060b763fc21aec44abb74ec3472a02661fd0aa17721656423cbc08984b07c63d655085e8db7ddbca2921235e1278f95a0ad8f76c6ab4efc33627405cb5a842fbd48fa16cef750533db2e163c780cb2633a051a83daf7a764bb94cca526a59f3217bea134d28c11c4aff4e55168978e4a56c24dc1a0dab263e28056bcd4891b24354dfdb06ed7445823b667cad0fdf7f6ce7288f7d6ebce21bcc70df025720e693ff9eb9d8c2ab07d01f3ee3cdff78c67760611285d526cb339acfa9e545ad447e1036c079d4d73387f50138b7c0b8946d7fee5c3e23dfb589d8535a50ff932255d19342928242795943313370d757296a5ff66ffa61739a7d2e94af51fdb6df22d0fb5d3a28442b13bebf8d104320907d95f190930a817e44f620f3883a6bc5d7e7a2c2c2dc75da213c019c348ea3596864850b73fdb2e591fc37466a7007ee279dd79f168c26785805a9eec70ce3457880a819de9bedae91204dd5e6dca0b759bc7fd984e26ff79bb16cfbd4d7c300c537f637efeca9d62fcce1402010922398fb86c8d7e7bd689c7a11bc7cd2449b48615531388c75ebf8f1f6929c78d14a440132d518562dc4e311ecb53ee524177df6e40ddfbdcfe5a272c52e29e7792542a0e64b6fb1afb0628efa1d1802101cf7be3287d9ef2779f06caaf40b73f8100884f428e67e4fe4ebf3b3ac1c8fa35fdb0ad5594cd847e1295b2507d32cc223ae734b1a51ace2791862c32f990ec76e55f904042e2a230e7b1b16f218bdefe99dc1575360d32631489df842079bbb7d6e9f2ea2e2d3afcc61b309901ff4d53706fded7cc73c8ab9df13f9fabcecd5d9e953d8d7e49148dbee3dbd38a0cb41984c7135e6224709c4f256fdf444c3ca739f85dc2bc2d99f4d6ec5ae3fd466dcdd8d9c0892a7dd11a1097ef9545941eee06ccafd7ad1a2b4b7b77790321d7a2be7b7676aff895cf90d91afcfe1808c3e3e6f8f412adbc3b31cef8be4b41478a9b9cdbde8f1b2cb946c77b4b3035980d34fc3d3a133380c76ceda367bd83e1cb1d2de0d704d0d6b564bac8e32ca7b285fb3c898fd13b2aac0804e5cd8b895e05a18760c2ddb5a54c6f3a7141ec40f4e7a7f4a1acce8bb4baf3305883994b8d35a48de37bd743623a47df8ed650d06bd10147e676594828fd7e92e91fe2b46dbe66f91de2ff4f6cbfb5a09d1d1afde7678d670370fbce57775498e1252c629aebe18e345be05d60ec2dfcf4aef07fc63b2aa1c0bc0b3aa60ed5a4f1f4d83fcb8d5258f06e89beb473563ed59ed801038768cf699d6a8ea65e38e21abf267c2f56a0ae1e9e5b04430a4c3000e389eb2b4f13422bbe31731debc65ffdea05e22279c5c6d2d5c549a9c6c1a36c108786ca8a3b2cc3d9e785dd68bf7a46e2a2d98f51e69f7438513536f4f75a5564ba8ed7b38a1fc620f27f4fc787738a02b55a34b9b18e4a6d01bc0aba226eb2e825c3f7e67c289cae93cc6ec9d8a9bcc003c32c722024d8e940152c29b5bbeb5a5279b6cb9155ab4e00e7323c3a30e43fdbadb9aff8cdd96821712f46c98b7943967355754422428a584973fe744a507b96a324deba3453d107c22307c18f0e00c677e05370faa943c9597c254bbc7b4ceec849f3e89269509c4627294fd3c20142c342ea40759a0ce7fa7efe2f6c879034592ac9db8aaf98e2781cf87cfdde910248e1d24d6205c0adbfd1796b51c396cb76df9e5bb2d91abfdae42e443aedd88f44d8fe111a50fe7356ac724955b4cd90afd26293846137c68c0da41f8035b5903bfffeb88dd36eb1f931e1901fff0ac054cbb5d06e2280187b4fe07c528482dd2e8f18eea5d8cdcedb839c68f02a481e9aa23cabcd151f9242bfefa326ccc163375e9859af8c53cac7742e5077c7752e120a68c6f409e163a4bed3fd466c5222c8f4b2375cde38bfef04578bc8728b262b7f239aa90284409e10556667ff799a43b691a10dfb4a87b0d64dff30d030718a07be9da8bfec4e267866df1e6cafe112a17911be89c749324f1936aca5361797b80dc9c13023e4bd784ac9cad478b3f85eeebfe358d0576472c97eb99db6c1f5363beee90163f638754232f89e59b71b9e63d949142b44307d5c859288e1ccd9daa64653febe7a60d72924388c0f0e1c0f5dab6d224811d590f2eca1291562b41bce5eda147cd444bb1eea8d4f91309a7016bdee24221452e1cf63a4f8a96fc672bf251780461c10a4293ccb5f7d3432eed42204edb0e01bb073e61eb6fe21cd2897ae550c6d21cdd6d9e1af54648845a8a5086224998b6d64120c158e7c389e0c0e3dbe49267c4529fac1b14dd7a6491049949af2968b2f58c6eca88dfd1f1d0b603ac85ab52c778dcce905e887c1e517a3ae844217de97aaf80ba1c56aa2b224146f4fe8929b27f623e7e1247c37df721af3abcb96d23f05319bd4b9a1cb962dd774ecc1b002b97864ef12477640106e98790815aea96a1c3060e8919cd63b37cfa1c0c2859c669971adef436755d6ad456ba7521119f00e0b442cb7816542ed4825e310bf87514ea38ceaebcb4612c36c4e78b68875ccaf190b2a85458192962526f717d0d8116ef400b840fbcad0b4ec6b18baf119df733f57b1bba9bc2f2be76ec838bab997f0d545221b29afec88f0915fa46306ae34a9dbc7a325cdb427778dd2cf3f66e91a7f391ce5aa8462f657e84fe77e05067fadf00ec9a5dccbb8505666e1534197c5fac13bf2cce6abae3d3137a5c796aad1bda9cf178615009ff293fa63ed5993eb8d74000a9e6f44ccb397d60672dbd7f1a3e9c10cbb0057e0dce1bccbc4d6b92bc774ae5b4aea9d7505a96a922a9dcbb7bbbf7cd553379b26a2500aec489b05483a54460ed4965c3edd60a1dd8d34421f72ada213a5e08e2e49b73ff1d278be4b75df570e0d2831cdef0d3580db8141df6564d59d21aac97ee912d9ebcb180ac146f66a5b30ab0f55ab55e8ee9cbb8dd807e7537e54a806580832fe5464a8eb44274e8951412fddf5cf9edc1220ff60a5f7ce32829aa8c386b3f43b61c4c166330afbef74a4ff7c9d1899ba883fde1004caf69237d46464c68928ed0e496b0fb1ea400cd621472dee7d985e5d7ad2c6c00ef52f0acbd7cb675a68096d9cd1d31f1eb4fa0530ea8f8fed55b6eab889d55b37f7179ec27f7eca5a6ab6ea7325d5bbac8d432a5ef20b13d0bf6a1fe5af8bbbb8f5a85c9ae5c72a7a621d5b661caf7e3c345616bf07b9f2b2f7bfe61ab37cb29e6c5274ec7a1ff65c708af3335702dca116421ba4065ad6b7b47422884a633e864c8354a7b89b3091d66eec4b7ced3d9909c72343953653df9c9e482f5e9fa0b2734ea35f3831d6c9680d3e03b46b1c380c9f0c329364cdd0bfcb7b0d91f5866b7b439d85f5219a86478284672c20bc0cafce06463744d30c63a134d1b96b2bd51b5935d07cd360d794d6d30d8a9900fc1e4d8c1fca222d8ed9ff8b8513587a808183fac227ccf33f3486c446c51b04a4a60959240f803d9e3c1127580dd82a183dd9281952d463c5eff60b5bda160f8aadb2ac00bab89b3cd7e1e0e9e5bf332eb09a97b641ed04f9c52edbb518d751efd9a3c52fe0700946d9c98b999a0fa61fca5a1a2b89ee02b06fdf3268c1dcce6c60faf7fe0f65d9afbed773f548052755bc51f70c25492edac839a546a8fdabe482bbf8a4db5d7f442dec1f52a25fde87c6e0d3720c5f6da09d9afc08e28b9a81f63ceebd1830906424891fbfbe5f96647143dba6dff6fe007ba4715df413d475b832a84b0830a83066187b2d4eccff8fd7f44ffa50c89fe7ee3c6fbe67293e8c08e0c3d78fedbcf8fea52f4cba440dad743f6393d480afb87d4b0487f9c397f74411385201c50daef8cf6db658a84f72dc56f48d142f0fe98e8f4009b16ef37fd6807857507aaff5d3febed60404e601465a0f9659bbce39d9bbb5661270555c272fb7cb5f59384c2914f756c7dfc26b54db0df73945184fbaf172fce47aa75fa99a19bbeacf9b11f7c0faac12437300fe8e3267a3d76fbb6561ca90fffcba9d3140a2fcf0c712a041a47d6d00dde7c054cd0b51057453e53677d9c48203b7d0659b0fe2d9a17c6e4c7f75b1195a472bcb1478ccdba7fbcdb82e6f670dcf72c1daf80b236ee8d4bd49442acc281ebd4af9d6cee35e3e2ea0777df7920a64559ede6a5540d36ec60830af6d2f420bf40c406e9617bf8bbbae92b40516c8970f2ecf34949d3d04a86dd96b0cde2355b5485e29713f72b5defb1069c077d35304d01ecd5bed1de7fec146cdac9d8da49dd818e1cf2d9661b162f31dc228954125a57843087270bd1c3ac4bc2b5dac70a9cc2d4bae6026b7e2cabf277deedb7acbc27a821f6df65dde1878f75f0630b8c67b06399e87bfb0608ceefe1972ff0dfffb13d76d85e9a7003db68be57e2cda0fdd095672d4b1cf4f71252332fdccae07169665c1c3398079db7e07b29559e646116c7bd44d7129b2edbfe2962a2f3f673b06b67c957ba17996f52aa0a571f77591fef7a084cfe010350eee000d9962a51a7ba416cafeffda4b13d3933eaec33a102eef6e2eac50ffbaee24fbe01986cc669e972a1b5b00da7f76bccf95ded1f4ab0edb4f5ac7530e5a99686c4deeeebd868071691d0f4c374eca9babb3f902afefb0003c81c0774f03cf24e3ac40e9d4926642846b761dc7e7a55cd5653d34dde3650231d603cbd1260d349f554ffdd3d123186acb571be54421ca9675b3b15739e971c5d388f172d65f75012abfca4caf55d47159204ca781849532158f5e1ff6ab4d49fe00f8c3c68b4d471fb8401c40121ca43cee376907c8d79bc53294456c45595af7c522ea7964acd1215a61702a6e3fa0e7c8de970663fb6cf8f58dc895a13423d1aeda36ccd0c4c781b9fccff2b505fee6718697ba202e96ba7f4c6e2c2ad6e07ea2920aecb95f610113b16757fb4ea4062f96403361e60f8702023b38523e33915caa6e83bd14e6e52c45ede732a865b35f3f99cd00bcf0943e08083f36e624806c294cb66b42c7a82caf2930a1ac2455d95ad08bbbefeba6b1898df585e9a68e3c82c6fa60c2d9786eee2d6dbe05e4ed459c0abaafd859617d24decedcca7218a338e7145b812b36770aebcf9c5a53b8e0b7f77cb8b7f612249dbc7aefa0c347fcc7371b10427442eaac78a8b3b0c3c3775eea59d74cedf380e7d080422368a234195697d4a4fe04ef2c74c9394ed08bdfba46745dc1b1962d483992b9813e590aeb9290f9ff74ceca6c4e623a514ceb5e432158bc60916daa5adb84e7cd61cdcf2f2b9cd8b04af6cbd5c4522ec6ae673a4888ae2f3aa7745b9c5376fce7cfe1ceec305782ab20e5ac7ada31924d6da3c907bf4ccd63590b96b18485936b1a77d81d718034170d841b00d42389710849bcc1984143b19775e56bbe4fc5bd1f3d5d11bc6bd6b08b7cc9ed3bff7af4140f2b4e8f7056108ec8b835906c0560498ecf1cd4d9ae5aaffa71e4b7ecbc89bc12b7c9c19cc4d18b4f1bf6f072b160146ff0f4d35ac31479aea5842556f838dcfe1f4a16d4d174d8e181eb07630fa1008620a0adf5104a06790d72030a04ae0d33948e5638f9e2e1d47e614aa206b13ec133e73c4f34a6b3ecc8d1b58f58009765aeced223944237effda47bc5ca7cb19d1572b0058185662abdeabb96996fd8b27c41f4cd6d0584a8912978e287c9ba9564467cde2d18ca8acfc512f8a66702b070e7c9a1a56afba88e3dd691a13f43981fa91b8b492eebb429d0da6b51cd1d49d1653002ebf4c779757c448b2d633c788ccb4779090455e9bd388ea7c09c1fd0a675bb5af179196ff8c803e1fc189c2084fb62e920eeb909a47546f696d99453efa2faf337baba3ccad016380cbd30f172f688ade252f3078b9177e076e725ba75efa25a510e9cb87c0fca81fece0a28dfbb78b3682bff2a2ed3babf370fadf81635fb4b99da269b56cbcfb8cfa2345d0a7b11abd4b7ebe89c44f93d5ef2feac2ede619da55499d9b7a5b2c6dc9f402735287f0b7228374335da71f22b8b6c3f17a4e4b9a80977f540d36e029dd24407347552258832d07a39b40a3d49b4bd95fb68f2e8cb7e8c60117e2fd2f9cbf26e733275cb12e757576bcf4f14796fcc591bd9566937b909833c11088d5b68545105ec7641032c43f2efe4581eec26e521e227b5ffbb0f29e3d6efe8b44ff6061b21a023810c4e3814c7a2ff03e45ecc5629c11daa7a5b9baacb1a2ce6723dee8506766fa4200316eafb4ab684ce75d11d516ab1e19bff988e88134217a46770452542aaf58ad7e904f0c41ee17fb585da1925e81038f3344ddfa9f198f3ac9ce5f95e3c22478554ada4c9b1da10c4c6a59965204cc02f8a95cf45526bb351b7779cb161503cee72c0e9e469dd519e1db68a91e6729397370abf7527a7f265f57138dfbce7412f7af962c404efba6405a3f312265536e427748798b6513e52dc2069284e0433845a06ff0137072c48da004309e8cdf1a253b87a5da4fd81bb269771a2e538cac53e0b35513cc6fca6d81a80a601448935f0ec6d2e395e3b50af0687e9dbdd68b34271f83837989a49489c6ab0c827a7907d52d20f4a090e7b992b8f1d5a269564445f5f03155cd68d3b35a59824ff04291ebf26fabef75d7a0a289a99b95fd9e1730e1e887ea56fdd6cd515f09c2d606b67ec08eea635e328069684860fc815d82809da5dfb4ff9070fa9f8c2f040256170b843fb06a1b6016b86f07184c54faf1ba6860a21e68367fb06a27478b9ae0f31704c0faffe1503402757b2b170f23470dd09a0a3f677d8289a2dfe0bf8911f7c25898659b5e5ca2219b24f6460e213605c1075b3fe2df9d53d0f5efe5a984404c7f6ae53dc82faef205f91a647204808d0f98b5196cfe81d1ff21550a6cfdff19e53c243ef89b391c02114252721c692eeac0e8887741be0f438b5d3c04d56474537ac7945f64100ee88d0e7fe895a2641031dfcd7bca2a543d0df00dd65c7c74615b610ca57624c50ae01b7932617b45558eda2353d6e88c23ea037c942669e52ee937569c91341c38b85fcd58f2ff0c6f6ce33cbc166bc70d8581bbfcf75af87d49169929997bd869d70772aa6d4a36ebdf011a0ce7d7d95150f74406ced93cf6f741bf6c9de95ae8f8326e8d84037139a95c05028ddc81de0824b5094a4af00f2299368cfb5eca57ff1a28c33aa9f9a1ce7d5fc0832fee9016c4d9c261e20555a30c905271df4ec21cfcad4e91f28f490482fe7ea991f2752f47cb8f9c44a6fce7c841e87fb3c8c1b610e556676dd9db2bedecb672a6340c4829d13e6520a9c6be08f14e37d3b885b5a42013b1519c1dfe2dd1be57c6fc7b1f48a30eed318b554a2bf20062711cfe45825790eb4fd4e5cbc1af047b7eeea752edbe72f3210d2c3228dbab1002b1d9b60aa464db97fd88abf2e3da05274ee407fb61872950913e7b5611429deb51ea1fbc5b0988c00102521235d956d3298ff413fa5df69c1ca83de48f9e8db29ac12699b21f7b0b5400ceabdb33aba27619852a2d77cb12eaaedd1ce4d6376a254ea6b9dd5e3da653088340a376a0e1811402c142299d902f73e04f7ffff23e83435a905f3db706e8ea5f1ee9b80df9e3f7bf707f6519675ef99cbfd91d0a7b3bfd01a3c4fee1a3904df925c0c26cfe0bdf5f3415a1d974a7bc544942d76ff121cda7c9ae8c74299a30c4f75cf6f8dc75433400ced38c9376e7188b823b66ad3b1e91a6549c1e620a08b5f0b44ebad3e5a02a74ff20a7eabe41647f397e37a72ae23ba74ad166c85f9053955d5fe60161fb8dbac74f308097ce27e959e2042c8f424679107a64496794885b60c149fff89caa3f3a663f191f020790b4c234ad338702baa12e7b2730f8b4a968d88c9bdccecf2a5e68cbc79f59bc0f6819232a6b06754fe4882896204ce9ac89cdd3c5d02990b3e690c1de3fc09bbbf5ad9fa9f77fdbcfb4206eb0cfd56a3d0d5ec2554c2772f281e0a3e5230aa1ff1de0ef7edb615143ad2a85bd194cbca218c77a4f5bcc95fb2c2aa695322b3bb1f2d90b3ca22e52d4c7a10f8140c498086daa8df4df3ea6bf1033e8fab0b7c8a137f979e6c333b511ef9c32f4a1d165027aa419aa1c752141540c7734af519b8ecbb9e8da641306d1a2f70ed224ec688119cc60c0d00da18bd76fdfc1c77de443d413a87e72fbd5fc885dc564c13ce300bc3e6b581e806b75aae50560c9ebf6ef72a765a7d9d8069eb21a7dd3c2cd26a1deb2e650bfb96f301338306f46f6c6a191e3df873486af4cabe9e0ee88e9a1a7515efd7c50ff020ea04be86553bdcc92be818d7d12f3fcfdf9f8488bb10f1378ab1622b1c1ccda1e5e809d17b6d3d6e7d7553ec1342d17238a247d144ea261d984c5e4aec251599b497421e86b3be8cb07897e31e5eae3be57fb3ac46729061277bf063dd8cc41184ca33aa64504f4f204cc220206c7adbb8c01d27e5cfe7e3580f107b241805e7e81d57f05fbbedfb497777d8ce8e8547ca3ffb0080d4b6e7840db3f9102041fecfb52d1ee358d4da1b3486bdf7ff5ae52dbdfe0ec4531a9a1b134710f2c11e647a8c5afc448b6a5444d6829663426745fd69cd89a588bfd981ee34fa062619e2f25f71e2cbfe837e30726ccfd89f73b12106fafb680fc04f811fefe4425fce3f207f2fd90c1baf8c6a9e64fd863fec298fe7f87be1b9744aeaf4ebd28b39804ba5ea22bda8bcd78ffbefd87e70f1e2be0626ba4626be568a2a5e6a6a06ea5e46cce2bc3a5fe1f73042ad682593cfffce5f201a081b41fe372fca700187d90fd13b4ecff0ff9ac9e8eaecf5a1b3f6fb4782d072b39af4032255fcc1504ff50c63e98366bdc9dca0713c08eeb20fe0dffc10e73c27189f63b21b4a2c31f0b1e4517badd3af242fd3fb0287e239f808d0fd8fafb0e80bddf37fc612b639e888c7c4f4df738fd44cd6d4905c109826fa20dbfb7bee1c08c7f25234d0131dd4b57bffc0f0b2e371d1ece9ea0288b5f702fa0b3503ad92208d07a7ed25c47ef43c3dbb0647bf16a6cea56ebebb326c4c5315177c2ae36a2b0214020b6dbd6885ff3875fc2bee04a25111187d4c0b3dccac12926a1ee71e21a54e42d8fa9c0f35bfe30003ff2255ae3b04e9d67afd06ee7409ebf255fbc6906a66687c23a217af624f7208089cb85cca6a968b9e65f927711cb445c0efff556198a4694b23739feb635b5c357e3e5859f61bcbc838b949f299edf2d67696d9df8dcf0c1c517d1ca1b897c7d82a76ebfe7a618f90c824f04860f074c160cb2e2976ace2a7120095f7d238f10a5a6ede4b2b16e625ee4eec4c55e5308b83ea4f10e7e03a18e986de2c9bd427afa14c9d979fe840c2c84ecb567042a1d8a10a8c20e542e10c1675faa2652dd89bb73a7eae47dd1ca1e6a5a44fb3c799990699a9671ffead75e33bd95bf674e2dbd61af41ba4143608737b231f0ad0847a607582941b0e96e7a7545a7f2b0464e863b9aade50687e52cb65b619d828ea0fb432465a424a541cb817d1fe0c0dbe71c3c21d1722f9838a12a2132224d69368b964d2cedb7a47cb73a669aa23a003e1d6dbc73d9c9a9ed4b4cf26375c26ffd50f426c70453c5873a69b91813a41e7ef56fb1fa19f3871071d46795c7fad4455c8f146f775697976c1aa11933f595b277cf226aa6cf801d1f4460f87040b6ccd57a2c6abdc034b09b211b3f4ff4063ab28d72a88a63ef595802177e651d00e7c2f5a3d55131b77fe67846758a3ee6b50df0a25ad05e5bdaea043016cf2f0141b8b083202bb53f7b282549e3881c3b7cd92a19bcf8dbb0a75fe87b27b21acfe1fad7405f974bd90afe9eb71f2df4f71f9ca6604624b0fb2330fae820ed60da1658ff5820ed6039457040dac1a46130db323e483b011c18d357275d2792dcc69c282eec4bdd71cc9bcfa7c95fe9219c71d2cbed9b515900b87547ebc9d518d893252e1903d8b352d3020f92650730e508af6813df2d45f4f8bafd2afc13960f0c7822b8249118f0faf2e287ad8b0d52f444a87c91bb28b609e65d5335cf88eafab30092ff4f97f3cf1c69db64c2a9c0733e7efb79afe78b363e591758ac7a4c6ed551f1f0094719188b7e32e68b4056a948354ce19adfe4c3badc3fbc2a38ab8b27ddb07945d1fd2f6da98c125232653b1959d6197cc33766f5e2ca523c7128c7a5f442eccd61029e9e85cc3974fef29c65a7bf2a9dfbad53c712f694a73964ad0c29f264004293b40ce60b340ecf3afd31eca2d4baf84ddf0f062a4eadd9f5e4fea58335ac374a746f719dbeb66c41b5d5bad97e7f6bdb1678dcbef9ad22d7b67c9ee796653587635f2e96da303d708309200000ffffbf4b7011', - maxFeePerGas: '0x91e91fa98', - maxPriorityFeePerGas: '0x55a0712', - nonce: '0xb02cd', - r: '0x0113be49a7e3226dbdba535e64da2d61aa66921904bcb5c88138ded11819f160', - s: '0x02f8b000478f11787977257fee2c20085a16c7b8f460d7cbdee5bb58c372d491', - to: '0x5e4e65926ba27467555eb562121fac00d24e9dd2', - transactionIndex: '0xc0', - type: '0x2', - v: '0x1', - value: '0x0', + index: '0x3a76c43', + validatorIndex: '0xc9c44', + address: '0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f', + amount: '0x1265658', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0xe1a9ac6a6fc957d2cb2633af61c451e3366c9ffa', - gas: '0x5208', - gasPrice: '0x479a12896', - hash: '0x12d7dbfb0bee81eb327e32170b201fbc8445ce3d780f446b50cc10b2c6a08ed2', - input: '0x', - maxFeePerGas: '0x57ae1ff95', - maxPriorityFeePerGas: '0x55a0712', - nonce: '0x13', - r: '0x891c8e4fb5416707bffdb3796101e4bab549d6d809bc8107dd3c64ab161d6ac5', - s: '0x739b527d8da18e099b86fb623f6a1c8436a2139c2ec8a49cde40f1cd35c70659', - to: '0x8b70497d9ef243a66111d43f567aeda3ebbe608b', - transactionIndex: '0xc1', - type: '0x2', - v: '0x0', - value: '0x20925741e3d00', + index: '0x3a76c44', + validatorIndex: '0xc9c4c', + address: '0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f', + amount: '0x1261797', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0x082c948908b571ed87be70f6ec2363b8da4fd3a9', - gas: '0x76094', - gasPrice: '0x479a12896', - hash: '0xc6f78588f68038b676f7a0ca3324f2c6b24618bf43b5c6e68704262e3fceba4a', - input: '0xfec53fc50000000000000000000000000000000000000000000000000000010ec833ae000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000db40e4269400d90142a2e5593b21b56a17fce57d690840a068530b08ac1fc53f0121c6db7bf8c081274b66467d9cd15335921f79bfcf67d4e25bb29571be71de4611e599d961c469f06e10bb1315a348df4b0cde7e1378e9378a8ab08b325816ff2ae0a693ded4304d333a0108aba908b94e4faa3ebb211f3be184f42247b099b1ae2aabbdd0bb1c1b9d79903935f4231667e4cda6ef1925667ddd45cecf693603d1804a2eca24c9340e579cd789042313e240d08fbb24745b7726c54247e1ed8e8e3ce759d01cf6d8a56fd5f0b9ac88c56767c92bf6c72d42cc6f03262b6a6e63690f73aadd76d215896895cb137552f0f1905cba732c22514921d0c3cd9027f66d309109d4f1c5e5eb8d51cc79c2261cdf49ba240c6cdd67fe5d91862c7ed25fb5902cd5e6c0366fc658042b60d554949d176b89a1633e33d9ea7bf857e7cd3f68516df72ac60398183e2756a5823ca91427e542cf897e54a6304a98e1146974e3153342d9c8c304f91e13aa8918576e0869296fd570b36120f990c2185fc04a5ac2bfaf676a9e23eb3617d17e60e034f123e71e7782dd34bdb84ab8f230481', - maxFeePerGas: '0x57ae1ff95', - maxPriorityFeePerGas: '0x55a0712', - nonce: '0x1', - r: '0x8c2590402601bfb04153ffc112a7b649d9a2e810fcb287acbed5fff1853d5a9e', - s: '0x2d4aee8e065ff06be42d1020b95bc35d21249c6b66b149ec15824f41eb3d54e6', - to: '0x1fe0fba03dcfa2bb97ba9047a5c523115fea9c8b', - transactionIndex: '0xc2', - type: '0x2', - v: '0x1', - value: '0x0', + index: '0x3a76c45', + validatorIndex: '0xc9c4d', + address: '0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f', + amount: '0x125bdf1', }, { - accessList: [], - blockHash: '0x2850e4a813762b2de589fa5268eacb92572defaf9520608deb129699e504cab2', - blockNumber: '0x103dab0', - chainId: '0x1', - from: '0xb121e5aeb374e80081d0cc180e50d3877401c249', - gas: '0xc91a', - gasPrice: '0x479a12896', - hash: '0xfaeaf9b4a6c5fcac8005239112a27f9c059e7aeb436f31f192a80c1691c29f29', - input: '0xa9059cbb000000000000000000000000890741ba72b148b70b4bafc631e27f75a8295406000000000000000000000000000000000000000000000002b5e3af16b1880000', - maxFeePerGas: '0x91e91fa98', - maxPriorityFeePerGas: '0x55a0712', - nonce: '0x876', - r: '0xe7a96ca63eab2a40e2a1c137bf0b2bf2133fd9fd07c5e05fbb0af11cb9ef28d0', - s: '0x128151f2fb774ee942a67b98b352e8b52bf07065bc07809220c115c313ffeddb', - to: '0x01659335fc8ad471c7079f6f04e7532c7d001d43', - transactionIndex: '0xc3', - type: '0x2', - v: '0x0', - value: '0x0', + index: '0x3a76c46', + validatorIndex: '0xc9c4e', + address: '0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f', + amount: '0x125da93', + }, + { + index: '0x3a76c47', + validatorIndex: '0xc9c4f', + address: '0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f', + amount: '0x125e4cc', + }, + { + index: '0x3a76c48', + validatorIndex: '0xc9c50', + address: '0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f', + amount: '0x125fca2', + }, + { + index: '0x3a76c49', + validatorIndex: '0xc9c51', + address: '0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f', + amount: '0x125409e', + }, + { + index: '0x3a76c4a', + validatorIndex: '0xc9c52', + address: '0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f', + amount: '0x125f393', }, ], - transactionsRoot: '0x2b0f787500743395385ad4a4142693bffd51d508cae1fdd675d269842b9bc2b0', - uncles: [], + withdrawalsRoot: '0x3efa15d064b679b07a7b1403e9d4ba485144661bb788dbf26e4f60d4bcd3d01b', }; diff --git a/packages/web3/test/e2e/fixtures/sepolia.ts b/packages/web3/test/e2e/fixtures/sepolia.ts index 6f79a26024c..845c9251298 100644 --- a/packages/web3/test/e2e/fixtures/sepolia.ts +++ b/packages/web3/test/e2e/fixtures/sepolia.ts @@ -15,884 +15,1621 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ export const sepoliaBlockHydrated = { - baseFeePerGas: '0x9', + baseFeePerGas: '0x2830801bb7', + blobGasUsed: '0x40000', difficulty: '0x0', - extraData: '0x496c6c756d696e61746520446d6f63726174697a6520447374726962757465', + excessBlobGas: '0x2ac0000', + extraData: '0xd883010e08846765746888676f312e32322e36856c696e7578', gasLimit: '0x1c9c380', - gasUsed: '0x4952f0', - hash: '0x241dab30227f58633e69fc4128b1c2b09699ec274cd575e39e697c1e460e5791', + gasUsed: '0xce24f1', + hash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', logsBloom: - '0x0000000c0000000002000410a0101000080100004000001000000040200040020008800000800450001040004000000008004040008000000000000000a004000000400000002080008c020800006080010c22004000010100002001400008000082a040080211000c01010002000b00080000000800000004000010200100044020008008082100010008200805800001210000200000000004000004200000820800800000000010140040504400082404000300000000100080000000400000400002113000000000000040040008240000200000000110002011000001000018122010020000002400008000000008090810000002001000200800300000', - miner: '0x1e2cd78882b12d3954a049fd82ffd691565dc0a5', - mixHash: '0xddbb2beaede8c4a7c401156c0a02c58b3c0732e25bd5bfd350a599c54309929c', + '0xa40000cc8104c208801002c28490789000090c102001a11201500c1a448300230001a001042021041000080000148388440828801e090408805090040024681010024002880420004008206e0100480004020002130610083c024020180002214a2c034002a12202a1c0402012000900004800c0000a00c02000051801408a000222b900129005003020081002010058800440201012200400111000446000782288020200010a0049c0914438010408044142c9801008080080a01302020080800610b20800140c00222c439803088a0004000041008040248592000c216000081028090502200001041141240800008a03001a59d412a004012b940139d004', + miner: '0xf29ff96aaea6c9a1fba851f74737f3c069d4f1a9', + mixHash: '0x3d1dbf1f0670c91819b881dbe1862be1ae7955e350b5356129e56ad119278428', nonce: '0x0', - number: '0x3148fe', - parentHash: '0x26b0438b6b537ec888afe7b673f633a0fdd3732c3629e1dee30e962a46444e9d', - receiptsRoot: '0x1ca1776ebf36ae37a1f48770684da37fe1c8fc134954b229b1f619e5e0ad2c51', + number: '0x679c39', + parentBeaconBlockRoot: '0x995fe00d44a9851fa744a16bdf0ac7ab5d607dc2a30ec92957abc7ff3df7274e', + parentHash: '0xca67b2df0e6f1d010c5ae7b6fcb569c153e82065bddc282733d911b10f322824', + receiptsRoot: '0xc6dff7f3c4d8b267684cc3c76b4fe730f76c4d77e613a0f29ec39e2c5a231ec6', sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347', - size: '0xd66e', - stateRoot: '0xc9e235dd0e663f36fee8f80d860961f2e8056f4cdcce501372a77bc1fed20534', - timestamp: '0x642d14c0', + size: '0xc612', + stateRoot: '0x1424d53811f37147d5103cc46e0b02644348c737b7356f7b24cb35c999d38f18', + timestamp: '0x66fb196c', totalDifficulty: '0x3c656d23029ab0', transactions: [ { - blockHash: '0x241dab30227f58633e69fc4128b1c2b09699ec274cd575e39e697c1e460e5791', - blockNumber: '0x3148fe', - chainId: '0xaa36a7', - from: '0x030b1cddf635e9e71ad70b8668e235e8ec3c67c4', - gas: '0xf618', - gasPrice: '0xb2d05e1b', - hash: '0x5d703f823e7e4d6719def234cf8683d0d34708c2b0ce0285f4b008bf555b0481', - input: '0x', - nonce: '0xb2ee', - r: '0x2fa59cd01f8bfe1e878f790b73fa281f03e7a97d667234727ce5b671370d9eb9', - s: '0x5cffb682215ab7a1c29fe90f3a0f414843399056a4d7bdc05d370ce9d2979913', - to: '0xb87a21184906b99477d9cca63a452a073ed9c1e5', + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0xcfb27e4440d1dc1c8e7c955ed1ce547dedb76d59', + gas: '0x11e09', + gasPrice: '0x530cf8b834', + hash: '0x2d771040a4c584af05fccb1483ce4c52d42e046aa08fb733bbdea00fc806b57a', + input: '0x95b335c84d053fdf52290285953409c8d9abdacc0000000066fb195e0352a61ea2000000000000000000000000000000000000000000000000000000000000000007a13b00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000004230783062356438386334366461643065303466386565346561396635353931623339373763633739313066623339383564626561613532303530356639656532346500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003dc9ee8def00000000000000000000000000000000000000000000000000000000000000003e80000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001a3078313a3a6170746f735f636f696e3a3a4170746f73436f696e000000000000', + nonce: '0x6', + to: '0xd600d94d0812f7edfa47d0cf02a767b1dd14a01b', transactionIndex: '0x0', + value: '0x3dc9ee8def000', type: '0x0', - v: '0x1546d71', - value: '0xde0b6b3a7640000', + chainId: '0xaa36a7', + v: '0x1546d72', + r: '0xefc487be6150190a71d218388c154e8e7a66922e9b2d68b4cfd7590c16d504fa', + s: '0x69770cbd7c0f57697a3173fb6a0398ca43bdaaf7574b0dd95899b77f43774029', }, { - blockHash: '0x241dab30227f58633e69fc4128b1c2b09699ec274cd575e39e697c1e460e5791', - blockNumber: '0x3148fe', - chainId: '0xaa36a7', - from: '0xf0046e53d11c6e7a6badb4c9e849fcc26509dc16', - gas: '0xf618', - gasPrice: '0xb2d05e1b', - hash: '0xa8a6e1f58adfe40a059e037c6c2b6e07bd23aa3d32d892bfcc6f40d85f22c907', - input: '0x', - nonce: '0x1a3a', - r: '0xa0f6ce97f49e3bd2e539430890ef4dddf2f3b1c4713b374234ed6ebceb80604b', - s: '0x33712ef7984df3ca434d854724b2b1d5be58012ccb39bd5f3a8b729a0c4d7931', - to: '0x83f3229e66fd1997961f76cbfb6e077f66ae1962', + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0xaa88878d91bc1a7b7f71c592349efc44b5f3b77d', + gas: '0x11e09', + gasPrice: '0x502d9c7397', + hash: '0xcf811d80757452f648f74bea7cdee088c5c2addafd8d049f644fc8cafee7a50d', + input: '0x95b335c84d053fdf52290285953409c8d9abdacc0000000066fb1966037903179f000000000000000000000000000000000000000000000000000000000000000007a13b0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000423078653030353565656530616135303532306162306162343132663535303666396635656664653663633561326565633231643031613063326266346638396261310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000299c007f9c00000000000000000000000000000000000000000000000000000000000000003e80000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001a3078313a3a6170746f735f636f696e3a3a4170746f73436f696e000000000000', + nonce: '0x2', + to: '0xd600d94d0812f7edfa47d0cf02a767b1dd14a01b', transactionIndex: '0x1', + value: '0x299c007f9c000', type: '0x0', - v: '0x1546d72', - value: '0xde0b6b3a7640000', + chainId: '0xaa36a7', + v: '0x1546d71', + r: '0x1cf2c321ee1a4331dee4f9243fc1a73aa23b49929d0f5e475b27685c303fc4b1', + s: '0x009d5ffea271ec91f967e2993ff83c2576c63e83604ca8934768ede951ed1c5a', }, { - blockHash: '0x241dab30227f58633e69fc4128b1c2b09699ec274cd575e39e697c1e460e5791', - blockNumber: '0x3148fe', - chainId: '0xaa36a7', - from: '0xfcf06e39a2961e12f5e3de9376f09be9de3830d2', - gas: '0xf618', - gasPrice: '0xb2d05e1b', - hash: '0xa4335f3948675d7cd43b84078e3567860b4e1ffa79e9f6e5278f1d3fc860699d', - input: '0x', - nonce: '0x1a14', - r: '0x9476a6d314e82c5b7cdfb15c2a2d27038e8ab61c647a5dcffd987c9e3fee1dc9', - s: '0x2e9bc3125ae89165cd47329b9f4e9b319514f64f6c4dc58562501c345ee167e5', - to: '0x3eac72bba356e497e5cd2ad1e4190e81810a0502', + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0x3ae6f80b4ce484e95a6827f7f84edff0bf4a9acf', + gas: '0x11e09', + gasPrice: '0x502d9c7397', + hash: '0x1dad76ca8ee9f98c6f3ae0e545cfcd0381d457f75021f42f6b8b9a9b0869d10e', + input: '0x95b335c84d053fdf52290285953409c8d9abdacc0000000066fb19670326e4a364000000000000000000000000000000000000000000000000000000000000000007a13b000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000042307835376461313362353538326637613763396138343462656430633130373761373533383534343434663038613336316463623837636333343034343134306362000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000039b231a72700000000000000000000000000000000000000000000000000000000000000003e80000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001a3078313a3a6170746f735f636f696e3a3a4170746f73436f696e000000000000', + nonce: '0x2', + to: '0xd600d94d0812f7edfa47d0cf02a767b1dd14a01b', transactionIndex: '0x2', + value: '0x39b231a727000', type: '0x0', - v: '0x1546d72', - value: '0xde0b6b3a7640000', + chainId: '0xaa36a7', + v: '0x1546d71', + r: '0x6e81521508765f9639a86295a84314eb4e7bba9d25a6712317bf5f5096b70a2d', + s: '0x543013689e61c81f325e343bf4bd55f6d8b07c6c645d26aac5449a3d9f827b19', }, { - blockHash: '0x241dab30227f58633e69fc4128b1c2b09699ec274cd575e39e697c1e460e5791', - blockNumber: '0x3148fe', - chainId: '0xaa36a7', - from: '0x8b8a3c7b9a182f3176885cf4c72ac53271eb9d7e', - gas: '0xf618', - gasPrice: '0xb2d05e1b', - hash: '0x25553d98cc5c2758b653b122a461e08250a0613752258ff1ecbea813632f08ef', + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0x2cda41645f2dbffb852a605e92b185501801fc28', + gas: '0x5208', + gasPrice: '0x4cf8963187', + hash: '0x75cc3c7d744f1b6ebad382ba5c4bbe53350798cf73ea8a260c6bf2e13eed93cb', input: '0x', - nonce: '0x19f7', - r: '0x82c42ae6667858b3edc1fa02d3016900341786d0e17bdc2ef1e3e3107c0d0314', - s: '0x14c9a378c116c1dc4b5492493e11ecdd046c7b433dd006d8b92ac65fe722add4', - to: '0xa3c3f6a0e31362fb240ce2766ebe9ff9e18fc9d1', + nonce: '0x802e3', + to: '0x34131af964256efdad03f358ef26f6e52f2cbd12', transactionIndex: '0x3', + value: '0xb1a2bc2ec50000', type: '0x0', - v: '0x1546d71', - value: '0xde0b6b3a7640000', + chainId: '0xaa36a7', + v: '0x1546d72', + r: '0xb1a512681a61dd3608d3277e28dde68f95dc549a1ed46a455024c29ca86c6f73', + s: '0x160539777d6ee0f8144750114eeea450229976b08fee6cc4e0a4a9cc8eccd35f', }, { - blockHash: '0x241dab30227f58633e69fc4128b1c2b09699ec274cd575e39e697c1e460e5791', - blockNumber: '0x3148fe', - chainId: '0xaa36a7', - from: '0x8c6484155c97eea1c2770c2952a99888b6ae9c3f', - gas: '0xf618', - gasPrice: '0xb2d05e1b', - hash: '0x5b7ae021605d0fad23fd882d48762851858bf0b6188641d619481f5ea230c502', - input: '0x', - nonce: '0x19d8', - r: '0x334c062cdd23a1a8fcae387e9d3c3e8704728fda13c7d2c0052ddedbb90e1b35', - s: '0x5a25e1af29531c78a1653a2d4136a5688437d29a3ceec2d2d3da537bc57f4152', - to: '0x76fa422f8aa368d09bd93016c76c2dcf889306eb', + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0xba626027dcdae0343a9a727e00bc2d0f566fe34c', + gas: '0x35ceb', + gasPrice: '0x37ebb889ae', + hash: '0x72ddcbddde555cd12b458c9ef1c1b95b55e0c99cd266bdf252e8e2d2688d8087', + input: '0xa694fc3a00000000000000000000000000000000000000000000006c7d4a66ca52ef5a80', + nonce: '0x6e', + to: '0x7abf52a91d3d078960bafc9912fa1be248ef6dcf', transactionIndex: '0x4', + value: '0x0', type: '0x0', - v: '0x1546d71', - value: '0xde0b6b3a7640000', + chainId: '0xaa36a7', + v: '0x1546d72', + r: '0x240d18235dc5af3205b9f88fd484d37a5bde7443ffa5908dcfbfd2bbcf1c661a', + s: '0x08663922369330d95b5669c81830d1c188acadafc9ef31636be9281695fc6401', }, { - blockHash: '0x241dab30227f58633e69fc4128b1c2b09699ec274cd575e39e697c1e460e5791', - blockNumber: '0x3148fe', - chainId: '0xaa36a7', - from: '0x39d2ba91296029afbe725436b4824ca803e27391', - gas: '0xf618', - gasPrice: '0xb2d05e1b', - hash: '0x6ff0dbf6f27ac5bd4cedebca54424e4ddf5bc6db1aeba945c2d980e7d759e5c5', - input: '0x', - nonce: '0xb747', - r: '0xae33f8741cdf375ef0a3978f94b8e61057c8dc387cd28ee3a6d84a574a060b95', - s: '0x141acb4124481f63e871c8f3f29f2adf28954ed42e47770fd112a83b0ef1c35e', - to: '0x203c2affd9bf0026b618fbb3983eba728d2b1cf5', + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0xb3a29e6bee26663772e4d9d38b453a5add44433e', + gas: '0x1e8480', + gasPrice: '0x3350642105', + hash: '0x66666900f2d02bd946a2036fe6e6c51071d369201f9eeba3f8b6fd4b5eee2d9d', + input: '0x58a997f6000000000000000000000000ff34b3d4aee8ddcd6f9afffb6fe49bd371b8a357000000000000000000000000ec46e0efb2ea8152da0327a5eb3ff9a43956f13e00000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000000000000000000000000000000000000000030d4000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000', + nonce: '0xde', + to: '0xc94b1bee63a3e101fe5f71c80f912b4f4b055925', transactionIndex: '0x5', + value: '0x0', type: '0x0', - v: '0x1546d71', - value: '0xde0b6b3a7640000', + chainId: '0xaa36a7', + v: '0x1546d72', + r: '0x55eba31c79800c84cd1044fea5ff8c38e8ffb8a864e59fba801ca363083016ee', + s: '0x069e6a5978542b2f2ffb474e6f44aae1dbf29557cb04660988aace9402781d09', }, { - blockHash: '0x241dab30227f58633e69fc4128b1c2b09699ec274cd575e39e697c1e460e5791', - blockNumber: '0x3148fe', - chainId: '0xaa36a7', - from: '0x9c193fb011cce9c176ba3e9a9f58dd02489437a8', - gas: '0xf618', - gasPrice: '0xb2d05e1b', - hash: '0x234db0c295cf5d70729dc85b36a3df18007c80e1e6c5dd3465f739be81b062c5', - input: '0x', - nonce: '0xb62e', - r: '0xe38f1b6fac252e016f3e846eb61894ed4379cd984838d1a0b694af4b7ed80881', - s: '0x37d9434359fd0afb45b08856915d7a35d57593e0ef3da9d6d3957f181181aef8', - to: '0x29c2e3d277b851a6486ad69bf9ec227fb9b2017a', + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0x60bf9b6395e5582c52dfb9867c286828d2f846b4', + gas: '0x8d975', + gasPrice: '0x2f76992201', + hash: '0x26c7693fdc8fdbf1091d247ab04f451b271cc2a7143d7ac4d1e1eaa46239d83d', + input: '0xd52471c100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000002b740000000000000000000000000000000000000000000000000035276b0e1408ad00000000000000000000000060bf9b6395e5582c52dfb9867c286828d2f846b4000000000000000000000000000000000000000000000000002aa1efb94e00000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000005de010000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000014000000000000000000000000060bf9b6395e5582c52dfb9867c286828d2f846b400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', + nonce: '0x98', + to: '0x35a54c8c757806eb6820629bc82d90e056394c92', transactionIndex: '0x6', + value: '0x35276b0e1408ad', type: '0x0', - v: '0x1546d72', - value: '0xde0b6b3a7640000', + chainId: '0xaa36a7', + v: '0x1546d71', + r: '0xb07ed5088bccda706b11c1d2acdc449733c2b69894857a928107403de478faa8', + s: '0x77ac9b667ed867e66070da74dae481f8de6e8ea7bc283d4549af6b2f64acb95c', }, { - blockHash: '0x241dab30227f58633e69fc4128b1c2b09699ec274cd575e39e697c1e460e5791', - blockNumber: '0x3148fe', - chainId: '0xaa36a7', - from: '0x086d404656dfa47972f8647271a1cd1456e2657c', - gas: '0xf618', - gasPrice: '0xb2d05e1b', - hash: '0x745ebf4cddbadb01df7eb32e393df6f712bad3d6f45d935151eb402fa2bee5d6', - input: '0x', - nonce: '0xacf8', - r: '0x8c8e4f396124ef46c5f4ca96108fa37de7b1ae67445eab91be23094e5d0fafa2', - s: '0x721509d52b20ab40d76d53415f9899bfbe546a241a1a4283508a5c70a1df12e9', - to: '0xed8814e2af46748658f96998596cfca17df94360', + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0xf845f65b1e6b871b01236046f4bf8b0ce5d17244', + gas: '0x40220', + gasPrice: '0x2ac2fe1b84', + hash: '0xe68e725c220c97ff5a7cbb8d570eba2d78d4609ac0f90909ad9dfb916b19bed5', + input: '0xdef57e5400000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000066fb18d00000000000000000000000000000000000000000000000000000000000000363000000000000000000000000f845f65b1e6b871b01236046f4bf8b0ce5d17244000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002d0b00000004000000000b00000004000000000b00000004000000000b00000004000000000b000000040000000000000000000000000000000000000000000000', + nonce: '0x282', + to: '0x0b752a106915f2ff93b24dcbc475c3f5134f560c', transactionIndex: '0x7', + value: '0x0', type: '0x0', + chainId: '0xaa36a7', v: '0x1546d72', - value: '0xde0b6b3a7640000', + r: '0xb88635f0f83a9562913e4f805c5517b069db01ee09fe30042b2fc5d40efc77d9', + s: '0x1a094d699409b124a17ebe61f4b5f660c60b68136fa3eb2026c2cbb6e5a499ea', }, { - blockHash: '0x241dab30227f58633e69fc4128b1c2b09699ec274cd575e39e697c1e460e5791', - blockNumber: '0x3148fe', - chainId: '0xaa36a7', - from: '0xf555e6826bcca97e5cdd649fc8a648b6465b0e76', - gas: '0xf618', - gasPrice: '0xb2d05e1b', - hash: '0x35607880ee334b3e5a2bfc419aa32d4ec2b87445a0c58b347c945265ffc8e57e', - input: '0x', - nonce: '0xb4cd', - r: '0xc5b971c8e80eeb211366f03c486dd97189d640b45d7ebada8ac40d0ea402427d', - s: '0x1b18cb0e10ea701f2b81dd37442afd63f98b7d1d6e57524c03af8721e5207c39', - to: '0x93dc0eae2a8a63829ec1ac09096a00b84c2d11d1', + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0xa1a05af7d0cda269dbce3dd0a557eceba29ea53d', + gas: '0x7a1200', + gasPrice: '0x28d797c046', + maxFeePerGas: '0x2e90edd000', + maxPriorityFeePerGas: '0xa717a48f', + hash: '0xda794cc60352fefb6f2ba63cd0316db0c9dd27ec6d86c485ede06944c35dd7e5', + input: '0xb1dc65a40001b698aa6a21f0b555ab585d47581a5e75d461ebc48266c0e3f218c7bb789500000000000000000000000000000000000000000000000000000000009b01033cd2c1764c9c2a9780bf09e9c8aedeff9c6387712adaba3b68e1d7708445679e00000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000002c001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000304611b6affba76a0000000000000000000000000e11be8c6b410000000000000000005b49a2d90c000000000000000000000000000000000000000000000000000000000000000221670008c44809e5b2ec624f46f129317ac2ed8ac50b58800a28eb78e4dbe50b9de19ef3a15a347439e174f9fbeb5a24d5e78d4e1845666cc499ec54175f77ae000000000000000000000000000000000000000000000000000000000000000267a0022dfece7b3865a13cdc90fda9bca52ffa9cbd39e069dd743777d3cc64a576af3a5088d0743b0d85b4afa09cb510a698fc1de2b87bbb1f5df95a54676920', + nonce: '0xefbb', + to: '0x02279e88601f6a66b225ad78949a3739d2c8b12c', transactionIndex: '0x8', - type: '0x0', - v: '0x1546d72', - value: '0xde0b6b3a7640000', + value: '0x0', + type: '0x2', + accessList: [], + chainId: '0xaa36a7', + v: '0x0', + r: '0x069f9ee74d58ee2af07602839d581683fdb43ca4103a05c9535d3964c9ae2eb6', + s: '0x520f28b97b0b1a2d2b0cee71d0afa8b8460d07734794f83257fa8e4b22816843', }, { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0x833222a4b0a2a20bd6d8cfbd14902e366841525c', + gas: '0x1e8480', + gasPrice: '0x28a7b5afb7', + maxFeePerGas: '0x48376436d1', + maxPriorityFeePerGas: '0x77359400', + hash: '0x35aabcf773f5121f01730f7ae9ef497cd7e7f941b3cfd59304f8bac90e54cec4', + input: '0x58a997f6000000000000000000000000ff34b3d4aee8ddcd6f9afffb6fe49bd371b8a357000000000000000000000000ec46e0efb2ea8152da0327a5eb3ff9a43956f13e0000000000000000000000000000000000000000000000d8d726b7177a8000000000000000000000000000000000000000000000000000000000000000030d4000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000', + nonce: '0x22', + to: '0xc94b1bee63a3e101fe5f71c80f912b4f4b055925', + transactionIndex: '0x9', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x241dab30227f58633e69fc4128b1c2b09699ec274cd575e39e697c1e460e5791', - blockNumber: '0x3148fe', chainId: '0xaa36a7', - from: '0xfed9f12df6a0d72a9ad4a4875a6153e737c8b980', - gas: '0x131dd', - gasPrice: '0x9502f909', - hash: '0xb3f527bc8306499630857a4d92578b2d492762e7828580af536ed10128953327', - input: '0xa9059cbb000000000000000000000000c1b7d14504f8441db63d0175cb4ed985d71c15bf0000000000000000000000000000000000000000000000000000000000002710', - maxFeePerGas: '0x9502f912', - maxPriorityFeePerGas: '0x9502f900', - nonce: '0x3', - r: '0xc98fb9abe0676d6a7101982010b3bc37d727c5cd2189a91710804a5ee98ff768', - s: '0x27c6fbb3ebd78df9dac8c292c6a9bd543f7538f5bd18883ad5ffa1c41dbd93da', - to: '0xf03df67abef78b29b2381f529651ab07d55bd42d', - transactionIndex: '0x9', + v: '0x1', + r: '0x5864243588331ef4aa536a32ffee6ac5743983c3aaa2d8b3d746901e759c5f07', + s: '0x23659fd450833dc71086144f62b19de008a8b9599f2406feddae3bcc1ff1b8e7', + }, + { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0xb1e97957a4f453219a5bab69012715ca662d8053', + gas: '0x1114f', + gasPrice: '0x28a7b5afb7', + maxFeePerGas: '0x4948180aa9', + maxPriorityFeePerGas: '0x77359400', + hash: '0xa6b563e6faa0908fba5a14606d0a4132ac710887823da37de7589cda4b47328c', + input: '0x095ea7b3000000000000000000000000c94b1bee63a3e101fe5f71c80f912b4f4b0559250000000000000000000000000000000000000000000000d8d726b7177a800000', + nonce: '0x1f', + to: '0xff34b3d4aee8ddcd6f9afffb6fe49bd371b8a357', + transactionIndex: '0xa', + value: '0x0', type: '0x2', + accessList: [], + chainId: '0xaa36a7', v: '0x1', + r: '0xcc0e2ed2c151a33aa6b3eae720923884a6d5598a76b025bfbf15f2474e4aa2cf', + s: '0x5de3db4f71e42ab36cf21c32691406f896286f9219f16e1277c957552199cc3d', + }, + { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0xe956911128b8bc8e33ce9070a1cc8f40a2a84683', + gas: '0x1114f', + gasPrice: '0x28a7b5afb7', + maxFeePerGas: '0x4948180aa9', + maxPriorityFeePerGas: '0x77359400', + hash: '0x6e47abdc2e0ae1bf68a72a26b7b9f476b77955623d7fc6b51729363e556a06f3', + input: '0x095ea7b3000000000000000000000000c94b1bee63a3e101fe5f71c80f912b4f4b0559250000000000000000000000000000000000000000000000d8d726b7177a800000', + nonce: '0x20', + to: '0xff34b3d4aee8ddcd6f9afffb6fe49bd371b8a357', + transactionIndex: '0xb', value: '0x0', + type: '0x2', + accessList: [], + chainId: '0xaa36a7', + v: '0x1', + r: '0xf8d5f468781e8769ff3cd507cb7c536c8f30cdd38bcee54cb8e1f4d9e5ec4bf7', + s: '0x5e03b502c8cc68124be68bca436d6361c0cb03a3869249426f7773c45339abe2', }, { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0x76c4c9f1dc799f720aaf392a6a9ce14f4f78dfb3', + gas: '0x1114f', + gasPrice: '0x28a7b5afb7', + maxFeePerGas: '0x4948180aa9', + maxPriorityFeePerGas: '0x77359400', + hash: '0xf190a73725b4e35e9c62cd12ae2cad28042d64875a3120d066b20639ac3f441d', + input: '0x095ea7b3000000000000000000000000c94b1bee63a3e101fe5f71c80f912b4f4b0559250000000000000000000000000000000000000000000000d8d726b7177a800000', + nonce: '0x20', + to: '0xff34b3d4aee8ddcd6f9afffb6fe49bd371b8a357', + transactionIndex: '0xc', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x241dab30227f58633e69fc4128b1c2b09699ec274cd575e39e697c1e460e5791', - blockNumber: '0x3148fe', chainId: '0xaa36a7', - from: '0x6cc9397c3b38739dacbfaa68ead5f5d77ba5f455', - gas: '0x5208', - gasPrice: '0x77359409', - hash: '0x59b21c5451f4c6bbaef6758aa4ddac3d350ee9d6f7f79cbc8aea1e4d6d30f32a', - input: '0x', - maxFeePerGas: '0x2e90edd000', + v: '0x1', + r: '0xdad8489f79173d5c597fd21edeb72bf0a1f2c8c927d25c4cc3aea1babf28c760', + s: '0x4be6886f2237af4750897d5370a7cd8515f7dad03a3596ce4bd72f8a4fa1528c', + }, + { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0x8ac38b4c4a570b8d4c78d3a409ca0ab713bfcc4b', + gas: '0x1114f', + gasPrice: '0x28a7b5afb7', + maxFeePerGas: '0x4948180aa9', maxPriorityFeePerGas: '0x77359400', - nonce: '0x1abd5', - r: '0xbaf97590694daf5555139cbafa03406fe7d158f203d5b0b45ece306aab1af770', - s: '0x2359e6e389613e518025c2d0f2ac9749499c46118af96fb007f9f523b56bd54d', - to: '0xa127c5e6a7e3600ac34a9a9928e52521677e7211', - transactionIndex: '0xa', + hash: '0xae5721f9c9ee178a4a3e651c0732e5cd260bed24663f5e5f70670a181d426cfc', + input: '0x095ea7b3000000000000000000000000c94b1bee63a3e101fe5f71c80f912b4f4b0559250000000000000000000000000000000000000000000000d8d726b7177a800000', + nonce: '0x1d', + to: '0xff34b3d4aee8ddcd6f9afffb6fe49bd371b8a357', + transactionIndex: '0xd', + value: '0x0', type: '0x2', + accessList: [], + chainId: '0xaa36a7', v: '0x0', - value: '0x53222d0fbe8000', + r: '0x2df927d26751364514dd427f5353059fb995e3aecd45806aaf198c7238fea10f', + s: '0x14ac0f1278770a0a71defcc1e81ef01d69b24d227d49d7284281ba75cbfc07df', }, { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0xacdbbe9425387110952d14f29253a2a86074d2f9', + gas: '0x23d2c', + gasPrice: '0x2889e84ab7', + maxFeePerGas: '0x3a2c76600e', + maxPriorityFeePerGas: '0x59682f00', + hash: '0xa84f8c29a46e8003e0d45fad85cb04b0a883814cdcc50c79668c79f6fe26f8fb', + input: '0xb79092fd0000000000000000000000000000000000000000000000003782dace9d900000', + nonce: '0x148', + to: '0x619891efb7049c64b52e2d787d42d46ea1d36fe7', + transactionIndex: '0xe', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x241dab30227f58633e69fc4128b1c2b09699ec274cd575e39e697c1e460e5791', - blockNumber: '0x3148fe', chainId: '0xaa36a7', - from: '0xea4d57b2dd421c5bfc893d126ec15bc42b3d0bcd', - gas: '0x55f0', - gasPrice: '0x59682f09', - hash: '0xe3708d5286b2a3fdb73db6b9409c70e121e65cd5896682f011e97b578906245c', - input: '0x', - maxFeePerGas: '0x77359400', + v: '0x1', + r: '0xfc257a7a1ba9bb455b60a8053a080b457ea88ae228b0a56fcc18aaef804f92f6', + s: '0x4adc0c444b67b685b2ed638e5f84ec474b5fa3026660078b4defc733b4c96009', + }, + { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0x9e1c950e743ec4f6afec299dcdff1bbc21bb2b3b', + gas: '0x1e8480', + gasPrice: '0x2889e84ab7', + maxFeePerGas: '0x3a2c76600e', maxPriorityFeePerGas: '0x59682f00', - nonce: '0x1602d', - r: '0xa3811d6c91a939c9a684eb1061c090c1459de3817cf6dfb02b57c344bdffb10d', - s: '0x2d2410b861ad3fc0895e59f918d9945dc888c48f1fdb032307fa4759ecc16843', - to: '0x4acc290a701ff39da78cde151176dee141b70656', - transactionIndex: '0xb', + hash: '0xc75a978c195d19b4ee4bcac2adf597237b8af228d6b2cb7359fe311922d6638c', + input: '0xb1a1a8820000000000000000000000000000000000000000000000000000000000030d4000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000', + nonce: '0x5a', + to: '0xc94b1bee63a3e101fe5f71c80f912b4f4b055925', + transactionIndex: '0xf', + value: '0x14d1120d7b160000', type: '0x2', + accessList: [], + chainId: '0xaa36a7', v: '0x1', - value: '0x6f05b59d3b20000', + r: '0x98aa877fa955a2188d4be855baeb4360150b210216d21f6b9bed9e3f656c5f5f', + s: '0x6d79b7ba8a80e1708e2394900efc812d484b2412aa49aae2dd961545a98bad84', }, { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0x14f0da42ba8728c5dd998b76a8bf3fe4c1e9fbdf', + gas: '0xb7fa', + gasPrice: '0x2889e84ab7', + maxFeePerGas: '0x3a2c76600e', + maxPriorityFeePerGas: '0x59682f00', + hash: '0x02311edfcca59505ef38e680a53fd7a380d163f2a4887515e98610e7afce1252', + input: '0xa22cb4650000000000000000000000009e7b172d207d5ac8d49136d8643830df8ca7e53c0000000000000000000000000000000000000000000000000000000000000001', + nonce: '0x166', + to: '0x14fc960b8cd3a2fb10973fbb5789e5908ef6dab9', + transactionIndex: '0x10', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x241dab30227f58633e69fc4128b1c2b09699ec274cd575e39e697c1e460e5791', - blockNumber: '0x3148fe', chainId: '0xaa36a7', - from: '0xb47300dc06756ab667b47d87523f9e3f44967db6', - gas: '0x5208', - gasPrice: '0x59682f09', - hash: '0x738a0a811d13a8735bd7b5ea4b784a0dff23e6bfd2b1897303f731bb49ef19bb', - input: '0x', - maxFeePerGas: '0x59682f0a', + v: '0x0', + r: '0xb4639ea52f2ecddab355f4ea0f76d911631f47354f5f07c6401e02773c0ef4c3', + s: '0x6c32197b408ea64d2c69cbba275d821591ea13a77806641758cb3148cb98a05a', + }, + { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0xfc094413ae9b30bb9957993b86238729b390ba28', + gas: '0x389f2', + gasPrice: '0x2889e84ab7', + maxFeePerGas: '0x3c0e07ad05', maxPriorityFeePerGas: '0x59682f00', - nonce: '0x4', - r: '0xfc0ab73abf97792641c05c82911ca19f77816ad45ca95bd0053c77044ce31bce', - s: '0x79c4de0d3e8d022cc449298a4abdcaf31fbfba8be042684bab86393893db2d4b', - to: '0x337381cc3d723b86a2acb97f34832d4673cbb5f8', - transactionIndex: '0xc', + hash: '0x057371fc02b3b6eb653f6114e426f42f985c0db1bc072ca02975e2976b468a9a', + input: '0xd52471c100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000002b74000000000000000000000000000000000000000000000000000be5d8a0427d54000000000000000000000000fc094413ae9b30bb9957993b86238729b390ba28000000000000000000000000000000000000000000000000000000d18c2e28000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000006412f00000000000000000000000000000000000000000000000000000000000003200000000000000000000000000000000000000000000000000000000000000140000000000000000000000000fc094413ae9b30bb9957993b86238729b390ba2800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', + nonce: '0x14', + to: '0x35a54c8c757806eb6820629bc82d90e056394c92', + transactionIndex: '0x11', + value: '0xbe5d8a0427d54', type: '0x2', + accessList: [], + chainId: '0xaa36a7', v: '0x0', - value: '0xde0b6b3a7640000', + r: '0xe480d30799d52a56cc709fa915769b403bd6a65a53a9dbc4c5e5195702c2cf54', + s: '0x5c7569c8c78a2cfe505c13302911cb21a3419bc9523db8ffa7ade94e4728236e', }, { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0x5807f8e3418ed4b7067d08e7140bf49df3b04f91', + gas: '0x1e8480', + gasPrice: '0x2889e84ab7', + maxFeePerGas: '0x3a2c76600e', + maxPriorityFeePerGas: '0x59682f00', + hash: '0xf8ff44a14a651fa9b4a353730f09f65a78e672c4bb468eeb51c0eb00d0dac0db', + input: '0xb1a1a8820000000000000000000000000000000000000000000000000000000000030d4000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000', + nonce: '0x1b', + to: '0xc94b1bee63a3e101fe5f71c80f912b4f4b055925', + transactionIndex: '0x12', + value: '0x1c087b4c2e4a0000', + type: '0x2', accessList: [], - blockHash: '0x241dab30227f58633e69fc4128b1c2b09699ec274cd575e39e697c1e460e5791', - blockNumber: '0x3148fe', chainId: '0xaa36a7', - from: '0xe3a97e0d58e58f9871fdd7d9a74d061cc3736bbb', - gas: '0x17ab1', - gasPrice: '0x59682f09', - hash: '0xd63d4edc0ca6567cea22cb342eda67d37bd4a5a5a36cb66e233f368a8f98c7cb', - input: '0x96e1785200000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000e3a97e0d58e58f9871fdd7d9a74d061cc3736bbb0000000000000000000000000000000000000000000000000000000000aa36a70000000000000000000000000000000000000000000000000000000000028c5c000000000000000000000000e3a97e0d58e58f9871fdd7d9a74d061cc3736bbb000000000000000000000000e3a97e0d58e58f9871fdd7d9a74d061cc3736bbb000000000000000000000000e3a97e0d58e58f9871fdd7d9a74d061cc3736bbb00000000000000000000000000000000000000000000000006f05b59d3b200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007fe5cf2bea000000000000000000000000000000000000000000000000000000000000000222e000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x59682f0a', + v: '0x0', + r: '0x6dc2971c254047002c8ff765eae1d594d45f58ed3dc5a5c793b8fe2602ab44c1', + s: '0x782508816319ab9ddafc61246c61b45526ee8818bd945a6a80230eacdfa69711', + }, + { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0x0b5875dc4c9b9c7c17ebf265a3042d9b9e0bed3e', + gas: '0x1e8480', + gasPrice: '0x2889e84ab7', + maxFeePerGas: '0x3a2c76600e', maxPriorityFeePerGas: '0x59682f00', - nonce: '0xf', - r: '0x95c807dbb20dacd1715759f369eb08c5b0cd431d42170bc44b62210a7adc7161', - s: '0x1c8ae2ba0a32668e606edd3d9792e96e54a033365d0d9a209456dd0572fccf41', - to: '0x2ab7c0ab9ab47fcf370d13058bfee28f2ec0940c', - transactionIndex: '0xd', + hash: '0xdcf062bb7d0217833dbcdaf4b2320df7d99a6e10cecfb0fe383afeaafb30fe5a', + input: '0xb1a1a8820000000000000000000000000000000000000000000000000000000000030d4000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000', + nonce: '0x53', + to: '0xc94b1bee63a3e101fe5f71c80f912b4f4b055925', + transactionIndex: '0x13', + value: '0x1bc16d674ec80000', type: '0x2', + accessList: [], + chainId: '0xaa36a7', v: '0x1', - value: '0x7704128ff9c0000', + r: '0xfdd84f5146237fa0c87e73bfb67b59d101b1f9e57d7a52c5d3b4be98c701a105', + s: '0x7bd5e8beb6bd4ec3f7bdd2b399757ff58fa7de582dd2e45b5020b6f681a5a41a', }, { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0x84a737a9daebb755120faeebd05d4941f010dbe6', + gas: '0x43893', + gasPrice: '0x2889e84ab7', + maxFeePerGas: '0x3bd4d718b0', + maxPriorityFeePerGas: '0x59682f00', + hash: '0xb8cceca254a0f17f894ec1684ee6ec54fa8e5bb40f06c9caff9a31e69888e199', + input: '0xa5b7e17800000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000003b9aca630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a6368616e6e656c2d3930000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014d2e4927078f6b89ac73da293163a56aef6b4919300000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000001c7d4b196cb0c7b01d743fbc6116a902379c723800000000000000000000000000000000000000000000000000000000000f42400000000000000000000000000000000000000000000000000000000000000014323032342d30392d33302d2d30302d33342d3234000000000000000000000000', + nonce: '0x1e', + to: '0xd0081080ae8493cf7340458eaf4412030df5feeb', + transactionIndex: '0x14', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x241dab30227f58633e69fc4128b1c2b09699ec274cd575e39e697c1e460e5791', - blockNumber: '0x3148fe', chainId: '0xaa36a7', - from: '0x59aa96058b9e61588c3b4bb6800ea4aa48ef0492', - gas: '0x17aa5', - gasPrice: '0x59682f09', - hash: '0xd383977c4ab373914a2199b5673eb43b1cb3c86a129c29a440b67b8ee491bad2', - input: '0x96e178520000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000059aa96058b9e61588c3b4bb6800ea4aa48ef04920000000000000000000000000000000000000000000000000000000000aa36a70000000000000000000000000000000000000000000000000000000000028c5c00000000000000000000000059aa96058b9e61588c3b4bb6800ea4aa48ef049200000000000000000000000059aa96058b9e61588c3b4bb6800ea4aa48ef049200000000000000000000000059aa96058b9e61588c3b4bb6800ea4aa48ef0492000000000000000000000000000000000000000000000000002386f26fc100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007fe5cf2bea000000000000000000000000000000000000000000000000000000000000000222e000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x59682f0a', + v: '0x0', + r: '0x5ea12ab046fc93c7867ee5ebc3489dce283eb71774fcc0ff8a0be843172ba566', + s: '0x724dcae2656c6b944187259f19c006a7fa7a61022bee2020fef8c6b86e786a58', + }, + { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0x05b362a7bf99d114597d015fd66cdc29bf5238b3', + gas: '0xb653', + gasPrice: '0x2889e84ab7', + maxFeePerGas: '0x3bd4d718b0', maxPriorityFeePerGas: '0x59682f00', - nonce: '0x1a', - r: '0xcc783d6b756263a49826c016982daa7ec589d1d55fafc3964ba187bf488bac0f', - s: '0x10d1019e31e0a2956586a382e73b96f8986a6f49eacad9533add0c6d3deb8741', - to: '0x2ab7c0ab9ab47fcf370d13058bfee28f2ec0940c', - transactionIndex: '0xe', + hash: '0x5c9fb5b701b5d05e8012c05e1f88c534cce03d1a880c20848c6534f86b331233', + input: '0x095ea7b300000000000000000000000086e55b81cf6a86b9efb630c0e6ad91e53a509a350000000000000000000000000000000000000000000000056bc75e2d63100000', + nonce: '0x1e', + to: '0xa94859ee2d59aedb2c776722ccae12e1a08f829c', + transactionIndex: '0x15', + value: '0x0', type: '0x2', - v: '0x1', - value: '0xa36cc19bab0000', + accessList: [], + chainId: '0xaa36a7', + v: '0x0', + r: '0x1d33a9c185ca67d8837ce62b4326de99b7fcd7f33272023bee645be527c7f8f2', + s: '0x4bbc38312fd1e8a918e2940495d3a5d116014892c987d22b217fc7f6ed9a553b', }, { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0xcca5b188b99605981136af15a994707bb8b43216', + gas: '0x12c58', + gasPrice: '0x2889e84ab7', + maxFeePerGas: '0x3bd4d718b0', + maxPriorityFeePerGas: '0x59682f00', + hash: '0xb139f91cff2b7bca7c0bd4ed942bc1d6c126ffdd7c3fdf475f5d7eccd3cfc6d7', + input: '0xde5f72fd', + nonce: '0xa6', + to: '0x5589bb8228c07c4e15558875faf2b859f678d129', + transactionIndex: '0x16', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x241dab30227f58633e69fc4128b1c2b09699ec274cd575e39e697c1e460e5791', - blockNumber: '0x3148fe', chainId: '0xaa36a7', - from: '0x877e0fa351f2014157f28af9c1dbe7922c42def8', - gas: '0x36500', - gasPrice: '0x59682f09', - hash: '0x554c50ff5d6578a8ea4a352651106151d0d4b5fc683fc4071096463744b3013a', - input: '0xee1490b20000000000000000000000000000000000000000000000000000000000028c5c000000000000000000000000877e0fa351f2014157f28af9c1dbe7922c42def80000000000000000000000005b9fedd37f0b92e7e282b19cebcf06f57b77c6040000000000000000000000000000000000000000000000015af1d78b58c4000000000000000000000000000000000000000000000000000000000000000222e000000000000000000000000000000000000000000000000001b88957d0260000000000000000000000000000877e0fa351f2014157f28af9c1dbe7922c42def800000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x59682f0a', + v: '0x1', + r: '0x795e754a52f68962b6693a7af5442851317d871d94071a688b1676dccd7e18db', + s: '0x4ab670a37e9e003a87759cd1b30cfd710718587203c2faf8c83ed7a18e46abfe', + }, + { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0xd5b4efe925539258aa805fc920d8df2ecefafb53', + gas: '0xd867', + gasPrice: '0x2889e84ab7', + maxFeePerGas: '0x3a2c76600e', maxPriorityFeePerGas: '0x59682f00', - nonce: '0x4', - r: '0x19a785d3beb63d2dce1c835d847e86293abc590503ee1fd3beb93a0fc4b6cae0', - s: '0x5313cb8e23be69b7507a15179012c9e41ba0c2e3de4d4bc38c4b0501348c821c', - to: '0x4284890d4acd0bcb017ece481b96fd4cb457cac8', - transactionIndex: '0xf', + hash: '0x228df1f5c02744e2ec623906df75bb4445b4df0b1e4a38ba71daaed91ea37f60', + input: '0xc63d75b6000000000000000000000000d5b4efe925539258aa805fc920d8df2ecefafb53', + nonce: '0x1bb', + to: '0x800ec0d65adb70f0b69b7db052c6bd89c2406ac4', + transactionIndex: '0x17', + value: '0x0', type: '0x2', + accessList: [], + chainId: '0xaa36a7', v: '0x0', - value: '0x1b88957d0260000', + r: '0xa093ca86d72c7f26c2b06bf4fdb5549e214f8cff2031165d1329cbf61a0841a1', + s: '0x31ca2eb2819f85bd12f84db09c413accd7d424270a14cb73d53cf9c0eac562d5', }, { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0xd333fce833efa8639b81e19399f85263cb7e4acb', + gas: '0x1e8480', + gasPrice: '0x2889e84ab7', + maxFeePerGas: '0x3bd4d718b0', + maxPriorityFeePerGas: '0x59682f00', + hash: '0x1b54cf530ed26e051e395baf9f860b27602fae051ed5942733d22f2eb02d9330', + input: '0x4870496f00000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000353700000000000000000000000000000000000000000000000000000000000000004e5bbb1feb3d61ff899470c564f150aee9fbaed6e42ce079dcb0d90b19bcdf3d8aa1e19cc9f28bc8c5913d67e54cfbc818620129adee11e252341b80d586c6d622e6c4fa0d3996721fe1ed38ebb34ed20d6ece6e6541308bc8945cd40808dd380000000000000000000000000000000000000000000000000000000000000380000100000000000000000000000000000000000000000000000000000001b29800000000000000000000000042000000000000000000000000000000000000070000000000000000000000009bcccf1d222539c4c47e4c6f5749e4d5fa33215c00000000000000000000000000000000000000000000000053444835ec580000000000000000000000000000000000000000000000000000000000000004638800000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001a4d764ad0b000100000000000000000000000000000000000000000000000000000001b2980000000000000000000000004200000000000000000000000000000000000010000000000000000000000000c94b1bee63a3e101fe5f71c80f912b4f4b05592500000000000000000000000000000000000000000000000053444835ec580000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000a41635f5fd000000000000000000000000d333fce833efa8639b81e19399f85263cb7e4acb000000000000000000000000d333fce833efa8639b81e19399f85263cb7e4acb00000000000000000000000000000000000000000000000053444835ec580000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000540000000000000000000000000000000000000000000000000000000000000078000000000000000000000000000000000000000000000000000000000000009800000000000000000000000000000000000000000000000000000000000000a200000000000000000000000000000000000000000000000000000000000000214f90211a0e688591cca39b813d2094255b499cdd71f2423d70b8d271b14d628d10208a016a01b6f9d430c03f5d8bbcd116e1d037adac0af91d5444cc7a325537fe9f1a592aea0959d4c125ff329014c5c4388fc7fa9cba6d1fdcf2fe99b46ff7ca95be2fd5d9ea0662d45d34b1f67039c8016a408a2ea4288bd56558e8af3ac3a07ef4cedae5f4ca056137e02e5c32a9a506e1e8525a74a4a3a7f7936203633a8fe3bbac32b8fdce1a0ff822272907b9d1b0ff203f246c0426bcba9c8e51e2fc7872172807f1fba2280a04fbadc2e4121971134d62d875661a22c856ef07b5e2c1b78c554ca122594cabaa0579ea5c6628816baf9b76c55726e7dba9ac48d1cd10c903709bcf3ceb1aab376a057b752eacdcda76ac32ec93a18d08a65dfe319a59093dcc59e302b5879f4abc6a066a1b248000d78b7923b0cd58d4a7c222464b7ba37b1e88e115c10ad5d286e9ca0231744dd2922e9dc86d86c2c90db75ff13515bf88ad259aa4e45a20243f898c7a0816c40527340409d652b2bf06725193102a593b4a2471053a7a1bc9ae0475685a096a975a5d7be5e6e077b80b4b09a9959270e60ac6cdc4863a25744d1716e5d95a09461eb3a1b4378e4ef4349c74c81c7544c89f0b6e708d067a07c8ba3f4b76931a0e15d2f61dbfd6c2ab830b198206c6f1e012242b3f0b86400cab0536e89acf7f5a0bfe45caaf197a7a66a09e741a15b451da8bc84292c0d253ff436125b155461cb800000000000000000000000000000000000000000000000000000000000000000000000000000000000000214f90211a0bd8345922c580da46c9dd690cc667d2272d49974d2be70baf6745eac26b10ab1a047a490d6b9e906641960754f09d969301ffcb6e0e143cb837897be3429b6f84fa0dc5235dc3af896c33e49ab5932990eab4b93fd3bd9cb2f3211ab3a426d486265a04350746ff29628ae86be799e502423e09d85320c01c4b1d06d5548786964cf13a07da274c57b8e24d3f8ea5f9f11b5b3a6857951aafd1be4d1a52f6d45ffdcb9cca024ecdc7c7785f42f06f687d86350bb76f1b2e0000fb073b05d4897a606ca5551a02b0aaba610bc07f00ece7e4497555543582ad7ab620bd44e863abc7927d99564a0e0311a7f4ecf034e288b57f8e90ad0c9767b214257faf6c1c0c79d31e779ebb1a0772229e9436b51fc4bf148622453a6eecdfdde48715e1ace45f27ad60cbed72da034cc3991b35c70210f2f64929e9c697aff3c362615186ece35af25e6f16578dea02cb258b3b485d090b3cae4ce4042e4791e13cf920a1ee6942f4be79358b637c8a09e58b81f423c9171f91ca963b7681961f7f05d0bda6eefae2fce437d807a65f5a09cb7a0171e592f86bca49fcc7d89b460519513befc6dc02eab4d0bcc750f1271a095eff6c1eebfdc5bc3558a50c9366c81e6af654be86a1f4b6373de99565b5054a0f663581742ca25637fa62a94068f4d7998bd8316d97106679e411887f28d2bf0a09d13c6d63856e00c26d468b30976c9d5c97d121e48b112e8a8780bd6fc3dcd1c800000000000000000000000000000000000000000000000000000000000000000000000000000000000000214f90211a072263fc86ca293bfe8d75bcd1388a9055365bb36ffbf7a5cb2495b6f27072ac5a0bd92a3a443a866461da263511d83ecb8dd151b1b03021758705ca5afc3a56bd4a02a54d5718271bee7a549b7061faaff6d4925a68219ededda8a88814b1efd1214a088820444406d3c66e183b31f160727bd1878218d724fa33ae0d09ea569264e08a06d4805fb846410c7c1f1c4fc5140b07b5779bac12aec8fa753c034fc3d2e6837a0a7b8d4d6171a384ba228883691631c5ceeeed0641a2b2b41729b304ed9c0cd4ea00d6fd8fb2a78a2ed9b82dd2a9fd3081b2f7607a8d54c593cd57c2ba405abd130a09e828fed012692a076d3bcd6ec59f8406ce12baf238094cd067107cf2d566f09a04fe997ca8b0ceed08dc8a920cae11044a39b9f5e5eae2928c6979efce47c81d1a0ae9b198e666f768dbc69147ff93dc698b6fbdd7847bfb063be414e94c276217ca00d1081f5f45034f2bc0f7d7d04834e1305a0595a176635a62b34f521f3ac2a99a023afa2c1997a8b2df52fc4443db57faab1da4caea7d4282f8fb6a733fad26efea02fb366b3dd0a60261736645792950445a8f224e903a15fa441388e03f5b49f41a0fdf658f9c7cac05a54bdf0997b62e96c08f7cf913cecc173d7ca36c99f34cee9a07a798182b2691d45a41de90ca5b65de74dff42e1dd34c5d82b1866c96df12a25a04f53894154f20233d8f3a6785f6ee7f339643852cb0db5a2ba9c3d85f28654588000000000000000000000000000000000000000000000000000000000000000000000000000000000000001d4f901d1a03637ae78b73fcbba95d7475791b061832b21ea51a036bdc9ff00c20475bd6556a02e57ad8a0554fddd85a1c9f97afe368669cd27967d3d6dcf3aa8861b17cceeeea0b39b037337b214fc05466ac845dc79694c7d67f40e87e9fa60349671f95ddce0a0aef51959b326000774e4786c24fd5421b0a982d8f1d76fc7e9c1e9653c516aa9a015d9b6f93413b11df65e7e18b0dc12748d0f0e893c68c4431ebdebe78b85150fa0505be642e9e57b07a863cf8c5b94bec03f20d3028d760b840c42c9539670078ea047ad26cdd34e1029318559b63e75c22b13f86c0cdc589ce8730ba35ec276b5dfa0577a293e24d0c144c179c86644dd57de254af81e28722e1bbd057be01cb79d7ba058a9a888668f8c5ea4651ed414394b710bda80ec87c9e4f050887fc5fc874158a0cd485414b5973bf1fce10390c84f2ad7655d32f7d4338f068f05505f702eb8f8a07e9b78f12baf2610c571d100e7c76ca9886211807b0c6b5f283f5bc4b40234e48080a01ade7e82fa32c0a3958fe77398c0ec7352664a9e7411ac3ad1ef18a7ebea796ea0198ad3f9debd4df23f1afd16f8f56c37656800fc83cb7de22a695474bf8e1435a082cb5783777bc6d42040f9281e7169a31bb363d364eec5552c295ebcbdd97de3800000000000000000000000000000000000000000000000000000000000000000000000000000000000000073f87180a02bfc67020c97e58cf8d96c58e9295a0bb9656ea2f3f14d167a55430a4eb277c6a0e8d2901dfae795bc0fd30436a3b93addbf7e893c0dbc943f26dcd397bc53064580808080808080a0c5f539e7123ed642ad7e77eaaff37bb61cb2da6f50ef4852a41036d4f540da4d808080808080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000021e09e315be40afb4477bc2be533fa8c417259abdad26f01e58055b94dee1573680100000000000000000000000000000000000000000000000000000000000000', + nonce: '0xbc', + to: '0xb6f9579980ae46f61217a99145645341e49e2516', + transactionIndex: '0x18', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x241dab30227f58633e69fc4128b1c2b09699ec274cd575e39e697c1e460e5791', - blockNumber: '0x3148fe', chainId: '0xaa36a7', - from: '0xb1d1db7481fcb2acaf5765942b8fe4514e18c55c', - gas: '0xb4a7', - gasPrice: '0x59682f09', - hash: '0x92d5693632cfc366be1a143bf63aef7b6307db1227e40d7806d1fb21e67137f7', - input: '0x095ea7b30000000000000000000000004284890d4acd0bcb017ece481b96fd4cb457cac8000000000000000000000000000000000000000000000002b5e3af16b1880000', - maxFeePerGas: '0x59682f0a', + v: '0x0', + r: '0xb63cd5bea8c5114926727677f74fcd6ebd50fae0e2cd05facc6fcdb0424c7e3f', + s: '0x5ed762a398930a078f0cc879c0de0df5287ea04bc87bf71beb00f4da6bf06760', + }, + { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0xd75e4294ec1403174c2e6d0bf0903bc434b3c40c', + gas: '0x1233d', + gasPrice: '0x2889e84ab7', + maxFeePerGas: '0x3bd4d718b0', maxPriorityFeePerGas: '0x59682f00', - nonce: '0x4', - r: '0x535f4d4aa8e5c826549c0d67a65ecfa7847871a214e180a0599ec149a92effce', - s: '0x3b16af47e38f2be732c01bb42d1b35d6d69ec21f631fcdf97c1d393f647aac08', - to: '0x5b9fedd37f0b92e7e282b19cebcf06f57b77c604', - transactionIndex: '0x10', + hash: '0x054e3318eefc580f7b394c185d7bafc91b2c579816f78974bf0deb67358bfed4', + input: '0x1249c58b', + nonce: '0x178', + to: '0xbdead2a70fe794d2f97b37efde497e68974a296d', + transactionIndex: '0x19', + value: '0x0', type: '0x2', + accessList: [], + chainId: '0xaa36a7', v: '0x0', - value: '0x0', + r: '0xed6ced6721b280b4d86ac84943f7ec5c02d5ff7ad8df807930e876a319780285', + s: '0x14f8dd01ed9b13b76e08b89d902ff175ef082cf1cecba5a829f19630a1192ebf', }, { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0xe93685f3bba03016f02bd1828badd6195988d950', + gas: '0x106f70', + gasPrice: '0x287806a7b7', + maxFeePerGas: '0x3081b9e075', + maxPriorityFeePerGas: '0x47868c00', + hash: '0x3a3954bb8706acd07922e84ea3129799f2e2e51c839344358cf2647674724050', + input: '0x252f7b01000000000000000000000000000000000000000000000000000000000000006f0000000000000000000000002e5221b0f855be4ea5cefffb8311eed0563b6e870000000000000000000000000000000000000000000000000000000000030d40faa09fed636aa29fda2701ee2e68fcba1e13062bbddad83c57ae289498c65ec8faa09fed636aa29fda2701ee2e68fcba1e13062bbddad83c57ae289498c65ec800000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000f40000000000000000000000004d73adb72bc3dd368966edd0f0b2148401a178e2000000000002b769006fe71bdfe1df69284f00ee185cf0d95d0c7680c0d400a12e5221b0f855be4ea5cefffb8311eed0563b6e870000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000c6a8569660250e00000000000000000000000000000000000000000000000000000000000000147c95ca901313cb3731c0d613376ba84a6206400c000000000000000000000000000000000000000000000000', + nonce: '0x75917', + to: '0x306b9a8953b9462f8b826e6768a93c8ea7454965', + transactionIndex: '0x1a', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x241dab30227f58633e69fc4128b1c2b09699ec274cd575e39e697c1e460e5791', - blockNumber: '0x3148fe', chainId: '0xaa36a7', - from: '0x8257f8eb8b24a8a8be5dc570dfea56d313339da6', - gas: '0x5b8d80', - gasPrice: '0x59682f09', - hash: '0x72bb6a4add14cb640948ebd801898076372c86bf2eac41154f414738da1d1a32', - input: '0xb1dc65a40001cd794ebe9e15991da9e85cede9ba7e00f407a77e6e7c91fec8c52515aff7000000000000000000000000000000000000000000000000000000000018ae02bfae234dbec1dcbff6f466c498914bcc14f45604fdb229d66827335946592d2100000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000009400000000000000000000000000000000000000000000000000000000000000ac00100010000000101000101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000084000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000007e000000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000280f0000000000000000000000000000000000000000000000000000000000002810000000000000000000000000000000000000000000000000000000000000281100000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000004a00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001a4000000000000000000000000000000000000000000000000000000000000280f00000000000000000000000000000000000000000000000000106322a2b0bca000000000000000000000000046887bd86d18cca57e9e6cb15b3de67318107d3c0000000000000000000000000000000000000000000000000000000000001b600000000000000000000000000000000000000000000000000000000000030d40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000031f5b934a60f2c9b649a657e14f1a2b2e83f8ac7000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000dc2cc710e42857672e7907cf474a69b63b93089ffb23f387bb217874b85e28017885db557c2fc43ad249a67a9ace1beb372bbff70000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000128f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001a4000000000000000000000000000000000000000000000000000000000000281000000000000000000000000000000000000000000000000000106322a2b0bca000000000000000000000000046887bd86d18cca57e9e6cb15b3de67318107d3c0000000000000000000000000000000000000000000000000000000000001b610000000000000000000000000000000000000000000000000000000000030d40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000031f5b934a60f2c9b649a657e14f1a2b2e83f8ac7000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000dc2cc710e42857672e7907cf474a69b63b93089f1ac28f841a31750f6b1e51d99bfe27b6c849bae45963eda319df4d9ccffd87a70000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000129000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001a4000000000000000000000000000000000000000000000000000000000000281100000000000000000000000000000000000000000000000000106322a2b0bca000000000000000000000000046887bd86d18cca57e9e6cb15b3de67318107d3c0000000000000000000000000000000000000000000000000000000000001b620000000000000000000000000000000000000000000000000000000000030d40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000031f5b934a60f2c9b649a657e14f1a2b2e83f8ac7000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000dc2cc710e42857672e7907cf474a69b63b93089f6a4d522654518006fa7a0635541df6dac30d6978e992434835d5cdcfc67d8c09000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000011a300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000b822c253e2eef8c82a895a0a6b0160e90a19b338a3507476113f114d781c664b706bd156aca371e0edf8a64b50fb211ede4dee6521e1316f371ca70e1f8a23d0fee0298af1997c78de533ed09facf1b9c5d772599a63e611cb71c2cd5f6d70b9ad648d5d9c1eb6779f3052cd0b19dd901c497c8b8fb352ecf19bcf020ddfa2aeef6ec6ae42cc7d2e5b1334055984fff0ba453677118eeba8c7b574e8a5a8e9525201fcf1239f0c38ec7c7ef6c27ab0c986372454fe44aca63a2fa6fc2c18d69fdfef89f67cb0b67d429b8ff0c0c164c56d37ed2b485d2c6e1b1f92176e1e4f25ae604f86f4914bc93999a539a7126fc3acaa323290bb0d4ba83e2f4faab74cd9e4c5bb621782e03826d56444a7dcd335c4b0c53ff7885fb97a9a1030180b10f4f535bdbb52018d064ff3f5e65772ab52fdbe8c8b7be34ce7984656859ca40d27c17f1db276c98eea1c46e3647a38c6aab78b3e526e73a57c4b02bd2f739b5534e000000000000000000000000000000000000000000000000000000000000000b3f81065f01ea8076809914067b3f23d37ef688763ffa3abca1f40a979e70e68b4007acd2a670c007944913238eb8ba6f0298227f2410b42fa3a1f0c0f48620e36465bf0d82c6fdf68ffb9e7cee4dc8f593a0fbfe4d2f2da55df96eac8688d6ac20da73d05d8e2b3eed6a90029cbc88bad3988c24803bffc490caf8c197e3d97d593cd78187c91fb6622738da192048d73466f6a63ee9998861324273496d2083642d808408bdb076385472f0547e99630a102096f9f4ac41bf31b0eb5148ead678a4ab1d4ba54f057daf6890c32e9edea25f7bd22e233abe3fb36b0e7f9be6da14d5bce7a84f5d66a0daeb6a1c8aad5e26ad0a2235d00e9c07ba6f7cf3b1c5b2553be10486ee4d282fef1b8a5a4b6e68741b15323bacdb84306bb7b7073677f95afe62e9fec3549a3ef1e8858819f7c21d5863a2fcf805cc64d4316b2eff40a9785e3dcaab9bb6f7d9249aba9d0845bce51066199f7c7875ac4d506a72a238ec', - maxFeePerGas: '0x59682f0e', - maxPriorityFeePerGas: '0x59682f00', - nonce: '0xebc', - r: '0x1bdd1518602b3172a4b5693466cb7e54bc07679c9deca2acbd99bf589d10248d', - s: '0x2a8889157f2264bf396394d10f46facfc5e032dac8b07d720bbc959268509a21', - to: '0xd2ca6d383917259dc2445bd6470dbad386d4b67a', - transactionIndex: '0x11', + v: '0x0', + r: '0xbcc50a02ca5990f13b3deace924c7abd6a1a6abcef0b02cf12c837ddcecc08ee', + s: '0x042c060e8d9429b45133617b342bc4e3fc4f25e53ea2b189db3fdedf4e4941ef', + }, + { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0xb8ff877ed78ba520ece21b1de7843a8a57ca47cb', + gas: '0x1b24d0', + gasPrice: '0x287806a7b7', + maxFeePerGas: '0x3081b9e075', + maxPriorityFeePerGas: '0x47868c00', + hash: '0x4c7368c0d34ea697bc97c50d2359ba2eee8f32518523bd8aa79616e8450ee894', + input: '0x6c459a2800000000000000000000000041bdb4aa4a63a5b2efc531858d3118392b1a1c3d00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000066fb6dc000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000084704316e5000000000000000000000000000000000000000000000000000000000000006f2b20b1a20fd738ed846dfe4d027312bec3d0d83b5ab7b3692749ad2344d061cc00000000000000000000000000000000000000000000000000000000000000142b20b1a20fd738ed846dfe4d027312bec3d0d83b5ab7b3692749ad2344d061cc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082b24b4307902f7326fbf99f3a4c2d2a1fb4f8db9c3a6dd4f0335b2d943c5ecc025785c4a3ea4bdb2899bd4fd1b364b674b61c0147b1e727cc29a4fe245cd6b72f1b673603d1b09c13fa59e775744362d5533c29cd3c1d9414a05fb48bf2db59bfd62b6bfcf4a549a7a29f1b0999a8941e855ca102529c7679a15e2f4f6b83de51881c000000000000000000000000000000000000000000000000000000000000', + nonce: '0x7583c', + to: '0xa6bf2be6c60175601bf88217c75dd4b14abb5fbb', + transactionIndex: '0x1b', + value: '0x0', type: '0x2', + accessList: [], + chainId: '0xaa36a7', v: '0x1', + r: '0x9a27a0f4f5c76d27a2dcf3a2194c772608a9581dabd54ad6db1fbea83674327d', + s: '0x67fa3889772a0f33452a627e319fea69379fa409adc001693cfd51cca47d5bfb', + }, + { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0xe93685f3bba03016f02bd1828badd6195988d950', + gas: '0x106f70', + gasPrice: '0x287806a7b7', + maxFeePerGas: '0x3081b9e075', + maxPriorityFeePerGas: '0x47868c00', + hash: '0x28fc033d69b961f2bcc756e9127f932350ffa1dca72c20eb6337e6b4bc9e0d49', + input: '0x252f7b01000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000002e5221b0f855be4ea5cefffb8311eed0563b6e870000000000000000000000000000000000000000000000000000000000030d409367acd7a279bbc253510994d29b7b0062e34f778fb1ca2ae485892c07d5829a9367acd7a279bbc253510994d29b7b0062e34f778fb1ca2ae485892c07d5829a00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000f40000000000000000000000004d73adb72bc3dd368966edd0f0b2148401a178e20000000000029d6a006ee71bdfe1df69284f00ee185cf0d95d0c7680c0d400a12e5221b0f855be4ea5cefffb8311eed0563b6e8700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000010656db0e7e2412000000000000000000000000000000000000000000000000000000000000001447410fd6d9cafafd4617bc20dbdd8ac278f200a9000000000000000000000000000000000000000000000000', + nonce: '0x75918', + to: '0x306b9a8953b9462f8b826e6768a93c8ea7454965', + transactionIndex: '0x1c', value: '0x0', + type: '0x2', + accessList: [], + chainId: '0xaa36a7', + v: '0x0', + r: '0x3c740b024880b76f3d53a6cdaf20cfe9b6b38ae3f8bad098531ed8f4728b09b3', + s: '0x67b04c776c4b402ae52ad4cc87e8d9008980f0fd85bbfcb21e930d2351e6a442', }, { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0xe93685f3bba03016f02bd1828badd6195988d950', + gas: '0x106f70', + gasPrice: '0x287806a7b7', + maxFeePerGas: '0x3081b9e075', + maxPriorityFeePerGas: '0x47868c00', + hash: '0xdce175cb3adc6c61a28cef7c2ac9be5392a54e0f6f1ef7fde2aaf6560b4b7604', + input: '0x252f7b01000000000000000000000000000000000000000000000000000000000000006f0000000000000000000000002e5221b0f855be4ea5cefffb8311eed0563b6e870000000000000000000000000000000000000000000000000000000000030d403098c0ebc4be331fe9f053aff6b860ea5dfb37c265691e291ab383143fb8cfe93098c0ebc4be331fe9f053aff6b860ea5dfb37c265691e291ab383143fb8cfe900000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000f40000000000000000000000004d73adb72bc3dd368966edd0f0b2148401a178e2000000000002b76a006fe71bdfe1df69284f00ee185cf0d95d0c7680c0d400a12e5221b0f855be4ea5cefffb8311eed0563b6e87000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000108e02ecdb9d227000000000000000000000000000000000000000000000000000000000000001403762bbbe1daed33e1fc3440d5a05ea2c050189d000000000000000000000000000000000000000000000000', + nonce: '0x75919', + to: '0x306b9a8953b9462f8b826e6768a93c8ea7454965', + transactionIndex: '0x1d', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x241dab30227f58633e69fc4128b1c2b09699ec274cd575e39e697c1e460e5791', - blockNumber: '0x3148fe', chainId: '0xaa36a7', - from: '0xea4d57b2dd421c5bfc893d126ec15bc42b3d0bcd', - gas: '0x55f0', - gasPrice: '0x59682f09', - hash: '0xc33480b85a113f779725fd2c1788ab95b066792a898ee0eebb0e98c8fa605989', - input: '0x', - maxFeePerGas: '0x77359400', - maxPriorityFeePerGas: '0x59682f00', - nonce: '0x1602e', - r: '0x1dd8238b1b4eb1148d4b3b6fa829cf047dcf7da6040c14ed1373c6d7c6c1a3f7', - s: '0x2de0a31bec48447a395537d36ef16414fe729ed282585e125fff8d50b7e960fc', - to: '0x0d3a7d69859a0dd6971d39703b15379e05ae2ec4', - transactionIndex: '0x12', + v: '0x0', + r: '0x4116be4105f75aa786befbf3f31d289e1cf85af87c505b32ca9f434bd443a301', + s: '0x107a3e12560837d509260c86f11783c6a535a4915ee3f9a423d392dec2c1ad66', + }, + { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0xe93685f3bba03016f02bd1828badd6195988d950', + gas: '0x106f70', + gasPrice: '0x287806a7b7', + maxFeePerGas: '0x3081b9e075', + maxPriorityFeePerGas: '0x47868c00', + hash: '0x2e2a631ac9ede986145bcd3c156670f2f646e72278c4e3e984e651f7c59d00d2', + input: '0x252f7b01000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000002e5221b0f855be4ea5cefffb8311eed0563b6e870000000000000000000000000000000000000000000000000000000000030d40b718ccf40dc8670cce3a67d21d93480dfd41c60f8fc87d6f4f450500718ce826b718ccf40dc8670cce3a67d21d93480dfd41c60f8fc87d6f4f450500718ce82600000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000f40000000000000000000000004d73adb72bc3dd368966edd0f0b2148401a178e20000000000029d6b006ee71bdfe1df69284f00ee185cf0d95d0c7680c0d400a12e5221b0f855be4ea5cefffb8311eed0563b6e8700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000010656bbe5bc543400000000000000000000000000000000000000000000000000000000000000145c856e0b46f8e875701a66baace6692bff7d6f53000000000000000000000000000000000000000000000000', + nonce: '0x7591a', + to: '0x306b9a8953b9462f8b826e6768a93c8ea7454965', + transactionIndex: '0x1e', + value: '0x0', type: '0x2', + accessList: [], + chainId: '0xaa36a7', + v: '0x1', + r: '0xd0d87ba2f5c90c91259ee44b8fd67bb29e0974960b5b205a62eb4e78b89ec7c3', + s: '0x796588504b8e6ee22684b406bde1d5472dccd52cdddce1ff4a5406e61e2dbe1a', + }, + { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0xe93685f3bba03016f02bd1828badd6195988d950', + gas: '0x106f70', + gasPrice: '0x287806a7b7', + maxFeePerGas: '0x3081b9e075', + maxPriorityFeePerGas: '0x47868c00', + hash: '0x4ce6a35c0e68f90239f8aa5b3f21a04e317ae63c729e20121b3bcffe84b9ccd6', + input: '0x252f7b01000000000000000000000000000000000000000000000000000000000000006f0000000000000000000000002e5221b0f855be4ea5cefffb8311eed0563b6e870000000000000000000000000000000000000000000000000000000000030d4053dc9e8076a21967f69707cd055ab42c9797f156d055dfa8be4953e6300e1b4d53dc9e8076a21967f69707cd055ab42c9797f156d055dfa8be4953e6300e1b4d00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000f40000000000000000000000004d73adb72bc3dd368966edd0f0b2148401a178e2000000000002b76b006fe71bdfe1df69284f00ee185cf0d95d0c7680c0d400a12e5221b0f855be4ea5cefffb8311eed0563b6e87000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000108dfe059eadead0000000000000000000000000000000000000000000000000000000000000014f8e1f87a512db9fdc5fb22e2142114f5c93a19fd000000000000000000000000000000000000000000000000', + nonce: '0x7591b', + to: '0x306b9a8953b9462f8b826e6768a93c8ea7454965', + transactionIndex: '0x1f', + value: '0x0', + type: '0x2', + accessList: [], + chainId: '0xaa36a7', v: '0x0', - value: '0x6f05b59d3b20000', + r: '0xe54d76a3501182c51555b18ed3c8a73b98e094bf2be638b1ae4c1b334bf0949c', + s: '0x0abb59840c2be033120fa497ab887db28dbe1aa937ef4202f2212b7ef00c49c1', }, { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0xe93685f3bba03016f02bd1828badd6195988d950', + gas: '0x106f70', + gasPrice: '0x287806a7b7', + maxFeePerGas: '0x3081b9e075', + maxPriorityFeePerGas: '0x47868c00', + hash: '0x9fd281e4699178dd3fecb22a25142838284e9a1e5c499f0babc790ff82106ef7', + input: '0x252f7b01000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000002e5221b0f855be4ea5cefffb8311eed0563b6e870000000000000000000000000000000000000000000000000000000000030d40c9fddf1203593b7f12653921254723a2823bf884ff1b50721460f5b395afbab7c9fddf1203593b7f12653921254723a2823bf884ff1b50721460f5b395afbab700000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000f40000000000000000000000004d73adb72bc3dd368966edd0f0b2148401a178e20000000000029d6c006ee71bdfe1df69284f00ee185cf0d95d0c7680c0d400a12e5221b0f855be4ea5cefffb8311eed0563b6e870000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000c4c0f8799165a700000000000000000000000000000000000000000000000000000000000000142fe95752e17a83e269379a80f9b63d3dd38290a5000000000000000000000000000000000000000000000000', + nonce: '0x7591c', + to: '0x306b9a8953b9462f8b826e6768a93c8ea7454965', + transactionIndex: '0x20', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x241dab30227f58633e69fc4128b1c2b09699ec274cd575e39e697c1e460e5791', - blockNumber: '0x3148fe', chainId: '0xaa36a7', - from: '0xc88b48a292f0b26d4dedd281b58cc6eabbf857bc', - gas: '0x6dfe', - gasPrice: '0x3b9aca09', - hash: '0xa8685562865ab1e6c73816fad05a38d6ea0670565ef27add5f4bd16db852eb46', - input: '0x0f5022140000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000cd0bfd180d0b8d0b2d0b5d1820000000000000000000000000000000000000000', - maxFeePerGas: '0x3b9aca09', - maxPriorityFeePerGas: '0x3b9aca00', - nonce: '0x27', - r: '0x792a33def1b103539418608bf306204927a964e640e39f379377efeb3af59174', - s: '0x1aba77c1fe4f5fc626ae96e41acb6626c0c567e41a25a6f8c1a957c12a868e69', - to: '0x3a6658a57c5e78cf4b4f6e774bfd1a812865d197', - transactionIndex: '0x13', + v: '0x0', + r: '0x0d8a17a1879d29abec8963fb3a30e68bde4e5fff16a7424dc4f223955f5e281e', + s: '0x7976eb9be591de5e6917af0054d305b1704499321bc5bdf3e17b6a8826b6de75', + }, + { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0x6db8952e4963541c9cc8be7e578e97fcbd37a576', + gas: '0xa037a0', + gasPrice: '0x287210c6b7', + maxFeePerGas: '0x46d54584c6', + maxPriorityFeePerGas: '0x4190ab00', + hash: '0x5daa9ce7f6272210ff526b31480cb390beff9d639ded882cfdefd4e3c92f1d2d', + input: '0xb1dc65a40001efcc06557badbcfc10367afacd814e090b9f7a3c8c3ccc3b96e0657b0ccd000000000000000000000000000000000000000000000000000000011891cb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000003c000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000773594000000000000000000000000000000000000000000000000000010598c7756a64000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000001b4e304b0000000000000000000000000da6e31da65205210e5075a5076742056000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000f42400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000679c37d0d0c837e429cfec5ee6ebe10e8167ce35ee9d84260361b742913d8de878ca630000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002f3fe0e0212921f315f4a7c8bc5b5574f0c61f69560ceeaae814879027f36f4f6d02ac892860ef529510d0a5ef42c5fcbcda07875f4ed93b39bbaaf72816977090000000000000000000000000000000000000000000000000000000000000002789304fdf0a4f6c4bbb378375e6178e253e757ea97a854ea35064e1225a39e757d2bab7793b84c5e092b36f523d830b34a97d99520c37afc5dc1338b093e82b0', + nonce: '0x205d8', + to: '0x86efbd0b6736bed994962f9797049422a3a8e8ad', + transactionIndex: '0x21', + value: '0x0', type: '0x2', + accessList: [], + chainId: '0xaa36a7', v: '0x1', + r: '0x581934e825769017d2d74d96ae206269f625ab9abbd7b8a450d54c1ae4bbd62f', + s: '0x1c58d4330b2bc36a28c914270efa87cb7bffb03b18af501759d1e4cbe09aecf2', + }, + { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0xf612196862dda3106a80022dd37f45b47046c62b', + gas: '0x5450', + gasPrice: '0x286c1ae5b7', + maxFeePerGas: '0x585ac3d85a', + maxPriorityFeePerGas: '0x3b9aca00', + hash: '0x8fa6437b5c4d710ab034504fe4c1f81b6cff05ffd5bec97c96c5692f70fac4ab', + input: '0xcec3062b00000000003c360e994540dd6c6b5de07591dba47f502bf881a2b1fd5e003d614edb7c7688', + nonce: '0x81c3', + to: '0x2edf1084d99e6e9865592edc8ba0c815e691cc2e', + transactionIndex: '0x22', value: '0x0', + type: '0x2', + accessList: [], + chainId: '0xaa36a7', + v: '0x0', + r: '0x8c8886e52e16e95828b14113ba99cb85e82f94f4b0de1fab627ab728f1c5c1cb', + s: '0x5fdd55f6306665c8745a3b5743200f4bc706b1035126d304dfe103d318db617f', }, { - blockHash: '0x241dab30227f58633e69fc4128b1c2b09699ec274cd575e39e697c1e460e5791', - blockNumber: '0x3148fe', + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0xf1fe26e54c971a67e370e1e8eb57805f1f5ff865', + gas: '0x545c', + gasPrice: '0x286c1ae5b7', + maxFeePerGas: '0x585ac3d85a', + maxPriorityFeePerGas: '0x3b9aca00', + hash: '0xe7362584fa34de12abcfb15d918619a7f5c7d8417e8d67637d52a88108b34820', + input: '0xcec3062b0000000000e9c9ebf26190cd64f37d0725454b313de11cbd22cebc5e9bfa98a4a31391a4d2', + nonce: '0xb955', + to: '0xf007b90de8e7a2a71802eb0936f8f66f00ada7ff', + transactionIndex: '0x23', + value: '0x0', + type: '0x2', + accessList: [], chainId: '0xaa36a7', - from: '0x43c92d390d3ed89716e4a0776d8aea1fb965d55d', - gas: '0x2bf20', - gasPrice: '0x3b9aca09', - hash: '0x7cff5abea75fd389d37b08fa73f8d4ea6c2a00f36c715fda422c8d92f05aed78', - input: '0xd45b6292000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000006f05b59d3b20000000000000000000000000000000000000000000000000000000000000000c35000000000000000000000000000000000000000000000000000000000000000020000000000000000000000004384ea50ec75a46a7dda1fd2a928d1280c45695d000000000000000000000000a6147b3802d51f47b348817ad43e647566d6df46', - nonce: '0x5c92', - r: '0xdd56ccd20763ac884900623962a5cd5d7919dff4e5530111bf83b30b21ae2202', - s: '0x4ea28f710dee138499d2f2683cf54325b3646c47d1b380dd4cf67f4f5e012ceb', - to: '0x041eac26aab0d7afe408c3ad3c07ea3f749e7453', - transactionIndex: '0x14', - type: '0x0', - v: '0x1546d71', + v: '0x1', + r: '0x2e7882739cdc332b0f593fa14993b43b98efe68d33ecc8388f7498c1376c4f18', + s: '0x3ea18d910ebff0c590c0149a7d776582c7821a672f04ab2662d83548eeae6115', + }, + { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0x09f9ced4b5f841e4a6255cbbe06f9aa726897ee8', + gas: '0x545c', + gasPrice: '0x286c1ae5b7', + maxFeePerGas: '0x585ac3d85a', + maxPriorityFeePerGas: '0x3b9aca00', + hash: '0x027b0ff3e896e00bfaa74f934d46c5632661fd276e7a928d4c9e9b79037e644d', + input: '0xcec3062b00000000007e932bc184e082a897207c4f3f07b1ce1fe2b46140edff53b78d375991bbcd83', + nonce: '0x1e319', + to: '0xbcad34ad7207db9088e1fcc4cb9382d3dc85355c', + transactionIndex: '0x24', value: '0x0', + type: '0x2', + accessList: [], + chainId: '0xaa36a7', + v: '0x0', + r: '0xc868f6a4ef3b17d1f88f25d644dc8eff60f4c9b290e35212623f6c6aebad8c4e', + s: '0x5c569d7f202550c0c5bdd5b5b5b95ad2f22979927ef29dbe409f51da864cd268', }, { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0x0c2ac914b2378e5afaecbab08a171c769d34947c', + gas: '0x10098', + gasPrice: '0x286c1ae5b7', + maxFeePerGas: '0x554a616d08', + maxPriorityFeePerGas: '0x3b9aca00', + hash: '0xf80502f2719543ba49fe5c7bfda7e0ca517bf237b41653f633b2c633c6dbdffb', + input: '0x006c13f6cf8f0d49c2913d404f2d3dcbde000000000ae0011bd415f83724291f8073825cd06be525aedeb20ed5515ec43217a0c5a725e808a60a4e049a5880a5a054d0d307ae700137040800128000c0f8bd561d943b4d78612c6a016d73b3860a20fa7e6436c43745a9d35a96f75fcf01650d718e92d870d0972c5eb8bc8b269db04a9a8d11c5258e3beb33c94a38be46cc11bb4dcb61a306bcffad5df0e7479aa59ef3ec2bc9c52d37b159a50a87ad13737dddd3bd2e501498e187fc0414b70db2b55db392a7456d89295ae3b6811c88dda4bbc52abd3a5ca6a15f53818741c83acc1790accd5a1e81699dbbe7739e38ec4cf75e49cea93b5f372ecbede8b320e0dbf25baeb5d62936f2c8b5ee2a45e009f78bb035ec78b27f753ecf571542ec726ccddbc0f4858da0e76ce589480cdbf62c7bec6106332e4e8c22d0fdcc3fcccb3cf72a54f1e90ff5c2be2db2334394c9bb910a5d7b2e09f85410bdd60f6aa988c59f2085e3f3bc8504a1476ba68337f07fe98fd35a977ed0b2c516839f1c6cecf084d96f387dd085606cb1232d2af7307b79eacba18202eb873ca6b002e56324ed34ded795d2e0b9117542ab8a6d4107c1190ef2606d184ad61b3a756493ca46e880309657bfec9675cf7b00024b152febd0e35138ca234216359455a4c99069ccbeb17b948f7a01fa0ba1295afc9a39b6b2f8084feae5244f6e56688d5f3a22bb5cfddeb1de6f22e0c206febe0ae67dd5fad04605ac22aee42ccf02f7b7291e39a68098710c201926928ce93de193a7c2c90ddfe05bd0ef4d592d2e663ca10903d2cc5ec464bf6141515ceb4463974fdef6b2f277cdebb8c7e76324cd011fdc454d52fb3673dec07e59b1adf007c79ff80aa7e7352d617a749be0a845571790ab3c2ab23cd75a10250e8a76e9dbb90abe8a78ee9f1aa3e080085d58e941d22b071a7ff30430a295e0ca1d2a476d8b5a79521e1b7075e4f9240937bf1eab460f6086a215f03f0fbec0b05b3f5c917b53b974e42876dbed25b60eba9b926e5840870b99bddf66e726cf430429305895d17d7b7a45904863f468f6d819b86069e1ff6a8ccd29694a1bca5d1ebc95c9df92f55050a866847335fae6bd6402ca27711e1c6d346347bb1e47c3321ee6cbceb01b7ed8671c8fb983f6f943c7ad2f8e9e016b472119d5bd16cd11990a7207fcf093c1fadaf061a30071939cdc07085e7f83e60cc098eec44cfe58e4ffc6cc189ea73c7e8f39284dd19b2b7785e7ab926dd7a7b3d452ec8101c1389883c742915e9c37bc64613b995acca28ceaf3511dd120b18a6bae1024c403be078e1d8943adea60c3545e5a943cf5b6f3527bb03aa7f9159da7ccce1c4cb049ec90c0d12fe0bcb9a53386e55932687946c41ba303c84c3b2b8bc0d583e05476f66ed72e6ef030f5c35294cb6247442118791808575bdb130fc3b714c55e74456d635a35cff822205c09d8d043551f528d5bb066464c3169d659a0ebed120c97c45437f771c696a2545d54d94d7d44c1f9b413700084d77eb4eb187790137c038cdfcc57ecd8e1855f2998717ac7da12c8ded380d25be1e4d12e8bc6c26e835ffa2f8e98dd2c8ff52754f073d77134dd93dc82f031ec9b14c1cb93eb57f76964ea7b2bcd577aa3aab6b101fb6aba0621e80e667a61a275f4bae91d0479bc2c5a761cc2eca3db929fe4e27ffcb0170a197ac9f7cddac932be91f541dce5409427a5f7dd01e36eef27a43c397edd02931cc606403a4e58f5e543ba524cce543b10923c51f1a259cf742c604d018338ae5593ea265a4129811e50d997dd6b0188c567186433f4a1ed6f12f3e686fc372755bf01b9200e66c1fe929da645c031313a344f68e040008e97e7a084a71aa8eabc09a83dbfe691455bafe7892745fe8a4d7e4a3bda924d4091c7026cbb25ff3a723855738105a71fae48f6f5e73d5ad5ea9aadefb1dcdcb36c832a4f9a8d220feb6d9e44beb334036ec91387ebe039a545cbbe4759cb1e4ce1ca25159a3c95a5c75a5ac6f6f6e2d42c087d43867f97accf5238248d7f2c8e99cc0fc0acafd0e5b1d3a3755df985f6f6c7aff0947f569c6dfa172f86ce5538a888c54aea4ddb045a18f2d4a1ac4611603f08021c1e275b3a05572c72bdd1e37ada1d9700dadd1a1109a530e5b922d8878c464507930fcc7eb24cee63d3435f6331d85055e1d42ad31bda02d9c1920763f52c5d1b027c2a26baec6301f166f2b667056bd6b4a8a56dd3034ffe9d78c29ae7fd32da6db95eaee029895d155bdebae3e15d624c31598c3ce68004ea2f23cb6bd8f3d0ea8189d39aa400ecba1d892cc9dc52e85acbb17fed409e286942210a2658de70e6617598ac4aad30c5057880b7a8d89ca831ccca006e3a07037ba6226f3a3883b4e1cec3d5f885a67afe84d4b7dac02ff1bc54ee8ecf23cd595078dc799d64fd0169be096f9e2ef3ebd298c8c294eaa90cc40faf1b3e0e1d7c4fb3f688639d7b7f04fff38f660f5f1dfa34db9b2e4c78a3d3e1bd8ba537c3cb43dd94baed6d97a7f78b0b0c19340c304f33d43927830313fa11bd142913ce816f817ddbcc54d2a278c4409af51566ed8a601e3199f9f0e564890de1d1e52d76943142d76324f68d03c338915c70b30b41263fc279c6ebfee99cd285878a33c90450ce95ea666f7e81443aec521da044bd92a54594239ae7b3ac4b268eafa985771e55c1e947cdf9075fff088f642bc09769e2f609155e19c4e77142615d37fbcc689ecdc398ba39ffbfca27cab21800d6372cc47f523fb73d381e08c26572502fc8ee2c9085b2b433e4a5d2fd2a6ad34012175fb2d5ffc56b057d2b8f24f23c6e6538d45a77ea04dffb7f6b59f75f9992b5a6f6fef76acf0eaf003bccd827219527280ddfd4bfeadc3bfdbd3fbddda0fbbbe08d0615d324a2055cc6da74093cf97664f27ccc45fa075ac3c026520b10bca8180af730a3207b936f76081af3cfb4bf4d0291fb76a80c112b7c98ab7d8be8e03ce4acfd379629ecfbadfec95fa573f2ca9a99caa390875c41f15cad242c4578a59b5ae1546724e873497cc5ffc0930f4d3f3733048368509a7d20b64e1f6225637e60aeca57b5655b9de415cb00702f53481aa761fb7b1468074270aba1f813cf6158274e65af1d43da7353798adae034732c9b6b8cfdf81b6f34762a793012a5ccc6e2c70687fc7a71bb5bb3208d4ada3eecbf62f527bf7d8de7677d0e009c47521b53b032e120dfdefbb3b5ba417c5d21e1fdba0da73ed2ed86c33fc9ce080df53cc21ffec9373b9a1ae48682f610af4e7925acf2fb8cbe1091ec62f9a5d1d8aa2e34f29c4c4d1ef436db55e49c5a85923f26279c5efde03243d234a762e8ef58cb11f1a099478459928c2eb215838b6550bb171f16bd5cf9fd5fc4035cfdee7fd597b34d6c4eb4673f02d8f1306bcd71be2c84b3b1fc7c07f1ab432899e8ac7976468ddf6b507ee340180e2adbba3290234b165aabaf075603bb18e7b0d3a7d0b1742eab09e27bd8191be9e631ced65daa6c2b5a9a01f79ed07c6ff8d44fd01b5c4971dd27248562e8ab38f68c7e1eb561c825e4a719c2b783aadfac64ff457112a96f3a2a4e944f615b01dab39bc1308f780a93392f62cf734384043af099e5e16cffd1a1018364a54a4ce80058711581719e65f7391994264a11d48e33bc20d900878fd2f8d0ab7ddf4b1a718e72a64a036e4cf3fcf5669a37e53657ae726467f9ca2ae347cb6808018010102f6ae3a85696bfa498cfefd56d8093166ff52895429e83f7acc2325dc2250e5a1e79f81a359826157d8b0e44e06efd1f74352a7d60b660626cf0035690f4a174209f61642fc9fc4959c9bf337496799ebbb17d1a90ee3c52dbfbb2e05fae5c630a83d9de82753cb30c97169e1ebc5758e7990aebdc7398c1d8ba8e13bdfe77641b8233b65d1422881e6f8bc6f1b168d0a4c0c7b60701', + nonce: '0x9812', + to: '0x734dde12fd466c14a85de838788efe6f1993c84c', + transactionIndex: '0x25', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x241dab30227f58633e69fc4128b1c2b09699ec274cd575e39e697c1e460e5791', - blockNumber: '0x3148fe', chainId: '0xaa36a7', - from: '0xe7e9ee3f2dca42b224aecc1610d3b7efbcc07200', - gas: '0x27f2c', - gasPrice: '0x3b9aca09', - hash: '0xd844bf22fcdd8fd5c472638540f114824082359ef753a4f9c929889226dec5f2', - input: '0xa043dbdf000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000df08f82de32b8d460adbe8d72043e3a7e25a3b39c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000005208000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004d65822107fcfd5200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x3b9aca12', + v: '0x0', + r: '0xbf61073a9714f166a5a22a5b3cba712cfd04b8bd92e2c6bed96a3d42308b82a0', + s: '0x0e1359a46b8843c46ac02458db84ae0a458524f200d3f50395828d93bc4d13ed', + }, + { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0x607e915c79cae95523064e29eb934290d0a5f5f6', + gas: '0x17372', + gasPrice: '0x286c1ae5b7', + maxFeePerGas: '0x554a616d08', maxPriorityFeePerGas: '0x3b9aca00', - nonce: '0x325e', - r: '0xefa5a4334b9c8a51a4a3cdc8f3ed55f03df079a5a4d88bc282da50e3a1204802', - s: '0x5f079ef81581100613c84ba82c05279ffff68672e2f5010d3e2f68d265f64476', - to: '0xede510d93a3a6c5e8b8be88f7719716063140197', - transactionIndex: '0x15', + hash: '0xf0626f99ac424d766cc4d135904b0b206abefff50e4ac2330b66a42cc2ddb019', + input: '0x9aaab6482ab0dcdd23915845fca1e178b8f3a45472f862aec4427ac2b7c4bd9df8189c560000000000000000000000000000000000000000000000000000000000717ff037a9e0f0533e129531dcb2b22eae2ebe1dd40799d003064fefae0c91c0241db40000000000000000000000000000000000000000000000000000000000679c32', + nonce: '0xf221', + to: '0x8149cd2679ada6e9f4c6ae8a9bbb6d62ac8a21b3', + transactionIndex: '0x26', + value: '0x0', type: '0x2', + accessList: [], + chainId: '0xaa36a7', v: '0x0', + r: '0xc7d4a031a8d01c8b47a09b3754576d30003fd28d408028dac049010f4126f5c1', + s: '0x508ed8ce8937b8bf108178c5481a9d00c5d0595fbfa62384bf3410e91f7dde3a', + }, + { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0xe352af821cf211c4320713d049f9f7984fdbf77e', + gas: '0x1090c', + gasPrice: '0x286c1ae5b7', + maxFeePerGas: '0x554a616d08', + maxPriorityFeePerGas: '0x3b9aca00', + hash: '0x51ffc58c43e144388e744344fd782c9cf88a7bf78741caab63ca86a961e7314e', + input: '0x007939a77f95a20004b8f929f1cd2ddffe000000000b65011bc716886700ced99fb4a445e3bd9ee0a3c505e9c95a30557022d0608025a054d02f1e70812bb88c0396e97dd7efb5aa423d2b8163b66ccafc30a5944bd7d229cf22dd40d77ae8c1b615273530d274f3c67f6fd2c2acb3e8c16c6cedfc2d149757877e3069736c8e1a6e2fa62ea3952284f4e83f9d6b2b49bcc3addef0e77a0679b21fc56250fe200967b6809d566a21e5e3db98df0e718bc07bebe34f154846c62ce4a973e7a4090b87a68c0895eec213beae938fa65420ba304f80f8d7d12111c7deb3745ee5fedbfa20b9d96052c1fe55ae4e851c651a8565e85093f232455a67c1b79461c00016755722e4904a37d5c6be46f0a2f800ac45232b249e5099b61c372a8007e46d59c91382d257ba16a6a0b1474cb617f529041f4fbbea204de0d54e4cb265a290543fc35a9edc55378112895293b0ed11d2d80032beeccfcf046ca9ad69487ad15517398b391b790c5d17e5d084ca73b5f8bcfeda75040b49f208f93d6c2df2200b0cc5272a5ae0b19527012dee79d62a090b920fdb921b13d764cd91f075f44fa0e726ab7581945c3f869d3cd8a40ad985da14b2457f06bb4ee4b326b5b96a3ac5a54289352ce7fcb1334e22d83ba3ea421d33a9eb9eb6710ff83304d58ee55481c3e08ca66b294c5cbdf7335cc20d18c1f7a0b759e5eb20efb2e5164d476a4a2a70eabc0d42bff752383cf78932ae57140779d21dbfb08b92495c1ab344244911bb81d6a43f24ac5f3e2b88620472092518c538ca9325067b5a18adb4389e45c5fda1226536de29936c478765dd9b1e4b7501753cc7499eba19f40beb4e43352b1b011ac52cac4dd6c517831ed6e1e261416d75e8022f0dcef25cd4d54766f84cdcf1e31869bd01fba4b9949a72aaf3511fe427872992c280f75ce4297e8563806527e0bf1686dcf0882a226231138b9cfc1bf83cbb5fbed97a6366e7eadc21206b62c3b4d6f18b323c9ad7197e47224b46b464437c57234edd1a5d734bce8009ec2ecbaff294b9a869b72ade56e8407d9b52e1fab1a1cc41046d1a1ebfece1cecb4d9e105fc92f8fb2e41ca74649a1c38d75038b02d9840bea7f583c6d69687f6a77dcb8cb738b407da8fe1d1f9fedd65742f85ab6d9126db48df42e233ed03e1907ae05291cc8e77fc96a899d8427ffeb5f97b7ba97bd5771fa7f6cf83e0f5ab7c2eb5ffa648cbfe2314f98cd4593a261ed8d6064c748573d64a4248b0b3837741e9aeb3f9e15150848e039cf53c04e310d277ed73f8af228a7bed5b38642732e3ed652a33cd95d347de615195ecf9ca0f8c3106aba44bc690888891662e9989aac494bcddc53a6701e45a07f776dc00c3e1baaaf8d1ed50ee1d1cdc97d55441a68509a23d7213cd3173de5846ccd4d20f19e07708526fe5ba638d5d90cdac8ac74f8dfd820087c6cc3bfd7140b2cd96b5b97e7338bbb968ed56235a1262a3b55dcaf9bb83cab047d1c359f2ef329ca55b77bc7c66d0f01541ec58bf944ee0400cdc4a3392e8b0f10419e5c6f73fe8636484cd58af0a3f02f88ef79a01d5d35fec3ecf6adb18e892b0115f463e18b8b1c5544f6a44aaa6829a703c881c993ab3c5de7812bf745151709dfcd2f23e399dee434aa6b2f48e5c758fa1751de1db8f3aaa864eedb85d9af97ea89a8711e1b7e50eed6575639cc8c6201cc395d360e94010bb8d6d2b673d259848d9125653b5fbc738f017c23a64fe39f648622fc82cf0b6a05214f2bd5ca838ee847046f33d7031717e2bbdfa00cf1b38d4d08b39f6b0225f22816487976c79f33e5f17ba967c5349cb2a2d48cf7d76664a6c3ee02c862a8518e8e8221a0e469eb077e9d73ddbc67af5705124bc9ebabe65acc0b16c71fee537e07c0a78fe68296e7f6392dcd76ed6dfe4a65317286c5feceb555263830900695a2f0804515a64d0a401e2603474ab112c265d11f406fe856ad192d578b3fd69d9aa4255c78feb59b9714609ea7045f01df2460b3f14f353b3042afc7ae44dea8f1cc85d708ee0585b6d0558106ac60a43c670924e95069b76df2dacb077ae1ef9bf5f42918c34e497fded34f768453c1cef3dc30b3f327566c483f957508aff0bdfb18813cc9e35955d612bc761705c4880337cf16a552b2af308b374902c6fe7d32d4f5b633df4801867521497aab42e58bbf08f879781f6d72de5f2ce7628645fdf95c7ac4d2ca0bb48960e03f2a925726c7ba24cd20cc3386eb3afacdcbb3b0bdd49cbc77312e22ac9b2466c97978874e4139cb418e1902719ecd9bd6491c12b022e74d9ca6c591ea6ea75a55537cb8193bfbe13dddcd7e4800c03cc28ba5c7e149c2f774d75fe7f39769a7b3f26179e817bd5675b74866d9a204b790e511928fea6265624fefd8405085e9ce97363afa0564cd3b2813253419a002347c4091a7695f4976e77e12a5ebf4c51c9b37f27fcdd9abf9c75022e033f04124de38620daa3c914a284eb57cd651e3135d732013b4549fa13f6bd4710d9bc6ef95863c07023ed0e4c932609e47b44f25ed76b46ec3d2f9bf7065f77d83c54e932d1545401548c200822e0fbb81338ee6986b2d3875b6d3c0b30abd4fec15915aa19b1b32883da518684308439e8be08fe3774f63cfecc97bd11ffaa84c9119b522a07128559ee941ae9cec411298f2f4031cca9917b6630226dbcde2e855a09da47165e1767ea95dc0388024fd40a5b0e479d6361e61b3f8739b5f3eec8786b127b3a82a243bb6b51922be2b3bf1ed81561bb63cd52d89abc0bb70324cb465566dd44e419126d91e0bd07ae7e3bf22afeba4512b38f2dce351b613ae6bffbc7351aa574dbba80a162faa9feb2b25fdf6f7f1fe7fe3fc195c79ea55781b9ee72e35e23759a02ab9d7fb49c63611757c9c2f009d4a00142bd66b78cec636c7da17aad8869d242976cef6f109f1563b47426d5ac347e1c8ddd3d2de79066c60a19c6f5798cf86c385c2047358a5820352b2b32c00f740cc7548f14641ffda1b7c7924847d6f0ab321a6581297314ec64fe328aa7751aca315e4c64b5cdb9699850708e499da77daf4694187798be59a4c976fcb7ce8b8ec57e994ae91c3f9bcc5c7b44b45288fd85b38d2a6c69e1f19e7d3475986d49c77a9541b2b7ba9d1ce73c4ded1b3633a2279dc894c0ddc8d07c33619a36eb7e5e52455ec912eba1e1862cb93a4413c6312ed88e5992550c871faf589b85deef0d90e2b3ff552743ad9e33145a5697eedd87333c785c4394744cb9d34783ad9c50c9be756b31fdda035fd7189121a62f271b90ceb0afb6ac00e361e4939f31d8de942a8ecb3254eff682aff2b3b344b9a44e9916837c9e8ff9d0aa93c6302090d71860bf1884e1e7fe506458da175d36516188999f1753431e5e3747b90c943bfcdf34f291a5431bc70f9a0a8e321590611dd72bd03fd2729f322fe016384865c9e6b0a3056a4875459f1d4ef74456f51e5d1b799822449f305c931be9caa657e2914f290038ef501316e9d44631ac45fda3b86c6db95d9906c959f8282ed91da6ee5dc28e5c15dc0bc9c6cc878bec8697d76795d41a851f02c8e914c8a1184ae1d59c987a8a3728ebc36e0d260368a472963b228267f8c9d9c114cdeeee0a644810ceb4915b29b1a708079cb766e344530ffb06fd4d7b354b3fc27598007cd40c3a95e57a3a4f4509134a296073a76c527002d04eb6f5a498b8838904f0f87be2296c0f3b4aa8e3c70bc63801a8d3c83e4f66cdcb7d7bc4b10da8a12218ff1b899c7c352c9a525a93842beaa6e4631b4f2f8de70acbd989170ec3885bae6be085fbdc3df0de880cba12a66779e8da4c18fe8e47159f33a6ea2c0a8839ea084439a64b850567a30936e7963910db4f2e2846f0e422f8f4f2f2d12a1a0dce172df3aba4db3d5a7c404bb10fdcac7199552efcd4056de3506dfca41d8136d36fa11baca4785b7a6ce780c0150f60d9686771e706c4cf9cb6ccf069c60cf811f6a0a9501316632e8f032af706182c782a14c5a717d80c5b3b292fb0b688cf24884efe86f2a2b6d1403bac8618390e4ce6b149d22cf5cf979d149a5b5e906b3c224cfdedfcf0a7eceebdd57ce091cb8c012e6ca1767f5289e343957e46164b880d92baf590f01', + nonce: '0x1af53', + to: '0xc2bdf3566f453c0b97bb8ff8229eaae0770eb4dc', + transactionIndex: '0x27', value: '0x0', + type: '0x2', + accessList: [], + chainId: '0xaa36a7', + v: '0x0', + r: '0x96a4da2ab7a74758873361d91979d3cc07f3c71adb2b24e12fe6b15afe5846cc', + s: '0x3ce246940f162964e4a232783ea579b0aedabd1860145b970b77a094911f2a94', }, { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0x45137398ccd72418f2da54bd8c7855fdc6a4bdcc', + gas: '0x10970', + gasPrice: '0x286c1ae5b7', + maxFeePerGas: '0x554a616d08', + maxPriorityFeePerGas: '0x3b9aca00', + hash: '0x958f8eb93a4a10bcb69e4ef703ee3474c5e516bee213df08db5f18b82c8fa2f5', + input: '0x00226f14c8875c99896f1680cccf315d96000000000b6f011bc716e86700e666d4881c31bae6a818d9a3a2151c95c3a2c4d1a29438227aa4081c87f6a81c75aae044a0c1004b8c02a4a70f5ce2e2320e5896794dbfd76d8677638cfc3534a73493074fa12c286cacb77648625ad95a12d08b99c4abe730ca67226848f5ad10414220bd8a5dbc8747bf12895eac40422c2271aee1334daaac2234de616d4d1c71693e77a0b5e1350f047c874ab9f2bd9d752d5e8218e2c38b27639b908876498cf771a0dce6c85336e6e9b7093d67feacae6e9bbfd72e53a24a1bc8e2d3a507a32b2a12529b006c2c3c0e44916a51c6ac52da25aed60cc78058de07daad2c0ac382bffcae5d7f5086c871830036f31c42308487fe69f79b5bcec1c47cbfbb1d259caa960702457731827944a99d7b6ce589a8d9b5e3da197993469b47188d55805bfda98796bf718375308b90540c8c90b093e7b06d5dca3b928c396ebf9e6fe8037363e0a248c522651dcc3ed1159aa658a0cd6e9ec2ab5c1d9a958354ff97c784641dc9b2d15262606fec83848d35e8cc3f1b1800268f0a7d25ade78fc40f714b67731d6b217ea18e505a23e004eb396fecfdaac70439dfe7ebf35c86e62c3272ba269a60f8bbac6f82e33ad3fb3f25181f4ad8479cde9f373a10439e97de2d9b1c27c7357ee9b20c11e0e34716affa03c6e236d24865ff9a30c566f233cfaee74b1c3bc7ab26e45caab59d85882fc6aba0e489162d51e69634056206cac7ef3c0f2b0e12ba7916367a78d4584fbb2c2e71f9ff365fbdd0fd33000f44b8a7dad4f037cfb6698981348bfd54d87bdc901a25eaed58f27beb32ed10d37bb8331ed1d7d002b079c21356f682dc2d771bf2d33656e8f02f633b0e7b2c1ac356857c05e50b42578739a8349acf062963ea1d165757aea01488b33d944cbf6999369f7d9183c633ce0dba73343b5810719d0415895df33e6017887e9807ca62f2d06b8bebb3db6ae4327a603107e2c8283d45d3ebf275cbc0af1a3db5c102a7888f110f3b26526c84ae69795fa2a3e439c9f3470cce74d61c3b935c2df7132e0802147a86f1297810bdd4096dafe2718161e3ec0b000df23d494b48fbdeffa63487a65f995f79dc53a30285faaeb1b741adfce62c2ef2c0452dcfd43e484e2c810cc8d38b1b3ca28baf94d57fbf00dc3011275de4b90670952793cd3c274da9b521de311531a6bbfc69aaae0f675443bde90f4854b3a348017393e746259507a17ccdb84bc347baabbdbc6b44c6dcab372979212c06deea254e0de176fe686dba1ea6c8a1b73822684e7ee79bd1f5abaef323da92f0656ded959f2e92cb8104123bd9de963563fd5cceb6f2ddad11f9f867e3151e1b56acbdda3fe98bdd957972eef368902e9acc9d1e068afa808d99fa136def7eeca871b2062dbf6bd681ff3f2d33cb639645ddc7feff55fc92db4d774a1298abb77472fd9f40d6f78008d48b2c5e1111770f0b5e9efe76cecbb66c1509a30e32aa2f037857be5e2cc3e930245e74f3686b66f2d74108f2b8e1a8438d7af9e2023072c269fafac903567d12870655dd5ddbe6cf56f0944a21ca03773704c629cdbad556b029ea35273e9349be8093b64a051fe9d2ef097f48318364ae86b2ee50def6e9d1fa14c898796719f89816f88a25cd8e6aa61765bc49d13f700046b67905f42f84a942c4c0886fd51afddf459127eaf68249856e94501c48beb41b401e8b40b4a6f79b91f5245dd14af0d789fc8347cb9ebfc558b15e0607ea9f13cd40c8f3d031ae69b5d6e3fb03b17f1bcb9bcd601aa36b1375e92632aa4e309975a27e5728f3a0533fd16f93f2de7fc5ea5b47a2863acc2bd9f72c0eddb4757c4a136041d85da8f394405fedd8864fc19a0bd4cb9722fefbc13cd83f0ddc9e7edae31d14ad1724b4006d9eb83f8f06958de67bbc539128019c7568b32d4181227059d0e14d9ca8d7ffc32fa19f2b8b063b88815f89dc50194783d6a7f3e5279c267187b70a1a0769d68bb0090a074f90e455619ae43a709dc86f3c6d8797225082ffda45107453a185afee4bfe62a0c530e42156e71c67225598697dcf6149b9553e23cf9d40bf0e78561afc7d96cda9c5f71ca63c51950dabcb7df92718b79d113091f9d12d89bbbc96ac377e883613cb4b19b60640797edfe33fa7b14d630da348769aa97e247e0cbaadc69505ff600eb7769c57edb980350fd7a444c24b9a84c09ba79517311ba728436c6c33f250e495b0194325530d9325ec79e291cfd3298993a55385d65e0a796cd496942408f402be27fd7c3d9a9411047d02671e6316a2f369ab0f7f52fa5dbdbd15e59f2aff8a127993a9e46755c801f40e435fc29da746567dc96347ffbaf2a5671fa07eaf88de32d8c3a17832b43311d2911adde00a6f9e8b3f87c1862e4f6317d8492d8be41d8031936a8e42ce03f0e7015a0ca6ab8b35f0e7911b07e5892840f3ecb92b62757f66502e9a9c33c018fe2e55d2848201f8923208e6f1591e6d03cac0655b6b2e6622eb575a961065a8f6c83aa24b3dbaf6b57bc3b708e771a20366ca045b514fb73f0e8c0b887df137ceea377f0ee0fd0f9d881a6e9f6740344f0bdf19e617c440a99b9f9ca44ffbb12c0a979ff2290c645073434501b4317a86789ebb22a1f280850e77c67d1674ca1f11a14f2fc21354dbdab8736904559bbf49f602ce83f534a019caa7b7201c9c296b4916361d28dc318a17d8b603a497f75d1e0f3500c9937b95c65816d046cff5af065e7d146473fb56751db33b2cb2a6e64e3ddcdced88549e37531c9aca19e875d9a742b26526f38e25a3f32efeaeee1186de8f91a3b733abc8e471257e7d217011acbb055393eac7da7755f30a7c0a4b4e3aa24a90c348acb68921379bbcebd25869b2b030b3ecb776a087968dc54eacf1d5bc1c7d3cd3e4d4007e66730041aa54e21fd1df384ed542595680ef95c7b5f596c1b451cfe8b72fea776ac6b6ee50c8d3f712e4b906b91e17de0f9120d7dc27d983d25021a06fed48f4044e3e09baa9a39427a2ed21d32eff1ffbbb6b44bc23099fab57f2897827bfa44773b4468ef4d01f7354f2648d1ed80758a1a2681faf9e7498cf254ed958a6963f979daa28293d93fcf5760dd53c204751a3fe6e48c4d09a579d11ff726734df362361b444b86ef278df7abdd909ea796067aaf9e07210c518fb475ccbefda59452e97e094a32943f162a5e035e6660534e7779581a8d738f7c7fa3ba590bfb24d9d8ff9bf23302cf71b117a2cf0e91fb5590e2491ced3086cc24cf600a0693480bde4a1e3c36bbdc965ae42bee882c005b124027eb4f318746a267d6d75ba22d6441e15dfd86e59b16a867593bfebc4d772c1310d0593a29b079714bc222a7f63955d97ac188fc694e0df8c337b985e53e33112e87fdaa2a2433fcfee6d9a26000a4b2fc7eeb574257d0bbeddfc0ac76ec3cbe2c28d40345907bc18e6d1a7d6a9882e30696fd377f06fe5f7310b2355aeb46dbbff092af6091fc2db3ac3380feb180c21341685bec3949f8bfcf2f47d6450796fac979f08fd1cf51e8117208ee9dcda00c9c647c7e0e4de3a8234d877ded78e55b1ec14e422bdf258502417e13e0ea490f28d98134b55fa57923bedede016f020c71a69299a90c4ecb8851231cccf81c23c4fe7fed0913d5aa1fb669b1ed68b53332c4ba20667df9a8649fb27b4e792f0a1b0c8736f046be8354b7809a2d0f7db84619d1063794f1f2ab962397e0592f4fdbbf2c12a0ff7a37e00e410402db53dfa63184c9287fe4334bef54459bd81c218fddc2408844d1e119f9c9c1f3ca8e192fa98d0f639e858b4dd796f4c81efeedcec895b8e4c691576794ab6f57b9bc819a798f08f837183b13541ced4d4f9dda4ccd63be4bea0c47a2f1ce6c0993bf7cdcfa2a295817be2b8cc6930ba1bd2b061a28297189a9da941af98e2401a1933ee696ed8f434db4d978654f7962455f98f325cdc2a7794761ddbd8707e4088531e90714a02fe6b0c7d8bbedf4a7810c1063bfd152e3de7ffdb06a8f41680f3d9092e79ce8e934b69ef5498a3ae8e628568bef5b07d27251e1979b183482710ad3f57ddc62dcfc4935f60cba8e770b4052117a8e81012d39b99293ce7f41ae20e78012449f9e9f5180601', + nonce: '0x8837', + to: '0x98bfa7d8ec3ae90573ff2bb9be22f111f2e96229', + transactionIndex: '0x28', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x241dab30227f58633e69fc4128b1c2b09699ec274cd575e39e697c1e460e5791', - blockNumber: '0x3148fe', chainId: '0xaa36a7', - from: '0xe09e4ff4353fbf984f99fa824524277f704e7475', - gas: '0xf4240', - gasPrice: '0x3b9aca09', - hash: '0xbafae79055a392cea650f90096a305d1338a170a66b58dacaf69a7feb2b3f187', - input: '0xa043dbdf000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000777700000000000000000000000000000001fa79306e7ac0966731a58de98cb2ba2f79542474af67f9d696783bac7161961000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000055a7f5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004d65822107fcfd52000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061e2f961dff90154128511a903268083023c6e94ae5c05d961b834bc5752d4bc6774b1d47e53a64c873c6568f12e8000b8e47ff36ab5000000000000000000000000000000000000000000000016426a792f94ac9b8200000000000000000000000000000000000000000000000000000000000000800000000000000000000000008fcdc43cc17ea9047a770762f20b6d1e816313cf00000000000000000000000000000000000000000000000000000000642d194a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000eac2bd4753c659c909c92f62b3b3a8836c2bd86c000000000000000000000000cea5bfe9542edf828ebc2ed054ca688f0224796f830518dca0dcbb81456ef28db9f78ba53d032804183435a2d240d344b8c3d7a1a5395a4ac0a05c628f436c4eb2827edfc67931073efefddcde7647ea707a8308a27e556d8fa9f9013405850ba43b74008302f8c894ae5c05d961b834bc5752d4bc6774b1d47e53a64c87470de4df820000b8c4f305d7190000000000000000000000006048e5ca54c021d39cd33b63a44980132bcfa66d00000000000000000000000000000000000000000000002b9451bb9dcd5e11a700000000000000000000000000000000000000000000002b5c89a4eb17dc51900000000000000000000000000000000000000000000000000046b2f1cf07c0000000000000000000000000007b741bb145ed7bbc1ef23e7650b5b03c67681ceb00000000000000000000000000000000000000000000000000000000642d1948830518dca07979aca687e96a60c032839e3a9e74007dd49ee05d770affed59fdd63edac960a07723c3a7400e4912d4da98e3074eb18b00daa82311dc2336117fcae96215ecbaf91d0e01850a3e9ab800830f424094000077770000000000000000000000000000000480b91ca4fee99b22000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000003e0000000000000000000000000000000000000000000000000000000000004bd3b0000000000000000000000004284890d4acd0bcb017ece481b96fd4cb457cac80000000000000000000000000000000000000000000000000000000000aa36a70000000000000000000000000000000000000000000000000000000000028c5c000000000000000000000000b865612584aec3737f0d4520954491a6dea83d3a0000000000000000000000000000777700000000000000000000000000000002000000000000000000000000b865612584aec3737f0d4520954491a6dea83d3a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002150c95c619800000000000000000000000000000000000000000000000000000000000000222e000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000001a40c6fab820000000000000000000000000000000000000000000000000000000000000080000000000000000000000000b865612584aec3737f0d4520954491a6dea83d3a000000000000000000000000b865612584aec3737f0d4520954491a6dea83d3a000000000000000000000000000000000000000000000002b5e3af16b18800000000000000000000000000000000000000000000000000000000000000aa36a70000000000000000000000001e8c104d068f22d351859cdbfe41a697a98e6ea2000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000005484f525345000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b486f72736520546f6b656e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000380999aafe268642f1363a30eb43fb543d0e33a55f341c1ea469f9a33a09ebdf1221dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493470000000000000000000000009b7e335088762ad8061c04d08c37902abc8acb87abf6d70b5ff1fc5a1373b5de54208c25a40423a327ae085501f3c5d18695aa0360ce76abc100bd3bfe97b7f1f20447047d2f8e2c7e6bfd41f0cf66c94935066bf48db3727031c390da1d98f28ae0525f280597666f8311868a2423033acf6f82000010000010000022000e0000000000000000400100001000404002000001020000010000000444000200430080000000004200000000010200040000240002010000000000001002040009000000200120020000040000000000480000080000000400030200000801000102000820180000008000011004002210409300004000008010002100010200000000000000001881000000000000001020240000020008000002000100000000810000000004014020000000000080120000000000000002101000000000000840800000002020230000000000088040000060000018022000000000040400000004004880000010000000410080000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003148f10000000000000000000000000000000000000000000000000000000001c9c380000000000000000000000000000000000000000000000000000000000043a98300000000000000000000000000000000000000000000000000000000642d141800000000000000000000000000000000000000000000000000000000000003002db892ff219e7700915f8a8b31f759e1b5c2d48fde6dabb6d9907e978e5d676900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009252a7040b39fd2a7d353c2ee4fb10c9e68b5d2c7faf1a2b45566f4831064a4400000000000000000000000000000000000000000000000000000000000000019d883010b02846765746888676f312e32302e31856c696e75780000000000000000000000000000000000000000000000000000000000000000000000000014e000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000b600000000000000000000000000000000000000000000000000000000000000af6f90af3b90214f90211a0e8a3c36316ce8c880120788f4533c1cbcf55da5a172b5c69cb53660b170fba52a0d86141ccd3bc25c9b4b9ca29cb536f25fc96da550ed6c14d7e508d5f4ef832a8a03babc1e29182c92322288322d36482bc36b0a6e7350412cacf38ab9ed81c69b2a041f800a512bd2733ad8291ff52a1f0bcab58f8981d570fec7a10d1dd3b4cd768a0a45b86b234fdce46035c71a60be34c5e3a3882e7f146cdf8a1a476e9fff30eb0a04f262f18cdbcfa40a7da85df010e8d3b7f37b04ef8e53bd9c547c30f5125adcca0a5e6d00bd39f85f1747a10fb1f837859f0bfcd540a346984ab86aea9844ddf22a05edd61ea627ac91bb516f94fed66860de3fc6bbed55f9ef9d4cc361d22208b7fa0c9a45bb6dbff27575e1163cda01f313d55df0025a240f09705ce37d718607bcaa02002cf35560566563ec0ab146e815b6cf70a5791a6b52ff55fc38740e562a76ba0df8fc7adfd97841212763e8895801c1d91c0da27375d45ca1dd6a980a31706d8a012034f55ec22d3497f2b8477b2ce21844684017e26e8e70fb634758da89d7bb1a04bf105ec9101c37b53ed744d6e29341cacaac8b4ca7de1b9bce027d766a477d9a0999b8512fda4fddaff0261e63edef3cbfa23038ad423b27f701ac43b872921e2a0fad97c330d39f4afacf64d34b52b5b9543155f9e6a91abeaea5617ecb1443e8da0c274643ff637699b38077f2c2c5e1c4902fd8c8d1e92e0645fbf0a3b42fcd0bc80b90214f90211a0ce44a7136381da9670e6a6170cd022bbc27a9c37170cfc8f7bfc219b2c0faabaa0d12741db1e9e672829a34e0be3c0596ef6d6c5eda81db65b8e0921f997c5b279a0ae255bbec9240630c05df2f2cf55d2b4dde112e747fd416ec7403730d3d9dccaa065eb21066db33e00eed2ea1771a9d745b3e7fe370ba59aaa107a7d6ad74a3b11a0af8763c3cf574f21fc7bbea6448fcf3c43998c2e6a1da2684b0f8fbe73ac9735a0374c4400cba54cad4956c667c623c5ed2b943da43a43759fb8a00264bb56b7c3a0b0d2f252bfe6ec639eae3f3955af0c6e140cdcebae67c11c17de58b5f00908e0a03ab50f5335e85ad35204b88ec7bb6f59286ba58ae8d2a6bb719aa9b1d0b581c6a0798f57b72788da7a66a0518bf5b5757b2953dc0fc24baf31ac21108598569ff9a025e82f74e80614ce295bd19ad290fc44fc9c24a0321a671a9cc5ad90ece2de66a0d5fa0dbfeb4b26cf8194bc284492e6b9da201942d0f534d0cee51f01622c54f5a0f72b2521817730b4360c256f002a55e5bfdd7a57dfd26a8a5253e27331402c79a05ceccc223372493580cb3fcc50d965fd92efb39957b1d590121d745e4fca36c3a0591623557d7b0559583aa9d89327b7895437478033e087097a4ca8ffd6672be5a0a77394ec78baf2d57955a44bb7610551ae052adf71a26fcc1094135b54f432aca0c425242acdc30f6ca12ddb1d00aee89d77e1b1128724690e96c6d08e1291754e80b90214f90211a0f1a115b1ccf575bffd5e20db76caac0cb639bae3d313fab7356882615a0583cda09316d64025f33cf5cda2e32e7b40bd4ff31db2e99e106da4e4dfa32a42e48189a02292614c13e0cd22c7d48a1952468293b885eb3b0f9519b7ae4ae13ea74acd7ba0f4548120c1fbe0d005058e667a85dccfc29d53b9683cd95c0062efc93dd0d020a04f9eb068fca53d383732e579bb1fa11f9f6c8540b7dcca2972a1a8146cb04e12a0778d7699916e807277a84b80802760f27d2117d8400e5b65a43758119d3c0369a0e83a591cbb8140afb0c30d79b954642b779e4ea2d7d41d95ede952d936db7633a085263e23a13a7ef85543662bcde96e5f98475ca6fe7a7cf9734787cc78040559a0bd926540a9cbb9e49be905af3035947bf233f612775263a9e5a344dea5e59d55a03b320ff6896bfecc2ffd218c17f253b6ed59d712eda26de98689d74a3593080ca04aa12df643f7d663ea71f76983243c32f72ad1cfd56d0790380269ec4fa1d398a02784ea76fb653f621c955dc9b5c76b3aa101bddf0b1dc77b09d7193ee3977ff2a0bcb4f825cebdcd5d726bacdc4bbbd6dc0bf95672ee35e1a518c2eac429a76eeaa00b99cf6211844d2fd3b6ac0ab25cb31f135297e90f5c5613ca1fb35c16d5be4aa082331a041db97ec1b9a5b4feed27453d7fb7ab6647a50e5e0a3be4f858181b06a0ac395c2196d298cd789910237b87d2b85a5696d15ae0c48c167dd32e98607ad080b90214f90211a0fb8ff560ca9504c5b571eb6a26c4a9e2b1480b1287e086fab1794517ea64dfdea096f8275a2fefa5ae97c7804cf017a46ff8da47113bc4a93a0ddf991bc621a8d7a063854d37d08448143def60bb81b6eef240a6c22504b6e2199b3d3f8c9dfe63c1a07b877adb359eda7830883ca8a3387da29ddc0422280cc6a7a98ebabc8c0dc4e3a0941d5b10d77efa5da043478200f2094bdb78504d5ee6eeebd92fda34b2151e35a07e53446fee6bb173e36a191fef2ff174b493be5c5d9c38f0e1af97144e025f61a03da10497ba8eee352c98ac78d7f55c297478196d048d93cfe2298ed889b9fc35a0b01689a2bba4a40e9c901e6ae215e5acdb2cfa42dd0af19607e1ef4b374108b5a0567e23606d43dbbfb8d35c52a876dfd411a7c5a66997319df928967ad437893aa0da99677795f76062a5c1927baf3fa32fd66c64e3ce8d0d4bb55685e7411b307aa004e6bc1d64ba72d89542266e946e7b24413131de4553934285f53dd2d966f14da0d18e5f84e70f8f4c8d62d95901a22e2f1f99dabd2fb79126d97e3614d2feb06ba0493e106ecae86a1a4c1a34fd2ddbc5538dc275838f82e7e17295e6f309196d61a0a6944951f8a22cac7ac02cf30d71bbe357cd5dd2904b49c450dc13504d9cf17da0ede98000b5e538c24d1d428f46f9bb60f4fd869aeff5cfe6432259e861417ceaa09e3548a8b2c15c778d70010e9ff5a82005a5955a55a1d1d3c7f13c1c5bfcc15480b901d4f901d180a03a82e40aac6b4b665b910256c2ac0673b9b8c7e2c18b846fdb17b19b38c79a01a0c2810e576f9a91de5be7774f18bcd3b8f32020c1b9051d7c6bbf212f954acad3a0e93274f3773d34269a28f86cd1c6dafd18b30f42f29808932a5d00c68c60dfd3a0b5208edc16ec4ebf968be0767439f69f24f3511c64fd2e1fec45be43a15f591ba0238e86031d6f812bfbfca85d204e6676534aca4a1e84d29260b2d1d48a687961a06f05395b7e998bfd1a5c57183a670b397a4aa50b0b102243d474aa724d89a46da0df367e8b5585cbc73aa2a0e9b06e138d7fda554b4fd3839fbc5445958e7d8313a0d3ef4210936892dd7a4b3fa191bd56583dd4b73b0d20c4b4ff8632ae09934c43a0a10cd7efab9147cb2fcc9cbbb2e67e09aab92542f970446b4773a2f613b0fae2a01f6b383ea1e5dadbc4bfcba833902c120c3d0448d04daf725df9f3afd619aa53a0c2fe0a493bcda2348f94385b85a2bfb882be9da8c7e46b4ea8ba5ef7462523b980a08220bae99bbce785e55a5f57633c059225d129a21748480ff5a35bf74f2aeb6da0a155a41a0bba49577953fa96701b75b3dbdc8c334824f34a702e2a84da00309fa09d6ad83ab9088859dca18089953e4b20f4ee820b09c6300ccb4533fafe7a648a80b853f85180808080a09f62c7586f7bfef17f50d84630afe9636af8eb5e4a8b736b4325ac79d1fc5d1f808080808080808080a012ef7fc37216a7288d799939f075fc145c8aba8774d94e943353c8e96d5ae7fe8080b869f8679e20016e8b63360d8bcd376eb61bf80f4e2e872ed064a0eac1ff06dd24db81b846f8440180a0f87ea7e5ea8fd1aaa75fe4ef2e4bdc95c49b2ead39fc52784a5c145c8b59e012a0b16944c8bb850059f91dc8cd33437c5002f7b19b721bfe36d3c5122cd47361cf00000000000000000000000000000000000000000000000000000000000000000000000000000000094bf90948b90214f90211a041ea73d589b499b3ca297f66d72fd42d32ac894d7342b9f1f5ba7df0766cc88fa0557554e81eff7a46810781361db3034e479996fc09996d31efc92083900b257fa0f852ed745b6b938dfdfdbb05907bd125d062d9bdf153f14b91965fbd373b4aeba095057628aabdf0895061932a702a7c3279cbc86fec951f3a9ef979b63bf77c42a0dff38b4d64d00d06db4cbf74f9277e58dafb07561745d5a9aaba45b02c344a68a0e742f0ff9b0c6b37825e640721e8f52e28f7496113dc739df7909f98b8d107ffa09c7d25dc86534637ed0ddca306af8ed926c69327a77256d656be65c574f48c39a02c7fced9043cdc8a8ed118b39934472292b458ea7b48892fcb7a917719bf6aa3a098b3b17535b51569cbdbc27c85a4a42b644a4ac78fa4acdccff33dc90c596f33a057eb0ba87b13ebf4a0ac86d488057a133a456573121a03920d6b016a5fce5463a0a22c8b42caf8e675b0415a034ebd819e8cf36b65a5417b96ab57155b1f37952fa09d8ce5996a6cb45c4cd772058d9e451559412d23e4e8649abc7d15f66620da22a00c8a07bf34ec6b444a2488df1e6dee30497ac0a0694edb0c491a92f8a3fd1ac3a0ab1f8c0851abae9f70f3d4fabc621a26f9113c9987a4ec6755e3e41717f28d66a0a28ef869f39a2b28799d430b3630ba2fe5a2fbb3e646505fee166c0dcb48c785a09b94dca3e9dfe985430f13bb45a3b699cc3a83498bc2b3fc5e31c305eef0960580b90214f90211a07544850744de7c220c6bcdb412a182a0faf4e592aa69eb2d521ade613332e02ea06f14ef90bb358061a456cfbad7dd52f7a79cd30b6622c9ff50f6020f03006930a01023cdfa47b2b47cb541da20367f11b2f91538d0b016d7120d4ce002bbcf728ea099803b259163e9a1cbde4a9a6543b3f774547ba3c9aa6f3a2369bb0b2d08ea71a0121f6deef8f8f6ca6f2b71b384d3490a19ac03d3f3082c71f8508f01e34a95b2a0fbd01048a7d9e98499f036f0cc5fc417cbb7ea879be6880f1b6e37855c7de23ca018fbbb79b0ab120d104c779f8ee612e1bb6ddf588240b80069950d57918187c7a0f6f9f34b7c39b4603bf855c6baba28f316ec71df886257dc25216f93103336d6a069daf4734db758f1b5f3b456f40c6ad56ebe62dbd56bb5cbe35ce38bf2205e90a0fd4319bd2c4af456ed04f731d154b1b98585ad79fa30660d8ec98503097b4209a0048f140b2b4347b9afa2aa947b7f46ad35362b06a95a0a3fb87b4ee3dfa1e78ea0f6bc8cf95443c45b8fd8e75e1a491c4a03d1d5729a55d57a959a7571e264a062a0fb3113550bea737b86e3dc4e72a8072a0e9b890bf63befec6d39f297dedd0796a0687c05fe5c12a70e56da4c77e00c5d4bc438fabe07c31f62503494dde8016978a0bfca8dea7c05e8270db239c82e794ad4242dd6924e20fb5b9d136e91021c5c95a0872c183cd12d7d0397abf5ed3e81fd999da65f88146ece15f4c65f48e3b46a6b80b90214f90211a0ba41b83e2ad6904279383f09fbdf8c459a35706ba25f43811f74b4d23f52f627a05a84e84952f0cafcaa6fd61a91ad8dfacb561a2fddadcdb8997a7de6a1f72b9fa0b8c0e2792b73a3fae088e89ef0cc53b9b13eb958152dd167f80992e34a09b23ea08db0903564f4be659fb086d2dba8e4bbbbc061cc887f9c298db8d5aa681a838aa0080129c83b673253a5ce9cdcc262b622cf65255af81cef6b2febe1e3a9f809e4a022171d91e75860c4f05072904fb672bc082d82272e3580991a300483e61feb2aa056abad306dad645a4bca0ecaae00ee951269dd8eb64d1bb9d96a4599c908ca62a0bafa662a4e9aa6c78a9409bcf89f01441a59da4d92499af9b1db380bcc099eaea0150825a048bb3ef04fdf8598effbf180dcd602cbd20afa028a4ee9955fe7b48ba021b740b6628824174434d0e5f9e5e6bb9bfbff61b3fe80c0f1b0346c1460c3fea071843fcad7ea6725c5c8d0e3031e2e3a08515ecdb5f8c5104e26df32514b3b3ba074d4f14fa46dc830fde8ec0c8f2c2b0c8ab9eec5ff6cddb294cfdccdfee161f6a04e58ecc875f43d81bcb03386f2a12c947a23d8451a6732617d5d3306b219a643a075a1d4100f45c5c11e118ad5e0551eae251b903447e754a0ab12b2b728eb7a70a006da9f19628e3cddb66c385c90b9d23397bf62cef30b9fe66a5cfce2cc4c2ce9a0b58d48c116e39334ccd93cef254d4a518042bef38eb4c5dbc579f8195608ee9080b90214f90211a0d7b4576eb42d968aff244c750d5473a43387d686fc412b70a2ca1a46d5e2e1a7a0b4aee2fe792e51c501c92081aa0ab6bacfc976f5e2dd4a83cfcd5253bb98969da0ddac590296ec991bcbffeffb8f55e989fde4618b02954073c480d883c8e5ace2a05a157f2ca6d6bd23255cc8d4c7ce53256fbc6e5b45ac2c4376e2d28f256415eba0759acd7f6212e706d1d3a8aea6e56a5a2e011f173ba1908a478aa87682f3c3dfa0b074f019a44b29c1deee41a4aa2ee93b4ac6ea0fefd50c3e5c74d23c0bfdf5a8a07c481dbc9e5949799bd08beeb62d422c2d91077f4550838555d76cc2443dab8da08d418428e9bc68bfb38750869077845f5b45a63d64eed70c6be344955954cc23a009fb661af65cf20697ef6c3ce87c01f0c9d72590620302f124a8a1efc49ed99fa03e634a4fe3e00a6ad4e0371468744fd19d71387c7067afc7d8d45f5789ae49e3a0e8110b5781de15ca775891e2e8c397b4f53afa9162450eb1e09deaabdc616227a0e2ab0eb32c800e837602ff7cf21959cb82c0c87c5313f2328d3516ccabf2680ca06c8d94d3591977a92da8f193e21275622ad67cc4589574033c97eded025a0d60a003c6ed7f4ced0b67a8459c0a99ba607ef2db9e98916f4f923e9af2bd1eae2d1da06acf2da1a1d47b6eaf994d32f6f991cb35095fc4178b32026182227a23c35009a0fd79d10811fe5b8f75077dd9ff52363915dc6e4d83a5ae5ae4e029e1f03543d080b873f87180808080808080808080a03f956bd8c44a9d7be9298f63278403b7e1b33227717b6626657625eb9f3c19dfa0fd96ad74cb7142dae07af9131f62d5e3a23a6233b0d73d1aafb12a0ec160d469808080a00776bbd5d115ccd841149960c470ac9e444010856d14987e7494c47813a8597680b853f85180a06c00ded51c34267fccdb1db0688a48706cf0bea7fd28a70193d4a2e0bfd2927e808080808080808080a0fcb61cb560e6d1ffbf88eadc60bc8cb593c6b088f79227f92beef54e5ab458b48080808080a1e09e20bfb62297e61f7629b2f51b1a4edcf7e8ecf6dbe50f9afa17c11f7d835501000000000000000000000000000000000000000000830518dca0ed2a8749a3816e817b88c3479df01d0685499e164dd0c803b84fcf1d5bb650eba02d3af26b95b65eadcaa4f0d71afbed99e19406e005cdcc3e3d51a2c38b6c4335f91d0e05850a3e9ab80083100aa394000077770000000000000000000000000000000480b91ca4fee99b22000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000003e0000000000000000000000000000000000000000000000000000000000004c1ba0000000000000000000000004284890d4acd0bcb017ece481b96fd4cb457cac80000000000000000000000000000000000000000000000000000000000aa36a70000000000000000000000000000000000000000000000000000000000028c5c000000000000000000000000d7fbf53d3e18372672e67df8bf83aa7f8ac4e2c90000000000000000000000000000777700000000000000000000000000000002000000000000000000000000d7fbf53d3e18372672e67df8bf83aa7f8ac4e2c90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001b88957d026000000000000000000000000000000000000000000000000000000000000000222e000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000001a40c6fab820000000000000000000000000000000000000000000000000000000000000080000000000000000000000000d7fbf53d3e18372672e67df8bf83aa7f8ac4e2c9000000000000000000000000d7fbf53d3e18372672e67df8bf83aa7f8ac4e2c9000000000000000000000000000000000000000000000001a055690d9db800000000000000000000000000000000000000000000000000000000000000aa36a70000000000000000000000005b9fedd37f0b92e7e282b19cebcf06f57b77c604000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000003424c4c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a42756c6c20546f6b656e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000380a44175b6e8d234a76c98202dbb7b012498baa271457d6ed1f4111d79c7010b201dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347000000000000000000000000c4bfccb1668d6e464f33a76badd8c8d7d341e04a596d8395e1c02ccd1ba1b826229b001759bdb9656a7f0ae7c0536efc55a63f8020f13ab81b1bc3ae52082eb26856839a49ef0573423b9073241567251e28b9d3b0d40afe714bb431c309207e5a97877a729eff49b6334dad55ebad5981d07d9d0240000000041c00020008008000000000000040000000100040400221000002000000000000405000000040000000004000400008000000000000000020000000000000000000002084010800000000010022020000000000000004000008010000040002280000080100000240080008000000000102000400001000030100410000001c0001608100400004040000010010b0200000004094004000200000020000002100000008000000000200002004000000000040000080020000400000010002001000000002000040000000000010210000000000090300000160000018020000000000000508000000000000000490000000000000000800800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003148f50000000000000000000000000000000000000000000000000000000001c9c380000000000000000000000000000000000000000000000000000000000027859a00000000000000000000000000000000000000000000000000000000642d144800000000000000000000000000000000000000000000000000000000000003003ad69e5da91cb5e54b112fd57b95b9046cb2eb03983264e65a6151b1a103c65800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009ca3963e30a41d2a880d35fb19d5b17a6f5ea2e6cfd506da3425ec598f1da01bf0000000000000000000000000000000000000000000000000000000000000019d883010b03846765746888676f312e31392e35856c696e75780000000000000000000000000000000000000000000000000000000000000000000000000014e000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000b600000000000000000000000000000000000000000000000000000000000000af6f90af3b90214f90211a019087213f44f688c0dcd49f983e583a9a329639709b1ee9a53101c23f26a0491a0fb087b9d0e040f002faaa7fde0e00785d52e65bab10aae8f6f9f77975967ccfda06806e17247225591351b0ef94ca66b243011f5177593a2b5781cadf7f4c414f3a02c15a958ac502bc76357ebd5227a147ab196da16a290d4f48f13daf5633e483ea0aaf5b7baf232ce3494ba8bc5a0f3e078816245087baf4f5a1a1d0751758e34aaa01c9abd9c070cc1aa478c5299ba183d910445d9d86e811d70a5a202d57a239b1ba073015359d4d590bac73425d43d096ec005f75bf4dc27ed7eef22bda4601cd2c6a045a19c11c50d7c744faeb9d064de95ddb60ca455f0f6682d8b50f62c2fae676ba037fc061c94b0e5a536a44478805429dd3b0110dee138f8ed80a7ab24dbc52ed4a0e65f4d9f4068c76e3bb660debec15576ed5207e588e22c9545d177db6ea1e321a0ce25e076b36d304c549c274777e72c5aed5ba0dfc471e670c53f4fc53bcce537a02dfe9fc01544248ebb72038c7a397231fa24b61e9ce9a5ae6e94bb5c2fcdfb1ba084f1962da79b4e6d7332a75b607b74a5cceb446115d2124b8e6c18a9b5373efea0582146f29eadb36a8a3fa5dec2985c3ab280326ffe759ddf6e43a1479c27a94ea0743ef5d9567359ac79d07652a3eb4376723965f4191df796919969db3470e4c9a08464b7740824eb4ef540072517c845aee4fb7c48c881049f38da2d49578326e380b90214f90211a0ce44a7136381da9670e6a6170cd022bbc27a9c37170cfc8f7bfc219b2c0faabaa0d12741db1e9e672829a34e0be3c0596ef6d6c5eda81db65b8e0921f997c5b279a0ae255bbec9240630c05df2f2cf55d2b4dde112e747fd416ec7403730d3d9dccaa0beb881a361c4a87d62fad952118eeae07ffbe058cdb1ff1854d79bb218c191b1a0af8763c3cf574f21fc7bbea6448fcf3c43998c2e6a1da2684b0f8fbe73ac9735a0374c4400cba54cad4956c667c623c5ed2b943da43a43759fb8a00264bb56b7c3a0806f7890e808603a81b7ab946b2108b84f9a52834a3a50c4ec01e712d287ba45a03ab50f5335e85ad35204b88ec7bb6f59286ba58ae8d2a6bb719aa9b1d0b581c6a0798f57b72788da7a66a0518bf5b5757b2953dc0fc24baf31ac21108598569ff9a0f1c4450cbf3ce67d50acfbc67efc17c9aafcad146c27b07f8c6b033d3b54c9fea0d5fa0dbfeb4b26cf8194bc284492e6b9da201942d0f534d0cee51f01622c54f5a0f72b2521817730b4360c256f002a55e5bfdd7a57dfd26a8a5253e27331402c79a063b19fbba61d7e28feb257250bd501aed1b5d090b1affbee3cc9c7b9e790e4b6a02490033191c954ad3f8deb6160c2ea280cd270ad6262c59d4117c7d03889ee38a0a77394ec78baf2d57955a44bb7610551ae052adf71a26fcc1094135b54f432aca0c425242acdc30f6ca12ddb1d00aee89d77e1b1128724690e96c6d08e1291754e80b90214f90211a0e2a7a4f00362bd1010c4e56ece897be4b0d0d63f2fe4eef9f826ae57b0d51451a09316d64025f33cf5cda2e32e7b40bd4ff31db2e99e106da4e4dfa32a42e48189a02292614c13e0cd22c7d48a1952468293b885eb3b0f9519b7ae4ae13ea74acd7ba0f4548120c1fbe0d005058e667a85dccfc29d53b9683cd95c0062efc93dd0d020a04f9eb068fca53d383732e579bb1fa11f9f6c8540b7dcca2972a1a8146cb04e12a0778d7699916e807277a84b80802760f27d2117d8400e5b65a43758119d3c0369a0e83a591cbb8140afb0c30d79b954642b779e4ea2d7d41d95ede952d936db7633a085263e23a13a7ef85543662bcde96e5f98475ca6fe7a7cf9734787cc78040559a0bd926540a9cbb9e49be905af3035947bf233f612775263a9e5a344dea5e59d55a03b320ff6896bfecc2ffd218c17f253b6ed59d712eda26de98689d74a3593080ca04aa12df643f7d663ea71f76983243c32f72ad1cfd56d0790380269ec4fa1d398a02784ea76fb653f621c955dc9b5c76b3aa101bddf0b1dc77b09d7193ee3977ff2a0bcb4f825cebdcd5d726bacdc4bbbd6dc0bf95672ee35e1a518c2eac429a76eeaa00b99cf6211844d2fd3b6ac0ab25cb31f135297e90f5c5613ca1fb35c16d5be4aa082331a041db97ec1b9a5b4feed27453d7fb7ab6647a50e5e0a3be4f858181b06a0ac395c2196d298cd789910237b87d2b85a5696d15ae0c48c167dd32e98607ad080b90214f90211a0fb8ff560ca9504c5b571eb6a26c4a9e2b1480b1287e086fab1794517ea64dfdea096f8275a2fefa5ae97c7804cf017a46ff8da47113bc4a93a0ddf991bc621a8d7a063854d37d08448143def60bb81b6eef240a6c22504b6e2199b3d3f8c9dfe63c1a07b877adb359eda7830883ca8a3387da29ddc0422280cc6a7a98ebabc8c0dc4e3a0941d5b10d77efa5da043478200f2094bdb78504d5ee6eeebd92fda34b2151e35a07e53446fee6bb173e36a191fef2ff174b493be5c5d9c38f0e1af97144e025f61a03da10497ba8eee352c98ac78d7f55c297478196d048d93cfe2298ed889b9fc35a0b01689a2bba4a40e9c901e6ae215e5acdb2cfa42dd0af19607e1ef4b374108b5a0567e23606d43dbbfb8d35c52a876dfd411a7c5a66997319df928967ad437893aa0da99677795f76062a5c1927baf3fa32fd66c64e3ce8d0d4bb55685e7411b307aa004e6bc1d64ba72d89542266e946e7b24413131de4553934285f53dd2d966f14da0d18e5f84e70f8f4c8d62d95901a22e2f1f99dabd2fb79126d97e3614d2feb06ba0493e106ecae86a1a4c1a34fd2ddbc5538dc275838f82e7e17295e6f309196d61a06c5fa2d0981473409efc193cef5faf4328a50fd0716c7e0b4051addf7e5fef27a0ede98000b5e538c24d1d428f46f9bb60f4fd869aeff5cfe6432259e861417ceaa09e3548a8b2c15c778d70010e9ff5a82005a5955a55a1d1d3c7f13c1c5bfcc15480b901d4f901d180a03a82e40aac6b4b665b910256c2ac0673b9b8c7e2c18b846fdb17b19b38c79a01a0c2810e576f9a91de5be7774f18bcd3b8f32020c1b9051d7c6bbf212f954acad3a0e93274f3773d34269a28f86cd1c6dafd18b30f42f29808932a5d00c68c60dfd3a0b5208edc16ec4ebf968be0767439f69f24f3511c64fd2e1fec45be43a15f591ba0238e86031d6f812bfbfca85d204e6676534aca4a1e84d29260b2d1d48a687961a06f05395b7e998bfd1a5c57183a670b397a4aa50b0b102243d474aa724d89a46da0df367e8b5585cbc73aa2a0e9b06e138d7fda554b4fd3839fbc5445958e7d8313a0d3ef4210936892dd7a4b3fa191bd56583dd4b73b0d20c4b4ff8632ae09934c43a0a10cd7efab9147cb2fcc9cbbb2e67e09aab92542f970446b4773a2f613b0fae2a01f6b383ea1e5dadbc4bfcba833902c120c3d0448d04daf725df9f3afd619aa53a0c2fe0a493bcda2348f94385b85a2bfb882be9da8c7e46b4ea8ba5ef7462523b980a069cf29178b35168344d55ac9cdf13b3c9517a2099aa7b6568319e02c03fe0313a0a155a41a0bba49577953fa96701b75b3dbdc8c334824f34a702e2a84da00309fa09d6ad83ab9088859dca18089953e4b20f4ee820b09c6300ccb4533fafe7a648a80b853f85180808080a0bc3bab8c81feae47b198f1bc1f2b9728336e3537281a2c6eee74d1331903b44f808080808080808080a012ef7fc37216a7288d799939f075fc145c8aba8774d94e943353c8e96d5ae7fe8080b869f8679e20016e8b63360d8bcd376eb61bf80f4e2e872ed064a0eac1ff06dd24db81b846f8440180a06e5f26163739b4053f6fdb1653ffa968e6e000f2b18b91f76234eaa0729d0caaa0b16944c8bb850059f91dc8cd33437c5002f7b19b721bfe36d3c5122cd47361cf00000000000000000000000000000000000000000000000000000000000000000000000000000000094bf90948b90214f90211a041ea73d589b499b3ca297f66d72fd42d32ac894d7342b9f1f5ba7df0766cc88fa07a762cbff3e0e9b739b06be7f151cfac3e1fff0cbc478a7df06a80d0d237958ca0f852ed745b6b938dfdfdbb05907bd125d062d9bdf153f14b91965fbd373b4aeba095057628aabdf0895061932a702a7c3279cbc86fec951f3a9ef979b63bf77c42a0dff38b4d64d00d06db4cbf74f9277e58dafb07561745d5a9aaba45b02c344a68a0e742f0ff9b0c6b37825e640721e8f52e28f7496113dc739df7909f98b8d107ffa08633a70716914d7e00573b6062745303dc8c50b532511667628f3036b0f0d88ba02c7fced9043cdc8a8ed118b39934472292b458ea7b48892fcb7a917719bf6aa3a098b3b17535b51569cbdbc27c85a4a42b644a4ac78fa4acdccff33dc90c596f33a0f2c484ab188760c2ca3253316d40b8668e7a3edb7485422a15ee0e1bad6bbf57a0dc8b8508c79a703e331d2cbd5d336ad327ce8047ca3719e3f4722d816871418ea07c9c89253637b06276978263682f31813025cf1e3e19cebb9b357783a09486b4a0cd74cf3e3946d2f8891fe0da0228e060b1147b2f171ce4dd8827ab70717eb767a0ab1f8c0851abae9f70f3d4fabc621a26f9113c9987a4ec6755e3e41717f28d66a0a28ef869f39a2b28799d430b3630ba2fe5a2fbb3e646505fee166c0dcb48c785a09b94dca3e9dfe985430f13bb45a3b699cc3a83498bc2b3fc5e31c305eef0960580b90214f90211a089201bb14180b19fb7df34063be2a7481b966e0e6272c36f828fc2a72a8630e0a0c90abd0029dec4e29c90aa6f351052601963d9c4b46f4e9fab46fc01bfde74c5a02adfeb4442c94f1f7c683bcdd5a33ebd1f30b7c20b68de726047f77590c94461a00ef122f9df924fa30e3a5356f189d21277bc242505ef320cbef05199010cf434a07811840bf06d862d735b4d6bfaf7d0300b789c64951f812114792a46f510de4ca0b838654503c0c0f1c717c30a16ddf1cdddaa1ede040d866f94e45368c6251c34a0a755455454546f6b85ea2c42097814835bb0e1ec30ace8654754534a974da5cea0bec74448dfd5902ac00a46e19f1e01ddd01219b3168d9debe9337b0b94037fada03242d6db52f2282a11853e9e19eb7ce48597e28e1317460a170999fa42d01b7ba0513c5c46a49afc25311a73f07eb8dd5bc47acdd97da2d5a8624d045cad1c3465a098a581e4a4c691bedd27e92aa5777ee4c7d9e5a7f1576d9f269d4f7cd0b77b97a0f6eac7ade1285bd9cc6691590979b2cf9b97a9e2068d5e26bdebb689b2eb6e92a0e61db35edd0fe645ca88f6d4dfbde75dc30024e43a776b22c57d3e398876ad88a07c07253ad6c92a1baa55c1dce017527ee7bf3612c5b0357e919b5f9057aa0949a05cd25cb29d58fd8b189695a7d96642334c84ee6454d932567f4470a3388ef80fa023951d6382b1d670313b2b6688987c86ea7ecbca27db72b0012fd43a537ff1b280b90214f90211a076814edc0895fe07658ada513c48af2f596ed7a9b611be321fd40a2f16194821a00fd1ff4f6c03b018f613ebb17d3a9f9a796bb00d733771f7d70056ac83587a03a04628bfd681977471eeccb07d549d480413dd931ed52bbec7db35ffe853b7462aa073d8cdacf622b48eeaa47d955641e85c40e7b3876b2e31ed9d5bbe9acfe4d213a07c35c17c3dda60e885ad10bd1f208ada6fc7b59b72cdcf493a6122fe5a3dcc9ba0db94a6cedeb519468e034b8199b4af37df3afcbd4ca5bad43c9cc8c6656ef3a1a0d4383c73c539c0fb0c01aff683349a0532efc1d9fdfe5f547d9c8a59bdbc28e4a0390e71a361ad7616a6e5162c535767ebcb58dac4717602e2b4842ff11ca95180a01bf070fb6366513fd315ed8dbca5a638c1cdd018f31ee419b183012599c75de9a0d0e359814cd0c97cb6a3784dec04ff63b832d0d41e8591cc4359e68d875eeebda08665f1035982d0d07e8fb80deddd8ea09180acf2589cba51fdd54e58131a1980a0710fc2165bb51a3c6a6c1f64dd03845da5e7cfc42fcdca6a60083213faa42d82a0e0a633f23669f0a9c333455b15c4ebf72b80f2b1dd4666a25df7f6ff0c8c5531a091b03b12098b70acc3ea664805b9ce003480085696d15ad3c6a1df64fcb495dea06d52d15099a0ad155e272442cdf9348300b50818edd35e313d160f9bf0888052a0e76435832c5426c1dd744e8e67d73e10b62793144c74517542e16e673bd5c34b80b90214f90211a0092e1220355187fac17a3eaf00596827d709338f5d43320381109596f2de9063a04868b9d1ea13db80e3a084c78eb5c5ab1ec9f369b100a85476a420c111d97a17a09c80c33524dcb325d9437e92fc367936c6183462a52df740c175898def1836c6a0258f325e2e7610aee21f183abb6be744118f289f0c53f3ef1eee232ff31bf9a6a023c16f96779b17da4905b3a5db19f681502c30f35a22d5e02ba9b96be2220970a09bd09a4616c3466d29377c99dac342e979494a3ce0d8d427dc231480fd520feea00b51043a67bcaa5bd08c0d86680fc95fcc131c919701b3f290ef541d08b9e7e5a017a361e510305ab01f0215b581c0d3be5ed04b445fc55d3ca9b6d61b2b92db3ba080c1ad78714bdf4301e7bd15520c6138825a5f437213a4410755794857b831b9a07ba9f0216277f53ea6491be0416497c4bf8a17fda48f6df5dace66e1b54ee74fa070ca4b58e48b7f85b0e9cccd7ae45b7bfd1aa32b944d259e92d2ae1985d702c7a0b5610a1133cdc9946048d3f1a7535e7cac687027f2a27613660265bd4238866da057b5f8e30cd24f15ee4ae6e37ea6943a7d5e2004cc6075b399c75db3163642a2a027fe02fd5e8e5e5ef339cb6662bafd4581f176154f9394bace17850619d3a36ea043e186e6dd5d28e5518b833e52b468fe2c0a3eacc5dcbb343349670506303acea009d38fd63881892d26b3d8568be37ce5f938266249512584f277b57bee68fb7980b873f87180808080808080a037bc769ec3332f0db4f5236033c8caa5bc7cd3e3f8e7c1a6d545d58edc467980a0b72651e2305a4bdd706c066b9710bcc5a5da25fbb8fb1a741150c42537027d7c8080808080a03fc64cabb2a299de986e031e44556f1b13b06823cc417ef76bcf9c7c185f16548080b853f8518080a065849fb1d635249f88023195daae6e05e4dbca1f8b19d795990c88eab40e1c2e80a04a1dd3c44fdc0808d8d1c05ab23bbc1f0d6d459e2fb92b12525286d47bf84c3d808080808080808080808080a1e09e207bcbf4b320d9565d4e40863938e75405cc2a240dffd3b8f7d37a7fc0ff01000000000000000000000000000000000000000000830518dba0abb10d4aa5a4c17595500ddc9281ce7df349cb94ee33c0a325cb6cfb5a6a3c9ba00689d7118eb556b5859aa88b78f908174237397f333ee01913fd191d15bddb64f9019520850a3e9ab800830389569400007777000000000000000000000000000000028703e871b5d7cfe0b90124ee1490b20000000000000000000000000000000000000000000000000000000000aa36a7000000000000000000000000b2fd0dc2c2e7b8b3da558e7c6da444770945646e000000000000000000000000cea5bfe9542edf828ebc2ed054ca688f0224796f00000000000000000000000000000000000000000000004ab248a86a443cf33100000000000000000000000000000000000000000000000000000000002fe9a00000000000000000000000000000000000000000000000000003e871b5d7cfe0000000000000000000000000b2fd0dc2c2e7b8b3da558e7c6da444770945646e00000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000830518dca090f8cb38410c4e5f51f1c3dab9fad9107571cf2985e350736310fde6b0e02404a055f0571255ffc9d2f8fc6784141c2a8c62c8ba41c3248dde022329a773c486e8f91b6e808509502f9000830f180694000077770000000000000000000000000000000480b91b04fee99b22000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000038477000000000000000000000000485f2de5569a504ea701162f4ee235301c1cab2c0000000000000000000000000000000000000000000000000000000000aa36a70000000000000000000000000000000000000000000000000000000000028c5c000000000000000000000000485f2de5569a504ea701162f4ee235301c1cab2c000000000000000000000000485f2de5569a504ea701162f4ee235301c1cab2c000000000000000000000000485f2de5569a504ea701162f4ee235301c1cab2c000000000000000000000000000000000000000000000000016345785d8a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a5886a555c952000000000000000000000000000000000000000000000000000000000000222e000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018c000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000038012823b70d9b15f6d91739609b7d182ecb6a57964e186d5c4b4b900226d3364251dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347000000000000000000000000455e5aa18469bc6ccef49594645666c587a3a71b7e9cf267a604c9c38c44eeb5b4416231ba157f385728e3f3c65875c3714d6bd82418bfb480a9bc956dedf1e95e81bd8ab52a0e648c3fc15beda5cac1c9f55256f3492058a4aee540756073d9f9ae5acb218ca2adfac746f3a2ff486b24be3ce400000000800000000040000000100000000500003000001000002000000000000000000000000040008000000000000002000000040000000000000020200000000400000000000000040188000001002102020000000000000000000000080000000000020100000000000002020902080000000000000024000010000000040000000000020000010000000004000000000000000400020000000000200004020000000000000400000000000000001004000000000000000000c00000000000020002001000200010000040800000000000200000000000000000000020020018020001000000000000000000000000200000101000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003148ea0000000000000000000000000000000000000000000000000000000001c9c3800000000000000000000000000000000000000000000000000000000000a17f5500000000000000000000000000000000000000000000000000000000642d13ac00000000000000000000000000000000000000000000000000000000000003000d5b96fcf24f97334763c284d18e74a1977bc6e118a0207cf8b99ca1f7037b3c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000813ad9dffe265df3d9fd155afe856e61538a665e864cf6a97a5bfdaa155874b870000000000000000000000000000000000000000000000000000000000000019d883010b05846765746888676f312e32302e32856c696e757800000000000000000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000b600000000000000000000000000000000000000000000000000000000000000af6f90af3b90214f90211a0e30639f36b4f7e8dda04e70a6adf46bb204483197bf989493da77d6d9c4c3a7da08b28f54f1e6fe13276e794bb0aa6228d0fd66f39111228e8207294e57c5788afa03287ef512557901399fc9b36c886fd4449d7f7e21ecb8e9606a8dbf53110d29ca0b34b7c77be6718012ba8bcfa4bfd3f8f99e85e5c07d4e3da98b9d2ac22b8062fa07c2677985344c377465b76c516ad97f6e507ca73a6293e3d92e1e5d1f021513ea02fcaf4048f087d7f1e26f3bac80925a2d5481e3a25110b3f2a5f388db1516986a04a7f47f0d0f928ae915507126f6e6d4429308b8327295460db833498bec11722a023eec22e60be0b65237da54922ca7f9ff9ef12bb2ea35d1b9ce38f8f2b66ab60a07bdaf46d75ce4d8429fed261e9673e7cfebab1d048b11bdc38f72fd7aad937b8a065193dfcd636417a3664080432b78fe4a6700703aa363ac11c6d63d4d5cc623fa041fe9f162a0f5be223c14f9956113a1c457f0576b91cf051b453371834a81846a010155771c6678681c2c8f566ab512fc0ebeff5192645d97411e451713602f847a0ccd7e792c7062cd05bfd887eedde84a2035b0400bc6a1700c9227bfc2593c9cea0dce33695bd479ca72de377c4aa89c01824099c9ab03652414c7e8d8dcd625974a05991ba033f429fc26d03ef859889ffd7438fc2fc0e01baf30e76467680a4c447a0809cc61e72a3b6c9d7daa1b0c6ba85adf10d16937b71271992c950b013c2da4b80b90214f90211a04168a79841ec63f1a27be1f13685a1a5fb73316410852540dd69c1dc354ecde0a08b39f24d9a123f404f7d6e8d9f2f5b138c7d748895076a44ed43ee4b4b3fbb4fa0e5e59873fdb14815394d861c1ba6a51682d5d4465bb4a10bec975ef9db599517a07a81d42fa6b60f8556e1e1f9b3a48b1d321fa3c4eaedcf6b62209704b4a58c2aa0978b4d6a9b154db57057c7fa36d516b68fd509b741c62655f76edcf14075076fa0374c4400cba54cad4956c667c623c5ed2b943da43a43759fb8a00264bb56b7c3a0d037e1cdc4dea2de2a42c68b171f85ab68f7f51bacfa41dd6f8c64a57a1a5f7fa093b12cb830bc3a9121b799da0be5a8d8a6682fb31d3c2892d5e2490690266af1a01e85fc0850a48e747dc9360238a6d04dab5189551c40e21bf475a3e36a566bf7a0907333ae3fbdf50263770f5a2d595329f5569d5b9c08023d79c01f5fbaf1f1ada0864910243de5af344acef3dbea807b8043537b0e5dfdc430f6917ae9e7c5e1c6a0fe82de6d286cd5f8c1cb3509bf4ecd8081b3c08ab92a2c752d7aea90e1204356a0058afdff89116e9ba922f184b932e53610208a9897e4fce11bc36929067fa422a0b9816c9c9a8b563e0d5edffda89bf316985bfd341eb5f09c28daddbc4dbc6e1fa054ff13ee87def15b2ed83fe56d99ca15f5a3dbe2321a16d18494a0e5241fb277a0daafcb8d2b18dc684616d118eebc77a0e892c9f617003f0de0098ac555290aae80b90214f90211a01767acda67ad081991ce0902646b21161177aca7aab2bf09c9d3577c8e996850a09316d64025f33cf5cda2e32e7b40bd4ff31db2e99e106da4e4dfa32a42e48189a02292614c13e0cd22c7d48a1952468293b885eb3b0f9519b7ae4ae13ea74acd7ba0f4548120c1fbe0d005058e667a85dccfc29d53b9683cd95c0062efc93dd0d020a04f9eb068fca53d383732e579bb1fa11f9f6c8540b7dcca2972a1a8146cb04e12a0778d7699916e807277a84b80802760f27d2117d8400e5b65a43758119d3c0369a0e83a591cbb8140afb0c30d79b954642b779e4ea2d7d41d95ede952d936db7633a085263e23a13a7ef85543662bcde96e5f98475ca6fe7a7cf9734787cc78040559a0bd926540a9cbb9e49be905af3035947bf233f612775263a9e5a344dea5e59d55a03b320ff6896bfecc2ffd218c17f253b6ed59d712eda26de98689d74a3593080ca04aa12df643f7d663ea71f76983243c32f72ad1cfd56d0790380269ec4fa1d398a02784ea76fb653f621c955dc9b5c76b3aa101bddf0b1dc77b09d7193ee3977ff2a0bcb4f825cebdcd5d726bacdc4bbbd6dc0bf95672ee35e1a518c2eac429a76eeaa00b99cf6211844d2fd3b6ac0ab25cb31f135297e90f5c5613ca1fb35c16d5be4aa082331a041db97ec1b9a5b4feed27453d7fb7ab6647a50e5e0a3be4f858181b06a0ac395c2196d298cd789910237b87d2b85a5696d15ae0c48c167dd32e98607ad080b90214f90211a0fb8ff560ca9504c5b571eb6a26c4a9e2b1480b1287e086fab1794517ea64dfdea096f8275a2fefa5ae97c7804cf017a46ff8da47113bc4a93a0ddf991bc621a8d7a063854d37d08448143def60bb81b6eef240a6c22504b6e2199b3d3f8c9dfe63c1a07b877adb359eda7830883ca8a3387da29ddc0422280cc6a7a98ebabc8c0dc4e3a0941d5b10d77efa5da043478200f2094bdb78504d5ee6eeebd92fda34b2151e35a07e53446fee6bb173e36a191fef2ff174b493be5c5d9c38f0e1af97144e025f61a03da10497ba8eee352c98ac78d7f55c297478196d048d93cfe2298ed889b9fc35a0b01689a2bba4a40e9c901e6ae215e5acdb2cfa42dd0af19607e1ef4b374108b5a0567e23606d43dbbfb8d35c52a876dfd411a7c5a66997319df928967ad437893aa0da99677795f76062a5c1927baf3fa32fd66c64e3ce8d0d4bb55685e7411b307aa004e6bc1d64ba72d89542266e946e7b24413131de4553934285f53dd2d966f14da0d18e5f84e70f8f4c8d62d95901a22e2f1f99dabd2fb79126d97e3614d2feb06ba0493e106ecae86a1a4c1a34fd2ddbc5538dc275838f82e7e17295e6f309196d61a0bf3e450b07bbc9a997d408aa561f958551b9152fcdde28860881f1e3e6f8b43ea0ede98000b5e538c24d1d428f46f9bb60f4fd869aeff5cfe6432259e861417ceaa09e3548a8b2c15c778d70010e9ff5a82005a5955a55a1d1d3c7f13c1c5bfcc15480b901d4f901d180a03a82e40aac6b4b665b910256c2ac0673b9b8c7e2c18b846fdb17b19b38c79a01a0c2810e576f9a91de5be7774f18bcd3b8f32020c1b9051d7c6bbf212f954acad3a0e93274f3773d34269a28f86cd1c6dafd18b30f42f29808932a5d00c68c60dfd3a0b5208edc16ec4ebf968be0767439f69f24f3511c64fd2e1fec45be43a15f591ba0238e86031d6f812bfbfca85d204e6676534aca4a1e84d29260b2d1d48a687961a06f05395b7e998bfd1a5c57183a670b397a4aa50b0b102243d474aa724d89a46da0df367e8b5585cbc73aa2a0e9b06e138d7fda554b4fd3839fbc5445958e7d8313a0d3ef4210936892dd7a4b3fa191bd56583dd4b73b0d20c4b4ff8632ae09934c43a0a10cd7efab9147cb2fcc9cbbb2e67e09aab92542f970446b4773a2f613b0fae2a01f6b383ea1e5dadbc4bfcba833902c120c3d0448d04daf725df9f3afd619aa53a0c2fe0a493bcda2348f94385b85a2bfb882be9da8c7e46b4ea8ba5ef7462523b980a0d0af2c60146ca870fb47a71d6deb019df6d90aa7cda6c7407009bda2a23d5cb7a0a155a41a0bba49577953fa96701b75b3dbdc8c334824f34a702e2a84da00309fa09d6ad83ab9088859dca18089953e4b20f4ee820b09c6300ccb4533fafe7a648a80b853f85180808080a0a3f51c2d0692164012dc9bcf40ffbd3578152cdb07fad54121dbc37d1e3abc71808080808080808080a012ef7fc37216a7288d799939f075fc145c8aba8774d94e943353c8e96d5ae7fe8080b869f8679e20016e8b63360d8bcd376eb61bf80f4e2e872ed064a0eac1ff06dd24db81b846f8440180a0c3a9aa0c9b4e4ac49ceda1e79136460afa072dc8a5c06a61afaf0acdcf2f3dffa0b16944c8bb850059f91dc8cd33437c5002f7b19b721bfe36d3c5122cd47361cf00000000000000000000000000000000000000000000000000000000000000000000000000000000096bf90968b90214f90211a041ea73d589b499b3ca297f66d72fd42d32ac894d7342b9f1f5ba7df0766cc88fa08409a88a9cd0446e5d86cb48699da9fba28f16bccbaff729f40f995187de292ca0f852ed745b6b938dfdfdbb05907bd125d062d9bdf153f14b91965fbd373b4aeba023d3a917bec1f8ffdb722b43a2fbc564d88e2cac88b750f77c4b24ec2f60a5eba0dff38b4d64d00d06db4cbf74f9277e58dafb07561745d5a9aaba45b02c344a68a0e742f0ff9b0c6b37825e640721e8f52e28f7496113dc739df7909f98b8d107ffa09c7d25dc86534637ed0ddca306af8ed926c69327a77256d656be65c574f48c39a0955aa5238a644da8f41346bbbbef37a125ba325cd82bd8c828a90fa62b25e3d8a098b3b17535b51569cbdbc27c85a4a42b644a4ac78fa4acdccff33dc90c596f33a057eb0ba87b13ebf4a0ac86d488057a133a456573121a03920d6b016a5fce5463a0236bd37c9f80cc33f7c13e0d8d762c7a9ef57d198bdff09074bdd0c61640a174a09d8ce5996a6cb45c4cd772058d9e451559412d23e4e8649abc7d15f66620da22a0622ea2bb068aff3062c77c06e2f4ee3d77142278fbe763313d24e26e0c9da1dba0ab1f8c0851abae9f70f3d4fabc621a26f9113c9987a4ec6755e3e41717f28d66a01edd4ebccdb98e98cb368bf113363e18d31c8a5045ba892184d1a1e7812d9343a0f9c3d074c6ffeb0ee9a54072526219c148471588c56867dd90fee70f9ff9b69e80b90214f90211a0ef35ebc10af238adea3cfd94edb733b63302f5a9a711628f26bd8e9c1ed5b85ea0c3d41a4c9b3997884183896e3c650ccb9fadb4e33076ca358b07e1bf07078594a085a29ed883efab0c8334470dabb77adc7f167cb67bcbdcd2e1758f1035f93cfaa0e451fbf995657f8cb28e2856665852fe413a31bb9474ae79686267262ca55079a049fa5a9ac382be66ace1d14c4241a0c40f5dabdacaf7b9c21e62ab35d97707e6a00dc228f7da2aa8f32939e493ee932134c6ff7392037f626b30248dfe0ecb9d22a0b474a23c26c6a63ac74bebeeb067584c39689b7634458b44f2c0137462d68088a022b697290e06ae32434d2475772462823f5737fa90015508338be0999d21878da082dacfca193987b94a1d121c60a95e7353dffceaf6de6e12ca555795f6370139a06131be7275213f6deaf1d2cb00b86206fd6316151a444124fe52e569e853f21aa066ad2a157f4ae81dfddc8d607d25f47d5d78f13004c724b6d4b4d8c97a989a93a06910ce53afd6e378ae9ddae2c18083738be6187e08e30f522d4012cbad9a8c72a07f118b2da0b7ae475be06a6848cc5fcfb84d61157f0c015fabffc84c3032a90ba04187f4230bafd2aa02cfeff072b352c4cb69608556487060c9605d63cde0f592a0620bc91f688b094206e63f99af0f588e1e0c34b4d5c730d50d9a6e0116459a44a0a4117f732e200c2e5817e83040900fd27af1f453188f4ddb338558078969af6f80b90214f90211a0c094b100f8398d844396723498fd0962bb5c4288212a8ff304c0d70c10dca6c6a02e75e7d79fd0fa9f6da10a0700e0c1b1ed932f8a99810c44babfb9ff75bd16c3a0cde74cb1e0a33182a8f3e50b76163dcbf304d667e38495280d5e0c2bf22541e7a0ee94499ed79fe328dd65a0e2e7bc9c6156e315b5d76881e9e53c416378ac8ccfa0b982f68b8ee4c39d25c74af3de3969447068567825b97dffd4a70b5f1047de70a05ff44a7bb582930859321130d46489efdbfb930b4568d10779b230884aea6bc1a03e76e4457a07d55758cb4542f59b143615428024a823bcb21c9b2d9e621a583fa0374622b546d2fdf29ce25bd6a47755110cb9d4e674a1259979a8ae7b971478bba06b6a8b1b89c50240bfab8eb7f98530bd20e166049b73e07ba98001374b9262a1a0265c7d0ddc2bd1d1732a5c341b26aeb99c324a005dc22c81f160aa2520df75f7a0af9885504e2d9bcf536f80c60f3f662533805d89971fe5d00a0aaa9d0530fae2a04df0c53be7f9bbd3ecbb0243d5312298939482b82c8eaed906c8265c916a19f4a00145ffc14555f9ae81e8c4540da0f73eb58418ac99ade8c78b248f458bfa8dd1a0234d972256b55fec4a83fba4cd0f952c342cb5e3d52fb879841ebfa88b6865b2a051997e3f9206b9b09c5ca7326dc448f123158e4c454917fcd13e3254c05eeb70a0609a0630cb48a43eedebd57516a220ac8e34faca884126fc25b78af8ebd8d9c980b901f4f901f1a0414069dffe8252e52a1a8896384784ef1aabc71ac8719e92e7c63960f02ecf34a0254db1a77f0c2288a0f390f691dbd08226b6db72d6a0b1dbc135e7705cf5e7bda052be66186fa5334849180233f16120b5baefc73bc99b89a665e84243eef8b982a0ae2b3fdc9e20552ea4a446493e0114ad56f39eed8184f1ce80dd5d63adab0bc7a0f645824e46620c0aa97a23502c9e271a3f510517f9c19f172103806287155d67a04f64fbd6f9f28c485f0fa46c55e0318ccd8c33bae97b2bf47dc0e2d77e5e05d1a0b4153067f6b6eb040fb63ab71bb4321cde525349bb11e411fdbebfe5b256324aa029bf330284c50674f23e35e251c52cc0c7d4c835cb9368ca0936bf07fa458706a04f3a05566c5cf1284c0d281507b12c0492cf8cee077fff204d6cbc34efde4d5fa0eae652fe309e69fef05ff51f198a241df3d5ddf772c15f0ed2fae5f30a037f18a0679aecc867f03867b8c4dfdfd28c4432fc6672850844a24c941ddf101c740651a0500aa8840cc931ee91740358021cb6a687149300c8edf13e79b1668d47aafc5da02d25b017323c0d995fe82f1f6312b721426d28e14c35ad5f82708685a7d47499a0bfb65c61addbdd4282051105c450e6f67129c306f4e6fcb44bb8392a0c0266cda03fa25bfdeacbfb5791361399d18a053de988b0eead21f6514a12431c5862c46d8080b893f89180a073fdf1307b9d69ba7c0da51a4d6d32b591523f02b9e627bd6e97aafdc4563db480808080a0c5bfa6e8b459945156f33737f4697e53bbaa100fa50ae9786b8924f791f15efb8080808080a01f1e2c58b1eaa96bceb967b8881d24b05aad95eb5a718aad4713a08f0f17885580a0bfb51940722cc8a40fb96c9371ce6d16a31273e4ab9cf2469a06a6409ee0fe518080b873f8718080a06950e9dc1e08db4958546dd1c1c4f04c2ab26e15c6898b5456b0cd0aeda480d0a02f092488a6ff995d1cec3e0b77d75ba474f3e3bc64da7b7a757e7a4389594b01808080a08a0627e9d8f667102e284ffea65f818feb1187959d9908ee07d464e230d27d61808080808080808080a1e09e206bb61e2074de886d6d4cdc48df7562b7f63e1d7457cd7881164323190101000000000000000000000000000000000000000000830518dba0359f2a8467b2f212e9f540083652954389c9bf2a55f1d8dbfb39ec0531da6972a071e059149dac7a8c03fa165d6a5dce7193e6a114681d9517f5b38d7d34cd584ff90410820a788509502f9000830f424094fa1072f0cdbefd5b8ddeb64ffd2fda8eb7e1cc3380b903a409779927000000000000000000000000fa1072f0cdbefd5b8ddeb64ffd2fda8eb7e1cc330000000000000000000000000000000000000000000000000000018750152ae8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002540be400000000000000000000000000000000000000000000000000000000000007a1200000000000000000000000000000000000000000000000000000000000014c08000000000000000000000000db5c4078ec50ad4cdc47f4597a377528b1d7bcdb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000001a42e9feb79000000000000000000000000ae5c05d961b834bc5752d4bc6774b1d47e53a64c0000000000000000000000000000000000000000000000000005915cdb3384770000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4fb3bdb410000000000000000000000000000000000000000000000022b1c8c1227a000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000fa1072f0cdbefd5b8ddeb64ffd2fda8eb7e1cc3300000000000000000000000000000000000000000000000000000000642d18690000000000000000000000000000000000000000000000000000000000000002000000000000000000000000eac2bd4753c659c909c92f62b3b3a8836c2bd86c000000000000000000000000cea5bfe9542edf828ebc2ed054ca688f0224796f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000420990e2c26966b1923e150eb584d99556a49f5bed5edd719ce87639431260afec079f4e529e02697b2c0fe1bb45565be94b40699438432bbd11072363a64faceb1b02000000000000000000000000000000000000000000000000000000000000830518dca023938095c841c02c94271e4d5c71490f4b09799f102e453897f99e425ac1866ea052eeb3d59062ba2e61d5d5c0d4f296d243fc804960bfab1ebca57149eca354c4f904108207118509502f9000830f424094810964c10ada4289e6c860eefa5bad4ed3a6b04480b903a409779927000000000000000000000000810964c10ada4289e6c860eefa5bad4ed3a6b044000000000000000000000000000000000000000000000000000001875015320d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002540be400000000000000000000000000000000000000000000000000000000000007a1200000000000000000000000000000000000000000000000000000000000014c08000000000000000000000000db5c4078ec50ad4cdc47f4597a377528b1d7bcdb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000001a42e9feb79000000000000000000000000ae5c05d961b834bc5752d4bc6774b1d47e53a64c00000000000000000000000000000000000000000000000000016bcc41e900000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e47ff36ab50000000000000000000000000000000000000000000000008daec643bfb5fe9e0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000810964c10ada4289e6c860eefa5bad4ed3a6b04400000000000000000000000000000000000000000000000000000000642d18680000000000000000000000000000000000000000000000000000000000000002000000000000000000000000eac2bd4753c659c909c92f62b3b3a8836c2bd86c000000000000000000000000cea5bfe9542edf828ebc2ed054ca688f0224796f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000042260055507625a83c3cfff9998d8448143be49dc90739579ef0952e6f5a5deaf84a6c6ceecb56f315f4870cc67684b8bb59cccac49e79e6186d6ffd71a95918191c02000000000000000000000000000000000000000000000000000000000000830518dba08e14fba1eb2c1e46e275b64fdd83976f8c741a835bfbab4d1d480b45c438d4a5a0167506d4eb7472a0184b6ebe2955980fe4dd8b1171488385a3802ac6751d9561000000000000000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x3b9aca12', + v: '0x0', + r: '0x942d68bb5bf34fe4d5962563146087af5c576d1c13d6d941c48c9e885136decd', + s: '0x1f313b27a79a2983534434bd407a7dc41edb5d4aafe34858034fc821973a66f1', + }, + { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0xd5ccdabf11e3de8d2f64022e232ac18001b8acac', + gas: '0x324a3', + gasPrice: '0x286c1ae5b7', + maxFeePerGas: '0x554a616d08', maxPriorityFeePerGas: '0x3b9aca00', - nonce: '0x1b86f', - r: '0x175362275825f1596f359970832405998bba012efc299cef4d9394f06c6b9b75', - s: '0x43d9acb8616d9251462c23141de510f86ea0f531247e04f3d34636f8dd391411', - to: '0xac9251ee97ed8bef31706354310c6b020c35d87b', - transactionIndex: '0x16', + hash: '0x6c6053b2beef9a1bcdbb88f5f3503cbe1c7a0dcfed98f90a1ab29ce2b57ee331', + input: '0x6ceef48000000000000000000000000000000000000000000000000000000000000000602cc8e702fecb5aa16917ba1293b9abbfedb56e53f73e0e850347266d01da799d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000020000000000000000000000000095f29fee11c5c55d26cccf1db6772de953b37b82000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044e677ae3700000000000000000000000019518ea0a601bae86b542cf65d73376e0a446cf3000000000000000000000000903ca654f4ef2d3ce8a63f4dc58e53d2a5468de60000000000000000000000000000000000000000000000000000000000000000000000000000000095f29fee11c5c55d26cccf1db6772de953b37b82000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000024156194da00000000000000000000000019518ea0a601bae86b542cf65d73376e0a446cf30000000000000000000000000000000000000000000000000000000000000000000000000000000095f29fee11c5c55d26cccf1db6772de953b37b820000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000444e847fc700000000000000000000000019518ea0a601bae86b542cf65d73376e0a446cf30000000000000000000000003c1e13da7fcbb30c7695efee5ce9a800d27c91f800000000000000000000000000000000000000000000000000000000', + nonce: '0x6db', + to: '0xbbe8e8358b227eaafe8ab9746f28bd0837095cb9', + transactionIndex: '0x29', + value: '0x0', type: '0x2', + accessList: [], + chainId: '0xaa36a7', v: '0x0', + r: '0x0125c9bb3d5efcecfe43e8ee0b6b5f3a088af3e9c726e6fa15d5d6fcfdbeb9f2', + s: '0x5467cc40da110f7d2e20cd26892bd6d8407fe1153538976d5c9e474461f3d8d3', + }, + { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0x9a94e121de3a8715dfadcaddb5f4cc4138dabbe2', + gas: '0x67fc', + gasPrice: '0x286c1ae5b7', + maxFeePerGas: '0x554a616d08', + maxPriorityFeePerGas: '0x3b9aca00', + hash: '0x2bd33e3268d6865b3a262a4c4c19f8938af2b243a68ecbd398e16ff6d50b2643', + input: '0x0054f94903c625c14dced9ffb1f5b6dae000000000014e78dadae1cff0c36701bfc5e99ce24ede09279c36edfd523ea5ed5c609d47e62ce9c03bc5ae9bc28edf9add9c3ec76081cd3cc677423fa28f2fb195bc24bcc2fa888bfb453d81923aa1db5f96dd597cf8d6ef96b4df923e0720069e9db5fa81edff53ce1e5f0ecbe75b89c4a9ce38daf2d4e4faed4597ef54aa193c6722da403fa88173defdf2d9fcebeae5ab62ec7c25f35532c46bcc8f2567b6f830bb49d7377d0d9222dac000a8813d5ac187d77dd93aa9cdf7d6ed4c2f5d9719df534c7e1d56d53bdbf265517799f08ce6f439860b624f4c7c5575b2732fc79a43593233fe6e5d35cdfdd845f97ee5d2beecb3da354c2a200383a0066ada1d7c2e7346437c8af31d76cec991c7f4afdd9611daf42d4374cde15565b609eb883630046a60f9864ecdf28cc01c5196adddc5a60e0bfc64b896655f5a53d11bf0ebca3e96d867441b187600100000ffffe8b1f3ae01', + nonce: '0x5d1f', + to: '0xff00000000000000000000000000000000062429', + transactionIndex: '0x2a', value: '0x0', + type: '0x2', + accessList: [], + chainId: '0xaa36a7', + v: '0x0', + r: '0x575a1864c87f4a22ab0e335b615be991cac6cc6cda13835406dc3798facd6229', + s: '0x7a4c8ea48c5a745d4bf5645ea3a12af6a7d6b7dac2382e6728303a2e5d326669', }, { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0xf144343d1a92f1f73b1766ac5e8e085cd4cf5251', + gas: '0x67e0', + gasPrice: '0x286c1ae5b7', + maxFeePerGas: '0x554a616d08', + maxPriorityFeePerGas: '0x3b9aca00', + hash: '0xf600a98adaa021ab929f3286363fdb83787d9a68f560842bb0a1844732f851f2', + input: '0x00e006321b7a2600543197c5828046ed1e00000000014d78dadae1cff0c367c194c8fd5ed1777e4ff93cbdfb77b942dd810b214b0edc6f5ae1a2727baf8feee204cde6f439060b6ce631be13fa117d7c89ade425e115d6475cdc2fea0994d409ddfeb2eccee2c3b77eb7a4fd96f439003170bacfea9e0acd3dfc2cda5ccc3b15630e4f915fe8f22e9a7dc5d61996c5cb0e35b2136da01fccc04bc9cfe38eebe65d5db346345199b1bd35c0d9cca3624962a86062a0db213669a20d0c801af8c54e5afa0ee723f5477236bfadca179ca89095708a3fe1b74884b5776fc687e478a20d0c821a78466365d7b7db2a3e5bf73a7c512ceae4d96558f8c9a83ad2eddfa2c8dce01c07a9e6f439860b624f4c7c5575b2732fc79a43593233fe6e5d35cdfdd845f97ee5d2beecb3da354c2a200343a0066ed35e3937417fffa94307e62fdb765a6167daa3f2bc15f6af56a58bce2d904d39c84bb481610700010000ffff39b1efbb01', + nonce: '0x4d', + to: '0xff00000000000000000000000000000000042513', + transactionIndex: '0x2b', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x241dab30227f58633e69fc4128b1c2b09699ec274cd575e39e697c1e460e5791', - blockNumber: '0x3148fe', chainId: '0xaa36a7', - from: '0xa1f4764640f5204a6adc12fe66f1aaeeca9515ae', - gas: '0x1a2c8', - gasPrice: '0x3b9aca09', - hash: '0xc9f12beaeff3325c3b58c03f66f6526593432f623d2a873bd8ca7e9f9d3c48dc', - input: '0x22c90a990000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffab9278060000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000373756d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005507269636500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x3b9aca12', + v: '0x1', + r: '0xccd970e8f49ca80decf9fe6d9f5d952b41ab4e2974a04045b5e3cf53e84c9e4a', + s: '0x4e258d169147f1534aa9ec714f7019cf9fa7e654a3e9d3981384533aa6467b91', + }, + { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0x1eae1117f7dc4b8d6a87c48d05228008a6aabbba', + gas: '0x1093c', + gasPrice: '0x286c1ae5b7', + maxFeePerGas: '0x554a616d08', maxPriorityFeePerGas: '0x3b9aca00', - nonce: '0x242', - r: '0xff8ca84b00f420a78380434fbace90d79ad66d69b3ab838674a2dd2757308ad8', - s: '0x7311d273c8f440d364efa011c3f7416dc97d8e34567a9b98f37e775ae9809821', - to: '0xd12fa5c13cff2be2b2527b745a7f96680bb28050', - transactionIndex: '0x17', + hash: '0x3bf24168c7c5d4036c94d26673e8de3d96bd332d4efc0d0546292ceed9a799cd', + input: '0x00aeb2b2a285c6e50b0beba6afbcf7a3d4000000000b68011bc716f83724291f8073c20bebeead2b70815802175f0f2f7f890be213b82caae044a0c1007a38e076d807aef18603014002100018ffd7288f742f0b27e03bd32aae4825feaad3fa6114fa1d99a0eddfe46c3a6bc1ac8cfa615b84884480791a359c91b199ab81e4e474d70b2d768ad14ec9f941df71b0949f881a68ea5059fa0d1a68f64438d7719e2218b85302e72b158c7530045e12d4224175d133b00d788718e97409848eff6221cffb8aedf5e37ce40c444b2976d965f07427351dc351746b2907cbdb900837ec91a5d9e61f138ad79ffc18b466ba7adc5a747c2eb7ff2776a54cb77209776dab78a7f10734700117592266d1247dd58f6758ee242f044b2138d2510764fa0dfbb5d2f01e292b2b79cafa042121c5e7cdf39206742bc226885ba64c880b6a5c1bc9f99fb970c2822ad6f2b89f1201a11c821582f01865909ed9d259aa893f19315e5a5c4baa32d0f547171b791e890af293d5fc01fd26a540cfc0d0d8463e93992b3ff2f86761801b1982ce9ead3cd65373668b99ab48a2122036d40aacf2b8f28065d572587c272376c71e3bd3043b79f2762ec5b74812d383f61d877e5c07d5b806bffdc81c66548058c27b570efe88b337a79b0d7e8f1db6f10bd4ec01f50c2d834ce58b0b05f0a7adf3c8fdb30cae474f0f68e157c94f9390b3dfd0a2f906653b72523278ccb4255637742e1093ed00f2d9fdaf833cc12081b3554eeff0460f28de04aafd3e7c667d863e77463c67e90cf9e65a8214449e75b488ade3991053ef43fbee454aafa2bb4e5f938894063b76d596eb477d2b228ef370ea30d373f85b362f94cec5a6dac433064c83acb12df1b9fca3d2fa942fe69839cdf3af306ee7c3301052ede5fe623752b0b0a0d060b4af8494d93f7edcbf184481e03ccfdb37ae1ba8c71cab5f8e5d2f2a33797ef2920ae0e120f65736c3b74e76184b0397338a3cc141ac854c1a79eccbdf43cae7a7a88d590dde4c81d2ffc8daf81d1391b80760b88b0497dc5deaacb2f5a25053ae2df905acc4e96505c20c42d50f8c987775e1709d276b28f53e0b12ed8065d72aa29d386e56183c66c3391e81293e9f290f27407de6360fa366ee7b580fb70416a94040fd90f04aa7521886ad95f0eef5eb56309f60663af7794479be9ef040b922c00b834c14126f662726addd6878e71ed1098e8ea7d9679f79cc0358c542c96b6fa788eecc7cc9ec069cbf8b4c1f263c5e2058b2b86ace7df3f3e3394ff570db047d5ece2792b62d29c05053f0ecbdb8ffd8af1db941b9d2a3a12c94475ee7c596ec75c2ef9ea685c85c339f1eda7fc8ba42e64f1332ae424ddaadee8025b53fa08323faaa2b430655fdd9d533321f65003d35b253bfd488109a02872cd76b532380e72b521e16cdc364ee6be9b8c9d639657746587215ba850171320356ea3131d2afe60a5f50f2b453b76d35faf7f70c44544cf2a247947c32cdaae299b3281019470a5d7d1609032d8f4f5228a8a3bcdd71067c639d3240f741447f2fc1d3b978c74cb889cadb41640d8c3caa847902662fbf147318d5b4a787495a8f3de825ac2700aeeb3c2da342fcd30e60e5819a050b56f70f340e95ee9da507e705dfa87fb870e39244ff69a2bc50dd9bfb1dc0ecf969cca0d96c8e02dcdcae46265e7d5048dc531b3ec6c534566ce45c8f74ef75400faf34b16a1d75e067a4a587ad670bb56ed1c0cf053529bca30d70f91e0839921be1e6b92f696bdb7f33a569a4c18f5d35bd3580dcabe5eb467b22d5b965799e08724d829f876e5aea48555b907a4e5c086d082b834de0aa252bcae9eed33639564887a10b18823c536ca7bb52be3779f89331223095c90891f49b97b3b4e6e75984ba3409ffd10aeff3ac55b398124ebabe1628f3ea92e28e13ba63e415a5abd19c6e107b52c7b1e30bf0314f1532eb90ddac25da44a79c39b3b4aeff22bc22967a4a6f779654d16477e14899cff36741c29ccefbff9d75746bae928e582d09043f6deb2a85e2bd278b698934eb630f18e0802c076180d81f31e7f55f952737d47c28abd5d4b077fdf6d1f1cf49071b7c3108f300dd1ae9dd1c31f4429dd83590ff3134af959956cf0718cf57a7972305b0f3044394a7626be16eedf734f56be3bf463fdc1410095a248792ea9747fdf003c2bec37a0c88f300fd73dfecbd1f4440d371b996a3c92e6ba6c1f44828ac5d1738d4bc0c0904a37ccf732500fed2c8310fe53ea18e5eabb73adc1e577e282777884c074a0afeaed322e3679ebebd37b946f0e96d0870ba82748b7454839ec537eb4ab640aced66f10be7bb0e48f25cb3d9f885f73407a94c13ce16d8072e8f0f1d2a5a1eaabdd8faf2727fccbbb2822ccfb12f8245d2bd2ec445ee78acc384b63f117c1f51d7e1a3a4bf65580861b3d381220f7e5c50279c7be9755fd47627b1ed71a9b0db228b31112915bddd3a409676fe05aa3ced27aa8b49d6a89109a35fd16ebc5b82cd2f6d86521dbbadcd0cf4c8acc766c6a1c983b2df8358096d6e64b7fd87ba54733e5ff9c90665f8bd1314b767a78f46c7951b709e9abcbd8483d3c3b29696250d264ffb2c431fc5de56f2ca938691b7a959216d18f47948eb175b1bc38a8ced4b58e53603314b3fb38e085a4003610633737f58f9031d61ccd3ffb793f425fa5b7fd748bc382b4992af6cfc84ff0fc55f90c074508d26adc004cc793e8fb20043b7864b3f2e88b45e7d1234f7c9a202bb28117ef40709f9f0f205e3c2fafe6843322abe1a31daae84cedeaa434f4e3e9b866e6d44c1b3c7f7d5c5ac8a2cec7992e8889e20f99bbf656eac24f9c50e8e1ef1d7924ac474b31372145655377591e0ccb3ed1a2671abc7d493694cbb67fa69eb33aac53b3e5e3c943b39cb369a0b516e42b86751b9d9becc5143549a71419be7f7ea29c68cbef6fb398dbffe770078ba7898da0e18e1bc19c8a7efefb5fb73f9be4e7d28e4e9119598a42770f17dbf7c9dbf92d3bdf484374ff48c3445e57b493e50a0bfd805287d8dfcc8474aeb0d6d5d880aea13214443067f1e6555bddb499339024d948ea43d5fd0b2d62bd112a64e87a3f163c323b6541b1f82792c0c3c19f0c4d6e44f6d03e62ac0783388541975e68f205c3a57d55c6a20ff7f84f334734358a83973579ad74d16767146d95bb584961deffa31115cb42b3195513b88e661d12249188a07cf0e1207d7baf59ab84ff76d3e295d660a855819f3f48eac7a233e57995a049636cf43b08d88752273e3eede25175549a739834222ed5cd8cacba60e98e0ba033084e760681b5669971571d24b5d718244dfe48f6852d728eb515a6f1432927972b41c9218b25609aa794da5e77fabb47a141b8e2f4b5528ecd305c48226d7b890ce135dfe176f356870820f8234336f8e6128a781fdc46c20ea8d211bdefde947ed02b279c66b52a28e453b75a545111605efa0117ef9df84c98776e94fa3f8264824cadc91cbd3a2a25158bdb9feb307b0c8649e97a663adef5aac2db2ee9b0efa29eed9c8be8d421e9b878068016fcd7d2659e8895de8e5f3370478023f327dab2a3a903f9f6df814a5391042694f421c4a019cf9cf49e15cab3883bfcb0913f6a08aa0f94ed66fcadd74c00ce728da3857e67f1fcfb4525d4d5f4edffe6d063379021543feac1c17d641f6ad964a1e89d8582a033e8ede7bfae582bfb8fde5300172ff3cc5a2308f7ba6504b37481a6a797a3ff9e8ee402ef4490051c63d1f68e39c6635d741c23c84e4d11bbb21b59a9a68e4f19c75536b57fa4c526e7b7d0d662155f6aafc6bd90f741619492cf076636fbb432bcf2bc45dd893c419a85f830e3097a7fdc2c4af3fd5a053530accf418f712efcf4227cfa142f5f4f97766a754858afe13fd2032348606aa64afba9dd1130f00d7ea26157ab3a55e8b7b57d90bed5a1f771f8a4dccc04d8ba4174edd87d8ab288f2fbbb0b5fa0316b85b8fb18274a94fa881381053fc112380679fe70f5825bc8b6016515470758cca204f835ae0e3ff723747d90dff8ce971ee3b868b03b1da84943e7b499f378ed980398cf2603da63d55cd54a9432df6506bf6724b6a2e9cb19a38cc854d2d8a5981fc49533e930e01', + nonce: '0x201b4', + to: '0xbe502b8d1f0a59975471218fe70161b212b8c55c', + transactionIndex: '0x2c', + value: '0x0', type: '0x2', + accessList: [], + chainId: '0xaa36a7', v: '0x0', + r: '0xb6168835036c1971c95e8bd87e14f44b631cd411ec9b9c2bcd8ea4ce0e25a21d', + s: '0x589f10641a2bb9430dcb19ac37c8bb6e32fa9825a348b79c1682df232ec2124e', + }, + { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0xb05e516f04ac76e1ce7c4cbeeb2a34ed8728bb74', + gas: '0x81b8', + gasPrice: '0x286c1ae5b7', + maxFeePerGas: '0x554a616d08', + maxPriorityFeePerGas: '0x3b9aca00', + hash: '0xa8965bf2af65b01ea8c2ec21081486e03b48bdf5eeea0663b007f800ab41772d', + input: '0x002a9171806a942a820d15a27d873977680000000002e978dadac9cac4b861f647a6cd3be6318b7ee0e5fee0b785bbd2dea151da65f5e9d55176cbcb8e240778ada9ed4c70e36777fbc5d66cfddcbaa98591a18943818143a18943b18123818983e12003998091817c80ae979961a001d34fc66b0d0d0d3b19cf732d62e29acfc425ad5f909f53999994ac979c5f94aae75b9c1e9c9a971290989c9d5a22f49f914b0f249d9b5a6468569a5c525e949b61929d9567605c666056609a9a9c9a9d6a915350925d999a61526996985c24c49d9c919897979aa36b66612431e1e1e4fd679b7bfe8a2b89e4af2ab83fed74b8715cd92fbdee5b7bbc8eba969cd162cacf36b8ba9cd16a1223975e4662718655b5525a665e624e66556a4a7c7e5e4ea592555a624e71aa8e524a6a4e62657c416a51667e8a929541ad1007d4435a5261d54a4589e54a564aa9955eb989e1a61949ee396651e141694946a6c5a9c19e6651b96ec5c946a1c59eb9413949ee6ea611c64e39c9b9396551ce9e66be1e06b64a3a4a259505a94a56463a4a19a999e91925201b1c7af79ee0104ae30ae472e392d74fce2fcecd2fd64b2eaa2c28c9d72b4e4d2e303235cb36d40b284df24ead1452e652641653b059a8f96dabd91b5335e358df3f57a7393bfc77ce98af101cd22c3ff7e6bc2421162e260e4689d75c42825c5c5cacc52589d9a9428c06020d2debe3a51cf4ae323c9c76fdf2a5d82b8daaa901caffcf2e9ef9ba9fbbd5e2d2ed59af1f6fb867e0f74f9cc1e59b5be5255526c6db39ee9b830e7cafdc10aeb965ed54f1df42c6b7fb0f901fb36569c6e9159655a52615b905a5e5a589e9462655965555d96666069526793959b95526294679a8313bfdcbf7ab3dedf863f6da608dd99324c6ecc3ab620e77843f842e997a5aefd59e8932a78c4fedba2bf5bce7c2f725120ae7642e4063f609f6980db9756fef3326793b45357b358b4ac7374a3793de6d68d059f173c6a2301687f7b6eee9cfd6d449ffbd64faf95fea896ff3fb6edf15bbdb23fdd143a05cd0fb78fedef403a0c000040000ffff6bc07ac701', + nonce: '0x17103', + to: '0xfe547f605a25980bd9105bf27d8a86b3cf8d5cce', + transactionIndex: '0x2d', value: '0x0', + type: '0x2', + accessList: [], + chainId: '0xaa36a7', + v: '0x0', + r: '0x65386c71a6f9d6dda3ff0d291f07d96a23fa64e0500362c3b6ac55c464d3f7ab', + s: '0x6864bf083895209e074d7fc1f209272120596c17e2c892451e4bcf115a77314c', }, { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0x631e9b031b16b18172a2b9d66c3668a68a668d20', + gas: '0xf618', + gasPrice: '0x286c1ae5b7', + maxFeePerGas: '0x99cd691d0c', + maxPriorityFeePerGas: '0x3b9aca00', + hash: '0x9cb28e006a3f1880091d533064c3c157ab0a08e3ce7506cb42afbe465e236ba9', + input: '0x', + nonce: '0x10d84a', + to: '0xd69759a0e9098973489280c37ef793ed89654c07', + transactionIndex: '0x2e', + value: '0x16345785d8a0000', + type: '0x2', accessList: [], - blockHash: '0x241dab30227f58633e69fc4128b1c2b09699ec274cd575e39e697c1e460e5791', - blockNumber: '0x3148fe', chainId: '0xaa36a7', - from: '0xe31c5bff7904c3a102434ffd75701cd8ff80d79b', - gas: '0x100fc', - gasPrice: '0x3b9aca09', - hash: '0xc8314b15135d8629e2423065b853fe91d7909d7cc9450e9477e667ba84eb45a9', - input: '0xd0e30db0', - maxFeePerGas: '0x3b9aca0b', + v: '0x0', + r: '0xba6a823380159bb1d36a47eb02fb4c03a60fb5158a5215e861467cd033c1b399', + s: '0x0f804fcc4a859911026ff7ce5a91adbb9cfc8faa5fb7a816af04b41438ad7afd', + }, + { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0xe270587243dce6969cf2e9a43a940053076c26bb', + gas: '0x5208', + gasPrice: '0x286c1ae5b7', + maxFeePerGas: '0x3344785f04', maxPriorityFeePerGas: '0x3b9aca00', + hash: '0x17c174883f54dfb11c9f0f373008ab0ec46d58599ffd7d7d78d174fa10216cbc', + input: '0x', + nonce: '0x1', + to: '0xe7f48e6dcfbea43ff5cd1f1570f6543878ccf156', + transactionIndex: '0x2f', + value: '0x221b262dd8000', + type: '0x2', + accessList: [], + chainId: '0xaa36a7', + v: '0x1', + r: '0x46df23fb2514cfe29405bf43af308fd59369c7e19f66d05b754692cf05d48f62', + s: '0x4bb889398e92f404d5b53335dd7f4f12bdc19205f60aedcf5fa18e906eecb002', + }, + { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0x296494cb8a8b2550e660160eb02c78a902ddcb16', + gas: '0x680c', + gasPrice: '0x286c1ae5b7', + maxFeePerGas: '0x554a616d08', + maxPriorityFeePerGas: '0x3b9aca00', + hash: '0x8eb9a51e113c99b5f2e6af8fd238d2962fb1c820e592772f52a43e1060eff41c', + input: '0x0080cdd54fbd1c6a4bcd05d225147a6d6500000000014f78dadae1cff0c367c1e3808fb666dd5c4ecb65b78a3ebf7a56f91ddb4f1edf4f8b2ce7fb2bea68bf603ede9c3ec76081cd3cc677423fa28f2fb195bc24bcc2fa888bfb453d81923aa1db5f96dd597cf8d6ef96b4df927e0720066e6574d3f293d65f135f58fe6cd395eae32c0a59df672c5a923265f606a307b1fa2b883630006a6048e99e48b5fc87bbcbfe1b69c9ec9eb3fead83c4f96077fec61aa79607077db34a893630086a6092d98702a385ecd38c66ddffd2bbcaf15c30d7a937cd57cb44f3f7df0bf1896ef624dac010a881db569cbb72ecce8d879aee914911af533efdd05fc57f333e70cff91d5b9c775adefade9c3ec77041ec8989afaa4e76eee55873284b66c6dfadaba6b91fbb28dfaf5cda977d56bb864905646018d4c0bce5dbdb2b0a2405b3e67f609a7a9279597b5952d301df1f0e0173d6f21db9f5e105d106461c00040000ffff132ff70101', nonce: '0x12', - r: '0x2fa6f8bf60f49a700e3d7c99843af1a4acb2c17f38c6367531e1e701ea4a86dd', - s: '0x6e7b0b7d4bce277491217d269719128e4c1b4b4823c7c0a87345a54829214b5b', - to: '0x2f37b8ab86428671974ba67465ac867754fb2bdc', - transactionIndex: '0x18', + to: '0xff00000000000000000000000000000000042514', + transactionIndex: '0x30', + value: '0x0', type: '0x2', + accessList: [], + chainId: '0xaa36a7', v: '0x1', - value: '0x16345785d8a0000', + r: '0x2009cc3564b11b25c1564d8d46ba33a7abae97d442a10e3b09af545267fa49a7', + s: '0x2c3d09a41872544de89591b73fb4729fc79ddce99963a0c9316da0b6b91f7d23', }, { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0xb4f3fd0da2d801ae8d02fdd1802293e1f39e2b96', + gas: '0x108b8', + gasPrice: '0x286c1ae5b7', + maxFeePerGas: '0x554a616d08', + maxPriorityFeePerGas: '0x3b9aca00', + hash: '0xdd2a3e0bbd72c7d98e2e9564ce85321e6fd84bdaca541e86324b4ceb7e20e927', + input: '0x009e283f139f5ceab4ca3c1365740ed4f5000000000b5f011bc716f817a1d207e09ca2178c2ff9b564ac3b1c81faf7452d700958d109147c6029b8ad1e708d27002800c0f85fbb1ec2833618931ae7db2852eb6a0253653cb178031f4fae9ea4219152191251f7884092b27a9c4b39275840a053a28de9ec7c3f0c25efaf80a7a1dfa38dcf44bd2c1527be93f79f7adae078e7678aa5fe792037133b8f6b5663601767a496f2014a5cf8729a750de5df93b1b9fb9426211f56f25899f663c8aea0ecf038aee8561dfe78837c717fa1987c539825b5f08b45d321656d06d4d78a005e513a9485e3acd3a1e56b125bff62f2b8ef739d8c9c1e03b46b430eb8c072feda5400e5621b13920b8c20a6578295646ccd4c188b4ddb61b3267858c3cd461ebd982b72f2f5955e2468ee9ceef7aee7cae892b52eaba58361cfc338cff7de3cb6f210a3b63247e0f944102afc3779f012b701b468a2c5c9f7accba1d35f11e71945b29387ab4b803635bc08b3b047cd7f429c2a422e6cc8c52ebe135e1c24d0b76be3e6c35e1e5a50e219d133bff4d3a02d849a30b9e29207d75c256481e9616342741ac89bcc411effb8957534d95ee979d01bec36bbeb6bafc53f0d6e66871d9ed3e537a75c696c6073c850f9598c79f40959df4f7e7972e1f7d0d350ac42374cd615a8a510a51da9ea0137185ef2bca07311155cb3d866e4c9cacc02cefde78a31140c8d471781e990052539cec3f5920967164a28537b3680a52af6a5fffdcdf361b9f0b15b75bfcbbb75d8ec8cd33c61f654c57d473f57401abb0beef3efa9dd0f265c85d8853a820323152a37886e9ce7399ae181aa553209b3fe68c078463e9d3b98e48be68de72ddefbfb8e7aa0430be7320f06cf4da2e0a21423726bce503896a94243bec53125fdd6e41c813ac85b648b90eb3cffe7cd57084d580b4832be56ef2d851e320c15f8cbfc7b9ab62457d841252273e66696fe7764619ce3c2d7b55d7febc16906bbf8dc33cecd57eec6be7d2e67ca2f5479c003f65793d0bd2ffb6f045a56e8f8e2c17a9553e7fbbaa603a046b6894f5f0cf0177397a722b55eee38f22cf01c8dbb0ded60b62f52b6b41f4d1cdde0bf13a115438417210f79b62e6eab42a5a48e1bc3362abb68f6e430ad3ea7463bcf64fef884e57ad813bcc7531ea770a741b348f5e4901a368b110f975f6d2fa946d8d828d9b3738a75ba97af83bce46914ae920aa18250337f346e5699ff752ba92a4a9597af8f81a79ccc40eb7742cf5b96a7700b655312444ea587f06097f7dae8db6f3adc67b6fd8672d0fcadf96aa1438f12618eb65c1a604bd3c213c4d266b6a83f2c4841bf735f7d0a1b1c6f7bda721d69523ae0051f8f36fe499e308911fd5059f5a48535dca4fd97d194ead84cee48e866e3ef3416a43cf9dd485a8e82b37bea286ed0b79552175d14747f2cba72b14505cb6db8034126287916602c914025bd3acf1885011283c9fab8475f4928a4e87ef2b18e7783fbeb066879d87e7fcc12ca58733d597c4fd7a3263be220c677d206b0e6b9855374769fd1498191e7efbd2f72d125074becc656e71177e8702d6dd0c70bb8eadd32f8c5b28a402004ac3cfdfb9bbb0600da5666fc971d1062afaba561e6abb24b695cedbb1d0b43b57d3738b396440924da51685092cff95ddb97450188abc05b0c3c71b3354e31a243c57d3de003ff7174eb9ef19615e0e6cbd9fca4d0bdc305be9437630bcfb2c59179a4102b698797c769b1b1311e71a3f713f497832b5eb7e3ffafab62acdc7a9d0d946b16531b84ef10e4e1ed0616886673037e7abcd01d5bd026ec8e16e03e7c6fdc9728e37cf3ff44b00c519e2f781310f00a77408c5afc53b6ec6d096a887d0d2a35504cd4863750185e0d83244f9a625211362491703ae21def23685448742abdb1b6a4f2cf89e9d76c38429b2d64798621f08d31928c7af341ec84f27db6189a7b0e34958bad00c5e557d0141b45021473f69eb7c6355b4f248d865571388ef0ae4367b51195c8d3bf949037140589a386037e3056b5b722964aac8adf26e39fb35b4e19a4f546ce1cc231afac829762d8964c2eaa3c6aa4d52a5b8e176b931bae6abe528ce7a637a48f8d772813a18a722d3112c796d0e421b1ec8e5aea40576e4f7f8e55b943d0b26cb1087c760f43d16b60eefda0be0f802e4f8653154a6329dc3ba6bbe22dd8d1f9ae1060a4037dc07590886443a88b3b9685218f56f6c7d29c8ca988770c04f448a13ea51cac759549b1994906b93c346732533798f2dcc06dbf49a2ea989a387c8a09fcacf304033ced9f6e84a27570b8520f248e95c092e772f46c7623c744a4db55c2a792209175a7fee767a6fc7be32d60e45eddbfb576d8f2ec742a72926786d0a3ac6b87b3697e87cb662a5e59c140c9d9cae79fe2ab6c8170e409bfbe9883e93f0cd14d3d8b9468b5896a11e23998fe48d34a23f93b39c1c38c02571e3a56407d08ef5845ab7e7ff8ac03f5590f32be9387fca5aed544ebbf72b3972078f214a22419a53a7eb733cd71743eab28e9f75cbadd6dde627928dbfe34759cb8eb015f9e04e7cda7b03f53da12ab273d312e1480016c26f4452cd0322f1114f916de6a8e409ef550ab452e761456ac3c0858f5bee1f2b163622cda2951e9ccb11346c975540e208f9fa6e639e7dc6a1e4d566c4e21b569769496d0eee52510f7cb7b4d18e1a91e2ac279f457a403e1f4a7583ed53950ee0c049c630dc40c2f83f552288c48a904a68a8d689e6aff13db2f100c73a652bbb9b715c9fbebabc031864a1028fc8fcd106e25e00be279f8edc66ab72caed22f68d3482b24a4a333c1d7a14039ea418e9a2f035a5b6a4c48e6c9077278c04176b3a020ccf940aae23286a5c5cc8c78158684fc7532983ba313d2b3fd1eafcc584834c8b8733c6558695ffbd707b102b1c4a9e40a0f14902bec91ec40002c5d89784ef46031f64586f22ff10fa96165b5053e02ff48a2d59b6f6b9f87569ec9e6c165338f8966a5005e787d409545bf6b2a9b49a36329c8aa0ed0550c4602199c219f0773fc1d5f9255a122bfb3bf9e26df8e14fc52e28c252122e4203b29d7ce483c82629e7f6a7e3d22b97c84adbb5e9a0119e60a7d7588f83c0ce2b163ece189c1294eb628e751de3653b262f78feddd7596005af65f241e6edf2e20c34811a1de21f962c92fa8e6d165a62cb21d13f8202d9c59b3cbe888dc2cde01f97c28139fabc375fb96f0b68afa0cbc8e77a18a4ba3e1309b7ba2fb3250fa8dd3d608935351157d5f8006c8b1be732008b61acf390e9d48e9c1a81f74a3297e6da92d541b5da0cf620ec804cd708723b1d0cc832415d3d60d51c990cdaf56baaebb7d55f429007f5d7c7764bb6f2ee1726156423bcf5bfe724b7b969afaada2d7c86303ed9af6e805532cb02638417c30ae58180f8a6e1efa2b43e9f783d3f0785a392fe9dc76d1c85a7c624f96d542156211959148712ff4f3785d23caf57eb15416f60a8ba75b79f99e215ddd24094825f873cf63eb99c9e68e619e940c06d093e1662b7f88d4fa44f2b49a5d1f33b89251fd472fed62f34af6b201c633c4a4e67836041d0d62a8bffdb0aebb9e457a172bcc60ec823faf35e90124113c0080c56ab62e8d64890a04d71a1bf97ef1f5d242d04be691d1f42e7ee1e4f4b3d03633cdd355eed95276b2ce4b58dfc22184dd84d6988927af5c58f3694763d7b7794a050a30cf4fcb99f0bb984287b4847eb7e19f4c5f59b48c9c7cc5d587feb2078c6db25348619ea79dc416e2c2aaf96316fe524fdc10909fc58bde1a87cf5be3e5ab74415948ba89659ef8ab6e6c7c7d3d4abe630efd6aa3dd12ff50f7da4218d3ee802af97989d56802d679a86dae907de0e81ef29b927be3a487bb2665062317629cc4473ab7930738548ed8ce43517f657a4b4f2b5207cf2a1bbe3e73913a3eea59395120d562c2966b32c7a20e84c081c30efa9af51129b6aaf8e8aa4f6871528752b13cc6698304ff8f6bbec34f91d9e72924f20e34e4bd7980be100c27d368bd36c8f1d90314567d7240c23f81d4621338e669d0aed6fe04e50e0513a27389f31bc244ef96de106336816f21c4f89f07ac857ccefd01', + nonce: '0x3a74', + to: '0x0e648ea78c21fb2a45ea1f114186630d76618f85', + transactionIndex: '0x31', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x241dab30227f58633e69fc4128b1c2b09699ec274cd575e39e697c1e460e5791', - blockNumber: '0x3148fe', chainId: '0xaa36a7', - from: '0x113ce23c9e0cc50f4d41d7ce6da02dcaff8bff85', - gas: '0xd0e71', - gasPrice: '0x3b9aca09', - hash: '0xc96f60d36bee10caaf4b40ddc2c90e752d7d4abebdd29646efff6b8a6454d070', - input: '0xfee99b22000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000003e0000000000000000000000000000000000000000000000000000000000000c59200000000000000000000000000007777000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000028c5c0000000000000000000000000000000000000000000000000000000000aa36a7000000000000000000000000b2fd0dc2c2e7b8b3da558e7c6da444770945646e0000000000000000000000004284890d4acd0bcb017ece481b96fd4cb457cac8000000000000000000000000b2fd0dc2c2e7b8b3da558e7c6da444770945646e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e871b5c7070000000000000000000000000000000000000000000000000000000000002fe9a000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000001a40c6fab820000000000000000000000000000000000000000000000000000000000000080000000000000000000000000b2fd0dc2c2e7b8b3da558e7c6da444770945646e000000000000000000000000b2fd0dc2c2e7b8b3da558e7c6da444770945646e0000000000000000000000000000000000000000000000b397f5c2384446e3e40000000000000000000000000000000000000000000000000000000000aa36a70000000000000000000000005b9fedd37f0b92e7e282b19cebcf06f57b77c604000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000003424c4c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a42756c6c20546f6b656e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001480000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000360635eb59f4e56ee875feeb613c7ed68ea8bd7773d453b6dbdf44811be702b967b1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493470000000000000000000000000000777700000000000000000000000000000001897ab168dfafe07e4c26bbf873c9d580efd28d0ce2565506047e788057b60e20f27911504675e6587a70a8759164f8c270a225e319423ad2c296aa298dd1ee11a305f695a5ea33e6859f353ccb80d14a9f5ef67e89e544d5a960a4d435dcaabd402000400020000000000000802000004000000000000000000000000000010000000000100000000000000001a000000000008000000040000802044020000000000000220000000008000802004020000001000000000000000000880000000020000002000100000010000000080000000000002820000000001011000000000000008000002000000000810000000000000110000008000004c0000000000200002000000004002808000000000220000200000000008000000040000001000200020040000000000000040200010100000000000010002000020000200004100000000000000900a800000100040000000000000040400000200000810000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014b41000000000000000000000000000000000000000000000000000000000025b415000000000000000000000000000000000000000000000000000000000014ec2f00000000000000000000000000000000000000000000000000000000642d14180000000000000000000000000000000000000000000000000000000000000300d7b65f05c1bf243167fe41c970fc12bcaa604ddd049f26eca84ce033a5fae1b8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010e00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000092000000000000000000000000000000000000000000000000000000000000008bff908bcb90214f90211a034af0f449ddd390928628256b6b82e5a62ae461ae28fcc38e297dd6f856bf0daa01b5c06879ab72540da901c73ba855717eaa7cbe5ac569b6bccd04f9cc78bebc1a090025b072a56a132b1fa8a30d59f2973521a4c23856385e7234c4febaafe96fda05da187651f0a998a909d86cfa9ac6363f94ec2ddef2906145d7de87c70d40584a00186235f90d15dcd1623417d4513099b313a62cdfa111aee8cb7bcb4142f1fa3a0fa29813f52a6a43e3abf2a51c1f3ef40c5a9a4d92f404da3520d0b5cff6c2e1ba09caf07709579182f27fb05f453e61935c3bc7ef4d2b597fe008ea1bfd322b3f3a0224f31434147ed03c5267cbc2a90b8e289ab377b5259ea57395c77868652d6c0a04e1e98000d792172b04c376e5e6b2c6f3b07786d66675f00d2aa7c515d86491fa076016edbd69faa9d65a60fd9453e8b7888f6be1b77fc5ea99dd187cd0ce27c5da0bd01d3e33f29301cdce2964d255e255008d6ff2210cdcdd21dd211148ea939e9a01f6557012edcaadfead88ebf12284615e04fbc4fb74f407740cc989a1f4b561aa0d267eee3d5c73e1f516445f7c5f9659cc058fbd05bc0ea13227f1af502cddb33a0f4a4656d2a1d89cecb9a5439cbc74745118c688d7e8b91a5ea20a51fc02c1d5da09488a79f75111c590842276247157c99ced6567b0c656d175db145538f8b4db3a03a59c6298e83c06ebc4efd1a445c00ba703647a86dc27d02440bf906e5430e1080b90214f90211a022b5bff55cc753b8386a29039a69bf06cc780551bbdbc6476375f8252c9acda6a0f3314118d029e09e6fb762ba0b4e81dd23718817eb7ddd67901c9f81a234e628a09faa8606558839ae524942d936fd360dab883562c1019f9bf2a6ea984a6abd09a0935cc557b83b8208653e33a1b02f3e39a302b9a780f7574cae248426698a54a0a07786d2b213b506b7e99fe7560ae6b88d120f41632b053a6885b6ebcf7e6c17f6a069b3b12ec66c2685578c342474433c21d1a9923f62c0f4f5ee116646ac4e72b5a0baa06480959c44b71089167b8550a2fba5b57464128ce9d82a111a562bb3d40fa0e43356fd5ba6edeec033418994b9abe0b3fa5dbc7e7eaca2fc905d7901b9dc1ea05160c6be64ea1192cfc7b587b9885626c6a9aadfed447879f1db8c49f0cf5f9ea0bb4f9fa3aea6851dd72365a846f77afc8c7baa818058efcc341e9dcd139078ada02d6bc148b394f015531eae2e3e1b2a3123ee7fc79e406d1235910b4b2a5b034da0e23628d70d3d0bcb04709378547a5149b092237931aed0deee0390f947616c31a00e07e5e2afc8e4edaac25e24ebca0ac035e8022f7730ebc2c14a3126db234320a0a48d64177f73d47230b0b7338e60554309f5fe77aecbd743f29d1eb6d3b62fa0a001a89c298decda4e4ad69e68d55db08d249e7f6b21a8a1a632990eeaea75b3a6a0129da127678f4d08c62b6d217e3fc900f147370f7cc050b56058a34f06cf919a80b90214f90211a0058b5c68803bb3adcf5cbc1559a4f96537330e4a9292cb772f4b273af79d1d77a0b23d6f6699535e9f1bed236a4b703465b1e15f0e81a7c5fe15014329aeddc4bfa0bafb8b56f68d791a2c73e0a3d321255ab48abca8cace945d31fc29cb89083be6a011e0b6974f0ef35e775f72659b5d6758257150224003152803f33f862541b427a01615babd46293d546db4b116207d7ef1aeb70b622b297c5bbc8554baaa6a0706a06df286d178ecffc118a3b316cff7c8571c8b6237a49b2c4c4be49db774a3531ea00e33eaefbbce215525a69d515656233f4bed4678e3e8dca0d39cbcc4923f0098a07413c9c9131c12fb98fc3276409f4a4e64a91ca9cdd98349e66838882fe44ed7a053920c26f3c2b7db1f3e8b7fe344fb0c2cc193644c9cb3c34f06d30e15b1c6a1a0cdb9a2fcc496b55bc249c5b46aea99f89055e4299d655f06acfe635388883d09a0e965d2f6ed723a86ec5157ed292522519505f65d9f888c098abee18ab49e00f2a08358af1733207d020f3cfe1d3acf1514ee84f96abf6a88c85ac8d75b5bd6936fa063665e7268dae7271a42e5695b217af12e7e2867a9e4513e324c5b19e637b8bda044a16cada2d885dbf801c28d6fa0551519c121b02c8b070768574098605c23ada09ad946a45a28264fa6268b10af6f8312cb847bb5430ff0224c0038c96a86d519a0bb835b2d8a7964cb35179a0743f82c064e008d298fb2373a619c4f1da787b07a80b901b4f901b1a02c5c8117c46e1c793f9f9c185a884d0e008b4da11811cefd0ffa5f9f92f94d0ca0f590e995526db9695176be42d62f6166eb9259a48cc049cce2d5ca16a2faf3afa037b2b4ae1dc3b6b028c63a963caf3c8c377ae3aeec3a7718668c75a0b0dd07dfa020cbef76677a8dbe17b9fa837c7ddb84f003613510c455c318de71a801dc9a0fa0599cedb5c60be89661537ee75ef8a91a2a7735300122d5c47eac5b2a171d9b55a0af953822ac983a2eed99c2b6c6ff83afeb7c25d87fa07805f415e4073f79e1678080a0548fc8dc803a5821bcdf7ed20664fd20fb5175f6d6ad6a8a716ff9ec830a0475a0ec364d661ae9f61324b5e48569b26138160b675e265c210b0f1117f5761efa79a0c09b6ade00c77463ca078699c68bd96fdeedd435e3af56a2fe7ab813ab25f92da05760f02a169893d2a86d8793946a7868f0afff463a1262667d695efebd5fd172a0bf65cac3bb5affaef46f5296678a557a5da43e0b3d9d4d7521b2e2f51b38fc86a07c4b791d546d46550b59f094061f5c7de27f57aa669b83e6d549c39da3f4f4f980a0a8ce6683a46ed8d524f85f30ed02b79b194e5b9d443944d57a17ed947b95633c80b853f8518080a0607f4b81fba20cc28a9befdd29999bea6775787367a0de8f69ebae31218516fb8080808080808080a0655d31aff8515489fc365adfde0a64ea71741c8883f1e83afd73082936fe785a8080808080b869f8679e3990ccafcb92f5855a1f4e1da52ebf72581fbb6b64c0d911513fe2f507b8b846f8440180a0a25fb907de6bc04edcd901638030f57574708c23417bbce8d073781a12e685cda095f9b3037c0e121b55f25fe3c1a83375541f5ffdd4548499458f0c60a645b9ac000000000000000000000000000000000000000000000000000000000000000782f9077fb90214f90211a04e6e3d7884aaef4383c74f71a74cd0d5c97922a50a73bd00fadbf5de10ef3b6ba0ac404cb6b6b51a678c9c06dbd2e1a15ae678a4e40e45c0e3044ba545d326b624a0159ed1937e2843cd20f16f08c88fec03d6392aea6267ed7909aad36c333cc4cfa088ab73a650eb400216ec7d319941852eadec6ecb9379b37114b24ab25405cff5a06240a2ec09e987f0201218e0c5d38ecee676ad7044ca6c3d6e5ba4d7a74a6f8da0f441e11ee8d6c5d255dd04913036e3514f57e6d0bfa4e3aa75389138f4294684a0f79ec2f068a3db745acbffffb06d40fbede425e38450d8cb2b2cd474689388afa0452c5041c45b3907552d475f48d26eae46da9a28e3c69de53a34cc68c9f84c30a09392cf77e4f00cf4f211da330703449303c53bf169708e9dd7dbfd4cff216bc2a03349153ec08c8905f90508fc26a8474e1f85f40f7aa9ea1f58738149a782de54a0c55fa252f7c0ea9d40175a14b65ddc2eba80de4724f105f75141d7dc0be8a3e6a0f37c275ba8aa253861287156aba9da4a47ad2e5cf0ce8dfaf78d7ce4c3dbef1da0d45cf6c6ee3dc0886437e53aee397260b304ba0b5763e11e55b82da8e0286e10a0188c1e354f05e773cc8d961799ca4ea9c2550383e82893759bd6f6eb60da23cba0a0aed233e3be15d0b2ae078063557a33add09b1ef89d3e2cfd2cc1ab9951aefba054d325d668c5023a880d1c137115f7af33df6d0806c3b5e0fd268ae278b0897780b90214f90211a0f9375ae5ecb619ea78f6eb465c5552f72c84a814e3f6c03f8544ca4bc3848d40a0c1108a07a7122b25e024e2d2e1c4522957c59ab0da06c84182cd196676474d29a0261ef34b508d3ae4ef115f5df93915b6921a6256008fbd29889101322b2ea234a072daca21e6475db55cc8334134cd848228349f791ca125d496d0260e3fa86cfda0f58147b85a898dde2e5923ec213564d30797f27ccb9ddb4e91f58c61c8cc9d80a0bde4914226f29e6ba355f544de3b2e41118e30147ee0aee348e5247545702ccaa0046017a655a7fc483469c36cba84e540f6e3e6210d84546414da9a008290bed6a07dd938ac80ac244d043b8a65843b304f2977e4d9d68e7af3d0e99505ae40c48aa0580acc0e48575954db44fd664804485f830eb11b301f12abcb3ea7884d4522d4a02a0df37e5e34f32e3d54dc9efa4179079c03ed06a622be0a57c23c63d4aeb689a0e5de958862bfd483180364b09b5fca66f675f06078f69143f5e087fb9fe67eb7a0371255278057176f8764c2d4e46bfcdab491331f8e0689f3d1f0d91dbe9d47f7a0ff80a85e7ad89b56543f2e8ec75ce302db46dbabb0e95e91d36e6393aa6e9b88a067a83b2529f108b7e8d373d4579ec19d16f764fa4dd137da441fc1bcf4adb39ea06ae1191deb90637ae41a08620f786b37277e38ed828e86b53416ea2605a25285a0a1cfde0e3b25bfc04760733e23b94c69e241e2df1e0da16ff197adc87a92a7aa80b90214f90211a0cd89739ddb8de2187359bf1fb97e5becfce2084ee7d35d838e6cf14a20c6c0b2a0dfb6a6df062bb342caf38b4ecc5d76ba83742e0d113d2cd5feddfc5ad5fba116a097633f086b46789d874ec6a70cb46000ec51a67665cd864aab03b3096381eecaa02fbc9da965bfab882704738606614d5c1d01838893f68a609b6f52c4dc98298ea017401ba05d6b395c213f2c26af295aae58a489690376d79ba1f732a1ce80a3eea0993db5d3fbfec116ede1625679ea6694233e46469a8172f32688cee8ba1c11a5a071c159c3afdcf2a2a71ad3bb662397db55ab5a708ce64402772ec997ecf46dbda0b5e0b63a49d2a61d9dc0ac72c83b1bbe75f8d9c8d106e1be20991bd224c8981da077f3ebe2680d284f3aa233966c32e42947a608f3a61cd86d578331826eaac663a06e56203c00b08c5fa5435cf90d9fb531186a2204ce3b044d8334762425aa3022a0e167c9c0090fb097e6c628fbf5d681950bef9ef491f726ad434da1afc71418c1a072c3bbdd8e01cc228db2640a27bff504a8acfb9033222cec1e488973fbd9170da0405027c929d71ddc2da325f083f0146e11af13e1be4c64a3ecf7763d242dd30ba02ca40b009934c77dbc45e1ea31707477da52c99f2e399eca348577bd04a86a23a03aeb7c5a907110d9904f7629ff6f8d4efff24a86e351fe12e7f3bb3db65b165da032af17e766d7560489c1f6cd7280ab1bed9b670afd6a99ff8e63f6af0d824bbb80b90114f90111808080a01d8c31c0497c7953f6d3c6be0a6413ce90962e3242ff56405e119ee48cd8de988080a0ec9dadb2a13b7880a7224184424dcafb1b5902bf8bc67dbd52a22a9486d54d9ca006f22293fd983b97b544fbc94a24804cf39409d43859e339765e200ef7888ddca027d6bc7b4f2c344c3cd60ebceb2a5118bf0d4c953ec8840247aa1740933760a6a0fd73cc3433e21fd601bac29afdb0d984b615dd3ed30a7cd65a44ecf60971e1c78080a08f4288c71f60261055795b541df25b55da481e01f1780eb90cca11dcb6f0a95aa09309fae74949de4c2ff7b9d37cf8e12541fd1c44c86ced9d8928c6642a60e0b780a0551c1bffb82addd464b3018ae95671295441bdcab322751e0a015b5a9333d4ad80a2e19f20d2dfed097155b4ed77a70788e2a2538cd6acf54cef17f92ee8272433306801000000000000000000000000000000000000000000000000000000000000', - maxFeePerGas: '0x3b9aca12', + v: '0x1', + r: '0xbbb098ff2204c20c59d4f962e9d8a77fa453578edb94b486693e582cf87e61e2', + s: '0x2da2d028c26e7cba6fd68910054a14aa244bd2a4b8cdebaf1bca2dfc5b187cd8', + }, + { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0x698897485087567046807a2b8b3c049f745fae0e', + gas: '0x53ec60', + gasPrice: '0x286c1ae5b7', + maxFeePerGas: '0x45d964b800', maxPriorityFeePerGas: '0x3b9aca00', - nonce: '0xc377', - r: '0xbdd0b4327329360ee358a8026009fd9f2a6b13005e5af55eeb377e641037698b', - s: '0x0f7e90c4a14653e8fb3591844de75a884086c80a52d6df34df73716639a3ef2d', - to: '0x2ab7c0ab9ab47fcf370d13058bfee28f2ec0940c', - transactionIndex: '0x19', + hash: '0xa619091df1b3ad1837921f84425446fc786cb5264f48dcdfa0c21d3b20891c24', + input: '0x7755264100000000000000000000000000000000000000000000000000000000000000608d7ebf4d622f3780683b55005ff7587f526a16dfa5db55826dabfc95bd3f0eac0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000701fba7029088ccc3b518c78bea44ed8d83bb873f73d14bcb146bb6a85ce7cdb500d197b38abc5c25fe76ad1e90df90f869dae2f7ff6fd842ebb48aa7e67221ae0000000000000000000000000000000000000000000000000000000000060d220166516cebc16e0e850c877305995a0a3af815ab30d3dd4bd323f09fa7635fad00bf916d7cb4dc6e1e004d3d7ee317ba33d302733cd9a279496d4aa8e9d7c27600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', + nonce: '0x6230d', + to: '0x74ca1ac5bd4c3c97006d2b7b9375dd3b6c17accd', + transactionIndex: '0x32', + value: '0x0', type: '0x2', + accessList: [], + chainId: '0xaa36a7', v: '0x1', + r: '0xb4ecccf2860469d2d5023e9ae1fe63ffa010ccd51fbfb20dc6fb20018473cef3', + s: '0x7c028a3c4d4337057bee4a25fdc66742ce3159cfc4d117919397255e0f9d9586', + }, + { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0x698897485087567046807a2b8b3c049f745fae0e', + gas: '0x53ec60', + gasPrice: '0x286c1ae5b7', + maxFeePerGas: '0x45d964b800', + maxPriorityFeePerGas: '0x3b9aca00', + hash: '0x2d6c49020598a9d010da56a2e9c99502241b70a4f8a7c84546af6204aacf6440', + input: '0x775526410000000000000000000000000000000000000000000000000000000000000060ea2a6e31e63a647bb8616df009552a4792c5b8ea8bf3be4ea493783948e4225d0000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000000700d197b38abc5c25fe76ad1e90df90f869dae2f7ff6fd842ebb48aa7e67221ae0599acf6d884bb4c9c02f453149fd7560e13b0f188e92b4eb6967fa498b7339a0000000000000000000000000000000000000000000000000000000000060d2307438ad7a06e6d19b3576095b64568b202a672c47d2f559e027d82050657788800bf916d7cb4dc6e1e004d3d7ee317ba33d302733cd9a279496d4aa8e9d7c27600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', + nonce: '0x6230e', + to: '0x74ca1ac5bd4c3c97006d2b7b9375dd3b6c17accd', + transactionIndex: '0x33', value: '0x0', + type: '0x2', + accessList: [], + chainId: '0xaa36a7', + v: '0x0', + r: '0xc3ff0d639f4e4ca9ed98a11045000c29c4d9808cceb48ca567637d8a113606a2', + s: '0x02e4b978cdf9211acfc4e07c240736c3aa0bdb1df55e2bfc8a7efc2900763a2c', }, { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0x698897485087567046807a2b8b3c049f745fae0e', + gas: '0x53ec60', + gasPrice: '0x286c1ae5b7', + maxFeePerGas: '0x45d964b800', + maxPriorityFeePerGas: '0x3b9aca00', + hash: '0x67d8664ab3a41a54559bf779e9442780ba714272969412b521e38368ccdfcb72', + input: '0x7755264100000000000000000000000000000000000000000000000000000000000000604a65e3415354881946a90a52829e5a8d638ad9532bc86630b9eb0a6698650883000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000070599acf6d884bb4c9c02f453149fd7560e13b0f188e92b4eb6967fa498b7339a05736285aa3d06b430d89da5325e05175e32965fe9962f693b3ebb035789cf7e0000000000000000000000000000000000000000000000000000000000060d2406b048db8c46a4ea05906a5e060d150cb77455786dd598c6cb84b6aa815ecef800bf916d7cb4dc6e1e004d3d7ee317ba33d302733cd9a279496d4aa8e9d7c27600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', + nonce: '0x6230f', + to: '0x74ca1ac5bd4c3c97006d2b7b9375dd3b6c17accd', + transactionIndex: '0x34', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x241dab30227f58633e69fc4128b1c2b09699ec274cd575e39e697c1e460e5791', - blockNumber: '0x3148fe', chainId: '0xaa36a7', - from: '0x1567cdab5f7a69154e61a16d8ff5ee6a3e991b39', - gas: '0x763ba', - gasPrice: '0x3b9aca09', - hash: '0x61f293e6fc8978ee7e4f8c47e678f44ab08bc475134952452422c9ed96ea0b65', - input: '0x8ed7b3be0000000000000000000000000000000000000000000000000000000000014b4c00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000009e00000000000000000000000000000000000000000000000000000000000000ac00000000000000000000000000000000000000000000000000000000000000960000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000002200000000000000000000000001567cdab5f7a69154e61a16d8ff5ee6a3e991b39000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014b4c00000000000000000000000000000000000000000000000000000000003148fc39c9a8534f0f63e3762a6acb0dbc650c4833e08f3cf6e6e80d6d05c9e72650700000000000000000000000000000777700000000000000000000000000000001859620d37816a8fe33f24568dd2466b4430ac8e9516fdea857fb772764cca82f0e76cf63a11fef75cc0cc7b53f049996c64c4d815b0e8b4852b2a2573dd6b90d000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000004dab7900000000000000000000000000000000000000000000000000000000642d14b400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004d65822107fcfd520000000000000000000000000000000000000000000000000000000000000000b5bcc88c61252dca03d1edd77745973d5ec00db9c9a1d3a086cd0c3843a610c81dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934700000000000000000000000000007777000000000000000000000000000000011fc2211bacd10d06b4a33ed4ee685e8fed00cd154c8658a51544d62605a78f6a6213dcbb514ba91b66c3f80b7cab9b129742be85808eac98232c60415e62cb8c6fd280bc3ec0dfc246c389bc54af9243f4adf6f1d4aa6941e9c4a46684a6be30002000000020200000000000800000020000004002000000000000000200800000000002800000000000000001000000000000c0000000400000920040000000000000000000020000080008000008200000000100400000000000008a0000000000000000000000400000000000000000000000000004000000001001000804000000000000000100000000014040000000010040000018000083c00010000010000020000000040000084000000004200002000000000080000000000062000002000280000000000000800400000000000000000000100000000200000100040000000000001001002800020100001010000000000000400000200000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014b4c0000000000000000000000000000000000000000000000000000000000517c09000000000000000000000000000000000000000000000000000000000026616000000000000000000000000000000000000000000000000000000000642d14b400000000000000000000000000000000000000000000000000000000000002e00e76cf63a11fef75cc0cc7b53f049996c64c4d815b0e8b4852b2a2573dd6b90d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000001ff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010cf90109b853f851a0d22c857853b67e2ecd1a36be5fd4fb57b847071e19a3f61c7cc6332d2ab3c2e280808080808080a054f43064a171ad1b429b9fef38d81a0f159d2c745e366f610d20b88149a7e8ec8080808080808080b8b2f8b030b8adf8ab83014b4b808303d09094000077770000000000000000000000000000000180b844a0ca2d0800000000000000000000000000000000000000000000000000000000003148fc39c9a8534f0f63e3762a6acb0dbc650c4833e08f3cf6e6e80d6d05c9e7265070830518dca079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798a05d1f57379d42e3cc1882aa8a2ae15031e199951301ec70f0965d96b68ba04116000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001ebf901e8b853f851a06115dcce3745caad12377ae6b95d4e5ae98d1678771214c080e486001d4d070d80808080808080a06b769c80467ec45da082aa3eb5907263f384138da48baf3e70dc4cbaff1b76728080808080808080b90190f9018d30b90189f901860183039445b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000800040000000000000000000000000000000000000000000000100000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000100000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000f87cf87a940000777700000000000000000000000000000001f842a058313b60ec6c5bfc381e52f0de3ede0faac3cdffea26f7d6bcc3d09b61018691a000000000000000000000000000000000000000000000000000000000003148fca039c9a8534f0f63e3762a6acb0dbc650c4833e08f3cf6e6e80d6d05c9e726507000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000adf8ab83014b4b808303d09094000077770000000000000000000000000000000180b844a0ca2d0800000000000000000000000000000000000000000000000000000000003148fc39c9a8534f0f63e3762a6acb0dbc650c4833e08f3cf6e6e80d6d05c9e7265070830518dca079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798a05d1f57379d42e3cc1882aa8a2ae15031e199951301ec70f0965d96b68ba04116000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000189f901860183039445b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000800040000000000000000000000000000000000000000000000100000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000100000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000f87cf87a940000777700000000000000000000000000000001f842a058313b60ec6c5bfc381e52f0de3ede0faac3cdffea26f7d6bcc3d09b61018691a000000000000000000000000000000000000000000000000000000000003148fca039c9a8534f0f63e3762a6acb0dbc650c4833e08f3cf6e6e80d6d05c9e72650700000000000000000000000000000000000000000000000', - maxFeePerGas: '0x3b9aca12', + v: '0x0', + r: '0xa0976b7b1ad2313ff57c570031e5ed64a570f8f37b6e64f087102fa5776026f2', + s: '0x0d82dc438596025b49446957e1e42535fa7793be7d2c921b6543fbd4e6f513c5', + }, + { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0xe6dfbc43be45a810936ffbb518bfe1129a8deb54', + gas: '0x10954', + gasPrice: '0x286c1ae5b7', + maxFeePerGas: '0x554a616d08', maxPriorityFeePerGas: '0x3b9aca00', - nonce: '0x1565e', - r: '0x70a9000a0ef35877d7f22f39c88f7ab5e50655eb0ceb75a02a97633a69f7cb10', - s: '0x05a1c9c7a9ae2615d4840367bd42176a279386fe245607869e6a85a851bd2adb', - to: '0xac9251ee97ed8bef31706354310c6b020c35d87b', - transactionIndex: '0x1a', + hash: '0x63b8e148241c5ee88ef9b4f7fa1f9301dd1b472f166412eb10694516547ac3ab', + input: '0x0082b7203ad3b4ce0e1ac897b9ad7ee3a4000000000b68011bc716f817a1d207e09cc2238ff88485452ce2b5fe052e61d17bcbaff78523f84b0fc09dbcb844ace8040a3eb014dc560fb8c61300140060fcafd500eb5a1719918d3ad01178acb2baf4bb988f42f2d4f4a81f6f42da5f56143a55df5e54fd8e752ee2458a88b4cbb4b01f1e6dc1f0b2e644a0c67e37609fd16a05665e0a47effa6ab6e038a73bc6bf3df3ccef6d6cf94fb17abf57de3bd8c0c9241a13371636d256f3750c6b11541c0c68e77f9e2f48a487adab0b2c411b80667e9d673673975e92dc1239a16f1410b4710adf6671167538304377c6ede0d49dd0b27ffd14ffd8ba059aa53f96b97cb23e5f6e483d3ee0432afaeb328ba9e583cd688f8982d81f28ff273dd3c9d8e504b7ec7cd7410e68bb59ce8386ef739bf089e6c0c26cf00c3017efd3d3fec4f22801ddcb82d5f6c845e68c59cd336b3041eefb8c90f60a9ff805bc16da395c658d38fe6ec2c3e3c4a6ab78fefc88f53c4696046e305984db6560f8138421a840b093436a8a611900aa0e2f8b8457a9b3992729afbca87850227f411653ee55ccab5ea3a48c9b389c1ad3a4575cf43d92c183ed3c802822a07bd8d763b97b2f26dbefe88b7f49195efd5112e1afeef3f0fdb2416076e78645542fbd479113448f7d20a9c36aae7fd84fbbe74fa0d3f4ffc2cdb609ccf4013ff2ace06e56ef3832b8e24f8b09948b831389987725ea0ffe1d4708d8d5a30f4a84ce53135614cba91a580c4a3e7cf1115cd2515b3ece5cd542b85900d0c1c7676c4ee0200f4fe7d29cc06cfd79340bddb790c16a5021d0c43bf5d64e7299e043566600c498a33cee52ca6f77a17833caef9d1c84126f9f22675477ac068cac3e64d819fec8a96be5248fb0b478417d94a543164da9d811702e6edd07bfedb74e64e0210544a31e3c7dc4691edebadaa241d6d671320b40fb9ff42df078630438cbdf1b1853494dfed6692d87f33cbf5e3a63d231298c3588ff21fb2fe3a18f37c107f1dc8106cbeb19d40af64af15cceed20b255f4434d6939e5613316fca81f65d7a182d1b755036cf6e898336cf31f0820fd3565f4af0a7f99b8ff536e2bf7e4c26456f93e2cea89b1e082e3d2fe04f84bb9ce2355fd8f5d974b52951b6bfcd0df629972b3b38d092df64dc4aed3f52db6e6ba2eb7790490e1d8653f83e869ee55ce6707da67b0da93fc426099a4699c71c550dcbe46eef3642efc54d5fce8dad127426d0f731c049af0b1fd400301e7b947b59ef4ff541578cc423d3660b01339f26ddad63c7e0db33e05b48201f40c2aeb0a02f3f8d0ce5c1a1e13569e89a19781424607a1ffd6cabe6f397ec568780c0378248a44df7cf47b69484c4203cefc364c80e0d095832a264d5eff2a29f33150885693cceffcfd17fb85fadbbd5711078248f450637dd2a859b4a445f1a75b10c94093eedc2b7366b495e29ef8f9f2dc0409bc3c6a32584501ef24b8477d58e79578c34de52369bc74a971267e0645eb4f8518b0429007414e545bcb7605f448475a69e3da36ff4cf568ea4c5e968f17dbe47afd45ec1b4479c0d9f64acd299a923d6eea09a602cf1082b2ead71776679c7fb364f4f0223aff4392c77ff49fb41bc2477e5cb5ff1796b2f39602ebda3805b9471d00cb10c2f4e0960f691e61e8eee44bd1422d1d5f59ec7ecb82f2dbd1e262164e3ec3702999d9cbd83b6ec867d9f327c344a2cef18474bd4dd145a927bf2d0cb690ef4f0f3d482fc9c1022aec400859efe0d631e9ad20c22f94b952aadcb1ce873c51b2e20e83db93cadf304a15b4a2cce32c206a2fd3f67abc2dbad2b0bffb47282e5bd6ca132ca60cb2c4912bf17b2919ea3c83e95311d89e64fabff9488a278dc43d2cda99d9edfe7ab13ef345b5fdbd1c3d81368fe77ba6fb349ebda7d5e021b114131cf626af613663aa74d0bc6bb4368ce06a1efa3cb2fe7f020a6f4108fae1334cde8949f208a964d7ab3dec09c769325845e4ae2e8c79dcdc8bd256e6a1f68f2d972db356f7759f6d546f7700f1ec3aa4fca18f0ba52898e7c8f1b5d1d680a6dcd2c96445fb17a440fa19566ad858150c22d4a097562a4f7c208c2429f15621518f51f75b79557f78c12b8fb3d4c89b4935ec05cfb9cfdf5d954760cdf371cd2c793cdf6397cc2e1bda26eef843d016254dd771465a4ced68c8c135bbc7f33cfb5941eb3e7cce0dde2f0edbcb865e511c7089c56f687f28cc79173656f0d3d08e977980a50a9c2d62c79656bed8dd2e9d326b7b8413e743716a45823703e4a6a3aeb8b0e759d67f67d0eb7c52d4a07481106104784ad78aaf1636c2bfe9862ab89e4e600ae1cce307e664afce3fa6f81a20df3ab83bce89bb01b9f9a466d781da4fe58b3816de873b0f3cdc5120862219dfb4ccec2be94ec3980ee1751eddbc05adb4c09ef99f863b04aff3944027420df03d218e97bbc77fcd1fab635870a6bc41cacd8ca4dfc25e93453bc09787765e1f96f8c8bf39ac5699116685d9070acad52f45a6ab413fab3229341a58239047cbf51eb2e6f4f623b5b9e3e7a572cb286b3ddfce3f0060d8dfae8c0677f80202a13c42f22b88ce3c5ec885d9410723554869f5c83b531f9221db1675147975ea8f2344f224060907e7e8ac9ced59f4fcd3c81fad581c770cdf27faa045ad39614dc3e704452ccfbdd4ccae53b54f2711388dc284c5d165c4025425453fd7462b87b16b2dd45a47228fe2e358d250b78d3696867b3324bdc2c50f55324eb80812ca7a5a129642b9792099676abe667b9b9dd3474d6927f4a8e2b81776a8870e1fc194bf53fa30f45b653007e93caf02cb354359f50c816dc7cf66c4084ebd200d8169e3d446b05899beb666ff4380791af0ddd11bb9c641b3436b2ce04f0feb14cfb2a4b748808c2c314195142e4620e4f218318be8da44f5a42895a548904e87358df9ef4a56e16b4d70d497849fcd09215198391063bf63250a269b7b80e542754f718dda6dbcf99c1bedf2380f10769876d3810852ae18fb88fada66b85c9e698ee69bec809ae6ac10a57f04f5c2f997c5b2feff7794f2e821a683d246247c15250fa78523f3ff7d4a894f82c166b8570b5becbae1184354f2f467964423a2862d70badb4bedf2ad3f56511ace145f1c7c057df44cfaf4a88b402d8fc48aa0f2956386ee82ea6963b98a92439c21565a7d454c5ec6a00067c017460634f28887d72b722595555684b6f085b5a1c043c345bd79521919c27693cdc0e0550db4f270016e0c8f64015ba36bccc8f2d0d199816c7fd460ee7a46811a7936d06f6a159d595db6826be174067e50e7b45b0861fda6cd9b0745c9acac05dbd4c0201ebb4707a248db914c74e868722751759f1b6bfe03aa32577368f6059c2320c37d923f0c87936e1e9ebb38f7d47bf1d8909c8b44ebb7994624ffc2c10229977c6ed665cd3e60943ffa797e54df99c07f7ed8aedefb73e9de5ae4461e866dec7df567a69c6719f170b35485611ee99262ce94a1beb9e0c30827230138104466c0b873500fb3779e1d764f9782619ca7420d7cd4391b5fb6a6dec88187b5d03b559dcfa0620c1d12ca1be2726edfd3c234cf23b74f5e366e7f8be740d91128302adfaca43ba12ef3299c6385fb3826e3a806f3f9cfb34626775ec91794b9fbb6b01ec5be434d1d7af4500f14c1f19118f3a680f7400c2955b17a62a2409d23bad8d828542bd4c5f693b0600697c0e0b89634b38793ed3bcb3ce43319b1dd0c1582af60ab95c40b14b6d7ca2bb40ea0c20aa9ab97b98f27621358e7f14d54960506cfe2ec24826e6472fe2ebe5b0d0b52824b6f53e09a96fcac80417993e79fde45afca896f1ba6fa91e769227c15804d5ab932bcc4a4b61963653d12a8835d9e05346a8c6e9d9049fb9a254b929349d34ef15ba3771d12f99ffd53a17ffd780ef679dadf2a787a830a3cd5bea0d874a85eb45dce236a5a5f2a8afc5a087979dbeb8ee0dd7cd28fe5320eee4f237595d562890ab1a32ef3cfe3f95d209c67fd370d9852c870208e0c1c8018ea548727db6b50106adc12c4caeec8c60898a6f651fe42577c3d3bc0e590273e5363b43cf71899accd68f1528c65edad2eba69f6ec0c4ab1fac5b6096b01ee73ea0101', + nonce: '0x5f05', + to: '0xb9f1e67feaa81ddb077c6a5ae2ec3e63adf1cdaf', + transactionIndex: '0x35', + value: '0x0', type: '0x2', + accessList: [], + chainId: '0xaa36a7', v: '0x1', + r: '0x07a1dc77c0b0e3b5603049e30a01ba67feb65ee5f71917dff854f715c7b7b0ee', + s: '0x37b4d1b1c15eaf3ddf714b72f0f38df711fc4c9e389394bcc0bd8048393541e5', + }, + { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0x22baae8586683884e9e171a78edc190ec524827d', + gas: '0x108d8', + gasPrice: '0x286c1ae5b7', + maxFeePerGas: '0x554a616d08', + maxPriorityFeePerGas: '0x3b9aca00', + hash: '0x8bf86600b9c25429756dc5a5e7c467bd2e85a98345aa94d4933619ae2c64cfee', + input: '0x00182e68f73dbecb761b0fd5ae70129017000000000b61011bc716f817a1d207e09cf4eaffa217c82f51afbb472e494f5a1016b1a21328f8c052705b3de01a4f00500080f1bf96af704f2a902fd451a4767981fbff969968af325ec7e9a475c8fceff50ecd7cad9c90566f62226c3399201c1c6d82cdd4e717fb814809b31c2e1a9e3053f7d10a3162265c6bb79a0a32bf489b17e072cf3c044ce462020650d9d450e0524d5eb6910ce11b93167b02858678b6cb6747e3fface621b61ede2f40e0f41c6e65f6c557da32d7224ec6af96998ed11120ad4cc5ddcf033afbb2d686fa3d184548bda9cfc3c7eb2a2df929e610ee337fa6482090d8dff7e83e6086887ba91073c9a49a6a135ea2f952bfe1adfec2548a3ea2356d3e6c50820c283ad8c8135e2fa3620e6a6720db9d5941de9b2cbe8d21075c0a016c1df6de43963d29f7d9ca23789e2100e7a1449abf314fa6cd875d1276addee2d6b2af0d180f53d921e76c60278f56e177f9e90368d9e84ceb9c50bac294ecb9a897cf1cabc26fe1f12f1b2ee24bece5013747d7a0e9d75fb6dbe2d69ca1f674703c8172fa7f74b0f2b72152454c46b17190a7bec0aff37da9d2d04ba5ed8752b9ffdfea82ceaaef32df9ffb1947e37b69ca3f389a8f14c165ff2ceea6640537a32231c1830e6f8f000a605935b117c7d17d30a9ec010be436ed6546f532d4af74a959d3858e8616123f678fd6efb71889ca7ba4fad9f7a7933c2500c0c962b3cfc2147890b02c2cac29b24163e5867c647a590379dce659da98b33caaa166dc4801f655c2752dcd4db0c6f1bc6d5f30f43a83476d57d54c08b9cc838b3c427f582c4bf68cf5574a89e041df3a5bdd3097c323347cc8c6bd637952465a22b8caa3003fb949f1b95714720ecea588a428eaf2c4b16d8639567106744ae1f070e87293e790c5881043ea06400dc876b0fce75345d250d5ca16fbbb19d470e7a5ad99f6c2dd3c2d5a6cdf9256414804b5926bdf4663ac91f039c70baa980e3756e709b6d254390041bce405d51e3316341d57245b0b9ce9aee3ca3ddea0aa5c2488a691514bde5efc1ef2807f3d9a2207f4a336e66891fc3abde15f9c6265a4e98284fdcd7647f25af569e2294fd9a27693e8370b42213071435f462922ee74bec48816e855fadcab5f213acc81e73cb65a39b19af4cd7f2aa82f7fbb725d09dc2848fce8af759a3b0e8bca2603568ef19a478b3dc4c28717c25ed8a76b5d2044d33a8fb3d6741dd5ac38a0415e454e1abbc17b969a364eeef0b7d8ba34b6c31f842b0cac1c20306a2e5839cf5418b86d559952e011c1cdedcee73d6baa93b8dd3ec83501a76e0f21056afeecb88faa3da33b4950cfd4e40356c8c9505dcdaf51ed703eddec9c67658c817a95592a1de2137df163eebb8dd9090c0879ea0c4235448de65a0e72093feb0cfc0a7544c4b5289c5fd6bd7f635c6f66cc0b0129cf6a94b1925e90ef8c30f5b2cd29ee0600b63e174664737b5e2e44977545563c054a9efd3edcb18645f7a33195148ec4e5e141cbb3d3eef03882e220ad02fffbf52a69d0f22ce60d89c73138c2a3566e41c40a5d80ef1cd0a68480919993b2df6a4ec2b29860e4317aad0801b8fcb76f54f429139df83067b3f38b9a8dcab39c324d60331226c8016b4e1f74ea3a0abf26615f9326081e2c2485eff0cc78fcab97ddc20754a6e4d5aa396083d45839744cba8971b0b0c56de64976ec3043ae24f4e98362ccb0446140feb4163879beea14ab89a4887a804a3df9e7dd4bb038302758c58c56e9d192197a7fd098b78097277055d3a5ebfe5360b472c6d268998c64c3fb9b53757917f5986ef7cd1f41b4360079728028871983e9773f26cfceedd7da1e03613dce0f56ce52b9e2a11eb200b43108f39ceb9b6006dd839dd048c51fb2e1b43449d16c4f7e0d7387c51edb7e7d75c63fe1739e0d7dbcba4ecd32e1ab257384cc72ab171d84532383ddc8ad3fd91f07fa0b2f8800678088092196bae0489f774472d61f9415c2126c3598f345a173a5aa99a61f59ff013b0423d74d0a43f69bace72655cdf93d9328c27a1d531cfeb06b4cd26bead196683ce23c823e48a5ef2939bb091539872f2a7acf49eaea9cc52877266586d67ccb3fa51f20cda3e2f573f394e33678dcd91941529cbc5bf2bb7231c2528fe5e3175911d7fbde6bc8f3c8fedb25688a9f198029aef9d57e247d521a96fa1a66e7174442bf5838846d7401659eb5f2fbf97cc5109299b2527d04a08c2f33bf8ebf640cc1af18978aa8469ec97f50e74110a73ec6c69c19d8354c9b97df23c7a7464fae0de33661ac4651013127781e439ba7c0f23ba68c7354b117162cda5a6911472cbccadee5e1484fe1a1d6c941c811087d1eae02f12bd53f9475baf8ae8fa53d185e4f7d4e7eb45860733a671916d6bcfe3718f3c08304a2417fcc9397ed3b0757adec576113244543f0b4f8ff9a1adc6e74132260ce93558f93ac76675829ca3f2818f12bafba07c360ad54b287c2fc7c321bc6838b0728cfe10449d36c8f3e859d7662855b6de96a382813f5747152f6d94c58959523170c5b1e175d943afe0c36366f15df8bdfad61bcbf7da29ec20162620fa241dbc4c5eecd70e4e92d609c4fb8185ffa92b6a8283f9603d2c716af74ac90e1cf18f9f64f0b18f507ae3c0d3f0995768b5329045fd67df9a76e569a9b554a2d7196b91f98c273cfc74422e0c9b36d92b2357a9308637c1b5e2743396ffbbad2862d41a5848a07ac111cf49248872f4f4d17861ccbb8c255b46dfe4c6679a2c9c345e1e4bd37c08717cdff98a530650a813c61deb00db9ba6e64d8151b52273282de8c4a72c4b5c05fda67ecb354857a6f4984f208bcd822ae388d0aa3e713df721f1fe53b5883dfc3a1599313b526a49a1532f288cc4b5eb5810cd5b9ee59a2ce7d18a3ef9bd6073c3feecad71aa3d53a30264a48ab0e382022d9f0178027c3e10251a2598212e10119f919363caf10c0da5d1134bf7ff585581e499de34fd275e2024ee1f7ac6eaa7c68a0190b7a148963e7769340f852354031127966f679b99c66de3462b87a4a7f69139a299f6d0d921ccdcd59d8fb6d4ed6eefa2195a76681a58aae8806de952f2f831ca220df173eccde388fe3fa89c8bb7ddaed3419993c5fcfaf0547dfd1ad57fc43d2a1042ffaa5ed77910facb6cc24cc1d035f7cd77b90cb13941ad7b1eba35365ecdb25e599166ead1b62962bc5a3116f4af25734c1a40e1785792222d1d509e99b2d7c84f0806680ded7e60f8d5fa8397f60bd966e313f2ccc0c0f3821c623712701a3bf3bd12afa1c4853df1acb92e58766286268bca31d275982106829e5392e9abe81ea33139fa77fa65a7ccf3839c68d54a8f4ba5520651d2c6e788b3b46258fb66371ffd072f1ef4fd3c863e0855d7b1a75ac1b7fc8ede1464a045d0dd3490a6a7988331e67f2f9ba2be2776006a032444e9ca9351da86cf2b0564f68fbc5a08310e03c48694bdb313376a4ef96ad37ef185b564a79f95356abca19d965721e13f18a6168e461b0ddef8ace3fab1d0fec0acd242e2f9b77549f55e220afbff396cc083e4cd2446b66ae56b9878225f1f6258d60c9f5f3ddfedb0528f5768eece8744c7a7979d093032e087fe9d695a6182089135a57c756c5d645368f9a368d88f2f5b20a2bae8796ac814e1e062b46569939a235437e1ae3a80f341ad118d565f485b326a0ff9b2670f7c41cbd3c42850f93e27cb5246951886f53bbfdf1698f6e256bc5cc0159de473ce439df8b30c8536b6c79a297a52c63523e505a58dac62d04556cc5eeafff3b84ce48d8b76df182511e3dee4daa151efb883f5b73703d4c191790c12179c8cfb54fcaf9f2e14384472898e43167d5238e52a5c5a2c60393846e15e59cf052a78c0475277d8b94b480057dfcc16ceeeaf55277ab43d20dfd6424ca68d3f737ede135f1edfa57f1c61df7b98b3e0ae8801be233600956aa08fe6d26878b2af78c12217c28fc0da4f5b70f6fe1a4b4f8f60c91459e6bb3942262ead3d12f0c8e6702acbd8aec403fc7e7171ae6e7e183508a8c0b44acf24448c90252ba0f36a09d5fb42158b81aabef6dab5b18b4b595af549474d4f1c23e9b1e01', + nonce: '0x1e385', + to: '0xe3a6abbef123483fc90678f0df4c39347599674d', + transactionIndex: '0x36', value: '0x0', + type: '0x2', + accessList: [], + chainId: '0xaa36a7', + v: '0x1', + r: '0x5eec31ec725f422b193a2e95c9dfab1db84ad67fc7a47f8f04fc21752ab4ed57', + s: '0x37c6c567e3d66271db1fca65b0f391e3552ebaf61d2d860b5b64d05a4b39c908', }, { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0x892691a61ea6dcfd4f21371370e16dc31792c6b9', + gas: '0x117f4', + gasPrice: '0x286c1ae5b7', + maxFeePerGas: '0x554a616d08', + maxPriorityFeePerGas: '0x3b9aca00', + hash: '0x176030659b35c6557ea6400f9d110b1d70afea606bad6bf0c0de6728a183bb72', + input: '0x007cace7f78dd202271ec4c055c3d4334c000000000c55011bad18f83724291f80739a7f3d617f841ea525ff095af422a882138106032c018308574f1fb8c61b04040009400060fc5f9b22c48b1cd0486232315ebde6565745e7d4f5bdda16907977682a49b097cab0210e4b92f61262914b0d6462eae06e25bfba3ef281495960b257717935741aaf11c0a7463773fc5743e4196afe8e37d5771e19849d4cc3a0a6b85386d8f24450805d05ccc9dd52292fe13b90f011b7c5c487993c0cfda80764cdd50da50b88073061d85725bf9ee6419c37edde0dceb5d77df6a1cce5d9865d2f1492e79d8b4832868688ec34c96f5e210944c56ee45432f45d7759106461f6a9a7f4e033625f4adbba01bd685ffee935a8d9f55d10e031e5589bce6e8dae3ca0010abacae1b388651aaae380113cc83f3136229165e24f290d5b4f9a648043d2d696f26064f8bca18cb99f92e48ef3e24c1354965f3ee3b4fe238e3881287aad8cbf8263258faee16ec36399c8f6a6aeca5034ca7936cad34054dcfa37e719248360232c92106b79acd6215f1d028526ae8c9d51d94dd4dbf6c33dad27c4dd4f6e2e8625521d794ed9c86340386e1e8a1a3a6c7ca42afc33d9e2fc5bcecedb00180a22d60d662de681d365330fa6cb20fe1863a5a23be49380d5795c99c27f9b7ed89083daebda6f6df85c2928b6674532c3d60b2f4d6a5f8dc5ed50a894b8438aa9a6c4f5b34c6e0dfecb4eb550ce035ae07dd6fbbc3c38c0b372b555d59e8a821298bc688530e8b9120acf7e2affd323c26e9e16f2135335f761562ee47ea5c219bac9bab9530a7cfc5e6ab8e1c20aa50b993cf6f33c0f92a1d26004042105fa9e1ce0cc7d2f5e23b12bc49f6e6733390add378df97398c7b8356fe998d6e0a7f70ed73876ff40ce2dbed279213f40be5e05f160562ebd89e33c857e22948a116e15d607e10ffb1cf74ab5abf8c12f7a1eebeb397e529623c5619ce611b6b522e3f4a3d652c303d328d5b1351bc57d8f2ce18e0941b637ab78a07dc4733e071e3a32f9678a4e75ad65b39a95964bc67c300bb0f48298158b459dffec5e621fd0015d25b9159e7396556dd685db4beca86e93aa9d3f37e55908a00d436357dd5c395de6d97f8485e693c0df9242cda14c93cc45798f43b77cce337b6bf361fe71974aa3ca759e47f3fd8726bb78757f150d84ef7468ff6b3d3c1a832e8ffc51bd0e4dce4bb01037793e2d5519f950f908adc56698e832c994d59f9a6b32ff275eb5dc00a46d46b79eb8cb73d63f994e84c4b39ca200487bf85ce5a1588526e25aa569e0cd7bde9b7614dfe0214f1ef80a62951fd2686e24d66f53dfaf575eaf8114a9bc03db8611ca7027de1781a7f91d09d42e978d672ef40754436ff771d181233cf17d41abae1125aa98588b847b400f3c1f69f81739ae1ec4a1995ff0268b34d428b740a6817fae2d78c6fab0bd3085e4254fcceb53c631993ab2f58151f87e8229c3ffb023bf844588f06139626a2ff4e767def23ca652d9e3bbfb221d96d78bea2a0739e6355413fe5aa89e789811384029b09ce4234f1f0f253e4c8905a7aede8f75caa5199930f8f2042eeaf6597c4555bae1dcf427beb2788fd8883fa9cd547261a85fc1cf02ee8fd6baa0b3534887622b061cea54773c3dbf20f2f04a12b1c32309a43a54ad3fef08e820e7fc6587da77dd9202d12cf860db056403357fd42f330f0abb2a1c16c792661819a83349f2e5dacab43c71f6b3cbc126a4a71c3000ff995a774d3b0a30d13224ed140977edd3006f84b401be094628fcaf789c596d60f2fcc0d6e2d7da5f60f7bb2bbf5289ee465b8cad9a27d07e20ef9d518626d76793052ecfae5da17064eda2d30b5b057b48822f14e578dbf5607853a7f543b21076841f36087956c0b5429ae9c750c4d7f42dbdffef289a951c25b195f684669ce8000c5d226120e5218d703aef285171b7d199b49e44dbca3168b7b3c8c9333bfbfbe604f267422f02258fe5e8b869e1a8087b93d668dde9926eb2d9561d0587df4c4c582d2d9767b3622568f3d7c8eeb0c9b83b55ce124d808e443fc2c523d679a33bcd29e9678218169ed1c7012310a9d05104493c58dc6587ecdfd523353fd456037512e6a84342da47e6e92e7f328c3ca7815c99f15d4292ceb31cf5d07fcb2025ef3443045bf1fa56808a55f725d60460e539d41aac9d20ad12871a6930a7d3eb5a85c57d96614126bdde8dde8d88efc3bd0527cf7c350f0d3a5f0c8b4bd3ab76d27e450faad29e60adf61c8804dcfe5d7ff69cc4cf9f6bbd58c0fea56f0eaa9ee2246664e832138490eeea0d19e29f893ccfca00e7062fcf6712f56325a30546b9bebf69b7dd4d7e18af43319da46fe27d652696bc987917f879fac8e7b8c0689eed406e561022dda5318d31ab8c92b33e4ee4ac56730bed2a228479f2223eb7b58e481702d4ad2ef3a5690674367aa07fc721afa5fc7b9df3860170439c07f7c659ba5b80608b7a93573b44dd05c7ecada642a9391eba34b6a09b43e4900ed23c3716b7006a9b55332be50fb37a304fea2d91c06a3644d999647a93deb2e5bb12e479ec30e794abb0441f2625c011dbb803af4366507e835589b8206cdb172a1696df50e62106bc1c341096d26b4d8a59ca1d0a167c4dcf02b1f875d5822a2cdce89dd3a200e4a975d9d98a61a8b24bc309e10643a7cba51217a599158f8a973ad46e205476a7f0278f75aaefdf77b76b1e8aab35df882271385a727cbb3e86d9c066e6ae177fcda44268f2141349291f320825da311faa932198a6bd8844ce6d72fe54a5592ce04077a6c5832e0f17e5592771e9b913a9137aa03e3164669cd0d3dece0e3f6e0c946ba5c09181210c7954248d8da1c88f778e184b717d271e401977bd5092099f531a904e3ee4a222e130e591d6600d0e85029cc0c6a36ea7cf67d2afcee25a440c14535ed9ef93120bbf53c1321fc82747349b61635289180b75c976b44dd91c88fb0c8d427c96a04b4438080f1f3001f9f221afb15e74474bf87f2d6057f00e8949ce3360b8fa63811eca368b0737deb1e5995e47975089846ae6a254e80955e7bb31bc52688b87b4cf27314c8584a68dc68323cf1fdab451e7b400a8daba7e76093dd396701848f76261370e5a40b9c6a2f3c92e5c795491d78a834fc9b1acbf2b21104ccc062e3cbf87af3252b34156e97a301648fdf0e409ced0b128f8f561b2f3db4463aa724f47e45db30375dc9228f00477d0c096ff1dbe3c1ed5e9084526c3114606bb5e54dec1d7740fc4782a4389d156d5bb039fa524c508cc97949e66d981011a036fe9e83b334ed17ff097357c6db2d7bc22b8cbc6b126090f9881fa6349e7dee351dd083503d684999fcd55e99223f32409146ef136d3b4be509484f2eca12208b04c66b8962c88a2389ad4a767cd2b2d4d1744181ee695fd18c10b6544248f3e0d7d0bc6d7a3881db826c1b41be0aa8f5a6ed67b628ae4e52b1bce44a4fa1fb13cc66b06beaa319e4d40887b51ea47c54611b25d975f83601ef4159ade527d7b3f24f25c663933e06a1788cceaa7ed016c96c069664e21079d14d35c78c124fbdb234248e5b9a80e1367998e2a2cb357d82cb97cb80d460114a1af4e6c77a7bd48a240727f2033c3baeb4070f2bd1595cf46ef232f674958dfe3adf214fdd15805bc3981220a290e58809c95bb37aa025869cc9b0d0d0c750c3d444bf05973d0708ae03a94a43e4aa226727926979bc5ec9e335ba7bc048c0153e7ee16956e91bacc856fe58502431215490828e4c158a7da76b2bcb4dff4b45993e3279415ddfe5d1588412dfbcaa9e0c0ba053a44290feeed319ad6468b82870dfc99e1f2c9e482cfb6c65b80af64c00f447c7355aa1354f2a0bb3852aaff09e3e0f0820eabf4ebee278dfdcbf23da489e5328f5fcc934c5f8e5a9e0e9628523cf949c10e1b2a6e31c39320c69e15dfd1e43a316ca9fa2b334b8f1c34e649467f2df1920c930316783bf87e6f3dedcd81058013673a151a13edeeb9b0f5012bd07dc84449a6c62fca48021d5ee20d2e84f78437984e2d660063f9bcb2fcfe129a569e461e32dbf4ef10b980b85cc2bab9d309a6dc4b309f2c38368c0e8aaf49c6f5169d3cf1c333baccad978f7e84965258e14e5c516a59f7c6315851d8289a315fd2852ee8e5011d5aa31d59794a91e372fc26fcfa9fffe5538ce62e65aafc3f56ace0bd7aba1f833c2e7d21de24c4a29937e18fab1b6b2b6a350d845189a4c51f2e790b52aecc815018e539a66b49f6ea4669ef27142dc6531a8533964d6497aac619236f08c96957e889e6ef9cd6edf90e3c1023714983edb49a9efa341eae2b07f70d4c3e7fb1d7366de6211fb0014129c79bc89ec4211706566e7d35c4dfa1a8c82bf495505541a5e462b94ef9f24cf3149f5b28408ab4a2846da69a7177ad7234ecb38da1d370b3c2339ee634ed9f6b7acdfb0001', + nonce: '0x889d', + to: '0x86548826b608b1e25e820cc921c89e1cf3e511ae', + transactionIndex: '0x37', + value: '0x0', + type: '0x2', accessList: [], - blockHash: '0x241dab30227f58633e69fc4128b1c2b09699ec274cd575e39e697c1e460e5791', - blockNumber: '0x3148fe', chainId: '0xaa36a7', - from: '0xf921640daca3cbadc982e4cd3e1352dfc3a6b39e', - gas: '0x156c4', - gasPrice: '0x3b9aca09', - hash: '0xd463fb86b29f6fe631756bf475c210bac81a596486947e1439f6e63cfed71e84', - input: '0x5a045f78a44038d11401dbec7df63285e67ae6630cfab0cdd51dd840f1f73502442e412b00000000000000000000000000000000000000000000000000000000000351d826b0438b6b537ec888afe7b673f633a0fdd3732c3629e1dee30e962a46444e9d00000000000000000000000000000000000000000000000000000000003148fd', - maxFeePerGas: '0x3b9aca12', + v: '0x0', + r: '0xa349b1172e690abf1cd9570d6f38838f11c2c1b9decf01c1f694422f36133fd0', + s: '0x6c37e61f407aedfc3465cba1ea4979496f37978f9c4429824bc290a0bfd23780', + }, + { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0xcdc6565ba1c3a048c3463a1c689aa14a92d6e694', + gas: '0x17366', + gasPrice: '0x286c1ae5b7', + maxFeePerGas: '0x554a616d08', maxPriorityFeePerGas: '0x3b9aca00', - nonce: '0x2e5d', - r: '0x721ec552c6693810a0cc42b632f48ad7fe4da1ff2ee4e776eee3d951499c4988', - s: '0x62f4ebb094b6cea8e803d110944073c740428934f64ea7d07b662b3e3242b4fa', - to: '0x29674fcfc8f24e96de1c0cabf6366be9e8a00fa1', - transactionIndex: '0x1b', + hash: '0x176100bc921f542088bf23d48d17d636102f8d3ba748ad74a9d1aecfb0213dec', + input: '0x9aaab64877b92c94f1f9c3587c3825f9ae70e230cd1864a18e5e673728d5f2d2eea687f500000000000000000000000000000000000000000000000000000000000bd6007447394ef79bd5536bd941b9a46d25f191ab72fddc4d321b035f848cd77574370000000000000000000000000000000000000000000000000000000000679c2c', + nonce: '0x193f', + to: '0x25fa56da10ecd030034c9d0dc5e08bb462899205', + transactionIndex: '0x38', + value: '0x0', type: '0x2', + accessList: [], + chainId: '0xaa36a7', v: '0x0', + r: '0x1d0bd59adddbbcbe5714fb1be4c96a74cac75793d1ec0bf287db9e1e9620df3b', + s: '0x353aba5b9a5b0ec0489bd5722121559d6edc03e9a238472638b80a3d3656439a', + }, + { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0xddbb6f358f290408d76847b4f602f0fd599295fd', + gas: '0x17a2e', + gasPrice: '0x286c1ae5b7', + maxFeePerGas: '0x4b2e4d2416', + maxPriorityFeePerGas: '0x3b9aca00', + hash: '0x78dd8bc6ae88885718a768a339e221e21c5d5730a17c3a14c750045a33d13d8b', + input: '0xb759d685000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000aa36a7000000000000000000000000f9ceed22b37da45545e6f30a164e1134527e5d9d0000000000000000000000000000000000000000000000000000000000000229000000000000000000000000903ca654f4ef2d3ce8a63f4dc58e53d2a5468de6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000184a944142d000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000008ec8453f150aaf42c30c78ef37eb524b5e2c39d761fc1db0ec5089524e85fbeb000000000000000000000000000000000000000000000000000000000000012c00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000b48eacf882dc4899ae750af4a6e2892e11866d8d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000024c0d78655000000000000000000000000bcf5a29ab58d8ba03b1a2487066fe0e2389fb38a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003df9d7af377bb671e205621d0577f0d2bd838eb644fe5809f70d3dec5930925c2abcbcc1a40bd039c8dcc4050f68631d0a986a87534b61ab9d33aaaca3c9698774f15c20fc7b54db4371950321fab39c094d36786291120cef9b369864537e769', + nonce: '0x13b', + to: '0xf9ceed22b37da45545e6f30a164e1134527e5d9d', + transactionIndex: '0x39', value: '0x0', + type: '0x2', + accessList: [], + chainId: '0xaa36a7', + v: '0x1', + r: '0xa5033418f6e05ea03d45d98b96f7fa4d8323275b0a2850cfc4c9b5e6da43b813', + s: '0x20c302854c32b92d0276d2f6819771e5101a4ff08e859ef1a1039621111f3fca', }, { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0x431f70a6ff5589c84f021813169387dbf57ead3f', + gas: '0x5208', + gasPrice: '0x286c1ae5b7', + maxFeePerGas: '0x3344785f04', + maxPriorityFeePerGas: '0x3b9aca00', + hash: '0xeb1ebd4687cf91bc43491fba0ba3ee20d8174a8b9ac24a264f4de9d6a7a39dea', + input: '0x', + nonce: '0x0', + to: '0xe7f48e6dcfbea43ff5cd1f1570f6543878ccf156', + transactionIndex: '0x3a', + value: '0x110d9316ec000', + type: '0x2', accessList: [], - blockHash: '0x241dab30227f58633e69fc4128b1c2b09699ec274cd575e39e697c1e460e5791', - blockNumber: '0x3148fe', chainId: '0xaa36a7', - from: '0x81ee20921f17db2a4413793640242cbee450de9a', - gas: '0x15be70', - gasPrice: '0x3b9aca09', - hash: '0xcc3a340e784872ba9dba17f268029e94ed3c7a49f44a4b8c7a4b8cfe7325b9c4', - input: '0x8ed7b3be0000000000000000000000000000000000000000000000000000000000014b470000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000001fe000000000000000000000000000000000000000000000000000000000000020c00000000000000000000000000000000000000000000000000000000000001f60000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000002200000000000000000000000002408e37489c231f883126c87e8aadbad782a040a000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014b4700000000000000000000000000000000000000000000000000000000003148f63248d87b672dba6ba432253a0f0234f5a5651d75e62e4b01ef9bc38e216aa8bf000000000000000000000000000077770000000000000000000000000000000161392851f9e4f80dfdd5e53164038d4eab9d409064f46c477f24fdf122243f7326633e046a9634e080e562c66b0324def962a4006378fe0f13a406c6111baf40000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000003ca21100000000000000000000000000000000000000000000000000000000642d146000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004d65822107fcfd5200000000000000000000000000000000000000000000000000000000000000002d41fd4239a27793a7f50ef1d76d707d7caa032dea3d15dc9a6ddc6d5d123cc41dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493470000000000000000000000000000777700000000000000000000000000000001ee180edcf187969cd241e7b501b6d656532e368c638b3cf0a57452e80c5a00910e6c0f5afbd8352a3221c8e16a0788b77071e4caab301dd1460c63a5f5b573eb79338ffac4100fb29cefb1bf8d25d31ce802be5bb478c228300da91d391d348301200000002020000000100280000202000000400200000000000000000101000000020690000000000000000100000000000080000000400020120040210a00000000002000020000080088001000200800400000000000000000008a0000000000000002000000480000000000080400000000000800000200001001010804400000000000000100000000014000020000010110000008200082c00000000012000020000000040000184410010002200002400000000080000000400082000002000280001000000000000402000001000000000000100200000200002902041000000000000001442800000500000010000000000040400000200000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014b4700000000000000000000000000000000000000000000000000000000004072a100000000000000000000000000000000000000000000000000000000002b71d600000000000000000000000000000000000000000000000000000000642d146000000000000000000000000000000000000000000000000000000000000002e026633e046a9634e080e562c66b0324def962a4006378fe0f13a406c6111baf400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000016a000000000000000000000000000000000000000000000000000000000000017e000000000000000000000000000000000000000000000000000000000000016202bf20ff78727f38ef16e03bfb3d4895f35cc626f97ede7cc99f48aeff8661fe32015ea8d62ec7a79e01cd398e85867bafdcf55cb6a7121b6fef097f5f5656a5d11ddf336b6879926ea2ae425e91c748a553c9a496cbe2ab556a91689f75ee2b01ad3c43aa774b50a9d8411a9f65be42d6cde781db1a1949a1e886f868917997b0ea95e7cecd43cceb9ffc714f4ba0bcdc123b8a4f20e92f13a1f02593a06357f0ad6942c184312ac915c8257e7861522c254623309d3c80715fef6cbe94241fd0f08e557b5dce0aa7f49996a67c4aeb80da9ac6f8a59b17a42deae4fbb0d0cf427501d2a701bf47ac4bdda9edceccc79fbc2206a84575182910ee2177f842ac024b24b4eeb776f98c6148c70af4507793a9498a37912ea2dd3df171a246e39f0040a1eaaecb4e85f3e205a797bcf35f61f95e9e44ab7bb8944fb92c12319436f1b9285ddc38316f4ebf6b9994fab4e19b0e435fbe00cd5e226dc9104239c954a06f5769d595f0fdb2f898988326b186c1e58060d04b1b41550e251c92966d99c276d00a69728aeb2267d0418c449a8917a7a200615e9b13a9f235d2b5fd7e4870b431542bba9db9887e7e6bbe4cea702143a430cc71b2849ef31120ebc2eb6862ec1f3dc58875ca2bca527d44ee0092790742aba0d80cd6123f9306bb1ac9f7c2e2878692ac62cc461c7c7d705589f776258d8ab6b61319034bbde9e09e8094d1f31c13d11b94f892bb9f96bd2931b66ffa5e22b104c549e7c0d5010e4e70e271d48c0bd6e4be68c920ea77af85d12eb155d9b25703eabbd0ede1909565a55f124a9b47bdc5b67578a43da803f237718e4466a7332fde04fe7f7e95359c41d0d0a30ba1f87af98ff63fa8fad3dab09a9ac5f441eeba3d6ac745dfb16366684e70dccda298015b84abcb05eef07b122a8b89d151125c2d80a936fddfbc6ddfd6327774a9effdf97052d1e1da625c9ebd9a7d112bb11e00398dec228256c662d04293d37b7d902a1f963b5607481f6562bb1724a67d2ed32b18cd8b54cc428162f1ca82274ef593f6c23dd0a29a74ddd3fe8a72e6086824bac9713de2750041a391d7a23ea5dc60b5f0a4b559d4cecec4de8f9305645ca2ed85db7ea2ed03289c30667df22a0fa810f67c200700542abece092d7b5e8a947d1fb4c0e128cf68fcc1af7be52603bd54144505dc737c294a191826b6acadc58bd650a4ab26e27da961dbfa5d4f40a1c249676f4b2fd88265ed6b23942ef4fb1afd2f1bfb808fdb53c0d6fbc3535b14cec095851e5e40d1402560966dc5b7c47cf75c0412bb78addd71a838d7f3d86fe3fe3e083c852ced873d023178496d6cf7313b4a6221b9f62632887363beb7267e0480c0d4618dea58a2674887b3e3f85d0b795518c2d9a0f66054878b7556fb2438981a67961b72c7e153610338839573a6b1ccc12425fbeea1e13209866b3023609f91667a324c7d4428ae28b8e022656e087680adaa4a9fe2936ce41c44f1e0ed8f9c7cd65c68b1b8506b8e75bcd59264e450bbb4d348402195db45a9ffe868ab920485d66d23a7625d1b9892b4a2ac859f91daf6613fbd702addcab7a7cf571319efb37880817e04740f060190e441d231d492f286d99f72c23a1ac53940f261541002268dc9c73adbaad064622c60ddf605a331b16b1bb1efe52cb9d73ec837a69926f28271aeaf4c61f4f50996a913d35b8a87d0f66f8163f23a65e66eb5e73b17d02f88299254808157022094c1020bc5767cd421ed30bc948ce794f70ca50ca6204aeedc6f6e796848895494ae73fc62df3ec9eaf6a0c38a99ee1cd24137da2616f25283852b77a7441a7435ae2dd90f7baed98ca0b19a10d20c1797afdda343a4fae32b01b3c3d2481de39dd9cfebc6c2fe6e44e081ca7994177168fce45be9b3c1f5428805ef91f262d68f47d08ce1b9e884910cb0cb6d39b55f1f3eaee3faefd6a3326c7fbc3b23ec1bf88dbadd85d24d68342b9129e79b98fc11d88190e3de7381ac3609d1205eafa1a71a506f0eb7ed7a5ee78170c11d33c30f76a1b24108587e5d6872568bfbb1f084e8dfc73df6e0f4be89d1f0f344a9b233f287b2bb1607b7946fd20ea44dd33a33d64361e57ec59f5f11f12ebdc318118aa421e1a73f41a21092b48b56a0d8d4049740f327a4197688e2d0870d46ed0b715be2bf14888e3c041d07f45efb8eee2f0e7f8d4e417604cedcb289749fa70d1e564d08411684887c72288692a86756968a38167559bbf143eee0c6570b2b27926d3c243c7df6483f22fbd0e96a9bc4cc39e8ac3d6a58e4ac80d147f188e8e9a002873589a76c9d4f308cf346acaa48353c6fdbd3329ca39c56d1b7932b70e7b068a2656173d241e8f20bb6be3a3a3767111aa6f459f84be961c2337f6e03ed3cc6c847a3683894288b471504cbdc43a78f856801a10a87c77322e36e0ca426ec67ad3a2a3b79bc5cb81928a79a67a0fb46bb967cbab73fd36022f92d920204de61717dde6a85b7bcf57584c11ce54ac92998f856bf042a01c501a1a8456e7b562dee9eb814f525bc166583117e8da765b63d0c16b76934b46870fdca9ce6594b76b5e4872c05eb95bda7098574c78cf73d517b5ae6e5d0c7b1f2b3bd4735aa3c92529df74b20a6895b437507fc1f44cdc88fb2d5e8468ed2fc0188fd50402d78574867667b3bfce7befe91d569edabfe217be4ac2dd8101d63728a08b0d02c6f725e3c14c0f47f4b7ce1483bddae55ee7e95dea6691597fa6db17a326f43dbac5ba1e3408fb2eac7ca167e8483575097d9dc804c23ba18bfd6f05abad37349c8584fc581608dd8d2fef8ab93c62ec82f50be7f87ddde40fa2a809c87ee8fc92fd87dbac398573ea193060575c87c6768c45494e7fa005df93480ffb3f375da875f2ba0e29c56295674d4d183d339bdbcfd26bf96c5f27f65a631c9042429fd3c3d670dc95b83954d9ddbc465b380fe59ce05927a6be8173569a0c84a5344c3aaf0dafdfe58e9284e6af05c034905d71ec2bc32b8d10069a87db2c8c35b4c4293954b6c0def975b3ca0ce484970c73a6edbc8b16f561c5d61cce1c10f3b1fe9d7ab286469a6564af7075382ce7a3ce10c5ab9184d5fd493f3d4c207a79ce978290537e704d612be188ec67e9e8872e03a51838856958a3c656430463484d31623127c09c6cec446a9ac9a53cb6841ca2a097ceef88e537e209880ffdcfd5033bc3f5a885c271e41ee332366345fa867780beb3c1d5eaa496ea091cb5ef81b351c4285af9541ce297346db590831516f2df062c8877ae8f1852481e36d3873e806faa86a7fc5637f716db5b02a56db3aa483c344a001c25a8b6c6225ddc4ade14a5a09f647e6fc93608a7db35bfea1fe027e777a3bffee81cca151a06b44c6ff05c06711df8ebf241e92e2c14dd0100eb5cea607bfba67f41e4ec0f852db2d456600fa346f2c17073677406268e73f212abb1cb94fea99c8b996517d80e2892266757606fb78597a9a05a331480446dc07a1d89fc58faad15be2d05508c9a55988c822834db73ca745755cf77975ed577b23fc092b574497c6c992018836986a2a4b0facaa47ed1f40eebacb8cd53301f4ec7fa016f97211905bf05354a05fce802ed398737a699b089fcab8959f4c77d8214ba2374db718e481120881343903805c37499ac6bba1da7dca697c266c9e568b64e56890295f76cbf19c27f56572aa103dce1f100a14eac719d8c51b08c4533e1f1d203045106bbdc180e09061be491621237be12f8432c950d09bd6a6809421265e2e15911d9107f16933682e6831182dec2b2c4bbddb7afa67e9a02fcdbf47b3efb21121217bea50a9e2b57943e2b29d7c41ca458d1dffb84f68a65b4fa5f0abae20125aa0126b32ca8127fbbef4f975fac1107c2ed708ff1b75ac0f16a3e10bd846f045d4737222ae159016f7dd9fc4bb866af4854833992dfe8dd3f990f782add743a930012d3168a34b0ca765ef2ab4e470068ab13302ba4973c6bd9d2e9fba518ec41ebfd310ab9f21bf6c769c41c8b45b6ff3fd300df2ff8087c42fc91b9115e1910f089192eda200a2f58e1d6ff8f4f63a899838e0917d0b076af83131da73a62a0e0b77f09c9f039ae81639b318f3854299fdadcd73784dacea2257838ee8bf988dea7181040d11baf575eeb983b1302d68b004cba286e8bc80b7a9ddeb6d56bf155f3ab0cf18d1403e14ea037377e7f95b49f38b22cc657a053f3ad45fdc33b32457995024516142200f791d61578579daee3ac9d7918e282d4584c79631189af38dd9925f79c0cab0fba6ebe24d9df162434b70ad2137a3600ba01daa5551d07a2b1701010c130c299f8764c69c14cceb50fca46295b409e1cdc393533d034894182cd01907a72f435bf4e4cebccdb59e3faf40163a13314cfc1335315d194586a0541254fc915b805e6d2e141dc63cbab4c49eac4935a8b4cc9c77a431e3db4159d8025bca474bbb209dfe7566541abf6485f81d8be4663cd339d95a3b34d4f8a42d51a26894d6e65d9450ecab365b0b19ad44db4af7432a5b459ed2dcb119de74b6e15dda8c38011f120ffb6884ea329037b0bdb5a4a5004cb456daf9b32f5cd1c0f1e1048af2a49e9cf2303f59efba6e1abb882d112311ad2add10776ef94afd2e916fc3a8205ca02dce8cb27b10ba26bf0d1b04d03b71f03d5f434c8af51dbf77702efdb10b5dcd0809a6da828b0eab03eacfd1554d44a807ef2c5de63e4a5c398259cb476fdd0dd2c304c4ae01f6b7b2e10d9bd86eef4ffa4397c2cd4084778dd2ea6228a4f17fc8b341a34ee7ccfb240dd01e283396965ce2448d73fd5b8e5d203b307ee73583771b93e28e8f177c825af0f8f8b4f16e6df18e9d9d0e49e859621407fcb4cd07ab64145026fa670a9698c261ef0cb76b47c6ad6b008dac8c6f92098fd0b2ee74f50c009cecae4eda22a080c0c86986b84f86f03ac28e7d79283018922c535833ead6a1b16ea042ee0ecd1af9b126c4bba84e11b60377c5bbff5163c8940526855472f7c786a8694e003a00ffd1da1e16fbab04eee6fe2ec5a6d2bbfe13c5c2af082fdf2d1818bfb3cc9ddc604db743b13832b89bd65ac9bcaaa1f602034c07d2bc913276d1632a2e9dbfe2ac1beb5ba1b469d1fea029b8a2b8c1d574d523edd2a5bee0780530aaee255436c338c1cfc0454d903318e3a00f4c5101c9b501ed89bc8b2b92ff724ebc50e0d1c8767d9ee4d5e58d78d7239a7cdbc1afc710fa8ec879cab3203d51091b9541bc36087419a211ee32109b77e327dbd082a0c91f5bb3516abf4bdaa71a8648e100866004295a9e50a0ad4243b4583cc111d5b8098fa7dc34ca98f99997eb8004ec212e0f5d58f903f54082b3d072b682ce1b7d0d2cfb3cdc55213daaa780ea1150cd9042d5883a1137db6b7a0afcef826a9c2e694f20669cb53787de5addeeac7c8641b3d668e9cf4d31b504976b127210fb83d80051bdbcae80f5aa9030cbd616d8bbdbb0b7d9d2a7862e8917cb79b204d9301d418ca96fd93e218e7187618b2f0ec47821592b9c52b3eebecdfc80a1a5c28caa8b56f42a2ccfa30f6e290a64396796b6fed903ce630b57528e9348107f6e0a0a5a2958144078fe1185e9cfb8f4b4ad7bd74cdc2a3c05122e24ee66b24c6b5d84b0b671eb48d3a928692222210405af3b2d5156970cab5f8d642ff730fe04e3e88dab94466803aa0b28e2a539bda7bc023fdc83a485b526b6e5582452f5e99730a994763a792d0e2542333b7b79a47c1d8aeb3e035505168836d6e7c2ff1fcedfaf2583e33081894764a6e1619be587762d3b9c9699cd046e8ea0eef21dbd595fcd9c71df2f02bc72a29b43ad5dcbe598afb785bde612708c73228d70768a8f37ed1be14e7905a812b46c915728e188e8d3e895fe223279aa5c7336b23221735362e209e2889b68505f20c41d60e731fb48af1e6fdbe8fa1bcb5e69b269ae9866cde5b68f479671a68334e4571a02c0fd1520086f9860c0328ee41c42dd52ea913d72ae6126584d42b15c1a2a5100236df160157f7fd213b031bcee528a1b8c0bb475069a918cbefbcf2dbdac8676483b2471e8adae1132e5beeb3b6210b43f3abcf96caf95692b855cf0e5db4eab0145fa54fb83d30ecf48fb16c001873ca92de8bd0d2b09cfcf49b5b0d8b50c6f99309602d17fa3c809830fd468f1a49d67be412fe930c2011ed756ca6f5197be70a04dee1686a07bc30ec6cf57c2a877f667410839e6882ab38bda1b51a54be67771dc8c80e1a8d515a33cafe092822b78463c3965d7c773b303f990a802b1c63a303b781c579273bfba954383919ee9238aa15231a80d75570a62e3dd08e9423275b3748c554f1bdc73c86e6572006491e1aa8f09f9d65583e97536fc0d913317b1aee89f537946ac387a7e5c6227a860e26fe3cea6dfea1bfcf3195104eea752d05525093c23841703a6e26a0112651daaa1072b3373a87235d4e80558f8f89b503ddb0448abdc4ecea5b907f0a424151ec50f6e8c813f08e3f37b695c68a1da8a35037985994291f97d7e78312981efa8ae18e5097ef5a39ec20e278aa6e7bdb36a5fe9cfda8b8b21814b0082ed09628ae5ff87cd89c81c2718ad0d55d9b00fbf3f96f4643f9c6b4b863309d09c7f64e51f2e419c8f74ba5bca8b33184e788309c3e9bfdf357c9abdcfaf58624c58b0978639536e838e7b37329155f72ddfcbd169156d272aa9f26857de30419ec04071ff9d2c7f56adaf08865b3aa55cd9cbcfc3ce4d2f292b319578df3811eb8f283a49d00adf709afc2a3bd646158ccd8846fbe77a850a77ec62bc3c18d038cc76d62c7a40bcec980d14fd291e17950985299a6cb6fac49167464dd734a11f4553a8f202609a1edacd64b680c003b711561f0b680f9760bedf215f62dce1d2fd2105ffe428d6ea1697a4e78187121df225472a09d4253835a8cd3244f2508846c4a1b6c59153ed263edf250bf64dea18a214e6425edfe0303eb8a6a8ee714010d1bddf92de313c209d0577f1fa845229b2ad06aeac09b2e880e74a6d3d61c544f2710b9d8634a7b75d3914e857c218b6fb077a14dac3c6953e91ff9e47322dfd143da2656b32ff72a3e5f2577cc05bcc0728f1c6218629c14a1995c96ad20af3782e3f8f7350c23d8cd1f16163fdc499a83d6f338d3de6908ef4523c015197f334696777b71ac026ab03225e22a65ffa07440de66c5e12e89e7d896d8942b895e01dee383588084337dcc9186473074499e8a9b64b42c1dfaf56216cde7188af85aa7549c42d4737b867514e5c53b7709b21770c868a88b69bc19b3ec3912773dcd4c4f80865be517d7a71a3a84648669f0109efc47561cdfbae366b9911c5f16af4dd990a55a1e97776419804b6f0cf129aae0a65565d9a1672c4d454805569db0397b08aaeb1094dd0ca8527463f247630bd239e9133ef2ec6fd8e7a00dca0f10ebf122ee1c3854e242307c94a8d954359ed923c1e22c4f9447b6aa7306a4eadd067e8c2713d8626540b0dc09305e6e352f809614a29848d69e9413b42242cf4450c9ec9168d3b6cd4785399e52fcf07e996f3b3838476dc6a4f7f2542183edf2b088899927498bc653196bd4b885d737ad926351b58def91759b1f35186159f9a180ec1e55d681781cd1f9d2fa1da758dcf4ab70108db61c0bcf1ac319dd3d266693eac735b312ea2fefa6e83fefbc3d515d56d885bfe2af3d8e970f0015b6881b6b88c6b40dbcba8546600d3171dc1429c875c9ddd874dda1e4424325b443b47d88bdb2a43f0937e96052b971803041112a7b000431e585af9134be16f30d90412876d38329ac1166c222cc9ea68bb11eb73d6d736452c13010640a2ece76ac65f5545069390f93bedbb77ad3e24064ffead9b509a020fa1e6d58eb0e1eed845b788a17e7ecd5cf5cb49683154c6aaf61464ee494ea530d77d6867b0252bba60f34de96239d0be4db7ededbd8562cb5fc898e4c93c14c35f0e46934000000000000000000000000000000000000000000000000000000000000010cf90109b853f851a039fee3b1b52c4050fee3645ef3892dcf67dd49afe451d52da9628f78b30f93da80808080808080a0bfd2c2c6fdcb0e0addc8f03535632e4c26491b593ae1dcca799a189ea6f78f7e8080808080808080b8b2f8b030b8adf8ab83014b46808303d09094000077770000000000000000000000000000000180b844a0ca2d0800000000000000000000000000000000000000000000000000000000003148f63248d87b672dba6ba432253a0f0234f5a5651d75e62e4b01ef9bc38e216aa8bf830518dba079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798a00a10a46dcd1ff9dcdf23a3b70ffbaaeed9017652f829a35fe91c796442c03e73000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001ebf901e8b853f851a00c1232913970f6ba64121513c54de53cec3b12062b1d763a60fd3159dc04b84180808080808080a0fe254438a68341820f132398f2ae2b48b5bad3ecc0796b53ac119791061da3c58080808080808080b90190f9018d30b90189f901860183039445b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000040000000000000000000000000000000001000000000000000000000000000008000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000100000000000000100000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000f87cf87a940000777700000000000000000000000000000001f842a058313b60ec6c5bfc381e52f0de3ede0faac3cdffea26f7d6bcc3d09b61018691a000000000000000000000000000000000000000000000000000000000003148f6a03248d87b672dba6ba432253a0f0234f5a5651d75e62e4b01ef9bc38e216aa8bf00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000adf8ab83014b46808303d09094000077770000000000000000000000000000000180b844a0ca2d0800000000000000000000000000000000000000000000000000000000003148f63248d87b672dba6ba432253a0f0234f5a5651d75e62e4b01ef9bc38e216aa8bf830518dba079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798a00a10a46dcd1ff9dcdf23a3b70ffbaaeed9017652f829a35fe91c796442c03e73000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000189f901860183039445b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000040000000000000000000000000000000001000000000000000000000000000008000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000100000000000000100000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000f87cf87a940000777700000000000000000000000000000001f842a058313b60ec6c5bfc381e52f0de3ede0faac3cdffea26f7d6bcc3d09b61018691a000000000000000000000000000000000000000000000000000000000003148f6a03248d87b672dba6ba432253a0f0234f5a5651d75e62e4b01ef9bc38e216aa8bf0000000000000000000000000000000000000000000000', - maxFeePerGas: '0x3b9aca12', + v: '0x0', + r: '0xc2464e2cfedaa54a921db1822c11862fa6399858f4a391d2d52b9f098a981e8e', + s: '0x3737456aa09e9bfe175e140c1f6fd77cff8474c7c67a06db3577a19ce1d6bcbb', + }, + { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0xe894ac1a1e76fe339275c78ed5193c327659f601', + gas: '0x545c', + gasPrice: '0x286c1ae5b7', + maxFeePerGas: '0x554a616d08', maxPriorityFeePerGas: '0x3b9aca00', - nonce: '0xafad', - r: '0x4ff829fe4720ebe3a48ed0ef37da1586961d6791a210b6ea57410db3aa875c28', - s: '0x663e7092e6e93c97a9451f1354cc6e29b862563cb0155d0bd971811a628c1749', - to: '0xac9251ee97ed8bef31706354310c6b020c35d87b', - transactionIndex: '0x1c', + hash: '0xf3ba54f16d43ca6bfe854046b75a29ceba6a3538036e447f93b7278fcbaefa22', + input: '0xcec4062b0000000000a586f9d9dea0d04e184bd9756b1ad9fc11f17164d95a6e0da53e5069490e6d82', + nonce: '0x6d39', + to: '0x57ab0658c5f0368692352e09b4a508c310f6e93b', + transactionIndex: '0x3b', + value: '0x0', type: '0x2', + accessList: [], + chainId: '0xaa36a7', v: '0x0', + r: '0x991b9aedc40fabcc26f122c14f0e7f9ebdbfef54498bf9e467c1ddb5c188a03a', + s: '0x145f78fa83beb02f353fd0eafe5cbb4e6c81a36a5787d466d30790f416cd4b36', + }, + { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0xbda2e2a27d26a289733851a16e828e989efcd738', + gas: '0x5408', + gasPrice: '0x286c1ae5b7', + maxFeePerGas: '0x554a616d08', + maxPriorityFeePerGas: '0x3b9aca00', + hash: '0x13179b4b22c648cd8a53fa30f57df8ed2771cec9e35f2f6f19e98eeeaa6d02af', + input: '0x8d53b2b31d6561feb10995698094454374427092e7109f04eb415a9bfe5a88aa', + nonce: '0x5cc3', + to: '0xff00000000000000000000000000000000062049', + transactionIndex: '0x3c', value: '0x0', + type: '0x2', + accessList: [], + chainId: '0xaa36a7', + v: '0x0', + r: '0xec98e1cb9629e260253f162196ab2bab585497f149873f30b1470efe626413c7', + s: '0x132d80ec182c29b270d1fcf182ba4f0fa5f2bfd223a287a6892df4dff430e4a1', }, { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0x13f33de6ac52d0ea058591399cee8b507da6202d', + gas: '0x5208', + gasPrice: '0x286c1ae5b7', + maxFeePerGas: '0x554a616d08', + maxPriorityFeePerGas: '0x3b9aca00', + hash: '0x9c12c2f049617879f93ff22d810f2ef6f57184c11005d88cdcc4b444c39e9121', + input: '0x', + nonce: '0x1965', + to: '0x6b155110d263b06432603d27184be620340683f9', + transactionIndex: '0x3d', + value: '0x0', + type: '0x3', accessList: [], - blockHash: '0x241dab30227f58633e69fc4128b1c2b09699ec274cd575e39e697c1e460e5791', - blockNumber: '0x3148fe', chainId: '0xaa36a7', - from: '0x1e2cd78882b12d3954a049fd82ffd691565dc0a5', + v: '0x1', + r: '0xc4daf80bcfe1fcbe2e96275d8d8ff73aa8721ac70532a0b7605e60d4f18537f9', + s: '0x1c06e5bceb1858a12bb23a41a34342a884e0eb6c426b9f10c89968c36963f263', + }, + { + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: '0x679c39', + from: '0x93f76439d78e0508bb1ab4fbebbc1f38541a9a34', gas: '0x5208', - gasPrice: '0x9', - hash: '0x31e1fd8c0516fba03ebaddf860ca4d16a63904e23b412ed7c2832c7906cf199b', + gasPrice: '0x286c1ae5b7', + maxFeePerGas: '0x554a616d08', + maxPriorityFeePerGas: '0x3b9aca00', + hash: '0x5252837552ad1d7012080e835ffaeecd751df86265d0a462b49251e2724e362f', input: '0x', - maxFeePerGas: '0x9', - maxPriorityFeePerGas: '0x0', - nonce: '0xbecb', - r: '0x5c720720ae8fb9cd9a075e5dbbcf54b67cb4448db579a5cbb2518d1f24abaf74', - s: '0x7d52476bd7fbfeccd82b32f01280b304f02b44ec6f3e1be0f4692eca07cdb8e2', - to: '0x388ea662ef2c223ec0b047d41bf3c0f362142ad5', - transactionIndex: '0x1d', - type: '0x2', + nonce: '0x1629', + to: '0x4a16a9ad14becfb8b3d209440edb6eacfe23c3a9', + transactionIndex: '0x3e', + value: '0x0', + type: '0x3', + accessList: [], + chainId: '0xaa36a7', v: '0x1', - value: '0x143c70de9f84c8', + r: '0x8619a78020cf705fa6f38cc0af9e4531137f4c375cb5ed9f6d21ff050d865438', + s: '0x78c502f9c5637c9e676551fa1e3f68745b16ecb19174b74c82c5470baf37e4dd', }, ], - - transactionsRoot: '0xbd2f86bc39fbe1ac6e24ce390d268404c199da060116437803875d2c0bfe7970', + transactionsRoot: '0xe4a018004a4bb3df8799eb0e69147b5c2bee6473d4404d55ccfcaef2efa4b568', uncles: [], withdrawals: [ { - address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', - amount: '0x3112f', - index: '0x3a477e', - validatorIndex: '0x38b', + index: '0x39f6e79', + validatorIndex: '0x197', + address: '0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b', + amount: '0x30f8e', }, { - address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', - amount: '0x2ef5d', - index: '0x3a477f', - validatorIndex: '0x38c', + index: '0x39f6e7a', + validatorIndex: '0x198', + address: '0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b', + amount: '0x30f8e', }, { - address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', - amount: '0x2ef5d', - index: '0x3a4780', - validatorIndex: '0x38d', + index: '0x39f6e7b', + validatorIndex: '0x199', + address: '0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b', + amount: '0x30f8e', }, { - address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', - amount: '0x23743', - index: '0x3a4781', - validatorIndex: '0x38e', + index: '0x39f6e7c', + validatorIndex: '0x19a', + address: '0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b', + amount: '0x24c8c', }, { - address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', - amount: '0x2ef5d', - index: '0x3a4782', - validatorIndex: '0x38f', + index: '0x39f6e7d', + validatorIndex: '0x19b', + address: '0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b', + amount: '0x30f8e', }, { - address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', - amount: '0x2ef5d', - index: '0x3a4783', - validatorIndex: '0x390', + index: '0x39f6e7e', + validatorIndex: '0x19c', + address: '0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b', + amount: '0x2f9fe', }, { - address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', - amount: '0x2ef5d', - index: '0x3a4784', - validatorIndex: '0x391', + index: '0x39f6e7f', + validatorIndex: '0x19d', + address: '0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b', + amount: '0x30f8e', }, { - address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', - amount: '0x2ef5d', - index: '0x3a4785', - validatorIndex: '0x392', + index: '0x39f6e80', + validatorIndex: '0x19e', + address: '0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b', + amount: '0x2f9fe', }, { - address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', - amount: '0x2ef5d', - index: '0x3a4786', - validatorIndex: '0x393', + index: '0x39f6e81', + validatorIndex: '0x19f', + address: '0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b', + amount: '0x2621c', }, { - address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', - amount: '0x25915', - index: '0x3a4787', - validatorIndex: '0x394', + index: '0x39f6e82', + validatorIndex: '0x1a0', + address: '0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b', + amount: '0x24c8c', }, { - address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', - amount: '0x2ef5d', - index: '0x3a4788', - validatorIndex: '0x395', + index: '0x39f6e83', + validatorIndex: '0x1a1', + address: '0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b', + amount: '0x30bf6', }, { - address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', - amount: '0x2ef5d', - index: '0x3a4789', - validatorIndex: '0x396', + index: '0x39f6e84', + validatorIndex: '0x1a2', + address: '0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b', + amount: '0x2f9fe', }, { - address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', - amount: '0x2ef5d', - index: '0x3a478a', - validatorIndex: '0x397', + index: '0x39f6e85', + validatorIndex: '0x1a3', + address: '0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b', + amount: '0x2f9fe', }, { - address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', - amount: '0x2ef5d', - index: '0x3a478b', - validatorIndex: '0x398', + index: '0x39f6e86', + validatorIndex: '0x1a4', + address: '0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b', + amount: '0x2f9fe', }, { - address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', - amount: '0x2ef5d', - index: '0x3a478c', - validatorIndex: '0x399', + index: '0x39f6e87', + validatorIndex: '0x1a5', + address: '0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b', + amount: '0x2f9fe', }, { - address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', - amount: '0x3112f', - index: '0x3a478d', - validatorIndex: '0x39a', + index: '0x39f6e88', + validatorIndex: '0x1a6', + address: '0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b', + amount: '0x30bf6', }, ], - withdrawalsRoot: '0xb99e42eaca3fc1000aa8be987cf107e08030c0e9ca93dc6ea6b7df69e377f953', + withdrawalsRoot: '0xbf6f1c2839936522db766ac4af3ec3cfef01e91d71dca8917d90affe0874a7b9', }; export const sepoliaBlock = { + baseFeePerGas: '0x2830801bb7', + blobGasUsed: '0x40000', difficulty: '0x0', - extraData: '0x496c6c756d696e61746520446d6f63726174697a6520447374726962757465', + excessBlobGas: '0x2ac0000', + extraData: '0xd883010e08846765746888676f312e32322e36856c696e7578', gasLimit: '0x1c9c380', - gasUsed: '0x4952f0', - hash: '0x241dab30227f58633e69fc4128b1c2b09699ec274cd575e39e697c1e460e5791', + gasUsed: '0xce24f1', + hash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', logsBloom: - '0x0000000c0000000002000410a0101000080100004000001000000040200040020008800000800450001040004000000008004040008000000000000000a004000000400000002080008c020800006080010c22004000010100002001400008000082a040080211000c01010002000b00080000000800000004000010200100044020008008082100010008200805800001210000200000000004000004200000820800800000000010140040504400082404000300000000100080000000400000400002113000000000000040040008240000200000000110002011000001000018122010020000002400008000000008090810000002001000200800300000', - miner: '0x1e2cd78882b12d3954a049fd82ffd691565dc0a5', - mixHash: '0xddbb2beaede8c4a7c401156c0a02c58b3c0732e25bd5bfd350a599c54309929c', + '0xa40000cc8104c208801002c28490789000090c102001a11201500c1a448300230001a001042021041000080000148388440828801e090408805090040024681010024002880420004008206e0100480004020002130610083c024020180002214a2c034002a12202a1c0402012000900004800c0000a00c02000051801408a000222b900129005003020081002010058800440201012200400111000446000782288020200010a0049c0914438010408044142c9801008080080a01302020080800610b20800140c00222c439803088a0004000041008040248592000c216000081028090502200001041141240800008a03001a59d412a004012b940139d004', + miner: '0xf29ff96aaea6c9a1fba851f74737f3c069d4f1a9', + mixHash: '0x3d1dbf1f0670c91819b881dbe1862be1ae7955e350b5356129e56ad119278428', nonce: '0x0', - number: '0x3148fe', - parentHash: '0x26b0438b6b537ec888afe7b673f633a0fdd3732c3629e1dee30e962a46444e9d', - receiptsRoot: '0x1ca1776ebf36ae37a1f48770684da37fe1c8fc134954b229b1f619e5e0ad2c51', + number: '0x679c39', + parentBeaconBlockRoot: '0x995fe00d44a9851fa744a16bdf0ac7ab5d607dc2a30ec92957abc7ff3df7274e', + parentHash: '0xca67b2df0e6f1d010c5ae7b6fcb569c153e82065bddc282733d911b10f322824', + receiptsRoot: '0xc6dff7f3c4d8b267684cc3c76b4fe730f76c4d77e613a0f29ec39e2c5a231ec6', sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347', - size: '0xd66e', - stateRoot: '0xc9e235dd0e663f36fee8f80d860961f2e8056f4cdcce501372a77bc1fed20534', + size: '0xc612', + stateRoot: '0x1424d53811f37147d5103cc46e0b02644348c737b7356f7b24cb35c999d38f18', + timestamp: '0x66fb196c', totalDifficulty: '0x3c656d23029ab0', - timestamp: '0x642d14c0', - baseFeePerGas: '0x9', transactions: [ - '0x5d703f823e7e4d6719def234cf8683d0d34708c2b0ce0285f4b008bf555b0481', - '0xa8a6e1f58adfe40a059e037c6c2b6e07bd23aa3d32d892bfcc6f40d85f22c907', - '0xa4335f3948675d7cd43b84078e3567860b4e1ffa79e9f6e5278f1d3fc860699d', - '0x25553d98cc5c2758b653b122a461e08250a0613752258ff1ecbea813632f08ef', - '0x5b7ae021605d0fad23fd882d48762851858bf0b6188641d619481f5ea230c502', - '0x6ff0dbf6f27ac5bd4cedebca54424e4ddf5bc6db1aeba945c2d980e7d759e5c5', - '0x234db0c295cf5d70729dc85b36a3df18007c80e1e6c5dd3465f739be81b062c5', - '0x745ebf4cddbadb01df7eb32e393df6f712bad3d6f45d935151eb402fa2bee5d6', - '0x35607880ee334b3e5a2bfc419aa32d4ec2b87445a0c58b347c945265ffc8e57e', - '0xb3f527bc8306499630857a4d92578b2d492762e7828580af536ed10128953327', - '0x59b21c5451f4c6bbaef6758aa4ddac3d350ee9d6f7f79cbc8aea1e4d6d30f32a', - '0xe3708d5286b2a3fdb73db6b9409c70e121e65cd5896682f011e97b578906245c', - '0x738a0a811d13a8735bd7b5ea4b784a0dff23e6bfd2b1897303f731bb49ef19bb', - '0xd63d4edc0ca6567cea22cb342eda67d37bd4a5a5a36cb66e233f368a8f98c7cb', - '0xd383977c4ab373914a2199b5673eb43b1cb3c86a129c29a440b67b8ee491bad2', - '0x554c50ff5d6578a8ea4a352651106151d0d4b5fc683fc4071096463744b3013a', - '0x92d5693632cfc366be1a143bf63aef7b6307db1227e40d7806d1fb21e67137f7', - '0x72bb6a4add14cb640948ebd801898076372c86bf2eac41154f414738da1d1a32', - '0xc33480b85a113f779725fd2c1788ab95b066792a898ee0eebb0e98c8fa605989', - '0xa8685562865ab1e6c73816fad05a38d6ea0670565ef27add5f4bd16db852eb46', - '0x7cff5abea75fd389d37b08fa73f8d4ea6c2a00f36c715fda422c8d92f05aed78', - '0xd844bf22fcdd8fd5c472638540f114824082359ef753a4f9c929889226dec5f2', - '0xbafae79055a392cea650f90096a305d1338a170a66b58dacaf69a7feb2b3f187', - '0xc9f12beaeff3325c3b58c03f66f6526593432f623d2a873bd8ca7e9f9d3c48dc', - '0xc8314b15135d8629e2423065b853fe91d7909d7cc9450e9477e667ba84eb45a9', - '0xc96f60d36bee10caaf4b40ddc2c90e752d7d4abebdd29646efff6b8a6454d070', - '0x61f293e6fc8978ee7e4f8c47e678f44ab08bc475134952452422c9ed96ea0b65', - '0xd463fb86b29f6fe631756bf475c210bac81a596486947e1439f6e63cfed71e84', - '0xcc3a340e784872ba9dba17f268029e94ed3c7a49f44a4b8c7a4b8cfe7325b9c4', - '0x31e1fd8c0516fba03ebaddf860ca4d16a63904e23b412ed7c2832c7906cf199b', + '0x2d771040a4c584af05fccb1483ce4c52d42e046aa08fb733bbdea00fc806b57a', + '0xcf811d80757452f648f74bea7cdee088c5c2addafd8d049f644fc8cafee7a50d', + '0x1dad76ca8ee9f98c6f3ae0e545cfcd0381d457f75021f42f6b8b9a9b0869d10e', + '0x75cc3c7d744f1b6ebad382ba5c4bbe53350798cf73ea8a260c6bf2e13eed93cb', + '0x72ddcbddde555cd12b458c9ef1c1b95b55e0c99cd266bdf252e8e2d2688d8087', + '0x66666900f2d02bd946a2036fe6e6c51071d369201f9eeba3f8b6fd4b5eee2d9d', + '0x26c7693fdc8fdbf1091d247ab04f451b271cc2a7143d7ac4d1e1eaa46239d83d', + '0xe68e725c220c97ff5a7cbb8d570eba2d78d4609ac0f90909ad9dfb916b19bed5', + '0xda794cc60352fefb6f2ba63cd0316db0c9dd27ec6d86c485ede06944c35dd7e5', + '0x35aabcf773f5121f01730f7ae9ef497cd7e7f941b3cfd59304f8bac90e54cec4', + '0xa6b563e6faa0908fba5a14606d0a4132ac710887823da37de7589cda4b47328c', + '0x6e47abdc2e0ae1bf68a72a26b7b9f476b77955623d7fc6b51729363e556a06f3', + '0xf190a73725b4e35e9c62cd12ae2cad28042d64875a3120d066b20639ac3f441d', + '0xae5721f9c9ee178a4a3e651c0732e5cd260bed24663f5e5f70670a181d426cfc', + '0xa84f8c29a46e8003e0d45fad85cb04b0a883814cdcc50c79668c79f6fe26f8fb', + '0xc75a978c195d19b4ee4bcac2adf597237b8af228d6b2cb7359fe311922d6638c', + '0x02311edfcca59505ef38e680a53fd7a380d163f2a4887515e98610e7afce1252', + '0x057371fc02b3b6eb653f6114e426f42f985c0db1bc072ca02975e2976b468a9a', + '0xf8ff44a14a651fa9b4a353730f09f65a78e672c4bb468eeb51c0eb00d0dac0db', + '0xdcf062bb7d0217833dbcdaf4b2320df7d99a6e10cecfb0fe383afeaafb30fe5a', + '0xb8cceca254a0f17f894ec1684ee6ec54fa8e5bb40f06c9caff9a31e69888e199', + '0x5c9fb5b701b5d05e8012c05e1f88c534cce03d1a880c20848c6534f86b331233', + '0xb139f91cff2b7bca7c0bd4ed942bc1d6c126ffdd7c3fdf475f5d7eccd3cfc6d7', + '0x228df1f5c02744e2ec623906df75bb4445b4df0b1e4a38ba71daaed91ea37f60', + '0x1b54cf530ed26e051e395baf9f860b27602fae051ed5942733d22f2eb02d9330', + '0x054e3318eefc580f7b394c185d7bafc91b2c579816f78974bf0deb67358bfed4', + '0x3a3954bb8706acd07922e84ea3129799f2e2e51c839344358cf2647674724050', + '0x4c7368c0d34ea697bc97c50d2359ba2eee8f32518523bd8aa79616e8450ee894', + '0x28fc033d69b961f2bcc756e9127f932350ffa1dca72c20eb6337e6b4bc9e0d49', + '0xdce175cb3adc6c61a28cef7c2ac9be5392a54e0f6f1ef7fde2aaf6560b4b7604', + '0x2e2a631ac9ede986145bcd3c156670f2f646e72278c4e3e984e651f7c59d00d2', + '0x4ce6a35c0e68f90239f8aa5b3f21a04e317ae63c729e20121b3bcffe84b9ccd6', + '0x9fd281e4699178dd3fecb22a25142838284e9a1e5c499f0babc790ff82106ef7', + '0x5daa9ce7f6272210ff526b31480cb390beff9d639ded882cfdefd4e3c92f1d2d', + '0x8fa6437b5c4d710ab034504fe4c1f81b6cff05ffd5bec97c96c5692f70fac4ab', + '0xe7362584fa34de12abcfb15d918619a7f5c7d8417e8d67637d52a88108b34820', + '0x027b0ff3e896e00bfaa74f934d46c5632661fd276e7a928d4c9e9b79037e644d', + '0xf80502f2719543ba49fe5c7bfda7e0ca517bf237b41653f633b2c633c6dbdffb', + '0xf0626f99ac424d766cc4d135904b0b206abefff50e4ac2330b66a42cc2ddb019', + '0x51ffc58c43e144388e744344fd782c9cf88a7bf78741caab63ca86a961e7314e', + '0x958f8eb93a4a10bcb69e4ef703ee3474c5e516bee213df08db5f18b82c8fa2f5', + '0x6c6053b2beef9a1bcdbb88f5f3503cbe1c7a0dcfed98f90a1ab29ce2b57ee331', + '0x2bd33e3268d6865b3a262a4c4c19f8938af2b243a68ecbd398e16ff6d50b2643', + '0xf600a98adaa021ab929f3286363fdb83787d9a68f560842bb0a1844732f851f2', + '0x3bf24168c7c5d4036c94d26673e8de3d96bd332d4efc0d0546292ceed9a799cd', + '0xa8965bf2af65b01ea8c2ec21081486e03b48bdf5eeea0663b007f800ab41772d', + '0x9cb28e006a3f1880091d533064c3c157ab0a08e3ce7506cb42afbe465e236ba9', + '0x17c174883f54dfb11c9f0f373008ab0ec46d58599ffd7d7d78d174fa10216cbc', + '0x8eb9a51e113c99b5f2e6af8fd238d2962fb1c820e592772f52a43e1060eff41c', + '0xdd2a3e0bbd72c7d98e2e9564ce85321e6fd84bdaca541e86324b4ceb7e20e927', + '0xa619091df1b3ad1837921f84425446fc786cb5264f48dcdfa0c21d3b20891c24', + '0x2d6c49020598a9d010da56a2e9c99502241b70a4f8a7c84546af6204aacf6440', + '0x67d8664ab3a41a54559bf779e9442780ba714272969412b521e38368ccdfcb72', + '0x63b8e148241c5ee88ef9b4f7fa1f9301dd1b472f166412eb10694516547ac3ab', + '0x8bf86600b9c25429756dc5a5e7c467bd2e85a98345aa94d4933619ae2c64cfee', + '0x176030659b35c6557ea6400f9d110b1d70afea606bad6bf0c0de6728a183bb72', + '0x176100bc921f542088bf23d48d17d636102f8d3ba748ad74a9d1aecfb0213dec', + '0x78dd8bc6ae88885718a768a339e221e21c5d5730a17c3a14c750045a33d13d8b', + '0xeb1ebd4687cf91bc43491fba0ba3ee20d8174a8b9ac24a264f4de9d6a7a39dea', + '0xf3ba54f16d43ca6bfe854046b75a29ceba6a3538036e447f93b7278fcbaefa22', + '0x13179b4b22c648cd8a53fa30f57df8ed2771cec9e35f2f6f19e98eeeaa6d02af', + '0x9c12c2f049617879f93ff22d810f2ef6f57184c11005d88cdcc4b444c39e9121', + '0x5252837552ad1d7012080e835ffaeecd751df86265d0a462b49251e2724e362f', ], - transactionsRoot: '0xbd2f86bc39fbe1ac6e24ce390d268404c199da060116437803875d2c0bfe7970', + transactionsRoot: '0xe4a018004a4bb3df8799eb0e69147b5c2bee6473d4404d55ccfcaef2efa4b568', uncles: [], withdrawals: [ { - address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', - amount: '0x3112f', - index: '0x3a477e', - validatorIndex: '0x38b', + index: '0x39f6e79', + validatorIndex: '0x197', + address: '0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b', + amount: '0x30f8e', }, { - address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', - amount: '0x2ef5d', - index: '0x3a477f', - validatorIndex: '0x38c', + index: '0x39f6e7a', + validatorIndex: '0x198', + address: '0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b', + amount: '0x30f8e', }, { - address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', - amount: '0x2ef5d', - index: '0x3a4780', - validatorIndex: '0x38d', + index: '0x39f6e7b', + validatorIndex: '0x199', + address: '0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b', + amount: '0x30f8e', }, { - address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', - amount: '0x23743', - index: '0x3a4781', - validatorIndex: '0x38e', + index: '0x39f6e7c', + validatorIndex: '0x19a', + address: '0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b', + amount: '0x24c8c', }, { - address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', - amount: '0x2ef5d', - index: '0x3a4782', - validatorIndex: '0x38f', + index: '0x39f6e7d', + validatorIndex: '0x19b', + address: '0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b', + amount: '0x30f8e', }, { - address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', - amount: '0x2ef5d', - index: '0x3a4783', - validatorIndex: '0x390', + index: '0x39f6e7e', + validatorIndex: '0x19c', + address: '0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b', + amount: '0x2f9fe', }, { - address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', - amount: '0x2ef5d', - index: '0x3a4784', - validatorIndex: '0x391', + index: '0x39f6e7f', + validatorIndex: '0x19d', + address: '0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b', + amount: '0x30f8e', }, { - address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', - amount: '0x2ef5d', - index: '0x3a4785', - validatorIndex: '0x392', + index: '0x39f6e80', + validatorIndex: '0x19e', + address: '0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b', + amount: '0x2f9fe', }, { - address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', - amount: '0x2ef5d', - index: '0x3a4786', - validatorIndex: '0x393', + index: '0x39f6e81', + validatorIndex: '0x19f', + address: '0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b', + amount: '0x2621c', }, { - address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', - amount: '0x25915', - index: '0x3a4787', - validatorIndex: '0x394', + index: '0x39f6e82', + validatorIndex: '0x1a0', + address: '0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b', + amount: '0x24c8c', }, { - address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', - amount: '0x2ef5d', - index: '0x3a4788', - validatorIndex: '0x395', + index: '0x39f6e83', + validatorIndex: '0x1a1', + address: '0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b', + amount: '0x30bf6', }, { - address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', - amount: '0x2ef5d', - index: '0x3a4789', - validatorIndex: '0x396', + index: '0x39f6e84', + validatorIndex: '0x1a2', + address: '0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b', + amount: '0x2f9fe', }, { - address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', - amount: '0x2ef5d', - index: '0x3a478a', - validatorIndex: '0x397', + index: '0x39f6e85', + validatorIndex: '0x1a3', + address: '0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b', + amount: '0x2f9fe', }, { - address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', - amount: '0x2ef5d', - index: '0x3a478b', - validatorIndex: '0x398', + index: '0x39f6e86', + validatorIndex: '0x1a4', + address: '0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b', + amount: '0x2f9fe', }, { - address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', - amount: '0x2ef5d', - index: '0x3a478c', - validatorIndex: '0x399', + index: '0x39f6e87', + validatorIndex: '0x1a5', + address: '0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b', + amount: '0x2f9fe', }, { - address: '0xe276bc378a527a8792b353cdca5b5e53263dfb9e', - amount: '0x3112f', - index: '0x3a478d', - validatorIndex: '0x39a', + index: '0x39f6e88', + validatorIndex: '0x1a6', + address: '0x25c4a76e7d118705e7ea2e9b7d8c59930d8acd3b', + amount: '0x30bf6', }, ], - withdrawalsRoot: '0xb99e42eaca3fc1000aa8be987cf107e08030c0e9ca93dc6ea6b7df69e377f953', + withdrawalsRoot: '0xbf6f1c2839936522db766ac4af3ec3cfef01e91d71dca8917d90affe0874a7b9', }; export const sepoliaBlockData: { @@ -909,20 +1646,25 @@ export const sepoliaBlockData: { pending: 'pending', finalized: 'finalized', safe: 'safe', - blockNumber: 3229950, - blockHash: '0x241dab30227f58633e69fc4128b1c2b09699ec274cd575e39e697c1e460e5791', + blockNumber: 6790201, + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', }; export const sepoliaProof = { accountProof: [ - '0xf90211a0bd15c5367fed7268b977d52e8e7aa9f961baaeb2bffb6d90c55cbe3b23c50867a074309ab894fa7cf4e291e0a61ec8e6add0c0b7698577dba557f91858743f7440a0135795d3fa69c75454cf6cacd210209f7c225ddfeefacafa1447330e82859e87a0f542e94a9320b7d615d95378262578df550f6a80a6217bc2f503088d4bf601d3a023e652402f5a6a44da6c71c3cd4a8b6f4c4a4f9451698b789cd4a7da37bb3196a0888fae0375d4cf0fe295979f015de598f2f7fb058d846c7fcd7fa8268e81163aa0eb060a257f3eee39a4579962233ea5cb521b3a1a9386005c9dbc3c9ce6174d28a0debaae98c52e95e669ac3b8d296a21c89193097a45fd4c4a0823ca55194a8d9ba0a86b400ecc676f1804ffa3ff941dbfaa6ccebe550c20209fe0665b6af927c3fba0eb9018f4d1782ea2adb33a473f710bc7d198aa882b8b0820fbf62f043c5dde5ea024c8e4ed90f41d7bdc598eba97abe9381da68f226453c89a136861f32a5bff26a0c7ce63cdedc4d07a451006586e16da4bb3c9e5d139af517ba1d278e4533efc90a0b16abc82bf81370bef07ee95a13d6a14d2188b0d8ad0696680e0b256bb2176f8a051ffa6ed1eff6147e636b0a8c49f1da1374d99942dfd4545ba857d879de5c629a06c32f72dda0421587d7c3b084f6c13c0dd6f35521fa23ef8e2bcf2d1f194e5d6a0f6f6120a27d4e3b14126d7f23e3f4542a5bf4f491f944dc151b3163472fb322b80', - '0xf90211a038929c628a18707795bb89a867c0b7495eaf95e40df84f4c6aedf8d5478ab59ea0a31f46c866a8a2dd599078744d9555a0a48f53b3529970cba5ef63fa6c4685a9a05d562bcb524148adac94e00e9f17756c426c53cd46fc31bf1ea467acd80413dda0614e03f044983248f1b19855ac7b38d4bb6bb34767ec8a60271bb5bc0c079171a0ffdaf1a1991f7fbbbebb23767a41c22117582260745b168c06ca7a4ff013591ba0ca57a67a4c02700c3cec0656710e2ca4728965b5cdcda8307b16db08b090a2d2a0a9f60bb268e9d96708dbb484e8a4ff1da76c6686691eac2c6481bc6e324f0536a03b20d5bed13d41810838c43581ed081d9a7c9d971c3e83476952a5d2fb60016aa07df274d27362ec672894d49ad82f521c1ab2d847cb0af304b8f7b1f6712e40d2a0d3b62b154087675f4523b66aa7859b2d73a55f6857a61383b85a4aa3888b027ea0f07c097aafb7b80cebdca5e31b17df8da434b1850c3a5d451ad0750a6359b1ffa08749e3e8a244fe9192d82b86478987cdb02496d121e1964fd8d41cf2fd94998aa03e170d58c142ff03585365200af853b786e9a44d72577aedbf6683b84625aefca085dcf138627c56661db6af1c4c7e44934d7f91a5d14ae6245320120dfa2aabfaa011cc33f31468451e493e4dd011ce880d60eabd6de4e2d00e489a0c4929f2a624a0a8334a9cd0b427828c2e9dfef0ff0047d5716358e4eea8195cf5780abd36333680', - '0xf90211a004a2e57b23ac28e0e6602053a68a67e3939a4b4679c1620ce59c638b4f7c58aca00384344638ceaeec259c4f6fb1f50a1993b56f93bcc10f074de47f3fecc78a25a03336ad1d963218b80d3a7ef692e74750d732b933491f377af2c9eb10bda9cc1aa0d70c044c14fd50d526bf3606cbfdf07f23d53a89f1e236aea1441b3ccffdba4ea0014fb6658cfb3c6a2f8c73213309017bec76ede238848061b7b6c8e6d34cd2fba0a8d1dcb19a8b0c79c25bf526d558e16c064f164a1c252620867c4a986d80805ea0fdd22438d97b4a42ed0d9210be8e1b00ab09d2e745c9a74880e0ac89265ebfd8a0dbdd2ae84eab9fbb4ad6782f8194edca15149a70c136a712e147a0e6c14b6025a0691f4ccc7ea60181f9a1fbb0c50d0fb8f87855f52725d99d51761800a8e1a898a0d4a1033a557673b58c44dd5d8933e3b9e6836073b62e81c51e393891e1c08406a084bc2853de7cb71cec627953a0244eb79715bcea8f98ba20c3172a91094e087ca046b189afc77399b676156153dcffdf015c9ed1e1e2de47964324f809f05f8028a083c10c2ffaab82d1bf06fcc2c688d9b2649eb2e7f6a2bcdf421871878ffbf0f3a0a784810c6a3b134e0efdb3673415ace91355301a85e4aacadb48c1bcdbed5b6ea0e8d8ea2dc934168667b82b7d0aa5ea98ff65827ddd5e6a1c7c79260c1b3772c0a0d74896fc22af6786c882135339c29b6247d0217fe1aec73b1e977a847558924d80', - '0xf90211a08d4d210a3e60087a4eb5f36727a3a56a9311278567c97d59fc50aa74f165bd8ba0d1a18b6ad21cd0f14238879fe57b6f09d14298a5928f6379ff80fd763459a4afa07bd9f101833e378d43e09fad08ce5509780f2ec57403598abe602b2a2af45ac0a093379828ca29052df58f45cd404e8b12c01c4ca26f86f1f923806bc06e72fd84a03392ad52fafa40ecf85d8847631bf161acf3431b3731af5e98fdf874d7647d37a00167dffc916786580e139b274b8b8b80c2e1a6db831777baf2b16296c05e5a58a0b6317e14b722a02c7e195028ac66b6ccd8cbd89914933ba30835b14c2c49cb65a0c959acdf92f6c065c1225bada0ef9b2b9ce4b59fa7647ae1c27c9a850742b8c8a0b20e9ed80d852af613897b6b44280d9ecadf531a089b917279e6128b0c010baaa02561c3d2cefe9e8b61f8603c89c9b0777ec90f97c79113c4e4a39140177429eca00de6d0d0b3871224e6a253b35b7da0f1b66d31fdb3a63ffeb9ce9d319f35700ba0828996f22bc8faa91b4290e70dc0a9a3084726049fd01084f737f7e1b9b888aca05305056bd62a34b39fe0a35dda9c4ded845a7ed1851b3f3b093e5e033d0c4aada0992d0e606f03e8ae4a4a7d2e1f0eda43768a25428fb925a3dd867b8a95b8ab17a07cd265da902a8955576d3efacdf91366c96866a6a0d552708baa98ed2ba977d9a0459eed6e81c723f98973c5eb34f2864bf893f0ca0b55c5392768956b17d7d95580', - '0xf901f1a058da106a0328d4a8fa604556b7f8a2b42996771251b58868d98b4ee9940b5a26a0cfd6ba241820c3367bbb70460455a3a7c0ab28cef4a12485d33e77882699e552a03dcef268450bb0cac9677fb51477e12944c1ec8d6e7d9c44ede32daa700de2dca0e7db3fa45aabf1d311be857d8b52fe3bd6406ce219bf694535071d6e2f734a8aa03a7fd296a5c7b18b5cf0ce2d400ff96c512aa89777a00daaa50c7e64b5728195a08c18b256d1caa08d692bdcdc4da7eb597dbd77908f3c6d704dded57b39d013bba0b95e5cb7469465246e4705e216a5244c56adac2c40ec49798e6771b48d26585480a0304cfc03edfb7f777c82331d3d34b4d8c77eafc9d6ba0a4a96347ebf83be4982a05edb92ab1d3707d6aee70be0f8f9271983c86d0b2a19ca490d3eed9b0e28f732a0d28b01f8c9eba67bde4dbaeab359f156e44598fae182bae9544979880ee034b6a00063032eced2cdb17d5b507b850dc45e2cfa9bf8a032011670b60ca80a2c2991a0315eaab728c1d381befe0ea772d95b8a0884f6076ae1865e970f410640cb2efca089e4aa4ec84ee7528ffede0f3d9e3d8b06f4ff39bbb4f717c7ec380ecff6546ba05f09cd4612d3eab1988a27dd387c5c8f97722a5108090f587af73fb70f9e71d6a003d3b1eec463fc3e82704b3abbc928d0a0ea17417c38d77d8f8d71f8d631d58480', - '0xf8709e37b7ae81a58eb98d9c78de4a1fd7fd9535fc953ed2be602daaa41767312ab84ff84d80891c2f286a1800abedffa056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470', + '0xf90211a00b98281e982dbf4f35f64098fa59b32d160fa09b834f6ce5848608daafa1ebffa0af2c6f222b9040596e1a51e2d9fb7b19ddc70c3356782d99b803dcaaaf080177a06c62a0e03bacb47124a79b97167dd4cb5ff5ca6f16574c23be2b4706e0912d76a058aca18f8e6fdd6d2ab876ae88d3f64baa9fd0cb9e830244a08432a0f18c3587a0e985c82b32bc791632b73b0dd2c8a9a1acfbd9d037182d9e14232e9746cb3f50a024b92f6344ff7b2b4ba936e21ac3700befb230bc0073d4d5449c5091cfc0aa2fa0c1e988af47591f2b97ffadc8d324871cadaf74ad0e8e6d54a8b10ab70feb852da043ae3a5dea07ecf8292b2ecada290264fc87bb464e00fd7561000f74c5ad9264a0aeaf42a47a676f10589ac23f0408e815d9aeb14351c5b62b92357e0457e94841a03b4e576476ae07490a087cfc5950c9e3f51c41c5118d41835f11725448aa1999a058fed18bac3f9bdfd232c3c3f2cbad7022a8d7795bd48477d59fcc7f0c3eb119a010a50f5188ebdf6937e7a89c46a3d02cc021cf30244b5e139c249faf79dad9b3a03da530501ff9ba1e456b530de50a071ec5c807f3ee9729defaff7377310c390ba0058654d6276a120fefe0ddd9410ee4eec6d31f2502ff93a1c62e6b4acc28d061a0ed7692ad8eb8c7931a8ff38fef248834f70ec377e751f64737b95d85b3fda3a1a0bb957747b1a7c70f3d7be2a468458a67f06ecb73fb860fd604b024679361af5d80', + '0xf90211a07eedc8f44e8f36c2758895f2698f5c3d7ee1f73964cdca698389c139453c2bc5a0bbff85d878cc6f06ad69167e4bada2d2a9c477436ac836635b3124bbe4c56947a0eb02de8781021d7822bbb846083679d8a5c3c440321a2765294a96911805bdaaa033b689ce91d960811e4e87a7c004e5bf18e7de4a6601c454ea81286d888a3e5da04f0620d05eaa36c9c828bdaf920557fbabfcce748d4a1cc9999b450d547f0c30a0e2d8a8920b45fd2691e8721307ef996716be32512cd0f34b1126fef7c1ae4d50a0067ca53adf608ad5b9806914e281ae8492b8629fd92d58d149f391dd0ed4452ea039e91f18fabc996ed1efcd57561653e4480c4f6efbe253e43c19058fc3b02469a015507fb46fcab1dd7c6f09663213b1956dc688654bf4b4fc6e4e4f7c4d7601dea03ed0565ba5283066a570e26f78776b8788dd2d296729594452fc27fd84c70325a084153237be8ac05a4b1c4325a972673cf4e33588df66bab7da92174ba2ea6f6da01d10f5a1db59f5d78f2eca25ac50f66d64209e195711ac986c94beb20e6a5bf3a0583ae3af19fa2d82251f3c060a182d9585e28073af197d8e0f140b9c69d87dcfa07b39d4eae1ed4d820353b125f8477f5c9eec2948638b997bfa9556badfd470e2a0f5f71a7da0b7279eba22ab49309053bc8460df1dc08413c92f44a609a263b5f2a0073d41c5824d39280e35bc3d5b8a4fe51202969029f6f98c5cb1da93714c616680', + '0xf90211a026f5d52f01cca28a6c9bf79245b7c736fb8bf9487b76885bde71f3b5bdc5577ea0590edd827bb04fc5844d9a6928c880b09968ad0afcc8a8f93a43e0a0633d15b6a0908f2419d84350653fb434d29139402beaf4c9ef9bac9bfe78bd250b0af5249ea04f8ef9fcd939ce4bd6b51326037f69f20cb640f1f234c0be96371712a19df807a082531522eee295e34cc6174e5f8e20ca286b1b39ede5612b1ab4674cd9fc9594a05fdcd0e5707c7b10b00e1707dad6e5e434efa67f1b705c049b772ce579b94648a0fee8d304f63529a64fde867b91882dd38f839a9f2de2f02b7adcaf032171a528a070eeec9d7b2a3c191dc9b1e20f5c0a72b4821e659858a9feda3f6e53d02ade5fa01810acb5fd851a1fe484f7b2b7b1d702016f8e2549f0a9a2c3fd3d4018d79376a0c301075635332d7677010ef6dc65c24fd9c5a70b569a58fef24bc43c7bd5e91ba0aed9cadd453bf3976afe1f59fa4ead25d16c18303776ea58fa8d413bc3bb69c7a055c35cf9ebe2f60bf1b1a0fc130fe9626877535abc633c8e5c80b8d9b9803426a0e0bbd931329306c815d0d3c05c215b3f51f0bd8dd0355933eb8c9fe2e95ceb8ca076de3bfbfcbf5cc6228145f2ad18ec8ab9814b3817c5e05b0c290a4463c24d28a001afba4668b1a254346b1bb65ff7367e25de630963c34c21b04be566df8cf6b7a03ebad37b10ac46307f5b029660cf609a64352d46f18b71b9034a75730e85d06d80', + '0xf90211a01ebc5c5277e4457ef5df5b09472d633e0439ab6cb6eab5aaf648a71d3357379da0e363c20dc0d6b06a384c2fc99f00552d43eee0e21608aa43cb2237a9a9597b41a0ebfbf8699eca825871087a3f382eddcfc4f60b81a525082cb07decb6d93450e5a05e8c6c1c186373405d185bae332925882b943f7a61198e5e7c6d5aa3fd8c466ca0617d9f3a99e3a90d88e39f402c364af1473b65e5272d7acd01c24490c9c321b7a00f252ae40b7020eb505da91efef6475ef7979039104616898cc318fca32fd9f6a0d861952ea274fd8bf8aa8daf2f69cc40c4e43f36358a937e971aa5d63419e856a0c44a9e89b6db77ae5ff61775188f9c6dcda4535ed0902c5f978139873497e6e3a025db21f513c7c16e9d14ee16bb3b1131f2303e20ec0c04e45028cf28687aa99aa031f5b22510266807e14a604322f73f34f98b2b571092069d922a71ea3b6d08d7a03f670def51687b8005d0da7b9456ecf1f2e3cc8d628e4bfee64d028e108d9a92a02aacdd23795598d59e680f9346236a762e201feba25952ec394c75e5e427b183a0d82a8194e4f47e69f13523c0e0e50db779c9baa4cbe292fd306fe9d14481d4fda026321fc93cc02a4294ba384edb3f228fc96e0c22b6c0c70956ee537db6ae298ba06d602ab5f5ea1fd31c59f22624b479ad14b7246fc1bb47377de8206ee1e3b80fa0facbd76174ec13e27b6e91b75e201b32430b4df641ce3b444376da8e31b1a1b580', + '0xf90211a09fa4608df106a90187f91deb3c45dceaba4dba31c5f19ca6adbc7f9cadbd7f05a0883ef2dc42dbbb9270fff804ee4e73d431cf11e9a199f575c7edb90889eecbeaa026fceebc3f21b3f98ac205dbba318002ccca0c9fc60325321731e5f822ead6b1a03778dd4d2e0f42fbf341ea3df13a4f418654069dc8291b25b30b1ecd011dc2c8a0f3589003541bc046a5b4871fdadb73f71371346db7b3134ac0c18bf43de2adf2a01acc396f1f86ee8d2bd18caa3016066c7be327387cafa56cf9d157ac093807a6a00385f0ce069a45aae9112455e5127a12e14168135c3523c5dbf470bfa9faa264a02e20c06443267a6fc22e4a5705dfd2068fdc5791f7518453b1682ed6fa4cf64da00eacb6593fc5aa144e8436e111ced2de28a45b138085221fec6c98a95ff7976fa0935c61529e524808aee291bc2298ee8b58167166c6de2882c1b4196fe1d6b08aa00dd3d056c7ac50fd3181046bea18f80b27d399b31621fd3ddb9e4741586af7aea07a7545c9bcf0f9710f65641eccb3a113e5aac0630864b93fe9019e51e15f41baa0f2b3d31cd176d0b10108febbab33230401f9e135f2882604192f8e3cbec09c81a029d83804ec362961e669d44e12ca68b55f4acd7f768f36cd7483140e2ee9e18ea0aae15771d92cc02da2d2e88d4607f14213b8af2ebd2b8d64bfdd0b259ecaa8aba0cca8e9e9717cbfbbe6ce580d12f25bdba1c8e090807d128c9513112c8e67b77780', + '0xf901f1a00604d6f7d7bad1c73872796360c75e84bb9a33af5a7ee731358e4922bb82b79fa083db0f00db4e9c3f10a74475b9b38449a08b3d6c943964d845815e896028d7cda09c9e745cedb5bc847c25a6b6fe2a4a221f4d4463bc39a2c0e1008d1615c2553da0ca5e5054ae0ff29b7791ffd3c3b8e692ca163c307a0c144f9521ad00f151c2dca0a93b3514bf7e10c90682475c99df893735620b6edec9107f6885daa4aff43881a01d20130117d040a978eda747a2de40c318d2e4c42aeeffd7fec513b130f71f2da0c56a8992c8b3340907bbb91e96192c30dd793506e8c3185d516bd4e11d12c174a0b54e93d93c00dcf2fb65eff86b5a5a3ebbbb0c4c4d750b95d57d245ccd268941a0a021d7b79f5f10445e682c18ef818cbee327fb2ed76bffd593226f3693be117fa0c85d8fa58f5d90c85de511b7a27858614fbbd3831dd06c1c78d8bf83fc86f0f0a061ee1b45a5cf4292a66bd028d68da1559b664f5beabc4e823509b4f70cd5fb6ba02f0dc0c919e9d75870ca213d88550ca899d9d3c5dd63e58c131280bfe657fa68a0ef2121de75ee5ba388d46da9043d704ce7f74b39ba74b4e4df6c854e9486c3aaa0467e412e77ffb9870716b914050a9084d4a8cba5d0ace46f20db8fcae681811a80a06417462ce90c8407f0fbf5ec2568750dd5fc2fec27160c28d1a82eaa0d43ce9180', + '0xf87180808080808080808080a054c782365886dd5f2712191e37bd03069d8c025b7f3d1acc58f76b9320d45194a07c5f9dbffee1dc71d4e31d66b04f672fd08ab89c22e8b2beea2fe97fc9bf99b78080a04b5811db567cdb0f9fa196de8d04833e150b766d10a03602ea3dff15036f57998080', + '0xf85180808080808080a010e135799922d6a2b191ad416e8cd7becaae37f77595ce92c45d8bb096db2785a094559a53ce7e36d9a26caa7a72d0f6e9f9554ac46179e4f1b99de0bc81dad18f8080808080808080', + '0xf851a0373fb608ed0f5df13386f02dd867f841be1fd9572b9fbb924cdc9b53da0457cb808080808080808080a092332a69deacd9e9951ed8a0315e852eb048e13b87c71bbb1b91b063b90f00db808080808080', + '0xf8518080808080808080808080808080a0bd05344d57adc70b42f9ff262b8cced5b0e19ca088cc5d1c97c2b72e8d7903a3a017d3b9ff99c67bfd58fae896f90da846a4b445f5117020649bd117aef1a31bce80', + '0xf86f9c2081a58eb98d9c78de4a1fd7fd9535fc953ed2be602daaa41767312ab850f84e808a18c112e4b5bea4ce9af8a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470', ], - balance: BigInt('519906916634041511423'), + balance: BigInt('116898378607915214740216'), codeHash: '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470', nonce: BigInt(0), storageHash: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421', @@ -930,21 +1672,21 @@ export const sepoliaProof = { }; export const sepoliaTransactionFromBlock = { - blockHash: '0x241dab30227f58633e69fc4128b1c2b09699ec274cd575e39e697c1e460e5791', - blockNumber: BigInt(3229950), - chainId: BigInt(11155111), - from: '0xf0046e53d11c6e7a6badb4c9e849fcc26509dc16', - gas: BigInt(63000), - gasPrice: BigInt(3000000027), - hash: '0xa8a6e1f58adfe40a059e037c6c2b6e07bd23aa3d32d892bfcc6f40d85f22c907', - input: '0x', - nonce: BigInt(6714), - r: '0xa0f6ce97f49e3bd2e539430890ef4dddf2f3b1c4713b374234ed6ebceb80604b', - s: '0x33712ef7984df3ca434d854724b2b1d5be58012ccb39bd5f3a8b729a0c4d7931', - to: '0x83f3229e66fd1997961f76cbfb6e077f66ae1962', + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: BigInt(6790201), + from: '0xaa88878d91bc1a7b7f71c592349efc44b5f3b77d', + gas: BigInt(73225), + gasPrice: BigInt(344362611607), + hash: '0xcf811d80757452f648f74bea7cdee088c5c2addafd8d049f644fc8cafee7a50d', + input: '0x95b335c84d053fdf52290285953409c8d9abdacc0000000066fb1966037903179f000000000000000000000000000000000000000000000000000000000000000007a13b0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000423078653030353565656530616135303532306162306162343132663535303666396635656664653663633561326565633231643031613063326266346638396261310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000299c007f9c00000000000000000000000000000000000000000000000000000000000000003e80000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001a3078313a3a6170746f735f636f696e3a3a4170746f73436f696e000000000000', + nonce: BigInt(2), + to: '0xd600d94d0812f7edfa47d0cf02a767b1dd14a01b', transactionIndex: BigInt(1), + value: BigInt(732000000000000), type: BigInt(0), - v: BigInt(22310258), - value: BigInt('1000000000000000000'), - data: '0x', + chainId: BigInt(11155111), + v: BigInt(22310257), + r: '0x1cf2c321ee1a4331dee4f9243fc1a73aa23b49929d0f5e475b27685c303fc4b1', + s: '0x009d5ffea271ec91f967e2993ff83c2576c63e83604ca8934768ede951ed1c5a', + data: '0x95b335c84d053fdf52290285953409c8d9abdacc0000000066fb1966037903179f000000000000000000000000000000000000000000000000000000000000000007a13b0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000423078653030353565656530616135303532306162306162343132663535303666396635656664653663633561326565633231643031613063326266346638396261310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000299c007f9c00000000000000000000000000000000000000000000000000000000000000003e80000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001a3078313a3a6170746f735f636f696e3a3a4170746f73436f696e000000000000', }; diff --git a/packages/web3/test/e2e/get_balance.test.ts b/packages/web3/test/e2e/get_balance.test.ts index e07f79b83fe..f79f67093e7 100644 --- a/packages/web3/test/e2e/get_balance.test.ts +++ b/packages/web3/test/e2e/get_balance.test.ts @@ -32,13 +32,13 @@ describe(`${getSystemTestBackend()} tests - getBalance`, () => { const provider = getSystemE2ETestProvider(); const blockData = getSystemTestBackend() === BACKEND.SEPOLIA ? sepoliaBlockData : mainnetBlockData; - const expectedBalance = - getSystemTestBackend() === BACKEND.SEPOLIA ? '172530374997217200' : '2099795781954790368'; + let expectedBalance = BigInt(0); let web3: Web3; - beforeAll(() => { + beforeAll(async () => { web3 = new Web3(provider); + expectedBalance = await web3.eth.getBalance(getE2ETestAccountAddress()); }); afterAll(async () => { @@ -69,7 +69,18 @@ describe(`${getSystemTestBackend()} tests - getBalance`, () => { format: [FMT_NUMBER.BIGINT, FMT_NUMBER.HEX, FMT_NUMBER.STR], }), )('getBalance', async ({ block, format }) => { - const result = await web3.eth.getBalance(getE2ETestAccountAddress(), blockData[block], { + let blockOrTag = blockData[block]; + if (block === 'blockHash' || block === 'blockNumber') { + /** + * @NOTE Getting a block too far back in history + * results in a missing trie node error, so + * we get latest block for this test + */ + const b = await web3.eth.getBlock('finalized'); + blockOrTag = block === 'blockHash' ? String(b.hash) : Number(b.number); + } + + const result = await web3.eth.getBalance(getE2ETestAccountAddress(), blockOrTag, { number: format as FMT_NUMBER, bytes: FMT_BYTES.HEX, }); @@ -83,15 +94,15 @@ describe(`${getSystemTestBackend()} tests - getBalance`, () => { * converted to a BigInt */ // eslint-disable-next-line jest/no-conditional-expect - expect(result).toBe(toHex(BigInt(expectedBalance))); + expect(result).toBe(toHex(expectedBalance)); break; case 'NUMBER_STR': // eslint-disable-next-line jest/no-conditional-expect - expect(result).toBe(expectedBalance); + expect(result).toBe(expectedBalance.toString()); break; case 'NUMBER_BIGINT': // eslint-disable-next-line jest/no-conditional-expect - expect(result).toBe(BigInt(expectedBalance)); + expect(result).toBe(expectedBalance); break; default: throw new Error('Unhandled format'); diff --git a/packages/web3/test/e2e/get_block_transaction_count.test.ts b/packages/web3/test/e2e/get_block_transaction_count.test.ts index 0dea0eb16f7..554ce9dd71b 100644 --- a/packages/web3/test/e2e/get_block_transaction_count.test.ts +++ b/packages/web3/test/e2e/get_block_transaction_count.test.ts @@ -68,33 +68,46 @@ describe(`${getSystemTestBackend()} tests - getBlockTransactionCount`, () => { )('getBlockTransactionCount', async ({ block, format }) => { let _blockData = blockData[block]; if (block === 'blockHash' || block === 'blockNumber') { + /** + * @NOTE Getting a block too far back in history + * results in a missing trie node error, so + * we get latest block for this test + */ const latestBlock = await web3.eth.getBlock('finalized'); _blockData = block === 'blockHash' ? (latestBlock.hash as string) : Number(latestBlock.number); } + const result = await web3.eth.getBlockTransactionCount(_blockData, { number: format as FMT_NUMBER, bytes: FMT_BYTES.HEX, }); - switch (format) { - case 'NUMBER_NUMBER': - // eslint-disable-next-line jest/no-conditional-expect - expect(isNumber(result)).toBeTruthy(); - break; - case 'NUMBER_HEX': - // eslint-disable-next-line jest/no-conditional-expect - expect(isHexStrict(result)).toBeTruthy(); - break; - case 'NUMBER_STR': - // eslint-disable-next-line jest/no-conditional-expect - expect(isString(result)).toBeTruthy(); - break; - case 'NUMBER_BIGINT': - // eslint-disable-next-line jest/no-conditional-expect - expect(isBigInt(result)).toBeTruthy(); - break; - default: - throw new Error('Unhandled format'); + if (block === 'pending') { + // eslint-disable-next-line no-null/no-null + const expectedResult = result === null || Number(result) > 0; + // eslint-disable-next-line jest/no-conditional-expect + expect(expectedResult).toBeTruthy(); + } else { + switch (format) { + case 'NUMBER_NUMBER': + // eslint-disable-next-line jest/no-conditional-expect + expect(isNumber(result)).toBeTruthy(); + break; + case 'NUMBER_HEX': + // eslint-disable-next-line jest/no-conditional-expect + expect(isHexStrict(result)).toBeTruthy(); + break; + case 'NUMBER_STR': + // eslint-disable-next-line jest/no-conditional-expect + expect(isString(result)).toBeTruthy(); + break; + case 'NUMBER_BIGINT': + // eslint-disable-next-line jest/no-conditional-expect + expect(isBigInt(result)).toBeTruthy(); + break; + default: + throw new Error('Unhandled format'); + } } }); }); diff --git a/packages/web3/test/e2e/get_block_uncle_count.test.ts b/packages/web3/test/e2e/get_block_uncle_count.test.ts index c06f57aec85..fd209faaacf 100644 --- a/packages/web3/test/e2e/get_block_uncle_count.test.ts +++ b/packages/web3/test/e2e/get_block_uncle_count.test.ts @@ -14,7 +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 Web3 from '../../src'; +import { Web3 } from '../../src'; import { getSystemE2ETestProvider } from './e2e_utils'; import { closeOpenConnection, @@ -74,8 +74,8 @@ describeIf(getSystemTestBackend() !== 'hardhat')( : Number(latestBlock.number); } const result = await web3.eth.getBlockUncleCount(_blockData); - - expect(result).toBe(BigInt(0)); + // eslint-disable-next-line no-null/no-null + expect(result).toBe(block === 'pending' || block === 'earliest' ? null : BigInt(0)); }); }, ); diff --git a/packages/web3/test/e2e/get_fee_history.test.ts b/packages/web3/test/e2e/get_fee_history.test.ts index 9097b310e90..0a10d49bebd 100644 --- a/packages/web3/test/e2e/get_fee_history.test.ts +++ b/packages/web3/test/e2e/get_fee_history.test.ts @@ -62,7 +62,7 @@ describe(`${getSystemTestBackend()} tests - estimateGas`, () => { format: string; }>({ blockCount: [1, '2', 3, BigInt(4)], - newestBlock: ['earliest', 'latest', 'pending', 'safe', 'finalized', 'blockNumber'], + newestBlock: ['earliest', 'latest', 'safe', 'finalized', 'blockNumber'], rewardPercentiles: [['0xa', '20', 30, BigInt(40)]], format: Object.values(FMT_NUMBER), }), diff --git a/packages/web3/test/e2e/get_proof.test.ts b/packages/web3/test/e2e/get_proof.test.ts index a9a449c28eb..059f210d2bc 100644 --- a/packages/web3/test/e2e/get_proof.test.ts +++ b/packages/web3/test/e2e/get_proof.test.ts @@ -55,13 +55,13 @@ describe(`${getSystemTestBackend()} tests - getProof`, () => { | 'blockNumber'; }>({ block: [ - // 'earliest', block is earlier than 128 blocks ago "Returned error: missing trie node" + // 'earliest', // error "distance to target block exceeds maximum proof window" 'latest', - // 'pending', block is not available "Returned error: missing trie node" + // 'pending', // error "unknown block number" 'safe', 'finalized', - 'blockHash', - 'blockNumber', + // 'blockHash', // error "distance to target block exceeds maximum proof window" + // 'blockNumber', // error "distance to target block exceeds maximum proof window" ], }), )('getProof', async ({ block }) => { diff --git a/packages/web3/test/e2e/get_transaction_count.test.ts b/packages/web3/test/e2e/get_transaction_count.test.ts index 89017756181..00ce422b935 100644 --- a/packages/web3/test/e2e/get_transaction_count.test.ts +++ b/packages/web3/test/e2e/get_transaction_count.test.ts @@ -62,14 +62,22 @@ describe(`${getSystemTestBackend()} tests - getTransactionCount`, () => { ], }), )('getTransactionCount', async ({ block }) => { - const result = await web3.eth.getTransactionCount( - getE2ETestAccountAddress(), - blockData[block], - ); + let blockOrTag = blockData[block]; + if (block === 'blockHash' || block === 'blockNumber') { + /** + * @NOTE Getting a block too far back in history + * results in a missing trie node error, so + * we get latest block for this test + */ + const b = await web3.eth.getBlock('finalized'); + blockOrTag = block === 'blockHash' ? String(b.hash) : Number(b.number); + } + + const result = await web3.eth.getTransactionCount(getE2ETestAccountAddress(), blockOrTag); if (block === 'blockHash' || block === 'blockNumber') { const expectedTxCount = - getSystemTestBackend() === BACKEND.SEPOLIA ? BigInt(1) : BigInt(11); + getSystemTestBackend() === BACKEND.SEPOLIA ? BigInt(47) : BigInt(40); // eslint-disable-next-line jest/no-conditional-expect expect(result).toBe(expectedTxCount); } else { diff --git a/packages/web3/test/e2e/mainnet/get_storage_at.test.ts b/packages/web3/test/e2e/mainnet/get_storage_at.test.ts index 9839a6db75f..f70b23cc0d8 100644 --- a/packages/web3/test/e2e/mainnet/get_storage_at.test.ts +++ b/packages/web3/test/e2e/mainnet/get_storage_at.test.ts @@ -39,9 +39,10 @@ describe(`${getSystemTestBackend()} tests - getStorageAt`, () => { it.each( toAllVariants<{ storageSlot: Numbers; - block: // | 'earliest' - | 'latest' - // | 'pending' + block: + | 'earliest' + | 'latest' + | 'pending' | 'finalized' | 'safe' | 'blockHash' @@ -61,10 +62,15 @@ describe(`${getSystemTestBackend()} tests - getStorageAt`, () => { )('getStorageAt', async ({ storageSlot, block }) => { let blockData = mainnetBlockData[block]; if (block === 'blockHash' || block === 'blockNumber') { - const blockNumber = await web3.eth.getBlockNumber(); - blockData = Number(blockNumber); + /** + * @NOTE Getting a block too far back in history + * results in a missing trie node error, so + * we get latest block for this test + */ + const b = await web3.eth.getBlock('finalized'); + blockData = Number(b.number); if (block === 'blockHash') { - blockData = (await web3.eth.getBlock(blockNumber)).hash as string; + blockData = b.hash as string; } } const result = await web3.eth.getStorageAt( @@ -79,7 +85,7 @@ describe(`${getSystemTestBackend()} tests - getStorageAt`, () => { } else if (block === 'blockHash' || block === 'blockNumber') { // eslint-disable-next-line jest/no-conditional-expect expect(result).toBe( - '0x00000000000000000000000000000000000000000000000000c354b137cba7ba', + '0x00000000000000000000000000000000000000000000000000c347d66ae6ce59', ); } else { // eslint-disable-next-line jest/no-conditional-expect diff --git a/packages/web3/test/e2e/mainnet/get_transaction.test.ts b/packages/web3/test/e2e/mainnet/get_transaction.test.ts index 294ddb00219..c8e0aedc070 100644 --- a/packages/web3/test/e2e/mainnet/get_transaction.test.ts +++ b/packages/web3/test/e2e/mainnet/get_transaction.test.ts @@ -43,15 +43,15 @@ describe(`${getSystemTestBackend()} tests - getTransaction`, () => { transactionHash: Bytes; }>({ transactionHash: [ - '0x9a968248400868beb931ed96ee37517275794ff44e8d968c29f0f3430a504594', + '0x79fd3cd0c84acfbb1b9c8f2ab33517626eceb8cb42c21f1c21439ce36e0e6cab', bytesToUint8Array( hexToBytes( - '0x9a968248400868beb931ed96ee37517275794ff44e8d968c29f0f3430a504594', + '0x79fd3cd0c84acfbb1b9c8f2ab33517626eceb8cb42c21f1c21439ce36e0e6cab', ), ), new Uint8Array( hexToBytes( - '0x9a968248400868beb931ed96ee37517275794ff44e8d968c29f0f3430a504594', + '0x79fd3cd0c84acfbb1b9c8f2ab33517626eceb8cb42c21f1c21439ce36e0e6cab', ), ), ], @@ -60,29 +60,26 @@ describe(`${getSystemTestBackend()} tests - getTransaction`, () => { const result = await web3.eth.getTransaction(transactionHash); expect(result).toMatchObject({ - hash: '0x9a968248400868beb931ed96ee37517275794ff44e8d968c29f0f3430a504594', - nonce: BigInt(2264), - blockHash: '0xabc81c29235c7962f5a0420644761627bdc064a560c7d1842cdf9517f7d7984e', - blockNumber: BigInt(17030310), - transactionIndex: BigInt(91), - from: '0xd67da12dc33d9730d9341bbfa4f0b67d0688b28b', - gasPrice: BigInt(19330338402), - maxPriorityFeePerGas: BigInt(100000000), - maxFeePerGas: BigInt(26848942133), - gas: BigInt(300858), - input: '0x6d78f47a000000000000000000000000a6e265667e1e18c28f2b5dc529f775c5f0d56d4a000000000000000000000000000000000000000000000001a055690d9db80000000000000000000000000000d67da12dc33d9730d9341bbfa4f0b67d0688b28b', + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: BigInt(20866453), + from: '0xbbff54095b09940a4046e21ed5053f1ea2a1c581', + gas: BigInt(320260), + gasPrice: BigInt(11058949155), + maxFeePerGas: BigInt(13199607524), + maxPriorityFeePerGas: BigInt(3000000000), + hash: '0x79fd3cd0c84acfbb1b9c8f2ab33517626eceb8cb42c21f1c21439ce36e0e6cab', + input: '0x3d0e3ec50000000000000000000000000000000000000000000000001a33261efb6495ca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000bbff54095b09940a4046e21ed5053f1ea2a1c5810000000000000000000000000000000000000000000000000000000066fb25a80000000000000000000000005c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000b9612ce2807de435a562b40a5ba9200ab86065e1000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', + nonce: BigInt(985), + to: '0x80a64c6d7f12c47b7c66c5b4e20e72bc1fcd5d9e', + transactionIndex: BigInt(6), + value: BigInt(0), + type: BigInt(2), + accessList: [], chainId: BigInt(1), - type: BigInt('0x2'), - v: BigInt('0x0'), - s: '0x72ca073bc16b35b3191b35fd8fb0eebdd536675ecb8459b110fcad2890a98ec9', - r: '0x45496fc11c7bf9972cb732bdc579f5d9d01e4df276dd49626e75fc3b5f8b6ec4', - // TODO These values are included when fetching the transaction from - // Nethermind, but not Infura - // https://github.com/web3/web3.js/issues/5997 - // data: '0x608060405234801561001057600080fd5b5033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f342827c97908e5e2f71151c08502a66d44b6f758e3ac2f1de95f02eb95f0a73560405160405180910390a36104dc806100de6000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632e64cec1146100515780636057361d1461006f578063893d20e81461008b578063a6f9dae1146100a9575b600080fd5b6100596100c5565b60405161006691906102fb565b60405180910390f35b61008960048036038101906100849190610347565b6100ce565b005b610093610168565b6040516100a091906103b5565b60405180910390f35b6100c360048036038101906100be91906103fc565b610192565b005b60008054905090565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461015e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161015590610486565b60405180910390fd5b8060008190555050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610222576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161021990610486565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f342827c97908e5e2f71151c08502a66d44b6f758e3ac2f1de95f02eb95f0a73560405160405180910390a380600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000819050919050565b6102f5816102e2565b82525050565b600060208201905061031060008301846102ec565b92915050565b600080fd5b610324816102e2565b811461032f57600080fd5b50565b6000813590506103418161031b565b92915050565b60006020828403121561035d5761035c610316565b5b600061036b84828501610332565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061039f82610374565b9050919050565b6103af81610394565b82525050565b60006020820190506103ca60008301846103a6565b92915050565b6103d981610394565b81146103e457600080fd5b50565b6000813590506103f6816103d0565b92915050565b60006020828403121561041257610411610316565b5b6000610420848285016103e7565b91505092915050565b600082825260208201905092915050565b7f43616c6c6572206973206e6f74206f776e657200000000000000000000000000600082015250565b6000610470601383610429565b915061047b8261043a565b602082019050919050565b6000602082019050818103600083015261049f81610463565b905091905056fea26469706673582212201fcfa803d5c15c78e1e356cc1946c1bf14f9809acd349df1fd41362fa1a9e4d564736f6c63430008120033', - // to: null, - // value: '0x0', - // yParity: '0x0' + v: BigInt(1), + r: '0xac126c6ad95a7a8970ce4ca34d61a3a2245e8d7f11bde871dd66ac43435405c6', + s: '0x1beeda8ed32586243281807ee42d8e524d5050bd7f224f62e5dce812472ecee5', + data: '0x3d0e3ec50000000000000000000000000000000000000000000000001a33261efb6495ca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000bbff54095b09940a4046e21ed5053f1ea2a1c5810000000000000000000000000000000000000000000000000000000066fb25a80000000000000000000000005c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000b9612ce2807de435a562b40a5ba9200ab86065e1000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', }); }); }); diff --git a/packages/web3/test/e2e/mainnet/get_transaction_receipt.test.ts b/packages/web3/test/e2e/mainnet/get_transaction_receipt.test.ts index 7c1ad00fcbb..90215cea6af 100644 --- a/packages/web3/test/e2e/mainnet/get_transaction_receipt.test.ts +++ b/packages/web3/test/e2e/mainnet/get_transaction_receipt.test.ts @@ -18,7 +18,7 @@ import { Bytes } from 'web3-types'; import { bytesToUint8Array, hexToBytes } from 'web3-utils'; import Web3 from '../../../src'; -import { getSystemE2ETestProvider, getE2ETestContractAddress } from '../e2e_utils'; +import { getSystemE2ETestProvider } from '../e2e_utils'; import { closeOpenConnection, getSystemTestBackend, @@ -43,15 +43,15 @@ describe(`${getSystemTestBackend()} tests - getTransactionReceipt`, () => { transactionHash: Bytes; }>({ transactionHash: [ - '0x9a968248400868beb931ed96ee37517275794ff44e8d968c29f0f3430a504594', + '0x79fd3cd0c84acfbb1b9c8f2ab33517626eceb8cb42c21f1c21439ce36e0e6cab', bytesToUint8Array( hexToBytes( - '0x9a968248400868beb931ed96ee37517275794ff44e8d968c29f0f3430a504594', + '0x79fd3cd0c84acfbb1b9c8f2ab33517626eceb8cb42c21f1c21439ce36e0e6cab', ), ), new Uint8Array( hexToBytes( - '0x9a968248400868beb931ed96ee37517275794ff44e8d968c29f0f3430a504594', + '0x79fd3cd0c84acfbb1b9c8f2ab33517626eceb8cb42c21f1c21439ce36e0e6cab', ), ), ], @@ -60,115 +60,111 @@ describe(`${getSystemTestBackend()} tests - getTransactionReceipt`, () => { const result = await web3.eth.getTransactionReceipt(transactionHash); expect(result).toMatchObject({ - blockHash: '0xabc81c29235c7962f5a0420644761627bdc064a560c7d1842cdf9517f7d7984e', - blockNumber: BigInt(17030310), - // contractAddress: '0xedfd52255571b4a9a9d4445989e39f5c14ff0447', - cumulativeGasUsed: BigInt(9010200), - effectiveGasPrice: BigInt(19330338402), - from: '0xd67da12dc33d9730d9341bbfa4f0b67d0688b28b', - gasUsed: BigInt(245737), + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + blockNumber: BigInt(20866453), + cumulativeGasUsed: BigInt(1119067), + effectiveGasPrice: BigInt(11058949155), + from: '0xbbff54095b09940a4046e21ed5053f1ea2a1c581', + gasUsed: BigInt(145229), logs: [ { - address: '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599', - blockHash: '0xabc81c29235c7962f5a0420644761627bdc064a560c7d1842cdf9517f7d7984e', - blockNumber: BigInt(17030310), - data: '0x0000000000000000000000000000000000000000000000000000000000668442', - logIndex: BigInt(200), - removed: false, + address: '0xb9612ce2807de435a562b40a5ba9200ab86065e1', topics: [ '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', - '0x000000000000000000000000d67da12dc33d9730d9341bbfa4f0b67d0688b28b', - '0x000000000000000000000000a6e265667e1e18c28f2b5dc529f775c5f0d56d4a', + '0x000000000000000000000000bbff54095b09940a4046e21ed5053f1ea2a1c581', + '0x000000000000000000000000226b6b07e508bda9dffe13866f807346faf94627', ], + data: '0x0000000000000000000000000000000000000000000000001a33261efb6495ca', + blockNumber: BigInt(20866453), transactionHash: - '0x9a968248400868beb931ed96ee37517275794ff44e8d968c29f0f3430a504594', - transactionIndex: BigInt(91), - }, - { - address: getE2ETestContractAddress(), - blockHash: '0xabc81c29235c7962f5a0420644761627bdc064a560c7d1842cdf9517f7d7984e', - blockNumber: BigInt(17030310), - data: '0x0000000000000000000000000000000000000000000000000000000000015bb2', - logIndex: BigInt(201), + '0x79fd3cd0c84acfbb1b9c8f2ab33517626eceb8cb42c21f1c21439ce36e0e6cab', + transactionIndex: BigInt(6), + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + logIndex: BigInt(30), removed: false, - topics: [ - '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', - '0x000000000000000000000000d67da12dc33d9730d9341bbfa4f0b67d0688b28b', - '0x000000000000000000000000a6e265667e1e18c28f2b5dc529f775c5f0d56d4a', - ], - transactionHash: - '0x9a968248400868beb931ed96ee37517275794ff44e8d968c29f0f3430a504594', - transactionIndex: BigInt(91), }, { - address: '0x5de8ab7e27f6e7a1fff3e5b337584aa43961beef', - blockHash: '0xabc81c29235c7962f5a0420644761627bdc064a560c7d1842cdf9517f7d7984e', - blockNumber: BigInt(17030310), - data: '0x00000000000000000000000000000000000000003fff92b9d57d1d7fca09d7dc', - logIndex: BigInt(202), - removed: false, + address: '0xb9612ce2807de435a562b40a5ba9200ab86065e1', topics: [ '0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925', - '0x000000000000000000000000d67da12dc33d9730d9341bbfa4f0b67d0688b28b', - '0x00000000000000000000000069a592d2129415a4a1d1b1e309c17051b7f28d57', + '0x000000000000000000000000bbff54095b09940a4046e21ed5053f1ea2a1c581', + '0x00000000000000000000000080a64c6d7f12c47b7c66c5b4e20e72bc1fcd5d9e', ], + data: '0xffffffffffffffffffffffffffffffffffffffffffffffffe5ccd9e1049b6a35', + blockNumber: BigInt(20866453), transactionHash: - '0x9a968248400868beb931ed96ee37517275794ff44e8d968c29f0f3430a504594', - transactionIndex: BigInt(91), + '0x79fd3cd0c84acfbb1b9c8f2ab33517626eceb8cb42c21f1c21439ce36e0e6cab', + transactionIndex: BigInt(6), + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + logIndex: BigInt(31), + removed: false, }, { - address: '0x5de8ab7e27f6e7a1fff3e5b337584aa43961beef', - blockHash: '0xabc81c29235c7962f5a0420644761627bdc064a560c7d1842cdf9517f7d7984e', - blockNumber: BigInt(17030310), - data: '0x000000000000000000000000000000000000000000006d462a82e28035f62824', - logIndex: BigInt(203), - removed: false, + address: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', topics: [ '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', - '0x000000000000000000000000d67da12dc33d9730d9341bbfa4f0b67d0688b28b', - '0x000000000000000000000000a6e265667e1e18c28f2b5dc529f775c5f0d56d4a', + '0x000000000000000000000000226b6b07e508bda9dffe13866f807346faf94627', + '0x00000000000000000000000080a64c6d7f12c47b7c66c5b4e20e72bc1fcd5d9e', ], + data: '0x00000000000000000000000000000000000000000000000013d4b60de784bded', + blockNumber: BigInt(20866453), transactionHash: - '0x9a968248400868beb931ed96ee37517275794ff44e8d968c29f0f3430a504594', - transactionIndex: BigInt(91), + '0x79fd3cd0c84acfbb1b9c8f2ab33517626eceb8cb42c21f1c21439ce36e0e6cab', + transactionIndex: BigInt(6), + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + logIndex: BigInt(32), + removed: false, }, { - address: '0xa6e265667e1e18c28f2b5dc529f775c5f0d56d4a', - blockHash: '0xabc81c29235c7962f5a0420644761627bdc064a560c7d1842cdf9517f7d7984e', - blockNumber: BigInt(17030310), - data: '0x000000000000000000000000000000000000000000000001a055690d9db80000', - logIndex: BigInt(204), + address: '0x226b6b07e508bda9dffe13866f807346faf94627', + topics: ['0x1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1'], + data: '0x0000000000000000000000000000000000000000000000010eecfc5e451812f1000000000000000000000000000000000000000000000000b9cb01773305f8bc', + blockNumber: BigInt(20866453), + transactionHash: + '0x79fd3cd0c84acfbb1b9c8f2ab33517626eceb8cb42c21f1c21439ce36e0e6cab', + transactionIndex: BigInt(6), + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + logIndex: BigInt(33), removed: false, + }, + { + address: '0x226b6b07e508bda9dffe13866f807346faf94627', topics: [ - '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', - '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x000000000000000000000000d67da12dc33d9730d9341bbfa4f0b67d0688b28b', + '0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822', + '0x00000000000000000000000080a64c6d7f12c47b7c66c5b4e20e72bc1fcd5d9e', + '0x00000000000000000000000080a64c6d7f12c47b7c66c5b4e20e72bc1fcd5d9e', ], + data: '0x0000000000000000000000000000000000000000000000001a33261efb6495ca0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013d4b60de784bded', + blockNumber: BigInt(20866453), transactionHash: - '0x9a968248400868beb931ed96ee37517275794ff44e8d968c29f0f3430a504594', - transactionIndex: BigInt(91), + '0x79fd3cd0c84acfbb1b9c8f2ab33517626eceb8cb42c21f1c21439ce36e0e6cab', + transactionIndex: BigInt(6), + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + logIndex: BigInt(34), + removed: false, }, { - address: '0x69a592d2129415a4a1d1b1e309c17051b7f28d57', - blockHash: '0xabc81c29235c7962f5a0420644761627bdc064a560c7d1842cdf9517f7d7984e', - blockNumber: BigInt(17030310), - data: '0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a055690d9db8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - logIndex: BigInt(205), - removed: false, + address: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', topics: [ - '0x1abc43bc3dd8b6c8bb9bcf1a14a84f83981bf5335700ef07758efefcb03a8c75', - '0x000000000000000000000000a6e265667e1e18c28f2b5dc529f775c5f0d56d4a', - '0x000000000000000000000000d67da12dc33d9730d9341bbfa4f0b67d0688b28b', - '0x000000000000000000000000d67da12dc33d9730d9341bbfa4f0b67d0688b28b', + '0x7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65', + '0x00000000000000000000000080a64c6d7f12c47b7c66c5b4e20e72bc1fcd5d9e', ], + data: '0x00000000000000000000000000000000000000000000000013d4b60de784bded', + blockNumber: BigInt(20866453), transactionHash: - '0x9a968248400868beb931ed96ee37517275794ff44e8d968c29f0f3430a504594', - transactionIndex: BigInt(91), + '0x79fd3cd0c84acfbb1b9c8f2ab33517626eceb8cb42c21f1c21439ce36e0e6cab', + transactionIndex: BigInt(6), + blockHash: '0x4cf4c590ad0c46e86c83d3156b6fafd7ec10da67da577ee8abae96854b3e474f', + logIndex: BigInt(35), + removed: false, }, ], + logsBloom: + '0x00200000000000000000000080000001000000000000000000000000000000000000100000040000000000000000000002008000080000000002020000280000000000000000000000000008000000200000000100400000000000000000004000000000000000000000400000000000000000000000040000000010000000000000000000000000000000000000000000000000000000088000004000000000020000000000000000000000000004000000000000004000000000000000000000000002000000000000000000000000000000000000001000000002000000000050200008000000000000000000000000000000000000000000000000000000', status: BigInt(1), - transactionHash: '0x9a968248400868beb931ed96ee37517275794ff44e8d968c29f0f3430a504594', - transactionIndex: BigInt(91), + to: '0x80a64c6d7f12c47b7c66c5b4e20e72bc1fcd5d9e', + transactionHash: '0x79fd3cd0c84acfbb1b9c8f2ab33517626eceb8cb42c21f1c21439ce36e0e6cab', + transactionIndex: BigInt(6), type: BigInt(2), }); }); diff --git a/packages/web3/test/e2e/sepolia/get_past_logs.test.ts b/packages/web3/test/e2e/sepolia/get_past_logs.test.ts index b7ada0c6d09..ef87ce20013 100644 --- a/packages/web3/test/e2e/sepolia/get_past_logs.test.ts +++ b/packages/web3/test/e2e/sepolia/get_past_logs.test.ts @@ -67,8 +67,8 @@ describe(`${getSystemTestBackend()} tests - getPastLogs`, () => { const result = ( await web3.eth.getPastLogs( { - fromBlock: 'earliest', - toBlock: 'latest', + fromBlock: 3229301, + toBlock: 3229310, address: getE2ETestContractAddress(), }, { diff --git a/packages/web3/test/e2e/sepolia/get_storage_at.test.ts b/packages/web3/test/e2e/sepolia/get_storage_at.test.ts index a9f8e0ddf68..da2f321f224 100644 --- a/packages/web3/test/e2e/sepolia/get_storage_at.test.ts +++ b/packages/web3/test/e2e/sepolia/get_storage_at.test.ts @@ -66,10 +66,15 @@ describe(`${getSystemTestBackend()} tests - getStorageAt`, () => { )('getStorageAt', async ({ storageSlot, block }) => { let blockData = sepoliaBlockData[block]; if (block === 'blockHash' || block === 'blockNumber') { - const blockNumber = await web3.eth.getBlockNumber(); - blockData = Number(blockNumber); + /** + * @NOTE Getting a block too far back in history + * results in a missing trie node error, so + * we get latest block for this test + */ + const b = await web3.eth.getBlock('finalized'); + blockData = Number(b.number); if (block === 'blockHash') { - blockData = (await web3.eth.getBlock(blockNumber)).hash as string; + blockData = b.hash as string; } } diff --git a/packages/web3/test/e2e/sepolia/get_transaction.test.ts b/packages/web3/test/e2e/sepolia/get_transaction.test.ts index 4c52583919d..dc3760319da 100644 --- a/packages/web3/test/e2e/sepolia/get_transaction.test.ts +++ b/packages/web3/test/e2e/sepolia/get_transaction.test.ts @@ -43,15 +43,15 @@ describe(`${getSystemTestBackend()} tests - getTransaction`, () => { transactionHash: Bytes; }>({ transactionHash: [ - '0xe3d28c23ffcd8b94b8f2fd802b4c8dd17a5f19992660acd082ac229ab410b959', + '0xcf811d80757452f648f74bea7cdee088c5c2addafd8d049f644fc8cafee7a50d', bytesToUint8Array( hexToBytes( - '0xe3d28c23ffcd8b94b8f2fd802b4c8dd17a5f19992660acd082ac229ab410b959', + '0xcf811d80757452f648f74bea7cdee088c5c2addafd8d049f644fc8cafee7a50d', ), ), new Uint8Array( hexToBytes( - '0xe3d28c23ffcd8b94b8f2fd802b4c8dd17a5f19992660acd082ac229ab410b959', + '0xcf811d80757452f648f74bea7cdee088c5c2addafd8d049f644fc8cafee7a50d', ), ), ], @@ -60,27 +60,23 @@ describe(`${getSystemTestBackend()} tests - getTransaction`, () => { const result = await web3.eth.getTransaction(transactionHash); expect(result).toMatchObject({ - hash: '0xe3d28c23ffcd8b94b8f2fd802b4c8dd17a5f19992660acd082ac229ab410b959', - nonce: BigInt('0x0'), - blockHash: '0xdb1cb1fc3867fa28e4ba2297fbb1e65b81a3212beb1b73cbcbfe40c4192ee948', - blockNumber: BigInt('0x314675'), - transactionIndex: BigInt('0x8'), - from: '0xa127c5e6a7e3600ac34a9a9928e52521677e7211', - gasPrice: BigInt('0x9502f908'), - maxPriorityFeePerGas: BigInt('0x9502f900'), - maxFeePerGas: BigInt('0x9502f910'), - gas: BigInt('0x54eca'), - input: '0x608060405234801561001057600080fd5b5033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f342827c97908e5e2f71151c08502a66d44b6f758e3ac2f1de95f02eb95f0a73560405160405180910390a36104dc806100de6000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632e64cec1146100515780636057361d1461006f578063893d20e81461008b578063a6f9dae1146100a9575b600080fd5b6100596100c5565b60405161006691906102fb565b60405180910390f35b61008960048036038101906100849190610347565b6100ce565b005b610093610168565b6040516100a091906103b5565b60405180910390f35b6100c360048036038101906100be91906103fc565b610192565b005b60008054905090565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461015e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161015590610486565b60405180910390fd5b8060008190555050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610222576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161021990610486565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f342827c97908e5e2f71151c08502a66d44b6f758e3ac2f1de95f02eb95f0a73560405160405180910390a380600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000819050919050565b6102f5816102e2565b82525050565b600060208201905061031060008301846102ec565b92915050565b600080fd5b610324816102e2565b811461032f57600080fd5b50565b6000813590506103418161031b565b92915050565b60006020828403121561035d5761035c610316565b5b600061036b84828501610332565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061039f82610374565b9050919050565b6103af81610394565b82525050565b60006020820190506103ca60008301846103a6565b92915050565b6103d981610394565b81146103e457600080fd5b50565b6000813590506103f6816103d0565b92915050565b60006020828403121561041257610411610316565b5b6000610420848285016103e7565b91505092915050565b600082825260208201905092915050565b7f43616c6c6572206973206e6f74206f776e657200000000000000000000000000600082015250565b6000610470601383610429565b915061047b8261043a565b602082019050919050565b6000602082019050818103600083015261049f81610463565b905091905056fea26469706673582212201fcfa803d5c15c78e1e356cc1946c1bf14f9809acd349df1fd41362fa1a9e4d564736f6c63430008120033', - chainId: BigInt('0xaa36a7'), - type: BigInt('0x2'), - v: BigInt('0x0'), - s: '0x58f3924a7c468ab3df1a46ecef93910b4c05a13c3c3a9f4bf87b11f912b2748a', - r: '0x7fcc0285117b5613d0766b0bcd6cab69538bc0991b2bc4ddebbcc3cb5b4d8fb0', - // TODO These values are included when fetching the transaction from - // Nethermind, but not Infura - // to: null, - // value: '0x0', - // yParity: '0x0' + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: BigInt(6790201), + from: '0xaa88878d91bc1a7b7f71c592349efc44b5f3b77d', + gas: BigInt(73225), + gasPrice: BigInt(344362611607), + hash: '0xcf811d80757452f648f74bea7cdee088c5c2addafd8d049f644fc8cafee7a50d', + input: '0x95b335c84d053fdf52290285953409c8d9abdacc0000000066fb1966037903179f000000000000000000000000000000000000000000000000000000000000000007a13b0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000423078653030353565656530616135303532306162306162343132663535303666396635656664653663633561326565633231643031613063326266346638396261310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000299c007f9c00000000000000000000000000000000000000000000000000000000000000003e80000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001a3078313a3a6170746f735f636f696e3a3a4170746f73436f696e000000000000', + nonce: BigInt(2), + to: '0xd600d94d0812f7edfa47d0cf02a767b1dd14a01b', + transactionIndex: BigInt(1), + value: BigInt(732000000000000), + type: BigInt(0), + chainId: BigInt(11155111), + v: BigInt(22310257), + r: '0x1cf2c321ee1a4331dee4f9243fc1a73aa23b49929d0f5e475b27685c303fc4b1', + s: '0x009d5ffea271ec91f967e2993ff83c2576c63e83604ca8934768ede951ed1c5a', + data: '0x95b335c84d053fdf52290285953409c8d9abdacc0000000066fb1966037903179f000000000000000000000000000000000000000000000000000000000000000007a13b0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000423078653030353565656530616135303532306162306162343132663535303666396635656664653663633561326565633231643031613063326266346638396261310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000299c007f9c00000000000000000000000000000000000000000000000000000000000000003e80000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001a3078313a3a6170746f735f636f696e3a3a4170746f73436f696e000000000000', }); }); }); diff --git a/packages/web3/test/e2e/sepolia/get_transaction_receipt.test.ts b/packages/web3/test/e2e/sepolia/get_transaction_receipt.test.ts index 063be95cb21..6a376b8949a 100644 --- a/packages/web3/test/e2e/sepolia/get_transaction_receipt.test.ts +++ b/packages/web3/test/e2e/sepolia/get_transaction_receipt.test.ts @@ -18,7 +18,7 @@ import { Bytes } from 'web3-types'; import { bytesToUint8Array, hexToBytes } from 'web3-utils'; import Web3 from '../../../src'; -import { getSystemE2ETestProvider, getE2ETestContractAddress } from '../e2e_utils'; +import { getSystemE2ETestProvider } from '../e2e_utils'; import { closeOpenConnection, getSystemTestBackend, @@ -43,15 +43,15 @@ describe(`${getSystemTestBackend()} tests - getTransactionReceipt`, () => { transactionHash: Bytes; }>({ transactionHash: [ - '0xe3d28c23ffcd8b94b8f2fd802b4c8dd17a5f19992660acd082ac229ab410b959', + '0xcf811d80757452f648f74bea7cdee088c5c2addafd8d049f644fc8cafee7a50d', bytesToUint8Array( hexToBytes( - '0xe3d28c23ffcd8b94b8f2fd802b4c8dd17a5f19992660acd082ac229ab410b959', + '0xcf811d80757452f648f74bea7cdee088c5c2addafd8d049f644fc8cafee7a50d', ), ), new Uint8Array( hexToBytes( - '0xe3d28c23ffcd8b94b8f2fd802b4c8dd17a5f19992660acd082ac229ab410b959', + '0xcf811d80757452f648f74bea7cdee088c5c2addafd8d049f644fc8cafee7a50d', ), ), ], @@ -60,37 +60,33 @@ describe(`${getSystemTestBackend()} tests - getTransactionReceipt`, () => { const result = await web3.eth.getTransactionReceipt(transactionHash); expect(result).toMatchObject({ - blockHash: '0xdb1cb1fc3867fa28e4ba2297fbb1e65b81a3212beb1b73cbcbfe40c4192ee948', - blockNumber: BigInt(3229301), - contractAddress: getE2ETestContractAddress(), - cumulativeGasUsed: BigInt(579732), - effectiveGasPrice: BigInt(2500000008), - from: '0xa127c5e6a7e3600ac34a9a9928e52521677e7211', - gasUsed: BigInt(347850), + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + blockNumber: BigInt(6790201), + cumulativeGasUsed: BigInt(96860), + effectiveGasPrice: BigInt(344362611607), + from: '0xaa88878d91bc1a7b7f71c592349efc44b5f3b77d', + gasUsed: BigInt(48430), logs: [ { - address: getE2ETestContractAddress(), - blockHash: '0xdb1cb1fc3867fa28e4ba2297fbb1e65b81a3212beb1b73cbcbfe40c4192ee948', - blockNumber: BigInt(3229301), - data: '0x', - logIndex: BigInt(4), - removed: false, - topics: [ - '0x342827c97908e5e2f71151c08502a66d44b6f758e3ac2f1de95f02eb95f0a735', - '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x000000000000000000000000a127c5e6a7e3600ac34a9a9928e52521677e7211', - ], + address: '0xd600d94d0812f7edfa47d0cf02a767b1dd14a01b', + topics: ['0x590c2f125cf2856ae220fc1092c632f5e2e27e42627e4535a158f2eeb3426beb'], + data: '0x4d053fdf52290285953409c8d9abdacc0000000066fb1966037903179f0000000000000000000000000000000000000000000000000000000000000000aa36a7000000000000000000000000000000000000000000000000000000000007a13b000000000000000000000000aa88878d91bc1a7b7f71c592349efc44b5f3b77d00000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000299c007f9c00000000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000042307865303035356565653061613530353230616230616234313266353530366639663565666465366363356132656563323164303161306332626634663839626131000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a3078313a3a6170746f735f636f696e3a3a4170746f73436f696e000000000000', + blockNumber: BigInt(6790201), transactionHash: - '0xe3d28c23ffcd8b94b8f2fd802b4c8dd17a5f19992660acd082ac229ab410b959', - transactionIndex: BigInt(8), + '0xcf811d80757452f648f74bea7cdee088c5c2addafd8d049f644fc8cafee7a50d', + transactionIndex: BigInt(1), + blockHash: '0xbdec00d52c5b4e1c00e0821fdaa492c0330ae06504d27a7e9f2e3e014957e96d', + logIndex: BigInt(1), + removed: false, }, ], logsBloom: - '0x00000000000000000000000000000000000000000400000001000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000060000000000040010000800000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000010000000000000000000000000000000', + '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000010000000000000000000000000000000004000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', status: BigInt(1), - transactionHash: '0xe3d28c23ffcd8b94b8f2fd802b4c8dd17a5f19992660acd082ac229ab410b959', - transactionIndex: BigInt(8), - type: BigInt(2), + to: '0xd600d94d0812f7edfa47d0cf02a767b1dd14a01b', + transactionHash: '0xcf811d80757452f648f74bea7cdee088c5c2addafd8d049f644fc8cafee7a50d', + transactionIndex: BigInt(1), + type: BigInt(0), }); }); }); From 7c207b8953b9d5aff369d0300498a42e46f11a2e Mon Sep 17 00:00:00 2001 From: Muhammad Altabba <24407834+Muhammad-Altabba@users.noreply.github.com> Date: Sat, 5 Oct 2024 20:08:14 +0200 Subject: [PATCH 160/186] fix: correct type and documentation for `baseFeePerGas` at `web3.eth.getFeeHistory` (#7291) * update type and documentation for `baseFeePerGas` at `web3.eth.getFeeHistory` * fix a type at a unit test --- .../guides/web3_upgrade_guide/1.x/web3_eth_migration_guide.md | 4 ++-- .../test/unit/rpc_method_wrappers/fixtures/get_fee_history.ts | 2 +- packages/web3-types/CHANGELOG.md | 4 ++++ packages/web3-types/src/eth_types.ts | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/docs/guides/web3_upgrade_guide/1.x/web3_eth_migration_guide.md b/docs/docs/guides/web3_upgrade_guide/1.x/web3_eth_migration_guide.md index 10b57e1d261..4a7b36d62fb 100644 --- a/docs/docs/guides/web3_upgrade_guide/1.x/web3_eth_migration_guide.md +++ b/docs/docs/guides/web3_upgrade_guide/1.x/web3_eth_migration_guide.md @@ -147,7 +147,7 @@ web3.eth.getHashRate // -> correct usage #### web3.eth.getFeeHistory -4.x returns a `BigInt` for `oldestBlock` instead of the hex string that's returned in 1.x. +4.x returns a `BigInt` for `oldestBlock` instead of the hex string that's returned in 1.x. And 4.x returns `number[]`, instead of `strings[]` for `baseFeePerGas`. ```typescript // in 1.x @@ -162,7 +162,7 @@ await web3.eth.getFeeHistory('0x1', 'latest', []); await web3.eth.getFeeHistory('0x1', 'latest', []); // { // oldestBlock: 0n, -// baseFeePerGas: [ '0x3b9aca00', '0x342770c0' ], +// baseFeePerGas: [ 1000000000, 875000000 ], // gasUsedRatio: [ 0 ] // } ``` diff --git a/packages/web3-eth/test/unit/rpc_method_wrappers/fixtures/get_fee_history.ts b/packages/web3-eth/test/unit/rpc_method_wrappers/fixtures/get_fee_history.ts index 54ea874c610..00ddece4e77 100644 --- a/packages/web3-eth/test/unit/rpc_method_wrappers/fixtures/get_fee_history.ts +++ b/packages/web3-eth/test/unit/rpc_method_wrappers/fixtures/get_fee_history.ts @@ -18,7 +18,7 @@ import { FeeHistoryResultAPI, BlockNumberOrTag, BlockTags, Numbers } from 'web3- export const mockRpcResponse: FeeHistoryResultAPI = { oldestBlock: '0xa30950', - baseFeePerGas: '0x9', + baseFeePerGas: ['0x9'], reward: [], gasUsedRatio: ['0'], }; diff --git a/packages/web3-types/CHANGELOG.md b/packages/web3-types/CHANGELOG.md index e38c479f914..aa6b36d4885 100644 --- a/packages/web3-types/CHANGELOG.md +++ b/packages/web3-types/CHANGELOG.md @@ -209,3 +209,7 @@ Documentation: - Add COMMITTED to BlockTags (#7124) ## [Unreleased] + +### Changed + +- update the type for `baseFeePerGas` at `web3.eth.getFeeHistory` to be a number. (#7291) diff --git a/packages/web3-types/src/eth_types.ts b/packages/web3-types/src/eth_types.ts index 9c83e92d0d5..5458fe1d426 100644 --- a/packages/web3-types/src/eth_types.ts +++ b/packages/web3-types/src/eth_types.ts @@ -515,7 +515,7 @@ export type Block = BlockBase< export interface FeeHistoryBase { readonly oldestBlock: NumberType; - readonly baseFeePerGas: NumberType; + readonly baseFeePerGas: NumberType[]; readonly reward: NumberType[][]; readonly gasUsedRatio: NumberType[]; } From 496ed9379d1f8343dd7acdb03be9aa6aeafbc2c3 Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Mon, 7 Oct 2024 08:24:11 -0700 Subject: [PATCH 161/186] Restructure Docs (#7298) * Restructure Docs * Set tab-size to 2 for Docs --- README.md | 26 +- docs/docs/glossary/index.md | 81 ++- .../_category_.yml | 0 .../guides/01_getting_started/introduction.md | 92 +++ .../quickstart.md | 77 +-- .../01_getting_started/return-formats.md | 121 ++++ .../_category_.yml | 0 .../eip6963.md | 45 +- .../events_listening.md | 16 +- .../index.md | 169 +++-- .../guides/{wallet => 03_wallet}/index.md | 76 +-- .../1.x => 04_transactions}/_category_.yml | 4 +- .../transactions.md | 228 +++---- docs/docs/guides/04_transactions/tx-types.md | 279 ++++++++ .../_category_.yml | 2 +- .../infer_contract_types.md | 66 +- .../mastering_smart_contracts.md | 153 ++--- .../smart_contracts_guide.md | 197 +++--- .../tips_and_tricks.md | 110 ++- .../_category_.yml | 2 +- .../custom_subscriptions.md | 118 ++-- .../index.md | 104 +-- .../{web3_config => 07_dapps}/_category_.yml | 2 +- docs/docs/guides/07_dapps/metamask-react.md | 612 +++++++++++++++++ docs/docs/guides/07_dapps/metamask-vanilla.md | 492 ++++++++++++++ .../web3_modal_guide/_category_.yml | 2 +- .../web3_modal_guide/index.mdx | 2 +- .../guides/07_dapps/web3_modal_guide/react.md | 122 ++++ .../asset/artifacts.png | Bin .../asset/image_2.png | Bin .../asset/image_3.png | Bin .../index.md | 255 ++++--- .../{web3_config => 09_web3_config}/index.md | 336 +++++----- .../{web3_eth => 10_web3_eth}/_category_.yml | 2 +- .../guides/{web3_eth => 10_web3_eth}/eth.md | 549 ++++++++------- .../{web3_eth => 10_web3_eth}/methods.md | 7 +- docs/docs/guides/{ens => 11_ens}/index.md | 12 +- .../index.md} | 140 ++-- .../{advanced => 13_advanced}/_category_.yml | 2 +- .../{advanced => 13_advanced}/custom_RPC.md | 0 .../{advanced => 13_advanced}/extend.md | 0 .../{advanced => 13_advanced}/tree_shaking.md | 0 .../_category_.yml | 2 +- .../assets/web3_context_augmentation.png | Bin .../index.mdx | 2 +- .../plugin_authors.md | 194 +++--- .../plugin_users.md | 40 +- .../_category_.yml | 2 +- .../abi_migration_guide.md | 0 .../accounts_migration_guide.md | 1 - .../contracts_migration_guide.md | 0 .../1.x => 15_web3_upgrade_guide}/index.md | 9 +- .../net_migration_guide.md | 0 .../personal_migration_guide.md | 0 .../providers_migration_guide.md | 2 +- .../subscribe_migration_guide.md | 0 .../web3_eth_ens.md | 0 .../web3_eth_iban.md | 0 .../web3_eth_migration_guide.md | 0 .../web3_utils_migration_guide.md | 0 docs/docs/guides/16_wagmi_usage/index.md | 127 ++++ .../index.md} | 141 ++-- .../index.md | 12 +- .../guides/{feedback => 19_feedback}/index.md | 4 +- docs/docs/guides/ens/_category_.yml | 5 - .../guides/getting_started/introduction.md | 92 --- .../guides/getting_started/return-formats.md | 121 ---- .../guides/hardhat_tutorial/_category_.yml | 5 - docs/docs/guides/wagmi_usage/_category_.yml | 5 - docs/docs/guides/wagmi_usage/wagmi.md | 131 ---- docs/docs/guides/wallet/_category_.yml | 5 - docs/docs/guides/wallet/metamask-react.md | 626 ------------------ docs/docs/guides/wallet/metamask-vanilla.md | 480 -------------- docs/docs/guides/wallet/tx-types.md | 280 -------- .../guides/wallet/web3_modal_guide/react.md | 121 ---- .../guides/web3_upgrade_guide/_category_.yml | 5 - .../guides/web3_utils_module/_category_.yml | 5 - docs/src/css/custom.css | 1 + packages/web3/src/types.ts | 2 +- 79 files changed, 3460 insertions(+), 3461 deletions(-) rename docs/docs/guides/{getting_started => 01_getting_started}/_category_.yml (100%) create mode 100644 docs/docs/guides/01_getting_started/introduction.md rename docs/docs/guides/{getting_started => 01_getting_started}/quickstart.md (87%) create mode 100644 docs/docs/guides/01_getting_started/return-formats.md rename docs/docs/guides/{web3_providers_guide => 02_web3_providers_guide}/_category_.yml (100%) rename docs/docs/guides/{web3_providers_guide => 02_web3_providers_guide}/eip6963.md (66%) rename docs/docs/guides/{web3_providers_guide => 02_web3_providers_guide}/events_listening.md (97%) rename docs/docs/guides/{web3_providers_guide => 02_web3_providers_guide}/index.md (74%) rename docs/docs/guides/{wallet => 03_wallet}/index.md (78%) rename docs/docs/guides/{web3_upgrade_guide/1.x => 04_transactions}/_category_.yml (53%) rename docs/docs/guides/{wallet => 04_transactions}/transactions.md (81%) create mode 100644 docs/docs/guides/04_transactions/tx-types.md rename docs/docs/guides/{smart_contracts => 05_smart_contracts}/_category_.yml (86%) rename docs/docs/guides/{smart_contracts => 05_smart_contracts}/infer_contract_types.md (82%) rename docs/docs/guides/{smart_contracts => 05_smart_contracts}/mastering_smart_contracts.md (78%) rename docs/docs/guides/{smart_contracts => 05_smart_contracts}/smart_contracts_guide.md (78%) rename docs/docs/guides/{smart_contracts => 05_smart_contracts}/tips_and_tricks.md (63%) rename docs/docs/guides/{events_subscriptions => 06_events_subscriptions}/_category_.yml (86%) rename docs/docs/guides/{events_subscriptions => 06_events_subscriptions}/custom_subscriptions.md (75%) rename docs/docs/guides/{events_subscriptions => 06_events_subscriptions}/index.md (51%) rename docs/docs/guides/{web3_config => 07_dapps}/_category_.yml (67%) create mode 100644 docs/docs/guides/07_dapps/metamask-react.md create mode 100644 docs/docs/guides/07_dapps/metamask-vanilla.md rename docs/docs/guides/{wallet => 07_dapps}/web3_modal_guide/_category_.yml (87%) rename docs/docs/guides/{wallet => 07_dapps}/web3_modal_guide/index.mdx (98%) create mode 100644 docs/docs/guides/07_dapps/web3_modal_guide/react.md rename docs/docs/guides/{hardhat_tutorial => 08_hardhat_tutorial}/asset/artifacts.png (100%) rename docs/docs/guides/{hardhat_tutorial => 08_hardhat_tutorial}/asset/image_2.png (100%) rename docs/docs/guides/{hardhat_tutorial => 08_hardhat_tutorial}/asset/image_3.png (100%) rename docs/docs/guides/{hardhat_tutorial => 08_hardhat_tutorial}/index.md (59%) rename docs/docs/guides/{web3_config => 09_web3_config}/index.md (70%) rename docs/docs/guides/{web3_eth => 10_web3_eth}/_category_.yml (85%) rename docs/docs/guides/{web3_eth => 10_web3_eth}/eth.md (66%) rename docs/docs/guides/{web3_eth => 10_web3_eth}/methods.md (97%) rename docs/docs/guides/{ens => 11_ens}/index.md (94%) rename docs/docs/guides/{web3_utils_module/mastering_web3-utils.md => 12_web3_utils_module/index.md} (62%) rename docs/docs/guides/{advanced => 13_advanced}/_category_.yml (83%) rename docs/docs/guides/{advanced => 13_advanced}/custom_RPC.md (100%) rename docs/docs/guides/{advanced => 13_advanced}/extend.md (100%) rename docs/docs/guides/{advanced => 13_advanced}/tree_shaking.md (100%) rename docs/docs/guides/{web3_plugin_guide => 14_web3_plugin_guide}/_category_.yml (85%) rename docs/docs/guides/{web3_plugin_guide => 14_web3_plugin_guide}/assets/web3_context_augmentation.png (100%) rename docs/docs/guides/{web3_plugin_guide => 14_web3_plugin_guide}/index.mdx (99%) rename docs/docs/guides/{web3_plugin_guide => 14_web3_plugin_guide}/plugin_authors.md (82%) rename docs/docs/guides/{web3_plugin_guide => 14_web3_plugin_guide}/plugin_users.md (83%) rename docs/docs/guides/{migration_from_other_libs => 15_web3_upgrade_guide}/_category_.yml (62%) rename docs/docs/guides/{web3_upgrade_guide/1.x => 15_web3_upgrade_guide}/abi_migration_guide.md (100%) rename docs/docs/guides/{web3_upgrade_guide/1.x => 15_web3_upgrade_guide}/accounts_migration_guide.md (99%) rename docs/docs/guides/{web3_upgrade_guide/1.x => 15_web3_upgrade_guide}/contracts_migration_guide.md (100%) rename docs/docs/guides/{web3_upgrade_guide/1.x => 15_web3_upgrade_guide}/index.md (95%) rename docs/docs/guides/{web3_upgrade_guide/1.x => 15_web3_upgrade_guide}/net_migration_guide.md (100%) rename docs/docs/guides/{web3_upgrade_guide/1.x => 15_web3_upgrade_guide}/personal_migration_guide.md (100%) rename docs/docs/guides/{web3_upgrade_guide/1.x => 15_web3_upgrade_guide}/providers_migration_guide.md (99%) rename docs/docs/guides/{web3_upgrade_guide/1.x => 15_web3_upgrade_guide}/subscribe_migration_guide.md (100%) rename docs/docs/guides/{web3_upgrade_guide/1.x => 15_web3_upgrade_guide}/web3_eth_ens.md (100%) rename docs/docs/guides/{web3_upgrade_guide/1.x => 15_web3_upgrade_guide}/web3_eth_iban.md (100%) rename docs/docs/guides/{web3_upgrade_guide/1.x => 15_web3_upgrade_guide}/web3_eth_migration_guide.md (100%) rename docs/docs/guides/{web3_upgrade_guide/1.x => 15_web3_upgrade_guide}/web3_utils_migration_guide.md (100%) create mode 100644 docs/docs/guides/16_wagmi_usage/index.md rename docs/docs/guides/{migration_from_other_libs/ethers.md => 17_migration_from_other_libs/index.md} (79%) rename docs/docs/guides/{resources_and_troubleshooting => 18_resources_and_troubleshooting}/index.md (96%) rename docs/docs/guides/{feedback => 19_feedback}/index.md (97%) delete mode 100644 docs/docs/guides/ens/_category_.yml delete mode 100644 docs/docs/guides/getting_started/introduction.md delete mode 100644 docs/docs/guides/getting_started/return-formats.md delete mode 100644 docs/docs/guides/hardhat_tutorial/_category_.yml delete mode 100644 docs/docs/guides/wagmi_usage/_category_.yml delete mode 100644 docs/docs/guides/wagmi_usage/wagmi.md delete mode 100644 docs/docs/guides/wallet/_category_.yml delete mode 100644 docs/docs/guides/wallet/metamask-react.md delete mode 100644 docs/docs/guides/wallet/metamask-vanilla.md delete mode 100644 docs/docs/guides/wallet/tx-types.md delete mode 100644 docs/docs/guides/wallet/web3_modal_guide/react.md delete mode 100644 docs/docs/guides/web3_upgrade_guide/_category_.yml delete mode 100644 docs/docs/guides/web3_utils_module/_category_.yml diff --git a/README.md b/README.md index adf5ec07574..3284ef04f23 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ yarn add web3 ## Migration Guide -- [Migration Guide from Web3.js 1.x to 4.x](https://docs.web3js.org/guides/web3_upgrade_guide/x/) +- [Migration Guide from Web3.js 1.x to 4.x](https://docs.web3js.org/guides/web3_upgrade_guide/index) Breaking changes are listed in migration guide and its first step for migrating from Web3.js 1.x to 4.x. If there is any question or discussion feel free to ask in [Discord](https://discord.gg/yjyvFRP), and in case of any bug or new feature request [open issue](https://github.com/web3/web3.js/issues/new) or create a pull request for [contributions](https://github.com/web3/web3.js/blob/4.x/.github/CONTRIBUTING.md). ## Useful links @@ -76,18 +76,18 @@ yarn add web3 ## Package.json Scripts -| Script | Description | -| ---------------- |--------------------------------------------------------------------| -| clean | Uses `rimraf` to remove `dist/` | -| build | Uses `tsc` to build all packages | -| lint | Uses `eslint` to lint all packages | -| lint:fix | Uses `eslint` to check and fix any warnings | -| format | Uses `prettier` to format the code | -| test | Uses `jest` to run unit tests in each package | -| test:integration | Uses `jest` to run tests under `/test/integration` in each package | -| test:unit | Uses `jest` to run tests under `/test/unit` in each package | -| test:manual:long-connection-ws | Runs manual tests for keeping a long WebSocket connection | -| test:manual | Runs manual tests under `test/manual` in the web3 package | +| Script | Description | +| ------------------------------ | ------------------------------------------------------------------ | +| clean | Uses `rimraf` to remove `dist/` | +| build | Uses `tsc` to build all packages | +| lint | Uses `eslint` to lint all packages | +| lint:fix | Uses `eslint` to check and fix any warnings | +| format | Uses `prettier` to format the code | +| test | Uses `jest` to run unit tests in each package | +| test:integration | Uses `jest` to run tests under `/test/integration` in each package | +| test:unit | Uses `jest` to run tests under `/test/unit` in each package | +| test:manual:long-connection-ws | Runs manual tests for keeping a long WebSocket connection | +| test:manual | Runs manual tests under `test/manual` in the web3 package | [npm-url]: https://npmjs.org/package/web3 [downloads-image]: https://img.shields.io/npm/dm/web3?label=npm%20downloads diff --git a/docs/docs/glossary/index.md b/docs/docs/glossary/index.md index 1af9691a85e..7af367af75b 100644 --- a/docs/docs/glossary/index.md +++ b/docs/docs/glossary/index.md @@ -4,7 +4,6 @@ sidebar_label: '📖 Glossary' title: Glossary --- - ## Provider In web3.js, a `provider` is an object responsible for enabling connectivity with the Ethereum network in various ways. Providers facilitate the connection of your web application to an Ethereum node, different provider types are available in web3.js(HTTP, WebSocket and IPC), each with its own features and use cases. **It's important to note that a provider itself only provides read-only access to the blockchain.** It does not use any private keys or accounts for interaction. This read-only functionality is particularly useful for querying data and making calls to the blockchain without the need for private key authorization. @@ -13,12 +12,10 @@ In web3.js, a `provider` is an object responsible for enabling connectivity with In web3.js, an `account` allows you to perform operations on the blockchain, such as sending transactions, signing data, and interacting with contracts. It serves as the key component for **using a private key** directly to execute various blockchain operations. In other libraries, this concept is often referred to as a `signer`. This versatility in terminology doesn't change its fundamental purpose, providing a secure and straightforward means to manage Ethereum-related operations. - ## Wallet A `wallet` in web3.js can store multiple `accounts`. This feature allows you to manage various private keys for different operations. When using methods such as `web3.eth.sendTransaction()` or `web3.eth.contract.methods.doSomething().send({})`, the web3.js library handles these transactions using the wallet accounts under the hood. Essentially, the wallet makes it easier to coordinate multiple accounts for smoother Ethereum operations. - ## Contract The `Contract` class is an important class in the `web3-eth-contract` package, also available in the `web3` package. It serves as an abstraction representing a connection to a specific contract on the Ethereum Network, enabling applications to interact with it as a typical JavaScript object. Through the `Contract` class, you can execute functions and listen to events associated with the smart contract (e.g, `contract.methods.doSomething().call()`) @@ -82,30 +79,39 @@ contract Test { ```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"}], - } + { + "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" }] + } ] ``` @@ -123,6 +129,7 @@ const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')); ``` ## WebSocketProvider + [WebSocketProvider](https://docs.web3js.org/guides/web3_providers_guide/#websocket-provider) in Web3.js connects your application to an Ethereum node via WebSocket, enabling real-time and asynchronous communication. This provider is ideal for applications needing real-time updates, such as new blocks or smart contract events. It offers better performance for high-throughput applications compared to `HttpProvider`. Ensure secure connections with `wss://` for exposed endpoints. Handle reconnections gracefully for reliable operation. ```javascript title='WebSocketProvider example' @@ -138,13 +145,14 @@ The `Events` class in Web3.js is a crucial part of the library that enables deve ```solidity title='Event in solidity' contract MyContract { - event Transfer(address indexed from, address indexed to, uint value); + event Transfer(address indexed from, address indexed to, uint256 value); - function transfer(address recipient, uint amount) public { - // ... transfer logic ... - emit Transfer(msg.sender, recipient, amount); - } + function transfer(address recipient, uint256 amount) public { + // ... transfer logic ... + emit Transfer(msg.sender, recipient, amount); + } } + ``` ```javascript title='Event in web3.js' @@ -158,9 +166,9 @@ const myContract = new web3.eth.Contract(MyContract.abi, contractAddress); const transferEvent = myContract.events.Transfer(); // Access the Transfer event -transferEvent.on('data', (event) => { - console.log('Transfer Event:', event); - // Process the event data (from, to, value) +transferEvent.on('data', event => { + console.log('Transfer Event:', event); + // Process the event data (from, to, value) }); ``` @@ -190,4 +198,5 @@ web3.eth.getPastLogs(options) .catch((error) => { console.error('Error retrieving logs:', error); }); -` \ No newline at end of file +` +``` diff --git a/docs/docs/guides/getting_started/_category_.yml b/docs/docs/guides/01_getting_started/_category_.yml similarity index 100% rename from docs/docs/guides/getting_started/_category_.yml rename to docs/docs/guides/01_getting_started/_category_.yml diff --git a/docs/docs/guides/01_getting_started/introduction.md b/docs/docs/guides/01_getting_started/introduction.md new file mode 100644 index 00000000000..b1fc2a8469a --- /dev/null +++ b/docs/docs/guides/01_getting_started/introduction.md @@ -0,0 +1,92 @@ +--- +slug: / +sidebar_position: 1 +sidebar_label: Introduction +--- + +# Introduction + +Web3.js is a robust and flexible collection of **TypeScript and JavaScript** libraries that allows developers to interact with local or remote [Ethereum](https://ethereum.org/en/) nodes (or **any EVM-compatible blockchain**) over **HTTP, IPC or WebSocket** connections. It is a powerful and efficient toolkit for crafting applications within the Ethereum ecosystem and beyond. + +This documentation is the entrypoint to Web3.js for developers. It covers [basic](/guides/getting_started/quickstart) and [advanced](/guides/smart_contracts/mastering_smart_contracts) usage with examples, and includes comprehensive [API documentation](/api) as well as guides for common tasks, like [upgrading](/guides/web3_upgrade_guide) from older versions. + +## Features of Web3.js v4 + +- Flexible + - ECMAScript (ESM) and CommonJS (CJS) builds + - [Plugins](/guides/web3_plugin_guide/) for extending functionality +- Efficient + - Modular, [package](/#packages)-based design reduces unneeded dependencies + - [Tree shakable with ESM](/guides/advanced/tree_shaking) + - Use of native [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) (instead of large [BigNumber](https://mikemcl.github.io/bignumber.js/) libraries) + - Efficient ABI [encoding](/api/web3-eth-abi/function/encodeFunctionCall) & [decoding](/api/web3-eth-abi/function/decodeParameter) +- Developer-Friendly + - [Dynamic contract types](/guides/smart_contracts/infer_contract_types/) & full API in TypeScript + - Custom output [formatters](https://docs.web3js.org/api/web3-utils/function/format) + - In compliance with the [Ethereum JSON-RPC Specification](https://ethereum.github.io/execution-apis/api-documentation/) + +## Using These Docs + +There is a lot to learn about Web3.js! Here are some tips for developers of different skill levels. Remember, you can always [reach out directly](/guides/feedback/#urgent-questions-or-concerns) with Discord or Twitter if you're feeling stuck. + +### For Beginner Web3.js Developers + +New Web3.js developers should proceed to the [Quickstart](/guides/getting_started/quickstart) section to learn how to get started with Web3.js. Once you understand the basics, you may want to consider learning more about [providers](/guides/web3_providers_guide/), [wallets and accounts](/guides/wallet), [smart contracts](/guides/smart_contracts/smart_contracts_guide), and how to [use Web3.js with the Hardhat development environment](/guides/hardhat_tutorial). + +### For Intermediate & Advanced Web3.js Developers + +If you're already familiar with Ethereum and Web3.js development, you may want to review the Web3.js [package structure](#packages--plugins) and proceed directly to the [package-level documentation](/libdocs/ABI) and [API documentation](/api). Application developers may wish to review the [Web3.js configuration guide](/guides/web3_config) or learn how to use Web3.js with tools like the [MetaMask](/guides/dapps/metamask-react) wallet or the [WalletConnect](/guides/dapps/web3_modal_guide) wallet selection modal. Don't forget to review the [list of available plugins](https://web3js.org/plugins) or even [learn how to build your own Web3.js plugin](/guides/web3_plugin_guide/plugin_authors)! + +## Packages & Plugins + +Web3.js is a modular collection of packages, each of which serves a specific needs. This means developers don't need to install the entire Web3 library for most use cases. Instead, necessary packages are selectively installed for a more efficient development experience. Here is an overview of a selection of available packages: + +- [**Web3Eth:**](/libdocs/Web3Eth) The `web3-eth` package is the entrypoint to Web3.js - it's the control center for managing interactions with Ethereum and other EVM-compatible networks. + +- [**Net:**](/libdocs/Net) The `web3-net` package provides discovery and interactions for an **Ethereum node's network properties.** + +- [**Accounts:**](/libdocs/Accounts) The `web3-eth-accounts` package has tools for creating Ethereum accounts and the **secure signing** of transactions and data. + +- [**Personal:**](/libdocs/Personal) Use `web3-eth-personal` for **direct communication about your accounts with the Ethereum node**, which streamlines account management during development. + + **NOTE:** _For enhanced security in production and when interacting with public nodes, consider using `web3-eth-accounts` for local signing operations, which keeps your private keys and sensitive information secure on your local machine_ + +- [**Utils:**](/libdocs/Utils) The `web3-utils` package provides helpers to perform a range of essential Ethereum development tasks, including **converting data formats, checking addresses, encoding and decoding data, hashing, handling numbers, and much more.**. + +- [**Contract:**](/libdocs/Contract) The `web3-eth-contract` package makes it easy to **interact with smart contracts through JavaScript or TypeScript,** which streamlines the development process and makes it less error-prone. + +- [**ABI:**](/libdocs/ABI) The `web3-eth-abi` package simplifies decoding logs and parameters, encoding function calls and signatures, and inferring types for efficient Ethereum **smart contract interactions.** + +- [**ENS:**](/libdocs/ENS) The `web3-eth-ens` package makes it easy for developers to communicate with the **Ethereum Name Service (ENS).** + +- [**Iban:**](/libdocs/Iban) The `web3-eth-iban` package allows you to switch between **Ethereum addresses and special banking-like addresses** (IBAN or BBAN) and simplifies conversion between the types. + +### Additional Supporting Packages + +- [**Web3 Core:**](/api/web3-core) subscriptions, request management, and configuration used by other Web3 packages + +- [**Web3 Types:**](/api/web3-types) data structures, objects, interfaces and types used by Web3 + +- [**Web3 Validator:**](/api/web3-validator) runtime type validation against predefined types or custom schemas + +- [**Web3 Errors:**](/api/web3-errors) error codes and common error classes that are used by other Web3 packages + +- [**Web3 RPC Methods:**](/api/web3/namespace/rpcMethods) functions for making RPC requests to Ethereum using a given provider + +### Plugins + +Web3.js supports [plugins](/guides/web3_plugin_guide/), which are another way to encapsulate capabilities that support a specific need. There are plugins that exist to support native features, like those described by [EIPs](https://eips.ethereum.org/) as well as plugins that are designed to support specific smart contracts, middleware, or even other Ethereum-compatible networks. Visit the [Web3.js plugins homepage](https://web3js.org/plugins) to view a list of the most important Web3.js plugins, which includes: + +- [EIP-4337 (Account Abstraction) Plugin](https://www.npmjs.com/package/@chainsafe/web3-plugin-eip4337) + +- [EIP-4844 (Blob Transactions) Plugin](https://www.npmjs.com/package/web3-plugin-blob-tx) + +- [zkSync Plugin](https://www.npmjs.com/package/web3-plugin-zksync) + +## Advantages Over Other Libraries + +- **Extensive Documentation and Community**: Web3.js is one of the most established Ethereum libraries, which means it 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, which allows developers to use specific packages according to their needs. This leads 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. diff --git a/docs/docs/guides/getting_started/quickstart.md b/docs/docs/guides/01_getting_started/quickstart.md similarity index 87% rename from docs/docs/guides/getting_started/quickstart.md rename to docs/docs/guides/01_getting_started/quickstart.md index 80551ad735b..fb0a70c851f 100644 --- a/docs/docs/guides/getting_started/quickstart.md +++ b/docs/docs/guides/01_getting_started/quickstart.md @@ -9,11 +9,11 @@ Use the live code editor to try Web3.js in your browser now! Keep reading to lea ## Live Code Editor - + ## Installation -If NPM is being used as package manager, install Web3.js with the following command: +If NPM is being used as package manager, install Web3.js with the following command: ``` npm i web3 @@ -25,19 +25,19 @@ For projects using Yarn as a package manager, use: yarn add web3 ``` -Note: Installing Web3.js in this way will bring in all Web3.js sub-[packages](/#packages). If you only need specific packages, it is recommended to install them individually (e.g, if you want the [Contract](/libdocs/Contract) package, use `npm i web3-eth-contract` instead) +Note: Installing Web3.js in this way will bring in all Web3.js sub-[packages](/#packages). If you only need specific packages, it is recommended to install them individually (e.g, if you want the [Contract](/libdocs/Contract) package, use `npm i web3-eth-contract` instead) ## Importing Web3.js Web3.js v4 supports both CommonJS (CJS) and native ECMAScript module (ESM) imports. For importing the main Web3 class in CJS, use: -``` js +```js const { Web3 } = require('web3'); ``` For ESM-style imports, use: -``` ts +```ts import { Web3 } from 'web3'; ``` @@ -47,18 +47,19 @@ import { Web3 } from 'web3'; Web3.js is in compliance with [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193), the Ethereum Provider JavaScript API, so any EIP-1193 provider can be used to initialize the `Web3` object. -``` ts +```ts import { Web3 } from 'web3'; -// private RPC endpoint -const web3 = new Web3('https://mainnet.infura.io/v3/YOUR_INFURA_ID'); +// private RPC endpoint +const web3 = new Web3('https://mainnet.infura.io/v3/YOUR_INFURA_ID'); // or public RPC endpoint -// const web3 = new Web3('https://eth.llamarpc.com'); +// const web3 = new Web3('https://eth.llamarpc.com'); web3.eth.getBlockNumber().then(console.log); // ↳ 18849658n ``` + ## Querying the Blockchain After instantiating the `Web3` instance with a provider, the [`web3-eth`](/libdocs/Web3Eth) package can be used to fetch data from the Ethereum network: @@ -97,7 +98,7 @@ Using the `Wallet` to create a random account is a good way to accelerate the de ```ts // create random wallet with 1 account -web3.eth.accounts.wallet.create(1) +web3.eth.accounts.wallet.create(1); /* ↳ Wallet(1) [ @@ -129,7 +130,9 @@ Private keys are sensitive data and should be treated as such. Make sure that pr ```ts // the private key must start with the "0x" prefix -const account = web3.eth.accounts.wallet.add('0x50d349f5cf627d44858d6fcb6fbf15d27457d35c58ba2d5cfeaf455f25db5bec'); +const account = web3.eth.accounts.wallet.add( + '0x50d349f5cf627d44858d6fcb6fbf15d27457d35c58ba2d5cfeaf455f25db5bec', +); console.log(account[0].address); //↳ 0xcE6A5235d6033341972782a15289277E85E5b305 @@ -144,21 +147,22 @@ This is an example of using a private key to add an account to a wallet, and the ```ts // add an account to a wallet -const account = web3.eth.accounts.wallet.add('0x50d349f5cf627d44858d6fcb6fbf15d27457d35c58ba2d5cfeaf455f25db5bec'); +const account = web3.eth.accounts.wallet.add( + '0x50d349f5cf627d44858d6fcb6fbf15d27457d35c58ba2d5cfeaf455f25db5bec', +); // create transaction object to send 1 eth to '0xa32...c94' address from the account[0] -const tx = -{ - from: account[0].address, - to: '0xa3286628134bad128faeef82f44e99aa64085c94', - value: web3.utils.toWei('1', 'ether') +const tx = { + from: account[0].address, + to: '0xa3286628134bad128faeef82f44e99aa64085c94', + value: web3.utils.toWei('1', 'ether'), }; // the "from" address must match the one previously added with wallet.add // send the transaction const txReceipt = await web3.eth.sendTransaction(tx); -console.log('Tx hash:', txReceipt.transactionHash) +console.log('Tx hash:', txReceipt.transactionHash); // ↳ Tx hash: 0x03c844b069646e08af1b6f31519a36e3e08452b198ef9f6ce0f0ccafd5e3ae0e ``` @@ -172,22 +176,21 @@ The first step to interacting with a smart contract is to instantiate it, which ```ts // Uniswap token smart contract address (Mainnet) -const address = '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984' +const address = '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984'; // you can find the complete ABI on etherscan.io // https://etherscan.io/address/0x1f9840a85d5af5bf1d1762f925bdaddc4201f984#code -const ABI = -[ - { - name: 'symbol', - outputs: [{ type: 'string' }], - type: 'function', - }, - { - name: 'totalSupply', - outputs: [{ type: 'uint256' }], - type: 'function', - }, +const ABI = [ + { + name: 'symbol', + outputs: [{ type: 'string' }], + type: 'function', + }, + { + name: 'totalSupply', + outputs: [{ type: 'uint256' }], + type: 'function', + }, ]; // instantiate the smart contract @@ -202,7 +205,7 @@ Since reading data from a smart contract does not consume any gas, it's not nece // make the call to the contract const symbol = await uniswapToken.methods.symbol().call(); -console.log('Uniswap symbol:',symbol); +console.log('Uniswap symbol:', symbol); // ↳ Uniswap symbol: UNI // make the call to the contract @@ -221,12 +224,12 @@ Writing data to a smart contract consumes gas and requires the use of an account const to = '0xcf185f2F3Fe19D82bFdcee59E3330FD7ba5f27ce'; // value to transfer (1 with 18 decimals) -const value = web3.utils.toWei('1','ether'); +const value = web3.utils.toWei('1', 'ether'); // send the transaction => return the Tx receipt -const txReceipt = await uniswapToken.methods.transfer(to,value).send({from: account[0].address}); +const txReceipt = await uniswapToken.methods.transfer(to, value).send({ from: account[0].address }); -console.log('Tx hash:',txReceipt.transactionHash); +console.log('Tx hash:', txReceipt.transactionHash); // ↳ Tx hash: 0x14273c2b5781cc8f1687906c68bfc93482c603026d01b4fd37a04adb6217ad43 ``` @@ -261,12 +264,12 @@ import { Web3 } from 'web3'; const web3 = new Web3('wss://ethereum.publicnode.com'); // instantiate contract -const uniswapToken = new web3.eth.Contract(abi, address) +const uniswapToken = new web3.eth.Contract(abi, address); // create the subscription to all the 'Transfer' events const subscription = uniswapToken.events.Transfer(); // listen to the events -subscription.on('data',console.log); +subscription.on('data', console.log); // ↳ [{...},{...}, ...] live events will be printed in the console ``` diff --git a/docs/docs/guides/01_getting_started/return-formats.md b/docs/docs/guides/01_getting_started/return-formats.md new file mode 100644 index 00000000000..3afabcb6871 --- /dev/null +++ b/docs/docs/guides/01_getting_started/return-formats.md @@ -0,0 +1,121 @@ +--- +sidebar_position: 3 +sidebar_label: Return Formats +--- + +# Return Formats + +By default, Web3.js formats byte values as hexadecimal strings (e.g. `"0x221`") and number values as [`BigInt`s](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt). The default formats can be configured at the global level by updating the [`defaultReturnFormat` configuration option](/guides/web3_config/#defaultreturnformat). Many Web3.js functions (e.g. [`getBlock`](/api/web3-eth/function/getBlock), [`sendTransaction`](/api/web3-eth/function/sendTransaction)) accept an optional parameter named `returnFormat` of the [type `DataFormat`](/api/web3-types#DataFormat) that can be used to configure the format for data returned by that single function invocation. + +The following example demonstrates working with return formats: + +```ts +import { Block, FMT_BYTES, FMT_NUMBER, Numbers, Web3 } from 'web3'; + +const web3 = new Web3('https://eth.llamarpc.com'); + +// use the default return format +web3.eth.getBlock().then((block: Block) => { + console.log(`Block #${block.number} Hash: ${block.hash}`); +}); +// ↳ Block #20735255 Hash: 0xbaea6dbd46fa810a27be4c9eac782602f8efe7512fb30a8455c127b101a23e22 + +// specify the return format for a single function invocation +web3.eth + .getBlockNumber({ + bytes: FMT_BYTES.HEX, + number: FMT_NUMBER.HEX, + }) + .then((blockNumber: Numbers) => { + console.log(`Block #${blockNumber}`); + }); +// ↳ Block #0x13c6517 + +// configure default return format for the web3-eth package +web3.eth.defaultReturnFormat = { + bytes: FMT_BYTES.UINT8ARRAY, + number: FMT_NUMBER.HEX, +}; + +web3.eth.getBlock().then((block: Block) => { + console.log(`Block #${block.number} Hash: [${block.hash}]`); +}); +// ↳ Block #0x13c6517 Hash: [186,234,109,...,162,62,34] +``` + +The supported return formats are: + +- Bytes + - [`FMT_BYTES.HEX`](/api/web3-types/enum/FMT_BYTES#HEX): hexadecimal [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) (e.g. `"0xdd"`) + ```ts + web3.eth + .getBlock(undefined, undefined, { + bytes: FMT_BYTES.HEX, + number: FMT_NUMBER.BIGINT, + }) + .then((block: Block) => { + console.log(`Block hash: ${block.hash}`); + }); + // ↳ Block hash: 0xbaea6dbd46fa810a27be4c9eac782602f8efe7512fb30a8455c127b101a23e22 + ``` + - [`FMT_BYTES.UINT8ARRAY`](/api/web3-types/enum/FMT_BYTES#UINT8ARRAY): [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) (e.g. `[ 2, 33 ]`) + ```ts + web3.eth + .getBlock(undefined, undefined, { + bytes: FMT_BYTES.UINT8ARRAY, + number: FMT_NUMBER.BIGINT, + }) + .then((block: Block) => { + console.log(`Block hash: [${block.hash}]`); + }); + // ↳ Block hash: [186,234,109,...,162,62,34] + ``` +- Numbers + - [`FMT_NUMBER.BIGINT`](/api/web3-types/enum/FMT_NUMBER#BIGINT): [`BigInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) (e.g. `221n`) + ```ts + web3.eth + .getBlockNumber({ + bytes: FMT_BYTES.HEX, + number: FMT_NUMBER.BIGINT, + }) + .then((blockNumber: Numbers) => { + console.log(`Block #${blockNumber}`); + }); + // ↳ Block #20735255 + ``` + - [`FMT_NUMBER.HEX`](/api/web3-types/enum/FMT_NUMBER#HEX): hexadecimal [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) (e.g. `"0xdd"`) + ```ts + web3.eth + .getBlockNumber({ + bytes: FMT_BYTES.HEX, + number: FMT_NUMBER.HEX, + }) + .then((blockNumber: Numbers) => { + console.log(`Block #${blockNumber}`); + }); + // ↳ Block #0x13c6517 + ``` + - [`FMT_NUMBER.NUMBER`](/api/web3-types/enum/FMT_NUMBER#NUMBER): [`Number`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number) (e.g. `221`) + ```ts + web3.eth + .getBlockNumber({ + bytes: FMT_BYTES.HEX, + number: FMT_NUMBER.NUMBER, + }) + .then((blockNumber: Numbers) => { + console.log(`Block #${blockNumber}`); + }); + // ↳ Block #20735255 + ``` + - [`FMT_NUMBER.STR`](/api/web3-types/enum/FMT_NUMBER#STR): [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) (e.g. `"221"`) + ```ts + web3.eth + .getBlockNumber({ + bytes: FMT_BYTES.HEX, + number: FMT_NUMBER.STR, + }) + .then((blockNumber: Numbers) => { + console.log(`Block #${blockNumber}`); + }); + // ↳ Block #20735255 + ``` diff --git a/docs/docs/guides/web3_providers_guide/_category_.yml b/docs/docs/guides/02_web3_providers_guide/_category_.yml similarity index 100% rename from docs/docs/guides/web3_providers_guide/_category_.yml rename to docs/docs/guides/02_web3_providers_guide/_category_.yml diff --git a/docs/docs/guides/web3_providers_guide/eip6963.md b/docs/docs/guides/02_web3_providers_guide/eip6963.md similarity index 66% rename from docs/docs/guides/web3_providers_guide/eip6963.md rename to docs/docs/guides/02_web3_providers_guide/eip6963.md index 0965e440c9b..37577aa54d4 100644 --- a/docs/docs/guides/web3_providers_guide/eip6963.md +++ b/docs/docs/guides/02_web3_providers_guide/eip6963.md @@ -9,7 +9,7 @@ sidebar_label: 'EIP-6963: Multi Injected Provider Discovery' EIP-6963 proposes the "Multi Injected Provider Discovery" standard, which aims to enhance the discoverability and interaction with multiple injected Ethereum providers in a browser environment. Injected providers refer to browser extensions or other injected scripts that provide access to an Ethereum provider within the context of a web application. -Web3.js library has utility functions for discovery of injected providers using `requestEIP6963Providers()` and `onNewProviderDiscovered(eventDetails)`. +Web3.js library has utility functions for discovery of injected providers using `requestEIP6963Providers()` and `onNewProviderDiscovered(eventDetails)`. `onNewProviderDiscovered(eventDetails)` can be used to subscribe to events of provider discovery & providers map update and `requestEIP6963Providers()` returns Promise object that resolves to `Map` object containing list of providers. For updated providers `eip6963:providersMapUpdated` event is emitted and it has updated Map object. This event can be subscribed as mentioned earlier using `onNewProviderDiscovered(eventDetails)` @@ -17,8 +17,8 @@ Web3.js library has utility functions for discovery of injected providers using ```ts export interface EIP6963ProviderDetail { - info: EIP6963ProviderInfo; - provider: EIP1193Provider; + info: EIP6963ProviderInfo; + provider: EIP1193Provider; } ``` @@ -26,42 +26,45 @@ where `info` has details of provider containing UUID, name, Icon and RDNS as def ```ts export interface EIP6963ProviderInfo { - uuid: string; - name: string; - icon: string; - rdns: string; + uuid: string; + name: string; + icon: string; + rdns: string; } ``` `provider` in `EIP6963ProviderDetail` is `EIP1193Provider` and it contains actual provider that can be injected in web3 instance. -Following code snippet demonstrates usage of `requestEIP6963Providers()` function for providers discovery. +Following code snippet demonstrates usage of `requestEIP6963Providers()` function for providers discovery. ```ts -//Assuming multiple providers are installed in browser. +//Assuming multiple providers are installed in browser. import { Web3 } from 'web3'; // Following will subscribe to event that will be triggered when providers map is updated. -Web3.onNewProviderDiscovered((provider) => { - console.log(provider.detail); // This will log the populated providers map object, provider.detail has Map of all providers yet discovered - // add logic here for updating UI of your DApp +Web3.onNewProviderDiscovered(provider => { + console.log(provider.detail); // This will log the populated providers map object, provider.detail has Map of all providers yet discovered + // add logic here for updating UI of your DApp }); // Call the function and wait for the promise to resolve let providers = await Web3.requestEIP6963Providers(); for (const [key, value] of providers) { - console.log(value); + console.log(value); -/* Based on your DApp's logic show use list of providers and get selected provider's UUID from user for injecting its EIP6963ProviderDetail.provider EIP1193 object into web3 object */ + /* Based on your DApp's logic show use list of providers and get selected provider's UUID from user for injecting its EIP6963ProviderDetail.provider EIP1193 object into web3 object */ - if (value.info.name === 'MetaMask') { - const web3 = new Web3(value.provider); + if (value.info.name === 'MetaMask') { + const web3 = new Web3(value.provider); - // now you can use web3 object with injected provider - console.log(await web3.eth.getTransaction('0x82512812c11f56aa2474a16d5cc8916b73cd6ed96bf9b8defb3499ec2d9070cb')); - } + // now you can use web3 object with injected provider + console.log( + await web3.eth.getTransaction( + '0x82512812c11f56aa2474a16d5cc8916b73cd6ed96bf9b8defb3499ec2d9070cb', + ), + ); + } } - -``` \ No newline at end of file +``` diff --git a/docs/docs/guides/web3_providers_guide/events_listening.md b/docs/docs/guides/02_web3_providers_guide/events_listening.md similarity index 97% rename from docs/docs/guides/web3_providers_guide/events_listening.md rename to docs/docs/guides/02_web3_providers_guide/events_listening.md index a8e36a3cd22..ae0b809d4a5 100644 --- a/docs/docs/guides/web3_providers_guide/events_listening.md +++ b/docs/docs/guides/02_web3_providers_guide/events_listening.md @@ -26,42 +26,42 @@ import { Web3 } from 'web3'; const web3 = new Web3(/* PROVIDER*/); web3.provider.on('message', () => { - // ... + // ... }); web3.provider.on('connect', () => { - // ... + // ... }); web3.provider.on('disconnect', () => { - // ... + // ... }); web3.provider.on('accountsChanged', () => { - // ... + // ... }); web3.provider.on('chainChanged', () => { - // ... + // ... }); // it is possible to catch errors that could happen in the underlying connection Socket with the `error` event // and it is also used to catch the error when max reconnection attempts is exceeded // as in section: /docs/guides/web3_providers_guide/#error-message web3.provider.on('error', () => { - // ... + // ... }); // ... // for every event above `once` can be used to register to the event only once web3.provider.once('SUPPORTED_EVENT_NAME', () => { - // ... + // ... }); // And to unregister a listener `removeListener` could be called web3.provider.removeListener('SUPPORTED_EVENT_NAME', () => { - // ... + // ... }); ``` diff --git a/docs/docs/guides/web3_providers_guide/index.md b/docs/docs/guides/02_web3_providers_guide/index.md similarity index 74% rename from docs/docs/guides/web3_providers_guide/index.md rename to docs/docs/guides/02_web3_providers_guide/index.md index 726ccd8c229..b17c5622531 100644 --- a/docs/docs/guides/web3_providers_guide/index.md +++ b/docs/docs/guides/02_web3_providers_guide/index.md @@ -37,14 +37,14 @@ Keep reading to learn more about the different types of providers and how to use HTTP is a request-response protocol and does not support persistent connection, which means that HTTP providers are not suitable for use cases that require real-time [event subscriptions](/guides/events_subscriptions/). -``` ts title='Initialize an HTTP Provider' +```ts title='Initialize an HTTP Provider' import { Web3, HttpProvider } from 'web3'; // supply an HTTP provider as a URL string // highlight-next-line const web3 = new Web3('https://mainnet.infura.io/v3/YOUR_INFURA_ID'); -await web3.eth.getBlockNumber() +await web3.eth.getBlockNumber(); // ↳ 18849658n // OR @@ -53,7 +53,7 @@ await web3.eth.getBlockNumber() // highlight-next-line const web3_2 = new Web3(new HttpProvider('https://mainnet.infura.io/v3/YOUR_INFURA_ID')); -await web3.eth.getBlockNumber() +await web3.eth.getBlockNumber(); // ↳ 18849658n ``` @@ -65,23 +65,23 @@ HTTP providers can be configured by including an [`HttpProviderOptions`](/api/we import { Web3, HttpProvider } from 'web3'; const httpOptions = { - providerOptions: { - body: undefined, - cache: 'force-cache', - credentials: 'same-origin', - headers: { - 'Content-Type': 'application/json', - }, - integrity: undefined, - keepalive: true, - method: 'GET', - mode: 'same-origin', - redirect: 'error', - referrer: undefined, - referrerPolicy: 'same-origin', - signal: undefined, - window: undefined, - } as RequestInit, + providerOptions: { + body: undefined, + cache: 'force-cache', + credentials: 'same-origin', + headers: { + 'Content-Type': 'application/json', + }, + integrity: undefined, + keepalive: true, + method: 'GET', + mode: 'same-origin', + redirect: 'error', + referrer: undefined, + referrerPolicy: 'same-origin', + signal: undefined, + window: undefined, + } as RequestInit, }; const web3 = new Web3(new HttpProvider('https://eth.llamarpc.com', httpOptions)); @@ -91,14 +91,14 @@ const web3 = new Web3(new HttpProvider('https://eth.llamarpc.com', httpOptions)) WebSockets support a persistent connection between a client and a server, which means they are suitable for use cases that require real-time [event subscriptions](/guides/events_subscriptions/). -``` ts title='Initialize WS Provider' +```ts title='Initialize WS Provider' import { Web3, WebSocketProvider } from 'web3'; // supply a WebSocket provider as a URL string // highlight-next-line const web3 = new Web3('wss://mainnet.infura.io/ws/v3/YOUR_INFURA_ID'); -await web3.eth.getBlockNumber(); +await web3.eth.getBlockNumber(); // ↳ 18849658n // OR @@ -118,29 +118,29 @@ The [`WebSocketProvider` constructor](/api/web3-providers-ws/class/WebSocketProv ```ts title='Configuring a WebSocket Provider' // include both optional parameters const provider = new WebSocketProvider( - `ws://localhost:8545`, - { - headers: { - // for node services that require an API key in a header - 'x-api-key': '', - }, - }, - { - delay: 500, - autoReconnect: true, - maxAttempts: 10, - } + `ws://localhost:8545`, + { + headers: { + // for node services that require an API key in a header + 'x-api-key': '', + }, + }, + { + delay: 500, + autoReconnect: true, + maxAttempts: 10, + }, ); // OR include only ReconnectOptions const provider = new WebSocketProvider( - `ws://localhost:8545`, - {}, - { - delay: 500, - autoReconnect: true, - maxAttempts: 10, - } + `ws://localhost:8545`, + {}, + { + delay: 500, + autoReconnect: true, + maxAttempts: 10, + }, ); ``` @@ -148,7 +148,7 @@ const provider = new WebSocketProvider( IPC (inter-process communication) providers offer high-performance local communication and provide a faster alternative to HTTP providers. IPC providers are tailored for efficiency and excel in local environments, and also support real-time [event subscriptions](/guides/events_subscriptions/). -``` ts title='Initialize IPC Provider' +```ts title='Initialize IPC Provider' import { Web3 } from 'web3'; // highlight-next-line import { IpcProvider } from 'web3-providers-ipc'; @@ -164,37 +164,35 @@ await web3.eth.getBlockNumber(); The [`IpcProvider` constructor](/api/web3-providers-ipc/class/IpcProvider#constructor) accepts two optional parameters that can be used to configure the behavior of the `IpcProvider`: the first parameter must be of type [`SocketConstructorOpts`](https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules__types_node_net_d_._net_.socketconstructoropts.html) and the second parameter must be of type [`ReconnectOptions`](/api/web3/namespace/utils#ReconnectOptions). - - ```ts title='Configuring an IPC Provider' // include both optional parameters const provider = new IpcProvider( - '/Users/myuser/Library/Ethereum/geth.ipc', - { - writable: false, - }, - { - delay: 500, - autoReconnect: true, - maxAttempts: 10, - } + '/Users/myuser/Library/Ethereum/geth.ipc', + { + writable: false, + }, + { + delay: 500, + autoReconnect: true, + maxAttempts: 10, + }, ); // OR include only ReconnectOptions const provider = new IpcProvider( - '/Users/myuser/Library/Ethereum/geth.ipc', - {}, - { - delay: 500, - autoReconnect: true, - maxAttempts: 10, - } + '/Users/myuser/Library/Ethereum/geth.ipc', + {}, + { + delay: 500, + autoReconnect: true, + maxAttempts: 10, + }, ); ``` ### Injected Provider -Injected providers are supplied by an external third-party, most often a wallet or a web browser that is designed to be used with the Ethereum network. In addition to providing network connectivity, injected providers often supply one or more [accounts](/guides/wallet/). Web3.js supports any injected provider that is compliant with [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193). Injected providers support real-time [event subscriptions](/guides/events_subscriptions/). Continue reading for an [example](#injected-provider-1) of using an injected provider. +Injected providers are supplied by an external third-party, most often a wallet or a web browser that is designed to be used with the Ethereum network. In addition to providing network connectivity, injected providers often supply one or more [accounts](/guides/wallet). Web3.js supports any injected provider that is compliant with [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193). Injected providers support real-time [event subscriptions](/guides/events_subscriptions/). Continue reading for an [example](#injected-provider-1) of using an injected provider. ## Provider Origins @@ -239,36 +237,37 @@ const web3 = new Web3('https://eth-mainnet.alchemyapi.io/v2/your-api-key'); ### Injected Provider -Injected providers are supplied by an external third-party, most often a wallet or a web browser that is designed to be used with the Ethereum network. In addition to providing network connectivity, injected providers often supply one or more [accounts](/guides/wallet/). Web3.js supports any injected provider that is compliant with [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193) and has been tested with multiple EIP-1193 providers, including [MetaMask](https://docs.metamask.io/wallet/reference/provider-api/), [Hardhat](https://hardhat.org/hardhat-runner/docs/advanced/hardhat-runtime-environment), and [Incubed (IN3)](https://in3.readthedocs.io/en/develop/index.html). +Injected providers are supplied by an external third-party, most often a wallet or a web browser that is designed to be used with the Ethereum network. In addition to providing network connectivity, injected providers often supply one or more [accounts](/guides/wallet). Web3.js supports any injected provider that is compliant with [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193) and has been tested with multiple EIP-1193 providers, including [MetaMask](https://docs.metamask.io/wallet/reference/provider-api/), [Hardhat](https://hardhat.org/hardhat-runner/docs/advanced/hardhat-runtime-environment), and [Incubed (IN3)](https://in3.readthedocs.io/en/develop/index.html). :::note The following example should be run in a browser with the MetaMask extension installed. ::: ```html title='E.g, Metamask' - + ``` diff --git a/docs/docs/guides/wallet/index.md b/docs/docs/guides/03_wallet/index.md similarity index 78% rename from docs/docs/guides/wallet/index.md rename to docs/docs/guides/03_wallet/index.md index ef75a663ec8..d93ba737a50 100644 --- a/docs/docs/guides/wallet/index.md +++ b/docs/docs/guides/03_wallet/index.md @@ -1,11 +1,11 @@ --- -sidebar_position: 1 -sidebar_label: 'Introduction to Accounts & Wallets' +sidebar_position: 3 +sidebar_label: '🔑 Accounts & Wallets' --- # Introduction to Accounts & Wallets -The concept of an [account](https://ethereum.org/en/developers/docs/accounts/) is central to Ethereum and it can be used to refer to two types of entities that are native to Ethereum: externally-owned accounts and contract accounts. This document relates _exclusively_ to **externally-owned accounts**. An externally-owned account is associated with a "[key pair](https://ethereum.org/en/developers/docs/accounts/#externally-owned-accounts-and-key-pairs)", which is a general concept that is related to [public-key cryptography](https://en.wikipedia.org/wiki/Public-key_cryptography). The key pair consists of a private key, which must always be kept secret, and a public key, which is used to derive a public identifier (address) for an account. Ethereum accounts have an [ETH](https://ethereum.org/en/developers/docs/intro-to-ethereum/#eth) balance, which can be [transferred](/guides/wallet/transactions) to other accounts or used to pay for interactions with [smart contracts](/guides/smart_contracts/smart_contracts_guide). Anyone with access to an account's private key has the ability to control that account's ETH balance, so it's important that an account's private key is always kept secret. In addition to the general guidelines for [protecting private keys](https://ethereum.org/en/security/#protect-private-keys/), private keys should never be included in client-side code that can be seen by end users and should never be committed to code repositories. +The concept of an [account](https://ethereum.org/en/developers/docs/accounts/) is central to Ethereum and it can be used to refer to two types of entities that are native to Ethereum: externally-owned accounts and contract accounts. This document relates _exclusively_ to **externally-owned accounts**. An externally-owned account is associated with a "[key pair](https://ethereum.org/en/developers/docs/accounts/#externally-owned-accounts-and-key-pairs)", which is a general concept that is related to [public-key cryptography](https://en.wikipedia.org/wiki/Public-key_cryptography). The key pair consists of a private key, which must always be kept secret, and a public key, which is used to derive a public identifier (address) for an account. Ethereum accounts have an [ETH](https://ethereum.org/en/developers/docs/intro-to-ethereum/#eth) balance, which can be [transferred](/guides/transactions/transactions) to other accounts or used to pay for interactions with [smart contracts](/guides/smart_contracts/smart_contracts_guide). Anyone with access to an account's private key has the ability to control that account's ETH balance, so it's important that an account's private key is always kept secret. In addition to the general guidelines for [protecting private keys](https://ethereum.org/en/security/#protect-private-keys/), private keys should never be included in client-side code that can be seen by end users and should never be committed to code repositories. In the context of this document, the term "wallet" refers to a collection of accounts and should not be confused with [wallet "applications"](https://ethereum.org/en/wallets/). @@ -29,7 +29,7 @@ console.log(account); */ // use the account to sign a message -const signature = account.sign("Hello, Web3.js!"); +const signature = account.sign('Hello, Web3.js!'); /* ↳ { message: 'Hello, Web3.js!', @@ -48,7 +48,7 @@ In addition to generating new random accounts, the Account package can also be u ```js // load an existing account from its private key -const account = web3.eth.accounts.privateKeyToAccount(""); +const account = web3.eth.accounts.privateKeyToAccount(''); console.log(account); /* ↳ @@ -62,7 +62,7 @@ console.log(account); */ // use the account to sign a message -const signature = account.sign("Hello, Web3.js!"); +const signature = account.sign('Hello, Web3.js!'); /* ↳ { message: 'Hello, Web3.js!', @@ -77,30 +77,30 @@ const signature = account.sign("Hello, Web3.js!"); ### Account Methods -The following is a list of [`Accounts`](/libdocs/Accounts) methods in the `web3.eth.accounts` package with descriptions and example usage: - -- [create](/libdocs/Accounts#create) -- [decrypt](/libdocs/Accounts#decrypt) -- [encrypt](/libdocs/Accounts#encrypt) -- [hashMessage](/libdocs/Accounts#hashMessage) -- [parseAndValidatePrivateKey](/libdocs/Accounts#libdocs/Accounts#parseandvalidateprivatekey) -- [privateKeyToAccount](/libdocs/Accounts#privatekeytoaccount) -- [privateKeyToAddress](/libdocs/Accounts#privatekeytoaddress) -- [privateKeyToPublicKey](/libdocs/Accounts#privatekeytopublickey) -- [recover](/libdocs/Accounts#recover) -- [recoverTransaction](/libdocs/Accounts#recovertransaction) -- [sign](/libdocs/Accounts#sign) -- [signTransaction](/libdocs/Accounts#signtransaction) +The following is a list of [`Accounts`](/libdocs/Accounts) methods in the `web3.eth.accounts` package with descriptions and example usage: + +- [create](/libdocs/Accounts#create) +- [decrypt](/libdocs/Accounts#decrypt) +- [encrypt](/libdocs/Accounts#encrypt) +- [hashMessage](/libdocs/Accounts#hashMessage) +- [parseAndValidatePrivateKey](/libdocs/Accounts#libdocs/Accounts#parseandvalidateprivatekey) +- [privateKeyToAccount](/libdocs/Accounts#privatekeytoaccount) +- [privateKeyToAddress](/libdocs/Accounts#privatekeytoaddress) +- [privateKeyToPublicKey](/libdocs/Accounts#privatekeytopublickey) +- [recover](/libdocs/Accounts#recover) +- [recoverTransaction](/libdocs/Accounts#recovertransaction) +- [sign](/libdocs/Accounts#sign) +- [signTransaction](/libdocs/Accounts#signtransaction) ## Wallets -A Web3.js wallet is a collection of accounts and is represented with the [`Wallet`](/api/web3-eth-accounts/class/Wallet) class. When a wallet is used to track an account, that account is added to an internal context (i.e. [`Web3Context`](/api/web3-core/class/Web3Context/)), which makes it easier to use that account in the future - this is described in more detail in the [transactions tutorial](/guides/wallet/transactions). The following snippet demonstrates creating a wallet with 2 new random accounts and using the second account to sign a message: +A Web3.js wallet is a collection of accounts and is represented with the [`Wallet`](/api/web3-eth-accounts/class/Wallet) class. When a wallet is used to track an account, that account is added to an internal context (i.e. [`Web3Context`](/api/web3-core/class/Web3Context/)), which makes it easier to use that account in the future - this is described in more detail in the [transactions tutorial](/guides/transactions/transactions). The following snippet demonstrates creating a wallet with 2 new random accounts and using the second account to sign a message: ```js // create a wallet with 2 new random accounts const wallet = web3.eth.accounts.wallet.create(2); -console.log(wallet) +console.log(wallet); /* ↳ Wallet(2) [ { @@ -131,7 +131,7 @@ Wallet(2) [ */ // use the second account in the wallet to sign a message -const signature = wallet[1].sign("Hello, Web3.js!"); +const signature = wallet[1].sign('Hello, Web3.js!'); // wallet accounts can also be accessed with the "at" and "get" methods // wallet.at(1).sign("Hello, Web3.js!") // wallet.get(1).sign("Hello, Web3.js!") @@ -154,7 +154,7 @@ In addition to generating new random accounts, a wallet can also be used to load ```js // create a wallet with a single existing account -const wallet = web3.eth.accounts.wallet.add(""); +const wallet = web3.eth.accounts.wallet.add(''); console.log(wallet); /* ↳ @@ -281,23 +281,23 @@ Wallet(3) [ ### Wallet Methods -The following is a list of [`Wallet`](/libdocs/Wallet) methods in the `web3.eth.accounts.wallet` package with description and example usage: +The following is a list of [`Wallet`](/libdocs/Wallet) methods in the `web3.eth.accounts.wallet` package with description and example usage: -- [add](/libdocs/Wallet#add) -- [clear](/libdocs/Wallet#clear) -- [create](/libdocs/Wallet#create) -- [decrypt](/libdocs/Wallet#decrypt) -- [encrypt](/libdocs/Wallet#encrypt) -- [get](/libdocs/Wallet#get) -- [load](/libdocs/Wallet#load) -- [remove](/libdocs/Wallet#remove) -- [save](/libdocs/Wallet#save) -- [getStorage](/libdocs/Wallet#getStorage) +- [add](/libdocs/Wallet#add) +- [clear](/libdocs/Wallet#clear) +- [create](/libdocs/Wallet#create) +- [decrypt](/libdocs/Wallet#decrypt) +- [encrypt](/libdocs/Wallet#encrypt) +- [get](/libdocs/Wallet#get) +- [load](/libdocs/Wallet#load) +- [remove](/libdocs/Wallet#remove) +- [save](/libdocs/Wallet#save) +- [getStorage](/libdocs/Wallet#getStorage) ## Next Steps This document is just an introduction to Web3.js accounts and wallets. Here are some suggestions for what to review next: -- Learn how to [transfer ETH](/guides/wallet/transactions) from one account to another. -- Build a front-end application that uses [injected accounts](/guides/wallet/metamask-vanilla) from the MetaMask wallet. -- Use an account to [deploy and interact with a smart contract](/guides/smart_contracts/smart_contracts_guide). +- Learn how to [transfer ETH](/guides/transactions/transactions) from one account to another. +- Build a front-end application that uses [injected accounts](/guides/dapps/metamask-vanilla) from the MetaMask wallet. +- Use an account to [deploy and interact with a smart contract](/guides/smart_contracts/smart_contracts_guide). diff --git a/docs/docs/guides/web3_upgrade_guide/1.x/_category_.yml b/docs/docs/guides/04_transactions/_category_.yml similarity index 53% rename from docs/docs/guides/web3_upgrade_guide/1.x/_category_.yml rename to docs/docs/guides/04_transactions/_category_.yml index 7723475cb40..99d68c8c3bc 100644 --- a/docs/docs/guides/web3_upgrade_guide/1.x/_category_.yml +++ b/docs/docs/guides/04_transactions/_category_.yml @@ -1,5 +1,5 @@ -label: 'Upgrade from 1.x' +label: '🔄 Transactions' collapsible: true collapsed: true link: null -position: 1 \ No newline at end of file +position: 4 diff --git a/docs/docs/guides/wallet/transactions.md b/docs/docs/guides/04_transactions/transactions.md similarity index 81% rename from docs/docs/guides/wallet/transactions.md rename to docs/docs/guides/04_transactions/transactions.md index dfc92765844..8b830554593 100644 --- a/docs/docs/guides/wallet/transactions.md +++ b/docs/docs/guides/04_transactions/transactions.md @@ -1,11 +1,11 @@ --- -sidebar_position: 2 +sidebar_position: 1 sidebar_label: 'Tutorial: Sending Transactions' --- # Sending Transactions -This tutorial will walk through the process of using accounts to send transactions on a [development network](https://ethereum.org/en/developers/docs/development-networks/), including how to subscribe to the events associated with a transaction. The topics covered in this tutorial include basic concepts of [Ethereum](https://ethereum.org/), such as [accounts](/guides/wallet/), [denominations of ether](https://ethereum.org/en/developers/docs/intro-to-ether/#denominations), [transactions](https://ethereum.org/en/developers/docs/transactions/), and [gas fees](https://ethereum.org/en/developers/docs/gas/), as well as the basics of the [Hardhat](https://hardhat.org/) development environment. +This tutorial will walk through the process of using accounts to send transactions on a [development network](https://ethereum.org/en/developers/docs/development-networks/), including how to subscribe to the events associated with a transaction. The topics covered in this tutorial include basic concepts of [Ethereum](https://ethereum.org/), such as [accounts](/guides/wallet), [denominations of ether](https://ethereum.org/en/developers/docs/intro-to-ether/#denominations), [transactions](https://ethereum.org/en/developers/docs/transactions/), and [gas fees](https://ethereum.org/en/developers/docs/gas/), as well as the basics of the [Hardhat](https://hardhat.org/) development environment. ## Overview @@ -19,7 +19,7 @@ Here is a high-level overview of the steps we will be taking in this tutorial: 6. Send a raw transaction :::tip -If you encounter any issues while following this guide or have any questions, don't hesitate to seek assistance. Our friendly community is ready to help you out! Join our [Discord](https://discord.gg/F4NUfaCC) server and head to the **#web3js-general** channel to connect with other developers and get the support you need. +If you encounter any issues while following this guide or have any questions, don't hesitate to seek assistance. Our friendly community is ready to help you out! Join our [Discord](https://discord.gg/F4NUfaCC) server and head to the **#web3js-general** channel to connect with other developers and get the support you need. ::: ## Step 1: Prerequisites @@ -105,19 +105,19 @@ The Hardhat development network needs to remain running in the terminal that was Next, create a new file called `index.js` in your project directory and add the following code to it: ```js -const { Web3 } = require("web3"); +const { Web3 } = require('web3'); -const web3 = new Web3("http://127.0.0.1:8545/"); +const web3 = new Web3('http://127.0.0.1:8545/'); // Log the chain ID to the console web3.eth - .getChainId() - .then((result) => { - console.log("Chain ID: " + result); - }) - .catch((error) => { - console.error(error); - }); + .getChainId() + .then(result => { + console.log('Chain ID: ' + result); + }) + .catch(error => { + console.error(error); + }); ``` This code sets up a Web3.js connection to the Hardhat development network and logs the chain ID to the console. @@ -147,51 +147,45 @@ Replace the value of the `privateKey` variable with one of the private keys of t ::: ```js -const { Web3 } = require("web3"); +const { Web3 } = require('web3'); async function main() { - const web3 = new Web3("http://127.0.0.1:8545/"); - - // create a new Web3.js account object with the private key of a Hardhat test account - const privateKey = ""; - // the account is created with a wallet, which makes it easier to use - const sender = web3.eth.accounts.wallet.add(privateKey)[0]; - - // generate a new random Web3.js account object to receive the transaction - const receiver = web3.eth.accounts.create(); - - // log initial balances - console.log( - "Initial sender balance:", - // account balance in wei - await web3.eth.getBalance(sender.address) - ); - console.log( - "Initial receiver balance:", - // account balance in wei - await web3.eth.getBalance(receiver.address) - ); - - // sign and send the transaction - const receipt = await web3.eth.sendTransaction({ - from: sender.address, - to: receiver.address, - // amount in wei - value: 100, - }); - - // log transaction receipt - console.log(receipt); - - // log final balances - console.log( - "Final sender balance:", - await web3.eth.getBalance(sender.address) - ); - console.log( - "Final receiver balance:", - await web3.eth.getBalance(receiver.address) - ); + const web3 = new Web3('http://127.0.0.1:8545/'); + + // create a new Web3.js account object with the private key of a Hardhat test account + const privateKey = ''; + // the account is created with a wallet, which makes it easier to use + const sender = web3.eth.accounts.wallet.add(privateKey)[0]; + + // generate a new random Web3.js account object to receive the transaction + const receiver = web3.eth.accounts.create(); + + // log initial balances + console.log( + 'Initial sender balance:', + // account balance in wei + await web3.eth.getBalance(sender.address), + ); + console.log( + 'Initial receiver balance:', + // account balance in wei + await web3.eth.getBalance(receiver.address), + ); + + // sign and send the transaction + const receipt = await web3.eth.sendTransaction({ + from: sender.address, + to: receiver.address, + // amount in wei + value: 100, + }); + + // log transaction receipt + console.log(receipt); + + // log final balances + console.log('Final sender balance:', await web3.eth.getBalance(sender.address)); + console.log('Final receiver balance:', await web3.eth.getBalance(receiver.address)); } main(); @@ -241,51 +235,51 @@ Note that the sender's balance has decreased by more than the amount that was tr In the previous example, the `transaction-receipt.js` script demonstrates sending a transaction to the network and reviewing the results after it has been successfully received. However, there are more stages to the [transaction lifecycle](https://ethereum.org/en/developers/docs/transactions/#transaction-lifecycle) and Web3.js makes it easy to subscribe to these lifecycle stages and create custom handlers for each one. Web3.js supports subscriptions for the following transaction lifecycle events: -- Sending - Web3.js is preparing to send the transaction to the network -- Sent - the transaction has been sent to the network -- Transaction hash - a hash of the transaction has been generated -- Receipt - the transaction has been included in a block -- Confirmation - the block in which the transaction was included has been [finalized](https://ethereum.org/en/glossary/#finality) -- Error - a problem with the transaction was encountered +- Sending - Web3.js is preparing to send the transaction to the network +- Sent - the transaction has been sent to the network +- Transaction hash - a hash of the transaction has been generated +- Receipt - the transaction has been included in a block +- Confirmation - the block in which the transaction was included has been [finalized](https://ethereum.org/en/glossary/#finality) +- Error - a problem with the transaction was encountered Create a new file called `transaction-events.js` in your project directory and add the following code to it: ```js -const { Web3 } = require("web3"); +const { Web3 } = require('web3'); -const web3 = new Web3("http://127.0.0.1:8545/"); +const web3 = new Web3('http://127.0.0.1:8545/'); -const privateKey = ""; +const privateKey = ''; const sender = web3.eth.accounts.wallet.add(privateKey)[0]; const receiver = web3.eth.accounts.create(); web3.eth - .sendTransaction({ - from: sender.address, - to: receiver.address, - value: 100, - }) - .on("sending", (sending) => { - console.log("Sending:", sending); - }) - .on("sent", (sent) => { - console.log("Sent:", sent); - }) - .on("transactionHash", (transactionHash) => { - console.log("Transaction Hash:", transactionHash); - }) - .on("receipt", (receipt) => { - console.log("Receipt:", receipt); - }) - .on("confirmation", (confirmation) => { - console.log("Confirmation:", confirmation); - process.exit(0); - }) - .on("error", (error) => { - console.log("Error:", error); - process.exit(1); - }); + .sendTransaction({ + from: sender.address, + to: receiver.address, + value: 100, + }) + .on('sending', sending => { + console.log('Sending:', sending); + }) + .on('sent', sent => { + console.log('Sent:', sent); + }) + .on('transactionHash', transactionHash => { + console.log('Transaction Hash:', transactionHash); + }) + .on('receipt', receipt => { + console.log('Receipt:', receipt); + }) + .on('confirmation', confirmation => { + console.log('Confirmation:', confirmation); + process.exit(0); + }) + .on('error', error => { + console.log('Error:', error); + process.exit(1); + }); ``` Execute the following command to run the code from `transaction-events.js`: @@ -406,37 +400,35 @@ The previous examples have relied on the helpful Web3.js context to automaticall Create a new file called `raw-transaction.js` in your project directory and add the following code to it: ```js -const { Web3 } = require("web3"); +const { Web3 } = require('web3'); async function main() { - const web3 = new Web3("http://127.0.0.1:8545/"); - - const privateKey = ""; - // import the Hardhat test account without the use of a wallet - const sender = web3.eth.accounts.privateKeyToAccount(privateKey); - - const receiver = web3.eth.accounts.create(); - - // used to calculate the transaction's maxFeePerGas - const block = await web3.eth.getBlock(); - - const transaction = { - from: sender.address, - to: receiver.address, - value: 100, - // the following two properties must be included in raw transactions - maxFeePerGas: block.baseFeePerGas * 2n, - maxPriorityFeePerGas: 100000, - }; - - const signedTransaction = await web3.eth.accounts.signTransaction( - transaction, - sender.privateKey - ); - const receipt = await web3.eth.sendSignedTransaction( - signedTransaction.rawTransaction - ); - console.log(receipt); + const web3 = new Web3('http://127.0.0.1:8545/'); + + const privateKey = ''; + // import the Hardhat test account without the use of a wallet + const sender = web3.eth.accounts.privateKeyToAccount(privateKey); + + const receiver = web3.eth.accounts.create(); + + // used to calculate the transaction's maxFeePerGas + const block = await web3.eth.getBlock(); + + const transaction = { + from: sender.address, + to: receiver.address, + value: 100, + // the following two properties must be included in raw transactions + maxFeePerGas: block.baseFeePerGas * 2n, + maxPriorityFeePerGas: 100000, + }; + + const signedTransaction = await web3.eth.accounts.signTransaction( + transaction, + sender.privateKey, + ); + const receipt = await web3.eth.sendSignedTransaction(signedTransaction.rawTransaction); + console.log(receipt); } main(); diff --git a/docs/docs/guides/04_transactions/tx-types.md b/docs/docs/guides/04_transactions/tx-types.md new file mode 100644 index 00000000000..33152103aec --- /dev/null +++ b/docs/docs/guides/04_transactions/tx-types.md @@ -0,0 +1,279 @@ +--- +sidebar_position: 2 +sidebar_label: 'Transaction Types' +--- + +# Transactions + +In this tutorial, we will explore how to send different types of [transactions](https://ethereum.org/en/developers/docs/transactions/) using web3.js, focusing on Ethereum's evolving transaction formats. We'll start with [legacy transactions (Transaction Type 0)](#transaction-type-0-legacy). Next, we'll delve into Transaction [Type 1 (EIP-2930)](#transaction-type-1-eip-2930), which introduces access lists to optimize gas usage. Finally, we'll cover [Transaction Type 2 (EIP-1559)](#transaction-type-2-eip-1559), the current default, which allows users to specify maximum fees and priority tips for more efficient and cost-effective transactions. Each section will include practical code examples to demonstrate sending raw transactions and interacting with ERC20 tokens on the Sepolia test network + +:::note +Web3.js uses transaction type 2 by default +::: + +## Transaction Type 0 (Legacy) + +### Raw Transaction + +A Legacy Transaction refers to a transaction that was created using an older version of Ethereum's transaction format, also known as "transaction type 0". This transaction format was used before the EIP-1559 upgrade, which was implemented in August 2021. + +```ts +import { Web3 } from 'web3'; + +const web3 = new Web3('https://rpc2.sepolia.org'); // RPC node url + +async function txLegacy() { + const wallet = web3.eth.wallet.add('YOUR_PRIVATE_KEY'); // make sure you have funds + + const sender = wallet[0].address; + const recipient = '0x807BFe4940016B5a7FdA19482042917B02e68359'; + const value = 1; // wei + const nonce = await web3.eth.getTransactionCount(sender); + const gas = 21000; + const gasPrice = await web3.eth.getGasPrice(); + + const tx = { + from: sender, + to: recipient, + value, + nonce, + gas, + gasPrice, + // highlight-next-line + type: 0, + }; + + const txReceipt = await web3.eth.sendTransaction(tx); + console.log('Tx hash', txReceipt.transactionHash); +} + +txLegacy(); +``` + +### ERC20 Interaction + +```ts +import { Web3 } from 'web3'; + +const web3 = new Web3('https://rpc2.sepolia.org'); + +//WETH token in Sepolia https://sepolia.etherscan.io/address/0xfff9976782d46cc05630d1f6ebab18b2324d6b14#code +const ADDRESS_WETH_SEPOLIA = '0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14'; +const ABI = [ + { + constant: false, + inputs: [ + { + name: 'dst', + type: 'address', + }, + { + name: 'wad', + type: 'uint256', + }, + ], + name: 'transfer', + outputs: [ + { + name: '', + type: 'bool', + }, + ], + payable: false, + stateMutability: 'nonpayable', + type: 'function', + }, +]; + +async function transfer() { + //initialize wallet + const wallet = web3.eth.accounts.wallet.add('YOUR_PRIVATE_KEY'); //make sure you have WETH tokens in the Sepolia network + //you can swap Sepolia tokens for WETH here https://app.uniswap.org/swap?chain=sepolia + + //initialize WETH contract in sepolia + const myERC20 = new web3.eth.Contract(ABI, ADDRESS_WETH_SEPOLIA); + + const TO = '0xEA9eEca67682Cd9c6Ce3DdD1681049D7A897289F'; //address to send the tokens to + const VALUE = 1; //wei value, dont forget to multiply by decimals + + //send transfer and specify the type + const txReceipt = await myERC20.methods.transfer(TO, VALUE).send({ + from: wallet[0].address, + // highlight-next-line + type: 0, + }); + + console.log(txReceipt.transactionHash); + //=> 0x5f2087c22166f3a1909c40ce537dd564dc3d4c70c5be02f35c6406a628123b16 +} + +transfer(); +``` + +## Transaction Type 1 (EIP-2930) + +This EIP was introduced in April 2021, it introduces a feature called 'Access List.' This improvement allows saving gas on cross-contract calls by declaring in advance which contract and storage slots will be accessed. + +### Raw Transaction + +```ts +import { Web3 } from 'web3'; + +const web3 = new Web3('https://rpc2.sepolia.org'); + +async function txEIP2930() { + const wallet = web3.eth.wallet.add('YOUR_PRIVATE_KEY'); + + const sender = wallet[0].address; + const contractAddress1 = '0x...'; + const gas = 500000; //could be higher + const gasPrice = await web3.eth.getGasPrice(); + const data = '0x9a67c8b100000000000000000000000000000000000000000000000000000000000004d0'; + + // highlight-start + //create access list using web3.eth + const accessListData = await web3.eth.createAccessList({ + from: sender, + to: contractAddress1, + data, + }); + // highlight-end + + console.log(accessListData); + /* + => + { + // highlight-start + "accessList": [ + { + "address": "0x15859bdf5aff2080a9968f6a410361e9598df62f", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + // highlight-end + "gasUsed": "0x7671" + } + */ + + const tx = { + from: sender, + to: contractAddress1, //the contract we are calling + data, + gas, + gasPrice, + // highlight-next-line + type: 1, + // highlight-next-line + accessList: accessListData.accessList, //access the object `accessList` + }; + + const txReceipt = await web3.eth.sendTransaction(tx); + + console.log('Tx hash', txReceipt.transactionHash); +} + +txEIP2930(); +``` + +## Transaction Type 2 (EIP-1559) + +When a user creates an EIP-1559 transaction, they specify the maximum fee they are willing to pay `maxFeePerGas` as well as a tip `maxPriorityFeePerGas` to incentivize the miner. The actual fee paid by the user is then determined by the network based on the current demand for block space and the priority of the transaction. + +### Raw Transaction + +```ts +import { Web3 } from 'web3'; + +const web3 = new Web3('https://rpc2.sepolia.org'); + +async function txEIP1559() { + const wallet = web3.eth.wallet.add('YOUR_PRIVATE_KEY'); //make sure you have funds + + const sender = wallet[0].address; + const recipient = '0x807BFe4940016B5a7FdA19482042917B02e68359'; + const value = 1; //wei + const nonce = await web3.eth.getTransactionCount(sender); + const gasLimit = 21000; + const maxFeePerGas = Number((await web3.eth.calculateFeeData()).maxFeePerGas); + const maxPriorityFeePerGas = Number((await web3.eth.calculateFeeData()).maxPriorityFeePerGas); + + const tx = { + from: sender, + to: recipient, + value, + nonce, + gasLimit, + maxFeePerGas, + maxPriorityFeePerGas, + // highlight-next-line + type: 2, + }; + + const txReceipt = await web3.eth.sendTransaction(tx); + console.log('Tx hash', txReceipt.transactionHash); +} + +txEIP1559(); +``` + +### ERC20 Interaction + +```ts +import { Web3 } from 'web3'; + +const web3 = new Web3('https://rpc2.sepolia.org'); + +//WETH token in Sepolia https://sepolia.etherscan.io/address/0xfff9976782d46cc05630d1f6ebab18b2324d6b14#code +const ADDRESS_WETH_SEPOLIA = '0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14'; +const ABI = [ + { + constant: false, + inputs: [ + { + name: 'dst', + type: 'address', + }, + { + name: 'wad', + type: 'uint256', + }, + ], + name: 'transfer', + outputs: [ + { + name: '', + type: 'bool', + }, + ], + payable: false, + stateMutability: 'nonpayable', + type: 'function', + }, +]; + +async function transfer() { + //initialize wallet + const wallet = web3.eth.accounts.wallet.add('YOUR_PRIVATE_KEY'); //make sure you have WETH tokens in the Sepolia network + //you can swap Sepolia tokens for WETH here https://app.uniswap.org/swap?chain=sepolia + + //initialize WETH contract in sepolia + const myERC20 = new web3.eth.Contract(ABI, ADDRESS_WETH_SEPOLIA); + + const TO = '0xEA9eEca67682Cd9c6Ce3DdD1681049D7A897289F'; //address to send the tokens to + const VALUE = 1; //wei value, dont forget to multiply by decimals + + //send transfer and specify the type + const txReceipt = await myERC20.methods.transfer(TO, VALUE).send({ + from: wallet[0].address, + // highlight-next-line + type: 2, + }); + + console.log(txReceipt.transactionHash); + //=> 0x174bc88023be4af431fad1693a59f7a41135238510cdcd00f15f6409b5471d77 +} + +transfer(); +``` diff --git a/docs/docs/guides/smart_contracts/_category_.yml b/docs/docs/guides/05_smart_contracts/_category_.yml similarity index 86% rename from docs/docs/guides/smart_contracts/_category_.yml rename to docs/docs/guides/05_smart_contracts/_category_.yml index 8a1d21c75b4..96b97cea9d2 100644 --- a/docs/docs/guides/smart_contracts/_category_.yml +++ b/docs/docs/guides/05_smart_contracts/_category_.yml @@ -2,4 +2,4 @@ label: '📜 Smart Contracts' collapsible: true collapsed: true link: null -position: 4 +position: 5 diff --git a/docs/docs/guides/smart_contracts/infer_contract_types.md b/docs/docs/guides/05_smart_contracts/infer_contract_types.md similarity index 82% rename from docs/docs/guides/smart_contracts/infer_contract_types.md rename to docs/docs/guides/05_smart_contracts/infer_contract_types.md index 3e7d4bfc7f1..b5288412522 100644 --- a/docs/docs/guides/smart_contracts/infer_contract_types.md +++ b/docs/docs/guides/05_smart_contracts/infer_contract_types.md @@ -7,7 +7,7 @@ sidebar_label: 'Infer Contract Types from JSON Artifact (TypeScript)' :::tip 📝 This article is for **TypeScript** developers. So, if you are using JavaScript, you do not need to read this. -However, web3.js version 4.x has been rewritten in TypeScript. And we encorage you to use its strongly-typed features with TypeScript. +However, web3.js version 4.x has been rewritten in TypeScript. And we encorage you to use its strongly-typed features with TypeScript. ::: Web3.js is a popular library used for interacting with EVM blockchains. One of its key features is the ability to invoke EVM smart contracts deployed on the blockchain. In this blog post, we will show how to interact with the smart contract in **TypeScript**, with a special focus on how to infer types from JSON artifact files. @@ -21,14 +21,14 @@ import { Contract, Web3 } from 'web3'; import ERC20 from './node_modules/@openzeppelin/contracts/build/contracts/ERC20.json'; (async function () { - const web3 = new Web3('rpc url'); + const web3 = new Web3('rpc url'); - const contract = new Contract(ERC20.abi, '0x7af963cF6D228E564e2A0aA0DdBF06210B38615D', web3); + const contract = new Contract(ERC20.abi, '0x7af963cF6D228E564e2A0aA0DdBF06210B38615D', web3); - const holder = '0xa8F6eB216e26C1F7d924A801E46eaE0CE8ed1A0A'; + const holder = '0xa8F6eB216e26C1F7d924A801E46eaE0CE8ed1A0A'; - //Error because Contract doesn't know what methods exists - const balance = await contract.methods.balanceOf(holder).call(); + //Error because Contract doesn't know what methods exists + const balance = await contract.methods.balanceOf(holder).call(); })(); ``` @@ -72,19 +72,22 @@ const artifactContent = fs.readFileSync('./artifacts.json', 'utf-8'); const artifacts: string[] = JSON.parse(artifactContent); (async function () { - for (const artifact of artifacts) { - let content; - try { - //try to import from node_modules - content = JSON.stringify(await import(artifact)); - } catch (e) { - //try to read as path on disc - content = fs.readFileSync(artifact, 'utf-8'); - } - const filename = path.basename(artifact, '.json'); - //create and write typescript file - fs.writeFileSync(path.join(destination, filename + '.ts'), `const artifact = ${content.trimEnd()} as const; export default artifact;`); - } + for (const artifact of artifacts) { + let content; + try { + //try to import from node_modules + content = JSON.stringify(await import(artifact)); + } catch (e) { + //try to read as path on disc + content = fs.readFileSync(artifact, 'utf-8'); + } + const filename = path.basename(artifact, '.json'); + //create and write typescript file + fs.writeFileSync( + path.join(destination, filename + '.ts'), + `const artifact = ${content.trimEnd()} as const; export default artifact;`, + ); + } })(); ``` @@ -98,10 +101,12 @@ To use this script, just create an `artifacts.json` file at the root of your pro ] ``` -and run the script with -```bash +and run the script with + +```bash node -r ts-node/register + + + +
+
+
+
+ + + +``` + +Review the comments in `index.html`. This document imports Web3.js, creates several placeholders that will be used to display network information, and defines a script that checks for an [injected provider](/guides/web3_providers_guide/#injected-provider). If an injected provider is found, it's used to construct a new `Web3` instance and connect to the Ethereum network. A check is performed to ensure that the injected provider is coming from MetaMask and the result of this check is displayed to the user. Once connected through the injected provider, the script updates the placeholders with the chain ID and latest block number, and creates an event subscription to update the block number as new blocks are created. If no injected provider is found, the user is instructed to install MetaMask. + +To start a local HTTP server to serve `index.html`, execute the following command in the project directory: + +```bash +npx watch-http-server . +``` + +The output should look like: + +``` +Websocket Server Listening on Port: 8086 +Starting up http-server, serving . on: http://0.0.0.0:8080 +Hit CTRL-C to stop the server +Scanned working directory. ready for changes.. +``` + +The HTTP server needs to remain running in the terminal that was used to start it. Any changes that are made in the project directory will cause the webpage to automatically refresh. + +Use a MetaMask-enabled web browser to navigate to the URL from the output (http://0.0.0.0:8080 in the example above). If everything is set up correctly, the webpage should state that it is connected to the Ethereum network with MetaMask and list the chain ID (for the default Ethereum Mainnet network this value should be `1`) and latest block number. The latest block number should change when new blocks are created. + +## Step 4: Request Access to the MetaMask Accounts + +Replace the contents of `index.html` with the following (take note of the highlighted sections, which are new): + +```html + + + + + + Web3.js MetaMask Tutorial + + + + + +
+
+
+ +
+
+ + +
+ +
+ + + + +``` + +The file has been updated to include a placeholder for the MetaMask account, as well as a button that is used to request the accounts from MetaMask. + +Once connected to MetaMask, the script now registers a click event for the new button. The accounts are requested by invoking `window.ethereum.request({ method: ["eth_requestAccounts"] })` and once the request has been approved, the account addresses are available by calling [`web3.eth.getAccounts()`](https://docs.web3js.org/api/web3-eth/class/Web3Eth#getAccounts). MetaMask can be used to manage multiple accounts, but this tutorial only makes use of a single account. More information about the [`window.ethereum.request`](https://docs.metamask.io/wallet/reference/provider-api/#request) function and [`eth_requestAccounts`](https://docs.metamask.io/wallet/reference/eth_requestaccounts/) RPC call can be found in the MetaMask documentation. + +If no Ethereum provider is found, the button to request the MetaMask accounts is disabled. + +Go back to the MetaMask-enabled browser and review the webpage, which should have been automatically refreshed to display the changes. Click the button that says "Request MetaMask Accounts", which should activate MetaMask. After accepting the MetaMask notifications, the address of the MetaMask account should be displayed on the webpage. MetaMask will remember that the webpage has been given permission to access its accounts and it will not be necessary to accept any confirmations when requesting accounts in the future. + +## Step #5: Sign a Message with a MetaMask Account + +Replace the contents of `index.html` with the following (take note of the highlighted sections, which are new): + +```html + + + + + + Web3.js MetaMask Tutorial + + + + + +
+
+
+
+
+ +
+ +
+ + +
+ + +
+
+ + + + +``` + +`index.html` has been updated to include inputs for signing a message with the MetaMask account. Initially, these inputs are disabled - they will be enabled once the page has access to the MetaMask account. A placeholder has been added for the result of the signing operation. + +Inside the click event for the "Request MetaMask Accounts" button, the signing inputs are initialized. First, the inputs are enabled. Then, a click event is registered for the "Sign" button. This click event calls the [`web3.eth.personal.sign`](/api/web3-eth-personal/class/Personal#sign) method. The first parameter to this method is the message to be signed, which is taken from the input field. The second parameter is the address of the account to use for signing. The third parameter is the passphrase to decrypt the account, which is not used in this example since MetaMask is managing the account. Once the message has been signed, the placeholder is updated with the signed message. + +Go back to the MetaMask-enabled browser and review the webpage, which should have been automatically refreshed to display the changes. There should now be disabled input fields below the "Request MetaMask Accounts" button. Click the button to request the accounts (remember, it will not be necessary to accept any MetaMask notifications this time). If everything is working properly, the address of the MetaMask account should be displayed on the webpage and the input fields should become enabled. Type a message (e.g. "Hello, Web3.js!") in the input field and click the "Sign Message" button. If everything is working properly, a MetaMask notification will appear. After the notification has been accepted, the signed message should appear beneath the input fields. + +## Step #6: Verify the Account Used to Sign a Message + +Replace the contents of `index.html` with the following (take note of the highlighted sections, which are new): + +```html + + + + + + Web3.js MetaMask Tutorial + + + + + +
+
+
+
+
+ +
+ +
+ +
+ + +
+
+ + +
+ + + +
+
+ + + + +``` + +As in the previous step, `index.html` has been updated to include inputs for recovering the account that was used to sign a message. As before, these inputs are disabled - they will be enabled once the page has access to the MetaMask account. A placeholder has been added for the result of the recovery operation. + +Inside the click event for the "Request MetaMask Accounts" button, the recovery inputs are initialized. First, the inputs are enabled. Then, a click event is registered for the "Recover" button. This click event calls the [`web3.eth.personal.ecRecover`](/api/web3-eth-personal/class/Personal#ecRecover) method. The first parameter to this method is the original unsigned message, which is taken from the first input field. The second parameter is the signed message, which is taken from the second input field. Once the account has been recovered, the placeholder is updated with the address of the account. + +Go back to the MetaMask-enabled browser and review the webpage, which should have been automatically refreshed to display the changes. There should now be additional disabled input fields below those from the previous step. Follow the same steps as before to request the accounts from MetaMask and sign a message, then copy and paste the original message and message signature (starting with the leading `0x` characters) into the new input fields. Click the "Recover Account" button. If everything is working properly, the address of the account that was used to sign the message should appear below the new input fields. This address should match the one that is displayed above the input fields that were used to sign the message. + +## Conclusion + +This tutorial demonstrated using Web3.js with MetaMask, including using the MetaMask injected provider and using a MetaMask account to sign a message. To use the MetaMask injected provider with Web3.js, simply construct a new instance of the `Web3` class with the `window.ethereum` property. To request access to the MetaMask accounts, use `window.ethereum.request({ method: "eth_requestAccounts" })` - once the user has confirmed this request, the MetaMask accounts will be available with `web3.eth.getAccounts()`. When the MetaMask injected provider handles a request that requires the use of a MetaMask account, MetaMask will prompt the user to confirm the request. diff --git a/docs/docs/guides/wallet/web3_modal_guide/_category_.yml b/docs/docs/guides/07_dapps/web3_modal_guide/_category_.yml similarity index 87% rename from docs/docs/guides/wallet/web3_modal_guide/_category_.yml rename to docs/docs/guides/07_dapps/web3_modal_guide/_category_.yml index 0ce376f6e80..c89deac9d4b 100644 --- a/docs/docs/guides/wallet/web3_modal_guide/_category_.yml +++ b/docs/docs/guides/07_dapps/web3_modal_guide/_category_.yml @@ -2,4 +2,4 @@ label: '📱 WalletConnect Tutorial' collapsible: true collapsed: true link: null -position: 6 +position: 4 diff --git a/docs/docs/guides/wallet/web3_modal_guide/index.mdx b/docs/docs/guides/07_dapps/web3_modal_guide/index.mdx similarity index 98% rename from docs/docs/guides/wallet/web3_modal_guide/index.mdx rename to docs/docs/guides/07_dapps/web3_modal_guide/index.mdx index 7e6f077b1a9..643ccb2cc79 100644 --- a/docs/docs/guides/wallet/web3_modal_guide/index.mdx +++ b/docs/docs/guides/07_dapps/web3_modal_guide/index.mdx @@ -126,5 +126,5 @@ function Components() { ``` :::info -- To learn how to set up Web3modal with React, click [here](/guides/wallet/web3_modal_guide/react). +- To learn how to set up Web3modal with React, click [here](/guides/dapps/web3_modal_guide/react). ::: diff --git a/docs/docs/guides/07_dapps/web3_modal_guide/react.md b/docs/docs/guides/07_dapps/web3_modal_guide/react.md new file mode 100644 index 00000000000..23f4bbcc052 --- /dev/null +++ b/docs/docs/guides/07_dapps/web3_modal_guide/react.md @@ -0,0 +1,122 @@ +--- +sidebar_position: 1 +sidebar_label: 'Web3Modal with React' +--- + +# Web3Modal with React 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({ + web3Config, + 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 React! + +:::info + +- For additional information take a look into the interactive code editor above. +- Learn more about Web3modal [here](https://docs.walletconnect.com/web3modal/about) + ::: diff --git a/docs/docs/guides/hardhat_tutorial/asset/artifacts.png b/docs/docs/guides/08_hardhat_tutorial/asset/artifacts.png similarity index 100% rename from docs/docs/guides/hardhat_tutorial/asset/artifacts.png rename to docs/docs/guides/08_hardhat_tutorial/asset/artifacts.png diff --git a/docs/docs/guides/hardhat_tutorial/asset/image_2.png b/docs/docs/guides/08_hardhat_tutorial/asset/image_2.png similarity index 100% rename from docs/docs/guides/hardhat_tutorial/asset/image_2.png rename to docs/docs/guides/08_hardhat_tutorial/asset/image_2.png diff --git a/docs/docs/guides/hardhat_tutorial/asset/image_3.png b/docs/docs/guides/08_hardhat_tutorial/asset/image_3.png similarity index 100% rename from docs/docs/guides/hardhat_tutorial/asset/image_3.png rename to docs/docs/guides/08_hardhat_tutorial/asset/image_3.png diff --git a/docs/docs/guides/hardhat_tutorial/index.md b/docs/docs/guides/08_hardhat_tutorial/index.md similarity index 59% rename from docs/docs/guides/hardhat_tutorial/index.md rename to docs/docs/guides/08_hardhat_tutorial/index.md index ea97d80e9b4..32850b50211 100644 --- a/docs/docs/guides/hardhat_tutorial/index.md +++ b/docs/docs/guides/08_hardhat_tutorial/index.md @@ -1,11 +1,12 @@ --- -sidebar_position: 1 -sidebar_label: Web3.js v4 with Hardhat +sidebar_position: 8 +sidebar_label: ⛑️ Web3.js v4 with Hardhat --- # Using Web3 With Hardhat ## Introduction + Following the recent compatibility update of Hardhat plugin [hardhat-web3-v4](https://hardhat.org/hardhat-runner/plugins/nomicfoundation-hardhat-web3-v4), `Web3.Js` is now available to use as plugin in Hardhat. This tutorial will guide you through using Web3js as a plugin to interact with the Blockchain. @@ -15,20 +16,23 @@ This tutorial explains how to create a Web3.js + Hardhat project from scratch. T ::: ## Pre-requisite + This tutorial assumes you have previous knowledge of writing Smart contracts, and are convenient working with JavaScript/TypeScript. You should have [NodeJS](https://nodejs.org/en) version greater than v16 installed. :::note -To install dependencies, we will use `NPM`. +To install dependencies, we will use `NPM`. ::: ## Steps -- [Initiate a Hardhat project](#initiate-a-hardhat-project) -- [Install required dependencies (including `hardhat-web3-v4`)](#install-required-dependencies-including-hardhat-web3-v4) -- [Write the Smart Contract](#write-the-smart-contract) -- [Compile and deploying the contract](#compile-test-and-deploy-the-contract) -- [Testing and interacting with the contract](#testing-and-interacting-with-the-contract) + +- [Initiate a Hardhat project](#initiate-a-hardhat-project) +- [Install required dependencies (including `hardhat-web3-v4`)](#install-required-dependencies-including-hardhat-web3-v4) +- [Write the Smart Contract](#write-the-smart-contract) +- [Compile and deploying the contract](#compile-test-and-deploy-the-contract) +- [Testing and interacting with the contract](#testing-and-interacting-with-the-contract) ### Initiate a Hardhat project + Create a new project folder and navigate into it. ```bash @@ -55,7 +59,7 @@ npx hardhat init Select `TypeScript` and `Yes` for the rest of the options. You will be prompted to install the required dependencies. Reply `yes` to complete the installation. -To include the `Hardhat-web3-v4` plugin, we will install it via `npm`. +To include the `Hardhat-web3-v4` plugin, we will install it via `npm`. ```bash npm install --save-dev @nomicfoundation/hardhat-web3-v4 'web3@4' @@ -64,21 +68,21 @@ npm install --save-dev @nomicfoundation/hardhat-web3-v4 'web3@4' This will add Web3.Js to your project by including it in the 'node_modules' folder. To extend the Hardhat functionality with this plugin, we have to import the `web3-v4 plugin` in the Hardhat configuration file `hardhat.config.ts`. Import this at the top of the config file. ```ts -import { HardhatUserConfig } from "hardhat/config"; -import "@nomicfoundation/hardhat-toolbox"; -import "@nomicfoundation/hardhat-web3-v4"; // <================ +import { HardhatUserConfig } from 'hardhat/config'; +import '@nomicfoundation/hardhat-toolbox'; +import '@nomicfoundation/hardhat-web3-v4'; // <================ const config: HardhatUserConfig = { - solidity: "0.8.19", + solidity: '0.8.19', }; export default config; - ``` By default, `hardhat-toolbox` is added to the file. You will need to explicitly invoke the plugin. This will modify the Hardhat Run-time Environment - HRE and to include both the Web3 class and an instantiated web3 object. With the latter, you get a modified ready-to-use web3 object can comes with an initialized local/Hardhat provider. The object will be available to use anywhere in the project such as testing and deployment files. ### Write the Smart Contract + When you start a new project, Hardhat provides a sample `Lock` contracts. Please refer to the contract in `myproject/contracts/Lock.sol` file. ```ts @@ -122,11 +126,13 @@ When you start a new project, Hardhat provides a sample `Lock` contracts. Please `Lock.sol` is a simple timeLock contract capable of accepting any amount of `Ether` at deployment while expecting one parameter that will be assigned to a state variable when deployed. The `withdraw` function allows only the address marked as `owner` to withdraw the total contract balance only if the 'unlockTime' is not in the future. ### Compile, test and deploy the contract -- Compile and deploying the contract + +- Compile and deploying the contract ```bash npx hardhat compile ``` + Running the above command will generate a folder called `artifacts` containing the build information and the compiled contracts. From this directory, we will require the jasonInterface otherwise called the Application Binary Interface - ABI during testing and deployment. ![images](./asset/artifacts.png) @@ -136,60 +142,58 @@ To deploy the contract, we will modify the `script/deploy.ts` file as shown belo First, we import the initialized web3 object from hardhat. Next we get the artifacts. ```ts -import { web3 } from "hardhat"; -import artifacts from "../artifacts/contracts/Lock.sol/Lock.json"; +import { web3 } from 'hardhat'; +import artifacts from '../artifacts/contracts/Lock.sol/Lock.json'; -async function main() { - -} +async function main() {} // We recommend this pattern to be able to use async/await everywhere // and properly handle errors. -main().catch((error) => { - console.error(error); - process.exitCode = 1; +main().catch(error => { + console.error(error); + process.exitCode = 1; }); - ``` Inside the main function, we prepare the deployment using a few of the web3.Js functionalities such as the `.utils` and `.eth` modules. ```ts async function main() { - const currentTimestampInSeconds = Math.round(Date.now() / 1000); - const unlockTime = currentTimestampInSeconds + 60; - - const lockedAmount = web3.utils.toWei("0.001", 'ether'); - - const [deployer] = await web3.eth.getAccounts(); - const lockContract = new web3.eth.Contract(artifacts.abi); - const rawContract = lockContract.deploy({ - data: artifacts.bytecode, - arguments: [unlockTime], - }); - - const lock = await rawContract.send({ - from: deployer, - gasPrice: "10000000000", - value: lockedAmount.toString() - }); - - console.log( - `Lock with ${web3.utils.toWei( - lockedAmount, - 'ether' - )}ETH and unlock timestamp ${unlockTime} deployed to ${lock.options.address}` - ); + const currentTimestampInSeconds = Math.round(Date.now() / 1000); + const unlockTime = currentTimestampInSeconds + 60; + + const lockedAmount = web3.utils.toWei('0.001', 'ether'); + + const [deployer] = await web3.eth.getAccounts(); + const lockContract = new web3.eth.Contract(artifacts.abi); + const rawContract = lockContract.deploy({ + data: artifacts.bytecode, + arguments: [unlockTime], + }); + + const lock = await rawContract.send({ + from: deployer, + gasPrice: '10000000000', + value: lockedAmount.toString(), + }); + + console.log( + `Lock with ${web3.utils.toWei( + lockedAmount, + 'ether', + )}ETH and unlock timestamp ${unlockTime} deployed to ${lock.options.address}`, + ); } // We recommend this pattern to be able to use async/await everywhere // and properly handle errors. -main().catch((error) => { - console.error(error); - process.exitCode = 1; +main().catch(error => { + console.error(error); + process.exitCode = 1; }); ``` -Running the following command will deploy the `Lock` contract to a local Blockchain built into Hardhat. We use Web3.Js to talk to the Blockchain to broadcast our smart contract data to the network. + +Running the following command will deploy the `Lock` contract to a local Blockchain built into Hardhat. We use Web3.Js to talk to the Blockchain to broadcast our smart contract data to the network. ```bash npx hardhat run scripts/deploy.ts @@ -197,86 +201,78 @@ npx hardhat run scripts/deploy.ts ### Testing and interacting with the contract -In the previous steps, we compiled and deployed the contract to the local Blockchain network. It's time to test our contract ensuring it performs as expected. Since we used Web3.Js to talk to the Blockchain to broadcast and save our data, we will use same protocol to view and modify the data. +In the previous steps, we compiled and deployed the contract to the local Blockchain network. It's time to test our contract ensuring it performs as expected. Since we used Web3.Js to talk to the Blockchain to broadcast and save our data, we will use same protocol to view and modify the data. In the `myproject/test/Lock.ts` file, replace the content with the code below. ```ts - import { - time, - loadFixture, - } from "@nomicfoundation/hardhat-toolbox/network-helpers"; - import { expect } from "chai"; - import { web3 } from "hardhat"; - import artifacts from "../artifacts/contracts/Lock.sol/Lock.json"; - - describe("Lock", function () { - async function deployOneYearLockFixture() { - const ONE_YEAR_IN_SECS = 365 * 24 * 60 * 60; - const ONE_GWEI = 1_000_000_000; - - const lockedAmount = ONE_GWEI; - const unlockTime = (await time.latest()) + ONE_YEAR_IN_SECS; - - const lockContract = new web3.eth.Contract(artifacts.abi); - lockContract.handleRevert = true; - - const [deployer, otherAccount] = await web3.eth.getAccounts(); - const rawContract = lockContract.deploy({ - data: artifacts.bytecode, - arguments: [unlockTime], - }); - - // To know how much gas will be consumed, we can estimate it first. - const estimateGas = await rawContract.estimateGas({ - from: deployer, - value: lockedAmount.toString() - }); - - const lock = await rawContract.send({ - from: deployer, - gas: estimateGas.toString(), - gasPrice: "10000000000", - value: lockedAmount.toString() - }); - - console.log("Lock contract deployed to: ", lock.options.address); - return { lock, unlockTime, lockedAmount, deployer, otherAccount, rawContract }; - } - - describe("Deployment", function () { - it("Should set the right unlockTime", async function () { - const { lock, unlockTime } = await loadFixture(deployOneYearLockFixture); - const setTime = await lock.methods.unlockTime().call(); - console.log("SetTime", setTime); - expect(setTime).to.equal(unlockTime); - }); - - it("Should set the right deployer", async function () { - const { lock, deployer } = await loadFixture(deployOneYearLockFixture); - - expect(await lock.methods.owner().call()).to.equal(deployer); - }); - - it("Should receive and store the funds to lock", async function () { - const { lock, lockedAmount } = await loadFixture( - deployOneYearLockFixture - ); - const balance = await web3.eth.getBalance(String(lock.options.address)); - expect(balance).to.equal(lockedAmount); - }); - - it("Shouldn't fail if the unlockTime has arrived and the deployer calls it", async function () { - const { lock, unlockTime, deployer } = await loadFixture( - deployOneYearLockFixture - ); - - await time.increaseTo(unlockTime); - await expect(lock.methods.withdraw().send({from: deployer})).not.to.be.reverted; - }); - }); - }); - +import { time, loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers'; +import { expect } from 'chai'; +import { web3 } from 'hardhat'; +import artifacts from '../artifacts/contracts/Lock.sol/Lock.json'; + +describe('Lock', function () { + async function deployOneYearLockFixture() { + const ONE_YEAR_IN_SECS = 365 * 24 * 60 * 60; + const ONE_GWEI = 1_000_000_000; + + const lockedAmount = ONE_GWEI; + const unlockTime = (await time.latest()) + ONE_YEAR_IN_SECS; + + const lockContract = new web3.eth.Contract(artifacts.abi); + lockContract.handleRevert = true; + + const [deployer, otherAccount] = await web3.eth.getAccounts(); + const rawContract = lockContract.deploy({ + data: artifacts.bytecode, + arguments: [unlockTime], + }); + + // To know how much gas will be consumed, we can estimate it first. + const estimateGas = await rawContract.estimateGas({ + from: deployer, + value: lockedAmount.toString(), + }); + + const lock = await rawContract.send({ + from: deployer, + gas: estimateGas.toString(), + gasPrice: '10000000000', + value: lockedAmount.toString(), + }); + + console.log('Lock contract deployed to: ', lock.options.address); + return { lock, unlockTime, lockedAmount, deployer, otherAccount, rawContract }; + } + + describe('Deployment', function () { + it('Should set the right unlockTime', async function () { + const { lock, unlockTime } = await loadFixture(deployOneYearLockFixture); + const setTime = await lock.methods.unlockTime().call(); + console.log('SetTime', setTime); + expect(setTime).to.equal(unlockTime); + }); + + it('Should set the right deployer', async function () { + const { lock, deployer } = await loadFixture(deployOneYearLockFixture); + + expect(await lock.methods.owner().call()).to.equal(deployer); + }); + + it('Should receive and store the funds to lock', async function () { + const { lock, lockedAmount } = await loadFixture(deployOneYearLockFixture); + const balance = await web3.eth.getBalance(String(lock.options.address)); + expect(balance).to.equal(lockedAmount); + }); + + it("Shouldn't fail if the unlockTime has arrived and the deployer calls it", async function () { + const { lock, unlockTime, deployer } = await loadFixture(deployOneYearLockFixture); + + await time.increaseTo(unlockTime); + await expect(lock.methods.withdraw().send({ from: deployer })).not.to.be.reverted; + }); + }); +}); ``` in this file, we performed similar steps as in the deployment script to prepare and deploy the contract using the `ABI` and `bytecode` in `deployOneYearLockFixture()`. To read the `owner` data from the Blockchain, we used an instance of the deployed contract i.e `lock.methods.owner().call().`Invoking `.call()` does not change the state of the blockchain hence no wallet signature is required. @@ -287,13 +283,14 @@ To change the status of the data we previously saved, we have to access the `met When using `.send()`, you must explicitly provide the `sender` of the transaction in the `from` field (in the above example is the address of the `deployer` account). ::: - To run the test you can use the command + ```bash npx hardhat test test/Lock.ts ``` And you'll get a similar result to this: + ```js /* Lock diff --git a/docs/docs/guides/web3_config/index.md b/docs/docs/guides/09_web3_config/index.md similarity index 70% rename from docs/docs/guides/web3_config/index.md rename to docs/docs/guides/09_web3_config/index.md index 32f645a465a..de8a8b9db7c 100644 --- a/docs/docs/guides/web3_config/index.md +++ b/docs/docs/guides/09_web3_config/index.md @@ -1,65 +1,64 @@ --- -sidebar_position: 6 -sidebar_label: 'Web3 Config Guide' +sidebar_position: 9 +sidebar_label: '⚙️ Web3 config' +title: 'Web3.js Config Guide' --- -# Web3.js Config Guide - ## Configuration parameters There is list of configuration params that can be set for modifying behavior of different functions in web3.js packages. Following is list of configuration options with details: -- [handleRevert](/guides/web3_config/#handlerevert) -- [defaultAccount](/guides/web3_config/#defaultaccount) -- [defaultBlock](/guides/web3_config/#defaultblock) -- [transactionBlockTimeout](/guides/web3_config/#transactionblocktimeout) -- [transactionConfirmationBlocks](/guides/web3_config/#transactionconfirmationblocks) -- [transactionPollingInterval](/guides/web3_config/#transactionpollinginterval) -- [transactionPollingTimeout](/guides/web3_config/#transactionpollingtimeout) -- [transactionReceiptPollingInterval](/guides/web3_config/#transactionreceiptpollinginterval) -- [transactionSendTimeout](/guides/web3_config/#transactionsendtimeout) -- [[Deprecated] transactionConfirmationPollingInterval](/guides/web3_config/#transactionconfirmationpollinginterval) -- [blockHeaderTimeout](/guides/web3_config/#blockheadertimeout) -- [maxListenersWarningThreshold](/guides/web3_config/#maxlistenerswarningthreshold) -- [contractDataInputFill](/guides/web3_config/#contractdatainputfill) -- [defaultNetworkId](/guides/web3_config/#defaultnetworkid) -- [defaultChain](/guides/web3_config/#defaultchain) -- [defaultHardfork](/guides/web3_config/#defaulthardfork) -- [defaultCommon](/guides/web3_config/#defaultcommon) -- [defaultTransactionType](/guides/web3_config/#defaulttransactiontype) -- [defaultMaxPriorityFeePerGas](/guides/web3_config/#defaultmaxpriorityfeepergas) -- [customTransactionSchema](/guides/web3_config/#customTransactionSchema) -- [defaultReturnFormat](/guides/web3_config/#defaultreturnformat) +- [handleRevert](/guides/web3_config/#handlerevert) +- [defaultAccount](/guides/web3_config/#defaultaccount) +- [defaultBlock](/guides/web3_config/#defaultblock) +- [transactionBlockTimeout](/guides/web3_config/#transactionblocktimeout) +- [transactionConfirmationBlocks](/guides/web3_config/#transactionconfirmationblocks) +- [transactionPollingInterval](/guides/web3_config/#transactionpollinginterval) +- [transactionPollingTimeout](/guides/web3_config/#transactionpollingtimeout) +- [transactionReceiptPollingInterval](/guides/web3_config/#transactionreceiptpollinginterval) +- [transactionSendTimeout](/guides/web3_config/#transactionsendtimeout) +- [[Deprecated] transactionConfirmationPollingInterval](/guides/web3_config/#transactionconfirmationpollinginterval) +- [blockHeaderTimeout](/guides/web3_config/#blockheadertimeout) +- [maxListenersWarningThreshold](/guides/web3_config/#maxlistenerswarningthreshold) +- [contractDataInputFill](/guides/web3_config/#contractdatainputfill) +- [defaultNetworkId](/guides/web3_config/#defaultnetworkid) +- [defaultChain](/guides/web3_config/#defaultchain) +- [defaultHardfork](/guides/web3_config/#defaulthardfork) +- [defaultCommon](/guides/web3_config/#defaultcommon) +- [defaultTransactionType](/guides/web3_config/#defaulttransactiontype) +- [defaultMaxPriorityFeePerGas](/guides/web3_config/#defaultmaxpriorityfeepergas) +- [customTransactionSchema](/guides/web3_config/#customTransactionSchema) +- [defaultReturnFormat](/guides/web3_config/#defaultreturnformat) ## Global level Config -There is option of modifying any of above-mentioned configuration parameter at global level when instantiating Web3, and it will be available to all packages. +There is option of modifying any of above-mentioned configuration parameter at global level when instantiating Web3, and it will be available to all packages. -``` ts +```ts import { Web3 } from 'web3'; const web3 = new Web3({ - provider: 'https://mainnet.infura.io/v3/YOURID', - config: { - defaultTransactionType: '0x0', - }, + provider: 'https://mainnet.infura.io/v3/YOURID', + config: { + defaultTransactionType: '0x0', + }, }); //now default transaction type will be 0x0 so using following function in eth will send type 0x0 transaction web3.eth - .sendTransaction({ - from: '0x18532dF2Ab835d4E9D07a8b9B759bf5F8f890f49', - to: '0xB2f70d8965e754cc07D343a9b5332876D3070155', - value: 100, - gasLimit: 21000, - }) - .then((res) => console.log(res)); + .sendTransaction({ + from: '0x18532dF2Ab835d4E9D07a8b9B759bf5F8f890f49', + to: '0xB2f70d8965e754cc07D343a9b5332876D3070155', + value: 100, + gasLimit: 21000, + }) + .then(res => console.log(res)); ``` For Advance Users: Global level config can also be set using `Web3Context` object. -``` ts +```ts import { Web3, Web3Context } from 'web3'; const context = new Web3Context('http://127.0.0.1:7545'); @@ -68,34 +67,37 @@ context.setConfig({ defaultTransactionType: '0x0' }); const web3 = new Web3(context); //it will not default to 0x0 type transactions -web3.eth.sendTransaction({ - from: '0x18532dF2Ab835d4E9D07a8b9B759bf5F8f890f49', - to: '0x018e221145dE7cefAD09BD53F41c11A918Bf1Cb7', - value: 100, - gasLimit: 21000 -}).then(res => console.log(res)); +web3.eth + .sendTransaction({ + from: '0x18532dF2Ab835d4E9D07a8b9B759bf5F8f890f49', + to: '0x018e221145dE7cefAD09BD53F41c11A918Bf1Cb7', + value: 100, + gasLimit: 21000, + }) + .then(res => console.log(res)); ``` ## Package level config ### Setting config in Individual Package under Web3 instance + Some configuration options that effects selected packages can be modified using `setConfig(...)` function. -``` ts +```ts import { Web3 } from 'web3'; const web3 = new Web3('https://mainnet.infura.io/v3/YOURID'); -web3.eth.setConfig({ defaultTransactionType: '0x0'}); +web3.eth.setConfig({ defaultTransactionType: '0x0' }); web3.eth - .sendTransaction({ - from: '0x18532dF2Ab835d4E9D07a8b9B759bf5F8f890f49', - to: '0xB2f70d8965e754cc07D343a9b5332876D3070155', - value: 100, - gasLimit: 21000, - }) - .then((res) => console.log(res)); + .sendTransaction({ + from: '0x18532dF2Ab835d4E9D07a8b9B759bf5F8f890f49', + to: '0xB2f70d8965e754cc07D343a9b5332876D3070155', + value: 100, + gasLimit: 21000, + }) + .then(res => console.log(res)); ``` ### Setting config in Individually imported Packages @@ -114,20 +116,20 @@ Configuration options can be set by passing in constructor: import { Web3Eth } from 'web3-eth'; const web3EthObj = new Web3Eth({ - provider: 'http://127.0.0.1:7545', - config: { - defaultTransactionType: 0x0, - }, + provider: 'http://127.0.0.1:7545', + config: { + defaultTransactionType: 0x0, + }, }); web3EthObj - .sendTransaction({ - from: '0x18532dF2Ab835d4E9D07a8b9B759bf5F8f890f49', - to: '0x018e221145dE7cefAD09BD53F41c11A918Bf1Cb7', - value: 100, - gasLimit: 21000, - }) - .then((res) => console.log(res)); + .sendTransaction({ + from: '0x18532dF2Ab835d4E9D07a8b9B759bf5F8f890f49', + to: '0x018e221145dE7cefAD09BD53F41c11A918Bf1Cb7', + value: 100, + gasLimit: 21000, + }) + .then(res => console.log(res)); ``` Another way of setting config for individually imported package is by using `setConfig(...)` function. @@ -140,25 +142,25 @@ const web3EthObj = new Web3Eth('http://127.0.0.1:7545'); web3EthObj.setConfig({ defaultTransactionType: 0x0 }); web3EthObj - .sendTransaction({ - from: '0x18532dF2Ab835d4E9D07a8b9B759bf5F8f890f49', - to: '0x018e221145dE7cefAD09BD53F41c11A918Bf1Cb7', - value: 100, - gasLimit: 21000, - }) - .then((res) => console.log(res)); + .sendTransaction({ + from: '0x18532dF2Ab835d4E9D07a8b9B759bf5F8f890f49', + to: '0x018e221145dE7cefAD09BD53F41c11A918Bf1Cb7', + value: 100, + gasLimit: 21000, + }) + .then(res => console.log(res)); ``` ## Getting Current Config For getting list of current config params `getContextObject().config` can be used as : -``` ts title='getContextObject() in Web3 object' +```ts title='getContextObject() in Web3 object' import { Web3 } from 'web3'; const web3 = new Web3('http://127.0.0.1:7545'); -console.log(web3.getContextObject().config) +console.log(web3.getContextObject().config); /* ↳ handleRevert: false, defaultAccount: undefined, @@ -190,7 +192,7 @@ import { Web3Eth } from 'web3'; const web3 = new Web3Eth('http://127.0.0.1:7545'); -console.log(web3.getContextObject().config) +console.log(web3.getContextObject().config); /* ↳ handleRevert: false, defaultAccount: undefined, @@ -206,65 +208,76 @@ console.log(web3.getContextObject().config) ## Explanation of Configuration Parameters ### [handleRevert](/api/web3-core/class/Web3Config#handleRevert) + The following methods will retrieve specific error types and error messages when `handleRevert` is set to `true`: -- [`web3.eth.sendTransaction()`](/api/web3-eth/function/sendTransaction); -- [`myContract.methods.myMethod().send()`](/libdocs/Contract#send); + +- [`web3.eth.sendTransaction()`](/api/web3-eth/function/sendTransaction); +- [`myContract.methods.myMethod().send()`](/libdocs/Contract#send); The error type will be one of the following: -- [InvalidResponseError](/api/web3-errors/class/InvalidResponseError) -- [ContractExecutionError](/api/web3-errors/class/ContractExecutionError) -- [TransactionRevertWithCustomError](/api/web3-errors/class/TransactionRevertWithCustomError) -- [TransactionRevertedWithoutReasonError](/api/web3-errors/class/TransactionRevertedWithoutReasonError) -- [TransactionRevertInstructionError](/api/web3-errors/class/TransactionRevertInstructionError) -- [TransactionPollingTimeoutError](/api/web3-errors/class/TransactionPollingTimeoutError) + +- [InvalidResponseError](/api/web3-errors/class/InvalidResponseError) +- [ContractExecutionError](/api/web3-errors/class/ContractExecutionError) +- [TransactionRevertWithCustomError](/api/web3-errors/class/TransactionRevertWithCustomError) +- [TransactionRevertedWithoutReasonError](/api/web3-errors/class/TransactionRevertedWithoutReasonError) +- [TransactionRevertInstructionError](/api/web3-errors/class/TransactionRevertInstructionError) +- [TransactionPollingTimeoutError](/api/web3-errors/class/TransactionPollingTimeoutError) For example, the error message could be `TransactionRevertInstructionError('Returned error: invalid argument 0: json: cannot unmarshal invalid hex string into Go struct field TransactionArgs.data of type hexutil.Bytes')`. The `handleRevert` option is only supported for [`sendTransaction`](/api/web3-eth/function/sendTransaction) and not for [`sendSignedTransaction`](/api/web3-eth/function/sendSignedTransaction) for now. The default value of `handleRevert` is `false`. ### [defaultAccount](/api/web3-core/class/Web3Config#defaultAccount) + The `defaultAccount` option is used as the default `from` property, if no `from` property is specified for the following methods: -- [`web3.eth.sendTransaction()`](/api/web3-eth/function/sendTransaction); -- [`web3.eth.call()`](/api/web3-eth/function/call); -- [`myContract.methods.myMethod().call()`](/libdocs/Contract#call); -- [`myContract.methods.myMethod().send()`](/libdocs/Contract#send); + +- [`web3.eth.sendTransaction()`](/api/web3-eth/function/sendTransaction); +- [`web3.eth.call()`](/api/web3-eth/function/call); +- [`myContract.methods.myMethod().call()`](/libdocs/Contract#call); +- [`myContract.methods.myMethod().send()`](/libdocs/Contract#send); The default value of `defaultAccount` is `undefined`. ### [defaultBlock](/api/web3-core/class/Web3Config#defaultBlock) -The following methods accept an optional `blockNumber` parameter, the `defaultBlock` option is used for these methods if no `blockNumber` parameter is provided. -- [`web3.eth.getBalance()`](/api/web3-eth/function/getBalance); -- [`web3.eth.getCode()`](/api/web3-eth/function/getCode); -- [`web3.eth.getTransactionCount()`](/api/web3-eth/function/getTransactionCount); -- [`web3.eth.getStorageAt()`](/api/web3-eth/function/getStorageAt); -- [`web3.eth.call()`](/api/web3-eth/function/call); -- [`myContract.methods.myMethod().call()`](/libdocs/Contract#call); + +The following methods accept an optional `blockNumber` parameter, the `defaultBlock` option is used for these methods if no `blockNumber` parameter is provided. + +- [`web3.eth.getBalance()`](/api/web3-eth/function/getBalance); +- [`web3.eth.getCode()`](/api/web3-eth/function/getCode); +- [`web3.eth.getTransactionCount()`](/api/web3-eth/function/getTransactionCount); +- [`web3.eth.getStorageAt()`](/api/web3-eth/function/getStorageAt); +- [`web3.eth.call()`](/api/web3-eth/function/call); +- [`myContract.methods.myMethod().call()`](/libdocs/Contract#call); If a `blockNumber` parameter is provided to one of the above function calls, it will override this option. The default value of `defaultBlock` is "latest". #### All available choices for defaultBlock: + ```ts web3.defaultBlock = 20167235; // A block number -web3.defaultBlock = "earliest"; // The genesis block -web3.defaultBlock = "latest"; // The latest block (current head of the blockchain) -web3.defaultBlock = "pending"; // The block pending to be mined (including pending transactions) -web3.defaultBlock = "finalized"; // (For POS networks) The finalized block is one which has been accepted as canonical by greater than 2/3 of validators -web3.defaultBlock = "safe"; // (For POS networks) The safe head block is one which under normal network conditions, is expected to be included in the canonical chain. Under normal network conditions the safe head and the actual tip of the chain will be equivalent (with safe head trailing only by a few seconds). Safe heads will be less likely to be reorged than the proof of work network`s latest blocks. +web3.defaultBlock = 'earliest'; // The genesis block +web3.defaultBlock = 'latest'; // The latest block (current head of the blockchain) +web3.defaultBlock = 'pending'; // The block pending to be mined (including pending transactions) +web3.defaultBlock = 'finalized'; // (For POS networks) The finalized block is one which has been accepted as canonical by greater than 2/3 of validators +web3.defaultBlock = 'safe'; // (For POS networks) The safe head block is one which under normal network conditions, is expected to be included in the canonical chain. Under normal network conditions the safe head and the actual tip of the chain will be equivalent (with safe head trailing only by a few seconds). Safe heads will be less likely to be reorged than the proof of work network`s latest blocks. ``` ### [transactionBlockTimeout](/api/web3-core/class/Web3Config#transactionBlockTimeout) - This option defines the number of new blocks to wait for the **first confirmation**, otherwise the [`PromiEvent`](/api/web3/class/Web3PromiEvent) rejects with a timeout error. -The default value of `transactionBlockTimeout` is 50. +This option defines the number of new blocks to wait for the **first confirmation**, otherwise the [`PromiEvent`](/api/web3/class/Web3PromiEvent) rejects with a timeout error. + +The default value of `transactionBlockTimeout` is 50. ### [transactionConfirmationBlocks](/api/web3-core/class/Web3Config#transactionConfirmationBlocks) + This defines the number of blocks required for a transaction to be considered confirmed. Different chains have varying security considerations and requirements for confirmation block numbers. The default value of `transactionConfirmationBlocks` is 24. ### [transactionPollingInterval](/api/web3-core/class/Web3Config#transactionPollingInterval) + This option defines the number of seconds between Web3 calls for a receipt which confirms that a transaction was mined by the network. Modifying this value can reduce the wait time for confirmations or decrease the number of network requests. Setting the `transactionPollingInterval` would also set [`transactionReceiptPollingInterval`](/guides/web3_config/#transactionreceiptpollinginterval) and [`transactionConfirmationPollingInterval`](/guides/web3_config/#transactionconfirmationpollinginterval) to the same value. The default value of `transactionPollingInterval` is 1000 ms. @@ -289,95 +302,109 @@ console.log(web3.getContextObject().config); ``` ### [transactionPollingTimeout](/api/web3-core/class/Web3Config#transactionPollingTimeout) + This option defines the number of seconds Web3 will wait for a receipt which confirms that a transaction was mined by the network. It can be set based on the average transaction confirmation time on the network. Note: If the `transactionPollingTimeout` is exceeded, the transaction may still be pending. The default value of `transactionPollingTimeout` is 750 seconds (12.5 minutes). ### [transactionReceiptPollingInterval](/api/web3-core/class/Web3Config#transactionReceiptPollingInterval) + This option defines the number of seconds between Web3 calls for a receipt which confirms that a transaction was mined by the network. Compared to [`transactionPollingInterval`](/guides/web3_config/#transactionpollinginterval), it takes higher precedence. When this value is set, it will be read first. The default value of `transactionReceiptPollingInterval` is `undefined`. ### [transactionSendTimeout](/api/web3-core/class/Web3Config#transactionSendTimeout) + The `transactionSendTimeout` option is used to specify how long to wait for the network to return the sent transaction result. Note: If the RPC call times out, the transaction may still be pending or even mined by the network. It is recommended that the pending transactions be checked in such a case. The default value of `transactionSendTimeout` is 750 seconds (12.5 minutes). ### [transactionConfirmationPollingInterval](/api/web3-core/class/Web3Config#transactionConfirmationPollingInterval) + The `transactionConfirmationPollingInterval` option is deprecated. Please use [`transactionReceiptPollingInterval`](/guides/web3_config/#transactionreceiptpollinginterval) or [`transactionPollingInterval`](/guides/web3_config/#transactionpollinginterval) instead. ### [blockHeaderTimeout](/api/web3-core/class/Web3Config#blockHeaderTimeout) + After sending a transaction, Web3 will listen for the appearance of new blocks and proceed with subsequent operations based on the transaction results within them. This option defines the number of seconds Web3 should wait for the appearance of new blocks before reverting to polling to fetch the transaction receipt. The default value of `blockHeaderTimeout` is 10 seconds. ### [maxListenersWarningThreshold](/api/web3-core/class/Web3Config#maxListenersWarningThreshold) + The `maxListenersWarningThreshold` is used to set the `maxListeners` property in [`EventEmitter`](/api/web3-utils/class/EventEmitter). The default value of `maxListenersWarningThreshold` is 100. ### [contractDataInputFill](/api/web3-core/class/Web3Config#contractDataInputFill) + The `contractDataInputFill` option allows users to specify whether the [`data`](/api/web3/namespace/types#data) or [`input`](/api/web3/namespace/types#input) property (or both properties) should be set to the hash of the method signature and encoded parameters. This will affect the contracts [`send`](/libdocs/Contract#send), [`call`](/libdocs/Contract#call) and [`estimateGas`](/libdocs/Contract#estimategas) methods. The default value of `contractDataInputFill` is `data`. #### All available choices for contractDataInputFill: + ```ts -'data' -'input' -'both' +'data'; +'input'; +'both'; ``` ### [defaultNetworkId](/api/web3-core/class/Web3Config#defaultNetworkId) + Each network has its own [network ID](https://docs.goquorum.consensys.io/concepts/network-and-chain-id). The `defaultNetworkId` option allows users to set the default network ID. If this option is not set, Web3 will fetch the network ID with an RPC request. The default value of `defaultNetworkId` is `undefined`. ### [defaultChain](/api/web3-core/class/Web3Config#defaultChain) + The `defaultChain` option is used to set the [`Common`](/api/web3-eth-contract/class/Contract#defaultCommon) `baseChain` property. The value of this option should be consistent with [`defaultCommon.baseChain`](/guides/web3_config/#defaultcommon) if both options are set. The default value of `defaultChain` is `mainnet`. #### All available choices for defaultChain: + ```ts -'goerli' -'kovan' -'mainnet' -'rinkeby' -'ropsten' -'sepolia' +'goerli'; +'kovan'; +'mainnet'; +'rinkeby'; +'ropsten'; +'sepolia'; ``` ### [defaultHardfork](/api/web3-core/class/Web3Config#defaultHardfork) + The `defaultHardfork` option is used to set the [`Common`](/api/web3-eth-contract/class/Contract#defaultCommon) `hardfork` property. The value of this option should be consistent with [`defaultCommon.hardfork`](/guides/web3_config/#defaultcommon) if both options are set. The default value of `defaultHardfork` is `london`. #### All available choices for defaultHardFork: + ```ts -'chainstart' -'frontier' -'homestead' -'dao' -'tangerineWhistle' -'spuriousDragon' -'byzantium' -'constantinople' -'petersburg' -'istanbul' -'muirGlacier' -'berlin' -'london' -'altair' -'arrowGlacier' -'grayGlacier' -'bellatrix' -'merge' -'capella' -'sharding' +'chainstart'; +'frontier'; +'homestead'; +'dao'; +'tangerineWhistle'; +'spuriousDragon'; +'byzantium'; +'constantinople'; +'petersburg'; +'istanbul'; +'muirGlacier'; +'berlin'; +'london'; +'altair'; +'arrowGlacier'; +'grayGlacier'; +'bellatrix'; +'merge'; +'capella'; +'sharding'; ``` ### [defaultCommon](/api/web3-core/class/Web3Config#defaultCommon) + The `defaultCommon` option is used to set the [`defaultCommon`](/libdocs/Contract#defaultcommon) value for smart contract transactions. It should be consistent with the [`defaultHardfork`](/guides/web3_config/#defaulthardfork) and [`defaultChain`](/guides/web3_config/#defaultchain) options if they are set. The default value of `defaultCommon` is `undefined`. @@ -387,59 +414,66 @@ import { Web3, Hardfork } from 'web3'; const web3 = new Web3('http://127.0.0.1:7545'); -web3.defaultHardfork = 'berlin' -web3.defaultChain = 'goerli' +web3.defaultHardfork = 'berlin'; +web3.defaultChain = 'goerli'; web3.defaultCommon = { - baseChain: 'goerli', - hardfork: 'berlin' as Hardfork, - customChain: { - networkId: 1, - chainId: 1, - }, + baseChain: 'goerli', + hardfork: 'berlin' as Hardfork, + customChain: { + networkId: 1, + chainId: 1, + }, }; console.log(web3.getContextObject().config); ``` ### [defaultTransactionType](/api/web3-core/class/Web3Config#defaultTransactionType) + The `defaultTransactionType` option is used to set the transaction type. Transactions with type 0x0 are legacy transactions that use the transaction format that existed before [typed transactions](https://ethereum.org/en/developers/docs/transactions/#typed-transaction-envelope) were introduced in [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718). Transactions with type 0x1 are transactions introduced in [EIP-2930](https://eips.ethereum.org/EIPS/eip-2930). Transactions with type 0x2 are transactions introduced in [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559), included in Ethereum's London fork. The default value of `defaultTransactionType` is `0x02`. ### [defaultMaxPriorityFeePerGas](/api/web3-core/class/Web3Config#defaultMaxPriorityFeePerGas) + The `defaultMaxPriorityFeePerGas` option is used to set the [`defaultMaxPriorityFeePerGas`](/api/web3-eth-contract/class/Contract#defaultMaxPriorityFeePerGas) value for [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) smart contract transactions ([transaction type](#defaulttransactiontype) 0x2). The default value of `defaultMaxPriorityFeePerGas` is 2500000000 (2.5gwei) in hexstring format. ### [customTransactionSchema](/api/web3-core/class/Web3Config#customTransactionSchema) + The `customTransactionSchema` option is used to allow [`formatTransaction`](/api/web3-eth/function/formatTransaction) to accept a custom schema to validate transactions. A use-case could be: your chain has an extra field in its transactions and you want to write a plugin that makes sending these transactions easier. ### [defaultReturnFormat](/api/web3-core/class/Web3Config#defaultReturnFormat) + The `defaultReturnFormat` option 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, + number: FMT_NUMBER.BIGINT, + bytes: FMT_BYTES.HEX, }; - ``` #### All available choices for numeric data: -```ts + +```ts export enum FMT_NUMBER { - NUMBER = 'NUMBER_NUMBER', - HEX = 'NUMBER_HEX', - STR = 'NUMBER_STR', - BIGINT = 'NUMBER_BIGINT', -}; + NUMBER = 'NUMBER_NUMBER', + HEX = 'NUMBER_HEX', + STR = 'NUMBER_STR', + BIGINT = 'NUMBER_BIGINT', +} ``` -#### All available choices for bytes data: + +#### All available choices for bytes data: + ```ts export enum FMT_BYTES { - HEX = 'BYTES_HEX', - UINT8ARRAY = 'BYTES_UINT8ARRAY', -}; + HEX = 'BYTES_HEX', + UINT8ARRAY = 'BYTES_UINT8ARRAY', +} ``` diff --git a/docs/docs/guides/web3_eth/_category_.yml b/docs/docs/guides/10_web3_eth/_category_.yml similarity index 85% rename from docs/docs/guides/web3_eth/_category_.yml rename to docs/docs/guides/10_web3_eth/_category_.yml index 197604038d5..10c784c3350 100644 --- a/docs/docs/guides/web3_eth/_category_.yml +++ b/docs/docs/guides/10_web3_eth/_category_.yml @@ -2,4 +2,4 @@ label: '📦 Web3 Eth module' collapsible: true collapsed: true link: null -position: 8 \ No newline at end of file +position: 10 diff --git a/docs/docs/guides/web3_eth/eth.md b/docs/docs/guides/10_web3_eth/eth.md similarity index 66% rename from docs/docs/guides/web3_eth/eth.md rename to docs/docs/guides/10_web3_eth/eth.md index 5db4eef6919..5b97adea208 100644 --- a/docs/docs/guides/web3_eth/eth.md +++ b/docs/docs/guides/10_web3_eth/eth.md @@ -33,7 +33,7 @@ Before we start writing and deploying our contract, we need to set up our enviro You can also interact with a mainnet/testnet by using a node provider instead of ganache, you can use [Alchemy](https://www.alchemy.com/), [Infura](https://www.infura.io/), [QuickNode](https://www.quicknode.com/) or get a public endpoint from [Chainlist](https://chainlist.org/) ::: -1. `Ganache` - Ganache is a personal blockchain for Ethereum development that allows you to see how your smart contracts function in real-world scenarios. You can download it from http://truffleframework.com/ganache +1. `Ganache` - Ganache is a personal blockchain for Ethereum development that allows you to see how your smart contracts function in real-world scenarios. You can download it from http://truffleframework.com/ganache 2. `Node.js` - Node.js is a JavaScript runtime environment that allows you to run JavaScript on the server-side. You can download it from https://nodejs.org/en/download/ 3. `npm` - Node Package Manager is used to publish and install packages to and from the public npm registry or a private npm registry. Here is how to install it https://docs.npmjs.com/downloading-and-installing-node-js-and-npm. (Alternatively, you can use yarn instead of npm https://classic.yarnpkg.com/lang/en/docs/getting-started/) @@ -118,43 +118,43 @@ const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:7545')); web3.eth.Contract.handleRevert = true; async function interact() { - //fetch all the available accounts - const accounts = await web3.eth.getAccounts(); - console.log(accounts); - - let balance1, balance2; - //The initial balances of the accounts should be 100 Eth (10^18 wei) - balance1 = await web3.eth.getBalance(accounts[0]); - balance2 = await web3.eth.getBalance(accounts[1]); - - console.log(balance1, balance2); - - //create a transaction sending 1 Ether from account 0 to account 1 - const transaction = { - from: accounts[0], - to: accounts[1], - // value should be passed in wei. For easier use and to avoid mistakes, - // we utilize the auxiliary `toWei` function: - value: web3.utils.toWei('1', 'ether'), - }; - - //send the actual transaction - const transactionHash = await web3.eth.sendTransaction(transaction); - console.log('transactionHash', transactionHash); - - balance1 = await web3.eth.getBalance(accounts[0]); - balance2 = await web3.eth.getBalance(accounts[1]); - - // see the updated balances - console.log(balance1, balance2); - - // irrelevant with the actual transaction, just to know the gasPrice - const gasPrice = await web3.eth.getGasPrice(); - console.log(gasPrice); + //fetch all the available accounts + const accounts = await web3.eth.getAccounts(); + console.log(accounts); + + let balance1, balance2; + //The initial balances of the accounts should be 100 Eth (10^18 wei) + balance1 = await web3.eth.getBalance(accounts[0]); + balance2 = await web3.eth.getBalance(accounts[1]); + + console.log(balance1, balance2); + + //create a transaction sending 1 Ether from account 0 to account 1 + const transaction = { + from: accounts[0], + to: accounts[1], + // value should be passed in wei. For easier use and to avoid mistakes, + // we utilize the auxiliary `toWei` function: + value: web3.utils.toWei('1', 'ether'), + }; + + //send the actual transaction + const transactionHash = await web3.eth.sendTransaction(transaction); + console.log('transactionHash', transactionHash); + + balance1 = await web3.eth.getBalance(accounts[0]); + balance2 = await web3.eth.getBalance(accounts[1]); + + // see the updated balances + console.log(balance1, balance2); + + // irrelevant with the actual transaction, just to know the gasPrice + const gasPrice = await web3.eth.getGasPrice(); + console.log(gasPrice); } (async () => { - await interact(); + await interact(); })(); ``` @@ -217,56 +217,56 @@ In the next example, we are going to use `estimateGas` function to see the expec import { Web3, ETH_DATA_FORMAT, DEFAULT_RETURN_FORMAT } from 'web3'; async function estimate() { - // abi of our contract - const abi = [ - { - inputs: [{ internalType: 'uint256', name: '_myNumber', type: 'uint256' }], - stateMutability: 'nonpayable', - type: 'constructor', - }, - { - inputs: [], - name: 'myNumber', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [{ internalType: 'uint256', name: '_myNumber', type: 'uint256' }], - name: 'setMyNumber', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - ]; - - const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:7545')); - - //get the available accounts - const accounts = await web3.eth.getAccounts(); - let acc = await accounts[0]; - - let contract = new web3.eth.Contract(abi); - - const deployment = contract.deploy({ - data: '0x608060405234801561001057600080fd5b506040516101d93803806101d983398181016040528101906100329190610054565b806000819055505061009e565b60008151905061004e81610087565b92915050565b60006020828403121561006657600080fd5b60006100748482850161003f565b91505092915050565b6000819050919050565b6100908161007d565b811461009b57600080fd5b50565b61012c806100ad6000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c806323fd0e401460375780636ffd773c146051575b600080fd5b603d6069565b6040516048919060bf565b60405180910390f35b6067600480360381019060639190608c565b606f565b005b60005481565b8060008190555050565b60008135905060868160e2565b92915050565b600060208284031215609d57600080fd5b600060a9848285016079565b91505092915050565b60b98160d8565b82525050565b600060208201905060d2600083018460b2565b92915050565b6000819050919050565b60e98160d8565b811460f357600080fd5b5056fea2646970667358221220d28cf161457f7936995800eb9896635a02a559a0561bff6a09a40bfb81cd056564736f6c63430008000033', - // @ts-expect-error - arguments: [1], - }); - - let estimatedGas = await deployment.estimateGas({ from: acc }, DEFAULT_RETURN_FORMAT); - // the returned data will be formatted as a bigint - - console.log('Default format:', estimatedGas); - - estimatedGas = await deployment.estimateGas({ from: acc }, ETH_DATA_FORMAT); - // the returned data will be formatted as a hexstring - - console.log('Eth format:', estimatedGas); + // abi of our contract + const abi = [ + { + inputs: [{ internalType: 'uint256', name: '_myNumber', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'constructor', + }, + { + inputs: [], + name: 'myNumber', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'uint256', name: '_myNumber', type: 'uint256' }], + name: 'setMyNumber', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + ]; + + const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:7545')); + + //get the available accounts + const accounts = await web3.eth.getAccounts(); + let acc = await accounts[0]; + + let contract = new web3.eth.Contract(abi); + + const deployment = contract.deploy({ + data: '0x608060405234801561001057600080fd5b506040516101d93803806101d983398181016040528101906100329190610054565b806000819055505061009e565b60008151905061004e81610087565b92915050565b60006020828403121561006657600080fd5b60006100748482850161003f565b91505092915050565b6000819050919050565b6100908161007d565b811461009b57600080fd5b50565b61012c806100ad6000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c806323fd0e401460375780636ffd773c146051575b600080fd5b603d6069565b6040516048919060bf565b60405180910390f35b6067600480360381019060639190608c565b606f565b005b60005481565b8060008190555050565b60008135905060868160e2565b92915050565b600060208284031215609d57600080fd5b600060a9848285016079565b91505092915050565b60b98160d8565b82525050565b600060208201905060d2600083018460b2565b92915050565b6000819050919050565b60e98160d8565b811460f357600080fd5b5056fea2646970667358221220d28cf161457f7936995800eb9896635a02a559a0561bff6a09a40bfb81cd056564736f6c63430008000033', + // @ts-expect-error + arguments: [1], + }); + + let estimatedGas = await deployment.estimateGas({ from: acc }, DEFAULT_RETURN_FORMAT); + // the returned data will be formatted as a bigint + + console.log('Default format:', estimatedGas); + + estimatedGas = await deployment.estimateGas({ from: acc }, ETH_DATA_FORMAT); + // the returned data will be formatted as a hexstring + + console.log('Eth format:', estimatedGas); } (async () => { - await estimate(); + await estimate(); })(); ``` @@ -298,29 +298,29 @@ const privateKey = '0x0fed6f64e01bc9fac9587b6e7245fd9d056c3c004ad546a17d3d029977 const value = web3.utils.toWei('1', 'ether'); async function sendSigned() { - const accounts = await web3.eth.getAccounts(); - const fromAddress = accounts[0]; - const toAddress = accounts[1]; - // Create a new transaction object - const tx = { - from: fromAddress, - to: toAddress, - value: value, - gas: 21000, - gasPrice: web3.utils.toWei('10', 'gwei'), - nonce: await web3.eth.getTransactionCount(fromAddress), - }; - - // Sign the transaction with the private key - const signedTx = await web3.eth.accounts.signTransaction(tx, privateKey); - - // Send the signed transaction to the network - const receipt = await web3.eth.sendSignedTransaction(signedTx.rawTransaction); - - console.log('Transaction receipt:', receipt); + const accounts = await web3.eth.getAccounts(); + const fromAddress = accounts[0]; + const toAddress = accounts[1]; + // Create a new transaction object + const tx = { + from: fromAddress, + to: toAddress, + value: value, + gas: 21000, + gasPrice: web3.utils.toWei('10', 'gwei'), + nonce: await web3.eth.getTransactionCount(fromAddress), + }; + + // Sign the transaction with the private key + const signedTx = await web3.eth.accounts.signTransaction(tx, privateKey); + + // Send the signed transaction to the network + const receipt = await web3.eth.sendSignedTransaction(signedTx.rawTransaction); + + console.log('Transaction receipt:', receipt); } (async () => { - await sendSigned(); + await sendSigned(); })(); ``` @@ -419,43 +419,43 @@ import { Web3 } from 'web3'; const web3 = new Web3('http://localhost:8545'); async function test() { - const privateKey = 'YOUR PRIVATE KEY HERE'; - // add private key to wallet to have auto-signing transactions feature - const account = web3.eth.accounts.privateKeyToAccount(privateKey); - web3.eth.accounts.wallet.add(account); - - // create transaction object - const tx = { - from: account.address, - to: '0x27aa427c1d668ddefd7bc93f8857e7599ffd16ab', - value: '0x1', - gas: BigInt(21000), - gasPrice: await web3.eth.getGasPrice(), - type: BigInt(0), // <- specify type - }; - - // send transaction - const receipt = await web3.eth.sendTransaction(tx); - - console.log('Receipt:', receipt); - // Receipt: { - // blockHash: '0xc0f2fea359233b0843fb53255b8a7f42aa7b1aff53da7cbe78c45b5bac187ad4', - // blockNumber: 21n, - // cumulativeGasUsed: 21000n, - // effectiveGasPrice: 2569891347n, - // from: '0xe2597eb05cf9a87eb1309e86750c903ec38e527e', - // gasUsed: 21000n, - // logs: [], - // logsBloom: '0x0...00000', - // status: 1n, - // to: '0x27aa427c1d668ddefd7bc93f8857e7599ffd16ab', - // transactionHash: '0x0ffe880776f5631e4b64caf521bd01cd816dd2cc29e533bc56f392211856cf9a', - // transactionIndex: 0n, - // type: 0n - // } + const privateKey = 'YOUR PRIVATE KEY HERE'; + // add private key to wallet to have auto-signing transactions feature + const account = web3.eth.accounts.privateKeyToAccount(privateKey); + web3.eth.accounts.wallet.add(account); + + // create transaction object + const tx = { + from: account.address, + to: '0x27aa427c1d668ddefd7bc93f8857e7599ffd16ab', + value: '0x1', + gas: BigInt(21000), + gasPrice: await web3.eth.getGasPrice(), + type: BigInt(0), // <- specify type + }; + + // send transaction + const receipt = await web3.eth.sendTransaction(tx); + + console.log('Receipt:', receipt); + // Receipt: { + // blockHash: '0xc0f2fea359233b0843fb53255b8a7f42aa7b1aff53da7cbe78c45b5bac187ad4', + // blockNumber: 21n, + // cumulativeGasUsed: 21000n, + // effectiveGasPrice: 2569891347n, + // from: '0xe2597eb05cf9a87eb1309e86750c903ec38e527e', + // gasUsed: 21000n, + // logs: [], + // logsBloom: '0x0...00000', + // status: 1n, + // to: '0x27aa427c1d668ddefd7bc93f8857e7599ffd16ab', + // transactionHash: '0x0ffe880776f5631e4b64caf521bd01cd816dd2cc29e533bc56f392211856cf9a', + // transactionIndex: 0n, + // type: 0n + // } } (async () => { - await test(); + await test(); })(); ``` @@ -476,48 +476,48 @@ EIP-2930 is part of Ethereum's ongoing efforts to improve the network's efficien To send EIP-2930 transaction use code below: ```typescript -import {Web3} from 'web3'; +import { Web3 } from 'web3'; const web3 = new Web3('http://localhost:8545'); async function test() { - const privateKey = 'YOUR PRIVATE KEY HERE'; - // add private key to wallet to have auto-signing transactions feature - const account = web3.eth.accounts.privateKeyToAccount(privateKey); - web3.eth.accounts.wallet.add(account); - - // create transaction object - const tx = { - from: account.address, - to: '0x27aa427c1d668ddefd7bc93f8857e7599ffd16ab', - value: '0x1', - gasLimit: BigInt(21000), - type: BigInt(1), // <- specify type - // gasPrice - you can specify this property directly or web3js will fill this field automatically - }; - - // send transaction - const receipt = await web3.eth.sendTransaction(tx); - - console.log('Receipt:', receipt); - // Receipt: { - // blockHash: '0xd8f6a3638112d17b476fd1b7c4369d473bc1a484408b6f39dbf64410df44adf6', - // blockNumber: 24n, - // cumulativeGasUsed: 21000n, - // effectiveGasPrice: 2546893579n, - // from: '0xe2597eb05cf9a87eb1309e86750c903ec38e527e', - // gasUsed: 21000n, - // logs: [], - // logsBloom: '0x...0000', - // status: 1n, - // to: '0x27aa427c1d668ddefd7bc93f8857e7599ffd16ab', - // transactionHash: '0xd1d682b6f6467897db5b8f0a99a6be2fb788d32fbc1329b568b8f6b2c15e809a', - // transactionIndex: 0n, - // type: 1n - // } + const privateKey = 'YOUR PRIVATE KEY HERE'; + // add private key to wallet to have auto-signing transactions feature + const account = web3.eth.accounts.privateKeyToAccount(privateKey); + web3.eth.accounts.wallet.add(account); + + // create transaction object + const tx = { + from: account.address, + to: '0x27aa427c1d668ddefd7bc93f8857e7599ffd16ab', + value: '0x1', + gasLimit: BigInt(21000), + type: BigInt(1), // <- specify type + // gasPrice - you can specify this property directly or web3js will fill this field automatically + }; + + // send transaction + const receipt = await web3.eth.sendTransaction(tx); + + console.log('Receipt:', receipt); + // Receipt: { + // blockHash: '0xd8f6a3638112d17b476fd1b7c4369d473bc1a484408b6f39dbf64410df44adf6', + // blockNumber: 24n, + // cumulativeGasUsed: 21000n, + // effectiveGasPrice: 2546893579n, + // from: '0xe2597eb05cf9a87eb1309e86750c903ec38e527e', + // gasUsed: 21000n, + // logs: [], + // logsBloom: '0x...0000', + // status: 1n, + // to: '0x27aa427c1d668ddefd7bc93f8857e7599ffd16ab', + // transactionHash: '0xd1d682b6f6467897db5b8f0a99a6be2fb788d32fbc1329b568b8f6b2c15e809a', + // transactionIndex: 0n, + // type: 1n + // } } (async () => { - await test(); + await test(); })(); ``` @@ -528,78 +528,78 @@ The code of `Greeter` contract you can find [here](https://github.com/web3/web3. ::: ```typescript -import {Web3} from 'web3'; +import { Web3 } from 'web3'; import { GreeterAbi, GreeterBytecode } from './fixture/Greeter'; const web3 = new Web3('http://localhost:8545'); async function test() { - const privateKey = 'YOUR PRIVATE KEY HERE'; - // add private key to wallet to have auto-signing transactions feature - const account = web3.eth.accounts.privateKeyToAccount(privateKey); - web3.eth.accounts.wallet.add(account); - - // deploy contract - const contract = new web3.eth.Contract(GreeterAbi); - const deployedContract = await contract - .deploy({ - data: GreeterBytecode, - arguments: ['My Greeting'], - }) - .send({ from: account.address }); - deployedContract.defaultAccount = account.address; - - const transaction = { - from: account.address, - to: deployedContract.options.address, - data: '0xcfae3217', // greet function call data encoded - }; - const { accessList } = await web3.eth.createAccessList(transaction, 'latest'); - - console.log('AccessList:', accessList); - // AccessList: [ - // { - // address: '0xce1f86f87bd3b8f32f0fb432f88e848f3a957ed7', - // storageKeys: [ - // '0x0000000000000000000000000000000000000000000000000000000000000001' - // ] - // } - // ] - - // create transaction object with accessList - const tx = { - from: account.address, - to: deployedContract.options.address, - gasLimit: BigInt(46000), - type: BigInt(1), // <- specify type - accessList, - data: '0xcfae3217', - // gasPrice - you can specify this property directly or web3js will fill this field automatically - }; - - // send transaction - const receipt = await web3.eth.sendTransaction(tx); - - console.log('Receipt:', receipt); - // Receipt: { - // blockHash: '0xc7b9561100c8ff6f1cde7a05916e86b7d037b2fdba86b0870e842d1814046e4b', - // blockNumber: 43n, - // cumulativeGasUsed: 26795n, - // effectiveGasPrice: 2504325716n, - // from: '0xe2597eb05cf9a87eb1309e86750c903ec38e527e', - // gasUsed: 26795n, - // logs: [], - // logsBloom: '0x...00000000000', - // status: 1n, - // to: '0xce1f86f87bd3b8f32f0fb432f88e848f3a957ed7', - // transactionHash: '0xa49753be1e2bd22c2a8e2530726614c808838bb0ebbed72809bbcb34f178799a', - // transactionIndex: 0n, - // type: 1n - // } + const privateKey = 'YOUR PRIVATE KEY HERE'; + // add private key to wallet to have auto-signing transactions feature + const account = web3.eth.accounts.privateKeyToAccount(privateKey); + web3.eth.accounts.wallet.add(account); + + // deploy contract + const contract = new web3.eth.Contract(GreeterAbi); + const deployedContract = await contract + .deploy({ + data: GreeterBytecode, + arguments: ['My Greeting'], + }) + .send({ from: account.address }); + deployedContract.defaultAccount = account.address; + + const transaction = { + from: account.address, + to: deployedContract.options.address, + data: '0xcfae3217', // greet function call data encoded + }; + const { accessList } = await web3.eth.createAccessList(transaction, 'latest'); + + console.log('AccessList:', accessList); + // AccessList: [ + // { + // address: '0xce1f86f87bd3b8f32f0fb432f88e848f3a957ed7', + // storageKeys: [ + // '0x0000000000000000000000000000000000000000000000000000000000000001' + // ] + // } + // ] + + // create transaction object with accessList + const tx = { + from: account.address, + to: deployedContract.options.address, + gasLimit: BigInt(46000), + type: BigInt(1), // <- specify type + accessList, + data: '0xcfae3217', + // gasPrice - you can specify this property directly or web3js will fill this field automatically + }; + + // send transaction + const receipt = await web3.eth.sendTransaction(tx); + + console.log('Receipt:', receipt); + // Receipt: { + // blockHash: '0xc7b9561100c8ff6f1cde7a05916e86b7d037b2fdba86b0870e842d1814046e4b', + // blockNumber: 43n, + // cumulativeGasUsed: 26795n, + // effectiveGasPrice: 2504325716n, + // from: '0xe2597eb05cf9a87eb1309e86750c903ec38e527e', + // gasUsed: 26795n, + // logs: [], + // logsBloom: '0x...00000000000', + // status: 1n, + // to: '0xce1f86f87bd3b8f32f0fb432f88e848f3a957ed7', + // transactionHash: '0xa49753be1e2bd22c2a8e2530726614c808838bb0ebbed72809bbcb34f178799a', + // transactionIndex: 0n, + // type: 1n + // } } (async () => { - await test(); + await test(); })(); ``` @@ -631,44 +631,44 @@ import { Web3 } from 'web3'; const web3 = new Web3('http://localhost:8545'); async function test() { - const privateKey = 'YOUR PRIVATE KEY HERE'; - // add private key to wallet to have auto-signing transactions feature - const account = web3.eth.accounts.privateKeyToAccount(privateKey); - web3.eth.accounts.wallet.add(account); - - // create transaction object - const tx = { - from: account.address, - to: '0x27aa427c1d668ddefd7bc93f8857e7599ffd16ab', - value: '0x1', - gasLimit: BigInt(21000), - type: BigInt(2), // <- specify type - // maxFeePerGas - you can specify this property directly or web3js will fill this field automatically - // maxPriorityFeePerGas - you can specify this property directly or web3js will fill this field automatically - }; - - // send transaction - const receipt = await web3.eth.sendTransaction(tx); - - console.log('Receipt:', receipt); - // Receipt: { - // blockHash: '0xfe472084d1471720b6887071d32a793f7c4576a489098e7d2a89aef205c977fb', - // blockNumber: 23n, - // cumulativeGasUsed: 21000n, - // effectiveGasPrice: 2546893579n, - // from: '0xe2597eb05cf9a87eb1309e86750c903ec38e527e', - // gasUsed: 21000n, - // logs: [], - // logsBloom: '0x0000...00000000000', - // status: 1n, - // to: '0x27aa427c1d668ddefd7bc93f8857e7599ffd16ab', - // transactionHash: '0x5c7a3d2965b426a5776e55f049ee379add44652322fb0b9fc2f7f57b38fafa2a', - // transactionIndex: 0n, - // type: 2n - // } + const privateKey = 'YOUR PRIVATE KEY HERE'; + // add private key to wallet to have auto-signing transactions feature + const account = web3.eth.accounts.privateKeyToAccount(privateKey); + web3.eth.accounts.wallet.add(account); + + // create transaction object + const tx = { + from: account.address, + to: '0x27aa427c1d668ddefd7bc93f8857e7599ffd16ab', + value: '0x1', + gasLimit: BigInt(21000), + type: BigInt(2), // <- specify type + // maxFeePerGas - you can specify this property directly or web3js will fill this field automatically + // maxPriorityFeePerGas - you can specify this property directly or web3js will fill this field automatically + }; + + // send transaction + const receipt = await web3.eth.sendTransaction(tx); + + console.log('Receipt:', receipt); + // Receipt: { + // blockHash: '0xfe472084d1471720b6887071d32a793f7c4576a489098e7d2a89aef205c977fb', + // blockNumber: 23n, + // cumulativeGasUsed: 21000n, + // effectiveGasPrice: 2546893579n, + // from: '0xe2597eb05cf9a87eb1309e86750c903ec38e527e', + // gasUsed: 21000n, + // logs: [], + // logsBloom: '0x0000...00000000000', + // status: 1n, + // to: '0x27aa427c1d668ddefd7bc93f8857e7599ffd16ab', + // transactionHash: '0x5c7a3d2965b426a5776e55f049ee379add44652322fb0b9fc2f7f57b38fafa2a', + // transactionIndex: 0n, + // type: 2n + // } } (async () => { - await test(); + await test(); })(); ``` @@ -699,4 +699,3 @@ The Ethereum ecosystem is constantly evolving, and there is always more to learn - Use the `estimateGas` function in web3.js to estimate the gas required for a transaction before sending it to the network. - Use events to notify the client application about state changes in the smart contract. - Use a linter like Solhint to check for common Solidity coding errors. - diff --git a/docs/docs/guides/web3_eth/methods.md b/docs/docs/guides/10_web3_eth/methods.md similarity index 97% rename from docs/docs/guides/web3_eth/methods.md rename to docs/docs/guides/10_web3_eth/methods.md index cc0f2f21df0..1a147916d48 100644 --- a/docs/docs/guides/web3_eth/methods.md +++ b/docs/docs/guides/10_web3_eth/methods.md @@ -7,7 +7,6 @@ sidebar_label: 'Web3Eth methods' ## createAccessList - The [createAccessList](/api/web3-eth/function/createAccessList) method is used to create an access list. Creating an access list in Ethereum is typically associated with Ethereum Improvement Proposal (EIP)-2930, which introduces a way to specify which accounts and storage keys a transaction expects to access. Access lists are used to optimize gas costs for transactions by providing explicit information about what the transaction needs to access. @@ -100,7 +99,7 @@ The [sendTransaction](/api/web3-eth/function/sendTransaction) method is used to :::important Please be cautious when sending transactions, especially when dealing with smart contracts, as they may execute specific functions that can have irreversible effects. Always ensure that the details in your transaction object are accurate and intended. -[Here](/guides/wallet/transactions) you can find more examples how to send transaction. +[Here](/guides/transactions/transactions) you can find more examples how to send transaction. ::: ## sign @@ -116,5 +115,5 @@ The [signTransaction](/api/web3-eth/function/signTransaction) method is used to The [sendSignedTransaction](/api/web3-eth/function/sendSignedTransaction) method is used to send a signed Ethereum transaction to the Ethereum network. Before sending a transaction, you need to sign it using a private key, and then you can use this method to broadcast the signed transaction to the network. :::note -[Here](/guides/wallet/transactions) you can find more examples how to send transaction. -::: \ No newline at end of file +[Here](/guides/transactions/transactions) you can find more examples how to send transaction. +::: diff --git a/docs/docs/guides/ens/index.md b/docs/docs/guides/11_ens/index.md similarity index 94% rename from docs/docs/guides/ens/index.md rename to docs/docs/guides/11_ens/index.md index a55f9662799..a98e899ad3a 100644 --- a/docs/docs/guides/ens/index.md +++ b/docs/docs/guides/11_ens/index.md @@ -1,14 +1,12 @@ --- -sidebar_position: 8 -sidebar_label: 'Mastering the Web3 ENS package' +sidebar_label: '📦 Web3 ENS module' title: Mastering the Web3 ENS package +position: 11 --- -# 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. +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 @@ -30,7 +28,6 @@ const web3 = new Web3('http://localhost:8545'); // You can use ENS with web3 object: const ens = await web3.eth.ens.getAddress('alice.eth'); - ``` ## Installing web3.js ENS @@ -44,10 +41,9 @@ npm install web3-eth-ens ```typescript import { ENS } from 'web3-eth-ens'; -const ens = new ENS(undefined,'https://127.0.0.1:4545'); +const ens = new ENS(undefined, 'https://127.0.0.1:4545'); console.log(await ens.getAddress('vitalik.eth')); - ``` ## ENS Examples diff --git a/docs/docs/guides/web3_utils_module/mastering_web3-utils.md b/docs/docs/guides/12_web3_utils_module/index.md similarity index 62% rename from docs/docs/guides/web3_utils_module/mastering_web3-utils.md rename to docs/docs/guides/12_web3_utils_module/index.md index b60d2a50deb..8a55f7bfe85 100644 --- a/docs/docs/guides/web3_utils_module/mastering_web3-utils.md +++ b/docs/docs/guides/12_web3_utils_module/index.md @@ -1,12 +1,18 @@ -# Mastering Utility Functions +--- +sidebar_label: '📦 Web3 Utils module' +title: Mastering Utility Functions +position: 12 +--- ## 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 ``` @@ -25,41 +31,40 @@ There are three different ways to import utils package. ```js // import web3 module -import { Web3 } from "web3"; +import { Web3 } from 'web3'; // no need to initialize a provider -Web3.utils.toHex("web3"); +Web3.utils.toHex('web3'); //=> 0x77656233 // initializing a provider -const web3 = new Web3("https:// eth.llamarpc.com"); +const web3 = new Web3('https:// eth.llamarpc.com'); // access the utils package -web3.utils.toHex("web3"); +web3.utils.toHex('web3'); //=> 0x77656233 ``` - ### Import utils module -```js +```js // import utils module -import { utils } from "web3"; +import { utils } from 'web3'; // access the utils package -utils.toWei("1", "ether") +utils.toWei('1', 'ether'); ``` ### Import specific methods ```js // import toWei and toHex functions -import { toWei, toHex } from"web3-utils"; +import { toWei, toHex } from 'web3-utils'; // usage -toWei("1", "ether") -toHex("") -``` +toWei('1', 'ether'); +toHex(''); +``` ## Methods example @@ -82,8 +87,8 @@ 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. ::: @@ -93,10 +98,10 @@ If you don't give any arguments then both of these functions will have a default We've got two different functions to perform conversions between Ethereum denominations. ```js -console.log(web3.utils.fromWei("1", "ether")); +console.log(web3.utils.fromWei('1', 'ether')); // 0.000000000000000001 -console.log(web3.utils.toWei("1", "ether")); +console.log(web3.utils.toWei('1', 'ether')); // 1_000_000_000_000_000_000 ``` @@ -128,48 +133,48 @@ console.log(web3.utils.bytesToHex(arr)); ### Conversions UTF and ASCII ```js -console.log(web3.utils.utf8ToHex("😊")); +console.log(web3.utils.utf8ToHex('😊')); // 0xf09f988a -console.log(web3.utils.fromUtf8("😊")); +console.log(web3.utils.fromUtf8('😊')); // 0xf09f988a -console.log(web3.utils.asciiToHex("😊")); +console.log(web3.utils.asciiToHex('😊')); // 0xd83dde0a -console.log(web3.utils.toUtf8("0xf09f988a")); +console.log(web3.utils.toUtf8('0xf09f988a')); // 😊 -console.log(web3.utils.hexToUtf8("0xf09f988a")); +console.log(web3.utils.hexToUtf8('0xf09f988a')); // 😊 -console.log(web3.utils.hexToString("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")); +console.log(web3.utils.toAscii('0x4869')); // Hi -console.log(web3.utils.hexToAscii("0x4869")); +console.log(web3.utils.hexToAscii('0x4869')); // Hi ``` ### Conversions - Numbers and Bigint ```js -console.log(web3.utils.toNumber("0xa")); +console.log(web3.utils.toNumber('0xa')); // 10 (number) -console.log(web3.utils.hexToNumber("0xa")); +console.log(web3.utils.hexToNumber('0xa')); // 10 (number) -console.log(web3.utils.toDecimal("0xa")); +console.log(web3.utils.toDecimal('0xa')); // 10 (number) -console.log(web3.utils.hexToNumberString("0xa")); +console.log(web3.utils.hexToNumberString('0xa')); // 10 (string) -console.log(web3.utils.toBigInt("0xa")); +console.log(web3.utils.toBigInt('0xa')); // 10n (bigint) ``` @@ -177,10 +182,10 @@ console.log(web3.utils.toBigInt("0xa")); ```js // both will return undefined if an empty string is passed as an argument -console.log(web3.utils.sha3("hello web3")); +console.log(web3.utils.sha3('hello web3')); // 0x6c171485a0138b7b0a49d72b570e1d9c589d42a79ae57329d90671d1ac702d74 -console.log(web3.utils.soliditySha3({ type: "string", value: "hello web3" })); +console.log(web3.utils.soliditySha3({ type: 'string', value: 'hello web3' })); // 0x6c171485a0138b7b0a49d72b570e1d9c589d42a79ae57329d90671d1ac702d74 ``` @@ -191,11 +196,11 @@ console.log(web3.utils.soliditySha3({ type: "string", value: "hello web3" })); // 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")); +console.log(web3.utils.toChecksumAddress('0xa3286628134bad128faeef82f44e99aa64085c94')); // 0xA3286628134baD128faeef82F44e99AA64085C94 // passing an wrong address -console.log(web3.utils.toChecksumAddress("0xa3286628134bad128faeef82f44e99aa64085c9")); +console.log(web3.utils.toChecksumAddress('0xa3286628134bad128faeef82f44e99aa64085c9')); // InvalidAddressError: Invalid value given "0xa286628134bad128faeef82f44e99aa64085c94". Error: invalid ethereum address. ``` @@ -204,10 +209,9 @@ console.log(web3.utils.toChecksumAddress("0xa3286628134bad128faeef82f44e99aa6408 ```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")); +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)); @@ -227,13 +231,13 @@ console.log(web3.utils.leftPad(10, 32, 0)); ```js // accepts numbers and formats as well -console.log(web3.utils.compareBlockNumbers("pending", "latest")); +console.log(web3.utils.compareBlockNumbers('pending', 'latest')); // 1 -console.log(web3.utils.compareBlockNumbers("latest", "pending")); +console.log(web3.utils.compareBlockNumbers('latest', 'pending')); // -1 -console.log(web3.utils.compareBlockNumbers("latest", "latest")); +console.log(web3.utils.compareBlockNumbers('latest', 'latest')); // 0 console.log(web3.utils.compareBlockNumbers(2, 2)); @@ -247,50 +251,50 @@ The [`format` function](/api/web3-utils/function/format) in the `web3-utils` pac Here are some example that demonstrate the use of the `format` function: ```js -import { format } from "web3-utils"; -import { FMT_BYTES, FMT_NUMBER } from "web3-types"; +import { format } from 'web3-utils'; +import { FMT_BYTES, FMT_NUMBER } from 'web3-types'; // format a primitive number as a hexidecimal string -console.log(format({ format: "uint" }, 221, { number: FMT_NUMBER.HEX })); +console.log(format({ format: 'uint' }, 221, { number: FMT_NUMBER.HEX })); // ↳ 0xdd // format a primitive number as a BigInt -console.log(format({ format: "uint" }, 221, { number: FMT_NUMBER.BIGINT })); +console.log(format({ format: 'uint' }, 221, { number: FMT_NUMBER.BIGINT })); // ↳ 221n // format a stringified number as a hexidecimal string -console.log(format({ format: "uint" }, "221", { number: FMT_NUMBER.HEX })); +console.log(format({ format: 'uint' }, '221', { number: FMT_NUMBER.HEX })); // ↳ 0xdd // format a Uint8Array of bytes as a hexidecimal string console.log( - format({ format: "bytes" }, new Uint8Array([2, 33]), { - bytes: FMT_BYTES.HEX, - }), + format({ format: 'bytes' }, new Uint8Array([2, 33]), { + bytes: FMT_BYTES.HEX, + }), ); // ↳ 0x0221 // format an array of values console.log( - format({ type: "array", items: { format: "uint" } }, ["221", 1983], { - number: FMT_NUMBER.HEX, - }), + format({ type: 'array', items: { format: 'uint' } }, ['221', 1983], { + number: FMT_NUMBER.HEX, + }), ); // ↳ [ '0xdd', '0x7bf' ] // format an object with multiple properties console.log( - format( - { - type: "object", - properties: { - aNumber: { format: "uint" }, - someBytes: { format: "bytes" }, - }, - }, - { aNumber: "221", someBytes: new Uint8Array([2, 33]) }, - { bytes: FMT_BYTES.UINT8ARRAY, number: FMT_NUMBER.HEX }, - ), + format( + { + type: 'object', + properties: { + aNumber: { format: 'uint' }, + someBytes: { format: 'bytes' }, + }, + }, + { aNumber: '221', someBytes: new Uint8Array([2, 33]) }, + { bytes: FMT_BYTES.UINT8ARRAY, number: FMT_NUMBER.HEX }, + ), ); // ↳ { aNumber: '0xdd', someBytes: Uint8Array(2) [ 2, 33 ] } ``` @@ -299,11 +303,11 @@ console.log( The following return formats are supported: -- Bytes - - [`FMT_BYTES.HEX`](/api/web3-types/enum/FMT_BYTES#HEX): hexadecimal [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) (e.g. `"0xdd"`) - - [`FMT_BYTES.UINT8ARRAY`](/api/web3-types/enum/FMT_BYTES#UINT8ARRAY): [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) (e.g. `[ 2, 33 ]`) -- Numbers - - [`FMT_NUMBER.BIGINT`](/api/web3-types/enum/FMT_NUMBER#BIGINT): [`BigInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) (e.g. `221n`) - - [`FMT_NUMBER.HEX`](/api/web3-types/enum/FMT_NUMBER#HEX): hexadecimal [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) (e.g. `"0xdd"`) - - [`FMT_NUMBER.NUMBER`](/api/web3-types/enum/FMT_NUMBER#NUMBER): [`Number`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number) (e.g. `221`) - - [`FMT_NUMBER.STR`](/api/web3-types/enum/FMT_NUMBER#STR): [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) (e.g. `"221"`) +- Bytes + - [`FMT_BYTES.HEX`](/api/web3-types/enum/FMT_BYTES#HEX): hexadecimal [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) (e.g. `"0xdd"`) + - [`FMT_BYTES.UINT8ARRAY`](/api/web3-types/enum/FMT_BYTES#UINT8ARRAY): [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) (e.g. `[ 2, 33 ]`) +- Numbers + - [`FMT_NUMBER.BIGINT`](/api/web3-types/enum/FMT_NUMBER#BIGINT): [`BigInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) (e.g. `221n`) + - [`FMT_NUMBER.HEX`](/api/web3-types/enum/FMT_NUMBER#HEX): hexadecimal [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) (e.g. `"0xdd"`) + - [`FMT_NUMBER.NUMBER`](/api/web3-types/enum/FMT_NUMBER#NUMBER): [`Number`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number) (e.g. `221`) + - [`FMT_NUMBER.STR`](/api/web3-types/enum/FMT_NUMBER#STR): [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) (e.g. `"221"`) diff --git a/docs/docs/guides/advanced/_category_.yml b/docs/docs/guides/13_advanced/_category_.yml similarity index 83% rename from docs/docs/guides/advanced/_category_.yml rename to docs/docs/guides/13_advanced/_category_.yml index c6ab4f48016..f427d428cc2 100644 --- a/docs/docs/guides/advanced/_category_.yml +++ b/docs/docs/guides/13_advanced/_category_.yml @@ -2,4 +2,4 @@ label: '🧠 Advanced' collapsible: true collapsed: true link: null -position: 11 +position: 13 diff --git a/docs/docs/guides/advanced/custom_RPC.md b/docs/docs/guides/13_advanced/custom_RPC.md similarity index 100% rename from docs/docs/guides/advanced/custom_RPC.md rename to docs/docs/guides/13_advanced/custom_RPC.md diff --git a/docs/docs/guides/advanced/extend.md b/docs/docs/guides/13_advanced/extend.md similarity index 100% rename from docs/docs/guides/advanced/extend.md rename to docs/docs/guides/13_advanced/extend.md diff --git a/docs/docs/guides/advanced/tree_shaking.md b/docs/docs/guides/13_advanced/tree_shaking.md similarity index 100% rename from docs/docs/guides/advanced/tree_shaking.md rename to docs/docs/guides/13_advanced/tree_shaking.md diff --git a/docs/docs/guides/web3_plugin_guide/_category_.yml b/docs/docs/guides/14_web3_plugin_guide/_category_.yml similarity index 85% rename from docs/docs/guides/web3_plugin_guide/_category_.yml rename to docs/docs/guides/14_web3_plugin_guide/_category_.yml index 8ab333571fd..8f57d7b3e6f 100644 --- a/docs/docs/guides/web3_plugin_guide/_category_.yml +++ b/docs/docs/guides/14_web3_plugin_guide/_category_.yml @@ -2,4 +2,4 @@ label: '🛠️ Web3 Plugin 🧩' collapsible: true collapsed: true link: null -position: 12 +position: 14 diff --git a/docs/docs/guides/web3_plugin_guide/assets/web3_context_augmentation.png b/docs/docs/guides/14_web3_plugin_guide/assets/web3_context_augmentation.png similarity index 100% rename from docs/docs/guides/web3_plugin_guide/assets/web3_context_augmentation.png rename to docs/docs/guides/14_web3_plugin_guide/assets/web3_context_augmentation.png diff --git a/docs/docs/guides/web3_plugin_guide/index.mdx b/docs/docs/guides/14_web3_plugin_guide/index.mdx similarity index 99% rename from docs/docs/guides/web3_plugin_guide/index.mdx rename to docs/docs/guides/14_web3_plugin_guide/index.mdx index ef1942c53fc..52f826601a7 100644 --- a/docs/docs/guides/web3_plugin_guide/index.mdx +++ b/docs/docs/guides/14_web3_plugin_guide/index.mdx @@ -277,7 +277,7 @@ class MyPlugin extends Web3PluginBase { } ``` :::info -All web3 config params [here](https://docs.web3js.org/guides/web3_config/) +All web3 config params [here](https://docs.web3js.org/guides/web3_config/index) ::: diff --git a/docs/docs/guides/web3_plugin_guide/plugin_authors.md b/docs/docs/guides/14_web3_plugin_guide/plugin_authors.md similarity index 82% rename from docs/docs/guides/web3_plugin_guide/plugin_authors.md rename to docs/docs/guides/14_web3_plugin_guide/plugin_authors.md index 4100882e67f..5a01ceed8de 100644 --- a/docs/docs/guides/web3_plugin_guide/plugin_authors.md +++ b/docs/docs/guides/14_web3_plugin_guide/plugin_authors.md @@ -19,7 +19,7 @@ To provide type safety and IntelliSense for your plugin users, please refer to t At the minimum, your plugin should depend on `web3` package version `4.0.2`. This will allow your plugin class to extend the provided `Web3PluginBase` abstract class. However, `web3` shouldn't be listed as a regular dependency, instead it should be listed in your plugin's `package.json` as a [peer dependency](https://nodejs.org/en/blog/npm/peer-dependencies/). :::important -It is important to note that the plugin name should be structured as `@/web3-plugin-` or `web3-plugin-`. +It is important to note that the plugin name should be structured as `@/web3-plugin-` or `web3-plugin-`. ::: ```json @@ -38,24 +38,23 @@ When your users install your plugin, this will allow the package manager to make Furthermore, you have the flexibility to expand your range of transaction types, enhancing compatibility with the `web3.js` library. - ```typescript // create new TransactionType class which extends BaseTransaction class import { BaseTransaction } from 'web3-eth-accounts'; const TRANSACTION_TYPE = 15; class SomeNewTxTypeTransaction extends BaseTransaction { - // ... + // ... } // create new plugin and add `SomeNewTxTypeTransaction` to the library import { Web3EthPluginBase } from 'web3'; class SomeNewTxTypeTransactionPlugin extends Web3PluginBase { - public pluginNamespace = 'someNewTxTypeTransaction'; - public constructor() { - super(); - TransactionFactory.registerTransactionType(TRANSACTION_TYPE, SomeNewTxTypeTransaction); - } + public pluginNamespace = 'someNewTxTypeTransaction'; + public constructor() { + super(); + TransactionFactory.registerTransactionType(TRANSACTION_TYPE, SomeNewTxTypeTransaction); + } } ``` @@ -90,11 +89,11 @@ The following represents your plugin code: import { Web3PluginBase } from 'web3'; export class CustomRpcMethodsPlugin extends Web3PluginBase { - public pluginNamespace = 'customRpcMethods'; + public pluginNamespace = 'customRpcMethods'; - public someMethod() { - return 'someValue'; - } + public someMethod() { + return 'someValue'; + } } ``` @@ -120,14 +119,14 @@ Below is an example of `CustomRpcMethodsPlugin` making use of `this.requestManag import { Web3PluginBase } from 'web3'; export class CustomRpcMethodsPlugin extends Web3PluginBase { - public pluginNamespace = 'customRpcMethods'; - - public async customRpcMethod() { - return this.requestManager.send({ - method: 'custom_rpc_method', - params: [], - }); - } + public pluginNamespace = 'customRpcMethods'; + + public async customRpcMethod() { + return this.requestManager.send({ + method: 'custom_rpc_method', + params: [], + }); + } } ``` @@ -161,18 +160,18 @@ If needed, you can provide an API type (that follows the [Web3ApiSpec](/api/web3 import { Web3PluginBase } from 'web3'; type CustomRpcApi = { - custom_rpc_method_with_parameters: (parameter1: string, parameter2: number) => string; + custom_rpc_method_with_parameters: (parameter1: string, parameter2: number) => string; }; export class CustomRpcMethodsPlugin extends Web3PluginBase { - public pluginNamespace = 'customRpcMethods'; - - public async customRpcMethodWithParameters(parameter1: string, parameter2: number) { - return this.requestManager.send({ - method: 'custom_rpc_method_with_parameters', - params: [parameter1, parameter2], - }); - } + public pluginNamespace = 'customRpcMethods'; + + public async customRpcMethodWithParameters(parameter1: string, parameter2: number) { + return this.requestManager.send({ + method: 'custom_rpc_method_with_parameters', + params: [parameter1, parameter2], + }); + } } ``` @@ -190,32 +189,39 @@ import { Contract, ContractAbi, Web3Context, Web3PluginBase, types, utils } from import { ERC20TokenAbi } from './ERC20Token'; export class ContractMethodWrappersPlugin extends Web3PluginBase { - public pluginNamespace = 'contractMethodWrappersPlugin'; - - private readonly _contract: Contract; - - public constructor(abi: ContractAbi, address: types.Address) { - super(); - this._contract = new Contract(abi, address); - } - - /** - * This method overrides the inherited `link` method from - * `Web3PluginBase` to add a configured `RequestManager` - * to the Contract instance when `Web3.registerPlugin` - * is called. - * - * @param parentContext - The context to be added to the instance of `ChainlinkPlugin`, - * and by extension, the instance of `Contract`. - */ - public link(parentContext: Web3Context) { - super.link(parentContext); - this._contract.link(parentContext); - } - - public async getFormattedBalance(address: types.Address, returnFormat?: ReturnFormat) { - return utils.format({ eth: 'unit' }, await this._contract.methods.balanceOf(address).call(), returnFormat ?? types.DEFAULT_RETURN_FORMAT); - } + public pluginNamespace = 'contractMethodWrappersPlugin'; + + private readonly _contract: Contract; + + public constructor(abi: ContractAbi, address: types.Address) { + super(); + this._contract = new Contract(abi, address); + } + + /** + * This method overrides the inherited `link` method from + * `Web3PluginBase` to add a configured `RequestManager` + * to the Contract instance when `Web3.registerPlugin` + * is called. + * + * @param parentContext - The context to be added to the instance of `ChainlinkPlugin`, + * and by extension, the instance of `Contract`. + */ + public link(parentContext: Web3Context) { + super.link(parentContext); + this._contract.link(parentContext); + } + + public async getFormattedBalance( + address: types.Address, + returnFormat?: ReturnFormat, + ) { + return utils.format( + { eth: 'unit' }, + await this._contract.methods.balanceOf(address).call(), + returnFormat ?? types.DEFAULT_RETURN_FORMAT, + ); + } } ``` @@ -243,24 +249,22 @@ Request middleware allows plugins to modify RPC requests before they are sent to ```ts export class RequestMiddleware implements RequestManagerMiddleware { - public async processRequest( - request: JsonRpcPayload - ): Promise> { - const reqObj = { ...request } as JsonRpcPayload; - console.log("Request:", reqObj); - return Promise.resolve(reqObj as JsonRpcPayload); - } - - public async processResponse< - Method extends Web3APIMethod, - ResponseType = Web3APIReturnType - >( - response: JsonRpcResponse - ): Promise> { - const resObj = { ...response }; - console.log("Response:", resObj); - return Promise.resolve(resObj); - } + public async processRequest( + request: JsonRpcPayload, + ): Promise> { + const reqObj = { ...request } as JsonRpcPayload; + console.log('Request:', reqObj); + return Promise.resolve(reqObj as JsonRpcPayload); + } + + public async processResponse< + Method extends Web3APIMethod, + ResponseType = Web3APIReturnType, + >(response: JsonRpcResponse): Promise> { + const resObj = { ...response }; + console.log('Response:', resObj); + return Promise.resolve(resObj); + } } ``` @@ -279,13 +283,13 @@ Transaction middleware allows plugins to modify transaction data before it is se ```ts export class TxnMiddleware implements TransactionMiddleware { - public async processTransaction( - transaction: TransactionMiddlewareData - ): Promise { - const txObj = { ...transaction }; - console.log("Transaction data:", txObj); - return Promise.resolve(txObj); - } + public async processTransaction( + transaction: TransactionMiddlewareData, + ): Promise { + const txObj = { ...transaction }; + console.log('Transaction data:', txObj); + return Promise.resolve(txObj); + } } ``` @@ -315,20 +319,20 @@ When registering a plugin, you're adding additional methods and/or classes to th import { Web3PluginBase } from 'web3'; export class CustomRpcMethodsPlugin extends Web3PluginBase { - public pluginNamespace = 'customRpcMethods'; + public pluginNamespace = 'customRpcMethods'; - public someMethod() { - return 'someValue'; - } + public someMethod() { + return 'someValue'; + } } // Module Augmentation declare module 'web3' { - // Here is where you're adding your plugin's - // class inside Web3Context class - interface Web3Context { - customRpcMethods: CustomRpcMethodsPlugin; - } + // Here is where you're adding your plugin's + // class inside Web3Context class + interface Web3Context { + customRpcMethods: CustomRpcMethodsPlugin; + } } ``` @@ -360,10 +364,10 @@ But, the user who does not call `.registerPlugin`, before accessing your plugin, // code written by the plugin **developer** declare module 'web3' { - // Here is where you're adding your plugin inside Web3Context - interface Web3Context { - customRpcMethods: CustomRpcMethodsPlugin; - } + // Here is where you're adding your plugin inside Web3Context + interface Web3Context { + customRpcMethods: CustomRpcMethodsPlugin; + } } ``` @@ -373,9 +377,9 @@ Your the plugin class: // code written by the plugin **developer** export class CustomRpcMethodsPlugin extends Web3PluginBase { - public pluginNamespace = 'customRpcMethods'; + public pluginNamespace = 'customRpcMethods'; - //... + //... } ``` diff --git a/docs/docs/guides/web3_plugin_guide/plugin_users.md b/docs/docs/guides/14_web3_plugin_guide/plugin_users.md similarity index 83% rename from docs/docs/guides/web3_plugin_guide/plugin_users.md rename to docs/docs/guides/14_web3_plugin_guide/plugin_users.md index 3c900d9e2a3..585f27699ad 100644 --- a/docs/docs/guides/web3_plugin_guide/plugin_users.md +++ b/docs/docs/guides/14_web3_plugin_guide/plugin_users.md @@ -34,8 +34,8 @@ For illustration purposes, let's assume a plugin developer has the following cod - + ```typescript // code written by the plugin **developer** @@ -43,18 +43,18 @@ For illustration purposes, let's assume a plugin developer has the following cod const { Web3PluginBase } = require('web3'); export class PluginExample extends Web3PluginBase { - public pluginNamespace = 'pluginExample'; + public pluginNamespace = 'pluginExample'; - public sampleMethod() { - return 'simpleValue'; - } + public sampleMethod() { + return 'simpleValue'; + } } // Module Augmentation declare module 'web3' { - interface Web3Context { - pluginExample: PluginExample; - } + interface Web3Context { + pluginExample: PluginExample; + } } ``` @@ -63,25 +63,24 @@ declare module 'web3' { - ```typescript // code written by the plugin **developer** import { Web3PluginBase } from 'web3'; export class PluginExample extends Web3PluginBase { - public pluginNamespace = 'pluginExample'; + public pluginNamespace = 'pluginExample'; - public sampleMethod() { - return 'simpleValue'; - } + public sampleMethod() { + return 'simpleValue'; + } } // Module Augmentation declare module 'web3' { - interface Web3Context { - pluginExample: PluginExample; - } + interface Web3Context { + pluginExample: PluginExample; + } } ``` @@ -92,8 +91,8 @@ Here is an example of how to register the `PluginExample` onto an instance of `W - + ```javascript // code written by the plugin **user** @@ -112,7 +111,6 @@ web3.pluginExample.sampleMethod(); - ```typescript // code written by the plugin **user** @@ -126,4 +124,4 @@ web3.pluginExample.sampleMethod(); ``` - \ No newline at end of file + diff --git a/docs/docs/guides/migration_from_other_libs/_category_.yml b/docs/docs/guides/15_web3_upgrade_guide/_category_.yml similarity index 62% rename from docs/docs/guides/migration_from_other_libs/_category_.yml rename to docs/docs/guides/15_web3_upgrade_guide/_category_.yml index 59fb5de8cdc..635cb9d743a 100644 --- a/docs/docs/guides/migration_from_other_libs/_category_.yml +++ b/docs/docs/guides/15_web3_upgrade_guide/_category_.yml @@ -1,4 +1,4 @@ -label: '🔄 Migration Guides' +label: '⬆️ Upgrading from 1.x' collapsible: true collapsed: true link: null diff --git a/docs/docs/guides/web3_upgrade_guide/1.x/abi_migration_guide.md b/docs/docs/guides/15_web3_upgrade_guide/abi_migration_guide.md similarity index 100% rename from docs/docs/guides/web3_upgrade_guide/1.x/abi_migration_guide.md rename to docs/docs/guides/15_web3_upgrade_guide/abi_migration_guide.md diff --git a/docs/docs/guides/web3_upgrade_guide/1.x/accounts_migration_guide.md b/docs/docs/guides/15_web3_upgrade_guide/accounts_migration_guide.md similarity index 99% rename from docs/docs/guides/web3_upgrade_guide/1.x/accounts_migration_guide.md rename to docs/docs/guides/15_web3_upgrade_guide/accounts_migration_guide.md index f6505e460f8..ec18f7e7f9c 100644 --- a/docs/docs/guides/web3_upgrade_guide/1.x/accounts_migration_guide.md +++ b/docs/docs/guides/15_web3_upgrade_guide/accounts_migration_guide.md @@ -43,5 +43,4 @@ In 1.x `stripHexPrefix` method is located in the `web3-utils` package, in 4.x th import { stripHexPrefix } from 'web3-eth-accounts'; console.log(stripHexPrefix('0x123')); // "123" - ``` diff --git a/docs/docs/guides/web3_upgrade_guide/1.x/contracts_migration_guide.md b/docs/docs/guides/15_web3_upgrade_guide/contracts_migration_guide.md similarity index 100% rename from docs/docs/guides/web3_upgrade_guide/1.x/contracts_migration_guide.md rename to docs/docs/guides/15_web3_upgrade_guide/contracts_migration_guide.md diff --git a/docs/docs/guides/web3_upgrade_guide/1.x/index.md b/docs/docs/guides/15_web3_upgrade_guide/index.md similarity index 95% rename from docs/docs/guides/web3_upgrade_guide/1.x/index.md rename to docs/docs/guides/15_web3_upgrade_guide/index.md index b375a63974f..d6c099804c9 100644 --- a/docs/docs/guides/web3_upgrade_guide/1.x/index.md +++ b/docs/docs/guides/15_web3_upgrade_guide/index.md @@ -3,7 +3,6 @@ sidebar_position: 1 sidebar_label: 'Introduction' --- - import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; @@ -28,8 +27,8 @@ And the correct usage now is: - + ```javascript const { Web3 } = require('web3'); @@ -57,11 +56,10 @@ Passing callbacks to functions is no longer supported, except for event listener For example, the approach to subscribing-to and listening-for blockchain events has changed in version 4.x. Detailed instructions can be found in the [**`web3.eth.subscribe` Migration Guide**](./subscribe_migration_guide.md#subscribing-to-events). -However, the approach to subscribing to Provider events remains the same, utilizing callbacks as explained in the [Providers Events Listening guide](../../web3_providers_guide/events_listening.md). It is important to note that Providers have undergone some breaking changes, including the renaming of the `on('close', ...)` to `on('disconnect', ...)`. +However, the approach to subscribing to Provider events remains the same, utilizing callbacks as explained in the [Providers Events Listening guide](/guides/02_web3_providers_guide/events_listening.md). It is important to note that Providers have undergone some breaking changes, including the renaming of the `on('close', ...)` to `on('disconnect', ...)`. ### Not Available - - [web3.bzz](https://web3js.readthedocs.io/en/v1.7.3/web3-bzz.html) Package for interacting with Swarm is not implemented - [web3.shh](https://web3js.readthedocs.io/en/v1.7.3/web3-shh.html) Package for interacting with Whisper is not implemented @@ -82,6 +80,7 @@ It will not have: :::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/docs/docs/guides/web3_upgrade_guide/1.x/net_migration_guide.md b/docs/docs/guides/15_web3_upgrade_guide/net_migration_guide.md similarity index 100% rename from docs/docs/guides/web3_upgrade_guide/1.x/net_migration_guide.md rename to docs/docs/guides/15_web3_upgrade_guide/net_migration_guide.md diff --git a/docs/docs/guides/web3_upgrade_guide/1.x/personal_migration_guide.md b/docs/docs/guides/15_web3_upgrade_guide/personal_migration_guide.md similarity index 100% rename from docs/docs/guides/web3_upgrade_guide/1.x/personal_migration_guide.md rename to docs/docs/guides/15_web3_upgrade_guide/personal_migration_guide.md diff --git a/docs/docs/guides/web3_upgrade_guide/1.x/providers_migration_guide.md b/docs/docs/guides/15_web3_upgrade_guide/providers_migration_guide.md similarity index 99% rename from docs/docs/guides/web3_upgrade_guide/1.x/providers_migration_guide.md rename to docs/docs/guides/15_web3_upgrade_guide/providers_migration_guide.md index 46375cdd0df..990ec6a989d 100644 --- a/docs/docs/guides/web3_upgrade_guide/1.x/providers_migration_guide.md +++ b/docs/docs/guides/15_web3_upgrade_guide/providers_migration_guide.md @@ -4,7 +4,7 @@ sidebar_position: 2 sidebar_label: web3.providers --- -For full description about the providers, their priorities and their types, you can check [web3.js Providers Guide](../../web3_providers_guide/). +For full description about the providers, their priorities and their types, you can check [web3.js Providers Guide](/guides/web3_providers_guide/). ### Provider Options Changes diff --git a/docs/docs/guides/web3_upgrade_guide/1.x/subscribe_migration_guide.md b/docs/docs/guides/15_web3_upgrade_guide/subscribe_migration_guide.md similarity index 100% rename from docs/docs/guides/web3_upgrade_guide/1.x/subscribe_migration_guide.md rename to docs/docs/guides/15_web3_upgrade_guide/subscribe_migration_guide.md diff --git a/docs/docs/guides/web3_upgrade_guide/1.x/web3_eth_ens.md b/docs/docs/guides/15_web3_upgrade_guide/web3_eth_ens.md similarity index 100% rename from docs/docs/guides/web3_upgrade_guide/1.x/web3_eth_ens.md rename to docs/docs/guides/15_web3_upgrade_guide/web3_eth_ens.md diff --git a/docs/docs/guides/web3_upgrade_guide/1.x/web3_eth_iban.md b/docs/docs/guides/15_web3_upgrade_guide/web3_eth_iban.md similarity index 100% rename from docs/docs/guides/web3_upgrade_guide/1.x/web3_eth_iban.md rename to docs/docs/guides/15_web3_upgrade_guide/web3_eth_iban.md diff --git a/docs/docs/guides/web3_upgrade_guide/1.x/web3_eth_migration_guide.md b/docs/docs/guides/15_web3_upgrade_guide/web3_eth_migration_guide.md similarity index 100% rename from docs/docs/guides/web3_upgrade_guide/1.x/web3_eth_migration_guide.md rename to docs/docs/guides/15_web3_upgrade_guide/web3_eth_migration_guide.md diff --git a/docs/docs/guides/web3_upgrade_guide/1.x/web3_utils_migration_guide.md b/docs/docs/guides/15_web3_upgrade_guide/web3_utils_migration_guide.md similarity index 100% rename from docs/docs/guides/web3_upgrade_guide/1.x/web3_utils_migration_guide.md rename to docs/docs/guides/15_web3_upgrade_guide/web3_utils_migration_guide.md diff --git a/docs/docs/guides/16_wagmi_usage/index.md b/docs/docs/guides/16_wagmi_usage/index.md new file mode 100644 index 00000000000..4d57030bf9e --- /dev/null +++ b/docs/docs/guides/16_wagmi_usage/index.md @@ -0,0 +1,127 @@ +--- +sidebar_label: '🔄 Wagmi usage' +title: 'Wagmi Web3.js Adapter' +position: 16 +--- + +### Reference Implementation + +If you're using [Wagmi](https://wagmi.sh/react/getting-started#use-wagmi) and want to add web3.js, use this code in your project. This snippet will help you to convert a `Viem` client to a `web3.js` instance for signing transactions and interacting with the blockchain: + +```typescript +import { Web3 } from 'web3'; +import { useMemo } from 'react'; +import type { Chain, Client, Transport } from 'viem'; +import { type Config, useClient, useConnectorClient } from 'wagmi'; + +export function clientToWeb3js(client?: Client) { + if (!client) { + return new Web3(); + } + + const { transport } = client; + + if (transport.type === 'fallback') { + return new Web3(transport.transports[0].value.url); + } + return new Web3(transport); +} + +/** Action to convert a viem Client to a web3.js Instance. */ +export function useWeb3js({ chainId }: { chainId?: number } = {}) { + const client = useClient({ chainId }); + return useMemo(() => clientToWeb3js(client), [client]); +} + +/** Action to convert a viem ConnectorClient to a web3.js Instance. */ +export function useWeb3jsSigner({ chainId }: { chainId?: number } = {}) { + const { data: client } = useConnectorClient({ chainId }); + return useMemo(() => clientToWeb3js(client), [client]); +} +``` + +### Usage examples + +Get block data example: + +```typescript +import { useWeb3js } from '../web3/useWeb3js'; +import { mainnet } from 'wagmi/chains'; +import { useEffect, useState } from 'react'; + +type Block = { + hash: string; + extraData: string; + miner: string; +}; + +function Block() { + const web3js = useWeb3js({ chainId: mainnet.id }); + const [block, setBlock] = useState(); + + useEffect(() => { + web3js.eth + .getBlock(19235006) + .then(b => { + setBlock(b as Block); + }) + .catch(console.error); + }, [setBlock]); + + if (!block) return
Loading...
; + + return ( + <> +
{block.hash}
+
{block.extraData}
+
{block.miner}
+ + ); +} + +export default Block; +``` + +Send transaction example: + +```typescript +import { mainnet } from 'wagmi/chains'; +import { useAccount, useConnect } from 'wagmi'; +import { useWeb3jsSigner } from '../web3/useWeb3js'; +import { useEffect } from 'react'; + +function SendTransaction() { + const account = useAccount(); + const { connectors, connect } = useConnect(); + const web3js = useWeb3jsSigner({ chainId: mainnet.id }); + + useEffect(() => { + if (account && account.address) { + web3js.eth + .sendTransaction({ + from: account.address, + to: '0x', // some address + value: '0x1', // set your value + }) + .then(console.log) + .catch(console.error); + } + }, [account]); + + return ( + <> + {connectors.map(connector => ( + + ))} + + ); +} + +export default SendTransaction; +``` + +:::tip +[This repository](https://github.com/avkos/wagmi-web3js-example-app) contains an example Wagmi app that demonstrates how to interact with the Ethereum blockchain using the web3.js library +::: diff --git a/docs/docs/guides/migration_from_other_libs/ethers.md b/docs/docs/guides/17_migration_from_other_libs/index.md similarity index 79% rename from docs/docs/guides/migration_from_other_libs/ethers.md rename to docs/docs/guides/17_migration_from_other_libs/index.md index 3d924499972..78e1f48d20c 100644 --- a/docs/docs/guides/migration_from_other_libs/ethers.md +++ b/docs/docs/guides/17_migration_from_other_libs/index.md @@ -1,7 +1,7 @@ --- -sidebar_position: 1 -sidebar_label: 'Migration from ethers.js' +sidebar_label: '🔄 Migration from ethers.js' title: 'Migration from ethers.js' +position: 17 --- Follow this guide, if you're currently using the ethers.js library to interact with the Ethereum blockchain and want to migrate to web3.js. This guide is for ethers v5 and v6. And, if there are differences, code for both would be provided. And, if you find something missing, or worth adding, feel free to open a PR, please. @@ -51,21 +51,21 @@ blockNumber.then(console.log); :::tip 📝 web3.js uses `bigint` as the default type for all big numbers returned. For, this you see above the blocknumber has the `n` at its end (`18561956n`). However, you can change the returned type by passing an optional parameter like: -::: +::: + ```ts title='BigInt Tip' import { Web3, DEFAULT_RETURN_FORMAT, FMT_NUMBER } from 'web3'; const blockNumber = web3.eth.getBlockNumber({ - ...DEFAULT_RETURN_FORMAT, - number: FMT_NUMBER.HEX, // to get the block number in hex format + ...DEFAULT_RETURN_FORMAT, + number: FMT_NUMBER.HEX, // to get the block number in hex format }); // outputs something like: 0x11B3BA4 blockNumber.then(console.log); - const blockNumber = web3.eth.getBlockNumber({ - ...DEFAULT_RETURN_FORMAT, - number: FMT_NUMBER.STR, // to get the block number as a string + ...DEFAULT_RETURN_FORMAT, + number: FMT_NUMBER.STR, // to get the block number as a string }); // the value would like: '18561956' blockNumber.then(console.log); @@ -89,7 +89,6 @@ With web3.js: const web3 = new Web3(window.ethereum); ``` - ## Wallets and Accounts ### Generate Private Key @@ -111,15 +110,16 @@ With web3.js: // (Be sure to store it encrypted in a safe place) const privateKey = web3.eth.accounts.create().privateKey; ``` + ### Create a wallet In ethers.js: ```typescript const wallet = new ethers.Wallet( - // A private key that you might had generated with: - // ethers.Wallet.createRandom().privateKey - privateKey, + // A private key that you might had generated with: + // ethers.Wallet.createRandom().privateKey + privateKey, ); // outputs: 0x6f7D735dFB514AA1778E8D97EaCE72BfECE71865 @@ -131,8 +131,8 @@ With web3.js: ```typescript const web3 = new Web3(); const wallet = web3.eth.accounts.wallet.add( - // you can generate a private key using web3.eth.accounts.create().privateKey - privateKey, + // you can generate a private key using web3.eth.accounts.create().privateKey + privateKey, ); // outputs: 0x6f7D735dFB514AA1778E8D97EaCE72BfECE71865 @@ -140,12 +140,12 @@ console.log(wallet[0].address); ``` :::info - In web3.js, if you want to use a private key to later sign and send transactions, you first need to add this private key to the accounts with, for example, one of the methods: - `web3.eth.accounts.create()`, or `web3.eth.accounts.wallet.add(privateKey)`. - - And then whenever you provide the public address of that private key, web3.js will use that private key to sign. For example, you would pass the public key at `web3.eth.sendTransaction({from: publicAddress,...})` and web3.`eth.signTransaction({from: publicAddress,...})` then the privateKey of that publicAddress will be lookup and used to sign. +In web3.js, if you want to use a private key to later sign and send transactions, you first need to add this private key to the accounts with, for example, one of the methods: +`web3.eth.accounts.create()`, or `web3.eth.accounts.wallet.add(privateKey)`. - However, it is not advised to use the privatekey directly. And you are advised to use a secret storage or a vault instead. +And then whenever you provide the public address of that private key, web3.js will use that private key to sign. For example, you would pass the public key at `web3.eth.sendTransaction({from: publicAddress,...})` and web3.`eth.signTransaction({from: publicAddress,...})` then the privateKey of that publicAddress will be lookup and used to sign. + +However, it is not advised to use the privatekey directly. And you are advised to use a secret storage or a vault instead. ::: ### Get unlocked account @@ -162,7 +162,6 @@ With web3.js: const account = (await web3.eth.getAccounts())[0]; ``` - ### Signing a string message with ethers.js: @@ -174,13 +173,11 @@ const signature = await signer.signMessage('Some data'); // Outputs something like: // 0xb475e02218d7d6a16f3575de789996d0a57f900f240d73ed792672256d63913840c1da0dd3e7fe2e79485b7a1d81e8cc163f405c3df22d496f28f1dd148faebf1b console.log(signature); - ``` With web3.js: ```typescript - // Sign with web3.js, using a private key: const signature = web3.eth.accounts.sign('Some data', privateKey).signature; @@ -190,8 +187,8 @@ console.log(signature); // Sign using an account managed by the connected provider (for example the RPC client or a browser-injected provider) const signature = await web3.eth.sign( - web3.utils.utf8ToHex('Some data'), // data to be signed (4.x only supports Hex Strings) - '0x6E599DA0bfF7A6598AC1224E4985430Bf16458a4', // the address that its private key would be used to sign + web3.utils.utf8ToHex('Some data'), // data to be signed (4.x only supports Hex Strings) + '0x6E599DA0bfF7A6598AC1224E4985430Bf16458a4', // the address that its private key would be used to sign ); // Outputs something like: @@ -209,8 +206,8 @@ Sending a transaction with ethers.js: const signer = new ethers.Wallet(privateKey, provider); const tx = await signer.sendTransaction({ - to: '0x92d3267215Ec56542b985473E73C8417403B15ac', - value: ethers.parseUnits('0.001', 'ether'), + to: '0x92d3267215Ec56542b985473E73C8417403B15ac', + value: ethers.parseUnits('0.001', 'ether'), }); console.log(tx); ``` @@ -220,7 +217,7 @@ With web3.js: :::info The method `web3.eth.sendTransaction` will use the account that you pass the public address at `from` to sign the transaction. -So, the `from` needs to be the public address of a private key that you added previously to the web3.eth.accounts. Or, else, it would pass it to the provider where an unlocked account would be used. +So, the `from` needs to be the public address of a private key that you added previously to the web3.eth.accounts. Or, else, it would pass it to the provider where an unlocked account would be used. And for the case when you did not add the private key early, and so the `from` was just passed to the provider. Then if the provider was a browser-injected provider like metamask, for example, it will ask the user to sign. And, if you are using a local dev node as a provider, it should be one of the accounts that were already unlocked at the node. However, note that it is highly risky and not recommended to unlock an account at a production or even a test node. ::: @@ -238,9 +235,9 @@ const wallet = web3.eth.accounts.wallet.add(privateKey); const account = wallet[0].address; const tx = await web3.eth.sendTransaction({ - from: account, - to: '0x92d3267215Ec56542b985473E73C8417403B15ac', - value: web3.utils.toWei('0.00000000001', 'ether'), + from: account, + to: '0x92d3267215Ec56542b985473E73C8417403B15ac', + value: web3.utils.toWei('0.00000000001', 'ether'), }); console.log(tx); ``` @@ -251,7 +248,7 @@ Posting a signed transaction to the node with ethers.js: ```typescript // in v5 -provider.sendTransaction(signedTx) +provider.sendTransaction(signedTx); // in v6 provider.broadcastTransaction(signedTx); @@ -261,28 +258,21 @@ With web3.js: ```typescript const transaction: Transaction = { - from: senderPublicAddress, - to: receiverPublicAddress, - value: 1, - gas: 21000, - type: 0, + from: senderPublicAddress, + to: receiverPublicAddress, + value: 1, + gas: 21000, + type: 0, }; // you might also use below `web3.eth.personal.signMessage`, depending on your use case. -const signedTransaction = await web3.eth.accounts.signTransaction( - transaction, - privateKey, -); +const signedTransaction = await web3.eth.accounts.signTransaction(transaction, privateKey); -const tx = await web3.eth.sendSignedTransaction( - signedTransaction.rawTransaction, -); +const tx = await web3.eth.sendSignedTransaction(signedTransaction.rawTransaction); console.log(tx); ``` - - ## Contracts ### Contracts Deployment @@ -303,23 +293,24 @@ In web3.js: ```typescript const contractObject = new web3.eth.Contract(abi); -const deployedContract = await contractObject.deploy({ - data: bytecode, - arguments: ['constructor param'] -}).send({ - from: '0x12598d2Fd88B420ED571beFDA8dD112624B5E730', - gas: '1000000', - // other transaction's params -}); +const deployedContract = await contractObject + .deploy({ + data: bytecode, + arguments: ['constructor param'], + }) + .send({ + from: '0x12598d2Fd88B420ED571beFDA8dD112624B5E730', + gas: '1000000', + // other transaction's params + }); -console.log('contract address', deployedContract.options.address) +console.log('contract address', deployedContract.options.address); ``` :::tip -📝 To get the smart contract ABI, you are advised to check: [#Step 4: Compile the Solidity code using the Solidity Compiler and get its ABI and Bytecode](/guides/smart_contracts/smart_contracts_guide#step-4-compile-the-solidity-code-using-the-solidity-compiler-and-get-its-abi-and-bytecode) and [Infer Contract Types from JSON Artifact](/guides/smart_contracts/infer_contract_types/) +📝 To get the smart contract ABI, you are advised to check: [#Step 4: Compile the Solidity code using the Solidity Compiler and get its ABI and Bytecode](/guides/smart_contracts/smart_contracts_guide#step-4-compile-the-solidity-code-using-the-solidity-compiler-and-get-its-abi-and-bytecode) and [Infer Contract Types from JSON Artifact](/guides/smart_contracts/infer_contract_types/) ::: - ### Calling Contracts' Methods To interact with contracts in ethers.js: @@ -335,9 +326,9 @@ In web3.js: const web3 = new Web3(provider); const contract = new web3.eth.Contract(ABI, CONTRACT_ADDRESS); -// If the method was only to read form the Blockchain: +// If the method was only to read form the Blockchain: const result = await contract.methods.someFunction().call(); -// Or, if the method would need a transaction to be sent: +// Or, if the method would need a transaction to be sent: const result = await contract.methods.someFunction().send(); ``` @@ -348,9 +339,9 @@ In ethers.js: ```typescript // ethers const abi = [ - 'function getMessage(string) public view returns (string)', - 'function getMessage() public view returns (string)' -] + 'function getMessage(string) public view returns (string)', + 'function getMessage() public view returns (string)', +]; const contract = new ethers.Contract(address, abi, signer); // for ambiguous functions (two functions with the same @@ -360,13 +351,13 @@ message = await contract['getMessage(string)']('nice'); message = await contract['getMessage()'](); // in v6 -contract.foo(Typed.string('nice')) +contract.foo(Typed.string('nice')); ``` In web3.js: ```typescript -// in web3.js the overloaded method implementation is automatically picked based on the passed datatype +// in web3.js the overloaded method implementation is automatically picked based on the passed datatype message = await contract.methods.getMessage('nice').call(); // To call the overladed method without a parameter: message = await contract.methods.getMessage().call(); @@ -378,7 +369,7 @@ To interact with contracts in ethers.js: ```typescript // Estimate the gas -contract.myMethod.estimateGas(123) +contract.myMethod.estimateGas(123); ``` In web3.js: @@ -386,18 +377,17 @@ In web3.js: ```typescript // Estimate the gas const gasAmount = await myContract.methods.myMethod(123).estimateGas( - { gas: 5000000, from: transactionSenderAddress } // optional + { gas: 5000000, from: transactionSenderAddress }, // optional ); ``` - ### Handling Events Handling events with ethers.js: ```typescript contract.on('SomeEvent', (arg1, arg2, event) => { - // event handling + // event handling }); ``` @@ -405,37 +395,36 @@ With web3.js: ```typescript const event = contract.events.SomeEvent({ - filter: { - filter: { val: 100 }, - }, - fromBlock: 0, + filter: { + filter: { val: 100 }, + }, + fromBlock: 0, }); event.on('data', resolve); event.on('error', reject); ``` - ## Utility methods ### Hashing -Here is how to compute `keccak256` hash of a UTF-8 string with web3 and ethers. +Here is how to compute `keccak256` hash of a UTF-8 string with web3 and ethers. With ethers.js: ```typescript // hash of a string -ethers.utils.id('hello world') +ethers.utils.id('hello world'); // hash of binary data -ethers.utils.keccak256('0x4242') +ethers.utils.keccak256('0x4242'); ``` With web3.js: ```typescript // computes the Keccak-256 hash of the input and returns a hexstring: -// the `utils.sha3` accepts: string and Uint8Array +// the `utils.sha3` accepts: string and Uint8Array web3.utils.sha3('hello world'); // the `utils.keccak256` accepts: string, Uint8Array, Numbers and ReadonlyArray web3.utils.keccak256('hello world'); diff --git a/docs/docs/guides/resources_and_troubleshooting/index.md b/docs/docs/guides/18_resources_and_troubleshooting/index.md similarity index 96% rename from docs/docs/guides/resources_and_troubleshooting/index.md rename to docs/docs/guides/18_resources_and_troubleshooting/index.md index 2dd82f1e5b6..8cf7327d828 100644 --- a/docs/docs/guides/resources_and_troubleshooting/index.md +++ b/docs/docs/guides/18_resources_and_troubleshooting/index.md @@ -1,7 +1,8 @@ --- -sidebar_position: 16 +sidebar_position: 18 sidebar_label: '📚 Resources & Troubleshooting' --- + # Resources & Troubleshooting ## Troubleshooting @@ -13,26 +14,30 @@ Occasionally, users encounter errors in web3.js due to external dependencies, wh **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'); + 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' +import './shim.js'; ``` Additional Info: @@ -47,7 +52,6 @@ This comprehensive 14-part video course from ChainSafe equips you with the skill [![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_) 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: diff --git a/docs/docs/guides/feedback/index.md b/docs/docs/guides/19_feedback/index.md similarity index 97% rename from docs/docs/guides/feedback/index.md rename to docs/docs/guides/19_feedback/index.md index 228003d5a6e..05ae7d90fef 100644 --- a/docs/docs/guides/feedback/index.md +++ b/docs/docs/guides/19_feedback/index.md @@ -1,5 +1,5 @@ --- -sidebar_position: 17 +sidebar_position: 19 sidebar_label: '🗣️ Feedback' --- @@ -24,5 +24,3 @@ Please reach out to us: [💬 Discord: `#web3js-general` channel](https://discord.gg/f5QhHUswtr) [🐦 Twitter: `@web3_js`](https://twitter.com/web3_js) - - diff --git a/docs/docs/guides/ens/_category_.yml b/docs/docs/guides/ens/_category_.yml deleted file mode 100644 index 6aaeb5a8a78..00000000000 --- a/docs/docs/guides/ens/_category_.yml +++ /dev/null @@ -1,5 +0,0 @@ -label: '📦 Web3 ENS module' -collapsible: true -collapsed: true -link: null -position: 9 \ No newline at end of file diff --git a/docs/docs/guides/getting_started/introduction.md b/docs/docs/guides/getting_started/introduction.md deleted file mode 100644 index 303401639f9..00000000000 --- a/docs/docs/guides/getting_started/introduction.md +++ /dev/null @@ -1,92 +0,0 @@ ---- -slug: / -sidebar_position: 1 -sidebar_label: Introduction ---- - -# Introduction - -Web3.js is a robust and flexible collection of **TypeScript and JavaScript** libraries that allows developers to interact with local or remote [Ethereum](https://ethereum.org/en/) nodes (or **any EVM-compatible blockchain**) over **HTTP, IPC or WebSocket** connections. It is a powerful and efficient toolkit for crafting applications within the Ethereum ecosystem and beyond. - -This documentation is the entrypoint to Web3.js for developers. It covers [basic](/guides/getting_started/quickstart) and [advanced](/guides/smart_contracts/mastering_smart_contracts) usage with examples, and includes comprehensive [API documentation](/api) as well as guides for common tasks, like [upgrading](/guides/web3_upgrade_guide/x/) from older versions. - -## Features of Web3.js v4 - -- Flexible - - ECMAScript (ESM) and CommonJS (CJS) builds - - [Plugins](/guides/web3_plugin_guide/) for extending functionality -- Efficient - - Modular, [package](/#packages)-based design reduces unneeded dependencies - - [Tree shakable with ESM](/guides/advanced/tree_shaking) - - Use of native [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) (instead of large [BigNumber](https://mikemcl.github.io/bignumber.js/) libraries) - - Efficient ABI [encoding](/api/web3-eth-abi/function/encodeFunctionCall) & [decoding](/api/web3-eth-abi/function/decodeParameter) -- Developer-Friendly - - [Dynamic contract types](/guides/smart_contracts/infer_contract_types/) & full API in TypeScript - - Custom output [formatters](https://docs.web3js.org/api/web3-utils/function/format) - - In compliance with the [Ethereum JSON-RPC Specification](https://ethereum.github.io/execution-apis/api-documentation/) - -## Using These Docs - -There is a lot to learn about Web3.js! Here are some tips for developers of different skill levels. Remember, you can always [reach out directly](/guides/feedback/#urgent-questions-or-concerns) with Discord or Twitter if you're feeling stuck. - -### For Beginner Web3.js Developers - -New Web3.js developers should proceed to the [Quickstart](/guides/getting_started/quickstart) section to learn how to get started with Web3.js. Once you understand the basics, you may want to consider learning more about [providers](/guides/web3_providers_guide/), [wallets and accounts](/guides/wallet/), [smart contracts](/guides/smart_contracts/smart_contracts_guide), and how to [use Web3.js with the Hardhat development environment](/guides/hardhat_tutorial/). - -### For Intermediate & Advanced Web3.js Developers - -If you're already familiar with Ethereum and Web3.js development, you may want to review the Web3.js [package structure](#packages--plugins) and proceed directly to the [package-level documentation](/libdocs/ABI) and [API documentation](/api). Application developers may wish to review the [Web3.js configuration guide](/guides/web3_config/) or learn how to use Web3.js with tools like the [MetaMask](/guides/wallet/metamask-react) wallet or the [WalletConnect](/guides/wallet/web3_modal_guide/) wallet selection modal. Don't forget to review the [list of available plugins](https://web3js.org/plugins) or even [learn how to build your own Web3.js plugin](/guides/web3_plugin_guide/plugin_authors)! - -## Packages & Plugins - -Web3.js is a modular collection of packages, each of which serves a specific needs. This means developers don't need to install the entire Web3 library for most use cases. Instead, necessary packages are selectively installed for a more efficient development experience. Here is an overview of a selection of available packages: - -- [**Web3Eth:**](/libdocs/Web3Eth) The `web3-eth` package is the entrypoint to Web3.js - it's the control center for managing interactions with Ethereum and other EVM-compatible networks. - -- [**Net:**](/libdocs/Net) The `web3-net` package provides discovery and interactions for an **Ethereum node's network properties.** - -- [**Accounts:**](/libdocs/Accounts) The `web3-eth-accounts` package has tools for creating Ethereum accounts and the **secure signing** of transactions and data. - -- [**Personal:**](/libdocs/Personal) Use `web3-eth-personal` for **direct communication about your accounts with the Ethereum node**, which streamlines account management during development. - - **NOTE:** *For enhanced security in production and when interacting with public nodes, consider using `web3-eth-accounts` for local signing operations, which keeps your private keys and sensitive information secure on your local machine* - -- [**Utils:**](/libdocs/Utils) The `web3-utils` package provides helpers to perform a range of essential Ethereum development tasks, including **converting data formats, checking addresses, encoding and decoding data, hashing, handling numbers, and much more.**. - -- [**Contract:**](/libdocs/Contract) The `web3-eth-contract` package makes it easy to **interact with smart contracts through JavaScript or TypeScript,** which streamlines the development process and makes it less error-prone. - -- [**ABI:**](/libdocs/ABI) The `web3-eth-abi` package simplifies decoding logs and parameters, encoding function calls and signatures, and inferring types for efficient Ethereum **smart contract interactions.** - -- [**ENS:**](/libdocs/ENS) The `web3-eth-ens` package makes it easy for developers to communicate with the **Ethereum Name Service (ENS).** - -- [**Iban:**](/libdocs/Iban) The `web3-eth-iban` package allows you to switch between **Ethereum addresses and special banking-like addresses** (IBAN or BBAN) and simplifies conversion between the types. - -### Additional Supporting Packages - -- [**Web3 Core:**](/api/web3-core) subscriptions, request management, and configuration used by other Web3 packages - -- [**Web3 Types:**](/api/web3-types) data structures, objects, interfaces and types used by Web3 - -- [**Web3 Validator:**](/api/web3-validator) runtime type validation against predefined types or custom schemas - -- [**Web3 Errors:**](/api/web3-errors) error codes and common error classes that are used by other Web3 packages - -- [**Web3 RPC Methods:**](/api/web3/namespace/rpcMethods) functions for making RPC requests to Ethereum using a given provider - -### Plugins - -Web3.js supports [plugins](/guides/web3_plugin_guide/), which are another way to encapsulate capabilities that support a specific need. There are plugins that exist to support native features, like those described by [EIPs](https://eips.ethereum.org/) as well as plugins that are designed to support specific smart contracts, middleware, or even other Ethereum-compatible networks. Visit the [Web3.js plugins homepage](https://web3js.org/plugins) to view a list of the most important Web3.js plugins, which includes: - -- [EIP-4337 (Account Abstraction) Plugin](https://www.npmjs.com/package/@chainsafe/web3-plugin-eip4337) - -- [EIP-4844 (Blob Transactions) Plugin](https://www.npmjs.com/package/web3-plugin-blob-tx) - -- [zkSync Plugin](https://www.npmjs.com/package/web3-plugin-zksync) - -## Advantages Over Other Libraries - -- **Extensive Documentation and Community**: Web3.js is one of the most established Ethereum libraries, which means it 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, which allows developers to use specific packages according to their needs. This leads 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. diff --git a/docs/docs/guides/getting_started/return-formats.md b/docs/docs/guides/getting_started/return-formats.md deleted file mode 100644 index ae4287a8336..00000000000 --- a/docs/docs/guides/getting_started/return-formats.md +++ /dev/null @@ -1,121 +0,0 @@ ---- -sidebar_position: 3 -sidebar_label: Return Formats ---- - -# Return Formats - -By default, Web3.js formats byte values as hexadecimal strings (e.g. `"0x221`") and number values as [`BigInt`s](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt). The default formats can be configured at the global level by updating the [`defaultReturnFormat` configuration option](/guides/web3_config/#defaultreturnformat). Many Web3.js functions (e.g. [`getBlock`](/api/web3-eth/function/getBlock), [`sendTransaction`](/api/web3-eth/function/sendTransaction)) accept an optional parameter named `returnFormat` of the [type `DataFormat`](/api/web3-types#DataFormat) that can be used to configure the format for data returned by that single function invocation. - -The following example demonstrates working with return formats: - -```ts -import { Block, FMT_BYTES, FMT_NUMBER, Numbers, Web3 } from "web3"; - -const web3 = new Web3("https://eth.llamarpc.com"); - -// use the default return format -web3.eth.getBlock().then((block: Block) => { - console.log(`Block #${block.number} Hash: ${block.hash}`); -}); -// ↳ Block #20735255 Hash: 0xbaea6dbd46fa810a27be4c9eac782602f8efe7512fb30a8455c127b101a23e22 - -// specify the return format for a single function invocation -web3.eth - .getBlockNumber({ - bytes: FMT_BYTES.HEX, - number: FMT_NUMBER.HEX, - }) - .then((blockNumber: Numbers) => { - console.log(`Block #${blockNumber}`); - }); -// ↳ Block #0x13c6517 - -// configure default return format for the web3-eth package -web3.eth.defaultReturnFormat = { - bytes: FMT_BYTES.UINT8ARRAY, - number: FMT_NUMBER.HEX, -}; - -web3.eth.getBlock().then((block: Block) => { - console.log(`Block #${block.number} Hash: [${block.hash}]`); -}); -// ↳ Block #0x13c6517 Hash: [186,234,109,...,162,62,34] -``` - -The supported return formats are: - -- Bytes - - [`FMT_BYTES.HEX`](/api/web3-types/enum/FMT_BYTES#HEX): hexadecimal [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) (e.g. `"0xdd"`) - ```ts - web3.eth - .getBlock(undefined, undefined, { - bytes: FMT_BYTES.HEX, - number: FMT_NUMBER.BIGINT, - }) - .then((block: Block) => { - console.log(`Block hash: ${block.hash}`); - }); - // ↳ Block hash: 0xbaea6dbd46fa810a27be4c9eac782602f8efe7512fb30a8455c127b101a23e22 - ``` - - [`FMT_BYTES.UINT8ARRAY`](/api/web3-types/enum/FMT_BYTES#UINT8ARRAY): [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) (e.g. `[ 2, 33 ]`) - ```ts - web3.eth - .getBlock(undefined, undefined, { - bytes: FMT_BYTES.UINT8ARRAY, - number: FMT_NUMBER.BIGINT, - }) - .then((block: Block) => { - console.log(`Block hash: [${block.hash}]`); - }); - // ↳ Block hash: [186,234,109,...,162,62,34] - ``` -- Numbers - - [`FMT_NUMBER.BIGINT`](/api/web3-types/enum/FMT_NUMBER#BIGINT): [`BigInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) (e.g. `221n`) - ```ts - web3.eth - .getBlockNumber({ - bytes: FMT_BYTES.HEX, - number: FMT_NUMBER.BIGINT, - }) - .then((blockNumber: Numbers) => { - console.log(`Block #${blockNumber}`); - }); - // ↳ Block #20735255 - ``` - - [`FMT_NUMBER.HEX`](/api/web3-types/enum/FMT_NUMBER#HEX): hexadecimal [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) (e.g. `"0xdd"`) - ```ts - web3.eth - .getBlockNumber({ - bytes: FMT_BYTES.HEX, - number: FMT_NUMBER.HEX, - }) - .then((blockNumber: Numbers) => { - console.log(`Block #${blockNumber}`); - }); - // ↳ Block #0x13c6517 - ``` - - [`FMT_NUMBER.NUMBER`](/api/web3-types/enum/FMT_NUMBER#NUMBER): [`Number`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number) (e.g. `221`) - ```ts - web3.eth - .getBlockNumber({ - bytes: FMT_BYTES.HEX, - number: FMT_NUMBER.NUMBER, - }) - .then((blockNumber: Numbers) => { - console.log(`Block #${blockNumber}`); - }); - // ↳ Block #20735255 - ``` - - [`FMT_NUMBER.STR`](/api/web3-types/enum/FMT_NUMBER#STR): [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) (e.g. `"221"`) - ```ts - web3.eth - .getBlockNumber({ - bytes: FMT_BYTES.HEX, - number: FMT_NUMBER.STR, - }) - .then((blockNumber: Numbers) => { - console.log(`Block #${blockNumber}`); - }); - // ↳ Block #20735255 - ``` diff --git a/docs/docs/guides/hardhat_tutorial/_category_.yml b/docs/docs/guides/hardhat_tutorial/_category_.yml deleted file mode 100644 index 8493ca97d6e..00000000000 --- a/docs/docs/guides/hardhat_tutorial/_category_.yml +++ /dev/null @@ -1,5 +0,0 @@ -label: '⛑️ Hardhat Tutorial' -collapsible: true -collapsed: true -link: null -position: 6 diff --git a/docs/docs/guides/wagmi_usage/_category_.yml b/docs/docs/guides/wagmi_usage/_category_.yml deleted file mode 100644 index ee90c923e38..00000000000 --- a/docs/docs/guides/wagmi_usage/_category_.yml +++ /dev/null @@ -1,5 +0,0 @@ -label: '🔄 Wagmi usage' -collapsible: true -collapsed: true -link: null -position: 14 diff --git a/docs/docs/guides/wagmi_usage/wagmi.md b/docs/docs/guides/wagmi_usage/wagmi.md deleted file mode 100644 index 9a3044c3767..00000000000 --- a/docs/docs/guides/wagmi_usage/wagmi.md +++ /dev/null @@ -1,131 +0,0 @@ ---- -sidebar_position: 1 -sidebar_label: 'Wagmi Web3js Adapter' -title: 'Wagmi Web3js Adapter' ---- - - -### Reference Implementation -If you're using [Wagmi](https://wagmi.sh/react/getting-started#use-wagmi) and want to add web3.js, use this code in your project. This snippet will help you to convert a `Viem` client to a `web3.js` instance for signing transactions and interacting with the blockchain: - - -```typescript -import {Web3} from 'web3' -import {useMemo} from 'react' -import type {Chain, Client, Transport} from 'viem' -import {type Config, useClient, useConnectorClient} from 'wagmi' - -export function clientToWeb3js(client?: Client) { - if (!client) { - return new Web3() - } - - const {transport} = client - - if (transport.type === 'fallback') { - return new Web3(transport.transports[0].value.url) - } - return new Web3(transport) -} - -/** Action to convert a viem Client to a web3.js Instance. */ -export function useWeb3js({chainId}: { chainId?: number } = {}) { - const client = useClient({chainId}) - return useMemo(() => clientToWeb3js(client), [client]) -} - -/** Action to convert a viem ConnectorClient to a web3.js Instance. */ -export function useWeb3jsSigner({chainId}: { chainId?: number } = {}) { - const {data: client} = useConnectorClient({chainId}) - return useMemo(() => clientToWeb3js(client), [client]) -} -``` - -### Usage examples -Get block data example: - -```typescript -import {useWeb3js} from '../web3/useWeb3js' -import {mainnet} from 'wagmi/chains' -import {useEffect, useState} from "react"; - -type Block = { - hash: string - extraData: string - miner: string - -} - -function Block() { - const web3js = useWeb3js({chainId: mainnet.id}) - const [block, setBlock] = useState() - - useEffect(() => { - web3js.eth.getBlock(19235006).then((b) => { - setBlock(b as Block) - }).catch(console.error) - }, [setBlock]); - - - if (!block) return (
Loading...
) - - return ( - <> -
{block.hash}
-
{block.extraData}
-
{block.miner}
- - -) -} - -export default Block - -``` - -Send transaction example: - -```typescript -import {mainnet} from 'wagmi/chains' -import {useAccount, useConnect} from "wagmi"; -import {useWeb3jsSigner} from "../web3/useWeb3js"; -import {useEffect} from "react"; - -function SendTransaction() { - const account = useAccount() - const {connectors, connect,} = useConnect() - const web3js = useWeb3jsSigner({chainId: mainnet.id}) - - useEffect(() => { - if (account && account.address) { - web3js.eth.sendTransaction({ - from: account.address, - to: '0x', // some address - value: '0x1' // set your value - }).then(console.log).catch(console.error) - } - }, [account]) - - return ( - <> - {connectors.map((connector) => ( - - ))} - - ) -} - -export default SendTransaction - -``` - - -:::tip -[This repository](https://github.com/avkos/wagmi-web3js-example-app) contains an example Wagmi app that demonstrates how to interact with the Ethereum blockchain using the web3.js library -::: diff --git a/docs/docs/guides/wallet/_category_.yml b/docs/docs/guides/wallet/_category_.yml deleted file mode 100644 index dde0bddd9ed..00000000000 --- a/docs/docs/guides/wallet/_category_.yml +++ /dev/null @@ -1,5 +0,0 @@ -label: '🔑 Wallet and Accounts ' -collapsible: true -collapsed: true -link: null -position: 3 diff --git a/docs/docs/guides/wallet/metamask-react.md b/docs/docs/guides/wallet/metamask-react.md deleted file mode 100644 index 8cdd7c70ba8..00000000000 --- a/docs/docs/guides/wallet/metamask-react.md +++ /dev/null @@ -1,626 +0,0 @@ ---- -sidebar_position: 5 -sidebar_label: 'Tutorial: Connecting to Metamask with React' ---- - -# Connecting to Metamask with React - - - -This tutorial builds on the previous tutorial that used [vanilla JavaScript with Web3.js and MetaMask](/guides/wallet/metamask-vanilla). In this tutorial, [React](https://react.dev/) and TypeScript will be used to implement similar capabilities. - -## Overview - -Here is a high-level overview of the steps we will be taking in this tutorial: - -1. Review prerequisites -2. Initialize a new React project and add Web3.js -3. Use MetaMask as the Web3.js provider -4. Request access to the MetaMask accounts -5. Sign a message with a MetaMask account -6. Verify the account used to sign a message - -:::tip -If you encounter any issues while following this guide or have any questions, don't hesitate to seek assistance. Our friendly community is ready to help you out! Join our [Discord](https://discord.gg/F4NUfaCC) server and head to the **#web3js-general** channel to connect with other developers and get the support you need. -::: - -## Step 1: Prerequisites - -This tutorial assumes basic familiarity with the command line as well as familiarity with React and [Node.js](https://nodejs.org/). Before starting this tutorial, ensure that Node.js and its package manager, npm, are installed. - -```bash -$: node -v -# your version may be different, but it's best to use the current stable version -v18.16.1 -$: npm -v -9.5.1 -``` - -Make sure that MetaMask is [installed](https://metamask.io/download/) as a browser extension and the steps to create an account (e.g. create a password, review the seed phrase) have been completed. - -## Step 2: Initialize a New React Project and Add Web3.js - -Initialize a new React project and navigate into the new project directory: - -```bash -npx create-react-app web3-metamask-react --template typescript -cd web3-metamask-react -``` - -Add Web3.js to the project with the following command: - -```bash -npm i web3 -``` - -## Step 3: Use MetaMask as the Web3.js Provider - -MetaMask will inject the Ethereum provider as an `ethereum` property on the [global `Window` object](https://developer.mozilla.org/en-US/docs/Web/API/Window). To communicate this change to the TypeScript compiler, update `src/react-app-env.d.ts` as follows: - -```ts -import { MetaMaskProvider } from "web3"; - -/// - -declare global { - interface Window { - ethereum: MetaMaskProvider; - } -} -``` - -Replace the contents of `src/App.tsx` with the following: - -```tsx -import { useEffect, useState } from "react"; -import { Web3 } from "web3"; - -function App() { - const [web3, setWeb3] = useState(null); - const [warning, setWarning] = useState(null); - const [provider, setProvider] = useState(null); - const [chainId, setChainId] = useState(null); - const [latestBlock, setLatestBlock] = useState(null); - useEffect(() => { - // ensure that there is an injected the Ethereum provider - if (window.ethereum) { - // use the injected Ethereum provider to initialize Web3.js - setWeb3(new Web3(window.ethereum)); - // check if Ethereum provider comes from MetaMask - if (window.ethereum.isMetaMask) { - setProvider("Connected to Ethereum with MetaMask."); - } else { - setProvider("Non-MetaMask Ethereum provider detected."); - } - } else { - // no Ethereum provider - instruct user to install MetaMask - setWarning("Please install MetaMask"); - } - }, []); - - useEffect(() => { - async function getChainId() { - if (web3 === null) { - return; - } - - // get chain ID and populate placeholder - setChainId(`Chain ID: ${await web3.eth.getChainId()}`); - } - - async function getLatestBlock() { - if (web3 === null) { - return; - } - - // get latest block and populate placeholder - setLatestBlock(`Latest Block: ${await web3.eth.getBlockNumber()}`); - - // subscribe to new blocks and update UI when a new block is created - const blockSubscription = await web3.eth.subscribe("newBlockHeaders"); - blockSubscription.on("data", (block) => { - setLatestBlock(`Latest Block: ${block.number}`); - }); - } - - getChainId(); - getLatestBlock(); - }, [web3]); - return ( - <> -
- {warning} -
-
{provider}
-
{chainId}
-
{latestBlock}
- - ); -} - -export default App; -``` - -Review the comments in `src/App.tsx`. This file defines a component with several placeholders that will be used to display network information, and also provides two `useEffect` hooks for populating those placeholders. The first `useEffect` hook checks for an [injected provider](/guides/web3_providers_guide/#injected-provider). If an injected provider is found, it's used to construct a new `Web3` instance and connect to the Ethereum network. A check is performed to ensure that the injected provider is coming from MetaMask and the result of this check is displayed to the user. If no injected provider is found, the user is instructed to install MetaMask. The second `useEffect` hook uses the injected provider to update the placeholders with the chain ID and latest block number, and creates an event subscription to update the block number as new blocks are created. - -To start the React app, execute the following command in the project directory: - -```bash -npm start -``` - -This should automatically open the page in a web browser (make sure it's the browser with the MetaMask extension). If everything is set up correctly, the webpage should state that it is connected to the Ethereum network with MetaMask and list the chain ID (for the default Ethereum Mainnet network this value should be `1`) and latest block number. The latest block number should change when new blocks are created. - -## Step 4: Request Access to the MetaMask Accounts - -Replace the contents of `src/App.tsx` with the following (take note of the highlighted sections, which are new): - -```tsx -import { useEffect, useState } from "react"; -import { Web3 } from "web3"; - -function App() { - const [web3, setWeb3] = useState(null); - const [warning, setWarning] = useState(null); - const [provider, setProvider] = useState(null); - const [chainId, setChainId] = useState(null); - const [latestBlock, setLatestBlock] = useState(null); - // highlight-start - const [accountButtonDisabled, setAccountButtonDisabled] = - useState(false); - const [accounts, setAccounts] = useState(null); - const [connectedAccount, setConnectedAccount] = useState(null); - // highlight-end - useEffect(() => { - // ensure that there is an injected the Ethereum provider - if (window.ethereum) { - // use the injected Ethereum provider to initialize Web3.js - setWeb3(new Web3(window.ethereum)); - // check if Ethereum provider comes from MetaMask - if (window.ethereum.isMetaMask) { - setProvider("Connected to Ethereum with MetaMask."); - } else { - setProvider("Non-MetaMask Ethereum provider detected."); - } - } else { - // no Ethereum provider - instruct user to install MetaMask - setWarning("Please install MetaMask"); - // highlight-next-line - setAccountButtonDisabled(true); - } - }, []); - - useEffect(() => { - async function getChainId() { - if (web3 === null) { - return; - } - - // get chain ID and populate placeholder - setChainId(`Chain ID: ${await web3.eth.getChainId()}`); - } - - async function getLatestBlock() { - if (web3 === null) { - return; - } - - // get latest block and populate placeholder - setLatestBlock(`Latest Block: ${await web3.eth.getBlockNumber()}`); - - // subscribe to new blocks and update UI when a new block is created - const blockSubscription = await web3.eth.subscribe("newBlockHeaders"); - blockSubscription.on("data", (block) => { - setLatestBlock(`Latest Block: ${block.number}`); - }); - } - - getChainId(); - getLatestBlock(); - }, [web3]); - - // highlight-start - // click event for "Request MetaMask Accounts" button - async function requestAccounts() { - if (web3 === null) { - return; - } - - // request accounts from MetaMask - await window.ethereum.request({ method: "eth_requestAccounts" }); - document.getElementById("requestAccounts")?.remove(); - - // get list of accounts - const allAccounts = await web3.eth.getAccounts(); - setAccounts(allAccounts); - // get the first account and populate placeholder - setConnectedAccount(`Account: ${allAccounts[0]}`); - } - // highlight-end - return ( - <> -
- {warning} -
-
{provider}
-
{chainId}
-
{latestBlock}
- // highlight-start -
{connectedAccount}
-
- -
- // highlight-end - - ); -} - -export default App; -``` - -The component has been updated to include a placeholder for the MetaMask account, as well as a button that is used to request the accounts from MetaMask. If no Ethereum provider is found, the button to request the MetaMask accounts is disabled. - -A function named `requestAccounts` has been defined as the click-handler for the new button. The accounts are requested by invoking `window.ethereum.request({ method: ["eth_requestAccounts"] })` and once the request has been approved, the account addresses are available by calling [`web3.eth.getAccounts()`](https://docs.web3js.org/api/web3-eth/class/Web3Eth#getAccounts). MetaMask can be used to manage multiple accounts, but this tutorial only makes use of a single account. More information about the [`window.ethereum.request`](https://docs.metamask.io/wallet/reference/provider-api/#request) function and [`eth_requestAccounts`](https://docs.metamask.io/wallet/reference/eth_requestaccounts/) RPC call can be found in the MetaMask documentation. - -Go back to the MetaMask-enabled browser and review the webpage, which should have been automatically refreshed to display the changes. Click the button that says "Request MetaMask Accounts", which should activate MetaMask. After accepting the MetaMask notifications, the address of the MetaMask account should be displayed on the webpage. MetaMask will remember that the webpage has been given permission to access its accounts and it will not be necessary to accept any confirmations when requesting accounts in the future. - -## Step #5: Sign a Message with a MetaMask Account - -Replace the contents of `src/App.tsx` with the following (take note of the highlighted sections, which are new): - -```tsx -import { useEffect, useState } from "react"; -import { Web3 } from "web3"; - -function App() { - const [web3, setWeb3] = useState(null); - const [warning, setWarning] = useState(null); - const [provider, setProvider] = useState(null); - const [chainId, setChainId] = useState(null); - const [latestBlock, setLatestBlock] = useState(null); - const [accountButtonDisabled, setAccountButtonDisabled] = - useState(false); - const [accounts, setAccounts] = useState(null); - const [connectedAccount, setConnectedAccount] = useState(null); - // highlight-start - const [messageToSign, setMessageToSign] = useState(null); - const [signingResult, setSigningResult] = useState(null); - // highlight-end - useEffect(() => { - // ensure that there is an injected the Ethereum provider - if (window.ethereum) { - // use the injected Ethereum provider to initialize Web3.js - setWeb3(new Web3(window.ethereum)); - // check if Ethereum provider comes from MetaMask - if (window.ethereum.isMetaMask) { - setProvider("Connected to Ethereum with MetaMask."); - } else { - setProvider("Non-MetaMask Ethereum provider detected."); - } - } else { - // no Ethereum provider - instruct user to install MetaMask - setWarning("Please install MetaMask"); - setAccountButtonDisabled(true); - } - }, []); - - useEffect(() => { - async function getChainId() { - if (web3 === null) { - return; - } - - // get chain ID and populate placeholder - setChainId(`Chain ID: ${await web3.eth.getChainId()}`); - } - - async function getLatestBlock() { - if (web3 === null) { - return; - } - - // get latest block and populate placeholder - setLatestBlock(`Latest Block: ${await web3.eth.getBlockNumber()}`); - - // subscribe to new blocks and update UI when a new block is created - const blockSubscription = await web3.eth.subscribe("newBlockHeaders"); - blockSubscription.on("data", (block) => { - setLatestBlock(`Latest Block: ${block.number}`); - }); - } - - getChainId(); - getLatestBlock(); - }, [web3]); - - // click event for "Request MetaMask Accounts" button - async function requestAccounts() { - if (web3 === null) { - return; - } - - // request accounts from MetaMask - await window.ethereum.request({ method: "eth_requestAccounts" }); - document.getElementById("requestAccounts")?.remove(); - - // get list of accounts - const allAccounts = await web3.eth.getAccounts(); - setAccounts(allAccounts); - // get the first account and populate placeholder - setConnectedAccount(`Account: ${allAccounts[0]}`); - } - - // highlight-start - // click event for "Sign Message" button - async function signMessage() { - if (web3 === null || accounts === null || messageToSign === null) { - return; - } - - // sign message with first MetaMask account - const signature = await web3.eth.personal.sign( - messageToSign, - accounts[0], - "", - ); - - setSigningResult(signature); - } - // highlight-end - return ( - <> -
- {warning} -
-
{provider}
-
{chainId}
-
{latestBlock}
-
{connectedAccount}
-
- -
- // highlight-start -
- { - setMessageToSign(e.target.value); - }} - id="messageToSign" - placeholder="Message to Sign" - disabled={connectedAccount === null} - /> - -
{signingResult}
-
- // highlight-end - - ); -} - -export default App; -``` - -`src/App.tsx` has been updated to include inputs for signing a message with the MetaMask account. Initially, these inputs are disabled - they will be enabled once the page has access to the MetaMask account. A placeholder has been added for the result of the signing operation. - -A function named `signMessage` has been defined as the click-handler for the "Sign Message" button. This function calls the [`web3.eth.personal.sign`](/api/web3-eth-personal/class/Personal#sign) method. The first parameter to this method is the message to be signed, which is taken from the input field. The second parameter is the address of the account to use for signing. The third parameter is the passphrase to decrypt the account, which is not used in this example since MetaMask is managing the account. Once the message has been signed, the placeholder is updated with the signed message. - -Go back to the MetaMask-enabled browser and review the webpage, which should have been automatically refreshed to display the changes. There should now be disabled input fields below the "Request MetaMask Accounts" button. Click the button to request the accounts (remember, it will not be necessary to accept any MetaMask notifications this time). If everything is working properly, the address of the MetaMask account should be displayed on the webpage and the input fields should become enabled. Type a message (e.g. "Hello, Web3.js!") in the input field and click the "Sign Message" button. If everything is working properly, a MetaMask notification will appear. After the notification has been accepted, the signed message should appear beneath the input fields. - -## Step #6: Verify the Account Used to Sign a Message - -Replace the contents of `src/App.tsx` with the following (take note of the highlighted sections, which are new): - -```tsx -import { useEffect, useState } from "react"; -import { Web3 } from "web3"; - -function App() { - const [web3, setWeb3] = useState(null); - const [warning, setWarning] = useState(null); - const [provider, setProvider] = useState(null); - const [chainId, setChainId] = useState(null); - const [latestBlock, setLatestBlock] = useState(null); - const [accountButtonDisabled, setAccountButtonDisabled] = - useState(false); - const [accounts, setAccounts] = useState(null); - const [connectedAccount, setConnectedAccount] = useState(null); - const [messageToSign, setMessageToSign] = useState(null); - const [signingResult, setSigningResult] = useState(null); - // highlight-start - const [originalMessage, setOriginalMessage] = useState(null); - const [signedMessage, setSignedMessage] = useState(null); - const [signingAccount, setSigningAccount] = useState(null); - // highlight-end - useEffect(() => { - // ensure that there is an injected the Ethereum provider - if (window.ethereum) { - // use the injected Ethereum provider to initialize Web3.js - setWeb3(new Web3(window.ethereum)); - // check if Ethereum provider comes from MetaMask - if (window.ethereum.isMetaMask) { - setProvider("Connected to Ethereum with MetaMask."); - } else { - setProvider("Non-MetaMask Ethereum provider detected."); - } - } else { - // no Ethereum provider - instruct user to install MetaMask - setWarning("Please install MetaMask"); - setAccountButtonDisabled(true); - } - }, []); - - useEffect(() => { - async function getChainId() { - if (web3 === null) { - return; - } - - // get chain ID and populate placeholder - setChainId(`Chain ID: ${await web3.eth.getChainId()}`); - } - - async function getLatestBlock() { - if (web3 === null) { - return; - } - - // get latest block and populate placeholder - setLatestBlock(`Latest Block: ${await web3.eth.getBlockNumber()}`); - - // subscribe to new blocks and update UI when a new block is created - const blockSubscription = await web3.eth.subscribe("newBlockHeaders"); - blockSubscription.on("data", (block) => { - setLatestBlock(`Latest Block: ${block.number}`); - }); - } - - getChainId(); - getLatestBlock(); - }, [web3]); - - // click event for "Request MetaMask Accounts" button - async function requestAccounts() { - if (web3 === null) { - return; - } - - // request accounts from MetaMask - await window.ethereum.request({ method: "eth_requestAccounts" }); - document.getElementById("requestAccounts")?.remove(); - - // get list of accounts - const allAccounts = await web3.eth.getAccounts(); - setAccounts(allAccounts); - // get the first account and populate placeholder - setConnectedAccount(`Account: ${allAccounts[0]}`); - } - - // click event for "Sign Message" button - async function signMessage() { - if (web3 === null || accounts === null || messageToSign === null) { - return; - } - - // sign message with first MetaMask account - const signature = await web3.eth.personal.sign( - messageToSign, - accounts[0], - "", - ); - - setSigningResult(signature); - } - - // highlight-start - // click event for "Recover Account" button - async function recoverAccount() { - if (web3 === null || originalMessage === null || signedMessage === null) { - return; - } - // recover account from signature - const account = await web3.eth.personal.ecRecover( - originalMessage, - signedMessage, - ); - - setSigningAccount(account); - } - // highlight-end - return ( - <> -
- {warning} -
-
{provider}
-
{chainId}
-
{latestBlock}
-
{connectedAccount}
-
- -
-
- { - setMessageToSign(e.target.value); - }} - id="messageToSign" - placeholder="Message to Sign" - disabled={connectedAccount === null} - /> - -
{signingResult}
-
- // highlight-start -
- { - setOriginalMessage(e.target.value); - }} - id="originalMessage" - placeholder="Original Message" - disabled={connectedAccount === null} - /> - { - setSignedMessage(e.target.value); - }} - id="signedMessage" - placeholder="Signed Message" - disabled={connectedAccount === null} - /> - -
{signingAccount}
-
- // highlight-end - - ); -} - -export default App; -``` - -As in the previous step, `src/App.tsx` has been updated to include inputs for recovering the account that was used to sign a message. As before, these inputs are disabled - they will be enabled once the page has access to the MetaMask account. A placeholder has been added for the result of the recovery operation. - -A function named `recoverAccount` has been defined as the click-handler for the "Recover Account" button. This function calls the [`web3.eth.personal.ecRecover`](/api/web3-eth-personal/class/Personal#ecRecover) method. The first parameter to this method is the original unsigned message, which is taken from the first input field. The second parameter is the signed message, which is taken from the second input field. Once the account has been recovered, the placeholder is updated with the address of the account. - -Go back to the MetaMask-enabled browser and review the webpage, which should have been automatically refreshed to display the changes. There should now be additional disabled input fields below those from the previous step. Follow the same steps as before to request the accounts from MetaMask and sign a message, then copy and paste the original message and message signature (starting with the leading `0x` characters) into the new input fields. Click the "Recover Account" button. If everything is working properly, the address of the account that was used to sign the message should appear below the new input fields. This address should match the one that is displayed above the input fields that were used to sign the message. - -## Conclusion - -This tutorial demonstrated using Web3.js with MetaMask, including using the MetaMask injected provider and using a MetaMask account to sign a message. To use the MetaMask injected provider with Web3.js, simply construct a new instance of the `Web3` class with the `window.ethereum` property. To request access to the MetaMask accounts, use `window.ethereum.request({ method: "eth_requestAccounts" })` - once the user has confirmed this request, the MetaMask accounts will be available with `web3.eth.getAccounts()`. When the MetaMask injected provider handles a request that requires the use of a MetaMask account, MetaMask will prompt the user to confirm the request. diff --git a/docs/docs/guides/wallet/metamask-vanilla.md b/docs/docs/guides/wallet/metamask-vanilla.md deleted file mode 100644 index ef55e9bcf8c..00000000000 --- a/docs/docs/guides/wallet/metamask-vanilla.md +++ /dev/null @@ -1,480 +0,0 @@ ---- -sidebar_position: 4 -sidebar_label: 'Tutorial: Connecting to Metamask with Vanilla JS' ---- - -# Connecting to Metamask with Vanilla JS - -[MetaMask](https://metamask.io/) is a powerful [wallet application](https://ethereum.org/en/wallets/) that makes it easy for Ethereum users to securely manage their accounts. Web3.js developers who are building front-end user-facing applications ("[dApps](https://ethereum.org/en/dapps/#what-are-dapps)") can easily integrate their dApp with MetaMask to allow users to safely use their own accounts. This tutorial covers the basics of using Web3.js with MetaMask, including using MetaMask as the Web3.js [provider](/guides/web3_providers_guide/) and using a MetaMask account to [sign](https://ethereum.org/en/glossary/#digital-signatures) a message. - -## Overview - -Here is a high-level overview of the steps we will be taking in this tutorial: - -1. Review prerequisites -2. Create a new directory for the tutorial -3. Use MetaMask as the Web3.js provider -4. Request access to the MetaMask accounts -5. Sign a message with a MetaMask account -6. Verify the account used to sign a message - -:::tip -If you encounter any issues while following this guide or have any questions, don't hesitate to seek assistance. Our friendly community is ready to help you out! Join our [Discord](https://discord.gg/F4NUfaCC) server and head to the **#web3js-general** channel to connect with other developers and get the support you need. -::: - -## Step 1: Prerequisites - -This tutorial assumes basic familiarity with the command line as well as familiarity with JavaScript and HTML. [Node.js](https://nodejs.org/) is used to run a local HTTP server. Before starting this tutorial, ensure that Node.js and its package manager, npm, are installed. - -```bash -$: node -v -# your version may be different, but it's best to use the current stable version -v18.16.1 -$: npm -v -9.5.1 -``` - -Make sure that MetaMask is [installed](https://metamask.io/download/) as a browser extension and the steps to create an account (e.g. create a password, review the seed phrase) have been completed. - -## Step 2: Create a New Directory for the Tutorial - -Create a new directory for the tutorial and navigate into it: - -```bash -mkdir web3js-metamask-tutorial -cd web3js-metamask-tutorial -``` - -## Step 3: Use MetaMask as the Web3.js Provider - -Create a new file called `index.html` in your project directory and add the following HTML to it: - -```html - - - - - - Web3.js MetaMask Tutorial - - - - - -
-
-
-
- - - -``` - -Review the comments in `index.html`. This document imports Web3.js, creates several placeholders that will be used to display network information, and defines a script that checks for an [injected provider](/guides/web3_providers_guide/#injected-provider). If an injected provider is found, it's used to construct a new `Web3` instance and connect to the Ethereum network. A check is performed to ensure that the injected provider is coming from MetaMask and the result of this check is displayed to the user. Once connected through the injected provider, the script updates the placeholders with the chain ID and latest block number, and creates an event subscription to update the block number as new blocks are created. If no injected provider is found, the user is instructed to install MetaMask. - -To start a local HTTP server to serve `index.html`, execute the following command in the project directory: - -```bash -npx watch-http-server . -``` - -The output should look like: - -``` -Websocket Server Listening on Port: 8086 -Starting up http-server, serving . on: http://0.0.0.0:8080 -Hit CTRL-C to stop the server -Scanned working directory. ready for changes.. -``` - -The HTTP server needs to remain running in the terminal that was used to start it. Any changes that are made in the project directory will cause the webpage to automatically refresh. - -Use a MetaMask-enabled web browser to navigate to the URL from the output (http://0.0.0.0:8080 in the example above). If everything is set up correctly, the webpage should state that it is connected to the Ethereum network with MetaMask and list the chain ID (for the default Ethereum Mainnet network this value should be `1`) and latest block number. The latest block number should change when new blocks are created. - -## Step 4: Request Access to the MetaMask Accounts - -Replace the contents of `index.html` with the following (take note of the highlighted sections, which are new): - -```html - - - - - - Web3.js MetaMask Tutorial - - - - - -
-
-
- -
-
- - -
- -
- - - - -``` - -The file has been updated to include a placeholder for the MetaMask account, as well as a button that is used to request the accounts from MetaMask. - -Once connected to MetaMask, the script now registers a click event for the new button. The accounts are requested by invoking `window.ethereum.request({ method: ["eth_requestAccounts"] })` and once the request has been approved, the account addresses are available by calling [`web3.eth.getAccounts()`](https://docs.web3js.org/api/web3-eth/class/Web3Eth#getAccounts). MetaMask can be used to manage multiple accounts, but this tutorial only makes use of a single account. More information about the [`window.ethereum.request`](https://docs.metamask.io/wallet/reference/provider-api/#request) function and [`eth_requestAccounts`](https://docs.metamask.io/wallet/reference/eth_requestaccounts/) RPC call can be found in the MetaMask documentation. - -If no Ethereum provider is found, the button to request the MetaMask accounts is disabled. - -Go back to the MetaMask-enabled browser and review the webpage, which should have been automatically refreshed to display the changes. Click the button that says "Request MetaMask Accounts", which should activate MetaMask. After accepting the MetaMask notifications, the address of the MetaMask account should be displayed on the webpage. MetaMask will remember that the webpage has been given permission to access its accounts and it will not be necessary to accept any confirmations when requesting accounts in the future. - -## Step #5: Sign a Message with a MetaMask Account - -Replace the contents of `index.html` with the following (take note of the highlighted sections, which are new): - -```html - - - - - - Web3.js MetaMask Tutorial - - - - - -
-
-
-
-
- -
- -
- - -
- - -
-
- - - - -``` - -`index.html` has been updated to include inputs for signing a message with the MetaMask account. Initially, these inputs are disabled - they will be enabled once the page has access to the MetaMask account. A placeholder has been added for the result of the signing operation. - -Inside the click event for the "Request MetaMask Accounts" button, the signing inputs are initialized. First, the inputs are enabled. Then, a click event is registered for the "Sign" button. This click event calls the [`web3.eth.personal.sign`](/api/web3-eth-personal/class/Personal#sign) method. The first parameter to this method is the message to be signed, which is taken from the input field. The second parameter is the address of the account to use for signing. The third parameter is the passphrase to decrypt the account, which is not used in this example since MetaMask is managing the account. Once the message has been signed, the placeholder is updated with the signed message. - -Go back to the MetaMask-enabled browser and review the webpage, which should have been automatically refreshed to display the changes. There should now be disabled input fields below the "Request MetaMask Accounts" button. Click the button to request the accounts (remember, it will not be necessary to accept any MetaMask notifications this time). If everything is working properly, the address of the MetaMask account should be displayed on the webpage and the input fields should become enabled. Type a message (e.g. "Hello, Web3.js!") in the input field and click the "Sign Message" button. If everything is working properly, a MetaMask notification will appear. After the notification has been accepted, the signed message should appear beneath the input fields. - -## Step #6: Verify the Account Used to Sign a Message - -Replace the contents of `index.html` with the following (take note of the highlighted sections, which are new): - -```html - - - - - - Web3.js MetaMask Tutorial - - - - - -
-
-
-
-
- -
- -
- -
- - -
-
- - -
- - - -
-
- - - - -``` - -As in the previous step, `index.html` has been updated to include inputs for recovering the account that was used to sign a message. As before, these inputs are disabled - they will be enabled once the page has access to the MetaMask account. A placeholder has been added for the result of the recovery operation. - -Inside the click event for the "Request MetaMask Accounts" button, the recovery inputs are initialized. First, the inputs are enabled. Then, a click event is registered for the "Recover" button. This click event calls the [`web3.eth.personal.ecRecover`](/api/web3-eth-personal/class/Personal#ecRecover) method. The first parameter to this method is the original unsigned message, which is taken from the first input field. The second parameter is the signed message, which is taken from the second input field. Once the account has been recovered, the placeholder is updated with the address of the account. - -Go back to the MetaMask-enabled browser and review the webpage, which should have been automatically refreshed to display the changes. There should now be additional disabled input fields below those from the previous step. Follow the same steps as before to request the accounts from MetaMask and sign a message, then copy and paste the original message and message signature (starting with the leading `0x` characters) into the new input fields. Click the "Recover Account" button. If everything is working properly, the address of the account that was used to sign the message should appear below the new input fields. This address should match the one that is displayed above the input fields that were used to sign the message. - -## Conclusion - -This tutorial demonstrated using Web3.js with MetaMask, including using the MetaMask injected provider and using a MetaMask account to sign a message. To use the MetaMask injected provider with Web3.js, simply construct a new instance of the `Web3` class with the `window.ethereum` property. To request access to the MetaMask accounts, use `window.ethereum.request({ method: "eth_requestAccounts" })` - once the user has confirmed this request, the MetaMask accounts will be available with `web3.eth.getAccounts()`. When the MetaMask injected provider handles a request that requires the use of a MetaMask account, MetaMask will prompt the user to confirm the request. diff --git a/docs/docs/guides/wallet/tx-types.md b/docs/docs/guides/wallet/tx-types.md deleted file mode 100644 index 1e58a6b840a..00000000000 --- a/docs/docs/guides/wallet/tx-types.md +++ /dev/null @@ -1,280 +0,0 @@ ---- -sidebar_position: 3 -sidebar_label: 'Transaction Types' ---- - -# Transactions - -In this tutorial, we will explore how to send different types of [transactions](https://ethereum.org/en/developers/docs/transactions/) using web3.js, focusing on Ethereum's evolving transaction formats. We'll start with [legacy transactions (Transaction Type 0)](#transaction-type-0-legacy). Next, we'll delve into Transaction [Type 1 (EIP-2930)](#transaction-type-1-eip-2930), which introduces access lists to optimize gas usage. Finally, we'll cover [Transaction Type 2 (EIP-1559)](#transaction-type-2-eip-1559), the current default, which allows users to specify maximum fees and priority tips for more efficient and cost-effective transactions. Each section will include practical code examples to demonstrate sending raw transactions and interacting with ERC20 tokens on the Sepolia test network - -:::note -Web3.js uses transaction type 2 by default -::: - -## Transaction Type 0 (Legacy) - -### Raw Transaction - -A Legacy Transaction refers to a transaction that was created using an older version of Ethereum's transaction format, also known as "transaction type 0". This transaction format was used before the EIP-1559 upgrade, which was implemented in August 2021. - -```ts -import { Web3 } from "web3"; - -const web3 = new Web3("https://rpc2.sepolia.org"); // RPC node url - -async function txLegacy() { - const wallet = web3.eth.wallet.add("YOUR_PRIVATE_KEY"); // make sure you have funds - - const sender = wallet[0].address; - const recipient = "0x807BFe4940016B5a7FdA19482042917B02e68359"; - const value = 1; // wei - const nonce = await web3.eth.getTransactionCount(sender); - const gas = 21000; - const gasPrice = await web3.eth.getGasPrice(); - - const tx = { - from: sender, - to: recipient, - value, - nonce, - gas, - gasPrice, - // highlight-next-line - type: 0, - }; - - const txReceipt = await web3.eth.sendTransaction(tx); - console.log("Tx hash", txReceipt.transactionHash); -} - -txLegacy(); -``` - -### ERC20 Interaction - -```ts -import { Web3 } from "web3"; - -const web3 = new Web3("https://rpc2.sepolia.org"); - -//WETH token in Sepolia https://sepolia.etherscan.io/address/0xfff9976782d46cc05630d1f6ebab18b2324d6b14#code -const ADDRESS_WETH_SEPOLIA = "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14"; -const ABI = [ - { - constant: false, - inputs: [ - { - name: "dst", - type: "address", - }, - { - name: "wad", - type: "uint256", - }, - ], - name: "transfer", - outputs: [ - { - name: "", - type: "bool", - }, - ], - payable: false, - stateMutability: "nonpayable", - type: "function", - }, -]; - -async function transfer() { - //initialize wallet - const wallet = web3.eth.accounts.wallet.add("YOUR_PRIVATE_KEY"); //make sure you have WETH tokens in the Sepolia network - //you can swap Sepolia tokens for WETH here https://app.uniswap.org/swap?chain=sepolia - - //initialize WETH contract in sepolia - const myERC20 = new web3.eth.Contract(ABI, ADDRESS_WETH_SEPOLIA); - - const TO = "0xEA9eEca67682Cd9c6Ce3DdD1681049D7A897289F"; //address to send the tokens to - const VALUE = 1; //wei value, dont forget to multiply by decimals - - //send transfer and specify the type - const txReceipt = await myERC20.methods.transfer(TO, VALUE).send({ - from: wallet[0].address, - // highlight-next-line - type: 0, - }); - - console.log(txReceipt.transactionHash); - //=> 0x5f2087c22166f3a1909c40ce537dd564dc3d4c70c5be02f35c6406a628123b16 -} - -transfer(); -``` - -## Transaction Type 1 (EIP-2930) - -This EIP was introduced in April 2021, it introduces a feature called 'Access List.' This improvement allows saving gas on cross-contract calls by declaring in advance which contract and storage slots will be accessed. - -### Raw Transaction - -```ts -import { Web3 } from "web3"; - -const web3 = new Web3("https://rpc2.sepolia.org"); - -async function txEIP2930() { - const wallet = web3.eth.wallet.add("YOUR_PRIVATE_KEY"); - - const sender = wallet[0].address; - const contractAddress1 = "0x..."; - const gas = 500000; //could be higher - const gasPrice = await web3.eth.getGasPrice(); - const data = "0x9a67c8b100000000000000000000000000000000000000000000000000000000000004d0" - - - // highlight-start - //create access list using web3.eth - const accessListData = await web3.eth.createAccessList({ - from: sender, - to: contractAddress1, - data, - }); - // highlight-end - - console.log(accessListData) - /* - => - { - // highlight-start - "accessList": [ - { - "address": "0x15859bdf5aff2080a9968f6a410361e9598df62f", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - // highlight-end - "gasUsed": "0x7671" - } - */ - - const tx = { - from: sender, - to: contractAddress1, //the contract we are calling - data, - gas, - gasPrice, - // highlight-next-line - type: 1, - // highlight-next-line - accessList: accessListData.accessList //access the object `accessList` - }; - - const txReceipt = await web3.eth.sendTransaction(tx); - - console.log("Tx hash", txReceipt.transactionHash); -} - -txEIP2930() -``` - -## Transaction Type 2 (EIP-1559) - -When a user creates an EIP-1559 transaction, they specify the maximum fee they are willing to pay `maxFeePerGas` as well as a tip `maxPriorityFeePerGas` to incentivize the miner. The actual fee paid by the user is then determined by the network based on the current demand for block space and the priority of the transaction. - -### Raw Transaction - -```ts -import { Web3 } from "web3"; - -const web3 = new Web3("https://rpc2.sepolia.org"); - -async function txEIP1559() { - const wallet = web3.eth.wallet.add("YOUR_PRIVATE_KEY"); //make sure you have funds - - const sender = wallet[0].address; - const recipient = "0x807BFe4940016B5a7FdA19482042917B02e68359"; - const value = 1; //wei - const nonce = await web3.eth.getTransactionCount(sender); - const gasLimit = 21000; - const maxFeePerGas = Number((await web3.eth.calculateFeeData()).maxFeePerGas); - const maxPriorityFeePerGas = Number((await web3.eth.calculateFeeData()).maxPriorityFeePerGas); - - const tx = { - from: sender, - to: recipient, - value, - nonce, - gasLimit, - maxFeePerGas, - maxPriorityFeePerGas, - // highlight-next-line - type: 2, - }; - - const txReceipt = await web3.eth.sendTransaction(tx); - console.log("Tx hash", txReceipt.transactionHash); -} - -txEIP1559(); -``` - -### ERC20 Interaction - -```ts -import { Web3 } from "web3"; - -const web3 = new Web3("https://rpc2.sepolia.org"); - -//WETH token in Sepolia https://sepolia.etherscan.io/address/0xfff9976782d46cc05630d1f6ebab18b2324d6b14#code -const ADDRESS_WETH_SEPOLIA = "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14"; -const ABI = [ - { - constant: false, - inputs: [ - { - name: "dst", - type: "address", - }, - { - name: "wad", - type: "uint256", - }, - ], - name: "transfer", - outputs: [ - { - name: "", - type: "bool", - }, - ], - payable: false, - stateMutability: "nonpayable", - type: "function", - }, -]; - -async function transfer() { - //initialize wallet - const wallet = web3.eth.accounts.wallet.add("YOUR_PRIVATE_KEY"); //make sure you have WETH tokens in the Sepolia network - //you can swap Sepolia tokens for WETH here https://app.uniswap.org/swap?chain=sepolia - - //initialize WETH contract in sepolia - const myERC20 = new web3.eth.Contract(ABI, ADDRESS_WETH_SEPOLIA); - - const TO = "0xEA9eEca67682Cd9c6Ce3DdD1681049D7A897289F"; //address to send the tokens to - const VALUE = 1; //wei value, dont forget to multiply by decimals - - //send transfer and specify the type - const txReceipt = await myERC20.methods.transfer(TO, VALUE).send({ - from: wallet[0].address, - // highlight-next-line - type: 2, - }); - - console.log(txReceipt.transactionHash); - //=> 0x174bc88023be4af431fad1693a59f7a41135238510cdcd00f15f6409b5471d77 -} - -transfer(); -``` \ No newline at end of file diff --git a/docs/docs/guides/wallet/web3_modal_guide/react.md b/docs/docs/guides/wallet/web3_modal_guide/react.md deleted file mode 100644 index 1bcc69c6af7..00000000000 --- a/docs/docs/guides/wallet/web3_modal_guide/react.md +++ /dev/null @@ -1,121 +0,0 @@ ---- -sidebar_position: 1 -sidebar_label: 'Web3Modal with React' ---- - -# Web3Modal with React 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({ - web3Config, - 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 React! - -:::info -- For additional information take a look into the interactive code editor above. -- Learn more about Web3modal [here](https://docs.walletconnect.com/web3modal/about) -::: - diff --git a/docs/docs/guides/web3_upgrade_guide/_category_.yml b/docs/docs/guides/web3_upgrade_guide/_category_.yml deleted file mode 100644 index 8335efbea79..00000000000 --- a/docs/docs/guides/web3_upgrade_guide/_category_.yml +++ /dev/null @@ -1,5 +0,0 @@ -label: '⬆️ Upgrading' -collapsible: true -collapsed: true -link: null -position: 13 diff --git a/docs/docs/guides/web3_utils_module/_category_.yml b/docs/docs/guides/web3_utils_module/_category_.yml deleted file mode 100644 index 95a9529cfce..00000000000 --- a/docs/docs/guides/web3_utils_module/_category_.yml +++ /dev/null @@ -1,5 +0,0 @@ -label: '📦 Web3 Utils module' -collapsible: true -collapsed: true -link: null -position: 10 \ No newline at end of file diff --git a/docs/src/css/custom.css b/docs/src/css/custom.css index 88f46c66fc7..8ab49468404 100644 --- a/docs/src/css/custom.css +++ b/docs/src/css/custom.css @@ -15,6 +15,7 @@ --ifm-color-primary-lightest: #e99c76; --ifm-code-font-size: 95%; --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); + tab-size: 2; } /* For readability concerns, you should choose a lighter palette in dark mode. */ diff --git a/packages/web3/src/types.ts b/packages/web3/src/types.ts index ef9bcc379cf..3b87896789c 100644 --- a/packages/web3/src/types.ts +++ b/packages/web3/src/types.ts @@ -52,7 +52,7 @@ export interface Web3EthInterface extends Eth { * Extended [Contract](/api/web3-eth-contract/class/Contract) constructor for main `web3` object. See [Contract](/api/web3-eth-contract/class/Contract) for further details. * * You can use `.setProvider` on this constructor to set provider for **all the instances** of the contracts which were created by `web3.eth.Contract`. - * Please check the {@doclink guides/web3_upgrade_guide/x/providers_migration_guide | following guide} to understand more about setting provider. + * Please check the {@doclink guides/web3_upgrade_guide/providers_migration_guide | following guide} to understand more about setting provider. * * ```ts * web3.eth.Contract.setProvider(myProvider) From 9edb183c97fba937e3ea7bde9874b043ba6f17ae Mon Sep 17 00:00:00 2001 From: Nikita Chebykin Date: Mon, 7 Oct 2024 17:47:28 +0200 Subject: [PATCH 162/186] Add Support for Nethermind and Besu 'syncing' Subscription Payload Format (#7306) * Add Support for Nethermind and Besu 'syncing' Subscription Payload Formats * Add CHANGELOG note for PR7306 --- CHANGELOG.md | 6 ++++++ packages/web3-eth/src/web3_subscriptions.ts | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 46c0eefe645..b07a0730c4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2729,6 +2729,12 @@ If there are any bugs, improvements, optimizations or any new feature proposal f ## [Unreleased] +### Added + +#### web3-eth + +- `syncing` subscription now supports Besu and Nethermind payload format + ### Changed #### web3-eth diff --git a/packages/web3-eth/src/web3_subscriptions.ts b/packages/web3-eth/src/web3_subscriptions.ts index 5838aa9ce2d..31949fc6883 100644 --- a/packages/web3-eth/src/web3_subscriptions.ts +++ b/packages/web3-eth/src/web3_subscriptions.ts @@ -163,7 +163,7 @@ export class SyncingSubscription extends Web3Subscription<{ this.emit('changed', data); } else { const mappedData: SyncOutput = Object.fromEntries( - Object.entries(data.status).map(([key, value]) => [ + Object.entries(data?.status || data).map(([key, value]) => [ key.charAt(0).toLowerCase() + key.substring(1), value, ]), From facc2e60fe763df34e35af4487ad3fec27b1e3fa Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Tue, 8 Oct 2024 06:59:49 -0700 Subject: [PATCH 163/186] Fix Typos (#7310) --- .../guides/05_smart_contracts/mastering_smart_contracts.md | 2 +- .../guides/06_events_subscriptions/custom_subscriptions.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/docs/guides/05_smart_contracts/mastering_smart_contracts.md b/docs/docs/guides/05_smart_contracts/mastering_smart_contracts.md index 41ac12950cc..aa129c5ef07 100644 --- a/docs/docs/guides/05_smart_contracts/mastering_smart_contracts.md +++ b/docs/docs/guides/05_smart_contracts/mastering_smart_contracts.md @@ -19,7 +19,7 @@ In the code editor you'll find: - `getNumber()`: this function will return the current value of the `number` variable. - `counterABI.json`: the ABI of the ContractCounter.sol - `counterBytecode.json`: the compiled Bytecode of the ContractCounter.sol -- `main.js`: here you will find 3 funtions: +- `main.js`: here you will find 3 functions: - `deploy()`: sample script to deploy the smart contract using the ABI and Bytecode - `getNumber()`: sample script to call the reading function getNumber() of the smart contract diff --git a/docs/docs/guides/06_events_subscriptions/custom_subscriptions.md b/docs/docs/guides/06_events_subscriptions/custom_subscriptions.md index 202e14d89ed..5241196f521 100644 --- a/docs/docs/guides/06_events_subscriptions/custom_subscriptions.md +++ b/docs/docs/guides/06_events_subscriptions/custom_subscriptions.md @@ -14,7 +14,7 @@ This guide is most likely for advanced users who are connecting to a node that p :::important If you are the developer who provides custom subscriptions to users. We encourage you to develop a web3.js Plugin after you follow the guide below. However, you can find how to develop a plugin at [web3.js Plugin Developer Guide](/guides/web3_plugin_guide/plugin_authors). -And even if you are not the developer who provides this custom subscription, we encourage you to write a web3.js plugin for the custom subscription, and publish it to the npm package registry. This way you can help the community. And they might contribute to your repository helping for things like: feature addition, maintenance, and bug detection. +And even if you are not the developer who provides this custom subscription, we encourage you to write a web3.js plugin for the custom subscription, and publish it to the npm package registry. This way you can help the community. And they might contribute to your repository by helping for things like: feature addition, maintenance, and bug detection. ::: ## Implementing the Subscription @@ -114,7 +114,7 @@ To subscribe, you need to pass the custom subscriptions to the `Web3`. And then ```ts const CustomSubscriptions = { - // the key (`custom`) is what you chose to use when you call `web3.subscriptionManager.subscribe`. + // the key (`custom`) is what you choose to use when you call `web3.subscriptionManager.subscribe`. // the value (`CustomSubscription`) is your class name. custom: MyCustomSubscription, // you can have as many custom subscriptions as you like... From f70140693b14edb20891a4c8554f5fcc58dc6dd3 Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Wed, 9 Oct 2024 06:24:03 -0700 Subject: [PATCH 164/186] Export EIP-6963 Types (#7270) * Export EIP-6963 Types * CHANGELOG * Comments from Review --- CHANGELOG.md | 4 ++++ packages/web3/src/index.ts | 1 + packages/web3/src/providers.exports.ts | 1 - 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b07a0730c4c..0666ebd3166 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2740,3 +2740,7 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3-eth - Allow `getEthereumjsTxDataFrom` to return additional fields that may be passed if using a `customTransactionSchema`. + +#### web3 + +- Exported EIP-6963 types are no longer under the `providers` namespace. (#7270) diff --git a/packages/web3/src/index.ts b/packages/web3/src/index.ts index 45d625b6e48..24a7b1aa501 100644 --- a/packages/web3/src/index.ts +++ b/packages/web3/src/index.ts @@ -327,6 +327,7 @@ along with web3.js. If not, see . import Web3 from './web3.js'; export * from './types.js'; +export * from './web3_eip6963.js'; export default Web3; /** diff --git a/packages/web3/src/providers.exports.ts b/packages/web3/src/providers.exports.ts index 3d20b0116b9..c0bbadc1b23 100644 --- a/packages/web3/src/providers.exports.ts +++ b/packages/web3/src/providers.exports.ts @@ -19,4 +19,3 @@ export { Eip1193Provider, SocketProvider } from 'web3-utils'; export * as http from 'web3-providers-http'; export * as ws from 'web3-providers-ws'; -export * from './web3_eip6963.js'; From bbde6ea45b3fdf4c6d790952844e1160d7c3e3b1 Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Fri, 11 Oct 2024 12:41:14 -0700 Subject: [PATCH 165/186] Add Gas Estimation Guide (#7319) * Add Gas Estimation Guide Closes #7299 * Update Docs for calculateFeeData * Add Access List Docs * Update docs/docs/guides/04_transactions/gas-and-fees.md Co-authored-by: Kris <605420+krzysu@users.noreply.github.com> * Update docs/docs/guides/04_transactions/gas-and-fees.md Co-authored-by: Alex * Update docs/docs/guides/04_transactions/gas-and-fees.md Co-authored-by: Kris <605420+krzysu@users.noreply.github.com> * Don't Mutate Values in Docs * Add Links to Gas Estimation Docs --------- Co-authored-by: Kris <605420+krzysu@users.noreply.github.com> Co-authored-by: Alex --- .../guides/04_transactions/gas-and-fees.md | 110 ++++++++++++++++++ .../guides/04_transactions/transactions.md | 4 + .../mastering_smart_contracts.md | 4 + .../smart_contracts_guide.md | 4 + packages/web3-eth/src/web3_eth.ts | 25 ++-- 5 files changed, 139 insertions(+), 8 deletions(-) create mode 100644 docs/docs/guides/04_transactions/gas-and-fees.md diff --git a/docs/docs/guides/04_transactions/gas-and-fees.md b/docs/docs/guides/04_transactions/gas-and-fees.md new file mode 100644 index 00000000000..6e67fb03775 --- /dev/null +++ b/docs/docs/guides/04_transactions/gas-and-fees.md @@ -0,0 +1,110 @@ +--- +sidebar_position: 3 +sidebar_label: 'Gas and Priority Fees' +--- + +# Gas and Priority Fees + +To prevent spam and reward node operators, Ethereum uses a mechanism called ["gas"](https://ethereum.org/en/gas/), which is a cost that is charged to execute a transaction. Gas costs are associated with all transactions that require computation or update state (e.g. transferring tokens from one account to another). Gas costs are not applied to requests that only involve reading state (e.g. querying the balance of an account). The amount of gas required to pay for a transaction is calculated based on the actual computational actions that are required to execute that transaction. For instance, a simple transaction to transfer ETH from one account to another will require less gas than invoking a complicated smart contract function that involves lots of computation and storage. The cost of gas varies based on network usage. Gas costs more during period of high network activity. The cost per unit of gas is known as the "base fee". + +In addition to the calculated gas cost, an Ethereum transaction can specify an optional priority fee, which is an additional fee that is paid directly to the operator of the node that executes the transaction. Priority fees are intended to incentive node operators to execute transactions. A priority fee is specified as a value in addition to the base fee, which means that the total cost of the priority fee is always a factor of the amount of gas required to execute a transaction. + +With the above in mind, the total cost of fees associated with a transaction is calculated as follows: + +Total cost of fees = _units of gas used \* (base fee + priority fee)_ + +## Estimating Gas + +The Ethereum JSON-RPC specifies the [`eth_estimateGas` method](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_estimategas), which accepts a transaction and returns an estimate of the amount of gas required to execute that transaction. The transaction will not be executed and added to the blockchain. The estimate may be different (typically more) than the amount of gas actually used by the transaction for a variety of reasons, including EVM mechanics, node performance, and changes to the state of a smart contract. To invoke the `eth_estimateGas` RPC method, use the [`Web3Eth.estimateGas` method](/api/web3-eth/class/Web3Eth#estimateGas) and provide the [`Transaction`](/api/web3-types/interface/Transaction) for which to estimate gas. + +Web3.js transactions may specify a gas limit (the maximum amount of gas they are able to consume) by providing the [`Transaction.gas` property](/api/web3/namespace/types#gas). If the specified gas limit is less than the actual amount of gas required to execute the transaction, the transaction will consume an amount of gas equal to the gas limit, which is not refunded, before failing and reverting any state changes made by the transaction. + +```ts +const transactionDraft: Transaction = { + from: '', + to: '', + value: web3.utils.ethUnitMap.ether, +}; + +const gas: bigint = await web3.eth.estimateGas(transactionDraft); + +const transaction: Transaction = { + ...transactionDraft, + gas, +}; +``` + +## Calculating Fees + +Web3.js exposes a helper, the [`Web3Eth.calculateFeeData` method](/api/web3-eth/class/Web3Eth#calculateFeeData), that can be used to intelligently calculate the value of the base and priority fees to specify for a transaction. `Web3Eth.calculateFeeData` accepts two optional parameters: `baseFeePerGasFactor` (default value: 2) and `alternativeMaxPriorityFeePerGas` (default value: 1 gwei). Both optional parameters are used in calculating the `maxFeePerGas`, which is described below. The return type of `Web3Eth.calculateFeeData` implements the [`FeeData` interface](/api/web3/namespace/types/#FeeData), which specifies four values: + +- `baseFeePerGas`: base fee from the last block +- `gasPrice`: result of the [`eth_gasPrice` RPC method](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gasprice) (legacy purposes only) +- `maxPriorityFeePerGas`: result of the [`eth_maxPriorityFeePerGas` RPC method](https://github.com/ethereum/execution-apis/blob/4140e528360fea53c34a766d86a000c6c039100e/src/eth/fee_market.yaml#L29-L42) +- `maxFeePerGas`: calculated as `baseFeePerGas * baseFeePerGasFactor + (maxPriorityFeePerGas ?? alternativeMaxPriorityFeePerGas)` + +Web3.js transactions may specify `maxFeePerGas` and `maxPriorityFeePerGas` values. If both values are specified, `maxFeePerGas` must be greater than or equal to `maxPriorityFeePerGas`. If `maxFeePerGas` is less than the current base fee, the transaction will not execute until the base fee drops to a value that is less than or equal to the `maxFeePerGas`. + +```ts +const transactionDraft: Transaction = { + from: '', + to: '', + value: web3.utils.ethUnitMap.ether, +}; + +const feeData: FeeData = await web3.eth.calculateFeeData(); + +const transaction: Transaction = { + ...transactionDraft, + maxFeePerGas: feeData.maxFeePerGas, + maxPriorityFeePerGas: feeData.maxPriorityFeePerGas, +}; +``` + +## Generating Access Lists + +An access list specifies the addresses and storage keys that a transaction plans to access. Specifying these elements in advance makes a transaction's gas costs more predictable. + +The Ethereum JSON-RPC specifies the [`eth_createAccessList` method](https://github.com/ethereum/execution-apis/blob/4140e528360fea53c34a766d86a000c6c039100e/src/eth/execute.yaml#L54-L97), which accepts a transaction and returns an object that lists the addresses and storage keys that the transaction will access, as well as the approximate gas cost for the transaction if the access list is included. The transaction will not be executed and added to the blockchain. To invoke the `eth_createAccessList` RPC method, use the [`Web3Eth.createAccessList` method](/api/web3-eth/function/createAccessList) and provide the [`TransactionForAccessList`](/api/web3-types/interface/TransactionForAccessList) for which to generate the access list. + +Web3.js transactions may specify an access list by providing the [`Transaction.accessList` property](/api/web3/namespace/types#accessList). + +```ts +const transactionDraft: TransactionForAccessList = { + from: '', + to: '', + value: web3.utils.ethUnitMap.ether, +}; + +const accessListResult: AccessListResult = await web3.eth.createAccessList(transactionDraft); + +const transaction: Transaction = { + ...transactionDraft, + accessList: accessListResult.accessList, + gas: accessListResult.gasUsed, +}; +``` + +## Smart Contract Fees + +The following example demonstrates specifying fee data and creating an access list for a transaction that invokes a [smart contract](/guides/smart_contracts/smart_contracts_guide) function: + +```ts +const transfer: NonPayableMethodObject = erc20.methods.transfer(receiver.address, 1); + +const transferOpts: NonPayableCallOptions = { from: sender.address }; +const accessListResult: AccessListResult = await transfer.createAccessList(transferOpts); +const transactionDraft: Transaction = transfer.populateTransaction(transferOpts); + +const feeData: FeeData = await web3.eth.calculateFeeData(); + +const transferTxn: Transaction = { + ...transactionDraft, + maxFeePerGas: feeData.maxFeePerGas, + maxPriorityFeePerGas: feeData.maxPriorityFeePerGas, + accessList: accessListResult.accessList, + gas: accessListResult.gasUsed, +}; + +const receipt: TransactionReceipt = await web3.eth.sendTransaction(transferTxn); +``` diff --git a/docs/docs/guides/04_transactions/transactions.md b/docs/docs/guides/04_transactions/transactions.md index 8b830554593..35078f053ec 100644 --- a/docs/docs/guides/04_transactions/transactions.md +++ b/docs/docs/guides/04_transactions/transactions.md @@ -231,6 +231,10 @@ Final receiver balance: 100n Note that the sender's balance has decreased by more than the amount that was transferred to the receiver. This is because the sender's balance is also used to pay for the transaction's [gas fees](https://ethereum.org/en/developers/docs/gas/). The transaction receipt specifies the amount of gas that was used (`cumulativeGasUsed`) and the gas price in wei (`effectiveGasPrice`). The total amount deducted from the sender's balance is equal to the amount transferred plus the cost of the gas fees (`cumulativeGasUsed` multiplied by `effectiveGasPrice`). +:::info +Gas and other fees are important topics for Ethereum developers to understand. Refer to the [Gas and Priority Fees guide](/guides/transactions/gas-and-fees) to learn more. +::: + ## Step 5: Send a Transaction and Subscribe to Its Events In the previous example, the `transaction-receipt.js` script demonstrates sending a transaction to the network and reviewing the results after it has been successfully received. However, there are more stages to the [transaction lifecycle](https://ethereum.org/en/developers/docs/transactions/#transaction-lifecycle) and Web3.js makes it easy to subscribe to these lifecycle stages and create custom handlers for each one. Web3.js supports subscriptions for the following transaction lifecycle events: diff --git a/docs/docs/guides/05_smart_contracts/mastering_smart_contracts.md b/docs/docs/guides/05_smart_contracts/mastering_smart_contracts.md index aa129c5ef07..46beb429dfa 100644 --- a/docs/docs/guides/05_smart_contracts/mastering_smart_contracts.md +++ b/docs/docs/guides/05_smart_contracts/mastering_smart_contracts.md @@ -200,6 +200,10 @@ contract.methods.METHOD_NAME(METHOD_PARAMETERS).send({ from: '0x...' }); contract.methods.METHOD_NAME(METHOD_PARAMETERS).call(); ``` +:::tip +Refer to the [Gas and Priority Fees guide](/guides/transactions/gas-and-fees#smart-contract-fees) to learn how to control and optimize fees when using Web3.js to interact with smart contracts. +::: + - **events**: An object mapping your contract's events, allowing you to subscribe to them. And here is an example on how to use it: diff --git a/docs/docs/guides/05_smart_contracts/smart_contracts_guide.md b/docs/docs/guides/05_smart_contracts/smart_contracts_guide.md index f1d7d537fc3..b913e372ddb 100644 --- a/docs/docs/guides/05_smart_contracts/smart_contracts_guide.md +++ b/docs/docs/guides/05_smart_contracts/smart_contracts_guide.md @@ -362,6 +362,10 @@ interact(); This code uses the previously generated ABI and contract address to instantiate a [`Contract`](/api/web3-eth-contract/class/Contract) object for interacting with the `MyContract` smart contract. It gets the current value of `myNumber` from `MyContract`, logs it, updates it, and gets its updated value. It logs the updated `myNumber` value and the [transaction hash](https://help.coinbase.com/en-au/coinbase/getting-started/crypto-education/what-is-a-transaction-hash-hash-id) to the console. +:::info +For the purposes of this tutorial, the above script uses relatively arbitrary values for `gas` and `gasPrice` when demonstrating how to interact with a smart contract. Refer to the [Gas and Priority Fees guide](/guides/transactions/gas-and-fees#smart-contract-fees) to learn how to properly set these values. +::: + Run the following command to interact with the smart contract: ```bash diff --git a/packages/web3-eth/src/web3_eth.ts b/packages/web3-eth/src/web3_eth.ts index a9db13d5abb..6aa4f2ab89d 100644 --- a/packages/web3-eth/src/web3_eth.ts +++ b/packages/web3-eth/src/web3_eth.ts @@ -273,28 +273,37 @@ export class Web3Eth extends Web3Context { * gasPrice: 20000000000n, - * maxFeePerGas: 20000000000n, + * maxFeePerGas: 60000000000n, * maxPriorityFeePerGas: 20000000000n, - * baseFeePerGas: 20000000000n + * baseFeePerGas: 20000000000n * } * - * web3.eth.calculateFeeData(ethUnitMap.Gwei, 2n).then(console.log); + * web3.eth.calculateFeeData(1n).then(console.log); * > { * gasPrice: 20000000000n, * maxFeePerGas: 40000000000n, * maxPriorityFeePerGas: 20000000000n, - * baseFeePerGas: 20000000000n + * baseFeePerGas: 20000000000n + * } + * + * web3.eth.calculateFeeData(3n).then(console.log); + * > { + * gasPrice: 20000000000n, + * maxFeePerGas: 80000000000n, + * maxPriorityFeePerGas: 20000000000n, + * baseFeePerGas: 20000000000n * } * ``` */ From 7008e5ca1d530e83f937e74e4dfad6e26c3f58ca Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 15 Oct 2024 09:14:17 -0400 Subject: [PATCH 166/186] update docs (#7318) --- .../providers_migration_guide.md | 79 ++++++++++++++----- 1 file changed, 58 insertions(+), 21 deletions(-) diff --git a/docs/docs/guides/15_web3_upgrade_guide/providers_migration_guide.md b/docs/docs/guides/15_web3_upgrade_guide/providers_migration_guide.md index 990ec6a989d..68ff15c9a3b 100644 --- a/docs/docs/guides/15_web3_upgrade_guide/providers_migration_guide.md +++ b/docs/docs/guides/15_web3_upgrade_guide/providers_migration_guide.md @@ -6,11 +6,13 @@ sidebar_label: web3.providers For full description about the providers, their priorities and their types, you can check [web3.js Providers Guide](/guides/web3_providers_guide/). -### Provider Options Changes +## Provider Options Changes -There are differences in the objects that could be passed in the Provider constructors between version 1.x and 4.x. Below, you will find the difference for every Provider object type. +There are differences in the objects that could be passed in the Provider constructors between version 1.x and v4. Below, you will find the difference for every Provider object type. -#### HttpProvider +### HttpProvider + +#### HttpProviderOptions In 1.x, options passed in the constructor should be of type [`HttpProviderOptions`](https://github.com/web3/web3.js/blob/1.x/packages/web3-core-helpers/types/index.d.ts#L173). The `HttpProviderOptions` interface consists of: @@ -35,7 +37,7 @@ interface HttpHeader { } ``` -In 4.x, the options is of type `HttpProviderOptions`, which is an object with a `providerOptions` key and value a `RequestInit` object. +In v4, the options is of type `HttpProviderOptions`, which is an object with a `providerOptions` key and value a `RequestInit` object. Regarding `RequestInit` see [microsoft's github](https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules_typedoc_node_modules_typescript_lib_lib_dom_d_.requestinit.html). For example: @@ -58,7 +60,7 @@ let httpOptions = { } }; -// in 4.x +// in v4 let httpOptions = { providerOptions: { body: undefined, @@ -80,7 +82,9 @@ let httpOptions = { }; ``` -#### WebSocketProvider +### WebSocketProvider + +#### WebsocketProviderOptions In 1.x, options passed in the constructor should be of type [`WebsocketProviderOptions`](https://github.com/web3/web3.js/blob/1.x/packages/web3-core-helpers/types/index.d.ts#L192). The `WebsocketProviderOptions` interface consists of: @@ -105,9 +109,9 @@ interface ReconnectOptions { } ``` -In 4.x, the `socketOptions` parameter is of type `ClientRequestArgs` or of `ClientOptions`. See [here](https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules__types_node_http_d_._http_.clientrequestargs.html) for `ClientRequestArgs` and [here](https://github.com/websockets/ws) for `ClientOptions`. +In v4, the `socketOptions` parameter is of type `ClientRequestArgs` or of `ClientOptions`. See [here](https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules__types_node_http_d_._http_.clientrequestargs.html) for `ClientRequestArgs` and [here](https://github.com/websockets/ws) for `ClientOptions`. -In 4.x the `reconnectOptions` parameter can be given to control: auto-reconnecting, delay and max tries attempts. And here is its type: +In v4 the `reconnectOptions` parameter can be given to control: auto-reconnecting, delay and max tries attempts. And here is its type: ```ts // this is the same options interface used for both WebSocketProvider and IpcProvider @@ -118,7 +122,36 @@ type ReconnectOptions = { }; ``` -##### Options examples +#### Program Behavior with WebSocket Provider + +In 1.x, a program connected to a WebSocket provider would automatically terminate after executing all code, even if the WebSocket connection was still active: + +```ts +const web3 = new Web3(wsUrl); +// The program will terminate after connecting since there are no more lines of code to run. +``` + +In version 4.x, this behavior has changed. When connected to a WebSocket provider, the program will not automatically terminate after the code finishes running. This is to ensure the WebSocket connection remains open, allowing the program to continue listening for events. + +The program will remain active until you explicitly disconnect from the WebSocket provider: + +```ts +const web3 = new Web3(wsUrl); +// The program will keep running to listen for events. +``` + +#### Terminating the Program + +When you're ready to stop the program, you can manually disconnect from the WebSocket provider by calling the disconnect method. This will properly close the connection and terminate the program: + +```ts +const web3 = new Web3(wsUrl); +// When you are ready to terminate your program +web3.currentProvider?.disconnect(); +// The program will now terminate +``` + +### Options examples Below is an example for the passed options for each version: @@ -150,7 +183,7 @@ var options = { onTimeout: false, }, }; -// in 4.x +// in v4 let clientOptions: ClientOptions = { // Useful for credentialed urls, e.g: ws://username:password@localhost:8546 headers: { @@ -199,7 +232,9 @@ const provider = new WebSocketProvider( ); ``` -#### Legacy Event `close` has been deprecated +### Legacy Event `close` has been deprecated + +#### Disconnect and close event Following EIP-1193, the `close` event has been deprecated and is superceded by `disconnect`. In 1.x, we listen for a `close` event: @@ -215,7 +250,7 @@ provider.disconnect(1012); // would eventually log closed ``` -In 4.x, we listen for a `disconnect` event: +In v4, we listen for a `disconnect` event: ```ts const provider = new WebSocketProvider(host + port); @@ -228,7 +263,9 @@ provider.disconnect(1012); // would eventually log 'closed' ``` -#### IpcProvider +### IpcProvider + +#### Using IpcProvider The IPC provider is used in node.js dapps when running a local node. And it provide the most secure connection. @@ -240,7 +277,7 @@ import * as net from 'net'; const ipcProvider = new IpcProvider('/Users/myuser/Library/Ethereum/geth.ipc', new net.Server()); ``` -In 4.x, it's no longer installed by default as its nodejs modules are impacting web3.js browser usage. +In v4, it's no longer installed by default as its nodejs modules are impacting web3.js browser usage. You can use it by installing `web3-providers-ipc` and creating a new instance. Since it's compatible with Eip1193Provider, you can pass it on to the Web3 instance. @@ -262,7 +299,7 @@ interface SocketConstructorOpts { } ``` -In 4.x the third parameter is called `reconnectOptions` that is of the type `ReconnectOptions`. It can be given to control: auto-reconnecting, delay and max tries attempts. And here its type: +In v4 the third parameter is called `reconnectOptions` that is of the type `ReconnectOptions`. It can be given to control: auto-reconnecting, delay and max tries attempts. And here its type: ```ts // this is the same options interface used for both WebSocketProvider and IpcProvider @@ -285,7 +322,7 @@ new Web3.providers.IpcProvider('/Users/myuser/Library/Ethereum/geth.ipc', net); // on windows the path is: "\\\\.\\pipe\\geth.ipc" // on linux the path is: "/users/myuser/.ethereum/geth.ipc" -// in 4.x +// in v4 let clientOptions: SocketConstructorOpts = { allowHalfOpen: false; readable: true; @@ -333,7 +370,7 @@ const provider = new IpcProvider( ); ``` -#### Error message for reconnect attempts +### Error message for reconnect attempts :::note This section applies for both `IpcProvider` and `WebSocketProvider`. @@ -342,11 +379,11 @@ This section applies for both `IpcProvider` and `WebSocketProvider`. The error in, version 1.x, was an Error object that contains the message: `'Maximum number of reconnect attempts reached!'` -And, the error in version 4.x, is the same, but will also contain the value of the variable `maxAttempts` as follows: +And, the error in version v4, is the same, but will also contain the value of the variable `maxAttempts` as follows: `` `Maximum number of reconnect attempts reached! (${maxAttempts})` `` -And here is how to catch the error, in version 4.x, if max attempts reached when there is auto reconnecting: +And here is how to catch the error, in version v4, if max attempts reached when there is auto reconnecting: ```ts provider.on('error', error => { @@ -357,7 +394,7 @@ provider.on('error', error => { }); ``` -#### Legacy Event `close` has been deprecated +### Legacy Event `close` has been deprecated Following EIP-1193, the `close` event has been deprecated and is superseded by `disconnect`. In 1.x, we listen for a `close` event: @@ -373,7 +410,7 @@ provider.disconnect(1012); // would eventually log closed ``` -In 4.x, we listen for a `disconnect` event: +In v4, we listen for a `disconnect` event: ```ts const provider = new IpcProvider(host + port); From 69187c5ed45fa771d46d731277b0292c15c5546a Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 15 Oct 2024 23:08:26 -0400 Subject: [PATCH 167/186] add ignoregaspricing config (#7320) * add ignoregaspricing config * update * add tests * update changelog and docs * update docs and changelog * format * close connection --- .../guides/02_web3_providers_guide/index.md | 22 +++++++++ .../05_smart_contracts/tips_and_tricks.md | 13 +++++ docs/docs/guides/09_web3_config/index.md | 28 +++++++++++ packages/web3-core/CHANGELOG.md | 4 ++ packages/web3-core/src/web3_config.ts | 15 +++++- .../__snapshots__/web3_context.test.ts.snap | 1 + .../web3-core/test/unit/web3_config.test.ts | 1 + .../test/integration/contract_methods.test.ts | 43 +++++++++++++++- packages/web3-eth/CHANGELOG.md | 4 ++ packages/web3-eth/src/utils/send_tx_helper.ts | 1 + packages/web3-eth/src/validation.ts | 8 +-- .../web3_eth/send_transaction.test.ts | 27 ++++++++++ .../web3-eth/test/unit/send_tx_helper.test.ts | 49 ++++++++++++++++++- packages/web3-types/src/eth_contract_types.ts | 4 ++ 14 files changed, 210 insertions(+), 10 deletions(-) diff --git a/docs/docs/guides/02_web3_providers_guide/index.md b/docs/docs/guides/02_web3_providers_guide/index.md index b17c5622531..23937a5b84f 100644 --- a/docs/docs/guides/02_web3_providers_guide/index.md +++ b/docs/docs/guides/02_web3_providers_guide/index.md @@ -111,6 +111,28 @@ await web3.eth.getBlockNumber(); // ↳ 18849658n ``` +#### Websocket Providers will only terminate when closed + +When connected to a WebSocket provider, the program will not automatically terminate after the code finishes running. This is to ensure the WebSocket connection remains open, allowing the program to continue listening for events. + +The program will remain active until you explicitly disconnect from the WebSocket provider: + +```ts +const web3 = new Web3(wsUrl); +// The program will keep running to listen for events. +``` + +#### Terminating the Program + +When you're ready to stop the program, you can manually disconnect from the WebSocket provider by calling the disconnect method. This will properly close the connection and terminate the program: + +```ts +const web3 = new Web3(wsUrl); +// When you are ready to terminate your program +web3.currentProvider?.disconnect(); +// The program will now terminate +``` + #### Configuring WebSocket Providers The [`WebSocketProvider` constructor](/api/web3-providers-ws/class/WebSocketProvider#constructor) accepts two optional parameters that can be used to configure the behavior of the `WebSocketProvider`: the first parameter must be of type [`ClientRequestArgs`](https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules__types_node_http_d_._http_.clientrequestargs.html) or of [`ClientOptions`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/e5ee5eae6a592198e469ad9f412bab8d223fcbb6/types/ws/index.d.ts#L243) and the second parameter must be of type [`ReconnectOptions`](/api/web3/namespace/utils#ReconnectOptions). diff --git a/docs/docs/guides/05_smart_contracts/tips_and_tricks.md b/docs/docs/guides/05_smart_contracts/tips_and_tricks.md index 189daec7727..35964550ca5 100644 --- a/docs/docs/guides/05_smart_contracts/tips_and_tricks.md +++ b/docs/docs/guides/05_smart_contracts/tips_and_tricks.md @@ -9,6 +9,19 @@ sidebar_label: 'Tips and Tricks' 📝 This article offers insights into **Smart Contracts** with helpful tips and tricks. If you have suggestions or questions, feel free to open an issue. We also welcome contributions through PRs. ::: +## Ignoring Web3.js autofill gas prices + +When interacting with methods in contracts, Web3.js will automatically fill the gas. If you are using metamask or a similar provider and would rather have a suggestion elsewhere, the `ignoreGasPricing` option enables you to send transactions or interact with contracts without having web3.js automatically fill in the gas estimate. + +#### Contract example + +```ts +let contractDeployed: Contract; +// instantiate contract... +contractDeployed.config.ignoreGasPricing = true; +const receipt = await contractDeployed.methods.setValues(1, 'string value', true).send(sendOptions); +``` + ## Calling Smart Contracts Methods with Parameter Overloading ### Overview of Function Overloading diff --git a/docs/docs/guides/09_web3_config/index.md b/docs/docs/guides/09_web3_config/index.md index de8a8b9db7c..3642aad951d 100644 --- a/docs/docs/guides/09_web3_config/index.md +++ b/docs/docs/guides/09_web3_config/index.md @@ -29,6 +29,7 @@ There is list of configuration params that can be set for modifying behavior of - [defaultMaxPriorityFeePerGas](/guides/web3_config/#defaultmaxpriorityfeepergas) - [customTransactionSchema](/guides/web3_config/#customTransactionSchema) - [defaultReturnFormat](/guides/web3_config/#defaultreturnformat) +- [ignoreGasPricing](/guides/web3_config/#ignoreGasPricing) ## Global level Config @@ -477,3 +478,30 @@ export enum FMT_BYTES { UINT8ARRAY = 'BYTES_UINT8ARRAY', } ``` + +### [ignoreGasPricing] + +The `ignoreGasPricing` option enables you to send transactions or interact with contracts without having web3.js automatically fill in the gas estimate. This feature is particularly useful when you prefer to let wallets or providers handle gas estimation instead. + +#### Send transaction example + +```ts +const web3 = new Web3(PROVIDER); +web3.config.ignoreGasPricing = true; // when setting configurations for the web3 object, this will also apply to newly created contracts from the web3 object +const transaction: TransactionWithToLocalWalletIndex = { + from: tempAcc.address, + to: '0x0000000000000000000000000000000000000000', + value: BigInt(1), + data: '0x64edfbf0e2c706ba4a09595315c45355a341a576cc17f3a19f43ac1c02f814ee', +}; +const receipt = await web3.eth.sendTransaction(transaction); // web3.js will not estimate gas now. +``` + +#### Contract example + +```ts +let contractDeployed: Contract; +// instantiate contract... +contractDeployed.config.ignoreGasPricing = true; +const receipt = await contractDeployed.methods.setValues(1, 'string value', true).send(sendOptions); +``` diff --git a/packages/web3-core/CHANGELOG.md b/packages/web3-core/CHANGELOG.md index 0ea27e97e22..b02756a075d 100644 --- a/packages/web3-core/CHANGELOG.md +++ b/packages/web3-core/CHANGELOG.md @@ -240,3 +240,7 @@ Documentation: - Adds a new property (`customTransactionSchema`) to `Web3ConfigOptions`(#7227) ## [Unreleased] + +### Added + +- Added new property `ignoreGasPricing` to `Web3ConfigOptions`. If `ignoreGasPricing` is true, gasPrice will not be estimated (#7320) diff --git a/packages/web3-core/src/web3_config.ts b/packages/web3-core/src/web3_config.ts index ee397ea9daf..6091bf35d4f 100644 --- a/packages/web3-core/src/web3_config.ts +++ b/packages/web3-core/src/web3_config.ts @@ -48,6 +48,7 @@ export interface Web3ConfigOptions { defaultNetworkId?: Numbers; defaultChain: string; defaultHardfork: string; + ignoreGasPricing: boolean; defaultCommon?: Common; defaultTransactionType: Numbers; @@ -104,6 +105,7 @@ export abstract class Web3Config transactionTypeParser: undefined, customTransactionSchema: undefined, defaultReturnFormat: DEFAULT_RETURN_FORMAT, + ignoreGasPricing: false, }; public constructor(options?: Partial) { @@ -208,7 +210,7 @@ export abstract class Web3Config * - `"latest"` - String: The latest block (current head of the blockchain) * - `"pending"` - String: The currently mined block (including pending transactions) * - `"finalized"` - String: (For POS networks) The finalized block is one which has been accepted as canonical by greater than 2/3 of validators - * - `"safe"` - String: (For POS networks) The safe head block is one which under normal network conditions, is expected to be included in the canonical chain. Under normal network conditions the safe head and the actual tip of the chain will be equivalent (with safe head trailing only by a few seconds). Safe heads will be less likely to be reorged than the proof of work network`s latest blocks. + * - `"safe"` - String: (For POS networks) The safe head block is one which under normal network conditions, is expected to be included in the canonical chain. Under normal network conditions the safe head and the actual tip of the chain will be equivalent (with safe head trailing only by a few seconds). Safe heads will be less likely to be reorged than the proof of work network's latest blocks. */ public set defaultBlock(val) { this._triggerConfigChange('defaultBlock', val); @@ -485,6 +487,17 @@ export abstract class Web3Config this.config.defaultCommon = val; } + /** + * Will get the ignoreGasPricing property. When true, the gasPrice, maxPriorityFeePerGas, and maxFeePerGas will not be autofilled in the transaction object. + * Useful when you want wallets to handle gas pricing. + */ + public get ignoreGasPricing() { + return this.config.ignoreGasPricing; + } + public set ignoreGasPricing(val) { + this._triggerConfigChange('ignoreGasPricing', val); + this.config.ignoreGasPricing = val; + } public get defaultTransactionType() { return this.config.defaultTransactionType; } 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 7d280405bfb..086b4a57991 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 @@ -24,6 +24,7 @@ exports[`Web3Context getContextObject should return correct context object 1`] = "useSubscriptionWhenCheckingBlockTimeout": false, }, "handleRevert": false, + "ignoreGasPricing": false, "maxListenersWarningThreshold": 100, "transactionBlockTimeout": 50, "transactionBuilder": undefined, diff --git a/packages/web3-core/test/unit/web3_config.test.ts b/packages/web3-core/test/unit/web3_config.test.ts index 7238c1fcb33..07dd05d355b 100644 --- a/packages/web3-core/test/unit/web3_config.test.ts +++ b/packages/web3-core/test/unit/web3_config.test.ts @@ -50,6 +50,7 @@ const defaultConfig = { transactionBuilder: undefined, transactionTypeParser: undefined, customTransactionSchema: undefined, + ignoreGasPricing: false, }; const setValue = { string: 'newValue', diff --git a/packages/web3-eth-contract/test/integration/contract_methods.test.ts b/packages/web3-eth-contract/test/integration/contract_methods.test.ts index 46a1490c119..152c3feec8a 100644 --- a/packages/web3-eth-contract/test/integration/contract_methods.test.ts +++ b/packages/web3-eth-contract/test/integration/contract_methods.test.ts @@ -92,7 +92,48 @@ describe('contract', () => { }); describe('send', () => { - it('should returns a receipt', async () => { + beforeEach(() => { + contractDeployed.config.ignoreGasPricing = false; + }); + it('should return a receipt', async () => { + const receipt = await contractDeployed.methods + .setValues(1, 'string value', true) + .send(sendOptions); + + expect(receipt.events).toBeUndefined(); + expect(receipt).toEqual( + expect.objectContaining({ + // status: BigInt(1), + transactionHash: expect.any(String), + }), + ); + + // To avoid issue with the `objectContaining` and `cypress` had to add + // these expectations explicitly on each attribute + expect(receipt.status).toEqual(BigInt(1)); + }); + + it('should return a receipt with ignoring gas config true', async () => { + contractDeployed.config.ignoreGasPricing = true; + const receipt = await contractDeployed.methods + .setValues(1, 'string value', true) + .send(sendOptions); + + expect(receipt.events).toBeUndefined(); + expect(receipt).toEqual( + expect.objectContaining({ + // status: BigInt(1), + transactionHash: expect.any(String), + }), + ); + + // To avoid issue with the `objectContaining` and `cypress` had to add + // these expectations explicitly on each attribute + expect(receipt.status).toEqual(BigInt(1)); + }); + + it('should return a receipt with ignoring gas config false', async () => { + contractDeployed.config.ignoreGasPricing = false; const receipt = await contractDeployed.methods .setValues(1, 'string value', true) .send(sendOptions); diff --git a/packages/web3-eth/CHANGELOG.md b/packages/web3-eth/CHANGELOG.md index 71fd65e4f9e..8d89960bd8e 100644 --- a/packages/web3-eth/CHANGELOG.md +++ b/packages/web3-eth/CHANGELOG.md @@ -284,3 +284,7 @@ Documentation: ### Changed - Allow `getEthereumjsTxDataFrom` to return additional fields that may be passed if using a `customTransactionSchema`. + +### Added + +- `populateGasPrice` function now checks `Web3Context.config.ignoreGasPricing`. If `ignoreGasPricing` is true, gasPrice will not be estimated (#7320) diff --git a/packages/web3-eth/src/utils/send_tx_helper.ts b/packages/web3-eth/src/utils/send_tx_helper.ts index fbe48c0e868..e28b353cda1 100644 --- a/packages/web3-eth/src/utils/send_tx_helper.ts +++ b/packages/web3-eth/src/utils/send_tx_helper.ts @@ -163,6 +163,7 @@ export class SendTxHelper< }): Promise { let result = transactionFormatted; if ( + !this.web3Context.config.ignoreGasPricing && !this.options?.ignoreGasPricing && isNullish((transactionFormatted as Transaction).gasPrice) && (isNullish((transaction as Transaction).maxPriorityFeePerGas) || diff --git a/packages/web3-eth/src/validation.ts b/packages/web3-eth/src/validation.ts index b318e16dd41..81a5ebd1090 100644 --- a/packages/web3-eth/src/validation.ts +++ b/packages/web3-eth/src/validation.ts @@ -27,13 +27,7 @@ import { TransactionWithSenderAPI, ETH_DATA_FORMAT, } from 'web3-types'; -import { - isAddress, - isHexStrict, - isHexString32Bytes, - isNullish, - isUInt, -} from 'web3-validator'; +import { isAddress, isHexStrict, isHexString32Bytes, isNullish, isUInt } from 'web3-validator'; import { ChainMismatchError, HardforkMismatchError, 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 b16479d886b..3de0778c500 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 @@ -199,7 +199,34 @@ describe('Web3Eth.sendTransaction', () => { const minedTransactionData = await web3Eth.getTransaction(response.transactionHash); expect(minedTransactionData).toMatchObject(transaction); }); + it('should send a transaction while ignoring gas price successfully', async () => { + const transaction: TransactionWithToLocalWalletIndex = { + from: tempAcc.address, + to: '0x0000000000000000000000000000000000000000', + value: BigInt(1), + data: '0x64edfbf0e2c706ba4a09595315c45355a341a576cc17f3a19f43ac1c02f814ee', + }; + const localWeb3Eth = new Web3Eth(getSystemTestProvider()); + localWeb3Eth.config.ignoreGasPricing = true; + const response = await localWeb3Eth.sendTransaction(transaction); + expect(response.status).toBe(BigInt(1)); + await closeOpenConnection(localWeb3Eth); + }); + it('should send a transaction with automated gas price successfully', async () => { + const transaction: TransactionWithToLocalWalletIndex = { + from: tempAcc.address, + to: '0x0000000000000000000000000000000000000000', + value: BigInt(1), + data: '0x64edfbf0e2c706ba4a09595315c45355a341a576cc17f3a19f43ac1c02f814ee', + }; + + const localWeb3Eth = new Web3Eth(getSystemTestProvider()); + localWeb3Eth.config.ignoreGasPricing = false; + const response = await localWeb3Eth.sendTransaction(transaction); + expect(response.status).toBe(BigInt(1)); + await closeOpenConnection(localWeb3Eth); + }); describe('Deploy and interact with contract', () => { let greeterContractAddress: string; 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 23e0d2aa526..6e25a0872b4 100644 --- a/packages/web3-eth/test/unit/send_tx_helper.test.ts +++ b/packages/web3-eth/test/unit/send_tx_helper.test.ts @@ -89,7 +89,8 @@ describe('sendTxHelper class', () => { let sendTxHelper: SendTxHelper; let promiEvent: Web3PromiEvent; let web3Context: Web3Context; - beforeAll(() => { + beforeEach(() => { + jest.clearAllMocks(); web3Context = new Web3Context(); promiEvent = new Web3PromiEvent(resolve => { resolve({} as unknown as TransactionReceipt); @@ -267,4 +268,50 @@ describe('sendTxHelper class', () => { expect(utils.trySendTransaction).toHaveBeenCalled(); expect(wallet.signTransaction).toHaveBeenCalledWith(receipt); }); + it('should not call getTransactionGasPricing when ignoreGasPricing is true', async () => { + web3Context.config.ignoreGasPricing = true; + const transaction = { + from: '0xa7d9ddbe1f17865597fbd27ec712455208b6b76d', + input: '0x68656c6c6f21', + nonce: '0x15', + to: '0xf02c1c8e6114b1dbe8937a39260b5b0a374432bb', + value: '0xf3dbb76162000', + type: '0x0', + chainId: '0x1', + }; + const _sendTxHelper = new SendTxHelper({ + web3Context, + promiEvent: promiEvent as PromiEvent, + options: {}, + returnFormat: DEFAULT_RETURN_FORMAT, + }); + await _sendTxHelper.populateGasPrice({ + transactionFormatted: transaction, + transaction, + }); + expect(getTransactionGasPricing).not.toHaveBeenCalled(); + }); + it('should call getTransactionGasPricing when ignoreGasPricing is false', async () => { + web3Context.config.ignoreGasPricing = false; + const transaction = { + from: '0xa7d9ddbe1f17865597fbd27ec712455208b6b76d', + input: '0x68656c6c6f21', + nonce: '0x15', + to: '0xf02c1c8e6114b1dbe8937a39260b5b0a374432bb', + value: '0xf3dbb76162000', + type: '0x0', + chainId: '0x1', + }; + const _sendTxHelper = new SendTxHelper({ + web3Context, + promiEvent: promiEvent as PromiEvent, + options: {}, + returnFormat: DEFAULT_RETURN_FORMAT, + }); + await _sendTxHelper.populateGasPrice({ + transactionFormatted: transaction, + transaction, + }); + expect(getTransactionGasPricing).toHaveBeenCalled(); + }); }); diff --git a/packages/web3-types/src/eth_contract_types.ts b/packages/web3-types/src/eth_contract_types.ts index 00eba77e5ed..5a0381e6362 100644 --- a/packages/web3-types/src/eth_contract_types.ts +++ b/packages/web3-types/src/eth_contract_types.ts @@ -168,4 +168,8 @@ export interface ContractOptions { * The max fee per gas to use for transactions. */ maxFeePerGas?: Uint; + /** + * Ignore gas price, turn on for metamask suggestion fee + */ + ignoreGasPricing?: boolean; } From 822f8c15863b28e4685b88f1da5502c36b9752d3 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 16 Oct 2024 09:52:53 -0400 Subject: [PATCH 168/186] fix types file (#7331) --- packages/web3-types/src/eth_contract_types.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/web3-types/src/eth_contract_types.ts b/packages/web3-types/src/eth_contract_types.ts index 5a0381e6362..00eba77e5ed 100644 --- a/packages/web3-types/src/eth_contract_types.ts +++ b/packages/web3-types/src/eth_contract_types.ts @@ -168,8 +168,4 @@ export interface ContractOptions { * The max fee per gas to use for transactions. */ maxFeePerGas?: Uint; - /** - * Ignore gas price, turn on for metamask suggestion fee - */ - ignoreGasPricing?: boolean; } From 376f19259deae5424ccc8274f2d7c978456905e0 Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 21 Oct 2024 10:29:45 -0400 Subject: [PATCH 169/186] v4.14.0 (#7333) * bump versioning for 4.14.0 * add missing changelogs * bump types package * bumped types to patch fix * add web3_eip6363 to exports --- CHANGELOG.md | 27 ++++++++++-- packages/web3-core/CHANGELOG.md | 4 +- packages/web3-core/package.json | 6 +-- packages/web3-eth-abi/CHANGELOG.md | 4 +- packages/web3-eth-abi/package.json | 6 +-- packages/web3-eth/CHANGELOG.md | 4 +- packages/web3-eth/package.json | 10 ++--- packages/web3-types/CHANGELOG.md | 6 ++- packages/web3-types/package.json | 2 +- packages/web3-utils/CHANGELOG.md | 4 +- packages/web3-utils/package.json | 6 +-- packages/web3/CHANGELOG.md | 41 +++++++++++++++++++ packages/web3/package.json | 12 +++--- packages/web3/src/providers.exports.ts | 1 + packages/web3/src/version.ts | 2 +- .../test/e2e/mainnet/get_storage_at.test.ts | 2 +- 16 files changed, 105 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0666ebd3166..6a7bdee5a44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2727,20 +2727,41 @@ If there are any bugs, improvements, optimizations or any new feature proposal f - `Web3.providers` namespace exports `type EIP6963ProviderResponse = Map`. Return type for the static `Web3.requestEIP6963Providers` function is now `Promise`. (#7239) - The callback function provided to the static `Web3.onNewProviderDiscovered` function expects a parameter of type `EIP6963ProvidersMapUpdateEvent` as opposed to `EIP6963AnnounceProviderEvent`. (#7242) -## [Unreleased] +## [4.14.0] ### Added +#### web3-core + +- Added new property `ignoreGasPricing` to `Web3ConfigOptions`. If `ignoreGasPricing` is true, gasPrice will not be estimated (#7320) + #### web3-eth - `syncing` subscription now supports Besu and Nethermind payload format +- `populateGasPrice` function now checks `Web3Context.config.ignoreGasPricing`. If `ignoreGasPricing` is true, gasPrice will not be estimated (#7320) ### Changed +#### web3 + +- Exported EIP-6963 types are no longer under the `providers` namespace. (#7270) + #### web3-eth - Allow `getEthereumjsTxDataFrom` to return additional fields that may be passed if using a `customTransactionSchema`. -#### web3 +#### web3-types -- Exported EIP-6963 types are no longer under the `providers` namespace. (#7270) +- update the type for `baseFeePerGas` at `web3.eth.getFeeHistory` to be a number. (#7291) + +### Fixed + +#### web3-eth-abi + +- `decodeLog` , `decodeParametersWith` , `decodeParameters` and `decodeParameters` now accepts first immutable param as well (#7288) + +#### web3-utils + +- fix `padRight` validation failure on large `uint` (#7265) + +## [Unreleased] diff --git a/packages/web3-core/CHANGELOG.md b/packages/web3-core/CHANGELOG.md index b02756a075d..06c64e305e9 100644 --- a/packages/web3-core/CHANGELOG.md +++ b/packages/web3-core/CHANGELOG.md @@ -239,8 +239,10 @@ Documentation: - Adds a new property (`customTransactionSchema`) to `Web3ConfigOptions`(#7227) -## [Unreleased] +## [4.7.0] ### Added - Added new property `ignoreGasPricing` to `Web3ConfigOptions`. If `ignoreGasPricing` is true, gasPrice will not be estimated (#7320) + +## [Unreleased] diff --git a/packages/web3-core/package.json b/packages/web3-core/package.json index 2f99bf7d3de..67cebb09009 100644 --- a/packages/web3-core/package.json +++ b/packages/web3-core/package.json @@ -1,6 +1,6 @@ { "name": "web3-core", - "version": "4.6.0", + "version": "4.7.0", "description": "Web3 core tools for sub-packages. This is an internal package.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -47,8 +47,8 @@ "web3-eth-iban": "^4.0.7", "web3-providers-http": "^4.2.0", "web3-providers-ws": "^4.0.8", - "web3-types": "^1.8.0", - "web3-utils": "^4.3.1", + "web3-types": "^1.8.1", + "web3-utils": "^4.3.2", "web3-validator": "^2.0.6" }, "optionalDependencies": { diff --git a/packages/web3-eth-abi/CHANGELOG.md b/packages/web3-eth-abi/CHANGELOG.md index cc8ab72306d..9cb5bd2d7b9 100644 --- a/packages/web3-eth-abi/CHANGELOG.md +++ b/packages/web3-eth-abi/CHANGELOG.md @@ -188,8 +188,10 @@ Documentation: - Handle common cases for smart contract errors according to EIP 838: `0x4e487b71` which is the ‘selector’ for `Panic(uint256)` and `0x08c379a0` is the ‘selector’ of `Error(string)`. (7155) -## [Unreleased] +## [4.3.0] ### Fixed - `decodeLog` , `decodeParametersWith` , `decodeParameters` and `decodeParameters` now accepts first immutable param as well (#7288) + +## [Unreleased] diff --git a/packages/web3-eth-abi/package.json b/packages/web3-eth-abi/package.json index 3331a9603b4..71ad43e1bf8 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.4", + "version": "4.3.0", "description": "Web3 module encode and decode EVM in/output.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -44,8 +44,8 @@ "dependencies": { "abitype": "0.7.1", "web3-errors": "^1.3.0", - "web3-types": "^1.8.0", - "web3-utils": "^4.3.1", + "web3-types": "^1.8.1", + "web3-utils": "^4.3.2", "web3-validator": "^2.0.6" }, "devDependencies": { diff --git a/packages/web3-eth/CHANGELOG.md b/packages/web3-eth/CHANGELOG.md index 8d89960bd8e..946429b8c7b 100644 --- a/packages/web3-eth/CHANGELOG.md +++ b/packages/web3-eth/CHANGELOG.md @@ -279,7 +279,7 @@ Documentation: - Adds the same `{transactionSchema?: ValidationSchemaInput}` that exists in `formatTransaction` to `validateTransactionForSigning` -## [Unreleased] +## [4.10.0] ### Changed @@ -288,3 +288,5 @@ Documentation: ### Added - `populateGasPrice` function now checks `Web3Context.config.ignoreGasPricing`. If `ignoreGasPricing` is true, gasPrice will not be estimated (#7320) + +## [Unreleased] diff --git a/packages/web3-eth/package.json b/packages/web3-eth/package.json index 66cf22b8852..6cd93768a6b 100644 --- a/packages/web3-eth/package.json +++ b/packages/web3-eth/package.json @@ -1,6 +1,6 @@ { "name": "web3-eth", - "version": "4.9.0", + "version": "4.10.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.6.0", + "web3-core": "^4.7.0", "web3-errors": "^1.3.0", - "web3-eth-abi": "^4.2.4", + "web3-eth-abi": "^4.3.0", "web3-eth-accounts": "^4.2.1", "web3-net": "^4.1.0", "web3-providers-ws": "^4.0.8", "web3-rpc-methods": "^1.3.0", - "web3-types": "^1.8.0", - "web3-utils": "^4.3.1", + "web3-types": "^1.8.1", + "web3-utils": "^4.3.2", "web3-validator": "^2.0.6" } } diff --git a/packages/web3-types/CHANGELOG.md b/packages/web3-types/CHANGELOG.md index aa6b36d4885..c28706fb44f 100644 --- a/packages/web3-types/CHANGELOG.md +++ b/packages/web3-types/CHANGELOG.md @@ -208,8 +208,10 @@ Documentation: - Add COMMITTED to BlockTags (#7124) -## [Unreleased] +## [1.8.1] -### Changed +### Fixed - update the type for `baseFeePerGas` at `web3.eth.getFeeHistory` to be a number. (#7291) + +## [Unreleased] diff --git a/packages/web3-types/package.json b/packages/web3-types/package.json index 85a069f1984..a16d9737993 100644 --- a/packages/web3-types/package.json +++ b/packages/web3-types/package.json @@ -1,6 +1,6 @@ { "name": "web3-types", - "version": "1.8.0", + "version": "1.8.1", "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 45439db666e..940059963d8 100644 --- a/packages/web3-utils/CHANGELOG.md +++ b/packages/web3-utils/CHANGELOG.md @@ -234,8 +234,10 @@ Documentation: - `_sendPendingRequests` will catch unhandled errors from `_sendToSocket` (#6968) -## [Unreleased] +## [4.3.2] ### Fixed - fix `padRight` validation failure on large `uint` (#7265) + +## [Unreleased] diff --git a/packages/web3-utils/package.json b/packages/web3-utils/package.json index c9c6c6a4ad8..d9c12c25ac8 100644 --- a/packages/web3-utils/package.json +++ b/packages/web3-utils/package.json @@ -1,7 +1,7 @@ { "name": "web3-utils", "sideEffects": false, - "version": "4.3.1", + "version": "4.3.2", "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.2.0", - "web3-types": "^1.7.0", + "web3-errors": "^1.3.0", + "web3-types": "^1.8.1", "web3-validator": "^2.0.6" } } diff --git a/packages/web3/CHANGELOG.md b/packages/web3/CHANGELOG.md index a9ad657d1c3..9830831b15a 100644 --- a/packages/web3/CHANGELOG.md +++ b/packages/web3/CHANGELOG.md @@ -489,4 +489,45 @@ Documentation: - `Web3.providers` namespace exports `type EIP6963ProviderResponse = Map`. Return type for the static `Web3.requestEIP6963Providers` function is now `Promise`. (#7239) - The callback function provided to the static `Web3.onNewProviderDiscovered` function expects a parameter of type `EIP6963ProvidersMapUpdateEvent` as opposed to `EIP6963AnnounceProviderEvent`. (#7242) +## [4.14.0] + +### Added + +#### web3 + +- Exported EIP-6963 types are no longer under the `providers` namespace. (#7270) + +#### web3-core + +- Added new property `ignoreGasPricing` to `Web3ConfigOptions`. If `ignoreGasPricing` is true, gasPrice will not be estimated (#7320) + +#### web3-eth + +- `populateGasPrice` function now checks `Web3Context.config.ignoreGasPricing`. If `ignoreGasPricing` is true, gasPrice will not be estimated (#7320) + +### Changed + +#### web3 + +- Exported EIP-6963 types are no longer under the `providers` namespace. (#7270) + +#### web3-eth + +- Allow `getEthereumjsTxDataFrom` to return additional fields that may be passed if using a `customTransactionSchema`. + +#### web3-types + +- `syncing` subscription now supports Besu and Nethermind payload format +- update the type for `baseFeePerGas` at `web3.eth.getFeeHistory` to be a number. (#7291) + +### Fixed + +#### web3-eth-abi + +- `decodeLog` , `decodeParametersWith` , `decodeParameters` and `decodeParameters` now accepts first immutable param as well (#7288) + +#### web3-utils + +- fix `padRight` validation failure on large `uint` (#7265) + ## [Unreleased] diff --git a/packages/web3/package.json b/packages/web3/package.json index 596d82d1b35..06565aeb4a3 100644 --- a/packages/web3/package.json +++ b/packages/web3/package.json @@ -1,6 +1,6 @@ { "name": "web3", - "version": "4.13.0", + "version": "4.14.0", "description": "Ethereum JavaScript API", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -86,10 +86,10 @@ "web3-providers-ipc": "^4.0.7" }, "dependencies": { - "web3-core": "^4.6.0", + "web3-core": "^4.7.0", "web3-errors": "^1.3.0", - "web3-eth": "^4.9.0", - "web3-eth-abi": "^4.2.4", + "web3-eth": "^4.10.0", + "web3-eth-abi": "^4.3.0", "web3-eth-accounts": "^4.2.1", "web3-eth-contract": "^4.7.0", "web3-eth-ens": "^4.4.0", @@ -100,8 +100,8 @@ "web3-providers-ws": "^4.0.8", "web3-rpc-methods": "^1.3.0", "web3-rpc-providers": "^1.0.0-rc.2", - "web3-types": "^1.8.0", - "web3-utils": "^4.3.1", + "web3-types": "^1.8.1", + "web3-utils": "^4.3.2", "web3-validator": "^2.0.6" } } diff --git a/packages/web3/src/providers.exports.ts b/packages/web3/src/providers.exports.ts index c0bbadc1b23..3d20b0116b9 100644 --- a/packages/web3/src/providers.exports.ts +++ b/packages/web3/src/providers.exports.ts @@ -19,3 +19,4 @@ export { Eip1193Provider, SocketProvider } from 'web3-utils'; export * as http from 'web3-providers-http'; export * as ws from 'web3-providers-ws'; +export * from './web3_eip6963.js'; diff --git a/packages/web3/src/version.ts b/packages/web3/src/version.ts index 82d0ac0dfb9..6d4d3be7654 100644 --- a/packages/web3/src/version.ts +++ b/packages/web3/src/version.ts @@ -1 +1 @@ -/* eslint-disable header/header */ export const Web3PkgInfo = { version: '4.13.0' }; +/* eslint-disable header/header */ export const Web3PkgInfo = { version: '4.14.0' }; diff --git a/packages/web3/test/e2e/mainnet/get_storage_at.test.ts b/packages/web3/test/e2e/mainnet/get_storage_at.test.ts index f70b23cc0d8..5d6ccba97f5 100644 --- a/packages/web3/test/e2e/mainnet/get_storage_at.test.ts +++ b/packages/web3/test/e2e/mainnet/get_storage_at.test.ts @@ -85,7 +85,7 @@ describe(`${getSystemTestBackend()} tests - getStorageAt`, () => { } else if (block === 'blockHash' || block === 'blockNumber') { // eslint-disable-next-line jest/no-conditional-expect expect(result).toBe( - '0x00000000000000000000000000000000000000000000000000c347d66ae6ce59', + '0x00000000000000000000000000000000000000000000000000c34723fc9a9240', ); } else { // eslint-disable-next-line jest/no-conditional-expect From fab66e99d5108cfc41999ab7260fb050beb76936 Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Mon, 21 Oct 2024 08:00:56 -0700 Subject: [PATCH 170/186] Intermediate dApp Guide (#7334) * Intermediate dApp Guide Closes #7038 * Fix Typo Closes #7324 Replaces #7325 * Update docs/docs/guides/07_dapps/intermediate-dapp.md Co-authored-by: Kris <605420+krzysu@users.noreply.github.com> * Small Changes Based on Suggestion from @krzysu --------- Co-authored-by: Kris <605420+krzysu@users.noreply.github.com> --- .../docs/guides/07_dapps/intermediate-dapp.md | 560 ++++++++++++++++++ .../subscribe_migration_guide.md | 2 +- 2 files changed, 561 insertions(+), 1 deletion(-) create mode 100644 docs/docs/guides/07_dapps/intermediate-dapp.md diff --git a/docs/docs/guides/07_dapps/intermediate-dapp.md b/docs/docs/guides/07_dapps/intermediate-dapp.md new file mode 100644 index 00000000000..16c05c232fb --- /dev/null +++ b/docs/docs/guides/07_dapps/intermediate-dapp.md @@ -0,0 +1,560 @@ +--- +sidebar_position: 3 +sidebar_label: 'Tutorial: Intermediate dApp Development' +--- + +# Intermediate dApp Development + + + +This tutorial demonstrates using Web3.js to build a dApp that uses the [EIP-6963 standard](https://eips.ethereum.org/EIPS/eip-6963). EIP-6963 was designed to make it easy for dApp developers to support users with more than one wallet browser extension. Rather than relying on the global `window.ethereum` object, EIP-6963 specifies a mechanism that allows multiple wallet providers to announce their availability to a dApp. The dApp in this tutorial will allow the user to transfer ether from one of their wallet accounts to another account on the network. + +:::info +This intermediate tutorial builds on concepts that were introduced in other tutorials, like [Sending Transactions](/guides/transactions/transactions) and [Connecting to Metamask with React](/guides/dapps/metamask-react). If you are new to working with Web3.js, considering reviewing or completing those tutorials before starting this one. +::: + +## Overview + +Here is a high-level overview of the steps in this tutorial: + +1. Review prerequisites +2. Initialize a new React project and add dependencies +3. Configure and start a Hardhat node +4. Update the React app and create a provider store +5. Use a provider with Web3.js +6. Create a form to transfer ether + +:::tip +If you encounter any issues while following this guide or have any questions, don't hesitate to seek assistance. Our friendly community is ready to help you out! Join our [Discord](https://discord.gg/F4NUfaCC) server and head to the **#web3js-general** channel to connect with other developers and get the support you need. +::: + +## Step 1: Prerequisites + +This tutorial assumes basic familiarity with the command line as well as familiarity with React and [Node.js](https://nodejs.org/). Before starting this tutorial, ensure that Node.js and its package manager, npm, are installed. + +```console +$: node -v +# your version may be different, but it's best to use the current stable version +v20.14.0 +$: npm -v +10.8.2 +``` + +Make sure that at least one EIP-6963 compliant wallet browser extension is installed and set up, such as: + +- [Enkrypt](https://www.enkrypt.com/download.html) +- [Exodus](https://www.exodus.com/download/) +- [MetaMask](https://metamask.io/download/) +- [Trust Wallet](https://trustwallet.com/download) + +This tutorial will use MetaMask as an example. + +## Step 2: Initialize a New React Project and Add Dependencies + +Initialize a new React project and navigate into the new project directory: + +```console +npx create-react-app web3-intermediate-dapp --template typescript +cd web3-intermediate-dapp +``` + +Add Web3.js to the project with the following command: + +```console +npm i web3 +``` + +This tutorial uses a local [Hardhat](https://hardhat.org/) network, which will be configured to fund the wallet's account. To support this, install Hardhat as a development dependency: + +```console +npm i -D hardhat +``` + +## Step 3: Configure and Start the Hardhat Node + +Because Hardhat will be configured with the wallet's secret recovery phrase, it's important that the Hardhat configuration file is not checked into version control systems like GitHub. Open the `.gitignore` file that was created by the `create-react-app` command and add a line for `hardhat.config.js`: + +```bash +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# add this line +hardhat.config.js + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# production +/build + +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* +``` + +Create a file called `hardhat.config.js` and add the following Hardhat configuration: + +```typescript +module.exports = { + networks: { + hardhat: { + accounts: { + mnemonic: '', + }, + chainId: 1337, + }, + }, +}; +``` + +Replace `` with the wallet's [secret recovery phrase](https://support.metamask.io/privacy-and-security/how-to-reveal-your-secret-recovery-phrase/). + +Start the Hardhat development network by executing the following command: + +```console +npx hardhat node +``` + +Executing this command will produce the following output, which provides the URL that can be used to connect to the Hardhat development network: + +```console +Started HTTP and WebSocket JSON-RPC server at http://127.0.0.1:8545/ + +Accounts +======== +Account #0: (10000 ETH) + +... + +Account #19: (10000 ETH) +``` + +:::note +If the Hardhat development network was properly configured with the wallet's secret recovery phrase, `` should match the address of the wallet's first account. +::: + +The Hardhat development network needs to remain running in the terminal that was used to start it. Open a new terminal instance in the project directory to execute the remaining commands in this tutorial. + +## Step 4: Update the React App and Create a Provider Store + +Delete the following files: + +- `src/App.css` +- `src/App.test.tsx` +- `src/logo.svg` + +Create a `src/useProviders.ts` file and add the following code: + +```ts +import { useSyncExternalStore } from 'react'; +import { providers, Web3 } from 'web3'; + +// initial empty list of providers +let providerList: providers.EIP6963ProviderDetail[] = []; + +/** + * External store for subscribing to EIP-6963 providers + */ +const providerStore = { + // get current list of providers + getSnapshot: () => providerList, + // subscribe to EIP-6963 provider events + subscribe: (callback: () => void) => { + // update the list of providers + function setProviders(response: providers.EIP6963ProviderResponse) { + providerList = []; + response.forEach((provider: providers.EIP6963ProviderDetail) => { + providerList.push(provider); + }); + + // notify subscribers that the list of providers has been updated + callback(); + } + + // Web3.js helper function to request EIP-6963 providers + Web3.requestEIP6963Providers().then(setProviders); + + // handler for newly discovered providers + function updateProviders(providerEvent: providers.EIP6963ProvidersMapUpdateEvent) { + setProviders(providerEvent.detail); + } + + // register handler for newly discovered providers with Web3.js helper function + Web3.onNewProviderDiscovered(updateProviders); + + // return a function that unsubscribes from the created event listener + return () => + window.removeEventListener(providers.web3ProvidersMapUpdated as any, updateProviders); + }, +}; + +// export the provider store as a React hook +export const useProviders = () => + useSyncExternalStore(providerStore.subscribe, providerStore.getSnapshot); +``` + +This file exports a single member - a React [`useSyncExternalStore` hook](https://react.dev/reference/react/useSyncExternalStore) with a subscription to the EIP-6963 providers. The provider store uses the Web3.js types and helper functions for working with the EIP-6963 standard. Any React component can use this hook to access a dynamic list of the available EIP-6963 providers. + +Replace the contents of the `src/App.tsx` file with the following: + +```tsx +import type { providers } from 'web3'; + +import { useProviders } from './useProviders'; + +function App() { + // get the dynamic list of providers + const providers = useProviders(); + + return ( + <> + {providers.map((provider: providers.EIP6963ProviderDetail) => { + // list available providers + return ( +
+ {provider.info.name} [{provider.info.rdns}] +
+ ); + })} + + ); +} + +export default App; +``` + +The `App` component defined in `src/App.tsx` uses the provider store to list the available EIP-6963 providers. For each provider, information that is [specified by EIP-6963](https://eips.ethereum.org/EIPS/eip-6963#provider-info) will be displayed. + +Use the `npm start` command to launch the dApp in a new browser tab. Keep this browser tab open as it will automatically update when changes are made. If everything is working properly, all available EIP-6963 providers should be listed. + +## Step 5: Use a Provider with Web3.js + +Replace the contents of the `src/App.tsx` file with the following: + +```tsx +import { useEffect, useState } from 'react'; +import { type providers, Web3 } from 'web3'; + +import { useProviders } from './useProviders'; + +function App() { + // get the dynamic list of providers + const providers = useProviders(); + + // application state + const [web3, setWeb3] = useState(undefined); + const [accounts, setAccounts] = useState([]); + const [balances, setBalances] = useState>(new Map()); + + // click-handler for provider buttons + function setProvider(provider: providers.EIP6963ProviderDetail) { + const web3: Web3 = new Web3(provider.provider); + setWeb3(web3); + web3.eth.requestAccounts().then(setAccounts); + provider.provider.on('accountsChanged', setAccounts); + provider.provider.on('chainChanged', () => window.location.reload()); + } + + // update account balances + useEffect(() => { + async function updateBalances(web3: Web3) { + const balances = new Map(); + for (const account of accounts) { + const balance = await web3.eth.getBalance(account); + balances.set(account, parseFloat(web3.utils.fromWei(balance, 'ether'))); + } + + setBalances(balances); + } + + if (web3 === undefined) { + return; + } + + // set balances for list of accounts + updateBalances(web3); + + // update balances when a new block is created + const subscription = web3.eth.subscribe('newBlockHeaders').then(subscription => { + subscription.on('data', () => updateBalances(web3)); + return subscription; + }); + + return () => { + subscription.then(subscription => subscription.unsubscribe()); + }; + }, [accounts, web3]); + + return ( + <> + {web3 === undefined + ? // no provider set, display list of available providers + providers.map((provider: providers.EIP6963ProviderDetail) => { + // for each provider, display a button to connect to that provider + return ( +
+ +
+ ); + }) + : accounts.map((address: string, ndx: number) => { + // provider set, list accounts and balances + return ( +
+
Account: {address}
+
Balance: {`${balances.get(address)}`}
+ {ndx !== accounts.length - 1 ?
: null} +
+ ); + })} + + ); +} + +export default App; +``` + +The `App` component now displays a button for each provider. The click-handler for these buttons creates a new Web3.js instance that uses the specified provider and [requests the accounts](/api/web3-eth/class/Web3Eth#requestAccounts) from that provider. An [`accountsChanged` handler](https://docs.metamask.io/wallet/reference/provider-api/#accountschanged) is registered to keep the list of accounts up-to-date. The click-handler also registers a [`chainChanged` handler](https://docs.metamask.io/wallet/reference/provider-api/#chainchanged) that reloads the page when the chain that the wallet is using changes. When the list of accounts is updated, a map of account balances is created. This map is kept up-to-date by creating a [`NewHeadsSubscription` handler](/api/web3-eth/class/NewHeadsSubscription) that refreshes the account balances every time a new block is created. + +In order to use the Hardhat development network with a wallet browser extension, the wallet must be configured with the details of the Hardhat development network. This process will be slightly different for each wallet (e.g. [add a network to MetaMask](https://support.metamask.io/networks-and-sidechains/managing-networks/how-to-add-a-custom-network-rpc/#adding-a-network-manually)), but will always require specifying the URL that was displayed when the Hardhat network was started as well as the chain ID 1337, which was specified in the `hardhat.config.js` file. Before proceeding, ensure that the wallet has been configured with the details of the Hardhat development network. + +Once the wallet has been configured with the details of the Hardhat development network, return to the browser tab that was opened by `npm start`. Ensure that the wallet is connected to the Hardhat network and click the button for the wallet. If everything is working properly, the wallet's accounts should be listed and each should have a balance of 10,000 ETH. + +## Step 6: Create a Form to Transfer Ether + +Create a `src/TransferForm.tsx` file and add the following code: + +```tsx +import { type ChangeEvent, type FormEvent, useEffect, useState } from 'react'; +import { type Address, Web3 } from 'web3'; + +function TransferForm({ address, web3 }: { address: Address; web3: Web3 }) { + // form state + const [isFormValid, setIsFormValid] = useState(false); + const [transferTo, setTransferTo] = useState(''); + const [transferAmount, setTransferAmount] = useState(''); + + // https://www.geeksforgeeks.org/ethereum-address-validation-using-regular-expressions/ + function isValidAddress(address: string): boolean { + return /^(0x)?[0-9a-fA-F]{40}$/.test(address); + } + + // form validator + useEffect(() => { + const amount = parseFloat(transferAmount); + setIsFormValid(isValidAddress(transferTo) && !isNaN(amount) && amount > 0); + }, [transferTo, transferAmount]); + + // form change handler + function transferFormChange(e: ChangeEvent): void { + const { name, value } = e.target; + + if (name === 'to') { + setTransferTo(value); + } else if (name === 'amount') { + setTransferAmount(value); + } + } + + // submit form handler + function transfer(e: FormEvent): void { + // prevent default form submission behavior + e.preventDefault(); + + if (web3 === undefined) { + return; + } + + // parse form data + const formData: FormData = new FormData(e.currentTarget); + + // validate "to" field + const to: FormDataEntryValue | null = formData.get('to'); + if (to === null || !isValidAddress(to as string)) { + return; + } + + // check if "amount" field is empty + const amount: FormDataEntryValue | null = formData.get('amount'); + if (amount === null) { + return; + } + + // validate "amount" field + const value: number = parseFloat(amount as string); + if (isNaN(value) || value <= 0) { + return; + } + + // reset form + setTransferTo(''); + setTransferAmount(''); + + // send transaction + web3.eth.sendTransaction({ + from: address, + to: to as string, + value: web3.utils.toWei(value, 'ether'), + }); + } + + return ( +
+ + + + + + + + + +
+ ); +} + +export default TransferForm; +``` + +The `src/TransferForm.tsx` file defines a React component called `TransferForm` that can be used to transfer ether from one account to another. This component requires two attributes: an address, which is the address that the ether will be transferred _from_, and a `Web3` object, which is the `Web3` instance that will be used to perform the transfer. + +Replace the contents of the `src/App.tsx` file with the following: + +```tsx +import { useEffect, useState } from 'react'; +import { type providers, Web3 } from 'web3'; + +// highlight-next-line +import TransferForm from './TransferForm'; +import { useProviders } from './useProviders'; + +function App() { + // get the dynamic list of providers + const providers = useProviders(); + + // application state + const [web3, setWeb3] = useState(undefined); + const [accounts, setAccounts] = useState([]); + const [balances, setBalances] = useState>(new Map()); + + // click-handler for provider buttons + function setProvider(provider: providers.EIP6963ProviderDetail) { + const web3: Web3 = new Web3(provider.provider); + setWeb3(web3); + web3.eth.requestAccounts().then(setAccounts); + provider.provider.on('accountsChanged', setAccounts); + provider.provider.on('chainChanged', () => window.location.reload()); + } + + // update account balances + useEffect(() => { + async function updateBalances(web3: Web3) { + const balances = new Map(); + for (const account of accounts) { + const balance = await web3.eth.getBalance(account); + balances.set(account, parseFloat(web3.utils.fromWei(balance, 'ether'))); + } + + setBalances(balances); + } + + if (web3 === undefined) { + return; + } + + // set balances for list of accounts + updateBalances(web3); + + // update balances when a new block is created + const subscription = web3.eth.subscribe('newBlockHeaders').then(subscription => { + subscription.on('data', () => updateBalances(web3)); + return subscription; + }); + + return () => { + subscription.then(subscription => subscription.unsubscribe()); + }; + }, [accounts, web3]); + + return ( + <> + {web3 === undefined + ? // no provider set, display list of available providers + providers.map((provider: providers.EIP6963ProviderDetail) => { + // for each provider, display a button to connect to that provider + return ( +
+ +
+ ); + }) + : accounts.map((address: string, ndx: number) => { + // provider set, list accounts and balances + return ( +
+
Account: {address}
+
Balance: {`${balances.get(address)}`}
+ // highlight-next-line + + {ndx !== accounts.length - 1 ?
: null} +
+ ); + })} + + ); +} + +export default App; +``` + +The only thing that has changed in the `src/App.tsx` file is that the `TransferForm` component is being imported and a `TransferForm` is created for each account in the list of accounts. + +Return to the browser tab that was opened by `npm start`. There should now be a transfer form below the address and balance of each account. Use the form to transfer ether - this should require accepting a confirmation from the wallet and should result in the balance of the transferring account decreasing. + +## Conclusion + +This tutorial demonstrated using Web3.js to build a dApp, including using EIP-6963 for the discovery of multiple wallet providers and using a wallet provider to submit a transaction to an Ethereum network. Web3.js provides helpful utilities for working with the EIP-6963 standard and works seamlessly with EIP-6963 providers. diff --git a/docs/docs/guides/15_web3_upgrade_guide/subscribe_migration_guide.md b/docs/docs/guides/15_web3_upgrade_guide/subscribe_migration_guide.md index 6ce6c2512a2..328c2a728e1 100644 --- a/docs/docs/guides/15_web3_upgrade_guide/subscribe_migration_guide.md +++ b/docs/docs/guides/15_web3_upgrade_guide/subscribe_migration_guide.md @@ -42,7 +42,7 @@ In summary, the differences you need to be aware of when subscribing to blockcha - It does not accept a callback function. - It returns a subscription object that you can use to listen to `data` and `error` events. - You should now use the `on`, or `once`, method on the newly returned subscription object to listen to `data` and `error` events, instead of passing a callback function directly. -- You can have multiple event listeners, if you have, for example multiple `on` calls. And you can get the number of listeners in you code by calling `listenerCount(event_name)` or get the listeners with `listeners(event_name)`. +- You can have multiple event listeners, if you have, for example multiple `on` calls. And you can get the number of listeners in your code by calling `listenerCount(event_name)` or get the listeners with `listeners(event_name)`. Keep in mind that these differences apply to all blockchain event subscriptions, not just to the `newBlockHeaders` event. From ed85ccecadc97cbacd0ee00dfb1a2ee7497347b8 Mon Sep 17 00:00:00 2001 From: Muhammad Altabba <24407834+Muhammad-Altabba@users.noreply.github.com> Date: Mon, 21 Oct 2024 18:13:17 +0200 Subject: [PATCH 171/186] fix: ensure contractInstance.subscriptionManager.subscribe is not throwing (#7327) * rename `LogsSubscription` at `web3-eth-contract` to `ContractLogsSubscription` * fix issue that `contractInstance.subscriptionManager.subscribe` was throwing * add a unit test --- .../src/contract-subscription-manager.ts | 72 +++++++++++++++++++ packages/web3-eth-contract/src/contract.ts | 27 +++++-- ...iption.ts => contract_log_subscription.ts} | 10 ++- packages/web3-eth-contract/src/index.ts | 6 +- packages/web3-eth-contract/src/types.ts | 4 +- .../web3-eth-contract/test/fixtures/erc20.ts | 8 +-- .../web3-eth-contract/test/fixtures/erc721.ts | 10 +-- .../test/unit/log_subscription.test.ts | 38 +++++++++- 8 files changed, 153 insertions(+), 22 deletions(-) create mode 100644 packages/web3-eth-contract/src/contract-subscription-manager.ts rename packages/web3-eth-contract/src/{log_subscription.ts => contract_log_subscription.ts} (92%) diff --git a/packages/web3-eth-contract/src/contract-subscription-manager.ts b/packages/web3-eth-contract/src/contract-subscription-manager.ts new file mode 100644 index 00000000000..3065e8aa7f4 --- /dev/null +++ b/packages/web3-eth-contract/src/contract-subscription-manager.ts @@ -0,0 +1,72 @@ +/* +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 { Web3SubscriptionConstructor, Web3SubscriptionManager } from 'web3-core'; +import { EthExecutionAPI, ContractAbi, DataFormat, DEFAULT_RETURN_FORMAT } from 'web3-types'; +// eslint-disable-next-line import/no-cycle +import { Contract } from './contract.js'; + +/** + * Similar to `Web3SubscriptionManager` but has a reference to the Contract that uses + */ +export class ContractSubscriptionManager< + API extends EthExecutionAPI, + RegisteredSubs extends { + [key: string]: Web3SubscriptionConstructor; + } = any, // = ContractSubscriptions +> extends Web3SubscriptionManager { + public readonly parentContract: Contract; + + /** + * + * @param - Web3SubscriptionManager + * @param - parentContract + * + * @example + * ```ts + * const requestManager = new Web3RequestManager("ws://localhost:8545"); + * const contract = new Contract(...) + * const subscriptionManager = new Web3SubscriptionManager(requestManager, {}, contract); + * ``` + */ + public constructor( + self: Web3SubscriptionManager, + parentContract: Contract, + ) { + super(self.requestManager, self.registeredSubscriptions); + + this.parentContract = parentContract; + } + + /** + * Will create a new subscription + * + * @param name - The subscription you want to subscribe to + * @param args - Optional additional parameters, depending on the subscription type + * @param returnFormat- ({@link DataFormat} defaults to {@link DEFAULT_RETURN_FORMAT}) - Specifies how the return data from the call should be formatted. + * + * Will subscribe to a specific topic (note: name) + * @returns The subscription object + */ + public async subscribe( + name: T, + args?: ConstructorParameters[0], + returnFormat: DataFormat = DEFAULT_RETURN_FORMAT, + ): Promise> { + return super.subscribe(name, args ?? this.parentContract.options, returnFormat); + } +} diff --git a/packages/web3-eth-contract/src/contract.ts b/packages/web3-eth-contract/src/contract.ts index 5566d0840bf..a99dc27628e 100644 --- a/packages/web3-eth-contract/src/contract.ts +++ b/packages/web3-eth-contract/src/contract.ts @@ -105,7 +105,7 @@ import { encodeEventABI, encodeMethodABI, } from './encoding.js'; -import { LogsSubscription } from './log_subscription.js'; +import { ContractLogsSubscription } from './contract_log_subscription.js'; import { ContractEventOptions, NonPayableMethodObject, @@ -123,6 +123,8 @@ import { } from './utils.js'; // eslint-disable-next-line import/no-cycle import { DeployerMethodClass } from './contract-deployer-method-class.js'; +// eslint-disable-next-line import/no-cycle +import { ContractSubscriptionManager } from './contract-subscription-manager.js'; type ContractBoundMethod< Abi extends AbiFunctionFragment, @@ -179,9 +181,9 @@ export type ContractMethodSend = Web3PromiEvent< * ``` * * @param options - The options used to subscribe for the event - * @returns - A Promise resolved with {@link LogsSubscription} object + * @returns - A Promise resolved with {@link ContractLogsSubscription} object */ -export type ContractBoundEvent = (options?: ContractEventOptions) => LogsSubscription; +export type ContractBoundEvent = (options?: ContractEventOptions) => ContractLogsSubscription; // To avoid circular dependency between types and encoding, declared these types here. export type ContractEventsInterface< @@ -204,11 +206,13 @@ export type ContractEventEmitterInterface = { type EventParameters = Parameters[2]; const contractSubscriptions = { - logs: LogsSubscription, + logs: ContractLogsSubscription, newHeads: NewHeadsSubscription, newBlockHeaders: NewHeadsSubscription, }; +type ContractSubscriptions = typeof contractSubscriptions; + /** * The `web3.eth.Contract` makes it easy to interact with smart contracts on the ethereum blockchain. * For using contract package, first install Web3 package using: `npm i web3` or `yarn add web3` based on your package manager, after that contracts features can be used as mentioned in following snippet. @@ -406,9 +410,15 @@ const contractSubscriptions = { * */ export class Contract - extends Web3Context + extends Web3Context implements Web3EventEmitter> { + protected override _subscriptionManager: ContractSubscriptionManager; + + public override get subscriptionManager(): ContractSubscriptionManager { + return this._subscriptionManager; + } + /** * The options `object` for the contract instance. `from`, `gas` and `gasPrice` are used as fallback values when sending transactions. * @@ -564,6 +574,11 @@ export class Contract registeredSubscriptions: contractSubscriptions, }); + this._subscriptionManager = new ContractSubscriptionManager< + EthExecutionAPI, + ContractSubscriptions + >(super.subscriptionManager, this); + // Init protected properties if ((contractContext as Web3Context)?.wallet) { this._wallet = (contractContext as Web3Context).wallet; @@ -1414,7 +1429,7 @@ export class Contract abi, params[0] as EventParameters, ); - const sub = new LogsSubscription( + const sub = new ContractLogsSubscription( { address: this.options.address, topics, diff --git a/packages/web3-eth-contract/src/log_subscription.ts b/packages/web3-eth-contract/src/contract_log_subscription.ts similarity index 92% rename from packages/web3-eth-contract/src/log_subscription.ts rename to packages/web3-eth-contract/src/contract_log_subscription.ts index 3cb1a527941..8010309c7cb 100644 --- a/packages/web3-eth-contract/src/log_subscription.ts +++ b/packages/web3-eth-contract/src/contract_log_subscription.ts @@ -28,9 +28,9 @@ import { Web3RequestManager, Web3Subscription, Web3SubscriptionManager } from 'w import { decodeEventABI } from 'web3-eth'; /** - * LogSubscription to be used to subscribe to events logs. + * ContractLogsSubscription to be used to subscribe to events logs. * - * Following events are supported and can be accessed with either {@link LogsSubscription.once} or ${@link LogsSubscription.on} methods. + * Following events are supported and can be accessed with either {@link ContractLogsSubscription.once} or ${@link ContractLogsSubscription.on} methods. * * - **connected**: Emitted when the subscription is connected. * - **data**: Fires on each incoming event with the event object as argument. @@ -81,7 +81,7 @@ import { decodeEventABI } from 'web3-eth'; * } * ``` */ -export class LogsSubscription extends Web3Subscription< +export class ContractLogsSubscription extends Web3Subscription< { data: EventLog; changed: EventLog & { removed: true }; @@ -162,3 +162,7 @@ export class LogsSubscription extends Web3Subscription< return decodeEventABI(this.abi, data as LogsInput, this.jsonInterface, super.returnFormat); } } +/** + * @deprecated LogsSubscription is renamed to ContractLogsSubscription in this package to not be confused with LogsSubscription at 'web3-eth'. + */ +export const LogsSubscription = ContractLogsSubscription; diff --git a/packages/web3-eth-contract/src/index.ts b/packages/web3-eth-contract/src/index.ts index ad7b5ab7fb7..93e90f03b96 100644 --- a/packages/web3-eth-contract/src/index.ts +++ b/packages/web3-eth-contract/src/index.ts @@ -42,11 +42,15 @@ along with web3.js. If not, see . */ import { Contract } from './contract.js'; +import { ContractLogsSubscription } from './contract_log_subscription.js'; +/** @deprecated Use `ContractLogsSubscription` instead. */ +export type LogsSubscription = ContractLogsSubscription; + export * from './encoding.js'; export * from './contract.js'; export * from './contract-deployer-method-class.js'; -export * from './log_subscription.js'; +export * from './contract_log_subscription.js'; export * from './types.js'; export * from './utils.js'; diff --git a/packages/web3-eth-contract/src/types.ts b/packages/web3-eth-contract/src/types.ts index 8f4bf564ca4..6ecff146844 100644 --- a/packages/web3-eth-contract/src/types.ts +++ b/packages/web3-eth-contract/src/types.ts @@ -32,7 +32,7 @@ import { } from 'web3-types'; import { NewHeadsSubscription, SendTransactionEvents } from 'web3-eth'; import type { ContractOptions } from 'web3-types'; -import { LogsSubscription } from './log_subscription.js'; +import { ContractLogsSubscription } from './contract_log_subscription.js'; export type NonPayableTxOptions = NonPayableCallOptions; export type PayableTxOptions = PayableCallOptions; @@ -462,7 +462,7 @@ export type Web3ContractContext = Partial< Web3ContextInitOptions< EthExecutionAPI, { - logs: typeof LogsSubscription; + logs: typeof ContractLogsSubscription; newHeads: typeof NewHeadsSubscription; newBlockHeaders: typeof NewHeadsSubscription; } diff --git a/packages/web3-eth-contract/test/fixtures/erc20.ts b/packages/web3-eth-contract/test/fixtures/erc20.ts index cf4b595ec8d..18b51748a4e 100644 --- a/packages/web3-eth-contract/test/fixtures/erc20.ts +++ b/packages/web3-eth-contract/test/fixtures/erc20.ts @@ -16,7 +16,7 @@ along with web3.js. If not, see . */ import { Address, Numbers } from 'web3-types'; -import { LogsSubscription } from '../../src/log_subscription'; +import { ContractLogsSubscription } from '../../src/contract_log_subscription'; import { ContractEventOptions, PayableMethodObject, NonPayableMethodObject } from '../../src/types'; export interface Erc20Interface { @@ -53,9 +53,9 @@ export interface Erc20Interface { }; events: { - [key: string]: (options?: ContractEventOptions) => LogsSubscription; - Approval: (options?: ContractEventOptions) => LogsSubscription; - Transfer: (options?: ContractEventOptions) => LogsSubscription; + [key: string]: (options?: ContractEventOptions) => ContractLogsSubscription; + Approval: (options?: ContractEventOptions) => ContractLogsSubscription; + Transfer: (options?: ContractEventOptions) => ContractLogsSubscription; }; } diff --git a/packages/web3-eth-contract/test/fixtures/erc721.ts b/packages/web3-eth-contract/test/fixtures/erc721.ts index 36c87289c24..0dab8017ea4 100644 --- a/packages/web3-eth-contract/test/fixtures/erc721.ts +++ b/packages/web3-eth-contract/test/fixtures/erc721.ts @@ -16,7 +16,7 @@ along with web3.js. If not, see . */ import { Address, Numbers } from 'web3-types'; -import { LogsSubscription } from '../../src/log_subscription'; +import { ContractLogsSubscription } from '../../src/contract_log_subscription'; import { ContractEventOptions, NonPayableMethodObject, PayableMethodObject } from '../../src/types'; export interface Erc721Interface { @@ -55,10 +55,10 @@ export interface Erc721Interface { }; events: { - [key: string]: (options?: ContractEventOptions) => LogsSubscription; - Transfer: (options?: ContractEventOptions) => LogsSubscription; - Approval: (options?: ContractEventOptions) => LogsSubscription; - ApprovalForAll: (options?: ContractEventOptions) => LogsSubscription; + [key: string]: (options?: ContractEventOptions) => ContractLogsSubscription; + Transfer: (options?: ContractEventOptions) => ContractLogsSubscription; + Approval: (options?: ContractEventOptions) => ContractLogsSubscription; + ApprovalForAll: (options?: ContractEventOptions) => ContractLogsSubscription; }; } diff --git a/packages/web3-eth-contract/test/unit/log_subscription.test.ts b/packages/web3-eth-contract/test/unit/log_subscription.test.ts index ccc72acaac6..520157a3cab 100644 --- a/packages/web3-eth-contract/test/unit/log_subscription.test.ts +++ b/packages/web3-eth-contract/test/unit/log_subscription.test.ts @@ -17,7 +17,8 @@ along with web3.js. If not, see . import * as eth from 'web3-eth'; import { WebSocketProvider } from 'web3-providers-ws'; -import { Contract } from '../../src'; +import { Web3SubscriptionManager } from 'web3-core'; +import { Contract, ContractLogsSubscription } from '../../src'; import { GreeterAbi, GreeterBytecode } from '../shared_fixtures/build/Greeter'; jest.mock('web3-eth'); @@ -76,4 +77,39 @@ describe('contract log subscription', () => { ], }); }); + + it('should be able to subscribe to logs with contractInstance.subscriptionManager.subscribe', async () => { + const address = '0x407D73d8a49eeb85D32Cf465507dd71d507100c1'; + const contractInstance = new Contract(GreeterAbi, address); + + jest.spyOn(WebSocketProvider.prototype, 'request').mockImplementation( + async (payload: any) => { + return { + jsonrpc: '2.0', + id: payload.id, + result: {}, + }; + }, + ); + + jest.spyOn(Web3SubscriptionManager.prototype, 'subscribe').mockImplementation( + async (name: string | number | symbol, args?: any) => { + expect(name).toBe('logs'); + expect(args.address).toBe(address); + + return new ContractLogsSubscription(args, { + subscriptionManager: contractInstance.subscriptionManager, + }); + }, + ); + + contract.setProvider(providerString); + + const sub = contractInstance.subscriptionManager.subscribe('logs'); + expect(await sub).toBeInstanceOf(ContractLogsSubscription); + + contractInstance.subscriptionManager.clear(); + + contractInstance.provider?.disconnect(); + }); }); From 331aa9c4a9d59bf1f8fc7dc64870f8fb8b799b1a Mon Sep 17 00:00:00 2001 From: Junaid <86780488+jdevcs@users.noreply.github.com> Date: Tue, 22 Oct 2024 10:03:44 +0200 Subject: [PATCH 172/186] 7202 account abstraction (#7311) * AA package structure * pkg config * aa types * aa class * utils * exports * readme chnglog and configs update * allow local provider if different * export * tests * updated tests * package config * docs update * doc update * doc update --- docs/docusaurus.config.js | 41 +- .../web3-account-abstraction/.eslintignore | 1 + .../web3-account-abstraction/.eslintrc.js | 7 + packages/web3-account-abstraction/.gitignore | 0 packages/web3-account-abstraction/.npmignore | 1 + packages/web3-account-abstraction/.npmrc | 1 + .../web3-account-abstraction/.prettierignore | 1 + .../web3-account-abstraction/.prettierrc.json | 1 + .../web3-account-abstraction/CHANGELOG.md | 38 + packages/web3-account-abstraction/README.md | 59 + .../assets/logo/web3js.ai | 1516 +++++++++++++++++ .../assets/logo/web3js.jpg | Bin 0 -> 80258 bytes .../assets/logo/web3js.svg | 33 + .../web3-account-abstraction/package.json | 65 + .../web3-account-abstraction/src/index.ts | 24 + .../web3-account-abstraction/src/types.ts | 107 ++ .../web3-account-abstraction/src/utils.ts | 97 ++ .../web3-account-abstraction/src/web3_aa.ts | 340 ++++ .../test/.eslintrc.js | 7 + .../test/config/jest.config.js | 1 + .../test/config/setup.js | 24 + .../test/integration/jest.config.js | 33 + .../test/integration/setup.js | 24 + .../test/tsconfig.json | 1 + .../test/unit/account_abstraction.test.ts | 184 ++ .../test/unit/jest.config.js | 9 + .../tsconfig.cjs.json | 1 + .../tsconfig.esm.json | 1 + .../tsconfig.types.json | 1 + packages/web3-account-abstraction/tsdoc.json | 4 + scripts/docshelper/classesdoc.config.js | 28 +- 31 files changed, 2628 insertions(+), 22 deletions(-) create mode 120000 packages/web3-account-abstraction/.eslintignore create mode 100644 packages/web3-account-abstraction/.eslintrc.js create mode 100644 packages/web3-account-abstraction/.gitignore create mode 120000 packages/web3-account-abstraction/.npmignore create mode 120000 packages/web3-account-abstraction/.npmrc create mode 120000 packages/web3-account-abstraction/.prettierignore create mode 120000 packages/web3-account-abstraction/.prettierrc.json create mode 100644 packages/web3-account-abstraction/CHANGELOG.md create mode 100644 packages/web3-account-abstraction/README.md create mode 100644 packages/web3-account-abstraction/assets/logo/web3js.ai create mode 100644 packages/web3-account-abstraction/assets/logo/web3js.jpg create mode 100644 packages/web3-account-abstraction/assets/logo/web3js.svg create mode 100644 packages/web3-account-abstraction/package.json create mode 100644 packages/web3-account-abstraction/src/index.ts create mode 100644 packages/web3-account-abstraction/src/types.ts create mode 100644 packages/web3-account-abstraction/src/utils.ts create mode 100644 packages/web3-account-abstraction/src/web3_aa.ts create mode 100644 packages/web3-account-abstraction/test/.eslintrc.js create mode 120000 packages/web3-account-abstraction/test/config/jest.config.js create mode 100644 packages/web3-account-abstraction/test/config/setup.js create mode 100644 packages/web3-account-abstraction/test/integration/jest.config.js create mode 100644 packages/web3-account-abstraction/test/integration/setup.js create mode 120000 packages/web3-account-abstraction/test/tsconfig.json create mode 100644 packages/web3-account-abstraction/test/unit/account_abstraction.test.ts create mode 100644 packages/web3-account-abstraction/test/unit/jest.config.js create mode 120000 packages/web3-account-abstraction/tsconfig.cjs.json create mode 120000 packages/web3-account-abstraction/tsconfig.esm.json create mode 120000 packages/web3-account-abstraction/tsconfig.types.json create mode 100644 packages/web3-account-abstraction/tsdoc.json diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index 2fff620f657..dbfba51275c 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -37,6 +37,7 @@ const packages = [ 'web3-providers-http', 'web3-providers-ws', 'web3-providers-ipc', + 'web3-account-abstraction', ]; /** @type {import('@docusaurus/types').Config} */ @@ -109,7 +110,7 @@ const config = { /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ ({ navbar: { - title: 'Web3.js Docs', + title: 'Web3.js Docs', logo: { src: 'img/web3js.svg', }, @@ -184,19 +185,43 @@ const config = { */ playgroundPosition: 'bottom', }, - image:"https://pbs.twimg.com/profile_images/1746099108937363456/duG_Pqem_400x400.jpg", + image: 'https://pbs.twimg.com/profile_images/1746099108937363456/duG_Pqem_400x400.jpg', metadata: [ - { name: 'keywords', content: 'web3.js, web3, web3js, ethereum, ethereum json rpc, blockchain development, smart contracts, dapps, dApp development' }, - { name: 'description', content: 'Collection of comprehensive TypeScript libraries for Interaction with the Ethereum JSON RPC API and utility functions.' }, + { + name: 'keywords', + content: + 'web3.js, web3, web3js, ethereum, ethereum json rpc, blockchain development, smart contracts, dapps, dApp development', + }, + { + name: 'description', + content: + 'Collection of comprehensive TypeScript libraries for Interaction with the Ethereum JSON RPC API and utility functions.', + }, { name: 'og:title', content: 'Web3.js Documentation' }, - { name: 'og:description', content: 'Collection of comprehensive TypeScript libraries for Interaction with the Ethereum JSON RPC API and utility functions.' }, + { + name: 'og:description', + content: + 'Collection of comprehensive TypeScript libraries for Interaction with the Ethereum JSON RPC API and utility functions.', + }, { name: 'og:type', content: 'website' }, { name: 'og:url', content: 'https://docs.web3js.org' }, - { name: 'og:image', content: 'https://pbs.twimg.com/profile_images/1746099108937363456/duG_Pqem_400x400.jpg' }, + { + name: 'og:image', + content: + 'https://pbs.twimg.com/profile_images/1746099108937363456/duG_Pqem_400x400.jpg', + }, { name: 'twitter:card', content: 'summary_large_image' }, { name: 'twitter:title', content: 'Web3.js Documentation' }, - { name: 'twitter:description', content: 'Official documentation for web3.js, the Type/JavaScript library for interacting with the Ethereum blockchain.' }, - { name: 'twitter:image', content: 'https://raw.githubusercontent.com/web3/web3.js/4.x/assets/logo/web3js.jpg' }, + { + name: 'twitter:description', + content: + 'Official documentation for web3.js, the Type/JavaScript library for interacting with the Ethereum blockchain.', + }, + { + name: 'twitter:image', + content: + 'https://raw.githubusercontent.com/web3/web3.js/4.x/assets/logo/web3js.jpg', + }, ], }), }; diff --git a/packages/web3-account-abstraction/.eslintignore b/packages/web3-account-abstraction/.eslintignore new file mode 120000 index 00000000000..94760d2888d --- /dev/null +++ b/packages/web3-account-abstraction/.eslintignore @@ -0,0 +1 @@ +../../templates/.eslintignore.tmpl \ No newline at end of file diff --git a/packages/web3-account-abstraction/.eslintrc.js b/packages/web3-account-abstraction/.eslintrc.js new file mode 100644 index 00000000000..12a507e5126 --- /dev/null +++ b/packages/web3-account-abstraction/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + extends: '../../.eslintrc.js', + parserOptions: { + project: './tsconfig.esm.json', + tsconfigRootDir: __dirname, + }, +}; diff --git a/packages/web3-account-abstraction/.gitignore b/packages/web3-account-abstraction/.gitignore new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/web3-account-abstraction/.npmignore b/packages/web3-account-abstraction/.npmignore new file mode 120000 index 00000000000..8a0be70f3ed --- /dev/null +++ b/packages/web3-account-abstraction/.npmignore @@ -0,0 +1 @@ +../../templates/.npmignore.tmpl \ No newline at end of file diff --git a/packages/web3-account-abstraction/.npmrc b/packages/web3-account-abstraction/.npmrc new file mode 120000 index 00000000000..5cc817c4313 --- /dev/null +++ b/packages/web3-account-abstraction/.npmrc @@ -0,0 +1 @@ +../../templates/.npmrc.tmpl \ No newline at end of file diff --git a/packages/web3-account-abstraction/.prettierignore b/packages/web3-account-abstraction/.prettierignore new file mode 120000 index 00000000000..044e4a3df69 --- /dev/null +++ b/packages/web3-account-abstraction/.prettierignore @@ -0,0 +1 @@ +../../templates/.prettierignore.tmpl \ No newline at end of file diff --git a/packages/web3-account-abstraction/.prettierrc.json b/packages/web3-account-abstraction/.prettierrc.json new file mode 120000 index 00000000000..00ecd510aaf --- /dev/null +++ b/packages/web3-account-abstraction/.prettierrc.json @@ -0,0 +1 @@ +../../templates/.prettierrc.json.tmpl \ No newline at end of file diff --git a/packages/web3-account-abstraction/CHANGELOG.md b/packages/web3-account-abstraction/CHANGELOG.md new file mode 100644 index 00000000000..87f56484e8e --- /dev/null +++ b/packages/web3-account-abstraction/CHANGELOG.md @@ -0,0 +1,38 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + + + +## [Unreleased] diff --git a/packages/web3-account-abstraction/README.md b/packages/web3-account-abstraction/README.md new file mode 100644 index 00000000000..61d49413a5e --- /dev/null +++ b/packages/web3-account-abstraction/README.md @@ -0,0 +1,59 @@ +

+ web3.js +

+ +# web3.js - Account Abstraction + +![ES Version](https://img.shields.io/badge/ES-2020-yellow) +![Node Version](https://img.shields.io/badge/node-14.x-green) +[![NPM Package][npm-image]][npm-url] +[![Downloads][downloads-image]][npm-url] + +This is a sub-package of [web3.js][repo]. + +`web3-account-abstraction` contains the ideal setup for a Web3.js package. + +## Installation + +You can install the package either using [NPM](https://www.npmjs.com/package/web3-account-abstraction) or using [Yarn](https://yarnpkg.com/package/web3-account-abstraction) + +### Using NPM + +```bash +npm install web3-account-abstraction +``` + +### Using Yarn + +```bash +yarn add web3-account-abstraction +``` + +## Getting Started + +- :writing_hand: If you have questions [submit an issue](https://github.com/ChainSafe/web3.js/issues/new) or join us on [Discord](https://discord.gg/yjyvFRP) + ![Discord](https://img.shields.io/discord/593655374469660673.svg?label=Discord&logo=discord) + +## Prerequisites + +- :gear: [NodeJS](https://nodejs.org/) (LTS/Fermium) +- :toolbox: [Yarn](https://yarnpkg.com/)/[Lerna](https://lerna.js.org/) + +## Package.json Scripts + +| Script | Description | +| ---------------- | -------------------------------------------------- | +| clean | Uses `rimraf` to remove `dist/` | +| build | Uses `tsc` to build package and dependent packages | +| lint | Uses `eslint` to lint package | +| lint:fix | Uses `eslint` to check and fix any warnings | +| format | Uses `prettier` to format the code | +| test | Uses `jest` to run unit tests | +| test:integration | Uses `jest` to run tests under `/test/integration` | +| test:unit | Uses `jest` to run tests under `/test/unit` | + +[docs]: https://docs.web3js.org/ +[repo]: https://github.com/web3/web3.js/tree/4.x/tools/web3-account-abstraction +[npm-image]: https://img.shields.io/github/package-json/v/web3/web3.js/4.x?filename=tools%2Fweb3-account-abstraction%2Fpackage.json +[npm-url]: https://npmjs.org/package/web3-account-abstraction +[downloads-image]: https://img.shields.io/npm/dm/web3-account-abstraction?label=npm%20downloads diff --git a/packages/web3-account-abstraction/assets/logo/web3js.ai b/packages/web3-account-abstraction/assets/logo/web3js.ai new file mode 100644 index 00000000000..669ef50e7cd --- /dev/null +++ b/packages/web3-account-abstraction/assets/logo/web3js.ai @@ -0,0 +1,1516 @@ +%PDF-1.5 % +1 0 obj <>/OCGs[5 0 R 6 0 R 29 0 R 30 0 R]>>/Pages 3 0 R/Type/Catalog>> endobj 2 0 obj <>stream + + + + + application/pdf + + + Print + + + + + 2017-01-27T15:51:37Z + 2017-01-27T15:51:37Z + 2017-01-27T14:51:33Z + Adobe Illustrator CS6 (Macintosh) + + + + 256 + 240 + JPEG + /9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgA8AEAAwER AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE 1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp 0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo +DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A7F+an5hy6Ov6F0qTjqMq VubhTvCjDYL4Ow3r2Hz2IQ8x8teevMXl+cvaXBlgdi01pMS8Tk7k0rUMfFTXCr2Xyl+Z/l/X+FvI 31DUWoPqszCjn/iuTYN8tj7YKSzDArsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirs VdirsVdirsVdirsVdirsVdir5W1nUptU1a71CYkvdSvKa9gx2H0DbJIQeKtqrMwVQWZjRVG5JPYY q+ify70jzPpujKmvXrTu4BgtX+NoFp9lpDuT/k9BgKWV4FdirsVdirsVdirsVdirsVdirsVdirsV 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 + + + + + + uuid:394c157d-8cf0-f94e-8261-98ccb840e1bc + xmp.did:106820F817276811822ACF3CAA06C913 + uuid:5D20892493BFDB11914A8590D31508C8 + proof:pdf + + uuid:1898a391-1dba-4249-9e7f-8804d46504b0 + xmp.did:FE7F11740720681183D1839CF7E6F44E + uuid:5D20892493BFDB11914A8590D31508C8 + proof:pdf + + + + + saved + xmp.iid:FE7F11740720681183D1839CF7E6F44E + 2017-01-06T15:27:37Z + Adobe Illustrator CS6 (Macintosh) + / + + + saved + xmp.iid:106820F817276811822ACF3CAA06C913 + 2017-01-27T14:51:33Z + Adobe Illustrator CS6 (Macintosh) + / + + + + + + Document + Print + + + False + False + 1 + + 3840.000000 + 2160.000000 + Pixels + + + + Cyan + Magenta + Yellow + Black + + + + + + Default Swatch Group + 0 + + + + White + RGB + PROCESS + 255 + 255 + 255 + + + Black + RGB + PROCESS + 35 + 31 + 32 + + + CMYK Red + RGB + PROCESS + 237 + 28 + 36 + + + CMYK Yellow + RGB + PROCESS + 255 + 242 + 0 + + + CMYK Green + RGB + PROCESS + 0 + 166 + 81 + + + CMYK Cyan + RGB + PROCESS + 0 + 174 + 239 + + + CMYK Blue + RGB + PROCESS + 46 + 49 + 146 + + + CMYK Magenta + RGB + PROCESS + 236 + 0 + 140 + + + C=15 M=100 Y=90 K=10 + RGB + PROCESS + 190 + 30 + 45 + + + C=0 M=90 Y=85 K=0 + RGB + PROCESS + 239 + 65 + 54 + + + C=0 M=80 Y=95 K=0 + RGB + PROCESS + 241 + 90 + 41 + + + C=0 M=50 Y=100 K=0 + RGB + PROCESS + 247 + 148 + 30 + + + C=0 M=35 Y=85 K=0 + RGB + PROCESS + 251 + 176 + 64 + + + C=5 M=0 Y=90 K=0 + RGB + PROCESS + 249 + 237 + 50 + + + C=20 M=0 Y=100 K=0 + RGB + PROCESS + 215 + 223 + 35 + + + C=50 M=0 Y=100 K=0 + RGB + PROCESS + 141 + 198 + 63 + + + C=75 M=0 Y=100 K=0 + RGB + PROCESS + 57 + 181 + 74 + + + C=85 M=10 Y=100 K=10 + RGB + PROCESS + 0 + 148 + 68 + + + C=90 M=30 Y=95 K=30 + RGB + PROCESS + 0 + 104 + 56 + + + C=75 M=0 Y=75 K=0 + RGB + PROCESS + 43 + 182 + 115 + + + C=80 M=10 Y=45 K=0 + RGB + PROCESS + 0 + 167 + 157 + + + C=70 M=15 Y=0 K=0 + RGB + PROCESS + 39 + 170 + 225 + + + C=85 M=50 Y=0 K=0 + RGB + PROCESS + 28 + 117 + 188 + + + C=100 M=95 Y=5 K=0 + RGB + PROCESS + 43 + 57 + 144 + + + C=100 M=100 Y=25 K=25 + RGB + PROCESS + 38 + 34 + 98 + + + C=75 M=100 Y=0 K=0 + RGB + PROCESS + 102 + 45 + 145 + + + C=50 M=100 Y=0 K=0 + RGB + PROCESS + 146 + 39 + 143 + + + C=35 M=100 Y=35 K=10 + RGB + PROCESS + 158 + 31 + 99 + + + C=10 M=100 Y=50 K=0 + RGB + PROCESS + 218 + 28 + 92 + + + C=0 M=95 Y=20 K=0 + RGB + PROCESS + 238 + 42 + 123 + + + C=25 M=25 Y=40 K=0 + RGB + PROCESS + 194 + 181 + 155 + + + C=40 M=45 Y=50 K=5 + RGB + PROCESS + 155 + 133 + 121 + + + C=50 M=50 Y=60 K=25 + RGB + PROCESS + 114 + 102 + 88 + + + C=55 M=60 Y=65 K=40 + RGB + PROCESS + 89 + 74 + 66 + + + C=25 M=40 Y=65 K=0 + RGB + PROCESS + 196 + 154 + 108 + + + C=30 M=50 Y=75 K=10 + RGB + PROCESS + 169 + 124 + 80 + + + C=35 M=60 Y=80 K=25 + RGB + PROCESS + 139 + 94 + 60 + + + C=40 M=65 Y=90 K=35 + RGB + PROCESS + 117 + 76 + 41 + + + C=40 M=70 Y=100 K=50 + RGB + PROCESS + 96 + 57 + 19 + + + C=50 M=70 Y=80 K=70 + RGB + PROCESS + 60 + 36 + 21 + + + + + + Grays + 1 + + + + C=0 M=0 Y=0 K=100 + RGB + PROCESS + 35 + 31 + 32 + + + C=0 M=0 Y=0 K=90 + RGB + PROCESS + 65 + 64 + 66 + + + C=0 M=0 Y=0 K=80 + RGB + PROCESS + 88 + 89 + 91 + + + C=0 M=0 Y=0 K=70 + RGB + PROCESS + 109 + 110 + 113 + + + C=0 M=0 Y=0 K=60 + RGB + PROCESS + 128 + 130 + 133 + + + C=0 M=0 Y=0 K=50 + RGB + PROCESS + 147 + 149 + 152 + + + C=0 M=0 Y=0 K=40 + RGB + PROCESS + 167 + 169 + 172 + + + C=0 M=0 Y=0 K=30 + RGB + PROCESS + 188 + 190 + 192 + + + C=0 M=0 Y=0 K=20 + RGB + PROCESS + 209 + 211 + 212 + + + C=0 M=0 Y=0 K=10 + RGB + PROCESS + 230 + 231 + 232 + + + C=0 M=0 Y=0 K=5 + RGB + PROCESS + 241 + 242 + 242 + + + + + + Brights + 1 + + + + C=0 M=100 Y=100 K=0 + RGB + PROCESS + 237 + 28 + 36 + + + C=0 M=75 Y=100 K=0 + RGB + PROCESS + 242 + 101 + 34 + + + C=0 M=10 Y=95 K=0 + RGB + PROCESS + 255 + 222 + 23 + + + C=85 M=10 Y=100 K=0 + RGB + PROCESS + 0 + 161 + 75 + + + C=100 M=90 Y=0 K=0 + RGB + PROCESS + 33 + 64 + 154 + + + C=60 M=90 Y=0 K=0 + RGB + PROCESS + 127 + 63 + 152 + + + + + + + + + Adobe PDF library 10.01 + + + + + + + + + + + + + + + + + + + + + + + + + endstream endobj 3 0 obj <> endobj 8 0 obj <>/Resources<>/ExtGState<>/Properties<>>>/Thumb 36 0 R/TrimBox[0.0 0.0 3840.0 2160.0]/Type/Page>> endobj 32 0 obj <>stream +HlVI9 +TK"cN(rh4P@A*n(EJ\A*z/ϑ>Lۯ-RN%7޾[+ELD}~Q_,RC)i%mR=V{uS¡,YHzeۓ Q!5nJ9P5"v[ uWvU7nێ,FP^$$5DDpɁd4ڋۙ90q|dDZ a1439<0}f0{ꖐhE#R 5Y9$ +zX]@~3ϋ̬3L>س|cΏs%sZNVuAcp~Rc阏b^Aй><\I/wP;bJ@|n[fDڍ^ -[D@Dňށ(TIfйkUE'Gx"/Þ!QLwBq:p.RZ[Yh=j{9 ACIY8w;vuu-ӹ2/;@r fdk6z1FMǯk׊x]*C1ylDTAœu&4`pv)5bǸ+ +VEC04,Tp9p)1Rِ9ֿmXѭxhPxʐke&ډAeL9Jl1|)Y|zf*ѷ.G%:o]~Ljh(eMBC#\fch\ij\mr#Jܢo;oَ?I >stream +8;Z]!gMI$9&4O4Loo+g]Y:Y;L9GQ$:@3.,T.n*;fRief@%Sif_3dV)Ok+/'6SR3bl +9q7Fhkme7N\oK:^?"i4k6BkiO2r#nub+]#^#o2T&%;/3"U%t=#DK/;5(hd<.rJl^nXukH^04p_5&"H=J0K1J +F,$ endstream endobj 37 0 obj [/Indexed/DeviceRGB 255 38 0 R] endobj 38 0 obj <>stream +8;X]O>EqN@%''O_@%e@?J;%+8(9e>X=MR6S?i^YgA3=].HDXF.R$lIL@"pJ+EP(%0 +b]6ajmNZn*!='OQZeQ^Y*,=]?C.B+\Ulg9dhD*"iC[;*=3`oP1[!S^)?1)IZ4dup` +E1r!/,*0[*9.aFIR2&b-C#soRZ7Dl%MLY\.?d>Mn +6%Q2oYfNRF$$+ON<+]RUJmC0InDZ4OTs0S!saG>GGKUlQ*Q?45:CI&4J'_2j$XKrcYp0n+Xl_nU*O( +l[$6Nn+Z_Nq0]s7hs]`XX1nZ8&94a\~> endstream endobj 29 0 obj <> endobj 30 0 obj <> endobj 41 0 obj [/View/Design] endobj 42 0 obj <>>> endobj 39 0 obj [/View/Design] endobj 40 0 obj <>>> endobj 35 0 obj <> endobj 34 0 obj [/ICCBased 43 0 R] endobj 43 0 obj <>stream +HyTSwoɞc [5laQIBHADED2mtFOE.c}08׎8GNg9w߽'0 ֠Jb  + 2y.-;!KZ ^i"L0- @8(r;q7Ly&Qq4j|9 +V)gB0iW8#8wթ8_٥ʨQQj@&A)/g>'Kt;\ ӥ$պFZUn(4T%)뫔0C&Zi8bxEB;Pӓ̹A om?W= +x-[0}y)7ta>jT7@tܛ`q2ʀ&6ZLĄ?_yxg)˔zçLU*uSkSeO4?׸c. R ߁-25 S>ӣVd`rn~Y&+`;A4 A9=-tl`;~p Gp| [`L`< "A YA+Cb(R,*T2B- +ꇆnQt}MA0alSx k&^>0|>_',G!"F$H:R!zFQd?r 9\A&G rQ hE]a4zBgE#H *B=0HIpp0MxJ$D1D, VĭKĻYdE"EI2EBGt4MzNr!YK ?%_&#(0J:EAiQ(()ӔWT6U@P+!~mD eԴ!hӦh/']B/ҏӿ?a0nhF!X8܌kc&5S6lIa2cKMA!E#ƒdV(kel }}Cq9 +N')].uJr + wG xR^[oƜchg`>b$*~ :Eb~,m,-ݖ,Y¬*6X[ݱF=3뭷Y~dó ti zf6~`{v.Ng#{}}jc1X6fm;'_9 r:8q:˜O:ϸ8uJqnv=MmR 4 +n3ܣkGݯz=[==<=GTB(/S,]6*-W:#7*e^YDY}UjAyT`#D="b{ų+ʯ:!kJ4Gmt}uC%K7YVfFY .=b?SƕƩȺy چ k5%4m7lqlioZlG+Zz͹mzy]?uuw|"űNwW&e֥ﺱ*|j5kyݭǯg^ykEklD_p߶7Dmo꿻1ml{Mś nLl<9O[$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD-u`ֲK³8%yhYѹJº;.! +zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)Km endstream endobj 33 0 obj <> endobj 44 0 obj <> endobj 45 0 obj <>stream +%!PS-Adobe-3.0 %%Creator: Adobe Illustrator(R) 16.0 %%AI8_CreatorVersion: 16.0.0 %%For: (Ian Meikle) () %%Title: (Web3_70.ai) %%CreationDate: 27/01/2017 15:51 %%Canvassize: 16383 %%BoundingBox: 1170 -1782 2670 -378 %%HiResBoundingBox: 1170 -1781.6396 2670 -378.3604 %%DocumentProcessColors: Cyan Magenta Yellow Black %AI5_FileFormat 12.0 %AI12_BuildNumber: 682 %AI3_ColorUsage: Color %AI7_ImageSettings: 0 %%RGBProcessColor: 0 0 0 ([Registration]) %AI3_Cropmarks: 0 -2160 3840 0 %AI3_TemplateBox: 1920.5 -1080.5 1920.5 -1080.5 %AI3_TileBox: 1517 -1359.5 2300 -800.5 %AI3_DocumentPreview: None %AI5_ArtSize: 14400 14400 %AI5_RulerUnits: 6 %AI9_ColorModel: 1 %AI5_ArtFlags: 0 0 0 1 0 0 1 0 0 %AI5_TargetResolution: 800 %AI5_NumLayers: 2 %AI9_OpenToView: -1717.0015 636.9985 0.3333 2078 1150 18 0 0 32 191 0 0 0 1 1 0 1 1 0 1 %AI5_OpenViewLayers: 77 %%PageOrigin:1614 -1476 %AI7_GridSettings: 72 8 72 8 1 0 0.8 0.8 0.8 0.9 0.9 0.9 %AI9_Flatten: 1 %AI12_CMSettings: 00.MS %%EndComments endstream endobj 46 0 obj <>stream +%%BoundingBox: 1170 -1782 2670 -378 %%HiResBoundingBox: 1170 -1781.6396 2670 -378.3604 %AI7_Thumbnail: 128 120 8 %%BeginData: 14636 Hex Bytes %0000330000660000990000CC0033000033330033660033990033CC0033FF %0066000066330066660066990066CC0066FF009900009933009966009999 %0099CC0099FF00CC0000CC3300CC6600CC9900CCCC00CCFF00FF3300FF66 %00FF9900FFCC3300003300333300663300993300CC3300FF333300333333 %3333663333993333CC3333FF3366003366333366663366993366CC3366FF %3399003399333399663399993399CC3399FF33CC0033CC3333CC6633CC99 %33CCCC33CCFF33FF0033FF3333FF6633FF9933FFCC33FFFF660000660033 %6600666600996600CC6600FF6633006633336633666633996633CC6633FF %6666006666336666666666996666CC6666FF669900669933669966669999 %6699CC6699FF66CC0066CC3366CC6666CC9966CCCC66CCFF66FF0066FF33 %66FF6666FF9966FFCC66FFFF9900009900339900669900999900CC9900FF %9933009933339933669933999933CC9933FF996600996633996666996699 %9966CC9966FF9999009999339999669999999999CC9999FF99CC0099CC33 %99CC6699CC9999CCCC99CCFF99FF0099FF3399FF6699FF9999FFCC99FFFF %CC0000CC0033CC0066CC0099CC00CCCC00FFCC3300CC3333CC3366CC3399 %CC33CCCC33FFCC6600CC6633CC6666CC6699CC66CCCC66FFCC9900CC9933 %CC9966CC9999CC99CCCC99FFCCCC00CCCC33CCCC66CCCC99CCCCCCCCCCFF %CCFF00CCFF33CCFF66CCFF99CCFFCCCCFFFFFF0033FF0066FF0099FF00CC %FF3300FF3333FF3366FF3399FF33CCFF33FFFF6600FF6633FF6666FF6699 %FF66CCFF66FFFF9900FF9933FF9966FF9999FF99CCFF99FFFFCC00FFCC33 %FFCC66FFCC99FFCCCCFFCCFFFFFF33FFFF66FFFF99FFFFCC110000001100 %000011111111220000002200000022222222440000004400000044444444 %550000005500000055555555770000007700000077777777880000008800 %000088888888AA000000AA000000AAAAAAAABB000000BB000000BBBBBBBB %DD000000DD000000DDDDDDDDEE000000EE000000EEEEEEEE0000000000FF %00FF0000FFFFFF0000FF00FFFFFF00FFFFFF %524C45FFFFFFA87D7DFD7CFFA8FD0452A8FD79FFA87D527D527D527DA8FD %77FF7D525352525253525259FD76FF527D527D527D527D527D52A8AFFD72 %FF7D52527D5252527D52525259527DA8FD71FF7D527D527D527D527D527D %527DA8FD72FF52535252525352525253527DA8FD39FFCACAA1C3A0C2A0C2 %A0C3A1CACAFD2DFF7D527D527D527D527D527DA8FD37FFC3C3BBBBBABBB4 %BBB4BBBABB92BBBBBBC2C9CAFD2AFF527D5252527DFD04527DFD35FFA1C2 %98BA92BB92BB92BB98BB92BB98BB92BB92BA92BB99CAFD28FF7D527D527D %527D527D52FD33FFCAC9BBBA92BBBBBB98BBBBBB98BBBBBB98BBBBBB98BB %BBBB98BBB4C2C9FD26FF5252525352525253527DFD0CFFA87D7DFD23FFA0 %BB92BB92BB92BB92BB92BB92BB92BB92BB92BB92BB92BB92BB92BB92BA99 %CAFD24FF7D527D527D527D52537DFD0BFFA87D525352A8FD1FFFCABBBBBA %BBBBBBBABBBBBBBABBBBBBBABBBBBBBABBBBBBBABBBBBBBABBBBBBBABBBA %C9FD23FF5252527D5252527D52A8FD0AFFA852527D5252527DA8FD1BFFCA %C292BB98BB92BB98BB92BB98BB92BB98BB92BB92BB92BB98BB92BB98BB92 %BB98BB92BB92C2CAFD21FF7D527D527D527D5253A8FD0AFF7D527D527D52 %7D52537DFD19FFC2BBB4BB98BBBBBB98BBBBBB98BBBBBB98BBB4BB92BBB4 %BA92BBBBBB98BBBBBB98BBBBBB98BBB4BBCAFD20FF525352525253525252 %A8FD09FFA8525352525253FD05527DA8FD14FFC998BA92BB92BB92BB92BB %92BB92BB92BB92BA99C3C3CAA7C9A0BB92BB92BB92BB92BB92BB92BB92BB %92BBA8FD1FFF7D527D527D527D5259A8FD09FF7D7D527D527D527D527D52 %7D527DFD12FFC9C2B4BBBABBBBBBBABBBBBBBABBBBBBBABBB4C2C9FD08FF %C9BBBBBABBBBBBBABBBBBBBABBBBBBB4C2FD1FFF527D5252527D525252A8 %FD09FF7D527D5252527D5252527D527DA8FD10FFCF9ABA92BB98BB92BB98 %BB92BB98BB92BB92BA98C9FD0BFFCF99BB92BB98BB92BB98BB92BB98BB92 %C3CAFD1DFF7D527D527D527D52527DFD09FF527D527D527D527D527D527D %FD11FFC398BBBABB98BBBBBB98BBBBBB98BBBBBB92BBC2FD0EFFC9B4BB98 %BBBBBB98BBBBBB98BBBBBB92BBBBC2C3CFFD19FF525252535252525352A8 %FD08FFA85952525253525252535252A8FD0FFFA1BB92BB92BB92BB92BB92 %BB92BB92BB92BB92C2A8FD0FFFA1BA92BB92BB92BB92BB92BB92BB92BB92 %BB92BA92C2C3FD17FF7D527D527D527D52527EFD09FF527D527D527D527D %52537DFD0EFFCABBBBBABBBABBBBBBBABBBBBBBABBBBBBBABBBBCAFD10FF %CFC2BABBBABBBBBBBABBBBBBBABBBBBBBABBBBBBBABBBABBBBC9FD15FF52 %52527D5252527D52A8FD08FFA87D5252527D5252525952FD0DFFA8C2B4BA %92BB98BB92BB98BB92BB98BB92BB92BBA0FD11FFCABB92BB98BB92BB98BB %92BB98BB92BB98BB92BB98BB92BB98BB92BBC3FD13FF7D527D527D527D52 %53A8FD09FF527D527D527D527D527DFD0CFFA87D75BBBABB98BBBBBB98BB %BBBB98BBBBBB92C3CFFD11FFC2BBBABB98BBBBBB98BBBBBB98BBBBBB98BB %BBBB98BBBBBB98BBBBBB92BBBBCAFD11FF525352525253525252A8FD08FF %A85252535252525352527DFD0BFF7D525253527698BA92BB92BB92BB92BB %92BA99CAFD11FFC999BA92BB92BB92BB92BB92BB92BB92BB92BB92BB92BB %92BB92BB92BB92BB92BB92C2CAFD0FFF7D527D527D527D5259A8FD09FF52 %7D527D527D527D52A8FD0AFFA87D527D527D537D99BBBABBBABBBBBB92C1 %C9FD11FFCAC2B4BBBABBBBBBBABBBBBBBABBBBBBBABBBBBBBABBBBBBBABB %BBBBBABBBBBBBABBBBBB92C2CAFD0EFF527D5252527D525252A8FD08FFA8 %53527D5252527D52527DFD0AFF7D527D5252527D52535299B4BB92BA98C3 %CAFD11FFC2BA92BB98BB92BB98BB92BB98BB92BB92BA92BB92BB92BA92BB %92BB98BB92BB98BB92BB98BB92BBCAFD0DFF7D527D527D527D52527DFD09 %FF527D527D527D527D52A8FD09FFA8527D527D527D527D5259527C99BBC2 %FD12FFC998BBBABB98BBBBBB98BBBBBB98BBBBBB92BBBBC9C9CFCACAC2C1 %B4BB98BBBBBB98BBBBBB98BBBBBB92BBCAFD0CFF525252535252525352A8 %FD08FFA85952525253FD04527DFD09FF59FD0452535252525352522E7DA8 %FD11FFA1BB92BB92BB92BB92BB92BB92BB92BB92BB92C2A7FD07FFCAC998 %BA92BB92BB92BB92BB92BB92BB92C1FD0CFF7D527D527D527D52527EFD09 %FF527D527D527D527D52A8FD09FF7D527D527D527D527D527D527DFD11FF %CFBBBBBABBBABBBBBBBABBBBBBBABBBBBBBABBBBCAFD0BFFCFFD04BBBABB %BBBBBABBBBBBBABBB4C9FD0BFF5252527D5252527D52A8FD08FFA87D5252 %527DFD04527DFD09FF52595252527D5252527D527DFD10FFCAC292BA92BB %98BB92BB98BB92BB98BB92BB92BBA0FD0EFFC992BB98BB92BB98BB92BB98 %BB92BB99FD0BFF7D527D527D527D5253A8FD09FF527D527D527D527D52A8 %FD08FFA87D527D527D527D527D527DFD10FFC3BB92BBBBBB98BBBBBB98BB %BBBB98BBBBBB92C2CAFD0FFFC3BB98BBBBBB98BBBBBB98BBBBBB92C2FD0B %FF525352525253525252A8FD08FFA85252535252525352527DFD09FF5252 %52535252525352527DFD0EFFCA99BA92BB92BB92BB92BB92BB92BB92BB92 %BA99CAFD10FFA8BB92BB92BB92BB92BB92BB92BB92BA99FD0BFF7D527D52 %7D527D5259A8FD09FF527D527D527D527D52A8FD09FF7D527D527D527D52 %7D52FD0DFFCFC292BBBBBBBABBBBBBBABBBBBBBABBBBBB92BBC9FD11FFCA %C1BABBBABBBBBBBABBBBBBBABBBBBB92C9FD0BFF527D5252527D525252A8 %FD08FFA853527D5252527D52527DFD09FF5252527D5252527D527DFD0EFF %C2BB92BB98BB92BB98BB92BB98BB92BA92C3CAFD11FFC2BB92BB98BB92BB %98BB92BB98BB92BB92BBCAFD0BFF7D527D527D527D52527DFD09FF527D52 %7D527D527D52A8FD08FFA87D527D527D527D52537EFD10FFC398BBBABB98 %BBBBBB98BBBABBBCFD12FFC998BBBABB98BBBBBB98BBBBBB98BBBBBB92BB %CAFD0CFF525252535252525352A8FD08FFA85952525253FD04527DFD09FF %FD055253525252A8FD11FFCA99BA92BB92BB92BA92BBC9FD11FFA1BB92BB %92BB92BB92BB92BB92BB92BB92BB92BBA8FD0DFF7D527D527D527D52527E %FD09FF527D527D527D527D52A8FD08FFA87D527D527D527D5259A8FD13FF %C9C292FD04BBC9FD11FFCFBCBBBABBBABBBBBBBABBBBBBBABBBBBBBABBBB %CAFD0FFF5252527D5252527D52A8FD08FFA87D5252527DFD04527DFD09FF %52595252527D525252A8FD15FFC992BBC2FD11FFCAC392BA92BB98BB92BB %98BB92BB98BB92BB92BBA0FD11FF7D527D527D527D5253A8FD09FF527D52 %7D527D527D52A8FD08FFA87D527D527D527D52527DFD17FFCAFD11FFC3BB %92BBBBBB98BBBBBB98BBBBBB98BBBBBB92C2CAFD12FF7DFD045253525252 %A8FD08FFA85252535252525352527DFD09FF525252535252525352A8FD27 %FFCA99BA92BB92BB92BB92BB92BB92BB92BB92BA99CAFD14FFA8527D527D %527D5259A8FD09FF527D527D527D527D52A8FD09FF7D527D527D527D5252 %7EFD25FFCAC2B4BBBBBBBABBBBBBBABBBBBBBABBBBBBB4BBC3FD16FFA853 %5252527D525252A8FD08FFA853527D5252527D52527DFD09FF5252527D52 %52527D52A8FD24FFA0BB92BB92BB98BB92BB98BB92BB98BB92BB92C2CAFD %18FF527D527D527D52527DFD09FF527D527D527D527D52A8FD08FFA87D52 %7D527D527D5253A8FD22FFCABBBA92BBBBBB98BBBBBB98BBBBBB98BBBABB %BBCFFD1AFF7D525352525253527DA8FD07FFA85952525253FD04527DFD09 %FFFD055253525252A8FD20FFA8BB92BB92BB92BB92BB92BB92BB92BB92BB %92BBC9FD1CFFA87D527D527D527D52FD09FF527D527D527D527D52A8FD08 %FFA87D527D527D527D5259A8FD1FFFA8A8A1C2BABBBABBBBBBBABBBBBBBA %FD04BBC9FD1FFF52535252527D52527DFD07FFA87D5252527DFD04527DFD %09FF52595252527D525252A8FD1EFFA8A87DA87DA199BA92BB98BB92BB98 %BB92BBC2FD21FF7E527D527D527D5252A8FD07FF527D527D527D527D52A8 %FD08FFA87D527D527D527D52527DFD1DFFA8A87DA87EA87EA8A0BBB4BBBB %BB98BBB4C2CAFD22FFA8525253525252535252A8FD05FFA8525253525252 %5352527DFD09FF525252535252525352A8FD08FFA8A8A8FD11FFA8A87DA8 %7DA87DA87DA87DA092BB92BA99C9FD25FF7D7D527D527D527D527DA8FD04 %FFA8527D527D527D527D52A8FD09FF7D527D527D527D52527EFD09FF7EA8 %7EFD11FF7DA87DA884A87DA884A884A799BBC2FD27FFA852595252527DFD %04527DA8A8A85252527D5252527D52527DFD09FF5252527D5252527D52A8 %FD08FFA8A87DA87DA8A8FD0DFF7DA87DA87DA87DA87DA87DA87DA8CAFD29 %FF7E527D527D527D527D5259527D527D527D527D527D527D52A8FD08FFA8 %7D527D527D527D5253A8FD09FF7DA87EA87DA8A8FD0CFFA87DA87EA87DA8 %7EA87DA87DA8FD2BFFA853525352525253525252535252525352525253FD %04527DFD09FFFD055253525252A8FD08FFA8A87DA87DA87DA87DA8A8FD09 %FF7DA87DA87DA87DA87DA87DA8FD2DFFA87D527D527D527D527D527D527D %527D527D527D527D52A8FD08FFA87D527D527D527D5259A8FD09FF7DA884 %A87DA884A87DFD0AFFA87DA884A87DA884A87DA8FD2FFF7DFD04527D5252 %527D5252527D5252527DFD04527DFD09FF52595252527D525252A8FD08FF %A8A87DA87DA87DA87D84A8FD09FF7DA87DA87DA87DA87D84A8FD30FF7D53 %527D527D527D527D527D527D527D527D527D527DFD08FFA87D527D527D52 %7D52527DFD09FF7EA87DA87EA87DA87DFD09FFA8A87DA87DA87EA87DA8A8 %FD32FFFD055253525252535252525352525253525252A8FD08FF52525253 %5252525352A8FD08FFA8A87DA87DA87DA87DA8A8FD09FF7DA87DA87DA87D %A87DA8FD33FF7D52527D527D527D527D527D527D527D527D527D7DFD08FF %7D527D527D527D52527EFD09FF7EA87DA884A87DA87DFD09FFA8A87EA87D %A884A87DA8A8FD34FF7D52527D5252527D5252527D5252527DFD0452A8FD %07FF5252527D5252527D52A8FD08FFA8A87DA87DA87DA87DA8A8FD09FF7D %A87DA87DA87DA87DFD36FFA859527D527D527D527D527D527D527D527D52 %7DA8FD05FFA87D527D527D527D5253A8FD0BFF7DA87DA87EA87DFD0AFFA8 %7DA87EA87DA87EA8A8FD0DFFFD05A8A9A8FD22FFA87DFD05525352525253 %5252525352525259A8FD04FF7D525352525253525252A8FD0CFFA87E7DA8 %7D7EA8FD09FF7DA87DA87DA87DA87DA9FD0CFF7DA87D847DA87D847DA8A8 %FD21FFA85953527D527D527D527D527D527D527D52597DFFFFA8527D527D %527D527D5259A8FD0DFFA8A87DA87DFD0AFFA87DA884A87DA884A8A8FD0B %FF7DA884A87DA884A87DA87DA8A8FD22FFA87DFD0552595252527D525252 %7D5252527D5252527D5252527D525252A8FD10FF7D7DA8FD09FF7DA87DA8 %7DA87DA87DFD0BFF7E847DA87DA87DA87DA87DA87D7E7DFD24FFFD05A87D %527D527D527D527D527D527D527D527D527D527D52527DFD11FFA8FD09FF %A8A87DA87DA87EA87DA8A8FD09FFA8A87EA87DA87EA87DA87EA87DA87EA8 %7DA8A8FD26FF84FD0452535252525352525253525252535252525352A8FD %1CFF7DA87DA87DA87DA87DFD0AFFA87DA87DA87DA87DA87DA87DA87DA87D %A87DA8A8FD26FF7D52527D527D527D527D527D527D527D527D527D5259A8 %FD1BFFA8A87EA87DA884A87DA8A8FD09FFA8A884A87DA884A87DA884A87D %A884A87DA87EA87DFD26FF7D52527D5252527D5252527D5252527D525252 %5952A8FD1CFF7DA87DA87DA87DA87DFD0AFFA87DA87DA87DA87DA87DA87D %A87DA87DA87DA87DA87DA8A8FD24FF7D52527D527D527D527D527D527D52 %7D527D527DFD1DFFA87DA87EA87DA87EA8A8FD09FF7EA87DA87EA87DA87E %A87DA87EA87DA87EA87DA87EA87DA8A8FD24FF7D52525352525253525252 %5352525253525253FD1DFF7DA87DA87DA87DA87DA9FD08FFA8A87DA87DA8 %7DA87DA87DA87DA87DA87DA87DA87DA87DA87DA87DA8A8FD22FF7D7D527D %527D527D527D527D527D527D52A8FD0AFFA8FD12FFA87DA884A87DA884A8 %A8FD09FF7EA87DA884A87DA884A87DA884A87DA884A87DA884A87DA884A8 %7DA8A8FD22FF7D535252527D5252527D5252527D5253A8FD09FFA8847EFD %11FF7DA87DA87DA87DA87DFD09FFA8A87DA87DA87DA87DA87DA87DA87DA8 %7DA87DA87DA87DA87DA87DA87DA87DFD22FFA87D5253527D527D527D527D %5252A8FD0BFF84A87DAFFD0EFFA8A87DA87DA87EA87DA8A8FD09FF7DA87E %A87DA87EA87DA8A8FFA8A87DA87DA87EA87DA87EA87DA87EA87DA87DA8A8 %FD21FFA8525252535252525352527DFD0CFFA87DA87DA8A8FD0DFF7DA87D %A87DA87DA87DFD09FFA8A87DA87DA87DA87D847DFFFFFFA8A87D7E7DA87D %A87DA87DA87DA87DA87DA87DA8FD23FFA87D52595259527D7DFD0DFFA8A8 %7DA87DA8A8FD0BFFA8A87EA87DA884A87DA8A8FD09FF84A884A87DA884A8 %7DFD07FFA8A87DA87DA884A87DA884A87DA884A87DFD26FFA8A87DA8A8FD %0EFFA87DA87DA87D847DA8FD0AFF7DA87DA87DA87DA87DFD0AFFA87DA87D %A87DA87D84A8FD07FFA8A87DA87DA87DA87DA87DA87DA87DA8FD39FFA8A8 %7DA87DA87EA87DFD0AFFA87DA87EA87DA87EA8A8FD09FFA8A87DA87EA87D %A87DFD0BFFA8A87DA87EA87DA87EA87DA87EFD3AFF7DA87DA87DA87D7EA8 %FD09FF7DA87DA87DA87DA87DA9FD0AFF7DA87DA87DA87DA8A8FD0BFFA8A8 %7DA87DA87DA87DA87DA8FD3AFFA87DA87DA884A87DA8FD09FFA87DA884A8 %7DA884A8A8FD0AFFA87DA884A87DA87DA8FD0DFFA87DA87DA884A87DA884 %FD3AFFA8A87DA87DA87DA87DFD09FF7DA87DA87DA87DA87DFD0BFFA8847D %A87DA87DA87DFD0FFF7E847DA87DA87DA8FD3BFF7DA87EA87DA87EA8A8FD %07FFA8A87DA87DA87EA87DA8A8FD0BFF7DA87DA87EA87DA8A8FD0FFFA8A8 %7DA87EA87DFD3BFFA87DA87DA87DA87D7EA8FD07FF7DA87DA87DA87DA87D %FD0CFFA87DA87DA87DA87DA8A8FD10FFA87DA87DA8FD3BFFA8A87EA87DA8 %84A87DA8FD06FFA8A884A87DA884A87DA8A8FD0BFFA8A87DA884A87DA87D %A8A9FD11FFA8A87DFD3CFF7DA87DA87DA87DA87DA8A8FD04FFA87DA87DA8 %7DA87DA87DFD0DFF7E847DA87DA87DA87DA8A8FD11FFA8A8FD3DFF7DA87E %A87DA87EA87DA8A8FFA8FF7DA87DA87EA87DA87EA8A8FD0DFF7DA87DA87E %A87DA87DA8A8FD4FFFA87DA87DA87DA87DA87DA87DA87DA87DA87DA87DA8 %7DA87DA9FD0DFFA87DA87DA87DA87DA87D7E7DA8FD4EFFA87DA87DA884A8 %7DA884A87DA884A87DA884A87DA884A8A8FD0EFFA87DA884A87DA884A87D %A87DA8A8FD4CFFA8A87DA87DA87DA87DA87DA87DA87DA87DA87DA87DA87D %FD0FFFA8A87DA87DA87DA87DA87DA87D7E7DFD4CFFA8A87EA87DA87EA87D %A87EA87DA87EA87DA87EA87DA8A8FD0FFFA8A87DA87EA87DA87EA87DA87E %A87DA8FD4BFF7DA87DA87DA87DA87DA87DA87DA87DA87DA87DA87DFD11FF %A87D7DA87DA87DA87DA87DA87DA87DA8A8FD4AFFA8A87DA884A87DA884A8 %7DA884A87DA884A87DA8FD12FFA8A87EA87DA884A87DA884A87DA87EA8A8 %FD4AFFA87E7DA87DA87DA87DA87DA87DA87DA87D84A8FD13FFA8A87DA87D %A87DA87DA87DA87DA87D7E7DFD4AFFA8A87DA87EA87DA87EA87DA87EA87D %A87DFD15FFA8A87DA87DA87EA87DA87EA87DA87EA8A8FD4AFFA8A87DA87D %A87DA87DA87DA87DA87DA8FD16FFA8A87DA87DA87DA87DA87DA87DA87D7D %7EFD4BFFA87DA87DA884A87DA884A87DA8A8FD18FFA87DA884A87DA884A8 %7DA884A87DA8A8FD4CFF7E847DA87DA87DA87D7EA8FD1AFFA87DA87DA87D %A87DA87DA87DA87DA8FD4DFFA8A87DA87DA87DA8A8FD1DFFA8A87DA87DA8 %7EA87DA87EA87DA8FD4FFFA8FFA8FFA8FD1FFFA8A87DA87DA87DA87DA87D %A87DFD62FFA8FD13FF7DA884A87DA884A87DA8A8FD60FFA8847DA8A8FD11 %FF7DA87DA87DA87DA87DA8FD61FF7DA87DA8A8FD11FF7DA87EA87DA87EA8 %7DFD60FFA8A87DA87DA87DA8FD0FFFA87DA87DA87DA87D7E84FD60FF7EA8 %7DA884A87DA8FD0EFFA8A87EA87DA884A87DA8FD5FFFA8A87DA87DA87DA8 %7DA8A8FD0DFF7DA87DA87DA87DA87DFD60FF7DA87EA87DA87EA87DA87DA9 %FD0BFFA87DA87EA87DA87EA8A8FD5EFFA8A87DA87DA87DA87DA87DA87DA8 %A8FD09FFA87D7DA87DA87DA87DA8FD5FFF7DA884A87DA884A87DA884A87D %A8A8FD09FF7DA884A87DA884A8A8FD5EFFA8A87DA87DA87DA87DA87DA87D %A87DA87DA8A8FD05FFA8847DA87DA87DA87DA8FD5FFF7DA87DA87EA87DA8 %7EA87DA87EA87DA87DA8A8FFFFFFA8A87DA87DA87EA87DA884FD60FF7E7E %7DA87DA87DA87DA87DA87DA87DA87D7E7DA8A8A87DA87DA87DA87DA87DA8 %FD61FFA8A87DA87DA884A87DA884A87DA884A87DA87DA87DA884A87DA884 %A87DA884FD63FFA87D847DA87DA87DA87DA87DA87DA87DA87DA87DA87DA8 %7DA87DA87DA8FD65FFA8A87DA87EA87DA87EA87DA87EA87DA87EA87DA87E %A87DA87EA87DFD66FFA8A87DA87DA87DA87DA87DA87DA87DA87DA87DA87D %A87DA87DA8FD69FFA8A87DA884A87DA884A87DA884A87DA884A87DA884A8 %84FD6AFFA8A87DA87DA87DA87DA87DA87DA87DA87DA87DA87DA8FD6CFFA8 %7DA87EA87DA87EA87DA87EA87DA87EA87DA8A8FD6EFF7DA87DA87DA87DA8 %7DA87DA87DA87DA87DFD70FFA8A87DA884A87DA884A87DA884A87DA9FD72 %FFA87DA87DA87DA87DA87DA87DA8A8FD74FFA8A87DA87DA87DA87DA8FD77 %FFA8FFA8A87DA8A8A8FFFFFFFF %%EndData endstream endobj 47 0 obj <>stream +%AI12_CompressedDataxyu' ;i`2cEo0ʣԲ-c0hPRc6`yVY7\ 4Y~gW_wwMo^;Żw?#.? MO717~xsO'?˿y_~ojO?/~Yi77~?+ÏyÇM߽9ˆ4=~ؾq2o'z͏ݽû'|o7wz݇޽~oC;^ >7wk~[׿|u ^IaEn?-/Mv߽oxv* csw7w}Wfa MygO_$fZWC bOϽVoNdWb)S?O~ȤÇo<܆D+ݏx;\-oB^7MpǷ߾}a0M,}|MY)f_q3W-|ŧOwuzhw-?|E/>;,8"Mz[̿^5ݯ>}>_ݏI7tiywAw7_~zowqvKzi}֯~_^w|{߼*}kv49߲z=7Tzċ^}?ہ˵ ?aywWq_;~{7 7I{ } ˿ޏ߽{훭l$~+?}?G/["rW|?߿{_]}f^ǟ|WaHM_~wx_>-1n_C}oiWXWGL4h7C"kH~=CvcΞOɝ=Iow O×b2Fp8o//?~ߪ0J @eYjr%5ۺF|8N11tx-x:Χssy:392?Um}G/?{>vhhBT!gic9I|ML{LOKӔƔSJ14=f;<׭l-qfpṣ<Ӽ̇4~%/2/rXi4i?H{{a:̇p8ta F#~3yv:BՆoVʝ.|;iG=L3<Ι:a~]iO4nMyJS)Tx;iގa܏(86|mamlvVVz=UzwUgno)δ43u6ЁJt&:b{:lG:vtCtG: [:oc]^xo{oKfoSFiIU Rb#D ñWt`CpޟX i?aOt~mGD*D!K !g?0 aĨiIoTpÉ-m!C +9b)a pp +pKdb1He sm~l`"\mfܹ% iUآm [۾|qۊT3>ofyyN43g|܇TGj왧{cܘA[Ж;ZMMX|y8|O 1 g!Jl%۲yK?i弔3aժmfgҕ?uM]rd&b^NѵeO ;+=vP CGەgWVM-U;6m7'"L4Ҷii(G{38Dfg y8vtDt>\^蘡! O/H N]jq]/9%h=sI0cMhH`J7я!L)WP=C_azWsdx3D "R +oR? / 1ӵ<ߐV{q+{('iç>/qs\>O26K!>QZ>=1X0ʕ=O2H)l7_cE/?Կ{7~ILF~OHi;zWtP,#dJ!Ap!-|l?kS,쬛unvMY/n.O7PH+ٻHiތy)Sq>f7<=cs}V/:i9W@/f A5[QN'@Sس}tcQ Bs{V%L@XR") (_:fJ<P8rPcvȎn¯3i"kGzLvM!4uO'TG`@S>t4Dϑ=@s a@,YYDi"B #i!t0pg~Y}AXuL z";K=K܁od\>M7(CYM^\YZ65hoQsRb_ҢjZżVW녻\% UK6UM8rH3%FCكJG AF,$AL%2|`  ( 4"bHqf D(*`Q +T,Gf zby{@ak m;g5Y<LpbKH$mh192P (İIC 㤉:^;C +8494d[7_*b}LB+l;2} +X 8g nb.2/ c6Ik~G#_ f#F?>ڻ S^ \G6pyˌ[Ŵ%ۣ獡Xay?l-0nɒc1w Է*f]EFt&C^j_:u ?WH-ݥV- Xf-mܴjz5tCpjZ$Ԍس;_mn-+}jc,5Zav+f0?Geծ_̿͠xfoUՂ%Vb(„Yw 5U:{hae.&2l8b]WܻhQU>vWlܿ+0wj ']EYy{z{ݪq얩I>ꊐPZ8o"ն-;9R,1V͗kͩKlWR ^p .pv}c6k[ڡiǪ[:R6򶨚w3[w8򳃓#όکLJ}P>d3$c.86#fvWZ\/uNGb6sj^fsmiX(+mܪ穜נwqY>tFA=Ǭf [5Po Le|~ytJ29=-Kuj̆2Jz^eN1Dܕ3ma|&\٨mz &.\> JTq)>I "OqV+j+oqXZrk̈́wXǤ{j 1OMD Ah,Boi +-D"F`3ρћ39P+TXx̓2sjf.0v`%\PRQ*yú]4Ɗi׶ >i8^T&m`(2v0( 9(LݑjȧG#ҩ*j\4jipqe HZ.N d:H|Ҙ9-N?*l^^~W[Z߯~*YP֎^$E!"h>{өiD،j;KטCX5nG_Ա{ +^v0Ε Sթ2Nj}?ؗض%OmMۍ]nEll&/iKh$uPvv)젒VZ`VWQ+Fp$ΕS >U]?WşS >EԥԈ;37c#Dmui}uvjZ_5-l*40J{1͗ם)fq;ea|ϻ9;`c~b\lS8O^xߑ;݂g?!`I4HGfFI_ٴ7yjas -*~Im*fÜe"Ζ1[~x\0M&J81VYdkp :(s9rʩD;qHH8&Y{}f4ӌpf`VX f о ؝m728@[c>*K?BaJ R9}DѝFw69C{8sw Z +TȾ|aAP),B P uT 8y6ܺmsǹōt[n+[߅®^tʩ"+2A3\j~ %'uXYξ,DFwш١u/s2!uL1LU1v DfΣAyVf`"^,XqvX|jOy X<9uS[9h&Z''<͟l˧=gU̝W{gk4.fZ,^P +uE.dRjhmQU  u,OoSZStX,S[gqYI5$$~7qCO2; =<~褚Ѹ.%hwL*f}iƖy2ļļļļļļļļļļļļļ<_bb^bbSݽr MF +{aIw}(}a[QmNjP}4s͢)d3]Ҭ~a`S<#u<~{f`?;8f&Tl 6uz_0aYT"y*8`/lR#c^"MXxi{dwrK0*ykWf S뱊UaY Vt%_M*\GIUKEkqU8v*ylyTxSv{&YwQ3!M+'J5ह2W2ݥ_!ӷ5_ Ԅƭ- hh k˜aQ@;k8Z'k 46ߚukMxM 6 bU5uXMA64뒍`Ln$ȫ[֩imqYhSV)"0 JY(m* ;IMIcFxIč!MxǶKM#G^iZI==ko6 GNyo7\;ATnUr|,LX@u'dd>bauICͭRF:yRw^ծdu4 +{hiŊT8@COSyMDzCWBU-u+T iTkm8e< +/AMђsf=bȉDP[?Hmj[gx+z= $@4fipɚ W2isdD%m ݊{K,;%cN5L%â})W%~E' ÝYb9lXAXUg4 < (8AhugNp*IY2(>1O)pKړSfRXΜhcW681hEgOǶLDӡ#Cʨ6u\`߬<=wl%AKE/ ^$(zIP%AKE/ ^$(zʟ$(zIP%AKE/ ^$(zIP7To4[e(JQ7=X7VS箱*bfϝXYظWAƓYYI]_:gZj<6QZbx Fj^k Ԡx_X42>Mi#RhR)<雨3A1Ufz[$Hdc1N-mqVkTKU g)l.yoOH]=o„\|$1s!, C {T 4m +YSNhKfY0Кqv,ym*kkz2x[=sytmAW$xiKR$ǁQ}n4$ gp +p$k]Rٞ^pLuV`yX'*@n(BA?U0l>J _})5c Ck8WQl˥ZId&* +s\i 3ZkpsKZoÅdy=ƭQ+mWQkUW+hx]{q4{iy@sB_B;9 ,>+PB4‹l JkchEtk׽a;ָ]a^nWV]ۭ3' iu߬k*kW@+z*?WH:1n8ϙk iOo3ٺds@'ssߋ:[YuVYx8nӴͰeJu ݆X]*]5>Zg2kX%*a53kQ;ƱU{U;.VUڡb蘏+kuٵB%]\y|v.dI&%-\K=( +;SX&]?qOk7gS(;,E F1Q5S+]ccNi+vAg闌ho]_EV(\ :Ա9f>JҶβʣ5*'EFdu%l.S)쯺솵&XpawEl!!#1ZZZe6{UY^WYG,E] ^{c\w{n:|xc#'y3xšLz'6rcl:cJ:4j X.{ 6!C8$a%酬VKp>v~X*ҙ6ѷ?UnS꠹uڹn:Yesc-^iZW~v񧻼?HS ϒ/rf%&YV +z]u#N3KG0vzM^y&y/ hGFĝXȝªX6֡eM5%K^Rjv -s^c]9Q2YEQ}KOKҊ~vDtz#zn-zKMUAעn3Ukѓۇ12D۟FJ;tMhV6.^TNzU;]ŗk/mݗ?_Tu:Om3%ne|uKX݆+QV|NCUɷV|[E=8 bohQƣz^< +z\.k|l.~tW3́Jg\wC(U|\MQЭt5ƍ!PA-e5v 6bYqWA3!zYVz:aY 4.5*+ylV|nVE]d_Tm;m+%8$iݕ$(/m] Z{N:,~m@G?r~)$Z`=6 ᇎЕ!"' +a/3f8d8<}GD0Ý6_O* +qӢE"4EM4<: 6?ReRVs4^Z"@H}8~V@%B$L]+yJͼRz:y,@ +1hPI><<˶ .08k}y/iьk$t&\t'1iG8$/n0SǍOw;{d7^X>@l1E@Xkۖ=m垒X6]6jb]ݶ P;\x^U4hE9=ozjBt i97]<_V0[/º:=+۩-nUWzXWh|UΗyxu}&Oq>SE]k +u*WrKu6k~_ЯklJ:t-e%*/jmuiUl끵,'Z1 ;nbLg>V?ׯV^Ẏm2ӓruW-vYI}$X2Tm"2Xm9kFf l֌2lþXdb(;XF0H]Kć6q[Mp1ϯraY+vu.'kMh=O>Ng Mǥ=m-Zk}~^YVJJ=~ -3\fSLjvs"e5:D +i9c) 2HEd! y+\+Ss UqtW߾^U]oW?}޾T>i7&Դ./fX|CX;GqO~_tw}#`}GW/޴ 6/6Ͽ~ͧ޿Çw>|@Z/׿y_߽7_Kh2 $ +l(q)½!vUHL@DZ(9 #'t7L~Bt3;s2'bc(CeoJ -BS`rlua}F15 }<ѕ|Dm(Z؜S@_5bx>֑Pq$:4Z:AP4~>Ow8 L#$'&jؑ3:w@盤 +[UDD^GMD2н2Sh!";dE<أHfz)ou]#~Rem@O ˅viLCSDJyBI"s?ϐljM!Nȋf & }%/0yDԅg]N+e { /@#Lo t\%=1>~_dH#Qqjj~ÿ9Pfk`uf:ݞ:2.ܣS=mB[D|fkLEFle[.Sd˪qi=Y]gP:Q $Bj~iSk~-{gb/Щ씓x# jLE*21Ȯd)䱡K6Sr0'N z'٩!+o3J)wR 0,g,pC_N_Fe'aj2YHDqۧaJXǙvqLYVֆ-܏LZ +#tv !_٭_4 as3X1zcg%C54;|E𝁴F`9Ww!m4qq "F02)+cU0,AncaL0 ӘZ3YkMUWəăn4z8mżj&#Eb08e:C/] ?qq=wcJ'"j='pK0Ch45j0H++4ud\bj Ĭe J1Ft03C&2B?_ \"zN8uͨDr9`@hKk8"`Gfӓ >uCàr2:CqZP=CO򅠨)K}%MĔ$PG`Lm%͉7zO\黽H6oA#Wf;'ve*d?SwjF@|y6tp%b437lzI]./dD6,;aȖoÁiěu,6~ږwm(r{@=臝$1b=i4s='3t>C\b/ G*ȫf * h:YgLj@ F%9=&Coƶ`N,+zbl&8$K9/aPsym9?h s?ca v/pn9/yvʪҢC5ދ=Ǣ}*saGh.x+&`a1AtHx {կ7bj%" ޤ.Zqldf+k&lϠ P&[LYcE* =XɎ]0w9' ӆ-E\+R- kX&Dy;x+(.DWaҺs)̕0Rf8i bR=.̅\'cMG UF +|hܸBֵ}h$C: pEIFQLLE%Pפ0Ա7UC̓k: չV8zTSe }eF ^t4HM5ebi:k0I˕\60h$EpUs~w #%J"H p\Y]E sq+ؒjq"Ф3vF t}ʕ媏͠2~ChV0M<>_5jpMI<85TYnî|K8ĵ:s7#jfu7csk|~xas$V[G=@1Xá5)Q'U9P:Gi"k4ކ:$$Qc%-7h'QSp yDZ8(ܽbα ]w|w&`3Rgn=p]L\5a./M+FTLuU%7ƸP6FxrNϬ?.+Q-%Ʉ:74F>tˑnrY `DV2\ݐ­r.+bn|Bݞnv4} 2,A]Iqci̸It7ZJyrXnu5McWܨlf]t[wIub67k5xḳ`c*5HLEz)<8 KVkunA`2HC Dx g_Y0M\&a1mL,-CSc7 Rc$.RJO7,7 a}`Ae* ,*SVJej |7|WF|1 *mpإ^ו>+{CJ_{pThF|2+ Q^ ~ E}glr  L.٧6.ƋO|N 3̋ګIT_]ʿ!fA]5Yǯޘ.W 1N{}Kߴc0gb=gc/}f !5$NǩLG(vd/# +G_Wcȏ;\b'7MIGʨKyeM>Q_`Gqeb lAE ; 9(wI,Էi!>Yf-$O~VBV{t`+V-Yh-\.hmp1Yg9|{ sTC/axMOAzhp#$:O >(̬A x%*pvypP\^#: 1lB^ ` YsKcG܋r EyWBӾq`lGJ\l$u/tͼAvuϳ#! Zf{|3@Gl_ v!mpNz H뻼nhH yQ ya1aOU2`MI]Md2M+ l'u r~ea0\`7>촲%hv%,yNׂȺa +m"5%rҍe~lL~lvo+֦jr,Df[Bp t!^(]SmKzo6 V%(`RCW%jD7*!"?F̡C g[81JHlۤzU7U&5xpd6h.Nd!Er5P;3Ũ 6r%v n #jiL>Ǩl臄'3Yp&q`"1p +A'Na8OF2Gq` &G#H8"?8Ѵ||Ҡ%8^l6Xc`[8E~_nϰƼ^P#΍\ffY웯w,=0r-4OAdvOOgxE,&b/y?@>?$mGi4ugC9q9I9Y3~K˵vOr`,pdE~bo8pbb)~9)C$1!^]ѧ<8,z!Y0,w  ^|iJM%kZ{W ꕽj:0]a3B 2|f_-,ڃL_=pe O>bwGZ¶+itD&`LA2b}0VH]-r]l}ʬjYهaTV+o?'" ^MQӾӶXm2~ۭws'rl >]6a⇯}Ow߀,5dhqr@`ydcl1H +@W R#=v:$,Aӡ]D!eֵ J 0̆Kr i 4@OM@4; -ύ#Xf 1]y,O]yuu[{ʣ%\GI/C)pQ6x%Y!Sj=P^ͯhk }tXHWГ4N`pΓX,_O0NUf8I p[SӒ^Ri;DԩyE ,5^ȊBj\ly.oypVMjhevxj9p!5y¦\RAm-5 ~<&5':ySO<<Y-5f,ѧЛ~f9Y%恳MbxK3%#*1@ +ub0Y< {!7y~8y^tr)mT52i+S\1Y0hsdLs2^eB c&C82^V#|zhPd2ܖXl##a9E4d#xR_ /vo6PT!83k \/FWzj +#\|π<"W;]Zt$Hb d_:x>\/isuUF&1WMNJfL~K[Hdq F_G{] +%^5:i&1ҁ2=UPHVM wŗ1[xXFY[f!Z | 5"fCtAǴ@@r!.ꋙ&fh!(KQä +J4M' >fΐĽ^膏0ÙHiK3xX4dO[Ȝڨj'| bɒgC +M7:gG^PcPv}3'TQ.H]p`72{lV·26ۿfX *fZ'Z/ MJ ؒ$ $X2^:+|| +` )u0c`x3I8I*|X.D fptLe%kI'pj`i) 1R';Vˁ9BJ @ N3Lmy7١JAZflL: +-IfciD%Ь$ZP}թM'8F0d* +XVMǂ +-yمbQKS|kayqԒ Uhr|5EB e mB/u!*Kp= 6AvGB̄Pqx8F=]ayS>w]j lҬ=ő\->_l1 qQUƹt%eYBA |2vrМeIUގ9TGS۔XU-o$)P o0QE 31k3|dx,n' ^#I#v2os-|4x09©4@9JI{#!b^'Yfl5a[ShNLtb*p.A5!}I17@^=YpJhui27bF Ӆ@=_I+ ^@8%zPwWd[cmz&oG; %8RLC#-y0&`SnԣqzT7J#<ԈHItscV^YTѴ&E]B>X[4؃vN7F=ɽ PE;c/l_vnq,^-ѣz䵳&B۹qu2lTQU7񠺠BD81J^Z?FBRnﲔ廴*5&yZ\HuVdՈns-f.7Z-^p7љFw{ nt EW2z[*u홦Ԙӵ7VN]}rkXnm07ֺ\Sۨ}6S|-mѮ{Ů]\F\A01 -DG͡ہv8NS22ZW)V1x`h;,U]DCN4XB.Y|X4g%ҏA$:2: 7e )U?eR &7ק| *+mե^~% uH { Дpc$+# GNA3Z*{CM[,Eye$ [|i+ؤ)5L}$?bsy& +UFr2πqD-;Mbdu>zjo^6F%* 5$4PfRt=GoO!>%(GX&Bώe/kh(^(J`J`-CKM6w),詬5:Sn թT~VBV*X%NvQP@Yy@X_$%<榉Lpa̿ QYensX.<)4-]h9.os@CL/L2*`%aŶ$ZUI_)} R}'~Sd\gFL@ iyM"85y3x W ʬ"!j|4p,kN/?\z*Ʌ];D rywd F D$e` ޒ2$ŦҨIӭqXZ@mi`ʖL1ee|Y߅7kƷd޻ѼJϙNcu~h}`D9h& O_9 +:iv'.(抬$5#%{K +$4M$0+L$J)zb$JafNc^cFTeamvd C40])Ur>&Uh4DU ȩ2X $WFe6AK$rp>KTR. g{.9Җ4}AR֩,eBU(X_(sail nZ|(o! +Yu>/<;u|}6i[gwϘff +sf>9LIyMMw% *GUOwEl&R[ +,.X,,j~]QKzqh?"-J>q&VwSU]e]AzT0j{b +r_wHWBK+9o'#5,f3^r|dƅ#$`]C!ٙVE![4 S؃)9 G@$%b59Ұ+9p$Ufr(z/G4jD1dJLI-[աժ*DZs]qq"CM?L*y!jZ55̥fODZmtH9{vZOZL(FJVo(,QXf*Ъyo{'[ hOB+/fB- */EͩUh +.Vʼn4NbT=E}'*6םQxeJZ_*bZG{PKUav dUU_&>AJc"^>R)1g+7GT,[.ŏk25Z2FQJFJfb^ṡv^ کvYJ֋O;!NuCԽܵ +g;o?`//<΋7Ћ;BVx~0qi]\~jKw72_wYJo\hWw+7W/YzʼZ}#yQ{KxkicؤJ\dU P K,t=pu3mddmMv}=*d|'ó +:&CW@C^ `9Nӱa~;\]8eRR:L$2'!h0&((4&V#9#iNC{$AeYѤ>Hrh& 6:?i ?s2cD;`2q\Ye ec kƠ5&8tf ++oPPS1+(e-]$ĔręM4]@G#_c8/]KXBԆʇdnN:$@\\ +$ń1YDУ .&؏LMH+B ~chBqJ¿ δ%ϔ ]Ƞ$Wq\CzIY i$Ey\TPF +IU7LL%I0x(j mj5<:!n%,Xҏde)8I)U &L&x194%|L(d(hUq_LY,0%ba~ijc/~(dž >Dƕ픃l2Q4:'mLOb_g !0-Ś)$PRzQ?25p"D+ a8 ڈˡ"ɞ +}x_JrfODW23(MaQ͔*`/^:^$9M./ebeojOBڈnIu9I/rZv]Mqpθ7&jFFr㴫Zn6m̭܍pW` +Eܧ[]tK~5`Jn<\iA01VfVGztE}\:pKQ' nJZ Z0" x Q gMcE +oL,,C2d7PI җ.ϼif0N{ؒjPʴS^| Q-_Qʪ@v[W] R Nþ{'G H(8ƓK @3⦐EB> #h/zcx$:e7]jp6kYYqF NYUflCGOm~e[XڸM5|uB&-ɵ`%A ,:{AvB>|ko^vn% @r8|l;Oi5_M\x"7c['tBe`vW^'NPk..02S]YTQ,=}ߛøcN +hox" d?Z} 5XmR8nUv]3gQسhƼsD"F$B7o#kӃj30lpRagvZ9hz2xOP"P;YgV:ۀc?Q."/- +Ѧ9840., ^q0Sݕwl߈A6.8߰kS}"2׹BW }-V N֬#81-7B8,w8l b0sRqqzϞt.<\,Z)s92_yjDǨQ +!N=l%1+ڊ3Z:Ioc/&W9TzOT˶*|lItW}h^HVΙݎcTmU(@=Rjb+TN:q/DDw +=-A3/hM:c^))A(߿?b6>lY/{AٓV#9s' @L' %@ !s xoA]6z ( }Ϩ,݁Lh`_pHdT4 HR>c'gc\gSMc +9gI'qW(^=a)T4˹/}H<V$F>7[,Ilôr  $6`y#ٳ+PuLZ6rNԓ +/DQ%"g F~8vO*nۭ:&DqVDGQ|GʝC 6}RKeY\~ LN>J^P4,Wj:enbJl +>ZztMbb3ldM_@%٧VgttӨ3l4,,2XY˚_&H~ _̑ +14B(`;T(솳c3餏VLD=v)~2`eƱ[!,slyȒm)JOy7&+#XFoJ>}f%[*]Ki@ B"1]zx Bu{Dm V^:m-N6Xo>77ָNjn>Ku>;FaZ^t,<g\uΌq#ֈ_y>ȹ|suq9IY3}2ɟ9EC̀be? ~2Rѐ]HtHqRp>yR}eQE[sDN=?'hIZBJ{o׳;r> 03kǙqA HbACt2dY}x룪RKO&}"6<|bժq_O|ly??˾`7%ۨC]*~T,l83iu.EY۾Yb9j@"b!>aqQ5цi 9NŴsoi}8pܲô*' HN;lRm}ځS!vyQӮħS3YGjg$fnY4䩧{6C<_OIfrN%~~yohqȊ9of?7IZ,DC^z{IͪHQY݃J{Se_MX-ߪ5tTVD|Y +YҾr+Uu8T9w:ZDmW9ZFi+kʾ__-\KY@M +gJThg\]]VBDr&p,ɷtChĔ@mRB̘TWhϸc7ڎd + @p͗ܨk.jlb4}i_Zc#A DP'-2CMY[Ьd'?aA@BhP!_l=CCFqIڽU|6 ;Bھ$U@v?xkc*+R.4ۙK!hiM&C/N 3eAa1)`Ō$$2B M + {jNܛ + "'n%Eu  oM4O6/V2?m>5*O1+yF!e<#z<N"K]#׬|QYVX/`k;O$8EҼl8%v@֒$ !jIQMEUjLax*Vc jL\U"uq5!s5k1q)F-E^Xt6-ŬF5X&QK1ojdbگm-&} +Sk1Gحbi6K#8j,XK۬pZ!ga-L{> GZ+ukqQЄ{k1vZ*i>ŅJK+Y%(kc~3=RV3psb)|U|{Ow: (l۴ kWO~?`!aq/H1uX϶NgIJq1nĨ/Mc17-ͼ7 +b˚2/t˸#P}1VW#Ÿ"֮b1n~_Ř&6 cbD]׾_MK"d&\yOdz;+jV:K[2˱Q<1 q1|=nTF&c؉C7kZ H1cz΄l`C17R ӌ%X1ϟr+)Q9%IneTN3FTNb=.r*;rfNTu*!WQkP9˱_G199TN`$l"&ǧp1$tP"&+3&Ǘ/5H19SY\e_J<&P#(ǥѽjž|dd`z^I]mz|#0#2=p t GA 뿈w ~g߮gbcn +6 +j[}wi 2 +b^M[*zvC%!ZA~êLiwIrwZ<=mo Kd0Ry[eETRIeNyrJVT˕7',G]oń:U3\}/[ [1'No-@-))m^1ӗ7EMKM 9kIH^8Yt3Z:X,kʇ.dVuBCCNj=GTqc҄ rn,IG^\vNښ)D +;})5ޕe5 ~%U޼Dd_YX"?|@65푲PBދU?>/+.T-^ׂS }pg"!lP% Ӌ +ŧm@|iN}v9 \@l3m + +u%Ep(!P^}y-ADBU+Iq7D=$1ypٯ^m"-~7ǭ--R-}@shDtQFWWƔ%(会M'%PNzu׬*A@eXLIx^" eNЈ +XWxz;#;u%lƒ:n7͆m6FcGdVZ/X6i!-i'Cg̯5xvkM K܇U4&KTs1K(#TlrUUosĹ8YmZBE)w9u%R~ýZlfXr^4DN؄pY{=UeYWdQ;vRrʣrNp;/kgQA kY-)LfwދkkoPeA[n*|[]?ZgEⵋgz8?RY ~}{e2a*b;i1?'h\*a_I-հUiC}ٍ Qu)(SّQ23}2嫥cC )fm.Wn +I +wQ/kӭ$,7O^@V%-PP?p!:bOl+3_^{w4< +"3x[#zkb^J͝e?st3>oJjsB7r^:!5f /%ƪr}_ų!^ +MqUHvfaSty]>7nqYnl-Yؾʀ +q+ܢ<̺ +-=t{1nGַtd޷2ddPBFXX CV[zB3"`9#+8L~\TgEХgg>NA Q*5iĄ݈Q޴1mPUNcH?}gwu x}CnYHg7eєq(lRF_uٹޤPqShU?$@5~eW{r*wF_Z֯W8(>) ־w{ l@M^;w9G|m|m>[ ?Ƭz]߫`LWb&yX\{~7~q0|r0)oHoWQ0K"BN/j7}[yKgj|MqBז;>= ⵤV@o'+ +FD +8s~#JkPC|8 ՘DaG~㏳S>]\p;^`U_$>=rn[(YPZ!'f0XJ) q!pK`;|G~\lLkD] J'},JkT;-YyX|Iw),߶|+_ooލ|D0ל0礒('Y$<yy1{|ϱ?9N{DwpZ` MϏ"?B>e ye y-[ȳ-[ȳ-[ȧ~l!~l!ݲ<޿@>eyeye  Sϛug[vg+[vOoA>}S[vg[vg[vO-oB[ޢE---S[g[GA~kC^mubW#e]W]W Ⱥ*K^aiϐW[#cA5W[)ljTgemWCSؐW[OwNy5>[/hjt5>j?}G WDkȃjK}5N}ue뫭Oؙ{Aڽ+\JAΫM5E֨ -[= +>sM`o ~J=.fC`S +g/y?OWX?y6j SNe|6,'$ϫF[A'EKLŌ%bFJiFJBb*'$(%b: +StS1TNG)15MG)1QkLQטkL|5kL|5b"S|Ub>*S1uq>2S1ucϜ,ǮhT"S5{G>L4A1EjaFզiM2_?C^ +FF&#'m:ߵuBg ^)NwiP:?K~ .*NwiJ!*NwiPb^=I~J~j*23=4?$Ӣ4U?ֽ)}|½w{=|jL:>cta?Cr&;455bjhES$l99>-_z:JX*]]&+IQ7,𵧟,๵k{ BzWvb4le. ʢqv=IOnmvIߪyFxPyet^Y_ꂲF_2lEv @١ .?p=g4Sey94VO[i i}ce yth][>!,iz=!~ątUI RwMj/㹤Vd]M`%^0R%u* 7i' b쳬ϽՉ,EZ*jY_lx4 X VIKşl=&d^j&bBaQ5{qj%R^ $.>[bVͫ US {ر^ޏuODNITSb;3%niDMJq_nl2XllrF5p;V#(YTa{(=jsְ$4v\3{ֹ|]&ġ+iPWc%\ҝ+O(+/k9H _^4?䀝$wf=gh ՜Z DN0m,pwH6rMR&~ZmCYn4&|޼^4T^Eq'f*HHu1?X;_ +HR|V# YŴ`D,`*FHYNF~yٍՙ_g³܎jyMwYۉuXf@,(l;L~WnYhsVWJ͂Kشƅíj^I޾'Ǒ6Lߙּ6fW5X1B~ew)6O^}S*VKM!zk ́qϙvZDyTwnǶGO1+nd{A4̔S1;#y\% f5 ǪH(VPBeJ_TtcգbL\kVi]]=KvZ=Z?G_LKNBH|2/iM7ZғT7qu3:|wBSK*B3mVzk-I[T'ot%Dw_K2ztQ6~wE&w;p/xݺNrZ$wvZm=l{Yʰ@-R-ŶDe޼찳 uyBF ̀ǼU:њ;*J_)۶7t‡mرy;B=w&fASdQn+HepYELK*#+btrv2iT %u0lV;F}$$7n,.sTuh;7 S"12Zb@(Alg ?}XݿXm592Z|ͣhs۴x7WPZeΐc5NG_jP;`a0M}`pܳ ڼ_f?GŴȄD 7ұbn;`%H' ˆrh]P< OuǷ!o{_ fò*% +ʾXmܣmOrc,5 VpU AQ +Qro3S}sbK@*b ] G*ٯ21wtf#12jE]~ŕ޶Up+y޿0`|Y}'v~Os P}e1Vc/ +?whyhFؑ6عS74MAk*|-!vN;PU\yhg3яXGLߙּ8+=ZEtvEgw?bH Ei~OWa~za~hP4ʛa|Hc)e ֻQ{xCG/`-sι*[uFڦsᒼ#vPq?nLl+CYEy<'QIAފt3C%VC̸fS@%MJha'_4҅x j8|$ڳfK|nK 7 ヨ=ou闎HN0TmցY ot{Zo{Gj|X.YG.;&viR5/V3xo[v;& i8h#[kO`8pH>/&|bc,/,a^|Gƨ{>W?Q3zl|Ϧcw{Ro~_Wo4!uٍ<¢qп7_?W?/_uΎkjE>ᄍ'_? }ϐ_Շ?k>W|__:g_|//~87O/{4o{ }??K?>s(W/d_7tſ?_dos ^³Ȣ/~bR3ަ֟mſ?/~amtm7}њW>m>?%ӟyX3~$/n':tĖ ^g w:fJ6|{aM)1kFoݨy5M{" K"4r e3 SAd;CV+#R2:H*D=b*,Ey 0s;VDH[jkJņBgLע߸Đ4-.|WE; ^`eJm|1b/{#3+BR],JM s("J-Vןr0u BXUϺ&ҮrD wJ}uso$`K@׭ Qh`5Uݻ2AޙxVUS|T+; D2=;#$G%$^74U֕xnCtJ G-Q຺lT HztrWê6%H+fi y|ӻ[h/ld/!{U_U3vw&u8Ԝ$7 ý4.j %k= mՠ(B>Gj7,J(YnuItNJMK-4tD[LhxPL@MF3ӔiC +^قtٽ暠e@Q- 3s^,*· w䪁_-pg<SGQ4l޸k񾏋8~|T$*M#i]G/75W#3ENA /*KjF>],z[|LE%ih8:ST)H~X(uSg,|uQ^1B<)?tw̯{ ^ej!?B5JՉR_Z0"WkcKfMJ$$RG!^24lf4 v| Kn=20.QԽlOF9:0hsoev;zOd7ZΦ5P :{KVd1YZ> >XR0.T yv)"A!۝Gݶnx@SxX>\{dڝZnqBY]86<ֺ3Py\N32E0h@NWt|#'0 +VT 0ovi|dg'E4u0pboD> w˝Na^XFW4KLB %q 3.&'6ĶpIT6^[/~Jdc0]J[\檩Nm7GX|g|Wx +"U.xiN/%8nm*m}u)HaCHujj4( ŎfPlhY%@j/5|P(s4 R5pmܸԽqjNW==Q6 k d@~xY$ܗU^LKmQp,oxμ\ y(%>t1-{7eu6yϰD=@K/ƪ UBEQwZ;6j۳.+t`%5P?#j,A G,74\f/&5Uv;y ೕbWmrS̶.!ӼY,?OAKW`J-fW>"YZf,_ڣ-[nSnY$D$KDӟ>ooPucVtc{]!e>Q*|wai[д_Um͕CZ>z408.YU#"PA^F}UdM҉ʊ40(>!Ij5L6Ym2Q(EZ!R(C"6\ĖOSQDga’zENRbp=ަhR;D~ +ķJGJUQӏ"eU%CI9>kK8e 8lnޑAE4IcgRnfU, +B@ę_#L{crL;Uc= g: +pQDA̰R?Zn직I氓GH]qy\-F J>ՇzO1ڑjK-DZ6v_q+7ahȱ=u𭟄N!"]*@>W¦n:mzz$jAz`(C3[ʿJ'ihLXw-Jř)G\LH,++PF,z3Eqx֖]DX-/Z9V;S?)hшvhE"Hȶ.NOoޭ,ÔHO)\l +reGwLgqU`WI3,njUie}C"&Lue) jP 3*Ӹ|m_Y,'TXa^tAZcT2ڌ8OTJ/);Y ןPTnW8GIW2(lmv8{~VW1\g!lϼ^:`b FQ\*dLgi/,N< + $j{srSWb4.x(5$J󉥳A")ǍlŒ>u+i5)k*RmSTQך#;"> +0釯dSjU9EMzSyCY-}l̛rqlӷY,Zkų6\)πZ$R5A~EY*0?ŷv}{XӔz #eRV0IZ7(̭JL1>\cmWVUD#`KˠOAbdogUN|7AZzNe&-LPB- &Vzq.fTuZV L ,$Zj=l+X>I\$g]l9&=^)1n(RuY)`(ݽTԔ30 MR觊, x_jҶַrȈ(3\|d Q줚{P8׶FpV vl#ekÊ%e4옘/1jӌrEBTnV> 5R': +)KlFt`"Rl%lee]qB0u<t@ 3L. \fZ3^K*ద"]\J' O+*qߧӨSJC<_{x DQD$UIVb;")b\K\F;mA.y0MX܇1ժ3i4|rPI^*b_[8CmPlU/p$R&^UtK9i7Ͽ DhVT:8 W<0oaR;8rgKwZx:2P 8%BY8%3}H|+YoE*1NQ>I60ьؖ)r pɶzsgj{Ж^mN"cLD'~e U-\bXfFڷQyEq(/%&jBҢv@?lb|MRqGg)jr\Ȣ,E9byː9UCN/L²J(+it{S$A;e(R3NʣԶC><3bPӯdΰUi>67_Qh͔1hakW^V\gYi'!*(b,pZ)7}"*py +_8Sf!#@Z*T)nDe&l'T +W/ fzH4ͻqEVҽ +YZcJN\;xת2AbΕݤ ۼ/zBMA tQ 'ޢԲm^dzB( 7&G"SIç{{TV hr^gʕn^k u=Kz r)3a+źSA毾ʍ]m6‚㝹7G]e)K̝30戤f$"$U bw:luO$,XC~%9/r(VUB yWrp7ETJ3>m]BXMnio+,x#wS4nRLlL*_,iL~ OIFo(Nd!Ҙel +?Ũk5>iE[ IsZwE9WS՗/#x][զ( -yzsbJScS+Zt$ +"QI0T%c,MqYf]8W'Z/u^ r;p;NuDԪD!u6YEp~Ir;x +׎:etNk_[*>>?!tՄuD +طn7'Gaz+ڗWVӃM@ͦV! b#"Ztġ#2b^_Umd=mAY= oB"vK4vBWcCeoW%hS:f#ʔHh|S>K=; ^k{VD.n.̲ YVIKKt,;SU0RdKMdYkAќR8JbޗwCN s=i*Vng1vnKڸ `b@qԤa;Ԃ> %1hW!r&R=^QXͫ*wYqea +#]][HKfUYdk"m_ .~}[Fj*DyYt/Nk'ɑaT^0 wJSIxbc)<iKA틗ՑYQU5Eq $WJr+/ʃp ]Pur`K՜bt>,Lb^$?`U4P @J c{"mjiԮi\UIhgqYrJ%ȁJ` [Cu I2P.e }Ϩ$_/Xz6%:_k7QF U(,-JpŬխW3BGH oBqlSVå."BQ/5/hS8W6/3GOdVo-S""KqnTʪF HMpV#جSD03/QNb,CDmWiD;Vvc6f]EK!v,i 2"V)0kWKJNtaNZ.tsi|"P[ M癕kQ#&f% wKVP3B.q6Zٽ4iU",V±mF1NltXC hK/71!RXb٤4 z=Q~ԱLBw'mCT~:` 96Ke/W"oVI +?i|+MfsTę9; ˉs^~Uq.ߌKݽ +Jǽv6}"Пn')S}/sKo-+SEMÅ%CjJ;X +}Qvvks| ZLXp[0U#/FEcJ+^?5*=83H)PUPFZ8vfJ"A_Rau s̲{wz<4Ji!u)ʰiæۊ7YlNtNM+_u Yn]/(i]{H +%n*qK5zU|W,e᠈rzT~=lTz2estVđ2ߴ[u;mM968Ʃ?6YOz+ê"-MTPv;X)L+=0*4t듷ue˄QBV*Y"'Z8QXvqZڏ,^Q2F>/ +GxrZfU$Z8e;G^2iJtWgqJ{RA6)ʥZtjҐau^nC{GAq.9-LVHߢi k"V/Z{G !h%&A6%#Lu$Rc +j'U?WjVp|'/fqu[f9rFy pYbe E4Vsڼq%Ra0wew; ?Z tB 48[#J<0@/>n,YPEvuɢAFkS\ +T4sXͅm//(Sv\z I1Jh~PhT#3zԶ@0L콅H +#x3zXtpMm%@N[ +h_MCDWkct†kbTosy) S_ܣ*)]1КKE򫧯DfjԄɸQjq-Mx(딑@j68MQhC],_,S +P[w{ PdGC%Z\)ȥmjZJi]+Dd< hV€tF4̧t!!ǺFy2if~b$ +Gz~Fl.Bջ`n*D¸:7ɒR|}ZYvÍh@wA=nmWQZ%PyȰ2,{: L։@&>@VR,dȅqI'l=@Fm& w5X@@FE [2ȸ@v`%Z0d\ eayȰ2,3 'GbS3l n {y{LrpdH[GVcd<7 9A&sf#LARf2 Ȱ2+Sx"PhdU2žoYYCi&'S A& à@&X0FrBU:'Y-uFU~҉ eBU?d AeFay#jiY-AvO *sBU5ZA& eDax#Ȱ2,3 AVigdUBA#(??d'd2l Ä ''6 Ȋ;\H +Tw2 AVz12 #@a-d& OYBpDtu[ԷH*w@aDugJ. c&dz( ddis~ǀ +2=dn3LwN{"ȊZY"d@ax!J-3Xs@uÀ Kc ABFY!h="0""IAV +Ba +lX Ɍ +W{#0Nb1"겼d' AV<#ȰM2F OYQa@1L,+U,/ AF΄ C 8!$4"$0Dd:iDc2v #D;&gM2mZl q@A/{ kdidi AVQy!ȪVAVNdoM2h'/80!0"2ɧ#kFUR#, #AVًvLk@mdR&y"dd27 0!Ȫj2iB [<"lL<dm̠PQ7zܻq@/#gB W<"0"vA&"AƳd8A4d`_ʦD6L2ędd&Y=A 0!AFrBU5}2m^2&3 A֍ b2yo`$a dy6tH > d#q"u@ KcȪ6#L/D H CE TH dؓ@H c20a Ye$u{rԙ@V;FYQa&;@v{3 7I m$a A 8d d2< d=02~ +H +"R7S{"i$adfd: H +"@FE c0Ȋ:, #,I r )BD /23 L +xȰN2 LGdEm#H$Z)_2 L Odd:s$_2~D + @@ OE +WdLda Y1}$^BD 6Ⱥe$ V'(tu~Ƌ@&D 2Ȱ dXg,L D R'Y9ۛ@sp|40Ⱥ5d#]@Fu&)8dD#, [@V2o֙@e& dXg,Lgd*wp&uH *Lr iydef`IY:l}$1 dpl&O֙@&D ә/H|$ayȸ@VȠM2Ⱥ5d(|Ȉp de;2KȊGNL #"qH +KXI@VJqT-O2Ⱥ5d%OA ;_2''@&ˋ@&D gM2L #R.': dȊ-#o@V5d^Y'dX«I c9@ "M c d%fYn L #" dčf78L 7L Cv&H$q"H KH K4$Q$q$х8^$AY‰@VA qI tO263&ʚ2 3 @8ȰL2^2 d/&ah {y* #@3ȈldX'd2YG' @\ @VL @F4i =ѱ<ǪO=3Lhq13 ?eacjcܞ7va⏁|ucb3L1?F0l握=ǘf?F:xfX?u2d!2ǔc\Ą7~n?VU<ǘ1*G ?c|1KU~idaL>k?ی?<ǨcD/1?ngQ'9ǰ2T3t u,fC޼,e3̶olP?FcɞcEO?V"'17Ss)f'c%+NJH^3.?~U;~L]I@1B #~ N2w#cE~L'~̚wv1E46?VR4c$oR~EcEnjSm%~ ?=q}?6[B+%*&~?& ?uƏjF7~sƏ)?X1Y' ?8ǔMcX1?eƏዼcEX?FgQ(jc:~̌2"Ό1Y\JN|0N1 }?1Sg9}acU>M:t',OXUsEcUԙ>> c*Bxy>c9Ǫk*>FL X-˃>ƙ3}‘{*]}=(|01Ĥ:ǰ1,oX 9e}xC1oN1]D>c;cc4!>cL})gQiS2J}Hӄ3x?'%^1YG>Vb)F}I3HS~o':l&.Ez>V2V15L1R(oΜcU1>GM*`cU^HS"IBC1z6fo'1h9xǪ(#}=aYH2ǰcXGz&,O#}Z#}L O?{.L1R/XR>1M3>F^}1g^1Rr>&>&B>Fx陎1F >{0ǪFc~T3Ǩ c,/ED|j6~p2&y>/+ʹ1#𱲭3|SW>Fh)0^q$SISj\1F[8dcv>c&|+cu;gS >?x'_/k|do=#{Lu"#{ Ë=&ads14'Um{IdILqvGgu5K;WLRF1ʑ=M1I+cE'z#>JG +V&,z̊Z1Y',zLDQ23x 3z[FYGX۝1c1tF/&F'/XjQx@ucT2(yǬNqDUncce @ͺOtFc*:zdc1 oXQsD5G7zL=& =fC+Rc܍=6X`uP'ro[''Xn 0o`FOc2:Ǩ}cEoO%3zD'@ǤBIq@IqB!:ǰ1Bf'ؽ]zinF>kB =6X%'1u1 3zLz̬#zL =f?+c3zl n XQ8aD=zz4uG{/Ȅ4cuxǴwcTnfz\ی'zdFB3z=fE#z,Sz tBU 71z111yBqq3z='< e ==@'zhB):QcĀg"z,-#žzLE#z=qBac8YOnDե4 豴zL=Vq1[> +$X{@1 =5x'Q'z ۈ#zL'=c21 z =uX{@q@JsD)DQO1Ǥ;Ǫg[G#BcKr1y <<֍NSHӷ=cJ1 yL'yLƁ<cYo5LjN1 nc)`d~T5O䱪‚yL'ycFX7 4yMc$1; 1էy W"AKcǤ7cg8yLcO1<^'yȉ_qQL޵&W{ P3:-$IjyR߀$D㍖eY 2M* y%J 4?F klg +c㸧r\\e>WTVV_=x&y >'g{/_w#!:@~QG6 Ejך1=ȯfY_ zvǸ2 %q̡|?0%ı{&~I;/1=G})m.wKnHϻK|%?W]b| Lgj|V^k]G9HɎ{-нt/;7^Lg| +.fںeOE#:ދ-{-ྲྀjx/z4Y^rq:F {O$bS}+K8RQJ{m5^z{s߽l*}Y9k rKrڋ:NnOd/^m%WMB9/g2(f׻^R.VSA WL'{2MAJJ"{m5^ .]g +KTlzGKLj>SԭK&2^wE%|FzaqZw$L%BuoD/ gxc_⦁26* O BP.==!uKXYtMd^z_uQ.F eܴ.R*ch]?BtM3ZW{=[~x-Ẻ^ %= J@G K&Еi] zȃ֥{B-`к +K8u1 )='TTമF[UcwZU[8 ᵿȸ.-SNEץo,K{PRBgQI|A@]e( X``4mGKoE%%qpЅn@C(_ҹ|.s]2|C0 <:Jw;ṡs;Id.v|r\/.VXW˅73FpU .AO*2EhpH~m. "cX,\(f2_?ں7o s'=ͥ+F,\ +Ruh.'ţ1Ϧ\Vd vsɲP%/( ,m3\A(v(;24\+ɥu\sNjMd=wNKwgISE|a{d.hFggYZi߽Ptzs5RY*ЉY ΙYTe\ ,Zi/ X̨],:ERռfe1Y8YaM8&3digo"1N)Y,T,V@ ENM"[hQl=:0Y@ξ)YpkHgJqrA+k d3_dUU)׆d]*,TbB!,d2$5 d5=}T=Ion HYsv&ɢ@`dRZ,)$Ku: $ l5"';#Km7`3,)ω !1:@cd6QtFΑfdn܌,oƋ>O`m;(Y5//HC@P.,uHegː,ސ,T[$T>nd5}nHVJDT%[dᒨ`@HnE2$ [юpFi@_I,))YkM2CCMצdIKbQLU[,TҀdaE YR,!Y͌dѕ|wCgeH[xwA[tVd>stream +87#K`pȐ,^?f*R!Y($GQ[PP9J:Lɲش-ij9FGARrʲr` ͈݋ʚ1$S9d)~eQ zJ256%AҟdJEؼvAɢ)+(Y~J"MDQP,qƦdq&LR8OPqS,RdJV{"',k)YJ]XFdq&d!,ߢd{غ$(YU37%-kd))w +LYG&d=tKժEiJz[4L h"Ԫ M՜ShJ")YdƘH7>(AZ YX!Y(%1dYB1Yt90%L~ d,2ůgm]AYeNqP>NplLϜ,S)n?6ɢCX!qQe +R,s2*KYŝUW}H`&ܚ-Vs-A1yUލҜ (͸iYPY(,+٩5q=XYYZo V` *뙾bpc@%j%Ё^zgdq>Di諅" 3*Iw5Gd!~➦i΃`dQ?e0W%Y*Fq⳴O FjMYY< D[gq%D SS~-#4c,lpW39#ڌK$PYT9# Aٜ`d9G2$Knb +~ KYXVeFVg3Y[H-:# QuL`[0"V91T,͚ȒYtY԰Pk`dIĒY k!kA$rdsv|^YK(=ddu\0* k ȒY 2 @dIdY),,Y@ûE;LB=~e%"!;x'%BQ/=_1 di/J-Y̑L18! ̬8hS"dIhhքiy'hH,KɚEXZըf,8!f*%3! Q d!沈a9 Ȣcftq2K{pbҥ>w?C45D$Ṉr>wc/6XTTuޒKjౖX[|:DGzc;Ҿ!bv" 7 +& c9E#=2 : c +2NO^E\'ca]imycOj븼+XIIu [ 2mb^B[Lfca@L~hCsX[ 6|s J 8Xf)!tWL;5@pݮM1lj:fRp,6^}E2vLBm=JmִXDN  e:jͺs\@ AȢl<+yFbdMmD:Ê,X['8yy]X4:=40aYk-uP "lPb[baD3Ԟ%f -$m(ҁXn\v'@mn%94, X  XXau; LBa)QF. k#5Z: /Nai^lYv0C?4: +)W!c牺дpޛ{E^m%sܫAY"Y}^A/x +롏mJhu 1JV 9J:vؕBf3XgGLsx +4gЕJ-+ fRxgW-^qux=^ML +-V,bj+؊0?_(T-!V[`+Sd mH;Jeg`~Q.)P+2: +SsċV+Jz΃h0Xt.gu-qT"pVjhe"K8arr^読{K*%X8/VbWx6ʟUhn4UfxwF¶H!.MR{YUPǝcLCy +ŮP" kxwt + ܁cWpWyœˬdaP\4-OX"Wa}rUQh3O\Y'8J#=Wѱ= pۮj+\e,p z\_Fk \Ex]g*V[%-}pſFl4snj +[8[*AVI.U8}'Utk*Ds[Y^ԋtWOlýA3EV1[ RRX$8?FuOHP2jARI~=c0{U[GG¹UK-:^]"Uh89ʖ zŧex$W!U[ v׽TZَ6ӫSW'ZZJW-1UsѫX@VU4)0B7U-ë`Vp(\kYJWhA;S\mV, WIU[ XU^EGk Eҝc*]a1[<Į +)U[ %t'8JEF'tFJ坍wAWXy + ]#,*3%&vbw2*]! u1{aW+ibW U߉]eLN"EnBWYGzuJm2 +Q:stb,2JG1.:$ATHQ]P2:yeeU[tv) v*dC߅BP'u]瘱!e2 +#-]ڢzvJ(plذ$]utK*DN2J-uXɃU ]ZaQ<*qyTYRp\m'q[WѮ`UԼO's}[hailPwָĬp//@V=Vu(@dU)|nv):*]hUK ZXkn_XUjx帿R U}BfUMs:J +mRf\SK;&U |`aʪWEA86jno`Us"rc`O; &59jbr1+&{;1?DV:5>WM%im Mk ]%aR, `5T!g)2oLJV%ZVn9JNvC%q$U3 P[h@XLvg aCj!XoGD=F1NlMWJt|mpjGh⓺vsU\,=sXZZK)oQƒU*5RI J8IgM{>ywVl/ʙVKUg Ic Z DbrXؕcЗxm|GBKU fZ +@E k(ɚn8=OTG?~ +wTD,h^N =QN^% U#g}2UkWnf WX)=*vV27}>JEPImQ8,X廉05a Kc/f)á+j(bueՌwSXx~_2i?Zsb+ܛU-9b#XMb\:U}>Ng1nE˰%󓰐b7}/!K5*UPmцƙ|yUƾ[*[@ +N +ho~KO_硷^\q +'434Rz\բ@sFEl~Oa7:d +}ch[ifl%4AS8[SZ^hK'av#_q[{mMuL߮/BTafF\"b0嫅9DZR[XlUcʇjݽ \J)VJB?=D$aŮF~Y" +։fݡdauFw!F1]?;YS!!ZZ#e>')Rj-BQV$ +#̞,n …jC++΃([2ymRk'qWB_qNU!MFxI"aY@'fFSY{iFqID=Y(D9PXۨ0x\Up&Q*dY1B.X*ٜhۮ۩ѭpp(MyvEwqJp}@^oRӦB9XA]D;e.%IȥmǤ,VT.\[P{Sd+(R^qrDyYSe ^8"ݔz,qQ=R,t*2ч_Y-OumJQ RwMnvϴ =+܊)r46ߜdUk}IXZ iszwbv鱺#-v ]%%you‹#ҮJ<,] +}֙Y8][UG4w8JcP p[zZ>NQWm"dKnR\RFDŽۖTjAZÔo;;i'}uFO_яdq\cC5# 8-f߼{3mBeSgN9KqXMkaλr[ݛ쥙uh/ͽ ) +͜NT!;r"TWLjp|cyʝ ; {Xq ;S<><qC>2R/%[Uo֕R{ +2UsE\^2*Ÿ8_Sg,ؠ/e㖦ID..(7ʹZ P{cN^f eRWfp(EEyRk +jT)R.[wNOGZO!!m)BV\÷]y|l'"uxMQy4 T[Z)2o;7c!MȍFŰBt)f[) lU'rWlFfLJ 3iQ!Z&NFz]G}G@qELZiˣLڄ0E^PÆA"lFRO31)²ZhEwbfjSԔ5%rԴ})Bϓ&7L@~+\Қ%:[d)i Ykgx&8N~Ra |ω)KcH;a ζaazs`.RWw g4!$7.%oEH} "˜*5)_8IKk;)* 3f Im v'l +Z^L*]ߍwK [ib_WZ^O'Xi6_e +ӈGއt5;<յrWܒil.T؂Ʃkqn)8*w͙D`@zXam*JD(IU T[uyid6LT}I"@[PMݕ=*`o/mQ6lL.H50c6ZNSmCǩ;0!,;1&542-iDeo2vKవWe((6HeJBrL@BU56=I|,~k-ޘvC;^LT{ +V"RȤ2@VYpiQs+BUm'P*f[ f봤౓z~ԴϿh{+ ubR1c)7qJH ~ UKN딆)K!=1?{%3'bߘR{핂F(2`wF(@]L<l!gw(Q I6 Qiinwnp]jJ'μ6IY=ķd&\&(+pQёPP*SSB}Zo\lܑKWў}#'F%uy5/j{Tg9[kLD=gPui]cӦ%+:5AUpIܫYU(**j Cn q| PmTAIy)_E֭Z,8R$Q  ,DMO/7^30B4)C;pJS(TTj^T:Pp_YL3AA ,FCA2=5Ǎe`3]ܵ]\0k3xW: F*LC;gT:Zu5$H5XQBi7aŰY?y^7U=\VO/T<*I8u)iu0 +:.bhrza*7*xg:!4~Zl%X-j#@uou?LQXZA : ;AMA_yyHC"W5)18ޛ6lTv8BKd )QOMtb鳀t;fs8S7Se./jG\N禫 l10."k.yrs%c/ Z_~z _3q97ӈT_[ DtK++KM^ٓ|c.tX9Bch'@:=?†==H"BZB%zBDrzRRtV,_E RB{{ aOUU̓C&5Uvf΂1_$ԫې|`ؔe0 WlU bhrAݷ\K4^|8larvJ"mo0JYp + +F 9vU@RK@.z*u1VJNj_]:I[ɒnU Qs}`n9HTD<0Va;mPCM Rh,PlS3 Ħj +}z3)gjIeFǻ`K9oyCn+!'Z;/6P 籓gO Zk춙>WRdܙTP +M @6U>A`-BdvTBiBv$& k %հ5j BUx(?}4ф93 :tU(WRT=v@&i+Z}Ipڨf`* EdNž7L$2=0<vEŜav̊ydd7cQ(k;[x?hYՇ[j\&ؙУ?v\]_Exvk\6-p]7b咽,;#͗X-y NS^UYr$Xi#YӅxކaಈQ kl>;n}>m˻Ϸ6NlZ2a}UW[ k4REC+vzx?¼RNH4_n' {–sX+l; $/vv;9p5 +ڦ ֵn,-A<`+~l㻝r rT`^!o'M>Fc1Po~oFhCà^A }w/"S5$zQ| 7=Nl;zےnjETUb~ڇX f;0PmM15*S`=ƽMr2ք (v^LڝgvOJŬZ}y* %M*Lzu !Q(}#h5b5!/KAS_KEp_ojxQuJP_ oJ8]T%ƽApvB=\4UvߒO8BMXхYskBzVyCRN`ɘݻϴ]i]DA9_ 2@ r[7u?lo0gTWmv˥oT\ h[,Oe~7 $E3g>n% i4] 4QTd%g9o+}ٰyl_:pEx…O },TkQ<81כGTCęktzQ'^>cćO϶|0f޸ uUΣ_Ec[hM{@"?p]uKYZNxj^ +XN3ŵDx,g47_ b (ww!T?i$TXn9XT$\B8kf]Ji;anZcZ>F/=_aV4RK.PfiE)wq`JkNV b*cݴrӚ=he& ʶ" l^Ui + q㚷*|O1R}JKS +;Zџӎ _+ $J2'ۑ7U'ף'afPbrZ=ꍏvI5ˌ)WW m)e5{r +U!*[#=Nv_J<TȬj+41-{5NOmWT{wk>V۶0'imP{z$x|=0@.JmT3?SZET7yh/bOׇ71t]6 m(8Y*eC6dn }-űr48?yqU[6۾_.R]JavP sK]670TP4D.: +<7onIFs`[mǽ6'Sn`7x +7'8rN'\j=|cv#>;\q[饔 TlO@)af +͜3k&`uH^fFS*] Ι;Q[I.E +GX5KW3E3u:o?=yLCyƍά,7VvՀ͜#ΔjfGtN^|9vN4~v^ۣ30F!ŠE!,{gk#*  47uN9L8eeZFL!4;7M R̷ږ(scL} ֶB[U3>,L 8zGFV +qk!+ɸ&'n^ey-T͛ns=}>]DŽTk $*]؅V^e1%#tg̗6 +jyf:Vqzqj'R xs*,Ҳs gw@!y}L(f~s%7dhn5cTJj.H3"WP3/ [PeÅNۅ+ʦ_u.\#qSx6$[շ%7=Hy{ɩ;}@Cm##nvėPup]귿+x>$BeD0yMSR.ˑ>TU6I蓤(w{&{Xn* Bӽ=K]ZJF%%,`Q^E0lDZkm:c1SXxhX<|pVf|heFNZÐPr}T\mY!! {mn24v+Z^*5R-[8ubzX)-4^'Na赎,/*QibD6)7rKč40JY:TZiS( 6 + A em9P3Fz%ncxv +u&{]JQt'ceh5s+6;F:f] A'_^Z+ԁAQ."ye9+pvgV!O6wAUG=9(QJE`Ki׆%^ |(=ᅿ}x6؎̾EY"nBBr+?/bnу<o0yIaÕ="= wI=݌de@:V>U;Kd$O.e.j4.Н>YeJ/{] +l`mqHIKVڴ^s4E r +”7 5cC#Cr7Bcb^YZVS8{@z}jؖ m( (ډӾޢZqZMQ*Zz)iI}Azfv^*v_,5albւê +BEã㪻8D< \2"^xbDӂK#Ux#+rx(K/O";E$/2Cē{=KAT%!)Do"/D$"V*Hw"J?o+D#2܇J!⡌+8CēZxL&I(-D< +o+T'/T"Vu_"=ej_x[D:O/x` Ou%m[x8~xdi +4}xR+OJ% x+P>DN$4 U"wR%:_"RRJēӗ'p*D<\>DD(.DO&♝BēRxRD@~^ģأ}x )ǙD23Sa/O +2/) u̝3 @<|xR+Cb ( (M[Q:I-@< /83OTSxK@%3e &t@<\2OCJſ3/iWx_  +ijxII@G1q% jI@<)_ ɠ|xR++/x{^Ъ񶒁x[ UxM ˖O #fZx[@ GGqQWx= +3+ OC^Q\x[@OD O +%IVV nSWx 'P +3?@<{3OJU J+o+Ɋ~xz+O/BiV & +SaG42@ d ^RoSp7?@<+|xg g~x+ J/)EuIGxxZ}x8TxV%g%%@<*;O_[x[@OOSH Uc)@<)FSxjK@<\?@<L Ϭ2o+UqxXx ?+͎87F;xWx~x<t@<7 Óq/ OJU2\SldPyx}yxBg=ȗ'8,$|yxG|yx9 +oh;A(<<ť*_4< TixVK^ixLK70)E 3 Cã. + ?4<-b* O_?B|CÓzQ48< + cp/8<ݍ#,)Pqx<tYdBAGDVqxtQOߤ?%j!u&]ÓVJXT;B5_BT,_G%ZpxA p"2ѣ'9f^UuGIюã'?8<* p"9_öPT^`"CQ iiB~i4cUefgOiS(4 83\/^ᑡ8< ?8<"X2 +gF8<g^8GN)[qxTS}px:G#ZpxjZ8<;3_^>qx*>8+4< ]1ixԡ~hx* .c&/ Bc /4<&1~hxAÓOY4<) ŅlЬhx8SѻEo\ /GyS᩵ Ek~ix*64Nti^/(4<~ix6.dz.@_X}hx$ _٪u1hx>4\.4<)_*'4  GBf!|XxYxzF+ j BCa + OJe :[~YxcGKaiX4?TS ۗuBe 4?_£䥠|QxRPx|/ +O›QxXXTh;($VBP]`Ap E!JAIf  +oೠ|Qx7ƌ›Gl KjXג(<Qwk@yRnRg8Ix72XSMxD&b$<vN“&!$<w/Hxz,|$$<W^~E£C3,$<å@u1^h`($<$<ۼdueD۪I}%=2 BCL$$}\&4gBJ&m5HxZT$<,D + 6&m!$<2 oD"!M³%e" %I,$PHxfuGC³.L{-$iVvVB7 K) <GZTAx|T᭚(* $^R7V+wlAx'˄/e[Jm5@x[L c <)+ϔ_V3c) eQIEdEt(~WvZqG2rdѓGg(}%"+Iv9 J-S@vڃ]9vl#9ŎZobsyotr8O"ر7OR\FGbiॎsj=&@t{/z߅AˑNG7NN7H~ȘnM݅,Şkuޅkޙ@,F6ŬY@(ao%5ճ<ǵ tR tR|@ה0l@7mǒ@)8z6d`Z.94ʅ?»i @'\,+\fe&- @.? @װKsj??qkohInٶs͢gI=@'8tmPuV]ï!E3݉ A:!ʮ ˨ {簒 ؜9ɽ =}N>}?='aԿp4乓6{.2uwnΉ(wtnc!aD!i{P{3#nnkF9U9Q\9B z*WNlJ+Goʡƈi:83">Gd9=Nwgd9^B&K=7Z{==/{ۗ0X\`9㰱ÒRWOY>ٛLNCog嶒r[  Pž֔]k.ub?,xklbr q Um%`9bf*k*Xt0#s, jy85Mc+qi͓8Ї^S:+_-jPGБjuȝv*#9ZN -6sZr+gD +3Īt!R[ ڗmTSx?-z7'mZ.) -@5B2xgEA`5;iC r[ > q +V *1M3S0ja;J-lw4Ng~m3`9)8OMO ,X E1@Ym%s\9nӟ +|`99X+"V̙,g6AD9-JV"ˑcz ^VE,LK:od<IO,!tfEbd96YW Ʃ[><؛ue7 ,V0 5~d/T3m&5XYoDr͈fN + dPR>o t"L۪Q䚐#*RLP>"'9㸗VomUdMNCyJ3Z$ %AUT[P䶒)r[ ^dZ3Rl} +,9Dn !%g?gjP2F{J99q |)zwm[IUmPNGa̙2@Uo5qf9)kJӑI V2@nk2~ý5*Xp:Jȟ+; < SeZw{g4t^^8|+_4w߶]D8puTGm!Q8eN潑q Uq;l`+޼RIQc"VymXC+'_L`[ؠ9't? O] KLpwg%D69'fiٟkᶐpK 0xsߢ];04 Jm5p'npb pʻY=@pl*3-$-3{)ؼp:=Upڱ]{cᴹ۱]&{ީjoi8$ +@ ۪ᬚ,>j[e0ݖװ#;K}6 +kÌ qd/0k S|`8l`8]~_ +>pIMT2S#"ISep賒Jp +Z`qV2!ޮM#(?C󚷴]p N gi#P(8|TE)d8TM Gq6pVwW4'&}khxV3d[ I^ᰔEG8!c/#:/UǬ\8l}/.JͅLSps gf+n+̅#^Ow hX8 , j$ ~e‘)^aQD%p$I*o˩p.+T8T,*6c2 +Gy+YIPPT}\p7kS%.p( X8;^5p [p6N c(e(w߃YN*NM͡pn@l˒3AAeDf,(f>BX1*)Oi:9ΓGl-NaV8s_φ` 6ͦ41FQ{ߕ̦% !䴟\6 +M1fo %R F[ 1xl?Yql!9͌Q熱)`ib#m#0[N}D2 ƦĆ?c  7MgKUg[p~/RqZIتٔbkQUXlKņB5Xl +>kؤ^4(~3Y)LYl JV|5S[XlzM +FbwbkfnYPl,Ql (6)Z&V+4\XPlLMaCMF{].AJ[=Pl*rؔQûbSQlņ,6TTؤZT&hlRlcvɖW'kt Æu!|IT" AooX+I/Pu3b'5xƆop 8I M*Ecq2M"yظņ4YN՜Ŧ\e [#;b0j4^GL,6XL2{st&bkғ0~~eBM5~DGM{b1 {t'<3L5pM|ih#36͔YlbCe,6)fI1f5k7XM/}VfشYl| bk]YlT+ pvؤlHb2'2ϴI|snJ|i$WE~d DnnYϔuE=7My33gM#;=fm۵`ltoK`l +^ ~? | c3rDVal8͇5h +wpͰUal(` 06dalt=!06\<c[all + +S [YR`l [#rwckdケZ%`l=7ԲBcShc +%p +c÷,6 Ʀe hy0k:czˊj j_i?(ؤZXlT5 휷c#M:hlZ'~ p86xǦ(kc345h86}c3cScӓnQG=Sz<6Z +[`Y5&Dd֊H6- FlGe۴*dӂ&dn}^=ld/DBi3^&nt͂֠uD~oNdSBpd1-eLXK#*hլ3MoRP?HlG޼ 6W: .kDbC(6q +Y ;Ŧ woXcw{h&VPl=EF%%(6zgoWZFj ņ-Pl(/tv:ݭ20DXo8 +kƝHlzbAlf>< 5f2-9U۬ߣsؔxshU8ll m+^,58l֌?qؠ}sXa pP2ob(6z~s(Un"9XauV,F pȚw<=z O+"Q6{8cVx1> 62i s bLŸ +M*AHrDR- b-S@ljaQfJFY bCe  6ÁmsxV9sؔ!6J`8DҴ}EPt?lӯ|ZV$SV)lpK e:э9+Mo9@l +Z(@lWM6#:&Xv^6FoFԇetC9#DmWW`ۃ勫vxv뱙j[hСjy"3 T#="Q4OM||SNSBB(mYjfD'I HGn?B'h*;g4NCZSiK)4Sr ~v.P9i"E,FnT<4z{wSϫZLNSX*rǜ#̚ig4l\v~24,KT<9i[HĴ%0F^R-j2.M_pRKS h1 -M KCJ;n/kW%ѿVm洖yI[bPhpF)X_GHSQ&HP`A ocTgB;Z*Nz/uZs"ѓK4k.DE#Ԯ֬!92 ywg7.|4mY ` ; MlLˏ;rr;u-@ +0@/#!HO?"d5!MO|4y[,|4ml >ЬNI|gѤ! >;/ F_BH+ +exDenҬjHSGSTܼ"m +lѤX%%LG5TB)Пh~u^hK\hRh=FqW:D/s<sc yh]!3x4%Ҽ1TƣI5_ѤLGGbŌGC89P+)JA5D>`ゎ֘ZNlњ$+y:]|1%Ѷp4m,mg:8vqVNGjx 爴 hݖ֦T$M`=#M$ HC it{~^~ݹ93$m{a}fHJfm5i憤iL%3N2HFG}HS,zNdFBn FThJf&iCٞ#PzHj#&z9;# XfInsICEs@Hǭ-Hnd:$MWqxؗ"-EH#~0;i&U!1r}'IG#m!Җ +%wA>8x[!Ѧj'l3 )K`AI},rXMBq"/@Fa8./D2@g +F9GG- L;,kψY!t"ɩy~޶/@Pd=3!L BB~2!M4B(eDujև2k" DV2"-Hu 6i狐FU#! ƙjbGYgBYEw5FsM'"(A3i4q 8"-BH[bdcztHao0..>)O48gG qq/KhࣩviMLG1;h*~fBɯ hwv#no, sM%8m Ā ϙhӹ SE5D{e\q_~w Mu!iR.U +I#O>vL0Բ">Zo?OS "iSZ⛪yE=&ڎ䠳8n;ڤ9Bm;-茸4⌎w*{蛣6?)gFZǂ +х׽Yjj΃uenӮ>Ԛz`sZxj?smÜ,,%՚Q:QM&Bq>+л<h|\?sռ mo,Gn-ޠ +Win!gκt*cXU>J 6ΏpZGVTXq{QR +qdh++TRR`wΨ^rmSfS唵sR8kKyz"mސVLH!OW\69^B#!^dwr]pWyf4kjm_<#M ͭm(lq8_,ը-L0FzKx\6` 1R]ö o)cx11 @OC”!.F5U;F.< b~]mP:T"m5N#0L3_"mRY8Wt!鍦Y _€jQ =Oʩx2 +O"%!mo;|`)ϰ2NͳլD"}UT'CUzԙP? o_ u"t(K+gEێh>'  +x^)*XAfPy~<ޟ +A[ ?gzM?7䣼 s2jjͤCYQ*BL3g޷iACh5˜67{Px?qȤ}VH)-ף_Ri91:P8e~8enTV퍆h[P{C߇LfEYJ\ٓzm*eUDM6~,tx-"RM* T u&t)OX>vjT6Z}3ls+v#Z襤n!IgE- isc+_ 8ž{_V6M׃ŻVc` P^):?޶U%عs_i%M:%tƳq†~uUq"Y.: j$Բ|Я ͤbJKc_RXf1)cf'5WR +hK7l:Kn=[7mi4|,㬵4՛uD]6 o1|SlCA3- 4IUۚJ:g-yWԬlVs43ٺok"V+wVT*{u$\S*Q9eB_VqPX&Zh<0c5ɫNPc7N-T 3`Z[ pV,E®oSH4NK۳cI_Ÿ֒Kљh+a݅`uw)'~ =iP%Ym8P& L8@*vZ6 U"wEq{?#~H9muz,ػL#M՜ٶJfډHySbF`J*[N{tШa+l +RJQ~G0ݴZGOYukۤU(".~yy?tI x4t3`K!G}<>T"+<=^a{ZIҙIp}^0fUG/)4ڀƛt7Ѫi7eݤ oXK6QvC'ΙWGlֱ_>iϒc * AM='dSx&6_NzJ,&̟iM;C_m)vQAqOWb[iqX'y6O6۸F(6RW %2$4>yKǖB.(Zz [L7,l=%~F5FV222b8YI(%˻p"ĻT-xv zە)))jjk5W*ⷚy(yx؃qKAKo#&%ʖ2FmUn#ݒfu)tm!ݤ8ni[)Jweз~s_xXL]ؽrg+ϱ;/UI\z'fYnoL=)+q lf+*!+@h9_wkzcne=udDq){7\NLY_-T"hq`kfk|n_`>i ?}@W>g^ְj*֬yD9%2鮿P. ';maR6bvm!pv3i~6i*$lCH-ndAwg FFg<⡀Gsubz)2WG>։g{]?>kxpR͖eQ,>lKatlYQf$,(,`o+սA*7"[܏ؒr~I4o xŀ禐yUNqTCHUEI(ϹU.Du;7V m <Fd>Y,&O1û$):z7A_=zNV2Mqao![WK0M*iAʣp%じ Po;zB/7)Q"BCQz7I"/ġx2jKZG1"(xd(X +8#*9]u3xF+EN*P3o'Q>OJ'C9B$I>[tACEJ9. *Fi-T5ڈqX{,aa,;]8=P5/#Cxcz2Q|Ukc)6#K涹C( :,"!]$e*'uY3,bna443,>jٖgBe|Ի sRvU>f'I(px lTwʅn3oV>.HѺia,78eޏ +YkK!=1k^, 74Jtͻ#[iCIJԈeJhFYL8feZcR_y yN;fqP2JM=WzU|;z˻=`a_ږ4h=gU4}$ S(߾6K8"y̿Fʂi=cgQ~:TU7+X:Nv͛M4--^❳Dd'QIDыXG]7a?ӌ};9N/b7`}px021i!\@7lCEy2FZy T h"0#}>Opt?YxE;(她r9A90'!F9a^fz% ߞV'͛Z +bE,hfxL "!g8(9t(?2`ڙć=(WEӉf±Ht-YV97P,Sc~"(T98v)Z_m6^;O}=eƆ|عˬqOT&E6F)8ۤ.c!z!v>_:IqϢC.Y̨<6qD {09En3ĆΝS f9 J21〝eNƞsRy.Nn4V1"4B1荐 +|N5z,s(ݎ+YA;U-'r%څ譥݂O$n2ӗ´vLzIǦ/F\(Xs$yw^C=kU| ޤZYk|J^2Zk"3^ HSUŝ^sH2>łE5C4G" f*xt 0v``We)TfkJw<7 E\L# *fEI +R)խ$$h!QhՒMi:2rDsئ6vC$a,]c^NIa9|ˢbwHa.%(;->f2}}HG7=̈́7ܡֵAdN;;9ԎfP'Oj&MXݶ0Ya9o~6NǮvTQ=#$F|Gy序nAʛnCd߈+LS#O\D:TV9X "F])V`h6bj:/6j&TOt-۔,"au'D BZ +"L[Q <^AcC lԒK@WC/{ޤ Sf US Rj$C.2B4R&Ȇ'wB>2ѫt3rtfj^EϾ!"{?Hg{=a4\VDL|wЌAT]9h} IR 6(+@:ɞXSRROD2qz4^UxS>ئU j[E?}n HGFnA,vh8*L,8D $yu,ŘeZ^qv Go`Àظ3c- i sQeFЖ1ptJZjI[.iec|{{4 t)mngm hT[^Im3}bDrXq3TiGΆB=JF}c<)ȯ"II! X%ۣ'ŠEQIOzV飉&ڴ2$.n;\@:Xw=VP_I d0;ClϺtxCż2kwMRfImvo+14V {ѦI*eQ2c.;feYFQ@w[dXL:l A*g*Ըl(mzJ JKh|ֺJv\P:-hCMp˥CTXXFKh_@y<$eAPOddRs:\5]mN1;;tGql+/?_ؙIMBs~bj)YC%UEM*F!jB10I{ۏ YW;R=׬m!'EXB5U&lٶ}#o 9i=ZKU]2Ewex*NNrB}R10!L$ >Z,W/$It-6KsCe> 4* EkJ+:( #qEB-(o'(Y\(y<5PN#3k.fcҀVcc9ɦ`PXNٗ[ĒχM-#w)dbl͸wE@ʴh>PD-KRoƨ;[Vf6}g합h>^;"H/-Ef=L*DCgwq|72,U9g*8<=4;4mrsHv7|ԮdJlK_"(G KA*jSNl֮{Lˏ&[\agmWiF7;2L r4;<w~ޮtx]x7y]睛i`Sގ{쩼GbƎ,䝤H'+Ǎh!6N\¡9iYUG<° [S3\s48W.[igmX +}Wt=ljf'x +1m"+ɸKw=1'K5gew,lϡa&R2pz3N7F|unMjX>EB0N}(mu1hr!7pZF>gZ~9ޫ'= :EB]c[;6w[춱~$gU(mkj H)Tm g\8651Y(H# V?|a]P"A"~(%:2 g:#Xw ~WXo8+)rn.ia;1BT iuY-C%??p1758 +0-3* IsWw>Rid+vi)-7BI$ɉJ{]/֙qy=unqOe h0}Ը}@{k`萯v}mS,x #n)"Dvʅ?cz0t;ކb<(%hFtR5*eBͪaUz~ ,+Qi̴lRoB@ʢߡjnJO:˜N{)kWғ|$<ޓpB.VW pDo8yBf -ik1/cHfc|s 3m|Z0+PVUK w[UnO@|5"sMArkV-5xF,-ᅐri?n<U]Y ְ&bgvq4'xiwQ8w^8f 5Jy)<n)Y\fZBcB0;[ӊ'B /\U`N x1DoAyOfk~-w"5"ϞxR+cDN+/"pD [B jX2P Ǡ"HHςj AHHE1$3B T$s G̳ T$W$c,HExguZxKD%3e"^盈ןQxR2/xDӋe(D0aYxK)D\!"J֣Rx[ "JSESDc\pxo(2OqxR͠ 8F/ru Љ9dD<<<~7On똽+)_yx=2dq#u +2/vxnCI<<ó{.Wx:ޟ#yx]oΫ<<ݍSSx$2O7+ZxxU^?U>/I*<<75 +c.<~óyx7O_cU<+뮒ׅ+<<^o r…yz^ +ì<<+WxxX OK7O7OjuZ@gO5( B4q4eUf/FÓ)oRyx7W^gPTxxi`u:ge)S#yx][9jJ;xx OQSãH'<< +<g8MÓXhx O|1BMÓZixR + Oʛ'𸆅Ma OJ|+ cuae 4 ϔL+'.jI4<)oX7>틆wMÀZhx|Bixzf O@iة4<4<:ף$hnhx<7($yP3 OBIx6)4VFC"Xp%/jAY{/Bh{:H³c}JAq 'eZ/ǂ3 +O&7 +OMD* +r£@C-(<B)SPx +_gETf>0d_(NJ08QxG$5$QxTjQxjF+(< ZPxR* +OG]~A-( +@A :'cH/(oRha:N/rrL/Ndu ͙g)fy [GmciA7*u5-n&Ub S[ΫUk} { 1icJb5sU״~ڳXu.WF53uC.kXSQu\FIFIkF5&|NGL2kj/IuMkcMk'T!zPx׃T'窝T'疜T'ynRuSIupoR]ҹAu2 -:y6^NJ'ěIuRv&IWۤGPakgb5VwBT_MN 稠:{ks9T: 'nͣb}S͸{CNRHOeԩ-#wh5.y1Uϓ{mn+AŠkH l~%\<a,ςj 9v-'GE5!fV{#Yt4j^;JƼr8X<@'&qy]@dz +.=9.QtlTl蒒t[ ]'=uE'z%Ex@'Px+t,bŜtk#8v_J:ML( +&_[n+A@u6W_ax5bxO:ȩMb Zh̳AGé{py4Z)ȇg{νD!ΊR0B5oU` #aZ,] 蚡gEi׬frش9B*ߥ8p: C@'͆R!0?0Cpdߜ>'m$4,.=홆Ö"FWKsC=msXfΝ9d3QJkcn蜖z +sBqoN#sܼ9ͨg?7n#Sisf߬9Ijn 4C@=8s3mȘ9=f䘹&قkT\cc fQ.V^q\ma$h p}3e OPP暈G&xY)saE3'5Ze*q,U3fN?;0sz^%d3טkbD2g)M{Tnm%9m׮6EɭP6/m撒hs[ \3n[9~O5P6mN +E2b6'pPϹis(ZeڜTVЋ6/{k[KI\9>&0DN涒is[ ڜ+n56טG>NO ?_;.P"#yhqs[ɸnyDV*4Z nN͝ ܜtn + jGP{ngSqsM#&7h;m%斺psz)&ők +)>-aBZ(ZeiPFkJ99ҏ8Is\VIsR~Uۤ9sw4z&I9[9)4 NkJ ˜4Bj} =5*9>-ǫP՟FA`W2eZ2wE's.!o1w]]8kS?+aNmuQm? W/ۢfigA) d9yh>kH+'X9}CQP0;mA)L9Wq&m̀r{6%N~O]Ca8r2Fd}9oơN3B(%AN{ޜX窕V΄[Jm5r'nb rʻY\-r +666?NQef8Ell~N|Xe~+McK8 +u评 r[:AB,Yߪ<^](#fA@?KkV9+A3AY7{䤐]+EI䴷=m9]~7$*} X$r9n'#f  s}V"|Akl r +7#ύS>XBq\!(5&BN bF!׭r )v;^2A.PrJ,? υ!GBbșsj!5j[^rP-4Bп!Gaž!`@cbȩR<r9+CNu$C_D G290I ҽr>ir(7@EW>\Q}cX)ne?ǁ¸Ώ7gW~2y?\B-8+,|\jAt^5^sl|beM鼂 e=.|'oPX8 ?K`[dL/`55 +~\͏ӐHߋqrnzC N{1~:z>gi .FkOv?L8 +G6G[P2"[Ҏ\-zf֬GKEc89)q4mjAa=)}4cS*8]EkF(c"3Z^$(MqyOSVayX 8}[}/ 9>'z^8y8,V'_iE]OiuL0q#6]gVh)O85҂j!N ?DϳqZE<yÿ#>_8iZ,X $ذ8箬8}ymT4Xޯ>}̤`zjpNrQWN-"8qZOk`. NM'ʉS9݁')1)Π836(N +CQPՅޛ8O8}ӱQqbdG,>:˙@.<1*\)N}A{߁gPlNϳ~a&) qg#%#4snB]v}'>p-*N5')3o2A}XBiEs2ǩsޘ_yw$d G ;܌Eu||L8@ N&@ Ahĩ +bCip|)5l6% +N TmM@p(2yfƩ1Td$Vij#w)N#h{|YnpBDBO-bn*㙑h$&\}<(xetzFp +M\&?(sp?~SV~Sal~4[70if"Dq^sakr{57M嫟)4|lYo/MIn$o2ue,TBiߞdM#F}/rb@C3-@=J%.QQUs8A{1%ZӜÓqo{h+:M=/۝鼵 z?X1op߼:;z`e|>H_C6 9Nq SQ-)?QooooO8d2g]|76}ۜn +c4 +n ߲$Iv33ʨd6sݎauSK8+v6jW{7nC )@ay0Ώ'U+ +w.@scv9G*MDF+ʍýAnR)vB7Dt@ܔnJ!- ։wথa?nf6=rm AQgbF]ٵmjn_AYmP!8:MmS'?C"9)A"mF2ڦ!iQHM:9V ڦ3M'[5mzmԶ|R-Զu6ж.mCe hnقIcI= жS7MUSeh&9ǽm$-s5c-6T= &Q@$\@$V 631ۚ-Ge5ʷk3ۤxlɓHZlk.H8M{&kؠ!1ۨ:c3۔{\{0(6ffxv^ m }Wf[نB mIlI%,mRX5M<)6W/ 5jr6& )DEmd6."!Jm4^@)vwʏΖm6=%=hrum:ӼmkIR3A<,m*#:m}m56i@ۚ|FIԶMW?mkHMDmHYɢ27m,\&PhbAۚ +mk#oh[.Y6Yچeo-ָPF#Ma'6?~V +h\ ڦqǢqm+ mcBw@Z,h[fesۖhX WV鱉m]`6T +&c3ۤ Ɖ m@3m" aqVjl3RP(Tmdf6jS۔8#cXmt$G6OܮEmΘmQmY6FCXxPۈO j[ekچ՜0mT0Umm(683Cwچg6mXyK2gpQ@e +Gڦ̊YK23AmkDpMfQM_*Ammyj3Mٸ++m@`TqzUqYcG*xuH0#km>QE5tY1XжNgϹmRM0 FYE>چr;nQH`S6v&„mۦ7LmSnf@jL1nG n fj)NI-Ep(ëmJۂ)m%NncXݦ5Nvn#LRa鍠۴೵I4|_|Wd %ӽm ?m]j@50Ͳu ݦnSF +sg5 +imZ[e۴g۔ǣ:&4:C*l\6! f++#z6Ql ن=TlC=SRݙmz6d6$zh %&"8lCQ b1W,4 +꒝&bl۸0T@+ǫMcY2M-8٦*k 7^Ai@l󄋿m(8/#se0"&_abq f8fY>*M->w` ֩w{1:Vm=Efm%C’6gf\of[gia`ۚ نH`%f+%CaI5B0ۺb<MlS+nJF& %!۶61d l}}%%ߋͺ'` = lC-6 l!`lQ6DrL)OmGc Q)PSE/y_Dl#fg")IkElk=ɤyVb4ubƙqbTAl#zy9;TD?U6g;Zg)p=pMa_<ĶX+. l>qm[û`XT$e7BjòVc:ܰ4pHkapsS0aLx;m:m%yMv&r4mTfLZh%d257M=AЍec](fDj32p? :dޔ6b%՝kl۵ kj}k}#lI|;S/yXGWq +],KV9jKh-BV;)JV ޹jǽ{̂U9SgC$0S_֮T-NTz-2OmS# շj. 8ǦWS>>+05a 6aj،4c|VeqۉԶ_J{;7@X!RB8KMIq;IّIj+Hqiho:^'j9۬$5SG㎱Ij\aV]*Xj(22Ks-MVcԴz +RRR6z$Tn 5)'Rk($5rV9 )po% +mRSTܼ"mݳI][Ԓ@j^Z*!@j4Fw gܛN]55%.5^5IO^@#pZ4qQrY_Aq#G+dƃDGM2G:I֬LtTwƉs]hMTFMx +QF1 禨5EyhwIEM3( F FMcx?8jII IM0tZ 2K 09MM6Zd4چ!05}S=Ђݹ3Mm>m%Զ05sԴOfajr'Y0/T>ς)m; Sk Skdk;B5dVp`jRwԤX3g!05>v8M ASk@%˶hjEFSU%R[ZH)QjLz])xPj[(FZ*H8xRQj 2@gF99Agm!L=,뷅H#f .7ϯ)}>V'bC+Kg@iAB)Ȋt.FhvHAWvʯ㚻HK-)`ẙ,5R#ݮ}Buz?FD(5T;K.gD=RèD)PjII(J̒#z-n(<>RS/*L(5T<ϳSccYjK(%Ih9;zxn R3I,5@jtd4@N#9R >n] 5kXm~dǖ1jC=EPT "3Ԉ"P n7"MM2)b4TB}MO[B-1i#:1$gR .Iᕱ;GHGڿI:͍Z'WX~H՞Ll٧x I:*y5#g t[52(qy~#`ȭ/rd{B),P^2ڢ {js:f8''I㰁{O.[^;B + <ҚQ;Ѱ?6 6EP- (Q dV`Hzƹ:HQPbY:ȚM$`路d--Glĩ%OJ>QjT DF1FU(5y:j(ԁұ^`Uc¥Zn! '5d'32}lnat MW. ,΀K$tk6d/"bHʔYoB~q1AzP$VEL-2$ҙ+C`ɍJD֬}O./dRJ>i\#!3g,K'D+1J4D+qTب}2XEGE,<)udLk_L5BÅ]ekl9*~s,BdK! `BYZ-⼾P. \,w d/+FET.<Q^"zO2l ⺤6 (Eg+1Z +R֕ rFyة,D<0,L|-ēwNN/ +3>%qK} E}mCȐ \Ȭ~P +AejSo +lOd\q.x<gxz <"Dz'r+*k t z0DL&.uyԫ pr- D}z t t7V=M5 "rUm渦5OyLu6J'я7Rj'7t:K?',9Yc?7PUJ4Ԅ>hԔG'ֻo֎AC2Bu'0 a! kT< Հq?T*A#N/xׁ y&%N"󳥁JN2> Ggy"JX?]a:Vb6lѕǃln=[G (~H)D[9Vl'k ϊX$2׻0h7X(JM=&D6>1Ь_cK\-if6m]1.,'ZY2Hy z67&gE?#f0:ĝLNP,W(<=|PƯY7dCRY]Qz!r"=\FN٪s. %zKp@Y`Mr ?Ǝ=}zYCkZmSD܄j ds )5&^`Ļ:S,bvdIbNK :kGm{$Cs DG%ਉiEvz ZE]HpIĎD곾 V[u֭ٙlY57J5sˠaPbDڠ\ .ƍ[؃덿Җ &3iZqlIT[b7X:$o<H./Bٶ޲'fh$IbtVi%[L| b3lJEG9D#UÐg!!X TG>m' ..܏i}VFEU{RmSowmZZ[r)nSAC}eOKS`}qX1⠞@^:K\-e#̅2C uZĪIRèWS[/Hԗp MQOH9!9 V\蚮u0Lk/.66?A_e0vi(1BNql"9|l{35y}yړCszzه?%˭f)XƒnM695<+M?@;oB5F۾{?kBdxaKt,"dz6Xё ׈)lXʾ_x6jIBIm;f 4vAZp +(!JpznvM<Ǿv] :\)aFlz,EJ(bmt~  +Ju4fnjs#: /R?FY[MEvSR2s蔨d\ܹE#1KJɦE0= zܖk1k-VI(i; õTg~v*v.vrl7"붨(z(V!u'T! ST@hT \QcxW}K3l,(Zy&!SEC#YSVJTGAaeį^Dp1N-$X+%Ypf%AYv uXw`ny^&N1qQ6Pgf ǀ&"=7Ŏ$|#Rdj6b/3kyU* T\v&MŒx䐛Zv`]Xy}a9' ITDDKvZUĈpٖT 2SȱorTbe .)Q5"ϬT @~hP/4 vɍR}nqAvb՝:(TW]RsfY9kHmE;n# +$ 1H*% ,>ܨǛn9O1 +[uҀ7ԇ@LC(8nE>"Y3'Ņ و6J<Bk@O$lQY[Qwe:i5g.Ԣ Eͱ fm>?5",x^~:]WLQ`Q|;Vt[!6'A$ص԰1|c]< +'y ) ?g0x}VCa.ЪrwFi` Ć_ܺ5r*1N҇%R /Eڀ\PݫKFm1%+- wn)IF4B#$wi *g)|4X\u|TZhoDExaX#:CA@ڣF*xC/̚jЏ{ǃ}To t%YPdLA@t*|jNO)5aAg?"J YYb'ggpv>Kg/jҔ>Q|`qk+^!`F c{쫔m{S+6&{rf1=fOSf凅d YM2m{Kj/{ñaQ.Y1F"\) h$ BX0/Kcdfjևm}x"ǒ롭ݠ^PJThC&)3h dJEOdcu?ނ~( @#Y29t ^?!͍^ L]94%)h'88:YN23n2u℘r͕\' Vz#Rz*;ownTth2mdh_16u͑RʄrȦJQ:C+jAXjM@.XJSNw(ƔHT=c {6+2z k %6k "9J0a{aPY*,I 7W:g"$ѢShцxCE1E&"˙"D\׃чl^7DR`M*5O&KSÓ,g JrWKVJgYUI@F? jQEogAAH/StYiQS\U8pjɭ"ntEBAҲͺfʰ@h )b=A!FղDaAVG3l +RF?_u9d۫9M-b D$IkkD 9Lt2$u=G"(/-yީ͔$ED(`ْ'=(xU'u5FvQbV"݅B/vRe 1fODk!ҕB0dJC3bY<F Nj +/xoO ,&Ӝ^9 I2> +U[K6 7tr0ZΈ}rj6.b֬7M"rcm! a )XE;pYX.}Ja$8RPQ`yYg!lϖdaTU6m2q7Ф%7(ۮrڋP3;Fl[?)6[2Rva?bTRФǓޖƎQzLRANLsb ͫaU7ӝ j֧w8bԞe~}6rQn@|Vx $ކZ"+`zu:esi+4'X0nwf&ƷP=F`jb  Ύ Bf0b6hNO ~; f$BT#+xuԫš8&0O_7?1ީB-B~D(6ַJ c6w*ͶZ_iH;hbg@HNɣ΂e{ dIb{?g0ԕh?_\7O*BNARAX!sK Y.E*[`7l#ZVpb4o 7|7e cPNiԦPhpE-bfmhs_6!do w~L]&IZ-ev!gNѸǍmqmQ9lq4*HUL{E5[<85Z9ŨeH tߏxQR*,2z@̔,M*J TfEp[r^YPKɒNkyry)GB̹׶Fט &ZfB +L[}@RTLj ?j`Dg\"QYM;QBQt5qp״3wBd`B deֽn,9Dm{6kΠmQ2rM`5~G%m+-#[dlf}&s:uCrXJ<z<4a\l.m>(XZ,0 $I/-:VLE(*޲-;z9ng +%])ٴY] Nqf[EBز$,Vnn3E `Q}O't;;_Is)8M -na(n +(skk Lqo-ePMJO5`m<d qPHXC-mҋp-azmPi?8 O5ŖcL8Ks[ΛN77tq|s--#9C']nzl۳ͭ|ٷ e ߗ. [޽BbAKRV/QE3G1eLa*V*kQ~̶umH"ŒLװ`y?[2r4QV [&d~>r c–z$SEq,a"4U MP,C +۫H!xh[M+=s;.Nso;2wl~=Ǫy~Lzdt6 0C}Ze''nBg,χtrwiyq|"*|nڔ҈01DB18~Jd+Qhr|`]~i1:)5 E4ͬTb0:*.7Pc3\n5 nrf{okTV'v4V!h$=`P6*P'k?Y6%+( Ė_VXezkƏ h`}6d/fftZj"Lm!&oԻ[~s?h#g^JlWf3K`yA*?E3 ) 66mE_AV, XƩgoGoy^:̐0: ʂ'lb!QHYKe^c`20b ,8*ۮoEyIw ּ3`شl t| ԧluA6l7-+wL~¤NF3^ö&㭅F4Sk0< R -͹PLłAVj̗}4k>pp 4ػk!/g2[O C#"qLM׾If[@S]r:b'S*h! 1h)6ꍈA7zfNZc (8Y9hs$ _F`1Va5 5Cg@}ѢtF6 ZAhyY~K@5z ـIE-9;X$4h,-2'[ AS~ѥcxط[[9l1Q Ie9qpu%Dc4cϴ6.oњ_˲,2Ibʳvᶢa \g{.k|x)Ӛ\Kh/.*-`z Y)oeɀ])8~>g;R)o nQ˵;3[rH$XFq8-ܓbC'{FNO50rne4{SURE}7Ʌ1"}Fܐ '%.$\y]H9 endstream endobj 49 0 obj <>stream + ĘI/MZ"蹛8;7FrߛiɚMDeO=ii-,G%i8SK>~5[ iiJ69LUG#s%һTh1[nn=ng}dN)ɵg)~Dz?&Z`^q*ol"fk͑r +G9Z3RjY)NFt>6^-ojVh $;FXWe=K(hP;#x\ĀJ)l^nj˵ 2jc +unQݙ5?VՍ]ov+< m`y=7hOwO(Uz5`K6;(&+}z,X#f+Kb ;gov=+'PjB^30 +3ڏgj +%B,HR74kI 邋A9 sCr/PQFgKGBhU8zViy-ZM~ K}~!6xjO dowq`魾@z y^tXC;FrJD2hPhut>W8k5Rp"fQb"$ۆ)/.`>`Ճ RQ4e:vZROVVe\l)Qz?H]`5%An'CfZX6< +\w[!=ɊcE]01پm\|~_g( lc{DA(̔ E,C<ᡟXRk>"O6KJ +l --{ET ۑ5^գ*ݳSMn@d4^3CkP;;ީ8V& hQwk8Oym$֮\r?4䪺}p;?͜-l~PG:LeY0% tMQʢUI@T횗(5X .$+/63̦ +-=4"W& +м2'6".,2j8)Pnvkp 4NǣzzL%DH*сJrpݒ%4dΤnb1 ,!d47^'}+Fy]c.I"2WZq3*YN \u֐ꮥleW^ n+|U@n\Ұ䒡&j~&9lr hT:8lrDюVGһQ':YJ[zoc+ MY&Im-)k3p^zr|Yjږ֟KjA pFO/XN67vD($ro)2& $'ldkh)95Ÿh񚎨Dsb,lc+0۷<:Tj8ƮvN#'* +&P3n&Po)R>D;V<vR0]b Vܡ@nUB,QhŔt,Ze&4B#d\KG4qlds 6[z" K+0"'MP?3eA$6fSRl︣hWdQ-ؖ.]9R7GZ*J7J5H3 %Dg$u3 '03&[ܔ}] +(Q")o|jA`Jo1r1ٳ!GJ.;pf +T6(%Ch!'S5UBdV8Qo7XvMhyl轑 \¯L %kǰbj3? M[.=]uNR3*a}"Ѳ`i,-NbKŏ¬’ ]7lg:QxJLV^|Mh}0ePV8L0[fdŖ@oNL/o:HzU @]?KB(} /*3` c:)warRZvloN(N ! ZI.]G: +l0ciE:\jƖ8ž]r fj r>8člArEKLJAoSE3MҀSN!潷QuuȖFg )(-hPJjI]KT\kfnTzg jvmXs]nt: #S, Ne#vGjbhՙXIV͞ΖVidfFlVN( GDk͌li-}%AEj1g|nQ+A/XT)G9-]qd +إ} IYII:׷zq,[ ̅4 o;ʭ+aS4H14 gt h{ۢ-g Sa_6[6b%)zBGz沚g̢)~,&NRZnE +Lnfé.ECP.G0ֆlC-8-E$6 ѫy8b]²,Jlu9߸4s2eFɃv1B>^1ƭMj4 nnp?Yz8yh|UZM $姬oEP.Ys&VFn1^zl+bHQ"g?7^~ jK,vUO)R%k mNɫ)"O{|-U< +}V6 j_`NIm^>G =_=H5mXn$-46# =hVqzgD^GgznՑփ)vlum\9Xe& 2DaJ㇧ő3m {zkdqD_WQj9m ۖFwk]-Q]j;3B$Gܝs{1TP/۪wP*0X{ UXh@WE@ӿτ)2{ƼD?m} dWh2 7` ]0ώs??Z9Me"e{)Ecj :HM5*vI]^h>ۛxezc⢷v7 r ; юjCޏWW_ +Gq鳿\]f~~<_w߽ďx=W?mI.__]/{0 o.񷟻/۫J{ߞ_gz? ֮kGW_?l=${Ǵ` ~7_՛##3>/ӻwoj>{}IQV}xZѮɇw_vz-žv_`48o.‹mo^=<3w#ܿ}ˋwgwoo_/y(on/?`>k ^]w_?jN]o8֧}[5޾j`7#Yjl;!\K Cq{ʲ<1BnVOq08L\خr?tW)"KlHxl}~t qM^ye'+~r_=|}s z}\8#tؕ'Z]u?[/ɏ׏zxvyu\鐂m +;:ջnoϷ K)voA._|A>\TOP}<[sپJۏh___wߙts^:ڷRwl=^~vi{b|kވwm!>vQ=a9v|lRv=zD?ؕ@S_^]_?[tz}u{y5yG;yCߝgm>?i|^~_ҜvHo\=\}F_x~zپb<1ͻ+Uym[I1Al;Rޚ#MG=Lonl?R~;.^lfKyb2'pخlf`3ۗY?̳_m_ΦpyAnmWp槨`>pgѾGYKe^1p kl?}}{ yrVyW~D"~O!/{\ boY/ۇWS2~ki^Wbɴ'Œ^eg,R"V-փ?ȷ|;ȷovo..vnOn  ^t>Zp Dp*JxDOD姼a64;N[ezp#yy}$ŭ3pv'n+$_5in\~yu蕨S,7~B_Tvl;㚽T͝W\m_LP%˻ljlWw.~UGGyɅlvEzwJ>'\/OO4a`WdFv=qiQϝnrwj#s/$l'vc=t %lHn:ydq{" }'7kz(_Q?ZC>ğ~Z!C>ğg|;_χcc;ğgۏ3MD}'zvAv9b·dg>{Rwuy}}ݶ㻾 zv7/߽TW9.(?nWwݯ|_ݟ>g?8[:[L#7CN=ܘuI/ cg~-fJeny7l3c (AOoM5>`/>b/'~)޲+98sΜ398s6gnętΜeΜp漄|mL}>uUfQDؾŽ~ ;rw|ݵ9x~Xpr® +Wv +WO_~z~I}8Aw=TzUVЏëjo?7wO+,\uɲCR;@<"xm?;Wv]}7O&l_Wl, +KOK(PSK!i-rp쁅oR8?vI^?`=?$t0ڄwWۣ-gƾC=)RG^Vg+u(*da'N?x]&=ҏI/]9CWx_><\vp~աО0}Am?Ơm?G'珔180^GaKmoOB>ۀO+`[`xw +Zk9X{mV G;p* gn=x0f <k4Wg>aDbb>e$;o +ﻻ7_ݟo/qv^ہ:uCUݰpT=`On +7C<Ƌɴ^s{Z+fձ9z׿?O_ۻ| 4}SFܿ-xy2~ -FSP泋'( k<;}-΁=+}ksP=}p]}Sp'-oɾi< +<}9z {n=!ٞ[k<ɵ>yţ%(֯x ZJUWمOV/?Q/t݃"V?ΈۃgAyєTDBnl7:b^P/y#v ;=GӁėg#ON^yeHݧw*%:r߶~k/ʮۯ>'B~ ۈu*qR8_?x:.p ?9O}e('XIM[vGiPIi)%jdf8CRs8щKŅ|ߝTr}ޝyyfΧr$ơt7iUJR׃$9MNC (9Ncr0Vh(.xC >ߗpїܺSWrX4FL }8v$Z4vpuz~̡ΕT)ݩ˱2)9ԏf%auT c0?;c:aX:ޮ].ǘ}4%c}SV;,i.e,w.]t#a9\JJ填0@(mC-WP8D|+ C*%r$-WY]v# Kal>+)LjĒSF+ O.V:%h央Jq~3Rv[ckG/rU _ ĴL\w5cx])WAd*>zLVtk®X຃:OAkpr W;0>kKsN߫jIQJߩ֩NXקJwFW | +qLh~@ﺁSZԅq7-bf &rN5n[U_ +,2aNVIX4>-:B:H|{=]9P¾FIu+IؚSN ҔjMQ5&~g*ac*3ݾjwHUU&ͣ#-nUkWz:= +L :_=1%%Oٙ_%$N/7} k:}k=7lB4$ec Y'| +HԡX Ef`Ufj4P +9Oشi +?nVef> wX\be`(T72_-BՕ)!AbBR <$qDKNb}/*>Cupvv-CoɾvM z(GrZ"=vh{lO sbg%),; 29 lرi qن/U嬎_rtKUçKaW_Yѓ&r7 ֽ$'!u Ӊ)Zd/AzIxegʭ8Y/wpfi;6Z|7p T{B_><cby,O|{4y/>R%_86l9?7G=9#p t4>zA7+YPHGsZUeURxӦ*6įJwWT7E{I15DCJXHXu?˩)'Sㄇ"E #?vYh{_8Aje {:|_-|7$HluAz8ѩZ#:]z +W. $_`*rE#,<3_bGXbV/6Nő1Xl^msEmt3u/"bV箣I +S0h0"Y:u`: ++"Z<E"H+% _8]r&jU DW`63|{ R,PWP{BC:1lE5_3V1~?pcb("Ai!VwH3@?X<p£q_]mr,b!ʷPt6<) R24t!=4WĤϼofYZpSLJD$*B@Hs1!`y8O{qs$UhODj /z9 +vؚT.pB+V.!b{pW xF[_b #l tZZ3iGpʆ;>ZeѡB}L0xci +(|<ίۑ hONyITUSPC@@CC HOWSeA$q Z"!l3O9,-?T;%_Nm',vuC{2>xaVu,BEꂦ0ohHqttr)ӆUxe )$J ^du8C1؛A=,]Tg Yg $VK>pܧ ‹ <àpB-\@58"xqj'/pixh&eqL]\g³QPpPu4jӰEOk=&+Ug~Um@YLY;/4@ $Wł0@PaE4Ep]G ½hqT{Bja]g*J$'P-'іŘrs|T#o$uK 8X†NFqA')ϏH';5S߇+w`AܻNŪ|aMmʤ"B+^?T;wf=ItΔEhO⣔@x%&ߡ _ +20im91k\EՆYNц \N|%.Ԋ^JJS y; Zyh` Xɞ)M*${ AƳz~lxP4_.Bu?K'D=MȪheW-o;6b^( E$qq8V ltM!zb/1@HN@~{ºGK)ObSXrȢ 9l#\dhcHcdVfȅ%aWm|fxQE]̞-qS#7kWnGt.2Ⲅ3LZذ?ROsKwBTFtesA"'R`-Ub ̫a8 t6@SSc:=Ѭ߻Z.b/6d CΘNc =D Txh]X$0a˫_ +M>z -U3ѱzRpO/RQ7 ցf8(AtNi@h ?hAֹ+/08X$`3]4m棇/dяVI*{i4S0f Y(H! +}u x@TQR <ͼY,|U 0  wB;њ`9z> @ 4$M2D?zCZYN&JGi9IFw2I=g%pLrs@ +5X9,j60lT d#nG8$S4Иx@`cz A9@(9Zi@<_E-[ 0{j AsS=$N(JCY#MbghYnP(Po<>J'DV`脂`PggS΅B˘Y6'WV0knNݵ. :?EeaWwNq 5Ԧ(OO V1M}؅AMUq}#W̥kۈS1bvM84}i"@g*LIp- 2ɠP]~@;AHO\"?0NDNR =F4x*P̰fo5Df0*K,ޠzZ HMj8LMь~ɘTMGxxOn1* Je@q`ȋ: +osXyY ꉮ_/6! +)&lZ rG̓Mx27|%+5_KThOCs &9GQ,/3깣 +VARvq>5Mf4xF1sL 5ɕ %ԆB-A;GAރ/&1jlp^6zauPD!(o":;Pay>&C >?Mz-zv A.Y7C83`G :r<[LAq!UNj!!JR`iǁ2,0/ \Eݲ +rcBwPP#fD28Sf9Bd ~%J3(Fdq-Vy)?@ha$fq9[!th" 8%h ݀% 4.@4#1jhEY͠^xi[f,|[ ׂ!s]0l=Nh@`@:ͺ,uT  ADY1G@4KC >DN$Ǯ3ý '% a/6`hK xYz=uNk~[ˠ2= gJܤ !m( xr` 5 AN%P aDP! +{ +v+zl$nqXRr4iQ }E_,&vXT">KH-{:jSQ5 IUiTSxy7Und%SI#M~D AcLưA|tNGrg(p3Sqq\qrdǪ8 nAړ%h!kP݅UgƂJ+@.`rtiݜQaUo[dAzuĴBz תCӜHIp`+EhYylHP,CBXLH&*fF`4uڙHUE̜ 3މ*sQ, +q UAO$A%J|m#6վ~}(趴VaЬSZ9q 9 #ᨔ554gR&L"(Ŷ2C@@DQUEOIYɋj7]Y O1WGduèA߲gbK6Kb<1/pȤP !M^?[yXNr=aԐ1 +륝:$\˚$FM_k_Ym6m˴p$P1EUJj|bwoj IW1jWWOͩG`tD8k&ydʞqVm<۞O_ծ&{"@z:*)T\SM 9yў,Ϳݐ|!~'-CnJ](OY D[*KeWSAzb{Z~p,L> +w f.8u<ٳf{>Z~S 9WXbw'E*Ws'8e v{kXmAĕt"iֆlU{ (RPusJ=K怒/4Lij|+\;)#)4SՆo26}Oj_gzRizC^_=|sۯ.P73HԀ sӊFz(3/wzAOLQՓeQ>`iWҢM:?-*9q #%O:ˮ=9n8sfgQL,ۼY`3ӋɫFa~zmjp+6+W86c|*Z㧟u6w)0lƴQ;yNN6Mq^= 5;yc}:On/;Ir&KU@G^B2ucfX"Ba&߾C Yk^~K桖}:$ٿ'I"C#1kzh#uiE֟rǓ'>qɢ-ps46rc-wl~v4775bNq6Jtѝ隮yFWRu$izGs/8}6^<|['Mg{O> 8>%9Bj]??<\?Y//?^ 绫7rӍ?]\}{ˋj\mɶ k KzWM0R$*K4I P;1L)J8;"K"eF +[M:=1c>ӤXW-R+S8&dOq]GDN{bpG^b >>64`:lcsr~.oϞ[2^7|Dn3=ӯ7E|d:`@GȗZ9w(S jF.˺*=͇[yk˖"d 43ku=n)Y;%/n_"2CRr=Cɕj>8lZ-Hjx ŭP pPW,/ $Ylw/DLRF^Kօqh |aN OUVbRNK +R֬EFf=Z2A<{͡lP28!x+W$.W6՟Ͼ>7uK~_.G OV?}zݽ= p<|§~rqOwdӺ5Y;SQ7rT{VVE9GTP$dS\-,#KZ UyJF+@@ǁbfyKA H$=񒼨\Z[o@SoC~'ʀs$u0)Ld>jvpJD 0]ND*#nKRWF9d-Y]n#Ln#6 %,9ϺBߵ?-X;8A Ay;0}Ctu)'uԣ<$ r#o&q񰉐(I% rchIW~Ah;bRr !1Cܢ Hfc* + +X ӌhVnB v^'Cxl4^wȡ$R.y Ĕs +XX%γ TbQGA }Hl)[ 0 +0D9%bI=,08'p1 +VM e'%Rxc$KTX8,FK%6PTc$uM<ʊcJ"ꍝrPK- б0^,N&rc2|{rri/tQ$yVӖdLƱT^DM$-s5<ݑD0W/iX(⬥lKܬ21UqkO9;9qUp,xDR[̟Ex{bqBxw*$Yj %)xˀaf' ulE>#%E.FZ5`B$sO`DN xsbNTZt.K ^!˜6-2yD +ٞEMzy ܱ&^ R,Idb[NsP"f|fD .!jXAHBaINl"u`Q5sJLͫAn`LY":LvR Y)g#7ZE1ڎ|!ɝ`BBgq >} Ǣ2‚es8-,\D,%e 'UJܷKӫZ;JG]U壐cr5ԤܿGy!p!S%IcͲ-Ł{R8Qrda|trI:5k*dD/* C,ZvA4S98Ѓő !2O_Gp#a`m+;(x͔j +Q3%N2@`9 + 3ZFl$(#Q=ePͧZF)=臤 ):pn8[HfAnₚ;z#P~ofC:ۑ=;я`K7G,UXDb:xskXdU ŢgV d@I=3DQ +#cסgvv= k$ka#2:M5OK2)JH ۽AB"LtBJE٤o)Q{:JL,-CU鎽pݡ]"bl;]aQp$^ot)3&{# ٳt0+%&!/L%b O@P)GY;lȌ-IL*8;Yv/"ASp# +-dubc^ 饤 +\-zX +LK/R efpc^ +ӱ\B 䇪dvȃ(q/u`dHV=$HL!Bz TRׅ] + QWJbzu@wxraαD%mnє[Ga˝2T2Nqzi­̌i'?{_T,C8ݧ,슢"M"!INBzKuum]]8bY :,Z|2MJ9|f,:kZ!I!{FK*Md=J' $+py1g$mdp䞷fz.l TP!=`,.|ܘ i袷,{mt4 *|J",sXw}wBQCrsRg֝sqJւIz٠9{Lx=VL'f?W8՗;#?>-.䛷k_~SIq<5JZI`)t&lNU~:@? %"K|onLV^)mx|?{9<y".#f,Q8v#f0!̡NOppw<"6~tgx0'0E/Y#KPhdq<6~#kE7 +pp @lϧ<84;?!)œ( cv+<npw9sp̓ Om`DQ?7DySJHy%u7 G?Ӥ(0TK69{$)̍XH\h +M9rc< g ƗpE$ԤJMnq~YF?()V0Px΃*oI~@iL)Ih4vhD?.k|o_€^}-p`SMA_p62d$ @1oDP`f A j H1.,]qQ?Pz>CM*;mje҂J$W4N[јdwH[_>HtN( ^0e{!(CR%GZP/P-Z ʒ܂ +£=4-"PcʟbyB7 !hACHp'4?\Q.hMNMcRʟ:`TdP0_B8b&KIrI^ BO\]R~I.rƱ 1$yvK5R% A]ĞDʢ BrD,Hh]A`8|%JFmd1R+;lR@$ agZvL;# φDDJUѧ4J|Y'!dbzByƽ&muK(i `"~ߜ2]uY*HJa;;17jT4a"𜶁BSjtrg)AJbA*{xK7] +lp$T!+SLfZҠxI(q5X7;"D9 hYFGN:&}]PDzGtɝ&hlc䫧)ۓp7r8XaqtRN kԖAV~Q>yr"-=$.q AJyʖU+/+]:`L* dA+.s:IC dz];aaxg(#E,&L) 'R*@ &J0Y!F;`B~aevP4D5B] &z%҃,3 [iQNL[qMiQkL[1.lRN%ҡmnF`:];kw< 6f Mel{/![V @* (aaE+-?zQ;)*}IZt - ȂijO'7pv, Ћ2{"̇+ Dv$@O'FAj젷$BV[h]qD( +8)OcwLTW/:Պ[EjqYV鷐p1)`?IT$.E1aP},ävbuŨ Axt!U[XD 4yIPMrR)X,Y V("Ԕ %'XD +Lv''Ɋ">ҫ +B7"-B +,?^6BhNL5JVšNcU #SӺ_=ojzsܪY ($q<(gYЧ^aYe#@9s(g;;xP4ٜ#'G$ `i 䗅,9˰%B8Eg>M0cŖT$#遙vfqBTr(7PQ9j +cX+PGF,j@Y,h$Εq0{<dފ2ʄď$M +1=9Y-QA yL +Ld#DeTiBbrd\TkH@<@QLV`~pH63;(Il’kh *y4ƸADURpʋ%!(4q" +Ǎ. +,4 "`vSϮP#@tVER9hX2 pidUxÝ#؍n.UVXDJa15k _"{_QXE9,vB5J]U+=H}qnu9l6KhQNX?j]T·werN_ ƷZ&.ݭrZ +Hn Y Av5"ȟla9>JkJwVT})ub.{[@RT@Tң iIz4pYu `-!%NϦ rRv#^p)Y @%M^p$ .i{e /{ _.z(WWɂSMq;ɁC8̙{%#hK"ˁ+;. !|/-BEՕ&YSQ#K$E-.@uivOQ7** b@K +im 0R= (JQШ[##;z+i1\ .C!$MG + .5vB"[ vUn]p)~*jS1AHfIi Ω]\ii,van?qjsspi6 { K]* f] nKRkv^qQٿzHr#VI%߂qx=5Z-|e6MI4! +"yt5 Wm5?>#P 2I S'INcA)]u! V$ZUUb/a> J +`<žՅ1OYD~9uI<@I6-$ FEi $N-3<2)TG7()Jv`Of ,| ؕsddpNbi}]$|~ 2 4oHa۹ z˲6^xuJa986#{\_ܬr i7?XjR5/>H)FIv4Z$:*6Zdlԥ kYfqmְ7|HnTQ.!%PJTJWʎQAV:mE迴ـZQq! O{gr@OyD#2^DHǘ$ѱ;(ņ@t=r ?VQq6F=>ۊ5@vCe/m,$q0QU`D>c&O!Yp(-Oi3@ +3V^@(wS(HP?()epiAᭅ:_ D}NvU.E2 +W@ǜ(&F⍔\Z9k(Վ@ѰKP_Y0 Y@Qs[9OHJ_櫧26L@<!, hδyp!cv݈nf5bZrfNʣ+D*}pW+E8e{~0 -̞2 +NSK2GcQ車O\V܁1@I(2YC zSa 11ihQq;4g@P†:|Ү`gGMrc#!5Įպ6 +L?)G4ƒoʹ>HF: mQg$םZ84 Q5-* iD` )* +&:8jGcZ% J9OOI\0sb +ce恞ވ`^ѩhY +*gl?=ر#@4nLEg{Or* |S;ȷ&|dmˋO=IhwzB ]@1]>JНo6J$ڹA[Yl.1!< =X)t 0ť.d)Ι!3IYjA1ҺD8.yWI V pC3N )Q,,EhC]g>ʤ0ܘ({cD;+ i02dEʴ UaiD|֐r;̃L8 g^y18XV2# ӊ+(Sf ^Fc{a)FTF9D"+8)ԧ!9<)Kw\ (HٱlzU +A@Uht9ɺ":qnL+GB ;GJMV!b'ݙe v療C-hgs^ǘ:!"  & :7TWN/ql6O*zz +A'!1rۙEp0߇`nv_* !9I"E (C^I7() `TU$I$ $ ¿~L{쯞 +\z4pEGWdH] \z$pE1+q-\zL#+RH=&pEjJB+?Ͷ)RH=&pE+h\"H#+R \ej +FNJ#+RH=&pEGW"H#+R \Q#+R \z$pEH8WH5&pEFW,zcʸ \j$pEo9pEFW\DHH[j$pEFW \ GYQiG+RH5"U5pE1+RH5""H +詹 LH5"HTcW \HLDSh6pEFW"u5pEH="HcW \z$pE1+ҿͶ+RH=6pX8 a<Ʊ1kXK5b-U!#V/ΪVTctVtJJJ>&+=TȰl`ahJx +:Xέ썵ң$+݂B+1 &ҭ(ҫ܊Ί.n]TbjbがtX騿V:JFQ+ +$٣Gt6qzU+[J+VzbkG[a`ˬl-(#`+Ո^iHz_ye`F^YZjpA#V:8q'b+Z%[BJYX;YݭZbUt'żSΪVzܪVz Q+Bd[Ͷ +-Y9-P obte(;)z ;DT~Y§>EH$ X +r{K]SɌHH_:K]3O!y+ߔ;dĘ]cg|BtݱYॽ g@ݗZl@[j"]EȖ: Z4eHN5ny4/WRWQfc:K]s, ,Y/\)35:A35Gc}(/t'RgPQoPEn=-ƭi`ېe\!g$`N,OLd$;=Z;=ss>Q ܇gngg!.dtK[/rv:\RyriTD4O菁LڗP@P׬-u,{xgA9§(9RT r+JG PPlÈPa&0ʠ*L`t:$ AAd`\2H"3a2`aE~&\dNﳁQ3J}ng$3JeA%*`ck7h,DЬ@ O ,KF S#Eó7&Q` f!SG5(,¨Az"¤KE(@5H6A Ŗ E +i}`9s!`ԛd*v R,$H &KN'Sq0a/yAF)E)1~vt&¬`60 +VX+ +$PZœ0)s8+({AI9'=kcj9~Dși3GXg7:Sz. +7҇ BѬOvDح :P2VBH,#7i| 5j4QiB,*+X{sp>hPckŅƒwTqhOA + +Ov FM\C +./ɜq):=qf0z/| rr=0\YkdRڎ_UfAdw!4zUےGpB +)9<$p@:nPL^HN䄤iqx[&6JSNPjh י6UgD(87GNb%AD>p +&H. l wOxe_=({`a_WRHUrM(].Ti.+( Ȕ08چɗP *>sd +<_Y_.2\V9-|Gldϔ%GB& `L?. g2 ^z K#xP:t2F7gù IukO)"XwgvIaסhnDXׁ]Joxb +A#!1;uc`)mWܖ +re[yHNe0dpsYS٣(8<S\UbE(!$Ny3UDXIc xeB\uhPJ0rLIm2: '|>lLI"DA%E⑇6!1p$I1jR3C%9,/(K6R"`V{C|BW/R]%h7(CY\ dH f{hU}ZZGfрJ2Z $~^Ŧ$ɷ ՊBO8/ Ei*d!!Ial\iXcM`eJ0 @ #%&e(!Fʇr h}XM &zxspDlP| +GA!t3ߑEǺ!le;Eƺ '"+l;*cL+@gRX$F $u3E^yX A!Rœ7]%S*~k;n E4$yHS 0O kBS~ GC=+C[Fi!+岉kQyDPM=2шbd\AbPC!Vtk^E1ôƔ%& Q $EE?0ʜk9X 9Gg~r#o TgMeI)Ʀ:ԁ*~MFBVP9TGe>,#nK,|*Bl epsP: R@M`+Y`y0?xy,>A1h6 APqW 5^xxJg L ( T( L$a +-e*҇+SD`ZMboq :5xn$f2% l&zT^IFr`31ËV JΠs"3Xtxp4Dzp9>B!XլC Dc*"h8586g./ WJ\A%%9čw< XWw@pf%)?Ģ + c2rVGTg9`H,\Pd ᅙ.,-PI/~칲Q~08/(_ 9ȱxz0g =*:a 22fŏqȔ 2eCN13lU05r,YG`OҷĐL&>`N&+) @XI˚.i| NbƇmr;o2E|RI!Ls NжR45 R6{9oΨDȦX/rpM|`-utPN bzy8S/SI*G@@p\!cJq_eF{AK,S$^5$65Q!X/Xу9"3̤SPr1=!(BI/CP&\EۇLB%D +z +/TjA:AGK)T Oc='`~y=5x(b?=7mFBdMP$n0mzhxQ!f)jECo.QbFPB/懅*C10R +Gp` 䰠29P)m:'cN)>)+Q2̎jȔ)zIIϺ΄q`R2:xx.T6aw7 +2_Q9} ^y-,`  @'D[,1fFe {ZBҫ604|cabf7pct }RLЌo0 D=9jTېQNo1R1!d\r@hci$Msș4,901A/(h]UL>Kjc=(#s@-`:&Z0D2H*LaU4[ hX0P.9$R<M<y< +3SJjJz)OXA-) Xpe?fQ]PWRit=1r( R!LYcxf; !FfSiF!y0@=ӧ"/U,e{(VƯ0 7)`$Ü15)12~rJ _eX4bZ(YYJ>WC-ꠀH2j1gɒg``0ABsPRRQ0rCdW&1K1 Ff 3Vсm!ӛP&H<Z RYI2^p§pFA b-Ѧ}n19rR39?O5b!9@S3|@fC>%316h$é5 !dvԾH!GH~z9@0ߍP*fR2e2 oQfQ@n[0SA +6ު+I*Й$ٲ,8d +F?<㞂6N$ځ Asn + c`kҗ贂Жt0qMiX ~`ROubΤ +(0|p3Ʒp)'CK _a7@ LXwecʜaLDɾ0G2DoOБ(92A씂߁ [a4ø"s9AJ,$aeJ68JbF+SnF"GBׄי)cIZrT -'/m[fTMWP*VK.rCDUVlEaD*PeT.*G Τ&mH92 )@EoDFITJ] &5궀#x$\-R=Z䮣g RwЋ?T4LH)>+m]ls0Ǵ\$,x4NH}<` !YJ[X},ڂٜ[}n  +k)kR\?"ᧈ50^ wҡD mr(<*Ypw_BN;d\ Gkb+I3wN0]pA.'2|(D= دĪ)'lr€?#EFaIL:!55'r:0Iic˵-ppMWR~0ĂFBJ,'QE) +~ +=5i&A ^4iMu+YQqɄFB@em"ŔRBT.)9:7sR`T~J&i"ߕ0$.M"67;=D4XI b=t(9p8``?7p#ѓ^kGjf`g1=z$t\)-9KxH+P1KV `:uHBڢV +d&z)9nʶQL ޞw9? g[,^1!1L%f31R 2+,>(;:3|vnOLB8OiJ.AF-spsAsi.{CtVG0 $]i@3"VTfh%f^ ``뛦^''|%ߏER>yZ."M#QvB0~P6ə`=˱[pxq2Oe+6@"ƫ7<CDq#.F)@Ώn%gk'jY:x1)|B>Jpsu}@q=6Ë0͖P2*  m4LѨS`0惾5XIIC:ݕ+Hx!il*x$8l\R"*'sg^茕 +o@ߨ@9M&|R]<\tS@)=1&P1hȠ JIO,9wIisA[ӂnN/Hs^RBO=Ww`F%*砗47Kb891hئ.Aă]KNo ܁ 4TrI.}:7A r*^lz*b52'HԒ5蘞9ΐ;ΔU+])%RP; +$I?!/5hH #Q2N ]NT›?TFj茛 +xn),s4C2)62I@PxOfzɭс? z=x!~4HE@ekX`0DwJpq~4`NvRȹX}E3=sEDb[r4 JF/*fn34< xnb1OoH(*B7/^ +` |'>\H6eP$Ø^ -z8 0 KvX/ #).^ɩpAΚ:pax?鼠S C,XRx$UBJ)F[!'4Iz :Dѥ RT::(|$:ŐFA4Cb +^+dM@6R + +Hx#W D,W8H٤;.m7֞9WvLK6Pqo 1+ ~% =IsKCZq`To2Nx|a=ƚU4[+ *p \quwi`X﷤qke-Ԟw:~-[j.Qx옑UDMLfP2cfcܿVla;'?l뚊bwڤ6 WhjLyPUV \ 7X:Hpu=@Bn= ,:Zo+@~W9w)Lmt*rK9IR3s|.&2!X[W7by7k/A qJzo =|}Askgsze@J 8D~<)ݢ_~4ߛa^dΧw^z9ЎtxMNVnN|2Y@fgʇI%9=YZkuyzzφۄlu>0ȂfѤݟa}Yi[mD۫qjl?tcx=Hӡ ;{`fFdV2=2?Zꂲ8)~Y( x@",,(g;@A/t{* )ڱ$AvvK ̝b}-b&PGG'j,TPRe2 -`z5sm$VC脺Bz@2 ]Z +3)J3 +b. 9\ۑ(s-RXeaWLɄ;iЅXp+qV,T<ѥse(:(U ze[^YL1 +|P j"Vk% +R2C8rl0~ܺ b*^ir *9i̡&K) +$5^сwO!9uM iƸQ# @7>Cg^*}?}s>5(mgLkHFhv;糿&qT\߮-~U^5Iƙm~kB%(q"ѤdJ3o(!8QmzM (| +J(ȴc(甞ӥ 1dDQie1 ǕSV٣[%$}@IzȔ8FA@rhSM[+a AW;UĚ):4*^WKR"mV!g lr4mjcd斢 3ڡӮEV'FQ(*KzaSA4ڡtJMH;f:~P)v[J(FBܟq4o3J.\ЦfӮ=c~hw*XlY3# eP3Ghk+dD*9ף4 +|`7YCXT$}`9%2 P0(S7* +aF -/!.z^i,Vi2?BWXZ&Md}(`1"HEg3ֲ+Z>l 54h$+.xJpk'W +9DU gwL14:@ShB`K~unۧ'N}ܯ0 q9zxP{7GkxT+Y@Dko1?ol%~*I3\P=#<~sofS4,q:vO~,'~txsP[[y]؁6/`i. Z}}r~Jyy:j}uٖ?xa6uFl6O-c\diE\zBGd13uj\d5_rގe#|ʒ1 16C `zw'eV9qְD?A~s0h~!6j=ް.ye%-yXYwT/O~'Htbl/luJ O _Z`'_ȓDn /-\q_sFĚď s} ^ipǏIsX߯wߜ}y 8J^}¯O0jU za9|fS({ymn&Q[:vk'AKBkǝn{:M[n>l W^6x>N~51[ýn_kx.řmjM i[`6 &pn[7Atmi/YW냝mYm9AvW֖x)<";5rq n'xPl|ЬmAY4칶)|4sf\Cϡ/sꕆ9;q{G|mg}X{i9a~S=C_[!U:4ڧFzxkFD}oEݮ?_[mlax9`T9n/Zy`ϡ$<<33Z33x2ѹ J2^| KykUg}jajk0ww!JQgNw|e<zNjBÀ>Nаrw./ EJ[7hi;n ρ.d.j#[}n ; սvc./lX̥Q ,7,`6B%9)$|nD3As'N YD۰ծwyd{8+۳?+2q5 f= WWEhUSyղ1 &/6B:;HӧvQrV]g-[9>$jk[;G4>OEmTlnyq秃aȓ_RNc&?G #9$q{~oz'΅'ۿpd}1n{>7 c7ִ  J* YrmŋvYC-~"ۆ:chޗjhTɛtB3:P賺3G;4 +#&u!1kqai9]}@|>ڎU']yV cwB˄@K'x(z9uۇkQ$G6:U}hG=H|C +Dؾm5v\4:IDl >Oz|

/hq-(ڱߎ.U'l& n0둹~Fn1`_|>Y0f|N; TBma);;VƦc|es=fv^>z7[]ci|)dtSٷj- +\P[puwqc<+Qe*hj׳ݎۯz4}I3FǦSt~SZSkK6]fᦔIa9hfmxԬXذ?ڀd{B ׀ +jncX;;= #u;5s\/84uwEQZ@7jf0iǬ6Bfz]f0j ΃LoF95[i +'O>vM׍~wmd9IRlo71Eޝږ[FEܘ"ږI0IHa5ɬ{QjN/Dw;Q{\5A)X8]?r.C%8f 磖 hFw$9횵FC('vcClfE޸aP=:=[6peA=agnR3B~G 0lXAl1\ZNxhЫat^❣rؑɗ'q"7d]p8:XP(a=W9Qj' +cAO^c>^uʩ;hw o[32<ϊ.2/v(dc߰A^|9,|#+j ª.$Rݫ7__S&/r(gIH3\T4!;.qp~1,scxI_#TT75C\qIC!ær˚K;+^m$+o~y+OOnv.=\tcJ>?5{`-|sս>^65J]Nɯ>_[}7X< SӋ6/m6oJÑ6_O՛K'՗Sӫýgo-̿8{а/̟\_1}>s`j9_GÕەՆx՗ԏ`ᇮՍKsŧ_v.whS姙덵~6r>޺4^oW>__i^[F~j]_;5vW?]_=Xxy^r.5K[6/ReW;u("ñh {]=YG|n^vz^(XV/G/]q}[~2^xw'Xjj;3m<7?s7.px:Nx `}o-Ut]6gfW7k{k~FܺsMᐱyCv{u8W7>u:GKO?,?^_9xX$kdcr; 7Y~{NeSfͧfgä͗V5O7{[I#6݃֠{%g/o<ռyĜY <|zuz.̬SWdK/v7kųWSӷ'k:zk7O+Z;vW7 {suiݻ{V`Uo]_zz35p+wE$2]Y=X!g/2 4͑{ߏ#I|}ݵ;^wd)uibgzKMvW=z0~{M_a-:|ra2{֟ϼ׺_4\_m\KG/=g|iϪflyg;O&[]X:V vZ[o I}^!};l i +MMƐPXYد~zq)[up2}hkoy߅y؝{ߕdɲȮ9ù{4oFQ{zu땅;7ybygOv^?xb^Iӽd^U|sleݥRy󏖏_7ց?7aX޹vbT<lc[ RǶG7v|֣׿Rӥ̾J܁;3 $w0|7|fCt;X{_dRupiiyf;Y;o-|؉ + >w[ n-Z|^m.5?a1/O5R,R<姧kA <)e^\,|uWaWıv/Qb߾:{}[&3N6=Du".L>}>5ޯkՃՃǧKzqZc=[Q3y8}ljK>Xxbiwsa97:3tik{ևkf_ѝC1׌[G A'f/-~h?^.{y -6glObosC.|)?[n$^dwo>}xWѥq;2/u{{{@ݷb͛fV^ug+;f}߭}4lrk{fo>]ݽr)"{MR1Yl;@\^_YzoTōWgH-vrT-E.'g6APSivscשgwRc%;^}v'2eSW/RV^f(O ]i|f:lL7(.=Y}5\zZyduY._bߎtpR1OVʇսkrvtV>\|nѣ g;sk`f/vC_οY_MF==[7ﷁί>epݾqz}1~4{[t0&s䤿cxM̒qt|H>qT{ry}utOy.Q,d~ +-;W,ھs=y]i8qzoB@BB׏?I6nƔkٌh4ͭyu8-Y,-ns6H1l-R|5$I n͢bf*OQY{"Sz5d~ /c)3#SQB;++Oj#^&cؽ rV"Cg9]Q2k +c.fAFZx}wWXi_Xy3! oTcYI'=gظ>Mq彆=HOymbe3賌[^D7.z +ĜuLyEFwod<>%Ny{rԙKVcvL <F +F1k.5~i,XƌfPuVWDž(pzʌ +E).opZ15mlr8pdbyCxE0A,1gF?=m۩oGXuY*M)fHh,4t\^wx5 5{39Y?O+?i=^_i;Z "8V59W&uc8LTf/aI,C@Q +~j̸ Z2Dkڄǒq=6 yڒy1\fx׌oJcodgY̐ k)m$~K8,bX{?cv`Erh;F:>2gwdt}-O.t5ӫYLm3 ͵w{}/o okGKBPEٗef`C#I5~ndO0^ч!I;WrT#@ +i7e[Hg^dL/h2K`7 FwTRZ)`a*slk-gLYC&bE`;SïON3E&LJk?ګ=BC)HF`9;lcq4Bf·7{@~/::tX`3li˅#91c~ GLckM5/TJgfܥpcw`Os9Bϩ/BHxK!c/)d`/w|QBB\䥙yA__ħp&EPm'3 +,M*g;g\~|q Yl}˂'˧olhaX#P)W%e&}8Q*JT m3s`;~2J@be0IaVc{Jʿky|W|gyǸ=`gL&5=(Z_n||O5Q[_d ï`ʚq;l/i߁Q : 쭆 ~E 8=~6WGzٙ $t@˼,`. +k3`=sRJxcw0d + xm`jS5D,C̷̤u؂L2Eq.*b;!bϺ yO{6Bנi*A6G2O\k}HZzOߜD6xϢDڥs߻-YMǚM28vݟO8 g.3OL?aTi.hKKlRKOZ`>}gEW2@߳[#Nk%@&esV=)jM9?*`}%ZT顭@ͥ 0SH_8wSD)="Ys}0,a>aSˌ:bV$h\̌57bn޶o?|䀲1qt'mSSx웂x3Gz%]`bȉـ[1a\?a _Ukq1Jwcԩ<놘1La; }~ƶD +, +c5aAk +Kt#,mLurmW:VU41͂U6nxش^fEJb39bK#VTYlaG;bI&ZcBgԚ֖Z0IHKƠ Zɬ }m4yݝ6xk3â[~n_mm[ mt?vTF +ʓڟ& mm՟MMN[uFwtL:GݛTׯ)οtЗ.K*\JeXWܺoء,& &^7tdWcЭߓ k+/ɞۆم>Rbd0sTܡ/ַjU*ǬӀNa`;o%ddm61bH_uCvQ[ŰP9c1 ;kʈ&ni9iC`c?q`z[Ec\F{QNm{zu4xh;LcrNSō۔gj?5[(]iUʏLe, +)ί@ xhNgBshEsc]7ɧyVؖ k>&Z)1W*E,iRKչY:d2`EOj!Yƞvhν(Z3n&f>N&}gг7bHfd S[j?[&ڃ[;mGOcG쯎MϞ>d~σT)JWeۡ]7!bs#k;_Gӧ~X:%ze8s[P2ҫ9)6sοϥ-P.<)7tUG, ]@=]u8+N5uKQ| % y3تěEeĔHnu" 8IM62IKv,9}䮤3QT}Myݖ1T՗(P>Fnmk n1is_}FwkӺ;V=?xlKhl2i4]{vvk&^?1y3 Wx?w}־ XfeŎ!~cfpm)W\n/&nG$)~J b50Zz`_AO fYl;_mD#B&Nf3Tt5RRh.B ~:k,Z]|_'u1;d8bYogxۂس}$"oEk>2(яlƨÑ\F#oA-U=o'u> XlZnpSO<=~i{o"P;-O Y]b-J%d)4J;YWy; +35h/\Oto},S |L+C ZY?-oYl}TuuHneH>n曽d7,'lzc1(,ZH\a>9} T7ŭE[XI$ˍYM7{{ommOULd=+T%]5ퟪX_?*Ac}ټwG_{ޚknlֳi}XlokF5h4_Ӧk&z`5вVy)߶%Qwk W7hH ~;9^?M G?GpQ~4*m)Wp[ŸX?i8 ziiW7`_9r6QLFmlqOXD'X=USZޫik֪N>)'3wVUg g^ $}~Uڝ+F}S$ԍa-:Vrq-Z3Y~}w/ƿٲ5]uO|"k}di_s7,-Wtj}4nlXAcϮhcAk?+ ppwx=7"nVKeir8w[[ 2Y0JgCB%?kXA9%[3٢ w[tq'Z R =Q1 +d9{x»)i {ʅ1Lq[d +-̾_`[q +1{x]U@ʠq;ZGP,ύIa֛iܾ}+ĊCğ{m;3w+੏L ß5[3P-鰾J^g_*С*qNwk9l6fF\l,fDGZ:]߅~u7%5J':%+߀$S+}aKWZ%n-r3`2z扩m^o鞂MX\t_Ix&QT{KX|չJ—6¨!Yi6G6dK~DcT)iZ8m S\K Խ`*LJ=hUI2]h?X2&^_FOHV:*i zKtt%ӯJRBW)(Ytn7Jo}EV*`WgXIJ'x>nIW㦹Ej bu(Sia183MAx `VQAo m[}Ld*|Yf(Wi +/[T):5 ~oC&JNRB9ȢA[zd-[6J򢯽,*n_+-Qf&t[JU +t25j2 UvI@AeG岯],#SiߏJ~JO*jGyZ{C݆TmUARC@xҜFS锲&4JISĜ8U +jŕ60S1jOzD }hF0P yWPix +sZ/]i(:Dоu+ &RX S~LװR\T~o[D M,.IǧӒm%N+_!c^]E9ڟ3^ii9_6xP_K=\ʶ>m.Li? 9&|lOmNE&j PנIGitG:3|ܯ1߷>Mӹcy9$zjkQi*8ks]K3S/蟱>2CF1;$(`ۀ,SIoL}Y)\u0sXDG +47N7#\ePZ#땭O O-@;i۽VcE;J:IW~V +_Bdv:%SRwyu^3QURJ^h= *t_aRRdT +r:0Zj _Hs*UZ2Vl +R8B!y\= %1[yoxZs_Mn7Lw*W,cEgW;<M$s3XfGs"[l֡NuR4#@NZ d{)&iX3ũ&H7L>Wږ=s-^µ w*)XKq!@UP`zm3׃Q@<-%I5jȋod[(܁@[N5?LͼDLl4ǯ>~:VFƤzצԏ'P,b5%Q#gf7I'Wlw;%F<gPX.U0-T=\t?3mFZHn6 `v;b-ͻUr$5*:GE[5VgF4A!)WU׫yidFBA-M0@vv-; r>A:)aoޔCmw2_[,9LOF/rE jȶ'W=!&D}wÞ>=0uS| +dlI!3AfpKtw*Snp4(/j@Sj3`Fuؒ|}yx~PDzprA 'ٓ_Pj9Rb).A$YGK8 /).]RU!Q%.Yqk\"ɪ e6]kČnK(uo$qS +'|{DB*~DkGcPҭ +p庯O +d5;^UӛOV`JNbSȁ3*iؔw=cPnZmL"nZ"KYv]΋Ǯ/wxE'!AAҁ{@ih:ƌ85NΖ-t!-K*?~ +YǓ$h6e;uNx*Jy[靅aI>@iTn$ok s&NytT$G嬓os% No[D&d]B3TrDibHg|2F崪b% X vXTh4II0&{T59v޽b]h'H  Fy:k Mq<~(fǥ1HYEQAm]o <qXy}2ՐJ, y(5imjka7)YAV -1P4u:L{Y*<lE'U%Ng jJXd*9U5JD\L.fE.E<΂;|cumtLc85q DЉCwctH'?C'[)Bɢo)#hG0t:NA'@ >SF)o)#Z :l+@б;1t:d] fUSFږG]T4IӛmUʈwæ֯s@ /%ظO!@\XQv7kN18,uCk9y.zno JIR9ؗ@stMZ +: +BǏI6sWu:iT݄:$1cLmk`7O[A[kې @ +#& ".OlQΚdnY)R!7ALux}o%uckå+r6%f8ʚ](0$Ɓ]5TNboM_t<4MlJ_ \bRM:`z0%O-ϿQat:$4;CBī ǮDwhwqL%CK ٲ>m;ߥx9 KpE 1&3V9=vweSٓ# QĵQ8j5B#r6i]w2h]&{% +Yő''핂<\SG,睌Io6V.<"(axnc;0;q|Z\4hD[ y##h EPhp2__V$8&p4$<,a + sw:xdx@q Zq <2rkn\LE6 +aP$nωd] __ L޻t|"tA-x Wwse*թS +HNТ%U˳-Cw2 .<1ux']]=ZG[/+^ +* vhTez>1rT^H=ګ x/T0DλH'^P|*BnmMEpFT5n*کh\LQׂSyлgfJ;"q +R&p+hHt' q}ג)+Id'Zk@5ӯݥ@8%;OD$64}~[tRs.T N'(/餰t"tRxHGt0sVtRrF49 V> M'ҩM'k?g`Njth:);4NtMZ-{tRƩl4IDC=S.4m\4z=? MwnF)bV?M'Ed4i( h:) ܽ>MwdIh3tRg!{|6b7]$2I87Jd0߽es&)ϳ[tn%A$$d^5,T zkIjUrƒ9uSe&IRj>)]QpD QJbse-K)ix\4Is'] +2͝KNUr|2vj(zTQy8c('{8}NѶ{hPD8BEOSj50:yVҩh\GqZo"ܑu %Y]-P$KSe,u7yO%Bu%\u4 u5~Lu4 .[9龧 ? +gF_%U]"Ϙ])|ˎkK`m}[!$2F2ZF.YV6Xy5߫R H".#wr1)-KRӳ2U#bsySj7xasy'@y4[5M< n8-Vp &1 [* <g;+r1 %+[}[;%,hLdʻ'R)Q<)iNKR'ÝRW wjo5ǁg^UkfFC离X+F>zA|aY}=WzH)x2n/v<Vb\f˻.b⟊BaAP:}S cRb2(oScv#Ŏ,)hVPWܶ2hV3+ՀLw_ٹ $As'*"PN k)ܿܚtXyWSuۓ0]٫na=^ɔʛl +u+hjԳƕ(;~ 7RK"p)ݼPRQ[ތm^)[EL6E/<ȵ3 ;RNc8Z*U%L2x8<o Npϫ-9^_RmfK>S\6 W)\JдgR"IU1@s `x1kUR~K97R4W>*Ey9R\RbKtDvjĀ0OְK82QI\=>[qm1-]dkopL*مNe$`ǂNY̮NXtC"I mdF%@̂W2$Cd"3 ~KNt+44ItukX5ݜeQIQZ7Eii J$-㴘\ƊU +ӗ9SJyW__Ϻp^V{3L?r-I2.MZwzhBࣗJ'k+Na$HN27;0'ԛctbu=}eb?u'Uq.L'S#8x"iٔL7a7sk2*Z&Bjެ +ԫrR^Ki|eY:PG0Kfص,:&1VhUycW<;)<|cWı/C.,e29* Bt +Z ?Z Qj1k}7 +P * +;Lqm(@@ȱQ?cu+ +P-#߅i^IW'S푤|]x'Ied{NR>3l||j@Lnoո-X^?c"z< R+p^?e3GFn맜[~TS{}B^?~7 +Җyjy(ߥ+O[)wV):|Jw^V?{o)'}y8%AQ^?Eey,aH^ eV ;)waJOm+7Yʆy8$/pе2S:⠈| ^]ÇViJG|Z7*JP*Ut1&qo,X!12|DK}# ,+{GT;qs}nj(d"@i5;VSbsoqbɌ1˕ݻg43gѹ<{x_6z^4o]<ҷwWx/.zII7fIZ8C}~j5$bLaW7B}+>k$4[y]jM!yRy%L[r0 ee5ݎQCu$9/6tZ3Y:}-}B%lz_m$NjȖnurp Avz[th焻f0:ҚqΟ3ϊP@k؎4V$f\4Y9ܖNs.'*pWgA $JL\xLɰp~tpG3z~g+s3c,@elDe6e#NvaPAw~I;]F< +doO9GswjVdO?SUZ#>3Sк uZlEL6nDe0q1ӴFw?τF%B~gSpD'r$0g=@Sh,>h}P-LdgeʖZS+37ݵ%Ύ xttyYyYSsY_ j\ uWoq`W6nlspsg٪̱8hf=#vd$5̂eYvq,`{R CeBτS²@t]PLb5a$Z LL`*CYX OX,rBx0/OgW,v_:񱗋- 1lιΛ첫o w9xzÍ }a +fz0b^ 1_fhyג! 5=sE<7w3Fy0hރ&zN@c`}ggWmm cAd l6e1:$Aѽp=(-]0 ++$!m05'CWΰw7'+3Ւ.2V}ǡ";T;4Y4XrvTnʼnj~-_Ʌ7SIu~V493\r>]I_x8G 14N.|m_#WLCag sk Mp=vð, im9'r%< C{gktBC-7ӟ+irS|} +@<~8Rɫ1653i%۩1q5&huռes;z.Ov)TԚ--jcK}k;:4=HfffH ON` yF$];h3΁OCg$QC'َ^a?b+q'#,!Nd|O3ΔdV5c+cDBC[Όqtᅬ  KPnq`Կufo @);S +U*YY Z\SSNXK:³r-d8Gz\aBGP[mY5ڒ936@eiGSd~:G'}c9coEM\:VZ ) ҫ@T2[ƈ}c8w)hq5{"4CM4{s2>FDhE+O6ZcƭrA@s/#2QU:-=~5?޺;熟|`IT/Y;_77\MRGwBjt) Wԙk#@d:Y2 ̴N\?fP"HeݹwT6.980/L~cuOtynw!/?Ob2agr21,F_7?Ywɟs2 CC#f΀8GLL18$~@ *⦮ t,% nF3(rVA1NDǵnL^8TQ1}%pGO m6;4koOxof; f旰Id`|22=(c@1?&c%# +c$1Q3-̏Șj% Nels>2ȵ$EȘZْt&ĭBOn)JYru4yu+F-ojYnE%*kn6#."GgGb:4<Lm66P +mB%j3ŭIħ#XӖWV"> oRr˶R[~FQ\%ZkƙbASpP[ӝFi-%W= DV8vyh +`{y?BE`bO?IYCvl]Zo(&[g@goRسR[*ǀC6F0n6&#&l٧2[{yC@!rWs1h'@Y̍(1Dc!!sER%vOZrכ.)Jahs;^?*:o0v>R-[>VXUQKB5v hOp&ή6:RGm C+/vId|' Z._{cXNRh@nیdl@en LM-3nu)ߒɤ-iЋ=Yu zAm;M;j")GD1@I}~Pހ!qA TC:^KWCx}8% N +O8N9) +6Ƈ;Al%zJv7ѐ, µ祜'kfJAR/Art)J? +!|$;>/] +>{I,9 wxyN p(*>7>Ḣ6q$`p/jxCadZDYF5 5ދ.q5I?/陉f LII(n->4$&>x'5!# MN@jq l)K^o=ye@Ddđ+&Mƒ,@wӇS$K3  ^ad#\).7m#NV2BBঘ_<>Cd'f7/$d=g܀ + endstream endobj 50 0 obj <>stream +ā. 8AB&H%XJ 7` X˜W@s%x 8h򿒼Fc@A8h//Ts NISXkN pe@hA!ʅ_L|Sb-4"⨘]0&!酑_B+>]/}:ZbTy$Ey|  +Z{8~_ Cډ8m^>7/T#7VR0T'~}3כ8߂'/_` u1d4 endstream endobj 5 0 obj <> endobj 6 0 obj <> endobj 18 0 obj [/View/Design] endobj 19 0 obj <>>> endobj 16 0 obj [/View/Design] endobj 17 0 obj <>>> endobj 31 0 obj [30 0 R 29 0 R] endobj 51 0 obj <> endobj xref 0 52 0000000004 65535 f +0000000016 00000 n +0000000185 00000 n +0000047379 00000 n +0000000000 00000 f +0000266555 00000 n +0000266625 00000 n +0000000000 00000 f +0000047430 00000 n +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000266816 00000 n +0000266847 00000 n +0000266700 00000 n +0000266731 00000 n +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000050006 00000 n +0000050077 00000 n +0000266932 00000 n +0000047801 00000 n +0000053181 00000 n +0000050498 00000 n +0000050385 00000 n +0000048830 00000 n +0000049445 00000 n +0000049493 00000 n +0000050269 00000 n +0000050300 00000 n +0000050153 00000 n +0000050184 00000 n +0000050533 00000 n +0000053249 00000 n +0000053489 00000 n +0000054522 00000 n +0000069362 00000 n +0000134950 00000 n +0000200538 00000 n +0000266126 00000 n +0000266964 00000 n +trailer <<64A8AB8E858948269A0BCA92EF85B468>]>> startxref 267136 %%EOF \ No newline at end of file diff --git a/packages/web3-account-abstraction/assets/logo/web3js.jpg b/packages/web3-account-abstraction/assets/logo/web3js.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3b4cf23de26173be4d1375647c4864ebd77a4767 GIT binary patch literal 80258 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 + + + + + + + + + + + + + + + diff --git a/packages/web3-account-abstraction/package.json b/packages/web3-account-abstraction/package.json new file mode 100644 index 00000000000..efbaa27231c --- /dev/null +++ b/packages/web3-account-abstraction/package.json @@ -0,0 +1,65 @@ +{ + "name": "web3-account-abstraction", + "version": "0.1.0-rc.0", + "description": "Web3 account abstraction package", + "main": "./lib/commonjs/index.js", + "module": "./lib/esm/index.js", + "exports": { + ".": { + "types": "./lib/types/index.d.ts", + "import": "./lib/esm/index.js", + "require": "./lib/commonjs/index.js" + } + }, + "repository": "https://github.com/web3/web3.js", + "author": "ChainSafe Systems", + "license": "LGPL-3.0", + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + }, + "files": [ + "lib/**/*", + "src/**/*" + ], + "scripts": { + "clean": "rimraf dist && rimraf lib", + "prebuild": "yarn clean", + "build": "concurrently --kill-others-on-fail \"yarn:build:*(!check)\"", + "build:cjs": "tsc --build tsconfig.cjs.json && echo '{\"type\": \"commonjs\"}' > ./lib/commonjs/package.json", + "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 --cache --cache-strategy content --ext .ts .", + "lint:fix": "eslint --fix --ext .js,.ts .", + "format": "prettier --write '**/*'", + "test": "jest --config=./test/unit/jest.config.js", + "test:coverage:unit": "jest --config=./test/unit/jest.config.js --coverage=true --coverage-reporters=text", + "test:coverage:integration": "jest --config=./test/integration/jest.config.js --passWithNoTests --coverage=true --coverage-reporters=text", + "test:ci": "jest --coverage=true --coverage-reporters=json --verbose", + "test:watch": "npm test -- --watch", + "test:unit": "jest --config=./test/unit/jest.config.js", + "test:integration": "jest --config=./test/integration/jest.config.js --passWithNoTests" + }, + "devDependencies": { + "@types/jest": "^28.1.6", + "@typescript-eslint/eslint-plugin": "^5.30.7", + "@typescript-eslint/parser": "^5.30.7", + "eslint": "^8.20.0", + "eslint-config-base-web3": "0.1.0", + "eslint-config-prettier": "^8.5.0", + "eslint-plugin-import": "^2.26.0", + "jest": "^29.7.0", + "jest-extended": "^3.0.1", + "prettier": "^2.7.1", + "ts-jest": "^29.1.1", + "typescript": "^4.7.4" + }, + "dependencies": { + "web3-core": "^4.6.0", + "web3-types": "^1.8.0", + "web3-eth-abi": "^4.1.3", + "web3-utils": "^4.0.7", + "web3-validator": "^2.0.3" + } +} diff --git a/packages/web3-account-abstraction/src/index.ts b/packages/web3-account-abstraction/src/index.ts new file mode 100644 index 00000000000..c28fd333cc8 --- /dev/null +++ b/packages/web3-account-abstraction/src/index.ts @@ -0,0 +1,24 @@ +/* +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 { AccountAbstraction } from './web3_aa.js'; + +export * from './types.js'; +export * from './utils.js'; +export * from './web3_aa.js'; + +export default AccountAbstraction; diff --git a/packages/web3-account-abstraction/src/types.ts b/packages/web3-account-abstraction/src/types.ts new file mode 100644 index 00000000000..b6a4c408877 --- /dev/null +++ b/packages/web3-account-abstraction/src/types.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 { + Address, + Uint256, + HexStringBytes, + Uint, + HexString32Bytes, + TransactionHash, + LogAPI, + TransactionReceiptAPI, +} from 'web3-types'; + +export type ValidInputTypes = Uint8Array | bigint | string | number | boolean; + +export interface UserOperation { + sender: Address; + nonce: Uint256; + initCode: HexStringBytes; + callData: HexStringBytes; + callGasLimit?: Uint256; + verificationGasLimit: Uint256; + preVerificationGas: Uint256; + maxFeePerGas?: Uint256; + maxPriorityFeePerGas?: Uint256; + paymasterAndData: HexStringBytes; + signature: HexStringBytes; +} +export interface UserOperationRequire + extends Omit { + callGasLimit: Uint256; + maxFeePerGas: Uint256; + maxPriorityFeePerGas: Uint256; +} + +export interface IUserOperation { + readonly callData: HexStringBytes; + readonly callGasLimit: Uint; + readonly initCode: HexStringBytes; + readonly maxFeePerGas: Uint; + readonly maxPriorityFeePerGas: Uint; + readonly nonce: Uint; + readonly paymasterAndData: HexStringBytes; + readonly preVerificationGas: Uint; + readonly sender: Address; + readonly signature: HexStringBytes; + readonly verificationGasLimit: Uint; +} + +export interface GetUserOperationByHashAPI { + readonly blockHash: HexString32Bytes; + readonly blockNumber: Uint; + readonly entryPoint: Address; + readonly transactionHash: TransactionHash; + readonly userOperation: IUserOperation; +} + +export interface EstimateUserOperationGasAPI { + readonly preVerificationGas: Uint; + readonly verificationGasLimit: Uint; + readonly callGasLimit: Uint; +} + +export interface GetUserOperationReceiptAPI { + readonly userOpHash: HexString32Bytes; + readonly entryPoint: Address; + readonly sender: Address; + readonly nonce: Uint; + readonly paymaster: Address; + readonly actualGasCost: Uint; + readonly actualGasUsed: Uint; + readonly success: boolean; + readonly reason: HexStringBytes; + readonly logs: LogAPI[]; + readonly receipt: TransactionReceiptAPI; +} + +export type AARpcApi = { + eth_sendUserOperation: (userOperation: UserOperation, entryPoint: Address) => HexString32Bytes; + eth_estimateUserOperationGas: ( + userOperation: UserOperation, + entryPoint: Address, + ) => EstimateUserOperationGasAPI; + eth_getUserOperationByHash: (hash: HexStringBytes) => GetUserOperationByHashAPI; + eth_getUserOperationReceipt: (hash: HexStringBytes) => GetUserOperationReceiptAPI; + eth_supportedEntryPoints: () => Address[]; + generateUserOpHash: ( + userOp: UserOperationRequire, + entryPoint: string, + chainId: string, + ) => string; +}; diff --git a/packages/web3-account-abstraction/src/utils.ts b/packages/web3-account-abstraction/src/utils.ts new file mode 100644 index 00000000000..f92afee649a --- /dev/null +++ b/packages/web3-account-abstraction/src/utils.ts @@ -0,0 +1,97 @@ +/* +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 { Address, AbiInput, Uint256, HexStringBytes } from 'web3-types'; +import { encodeParameters } from 'web3-eth-abi'; +import { sha3 } from 'web3-utils'; +import { isHexStrict } from 'web3-validator'; +import { UserOperation, UserOperationRequire } from './types.js'; + +export const convertValuesToHex = (obj: Record): Record => { + const hexObj: Record = {}; + + Object.entries(obj).forEach(([key, value]) => { + if (typeof value === 'string') { + hexObj[key] = value.startsWith('0x') ? value : `0x${value}`; + } else if (typeof value === 'number' || typeof value === 'bigint') { + hexObj[key] = `0x${value.toString(16)}`; + } else if (typeof value === 'boolean') { + hexObj[key] = value ? '0x1' : '0x0'; + } else { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + hexObj[key] = value; + } + }); + + return hexObj; +}; + +const sha3Checked = (data: string): string => { + const result = sha3(data); + if (result === undefined) { + throw new Error('sha3 returned undefined'); + } + return result; +}; + +export const generateUserOpHash = ( + userOp: UserOperationRequire, + entryPoint: string, + chainId: string, +): string => { + const types: AbiInput[] = [ + 'address', + 'uint256', + 'bytes32', + 'bytes32', + 'uint256', + 'uint256', + 'uint256', + 'uint256', + 'uint256', + 'bytes32', + ]; + + const values: (Address | Uint256 | HexStringBytes)[] = [ + userOp.sender, + userOp.nonce, + sha3Checked(userOp.initCode), + sha3Checked(userOp.callData), + userOp.callGasLimit, + userOp.verificationGasLimit, + userOp.preVerificationGas, + userOp.maxFeePerGas, + userOp.maxPriorityFeePerGas, + sha3Checked(userOp.paymasterAndData), + ]; + + const packed: string = encodeParameters(types, values); + + const enctype: AbiInput[] = ['bytes32', 'address', 'uint256']; + const encValues: string[] = [sha3Checked(packed), entryPoint, chainId]; + const enc: string = encodeParameters(enctype, encValues); + + return sha3Checked(enc); +}; + +/** + * UserOperation a full user-operation struct. All fields MUST be set as hex values. empty bytes block (e.g. empty initCode) MUST be set to "0x" + * @param userOperation - represents the structure of a transaction initiated by the user. It contains the sender, receiver, call data, maximum fee per unit of Gas, maximum priority fee, signature, nonce, and other specific elements. + * @returns boolean + */ +export const isUserOperationAllHex = (userOperation: UserOperation): boolean => + Object.values(userOperation).every(isHexStrict); diff --git a/packages/web3-account-abstraction/src/web3_aa.ts b/packages/web3-account-abstraction/src/web3_aa.ts new file mode 100644 index 00000000000..fb81e6a8570 --- /dev/null +++ b/packages/web3-account-abstraction/src/web3_aa.ts @@ -0,0 +1,340 @@ +/* +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, Web3RequestManager, isSupportedProvider } from 'web3-core'; +import { Address, HexStringBytes, SupportedProviders } from 'web3-types'; + +import { AARpcApi, UserOperation, UserOperationRequire } from './types.js'; +import { convertValuesToHex, generateUserOpHash, isUserOperationAllHex } from './utils.js'; + +/** + * Account Abstraction feature allows enhancing user experience and security by allowing smart contracts to manage user accounts and transactions more flexibly. + * + * For using account abstraction functions, install `web3-account-abstraction` packages using: `npm i web3-account-abstraction` or `yarn add web3-account-abstraction`. + * + * ```ts + * import {AccountAbstraction} from 'web3-account-abstraction'; + * + * const aa = new AccountAbstraction('https://bundler-provider'); + * aa.supportedEntryPoints().then(console.log); + * ``` + */ +export class AccountAbstraction extends Web3Context { + // local package level request manager + private readonly bundlerRequestManager!: Web3RequestManager; + + public constructor(provider?: SupportedProviders | string) { + super(); + + // If "provider" is provided as "string" or an objects matching "SupportedProviders" interface + if ( + (typeof provider === 'string' && provider.trim() !== '') || + isSupportedProvider(provider as SupportedProviders) + ) { + this.bundlerRequestManager = new Web3RequestManager(provider); + } + } + /** + * Sends a UserOperation to the bundler. If accepted, the bundler will add it to the UserOperation mempool and return a userOpHash. + * + * @param UserOperation - represents the structure of a transaction initiated by the user. It contains the sender, receiver, call data, maximum fee per unit of Gas, maximum priority fee, signature, nonce, and other specific elements. + * @param entryPoint - a singleton contract to execute bundles of UserOperations. Bundlers/Clients whitelist the supported entrypoint. + * @returns userOperation hash or throws error instead of balance. + * @example + * ```ts + * sendUserOperation({ + * sender: "0x9fd042a18e90ce326073fa70f111dc9d798d9a52", + * nonce: "123", + * initCode: "0x68656c6c6f", + * callData: "0x776F726C64", + * callGasLimit: "1000", + * verificationGasLimit: "2300", + * preVerificationGas: "3100", + * maxFeePerGas: "8500", + * maxPriorityFeePerGas: "1", + * paymasterAndData: "0x626c6f63746f", + * signature: "0x636c656d656e74" + * },"0x636c656d656e74").then(console.log); + * > 0xe554d0701f7fdc734f84927d109537f1ac4ee4ebfa3670c71d224a4fa15dbcd1 + * ``` + */ + public async sendUserOperation(userOperation: UserOperation, entryPoint: Address) { + let userOp = { ...userOperation }; + const validator = isUserOperationAllHex(userOp); + if (!validator) { + userOp = convertValuesToHex(userOperation) as UserOperation; + } + return (this.bundlerRequestManager ?? this.requestManager).send({ + method: 'eth_sendUserOperation', + params: [userOp, entryPoint], + }); + } + /** + * Estimate the gas values for a UserOperation. Given UserOperation optionally without gas limits and gas prices, return the needed gas limits. The signature field is ignored by the wallet, so that the operation will not require user's approval. Still, it might require putting a "semi-valid" signature (e.g. a signature in the right length) + * + * @param UserOperation - represents the structure of a transaction initiated by the user. It contains the sender, receiver, call data, maximum fee per unit of Gas, maximum priority fee, signature, nonce, and other specific elements. + * @param entryPoint - a singleton contract to execute bundles of UserOperations. Bundlers/Clients whitelist the supported entrypoint. + * @returns - `preVerificationGas` gas overhead of this UserOperation + * - `verificationGasLimit` actual gas used by the validation of this UserOperation + * - `callGasLimit` value used by inner account execution + * @example + * ```ts + * estimateUserOperationGas({ + * sender: "0x9fd042a18e90ce326073fa70f111dc9d798d9a52", + * nonce: "123", + * initCode: "0x68656c6c6f", + * callData: "0x776F726C64", + * callGasLimit: "1000", + * verificationGasLimit: "2300", + * preVerificationGas: "3100", + * maxFeePerGas: "0", + * maxPriorityFeePerGas: "0", + * paymasterAndData: "0x626c6f63746f", + * signature: "0x636c656d656e74" + * },"0x636c656d656e74").then(console.log); + * > { + * callGasLimit : "0x18b33", + * preVerificationGas: "0xdf17", + * verificationGasLimit:"0x128c4" + * } + * ``` + */ + public async estimateUserOperationGas(userOperation: UserOperation, entryPoint: Address) { + const userOp = { ...userOperation }; + if (userOperation?.maxFeePerGas === undefined) { + userOp.maxFeePerGas = '0'; + } + if (userOperation?.maxPriorityFeePerGas === undefined) { + userOp.maxPriorityFeePerGas = '0'; + } + return (this.bundlerRequestManager ?? this.requestManager).send({ + method: 'eth_estimateUserOperationGas', + params: [userOp, entryPoint], + }); + } + /** + * Return a UserOperation based on a hash (userOpHash) returned by eth_sendUserOperation + * + * @param hash - a userOpHash value returned by `eth_sendUserOperation` + * @returns null in case the UserOperation is not yet included in a block, or a full UserOperation, with the addition of entryPoint, blockNumber, blockHash and transactionHash + * @example + * ```ts + * getUserOperationByHash("0xxxxx").then(console.log); + * > { + * userOperation: { + * sender: "xxxx", + * nonce: "xxxx", + * initCode: "0xxxxxxxxxxxxxxx", + * callData: "0xxxxxxxxxxxxxxx", + * callGasLimit: "xxxx", + * verificationGasLimit: "xxxx", + * preVerificationGas: "xxxx", + * maxFeePerGas: "0", + * maxPriorityFeePerGas: "0", + * paymasterAndData: "0xxxxxxxxxxxxxxx", + * signature: "0xxxxxxxxxxxxxxx" + * }, + * entryPoint: '0x5ff137d4b0fdcd49dca30c7cf57e578a026d2789', + * blockNumber: 39642225, + * blockHash: '0x638a175940cacb33f35e265961b164b14aa77477438340e635b227752f31981f', + * transactionHash: '0xc3e64ac247ae2343335596e106d1b97e35637656e1b99b37977a4165b34aeeb4', + * } + * ``` + */ + + public async getUserOperationByHash(hash: HexStringBytes) { + return (this.bundlerRequestManager ?? this.requestManager).send({ + method: 'eth_getUserOperationByHash', + params: [hash], + }); + } + /** + * Return null in case the UserOperation is not yet included in a block, or + * - userOpHash the request hash + * - entryPoint + * - sender + * - nonce + * - paymaster the paymaster used for this userOp (or empty) + * - actualGasCost - actual amount paid (by account or paymaster) for this UserOperation + * - actualGasUsed - total gas used by this UserOperation (including preVerification, creation, validation and execution) + * - success boolean - did this execution completed without revert + * - reason in case of revert, this is the revert reason + * - logs the logs generated by this UserOperation (not including logs of other UserOperations in the same bundle) + * - receipt the TransactionReceipt object. Note that the returned TransactionReceipt is for the entire bundle, not only for this UserOperation. + * + * @param hash - hash a userOpHash value returned by `eth_sendUserOperation` + * @returns null in case the UserOperation is not yet included in a block, or UserOperation + * @example + * ```ts + * getUserOperationReceipt("0xa890d7c0dccfd6cebc025919f4857ab97953ae218e82f5e24c297f02ceea5b21").then(console.log); + * >"userOpHash": "0xa890d7c0dccfd6cebc025919f4857ab97953ae218e82f5e24c297f02ceea5b21", + "entryPoint": "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789", + "sender": "0x026B37A09aF3ceB346c39999c5738F86A1a48f4d", + "nonce": "0x7", + "paymaster": "0xa312d8D37Be746BD09cBD9e9ba2ef16bc7Da48FF", + "actualGasCost": "0x1a036c1638be0", + "actualGasUsed": "0x2e8d8", + "success": true, + "reason": "", + "logs": [ + { + "address": "0x5ff137d4b0fdcd49dca30c7cf57e578a026d2789", + "topics": [ + "0xbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972" + ], + "data": "0x", + "blockHash": "0x638a175940cacb33f35e265961b164b14aa77477438340e635b227752f31981f", + "blockNumber": "0x25ce471", + "transactionHash": "0xc3e64ac247ae2343335596e106d1b97e35637656e1b99b37977a4165b34aeeb4", + "transactionIndex": "0x44", + "logIndex": "0x12d", + "removed": false + }, + { + "address": "0xfd8ec18d48ac1f46b600e231da07d1da8209ceef", + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000026b37a09af3ceb346c39999c5738f86a1a48f4d", + "0x000000000000000000000000000000000000000000000000000000000000007f" + ], + "data": "0x", + "blockHash": "0x638a175940cacb33f35e265961b164b14aa77477438340e635b227752f31981f", + "blockNumber": "0x25ce471", + "transactionHash": "0xc3e64ac247ae2343335596e106d1b97e35637656e1b99b37977a4165b34aeeb4", + "transactionIndex": "0x44", + "logIndex": "0x12e", + "removed": false + }, + { + "address": "0x00005ea00ac477b1030ce78506496e8c2de24bf5", + "topics": [ + "0xe90cf9cc0a552cf52ea6ff74ece0f1c8ae8cc9ad630d3181f55ac43ca076b7d6", + "0x000000000000000000000000fd8ec18d48ac1f46b600e231da07d1da8209ceef", + "0x000000000000000000000000026b37a09af3ceb346c39999c5738f86a1a48f4d", + "0x0000000000000000000000000000a26b00c1f0df003000390027140000faa719" + ], + "data": "0x000000000000000000000000026b37a09af3ceb346c39999c5738f86a1a48f4d0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e80000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x638a175940cacb33f35e265961b164b14aa77477438340e635b227752f31981f", + "blockNumber": "0x25ce471", + "transactionHash": "0xc3e64ac247ae2343335596e106d1b97e35637656e1b99b37977a4165b34aeeb4", + "transactionIndex": "0x44", + "logIndex": "0x12f", + "removed": false + }, + { + "address": "0x5ff137d4b0fdcd49dca30c7cf57e578a026d2789", + "topics": [ + "0x49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f", + "0xa890d7c0dccfd6cebc025919f4857ab97953ae218e82f5e24c297f02ceea5b21", + "0x000000000000000000000000026b37a09af3ceb346c39999c5738f86a1a48f4d", + "0x000000000000000000000000a312d8d37be746bd09cbd9e9ba2ef16bc7da48ff" + ], + "data": "0x000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000001a036c1638be0000000000000000000000000000000000000000000000000000000000002e8d8", + "blockHash": "0x638a175940cacb33f35e265961b164b14aa77477438340e635b227752f31981f", + "blockNumber": "0x25ce471", + "transactionHash": "0xc3e64ac247ae2343335596e106d1b97e35637656e1b99b37977a4165b34aeeb4", + "transactionIndex": "0x44", + "logIndex": "0x130", + "removed": false + } + ], + "receipt": { + "transactionHash": "0xc3e64ac247ae2343335596e106d1b97e35637656e1b99b37977a4165b34aeeb4", + "transactionIndex": "0x44", + "blockHash": "0x638a175940cacb33f35e265961b164b14aa77477438340e635b227752f31981f", + "blockNumber": "0x25ce471", + "from": "0x1e6754b227c6ae4b0ca61d82f79d60660737554a", + "to": "0x5ff137d4b0fdcd49dca30c7cf57e578a026d2789", + "cumulativeGasUsed": "0x1716d3b", + "gasUsed": "0x2b6c6", + "contractAddress": null, + "logs": [ + { + "address": "0xfd8ec18d48ac1f46b600e231da07d1da8209ceef", + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000026b37a09af3ceb346c39999c5738f86a1a48f4d", + "0x000000000000000000000000000000000000000000000000000000000000007f" + ], + "data": "0x", + "blockHash": "0x638a175940cacb33f35e265961b164b14aa77477438340e635b227752f31981f", + "blockNumber": "0x25ce471", + "transactionHash": "0xc3e64ac247ae2343335596e106d1b97e35637656e1b99b37977a4165b34aeeb4", + "transactionIndex": "0x44", + "logIndex": "0x12e", + "removed": false + }, + ], + "status": "0x1", + "logsBloom": "0x000000000000000000000000000000000008000000000000000000000000000000080000000000000002001108040020001080000000000000000200004000000000000000000000000800080000008000000000000000000001000208400040000000000a0008000000000000000800000000000000004080800010020100040000000000000000100000000000010000000000200080000000000000000000210000000000000000400080000000000000000000000000108002000004004008000002000000000001001000800000000001000000800000148040020020000000000000000000000001000000000100000000000000000000002000100000", + "type": "0x2", + "effectiveGasPrice": "0x59682f2e" + } + * ``` + */ + public async getUserOperationReceipt(hash: HexStringBytes) { + return (this.bundlerRequestManager ?? this.requestManager).send({ + method: 'eth_getUserOperationReceipt', + params: [hash], + }); + } + /** + * Returns an array of the entryPoint addresses supported by the client. The first element of the array SHOULD be the entryPoint addressed preferred by the client. + * @returns an array of the entryPoint addresses supported by the client. The first element of the array SHOULD be the entryPoint addressed preferred by the client. + * @example + * ```ts + * supportedEntryPoints().then(console.log); + * > ["0xcd01C8aa8995A59eB7B2627E69b40e0524B5ecf8", "0x7A0A0d159218E6a2f407B99173A2b12A6DDfC2a6"] + * ``` + */ + public async supportedEntryPoints() { + return (this.bundlerRequestManager ?? this.requestManager).send({ + method: 'eth_supportedEntryPoints', + params: [], + }); + } + + /** + * calculate UserOperationHash + * @param userOp - a structure that describes a transaction to be sent on behalf of a user. + * @param entryPoint - a singleton contract to execute bundles of UserOperations. Bundlers/Clients whitelist the supported entrypoint. + * @returns an array of the entryPoint addresses supported by the client. The first element of the array SHOULD be the entryPoint addressed preferred by the client. + * @example + * ```ts + * generateUserOpHash({ + * sender: "0x9fd042a18e90ce326073fa70f111dc9d798d9a52", + * nonce: "123", + * initCode: "0x68656c6c6f", + * callData: "0x776F726C64", + * callGasLimit: "1000", + * verificationGasLimit: "2300", + * preVerificationGas: "3100", + * maxFeePerGas: "0", + * maxPriorityFeePerGas: "0", + * paymasterAndData: "0x626c6f63746f", + * signature: "0x636c656d656e74" + * },"0x636c656d656e74", '0x1').then(console.log); + * > 0xxxx + * ``` + */ + // eslint-disable-next-line class-methods-use-this + public generateUserOpHash(userOp: UserOperationRequire, entryPoint: string, chainId: string) { + return generateUserOpHash(userOp, entryPoint, chainId); + } +} diff --git a/packages/web3-account-abstraction/test/.eslintrc.js b/packages/web3-account-abstraction/test/.eslintrc.js new file mode 100644 index 00000000000..a98dfb6d823 --- /dev/null +++ b/packages/web3-account-abstraction/test/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + extends: '../../../.eslintrc.test.js', + parserOptions: { + project: './tsconfig.json', + tsconfigRootDir: __dirname, + }, +}; diff --git a/packages/web3-account-abstraction/test/config/jest.config.js b/packages/web3-account-abstraction/test/config/jest.config.js new file mode 120000 index 00000000000..b875b48129d --- /dev/null +++ b/packages/web3-account-abstraction/test/config/jest.config.js @@ -0,0 +1 @@ +../../../../templates/jest.config.js.tmpl \ No newline at end of file diff --git a/packages/web3-account-abstraction/test/config/setup.js b/packages/web3-account-abstraction/test/config/setup.js new file mode 100644 index 00000000000..0b6b9109ce0 --- /dev/null +++ b/packages/web3-account-abstraction/test/config/setup.js @@ -0,0 +1,24 @@ +/* +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 . +*/ + +// Have to use `require` because of Jest issue https://jestjs.io/docs/ecmascript-modules +// eslint-disable-next-line @typescript-eslint/no-require-imports +require('jest-extended'); + +// @todo extend jest to have "toHaveBeenCalledOnceWith" matcher. + +process.env.NODE_ENV = 'test'; diff --git a/packages/web3-account-abstraction/test/integration/jest.config.js b/packages/web3-account-abstraction/test/integration/jest.config.js new file mode 100644 index 00000000000..1d95890206a --- /dev/null +++ b/packages/web3-account-abstraction/test/integration/jest.config.js @@ -0,0 +1,33 @@ +'use strict'; + +const base = require('../config/jest.config'); + +module.exports = { + ...base, + setupFilesAfterEnv: ['/test/integration/setup.js'], + testMatch: ['/test/integration/**/*.(spec|test).(js|ts)'], + /** + * restoreMocks [boolean] + * + * Default: false + * + * Automatically restore mock state between every test. + * Equivalent to calling jest.restoreAllMocks() between each test. + * This will lead to any mocks having their fake implementations removed + * and restores their initial implementation. + */ + restoreMocks: true, + + /** + * resetModules [boolean] + * + * Default: false + * + * By default, each test file gets its own independent module registry. + * Enabling resetModules goes a step further and resets the module registry before running each individual test. + * This is useful to isolate modules for every test so that local module state doesn't conflict between tests. + * This can be done programmatically using jest.resetModules(). + */ + resetModules: true, + coverageDirectory: '.coverage/integration', +}; diff --git a/packages/web3-account-abstraction/test/integration/setup.js b/packages/web3-account-abstraction/test/integration/setup.js new file mode 100644 index 00000000000..5be1bccf7cc --- /dev/null +++ b/packages/web3-account-abstraction/test/integration/setup.js @@ -0,0 +1,24 @@ +/* +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 . +*/ + +// Have to use `require` because of Jest issue https://jestjs.io/docs/ecmascript-modules +// eslint-disable-next-line @typescript-eslint/no-require-imports +require('../config/setup'); + +const jestTimeout = 15000; + +jest.setTimeout(jestTimeout); diff --git a/packages/web3-account-abstraction/test/tsconfig.json b/packages/web3-account-abstraction/test/tsconfig.json new file mode 120000 index 00000000000..c73c54e77b4 --- /dev/null +++ b/packages/web3-account-abstraction/test/tsconfig.json @@ -0,0 +1 @@ +../../../templates/test/tsconfig.json.tmpl \ No newline at end of file diff --git a/packages/web3-account-abstraction/test/unit/account_abstraction.test.ts b/packages/web3-account-abstraction/test/unit/account_abstraction.test.ts new file mode 100644 index 00000000000..7afb15fbb4e --- /dev/null +++ b/packages/web3-account-abstraction/test/unit/account_abstraction.test.ts @@ -0,0 +1,184 @@ +/* +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 { AccountAbstraction, UserOperation, UserOperationRequire } from '../../src/index.js'; + +describe('AccountAbstraction tests', () => { + const web3aa = new AccountAbstraction('http://127.0.0.1:8555/'); + let sendSpy: jest.SpyInstance; + const requestManagerSendSpy = jest.fn(); + + beforeAll(() => { + // spy on private member so using any in tests only + (web3aa as any).bundlerRequestManager.send = requestManagerSendSpy; + }); + + it('should have requestManager defined with context', () => { + expect(web3aa.requestManager).toBeDefined(); + }); + + describe('AccountAbstraction method tests', () => { + let userOperation: UserOperation | UserOperationRequire; + + beforeEach(() => { + userOperation = { + sender: '0x9fd042a18e90ce326073fa70f111dc9d798d9a52', + nonce: '123', + initCode: '0x68656c6c6f', + callData: '0x776F726C64', + callGasLimit: '1000', + verificationGasLimit: '2300', + preVerificationGas: '3100', + maxFeePerGas: '8500', + maxPriorityFeePerGas: '1', + paymasterAndData: '0x626c6f63746f', + signature: '0x636c656d656e74', + }; + sendSpy = jest.spyOn(web3aa, 'sendUserOperation').mockImplementation(); + }); + + afterEach(() => { + sendSpy.mockRestore(); + }); + + it('should call rpcMethods.sendUserOperation with expected parameters', async () => { + const entryPoint = '0x636c656d656e74'; + await web3aa.sendUserOperation(userOperation, entryPoint); + expect(sendSpy).toHaveBeenCalledWith(userOperation, entryPoint); + }); + + it('should call rpcMethods.estimateUserOperationGas with expected parameters', async () => { + const entryPoint = '0x636c656d656e74'; + const estimateSpy = jest.spyOn(web3aa, 'estimateUserOperationGas').mockImplementation(); + await web3aa.estimateUserOperationGas(userOperation, entryPoint); + expect(estimateSpy).toHaveBeenCalledWith(userOperation, entryPoint); + estimateSpy.mockRestore(); + }); + + it('should call rpcMethods.estimateUserOperationGas should set maxFeePerGas to "0" if not provided', async () => { + const entryPoint = '0x636c656d656e74'; + const userOperationWithoutMaxFee = { + ...userOperation, + maxFeePerGas: undefined, + }; + await web3aa.estimateUserOperationGas(userOperationWithoutMaxFee, entryPoint); + + expect(requestManagerSendSpy).toHaveBeenCalledWith({ + method: 'eth_estimateUserOperationGas', + params: [ + { + ...userOperationWithoutMaxFee, + maxFeePerGas: '0', // Ensure it's set to "0" + }, + entryPoint, + ], + }); + }); + + it('should call rpcMethods.estimateUserOperationGas should set maxPriorityFeePerGas to "0" if not provided', async () => { + const entryPoint = '0x636c656d656e74'; + const userOperationWithoutMaxFee = { + ...userOperation, + maxPriorityFeePerGas: undefined, + }; + await web3aa.estimateUserOperationGas(userOperationWithoutMaxFee, entryPoint); + + expect(requestManagerSendSpy).toHaveBeenCalledWith({ + method: 'eth_estimateUserOperationGas', + params: [ + { + ...userOperationWithoutMaxFee, + maxPriorityFeePerGas: '0', // Ensure it's set to "0" + }, + entryPoint, + ], + }); + }); + + it('should call rpcMethods.getUserOperationByHash with expected parameters', async () => { + const hash = '0xa890d7c0dccfd6cebc025919f4857ab97953ae218e82f5e24c297f02ceea5b21'; + const estimateSpy = jest.spyOn(web3aa, 'getUserOperationByHash').mockImplementation(); + await web3aa.getUserOperationByHash(hash); + expect(estimateSpy).toHaveBeenCalledWith(hash); + estimateSpy.mockRestore(); + }); + + it('should call rpcMethods.getUserOperationReceipt with expected parameters', async () => { + const hash = '0x123456789abcdef0123456789abcdef012345678'; + const estimateSpy = jest.spyOn(web3aa, 'getUserOperationReceipt').mockImplementation(); + await web3aa.getUserOperationReceipt(hash); + expect(estimateSpy).toHaveBeenCalledWith(hash); + estimateSpy.mockRestore(); + }); + + it('should call rpcMethods.supportedEntryPoints with expected parameters', async () => { + const supportedEntryPointsSendSpy = jest + .spyOn((web3aa as any).bundlerRequestManager, 'send') + .mockResolvedValue([ + '0xcd01C8aa8995A59eB7B2627E69b40e0524B5ecf8', + '0x7A0A0d159218E6a2f407B99173A2b12A6DDfC2a6', + ]); + + const result = await web3aa.supportedEntryPoints(); + + expect(supportedEntryPointsSendSpy).toHaveBeenCalledWith({ + method: 'eth_supportedEntryPoints', + params: [], + }); + expect(result).toEqual([ + '0xcd01C8aa8995A59eB7B2627E69b40e0524B5ecf8', + '0x7A0A0d159218E6a2f407B99173A2b12A6DDfC2a6', + ]); + }); + + it('should call rpcMethods.generateUserOpHash with expected parameters', () => { + const entryPoint = '0xaE036c65C649172b43ef7156b009c6221B596B8b'; + const chainId = '0x1'; + const expectedResult = + '0xe554d0701f7fdc734f84927d109537f1ac4ee4ebfa3670c71d224a4fa15dbcd1'; + const result = web3aa.generateUserOpHash( + userOperation as UserOperationRequire, + entryPoint, + chainId, + ); + + expect(result).toEqual(expectedResult); + }); + it('should call rpcMethods.generateUserOpHash with throws an error when sha3 returns undefined', () => { + const userOp = { + sender: '0x9fd042a18e90ce326073fa70f111dc9d798d9a52', + nonce: '123', + initCode: '', + callData: '0x776F726C64', + callGasLimit: '1000', + verificationGasLimit: '2300', + preVerificationGas: '3100', + maxFeePerGas: '8500', + maxPriorityFeePerGas: '1', + paymasterAndData: '0x626c6f63746f', + signature: '0x636c656d656e74', + }; + const entryPoint = '0xaE036c65C649172b43ef7156b009c6221B596B8b'; + const chainId = '0x1'; + + // Expect an error to be thrown + expect(() => web3aa.generateUserOpHash(userOp, entryPoint, chainId)).toThrow( + 'sha3 returned undefined', + ); + }); + }); +}); diff --git a/packages/web3-account-abstraction/test/unit/jest.config.js b/packages/web3-account-abstraction/test/unit/jest.config.js new file mode 100644 index 00000000000..ceac341e332 --- /dev/null +++ b/packages/web3-account-abstraction/test/unit/jest.config.js @@ -0,0 +1,9 @@ +const base = require('../config/jest.config'); + +module.exports = { + ...base, + testMatch: ['/test/unit/**/*.(spec|test).(js|ts)'], + + coverageDirectory: '.coverage/unit', + collectCoverageFrom: ['src/**'], +}; diff --git a/packages/web3-account-abstraction/tsconfig.cjs.json b/packages/web3-account-abstraction/tsconfig.cjs.json new file mode 120000 index 00000000000..f8b17044cd5 --- /dev/null +++ b/packages/web3-account-abstraction/tsconfig.cjs.json @@ -0,0 +1 @@ +../../config/tsconfig.cjs.json \ No newline at end of file diff --git a/packages/web3-account-abstraction/tsconfig.esm.json b/packages/web3-account-abstraction/tsconfig.esm.json new file mode 120000 index 00000000000..f5fab722b38 --- /dev/null +++ b/packages/web3-account-abstraction/tsconfig.esm.json @@ -0,0 +1 @@ +../../config/tsconfig.esm.json \ No newline at end of file diff --git a/packages/web3-account-abstraction/tsconfig.types.json b/packages/web3-account-abstraction/tsconfig.types.json new file mode 120000 index 00000000000..c67a7816f18 --- /dev/null +++ b/packages/web3-account-abstraction/tsconfig.types.json @@ -0,0 +1 @@ +../../config/tsconfig.types.json \ No newline at end of file diff --git a/packages/web3-account-abstraction/tsdoc.json b/packages/web3-account-abstraction/tsdoc.json new file mode 100644 index 00000000000..776fc76a3d3 --- /dev/null +++ b/packages/web3-account-abstraction/tsdoc.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", + "extends": ["../../tsdoc.json"] +} diff --git a/scripts/docshelper/classesdoc.config.js b/scripts/docshelper/classesdoc.config.js index 1c8a9d45cb2..b630f580cf9 100644 --- a/scripts/docshelper/classesdoc.config.js +++ b/scripts/docshelper/classesdoc.config.js @@ -1,20 +1,20 @@ const baseDocConfig = require('./base.config.js'); module.exports = { - ... baseDocConfig, + ...baseDocConfig, - entryPoints: [ - "./packages/web3-eth/src/web3_eth.ts", - "./packages/web3-eth-accounts/src/wallet.ts", - "./packages/web3-eth-accounts/src/account.ts", - "./packages/web3-eth-contract/src/contract.ts", - "./packages/web3-eth-ens/src/ens.ts", - "./packages/web3-eth-iban/src/iban.ts", - "./packages/web3-eth-personal/src/personal.ts", - "./packages/web3-net/src/net.ts", - ], - - excludeCategories: "ContractEvent", // for exluding being in module.md file and invalid link in contract.md - mergeModulesMergeMode: "project", // NEW option of TypeDoc added by typedoc-plugin-merge-modules plugin + entryPoints: [ + './packages/web3-eth/src/web3_eth.ts', + './packages/web3-eth-accounts/src/wallet.ts', + './packages/web3-eth-accounts/src/account.ts', + './packages/web3-eth-contract/src/contract.ts', + './packages/web3-eth-ens/src/ens.ts', + './packages/web3-eth-iban/src/iban.ts', + './packages/web3-eth-personal/src/personal.ts', + './packages/web3-net/src/net.ts', + './packages/web3-account-abstraction/src/web3_aa.ts', + ], + excludeCategories: 'ContractEvent', // for exluding being in module.md file and invalid link in contract.md + mergeModulesMergeMode: 'project', // NEW option of TypeDoc added by typedoc-plugin-merge-modules plugin }; From 3687070dc165d414a0e7f2cbed91cd448b8da13a Mon Sep 17 00:00:00 2001 From: Muhammad Altabba <24407834+Muhammad-Altabba@users.noreply.github.com> Date: Tue, 22 Oct 2024 13:49:41 +0200 Subject: [PATCH 173/186] make `decodeFunctionCall` and `decodeFunctionReturn` available at `web3-eth-abi` (#7345) * move `decodeFunctionCall` and `decodeFunctionReturn` to web3-eth-abi * add unit tests * update CHANGELOG.md * add functions docs --- packages/web3-eth-abi/CHANGELOG.md | 4 + .../web3-eth-abi/src/api/functions_api.ts | 145 +++++++++++- .../unit/decodeMethodParamsAndReturn.test.ts | 217 ++++++++++++++++++ .../src/contract-deployer-method-class.ts | 5 +- packages/web3-eth-contract/src/contract.ts | 15 +- packages/web3-eth-contract/src/encoding.ts | 48 +--- 6 files changed, 378 insertions(+), 56 deletions(-) create mode 100644 packages/web3-eth-abi/test/unit/decodeMethodParamsAndReturn.test.ts diff --git a/packages/web3-eth-abi/CHANGELOG.md b/packages/web3-eth-abi/CHANGELOG.md index 9cb5bd2d7b9..7a6951386d9 100644 --- a/packages/web3-eth-abi/CHANGELOG.md +++ b/packages/web3-eth-abi/CHANGELOG.md @@ -195,3 +195,7 @@ Documentation: - `decodeLog` , `decodeParametersWith` , `decodeParameters` and `decodeParameters` now accepts first immutable param as well (#7288) ## [Unreleased] + +### Added + +- added `decodeFunctionCall` and `decodeFunctionReturn`. (#7345) diff --git a/packages/web3-eth-abi/src/api/functions_api.ts b/packages/web3-eth-abi/src/api/functions_api.ts index 7504f352275..8518deeab24 100644 --- a/packages/web3-eth-abi/src/api/functions_api.ts +++ b/packages/web3-eth-abi/src/api/functions_api.ts @@ -19,11 +19,11 @@ along with web3.js. If not, see . * * @module ABI */ -import { AbiError } from 'web3-errors'; +import { AbiError, Web3ContractError } from 'web3-errors'; import { sha3Raw } from 'web3-utils'; -import { AbiFunctionFragment } from 'web3-types'; +import { AbiConstructorFragment, AbiFunctionFragment, DecodedParams, HexString } from 'web3-types'; import { isAbiFunctionFragment, jsonInterfaceMethodToString } from '../utils.js'; -import { encodeParameters } from './parameters_api.js'; +import { decodeParameters, encodeParameters } from './parameters_api.js'; /** * Encodes the function name to its ABI representation, which are the first 4 bytes of the sha3 of the function name including types. @@ -143,3 +143,142 @@ export const encodeFunctionCall = ( params ?? [], ).replace('0x', '')}`; }; + +/** + * Decodes a function call data using its `JSON interface` object. + * The JSON interface spec documentation https://docs.soliditylang.org/en/latest/abi-spec.html#json + * @param functionsAbi - The `JSON interface` object of the function. + * @param data - The data to decode + * @param methodSignatureProvided - (Optional) if `false` do not remove the first 4 bytes that would rather contain the function signature. + * @returns - The data decoded according to the passed ABI. + * @example + * ```ts + * const data = + * '0xa413686200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000548656c6c6f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010416e6f74686572204772656574696e6700000000000000000000000000000000'; + * const params = decodeFunctionCall( + * { + * inputs: [ + * { internalType: 'string', name: '_greeting', type: 'string' }, + * { internalType: 'string', name: '_second_greeting', type: 'string' }, + * ], + * name: 'setGreeting', + * outputs: [ + * { internalType: 'bool', name: '', type: 'bool' }, + * { internalType: 'string', name: '', type: 'string' }, + * ], + * stateMutability: 'nonpayable', + * type: 'function', + * }, + * data, + * ); + + * console.log(params); + * > { + * > '0': 'Hello', + * > '1': 'Another Greeting', + * > __length__: 2, + * > __method__: 'setGreeting(string,string)', + * > _greeting: 'Hello', + * > _second_greeting: 'Another Greeting', + * > } + * ``` + */ +export const decodeFunctionCall = ( + functionsAbi: AbiFunctionFragment | AbiConstructorFragment, + data: HexString, + methodSignatureProvided = true, +): DecodedParams & { __method__: string } => { + const value = + methodSignatureProvided && data && data.length >= 10 && data.startsWith('0x') + ? data.slice(10) + : data; + if (!functionsAbi.inputs) { + throw new Web3ContractError('No inputs found in the ABI'); + } + const result = decodeParameters([...functionsAbi.inputs], value); + return { + ...result, + __method__: jsonInterfaceMethodToString(functionsAbi), + }; +}; + +/** + * Decodes a function call data using its `JSON interface` object. + * The JSON interface spec documentation https://docs.soliditylang.org/en/latest/abi-spec.html#json + * @returns - The ABI encoded function call, which, means the function signature and the parameters passed. + * @param functionsAbi - The `JSON interface` object of the function. + * @param returnValues - The data (the function-returned-values) to decoded + * @returns - The function-returned-values decoded according to the passed ABI. If there are multiple values, it returns them as an object as the example below. But if it is a single value, it returns it only for simplicity. + * @example + * ```ts + * // decode a multi-value data of a method + * const data = + * '0x00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000548656c6c6f000000000000000000000000000000000000000000000000000000'; + * const decodedResult = decodeFunctionReturn( + * { + * inputs: [ + * { internalType: 'string', name: '_greeting', type: 'string' } + * ], + * name: 'setGreeting', + * outputs: [ + * { internalType: 'string', name: '', type: 'string' }, + * { internalType: 'bool', name: '', type: 'bool' }, + * ], + * stateMutability: 'nonpayable', + * type: 'function', + * }, + * data, + * ); + + * console.log(decodedResult); + * > { '0': 'Hello', '1': true, __length__: 2 } + * + * + * // decode a single-value data of a method + * const data = + * '0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000548656c6c6f000000000000000000000000000000000000000000000000000000'; + * const decodedResult = decodeFunctionReturn( + * { + * inputs: [ + * { internalType: 'string', name: '_greeting', type: 'string' } + * ], + * name: 'setGreeting', + * outputs: [{ internalType: 'string', name: '', type: 'string' }], + * stateMutability: 'nonpayable', + * type: 'function', + * }, + * data, + * ); + + * console.log(decodedResult); + * > 'Hello' + * ``` + */ +export const decodeFunctionReturn = ( + functionsAbi: AbiFunctionFragment, + returnValues?: HexString, +) => { + // If it is a constructor there is nothing to decode! + if (functionsAbi.type === 'constructor') { + return returnValues; + } + + if (!returnValues) { + // Using "null" value intentionally to match legacy behavior + // eslint-disable-next-line no-null/no-null + return null; + } + + const value = returnValues.length >= 2 ? returnValues.slice(2) : returnValues; + if (!functionsAbi.outputs) { + // eslint-disable-next-line no-null/no-null + return null; + } + const result = decodeParameters([...functionsAbi.outputs], value); + + if (result.__length__ === 1) { + return result[0]; + } + + return result; +}; diff --git a/packages/web3-eth-abi/test/unit/decodeMethodParamsAndReturn.test.ts b/packages/web3-eth-abi/test/unit/decodeMethodParamsAndReturn.test.ts new file mode 100644 index 00000000000..acf96c2aa41 --- /dev/null +++ b/packages/web3-eth-abi/test/unit/decodeMethodParamsAndReturn.test.ts @@ -0,0 +1,217 @@ +/* +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 { AbiFunctionFragment } from 'web3-types'; +import { decodeFunctionCall, decodeFunctionReturn } from '../../src'; + +describe('decodeFunctionCall and decodeFunctionReturn tests should pass', () => { + it('decodeFunctionCall should decode single-value data of a method', async () => { + const data = + '0xa41368620000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000548656c6c6f000000000000000000000000000000000000000000000000000000'; + + const params = decodeFunctionCall( + { + inputs: [{ internalType: 'string', name: '_greeting', type: 'string' }], + name: 'setGreeting', + outputs: [ + { internalType: 'bool', name: '', type: 'bool' }, + { internalType: 'string', name: '', type: 'string' }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + data, + ); + + expect(params).toMatchObject({ + __method__: 'setGreeting(string)', + __length__: 1, + '0': 'Hello', + _greeting: 'Hello', + }); + }); + + it('decodeFunctionCall should decode data of a method without removing the method signature (if intended)', async () => { + const data = + '0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000548656c6c6f000000000000000000000000000000000000000000000000000000'; + + const params = decodeFunctionCall( + { + inputs: [{ internalType: 'string', name: '_greeting', type: 'string' }], + name: 'setGreeting', + outputs: [ + { internalType: 'bool', name: '', type: 'bool' }, + { internalType: 'string', name: '', type: 'string' }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + data, + false, + ); + + expect(params).toMatchObject({ + __method__: 'setGreeting(string)', + __length__: 1, + '0': 'Hello', + _greeting: 'Hello', + }); + }); + + it('decodeFunctionCall should throw if no inputs at the ABI', async () => { + const data = + '0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000548656c6c6f000000000000000000000000000000000000000000000000000000'; + + expect(() => + decodeFunctionCall( + { + name: 'setGreeting', + // no `inputs` provided! + outputs: [ + { internalType: 'bool', name: '', type: 'bool' }, + { internalType: 'string', name: '', type: 'string' }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + data, + false, + ), + ).toThrow('No inputs found in the ABI'); + }); + + it('decodeFunctionCall should decode multi-value data of a method', async () => { + const data = + '0xa413686200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000548656c6c6f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010416e6f74686572204772656574696e6700000000000000000000000000000000'; + + const params = decodeFunctionCall( + { + inputs: [ + { internalType: 'string', name: '_greeting', type: 'string' }, + { internalType: 'string', name: '_second_greeting', type: 'string' }, + ], + name: 'setGreeting', + outputs: [ + { internalType: 'bool', name: '', type: 'bool' }, + { internalType: 'string', name: '', type: 'string' }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + data, + ); + + expect(params).toEqual({ + '0': 'Hello', + '1': 'Another Greeting', + __length__: 2, + __method__: 'setGreeting(string,string)', + _greeting: 'Hello', + _second_greeting: 'Another Greeting', + }); + }); + + it('decodeFunctionReturn should decode single-value data of a method', async () => { + const data = + '0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000548656c6c6f000000000000000000000000000000000000000000000000000000'; + + const decodedResult = decodeFunctionReturn( + { + inputs: [{ internalType: 'string', name: '_greeting', type: 'string' }], + name: 'setGreeting', + outputs: [{ internalType: 'string', name: '', type: 'string' }], + stateMutability: 'nonpayable', + type: 'function', + }, + data, + ); + + expect(decodedResult).toBe('Hello'); + }); + + it('decodeFunctionReturn should decode multi-value data of a method', async () => { + const data = + '0x00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000548656c6c6f000000000000000000000000000000000000000000000000000000'; + + const decodedResult = decodeFunctionReturn( + { + inputs: [{ internalType: 'string', name: '_greeting', type: 'string' }], + name: 'setGreeting', + outputs: [ + { internalType: 'string', name: '', type: 'string' }, + { internalType: 'bool', name: '', type: 'bool' }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + data, + ); + + expect(decodedResult).toEqual({ '0': 'Hello', '1': true, __length__: 2 }); + }); + + it('decodeFunctionReturn should decode nothing if it is called on a constructor', async () => { + const data = 'anything passed should be returned as-is'; + + const decodedResult = decodeFunctionReturn( + { + inputs: [{ internalType: 'string', name: '_greeting', type: 'string' }], + stateMutability: 'nonpayable', + type: 'constructor', + } as unknown as AbiFunctionFragment, + data, + ); + + expect(decodedResult).toEqual(data); + }); + + it('decodeFunctionReturn should return `null` if no values passed', async () => { + const data = ''; + + const decodedResult = decodeFunctionReturn( + { + inputs: [{ internalType: 'string', name: '_greeting', type: 'string' }], + name: 'setGreeting', + outputs: [ + { internalType: 'string', name: '', type: 'string' }, + { internalType: 'bool', name: '', type: 'bool' }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + data, + ); + + expect(decodedResult).toBeNull(); + }); + + it('decodeFunctionReturn should return `null` if no function output provided', async () => { + const data = '0x000000'; + + const decodedResult = decodeFunctionReturn( + { + inputs: [{ internalType: 'string', name: '_greeting', type: 'string' }], + name: 'setGreeting', + stateMutability: 'nonpayable', + type: 'function', + }, + data, + ); + + expect(decodedResult).toBeNull(); + }); +}); diff --git a/packages/web3-eth-contract/src/contract-deployer-method-class.ts b/packages/web3-eth-contract/src/contract-deployer-method-class.ts index 33018541390..08d04b16c8f 100644 --- a/packages/web3-eth-contract/src/contract-deployer-method-class.ts +++ b/packages/web3-eth-contract/src/contract-deployer-method-class.ts @@ -17,6 +17,7 @@ along with web3.js. If not, see . import { Web3ContractError } from 'web3-errors'; import { sendTransaction, SendTransactionEvents, SendTransactionOptions } from 'web3-eth'; +import { decodeFunctionCall } from 'web3-eth-abi'; import { AbiConstructorFragment, AbiFunctionFragment, @@ -34,7 +35,7 @@ import { import { format } from 'web3-utils'; import { isNullish } from 'web3-validator'; import { Web3PromiEvent } from 'web3-core'; -import { decodeMethodParams, encodeMethodABI } from './encoding.js'; +import { encodeMethodABI } from './encoding.js'; import { NonPayableTxOptions, PayableTxOptions } from './types.js'; import { getSendTxParams } from './utils.js'; // eslint-disable-next-line import/no-cycle @@ -209,7 +210,7 @@ export class DeployerMethodClass { public decodeData(data: HexString) { return { - ...decodeMethodParams( + ...decodeFunctionCall( this.constructorAbi, data.replace(this.deployData as string, ''), false, diff --git a/packages/web3-eth-contract/src/contract.ts b/packages/web3-eth-contract/src/contract.ts index a99dc27628e..60602497e65 100644 --- a/packages/web3-eth-contract/src/contract.ts +++ b/packages/web3-eth-contract/src/contract.ts @@ -42,6 +42,8 @@ import { TransactionMiddleware, } from 'web3-eth'; import { + decodeFunctionCall, + decodeFunctionReturn, encodeEventSignature, encodeFunctionSignature, decodeContractErrorData, @@ -99,12 +101,7 @@ import { ValidationSchemaInput, Web3ValidatorError, } from 'web3-validator'; -import { - decodeMethodReturn, - decodeMethodParams, - encodeEventABI, - encodeMethodABI, -} from './encoding.js'; +import { encodeEventABI, encodeMethodABI } from './encoding.js'; import { ContractLogsSubscription } from './contract_log_subscription.js'; import { ContractEventOptions, @@ -1026,7 +1023,7 @@ export class Contract `The ABI for the provided method signature ${methodSignature} was not found.`, ); } - return { ...decodeMethodParams(abi, data), __method__: jsonInterfaceMethodToString(abi) }; + return decodeFunctionCall(abi, data); } private _parseAndSetJsonInterface( @@ -1251,7 +1248,7 @@ export class Contract }), encodeABI: () => encodeMethodABI(methodAbi, abiParams), - decodeData: (data: HexString) => decodeMethodParams(methodAbi, data), + decodeData: (data: HexString) => decodeFunctionCall(methodAbi, data), createAccessList: async ( options?: PayableCallOptions | NonPayableCallOptions, @@ -1305,7 +1302,7 @@ export class Contract block, this.defaultReturnFormat as typeof DEFAULT_RETURN_FORMAT, ); - return decodeMethodReturn(abi, result); + return decodeFunctionReturn(abi, result); } 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 diff --git a/packages/web3-eth-contract/src/encoding.ts b/packages/web3-eth-contract/src/encoding.ts index 48531277518..2b347269d36 100644 --- a/packages/web3-eth-contract/src/encoding.ts +++ b/packages/web3-eth-contract/src/encoding.ts @@ -30,7 +30,8 @@ import { } from 'web3-types'; import { - decodeParameters, + decodeFunctionCall, + decodeFunctionReturn, encodeEventSignature, encodeFunctionSignature, encodeParameter, @@ -153,44 +154,7 @@ export const encodeMethodABI = ( return `${encodeFunctionSignature(abi)}${params}`; }; -export const decodeMethodParams = ( - abi: AbiFunctionFragment | AbiConstructorFragment, - data: HexString, - methodSignatureProvided = true, -) => { - const value = - methodSignatureProvided && data && data.length >= 10 && data.startsWith('0x') - ? data.slice(10) - : data; - if (!abi.inputs) { - throw new Web3ContractError('No inputs found in the ABI'); - } - const result = decodeParameters([...abi.inputs], value); - return result; -}; - -export const decodeMethodReturn = (abi: AbiFunctionFragment, returnValues?: HexString) => { - // If it was constructor then we need to return contract address - if (abi.type === 'constructor') { - return returnValues; - } - - if (!returnValues) { - // Using "null" value intentionally to match legacy behavior - // eslint-disable-next-line no-null/no-null - return null; - } - - const value = returnValues.length >= 2 ? returnValues.slice(2) : returnValues; - if (!abi.outputs) { - // eslint-disable-next-line no-null/no-null - return null; - } - const result = decodeParameters([...abi.outputs], value); - - if (result.__length__ === 1) { - return result[0]; - } - - return result; -}; +/** @deprecated import `decodeFunctionCall` from ''web3-eth-abi' instead. */ +export const decodeMethodParams = decodeFunctionCall; +/** @deprecated import `decodeFunctionReturn` from ''web3-eth-abi' instead. */ +export const decodeMethodReturn = decodeFunctionReturn; From 4ca66af181a46f134df514d3bd7b67c4c440f159 Mon Sep 17 00:00:00 2001 From: Oleksii Kosynskyi Date: Wed, 23 Oct 2024 11:47:15 -0400 Subject: [PATCH 174/186] Add rpc provider public node (#7322) * init * finished * add unit test * add changelog * Update CHANGELOG.md * Update web3_provider_publicnode.ts * fix * Update web3_provider_publicnode.ts --- CHANGELOG.md | 6 + packages/web3-rpc-providers/CHANGELOG.md | 4 + packages/web3-rpc-providers/src/index.ts | 1 + packages/web3-rpc-providers/src/types.ts | 51 +++++++- .../src/web3_provider_publicnode.ts | 112 ++++++++++++++++++ .../src/web3_provider_quicknode.ts | 2 +- .../test/unit/request.test.ts | 24 ++++ .../test/integration/web3RPCProviders.test.ts | 93 ++++++++++++++- 8 files changed, 287 insertions(+), 6 deletions(-) create mode 100644 packages/web3-rpc-providers/src/web3_provider_publicnode.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a7bdee5a44..d9abf6019de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2765,3 +2765,9 @@ If there are any bugs, improvements, optimizations or any new feature proposal f - fix `padRight` validation failure on large `uint` (#7265) ## [Unreleased] + +### Added + +#### web3-rpc-providers + +- PublicNodeProvider was added (#7322) diff --git a/packages/web3-rpc-providers/CHANGELOG.md b/packages/web3-rpc-providers/CHANGELOG.md index a9e2c2a8b79..110b620707d 100644 --- a/packages/web3-rpc-providers/CHANGELOG.md +++ b/packages/web3-rpc-providers/CHANGELOG.md @@ -59,3 +59,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added optional `HttpProviderOptions | SocketOptions` in `Web3ExternalProvider` and `QuickNodeProvider` for provider configs ## [Unreleased] + +### Added + +- PublicNodeProvider was added (#7322) diff --git a/packages/web3-rpc-providers/src/index.ts b/packages/web3-rpc-providers/src/index.ts index 577d8e6b960..f7c0e6c2613 100644 --- a/packages/web3-rpc-providers/src/index.ts +++ b/packages/web3-rpc-providers/src/index.ts @@ -19,6 +19,7 @@ import { QuickNodeProvider } from './web3_provider_quicknode.js'; export * from './types.js'; export * from './web3_provider_quicknode.js'; +export * from './web3_provider_publicnode.js'; export * from './web3_provider.js'; export * from './errors.js'; diff --git a/packages/web3-rpc-providers/src/types.ts b/packages/web3-rpc-providers/src/types.ts index 9fda306ae0d..258d6411c57 100644 --- a/packages/web3-rpc-providers/src/types.ts +++ b/packages/web3-rpc-providers/src/types.ts @@ -25,13 +25,15 @@ export enum Transport { export enum Network { ETH_MAINNET = 'eth_mainnet', - ETH_GOERLI = 'eth_goerli', ETH_SEPOLIA = 'eth_sepolia', ETH_HOLESKY = 'eth_holesky', POLYGON_MAINNET = 'polygon_mainnet', - POLYGON_MUMBAI = 'polygon_mumbai', - POLYGON_AMONY = 'polygon_amony', + + POLYGON_AMOY = 'polygon_amoy', + AVALANCHE_C_MAINNET = 'avalanche_c_mainnet', + AVALANCHE_P_MAINNET = 'avalanche_p_mainnet', + AVALANCHE_X_MAINNET = 'avalanche_x_mainnet', ARBITRUM_MAINNET = 'arbitrum_mainnet', ARBITRUM_SEPOLIA = 'arbitrum_sepolia', @@ -42,8 +44,51 @@ export enum Network { OPTIMISM_MAINNET = 'optimism_mainnet', OPTIMISM_SEPOLIA = 'optimism_sepolia', + FANTOM_MAINNET = 'fantom_mainnet', + FANTOM_TESTNET = 'fantom_testnet', + + DYMENSION_MAINNET = 'dymension_mainnet', + DYMENSION_TESTNET = 'dymension_testnet', + BNB_MAINNET = 'bnb_mainnet', BNB_TESTNET = 'bnb_testnet', + + BSC_MAINNET = 'bsc_mainnet', + BSC_TESTNET = 'bsc_testnet', + + ARBITRUM_ONE = 'arbitrum_one', + ARBITRUM_NOVA = 'arbitrum_nova', + AVALANCHE_FUJI_C = 'avalanche_fuji_c', + AVALANCHE_FUJI_P = 'avalanche_fuji_p', + AVALANCHE_FUJI_X = 'avalanche_fuji_x', + BLAST_MAINNET = 'blast_mainnet', + OPBNB_MAINNET = 'opbnb_mainnet', + OPBNB_TESTNET = 'opbnb_testnet', + GNOSIS_MAINNET = 'gnosis_mainnet', + GNOSIS_CHIADO = 'gnosis_chiado', + PULSECHAIN_MAINNET = 'pulsechain_mainnet', + PULSECHAIN_TESTNET = 'pulsechain_testnet', + KAVA_MAINNET = 'kava_mainnet', + CRONOS_MAINNET = 'cronos_mainnet', + MANTLE_MAINNET = 'mantle_mainnet', + CHILIZ_MAINNET = 'chiliz_mainnet', + CHILIZ_SPICY = 'chiliz_spicy', + MOONBEAM_MAINNET = 'moonbeam_mainnet', + TAIKO_MAINNET = 'taiko_mainnet', + TAIKO_HEKLA = 'taiko_hekla', + LINEA_MAINNET = 'linea_mainnet', + LINEA_SEPOLIA = 'linea_sepolia', + BAHAMUT_MAINNET = 'bahamut_mainnet', + SCROLL_MAINNET = 'scroll_mainnet', + SCROLL_SEPOLIA = 'scroll_sepolia', + TRON_MAINNET = 'tron_mainnet', + SYSCOIN_MAINNET = 'syscoin_mainnet', + SYSCOIN_TANENBAUM = 'syscoin_tanenbaum', + MOONRIVER_MAINNET = 'moonriver_mainnet', + HAQQ_MAINNET = 'haqq_mainnet', + EVMOS_MAINNET = 'evmos_mainnet', + EVMOS_TESTNET = 'evmos_testnet', + BERACHAIN_TESTNET = 'berachain_testnet', } // Combining the ws types diff --git a/packages/web3-rpc-providers/src/web3_provider_publicnode.ts b/packages/web3-rpc-providers/src/web3_provider_publicnode.ts new file mode 100644 index 00000000000..027d7a45921 --- /dev/null +++ b/packages/web3-rpc-providers/src/web3_provider_publicnode.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 { EthExecutionAPI, Web3APISpec } from 'web3-types'; +import { HttpProviderOptions } from 'web3-providers-http'; +import { Network, SocketOptions, Transport } from './types.js'; +import { Web3ExternalProvider } from './web3_provider.js'; + +const isValid = (str: string) => str !== undefined && str.trim().length > 0; + +const websocketExclusions = [ + Network.DYMENSION_MAINNET, + Network.DYMENSION_TESTNET, + Network.KAVA_MAINNET, + Network.CRONOS_MAINNET, + // deprecated + Network.POLYGON_MAINNET, +]; + +export class PublicNodeProvider< + API extends Web3APISpec = EthExecutionAPI, +> extends Web3ExternalProvider { + // eslint-disable-next-line default-param-last + public constructor( + network: Network = Network.ETH_MAINNET, + transport: Transport = Transport.HTTPS, + host = '', + providerConfigOptions?: HttpProviderOptions | SocketOptions, + ) { + super(network, transport, '', host, providerConfigOptions); + } + public static readonly networkHostMap: { [key: string]: string } = { + [Network.POLYGON_AMOY]: 'polygon-amoy-bor-rpc', + [Network.DYMENSION_MAINNET]: 'dymension-evm-rpc', + [Network.DYMENSION_TESTNET]: 'dymension-testnet-evm-rpc', + [Network.BLAST_MAINNET]: 'blast-rpc', + [Network.GNOSIS_MAINNET]: 'gnosis-rpc', + [Network.PULSECHAIN_MAINNET]: 'pulsechain-rpc', + [Network.PULSECHAIN_TESTNET]: 'pulsechain-testnet-rpc', + [Network.KAVA_MAINNET]: 'kava-evm-rpc', + [Network.CRONOS_MAINNET]: 'cronos-evm-rpc', + [Network.MANTLE_MAINNET]: 'mantle-rpc', + [Network.TAIKO_MAINNET]: 'taiko-rpc', + [Network.TAIKO_HEKLA]: 'taiko-hekla-rpc', + [Network.LINEA_MAINNET]: 'linea-rpc', + [Network.LINEA_SEPOLIA]: 'linea-sepolia-rpc', + [Network.SCROLL_MAINNET]: 'scroll-rpc', + [Network.SCROLL_SEPOLIA]: 'scroll-sepolia-rpc', + [Network.SYSCOIN_MAINNET]: 'syscoin-evm-rpc', + [Network.SYSCOIN_TANENBAUM]: 'syscoin-tanenbaum-evm-rpc', + [Network.HAQQ_MAINNET]: 'haqq-evm-rpc', + [Network.EVMOS_MAINNET]: 'evmos-evm-rpc', + [Network.EVMOS_TESTNET]: 'evmos-testnet-evm-rpc', + [Network.BERACHAIN_TESTNET]: 'berachain-testnet-evm-rpc', + [Network.ETH_MAINNET]: 'ethereum-rpc', + [Network.ETH_SEPOLIA]: 'ethereum-sepolia-rpc', + [Network.ETH_HOLESKY]: 'ethereum-holesky-rpc', + [Network.BSC_MAINNET]: 'bsc-rpc', + [Network.BSC_TESTNET]: 'bsc-testnet-rpc', + [Network.POLYGON_MAINNET]: 'polygon-bor-rpc', + [Network.BASE_MAINNET]: 'base-rpc', + [Network.BASE_SEPOLIA]: 'base-sepolia-rpc', + [Network.ARBITRUM_ONE]: 'arbitrum-one-rpc', + [Network.ARBITRUM_NOVA]: 'arbitrum-nova-rpc', + [Network.ARBITRUM_SEPOLIA]: 'arbitrum-sepolia-rpc', + [Network.AVALANCHE_C_MAINNET]: 'avalanche-c-chain-rpc', + [Network.AVALANCHE_P_MAINNET]: 'avalanche-p-chain-rpc', + [Network.AVALANCHE_X_MAINNET]: 'avalanche-x-chain-rpc', + [Network.AVALANCHE_FUJI_C]: 'avalanche-fuji-c-chain-rpc', + [Network.AVALANCHE_FUJI_P]: 'avalanche-fuji-p-chain-rpc', + [Network.AVALANCHE_FUJI_X]: 'avalanche-fuji-x-chain-rpc', + [Network.OPTIMISM_MAINNET]: 'optimism-rpc', + [Network.OPTIMISM_SEPOLIA]: 'optimism-sepolia-rpc', + [Network.FANTOM_MAINNET]: 'fantom-rpc', + [Network.FANTOM_TESTNET]: 'fantom-testnet-rpc', + [Network.OPBNB_MAINNET]: 'opbnb-rpc', + [Network.OPBNB_TESTNET]: 'opbnb-testnet-rpc', + [Network.GNOSIS_CHIADO]: 'gnosis-chiado-rpc', + [Network.CHILIZ_MAINNET]: 'chiliz-rpc', + [Network.CHILIZ_SPICY]: 'chiliz-spicy-rpc', + [Network.MOONBEAM_MAINNET]: 'moonbeam-rpc', + [Network.BAHAMUT_MAINNET]: 'bahamut-rpc', + [Network.TRON_MAINNET]: 'tron-evm-rpc', + [Network.MOONRIVER_MAINNET]: 'moonriver-rpc', + }; + // eslint-disable-next-line class-methods-use-this + public getRPCURL(network: Network, transport: Transport, _: string, _host: string) { + if (!PublicNodeProvider.networkHostMap[network]) { + throw new Error('Network info not avalible.'); + } + const defaultHost = `${PublicNodeProvider.networkHostMap[network]}.publicnode.com`; + const host = isValid(_host) ? _host : defaultHost; + if (websocketExclusions.includes(network) && transport === Transport.WebSocket) { + return `${transport}://${host}/websocket`; + } + return `${transport}://${host}`; + } +} diff --git a/packages/web3-rpc-providers/src/web3_provider_quicknode.ts b/packages/web3-rpc-providers/src/web3_provider_quicknode.ts index ae74fa49860..4b6e5ae73e6 100644 --- a/packages/web3-rpc-providers/src/web3_provider_quicknode.ts +++ b/packages/web3-rpc-providers/src/web3_provider_quicknode.ts @@ -107,7 +107,7 @@ export class QuickNodeProvider< host = isValid(_host) ? _host : 'small-chaotic-moon.matic.quiknode.pro'; token = isValid(_token) ? _token : '847569f8a017e84d985e10d0f44365d965a951f1'; break; - case Network.POLYGON_AMONY: + case Network.POLYGON_AMOY: host = isValid(_host) ? _host : 'prettiest-side-shape.matic-amoy.quiknode.pro'; token = isValid(_token) ? _token : '79a9476eea661d4f82de614db1d8a895b14b881c'; break; diff --git a/packages/web3-rpc-providers/test/unit/request.test.ts b/packages/web3-rpc-providers/test/unit/request.test.ts index 3de14fc0513..da07c2a578c 100644 --- a/packages/web3-rpc-providers/test/unit/request.test.ts +++ b/packages/web3-rpc-providers/test/unit/request.test.ts @@ -20,6 +20,7 @@ import { Network, Transport } from '../../src/types'; import { Web3ExternalProvider } from '../../src/web3_provider'; import { QuickNodeRateLimitError } from '../../src/errors'; import { QuickNodeProvider } from '../../src/web3_provider_quicknode'; +import { PublicNodeProvider } from '../../src/web3_provider_publicnode'; jest.mock('web3-providers-ws', () => { return { @@ -122,4 +123,27 @@ describe('Web3ExternalProvider', () => { }; await expect(provider.request(payload)).rejects.toThrow(QuickNodeRateLimitError); }); + + it('should make a request using the PublicNodeProvider provider', async () => { + const network: Network = Network.ETH_MAINNET; + const transport: Transport = Transport.HTTPS; + + const mockHttpProvider = { + request: jest.fn(), + }; + + const mockResponse = { result: 'mock-result' }; + mockHttpProvider.request.mockResolvedValue(mockResponse); + + const provider = new PublicNodeProvider(network, transport); + (provider as any).provider = mockHttpProvider; + + const payload: Web3APIPayload> = { + method: 'eth_getBalance', + params: ['0x0123456789012345678901234567890123456789', 'latest'], + }; + + const result = await provider.request(payload); + expect(result).toEqual(mockResponse); + }); }); diff --git a/packages/web3/test/integration/web3RPCProviders.test.ts b/packages/web3/test/integration/web3RPCProviders.test.ts index 1faeffad452..6e6d2994f9c 100644 --- a/packages/web3/test/integration/web3RPCProviders.test.ts +++ b/packages/web3/test/integration/web3RPCProviders.test.ts @@ -15,7 +15,13 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ -import { mainnet, Network, QuickNodeProvider, Transport } from 'web3-rpc-providers'; +import { + mainnet, + Network, + QuickNodeProvider, + Transport, + PublicNodeProvider, +} from 'web3-rpc-providers'; import { Web3 } from '../../src/index'; describe('Web3 RPC Provider Integration tests', () => { @@ -29,7 +35,7 @@ describe('Web3 RPC Provider Integration tests', () => { Network.BNB_MAINNET, Network.BNB_TESTNET, Network.POLYGON_MAINNET, - Network.POLYGON_AMONY, + Network.POLYGON_AMOY, ]; transports.forEach(transport => { @@ -48,6 +54,89 @@ describe('Web3 RPC Provider Integration tests', () => { }); }); }); + + const publicNodeNetworks = [ + Network.POLYGON_AMOY, + Network.POLYGON_MAINNET, + Network.DYMENSION_MAINNET, + Network.DYMENSION_TESTNET, + Network.BLAST_MAINNET, + Network.GNOSIS_MAINNET, + Network.PULSECHAIN_MAINNET, + Network.PULSECHAIN_TESTNET, + Network.KAVA_MAINNET, + Network.CRONOS_MAINNET, + Network.MANTLE_MAINNET, + Network.HAQQ_MAINNET, + Network.TAIKO_MAINNET, + Network.TAIKO_HEKLA, + Network.EVMOS_MAINNET, + Network.EVMOS_TESTNET, + Network.BERACHAIN_TESTNET, + Network.LINEA_MAINNET, + Network.LINEA_SEPOLIA, + Network.SCROLL_MAINNET, + Network.SCROLL_SEPOLIA, + Network.SYSCOIN_MAINNET, + Network.SYSCOIN_TANENBAUM, + Network.ETH_MAINNET, + Network.ETH_SEPOLIA, + Network.ETH_HOLESKY, + Network.BSC_MAINNET, + Network.BSC_TESTNET, + Network.BASE_MAINNET, + Network.BASE_SEPOLIA, + Network.ARBITRUM_ONE, + Network.ARBITRUM_NOVA, + Network.ARBITRUM_SEPOLIA, + Network.AVALANCHE_C_MAINNET, + Network.AVALANCHE_P_MAINNET, + Network.AVALANCHE_X_MAINNET, + Network.AVALANCHE_FUJI_C, + Network.AVALANCHE_FUJI_P, + Network.AVALANCHE_FUJI_X, + Network.OPTIMISM_MAINNET, + Network.OPTIMISM_SEPOLIA, + Network.FANTOM_MAINNET, + Network.FANTOM_TESTNET, + Network.OPBNB_MAINNET, + Network.OPBNB_TESTNET, + Network.GNOSIS_CHIADO, + Network.CHILIZ_MAINNET, + Network.CHILIZ_SPICY, + Network.MOONBEAM_MAINNET, + Network.BAHAMUT_MAINNET, + Network.TRON_MAINNET, + Network.MOONRIVER_MAINNET, + ]; + transports.forEach(transport => { + publicNodeNetworks.forEach(network => { + if ( + !( + [ + Network.AVALANCHE_P_MAINNET, + Network.AVALANCHE_X_MAINNET, + Network.AVALANCHE_FUJI_X, + Network.AVALANCHE_FUJI_P, + ].includes(network) && transport === Transport.WebSocket + ) + ) { + it(`PublicNodeProvider should work with ${transport} transport and ${network} network`, async () => { + const provider = new PublicNodeProvider(network, transport); + const web3 = new Web3(provider); + const result = await web3.eth.getBlockNumber(); + + expect(typeof result).toBe('bigint'); + expect(result > 0).toBe(true); + + if (transport === Transport.WebSocket) { + web3.provider?.disconnect(); + } + }); + } + }); + }); + it(`should work with mainnet provider`, async () => { const web3 = new Web3(mainnet); const result = await web3.eth.getBlockNumber(); From 70352cdf6fd6eff92b352ca5d6b3a07507fe5472 Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Wed, 23 Oct 2024 11:06:38 -0700 Subject: [PATCH 175/186] Update Intermediate dApp Guide (EIP-6963 Types no Longer in Namespace) (#7349) --- .../docs/guides/07_dapps/intermediate-dapp.md | 35 +++++++++++-------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/docs/docs/guides/07_dapps/intermediate-dapp.md b/docs/docs/guides/07_dapps/intermediate-dapp.md index 16c05c232fb..40c408644fc 100644 --- a/docs/docs/guides/07_dapps/intermediate-dapp.md +++ b/docs/docs/guides/07_dapps/intermediate-dapp.md @@ -158,10 +158,16 @@ Create a `src/useProviders.ts` file and add the following code: ```ts import { useSyncExternalStore } from 'react'; -import { providers, Web3 } from 'web3'; +import { + type EIP6963ProviderDetail, + type EIP6963ProviderResponse, + type EIP6963ProvidersMapUpdateEvent, + Web3, + web3ProvidersMapUpdated, +} from 'web3'; // initial empty list of providers -let providerList: providers.EIP6963ProviderDetail[] = []; +let providerList: EIP6963ProviderDetail[] = []; /** * External store for subscribing to EIP-6963 providers @@ -172,9 +178,9 @@ const providerStore = { // subscribe to EIP-6963 provider events subscribe: (callback: () => void) => { // update the list of providers - function setProviders(response: providers.EIP6963ProviderResponse) { + function setProviders(response: EIP6963ProviderResponse) { providerList = []; - response.forEach((provider: providers.EIP6963ProviderDetail) => { + response.forEach((provider: EIP6963ProviderDetail) => { providerList.push(provider); }); @@ -186,7 +192,7 @@ const providerStore = { Web3.requestEIP6963Providers().then(setProviders); // handler for newly discovered providers - function updateProviders(providerEvent: providers.EIP6963ProvidersMapUpdateEvent) { + function updateProviders(providerEvent: EIP6963ProvidersMapUpdateEvent) { setProviders(providerEvent.detail); } @@ -194,8 +200,7 @@ const providerStore = { Web3.onNewProviderDiscovered(updateProviders); // return a function that unsubscribes from the created event listener - return () => - window.removeEventListener(providers.web3ProvidersMapUpdated as any, updateProviders); + return () => window.removeEventListener(web3ProvidersMapUpdated as any, updateProviders); }, }; @@ -209,7 +214,7 @@ This file exports a single member - a React [`useSyncExternalStore` hook](https: Replace the contents of the `src/App.tsx` file with the following: ```tsx -import type { providers } from 'web3'; +import type { EIP6963ProviderDetail } from 'web3'; import { useProviders } from './useProviders'; @@ -219,7 +224,7 @@ function App() { return ( <> - {providers.map((provider: providers.EIP6963ProviderDetail) => { + {providers.map((provider: EIP6963ProviderDetail) => { // list available providers return (

@@ -244,7 +249,7 @@ Replace the contents of the `src/App.tsx` file with the following: ```tsx import { useEffect, useState } from 'react'; -import { type providers, Web3 } from 'web3'; +import { type EIP6963ProviderDetail, Web3 } from 'web3'; import { useProviders } from './useProviders'; @@ -258,7 +263,7 @@ function App() { const [balances, setBalances] = useState>(new Map()); // click-handler for provider buttons - function setProvider(provider: providers.EIP6963ProviderDetail) { + function setProvider(provider: EIP6963ProviderDetail) { const web3: Web3 = new Web3(provider.provider); setWeb3(web3); web3.eth.requestAccounts().then(setAccounts); @@ -300,7 +305,7 @@ function App() { <> {web3 === undefined ? // no provider set, display list of available providers - providers.map((provider: providers.EIP6963ProviderDetail) => { + providers.map((provider: EIP6963ProviderDetail) => { // for each provider, display a button to connect to that provider return (
@@ -456,7 +461,7 @@ Replace the contents of the `src/App.tsx` file with the following: ```tsx import { useEffect, useState } from 'react'; -import { type providers, Web3 } from 'web3'; +import { type EIP6963ProviderDetail, Web3 } from 'web3'; // highlight-next-line import TransferForm from './TransferForm'; @@ -472,7 +477,7 @@ function App() { const [balances, setBalances] = useState>(new Map()); // click-handler for provider buttons - function setProvider(provider: providers.EIP6963ProviderDetail) { + function setProvider(provider: EIP6963ProviderDetail) { const web3: Web3 = new Web3(provider.provider); setWeb3(web3); web3.eth.requestAccounts().then(setAccounts); @@ -514,7 +519,7 @@ function App() { <> {web3 === undefined ? // no provider set, display list of available providers - providers.map((provider: providers.EIP6963ProviderDetail) => { + providers.map((provider: EIP6963ProviderDetail) => { // for each provider, display a button to connect to that provider return (
From 0681f97ed9daa592f86c8d8100d8802f706d046d Mon Sep 17 00:00:00 2001 From: Junaid <86780488+jdevcs@users.noreply.github.com> Date: Thu, 24 Oct 2024 10:30:38 +0200 Subject: [PATCH 176/186] update (#7350) --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index ed6a5bfe2af..116e5513a02 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -2,4 +2,4 @@ # https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners # Automatically assigns members of the web3.js team to new pending PRs as reviewers -* @avkos @jdevcs @luu-alex @Muhammad-Altabba +* @avkos @jdevcs @luu-alex @Muhammad-Altabba @krzysu @danforbes From d3baae69e73491ffb332fd2de95d99c18ff0e335 Mon Sep 17 00:00:00 2001 From: Oleksii Kosynskyi Date: Thu, 24 Oct 2024 09:44:50 -0400 Subject: [PATCH 177/186] Fix Contract methods input param type any[] (#7340) * fix types * fix * Update type.test.ts * fix tests * fix test --- packages/web3-eth-contract/src/contract.ts | 6 +- .../web3-eth-contract/test/fixtures/erc20.ts | 2 +- .../contract_overloaded_methods.test.ts | 5 +- .../test/unit/contract_typing.test.ts | 6 +- .../web3-eth-contract/test/unit/type.test.ts | 79 +++++++++++++++++++ packages/web3-types/src/eth_abi_types.ts | 4 +- 6 files changed, 96 insertions(+), 6 deletions(-) create mode 100644 packages/web3-eth-contract/test/unit/type.test.ts diff --git a/packages/web3-eth-contract/src/contract.ts b/packages/web3-eth-contract/src/contract.ts index 60602497e65..cff3a440bfe 100644 --- a/packages/web3-eth-contract/src/contract.ts +++ b/packages/web3-eth-contract/src/contract.ts @@ -127,7 +127,11 @@ type ContractBoundMethod< Abi extends AbiFunctionFragment, Method extends ContractMethod = ContractMethod, > = ( - ...args: Method['Inputs'] extends undefined | unknown ? any[] : Method['Inputs'] + ...args: Abi extends undefined + ? any[] + : Method['Inputs'] extends never + ? any[] + : Method['Inputs'] ) => Method['Abi']['stateMutability'] extends 'payable' | 'pure' ? PayableMethodObject : NonPayableMethodObject; diff --git a/packages/web3-eth-contract/test/fixtures/erc20.ts b/packages/web3-eth-contract/test/fixtures/erc20.ts index 18b51748a4e..30168dc4505 100644 --- a/packages/web3-eth-contract/test/fixtures/erc20.ts +++ b/packages/web3-eth-contract/test/fixtures/erc20.ts @@ -22,7 +22,7 @@ import { ContractEventOptions, PayableMethodObject, NonPayableMethodObject } fro export interface Erc20Interface { methods: { [key: string]: ( - ...args: ReadonlyArray + ...args: any[] ) => | PayableMethodObject, ReadonlyArray> | NonPayableMethodObject, ReadonlyArray>; diff --git a/packages/web3-eth-contract/test/integration/local_account/contract_overloaded_methods.test.ts b/packages/web3-eth-contract/test/integration/local_account/contract_overloaded_methods.test.ts index 96985cda3a7..0c905e8ece2 100644 --- a/packages/web3-eth-contract/test/integration/local_account/contract_overloaded_methods.test.ts +++ b/packages/web3-eth-contract/test/integration/local_account/contract_overloaded_methods.test.ts @@ -102,11 +102,14 @@ describe('contract ERC721 overloaded functions', () => { }); it('transferFrom with 3 invalid arguments', () => { - expect(() => contractDeployed.methods.safeTransferFrom(1, 2, 3)).toThrow('Web3 validator'); + expect(() => contractDeployed.methods.safeTransferFrom('1', '2', 3)).toThrow( + 'Web3 validator', + ); }); it('transferFrom with 2 arguments', () => { expect(() => + // @ts-expect-error invalid arguments so ts will throw an error contractDeployed.methods.safeTransferFrom(localAccount.address, localAccount.address), ).toThrow('Web3 validator'); }); diff --git a/packages/web3-eth-contract/test/unit/contract_typing.test.ts b/packages/web3-eth-contract/test/unit/contract_typing.test.ts index 79f66bdca29..c5190e10cda 100644 --- a/packages/web3-eth-contract/test/unit/contract_typing.test.ts +++ b/packages/web3-eth-contract/test/unit/contract_typing.test.ts @@ -37,8 +37,10 @@ describe('contract typing', () => { ]); typecheck('should allow any input params', () => [ - expectTypeOf>().toBe(), - expectTypeOf>().toBe(), + expectTypeOf>().toBe< + any[] | [] + >(), + expectTypeOf>().toBe(), ]); }); describe('custom abi', () => { diff --git a/packages/web3-eth-contract/test/unit/type.test.ts b/packages/web3-eth-contract/test/unit/type.test.ts new file mode 100644 index 00000000000..0b7082ca1de --- /dev/null +++ b/packages/web3-eth-contract/test/unit/type.test.ts @@ -0,0 +1,79 @@ +/* +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 { Contract } from '../../src'; + +describe('Contract method types', () => { + it('contract method params types test', () => { + const abiAsConst = [ + { + inputs: [ + { internalType: 'uint256', name: 'testArg1', type: 'uint256' }, + { internalType: 'uint256', name: 'testArg2', type: 'uint256' }, + ], + name: 'testWithParams', + outputs: [{ internalType: 'uint256', name: 'testRes1', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'testWithoutParams', + outputs: [{ internalType: 'uint256', name: 'testRes1', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, + ] as const; + + const abiAsArray = [ + { + inputs: [ + { internalType: 'uint256', name: 'testArg1', type: 'uint256' }, + { internalType: 'uint256', name: 'testArg2', type: 'uint256' }, + ], + name: 'testWithParams', + outputs: [{ internalType: 'uint256', name: 'testRes1', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'testWithoutParams', + outputs: [{ internalType: 'uint256', name: 'testRes1', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, + ]; + + // abi as const + const contract = new Contract(abiAsConst); + contract.methods.testWithParams(1, 2); // no ts error - works as expected + // @ts-expect-error ts compiler error + expect(() => contract.methods.testWithParams()).toThrow(); // ts error - works as expected + // @ts-expect-error ts compiler error + contract.methods.testWithoutParams(1, 2); // ts error - works as expected + contract.methods.testWithoutParams(); // no ts error - works as expected + + // abi as usual array type + const contract2 = new Contract(abiAsArray); + // because we do not know exact type without const or provided type + contract2.methods.testWithParams(1, 2); // no ts error - works as expected + contract2.methods.testWithoutParams(); // no ts error - works as expected + contract2.methods.testWithoutParams(1, 2); // no ts error - works as expected + expect(() => contract2.methods.testWithParams()).toThrow(); // no ts error - works as expected + }); +}); diff --git a/packages/web3-types/src/eth_abi_types.ts b/packages/web3-types/src/eth_abi_types.ts index 0daaa2db877..06c56afa14f 100644 --- a/packages/web3-types/src/eth_abi_types.ts +++ b/packages/web3-types/src/eth_abi_types.ts @@ -320,7 +320,9 @@ export type ContractMethodOutputParameters : []; export type ContractMethodInputParameters | undefined> = - Params extends readonly [] + Params extends undefined + ? any[] + : Params extends readonly [] ? [] : Params extends readonly [infer H, ...infer R] ? H extends AbiParameter From efac906a9fdcfda895aaf602c458d574645bc549 Mon Sep 17 00:00:00 2001 From: Muhammad Altabba <24407834+Muhammad-Altabba@users.noreply.github.com> Date: Mon, 28 Oct 2024 15:18:16 +0100 Subject: [PATCH 178/186] fix: upgrade @cookbookdev/docsbot from 4.21.1 to 4.21.23 (#7357) Snyk has created this PR to upgrade @cookbookdev/docsbot from 4.21.1 to 4.21.23. See this package in yarn: @cookbookdev/docsbot See this project in Snyk: https://app.snyk.io/org/muhammad-altabba/project/97fdd18d-9bab-4c87-87eb-da3caee72033?utm_source=github&utm_medium=referral&page=upgrade-pr Co-authored-by: snyk-bot --- docs/package.json | 2 +- docs/yarn.lock | 620 +++++++++++++++++++++++++++++++++++++++------- 2 files changed, 529 insertions(+), 93 deletions(-) diff --git a/docs/package.json b/docs/package.json index c729ef5a765..3d4031e1204 100644 --- a/docs/package.json +++ b/docs/package.json @@ -15,7 +15,7 @@ "typecheck": "tsc" }, "dependencies": { - "@cookbookdev/docsbot": "^4.21.1", + "@cookbookdev/docsbot": "^4.21.23", "@docusaurus/core": "^3.0.1", "@docusaurus/preset-classic": "^3.0.1", "@docusaurus/theme-live-codeblock": "^3.0.1", diff --git a/docs/yarn.lock b/docs/yarn.lock index 05de2845cc6..bb8f6b3fcc5 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -202,6 +202,17 @@ json5 "^2.2.3" semver "^6.3.1" +"@babel/generator@^7.14.5": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.26.0.tgz#505cc7c90d92513f458a477e5ef0703e7c91b8d7" + integrity sha512-/AIkAmInnWwgEAJGQr9vY0c66Mj6kjkE2ZPB1PurTRaRAh3U+J45sAQMjQDJdh4WbR3l0x5xkimXBKyBXXAu2w== + dependencies: + "@babel/parser" "^7.26.0" + "@babel/types" "^7.26.0" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + jsesc "^3.0.2" + "@babel/generator@^7.23.3", "@babel/generator@^7.24.8", "@babel/generator@^7.24.9": version "7.24.10" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.10.tgz#a4ab681ec2a78bbb9ba22a3941195e28a81d8e76" @@ -380,11 +391,21 @@ resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz#5b3329c9a58803d5df425e5785865881a81ca48d" integrity sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ== +"@babel/helper-string-parser@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz#1aabb72ee72ed35789b4bbcad3ca2862ce614e8c" + integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA== + "@babel/helper-validator-identifier@^7.24.7": version "7.24.7" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db" integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w== +"@babel/helper-validator-identifier@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7" + integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ== + "@babel/helper-validator-option@^7.24.7", "@babel/helper-validator-option@^7.24.8": version "7.24.8" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz#3725cdeea8b480e86d34df15304806a06975e33d" @@ -423,6 +444,13 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.8.tgz#58a4dbbcad7eb1d48930524a3fd93d93e9084c6f" integrity sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w== +"@babel/parser@^7.26.0": + version "7.26.1" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.1.tgz#44e02499960df2cdce2c456372a3e8e0c3c5c975" + integrity sha512-reoQYNiAJreZNsJzyrDNzFQ+IQ5JFiIzAHJg9bn94S3l+4++J7RsIhNMoB+lgP/9tpmiAQqspv+xfdxTSzREOw== + dependencies: + "@babel/types" "^7.26.0" + "@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.24.7": version "7.24.7" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.7.tgz#fd059fd27b184ea2b4c7e646868a9a381bbc3055" @@ -1182,13 +1210,20 @@ core-js-pure "^3.30.2" regenerator-runtime "^0.14.0" -"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.22.6", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": +"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.22.6", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": version "7.24.8" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.8.tgz#5d958c3827b13cc6d05e038c07fb2e5e3420d82e" integrity sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA== dependencies: regenerator-runtime "^0.14.0" +"@babel/runtime@^7.20.13": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.0.tgz#8600c2f595f277c60815256418b85356a65173c1" + integrity sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw== + dependencies: + regenerator-runtime "^0.14.0" + "@babel/template@^7.24.7": version "7.24.7" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.7.tgz#02efcee317d0609d2c07117cb70ef8fb17ab7315" @@ -1214,6 +1249,14 @@ debug "^4.3.1" globals "^11.1.0" +"@babel/types@^7.14.5", "@babel/types@^7.20.7", "@babel/types@^7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.0.tgz#deabd08d6b753bc8e0f198f8709fb575e31774ff" + integrity sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA== + dependencies: + "@babel/helper-string-parser" "^7.25.9" + "@babel/helper-validator-identifier" "^7.25.9" + "@babel/types@^7.21.3", "@babel/types@^7.24.7", "@babel/types@^7.24.8", "@babel/types@^7.24.9", "@babel/types@^7.4.4": version "7.24.9" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.9.tgz#228ce953d7b0d16646e755acf204f4cf3d08cc73" @@ -1228,13 +1271,18 @@ resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== -"@cookbookdev/docsbot@^4.21.1": - version "4.21.1" - resolved "https://registry.yarnpkg.com/@cookbookdev/docsbot/-/docsbot-4.21.1.tgz#cfd9fc24ebff06182106092ea36dca513f537fee" - integrity sha512-RT9K5K021W6HtO5VavH4BP+TNZ0W0fRo6yeyySvCRRnWhOK38nuvVVU9hg09eSD2miE7fGXDrYLlG9WE/j1OEA== +"@cookbookdev/docsbot@^4.21.23": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@cookbookdev/docsbot/-/docsbot-4.24.0.tgz#3537bd6e6c5e48152b6f15fa956fb2cb7caab4ec" + integrity sha512-8v62HNLzAKPVu1NjSI/o0bkR67GCz5WSlNXCOvBs4jJktny4s+XvrfXgG9wo/m8UyKuPky63skAWaKTE3I+M6g== dependencies: + "@cookbookdev/sonner" "1.5.1" "@headlessui/react" "^1.7.18" "@headlessui/tailwindcss" "^0.2.0" + "@lingui/detect-locale" "^4.11.4" + "@lingui/macro" "^4.11.4" + "@lingui/react" "^4.11.4" + "@lingui/remote-loader" "^3.11.0" "@monaco-editor/react" "^4.6.0" "@radix-ui/react-avatar" "^1.0.4" "@radix-ui/react-checkbox" "^1.0.4" @@ -1253,9 +1301,13 @@ "@radix-ui/react-tabs" "^1.0.4" "@radix-ui/react-toast" "^1.1.5" "@radix-ui/react-tooltip" "^1.0.7" + "@shikijs/rehype" "^1.12.1" + "@statsig/js-client" "^3.1.0" + "@statsig/react-bindings" "^3.1.0" "@tailwindcss/line-clamp" "^0.4.4" "@tanstack/react-table" "^8.11.7" "@vercel/edge" "^1.1.1" + bcp-47 "^2.1.0" can-dom-mutate "^2.0.9" clsx "^2.1.0" cmdk-react17 "^1.0.0" @@ -1264,18 +1316,20 @@ file-saver "^2.0.5" framer-motion "^6.5.1" idb "^8.0.0" + iso-639-1 "^3.1.3" jszip "^3.10.1" - nanoid "^5.0.5" + nanoid "3.3.7" posthog-js "^1.136.8" prop-types "^15.8.1" react-complex-tree "^2.3.7" - react-markdown "^9.0.1" + react-remark "^2.1.0" react-resizable-panels "2.0.19" - react-syntax-highlighter "^15.5.0" recharts "^2.12.4" + rehype-react "^8.0.0" remark-gfm "^4.0.0" + remark-parse "^11.0.0" + remark-rehype "^11.1.0" solc "^0.8.25" - sonner "^1.4.41" styled-components "^6.1.8" swr "^2.2.5" tailwind-merge "^2.2.1" @@ -1283,6 +1337,11 @@ use-sync-external-store "^1.2.0" viem "2.9.16" +"@cookbookdev/sonner@1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@cookbookdev/sonner/-/sonner-1.5.1.tgz#a50b53a1287d0a373e2fc1b2aea78cf1b45b82bb" + integrity sha512-MqPxvFpWKRWuYpKv6ktnT+nGa2mk4jz+OVgunlpIxqfLgMvJ/PSg9OQv0+QlR6iAbThyjiedD6exULSgogPTmA== + "@discoveryjs/json-ext@0.5.7": version "0.5.7" resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" @@ -1890,6 +1949,77 @@ resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz#4fc56c15c580b9adb7dc3c333a134e540b44bfb1" integrity sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw== +"@lingui/conf@4.13.0": + version "4.13.0" + resolved "https://registry.yarnpkg.com/@lingui/conf/-/conf-4.13.0.tgz#5c63b45cee12fc3fbb0c5a340cbf986e5eb3845a" + integrity sha512-7NSinlzgSMKBezLsSM7DMwr0IpTHKr8nuSDpTZpI79+BhW+Xq38jPRQqMXdzItW8Cl/Lsdr3Y3MnYJIl8tADsQ== + dependencies: + "@babel/runtime" "^7.20.13" + chalk "^4.1.0" + cosmiconfig "^8.0.0" + jest-validate "^29.4.3" + jiti "^1.17.1" + lodash.get "^4.4.2" + +"@lingui/core@4.13.0": + version "4.13.0" + resolved "https://registry.yarnpkg.com/@lingui/core/-/core-4.13.0.tgz#d21c062b4e7cec198dd602caf07fe212a98c0b2c" + integrity sha512-kRqQWeEVoqNrDtEdyHPWGsAHRStN8ObYc5a1gdyuBhoj1zaoUS/DMK5C7B1ZeTtj6rCCmZRs6d2tN12hsZ2zJA== + dependencies: + "@babel/runtime" "^7.20.13" + "@lingui/message-utils" "4.13.0" + unraw "^3.0.0" + +"@lingui/detect-locale@^4.11.4": + version "4.13.0" + resolved "https://registry.yarnpkg.com/@lingui/detect-locale/-/detect-locale-4.13.0.tgz#cbca1a4152e9f66b4376a4b33f652afdc1aa99ca" + integrity sha512-1Q08tMdG3Avh7ruBxFPNA9Ll1ekunpIMHWg9MuGDcDsG/5ucNbZocUh9+iJxkqWmBMNbEaOj14oN8oRsHk2ufA== + +"@lingui/macro@^4.11.4": + version "4.13.0" + resolved "https://registry.yarnpkg.com/@lingui/macro/-/macro-4.13.0.tgz#c63c0b69da92fcd6c1a322ac957b2ab288f10a9b" + integrity sha512-OjhaWOWbTCXHOOHNaGI0shMP3qrPjNZ19tpEx/iStAmJq64fkevx/HbDPI0uuqLX8v1NFWG/SzBMIQzJb5YOvA== + dependencies: + "@babel/runtime" "^7.20.13" + "@babel/types" "^7.20.7" + "@lingui/conf" "4.13.0" + "@lingui/core" "4.13.0" + "@lingui/message-utils" "4.13.0" + +"@lingui/message-utils@4.13.0": + version "4.13.0" + resolved "https://registry.yarnpkg.com/@lingui/message-utils/-/message-utils-4.13.0.tgz#ebf64c5c47857dc4d39fde673804c9966ae8c8d8" + integrity sha512-tI/WBVZym+APwqk0O3xTaF0k+RQIv5E4PqGHdXqwbofycHly2C+izH+hg6UeNctc6jd19GRwqu/4ga9knkdAlQ== + dependencies: + "@messageformat/parser" "^5.0.0" + js-sha256 "^0.10.1" + +"@lingui/react@^4.11.4": + version "4.13.0" + resolved "https://registry.yarnpkg.com/@lingui/react/-/react-4.13.0.tgz#19d86560bcb0514738d8087eb567d6cc5caadc25" + integrity sha512-5remR9rVwosiiX/RnEWETHA8cpqQiP7U87OXXMPz67LuyG3XP8RP+ic75rVn284DHLHgpjDbauz7vYIz855ZoQ== + dependencies: + "@babel/runtime" "^7.20.13" + "@lingui/core" "4.13.0" + +"@lingui/remote-loader@^3.11.0": + version "3.11.0" + resolved "https://registry.yarnpkg.com/@lingui/remote-loader/-/remote-loader-3.11.0.tgz#1c7906f356129e82ac15d1d9ac7644df6a1f5dcf" + integrity sha512-oAoSEbPfFm+GyAQQOhMCBcuZpyqW6HqUtkAbv/k8z1eqvuk2vmduxfZ9WicyU6T2V0vjgWekVdHRa83NObk8xQ== + dependencies: + "@babel/generator" "^7.14.5" + "@babel/types" "^7.14.5" + json5 "^2.2.0" + messageformat-parser "^4.1.3" + ramda "^0.27.1" + +"@mapbox/hast-util-table-cell-style@^0.2.0": + version "0.2.1" + resolved "https://registry.yarnpkg.com/@mapbox/hast-util-table-cell-style/-/hast-util-table-cell-style-0.2.1.tgz#b8e92afdd38b668cf0762400de980073d2ade101" + integrity sha512-LyQz4XJIdCdY/+temIhD/Ed0x/p4GAOUycpFSEK2Ads1CPKZy6b7V/2ROEtQiLLQ8soIs0xe/QAoR6kwpyW/yw== + dependencies: + unist-util-visit "^1.4.1" + "@mdx-js/mdx@^3.0.0": version "3.0.1" resolved "https://registry.yarnpkg.com/@mdx-js/mdx/-/mdx-3.0.1.tgz#617bd2629ae561fdca1bb88e3badd947f5a82191" @@ -1926,6 +2056,13 @@ dependencies: "@types/mdx" "^2.0.0" +"@messageformat/parser@^5.0.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@messageformat/parser/-/parser-5.1.0.tgz#05e4851c782d633ad735791dd0a68ee65d2a7201" + integrity sha512-jKlkls3Gewgw6qMjKZ9SFfHUpdzEVdovKFtW1qRhJ3WI4FW5R/NnGDqr8SDGz+krWDO3ki94boMmQvGke1HwUQ== + dependencies: + moo "^0.5.1" + "@monaco-editor/loader@^1.4.0": version "1.4.0" resolved "https://registry.yarnpkg.com/@monaco-editor/loader/-/loader-1.4.0.tgz#f08227057331ec890fa1e903912a5b711a2ad558" @@ -2690,6 +2827,60 @@ "@noble/hashes" "~1.3.0" "@scure/base" "~1.1.0" +"@shikijs/core@1.22.1": + version "1.22.1" + resolved "https://registry.yarnpkg.com/@shikijs/core/-/core-1.22.1.tgz#31e4d2d92d32ce16f1ab07c5ca33526b5b0611e5" + integrity sha512-bqAhT/Ri5ixV4oYsvJNH8UJjpjbINWlWyXY6tBTsP4OmD6XnFv43nRJ+lTdxd2rmG5pgam/x+zGR6kLRXrpEKA== + dependencies: + "@shikijs/engine-javascript" "1.22.1" + "@shikijs/engine-oniguruma" "1.22.1" + "@shikijs/types" "1.22.1" + "@shikijs/vscode-textmate" "^9.3.0" + "@types/hast" "^3.0.4" + hast-util-to-html "^9.0.3" + +"@shikijs/engine-javascript@1.22.1": + version "1.22.1" + resolved "https://registry.yarnpkg.com/@shikijs/engine-javascript/-/engine-javascript-1.22.1.tgz#8f2bf3c05d81be94974d6487f2803363b9a470eb" + integrity sha512-540pyoy0LWe4jj2BVbgELwOFu1uFvRI7lg4hdsExrSXA9x7gqfzZ/Nnh4RfX86aDAgJ647gx4TCmRwACbnQSvw== + dependencies: + "@shikijs/types" "1.22.1" + "@shikijs/vscode-textmate" "^9.3.0" + oniguruma-to-js "0.4.3" + +"@shikijs/engine-oniguruma@1.22.1": + version "1.22.1" + resolved "https://registry.yarnpkg.com/@shikijs/engine-oniguruma/-/engine-oniguruma-1.22.1.tgz#fdf943f0203dc5ee1db0060a441da68fa6f3089e" + integrity sha512-L+1Vmd+a2kk8HtogUFymQS6BjUfJnzcWoUp1BUgxoDiklbKSMvrsMuLZGevTOP1m0rEjgnC5MsDmsr8lX1lC+Q== + dependencies: + "@shikijs/types" "1.22.1" + "@shikijs/vscode-textmate" "^9.3.0" + +"@shikijs/rehype@^1.12.1": + version "1.22.1" + resolved "https://registry.yarnpkg.com/@shikijs/rehype/-/rehype-1.22.1.tgz#0ee64085d36abd292c0837a7c1d54e25c6dbe1ac" + integrity sha512-Uuuqj/poMLj1Z02sJsS1qEqpfUNp2hV2YFVt/SY5+Ielo5Ms1bRfYQHs3hTbsEDB6FmYuOu5ieqNumPlWBmrng== + dependencies: + "@shikijs/types" "1.22.1" + "@types/hast" "^3.0.4" + hast-util-to-string "^3.0.1" + shiki "1.22.1" + unified "^11.0.5" + unist-util-visit "^5.0.0" + +"@shikijs/types@1.22.1": + version "1.22.1" + resolved "https://registry.yarnpkg.com/@shikijs/types/-/types-1.22.1.tgz#083f11539e83862542546beb4dde41ff5409fefc" + integrity sha512-+45f8mu/Hxqs6Kyhfm98Nld5n7Q7lwhjU8UtdQwrOPs7BnM4VAb929O3IQ2ce+4D7SlNFlZGd8CnKRSnwbQreQ== + dependencies: + "@shikijs/vscode-textmate" "^9.3.0" + "@types/hast" "^3.0.4" + +"@shikijs/vscode-textmate@^9.3.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@shikijs/vscode-textmate/-/vscode-textmate-9.3.0.tgz#b2f1776e488c1d6c2b6cd129bab62f71bbc9c7ab" + integrity sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA== + "@sideway/address@^4.1.5": version "4.1.5" resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.5.tgz#4bc149a0076623ced99ca8208ba780d65a99b9d5" @@ -2731,6 +2922,26 @@ micromark-util-character "^1.1.0" micromark-util-symbol "^1.0.1" +"@statsig/client-core@3.3.0": + version "3.3.0" + resolved "https://registry.yarnpkg.com/@statsig/client-core/-/client-core-3.3.0.tgz#0acff08d225be0f061c530c918e15475ca001293" + integrity sha512-4mPj0h0nGHb13tjEXdzqCa81U99nTe9N1i4DqEWYmdaH6lcZrN6ZFMhlHixqvzrtQlgaZwh0PiL9jv4grj6alQ== + +"@statsig/js-client@3.3.0", "@statsig/js-client@^3.1.0": + version "3.3.0" + resolved "https://registry.yarnpkg.com/@statsig/js-client/-/js-client-3.3.0.tgz#976d6b6bf22df861d09909ac0e1e2d63045724ce" + integrity sha512-MeMrhyH3ICjj4blOQNDU7uGcsm8hiw+ai9EV4cJw2bb0ecHCKmzc/0pNsNVkgvXQM3IWJyKKlQo0Iscq+oYRQQ== + dependencies: + "@statsig/client-core" "3.3.0" + +"@statsig/react-bindings@^3.1.0": + version "3.3.0" + resolved "https://registry.yarnpkg.com/@statsig/react-bindings/-/react-bindings-3.3.0.tgz#a8ad4da58b7bae56c5e654fb12e96d56d117a16f" + integrity sha512-t5JlUVxgg0lbaBAnwP3GCUhHY4duSTLtNR6qoOaNlFSZik2BG6Zu8t9Jc8jUp0KJwqoquMl/BPAGZ4+869sZgQ== + dependencies: + "@statsig/client-core" "3.3.0" + "@statsig/js-client" "3.3.0" + "@svgr/babel-plugin-add-jsx-attribute@8.0.0": version "8.0.0" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz#4001f5d5dd87fa13303e36ee106e3ff3a7eb8b22" @@ -3038,7 +3249,7 @@ dependencies: "@types/unist" "^2" -"@types/hast@^3.0.0": +"@types/hast@^3.0.0", "@types/hast@^3.0.4": version "3.0.4" resolved "https://registry.yarnpkg.com/@types/hast/-/hast-3.0.4.tgz#1d6b39993b82cea6ad783945b0508c25903e15aa" integrity sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ== @@ -3096,6 +3307,13 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== +"@types/mdast@^3.0.0": + version "3.0.15" + resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.15.tgz#49c524a263f30ffa28b71ae282f813ed000ab9f5" + integrity sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ== + dependencies: + "@types/unist" "^2" + "@types/mdast@^4.0.0", "@types/mdast@^4.0.2": version "4.0.4" resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-4.0.4.tgz#7ccf72edd2f1aa7dd3437e180c64373585804dd6" @@ -3259,6 +3477,11 @@ resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.10.tgz#04ffa7f406ab628f7f7e97ca23e290cd8ab15efc" integrity sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA== +"@types/unist@^2.0.3": + version "2.0.11" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.11.tgz#11af57b127e32487774841f7a4e54eab166d03c4" + integrity sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA== + "@types/ws@^8.5.5": version "8.5.11" resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.11.tgz#90ad17b3df7719ce3e6bc32f83ff954d38656508" @@ -3600,6 +3823,11 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" +ansi-styles@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + ansi-styles@^6.1.0: version "6.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" @@ -3750,6 +3978,15 @@ bcp-47-match@^1.0.0: resolved "https://registry.yarnpkg.com/bcp-47-match/-/bcp-47-match-1.0.3.tgz#cb8d03071389a10aff2062b862d6575ffd7cd7ef" integrity sha512-LggQ4YTdjWQSKELZF5JwchnBa1u0pIQSZf5lSdOHEdbVP55h0qICA/FUp3+W99q0xqxYa1ZQizTUH87gecII5w== +bcp-47@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/bcp-47/-/bcp-47-2.1.0.tgz#7e80734c3338fe8320894981dccf4968c3092df6" + integrity sha512-9IIS3UPrvIa1Ej+lVDdDwO7zLehjqsaByECw0bu2RRGP73jALm6FYbzI5gWbgHLvNdkvfXB5YrSbocZdOS0c0w== + dependencies: + is-alphabetical "^2.0.0" + is-alphanumerical "^2.0.0" + is-decimal "^2.0.0" + big.js@^5.2.2: version "5.2.2" resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" @@ -4404,7 +4641,7 @@ cosmiconfig@^6.0.0: path-type "^4.0.0" yaml "^1.7.2" -cosmiconfig@^8.1.3, cosmiconfig@^8.3.5: +cosmiconfig@^8.0.0, cosmiconfig@^8.1.3, cosmiconfig@^8.3.5: version "8.3.6" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.3.6.tgz#060a2b871d66dba6c8538ea1118ba1ac16f5fae3" integrity sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA== @@ -5307,13 +5544,6 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" -fault@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/fault/-/fault-1.0.4.tgz#eafcfc0a6d214fc94601e170df29954a4f842f13" - integrity sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA== - dependencies: - format "^0.2.0" - fault@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/fault/-/fault-2.0.1.tgz#d47ca9f37ca26e4bd38374a7c500b5a384755b6c" @@ -5781,6 +6011,19 @@ hasown@^2.0.0, hasown@^2.0.2: dependencies: function-bind "^1.1.2" +hast-to-hyperscript@^9.0.0: + version "9.0.1" + resolved "https://registry.yarnpkg.com/hast-to-hyperscript/-/hast-to-hyperscript-9.0.1.tgz#9b67fd188e4c81e8ad66f803855334173920218d" + integrity sha512-zQgLKqF+O2F72S1aa4y2ivxzSlko3MAvxkwG8ehGmNiqd98BIN3JM1rAJPmplEyLmGLO2QZYJtIneOSZ2YbJuA== + dependencies: + "@types/unist" "^2.0.3" + comma-separated-tokens "^1.0.0" + property-information "^5.3.0" + space-separated-tokens "^1.0.0" + style-to-object "^0.3.0" + unist-util-is "^4.0.0" + web-namespaces "^1.0.0" + hast-util-from-parse5@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/hast-util-from-parse5/-/hast-util-from-parse5-6.0.1.tgz#554e34abdeea25ac76f5bd950a1f0180e0b3bc2a" @@ -5890,6 +6133,23 @@ hast-util-to-estree@^3.0.0: unist-util-position "^5.0.0" zwitch "^2.0.0" +hast-util-to-html@^9.0.3: + version "9.0.3" + resolved "https://registry.yarnpkg.com/hast-util-to-html/-/hast-util-to-html-9.0.3.tgz#a9999a0ba6b4919576a9105129fead85d37f302b" + integrity sha512-M17uBDzMJ9RPCqLMO92gNNUDuBSq10a25SDBI08iCCxmorf4Yy6sYHK57n9WAbRAAaU+DuR4W6GN9K4DFZesYg== + dependencies: + "@types/hast" "^3.0.0" + "@types/unist" "^3.0.0" + ccount "^2.0.0" + comma-separated-tokens "^2.0.0" + hast-util-whitespace "^3.0.0" + html-void-elements "^3.0.0" + mdast-util-to-hast "^13.0.0" + property-information "^6.0.0" + space-separated-tokens "^2.0.0" + stringify-entities "^4.0.0" + zwitch "^2.0.4" + hast-util-to-jsx-runtime@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.0.tgz#3ed27caf8dc175080117706bf7269404a0aa4f7c" @@ -5929,6 +6189,13 @@ hast-util-to-string@^1.0.0: resolved "https://registry.yarnpkg.com/hast-util-to-string/-/hast-util-to-string-1.0.4.tgz#9b24c114866bdb9478927d7e9c36a485ac728378" integrity sha512-eK0MxRX47AV2eZ+Lyr18DCpQgodvaS3fAQO2+b9Two9F5HEoRPhiUMNzoXArMJfZi2yieFzUBMRl3HNJ3Jus3w== +hast-util-to-string@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/hast-util-to-string/-/hast-util-to-string-3.0.1.tgz#a4f15e682849326dd211c97129c94b0c3e76527c" + integrity sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A== + dependencies: + "@types/hast" "^3.0.0" + hast-util-to-text@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/hast-util-to-text/-/hast-util-to-text-2.0.1.tgz#04f2e065642a0edb08341976084aa217624a0f8b" @@ -5982,11 +6249,6 @@ hey-listen@^1.0.8: resolved "https://registry.yarnpkg.com/hey-listen/-/hey-listen-1.0.8.tgz#8e59561ff724908de1aa924ed6ecc84a56a9aa68" integrity sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q== -highlight.js@^10.4.1, highlight.js@~10.7.0: - version "10.7.3" - resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531" - integrity sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A== - history@^4.9.0: version "4.10.1" resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3" @@ -6065,11 +6327,6 @@ html-tags@^3.3.1: resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.3.1.tgz#a04026a18c882e4bba8a01a3d39cfe465d40b5ce" integrity sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ== -html-url-attributes@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/html-url-attributes/-/html-url-attributes-3.0.0.tgz#fc4abf0c3fb437e2329c678b80abb3c62cff6f08" - integrity sha512-/sXbVCWayk6GDVg3ctOX6nxaVj7So40FcFAnWlWGNAB1LpYKcV5Cd10APjPjW80O7zYW2MsjBV4zZ7IZO5fVow== - html-void-elements@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-3.0.0.tgz#fc9dbd84af9e747249034d4d62602def6517f1d7" @@ -6530,6 +6787,11 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== +iso-639-1@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/iso-639-1/-/iso-639-1-3.1.3.tgz#73c0a8d19988837e1cf5c2fa397a67f72cd34aee" + integrity sha512-1jz0Wh9hyLMRwqEPchb/KZCiTqfFWtc9R3nm7GHPygBAKS8wdKJ3FH4lvLsri6UtAE5Kz5SnowtXZa//6bqMyw== + isobject@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" @@ -6549,6 +6811,11 @@ jackspeak@^3.1.2: optionalDependencies: "@pkgjs/parseargs" "^0.11.0" +jest-get-type@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1" + integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== + jest-util@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc" @@ -6561,6 +6828,18 @@ jest-util@^29.7.0: graceful-fs "^4.2.9" picomatch "^2.2.3" +jest-validate@^29.4.3: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c" + integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw== + dependencies: + "@jest/types" "^29.6.3" + camelcase "^6.2.0" + chalk "^4.0.0" + jest-get-type "^29.6.3" + leven "^3.1.0" + pretty-format "^29.7.0" + jest-worker@^27.4.5: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" @@ -6580,7 +6859,7 @@ jest-worker@^29.4.3: merge-stream "^2.0.0" supports-color "^8.0.0" -jiti@^1.20.0: +jiti@^1.17.1, jiti@^1.20.0: version "1.21.6" resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.6.tgz#6c7f7398dd4b3142767f9a168af2f317a428d268" integrity sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w== @@ -6596,6 +6875,11 @@ joi@^17.9.2: "@sideway/formula" "^3.0.1" "@sideway/pinpoint" "^2.0.0" +js-sha256@^0.10.1: + version "0.10.1" + resolved "https://registry.yarnpkg.com/js-sha256/-/js-sha256-0.10.1.tgz#b40104ba1368e823fdd5f41b66b104b15a0da60d" + integrity sha512-5obBtsz9301ULlsgggLg542s/jqtddfOpV5KJc4hajc9JV8GeY2gZHSVpYBn4nWqAUTJ9v+xwtbJ1mIBgIH5Vw== + js-sha3@0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" @@ -6626,6 +6910,11 @@ jsesc@^2.5.1: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== +jsesc@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.0.2.tgz#bb8b09a6597ba426425f2e4a07245c3d00b9343e" + integrity sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g== + jsesc@~0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" @@ -6651,7 +6940,7 @@ json-schema-traverse@^1.0.0: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== -json5@^2.1.2, json5@^2.2.3: +json5@^2.1.2, json5@^2.2.0, json5@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== @@ -6780,6 +7069,11 @@ lodash.debounce@^4.0.8: resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== +lodash.get@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" + integrity sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ== + lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" @@ -6819,14 +7113,6 @@ lowercase-keys@^3.0.0: resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-3.0.0.tgz#c5e7d442e37ead247ae9db117a9d0a467c89d4f2" integrity sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ== -lowlight@^1.17.0: - version "1.20.0" - resolved "https://registry.yarnpkg.com/lowlight/-/lowlight-1.20.0.tgz#ddb197d33462ad0d93bf19d17b6c301aa3941888" - integrity sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw== - dependencies: - fault "^1.0.0" - highlight.js "~10.7.0" - lru-cache@^10.2.0: version "10.4.3" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" @@ -6888,6 +7174,13 @@ marked@^9.1.6: resolved "https://registry.yarnpkg.com/marked/-/marked-9.1.6.tgz#5d2a3f8180abfbc5d62e3258a38a1c19c0381695" integrity sha512-jcByLnIFkd5gSXZmjNvS1TlmRhCXZjIzHYlaGkPlLIekG55JDR2Z4va9tZwCiP+/RDERiNhMOFu01xd6O5ct1Q== +mdast-util-definitions@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz#c5c1a84db799173b4dcf7643cda999e440c24db2" + integrity sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ== + dependencies: + unist-util-visit "^2.0.0" + mdast-util-directive@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/mdast-util-directive/-/mdast-util-directive-3.0.0.tgz#3fb1764e705bbdf0afb0d3f889e4404c3e82561f" @@ -6912,6 +7205,17 @@ mdast-util-find-and-replace@^3.0.0, mdast-util-find-and-replace@^3.0.1: unist-util-is "^6.0.0" unist-util-visit-parents "^6.0.0" +mdast-util-from-markdown@^0.8.0: + version "0.8.5" + resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-0.8.5.tgz#d1ef2ca42bc377ecb0463a987910dae89bd9a28c" + integrity sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ== + dependencies: + "@types/mdast" "^3.0.0" + mdast-util-to-string "^2.0.0" + micromark "~2.11.0" + parse-entities "^2.0.0" + unist-util-stringify-position "^2.0.0" + mdast-util-from-markdown@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.1.tgz#32a6e8f512b416e1f51eb817fc64bd867ebcd9cc" @@ -7069,6 +7373,20 @@ mdast-util-phrasing@^4.0.0: "@types/mdast" "^4.0.0" unist-util-is "^6.0.0" +mdast-util-to-hast@^10.2.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-10.2.0.tgz#61875526a017d8857b71abc9333942700b2d3604" + integrity sha512-JoPBfJ3gBnHZ18icCwHR50orC9kNH81tiR1gs01D8Q5YpV6adHNO9nKNuFBCJQ941/32PT1a63UF/DitmS3amQ== + dependencies: + "@types/mdast" "^3.0.0" + "@types/unist" "^2.0.0" + mdast-util-definitions "^4.0.0" + mdurl "^1.0.0" + unist-builder "^2.0.0" + unist-util-generated "^1.0.0" + unist-util-position "^3.0.0" + unist-util-visit "^2.0.0" + mdast-util-to-hast@^13.0.0: version "13.2.0" resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz#5ca58e5b921cc0a3ded1bc02eed79a4fe4fe41f4" @@ -7098,6 +7416,11 @@ mdast-util-to-markdown@^2.0.0: unist-util-visit "^5.0.0" zwitch "^2.0.0" +mdast-util-to-string@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz#b8cfe6a713e1091cb5b728fc48885a4767f8b97b" + integrity sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w== + mdast-util-to-string@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz#7a5121475556a04e7eddeb67b264aae79d312814" @@ -7115,6 +7438,11 @@ mdn-data@2.0.30: resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.30.tgz#ce4df6f80af6cfbe218ecd5c552ba13c4dfa08cc" integrity sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA== +mdurl@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" + integrity sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g== + media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" @@ -7147,6 +7475,11 @@ merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== +messageformat-parser@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/messageformat-parser/-/messageformat-parser-4.1.3.tgz#b824787f57fcda7d50769f5b63e8d4fda68f5b9e" + integrity sha512-2fU3XDCanRqeOCkn7R5zW5VQHWf+T3hH65SzuqRvjatBK7r4uyFa5mEX+k6F9Bd04LVM5G4/BHBTUJsOdW7uyg== + methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" @@ -7568,6 +7901,14 @@ micromark@^4.0.0: micromark-util-symbol "^2.0.0" micromark-util-types "^2.0.0" +micromark@~2.11.0: + version "2.11.4" + resolved "https://registry.yarnpkg.com/micromark/-/micromark-2.11.4.tgz#d13436138eea826383e822449c9a5c50ee44665a" + integrity sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA== + dependencies: + debug "^4.0.0" + parse-entities "^2.0.0" + micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5: version "4.0.7" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.7.tgz#33e8190d9fe474a9895525f5618eee136d46c2e5" @@ -7667,6 +8008,11 @@ mkdirp@0.3.0: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e" integrity sha512-OHsdUcVAQ6pOtg5JYWpCBo9W/GySVuwvP9hueRMW7UqshC0tbfzLv8wjySTPm3tfUZ/21CE9E1pJagOA91Pxew== +moo@^0.5.1: + version "0.5.2" + resolved "https://registry.yarnpkg.com/moo/-/moo-0.5.2.tgz#f9fe82473bc7c184b0d32e2215d3f6e67278733c" + integrity sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q== + mrmime@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-2.0.0.tgz#151082a6e06e59a9a39b46b3e14d5cfe92b3abb4" @@ -7704,16 +8050,11 @@ mz@^2.7.0: object-assign "^4.0.1" thenify-all "^1.0.0" -nanoid@^3.3.7: +nanoid@3.3.7, nanoid@^3.3.7: version "3.3.7" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== -nanoid@^5.0.5: - version "5.0.7" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-5.0.7.tgz#6452e8c5a816861fd9d2b898399f7e5fd6944cc6" - integrity sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ== - negotiator@0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" @@ -7854,6 +8195,13 @@ onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" +oniguruma-to-js@0.4.3: + version "0.4.3" + resolved "https://registry.yarnpkg.com/oniguruma-to-js/-/oniguruma-to-js-0.4.3.tgz#8d899714c21f5c7d59a3c0008ca50e848086d740" + integrity sha512-X0jWUcAlxORhOqqBREgPMgnshB7ZGYszBNspP+tS9hPD3l13CdaXcHbgImoHUHlrvGx/7AvFEkTRhAGYh+jzjQ== + dependencies: + regex "^4.3.2" + open@^8.0.9, open@^8.4.0: version "8.4.2" resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" @@ -8487,6 +8835,15 @@ pretty-error@^4.0.0: lodash "^4.17.20" renderkid "^3.0.0" +pretty-format@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" + integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== + dependencies: + "@jest/schemas" "^29.6.3" + ansi-styles "^5.0.0" + react-is "^18.0.0" + pretty-time@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/pretty-time/-/pretty-time-1.1.0.tgz#ffb7429afabb8535c346a34e41873adf3d74dd0e" @@ -8500,16 +8857,11 @@ prism-react-renderer@^2.0.6, prism-react-renderer@^2.3.0: "@types/prismjs" "^1.26.0" clsx "^2.0.0" -prismjs@^1.27.0, prismjs@^1.29.0: +prismjs@^1.29.0: version "1.29.0" resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.29.0.tgz#f113555a8fa9b57c35e637bba27509dcf802dd12" integrity sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q== -prismjs@~1.27.0: - version "1.27.0" - resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.27.0.tgz#bb6ee3138a0b438a3653dd4d6ce0cc6510a45057" - integrity sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA== - process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" @@ -8532,7 +8884,7 @@ prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: object-assign "^4.1.1" react-is "^16.13.1" -property-information@^5.0.0: +property-information@^5.0.0, property-information@^5.3.0: version "5.6.0" resolved "https://registry.yarnpkg.com/property-information/-/property-information-5.6.0.tgz#61675545fb23002f245c6540ec46077d4da3ed69" integrity sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA== @@ -8598,6 +8950,11 @@ quick-lru@^5.1.1: resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== +ramda@^0.27.1: + version "0.27.2" + resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.27.2.tgz#84463226f7f36dc33592f6f4ed6374c48306c3f1" + integrity sha512-SbiLPU40JuJniHexQSAgad32hfwd+DRUdwF2PlVuI5RZD0/vahUco7R8vD86J/tcEKKF9vZrUVwgtmGCqlCKyA== + randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -8713,6 +9070,11 @@ react-is@^16.10.2, react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== +react-is@^18.0.0: + version "18.3.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" + integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== + react-json-view-lite@^1.2.0: version "1.4.0" resolved "https://registry.yarnpkg.com/react-json-view-lite/-/react-json-view-lite-1.4.0.tgz#0ff493245f4550abe5e1f1836f170fa70bb95914" @@ -8741,21 +9103,15 @@ react-loadable-ssr-addon-v5-slorber@^1.0.1: dependencies: "@types/react" "*" -react-markdown@^9.0.1: - version "9.0.1" - resolved "https://registry.yarnpkg.com/react-markdown/-/react-markdown-9.0.1.tgz#c05ddbff67fd3b3f839f8c648e6fb35d022397d1" - integrity sha512-186Gw/vF1uRkydbsOIkcGXw7aHq0sZOCRFFjGrr7b9+nVZg4UfA4enXCaxm4fUzecU38sWfrNDitGhshuU7rdg== +react-remark@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/react-remark/-/react-remark-2.1.0.tgz#dd68a32ab2d022e598b27dbfb754400e8f68555c" + integrity sha512-7dEPxRGQ23sOdvteuRGaQAs9cEOH/BOeCN4CqsJdk3laUDIDYRCWnM6a3z92PzXHUuxIRLXQNZx7SiO0ijUcbw== dependencies: - "@types/hast" "^3.0.0" - devlop "^1.0.0" - hast-util-to-jsx-runtime "^2.0.0" - html-url-attributes "^3.0.0" - mdast-util-to-hast "^13.0.0" - remark-parse "^11.0.0" - remark-rehype "^11.0.0" - unified "^11.0.0" - unist-util-visit "^5.0.0" - vfile "^6.0.0" + rehype-react "^6.0.0" + remark-parse "^9.0.0" + remark-rehype "^8.0.0" + unified "^9.0.0" react-remove-scroll-bar@^2.3.3, react-remove-scroll-bar@^2.3.4: version "2.3.6" @@ -8845,17 +9201,6 @@ react-style-singleton@^2.2.1: invariant "^2.2.4" tslib "^2.0.0" -react-syntax-highlighter@^15.5.0: - version "15.5.0" - resolved "https://registry.yarnpkg.com/react-syntax-highlighter/-/react-syntax-highlighter-15.5.0.tgz#4b3eccc2325fa2ec8eff1e2d6c18fa4a9e07ab20" - integrity sha512-+zq2myprEnQmH5yw6Gqc8lD55QHnpKaU8TOcFeC/Lg/MQSs8UknEA0JC4nTZGFAXC2J2Hyj/ijJ7NlabyPi2gg== - dependencies: - "@babel/runtime" "^7.3.1" - highlight.js "^10.4.1" - lowlight "^1.17.0" - prismjs "^1.27.0" - refractor "^3.6.0" - react-transition-group@^4.4.5: version "4.4.5" resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.5.tgz#e53d4e3f3344da8521489fbef8f2581d42becdd1" @@ -8942,15 +9287,6 @@ recursive-readdir@^2.2.2: dependencies: minimatch "^3.0.5" -refractor@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/refractor/-/refractor-3.6.0.tgz#ac318f5a0715ead790fcfb0c71f4dd83d977935a" - integrity sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA== - dependencies: - hastscript "^6.0.0" - parse-entities "^2.0.0" - prismjs "~1.27.0" - regenerate-unicode-properties@^10.1.0: version "10.1.1" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz#6b0e05489d9076b04c436f318d9b067bba459480" @@ -8982,6 +9318,11 @@ regenerator-transform@^0.15.2: dependencies: "@babel/runtime" "^7.8.4" +regex@^4.3.2: + version "4.3.3" + resolved "https://registry.yarnpkg.com/regex/-/regex-4.3.3.tgz#8cda73ccbdfa7c5691881d02f9bb142dba9daa6a" + integrity sha512-r/AadFO7owAq1QJVeZ/nq9jNS1vyZt+6t1p/E59B56Rn2GCya+gr1KSyOzNL/er+r+B7phv5jG2xU2Nz1YkmJg== + regexpu-core@^4.5.4: version "4.8.0" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.8.0.tgz#e5605ba361b67b1718478501327502f4479a98f0" @@ -9056,6 +9397,23 @@ rehype-raw@^7.0.0: hast-util-raw "^9.0.0" vfile "^6.0.0" +rehype-react@^6.0.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/rehype-react/-/rehype-react-6.2.1.tgz#9b9bf188451ad6f63796b784fe1f51165c67b73a" + integrity sha512-f9KIrjktvLvmbGc7si25HepocOg4z0MuNOtweigKzBcDjiGSTGhyz6VSgaV5K421Cq1O+z4/oxRJ5G9owo0KVg== + dependencies: + "@mapbox/hast-util-table-cell-style" "^0.2.0" + hast-to-hyperscript "^9.0.0" + +rehype-react@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/rehype-react/-/rehype-react-8.0.0.tgz#a3e2fecb10579af7bb065c7b232410a500699ba7" + integrity sha512-vzo0YxYbB2HE+36+9HWXVdxNoNDubx63r5LBzpxBGVWM8s9mdnMdbmuJBAX6TTyuGdZjZix6qU3GcSuKCIWivw== + dependencies: + "@types/hast" "^3.0.0" + hast-util-to-jsx-runtime "^2.0.0" + unified "^11.0.0" + relateurl@^0.2.7: version "0.2.7" resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" @@ -9122,6 +9480,13 @@ remark-parse@^11.0.0: micromark-util-types "^2.0.0" unified "^11.0.0" +remark-parse@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-9.0.0.tgz#4d20a299665880e4f4af5d90b7c7b8a935853640" + integrity sha512-geKatMwSzEXKHuzBNU1z676sGcDcFoChMK38TgdHJNAYfFtsfHDQG7MoJAjs6sgYMqyLduCYWDIWZIxiPeafEw== + dependencies: + mdast-util-from-markdown "^0.8.0" + remark-rehype@^11.0.0: version "11.1.0" resolved "https://registry.yarnpkg.com/remark-rehype/-/remark-rehype-11.1.0.tgz#d5f264f42bcbd4d300f030975609d01a1697ccdc" @@ -9133,6 +9498,24 @@ remark-rehype@^11.0.0: unified "^11.0.0" vfile "^6.0.0" +remark-rehype@^11.1.0: + version "11.1.1" + resolved "https://registry.yarnpkg.com/remark-rehype/-/remark-rehype-11.1.1.tgz#f864dd2947889a11997c0a2667cd6b38f685bca7" + integrity sha512-g/osARvjkBXb6Wo0XvAeXQohVta8i84ACbenPpoSsxTOQH/Ae0/RGP4WZgnMH5pMLpsj4FG7OHmcIcXxpza8eQ== + dependencies: + "@types/hast" "^3.0.0" + "@types/mdast" "^4.0.0" + mdast-util-to-hast "^13.0.0" + unified "^11.0.0" + vfile "^6.0.0" + +remark-rehype@^8.0.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/remark-rehype/-/remark-rehype-8.1.0.tgz#610509a043484c1e697437fa5eb3fd992617c945" + integrity sha512-EbCu9kHgAxKmW1yEYjx3QafMyGY3q8noUbNUI5xyKbaFP89wbhDrKxyIQNukNYthzjNHZu6J7hwFg7hRm1svYA== + dependencies: + mdast-util-to-hast "^10.2.0" + remark-stringify@^11.0.0: version "11.0.0" resolved "https://registry.yarnpkg.com/remark-stringify/-/remark-stringify-11.0.0.tgz#4c5b01dd711c269df1aaae11743eb7e2e7636fd3" @@ -9469,6 +9852,18 @@ shelljs@^0.8.5: interpret "^1.0.0" rechoir "^0.6.2" +shiki@1.22.1: + version "1.22.1" + resolved "https://registry.yarnpkg.com/shiki/-/shiki-1.22.1.tgz#78787a9d17863a6d6ce3c1f2219d4ee017dd3b0c" + integrity sha512-PbJ6XxrWLMwB2rm3qdjIHNm3zq4SfFnOx0B3rEoi4AN8AUngsdyZ1tRe5slMPtn6jQkbUURLNZPpLR7Do3k78g== + dependencies: + "@shikijs/core" "1.22.1" + "@shikijs/engine-javascript" "1.22.1" + "@shikijs/engine-oniguruma" "1.22.1" + "@shikijs/types" "1.22.1" + "@shikijs/vscode-textmate" "^9.3.0" + "@types/hast" "^3.0.4" + shiki@^0.14.7: version "0.14.7" resolved "https://registry.yarnpkg.com/shiki/-/shiki-0.14.7.tgz#c3c9e1853e9737845f1d2ef81b31bcfb07056d4e" @@ -9575,11 +9970,6 @@ solc@^0.8.25: semver "^5.5.0" tmp "0.0.33" -sonner@^1.4.41: - version "1.5.0" - resolved "https://registry.yarnpkg.com/sonner/-/sonner-1.5.0.tgz#af359f817063318415326b33aab54c5d17c747b7" - integrity sha512-FBjhG/gnnbN6FY0jaNnqZOMmB73R+5IiyYAw8yBj7L54ER7HB3fOSE5OFiQiE2iXWxeXKvg6fIP4LtVppHEdJA== - sort-css-media-queries@2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/sort-css-media-queries/-/sort-css-media-queries-2.2.0.tgz#aa33cf4a08e0225059448b6c40eddbf9f1c8334c" @@ -9775,6 +10165,13 @@ strip-json-comments@~2.0.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== +style-to-object@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-0.3.0.tgz#b1b790d205991cc783801967214979ee19a76e46" + integrity sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA== + dependencies: + inline-style-parser "0.1.1" + style-to-object@^0.4.0: version "0.4.4" resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-0.4.4.tgz#266e3dfd56391a7eefb7770423612d043c3f33ec" @@ -10105,7 +10502,7 @@ unicode-property-aliases-ecmascript@^2.0.0: resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd" integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== -unified@^11.0.0, unified@^11.0.3, unified@^11.0.4: +unified@^11.0.0, unified@^11.0.3, unified@^11.0.4, unified@^11.0.5: version "11.0.5" resolved "https://registry.yarnpkg.com/unified/-/unified-11.0.5.tgz#f66677610a5c0a9ee90cab2b8d4d66037026d9e1" integrity sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA== @@ -10137,6 +10534,11 @@ unique-string@^3.0.0: dependencies: crypto-random-string "^4.0.0" +unist-builder@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/unist-builder/-/unist-builder-2.0.3.tgz#77648711b5d86af0942f334397a33c5e91516436" + integrity sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw== + unist-util-find-after@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/unist-util-find-after/-/unist-util-find-after-3.0.0.tgz#5c65fcebf64d4f8f496db46fa8fd0fbf354b43e6" @@ -10144,6 +10546,16 @@ unist-util-find-after@^3.0.0: dependencies: unist-util-is "^4.0.0" +unist-util-generated@^1.0.0: + version "1.1.6" + resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-1.1.6.tgz#5ab51f689e2992a472beb1b35f2ce7ff2f324d4b" + integrity sha512-cln2Mm1/CZzN5ttGK7vkoGw+RZ8VcUH6BtGbq98DDtRGquAAOXig1mrBQYelOwMXYS8rK+vZDyyojSjp7JX+Lg== + +unist-util-is@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-3.0.0.tgz#d9e84381c2468e82629e4a5be9d7d05a2dd324cd" + integrity sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A== + unist-util-is@^4.0.0, unist-util-is@^4.0.2: version "4.1.0" resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-4.1.0.tgz#976e5f462a7a5de73d94b706bac1b90671b57797" @@ -10163,6 +10575,11 @@ unist-util-position-from-estree@^2.0.0: dependencies: "@types/unist" "^3.0.0" +unist-util-position@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-3.1.0.tgz#1c42ee6301f8d52f47d14f62bbdb796571fa2d47" + integrity sha512-w+PkwCbYSFw8vpgWD0v7zRCl1FpY3fjDSQ3/N/wNd9Ffa4gPi8+4keqt99N3XW6F99t/mUzp2xAhNmfKWp95QA== + unist-util-position@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-5.0.0.tgz#678f20ab5ca1207a97d7ea8a388373c9cf896be4" @@ -10192,6 +10609,13 @@ unist-util-stringify-position@^4.0.0: dependencies: "@types/unist" "^3.0.0" +unist-util-visit-parents@^2.0.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz#25e43e55312166f3348cae6743588781d112c1e9" + integrity sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g== + dependencies: + unist-util-is "^3.0.0" + unist-util-visit-parents@^3.0.0: version "3.1.1" resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz#65a6ce698f78a6b0f56aa0e88f13801886cdaef6" @@ -10208,6 +10632,13 @@ unist-util-visit-parents@^6.0.0: "@types/unist" "^3.0.0" unist-util-is "^6.0.0" +unist-util-visit@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-1.4.1.tgz#4724aaa8486e6ee6e26d7ff3c8685960d560b1e3" + integrity sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw== + dependencies: + unist-util-visit-parents "^2.0.0" + unist-util-visit@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-2.0.3.tgz#c3703893146df47203bb8a9795af47d7b971208c" @@ -10236,6 +10667,11 @@ unpipe@1.0.0, unpipe@~1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== +unraw@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/unraw/-/unraw-3.0.0.tgz#73443ed70d2ab09ccbac2b00525602d5991fbbe3" + integrity sha512-08/DA66UF65OlpUDIQtbJyrqTR0jTAlJ+jsnkQ4jxR7+K5g5YG1APZKQSMCE1vqqmD+2pv6+IdEjmopFatacvg== + update-browserslist-db@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz#7ca61c0d8650766090728046e416a8cde682859e" @@ -10718,7 +11154,7 @@ zwitch@^1.0.0: resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-1.0.5.tgz#d11d7381ffed16b742f6af7b3f223d5cd9fe9920" integrity sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw== -zwitch@^2.0.0: +zwitch@^2.0.0, zwitch@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-2.0.4.tgz#c827d4b0acb76fc3e685a4c6ec2902d51070e9d7" integrity sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A== From 69d83e72126939308bbee19be80f8edb80d64e47 Mon Sep 17 00:00:00 2001 From: Temix <57500808+TemirlanBasitov@users.noreply.github.com> Date: Wed, 30 Oct 2024 12:19:25 +0100 Subject: [PATCH 179/186] allowing to specify percentage-based factors (like 1.125 for 112.5%) (#7332) * allowing to specify percentage-based factors (like 1.125 for 112.5%) * added change log * implemented with backward compatibility for any existing users logic handled according to number or bigint added unit test * Adjusted method description --------- Co-authored-by: I744506 --- CHANGELOG.md | 6 +- packages/web3-eth/src/web3_eth.ts | 96 ++++++++++++------- .../unit/web3_eth_calculate_fee_data.test.ts | 21 ++++ 3 files changed, 85 insertions(+), 38 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d9abf6019de..c279326d17a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2754,6 +2754,10 @@ If there are any bugs, improvements, optimizations or any new feature proposal f - update the type for `baseFeePerGas` at `web3.eth.getFeeHistory` to be a number. (#7291) +#### web3-eth + +- Allow specifying percentage based factor in Web3Eth.calculateFeeData Param baseFeePerGasFactor #7332 + ### Fixed #### web3-eth-abi @@ -2770,4 +2774,4 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3-rpc-providers -- PublicNodeProvider was added (#7322) +- PublicNodeProvider was added (#7322) \ No newline at end of file diff --git a/packages/web3-eth/src/web3_eth.ts b/packages/web3-eth/src/web3_eth.ts index 6aa4f2ab89d..4f0a191d9f8 100644 --- a/packages/web3-eth/src/web3_eth.ts +++ b/packages/web3-eth/src/web3_eth.ts @@ -272,43 +272,57 @@ export class Web3Eth extends Web3Context { - * gasPrice: 20000000000n, - * maxFeePerGas: 60000000000n, - * maxPriorityFeePerGas: 20000000000n, - * baseFeePerGas: 20000000000n - * } - * - * web3.eth.calculateFeeData(1n).then(console.log); - * > { - * gasPrice: 20000000000n, - * maxFeePerGas: 40000000000n, - * maxPriorityFeePerGas: 20000000000n, - * baseFeePerGas: 20000000000n - * } - * - * web3.eth.calculateFeeData(3n).then(console.log); - * > { - * gasPrice: 20000000000n, - * maxFeePerGas: 80000000000n, - * maxPriorityFeePerGas: 20000000000n, - * baseFeePerGas: 20000000000n - * } - * ``` - */ + * Calculates the current Fee Data. + * If the node supports EIP-1559, then `baseFeePerGas` and `maxPriorityFeePerGas` will be returned along with the calculated `maxFeePerGas` value. + * `maxFeePerGas` is calculated as `baseFeePerGas` * `baseFeePerGasFactor` + `maxPriorityFeePerGas`. + * If the node does not support EIP-1559, then the `gasPrice` will be returned and the other values will be undefined. + * + * @param baseFeePerGasFactor (optional) The factor to multiply the `baseFeePerGas` with when calculating `maxFeePerGas`, if the node supports EIP-1559. This can be a `bigint` for precise calculation or a `number` to support decimals. The default value is 2 (BigInt). + * If a `number` is provided, it will be converted to `bigint` with three decimal precision. + * @param alternativeMaxPriorityFeePerGas (optional) The alternative `maxPriorityFeePerGas` to use when calculating `maxFeePerGas`, if the node supports EIP-1559 but does not support the method `eth_maxPriorityFeePerGas`. The default value is 1 gwei. + * @returns The current fee data. + * + * @example + * web3.eth.calculateFeeData().then(console.log); + * > { + * gasPrice: 20000000000n, + * maxFeePerGas: 60000000000n, + * maxPriorityFeePerGas: 20000000000n, + * baseFeePerGas: 20000000000n + * } + * + * @example + * // Using a `bigint` for baseFeePerGasFactor + * web3.eth.calculateFeeData(1n).then(console.log); + * > { + * gasPrice: 20000000000n, + * maxFeePerGas: 40000000000n, + * maxPriorityFeePerGas: 20000000000n, + * baseFeePerGas: 20000000000n + * } + * + * @example + * // Using a `number` for baseFeePerGasFactor (with decimals) + * web3.eth.calculateFeeData(1.5).then(console.log); + * > { + * gasPrice: 20000000000n, + * maxFeePerGas: 50000000000n, // baseFeePerGasFactor is converted to BigInt(1.500) + * maxPriorityFeePerGas: 20000000000n, + * baseFeePerGas: 20000000000n + * } + * + * @example + * web3.eth.calculateFeeData(3n).then(console.log); + * > { + * gasPrice: 20000000000n, + * maxFeePerGas: 80000000000n, + * maxPriorityFeePerGas: 20000000000n, + * baseFeePerGas: 20000000000n + * } + */ + public async calculateFeeData( - baseFeePerGasFactor = BigInt(2), + baseFeePerGasFactor: bigint | number = BigInt(2), alternativeMaxPriorityFeePerGas = ethUnitMap.Gwei, ): Promise { const block = await this.getBlock<{ number: FMT_NUMBER.BIGINT; bytes: FMT_BYTES.HEX }>( @@ -348,7 +362,15 @@ export class Web3Eth extends Web3Context { baseFeePerGas, }); }); + + it('should use default baseFeePerGasFactor if none is provided', async () => { + const gasPrice = BigInt(20 * 1000); + const baseFeePerGas = BigInt(1000); + const maxPriorityFeePerGas = BigInt(100); // this will be used directly + + jest.spyOn(ethRpcMethods, 'getBlockByNumber').mockReturnValueOnce({ baseFeePerGas } as any); + jest.spyOn(ethRpcMethods, 'getGasPrice').mockReturnValueOnce(gasPrice as any); + jest.spyOn(ethRpcMethods, 'getMaxPriorityFeePerGas').mockReturnValueOnce( + maxPriorityFeePerGas as any, + ); + + const feeData = await web3Eth.calculateFeeData(); // no baseFeePerGasFactor passed + const defaultBaseFeePerGasFactor = BigInt(2); + expect(feeData).toMatchObject({ + gasPrice, + maxFeePerGas: baseFeePerGas * defaultBaseFeePerGasFactor + maxPriorityFeePerGas, + maxPriorityFeePerGas, + baseFeePerGas, + }); + }); }); From 95b4bab9272f46544aecd7f034c5221e832cf2c1 Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Wed, 30 Oct 2024 07:03:10 -0700 Subject: [PATCH 180/186] Fix Link to SocketConstructorOpts Type (#7363) --- docs/docs/guides/02_web3_providers_guide/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/guides/02_web3_providers_guide/index.md b/docs/docs/guides/02_web3_providers_guide/index.md index 23937a5b84f..2fd5c9a1fd8 100644 --- a/docs/docs/guides/02_web3_providers_guide/index.md +++ b/docs/docs/guides/02_web3_providers_guide/index.md @@ -184,7 +184,7 @@ await web3.eth.getBlockNumber(); #### Configuring IPC Providers -The [`IpcProvider` constructor](/api/web3-providers-ipc/class/IpcProvider#constructor) accepts two optional parameters that can be used to configure the behavior of the `IpcProvider`: the first parameter must be of type [`SocketConstructorOpts`](https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules__types_node_net_d_._net_.socketconstructoropts.html) and the second parameter must be of type [`ReconnectOptions`](/api/web3/namespace/utils#ReconnectOptions). +The [`IpcProvider` constructor](/api/web3-providers-ipc/class/IpcProvider#constructor) accepts two optional parameters that can be used to configure the behavior of the `IpcProvider`: the first parameter must be of type [`SocketConstructorOpts`](https://docs.deno.com/api/node/net/~/SocketConstructorOpts) and the second parameter must be of type [`ReconnectOptions`](/api/web3/namespace/utils#ReconnectOptions). ```ts title='Configuring an IPC Provider' // include both optional parameters From 3283431d22bf355168ceb25abba120471778b1e0 Mon Sep 17 00:00:00 2001 From: Muhammad Altabba <24407834+Muhammad-Altabba@users.noreply.github.com> Date: Thu, 31 Oct 2024 15:10:49 +0100 Subject: [PATCH 181/186] [Snyk] Upgrade @docusaurus/core from 3.4.0 to 3.5.2 (#7365) * fix: upgrade @docusaurus/core from 3.4.0 to 3.5.2 Snyk has created this PR to upgrade @docusaurus/core from 3.4.0 to 3.5.2. See this package in yarn: @docusaurus/core See this project in Snyk: https://app.snyk.io/org/junaid-haLhdAEeRGpDte5iWFihbt/project/af7e706d-a666-4552-9392-c89c232cb8dc?utm_source=github&utm_medium=referral&page=upgrade-pr * Update Docs Dependencies --------- Co-authored-by: snyk-bot Co-authored-by: Dan Forbes --- docs/package.json | 8 +- docs/yarn.lock | 443 ++++++++++++++++++++++++---------------------- 2 files changed, 239 insertions(+), 212 deletions(-) diff --git a/docs/package.json b/docs/package.json index 3d4031e1204..9f337bbbcd3 100644 --- a/docs/package.json +++ b/docs/package.json @@ -16,9 +16,9 @@ }, "dependencies": { "@cookbookdev/docsbot": "^4.21.23", - "@docusaurus/core": "^3.0.1", - "@docusaurus/preset-classic": "^3.0.1", - "@docusaurus/theme-live-codeblock": "^3.0.1", + "@docusaurus/core": "^3.5.2", + "@docusaurus/preset-classic": "^3.5.2", + "@docusaurus/theme-live-codeblock": "^3.5.2", "@mdx-js/react": "^3.0.0", "classnames": "^2.3.2", "clsx": "^2.0.0", @@ -30,7 +30,7 @@ "devDependencies": { "@docusaurus/module-type-aliases": "^3.0.0", "@tsconfig/docusaurus": "^2.0.2", - "docusaurus-plugin-typedoc-api": "^4.0.1", + "docusaurus-plugin-typedoc-api": "^4.4.0", "typescript": "^4.6.4" }, "browserslist": { diff --git a/docs/yarn.lock b/docs/yarn.lock index bb8f6b3fcc5..eb8d7afa5c4 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -1362,10 +1362,10 @@ "@docsearch/css" "3.6.1" algoliasearch "^4.19.1" -"@docusaurus/core@3.4.0", "@docusaurus/core@^3.0.1": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/core/-/core-3.4.0.tgz#bdbf1af4b2f25d1bf4a5b62ec6137d84c821cb3c" - integrity sha512-g+0wwmN2UJsBqy2fQRQ6fhXruoEa62JDeEa5d8IdTJlMoaDaEDfHh7WjwGRn4opuTQWpjAwP/fbcgyHKlE+64w== +"@docusaurus/core@3.5.2", "@docusaurus/core@^3.5.2": + version "3.5.2" + resolved "https://registry.yarnpkg.com/@docusaurus/core/-/core-3.5.2.tgz#3adedb90e7b6104592f1231043bd6bf91680c39c" + integrity sha512-4Z1WkhCSkX4KO0Fw5m/Vuc7Q3NxBG53NE5u59Rs96fWkMPZVSrzEPP16/Nk6cWb/shK7xXPndTmalJtw7twL/w== dependencies: "@babel/core" "^7.23.3" "@babel/generator" "^7.23.3" @@ -1377,12 +1377,12 @@ "@babel/runtime" "^7.22.6" "@babel/runtime-corejs3" "^7.22.6" "@babel/traverse" "^7.22.8" - "@docusaurus/cssnano-preset" "3.4.0" - "@docusaurus/logger" "3.4.0" - "@docusaurus/mdx-loader" "3.4.0" - "@docusaurus/utils" "3.4.0" - "@docusaurus/utils-common" "3.4.0" - "@docusaurus/utils-validation" "3.4.0" + "@docusaurus/cssnano-preset" "3.5.2" + "@docusaurus/logger" "3.5.2" + "@docusaurus/mdx-loader" "3.5.2" + "@docusaurus/utils" "3.5.2" + "@docusaurus/utils-common" "3.5.2" + "@docusaurus/utils-validation" "3.5.2" autoprefixer "^10.4.14" babel-loader "^9.1.3" babel-plugin-dynamic-import-node "^2.3.3" @@ -1436,32 +1436,32 @@ webpack-merge "^5.9.0" webpackbar "^5.0.2" -"@docusaurus/cssnano-preset@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/cssnano-preset/-/cssnano-preset-3.4.0.tgz#dc7922b3bbeabcefc9b60d0161680d81cf72c368" - integrity sha512-qwLFSz6v/pZHy/UP32IrprmH5ORce86BGtN0eBtG75PpzQJAzp9gefspox+s8IEOr0oZKuQ/nhzZ3xwyc3jYJQ== +"@docusaurus/cssnano-preset@3.5.2": + version "3.5.2" + resolved "https://registry.yarnpkg.com/@docusaurus/cssnano-preset/-/cssnano-preset-3.5.2.tgz#6c1f2b2f9656f978c4694c84ab24592b04dcfab3" + integrity sha512-D3KiQXOMA8+O0tqORBrTOEQyQxNIfPm9jEaJoALjjSjc2M/ZAWcUfPQEnwr2JB2TadHw2gqWgpZckQmrVWkytA== dependencies: cssnano-preset-advanced "^6.1.2" postcss "^8.4.38" postcss-sort-media-queries "^5.2.0" tslib "^2.6.0" -"@docusaurus/logger@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/logger/-/logger-3.4.0.tgz#8b0ac05c7f3dac2009066e2f964dee8209a77403" - integrity sha512-bZwkX+9SJ8lB9kVRkXw+xvHYSMGG4bpYHKGXeXFvyVc79NMeeBSGgzd4TQLHH+DYeOJoCdl8flrFJVxlZ0wo/Q== +"@docusaurus/logger@3.5.2": + version "3.5.2" + resolved "https://registry.yarnpkg.com/@docusaurus/logger/-/logger-3.5.2.tgz#1150339ad56844b30734115c19c580f3b25cf5ed" + integrity sha512-LHC540SGkeLfyT3RHK3gAMK6aS5TRqOD4R72BEU/DE2M/TY8WwEUAMY576UUc/oNJXv8pGhBmQB6N9p3pt8LQw== dependencies: chalk "^4.1.2" tslib "^2.6.0" -"@docusaurus/mdx-loader@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/mdx-loader/-/mdx-loader-3.4.0.tgz#483d7ab57928fdbb5c8bd1678098721a930fc5f6" - integrity sha512-kSSbrrk4nTjf4d+wtBA9H+FGauf2gCax89kV8SUSJu3qaTdSIKdWERlngsiHaCFgZ7laTJ8a67UFf+xlFPtuTw== +"@docusaurus/mdx-loader@3.5.2": + version "3.5.2" + resolved "https://registry.yarnpkg.com/@docusaurus/mdx-loader/-/mdx-loader-3.5.2.tgz#99781641372c5037bcbe09bb8ade93a0e0ada57d" + integrity sha512-ku3xO9vZdwpiMIVd8BzWV0DCqGEbCP5zs1iHfKX50vw6jX8vQo0ylYo1YJMZyz6e+JFJ17HYHT5FzVidz2IflA== dependencies: - "@docusaurus/logger" "3.4.0" - "@docusaurus/utils" "3.4.0" - "@docusaurus/utils-validation" "3.4.0" + "@docusaurus/logger" "3.5.2" + "@docusaurus/utils" "3.5.2" + "@docusaurus/utils-validation" "3.5.2" "@mdx-js/mdx" "^3.0.0" "@slorber/remark-comment" "^1.0.0" escape-html "^1.0.3" @@ -1484,7 +1484,20 @@ vfile "^6.0.1" webpack "^5.88.1" -"@docusaurus/module-type-aliases@3.4.0", "@docusaurus/module-type-aliases@^3.0.0": +"@docusaurus/module-type-aliases@3.5.2": + version "3.5.2" + resolved "https://registry.yarnpkg.com/@docusaurus/module-type-aliases/-/module-type-aliases-3.5.2.tgz#4e8f9c0703e23b2e07ebfce96598ec83e4dd2a9e" + integrity sha512-Z+Xu3+2rvKef/YKTMxZHsEXp1y92ac0ngjDiExRdqGTmEKtCUpkbNYH8v5eXo5Ls+dnW88n6WTa+Q54kLOkwPg== + dependencies: + "@docusaurus/types" "3.5.2" + "@types/history" "^4.7.11" + "@types/react" "*" + "@types/react-router-config" "*" + "@types/react-router-dom" "*" + react-helmet-async "*" + react-loadable "npm:@docusaurus/react-loadable@6.0.0" + +"@docusaurus/module-type-aliases@^3.0.0": version "3.4.0" resolved "https://registry.yarnpkg.com/@docusaurus/module-type-aliases/-/module-type-aliases-3.4.0.tgz#2653bde58fc1aa3dbc626a6c08cfb63a37ae1bb8" integrity sha512-A1AyS8WF5Bkjnb8s+guTDuYmUiwJzNrtchebBHpc0gz0PyHJNMaybUlSrmJjHVcGrya0LKI4YcR3lBDQfXRYLw== @@ -1497,19 +1510,20 @@ react-helmet-async "*" react-loadable "npm:@docusaurus/react-loadable@6.0.0" -"@docusaurus/plugin-content-blog@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.4.0.tgz#6373632fdbababbda73a13c4a08f907d7de8f007" - integrity sha512-vv6ZAj78ibR5Jh7XBUT4ndIjmlAxkijM3Sx5MAAzC1gyv0vupDQNhzuFg1USQmQVj3P5I6bquk12etPV3LJ+Xw== - dependencies: - "@docusaurus/core" "3.4.0" - "@docusaurus/logger" "3.4.0" - "@docusaurus/mdx-loader" "3.4.0" - "@docusaurus/types" "3.4.0" - "@docusaurus/utils" "3.4.0" - "@docusaurus/utils-common" "3.4.0" - "@docusaurus/utils-validation" "3.4.0" - cheerio "^1.0.0-rc.12" +"@docusaurus/plugin-content-blog@3.5.2": + version "3.5.2" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.5.2.tgz#649c07c34da7603645f152bcebdf75285baed16b" + integrity sha512-R7ghWnMvjSf+aeNDH0K4fjyQnt5L0KzUEnUhmf1e3jZrv3wogeytZNN6n7X8yHcMsuZHPOrctQhXWnmxu+IRRg== + dependencies: + "@docusaurus/core" "3.5.2" + "@docusaurus/logger" "3.5.2" + "@docusaurus/mdx-loader" "3.5.2" + "@docusaurus/theme-common" "3.5.2" + "@docusaurus/types" "3.5.2" + "@docusaurus/utils" "3.5.2" + "@docusaurus/utils-common" "3.5.2" + "@docusaurus/utils-validation" "3.5.2" + cheerio "1.0.0-rc.12" feed "^4.2.2" fs-extra "^11.1.1" lodash "^4.17.21" @@ -1520,19 +1534,20 @@ utility-types "^3.10.0" webpack "^5.88.1" -"@docusaurus/plugin-content-docs@3.4.0", "@docusaurus/plugin-content-docs@^3.1.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.4.0.tgz#3088973f72169a2a6d533afccec7153c8720d332" - integrity sha512-HkUCZffhBo7ocYheD9oZvMcDloRnGhBMOZRyVcAQRFmZPmNqSyISlXA1tQCIxW+r478fty97XXAGjNYzBjpCsg== - dependencies: - "@docusaurus/core" "3.4.0" - "@docusaurus/logger" "3.4.0" - "@docusaurus/mdx-loader" "3.4.0" - "@docusaurus/module-type-aliases" "3.4.0" - "@docusaurus/types" "3.4.0" - "@docusaurus/utils" "3.4.0" - "@docusaurus/utils-common" "3.4.0" - "@docusaurus/utils-validation" "3.4.0" +"@docusaurus/plugin-content-docs@3.5.2", "@docusaurus/plugin-content-docs@^3.5.0": + version "3.5.2" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.5.2.tgz#adcf6c0bd9a9818eb192ab831e0069ee62d31505" + integrity sha512-Bt+OXn/CPtVqM3Di44vHjE7rPCEsRCB/DMo2qoOuozB9f7+lsdrHvD0QCHdBs0uhz6deYJDppAr2VgqybKPlVQ== + dependencies: + "@docusaurus/core" "3.5.2" + "@docusaurus/logger" "3.5.2" + "@docusaurus/mdx-loader" "3.5.2" + "@docusaurus/module-type-aliases" "3.5.2" + "@docusaurus/theme-common" "3.5.2" + "@docusaurus/types" "3.5.2" + "@docusaurus/utils" "3.5.2" + "@docusaurus/utils-common" "3.5.2" + "@docusaurus/utils-validation" "3.5.2" "@types/react-router-config" "^5.0.7" combine-promises "^1.1.0" fs-extra "^11.1.1" @@ -1542,118 +1557,118 @@ utility-types "^3.10.0" webpack "^5.88.1" -"@docusaurus/plugin-content-pages@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.4.0.tgz#1846172ca0355c7d32a67ef8377750ce02bbb8ad" - integrity sha512-h2+VN/0JjpR8fIkDEAoadNjfR3oLzB+v1qSXbIAKjQ46JAHx3X22n9nqS+BWSQnTnp1AjkjSvZyJMekmcwxzxg== - dependencies: - "@docusaurus/core" "3.4.0" - "@docusaurus/mdx-loader" "3.4.0" - "@docusaurus/types" "3.4.0" - "@docusaurus/utils" "3.4.0" - "@docusaurus/utils-validation" "3.4.0" +"@docusaurus/plugin-content-pages@3.5.2": + version "3.5.2" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.5.2.tgz#2b59e43f5bc5b5176ff01835de706f1c65c2e68b" + integrity sha512-WzhHjNpoQAUz/ueO10cnundRz+VUtkjFhhaQ9jApyv1a46FPURO4cef89pyNIOMny1fjDz/NUN2z6Yi+5WUrCw== + dependencies: + "@docusaurus/core" "3.5.2" + "@docusaurus/mdx-loader" "3.5.2" + "@docusaurus/types" "3.5.2" + "@docusaurus/utils" "3.5.2" + "@docusaurus/utils-validation" "3.5.2" fs-extra "^11.1.1" tslib "^2.6.0" webpack "^5.88.1" -"@docusaurus/plugin-debug@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-debug/-/plugin-debug-3.4.0.tgz#74e4ec5686fa314c26f3ac150bacadbba7f06948" - integrity sha512-uV7FDUNXGyDSD3PwUaf5YijX91T5/H9SX4ErEcshzwgzWwBtK37nUWPU3ZLJfeTavX3fycTOqk9TglpOLaWkCg== +"@docusaurus/plugin-debug@3.5.2": + version "3.5.2" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-debug/-/plugin-debug-3.5.2.tgz#c25ca6a59e62a17c797b367173fe80c06fdf2f65" + integrity sha512-kBK6GlN0itCkrmHuCS6aX1wmoWc5wpd5KJlqQ1FyrF0cLDnvsYSnh7+ftdwzt7G6lGBho8lrVwkkL9/iQvaSOA== dependencies: - "@docusaurus/core" "3.4.0" - "@docusaurus/types" "3.4.0" - "@docusaurus/utils" "3.4.0" + "@docusaurus/core" "3.5.2" + "@docusaurus/types" "3.5.2" + "@docusaurus/utils" "3.5.2" fs-extra "^11.1.1" react-json-view-lite "^1.2.0" tslib "^2.6.0" -"@docusaurus/plugin-google-analytics@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.4.0.tgz#5f59fc25329a59decc231936f6f9fb5663da3c55" - integrity sha512-mCArluxEGi3cmYHqsgpGGt3IyLCrFBxPsxNZ56Mpur0xSlInnIHoeLDH7FvVVcPJRPSQ9/MfRqLsainRw+BojA== +"@docusaurus/plugin-google-analytics@3.5.2": + version "3.5.2" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.5.2.tgz#1143e78d1461d3c74a2746f036d25b18d4a2608d" + integrity sha512-rjEkJH/tJ8OXRE9bwhV2mb/WP93V441rD6XnM6MIluu7rk8qg38iSxS43ga2V2Q/2ib53PcqbDEJDG/yWQRJhQ== dependencies: - "@docusaurus/core" "3.4.0" - "@docusaurus/types" "3.4.0" - "@docusaurus/utils-validation" "3.4.0" + "@docusaurus/core" "3.5.2" + "@docusaurus/types" "3.5.2" + "@docusaurus/utils-validation" "3.5.2" tslib "^2.6.0" -"@docusaurus/plugin-google-gtag@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.4.0.tgz#42489ac5fe1c83b5523ceedd5ef74f9aa8bc251b" - integrity sha512-Dsgg6PLAqzZw5wZ4QjUYc8Z2KqJqXxHxq3vIoyoBWiLEEfigIs7wHR+oiWUQy3Zk9MIk6JTYj7tMoQU0Jm3nqA== +"@docusaurus/plugin-google-gtag@3.5.2": + version "3.5.2" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.5.2.tgz#60b5a9e1888c4fa16933f7c5cb5f2f2c31caad3a" + integrity sha512-lm8XL3xLkTPHFKKjLjEEAHUrW0SZBSHBE1I+i/tmYMBsjCcUB5UJ52geS5PSiOCFVR74tbPGcPHEV/gaaxFeSA== dependencies: - "@docusaurus/core" "3.4.0" - "@docusaurus/types" "3.4.0" - "@docusaurus/utils-validation" "3.4.0" + "@docusaurus/core" "3.5.2" + "@docusaurus/types" "3.5.2" + "@docusaurus/utils-validation" "3.5.2" "@types/gtag.js" "^0.0.12" tslib "^2.6.0" -"@docusaurus/plugin-google-tag-manager@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.4.0.tgz#cebb03a5ffa1e70b37d95601442babea251329ff" - integrity sha512-O9tX1BTwxIhgXpOLpFDueYA9DWk69WCbDRrjYoMQtFHSkTyE7RhNgyjSPREUWJb9i+YUg3OrsvrBYRl64FCPCQ== +"@docusaurus/plugin-google-tag-manager@3.5.2": + version "3.5.2" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.5.2.tgz#7a37334d2e7f00914d61ad05bc09391c4db3bfda" + integrity sha512-QkpX68PMOMu10Mvgvr5CfZAzZQFx8WLlOiUQ/Qmmcl6mjGK6H21WLT5x7xDmcpCoKA/3CegsqIqBR+nA137lQg== dependencies: - "@docusaurus/core" "3.4.0" - "@docusaurus/types" "3.4.0" - "@docusaurus/utils-validation" "3.4.0" + "@docusaurus/core" "3.5.2" + "@docusaurus/types" "3.5.2" + "@docusaurus/utils-validation" "3.5.2" tslib "^2.6.0" -"@docusaurus/plugin-sitemap@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.4.0.tgz#b091d64d1e3c6c872050189999580187537bcbc6" - integrity sha512-+0VDvx9SmNrFNgwPoeoCha+tRoAjopwT0+pYO1xAbyLcewXSemq+eLxEa46Q1/aoOaJQ0qqHELuQM7iS2gp33Q== - dependencies: - "@docusaurus/core" "3.4.0" - "@docusaurus/logger" "3.4.0" - "@docusaurus/types" "3.4.0" - "@docusaurus/utils" "3.4.0" - "@docusaurus/utils-common" "3.4.0" - "@docusaurus/utils-validation" "3.4.0" +"@docusaurus/plugin-sitemap@3.5.2": + version "3.5.2" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.5.2.tgz#9c940b27f3461c54d65295cf4c52cb20538bd360" + integrity sha512-DnlqYyRAdQ4NHY28TfHuVk414ft2uruP4QWCH//jzpHjqvKyXjj2fmDtI8RPUBh9K8iZKFMHRnLtzJKySPWvFA== + dependencies: + "@docusaurus/core" "3.5.2" + "@docusaurus/logger" "3.5.2" + "@docusaurus/types" "3.5.2" + "@docusaurus/utils" "3.5.2" + "@docusaurus/utils-common" "3.5.2" + "@docusaurus/utils-validation" "3.5.2" fs-extra "^11.1.1" sitemap "^7.1.1" tslib "^2.6.0" -"@docusaurus/preset-classic@^3.0.1": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/preset-classic/-/preset-classic-3.4.0.tgz#6082a32fbb465b0cb2c2a50ebfc277cff2c0f139" - integrity sha512-Ohj6KB7siKqZaQhNJVMBBUzT3Nnp6eTKqO+FXO3qu/n1hJl3YLwVKTWBg28LF7MWrKu46UuYavwMRxud0VyqHg== - dependencies: - "@docusaurus/core" "3.4.0" - "@docusaurus/plugin-content-blog" "3.4.0" - "@docusaurus/plugin-content-docs" "3.4.0" - "@docusaurus/plugin-content-pages" "3.4.0" - "@docusaurus/plugin-debug" "3.4.0" - "@docusaurus/plugin-google-analytics" "3.4.0" - "@docusaurus/plugin-google-gtag" "3.4.0" - "@docusaurus/plugin-google-tag-manager" "3.4.0" - "@docusaurus/plugin-sitemap" "3.4.0" - "@docusaurus/theme-classic" "3.4.0" - "@docusaurus/theme-common" "3.4.0" - "@docusaurus/theme-search-algolia" "3.4.0" - "@docusaurus/types" "3.4.0" - -"@docusaurus/theme-classic@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-classic/-/theme-classic-3.4.0.tgz#1b0f48edec3e3ec8927843554b9f11e5927b0e52" - integrity sha512-0IPtmxsBYv2adr1GnZRdMkEQt1YW6tpzrUPj02YxNpvJ5+ju4E13J5tB4nfdaen/tfR1hmpSPlTFPvTf4kwy8Q== - dependencies: - "@docusaurus/core" "3.4.0" - "@docusaurus/mdx-loader" "3.4.0" - "@docusaurus/module-type-aliases" "3.4.0" - "@docusaurus/plugin-content-blog" "3.4.0" - "@docusaurus/plugin-content-docs" "3.4.0" - "@docusaurus/plugin-content-pages" "3.4.0" - "@docusaurus/theme-common" "3.4.0" - "@docusaurus/theme-translations" "3.4.0" - "@docusaurus/types" "3.4.0" - "@docusaurus/utils" "3.4.0" - "@docusaurus/utils-common" "3.4.0" - "@docusaurus/utils-validation" "3.4.0" +"@docusaurus/preset-classic@^3.5.2": + version "3.5.2" + resolved "https://registry.yarnpkg.com/@docusaurus/preset-classic/-/preset-classic-3.5.2.tgz#977f78510bbc556aa0539149eef960bb7ab52bd9" + integrity sha512-3ihfXQ95aOHiLB5uCu+9PRy2gZCeSZoDcqpnDvf3B+sTrMvMTr8qRUzBvWkoIqc82yG5prCboRjk1SVILKx6sg== + dependencies: + "@docusaurus/core" "3.5.2" + "@docusaurus/plugin-content-blog" "3.5.2" + "@docusaurus/plugin-content-docs" "3.5.2" + "@docusaurus/plugin-content-pages" "3.5.2" + "@docusaurus/plugin-debug" "3.5.2" + "@docusaurus/plugin-google-analytics" "3.5.2" + "@docusaurus/plugin-google-gtag" "3.5.2" + "@docusaurus/plugin-google-tag-manager" "3.5.2" + "@docusaurus/plugin-sitemap" "3.5.2" + "@docusaurus/theme-classic" "3.5.2" + "@docusaurus/theme-common" "3.5.2" + "@docusaurus/theme-search-algolia" "3.5.2" + "@docusaurus/types" "3.5.2" + +"@docusaurus/theme-classic@3.5.2": + version "3.5.2" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-classic/-/theme-classic-3.5.2.tgz#602ddb63d987ab1f939e3760c67bc1880f01c000" + integrity sha512-XRpinSix3NBv95Rk7xeMF9k4safMkwnpSgThn0UNQNumKvmcIYjfkwfh2BhwYh/BxMXQHJ/PdmNh22TQFpIaYg== + dependencies: + "@docusaurus/core" "3.5.2" + "@docusaurus/mdx-loader" "3.5.2" + "@docusaurus/module-type-aliases" "3.5.2" + "@docusaurus/plugin-content-blog" "3.5.2" + "@docusaurus/plugin-content-docs" "3.5.2" + "@docusaurus/plugin-content-pages" "3.5.2" + "@docusaurus/theme-common" "3.5.2" + "@docusaurus/theme-translations" "3.5.2" + "@docusaurus/types" "3.5.2" + "@docusaurus/utils" "3.5.2" + "@docusaurus/utils-common" "3.5.2" + "@docusaurus/utils-validation" "3.5.2" "@mdx-js/react" "^3.0.0" clsx "^2.0.0" copy-text-to-clipboard "^3.2.0" - infima "0.2.0-alpha.43" + infima "0.2.0-alpha.44" lodash "^4.17.21" nprogress "^0.2.0" postcss "^8.4.26" @@ -1664,18 +1679,15 @@ tslib "^2.6.0" utility-types "^3.10.0" -"@docusaurus/theme-common@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-common/-/theme-common-3.4.0.tgz#01f2b728de6cb57f6443f52fc30675cf12a5d49f" - integrity sha512-0A27alXuv7ZdCg28oPE8nH/Iz73/IUejVaCazqu9elS4ypjiLhK3KfzdSQBnL/g7YfHSlymZKdiOHEo8fJ0qMA== - dependencies: - "@docusaurus/mdx-loader" "3.4.0" - "@docusaurus/module-type-aliases" "3.4.0" - "@docusaurus/plugin-content-blog" "3.4.0" - "@docusaurus/plugin-content-docs" "3.4.0" - "@docusaurus/plugin-content-pages" "3.4.0" - "@docusaurus/utils" "3.4.0" - "@docusaurus/utils-common" "3.4.0" +"@docusaurus/theme-common@3.5.2": + version "3.5.2" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-common/-/theme-common-3.5.2.tgz#b507ab869a1fba0be9c3c9d74f2f3d74c3ac78b2" + integrity sha512-QXqlm9S6x9Ibwjs7I2yEDgsCocp708DrCrgHgKwg2n2AY0YQ6IjU0gAK35lHRLOvAoJUfCKpQAwUykB0R7+Eew== + dependencies: + "@docusaurus/mdx-loader" "3.5.2" + "@docusaurus/module-type-aliases" "3.5.2" + "@docusaurus/utils" "3.5.2" + "@docusaurus/utils-common" "3.5.2" "@types/history" "^4.7.11" "@types/react" "*" "@types/react-router-config" "*" @@ -1685,34 +1697,34 @@ tslib "^2.6.0" utility-types "^3.10.0" -"@docusaurus/theme-live-codeblock@^3.0.1": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-live-codeblock/-/theme-live-codeblock-3.4.0.tgz#1de96234eea796a031f9455169e7f75151c3d9e4" - integrity sha512-UvsYhN6aTQiQlhY6cd0I4ckNbyZ/pQVKtKNRw3ojr+SPXYqSyXTpFzcuTUYcglKFVz1IK7LeeFymGFnsfkCWmw== +"@docusaurus/theme-live-codeblock@^3.5.2": + version "3.5.2" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-live-codeblock/-/theme-live-codeblock-3.5.2.tgz#1a39505f1b221b76a0860aa8e30437f1f963e929" + integrity sha512-/jr+xvmJmvPhZsqUXQ+SGuI38qCb4dR9IZu0e+UA5my4pO63h//Nnf73naTiK3DYeszK+E0dyULPyWszVpjjOw== dependencies: - "@docusaurus/core" "3.4.0" - "@docusaurus/theme-common" "3.4.0" - "@docusaurus/theme-translations" "3.4.0" - "@docusaurus/utils-validation" "3.4.0" + "@docusaurus/core" "3.5.2" + "@docusaurus/theme-common" "3.5.2" + "@docusaurus/theme-translations" "3.5.2" + "@docusaurus/utils-validation" "3.5.2" "@philpl/buble" "^0.19.7" clsx "^2.0.0" fs-extra "^11.1.1" react-live "^4.1.6" tslib "^2.6.0" -"@docusaurus/theme-search-algolia@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.4.0.tgz#c499bad71d668df0d0f15b0e5e33e2fc4e330fcc" - integrity sha512-aiHFx7OCw4Wck1z6IoShVdUWIjntC8FHCw9c5dR8r3q4Ynh+zkS8y2eFFunN/DL6RXPzpnvKCg3vhLQYJDmT9Q== +"@docusaurus/theme-search-algolia@3.5.2": + version "3.5.2" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.5.2.tgz#466c83ca7e8017d95ae6889ccddc5ef8bf6b61c6" + integrity sha512-qW53kp3VzMnEqZGjakaV90sst3iN1o32PH+nawv1uepROO8aEGxptcq2R5rsv7aBShSRbZwIobdvSYKsZ5pqvA== dependencies: "@docsearch/react" "^3.5.2" - "@docusaurus/core" "3.4.0" - "@docusaurus/logger" "3.4.0" - "@docusaurus/plugin-content-docs" "3.4.0" - "@docusaurus/theme-common" "3.4.0" - "@docusaurus/theme-translations" "3.4.0" - "@docusaurus/utils" "3.4.0" - "@docusaurus/utils-validation" "3.4.0" + "@docusaurus/core" "3.5.2" + "@docusaurus/logger" "3.5.2" + "@docusaurus/plugin-content-docs" "3.5.2" + "@docusaurus/theme-common" "3.5.2" + "@docusaurus/theme-translations" "3.5.2" + "@docusaurus/utils" "3.5.2" + "@docusaurus/utils-validation" "3.5.2" algoliasearch "^4.18.0" algoliasearch-helper "^3.13.3" clsx "^2.0.0" @@ -1722,15 +1734,15 @@ tslib "^2.6.0" utility-types "^3.10.0" -"@docusaurus/theme-translations@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-translations/-/theme-translations-3.4.0.tgz#e6355d01352886c67e38e848b2542582ea3070af" - integrity sha512-zSxCSpmQCCdQU5Q4CnX/ID8CSUUI3fvmq4hU/GNP/XoAWtXo9SAVnM3TzpU8Gb//H3WCsT8mJcTfyOk3d9ftNg== +"@docusaurus/theme-translations@3.5.2": + version "3.5.2" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-translations/-/theme-translations-3.5.2.tgz#38f9ebf2a5d860397022206a05fef66c08863c89" + integrity sha512-GPZLcu4aT1EmqSTmbdpVrDENGR2yObFEX8ssEFYTCiAIVc0EihNSdOIBTazUvgNqwvnoU1A8vIs1xyzc3LITTw== dependencies: fs-extra "^11.1.1" tslib "^2.6.0" -"@docusaurus/types@3.4.0", "@docusaurus/types@^3.1.0": +"@docusaurus/types@3.4.0": version "3.4.0" resolved "https://registry.yarnpkg.com/@docusaurus/types/-/types-3.4.0.tgz#237c3f737e9db3f7c1a5935a3ef48d6eadde8292" integrity sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A== @@ -1745,34 +1757,49 @@ webpack "^5.88.1" webpack-merge "^5.9.0" -"@docusaurus/utils-common@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/utils-common/-/utils-common-3.4.0.tgz#2a43fefd35b85ab9fcc6833187e66c15f8bfbbc6" - integrity sha512-NVx54Wr4rCEKsjOH5QEVvxIqVvm+9kh7q8aYTU5WzUU9/Hctd6aTrcZ3G0Id4zYJ+AeaG5K5qHA4CY5Kcm2iyQ== +"@docusaurus/types@3.5.2", "@docusaurus/types@^3.5.0": + version "3.5.2" + resolved "https://registry.yarnpkg.com/@docusaurus/types/-/types-3.5.2.tgz#058019dbeffbee2d412c3f72569e412a727f9608" + integrity sha512-N6GntLXoLVUwkZw7zCxwy9QiuEXIcTVzA9AkmNw16oc0AP3SXLrMmDMMBIfgqwuKWa6Ox6epHol9kMtJqekACw== + dependencies: + "@mdx-js/mdx" "^3.0.0" + "@types/history" "^4.7.11" + "@types/react" "*" + commander "^5.1.0" + joi "^17.9.2" + react-helmet-async "^1.3.0" + utility-types "^3.10.0" + webpack "^5.88.1" + webpack-merge "^5.9.0" + +"@docusaurus/utils-common@3.5.2": + version "3.5.2" + resolved "https://registry.yarnpkg.com/@docusaurus/utils-common/-/utils-common-3.5.2.tgz#4d7f5e962fbca3e2239d80457aa0e4bd3d8f7e0a" + integrity sha512-i0AZjHiRgJU6d7faQngIhuHKNrszpL/SHQPgF1zH4H+Ij6E9NBYGy6pkcGWToIv7IVPbs+pQLh1P3whn0gWXVg== dependencies: tslib "^2.6.0" -"@docusaurus/utils-validation@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/utils-validation/-/utils-validation-3.4.0.tgz#0176f6e503ff45f4390ec2ecb69550f55e0b5eb7" - integrity sha512-hYQ9fM+AXYVTWxJOT1EuNaRnrR2WGpRdLDQG07O8UOpsvCPWUVOeo26Rbm0JWY2sGLfzAb+tvJ62yF+8F+TV0g== +"@docusaurus/utils-validation@3.5.2": + version "3.5.2" + resolved "https://registry.yarnpkg.com/@docusaurus/utils-validation/-/utils-validation-3.5.2.tgz#1b2b2f02082781cc8ce713d4c85e88d6d2fc4eb3" + integrity sha512-m+Foq7augzXqB6HufdS139PFxDC5d5q2QKZy8q0qYYvGdI6nnlNsGH4cIGsgBnV7smz+mopl3g4asbSDvMV0jA== dependencies: - "@docusaurus/logger" "3.4.0" - "@docusaurus/utils" "3.4.0" - "@docusaurus/utils-common" "3.4.0" + "@docusaurus/logger" "3.5.2" + "@docusaurus/utils" "3.5.2" + "@docusaurus/utils-common" "3.5.2" fs-extra "^11.2.0" joi "^17.9.2" js-yaml "^4.1.0" lodash "^4.17.21" tslib "^2.6.0" -"@docusaurus/utils@3.4.0", "@docusaurus/utils@^3.1.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/utils/-/utils-3.4.0.tgz#c508e20627b7a55e2b541e4a28c95e0637d6a204" - integrity sha512-fRwnu3L3nnWaXOgs88BVBmG1yGjcQqZNHG+vInhEa2Sz2oQB+ZjbEMO5Rh9ePFpZ0YDiDUhpaVjwmS+AU2F14g== +"@docusaurus/utils@3.5.2", "@docusaurus/utils@^3.5.0": + version "3.5.2" + resolved "https://registry.yarnpkg.com/@docusaurus/utils/-/utils-3.5.2.tgz#17763130215f18d7269025903588ef7fb373e2cb" + integrity sha512-33QvcNFh+Gv+C2dP9Y9xWEzMgf3JzrpL2nW9PopidiohS1nDcyknKRx2DWaFvyVTTYIkkABVSr073VTj/NITNA== dependencies: - "@docusaurus/logger" "3.4.0" - "@docusaurus/utils-common" "3.4.0" + "@docusaurus/logger" "3.5.2" + "@docusaurus/utils-common" "3.5.2" "@svgr/webpack" "^8.1.0" escape-string-regexp "^4.0.0" file-loader "^6.2.0" @@ -3511,10 +3538,10 @@ resolved "https://registry.yarnpkg.com/@vercel/edge/-/edge-1.1.2.tgz#b89bc5fa927b9af64c99311afb4dcf48e7b9e87a" integrity sha512-wt5SnhsMahWX8U9ZZhFUQoiXhMn/CUxA5xeMdZX1cwyOL1ZbDR3rNI8HRT9RSU73nDxeF6jlnqJyp/0Jy0VM2A== -"@vscode/codicons@^0.0.35": - version "0.0.35" - resolved "https://registry.yarnpkg.com/@vscode/codicons/-/codicons-0.0.35.tgz#7424a647f39c6e71c86c1edf12bfc27196c8fba1" - integrity sha512-7iiKdA5wHVYSbO7/Mm0hiHD3i4h+9hKUe1O4hISAe/nHhagMwb2ZbFC8jU6d7Cw+JNT2dWXN2j+WHbkhT5/l2w== +"@vscode/codicons@^0.0.36": + version "0.0.36" + resolved "https://registry.yarnpkg.com/@vscode/codicons/-/codicons-0.0.36.tgz#ccdabfaef5db596b266644ab85fc25aa701058f0" + integrity sha512-wsNOvNMMJ2BY8rC2N2MNBG7yOowV3ov8KlvUE/AiVUlHKTfWsw3OgAOQduX7h0Un6GssKD3aoTVH+TF3DSQwKQ== "@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.12.1": version "1.12.1" @@ -4293,7 +4320,7 @@ cheerio-select@^2.1.0: domhandler "^5.0.3" domutils "^3.0.1" -cheerio@^1.0.0-rc.12: +cheerio@1.0.0-rc.12: version "1.0.0-rc.12" resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.12.tgz#788bf7466506b1c6bf5fae51d24a2c4d62e47683" integrity sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q== @@ -5099,15 +5126,15 @@ docusaurus-lunr-search@^3.3.1: unified "^9.0.0" unist-util-is "^4.0.2" -docusaurus-plugin-typedoc-api@^4.0.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/docusaurus-plugin-typedoc-api/-/docusaurus-plugin-typedoc-api-4.2.0.tgz#201a55f53d10a87d532fe4eeab3fbf5580aa6a5f" - integrity sha512-jD31Ro2joo7U8Yyru7oPKnqOrN/Vd6uQQxmbTrTzbTp0Br4Odw1W+YxW4DLqm+CCFryMP3Ru1p4qSLFbq4uj5A== +docusaurus-plugin-typedoc-api@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/docusaurus-plugin-typedoc-api/-/docusaurus-plugin-typedoc-api-4.4.0.tgz#b6a10538ce13dbbc51b882c464ce5d891ae7c779" + integrity sha512-7crE/IO2qh4WztNQThIlXiSgToFLb57urYz5VKnHVGuwTxLfStWaXoAGKB60s+XAaLFuTh7wUI93fx72wIdC3w== dependencies: - "@docusaurus/plugin-content-docs" "^3.1.0" - "@docusaurus/types" "^3.1.0" - "@docusaurus/utils" "^3.1.0" - "@vscode/codicons" "^0.0.35" + "@docusaurus/plugin-content-docs" "^3.5.0" + "@docusaurus/types" "^3.5.0" + "@docusaurus/utils" "^3.5.0" + "@vscode/codicons" "^0.0.36" marked "^9.1.6" marked-smartypants "^1.1.5" typedoc "^0.25.7" @@ -6499,10 +6526,10 @@ indent-string@^4.0.0: resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== -infima@0.2.0-alpha.43: - version "0.2.0-alpha.43" - resolved "https://registry.yarnpkg.com/infima/-/infima-0.2.0-alpha.43.tgz#f7aa1d7b30b6c08afef441c726bac6150228cbe0" - integrity sha512-2uw57LvUqW0rK/SWYnd/2rRfxNA5DDNOh33jxF7fy46VWoNhGxiUQyVZHbBMjQ33mQem0cjdDVwgWVAmlRfgyQ== +infima@0.2.0-alpha.44: + version "0.2.0-alpha.44" + resolved "https://registry.yarnpkg.com/infima/-/infima-0.2.0-alpha.44.tgz#9cd9446e473b44d49763f48efabe31f32440861d" + integrity sha512-tuRkUSO/lB3rEhLJk25atwAjgLuzq070+pOW8XcvpHky/YbENnRRdPd85IBkyeTgttmOy5ah+yHYsK1HhUd4lQ== inflight@^1.0.4: version "1.0.6" From 4aaf91505cbb63650d97e5739f162585a5aa439a Mon Sep 17 00:00:00 2001 From: blackmoshui Date: Mon, 4 Nov 2024 20:54:14 +0800 Subject: [PATCH 182/186] Add accout.signRaw function to sign a message without prefix (#7346) * workable code and test * refine comments and docs * add parallel test back * using default value instead of ? * update changelog * update changelog * remove wrong doc * update package changelog * Update CHANGELOG.md --- CHANGELOG.md | 6 +- docs/docs/guides/03_wallet/index.md | 1 + packages/web3-eth-accounts/CHANGELOG.md | 4 + packages/web3-eth-accounts/src/account.ts | 47 ++++++++++- .../test/fixtures/account.ts | 83 +++++++++++++++++++ .../test/integration/account.test.ts | 34 ++++++++ .../test/unit/account.test.ts | 34 ++++++++ .../test/unit/account_dom.test.ts | 34 ++++++++ 8 files changed, 239 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c279326d17a..d96a9e23283 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2772,6 +2772,10 @@ If there are any bugs, improvements, optimizations or any new feature proposal f ### Added +#### web3-eth-accounts + +- `hashMessage` now has a new optional param `skipPrefix` with a default value of `false`. A new function `signRaw` was added to sign a message without prefix. (#7346) + #### web3-rpc-providers -- PublicNodeProvider was added (#7322) \ No newline at end of file +- PublicNodeProvider was added (#7322) diff --git a/docs/docs/guides/03_wallet/index.md b/docs/docs/guides/03_wallet/index.md index d93ba737a50..5a8c7e270a5 100644 --- a/docs/docs/guides/03_wallet/index.md +++ b/docs/docs/guides/03_wallet/index.md @@ -90,6 +90,7 @@ The following is a list of [`Accounts`](/libdocs/Accounts) methods in the `web3. - [recover](/libdocs/Accounts#recover) - [recoverTransaction](/libdocs/Accounts#recovertransaction) - [sign](/libdocs/Accounts#sign) +- [signRaw](/libdocs/Accounts#signraw) - [signTransaction](/libdocs/Accounts#signtransaction) ## Wallets diff --git a/packages/web3-eth-accounts/CHANGELOG.md b/packages/web3-eth-accounts/CHANGELOG.md index dc08d0cc692..22498dca080 100644 --- a/packages/web3-eth-accounts/CHANGELOG.md +++ b/packages/web3-eth-accounts/CHANGELOG.md @@ -184,3 +184,7 @@ Documentation: - Revert `TransactionFactory.registerTransactionType` if there is a version mistatch between `web3-eth` and `web3-eth-accounts` and fix nextjs problem. (#7216) ## [Unreleased] + +### Added + +- `hashMessage` now has a new optional param `skipPrefix` with a default value of `false`. A new function `signRaw` was added to sign a message without prefix. (#7346) diff --git a/packages/web3-eth-accounts/src/account.ts b/packages/web3-eth-accounts/src/account.ts index e928a95f53f..511ebcc92d2 100644 --- a/packages/web3-eth-accounts/src/account.ts +++ b/packages/web3-eth-accounts/src/account.ts @@ -144,6 +144,7 @@ export const parseAndValidatePrivateKey = (data: Bytes, ignoreLength?: boolean): * `"\x19Ethereum Signed Message:\n" + message.length + message` and hashed using keccak256. * * @param message - A message to hash, if its HEX it will be UTF8 decoded. + * @param skipPrefix - (default: false) If true, the message will be not prefixed with "\x19Ethereum Signed Message:\n" + message.length * @returns The hashed message * * ```ts @@ -154,9 +155,13 @@ export const parseAndValidatePrivateKey = (data: Bytes, ignoreLength?: boolean): * web3.eth.accounts.hashMessage(web3.utils.utf8ToHex("Hello world")) // Will be hex decoded in hashMessage * * > "0x8144a6fa26be252b86456491fbcd43c1de7e022241845ffea1c3df066f7cfede" + * + * web3.eth.accounts.hashMessage("Hello world", true) + * + * > "0xed6c11b0b5b808960df26f5bfc471d04c1995b0ffd2055925ad1be28d6baadfd" * ``` */ -export const hashMessage = (message: string): string => { +export const hashMessage = (message: string, skipPrefix = false): string => { const messageHex = isHexStrict(message) ? message : utf8ToHex(message); const messageBytes = hexToBytes(messageHex); @@ -165,7 +170,7 @@ export const hashMessage = (message: string): string => { fromUtf8(`\x19Ethereum Signed Message:\n${messageBytes.byteLength}`), ); - const ethMessage = uint8ArrayConcat(preamble, messageBytes); + const ethMessage = skipPrefix ? messageBytes : uint8ArrayConcat(preamble, messageBytes); return sha3Raw(ethMessage); // using keccak in web3-utils.sha3Raw instead of SHA3 (NIST Standard) as both are different }; @@ -230,6 +235,42 @@ export const sign = (data: string, privateKey: Bytes): SignResult => { }; }; +/** + * Signs raw data with a given private key without adding the Ethereum-specific prefix. + * + * @param data - The raw data to sign. If it's a hex string, it will be used as-is. Otherwise, it will be UTF-8 encoded. + * @param privateKey - The 32 byte private key to sign with + * @returns The signature Object containing the message, messageHash, signature r, s, v + * + * ```ts + * web3.eth.accounts.signRaw('Some data', '0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318') + * > { + * message: 'Some data', + * messageHash: '0x43a26051362b8040b289abe93334a5e3662751aa691185ae9e9a2e1e0c169350', + * v: '0x1b', + * r: '0x93da7e2ddd6b2ff1f5af0c752f052ed0d7d5bff19257db547a69cd9a879b37d4', + * s: '0x334485e42b33815fd2cf8a245a5393b282214060844a9681495df2257140e75c', + * signature: '0x93da7e2ddd6b2ff1f5af0c752f052ed0d7d5bff19257db547a69cd9a879b37d4334485e42b33815fd2cf8a245a5393b282214060844a9681495df2257140e75c1b' + * } + * ``` + */ +export const signRaw = (data: string, privateKey: Bytes): SignResult => { + // Hash the message without the Ethereum-specific prefix + const hash = hashMessage(data, true); + + // Sign the hash with the private key + const { messageHash, v, r, s, signature } = signMessageWithPrivateKey(hash, privateKey); + + return { + message: data, + messageHash, + v, + r, + s, + signature, + }; +}; + /** * Signs an Ethereum transaction with a given private key. * @@ -380,7 +421,7 @@ export const recoverTransaction = (rawTransaction: HexString): Address => { * @param signatureOrV - signature or V * @param prefixedOrR - prefixed or R * @param s - S value in signature - * @param prefixed - (default: false) If the last parameter is true, the given message will NOT automatically be prefixed with `"\\x19Ethereum Signed Message:\\n" + message.length + message`, and assumed to be already prefixed. + * @param prefixed - (default: false) If the last parameter is true, the given message will NOT automatically be prefixed with `"\\x19Ethereum Signed Message:\\n" + message.length + message`, and assumed to be already prefixed and hashed. * @returns The Ethereum address used to sign this data * * ```ts diff --git a/packages/web3-eth-accounts/test/fixtures/account.ts b/packages/web3-eth-accounts/test/fixtures/account.ts index 08c6a19ef54..0ccb52c9bec 100644 --- a/packages/web3-eth-accounts/test/fixtures/account.ts +++ b/packages/web3-eth-accounts/test/fixtures/account.ts @@ -164,6 +164,79 @@ export const signatureRecoverData: [string, any][] = [ ], ]; +export const signatureRecoverWithoutPrefixData: [string, any][] = [ + [ + 'Some long text with integers 1233 and special characters and unicode \u1234 as well.', + { + prefixedOrR: true, + r: '0x66ff35193d5763bbb86428b87cd10451704fa1d00a8831e75cc0eca16701521d', + s: '0x5ec294b63778e854929a53825191222415bf93871d091a137f61d92f2f3d37bb', + address: '0x6E599DA0bfF7A6598AC1224E4985430Bf16458a4', + privateKey: '0xcb89ec4b01771c6c8272f4c0aafba2f8ee0b101afb22273b786939a8af7c1912', + data: 'Some long text with integers 1233 and special characters and unicode \u1234 as well.', + // signature done with personal_sign + signatureOrV: + '0x66ff35193d5763bbb86428b87cd10451704fa1d00a8831e75cc0eca16701521d5ec294b63778e854929a53825191222415bf93871d091a137f61d92f2f3d37bb1b', + }, + ], + [ + 'Some data', + { + prefixedOrR: true, + r: '0xbbae52f4cd6776e66e01673228474866cead8ccc9530e0ae06b42d0f5917865f', + s: '0x170e7a9e792288955e884c9b2da7d2c69b69d3b29e24372d1dec1164a7deaec0', + address: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', + privateKey: '0xbe6383dad004f233317e46ddb46ad31b16064d14447a95cc1d8c8d4bc61c3728', + data: 'Some data', + // signature done with personal_sign + signatureOrV: + '0xbbae52f4cd6776e66e01673228474866cead8ccc9530e0ae06b42d0f5917865f170e7a9e792288955e884c9b2da7d2c69b69d3b29e24372d1dec1164a7deaec01c', + }, + ], + [ + 'Some data!%$$%&@*', + { + prefixedOrR: true, + r: '0x91b3ccd107995becaca361e9f282723176181bb9250e8ebb8a5119f5e0b91978', + s: '0x5e67773c632e036712befe130577d2954b91f7c5fb4999bc94d80d471dfd468b', + address: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', + privateKey: '0xbe6383dad004f233317e46ddb46ad31b16064d14447a95cc1d8c8d4bc61c3728', + data: 'Some data!%$$%&@*', + // signature done with personal_sign + signatureOrV: + '0x91b3ccd107995becaca361e9f282723176181bb9250e8ebb8a5119f5e0b919785e67773c632e036712befe130577d2954b91f7c5fb4999bc94d80d471dfd468b1c', + }, + ], + [ + '102', + { + prefixedOrR: true, + r: '0xecbd18fc2919bef2a9371536df0fbabdb09fda9823b15c5ce816ab71d7b5e359', + s: '0x3860327ffde34fe72ae5d6abdcdc91e984f936ea478cfb8b1547383d6e4d6a98', + address: '0xEB014f8c8B418Db6b45774c326A0E64C78914dC0', + privateKey: '0xbe6383dad004f233317e46ddb46ad31b16064d14447a95cc1d8c8d4bc61c3728', + data: '102', + // signature done with personal_sign + signatureOrV: + '0xecbd18fc2919bef2a9371536df0fbabdb09fda9823b15c5ce816ab71d7b5e3593860327ffde34fe72ae5d6abdcdc91e984f936ea478cfb8b1547383d6e4d6a981b', + }, + ], + [ + // testcase for recover(data, V, R, S) + 'some data', + { + signatureOrV: '0x1b', + prefixedOrR: '0x48f828a3ed107ce28551a3264d75b18df806d6960c273396dc022baadd0cf26e', + r: '0x48f828a3ed107ce28551a3264d75b18df806d6960c273396dc022baadd0cf26e', + s: '0x373e1b6709512c2dab9dff4066c6b40d32bd747bdb84469023952bc82123e8cc', + address: '0x54BF9ed7F22b64a5D69Beea57cFCd378763bcdc5', + privateKey: '0x03a0021a87dc354855f900fd15c063bcc9c155c33b8f2321ec294e0933ef29d2', + signature: + '0x48f828a3ed107ce28551a3264d75b18df806d6960c273396dc022baadd0cf26e373e1b6709512c2dab9dff4066c6b40d32bd747bdb84469023952bc82123e8cc1b', + }, + ], +]; + export const transactionsTestData: [TxData | AccessListEIP2930TxData | FeeMarketEIP1559TxData][] = [ [ // 'TxLegacy' @@ -526,3 +599,13 @@ export const validHashMessageData: [string, string][] = [ ['non utf8 string', '0x8862c6a425a83c082216090e4f0e03b64106189e93c29b11d0112e77b477cce2'], ['', '0x5f35dce98ba4fba25530a026ed80b2cecdaa31091ba4958b99b52ea1d068adad'], ]; + +export const validHashMessageWithoutPrefixData: [string, string][] = [ + ['🤗', '0x4bf650e97ac50e9e4b4c51deb9e01455c1a9b2f35143bc0a43f1ea5bc9e51856'], + [ + 'Some long text with integers 1233 and special characters and unicode \u1234 as well.', + '0x6965440cc2890e0f118738d6300a21afb2de316c578dad144aa55c9ea45c0fa7', + ], + ['non utf8 string', '0x52000fc43fe3aa422eecafff3e0d82205a1409850c4bd2871dfde932de1fec13'], + ['', '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470'], +]; diff --git a/packages/web3-eth-accounts/test/integration/account.test.ts b/packages/web3-eth-accounts/test/integration/account.test.ts index 06b703e496f..c4986b8a5a2 100644 --- a/packages/web3-eth-accounts/test/integration/account.test.ts +++ b/packages/web3-eth-accounts/test/integration/account.test.ts @@ -27,6 +27,7 @@ import { recover, recoverTransaction, sign, + signRaw, signTransaction, } from '../../src'; import { TransactionFactory } from '../../src/tx/transactionFactory'; @@ -37,10 +38,12 @@ import { invalidPrivateKeytoAccountData, invalidPrivateKeyToAddressData, signatureRecoverData, + signatureRecoverWithoutPrefixData, transactionsTestData, validDecryptData, validEncryptData, validHashMessageData, + validHashMessageWithoutPrefixData, validPrivateKeytoAccountData, validPrivateKeyToAddressData, } from '../fixtures/account'; @@ -128,6 +131,12 @@ describe('accounts', () => { }); }); + describe('Hash Message Without Prefix', () => { + it.each(validHashMessageWithoutPrefixData)('%s', (message, hash) => { + expect(hashMessage(message, true)).toEqual(hash); + }); + }); + describe('Sign Message', () => { describe('sign', () => { it.each(signatureRecoverData)('%s', (data, testObj) => { @@ -144,6 +153,31 @@ describe('accounts', () => { }); }); + describe('Sign Raw Message', () => { + describe('signRaw', () => { + it.each(signatureRecoverWithoutPrefixData)('%s', (data, testObj) => { + const result = signRaw(data, testObj.privateKey); + expect(result.signature).toEqual(testObj.signature || testObj.signatureOrV); // makes sure we get signature and not V value + expect(result.r).toEqual(testObj.r); + expect(result.s).toEqual(testObj.s); + }); + }); + + describe('recover', () => { + it.each(signatureRecoverWithoutPrefixData)('%s', (data, testObj) => { + const hashedMessage = hashMessage(data, true); // hash the message first without prefix + const address = recover( + hashedMessage, + testObj.signatureOrV, + testObj.prefixedOrR, + testObj.s, + true, // make sure the prefixed is true since we already hashed the message + ); + expect(address).toEqual(testObj.address); + }); + }); + }); + describe('encrypt', () => { describe('valid cases', () => { it.each(validEncryptData)('%s', async (input, output) => { diff --git a/packages/web3-eth-accounts/test/unit/account.test.ts b/packages/web3-eth-accounts/test/unit/account.test.ts index 10dae39fbc7..7285f65e6e3 100644 --- a/packages/web3-eth-accounts/test/unit/account.test.ts +++ b/packages/web3-eth-accounts/test/unit/account.test.ts @@ -29,6 +29,7 @@ import { sign, signTransaction, privateKeyToPublicKey, + signRaw, } from '../../src/account'; import { invalidDecryptData, @@ -37,10 +38,12 @@ import { invalidPrivateKeytoAccountData, invalidPrivateKeyToAddressData, signatureRecoverData, + signatureRecoverWithoutPrefixData, transactionsTestData, validDecryptData, validEncryptData, validHashMessageData, + validHashMessageWithoutPrefixData, validPrivateKeytoAccountData, validPrivateKeyToAddressData, validPrivateKeyToPublicKeyData, @@ -143,6 +146,12 @@ describe('accounts', () => { }); }); + describe('Hash Message Without Prefix', () => { + it.each(validHashMessageWithoutPrefixData)('%s', (message, hash) => { + expect(hashMessage(message, true)).toEqual(hash); + }); + }); + describe('Sign Message', () => { describe('sign', () => { it.each(signatureRecoverData)('%s', (data, testObj) => { @@ -161,6 +170,31 @@ describe('accounts', () => { }); }); + describe('Sign Raw Message', () => { + describe('signRaw', () => { + it.each(signatureRecoverWithoutPrefixData)('%s', (data, testObj) => { + const result = signRaw(data, testObj.privateKey); + expect(result.signature).toEqual(testObj.signature || testObj.signatureOrV); // makes sure we get signature and not V value + expect(result.r).toEqual(testObj.r); + expect(result.s).toEqual(testObj.s); + }); + }); + + describe('recover', () => { + it.each(signatureRecoverWithoutPrefixData)('%s', (data, testObj) => { + const hashedMessage = hashMessage(data, true); // hash the message first without prefix + const address = recover( + hashedMessage, + testObj.signatureOrV, + testObj.prefixedOrR, + testObj.s, + true, // make sure the prefixed is true since we already hashed the message + ); + expect(address).toEqual(testObj.address); + }); + }); + }); + describe('encrypt', () => { describe('valid cases', () => { it.each(validEncryptData)('%s', async (input, output) => { diff --git a/packages/web3-eth-accounts/test/unit/account_dom.test.ts b/packages/web3-eth-accounts/test/unit/account_dom.test.ts index 799fc4f2f8e..e0bf85fcbd2 100644 --- a/packages/web3-eth-accounts/test/unit/account_dom.test.ts +++ b/packages/web3-eth-accounts/test/unit/account_dom.test.ts @@ -44,6 +44,7 @@ import { recover, recoverTransaction, sign, + signRaw, signTransaction, privateKeyToPublicKey, } from '../../src/account'; @@ -54,10 +55,12 @@ import { invalidPrivateKeytoAccountData, invalidPrivateKeyToAddressData, signatureRecoverData, + signatureRecoverWithoutPrefixData, transactionsTestData, validDecryptData, validEncryptData, validHashMessageData, + validHashMessageWithoutPrefixData, validPrivateKeytoAccountData, validPrivateKeyToAddressData, validPrivateKeyToPublicKeyData, @@ -158,6 +161,12 @@ describe('accounts', () => { }); }); + describe('Hash Message Without Prefix', () => { + it.each(validHashMessageWithoutPrefixData)('%s', (message, hash) => { + expect(hashMessage(message, true)).toEqual(hash); + }); + }); + describe('Sign Message', () => { describe('sign', () => { it.each(signatureRecoverData)('%s', (data, testObj) => { @@ -176,6 +185,31 @@ describe('accounts', () => { }); }); + describe('Sign Raw Message', () => { + describe('signRaw', () => { + it.each(signatureRecoverWithoutPrefixData)('%s', (data, testObj) => { + const result = signRaw(data, testObj.privateKey); + expect(result.signature).toEqual(testObj.signature || testObj.signatureOrV); // makes sure we get signature and not V value + expect(result.r).toEqual(testObj.r); + expect(result.s).toEqual(testObj.s); + }); + }); + + describe('recover', () => { + it.each(signatureRecoverWithoutPrefixData)('%s', (data, testObj) => { + const hashedMessage = hashMessage(data, true); // hash the message first without prefix + const address = recover( + hashedMessage, + testObj.signatureOrV, + testObj.prefixedOrR, + testObj.s, + true, // make sure the prefixed is true since we already hashed the message + ); + expect(address).toEqual(testObj.address); + }); + }); + }); + describe('encrypt', () => { describe('valid cases', () => { it.each(validEncryptData)('%s', async (input, output) => { From d446838a72384d548628bf70f632ca797ed3bb92 Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Mon, 4 Nov 2024 11:57:13 -0800 Subject: [PATCH 183/186] Lightweight dApp Development Guide (#7364) * Lightweight dApp Development Guide Closes #7300 * Fix Broken Discord Link * Apply suggestions from code review Co-authored-by: Junaid <86780488+jdevcs@users.noreply.github.com> --------- Co-authored-by: Junaid <86780488+jdevcs@users.noreply.github.com> --- .../guides/01_getting_started/introduction.md | 4 +- .../guides/04_transactions/transactions.md | 2 +- .../smart_contracts_guide.md | 2 +- .../docs/guides/07_dapps/intermediate-dapp.md | 2 +- docs/docs/guides/07_dapps/lightweight-dapp.md | 276 ++++++++++++++++++ docs/docs/guides/07_dapps/metamask-react.md | 2 +- docs/docs/guides/07_dapps/metamask-vanilla.md | 2 +- 7 files changed, 283 insertions(+), 7 deletions(-) create mode 100644 docs/docs/guides/07_dapps/lightweight-dapp.md diff --git a/docs/docs/guides/01_getting_started/introduction.md b/docs/docs/guides/01_getting_started/introduction.md index b1fc2a8469a..d8838984205 100644 --- a/docs/docs/guides/01_getting_started/introduction.md +++ b/docs/docs/guides/01_getting_started/introduction.md @@ -8,7 +8,7 @@ sidebar_label: Introduction Web3.js is a robust and flexible collection of **TypeScript and JavaScript** libraries that allows developers to interact with local or remote [Ethereum](https://ethereum.org/en/) nodes (or **any EVM-compatible blockchain**) over **HTTP, IPC or WebSocket** connections. It is a powerful and efficient toolkit for crafting applications within the Ethereum ecosystem and beyond. -This documentation is the entrypoint to Web3.js for developers. It covers [basic](/guides/getting_started/quickstart) and [advanced](/guides/smart_contracts/mastering_smart_contracts) usage with examples, and includes comprehensive [API documentation](/api) as well as guides for common tasks, like [upgrading](/guides/web3_upgrade_guide) from older versions. +This documentation is the entrypoint to Web3.js for developers. It covers [basic](/guides/getting_started/quickstart) and [advanced](/guides/dapps/lightweight-dapp) usage with examples, and includes comprehensive [API documentation](/api) as well as guides for common tasks, like [upgrading](/guides/web3_upgrade_guide) from older versions. ## Features of Web3.js v4 @@ -35,7 +35,7 @@ New Web3.js developers should proceed to the [Quickstart](/guides/getting_starte ### For Intermediate & Advanced Web3.js Developers -If you're already familiar with Ethereum and Web3.js development, you may want to review the Web3.js [package structure](#packages--plugins) and proceed directly to the [package-level documentation](/libdocs/ABI) and [API documentation](/api). Application developers may wish to review the [Web3.js configuration guide](/guides/web3_config) or learn how to use Web3.js with tools like the [MetaMask](/guides/dapps/metamask-react) wallet or the [WalletConnect](/guides/dapps/web3_modal_guide) wallet selection modal. Don't forget to review the [list of available plugins](https://web3js.org/plugins) or even [learn how to build your own Web3.js plugin](/guides/web3_plugin_guide/plugin_authors)! +If you're already familiar with Ethereum and Web3.js development, you may want to review the Web3.js [package structure](#packages--plugins) and proceed directly to the [package-level documentation](/libdocs/ABI) and [API documentation](/api). Application developers may wish to review the [Web3.js configuration guide](/guides/web3_config) or learn how to use Web3.js with tools like [EIP-6963 wallets](/guides/dapps/intermediate-dapp) or the [WalletConnect](/guides/dapps/web3_modal_guide) wallet selection modal. Don't forget to review the [list of available plugins](https://web3js.org/plugins) or even [learn how to build your own Web3.js plugin](/guides/web3_plugin_guide/plugin_authors)! ## Packages & Plugins diff --git a/docs/docs/guides/04_transactions/transactions.md b/docs/docs/guides/04_transactions/transactions.md index 35078f053ec..95d74cbf057 100644 --- a/docs/docs/guides/04_transactions/transactions.md +++ b/docs/docs/guides/04_transactions/transactions.md @@ -19,7 +19,7 @@ Here is a high-level overview of the steps we will be taking in this tutorial: 6. Send a raw transaction :::tip -If you encounter any issues while following this guide or have any questions, don't hesitate to seek assistance. Our friendly community is ready to help you out! Join our [Discord](https://discord.gg/F4NUfaCC) server and head to the **#web3js-general** channel to connect with other developers and get the support you need. +If you encounter any issues while following this guide or have any questions, don't hesitate to seek assistance. Our friendly community is ready to help you out! Join our [Discord](https://discord.gg/pb3U4zE8ca) server and head to the **#web3js-general** channel to connect with other developers and get the support you need. ::: ## Step 1: Prerequisites diff --git a/docs/docs/guides/05_smart_contracts/smart_contracts_guide.md b/docs/docs/guides/05_smart_contracts/smart_contracts_guide.md index b913e372ddb..90d861c7a54 100644 --- a/docs/docs/guides/05_smart_contracts/smart_contracts_guide.md +++ b/docs/docs/guides/05_smart_contracts/smart_contracts_guide.md @@ -20,7 +20,7 @@ Here is a high-level overview of the steps we will be taking in this tutorial: 7. Use Web3.js to interact with the smart contract :::tip -If you encounter any issues while following this guide or have any questions, don't hesitate to seek assistance. Our friendly community is ready to help you out! Join our [Discord](https://discord.gg/F4NUfaCC) server and head to the **#web3js-general** channel to connect with other developers and get the support you need. +If you encounter any issues while following this guide or have any questions, don't hesitate to seek assistance. Our friendly community is ready to help you out! Join our [Discord](https://discord.gg/pb3U4zE8ca) server and head to the **#web3js-general** channel to connect with other developers and get the support you need. ::: ## Step 1: Prerequisites diff --git a/docs/docs/guides/07_dapps/intermediate-dapp.md b/docs/docs/guides/07_dapps/intermediate-dapp.md index 40c408644fc..c14903e244d 100644 --- a/docs/docs/guides/07_dapps/intermediate-dapp.md +++ b/docs/docs/guides/07_dapps/intermediate-dapp.md @@ -25,7 +25,7 @@ Here is a high-level overview of the steps in this tutorial: 6. Create a form to transfer ether :::tip -If you encounter any issues while following this guide or have any questions, don't hesitate to seek assistance. Our friendly community is ready to help you out! Join our [Discord](https://discord.gg/F4NUfaCC) server and head to the **#web3js-general** channel to connect with other developers and get the support you need. +If you encounter any issues while following this guide or have any questions, don't hesitate to seek assistance. Our friendly community is ready to help you out! Join our [Discord](https://discord.gg/pb3U4zE8ca) server and head to the **#web3js-general** channel to connect with other developers and get the support you need. ::: ## Step 1: Prerequisites diff --git a/docs/docs/guides/07_dapps/lightweight-dapp.md b/docs/docs/guides/07_dapps/lightweight-dapp.md new file mode 100644 index 00000000000..87d8784eafd --- /dev/null +++ b/docs/docs/guides/07_dapps/lightweight-dapp.md @@ -0,0 +1,276 @@ +--- +sidebar_position: 4 +sidebar_label: 'Tutorial: Lightweight dApp Development' +--- + +# Lightweight dApp Development + +In web development, the term "bundle size" refers to the aggregate size of all the files that are delivered to a user when they visit a web page. Large bundle sizes result in long loading times, poor performance, and overall bad user experience. A web application with a relatively small bundle size can be described as "lightweight". + +The [modular design](/#packages--plugins) of Web3.js promotes lightweight dApp development by allowing developers to include only the capabilities that are required for their dApp. Furthermore, Web3.js makes use of modern [JavaScript module](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) syntax to facilitate [tree shaking](https://developer.mozilla.org/en-US/docs/Glossary/Tree_shaking), which is a powerful mechanism for removing unused code that would otherwise be included in a web application. + +This guide will apply lightweight dApp development techniques to the minimal React template provided by the [`create-web3js-dapp` command-line utility](https://github.com/web3/create-web3js-dapp). [Webpack Bundle Analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer) will be used to analyze the impact of these techniques. + +## Overview + +Here is a high-level overview of the steps in this tutorial: + +1. Review prerequisites +2. Initialize a new Web3.js dApp and add dependencies +3. Configure and analyze a development build +4. Analyze the built-in React production build +5. Use only necessary packages and analyze the result + +:::tip +If you encounter any issues while following this guide or have any questions, don't hesitate to seek assistance. Our friendly community is ready to help you out! Join our [Discord](https://discord.gg/pb3U4zE8ca) server and head to the **#web3js-general** channel to connect with other developers and get the support you need. +::: + +## Step 1: Prerequisites + +This tutorial assumes basic familiarity with the command line as well as familiarity with React and [Node.js](https://nodejs.org/). Before starting this tutorial, ensure that Node.js and its package manager, npm, are installed. + +```console +$: node -v +# your version may be different, but it's best to use the current stable version +v20.14.0 +$: npm -v +10.8.2 +``` + +## Step 2: Initialize a New Web3.js dApp and Add Dependencies + +Use `create-web3js-dapp` to initialize a new Web3.js dApp and navigate into the new project directory: + +```console +npm install -g create-web3js-dapp +npx create-web3js-dapp --framework react --template minimal +cd web3js-react-dapp-min +``` + +Add the dependencies that will be used to generate the development bundle and analyze the bundle size: + +```console +npm i -D @babel/core @babel/preset-env \ + @babel/preset-react @babel/preset-typescript \ + babel-loader html-webpack-plugin webpack \ + webpack-bundle-analyzer webpack-cli +``` + +## Step 3: Configure and Analyze a Development Build + +For the purposes of this guide, a baseline development build will be configured to allow comparison with React's built-in production build. This initial development build will not make use of the modular design of Web3.js nor will it make use of tree shaking. + +The first step to configuring the development build is to create a template HTML file. Create a new file in the project's root directory called `index.html` and populate it with the following text: + +```html + + + + Web3.js Lightweight dApp Development + + +
+ + +``` + +Next, create a file called `webpack.config.js` and add the following code: + +```js +const path = require('path'); + +const HtmlWebpackPlugin = require('html-webpack-plugin'); +const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); + +module.exports = { + mode: 'development', + entry: path.join(__dirname, 'src', 'index.tsx'), + module: { + rules: [ + { + exclude: /node_modules/, + test: /\.(ts|tsx)$/, + use: { + loader: 'babel-loader', + options: { + presets: [ + '@babel/preset-env', + ['@babel/preset-react', { runtime: 'automatic' }], + '@babel/preset-typescript', + ], + }, + }, + }, + ], + }, + output: { + path: path.join(__dirname, 'dist'), + filename: 'index_bundle.js', + }, + resolve: { + extensions: ['.ts', '.tsx'], + }, + plugins: [new HtmlWebpackPlugin({ template: 'index.html' }), new BundleAnalyzerPlugin()], +}; +``` + +To generate the development build and display the output of Webpack Bundle Analyzer, execute the following command: + +```console +npx webpack +``` + +This will open a new browser tab that displays the output of Webpack Bundle Analyzer. Although the exact bundle size will vary, at the time of writing this guide, the size of the bundle generated by the development build is about **3.3 megabytes**. After reviewing the output of Webpack Bundle Analyzer, close the browser tab and use `Ctrl + C` to cancel the Webpack process. + +## Step 4: Analyze the Built-In React Production Build + +Next, write a script to analyze React's built-in production build. Create a file called `analyze.js` and add the following code: + +```js +const webpack = require('webpack'); +const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); + +process.env.NODE_ENV = 'production'; + +const config = require('react-scripts/config/webpack.config')('production'); +config.plugins.push(new BundleAnalyzerPlugin({ analyzerPort: 8089 })); + +webpack(config, (err, stats) => { + if (err || stats.hasErrors()) { + console.error(err); + } +}); +``` + +To generate the built-in production build and display the output of Webpack Bundle Analyzer, execute the following command: + +```console +node analyze.js +``` + +At the time of writing this guide, the size of the bundle generated by the built-in production build is about **593 kilobytes**, which is about 2% the size of the initial development build. The reduction in bundle size is due to techniques such as tree shaking. After reviewing the output of Webpack Bundle Analyzer, close the browser tab and use `Ctrl + C` to cancel the Webpack process. + +## Step 5: Use Only Necessary Packages and Analyze the Result + +The minimal template dApp that was created by `create-web3js-dapp` uses the umbrella `web3` package, which is useful for development purposes but results in a relatively large bundle size. In fact, the capabilities of the minimal React template only require the `web3-eth` and `web3-types` packages. To replace the umbrella `web3` package with `web3-eth` and `web3-types`, execute the following commands: + +```console +npm uninstall web3 +npm i web3-eth web3-types +``` + +Next, update the template dApp to remove references to the umbrella `web3` package and make use of the `web3-eth` and `web3-types` packages. Replace the contents of `src/react-app-env.d.ts` with the following: + +```ts +/// + +import type { EIP1193Provider, Web3APISpec } from 'web3-types'; + +declare global { + interface Window { + ethereum?: EIP1193Provider; + } +} +``` + +Replace the contents of `src/web3/web3-service.ts` with: + +```ts +import { Web3Eth } from 'web3-eth'; +import type { EIP1193Provider, Web3APISpec } from 'web3-types'; + +const provider: EIP1193Provider | undefined = window.ethereum; +if (provider !== undefined) { + provider.on('chainChanged', () => window.location.reload()); +} + +const web3: Web3Eth = provider === undefined ? new Web3Eth() : new Web3Eth(provider); +const Web3Service = { provider, web3 }; + +export default Web3Service; +``` + +Finally, replace the contents of `src/App.tsx` with the following (only the highlighted line has changed): + +```ts +import { useState } from 'react'; + +import Web3Service from './web3/web3-service'; + +function App() { + const hasProvider = Web3Service.provider !== undefined; + const [chainId, setChainId] = useState(0n); + if (hasProvider) { + // highlight-next-line + Web3Service.web3.getChainId().then(setChainId); + } + + return ( +
+

Web3.js + React Minimal dApp Template

+
+ This is a sample project that demonstrates using{' '} + Web3.js with the{' '} + React front-end framework. + + Learn more about this project and its design by referring to the{' '} + + GitHub README + + . +
+ {!hasProvider ? ( + <> +

Install a Wallet

+
Install a wallet browser extension:
+ + + ) : ( + <> +

Network Details

+
Chain ID: {chainId.toString()}
+ + )} +
+ + This project was bootstrapped with{' '} + Create React App. + +
+ ); +} + +export default App; +``` + +Finally, use the `analyze.js` script to analyze the size of the bundle generated by the updated production build by running the following command: + +```console +node analyze.js +``` + +At the time of writing this guide, the size of the final bundle is **467 kilobytes**, or about 75% the size of the bundle before using only the necessary packages. + +## Conclusion + +Managing bundle size is one of the most important considerations for web developers. Web3.js is designed to give developers control over bundle size. The modular design of Web3.js facilitates the selective use of only required dependencies. The use of JavaScript modules allows build tools like Webpack to remove unnecessary code through tree shaking. Understanding and deploying these techniques allows Web3.js developers to create dApps that are feature-rich while still being lightweight and performance-preserving. diff --git a/docs/docs/guides/07_dapps/metamask-react.md b/docs/docs/guides/07_dapps/metamask-react.md index 9a99b2f6b8f..02ecaedfda4 100644 --- a/docs/docs/guides/07_dapps/metamask-react.md +++ b/docs/docs/guides/07_dapps/metamask-react.md @@ -21,7 +21,7 @@ Here is a high-level overview of the steps we will be taking in this tutorial: 6. Verify the account used to sign a message :::tip -If you encounter any issues while following this guide or have any questions, don't hesitate to seek assistance. Our friendly community is ready to help you out! Join our [Discord](https://discord.gg/F4NUfaCC) server and head to the **#web3js-general** channel to connect with other developers and get the support you need. +If you encounter any issues while following this guide or have any questions, don't hesitate to seek assistance. Our friendly community is ready to help you out! Join our [Discord](https://discord.gg/pb3U4zE8ca) server and head to the **#web3js-general** channel to connect with other developers and get the support you need. ::: ## Step 1: Prerequisites diff --git a/docs/docs/guides/07_dapps/metamask-vanilla.md b/docs/docs/guides/07_dapps/metamask-vanilla.md index de7552c8bbf..a614ddd1991 100644 --- a/docs/docs/guides/07_dapps/metamask-vanilla.md +++ b/docs/docs/guides/07_dapps/metamask-vanilla.md @@ -19,7 +19,7 @@ Here is a high-level overview of the steps we will be taking in this tutorial: 6. Verify the account used to sign a message :::tip -If you encounter any issues while following this guide or have any questions, don't hesitate to seek assistance. Our friendly community is ready to help you out! Join our [Discord](https://discord.gg/F4NUfaCC) server and head to the **#web3js-general** channel to connect with other developers and get the support you need. +If you encounter any issues while following this guide or have any questions, don't hesitate to seek assistance. Our friendly community is ready to help you out! Join our [Discord](https://discord.gg/pb3U4zE8ca) server and head to the **#web3js-general** channel to connect with other developers and get the support you need. ::: ## Step 1: Prerequisites From 9fa32c92bc2f74d50e663fd9a42c2ea45e1a8ea0 Mon Sep 17 00:00:00 2001 From: Junaid <86780488+jdevcs@users.noreply.github.com> Date: Tue, 5 Nov 2024 17:36:47 +0100 Subject: [PATCH 184/186] newPendingTransactionFilter (#7353) * rpc method * createNewPendingTransactionFilter in eth class * unit test * integration test * rpc method * web3Eth class updates * test update * type FilterParams * createNewBlockFilter test * createNewFilter test * getFilterChanges test * getFilterLogs test * uninstallFilter test * fixtures * changelog update * updated changelog * tests for coverage --- CHANGELOG.md | 2 +- packages/web3-eth/CHANGELOG.md | 4 + .../src/filtering_rpc_method_wrappers.ts | 171 +++++++++++++ packages/web3-eth/src/web3_eth.ts | 237 ++++++++++++++---- .../web3_eth_methods_with_parameters.ts | 48 ++++ .../web3-eth/test/integration/format.test.ts | 7 + .../create_new_block_filter.test.ts | 35 +++ .../create_new_filter.test.ts | 51 ++++ .../fixtures/new_filter_block_params.ts | 59 +++++ .../get_filter_changes.test.ts | 43 ++++ .../get_filter_logs.test.ts | 44 ++++ .../new_pending_transaction_filter.test.ts | 37 +++ .../uninstall_filter.test.ts | 38 +++ .../web3_eth_methods_no_parameters.test.ts | 12 + .../web3_eth_methods_with_parameters.test.ts | 157 +++++++++++- packages/web3-types/CHANGELOG.md | 4 + packages/web3-types/src/eth_types.ts | 2 + 17 files changed, 900 insertions(+), 51 deletions(-) create mode 100644 packages/web3-eth/src/filtering_rpc_method_wrappers.ts create mode 100644 packages/web3-eth/test/unit/rpc_method_wrappers/create_new_block_filter.test.ts create mode 100644 packages/web3-eth/test/unit/rpc_method_wrappers/create_new_filter.test.ts create mode 100644 packages/web3-eth/test/unit/rpc_method_wrappers/fixtures/new_filter_block_params.ts create mode 100644 packages/web3-eth/test/unit/rpc_method_wrappers/get_filter_changes.test.ts create mode 100644 packages/web3-eth/test/unit/rpc_method_wrappers/get_filter_logs.test.ts create mode 100644 packages/web3-eth/test/unit/rpc_method_wrappers/new_pending_transaction_filter.test.ts create mode 100644 packages/web3-eth/test/unit/rpc_method_wrappers/uninstall_filter.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index d96a9e23283..08102f589e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2756,7 +2756,7 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3-eth -- Allow specifying percentage based factor in Web3Eth.calculateFeeData Param baseFeePerGasFactor #7332 +- Allow specifying percentage based factor in Web3Eth.calculateFeeData Param baseFeePerGasFactor #7332 ### Fixed diff --git a/packages/web3-eth/CHANGELOG.md b/packages/web3-eth/CHANGELOG.md index 946429b8c7b..5f1aab23bde 100644 --- a/packages/web3-eth/CHANGELOG.md +++ b/packages/web3-eth/CHANGELOG.md @@ -290,3 +290,7 @@ Documentation: - `populateGasPrice` function now checks `Web3Context.config.ignoreGasPricing`. If `ignoreGasPricing` is true, gasPrice will not be estimated (#7320) ## [Unreleased] + +### Added + +- `createNewPendingTransactionFilter` , `createNewFilter` , `createNewBlockFilter` , `uninstallFilter` , `getFilterChanges` and `getFilterLogs` are exported from `Web3Eth` and `filtering_rpc_method_wrappers` (#7353) diff --git a/packages/web3-eth/src/filtering_rpc_method_wrappers.ts b/packages/web3-eth/src/filtering_rpc_method_wrappers.ts new file mode 100644 index 00000000000..5b13fcc54b1 --- /dev/null +++ b/packages/web3-eth/src/filtering_rpc_method_wrappers.ts @@ -0,0 +1,171 @@ +/* +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 { ethRpcMethods } from 'web3-rpc-methods'; +import { DataFormat, EthExecutionAPI, Numbers, Log, FilterParams } from 'web3-types'; +import { format, numberToHex } from 'web3-utils'; +import { isNullish } from 'web3-validator'; +import { logSchema } from './schemas.js'; + +/** + * View additional documentations here: {@link Web3Eth.createNewPendingTransactionFilter} + * @param web3Context ({@link Web3Context}) Web3 configuration object that contains things such as the provider, request manager, wallet, etc. + * @param returnFormat ({@link DataFormat}) Return format + */ +export async function createNewPendingTransactionFilter( + web3Context: Web3Context, + returnFormat: ReturnFormat, +) { + const response = await ethRpcMethods.newPendingTransactionFilter(web3Context.requestManager); + + return format( + { format: 'uint' }, + response as Numbers, + returnFormat ?? web3Context.defaultReturnFormat, + ); +} + +/** + * View additional documentations here: {@link Web3Eth.createNewFilter} + * @param web3Context ({@link Web3Context}) Web3 configuration object that contains things such as the provider, request manager, wallet, etc. + * @param filter ({@link FilterParam}) Filter param optional having from-block to-block address or params + * @param returnFormat ({@link DataFormat}) Return format + */ +export async function createNewFilter( + web3Context: Web3Context, + filter: FilterParams, + returnFormat: ReturnFormat, +) { + // format type bigint or number toBlock and fromBlock to hexstring. + let { toBlock, fromBlock } = filter; + if (!isNullish(toBlock)) { + if (typeof toBlock === 'number' || typeof toBlock === 'bigint') { + toBlock = numberToHex(toBlock); + } + } + if (!isNullish(fromBlock)) { + if (typeof fromBlock === 'number' || typeof fromBlock === 'bigint') { + fromBlock = numberToHex(fromBlock); + } + } + + const formattedFilter = { ...filter, fromBlock, toBlock }; + + const response = await ethRpcMethods.newFilter(web3Context.requestManager, formattedFilter); + + return format( + { format: 'uint' }, + response as Numbers, + returnFormat ?? web3Context.defaultReturnFormat, + ); +} + +/** + * View additional documentations here: {@link Web3Eth.createNewBlockFilter} + * @param web3Context ({@link Web3Context}) Web3 configuration object that contains things such as the provider, request manager, wallet, etc. + * @param returnFormat ({@link DataFormat}) Return format + */ +export async function createNewBlockFilter( + web3Context: Web3Context, + returnFormat: ReturnFormat, +) { + const response = await ethRpcMethods.newBlockFilter(web3Context.requestManager); + + return format( + { format: 'uint' }, + response as Numbers, + returnFormat ?? web3Context.defaultReturnFormat, + ); +} + +/** + * View additional documentations here: {@link Web3Eth.uninstallFilter} + * @param web3Context ({@link Web3Context}) Web3 configuration object that contains things such as the provider, request manager, wallet, etc. + * @param filterIdentifier ({@link Numbers}) filter id + */ +export async function uninstallFilter( + web3Context: Web3Context, + filterIdentifier: Numbers, +) { + const response = await ethRpcMethods.uninstallFilter( + web3Context.requestManager, + numberToHex(filterIdentifier), + ); + + return response; +} + +/** + * View additional documentations here: {@link Web3Eth.getFilterChanges} + * @param web3Context ({@link Web3Context}) Web3 configuration object that contains things such as the provider, request manager, wallet, etc. + * @param filterIdentifier ({@link Numbers}) filter id + */ +export async function getFilterChanges( + web3Context: Web3Context, + filterIdentifier: Numbers, + returnFormat: ReturnFormat, +) { + const response = await ethRpcMethods.getFilterChanges( + web3Context.requestManager, + numberToHex(filterIdentifier), + ); + + const result = response.map(res => { + if (typeof res === 'string') { + return res; + } + + return format( + logSchema, + res as unknown as Log, + returnFormat ?? web3Context.defaultReturnFormat, + ); + }); + + return result; +} + +/** + * View additional documentations here: {@link Web3Eth.getFilterLogs} + * @param web3Context ({@link Web3Context}) Web3 configuration object that contains things such as the provider, request manager, wallet, etc. + * @param filterIdentifier ({@link Numbers}) filter id + */ +export async function getFilterLogs( + web3Context: Web3Context, + filterIdentifier: Numbers, + returnFormat: ReturnFormat, +) { + const response = await ethRpcMethods.getFilterLogs( + web3Context.requestManager, + numberToHex(filterIdentifier), + ); + + const result = response.map(res => { + if (typeof res === 'string') { + return res; + } + + return format( + logSchema, + res as unknown as Log, + returnFormat ?? web3Context.defaultReturnFormat, + ); + }); + + return result; +} diff --git a/packages/web3-eth/src/web3_eth.ts b/packages/web3-eth/src/web3_eth.ts index 4f0a191d9f8..ba951914e91 100644 --- a/packages/web3-eth/src/web3_eth.ts +++ b/packages/web3-eth/src/web3_eth.ts @@ -41,6 +41,7 @@ import { Eip712TypedData, FMT_BYTES, FMT_NUMBER, + FilterParams, } from 'web3-types'; import { isSupportedProvider, Web3Context, Web3ContextInitOptions } from 'web3-core'; import { TransactionNotFound } from 'web3-errors'; @@ -48,6 +49,7 @@ import { toChecksumAddress, isNullish, ethUnitMap } from 'web3-utils'; import { ethRpcMethods } from 'web3-rpc-methods'; import * as rpcMethodsWrappers from './rpc_method_wrappers.js'; +import * as filteringRpcMethodsWrappers from './filtering_rpc_method_wrappers.js'; import { SendTransactionOptions, TransactionMiddleware } from './types.js'; import { LogsSubscription, @@ -272,54 +274,54 @@ export class Web3Eth extends Web3Context { - * gasPrice: 20000000000n, - * maxFeePerGas: 60000000000n, - * maxPriorityFeePerGas: 20000000000n, - * baseFeePerGas: 20000000000n - * } - * - * @example - * // Using a `bigint` for baseFeePerGasFactor - * web3.eth.calculateFeeData(1n).then(console.log); - * > { - * gasPrice: 20000000000n, - * maxFeePerGas: 40000000000n, - * maxPriorityFeePerGas: 20000000000n, - * baseFeePerGas: 20000000000n - * } - * - * @example - * // Using a `number` for baseFeePerGasFactor (with decimals) - * web3.eth.calculateFeeData(1.5).then(console.log); - * > { - * gasPrice: 20000000000n, - * maxFeePerGas: 50000000000n, // baseFeePerGasFactor is converted to BigInt(1.500) - * maxPriorityFeePerGas: 20000000000n, - * baseFeePerGas: 20000000000n - * } - * - * @example - * web3.eth.calculateFeeData(3n).then(console.log); - * > { - * gasPrice: 20000000000n, - * maxFeePerGas: 80000000000n, - * maxPriorityFeePerGas: 20000000000n, - * baseFeePerGas: 20000000000n - * } - */ + * Calculates the current Fee Data. + * If the node supports EIP-1559, then `baseFeePerGas` and `maxPriorityFeePerGas` will be returned along with the calculated `maxFeePerGas` value. + * `maxFeePerGas` is calculated as `baseFeePerGas` * `baseFeePerGasFactor` + `maxPriorityFeePerGas`. + * If the node does not support EIP-1559, then the `gasPrice` will be returned and the other values will be undefined. + * + * @param baseFeePerGasFactor (optional) The factor to multiply the `baseFeePerGas` with when calculating `maxFeePerGas`, if the node supports EIP-1559. This can be a `bigint` for precise calculation or a `number` to support decimals. The default value is 2 (BigInt). + * If a `number` is provided, it will be converted to `bigint` with three decimal precision. + * @param alternativeMaxPriorityFeePerGas (optional) The alternative `maxPriorityFeePerGas` to use when calculating `maxFeePerGas`, if the node supports EIP-1559 but does not support the method `eth_maxPriorityFeePerGas`. The default value is 1 gwei. + * @returns The current fee data. + * + * @example + * web3.eth.calculateFeeData().then(console.log); + * > { + * gasPrice: 20000000000n, + * maxFeePerGas: 60000000000n, + * maxPriorityFeePerGas: 20000000000n, + * baseFeePerGas: 20000000000n + * } + * + * @example + * // Using a `bigint` for baseFeePerGasFactor + * web3.eth.calculateFeeData(1n).then(console.log); + * > { + * gasPrice: 20000000000n, + * maxFeePerGas: 40000000000n, + * maxPriorityFeePerGas: 20000000000n, + * baseFeePerGas: 20000000000n + * } + * + * @example + * // Using a `number` for baseFeePerGasFactor (with decimals) + * web3.eth.calculateFeeData(1.5).then(console.log); + * > { + * gasPrice: 20000000000n, + * maxFeePerGas: 50000000000n, // baseFeePerGasFactor is converted to BigInt(1.500) + * maxPriorityFeePerGas: 20000000000n, + * baseFeePerGas: 20000000000n + * } + * + * @example + * web3.eth.calculateFeeData(3n).then(console.log); + * > { + * gasPrice: 20000000000n, + * maxFeePerGas: 80000000000n, + * maxPriorityFeePerGas: 20000000000n, + * baseFeePerGas: 20000000000n + * } + */ public async calculateFeeData( baseFeePerGasFactor: bigint | number = BigInt(2), @@ -1916,4 +1918,143 @@ export class Web3Eth extends Web3Context 1n + * + * web3.eth.createNewPendingTransactionFilter({ number: FMT_NUMBER.HEX , bytes: FMT_BYTES.HEX }).then(console.log); + * > "0x1" + * ``` + */ + public async createNewPendingTransactionFilter< + ReturnFormat extends DataFormat = typeof DEFAULT_RETURN_FORMAT, + >(returnFormat: ReturnFormat = this.defaultReturnFormat as ReturnFormat) { + return filteringRpcMethodsWrappers.createNewPendingTransactionFilter(this, returnFormat); + } + + /** + * Creates a filter object, based on filter options, to notify when the state changes (logs) + * + * @param filter A {@link FilterParams} object containing the filter properties. + * @param returnFormat ({@link DataFormat} defaults to {@link DEFAULT_RETURN_FORMAT}) Specifies how the return data should be formatted. + * @returns A filter id. + * + * ```ts + * web3.eth.createNewFilter(filterParams).then(console.log); + * > 1n + * + * web3.eth.createNewFilter(filterParams, { number: FMT_NUMBER.HEX , bytes: FMT_BYTES.HEX }).then(console.log); + * > "0x1" + * ``` + */ + public async createNewFilter( + filter: FilterParams, + returnFormat: ReturnFormat = this.defaultReturnFormat as ReturnFormat, + ) { + return filteringRpcMethodsWrappers.createNewFilter(this, filter, returnFormat); + } + + /** + * Creates a filter in the node, to notify when a new block arrives. + * + * @param returnFormat ({@link DataFormat} defaults to {@link DEFAULT_RETURN_FORMAT}) Specifies how the return data should be formatted. + * @returns A filter id. + * + * ```ts + * web3.eth.createNewBlockFilter().then(console.log); + * > 1n + * + * web3.eth.createNewBlockFilter({ number: FMT_NUMBER.HEX , bytes: FMT_BYTES.HEX }).then(console.log); + * > "0x1" + * ``` + */ + public async createNewBlockFilter< + ReturnFormat extends DataFormat = typeof DEFAULT_RETURN_FORMAT, + >(returnFormat: ReturnFormat = this.defaultReturnFormat as ReturnFormat) { + return filteringRpcMethodsWrappers.createNewBlockFilter(this, returnFormat); + } + + /** + * Uninstalls a filter with given id. Should always be called when watch is no longer needed. + * + * @param filterIdentifier ({@link Numbers} filter id + * @returns true if the filter was successfully uninstalled, otherwise false. + * + * ```ts + * web3.eth.uninstallFilter(123).then(console.log); + * > true + * + * web3.eth.uninstallFilter('0x123').then(console.log); + * > true + * + * web3.eth.uninstallFilter(12n).then(console.log); + * > true + * ``` + */ + public async uninstallFilter(filterIdentifier: Numbers) { + return filteringRpcMethodsWrappers.uninstallFilter(this, filterIdentifier); + } + + /** + * Polling method for a filter, which returns an array of logs which occurred since last poll. + * + * @param filterIdentifier ({@link Numbers} filter id + * @param returnFormat ({@link DataFormat} defaults to {@link DEFAULT_RETURN_FORMAT}) - Specifies how the return data from the call should be formatted. + * @returns {@link FilterResultsAPI}, an array of {@link Log} objects. + * + * ```ts + * web3.eth.getFilterChanges(123).then(console.log); + * > [{ + * data: '0x7f9fade1c0d57a7af66ab4ead79fade1c0d57a7af66ab4ead7c2c2eb7b11a91385', + * topics: ['0xfd43ade1c09fade1c0d57a7af66ab4ead7c2c2eb7b11a91ffdd57a7af66ab4ead7', '0x7f9fade1c0d57a7af66ab4ead79fade1c0d57a7af66ab4ead7c2c2eb7b11a91385'] + * logIndex: 0n, + * transactionIndex: 0n, + * transactionHash: '0x7f9fade1c0d57a7af66ab4ead79fade1c0d57a7af66ab4ead7c2c2eb7b11a91385', + * blockHash: '0xfd43ade1c09fade1c0d57a7af66ab4ead7c2c2eb7b11a91ffdd57a7af66ab4ead7', + * blockNumber: 1234n, + * address: '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe' + * }, + * {...}] + */ + public async getFilterChanges( + filterIdentifier: Numbers, + returnFormat: ReturnFormat = this.defaultReturnFormat as ReturnFormat, + ) { + return filteringRpcMethodsWrappers.getFilterChanges(this, filterIdentifier, returnFormat); + } + + /** + * Returns an array of all logs matching filter with given id. + * + * @param filterIdentifier ({@link Numbers} filter id + * @param returnFormat ({@link DataFormat} defaults to {@link DEFAULT_RETURN_FORMAT}) - Specifies how the return data from the call should be formatted. + * @returns {@link FilterResultsAPI}, an array of {@link Log} objects. + * + * ```ts + * web3.eth.getFilterLogs(123).then(console.log); + * > [{ + * data: '0x7f9fade1c0d57a7af66ab4ead79fade1c0d57a7af66ab4ead7c2c2eb7b11a91385', + * topics: ['0xfd43ade1c09fade1c0d57a7af66ab4ead7c2c2eb7b11a91ffdd57a7af66ab4ead7', '0x7f9fade1c0d57a7af66ab4ead79fade1c0d57a7af66ab4ead7c2c2eb7b11a91385'] + * logIndex: 0n, + * transactionIndex: 0n, + * transactionHash: '0x7f9fade1c0d57a7af66ab4ead79fade1c0d57a7af66ab4ead7c2c2eb7b11a91385', + * blockHash: '0xfd43ade1c09fade1c0d57a7af66ab4ead7c2c2eb7b11a91ffdd57a7af66ab4ead7', + * blockNumber: 1234n, + * address: '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe' + * }, + * {...}] + */ + public async getFilterLogs( + filterIdentifier: Numbers, + returnFormat: ReturnFormat = this.defaultReturnFormat as ReturnFormat, + ) { + return filteringRpcMethodsWrappers.getFilterLogs(this, filterIdentifier, returnFormat); + } } diff --git a/packages/web3-eth/test/fixtures/web3_eth_methods_with_parameters.ts b/packages/web3-eth/test/fixtures/web3_eth_methods_with_parameters.ts index 17d9c204f21..dd2c7907ab9 100644 --- a/packages/web3-eth/test/fixtures/web3_eth_methods_with_parameters.ts +++ b/packages/web3-eth/test/fixtures/web3_eth_methods_with_parameters.ts @@ -30,6 +30,8 @@ import { Uint256, TransactionWithSenderAPI, TransactionReceipt, + Numbers, + FilterParams, } from 'web3-types'; import { transactionWithSender } from './rpc_methods_wrappers'; @@ -2302,3 +2304,49 @@ export const txReceipt: TransactionReceipt = { type: BigInt(0), root: '', }; + +export const getFilterLogsDataWithformater: [Numbers, DataFormat][] = [ + [123, { ...DEFAULT_RETURN_FORMAT, number: FMT_NUMBER.BIGINT }], // Number + ['0x7b', { ...DEFAULT_RETURN_FORMAT, number: FMT_NUMBER.BIGINT }], // Hex string + [BigInt(123), { ...DEFAULT_RETURN_FORMAT, number: FMT_NUMBER.BIGINT }], // BigInt +]; + +export const getFilterLogsData: [Numbers][] = [ + [456], // Number without return format + ['0x1c8'], // Hex string without return format + [BigInt(456)], // BigInt without return format +]; + +// Export the test data +export const uninstallFilterData: [Numbers][] = [ + [123], // Number + ['0x7b'], // Hex string equivalent of 123 + [BigInt(123)], // BigInt + [456], // Another number + ['0x1c8'], // Another hex string equivalent of 456 + [BigInt(456)], // Another BigInt +]; + +export type CreateNewFilterTestData = [FilterParams, DataFormat]; + +// Export the test data +export const createNewFilterData: CreateNewFilterTestData[] = [ + [ + { fromBlock: 123, toBlock: 456 }, + { ...DEFAULT_RETURN_FORMAT, number: FMT_NUMBER.BIGINT }, + ], // Number to hex conversion + [ + { fromBlock: BigInt(123), toBlock: BigInt(456) }, + { ...DEFAULT_RETURN_FORMAT, number: FMT_NUMBER.BIGINT }, + ], // BigInt to hex conversion + [ + { address: '0x1234567890abcdef1234567890abcdef12345678' }, + { ...DEFAULT_RETURN_FORMAT, number: FMT_NUMBER.BIGINT }, + ], // Address only + // eslint-disable-next-line no-null/no-null + [{ topics: [null, '0xabcdef'] }, { ...DEFAULT_RETURN_FORMAT, number: FMT_NUMBER.BIGINT }], // Topics with null + [ + { fromBlock: BlockTags.LATEST, toBlock: BlockTags.PENDING }, + { ...DEFAULT_RETURN_FORMAT, number: FMT_NUMBER.BIGINT }, + ], // Non-numeric blocks +]; diff --git a/packages/web3-eth/test/integration/format.test.ts b/packages/web3-eth/test/integration/format.test.ts index b9962c065ff..09d3abdaa1a 100644 --- a/packages/web3-eth/test/integration/format.test.ts +++ b/packages/web3-eth/test/integration/format.test.ts @@ -108,5 +108,12 @@ describe('format', () => { expect(typeof res).toBe(mapFormatToType[format as string]); expect(Number(res)).toBeGreaterThan(0); }); + + it.each(Object.values(FMT_NUMBER))('createNewPendingTransactionFilter', async format => { + web3Eth.defaultReturnFormat = { number: format as FMT_NUMBER, bytes: FMT_BYTES.HEX }; + const res = await web3Eth.createNewPendingTransactionFilter(); + expect(typeof res).toBe(mapFormatToType[format as string]); + expect(parseInt(String(res), 16)).toBeGreaterThan(0); + }); }); }); diff --git a/packages/web3-eth/test/unit/rpc_method_wrappers/create_new_block_filter.test.ts b/packages/web3-eth/test/unit/rpc_method_wrappers/create_new_block_filter.test.ts new file mode 100644 index 00000000000..aafa6e8f0d1 --- /dev/null +++ b/packages/web3-eth/test/unit/rpc_method_wrappers/create_new_block_filter.test.ts @@ -0,0 +1,35 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ +import { Web3Context } from 'web3-core'; +import { DEFAULT_RETURN_FORMAT, Web3EthExecutionAPI } from 'web3-types'; +import { ethRpcMethods } from 'web3-rpc-methods'; +import { createNewBlockFilter } from '../../../src/filtering_rpc_method_wrappers'; + +jest.mock('web3-rpc-methods'); + +describe('createNewBlockFilter', () => { + let web3Context: Web3Context; + + beforeAll(() => { + web3Context = new Web3Context('http://127.0.0.1:8545'); + }); + + it('should call rpcMethods.newBlockFilter with expected parameters', async () => { + await createNewBlockFilter(web3Context, DEFAULT_RETURN_FORMAT); + expect(ethRpcMethods.newBlockFilter).toHaveBeenCalledWith(web3Context.requestManager); + }); +}); diff --git a/packages/web3-eth/test/unit/rpc_method_wrappers/create_new_filter.test.ts b/packages/web3-eth/test/unit/rpc_method_wrappers/create_new_filter.test.ts new file mode 100644 index 00000000000..0f44c3cca6f --- /dev/null +++ b/packages/web3-eth/test/unit/rpc_method_wrappers/create_new_filter.test.ts @@ -0,0 +1,51 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ +import { Web3Context } from 'web3-core'; +import { DEFAULT_RETURN_FORMAT, FilterParams, Web3EthExecutionAPI } from 'web3-types'; +import { ethRpcMethods } from 'web3-rpc-methods'; +import { createNewFilter } from '../../../src/filtering_rpc_method_wrappers'; +import { blockParams } from './fixtures/new_filter_block_params'; + +jest.mock('web3-rpc-methods'); + +describe('createNewFilter', () => { + let web3Context: Web3Context; + + beforeAll(() => { + web3Context = new Web3Context(); + }); + + it.each(blockParams)( + 'should call rpcMethods.newFilter with fromBlock %p and toBlock %p', + async (actualParams, expectedParams) => { + const [fromBlockParam, toBlockParam] = actualParams; + const [expectedFromBlock, expectedToBlock] = expectedParams; + + const sampleFilterParams: FilterParams = { + fromBlock: fromBlockParam, + toBlock: toBlockParam, + address: ['0x1234567890abcdef1234567890abcdef12345678'], + }; + await createNewFilter(web3Context, sampleFilterParams, DEFAULT_RETURN_FORMAT); + expect(ethRpcMethods.newFilter).toHaveBeenCalledWith(web3Context.requestManager, { + ...sampleFilterParams, + fromBlock: expectedFromBlock, + toBlock: expectedToBlock, + }); + }, + ); +}); diff --git a/packages/web3-eth/test/unit/rpc_method_wrappers/fixtures/new_filter_block_params.ts b/packages/web3-eth/test/unit/rpc_method_wrappers/fixtures/new_filter_block_params.ts new file mode 100644 index 00000000000..9af69751246 --- /dev/null +++ b/packages/web3-eth/test/unit/rpc_method_wrappers/fixtures/new_filter_block_params.ts @@ -0,0 +1,59 @@ +/* +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 . +*/ + +// Modified blockParams to include sub-arrays for actual and expected parameters +export const blockParams: [ + [string | number | bigint, string | number | bigint], + [string, string], +][] = [ + [ + [123, 'latest'], + ['0x7b', 'latest'], + ], // Number fromBlock + [ + [BigInt(123), 'latest'], + ['0x7b', 'latest'], + ], // BigInt fromBlock + [ + ['0x7b', 'latest'], + ['0x7b', 'latest'], + ], // Hexadecimal fromBlock + [ + [123, 456], + ['0x7b', '0x1c8'], + ], // Number fromBlock and toBlock + [ + [BigInt(123), BigInt(456)], + ['0x7b', '0x1c8'], + ], // BigInt fromBlock and toBlock + [ + ['0x7b', '0x1c8'], + ['0x7b', '0x1c8'], + ], // Hexadecimal fromBlock and toBlock + [ + ['latest', 123], + ['latest', '0x7b'], + ], + [ + ['latest', BigInt(123)], + ['latest', '0x7b'], + ], + [ + ['latest', '0x7b'], + ['latest', '0x7b'], + ], +]; diff --git a/packages/web3-eth/test/unit/rpc_method_wrappers/get_filter_changes.test.ts b/packages/web3-eth/test/unit/rpc_method_wrappers/get_filter_changes.test.ts new file mode 100644 index 00000000000..df3b4fce3b8 --- /dev/null +++ b/packages/web3-eth/test/unit/rpc_method_wrappers/get_filter_changes.test.ts @@ -0,0 +1,43 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ +import { Web3Context } from 'web3-core'; +import { DEFAULT_RETURN_FORMAT, Web3EthExecutionAPI } from 'web3-types'; +import { ethRpcMethods } from 'web3-rpc-methods'; +import { getFilterChanges } from '../../../src/filtering_rpc_method_wrappers'; +import { mockRpcResponse } from './fixtures/get_logs'; + +jest.mock('web3-rpc-methods'); + +describe('getFilterChanges', () => { + let web3Context: Web3Context; + + beforeAll(() => { + web3Context = new Web3Context(); + }); + it.each([ + [123], // Number input + [BigInt(123)], // BigInt input + ['0x7b'], // Hexadecimal string input + ])('should call rpcMethods.getFilterChanges with input %p', async input => { + (ethRpcMethods.getFilterChanges as jest.Mock).mockResolvedValueOnce(mockRpcResponse); + await getFilterChanges(web3Context, input, DEFAULT_RETURN_FORMAT); + expect(ethRpcMethods.getFilterChanges).toHaveBeenCalledWith( + web3Context.requestManager, + '0x7b', + ); + }); +}); diff --git a/packages/web3-eth/test/unit/rpc_method_wrappers/get_filter_logs.test.ts b/packages/web3-eth/test/unit/rpc_method_wrappers/get_filter_logs.test.ts new file mode 100644 index 00000000000..6b69817b14c --- /dev/null +++ b/packages/web3-eth/test/unit/rpc_method_wrappers/get_filter_logs.test.ts @@ -0,0 +1,44 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ +import { Web3Context } from 'web3-core'; +import { DEFAULT_RETURN_FORMAT, Web3EthExecutionAPI } from 'web3-types'; +import { ethRpcMethods } from 'web3-rpc-methods'; +import { mockRpcResponse } from './fixtures/get_logs'; +import { getFilterLogs } from '../../../src/filtering_rpc_method_wrappers'; + +jest.mock('web3-rpc-methods'); + +describe('getFilterLogs', () => { + let web3Context: Web3Context; + + beforeAll(() => { + web3Context = new Web3Context(); + }); + + it.each([ + [123], // Number input + [BigInt(123)], // BigInt input + ['0x7b'], // Hexadecimal string input + ])('should call rpcMethods.getFilterLogs with input %p', async input => { + (ethRpcMethods.getFilterLogs as jest.Mock).mockResolvedValueOnce(mockRpcResponse); + await getFilterLogs(web3Context, input, DEFAULT_RETURN_FORMAT); + expect(ethRpcMethods.getFilterLogs).toHaveBeenCalledWith( + web3Context.requestManager, + '0x7b', + ); + }); +}); diff --git a/packages/web3-eth/test/unit/rpc_method_wrappers/new_pending_transaction_filter.test.ts b/packages/web3-eth/test/unit/rpc_method_wrappers/new_pending_transaction_filter.test.ts new file mode 100644 index 00000000000..20ecc54f2f8 --- /dev/null +++ b/packages/web3-eth/test/unit/rpc_method_wrappers/new_pending_transaction_filter.test.ts @@ -0,0 +1,37 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ +import { Web3Context } from 'web3-core'; +import { DEFAULT_RETURN_FORMAT, Web3EthExecutionAPI } from 'web3-types'; +import { ethRpcMethods } from 'web3-rpc-methods'; +import { createNewPendingTransactionFilter } from '../../../src/filtering_rpc_method_wrappers'; + +jest.mock('web3-rpc-methods'); + +describe('createNewPendingTransactionFilter', () => { + let web3Context: Web3Context; + + beforeAll(() => { + web3Context = new Web3Context('http://127.0.0.1:8545'); + }); + + it('should call rpcMethods.newPendingTransactionFilter with expected parameters', async () => { + await createNewPendingTransactionFilter(web3Context, DEFAULT_RETURN_FORMAT); + expect(ethRpcMethods.newPendingTransactionFilter).toHaveBeenCalledWith( + web3Context.requestManager, + ); + }); +}); diff --git a/packages/web3-eth/test/unit/rpc_method_wrappers/uninstall_filter.test.ts b/packages/web3-eth/test/unit/rpc_method_wrappers/uninstall_filter.test.ts new file mode 100644 index 00000000000..e93d2921946 --- /dev/null +++ b/packages/web3-eth/test/unit/rpc_method_wrappers/uninstall_filter.test.ts @@ -0,0 +1,38 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ +import { Web3Context } from 'web3-core'; +import { Web3EthExecutionAPI } from 'web3-types'; +import { ethRpcMethods } from 'web3-rpc-methods'; +import { uninstallFilter } from '../../../src/filtering_rpc_method_wrappers'; + +jest.mock('web3-rpc-methods'); + +describe('uninstallFilter', () => { + let web3Context: Web3Context; + + beforeAll(() => { + web3Context = new Web3Context('http://127.0.0.1:8545'); + }); + + it('should call rpcMethods.uninstallFilter with expected parameters', async () => { + await uninstallFilter(web3Context, 123); + expect(ethRpcMethods.uninstallFilter).toHaveBeenCalledWith( + web3Context.requestManager, + '0x7b', + ); + }); +}); diff --git a/packages/web3-eth/test/unit/web3_eth_methods_no_parameters.test.ts b/packages/web3-eth/test/unit/web3_eth_methods_no_parameters.test.ts index c01ae8f0fc6..ee0aea12a32 100644 --- a/packages/web3-eth/test/unit/web3_eth_methods_no_parameters.test.ts +++ b/packages/web3-eth/test/unit/web3_eth_methods_no_parameters.test.ts @@ -83,5 +83,17 @@ describe('web3_eth_methods_no_parameters', () => { web3Eth.requestManager, ); }); + + it('createNewPendingTransactionFilter', async () => { + await web3Eth.createNewPendingTransactionFilter(); + expect(ethRpcMethods.newPendingTransactionFilter).toHaveBeenCalledWith( + web3Eth.requestManager, + ); + }); + + it('createNewBlockFilter', async () => { + await web3Eth.createNewBlockFilter(); + expect(ethRpcMethods.newBlockFilter).toHaveBeenCalledWith(web3Eth.requestManager); + }); }); }); diff --git a/packages/web3-eth/test/unit/web3_eth_methods_with_parameters.test.ts b/packages/web3-eth/test/unit/web3_eth_methods_with_parameters.test.ts index 7186e2e63de..8240c69274d 100644 --- a/packages/web3-eth/test/unit/web3_eth_methods_with_parameters.test.ts +++ b/packages/web3-eth/test/unit/web3_eth_methods_with_parameters.test.ts @@ -16,9 +16,10 @@ along with web3.js. If not, see . */ import { ethRpcMethods } from 'web3-rpc-methods'; -import { TransactionInfoAPI } from 'web3-types'; +import { DEFAULT_RETURN_FORMAT, FMT_NUMBER, TransactionInfoAPI } from 'web3-types'; import Web3Eth, { TransactionMiddleware } from '../../src/index'; import * as rpcMethodWrappers from '../../src/rpc_method_wrappers'; +import * as filteringRpcMethodWrappers from '../../src/filtering_rpc_method_wrappers'; import { getBlockNumberValidData, getChainIdValidData, @@ -26,6 +27,7 @@ import { getHashRateValidData, } from '../fixtures/rpc_methods_wrappers'; import { + createNewFilterData, estimateGasValidData, getBalanceValidData, getBlockTransactionCountValidData, @@ -33,6 +35,8 @@ import { getBlockValidData, getCodeValidData, getFeeHistoryValidData, + getFilterLogsData, + getFilterLogsDataWithformater, getPastLogsValidData, getProofValidData, getStorageAtValidData, @@ -46,12 +50,14 @@ import { submitWorkValidData, tx, txReceipt, + uninstallFilterData, } from '../fixtures/web3_eth_methods_with_parameters'; - import { testData as createAccessListTestData } from './rpc_method_wrappers/fixtures/createAccessList'; +import { mockRpcResponse } from './rpc_method_wrappers/fixtures/get_logs'; jest.mock('web3-rpc-methods'); jest.mock('../../src/rpc_method_wrappers'); +jest.mock('../../src/filtering_rpc_method_wrappers'); // eslint-disable-next-line @typescript-eslint/no-unsafe-call jest.spyOn(rpcMethodWrappers, 'getTransaction').mockResolvedValue(tx as TransactionInfoAPI); jest.spyOn(rpcMethodWrappers, 'getTransactionReceipt').mockResolvedValue(txReceipt); @@ -391,6 +397,153 @@ describe('web3_eth_methods_with_parameters', () => { }); }); }); + + describe('getFilterLogs', () => { + it.each(getFilterLogsDataWithformater)( + 'should call getFilterLogs with correct parameters for filterIdentifier %s', + async (filterIdentifier, returnFormat) => { + (filteringRpcMethodWrappers.getFilterLogs as jest.Mock).mockResolvedValue( + mockRpcResponse, + ); + + const result = await web3Eth.getFilterLogs(filterIdentifier, returnFormat); + + expect(filteringRpcMethodWrappers.getFilterLogs).toHaveBeenCalledWith( + web3Eth, + filterIdentifier, + returnFormat, + ); + + expect(result).toEqual(mockRpcResponse); + }, + ); + + it.each(getFilterLogsData)( + 'should use default return format if none is provided for filterIdentifier %s', + async filterIdentifier => { + (filteringRpcMethodWrappers.getFilterLogs as jest.Mock).mockResolvedValue( + mockRpcResponse, + ); + + const result = await web3Eth.getFilterLogs(filterIdentifier); + + expect(filteringRpcMethodWrappers.getFilterLogs).toHaveBeenCalledWith( + web3Eth, + filterIdentifier, + { ...DEFAULT_RETURN_FORMAT, number: FMT_NUMBER.BIGINT }, + ); + + expect(result).toEqual(mockRpcResponse); + }, + ); + }); + + describe('getFilterChanges', () => { + it.each(getFilterLogsDataWithformater)( + 'should call getFilterChanges with correct parameters for filterIdentifier %s', + async (filterIdentifier, returnFormat) => { + ( + filteringRpcMethodWrappers.getFilterChanges as jest.Mock + ).mockResolvedValue(mockRpcResponse); + + const result = await web3Eth.getFilterChanges( + filterIdentifier, + returnFormat, + ); + + expect(filteringRpcMethodWrappers.getFilterChanges).toHaveBeenCalledWith( + web3Eth, + filterIdentifier, + returnFormat, + ); + + expect(result).toEqual(mockRpcResponse); + }, + ); + + it.each(getFilterLogsData)( + 'should use default return format if none is provided for filterIdentifier %s', + async filterIdentifier => { + await web3Eth.getFilterChanges(filterIdentifier); + + expect(filteringRpcMethodWrappers.getFilterChanges).toHaveBeenCalledWith( + web3Eth, + filterIdentifier, + { ...DEFAULT_RETURN_FORMAT, number: FMT_NUMBER.BIGINT }, + ); + }, + ); + }); + + describe('uninstallFilter', () => { + it.each(uninstallFilterData)( + 'should call uninstallFilter with correct parameters for filterIdentifier %s', + async filterIdentifier => { + await web3Eth.uninstallFilter(filterIdentifier); + + expect(filteringRpcMethodWrappers.uninstallFilter).toHaveBeenCalledWith( + web3Eth, + filterIdentifier, + ); + }, + ); + }); + + describe('createNewBlockFilter', () => { + it('should call createNewBlockFilter with correct parameters and return format', async () => { + const returnFormat = { ...DEFAULT_RETURN_FORMAT, number: FMT_NUMBER.BIGINT }; + await web3Eth.createNewBlockFilter(returnFormat); + + expect(filteringRpcMethodWrappers.createNewBlockFilter).toHaveBeenCalledWith( + web3Eth, + returnFormat, + ); + }); + + it('should use default return format if none is provided', async () => { + await web3Eth.createNewBlockFilter(); + + expect(filteringRpcMethodWrappers.createNewBlockFilter).toHaveBeenCalledWith( + web3Eth, + web3Eth.defaultReturnFormat, // Expecting default return format + ); + }); + }); + + describe('createNewFilter', () => { + it.each(createNewFilterData)( + 'should call createNewFilter with correct parameters for filter %s', + async (filterParams, returnFormat) => { + (filteringRpcMethodWrappers.createNewFilter as jest.Mock).mockResolvedValue( + '0x1', + ); + + await web3Eth.createNewFilter(filterParams, returnFormat); + + expect(filteringRpcMethodWrappers.createNewFilter).toHaveBeenCalledWith( + web3Eth, + filterParams, + returnFormat, + ); + }, + ); + + it('should use default return format if none is provided', async () => { + const filterParams = { fromBlock: 123, toBlock: 456 }; // Example filter params + + (filteringRpcMethodWrappers.createNewFilter as jest.Mock).mockResolvedValue( + '0x2', + ); + + await web3Eth.createNewFilter(filterParams); + + expect(filteringRpcMethodWrappers.createNewFilter).toHaveBeenCalledWith( + web3Eth, + filterParams, + web3Eth.defaultReturnFormat, // Expecting default return format + ); + }); + }); }); }); }); diff --git a/packages/web3-types/CHANGELOG.md b/packages/web3-types/CHANGELOG.md index c28706fb44f..d7453363c17 100644 --- a/packages/web3-types/CHANGELOG.md +++ b/packages/web3-types/CHANGELOG.md @@ -215,3 +215,7 @@ Documentation: - update the type for `baseFeePerGas` at `web3.eth.getFeeHistory` to be a number. (#7291) ## [Unreleased] + +### Added + +- `FilterParams` type added (#7353) diff --git a/packages/web3-types/src/eth_types.ts b/packages/web3-types/src/eth_types.ts index 5458fe1d426..dbd6c3348a9 100644 --- a/packages/web3-types/src/eth_types.ts +++ b/packages/web3-types/src/eth_types.ts @@ -278,6 +278,8 @@ export interface Filter { readonly filter?: FilterOption; } +export type FilterParams = Omit; + export interface AccessListEntry { readonly address?: Address; readonly storageKeys?: HexString32Bytes[]; From 07993c230ee2460da8eae093701e7b43462b5a39 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Nov 2024 17:37:58 +0100 Subject: [PATCH 185/186] Bump http-proxy-middleware from 2.0.6 to 2.0.7 in /docs (#7356) Bumps [http-proxy-middleware](https://github.com/chimurai/http-proxy-middleware) from 2.0.6 to 2.0.7. - [Release notes](https://github.com/chimurai/http-proxy-middleware/releases) - [Changelog](https://github.com/chimurai/http-proxy-middleware/blob/v2.0.7/CHANGELOG.md) - [Commits](https://github.com/chimurai/http-proxy-middleware/compare/v2.0.6...v2.0.7) --- updated-dependencies: - dependency-name: http-proxy-middleware dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/yarn.lock b/docs/yarn.lock index eb8d7afa5c4..cf67200d6e6 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -6427,9 +6427,9 @@ http-parser-js@>=0.5.1: integrity sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q== http-proxy-middleware@^2.0.3: - version "2.0.6" - resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz#e1a4dd6979572c7ab5a4e4b55095d1f32a74963f" - integrity sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw== + version "2.0.7" + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz#915f236d92ae98ef48278a95dedf17e991936ec6" + integrity sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA== dependencies: "@types/http-proxy" "^1.17.8" http-proxy "^1.18.1" From aa516b9df16995d449dc672b2c27ce1f8fce563c Mon Sep 17 00:00:00 2001 From: luu-alex <98a.lexluu@gmail.com> Date: Wed, 6 Nov 2024 00:12:43 -0500 Subject: [PATCH 186/186] update version --- CHANGELOG.md | 26 +++++++++++++++- .../web3-account-abstraction/CHANGELOG.md | 6 ++++ .../web3-account-abstraction/package.json | 10 +++---- packages/web3-eth-abi/CHANGELOG.md | 4 ++- packages/web3-eth-abi/package.json | 4 +-- packages/web3-eth-accounts/CHANGELOG.md | 4 ++- packages/web3-eth-accounts/package.json | 6 ++-- packages/web3-eth-contract/CHANGELOG.md | 6 ++++ packages/web3-eth-contract/package.json | 14 ++++----- packages/web3-eth/CHANGELOG.md | 4 ++- packages/web3-eth/package.json | 8 ++--- packages/web3-rpc-providers/CHANGELOG.md | 4 ++- packages/web3-rpc-providers/package.json | 6 ++-- packages/web3-types/CHANGELOG.md | 4 ++- packages/web3-types/package.json | 2 +- packages/web3/CHANGELOG.md | 30 +++++++++++++++++++ packages/web3/package.json | 14 ++++----- packages/web3/src/version.ts | 2 +- 18 files changed, 115 insertions(+), 39 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 08102f589e4..91d8d858ed7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2768,10 +2768,18 @@ If there are any bugs, improvements, optimizations or any new feature proposal f - fix `padRight` validation failure on large `uint` (#7265) -## [Unreleased] +## [4.15.0] ### Added +#### web3-eth + +- `createNewPendingTransactionFilter` , `createNewFilter` , `createNewBlockFilter` , `uninstallFilter` , `getFilterChanges` and `getFilterLogs` are exported from `Web3Eth` and `filtering_rpc_method_wrappers` (#7353) + +#### web3-eth-abi + +- added `decodeFunctionCall` and `decodeFunctionReturn`. (#7345) + #### web3-eth-accounts - `hashMessage` now has a new optional param `skipPrefix` with a default value of `false`. A new function `signRaw` was added to sign a message without prefix. (#7346) @@ -2779,3 +2787,19 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3-rpc-providers - PublicNodeProvider was added (#7322) + +#### web3-types + +- `FilterParams` type added (#7353) + +#### web3-account-abstraction + +- RC release + +### Fixed + +#### web3-eth-contracts + +- Fix Contract methods input param type any[] (#7340) + +## [Unreleased] diff --git a/packages/web3-account-abstraction/CHANGELOG.md b/packages/web3-account-abstraction/CHANGELOG.md index 87f56484e8e..03ad474df40 100644 --- a/packages/web3-account-abstraction/CHANGELOG.md +++ b/packages/web3-account-abstraction/CHANGELOG.md @@ -35,4 +35,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 --> +## [0.1.0.rc.0] + +### Added + +- RC release + ## [Unreleased] diff --git a/packages/web3-account-abstraction/package.json b/packages/web3-account-abstraction/package.json index efbaa27231c..a63d42985b6 100644 --- a/packages/web3-account-abstraction/package.json +++ b/packages/web3-account-abstraction/package.json @@ -56,10 +56,10 @@ "typescript": "^4.7.4" }, "dependencies": { - "web3-core": "^4.6.0", - "web3-types": "^1.8.0", - "web3-eth-abi": "^4.1.3", - "web3-utils": "^4.0.7", - "web3-validator": "^2.0.3" + "web3-core": "^4.7.0", + "web3-eth-abi": "^4.4.0", + "web3-types": "^1.9.0", + "web3-utils": "^4.3.2", + "web3-validator": "^2.0.6" } } diff --git a/packages/web3-eth-abi/CHANGELOG.md b/packages/web3-eth-abi/CHANGELOG.md index 7a6951386d9..0b9920eca20 100644 --- a/packages/web3-eth-abi/CHANGELOG.md +++ b/packages/web3-eth-abi/CHANGELOG.md @@ -194,8 +194,10 @@ Documentation: - `decodeLog` , `decodeParametersWith` , `decodeParameters` and `decodeParameters` now accepts first immutable param as well (#7288) -## [Unreleased] +## [4.4.0] ### Added - added `decodeFunctionCall` and `decodeFunctionReturn`. (#7345) + +## [Unreleased] diff --git a/packages/web3-eth-abi/package.json b/packages/web3-eth-abi/package.json index 71ad43e1bf8..02bead98645 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.4.0", "description": "Web3 module encode and decode EVM in/output.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -44,7 +44,7 @@ "dependencies": { "abitype": "0.7.1", "web3-errors": "^1.3.0", - "web3-types": "^1.8.1", + "web3-types": "^1.9.0", "web3-utils": "^4.3.2", "web3-validator": "^2.0.6" }, diff --git a/packages/web3-eth-accounts/CHANGELOG.md b/packages/web3-eth-accounts/CHANGELOG.md index 22498dca080..939bd836ce8 100644 --- a/packages/web3-eth-accounts/CHANGELOG.md +++ b/packages/web3-eth-accounts/CHANGELOG.md @@ -183,8 +183,10 @@ Documentation: - Revert `TransactionFactory.registerTransactionType` if there is a version mistatch between `web3-eth` and `web3-eth-accounts` and fix nextjs problem. (#7216) -## [Unreleased] +## [4.3.0] ### Added - `hashMessage` now has a new optional param `skipPrefix` with a default value of `false`. A new function `signRaw` was added to sign a message without prefix. (#7346) + +## [Unreleased] diff --git a/packages/web3-eth-accounts/package.json b/packages/web3-eth-accounts/package.json index cc411137242..afd61cf1549 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.2.1", + "version": "4.3.0", "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.3.0", - "web3-types": "^1.7.0", - "web3-utils": "^4.3.1", + "web3-types": "^1.9.0", + "web3-utils": "^4.3.2", "web3-validator": "^2.0.6" } } diff --git a/packages/web3-eth-contract/CHANGELOG.md b/packages/web3-eth-contract/CHANGELOG.md index 318816b7941..1e7906decf1 100644 --- a/packages/web3-eth-contract/CHANGELOG.md +++ b/packages/web3-eth-contract/CHANGELOG.md @@ -404,4 +404,10 @@ Documentation: - The returnred properties of `contract.deploy(...)` are structured with a newly created class named `DeployerMethodClass`. (#7197) - Add a missed accepted type for the `abi` parameter, at `dataInputEncodeMethodHelper` and `getSendTxParams`. (#7197) +## [4.7.1] + +### Fixed + +- Fix Contract methods input param type any[] (#7340) + ## [Unreleased] diff --git a/packages/web3-eth-contract/package.json b/packages/web3-eth-contract/package.json index 237e1cec48b..4d780091c80 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.7.0", + "version": "4.7.1", "description": "Web3 module to interact with Ethereum smart contracts.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -46,12 +46,12 @@ }, "dependencies": { "@ethereumjs/rlp": "^5.0.2", - "web3-core": "^4.5.1", + "web3-core": "^4.7.0", "web3-errors": "^1.3.0", - "web3-eth": "^4.8.2", - "web3-eth-abi": "^4.2.3", - "web3-types": "^1.7.0", - "web3-utils": "^4.3.1", + "web3-eth": "^4.11.0", + "web3-eth-abi": "^4.4.0", + "web3-types": "^1.9.0", + "web3-utils": "^4.3.2", "web3-validator": "^2.0.6" }, "devDependencies": { @@ -69,7 +69,7 @@ "prettier": "^2.7.1", "ts-jest": "^29.1.1", "typescript": "^4.7.4", - "web3-eth-accounts": "^4.2.0", + "web3-eth-accounts": "^4.3.0", "web3-providers-ws": "^4.0.8" } } diff --git a/packages/web3-eth/CHANGELOG.md b/packages/web3-eth/CHANGELOG.md index 5f1aab23bde..36f6fd4b633 100644 --- a/packages/web3-eth/CHANGELOG.md +++ b/packages/web3-eth/CHANGELOG.md @@ -289,8 +289,10 @@ Documentation: - `populateGasPrice` function now checks `Web3Context.config.ignoreGasPricing`. If `ignoreGasPricing` is true, gasPrice will not be estimated (#7320) -## [Unreleased] +## [4.11.0] ### Added - `createNewPendingTransactionFilter` , `createNewFilter` , `createNewBlockFilter` , `uninstallFilter` , `getFilterChanges` and `getFilterLogs` are exported from `Web3Eth` and `filtering_rpc_method_wrappers` (#7353) + +## [Unreleased] diff --git a/packages/web3-eth/package.json b/packages/web3-eth/package.json index 6cd93768a6b..6c598d767e7 100644 --- a/packages/web3-eth/package.json +++ b/packages/web3-eth/package.json @@ -1,6 +1,6 @@ { "name": "web3-eth", - "version": "4.10.0", + "version": "4.11.0", "description": "Web3 module to interact with the Ethereum blockchain and smart contracts.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -65,12 +65,12 @@ "setimmediate": "^1.0.5", "web3-core": "^4.7.0", "web3-errors": "^1.3.0", - "web3-eth-abi": "^4.3.0", - "web3-eth-accounts": "^4.2.1", + "web3-eth-abi": "^4.4.0", + "web3-eth-accounts": "^4.3.0", "web3-net": "^4.1.0", "web3-providers-ws": "^4.0.8", "web3-rpc-methods": "^1.3.0", - "web3-types": "^1.8.1", + "web3-types": "^1.9.0", "web3-utils": "^4.3.2", "web3-validator": "^2.0.6" } diff --git a/packages/web3-rpc-providers/CHANGELOG.md b/packages/web3-rpc-providers/CHANGELOG.md index 110b620707d..4bc16682b31 100644 --- a/packages/web3-rpc-providers/CHANGELOG.md +++ b/packages/web3-rpc-providers/CHANGELOG.md @@ -58,8 +58,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Updated rate limit error of QuickNode provider for HTTP transport - Added optional `HttpProviderOptions | SocketOptions` in `Web3ExternalProvider` and `QuickNodeProvider` for provider configs -## [Unreleased] +## [1.0.0-rc.3] ### Added - PublicNodeProvider was added (#7322) + +## [Unreleased] diff --git a/packages/web3-rpc-providers/package.json b/packages/web3-rpc-providers/package.json index 91da2144b40..9339d4a3fb3 100644 --- a/packages/web3-rpc-providers/package.json +++ b/packages/web3-rpc-providers/package.json @@ -1,6 +1,6 @@ { "name": "web3-rpc-providers", - "version": "1.0.0-rc.2", + "version": "1.0.0-rc.3", "description": "Web3 Providers package", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -60,8 +60,8 @@ "web3-errors": "^1.3.0", "web3-providers-http": "^4.2.0", "web3-providers-ws": "^4.0.8", - "web3-types": "^1.7.0", - "web3-utils": "^4.3.1", + "web3-types": "^1.9.0", + "web3-utils": "^4.3.2", "web3-validator": "^2.0.6" } } diff --git a/packages/web3-types/CHANGELOG.md b/packages/web3-types/CHANGELOG.md index d7453363c17..4158022da52 100644 --- a/packages/web3-types/CHANGELOG.md +++ b/packages/web3-types/CHANGELOG.md @@ -214,8 +214,10 @@ Documentation: - update the type for `baseFeePerGas` at `web3.eth.getFeeHistory` to be a number. (#7291) -## [Unreleased] +## [1.9.0] ### Added - `FilterParams` type added (#7353) + +## [Unreleased] diff --git a/packages/web3-types/package.json b/packages/web3-types/package.json index a16d9737993..31c8f217726 100644 --- a/packages/web3-types/package.json +++ b/packages/web3-types/package.json @@ -1,6 +1,6 @@ { "name": "web3-types", - "version": "1.8.1", + "version": "1.9.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/CHANGELOG.md b/packages/web3/CHANGELOG.md index 9830831b15a..f3ec9b9679e 100644 --- a/packages/web3/CHANGELOG.md +++ b/packages/web3/CHANGELOG.md @@ -530,4 +530,34 @@ Documentation: - fix `padRight` validation failure on large `uint` (#7265) +## [4.15.0] + +### Added + +#### web3-eth + +- `createNewPendingTransactionFilter` , `createNewFilter` , `createNewBlockFilter` , `uninstallFilter` , `getFilterChanges` and `getFilterLogs` are exported from `Web3Eth` and `filtering_rpc_method_wrappers` (#7353) + +#### web3-eth-abi + +- added `decodeFunctionCall` and `decodeFunctionReturn`. (#7345) + +#### web3-eth-accounts + +- `hashMessage` now has a new optional param `skipPrefix` with a default value of `false`. A new function `signRaw` was added to sign a message without prefix. (#7346) + +#### web3-rpc-providers + +- PublicNodeProvider was added (#7322) + +#### web3-types + +- `FilterParams` type added (#7353) + +### Fixed + +#### web3-eth-contracts + +- Fix Contract methods input param type any[] (#7340) + ## [Unreleased] diff --git a/packages/web3/package.json b/packages/web3/package.json index 06565aeb4a3..7e4be7ba12d 100644 --- a/packages/web3/package.json +++ b/packages/web3/package.json @@ -1,6 +1,6 @@ { "name": "web3", - "version": "4.14.0", + "version": "4.15.0", "description": "Ethereum JavaScript API", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -88,10 +88,10 @@ "dependencies": { "web3-core": "^4.7.0", "web3-errors": "^1.3.0", - "web3-eth": "^4.10.0", - "web3-eth-abi": "^4.3.0", - "web3-eth-accounts": "^4.2.1", - "web3-eth-contract": "^4.7.0", + "web3-eth": "^4.11.0", + "web3-eth-abi": "^4.4.0", + "web3-eth-accounts": "^4.3.0", + "web3-eth-contract": "^4.7.1", "web3-eth-ens": "^4.4.0", "web3-eth-iban": "^4.0.7", "web3-eth-personal": "^4.1.0", @@ -99,8 +99,8 @@ "web3-providers-http": "^4.2.0", "web3-providers-ws": "^4.0.8", "web3-rpc-methods": "^1.3.0", - "web3-rpc-providers": "^1.0.0-rc.2", - "web3-types": "^1.8.1", + "web3-rpc-providers": "^1.0.0-rc.3", + "web3-types": "^1.9.0", "web3-utils": "^4.3.2", "web3-validator": "^2.0.6" } diff --git a/packages/web3/src/version.ts b/packages/web3/src/version.ts index 6d4d3be7654..ca906081781 100644 --- a/packages/web3/src/version.ts +++ b/packages/web3/src/version.ts @@ -1 +1 @@ -/* eslint-disable header/header */ export const Web3PkgInfo = { version: '4.14.0' }; +/* eslint-disable header/header */ export const Web3PkgInfo = { version: '4.15.0' };