diff --git a/.gitignore b/.gitignore index ee07ced40..816bf92c1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,18 +1,18 @@ packages/subgraph/subgraph.yaml packages/subgraph/generated -packages/subgraph/abis +packages/subgraph/abis/* packages/hardhat/*.txt **/aws.json # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. **/node_modules -packages/hardhat/artifacts +packages/hardhat/artifacts* packages/hardhat/deployments packages/react-app/src/contracts/* -!packages/react-app/src/contracts/contracts.js -packages/hardhat/cache +!packages/react-app/src/contracts/external_contracts.js +packages/hardhat/cache* -docker/**/data +packages/**/data packages/subgraph/config/config.json tenderly.yaml diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..592fcfa19 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,8 @@ +[submodule "packages/services/arbitrum"] + path = packages/services/arbitrum + url = https://github.com/OffchainLabs/arbitrum + branch = master +[submodule "packages/services/optimism"] + path = packages/services/optimism + url = https://github.com/ethereum-optimism/optimism + branch = regenesis/0.4.0 diff --git a/README.md b/README.md index fdd91c18d..df0422211 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,9 @@ # ๐Ÿ— scaffold-eth -> is everything you need to get started building decentralized applications on Ethereum! ๐Ÿš€ +> is everything you need to get started building decentralized applications on Ethereum! ๐Ÿš€ --- - #### [ ๐Ÿƒโ€โ™€๏ธ Quick Start ](https://github.com/austintgriffith/scaffold-eth#%EF%B8%8F-quick-start) #### [ ๐Ÿ”ญ Learning Solidity ](https://github.com/austintgriffith/scaffold-eth#-learning-solidity) @@ -12,22 +11,26 @@ #### [ ๐Ÿ“ก Deploy ](https://github.com/austintgriffith/scaffold-eth#-deploy) #### [ ๐Ÿ“บ Frontend](https://github.com/austintgriffith/scaffold-eth#-frontend) + - [ ๐Ÿ›ฐ Providers ](https://github.com/austintgriffith/scaffold-eth#-providers) - [ ๐Ÿ–‡ Hooks ](https://github.com/austintgriffith/scaffold-eth#-hooks) - [ ๐Ÿ“ฆ Components ](https://github.com/austintgriffith/scaffold-eth#-components) - [ ๐Ÿ–ฒ UI Library ](https://github.com/austintgriffith/scaffold-eth#-ui-library) - [ โ›‘ Helpers ](https://github.com/austintgriffith/scaffold-eth#-helpers) - [ ๐ŸŽš Extras ](https://github.com/austintgriffith/scaffold-eth#-extras) -- [ ๐Ÿ›ณ Ship it! ](https://github.com/austintgriffith/scaffold-eth#-ship-it) +- [ ๐Ÿ›ณ Ship it! ](https://github.com/austintgriffith/scaffold-eth#-ship-it) #### [ ๐Ÿšฉ Challenges ](https://github.com/austintgriffith/scaffold-eth#-challenges) + - [ ๐Ÿฅฉ Staking App](https://github.com/austintgriffith/scaffold-eth/tree/challenge-1-decentralized-staking) - [ ๐Ÿต Token Vendor ](https://github.com/austintgriffith/scaffold-eth/tree/challenge-2-token-vendor) #### [ ๐Ÿ‘ฉโ€๐Ÿ’ป Examples & Tutorials ](https://github.com/austintgriffith/scaffold-eth#-examples-and-tutorials) + - [ ๐ŸŽŸ Simple NFT ](https://github.com/austintgriffith/scaffold-eth/tree/simple-nft-example) #### [ Built with ๐Ÿ— scaffold-eth ](https://github.com/austintgriffith/scaffold-eth#-built-with--scaffold-eth) + - [ ๐ŸŽจ Nifty.ink ](https://nifty.ink) ([code](https://github.com/austintgriffith/scaffold-eth/tree/nifty-ink-dev)) - [ ๐Ÿง‘โ€๐ŸŽคPunkWallet.io ](https://punkwallet.io/) ([code](https://github.com/austintgriffith/scaffold-eth/tree/punk-wallet)) @@ -37,27 +40,26 @@ - [ ๐Ÿ”ฌ Tenderly ](https://github.com/austintgriffith/scaffold-eth#-using-tenderly) - [ ๐ŸŒ Etherscan ](https://github.com/austintgriffith/scaffold-eth#-etherscan) - [ ๐Ÿ”ถ Infura ](https://github.com/austintgriffith/scaffold-eth#-using-infura) -- ๐ŸŸช [ Blocknative ](https://github.com/austintgriffith/scaffold-eth#-blocknative) +- ๐ŸŸช [ Blocknative ](https://github.com/austintgriffith/scaffold-eth#-blocknative) -|- [ ๐Ÿ“  Legacy Content ](https://github.com/austintgriffith/scaffold-eth#-legacy-content) - | - [ ๐Ÿ’ฌ Support Chat ](https://github.com/austintgriffith/scaffold-eth#-support-chat) -| +|- [ ๐Ÿ“  Legacy Content ](https://github.com/austintgriffith/scaffold-eth#-legacy-content) - | - [ ๐Ÿ’ฌ Support Chat ](https://github.com/austintgriffith/scaffold-eth#-support-chat) -| [![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/austintgriffith/scaffold-eth) - --- [![ethdenvervideo](https://user-images.githubusercontent.com/2653167/109873369-e2c58c00-7c2a-11eb-8adf-0ec4b8dcae1e.png)](https://youtu.be/33gnKe7ttCc?t=477) - --- + --- + --- # ๐Ÿƒโ€โ™€๏ธ Quick Start required: [Node](https://nodejs.org/dist/latest-v12.x/) plus [Yarn](https://classic.yarnpkg.com/en/docs/install/) and [Git](https://git-scm.com/downloads) - ```bash git clone https://github.com/austintgriffith/scaffold-eth.git cd scaffold-eth @@ -83,7 +85,7 @@ yarn deploy ๐Ÿ“ Edit your frontend `App.jsx` in `packages/react-app/src` -๐Ÿ’ผ Edit your deployment script `deploy.js` in `packages/hardhat/scripts` +๐Ÿ’ผ Edit and add your deployment scripts in `packages/hardhat/deploy` - we are using [hardhat-deploy](https://www.npmjs.com/package/hardhat-deploy) ๐Ÿ“ฑ Open http://localhost:3000 to see the app @@ -93,37 +95,26 @@ yarn deploy ๐Ÿงช It is a free standing dapp so you can learn by making small changes. - -> *After installing*, your dev environment should look like this: +> _After installing_, your dev environment should look like this: ![image](https://user-images.githubusercontent.com/2653167/109870279-24ecce80-7c27-11eb-91f3-b2c4febac118.png) - > React dev server, HardHat blockchain, deploy terminal, code IDE, and frontend browser. โœ๏ธ Make small changes to `YourContract.sol` and watch your app auto update! - ๐Ÿ” You can `yarn deploy` any time and get a fresh new contract in the frontend: - ![deploy](https://user-images.githubusercontent.com/2653167/93149199-f8fa8280-f6b2-11ea-9da7-3b26413ec8ab.gif) - -๐Ÿ’ต Each browser has an account in the top right and you can use the faucet (bottom left) to get โ›ฝ๏ธ testnet eth for gas: - +๐Ÿ’ต Each browser has an account in the top right and you can use the faucet (bottom left) to get โ›ฝ๏ธ testnet eth for gas: ![faucet](https://user-images.githubusercontent.com/2653167/93150077-6c04f880-f6b5-11ea-9ee8-5c646b5b7afc.gif) - - - ๐Ÿ”จOnce you have funds, you can call `setPurpose` on your contract and "write" to the `purpose` storage: - ![setp](https://user-images.githubusercontent.com/2653167/93229761-2d625300-f734-11ea-9036-44a75429ef0c.gif) - Look for the [HardHat](https://hardhat.org) console.log() output in the `yarn chain` terminal: ![image](https://user-images.githubusercontent.com/2653167/93687934-2f534b80-fa7f-11ea-84b2-c0ba99533dc2.png) @@ -135,6 +126,7 @@ Look for the [HardHat](https://hardhat.org) console.log() output in the `yarn ch ===================================================== [โซ back to the top โซ](https://github.com/austintgriffith/scaffold-eth#-scaffold-eth) --- + --- # ๐Ÿ”ญ Learning Solidity @@ -160,8 +152,7 @@ Look for the [HardHat](https://hardhat.org) console.log() output in the `yarn ch ![image](https://user-images.githubusercontent.com/2653167/93150263-dae25180-f6b5-11ea-94e1-b24ab2a63fa5.png) - -๐Ÿ”ฌ What happens when you subtract 1 from 0? Try it out in the app to see what happens! +๐Ÿ”ฌ What happens when you subtract 1 from 0? Try it out in the app to see what happens! ![underflow](https://user-images.githubusercontent.com/2653167/93688066-46466d80-fa80-11ea-85df-81fbafa46575.gif) @@ -203,7 +194,7 @@ Look for the [HardHat](https://hardhat.org) console.log() output in the `yarn ch ๐Ÿ—ณ Maybe an make an array `YourStructName[] public proposals;` that could call be voted on with `function vote() public {}` -๐Ÿ”ญ Your dev environment is perfect for *testing assumptions* and learning by prototyping. +๐Ÿ”ญ Your dev environment is perfect for _testing assumptions_ and learning by prototyping. ๐Ÿ“ Next learn about the [fallback function](https://solidity-by-example.org/0.6/fallback/) @@ -216,12 +207,11 @@ Look for the [HardHat](https://hardhat.org) console.log() output in the `yarn ch ===================================================== [โซ back to the top โซ](https://github.com/austintgriffith/scaffold-eth#-scaffold-eth) --- ---- +--- # ๐Ÿ“ก Deploy - ๐Ÿ›ฐ Ready to deploy to a testnet? Change the `defaultNetwork` in `packages/hardhat/hardhat.config.js` ๐Ÿ” Generate a deploy account with `yarn generate` and view it with `yarn account` @@ -234,13 +224,24 @@ Look for the [HardHat](https://hardhat.org) console.log() output in the `yarn ch yarn deploy ``` +## hardhat-deploy + +scaffold-eth now uses [hardhat-deploy](https://www.npmjs.com/package/hardhat-deploy), a hardhat plugin by [wighawag](https://twitter.com/wighawag?lang=en) that gives your hardhat deployments super-powers! + +When you run `yarn deploy`, the scripts in `/packages/hardhat/deploy` are run in alphabetical order (by default - more fine-grained controls in the hardhat-deploy docs). You can deploy contracts, interact with contracts & send ETH - whatever you want! + +Deployment metadata is stored in the `/deployments` folder, and automatically copied to `/packages/react-app/src/contracts/hardhat_contracts.json` via the `--export-all` flag in the `yarn deploy` command (see `/packages/hardhat/packagen.json`). + +Crucially, this information is stored by network, so if you redeploy contracts on a new network (e.g. on testnet, after running locally), your local deployments are still tracked. + --- ===================================================== [โซ back to the top โซ](https://github.com/austintgriffith/scaffold-eth#-scaffold-eth) - --- + --- + # ๐Ÿ“บ Frontend > Edit your frontend `App.jsx` in `packages/react-app/src` @@ -249,17 +250,17 @@ yarn deploy ![image](https://user-images.githubusercontent.com/2653167/110500412-68778a80-80b6-11eb-91bd-194d47d62771.png) - ๐Ÿคก Adjust your debugging settings as needed: ![image](https://user-images.githubusercontent.com/2653167/110499550-95776d80-80b5-11eb-8024-287878b180d5.png) - --- -## ๐Ÿ” Providers: +## ๐Ÿ” Providers & Signers: + +### Providers -Providers are your connections to different blockchains. +Providers are your connections to different blockchains. scaffold-eth uses [ethers.js providers](https://docs.ethers.io/v5/api/providers/). The frontend has three different providers that provide different levels of access to different chains: @@ -267,10 +268,23 @@ The frontend has three different providers that provide different levels of acce `localProvider`: local [HardHat](https://hardhat.org) accounts, used to read from _your_ contracts (`.env` file points you at testnet or mainnet) -`injectedProvider`: your personal [MetaMask](https://metamask.io/download.html), [WalletConnect](https://walletconnect.org/apps) via [Argent](https://www.argent.xyz/), or other injected wallet (generates [burner-provider](https://www.npmjs.com/package/burner-provider) on page load) +We use `ethers.providers.StaticJsonRpcProvider` when instantiating providers from RPCs where we are confident that the chainId won't change to save on network calls :) + +`injectedProvider`: your personal [MetaMask](https://metamask.io/download.html), [WalletConnect](https://walletconnect.org/apps) via [Argent](https://www.argent.xyz/), connected using [web3modal](https://github.com/Web3Modal/web3modal). ![image](https://user-images.githubusercontent.com/2653167/110499705-bc35a400-80b5-11eb-826d-44815b89296c.png) +### Signers + +From the [ethers.js docs...](https://docs.ethers.io/v5/api/signer/) + +A Signer in ethers is an abstraction of an Ethereum Account, which can be used to sign messages and transactions and send signed transactions to the Ethereum Network to execute state changing operations. + +scaffold-eth now uses signers for user operations, either using injectedProvider.getSigner(), or using a Burner Signer created and stored in localStorage (all handled by the `useUserSigner` hook!) + +### When should I use a provider and when should I use a signer? + +If you are only reading data, use a provider. If you need to make transactions, or sign things, use a Signer. --- @@ -278,10 +292,8 @@ The frontend has three different providers that provide different levels of acce ![image](https://user-images.githubusercontent.com/2653167/110499834-dcfdf980-80b5-11eb-9d2d-de7046bf5c2b.png) - Commonly used Ethereum hooks located in `packages/react-app/src/`: - `usePoller(fn, delay)`: runs a function on app load and then on a custom interval ```jsx @@ -290,6 +302,22 @@ usePoller(() => { }, 3000); ``` +`useOnBlock(provider, fn, args)`: runs a function on app load and then on every new block for a provider + +```jsx +useOnBlock(mainnetProvider, () => { + console.log(`โ›“ A new mainnet block is here!`); +}); +``` + +
+ +`useUserSigner(injectedProviderOrSigner, localProvider)`: returns the signer associated with an injected web3 provider; if injectedProvider is null, generates a burner signer (stored in local storage) + +```js +const userSigner = useUserSigner(injectedProvider, localProvider); +``` +
`useBalance(address, provider, [pollTime])`: poll for the balance of an address from a provider @@ -324,11 +352,47 @@ const price = useExchangePrice(mainnetProvider);
-`useContractLoader(provider)`: loads your smart contract interface +`useContractLoader(provider)`: loads your smart contract interface, for contracts on the provider's chain. + +This will use contracts deployed from `packages/hardhat` (which are exported to `src/contracts/hardhat_contracts.json`), as well as external contract information, which can be added to `src/contracts/external_contracts.js`. Note that you can override both of these by passing `hardhatContracts` or `externalContracts` to the second config parameter of `useContractLoader` (see those files for the required format). ```js const readContracts = useContractLoader(localProvider); const writeContracts = useContractLoader(injectedProvider); +const writeContracts = useContractLoader(injectedProvider, { chainId: 1 }); // fix the chainId (even if the provider is on a different chain) +const writeContracts = useContractLoader(injectedProvider, { + networkName: "localhost", +}); // fix the hardhat network name (even if the provider is on a different chain) +const writeContracts = useContractLoader(injectedProvider, { + customAddresses: { EXAMPLE: "0xADDRESS" }, +}); // over-ride the address + +// Pass custom contracts +const ERC20ABI = [ + "function balanceOf(address owner) view returns (uint256)", + "function decimals() view returns (uint8)", + "function symbol() view returns (string)", + "function transfer(address to, uint amount) returns (boolean)", + "event Transfer(address indexed from, address indexed to, uint amount)", +]; +const ERC20ContractMetadata = { + 1: { + contracts: { + DAI: { + address: "0x6B175474E89094C44Da98b954EedeAC495271d0F", + abi: ERC20ABI, + }, + UNI: { + address: "0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984", + abi: ERC20ABI, + }, + }, + }, +}; + +const writeContracts = useContractLoader(injectedProvider, { chainId: 1 + externalContracts: ERC20ContractMetadata, +}); ```
@@ -360,7 +424,6 @@ const ownerUpdates = useEventListener( ![image](https://user-images.githubusercontent.com/2653167/110500019-04ed5d00-80b6-11eb-97a4-74068fa90846.png) - Your commonly used React Ethereum components located in `packages/react-app/src/`:
@@ -475,7 +538,7 @@ tx(writeContracts["SmartContractWallet"].updateOwner(newOwner)); โฌ‡๏ธ Installing a new package to your frontend? You need to `cd packages/react-app` and then `yarn add PACKAGE` -โฌ‡๏ธ Installing a new package to your backend? You need to `cd packages/harthat` and then `yarn add PACKAGE` +โฌ‡๏ธ Installing a new package to your backend? You need to `cd packages/hardhat` and then `yarn add PACKAGE` --- @@ -509,38 +572,169 @@ yarn ipfs ===================================================== [โซ back to the top โซ](https://github.com/austintgriffith/scaffold-eth#-scaffold-eth) --- + --- ## ๐Ÿšฉ Challenges 1. [ ๐Ÿฅฉ Decentralized Staking App ](https://github.com/austintgriffith/scaffold-eth/tree/challenge-1-decentralized-staking) -2. [ ๐Ÿต Token Vendor ](https://github.com/austintgriffith/scaffold-eth/tree/challenge-2-token-vendor) +2. [ ๐Ÿต Token Vendor ](https://github.com/austintgriffith/scaffold-eth/tree/challenge-2-token-vendor) --- ===================================================== [โซ back to the top โซ](https://github.com/austintgriffith/scaffold-eth#-scaffold-eth) --- + --- ## ๐Ÿ“ก Examples and Tutorials (todo: insert all the cool active branches) - -| [ tenderly ](https://github.com/austintgriffith/scaffold-eth/tree/tenderly) | -| --- | +| [ tenderly ](https://github.com/austintgriffith/scaffold-eth/tree/tenderly) | +| ----------------------------------------------------------------------------------------------- | | [ simple-nft-example ](https://github.com/austintgriffith/scaffold-eth/tree/simple-nft-example) | - ^^^ โ› PR your ๐Ÿ— scaffold-eth branch!!! ๐Ÿ™๐Ÿ™๐Ÿ™ ^^^ --- +# Subgraph + +[The Graph](https://thegraph.com/docs/introduction) lets you process on-chain events to create a Subgraph, an easy to query graphQL endpoint! + +scaffold-eth comes with a built in demo subgraph, as well as a local docker setup to run a graph-node locally. + +[![thegraphplayvideo](https://user-images.githubusercontent.com/2653167/101052782-4664ee00-3544-11eb-8805-887ad4d1406e.png) +](https://youtu.be/T5ylzOTkn-Q) + +[ ๐ŸŽฅ here is another Graph speed run tutorial video ](https://youtu.be/T5ylzOTkn-Q) + +** [Requires Docker](https://www.docker.com/products/docker-desktop) ** + +๐Ÿšฎ Clean up previous data: + +``` +yarn clean-graph-node +``` + +๐Ÿ“ก Spin up a local graph node by running + +``` +yarn run-graph-node +``` + +๐Ÿ“ Create your local subgraph by running + +``` +yarn graph-create-local +``` + +This is only required once! + +๐Ÿšข Deploy your local subgraph by running + +``` +yarn graph-ship-local +``` + +๐Ÿ–๏ธ Edit your local subgraph in `packages/subgraph/src` + +Learn more about subgraph definition [here](https://thegraph.com/docs/define-a-subgraph) + +๐ŸคฉDeploy your contracts and your subgraph in one go by running: + +``` +yarn deploy-and-graph +``` + +--- + +# Services: + +`/services` is a new (!) scaffold-eth package that pulls in backend services that you might need for local development, or even for production deployment. + +## Graph node + +graph-node lets you [run a node locally](https://thegraph.com/docs/quick-start#local-development). + +``` +run-graph-node // runs the graph node +remove-graph-node // stops the graph node +clean-graph-node // clears the local data +``` + +## Submodules + +scaffold-eth uses [submodules](https://git-scm.com/book/en/v2/Git-Tools-Submodules) to pull in other repositories. These first need to be initiated. + +``` +yarn workspace @scaffold-eth/services submodule-init +``` + +## Optimism + +[optimism.io](https://optimism.io) is an Optimistic Rollup. This submodule (of the [Optimism monorepo](https://github.com/ethereum-optimism/optimism)) runs a local chain, with an optimistic rollup. + +To run the local setup... + +** [Requires Docker](https://www.docker.com/products/docker-desktop) ** + +``` +yarn workspace @scaffold-eth/services run-optimism +``` + +> The first time may take a while as the services build! + +The underlying services are run in the background, so you won't see anything in the terminal, but you can use Docker Desktop to inspect them. + +You can stop local optimism at any time by running: + +``` +yarn workspace @scaffold-eth/services stop-optimism +``` + +The local L1 and the Rollup are configured in both `/hardhat` and `/react-app` as `localOptimism` and `localOptimismL1`, so you can deploy and build out of the box! + +Learn more about building on Optimism [here](https://community.optimism.io/docs/). + +## Arbitrum + +[Arbitrum](https://developer.offchainlabs.com/docs/developer_quickstart) is an Optimistic Rollup. This submodule (of the [Arbitrum monorepo](https://github.com/OffchainLabs/arbitrum)) runs a local chain, with an optimistic rollup. + +To run the local setup... + +** [Requires Docker](https://www.docker.com/products/docker-desktop) ** + +In one terminal: + +``` +yarn workspace @scaffold-eth/services arbitrum-init +yarn workspace @scaffold-eth/services arbitrum-build-l1 +yarn workspace @scaffold-eth/services arbitrum-run-l1 +``` + +In a second terminal: + +``` +yarn workspace @scaffold-eth/services arbitrum-init-l2 +yarn workspace @scaffold-eth/services arbitrum-run-l2 +``` + +> The first time may take a while as the services build! + +To stop the processes, you can just run CTRL-C + +The local L1 and the Rollup are configured in both `/hardhat` and `/react-app` as `localArbitrum` and `localArbitrumL1`, so you can deploy and build out of the box! + +Learn more about building on Arbitrum [here](https://developer.offchainlabs.com/docs/developer_quickstart). + ===================================================== [โซ back to the top โซ](https://github.com/austintgriffith/scaffold-eth#-scaffold-eth) --- + --- # ๐Ÿ”จ Built with ๐Ÿ— scaffold-eth: @@ -553,15 +747,12 @@ Paintings come to life as you "ink" new creations and trade them on Ethereum. A [๐Ÿ’พ Source Code ](https://github.com/austintgriffith/scaffold-eth/tree/nifty-ink-dev) - [

๐Ÿง™โ€โ™‚๏ธ Instant Wallet

](https://instantwallet.io) An instant wallet running on xDAI insired by [xdai.io](https://xdai.io). - [๐Ÿ’พ Source Code ](https://github.com/austintgriffith/scaffold-eth/tree/instantwallet-dev-session) - [

๐Ÿ—ณ Personal Token Voting

](https://medium.com/@austin_48503/personal-token-voting-73b44a598d8e) Poll your holders! Build an example emoji voting system with ๐Ÿ— scaffold-eth. ๐Ÿ” Cryptographically signed votes but tracked off-chain with ๐Ÿ“ก Zapier and ๐Ÿ“‘ Google Sheets. @@ -570,78 +761,75 @@ Poll your holders! Build an example emoji voting system with ๐Ÿ— scaffold-et [๐Ÿ’พ Source Code ](https://github.com/austintgriffith/scaffold-eth/tree/emoji-vote-dev) - ^^^ โ› PLEASE PR your ๐Ÿ— scaffold-eth project in above!!! ๐Ÿ™๐Ÿ™๐Ÿ™ ^^^ --- + ===================================================== [โซ back to the top โซ](https://github.com/austintgriffith/scaffold-eth#-scaffold-eth) ---- --- -# ๐Ÿ“Ÿ Infrastructure - --- -## ๐Ÿ›ฐ Using The Graph - -[![thegraphplayvideo](https://user-images.githubusercontent.com/2653167/101052782-4664ee00-3544-11eb-8805-887ad4d1406e.png) -](https://youtu.be/T5ylzOTkn-Q) - -[ ๐ŸŽฅ here is another Graph speed run tutorial video ](https://youtu.be/T5ylzOTkn-Q) - +# ๐Ÿ“Ÿ Infrastructure --- ## ๐Ÿ”ฌ Using Tenderly + [Tenderly](https://tenderly.co) is a platform for monitoring, alerting and trouble-shooting smart contracts. They also have a hardhat plugin and CLI tool that can be helpful for local development! Hardhat Tenderly [announcement blog](https://blog.tenderly.co/level-up-your-smart-contract-productivity-using-hardhat-and-tenderly/) for reference. - ### Verifying contracts on Tenderly + scaffold-eth includes the hardhat-tenderly plugin. When deploying to any of the following networks: + ``` ["kovan","goerli","mainnet","rinkeby","ropsten","matic","mumbai","xDai","POA"] ``` -You can verify contracts as part of the `deploy.js` script. We have created a `tenderlyVerify()` helper function, which takes your contract name and its deployed address: -``` -await tenderlyVerify( - {contractName: "YourContract", - contractAddress: yourContract.address -}) -``` -Make sure your target network is present in the hardhat networks config, then either update the default network in `hardhat.config.js` to your network of choice or run: + +You can verify contracts as part of a deployment script. + ``` -yarn deploy --network NETWORK_OF_CHOICE +let verification = await tenderly.verify({ + name: contractName, + address: contractAddress, + network: targetNetwork, +}); ``` -Once verified, they will then be available to view on Tenderly! - +Once verified, they will then be available to view on Tenderly! [![TenderlyRun](https://user-images.githubusercontent.com/2653167/110502199-38c98200-80b8-11eb-8d79-a98bb1f39617.png)](https://www.youtube.com/watch?v=c04rrld1IiE&t=47s) - #### Exporting local Transactions + One of Tenderly's best features for builders is the ability to [upload local transactions](https://dashboard.tenderly.co/tx/main/0xb8f28a9cace2bdf6d10809b477c9c83e81ce1a1b2f75f35ddd19690bbc6612aa/local-transactions) so that you can use all of Tenderly's tools for analysis and debugging. You will need to create a [tenderly account](https://tenderly.co/) if you haven't already. Exporting local transactions can be done using the [Tenderly CLI](https://github.com/tenderly/tenderly-cli). Installing the Tenderly CLI: + ``` brew tap tenderly/tenderly brew install tenderly ``` + _See alternative installation steps [here](https://github.com/tenderly/tenderly-cli#installation)_ You need to log in and configure for your local chain (including any forking information) - this can be done from any directory, but it probably makes sense to do under `/packages/hardhat` to ensure that local contracts are also uploaded with the local transaction (see more below!) + ``` cd packages/hardhat tenderly login tenderly export init ``` + You can then take transaction hashes from your local chain and run the following from the `packages/hardhat` directory: + ``` tenderly export ``` + Which will upload them to tenderly.co/dashboard! Tenderly also allows users to debug smart contracts deployed to a local fork of some network (see `yarn fork`). To let Tenderly know that we are dealing with a fork, run the following command: @@ -658,9 +846,10 @@ tenderly export --export-network Note that `tenderly.yaml` file stores information about all networks that you initialized for exporting transactions. There can be multiple of them in a single file. You only need the `--export-network` if you have more than one network in your tenderly.yaml config! -**A quick note on local contracts:** if your local contracts are persisted in a place that Tenderly can find them, then they will also be uploaded as part of the local transaction `export`, which is one of the freshest features! We have added a call to `tenderly.persistArtifacts()` as part of the scaffold-eth deploy() script, which stores the contracts & meta-information in a `deployments` folder, so this should work out of the box. +**A quick note on local contracts:** if your local contracts are persisted in a place that Tenderly can find them, then they will also be uploaded as part of the local transaction `export`, which is one of the freshest features! We are using hardhat-deploy, which stores the contracts & meta-information in a `deployments` folder, so this should work out of the box. Another pitfall when dealing with a local network (fork or not) is that you will not see the transaction hash if it fails. This happens because the hardhat detects an error while `eth_estimateGas` is executed. To prevent such behaviour, you can skip this estimation by passing a `gasLimit` override when making a call - an example of this is demonstrated in the `FunctionForm.jsx` file of the Contract component: + ``` let overrides = {} // Uncomment the next line if you want to skip the gas estimation for each transaction @@ -669,6 +858,7 @@ const returned = await tx(contractFunction(...args, overrides)); ``` **One gotcha** - Tenderly does not (currently) support yarn workspaces, so any imported solidity contracts need to be local to `packages/hardhat` for your contracts to be exported. You can achieve this by using [`nohoist`](https://classic.yarnpkg.com/blog/2018/02/15/nohoist/) - this has been done for `hardhat` so that we can export `console.sol` - see the top-level `package.json` to see how! + ``` "workspaces": { "packages": [ @@ -681,30 +871,17 @@ const returned = await tx(contractFunction(...args, overrides)); } ``` - --- ## ๐ŸŒ Etherscan -Hardhat has a truly wonderful [`hardhat-etherscan` plugin](https://www.npmjs.com/package/@nomiclabs/hardhat-etherscan) that takes care of contract verification after deployment. You need to add the following to your `hardhat.config.js` imports: -``` -require("@nomiclabs/hardhat-etherscan"); -``` -Then add your etherscan API key to the module.exports: -``` -etherscan: { - // Your API key for Etherscan - // Obtain one at https://etherscan.io/ - apiKey: "YOUR-API-KEY-HERE" -} -``` -Verifying is simple, assuming you are verifying a contract that you have just deployed from your hardhat setup - you just need to run the verify script, passing constructor arguments as an array if necessary (there is an example commented out in the `deploy.js`): + +hardhat-deploy lets you easily verify contracts on Etherscan, and we have added a helper script to `/packages/hardhat` to let you do that. Simply run: + ``` -await run("verify:verify", { - address: yourContract.address, - // constructorArguments: args // If your contract has constructor arguments, you can pass them as an array -}) +yarn etherscan-verify --network ``` -You only have to pass the contract because the plugin figures out which of the locally compiled contracts is the right one to verify. Pretty cool stuff! + +And all hardhat's deployed contracts with matching ABIs for that network will be automatically verified. Neat! --- @@ -719,17 +896,16 @@ You will need to update the `constants.js` in `packages/react-app/src` with [you > update the `BLOCKNATIVE_DAPPID` in `packages/react-app/src/constants.js` with [your own Blocknative DappID](https://docs.blocknative.com/notify) --- + ===================================================== [โซ back to the top โซ](https://github.com/austintgriffith/scaffold-eth#-scaffold-eth) --- ---- +--- ## ๐Ÿ“  Legacy Content - -[
๐Ÿงซ Building on Ethereum in 2020 (research for this repo)
](https://medium.com/@austin_48503/building-on-ethereum-in-2020-dca52eda5f00) - +[
๐Ÿงซ Building on Ethereum in 2020 (research for this repo)
](https://medium.com/@austin_48503/building-on-ethereum-in-2020-dca52eda5f00) [![splash](https://user-images.githubusercontent.com/2653167/88085723-7ab2b180-cb43-11ea-832d-8db6efcbdc02.png)](https://www.youtube.com/watch?v=ShJZf5lsXiM&feature=youtu.be&t=19) @@ -752,35 +928,32 @@ Learn about tokens. [coming soon] What is a token? Why is it cool? How can I dep Learn the basics of Automated Market Makers like ๐Ÿฆ„ Uniswap. Learn how ๐Ÿ’ฐReserves affect the ๐Ÿ“‰ price, โš–๏ธ trading, and ๐Ÿ’ฆ slippage from low liquidity. -[๐Ÿƒโ€โ™€๏ธ SpeedRun ๐Ÿ“น](https://youtu.be/eP5w6Ger1EQ) +[๐Ÿƒโ€โ™€๏ธ SpeedRun ๐Ÿ“น](https://youtu.be/eP5w6Ger1EQ) --- [
Tutorial 4: ๐Ÿš€ Connecting ETH to IPFS
](https://medium.com/@austin_48503/tl-dr-scaffold-eth-ipfs-20fa35b11c35) Build a simple IPFS application in ๐Ÿ— scaffold-eth to learn more about distributed file storage and content addressing. - [๐ŸŽฅ Live Tutorial](https://youtu.be/vqrLr5eOjLo?t=342) +[๐ŸŽฅ Live Tutorial](https://youtu.be/vqrLr5eOjLo?t=342) ---
Tutorial 5: โ›ฝ๏ธGSN and Meta Transactions
-Learn about to provide your users with better UX by abstracting away gas fees and blockchain mechanics. (todo) - +Learn about to provide your users with better UX by abstracting away gas fees and blockchain mechanics. (todo) --- - [
Tutorial 6: ๐Ÿ›ฐ Decentralized Deployment
](https://medium.com/@austin_48503/decentralized-deployment-7d975c9d5016) -Learn how to deploy your smart contract to a production blockchain. Then deploy your applicaton to Surge, S3, and IPFS. Finally, register an ENS and point it at the decentralized content! [๐ŸŽฅ Live Tutorial](https://youtu.be/vqrLr5eOjLo?t=1350) +Learn how to deploy your smart contract to a production blockchain. Then deploy your applicaton to Surge, S3, and IPFS. Finally, register an ENS and point it at the decentralized content! [๐ŸŽฅ Live Tutorial](https://youtu.be/vqrLr5eOjLo?t=1350) --- - ## ๐Ÿ’ฌ Support Chat -Join the telegram [support chat ๐Ÿ’ฌ](https://t.me/joinchat/KByvmRe5wkR-8F_zz6AjpA) to ask questions and find others building with ๐Ÿ— scaffold-eth! +Join the telegram [support chat ๐Ÿ’ฌ](https://t.me/joinchat/KByvmRe5wkR-8F_zz6AjpA) to ask questions and find others building with ๐Ÿ— scaffold-eth! --- diff --git a/package.json b/package.json index 43b9674fa..5ab2f7175 100644 --- a/package.json +++ b/package.json @@ -37,8 +37,9 @@ "fundedwallet": "cd packages/hardhat && npx hardhat fundedwallet", "flatten": "cd packages/hardhat && npx hardhat flatten", "clean": "cd packages/hardhat && npx hardhat clean", - "graph-run-node": "cd docker/graph-node && docker-compose up", - "graph-remove-node": "cd docker/graph-node && docker-compose down", + "run-graph-node": "yarn workspace @scaffold-eth/services run-graph-node", + "remove-graph-node": "yarn workspace @scaffold-eth/services remove-graph-node", + "clean-graph-node": "yarn workspace @scaffold-eth/services clean-graph-node", "graph-prepare": "mustache packages/subgraph/config/config.json packages/subgraph/src/subgraph.template.yaml > packages/subgraph/subgraph.yaml", "graph-codegen": "yarn workspace @scaffold-eth/subgraph graph codegen", "graph-build": "yarn workspace @scaffold-eth/subgraph graph build", diff --git a/packages/hardhat/deploy/00_deploy_your_contract.js b/packages/hardhat/deploy/00_deploy_your_contract.js new file mode 100644 index 000000000..17885b302 --- /dev/null +++ b/packages/hardhat/deploy/00_deploy_your_contract.js @@ -0,0 +1,30 @@ +// deploy/00_deploy_your_contract.js + +module.exports = async ({ getNamedAccounts, deployments }) => { + const { deploy } = deployments; + const { deployer } = await getNamedAccounts(); + await deploy("YourContract", { + // Learn more about args here: https://www.npmjs.com/package/hardhat-deploy#deploymentsdeploy + from: deployer, + // args: ["Hello"], + log: true, + }); + + /* + // Getting a previously deployed contract + const YourContract = await ethers.getContract("YourContract", deployer); + await YourContract.setPurpose("Hello"); + + //const yourContract = await ethers.getContractAt('YourContract', "0xaAC799eC2d00C013f1F11c37E654e59B0429DF6A") //<-- if you want to instantiate a version of a contract at a specific address! + */ +}; +module.exports.tags = ["YourContract"]; + +/* +Tenderly verification +let verification = await tenderly.verify({ + name: contractName, + address: contractAddress, + network: targetNetwork, +}); +*/ diff --git a/packages/hardhat/hardhat.config.js b/packages/hardhat/hardhat.config.js index 60ca12b2b..94cf720f1 100644 --- a/packages/hardhat/hardhat.config.js +++ b/packages/hardhat/hardhat.config.js @@ -3,9 +3,12 @@ const fs = require("fs"); const chalk = require("chalk"); require("@nomiclabs/hardhat-waffle"); -require("@tenderly/hardhat-tenderly") +require("@tenderly/hardhat-tenderly"); -require("@nomiclabs/hardhat-etherscan"); +require("hardhat-deploy"); + +require("@eth-optimism/hardhat-ovm"); +require("@nomiclabs/hardhat-ethers"); const { isAddress, getAddress, formatUnits, parseUnits } = utils; @@ -28,7 +31,9 @@ function mnemonic() { return fs.readFileSync("./mnemonic.txt").toString().trim(); } catch (e) { if (defaultNetwork !== "localhost") { - console.log("โ˜ข๏ธ WARNING: No mnemonic file created for a deploy account. Try `yarn run generate` and then `yarn run account`.") + console.log( + "โ˜ข๏ธ WARNING: No mnemonic file created for a deploy account. Try `yarn run generate` and then `yarn run account`." + ); } } return ""; @@ -51,49 +56,111 @@ module.exports = { */ }, rinkeby: { - url: "https://rinkeby.infura.io/v3/460f40a260564ac4a4f4b3fffb032dad", //<---- YOUR INFURA ID! (or it won't work) + url: "https://rinkeby.infura.io/v3/460f40a260564ac4a4f4b3fffb032dad", // <---- YOUR INFURA ID! (or it won't work) accounts: { mnemonic: mnemonic(), }, }, kovan: { - url: "https://kovan.infura.io/v3/460f40a260564ac4a4f4b3fffb032dad", //<---- YOUR INFURA ID! (or it won't work) + url: "https://kovan.infura.io/v3/460f40a260564ac4a4f4b3fffb032dad", // <---- YOUR INFURA ID! (or it won't work) accounts: { mnemonic: mnemonic(), }, }, mainnet: { - url: "https://mainnet.infura.io/v3/460f40a260564ac4a4f4b3fffb032dad", //<---- YOUR INFURA ID! (or it won't work) + url: "https://mainnet.infura.io/v3/460f40a260564ac4a4f4b3fffb032dad", // <---- YOUR INFURA ID! (or it won't work) accounts: { mnemonic: mnemonic(), }, }, ropsten: { - url: "https://ropsten.infura.io/v3/460f40a260564ac4a4f4b3fffb032dad", //<---- YOUR INFURA ID! (or it won't work) + url: "https://ropsten.infura.io/v3/460f40a260564ac4a4f4b3fffb032dad", // <---- YOUR INFURA ID! (or it won't work) accounts: { mnemonic: mnemonic(), }, }, goerli: { - url: "https://goerli.infura.io/v3/460f40a260564ac4a4f4b3fffb032dad", //<---- YOUR INFURA ID! (or it won't work) + url: "https://goerli.infura.io/v3/460f40a260564ac4a4f4b3fffb032dad", // <---- YOUR INFURA ID! (or it won't work) accounts: { mnemonic: mnemonic(), }, }, xdai: { - url: 'https://rpc.xdaichain.com/', + url: "https://rpc.xdaichain.com/", gasPrice: 1000000000, accounts: { mnemonic: mnemonic(), }, }, matic: { - url: 'https://rpc-mainnet.maticvigil.com/', + url: "https://rpc-mainnet.maticvigil.com/", gasPrice: 1000000000, accounts: { mnemonic: mnemonic(), }, }, + rinkebyArbitrum: { + url: "https://rinkeby.arbitrum.io/rpc", + gasPrice: 0, + accounts: { + mnemonic: mnemonic(), + }, + companionNetworks: { + l1: "rinkeby", + }, + }, + localArbitrum: { + url: "http://localhost:8547", + gasPrice: 0, + accounts: { + mnemonic: mnemonic(), + }, + companionNetworks: { + l1: "localArbitrumL1", + }, + }, + localArbitrumL1: { + url: "http://localhost:7545", + gasPrice: 0, + accounts: { + mnemonic: mnemonic(), + }, + companionNetworks: { + l2: "localArbitrum", + }, + }, + kovanOptimism: { + url: "https://kovan.optimism.io", + gasPrice: 0, + accounts: { + mnemonic: mnemonic(), + }, + ovm: true, + companionNetworks: { + l1: "kovan", + }, + }, + localOptimism: { + url: "http://localhost:8545", + gasPrice: 0, + accounts: { + mnemonic: mnemonic(), + }, + ovm: true, + companionNetworks: { + l1: "localOptimismL1", + }, + }, + localOptimismL1: { + url: "http://localhost:9545", + gasPrice: 0, + accounts: { + mnemonic: mnemonic(), + }, + companionNetworks: { + l2: "localOptimism", + }, + }, }, solidity: { compilers: [ @@ -102,27 +169,29 @@ module.exports = { settings: { optimizer: { enabled: true, - runs: 200 - } - } + runs: 200, + }, + }, }, { version: "0.6.7", settings: { optimizer: { enabled: true, - runs: 200 - } - } - } + runs: 200, + }, + }, + }, ], - }, - etherscan: { - // Your API key for Etherscan - // Obtain one at https://etherscan.io/ - apiKey: "PSW8C433Q667DVEX5BCRMGNAH9FSGFZ7Q8" - } + ovm: { + solcVersion: "0.7.6", + }, + namedAccounts: { + deployer: { + default: 0, // here this will by default take the first account as deployer + }, + }, }; const DEBUG = false; @@ -134,171 +203,214 @@ function debug(text) { } task("wallet", "Create a wallet (pk) link", async (_, { ethers }) => { - const randomWallet = ethers.Wallet.createRandom() - const privateKey = randomWallet._signingKey().privateKey - console.log("๐Ÿ” WALLET Generated as " + randomWallet.address + "") - console.log("๐Ÿ”— http://localhost:3000/pk#"+privateKey) + const randomWallet = ethers.Wallet.createRandom(); + const privateKey = randomWallet._signingKey().privateKey; + console.log("๐Ÿ” WALLET Generated as " + randomWallet.address + ""); + console.log("๐Ÿ”— http://localhost:3000/pk#" + privateKey); }); - task("fundedwallet", "Create a wallet (pk) link and fund it with deployer?") - .addOptionalParam("amount", "Amount of ETH to send to wallet after generating") + .addOptionalParam( + "amount", + "Amount of ETH to send to wallet after generating" + ) .addOptionalParam("url", "URL to add pk to") .setAction(async (taskArgs, { network, ethers }) => { + const randomWallet = ethers.Wallet.createRandom(); + const privateKey = randomWallet._signingKey().privateKey; + console.log("๐Ÿ” WALLET Generated as " + randomWallet.address + ""); + let url = taskArgs.url ? taskArgs.url : "http://localhost:3000"; - const randomWallet = ethers.Wallet.createRandom() - const privateKey = randomWallet._signingKey().privateKey - console.log("๐Ÿ” WALLET Generated as " + randomWallet.address + "") - let url = taskArgs.url?taskArgs.url:"http://localhost:3000" - - let localDeployerMnemonic - try{ - localDeployerMnemonic = fs.readFileSync("./mnemonic.txt") - localDeployerMnemonic = localDeployerMnemonic.toString().trim() + let localDeployerMnemonic; + try { + localDeployerMnemonic = fs.readFileSync("./mnemonic.txt"); + localDeployerMnemonic = localDeployerMnemonic.toString().trim(); } catch (e) { /* do nothing - this file isn't always there */ } - let amount = taskArgs.amount?taskArgs.amount:"0.01" + let amount = taskArgs.amount ? taskArgs.amount : "0.01"; const tx = { to: randomWallet.address, - value: ethers.utils.parseEther(amount) + value: ethers.utils.parseEther(amount), }; //SEND USING LOCAL DEPLOYER MNEMONIC IF THERE IS ONE // IF NOT SEND USING LOCAL HARDHAT NODE: - if(localDeployerMnemonic){ - let deployerWallet = new ethers.Wallet.fromMnemonic(localDeployerMnemonic) - deployerWallet = deployerWallet.connect(ethers.provider) - console.log("๐Ÿ’ต Sending "+amount+" ETH to "+randomWallet.address+" using deployer account"); - let sendresult = await deployerWallet.sendTransaction(tx) - console.log("\n"+url+"/pk#"+privateKey+"\n") - return - }else{ - console.log("๐Ÿ’ต Sending "+amount+" ETH to "+randomWallet.address+" using local node"); - console.log("\n"+url+"/pk#"+privateKey+"\n") + if (localDeployerMnemonic) { + let deployerWallet = new ethers.Wallet.fromMnemonic( + localDeployerMnemonic + ); + deployerWallet = deployerWallet.connect(ethers.provider); + console.log( + "๐Ÿ’ต Sending " + + amount + + " ETH to " + + randomWallet.address + + " using deployer account" + ); + let sendresult = await deployerWallet.sendTransaction(tx); + console.log("\n" + url + "/pk#" + privateKey + "\n"); + return; + } else { + console.log( + "๐Ÿ’ต Sending " + + amount + + " ETH to " + + randomWallet.address + + " using local node" + ); + console.log("\n" + url + "/pk#" + privateKey + "\n"); return send(ethers.provider.getSigner(), tx); } + }); -}); - - -task("generate", "Create a mnemonic for builder deploys", async (_, { ethers }) => { - const bip39 = require("bip39") - const hdkey = require('ethereumjs-wallet/hdkey'); - const mnemonic = bip39.generateMnemonic() - if (DEBUG) console.log("mnemonic", mnemonic) - const seed = await bip39.mnemonicToSeed(mnemonic) - if (DEBUG) console.log("seed", seed) - const hdwallet = hdkey.fromMasterSeed(seed); - const wallet_hdpath = "m/44'/60'/0'/0/"; - const account_index = 0 - let fullPath = wallet_hdpath + account_index - if (DEBUG) console.log("fullPath", fullPath) - const wallet = hdwallet.derivePath(fullPath).getWallet(); - const privateKey = "0x" + wallet._privKey.toString('hex'); - if (DEBUG) console.log("privateKey", privateKey) - var EthUtil = require('ethereumjs-util'); - const address = "0x" + EthUtil.privateToAddress(wallet._privKey).toString('hex') - console.log("๐Ÿ” Account Generated as " + address + " and set as mnemonic in packages/hardhat") - console.log("๐Ÿ’ฌ Use 'yarn run account' to get more information about the deployment account.") - - fs.writeFileSync("./" + address + ".txt", mnemonic.toString()) - fs.writeFileSync("./mnemonic.txt", mnemonic.toString()) -}); +task( + "generate", + "Create a mnemonic for builder deploys", + async (_, { ethers }) => { + const bip39 = require("bip39"); + const hdkey = require("ethereumjs-wallet/hdkey"); + const mnemonic = bip39.generateMnemonic(); + if (DEBUG) console.log("mnemonic", mnemonic); + const seed = await bip39.mnemonicToSeed(mnemonic); + if (DEBUG) console.log("seed", seed); + const hdwallet = hdkey.fromMasterSeed(seed); + const wallet_hdpath = "m/44'/60'/0'/0/"; + const account_index = 0; + let fullPath = wallet_hdpath + account_index; + if (DEBUG) console.log("fullPath", fullPath); + const wallet = hdwallet.derivePath(fullPath).getWallet(); + const privateKey = "0x" + wallet._privKey.toString("hex"); + if (DEBUG) console.log("privateKey", privateKey); + var EthUtil = require("ethereumjs-util"); + const address = + "0x" + EthUtil.privateToAddress(wallet._privKey).toString("hex"); + console.log( + "๐Ÿ” Account Generated as " + + address + + " and set as mnemonic in packages/hardhat" + ); + console.log( + "๐Ÿ’ฌ Use 'yarn run account' to get more information about the deployment account." + ); + + fs.writeFileSync("./" + address + ".txt", mnemonic.toString()); + fs.writeFileSync("./mnemonic.txt", mnemonic.toString()); + } +); -task("mineContractAddress", "Looks for a deployer account that will give leading zeros") +task( + "mineContractAddress", + "Looks for a deployer account that will give leading zeros" +) .addParam("searchFor", "String to search for") .setAction(async (taskArgs, { network, ethers }) => { + let contract_address = ""; + let address; + + const bip39 = require("bip39"); + const hdkey = require("ethereumjs-wallet/hdkey"); + + let mnemonic = ""; + while (contract_address.indexOf(taskArgs.searchFor) != 0) { + mnemonic = bip39.generateMnemonic(); + if (DEBUG) console.log("mnemonic", mnemonic); + const seed = await bip39.mnemonicToSeed(mnemonic); + if (DEBUG) console.log("seed", seed); + const hdwallet = hdkey.fromMasterSeed(seed); + const wallet_hdpath = "m/44'/60'/0'/0/"; + const account_index = 0; + let fullPath = wallet_hdpath + account_index; + if (DEBUG) console.log("fullPath", fullPath); + const wallet = hdwallet.derivePath(fullPath).getWallet(); + const privateKey = "0x" + wallet._privKey.toString("hex"); + if (DEBUG) console.log("privateKey", privateKey); + var EthUtil = require("ethereumjs-util"); + address = + "0x" + EthUtil.privateToAddress(wallet._privKey).toString("hex"); + + const rlp = require("rlp"); + const keccak = require("keccak"); + + let nonce = 0x00; //The nonce must be a hex literal! + let sender = address; + + let input_arr = [sender, nonce]; + let rlp_encoded = rlp.encode(input_arr); + + let contract_address_long = keccak("keccak256") + .update(rlp_encoded) + .digest("hex"); + + contract_address = contract_address_long.substring(24); //Trim the first 24 characters. + } - let contract_address = "" - let address; - - const bip39 = require("bip39") - const hdkey = require('ethereumjs-wallet/hdkey'); - - let mnemonic = "" - while(contract_address.indexOf(taskArgs.searchFor)!=0){ + console.log( + "โ› Account Mined as " + + address + + " and set as mnemonic in packages/hardhat" + ); + console.log( + "๐Ÿ“œ This will create the first contract: " + + chalk.magenta("0x" + contract_address) + ); + console.log( + "๐Ÿ’ฌ Use 'yarn run account' to get more information about the deployment account." + ); + + fs.writeFileSync( + "./" + address + "_produces" + contract_address + ".txt", + mnemonic.toString() + ); + fs.writeFileSync("./mnemonic.txt", mnemonic.toString()); + }); - mnemonic = bip39.generateMnemonic() - if (DEBUG) console.log("mnemonic", mnemonic) - const seed = await bip39.mnemonicToSeed(mnemonic) - if (DEBUG) console.log("seed", seed) +task( + "account", + "Get balance informations for the deployment account.", + async (_, { ethers }) => { + const hdkey = require("ethereumjs-wallet/hdkey"); + const bip39 = require("bip39"); + let mnemonic = fs.readFileSync("./mnemonic.txt").toString().trim(); + if (DEBUG) console.log("mnemonic", mnemonic); + const seed = await bip39.mnemonicToSeed(mnemonic); + if (DEBUG) console.log("seed", seed); const hdwallet = hdkey.fromMasterSeed(seed); const wallet_hdpath = "m/44'/60'/0'/0/"; - const account_index = 0 - let fullPath = wallet_hdpath + account_index - if (DEBUG) console.log("fullPath", fullPath) + const account_index = 0; + let fullPath = wallet_hdpath + account_index; + if (DEBUG) console.log("fullPath", fullPath); const wallet = hdwallet.derivePath(fullPath).getWallet(); - const privateKey = "0x" + wallet._privKey.toString('hex'); - if (DEBUG) console.log("privateKey", privateKey) - var EthUtil = require('ethereumjs-util'); - address = "0x" + EthUtil.privateToAddress(wallet._privKey).toString('hex') - - - const rlp = require('rlp'); - const keccak = require('keccak'); - - let nonce = 0x00; //The nonce must be a hex literal! - let sender = address; - - let input_arr = [ sender, nonce ]; - let rlp_encoded = rlp.encode(input_arr); - - let contract_address_long = keccak('keccak256').update(rlp_encoded).digest('hex'); - - contract_address = contract_address_long.substring(24); //Trim the first 24 characters. - - - } - - console.log("โ› Account Mined as " + address + " and set as mnemonic in packages/hardhat") - console.log("๐Ÿ“œ This will create the first contract: "+chalk.magenta("0x"+contract_address)); - console.log("๐Ÿ’ฌ Use 'yarn run account' to get more information about the deployment account.") - - fs.writeFileSync("./" + address + "_produces"+contract_address+".txt", mnemonic.toString()) - fs.writeFileSync("./mnemonic.txt", mnemonic.toString()) -}); - -task("account", "Get balance informations for the deployment account.", async (_, { ethers }) => { - const hdkey = require('ethereumjs-wallet/hdkey'); - const bip39 = require("bip39") - let mnemonic = fs.readFileSync("./mnemonic.txt").toString().trim() - if (DEBUG) console.log("mnemonic", mnemonic) - const seed = await bip39.mnemonicToSeed(mnemonic) - if (DEBUG) console.log("seed", seed) - const hdwallet = hdkey.fromMasterSeed(seed); - const wallet_hdpath = "m/44'/60'/0'/0/"; - const account_index = 0 - let fullPath = wallet_hdpath + account_index - if (DEBUG) console.log("fullPath", fullPath) - const wallet = hdwallet.derivePath(fullPath).getWallet(); - const privateKey = "0x" + wallet._privKey.toString('hex'); - if (DEBUG) console.log("privateKey", privateKey) - var EthUtil = require('ethereumjs-util'); - const address = "0x" + EthUtil.privateToAddress(wallet._privKey).toString('hex') - - var qrcode = require('qrcode-terminal'); - qrcode.generate(address); - console.log("โ€๐Ÿ“ฌ Deployer Account is " + address) - for (let n in config.networks) { - //console.log(config.networks[n],n) - try { - - let provider = new ethers.providers.JsonRpcProvider(config.networks[n].url) - let balance = (await provider.getBalance(address)) - console.log(" -- " + n + " -- -- -- ๐Ÿ“ก ") - console.log(" balance: " + ethers.utils.formatEther(balance)) - console.log(" nonce: " + (await provider.getTransactionCount(address))) - } catch (e) { - if (DEBUG) { - console.log(e) + const privateKey = "0x" + wallet._privKey.toString("hex"); + if (DEBUG) console.log("privateKey", privateKey); + var EthUtil = require("ethereumjs-util"); + const address = + "0x" + EthUtil.privateToAddress(wallet._privKey).toString("hex"); + + var qrcode = require("qrcode-terminal"); + qrcode.generate(address); + console.log("โ€๐Ÿ“ฌ Deployer Account is " + address); + for (let n in config.networks) { + //console.log(config.networks[n],n) + try { + let provider = new ethers.providers.JsonRpcProvider( + config.networks[n].url + ); + let balance = await provider.getBalance(address); + console.log(" -- " + n + " -- -- -- ๐Ÿ“ก "); + console.log(" balance: " + ethers.utils.formatEther(balance)); + console.log( + " nonce: " + (await provider.getTransactionCount(address)) + ); + } catch (e) { + if (DEBUG) { + console.log(e); + } } } } - -}); - +); async function addr(ethers, addr) { if (isAddress(addr)) { @@ -322,13 +434,13 @@ task("blockNumber", "Prints the block number", async (_, { ethers }) => { }); task("balance", "Prints an account's balance") - .addPositionalParam("account", "The account's address") - .setAction(async (taskArgs, { ethers }) => { - const balance = await ethers.provider.getBalance( - await addr(ethers, taskArgs.account) - ); - console.log(formatUnits(balance, "ether"), "ETH"); - }); + .addPositionalParam("account", "The account's address") + .setAction(async (taskArgs, { ethers }) => { + const balance = await ethers.provider.getBalance( + await addr(ethers, taskArgs.account) + ); + console.log(formatUnits(balance, "ether"), "ETH"); + }); function send(signer, txparams) { return signer.sendTransaction(txparams, (error, transactionHash) => { @@ -363,13 +475,13 @@ task("send", "Send ETH") from: await fromSigner.getAddress(), to, value: parseUnits( - taskArgs.amount ? taskArgs.amount : "0", - "ether" + taskArgs.amount ? taskArgs.amount : "0", + "ether" ).toHexString(), nonce: await fromSigner.getTransactionCount(), gasPrice: parseUnits( - taskArgs.gasPrice ? taskArgs.gasPrice : "1.001", - "gwei" + taskArgs.gasPrice ? taskArgs.gasPrice : "1.001", + "gwei" ).toHexString(), gasLimit: taskArgs.gasLimit ? taskArgs.gasLimit : 24000, chainId: network.config.chainId, @@ -383,4 +495,4 @@ task("send", "Send ETH") debug(JSON.stringify(txRequest, null, 2)); return send(fromSigner, txRequest); -}); + }); diff --git a/packages/hardhat/package.json b/packages/hardhat/package.json index 3e548296a..eeb6b3ac4 100644 --- a/packages/hardhat/package.json +++ b/packages/hardhat/package.json @@ -11,32 +11,34 @@ "eslint-plugin-prettier": "^3.1.4" }, "dependencies": { - "@nomiclabs/hardhat-ethers": "^2.0.0", - "@nomiclabs/hardhat-etherscan": "^2.1.1", + "@eth-optimism/hardhat-ovm": "^0.2.2", + "@nomiclabs/hardhat-ethers": "npm:hardhat-deploy-ethers", "@nomiclabs/hardhat-waffle": "^2.0.0", "@openzeppelin/contracts": "^3.2.0", "@tenderly/hardhat-tenderly": "^1.0.10", "chai": "^4.2.0", "chalk": "^4.1.0", "ethereum-waffle": "^3.1.1", - "ethers": "^5.0.17", + "ethers": "^5.3.0", "hardhat": "^2.0.11", + "hardhat-deploy": "^0.8.6", "node-watch": "^0.7.0", "qrcode-terminal": "^0.12.0", "ramda": "^0.27.1" }, "scripts": { - "chain": "hardhat node", + "chain": "hardhat node --network hardhat --no-deploy", "fork": "hardhat node --fork https://mainnet.infura.io/v3/460f40a260564ac4a4f4b3fffb032dad", "test": "hardhat test --network hardhat", "compile": "hardhat compile", - "deploy": "hardhat run scripts/deploy.js", + "deploy": "hardhat deploy --export-all ../react-app/src/contracts/hardhat_contracts.json", "postdeploy": "hardhat run scripts/publish.js", "watch": "node scripts/watch.js", "accounts": "hardhat accounts", "balance": "hardhat balance", "send": "hardhat send", "generate": "hardhat generate", - "account": "hardhat account" + "account": "hardhat account", + "etherscan-verify": "hardhat etherscan-verify --api-key PSW8C433Q667DVEX5BCRMGNAH9FSGFZ7Q8" } } diff --git a/packages/hardhat/scripts/deploy.js b/packages/hardhat/scripts/deploy.js index 23ede244b..d87fc2929 100644 --- a/packages/hardhat/scripts/deploy.js +++ b/packages/hardhat/scripts/deploy.js @@ -5,11 +5,30 @@ const { config, ethers, tenderly, run } = require("hardhat"); const { utils } = require("ethers"); const R = require("ramda"); -const main = async () => { +/* + + _______ _________ _______ _______ +( ____ \\__ __/( ___ )( ____ ) +| ( \/ ) ( | ( ) || ( )| +| (_____ | | | | | || (____)| +(_____ ) | | | | | || _____) + ) | | | | | | || ( +/\____) | | | | (___) || ) +\_______) )_( (_______)|/ + +This deploy script is no longer in use, but is left for reference purposes! +scaffold-eth now uses hardhat-deploy to manage deployments, see the /deploy folder +And learn more here: https://www.npmjs.com/package/hardhat-deploy + +*/ + +const main = async () => { console.log("\n\n ๐Ÿ“ก Deploying...\n"); - const yourContract = await deploy("YourContract") // <-- add in constructor args like line 19 vvvv + const yourContract = await deploy("YourContract"); // <-- add in constructor args like line 19 vvvv + // use for local token bridging + // const mockToken = await deploy("MockERC20") // <-- add in constructor args like line 19 vvvv //const yourContract = await ethers.getContractAt('YourContract', "0xaAC799eC2d00C013f1F11c37E654e59B0429DF6A") //<-- if you want to instantiate a version of a contract at a specific address! //const secondContract = await deploy("SecondContract") @@ -27,7 +46,6 @@ const main = async () => { }) */ - /* //If you want to send some ETH to a contract on deploy (make your constructor payable!) const yourContract = await deploy("YourContract", [], { @@ -35,7 +53,6 @@ const main = async () => { }); */ - /* //If you want to link a library into your contract: // reference: https://github.com/austintgriffith/scaffold-eth/blob/using-libraries-example/packages/hardhat/scripts/deploy.js#L19 @@ -44,7 +61,6 @@ const main = async () => { }); */ - //If you want to verify your contract on tenderly.co (see setup details in the scaffold-eth README!) /* await tenderlyVerify( @@ -53,16 +69,6 @@ const main = async () => { }) */ - // If you want to verify your contract on etherscan - /* - console.log(chalk.blue('verifying on etherscan')) - await run("verify:verify", { - address: yourContract.address, - // contract: "contracts/Example.sol:ExampleContract" // If you are inheriting from multiple contracts in yourContract.sol, you can specify which to verify - // constructorArguments: args // If your contract has constructor arguments, you can pass them as an array - }) - */ - console.log( " ๐Ÿ’พ Artifacts (address, abi, and args) saved to: ", chalk.blue("packages/hardhat/artifacts/"), @@ -70,19 +76,30 @@ const main = async () => { ); }; -const deploy = async (contractName, _args = [], overrides = {}, libraries = {}) => { +const deploy = async ( + contractName, + _args = [], + overrides = {}, + libraries = {} +) => { console.log(` ๐Ÿ›ฐ Deploying: ${contractName}`); const contractArgs = _args || []; - const contractArtifacts = await ethers.getContractFactory(contractName,{libraries: libraries}); + const contractArtifacts = await ethers.getContractFactory(contractName, { + libraries: libraries, + }); const deployed = await contractArtifacts.deploy(...contractArgs, overrides); const encoded = abiEncodeArgs(deployed, contractArgs); fs.writeFileSync(`artifacts/${contractName}.address`, deployed.address); - let extraGasInfo = "" - if(deployed&&deployed.deployTransaction){ - const gasUsed = deployed.deployTransaction.gasLimit.mul(deployed.deployTransaction.gasPrice) - extraGasInfo = `${utils.formatEther(gasUsed)} ETH, tx hash ${deployed.deployTransaction.hash}` + let extraGasInfo = ""; + if (deployed && deployed.deployTransaction) { + const gasUsed = deployed.deployTransaction.gasLimit.mul( + deployed.deployTransaction.gasPrice + ); + extraGasInfo = `${utils.formatEther(gasUsed)} ETH, tx hash ${ + deployed.deployTransaction.hash + }`; } console.log( @@ -91,14 +108,11 @@ const deploy = async (contractName, _args = [], overrides = {}, libraries = {}) "deployed to:", chalk.magenta(deployed.address) ); - console.log( - " โ›ฝ", - chalk.grey(extraGasInfo) - ); + console.log(" โ›ฝ", chalk.grey(extraGasInfo)); await tenderly.persistArtifacts({ name: contractName, - address: deployed.address + address: deployed.address, }); if (!encoded || encoded.length <= 2) return deployed; @@ -107,7 +121,6 @@ const deploy = async (contractName, _args = [], overrides = {}, libraries = {}) return deployed; }; - // ------ utils ------- // abi encodes contract arguments @@ -131,7 +144,9 @@ const abiEncodeArgs = (deployed, contractArgs) => { // checks if it is a Solidity file const isSolidity = (fileName) => - fileName.indexOf(".sol") >= 0 && fileName.indexOf(".swp") < 0 && fileName.indexOf(".swap") < 0; + fileName.indexOf(".sol") >= 0 && + fileName.indexOf(".swp") < 0 && + fileName.indexOf(".swap") < 0; const readArgsFile = (contractName) => { let args = []; @@ -146,34 +161,49 @@ const readArgsFile = (contractName) => { }; function sleep(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); + return new Promise((resolve) => setTimeout(resolve, ms)); } // If you want to verify on https://tenderly.co/ -const tenderlyVerify = async ({contractName, contractAddress}) => { - - let tenderlyNetworks = ["kovan","goerli","mainnet","rinkeby","ropsten","matic","mumbai","xDai","POA"] - let targetNetwork = process.env.HARDHAT_NETWORK || config.defaultNetwork - - if(tenderlyNetworks.includes(targetNetwork)) { - console.log(chalk.blue(` ๐Ÿ“ Attempting tenderly verification of ${contractName} on ${targetNetwork}`)) +const tenderlyVerify = async ({ contractName, contractAddress }) => { + let tenderlyNetworks = [ + "kovan", + "goerli", + "mainnet", + "rinkeby", + "ropsten", + "matic", + "mumbai", + "xDai", + "POA", + ]; + let targetNetwork = process.env.HARDHAT_NETWORK || config.defaultNetwork; + + if (tenderlyNetworks.includes(targetNetwork)) { + console.log( + chalk.blue( + ` ๐Ÿ“ Attempting tenderly verification of ${contractName} on ${targetNetwork}` + ) + ); await tenderly.persistArtifacts({ name: contractName, - address: contractAddress + address: contractAddress, }); let verification = await tenderly.verify({ - name: contractName, - address: contractAddress, - network: targetNetwork - }) + name: contractName, + address: contractAddress, + network: targetNetwork, + }); - return verification + return verification; } else { - console.log(chalk.grey(` ๐Ÿง Contract verification not supported on ${targetNetwork}`)) + console.log( + chalk.grey(` ๐Ÿง Contract verification not supported on ${targetNetwork}`) + ); } -} +}; main() .then(() => process.exit(0)) diff --git a/packages/hardhat/scripts/publish.js b/packages/hardhat/scripts/publish.js index 6aef6943d..89b765e80 100644 --- a/packages/hardhat/scripts/publish.js +++ b/packages/hardhat/scripts/publish.js @@ -1,98 +1,80 @@ const fs = require("fs"); const chalk = require("chalk"); -const bre = require("hardhat"); +const graphDir = "../subgraph"; +const deploymentsDir = "./deployments"; const publishDir = "../react-app/src/contracts"; -const graphDir = "../subgraph" -function publishContract(contractName) { - console.log( - " ๐Ÿ’ฝ Publishing", - chalk.cyan(contractName), - "to", - chalk.gray(publishDir) - ); +function publishContract(contractName, networkName) { try { let contract = fs - .readFileSync(`${bre.config.paths.artifacts}/contracts/${contractName}.sol/${contractName}.json`) - .toString(); - const address = fs - .readFileSync(`${bre.config.paths.artifacts}/${contractName}.address`) + .readFileSync(`${deploymentsDir}/${networkName}/${contractName}.json`) .toString(); contract = JSON.parse(contract); - let graphConfigPath = `${graphDir}/config/config.json` - let graphConfig + const graphConfigPath = `${graphDir}/config/config.json`; + let graphConfig; try { if (fs.existsSync(graphConfigPath)) { - graphConfig = fs - .readFileSync(graphConfigPath) - .toString(); + graphConfig = fs.readFileSync(graphConfigPath).toString(); } else { - graphConfig = '{}' - } - } catch (e) { - console.log(e) + graphConfig = "{}"; } + } catch (e) { + console.log(e); + } - graphConfig = JSON.parse(graphConfig) - graphConfig[contractName + "Address"] = address - fs.writeFileSync( - `${publishDir}/${contractName}.address.js`, - `module.exports = "${address}";` - ); - fs.writeFileSync( - `${publishDir}/${contractName}.abi.js`, - `module.exports = ${JSON.stringify(contract.abi, null, 2)};` - ); - fs.writeFileSync( - `${publishDir}/${contractName}.bytecode.js`, - `module.exports = "${contract.bytecode}";` - ); + graphConfig = JSON.parse(graphConfig); + graphConfig[`${networkName}_${contractName}Address`] = contract.address; - const folderPath = graphConfigPath.replace("/config.json","") - if (!fs.existsSync(folderPath)){ + const folderPath = graphConfigPath.replace("/config.json", ""); + if (!fs.existsSync(folderPath)) { fs.mkdirSync(folderPath); } + fs.writeFileSync(graphConfigPath, JSON.stringify(graphConfig, null, 2)); + if (!fs.existsSync(`${graphDir}/abis`)) fs.mkdirSync(`${graphDir}/abis`); fs.writeFileSync( - graphConfigPath, - JSON.stringify(graphConfig, null, 2) - ); - fs.writeFileSync( - `${graphDir}/abis/${contractName}.json`, + `${graphDir}/abis/${networkName}_${contractName}.json`, JSON.stringify(contract.abi, null, 2) ); - console.log(" ๐Ÿ“  Published "+chalk.green(contractName)+" to the frontend.") + //Hardhat Deploy writes a file with all ABIs in react-app/src/contracts/contracts.json + //If you need the bytecodes and/or you want one file per ABIs, un-comment the following block. + //Write the contracts ABI, address and bytecodes in case the front-end needs them + // fs.writeFileSync( + // `${publishDir}/${contractName}.address.js`, + // `module.exports = "${contract.address}";` + // ); + // fs.writeFileSync( + // `${publishDir}/${contractName}.abi.js`, + // `module.exports = ${JSON.stringify(contract.abi, null, 2)};` + // ); + // fs.writeFileSync( + // `${publishDir}/${contractName}.bytecode.js`, + // `module.exports = "${contract.bytecode}";` + // ); return true; } catch (e) { - if(e.toString().indexOf("no such file or directory")>=0){ - console.log(chalk.yellow(" โš ๏ธ Can't publish "+contractName+" yet (make sure it getting deployed).")) - }else{ - console.log(e); - return false; - } + console.log( + "Failed to publish " + chalk.red(contractName) + " to the subgraph." + ); + console.log(e); + return false; } } async function main() { - if (!fs.existsSync(publishDir)) { - fs.mkdirSync(publishDir); - } - const finalContractList = []; - fs.readdirSync(bre.config.paths.sources).forEach((file) => { - if (file.indexOf(".sol") >= 0) { - const contractName = file.replace(".sol", ""); - // Add contract to list if publishing is successful - if (publishContract(contractName)) { - finalContractList.push(contractName); + const directories = fs.readdirSync(deploymentsDir); + directories.forEach(function (directory) { + const files = fs.readdirSync(`${deploymentsDir}/${directory}`); + files.forEach(function (file) { + if (file.indexOf(".json") >= 0) { + const contractName = file.replace(".json", ""); + publishContract(contractName, directory); } - } + }); }); - fs.writeFileSync( - `${publishDir}/contracts.js`, - `module.exports = ${JSON.stringify(finalContractList)};` - ); + console.log("โœ… Published contracts to the subgraph package."); } main() .then(() => process.exit(0)) diff --git a/packages/react-app/package.json b/packages/react-app/package.json index b12bc92d3..ad988d414 100644 --- a/packages/react-app/package.json +++ b/packages/react-app/package.json @@ -17,13 +17,6 @@ "dependencies": { "@ant-design/icons": "^4.2.2", "@apollo/react-hooks": "^4.0.0", - "@ethersproject/address": "^5.0.5", - "@ethersproject/bignumber": "^5.0.8", - "@ethersproject/bytes": "^5.0.5", - "@ethersproject/contracts": "^5.0.5", - "@ethersproject/providers": "^5.0.12", - "@ethersproject/solidity": "^5.0.9", - "@ethersproject/units": "^5.0.6", "@ramp-network/ramp-instant-sdk": "^2.2.0", "@testing-library/jest-dom": "^5.11.4", "@testing-library/react": "^11.1.0", @@ -35,12 +28,12 @@ "apollo-boost": "^0.4.9", "apollo-client": "^2.6.10", "apollo-utilities": "^1.3.4", + "arb-ts": "^0.0.18", "axios": "^0.20.0", "bnc-notify": "^1.5.0", - "burner-provider": "^1.0.38", "dotenv": "^8.2.0", "eth-hooks": "^1.1.2", - "ethers": "^5.0.31", + "ethers": "^5.3.0", "graphiql": "^1.0.5", "graphql": "^15.3.0", "isomorphic-fetch": "^3.0.0", @@ -87,6 +80,7 @@ "scripts": { "build": "react-scripts build", "eject": "react-scripts eject", + "prestart": "node ./scripts/create_contracts.js", "start": "react-scripts start", "test": "react-scripts test", "lint": "eslint --config ./.eslintrc.js --ignore-path ./.eslintignore ./src/**/*", diff --git a/packages/react-app/scripts/create_contracts.js b/packages/react-app/scripts/create_contracts.js new file mode 100644 index 000000000..539d2de93 --- /dev/null +++ b/packages/react-app/scripts/create_contracts.js @@ -0,0 +1,11 @@ +const fs = require("fs"); + +if (!fs.existsSync("./src/contracts/hardhat_contracts.json")) { + try { + fs.writeFileSync("./src/contracts/hardhat_contracts.json", JSON.stringify({})); + + console.log("src/contracts/hardhat_contracts.json created."); + } catch (error) { + console.log(error); + } +} diff --git a/packages/react-app/src/App.jsx b/packages/react-app/src/App.jsx index b01456f18..2f93ab3c8 100644 --- a/packages/react-app/src/App.jsx +++ b/packages/react-app/src/App.jsx @@ -1,15 +1,12 @@ -import { StaticJsonRpcProvider, Web3Provider } from "@ethersproject/providers"; -import { formatEther, parseEther } from "@ethersproject/units"; import WalletConnectProvider from "@walletconnect/web3-provider"; import { Alert, Button, Col, Menu, Row } from "antd"; import "antd/dist/antd.css"; -import { useUserAddress } from "eth-hooks"; import React, { useCallback, useEffect, useState } from "react"; import { BrowserRouter, Link, Route, Switch } from "react-router-dom"; import Web3Modal from "web3modal"; import "./App.css"; import { Account, Contract, Faucet, GasGauge, Header, Ramp, ThemeSwitch } from "./components"; -import { DAI_ABI, DAI_ADDRESS, INFURA_ID, NETWORK, NETWORKS } from "./constants"; +import { INFURA_ID, NETWORK, NETWORKS } from "./constants"; import { Transactor } from "./helpers"; import { useBalance, @@ -17,13 +14,14 @@ import { useContractReader, useEventListener, useExchangePrice, - useExternalContractLoader, useGasPrice, useOnBlock, - useUserProvider, + useUserSigner, } from "./hooks"; // import Hints from "./Hints"; import { ExampleUI, Hints, Subgraph } from "./views"; + +const { ethers } = require("ethers"); /* Welcome to ๐Ÿ— scaffold-eth ! @@ -48,6 +46,7 @@ const targetNetwork = NETWORKS.localhost; // <------- select your target fronten // ๐Ÿ˜ฌ Sorry for all the console logging const DEBUG = true; +const NETWORKCHECK = false; // ๐Ÿ›ฐ providers if (DEBUG) console.log("๐Ÿ“ก Connecting to Mainnet Ethereum"); @@ -56,8 +55,8 @@ if (DEBUG) console.log("๐Ÿ“ก Connecting to Mainnet Ethereum"); // // attempt to connect to our own scaffold eth rpc and if that fails fall back to infura... // Using StaticJsonRpcProvider as the chainId won't change see https://github.com/ethers-io/ethers.js/issues/901 -const scaffoldEthProvider = new StaticJsonRpcProvider("https://rpc.scaffoldeth.io:48544"); -const mainnetInfura = new StaticJsonRpcProvider("https://mainnet.infura.io/v3/" + INFURA_ID); +const scaffoldEthProvider = new ethers.providers.StaticJsonRpcProvider("https://rpc.scaffoldeth.io:48544"); +const mainnetInfura = new ethers.providers.StaticJsonRpcProvider("https://mainnet.infura.io/v3/" + INFURA_ID); // ( โš ๏ธ Getting "failed to meet quorum" errors? Check your INFURA_I // ๐Ÿ  Your local provider is usually pointed at your local blockchain @@ -65,7 +64,7 @@ const localProviderUrl = targetNetwork.rpcUrl; // as you deploy to other networks you can set REACT_APP_PROVIDER=https://dai.poa.network in packages/react-app/.env const localProviderUrlFromEnv = process.env.REACT_APP_PROVIDER ? process.env.REACT_APP_PROVIDER : localProviderUrl; if (DEBUG) console.log("๐Ÿ  Connecting to provider:", localProviderUrlFromEnv); -const localProvider = new StaticJsonRpcProvider(localProviderUrlFromEnv); +const localProvider = new ethers.providers.StaticJsonRpcProvider(localProviderUrlFromEnv); // ๐Ÿ”ญ block explorer URL const blockExplorer = targetNetwork.blockExplorer; @@ -97,23 +96,34 @@ function App(props) { const mainnetProvider = scaffoldEthProvider && scaffoldEthProvider._network ? scaffoldEthProvider : mainnetInfura; const [injectedProvider, setInjectedProvider] = useState(); + const [address, setAddress] = useState(); /* ๐Ÿ’ต This hook will get the price of ETH from ๐Ÿฆ„ Uniswap: */ const price = useExchangePrice(targetNetwork, mainnetProvider); /* ๐Ÿ”ฅ This hook will get the price of Gas from โ›ฝ๏ธ EtherGasStation */ const gasPrice = useGasPrice(targetNetwork, "fast"); // Use your injected provider from ๐ŸฆŠ Metamask or if you don't have it then instantly generate a ๐Ÿ”ฅ burner wallet. - const userProvider = useUserProvider(injectedProvider, localProvider); - const address = useUserAddress(userProvider); + const userSigner = useUserSigner(injectedProvider, localProvider); + + useEffect(() => { + async function getAddress() { + if (userSigner) { + const newAddress = await userSigner.getAddress(); + setAddress(newAddress); + } + } + getAddress(); + }, [userSigner]); // You can warn the user if you would like them to be on a specific network const localChainId = localProvider && localProvider._network && localProvider._network.chainId; - const selectedChainId = userProvider && userProvider._network && userProvider._network.chainId; + const selectedChainId = + userSigner && userSigner.provider && userSigner.provider._network && userSigner.provider._network.chainId; // For more hooks, check out ๐Ÿ”—eth-hooks at: https://www.npmjs.com/package/eth-hooks // The transactor wraps transactions and provides notificiations - const tx = Transactor(userProvider, gasPrice); + const tx = Transactor(userSigner, gasPrice); // Faucet Tx can be used to send funds from the faucet const faucetTx = Transactor(localProvider, gasPrice); @@ -127,13 +137,13 @@ function App(props) { // Load in your local ๐Ÿ“ contract and read a value from it: const readContracts = useContractLoader(localProvider); - // If you want to make ๐Ÿ” write transactions to your contracts, use the userProvider: - const writeContracts = useContractLoader(userProvider); + // If you want to make ๐Ÿ” write transactions to your contracts, use the userSigner: + const writeContracts = useContractLoader(userSigner, { chainId: localChainId }); // EXTERNAL CONTRACT EXAMPLE: // // If you want to bring in the mainnet DAI contract it would look like: - const mainnetDAIContract = useExternalContractLoader(mainnetProvider, DAI_ADDRESS, DAI_ABI); + const mainnetContracts = useContractLoader(mainnetProvider); // If you want to call a function on a new block useOnBlock(mainnetProvider, () => { @@ -141,7 +151,7 @@ function App(props) { }); // Then read your DAI balance like: - const myMainnetDAIBalance = useContractReader({ DAI: mainnetDAIContract }, "DAI", "balanceOf", [ + const myMainnetDAIBalance = useContractReader(mainnetContracts, "DAI", "balanceOf", [ "0x34aA3F359A9D614239015126635CE7732c18fDF3", ]); @@ -169,17 +179,18 @@ function App(props) { yourMainnetBalance && readContracts && writeContracts && - mainnetDAIContract + mainnetContracts ) { console.log("_____________________________________ ๐Ÿ— scaffold-eth _____________________________________"); console.log("๐ŸŒŽ mainnetProvider", mainnetProvider); console.log("๐Ÿ  localChainId", localChainId); console.log("๐Ÿ‘ฉโ€๐Ÿ’ผ selected address:", address); console.log("๐Ÿ•ต๐Ÿปโ€โ™‚๏ธ selectedChainId:", selectedChainId); - console.log("๐Ÿ’ต yourLocalBalance", yourLocalBalance ? formatEther(yourLocalBalance) : "..."); - console.log("๐Ÿ’ต yourMainnetBalance", yourMainnetBalance ? formatEther(yourMainnetBalance) : "..."); + console.log("๐Ÿ’ต yourLocalBalance", yourLocalBalance ? ethers.utils.formatEther(yourLocalBalance) : "..."); + console.log("๐Ÿ’ต yourMainnetBalance", yourMainnetBalance ? ethers.utils.formatEther(yourMainnetBalance) : "..."); console.log("๐Ÿ“ readContracts", readContracts); - console.log("๐ŸŒ DAI contract on mainnet:", mainnetDAIContract); + console.log("๐ŸŒ DAI contract on mainnet:", mainnetContracts); + console.log("๐Ÿ’ต yourMainnetDAIBalance", myMainnetDAIBalance); console.log("๐Ÿ” writeContracts", writeContracts); } }, [ @@ -190,11 +201,11 @@ function App(props) { yourMainnetBalance, readContracts, writeContracts, - mainnetDAIContract, + mainnetContracts, ]); let networkDisplay = ""; - if (localChainId && selectedChainId && localChainId !== selectedChainId) { + if (NETWORKCHECK && localChainId && selectedChainId && localChainId !== selectedChainId) { const networkSelected = NETWORK(selectedChainId); const networkLocal = NETWORK(localChainId); if (selectedChainId === 1337 && localChainId === 31337) { @@ -241,7 +252,23 @@ function App(props) { const loadWeb3Modal = useCallback(async () => { const provider = await web3Modal.connect(); - setInjectedProvider(new Web3Provider(provider)); + setInjectedProvider(new ethers.providers.Web3Provider(provider)); + + provider.on("chainChanged", chainId => { + console.log(`chain changed to ${chainId}! updating providers`); + setInjectedProvider(new ethers.providers.Web3Provider(provider)); + }); + + provider.on("accountsChanged", () => { + console.log(`account changed!`); + setInjectedProvider(new ethers.providers.Web3Provider(provider)); + }); + + // Subscribe to session disconnection + provider.on("disconnect", (code, reason) => { + console.log(code, reason); + logoutOfWeb3Modal(); + }); }, [setInjectedProvider]); useEffect(() => { @@ -256,7 +283,7 @@ function App(props) { }, [setRoute]); let faucetHint = ""; - const faucetAvailable = localProvider && localProvider.connection && targetNetwork.name === "localhost"; + const faucetAvailable = localProvider && localProvider.connection && targetNetwork.name.indexOf("local") !== -1; const [faucetClicked, setFaucetClicked] = useState(false); if ( @@ -265,7 +292,7 @@ function App(props) { localProvider._network && localProvider._network.chainId === 31337 && yourLocalBalance && - formatEther(yourLocalBalance) <= 0 + ethers.utils.formatEther(yourLocalBalance) <= 0 ) { faucetHint = (
@@ -274,7 +301,7 @@ function App(props) { onClick={() => { faucetTx({ to: address, - value: parseEther("0.01"), + value: ethers.utils.parseEther("0.01"), }); setFaucetClicked(true); }} @@ -354,32 +381,11 @@ function App(props) { - - {/* uncomment for a second contract: - - */} - - {/* Uncomment to display and interact with an external contract (DAI on mainnet): - - */} + {/* + + */} { - web3Modal.cachedProvider && - setTimeout(() => { - window.location.reload(); - }, 1); - }); - -window.ethereum && - window.ethereum.on("accountsChanged", accounts => { - web3Modal.cachedProvider && - setTimeout(() => { - window.location.reload(); - }, 1); - }); -/* eslint-enable */ - export default App; diff --git a/packages/react-app/src/components/Balance.jsx b/packages/react-app/src/components/Balance.jsx index 2b165f559..a36f22586 100644 --- a/packages/react-app/src/components/Balance.jsx +++ b/packages/react-app/src/components/Balance.jsx @@ -1,7 +1,8 @@ -import { formatEther } from "@ethersproject/units"; import React, { useState } from "react"; import { useBalance } from "../hooks"; +const { utils } = require("ethers"); + /* ~ What it does? ~ @@ -47,7 +48,7 @@ export default function Balance(props) { } if (usingBalance) { - const etherBalance = formatEther(usingBalance); + const etherBalance = utils.formatEther(usingBalance); parseFloat(etherBalance).toFixed(2); floatBalance = parseFloat(etherBalance); } diff --git a/packages/react-app/src/components/Contract/FunctionForm.jsx b/packages/react-app/src/components/Contract/FunctionForm.jsx index d73da9c6b..9ce66d931 100644 --- a/packages/react-app/src/components/Contract/FunctionForm.jsx +++ b/packages/react-app/src/components/Contract/FunctionForm.jsx @@ -1,14 +1,13 @@ /* eslint-disable jsx-a11y/click-events-have-key-events */ /* eslint-disable jsx-a11y/no-static-element-interactions */ /* eslint-disable jsx-a11y/accessible-emoji */ -import { BigNumber } from "@ethersproject/bignumber"; import { Button, Col, Divider, Input, Row, Tooltip } from "antd"; import React, { useState } from "react"; import Blockies from "react-blockies"; import { Transactor } from "../../helpers"; import tryToDisplay from "./utils"; -const { utils } = require("ethers"); +const { utils, BigNumber } = require("ethers"); export default function FunctionForm({ contractFunction, functionInfo, provider, gasPrice, triggerRefresh }) { const [form, setForm] = useState({}); @@ -203,6 +202,9 @@ export default function FunctionForm({ contractFunction, functionInfo, provider, if (txValue) { overrides.value = txValue; // ethers.utils.parseEther() } + if (gasPrice) { + overrides.gasPrice = gasPrice; + } // Uncomment this if you want to skip the gas estimation for each transaction // overrides.gasLimit = hexlify(1200000); diff --git a/packages/react-app/src/components/Contract/index.jsx b/packages/react-app/src/components/Contract/index.jsx index fb9fae439..78e1fb49f 100644 --- a/packages/react-app/src/components/Contract/index.jsx +++ b/packages/react-app/src/components/Contract/index.jsx @@ -53,8 +53,9 @@ export default function Contract({ show, price, blockExplorer, + chainId, }) { - const contracts = useContractLoader(provider); + const contracts = useContractLoader(provider, { chainId }); let contract; if (!customContract) { contract = contracts ? contracts[name] : ""; diff --git a/packages/react-app/src/components/Contract/utils.js b/packages/react-app/src/components/Contract/utils.js index ffdc37345..611d23dd2 100644 --- a/packages/react-app/src/components/Contract/utils.js +++ b/packages/react-app/src/components/Contract/utils.js @@ -1,13 +1,13 @@ -import { formatUnits } from "@ethersproject/units"; import React from "react"; import { Address } from ".."; +const { utils } = require("ethers"); const tryToDisplay = thing => { if (thing && thing.toNumber) { try { return thing.toNumber(); } catch (e) { - return "ฮž" + formatUnits(thing, "ether"); + return "ฮž" + utils.formatUnits(thing, "ether"); } } if (thing && thing.indexOf && thing.indexOf("0x") === 0 && thing.length === 42) { diff --git a/packages/react-app/src/components/Faucet.jsx b/packages/react-app/src/components/Faucet.jsx index b0bc38231..a3143aa47 100644 --- a/packages/react-app/src/components/Faucet.jsx +++ b/packages/react-app/src/components/Faucet.jsx @@ -1,5 +1,4 @@ import { SendOutlined } from "@ant-design/icons"; -import { parseEther } from "@ethersproject/units"; import { Button, Input, Tooltip } from "antd"; import { useLookupAddress } from "eth-hooks"; import React, { useCallback, useState } from "react"; @@ -7,6 +6,8 @@ import Blockies from "react-blockies"; import { Transactor } from "../helpers"; import Wallet from "./Wallet"; +const { utils } = require("ethers"); + // improved a bit by converting address to ens if it exists // added option to directly input ens name // added placeholder option @@ -86,7 +87,7 @@ export default function Faucet(props) { onClick={() => { tx({ to: address, - value: parseEther("0.01"), + value: utils.parseEther("0.01"), }); setAddress(""); }} diff --git a/packages/react-app/src/components/L2Bridge.jsx b/packages/react-app/src/components/L2Bridge.jsx new file mode 100644 index 000000000..f4b0a84f1 --- /dev/null +++ b/packages/react-app/src/components/L2Bridge.jsx @@ -0,0 +1,426 @@ +/* eslint-disable jsx-a11y/accessible-emoji */ + +import { utils, ethers } from "ethers"; +import { Button, Input, Form, Select, InputNumber, Table, Radio } from "antd"; +import React, { useState, useEffect } from "react"; +import { useContractLoader, useOnBlock } from "../hooks"; +import { NETWORKS } from "../constants"; +import { Transactor } from "../helpers"; + +/* +This is a component for bridging between L1 & L2 +Currently it supports Testnet deposits for Arbitrum & Optimism + + __ _______ _____ + \ \ / /_ _| __ \ + \ \ /\ / / | | | |__) | + \ \/ \/ / | | | ___/ + \ /\ / _| |_| | + \/ \/ |_____|_| + + +*/ + +export default function L2ArbitrumBridge({ address, userSigner }) { + const [L1EthBalance, setL1EthBalance] = useState("..."); + const [L2EthBalance, setL2EthBalance] = useState("..."); + const [L1Provider, setL1Provider] = useState(""); + const [L2Provider, setL2Provider] = useState(""); + const [rollup, setRollup] = useState("arbitrum"); + const [environment, setEnvironment] = useState("test"); + + const rollupConfig = { + arbitrum: { + test: { L1: NETWORKS.rinkeby, L2: NETWORKS.rinkebyArbitrum }, + main: { L1: NETWORKS.mainnet, L2: NETWORKS.arbitrum }, + local: { L1: NETWORKS.localArbitrumL1, L2: NETWORKS.localArbitrum }, + }, + optimism: { + test: { L1: NETWORKS.kovan, L2: NETWORKS.kovanOptimism }, + local: { L1: NETWORKS.localOptimismL1, L2: NETWORKS.localOptimism }, + }, + }; + + const activeConfig = rollupConfig[rollup][environment]; + + const selectedChainId = + userSigner && userSigner.provider && userSigner.provider._network && userSigner.provider._network.chainId; + + const tx = Transactor(userSigner); + + useEffect(() => { + async function setProviders() { + const L1 = activeConfig.L1; + const L2 = activeConfig.L2; + setL1Provider(new ethers.providers.StaticJsonRpcProvider(L1.rpcUrl)); + setL2Provider(new ethers.providers.StaticJsonRpcProvider(L2.rpcUrl)); + setL1EthBalance("..."); + setL2EthBalance("..."); + } + setProviders(); + }, [rollup]); + + const contracts = useContractLoader(userSigner, { externalContracts: L1BridgeMetadata, hardhatContracts: {} }); + + useOnBlock(L1Provider, async () => { + console.log(`โ›“ A new mainnet block is here: ${L1Provider._lastBlockNumber}`); + const yourL1Balance = await L1Provider.getBalance(address); + setL1EthBalance(yourL1Balance ? ethers.utils.formatEther(yourL1Balance) : "..."); + const yourL2Balance = await L2Provider.getBalance(address); + setL2EthBalance(yourL2Balance ? ethers.utils.formatEther(yourL2Balance) : "..."); + }); + + const { Option } = Select; + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 8 }, + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 12 }, + }, + }; + const tailFormItemLayout = { + wrapperCol: { + xs: { + span: 24, + offset: 0, + }, + sm: { + span: 12, + offset: 8, + }, + }, + }; + + const columns = [ + { + title: "", + dataIndex: "token", + key: "token", + align: "center", + }, + { + title: `${activeConfig.L1.name} L1 Balance`, + dataIndex: "l1", + key: "l1", + align: "center", + }, + { + title: `${activeConfig.L1.name} ${rollup} Balance`, + dataIndex: "l2", + key: "l2", + align: "center", + }, + ]; + + const data = [ + { + key: "1", + token: "ETH", + l1: "ฮž" + L1EthBalance, + l2: "ฮž" + L2EthBalance, + }, + ]; + + const [form] = Form.useForm(); + + const onAssetChange = value => { + console.log(value); + }; + + async function onFinish(values) { + console.log(contracts); + console.log(values.amount.toString()); + console.log(rollup); + let newTx; + try { + if (rollup === "arbitrum") { + newTx = await tx( + contracts.Inbox.depositEth(1_300_000, { + value: utils.parseEther(values.amount.toString()), + gasLimit: 300000, + }), + ); + } else if (rollup === "optimism") { + newTx = await tx( + contracts.OVM_L1StandardBridge.depositETH(1_300_000, "0x", { + value: utils.parseEther(values.amount.toString()), + }), + ); + } + await newTx.wait(); + console.log("woop!"); + } catch (e) { + console.log(e); + console.log("something went wrong!"); + } + } + + const onReset = () => { + form.resetFields(); + }; + + const wrongNetwork = selectedChainId !== activeConfig.L1.chainId; + + return ( +
+
+

Welcome to the L2 Deposit Bridge!

+ { + setRollup(e.target.value); + }} + style={{ marginBottom: 10 }} + > + Arbitrum + Optimism + + + + + + + + + + + + + + + + + + + + + ); +} + +// Arbitrum Inbox https://rinkeby.etherscan.io/address/0xa157dc79ca26d69c3b1282d03ec42bdee2790a8f#code +const ArbitrumInboxABI = [ + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "uint256", name: "messageNum", type: "uint256" }, + { indexed: false, internalType: "bytes", name: "data", type: "bytes" }, + ], + name: "InboxMessageDelivered", + type: "event", + }, + { + anonymous: false, + inputs: [{ indexed: true, internalType: "uint256", name: "messageNum", type: "uint256" }], + name: "InboxMessageDeliveredFromOrigin", + type: "event", + }, + { + anonymous: false, + inputs: [{ indexed: false, internalType: "address", name: "newSource", type: "address" }], + name: "WhitelistSourceUpdated", + type: "event", + }, + { + inputs: [], + name: "bridge", + outputs: [{ internalType: "contract IBridge", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "destAddr", type: "address" }, + { internalType: "uint256", name: "l2CallValue", type: "uint256" }, + { internalType: "uint256", name: "maxSubmissionCost", type: "uint256" }, + { internalType: "address", name: "excessFeeRefundAddress", type: "address" }, + { internalType: "address", name: "callValueRefundAddress", type: "address" }, + { internalType: "uint256", name: "maxGas", type: "uint256" }, + { internalType: "uint256", name: "gasPriceBid", type: "uint256" }, + { internalType: "bytes", name: "data", type: "bytes" }, + ], + name: "createRetryableTicket", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "payable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "maxSubmissionCost", type: "uint256" }], + name: "depositEth", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "payable", + type: "function", + }, + { + inputs: [ + { internalType: "contract IBridge", name: "_bridge", type: "address" }, + { internalType: "address", name: "_whitelist", type: "address" }, + ], + name: "initialize", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "isMaster", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "maxGas", type: "uint256" }, + { internalType: "uint256", name: "gasPriceBid", type: "uint256" }, + { internalType: "address", name: "destAddr", type: "address" }, + { internalType: "uint256", name: "amount", type: "uint256" }, + { internalType: "bytes", name: "data", type: "bytes" }, + ], + name: "sendContractTransaction", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "maxGas", type: "uint256" }, + { internalType: "uint256", name: "gasPriceBid", type: "uint256" }, + { internalType: "address", name: "destAddr", type: "address" }, + { internalType: "bytes", name: "data", type: "bytes" }, + ], + name: "sendL1FundedContractTransaction", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "payable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "maxGas", type: "uint256" }, + { internalType: "uint256", name: "gasPriceBid", type: "uint256" }, + { internalType: "uint256", name: "nonce", type: "uint256" }, + { internalType: "address", name: "destAddr", type: "address" }, + { internalType: "bytes", name: "data", type: "bytes" }, + ], + name: "sendL1FundedUnsignedTransaction", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "payable", + type: "function", + }, + { + inputs: [{ internalType: "bytes", name: "messageData", type: "bytes" }], + name: "sendL2Message", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "bytes", name: "messageData", type: "bytes" }], + name: "sendL2MessageFromOrigin", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "maxGas", type: "uint256" }, + { internalType: "uint256", name: "gasPriceBid", type: "uint256" }, + { internalType: "uint256", name: "nonce", type: "uint256" }, + { internalType: "address", name: "destAddr", type: "address" }, + { internalType: "uint256", name: "amount", type: "uint256" }, + { internalType: "bytes", name: "data", type: "bytes" }, + ], + name: "sendUnsignedTransaction", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "newSource", type: "address" }], + name: "updateWhitelistSource", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "whitelist", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, +]; + +// https://github.com/ethereum-optimism/optimism/blob/2bd49730fa8d2c10953873f0ccc792198a49d5c9/packages/contracts/contracts/optimistic-ethereum/iOVM/bridge/tokens/iOVM_L1StandardBridge.sol +const OVM_L1StandardBridgeABI = [ + "function depositETH(uint32 _l2Gas,bytes calldata _data) external payable", + "function depositETHTo(address _to,uint32 _l2Gas,bytes calldata _data) external payable", + "function finalizeETHWithdrawal (address _from,address _to,uint _amount,bytes calldata _data) external", +]; + +const L1BridgeMetadata = { + // Arbitrium Contract's + 44010: { + contracts: { + Inbox: { + address: "0xA4d796Ad4e79aFB703340a596AEd88f8a5924183", + abi: ArbitrumInboxABI, + }, + }, + }, + 4: { + contracts: { + Inbox: { + address: "0x578bade599406a8fe3d24fd7f7211c0911f5b29e", + abi: ArbitrumInboxABI, + }, + }, + }, + // Optimism Contract's + 31337: { + contracts: { + OVM_L1StandardBridge: { + address: "0x998abeb3E57409262aE5b751f60747921B33613E", + abi: OVM_L1StandardBridgeABI, + }, + }, + }, + 42: { + contracts: { + OVM_L1StandardBridge: { + address: "0x22F24361D548e5FaAfb36d1437839f080363982B", + abi: OVM_L1StandardBridgeABI, + }, + }, + }, +}; diff --git a/packages/react-app/src/components/Swap.jsx b/packages/react-app/src/components/Swap.jsx index 7ba676d8d..e78049516 100644 --- a/packages/react-app/src/components/Swap.jsx +++ b/packages/react-app/src/components/Swap.jsx @@ -1,5 +1,4 @@ import { RetweetOutlined, SettingOutlined } from "@ant-design/icons"; -import { formatUnits, parseUnits } from "@ethersproject/units"; import { ChainId, Fetcher, Percent, Token, TokenAmount, Trade, WETH } from "@uniswap/sdk"; import { abi as IUniswapV2Router02ABI } from "@uniswap/v2-periphery/build/IUniswapV2Router02.json"; import { @@ -150,7 +149,7 @@ function Swap({ selectedProvider, tokenListURI }) { setAmountInMax(); bestTrade = Trade.bestTradeExactIn( listOfPairs.filter(item => item), - new TokenAmount(tokens[tokenIn], parseUnits(amountIn.toString(), tokens[tokenIn].decimals)), + new TokenAmount(tokens[tokenIn], ethers.utils.parseUnits(amountIn.toString(), tokens[tokenIn].decimals)), tokens[tokenOut], { maxNumResults: 3, maxHops: 1 }, ); @@ -164,7 +163,7 @@ function Swap({ selectedProvider, tokenListURI }) { bestTrade = Trade.bestTradeExactOut( listOfPairs.filter(item => item), tokens[tokenIn], - new TokenAmount(tokens[tokenOut], parseUnits(amountOut.toString(), tokens[tokenOut].decimals)), + new TokenAmount(tokens[tokenOut], ethers.utils.parseUnits(amountOut.toString(), tokens[tokenOut].decimals)), { maxNumResults: 3, maxHops: 1 }, ); if (bestTrade[0]) { @@ -260,7 +259,7 @@ function Swap({ selectedProvider, tokenListURI }) { const approveRouter = async () => { const approvalAmount = exact === "in" - ? ethers.utils.hexlify(parseUnits(amountIn.toString(), tokens[tokenIn].decimals)) + ? ethers.utils.hexlify(ethers.utils.parseUnits(amountIn.toString(), tokens[tokenIn].decimals)) : amountInMax.raw.toString(); console.log(approvalAmount); const approval = updateRouterAllowance(approvalAmount); @@ -300,7 +299,7 @@ function Swap({ selectedProvider, tokenListURI }) { const address = accountList[0]; if (exact === "in") { - const _amountIn = ethers.utils.hexlify(parseUnits(amountIn.toString(), tokens[tokenIn].decimals)); + const _amountIn = ethers.utils.hexlify(ethers.utils.parseUnits(amountIn.toString(), tokens[tokenIn].decimals)); const _amountOutMin = ethers.utils.hexlify(ethers.BigNumber.from(amountOutMin.raw.toString())); if (tokenIn === "ETH") { call = "swapExactETHForTokens"; @@ -311,7 +310,9 @@ function Swap({ selectedProvider, tokenListURI }) { args = [_amountIn, _amountOutMin, path, address, deadline]; } } else if (exact === "out") { - const _amountOut = ethers.utils.hexlify(parseUnits(amountOut.toString(), tokens[tokenOut].decimals)); + const _amountOut = ethers.utils.hexlify( + ethers.utils.parseUnits(amountOut.toString(), tokens[tokenOut].decimals), + ); const _amountInMax = ethers.utils.hexlify(ethers.BigNumber.from(amountInMax.raw.toString())); if (tokenIn === "ETH") { call = "swapETHForExactTokens"; @@ -359,19 +360,19 @@ function Swap({ selectedProvider, tokenListURI }) { }; const insufficientBalance = balanceIn - ? parseFloat(formatUnits(balanceIn, tokens[tokenIn].decimals)) < amountIn + ? parseFloat(ethers.utils.formatUnits(balanceIn, tokens[tokenIn].decimals)) < amountIn : null; const inputIsToken = tokenIn !== "ETH"; const insufficientAllowance = !inputIsToken ? false : routerAllowance - ? parseFloat(formatUnits(routerAllowance, tokens[tokenIn].decimals)) < amountIn + ? parseFloat(ethers.utils.formatUnits(routerAllowance, tokens[tokenIn].decimals)) < amountIn : null; const formattedBalanceIn = balanceIn - ? parseFloat(formatUnits(balanceIn, tokens[tokenIn].decimals)).toPrecision(6) + ? parseFloat(ethers.utils.formatUnits(balanceIn, tokens[tokenIn].decimals)).toPrecision(6) : null; const formattedBalanceOut = balanceOut - ? parseFloat(formatUnits(balanceOut, tokens[tokenOut].decimals)).toPrecision(6) + ? parseFloat(ethers.utils.formatUnits(balanceOut, tokens[tokenOut].decimals)).toPrecision(6) : null; const metaIn = @@ -488,7 +489,7 @@ function Swap({ selectedProvider, tokenListURI }) { type="link" onClick={() => { setAmountOut(); - setAmountIn(formatUnits(balanceIn, tokens[tokenIn].decimals)); + setAmountIn(ethers.utils.formatUnits(balanceIn, tokens[tokenIn].decimals)); setAmountOutMin(); setAmountInMax(); setExact("in"); @@ -638,7 +639,7 @@ function Swap({ selectedProvider, tokenListURI }) { {blockNumber} - {routerAllowance ? formatUnits(routerAllowance, tokens[tokenIn].decimals) : null} + {routerAllowance ? ethers.utils.formatUnits(routerAllowance, tokens[tokenIn].decimals) : null} {routerAllowance > 0 ? : null} diff --git a/packages/react-app/src/components/TokenBalance.jsx b/packages/react-app/src/components/TokenBalance.jsx index 9980fc16f..a6c161313 100644 --- a/packages/react-app/src/components/TokenBalance.jsx +++ b/packages/react-app/src/components/TokenBalance.jsx @@ -1,7 +1,8 @@ -import { formatEther } from "@ethersproject/units"; import { useTokenBalance } from "eth-hooks"; import React, { useState } from "react"; +import { utils } from "ethers"; + export default function TokenBalance(props) { const [dollarMode, setDollarMode] = useState(true); @@ -17,7 +18,7 @@ export default function TokenBalance(props) { } if (usingBalance) { - const etherBalance = formatEther(usingBalance); + const etherBalance = utils.formatEther(usingBalance); parseFloat(etherBalance).toFixed(2); floatBalance = parseFloat(etherBalance); } diff --git a/packages/react-app/src/components/Wallet.jsx b/packages/react-app/src/components/Wallet.jsx index 4228fcaba..84ca1882d 100644 --- a/packages/react-app/src/components/Wallet.jsx +++ b/packages/react-app/src/components/Wallet.jsx @@ -1,10 +1,8 @@ import { KeyOutlined, QrcodeOutlined, SendOutlined, WalletOutlined } from "@ant-design/icons"; -import { parseEther } from "@ethersproject/units"; import { Button, Modal, Spin, Tooltip, Typography } from "antd"; -import { useUserAddress } from "eth-hooks"; import { ethers } from "ethers"; import QR from "qrcode.react"; -import React, { useState } from "react"; +import React, { useState, useEffect } from "react"; import { Transactor } from "../helpers"; import Address from "./Address"; import AddressInput from "./AddressInput"; @@ -42,7 +40,17 @@ const { Text, Paragraph } = Typography; */ export default function Wallet(props) { - const signerAddress = useUserAddress(props.provider); + const [signerAddress, setSignerAddress] = useState(); + useEffect(() => { + async function getAddress() { + if (props.signer) { + const newAddress = await props.signer.getAddress(); + setSignerAddress(newAddress); + } + } + getAddress(); + }, [props.signer]); + const selectedAddress = props.address || signerAddress; const [open, setOpen] = useState(); @@ -316,10 +324,10 @@ export default function Wallet(props) { let value; try { - value = parseEther("" + amount); + value = ethers.utils.parseEther("" + amount); } catch (e) { // failed to parseEther, try something else - value = parseEther("" + parseFloat(amount).toFixed(8)); + value = ethers.utils.parseEther("" + parseFloat(amount).toFixed(8)); } tx({ diff --git a/packages/react-app/src/components/index.js b/packages/react-app/src/components/index.js index 00258b49f..f2a460ebe 100644 --- a/packages/react-app/src/components/index.js +++ b/packages/react-app/src/components/index.js @@ -16,3 +16,4 @@ export { default as ThemeSwitch } from "./ThemeSwitch"; export { default as Timeline } from "./Timeline"; export { default as TokenBalance } from "./TokenBalance"; export { default as Wallet } from "./Wallet"; +export { default as L2Bridge } from "./L2Bridge"; diff --git a/packages/react-app/src/constants.js b/packages/react-app/src/constants.js index 1cb79300b..b43406614 100644 --- a/packages/react-app/src/constants.js +++ b/packages/react-app/src/constants.js @@ -7,295 +7,6 @@ export const ETHERSCAN_KEY = "PSW8C433Q667DVEX5BCRMGNAH9FSGFZ7Q8"; // BLOCKNATIVE ID FOR Notify.js: export const BLOCKNATIVE_DAPPID = "0b58206a-f3c0-4701-a62f-73c7243e8c77"; -// EXTERNAL CONTRACTS - -export const DAI_ADDRESS = "0x6B175474E89094C44Da98b954EedeAC495271d0F"; - -export const DAI_ABI = [ - { - inputs: [{ internalType: "uint256", name: "chainId_", type: "uint256" }], - payable: false, - stateMutability: "nonpayable", - type: "constructor", - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: "address", name: "src", type: "address" }, - { indexed: true, internalType: "address", name: "guy", type: "address" }, - { indexed: false, internalType: "uint256", name: "wad", type: "uint256" }, - ], - name: "Approval", - type: "event", - }, - { - anonymous: true, - inputs: [ - { indexed: true, internalType: "bytes4", name: "sig", type: "bytes4" }, - { indexed: true, internalType: "address", name: "usr", type: "address" }, - { indexed: true, internalType: "bytes32", name: "arg1", type: "bytes32" }, - { indexed: true, internalType: "bytes32", name: "arg2", type: "bytes32" }, - { indexed: false, internalType: "bytes", name: "data", type: "bytes" }, - ], - name: "LogNote", - type: "event", - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: "address", name: "src", type: "address" }, - { indexed: true, internalType: "address", name: "dst", type: "address" }, - { indexed: false, internalType: "uint256", name: "wad", type: "uint256" }, - ], - name: "Transfer", - type: "event", - }, - { - constant: true, - inputs: [], - name: "DOMAIN_SEPARATOR", - outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], - payable: false, - stateMutability: "view", - type: "function", - }, - { - constant: true, - inputs: [], - name: "PERMIT_TYPEHASH", - outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], - payable: false, - stateMutability: "view", - type: "function", - }, - { - constant: true, - inputs: [ - { internalType: "address", name: "", type: "address" }, - { internalType: "address", name: "", type: "address" }, - ], - name: "allowance", - outputs: [{ internalType: "uint256", name: "", type: "uint256" }], - payable: false, - stateMutability: "view", - type: "function", - }, - { - constant: false, - inputs: [ - { internalType: "address", name: "usr", type: "address" }, - { internalType: "uint256", name: "wad", type: "uint256" }, - ], - name: "approve", - outputs: [{ internalType: "bool", name: "", type: "bool" }], - payable: false, - stateMutability: "nonpayable", - type: "function", - }, - { - constant: true, - inputs: [{ internalType: "address", name: "", type: "address" }], - name: "balanceOf", - outputs: [{ internalType: "uint256", name: "", type: "uint256" }], - payable: false, - stateMutability: "view", - type: "function", - }, - { - constant: false, - inputs: [ - { internalType: "address", name: "usr", type: "address" }, - { internalType: "uint256", name: "wad", type: "uint256" }, - ], - name: "burn", - outputs: [], - payable: false, - stateMutability: "nonpayable", - type: "function", - }, - { - constant: true, - inputs: [], - name: "decimals", - outputs: [{ internalType: "uint8", name: "", type: "uint8" }], - payable: false, - stateMutability: "view", - type: "function", - }, - { - constant: false, - inputs: [{ internalType: "address", name: "guy", type: "address" }], - name: "deny", - outputs: [], - payable: false, - stateMutability: "nonpayable", - type: "function", - }, - { - constant: false, - inputs: [ - { internalType: "address", name: "usr", type: "address" }, - { internalType: "uint256", name: "wad", type: "uint256" }, - ], - name: "mint", - outputs: [], - payable: false, - stateMutability: "nonpayable", - type: "function", - }, - { - constant: false, - inputs: [ - { internalType: "address", name: "src", type: "address" }, - { internalType: "address", name: "dst", type: "address" }, - { internalType: "uint256", name: "wad", type: "uint256" }, - ], - name: "move", - outputs: [], - payable: false, - stateMutability: "nonpayable", - type: "function", - }, - { - constant: true, - inputs: [], - name: "name", - outputs: [{ internalType: "string", name: "", type: "string" }], - payable: false, - stateMutability: "view", - type: "function", - }, - { - constant: true, - inputs: [{ internalType: "address", name: "", type: "address" }], - name: "nonces", - outputs: [{ internalType: "uint256", name: "", type: "uint256" }], - payable: false, - stateMutability: "view", - type: "function", - }, - { - constant: false, - inputs: [ - { internalType: "address", name: "holder", type: "address" }, - { internalType: "address", name: "spender", type: "address" }, - { internalType: "uint256", name: "nonce", type: "uint256" }, - { internalType: "uint256", name: "expiry", type: "uint256" }, - { internalType: "bool", name: "allowed", type: "bool" }, - { internalType: "uint8", name: "v", type: "uint8" }, - { internalType: "bytes32", name: "r", type: "bytes32" }, - { internalType: "bytes32", name: "s", type: "bytes32" }, - ], - name: "permit", - outputs: [], - payable: false, - stateMutability: "nonpayable", - type: "function", - }, - { - constant: false, - inputs: [ - { internalType: "address", name: "usr", type: "address" }, - { internalType: "uint256", name: "wad", type: "uint256" }, - ], - name: "pull", - outputs: [], - payable: false, - stateMutability: "nonpayable", - type: "function", - }, - { - constant: false, - inputs: [ - { internalType: "address", name: "usr", type: "address" }, - { internalType: "uint256", name: "wad", type: "uint256" }, - ], - name: "push", - outputs: [], - payable: false, - stateMutability: "nonpayable", - type: "function", - }, - { - constant: false, - inputs: [{ internalType: "address", name: "guy", type: "address" }], - name: "rely", - outputs: [], - payable: false, - stateMutability: "nonpayable", - type: "function", - }, - { - constant: true, - inputs: [], - name: "symbol", - outputs: [{ internalType: "string", name: "", type: "string" }], - payable: false, - stateMutability: "view", - type: "function", - }, - { - constant: true, - inputs: [], - name: "totalSupply", - outputs: [{ internalType: "uint256", name: "", type: "uint256" }], - payable: false, - stateMutability: "view", - type: "function", - }, - { - constant: false, - inputs: [ - { internalType: "address", name: "dst", type: "address" }, - { internalType: "uint256", name: "wad", type: "uint256" }, - ], - name: "transfer", - outputs: [{ internalType: "bool", name: "", type: "bool" }], - payable: false, - stateMutability: "nonpayable", - type: "function", - }, - { - constant: false, - inputs: [ - { internalType: "address", name: "src", type: "address" }, - { internalType: "address", name: "dst", type: "address" }, - { internalType: "uint256", name: "wad", type: "uint256" }, - ], - name: "transferFrom", - outputs: [{ internalType: "bool", name: "", type: "bool" }], - payable: false, - stateMutability: "nonpayable", - type: "function", - }, - { - constant: true, - inputs: [], - name: "version", - outputs: [{ internalType: "string", name: "", type: "string" }], - payable: false, - stateMutability: "view", - type: "function", - }, - { - constant: true, - inputs: [{ internalType: "address", name: "", type: "address" }], - name: "wards", - outputs: [{ internalType: "uint256", name: "", type: "uint256" }], - payable: false, - stateMutability: "view", - type: "function", - }, -]; - -export const NETWORK = chainId => { - for (const n in NETWORKS) { - if (NETWORKS[n].chainId === chainId) { - return NETWORKS[n]; - } - } -}; - export const NETWORKS = { localhost: { name: "localhost", @@ -373,4 +84,71 @@ export const NETWORKS = { faucet: "https://faucet.matic.network/", blockExplorer: "https://mumbai-explorer.matic.today/", }, + localArbitrum: { + name: "localArbitrum", + color: "#50a0ea", + chainId: 153869338190755, + blockExplorer: "", + rpcUrl: `http://localhost:8547`, + }, + localArbitrumL1: { + name: "localArbitrumL1", + color: "#50a0ea", + chainId: 44010, + blockExplorer: "", + rpcUrl: `http://localhost:7545`, + }, + rinkebyArbitrum: { + name: "Arbitrum Testnet", + color: "#50a0ea", + chainId: 421611, + blockExplorer: "https://rinkeby-explorer.arbitrum.io/#/", + rpcUrl: `https://rinkeby.arbitrum.io/rpc`, + }, + arbitrum: { + name: "Arbitrum", + color: "#50a0ea", + chainId: 42161, + blockExplorer: "https://explorer.arbitrum.io/#/", + rpcUrl: `https://arb1.arbitrum.io/rpc`, + gasPrice: 0, + }, + localOptimismL1: { + name: "localOptimismL1", + color: "#f01a37", + chainId: 31337, + blockExplorer: "", + rpcUrl: "http://" + window.location.hostname + ":9545", + }, + localOptimism: { + name: "localOptimism", + color: "#f01a37", + chainId: 420, + blockExplorer: "", + rpcUrl: "http://" + window.location.hostname + ":8545", + gasPrice: 0, + }, + kovanOptimism: { + name: "kovanOptimism", + color: "#f01a37", + chainId: 69, + blockExplorer: "https://kovan-optimistic.etherscan.io/", + rpcUrl: `https://kovan.optimism.io`, + gasPrice: 0, + }, + optimism: { + name: "optimism", + color: "#f01a37", + chainId: 10, + blockExplorer: "https://optimistic.etherscan.io/", + rpcUrl: `https://mainnet.optimism.io`, + }, +}; + +export const NETWORK = chainId => { + for (const n in NETWORKS) { + if (NETWORKS[n].chainId === chainId) { + return NETWORKS[n]; + } + } }; diff --git a/packages/react-app/src/contracts/contracts.js b/packages/react-app/src/contracts/contracts.js deleted file mode 100644 index c7818c88e..000000000 --- a/packages/react-app/src/contracts/contracts.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = ["YourContract"]; \ No newline at end of file diff --git a/packages/react-app/src/contracts/external_contracts.js b/packages/react-app/src/contracts/external_contracts.js new file mode 100644 index 000000000..5ab4769b7 --- /dev/null +++ b/packages/react-app/src/contracts/external_contracts.js @@ -0,0 +1,801 @@ +const ERC20ABI = [ + { + constant: true, + inputs: [], + name: "name", + outputs: [ + { + name: "", + type: "string", + }, + ], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: false, + inputs: [ + { + name: "_spender", + type: "address", + }, + { + name: "_value", + type: "uint256", + }, + ], + name: "approve", + outputs: [ + { + name: "", + type: "bool", + }, + ], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: true, + inputs: [], + name: "totalSupply", + outputs: [ + { + name: "", + type: "uint256", + }, + ], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: false, + inputs: [ + { + name: "_from", + type: "address", + }, + { + name: "_to", + type: "address", + }, + { + name: "_value", + type: "uint256", + }, + ], + name: "transferFrom", + outputs: [ + { + name: "", + type: "bool", + }, + ], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: true, + inputs: [], + name: "decimals", + outputs: [ + { + name: "", + type: "uint8", + }, + ], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [ + { + name: "_owner", + type: "address", + }, + ], + name: "balanceOf", + outputs: [ + { + name: "balance", + type: "uint256", + }, + ], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "symbol", + outputs: [ + { + name: "", + type: "string", + }, + ], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: false, + inputs: [ + { + name: "_to", + type: "address", + }, + { + name: "_value", + type: "uint256", + }, + ], + name: "transfer", + outputs: [ + { + name: "", + type: "bool", + }, + ], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: true, + inputs: [ + { + name: "_owner", + type: "address", + }, + { + name: "_spender", + type: "address", + }, + ], + name: "allowance", + outputs: [ + { + name: "", + type: "uint256", + }, + ], + payable: false, + stateMutability: "view", + type: "function", + }, + { + payable: true, + stateMutability: "payable", + type: "fallback", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + name: "owner", + type: "address", + }, + { + indexed: true, + name: "spender", + type: "address", + }, + { + indexed: false, + name: "value", + type: "uint256", + }, + ], + name: "Approval", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + name: "from", + type: "address", + }, + { + indexed: true, + name: "to", + type: "address", + }, + { + indexed: false, + name: "value", + type: "uint256", + }, + ], + name: "Transfer", + type: "event", + }, +]; +const DAIABI = [ + { + inputs: [ + { + internalType: "uint256", + name: "chainId_", + type: "uint256", + }, + ], + payable: false, + stateMutability: "nonpayable", + type: "constructor", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "src", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "guy", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "wad", + type: "uint256", + }, + ], + name: "Approval", + type: "event", + }, + { + anonymous: true, + inputs: [ + { + indexed: true, + internalType: "bytes4", + name: "sig", + type: "bytes4", + }, + { + indexed: true, + internalType: "address", + name: "usr", + type: "address", + }, + { + indexed: true, + internalType: "bytes32", + name: "arg1", + type: "bytes32", + }, + { + indexed: true, + internalType: "bytes32", + name: "arg2", + type: "bytes32", + }, + { + indexed: false, + internalType: "bytes", + name: "data", + type: "bytes", + }, + ], + name: "LogNote", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "src", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "dst", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "wad", + type: "uint256", + }, + ], + name: "Transfer", + type: "event", + }, + { + constant: true, + inputs: [], + name: "DOMAIN_SEPARATOR", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "PERMIT_TYPEHASH", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + { + internalType: "address", + name: "", + type: "address", + }, + ], + name: "allowance", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: false, + inputs: [ + { + internalType: "address", + name: "usr", + type: "address", + }, + { + internalType: "uint256", + name: "wad", + type: "uint256", + }, + ], + name: "approve", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: true, + inputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + name: "balanceOf", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: false, + inputs: [ + { + internalType: "address", + name: "usr", + type: "address", + }, + { + internalType: "uint256", + name: "wad", + type: "uint256", + }, + ], + name: "burn", + outputs: [], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: true, + inputs: [], + name: "decimals", + outputs: [ + { + internalType: "uint8", + name: "", + type: "uint8", + }, + ], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: false, + inputs: [ + { + internalType: "address", + name: "guy", + type: "address", + }, + ], + name: "deny", + outputs: [], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: false, + inputs: [ + { + internalType: "address", + name: "usr", + type: "address", + }, + { + internalType: "uint256", + name: "wad", + type: "uint256", + }, + ], + name: "mint", + outputs: [], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: false, + inputs: [ + { + internalType: "address", + name: "src", + type: "address", + }, + { + internalType: "address", + name: "dst", + type: "address", + }, + { + internalType: "uint256", + name: "wad", + type: "uint256", + }, + ], + name: "move", + outputs: [], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: true, + inputs: [], + name: "name", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + name: "nonces", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: false, + inputs: [ + { + internalType: "address", + name: "holder", + type: "address", + }, + { + internalType: "address", + name: "spender", + type: "address", + }, + { + internalType: "uint256", + name: "nonce", + type: "uint256", + }, + { + internalType: "uint256", + name: "expiry", + type: "uint256", + }, + { + internalType: "bool", + name: "allowed", + type: "bool", + }, + { + internalType: "uint8", + name: "v", + type: "uint8", + }, + { + internalType: "bytes32", + name: "r", + type: "bytes32", + }, + { + internalType: "bytes32", + name: "s", + type: "bytes32", + }, + ], + name: "permit", + outputs: [], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: false, + inputs: [ + { + internalType: "address", + name: "usr", + type: "address", + }, + { + internalType: "uint256", + name: "wad", + type: "uint256", + }, + ], + name: "pull", + outputs: [], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: false, + inputs: [ + { + internalType: "address", + name: "usr", + type: "address", + }, + { + internalType: "uint256", + name: "wad", + type: "uint256", + }, + ], + name: "push", + outputs: [], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: false, + inputs: [ + { + internalType: "address", + name: "guy", + type: "address", + }, + ], + name: "rely", + outputs: [], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: true, + inputs: [], + name: "symbol", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "totalSupply", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: false, + inputs: [ + { + internalType: "address", + name: "dst", + type: "address", + }, + { + internalType: "uint256", + name: "wad", + type: "uint256", + }, + ], + name: "transfer", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: false, + inputs: [ + { + internalType: "address", + name: "src", + type: "address", + }, + { + internalType: "address", + name: "dst", + type: "address", + }, + { + internalType: "uint256", + name: "wad", + type: "uint256", + }, + ], + name: "transferFrom", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: true, + inputs: [], + name: "version", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + name: "wards", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + payable: false, + stateMutability: "view", + type: "function", + }, +]; + +// Mainnet DAI, Optimism and Arbitrium Rollup Contracts with local addresses +module.exports = { + 1: { + contracts: { + DAI: { + address: "0x6B175474E89094C44Da98b954EedeAC495271d0F", + abi: DAIABI, + }, + UNI: { + address: "0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984", + abi: ERC20ABI, + }, + }, + }, +}; diff --git a/packages/react-app/src/helpers/Transactor.js b/packages/react-app/src/helpers/Transactor.js index 69708d1e1..8a0ec1345 100644 --- a/packages/react-app/src/helpers/Transactor.js +++ b/packages/react-app/src/helpers/Transactor.js @@ -1,22 +1,33 @@ -import { hexlify } from "@ethersproject/bytes"; -import { parseUnits } from "@ethersproject/units"; import { notification } from "antd"; import Notify from "bnc-notify"; import { BLOCKNATIVE_DAPPID } from "../constants"; +const { ethers } = require("ethers"); + // this should probably just be renamed to "notifier" // it is basically just a wrapper around BlockNative's wonderful Notify.js // https://docs.blocknative.com/notify const callbacks = {}; -const DEBUG = true +const DEBUG = true; -export default function Transactor(provider, gasPrice, etherscan) { - if (typeof provider !== "undefined") { +export default function Transactor(providerOrSigner, gasPrice, etherscan) { + if (typeof providerOrSigner !== "undefined") { // eslint-disable-next-line consistent-return return async (tx, callback) => { - const signer = provider.getSigner(); - const network = await provider.getNetwork(); + let signer; + let network; + let provider; + if (ethers.Signer.isSigner(providerOrSigner) === true) { + provider = providerOrSigner.provider; + signer = providerOrSigner; + network = providerOrSigner.provider && (await providerOrSigner.provider.getNetwork()); + } else if (providerOrSigner._isProvider) { + provider = providerOrSigner; + signer = providerOrSigner.getSigner(); + network = await providerOrSigner.getNetwork(); + } + console.log("network", network); const options = { dappId: BLOCKNATIVE_DAPPID, // GET YOUR OWN KEY AT https://account.blocknative.com @@ -24,7 +35,7 @@ export default function Transactor(provider, gasPrice, etherscan) { networkId: network.chainId, // darkMode: Boolean, // (default: false) transactionHandler: txInformation => { - if(DEBUG) console.log("HANDLE TX", txInformation); + if (DEBUG) console.log("HANDLE TX", txInformation); const possibleFunction = callbacks[txInformation.transaction.hash]; if (typeof possibleFunction === "function") { possibleFunction(txInformation.transaction); @@ -46,19 +57,19 @@ export default function Transactor(provider, gasPrice, etherscan) { try { let result; if (tx instanceof Promise) { - if(DEBUG) console.log("AWAITING TX", tx); + if (DEBUG) console.log("AWAITING TX", tx); result = await tx; } else { if (!tx.gasPrice) { - tx.gasPrice = gasPrice || parseUnits("4.1", "gwei"); + tx.gasPrice = gasPrice || ethers.utils.parseUnits("4.1", "gwei"); } if (!tx.gasLimit) { - tx.gasLimit = hexlify(120000); + tx.gasLimit = ethers.utils.hexlify(120000); } - if(DEBUG) console.log("RUNNING TX", tx); + if (DEBUG) console.log("RUNNING TX", tx); result = await signer.sendTransaction(tx); } - if(DEBUG) console.log("RESULT:", result); + if (DEBUG) console.log("RESULT:", result); // console.log("Notify", notify); if (callback) { @@ -94,6 +105,10 @@ export default function Transactor(provider, gasPrice, etherscan) { } } + if (typeof result.wait === "function") { + await result.wait(); + } + return result; } catch (e) { console.log(e); diff --git a/packages/react-app/src/hooks/BurnerSigner.js b/packages/react-app/src/hooks/BurnerSigner.js new file mode 100644 index 000000000..47727203d --- /dev/null +++ b/packages/react-app/src/hooks/BurnerSigner.js @@ -0,0 +1,41 @@ +import { useState, useEffect } from "react"; + +const { ethers } = require("ethers"); + +export default function useBurnerSigner(provider) { + const key = "metaPrivateKey"; + let wallet; + const [signer, setSigner] = useState(); + const [storedValue, setStoredValue] = useState(); + + const setValue = value => { + try { + setStoredValue(value); + window.localStorage.setItem(key, value); + } catch (error) { + console.log(error); + } + }; + + useEffect(() => { + const storedKey = window.localStorage.getItem(key); + if (!storedKey) { + console.log("generating a new key"); + const _newWallet = ethers.Wallet.createRandom(); + const _newKey = _newWallet.privateKey; + setValue(_newKey); + } else { + setValue(storedKey); + } + }, []); + + useEffect(() => { + if (storedValue && provider) { + wallet = new ethers.Wallet(storedValue); + const _signer = wallet.connect(provider); + setSigner(_signer); + } + }, [storedValue, provider]); + + return signer; +} diff --git a/packages/react-app/src/hooks/ContractExistsAtAddress.js b/packages/react-app/src/hooks/ContractExistsAtAddress.js index ab1f415f8..a2914c8bb 100644 --- a/packages/react-app/src/hooks/ContractExistsAtAddress.js +++ b/packages/react-app/src/hooks/ContractExistsAtAddress.js @@ -1,4 +1,4 @@ -import { isAddress } from "@ethersproject/address"; +import { utils } from "ethers"; import { useEffect, useState } from "react"; /* @@ -25,7 +25,7 @@ const useContractExistsAtAddress = (provider, contractAddress) => { useEffect(() => { // eslint-disable-next-line consistent-return const checkDeployment = async () => { - if (!isAddress(contractAddress)) return false; + if (!utils.isAddress(contractAddress)) return false; const bytecode = await provider.getCode(contractAddress); setContractIsDeployed(bytecode !== "0x0"); }; diff --git a/packages/react-app/src/hooks/ContractLoader.js b/packages/react-app/src/hooks/ContractLoader.js index 480938e38..e95975cca 100644 --- a/packages/react-app/src/hooks/ContractLoader.js +++ b/packages/react-app/src/hooks/ContractLoader.js @@ -1,8 +1,9 @@ /* eslint-disable import/no-dynamic-require */ /* eslint-disable global-require */ -import { Contract } from "@ethersproject/contracts"; import { useEffect, useState } from "react"; +const { ethers } = require("ethers"); + /* ~ What it does? ~ @@ -23,54 +24,100 @@ import { useEffect, useState } from "react"; const purpose = useContractReader(readContracts,"YourContract", "purpose") - Example of using setPurpose function from our contract and writing transactions by Transactor.js helper: tx( writeContracts.YourContract.setPurpose(newPurpose) ) + + config can include: + - chainId - to hardcode the chainId, irrespective of the providerOrSigner chainId + - hardhatNetworkName - to hardcode the hardhat network of interest + - customAddresses: { contractName: 0xCustomAddress } to hardcode the address for a given named contract + - hardhatContracts: object following the hardhat deploy export format (Json with chainIds as keys, which have hardhat network names as keys, which contain arrays of contracts for each) + - externalContracts: object with chainIds as keys, with an array of contracts for each */ -const loadContract = (contractName, signer) => { - const newContract = new Contract( - require(`../contracts/${contractName}.address.js`), - require(`../contracts/${contractName}.abi.js`), - signer, - ); - try { - newContract.bytecode = require(`../contracts/${contractName}.bytecode.js`); - } catch (e) { - console.log(e); - } - return newContract; -}; - -export default function useContractLoader(providerOrSigner) { +export default function useContractLoader(providerOrSigner, config = {}) { const [contracts, setContracts] = useState(); useEffect(() => { + let active = true; + async function loadContracts() { if (typeof providerOrSigner !== "undefined") { + console.log(`loading contracts`); try { // we need to check to see if this providerOrSigner has a signer or not let signer; + let provider; let accounts; + if (providerOrSigner && typeof providerOrSigner.listAccounts === "function") { accounts = await providerOrSigner.listAccounts(); } - if (accounts && accounts.length > 0) { + if (ethers.Signer.isSigner(providerOrSigner)) { + signer = providerOrSigner; + provider = signer.provider; + } else if (accounts && accounts.length > 0) { signer = providerOrSigner.getSigner(); + provider = providerOrSigner; } else { signer = providerOrSigner; + provider = providerOrSigner; + } + + const providerNetwork = await provider.getNetwork(); + + const _chainId = config.chainId || providerNetwork.chainId; + + let contractList = {}; + let externalContractList = {}; + try { + contractList = config.hardhatContracts || require("../contracts/hardhat_contracts.json"); + } catch (e) { + console.log(e); + } + try { + externalContractList = config.externalContracts || require("../contracts/external_contracts.js"); + } catch (e) { + console.log(e); + } + + let combinedContracts = {}; + + if (contractList[_chainId]) { + for (const hardhatNetwork in contractList[_chainId]) { + if (Object.prototype.hasOwnProperty.call(contractList[_chainId], hardhatNetwork)) { + if (!config.hardhatNetworkName || hardhatNetwork === config.hardhatNetworkName) { + combinedContracts = { + ...combinedContracts, + ...contractList[_chainId][hardhatNetwork].contracts, + }; + } + } + } } - const contractList = require("../contracts/contracts.js"); + if (externalContractList[_chainId]) { + combinedContracts = { ...combinedContracts, ...externalContractList[_chainId].contracts }; + } - const newContracts = contractList.reduce((accumulator, contractName) => { - accumulator[contractName] = loadContract(contractName, signer); + const newContracts = Object.keys(combinedContracts).reduce((accumulator, contractName) => { + const _address = + config.customAddresses && Object.keys(config.customAddresses).includes(contractName) + ? config.customAddresses[contractName] + : combinedContracts[contractName].address; + accumulator[contractName] = new ethers.Contract(_address, combinedContracts[contractName].abi, signer); return accumulator; }, {}); - setContracts(newContracts); + if (active) setContracts(newContracts); } catch (e) { console.log("ERROR LOADING CONTRACTS!!", e); } } } loadContracts(); - }, [providerOrSigner]); + + return () => { + active = false; + }; + }, [providerOrSigner, config.chainId, config.hardhatNetworkName]); + return contracts; } diff --git a/packages/react-app/src/hooks/CustomContractLoader.js b/packages/react-app/src/hooks/CustomContractLoader.js deleted file mode 100644 index f9d425594..000000000 --- a/packages/react-app/src/hooks/CustomContractLoader.js +++ /dev/null @@ -1,57 +0,0 @@ -/* eslint-disable import/no-dynamic-require */ -/* eslint-disable global-require */ -import { Contract } from "@ethersproject/contracts"; -import { useEffect, useState } from "react"; - -/* - when you want to load a local contract's abi but supply a custom address -*/ - -/* - ~ What it does? ~ - - Enables you to load a local contract with custom address - - ~ How can I use? ~ - - const customContract = useCustomContractLoader(localProvider, "YourContract", customAddress) - - ~ Features ~ - - - Specify the localProvider - - Specify the name of the contract, in this case it is "YourContract" - - Specify the customAddress of your contract -*/ - -export default function useCustomContractLoader(provider, contractName, address) { - const [contract, setContract] = useState(); - useEffect(() => { - async function loadContract() { - if (typeof provider !== "undefined" && contractName && address) { - try { - // we need to check to see if this provider has a signer or not - let signer; - const accounts = await provider.listAccounts(); - if (accounts && accounts.length > 0) { - signer = provider.getSigner(); - } else { - signer = provider; - } - - const customContract = new Contract(address, require(`../contracts/${contractName}.abi.js`), signer); - try { - customContract.bytecode = require(`../contracts/${contractName}.bytecode.js`); - } catch (e) { - console.log(e); - } - - setContract(customContract); - } catch (e) { - console.log("ERROR LOADING CONTRACTS!!", e); - } - } - } - loadContract(); - }, [provider, contractName, address]); - return contract; -} diff --git a/packages/react-app/src/hooks/ExternalContractLoader.js b/packages/react-app/src/hooks/ExternalContractLoader.js deleted file mode 100644 index 64b83b646..000000000 --- a/packages/react-app/src/hooks/ExternalContractLoader.js +++ /dev/null @@ -1,51 +0,0 @@ -/* eslint-disable import/no-dynamic-require */ -/* eslint-disable global-require */ -import { Contract } from "@ethersproject/contracts"; -import { useEffect, useState } from "react"; - -/* - when you want to load an existing contract using just the provider, address, and ABI -*/ - -/* - ~ What it does? ~ - - Enables you to load an existing mainnet DAI contract using the provider, address and abi - - ~ How can I use? ~ - - const mainnetDAIContract = useExternalContractLoader(mainnetProvider, DAI_ADDRESS, DAI_ABI) - - ~ Features ~ - - - Specify mainnetProvider - - Specify DAI_ADDRESS and DAI_ABI, you can load/write them using constants.js -*/ -export default function useExternalContractLoader(provider, address, ABI, optionalBytecode) { - const [contract, setContract] = useState(); - useEffect(() => { - async function loadContract() { - if (typeof provider !== "undefined" && address && ABI) { - try { - // we need to check to see if this provider has a signer or not - let signer; - const accounts = await provider.listAccounts(); - if (accounts && accounts.length > 0) { - signer = provider.getSigner(); - } else { - signer = provider; - } - - const customContract = new Contract(address, ABI, signer); - if (optionalBytecode) customContract.bytecode = optionalBytecode; - - setContract(customContract); - } catch (e) { - console.log("ERROR LOADING EXTERNAL CONTRACT AT " + address + " (check provider, address, and ABI)!!", e); - } - } - } - loadContract(); - }, [provider, address, ABI, optionalBytecode]); - return contract; -} diff --git a/packages/react-app/src/hooks/GasPrice.js b/packages/react-app/src/hooks/GasPrice.js index de1423cc6..f7656c380 100644 --- a/packages/react-app/src/hooks/GasPrice.js +++ b/packages/react-app/src/hooks/GasPrice.js @@ -5,7 +5,7 @@ import { useState } from "react"; export default function useGasPrice(targetNetwork, speed) { const [gasPrice, setGasPrice] = useState(); const loadGasPrice = async () => { - if (targetNetwork.gasPrice) { + if (targetNetwork.hasOwnProperty("gasPrice")) { setGasPrice(targetNetwork.gasPrice); } else { axios diff --git a/packages/react-app/src/hooks/LookupAddress.js b/packages/react-app/src/hooks/LookupAddress.js index 4ad65670d..171d51374 100644 --- a/packages/react-app/src/hooks/LookupAddress.js +++ b/packages/react-app/src/hooks/LookupAddress.js @@ -1,4 +1,4 @@ -import { getAddress, isAddress } from "@ethersproject/address"; +import { utils } from "ethers"; import { useEffect, useState } from "react"; // resolved if(name){} to not save "" into cache @@ -18,7 +18,7 @@ import { useEffect, useState } from "react"; */ const lookupAddress = async (provider, address) => { - if (isAddress(address)) { + if (address && utils.isAddress(address)) { // console.log(`looking up ${address}`) try { // Accuracy of reverse resolution is not enforced. @@ -27,12 +27,12 @@ const lookupAddress = async (provider, address) => { const resolvedAddress = await provider.resolveName(reportedName); - if (getAddress(address) === getAddress(resolvedAddress)) { + if (address && utils.getAddress(address) === utils.getAddress(resolvedAddress)) { return reportedName; } - return getAddress(address); + return utils.getAddress(address); } catch (e) { - return getAddress(address); + return utils.getAddress(address); } } return 0; diff --git a/packages/react-app/src/hooks/ResolveName.js b/packages/react-app/src/hooks/ResolveName.js index dd01f5838..0eea51798 100644 --- a/packages/react-app/src/hooks/ResolveName.js +++ b/packages/react-app/src/hooks/ResolveName.js @@ -1,4 +1,4 @@ -import { AddressZero } from "@ethersproject/constants"; +import { constants } from "ethers"; import { useEffect, useState } from "react"; /* @@ -17,7 +17,7 @@ import { useEffect, useState } from "react"; */ const useResolveName = (provider, ensName) => { - const [address, setAddress] = useState(AddressZero); + const [address, setAddress] = useState(constants.AddressZero); useEffect(() => { if (provider) { diff --git a/packages/react-app/src/hooks/UserProvider.js b/packages/react-app/src/hooks/UserProvider.js deleted file mode 100644 index 656735423..000000000 --- a/packages/react-app/src/hooks/UserProvider.js +++ /dev/null @@ -1,63 +0,0 @@ -import { Web3Provider } from "@ethersproject/providers"; -import BurnerProvider from "burner-provider"; -import { useMemo } from "react"; -import { INFURA_ID } from "../constants"; - -/* - ~ What it does? ~ - - Gets user provider - - ~ How can I use? ~ - - const userProvider = useUserProvider(injectedProvider, localProvider); - - ~ Features ~ - - - Specify the injected provider from Metamask - - Specify the local provider - - Usage examples: - const address = useUserAddress(userProvider); - const tx = Transactor(userProvider, gasPrice) -*/ - -const useUserProvider = (injectedProvider, localProvider) => - useMemo(() => { - if (injectedProvider) { - console.log("๐ŸฆŠ Using injected provider"); - return injectedProvider; - } - if (!localProvider) return undefined; - - const burnerConfig = {}; - - if (window.location.pathname) { - if (window.location.pathname.indexOf("/pk") >= 0) { - const incomingPK = window.location.hash.replace("#", ""); - let rawPK; - if (incomingPK.length === 64 || incomingPK.length === 66) { - console.log("๐Ÿ”‘ Incoming Private Key..."); - rawPK = incomingPK; - burnerConfig.privateKey = rawPK; - window.history.pushState({}, "", "/"); - const currentPrivateKey = window.localStorage.getItem("metaPrivateKey"); - if (currentPrivateKey && currentPrivateKey !== rawPK) { - window.localStorage.setItem("metaPrivateKey_backup" + Date.now(), currentPrivateKey); - } - window.localStorage.setItem("metaPrivateKey", rawPK); - } - } - } - - console.log("๐Ÿ”ฅ Using burner provider", burnerConfig); - if (localProvider.connection && localProvider.connection.url) { - burnerConfig.rpcUrl = localProvider.connection.url; - return new Web3Provider(new BurnerProvider(burnerConfig)); - } - // eslint-disable-next-line no-underscore-dangle - const networkName = localProvider._network && localProvider._network.name; - burnerConfig.rpcUrl = `https://${networkName || "mainnet"}.infura.io/v3/${INFURA_ID}`; - return new Web3Provider(new BurnerProvider(burnerConfig)); - }, [injectedProvider, localProvider]); - -export default useUserProvider; diff --git a/packages/react-app/src/hooks/UserSigner.js b/packages/react-app/src/hooks/UserSigner.js new file mode 100644 index 000000000..e240dc3f9 --- /dev/null +++ b/packages/react-app/src/hooks/UserSigner.js @@ -0,0 +1,55 @@ +import { useMemo, useState } from "react"; +import useBurnerSigner from "./BurnerSigner"; + +/* + ~ What it does? ~ + + Gets user provider + + ~ How can I use? ~ + + const userProvider = useUserProvider(injectedProvider, localProvider); + + ~ Features ~ + + - Specify the injected provider from Metamask + - Specify the local provider + - Usage examples: + const tx = Transactor(userSigner, gasPrice) +*/ + +const useUserSigner = (injectedProvider, localProvider) => { + const [signer, setSigner] = useState(); + const burnerSigner = useBurnerSigner(localProvider); + + useMemo(() => { + if (injectedProvider) { + console.log("๐ŸฆŠ Using injected provider"); + const injectedSigner = injectedProvider._isProvider ? injectedProvider.getSigner() : injectedProvider; + setSigner(injectedSigner); + } else if (!localProvider) setSigner(); + else { + if (window.location.pathname && window.location.pathname.indexOf("/pk") >= 0) { + const incomingPK = window.location.hash.replace("#", ""); + let rawPK; + if (incomingPK.length === 64 || incomingPK.length === 66) { + console.log("๐Ÿ”‘ Incoming Private Key..."); + rawPK = incomingPK; + window.history.pushState({}, "", "/"); + const currentPrivateKey = window.localStorage.getItem("metaPrivateKey"); + if (currentPrivateKey && currentPrivateKey !== rawPK) { + window.localStorage.setItem("metaPrivateKey_backup" + Date.now(), currentPrivateKey); + } + window.localStorage.setItem("metaPrivateKey", rawPK); + } + } + + console.log("๐Ÿ”ฅ Using burner signer", burnerSigner); + setSigner(burnerSigner); + } + }, [injectedProvider, localProvider, burnerSigner]); + + return signer; +}; + +export default useUserSigner; diff --git a/packages/react-app/src/hooks/index.js b/packages/react-app/src/hooks/index.js index 3f4327435..d5d69034c 100644 --- a/packages/react-app/src/hooks/index.js +++ b/packages/react-app/src/hooks/index.js @@ -2,11 +2,9 @@ export { default as useBalance } from "./Balance"; export { default as useContractExistsAtAddress } from "./ContractExistsAtAddress"; export { default as useContractLoader } from "./ContractLoader"; export { default as useContractReader } from "./ContractReader"; -export { default as useCustomContractLoader } from "./CustomContractLoader"; export { default as useDebounce } from "./Debounce"; export { default as useEventListener } from "./EventListener"; export { default as useExchangePrice } from "./ExchangePrice"; -export { default as useExternalContractLoader } from "./ExternalContractLoader"; export { default as useGasPrice } from "./GasPrice"; export { default as useLocalStorage } from "./LocalStorage"; export { default as useLookupAddress } from "./LookupAddress"; @@ -15,4 +13,5 @@ export { default as useOnBlock } from "./OnBlock"; export { default as usePoller } from "./Poller"; export { default as useResolveName } from "./ResolveName"; export { default as useTokenList } from "./TokenList"; -export { default as useUserProvider } from "./UserProvider"; +export { default as useUserSigner } from "./UserSigner"; +export { default as useBurnerSigner } from "./BurnerSigner"; diff --git a/packages/react-app/src/views/ExampleUI.jsx b/packages/react-app/src/views/ExampleUI.jsx index 13badcea6..61c2c1e73 100644 --- a/packages/react-app/src/views/ExampleUI.jsx +++ b/packages/react-app/src/views/ExampleUI.jsx @@ -1,7 +1,7 @@ /* eslint-disable jsx-a11y/accessible-emoji */ import { SyncOutlined } from "@ant-design/icons"; -import { formatEther, parseEther } from "@ethersproject/units"; +import { utils } from "ethers"; import { Button, Card, DatePicker, Divider, Input, List, Progress, Slider, Spin, Switch } from "antd"; import React, { useState } from "react"; import { Address, Balance } from "../components"; @@ -73,20 +73,20 @@ export default function ExampleUI({ fontSize={16} /> - {/* use formatEther to display a BigNumber: */} -

Your Balance: {yourLocalBalance ? formatEther(yourLocalBalance) : "..."}

+ {/* use utils.formatEther to display a BigNumber: */} +

Your Balance: {yourLocalBalance ? utils.formatEther(yourLocalBalance) : "..."}

OR
๐Ÿณ Example Whale Balance:
- + - {/* use formatEther to display a BigNumber: */} -

Your Balance: {yourLocalBalance ? formatEther(yourLocalBalance) : "..."}

+ {/* use utils.formatEther to display a BigNumber: */} +

Your Balance: {yourLocalBalance ? utils.formatEther(yourLocalBalance) : "..."}

Your Contract Address:
@@ -110,7 +110,7 @@ export default function ExampleUI({ */ tx({ to: writeContracts.YourContract.address, - value: parseEther("0.001"), + value: utils.parseEther("0.001"), }); /* this should throw an error about "no fallback nor receive function" until you add it */ }} @@ -124,7 +124,7 @@ export default function ExampleUI({ /* look how we call setPurpose AND send some value along */ tx( writeContracts.YourContract.setPurpose("๐Ÿ’ต Paying for this one!", { - value: parseEther("0.001"), + value: utils.parseEther("0.001"), }), ); /* this will fail until you make the setPurpose function payable */ @@ -139,7 +139,7 @@ export default function ExampleUI({ /* you can also just craft a transaction and send it to the tx() transactor */ tx({ to: writeContracts.YourContract.address, - value: parseEther("0.001"), + value: utils.parseEther("0.001"), data: writeContracts.YourContract.interface.encodeFunctionData("setPurpose(string)", [ "๐Ÿค“ Whoa so 1337!", ]), @@ -164,7 +164,7 @@ export default function ExampleUI({ renderItem={item => { return ( -
=> +
{item[1]} ); diff --git a/packages/react-app/src/views/Hints.jsx b/packages/react-app/src/views/Hints.jsx index cf2e44634..a1b6a2a1b 100644 --- a/packages/react-app/src/views/Hints.jsx +++ b/packages/react-app/src/views/Hints.jsx @@ -1,6 +1,6 @@ /* eslint-disable jsx-a11y/accessible-emoji */ -import { formatEther } from "@ethersproject/units"; +import { utils } from "ethers"; import { Select } from "antd"; import React, { useState } from "react"; import { Address, AddressInput } from "../components"; @@ -94,7 +94,7 @@ export default function Hints({ yourLocalBalance, mainnetProvider, price, addres > useBalance() {" "} - hook keeps track of your balance: {formatEther(yourLocalBalance || 0)} + hook keeps track of your balance: {utils.formatEther(yourLocalBalance || 0)}
@@ -199,9 +199,10 @@ export default function Hints({ yourLocalBalance, mainnetProvider, price, addres > packages/hardhat -
+
(use{" "}
- ๐Ÿ›  Check out your browser's developer console for more... (inpect -> console) ๐Ÿš€ + ๐Ÿ›  Check out your browser's developer console for more... (inspect console) ๐Ÿš€
); diff --git a/packages/react-app/src/views/Subgraph.jsx b/packages/react-app/src/views/Subgraph.jsx index 2603e0849..4745e22d1 100644 --- a/packages/react-app/src/views/Subgraph.jsx +++ b/packages/react-app/src/views/Subgraph.jsx @@ -95,7 +95,7 @@ function Subgraph(props) { ๐Ÿšฎ Clean up previous data: - rm -rf docker/graph-node/data/ + yarn clean-graph-node
@@ -103,7 +103,7 @@ function Subgraph(props) { ๐Ÿ“ก Spin up a local graph node by running - yarn graph-run-node + yarn run-graph-node {" "} diff --git a/packages/services/arbitrum b/packages/services/arbitrum new file mode 160000 index 000000000..4f1a02688 --- /dev/null +++ b/packages/services/arbitrum @@ -0,0 +1 @@ +Subproject commit 4f1a02688639f8f98f5357b30af5c437ba714553 diff --git a/docker/graph-node/Dockerfile b/packages/services/graph-node/Dockerfile similarity index 100% rename from docker/graph-node/Dockerfile rename to packages/services/graph-node/Dockerfile diff --git a/docker/graph-node/README.md b/packages/services/graph-node/README.md similarity index 100% rename from docker/graph-node/README.md rename to packages/services/graph-node/README.md diff --git a/docker/graph-node/bin/create b/packages/services/graph-node/bin/create similarity index 100% rename from docker/graph-node/bin/create rename to packages/services/graph-node/bin/create diff --git a/docker/graph-node/bin/debug b/packages/services/graph-node/bin/debug similarity index 100% rename from docker/graph-node/bin/debug rename to packages/services/graph-node/bin/debug diff --git a/docker/graph-node/bin/deploy b/packages/services/graph-node/bin/deploy similarity index 100% rename from docker/graph-node/bin/deploy rename to packages/services/graph-node/bin/deploy diff --git a/docker/graph-node/bin/reassign b/packages/services/graph-node/bin/reassign similarity index 100% rename from docker/graph-node/bin/reassign rename to packages/services/graph-node/bin/reassign diff --git a/docker/graph-node/bin/remove b/packages/services/graph-node/bin/remove similarity index 100% rename from docker/graph-node/bin/remove rename to packages/services/graph-node/bin/remove diff --git a/docker/graph-node/build.sh b/packages/services/graph-node/build.sh similarity index 100% rename from docker/graph-node/build.sh rename to packages/services/graph-node/build.sh diff --git a/docker/graph-node/cloudbuild.yaml b/packages/services/graph-node/cloudbuild.yaml similarity index 100% rename from docker/graph-node/cloudbuild.yaml rename to packages/services/graph-node/cloudbuild.yaml diff --git a/docker/graph-node/docker-compose.yml b/packages/services/graph-node/docker-compose.yml similarity index 66% rename from docker/graph-node/docker-compose.yml rename to packages/services/graph-node/docker-compose.yml index 58addff07..1b2f3aa23 100644 --- a/docker/graph-node/docker-compose.yml +++ b/packages/services/graph-node/docker-compose.yml @@ -1,13 +1,13 @@ -version: '3' +version: "3" services: graph-node: - image: graphprotocol/graph-node + image: graphprotocol/graph-node:2c23cce ports: - - '8000:8000' - - '8001:8001' - - '8020:8020' - - '8030:8030' - - '8040:8040' + - "8000:8000" + - "8001:8001" + - "8020:8020" + - "8030:8030" + - "8040:8040" depends_on: - ipfs - postgres @@ -16,19 +16,19 @@ services: postgres_user: graph-node postgres_pass: let-me-in postgres_db: graph-node - ipfs: 'ipfs:5001' - ethereum: 'localhost:http://host.docker.internal:8545' - RUST_LOG: info + ipfs: "ipfs:5001" + ethereum: "localhost:http://host.docker.internal:8545" + GRAPH_LOG: info ipfs: image: ipfs/go-ipfs:v0.4.23 ports: - - '5001:5001' + - "5001:5001" volumes: - ./data/ipfs:/data/ipfs postgres: image: postgres ports: - - '5432:5432' + - "5432:5432" command: ["postgres", "-cshared_preload_libraries=pg_stat_statements"] environment: POSTGRES_USER: graph-node diff --git a/docker/graph-node/hooks/post_checkout b/packages/services/graph-node/hooks/post_checkout similarity index 100% rename from docker/graph-node/hooks/post_checkout rename to packages/services/graph-node/hooks/post_checkout diff --git a/docker/graph-node/setup.sh b/packages/services/graph-node/setup.sh similarity index 100% rename from docker/graph-node/setup.sh rename to packages/services/graph-node/setup.sh diff --git a/docker/graph-node/start b/packages/services/graph-node/start similarity index 100% rename from docker/graph-node/start rename to packages/services/graph-node/start diff --git a/docker/graph-node/tag.sh b/packages/services/graph-node/tag.sh similarity index 100% rename from docker/graph-node/tag.sh rename to packages/services/graph-node/tag.sh diff --git a/docker/graph-node/wait_for b/packages/services/graph-node/wait_for similarity index 100% rename from docker/graph-node/wait_for rename to packages/services/graph-node/wait_for diff --git a/packages/services/optimism b/packages/services/optimism new file mode 160000 index 000000000..958477be4 --- /dev/null +++ b/packages/services/optimism @@ -0,0 +1 @@ +Subproject commit 958477be4f8e778864ddc383c1c62a898b55672a diff --git a/packages/services/package.json b/packages/services/package.json new file mode 100644 index 000000000..b48d3cb1a --- /dev/null +++ b/packages/services/package.json @@ -0,0 +1,18 @@ +{ + "name": "@scaffold-eth/services", + "version": "1.0.0", + "license": "MIT", + "scripts": { + "submodule-init": "git submodule init && git submodule update --remote", + "arbitrum-init": "cd arbitrum && git submodule init && git submodule update && yarn install", + "arbitrum-build-l1": "cd arbitrum && yarn docker:build:geth", + "arbitrum-run-l1": "cd arbitrum && yarn docker:geth", + "arbitrum-init-l2": "cd arbitrum && yarn demo:initialize", + "arbitrum-run-l2": "cd arbitrum && yarn demo:deploy", + "run-optimism": "cd optimism/ops && make up", + "stop-optimism": "cd optimism/ops && make down", + "run-graph-node": "cd graph-node && docker-compose up", + "remove-graph-node": "cd graph-node && docker-compose down", + "clean-graph-node": "rm -rf graph-node/data/" + } +} diff --git a/packages/subgraph/abis/YourContract.json b/packages/subgraph/abis/YourContract.json deleted file mode 100644 index 5616f6205..000000000 --- a/packages/subgraph/abis/YourContract.json +++ /dev/null @@ -1,52 +0,0 @@ -[ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "indexed": false, - "internalType": "string", - "name": "purpose", - "type": "string" - } - ], - "name": "SetPurpose", - "type": "event" - }, - { - "inputs": [], - "name": "purpose", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "newPurpose", - "type": "string" - } - ], - "name": "setPurpose", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] \ No newline at end of file diff --git a/packages/subgraph/src/subgraph.template.yaml b/packages/subgraph/src/subgraph.template.yaml index 62595d092..50f99efdf 100644 --- a/packages/subgraph/src/subgraph.template.yaml +++ b/packages/subgraph/src/subgraph.template.yaml @@ -6,7 +6,7 @@ dataSources: name: YourContract network: localhost source: - address: '{{YourContractAddress}}' + address: "{{localhost_YourContractAddress}}" abi: YourContract startBlock: 1 mapping: @@ -18,7 +18,7 @@ dataSources: - Sender abis: - name: YourContract - file: ./abis/YourContract.json + file: ./abis/localhost_YourContract.json eventHandlers: - event: SetPurpose(address,string) handler: handleSetPurpose diff --git a/yarn.lock b/yarn.lock index bb0c7b848..f7befb659 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1306,6 +1306,13 @@ minimatch "^3.0.4" strip-json-comments "^3.1.1" +"@eth-optimism/hardhat-ovm@^0.2.2": + version "0.2.2" + resolved "https://registry.yarnpkg.com/@eth-optimism/hardhat-ovm/-/hardhat-ovm-0.2.2.tgz#55fafaa6b8277447abaf132602c1c6d14a2a18a2" + integrity sha512-QLzqawYCzC/m6K/Oaj/tCZQlu6kZTgnleg1cJad8kVYA5E+JWZQ6ZJrcStoJoJrco9RIroPUjAFEhFM8YiCc7Q== + dependencies: + node-fetch "^2.6.1" + "@ethereum-waffle/chai@^3.1.1": version "3.1.1" resolved "https://registry.yarnpkg.com/@ethereum-waffle/chai/-/chai-3.1.1.tgz#2d2594e19613cdee0eaa1a38fc8dac31f66460e6" @@ -1371,21 +1378,6 @@ "@ethersproject/properties" ">=5.0.0-beta.131" "@ethersproject/strings" ">=5.0.0-beta.130" -"@ethersproject/abi@5.0.13", "@ethersproject/abi@^5.0.10", "@ethersproject/abi@^5.0.2": - version "5.0.13" - resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.0.13.tgz#600a559c3730467716595658beaa2894b4352bcc" - integrity sha512-2coOH3D7ra1lwamKEH0HVc+Jbcsw5yfeCgmY8ekhCDualEiyyovD2qDcMBBcY3+kjoLHVTmo7ost6MNClxdOrg== - dependencies: - "@ethersproject/address" "^5.0.9" - "@ethersproject/bignumber" "^5.0.13" - "@ethersproject/bytes" "^5.0.9" - "@ethersproject/constants" "^5.0.8" - "@ethersproject/hash" "^5.0.10" - "@ethersproject/keccak256" "^5.0.7" - "@ethersproject/logger" "^5.0.8" - "@ethersproject/properties" "^5.0.7" - "@ethersproject/strings" "^5.0.8" - "@ethersproject/abi@5.0.7", "@ethersproject/abi@^5.0.1", "@ethersproject/abi@^5.0.5": version "5.0.7" resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.0.7.tgz#79e52452bd3ca2956d0e1c964207a58ad1a0ee7b" @@ -1401,18 +1393,35 @@ "@ethersproject/properties" "^5.0.3" "@ethersproject/strings" "^5.0.4" -"@ethersproject/abstract-provider@5.0.10", "@ethersproject/abstract-provider@^5.0.8": - version "5.0.10" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.0.10.tgz#a533aed39a5f27312745c8c4c40fa25fc884831c" - integrity sha512-OSReY5iz94iIaPlRvLiJP8YVIvQLx4aUvMMnHWSaA/vTU8QHZmgNlt4OBdYV1+aFY8Xl+VRYiWBHq72ZDKXXCQ== +"@ethersproject/abi@5.3.0", "@ethersproject/abi@^5.0.0", "@ethersproject/abi@^5.3.0": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.3.0.tgz#00f0647d906edcd32c50b16ab9c98f83e208dcf1" + integrity sha512-NaT4UacjOwca8qCG/gv8k+DgTcWu49xlrvdhr/p8PTFnoS8e3aMWqjI3znFME5Txa/QWXDrg2/heufIUue9rtw== + dependencies: + "@ethersproject/address" "^5.3.0" + "@ethersproject/bignumber" "^5.3.0" + "@ethersproject/bytes" "^5.3.0" + "@ethersproject/constants" "^5.3.0" + "@ethersproject/hash" "^5.3.0" + "@ethersproject/keccak256" "^5.3.0" + "@ethersproject/logger" "^5.3.0" + "@ethersproject/properties" "^5.3.0" + "@ethersproject/strings" "^5.3.0" + +"@ethersproject/abi@^5.0.2": + version "5.0.13" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.0.13.tgz#600a559c3730467716595658beaa2894b4352bcc" + integrity sha512-2coOH3D7ra1lwamKEH0HVc+Jbcsw5yfeCgmY8ekhCDualEiyyovD2qDcMBBcY3+kjoLHVTmo7ost6MNClxdOrg== dependencies: + "@ethersproject/address" "^5.0.9" "@ethersproject/bignumber" "^5.0.13" "@ethersproject/bytes" "^5.0.9" + "@ethersproject/constants" "^5.0.8" + "@ethersproject/hash" "^5.0.10" + "@ethersproject/keccak256" "^5.0.7" "@ethersproject/logger" "^5.0.8" - "@ethersproject/networks" "^5.0.7" "@ethersproject/properties" "^5.0.7" - "@ethersproject/transactions" "^5.0.9" - "@ethersproject/web" "^5.0.12" + "@ethersproject/strings" "^5.0.8" "@ethersproject/abstract-provider@5.0.5", "@ethersproject/abstract-provider@^5.0.4": version "5.0.5" @@ -1427,16 +1436,31 @@ "@ethersproject/transactions" "^5.0.5" "@ethersproject/web" "^5.0.6" -"@ethersproject/abstract-signer@5.0.14", "@ethersproject/abstract-signer@^5.0.10": - version "5.0.14" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.0.14.tgz#30ef912b0f86599d90fdffc65c110452e7b55cf1" - integrity sha512-JztBwVO7o5OHLh2vyjordlS4/1EjRyaECtc8vPdXTF1i4dXN+J0coeRoPN6ZFbBvi/YbaB6br2fvqhst1VQD/g== +"@ethersproject/abstract-provider@5.3.0", "@ethersproject/abstract-provider@^5.3.0": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.3.0.tgz#f4c0ae4a4cef9f204d7781de805fd44b72756c81" + integrity sha512-1+MLhGP1GwxBDBNwMWVmhCsvKwh4gK7oIfOrmlmePNeskg1NhIrYssraJBieaFNHUYfKEd/1DjiVZMw8Qu5Cxw== + dependencies: + "@ethersproject/bignumber" "^5.3.0" + "@ethersproject/bytes" "^5.3.0" + "@ethersproject/logger" "^5.3.0" + "@ethersproject/networks" "^5.3.0" + "@ethersproject/properties" "^5.3.0" + "@ethersproject/transactions" "^5.3.0" + "@ethersproject/web" "^5.3.0" + +"@ethersproject/abstract-provider@^5.0.8": + version "5.0.10" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.0.10.tgz#a533aed39a5f27312745c8c4c40fa25fc884831c" + integrity sha512-OSReY5iz94iIaPlRvLiJP8YVIvQLx4aUvMMnHWSaA/vTU8QHZmgNlt4OBdYV1+aFY8Xl+VRYiWBHq72ZDKXXCQ== dependencies: - "@ethersproject/abstract-provider" "^5.0.8" "@ethersproject/bignumber" "^5.0.13" "@ethersproject/bytes" "^5.0.9" "@ethersproject/logger" "^5.0.8" + "@ethersproject/networks" "^5.0.7" "@ethersproject/properties" "^5.0.7" + "@ethersproject/transactions" "^5.0.9" + "@ethersproject/web" "^5.0.12" "@ethersproject/abstract-signer@5.0.6", "@ethersproject/abstract-signer@^5.0.4": version "5.0.6" @@ -1449,18 +1473,29 @@ "@ethersproject/logger" "^5.0.5" "@ethersproject/properties" "^5.0.3" -"@ethersproject/address@5.0.11", "@ethersproject/address@^5.0.2", "@ethersproject/address@^5.0.9": - version "5.0.11" - resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.0.11.tgz#12022e8c590c33939beb5ab18b401ecf585eac59" - integrity sha512-Et4GBdD8/tsBGjCEOKee9upN29qjL5kbRcmJifb4Penmiuh9GARXL2/xpXvEp5EW+EIW/rfCHFJrkYBgoQFQBw== +"@ethersproject/abstract-signer@5.3.0", "@ethersproject/abstract-signer@^5.0.0", "@ethersproject/abstract-signer@^5.3.0": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.3.0.tgz#05172b653e15b535ed5854ef5f6a72f4b441052d" + integrity sha512-w8IFwOYqiPrtvosPuArZ3+QPR2nmdVTRrVY8uJYL3NNfMmQfTy3V3l2wbzX47UUlNbPJY+gKvzJAyvK1onZxJg== dependencies: + "@ethersproject/abstract-provider" "^5.3.0" + "@ethersproject/bignumber" "^5.3.0" + "@ethersproject/bytes" "^5.3.0" + "@ethersproject/logger" "^5.3.0" + "@ethersproject/properties" "^5.3.0" + +"@ethersproject/abstract-signer@^5.0.10": + version "5.0.14" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.0.14.tgz#30ef912b0f86599d90fdffc65c110452e7b55cf1" + integrity sha512-JztBwVO7o5OHLh2vyjordlS4/1EjRyaECtc8vPdXTF1i4dXN+J0coeRoPN6ZFbBvi/YbaB6br2fvqhst1VQD/g== + dependencies: + "@ethersproject/abstract-provider" "^5.0.8" "@ethersproject/bignumber" "^5.0.13" "@ethersproject/bytes" "^5.0.9" - "@ethersproject/keccak256" "^5.0.7" "@ethersproject/logger" "^5.0.8" - "@ethersproject/rlp" "^5.0.7" + "@ethersproject/properties" "^5.0.7" -"@ethersproject/address@5.0.5", "@ethersproject/address@>=5.0.0-beta.128", "@ethersproject/address@^5.0.4", "@ethersproject/address@^5.0.5": +"@ethersproject/address@5.0.5", "@ethersproject/address@>=5.0.0-beta.128", "@ethersproject/address@^5.0.4": version "5.0.5" resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.0.5.tgz#2caa65f6b7125015395b1b54c985ee0b27059cc7" integrity sha512-DpkQ6rwk9jTefrRsJzEm6nhRiJd9pvhn1xN0rw5N/jswXG5r7BLk/GVA0mMAVWAsYfvi2xSc5L41FMox43RYEA== @@ -1472,6 +1507,28 @@ "@ethersproject/rlp" "^5.0.3" bn.js "^4.4.0" +"@ethersproject/address@5.3.0", "@ethersproject/address@^5.0.0", "@ethersproject/address@^5.0.8", "@ethersproject/address@^5.3.0": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.3.0.tgz#e53b69eacebf332e8175de814c5e6507d6932518" + integrity sha512-29TgjzEBK+gUEUAOfWCG7s9IxLNLCqvr+oDSk6L9TXD0VLvZJKhJV479tKQqheVA81OeGxfpdxYtUVH8hqlCvA== + dependencies: + "@ethersproject/bignumber" "^5.3.0" + "@ethersproject/bytes" "^5.3.0" + "@ethersproject/keccak256" "^5.3.0" + "@ethersproject/logger" "^5.3.0" + "@ethersproject/rlp" "^5.3.0" + +"@ethersproject/address@^5.0.2", "@ethersproject/address@^5.0.9": + version "5.0.11" + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.0.11.tgz#12022e8c590c33939beb5ab18b401ecf585eac59" + integrity sha512-Et4GBdD8/tsBGjCEOKee9upN29qjL5kbRcmJifb4Penmiuh9GARXL2/xpXvEp5EW+EIW/rfCHFJrkYBgoQFQBw== + dependencies: + "@ethersproject/bignumber" "^5.0.13" + "@ethersproject/bytes" "^5.0.9" + "@ethersproject/keccak256" "^5.0.7" + "@ethersproject/logger" "^5.0.8" + "@ethersproject/rlp" "^5.0.7" + "@ethersproject/base64@5.0.4", "@ethersproject/base64@^5.0.3": version "5.0.4" resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.0.4.tgz#b0d8fdbf3dda977cf546dcd35725a7b1d5256caa" @@ -1479,7 +1536,14 @@ dependencies: "@ethersproject/bytes" "^5.0.4" -"@ethersproject/base64@5.0.9", "@ethersproject/base64@^5.0.7": +"@ethersproject/base64@5.3.0", "@ethersproject/base64@^5.3.0": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.3.0.tgz#b831fb35418b42ad24d943c557259062b8640824" + integrity sha512-JIqgtOmgKcbc2sjGWTXyXktqUhvFUDte8fPVsAaOrcPiJf6YotNF+nsrOYGC9pbHBEGSuSBp3QR0varkO8JHEw== + dependencies: + "@ethersproject/bytes" "^5.3.0" + +"@ethersproject/base64@^5.0.7": version "5.0.9" resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.0.9.tgz#bb1f35d3dba92082a574d5e2418f9202a0a1a7e6" integrity sha512-37RBz5LEZ9SlTNGiWCYFttnIN9J7qVs9Xo2EbqGqDH5LfW9EIji66S+YDMpXVo1zWDax1FkEldAoatxHK2gfgA== @@ -1494,24 +1558,15 @@ "@ethersproject/bytes" "^5.0.4" "@ethersproject/properties" "^5.0.3" -"@ethersproject/basex@5.0.9", "@ethersproject/basex@^5.0.7": - version "5.0.9" - resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.0.9.tgz#00d727a031bac563cb8bb900955206f1bf3cf1fc" - integrity sha512-FANswl1IN3PS0eltQxH2aM2+utPrkLUVG4XVFi6SafRG9EpAqXCgycxC8PU90mPGhigYTpg9cnTB5mCZ6ejQjw== - dependencies: - "@ethersproject/bytes" "^5.0.9" - "@ethersproject/properties" "^5.0.7" - -"@ethersproject/bignumber@5.0.15", "@ethersproject/bignumber@^5.0.13": - version "5.0.15" - resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.0.15.tgz#b089b3f1e0381338d764ac1c10512f0c93b184ed" - integrity sha512-MTADqnyacvdRwtKh7o9ujwNDSM1SDJjYDMYAzjIgjoi9rh6TY4suMbhCa3i2vh3SUXiXSICyTI8ui+NPdrZ9Lw== +"@ethersproject/basex@5.3.0", "@ethersproject/basex@^5.3.0": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.3.0.tgz#02dea3ab8559ae625c6d548bc11773432255c916" + integrity sha512-8J4nS6t/SOnoCgr3DF5WCSRLC5YwTKYpZWJqeyYQLX+86TwPhtzvHXacODzcDII9tWKhVg6g0Bka8JCBWXsCiQ== dependencies: - "@ethersproject/bytes" "^5.0.9" - "@ethersproject/logger" "^5.0.8" - bn.js "^4.4.0" + "@ethersproject/bytes" "^5.3.0" + "@ethersproject/properties" "^5.3.0" -"@ethersproject/bignumber@5.0.8", "@ethersproject/bignumber@>=5.0.0-beta.130", "@ethersproject/bignumber@^5.0.7", "@ethersproject/bignumber@^5.0.8": +"@ethersproject/bignumber@5.0.8", "@ethersproject/bignumber@>=5.0.0-beta.130", "@ethersproject/bignumber@^5.0.7": version "5.0.8" resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.0.8.tgz#cee33bd8eb0266176def0d371b45274b1d2c4ec0" integrity sha512-KXFVAFKS1jdTXYN8BE5Oj+ZfPMh28iRdFeNGBVT6cUFdtiPVqeXqc0ggvBqA3A1VoFFGgM7oAeaagA393aORHA== @@ -1520,26 +1575,44 @@ "@ethersproject/logger" "^5.0.5" bn.js "^4.4.0" -"@ethersproject/bytes@5.0.11", "@ethersproject/bytes@^5.0.9": - version "5.0.11" - resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.0.11.tgz#21118e75b1d00db068984c15530e316021101276" - integrity sha512-D51plLYY5qF05AsoVQwIZVLqlBkaTPVHVP/1WmmBIWyHB0cRW0C9kh0kx5Exo51rB63Hk8PfHxc7SmpoaQFEyg== +"@ethersproject/bignumber@5.3.0", "@ethersproject/bignumber@^5.0.0", "@ethersproject/bignumber@^5.1.1", "@ethersproject/bignumber@^5.3.0": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.3.0.tgz#74ab2ec9c3bda4e344920565720a6ee9c794e9db" + integrity sha512-5xguJ+Q1/zRMgHgDCaqAexx/8DwDVLRemw2i6uR8KyGjwGdXI8f32QZZ1cKGucBN6ekJvpUpHy6XAuQnTv0mPA== dependencies: + "@ethersproject/bytes" "^5.3.0" + "@ethersproject/logger" "^5.3.0" + bn.js "^4.11.9" + +"@ethersproject/bignumber@^5.0.13": + version "5.0.15" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.0.15.tgz#b089b3f1e0381338d764ac1c10512f0c93b184ed" + integrity sha512-MTADqnyacvdRwtKh7o9ujwNDSM1SDJjYDMYAzjIgjoi9rh6TY4suMbhCa3i2vh3SUXiXSICyTI8ui+NPdrZ9Lw== + dependencies: + "@ethersproject/bytes" "^5.0.9" "@ethersproject/logger" "^5.0.8" + bn.js "^4.4.0" -"@ethersproject/bytes@5.0.5", "@ethersproject/bytes@>=5.0.0-beta.129", "@ethersproject/bytes@^5.0.4", "@ethersproject/bytes@^5.0.5": +"@ethersproject/bytes@5.0.5", "@ethersproject/bytes@>=5.0.0-beta.129", "@ethersproject/bytes@^5.0.4": version "5.0.5" resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.0.5.tgz#688b70000e550de0c97a151a21f15b87d7f97d7c" integrity sha512-IEj9HpZB+ACS6cZ+QQMTqmu/cnUK2fYNE6ms/PVxjoBjoxc6HCraLpam1KuRvreMy0i523PLmjN8OYeikRdcUQ== dependencies: "@ethersproject/logger" "^5.0.5" -"@ethersproject/constants@5.0.10", "@ethersproject/constants@^5.0.8": - version "5.0.10" - resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.0.10.tgz#eb0c604fbc44c53ba9641eed31a1d0c9e1ebcadc" - integrity sha512-OSo8jxkHLDXieCy8bgOFR7lMfgPxEzKvSDdP+WAWHCDM8+orwch0B6wzkTmiQFgryAtIctrBt5glAdJikZ3hGw== +"@ethersproject/bytes@5.3.0", "@ethersproject/bytes@^5.0.0", "@ethersproject/bytes@^5.0.8", "@ethersproject/bytes@^5.3.0": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.3.0.tgz#473e0da7f831d535b2002be05e6f4ca3729a1bc9" + integrity sha512-rqLJjdVqCcn7glPer7Fxh87PRqlnRScVAoxcIP3PmOUNApMWJ6yRdOFfo2KvPAdO7Le3yEI1o0YW+Yvr7XCYvw== dependencies: - "@ethersproject/bignumber" "^5.0.13" + "@ethersproject/logger" "^5.3.0" + +"@ethersproject/bytes@^5.0.9": + version "5.0.11" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.0.11.tgz#21118e75b1d00db068984c15530e316021101276" + integrity sha512-D51plLYY5qF05AsoVQwIZVLqlBkaTPVHVP/1WmmBIWyHB0cRW0C9kh0kx5Exo51rB63Hk8PfHxc7SmpoaQFEyg== + dependencies: + "@ethersproject/logger" "^5.0.8" "@ethersproject/constants@5.0.5", "@ethersproject/constants@>=5.0.0-beta.128", "@ethersproject/constants@^5.0.4": version "5.0.5" @@ -1548,22 +1621,21 @@ dependencies: "@ethersproject/bignumber" "^5.0.7" -"@ethersproject/contracts@5.0.12": - version "5.0.12" - resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.0.12.tgz#6d488db46221258399dfe80b89bf849b3afd7897" - integrity sha512-srijy31idjz8bE+gL1I6IRj2H4I9dUwfQ+QroLrIgNdGArqY8y2iFUKa3QTy+JBX26fJsdYiCQi1kKkaNpnMpQ== +"@ethersproject/constants@5.3.0", "@ethersproject/constants@^5.3.0": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.3.0.tgz#a5d6d86c0eec2c64c3024479609493b9afb3fc77" + integrity sha512-4y1feNOwEpgjAfiCFWOHznvv6qUF/H6uI0UKp8xdhftb+H+FbKflXg1pOgH5qs4Sr7EYBL+zPyPb+YD5g1aEyw== + dependencies: + "@ethersproject/bignumber" "^5.3.0" + +"@ethersproject/constants@^5.0.8": + version "5.0.10" + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.0.10.tgz#eb0c604fbc44c53ba9641eed31a1d0c9e1ebcadc" + integrity sha512-OSo8jxkHLDXieCy8bgOFR7lMfgPxEzKvSDdP+WAWHCDM8+orwch0B6wzkTmiQFgryAtIctrBt5glAdJikZ3hGw== dependencies: - "@ethersproject/abi" "^5.0.10" - "@ethersproject/abstract-provider" "^5.0.8" - "@ethersproject/abstract-signer" "^5.0.10" - "@ethersproject/address" "^5.0.9" "@ethersproject/bignumber" "^5.0.13" - "@ethersproject/bytes" "^5.0.9" - "@ethersproject/constants" "^5.0.8" - "@ethersproject/logger" "^5.0.8" - "@ethersproject/properties" "^5.0.7" -"@ethersproject/contracts@5.0.5", "@ethersproject/contracts@^5.0.5": +"@ethersproject/contracts@5.0.5": version "5.0.5" resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.0.5.tgz#64831a341ec8ca225e83ff3e9437c26b970fd5d7" integrity sha512-tFI255lFbmbqMkgnuyhDWHl3yWqttPlReplYuVvDCT/SuvBjLR4ad2uipBlh1fh5X1ipK9ettAoV4S0HKim4Kw== @@ -1578,19 +1650,21 @@ "@ethersproject/logger" "^5.0.5" "@ethersproject/properties" "^5.0.3" -"@ethersproject/hash@5.0.12", "@ethersproject/hash@^5.0.10": - version "5.0.12" - resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.0.12.tgz#1074599f7509e2ca2bb7a3d4f4e39ab3a796da42" - integrity sha512-kn4QN+fhNFbUgX3XZTZUaQixi0oyfIEY+hfW+KtkHu+rq7dV76oAIvaLEEynu1/4npOL38E4X4YI42gGZk+C0Q== - dependencies: - "@ethersproject/abstract-signer" "^5.0.10" - "@ethersproject/address" "^5.0.9" - "@ethersproject/bignumber" "^5.0.13" - "@ethersproject/bytes" "^5.0.9" - "@ethersproject/keccak256" "^5.0.7" - "@ethersproject/logger" "^5.0.8" - "@ethersproject/properties" "^5.0.7" - "@ethersproject/strings" "^5.0.8" +"@ethersproject/contracts@5.3.0", "@ethersproject/contracts@^5.0.0": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.3.0.tgz#ad699a3abaae30bfb6422cf31813a663b2d4099c" + integrity sha512-eDyQ8ltykvyQqnGZxb/c1e0OnEtzqXhNNC4BX8nhYBCaoBrYYuK/1fLmyEvc5+XUMoxNhwpYkoSSwvPLci7/Zg== + dependencies: + "@ethersproject/abi" "^5.3.0" + "@ethersproject/abstract-provider" "^5.3.0" + "@ethersproject/abstract-signer" "^5.3.0" + "@ethersproject/address" "^5.3.0" + "@ethersproject/bignumber" "^5.3.0" + "@ethersproject/bytes" "^5.3.0" + "@ethersproject/constants" "^5.3.0" + "@ethersproject/logger" "^5.3.0" + "@ethersproject/properties" "^5.3.0" + "@ethersproject/transactions" "^5.3.0" "@ethersproject/hash@5.0.5", "@ethersproject/hash@>=5.0.0-beta.128", "@ethersproject/hash@^5.0.4": version "5.0.5" @@ -1602,23 +1676,33 @@ "@ethersproject/logger" "^5.0.5" "@ethersproject/strings" "^5.0.4" -"@ethersproject/hdnode@5.0.10", "@ethersproject/hdnode@^5.0.8": - version "5.0.10" - resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.0.10.tgz#f7cdf154bf5d104c76dce2940745fc71d9e7eb1b" - integrity sha512-ZLwMtIcXK7xz2lSITDCl40W04CtRq4K9NwBxhCzdzPdaz6XnoJMwGz2YMVLg+8ksseq+RYtTwIIXtlK6vyvQyg== +"@ethersproject/hash@5.3.0", "@ethersproject/hash@^5.3.0": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.3.0.tgz#f65e3bf3db3282df4da676db6cfa049535dd3643" + integrity sha512-gAFZSjUPQ32CIfoKSMtMEQ+IO0kQxqhwz9fCIFt2DtAq2u4pWt8mL9Z5P0r6KkLcQU8LE9FmuPPyd+JvBzmr1w== + dependencies: + "@ethersproject/abstract-signer" "^5.3.0" + "@ethersproject/address" "^5.3.0" + "@ethersproject/bignumber" "^5.3.0" + "@ethersproject/bytes" "^5.3.0" + "@ethersproject/keccak256" "^5.3.0" + "@ethersproject/logger" "^5.3.0" + "@ethersproject/properties" "^5.3.0" + "@ethersproject/strings" "^5.3.0" + +"@ethersproject/hash@^5.0.10": + version "5.0.12" + resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.0.12.tgz#1074599f7509e2ca2bb7a3d4f4e39ab3a796da42" + integrity sha512-kn4QN+fhNFbUgX3XZTZUaQixi0oyfIEY+hfW+KtkHu+rq7dV76oAIvaLEEynu1/4npOL38E4X4YI42gGZk+C0Q== dependencies: "@ethersproject/abstract-signer" "^5.0.10" - "@ethersproject/basex" "^5.0.7" + "@ethersproject/address" "^5.0.9" "@ethersproject/bignumber" "^5.0.13" "@ethersproject/bytes" "^5.0.9" + "@ethersproject/keccak256" "^5.0.7" "@ethersproject/logger" "^5.0.8" - "@ethersproject/pbkdf2" "^5.0.7" "@ethersproject/properties" "^5.0.7" - "@ethersproject/sha2" "^5.0.7" - "@ethersproject/signing-key" "^5.0.8" "@ethersproject/strings" "^5.0.8" - "@ethersproject/transactions" "^5.0.9" - "@ethersproject/wordlists" "^5.0.8" "@ethersproject/hdnode@5.0.5", "@ethersproject/hdnode@^5.0.4": version "5.0.5" @@ -1638,24 +1722,23 @@ "@ethersproject/transactions" "^5.0.5" "@ethersproject/wordlists" "^5.0.4" -"@ethersproject/json-wallets@5.0.12", "@ethersproject/json-wallets@^5.0.10": - version "5.0.12" - resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.0.12.tgz#8946a0fcce1634b636313a50330b7d30a24996e8" - integrity sha512-nac553zGZnOewpjlqbfy7WBl8m3y7qudzRsI2dCxrediYtPIVIs9f6Pbnou8vDmmp8X4/U4W788d+Ma88o+Gbg== - dependencies: - "@ethersproject/abstract-signer" "^5.0.10" - "@ethersproject/address" "^5.0.9" - "@ethersproject/bytes" "^5.0.9" - "@ethersproject/hdnode" "^5.0.8" - "@ethersproject/keccak256" "^5.0.7" - "@ethersproject/logger" "^5.0.8" - "@ethersproject/pbkdf2" "^5.0.7" - "@ethersproject/properties" "^5.0.7" - "@ethersproject/random" "^5.0.7" - "@ethersproject/strings" "^5.0.8" - "@ethersproject/transactions" "^5.0.9" - aes-js "3.0.0" - scrypt-js "3.0.1" +"@ethersproject/hdnode@5.3.0", "@ethersproject/hdnode@^5.3.0": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.3.0.tgz#26fed65ffd5c25463fddff13f5fb4e5617553c94" + integrity sha512-zLmmtLNoDMGoYRdjOab01Zqkvp+TmZyCGDAMQF1Bs3yZyBs/kzTNi1qJjR1jVUcPP5CWGtjFwY8iNG8oNV9J8g== + dependencies: + "@ethersproject/abstract-signer" "^5.3.0" + "@ethersproject/basex" "^5.3.0" + "@ethersproject/bignumber" "^5.3.0" + "@ethersproject/bytes" "^5.3.0" + "@ethersproject/logger" "^5.3.0" + "@ethersproject/pbkdf2" "^5.3.0" + "@ethersproject/properties" "^5.3.0" + "@ethersproject/sha2" "^5.3.0" + "@ethersproject/signing-key" "^5.3.0" + "@ethersproject/strings" "^5.3.0" + "@ethersproject/transactions" "^5.3.0" + "@ethersproject/wordlists" "^5.3.0" "@ethersproject/json-wallets@5.0.7", "@ethersproject/json-wallets@^5.0.6": version "5.0.7" @@ -1676,6 +1759,25 @@ aes-js "3.0.0" scrypt-js "3.0.1" +"@ethersproject/json-wallets@5.3.0", "@ethersproject/json-wallets@^5.3.0": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.3.0.tgz#7b1a5ff500c12aa8597ae82c8939837b0449376e" + integrity sha512-/xwbqaIb5grUIGNmeEaz8GdcpmDr++X8WT4Jqcclnxow8PXCUHFeDxjf3O+nSuoqOYG/Ds0+BI5xuQKbva6Xkw== + dependencies: + "@ethersproject/abstract-signer" "^5.3.0" + "@ethersproject/address" "^5.3.0" + "@ethersproject/bytes" "^5.3.0" + "@ethersproject/hdnode" "^5.3.0" + "@ethersproject/keccak256" "^5.3.0" + "@ethersproject/logger" "^5.3.0" + "@ethersproject/pbkdf2" "^5.3.0" + "@ethersproject/properties" "^5.3.0" + "@ethersproject/random" "^5.3.0" + "@ethersproject/strings" "^5.3.0" + "@ethersproject/transactions" "^5.3.0" + aes-js "3.0.0" + scrypt-js "3.0.1" + "@ethersproject/keccak256@5.0.4", "@ethersproject/keccak256@>=5.0.0-beta.127", "@ethersproject/keccak256@^5.0.3": version "5.0.4" resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.0.4.tgz#36ca0a7d1ae2a272da5654cb886776d0c680ef3a" @@ -1684,7 +1786,15 @@ "@ethersproject/bytes" "^5.0.4" js-sha3 "0.5.7" -"@ethersproject/keccak256@5.0.9", "@ethersproject/keccak256@^5.0.7": +"@ethersproject/keccak256@5.3.0", "@ethersproject/keccak256@^5.3.0": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.3.0.tgz#fb5cd36bdfd6fa02e2ea84964078a9fc6bd731be" + integrity sha512-Gv2YqgIUmRbYVNIibafT0qGaeGYLIA/EdWHJ7JcVxVSs2vyxafGxOJ5VpSBHWeOIsE6OOaCelYowhuuTicgdFQ== + dependencies: + "@ethersproject/bytes" "^5.3.0" + js-sha3 "0.5.7" + +"@ethersproject/keccak256@^5.0.7": version "5.0.9" resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.0.9.tgz#ca0d86e4af56c13b1ef25e533bde3e96d28f647d" integrity sha512-zhdUTj6RGtCJSgU+bDrWF6cGbvW453LoIC1DSNWrTlXzC7WuH4a+EiPrgc7/kNoRxerKuA/cxYlI8GwNtVtDlw== @@ -1692,16 +1802,21 @@ "@ethersproject/bytes" "^5.0.9" js-sha3 "0.5.7" -"@ethersproject/logger@5.0.10", "@ethersproject/logger@^5.0.8": - version "5.0.10" - resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.0.10.tgz#fd884688b3143253e0356ef92d5f22d109d2e026" - integrity sha512-0y2T2NqykDrbPM3Zw9RSbPkDOxwChAL8detXaom76CfYoGxsOnRP/zTX8OUAV+x9LdwzgbWvWmeXrc0M7SuDZw== - "@ethersproject/logger@5.0.6", "@ethersproject/logger@>=5.0.0-beta.129", "@ethersproject/logger@^5.0.5": version "5.0.6" resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.0.6.tgz#faa484203e86e08be9e07fef826afeef7183fe88" integrity sha512-FrX0Vnb3JZ1md/7GIZfmJ06XOAA8r3q9Uqt9O5orr4ZiksnbpXKlyDzQtlZ5Yv18RS8CAUbiKH9vwidJg1BPmQ== +"@ethersproject/logger@5.3.0", "@ethersproject/logger@^5.3.0": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.3.0.tgz#7a69fa1d4ca0d4b7138da1627eb152f763d84dd0" + integrity sha512-8bwJ2gxJGkZZnpQSq5uSiZSJjyVTWmlGft4oH8vxHdvO1Asy4TwVepAhPgxIQIMxXZFUNMych1YjIV4oQ4I7dA== + +"@ethersproject/logger@^5.0.8": + version "5.0.10" + resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.0.10.tgz#fd884688b3143253e0356ef92d5f22d109d2e026" + integrity sha512-0y2T2NqykDrbPM3Zw9RSbPkDOxwChAL8detXaom76CfYoGxsOnRP/zTX8OUAV+x9LdwzgbWvWmeXrc0M7SuDZw== + "@ethersproject/networks@5.0.4", "@ethersproject/networks@^5.0.3": version "5.0.4" resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.0.4.tgz#6d320a5e15a0cda804f5da88be0ba846156f6eec" @@ -1709,7 +1824,14 @@ dependencies: "@ethersproject/logger" "^5.0.5" -"@ethersproject/networks@5.0.9", "@ethersproject/networks@^5.0.7": +"@ethersproject/networks@5.3.0", "@ethersproject/networks@^5.3.0": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.3.0.tgz#d8ad06eb107c69fb8651f4c81ddd0e88944fdfea" + integrity sha512-XGbD9MMgqrR7SYz8o6xVgdG+25v7YT5vQG8ZdlcLj2I7elOBM7VNeQrnxfSN7rWQNcqu2z80OM29gGbQz+4Low== + dependencies: + "@ethersproject/logger" "^5.3.0" + +"@ethersproject/networks@^5.0.7": version "5.0.9" resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.0.9.tgz#ec5da11e4d4bfd69bec4eaebc9ace33eb9569279" integrity sha512-L8+VCQwArBLGkxZb/5Ns/OH/OxP38AcaveXIxhUTq+VWpXYjrObG3E7RDQIKkUx1S1IcQl/UWTz5w4DK0UitJg== @@ -1724,13 +1846,13 @@ "@ethersproject/bytes" "^5.0.4" "@ethersproject/sha2" "^5.0.3" -"@ethersproject/pbkdf2@5.0.9", "@ethersproject/pbkdf2@^5.0.7": - version "5.0.9" - resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.0.9.tgz#be39c7f0a66c0d3cb1ad1dbb12a78e9bcdf9b5ae" - integrity sha512-ItE/wQ/WVw/ajEHPUVgfu0aEvksPgOQc+278bke8sGKnGO3ppjmqp0MHh17tHc1EBTzJbSms5aLIqc56qZ/oiA== +"@ethersproject/pbkdf2@5.3.0", "@ethersproject/pbkdf2@^5.3.0": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.3.0.tgz#8adbb41489c3c9f319cc44bc7d3e6095fd468dc8" + integrity sha512-Q9ChVU6gBFiex0FSdtzo4b0SAKz3ZYcYVFLrEWHL0FnHvNk3J3WgAtRNtBQGQYn/T5wkoTdZttMbfBkFlaiWcA== dependencies: - "@ethersproject/bytes" "^5.0.9" - "@ethersproject/sha2" "^5.0.7" + "@ethersproject/bytes" "^5.3.0" + "@ethersproject/sha2" "^5.3.0" "@ethersproject/properties@5.0.4", "@ethersproject/properties@>=5.0.0-beta.131", "@ethersproject/properties@^5.0.3": version "5.0.4" @@ -1739,14 +1861,21 @@ dependencies: "@ethersproject/logger" "^5.0.5" -"@ethersproject/properties@5.0.9", "@ethersproject/properties@^5.0.7": +"@ethersproject/properties@5.3.0", "@ethersproject/properties@^5.3.0": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.3.0.tgz#feef4c4babeb7c10a6b3449575016f4ad2c092b2" + integrity sha512-PaHxJyM5/bfusk6vr3yP//JMnm4UEojpzuWGTmtL5X4uNhNnFNvlYilZLyDr4I9cTkIbipCMsAuIcXWsmdRnEw== + dependencies: + "@ethersproject/logger" "^5.3.0" + +"@ethersproject/properties@^5.0.7": version "5.0.9" resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.0.9.tgz#d7aae634680760136ea522e25c3ef043ec15b5c2" integrity sha512-ZCjzbHYTw+rF1Pn8FDCEmx3gQttwIHcm/6Xee8g/M3Ga3SfW4tccNMbs5zqnBH0E4RoOPaeNgyg1O68TaF0tlg== dependencies: "@ethersproject/logger" "^5.0.8" -"@ethersproject/providers@5.0.12", "@ethersproject/providers@^5.0.12": +"@ethersproject/providers@5.0.12": version "5.0.12" resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.0.12.tgz#de05e865e130709ea1e0870511eb892bda7d41cb" integrity sha512-bRUEVNth+wGlm2Q0cQprVlixBWumfP9anrgAc3V2CbIh+GKvCwisVO8uRLrZOfOvTNSy6PUJi/Z4D5L+k3NAog== @@ -1771,30 +1900,30 @@ bech32 "1.1.4" ws "7.2.3" -"@ethersproject/providers@5.0.24": - version "5.0.24" - resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.0.24.tgz#4c638a029482d052faa18364b5e0e2d3ddd9c0cb" - integrity sha512-M4Iw1r4gGJkt7ZUa++iREuviKL/DIpmIMsaUlVlXtV+ZrUXeN8xQ3zOTrbz7R4h9W9oljBZM7i4D3Kn1krJ30A== - dependencies: - "@ethersproject/abstract-provider" "^5.0.8" - "@ethersproject/abstract-signer" "^5.0.10" - "@ethersproject/address" "^5.0.9" - "@ethersproject/basex" "^5.0.7" - "@ethersproject/bignumber" "^5.0.13" - "@ethersproject/bytes" "^5.0.9" - "@ethersproject/constants" "^5.0.8" - "@ethersproject/hash" "^5.0.10" - "@ethersproject/logger" "^5.0.8" - "@ethersproject/networks" "^5.0.7" - "@ethersproject/properties" "^5.0.7" - "@ethersproject/random" "^5.0.7" - "@ethersproject/rlp" "^5.0.7" - "@ethersproject/sha2" "^5.0.7" - "@ethersproject/strings" "^5.0.8" - "@ethersproject/transactions" "^5.0.9" - "@ethersproject/web" "^5.0.12" +"@ethersproject/providers@5.3.0", "@ethersproject/providers@^5.0.0": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.3.0.tgz#bccb49f1073a7d56e24f49abb14bb281c9b08636" + integrity sha512-HtL+DEbzPcRyfrkrMay7Rk/4he+NbUpzI/wHXP4Cqtra82nQOnqqCgTQc4HbdDrl75WVxG/JRMFhyneIPIMZaA== + dependencies: + "@ethersproject/abstract-provider" "^5.3.0" + "@ethersproject/abstract-signer" "^5.3.0" + "@ethersproject/address" "^5.3.0" + "@ethersproject/basex" "^5.3.0" + "@ethersproject/bignumber" "^5.3.0" + "@ethersproject/bytes" "^5.3.0" + "@ethersproject/constants" "^5.3.0" + "@ethersproject/hash" "^5.3.0" + "@ethersproject/logger" "^5.3.0" + "@ethersproject/networks" "^5.3.0" + "@ethersproject/properties" "^5.3.0" + "@ethersproject/random" "^5.3.0" + "@ethersproject/rlp" "^5.3.0" + "@ethersproject/sha2" "^5.3.0" + "@ethersproject/strings" "^5.3.0" + "@ethersproject/transactions" "^5.3.0" + "@ethersproject/web" "^5.3.0" bech32 "1.1.4" - ws "7.2.3" + ws "7.4.6" "@ethersproject/random@5.0.4", "@ethersproject/random@^5.0.3": version "5.0.4" @@ -1804,13 +1933,13 @@ "@ethersproject/bytes" "^5.0.4" "@ethersproject/logger" "^5.0.5" -"@ethersproject/random@5.0.9", "@ethersproject/random@^5.0.7": - version "5.0.9" - resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.0.9.tgz#1903d4436ba66e4c8ac77968b16f756abea3a0d0" - integrity sha512-DANG8THsKqFbJOantrxumtG6gyETNE54VfbsWa+SQAT8WKpDo9W/X5Zhh73KuhClaey1UI32uVmISZeq/Zxn1A== +"@ethersproject/random@5.3.0", "@ethersproject/random@^5.3.0": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.3.0.tgz#7c46bf36e50cb0d0550bc8c666af8e1d4496dc1a" + integrity sha512-A5SL/4inutSwt3Fh2OD0x2gz+x6GHmuUnIPkR7zAiTidMD2N8F6tZdMF1hlQKWVCcVMWhEQg8mWijhEzm6BBYw== dependencies: - "@ethersproject/bytes" "^5.0.9" - "@ethersproject/logger" "^5.0.8" + "@ethersproject/bytes" "^5.3.0" + "@ethersproject/logger" "^5.3.0" "@ethersproject/rlp@5.0.4", "@ethersproject/rlp@^5.0.3": version "5.0.4" @@ -1820,7 +1949,15 @@ "@ethersproject/bytes" "^5.0.4" "@ethersproject/logger" "^5.0.5" -"@ethersproject/rlp@5.0.9", "@ethersproject/rlp@^5.0.7": +"@ethersproject/rlp@5.3.0", "@ethersproject/rlp@^5.3.0": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.3.0.tgz#7cb93a7b5dfa69163894153c9d4b0d936f333188" + integrity sha512-oI0joYpsRanl9guDubaW+1NbcpK0vJ3F/6Wpcanzcnqq+oaW9O5E98liwkEDPcb16BUTLIJ+ZF8GPIHYxJ/5Pw== + dependencies: + "@ethersproject/bytes" "^5.3.0" + "@ethersproject/logger" "^5.3.0" + +"@ethersproject/rlp@^5.0.7": version "5.0.9" resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.0.9.tgz#da205bf8a34d3c3409eb73ddd237130a4b376aff" integrity sha512-ns1U7ZMVeruUW6JXc4om+1w3w4ynHN/0fpwmeNTsAjwGKoF8SAUgue6ylKpHKWSti2idx7jDxbn8hNNFHk67CA== @@ -1837,24 +1974,14 @@ "@ethersproject/logger" "^5.0.5" hash.js "1.1.3" -"@ethersproject/sha2@5.0.9", "@ethersproject/sha2@^5.0.7": - version "5.0.9" - resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.0.9.tgz#41275ee03e6e1660b3c997754005e089e936adc6" - integrity sha512-5FH4s47gM7N1fFAYQ1+m7aX0SbLg0Xr+6tvqndmNqc382/qBIbzXiGlUookrsjlPb6gLNurnTssCXjNM72J6lQ== - dependencies: - "@ethersproject/bytes" "^5.0.9" - "@ethersproject/logger" "^5.0.8" - hash.js "1.1.3" - -"@ethersproject/signing-key@5.0.11", "@ethersproject/signing-key@^5.0.8": - version "5.0.11" - resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.0.11.tgz#19fc5c4597e18ad0a5efc6417ba5b74069fdd2af" - integrity sha512-Jfcru/BGwdkXhLxT+8WCZtFy7LL0TPFZw05FAb5asxB/MyVsEfNdNxGDtjVE9zXfmRSPe/EusXYY4K7wcygOyQ== +"@ethersproject/sha2@5.3.0", "@ethersproject/sha2@^5.3.0": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.3.0.tgz#209f9a1649f7d2452dcd5e5b94af43b7f3f42366" + integrity sha512-r5ftlwKcocYEuFz2JbeKOT5SAsCV4m1RJDsTOEfQ5L67ZC7NFDK5i7maPdn1bx4nPhylF9VAwxSrQ1esmwzylg== dependencies: - "@ethersproject/bytes" "^5.0.9" - "@ethersproject/logger" "^5.0.8" - "@ethersproject/properties" "^5.0.7" - elliptic "6.5.4" + "@ethersproject/bytes" "^5.3.0" + "@ethersproject/logger" "^5.3.0" + hash.js "1.1.7" "@ethersproject/signing-key@5.0.5", "@ethersproject/signing-key@^5.0.4": version "5.0.5" @@ -1866,16 +1993,27 @@ "@ethersproject/properties" "^5.0.3" elliptic "6.5.3" -"@ethersproject/solidity@5.0.10", "@ethersproject/solidity@^5.0.9": - version "5.0.10" - resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.0.10.tgz#128c9289761cf83d81ff62a1195d6079a924a86c" - integrity sha512-8OG3HLqynWXDA6mVIHuHfF/ojTTwBahON7hc9GAKCqglzXCkVA3OpyxOJXPzjHClRIAUUiU7r9oy9Z/nsjtT/g== +"@ethersproject/signing-key@5.3.0", "@ethersproject/signing-key@^5.3.0": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.3.0.tgz#a96c88f8173e1abedfa35de32d3e5db7c48e5259" + integrity sha512-+DX/GwHAd0ok1bgedV1cKO0zfK7P/9aEyNoaYiRsGHpCecN7mhLqcdoUiUzE7Uz86LBsxm5ssK0qA1kBB47fbQ== + dependencies: + "@ethersproject/bytes" "^5.3.0" + "@ethersproject/logger" "^5.3.0" + "@ethersproject/properties" "^5.3.0" + bn.js "^4.11.9" + elliptic "6.5.4" + hash.js "1.1.7" + +"@ethersproject/signing-key@^5.0.8": + version "5.0.11" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.0.11.tgz#19fc5c4597e18ad0a5efc6417ba5b74069fdd2af" + integrity sha512-Jfcru/BGwdkXhLxT+8WCZtFy7LL0TPFZw05FAb5asxB/MyVsEfNdNxGDtjVE9zXfmRSPe/EusXYY4K7wcygOyQ== dependencies: - "@ethersproject/bignumber" "^5.0.13" "@ethersproject/bytes" "^5.0.9" - "@ethersproject/keccak256" "^5.0.7" - "@ethersproject/sha2" "^5.0.7" - "@ethersproject/strings" "^5.0.8" + "@ethersproject/logger" "^5.0.8" + "@ethersproject/properties" "^5.0.7" + elliptic "6.5.4" "@ethersproject/solidity@5.0.5": version "5.0.5" @@ -1888,14 +2026,16 @@ "@ethersproject/sha2" "^5.0.3" "@ethersproject/strings" "^5.0.4" -"@ethersproject/strings@5.0.10", "@ethersproject/strings@^5.0.8": - version "5.0.10" - resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.0.10.tgz#ddce1e9724f4ac4f3f67e0cac0b48748e964bfdb" - integrity sha512-KAeoS1tZ9/5ECXiIZA6S6hywbD0so2VmuW+Wfyo5EDXeyZ6Na1nxTPhTnW7voQmjbeYJffCrOc0qLFJeylyg7w== +"@ethersproject/solidity@5.3.0", "@ethersproject/solidity@^5.0.0": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.3.0.tgz#2a0b00b4aaaef99a080ddea13acab1fa35cd4a93" + integrity sha512-uLRBaNUiISHbut94XKewJgQh6UmydWTBp71I7I21pkjVXfZO2dJ5EOo3jCnumJc01M4LOm79dlNNmF3oGIvweQ== dependencies: - "@ethersproject/bytes" "^5.0.9" - "@ethersproject/constants" "^5.0.8" - "@ethersproject/logger" "^5.0.8" + "@ethersproject/bignumber" "^5.3.0" + "@ethersproject/bytes" "^5.3.0" + "@ethersproject/keccak256" "^5.3.0" + "@ethersproject/sha2" "^5.3.0" + "@ethersproject/strings" "^5.3.0" "@ethersproject/strings@5.0.5", "@ethersproject/strings@>=5.0.0-beta.130", "@ethersproject/strings@^5.0.4": version "5.0.5" @@ -1906,20 +2046,23 @@ "@ethersproject/constants" "^5.0.4" "@ethersproject/logger" "^5.0.5" -"@ethersproject/transactions@5.0.11", "@ethersproject/transactions@^5.0.9": - version "5.0.11" - resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.0.11.tgz#b31df5292f47937136a45885d6ee6112477c13df" - integrity sha512-ftsRvR9+gQp7L63F6+XmstvsZ4w8GtWvQB08e/zB+oB86Fnhq8+i/tkgpJplSHC8I/qgiCisva+M3u2GVhDFPA== +"@ethersproject/strings@5.3.0", "@ethersproject/strings@^5.3.0": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.3.0.tgz#a6b640aab56a18e0909f657da798eef890968ff0" + integrity sha512-j/AzIGZ503cvhuF2ldRSjB0BrKzpsBMtCieDtn4TYMMZMQ9zScJn9wLzTQl/bRNvJbBE6TOspK0r8/Ngae/f2Q== + dependencies: + "@ethersproject/bytes" "^5.3.0" + "@ethersproject/constants" "^5.3.0" + "@ethersproject/logger" "^5.3.0" + +"@ethersproject/strings@^5.0.8": + version "5.0.10" + resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.0.10.tgz#ddce1e9724f4ac4f3f67e0cac0b48748e964bfdb" + integrity sha512-KAeoS1tZ9/5ECXiIZA6S6hywbD0so2VmuW+Wfyo5EDXeyZ6Na1nxTPhTnW7voQmjbeYJffCrOc0qLFJeylyg7w== dependencies: - "@ethersproject/address" "^5.0.9" - "@ethersproject/bignumber" "^5.0.13" "@ethersproject/bytes" "^5.0.9" "@ethersproject/constants" "^5.0.8" - "@ethersproject/keccak256" "^5.0.7" "@ethersproject/logger" "^5.0.8" - "@ethersproject/properties" "^5.0.7" - "@ethersproject/rlp" "^5.0.7" - "@ethersproject/signing-key" "^5.0.8" "@ethersproject/transactions@5.0.6", "@ethersproject/transactions@^5.0.0-beta.135", "@ethersproject/transactions@^5.0.5": version "5.0.6" @@ -1936,16 +2079,37 @@ "@ethersproject/rlp" "^5.0.3" "@ethersproject/signing-key" "^5.0.4" -"@ethersproject/units@5.0.11": +"@ethersproject/transactions@5.3.0", "@ethersproject/transactions@^5.0.0", "@ethersproject/transactions@^5.3.0": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.3.0.tgz#49b86f2bafa4d0bdf8e596578fc795ee47c50458" + integrity sha512-cdfK8VVyW2oEBCXhURG0WQ6AICL/r6Gmjh0e4Bvbv6MCn/GBd8FeBH3rtl7ho+AW50csMKeGv3m3K1HSHB2jMQ== + dependencies: + "@ethersproject/address" "^5.3.0" + "@ethersproject/bignumber" "^5.3.0" + "@ethersproject/bytes" "^5.3.0" + "@ethersproject/constants" "^5.3.0" + "@ethersproject/keccak256" "^5.3.0" + "@ethersproject/logger" "^5.3.0" + "@ethersproject/properties" "^5.3.0" + "@ethersproject/rlp" "^5.3.0" + "@ethersproject/signing-key" "^5.3.0" + +"@ethersproject/transactions@^5.0.9": version "5.0.11" - resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.0.11.tgz#f82f6e353ac0d6fa43b17337790f1f9aa72cb4c8" - integrity sha512-nOSPmcCWyB/dwoBRhhTtPGCsTbiXqmc7Q0Adwvafc432AC7hy3Fj3IFZtnSXsbtJ/GdHCIUIoA8gtvxSsFuBJg== + resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.0.11.tgz#b31df5292f47937136a45885d6ee6112477c13df" + integrity sha512-ftsRvR9+gQp7L63F6+XmstvsZ4w8GtWvQB08e/zB+oB86Fnhq8+i/tkgpJplSHC8I/qgiCisva+M3u2GVhDFPA== dependencies: + "@ethersproject/address" "^5.0.9" "@ethersproject/bignumber" "^5.0.13" + "@ethersproject/bytes" "^5.0.9" "@ethersproject/constants" "^5.0.8" + "@ethersproject/keccak256" "^5.0.7" "@ethersproject/logger" "^5.0.8" + "@ethersproject/properties" "^5.0.7" + "@ethersproject/rlp" "^5.0.7" + "@ethersproject/signing-key" "^5.0.8" -"@ethersproject/units@5.0.6", "@ethersproject/units@^5.0.6": +"@ethersproject/units@5.0.6": version "5.0.6" resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.0.6.tgz#e1169ecffb7e8d5eab84e1481a4e35df19045708" integrity sha512-tsJuy4mipppdmooukRfhXt8fGx9nxvfvG6Xdy0RDm7LzHsjghjwQ69m2bCpId6SDSR1Uq1cQ9irPiUBSyWolUA== @@ -1954,26 +2118,14 @@ "@ethersproject/constants" "^5.0.4" "@ethersproject/logger" "^5.0.5" -"@ethersproject/wallet@5.0.12": - version "5.0.12" - resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.0.12.tgz#bfb96f95e066b4b1b4591c4615207b87afedda8b" - integrity sha512-rboJebGf47/KPZrKZQdYg9BAYuXbc/OwcUyML1K1f2jnJeo1ObWV11U1PAWTjTbhhSy6/Fg+34GO2yMb5Dt1Rw== +"@ethersproject/units@5.3.0": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.3.0.tgz#c4d1493532ad3d4ddf6e2bc4f8c94a2db933a8f5" + integrity sha512-BkfccZGwfJ6Ob+AelpIrgAzuNhrN2VLp3AILnkqTOv+yBdsc83V4AYf25XC/u0rHnWl6f4POaietPwlMqP2vUg== dependencies: - "@ethersproject/abstract-provider" "^5.0.8" - "@ethersproject/abstract-signer" "^5.0.10" - "@ethersproject/address" "^5.0.9" - "@ethersproject/bignumber" "^5.0.13" - "@ethersproject/bytes" "^5.0.9" - "@ethersproject/hash" "^5.0.10" - "@ethersproject/hdnode" "^5.0.8" - "@ethersproject/json-wallets" "^5.0.10" - "@ethersproject/keccak256" "^5.0.7" - "@ethersproject/logger" "^5.0.8" - "@ethersproject/properties" "^5.0.7" - "@ethersproject/random" "^5.0.7" - "@ethersproject/signing-key" "^5.0.8" - "@ethersproject/transactions" "^5.0.9" - "@ethersproject/wordlists" "^5.0.8" + "@ethersproject/bignumber" "^5.3.0" + "@ethersproject/constants" "^5.3.0" + "@ethersproject/logger" "^5.3.0" "@ethersproject/wallet@5.0.5": version "5.0.5" @@ -1996,16 +2148,26 @@ "@ethersproject/transactions" "^5.0.5" "@ethersproject/wordlists" "^5.0.4" -"@ethersproject/web@5.0.14", "@ethersproject/web@^5.0.12": - version "5.0.14" - resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.0.14.tgz#6e7bebdd9fb967cb25ee60f44d9218dc0803bac4" - integrity sha512-QpTgplslwZ0Sp9oKNLoRuS6TKxnkwfaEk3gr7zd7XLF8XBsYejsrQO/03fNfnMx/TAT/RR6WEw/mbOwpRSeVRA== - dependencies: - "@ethersproject/base64" "^5.0.7" - "@ethersproject/bytes" "^5.0.9" - "@ethersproject/logger" "^5.0.8" - "@ethersproject/properties" "^5.0.7" - "@ethersproject/strings" "^5.0.8" +"@ethersproject/wallet@5.3.0", "@ethersproject/wallet@^5.0.0": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.3.0.tgz#91946b470bd279e39ade58866f21f92749d062af" + integrity sha512-boYBLydG6671p9QoG6EinNnNzbm7DNOjVT20eV8J6HQEq4aUaGiA2CytF2vK+2rOEWbzhZqoNDt6AlkE1LlsTg== + dependencies: + "@ethersproject/abstract-provider" "^5.3.0" + "@ethersproject/abstract-signer" "^5.3.0" + "@ethersproject/address" "^5.3.0" + "@ethersproject/bignumber" "^5.3.0" + "@ethersproject/bytes" "^5.3.0" + "@ethersproject/hash" "^5.3.0" + "@ethersproject/hdnode" "^5.3.0" + "@ethersproject/json-wallets" "^5.3.0" + "@ethersproject/keccak256" "^5.3.0" + "@ethersproject/logger" "^5.3.0" + "@ethersproject/properties" "^5.3.0" + "@ethersproject/random" "^5.3.0" + "@ethersproject/signing-key" "^5.3.0" + "@ethersproject/transactions" "^5.3.0" + "@ethersproject/wordlists" "^5.3.0" "@ethersproject/web@5.0.9", "@ethersproject/web@^5.0.6": version "5.0.9" @@ -2018,13 +2180,24 @@ "@ethersproject/properties" "^5.0.3" "@ethersproject/strings" "^5.0.4" -"@ethersproject/wordlists@5.0.10", "@ethersproject/wordlists@^5.0.8": - version "5.0.10" - resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.0.10.tgz#177b9a0b4d72b9c4f304d08b36612d6c60e9b896" - integrity sha512-jWsEm1iJzpg9SCXnNfFz+tcp4Ofzv0TJb6mj+soCNcar9GcT0yGz62ZsHC3pLQWaF4LkCzGwRJHJTXKjHQfG1A== +"@ethersproject/web@5.3.0", "@ethersproject/web@^5.3.0": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.3.0.tgz#7959c403f6476c61515008d8f92da51c553a8ee1" + integrity sha512-Ni6/DHnY6k/TD41LEkv0RQDx4jqWz5e/RZvrSecsxGYycF+MFy2z++T/yGc2peRunLOTIFwEksgEGGlbwfYmhQ== + dependencies: + "@ethersproject/base64" "^5.3.0" + "@ethersproject/bytes" "^5.3.0" + "@ethersproject/logger" "^5.3.0" + "@ethersproject/properties" "^5.3.0" + "@ethersproject/strings" "^5.3.0" + +"@ethersproject/web@^5.0.12": + version "5.0.14" + resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.0.14.tgz#6e7bebdd9fb967cb25ee60f44d9218dc0803bac4" + integrity sha512-QpTgplslwZ0Sp9oKNLoRuS6TKxnkwfaEk3gr7zd7XLF8XBsYejsrQO/03fNfnMx/TAT/RR6WEw/mbOwpRSeVRA== dependencies: + "@ethersproject/base64" "^5.0.7" "@ethersproject/bytes" "^5.0.9" - "@ethersproject/hash" "^5.0.10" "@ethersproject/logger" "^5.0.8" "@ethersproject/properties" "^5.0.7" "@ethersproject/strings" "^5.0.8" @@ -2040,6 +2213,17 @@ "@ethersproject/properties" "^5.0.3" "@ethersproject/strings" "^5.0.4" +"@ethersproject/wordlists@5.3.0", "@ethersproject/wordlists@^5.3.0": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.3.0.tgz#45a0205f5178c1de33d316cb2ab7ed5eac3c06c5" + integrity sha512-JcwumCZcsUxgWpiFU/BRy6b4KlTRdOmYvOKZcAw/3sdF93/pZyPW5Od2hFkHS8oWp4xS06YQ+qHqQhdcxdHafQ== + dependencies: + "@ethersproject/bytes" "^5.3.0" + "@ethersproject/hash" "^5.3.0" + "@ethersproject/logger" "^5.3.0" + "@ethersproject/properties" "^5.3.0" + "@ethersproject/strings" "^5.3.0" + "@graphprotocol/graph-cli@0.18.0": version "0.18.0" resolved "https://registry.yarnpkg.com/@graphprotocol/graph-cli/-/graph-cli-0.18.0.tgz#c09c6a54cb2da114c499b19de7adb74f0157fbd2" @@ -2336,10 +2520,10 @@ safe-buffer "^5.1.1" util.promisify "^1.0.0" -"@nomiclabs/hardhat-ethers@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.0.0.tgz#ebab032b3aed03945ea560f56bb67aec56a30cbc" - integrity sha512-fIi6XP9PgKqwSNVcLDr6S5hvGlc21PendaLD5eGdXEXc9aYQ0OJX8Mk3evs+p78x7W9n9U3ZcKtTiGc1+YScDw== +"@nomiclabs/hardhat-ethers@npm:hardhat-deploy-ethers": + version "0.3.0-beta.8" + resolved "https://registry.yarnpkg.com/hardhat-deploy-ethers/-/hardhat-deploy-ethers-0.3.0-beta.8.tgz#a0ca0e7db31301a11e61b738cb1576c6e6a57bc0" + integrity sha512-asPqbKxMZ0XGjf5x2F/zdfW5dzEID9xXOCx7ZVrEB0dkxbCIzjsYUb5ovYSZkoCWMVLOrCa4sNh8CkOVNMBJCQ== "@nomiclabs/hardhat-etherscan@^2.1.1": version "2.1.1" @@ -2860,6 +3044,11 @@ dependencies: "@types/node" "*" +"@types/promise-poller@^1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@types/promise-poller/-/promise-poller-1.7.0.tgz#479f14c87ffd340736666e338369ca3331bb635c" + integrity sha512-pxEVcCo5rc0S5Fm+6dzPoE0jsfwXaczEU8fStTVluclw/qk+607AGyvwTmeYXWtbBXUkKlOsf/Lq7Hbwg4pxbw== + "@types/prop-types@*": version "15.7.3" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7" @@ -2875,6 +3064,11 @@ resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.5.tgz#434711bdd49eb5ee69d90c1d67c354a9a8ecb18b" integrity sha512-/JHkVHtx/REVG0VVToGRGH2+23hsYLHdyG+GrvoUGlGAd0ErauXDyvHtRI/7H7mzLm+tBCKA7pfcpkQ1lf58iQ== +"@types/qs@^6.9.4": + version "6.9.6" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.6.tgz#df9c3c8b31a247ec315e6996566be3171df4b3b1" + integrity sha512-0/HnwIfW4ki2D8L8c9GVcG5I72s9jP5GSLVF0VIXDW00kmIpA6O33G7a8n59Tmh7Nz0WUC3rSb7PTY/sdW2JzA== + "@types/range-parser@*": version "1.2.3" resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c" @@ -3836,6 +4030,17 @@ aproba@^1.0.3, aproba@^1.1.1: resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== +arb-ts@^0.0.18: + version "0.0.18" + resolved "https://registry.yarnpkg.com/arb-ts/-/arb-ts-0.0.18.tgz#f38ebf55d7274f06fce5c57c2a9facaad7dd7b09" + integrity sha512-0VSvtFx9wcq73qLqHTCFv7evkekT9V2GYiUVOX5zdoiStTXi8Chd9o2AxD/Ro0tUcu0+oXbfhw+gErgZCoiqAQ== + dependencies: + "@ethersproject/address" "^5.0.8" + "@ethersproject/bignumber" "^5.1.1" + "@ethersproject/bytes" "^5.0.8" + "@types/promise-poller" "^1.7.0" + ethers "^5.0.24" + archy@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" @@ -5514,7 +5719,7 @@ builtin-status-codes@^3.0.0: resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= -burner-provider@^1.0.15, burner-provider@^1.0.38: +burner-provider@^1.0.15: version "1.0.38" resolved "https://registry.yarnpkg.com/burner-provider/-/burner-provider-1.0.38.tgz#a610ebfdf13220558bd2b8f3db73bad0eea8954f" integrity sha512-ZcZ8wNm380+l4MlVD5qhy5Gsa6Gr0Cftniksyqw6tVi+HmFuy8mvu1+eJR4Vt7NdGNWh9v74zNJVx3HQfQveUw== @@ -7493,6 +7698,11 @@ enc-utils@2.1.0: is-typedarray "1.0.0" typedarray-to-buffer "3.1.5" +encode-utf8@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/encode-utf8/-/encode-utf8-1.0.3.tgz#f30fdd31da07fb596f281beb2f6b027851994cda" + integrity sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw== + encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" @@ -8640,7 +8850,7 @@ ethers@^4.0.46: uuid "2.0.1" xmlhttprequest "1.8.0" -ethers@^5.0.0, ethers@^5.0.1, ethers@^5.0.17: +ethers@^5.0.0, ethers@^5.0.1: version "5.0.17" resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.0.17.tgz#35dea41f1d09d31f80e0bb4c03cb633cd6673756" integrity sha512-E0MrwCttHgdD6Irfa0B9cNdX0VoWVWLusaj51+EQalkl3pqhV2zGMPncfhYbc9+4nD2u81dbX8Pk9UN5kh/jew== @@ -8676,41 +8886,41 @@ ethers@^5.0.0, ethers@^5.0.1, ethers@^5.0.17: "@ethersproject/web" "5.0.9" "@ethersproject/wordlists" "5.0.5" -ethers@^5.0.31: - version "5.0.32" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.0.32.tgz#f009970be31d96a589bf0ce597a39c10c7e297a6" - integrity sha512-rORfGWR0HsA4pjKMMcWZorw12DHsXqfIAuPVHJsXt+vI24jvXcVqx+rLsSvgOoLdaCMdxiN5qlIq2+4axKG31g== - dependencies: - "@ethersproject/abi" "5.0.13" - "@ethersproject/abstract-provider" "5.0.10" - "@ethersproject/abstract-signer" "5.0.14" - "@ethersproject/address" "5.0.11" - "@ethersproject/base64" "5.0.9" - "@ethersproject/basex" "5.0.9" - "@ethersproject/bignumber" "5.0.15" - "@ethersproject/bytes" "5.0.11" - "@ethersproject/constants" "5.0.10" - "@ethersproject/contracts" "5.0.12" - "@ethersproject/hash" "5.0.12" - "@ethersproject/hdnode" "5.0.10" - "@ethersproject/json-wallets" "5.0.12" - "@ethersproject/keccak256" "5.0.9" - "@ethersproject/logger" "5.0.10" - "@ethersproject/networks" "5.0.9" - "@ethersproject/pbkdf2" "5.0.9" - "@ethersproject/properties" "5.0.9" - "@ethersproject/providers" "5.0.24" - "@ethersproject/random" "5.0.9" - "@ethersproject/rlp" "5.0.9" - "@ethersproject/sha2" "5.0.9" - "@ethersproject/signing-key" "5.0.11" - "@ethersproject/solidity" "5.0.10" - "@ethersproject/strings" "5.0.10" - "@ethersproject/transactions" "5.0.11" - "@ethersproject/units" "5.0.11" - "@ethersproject/wallet" "5.0.12" - "@ethersproject/web" "5.0.14" - "@ethersproject/wordlists" "5.0.10" +ethers@^5.0.24, ethers@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.3.0.tgz#1ec14d09c461e8f2554b00cd080e94a3094e7e9d" + integrity sha512-myN+338S4sFQZvQ9trii7xit8Hu/LnUtjA0ROFOHpUreQc3fgLZEMNVqF3vM1u2D78DIIeG1TbuozVCVlXQWvQ== + dependencies: + "@ethersproject/abi" "5.3.0" + "@ethersproject/abstract-provider" "5.3.0" + "@ethersproject/abstract-signer" "5.3.0" + "@ethersproject/address" "5.3.0" + "@ethersproject/base64" "5.3.0" + "@ethersproject/basex" "5.3.0" + "@ethersproject/bignumber" "5.3.0" + "@ethersproject/bytes" "5.3.0" + "@ethersproject/constants" "5.3.0" + "@ethersproject/contracts" "5.3.0" + "@ethersproject/hash" "5.3.0" + "@ethersproject/hdnode" "5.3.0" + "@ethersproject/json-wallets" "5.3.0" + "@ethersproject/keccak256" "5.3.0" + "@ethersproject/logger" "5.3.0" + "@ethersproject/networks" "5.3.0" + "@ethersproject/pbkdf2" "5.3.0" + "@ethersproject/properties" "5.3.0" + "@ethersproject/providers" "5.3.0" + "@ethersproject/random" "5.3.0" + "@ethersproject/rlp" "5.3.0" + "@ethersproject/sha2" "5.3.0" + "@ethersproject/signing-key" "5.3.0" + "@ethersproject/solidity" "5.3.0" + "@ethersproject/strings" "5.3.0" + "@ethersproject/transactions" "5.3.0" + "@ethersproject/units" "5.3.0" + "@ethersproject/wallet" "5.3.0" + "@ethersproject/web" "5.3.0" + "@ethersproject/wordlists" "5.3.0" ethjs-unit@0.1.6: version "0.1.6" @@ -9287,6 +9497,13 @@ flush-write-stream@^1.0.0, flush-write-stream@^1.0.2: inherits "^2.0.3" readable-stream "^2.3.6" +fmix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/fmix/-/fmix-0.1.0.tgz#c7bbf124dec42c9d191cfb947d0a9778dd986c0c" + integrity sha1-x7vxJN7ELJ0ZHPuUfQqXeN2YbAw= + dependencies: + imul "^1.0.0" + follow-redirects@1.5.10: version "1.5.10" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a" @@ -9455,6 +9672,16 @@ fs-extra@^8.1.0: jsonfile "^4.0.0" universalify "^0.1.0" +fs-extra@^9.0.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" + integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== + dependencies: + at-least-node "^1.0.0" + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + fs-extra@^9.0.1: version "9.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.0.1.tgz#910da0062437ba4c39fedd863f1675ccfefcb9fc" @@ -10121,6 +10348,32 @@ har-validator@~5.1.3: ajv "^6.12.3" har-schema "^2.0.0" +hardhat-deploy@^0.7.10: + version "0.7.10" + resolved "https://registry.yarnpkg.com/hardhat-deploy/-/hardhat-deploy-0.7.10.tgz#2bc94bf36db5f39aa488c6c6569f07d5ca4b410a" + integrity sha512-+0oiEWy/FgKOEzRNhSWPqSjofVCwtkK3E5x916kbZ5SgFGOjWTFCrWbWUYjzc2GyZgNXuSuRn8mBowHSLF4sVg== + dependencies: + "@ethersproject/abi" "^5.0.0" + "@ethersproject/abstract-signer" "^5.0.0" + "@ethersproject/address" "^5.0.0" + "@ethersproject/bignumber" "^5.0.0" + "@ethersproject/bytes" "^5.0.0" + "@ethersproject/contracts" "^5.0.0" + "@ethersproject/providers" "^5.0.0" + "@ethersproject/solidity" "^5.0.0" + "@ethersproject/transactions" "^5.0.0" + "@ethersproject/wallet" "^5.0.0" + "@types/qs" "^6.9.4" + axios "^0.21.1" + chalk "^4.1.0" + chokidar "^3.4.0" + debug "^4.1.1" + form-data "^3.0.0" + fs-extra "^9.0.0" + match-all "^1.2.6" + murmur-128 "^0.2.1" + qs "^6.9.4" + hardhat@^2.0.11: version "2.1.1" resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.1.1.tgz#bcfed980019672b57011845a1678f714728d6ee7" @@ -10667,6 +10920,11 @@ import-local@^2.0.0: pkg-dir "^3.0.0" resolve-cwd "^2.0.0" +imul@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/imul/-/imul-1.0.1.tgz#9d5867161e8b3de96c2c38d5dc7cb102f35e2ac9" + integrity sha1-nVhnFh6LPelsLDjV3HyxAvNeKsk= + imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -13409,6 +13667,11 @@ markdown-it@^10.0.0: mdurl "^1.0.1" uc.micro "^1.0.5" +match-all@^1.2.6: + version "1.2.6" + resolved "https://registry.yarnpkg.com/match-all/-/match-all-1.2.6.tgz#66d276ad6b49655551e63d3a6ee53e8be0566f8d" + integrity sha512-0EESkXiTkWzrQQntBu2uzKvLu6vVkUGz40nGPbSZuegcfE5UuSzNjLaIu76zJWuaT/2I3Z/8M06OlUOZLGwLlQ== + matchdep@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/matchdep/-/matchdep-2.0.0.tgz#c6f34834a0d8dbc3b37c27ee8bbcb27c7775582e" @@ -14038,6 +14301,15 @@ multihashing-async@~0.8.0, multihashing-async@~0.8.1: multihashes "^1.0.1" murmurhash3js-revisited "^3.0.0" +murmur-128@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/murmur-128/-/murmur-128-0.2.1.tgz#a9f6568781d2350ecb1bf80c14968cadbeaa4b4d" + integrity sha512-WseEgiRkI6aMFBbj8Cg9yBj/y+OdipwVC7zUo3W2W1JAJITwouUOtpqsmGSg67EQmwwSyod7hsVsWY5LsrfQVg== + dependencies: + encode-utf8 "^1.0.2" + fmix "^0.1.0" + imul "^1.0.0" + murmurhash3js-revisited@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/murmurhash3js-revisited/-/murmurhash3js-revisited-3.0.0.tgz#6bd36e25de8f73394222adc6e41fa3fac08a5869" @@ -16438,6 +16710,13 @@ qs@^6.5.2, qs@^6.7.0: resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.4.tgz#9090b290d1f91728d3c22e54843ca44aea5ab687" integrity sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ== +qs@^6.9.4: + version "6.10.1" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.1.tgz#4931482fa8d647a5aab799c5271d2133b981fb6a" + integrity sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg== + dependencies: + side-channel "^1.0.4" + qs@~6.5.2: version "6.5.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" @@ -18191,6 +18470,15 @@ side-channel@^1.0.2, side-channel@^1.0.3: es-abstract "^1.18.0-next.0" object-inspect "^1.8.0" +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" @@ -19726,6 +20014,11 @@ universalify@^1.0.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-1.0.0.tgz#b61a1da173e8435b2fe3c67d29b9adf8594bd16d" integrity sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug== +universalify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" + integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== + unorm@^1.3.3: version "1.6.0" resolved "https://registry.yarnpkg.com/unorm/-/unorm-1.6.0.tgz#029b289661fba714f1a9af439eb51d9b16c205af" @@ -20949,6 +21242,11 @@ ws@7.3.0: resolved "https://registry.yarnpkg.com/ws/-/ws-7.3.0.tgz#4b2f7f219b3d3737bc1a2fbf145d825b94d38ffd" integrity sha512-iFtXzngZVXPGgpTlP1rBqsUK82p9tKqsWRPg5L56egiljujJT3vGAYnHANvFxBieXrTFavhzhxW52jnaWV+w2w== +ws@7.4.6: + version "7.4.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" + integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== + ws@^3.0.0: version "3.3.3" resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2"