From 822f8c15863b28e4685b88f1da5502c36b9752d3 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 16 Oct 2024 09:52:53 -0400 Subject: [PATCH 01/49] 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 02/49] 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 03/49] 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 04/49] 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 05/49] 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 06/49] 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 07/49] 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 08/49] 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 09/49] 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 10/49] 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 11/49] 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 12/49] 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 13/49] 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 14/49] [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 15/49] 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 16/49] 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 + + + + Codestin Search App + + +
+ + +``` + +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 17/49] 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 18/49] 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 098ee6d30f76082f9cfef16cb256d3f1682ee956 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 6 Nov 2024 18:00:04 -0500 Subject: [PATCH 19/49] v4.15.0 (#7370) * update version * update e2e storage tests on mainnet * update storage test * changing fixture --- 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 +- .../test/e2e/mainnet/get_storage_at.test.ts | 2 +- 19 files changed, 116 insertions(+), 40 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' }; 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 5d6ccba97f5..e1a971230a7 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( - '0x00000000000000000000000000000000000000000000000000c34723fc9a9240', + '0x00000000000000000000000000000000000000000000000000ca4aafc2e0b163', ); } else { // eslint-disable-next-line jest/no-conditional-expect From 1724f3542ccfe3c17af9e14b93da72a2f65d959e Mon Sep 17 00:00:00 2001 From: Kris <605420+krzysu@users.noreply.github.com> Date: Mon, 11 Nov 2024 09:14:43 +0100 Subject: [PATCH 20/49] fix: correctly close ws connection in web3-eth-contract integration tests (#7338) --- lerna.json | 10 +- packages/web3-eth-contract/package.json | 4 +- .../integration/contract_accesslist.test.ts | 17 +- .../test/integration/contract_clone.test.ts | 13 +- .../integration/contract_defaults.test.ts | 22 +- .../contract_defaults_extra.test.ts | 145 ++++----- .../test/integration/contract_deploy.test.ts | 77 +++-- .../integration/contract_empty_string.test.ts | 13 +- .../test/integration/contract_erc20.test.ts | 43 ++- .../test/integration/contract_erc721.test.ts | 76 ++--- .../contract_estimateGas_without_0x.test.ts | 10 +- .../test/integration/contract_events.test.ts | 279 +++++++++--------- .../contract_filter_events.test.ts | 10 + .../test/integration/contract_methods.test.ts | 9 + .../contract_methods_errors.test.ts | 5 +- .../contract_negative_numbers.test.ts | 15 +- .../contract_simple_overloaded.test.ts | 12 +- .../local_account/contract_deploy.test.ts | 15 +- .../local_account/contract_erc20.test.ts | 10 +- .../local_account/contract_erc721.test.ts | 17 +- .../contract_overloaded_methods.test.ts | 10 +- scripts/system_tests_utils.ts | 22 +- 22 files changed, 487 insertions(+), 347 deletions(-) diff --git a/lerna.json b/lerna.json index b5104ac58aa..e45823a46f8 100644 --- a/lerna.json +++ b/lerna.json @@ -1,7 +1,7 @@ { - "lerna": "4.0.0", - "npmClient": "yarn", - "useWorkspaces": true, - "version": "independent", - "packages": ["packages/*", "tools/*"] + "lerna": "4.0.0", + "npmClient": "yarn", + "useWorkspaces": true, + "version": "independent", + "packages": ["packages/*", "tools/*"] } diff --git a/packages/web3-eth-contract/package.json b/packages/web3-eth-contract/package.json index 4d780091c80..30db5ffc723 100644 --- a/packages/web3-eth-contract/package.json +++ b/packages/web3-eth-contract/package.json @@ -35,11 +35,11 @@ "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 --runInBand --forceExit --coverage=true --coverage-reporters=text", + "test:coverage:integration": "jest --config=./test/integration/jest.config.js --runInBand --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 --runInBand --forceExit", + "test:integration": "jest --config=./test/integration/jest.config.js --runInBand", "test:e2e:electron": "npx cypress run --headless --browser electron --env grep='ignore',invert=true", "test:e2e:chrome": "npx cypress run --headless --browser chrome --env grep='ignore',invert=true", "test:e2e:firefox": "npx cypress run --headless --browser firefox --env grep='ignore',invert=true" 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 3173f452c33..9c1aff2af36 100644 --- a/packages/web3-eth-contract/test/integration/contract_accesslist.test.ts +++ b/packages/web3-eth-contract/test/integration/contract_accesslist.test.ts @@ -23,16 +23,18 @@ import { describeIf, getSystemTestBackend, BACKEND, + closeOpenConnection, } from '../fixtures/system_test_utils'; describe('contract', () => { describeIf(getSystemTestBackend() === BACKEND.GETH)('createAccessList', () => { let contract: Contract; + let deployedContract: Contract; let deployOptions: Record; let sendOptions: Record; let acc: { address: string; privateKey: string }; - beforeEach(async () => { + beforeAll(async () => { contract = new Contract(GreeterAbi, undefined, { provider: getSystemTestProvider(), }); @@ -46,10 +48,16 @@ describe('contract', () => { sendOptions = { from: acc.address, gas: '1000000' }; }); - it('create access list for setter', async () => { - const deployedContract = await contract.deploy(deployOptions).send(sendOptions); + afterAll(async () => { + await closeOpenConnection(contract); + }); + + beforeEach(async () => { + deployedContract = await contract.deploy(deployOptions).send(sendOptions); deployedContract.defaultAccount = acc.address; + }); + it('create access list for setter', async () => { const receipt = await deployedContract.methods .setGreeting('New Greeting') .send({ gas: '1000000' }); @@ -75,9 +83,6 @@ describe('contract', () => { }); it('create access list for getter', async () => { - const deployedContract = await contract.deploy(deployOptions).send(sendOptions); - deployedContract.defaultAccount = acc.address; - const receipt = await deployedContract.methods .setGreeting('New Greeting') .send({ gas: '1000000' }); diff --git a/packages/web3-eth-contract/test/integration/contract_clone.test.ts b/packages/web3-eth-contract/test/integration/contract_clone.test.ts index 873ac0658ea..e27b0be402f 100644 --- a/packages/web3-eth-contract/test/integration/contract_clone.test.ts +++ b/packages/web3-eth-contract/test/integration/contract_clone.test.ts @@ -16,13 +16,18 @@ along with web3.js. If not, see . */ import { Contract } from '../../src'; import { GreeterBytecode, GreeterAbi } from '../shared_fixtures/build/Greeter'; -import { getSystemTestProvider, createTempAccount } from '../fixtures/system_test_utils'; +import { + getSystemTestProvider, + createTempAccount, + closeOpenConnection, +} from '../fixtures/system_test_utils'; describe('contract', () => { describe('clone', () => { let contract: Contract; let deployOptions: Record; let sendOptions: Record; + beforeAll(async () => { contract = new Contract(GreeterAbi, undefined, { provider: getSystemTestProvider(), @@ -34,7 +39,11 @@ describe('contract', () => { arguments: ['My Greeting'], }; - sendOptions = { from: acc.address, gas: '1000000' }; + sendOptions = { from: acc.address }; + }); + + afterAll(async () => { + await closeOpenConnection(contract); }); it('should clone the contract but with same address', async () => { diff --git a/packages/web3-eth-contract/test/integration/contract_defaults.test.ts b/packages/web3-eth-contract/test/integration/contract_defaults.test.ts index b481237c739..0f28e31269b 100644 --- a/packages/web3-eth-contract/test/integration/contract_defaults.test.ts +++ b/packages/web3-eth-contract/test/integration/contract_defaults.test.ts @@ -20,7 +20,11 @@ import { Web3Context } from 'web3-core'; import { Contract } from '../../src'; import { GreeterBytecode, GreeterAbi } from '../shared_fixtures/build/Greeter'; -import { getSystemTestProvider, createTempAccount } from '../fixtures/system_test_utils'; +import { + getSystemTestProvider, + createTempAccount, + closeOpenConnection, +} from '../fixtures/system_test_utils'; describe('contract', () => { describe('defaults', () => { @@ -43,6 +47,10 @@ describe('contract', () => { sendOptions = { from: acc.address, gas: '1000000' }; }); + afterEach(async () => { + await closeOpenConnection(contract); + }); + it('should use "defaultAccount" on "instance" level instead of "from"', async () => { const deployedContract = await contract.deploy(deployOptions).send(sendOptions); // eslint-disable-next-line prefer-destructuring @@ -63,23 +71,27 @@ describe('contract', () => { }); it('should set syncWithContext from init options', async () => { - contract = new Contract(GreeterAbi, { + const testContract = new Contract(GreeterAbi, { provider: getSystemTestProvider(), syncWithContext: true, }); - contract = await contract.deploy(deployOptions).send(sendOptions); + const deployedContract = await testContract.deploy(deployOptions).send(sendOptions); - expect(contract.syncWithContext).toBeTruthy(); + expect(deployedContract.syncWithContext).toBeTruthy(); + + await closeOpenConnection(testContract); }); - it('should subscribe to provided context upon instantiation', () => { + it('should subscribe to provided context upon instantiation', async () => { const web3Context = new Web3Context('http://127.0.0.1:8545'); const _contract = new Contract([], { syncWithContext: true }, web3Context); expect(_contract.defaultBlock).toBe('latest'); web3Context.defaultBlock = 'earliest'; expect(_contract.defaultBlock).toBe('earliest'); + + await closeOpenConnection(_contract); }); describe('defaultBlock', () => { diff --git a/packages/web3-eth-contract/test/integration/contract_defaults_extra.test.ts b/packages/web3-eth-contract/test/integration/contract_defaults_extra.test.ts index 206b10ee709..ce4f126a539 100644 --- a/packages/web3-eth-contract/test/integration/contract_defaults_extra.test.ts +++ b/packages/web3-eth-contract/test/integration/contract_defaults_extra.test.ts @@ -48,7 +48,11 @@ describe('contract defaults (extra)', () => { let sendOptions: Record; let acc: { address: string; privateKey: string }; - beforeEach(async () => { + beforeAll(async () => { + contract = new Contract(GreeterAbi, undefined, { + provider: getSystemTestProvider(), + }); + acc = await createTempAccount(); deployOptions = { @@ -59,27 +63,23 @@ describe('contract defaults (extra)', () => { sendOptions = { from: acc.address, gas: '1000000' }; }); - afterEach(async () => { + afterAll(async () => { await closeOpenConnection(contract); }); it('should use "defaultHardfork" on "instance" level', async () => { const hardfork = 'berlin'; - contract = new Contract(GreeterAbi, undefined, { - provider: getSystemTestProvider(), - }); - - contract = await contract.deploy(deployOptions).send(sendOptions); - contract.defaultHardfork = hardfork; + const deployedContract = await contract.deploy(deployOptions).send(sendOptions); + deployedContract.defaultHardfork = hardfork; - await contract.methods.setGreeting('New Greeting').send(sendOptions); - await contract.methods.greet().send(sendOptions); + await deployedContract.methods.setGreeting('New Greeting').send(sendOptions); + await deployedContract.methods.greet().send(sendOptions); - expect(contract.defaultHardfork).toBe(hardfork); + expect(deployedContract.defaultHardfork).toBe(hardfork); const callSpy = jest.spyOn(Web3Eth, 'call'); - await contract.methods.greet().call(); + await deployedContract.methods.greet().call(); expect(callSpy).toHaveBeenLastCalledWith( expect.objectContaining({ @@ -93,24 +93,20 @@ describe('contract defaults (extra)', () => { describe('defaultChain', () => { it('should use "defaultChain" on "instance" level', async () => { - contract = new Contract(GreeterAbi, undefined, { - provider: getSystemTestProvider(), - }); + const deployedContract = await contract.deploy(deployOptions).send(sendOptions); - contract = await contract.deploy(deployOptions).send(sendOptions); - - expect(contract.defaultChain).toBe('mainnet'); + expect(deployedContract.defaultChain).toBe('mainnet'); const defaultChain = 'ropsten'; - contract.defaultChain = defaultChain; + deployedContract.defaultChain = defaultChain; - expect(contract.defaultChain).toBe(defaultChain); + expect(deployedContract.defaultChain).toBe(defaultChain); - await contract.methods.setGreeting('New Greeting').send(sendOptions); + await deployedContract.methods.setGreeting('New Greeting').send(sendOptions); const callSpy = jest.spyOn(Web3Eth, 'call'); - await contract.methods.greet().call(); + await deployedContract.methods.greet().call(); expect(callSpy).toHaveBeenCalledWith( expect.objectContaining({ @@ -131,27 +127,12 @@ describe('contract defaults (extra)', () => { hardfork: 'london' as Hardfork, }; - beforeEach(async () => { - contract = new Contract(GreeterAbi, undefined, { - provider: getSystemTestProvider(), - }); - acc = await createTempAccount(); - - deployOptions = { - data: GreeterBytecode, - arguments: ['My Greeting'], - }; - - sendOptions = { from: acc.address, gas: '1000000' }; - - contract = await contract.deploy(deployOptions).send(sendOptions); - }); - it('should use "defaultCommon" on "instance" level', async () => { - contract.defaultCommon = common; + const deployedContract = await contract.deploy(deployOptions).send(sendOptions); + deployedContract.defaultCommon = common; const callSpy = jest.spyOn(Web3Eth, 'call'); - await contract.methods.greet().call(); + await deployedContract.methods.greet().call(); expect(callSpy).toHaveBeenCalledWith( expect.objectContaining({ @@ -166,19 +147,16 @@ describe('contract defaults (extra)', () => { describeIf(isWs)('transactionBlockTimeout', () => { it('should use "transactionBlockTimeout" on "instance" level', async () => { - contract = new Contract(GreeterAbi, undefined, { - provider: getSystemTestProvider(), - }); - contract = await contract.deploy(deployOptions).send(sendOptions); + const deployedContract = await contract.deploy(deployOptions).send(sendOptions); const sendTransactionSpy = jest.spyOn(Web3Eth, 'sendTransaction'); - expect(contract.transactionBlockTimeout).toBe(50); + expect(deployedContract.transactionBlockTimeout).toBe(50); - contract.transactionBlockTimeout = 32; - expect(contract.transactionBlockTimeout).toBe(32); + deployedContract.transactionBlockTimeout = 32; + expect(deployedContract.transactionBlockTimeout).toBe(32); // eslint-disable-next-line @typescript-eslint/no-unsafe-call - await contract.methods.setGreeting('New Greeting').send(sendOptions); + await deployedContract.methods.setGreeting('New Greeting').send(sendOptions); expect(sendTransactionSpy).toHaveBeenLastCalledWith( expect.objectContaining({ @@ -191,38 +169,41 @@ describe('contract defaults (extra)', () => { }); it('should fail if transaction was not mined within `transactionBlockTimeout` blocks', async () => { - contract = new Contract(GreeterAbi, undefined, { - provider: getSystemTestProvider(), - }); - contract = await contract.deploy(deployOptions).send(sendOptions); + const deployedContract = await contract.deploy(deployOptions).send(sendOptions); // Make the test run faster by casing the polling to start after 2 blocks - contract.transactionBlockTimeout = 1; + deployedContract.transactionBlockTimeout = 1; // Prevent transaction from stucking for a long time if the provider (like Ganache v7.4.0) // does not respond, when raising the nonce - contract.transactionSendTimeout = MAX_32_SIGNED_INTEGER; + deployedContract.transactionSendTimeout = MAX_32_SIGNED_INTEGER; // Increase other timeouts - contract.transactionPollingTimeout = MAX_32_SIGNED_INTEGER; + deployedContract.transactionPollingTimeout = MAX_32_SIGNED_INTEGER; // Setting a high `nonce` when sending a transaction, to cause the RPC call to stuck at the Node // The previous test has the nonce set to Number.MAX_SAFE_INTEGER. // So, just decrease 1 from it here to not fall into another error. - const sentTx = contract.methods.setGreeting('New Greeting with high nonce').send({ - ...sendOptions, - nonce: (Number.MAX_SAFE_INTEGER - 1).toString(), - }); + const sentTx = deployedContract.methods + .setGreeting('New Greeting with high nonce') + .send({ + ...sendOptions, + nonce: (Number.MAX_SAFE_INTEGER - 1).toString(), + }); // Some providers (mostly used for development) will make blocks only when there are new transactions // So, send 2 transactions because in this test `transactionBlockTimeout = 2`. And do nothing if an error happens. setTimeout(() => { (async () => { try { - await contract.methods.setGreeting('New Greeting').send(sendOptions); + await deployedContract.methods + .setGreeting('New Greeting') + .send(sendOptions); } catch (error) { // Nothing needed to be done. } try { - await contract.methods.setGreeting('New Greeting').send(sendOptions); + await deployedContract.methods + .setGreeting('New Greeting') + .send(sendOptions); } catch (error) { // Nothing needed to be done. } @@ -237,20 +218,16 @@ describe('contract defaults (extra)', () => { describeIf(isWs)('blockHeaderTimeout', () => { it('should use "blockHeaderTimeout" on "instance" level', async () => { - contract = new Contract(GreeterAbi, undefined, { - provider: getSystemTestProvider(), - }); + const deployedContract = await contract.deploy(deployOptions).send(sendOptions); - contract = await contract.deploy(deployOptions).send(sendOptions); - - expect(contract.blockHeaderTimeout).toBe(10); + expect(deployedContract.blockHeaderTimeout).toBe(10); const blockHeaderTimeout = 1; - contract.blockHeaderTimeout = blockHeaderTimeout; + deployedContract.blockHeaderTimeout = blockHeaderTimeout; - expect(contract.blockHeaderTimeout).toBe(blockHeaderTimeout); + expect(deployedContract.blockHeaderTimeout).toBe(blockHeaderTimeout); - const sentTx = contract.methods.setGreeting('New Greeting').send(sendOptions); + const sentTx = deployedContract.methods.setGreeting('New Greeting').send(sendOptions); const confirmationPromise = new Promise((resolve: Resolve) => { // Tx promise is handled separately @@ -262,7 +239,9 @@ describe('contract defaults (extra)', () => { resolve(); } else { // Send a transaction to cause dev providers creating new blocks to fire the 'confirmation' event again. - await contract.methods.setGreeting('New Greeting').send(sendOptions); + await deployedContract.methods + .setGreeting('New Greeting') + .send(sendOptions); } }, ); @@ -284,36 +263,28 @@ describe('contract defaults (extra)', () => { describeIf(isHttp)('transactionPollingInterval', () => { it('should use "transactionPollingTimeout" on "instance" level', async () => { - contract = new Contract(GreeterAbi, undefined, { - provider: getSystemTestProvider(), - }); - - contract = await contract.deploy(deployOptions).send(sendOptions); + const deployedContract = await contract.deploy(deployOptions).send(sendOptions); const transactionPollingInterval = 500; - contract.transactionPollingInterval = transactionPollingInterval; + deployedContract.transactionPollingInterval = transactionPollingInterval; - expect(contract.transactionPollingInterval).toBe(transactionPollingInterval); + expect(deployedContract.transactionPollingInterval).toBe(transactionPollingInterval); }); }); it('should use "handleRevert" on "instance" level', async () => { - contract = new Contract(GreeterAbi, undefined, { - provider: getSystemTestProvider(), - }); - - contract = await contract.deploy(deployOptions).send(sendOptions); + const deployedContract = await contract.deploy(deployOptions).send(sendOptions); - expect(contract.handleRevert).toBeFalsy(); + expect(deployedContract.handleRevert).toBeFalsy(); const handleRevert = true; - contract.handleRevert = handleRevert; + deployedContract.handleRevert = handleRevert; - expect(contract.handleRevert).toBe(handleRevert); + expect(deployedContract.handleRevert).toBe(handleRevert); const sendTransactionSpy = jest.spyOn(Web3Eth, 'sendTransaction'); - await contract.methods.setGreeting('New Greeting').send(sendOptions); + await deployedContract.methods.setGreeting('New Greeting').send(sendOptions); expect(sendTransactionSpy).toHaveBeenCalled(); }); 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 b54ed63b41d..e4833882e94 100644 --- a/packages/web3-eth-contract/test/integration/contract_deploy.test.ts +++ b/packages/web3-eth-contract/test/integration/contract_deploy.test.ts @@ -17,13 +17,11 @@ along with web3.js. If not, see . import { Web3Eth } from 'web3-eth'; import { FMT_BYTES, FMT_NUMBER } from 'web3-types'; 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'; import { DeployRevertAbi, DeployRevertBytecode } from '../shared_fixtures/build/DeployRevert'; import { getSystemTestProvider, - isWs, createTempAccount, createNewAccount, signTxAndSendEIP2930, @@ -46,16 +44,22 @@ describe('contract', () => { beforeAll(() => { web3Eth = new Web3Eth(getSystemTestProvider()); + contract = new Contract(GreeterAbi, undefined, { + provider: getSystemTestProvider(), + }); deployOptions = { data: GreeterBytecode, arguments: ['My Greeting'], }; }); + + afterAll(async () => { + await closeOpenConnection(web3Eth); + await closeOpenConnection(contract); + }); + beforeEach(async () => { acc = await createTempAccount(); - contract = new Contract(GreeterAbi, undefined, { - provider: getSystemTestProvider(), - }); sendOptions = { from: acc.address, gas: '1000000' }; }); @@ -71,9 +75,6 @@ describe('contract', () => { expect(deployedContract.options.address).toEqual(address); }); - afterAll(async () => { - await closeOpenConnection(web3Eth); - }); describe('local account', () => { it.each([signTxAndSendEIP1559, signTxAndSendEIP2930])( 'should deploy the contract %p', @@ -112,9 +113,11 @@ describe('contract', () => { ); it('should return estimated gas of contract constructor %p', async () => { - const estimatedGas = await new Contract(GreeterAbi, undefined, { + const testContract = new Contract(GreeterAbi, undefined, { provider: getSystemTestProvider(), - }) + }); + + const estimatedGas = await testContract .deploy({ data: GreeterBytecode, arguments: ['My Greeting'], @@ -123,21 +126,27 @@ describe('contract', () => { from: acc.address, gas: '1000000', }); + expect(typeof estimatedGas).toBe('bigint'); expect(Number(estimatedGas)).toBeGreaterThan(0); + + await closeOpenConnection(testContract); }); + it.each(Object.values(FMT_NUMBER))( 'should return estimated gas of contract constructor %p with correct type', async format => { const returnFormat = { number: format as FMT_NUMBER, bytes: FMT_BYTES.HEX }; - const estimatedGas = await new Contract( + const testContract = new Contract( GreeterAbi, { provider: getSystemTestProvider(), }, returnFormat, - ) + ); + + const estimatedGas = await testContract .deploy({ data: GreeterBytecode, arguments: ['My Greeting'], @@ -146,14 +155,20 @@ describe('contract', () => { from: acc.address, gas: '1000000', }); + expect(typeof estimatedGas).toBe(mapFormatToType[format as string]); expect(Number(estimatedGas)).toBeGreaterThan(0); + + await closeOpenConnection(testContract); }, ); + it('should return estimated gas of contract constructor without arguments', async () => { - const estimatedGas = await new Contract(ERC721TokenAbi, undefined, { + const testContract = new Contract(ERC721TokenAbi, undefined, { provider: getSystemTestProvider(), - }) + }); + + const estimatedGas = await testContract .deploy({ data: ERC721TokenBytecode, arguments: [], @@ -162,8 +177,12 @@ describe('contract', () => { from: acc.address, gas: '10000000', }); + expect(Number(estimatedGas)).toBeGreaterThan(0); + + await closeOpenConnection(testContract); }); + it('should return estimated gas of contract method', async () => { const contractDeployed = await contract.deploy(deployOptions).send(sendOptions); @@ -173,8 +192,10 @@ describe('contract', () => { gas: '1000000', from: acc.address, }); + expect(Number(estimatedGas)).toBeGreaterThan(0); }); + it('should return estimated gas of contract method without arguments', async () => { const contractDeployed = await contract.deploy(deployOptions).send(sendOptions); @@ -193,15 +214,19 @@ describe('contract', () => { }); it('should deploy the contract if data is provided at initiation', async () => { - contract = new Contract(GreeterAbi, { + const testContract = new Contract(GreeterAbi, { provider: getSystemTestProvider(), data: GreeterBytecode, from: acc.address, gas: '1000000', }); - const deployedContract = await contract.deploy({ arguments: ['Hello World'] }).send(); + const deployedContract = await testContract + .deploy({ arguments: ['Hello World'] }) + .send(); expect(deployedContract).toBeDefined(); + + await closeOpenConnection(testContract); }); it('should return instance of the contract', async () => { @@ -218,26 +243,18 @@ describe('contract', () => { it('should emit the "confirmation" event', async () => { const confirmationHandler = jest.fn(); - contract.setConfig({ transactionConfirmationBlocks: 1 }); - await contract + contract.setConfig({ transactionConfirmationBlocks: 2 }); + + const promiEvent = contract .deploy(deployOptions) .send(sendOptions) .on('confirmation', confirmationHandler); - // Wait for some time to allow the transaction to be processed - await sleep(500); - - // Deploy once again to trigger block mining to trigger confirmation - // We can send any other transaction as well - await contract.deploy(deployOptions).send(sendOptions); + // Deploy the contract + await promiEvent; await sendFewSampleTxs(3); - // Wait for some fraction of time to trigger the handler - // On http we use polling to get confirmation, so wait a bit longer - await sleep(isWs ? 500 : 2000); - - // eslint-disable-next-line jest/no-standalone-expect expect(confirmationHandler).toHaveBeenCalled(); }); @@ -345,6 +362,8 @@ describe('contract', () => { 'Error happened while trying to execute a function inside a smart contract', ); } + + await closeOpenConnection(revert); }); }); }); diff --git a/packages/web3-eth-contract/test/integration/contract_empty_string.test.ts b/packages/web3-eth-contract/test/integration/contract_empty_string.test.ts index 25540c2ebf4..ceba0aa6c61 100644 --- a/packages/web3-eth-contract/test/integration/contract_empty_string.test.ts +++ b/packages/web3-eth-contract/test/integration/contract_empty_string.test.ts @@ -16,13 +16,18 @@ along with web3.js. If not, see . */ import { Contract } from '../../src'; -import { getSystemTestProvider, createTempAccount } from '../fixtures/system_test_utils'; +import { + getSystemTestProvider, + createTempAccount, + closeOpenConnection, +} from '../fixtures/system_test_utils'; import { MyContractAbi, MyContractBytecode } from '../fixtures/MyContract'; describe('request empty string from contract', () => { let contract: Contract; let deployOptions: Record; let sendOptions: Record; + beforeAll(async () => { contract = new Contract(MyContractAbi, undefined, { provider: getSystemTestProvider(), @@ -34,7 +39,11 @@ describe('request empty string from contract', () => { arguments: [], }; - sendOptions = { from: acc.address, gas: '1000000' }; + sendOptions = { from: acc.address }; + }); + + afterAll(async () => { + await closeOpenConnection(contract); }); it('should fetch empty string', async () => { diff --git a/packages/web3-eth-contract/test/integration/contract_erc20.test.ts b/packages/web3-eth-contract/test/integration/contract_erc20.test.ts index 5e268691aa5..c18582a4f8e 100644 --- a/packages/web3-eth-contract/test/integration/contract_erc20.test.ts +++ b/packages/web3-eth-contract/test/integration/contract_erc20.test.ts @@ -27,8 +27,9 @@ import { refillAccount, signAndSendContractMethodEIP1559, signAndSendContractMethodEIP2930, + closeOpenConnection, } from '../fixtures/system_test_utils'; -import { processAsync, toUpperCaseHex } from '../shared_fixtures/utils'; +import { toUpperCaseHex } from '../shared_fixtures/utils'; const initialSupply = BigInt('5000000000'); @@ -49,6 +50,10 @@ describe('contract', () => { }; }); + afterAll(async () => { + await closeOpenConnection(contract); + }); + it('should deploy the contract', async () => { const acc = await createTempAccount(); const sendOptionsLocal = { from: acc.address, gas: '10000000' }; @@ -61,6 +66,7 @@ describe('contract', () => { let contractDeployed: Contract; let pkAccount: { address: string; privateKey: string }; let mainAcc: { address: string; privateKey: string }; + const prepareForTransfer = async (value: string) => { const tempAccount = await createTempAccount(); await contractDeployed.methods.transfer(pkAccount.address, value).send(sendOptions); @@ -74,6 +80,11 @@ describe('contract', () => { sendOptions = { from: mainAcc.address, gas: '10000000' }; contractDeployed = await contract.deploy(deployOptions).send(sendOptions); }); + + afterAll(async () => { + await closeOpenConnection(contractDeployed); + }); + describe('methods', () => { it('should return the name', async () => { expect(await contractDeployed.methods.name().call()).toBe('Gold'); @@ -150,6 +161,7 @@ describe('contract', () => { expect(await catchErrorPromise).toBeDefined(); expect(catchError).toBe(true); }); + it('send tokens from the account that does not have tokens', async () => { const tempAccount = await createTempAccount(); const test = await createNewAccount({ @@ -186,7 +198,7 @@ describe('contract', () => { const value = BigInt(10); const tempAccount = await prepareForTransfer(value.toString()); await signAndSendContractMethod( - contract.provider, + contractDeployed.provider, contractDeployed.options.address as string, contractDeployed.methods.transfer(tempAccount.address, value), pkAccount.privateKey, @@ -291,22 +303,21 @@ describe('contract', () => { describeIf(isWs)('events', () => { it('should emit transfer event', async () => { const acc2 = await createTempAccount(); - await expect( - processAsync(async resolve => { - const event = contractDeployed.events.Transfer(); - event.on('data', data => { - resolve({ - from: toUpperCaseHex(data.returnValues.from as string), - to: toUpperCaseHex(data.returnValues.to as string), - value: data.returnValues.value, - }); + const event = contractDeployed.events.Transfer(); + const eventPromise = new Promise((resolve, reject) => { + event.on('data', data => { + resolve({ + from: toUpperCaseHex(data.returnValues.from as string), + to: toUpperCaseHex(data.returnValues.to as string), + value: data.returnValues.value, }); + }); + event.on('error', reject); + }); - await contractDeployed.methods - .transfer(acc2.address, '100') - .send(sendOptions); - }), - ).resolves.toEqual({ + await contractDeployed.methods.transfer(acc2.address, '100').send(sendOptions); + + await expect(eventPromise).resolves.toEqual({ from: toUpperCaseHex(sendOptions.from as string), to: toUpperCaseHex(acc2.address), value: BigInt(100), diff --git a/packages/web3-eth-contract/test/integration/contract_erc721.test.ts b/packages/web3-eth-contract/test/integration/contract_erc721.test.ts index 9463a636930..f979e1d396a 100644 --- a/packages/web3-eth-contract/test/integration/contract_erc721.test.ts +++ b/packages/web3-eth-contract/test/integration/contract_erc721.test.ts @@ -27,8 +27,9 @@ import { signAndSendContractMethodEIP2930, createNewAccount, refillAccount, + closeOpenConnection, } from '../fixtures/system_test_utils'; -import { processAsync, toUpperCaseHex } from '../shared_fixtures/utils'; +import { toUpperCaseHex } from '../shared_fixtures/utils'; describe('contract', () => { describe('erc721', () => { @@ -51,21 +52,25 @@ describe('contract', () => { sendOptions = { from: acc.address, gas: '10000000' }; }); + afterAll(async () => { + await closeOpenConnection(contract); + }); + it('should deploy the contract', async () => { await expect(contract.deploy(deployOptions).send(sendOptions)).resolves.toBeDefined(); }); describe('contract instance', () => { let acc: { address: string; privateKey: string }; - let acc2: { address: string; privateKey: string }; let pkAccount: { address: string; privateKey: string }; + beforeAll(async () => { acc = await createTempAccount(); pkAccount = await createNewAccount(); await refillAccount(acc.address, pkAccount.address, '20000000000000000'); }); + beforeEach(async () => { - acc2 = await createTempAccount(); sendOptions = { from: acc.address, gas: '10000000' }; contractDeployed = await contract.deploy(deployOptions).send(sendOptions); }); @@ -293,42 +298,47 @@ describe('contract', () => { describeIf(isWs)('events', () => { it('should emit transfer event', async () => { - await expect( - processAsync(async resolve => { - const event = contractDeployed.events.Transfer(); - event.on('data', data => { - resolve({ - from: toUpperCaseHex(data.returnValues.from as string), - to: toUpperCaseHex(data.returnValues.to as string), - tokenId: data.returnValues.tokenId, - }); + const acc2 = await createTempAccount(); + const event = contractDeployed.events.Transfer(); + + const eventPromise = new Promise((resolve, reject) => { + event.on('data', data => { + resolve({ + from: toUpperCaseHex(data.returnValues.from as string), + to: toUpperCaseHex(data.returnValues.to as string), + tokenId: data.returnValues.tokenId, }); + }); + event.on('error', reject); + }); + + const receipt = await contractDeployed.methods + .awardItem(acc2.address, 'http://my-nft-uri') + .send(sendOptions); - const receipt = await contractDeployed.methods - .awardItem(acc2.address, 'http://my-nft-uri') - .send(sendOptions); - - expect(receipt.events).toBeDefined(); - expect(receipt.events?.Transfer).toBeDefined(); - expect(receipt.events?.Transfer.event).toBe('Transfer'); - expect( - String(receipt.events?.Transfer.returnValues.from).toLowerCase(), - ).toBe('0x0000000000000000000000000000000000000000'); - expect( - String(receipt.events?.Transfer.returnValues[0]).toLowerCase(), - ).toBe('0x0000000000000000000000000000000000000000'); - expect( - String(receipt.events?.Transfer.returnValues.to).toLowerCase(), - ).toBe(acc2.address.toLowerCase()); - expect( - String(receipt.events?.Transfer.returnValues[1]).toLowerCase(), - ).toBe(acc2.address.toLowerCase()); - }), - ).resolves.toEqual({ + expect(receipt.events).toBeDefined(); + expect(receipt.events?.Transfer).toBeDefined(); + expect(receipt.events?.Transfer.event).toBe('Transfer'); + expect(String(receipt.events?.Transfer.returnValues.from).toLowerCase()).toBe( + '0x0000000000000000000000000000000000000000', + ); + expect(String(receipt.events?.Transfer.returnValues[0]).toLowerCase()).toBe( + '0x0000000000000000000000000000000000000000', + ); + expect(String(receipt.events?.Transfer.returnValues.to).toLowerCase()).toBe( + acc2.address.toLowerCase(), + ); + expect(String(receipt.events?.Transfer.returnValues[1]).toLowerCase()).toBe( + acc2.address.toLowerCase(), + ); + + await expect(eventPromise).resolves.toEqual({ from: '0x0000000000000000000000000000000000000000', to: toUpperCaseHex(acc2.address), tokenId: BigInt(0), }); + + event.removeAllListeners(); }); }); }); diff --git a/packages/web3-eth-contract/test/integration/contract_estimateGas_without_0x.test.ts b/packages/web3-eth-contract/test/integration/contract_estimateGas_without_0x.test.ts index d74a901e265..7212060bac5 100644 --- a/packages/web3-eth-contract/test/integration/contract_estimateGas_without_0x.test.ts +++ b/packages/web3-eth-contract/test/integration/contract_estimateGas_without_0x.test.ts @@ -17,7 +17,11 @@ along with web3.js. If not, see . import { ETH_DATA_FORMAT } from 'web3-types'; import { Contract } from '../../src'; -import { getSystemTestProvider, createTempAccount } from '../fixtures/system_test_utils'; +import { + getSystemTestProvider, + createTempAccount, + closeOpenConnection, +} from '../fixtures/system_test_utils'; describe('contract', () => { // Create a new contract object using the ABI and bytecode @@ -49,6 +53,10 @@ describe('contract', () => { acc = await createTempAccount(); }); + afterAll(async () => { + await closeOpenConnection(contract); + }); + it('should be able to add `data` input without `0x` prefix', async () => { contract = new Contract(abi, undefined, { provider: getSystemTestProvider(), diff --git a/packages/web3-eth-contract/test/integration/contract_events.test.ts b/packages/web3-eth-contract/test/integration/contract_events.test.ts index b84a875d173..0e13a68f366 100644 --- a/packages/web3-eth-contract/test/integration/contract_events.test.ts +++ b/packages/web3-eth-contract/test/integration/contract_events.test.ts @@ -15,10 +15,8 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ -import { EventLog } from 'web3-types'; -import { Contract } from '../../src'; +import { Contract, EventLog } from '../../src'; import { BasicAbi, BasicBytecode } from '../shared_fixtures/build/Basic'; -import { processAsync } from '../shared_fixtures/utils'; import { getSystemTestProvider, describeIf, @@ -26,6 +24,8 @@ import { itIf, isHttp, createTempAccount, + closeOpenConnection, + sendFewSampleTxs, } from '../fixtures/system_test_utils'; describe('contract', () => { @@ -34,12 +34,11 @@ describe('contract', () => { let deployOptions: Record; let sendOptions: Record; - beforeAll(() => { + beforeAll(async () => { contract = new Contract(BasicAbi, undefined, { provider: getSystemTestProvider(), }); - }); - beforeEach(async () => { + const acc = await createTempAccount(); deployOptions = { @@ -47,123 +46,127 @@ describe('contract', () => { arguments: [10, 'string init value'], }; - sendOptions = { from: acc.address, gas: '1000000' }; + sendOptions = { from: acc.address }; + }); + afterAll(async () => { + await closeOpenConnection(contract); + }); + + beforeEach(async () => { contractDeployed = await contract.deploy(deployOptions).send(sendOptions); }); - describe('events', () => { - itIf(isWs)('should trigger the "contract.events."', async () => { - // eslint-disable-next-line jest/no-standalone-expect - return expect( - processAsync(async (resolve, reject) => { - const event = contractDeployed.events.MultiValueEvent(); + describeIf(isWs)('events', () => { + it('should trigger the "contract.events."', async () => { + const event = contractDeployed.events.MultiValueEvent(); + + const eventPromise = new Promise((resolve, reject) => { + event.on('data', resolve); + event.on('error', reject); + }); - event.on('data', resolve); - event.on('error', reject); + await contractDeployed.methods + .firesMultiValueEvent('value', 12, true) + .send(sendOptions); - // trigger event - await contractDeployed.methods - .firesMultiValueEvent('value', 12, true) - .send(sendOptions); + await expect(eventPromise).resolves.toEqual( + expect.objectContaining({ + event: 'MultiValueEvent', }), - ).resolves.toEqual( + ); + + event.removeAllListeners(); + }); + + it('should trigger the "contract.events." for indexed parameters', async () => { + const event = contractDeployed.events.MultiValueIndexedEvent({ + filter: { val: 100 }, + }); + + const eventPromise = new Promise((resolve, reject) => { + event.on('data', resolve); + event.on('error', reject); + }); + + await contractDeployed.methods + .firesMultiValueIndexedEvent('value', 12, true) + .send(sendOptions); + await contractDeployed.methods + .firesMultiValueIndexedEvent('value', 100, true) + .send(sendOptions); + + await expect(eventPromise).resolves.toEqual( + expect.objectContaining({ + event: 'MultiValueIndexedEvent', + returnValues: expect.objectContaining({ + val: BigInt(100), + }), + }), + ); + + event.removeAllListeners(); + }); + + it('should trigger when "fromBlock" is passed to contract.events.', async () => { + const event = contractDeployed.events.MultiValueEvent({ + fromBlock: 'latest', + }); + + const eventPromise = new Promise((resolve, reject) => { + event.on('data', resolve); + event.on('error', reject); + }); + + await contractDeployed.methods + .firesMultiValueEvent('Event Value', 11, false) + .send(sendOptions); + + await expect(eventPromise).resolves.toEqual( expect.objectContaining({ event: 'MultiValueEvent', }), ); + + event.removeAllListeners(); }); - itIf(isWs)( - 'should trigger the "contract.events." for indexed parameters', - async () => { - const res = await processAsync(async (resolve, reject) => { - const event = contractDeployed.events.MultiValueIndexedEvent({ - filter: { val: 100 }, - }); - - event.on('data', resolve); - event.on('error', reject); - - // trigger event - await contractDeployed.methods - .firesMultiValueIndexedEvent('value', 12, true) - .send(sendOptions); - await contractDeployed.methods - .firesMultiValueIndexedEvent('value', 100, true) - .send(sendOptions); + it('should fetch past events when "fromBlock" is passed to contract.events.', async () => { + const eventValues = [11, 12, 13, 14]; + const event = contractDeployed.events.MultiValueEvent({ + fromBlock: 'earliest', + }); + + const eventPromise = new Promise((resolve, reject) => { + const pastEvents: EventLog[] = []; + event.on('data', d => { + pastEvents.push(d); + if (pastEvents.length === eventValues.length) { + resolve(pastEvents); + } }); - // eslint-disable-next-line jest/no-standalone-expect - expect((res as any)?.event).toBe('MultiValueIndexedEvent'); - // eslint-disable-next-line jest/no-standalone-expect - expect((res as any)?.returnValues.val).toBe(BigInt(100)); - }, - ); - - itIf(isWs)( - 'should trigger when "fromBlock" is passed to contract.events.', - async () => { - // eslint-disable-next-line jest/no-standalone-expect - return expect( - processAsync(async (resolve, reject) => { - const event = contractDeployed.events.MultiValueEvent({ - fromBlock: 'latest', - }); - - event.on('data', resolve); - event.on('error', reject); - - // trigger event - await contractDeployed.methods - .firesMultiValueEvent('Event Value', 11, false) - .send(sendOptions); - }), - ).resolves.toEqual( - expect.objectContaining({ - event: 'MultiValueEvent', - }), - ); - }, - ); - - itIf(isWs)( - 'should fetch past events when "fromBlock" is passed to contract.events.', - async () => { - const eventValues = [11, 12, 13, 14]; - // eslint-disable-next-line jest/no-standalone-expect - return expect( - processAsync(async resolve => { - // trigger multiple events - for (const eventValue of eventValues) { - // Wait for every transaction, before firing the next one, to prevent a possible nonce duplication. - // eslint-disable-next-line no-await-in-loop - await contractDeployed.methods - .firesMultiValueEvent('Event Value', eventValue, false) - .send(sendOptions); - } - - const event = contractDeployed.events.MultiValueEvent({ - fromBlock: 'earliest', - }); - - const pastEvents: EventLog[] = []; - event.on('data', d => { - pastEvents.push(d); - if (pastEvents.length === eventValues.length) { - resolve(pastEvents); - } - }); - }), - ).resolves.toEqual( - expect.arrayContaining([ - expect.objectContaining({ event: 'MultiValueEvent' }), - expect.objectContaining({ event: 'MultiValueEvent' }), - expect.objectContaining({ event: 'MultiValueEvent' }), - expect.objectContaining({ event: 'MultiValueEvent' }), - ]), - ); - }, - ); + event.on('error', reject); + }); + + for (const eventValue of eventValues) { + // Wait for every transaction, before firing the next one, to prevent a possible nonce duplication. + // eslint-disable-next-line no-await-in-loop + await contractDeployed.methods + .firesMultiValueEvent('Event Value', eventValue, false) + .send(sendOptions); + } + + await expect(eventPromise).resolves.toEqual( + expect.arrayContaining([ + expect.objectContaining({ event: 'MultiValueEvent' }), + expect.objectContaining({ event: 'MultiValueEvent' }), + expect.objectContaining({ event: 'MultiValueEvent' }), + expect.objectContaining({ event: 'MultiValueEvent' }), + ]), + ); + + event.removeAllListeners(); + }); }); describe('events subscription with HTTP', () => { @@ -186,7 +189,6 @@ describe('contract', () => { }); describeIf(isWs)('getPastEvents', () => { - // TODO: Debug why this tests is hanging the websocket it('should return all past events using earliest and latest options', async () => { await contractDeployed.methods .firesMultiValueEvent('New Greeting 1', 11, true) @@ -195,6 +197,8 @@ describe('contract', () => { .firesMultiValueEvent('New Greeting 2', 12, true) .send(sendOptions); + await sendFewSampleTxs(2); + expect( await contractDeployed.getPastEvents('MultiValueEvent', { fromBlock: 'earliest', @@ -202,6 +206,7 @@ describe('contract', () => { }), ).toHaveLength(2); }); + it('should return all past events using number options', async () => { await contractDeployed.methods .firesMultiValueEvent('New Greeting 1', 11, true) @@ -210,6 +215,8 @@ describe('contract', () => { .firesMultiValueEvent('New Greeting 2', 12, true) .send(sendOptions); + await sendFewSampleTxs(2); + expect( await contractDeployed.getPastEvents('MultiValueEvent', { fromBlock: 0, @@ -217,6 +224,7 @@ describe('contract', () => { }), ).toHaveLength(2); }); + it('should return all past events using string options', async () => { await contractDeployed.methods .firesMultiValueEvent('New Greeting 1', 11, true) @@ -225,6 +233,8 @@ describe('contract', () => { .firesMultiValueEvent('New Greeting 2', 12, true) .send(sendOptions); + await sendFewSampleTxs(2); + expect( await contractDeployed.getPastEvents('MultiValueEvent', { fromBlock: '0', @@ -232,6 +242,7 @@ describe('contract', () => { }), ).toHaveLength(2); }); + it('should return all past events using bigint options', async () => { await contractDeployed.methods .firesMultiValueEvent('New Greeting 1', 11, true) @@ -240,6 +251,8 @@ describe('contract', () => { .firesMultiValueEvent('New Greeting 2', 12, true) .send(sendOptions); + await sendFewSampleTxs(2); + expect( await contractDeployed.getPastEvents('MultiValueEvent', { fromBlock: BigInt(0), @@ -251,45 +264,43 @@ describe('contract', () => { describeIf(isWs)('allEvents', () => { it('should sub and get event using earliest options with allEvents()', async () => { - // eslint-disable-next-line jest/no-standalone-expect - return expect( - processAsync(async (resolve, reject) => { - const event = contractDeployed.events.allEvents({ fromBlock: 'earliest' }); + const event = contractDeployed.events.allEvents({ fromBlock: 'earliest' }); - event.on('data', resolve); - event.on('error', reject); + const eventPromise = new Promise((resolve, reject) => { + event.on('data', resolve); + event.on('error', reject); + }); - // trigger event - await contractDeployed.methods - .firesMultiValueEvent('val test', 12, true) - .send(sendOptions); - }), - ).resolves.toEqual( + await contractDeployed.methods + .firesMultiValueEvent('val test', 12, true) + .send(sendOptions); + + await expect(eventPromise).resolves.toEqual( expect.objectContaining({ event: 'MultiValueEvent', }), ); + + event.removeAllListeners(); }); it('should sub allEvents()', async () => { - // eslint-disable-next-line jest/no-standalone-expect - return expect( - processAsync(async (resolve, reject) => { - const event = contractDeployed.events.allEvents(); + const event = contractDeployed.events.allEvents(); - event.on('data', resolve); - event.on('error', reject); + const eventPromise = new Promise((resolve, reject) => { + event.on('data', resolve); + event.on('error', reject); + }); - // trigger event - await contractDeployed.methods - .firesMultiValueEvent('Pak1', 12, true) - .send(sendOptions); - }), - ).resolves.toEqual( + await contractDeployed.methods.firesMultiValueEvent('Pak1', 12, true).send(sendOptions); + + await expect(eventPromise).resolves.toEqual( expect.objectContaining({ event: 'MultiValueEvent', }), ); + + event.removeAllListeners(); }); }); }); diff --git a/packages/web3-eth-contract/test/integration/contract_filter_events.test.ts b/packages/web3-eth-contract/test/integration/contract_filter_events.test.ts index 338cd448c12..000a305eb72 100644 --- a/packages/web3-eth-contract/test/integration/contract_filter_events.test.ts +++ b/packages/web3-eth-contract/test/integration/contract_filter_events.test.ts @@ -24,6 +24,7 @@ import { getSystemTestProvider, createTempAccount, createNewAccount, + closeOpenConnection, } from '../fixtures/system_test_utils'; const initialSupply = BigInt('5000000000'); @@ -60,6 +61,10 @@ describe('contract getPastEvent filter', () => { await contractDeployed.methods.transfer(toAcc3.address, value).send(sendOptions); }); + afterAll(async () => { + await closeOpenConnection(contract); + }); + it('should filter one event by address with event name and filter param', async () => { const res: EventLog[] = (await contractDeployed.getPastEvents('Transfer', { fromBlock: 'earliest', @@ -155,6 +160,7 @@ describe('contract getPastEvent filter', () => { ); }); }); + describe('basic', () => { let contract: Contract; let contractDeployed: Contract; @@ -188,6 +194,10 @@ describe('contract getPastEvent filter', () => { .send(sendOptions); }); + afterAll(async () => { + await closeOpenConnection(contract); + }); + it('should filter one event by address with event name and filter param', async () => { const res: EventLog[] = (await contractDeployed.getPastEvents( 'MultiValueIndexedEvent', 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 152c3feec8a..7048fe121d6 100644 --- a/packages/web3-eth-contract/test/integration/contract_methods.test.ts +++ b/packages/web3-eth-contract/test/integration/contract_methods.test.ts @@ -22,6 +22,7 @@ import { createTempAccount, getSystemTestBackend, BACKEND, + closeOpenConnection, } from '../fixtures/system_test_utils'; describe('contract', () => { @@ -47,6 +48,10 @@ describe('contract', () => { contractDeployed = await contract.deploy(deployOptions).send(sendOptions); }); + afterAll(async () => { + await closeOpenConnection(contract); + }); + describe('methods', () => { describe('call', () => { it('should retrieve the values', async () => { @@ -72,6 +77,8 @@ describe('contract', () => { .send(); const res = await deployedTempContract.methods.getStringValue().call(); expect(res).toBe('string init value'); + + await closeOpenConnection(tempContract); }); describe('revert handling', () => { @@ -191,6 +198,8 @@ describe('contract', () => { await deployedTempContract.methods.setValues(10, 'TEST', true).send(); expect(await deployedTempContract.methods.getStringValue().call()).toBe('TEST'); + + await closeOpenConnection(tempContract); }); it('should returns errors on reverts', async () => { diff --git a/packages/web3-eth-contract/test/integration/contract_methods_errors.test.ts b/packages/web3-eth-contract/test/integration/contract_methods_errors.test.ts index 7c07ee5af8d..276bb23b992 100644 --- a/packages/web3-eth-contract/test/integration/contract_methods_errors.test.ts +++ b/packages/web3-eth-contract/test/integration/contract_methods_errors.test.ts @@ -24,6 +24,7 @@ import { getSystemTestBackend, describeIf, BACKEND, + closeOpenConnection, } from '../fixtures/system_test_utils'; describe('contract errors', () => { @@ -47,8 +48,10 @@ describe('contract errors', () => { const sendOptionsLocal = { from: acc.address, gas: '10000000' }; deployedContract = await contract.deploy(deployOptions).send(sendOptionsLocal); + }); - contract.setProvider(getSystemTestProvider()); + afterAll(async () => { + await closeOpenConnection(contract); }); describeIf(getSystemTestBackend() === BACKEND.GETH)('Test EIP-838 Error Codes', () => { diff --git a/packages/web3-eth-contract/test/integration/contract_negative_numbers.test.ts b/packages/web3-eth-contract/test/integration/contract_negative_numbers.test.ts index bf9283d5a4f..9e29824c2c6 100644 --- a/packages/web3-eth-contract/test/integration/contract_negative_numbers.test.ts +++ b/packages/web3-eth-contract/test/integration/contract_negative_numbers.test.ts @@ -15,7 +15,11 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ import Contract from '../../src'; -import { createTempAccount, getSystemTestProvider } from '../fixtures/system_test_utils'; +import { + closeOpenConnection, + createTempAccount, + getSystemTestProvider, +} from '../fixtures/system_test_utils'; import { NegativeNumbersAbi, NegativeNumbersBytecode, @@ -39,14 +43,15 @@ describe('Contract - NegativeNumbers.sol', () => { data: NegativeNumbersBytecode, arguments: [storedNegativeNumber], }; - sendOptions = { - from: account.address, - gas: '1000000', - }; + sendOptions = { from: account.address }; contractDeployed = await contract.deploy(deployOptions).send(sendOptions); }); + afterAll(async () => { + await closeOpenConnection(contract); + }); + it('should retrieve storedNegativeNumber', async () => { const response = await contractDeployed.methods.storedNegativeNumber().call(); expect(response).toBe(BigInt(storedNegativeNumber)); diff --git a/packages/web3-eth-contract/test/integration/contract_simple_overloaded.test.ts b/packages/web3-eth-contract/test/integration/contract_simple_overloaded.test.ts index 0e786b77428..fd71aff487a 100644 --- a/packages/web3-eth-contract/test/integration/contract_simple_overloaded.test.ts +++ b/packages/web3-eth-contract/test/integration/contract_simple_overloaded.test.ts @@ -16,7 +16,11 @@ along with web3.js. If not, see . */ import Contract from '../../src'; import { SimpleOverloadedAbi, SimpleOverloadedBytecode } from '../fixtures/SimpleOverloaded'; -import { createTempAccount, getSystemTestProvider } from '../fixtures/system_test_utils'; +import { + closeOpenConnection, + createTempAccount, + getSystemTestProvider, +} from '../fixtures/system_test_utils'; describe('SimpleOverloaded', () => { let contract: Contract; @@ -32,7 +36,11 @@ describe('SimpleOverloaded', () => { .deploy({ data: SimpleOverloadedBytecode, }) - .send({ from: mainAcc.address, gas: '10000000' }); + .send({ from: mainAcc.address }); + }); + + afterAll(async () => { + await closeOpenConnection(contract); }); it('should call getSecret with no args', async () => { 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 821101ca225..cb24ad22fca 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 @@ -20,7 +20,11 @@ import Web3 from 'web3'; // eslint-disable-next-line import/no-extraneous-dependencies import { Web3Account } from 'web3-eth-accounts'; import { GreeterBytecode, GreeterAbi } from '../../shared_fixtures/build/Greeter'; -import { getSystemTestProvider, createLocalAccount } from '../../fixtures/system_test_utils'; +import { + getSystemTestProvider, + createLocalAccount, + closeOpenConnection, +} from '../../fixtures/system_test_utils'; import { Contract } from '../../../src'; describe('contract', () => { @@ -31,13 +35,20 @@ describe('contract', () => { let localAccount: Web3Account; let web3: Web3; - beforeEach(async () => { + beforeAll(async () => { web3 = new Web3(getSystemTestProvider()); contract = new web3.eth.Contract(GreeterAbi) as unknown as Contract; deployOptions = { data: GreeterBytecode, arguments: ['My Greeting'], }; + }); + + afterAll(async () => { + await closeOpenConnection(web3); + }); + + beforeEach(async () => { localAccount = await createLocalAccount(web3); sendOptions = { from: localAccount.address, diff --git a/packages/web3-eth-contract/test/integration/local_account/contract_erc20.test.ts b/packages/web3-eth-contract/test/integration/local_account/contract_erc20.test.ts index edff03fe598..35ebc29cc46 100644 --- a/packages/web3-eth-contract/test/integration/local_account/contract_erc20.test.ts +++ b/packages/web3-eth-contract/test/integration/local_account/contract_erc20.test.ts @@ -21,7 +21,11 @@ import Web3 from 'web3'; import { Web3Account } from 'web3-eth-accounts'; import { Contract } from '../../../src'; import { ERC20TokenAbi, ERC20TokenBytecode } from '../../shared_fixtures/build/ERC20Token'; -import { getSystemTestProvider, createLocalAccount } from '../../fixtures/system_test_utils'; +import { + getSystemTestProvider, + createLocalAccount, + closeOpenConnection, +} from '../../fixtures/system_test_utils'; const initialSupply = BigInt('5000000000'); @@ -53,6 +57,10 @@ describe('contract', () => { contractDeployed = await contract.deploy(deployOptions).send(sendOptions); }); + afterAll(async () => { + await closeOpenConnection(web3); + }); + it('should deploy the contract', () => { expect(contractDeployed.options.address).toBeDefined(); }); diff --git a/packages/web3-eth-contract/test/integration/local_account/contract_erc721.test.ts b/packages/web3-eth-contract/test/integration/local_account/contract_erc721.test.ts index d9226c580f1..4ea801ee686 100644 --- a/packages/web3-eth-contract/test/integration/local_account/contract_erc721.test.ts +++ b/packages/web3-eth-contract/test/integration/local_account/contract_erc721.test.ts @@ -21,7 +21,11 @@ import Web3 from 'web3'; import { Web3Account } from 'web3-eth-accounts'; import { Contract } from '../../../src'; import { ERC721TokenAbi, ERC721TokenBytecode } from '../../shared_fixtures/build/ERC721Token'; -import { getSystemTestProvider, createLocalAccount } from '../../fixtures/system_test_utils'; +import { + getSystemTestProvider, + createLocalAccount, + closeOpenConnection, +} from '../../fixtures/system_test_utils'; import { toUpperCaseHex } from '../../shared_fixtures/utils'; describe('contract', () => { @@ -32,6 +36,7 @@ describe('contract', () => { let localAccount: Web3Account; let web3: Web3; let contractDeployed: Contract; + beforeAll(async () => { web3 = new Web3(getSystemTestProvider()); localAccount = await createLocalAccount(web3); @@ -46,11 +51,13 @@ describe('contract', () => { sendOptions = { from: localAccount.address, - gas: '1000000', }; - contractDeployed = await contract - .deploy(deployOptions) - .send({ ...sendOptions, gas: '3000000' }); + contractDeployed = await contract.deploy(deployOptions).send({ ...sendOptions }); + }); + + afterAll(async () => { + await closeOpenConnection(web3); + await closeOpenConnection(contract); }); it('should deploy the contract', () => { 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 0c905e8ece2..5593e905b3a 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 @@ -23,7 +23,11 @@ import { utf8ToHex } from 'web3-utils'; import { EventLog } from 'web3-types'; import { Contract } from '../../../src'; import { ERC721TokenAbi, ERC721TokenBytecode } from '../../shared_fixtures/build/ERC721Token'; -import { getSystemTestProvider, createLocalAccount } from '../../fixtures/system_test_utils'; +import { + getSystemTestProvider, + createLocalAccount, + closeOpenConnection, +} from '../../fixtures/system_test_utils'; import { toUpperCaseHex } from '../../shared_fixtures/utils'; describe('contract ERC721 overloaded functions', () => { @@ -55,6 +59,10 @@ describe('contract ERC721 overloaded functions', () => { .send({ ...sendOptions, gas: '3000000' }); }); + afterAll(async () => { + await closeOpenConnection(web3); + }); + it('transferFrom with 4 arguments', async () => { const tempAccount = await createLocalAccount(web3); const toAccount = await createLocalAccount(web3); diff --git a/scripts/system_tests_utils.ts b/scripts/system_tests_utils.ts index e634b98a35b..db460e8229c 100644 --- a/scripts/system_tests_utils.ts +++ b/scripts/system_tests_utils.ts @@ -165,7 +165,8 @@ export const closeOpenConnection = async (web3Context: Web3Context) => { (web3Context.provider as unknown as Web3BaseProvider).disconnect(); await new Promise(resolve => { - setTimeout(resolve, 1000); + const timer = setTimeout(resolve, 1); + timer.unref(); }); } }; @@ -250,8 +251,9 @@ export const createNewAccount = async (config?: { const url = getSystemTestProviderUrl(); const web3 = new Web3(url); web3.registerPlugin(new HardhatPlugin()); + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call await web3.hardhat.impersonateAccount(acc.address); - // await impersonateAccount(acc.address); + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call await web3.hardhat.setBalance(acc.address, web3.utils.toHex('100000000')); await closeOpenConnection(web3); } else { @@ -275,6 +277,7 @@ export const createNewAccount = async (config?: { const url = getSystemTestProviderUrl(); const web3 = new Web3(url); web3.registerPlugin(new HardhatPlugin()); + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call await web3.hardhat.setBalance(acc.address, web3.utils.toHex('100000000')); await closeOpenConnection(web3); } else { @@ -365,7 +368,9 @@ export const signTxAndSendEIP1559 = async ( from: acc.address, }; - return web3.eth.sendTransaction(txObj, undefined, { checkRevertBeforeSending: false }); + return web3.eth.sendTransaction(txObj, undefined, { + checkRevertBeforeSending: false, + }); }; export const signTxAndSendEIP2930 = async ( @@ -383,7 +388,9 @@ export const signTxAndSendEIP2930 = async ( from: acc.address, }; - return web3.eth.sendTransaction(txObj, undefined, { checkRevertBeforeSending: false }); + return web3.eth.sendTransaction(txObj, undefined, { + checkRevertBeforeSending: false, + }); }; export const signAndSendContractMethodEIP1559 = async ( @@ -418,7 +425,7 @@ export const signAndSendContractMethodEIP2930 = async ( export const createLocalAccount = async (web3: Web3) => { const account = web3.eth.accounts.create(); - await refillAccount((await createTempAccount()).address, account.address, '10000000000000000'); + await refillAccount((await createTempAccount()).address, account.address, '100000000000000000'); web3.eth.accounts.wallet.add(account); return account; }; @@ -515,8 +522,8 @@ export const waitForCondition = async ( logicFunc: () => Promise | void, maxIterations = 10, // 10 times duration = 8000, // check after each 8 seconds -): Promise => { - return new Promise((resolve, reject) => { +): Promise => + new Promise((resolve, reject) => { let iterations = 0; // eslint-disable-next-line @typescript-eslint/no-misused-promises const interval = setInterval(async () => { @@ -540,4 +547,3 @@ export const waitForCondition = async ( } }, duration); }); -}; From 2011192f92218aa1572f2c711f38866eba92f844 Mon Sep 17 00:00:00 2001 From: Kris <605420+krzysu@users.noreply.github.com> Date: Wed, 13 Nov 2024 10:25:57 +0100 Subject: [PATCH 21/49] fix: export Web3Account, Wallet and signature related types (#7374) --- CHANGELOG.md | 6 ++++ packages/web3-eth-accounts/CHANGELOG.md | 4 +++ packages/web3-eth-accounts/src/account.ts | 11 +++--- packages/web3-eth-accounts/src/types.ts | 38 +++++---------------- packages/web3-types/CHANGELOG.md | 4 +++ packages/web3-types/src/web3_base_wallet.ts | 35 ++++++++++--------- packages/web3/CHANGELOG.md | 6 ++++ packages/web3/src/types.ts | 2 ++ packages/web3/test/unit/accounts.test.ts | 3 +- 9 files changed, 55 insertions(+), 54 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91d8d858ed7..6c97c573755 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2803,3 +2803,9 @@ If there are any bugs, improvements, optimizations or any new feature proposal f - Fix Contract methods input param type any[] (#7340) ## [Unreleased] + +### Fixed + +#### web3 + +- Export Web3Account, Wallet and signature related types. (#7374) diff --git a/packages/web3-eth-accounts/CHANGELOG.md b/packages/web3-eth-accounts/CHANGELOG.md index 939bd836ce8..e707999a1c2 100644 --- a/packages/web3-eth-accounts/CHANGELOG.md +++ b/packages/web3-eth-accounts/CHANGELOG.md @@ -190,3 +190,7 @@ Documentation: - `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] + +### Removed + +- Move signature related types to web3-types. Re-export them for backwards compatibility. (#7374) diff --git a/packages/web3-eth-accounts/src/account.ts b/packages/web3-eth-accounts/src/account.ts index 511ebcc92d2..9faed9ceaed 100644 --- a/packages/web3-eth-accounts/src/account.ts +++ b/packages/web3-eth-accounts/src/account.ts @@ -69,6 +69,9 @@ import { KeyStore, PBKDF2SHA256Params, ScryptParams, + SignatureObject, + SignResult, + SignTransactionResult, Transaction, } from 'web3-types'; import { @@ -90,13 +93,7 @@ import { isHexStrict, isNullish, isString, validator } from 'web3-validator'; import { secp256k1 } from './tx/constants.js'; import { keyStoreSchema } from './schemas.js'; import { TransactionFactory } from './tx/transactionFactory.js'; -import type { - SignatureObject, - SignTransactionResult, - TypedTransaction, - Web3Account, - SignResult, -} from './types.js'; +import type { TypedTransaction, Web3Account } from './types.js'; /** * Get the private key Uint8Array after the validation. diff --git a/packages/web3-eth-accounts/src/types.ts b/packages/web3-eth-accounts/src/types.ts index ed45ad94ffb..54a7aba7b78 100644 --- a/packages/web3-eth-accounts/src/types.ts +++ b/packages/web3-eth-accounts/src/types.ts @@ -15,38 +15,16 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ -import { Web3BaseWalletAccount, HexString } from 'web3-types'; -import { FeeMarketEIP1559TxData, AccessListEIP2930TxData, TxData } from './tx/types.js'; +import { + HexString, + SignatureObject, + SignResult, + SignTransactionResult, + Web3BaseWalletAccount, +} from 'web3-types'; import { AccessListEIP2930Transaction, FeeMarketEIP1559Transaction, Transaction } from './tx'; -export type SignatureObject = { - messageHash: string; - r: string; - s: string; - v: string; -}; - -export type SignTransactionResult = SignatureObject & { - rawTransaction: string; - transactionHash: string; -}; - -export type SignTransactionFunction = ( - transaction: - | TxData - | AccessListEIP2930TxData - | FeeMarketEIP1559TxData - | Record, -) => SignTransactionResult; - -export type SignResult = SignatureObject & { - message?: string; - signature: string; -}; - -export type SignFunction = (data: string, privateKey: string) => SignResult; - -// https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition +export { SignatureObject, SignResult, SignTransactionResult }; export interface Web3Account extends Web3BaseWalletAccount { address: HexString; diff --git a/packages/web3-types/CHANGELOG.md b/packages/web3-types/CHANGELOG.md index 4158022da52..c78df9f3265 100644 --- a/packages/web3-types/CHANGELOG.md +++ b/packages/web3-types/CHANGELOG.md @@ -221,3 +221,7 @@ Documentation: - `FilterParams` type added (#7353) ## [Unreleased] + +#### Added + +- Add signature related types. (#7374) diff --git a/packages/web3-types/src/web3_base_wallet.ts b/packages/web3-types/src/web3_base_wallet.ts index 484e8072603..153a34450a1 100644 --- a/packages/web3-types/src/web3_base_wallet.ts +++ b/packages/web3-types/src/web3_base_wallet.ts @@ -60,26 +60,29 @@ export type KeyStore = { address: string; }; +export type SignatureObject = { + messageHash: string; + r: string; + s: string; + v: string; +}; + +export type SignTransactionResult = SignatureObject & { + rawTransaction: string; + transactionHash: string; +}; + +export type SignResult = SignatureObject & { + message?: string; + signature: string; +}; + export interface Web3BaseWalletAccount { [key: string]: unknown; readonly address: string; readonly privateKey: string; - readonly signTransaction: (tx: Transaction) => Promise<{ - readonly messageHash: HexString; - readonly r: HexString; - readonly s: HexString; - readonly v: HexString; - readonly rawTransaction: HexString; - readonly transactionHash: HexString; - }>; - readonly sign: (data: Record | string) => { - readonly messageHash: HexString; - readonly r: HexString; - readonly s: HexString; - readonly v: HexString; - readonly message?: string; - readonly signature: HexString; - }; + readonly signTransaction: (tx: Transaction) => Promise; + readonly sign: (data: Record | string) => SignResult; readonly encrypt: (password: string, options?: Record) => Promise; } diff --git a/packages/web3/CHANGELOG.md b/packages/web3/CHANGELOG.md index f3ec9b9679e..b1f440e0074 100644 --- a/packages/web3/CHANGELOG.md +++ b/packages/web3/CHANGELOG.md @@ -561,3 +561,9 @@ Documentation: - Fix Contract methods input param type any[] (#7340) ## [Unreleased] + +### Fixed + +#### web3 + +- Export Web3Account, Wallet and signature related types. (#7374) diff --git a/packages/web3/src/types.ts b/packages/web3/src/types.ts index 3b87896789c..341e017015c 100644 --- a/packages/web3/src/types.ts +++ b/packages/web3/src/types.ts @@ -42,6 +42,8 @@ import { Net } from 'web3-net'; import { Iban } from 'web3-eth-iban'; import { Personal } from 'web3-eth-personal'; +export type { Web3Account, Wallet } from 'web3-eth-accounts'; + /** * The Ethereum interface for main web3 object. It provides extra methods in addition to `web3-eth` interface. * diff --git a/packages/web3/test/unit/accounts.test.ts b/packages/web3/test/unit/accounts.test.ts index 9cc2618d24b..2bd75cbe90e 100644 --- a/packages/web3/test/unit/accounts.test.ts +++ b/packages/web3/test/unit/accounts.test.ts @@ -17,7 +17,8 @@ along with web3.js. If not, see . import * as eth from 'web3-eth'; import * as ethAccounts from 'web3-eth-accounts'; -import { SignTransactionResult, Web3Account } from 'web3-eth-accounts'; +import { Web3Account } from 'web3-eth-accounts'; +import type { SignTransactionResult } from 'web3-types'; import { Web3EthInterface } from '../../src/types'; import { Web3 } from '../../src'; From 0915cf4e426feb06618d6e264239bf8f67b3c278 Mon Sep 17 00:00:00 2001 From: Kris <605420+krzysu@users.noreply.github.com> Date: Wed, 13 Nov 2024 21:39:04 +0100 Subject: [PATCH 22/49] fix: CI workflow cache issues (#7384) --- .github/workflows/build.yml | 435 +++++++++--------- .../test/integration/resolver.test.ts | 2 +- 2 files changed, 208 insertions(+), 229 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b8c0f6647fd..81ce725b842 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -28,136 +28,107 @@ jobs: - run: yarn build:cjs - uses: actions/cache/save@v4 with: - path: ./ - key: web3-${{ matrix.node }}-${{github.sha}} + path: ./ + key: web3-${{ matrix.node }}-${{ github.sha }} build-esm: name: Build ESM needs: build runs-on: ubuntu-latest steps: - - uses: actions/setup-node@v4 - with: - node-version: 18 - - uses: actions/cache/restore@v4 - with: - path: ./ - key: web3-18-${{github.sha}} - - run: yarn build:esm + - uses: actions/setup-node@v4 + with: + node-version: 18 + - uses: actions/cache/restore@v4 + with: + path: ./ + key: web3-18-${{ github.sha }} + - run: yarn build:esm + build-types: name: Build Types needs: build runs-on: ubuntu-latest steps: - - uses: actions/setup-node@v4 - with: - node-version: 18 - - uses: actions/cache/restore@v4 - with: - path: ./ - key: web3-18-${{github.sha}} - - run: yarn build:types + - uses: actions/setup-node@v4 + with: + node-version: 18 + - uses: actions/cache/restore@v4 + with: + path: ./ + key: web3-18-${{ github.sha }} + - run: yarn build:types + lint: name: Lint needs: build runs-on: ubuntu-latest steps: - - uses: actions/setup-node@v4 - with: - node-version: 18 - - 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 + - uses: actions/setup-node@v4 + with: + node-version: 18 + - uses: actions/cache/restore@v4 + with: + path: ./ + key: web3-18-${{ github.sha }} + - run: npx ts-node scripts/init.ts + - uses: actions/cache@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-${{ github.ref_name }} + - run: yarn lint build-web: name: Build Web needs: build runs-on: ubuntu-latest steps: - - uses: actions/setup-node@v4 - with: - node-version: 18 - - 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@v4 - with: - path: packages/web3/dist/4.x.json - key: web3-bundle-stats-4x-${{github.event.pull_request.base.sha}} - - run: yarn build:web:analyze - env: - STATS_FILE: ${{ github.ref_name }}.json - - name: Compare bundle stats - uses: github/webpack-bundlesize-compare-action@v1.8.2 - continue-on-error: true - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - 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@v4 - if: github.event_name == 'push' && github.ref == 'refs/heads/4.x' - with: - path: packages/web3/dist/${{ github.ref_name }}.json - key: web3-bundle-stats-4x-${{github.sha}} - + - uses: actions/setup-node@v4 + with: + node-version: 18 + - 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@v4 + with: + path: packages/web3/dist/4.x.json + key: web3-bundle-stats-4x-${{ github.event.pull_request.base.sha }} + - run: yarn build:web:analyze + env: + STATS_FILE: ${{ github.ref_name }}.json + - name: Compare bundle stats + uses: github/webpack-bundlesize-compare-action@v1.8.2 + continue-on-error: true + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + 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@v4 + if: github.event_name == 'push' && github.ref == 'refs/heads/4.x' + with: + path: packages/web3/dist/${{ github.ref_name }}.json + key: web3-bundle-stats-4x-${{ github.sha }} unit: name: Unit Tests @@ -173,8 +144,8 @@ jobs: node-version: ${{ matrix.node }} - uses: actions/cache/restore@v4 with: - path: ./ - key: web3-${{ matrix.node }}-${{github.sha}} + path: ./ + key: web3-${{ matrix.node }}-${{ github.sha }} - run: yarn test:unit continue-on-error: ${{ matrix.node == '20.17.0' }} - name: Upload coverage to Codecov @@ -189,18 +160,18 @@ jobs: needs: build runs-on: ubuntu-latest strategy: - fail-fast: false + fail-fast: false steps: - - uses: actions/setup-node@v3 - with: - node-version: 18 - - uses: actions/cache/restore@v4 - with: - path: ./ - key: web3-18-${{github.sha}} - - run: npx hardhat node & - - run: yarn test:e2e:hardhat:http - shell: bash + - uses: actions/setup-node@v3 + with: + node-version: 18 + - uses: actions/cache/restore@v4 + with: + path: ./ + key: web3-18-${{ github.sha }} + - run: npx hardhat node & + - run: yarn test:e2e:hardhat:http + shell: bash e2e-geth: name: Integration # (geth with HTTP, IPC & WS) @@ -212,44 +183,44 @@ jobs: strategy: fail-fast: false matrix: - mode: [ 'ipc', 'ws', 'http' ] + mode: ['ipc', 'ws', 'http'] steps: - - uses: actions/setup-node@v4 - with: - node-version: 18 - - uses: actions/cache/restore@v4 - with: - path: ./ - key: web3-18-${{github.sha}} - - run: yarn test:e2e:geth:${{ matrix.mode }} - shell: bash + - uses: actions/setup-node@v4 + with: + node-version: 18 + - uses: actions/cache/restore@v4 + with: + path: ./ + key: web3-18-${{ github.sha }} + - run: yarn test:e2e:geth:${{ matrix.mode }} + shell: bash e2e-browsers: name: End-to-End hardhat:ws needs: build runs-on: ubuntu-latest strategy: - fail-fast: false - matrix: - browser: ['electron', 'chrome', 'firefox'] + fail-fast: false + matrix: + browser: ['electron', 'chrome', 'firefox'] steps: - - uses: actions/setup-node@v3 - with: - node-version: 18 - - uses: browser-actions/setup-firefox@latest - if: matrix.browser == 'firefox' - - uses: actions/cache/restore@v4 - with: - path: ./ - key: web3-18-${{github.sha}} - - run: npx hardhat node & - - run: npm install --no-package-lock --no-save --force cypress - - name: Cypress run - uses: cypress-io/github-action@v4 - with: - install: false - command: yarn test:e2e:hardhat:ws:${{ matrix.browser }} - cache-key: node-v18-on-${{ matrix.browser }}-hash-${{ hashFiles('yarn.lock') }} + - uses: actions/setup-node@v3 + with: + node-version: 18 + - uses: browser-actions/setup-firefox@latest + if: matrix.browser == 'firefox' + - uses: actions/cache/restore@v4 + with: + path: ./ + key: web3-18-${{ github.sha }} + - run: npx hardhat node & + - run: npm install --no-package-lock --no-save --force cypress + - name: Cypress run + uses: cypress-io/github-action@v4 + with: + install: false + command: yarn test:e2e:hardhat:ws:${{ matrix.browser }} + cache-key: node-v18-on-${{ matrix.browser }}-hash-${{ hashFiles('yarn.lock') }} deploy-docs: name: Docs CloudFlare Deploy @@ -259,85 +230,93 @@ jobs: contents: read deployments: write steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - cache: yarn - node-version: '18' - - uses: actions/cache/restore@v4 - with: - path: ./ - key: web3-18-${{github.sha}} - - run: yarn install --ignore-scripts - - run: yarn build:cjs - - run: yarn run build:docs - - name: Publish to Cloudflare Pages - uses: cloudflare/pages-action@v1 - with: - apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} - accountId: 2238a825c5aca59233eab1f221f7aefb - projectName: web3-js-docs - directory: ./docs/build - gitHubToken: ${{ secrets.GITHUB_TOKEN }} + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + cache: yarn + node-version: '18' + - uses: actions/cache/restore@v4 + with: + path: ./ + key: web3-18-${{ github.sha }} + - run: yarn install --ignore-scripts + - run: yarn build:cjs + - run: yarn run build:docs + - name: Publish to Cloudflare Pages + uses: cloudflare/pages-action@v1 + with: + apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} + accountId: 2238a825c5aca59233eab1f221f7aefb + projectName: web3-js-docs + directory: ./docs/build + gitHubToken: ${{ secrets.GITHUB_TOKEN }} + benchmark: name: Benchmark Tests needs: build runs-on: ubuntu-latest steps: - - uses: actions/setup-node@v4 - with: - node-version: 18 - - 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@v4 - with: - path: web3-benchmark-main.json - key: ${{ runner.os }}-web3-benchmark-main.json - - run: yarn test:benchmark - - name: Compare benchmark result and make comment - uses: benchmark-action/github-action-benchmark@v1 - with: - # What benchmark tool the output.txt came from - tool: 'benchmarkjs' - # Where the output from the benchmark tool is stored - output-file-path: benchmark-data.txt - # Where the previous data file is stored - external-data-json-path: web3-benchmark-main.json - # Workflow will fail when an alert happens - fail-on-alert: false - # GitHub API token to make a commit comment - github-token: ${{ secrets.GITHUB_TOKEN }} - # Enable alert commit comment - comment-always: true - save-data-file: false - # copy comment from commit to Pull Request - - run: node scripts/copyCommitCommentToPrComment.js ${{ secrets.GITHUB_TOKEN }} ${{github.event.pull_request.head.sha}} ${{github.event.number}} - - name: Compare benchmark result and fail if threshold is reached - uses: benchmark-action/github-action-benchmark@v1 - with: - # What benchmark tool the output.txt came from - tool: 'benchmarkjs' - # Where the output from the benchmark tool is stored - output-file-path: benchmark-data.txt - # Where the previous data file is stored - external-data-json-path: web3-benchmark-main.json - # Workflow will fail when an alert happens - fail-on-alert: true - # 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@v4 - if: github.event_name == 'push' && github.ref == 'refs/heads/4.x' - with: - path: web3-benchmark-main.json - key: ${{ runner.os }}-web3-benchmark-main.json + - uses: actions/setup-node@v4 + with: + node-version: 18 + - 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@v4 + with: + path: web3-benchmark-main.json + key: ${{ runner.os }}-web3-benchmark-main + - run: yarn test:benchmark + - name: Compare benchmark result and make comment + uses: benchmark-action/github-action-benchmark@v1 + with: + # What benchmark tool the output.txt came from + tool: 'benchmarkjs' + # Where the output from the benchmark tool is stored + output-file-path: benchmark-data.txt + # Where the previous data file is stored + external-data-json-path: web3-benchmark-main.json + # Workflow will fail when an alert happens + fail-on-alert: false + # GitHub API token to make a commit comment + github-token: ${{ secrets.GITHUB_TOKEN }} + # Enable alert commit comment + comment-always: true + save-data-file: false + # copy comment from commit to Pull Request + - run: node scripts/copyCommitCommentToPrComment.js ${{ secrets.GITHUB_TOKEN }} ${{ github.event.pull_request.head.sha }} ${{ github.event.number }} + - name: Compare benchmark result and fail if threshold is reached + uses: benchmark-action/github-action-benchmark@v1 + with: + # What benchmark tool the output.txt came from + tool: 'benchmarkjs' + # Where the output from the benchmark tool is stored + output-file-path: benchmark-data.txt + # Where the previous data file is stored + external-data-json-path: web3-benchmark-main.json + # Workflow will fail when an alert happens + fail-on-alert: true + # Enable alert commit comment + alert-threshold: '200%' + comment-always: false + - name: Check and delete cache if it exists + run: | + if gh cache list | grep -q "${{ runner.os }}-web3-benchmark-main"; then + echo "Cache found. Deleting..." + gh cache delete "${{ runner.os }}-web3-benchmark-main" + else + echo "No matching cache found. Skipping delete." + fi + 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@v4 + if: github.event_name == 'push' && github.ref == 'refs/heads/4.x' + with: + path: web3-benchmark-main.json + key: ${{ runner.os }}-web3-benchmark-main diff --git a/packages/web3-eth-ens/test/integration/resolver.test.ts b/packages/web3-eth-ens/test/integration/resolver.test.ts index f6b2e648991..a79003d009c 100644 --- a/packages/web3-eth-ens/test/integration/resolver.test.ts +++ b/packages/web3-eth-ens/test/integration/resolver.test.ts @@ -42,7 +42,7 @@ import { ENSRegistryBytecode } from '../fixtures/ens/bytecode/ENSRegistryBytecod import { NameWrapperBytecode } from '../fixtures/ens/bytecode/NameWrapperBytecode'; import { PublicResolverBytecode } from '../fixtures/ens/bytecode/PublicResolverBytecode'; -jest.setTimeout(25000); +jest.setTimeout(35000); describe('ens', () => { let registry: Contract; let resolver: Contract; From 6af068fa5982f0e487146fc61a8c1e4032fc5dca Mon Sep 17 00:00:00 2001 From: Kris <605420+krzysu@users.noreply.github.com> Date: Wed, 13 Nov 2024 23:03:47 +0100 Subject: [PATCH 23/49] fix: return type of sendTransaction in docs (#7386) * fix: return type of sendTransaction in docs * Fix Very Minor Typo in Docs --------- Co-authored-by: Dan Forbes --- .../infer_contract_types.md | 2 +- packages/web3-eth/src/web3_eth.ts | 84 ++++++++++++++----- 2 files changed, 64 insertions(+), 22 deletions(-) diff --git a/docs/docs/guides/05_smart_contracts/infer_contract_types.md b/docs/docs/guides/05_smart_contracts/infer_contract_types.md index b5288412522..4d7c6e3b8c7 100644 --- a/docs/docs/guides/05_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 encourage 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. diff --git a/packages/web3-eth/src/web3_eth.ts b/packages/web3-eth/src/web3_eth.ts index ba951914e91..6320ff4f524 100644 --- a/packages/web3-eth/src/web3_eth.ts +++ b/packages/web3-eth/src/web3_eth.ts @@ -1021,19 +1021,61 @@ export class Web3Eth extends Web3Context 0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f + * const transactionReceipt = await web3.eth.sendTransaction(transaction); + * console.log(transactionReceipt); + * > { + * blockHash: '0x39cee0da843293ae3136cee0de4c0803745868b6e72b7cd05fba395bffa0ee85', + * blockNumber: 6659547n, + * cumulativeGasUsed: 1029036n, + * effectiveGasPrice: 6765796845n, + * from: '0x6E599DA0bfF7A6598AC1224E4985430Bf16458a4', + * gasUsed: 21000n, + * logs: [], + * logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', + * status: 1n, + * to: '0x6f1df96865d09d21e8f3f9a7fba3b17a11c7c53c', + * transactionHash: '0x619de868dd73c07bd0c096adcd405c93c1e924fdf741e684a127a52324c28bb9', + * transactionIndex: 16n, + * type: 2n + *} * * web3.eth.sendTransaction(transaction).then(console.log); - * > 0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f + * > { + * blockHash: '0x39cee0da843293ae3136cee0de4c0803745868b6e72b7cd05fba395bffa0ee85', + * blockNumber: 6659547n, + * cumulativeGasUsed: 1029036n, + * effectiveGasPrice: 6765796845n, + * from: '0x6E599DA0bfF7A6598AC1224E4985430Bf16458a4', + * gasUsed: 21000n, + * logs: [], + * logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', + * status: 1n, + * to: '0x6f1df96865d09d21e8f3f9a7fba3b17a11c7c53c', + * transactionHash: '0x619de868dd73c07bd0c096adcd405c93c1e924fdf741e684a127a52324c28bb9', + * transactionIndex: 16n, + * type: 2n + *} * * web3.eth.sendTransaction(transaction).catch(console.log); * > * * // Example using options.ignoreGasPricing = true * web3.eth.sendTransaction(transaction, undefined, { ignoreGasPricing: true }).then(console.log); - * > 0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f + * > { + * blockHash: '0x39cee0da843293ae3136cee0de4c0803745868b6e72b7cd05fba395bffa0ee85', + * blockNumber: 6659547n, + * cumulativeGasUsed: 1029036n, + * effectiveGasPrice: 6765796845n, + * from: '0x6E599DA0bfF7A6598AC1224E4985430Bf16458a4', + * gasUsed: 21000n, + * logs: [], + * logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', + * status: 1n, + * to: '0x6f1df96865d09d21e8f3f9a7fba3b17a11c7c53c', + * transactionHash: '0x619de868dd73c07bd0c096adcd405c93c1e924fdf741e684a127a52324c28bb9', + * transactionIndex: 16n, + * type: 2n + *} * ``` * * @@ -1042,24 +1084,24 @@ export class Web3Eth extends Web3Context console.log(transactionToBeSent)); * > { - * from: '0x6E599DA0bfF7A6598AC1224E4985430Bf16458a4', - * to: '0x6f1DF96865D09d21e8f3f9a7fbA3b17A11c7C53C', - * value: '0x1', - * gasPrice: '0x77359400', - * maxPriorityFeePerGas: undefined, - * maxFeePerGas: undefined + * from: '0x6E599DA0bfF7A6598AC1224E4985430Bf16458a4', + * to: '0x6f1DF96865D09d21e8f3f9a7fbA3b17A11c7C53C', + * value: '0x1', + * gasPrice: '0x77359400', + * maxPriorityFeePerGas: undefined, + * maxFeePerGas: undefined * } * ``` * - `sent` * ```ts * web3.eth.sendTransaction(transaction).on('sent', sentTransaction => console.log(sentTransaction)); * > { - * from: '0x6E599DA0bfF7A6598AC1224E4985430Bf16458a4', - * to: '0x6f1DF96865D09d21e8f3f9a7fbA3b17A11c7C53C', - * value: '0x1', - * gasPrice: '0x77359400', - * maxPriorityFeePerGas: undefined, - * maxFeePerGas: undefined + * from: '0x6E599DA0bfF7A6598AC1224E4985430Bf16458a4', + * to: '0x6f1DF96865D09d21e8f3f9a7fbA3b17A11c7C53C', + * value: '0x1', + * gasPrice: '0x77359400', + * maxPriorityFeePerGas: undefined, + * maxFeePerGas: undefined * } * ``` * - `transactionHash` @@ -1090,8 +1132,8 @@ export class Web3Eth extends Web3Context console.log(confirmation)); * > { - * confirmations: 1n, - * receipt: { + * confirmations: 1n, + * receipt: { * transactionHash: '0xb4a3a35ae0f3e77ef0ff7be42010d948d011b21a4e341072ee18717b67e99ab8', * transactionIndex: 0n, * blockNumber: 5n, @@ -1105,8 +1147,8 @@ export class Web3Eth extends Web3Context Date: Thu, 14 Nov 2024 10:17:26 +0100 Subject: [PATCH 24/49] chore: update CI actions (#7385) --- .github/workflows/black_box_tests.yml | 96 ++++++++++++------------- .github/workflows/build.yml | 6 +- .github/workflows/canary_release.yml | 37 +++++----- .github/workflows/deploy-docs.yaml | 8 +-- .github/workflows/e2e_network_tests.yml | 90 +++++++++++------------ .github/workflows/stale.yml | 32 ++++----- 6 files changed, 134 insertions(+), 135 deletions(-) diff --git a/.github/workflows/black_box_tests.yml b/.github/workflows/black_box_tests.yml index 8d26e163264..bb47ea822d2 100644 --- a/.github/workflows/black_box_tests.yml +++ b/.github/workflows/black_box_tests.yml @@ -1,53 +1,53 @@ name: 'Black Box Tests' on: push: - branches: - - release/** - tags: - - v4.* + branches: + - release/** + tags: + - v4.* jobs: - build: - strategy: - matrix: - node: [18] - name: Build Packages - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - with: - node-version: ${{ matrix.node }} - - run: yarn - - run: tar -czf /tmp/web3-${{ matrix.node }}.js.tar.gz --exclude="./.git" ./ - - uses: actions/upload-artifact@v3 - with: - name: web3-${{ matrix.node }}.js.tar.gz - path: /tmp/web3-${{ matrix.node }}.js.tar.gz - black-box: - name: Black Box - needs: build - runs-on: ubuntu-latest - env: - 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 - matrix: - node: [18] - mode: ['http', 'ws'] - backend: ['geth', 'infura'] - steps: - - uses: actions/setup-node@v3 - with: - node-version: ${{ matrix.node }} - - uses: actions/download-artifact@v3 - with: - name: web3-${{ matrix.node }}.js.tar.gz - path: /tmp - - run: tar -xf /tmp/web3-${{ matrix.node }}.js.tar.gz -C ./ - - run: | - yarn test:blackbox:${{ matrix.backend }}:${{ matrix.mode }} - shell: bash + build: + strategy: + matrix: + node: [18] + name: Build Packages + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node }} + - run: yarn + - run: tar -czf /tmp/web3-${{ matrix.node }}.js.tar.gz --exclude="./.git" ./ + - uses: actions/upload-artifact@v4 + with: + name: web3-${{ matrix.node }}.js.tar.gz + path: /tmp/web3-${{ matrix.node }}.js.tar.gz + black-box: + name: Black Box + needs: build + runs-on: ubuntu-latest + env: + 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 + matrix: + node: [18] + mode: ['http', 'ws'] + backend: ['geth', 'infura'] + steps: + - uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node }} + - uses: actions/download-artifact@v4 + with: + name: web3-${{ matrix.node }}.js.tar.gz + path: /tmp + - run: tar -xf /tmp/web3-${{ matrix.node }}.js.tar.gz -C ./ + - run: | + yarn test:blackbox:${{ matrix.backend }}:${{ matrix.mode }} + shell: bash diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 81ce725b842..a9d9346359e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -149,7 +149,7 @@ jobs: - run: yarn test:unit continue-on-error: ${{ matrix.node == '20.17.0' }} - name: Upload coverage to Codecov - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 with: flags: UnitTests token: ${{ secrets.CODECOV_TOKEN }} @@ -162,7 +162,7 @@ jobs: strategy: fail-fast: false steps: - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: node-version: 18 - uses: actions/cache/restore@v4 @@ -204,7 +204,7 @@ jobs: matrix: browser: ['electron', 'chrome', 'firefox'] steps: - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: node-version: 18 - uses: browser-actions/setup-firefox@latest diff --git a/.github/workflows/canary_release.yml b/.github/workflows/canary_release.yml index f7081481f8d..8b59ebde563 100644 --- a/.github/workflows/canary_release.yml +++ b/.github/workflows/canary_release.yml @@ -1,23 +1,22 @@ name: 'Release Canary' on: - push: - branches: - - '4.x' + push: + branches: + - '4.x' jobs: - release: - name: release - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - with: - node-version: 18 - cache: yarn - registry-url: 'https://registry.npmjs.org' - - run: yarn install --frozen-lockfile - - run: yarn build:web - - run: yarn publish:canary - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - \ No newline at end of file + release: + name: release + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 18 + cache: yarn + registry-url: 'https://registry.npmjs.org' + - run: yarn install --frozen-lockfile + - run: yarn build:web + - run: yarn publish:canary + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/deploy-docs.yaml b/.github/workflows/deploy-docs.yaml index ce0ee35cee2..aff3ca793bb 100644 --- a/.github/workflows/deploy-docs.yaml +++ b/.github/workflows/deploy-docs.yaml @@ -1,10 +1,10 @@ name: Docs CloudFlare Deploy on: push: - branches: - - "4.x" - tags-ignore: - - v4* + branches: + - '4.x' + tags-ignore: + - v4* jobs: deploy: diff --git a/.github/workflows/e2e_network_tests.yml b/.github/workflows/e2e_network_tests.yml index 232420fca12..133815e4e2e 100644 --- a/.github/workflows/e2e_network_tests.yml +++ b/.github/workflows/e2e_network_tests.yml @@ -1,10 +1,10 @@ name: 'E2E Network Tests' on: push: - branches: - - release/** - tags: - - v4.* + branches: + - release/** + tags: + - v4.* # For test purpose only: # pull_request: @@ -12,44 +12,44 @@ on: # - '4.x' # types: [ opened, reopened, synchronize ] jobs: - build: - name: Build Packages - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - with: - node-version: 18 - cache: yarn - - run: yarn - - uses: actions/cache/save@v4 - with: - path: ./ - key: web3-e2e-18-${{github.sha}} - e2e: - name: E2E Network Tests - needs: build - runs-on: ubuntu-latest - env: - 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 }} - TEST_ACCOUNT_PRIVATE_KEY: ${{ secrets.TEST_ACCOUNT_PRIVATE_KEY }} - strategy: - fail-fast: false - matrix: - mode: ['http'] - network: ['sepolia', 'mainnet'] - steps: - - uses: actions/setup-node@v3 - with: - node-version: 18 - - uses: actions/cache/restore@v4 - with: - path: ./ - key: web3-e2e-18-${{github.sha}} - - run: | - yarn test:e2e:${{ matrix.network }}:${{ matrix.mode }} - shell: bash + build: + name: Build Packages + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 18 + cache: yarn + - run: yarn + - uses: actions/cache/save@v4 + with: + path: ./ + key: web3-e2e-18-${{github.sha}} + e2e: + name: E2E Network Tests + needs: build + runs-on: ubuntu-latest + env: + 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 }} + TEST_ACCOUNT_PRIVATE_KEY: ${{ secrets.TEST_ACCOUNT_PRIVATE_KEY }} + strategy: + fail-fast: false + matrix: + mode: ['http'] + network: ['sepolia', 'mainnet'] + steps: + - uses: actions/setup-node@v4 + with: + node-version: 18 + - uses: actions/cache/restore@v4 + with: + path: ./ + key: web3-e2e-18-${{github.sha}} + - run: | + yarn test:e2e:${{ matrix.network }}:${{ matrix.mode }} + shell: bash diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index d89cbdb6622..bc5e88ab6c9 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -1,19 +1,19 @@ -name: "Close stale issues" +name: 'Close stale issues' on: - schedule: - - cron: "0 0 * * *" + schedule: + - cron: '0 0 * * *' jobs: - stale: - runs-on: ubuntu-latest - steps: - - uses: actions/stale@v3 - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - stale-issue-message: 'This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 7 days if no further activity occurs. Thank you for your contributions. If you believe this was a mistake, please comment.' - stale-pr-message: 'This PR has been automatically marked as stale because it has not had recent activity. It will be closed in 7 days if no further activity occurs. Thank you for your contributions. If you believe this was a mistake, please comment.' - days-before-stale: 60 - days-before-close: 14 - operations-per-run: 100 - exempt-pr-labels: 'work-in-progress,4.x' - exempt-issue-labels: 'work-in-progress,4.x' + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v3 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + stale-issue-message: 'This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 7 days if no further activity occurs. Thank you for your contributions. If you believe this was a mistake, please comment.' + stale-pr-message: 'This PR has been automatically marked as stale because it has not had recent activity. It will be closed in 7 days if no further activity occurs. Thank you for your contributions. If you believe this was a mistake, please comment.' + days-before-stale: 60 + days-before-close: 14 + operations-per-run: 100 + exempt-pr-labels: 'work-in-progress,4.x' + exempt-issue-labels: 'work-in-progress,4.x' From 6ad1ca9f99624fb650b9391347e930fc6595d2ae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Nov 2024 11:09:08 +0100 Subject: [PATCH 25/49] Bump express from 4.19.2 to 4.21.1 in /docs (#7388) --- docs/yarn.lock | 105 ++++++++++++++++++++++++++----------------------- 1 file changed, 55 insertions(+), 50 deletions(-) diff --git a/docs/yarn.lock b/docs/yarn.lock index cf67200d6e6..13d7341ed3a 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -4024,10 +4024,10 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== -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== +body-parser@1.20.3: + version "1.20.3" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.3.tgz#1953431221c6fb5cd63c4b36d53fab0928e548c6" + integrity sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g== dependencies: bytes "3.1.2" content-type "~1.0.5" @@ -4037,7 +4037,7 @@ body-parser@1.20.2: http-errors "2.0.0" iconv-lite "0.4.24" on-finished "2.4.1" - qs "6.11.0" + qs "6.13.0" raw-body "2.5.2" type-is "~1.6.18" unpipe "1.0.0" @@ -4613,10 +4613,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.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" - integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== +cookie@0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.1.tgz#2f73c42142d5d5cf71310a74fc4ae61670e5dbc9" + integrity sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w== copy-text-to-clipboard@^3.2.0: version "3.2.0" @@ -5274,6 +5274,11 @@ encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== +encodeurl@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58" + integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== + enhanced-resolve@^5.17.0: version "5.17.1" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz#67bfbbcc2f81d511be77d686a90267ef7f898a15" @@ -5478,36 +5483,36 @@ execa@^5.0.0: strip-final-newline "^2.0.0" express@^4.17.3: - version "4.19.2" - resolved "https://registry.yarnpkg.com/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465" - integrity sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q== + version "4.21.1" + resolved "https://registry.yarnpkg.com/express/-/express-4.21.1.tgz#9dae5dda832f16b4eec941a4e44aa89ec481b281" + integrity sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ== dependencies: accepts "~1.3.8" array-flatten "1.1.1" - body-parser "1.20.2" + body-parser "1.20.3" content-disposition "0.5.4" content-type "~1.0.4" - cookie "0.6.0" + cookie "0.7.1" cookie-signature "1.0.6" debug "2.6.9" depd "2.0.0" - encodeurl "~1.0.2" + encodeurl "~2.0.0" escape-html "~1.0.3" etag "~1.8.1" - finalhandler "1.2.0" + finalhandler "1.3.1" fresh "0.5.2" http-errors "2.0.0" - merge-descriptors "1.0.1" + merge-descriptors "1.0.3" methods "~1.1.2" on-finished "2.4.1" parseurl "~1.3.3" - path-to-regexp "0.1.7" + path-to-regexp "0.1.10" proxy-addr "~2.0.7" - qs "6.11.0" + qs "6.13.0" range-parser "~1.2.1" safe-buffer "5.2.1" - send "0.18.0" - serve-static "1.15.0" + send "0.19.0" + serve-static "1.16.2" setprototypeof "1.2.0" statuses "2.0.1" type-is "~1.6.18" @@ -5627,13 +5632,13 @@ fill-range@^7.1.1: 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" - integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== +finalhandler@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.3.1.tgz#0c575f1d1d324ddd1da35ad7ece3df7d19088019" + integrity sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ== dependencies: debug "2.6.9" - encodeurl "~1.0.2" + encodeurl "~2.0.0" escape-html "~1.0.3" on-finished "2.4.1" parseurl "~1.3.3" @@ -7487,10 +7492,10 @@ memorystream@^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" - integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== +merge-descriptors@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz#d80319a65f3c7935351e5cfdac8f9318504dbed5" + integrity sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ== merge-stream@^2.0.0: version "2.0.0" @@ -8472,10 +8477,10 @@ path-scurry@^1.11.1: lru-cache "^10.2.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== +path-to-regexp@0.1.10: + version "0.1.10" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.10.tgz#67e9108c5c0551b9e5326064387de4763c4d5f8b" + integrity sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w== path-to-regexp@2.2.1: version "2.2.1" @@ -8953,12 +8958,12 @@ pupa@^3.1.0: dependencies: escape-goat "^4.0.0" -qs@6.11.0: - version "6.11.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" - integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== +qs@6.13.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906" + integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg== dependencies: - side-channel "^1.0.4" + side-channel "^1.0.6" queue-microtask@^1.2.2: version "1.2.3" @@ -9751,10 +9756,10 @@ semver@^7.3.2, semver@^7.3.5, semver@^7.3.7, semver@^7.5.4: 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" - resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" - integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== +send@0.19.0: + version "0.19.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8" + integrity sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw== dependencies: debug "2.6.9" depd "2.0.0" @@ -9804,15 +9809,15 @@ serve-index@^1.9.1: mime-types "~2.1.17" parseurl "~1.3.2" -serve-static@1.15.0: - version "1.15.0" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" - integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== +serve-static@1.16.2: + version "1.16.2" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.2.tgz#b6a5343da47f6bdd2673848bf45754941e803296" + integrity sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw== dependencies: - encodeurl "~1.0.2" + encodeurl "~2.0.0" escape-html "~1.0.3" parseurl "~1.3.3" - send "0.18.0" + send "0.19.0" set-function-length@^1.2.1: version "1.2.2" @@ -9901,7 +9906,7 @@ shiki@^0.14.7: vscode-oniguruma "^1.7.0" vscode-textmate "^8.0.0" -side-channel@^1.0.4: +side-channel@^1.0.6: 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== From bde13161e76e99841c6d8901c03901ce739174f2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Nov 2024 11:13:51 +0100 Subject: [PATCH 26/49] Bump ws from 7.4.6 to 8.18.0 (#7171) --- yarn.lock | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/yarn.lock b/yarn.lock index 0884fd08293..52a562b8587 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12953,26 +12953,21 @@ ws@7.4.6: integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== ws@^5.1.1: - version "5.2.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.3.tgz#05541053414921bc29c63bee14b8b0dd50b07b3d" - integrity sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA== + version "5.2.4" + resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.4.tgz#c7bea9f1cfb5f410de50e70e82662e562113f9a7" + integrity sha512-fFCejsuC8f9kOSu9FYaOw8CdO68O3h5v0lg4p74o8JqWpwTf9tniOD+nOB78aWoVSS6WptVUmDrp/KPsMVBWFQ== dependencies: async-limiter "~1.0.0" ws@^7.3.1, ws@^7.4.6: - version "7.5.9" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" - integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== - -ws@^8.11.0: - version "8.14.2" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.14.2.tgz#6c249a806eb2db7a20d26d51e7709eab7b2e6c7f" - integrity sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g== - -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== + version "7.5.10" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" + integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== + +ws@^8.11.0, ws@^8.17.1: + version "8.18.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" + integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== xhr@^2.2.0: version "2.6.0" From 8c55cb0061a4089a2c5470b11834e18c6c1b11ea Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Nov 2024 11:20:39 +0100 Subject: [PATCH 27/49] Bump micromatch from 4.0.7 to 4.0.8 in /docs (#7225) --- docs/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/yarn.lock b/docs/yarn.lock index 13d7341ed3a..a25944a756d 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -7942,9 +7942,9 @@ micromark@~2.11.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" - integrity sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q== + 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" From 471c12bac67dd40162c8c6c897a5c98c3a3815cc Mon Sep 17 00:00:00 2001 From: Muhammad Altabba <24407834+Muhammad-Altabba@users.noreply.github.com> Date: Thu, 14 Nov 2024 11:21:52 +0100 Subject: [PATCH 28/49] fix: upgrade prism-react-renderer from 2.3.1 to 2.4.0 (#7367) --- docs/package.json | 2 +- docs/yarn.lock | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/package.json b/docs/package.json index 9f337bbbcd3..f8b1958d25f 100644 --- a/docs/package.json +++ b/docs/package.json @@ -23,7 +23,7 @@ "classnames": "^2.3.2", "clsx": "^2.0.0", "docusaurus-lunr-search": "^3.3.1", - "prism-react-renderer": "^2.3.0", + "prism-react-renderer": "^2.4.0", "react": "^18.2.0", "react-dom": "^18.2.0" }, diff --git a/docs/yarn.lock b/docs/yarn.lock index a25944a756d..dc1815d39a5 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -8889,6 +8889,14 @@ prism-react-renderer@^2.0.6, prism-react-renderer@^2.3.0: "@types/prismjs" "^1.26.0" clsx "^2.0.0" +prism-react-renderer@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/prism-react-renderer/-/prism-react-renderer-2.4.0.tgz#c5ea692029c2f8b3fd04f63662d04ffd4eaf10a0" + integrity sha512-327BsVCD/unU4CNLZTWVHyUHKnsqcvj2qbPlQ8MiBE2eq2rgctjigPA1Gp9HLF83kZ20zNN6jgizHJeEsyFYOw== + dependencies: + "@types/prismjs" "^1.26.0" + clsx "^2.0.0" + prismjs@^1.29.0: version "1.29.0" resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.29.0.tgz#f113555a8fa9b57c35e637bba27509dcf802dd12" From 1b367e6c0c98682a605c56bba786045823d375f0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Nov 2024 11:31:40 +0100 Subject: [PATCH 29/49] Bump express from 4.18.1 to 4.20.0 (#7258) --- yarn.lock | 275 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 221 insertions(+), 54 deletions(-) diff --git a/yarn.lock b/yarn.lock index 52a562b8587..cf7dd00cedd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3595,21 +3595,21 @@ bn.js@^5.1.2, bn.js@^5.2.0, bn.js@^5.2.1: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== -body-parser@1.20.0: - version "1.20.0" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.0.tgz#3de69bd89011c11573d7bfee6a64f11b6bd27cc5" - integrity sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg== +body-parser@1.20.3: + version "1.20.3" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.3.tgz#1953431221c6fb5cd63c4b36d53fab0928e548c6" + integrity sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g== 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" http-errors "2.0.0" iconv-lite "0.4.24" on-finished "2.4.1" - qs "6.10.3" - raw-body "2.5.1" + qs "6.13.0" + raw-body "2.5.2" type-is "~1.6.18" unpipe "1.0.0" @@ -3876,6 +3876,17 @@ call-bind@^1.0.0, call-bind@^1.0.2: function-bind "^1.1.1" get-intrinsic "^1.0.2" +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.4" + set-function-length "^1.2.1" + callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -4329,10 +4340,10 @@ content-disposition@0.5.4: dependencies: safe-buffer "5.2.1" -content-type@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== +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== conventional-changelog-angular@5.0.12: version "5.0.12" @@ -4433,10 +4444,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== cookie@^0.4.1: version "0.4.2" @@ -4631,7 +4642,14 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9: dependencies: ms "2.0.0" -debug@4, debug@4.3.4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4, 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" + +debug@4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -4645,13 +4663,6 @@ 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" @@ -4737,6 +4748,15 @@ deferred-leveldown@~1.2.1: dependencies: abstract-leveldown "~2.6.0" +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: + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" + define-lazy-prop@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" @@ -5004,6 +5024,11 @@ encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== +encodeurl@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58" + integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== + encoding@^0.1.13: version "0.1.13" resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" @@ -5109,6 +5134,18 @@ es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.19.2, es-abstract@^1.19 string.prototype.trimstart "^1.0.5" unbox-primitive "^1.0.2" +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@^0.9.0: version "0.9.3" resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" @@ -5873,36 +5910,36 @@ expect@^29.7.0: jest-util "^29.7.0" express@^4.18.1: - version "4.18.1" - resolved "https://registry.yarnpkg.com/express/-/express-4.18.1.tgz#7797de8b9c72c857b9cd0e14a5eea80666267caf" - integrity sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q== + version "4.20.0" + resolved "https://registry.yarnpkg.com/express/-/express-4.20.0.tgz#f1d08e591fcec770c07be4767af8eb9bcfd67c48" + integrity sha512-pLdae7I6QqShF5PnNTCVn4hI91Dx0Grkn2+IAsMTgMIKuQVte2dN9PeGSSAME2FR8anOhVA62QDIUaWVfEXVLw== dependencies: accepts "~1.3.8" array-flatten "1.1.1" - body-parser "1.20.0" + body-parser "1.20.3" 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" - encodeurl "~1.0.2" + encodeurl "~2.0.0" escape-html "~1.0.3" etag "~1.8.1" finalhandler "1.2.0" fresh "0.5.2" http-errors "2.0.0" - merge-descriptors "1.0.1" + merge-descriptors "1.0.3" methods "~1.1.2" on-finished "2.4.1" parseurl "~1.3.3" - path-to-regexp "0.1.7" + path-to-regexp "0.1.10" proxy-addr "~2.0.7" - qs "6.10.3" + qs "6.11.0" range-parser "~1.2.1" safe-buffer "5.2.1" - send "0.18.0" - serve-static "1.15.0" + send "0.19.0" + serve-static "1.16.0" setprototypeof "1.2.0" statuses "2.0.1" type-is "~1.6.18" @@ -6303,6 +6340,11 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + function.prototype.name@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" @@ -6426,6 +6468,17 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: has "^1.0.3" has-symbols "^1.0.3" +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-package-type@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" @@ -6678,6 +6731,13 @@ globby@^6.1.0: pify "^2.0.0" pinkie-promise "^2.0.0" +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + graceful-fs@4.2.10, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: version "4.2.10" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" @@ -6801,6 +6861,18 @@ has-property-descriptors@^1.0.0: dependencies: get-intrinsic "^1.1.1" +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: + es-define-property "^1.0.0" + +has-proto@^1.0.1: + 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.2, has-symbols@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" @@ -6873,6 +6945,13 @@ hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: inherits "^2.0.3" minimalistic-assert "^1.0.1" +hasown@^2.0.0: + 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" + he@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" @@ -9048,10 +9127,10 @@ meow@^8.0.0: type-fest "^0.18.0" yargs-parser "^20.2.3" -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== +merge-descriptors@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz#d80319a65f3c7935351e5cfdac8f9318504dbed5" + integrity sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ== merge-stream@^2.0.0: version "2.0.0" @@ -9884,6 +9963,11 @@ object-inspect@^1.12.0, object-inspect@^1.9.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== +object-inspect@^1.13.1: + version "1.13.3" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.3.tgz#f14c183de51130243d6d18ae149375ff50ea488a" + integrity sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA== + object-is@^1.0.1: version "1.1.5" resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" @@ -10320,10 +10404,10 @@ path-scurry@^1.6.1, path-scurry@^1.7.0: lru-cache "^9.1.1" minipass "^5.0.0 || ^6.0.2" -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== +path-to-regexp@0.1.10: + version "0.1.10" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.10.tgz#67e9108c5c0551b9e5326064387de4763c4d5f8b" + integrity sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w== path-type@^3.0.0: version "3.0.0" @@ -10614,13 +10698,20 @@ q@^1.5.1: resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" integrity sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw== -qs@6.10.3: - version "6.10.3" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e" - integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ== +qs@6.11.0: + version "6.11.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" + integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== dependencies: side-channel "^1.0.4" +qs@6.13.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906" + integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg== + dependencies: + side-channel "^1.0.6" + qs@~6.5.2: version "6.5.3" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" @@ -10653,7 +10744,17 @@ 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, raw-body@^2.4.1: +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" + iconv-lite "0.4.24" + unpipe "1.0.0" + +raw-body@^2.4.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== @@ -11235,6 +11336,25 @@ send@0.18.0: range-parser "~1.2.1" statuses "2.0.1" +send@0.19.0: + version "0.19.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8" + integrity sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw== + dependencies: + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "2.0.0" + mime "1.6.0" + ms "2.1.3" + on-finished "2.4.1" + range-parser "~1.2.1" + statuses "2.0.1" + serialize-javascript@6.0.0, serialize-javascript@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" @@ -11242,10 +11362,10 @@ serialize-javascript@6.0.0, serialize-javascript@^6.0.0: dependencies: randombytes "^2.1.0" -serve-static@1.15.0: - version "1.15.0" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" - integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== +serve-static@1.16.0: + version "1.16.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.0.tgz#2bf4ed49f8af311b519c46f272bf6ac3baf38a92" + integrity sha512-pDLK8zwl2eKaYrs8mrPZBJua4hMplRWJ1tIFksVC3FtBEBnl8dxgeHtsaMS8DhS9i4fLObaon6ABoc4/hQGdPA== dependencies: encodeurl "~1.0.2" escape-html "~1.0.3" @@ -11257,6 +11377,18 @@ set-blocking@^2.0.0, set-blocking@~2.0.0: resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== +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.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.2" + set-immediate-shim@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" @@ -11333,6 +11465,16 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" +side-channel@^1.0.6: + 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.7" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + object-inspect "^1.13.1" + signal-exit@3.0.7, signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" @@ -11681,7 +11823,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== @@ -11699,6 +11841,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" @@ -11754,7 +11905,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== @@ -11768,6 +11919,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" @@ -12861,7 +13019,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== From 6229f4d8f0f0a327b00970a48702d191b64a6b49 Mon Sep 17 00:00:00 2001 From: Kris <605420+krzysu@users.noreply.github.com> Date: Tue, 19 Nov 2024 10:48:21 +0100 Subject: [PATCH 30/49] chore: update deps to fix vulnerabilities (#7389) --- yarn.lock | 541 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 297 insertions(+), 244 deletions(-) diff --git a/yarn.lock b/yarn.lock index cf7dd00cedd..a6973e86251 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1210,7 +1210,7 @@ "@jridgewell/set-array" "^1.0.0" "@jridgewell/sourcemap-codec" "^1.4.10" -"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": +"@jridgewell/gen-mapping@^0.3.2": version "0.3.2" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== @@ -1219,6 +1219,15 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.9" +"@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.2.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.24" + "@jridgewell/resolve-uri@^3.0.3": version "3.1.0" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" @@ -1234,13 +1243,18 @@ resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== -"@jridgewell/source-map@^0.3.2": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" - integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== +"@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.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": version "1.4.14" @@ -1260,7 +1274,7 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" -"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.14", "@jridgewell/trace-mapping@^0.3.9": +"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.9": version "0.3.15" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz#aba35c48a38d3fd84b37e66c9c0423f9744f9774" integrity sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g== @@ -1284,6 +1298,14 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" +"@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" + "@lerna/child-process@6.6.2": version "6.6.2" resolved "https://registry.yarnpkg.com/@lerna/child-process/-/child-process-6.6.2.tgz#5d803c8dee81a4e013dc428292e77b365cba876c" @@ -2037,9 +2059,9 @@ "@octokit/openapi-types" "^13.1.0" "@openzeppelin/contracts@^4.7.1": - version "4.9.3" - resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.9.3.tgz#00d7a8cf35a475b160b3f0293a6403c511099364" - integrity sha512-He3LieZ1pP2TNt5JbkPA4PNT9WC3gOTOlDcFGJW4Le4QKqwmiNJCRt44APfxMxvq7OugU/cqYuPcSBzOw38DAg== + version "4.9.6" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.9.6.tgz#2a880a24eb19b4f8b25adc2a5095f2aa27f39677" + integrity "sha1-KogKJOsZtPiyWtwqUJXyqifzlnc= sha512-xSmezSupL+y9VkHZJGDoCBpmnB2ogM13ccaYDWqJTfS3dbuHkgjuwDFUmaFauBCboQMGB/S5UqUl2y54X99BmA==" "@parcel/watcher@2.0.4": version "2.0.4" @@ -2362,10 +2384,10 @@ dependencies: "@types/node" "*" -"@types/eslint-scope@^3.7.3": - version "3.7.4" - resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16" - integrity sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA== +"@types/eslint-scope@^3.7.7": + version "3.7.7" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5" + integrity "sha1-MQi9XxiwzbJ3yGez3UScntcHmsU= sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==" dependencies: "@types/eslint" "*" "@types/estree" "*" @@ -2383,10 +2405,10 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== -"@types/estree@^0.0.51": - version "0.0.51" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" - integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== +"@types/estree@^1.0.6": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" + integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== "@types/express-serve-static-core@^4.17.18": version "4.17.30" @@ -2719,125 +2741,125 @@ "@typescript-eslint/types" "5.33.1" eslint-visitor-keys "^3.3.0" -"@webassemblyjs/ast@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" - integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw== +"@webassemblyjs/ast@1.14.1", "@webassemblyjs/ast@^1.12.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.14.1.tgz#a9f6a07f2b03c95c8d38c4536a1fdfb521ff55b6" + integrity "sha1-qfagfysDyVyNOMRTah/ftSH/VbY= sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==" dependencies: - "@webassemblyjs/helper-numbers" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/helper-numbers" "1.13.2" + "@webassemblyjs/helper-wasm-bytecode" "1.13.2" -"@webassemblyjs/floating-point-hex-parser@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f" - integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== +"@webassemblyjs/floating-point-hex-parser@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz#fcca1eeddb1cc4e7b6eed4fc7956d6813b21b9fb" + integrity "sha1-/Moe7dscxOe27tT8eVbWgTshufs= sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==" -"@webassemblyjs/helper-api-error@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16" - integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== +"@webassemblyjs/helper-api-error@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz#e0a16152248bc38daee76dd7e21f15c5ef3ab1e7" + integrity "sha1-4KFhUiSLw42u523X4h8Vxe86sec= sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==" -"@webassemblyjs/helper-buffer@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5" - integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== +"@webassemblyjs/helper-buffer@1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz#822a9bc603166531f7d5df84e67b5bf99b72b96b" + integrity "sha1-giqbxgMWZTH31d+E5ntb+ZtyuWs= sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==" -"@webassemblyjs/helper-numbers@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae" - integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ== +"@webassemblyjs/helper-numbers@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz#dbd932548e7119f4b8a7877fd5a8d20e63490b2d" + integrity "sha1-29kyVI5xGfS4p4d/1ajSDmNJCy0= sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==" dependencies: - "@webassemblyjs/floating-point-hex-parser" "1.11.1" - "@webassemblyjs/helper-api-error" "1.11.1" + "@webassemblyjs/floating-point-hex-parser" "1.13.2" + "@webassemblyjs/helper-api-error" "1.13.2" "@xtuc/long" "4.2.2" -"@webassemblyjs/helper-wasm-bytecode@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1" - integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== +"@webassemblyjs/helper-wasm-bytecode@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz#e556108758f448aae84c850e593ce18a0eb31e0b" + integrity "sha1-5VYQh1j0SKroTIUOWTzhig6zHgs= sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==" -"@webassemblyjs/helper-wasm-section@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a" - integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg== +"@webassemblyjs/helper-wasm-section@1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz#9629dda9c4430eab54b591053d6dc6f3ba050348" + integrity "sha1-lindqcRDDqtUtZEFPW3G87oFA0g= sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==" dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/ast" "1.14.1" + "@webassemblyjs/helper-buffer" "1.14.1" + "@webassemblyjs/helper-wasm-bytecode" "1.13.2" + "@webassemblyjs/wasm-gen" "1.14.1" -"@webassemblyjs/ieee754@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614" - integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ== +"@webassemblyjs/ieee754@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz#1c5eaace1d606ada2c7fd7045ea9356c59ee0dba" + integrity "sha1-HF6qzh1gatosf9cEXqk1bFnuDbo= sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==" dependencies: "@xtuc/ieee754" "^1.2.0" -"@webassemblyjs/leb128@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5" - integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw== +"@webassemblyjs/leb128@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.13.2.tgz#57c5c3deb0105d02ce25fa3fd74f4ebc9fd0bbb0" + integrity "sha1-V8XD3rAQXQLOJfo/109OvJ/Qu7A= sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==" dependencies: "@xtuc/long" "4.2.2" -"@webassemblyjs/utf8@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff" - integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== - -"@webassemblyjs/wasm-edit@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6" - integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/helper-wasm-section" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" - "@webassemblyjs/wasm-opt" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" - "@webassemblyjs/wast-printer" "1.11.1" - -"@webassemblyjs/wasm-gen@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76" - integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/ieee754" "1.11.1" - "@webassemblyjs/leb128" "1.11.1" - "@webassemblyjs/utf8" "1.11.1" - -"@webassemblyjs/wasm-opt@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2" - integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" - -"@webassemblyjs/wasm-parser@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199" - integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-api-error" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/ieee754" "1.11.1" - "@webassemblyjs/leb128" "1.11.1" - "@webassemblyjs/utf8" "1.11.1" - -"@webassemblyjs/wast-printer@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0" - integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg== - dependencies: - "@webassemblyjs/ast" "1.11.1" +"@webassemblyjs/utf8@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.13.2.tgz#917a20e93f71ad5602966c2d685ae0c6c21f60f1" + integrity "sha1-kXog6T9xrVYClmwtaFrgxsIfYPE= sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==" + +"@webassemblyjs/wasm-edit@^1.12.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz#ac6689f502219b59198ddec42dcd496b1004d597" + integrity "sha1-rGaJ9QIhm1kZjd7ELc1JaxAE1Zc= sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==" + dependencies: + "@webassemblyjs/ast" "1.14.1" + "@webassemblyjs/helper-buffer" "1.14.1" + "@webassemblyjs/helper-wasm-bytecode" "1.13.2" + "@webassemblyjs/helper-wasm-section" "1.14.1" + "@webassemblyjs/wasm-gen" "1.14.1" + "@webassemblyjs/wasm-opt" "1.14.1" + "@webassemblyjs/wasm-parser" "1.14.1" + "@webassemblyjs/wast-printer" "1.14.1" + +"@webassemblyjs/wasm-gen@1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz#991e7f0c090cb0bb62bbac882076e3d219da9570" + integrity "sha1-mR5/DAkMsLtiu6yIIHbj0hnalXA= sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==" + dependencies: + "@webassemblyjs/ast" "1.14.1" + "@webassemblyjs/helper-wasm-bytecode" "1.13.2" + "@webassemblyjs/ieee754" "1.13.2" + "@webassemblyjs/leb128" "1.13.2" + "@webassemblyjs/utf8" "1.13.2" + +"@webassemblyjs/wasm-opt@1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz#e6f71ed7ccae46781c206017d3c14c50efa8106b" + integrity "sha1-5vce18yuRngcIGAX08FMUO+oEGs= sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==" + dependencies: + "@webassemblyjs/ast" "1.14.1" + "@webassemblyjs/helper-buffer" "1.14.1" + "@webassemblyjs/wasm-gen" "1.14.1" + "@webassemblyjs/wasm-parser" "1.14.1" + +"@webassemblyjs/wasm-parser@1.14.1", "@webassemblyjs/wasm-parser@^1.12.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz#b3e13f1893605ca78b52c68e54cf6a865f90b9fb" + integrity "sha1-s+E/GJNgXKeLUsaOVM9qhl+Qufs= sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==" + dependencies: + "@webassemblyjs/ast" "1.14.1" + "@webassemblyjs/helper-api-error" "1.13.2" + "@webassemblyjs/helper-wasm-bytecode" "1.13.2" + "@webassemblyjs/ieee754" "1.13.2" + "@webassemblyjs/leb128" "1.13.2" + "@webassemblyjs/utf8" "1.13.2" + +"@webassemblyjs/wast-printer@1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz#3bb3e9638a8ae5fdaf9610e7a06b4d9f9aa6fe07" + integrity "sha1-O7PpY4qK5f2vlhDnoGtNn5qm/gc= sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==" + dependencies: + "@webassemblyjs/ast" "1.14.1" "@xtuc/long" "4.2.2" "@webpack-cli/configtest@^1.2.0": @@ -2982,11 +3004,6 @@ acorn-globals@^7.0.0: acorn "^8.1.0" acorn-walk "^8.0.2" -acorn-import-assertions@^1.7.6: - version "1.8.0" - resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" - integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== - acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" @@ -2997,7 +3014,7 @@ acorn-walk@^8.0.0, acorn-walk@^8.0.2, acorn-walk@^8.1.1: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== -acorn@^8.0.4, acorn@^8.4.1, acorn@^8.5.0, acorn@^8.7.1, acorn@^8.8.0: +acorn@^8.0.4, acorn@^8.4.1, acorn@^8.8.0: version "8.8.2" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== @@ -3007,6 +3024,11 @@ acorn@^8.1.0, acorn@^8.8.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== +acorn@^8.14.0, acorn@^8.8.2: + version "8.14.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" + integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== + add-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/add-stream/-/add-stream-1.0.0.tgz#6a7990437ca736d5e1288db92bd3266d5f5cb2aa" @@ -3651,14 +3673,7 @@ braces@^2.3.1: split-string "^3.0.2" to-regex "^3.0.1" -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== - dependencies: - fill-range "^7.0.1" - -braces@^3.0.3: +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== @@ -3697,7 +3712,7 @@ browserify-aes@^1.2.0: inherits "^2.0.1" safe-buffer "^5.0.1" -browserslist@^4.14.5, browserslist@^4.20.2, browserslist@^4.21.3: +browserslist@^4.20.2, browserslist@^4.21.3: version "4.21.3" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.3.tgz#5df277694eb3c48bc5c4b05af3e8b7e09c5a6d1a" integrity sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ== @@ -3707,6 +3722,16 @@ browserslist@^4.14.5, browserslist@^4.20.2, browserslist@^4.21.3: node-releases "^2.0.6" update-browserslist-db "^1.0.5" +browserslist@^4.24.0: + version "4.24.2" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.2.tgz#f5845bc91069dbd55ee89faf9822e1d885d16580" + integrity sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg== + dependencies: + caniuse-lite "^1.0.30001669" + electron-to-chromium "^1.5.41" + node-releases "^2.0.18" + update-browserslist-db "^1.1.1" + bs-logger@0.x: version "0.2.6" resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" @@ -3916,6 +3941,11 @@ caniuse-lite@^1.0.30001370: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001378.tgz#3d2159bf5a8f9ca093275b0d3ecc717b00f27b67" integrity sha512-JVQnfoO7FK7WvU4ZkBRbPjaot4+YqxogSDosHv0Hv5mWpUESmN+UubMU6L/hGz8QlQ2aY5U0vR6MOs6j/CXpNA== +caniuse-lite@^1.0.30001669: + version "1.0.30001680" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001680.tgz#5380ede637a33b9f9f1fc6045ea99bd142f3da5e" + integrity "sha1-U4Dt5jejO5+fH8YEXqmb0ULz2l4= sha512-rPQy70G6AGUMnbwS1z6Xg+RkHYPAi18ihs47GH0jcxIG7wArmPgY3XbS2sRdBbxJljp3thdT8BIqv9ccCypiPA==" + case@^1.6.3: version "1.6.3" resolved "https://registry.yarnpkg.com/case/-/case-1.6.3.tgz#0a4386e3e9825351ca2e6216c60467ff5f1ea1c9" @@ -4692,9 +4722,9 @@ declaration-bundler-webpack-plugin@^1.0.3: integrity sha512-bgeoSOZYTOOdiNUZd/U8K6Z+6IrM/X+DgUcm3/VI1l130lzOBeL+ObetjIkKksxcj0zUJbLaFRFumFGYDOQ9fg== decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og== + version "0.2.2" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" + integrity "sha1-5p2+JdN5QRcd1UDgJMREzVGI4ek= sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==" dedent@0.7.0, dedent@^0.7.0: version "0.7.0" @@ -4965,9 +4995,9 @@ ee-first@1.1.1: integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== ejs@^3.1.7: - version "3.1.9" - resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.9.tgz#03c9e8777fe12686a9effcef22303ca3d8eeb361" - integrity sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ== + version "3.1.10" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.10.tgz#69ab8358b14e896f80cc39e62087b88500c3ac3b" + integrity sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA== dependencies: jake "^10.8.5" @@ -4976,6 +5006,11 @@ electron-to-chromium@^1.4.202: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.222.tgz#2ba24bef613fc1985dbffea85df8f62f2dec6448" integrity sha512-gEM2awN5HZknWdLbngk4uQCVfhucFAfFzuchP3wM3NN6eow1eDU0dFy2kts43FB20ZfhVFF0jmFSTb1h5OhyIg== +electron-to-chromium@^1.5.41: + version "1.5.58" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.58.tgz#d90bd7a04d9223dce4e72316e14492140ec9af40" + integrity "sha1-2QvXoE2SI9zk5yMW4USSFA7Jr0A= sha512-al2l4r+24ZFL7WzyPTlyD0fC33LLzvxqLCwurtBibVPghRGO9hSTl+tis8t1kD7biPiH/en4U0I7o/nQbYeoVA==" + elliptic@6.5.4, elliptic@^6.5.2, elliptic@^6.5.4: version "6.5.4" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" @@ -5043,7 +5078,7 @@ end-of-stream@^1.4.1: dependencies: once "^1.4.0" -enhanced-resolve@^5.0.0, enhanced-resolve@^5.10.0: +enhanced-resolve@^5.0.0: version "5.10.0" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz#0dc579c3bb2a1032e357ac45b8f3a6f3ad4fb1e6" integrity sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ== @@ -5059,6 +5094,14 @@ enhanced-resolve@^5.12.0: graceful-fs "^4.2.4" tapable "^2.2.0" +enhanced-resolve@^5.17.1: + 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" + enquirer@^2.3.0, enquirer@~2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" @@ -5146,10 +5189,10 @@ es-errors@^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@^0.9.0: - version "0.9.3" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" - integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== +es-module-lexer@^1.2.1: + 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== es-shim-unscopables@^1.0.0: version "1.0.0" @@ -5177,6 +5220,11 @@ escalade@^3.1.1: resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== +escalade@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== + escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" @@ -6114,13 +6162,6 @@ fill-range@^4.0.0: repeat-string "^1.6.1" to-regex-range "^2.1.0" -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== - 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" @@ -6188,9 +6229,9 @@ flatted@^3.3.1: integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== follow-redirects@^1.0.0, follow-redirects@^1.12.1: - version "1.15.1" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5" - integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA== + version "1.15.9" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" + integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== follow-redirects@^1.15.6: version "1.15.6" @@ -6743,6 +6784,11 @@ graceful-fs@4.2.10, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2 resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== +graceful-fs@^4.2.11: + 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== + grapheme-splitter@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" @@ -7019,12 +7065,7 @@ http-browserify@^1.7.0: Base64 "~0.2.0" inherits "~2.0.1" -http-cache-semantics@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" - integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== - -http-cache-semantics@^4.1.1: +http-cache-semantics@^4.1.0, http-cache-semantics@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== @@ -8465,9 +8506,9 @@ json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== json5@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" - integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + version "1.0.2" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" + integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== dependencies: minimist "^1.2.0" @@ -9180,15 +9221,7 @@ micromatch@^3.1.10: snapdragon "^0.8.1" to-regex "^3.0.2" -micromatch@^4.0.0, micromatch@^4.0.2, micromatch@^4.0.4: - version "4.0.5" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== - dependencies: - braces "^3.0.2" - picomatch "^2.3.1" - -micromatch@~4.0.7: +micromatch@^4.0.0, micromatch@^4.0.2, micromatch@^4.0.4, 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== @@ -9607,6 +9640,11 @@ node-int64@^0.4.0: resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== +node-releases@^2.0.18: + version "2.0.18" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.18.tgz#f010e8d35e2fe8d6b2944f03f70213ecedc4ca3f" + integrity sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g== + node-releases@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" @@ -10442,6 +10480,11 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== +picocolors@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" @@ -11234,7 +11277,7 @@ saxes@^6.0.0: dependencies: xmlchars "^2.2.0" -schema-utils@^3.1.0, schema-utils@^3.1.1: +schema-utils@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== @@ -11243,6 +11286,15 @@ schema-utils@^3.1.0, schema-utils@^3.1.1: ajv "^6.12.5" ajv-keywords "^3.5.2" +schema-utils@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" + integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== + dependencies: + "@types/json-schema" "^7.0.8" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + scrypt-js@3.0.1, scrypt-js@^3.0.0, scrypt-js@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" @@ -11287,9 +11339,9 @@ semver@7.3.8: lru-cache "^6.0.0" semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== semver@^7.0.0, semver@^7.1.1, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7: version "7.3.7" @@ -11355,13 +11407,20 @@ send@0.19.0: range-parser "~1.2.1" statuses "2.0.1" -serialize-javascript@6.0.0, serialize-javascript@^6.0.0: +serialize-javascript@6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== dependencies: randombytes "^2.1.0" +serialize-javascript@^6.0.1: + 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" + serve-static@1.16.0: version "1.16.0" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.0.tgz#2bf4ed49f8af311b519c46f272bf6ac3baf38a92" @@ -11823,7 +11882,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== @@ -11841,15 +11900,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" @@ -11905,7 +11955,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== @@ -11919,13 +11969,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" @@ -12043,7 +12086,7 @@ tar-stream@~2.2.0: inherits "^2.0.3" readable-stream "^3.1.1" -tar@6.1.11, tar@^6.1.11, tar@^6.1.2: +tar@6.1.11: version "6.1.11" resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621" integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA== @@ -12055,6 +12098,18 @@ tar@6.1.11, tar@^6.1.11, tar@^6.1.2: mkdirp "^1.0.3" yallist "^4.0.0" +tar@^6.1.11, tar@^6.1.2: + version "6.2.1" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.1.tgz#717549c541bc3c2af15751bea94b1dd068d4b03a" + integrity "sha1-cXVJxUG8PCrxV1G+qUsd0GjUsDo= sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==" + dependencies: + chownr "^2.0.0" + fs-minipass "^2.0.0" + minipass "^5.0.0" + minizlib "^2.1.1" + mkdirp "^1.0.3" + yallist "^4.0.0" + temp-dir@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d" @@ -12076,24 +12131,24 @@ tempy@1.0.0: type-fest "^0.16.0" unique-string "^2.0.0" -terser-webpack-plugin@^5.1.3: - version "5.3.5" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.5.tgz#f7d82286031f915a4f8fb81af4bd35d2e3c011bc" - integrity sha512-AOEDLDxD2zylUGf/wxHxklEkOe2/r+seuyOWujejFrIxHf11brA1/dWQNIgXa1c6/Wkxgu7zvv0JhOWfc2ELEA== +terser-webpack-plugin@^5.3.10: + 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== dependencies: - "@jridgewell/trace-mapping" "^0.3.14" + "@jridgewell/trace-mapping" "^0.3.20" jest-worker "^27.4.5" schema-utils "^3.1.1" - serialize-javascript "^6.0.0" - terser "^5.14.1" + serialize-javascript "^6.0.1" + terser "^5.26.0" -terser@^5.14.1: - version "5.14.2" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.14.2.tgz#9ac9f22b06994d736174f4091aa368db896f1c10" - integrity sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA== +terser@^5.26.0: + version "5.36.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.36.0.tgz#8b0dbed459ac40ff7b4c9fd5a3a2029de105180e" + integrity sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w== dependencies: - "@jridgewell/source-map" "^0.3.2" - acorn "^8.5.0" + "@jridgewell/source-map" "^0.3.3" + acorn "^8.8.2" commander "^2.20.0" source-map-support "~0.5.20" @@ -12607,6 +12662,14 @@ update-browserslist-db@^1.0.5: escalade "^3.1.1" picocolors "^1.0.0" +update-browserslist-db@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz#80846fba1d79e82547fb661f8d141e0945755fe5" + integrity sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A== + dependencies: + escalade "^3.2.0" + picocolors "^1.1.0" + uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -12785,10 +12848,10 @@ walker@^1.0.8: dependencies: makeerror "1.0.12" -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.2" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.2.tgz#2feeaed67412e7c33184e5a79ca738fbd38564da" + integrity sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw== dependencies: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" @@ -12893,33 +12956,32 @@ webpack-sources@^3.2.3: integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== webpack@^5, webpack@^5.73.0: - version "5.76.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.76.0.tgz#f9fb9fb8c4a7dbdcd0d56a98e56b8a942ee2692c" - integrity sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA== - dependencies: - "@types/eslint-scope" "^3.7.3" - "@types/estree" "^0.0.51" - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/wasm-edit" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" - acorn "^8.7.1" - acorn-import-assertions "^1.7.6" - browserslist "^4.14.5" + version "5.96.1" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.96.1.tgz#3676d1626d8312b6b10d0c18cc049fba7ac01f0c" + integrity "sha1-NnbRYm2DEraxDQwYzASfunrAHww= sha512-l2LlBSvVZGhL4ZrPwyr8+37AunkcYj5qh8o6u2/2rzoPc8gxFJkLj1WxNgooi9pnoc06jh0BjuXnamM4qlujZA==" + dependencies: + "@types/eslint-scope" "^3.7.7" + "@types/estree" "^1.0.6" + "@webassemblyjs/ast" "^1.12.1" + "@webassemblyjs/wasm-edit" "^1.12.1" + "@webassemblyjs/wasm-parser" "^1.12.1" + acorn "^8.14.0" + browserslist "^4.24.0" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.10.0" - es-module-lexer "^0.9.0" + enhanced-resolve "^5.17.1" + 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.1.0" + schema-utils "^3.2.0" tapable "^2.1.1" - terser-webpack-plugin "^5.1.3" - watchpack "^2.4.0" + terser-webpack-plugin "^5.3.10" + watchpack "^2.4.1" webpack-sources "^3.2.3" whatwg-encoding@^2.0.0: @@ -13019,16 +13081,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== From 5eeb2d6188469f2ad4f5377b37ef5d3f92017bdc Mon Sep 17 00:00:00 2001 From: whitemoshui <139415706+whitemoshui@users.noreply.github.com> Date: Tue, 19 Nov 2024 17:50:33 +0800 Subject: [PATCH 31/49] chore: fix 0 kwei bug (#7387) --- CHANGELOG.md | 4 ++++ packages/web3-utils/CHANGELOG.md | 4 ++++ packages/web3-utils/src/converters.ts | 2 +- packages/web3-utils/test/fixtures/converters.ts | 3 +++ 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c97c573755..7ea32551380 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2809,3 +2809,7 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3 - Export Web3Account, Wallet and signature related types. (#7374) + +#### web3-utils + +- Make `fromWei` return "0" when input is `0` (#7387) diff --git a/packages/web3-utils/CHANGELOG.md b/packages/web3-utils/CHANGELOG.md index 940059963d8..b698fcf51ba 100644 --- a/packages/web3-utils/CHANGELOG.md +++ b/packages/web3-utils/CHANGELOG.md @@ -241,3 +241,7 @@ Documentation: - fix `padRight` validation failure on large `uint` (#7265) ## [Unreleased] + +### Fixed + +- Make `fromWei` return "0" when input is `0` (#7387) diff --git a/packages/web3-utils/src/converters.ts b/packages/web3-utils/src/converters.ts index 9c94a4332b0..dce6ce78871 100644 --- a/packages/web3-utils/src/converters.ts +++ b/packages/web3-utils/src/converters.ts @@ -546,7 +546,7 @@ export const fromWei = (number: Numbers, unit: EtherUnits | number): string => { const fraction = zeroPaddedValue.slice(-numberOfZerosInDenomination).replace(/\.?0+$/, ''); if (integer === '') { - return `0.${fraction}`; + return fraction ? `0.${fraction}` : '0'; } if (fraction === '') { diff --git a/packages/web3-utils/test/fixtures/converters.ts b/packages/web3-utils/test/fixtures/converters.ts index cecb0b3fafb..025f9f7a987 100644 --- a/packages/web3-utils/test/fixtures/converters.ts +++ b/packages/web3-utils/test/fixtures/converters.ts @@ -328,6 +328,9 @@ export const fromWeiValidData: [[Numbers, EtherUnits | number], Numbers][] = [ [['1123', 'kwei'], '1.123'], [['1234100', 'kwei'], '1234.1'], [['3308685546611893', 'ether'], '0.003308685546611893'], + [['0', 'wei'], '0'], + [['0', 'kwei'], '0'], + [['0', 'ether'], '0'], ]; export const toWeiValidData: [[Numbers, EtherUnits | number], Numbers][] = [ From e79ace2900e19a089a04ae47727125e68da46501 Mon Sep 17 00:00:00 2001 From: Muhammad Altabba <24407834+Muhammad-Altabba@users.noreply.github.com> Date: Tue, 19 Nov 2024 11:06:22 +0100 Subject: [PATCH 32/49] fix: upgrade docusaurus-lunr-search from 3.4.0 to 3.5.0 (#7396) --- docs/package.json | 2 +- docs/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/package.json b/docs/package.json index f8b1958d25f..620dcb1938a 100644 --- a/docs/package.json +++ b/docs/package.json @@ -22,7 +22,7 @@ "@mdx-js/react": "^3.0.0", "classnames": "^2.3.2", "clsx": "^2.0.0", - "docusaurus-lunr-search": "^3.3.1", + "docusaurus-lunr-search": "^3.5.0", "prism-react-renderer": "^2.4.0", "react": "^18.2.0", "react-dom": "^18.2.0" diff --git a/docs/yarn.lock b/docs/yarn.lock index dc1815d39a5..be41e52be84 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -5106,10 +5106,10 @@ dns-packet@^5.2.2: dependencies: "@leichtgewicht/ip-codec" "^2.0.1" -docusaurus-lunr-search@^3.3.1: - version "3.4.0" - resolved "https://registry.yarnpkg.com/docusaurus-lunr-search/-/docusaurus-lunr-search-3.4.0.tgz#cefb0f8628f629e780451ae042d3cc35f078826f" - integrity sha512-GfllnNXCLgTSPH9TAKWmbn8VMfwpdOAZ1xl3T2GgX8Pm26qSDLfrrdVwjguaLfMJfzciFL97RKrAJlgrFM48yw== +docusaurus-lunr-search@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/docusaurus-lunr-search/-/docusaurus-lunr-search-3.5.0.tgz#52832d7bdd858ed093e98a743ee7bd4df596cfbf" + integrity sha512-k3zN4jYMi/prWInJILGKOxE+BVcgYinwj9+gcECsYm52tS+4ZKzXQzbPnVJAEXmvKOfFMcDFvS3MSmm6cEaxIQ== dependencies: autocomplete.js "^0.37.0" clsx "^1.2.1" From 079c558bd20a1bb2269b6b929c4d5872fcdfddc6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Nov 2024 11:25:47 +0100 Subject: [PATCH 33/49] Bump cross-spawn from 7.0.3 to 7.0.6 in /docs (#7399) --- docs/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/yarn.lock b/docs/yarn.lock index be41e52be84..1809f741bb4 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -4679,9 +4679,9 @@ cosmiconfig@^8.0.0, cosmiconfig@^8.1.3, cosmiconfig@^8.3.5: path-type "^4.0.0" cross-spawn@^7.0.0, cross-spawn@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== dependencies: path-key "^3.1.0" shebang-command "^2.0.0" From 5437fbc90395bfe4b15d14d8eed37e2f70a4e4b8 Mon Sep 17 00:00:00 2001 From: Muhammad Altabba <24407834+Muhammad-Altabba@users.noreply.github.com> Date: Tue, 19 Nov 2024 11:29:56 +0100 Subject: [PATCH 34/49] fix: upgrade @mdx-js/react from 3.0.1 to 3.1.0 (#7395) --- docs/package.json | 2 +- docs/yarn.lock | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/package.json b/docs/package.json index 620dcb1938a..5f7dff66c8a 100644 --- a/docs/package.json +++ b/docs/package.json @@ -19,7 +19,7 @@ "@docusaurus/core": "^3.5.2", "@docusaurus/preset-classic": "^3.5.2", "@docusaurus/theme-live-codeblock": "^3.5.2", - "@mdx-js/react": "^3.0.0", + "@mdx-js/react": "^3.1.0", "classnames": "^2.3.2", "clsx": "^2.0.0", "docusaurus-lunr-search": "^3.5.0", diff --git a/docs/yarn.lock b/docs/yarn.lock index 1809f741bb4..79d5fb6d6f5 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -2083,6 +2083,13 @@ dependencies: "@types/mdx" "^2.0.0" +"@mdx-js/react@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-3.1.0.tgz#c4522e335b3897b9a845db1dbdd2f966ae8fb0ed" + integrity sha512-QjHtSaoameoalGnKDT3FoIl4+9RwyTmo9ZJGBdLOks/YOiWHoRDI3PUwEzOE7kEmGcV3AFcp9K6dYu9rEuKLAQ== + 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" From 6379aa8afaf22b497c0d960f1a8462bcb1aeff91 Mon Sep 17 00:00:00 2001 From: Kris <605420+krzysu@users.noreply.github.com> Date: Tue, 19 Nov 2024 16:13:59 +0100 Subject: [PATCH 35/49] fix: remove force exit from blackbox tests (#7397) --- packages/web3/test/cjs_black_box/package.json | 4 ++-- packages/web3/test/esm_black_box/package.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/web3/test/cjs_black_box/package.json b/packages/web3/test/cjs_black_box/package.json index e5041d08c1d..a0fcd9a4d7b 100644 --- a/packages/web3/test/cjs_black_box/package.json +++ b/packages/web3/test/cjs_black_box/package.json @@ -7,9 +7,9 @@ "type": "commonjs", "scripts": { "test:geth:http": "WEB3_SYSTEM_TEST_BACKEND=geth WEB3_SYSTEM_TEST_PROVIDER=http://localhost:8545 jest", - "test:geth:ws": "WEB3_SYSTEM_TEST_BACKEND=geth WEB3_SYSTEM_TEST_PROVIDER=ws://localhost:8545 jest --forceExit", + "test:geth:ws": "WEB3_SYSTEM_TEST_BACKEND=geth WEB3_SYSTEM_TEST_PROVIDER=ws://localhost:8545 jest", "test:infura:http": "WEB3_SYSTEM_TEST_BACKEND=infura jest", - "test:infura:ws": "WEB3_SYSTEM_TEST_BACKEND=infura jest --forceExit" + "test:infura:ws": "WEB3_SYSTEM_TEST_BACKEND=infura jest" }, "dependencies": { "web3": "5.0.0" diff --git a/packages/web3/test/esm_black_box/package.json b/packages/web3/test/esm_black_box/package.json index 252793ca6cc..095ac51eb27 100644 --- a/packages/web3/test/esm_black_box/package.json +++ b/packages/web3/test/esm_black_box/package.json @@ -8,9 +8,9 @@ "scripts": { "test:hardhat:http": "WEB3_SYSTEM_TEST_BACKEND=hardhat WEB3_SYSTEM_TEST_PROVIDER=http://localhost:8545 jest", "test:geth:http": "WEB3_SYSTEM_TEST_BACKEND=geth WEB3_SYSTEM_TEST_PROVIDER=http://localhost:8545 jest", - "test:geth:ws": "WEB3_SYSTEM_TEST_BACKEND=geth WEB3_SYSTEM_TEST_PROVIDER=ws://localhost:8545 jest --forceExit", + "test:geth:ws": "WEB3_SYSTEM_TEST_BACKEND=geth WEB3_SYSTEM_TEST_PROVIDER=ws://localhost:8545 jest", "test:infura:http": "WEB3_SYSTEM_TEST_BACKEND=infura jest", - "test:infura:ws": "WEB3_SYSTEM_TEST_BACKEND=infura jest --forceExit" + "test:infura:ws": "WEB3_SYSTEM_TEST_BACKEND=infura jest" }, "dependencies": { "web3": "5.0.0" From 56d4aec22972320bb1a4ac2ce2a9cb88a569a12a Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Tue, 19 Nov 2024 07:27:24 -0800 Subject: [PATCH 36/49] Replaces #7390, #7391, & #7400 (#7401) --- RELEASE.md | 17 +++++----- docs/docs/glossary/index.md | 2 +- .../events_listening.md | 2 +- .../05_smart_contracts/tips_and_tricks.md | 4 +-- .../guides/06_events_subscriptions/index.md | 34 +++++++++---------- 5 files changed, 30 insertions(+), 29 deletions(-) diff --git a/RELEASE.md b/RELEASE.md index 5e2182e995f..1fdcfc3de47 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -36,8 +36,8 @@ Further details about versioning can be found in the [semver 2.0.0 specification - `bumped-version` of release branch should be of main web3 package. 3. `yarn`: Verify all dependencies have been installed 4. Bump packages version numbers using `lerna version --no-push --no-private --no-git-tag-version` . This will update package versions and also run lifecycle scripts. - - It will prompt for new version , modify package metadata and run life cycle scripts (in our case `version`), for bootstrapping lerna will use underlying yarn. -5. Update each package's and also root `CHANGELOG.md`: + - It will prompt for new version , modify package metadata and run lifecycle scripts (in our case `version`), for bootstrapping lerna will use underlying yarn. +5. Update each package's and also root `CHANGELOG.md`: 5.A. If there are any changes in package during release PR e.g. dependency updated that effects package, add entry in changelog under `## [Unreleased]` of that package's changelog. @@ -61,19 +61,20 @@ Further details about versioning can be found in the [semver 2.0.0 specification - In the release description, copy all entries in `CHANGELOG.md` for the version being released - Click `Save draft` - + 12. Open pull request to merge branch created in `Step 2` (`release/bumped-version`) into `4.x` 13. Wait for all tests to pass in github CI/CD , If there are any unusual warnings or errors in logs, discuss with team 14. When sufficient approvals have been met, publish draft release created in `Step 11` 15. Publish on NPM. + - login in NPM and verify you are logged in with right user and in right dir - + - If you want to publish `latest` tag release, run `npx lerna publish from-package --ignore-scripts` in the root directory to publish packages to NPM. - - - If you want to publish any other tag, run `npx lerna publish from-package --ignore-scripts --dist-tag <>` in the root directory e.g. `rc` - + + - If you want to publish any other tag, run `npx lerna publish from-package --ignore-scripts --dist-tag <>` in the root directory e.g. `rc` + IMPORTANT: Replace `<>` with required tag in above command, e.g. if publishing `RC`, use following command: - `npx lerna publish from-package --ignore-scripts --dist-tag rc` + `npx lerna publish from-package --ignore-scripts --dist-tag rc` - lerna will not invoke life cycle scripts before publishing and this will publish all packages to NPM public registry. diff --git a/docs/docs/glossary/index.md b/docs/docs/glossary/index.md index 7af367af75b..4f67ceaa4f6 100644 --- a/docs/docs/glossary/index.md +++ b/docs/docs/glossary/index.md @@ -24,7 +24,7 @@ The `Contract` class is an important class in the `web3-eth-contract` package, a 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. +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. ### Functions diff --git a/docs/docs/guides/02_web3_providers_guide/events_listening.md b/docs/docs/guides/02_web3_providers_guide/events_listening.md index ae0b809d4a5..9b84fa7dcac 100644 --- a/docs/docs/guides/02_web3_providers_guide/events_listening.md +++ b/docs/docs/guides/02_web3_providers_guide/events_listening.md @@ -5,7 +5,7 @@ sidebar_label: 'Providers Events Listening' # Providers Events Listening -Some providers are, by design, always connected. Therefor, they can communicate changes with the user through events. Actually, among the 3 providers, `HttpProvider` is the only one that does not support event. And the other 2: +Some providers are, by design, always connected. Therefore, they can communicate changes with the user through events. Actually, among the 3 providers, `HttpProvider` is the only one that does not support event. And the other 2: [WebSocketProvider](/api/web3-providers-ws/class/WebSocketProvider) and [IpcProvider](/api/web3-providers-ipc/class/IpcProvider) enable the user to listen to emitted events. Actually, the events can be categorized as follows ([according to EIP 1193](https://eips.ethereum.org/EIPS/eip-1193#rationale)): 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 35964550ca5..911dccaa5f0 100644 --- a/docs/docs/guides/05_smart_contracts/tips_and_tricks.md +++ b/docs/docs/guides/05_smart_contracts/tips_and_tricks.md @@ -39,7 +39,7 @@ The Solidity code: pragma solidity >=0.8.20 <0.9.0; -contract TestOverlading { +contract TestOverloading { function funcWithParamsOverloading(uint256 userId) public pure returns (string memory) { return "called for the parameter with the type 'uint256'"; } @@ -138,6 +138,6 @@ Multiple methods found that are compatible with the given inputs. Found 2 compat Future releases of web3.js, specifically version 5.x, will replace the warning with an error whenever multiple methods match a call without explicit overloading. This aims to foster greater precision in method invocation. -### Key Takeaway for function overlading: Method Specification +### Key Takeaway for function overloading: Method Specification When working with overloaded smart contract methods, it's imperative to specify the intended method by appending its parameter types within parentheses, such as `funcWithParamsOverloading(address)` versus `funcWithParamsOverloading(uint256)`. This ensures the accuracy of method invocation, leading to more efficient and clearer contract interactions. diff --git a/docs/docs/guides/06_events_subscriptions/index.md b/docs/docs/guides/06_events_subscriptions/index.md index 80a1457874d..4ecaaafed52 100644 --- a/docs/docs/guides/06_events_subscriptions/index.md +++ b/docs/docs/guides/06_events_subscriptions/index.md @@ -1,6 +1,6 @@ --- sidebar_position: 1 -sidebar_label: 'Mastering Events Subcriptions' +sidebar_label: 'Mastering Events Subscriptions' --- # Events Subscription @@ -46,25 +46,25 @@ If you are the developer who provides custom subscriptions to users. We encourag - `on("data")` - Fires on each incoming log with the log object as argument. ```ts -subcription.on('data', data => console.log(data)); +subscription.on('data', data => console.log(data)); ``` - `on("changed")` - Fires on each log which was removed from the blockchain. The log will have the additional property "removed: true". ```ts -subcription.on('changed', changed => console.log(changed)); +subscription.on('changed', changed => console.log(changed)); ``` - `on("error")` - Fires when an error in the subscription occurs. ```ts -subcription.on('error', error => console.log(error)); +subscription.on('error', error => console.log(error)); ``` - `on("connected")` - Fires once after the subscription successfully connected. Returns the subscription id. ```ts -subcription.on('connected', connected => console.log(connected)); +subscription.on('connected', connected => console.log(connected)); ``` ### Logs @@ -77,11 +77,11 @@ import { Web3 } from 'web3'; const web3 = new Web3('wss://ethereum-rpc.publicnode.com'); async function subscribe() { - //create subcription - const subcription = await web3.eth.subscribe('logs'); + //create subscription + const subscription = await web3.eth.subscribe('logs'); //print logs of the latest mined block - subcription.on('data', data => console.log(data)); + subscription.on('data', data => console.log(data)); } // function to unsubscribe from a subscription @@ -104,11 +104,11 @@ import { Web3 } from 'web3'; const web3 = new Web3('wss://ethereum-rpc.publicnode.com'); async function subscribe() { - //create subcription - const subcription = await web3.eth.subscribe('pendingTransactions'); //or ("newPendingTransactions") + //create subscription + const subscription = await web3.eth.subscribe('pendingTransactions'); //or ("newPendingTransactions") //print tx hashs of pending transactions - subcription.on('data', data => console.log(data)); + subscription.on('data', data => console.log(data)); } // function to unsubscribe from a subscription @@ -131,11 +131,11 @@ import { Web3 } from 'web3'; const web3 = new Web3('wss://ethereum-rpc.publicnode.com'); async function subscribe() { - //create subcription - const subcription = await web3.eth.subscribe('newBlockHeaders'); //or ("newHeads") + //create subscription + const subscription = await web3.eth.subscribe('newBlockHeaders'); //or ("newHeads") //print block header everytime a block is mined - subcription.on('data', data => console.log(data)); + subscription.on('data', data => console.log(data)); } // function to unsubscribe from a subscription @@ -157,12 +157,12 @@ import { Web3 } from 'web3'; const web3 = new Web3('wss://ethereum-rpc.publicnode.com'); async function subscribe() { - //create subcription - const subcription = await web3.eth.subscribe('syncing'); + //create subscription + const subscription = await web3.eth.subscribe('syncing'); //this will return `true` when the node is syncing //when it’s finished syncing will return `false`, for the `changed` event. - subcription.on('data', data => console.log(data)); + subscription.on('data', data => console.log(data)); } // function to unsubscribe from a subscription From 3b122a214a4c16225bbce37c493449fc6d536da1 Mon Sep 17 00:00:00 2001 From: Oleksii Kosynskyi Date: Fri, 22 Nov 2024 03:59:36 +0700 Subject: [PATCH 37/49] fix: upgrade @cookbookdev/docsbot from 4.24.0 to 4.24.4 (#7403) --- docs/package.json | 2 +- docs/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/package.json b/docs/package.json index 5f7dff66c8a..78b14ce26a8 100644 --- a/docs/package.json +++ b/docs/package.json @@ -15,7 +15,7 @@ "typecheck": "tsc" }, "dependencies": { - "@cookbookdev/docsbot": "^4.21.23", + "@cookbookdev/docsbot": "^4.24.4", "@docusaurus/core": "^3.5.2", "@docusaurus/preset-classic": "^3.5.2", "@docusaurus/theme-live-codeblock": "^3.5.2", diff --git a/docs/yarn.lock b/docs/yarn.lock index 79d5fb6d6f5..af39624b139 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -1271,10 +1271,10 @@ resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== -"@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== +"@cookbookdev/docsbot@^4.24.4": + version "4.24.7" + resolved "https://registry.yarnpkg.com/@cookbookdev/docsbot/-/docsbot-4.24.7.tgz#98288b5018e068b1b41a3913fc09c2e48447418c" + integrity sha512-XqEaIBX3iFRQoM5dNm06UVYnBZ19BiV2mw3DWj4RcHtViGuOtRw943/Ab6IJc9cN+tJqE5OV9vb6OQUSttVmiw== dependencies: "@cookbookdev/sonner" "1.5.1" "@headlessui/react" "^1.7.18" From 984cb7cc3649f5aaca498921f4a40f20efde7c08 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:22:18 +0100 Subject: [PATCH 38/49] chore(deps): bump cross-spawn from 7.0.3 to 7.0.6 (#7404) --- yarn.lock | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/yarn.lock b/yarn.lock index a6973e86251..23b071c7071 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4587,9 +4587,9 @@ cross-fetch@^4.0.0: node-fetch "^2.6.12" cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== dependencies: path-key "^3.1.0" shebang-command "^2.0.0" @@ -11882,7 +11882,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== @@ -11900,6 +11900,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" @@ -11955,7 +11964,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== @@ -11969,6 +11978,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" @@ -13081,7 +13097,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== From 7a8df69b8aca8718d4e862955a12c6944a701f6b Mon Sep 17 00:00:00 2001 From: Muhammad Altabba <24407834+Muhammad-Altabba@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:42:57 +0100 Subject: [PATCH 39/49] update typescript version to 5 (#7272) * upgrade typescript to v5 * fix some issues detected by typescript v5 * fix lint issues after the typescript version upgrade --- .gitignore | 3 +- fixtures/utils.ts | 1 + package.json | 2 +- .../web3-account-abstraction/package.json | 2 +- packages/web3-core/package.json | 2 +- .../src/web3_subscription_manager.ts | 1 + .../test/unit/web3_promi_event.test.ts | 2 +- packages/web3-errors/package.json | 2 +- .../web3-errors/src/errors/contract_errors.ts | 1 + packages/web3-eth-abi/package.json | 2 +- packages/web3-eth-abi/src/coders/encode.ts | 2 +- packages/web3-eth-abi/src/utils.ts | 1 + packages/web3-eth-accounts/package.json | 2 +- .../web3-eth-accounts/src/common/common.ts | 13 ++++---- .../web3-eth-accounts/src/common/utils.ts | 11 ++++--- .../src/tx/baseTransaction.ts | 14 ++++---- .../src/tx/eip1559Transaction.ts | 7 ++-- .../src/tx/eip2930Transaction.ts | 7 ++-- .../src/tx/legacyTransaction.ts | 2 +- .../src/tx/transactionFactory.ts | 2 +- packages/web3-eth-accounts/src/tx/types.ts | 2 +- packages/web3-eth-accounts/src/tx/utils.ts | 9 +++--- .../test/unit/common/hardforks.test.ts | 2 +- .../test/unit/common/mergePOS.test.ts | 2 +- .../test/unit/common/timestamp.test.ts | 4 +-- .../test/unit/tx/inputValue.test.ts | 2 +- packages/web3-eth-contract/package.json | 2 +- packages/web3-eth-contract/src/contract.ts | 26 ++++++++------- .../src/contract_log_subscription.ts | 6 ++-- 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-eth/src/rpc_method_wrappers.ts | 12 ++++--- packages/web3-eth/src/utils/decoding.ts | 6 ++-- .../src/utils/reject_if_block_timeout.ts | 2 ++ packages/web3-eth/src/utils/send_tx_helper.ts | 19 ++++++++--- .../web3-eth/src/utils/transaction_builder.ts | 3 +- .../watch_transaction_for_confirmations.ts | 2 +- packages/web3-eth/src/web3_eth.ts | 7 ++-- .../validate_transaction_for_signing.ts | 4 +++ .../web3-eth/test/integration/rpc.test.ts | 4 +-- .../send_transaction.test.ts | 1 + 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-rpc-providers/package.json | 2 +- .../web3-rpc-providers/src/web3_provider.ts | 25 ++++++++++++--- packages/web3-types/package.json | 2 +- packages/web3-types/src/primitives_types.ts | 1 + packages/web3-utils/package.json | 2 +- packages/web3-utils/src/objects.ts | 5 +-- packages/web3-utils/src/validation.ts | 4 +-- .../test/unit/socket_provider.test.ts | 2 +- packages/web3-validator/package.json | 2 +- .../web3-validator/test/unit/utils.test.ts | 2 +- packages/web3/package.json | 2 +- packages/web3/src/web3_eip6963.ts | 32 ++++++++++--------- .../web3/test/benchmark/processingContract.ts | 4 +-- packages/web3/test/e2e/get_block.test.ts | 4 +-- .../web3/test/fixtures/tx-type-15/index.ts | 2 +- scripts/system_tests_utils.ts | 3 +- tools/eslint-config-base-web3/package.json | 2 +- tools/web3-packagetemplate/package.json | 2 +- tools/web3-plugin-example/package.json | 2 +- yarn.lock | 10 +++--- 68 files changed, 191 insertions(+), 131 deletions(-) diff --git a/.gitignore b/.gitignore index 72f88324900..b0c480e7c8f 100644 --- a/.gitignore +++ b/.gitignore @@ -34,6 +34,7 @@ tmp lib/ dist/ tsconfig.tsbuildinfo +tsconfig.types.tsbuildinfo # Unsupported lock files package-lock.json @@ -48,4 +49,4 @@ benchmark-data.txt .eslintcache -.history \ No newline at end of file +.history diff --git a/fixtures/utils.ts b/fixtures/utils.ts index 191aed2138e..18d2a766861 100644 --- a/fixtures/utils.ts +++ b/fixtures/utils.ts @@ -18,6 +18,7 @@ export const processAsync = async ( processFunc: ( resolver: (value: unknown) => void, reject: (value: unknown) => void, + // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents ) => Promise | unknown, ) => new Promise((resolve, reject) => { diff --git a/package.json b/package.json index 8e741afb9f6..a484b558aca 100644 --- a/package.json +++ b/package.json @@ -137,7 +137,7 @@ "typedoc-plugin-markdown": "^3.17.0", "typedoc-plugin-mdn-links": "^2.0.0", "typedoc-plugin-merge-modules": "^5.1.0", - "typescript": "^4.7.4", + "typescript": "^5.5.4", "utf-8-validate": "^5.0.9", "web3-hardhat-plugin": "^1.0.0", "webpack": "^5.73.0", diff --git a/packages/web3-account-abstraction/package.json b/packages/web3-account-abstraction/package.json index a63d42985b6..530f0a09476 100644 --- a/packages/web3-account-abstraction/package.json +++ b/packages/web3-account-abstraction/package.json @@ -53,7 +53,7 @@ "jest-extended": "^3.0.1", "prettier": "^2.7.1", "ts-jest": "^29.1.1", - "typescript": "^4.7.4" + "typescript": "^5.5.4" }, "dependencies": { "web3-core": "^4.7.0", diff --git a/packages/web3-core/package.json b/packages/web3-core/package.json index 67cebb09009..856baa3b5b5 100644 --- a/packages/web3-core/package.json +++ b/packages/web3-core/package.json @@ -68,6 +68,6 @@ "jest-when": "^3.5.1", "prettier": "^2.7.1", "ts-jest": "^29.1.1", - "typescript": "^4.7.4" + "typescript": "^5.5.4" } } diff --git a/packages/web3-core/src/web3_subscription_manager.ts b/packages/web3-core/src/web3_subscription_manager.ts index 8e76498e3c2..754d8e93553 100644 --- a/packages/web3-core/src/web3_subscription_manager.ts +++ b/packages/web3-core/src/web3_subscription_manager.ts @@ -163,6 +163,7 @@ export class Web3SubscriptionManager< const subscription = new Klass(args ?? undefined, { subscriptionManager: this as Web3SubscriptionManager, returnFormat, + // eslint.disable-next-line @typescript-eslint/no-unsafe-any } as any) as InstanceType; await this.addSubscription(subscription); diff --git a/packages/web3-core/test/unit/web3_promi_event.test.ts b/packages/web3-core/test/unit/web3_promi_event.test.ts index 1f597505939..ac4e8b5646f 100644 --- a/packages/web3-core/test/unit/web3_promi_event.test.ts +++ b/packages/web3-core/test/unit/web3_promi_event.test.ts @@ -134,7 +134,7 @@ describe('Web3PromiEvent', () => { }); const f = jest.fn(); - p.finally(f); + await p.finally(f); await p; expect(f).toHaveBeenCalled(); }); diff --git a/packages/web3-errors/package.json b/packages/web3-errors/package.json index c20818ca8a2..17496f4d2cb 100644 --- a/packages/web3-errors/package.json +++ b/packages/web3-errors/package.json @@ -55,6 +55,6 @@ "jest-extended": "^3.0.1", "prettier": "^2.7.1", "ts-jest": "^29.1.1", - "typescript": "^4.7.4" + "typescript": "^5.5.4" } } diff --git a/packages/web3-errors/src/errors/contract_errors.ts b/packages/web3-errors/src/errors/contract_errors.ts index ccd2b7dd46a..85fa96bb43f 100644 --- a/packages/web3-errors/src/errors/contract_errors.ts +++ b/packages/web3-errors/src/errors/contract_errors.ts @@ -150,6 +150,7 @@ export class Eip838ExecutionError extends Web3ContractError { super(error.message || 'Error'); this.name = ('name' in error && error.name) || this.constructor.name; + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing this.stack = ('stack' in error && error.stack) || undefined; this.code = error.code; diff --git a/packages/web3-eth-abi/package.json b/packages/web3-eth-abi/package.json index 02bead98645..8423b96294f 100644 --- a/packages/web3-eth-abi/package.json +++ b/packages/web3-eth-abi/package.json @@ -63,6 +63,6 @@ "jest-when": "^3.5.1", "prettier": "^2.7.1", "ts-jest": "^29.1.1", - "typescript": "^4.7.4" + "typescript": "^5.5.4" } } diff --git a/packages/web3-eth-abi/src/coders/encode.ts b/packages/web3-eth-abi/src/coders/encode.ts index 791c86c827d..1bfb4529220 100644 --- a/packages/web3-eth-abi/src/coders/encode.ts +++ b/packages/web3-eth-abi/src/coders/encode.ts @@ -44,7 +44,7 @@ function inferParamsAbi(params: unknown[]): ReadonlyArray { } as AbiParameter); } else { // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - abi.push({ type: toHex(param as any, true) } as AbiParameter); + abi.push({ type: toHex(param as object, true) } as AbiParameter); } }); return abi; diff --git a/packages/web3-eth-abi/src/utils.ts b/packages/web3-eth-abi/src/utils.ts index 79c15b78d78..df8be81995d 100644 --- a/packages/web3-eth-abi/src/utils.ts +++ b/packages/web3-eth-abi/src/utils.ts @@ -253,6 +253,7 @@ export const flattenTypes = ( * returns a string */ export const jsonInterfaceMethodToString = (json: AbiFragment): string => { + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing if (isAbiErrorFragment(json) || isAbiEventFragment(json) || isAbiFunctionFragment(json)) { if (json.name?.includes('(')) { return json.name; diff --git a/packages/web3-eth-accounts/package.json b/packages/web3-eth-accounts/package.json index afd61cf1549..5efdc5d2547 100644 --- a/packages/web3-eth-accounts/package.json +++ b/packages/web3-eth-accounts/package.json @@ -54,7 +54,7 @@ "jest-when": "^3.5.1", "prettier": "^2.7.1", "ts-jest": "^29.1.1", - "typescript": "^4.7.4", + "typescript": "^5.5.4", "web3-providers-ipc": "^4.0.7" }, "dependencies": { diff --git a/packages/web3-eth-accounts/src/common/common.ts b/packages/web3-eth-accounts/src/common/common.ts index 1569050d2f6..7f1b6aee61e 100644 --- a/packages/web3-eth-accounts/src/common/common.ts +++ b/packages/web3-eth-accounts/src/common/common.ts @@ -190,6 +190,7 @@ export class Common extends EventEmitter { * @returns Common */ public static fromGethGenesis( + // eslint-disable-next-line @typescript-eslint/no-explicit-any genesisJson: any, { chain, eips, genesisHash, hardfork, mergeForkIdPostMerge }: GethConfigOpts, ): Common { @@ -811,9 +812,9 @@ export class Common extends EventEmitter { */ // eslint-disable-next-line @typescript-eslint/ban-types public nextHardforkBlockOrTimestamp(_hardfork?: string | Hardfork): bigint | null { - const hardfork = _hardfork ?? this._hardfork; + const hardfork = (_hardfork as Hardfork) ?? this._hardfork; const hfs = this.hardforks(); - let hfIndex = hfs.findIndex(hf => hf.name === hardfork); + let hfIndex = hfs.findIndex(hf => (hf.name as Hardfork) === hardfork); // If the current hardfork is merge, go one behind as merge hf is not part of these // calcs even if the merge hf block is set if (hardfork === Hardfork.Merge) { @@ -842,7 +843,7 @@ export class Common extends EventEmitter { : // eslint-disable-next-line no-null/no-null null; return ( - hf.name !== Hardfork.Merge && + (hf.name as Hardfork) !== Hardfork.Merge && // eslint-disable-next-line no-null/no-null hfTimeOrBlock !== null && hfTimeOrBlock !== undefined && @@ -873,7 +874,7 @@ export class Common extends EventEmitter { */ // eslint-disable-next-line @typescript-eslint/ban-types public nextHardforkBlock(_hardfork?: string | Hardfork): bigint | null { - const hardfork = _hardfork ?? this._hardfork; + const hardfork = (_hardfork as Hardfork) ?? this._hardfork; let hfBlock = this.hardforkBlock(hardfork); // If this is a merge hardfork with block not set, then we fallback to previous hardfork // to find the nextHardforkBlock @@ -905,7 +906,7 @@ export class Common extends EventEmitter { ); // TypeScript can't seem to follow that the hfBlock is not null at this point // eslint-disable-next-line no-null/no-null - return block > hfBlock! && acc === null ? block : acc; + return block > hfBlock && acc === null ? block : acc; // eslint-disable-next-line no-null/no-null }, null); return nextHfBlock; @@ -951,7 +952,7 @@ export class Common extends EventEmitter { typeof blockOrTime === 'number' && blockOrTime !== 0 && blockOrTime !== prevBlockOrTime && - name !== Hardfork.Merge + (name as Hardfork) !== Hardfork.Merge ) { const hfBlockUint8Array = hexToBytes(blockOrTime.toString(16).padStart(16, '0')); hfUint8Array = uint8ArrayConcat(hfUint8Array, hfBlockUint8Array); diff --git a/packages/web3-eth-accounts/src/common/utils.ts b/packages/web3-eth-accounts/src/common/utils.ts index a1d46c36140..44fcadd9154 100644 --- a/packages/web3-eth-accounts/src/common/utils.ts +++ b/packages/web3-eth-accounts/src/common/utils.ts @@ -71,6 +71,7 @@ const intToHex = function (i: number) { * before merge like in kiln genesis * @returns genesis parameters in a `CommonOpts` compliant object */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any function parseGethParams(json: any, mergeForkIdPostMerge = true) { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const { @@ -83,6 +84,7 @@ function parseGethParams(json: any, mergeForkIdPostMerge = true) { baseFeePerGas, }: { name: string; + // eslint-disable-next-line @typescript-eslint/no-explicit-any config: any; difficulty: string; mixHash: string; @@ -194,7 +196,7 @@ function parseGethParams(json: any, mergeForkIdPostMerge = true) { }, {}); // eslint-disable-next-line @typescript-eslint/no-unsafe-argument const configHardforkNames = Object.keys(config).filter( - // eslint-disable-next-line no-null/no-null, @typescript-eslint/no-unsafe-member-access + // eslint-disable-next-line no-null/no-null, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/prefer-optional-chain key => forkMapRev[key] !== undefined && config[key] !== undefined && config[key] !== null, ); @@ -250,7 +252,7 @@ function parseGethParams(json: any, mergeForkIdPostMerge = true) { // Merge hardfork has to be placed before first hardfork that is dependent on merge const postMergeIndex = params.hardforks.findIndex( // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - (hf: any) => forkMap[hf.name]?.postMerge === true, + hf => forkMap[hf.name]?.postMerge === true, ); if (postMergeIndex !== -1) { params.hardforks.splice(postMergeIndex, 0, mergeConfig as unknown as ConfigHardfork); @@ -272,6 +274,7 @@ function parseGethParams(json: any, mergeForkIdPostMerge = true) { * @param name optional chain name * @returns parsed params */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any export function parseGethGenesis(json: any, name?: string, mergeForkIdPostMerge?: boolean) { try { if (['config', 'difficulty', 'gasLimit', 'alloc'].some(field => !(field in json))) { @@ -282,9 +285,9 @@ export function parseGethGenesis(json: any, name?: string, mergeForkIdPostMerge? json.name = name; } return parseGethParams(json, mergeForkIdPostMerge); - } catch (e: any) { + } catch (e) { // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/restrict-template-expressions - throw new Error(`Error parsing parameters file: ${e.message}`); + throw new Error(`Error parsing parameters file: ${(e as { message: string }).message}`); } } diff --git a/packages/web3-eth-accounts/src/tx/baseTransaction.ts b/packages/web3-eth-accounts/src/tx/baseTransaction.ts index 5762b8889e9..a39b3cd1ffe 100644 --- a/packages/web3-eth-accounts/src/tx/baseTransaction.ts +++ b/packages/web3-eth-accounts/src/tx/baseTransaction.ts @@ -307,7 +307,7 @@ export abstract class BaseTransaction { // Main signature verification is done in `getSenderPublicKey()` const publicKey = this.getSenderPublicKey(); return unpadUint8Array(publicKey).length !== 0; - } catch (e: any) { + } catch (e) { return false; } } @@ -510,6 +510,7 @@ export abstract class BaseTransaction { } } + // eslint-disable-next-line @typescript-eslint/no-explicit-any protected static _validateNotArray(values: { [key: string]: any }) { const txDataKeys = [ 'nonce', @@ -556,19 +557,19 @@ export abstract class BaseTransaction { let hash = ''; try { hash = this.isSigned() ? bytesToHex(this.hash()) : 'not available (unsigned)'; - } catch (e: any) { + } catch (e) { hash = 'error'; } let isSigned = ''; try { isSigned = this.isSigned().toString(); - } catch (e: any) { + } catch (e) { hash = 'error'; } let hf = ''; try { hf = this.common.hardfork(); - } catch (e: any) { + } catch (e) { hf = 'error'; } @@ -603,15 +604,16 @@ export abstract class BaseTransaction { serialized: Uint8Array, // @ts-expect-error unused variable opts: TxOptions = {}, - // eslint-disable-next-line @typescript-eslint/no-empty-function + // eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-explicit-any ): any {} // eslint-disable-next-line @typescript-eslint/no-explicit-any public static fromTxData( // @ts-expect-error unused variable + // eslint-disable-next-line @typescript-eslint/no-explicit-any txData: any, // @ts-expect-error unused variable opts: TxOptions = {}, - // eslint-disable-next-line @typescript-eslint/no-empty-function + // eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-explicit-any ): any {} } diff --git a/packages/web3-eth-accounts/src/tx/eip1559Transaction.ts b/packages/web3-eth-accounts/src/tx/eip1559Transaction.ts index eafb889220a..6b1b3dd3258 100644 --- a/packages/web3-eth-accounts/src/tx/eip1559Transaction.ts +++ b/packages/web3-eth-accounts/src/tx/eip1559Transaction.ts @@ -104,7 +104,10 @@ export class FeeMarketEIP1559Transaction extends BaseTransaction { ? this.common.chainId() : undefined, ); - } catch (e: any) { + } catch (e) { const msg = this._errorMsg('Invalid Signature'); throw new Error(msg); } diff --git a/packages/web3-eth-accounts/src/tx/transactionFactory.ts b/packages/web3-eth-accounts/src/tx/transactionFactory.ts index 7d3305ec59a..c19e512baa8 100644 --- a/packages/web3-eth-accounts/src/tx/transactionFactory.ts +++ b/packages/web3-eth-accounts/src/tx/transactionFactory.ts @@ -36,7 +36,7 @@ const extraTxTypes: Map> = new Map(); // eslint-disable-next-line @typescript-eslint/no-extraneous-class export class TransactionFactory { // It is not possible to instantiate a TransactionFactory object. - // eslint-disable-next-line @typescript-eslint/no-empty-function, no-useless-constructor + // eslint-disable-next-line no-useless-constructor, @typescript-eslint/no-empty-function private constructor() {} public static typeToInt(txType: Numbers) { diff --git a/packages/web3-eth-accounts/src/tx/types.ts b/packages/web3-eth-accounts/src/tx/types.ts index 830c9e7582f..80bf24d757e 100644 --- a/packages/web3-eth-accounts/src/tx/types.ts +++ b/packages/web3-eth-accounts/src/tx/types.ts @@ -206,7 +206,7 @@ export interface FeeMarketEIP1559TxData extends AccessListEIP2930TxData { * The transaction's gas price, inherited from {@link Transaction}. This property is not used for EIP1559 * transactions and should always be undefined for this specific transaction type. */ - // eslint-disable-next-line @typescript-eslint/ban-types + // eslint-disable-next-line @typescript-eslint/ban-types, @typescript-eslint/no-redundant-type-constituents gasPrice?: never | null; /** * The maximum inclusion fee per gas (this fee is given to the miner) diff --git a/packages/web3-eth-accounts/src/tx/utils.ts b/packages/web3-eth-accounts/src/tx/utils.ts index 3b2fabbe4ed..d61350d82fa 100644 --- a/packages/web3-eth-accounts/src/tx/utils.ts +++ b/packages/web3-eth-accounts/src/tx/utils.ts @@ -87,7 +87,7 @@ export const verifyAccessList = (accessList: AccessListUint8Array) => { const address = accessListItem[0]; const storageSlots = accessListItem[1]; // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/consistent-type-assertions - if ((accessListItem)[2] !== undefined) { + if ((>accessListItem)[2] !== undefined) { throw new Error( 'Access list item cannot have 3 elements. It can only have an address, and an array of storage slots.', ); @@ -115,13 +115,12 @@ export const getAccessListJSON = ( const accessListJSON: { address: HexString; storageKeys: HexString[] }[] = []; // eslint-disable-next-line @typescript-eslint/prefer-for-of for (let index = 0; index < accessList.length; index += 1) { - const item: any = accessList[index]; + const item = accessList[index]; const JSONItem: { address: HexString; storageKeys: HexString[] } = { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/consistent-type-assertions - address: bytesToHex(setLengthLeft(item[0], 20)), + address: bytesToHex(setLengthLeft(item[0], 20)), storageKeys: [], }; - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/prefer-optional-chain + // eslint-disable-next-line @typescript-eslint/prefer-optional-chain const storageSlots: Uint8Array[] = item && item[1]; // eslint-disable-next-line @typescript-eslint/prefer-for-of for (let slot = 0; slot < storageSlots.length; slot += 1) { diff --git a/packages/web3-eth-accounts/test/unit/common/hardforks.test.ts b/packages/web3-eth-accounts/test/unit/common/hardforks.test.ts index 78229bf8d4e..aff6e445c78 100644 --- a/packages/web3-eth-accounts/test/unit/common/hardforks.test.ts +++ b/packages/web3-eth-accounts/test/unit/common/hardforks.test.ts @@ -263,7 +263,7 @@ describe('[Common]: Hardfork logic', () => { c = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Shanghai }); // unschedule shanghai on it to test c.hardforks() - .filter(hf => hf.name === Hardfork.Shanghai) + .filter(hf => (hf.name as Hardfork) === Hardfork.Shanghai) // eslint-disable-next-line array-callback-return .map(hf => { // eslint-disable-next-line no-null/no-null, no-param-reassign diff --git a/packages/web3-eth-accounts/test/unit/common/mergePOS.test.ts b/packages/web3-eth-accounts/test/unit/common/mergePOS.test.ts index a2337c58c32..02882a635ca 100644 --- a/packages/web3-eth-accounts/test/unit/common/mergePOS.test.ts +++ b/packages/web3-eth-accounts/test/unit/common/mergePOS.test.ts @@ -247,7 +247,7 @@ describe('[Common]: Merge/POS specific logic', () => { it('should throw if encounters a double ttd hardfork specification', () => { const c = new Common({ chain: Chain.Sepolia }); // Add the ttd to mergeForkIdTransition which occurs post merge in sepolia - c.hardforks().filter(hf => hf.name === 'mergeForkIdTransition')[0]!['ttd'] = + c.hardforks().filter(hf => hf.name === 'mergeForkIdTransition')[0]['ttd'] = '17000000000000000'; expect(() => { c.setHardforkByBlockNumber(1735371); diff --git a/packages/web3-eth-accounts/test/unit/common/timestamp.test.ts b/packages/web3-eth-accounts/test/unit/common/timestamp.test.ts index 6718119c349..47e262adf13 100644 --- a/packages/web3-eth-accounts/test/unit/common/timestamp.test.ts +++ b/packages/web3-eth-accounts/test/unit/common/timestamp.test.ts @@ -60,7 +60,7 @@ describe('[Common]: Timestamp Hardfork logic', () => { it('forkHash', () => { const mainnet = new Common({ chain: Chain.Mainnet }); const hfs = mainnet.hardforks(); - const mergeIndex = hfs.findIndex(hf => hf.name === Hardfork.Merge); + const mergeIndex = hfs.findIndex(hf => (hf.name as Hardfork) === Hardfork.Merge); const hardforks = hfs.slice(0, mergeIndex + 1).concat([ // Add these hardforks as specified here: // https://github.com/ethereum/EIPs/pull/6122/files @@ -100,7 +100,7 @@ describe('[Common]: Timestamp Hardfork logic', () => { it('setForkHashes', () => { const mainnet = new Common({ chain: Chain.Mainnet }); const hfs = mainnet.hardforks(); - const mergeIndex = hfs.findIndex(hf => hf.name === Hardfork.Merge); + const mergeIndex = hfs.findIndex(hf => (hf.name as Hardfork) === Hardfork.Merge); const hardforks = hfs.slice(0, mergeIndex + 1).concat([ // Add these hardforks as specified here: // https://github.com/ethereum/EIPs/pull/6122/files diff --git a/packages/web3-eth-accounts/test/unit/tx/inputValue.test.ts b/packages/web3-eth-accounts/test/unit/tx/inputValue.test.ts index e39ba839775..c5c2b2b80b1 100644 --- a/packages/web3-eth-accounts/test/unit/tx/inputValue.test.ts +++ b/packages/web3-eth-accounts/test/unit/tx/inputValue.test.ts @@ -248,7 +248,7 @@ test('[Invalid Access Lists]', () => { // eslint-disable-next-line @typescript-eslint/no-unsafe-call tx = tx.sign(hexToBytes('42'.repeat(32))); } - } catch (e: any) { + } catch (e) { tx = TransactionFactory.fromTxData({ type: txType }); if (signed) { // eslint-disable-next-line @typescript-eslint/no-unsafe-call diff --git a/packages/web3-eth-contract/package.json b/packages/web3-eth-contract/package.json index 30db5ffc723..3133720681f 100644 --- a/packages/web3-eth-contract/package.json +++ b/packages/web3-eth-contract/package.json @@ -68,7 +68,7 @@ "jest-extended": "^3.0.1", "prettier": "^2.7.1", "ts-jest": "^29.1.1", - "typescript": "^4.7.4", + "typescript": "^5.5.4", "web3-eth-accounts": "^4.3.0", "web3-providers-ws": "^4.0.8" } diff --git a/packages/web3-eth-contract/src/contract.ts b/packages/web3-eth-contract/src/contract.ts index cff3a440bfe..bc0cde9022a 100644 --- a/packages/web3-eth-contract/src/contract.ts +++ b/packages/web3-eth-contract/src/contract.ts @@ -21,6 +21,7 @@ import { Web3PromiEvent, Web3ConfigEvent, Web3SubscriptionManager, + Web3SubscriptionConstructor, } from 'web3-core'; import { ContractExecutionError, @@ -128,9 +129,11 @@ type ContractBoundMethod< Method extends ContractMethod = ContractMethod, > = ( ...args: Abi extends undefined - ? any[] + ? // eslint-disable-next-line @typescript-eslint/no-explicit-any + any[] : Method['Inputs'] extends never - ? any[] + ? // eslint-disable-next-line @typescript-eslint/no-explicit-any + any[] : Method['Inputs'] ) => Method['Abi']['stateMutability'] extends 'payable' | 'pure' ? PayableMethodObject @@ -737,7 +740,7 @@ export class Contract * ``` */ public clone() { - let newContract: Contract; + let newContract: Contract; if (this.options.address) { newContract = new Contract( [...this._jsonInterface, ...this._errorsInterface] as unknown as Abi, @@ -930,12 +933,12 @@ export class Contract param2?: Omit | ReturnFormat, param3?: ReturnFormat, ): Promise<(string | EventLog)[]> { - const eventName = typeof param1 === 'string' ? param1 : ALL_EVENTS; + const eventName: string = typeof param1 === 'string' ? param1 : ALL_EVENTS; const options = // eslint-disable-next-line no-nested-ternary typeof param1 !== 'string' && !isDataFormat(param1) - ? param1 + ? (param1 as Omit) : !isDataFormat(param2) ? param2 : {}; @@ -955,7 +958,7 @@ export class Contract ) as AbiEventFragment & { signature: string }); if (!abi) { - throw new Web3ContractError(`Event ${eventName} not found.`); + throw new Web3ContractError(`Event ${String(eventName)} not found.`); } const { fromBlock, toBlock, topics, address } = encodeEventABI( @@ -1059,11 +1062,11 @@ export class Contract // make constant and payable backwards compatible abi.constant = - abi.stateMutability === 'view' ?? - abi.stateMutability === 'pure' ?? + abi.stateMutability === 'view' || + abi.stateMutability === 'pure' || abi.constant; - abi.payable = abi.stateMutability === 'payable' ?? abi.payable; + abi.payable = abi.stateMutability === 'payable' || abi.payable; this._overloadedMethodAbis.set(abi.name, [ ...(this._overloadedMethodAbis.get(abi.name) ?? []), abi, @@ -1438,10 +1441,11 @@ export class Contract jsonInterface: this._jsonInterface, }, { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment subscriptionManager: this.subscriptionManager as Web3SubscriptionManager< unknown, - any + { + [key: string]: Web3SubscriptionConstructor; + } >, returnFormat, }, diff --git a/packages/web3-eth-contract/src/contract_log_subscription.ts b/packages/web3-eth-contract/src/contract_log_subscription.ts index 8010309c7cb..b1994a81af8 100644 --- a/packages/web3-eth-contract/src/contract_log_subscription.ts +++ b/packages/web3-eth-contract/src/contract_log_subscription.ts @@ -145,8 +145,10 @@ export class ContractLogsSubscription extends Web3Subscription< returnFormat?: DataFormat; }, ) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - super(args, options as any); + super( + args, + options as { subscriptionManager: Web3SubscriptionManager; returnFormat?: DataFormat }, + ); this.address = args.address; this.topics = args.topics; diff --git a/packages/web3-eth-ens/package.json b/packages/web3-eth-ens/package.json index e18474e0140..b509be62457 100644 --- a/packages/web3-eth-ens/package.json +++ b/packages/web3-eth-ens/package.json @@ -55,7 +55,7 @@ "jest-extended": "^3.0.1", "prettier": "^2.7.1", "ts-jest": "^29.1.1", - "typescript": "^4.7.4" + "typescript": "^5.5.4" }, "dependencies": { "@adraffy/ens-normalize": "^1.8.8", diff --git a/packages/web3-eth-iban/package.json b/packages/web3-eth-iban/package.json index 81e65c298b1..b5d1013c396 100644 --- a/packages/web3-eth-iban/package.json +++ b/packages/web3-eth-iban/package.json @@ -53,7 +53,7 @@ "jest-extended": "^3.0.1", "prettier": "^2.7.1", "ts-jest": "^29.1.1", - "typescript": "^4.7.4" + "typescript": "^5.5.4" }, "dependencies": { "web3-errors": "^1.1.3", diff --git a/packages/web3-eth-personal/package.json b/packages/web3-eth-personal/package.json index 2a1f3000308..cee759d16af 100644 --- a/packages/web3-eth-personal/package.json +++ b/packages/web3-eth-personal/package.json @@ -61,7 +61,7 @@ "jest-extended": "^3.0.1", "prettier": "^2.7.1", "ts-jest": "^29.1.1", - "typescript": "^4.7.4", + "typescript": "^5.5.4", "web3-providers-ws": "^4.0.8" } } diff --git a/packages/web3-eth/package.json b/packages/web3-eth/package.json index 6c598d767e7..536bb91aee4 100644 --- a/packages/web3-eth/package.json +++ b/packages/web3-eth/package.json @@ -58,7 +58,7 @@ "jest-extended": "^3.0.1", "prettier": "^2.7.1", "ts-jest": "^29.1.1", - "typescript": "^4.7.4", + "typescript": "^5.5.4", "web3-providers-http": "^4.2.0" }, "dependencies": { diff --git a/packages/web3-eth/src/rpc_method_wrappers.ts b/packages/web3-eth/src/rpc_method_wrappers.ts index 9931c56364f..b8dddb70589 100644 --- a/packages/web3-eth/src/rpc_method_wrappers.ts +++ b/packages/web3-eth/src/rpc_method_wrappers.ts @@ -598,11 +598,13 @@ export function sendTransaction< transaction = await transactionMiddleware.processTransaction(transaction); } - let transactionFormatted: + let transactionFormatted: FormatType< | Transaction | TransactionWithFromLocalWalletIndex | TransactionWithToLocalWalletIndex - | TransactionWithFromAndToLocalWalletIndex = formatTransaction( + | TransactionWithFromAndToLocalWalletIndex, + ReturnFormat + > = formatTransaction( { ...transaction, from: getTransactionFromOrToAttr('from', web3Context, transaction), @@ -612,13 +614,13 @@ export function sendTransaction< { transactionSchema: web3Context.config.customTransactionSchema, }, - ); + ) as FormatType; try { - transactionFormatted = await sendTxHelper.populateGasPrice({ + transactionFormatted = (await sendTxHelper.populateGasPrice({ transaction, transactionFormatted, - }); + })) as FormatType; await sendTxHelper.checkRevertBeforeSending( transactionFormatted as TransactionCall, diff --git a/packages/web3-eth/src/utils/decoding.ts b/packages/web3-eth/src/utils/decoding.ts index f4b61c0a5ac..1f8c33c19ec 100644 --- a/packages/web3-eth/src/utils/decoding.ts +++ b/packages/web3-eth/src/utils/decoding.ts @@ -83,9 +83,9 @@ export const decodeEventABI = ( returnValues: decodeLog([...(modifiedEvent.inputs ?? [])], data.data, argTopics), event: modifiedEvent.name, signature: - modifiedEvent.anonymous || !data.topics || data.topics.length === 0 || !data.topics[0] - ? undefined - : data.topics[0], + !modifiedEvent.anonymous && data.topics?.length > 0 && data.topics[0] + ? data.topics[0] + : undefined, raw: { data: data.data, 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 e3563ca2a1a..72ef1a3bd02 100644 --- a/packages/web3-eth/src/utils/reject_if_block_timeout.ts +++ b/packages/web3-eth/src/utils/reject_if_block_timeout.ts @@ -168,8 +168,10 @@ export async function rejectIfBlockTimeout( (provider as Web3BaseProvider).supportsSubscriptions?.() && web3Context.enableExperimentalFeatures.useSubscriptionWhenCheckingBlockTimeout ) { + // eslint-disable-next-line @typescript-eslint/no-floating-promises callingRes = await resolveBySubscription(web3Context, starterBlockNumber, transactionHash); } else { + // eslint-disable-next-line @typescript-eslint/no-floating-promises callingRes = resolveByPolling(web3Context, starterBlockNumber, transactionHash); } return callingRes; diff --git a/packages/web3-eth/src/utils/send_tx_helper.ts b/packages/web3-eth/src/utils/send_tx_helper.ts index e28b353cda1..75f69ddb0f2 100644 --- a/packages/web3-eth/src/utils/send_tx_helper.ts +++ b/packages/web3-eth/src/utils/send_tx_helper.ts @@ -45,6 +45,7 @@ import { import { ethRpcMethods } from 'web3-rpc-methods'; import { + InternalTransaction, SendSignedTransactionEvents, SendTransactionEvents, SendTransactionOptions, @@ -150,7 +151,12 @@ export class SendTxHelper< public emitSending(tx: TxType | HexString) { if (this.promiEvent.listenerCount('sending') > 0) { - this.promiEvent.emit('sending', tx); + this.promiEvent.emit( + 'sending', + tx as + | SendSignedTransactionEvents['sending'] + | SendTransactionEvents['sending'], + ); } } @@ -174,7 +180,7 @@ export class SendTxHelper< // @TODO gasPrice, maxPriorityFeePerGas, maxFeePerGas // should not be included if undefined, but currently are ...(await getTransactionGasPricing( - transactionFormatted, + transactionFormatted as InternalTransaction, this.web3Context, ETH_DATA_FORMAT, )), @@ -192,7 +198,7 @@ export class SendTxHelper< tx: TxType; }) { if (wallet) { - const signedTransaction = await wallet.signTransaction(tx); + const signedTransaction = await wallet.signTransaction(tx as Transaction); return trySendTransaction( this.web3Context, @@ -216,7 +222,12 @@ export class SendTxHelper< public emitSent(tx: TxType | HexString) { if (this.promiEvent.listenerCount('sent') > 0) { - this.promiEvent.emit('sent', tx); + this.promiEvent.emit( + 'sent', + tx as + | SendSignedTransactionEvents['sent'] + | SendTransactionEvents['sent'], + ); } } public emitTransactionHash(hash: string & Uint8Array) { diff --git a/packages/web3-eth/src/utils/transaction_builder.ts b/packages/web3-eth/src/utils/transaction_builder.ts index 0d459017b4a..c4bc2d88fb4 100644 --- a/packages/web3-eth/src/utils/transaction_builder.ts +++ b/packages/web3-eth/src/utils/transaction_builder.ts @@ -64,7 +64,8 @@ export const getTransactionFromOrToAttr = ( privateKey?: HexString | Uint8Array, ): Address | undefined => { if (transaction !== undefined && attr in transaction && transaction[attr] !== undefined) { - if (typeof transaction[attr] === 'string' && isAddress(transaction[attr] as string)) { + if (typeof transaction[attr] === 'string' && isAddress(transaction[attr])) { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion return transaction[attr] as Address; } if (!isHexStrict(transaction[attr] as string) && isNumber(transaction[attr] as Numbers)) { 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 01ca39f8894..4dd94dd3394 100644 --- a/packages/web3-eth/src/utils/watch_transaction_for_confirmations.ts +++ b/packages/web3-eth/src/utils/watch_transaction_for_confirmations.ts @@ -62,7 +62,7 @@ export function watchTransactionForConfirmations< returnFormat, ), latestBlockHash: format({ format: 'bytes32' }, transactionReceipt.blockHash, returnFormat), - }); + } as Web3PromiEventEventType['confirmation']); // so a subscription for newBlockHeaders can be made instead of polling const provider: Web3BaseProvider = web3Context.requestManager.provider as Web3BaseProvider; diff --git a/packages/web3-eth/src/web3_eth.ts b/packages/web3-eth/src/web3_eth.ts index 6320ff4f524..89d4f1450b4 100644 --- a/packages/web3-eth/src/web3_eth.ts +++ b/packages/web3-eth/src/web3_eth.ts @@ -104,14 +104,17 @@ export class Web3Eth extends Web3Context | Web3ContextInitOptions | string, ) { if ( typeof providerOrContext === 'string' || + // eslint-disable-next-line @typescript-eslint/no-explicit-any isSupportedProvider(providerOrContext as SupportedProviders) ) { // @ts-expect-error disable the error: "A 'super' call must be a root-level statement within a constructor of a derived class that contains initialized properties, parameter properties, or private identifiers." super({ + // eslint-disable-next-line @typescript-eslint/no-explicit-any provider: providerOrContext as SupportedProviders, registeredSubscriptions, }); @@ -1921,8 +1924,8 @@ export class Web3Eth extends Web3Context { this.getPastLogs(args) diff --git a/packages/web3-eth/test/fixtures/validate_transaction_for_signing.ts b/packages/web3-eth/test/fixtures/validate_transaction_for_signing.ts index f22d5ac60cc..3e341cbcc3b 100644 --- a/packages/web3-eth/test/fixtures/validate_transaction_for_signing.ts +++ b/packages/web3-eth/test/fixtures/validate_transaction_for_signing.ts @@ -35,6 +35,7 @@ import { export const invalidTransactionObject: any[] = ['42', false, '0x0', BigInt(42), () => {}]; export const validateCustomChainInfoData: [ + // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents FormatType | any, undefined | MissingCustomChainError | MissingCustomChainIdError | ChainIdMismatchError, ][] = [ @@ -178,6 +179,7 @@ export const validateCustomChainInfoData: [ ]; export const validateChainInfoData: [ + // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents FormatType | any, undefined | CommonOrChainAndHardforkError | MissingChainOrHardforkError, ][] = [ @@ -304,6 +306,7 @@ export const validateChainInfoData: [ ]; export const validateGasData: [ + // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents FormatType | any, ( | undefined @@ -727,6 +730,7 @@ export const validateGasData: [ ]; export const invalidNonceOrChainIdData: [ + // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents FormatType | any, undefined | InvalidNonceOrChainIdError, ][] = [ diff --git a/packages/web3-eth/test/integration/rpc.test.ts b/packages/web3-eth/test/integration/rpc.test.ts index eba6792a2f8..cc4fa2a76f4 100644 --- a/packages/web3-eth/test/integration/rpc.test.ts +++ b/packages/web3-eth/test/integration/rpc.test.ts @@ -380,10 +380,10 @@ describe('rpc', () => { times: 1, }); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const res: TransactionReceipt = (await web3Eth.getTransactionReceipt( + const res: TransactionReceipt = await web3Eth.getTransactionReceipt( // TODO: add more scenarios in future release with block number receipt.transactionHash as string, - ))!; + ); validateReceipt(res); expect(res?.transactionHash).toBe(receipt.transactionHash); }); 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 e9b60f97e74..134910f19f7 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 @@ -66,6 +66,7 @@ describe('sendTransaction', () => { ); if ( + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing sendTransactionOptions?.ignoreGasPricing || !isNullish(inputTransaction.gasPrice) || (!isNullish(inputTransaction.maxPriorityFeePerGas) && diff --git a/packages/web3-net/package.json b/packages/web3-net/package.json index 952457f72be..c1670f15f9f 100644 --- a/packages/web3-net/package.json +++ b/packages/web3-net/package.json @@ -53,7 +53,7 @@ "jest-extended": "^3.0.1", "prettier": "^2.7.1", "ts-jest": "^29.1.1", - "typescript": "^4.7.4" + "typescript": "^5.5.4" }, "dependencies": { "web3-core": "^4.4.0", diff --git a/packages/web3-providers-http/package.json b/packages/web3-providers-http/package.json index c94d24177e8..9e9631108f1 100644 --- a/packages/web3-providers-http/package.json +++ b/packages/web3-providers-http/package.json @@ -57,7 +57,7 @@ "jest-fetch-mock": "^3.0.3", "prettier": "^2.7.1", "ts-jest": "^29.1.1", - "typescript": "^4.7.4" + "typescript": "^5.5.4" }, "dependencies": { "cross-fetch": "^4.0.0", diff --git a/packages/web3-providers-ipc/package.json b/packages/web3-providers-ipc/package.json index 395156d6598..82b2d9aada2 100644 --- a/packages/web3-providers-ipc/package.json +++ b/packages/web3-providers-ipc/package.json @@ -53,7 +53,7 @@ "jest-extended": "^3.0.1", "prettier": "^2.7.1", "ts-jest": "^29.1.1", - "typescript": "^4.7.4" + "typescript": "^5.5.4" }, "dependencies": { "web3-errors": "^1.1.3", diff --git a/packages/web3-providers-ws/package.json b/packages/web3-providers-ws/package.json index 49595cc21df..da21e8db8bb 100644 --- a/packages/web3-providers-ws/package.json +++ b/packages/web3-providers-ws/package.json @@ -58,7 +58,7 @@ "jest-extended": "^3.0.1", "prettier": "^2.7.1", "ts-jest": "^29.1.1", - "typescript": "^4.7.4", + "typescript": "^5.5.4", "web3-providers-http": "^4.1.0" }, "dependencies": { diff --git a/packages/web3-rpc-methods/package.json b/packages/web3-rpc-methods/package.json index 3a05060f2c2..6931807ee1c 100644 --- a/packages/web3-rpc-methods/package.json +++ b/packages/web3-rpc-methods/package.json @@ -53,7 +53,7 @@ "jest-extended": "^3.0.1", "prettier": "^2.7.1", "ts-jest": "^29.1.1", - "typescript": "^4.7.4" + "typescript": "^5.5.4" }, "dependencies": { "web3-core": "^4.4.0", diff --git a/packages/web3-rpc-providers/package.json b/packages/web3-rpc-providers/package.json index 9339d4a3fb3..028c7f49050 100644 --- a/packages/web3-rpc-providers/package.json +++ b/packages/web3-rpc-providers/package.json @@ -54,7 +54,7 @@ "jest-extended": "^3.0.1", "prettier": "^2.7.1", "ts-jest": "^29.1.1", - "typescript": "^4.7.4" + "typescript": "^5.5.4" }, "dependencies": { "web3-errors": "^1.3.0", diff --git a/packages/web3-rpc-providers/src/web3_provider.ts b/packages/web3-rpc-providers/src/web3_provider.ts index 922d8217256..41c5513bbb7 100644 --- a/packages/web3-rpc-providers/src/web3_provider.ts +++ b/packages/web3-rpc-providers/src/web3_provider.ts @@ -141,9 +141,15 @@ export abstract class Web3ExternalProvider< listener: Web3Eip1193ProviderEventCallback, ): void; public once(_type: string, _listener: unknown): void { - if (this.provider?.once) + if (this.provider?.once) { // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - this.provider.once(_type, _listener as any); + this.provider.once( + _type, + _listener as + | Web3Eip1193ProviderEventCallback + | Web3ProviderEventCallback, + ); + } } public removeAllListeners?(_type: string): void { if (this.provider?.removeAllListeners) this.provider.removeAllListeners(_type); @@ -183,7 +189,12 @@ export abstract class Web3ExternalProvider< 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); + this.provider.on( + _type as string, + _listener as + | Web3Eip1193ProviderEventCallback + | Web3ProviderMessageEventCallback, + ); } public removeListener( type: 'disconnect', @@ -207,7 +218,11 @@ export abstract class Web3ExternalProvider< ): 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); + this.provider.removeListener( + _type as string, + _listener as + | Web3Eip1193ProviderEventCallback + | Web3ProviderEventCallback, + ); } } diff --git a/packages/web3-types/package.json b/packages/web3-types/package.json index 31c8f217726..5fa5b7e1da7 100644 --- a/packages/web3-types/package.json +++ b/packages/web3-types/package.json @@ -54,6 +54,6 @@ "jest-extended": "^3.0.1", "prettier": "^2.7.1", "ts-jest": "^29.1.1", - "typescript": "^4.7.4" + "typescript": "^5.5.4" } } diff --git a/packages/web3-types/src/primitives_types.ts b/packages/web3-types/src/primitives_types.ts index 387900e7b66..1150994906b 100644 --- a/packages/web3-types/src/primitives_types.ts +++ b/packages/web3-types/src/primitives_types.ts @@ -15,6 +15,7 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ +// TODO: consider using `0x${string}` instead of `string` for HexString export type HexString = string; export type Bytes = Uint8Array | HexString; export type Numbers = number | bigint | string | HexString; diff --git a/packages/web3-utils/package.json b/packages/web3-utils/package.json index d9c12c25ac8..c49a2929bf6 100644 --- a/packages/web3-utils/package.json +++ b/packages/web3-utils/package.json @@ -60,7 +60,7 @@ "js-sha3": "^0.8.0", "prettier": "^2.7.1", "ts-jest": "^29.1.1", - "typescript": "^4.7.4" + "typescript": "^5.5.4" }, "dependencies": { "ethereum-cryptography": "^2.0.0", diff --git a/packages/web3-utils/src/objects.ts b/packages/web3-utils/src/objects.ts index feda5510e4f..75fe0e81187 100644 --- a/packages/web3-utils/src/objects.ts +++ b/packages/web3-utils/src/objects.ts @@ -48,10 +48,7 @@ export const mergeDeep = ( if (!result[key]) { result[key] = {}; } - result[key] = mergeDeep( - result[key] as Record, - src[key] as Record, - ); + result[key] = mergeDeep(result[key] as Record, src[key]); } else if (!isNullish(src[key]) && Object.hasOwnProperty.call(src, key)) { if (Array.isArray(src[key]) || src[key] instanceof TypedArray) { result[key] = (src[key] as unknown[]).slice(0); diff --git a/packages/web3-utils/src/validation.ts b/packages/web3-utils/src/validation.ts index 57e91aae76d..1cfd4615ea4 100644 --- a/packages/web3-utils/src/validation.ts +++ b/packages/web3-utils/src/validation.ts @@ -134,10 +134,10 @@ export const compareBlockNumbers = (blockA: BlockNumberOrTag, blockB: BlockNumbe ) { return 0; } - if (blockA === 'earliest' && blockB > 0) { + if (blockA === 'earliest') { return -1; } - if (blockB === 'earliest' && blockA > 0) { + if (blockB === 'earliest') { return 1; } diff --git a/packages/web3-utils/test/unit/socket_provider.test.ts b/packages/web3-utils/test/unit/socket_provider.test.ts index 19529f4181a..f65fa4c3a79 100644 --- a/packages/web3-utils/test/unit/socket_provider.test.ts +++ b/packages/web3-utils/test/unit/socket_provider.test.ts @@ -48,7 +48,7 @@ class TestProvider extends SocketProvider { protected _sendToSocket(_payload: Web3APIPayload): void {} // eslint-disable-next-line protected _parseResponses(_event: { data: string } | undefined): JsonRpcResponse[] { - if (!_event || !_event.data) { + if (!_event?.data) { return []; } const returnValues: JsonRpcResponse[] = []; diff --git a/packages/web3-validator/package.json b/packages/web3-validator/package.json index 4a12b604981..bff4e5a7c59 100644 --- a/packages/web3-validator/package.json +++ b/packages/web3-validator/package.json @@ -62,6 +62,6 @@ "jest-extended": "^3.0.1", "prettier": "^2.7.1", "ts-jest": "^29.1.1", - "typescript": "^4.7.4" + "typescript": "^5.5.4" } } diff --git a/packages/web3-validator/test/unit/utils.test.ts b/packages/web3-validator/test/unit/utils.test.ts index eac7d652bbf..fb61c9da776 100644 --- a/packages/web3-validator/test/unit/utils.test.ts +++ b/packages/web3-validator/test/unit/utils.test.ts @@ -107,7 +107,7 @@ describe('utils', () => { it.each(validHexStrictDataWithNumber.map(tuple => [tuple[1], tuple[0]]))( 'valid numbers and bigints', (input, res) => { - expect(numberToHex(input)).toEqual((res as string).toLowerCase()); + expect(numberToHex(input)).toEqual(res.toLowerCase()); }, ); diff --git a/packages/web3/package.json b/packages/web3/package.json index 7e4be7ba12d..8669034a092 100644 --- a/packages/web3/package.json +++ b/packages/web3/package.json @@ -82,7 +82,7 @@ "jest-extended": "^3.0.1", "prettier": "^2.7.1", "ts-jest": "^29.1.1", - "typescript": "^4.7.4", + "typescript": "^5.5.4", "web3-providers-ipc": "^4.0.7" }, "dependencies": { diff --git a/packages/web3/src/web3_eip6963.ts b/packages/web3/src/web3_eip6963.ts index 2e9a2a391f8..368b075d4ec 100644 --- a/packages/web3/src/web3_eip6963.ts +++ b/packages/web3/src/web3_eip6963.ts @@ -63,20 +63,19 @@ export const requestEIP6963Providers = async (): Promise { - eip6963ProvidersMap.set(event.detail.info.uuid, event.detail); - - const newEvent: EIP6963ProvidersMapUpdateEvent = new CustomEvent( - web3ProvidersMapUpdated, - { detail: eip6963ProvidersMap }, - ); - - window.dispatchEvent(newEvent); - resolve(eip6963ProvidersMap); - }, - ); + window.addEventListener(Eip6963EventName.eip6963announceProvider, (( + event: EIP6963AnnounceProviderEvent, + ) => { + eip6963ProvidersMap.set(event.detail.info.uuid, event.detail); + + const newEvent: EIP6963ProvidersMapUpdateEvent = new CustomEvent( + web3ProvidersMapUpdated, + { detail: eip6963ProvidersMap }, + ); + + window.dispatchEvent(newEvent); + resolve(eip6963ProvidersMap); + }) as EventListenerOrEventListenerObject); window.dispatchEvent(new Event(Eip6963EventName.eip6963requestProvider)); }); @@ -89,5 +88,8 @@ export const onNewProviderDiscovered = ( 'window object not available, EIP-6963 is intended to be used within a browser', ); } - window.addEventListener(web3ProvidersMapUpdated as any, callback); + window.addEventListener( + web3ProvidersMapUpdated, + callback as EventListenerOrEventListenerObject, + ); }; diff --git a/packages/web3/test/benchmark/processingContract.ts b/packages/web3/test/benchmark/processingContract.ts index 2f1966cdf04..60311fcc46e 100644 --- a/packages/web3/test/benchmark/processingContract.ts +++ b/packages/web3/test/benchmark/processingContract.ts @@ -14,13 +14,13 @@ 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, ContractOptions } from 'web3-types'; +import { AbiConstructorFragment, AbiFunctionFragment, ContractOptions } from 'web3-types'; // eslint-disable-next-line import { getSendTxParams, getEthTxCallParams } from 'web3-eth-contract'; import { BasicAbi, BasicBytecode } from '../shared_fixtures/build/Basic'; import accounts from '../shared_fixtures/accounts.json'; -const abiConstructor = BasicAbi.find(j => j.type === 'constructor') as AbiFunctionFragment; +const abiConstructor = BasicAbi.find(j => j.type === 'constructor') as AbiConstructorFragment; const abiSendMethod = BasicAbi.find( j => j.type === 'function' && j.name === 'firesMultiValueEvent', ) as AbiFunctionFragment; diff --git a/packages/web3/test/e2e/get_block.test.ts b/packages/web3/test/e2e/get_block.test.ts index 33d78291b36..eb9cd09a50a 100644 --- a/packages/web3/test/e2e/get_block.test.ts +++ b/packages/web3/test/e2e/get_block.test.ts @@ -57,7 +57,7 @@ describe(`${getSystemTestBackend()} tests - getBlock`, () => { | 'blockHash' | 'blockNumber'; hydrated: boolean; - format: string; + format: FMT_NUMBER; }>({ block: ['earliest', 'latest', 'safe', 'finalized', 'blockHash', 'blockNumber'], hydrated: [true, false], @@ -66,7 +66,7 @@ describe(`${getSystemTestBackend()} tests - getBlock`, () => { )('getBlock', async ({ hydrated, block, format }) => { const result = { ...(await web3.eth.getBlock(blockData[block], hydrated, { - number: format as FMT_NUMBER, + number: format, bytes: FMT_BYTES.HEX, })), }; diff --git a/packages/web3/test/fixtures/tx-type-15/index.ts b/packages/web3/test/fixtures/tx-type-15/index.ts index 1d7dd778067..479a5badfab 100644 --- a/packages/web3/test/fixtures/tx-type-15/index.ts +++ b/packages/web3/test/fixtures/tx-type-15/index.ts @@ -400,7 +400,7 @@ export class SomeNewTxTypeTransaction extends BaseTransaction Date: Tue, 26 Nov 2024 09:32:15 +0100 Subject: [PATCH 40/49] chore(deps-dev): bump http-proxy-middleware from 2.0.6 to 2.0.7 (#7407) --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 995a41a404d..e7a13c95870 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7091,9 +7091,9 @@ http-proxy-agent@^5.0.0: debug "4" http-proxy-middleware@^2.0.6: - 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 acdb0c775b885e0411e177a64f0cbd350b90315f Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Tue, 3 Dec 2024 05:18:19 -0800 Subject: [PATCH 41/49] Fixes for Minor Typographical Errors are Not Accepted (#7406) Replaces #7405 --- .github/CONTRIBUTING.md | 21 +++++++++++++------ .github/PULL_REQUEST_TEMPLATE.md | 35 ++++++++++++++++---------------- packages/web3-core/CHANGELOG.md | 8 ++++---- packages/web3-utils/README.md | 2 +- 4 files changed, 38 insertions(+), 28 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 2702e75d4d2..ad7ab9572d2 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -8,35 +8,45 @@ If you face any issues while contributing or want any type of support, we encour ## Prerequisites -- [NodeJS](https://nodejs.org/) (LTS) -- [Yarn](https://yarnpkg.com/) +- [NodeJS](https://nodejs.org/) (LTS) +- [Yarn](https://yarnpkg.com/) ## Contributing to the docs +> [!NOTE] +> Contributions that only address relatively minor typographical errors are not accepted. If you believe you have identified an important typographical error that should be addressed, [please open an Issue](https://github.com/web3/web3.js/issues/new?assignees=&labels=Documentation&projects=&template=issue-template.md&title=[Typo]). + 1. **Fork the docs:** Start by forking our repository to your GitHub account. 2. **Clone the repo:** Clone the forked repository to your local machine using the following command: + ```bash git clone https://github.com/your-username/web3.js.git ``` + 3. **Create a Branch:** Create a new branch for your changes with a descriptive name. - **NOTE: The branch name must include the issue number (if there is no issue created for your contribution, please create one).** + **NOTE: The branch name must include the issue number (if there is no issue created for your contribution, please create one).** + ```bash git checkout -b issue-name-1234 ``` + 4. **Navigate to the docs folder:** `cd web3.js/docs/docs` -5. **Install dependencies:** +5. **Install dependencies:** + ```bash yarn ``` + 6. **Make your changes:**... 7. Check changes in the local environment: Run the command `yarn start` and you'll see a local environment in `localhost:3000` with the documents. -8. **Commit your changes:** `git add .` and `git commit -m 'descriptive msg'` +8. **Commit your changes:** `git add .` and `git commit -m 'descriptive msg'` 9. **Push your changes:** + ```bash git push origin branch-name ``` @@ -96,4 +106,3 @@ Emergency releases are allowed to shorten waiting periods depending on the sever There is precedent set for this in the 1.2.6 release (see [#3351](https://github.com/ethereum/web3.js/pull/3351)), where the consensus view was to make the smallest change necessary to address the emergency while waiving the `rc` process (meaning many existing additions to master were excluded). This topic is under further org-wide discussion at [ethereum/js-organization#6](https://github.com/ethereum/js-organization/issues/6). - diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 7ad07339c5c..b7a527fb7d8 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -11,23 +11,24 @@ Fixes #(issue) -- [ ] Bug fix (non-breaking change which fixes an issue) -- [ ] New feature (non-breaking change which adds functionality) -- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) +- [ ] Bug fix (non-breaking change which fixes an issue) +- [ ] New feature (non-breaking change which adds functionality) +- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) +- [ ] Documentation (changes that only address relatively minor typographical errors are not accepted) ## Checklist: -- [ ] I have selected the correct base branch. -- [ ] I have performed a self-review of my own code. -- [ ] I have commented my code, particularly in hard-to-understand areas. -- [ ] I have made corresponding changes to the documentation. -- [ ] My changes generate no new warnings. -- [ ] Any dependent changes have been merged and published in downstream modules. -- [ ] I ran `npm run lint` with success and extended the tests and types if necessary. -- [ ] I ran `npm run test:unit` with success. -- [ ] I ran `npm run test:coverage` and my test cases cover all the lines and branches of the added code. -- [ ] I ran `npm run build` and tested `dist/web3.min.js` in a browser. -- [ ] I have tested my code on the live network. -- [ ] I have checked the Deploy Preview and it looks correct. -- [ ] I have updated the `CHANGELOG.md` file in the root folder. -- [ ] I have linked Issue(s) with this PR in "Linked Issues" menu. +- [ ] I have selected the correct base branch. +- [ ] I have performed a self-review of my own code. +- [ ] I have commented my code, particularly in hard-to-understand areas. +- [ ] I have made corresponding changes to the documentation. +- [ ] My changes generate no new warnings. +- [ ] Any dependent changes have been merged and published in downstream modules. +- [ ] I ran `npm run lint` with success and extended the tests and types if necessary. +- [ ] I ran `npm run test:unit` with success. +- [ ] I ran `npm run test:coverage` and my test cases cover all the lines and branches of the added code. +- [ ] I ran `npm run build` and tested `dist/web3.min.js` in a browser. +- [ ] I have tested my code on the live network. +- [ ] I have checked the Deploy Preview and it looks correct. +- [ ] I have updated the `CHANGELOG.md` file in the root folder. +- [ ] I have linked Issue(s) with this PR in "Linked Issues" menu. diff --git a/packages/web3-core/CHANGELOG.md b/packages/web3-core/CHANGELOG.md index 06c64e305e9..1cdae319e20 100644 --- a/packages/web3-core/CHANGELOG.md +++ b/packages/web3-core/CHANGELOG.md @@ -123,7 +123,7 @@ Documentation: ### Added -- Web3Subscription constructor accept a Subscription Manager (as an alternative to accepting Request Manager that is now marked marked as deprecated) (#6210) +- Web3Subscription constructor accept a Subscription Manager (as an alternative to accepting Request Manager that is now marked as deprecated) (#6210) ### Changed @@ -185,7 +185,7 @@ Documentation: - defaultTransactionType is now type 0x2 instead of 0x0 (#6282) - Allows formatter to parse large base fee (#6456) -- The package now uses `EventEmitter` from `web3-utils` that works in node envrioment as well as in the browser. (#6398) +- The package now uses `EventEmitter` from `web3-utils` that works in node environment as well as in the browser. (#6398) ### Fixed @@ -205,7 +205,7 @@ Documentation: ### Changed -- Web3config `contractDataInputFill` has been defaulted to `data`, istead of `input`. (#6622) +- Web3config `contractDataInputFill` has been defaulted to `data`, instead of `input`. (#6622) ## [4.4.0] @@ -225,7 +225,7 @@ Documentation: ### Added -- Now when existing packages are added in web3, will be avalible for plugins via context. (#7088) +- Now when existing packages are added in web3, will be available for plugins via context. (#7088) ## [4.5.1] diff --git a/packages/web3-utils/README.md b/packages/web3-utils/README.md index 78cce56e322..45d0fa685be 100644 --- a/packages/web3-utils/README.md +++ b/packages/web3-utils/README.md @@ -11,7 +11,7 @@ This is a sub-package of [web3.js][repo]. -`web3-utils` This contains useful utility functions for Dapp developers. +`web3-utils` contains useful utility functions for Dapp developers. ## Installation From b3ee41788cbec9a29a37415565f8adeb6a295fe5 Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Tue, 3 Dec 2024 05:18:45 -0800 Subject: [PATCH 42/49] Various Typo Fixes (#7413) Replaces #7408, #7409, #7410, and #7411 --- .github/CODE_OF_CONDUCT.md | 38 +++++++++---------- CHANGELOG.md | 2 +- docs/docs/guides/09_web3_config/index.md | 4 +- docs/docs/guides/10_web3_eth/eth.md | 2 +- .../docs/guides/12_web3_utils_module/index.md | 4 +- .../17_migration_from_other_libs/index.md | 2 +- packages/web3-account-abstraction/README.md | 2 +- packages/web3-validator/CHANGELOG.md | 2 +- packages/web3/CHANGELOG.md | 2 +- 9 files changed, 29 insertions(+), 29 deletions(-) diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md index 9ebc3e40d6c..cccc9fc9341 100644 --- a/.github/CODE_OF_CONDUCT.md +++ b/.github/CODE_OF_CONDUCT.md @@ -11,36 +11,36 @@ appearance, race, religion, or sexual identity and orientation. ## Our Standards -Examples of behaviour that contributes to creating a positive environment +Examples of behavior that contributes to creating a positive environment include: -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members +- Using welcoming and inclusive language +- Being respectful of differing viewpoints and experiences +- Gracefully accepting constructive criticism +- Focusing on what is best for the community +- Showing empathy towards other community members -Examples of unacceptable behaviour by participants include: +Examples of unacceptable behavior by participants include: -* The use of sexualized language or imagery and unwelcome sexual attention or - advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic - address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting +- The use of sexualized language or imagery and unwelcome sexual attention or + advances +- Trolling, insulting/derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or electronic + address, without explicit permission +- Other conduct which could reasonably be considered inappropriate in a + professional setting ## Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable -behaviour and are expected to take appropriate and fair corrective action in -response to any instances of unacceptable behaviour. +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or -permanently any contributor for other behaviours that they deem inappropriate, +permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope @@ -73,4 +73,4 @@ available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.ht [homepage]: https://www.contributor-covenant.org For answers to common questions about this code of conduct, see -https://www.contributor-covenant.org/faq \ No newline at end of file +https://www.contributor-covenant.org/faq diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ea32551380..524e83eb8f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2501,7 +2501,7 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3-validator - The JSON schema conversion process now correctly assigns an id when the `abi.name` is not available, for example, in the case of public mappings. (#6981) -- `browser` entry point that was pointing to an non-existing bundle file was removed from `package.json` (#7015) +- `browser` entry point that was pointing to a non-existing bundle file was removed from `package.json` (#7015) #### web3-core diff --git a/docs/docs/guides/09_web3_config/index.md b/docs/docs/guides/09_web3_config/index.md index 3642aad951d..ff1576edfc3 100644 --- a/docs/docs/guides/09_web3_config/index.md +++ b/docs/docs/guides/09_web3_config/index.md @@ -6,7 +6,7 @@ title: '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: +There is list of configuration parameters that can be set to modify the 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) @@ -33,7 +33,7 @@ There is list of configuration params that can be set for modifying behavior of ## 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. +It is possible to modify any of the above-mentioned configuration parameter at the global level when instantiating a `Web3` object, and it will be available to all packages. ```ts import { Web3 } from 'web3'; diff --git a/docs/docs/guides/10_web3_eth/eth.md b/docs/docs/guides/10_web3_eth/eth.md index 5b97adea208..bc63995118f 100644 --- a/docs/docs/guides/10_web3_eth/eth.md +++ b/docs/docs/guides/10_web3_eth/eth.md @@ -674,7 +674,7 @@ async function test() { ## Conclusion -In this tutorial, we learned how to use different methods provied by the `web3-eth` package. +In this tutorial, we learned how to use different methods provided by the `web3-eth` package. With this knowledge, you can start experimenting with the Ethereum blockchain. Keep in mind that this is just the beginning, and there is a lot more to learn about Ethereum and web3.js. So keep exploring and building, and have fun! diff --git a/docs/docs/guides/12_web3_utils_module/index.md b/docs/docs/guides/12_web3_utils_module/index.md index 8a55f7bfe85..7833ffd8a1b 100644 --- a/docs/docs/guides/12_web3_utils_module/index.md +++ b/docs/docs/guides/12_web3_utils_module/index.md @@ -199,7 +199,7 @@ console.log(web3.utils.soliditySha3({ type: 'string', value: 'hello web3' })); console.log(web3.utils.toChecksumAddress('0xa3286628134bad128faeef82f44e99aa64085c94')); // 0xA3286628134baD128faeef82F44e99AA64085C94 -// passing an wrong address +// passing a wrong address console.log(web3.utils.toChecksumAddress('0xa3286628134bad128faeef82f44e99aa64085c9')); // InvalidAddressError: Invalid value given "0xa286628134bad128faeef82f44e99aa64085c94". Error: invalid ethereum address. ``` @@ -246,7 +246,7 @@ console.log(web3.utils.compareBlockNumbers(2, 2)); ### 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. +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 hexadecimal 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: diff --git a/docs/docs/guides/17_migration_from_other_libs/index.md b/docs/docs/guides/17_migration_from_other_libs/index.md index 78e1f48d20c..e39477b49ea 100644 --- a/docs/docs/guides/17_migration_from_other_libs/index.md +++ b/docs/docs/guides/17_migration_from_other_libs/index.md @@ -326,7 +326,7 @@ 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 from the blockchain: const result = await contract.methods.someFunction().call(); // Or, if the method would need a transaction to be sent: const result = await contract.methods.someFunction().send(); diff --git a/packages/web3-account-abstraction/README.md b/packages/web3-account-abstraction/README.md index 61d49413a5e..a70a9aa3fc6 100644 --- a/packages/web3-account-abstraction/README.md +++ b/packages/web3-account-abstraction/README.md @@ -53,7 +53,7 @@ yarn add web3-account-abstraction | 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 +[repo]: https://github.com/web3/web3.js/tree/4.x/packages/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-validator/CHANGELOG.md b/packages/web3-validator/CHANGELOG.md index 8410b156c08..0ef2b96252e 100644 --- a/packages/web3-validator/CHANGELOG.md +++ b/packages/web3-validator/CHANGELOG.md @@ -173,6 +173,6 @@ 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. (#6981) -- `browser` entry point that was pointing to an non-existing bundle file was removed from `package.json` (#7015) +- `browser` entry point that was pointing to a non-existing bundle file was removed from `package.json` (#7015) ## [Unreleased] diff --git a/packages/web3/CHANGELOG.md b/packages/web3/CHANGELOG.md index b1f440e0074..ad452273c60 100644 --- a/packages/web3/CHANGELOG.md +++ b/packages/web3/CHANGELOG.md @@ -316,7 +316,7 @@ Documentation: #### 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) +- `browser` entry point that was pointing to a non-existing bundle file was removed from `package.json` (#7015) #### web3-core From 594f83aa9a39e4c12d182ead45d6150e3361f63c Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 3 Dec 2024 11:55:04 -0500 Subject: [PATCH 43/49] Release/4.16.0 (#7412) * v4.16.0 release * update web3-types * add typescript and version bump to changelogs --- CHANGELOG.md | 61 +++++++++++++++++-- .../web3-account-abstraction/CHANGELOG.md | 2 +- .../web3-account-abstraction/package.json | 10 +-- packages/web3-core/CHANGELOG.md | 6 ++ packages/web3-core/package.json | 10 +-- 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-accounts/CHANGELOG.md | 8 ++- packages/web3-eth-accounts/package.json | 8 +-- 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 | 14 ++--- packages/web3-rpc-providers/CHANGELOG.md | 6 ++ packages/web3-rpc-providers/package.json | 8 +-- packages/web3-types/CHANGELOG.md | 5 +- packages/web3-types/package.json | 2 +- packages/web3-utils/CHANGELOG.md | 8 ++- packages/web3-utils/package.json | 6 +- packages/web3/CHANGELOG.md | 61 ++++++++++++++++++- packages/web3/package.json | 20 +++--- packages/web3/src/version.ts | 2 +- 24 files changed, 225 insertions(+), 64 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 524e83eb8f6..a389b273b58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2792,17 +2792,13 @@ If there are any bugs, improvements, optimizations or any new feature proposal f - `FilterParams` type added (#7353) -#### web3-account-abstraction - -- RC release - ### Fixed #### web3-eth-contracts - Fix Contract methods input param type any[] (#7340) -## [Unreleased] +## [4.16.0] ### Fixed @@ -2813,3 +2809,58 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3-utils - Make `fromWei` return "0" when input is `0` (#7387) + +### Removed + +#### web3-eth-accounts + +- Move signature related types to web3-types. Re-export them for backwards compatibility. (#7374) + +### Added + +#### web3-types + +- Add signature related types. (#7374) +- Updated Typescript version 4 -> 5 (#7272) + +#### web3-eth-accounts + +- Updated Typescript version 4 -> 5 (#7272) + +#### web3 + +- Updated Typescript version 4 -> 5 (#7272) + +#### web3-core + +- Updated Typescript version 4 -> 5 (#7272) + +#### web3-account-abstraction + +- RC release + +#### web3-errors + +- Updated Typescript version 4 -> 5 (#7272) + +#### web3-eth + +- Updated Typescript version 4 -> 5 (#7272) + +#### web3-eth-contract + +- Updated Typescript version 4 -> 5 (#7272) + +#### web3-rpc-providers + +- Updated Typescript version 4 -> 5 (#7272) + +#### web3-utils + +- Updated Typescript version 4 -> 5 (#7272) + +#### web3-eth-abi + +- Updated Typescript version 4 -> 5 (#7272) + +## [Unreleased] diff --git a/packages/web3-account-abstraction/CHANGELOG.md b/packages/web3-account-abstraction/CHANGELOG.md index 03ad474df40..f560e532293 100644 --- a/packages/web3-account-abstraction/CHANGELOG.md +++ b/packages/web3-account-abstraction/CHANGELOG.md @@ -35,7 +35,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 --> -## [0.1.0.rc.0] +## [1.0.0.rc.0] ### Added diff --git a/packages/web3-account-abstraction/package.json b/packages/web3-account-abstraction/package.json index 530f0a09476..2df534a7ad1 100644 --- a/packages/web3-account-abstraction/package.json +++ b/packages/web3-account-abstraction/package.json @@ -1,6 +1,6 @@ { "name": "web3-account-abstraction", - "version": "0.1.0-rc.0", + "version": "1.0.0-rc.0", "description": "Web3 account abstraction package", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -56,10 +56,10 @@ "typescript": "^5.5.4" }, "dependencies": { - "web3-core": "^4.7.0", - "web3-eth-abi": "^4.4.0", - "web3-types": "^1.9.0", - "web3-utils": "^4.3.2", + "web3-core": "^4.7.1", + "web3-eth-abi": "^4.4.1", + "web3-types": "^1.10.0", + "web3-utils": "^4.3.3", "web3-validator": "^2.0.6" } } diff --git a/packages/web3-core/CHANGELOG.md b/packages/web3-core/CHANGELOG.md index 1cdae319e20..546b8bbd9d5 100644 --- a/packages/web3-core/CHANGELOG.md +++ b/packages/web3-core/CHANGELOG.md @@ -245,4 +245,10 @@ Documentation: - Added new property `ignoreGasPricing` to `Web3ConfigOptions`. If `ignoreGasPricing` is true, gasPrice will not be estimated (#7320) +## [4.7.1] + +### Added + +- Updated Typescript version 4 -> 5 (#7272) + ## [Unreleased] diff --git a/packages/web3-core/package.json b/packages/web3-core/package.json index 856baa3b5b5..7fae25e7df1 100644 --- a/packages/web3-core/package.json +++ b/packages/web3-core/package.json @@ -1,6 +1,6 @@ { "name": "web3-core", - "version": "4.7.0", + "version": "4.7.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.3.0", - "web3-eth-accounts": "^4.2.1", + "web3-errors": "^1.3.1", + "web3-eth-accounts": "^4.3.1", "web3-eth-iban": "^4.0.7", "web3-providers-http": "^4.2.0", "web3-providers-ws": "^4.0.8", - "web3-types": "^1.8.1", - "web3-utils": "^4.3.2", + "web3-types": "^1.10.0", + "web3-utils": "^4.3.3", "web3-validator": "^2.0.6" }, "optionalDependencies": { diff --git a/packages/web3-errors/CHANGELOG.md b/packages/web3-errors/CHANGELOG.md index 2bcd592fb2d..a8b64311f08 100644 --- a/packages/web3-errors/CHANGELOG.md +++ b/packages/web3-errors/CHANGELOG.md @@ -184,4 +184,10 @@ Documentation: - Added optional `statusCode` property of response in ResponseError. +## [1.3.1] + +### Added + +- Updated Typescript version 4 -> 5 (#7272) + ## [Unreleased] diff --git a/packages/web3-errors/package.json b/packages/web3-errors/package.json index 17496f4d2cb..c04551af052 100644 --- a/packages/web3-errors/package.json +++ b/packages/web3-errors/package.json @@ -1,6 +1,6 @@ { "name": "web3-errors", - "version": "1.3.0", + "version": "1.3.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.7.0" + "web3-types": "^1.10.0" }, "devDependencies": { "@types/jest": "^28.1.6", diff --git a/packages/web3-eth-abi/CHANGELOG.md b/packages/web3-eth-abi/CHANGELOG.md index 0b9920eca20..06902627018 100644 --- a/packages/web3-eth-abi/CHANGELOG.md +++ b/packages/web3-eth-abi/CHANGELOG.md @@ -200,4 +200,10 @@ Documentation: - added `decodeFunctionCall` and `decodeFunctionReturn`. (#7345) +## [4.4.1] + +### Added + +- Updated Typescript version 4 -> 5 (#7272) + ## [Unreleased] diff --git a/packages/web3-eth-abi/package.json b/packages/web3-eth-abi/package.json index 8423b96294f..5f38242a8e6 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.4.0", + "version": "4.4.1", "description": "Web3 module encode and decode EVM in/output.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -43,9 +43,9 @@ }, "dependencies": { "abitype": "0.7.1", - "web3-errors": "^1.3.0", - "web3-types": "^1.9.0", - "web3-utils": "^4.3.2", + "web3-errors": "^1.3.1", + "web3-types": "^1.10.0", + "web3-utils": "^4.3.3", "web3-validator": "^2.0.6" }, "devDependencies": { diff --git a/packages/web3-eth-accounts/CHANGELOG.md b/packages/web3-eth-accounts/CHANGELOG.md index e707999a1c2..d308595bde8 100644 --- a/packages/web3-eth-accounts/CHANGELOG.md +++ b/packages/web3-eth-accounts/CHANGELOG.md @@ -189,8 +189,14 @@ Documentation: - `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] +## [4.3.1] ### Removed - Move signature related types to web3-types. Re-export them for backwards compatibility. (#7374) + +### Added + +- Updated Typescript version 4 -> 5 (#7272) + +## [Unreleased] diff --git a/packages/web3-eth-accounts/package.json b/packages/web3-eth-accounts/package.json index 5efdc5d2547..b89699410e7 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.3.0", + "version": "4.3.1", "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.3.0", - "web3-types": "^1.9.0", - "web3-utils": "^4.3.2", + "web3-errors": "^1.3.1", + "web3-types": "^1.10.0", + "web3-utils": "^4.3.3", "web3-validator": "^2.0.6" } } diff --git a/packages/web3-eth-contract/CHANGELOG.md b/packages/web3-eth-contract/CHANGELOG.md index 1e7906decf1..9fa8fe2120b 100644 --- a/packages/web3-eth-contract/CHANGELOG.md +++ b/packages/web3-eth-contract/CHANGELOG.md @@ -410,4 +410,10 @@ Documentation: - Fix Contract methods input param type any[] (#7340) +## [4.7.2] + +### Added + +- Updated Typescript version 4 -> 5 (#7272) + ## [Unreleased] diff --git a/packages/web3-eth-contract/package.json b/packages/web3-eth-contract/package.json index 3133720681f..fefccf4aae1 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.1", + "version": "4.7.2", "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.7.0", - "web3-errors": "^1.3.0", - "web3-eth": "^4.11.0", - "web3-eth-abi": "^4.4.0", - "web3-types": "^1.9.0", - "web3-utils": "^4.3.2", + "web3-core": "^4.7.1", + "web3-errors": "^1.3.1", + "web3-eth": "^4.11.1", + "web3-eth-abi": "^4.4.1", + "web3-types": "^1.10.0", + "web3-utils": "^4.3.3", "web3-validator": "^2.0.6" }, "devDependencies": { @@ -69,7 +69,7 @@ "prettier": "^2.7.1", "ts-jest": "^29.1.1", "typescript": "^5.5.4", - "web3-eth-accounts": "^4.3.0", + "web3-eth-accounts": "^4.3.1", "web3-providers-ws": "^4.0.8" } } diff --git a/packages/web3-eth/CHANGELOG.md b/packages/web3-eth/CHANGELOG.md index 36f6fd4b633..75d6b67021e 100644 --- a/packages/web3-eth/CHANGELOG.md +++ b/packages/web3-eth/CHANGELOG.md @@ -295,4 +295,10 @@ Documentation: - `createNewPendingTransactionFilter` , `createNewFilter` , `createNewBlockFilter` , `uninstallFilter` , `getFilterChanges` and `getFilterLogs` are exported from `Web3Eth` and `filtering_rpc_method_wrappers` (#7353) +## [4.11.1] + +### Added + +- Updated Typescript version 4 -> 5 (#7272) + ## [Unreleased] diff --git a/packages/web3-eth/package.json b/packages/web3-eth/package.json index 536bb91aee4..603fbb53ae0 100644 --- a/packages/web3-eth/package.json +++ b/packages/web3-eth/package.json @@ -1,6 +1,6 @@ { "name": "web3-eth", - "version": "4.11.0", + "version": "4.11.1", "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.7.0", - "web3-errors": "^1.3.0", - "web3-eth-abi": "^4.4.0", - "web3-eth-accounts": "^4.3.0", + "web3-core": "^4.7.1", + "web3-errors": "^1.3.1", + "web3-eth-abi": "^4.4.1", + "web3-eth-accounts": "^4.3.1", "web3-net": "^4.1.0", "web3-providers-ws": "^4.0.8", "web3-rpc-methods": "^1.3.0", - "web3-types": "^1.9.0", - "web3-utils": "^4.3.2", + "web3-types": "^1.10.0", + "web3-utils": "^4.3.3", "web3-validator": "^2.0.6" } } diff --git a/packages/web3-rpc-providers/CHANGELOG.md b/packages/web3-rpc-providers/CHANGELOG.md index 4bc16682b31..185818784ce 100644 --- a/packages/web3-rpc-providers/CHANGELOG.md +++ b/packages/web3-rpc-providers/CHANGELOG.md @@ -64,4 +64,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - PublicNodeProvider was added (#7322) +## [1.0.0-rc.4] + +### Added + +- Updated Typescript version 4 -> 5 (#7272) + ## [Unreleased] diff --git a/packages/web3-rpc-providers/package.json b/packages/web3-rpc-providers/package.json index 028c7f49050..affda08aba1 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.3", + "version": "1.0.0-rc.4", "description": "Web3 Providers package", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -57,11 +57,11 @@ "typescript": "^5.5.4" }, "dependencies": { - "web3-errors": "^1.3.0", + "web3-errors": "^1.3.1", "web3-providers-http": "^4.2.0", "web3-providers-ws": "^4.0.8", - "web3-types": "^1.9.0", - "web3-utils": "^4.3.2", + "web3-types": "^1.10.0", + "web3-utils": "^4.3.3", "web3-validator": "^2.0.6" } } diff --git a/packages/web3-types/CHANGELOG.md b/packages/web3-types/CHANGELOG.md index c78df9f3265..6fb34da9926 100644 --- a/packages/web3-types/CHANGELOG.md +++ b/packages/web3-types/CHANGELOG.md @@ -220,8 +220,11 @@ Documentation: - `FilterParams` type added (#7353) -## [Unreleased] +## [1.10.0] #### Added - Add signature related types. (#7374) +- Updated Typescript version 4 -> 5 (#7272) + +## [Unreleased] diff --git a/packages/web3-types/package.json b/packages/web3-types/package.json index 5fa5b7e1da7..375fe3d4fde 100644 --- a/packages/web3-types/package.json +++ b/packages/web3-types/package.json @@ -1,6 +1,6 @@ { "name": "web3-types", - "version": "1.9.0", + "version": "1.10.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 b698fcf51ba..76534484624 100644 --- a/packages/web3-utils/CHANGELOG.md +++ b/packages/web3-utils/CHANGELOG.md @@ -240,8 +240,14 @@ Documentation: - fix `padRight` validation failure on large `uint` (#7265) -## [Unreleased] +## [4.3.3] ### Fixed - Make `fromWei` return "0" when input is `0` (#7387) + +### Added + +- Updated Typescript version 4 -> 5 (#7272) + +## [Unreleased] diff --git a/packages/web3-utils/package.json b/packages/web3-utils/package.json index c49a2929bf6..9bc256403ba 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.2", + "version": "4.3.3", "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.3.0", - "web3-types": "^1.8.1", + "web3-errors": "^1.3.1", + "web3-types": "^1.10.0", "web3-validator": "^2.0.6" } } diff --git a/packages/web3/CHANGELOG.md b/packages/web3/CHANGELOG.md index ad452273c60..3bceff19ce3 100644 --- a/packages/web3/CHANGELOG.md +++ b/packages/web3/CHANGELOG.md @@ -560,10 +560,69 @@ Documentation: - Fix Contract methods input param type any[] (#7340) -## [Unreleased] +## [4.16.0] ### Fixed #### web3 - Export Web3Account, Wallet and signature related types. (#7374) + +#### web3-utils + +- Make `fromWei` return "0" when input is `0` (#7387) + +### Removed + +#### web3-eth-accounts + +- Move signature related types to web3-types. Re-export them for backwards compatibility. (#7374) + +### Added + +#### web3-types + +- Add signature related types. (#7374) +- Updated Typescript version 4 -> 5 (#7272) + +#### web3-eth-accounts + +- Updated Typescript version 4 -> 5 (#7272) + +#### web3 + +- Updated Typescript version 4 -> 5 (#7272) + +#### web3-core + +- Updated Typescript version 4 -> 5 (#7272) + +#### web3-account-abstraction + +- RC release + +#### web3-errors + +- Updated Typescript version 4 -> 5 (#7272) + +#### web3-eth + +- Updated Typescript version 4 -> 5 (#7272) + +#### web3-eth-contract + +- Updated Typescript version 4 -> 5 (#7272) + +#### web3-rpc-providers + +- Updated Typescript version 4 -> 5 (#7272) + +#### web3-utils + +- Updated Typescript version 4 -> 5 (#7272) + +#### web3-eth-abi + +- Updated Typescript version 4 -> 5 (#7272) + +## [Unreleased] diff --git a/packages/web3/package.json b/packages/web3/package.json index 8669034a092..fbb92b9697a 100644 --- a/packages/web3/package.json +++ b/packages/web3/package.json @@ -1,6 +1,6 @@ { "name": "web3", - "version": "4.15.0", + "version": "4.16.0", "description": "Ethereum JavaScript API", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -86,12 +86,12 @@ "web3-providers-ipc": "^4.0.7" }, "dependencies": { - "web3-core": "^4.7.0", - "web3-errors": "^1.3.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-core": "^4.7.1", + "web3-errors": "^1.3.1", + "web3-eth": "^4.11.1", + "web3-eth-abi": "^4.4.1", + "web3-eth-accounts": "^4.3.1", + "web3-eth-contract": "^4.7.2", "web3-eth-ens": "^4.4.0", "web3-eth-iban": "^4.0.7", "web3-eth-personal": "^4.1.0", @@ -99,9 +99,9 @@ "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.3", - "web3-types": "^1.9.0", - "web3-utils": "^4.3.2", + "web3-rpc-providers": "^1.0.0-rc.4", + "web3-types": "^1.10.0", + "web3-utils": "^4.3.3", "web3-validator": "^2.0.6" } } diff --git a/packages/web3/src/version.ts b/packages/web3/src/version.ts index ca906081781..64298450599 100644 --- a/packages/web3/src/version.ts +++ b/packages/web3/src/version.ts @@ -1 +1 @@ -/* eslint-disable header/header */ export const Web3PkgInfo = { version: '4.15.0' }; +/* eslint-disable header/header */ export const Web3PkgInfo = { version: '4.16.0' }; From f41ca32aabdc5169ea85f990a6ff5b1317650364 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 10 Dec 2024 11:14:10 -0500 Subject: [PATCH 44/49] add dist path for minified builds in validator (#7416) * add dist path for minified builds in validator * update changelog --- CHANGELOG.md | 6 ++++++ packages/web3-validator/CHANGELOG.md | 4 ++++ packages/web3-validator/package.json | 1 + 3 files changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a389b273b58..13aa1bcb9eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2864,3 +2864,9 @@ If there are any bugs, improvements, optimizations or any new feature proposal f - Updated Typescript version 4 -> 5 (#7272) ## [Unreleased] + +### Added + +#### web3-validator + +- Add web3-validator dist path for react-native builds (#7416) diff --git a/packages/web3-validator/CHANGELOG.md b/packages/web3-validator/CHANGELOG.md index 0ef2b96252e..2a1af7cfee7 100644 --- a/packages/web3-validator/CHANGELOG.md +++ b/packages/web3-validator/CHANGELOG.md @@ -176,3 +176,7 @@ Documentation: - `browser` entry point that was pointing to a non-existing bundle file was removed from `package.json` (#7015) ## [Unreleased] + +### Added + +- Add web3-validator dist path for react-native builds (#7416) diff --git a/packages/web3-validator/package.json b/packages/web3-validator/package.json index bff4e5a7c59..eacbfd5ddc2 100644 --- a/packages/web3-validator/package.json +++ b/packages/web3-validator/package.json @@ -11,6 +11,7 @@ "require": "./lib/commonjs/index.js" } }, + "./dist/web3-validator.min.js": "./dist/web3-validator.min.js", "repository": "https://github.com/ChainSafe/web3.js", "author": "ChainSafe Systems", "license": "LGPL-3.0", From fa5ce5b46707a1ce63fef9f913ee8b3318bc0382 Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Tue, 10 Dec 2024 08:14:24 -0800 Subject: [PATCH 45/49] Add Documentation for React Native (#7419) * Add Documentation for React Native Closes #7314 * Web3.js Must be Imported as Default Import --- .../18_resources_and_troubleshooting/index.md | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/docs/docs/guides/18_resources_and_troubleshooting/index.md b/docs/docs/guides/18_resources_and_troubleshooting/index.md index 8cf7327d828..e10a0b3f83b 100644 --- a/docs/docs/guides/18_resources_and_troubleshooting/index.md +++ b/docs/docs/guides/18_resources_and_troubleshooting/index.md @@ -44,6 +44,30 @@ Additional Info: [Facebook/React-native Issue #28492](https://github.com/facebook/react-native/issues/28492#issuecomment-824698934) +### TypeError: Cannot read property 'prototype' of undefined, js engine: hermes + +This error occurs when trying to use Web3.js with React Native. To solve this error, use [the `react-native-quick-crypto` package](https://www.npmjs.com/package/react-native-quick-crypto). + +**Resolution Steps:** + +1. Install `react-native-quick-crypto` as a dependency: + +```bash +yarn add react-native-quick-crypto +``` + +2. Set up `react-native-quick-crypto`: + +```bash +cd ios && pod install +``` + +3. Ensure that Web3.js is imported using the default import, as using a named import does not work: + +```bash +import Web3 from 'web3'; +``` + ## Resources ### [Web3.js v4 course](https://www.youtube.com/watch?v=3ZO_t-Kyr1g&list=PLPn3rQCo3XrP4LbQcOyyHQR8McV7w3HZT) From ae994346a656688b8e9b907e1ab4731be8c5736e Mon Sep 17 00:00:00 2001 From: Jasonandjay Date: Thu, 12 Dec 2024 05:25:18 +0800 Subject: [PATCH 46/49] doc: add docs of createContractAddress (#7421) * doc: add docs of createContractAddress * docs: add detail refer to nonce --- packages/web3-eth-contract/src/utils.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/packages/web3-eth-contract/src/utils.ts b/packages/web3-eth-contract/src/utils.ts index 5ef2de6d594..b5f5fc75fbf 100644 --- a/packages/web3-eth-contract/src/utils.ts +++ b/packages/web3-eth-contract/src/utils.ts @@ -227,6 +227,29 @@ export const getCreateAccessListParams = ({ return txParams; }; +/** + * Generates the Ethereum address of a contract created via a regular transaction. + * + * This function calculates the contract address based on the sender's address and nonce, + * following Ethereum's address generation rules. + * + * @param from The sender’s Ethereum {@link Address}, from which the contract will be deployed. + * @param nonce The transaction count (or {@link Numbers}) of the sender account at the time of contract creation. + * You can get it here: https://docs.web3js.org/api/web3/class/Web3Eth#getTransactionCount. + * @returns An Ethereum {@link Address} of the contract in checksum address format. + * @throws An {@link InvalidAddressError} if the provided address ('from') is invalid. + * @throws An {@link InvalidNumberError} if the provided nonce value is not in a valid format. + * @example + * ```ts + * const from = "0x1234567890abcdef1234567890abcdef12345678"; + * const nonce = (await web3.eth.getTransactionCount(from)) + 1; // The nonce value for the transaction + * + * const res = createContractAddress(from, nonce); + * + * console.log(res); + * // > "0x604f1ECbA68f4B4Da57D49C2b945A75bAb331208" + * ``` + */ export const createContractAddress = (from: Address, nonce: Numbers): Address => { if (!isAddress(from)) throw new InvalidAddressError(`Invalid address given ${from}`); From 89976a9b986fd562f85206aab014f65b98f8aa52 Mon Sep 17 00:00:00 2001 From: Junaid <86780488+jdevcs@users.noreply.github.com> Date: Tue, 14 Jan 2025 13:46:16 +0100 Subject: [PATCH 47/49] Ethers Migration guide (#7441) * update codeowners * migration guide * update * updated code owners * doc update * doc update * docs updates --- .github/CODEOWNERS | 2 +- docs/docs/guides/17_migration_ethers/index.md | 345 +++++++++++++ .../17_migration_from_other_libs/index.md | 465 ------------------ docs/docs/guides/18_migration_viem/index.md | 7 + .../index.md | 2 +- .../{19_feedback => 20_feedback}/index.md | 2 +- 6 files changed, 355 insertions(+), 468 deletions(-) create mode 100644 docs/docs/guides/17_migration_ethers/index.md delete mode 100644 docs/docs/guides/17_migration_from_other_libs/index.md create mode 100644 docs/docs/guides/18_migration_viem/index.md rename docs/docs/guides/{18_resources_and_troubleshooting => 19_resources_and_troubleshooting}/index.md (99%) rename docs/docs/guides/{19_feedback => 20_feedback}/index.md (97%) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 116e5513a02..ff423d3e49c 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 @krzysu @danforbes +* @jdevcs @AlexeyKrasnoperov diff --git a/docs/docs/guides/17_migration_ethers/index.md b/docs/docs/guides/17_migration_ethers/index.md new file mode 100644 index 00000000000..33aaad48f3e --- /dev/null +++ b/docs/docs/guides/17_migration_ethers/index.md @@ -0,0 +1,345 @@ +--- +sidebar_label: '🔄 Migration to ethers.js' +title: 'Migration from Web3.js to Ethers.js' +position: 17 +--- + +This guide will help you migrate from web3.js to ethers.js for interacting with the Ethereum blockchain. The guide covers ethers.js v6, providing code examples for both libraries. + +### Installation + +To begin migrating from Web3.js to ethers.js, first install the ethers.js package: + +``` +npm install ethers@6 + +``` + +### Providers Initialization + +When migrating from Web3.js to ethers.js, the first step is to update how you connect to the Ethereum network. Both libraries use providers, but their initialization differs. + +```typescript +import { Web3 } from 'web3'; + +// private RPC endpoint +const web3 = new Web3(providerURL); + +const blockNumber = await web3.eth.getBlockNumber(); +console.log(blockNumber); +``` + +To migrate this to ethers.js, you'll need to replace it with JsonRpcProvider. Note that ethers.js separates provider types more explicitly: + +```typescript +import { ethers } from 'ethers'; + +// ethers.js v6 +const provider = new ethers.JsonRpcProvider(providerURL); + +const blockNumber = await provider.getBlockNumber(); +console.log(blockNumber); +``` + +### Browser-injected Provider + +When migrating browser wallet connections, you'll need to update how you handle the injected provider (like MetaMask). Here's your existing Web3.js code: + +```typescript +const web3 = new Web3(window.ethereum); +``` + +In ethers.js v6, you'll need to use the BrowserProvider class instead. This provider is specifically designed for browser environments: + +```typescript +// in v6 +const provider = new ethers.BrowserProvider(window.ethereum); +``` + +### Wallets and Accounts - Generate Private Key + +If your code generates private keys with Web3.js, here's how to migrate that functionality. Your existing Web3.js code: + +```typescript +// this would generate a private key similar to: +// '0x286f65c4191759fc5c7e6083b8c275ac2238cc7abb5915bd8c905ae4404215c9' +// (Be sure to store it encrypted in a safe place) +const privateKey = web3.eth.accounts.create().privateKey; +``` + +To achieve the same in ethers.js, use the `Wallet.createRandom()` method: + +```typescript +// this would generate a private key similar to: +// '0x286f65c4191759fc5c7e6083b8c275ac2238cc7abb5915bd8c905ae4404215c9' +// (Be sure to store it encrypted in a safe place) +const privateKey = ethers.Wallet.createRandom().privateKey; +``` + +### Wallets and Accounts - Create a wallet + +When migrating wallet creation code, you'll need to change how accounts are added to wallets. Your existing Web3.js code using `wallet.add()`: + +```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, +); + +// outputs: 0x6f7D735dFB514AA1778E8D97EaCE72BfECE71865 +console.log(wallet[0].address); +``` + +In ethers.js, wallet creation uses the Wallet constructor: + +```typescript +const wallet = new ethers.Wallet( + // A private key that you might had generated with: + ethers.Wallet.createRandom().privateKey, + // or explicitly given privateKey +); + +// outputs: 0x6f7D735dFB514AA1778E8D97EaCE72BfECE71865 +console.log(wallet.address); +``` + +### Get Signer account + +When migrating code that gets the current account, you'll need to change from Web3.js's getAccounts(): + +```typescript +const account = (await web3.eth.getAccounts())[0]; +``` + +To ethers.js's getSigner() method, which returns a signer object instead of just an address: + +```typescript +const signer = await provider.getSigner(); +``` + +### Signing + +When migrating message signing functionality, you'll need to update from Web3.js's sign methods: + +```typescript +// Sign with web3.js, using a private key: +const signature = web3.eth.accounts.sign('Some data', privateKey).signature; + +// Sign using an account managed by the connected 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 +); +``` + +In ethers.js, signing is simplified using the signMessage method: + +```typescript +const signer = new ethers.Wallet(privateKey); +const signature = await signer.signMessage('Some data'); +``` + +## Signing and Sending Transactions + +### Sending Transactions + +When migrating transaction sending code, you'll need to update how transactions are signed and sent. Your existing Web3.js code where transactions are signed using an unlocked or added account: + +```typescript +const web3 = new Web3(url); + +// Add wallet to be used as a signer +const wallet = web3.eth.accounts.wallet.add(givenPrivateKey); +const account = wallet[0].address; + +const tx = await web3.eth.sendTransaction({ + from: account, + to: '0x92d3267215Ec56542b985473E73C8417403B15ac', + value: web3.utils.toWei('0.00000000001', 'ether'), +}); +console.log(tx); +``` + +In ethers.js, transactions are sent using a signer instance, which combines the private key and provider: + +```typescript +const signer = new ethers.Wallet(privateKey, provider); + +const tx = await signer.sendTransaction({ + to: '0x92d3267215Ec56542b985473E73C8417403B15ac', + value: ethers.parseUnits('0.001', 'ether'), +}); +console.log(tx); +``` + +### Sending a Signed Transaction + +When migrating code that separates transaction signing and broadcasting, you'll need to update from Web3.js's two-step process: + +```typescript +const transaction = { + from: senderPublicAddress, + to: receiverPublicAddress, + value: 1, + gas: 21000, +}; + +const signedTransaction = await web3.eth.accounts.signTransaction(transaction, privateKey); + +const tx = await web3.eth.sendSignedTransaction(signedTransaction.rawTransaction); + +console.log(tx); +``` + +In ethers.js, you can broadcast a pre-signed transaction using the provider's broadcastTransaction method: + +```typescript +await provider.broadcastTransaction(signedTx); +``` + +## Contracts + +### Contract Deployment + +When migrating contract deployment code, you'll need to update from Web3.js's deploy and send pattern: + +```typescript +const contract = new web3.eth.Contract(abi); +const deployTx = await contract + .deploy({ + data: bytecode, + arguments: ['constructor param'], + }) + .send({ + from: '0x12598d2Fd88B420ED571beFDA8dD112624B5E730', + gas: '1000000', + }); + +console.log('contract address', deployTx.options.address); +``` + +In ethers.js, contract deployment uses the ContractFactory class: + +```typescript +const signer = await provider.getSigner(); +const factory = new ethers.ContractFactory(abi, bytecode, signer); +const contract = await factory.deploy('constructor param'); +console.log('contract address', contract.address); + +// wait for contract creation transaction to be mined +await contract.deployTransaction.wait(); +``` + +### Contract Method Calls + +When migrating contract method calls, you'll need to update from Web3.js's methods object pattern: + +```typescript +const contract = new web3.eth.Contract(ABI, CONTRACT_ADDRESS); + +// For read operations +const result = await contract.methods.someFunction().call(); + +// For write operations +const tx = await contract.methods.someFunction().send(); +``` + +In ethers.js, contract methods are called directly as functions: + +```typescript +const contract = new ethers.Contract(CONTRACT_ADDRESS, ABI, provider); +const result = await contract.someFunction(); +``` + +### Contract Events + +When migrating event handling code, you'll need to update from Web3.js's events interface: + +```typescript +const event = contract.events.SomeEvent({ + filter: { val: 100 }, + fromBlock: 0, +}); + +event.on('data', resolve); +event.on('error', reject); +``` + +In ethers.js, event listening is : + +```typescript +contract.on('SomeEvent', (arg1, arg2, event) => { + // event handling +}); +``` + +### Gas Estimation + +When migrating gas estimation code, you'll need to update from Web3.js's estimateGas method: + +```typescript +const gasAmount = await contract.methods.myMethod(123).estimateGas({ + from: transactionSenderAddress, +}); +``` + +In ethers.js, gas estimation is made through a direct method call: + +```typescript +const gasEstimate = await contract.myMethod.estimateGas(123); +``` + +## Utility methods + +### Hashing + +When migrating code that computes Keccak-256 hashes, you'll need to update from Web3.js's utility methods: + +```typescript +// computes the Keccak-256 hash of the input and returns a hexstring +const hash1 = web3.utils.sha3('hello world'); + +// alternative keccak256 method with broader input support +const hash2 = web3.utils.keccak256('hello world'); +``` + +In ethers.js, hashing requires explicit conversion of strings to bytes: + +```typescript +import { keccak256, toUtf8Bytes } from 'ethers'; + +const message = 'Hello, World!'; +const messageBytes = toUtf8Bytes(message); +const hash = keccak256(messageBytes); +``` + +### Ether Unit Conversion + +When migrating code that converts between ether units, you'll need to update from Web3.js's fromWei and toWei methods: + +```typescript +// Convert Wei to Ether +const fromWeiToEther = web3.utils.fromWei('1000000000000000000', 'ether'); +// outputs: 1 +console.log(fromWeiToEther); + +// Convert Ether to Wei +const fromEtherToWei = web3.utils.toWei('1.0', 'ether'); +// outputs: 1000000000000000000 +console.log(fromEtherToWei); +``` + +In ethers.js, use formatEther and parseEther for common ether conversions: + +```typescript +// Convert Wei to Ether +const fromWeiToEther = ethers.formatEther('1000000000000000000'); +// outputs: 1.0 +console.log(fromWeiToEther); + +// Convert Ether to Wei +const fromEtherToWei = ethers.parseEther('1.0'); +// outputs: 1000000000000000000n +console.log(fromEtherToWei); +``` diff --git a/docs/docs/guides/17_migration_from_other_libs/index.md b/docs/docs/guides/17_migration_from_other_libs/index.md deleted file mode 100644 index e39477b49ea..00000000000 --- a/docs/docs/guides/17_migration_from_other_libs/index.md +++ /dev/null @@ -1,465 +0,0 @@ ---- -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. - -However, migrating from a library to another would usually need careful changes. But, ethers.js have lots of similarities with web3.js and migration would usually be easy and straightforward. However, you still need to check your code for possible tweaks as needed. - -## Installation - -First, install the latest version of web3.js: - -```bash -npm install web3 -``` - -## Providers - -### Initialization and Calling RPC Methods - -With ethers.js, you would get the last block number from a provider like this: - -```typescript -import { ethers } from 'ethers'; - -// in v5: -const provider = new ethers.providers.JsonRpcProvider(url); - -// in v6: -const provider = new ethers.JsonRpcProvider(url); - -const blockNumber = provider.getBlockNumber(); - -// outputs something like: 18561956 -blockNumber.then(console.log); -``` - -With web3.js, you would get the last block number from a provider like this: - -```typescript -import { Web3 } from 'web3'; - -const web3 = new Web3(url); -const blockNumber = web3.eth.getBlockNumber(); - -// outputs something like: 18561956n -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 -}); -// 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 -}); -// the value would like: '18561956' -blockNumber.then(console.log); -``` - -### Use browser-injected provider - -With ethers.js: - -```typescript -// in v5 -const provider = new ethers.providers.Web3Provider(window.ethereum); - -// in v6 -const provider = new ethers.BrowserProvider(window.ethereum); -``` - -With web3.js: - -```typescript -const web3 = new Web3(window.ethereum); -``` - -## Wallets and Accounts - -### Generate Private Key - -With ethers.js: - -```typescript -// this would generate a private key similar to: -// '0x286f65c4191759fc5c7e6083b8c275ac2238cc7abb5915bd8c905ae4404215c9' -// (Be sure to store it encrypted in a safe place) -const privateKey = ethers.Wallet.createRandom().privateKey; -``` - -With web3.js: - -```typescript -// this would generate a private key similar to: -// '0x286f65c4191759fc5c7e6083b8c275ac2238cc7abb5915bd8c905ae4404215c9' -// (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, -); - -// outputs: 0x6f7D735dFB514AA1778E8D97EaCE72BfECE71865 -console.log(wallet.address); -``` - -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, -); - -// outputs: 0x6f7D735dFB514AA1778E8D97EaCE72BfECE71865 -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. - -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 - -With ethers.js: - -```typescript -const signer = await provider.getSigner(); -``` - -With web3.js: - -```typescript -const account = (await web3.eth.getAccounts())[0]; -``` - -### Signing a string message - -with ethers.js: - -```typescript -const signer = new ethers.Wallet(privateKey); - -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; - -// Outputs something like: -// 0xb475e02218d7d6a16f3575de789996d0a57f900f240d73ed792672256d63913840c1da0dd3e7fe2e79485b7a1d81e8cc163f405c3df22d496f28f1dd148faebf1b -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 -); - -// Outputs something like: -// 0xb475e02218d7d6a16f3575de789996d0a57f900f240d73ed792672256d63913840c1da0dd3e7fe2e79485b7a1d81e8cc163f405c3df22d496f28f1dd148faebf1b -console.log(signature); -``` - -## Signing and Sending Transactions - -### Sending Transactions - -Sending a transaction with ethers.js: - -```typescript -const signer = new ethers.Wallet(privateKey, provider); - -const tx = await signer.sendTransaction({ - to: '0x92d3267215Ec56542b985473E73C8417403B15ac', - value: ethers.parseUnits('0.001', 'ether'), -}); -console.log(tx); -``` - -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. - -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. -::: - -```typescript -const web3 = new Web3(url); - -// The method web3.eth.sendTransaction is helpful if you are using a browser-injected provider like metamask. -// Or, if you are using a local dev node like ganache; and you have some accounts already unlocked at the node. -// And this is how you would get the first unlocked account from a local node (not advised for production or even on test node to use unlock accounts on the node). -const account = (await web3.eth.getAccounts())[0]; - -// Alternative to the above, here is how to add wallet to be used as a signer later: -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'), -}); -console.log(tx); -``` - -### Sending a Signed Transactions - -Posting a signed transaction to the node with ethers.js: - -```typescript -// in v5 -provider.sendTransaction(signedTx); - -// in v6 -provider.broadcastTransaction(signedTx); -``` - -With web3.js: - -```typescript -const transaction: Transaction = { - 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 tx = await web3.eth.sendSignedTransaction(signedTransaction.rawTransaction); - -console.log(tx); -``` - -## Contracts - -### Contracts Deployment - -To deploy a contract in ethers.js you might have something like: - -```typescript -const signer = provider.getSigner(); -const factory = new ethers.ContractFactory(abi, bytecode, signer); -const contract = await factory.deploy('constructor param'); -console.log('contract address', contract.address); - -// wait for contract creation transaction to be mined -await contract.deployTransaction.wait(); -``` - -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 - }); - -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/) -::: - -### Calling Contracts' Methods - -To interact with contracts in ethers.js: - -```typescript -const contract = new ethers.Contract(CONTRACT_ADDRESS, ABI, providerOrSigner); -const result = await contract.someFunction(); -``` - -In web3.js: - -```typescript -const web3 = new Web3(provider); -const contract = new web3.eth.Contract(ABI, CONTRACT_ADDRESS); - -// If the method was only to read from the blockchain: -const result = await contract.methods.someFunction().call(); -// Or, if the method would need a transaction to be sent: -const result = await contract.methods.someFunction().send(); -``` - -#### Contracts Overloaded Methods - -In ethers.js: - -```typescript -// ethers -const abi = [ - '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 -// name), the signature must also be specified -message = await contract['getMessage(string)']('nice'); -// and to call the overladed method without a parameter: -message = await contract['getMessage()'](); - -// in v6 -contract.foo(Typed.string('nice')); -``` - -In web3.js: - -```typescript -// 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(); -``` - -### Gas Estimation - -To interact with contracts in ethers.js: - -```typescript -// Estimate the gas -contract.myMethod.estimateGas(123); -``` - -In web3.js: - -```typescript -// Estimate the gas -const gasAmount = await myContract.methods.myMethod(123).estimateGas( - { gas: 5000000, from: transactionSenderAddress }, // optional -); -``` - -### Handling Events - -Handling events with ethers.js: - -```typescript -contract.on('SomeEvent', (arg1, arg2, event) => { - // event handling -}); -``` - -With web3.js: - -```typescript -const event = contract.events.SomeEvent({ - 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. - -With ethers.js: - -```typescript -// hash of a string -ethers.utils.id('hello world'); -// hash of binary data -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 -web3.utils.sha3('hello world'); -// the `utils.keccak256` accepts: string, Uint8Array, Numbers and ReadonlyArray -web3.utils.keccak256('hello world'); -``` - -### Ethers Conversion - -Here is how to convert from and to ether units. - -With ethers.js: - -```typescript -const fromWieToEther = ethers.formatEther('1000000000000000000'); -// outputs: 1.0 -console.log(fromWieToEther); - -const fromEtherToWie = ethers.parseEther('1.0'); -// outputs: 1000000000000000000n -console.log(fromEtherToWie); -``` - -With web3.js: - -```typescript -// the second parameter is 'the unit to convert to' -const fromWieToEther = Web3.utils.fromWei('1000000000000000000', 'ether'); -// outputs: 1 -console.log(fromWieToEther); - -// the second parameter is 'the unit of the number passed' -const fromEtherToWie = Web3.utils.toWei('1.0', 'ether'); -// outputs: 1000000000000000000 -console.log(fromEtherToWie); -``` - -## Conclusion - -This guide should provide a starting point for migrating from ethers.js to web3.js version 4.x. Remember to adapt the example code to your actual use case and verify the function arguments and setup as you migrate your application. And the official documentation of web3.js is your go-to resource for detailed information and updates. diff --git a/docs/docs/guides/18_migration_viem/index.md b/docs/docs/guides/18_migration_viem/index.md new file mode 100644 index 00000000000..e85a40dd999 --- /dev/null +++ b/docs/docs/guides/18_migration_viem/index.md @@ -0,0 +1,7 @@ +--- +sidebar_label: '🔄 Migration to Viem' +title: 'Migration from Web3.js to Viem' +position: 18 +--- + +Coming soon. diff --git a/docs/docs/guides/18_resources_and_troubleshooting/index.md b/docs/docs/guides/19_resources_and_troubleshooting/index.md similarity index 99% rename from docs/docs/guides/18_resources_and_troubleshooting/index.md rename to docs/docs/guides/19_resources_and_troubleshooting/index.md index e10a0b3f83b..119c9420cbc 100644 --- a/docs/docs/guides/18_resources_and_troubleshooting/index.md +++ b/docs/docs/guides/19_resources_and_troubleshooting/index.md @@ -1,5 +1,5 @@ --- -sidebar_position: 18 +sidebar_position: 19 sidebar_label: '📚 Resources & Troubleshooting' --- diff --git a/docs/docs/guides/19_feedback/index.md b/docs/docs/guides/20_feedback/index.md similarity index 97% rename from docs/docs/guides/19_feedback/index.md rename to docs/docs/guides/20_feedback/index.md index 05ae7d90fef..657a293b66a 100644 --- a/docs/docs/guides/19_feedback/index.md +++ b/docs/docs/guides/20_feedback/index.md @@ -1,5 +1,5 @@ --- -sidebar_position: 19 +sidebar_position: 20 sidebar_label: '🗣️ Feedback' --- From bc4a34beb6a1e4e77265daad326cb6093684303d Mon Sep 17 00:00:00 2001 From: Junaid <86780488+jdevcs@users.noreply.github.com> Date: Thu, 16 Jan 2025 13:21:53 +0100 Subject: [PATCH 48/49] viem migration guide (#7444) * viem migration guide * desc * updates * updates * updates --- docs/docs/guides/18_migration_viem/index.md | 258 +++++++++++++++++++- 1 file changed, 257 insertions(+), 1 deletion(-) diff --git a/docs/docs/guides/18_migration_viem/index.md b/docs/docs/guides/18_migration_viem/index.md index e85a40dd999..b4fee378ebd 100644 --- a/docs/docs/guides/18_migration_viem/index.md +++ b/docs/docs/guides/18_migration_viem/index.md @@ -4,4 +4,260 @@ title: 'Migration from Web3.js to Viem' position: 18 --- -Coming soon. +# Migration from Web3.js to Viem + +This guide will help you migrate from Web3.js v4 to Viem v2 for interacting with the Ethereum blockchain. The guide provides code examples for both libraries for transition. + +## Installation + +To begin migrating from Web3.js to Viem, first install the Viem package: + +```bash +npm install viem@2 +``` + +## Providers + +When migrating from Web3.js to Viem, the first step is to update how you connect to the Ethereum network. Both libraries use providers, but their initialization differs. + +```javascript +import Web3 from 'web3'; + +const web3 = new Web3(providerURL); +``` + +To migrate this to Viem, you'll need to replace it with using `createPublicClient()`. This function creates a client for interacting with the Ethereum network. + +```javascript +import { createPublicClient, http } from 'viem'; + +const client = createPublicClient({ transport: http(providerURL) }); +``` + +## Browser-injected Provider + +For browser wallet connections like MetaMask, update how you handle the injected provider. + +```javascript +const web3 = new Web3(window.ethereum); +``` + +To migrate this to Viem, you'll need to use `createWalletClient()` with `custom()` instead of creating a new Web3 instance. + +```javascript +import { createWalletClient, custom } from 'viem'; +import { mainnet } from 'viem/chains'; + +const client = createWalletClient({ + chain: mainnet, + transport: custom(window.ethereum), +}); +``` + +## Wallets and Accounts - Generate Private Key + +If your code generates private keys, here’s how to migrate that functionality. In web3.js if you are using: + +```javascript +const privateKey = web3.eth.accounts.create().privateKey; +console.log(privateKey); +``` + +To migrate this to Viem, you'll use the `generatePrivateKey()` function from the 'viem/accounts' module. + +```javascript +import { generatePrivateKey } from 'viem/accounts'; + +const privateKey = generatePrivateKey(); +console.log(privateKey); +``` + +## Wallets and Accounts - Create a Wallet + +When migrating from Web3.js to Viem, you'll need to update how you create and manage wallets. The process of adding accounts to wallets differs between the two libraries. In web3.js : + +```javascript +const web3 = new Web3(); +const wallet = web3.eth.accounts.wallet.add(privateKey); +console.log(wallet[0].address); +``` + +To migrate this to Viem, you'll use privateKeyToAccount() to create an account, and then can pass it to createWalletClient() for using it with client. + +```javascript +import { createWalletClient, http } from 'viem'; +import { privateKeyToAccount } from 'viem/accounts'; +import { mainnet } from 'viem/chains'; + +const account = privateKeyToAccount(privateKey); + +const client = createWalletClient({ + account, + chain: mainnet, + transport: http(), +}); +``` + +## Signing Messages + +Update how you handle message signing, following is web3.js example: + +```javascript +const signature = web3.eth.accounts.sign('Some data', privateKey).signature; +console.log(signature); +``` + +To sign message using Viem, you can use `signMessage()` method. + +```javascript +import { createWalletClient, custom } from 'viem' +import { mainnet } from 'viem/chains' + +const walletClient = createWalletClient({ + chain: mainnet, + transport: custom(window.ethereum!), +}); + +const [account] = await walletClient.getAddresses(); + +const signature = await walletClient.signMessage({ + account, + message: 'Some data', +}); + +``` + +## Transaction + +When migrating transaction sending code, you'll need to update how transactions are signed and sent. + +```javascript +const tx = await web3.eth.sendTransaction({ + from: account, + to: '0x92d3267215Ec56542b985473E73C8417403B15ac', + value: web3.utils.toWei('0.001', 'ether'), +}); +``` + +In Viem there is `sendTransaction()` function avalible with walletClient. + +```javascript +import { createWalletClient, custom, parseEther } from 'viem' +import { mainnet } from 'viem/chains' + +const walletClient = createWalletClient({ + chain: mainnet, + transport: custom(window.ethereum!), +}); + +const [account] = await walletClient.getAddresses(); + +const hash = await walletClient.sendTransaction({ + account, + to: '0x92d3267215Ec56542b985473E73C8417403B15ac', + value: parseEther('0.001') +}); + +``` + +## Contracts + +### Contract Deployment + +When migrating contract deployment code, you'll need to update from Web3.js's deploy and send pattern: + +```javascript +// use existing web3 instance connected with provider +const contract = new web3.eth.Contract(abi); +const deployTx = await contract + .deploy({ + data: bytecode, + arguments: ['constructor param'], + }) + .send({ + from: account, + gas: '1000000', + }); +console.log(deployTx.options.address); +``` + +In Viem there is `deployContract()` function that can be used for contracts deployment. + +```javascript +//import { deployContract } from 'viem' +import { createWalletClient, custom } from 'viem'; +import { mainnet } from 'viem/chains'; + +const walletClient = createWalletClient({ + chain: mainnet, + transport: custom(window.ethereum), +}); + +const hash = await walletClient.deployContract({ + abi, + account, //given account + args: ['constructor param'], + bytecode: bytecode, +}); +``` + +### Contract Method Calls + +When migrating contract method calls, you'll need to update from Web3.js's `contract.methods.someFunction().call()` + +```javascript +const contract = new web3.eth.Contract(ABI, CONTRACT_ADDRESS); +const result = await contract.methods.someFunction().call(); +console.log(result); +``` + +In Viem `readContract()` function can be used for method calls. + +```javascript +const data = await publicClient.readContract({ + address: '0x92d3267215Ec56542b985473E73C8417403B15ac', + abi: wagmiAbi, + functionName: 'tokenTotalSupply', +}); +``` + +### Contract Events + +When migrating event handling code, you'll need to update from Web3.js's events code : + +```javascript +const event = contract.events.SomeEvent({ fromBlock: 0 }); +event.on('data', resolve); +event.on('error', reject); +``` + +In Viem there is `watchContractEvent()` function. + +```javascript +const unwatch = publicClient.watchContractEvent({ + address: '0x92d3267215Ec56542b985473E73C8417403B15ac', + abi: wagmiAbi, + eventName: 'Transfer', + args: { from: '0x34d3267215Ec56542b985473E73C8417403B1533' }, + onLogs: logs => func(logs), +}); +``` + +## Utility Methods + +### Hashing + +When migrating code that computes Keccak-256 hashes, you'll need to update from Web3.js's utility method: + +``` +// keccak256 method with broader input support in web3.js +const hash = web3.utils.keccak256('hello world'); +``` + +In Viem there is `keccak256()` function for keccak256. + +``` +import { keccak256 , toHex } from 'viem' + +keccak256(toHex('hello world')); +``` From bf1691765bd9d4b0f7a4479e915207707d69226d Mon Sep 17 00:00:00 2001 From: Junaid <86780488+jdevcs@users.noreply.github.com> Date: Fri, 17 Jan 2025 14:24:32 +0100 Subject: [PATCH 49/49] disclaimer msgs (#7446) * readme update * docs update --- README.md | 2 ++ docs/docs/guides/01_getting_started/introduction.md | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/README.md b/README.md index 3284ef04f23..1caa1dd5e55 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ # Web3.js +### Web3.js libraries are being sunset on March 4th, 2025. For migration guides and more details please refer to [Chainsafe blog](https://blog.chainsafe.io/web3-js-sunset/) + [![Dependency Status][downloads-image]][npm-url] ![Unit Test Coverage](https://img.shields.io/codecov/c/github/web3/web3.js/4.x?label=unit%20test%20coverage) ![Commit Activity](https://img.shields.io/github/commit-activity/m/web3/web3.js/4.x?label=commit%20activity%20on%204.x) ![Contributors](https://img.shields.io/github/contributors/web3/web3.js?label=contributors%20on%20all%20branches) diff --git a/docs/docs/guides/01_getting_started/introduction.md b/docs/docs/guides/01_getting_started/introduction.md index d8838984205..bfd5e6465ba 100644 --- a/docs/docs/guides/01_getting_started/introduction.md +++ b/docs/docs/guides/01_getting_started/introduction.md @@ -6,6 +6,12 @@ sidebar_label: Introduction # Introduction +:::warning + +Web3.js libraries are being sunset on March 4th, 2025. For migration guides and more details please refer to [Chainsafe blog](https://blog.chainsafe.io/web3-js-sunset/) + +::: + 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/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.