From 4e413915f8fa3bfdda98c6d623dd35d207cda150 Mon Sep 17 00:00:00 2001 From: Noah Zinsmeister Date: Thu, 25 Apr 2019 12:12:47 -0400 Subject: [PATCH] web3-react migration (#269) * put suspense below redux * don't mount qr * properly format .json's * remove useless Web3Connect component * remove react-responsive header logic * finalize initial web3-react migration * add rudimentary network support * address ci/cd issues * fix syntax * add infura support rewrite create-exchange closes #173 * remove CI flag, lazy loaded disabled for now * roll back /pool * fix currency input errors fix valid state of buttons * fix nav * obscure env variables * fix mobile header bug --- .env.example | 3 + .gitignore | 1 + README.md | 16 +- netlify.toml | 1 + package.json | 7 +- public/locales/en.json | 1 + src/abi/erc20.json | 160 +----- src/abi/erc20_symbol_bytes32.json | 160 +----- src/abi/exchange.json | 462 +++++++++++++++++- src/abi/factory.json | 75 ++- .../address-input-panel.scss | 1 - src/components/AddressInputPanel/index.js | 83 ++-- src/components/CurrencyInputPanel/index.js | 250 +++++----- src/components/Header/header.scss | 11 +- src/components/Header/index.js | 163 +++--- .../NavigationTabs/beta-message.scss | 25 - src/components/NavigationTabs/index.js | 111 +++-- .../NavigationTabs/navigation-tabs.scss | 58 +++ src/components/Tab/index.js | 33 -- src/components/Tab/tab.scss | 45 -- src/components/Web3Status/index.js | 5 +- src/constants/actionTypes.js | 2 - src/ducks/addresses.js | 4 + src/ducks/web3connect.js | 185 +++---- src/hooks/index.js | 51 ++ src/i18n.js | 10 +- src/index.js | 20 +- src/pages/App.js | 119 +++-- src/pages/App.scss | 14 + src/pages/App.test.js | 12 +- src/pages/Pool/AddLiquidity.js | 83 ++-- src/pages/Pool/CreateExchange.js | 339 +++++-------- src/pages/Pool/ModeSelector.js | 156 +++--- src/pages/Pool/RemoveLiquidity.js | 66 +-- src/pages/Pool/index.js | 53 +- src/pages/Pool/pool.scss | 29 +- src/pages/Send/index.js | 153 +++--- src/pages/Swap/index.js | 132 +++-- src/pages/Swap/swap.scss | 1 + src/utils/index.js | 71 +++ yarn.lock | 385 +++------------ 41 files changed, 1820 insertions(+), 1736 deletions(-) create mode 100644 .env.example delete mode 100644 src/components/NavigationTabs/beta-message.scss create mode 100644 src/components/NavigationTabs/navigation-tabs.scss delete mode 100644 src/components/Tab/index.js delete mode 100644 src/components/Tab/tab.scss create mode 100644 src/hooks/index.js create mode 100644 src/utils/index.js diff --git a/.env.example b/.env.example new file mode 100644 index 00000000000..be2aa2fe268 --- /dev/null +++ b/.env.example @@ -0,0 +1,3 @@ +REACT_APP_NETWORK_ID="1" +REACT_APP_NETWORK_URL="" +REACT_APP_NETWORK_NAME="Main Ethereum Network" \ No newline at end of file diff --git a/.gitignore b/.gitignore index ae4492d7fd4..51e4bad77b5 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ # misc .DS_Store +.env .env.local .env.development.local .env.test.local diff --git a/README.md b/README.md index a0e1ea61b4b..096dd2947f3 100644 --- a/README.md +++ b/README.md @@ -16,24 +16,26 @@ This an an open source interface for Uniswap - a protocol for decentralized exch ## To Start Development -###### Installing dependencies +### Install Dependencies ```bash yarn ``` -###### Running locally on Rinkeby +### Configure Environment -```bash -yarn start:rinkeby -``` +Rename `.env.example` to `.env` and fill in the appropriate variables. -###### Running locally on other testnet +### Run ```bash -REACT_APP_NETWORK_ID=2 REACT_APP_NETWORK='Ropsten Test Network' yarn start +yarn start +# or +yarn start:rinkeby ``` +More robust support for other testnets is in the works! + ## Contributions **Please open all pull requests against the `beta` branch.** CI checks will run against all PRs. To ensure that your changes will pass, run `yarn check:all` before pushing. If this command fails, you can try to automatically fix problems with `yarn fix:all`, or do it manually. diff --git a/netlify.toml b/netlify.toml index b87b8d3ddaa..d4796aaa75d 100644 --- a/netlify.toml +++ b/netlify.toml @@ -1,3 +1,4 @@ +# support SPA setup [[redirects]] from = "/*" to = "/index.html" diff --git a/package.json b/package.json index 6295d321018..a73ccf5077a 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,6 @@ "react-ga": "^2.5.7", "react-i18next": "^10.7.0", "react-redux": "^5.0.7", - "react-responsive": "^5.0.0", "react-router-dom": "^5.0.0", "react-scripts": "^2.1.8", "react-transition-group": "1.x", @@ -29,13 +28,13 @@ "redux-thunk": "^2.2.0", "ua-parser-js": "^0.7.18", "web3": "1.0.0-beta.52", - "web3-react": "^4.0.0" + "web3-react": "^5.0.4" }, "scripts": { "start": "react-scripts start", - "start:rinkeby": "REACT_APP_NETWORK_ID=4 REACT_APP_NETWORK='Rinkeby Test Network' yarn start", "build": "react-scripts build", - "build:rinkeby": "REACT_APP_NETWORK_ID=4 REACT_APP_NETWORK='Rinkeby Test Network' yarn build", + "start:rinkeby": "REACT_APP_NETWORK_ID=4 REACT_APP_NETWORK_NAME='Rinkeby Test Network' yarn start", + "build:rinkeby": "REACT_APP_NETWORK_ID=4 REACT_APP_NETWORK_NAME='Rinkeby Test Network' yarn build", "test": "react-scripts test --env=jsdom", "eject": "react-scripts eject", "lint:base": "yarn eslint './src/**/*.{js,jsx}'", diff --git a/public/locales/en.json b/public/locales/en.json index 3d59b67acc2..5b788eea1e4 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -70,6 +70,7 @@ "invalidDecimals": "Invalid decimals", "tokenAddress": "Token Address", "label": "Label", + "symbol": "Symbol", "decimals": "Decimals", "enterTokenCont": "Enter a token address to continue" } diff --git a/src/abi/erc20.json b/src/abi/erc20.json index 405d6b36486..0e647b9a234 100644 --- a/src/abi/erc20.json +++ b/src/abi/erc20.json @@ -3,35 +3,16 @@ "constant": true, "inputs": [], "name": "name", - "outputs": [ - { - "name": "", - "type": "string" - } - ], + "outputs": [{ "name": "", "type": "string" }], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": false, - "inputs": [ - { - "name": "_spender", - "type": "address" - }, - { - "name": "_value", - "type": "uint256" - } - ], + "inputs": [{ "name": "_spender", "type": "address" }, { "name": "_value", "type": "uint256" }], "name": "approve", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], + "outputs": [{ "name": "", "type": "bool" }], "payable": false, "stateMutability": "nonpayable", "type": "function" @@ -40,12 +21,7 @@ "constant": true, "inputs": [], "name": "totalSupply", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], + "outputs": [{ "name": "", "type": "uint256" }], "payable": false, "stateMutability": "view", "type": "function" @@ -53,26 +29,12 @@ { "constant": false, "inputs": [ - { - "name": "_from", - "type": "address" - }, - { - "name": "_to", - "type": "address" - }, - { - "name": "_value", - "type": "uint256" - } + { "name": "_from", "type": "address" }, + { "name": "_to", "type": "address" }, + { "name": "_value", "type": "uint256" } ], "name": "transferFrom", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], + "outputs": [{ "name": "", "type": "bool" }], "payable": false, "stateMutability": "nonpayable", "type": "function" @@ -81,31 +43,16 @@ "constant": true, "inputs": [], "name": "decimals", - "outputs": [ - { - "name": "", - "type": "uint8" - } - ], + "outputs": [{ "name": "", "type": "uint8" }], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], + "inputs": [{ "name": "_owner", "type": "address" }], "name": "balanceOf", - "outputs": [ - { - "name": "balance", - "type": "uint256" - } - ], + "outputs": [{ "name": "balance", "type": "uint256" }], "payable": false, "stateMutability": "view", "type": "function" @@ -114,85 +61,36 @@ "constant": true, "inputs": [], "name": "symbol", - "outputs": [ - { - "name": "", - "type": "string" - } - ], + "outputs": [{ "name": "", "type": "string" }], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": false, - "inputs": [ - { - "name": "_to", - "type": "address" - }, - { - "name": "_value", - "type": "uint256" - } - ], + "inputs": [{ "name": "_to", "type": "address" }, { "name": "_value", "type": "uint256" }], "name": "transfer", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], + "outputs": [{ "name": "", "type": "bool" }], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - }, - { - "name": "_spender", - "type": "address" - } - ], + "inputs": [{ "name": "_owner", "type": "address" }, { "name": "_spender", "type": "address" }], "name": "allowance", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], + "outputs": [{ "name": "", "type": "uint256" }], "payable": false, "stateMutability": "view", "type": "function" }, - { - "payable": true, - "stateMutability": "payable", - "type": "fallback" - }, + { "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" - } + { "indexed": true, "name": "owner", "type": "address" }, + { "indexed": true, "name": "spender", "type": "address" }, + { "indexed": false, "name": "value", "type": "uint256" } ], "name": "Approval", "type": "event" @@ -200,21 +98,9 @@ { "anonymous": false, "inputs": [ - { - "indexed": true, - "name": "from", - "type": "address" - }, - { - "indexed": true, - "name": "to", - "type": "address" - }, - { - "indexed": false, - "name": "value", - "type": "uint256" - } + { "indexed": true, "name": "from", "type": "address" }, + { "indexed": true, "name": "to", "type": "address" }, + { "indexed": false, "name": "value", "type": "uint256" } ], "name": "Transfer", "type": "event" diff --git a/src/abi/erc20_symbol_bytes32.json b/src/abi/erc20_symbol_bytes32.json index 8b556812186..329bf2bb3dc 100644 --- a/src/abi/erc20_symbol_bytes32.json +++ b/src/abi/erc20_symbol_bytes32.json @@ -3,35 +3,16 @@ "constant": true, "inputs": [], "name": "name", - "outputs": [ - { - "name": "", - "type": "string" - } - ], + "outputs": [{ "name": "", "type": "string" }], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": false, - "inputs": [ - { - "name": "_spender", - "type": "address" - }, - { - "name": "_value", - "type": "uint256" - } - ], + "inputs": [{ "name": "_spender", "type": "address" }, { "name": "_value", "type": "uint256" }], "name": "approve", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], + "outputs": [{ "name": "", "type": "bool" }], "payable": false, "stateMutability": "nonpayable", "type": "function" @@ -40,12 +21,7 @@ "constant": true, "inputs": [], "name": "totalSupply", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], + "outputs": [{ "name": "", "type": "uint256" }], "payable": false, "stateMutability": "view", "type": "function" @@ -53,26 +29,12 @@ { "constant": false, "inputs": [ - { - "name": "_from", - "type": "address" - }, - { - "name": "_to", - "type": "address" - }, - { - "name": "_value", - "type": "uint256" - } + { "name": "_from", "type": "address" }, + { "name": "_to", "type": "address" }, + { "name": "_value", "type": "uint256" } ], "name": "transferFrom", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], + "outputs": [{ "name": "", "type": "bool" }], "payable": false, "stateMutability": "nonpayable", "type": "function" @@ -81,31 +43,16 @@ "constant": true, "inputs": [], "name": "decimals", - "outputs": [ - { - "name": "", - "type": "uint8" - } - ], + "outputs": [{ "name": "", "type": "uint8" }], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], + "inputs": [{ "name": "_owner", "type": "address" }], "name": "balanceOf", - "outputs": [ - { - "name": "balance", - "type": "uint256" - } - ], + "outputs": [{ "name": "balance", "type": "uint256" }], "payable": false, "stateMutability": "view", "type": "function" @@ -114,85 +61,36 @@ "constant": true, "inputs": [], "name": "symbol", - "outputs": [ - { - "name": "", - "type": "bytes32" - } - ], + "outputs": [{ "name": "", "type": "bytes32" }], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": false, - "inputs": [ - { - "name": "_to", - "type": "address" - }, - { - "name": "_value", - "type": "uint256" - } - ], + "inputs": [{ "name": "_to", "type": "address" }, { "name": "_value", "type": "uint256" }], "name": "transfer", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], + "outputs": [{ "name": "", "type": "bool" }], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - }, - { - "name": "_spender", - "type": "address" - } - ], + "inputs": [{ "name": "_owner", "type": "address" }, { "name": "_spender", "type": "address" }], "name": "allowance", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], + "outputs": [{ "name": "", "type": "uint256" }], "payable": false, "stateMutability": "view", "type": "function" }, - { - "payable": true, - "stateMutability": "payable", - "type": "fallback" - }, + { "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" - } + { "indexed": true, "name": "owner", "type": "address" }, + { "indexed": true, "name": "spender", "type": "address" }, + { "indexed": false, "name": "value", "type": "uint256" } ], "name": "Approval", "type": "event" @@ -200,21 +98,9 @@ { "anonymous": false, "inputs": [ - { - "indexed": true, - "name": "from", - "type": "address" - }, - { - "indexed": true, - "name": "to", - "type": "address" - }, - { - "indexed": false, - "name": "value", - "type": "uint256" - } + { "indexed": true, "name": "from", "type": "address" }, + { "indexed": true, "name": "to", "type": "address" }, + { "indexed": false, "name": "value", "type": "uint256" } ], "name": "Transfer", "type": "event" diff --git a/src/abi/exchange.json b/src/abi/exchange.json index 4eda656d62b..25cff7558a8 100644 --- a/src/abi/exchange.json +++ b/src/abi/exchange.json @@ -1,2 +1,460 @@ -[{"name": "TokenPurchase", "inputs": [{"type": "address", "name": "buyer", "indexed": true}, {"type": "uint256", "name": "eth_sold", "indexed": true}, {"type": "uint256", "name": "tokens_bought", "indexed": true}], "anonymous": false, "type": "event"}, {"name": "EthPurchase", "inputs": [{"type": "address", "name": "buyer", "indexed": true}, {"type": "uint256", "name": "tokens_sold", "indexed": true}, {"type": "uint256", "name": "eth_bought", "indexed": true}], "anonymous": false, "type": "event"}, {"name": "AddLiquidity", "inputs": [{"type": "address", "name": "provider", "indexed": true}, {"type": "uint256", "name": "eth_amount", "indexed": true}, {"type": "uint256", "name": "token_amount", "indexed": true}], "anonymous": false, "type": "event"}, {"name": "RemoveLiquidity", "inputs": [{"type": "address", "name": "provider", "indexed": true}, {"type": "uint256", "name": "eth_amount", "indexed": true}, {"type": "uint256", "name": "token_amount", "indexed": true}], "anonymous": false, "type": "event"}, {"name": "Transfer", "inputs": [{"type": "address", "name": "_from", "indexed": true}, {"type": "address", "name": "_to", "indexed": true}, {"type": "uint256", "name": "_value", "indexed": false}], "anonymous": false, "type": "event"}, {"name": "Approval", "inputs": [{"type": "address", "name": "_owner", "indexed": true}, {"type": "address", "name": "_spender", "indexed": true}, {"type": "uint256", "name": "_value", "indexed": false}], "anonymous": false, "type": "event"}, {"name": "setup", "outputs": [], "inputs": [{"type": "address", "name": "token_addr"}], "constant": false, "payable": false, "type": "function", "gas": 175875}, {"name": "addLiquidity", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "min_liquidity"}, {"type": "uint256", "name": "max_tokens"}, {"type": "uint256", "name": "deadline"}], "constant": false, "payable": true, "type": "function", "gas": 82605}, {"name": "removeLiquidity", "outputs": [{"type": "uint256", "name": "out"}, {"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "amount"}, {"type": "uint256", "name": "min_eth"}, {"type": "uint256", "name": "min_tokens"}, {"type": "uint256", "name": "deadline"}], "constant": false, "payable": false, "type": "function", "gas": 116814}, {"name": "__default__", "outputs": [], "inputs": [], "constant": false, "payable": true, "type": "function"}, {"name": "ethToTokenSwapInput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "min_tokens"}, {"type": "uint256", "name": "deadline"}], "constant": false, "payable": true, "type": "function", "gas": 12757}, {"name": "ethToTokenTransferInput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "min_tokens"}, {"type": "uint256", "name": "deadline"}, {"type": "address", "name": "recipient"}], "constant": false, "payable": true, "type": "function", "gas": 12965}, {"name": "ethToTokenSwapOutput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_bought"}, {"type": "uint256", "name": "deadline"}], "constant": false, "payable": true, "type": "function", "gas": 50463}, {"name": "ethToTokenTransferOutput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_bought"}, {"type": "uint256", "name": "deadline"}, {"type": "address", "name": "recipient"}], "constant": false, "payable": true, "type": "function", "gas": 50671}, {"name": "tokenToEthSwapInput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_sold"}, {"type": "uint256", "name": "min_eth"}, {"type": "uint256", "name": "deadline"}], "constant": false, "payable": false, "type": "function", "gas": 47503}, {"name": "tokenToEthTransferInput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_sold"}, {"type": "uint256", "name": "min_eth"}, {"type": "uint256", "name": "deadline"}, {"type": "address", "name": "recipient"}], "constant": false, "payable": false, "type": "function", "gas": 47712}, {"name": "tokenToEthSwapOutput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "eth_bought"}, {"type": "uint256", "name": "max_tokens"}, {"type": "uint256", "name": "deadline"}], "constant": false, "payable": false, "type": "function", "gas": 50175}, {"name": "tokenToEthTransferOutput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "eth_bought"}, {"type": "uint256", "name": "max_tokens"}, {"type": "uint256", "name": "deadline"}, {"type": "address", "name": "recipient"}], "constant": false, "payable": false, "type": "function", "gas": 50384}, {"name": "tokenToTokenSwapInput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_sold"}, {"type": "uint256", "name": "min_tokens_bought"}, {"type": "uint256", "name": "min_eth_bought"}, {"type": "uint256", "name": "deadline"}, {"type": "address", "name": "token_addr"}], "constant": false, "payable": false, "type": "function", "gas": 51007}, {"name": "tokenToTokenTransferInput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_sold"}, {"type": "uint256", "name": "min_tokens_bought"}, {"type": "uint256", "name": "min_eth_bought"}, {"type": "uint256", "name": "deadline"}, {"type": "address", "name": "recipient"}, {"type": "address", "name": "token_addr"}], "constant": false, "payable": false, "type": "function", "gas": 51098}, {"name": "tokenToTokenSwapOutput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_bought"}, {"type": "uint256", "name": "max_tokens_sold"}, {"type": "uint256", "name": "max_eth_sold"}, {"type": "uint256", "name": "deadline"}, {"type": "address", "name": "token_addr"}], "constant": false, "payable": false, "type": "function", "gas": 54928}, {"name": "tokenToTokenTransferOutput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_bought"}, {"type": "uint256", "name": "max_tokens_sold"}, {"type": "uint256", "name": "max_eth_sold"}, {"type": "uint256", "name": "deadline"}, {"type": "address", "name": "recipient"}, {"type": "address", "name": "token_addr"}], "constant": false, "payable": false, "type": "function", "gas": 55019}, {"name": "tokenToExchangeSwapInput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_sold"}, {"type": "uint256", "name": "min_tokens_bought"}, {"type": "uint256", "name": "min_eth_bought"}, {"type": "uint256", "name": "deadline"}, {"type": "address", "name": "exchange_addr"}], "constant": false, "payable": false, "type": "function", "gas": 49342}, {"name": "tokenToExchangeTransferInput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_sold"}, {"type": "uint256", "name": "min_tokens_bought"}, {"type": "uint256", "name": "min_eth_bought"}, {"type": "uint256", "name": "deadline"}, {"type": "address", "name": "recipient"}, {"type": "address", "name": "exchange_addr"}], "constant": false, "payable": false, "type": "function", "gas": 49532}, {"name": "tokenToExchangeSwapOutput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_bought"}, {"type": "uint256", "name": "max_tokens_sold"}, {"type": "uint256", "name": "max_eth_sold"}, {"type": "uint256", "name": "deadline"}, {"type": "address", "name": "exchange_addr"}], "constant": false, "payable": false, "type": "function", "gas": 53233}, {"name": "tokenToExchangeTransferOutput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_bought"}, {"type": "uint256", "name": "max_tokens_sold"}, {"type": "uint256", "name": "max_eth_sold"}, {"type": "uint256", "name": "deadline"}, {"type": "address", "name": "recipient"}, {"type": "address", "name": "exchange_addr"}], "constant": false, "payable": false, "type": "function", "gas": 53423}, {"name": "getEthToTokenInputPrice", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "eth_sold"}], "constant": true, "payable": false, "type": "function", "gas": 5542}, {"name": "getEthToTokenOutputPrice", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_bought"}], "constant": true, "payable": false, "type": "function", "gas": 6872}, {"name": "getTokenToEthInputPrice", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_sold"}], "constant": true, "payable": false, "type": "function", "gas": 5637}, {"name": "getTokenToEthOutputPrice", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "eth_bought"}], "constant": true, "payable": false, "type": "function", "gas": 6897}, {"name": "tokenAddress", "outputs": [{"type": "address", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 1413}, {"name": "factoryAddress", "outputs": [{"type": "address", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 1443}, {"name": "balanceOf", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "address", "name": "_owner"}], "constant": true, "payable": false, "type": "function", "gas": 1645}, {"name": "transfer", "outputs": [{"type": "bool", "name": "out"}], "inputs": [{"type": "address", "name": "_to"}, {"type": "uint256", "name": "_value"}], "constant": false, "payable": false, "type": "function", "gas": 75034}, {"name": "transferFrom", "outputs": [{"type": "bool", "name": "out"}], "inputs": [{"type": "address", "name": "_from"}, {"type": "address", "name": "_to"}, {"type": "uint256", "name": "_value"}], "constant": false, "payable": false, "type": "function", "gas": 110907}, {"name": "approve", "outputs": [{"type": "bool", "name": "out"}], "inputs": [{"type": "address", "name": "_spender"}, {"type": "uint256", "name": "_value"}], "constant": false, "payable": false, "type": "function", "gas": 38769}, {"name": "allowance", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "address", "name": "_owner"}, {"type": "address", "name": "_spender"}], "constant": true, "payable": false, "type": "function", "gas": 1925}, {"name": "name", "outputs": [{"type": "bytes32", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 1623}, {"name": "symbol", "outputs": [{"type": "bytes32", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 1653}, {"name": "decimals", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 1683}, {"name": "totalSupply", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 1713}] - +[ + { + "name": "TokenPurchase", + "inputs": [ + { "type": "address", "name": "buyer", "indexed": true }, + { "type": "uint256", "name": "eth_sold", "indexed": true }, + { "type": "uint256", "name": "tokens_bought", "indexed": true } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "EthPurchase", + "inputs": [ + { "type": "address", "name": "buyer", "indexed": true }, + { "type": "uint256", "name": "tokens_sold", "indexed": true }, + { "type": "uint256", "name": "eth_bought", "indexed": true } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "AddLiquidity", + "inputs": [ + { "type": "address", "name": "provider", "indexed": true }, + { "type": "uint256", "name": "eth_amount", "indexed": true }, + { "type": "uint256", "name": "token_amount", "indexed": true } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "RemoveLiquidity", + "inputs": [ + { "type": "address", "name": "provider", "indexed": true }, + { "type": "uint256", "name": "eth_amount", "indexed": true }, + { "type": "uint256", "name": "token_amount", "indexed": true } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "Transfer", + "inputs": [ + { "type": "address", "name": "_from", "indexed": true }, + { "type": "address", "name": "_to", "indexed": true }, + { "type": "uint256", "name": "_value", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "Approval", + "inputs": [ + { "type": "address", "name": "_owner", "indexed": true }, + { "type": "address", "name": "_spender", "indexed": true }, + { "type": "uint256", "name": "_value", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "setup", + "outputs": [], + "inputs": [{ "type": "address", "name": "token_addr" }], + "constant": false, + "payable": false, + "type": "function", + "gas": 175875 + }, + { + "name": "addLiquidity", + "outputs": [{ "type": "uint256", "name": "out" }], + "inputs": [ + { "type": "uint256", "name": "min_liquidity" }, + { "type": "uint256", "name": "max_tokens" }, + { "type": "uint256", "name": "deadline" } + ], + "constant": false, + "payable": true, + "type": "function", + "gas": 82605 + }, + { + "name": "removeLiquidity", + "outputs": [{ "type": "uint256", "name": "out" }, { "type": "uint256", "name": "out" }], + "inputs": [ + { "type": "uint256", "name": "amount" }, + { "type": "uint256", "name": "min_eth" }, + { "type": "uint256", "name": "min_tokens" }, + { "type": "uint256", "name": "deadline" } + ], + "constant": false, + "payable": false, + "type": "function", + "gas": 116814 + }, + { "name": "__default__", "outputs": [], "inputs": [], "constant": false, "payable": true, "type": "function" }, + { + "name": "ethToTokenSwapInput", + "outputs": [{ "type": "uint256", "name": "out" }], + "inputs": [{ "type": "uint256", "name": "min_tokens" }, { "type": "uint256", "name": "deadline" }], + "constant": false, + "payable": true, + "type": "function", + "gas": 12757 + }, + { + "name": "ethToTokenTransferInput", + "outputs": [{ "type": "uint256", "name": "out" }], + "inputs": [ + { "type": "uint256", "name": "min_tokens" }, + { "type": "uint256", "name": "deadline" }, + { "type": "address", "name": "recipient" } + ], + "constant": false, + "payable": true, + "type": "function", + "gas": 12965 + }, + { + "name": "ethToTokenSwapOutput", + "outputs": [{ "type": "uint256", "name": "out" }], + "inputs": [{ "type": "uint256", "name": "tokens_bought" }, { "type": "uint256", "name": "deadline" }], + "constant": false, + "payable": true, + "type": "function", + "gas": 50463 + }, + { + "name": "ethToTokenTransferOutput", + "outputs": [{ "type": "uint256", "name": "out" }], + "inputs": [ + { "type": "uint256", "name": "tokens_bought" }, + { "type": "uint256", "name": "deadline" }, + { "type": "address", "name": "recipient" } + ], + "constant": false, + "payable": true, + "type": "function", + "gas": 50671 + }, + { + "name": "tokenToEthSwapInput", + "outputs": [{ "type": "uint256", "name": "out" }], + "inputs": [ + { "type": "uint256", "name": "tokens_sold" }, + { "type": "uint256", "name": "min_eth" }, + { "type": "uint256", "name": "deadline" } + ], + "constant": false, + "payable": false, + "type": "function", + "gas": 47503 + }, + { + "name": "tokenToEthTransferInput", + "outputs": [{ "type": "uint256", "name": "out" }], + "inputs": [ + { "type": "uint256", "name": "tokens_sold" }, + { "type": "uint256", "name": "min_eth" }, + { "type": "uint256", "name": "deadline" }, + { "type": "address", "name": "recipient" } + ], + "constant": false, + "payable": false, + "type": "function", + "gas": 47712 + }, + { + "name": "tokenToEthSwapOutput", + "outputs": [{ "type": "uint256", "name": "out" }], + "inputs": [ + { "type": "uint256", "name": "eth_bought" }, + { "type": "uint256", "name": "max_tokens" }, + { "type": "uint256", "name": "deadline" } + ], + "constant": false, + "payable": false, + "type": "function", + "gas": 50175 + }, + { + "name": "tokenToEthTransferOutput", + "outputs": [{ "type": "uint256", "name": "out" }], + "inputs": [ + { "type": "uint256", "name": "eth_bought" }, + { "type": "uint256", "name": "max_tokens" }, + { "type": "uint256", "name": "deadline" }, + { "type": "address", "name": "recipient" } + ], + "constant": false, + "payable": false, + "type": "function", + "gas": 50384 + }, + { + "name": "tokenToTokenSwapInput", + "outputs": [{ "type": "uint256", "name": "out" }], + "inputs": [ + { "type": "uint256", "name": "tokens_sold" }, + { "type": "uint256", "name": "min_tokens_bought" }, + { "type": "uint256", "name": "min_eth_bought" }, + { "type": "uint256", "name": "deadline" }, + { "type": "address", "name": "token_addr" } + ], + "constant": false, + "payable": false, + "type": "function", + "gas": 51007 + }, + { + "name": "tokenToTokenTransferInput", + "outputs": [{ "type": "uint256", "name": "out" }], + "inputs": [ + { "type": "uint256", "name": "tokens_sold" }, + { "type": "uint256", "name": "min_tokens_bought" }, + { "type": "uint256", "name": "min_eth_bought" }, + { "type": "uint256", "name": "deadline" }, + { "type": "address", "name": "recipient" }, + { "type": "address", "name": "token_addr" } + ], + "constant": false, + "payable": false, + "type": "function", + "gas": 51098 + }, + { + "name": "tokenToTokenSwapOutput", + "outputs": [{ "type": "uint256", "name": "out" }], + "inputs": [ + { "type": "uint256", "name": "tokens_bought" }, + { "type": "uint256", "name": "max_tokens_sold" }, + { "type": "uint256", "name": "max_eth_sold" }, + { "type": "uint256", "name": "deadline" }, + { "type": "address", "name": "token_addr" } + ], + "constant": false, + "payable": false, + "type": "function", + "gas": 54928 + }, + { + "name": "tokenToTokenTransferOutput", + "outputs": [{ "type": "uint256", "name": "out" }], + "inputs": [ + { "type": "uint256", "name": "tokens_bought" }, + { "type": "uint256", "name": "max_tokens_sold" }, + { "type": "uint256", "name": "max_eth_sold" }, + { "type": "uint256", "name": "deadline" }, + { "type": "address", "name": "recipient" }, + { "type": "address", "name": "token_addr" } + ], + "constant": false, + "payable": false, + "type": "function", + "gas": 55019 + }, + { + "name": "tokenToExchangeSwapInput", + "outputs": [{ "type": "uint256", "name": "out" }], + "inputs": [ + { "type": "uint256", "name": "tokens_sold" }, + { "type": "uint256", "name": "min_tokens_bought" }, + { "type": "uint256", "name": "min_eth_bought" }, + { "type": "uint256", "name": "deadline" }, + { "type": "address", "name": "exchange_addr" } + ], + "constant": false, + "payable": false, + "type": "function", + "gas": 49342 + }, + { + "name": "tokenToExchangeTransferInput", + "outputs": [{ "type": "uint256", "name": "out" }], + "inputs": [ + { "type": "uint256", "name": "tokens_sold" }, + { "type": "uint256", "name": "min_tokens_bought" }, + { "type": "uint256", "name": "min_eth_bought" }, + { "type": "uint256", "name": "deadline" }, + { "type": "address", "name": "recipient" }, + { "type": "address", "name": "exchange_addr" } + ], + "constant": false, + "payable": false, + "type": "function", + "gas": 49532 + }, + { + "name": "tokenToExchangeSwapOutput", + "outputs": [{ "type": "uint256", "name": "out" }], + "inputs": [ + { "type": "uint256", "name": "tokens_bought" }, + { "type": "uint256", "name": "max_tokens_sold" }, + { "type": "uint256", "name": "max_eth_sold" }, + { "type": "uint256", "name": "deadline" }, + { "type": "address", "name": "exchange_addr" } + ], + "constant": false, + "payable": false, + "type": "function", + "gas": 53233 + }, + { + "name": "tokenToExchangeTransferOutput", + "outputs": [{ "type": "uint256", "name": "out" }], + "inputs": [ + { "type": "uint256", "name": "tokens_bought" }, + { "type": "uint256", "name": "max_tokens_sold" }, + { "type": "uint256", "name": "max_eth_sold" }, + { "type": "uint256", "name": "deadline" }, + { "type": "address", "name": "recipient" }, + { "type": "address", "name": "exchange_addr" } + ], + "constant": false, + "payable": false, + "type": "function", + "gas": 53423 + }, + { + "name": "getEthToTokenInputPrice", + "outputs": [{ "type": "uint256", "name": "out" }], + "inputs": [{ "type": "uint256", "name": "eth_sold" }], + "constant": true, + "payable": false, + "type": "function", + "gas": 5542 + }, + { + "name": "getEthToTokenOutputPrice", + "outputs": [{ "type": "uint256", "name": "out" }], + "inputs": [{ "type": "uint256", "name": "tokens_bought" }], + "constant": true, + "payable": false, + "type": "function", + "gas": 6872 + }, + { + "name": "getTokenToEthInputPrice", + "outputs": [{ "type": "uint256", "name": "out" }], + "inputs": [{ "type": "uint256", "name": "tokens_sold" }], + "constant": true, + "payable": false, + "type": "function", + "gas": 5637 + }, + { + "name": "getTokenToEthOutputPrice", + "outputs": [{ "type": "uint256", "name": "out" }], + "inputs": [{ "type": "uint256", "name": "eth_bought" }], + "constant": true, + "payable": false, + "type": "function", + "gas": 6897 + }, + { + "name": "tokenAddress", + "outputs": [{ "type": "address", "name": "out" }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function", + "gas": 1413 + }, + { + "name": "factoryAddress", + "outputs": [{ "type": "address", "name": "out" }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function", + "gas": 1443 + }, + { + "name": "balanceOf", + "outputs": [{ "type": "uint256", "name": "out" }], + "inputs": [{ "type": "address", "name": "_owner" }], + "constant": true, + "payable": false, + "type": "function", + "gas": 1645 + }, + { + "name": "transfer", + "outputs": [{ "type": "bool", "name": "out" }], + "inputs": [{ "type": "address", "name": "_to" }, { "type": "uint256", "name": "_value" }], + "constant": false, + "payable": false, + "type": "function", + "gas": 75034 + }, + { + "name": "transferFrom", + "outputs": [{ "type": "bool", "name": "out" }], + "inputs": [ + { "type": "address", "name": "_from" }, + { "type": "address", "name": "_to" }, + { "type": "uint256", "name": "_value" } + ], + "constant": false, + "payable": false, + "type": "function", + "gas": 110907 + }, + { + "name": "approve", + "outputs": [{ "type": "bool", "name": "out" }], + "inputs": [{ "type": "address", "name": "_spender" }, { "type": "uint256", "name": "_value" }], + "constant": false, + "payable": false, + "type": "function", + "gas": 38769 + }, + { + "name": "allowance", + "outputs": [{ "type": "uint256", "name": "out" }], + "inputs": [{ "type": "address", "name": "_owner" }, { "type": "address", "name": "_spender" }], + "constant": true, + "payable": false, + "type": "function", + "gas": 1925 + }, + { + "name": "name", + "outputs": [{ "type": "bytes32", "name": "out" }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function", + "gas": 1623 + }, + { + "name": "symbol", + "outputs": [{ "type": "bytes32", "name": "out" }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function", + "gas": 1653 + }, + { + "name": "decimals", + "outputs": [{ "type": "uint256", "name": "out" }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function", + "gas": 1683 + }, + { + "name": "totalSupply", + "outputs": [{ "type": "uint256", "name": "out" }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function", + "gas": 1713 + } +] diff --git a/src/abi/factory.json b/src/abi/factory.json index aba20fd18c1..cc50a366e07 100644 --- a/src/abi/factory.json +++ b/src/abi/factory.json @@ -1 +1,74 @@ -[{"name": "NewExchange", "inputs": [{"type": "address", "name": "token", "indexed": true}, {"type": "address", "name": "exchange", "indexed": true}], "anonymous": false, "type": "event"}, {"name": "initializeFactory", "outputs": [], "inputs": [{"type": "address", "name": "template"}], "constant": false, "payable": false, "type": "function", "gas": 35725}, {"name": "createExchange", "outputs": [{"type": "address", "name": "out"}], "inputs": [{"type": "address", "name": "token"}], "constant": false, "payable": false, "type": "function", "gas": 187911}, {"name": "getExchange", "outputs": [{"type": "address", "name": "out"}], "inputs": [{"type": "address", "name": "token"}], "constant": true, "payable": false, "type": "function", "gas": 715}, {"name": "getToken", "outputs": [{"type": "address", "name": "out"}], "inputs": [{"type": "address", "name": "exchange"}], "constant": true, "payable": false, "type": "function", "gas": 745}, {"name": "getTokenWithId", "outputs": [{"type": "address", "name": "out"}], "inputs": [{"type": "uint256", "name": "token_id"}], "constant": true, "payable": false, "type": "function", "gas": 736}, {"name": "exchangeTemplate", "outputs": [{"type": "address", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 633}, {"name": "tokenCount", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 663}] \ No newline at end of file +[ + { + "name": "NewExchange", + "inputs": [ + { "type": "address", "name": "token", "indexed": true }, + { "type": "address", "name": "exchange", "indexed": true } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "initializeFactory", + "outputs": [], + "inputs": [{ "type": "address", "name": "template" }], + "constant": false, + "payable": false, + "type": "function", + "gas": 35725 + }, + { + "name": "createExchange", + "outputs": [{ "type": "address", "name": "out" }], + "inputs": [{ "type": "address", "name": "token" }], + "constant": false, + "payable": false, + "type": "function", + "gas": 187911 + }, + { + "name": "getExchange", + "outputs": [{ "type": "address", "name": "out" }], + "inputs": [{ "type": "address", "name": "token" }], + "constant": true, + "payable": false, + "type": "function", + "gas": 715 + }, + { + "name": "getToken", + "outputs": [{ "type": "address", "name": "out" }], + "inputs": [{ "type": "address", "name": "exchange" }], + "constant": true, + "payable": false, + "type": "function", + "gas": 745 + }, + { + "name": "getTokenWithId", + "outputs": [{ "type": "address", "name": "out" }], + "inputs": [{ "type": "uint256", "name": "token_id" }], + "constant": true, + "payable": false, + "type": "function", + "gas": 736 + }, + { + "name": "exchangeTemplate", + "outputs": [{ "type": "address", "name": "out" }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function", + "gas": 633 + }, + { + "name": "tokenCount", + "outputs": [{ "type": "uint256", "name": "out" }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function", + "gas": 663 + } +] diff --git a/src/components/AddressInputPanel/address-input-panel.scss b/src/components/AddressInputPanel/address-input-panel.scss index d9c70290e0c..6f3df3a7c3d 100644 --- a/src/components/AddressInputPanel/address-input-panel.scss +++ b/src/components/AddressInputPanel/address-input-panel.scss @@ -33,7 +33,6 @@ } &__qr-container { - display: none; padding: 10px; background: $concrete-gray; border: 1px solid $mercury-gray; diff --git a/src/components/AddressInputPanel/index.js b/src/components/AddressInputPanel/index.js index e8ebc29ef2b..899336d691b 100644 --- a/src/components/AddressInputPanel/index.js +++ b/src/components/AddressInputPanel/index.js @@ -1,58 +1,45 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import c from 'classnames' +import React from 'react' +import classnames from 'classnames' +import { useTranslation } from 'react-i18next' -import QrCode from '../QrCode' -import './address-input-panel.scss' - -class AddressInputPanel extends Component { - static propTypes = { - title: PropTypes.string, - onChange: PropTypes.func, - value: PropTypes.string, - errorMessage: PropTypes.string - } +// import QrCode from '../QrCode' // commented out pending further review - static defaultProps = { - onChange() {}, - value: '' - } +import './address-input-panel.scss' - render() { - const { t, title, onChange, value, errorMessage } = this.props +export default function AddressInputPanel({ title, onChange = () => {}, value = '', errorMessage }) { + const { t } = useTranslation() - return ( -
-
-
-
-
- {title || t('recipientAddress')} -
-
-
- onChange(e.target.value)} - value={value} - /> + return ( +
+
+
+
+
+ {title || t('recipientAddress')}
-
- onChange(value)} /> +
+ onChange(e.target.value)} + value={value} + />
+ {/* commented out pending further review +
+ onChange(value)} /> +
+ */}
- ) - } +
+ ) } - -export default AddressInputPanel diff --git a/src/components/CurrencyInputPanel/index.js b/src/components/CurrencyInputPanel/index.js index 65fd366ed2b..be66f6f44f5 100644 --- a/src/components/CurrencyInputPanel/index.js +++ b/src/components/CurrencyInputPanel/index.js @@ -1,10 +1,15 @@ -import React, { Component } from 'react' +import React, { useState, useRef, useEffect } from 'react' import { connect } from 'react-redux' -import PropTypes from 'prop-types' import { CSSTransitionGroup } from 'react-transition-group' import classnames from 'classnames' import { withRouter } from 'react-router-dom' -import { withTranslation } from 'react-i18next' +import { withTranslation, useTranslation } from 'react-i18next' +import { BigNumber as BN } from 'bignumber.js' +import { useWeb3Context } from 'web3-react' +import { ethers } from 'ethers' + +import { useSignerOrProvider } from '../../hooks' +import { getExchangeDetails, getTokenDetails, isAddress } from '../../utils' import Fuse from '../../helpers/fuse' import Modal from '../Modal' import TokenLogo from '../TokenLogo' @@ -12,13 +17,10 @@ import SearchIcon from '../../assets/images/magnifying-glass.svg' import { selectors, addPendingTx } from '../../ducks/web3connect' import { addApprovalTx } from '../../ducks/pending' import { addExchange } from '../../ducks/addresses' -import { BigNumber as BN } from 'bignumber.js' +import ERC20_ABI from '../../abi/erc20' import './currency-panel.scss' -import ERC20_ABI from '../../abi/erc20' -import FACTORY_ABI from '../../abi/factory' - const FUSE_OPTIONS = { includeMatches: false, threshold: 0.0, @@ -32,50 +34,51 @@ const FUSE_OPTIONS = { const TOKEN_ADDRESS_TO_LABEL = { ETH: 'ETH' } -class CurrencyInputPanel extends Component { - static propTypes = { - title: PropTypes.string, - description: PropTypes.string, - extraText: PropTypes.string, - value: PropTypes.string, - onCurrencySelected: PropTypes.func, - onValueChange: PropTypes.func, - tokenAddresses: PropTypes.shape({ - addresses: PropTypes.array.isRequired - }).isRequired, - exchangeAddresses: PropTypes.shape({ - fromToken: PropTypes.object.isRequired - }).isRequired, - factoryAddress: PropTypes.string, - selectedTokens: PropTypes.array.isRequired, - errorMessage: PropTypes.string, - account: PropTypes.string, - selectedTokenAddress: PropTypes.string, - disableTokenSelect: PropTypes.bool, - selectors: PropTypes.func.isRequired, - addExchange: PropTypes.func.isRequired, - filteredTokens: PropTypes.arrayOf(PropTypes.string), - disableUnlock: PropTypes.bool, - renderInput: PropTypes.func - } - - static defaultProps = { - selectedTokens: [], - filteredTokens: [], - onCurrencySelected() {}, - onValueChange() {}, - selectedTokenAddress: '' - } - - state = { - isShowingModal: false, - searchQuery: '', - loadingExchange: false - } +function CurrencyInputPanel({ + tokenAddresses, + filteredTokens = [], + onValueChange = () => {}, + renderInput, + onCurrencySelected = () => {}, + title, + description, + extraText, + errorMessage, + selectedTokens = [], + disableUnlock, + disableTokenSelect, + selectors, + account, + factoryAddress, + selectedTokenAddress = '', + exchangeAddresses: { fromToken }, + addExchange, + history, + web3, + transactions, + pendingApprovals, + value, + addApprovalTx, + addPendingTx +}) { + const { t } = useTranslation() + const context = useWeb3Context() + const signerOrProvider = useSignerOrProvider() + + const inputRef = useRef() + + const [isShowingModal, setIsShowingModal] = useState(false) + const [searchQuery, setSearchQuery] = useState('') + const [loadingExchange, setLoadingExchange] = useState(false) + + useEffect(() => { + if (inputRef.current && isShowingModal) { + inputRef.current.focus() + } + }, [inputRef.current, isShowingModal]) - createTokenList = () => { - const { filteredTokens } = this.props - let tokens = this.props.tokenAddresses.addresses + function createTokenList() { + let tokens = tokenAddresses.addresses let tokenList = [{ value: 'ETH', label: 'ETH', address: 'ETH' }] for (let i = 0; i < tokens.length; i++) { @@ -90,30 +93,15 @@ class CurrencyInputPanel extends Component { return tokenList.filter(({ address }) => !filteredTokens.includes(address)) } - onTokenSelect = address => { - this.setState({ - searchQuery: '', - isShowingModal: false - }) + function onTokenSelect(address) { + setSearchQuery('') + setIsShowingModal(false) - this.props.onCurrencySelected(address) + onCurrencySelected(address) } - renderTokenList() { - const tokens = this.createTokenList() - const { loadingExchange, searchQuery } = this.state - const { - t, - selectedTokens, - disableTokenSelect, - web3, - selectors, - account, - factoryAddress, - exchangeAddresses: { fromToken }, - addExchange, - history - } = this.props + function renderTokenList() { + const tokens = createTokenList() if (loadingExchange) { return ( @@ -124,21 +112,24 @@ class CurrencyInputPanel extends Component { ) } - if (web3 && web3.utils && web3.utils.isAddress(searchQuery)) { + if (isAddress(searchQuery)) { const tokenAddress = searchQuery - const { label } = selectors().getBalance(account, tokenAddress) - const factory = new web3.eth.Contract(FACTORY_ABI, factoryAddress) const exchangeAddress = fromToken[tokenAddress] if (!exchangeAddress) { - this.setState({ loadingExchange: true }) - factory.methods.getExchange(tokenAddress).call((err, data) => { - if (!err && data !== '0x0000000000000000000000000000000000000000') { - addExchange({ label, tokenAddress, exchangeAddress: data }) + setLoadingExchange(true) + + getExchangeDetails(context.networkId, tokenAddress, signerOrProvider).then(async ({ exchangeAddress }) => { + if (exchangeAddress !== ethers.constants.AddressZero) { + const { symbol } = await getTokenDetails(tokenAddress, signerOrProvider) + addExchange({ + tokenAddress, + label: symbol, + exchangeAddress + }) } - this.setState({ loadingExchange: false }) + setLoadingExchange(false) }) - return } } @@ -152,10 +143,10 @@ class CurrencyInputPanel extends Component { results = tokens } else { const fuse = new Fuse(tokens, FUSE_OPTIONS) - results = fuse.search(this.state.searchQuery) + results = fuse.search(searchQuery) } - if (!results.length && web3 && web3.utils && web3.utils.isAddress(searchQuery)) { + if (!results.length && web3 && web3.utils && isAddress(searchQuery)) { const { label } = selectors().getBalance(account, searchQuery) return [
@@ -165,7 +156,7 @@ class CurrencyInputPanel extends Component { key="token-modal-create-exchange" className="token-modal__token-row token-modal__token-row--create-exchange" onClick={() => { - this.setState({ isShowingModal: false }) + setIsShowingModal(false) history.push(`/create-exchange/${searchQuery}`) }} > @@ -191,7 +182,7 @@ class CurrencyInputPanel extends Component { className={classnames('token-modal__token-row', { 'token-modal__token-row--selected': isSelected })} - onClick={() => this.onTokenSelect(address)} + onClick={() => onTokenSelect(address)} >
{label}
@@ -200,13 +191,18 @@ class CurrencyInputPanel extends Component { }) } - renderModal() { - if (!this.state.isShowingModal) { + function renderModal() { + if (!isShowingModal) { return null } return ( - this.setState({ isShowingModal: false, searchQuery: '' })}> + { + setIsShowingModal(false) + setSearchQuery('') + }} + >
{ - this.setState({ searchQuery: e.target.value }) + setSearchQuery(e.target.value) }} /> search
-
{this.renderTokenList()}
+
{renderTokenList()}
) } - renderUnlockButton() { - const { - t, - selectors, - selectedTokenAddress, - account, - exchangeAddresses: { fromToken }, - web3, - disableUnlock, - transactions, - pendingApprovals, - value, - addApprovalTx, - addPendingTx - } = this.props - + function renderUnlockButton() { if (disableUnlock || !selectedTokenAddress || selectedTokenAddress === 'ETH') { return } @@ -294,9 +276,7 @@ class CurrencyInputPanel extends Component { ) } - renderInput() { - const { t, errorMessage, value, onValueChange, selectedTokenAddress, disableTokenSelect, renderInput } = this.props - + function _renderInput() { if (typeof renderInput === 'function') { return renderInput() } @@ -322,7 +302,7 @@ class CurrencyInputPanel extends Component { }} value={value} /> - {this.renderUnlockButton()} + {renderUnlockButton()} +
-
- ] + + ) } } +function AddLiquidityButton({ callOnClick, isValid }) { + const { t } = useTranslation() + const context = useWeb3Context() + + const isActive = context.active && context.account + return ( + + ) +} + export default connect( state => ({ - isConnected: - Boolean(state.web3connect.account) && state.web3connect.networkId === (process.env.REACT_APP_NETWORK_ID || 1), account: state.web3connect.account, balances: state.web3connect.balances, web3: state.web3connect.web3, diff --git a/src/pages/Pool/CreateExchange.js b/src/pages/Pool/CreateExchange.js index 6ec9dc0798a..f9b72dfab74 100644 --- a/src/pages/Pool/CreateExchange.js +++ b/src/pages/Pool/CreateExchange.js @@ -1,243 +1,158 @@ -import React, { Component } from 'react' +import React, { useState, useEffect } from 'react' import { connect } from 'react-redux' -import PropTypes from 'prop-types' -import { withRouter } from 'react-router-dom' -import { withTranslation } from 'react-i18next' -import { selectors, addPendingTx } from '../../ducks/web3connect' +import { ethers } from 'ethers' import classnames from 'classnames' -import NavigationTabs from '../../components/NavigationTabs' -import ModeSelector from './ModeSelector' +import { withRouter } from 'react-router' +import { useTranslation } from 'react-i18next' +import ReactGA from 'react-ga' +import { useWeb3Context } from 'web3-react' + +import { addPendingTx } from '../../ducks/web3connect' import AddressInputPanel from '../../components/AddressInputPanel' import OversizedPanel from '../../components/OversizedPanel' -import FACTORY_ABI from '../../abi/factory' import { addExchange } from '../../ducks/addresses' -import ReactGA from 'react-ga' - -class CreateExchange extends Component { - static propTypes = { - web3: PropTypes.object, - selectors: PropTypes.func.isRequired, - addExchange: PropTypes.func.isRequired, - account: PropTypes.string, - isConnected: PropTypes.bool.isRequired, - factoryAddress: PropTypes.string.isRequired, - exchangeAddresses: PropTypes.shape({ - fromToken: PropTypes.object.isRequired - }).isRequired - } - - constructor(props) { - super(props) - const { - match: { - params: { tokenAddress } - } - } = this.props - - this.state = { - tokenAddress, - label: '', - decimals: 0 +import { useSignerOrProvider, useFactoryContract } from '../../hooks' +import { isAddress, getTokenDetails, getExchangeDetails, errorCodes } from '../../utils' + +function CreateExchange({ history, location, addExchange, addPendingTx }) { + const { t } = useTranslation() + const context = useWeb3Context() + const signerOrProvider = useSignerOrProvider() + const factory = useFactoryContract() + + const [tokenAddress, setTokenAddress] = useState(location.state && location.state.tokenAddress) + const [errorMessage, _setErrorMessage] = useState(context.account ? undefined : t('noWallet')) + const [tokenDetails, setTokenDetails] = useState() + + // wrap _setErrorMessage to ensure an account is in context + function setErrorMessage(value) { + if (value) { + _setErrorMessage(value) + } else if (!context.account) { + _setErrorMessage(t('noWallet')) + } else { + _setErrorMessage() } } - validate() { - const { tokenAddress } = this.state - const { - t, - web3, - account, - selectors, - factoryAddress, - exchangeAddresses: { fromToken }, - addExchange - } = this.props - - let isValid = true - let errorMessage = '' - - if (!tokenAddress) { - return { - isValid: false - } - } - - if (web3 && web3.utils && !web3.utils.isAddress(tokenAddress)) { - return { - isValid: false, - errorMessage: t('invalidTokenAddress') - } + // clear state, if it exists + useEffect(() => { + if (location.state) { + history.replace(location.pathname) } - - const { label, decimals } = selectors().getBalance(account, tokenAddress) - const factory = new web3.eth.Contract(FACTORY_ABI, factoryAddress) - const exchangeAddress = fromToken[tokenAddress] - - if (!exchangeAddress) { - factory.methods.getExchange(tokenAddress).call((err, data) => { - if (!err && data !== '0x0000000000000000000000000000000000000000') { - addExchange({ label, tokenAddress, exchangeAddress: data }) - } - }) - } else { - errorMessage = t('exchangeExists', { label }) + }, []) + + // handle changes to tokenAddress + useEffect(() => { + let stale = false + + // happy path + if (isAddress(tokenAddress)) { + const tokenDetailsPromise = getTokenDetails(tokenAddress, signerOrProvider) + const exchangeDetailsPromise = getExchangeDetails(context.networkId, tokenAddress, signerOrProvider) + + Promise.all([tokenDetailsPromise, exchangeDetailsPromise]) + .then(([tokenDetails, exchangeDetails]) => { + if (!stale) { + if (exchangeDetails.exchangeAddress !== ethers.constants.AddressZero) { + addExchange({ + tokenAddress, + label: tokenDetails.symbol, + exchangeAddress: exchangeDetails.exchangeAddress + }) + setErrorMessage(t('exchangeExists', { tokenAddress })) + } + setTokenDetails(tokenDetails) + } + }) + .catch(error => { + if (!stale) { + if (error.code === errorCodes.TOKEN_DETAILS_DECIMALS) { + setErrorMessage(t('invalidDecimals')) + } else if (error.code === errorCodes.TOKEN_DETAILS_SYMBOL) { + setErrorMessage(t('invalidSymbol')) + } else { + setErrorMessage(t('invalidTokenAddress')) + } + } + }) } - - if (!label) { - errorMessage = t('invalidSymbol') + // is tokenAddress is empty, there's no error + else if (tokenAddress === undefined || tokenAddress === '') { + setErrorMessage() } - - if (!decimals) { - errorMessage = t('invalidDecimals') + // tokenAddress is not a proper address + else { + setErrorMessage(t('invalidTokenAddress')) } - return { - isValid: isValid && !errorMessage, - errorMessage + return () => { + stale = true + setErrorMessage() + setTokenDetails() } - } - - onChange = tokenAddress => { - const { selectors, account, web3 } = this.props - if (web3 && web3.utils && web3.utils.isAddress(tokenAddress)) { - const { label, decimals } = selectors().getBalance(account, tokenAddress) - this.setState({ - label, - decimals, - tokenAddress - }) - } else { - this.setState({ - label: '', - decimals: 0, - tokenAddress + }, [tokenAddress, signerOrProvider, context.networkId]) + + async function createExchange() { + const estimatedGasLimit = await factory.estimate.createExchange(tokenAddress) + + factory.createExchange(tokenAddress, { gasLimit: estimatedGasLimit }).then(details => { + addPendingTx(details.hash) + setErrorMessage() + setTokenAddress() + ReactGA.event({ + category: 'Pool', + action: 'CreateExchange' }) - } - } - - onCreateExchange = () => { - const { tokenAddress } = this.state - const { account, web3, factoryAddress } = this.props - - if (web3 && web3.utils && !web3.utils.isAddress(tokenAddress)) { - return - } - - const factory = new web3.eth.Contract(FACTORY_ABI, factoryAddress) - factory.methods.createExchange(tokenAddress).send({ from: account }, (err, data) => { - if (!err) { - this.setState({ - label: '', - decimals: 0, - tokenAddress: '' - }) - this.props.addPendingTx(data) - ReactGA.event({ - category: 'Pool', - action: 'CreateExchange' - }) - } }) } - renderSummary() { - const { tokenAddress } = this.state - const { errorMessage } = this.validate() - - if (!tokenAddress) { - return ( -
-
{this.props.t('enterTokenCont')}
-
- ) - } - - if (errorMessage) { - return ( -
-
{errorMessage}
+ const isValid = isAddress(tokenAddress) && !errorMessage && tokenDetails && tokenDetails.tokenAddress === tokenAddress + + return ( + <> + setTokenAddress(input)} + errorMessage={errorMessage === t('noWallet') ? '' : errorMessage} + /> + +
+
+ {t('symbol')} + {tokenDetails ? tokenDetails.symbol : ' - '} +
+
+ {t('decimals')} + {tokenDetails ? tokenDetails.decimals : ' - '} +
- ) - } - - return null - } - - render() { - const { tokenAddress } = this.state - const { t, isConnected, account, selectors, web3 } = this.props - const { isValid, errorMessage } = this.validate() - let label, decimals - - if (web3 && web3.utils && web3.utils.isAddress(tokenAddress)) { - const { label: _label, decimals: _decimals } = selectors().getBalance(account, tokenAddress) - label = _label - decimals = _decimals - } - - return ( -
- +
+
- - - -
-
- {t('label')} - {label || ' - '} -
-
- {t('decimals')} - {decimals || ' - '} -
-
-
- {this.renderSummary()} -
- + > + {!!errorMessage ? errorMessage : t('enterTokenCont')}
- ) - } +
+ +
+ + ) } export default withRouter( connect( - state => ({ - isConnected: - Boolean(state.web3connect.account) && state.web3connect.networkId === (process.env.REACT_APP_NETWORK_ID || 1), - account: state.web3connect.account, - balances: state.web3connect.balances, - web3: state.web3connect.web3, - exchangeAddresses: state.addresses.exchangeAddresses, - factoryAddress: state.addresses.factoryAddress - }), + undefined, dispatch => ({ - selectors: () => dispatch(selectors()), addExchange: opts => dispatch(addExchange(opts)), addPendingTx: id => dispatch(addPendingTx(id)) }) - )(withTranslation()(CreateExchange)) + )(CreateExchange) ) diff --git a/src/pages/Pool/ModeSelector.js b/src/pages/Pool/ModeSelector.js index b16b5eb2eec..de232a7c5b5 100644 --- a/src/pages/Pool/ModeSelector.js +++ b/src/pages/Pool/ModeSelector.js @@ -1,83 +1,103 @@ -import React, { Component } from 'react' -import { withRouter } from 'react-router-dom' -import { withTranslation } from 'react-i18next' +import React, { useState, useCallback } from 'react' +import { withRouter, NavLink } from 'react-router-dom' +import { useTranslation } from 'react-i18next' +import { CSSTransitionGroup } from 'react-transition-group' + import OversizedPanel from '../../components/OversizedPanel' import Dropdown from '../../assets/images/dropdown-blue.svg' import Modal from '../../components/Modal' -import { CSSTransitionGroup } from 'react-transition-group' +import { useBodyKeyDown } from '../../hooks' -const ADD = 'Add Liquidity' -const REMOVE = 'Remove Liquidity' -const CREATE = 'Create Exchange' +import './pool.scss' -class ModeSelector extends Component { - state = { - isShowingModal: false, - selected: ADD +const poolTabOrder = [ + { + path: '/add-liquidity', + textKey: 'addLiquidity', + regex: /\/add-liquidity/ + }, + { + path: '/remove-liquidity', + textKey: 'removeLiquidity', + regex: /\/remove-liquidity/ + }, + { + path: '/create-exchange', + textKey: 'createExchange', + regex: /\/create-exchange.*/ } +] - changeView(view) { - const { history } = this.props +function ModeSelector({ location: { pathname }, history }) { + const { t } = useTranslation() - this.setState({ - isShowingModal: false, - selected: view - }) + const [isShowingModal, setIsShowingModal] = useState(false) - switch (view) { - case ADD: - return history.push('/add-liquidity') - case REMOVE: - return history.push('/remove-liquidity') - case CREATE: - return history.push('/create-exchange') - default: - return - } - } + const activeTabKey = poolTabOrder[poolTabOrder.findIndex(({ regex }) => pathname.match(regex))].textKey + + const navigate = useCallback( + direction => { + const tabIndex = poolTabOrder.findIndex(({ regex }) => pathname.match(regex)) + history.push(poolTabOrder[(tabIndex + poolTabOrder.length + direction) % poolTabOrder.length].path) + }, + [pathname, history] + ) + const navigateRight = useCallback(() => { + navigate(1) + }, [navigate]) + const navigateLeft = useCallback(() => { + navigate(-1) + }, [navigate]) - renderModal() { - if (!this.state.isShowingModal) { - return - } + useBodyKeyDown('ArrowDown', navigateRight, isShowingModal) + useBodyKeyDown('ArrowUp', navigateLeft, isShowingModal) - return ( - this.setState({ isShowingModal: false })}> - +
{ + setIsShowingModal(true) + }} + > + {t(activeTabKey)} + dropdown +
+ {isShowingModal && ( + { + setIsShowingModal(false) + }} > -
-
this.changeView(ADD)}> - {this.props.t('addLiquidity')} + +
+ {poolTabOrder.map(({ path, textKey, regex }) => ( + pathname.match(regex)} + onClick={() => { + setIsShowingModal(false) + }} + > + {t(textKey)} + + ))}
-
this.changeView(REMOVE)}> - {this.props.t('removeLiquidity')} -
-
this.changeView(CREATE)}> - {this.props.t('createExchange')} -
-
- - - ) - } - - render() { - return ( - -
this.setState({ isShowingModal: true })}> - {this.props.title} - dropdown -
- {this.renderModal()} -
- ) - } + + + )} + + ) } -export default withRouter(withTranslation()(ModeSelector)) +export default withRouter(ModeSelector) diff --git a/src/pages/Pool/RemoveLiquidity.js b/src/pages/Pool/RemoveLiquidity.js index 95b1d73a679..db4c901cd8e 100644 --- a/src/pages/Pool/RemoveLiquidity.js +++ b/src/pages/Pool/RemoveLiquidity.js @@ -3,9 +3,10 @@ import PropTypes from 'prop-types' import classnames from 'classnames' import { connect } from 'react-redux' import { BigNumber as BN } from 'bignumber.js' -import { withTranslation } from 'react-i18next' -import NavigationTabs from '../../components/NavigationTabs' -import ModeSelector from './ModeSelector' +import { withTranslation, useTranslation } from 'react-i18next' +import ReactGA from 'react-ga' +import { useWeb3Context } from 'web3-react' + import CurrencyInputPanel from '../../components/CurrencyInputPanel' import { selectors, addPendingTx } from '../../ducks/web3connect' import ContextualInfo from '../../components/ContextualInfo' @@ -15,7 +16,6 @@ import ArrowDownGrey from '../../assets/images/arrow-down-grey.svg' import { getBlockDeadline } from '../../helpers/web3-utils' import { retry } from '../../helpers/promise-utils' import EXCHANGE_ABI from '../../abi/exchange' -import ReactGA from 'react-ga' class RemoveLiquidity extends Component { static propTypes = { @@ -173,6 +173,7 @@ class RemoveLiquidity extends Component { renderSummary(errorMessage) { const { t, + account, selectors, exchangeAddresses: { fromToken } } = this.props @@ -181,7 +182,10 @@ class RemoveLiquidity extends Component { let contextualInfo = '' let isError = false - if (errorMessage) { + if (!account) { + contextualInfo = t('noWallet') + isError = true + } else if (errorMessage) { contextualInfo = errorMessage isError = true } else if (!tokenAddress) { @@ -366,23 +370,12 @@ class RemoveLiquidity extends Component { } render() { - const { t, isConnected } = this.props + const { t } = this.props const { tokenAddress, value } = this.state const { isValid, errorMessage } = this.validate() - return [ -
- - + return ( + <> - +
-
- ] + + ) } } +function RemoveLiquidityButton({ callOnClick, isValid }) { + const { t } = useTranslation() + const context = useWeb3Context() + + const isActive = context.active && context.account + return ( + + ) +} + export default connect( state => ({ - isConnected: - Boolean(state.web3connect.account) && state.web3connect.networkId === (process.env.REACT_APP_NETWORK_ID || 1), web3: state.web3connect.web3, balances: state.web3connect.balances, account: state.web3connect.account, diff --git a/src/pages/Pool/index.js b/src/pages/Pool/index.js index d8288011a2b..031986d4701 100644 --- a/src/pages/Pool/index.js +++ b/src/pages/Pool/index.js @@ -1,31 +1,36 @@ -import React, { Component } from 'react' -import Header from '../../components/Header' +import React, { useEffect } from 'react' +import ReactGA from 'react-ga' +import { Switch, Route, Redirect } from 'react-router-dom' + +import ModeSelector from './ModeSelector' import AddLiquidity from './AddLiquidity' import CreateExchange from './CreateExchange' import RemoveLiquidity from './RemoveLiquidity' -import { Switch, Route } from 'react-router-dom' + import './pool.scss' -import MediaQuery from 'react-responsive' -import ReactGA from 'react-ga' -class Pool extends Component { - componentWillMount() { +export default function Pool() { + useEffect(() => { ReactGA.pageview(window.location.pathname + window.location.search) - } - render() { - return ( -
- -
- - - - - - -
- ) - } -} + }, []) -export default Pool + return ( + <> + + + + + + { + return ( + + ) + }} + /> + + + + ) +} diff --git a/src/pages/Pool/pool.scss b/src/pages/Pool/pool.scss index 9bae69dc745..22a2adeeae3 100644 --- a/src/pages/Pool/pool.scss +++ b/src/pages/Pool/pool.scss @@ -5,6 +5,13 @@ height: 100%; background-color: $white; + &__content { + padding: 1rem 0.75rem; + flex: 1 1 auto; + height: 0; + overflow-y: auto; + } + &__liquidity-container { @extend %row-nowrap; align-items: center; @@ -114,20 +121,22 @@ } &__item { + @extend %row-nowrap; padding: 1rem; + margin-left: 1rem; + margin-right: 1rem; font-size: 1rem; cursor: pointer; + text-decoration: none; + color: $dove-gray; + font-size: 1rem; - &:hover { - background-color: $concrete-gray; - - .token-modal__token-label { - color: $black; - } - } - - &:active { - background-color: darken($concrete-gray, 1); + &--selected { + background-color: $white; + border-radius: 3rem; + box-shadow: 0 0 0.5px 0.5px $mercury-gray; + font-weight: 500; + color: $royal-blue; } } } diff --git a/src/pages/Send/index.js b/src/pages/Send/index.js index 016f934d075..a5b6faf1694 100644 --- a/src/pages/Send/index.js +++ b/src/pages/Send/index.js @@ -3,10 +3,11 @@ import { connect } from 'react-redux' import PropTypes from 'prop-types' import classnames from 'classnames' import { BigNumber as BN } from 'bignumber.js' -import { withTranslation } from 'react-i18next' +import { withTranslation, useTranslation } from 'react-i18next' +import ReactGA from 'react-ga' +import { useWeb3Context } from 'web3-react' + import { selectors, addPendingTx } from '../../ducks/web3connect' -import Header from '../../components/Header' -import NavigationTabs from '../../components/NavigationTabs' import AddressInputPanel from '../../components/AddressInputPanel' import CurrencyInputPanel from '../../components/CurrencyInputPanel' import ContextualInfo from '../../components/ContextualInfo' @@ -18,8 +19,6 @@ import { retry } from '../../helpers/promise-utils' import EXCHANGE_ABI from '../../abi/exchange' import './send.scss' -import MediaQuery from 'react-responsive' -import ReactGA from 'react-ga' const INPUT = 0 const OUTPUT = 1 @@ -27,7 +26,6 @@ const OUTPUT = 1 class Send extends Component { static propTypes = { account: PropTypes.string, - isConnected: PropTypes.bool.isRequired, selectors: PropTypes.func.isRequired, web3: PropTypes.object.isRequired } @@ -583,7 +581,10 @@ class Send extends Component { let contextualInfo = '' let isError = false - if (inputError || outputError) { + if (!account) { + contextualInfo = t('noWallet') + isError = true + } else if (inputError || outputError) { contextualInfo = inputError || outputError isError = true } else if (!inputCurrency || !outputCurrency) { @@ -751,87 +752,81 @@ class Send extends Component { const { inputError, outputError, isValid } = this.validate() return ( -
- -
- -
- - - this.setState({ inputCurrency }, this.recalcForm)} - onValueChange={this.updateInput} - selectedTokens={[inputCurrency, outputCurrency]} - selectedTokenAddress={inputCurrency} - value={inputValue} - errorMessage={inputError} - /> - -
- arrow -
-
- this.setState({ outputCurrency }, this.recalcForm)} - onValueChange={this.updateOutput} - selectedTokens={[inputCurrency, outputCurrency]} - value={outputValue} - selectedTokenAddress={outputCurrency} - errorMessage={outputError} - disableUnlock - /> - -
- arrow -
-
- this.setState({ recipient: address })} - /> - {this.renderExchangeRate()} - {this.renderSummary(inputError, outputError)} -
- + <> + this.setState({ inputCurrency }, this.recalcForm)} + onValueChange={this.updateInput} + selectedTokens={[inputCurrency, outputCurrency]} + selectedTokenAddress={inputCurrency} + value={inputValue} + errorMessage={inputError} + /> + +
+ arrow
+
+ this.setState({ outputCurrency }, this.recalcForm)} + onValueChange={this.updateOutput} + selectedTokens={[inputCurrency, outputCurrency]} + value={outputValue} + selectedTokenAddress={outputCurrency} + errorMessage={outputError} + disableUnlock + /> + +
+ arrow +
+
+ this.setState({ recipient: address })} + /> + {this.renderExchangeRate()} + {this.renderSummary(inputError, outputError)} +
+
-
+ ) } } +function SendButton({ callOnClick, isValid }) { + const { t } = useTranslation() + const context = useWeb3Context() + + const isActive = context.active && context.account + return ( + + ) +} + export default connect( state => ({ balances: state.web3connect.balances, - isConnected: !!state.web3connect.account && state.web3connect.networkId === (process.env.REACT_APP_NETWORK_ID || 1), account: state.web3connect.account, web3: state.web3connect.web3, exchangeAddresses: state.addresses.exchangeAddresses diff --git a/src/pages/Swap/index.js b/src/pages/Swap/index.js index ac5b7dc5920..4d4c272d9fd 100644 --- a/src/pages/Swap/index.js +++ b/src/pages/Swap/index.js @@ -3,12 +3,11 @@ import { connect } from 'react-redux' import PropTypes from 'prop-types' import classnames from 'classnames' import { BigNumber as BN } from 'bignumber.js' -import MediaQuery from 'react-responsive' import ReactGA from 'react-ga' -import { withTranslation } from 'react-i18next' +import { withTranslation, useTranslation } from 'react-i18next' +import { useWeb3Context } from 'web3-react' + import { selectors, addPendingTx } from '../../ducks/web3connect' -import Header from '../../components/Header' -import NavigationTabs from '../../components/NavigationTabs' import CurrencyInputPanel from '../../components/CurrencyInputPanel' import ContextualInfo from '../../components/ContextualInfo' import OversizedPanel from '../../components/OversizedPanel' @@ -26,7 +25,6 @@ const OUTPUT = 1 class Swap extends Component { static propTypes = { account: PropTypes.string, - isConnected: PropTypes.bool.isRequired, selectors: PropTypes.func.isRequired, addPendingTx: PropTypes.func.isRequired, web3: PropTypes.object.isRequired @@ -554,7 +552,7 @@ class Swap extends Component { renderSummary(inputError, outputError) { const { inputValue, inputCurrency, outputValue, outputCurrency } = this.state - const t = this.props.t + const { t, account } = this.props const inputIsZero = BN(inputValue).isZero() const outputIsZero = BN(outputValue).isZero() @@ -582,6 +580,11 @@ class Swap extends Component { contextualInfo = t('unlockTokenCont') } + if (!account) { + contextualInfo = t('noWallet') + isError = true + } + return ( - -
- -
- - - this.setState({ inputCurrency }, this.recalcForm)} - onValueChange={this.updateInput} - selectedTokens={[inputCurrency, outputCurrency]} - selectedTokenAddress={inputCurrency} - value={inputValue} - errorMessage={inputError} - /> - -
- swap -
-
- this.setState({ outputCurrency }, this.recalcForm)} - onValueChange={this.updateOutput} - selectedTokens={[inputCurrency, outputCurrency]} - value={outputValue} - selectedTokenAddress={outputCurrency} - errorMessage={outputError} - disableUnlock - /> - {this.renderExchangeRate()} - {this.renderSummary(inputError, outputError)} -
- + <> + this.setState({ inputCurrency }, this.recalcForm)} + onValueChange={this.updateInput} + selectedTokens={[inputCurrency, outputCurrency]} + selectedTokenAddress={inputCurrency} + value={inputValue} + errorMessage={inputError} + /> + +
+ swap
+
+ this.setState({ outputCurrency }, this.recalcForm)} + onValueChange={this.updateOutput} + selectedTokens={[inputCurrency, outputCurrency]} + value={outputValue} + selectedTokenAddress={outputCurrency} + errorMessage={outputError} + disableUnlock + /> + {this.renderExchangeRate()} + {this.renderSummary(inputError, outputError)} +
+
-
+ ) } } +function SwapButton({ callOnClick, isValid }) { + const { t } = useTranslation() + const context = useWeb3Context() + + const isActive = context.active && context.account + + return ( + + ) +} + export default connect( state => ({ balances: state.web3connect.balances, - isConnected: !!state.web3connect.account && state.web3connect.networkId === (process.env.REACT_APP_NETWORK_ID || 1), account: state.web3connect.account, web3: state.web3connect.web3, exchangeAddresses: state.addresses.exchangeAddresses diff --git a/src/pages/Swap/swap.scss b/src/pages/Swap/swap.scss index fd74521a238..9931dd133b5 100644 --- a/src/pages/Swap/swap.scss +++ b/src/pages/Swap/swap.scss @@ -7,6 +7,7 @@ &--inactive { opacity: 0.5; + cursor: default; } &__content { diff --git a/src/utils/index.js b/src/utils/index.js new file mode 100644 index 00000000000..ab71b529b93 --- /dev/null +++ b/src/utils/index.js @@ -0,0 +1,71 @@ +import { ethers } from 'ethers' + +import FACTORY_ABI from '../abi/factory' +import ERC20_ABI from '../abi/erc20' +import ERC20_WITH_BYTES_ABI from '../abi/erc20_symbol_bytes32' + +const factoryAddresses = { + 1: '0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95', + 4: '0xf5D915570BC477f9B8D6C0E980aA81757A3AaC36' +} + +export const errorCodes = ['TOKEN_DETAILS_DECIMALS', 'TOKEN_DETAILS_SYMBOL'].reduce( + (accumulator, currentValue, currentIndex) => { + accumulator[currentValue] = currentIndex + return accumulator + }, + {} +) + +function getFactoryContract(networkId, signerOrProvider) { + return getContract(factoryAddresses[networkId], FACTORY_ABI, signerOrProvider) +} + +export function isAddress(value) { + try { + ethers.utils.getAddress(value) + return true + } catch { + return false + } +} + +export function getSignerOrProvider(library, account) { + return account ? library.getSigner(account) : library +} + +export function getContract(contractAddress, ABI, signerOrProvider) { + return new ethers.Contract(contractAddress, ABI, signerOrProvider) +} + +export async function getTokenDetails(tokenAddress, signerOrProvider) { + const contract = getContract(tokenAddress, ERC20_ABI, signerOrProvider) + + const decimalsPromise = contract.decimals().catch(error => { + console.log(error) + error.code = errorCodes.TOKEN_DETAILS_DECIMALS + throw error + }) + const symbolPromise = contract + .symbol() + .catch(() => { + const contractBytes32 = getContract(tokenAddress, ERC20_WITH_BYTES_ABI, signerOrProvider) + return contractBytes32.symbol().then(bytes32 => ethers.utils.parseBytes32String(bytes32)) + }) + .catch(error => { + error.code = errorCodes.TOKEN_DETAILS_SYMBOL + throw error + }) + + return Promise.all([decimalsPromise, symbolPromise]).then(([decimals, symbol]) => ({ + decimals, + symbol, + tokenAddress + })) +} + +export async function getExchangeDetails(networkId, tokenAddress, signerOrProvider) { + const factoryContract = getFactoryContract(networkId, signerOrProvider) + + return factoryContract.getExchange(tokenAddress).then(exchangeAddress => ({ exchangeAddress, tokenAddress })) +} diff --git a/yarn.lock b/yarn.lock index 59659340fae..f7c577189da 100644 --- a/yarn.lock +++ b/yarn.lock @@ -871,7 +871,7 @@ js-levenshtein "^1.1.3" semver "^5.3.0" -"@babel/preset-env@^7.1.6", "@babel/preset-env@^7.3.4": +"@babel/preset-env@^7.1.6": version "7.4.3" resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.4.3.tgz#e71e16e123dc0fbf65a52cbcbcefd072fbd02880" integrity sha512-FYbZdV12yHdJU5Z70cEg0f6lvtpZ8jFSDakTm7WXeJbLXh4R0ztGEu/SW7G1nJ2ZvKwDhz8YrbA84eYyprmGqw== @@ -951,13 +951,6 @@ dependencies: regenerator-runtime "^0.12.0" -"@babel/runtime@7.3.4": - version "7.3.4" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.3.4.tgz#73d12ba819e365fcf7fd152aed56d6df97d21c83" - integrity sha512-IvfvnMdSaLBateu0jfsYIpZTxAc2cKEXEMiezGGN75QcBcecDUKd3PgLAncT0oOgxKy8dd8hrJKj9MfzgfZd6g== - dependencies: - regenerator-runtime "^0.12.0" - "@babel/runtime@^7.1.2", "@babel/runtime@^7.3.1": version "7.4.3" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.3.tgz#79888e452034223ad9609187a0ad1fe0d2ad4bdc" @@ -1064,43 +1057,6 @@ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== -"@portis/web3-provider-engine@1.0.9": - version "1.0.9" - resolved "https://registry.yarnpkg.com/@portis/web3-provider-engine/-/web3-provider-engine-1.0.9.tgz#2d2f6e4d3701f0003308a1071bd8b9de4cca6ba5" - integrity sha512-0N9uhKKGUBWKU96KlbOkQSz6WYXI46QP5oubxffFGdxKUBiRU2IPrRkQA2d0zoERLMgtT4OlGvog1pxLpjzLfg== - dependencies: - async "^2.5.0" - backoff "^2.5.0" - clone "^2.0.0" - cross-fetch "^2.1.0" - eth-block-tracker "^4.2.0" - eth-json-rpc-filters "^4.0.2" - eth-json-rpc-infura "^3.1.0" - eth-json-rpc-middleware "github:radotzki/eth-json-rpc-middleware#patch-1" - eth-sig-util "^1.4.2" - ethereumjs-block "^1.2.2" - ethereumjs-tx "^1.2.0" - ethereumjs-util "^5.1.5" - ethereumjs-vm "^2.3.4" - json-rpc-error "^2.0.0" - json-stable-stringify "^1.0.1" - promise-to-callback "^1.0.0" - readable-stream "^2.2.9" - request "^2.85.0" - semaphore "^1.0.3" - ws "^5.1.1" - xhr "^2.2.0" - xtend "^4.0.1" - -"@portis/web3@^2.0.0-beta.23": - version "2.0.0-beta.23" - resolved "https://registry.yarnpkg.com/@portis/web3/-/web3-2.0.0-beta.23.tgz#873ef9c47405cbc7cffd0bbb58d5a887095a3410" - integrity sha512-rf1MkUvG9rtRdC/jNENit74X02ZtSClcC6/2dnyiNZHlufBAF+G5KUXVgrKZRDQSL/lGUCJL7dZYssltqDhXMg== - dependencies: - "@portis/web3-provider-engine" "1.0.9" - ethereumjs-util "5.2.0" - penpal "3.0.7" - "@svgr/babel-plugin-add-jsx-attribute@^4.2.0": version "4.2.0" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-4.2.0.tgz#dadcb6218503532d6884b210e7f3c502caaa44b1" @@ -1296,55 +1252,6 @@ dependencies: "@types/ethereum-protocol" "*" -"@walletconnect/browser@^1.0.0-beta.11": - version "1.0.0-beta.11" - resolved "https://registry.yarnpkg.com/@walletconnect/browser/-/browser-1.0.0-beta.11.tgz#ca826e5c5253e59b492cb406b8eecc45bb33279e" - integrity sha512-JTpUvMOBF6G1D46AJIOJRhsRvDZ9GpOJIcOg5jXv95oExtCRqjlVhoEx/i4KiYrIudaFg4+gzI3uhL829aCqjA== - dependencies: - "@walletconnect/core" "^1.0.0-beta.11" - "@walletconnect/types" "^1.0.0-beta.10" - "@walletconnect/utils" "^1.0.0-beta.11" - -"@walletconnect/core@^1.0.0-beta.11": - version "1.0.0-beta.11" - resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-1.0.0-beta.11.tgz#d83b17488cf0f3fff6818009d705081963ad9fbd" - integrity sha512-Lh51x4J9yXTS87C0YtNigVRo+3XggStSTH0VlJrwW7l7XFkBJwDCzYwwKyM5h7w91WGlrn6tSjnJl6nE4V2W/w== - dependencies: - "@walletconnect/types" "^1.0.0-beta.10" - "@walletconnect/utils" "^1.0.0-beta.11" - -"@walletconnect/qrcode-modal@^1.0.0-beta.11": - version "1.0.0-beta.11" - resolved "https://registry.yarnpkg.com/@walletconnect/qrcode-modal/-/qrcode-modal-1.0.0-beta.11.tgz#0dd14b76a1897a95a55153c73697e1ae46860e3b" - integrity sha512-BbEv05Bp9n7pWoau1iwiyEggTujuFVKm+vC83aNPcsYNQ0uyxyRfhZkUhnIRg6ry1dsIqeyazBS/Q8/J8Q8PkQ== - dependencies: - "@walletconnect/types" "^1.0.0-beta.10" - qr-image "^3.2.0" - -"@walletconnect/types@^1.0.0-beta.10": - version "1.0.0-beta.11" - resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-1.0.0-beta.11.tgz#e9e751268c73945255484adcbddaabda4a81dab4" - integrity sha512-LgO/R5WGUIwbn9Euzwbx2tWC/XtlFVtRR3ulSldsl5wUA+y04XlAcHsirp2b3ebuaaOJGcAnfFdwK3Qa7k5K5g== - -"@walletconnect/utils@^1.0.0-beta.11": - version "1.0.0-beta.11" - resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-1.0.0-beta.11.tgz#25fadd17973086df8f10d625161c0c3cb1f61bc1" - integrity sha512-El+OVX4T+5xZcfCYunHECkPBcX6AKiuhwxzQ1ElQ9jnujEr6Z1+KP1DptLnAGMfvNKZ/dbJlqh8Y1K0wYV0hOQ== - dependencies: - "@walletconnect/types" "^1.0.0-beta.10" - lodash.isnumber "^3.0.3" - -"@walletconnect/web3-subprovider@^1.0.0-beta.10": - version "1.0.0-beta.11" - resolved "https://registry.yarnpkg.com/@walletconnect/web3-subprovider/-/web3-subprovider-1.0.0-beta.11.tgz#7d459e70cf0d8e6bca4cc4997d40c693228446e7" - integrity sha512-0mRe45WkNKdZAidkIJBe3T91U7YpDLwPlno5B5SzwJZIVgrfLT2eU94shVHEUFsfYSP4J7d+FWiGpe3PqLJdEw== - dependencies: - "@walletconnect/browser" "^1.0.0-beta.11" - "@walletconnect/qrcode-modal" "^1.0.0-beta.11" - "@walletconnect/types" "^1.0.0-beta.10" - "@walletconnect/utils" "^1.0.0-beta.11" - web3-provider-engine "github:walletconnect/web3-provider-engine" - "@webassemblyjs/ast@1.7.11": version "1.7.11" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.7.11.tgz#b988582cafbb2b095e8b556526f30c90d057cace" @@ -1922,11 +1829,6 @@ autoprefixer@^9.4.2: postcss "^7.0.14" postcss-value-parser "^3.3.1" -await-semaphore@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/await-semaphore/-/await-semaphore-0.1.3.tgz#2b88018cc8c28e06167ae1cdff02504f1f9688d3" - integrity sha512-d1W2aNSYcz/sxYO4pMGX9vq65qOTu0P800epMud+6cYYX0QcT7zyqcxec3VWzpgvdXo57UWmVbZpLMjX2m1I7Q== - aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" @@ -2578,11 +2480,6 @@ babel-types@^6.0.0, babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.24. lodash "^4.17.4" to-fast-properties "^1.0.3" -babelify@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/babelify/-/babelify-10.0.0.tgz#fe73b1a22583f06680d8d072e25a1e0d1d1d7fb5" - integrity sha512-X40FaxyH7t3X+JFAKvb1H9wooWKLRCi8pg3m8poqtdZaIng+bjzp9RvKQCvRjF9isHiPkXspbbXT/zwXLtwgwg== - babelify@^7.3.0: version "7.3.0" resolved "https://registry.yarnpkg.com/babelify/-/babelify-7.3.0.tgz#aa56aede7067fd7bd549666ee16dc285087e88e5" @@ -2959,7 +2856,7 @@ browserslist@^3.2.6: caniuse-lite "^1.0.30000844" electron-to-chromium "^1.3.47" -browserslist@^4.0.0, browserslist@^4.3.4, browserslist@^4.3.5, browserslist@^4.5.2, browserslist@^4.5.4: +browserslist@^4.0.0, browserslist@^4.3.4, browserslist@^4.5.2, browserslist@^4.5.4: version "4.5.4" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.5.4.tgz#166c4ecef3b51737a42436ea8002aeea466ea2c7" integrity sha512-rAjx494LMjqKnMPhFkuLmLp8JWEX0o8ADTGeAbOqaF+XCvYLreZrG5uVjnPBlAQ8REZK4pzXGvp0bWgrFtKaag== @@ -2968,6 +2865,15 @@ browserslist@^4.0.0, browserslist@^4.3.4, browserslist@^4.3.5, browserslist@^4.5 electron-to-chromium "^1.3.122" node-releases "^1.1.13" +browserslist@^4.3.5: + version "4.5.5" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.5.5.tgz#fe1a352330d2490d5735574c149a85bc18ef9b82" + integrity sha512-0QFO1r/2c792Ohkit5XI8Cm8pDtZxgNl2H6HU4mHrpYz7314pEYcsAVVatM0l/YmxPnEzh9VygXouj4gkFUTKA== + dependencies: + caniuse-lite "^1.0.30000960" + electron-to-chromium "^1.3.124" + node-releases "^1.1.14" + bs58@=4.0.1, bs58@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" @@ -2996,11 +2902,6 @@ bser@^2.0.0: dependencies: node-int64 "^0.4.0" -btoa@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/btoa/-/btoa-1.2.1.tgz#01a9909f8b2c93f6bf680ba26131eb30f7fa3d73" - integrity sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g== - buffer-alloc-unsafe@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" @@ -3209,11 +3110,16 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30000918, caniuse-lite@^1.0.30000929, caniuse-lite@^1.0.30000955, caniuse-lite@^1.0.30000957: +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30000955, caniuse-lite@^1.0.30000957: version "1.0.30000959" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000959.tgz#215d3455866da874179c6170202f0cc64f961cfd" integrity sha512-6BvqmS0VLmY4sJCz6AbIJRQfcns8McDxi424y+3kmtisJeA9/5qslP+K8sqremDau7UU4WSsqdRP032JrqZY8Q== +caniuse-lite@^1.0.30000918, caniuse-lite@^1.0.30000929, caniuse-lite@^1.0.30000960: + version "1.0.30000960" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000960.tgz#ec48297037e5607f582f246ae7b12bee66a78999" + integrity sha512-7nK5qs17icQaX6V3/RYrJkOsZyRNnroA4+ZwxaKJzIKy+crIy0Mz5CBlLySd2SNV+4nbUZeqeNfiaEieUBu3aA== + capture-exit@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-1.2.0.tgz#1c5fcc489fd0ab00d4f1ac7ae1072e3173fbab6f" @@ -3407,7 +3313,7 @@ clone-deep@^2.0.1: kind-of "^6.0.0" shallow-clone "^1.0.0" -clone@2.1.2, clone@^2.0.0, clone@^2.1.1: +clone@2.1.2, clone@^2.0.0: version "2.1.2" resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= @@ -3884,11 +3790,6 @@ css-loader@1.0.0: postcss-value-parser "^3.3.0" source-list-map "^2.0.0" -css-mediaquery@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/css-mediaquery/-/css-mediaquery-0.1.2.tgz#6a2c37344928618631c54bd33cedd301da18bea0" - integrity sha1-aiw3NEkoYYYxxUvTPO3TAdoYvqA= - css-prefers-color-scheme@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/css-prefers-color-scheme/-/css-prefers-color-scheme-3.1.1.tgz#6f830a2714199d4f0d0d0bb8a27916ed65cff1f4" @@ -4548,7 +4449,7 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= -electron-to-chromium@^1.3.103, electron-to-chromium@^1.3.122, electron-to-chromium@^1.3.47: +electron-to-chromium@^1.3.103, electron-to-chromium@^1.3.122, electron-to-chromium@^1.3.124, electron-to-chromium@^1.3.47: version "1.3.124" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.124.tgz#861fc0148748a11b3e5ccebdf8b795ff513fa11f" integrity sha512-glecGr/kFdfeXUHOHAWvGcXrxNU+1wSO/t5B23tT1dtlvYB26GY8aHzZSWD7HqhqC800Lr+w/hQul6C5AF542w== @@ -4929,15 +4830,6 @@ eth-block-tracker@^3.0.0: pify "^2.3.0" tape "^4.6.3" -eth-block-tracker@^4.2.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/eth-block-tracker/-/eth-block-tracker-4.3.0.tgz#9a54bb8241510367003d1f183adfac05abfe0e87" - integrity sha512-QbBsNaGFbpozqzUnjhaR6Skej0485tApPoKMWAW6qpR6J3kY2lgQv47vQvv0MjayxgWXnYH48sjTm2gNRS0NXA== - dependencies: - eth-query "^2.1.0" - pify "^3.0.0" - safe-event-emitter "^1.0.1" - eth-ens-namehash@2.0.8: version "2.0.8" resolved "https://registry.yarnpkg.com/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz#229ac46eca86d52e0c991e7cb2aef83ff0f68bcf" @@ -4946,18 +4838,6 @@ eth-ens-namehash@2.0.8: idna-uts46-hx "^2.3.1" js-sha3 "^0.5.7" -eth-json-rpc-filters@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/eth-json-rpc-filters/-/eth-json-rpc-filters-4.0.2.tgz#881ea459f3edd6b4f1889914f4d0e7d2deeb2032" - integrity sha512-936WGvom7gGMwVqqIdWyQZeXCk5i6yjAfd3oDcgfKG/jCNQnkB28qplviX2cEik/2onWvg8mpgy2D/eutv9xnw== - dependencies: - await-semaphore "^0.1.3" - eth-json-rpc-middleware "^4.0.0" - eth-query "^2.1.2" - json-rpc-engine "^5.0.0" - lodash.flatmap "^4.5.0" - safe-event-emitter "^1.0.1" - eth-json-rpc-infura@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/eth-json-rpc-infura/-/eth-json-rpc-infura-3.2.0.tgz#62c3f516b51351038c32a548704467cec113ca8f" @@ -4988,25 +4868,6 @@ eth-json-rpc-middleware@^1.5.0: promise-to-callback "^1.0.0" tape "^4.6.3" -eth-json-rpc-middleware@^4.0.0, eth-json-rpc-middleware@^4.1.1, "eth-json-rpc-middleware@github:radotzki/eth-json-rpc-middleware#patch-1": - version "4.1.2" - resolved "https://codeload.github.com/radotzki/eth-json-rpc-middleware/tar.gz/8acc43df4a8c0c7f6d212af9163d379211dad4c7" - dependencies: - btoa "^1.2.1" - clone "^2.1.1" - eth-query "^2.1.2" - eth-sig-util "^1.4.2" - ethereumjs-block "^1.6.0" - ethereumjs-tx "^1.3.3" - ethereumjs-util "^5.1.2" - ethereumjs-vm "2.2.2" - fetch-ponyfill "^4.0.0" - json-rpc-engine "^5.0.0" - json-rpc-error "^2.0.0" - json-stable-stringify "^1.0.1" - pify "^3.0.0" - safe-event-emitter "^1.0.1" - eth-lib@0.1.27, eth-lib@^0.1.26: version "0.1.27" resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.1.27.tgz#f0b0fd144f865d2d6bf8257a40004f2e75ca1dd6" @@ -5095,21 +4956,16 @@ eth-tx-summary@^3.1.2: ethereumjs-vm "^2.6.0" through2 "^2.0.3" -ethereum-common@0.0.18, ethereum-common@^0.0.18: - version "0.0.18" - resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.0.18.tgz#2fdc3576f232903358976eb39da783213ff9523f" - integrity sha1-L9w1dvIykDNYl26znaeDIT/5Uj8= - -ethereum-common@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.1.0.tgz#874dd0fae5e962a56c50ebf28efa6fe39492b0e7" - integrity sha1-h03Q+uXpYqVsUOvyjvpv45SSsOc= - ethereum-common@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.2.0.tgz#13bf966131cce1eeade62a1b434249bb4cb120ca" integrity sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA== +ethereum-common@^0.0.18: + version "0.0.18" + resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.0.18.tgz#2fdc3576f232903358976eb39da783213ff9523f" + integrity sha1-L9w1dvIykDNYl26znaeDIT/5Uj8= + ethereum-types@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ethereum-types/-/ethereum-types-2.1.2.tgz#7398873e0eede1dd0956a134e1037032f6ed3c14" @@ -5164,17 +5020,6 @@ ethereumjs-block@^1.2.2, ethereumjs-block@^1.4.1, ethereumjs-block@^1.6.0: ethereumjs-util "^5.0.0" merkle-patricia-tree "^2.1.2" -ethereumjs-block@~1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-1.6.0.tgz#cded4962deaca1eef17372b4d290e84b35c84372" - integrity sha1-ze1JYt6soe7xc3K00pDoSzXIQ3I= - dependencies: - async "^2.0.1" - ethereum-common "0.0.18" - ethereumjs-tx "^1.2.2" - ethereumjs-util "^5.0.0" - merkle-patricia-tree "^2.1.2" - ethereumjs-block@~2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-2.2.0.tgz#8c6c3ab4a5eff0a16d9785fbeedbe643f4dbcbef" @@ -5204,17 +5049,6 @@ ethereumjs-tx@1.3.7, ethereumjs-tx@^1.1.1, ethereumjs-tx@^1.2.0, ethereumjs-tx@^ ethereum-common "^0.0.18" ethereumjs-util "^5.0.0" -ethereumjs-util@4.5.0, ethereumjs-util@^4.3.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz#3e9428b317eebda3d7260d854fddda954b1f1bc6" - integrity sha1-PpQosxfuvaPXJg2FT93alUsfG8Y= - dependencies: - bn.js "^4.8.0" - create-hash "^1.1.2" - keccakjs "^0.2.0" - rlp "^2.0.0" - secp256k1 "^3.0.1" - ethereumjs-util@5.2.0, ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereumjs-util@^5.1.2, ethereumjs-util@^5.1.3, ethereumjs-util@^5.1.5, ethereumjs-util@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz#3e0c0d1741471acf1036052d048623dee54ad642" @@ -5228,6 +5062,17 @@ ethereumjs-util@5.2.0, ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumj safe-buffer "^5.1.1" secp256k1 "^3.0.1" +ethereumjs-util@^4.3.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz#3e9428b317eebda3d7260d854fddda954b1f1bc6" + integrity sha1-PpQosxfuvaPXJg2FT93alUsfG8Y= + dependencies: + bn.js "^4.8.0" + create-hash "^1.1.2" + keccakjs "^0.2.0" + rlp "^2.0.0" + secp256k1 "^3.0.1" + ethereumjs-util@^6.0.0: version "6.1.0" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.1.0.tgz#e9c51e5549e8ebd757a339cc00f5380507e799c8" @@ -5241,22 +5086,6 @@ ethereumjs-util@^6.0.0: safe-buffer "^5.1.1" secp256k1 "^3.0.1" -ethereumjs-vm@2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-2.2.2.tgz#786317d2c63e547d936c1a468607510e70b4c262" - integrity sha512-sAus9UxYjUnA42G91Q1/hR7ff35IJRpcLrUfbaIH7V4cl8qKsNs3wqf3dHvtj3wRqy12ke2Wd0tYdARyGKdD6g== - dependencies: - async "^2.1.2" - async-eventemitter "^0.2.2" - ethereum-common "0.1.0" - ethereumjs-account "^2.0.3" - ethereumjs-block "~1.6.0" - ethereumjs-util "4.5.0" - fake-merkle-patricia-tree "^1.0.1" - functional-red-black-tree "^1.0.1" - merkle-patricia-tree "^2.1.2" - safe-buffer "^5.1.1" - ethereumjs-vm@2.6.0, ethereumjs-vm@^2.1.0, ethereumjs-vm@^2.3.4, ethereumjs-vm@^2.6.0: version "2.6.0" resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-2.6.0.tgz#76243ed8de031b408793ac33907fb3407fe400c6" @@ -5861,13 +5690,6 @@ form-data@~2.3.2: combined-stream "^1.0.6" mime-types "^2.1.12" -fortmatic@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/fortmatic/-/fortmatic-0.7.0.tgz#978fa01e56a0fb1e5fb167c8fb366e8f100b57cd" - integrity sha512-ZLHy7g3z9jKkfba7Ow8H7ZR0IbKAG7wUy062BKBMGrDFqtM2ii7n4eMRYNWcqvsZXZ3E26CxXEqIFI81ibTdLw== - dependencies: - "@babel/runtime" "7.3.4" - forwarded@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" @@ -5964,7 +5786,15 @@ fsevents@1.2.4: nan "^2.9.2" node-pre-gyp "^0.10.0" -fsevents@^1.2.3, fsevents@^1.2.7: +fsevents@^1.2.3: + version "1.2.8" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.8.tgz#57ea5320f762cd4696e5e8e87120eccc8b11cacf" + integrity sha512-tPvHgPGB7m40CZ68xqFGkKuzN+RnpGmSV+hgeKxhRpbxdqKXUFJGC3yonBOLzQBcJyGpdZFDfCsdOC2KFsXzeA== + dependencies: + nan "^2.12.1" + node-pre-gyp "^0.12.0" + +fsevents@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.7.tgz#4851b664a3783e52003b3c66eb0eee1074933aa4" integrity sha512-Pxm6sI2MeBD7RdD12RYsqaP0nMiwx8eZBXCa6z2L+mRHm2DYrOYwihmhjpkdjUHwQhslWQjRpEgNq4XvBmaAuw== @@ -6650,11 +6480,6 @@ https-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= -hyphenate-style-name@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.3.tgz#097bb7fa0b8f1a9cf0bd5c734cf95899981a9b48" - integrity sha512-EcuixamT82oplpoJ2XU4pDtKGWQ7b00CD9f1ug9IaQ3p1bkHMiKCZ9ut9QDI6qsa6cpUuB+A/I+zLtdNK4n2DQ== - i18next-browser-languagedetector@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/i18next-browser-languagedetector/-/i18next-browser-languagedetector-3.0.1.tgz#a47c43176e8412c91e808afb7c6eb5367649aa8e" @@ -7877,17 +7702,6 @@ json-rpc-engine@^3.4.0, json-rpc-engine@^3.6.0: promise-to-callback "^1.0.0" safe-event-emitter "^1.0.1" -json-rpc-engine@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-5.0.0.tgz#f048a5402f602604595f820229b71e8431206490" - integrity sha512-bxzuHwoP/U7xBIcqxP9QaOMgW7GDbBNU2TLNWfndRfHxwPLKkGMBfgtns0oDvgjMPJLCgyFZjrnVuSHW5GSC7A== - dependencies: - "@babel/preset-env" "^7.3.4" - async "^2.0.1" - babelify "^10.0.0" - promise-to-callback "^1.0.0" - safe-event-emitter "^1.0.1" - json-rpc-error@2.0.0, json-rpc-error@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/json-rpc-error/-/json-rpc-error-2.0.0.tgz#a7af9c202838b5e905c7250e547f1aff77258a02" @@ -8298,16 +8112,6 @@ lodash.clonedeep@^4.3.2: resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= -lodash.flatmap@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.flatmap/-/lodash.flatmap-4.5.0.tgz#ef8cbf408f6e48268663345305c6acc0b778702e" - integrity sha1-74y/QI9uSCaGYzRTBcaswLd4cC4= - -lodash.isnumber@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" - integrity sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w= - lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" @@ -8486,13 +8290,6 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" -matchmediaquery@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/matchmediaquery/-/matchmediaquery-0.3.0.tgz#6f672bcdbc44de16825c6917fbcdcfb9b82607b1" - integrity sha512-u0dlv+VENJ+3YepvwSPBieuvnA6DWfaYa/ctwysAR13y4XLJNyt7bEVKzNj/Nvjo+50d88Pj+xL9xaSo6JmX/w== - dependencies: - css-mediaquery "^0.1.2" - math-random@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.4.tgz#5dd6943c938548267016d4e34f057583080c514c" @@ -9103,13 +8900,36 @@ node-pre-gyp@^0.11.0: semver "^5.3.0" tar "^4" -node-releases@^1.1.13, node-releases@^1.1.3: +node-pre-gyp@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149" + integrity sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A== + dependencies: + detect-libc "^1.0.2" + mkdirp "^0.5.1" + needle "^2.2.1" + nopt "^4.0.1" + npm-packlist "^1.1.6" + npmlog "^4.0.2" + rc "^1.2.7" + rimraf "^2.6.1" + semver "^5.3.0" + tar "^4" + +node-releases@^1.1.13: version "1.1.14" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.14.tgz#f1f41c83cac82caebd6739e6313d56b3b09c9189" integrity sha512-d58EpVZRhQE60kWiWUaaPlK9dyC4zg3ZoMcHcky2d4hDksyQj0rUozwInOl0C66mBsqo01Tuns8AvxnL5S7PKg== dependencies: semver "^5.3.0" +node-releases@^1.1.14, node-releases@^1.1.3: + version "1.1.15" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.15.tgz#9e76a73b0eca3bf7801addaa0e6ce90c795f2b9a" + integrity sha512-cKV097BQaZr8LTSRUa2+oc/aX5L8UkZtPQrMSTgiJEeaW7ymTDCoRaGCoaTqk0lqnalcoSHu4wjSl0Cmj2+bMw== + dependencies: + semver "^5.3.0" + node-sass@^4.11.0: version "4.11.0" resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.11.0.tgz#183faec398e9cbe93ba43362e2768ca988a6369a" @@ -9742,11 +9562,6 @@ pend@~1.2.0: resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= -penpal@3.0.7: - version "3.0.7" - resolved "https://registry.yarnpkg.com/penpal/-/penpal-3.0.7.tgz#d252711ed93b30f1d867eb82342785b3a95f5f75" - integrity sha512-WSXiq5HnEvzvY05SHhaXcsviUmCvh4Ze8AiIZzvmdzaaYAAx4rx8c6Xq6+MaVDG/Nfve3VmGD8HyRP3CkPvPbQ== - performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" @@ -10756,11 +10571,6 @@ q@^1.1.2: resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= -qr-image@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/qr-image/-/qr-image-3.2.0.tgz#9fa8295beae50c4a149cf9f909a1db464a8672e8" - integrity sha1-n6gpW+rlDEoUnPn5CaHbRkqGcug= - qs@6.5.2, qs@~6.5.2: version "6.5.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" @@ -10951,15 +10761,6 @@ react-redux@^5.0.7: react-is "^16.6.0" react-lifecycles-compat "^3.0.0" -react-responsive@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/react-responsive/-/react-responsive-5.0.0.tgz#b6e559b2ce8c4d82b0d47a7a78a74645b977e4af" - integrity sha512-oEimZ0FTCC3/pjGDEBHOz06nWbBNDIbMGOdRYp6K9SBUmrqgNAX77hTiqvmRQeLyI97zz4F4kiaFRxFspDxE+w== - dependencies: - hyphenate-style-name "^1.0.0" - matchmediaquery "^0.3.0" - prop-types "^15.6.1" - react-router-dom@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.0.0.tgz#542a9b86af269a37f0b87218c4c25ea8dcf0c073" @@ -12821,15 +12622,6 @@ tr46@^1.0.1: dependencies: punycode "^2.1.0" -trezor-connect@^7.0.2: - version "7.0.2" - resolved "https://registry.yarnpkg.com/trezor-connect/-/trezor-connect-7.0.2.tgz#8b1b0d1b3b6dc6564bc3d22fe8f54ba826f2a242" - integrity sha512-KAFOqxEHHaFvrG8NGLFlM/QxHcwIa3gwfXcgTjCYM0g0zRpwIQBwe35AKsjAQO5yiTJQGa0Cu5MZufGJRGYjjw== - dependencies: - "@babel/runtime" "^7.3.1" - events "^3.0.0" - whatwg-fetch "^3.0.0" - trim-newlines@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" @@ -13753,33 +13545,6 @@ web3-provider-engine@14.1.0: xhr "^2.2.0" xtend "^4.0.1" -"web3-provider-engine@github:walletconnect/web3-provider-engine": - version "15.0.0" - resolved "https://codeload.github.com/walletconnect/web3-provider-engine/tar.gz/48080be33018e8f24e4ba80ccb76787a33ed3e9b" - dependencies: - async "^2.5.0" - backoff "^2.5.0" - clone "^2.0.0" - cross-fetch "^2.1.0" - eth-block-tracker "^4.2.0" - eth-json-rpc-filters "^4.0.2" - eth-json-rpc-infura "^3.1.0" - eth-json-rpc-middleware "^4.1.1" - eth-sig-util "^1.4.2" - ethereumjs-block "^1.2.2" - ethereumjs-tx "^1.2.0" - ethereumjs-util "^5.1.5" - ethereumjs-vm "^2.3.4" - json-rpc-error "^2.0.0" - json-stable-stringify "^1.0.1" - promise-to-callback "^1.0.0" - readable-stream "^2.2.9" - request "^2.85.0" - semaphore "^1.0.3" - ws "^5.1.1" - xhr "^2.2.0" - xtend "^4.0.1" - web3-providers-http@1.0.0-beta.35: version "1.0.0-beta.35" resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.0.0-beta.35.tgz#92059d9d6de6e9f82f4fae30b743efd841afc1e1" @@ -13819,16 +13584,12 @@ web3-providers@1.0.0-beta.52: websocket "^1.0.28" xhr2-cookies "1.1.0" -web3-react@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/web3-react/-/web3-react-4.0.0.tgz#d364c96f0c3ac615129490efe3ad8526e415b022" - integrity sha512-lcUXlv1m+eO1nesMFH7faNpVpTTiWzB+9J3TNPjibndtlqRw91EzDLO4uS1LK053aYUIK1dWikANjyX6GM6f9w== +web3-react@^5.0.4: + version "5.0.4" + resolved "https://registry.yarnpkg.com/web3-react/-/web3-react-5.0.4.tgz#6006ee51c17255707f73d927f16eb48857957034" + integrity sha512-K9Bz+CojWOt3Fiya9SRkYmDsTPjT4vuEs5JQCfEyWH9wWVrXJgGMQxglq5RNfRWBhqgN0PmDMLeYiERQcNt/6g== dependencies: "@0x/subproviders" "^4.0.5" - "@portis/web3" "^2.0.0-beta.23" - "@walletconnect/web3-subprovider" "^1.0.0-beta.10" - fortmatic "^0.7.0" - trezor-connect "^7.0.2" web3-shh@1.0.0-beta.35: version "1.0.0-beta.35" @@ -14085,7 +13846,7 @@ whatwg-fetch@2.0.4: resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f" integrity sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng== -whatwg-fetch@3.0.0, whatwg-fetch@>=0.10.0, whatwg-fetch@^3.0.0: +whatwg-fetch@3.0.0, whatwg-fetch@>=0.10.0: version "3.0.0" resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb" integrity sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==