diff --git a/.env.example b/.env.example index cb172be8..1e81bb2a 100644 --- a/.env.example +++ b/.env.example @@ -1,13 +1,8 @@ # You can leave this empty for rinkeby or use "mainnet" REACT_APP_NETWORK= -# For Rinkeby network -REACT_APP_GOOGLE_ANALYTICS_ID_RINKEBY= - -# For Mainnet network (no needed on dev mode) -REACT_APP_GOOGLE_ANALYTICS_ID_MAINNET= - # For all environments +REACT_APP_GOOGLE_ANALYTICS= REACT_APP_INFURA_TOKEN= REACT_APP_IPFS_GATEWAY=https://ipfs.io/ipfs PUBLIC_URL=/app/ diff --git a/.travis.yml b/.travis.yml index 0804243d..8aa5c157 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,4 @@ -if: (branch = development) OR (branch = master) OR (type = pull_request) OR (tag IS present) +if: (branch = development) OR (branch = master) OR (branch = release/2.14.0) OR (type = pull_request) OR (tag IS present) sudo: required dist: bionic language: node_js @@ -10,20 +10,39 @@ matrix: include: - env: - REACT_APP_NETWORK='mainnet' + - REACT_APP_GOOGLE_ANALYTICS=${REACT_APP_GOOGLE_ANALYTICS_ID_MAINNET} - STAGING_BUCKET_NAME=${STAGING_MAINNET_BUCKET_NAME} - REACT_APP_GNOSIS_APPS_URL=${REACT_APP_GNOSIS_APPS_URL_PROD} if: (branch = master AND NOT type = pull_request) OR tag IS present - env: - REACT_APP_NETWORK='rinkeby' + - REACT_APP_GOOGLE_ANALYTICS=${REACT_APP_GOOGLE_ANALYTICS_ID_RINKEBY} - REACT_APP_GNOSIS_APPS_URL=${REACT_APP_GNOSIS_APPS_URL_STAGING} + - env: + - REACT_APP_NETWORK='xdai' + - REACT_APP_GOOGLE_ANALYTICS=${REACT_APP_GOOGLE_ANALYTICS_ID_XDAI} + - STAGING_BUCKET_NAME=${STAGING_XDAI_BUCKET_NAME} + if: (branch = master AND NOT type = pull_request) OR tag IS present + - env: + - REACT_APP_NETWORK='volta' + - REACT_APP_GOOGLE_ANALYTICS=${REACT_APP_GOOGLE_ANALYTICS_ID_VOLTA} + - STAGING_BUCKET_NAME=${STAGING_VOLTA_BUCKET_NAME} + if: (branch = master AND NOT type = pull_request) OR tag IS present + - env: + - REACT_APP_NETWORK='energy_web_chain' + - REACT_APP_GOOGLE_ANALYTICS=${REACT_APP_GOOGLE_ANALYTICS_ID_EWC} + - STAGING_BUCKET_NAME=${STAGING_EWC_BUCKET_NAME} + if: ((branch = master OR branch = release/2.14.0) AND NOT type = pull_request) OR tag IS present + cache: yarn: true before_script: - if [[ -n "$TRAVIS_TAG" ]]; then export REACT_APP_ENV='production'; fi; + - if [ $TRAVIS_PULL_REQUEST != "false" ]; then export PUBLIC_URL="/${REACT_APP_NETWORK}/app"; fi; before_install: # Needed to deploy pull request and releases - sudo apt-get update - - sudo apt-get -y install python-pip python-dev libusb-1.0-0-dev + - sudo apt-get -y install python-pip python-dev libusb-1.0-0-dev libudev-dev - pip install awscli --upgrade --user script: - yarn lint:check @@ -47,31 +66,44 @@ deploy: secret_access_key: $AWS_SECRET_ACCESS_KEY skip_cleanup: true local_dir: build - upload-dir: app + upload_dir: app region: $AWS_DEFAULT_REGION on: branch: development - # Staging environment + # Staging environment - provider: s3 bucket: $STAGING_BUCKET_NAME access_key_id: $AWS_ACCESS_KEY_ID secret_access_key: $AWS_SECRET_ACCESS_KEY skip_cleanup: true local_dir: build - upload-dir: current/app + upload_dir: current/app region: $AWS_DEFAULT_REGION on: branch: master + + # EWC testing on staging + - provider: s3 + bucket: $STAGING_BUCKET_NAME + access_key_id: $AWS_ACCESS_KEY_ID + secret_access_key: $AWS_SECRET_ACCESS_KEY + skip_cleanup: true + local_dir: build + upload_dir: current/app + region: $AWS_DEFAULT_REGION + on: + branch: release/2.14.0 + condition: $REACT_APP_NETWORK = energy_web_chain - # Prepare production deployment + # Prepare production deployment - provider: s3 bucket: $STAGING_BUCKET_NAME secret_access_key: $AWS_SECRET_ACCESS_KEY access_key_id: $AWS_ACCESS_KEY_ID skip_cleanup: true local_dir: build - upload-dir: releases/$TRAVIS_TAG + upload_dir: releases/$TRAVIS_TAG region: $AWS_DEFAULT_REGION on: tags: true diff --git a/config-overrides.js b/config-overrides.js index dd45a035..5c1d3fc4 100644 --- a/config-overrides.js +++ b/config-overrides.js @@ -5,7 +5,7 @@ module.exports = function override(config) { config.plugins = [] } config.plugins.push( - new webpack.ContextReplacementPlugin(/truffle-(contract|interface-adapter)/, (data) => { + new webpack.ContextReplacementPlugin(/@truffle\/(contract|interface-adapter)/, (data) => { delete data.dependencies[0].critical return data }), diff --git a/config/travis/deploy_pull_request.sh b/config/travis/deploy_pull_request.sh index ca0e155d..e6f5e884 100755 --- a/config/travis/deploy_pull_request.sh +++ b/config/travis/deploy_pull_request.sh @@ -15,11 +15,11 @@ function deploy_pull_request { REVIEW_FEATURE_FOLDER="$REPO_NAME_ALPHANUMERIC/$PULL_REQUEST_NAME" # Deploy safe-team project - aws s3 sync build s3://${REVIEW_BUCKET_NAME}/${REVIEW_FEATURE_FOLDER}/app --delete + aws s3 sync build s3://${REVIEW_BUCKET_NAME}/${REVIEW_FEATURE_FOLDER}/${REACT_APP_NETWORK}/app --delete } function publish_pull_request_urls_in_github { - REVIEW_FEATURE_URL="https://$PULL_REQUEST_NAME--$REPO_NAME_ALPHANUMERIC.$REVIEW_ENVIRONMENT_DOMAIN/app" + REVIEW_FEATURE_URL="https://$PULL_REQUEST_NAME--$REPO_NAME_ALPHANUMERIC.$REVIEW_ENVIRONMENT_DOMAIN/$REACT_APP_NETWORK/app" # Using the Issues api instead of the PR api # Done so because every PR is an issue, and the issues api allows to post general comments, diff --git a/package.json b/package.json index 7ca2a4bb..08fee6b4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "safe-react", - "version": "2.12.1", + "version": "2.13.1", "description": "Allowing crypto users manage funds in a safer way", "website": "https://github.com/gnosis/safe-react#readme", "bugs": { @@ -61,8 +61,7 @@ "src/**/*.{js,jsx,ts,tsx}", "!src/**/*.{.test.*}", "!src/**/test/**/*", - "!src/**/assets/**", - "!src/config/**/*" + "!src/**/assets/**" ] }, "productName": "Safe Multisig", @@ -149,6 +148,8 @@ } }, "resolutions": { + "@typescript-eslint/eslint-plugin": "^4.5.0", + "@typescript-eslint/parser": "^4.5.0", "node-gyp": "^5.1.0" }, "browserslist": { @@ -164,36 +165,38 @@ ] }, "dependencies": { - "@gnosis.pm/safe-apps-sdk": "0.4.0", + "@gnosis.pm/safe-apps-sdk": "https://github.com/gnosis/safe-apps-sdk.git#3f0689f", "@gnosis.pm/safe-contracts": "1.1.1-dev.2", - "@gnosis.pm/safe-react-components": "https://github.com/gnosis/safe-react-components.git#1bf397f", + "@gnosis.pm/safe-react-components": "https://github.com/gnosis/safe-react-components.git#70e57bdd1e0fd5dfdf5768076577c1e000b5fe28", "@gnosis.pm/util-contracts": "2.0.6", - "@ledgerhq/hw-transport-node-hid": "5.22.0", + "@ledgerhq/hw-transport-node-hid": "5.26.0", "@material-ui/core": "4.11.0", "@material-ui/icons": "4.9.1", "@material-ui/lab": "4.0.0-alpha.56", "@openzeppelin/contracts": "3.1.0", + "@truffle/contract": "4.2.26", "async-sema": "^3.1.0", "axios": "0.20.0", - "bignumber.js": "9.0.0", - "bnc-onboard": "1.13.1", + "bignumber.js": "9.0.1", + "bnc-onboard": "1.13.2", "classnames": "^2.2.6", "concurrently": "^5.3.0", "connected-react-router": "6.8.0", "coveralls": "^3.1.0", "currency-flags": "2.1.2", - "date-fns": "2.15.0", + "date-fns": "2.16.1", + "detect-port": "^1.3.0", "electron-is-dev": "^1.2.0", "electron-log": "4.2.4", "electron-settings": "^4.0.2", - "electron-updater": "4.3.4", + "electron-updater": "4.3.5", "eth-sig-util": "^2.5.3", "ethereum-blockies-base64": "^1.0.2", "ethereumjs-abi": "0.6.8", "exponential-backoff": "^3.1.0", "express": "^4.17.1", "final-form": "^4.20.1", - "final-form-calculate": "^1.3.1", + "final-form-calculate": "^1.3.2", "history": "4.10.1", "immortal-db": "^1.1.0", "immutable": "^4.0.0-rc.12", @@ -202,16 +205,15 @@ "lodash.memoize": "^4.1.2", "material-ui-search-bar": "^1.0.0", "notistack": "https://github.com/gnosis/notistack.git#v0.9.4", - "open": "^7.2.0", "polished": "3.6.7", "qrcode.react": "1.0.0", - "query-string": "6.13.1", + "query-string": "6.13.6", "react": "16.13.1", "react-dom": "16.13.1", - "react-final-form": "^6.5.1", + "react-final-form": "^6.5.2", "react-final-form-listeners": "^1.0.2", - "react-ga": "3.1.2", - "react-hot-loader": "4.12.21", + "react-ga": "3.2.0", + "react-hot-loader": "4.13.0", "react-qr-reader": "^2.2.1", "react-redux": "7.2.1", "react-router-dom": "5.2.0", @@ -224,7 +226,6 @@ "reselect": "^4.0.0", "semver": "7.3.2", "styled-components": "^5.2.0", - "truffle-contract": "4.0.31", "web3": "1.2.9", "web3-core": "^1.2.11", "web3-eth-contract": "^1.2.11", @@ -236,43 +237,43 @@ "@storybook/addons": "^5.3.19", "@storybook/preset-create-react-app": "^3.1.4", "@storybook/react": "^5.3.19", - "@testing-library/jest-dom": "5.11.4", + "@testing-library/jest-dom": "5.11.5", "@testing-library/react": "10.4.9", "@typechain/web3-v1": "^1.0.0", "@types/history": "4.6.2", - "@types/jest": "^26.0.14", + "@types/jest": "^26.0.15", "@types/lodash.memoize": "^4.1.6", - "@types/node": "14.11.2", - "@types/react": "^16.9.49", - "@types/react-dom": "^16.9.6", + "@types/node": "^14.14.5", + "@types/react": "^16.9.54", + "@types/react-dom": "^16.9.9", "@types/react-redux": "^7.1.9", - "@types/react-router-dom": "^5.1.5", - "@types/styled-components": "^5.1.3", - "@typescript-eslint/eslint-plugin": "3.9.1", - "@typescript-eslint/parser": "3.9.1", + "@types/react-router-dom": "^5.1.6", + "@types/styled-components": "^5.1.4", + "@typescript-eslint/eslint-plugin": "4.6.0", + "@typescript-eslint/parser": "4.6.0", "autoprefixer": "9.8.6", "cross-env": "^7.0.2", "dotenv": "^8.2.0", "dotenv-expand": "^5.1.0", - "electron": "9.3.0", - "electron-builder": "22.8.0", + "electron": "9.3.1", + "electron-builder": "22.8.1", "electron-notarize": "1.0.0", "eslint": "6.8.0", - "eslint-config-prettier": "6.11.0", - "eslint-plugin-import": "2.22.0", + "eslint-config-prettier": "6.14.0", + "eslint-plugin-import": "2.22.1", "eslint-plugin-jsx-a11y": "^6.3.1", "eslint-plugin-prettier": "^3.1.4", - "eslint-plugin-react": "^7.20.6", + "eslint-plugin-react": "^7.21.5", "eslint-plugin-sort-destructure-keys": "1.3.5", "ethereumjs-abi": "0.6.8", - "husky": "^4.2.5", - "lint-staged": "10.4.0", + "husky": "^4.3.0", + "lint-staged": "^10.4.2", "node-sass": "^4.14.1", "prettier": "2.1.2", "react-app-rewired": "^2.1.6", "react-docgen-typescript-loader": "^3.7.2", "typechain": "^2.0.0", - "typescript": "3.9.7", + "typescript": "4.0.5", "wait-on": "5.2.0" } } diff --git a/public/electron.js b/public/electron.js index d55fa0bc..b9f45dbb 100644 --- a/public/electron.js +++ b/public/electron.js @@ -1,84 +1,88 @@ -const electron = require("electron"); -const express = require('express'); -const open = require('open'); -const log = require('electron-log'); -const fs = require('fs'); -const Menu = electron.Menu; -const https = require('https'); -const autoUpdater = require('./auto-updater'); +const electron = require('electron') +const express = require('express') +const log = require('electron-log') +const fs = require('fs') +const Menu = electron.Menu +const https = require('https') +const detect = require('detect-port') +const autoUpdater = require('./auto-updater') -const app = electron.app; -const session = electron.session; -const BrowserWindow = electron.BrowserWindow; +const { app, session, BrowserWindow, shell } = electron -const path = require("path"); -const isDev = require("electron-is-dev"); +const path = require('path') +const isDev = require('electron-is-dev') const options = { - key: fs.readFileSync(path.join(__dirname, './ssl/server.key')), + key: fs.readFileSync(path.join(__dirname, './ssl/server.key')), cert: fs.readFileSync(path.join(__dirname, './ssl/server.crt')), - ca: fs.readFileSync(path.join(__dirname, './ssl/rootCA.crt')) -}; - -const PORT = 5000; - -const createServer = () => { - const app = express(); - const staticRoute = path.join(__dirname, '../build'); - app.use(express.static(staticRoute)); - https.createServer(options, app).listen(PORT); + ca: fs.readFileSync(path.join(__dirname, './ssl/rootCA.crt')), } +const DEFAULT_PORT = 5000 -let mainWindow; +const createServer = async () => { + const app = express() + const staticRoute = path.join(__dirname, '../build') + app.use(express.static(staticRoute)) + let selectedPort = DEFAULT_PORT + try { + const _port = await detect(DEFAULT_PORT) + if (_port !== DEFAULT_PORT) selectedPort = _port + https.createServer(options, app).listen(selectedPort) + } catch (e) { + log.error(e) + } finally { + return selectedPort + } +} -function getOpenedWindow(url,options) { - let display = electron.screen.getPrimaryDisplay(); - let width = display.bounds.width; - let height = display.bounds.height; +let mainWindow + +function getOpenedWindow(url, options) { + let display = electron.screen.getPrimaryDisplay() + let width = display.bounds.width + let height = display.bounds.height // filter all requests to trezor-bridge and change origin to make it work - const filter = { - urls: ['http://127.0.0.1:21325/*'] - }; - - options.webPreferences.affinity = 'main-window'; - - if(url.includes('trezor')){ - session.defaultSession.webRequest.onBeforeSendHeaders(filter, (details, callback) => { - details.requestHeaders['Origin'] = 'https://connect.trezor.io'; - callback({cancel: false, requestHeaders: details.requestHeaders}); - }); + const filter = { + urls: ['http://127.0.0.1:21325/*'], } - if(url.includes('wallet.portis') || url.includes('trezor') || url.includes('app.tor.us')){ + options.webPreferences.affinity = 'main-window' + + if (url.includes('trezor')) { + session.defaultSession.webRequest.onBeforeSendHeaders(filter, (details, callback) => { + details.requestHeaders['Origin'] = 'https://connect.trezor.io' + callback({ cancel: false, requestHeaders: details.requestHeaders }) + }) + } + + if (url.includes('wallet.portis') || url.includes('trezor') || url.includes('app.tor.us')) { const win = new BrowserWindow({ - width:350, - height:700, + width: 350, + height: 700, x: width - 1300, - parent:mainWindow, + parent: mainWindow, y: height - (process.platform === 'win32' ? 750 : 200), webContents: options.webContents, // use existing webContents if provided fullscreen: false, show: false, - }); - win.webContents.on('new-window', function(event, url){ - if(url.includes('trezor') && url.includes('bridge')) - open(url); - }); - win.once('ready-to-show', () => win.show()); + }) + win.webContents.on('new-window', function (event, url) { + if (url.includes('trezor') && url.includes('bridge')) shell.openExternal(url) + }) + win.once('ready-to-show', () => win.show()) - if(!options.webPreferences){ - win.loadURL(url); + if (!options.webPreferences) { + win.loadURL(url) } return win } - return null; - + return null } -function createWindow() { +function createWindow(port = DEFAULT_PORT) { mainWindow = new BrowserWindow({ show: false, width: 1024, @@ -88,80 +92,78 @@ function createWindow() { allowRunningInsecureContent: true, nativeWindowOpen: true, // need to be set in order to display modal }, - icon: path.join(__dirname, './build/safe.png'), - }); + icon: electron.nativeImage.createFromPath(path.join(__dirname, './build/safe.png')), + }) mainWindow.once('ready-to-show', () => { - mainWindow.show(); - }); + mainWindow.show() + }) - mainWindow.loadURL( - isDev - ? "http://localhost:3000" - : `https://localhost:${PORT}` - ) + mainWindow.loadURL(isDev ? 'http://localhost:3000' : `https://localhost:${port}`) if (isDev) { // Open the DevTools. - mainWindow.webContents.openDevTools(); + mainWindow.webContents.openDevTools() //BrowserWindow.addDevToolsExtension(''); } - mainWindow.setMenu(null); - mainWindow.setMenuBarVisibility(false); + mainWindow.setMenu(null) + mainWindow.setMenuBarVisibility(false) - mainWindow.webContents.on('new-window', function(event, url, frameName, disposition, options){ - event.preventDefault(); - const win = getOpenedWindow(url,options); - if(win){ - win.once('ready-to-show', () => win.show()); + mainWindow.webContents.on('new-window', function (event, url, frameName, disposition, options) { + event.preventDefault() + const win = getOpenedWindow(url, options) + if (win) { + win.once('ready-to-show', () => win.show()) - if(!options.webPreferences){ - win.loadURL(url); + if (!options.webPreferences) { + win.loadURL(url) } event.newGuest = win - } else open(url); - }); + } else shell.openExternal(url) + }) mainWindow.webContents.on('did-finish-load', () => { - autoUpdater.init(mainWindow); - }); + autoUpdater.init(mainWindow) + }) mainWindow.webContents.on('crashed', (event) => { - log.info(`App Crashed: ${event}`); - mainWindow.reload(); - }); + log.info(`App Crashed: ${event}`) + mainWindow.reload() + }) - mainWindow.on("closed", () => (mainWindow = null)); + mainWindow.on('closed', () => (mainWindow = null)) } -process.on('uncaughtException',function(error){ - log.error(error); -}); +process.on('uncaughtException', function (error) { + log.error(error) +}) -app.userAgentFallback = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) old-airport-include/1.0.0 Chrome Electron/7.1.7 Safari/537.36'; +app.userAgentFallback = + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) old-airport-include/1.0.0 Chrome Electron/7.1.7 Safari/537.36' // We have one non-context-aware module in node_modules/usb. This is used by @ledgerhq/hw-transport-node-hid // This type of modules will be impossible to use after electron 10 -app.allowRendererProcessReuse = false; +app.allowRendererProcessReuse = false -app.commandLine.appendSwitch('ignore-certificate-errors'); -app.on("ready", () =>{ +app.commandLine.appendSwitch('ignore-certificate-errors') +app.on('ready', async () => { // Hide the menu - Menu.setApplicationMenu(null); - if(!isDev) createServer(); - createWindow(); -}); + Menu.setApplicationMenu(null) + let usedPort = DEFAULT_PORT + if (!isDev) usedPort = await createServer() + createWindow(usedPort) +}) -app.on("window-all-closed", () => { - if (process.platform !== "darwin") { - app.quit(); +app.on('window-all-closed', () => { + if (process.platform !== 'darwin') { + app.quit() } -}); +}) -app.on("activate", () => { +app.on('activate', () => { if (mainWindow === null) { - createWindow(); + createWindow() } -}); +}) diff --git a/src/components/App/assets/alert.svg b/src/assets/icons/alert.svg similarity index 100% rename from src/components/App/assets/alert.svg rename to src/assets/icons/alert.svg diff --git a/src/components/App/assets/check.svg b/src/assets/icons/check_bg.svg similarity index 100% rename from src/components/App/assets/check.svg rename to src/assets/icons/check_bg.svg diff --git a/src/components/App/assets/error.svg b/src/assets/icons/error.svg similarity index 100% rename from src/components/App/assets/error.svg rename to src/assets/icons/error.svg diff --git a/src/assets/icons/info.svg b/src/assets/icons/info.svg index 7becafe5..9f7502e4 100644 --- a/src/assets/icons/info.svg +++ b/src/assets/icons/info.svg @@ -1,52 +1,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + diff --git a/src/assets/icons/info_red.svg b/src/assets/icons/info_red.svg new file mode 100644 index 00000000..3623e9dd --- /dev/null +++ b/src/assets/icons/info_red.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/components/AddressInfo/index.tsx b/src/components/AddressInfo/index.tsx index efd40e50..0e618a2a 100644 --- a/src/components/AddressInfo/index.tsx +++ b/src/components/AddressInfo/index.tsx @@ -1,6 +1,5 @@ import React from 'react' -import styled from 'styled-components' - +import { getNetworkInfo } from 'src/config' import CopyBtn from 'src/components/CopyBtn' import EtherscanBtn from 'src/components/EtherscanBtn' import Identicon from 'src/components/Identicon' @@ -8,6 +7,7 @@ import Block from 'src/components/layout/Block' import Bold from 'src/components/layout/Bold' import Paragraph from 'src/components/layout/Paragraph' import { border, xs } from 'src/theme/variables' +import styled from 'styled-components' const Wrapper = styled.div` display: flex; @@ -42,6 +42,8 @@ interface Props { ethBalance?: string } +const { nativeCoin } = getNetworkInfo() + const AddressInfo = ({ ethBalance, safeAddress, safeName }: Props): React.ReactElement => { return ( @@ -59,12 +61,12 @@ const AddressInfo = ({ ethBalance, safeAddress, safeName }: Props): React.ReactE {safeAddress} - + {ethBalance && ( - Balance: {`${ethBalance} ETH`} + Balance: {`${ethBalance} ${nativeCoin.symbol}`} )} diff --git a/src/components/App/ReceiveModal.tsx b/src/components/App/ReceiveModal.tsx index 535a50bd..143b05ba 100644 --- a/src/components/App/ReceiveModal.tsx +++ b/src/components/App/ReceiveModal.tsx @@ -2,7 +2,7 @@ import IconButton from '@material-ui/core/IconButton' import { createStyles, makeStyles } from '@material-ui/core/styles' import Close from '@material-ui/icons/Close' import QRCode from 'qrcode.react' -import * as React from 'react' +import React, { ReactElement } from 'react' import CopyBtn from 'src/components/CopyBtn' import EtherscanBtn from 'src/components/EtherscanBtn' @@ -13,9 +13,11 @@ import Col from 'src/components/layout/Col' import Hairline from 'src/components/layout/Hairline' import Paragraph from 'src/components/layout/Paragraph' import Row from 'src/components/layout/Row' -import { lg, md, screenSm, secondaryText, sm } from 'src/theme/variables' +import { border, fontColor, lg, md, screenSm, secondaryText, sm } from 'src/theme/variables' import { copyToClipboard } from 'src/utils/clipboard' +import { getNetworkInfo } from 'src/config' +const networkInfo = getNetworkInfo() const useStyles = makeStyles( createStyles({ heading: { @@ -35,6 +37,12 @@ const useStyles = makeStyles( borderRadius: '6px', border: `1px solid ${secondaryText}`, }, + networkInfo: { + backgroundColor: `${networkInfo?.backgroundColor ?? border}`, + color: `${networkInfo?.textColor ?? fontColor}`, + padding: md, + marginBottom: 0, + }, annotation: { margin: lg, marginBottom: 0, @@ -79,7 +87,7 @@ type Props = { safeName: string } -const ReceiveModal = ({ onClose, safeAddress, safeName }: Props) => { +const ReceiveModal = ({ onClose, safeAddress, safeName }: Props): ReactElement => { const classes = useStyles() return ( @@ -93,9 +101,12 @@ const ReceiveModal = ({ onClose, safeAddress, safeName }: Props) => { + + {networkInfo.label} Network only send {networkInfo.label} assets to this Safe. + - This is the address of your Safe. Deposit funds by scanning the QR code or copying the address below. Only send - ETH and ERC-20 tokens to this address! + This is the address of your Safe. Deposit funds by scanning the QR code or copying the address below. Only send{' '} + {networkInfo.nativeCoin.name} and ERC-20 tokens to this address! @@ -115,7 +126,7 @@ const ReceiveModal = ({ onClose, safeAddress, safeName }: Props) => { {safeAddress} - + diff --git a/src/components/App/assets/info.svg b/src/components/App/assets/info.svg deleted file mode 100644 index 9f7502e4..00000000 --- a/src/components/App/assets/info.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/src/components/App/index.tsx b/src/components/App/index.tsx index ee90992a..f0fa31f4 100644 --- a/src/components/App/index.tsx +++ b/src/components/App/index.tsx @@ -5,10 +5,10 @@ import { useSelector } from 'react-redux' import { useRouteMatch, useHistory } from 'react-router-dom' import styled from 'styled-components' -import AlertIcon from './assets/alert.svg' -import CheckIcon from './assets/check.svg' -import ErrorIcon from './assets/error.svg' -import InfoIcon from './assets/info.svg' +import AlertIcon from 'src/assets/icons/alert.svg' +import CheckIcon from 'src/assets/icons/check.svg' +import ErrorIcon from 'src/assets/icons/error.svg' +import InfoIcon from 'src/assets/icons/info.svg' import AppLayout from 'src/components/AppLayout' import SafeListSidebarProvider, { SafeListSidebarContext } from 'src/components/SafeListSidebar' @@ -16,8 +16,8 @@ import CookiesBanner from 'src/components/CookiesBanner' import Notifier from 'src/components/Notifier' import Backdrop from 'src/components/layout/Backdrop' import Img from 'src/components/layout/Img' -import { getNetwork } from 'src/config' -import { ETHEREUM_NETWORK } from 'src/logic/wallets/getWeb3' +import { getNetworkId } from 'src/config' +import { ETHEREUM_NETWORK } from 'src/config/networks/network.d' import { networkSelector } from 'src/logic/wallets/store/selectors' import { SAFELIST_ADDRESS, WELCOME_ADDRESS } from 'src/routes/routes' import { safeNameSelector, safeParamAddressFromStateSelector } from 'src/logic/safe/store/selectors' @@ -26,11 +26,11 @@ import SendModal from 'src/routes/safe/components/Balances/SendModal' import { useLoadSafe } from 'src/logic/safe/hooks/useLoadSafe' import { useSafeScheduledUpdates } from 'src/logic/safe/hooks/useSafeScheduledUpdates' import useSafeActions from 'src/logic/safe/hooks/useSafeActions' -import { currentCurrencySelector, safeFiatBalancesTotalSelector } from 'src/logic/currencyValues/store/selectors/index' +import { currentCurrencySelector, safeFiatBalancesTotalSelector } from 'src/logic/currencyValues/store/selectors' import { formatAmountInUsFormat } from 'src/logic/tokens/utils/formatAmount' import { grantedSelector } from 'src/routes/safe/container/selector' -import Receive from './ReceiveModal' +import ReceiveModal from './ReceiveModal' import { useSidebarItems } from 'src/components/AppLayout/Sidebar/useSidebarItems' const notificationStyles = { @@ -46,6 +46,12 @@ const notificationStyles = { info: { background: '#fff', }, + receiveModal: { + height: 'auto', + maxWidth: 'calc(100% - 30px)', + minHeight: '544px', + overflow: 'hidden', + }, } const Frame = styled.div` @@ -55,7 +61,7 @@ const Frame = styled.div` max-width: 100%; ` -const desiredNetwork = getNetwork() +const desiredNetwork = getNetworkId() const useStyles = makeStyles(notificationStyles) @@ -67,7 +73,7 @@ const App: React.FC = ({ children }) => { const matchSafe = useRouteMatch({ path: `${SAFELIST_ADDRESS}`, strict: false }) const history = useHistory() const safeAddress = useSelector(safeParamAddressFromStateSelector) - const safeName = useSelector(safeNameSelector) + const safeName = useSelector(safeNameSelector) ?? '' const { safeActionsState, onShow, onHide, showSendFunds, hideSendFunds } = useSafeActions() const currentSafeBalance = useSelector(safeFiatBalancesTotalSelector) const currentCurrency = useSelector(currentCurrencySelector) @@ -77,7 +83,7 @@ const App: React.FC = ({ children }) => { useLoadSafe(safeAddress) useSafeScheduledUpdates(safeAddress) - const sendFunds = safeActionsState.sendFunds as { isOpen: boolean; selectedToken: string } + const sendFunds = safeActionsState.sendFunds const formattedTotalBalance = currentSafeBalance ? formatAmountInUsFormat(currentSafeBalance) : '' const balance = !!formattedTotalBalance && !!currentCurrency ? `${formattedTotalBalance} ${currentCurrency}` : undefined @@ -138,10 +144,11 @@ const App: React.FC = ({ children }) => { - + )} diff --git a/src/components/AppLayout/Header/components/CircleDot.tsx b/src/components/AppLayout/Header/components/CircleDot.tsx index 2ae0fe65..83ce6a0d 100644 --- a/src/components/AppLayout/Header/components/CircleDot.tsx +++ b/src/components/AppLayout/Header/components/CircleDot.tsx @@ -1,86 +1,27 @@ -import { withStyles } from '@material-ui/core/styles' -import Dot from '@material-ui/icons/FiberManualRecord' import * as React from 'react' +import { getNetworkInfo } from 'src/config' -import Block from 'src/components/layout/Block' -import Img from 'src/components/layout/Img' -import { border, fancy, screenSm, warning } from 'src/theme/variables' - -const key = require('../assets/key.svg') -const triangle = require('../assets/triangle.svg') - -const styles = () => ({ - root: { - display: 'none', - [`@media (min-width: ${screenSm}px)`]: { - display: 'flex', - }, - }, - dot: { - position: 'relative', - backgroundColor: '#ffffff', - color: fancy, - }, - key: { - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - backgroundColor: border, - }, - warning: { - position: 'relative', - top: '-2px', - }, -}) - -const buildKeyStyleFrom = (size, center, dotSize) => ({ - width: `${size}px`, - height: `${size}px`, - marginLeft: center ? `${dotSize}px` : 'none', - borderRadius: `${size}px`, -}) - -const buildDotStyleFrom = (size, top, right, mode) => ({ - width: `${size}px`, - height: `${size}px`, - borderRadius: `${size}px`, - top: `${top}px`, - right: `${right}px`, - color: mode === 'error' ? fancy : warning, -}) - -const KeyRing = ({ - center = false, - circleSize, - classes, - dotRight, - dotSize, - dotTop, - hideDot = false, - keySize, - mode, -}) => { - const keyStyle = buildKeyStyleFrom(circleSize, center, dotSize) - const dotStyle = buildDotStyleFrom(dotSize, dotTop, dotRight, mode) - const isWarning = mode === 'warning' - const img = isWarning ? triangle : key - - return ( - <> - - - Status connection - - {!hideDot && } - - - ) +type Props = { + className: string } -export default withStyles(styles as any)(KeyRing) +export const CircleDot = (props: Props): React.ReactElement => { + const networkInfo = getNetworkInfo() + + return ( +
+ + + +
+ ) +} diff --git a/src/components/AppLayout/Header/components/KeyRing.tsx b/src/components/AppLayout/Header/components/KeyRing.tsx new file mode 100644 index 00000000..10c39b74 --- /dev/null +++ b/src/components/AppLayout/Header/components/KeyRing.tsx @@ -0,0 +1,97 @@ +import { createStyles, makeStyles } from '@material-ui/core/styles' +import Dot from '@material-ui/icons/FiberManualRecord' +import * as React from 'react' + +import Block from 'src/components/layout/Block' +import Img from 'src/components/layout/Img' +import { border, fancy, screenSm, warning } from 'src/theme/variables' + +const key = require('../assets/key.svg') +const triangle = require('../assets/triangle.svg') + +const styles = createStyles({ + root: { + display: 'none', + [`@media (min-width: ${screenSm}px)`]: { + display: 'flex', + }, + }, + dot: { + position: 'relative', + backgroundColor: '#ffffff', + color: fancy, + }, + key: { + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + backgroundColor: border, + }, + warning: { + position: 'relative', + top: '-2px', + }, +}) + +const useStyles = makeStyles(styles) + +const buildKeyStyleFrom = (size, center, dotSize) => ({ + width: `${size}px`, + height: `${size}px`, + marginLeft: center ? `${dotSize}px` : 'none', + borderRadius: `${size}px`, +}) + +const buildDotStyleFrom = (size, top, right, mode) => ({ + width: `${size}px`, + height: `${size}px`, + borderRadius: `${size}px`, + top: `${top}px`, + right: `${right}px`, + color: mode === 'error' ? fancy : warning, +}) + +type Props = { + center?: boolean + circleSize?: number + dotRight?: number + dotSize?: number + dotTop?: number + hideDot?: boolean + keySize: number + mode?: string +} + +export const KeyRing = ({ + center = false, + circleSize, + dotRight, + dotSize, + dotTop, + hideDot = false, + keySize, + mode, +}: Props): React.ReactElement => { + const classes = useStyles(styles) + const keyStyle = buildKeyStyleFrom(circleSize, center, dotSize) + const dotStyle = buildDotStyleFrom(dotSize, dotTop, dotRight, mode) + const isWarning = mode === 'warning' + const img = isWarning ? triangle : key + + return ( + <> + + + Status connection + + {!hideDot && } + + + ) +} diff --git a/src/components/AppLayout/Header/components/NetworkLabel.tsx b/src/components/AppLayout/Header/components/NetworkLabel.tsx index 594c0cee..edd88fe3 100644 --- a/src/components/AppLayout/Header/components/NetworkLabel.tsx +++ b/src/components/AppLayout/Header/components/NetworkLabel.tsx @@ -3,11 +3,10 @@ import * as React from 'react' import Col from 'src/components/layout/Col' import Paragraph from 'src/components/layout/Paragraph' -import { getNetwork } from 'src/config' -import { border, md, screenSm, sm, xs } from 'src/theme/variables' +import { getNetworkInfo } from 'src/config' +import { border, md, screenSm, sm, xs, fontColor } from 'src/theme/variables' -const interfaceNetwork = getNetwork() -const formatNetwork = (network: string): string => network[0].toUpperCase() + network.substring(1).toLowerCase() +const networkInfo = getNetworkInfo() const useStyles = makeStyles({ container: { @@ -19,7 +18,8 @@ const useStyles = makeStyles({ }, }, text: { - background: border, + backgroundColor: `${networkInfo?.backgroundColor ?? border}`, + color: `${networkInfo?.textColor ?? fontColor}`, borderRadius: '3px', lineHeight: 'normal', margin: '0', @@ -31,18 +31,13 @@ const useStyles = makeStyles({ }, }) -interface NetworkLabelProps { - network?: string -} - -const NetworkLabel = ({ network = interfaceNetwork }: NetworkLabelProps): React.ReactElement => { +const NetworkLabel = (): React.ReactElement => { const classes = useStyles() - const formattedNetwork = formatNetwork(network) return ( - {formattedNetwork} + {networkInfo.label} ) diff --git a/src/components/AppLayout/Header/components/ProviderDetails/ConnectDetails.tsx b/src/components/AppLayout/Header/components/ProviderDetails/ConnectDetails.tsx index 76300a96..0b52d4e5 100644 --- a/src/components/AppLayout/Header/components/ProviderDetails/ConnectDetails.tsx +++ b/src/components/AppLayout/Header/components/ProviderDetails/ConnectDetails.tsx @@ -2,11 +2,12 @@ import { withStyles } from '@material-ui/core/styles' import * as React from 'react' import ConnectButton from 'src/components/ConnectButton' -import CircleDot from 'src/components/AppLayout/Header/components/CircleDot' + import Block from 'src/components/layout/Block' import Paragraph from 'src/components/layout/Paragraph' import Row from 'src/components/layout/Row' import { lg, md } from 'src/theme/variables' +import { KeyRing } from 'src/components/AppLayout/Header/components/KeyRing' const styles = () => ({ container: { @@ -42,7 +43,7 @@ const ConnectDetails = ({ classes }) => ( - + diff --git a/src/components/AppLayout/Header/components/ProviderDetails/UserDetails.tsx b/src/components/AppLayout/Header/components/ProviderDetails/UserDetails.tsx index 1319e05f..0f3ff77f 100644 --- a/src/components/AppLayout/Header/components/ProviderDetails/UserDetails.tsx +++ b/src/components/AppLayout/Header/components/ProviderDetails/UserDetails.tsx @@ -1,10 +1,9 @@ -import { withStyles } from '@material-ui/core/styles' +import { makeStyles } from '@material-ui/core/styles' import Dot from '@material-ui/icons/FiberManualRecord' import classNames from 'classnames' import * as React from 'react' import { EthHashInfo, Identicon } from '@gnosis.pm/safe-react-components' -import CircleDot from 'src/components/AppLayout/Header/components/CircleDot' import Spacer from 'src/components/Spacer' import Block from 'src/components/layout/Block' import Button from 'src/components/layout/Button' @@ -14,11 +13,15 @@ import Paragraph from 'src/components/layout/Paragraph' import Row from 'src/components/layout/Row' import { background, connected as connectedBg, lg, md, sm, warning, xs } from 'src/theme/variables' import { upperFirst } from 'src/utils/css' +import { ETHEREUM_NETWORK } from 'src/config/networks/network.d' +import { getExplorerInfo } from 'src/config' +import { KeyRing } from 'src/components/AppLayout/Header/components/KeyRing' +import { CircleDot } from '../CircleDot' +import { createStyles } from '@material-ui/core' -const dot = require('../../assets/dotRinkeby.svg') const walletIcon = require('../../assets/wallet.svg') -const styles = () => ({ +const styles = createStyles({ container: { padding: `${md} 12px`, display: 'flex', @@ -88,9 +91,29 @@ const styles = () => ({ }, }) -const UserDetails = ({ classes, connected, network, onDisconnect, openDashboard, provider, userAddress }) => { +type Props = { + connected: boolean + network: ETHEREUM_NETWORK + onDisconnect: () => void + openDashboard?: (() => void | null) | boolean + provider?: string + userAddress: string +} + +const useStyles = makeStyles(styles) + +export const UserDetails = ({ + connected, + network, + onDisconnect, + openDashboard, + provider, + userAddress, +}: Props): React.ReactElement => { const status = connected ? 'Connected' : 'Connection error' const color = connected ? 'primary' : 'warning' + const explorerUrl = getExplorerInfo(userAddress) + const classes = useStyles() return ( <> @@ -99,12 +122,12 @@ const UserDetails = ({ classes, connected, network, onDisconnect, openDashboard, {connected ? ( ) : ( - + )} {userAddress ? ( - + ) : ( 'Address not available' )} @@ -138,9 +161,9 @@ const UserDetails = ({ classes, connected, network, onDisconnect, openDashboard, Network - Network + - {upperFirst(network)} + {upperFirst(ETHEREUM_NETWORK[network])} @@ -170,5 +193,3 @@ const UserDetails = ({ classes, connected, network, onDisconnect, openDashboard, ) } - -export default withStyles(styles as any)(UserDetails) diff --git a/src/components/AppLayout/Header/components/ProviderInfo/ProviderAccessible.tsx b/src/components/AppLayout/Header/components/ProviderInfo/ProviderAccessible.tsx index 07989c05..563c3abb 100644 --- a/src/components/AppLayout/Header/components/ProviderInfo/ProviderAccessible.tsx +++ b/src/components/AppLayout/Header/components/ProviderInfo/ProviderAccessible.tsx @@ -3,11 +3,11 @@ import * as React from 'react' import { EthHashInfo, Text } from '@gnosis.pm/safe-react-components' import NetworkLabel from '../NetworkLabel' -import CircleDot from 'src/components/AppLayout/Header/components/CircleDot' import Col from 'src/components/layout/Col' import Paragraph from 'src/components/layout/Paragraph' import WalletIcon from '../WalletIcon' import { connected as connectedBg, screenSm, sm } from 'src/theme/variables' +import { KeyRing } from 'src/components/AppLayout/Header/components/KeyRing' const useStyles = makeStyles({ network: { @@ -62,16 +62,16 @@ const useStyles = makeStyles({ interface ProviderInfoProps { connected: boolean provider: string - network: string + // TODO: [xDai] Review. This may cause some issues with EthHashInfo. userAddress: string } -const ProviderInfo = ({ connected, provider, userAddress, network }: ProviderInfoProps): React.ReactElement => { +const ProviderInfo = ({ connected, provider, userAddress }: ProviderInfoProps): React.ReactElement => { const classes = useStyles() const addressColor = connected ? 'text' : 'warning' return ( <> - {!connected && } + {!connected && } ) : ( @@ -107,7 +106,7 @@ const ProviderInfo = ({ connected, provider, userAddress, network }: ProviderInf - + ) diff --git a/src/components/AppLayout/Header/components/ProviderInfo/ProviderDisconnected.tsx b/src/components/AppLayout/Header/components/ProviderInfo/ProviderDisconnected.tsx index c038f916..bb8e57fc 100644 --- a/src/components/AppLayout/Header/components/ProviderInfo/ProviderDisconnected.tsx +++ b/src/components/AppLayout/Header/components/ProviderInfo/ProviderDisconnected.tsx @@ -1,11 +1,10 @@ import { withStyles } from '@material-ui/core/styles' import * as React from 'react' -import CircleDot from 'src/components/AppLayout/Header/components/CircleDot' - import Col from 'src/components/layout/Col' import Paragraph from 'src/components/layout/Paragraph' import { sm } from 'src/theme/variables' +import { KeyRing } from 'src/components/AppLayout/Header/components/KeyRing' const styles = () => ({ network: { @@ -27,7 +26,7 @@ const styles = () => ({ const ProviderDisconnected = ({ classes }) => ( <> - + { return } - return + return } const getProviderDetailsBased = () => { diff --git a/src/components/AppLayout/Sidebar/SafeHeader/index.tsx b/src/components/AppLayout/Sidebar/SafeHeader/index.tsx index 9d3c2f3f..16a0268d 100644 --- a/src/components/AppLayout/Sidebar/SafeHeader/index.tsx +++ b/src/components/AppLayout/Sidebar/SafeHeader/index.tsx @@ -8,11 +8,13 @@ import { Identicon, Button, CopyToClipboardBtn, - EtherscanButton, + ExplorerButton, } from '@gnosis.pm/safe-react-components' -import { getNetwork } from 'src/config' import FlexSpacer from 'src/components/FlexSpacer' +import { getExplorerInfo, getNetworkInfo } from 'src/config' +import { NetworkSettings } from 'src/config/networks/network.d' +import { border, fontColor } from 'src/theme/variables' export const TOGGLE_SIDEBAR_BTN_TESTID = 'TOGGLE_SIDEBAR_BTN' @@ -46,6 +48,19 @@ const StyledButton = styled(Button)` margin: 0 4px 0 0; } ` + +type StyledTextLabelProps = { + networkInfo: NetworkSettings +} + +const StyledTextLabel = styled(Text)` + margin: -8px 0 4px -8px; + padding: 4px 8px; + width: 100%; + text-align: center; + color: ${(props: StyledTextLabelProps) => props.networkInfo?.textColor ?? fontColor}; + background-color: ${(props: StyledTextLabelProps) => props.networkInfo?.backgroundColor ?? border}; +` const StyledEthHashInfo = styled(EthHashInfo)` p { color: ${({ theme }) => theme.colors.placeHolder}; @@ -110,43 +125,50 @@ const SafeHeader = ({ ) } + const explorerUrl = getExplorerInfo(address) + const networkInfo = getNetworkInfo() return ( - - - - - - - - + <> + + {networkInfo.label} + + + + + + + + + - {safeName} - - - - - - - - + {safeName} + + + + + + + + - {granted ? null : ( - - - READ ONLY + {granted ? null : ( + + + READ ONLY + + + )} + + {balance} + + + + New Transaction - - )} - - {balance} - - - - New Transaction - - - + + + ) } diff --git a/src/components/AppLayout/Sidebar/useSidebarItems.tsx b/src/components/AppLayout/Sidebar/useSidebarItems.tsx index 58439e79..4cf8e76b 100644 --- a/src/components/AppLayout/Sidebar/useSidebarItems.tsx +++ b/src/components/AppLayout/Sidebar/useSidebarItems.tsx @@ -4,8 +4,13 @@ import { useRouteMatch } from 'react-router-dom' import { ListItemType } from 'src/components/List' import ListIcon from 'src/components/List/ListIcon' import { SAFELIST_ADDRESS } from 'src/routes/routes' +import { FEATURES } from 'src/config/networks/network.d' +import { useSelector } from 'react-redux' +import { safeFeaturesEnabledSelector } from 'src/logic/safe/store/selectors' const useSidebarItems = (): ListItemType[] => { + const featuresEnabled = useSelector(safeFeaturesEnabledSelector) + const safeAppsEnabled = Boolean(featuresEnabled?.includes(FEATURES.SAFE_APPS)) const matchSafe = useRouteMatch({ path: `${SAFELIST_ADDRESS}`, strict: false }) const matchSafeWithAddress = useRouteMatch<{ safeAddress: string }>({ path: `${SAFELIST_ADDRESS}/:safeAddress` }) const matchSafeWithAction = useRouteMatch({ path: `${SAFELIST_ADDRESS}/:safeAddress/:safeAction` }) as { @@ -13,11 +18,30 @@ const useSidebarItems = (): ListItemType[] => { params: Record } - const sidebarItems = useMemo((): ListItemType[] => { + return useMemo((): ListItemType[] => { if (!matchSafe || !matchSafeWithAddress) { return [] } + const settingsItem = { + label: 'Settings', + icon: , + selected: matchSafeWithAction?.params.safeAction === 'settings', + href: `${matchSafeWithAddress?.url}/settings`, + } + + const safeSidebar = safeAppsEnabled + ? [ + { + label: 'Apps', + icon: , + selected: matchSafeWithAction?.params.safeAction === 'apps', + href: `${matchSafeWithAddress?.url}/apps`, + }, + settingsItem, + ] + : [settingsItem] + return [ { label: 'ASSETS', @@ -37,22 +61,9 @@ const useSidebarItems = (): ListItemType[] => { selected: matchSafeWithAction?.params.safeAction === 'address-book', href: `${matchSafeWithAddress?.url}/address-book`, }, - { - label: 'Apps', - icon: , - selected: matchSafeWithAction?.params.safeAction === 'apps', - href: `${matchSafeWithAddress?.url}/apps`, - }, - { - label: 'Settings', - icon: , - selected: matchSafeWithAction?.params.safeAction === 'settings', - href: `${matchSafeWithAddress?.url}/settings`, - }, + ...safeSidebar, ] - }, [matchSafe, matchSafeWithAction, matchSafeWithAddress]) - - return sidebarItems + }, [matchSafe, matchSafeWithAction, matchSafeWithAddress, safeAppsEnabled]) } export { useSidebarItems } diff --git a/src/components/Collapse/index.tsx b/src/components/Collapse/index.tsx index 2f235748..85a87290 100644 --- a/src/components/Collapse/index.tsx +++ b/src/components/Collapse/index.tsx @@ -16,14 +16,14 @@ const Header = styled.div` align-items: center; ` -interface Collapse { +interface CollapseProps { title: React.ReactElement | string description?: React.ReactElement | string collapseClassName?: string headerWrapperClassName?: string } -const Collapse: React.FC = ({ +const Collapse: React.FC = ({ children, description = null, title, diff --git a/src/components/ConnectButton/index.tsx b/src/components/ConnectButton/index.tsx index a719776f..478a5712 100644 --- a/src/components/ConnectButton/index.tsx +++ b/src/components/ConnectButton/index.tsx @@ -8,10 +8,9 @@ import { fetchProvider } from 'src/logic/wallets/store/actions' import transactionDataCheck from 'src/logic/wallets/transactionDataCheck' import { getSupportedWallets } from 'src/logic/wallets/utils/walletList' import { store } from 'src/store' +import { BLOCKNATIVE_KEY } from 'src/utils/constants' -const isMainnet = process.env.REACT_APP_NETWORK === 'mainnet' - -const BLOCKNATIVE_API_KEY = isMainnet ? process.env.REACT_APP_BLOCKNATIVE_KEY : '7fbb9cee-7e97-4436-8770-8b29a9a8814c' +const networkId = getNetworkId() let lastUsedAddress = '' let providerName @@ -19,8 +18,8 @@ let providerName const wallets = getSupportedWallets() export const onboard = Onboard({ - dappId: BLOCKNATIVE_API_KEY, - networkId: getNetworkId(), + dappId: BLOCKNATIVE_KEY, + networkId: networkId, subscriptions: { wallet: (wallet) => { if (wallet.provider) { diff --git a/src/components/EtherscanBtn/index.tsx b/src/components/EtherscanBtn/index.tsx index c81d0be8..f7609489 100644 --- a/src/components/EtherscanBtn/index.tsx +++ b/src/components/EtherscanBtn/index.tsx @@ -6,8 +6,8 @@ import React from 'react' import EtherscanOpenIcon from './img/etherscan-open.svg' import Img from 'src/components/layout/Img' -import { getEtherScanLink } from 'src/logic/wallets/getWeb3' import { xs } from 'src/theme/variables' +import { getExplorerInfo } from 'src/config' const useStyles = makeStyles({ container: { @@ -30,26 +30,23 @@ const useStyles = makeStyles({ interface EtherscanBtnProps { className?: string increaseZindex?: boolean - type: 'tx' | 'address' value: string } -const EtherscanBtn = ({ - className = '', - increaseZindex = false, - type, - value, -}: EtherscanBtnProps): React.ReactElement => { +const EtherscanBtn = ({ className = '', increaseZindex = false, value }: EtherscanBtnProps): React.ReactElement => { const classes = useStyles() const customClasses = increaseZindex ? { popper: classes.increasedPopperZindex } : {} + const explorerInfo = getExplorerInfo(value) + const { url } = explorerInfo() + return ( event.stopPropagation()} - href={getEtherScanLink(type, value)} + href={url} rel="noopener noreferrer" target="_blank" > diff --git a/src/components/EtherscanLink/index.tsx b/src/components/EtherscanLink/index.tsx index fe33a953..e37beeef 100644 --- a/src/components/EtherscanLink/index.tsx +++ b/src/components/EtherscanLink/index.tsx @@ -17,11 +17,10 @@ interface EtherscanLinkProps { className?: string cut?: number knownAddress?: boolean - type: 'tx' | 'address' value: string } -const EtherscanLink = ({ className, cut, knownAddress, type, value }: EtherscanLinkProps): React.ReactElement => { +const EtherscanLink = ({ className, cut, knownAddress, value }: EtherscanLinkProps): React.ReactElement => { const classes = useStyles() return ( @@ -30,7 +29,7 @@ const EtherscanLink = ({ className, cut, knownAddress, type, value }: EtherscanL {cut ? shortVersionOf(value, cut) : value} - + {knownAddress !== undefined ? : null} ) diff --git a/src/components/ListContentLayout/Layout.ts b/src/components/ListContentLayout/Layout.ts index feb7d423..dbb5b2a0 100644 --- a/src/components/ListContentLayout/Layout.ts +++ b/src/components/ListContentLayout/Layout.ts @@ -3,7 +3,7 @@ import styled from 'styled-components' export const Wrapper = styled.div` display: grid; grid-template-columns: 245px auto; - min-height: 560px; + min-height: 75vh; .background { box-shadow: 1px 2px 10px 0 rgba(212, 212, 211, 0.59); background-color: white; diff --git a/src/components/SafeListSidebar/SafeList/AddresWrapper.tsx b/src/components/SafeListSidebar/SafeList/AddresWrapper.tsx new file mode 100644 index 00000000..8bf621a3 --- /dev/null +++ b/src/components/SafeListSidebar/SafeList/AddresWrapper.tsx @@ -0,0 +1,81 @@ +import React from 'react' +import styled from 'styled-components' +import { ButtonLink, EthHashInfo, Text } from '@gnosis.pm/safe-react-components' +import { formatAmount } from 'src/logic/tokens/utils/formatAmount' +import { sameAddress } from 'src/logic/wallets/ethAddresses' +import DefaultBadge from './DefaultBadge' +import { SafeRecordProps } from 'src/logic/safe/store/models/safe' +import { DefaultSafe } from 'src/routes/safe/store/reducer/types/safe' +import { SetDefaultSafe } from 'src/logic/safe/store/actions/setDefaultSafe' +import { makeStyles } from '@material-ui/core/styles' +import { getNetworkInfo } from 'src/config' + +const StyledButtonLink = styled(ButtonLink)` + visibility: hidden; + white-space: nowrap; +` +const useStyles = makeStyles({ + wrapper: { + display: 'flex', + padding: '5px 0', + width: '100%', + justifyContent: 'space-between', + '& > nth-child(2)': { + display: 'flex', + alignItems: 'center', + }, + }, + addressDetails: { + display: 'flex', + alignItems: 'center', + justifyContent: 'space-between', + width: '175px', + '& div': { + marginLeft: '0px', + padding: '5px 20px', + '& img': { + marginRight: '5px', + }, + '& p': { + marginTop: '3px', + }, + }, + }, +}) + +type Props = { + safe: SafeRecordProps + defaultSafe: DefaultSafe + setDefaultSafe: SetDefaultSafe +} + +const { nativeCoin } = getNetworkInfo() + +export const AddressWrapper = (props: Props): React.ReactElement => { + const classes = useStyles() + const { safe, defaultSafe, setDefaultSafe } = props + + return ( +
+ + +
+ {`${formatAmount(safe.ethBalance)} ${nativeCoin.name}`} + {sameAddress(defaultSafe, safe.address) ? ( + + ) : ( + { + setDefaultSafe(safe.address) + }} + color="primary" + > + Make default + + )} +
+
+ ) +} diff --git a/src/components/SafeListSidebar/SafeList/index.tsx b/src/components/SafeListSidebar/SafeList/index.tsx index 23ecd436..57b60238 100644 --- a/src/components/SafeListSidebar/SafeList/index.tsx +++ b/src/components/SafeListSidebar/SafeList/index.tsx @@ -1,62 +1,22 @@ import MuiList from '@material-ui/core/List' import ListItem from '@material-ui/core/ListItem' import { makeStyles } from '@material-ui/core/styles' -import { EthHashInfo, Icon, Text, ButtonLink } from '@gnosis.pm/safe-react-components' +import { Icon } from '@gnosis.pm/safe-react-components' import * as React from 'react' import styled from 'styled-components' - import { SafeRecord } from 'src/logic/safe/store/models/safe' import { DefaultSafe } from 'src/routes/safe/store/reducer/types/safe' import { SetDefaultSafe } from 'src/logic/safe/store/actions/setDefaultSafe' -import { getNetwork } from 'src/config' -import DefaultBadge from './DefaultBadge' import Hairline from 'src/components/layout/Hairline' import Link from 'src/components/layout/Link' -import { formatAmount } from 'src/logic/tokens/utils/formatAmount' import { sameAddress } from 'src/logic/wallets/ethAddresses' import { SAFELIST_ADDRESS } from 'src/routes/routes' - +import { AddressWrapper } from './AddresWrapper' export const SIDEBAR_SAFELIST_ROW_TESTID = 'SIDEBAR_SAFELIST_ROW_TESTID' const StyledIcon = styled(Icon)` margin-right: 4px; ` -const AddressWrapper = styled.div` - display: flex; - padding: 5px 0; - width: 100%; - justify-content: space-between; - - > nth-child(2) { - display: flex; - align-items: center; - } -` - -const StyledButtonLink = styled(ButtonLink)` - visibility: hidden; - white-space: nowrap; -` - -const AddressDetails = styled.div` - display: flex; - align-items: center; - justify-content: space-between; - width: 175px; - - div { - margin-left: 0px; - padding: 5px 20px; - - img { - margin-right: 5px; - } - - p { - margin-top: 3px; - } - } -` const useStyles = makeStyles({ list: { @@ -107,34 +67,7 @@ const SafeList = ({ currentSafe, defaultSafe, onSafeClick, safes, setDefaultSafe ) : (
placeholder
)} - - - - - - {`${formatAmount(safe.ethBalance)} ETH`} - {sameAddress(defaultSafe, safe.address) ? ( - - ) : ( - { - setDefaultSafe(safe.address) - }} - color="primary" - > - Make default - - )} - - + diff --git a/src/components/layout/Img/index.tsx b/src/components/layout/Img/index.tsx index bab91c2b..425e719a 100644 --- a/src/components/layout/Img/index.tsx +++ b/src/components/layout/Img/index.tsx @@ -1,11 +1,17 @@ import classNames from 'classnames/bind' -import React from 'react' +import React, { ReactElement, ImgHTMLAttributes } from 'react' import styles from './index.module.scss' const cx = classNames.bind(styles) -const Img: any = ({ alt, bordered, className, fullwidth, style, testId = '', ...props }) => { +type ImgProps = ImgHTMLAttributes & { + bordered?: boolean + fullwidth?: boolean + testId?: string +} + +const Img = ({ alt, bordered, className, fullwidth, style, testId = '', ...props }: ImgProps): ReactElement => { const classes = cx(styles.img, { fullwidth, bordered }, className) return {alt} diff --git a/src/config/__tests__/config.test.ts b/src/config/__tests__/config.test.ts new file mode 100644 index 00000000..021a4a20 --- /dev/null +++ b/src/config/__tests__/config.test.ts @@ -0,0 +1,136 @@ +import { ETHEREUM_NETWORK } from 'src/config/networks/network.d' +import { default as networks } from 'src/config/networks' + +const { mainnet, xdai } = networks + +describe('Config Services', () => { + beforeEach(() => { + jest.resetModules() + }) + + it(`should load 'test' network config`, () => { + // Given + jest.mock('src/utils/constants', () => ({ + NODE_ENV: 'test', + })) + const { getNetworkInfo } = require('src/config') + + // When + const networkInfo = getNetworkInfo() + + // Then + expect(networkInfo.id).toBe(ETHEREUM_NETWORK.LOCAL) + }) + + it(`should load 'mainnet' network config`, () => { + // Given + jest.mock('src/utils/constants', () => ({ + NODE_ENV: '', + NETWORK: 'MAINNET', + })) + const { getNetworkInfo } = require('src/config') + + // When + const networkInfo = getNetworkInfo() + + // Then + expect(networkInfo.id).toBe(ETHEREUM_NETWORK.MAINNET) + }) + + it(`should load 'mainnet.dev' network config`, () => { + // Given + jest.mock('src/utils/constants', () => ({ + NODE_ENV: '', + NETWORK: 'MAINNET', + })) + const { getTxServiceUrl, getGnosisSafeAppsUrl } = require('src/config') + const TX_SERVICE_URL = mainnet.environment.dev?.txServiceUrl + const SAFE_APPS_URL = mainnet.environment.dev?.safeAppsUrl + + // When + const txServiceUrl = getTxServiceUrl() + const safeAppsUrl = getGnosisSafeAppsUrl() + + // Then + expect(TX_SERVICE_URL).toBe(txServiceUrl) + expect(SAFE_APPS_URL).toBe(safeAppsUrl) + }) + + it(`should load 'mainnet.staging' network config`, () => { + // Given + jest.mock('src/utils/constants', () => ({ + NODE_ENV: 'production', + NETWORK: 'MAINNET', + })) + const { getTxServiceUrl, getGnosisSafeAppsUrl } = require('src/config') + const TX_SERVICE_URL = mainnet.environment.staging?.txServiceUrl + const SAFE_APPS_URL = mainnet.environment.staging?.safeAppsUrl + + // When + const txServiceUrl = getTxServiceUrl() + const safeAppsUrl = getGnosisSafeAppsUrl() + + // Then + expect(TX_SERVICE_URL).toBe(txServiceUrl) + expect(SAFE_APPS_URL).toBe(safeAppsUrl) + }) + + it(`should load 'mainnet.production' network config`, () => { + // Given + jest.mock('src/utils/constants', () => ({ + NODE_ENV: 'production', + NETWORK: 'MAINNET', + APP_ENV: 'production' + })) + const { getTxServiceUrl, getGnosisSafeAppsUrl } = require('src/config') + const TX_SERVICE_URL = mainnet.environment.production.txServiceUrl + const SAFE_APPS_URL = mainnet.environment.production.safeAppsUrl + + // When + const txServiceUrl = getTxServiceUrl() + const safeAppsUrl = getGnosisSafeAppsUrl() + + // Then + expect(TX_SERVICE_URL).toBe(txServiceUrl) + expect(SAFE_APPS_URL).toBe(safeAppsUrl) + }) + + it(`should load 'xdai.production' network config`, () => { + // Given + jest.mock('src/utils/constants', () => ({ + NODE_ENV: 'production', + NETWORK: 'XDAI', + APP_ENV: 'production' + })) + const { getTxServiceUrl, getGnosisSafeAppsUrl } = require('src/config') + const TX_SERVICE_URL = xdai.environment.production.txServiceUrl + const SAFE_APPS_URL = xdai.environment.production.safeAppsUrl + + // When + const txServiceUrl = getTxServiceUrl() + const safeAppsUrl = getGnosisSafeAppsUrl() + + // Then + expect(TX_SERVICE_URL).toBe(txServiceUrl) + expect(SAFE_APPS_URL).toBe(safeAppsUrl) + }) + + it(`should default to 'xdai.production' network config if no environment is found`, () => { + // Given + jest.mock('src/utils/constants', () => ({ + NODE_ENV: '', + NETWORK: 'XDAI', + })) + const { getTxServiceUrl, getGnosisSafeAppsUrl } = require('src/config') + const TX_SERVICE_URL = xdai.environment.production.txServiceUrl + const SAFE_APPS_URL = xdai.environment.production.safeAppsUrl + + // When + const txServiceUrl = getTxServiceUrl() + const safeAppsUrl = getGnosisSafeAppsUrl() + + // Then + expect(TX_SERVICE_URL).toBe(txServiceUrl) + expect(SAFE_APPS_URL).toBe(safeAppsUrl) + }) +}) diff --git a/src/assets/icons/icon_etherTokens.svg b/src/config/assets/token_eth.svg similarity index 100% rename from src/assets/icons/icon_etherTokens.svg rename to src/config/assets/token_eth.svg diff --git a/src/config/assets/token_ewc.svg b/src/config/assets/token_ewc.svg new file mode 100644 index 00000000..f52e2285 --- /dev/null +++ b/src/config/assets/token_ewc.svg @@ -0,0 +1,18 @@ + + + + +ewf_logo + + diff --git a/src/config/assets/token_xdai.svg b/src/config/assets/token_xdai.svg new file mode 100644 index 00000000..044b3395 --- /dev/null +++ b/src/config/assets/token_xdai.svg @@ -0,0 +1,22 @@ + + + + +Group 6 +Created with Sketch. + + + + + + + + + + + + diff --git a/src/config/development-mainnet.ts b/src/config/development-mainnet.ts deleted file mode 100644 index a26a7075..00000000 --- a/src/config/development-mainnet.ts +++ /dev/null @@ -1,11 +0,0 @@ -// -import devConfig from './development' -import { TX_SERVICE_HOST, RELAY_API_URL } from 'src/config/names' - -const devMainnetConfig = { - ...devConfig, - [TX_SERVICE_HOST]: 'https://safe-transaction.mainnet.staging.gnosisdev.com/api/v1/', - [RELAY_API_URL]: 'https://safe-relay.mainnet.staging.gnosisdev.com/api/v1/', -} - -export default devMainnetConfig diff --git a/src/config/development.ts b/src/config/development.ts deleted file mode 100644 index fa26777e..00000000 --- a/src/config/development.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { TX_SERVICE_HOST, SIGNATURES_VIA_METAMASK, RELAY_API_URL, SAFE_APPS_URL } from 'src/config/names' - -const devConfig = { - [TX_SERVICE_HOST]: 'https://safe-transaction.staging.gnosisdev.com/api/v1/', - [SIGNATURES_VIA_METAMASK]: false, - [RELAY_API_URL]: 'https://safe-relay.staging.gnosisdev.com/api/v1/', - [SAFE_APPS_URL]: 'https://safe-apps.dev.gnosisdev.com/' - //[SAFE_APPS_URL]: 'http://localhost:3002/' -} - -export default devConfig diff --git a/src/config/index.ts b/src/config/index.ts index 929cbf1b..ba2d718e 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -1,103 +1,170 @@ -import { checksumAddress } from 'src/utils/checksumAddress'; -import { ensureOnce } from 'src/utils/singleton' -import { ETHEREUM_NETWORK } from 'src/logic/wallets/getWeb3' -import { - RELAY_API_URL, - SIGNATURES_VIA_METAMASK, - TX_SERVICE_HOST, - SAFE_APPS_URL -} from 'src/config/names' -import devConfig from './development' -import testConfig from './testing' -import stagingConfig from './staging' -import prodConfig from './production' -import mainnetDevConfig from './development-mainnet' -import mainnetProdConfig from './production-mainnet' -import mainnetStagingConfig from './staging-mainnet' +import memoize from 'lodash.memoize' -const configuration = () => { - if (process.env.NODE_ENV === 'test') { - return testConfig +import networks from 'src/config/networks' +import { EnvironmentSettings, ETHEREUM_NETWORK, NetworkSettings, SafeFeatures, Wallets, GasPriceOracle } from 'src/config/networks/network.d' +import { APP_ENV, ETHERSCAN_API_KEY, GOOGLE_ANALYTICS_ID, INFURA_TOKEN, NETWORK, NODE_ENV } from 'src/utils/constants' +import { ensureOnce } from 'src/utils/singleton' + +export const getNetworkId = (): ETHEREUM_NETWORK => ETHEREUM_NETWORK[NETWORK] + +export const getNetworkName = (): string => ETHEREUM_NETWORK[getNetworkId()] + +const getCurrentEnvironment = (): string => { + switch (NODE_ENV) { + case 'test': { + return 'test' + } + case 'production': { + return APP_ENV === 'production' ? 'production' : 'staging' + } + default: { + return 'dev' + } + } +} + +type NetworkSpecificConfiguration = EnvironmentSettings & { + network: NetworkSettings, + disabledFeatures?: SafeFeatures, + disabledWallets?: Wallets, +} + +const configuration = (): NetworkSpecificConfiguration => { + const currentEnvironment = getCurrentEnvironment() + + // special case for test environment + if (currentEnvironment === 'test') { + const configFile = networks.local + + return { + ...configFile.environment.production, + network: configFile.network, + disabledFeatures: configFile.disabledFeatures, + } } - if (process.env.NODE_ENV === 'production') { - if (process.env.REACT_APP_NETWORK === 'mainnet') { - return process.env.REACT_APP_ENV === 'production' - ? mainnetProdConfig - : mainnetStagingConfig + // lookup the config file based on the network specified in the NETWORK variable + const configFile = networks[getNetworkName().toLowerCase()] + // defaults to 'production' as it's the only environment that is required for the network configs + const networkBaseConfig = configFile.environment[currentEnvironment] ?? configFile.environment.production + + return { + ...networkBaseConfig, + network: configFile.network, + disabledFeatures: configFile.disabledFeatures, + disabledWallets: configFile.disabledWallets + } +} + +const getConfig: () => NetworkSpecificConfiguration = ensureOnce(configuration) + +export const getTxServiceUrl = (): string => getConfig().txServiceUrl + +export const getRelayUrl = (): string | undefined => getConfig().relayApiUrl + +export const getGnosisSafeAppsUrl = (): string => getConfig().safeAppsUrl + +export const getGasPrice = (): number | undefined => getConfig()?.gasPrice + +export const getGasPriceOracle = (): GasPriceOracle | undefined => getConfig()?.gasPriceOracle + +export const getRpcServiceUrl = (): string => { + const usesInfuraRPC = [ETHEREUM_NETWORK.MAINNET, ETHEREUM_NETWORK.RINKEBY].includes(getNetworkId()) + + if (usesInfuraRPC) { + return `${getConfig().rpcServiceUrl}/${INFURA_TOKEN}` + } + + return getConfig().rpcServiceUrl +} + +export const getSafeServiceBaseUrl = (safeAddress: string) => `${getTxServiceUrl()}/safes/${safeAddress}` + +export const getTokensServiceBaseUrl = () => `${getTxServiceUrl()}/tokens` + +export const getNetworkExplorerInfo = (): { name: string; url: string; apiUrl: string } => ({ + name: getConfig().networkExplorerName, + url: getConfig().networkExplorerUrl, + apiUrl: getConfig().networkExplorerApiUrl, +}) + +export const getNetworkConfigDisabledFeatures = (): SafeFeatures => getConfig().disabledFeatures || [] + +export const getNetworkConfigDisabledWallets = (): Wallets => getConfig()?.disabledWallets || [] + +export const getNetworkInfo = (): NetworkSettings => getConfig().network + +export const getGoogleAnalyticsTrackingID = (): string => GOOGLE_ANALYTICS_ID + +const fetchContractABI = memoize( + async (url: string, contractAddress: string, apiKey?: string) => { + let params: Record = { + module: 'contract', + action: 'getAbi', + address: contractAddress, } - return process.env.REACT_APP_ENV === 'production' - ? prodConfig - : stagingConfig + if (apiKey) { + params = { ...params, apiKey } + } + + const response = await fetch(`${url}?${new URLSearchParams(params)}`) + + if (!response.ok) { + return { status: 0, result: [] } + } + + return response.json() + }, + (url, contractAddress) => `${url}_${contractAddress}`, +) + +const getNetworkExplorerApiKey = (networkExplorerName: string): string | undefined=> { + switch (networkExplorerName.toLowerCase()) { + case 'etherscan': { + return ETHERSCAN_API_KEY + } + default: { + return undefined + } } - - return process.env.REACT_APP_NETWORK === 'mainnet' - ? mainnetDevConfig - : devConfig } -export const getNetwork = () => - process.env.REACT_APP_NETWORK === 'mainnet' - ? ETHEREUM_NETWORK.MAINNET - : ETHEREUM_NETWORK.RINKEBY +export const getContractABI = async (contractAddress: string) =>{ + const { apiUrl, name } = getNetworkExplorerInfo() -export const getNetworkId = () => - process.env.REACT_APP_NETWORK === 'mainnet' ? 1 : 4 + const apiKey = getNetworkExplorerApiKey(name) -const getConfig = ensureOnce(configuration) + try { + const { result, status } = await fetchContractABI(apiUrl, contractAddress, apiKey) -export const getTxServiceHost = () => { - const config = getConfig() + if (status === '0') { + return [] + } - return config[TX_SERVICE_HOST] + return result + } catch (e) { + console.error('Failed to retrieve ABI', e) + return undefined + } } -export const getTxServiceUriFrom = (safeAddress) => - `safes/${safeAddress}/transactions/` - -export const getIncomingTxServiceUriTo = (safeAddress) => - `safes/${safeAddress}/incoming-transfers/` - -export const getAllTransactionsUriFrom = (safeAddress: string): string => - `safes/${safeAddress}/all-transactions/` - -export const getSafeCreationTxUri = (safeAddress) => `safes/${safeAddress}/creation/` - -export const getRelayUrl = () => getConfig()[RELAY_API_URL] - -export const signaturesViaMetamask = () => { - const config = getConfig() - - return config[SIGNATURES_VIA_METAMASK] +export type BlockScanInfo = () => { + alt: string + url: string } -export const getGnosisSafeAppsUrl = () => { - const config = getConfig() +export const getExplorerInfo = (hash: string): BlockScanInfo => { + const { name, url } = getNetworkExplorerInfo() + const networkInfo = getNetworkInfo() - return config[SAFE_APPS_URL] -} - -export const getGoogleAnalyticsTrackingID = () => - getNetwork() === ETHEREUM_NETWORK.MAINNET - ? process.env.REACT_APP_GOOGLE_ANALYTICS_ID_MAINNET - : process.env.REACT_APP_GOOGLE_ANALYTICS_ID_RINKEBY - -export const getIntercomId = () => - process.env.REACT_APP_ENV === 'production' - ? process.env.REACT_APP_INTERCOM_ID - : 'plssl1fl' - -export const getExchangeRatesUrl = () => 'https://api.exchangeratesapi.io/latest' - -export const getExchangeRatesUrlFallback = () => 'https://api.coinbase.com/v2/exchange-rates' - -export const getSafeLastVersion = () => process.env.REACT_APP_LATEST_SAFE_VERSION || '1.1.1' - -export const buildSafeCreationTxUrl = (safeAddress) => { - const host = getTxServiceHost() - const address = checksumAddress(safeAddress) - const base = getSafeCreationTxUri(address) - - return `${host}${base}` + switch (networkInfo.id) { + default: { + const type = hash.length > 42 ? 'tx' : 'address' + return () => ({ + url: `${url}/${type}/${hash}`, + alt: name || '', + }) + } + } } diff --git a/src/config/names.ts b/src/config/names.ts deleted file mode 100644 index 3390fbec..00000000 --- a/src/config/names.ts +++ /dev/null @@ -1,4 +0,0 @@ -export const TX_SERVICE_HOST = 'tsh' -export const SIGNATURES_VIA_METAMASK = 'svm' -export const RELAY_API_URL = 'rau' -export const SAFE_APPS_URL = 'sau' diff --git a/src/config/networks/__tests__/networks.test.ts b/src/config/networks/__tests__/networks.test.ts new file mode 100644 index 00000000..00a79dfd --- /dev/null +++ b/src/config/networks/__tests__/networks.test.ts @@ -0,0 +1,142 @@ +import fs from 'fs' + +import networks from 'src/config/networks' +import { ETHEREUM_NETWORK } from 'src/config/networks/network.d' +import { isValidURL } from 'src/utils/url' + +describe('Networks config files test', () => { + const environments = ['dev', 'staging', 'production'] + + const NETWORKS_PATH = 'src/config/networks/' + const configFiles = fs.readdirSync(NETWORKS_PATH) + const networksFileNames = configFiles + .filter((file) => !fs.lstatSync(`${NETWORKS_PATH}${file}`).isDirectory()) + .filter((file) => { + const [fileName, extension] = file.split('.') + return extension === 'ts' && fileName !== 'index' + }) + .map((file) => file.split('.')[0]) + + it(`should verify that the network file is exported in the networks/index.ts file`, () => { + networksFileNames.forEach((networkFileName) => { + const isValid = !!networks[networkFileName] + + if (!isValid) { + console.log(`Network file "${networkFileName}" is not exported in "networks/index.ts"`) + } + + expect(isValid).toBeTruthy() + }) + }) + + environments.forEach((environment) => { + networksFileNames.forEach((networkFileName) => { + it(`should validate "${environment}" environment URIs for ${networkFileName} config`, () => { + // Given + const networkConfig = networks[networkFileName] + + // When + const networkConfigElement = networkConfig.environment[environment] + if (!networkConfigElement) { + return + } + + const environmentConfigKeys = Object + .keys(networkConfigElement) + .filter((environmentConfigKey) => + environmentConfigKey.endsWith('Uri') && !!networkConfigElement[environmentConfigKey] + ) + + // Then + environmentConfigKeys.forEach((environmentConfigKey) => { + const networkConfigElementUri = networkConfigElement[environmentConfigKey] + const isValid = isValidURL(networkConfigElementUri) + + if (!isValid) { + console.log(`Invalid URI in "${networkFileName}" at ${environment}.${environmentConfigKey}:`, networkConfigElementUri) + } + + expect(isValid).toBeTruthy() + }) + }) + }) + }) + + networksFileNames.forEach((networkFileName) => { + it(`should have a valid 'decimal' value for 'nativeToken'`, () => { + // Given + const networkConfig = networks[networkFileName] + + // When + const { decimals } = networkConfig.network.nativeCoin + + // Then + const isValid = Number.isInteger(decimals) && decimals >= 0 + + if (!isValid) { + console.log(`Invalid value in "${networkFileName}" at network.decimals:`, decimals) + } + + expect(isValid).toBeTruthy() + }) + }) + + networksFileNames.forEach((networkFileName) => { + it(`should have one of 'ETHEREUM_NETWORK' values for 'network.id'`, () => { + // Given + const networkConfig = networks[networkFileName] + + // When + const { id } = networkConfig.network + + // Then + const isValid = ETHEREUM_NETWORK[id] + + if (!isValid) { + console.log(`Invalid value in "${networkFileName}" at network.id:`, id) + } + + expect(isValid).toBeTruthy() + }) + }) + + networksFileNames.forEach((networkFileName) => { + it(`should have a valid CSS color defined for 'network.backgroundColor'`, () => { + // Given + const networkConfig = networks[networkFileName] + + // When + const { backgroundColor } = networkConfig.network + + // Then + const s = new Option().style + s.color = backgroundColor + const isValid = s.color !== '' + + if (!isValid) { + console.log(`Invalid value in "${networkFileName}" at network.backgroundColor:`, backgroundColor) + } + + expect(isValid).toBeTruthy() + }) + + it(`should have a valid CSS color defined for 'network.textColor'`, () => { + // Given + const networkConfig = networks[networkFileName] + + // When + const { textColor } = networkConfig.network + + // Then + const s = new Option().style + s.color = textColor + const isValid = s.color !== '' + + if (!isValid) { + console.log(`Invalid value in "${networkFileName}" at network.textColor:`, textColor) + } + + expect(isValid).toBeTruthy() + }) + }) +}) diff --git a/src/config/networks/energy_web_chain.ts b/src/config/networks/energy_web_chain.ts new file mode 100644 index 00000000..ee705489 --- /dev/null +++ b/src/config/networks/energy_web_chain.ts @@ -0,0 +1,47 @@ +import EwcLogo from 'src/config/assets/token_ewc.svg' +import { EnvironmentSettings, ETHEREUM_NETWORK, NetworkConfig } from 'src/config/networks/network.d' + +const baseConfig: EnvironmentSettings = { + txServiceUrl: 'https://safe-transaction.ewc.gnosis.io/api/v1', + safeAppsUrl: 'https://safe-apps.dev.gnosisdev.com', + gasPriceOracle: { + url: 'https://station.energyweb.org', + gasParameter: 'standard', + }, + rpcServiceUrl: 'https://rpc.energyweb.org', + networkExplorerName: 'Energy web explorer', + networkExplorerUrl: 'https://explorer.energyweb.org', + networkExplorerApiUrl: 'https://explorer.energyweb.org/api', +} + +const mainnet: NetworkConfig = { + environment: { + dev: { + ...baseConfig, + }, + staging: { + ...baseConfig, + safeAppsUrl: 'https://safe-apps.staging.gnosisdev.com', + }, + production: { + ...baseConfig, + safeAppsUrl: 'https://apps.gnosis-safe.io', + }, + }, + network: { + id: ETHEREUM_NETWORK.ENERGY_WEB_CHAIN, + backgroundColor: '#A566FF', + textColor: '#ffffff', + label: 'EWC', + isTestNet: false, + nativeCoin: { + address: '0x000', + name: 'Energy web token', + symbol: 'EWT', + decimals: 18, + logoUri: EwcLogo, + }, + } +} + +export default mainnet diff --git a/src/config/networks/index.ts b/src/config/networks/index.ts new file mode 100644 index 00000000..682b33d3 --- /dev/null +++ b/src/config/networks/index.ts @@ -0,0 +1,15 @@ +import local from './local' +import mainnet from './mainnet' +import rinkeby from './rinkeby' +import xdai from './xdai' +import energy_web_chain from './energy_web_chain' +import volta from './volta' + +export default { + local, + mainnet, + rinkeby, + xdai, + energy_web_chain, + volta +} diff --git a/src/config/networks/local.ts b/src/config/networks/local.ts new file mode 100644 index 00000000..bbb7d15b --- /dev/null +++ b/src/config/networks/local.ts @@ -0,0 +1,40 @@ +import EtherLogo from 'src/config/assets/token_eth.svg' +import { EnvironmentSettings, ETHEREUM_NETWORK, NetworkConfig } from 'src/config/networks/network.d' + +const baseConfig: EnvironmentSettings = { + txServiceUrl: 'http://localhost:8000/api/v1', + relayApiUrl: 'https://safe-relay.staging.gnosisdev.com/api/v1', + safeAppsUrl: 'http://localhost:3002', + gasPriceOracle: { + url: 'https://ethgasstation.info/json/ethgasAPI.json', + gasParameter: 'average', + }, + rpcServiceUrl: 'http://localhost:4447', + networkExplorerName: 'Etherscan', + networkExplorerUrl: 'https://rinkeby.etherscan.io', + networkExplorerApiUrl: 'https://api-rinkeby.etherscan.io/api', +} + +const local: NetworkConfig = { + environment: { + production: { + ...baseConfig, + }, + }, + network: { + id: ETHEREUM_NETWORK.LOCAL, + backgroundColor: '#E8673C', + textColor: '#ffffff', + label: 'LocalRPC', + isTestNet: true, + nativeCoin: { + address: '0x000', + name: 'Ether', + symbol: 'ETH', + decimals: 18, + logoUri: EtherLogo, + }, + }, +} + +export default local diff --git a/src/config/networks/mainnet.ts b/src/config/networks/mainnet.ts new file mode 100644 index 00000000..0a7ca3a4 --- /dev/null +++ b/src/config/networks/mainnet.ts @@ -0,0 +1,48 @@ +import EtherLogo from 'src/config/assets/token_eth.svg' +import { EnvironmentSettings, ETHEREUM_NETWORK, NetworkConfig } from 'src/config/networks/network.d' + +const baseConfig: EnvironmentSettings = { + txServiceUrl: 'https://safe-transaction.mainnet.staging.gnosisdev.com/api/v1', + safeAppsUrl: 'https://safe-apps.dev.gnosisdev.com', + gasPriceOracle: { + url: 'https://ethgasstation.info/json/ethgasAPI.json', + gasParameter: 'average', + }, + rpcServiceUrl: 'https://mainnet.infura.io:443/v3', + networkExplorerName: 'Etherscan', + networkExplorerUrl: 'https://etherscan.io', + networkExplorerApiUrl: 'https://api.etherscan.io/api', +} + +const mainnet: NetworkConfig = { + environment: { + dev: { + ...baseConfig, + }, + staging: { + ...baseConfig, + safeAppsUrl: 'https://safe-apps.staging.gnosisdev.com', + }, + production: { + ...baseConfig, + txServiceUrl: 'https://safe-transaction.mainnet.gnosis.io/api/v1', + safeAppsUrl: 'https://apps.gnosis-safe.io', + }, + }, + network: { + id: ETHEREUM_NETWORK.MAINNET, + backgroundColor: '#E8E7E6', + textColor: '#001428', + label: 'Mainnet', + isTestNet: false, + nativeCoin: { + address: '0x000', + name: 'Ether', + symbol: 'ETH', + decimals: 18, + logoUri: EtherLogo, + }, + } +} + +export default mainnet diff --git a/src/config/networks/network.d.ts b/src/config/networks/network.d.ts new file mode 100644 index 00000000..b6aa270d --- /dev/null +++ b/src/config/networks/network.d.ts @@ -0,0 +1,105 @@ +// matches src/logic/tokens/store/model/token.ts `TokenProps` type + +export enum WALLETS { + METAMASK = 'metamask', + WALLET_CONNECT = 'walletConnect', + TREZOR = 'trezor', + LEDGER = 'ledger', + TRUST = 'trust', + DAPPER = 'dapper', + FORTMATIC = 'fortmatic', + PORTIS = 'portis', + AUTHEREUM = 'authereum', + TORUS = 'torus', + UNILOGIN = 'unilogin', + COINBASE = 'coinbase', + WALLET_LINK = 'walletLink', + OPERA = 'opera', + OPERA_TOUCH = 'operaTouch' +} + +export enum FEATURES { + ERC721 = 'ERC721', + ERC1155 = 'ERC1155', + SAFE_APPS = 'SAFE_APPS', + CONTRACT_INTERACTION = 'CONTRACT_INTERACTION' +} + +type Token = { + address: string + name: string + symbol: string + decimals: number + logoUri?: string +} + +export enum ETHEREUM_NETWORK { + MAINNET = 1, + MORDEN = 2, + ROPSTEN = 3, + RINKEBY = 4, + GOERLI = 5, + KOVAN = 42, + XDAI = 100, + ENERGY_WEB_CHAIN = 246, + VOLTA = 73799, + UNKNOWN = 0, + LOCAL = 4447, +} + +export type NetworkSettings = { + // TODO: id now seems to be unnecessary + id: ETHEREUM_NETWORK, + backgroundColor: string, + textColor: string, + label: string, + isTestNet: boolean, + nativeCoin: Token, +} + +// something around this to display or not some critical sections in the app, depending on the network support +// I listed the ones that may conflict with the network. +// If non is present, all the sections are available. +export type SafeFeatures = FEATURES[] + +export type Wallets = WALLETS[] + +export type GasPriceOracle = { + url: string + // Different gas api providers can use a different name to reflect different gas levels based on tx speed + // For example in ethGasStation for ETHEREUM_MAINNET = safeLow | average | fast + gasParameter: string +} + +type GasPrice = { + gasPrice: number + gasPriceOracle?: GasPriceOracle +} | { + gasPrice?: number + // for infura there's a REST API Token required stored in: `REACT_APP_INFURA_TOKEN` + gasPriceOracle: GasPriceOracle +} + +export type EnvironmentSettings = GasPrice & { + txServiceUrl: string + // Shall we keep a reference to the relay? + relayApiUrl?: string + safeAppsUrl: string + rpcServiceUrl: string + networkExplorerName: string + networkExplorerUrl: string + networkExplorerApiUrl: string +} + +type SafeEnvironments = { + dev?: EnvironmentSettings + staging?: EnvironmentSettings + production: EnvironmentSettings +} + +export interface NetworkConfig { + network: NetworkSettings + disabledFeatures?: SafeFeatures + disabledWallets?: Wallets + environment: SafeEnvironments +} diff --git a/src/config/networks/rinkeby.ts b/src/config/networks/rinkeby.ts new file mode 100644 index 00000000..722e8751 --- /dev/null +++ b/src/config/networks/rinkeby.ts @@ -0,0 +1,48 @@ +import EtherLogo from 'src/config/assets/token_eth.svg' +import { EnvironmentSettings, ETHEREUM_NETWORK, NetworkConfig } from 'src/config/networks/network.d' + +const baseConfig: EnvironmentSettings = { + txServiceUrl: 'https://safe-transaction.staging.gnosisdev.com/api/v1', + safeAppsUrl: 'https://safe-apps.dev.gnosisdev.com', + gasPriceOracle: { + url: 'https://ethgasstation.info/json/ethgasAPI.json', + gasParameter: 'average', + }, + rpcServiceUrl: 'https://rinkeby.infura.io:443/v3', + networkExplorerName: 'Etherscan', + networkExplorerUrl: 'https://rinkeby.etherscan.io', + networkExplorerApiUrl: 'https://api-rinkeby.etherscan.io/api', +} + +const rinkeby: NetworkConfig = { + environment: { + dev: { + ...baseConfig, + }, + staging: { + ...baseConfig, + safeAppsUrl: 'https://safe-apps.staging.gnosisdev.com', + }, + production: { + ...baseConfig, + txServiceUrl: 'https://safe-transaction.rinkeby.gnosis.io/api/v1', + safeAppsUrl: 'https://apps.gnosis-safe.io', + }, + }, + network: { + id: ETHEREUM_NETWORK.RINKEBY, + backgroundColor: '#E8673C', + textColor: '#ffffff', + label: 'Rinkeby', + isTestNet: true, + nativeCoin: { + address: '0x000', + name: 'Ether', + symbol: 'ETH', + decimals: 18, + logoUri: EtherLogo, + }, + }, +} + +export default rinkeby diff --git a/src/config/networks/volta.ts b/src/config/networks/volta.ts new file mode 100644 index 00000000..d8930e6b --- /dev/null +++ b/src/config/networks/volta.ts @@ -0,0 +1,47 @@ +import EwcLogo from 'src/config/assets/token_ewc.svg' +import { EnvironmentSettings, ETHEREUM_NETWORK, NetworkConfig } from 'src/config/networks/network.d' + +const baseConfig: EnvironmentSettings = { + txServiceUrl: 'https://safe-transaction.volta.gnosis.io/api/v1', + safeAppsUrl: 'https://safe-apps.dev.gnosisdev.com', + gasPriceOracle: { + url: 'https://station.energyweb.org', + gasParameter: 'standard', + }, + rpcServiceUrl: 'https://volta-rpc.energyweb.org', + networkExplorerName: 'Volta explorer', + networkExplorerUrl: 'https://volta-explorer.energyweb.org', + networkExplorerApiUrl: 'https://volta-explorer.energyweb.org/api', +} + +const mainnet: NetworkConfig = { + environment: { + dev: { + ...baseConfig, + }, + staging: { + ...baseConfig, + safeAppsUrl: 'https://safe-apps.staging.gnosisdev.com', + }, + production: { + ...baseConfig, + safeAppsUrl: 'https://apps.gnosis-safe.io', + }, + }, + network: { + id: ETHEREUM_NETWORK.VOLTA, + backgroundColor: '#514989', + textColor: '#ffffff', + label: 'Volta', + isTestNet: true, + nativeCoin: { + address: '0x000', + name: 'Energy web token', + symbol: 'EWT', + decimals: 18, + logoUri: EwcLogo, + }, + } +} + +export default mainnet diff --git a/src/config/networks/xdai.ts b/src/config/networks/xdai.ts new file mode 100644 index 00000000..dee4c790 --- /dev/null +++ b/src/config/networks/xdai.ts @@ -0,0 +1,45 @@ +import { EnvironmentSettings, ETHEREUM_NETWORK, WALLETS, NetworkConfig } from 'src/config/networks/network.d' +import xDaiLogo from 'src/config/assets/token_xdai.svg' + +const baseConfig: EnvironmentSettings = { + txServiceUrl: 'https://safe-transaction.xdai.gnosis.io/api/v1', + safeAppsUrl: 'https://safe-apps-xdai.staging.gnosisdev.com', + gasPrice: 1e9, + rpcServiceUrl: 'https://dai.poa.network/', + networkExplorerName: 'Blockscout', + networkExplorerUrl: 'https://blockscout.com/poa/xdai', + networkExplorerApiUrl: 'https://blockscout.com/poa/xdai/api', +} + +const xDai: NetworkConfig = { + environment: { + staging: { + ...baseConfig + }, + production: { + ...baseConfig, + safeAppsUrl: 'https://apps-xdai.gnosis-safe.io', + + }, + }, + network: { + id: ETHEREUM_NETWORK.XDAI, + backgroundColor: '#48A8A6', + textColor: '#ffffff', + label: 'xDai', + isTestNet: false, + nativeCoin: { + address: '0x000', + name: 'xDai', + symbol: 'xDai', + decimals: 18, + logoUri: xDaiLogo, + }, + }, + disabledWallets:[ + WALLETS.TREZOR, + WALLETS.LEDGER + ] +} + +export default xDai diff --git a/src/config/production-mainnet.ts b/src/config/production-mainnet.ts deleted file mode 100644 index d24d20e1..00000000 --- a/src/config/production-mainnet.ts +++ /dev/null @@ -1,11 +0,0 @@ -// -import prodConfig from './production' -import { TX_SERVICE_HOST, RELAY_API_URL } from 'src/config/names' - -const prodMainnetConfig = { - ...prodConfig, - [TX_SERVICE_HOST]: 'https://safe-transaction.mainnet.gnosis.io/api/v1/', - [RELAY_API_URL]: 'https://safe-relay.gnosis.io/api/v1/', -} - -export default prodMainnetConfig diff --git a/src/config/production.ts b/src/config/production.ts deleted file mode 100644 index 246fcb9c..00000000 --- a/src/config/production.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { TX_SERVICE_HOST, SIGNATURES_VIA_METAMASK, RELAY_API_URL, SAFE_APPS_URL } from 'src/config/names' - -const prodConfig = { - [TX_SERVICE_HOST]: 'https://safe-transaction.rinkeby.gnosis.io/api/v1/', - [SIGNATURES_VIA_METAMASK]: false, - [RELAY_API_URL]: 'https://safe-relay.rinkeby.gnosis.io/api/v1/', - [SAFE_APPS_URL]: 'https://apps.gnosis-safe.io/' -} - -export default prodConfig diff --git a/src/config/staging-mainnet.ts b/src/config/staging-mainnet.ts deleted file mode 100644 index 08f225fa..00000000 --- a/src/config/staging-mainnet.ts +++ /dev/null @@ -1,11 +0,0 @@ -// -import stagingConfig from './staging' -import { TX_SERVICE_HOST, RELAY_API_URL } from 'src/config/names' - -const stagingMainnetConfig = { - ...stagingConfig, - [TX_SERVICE_HOST]: 'https://safe-transaction.mainnet.staging.gnosisdev.com/api/v1/', - [RELAY_API_URL]: 'https://safe-relay.mainnet.staging.gnosisdev.com/api/v1/', -} - -export default stagingMainnetConfig diff --git a/src/config/staging.ts b/src/config/staging.ts deleted file mode 100644 index 61b4ebca..00000000 --- a/src/config/staging.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { TX_SERVICE_HOST, SIGNATURES_VIA_METAMASK, RELAY_API_URL, SAFE_APPS_URL } from 'src/config/names' - -const stagingConfig = { - [TX_SERVICE_HOST]: 'https://safe-transaction.staging.gnosisdev.com/api/v1/', - [SIGNATURES_VIA_METAMASK]: false, - [RELAY_API_URL]: 'https://safe-relay.staging.gnosisdev.com/api/v1/', - [SAFE_APPS_URL]: 'https://safe-apps.staging.gnosisdev.com' -} - -export default stagingConfig diff --git a/src/config/testing.ts b/src/config/testing.ts deleted file mode 100644 index cce8aa96..00000000 --- a/src/config/testing.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { TX_SERVICE_HOST, SIGNATURES_VIA_METAMASK, RELAY_API_URL, SAFE_APPS_URL } from 'src/config/names' - -const testConfig = { - [TX_SERVICE_HOST]: 'http://localhost:8000/api/v1/', - [SIGNATURES_VIA_METAMASK]: false, - [RELAY_API_URL]: 'https://safe-relay.staging.gnosisdev.com/api/v1', - [SAFE_APPS_URL]: 'http://localhost:3002/' -} - -export default testConfig diff --git a/src/logic/addressBook/store/middleware/addressBookMiddleware.ts b/src/logic/addressBook/store/middleware/addressBookMiddleware.ts index fb7075dd..0d982ace 100644 --- a/src/logic/addressBook/store/middleware/addressBookMiddleware.ts +++ b/src/logic/addressBook/store/middleware/addressBookMiddleware.ts @@ -7,6 +7,9 @@ import { saveAddressBook } from 'src/logic/addressBook/utils' import { enhanceSnackbarForAction, getNotificationsFromTxType } from 'src/logic/notifications' import enqueueSnackbar from 'src/logic/notifications/store/actions/enqueueSnackbar' import { TX_NOTIFICATION_TYPES } from 'src/logic/safe/transactions' +import { safesListSelector } from 'src/logic/safe/store/selectors' +import { sameAddress } from 'src/logic/wallets/ethAddresses' +import updateSafe from 'src/logic/safe/store/actions/updateSafe' const watchedActions = [ADD_ENTRY, REMOVE_ENTRY, UPDATE_ENTRY, ADD_OR_UPDATE_ENTRY] @@ -17,6 +20,7 @@ const addressBookMiddleware = (store) => (next) => async (action) => { const state = store.getState() const { dispatch } = store const addressBook = addressBookSelector(state) + const safes = safesListSelector(state) if (addressBook.length) { await saveAddressBook(addressBook) } @@ -36,8 +40,13 @@ const addressBookMiddleware = (store) => (next) => async (action) => { break } case UPDATE_ENTRY: { + const { entry } = action.payload const notification = getNotificationsFromTxType(TX_NOTIFICATION_TYPES.ADDRESSBOOK_EDIT_ENTRY) dispatch(enqueueSnackbar(enhanceSnackbarForAction(notification.afterExecution.noMoreConfirmationsNeeded))) + const safeFound = safes.find((safe) => sameAddress(safe.address, entry.address)) + if (safeFound) { + dispatch(updateSafe({ address: safeFound.address, name: entry.name })) + } break } default: diff --git a/src/logic/addressBook/store/reducer/addressBook.ts b/src/logic/addressBook/store/reducer/addressBook.ts index ad23f4fd..a59e2ab0 100644 --- a/src/logic/addressBook/store/reducer/addressBook.ts +++ b/src/logic/addressBook/store/reducer/addressBook.ts @@ -29,9 +29,7 @@ export default handleActions( const entryFound = state.find((oldEntry) => oldEntry.address === entry.address) - // Only adds entries with valid names - const validName = getValidAddressBookName(entry.name) - if (!entryFound && validName) { + if (!entryFound) { state.push(entry) } return state diff --git a/src/logic/collectibles/sources/Gnosis.ts b/src/logic/collectibles/sources/Gnosis.ts new file mode 100644 index 00000000..c916a653 --- /dev/null +++ b/src/logic/collectibles/sources/Gnosis.ts @@ -0,0 +1,106 @@ +import { RateLimit } from 'async-sema' + +import { Collectibles, NFTAsset, NFTAssets, NFTTokens } from 'src/logic/collectibles/sources/collectibles.d' +import NFTIcon from 'src/routes/safe/components/Balances/assets/nft_icon.png' +import { fetchErc20AndErc721AssetsList, fetchSafeCollectibles } from 'src/logic/tokens/api' +import { TokenResult } from 'src/logic/tokens/api/fetchErc20AndErc721AssetsList' +import { CollectibleResult } from 'src/logic/tokens/api/fetchSafeCollectibles' + +type FetchResult = { + erc721Assets: TokenResult[] + erc721Tokens: CollectibleResult[] +} + +class Gnosis { + _rateLimit = async (): Promise => {} + + _fetch = async (safeAddress: string): Promise => { + const collectibles: FetchResult = { + erc721Assets: [], + erc721Tokens: [], + } + + try { + const { + data: { results: assets = [] }, + } = await fetchErc20AndErc721AssetsList() + collectibles.erc721Assets = assets.filter((token) => token.type.toLowerCase() === 'erc721') + } catch (e) { + console.error('no erc721 assets could be fetched', e) + } + + try { + const { data: tokens = [] } = await fetchSafeCollectibles(safeAddress) + collectibles.erc721Tokens = tokens + } catch (e) { + console.error('no erc721 tokens for the current safe', e) + } + + return collectibles + } + + /** + * OpenSea class constructor + * @param {object} options + * @param {number} options.rps - requests per second + */ + constructor(options: { rps: number }) { + // eslint-disable-next-line no-underscore-dangle + this._rateLimit = RateLimit(options.rps, { timeUnit: 60 * 1000, uniformDistribution: true }) + } + + static extractAssets(assets: TokenResult[], nftTokens: NFTTokens): NFTAssets { + const extractNFTAsset = (asset: TokenResult): NFTAsset => { + const numberOfTokens = nftTokens.filter(({ assetAddress }) => assetAddress === asset.address).length + + return { + address: asset.address, + description: asset.name, + image: asset.logoUri || NFTIcon, + name: asset.name, + numberOfTokens, + slug: `${asset.address}_${asset.name}`, + symbol: asset.symbol, + } + } + + return assets.reduce((acc, asset) => { + const address = asset.address + + if (acc[address] === undefined) { + acc[address] = extractNFTAsset(asset) + } + + return acc + }, {}) + } + + static extractTokens(tokens: CollectibleResult[]): NFTTokens { + return tokens.map((token) => ({ + assetAddress: token.address, + color: 'red', + description: token.description || '', + image: token.imageUri || NFTIcon, + name: token.name || '', + tokenId: token.id, + })) + } + + /** + * Fetches from OpenSea the list of collectibles, grouped by category, + * for the provided Safe Address in the specified Network + * @param {string} safeAddress + * @returns {Promise} + */ + async fetchCollectibles(safeAddress: string): Promise { + const { erc721Assets, erc721Tokens } = await this._fetch(safeAddress) + const nftTokens = Gnosis.extractTokens(erc721Tokens) + + return { + nftTokens, + nftAssets: Gnosis.extractAssets(erc721Assets, nftTokens), + } + } +} + +export default Gnosis diff --git a/src/logic/collectibles/sources/OpenSea.ts b/src/logic/collectibles/sources/OpenSea.ts index d626e825..97661b76 100644 --- a/src/logic/collectibles/sources/OpenSea.ts +++ b/src/logic/collectibles/sources/OpenSea.ts @@ -1,61 +1,11 @@ import { RateLimit } from 'async-sema' +import { getNetworkId } from 'src/config' -import { ETHEREUM_NETWORK } from 'src/logic/wallets/getWeb3' +import { ETHEREUM_NETWORK } from 'src/config/networks/network.d' +import { Collectibles, NFTAssets, NFTTokens, OpenSeaAssets } from 'src/logic/collectibles/sources/collectibles.d' import NFTIcon from 'src/routes/safe/components/Balances/assets/nft_icon.png' import { OPENSEA_API_KEY } from 'src/utils/constants' -export interface OpenSeaAssetContract { - address: string - name: string - image_url: string - symbol: string -} - -export interface OpenSeaCollection { - name: string - slug: string -} - -export interface OpenSeaAsset { - asset_contract: OpenSeaAssetContract - background_color: string - collection: OpenSeaCollection - description: string - image_thumbnail_url: string - name: string - token_id: string -} - -export type OpenSeaAssets = Array - -export interface NFTAsset { - address: string - assetContract: OpenSeaAssetContract - collection: OpenSeaCollection - description: string - image: string - name: string - numberOfTokens: number - slug: string - symbol: string -} -export type NFTAssets = Record - -export interface NFTToken { - assetAddress: string - color: string - description: string - image: string - name: string - tokenId: number | string -} -export type NFTTokens = Array - -export interface Collectibles { - nftAssets: NFTAssets - nftTokens: NFTTokens -} - class OpenSea { _rateLimit = async (): Promise => {} @@ -133,14 +83,11 @@ class OpenSea { * Fetches from OpenSea the list of collectibles, grouped by category, * for the provided Safe Address in the specified Network * @param {string} safeAddress - * @param {string} network * @returns {Promise} */ - async fetchAllUserCollectiblesByCategoryAsync(safeAddress: string, network: string): Promise { - // eslint-disable-next-line no-underscore-dangle - const metadataSourceUrl = this._endpointsUrls[network] + async fetchCollectibles(safeAddress: string): Promise { + const metadataSourceUrl = this._endpointsUrls[getNetworkId()] const url = `${metadataSourceUrl}/assets/?owner=${safeAddress}` - // eslint-disable-next-line no-underscore-dangle const assetsResponse = await this._fetch(url) const assetsResponseJson = await assetsResponse.json() return OpenSea.extractCollectiblesInfo(assetsResponseJson) diff --git a/src/logic/collectibles/sources/collectibles.d.ts b/src/logic/collectibles/sources/collectibles.d.ts new file mode 100644 index 00000000..88edabf8 --- /dev/null +++ b/src/logic/collectibles/sources/collectibles.d.ts @@ -0,0 +1,53 @@ +export interface OpenSeaAssetContract { + address: string + name: string + image_url: string + symbol: string +} + +export interface OpenSeaCollection { + name: string + slug: string +} + +export interface OpenSeaAsset { + asset_contract: OpenSeaAssetContract + background_color: string + collection: OpenSeaCollection + description: string + image_thumbnail_url: string + name: string + token_id: string +} + +export type OpenSeaAssets = Array + +export interface NFTAsset { + address: string + assetContract?: OpenSeaAssetContract + collection?: OpenSeaCollection + description: string + image: string + name: string + numberOfTokens: number + slug: string + symbol: string +} + +export type NFTAssets = Record + +export interface NFTToken { + assetAddress: string + color: string + description: string + image: string + name: string + tokenId: number | string +} + +export type NFTTokens = Array + +export interface Collectibles { + nftAssets: NFTAssets + nftTokens: NFTTokens +} diff --git a/src/logic/collectibles/sources/index.ts b/src/logic/collectibles/sources/index.ts index 14636bd2..439cf05f 100644 --- a/src/logic/collectibles/sources/index.ts +++ b/src/logic/collectibles/sources/index.ts @@ -1,13 +1,15 @@ import MockedOpenSea from 'src/logic/collectibles/sources/MockedOpenSea' import OpenSea from 'src/logic/collectibles/sources/OpenSea' +import Gnosis from 'src/logic/collectibles/sources/Gnosis' import { COLLECTIBLES_SOURCE } from 'src/utils/constants' const SOURCES = { opensea: new OpenSea({ rps: 4 }), + gnosis: new Gnosis({ rps: 4 }), mockedopensea: new MockedOpenSea({ rps: 4 }), } type Sources = typeof SOURCES -export const getConfiguredSource = (): Sources['opensea'] | Sources['mockedopensea'] => +export const getConfiguredSource = (): Sources['opensea'] | Sources['mockedopensea'] | Sources['gnosis'] => SOURCES[COLLECTIBLES_SOURCE.toLowerCase()] diff --git a/src/logic/collectibles/store/actions/fetchCollectibles.ts b/src/logic/collectibles/store/actions/fetchCollectibles.ts index c87e51df..6c70bba4 100644 --- a/src/logic/collectibles/store/actions/fetchCollectibles.ts +++ b/src/logic/collectibles/store/actions/fetchCollectibles.ts @@ -1,15 +1,13 @@ import { batch } from 'react-redux' - -import { getNetwork } from 'src/config' -import { getConfiguredSource } from 'src/logic/collectibles/sources' -import { addNftAssets, addNftTokens } from 'src/logic/collectibles/store/actions/addCollectibles' import { Dispatch } from 'redux' -const fetchCollectibles = (safeAddress: string) => async (dispatch: Dispatch): Promise => { +import { getConfiguredSource } from 'src/logic/collectibles/sources' +import { addNftAssets, addNftTokens } from 'src/logic/collectibles/store/actions/addCollectibles' + +export const fetchCollectibles = (safeAddress: string) => async (dispatch: Dispatch): Promise => { try { - const network = getNetwork() const source = getConfiguredSource() - const collectibles = await source.fetchAllUserCollectiblesByCategoryAsync(safeAddress, network) + const collectibles = await source.fetchCollectibles(safeAddress) batch(() => { dispatch(addNftAssets(collectibles.nftAssets)) @@ -19,5 +17,3 @@ const fetchCollectibles = (safeAddress: string) => async (dispatch: Dispatch): P console.log('Error fetching collectibles:', error) } } - -export default fetchCollectibles diff --git a/src/logic/collectibles/store/selectors/index.ts b/src/logic/collectibles/store/selectors/index.ts index 3829eb00..e8940dcc 100644 --- a/src/logic/collectibles/store/selectors/index.ts +++ b/src/logic/collectibles/store/selectors/index.ts @@ -1,22 +1,33 @@ import { createSelector } from 'reselect' -import { NFTAsset, NFTAssets, NFTTokens } from 'src/logic/collectibles/sources/OpenSea' +import { NFTAsset, NFTAssets, NFTTokens } from 'src/logic/collectibles/sources/collectibles.d' import { AppReduxState } from 'src/store' import { NFT_ASSETS_REDUCER_ID, NFT_TOKENS_REDUCER_ID } from 'src/logic/collectibles/store/reducer/collectibles' import { safeActiveAssetsSelector } from 'src/logic/safe/store/selectors' -export const nftAssetsSelector = (state: AppReduxState): NFTAssets => state[NFT_ASSETS_REDUCER_ID] -export const nftTokensSelector = (state: AppReduxState): NFTTokens => state[NFT_TOKENS_REDUCER_ID] +export const nftAssets = (state: AppReduxState): NFTAssets => state[NFT_ASSETS_REDUCER_ID] +export const nftTokens = (state: AppReduxState): NFTTokens => state[NFT_TOKENS_REDUCER_ID] -export const nftAssetsListSelector = createSelector(nftAssetsSelector, (assets): NFTAsset[] => { +export const nftAssetsSelector = createSelector(nftAssets, (assets) => assets) + +export const nftTokensSelector = createSelector(nftTokens, (tokens) => tokens) + +export const nftAssetsListSelector = createSelector(nftAssets, (assets): NFTAsset[] => { return assets ? Object.values(assets) : [] }) +export const availableNftAssetsAddresses = createSelector(nftTokensSelector, (userNftTokens): string[] => { + return Array.from(new Set(userNftTokens.map((nftToken) => nftToken.assetAddress))) +}) + export const activeNftAssetsListSelector = createSelector( nftAssetsListSelector, safeActiveAssetsSelector, - (assets, activeAssetsList): NFTAsset[] => { - return assets.filter(({ address }) => activeAssetsList.has(address)) + availableNftAssetsAddresses, + (assets, activeAssetsList, availableNftAssetsAddresses): NFTAsset[] => { + return assets + .filter(({ address }) => activeAssetsList.has(address)) + .filter(({ address }) => availableNftAssetsAddresses.includes(address)) }, ) diff --git a/src/logic/contractInteraction/sources/EtherscanService.ts b/src/logic/contractInteraction/sources/EtherscanService.ts deleted file mode 100644 index d9e7bfc5..00000000 --- a/src/logic/contractInteraction/sources/EtherscanService.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { RateLimit } from 'async-sema' -import memoize from 'lodash.memoize' - -import { ETHEREUM_NETWORK } from 'src/logic/wallets/getWeb3' -import { ETHERSCAN_API_KEY } from 'src/utils/constants' - -class EtherscanService { - _rateLimit = async () => {} - - _endpointsUrls = { - [ETHEREUM_NETWORK.MAINNET]: 'https://api.etherscan.io/api', - [ETHEREUM_NETWORK.RINKEBY]: 'https://api-rinkeby.etherscan.io/api', - } - - _fetch = memoize( - async (url: string, contractAddress: string) => { - let params: any = { - module: 'contract', - action: 'getAbi', - address: contractAddress, - } - - if (ETHERSCAN_API_KEY) { - const apiKey = ETHERSCAN_API_KEY - params = { ...params, apiKey } - } - - const response = await fetch(`${url}?${new URLSearchParams(params)}`) - - if (!response.ok) { - return { status: 0, result: [] } - } - - return response.json() - }, - (url, contractAddress) => `${url}_${contractAddress}`, - ) - - constructor(options) { - this._rateLimit = RateLimit(options.rps) - } - - async getContractABI(contractAddress, network) { - const etherscanUrl = this._endpointsUrls[network] - try { - const { result, status } = await this._fetch(etherscanUrl, contractAddress) - - if (status === '0') { - return [] - } - - return result - } catch (e) { - console.error('Failed to retrieve ABI', e) - return undefined - } - } -} - -export default EtherscanService diff --git a/src/logic/contractInteraction/sources/index.ts b/src/logic/contractInteraction/sources/index.ts deleted file mode 100644 index b5bc4f3f..00000000 --- a/src/logic/contractInteraction/sources/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -import EtherscanService from 'src/logic/contractInteraction/sources/EtherscanService' - -const sources = { - etherscan: new EtherscanService({ rps: 4 }), -} - -export const getConfiguredSource = () => sources['etherscan'] diff --git a/src/logic/contracts/generateBatchRequests.ts b/src/logic/contracts/generateBatchRequests.ts index 2d48979b..adf327b8 100644 --- a/src/logic/contracts/generateBatchRequests.ts +++ b/src/logic/contracts/generateBatchRequests.ts @@ -1,4 +1,6 @@ import { web3ReadOnly as web3 } from 'src/logic/wallets/getWeb3' +import { BatchRequest } from 'web3-core' +import { AbiItem } from 'web3-utils' /** * Generates a batch request for grouping RPC calls @@ -10,23 +12,33 @@ import { web3ReadOnly as web3 } from 'src/logic/wallets/getWeb3' * @param {array<{ args: [any], method: string, type: 'eth'|undefined } | string>} args.methods - methods to be called * @returns {Promise<[*]>} */ -const generateBatchRequests = ({ abi, address, batch, context, methods }: any): any => { - const contractInstance: any = new web3.eth.Contract(abi, address) +type MethodsArgsType = Array + + interface Props { + abi: AbiItem[] + address: string + batch?: BatchRequest + context?: unknown + methods: Array + } + +const generateBatchRequests = ({ abi, address, batch, context, methods }: Props): Promise => { + const contractInstance = new web3.eth.Contract(abi, address) const localBatch = new web3.BatchRequest() const values = methods.map((methodObject) => { - let method, type, args = [] + let method, type, args: MethodsArgsType = [] if (typeof methodObject === 'string') { method = methodObject } else { - ;({ method, type, args = [] } = methodObject) + ({ method, type, args } = methodObject) } return new Promise((resolve) => { const resolver = (error, result) => { if (error) { - resolve(null) + resolve() } else { resolve(result) } @@ -43,7 +55,8 @@ const generateBatchRequests = ({ abi, address, batch, context, methods }: any): // If batch was provided add to external batch batch ? batch.add(request) : localBatch.add(request) } catch (e) { - resolve(null) + console.warn('There was an error trying to batch request from web3.', e) + resolve() } }) }) @@ -54,9 +67,8 @@ const generateBatchRequests = ({ abi, address, batch, context, methods }: any): // in the outside function where the batch object is created. !batch && localBatch.execute() - const returnValues = context ? [context, ...values] : values - - return Promise.all(returnValues) + // @ts-ignore + return Promise.all([context, ...values]) } export default generateBatchRequests diff --git a/src/logic/contracts/safeContracts.ts b/src/logic/contracts/safeContracts.ts index 68d971f9..b9673cf9 100644 --- a/src/logic/contracts/safeContracts.ts +++ b/src/logic/contracts/safeContracts.ts @@ -1,17 +1,17 @@ import { AbiItem } from 'web3-utils' -import contract from 'truffle-contract' -import Web3 from 'web3' -import ProxyFactorySol from '@gnosis.pm/safe-contracts/build/contracts/GnosisSafeProxyFactory.json' import GnosisSafeSol from '@gnosis.pm/safe-contracts/build/contracts/GnosisSafe.json' -import SafeProxy from '@gnosis.pm/safe-contracts/build/contracts/GnosisSafeProxy.json' -import { ensureOnce } from 'src/utils/singleton' import memoize from 'lodash.memoize' -import { getWeb3, getNetworkIdFrom } from 'src/logic/wallets/getWeb3' -import { calculateGasOf, calculateGasPrice } from 'src/logic/wallets/ethTransactions' -import { ZERO_ADDRESS } from 'src/logic/wallets/ethAddresses' +import ProxyFactorySol from '@gnosis.pm/safe-contracts/build/contracts/GnosisSafeProxyFactory.json' +import SafeProxy from '@gnosis.pm/safe-contracts/build/contracts/GnosisSafeProxy.json' +import Web3 from 'web3' + +import { ETHEREUM_NETWORK } from 'src/config/networks/network.d' import { isProxyCode } from 'src/logic/contracts/historicProxyCode' -import { GnosisSafeProxyFactory } from 'src/types/contracts/GnosisSafeProxyFactory.d'; +import { ZERO_ADDRESS } from 'src/logic/wallets/ethAddresses' +import { calculateGasOf, calculateGasPrice } from 'src/logic/wallets/ethTransactions' +import { getWeb3, getNetworkIdFrom } from 'src/logic/wallets/getWeb3' import { GnosisSafe } from 'src/types/contracts/GnosisSafe.d' +import { GnosisSafeProxyFactory } from 'src/types/contracts/GnosisSafeProxyFactory.d' export const SENTINEL_ADDRESS = '0x0000000000000000000000000000000000000001' export const MULTI_SEND_ADDRESS = '0x8d29be29923b68abfdd21e541b9374737b49cdad' @@ -20,24 +20,39 @@ export const DEFAULT_FALLBACK_HANDLER_ADDRESS = '0xd5D82B6aDDc9027B22dCA772Aa68D export const SAFE_MASTER_COPY_ADDRESS_V10 = '0xb6029EA3B2c51D09a50B53CA8012FeEB05bDa35A' -let proxyFactoryMaster -let safeMaster +let proxyFactoryMaster: GnosisSafeProxyFactory +let safeMaster: GnosisSafe -const createGnosisSafeContract = (web3: Web3) => { - const gnosisSafe = contract(GnosisSafeSol) - gnosisSafe.setProvider(web3.currentProvider) - - return gnosisSafe +/** + * Creates a Contract instance of the GnosisSafe contract + * @param {Web3} web3 + * @param {ETHEREUM_NETWORK} networkId + */ +const createGnosisSafeContract = (web3: Web3, networkId: ETHEREUM_NETWORK) => { + const networks = GnosisSafeSol.networks + // TODO: this may not be the most scalable approach, + // but up until v1.2.0 the address is the same for all the networks. + // So, if we can't find the network in the Contract artifact, we fallback to MAINNET. + const contractAddress = networks[networkId]?.address ?? networks[ETHEREUM_NETWORK.MAINNET].address + return new web3.eth.Contract(GnosisSafeSol.abi as AbiItem[], contractAddress) as unknown as GnosisSafe } -const createProxyFactoryContract = (web3: Web3, networkId: number): GnosisSafeProxyFactory => { - const contractAddress = ProxyFactorySol.networks[networkId].address - const proxyFactory = new web3.eth.Contract(ProxyFactorySol.abi as AbiItem[], contractAddress) as unknown as GnosisSafeProxyFactory - - return proxyFactory +/** + * Creates a Contract instance of the GnosisSafeProxyFactory contract + * @param {Web3} web3 + * @param {ETHEREUM_NETWORK} networkId + */ +const createProxyFactoryContract = (web3: Web3, networkId: ETHEREUM_NETWORK): GnosisSafeProxyFactory => { + const networks = ProxyFactorySol.networks + // TODO: this may not be the most scalable approach, + // but up until v1.2.0 the address is the same for all the networks. + // So, if we can't find the network in the Contract artifact, we fallback to MAINNET. + const contractAddress = networks[networkId]?.address ?? networks[ETHEREUM_NETWORK.MAINNET].address + return new web3.eth.Contract(ProxyFactorySol.abi as AbiItem[], contractAddress) as unknown as GnosisSafeProxyFactory } export const getGnosisSafeContract = memoize(createGnosisSafeContract) + const getCreateProxyFactoryContract = memoize(createProxyFactoryContract) const instantiateMasterCopies = async () => { @@ -47,25 +62,11 @@ const instantiateMasterCopies = async () => { // Create ProxyFactory Master Copy proxyFactoryMaster = getCreateProxyFactoryContract(web3, networkId) - // Initialize Safe master copy - const GnosisSafe = getGnosisSafeContract(web3) - safeMaster = await GnosisSafe.deployed() + // Create Safe Master copy + safeMaster = getGnosisSafeContract(web3, networkId) } -// ONLY USED IN TEST ENVIRONMENT -const createMasterCopies = async () => { - const web3 = getWeb3() - const accounts = await web3.eth.getAccounts() - const userAccount = accounts[0] - - const ProxyFactory = getCreateProxyFactoryContract(web3, 4441) - proxyFactoryMaster = await ProxyFactory.deploy({ data: GnosisSafeSol.bytecode }).send({ from: userAccount, gas: 5000000 }) - - const GnosisSafe = getGnosisSafeContract(web3) - safeMaster = await GnosisSafe.new({ from: userAccount, gas: '7000000' }) -} - -export const initContracts = process.env.NODE_ENV === 'test' ? ensureOnce(createMasterCopies) : instantiateMasterCopies +export const initContracts = instantiateMasterCopies export const getSafeMasterContract = async () => { await initContracts() @@ -74,11 +75,11 @@ export const getSafeMasterContract = async () => { } export const getSafeDeploymentTransaction = (safeAccounts, numConfirmations) => { - const gnosisSafeData = safeMaster.contract.methods + const gnosisSafeData = safeMaster.methods .setup(safeAccounts, numConfirmations, ZERO_ADDRESS, '0x', DEFAULT_FALLBACK_HANDLER_ADDRESS, ZERO_ADDRESS, 0, ZERO_ADDRESS) .encodeABI() - return proxyFactoryMaster.methods.createProxy(safeMaster.address, gnosisSafeData) + return proxyFactoryMaster.methods.createProxy(safeMaster.options.address, gnosisSafeData) } export const estimateGasForDeployingSafe = async ( @@ -86,13 +87,13 @@ export const estimateGasForDeployingSafe = async ( numConfirmations, userAccount, ) => { - const gnosisSafeData = await safeMaster.contract.methods + const gnosisSafeData = await safeMaster.methods .setup(safeAccounts, numConfirmations, ZERO_ADDRESS, '0x', DEFAULT_FALLBACK_HANDLER_ADDRESS, ZERO_ADDRESS, 0, ZERO_ADDRESS) .encodeABI() const proxyFactoryData = proxyFactoryMaster.methods - .createProxy(safeMaster.address, gnosisSafeData) + .createProxy(safeMaster.options.address, gnosisSafeData) .encodeABI() - const gas = await calculateGasOf(proxyFactoryData, userAccount, proxyFactoryMaster.address) + const gas = await calculateGasOf(proxyFactoryData, userAccount, proxyFactoryMaster.options.address) const gasPrice = await calculateGasPrice() return gas * parseInt(gasPrice, 10) diff --git a/src/logic/cookies/utils/index.ts b/src/logic/cookies/utils/index.ts index 08313a64..7b9f8ce7 100644 --- a/src/logic/cookies/utils/index.ts +++ b/src/logic/cookies/utils/index.ts @@ -1,8 +1,8 @@ import Cookies from 'js-cookie' -import { getNetwork } from 'src/config' +import { getNetworkName } from 'src/config' -const PREFIX = `v1_${getNetwork()}` +const PREFIX = `v1_${getNetworkName()}` export const loadFromCookie = async (key) => { try { diff --git a/src/logic/currencyValues/__tests__/fetchSafeTokens.test.ts b/src/logic/currencyValues/__tests__/fetchSafeTokens.test.ts index 32bf362f..3ed5283e 100644 --- a/src/logic/currencyValues/__tests__/fetchSafeTokens.test.ts +++ b/src/logic/currencyValues/__tests__/fetchSafeTokens.test.ts @@ -1,7 +1,8 @@ -import { aNewStore } from 'src/store' -import fetchTokenCurrenciesBalances from 'src/logic/currencyValues/api/fetchTokenCurrenciesBalances' import axios from 'axios' -import { getTxServiceHost } from 'src/config' + +import { getSafeServiceBaseUrl } from 'src/config' +import { fetchTokenCurrenciesBalances } from 'src/logic/currencyValues/api/fetchTokenCurrenciesBalances' +import { aNewStore } from 'src/store' jest.mock('axios') describe('fetchTokenCurrenciesBalances', () => { @@ -19,26 +20,28 @@ describe('fetchTokenCurrenciesBalances', () => { // given const expectedResult = [ { - balance: '849890000000000000', - balanceUsd: '337.2449', - token: null, tokenAddress: null, - usdConversion: '396.81', + token: null, + balance: '849890000000000000', + fiatBalance: '337.2449', + fiatConversion: '396.81', + fiatCode: 'USD', }, { - balance: '24698677800000000000', - balanceUsd: '29.3432', + tokenAddress: '0x5592EC0cfb4dbc12D3aB100b257153436a1f0FEa', token: { name: 'Dai', symbol: 'DAI', decimals: 18, logoUri: 'https://gnosis-safe-token-logos.s3.amazonaws.com/0x5592EC0cfb4dbc12D3aB100b257153436a1f0FEa.png', }, - tokenAddress: '0x5592EC0cfb4dbc12D3aB100b257153436a1f0FEa', - usdConversion: '1.188', + balance: '24698677800000000000', + fiatBalance: '29.3432', + fiatConversion: '1.188', + fiatCode: 'USD', }, ] - const apiUrl = getTxServiceHost() + const apiUrl = getSafeServiceBaseUrl(safeAddress) // @ts-ignore axios.get.mockImplementationOnce(() => Promise.resolve(expectedResult)) @@ -49,8 +52,6 @@ describe('fetchTokenCurrenciesBalances', () => { // then expect(result).toStrictEqual(expectedResult) expect(axios.get).toHaveBeenCalled() - expect(axios.get).toBeCalledWith(`${apiUrl}safes/${safeAddress}/balances/usd/?exclude_spam=${excludeSpamTokens}`, { - params: { limit: 3000 }, - }) + expect(axios.get).toBeCalledWith(`${apiUrl}/balances/usd/?exclude_spam=${excludeSpamTokens}`) }) }) diff --git a/src/logic/currencyValues/api/fetchCurrenciesRates.ts b/src/logic/currencyValues/api/fetchCurrenciesRates.ts index 00e2c48a..6f3c751d 100644 --- a/src/logic/currencyValues/api/fetchCurrenciesRates.ts +++ b/src/logic/currencyValues/api/fetchCurrenciesRates.ts @@ -1,31 +1,32 @@ import axios from 'axios' - -import { getExchangeRatesUrl } from 'src/config' -import { AVAILABLE_CURRENCIES } from '../store/model/currencyValues' -import fetchTokenCurrenciesBalances from './fetchTokenCurrenciesBalances' import BigNumber from 'bignumber.js' +import { EXCHANGE_RATE_URL } from 'src/utils/constants' +import { fetchTokenCurrenciesBalances } from './fetchTokenCurrenciesBalances' +import { sameString } from 'src/utils/strings' +import { AVAILABLE_CURRENCIES } from '../store/model/currencyValues' + const fetchCurrenciesRates = async ( - baseCurrency: AVAILABLE_CURRENCIES, - targetCurrencyValue: AVAILABLE_CURRENCIES, + baseCurrency: string, + targetCurrencyValue: string, safeAddress: string, ): Promise => { let rate = 0 - - if (targetCurrencyValue === AVAILABLE_CURRENCIES.ETH) { + if (sameString(targetCurrencyValue, AVAILABLE_CURRENCIES.NETWORK)) { try { const result = await fetchTokenCurrenciesBalances(safeAddress) if (result?.data?.length) { - rate = new BigNumber(1).div(result.data[0].usdConversion).toNumber() + rate = new BigNumber(1).div(result.data[0].fiatConversion).toNumber() } } catch (error) { - console.error('Fetching ETH data from the relayer errored', error) + console.error(`Fetching ${AVAILABLE_CURRENCIES.NETWORK} data from the relayer errored`, error) } return rate } + // National currencies try { - const url = `${getExchangeRatesUrl()}?base=${baseCurrency}&symbols=${targetCurrencyValue}` + const url = `${EXCHANGE_RATE_URL}?base=${baseCurrency}&symbols=${targetCurrencyValue}` const result = await axios.get(url) if (result?.data) { const { rates } = result.data diff --git a/src/logic/currencyValues/api/fetchTokenCurrenciesBalances.ts b/src/logic/currencyValues/api/fetchTokenCurrenciesBalances.ts index c2804708..94b06c17 100644 --- a/src/logic/currencyValues/api/fetchTokenCurrenciesBalances.ts +++ b/src/logic/currencyValues/api/fetchTokenCurrenciesBalances.ts @@ -1,28 +1,22 @@ import axios, { AxiosResponse } from 'axios' -import { getTxServiceHost } from 'src/config' +import { getSafeServiceBaseUrl } from 'src/config' import { TokenProps } from 'src/logic/tokens/store/model/token' export type BalanceEndpoint = { - balance: string - balanceUsd: string tokenAddress: string token?: TokenProps - usdConversion: string + balance: string + fiatBalance: string + fiatConversion: string + fiatCode: string } -const fetchTokenCurrenciesBalances = ( +export const fetchTokenCurrenciesBalances = ( safeAddress: string, excludeSpamTokens = true, ): Promise> => { - const apiUrl = getTxServiceHost() - const url = `${apiUrl}safes/${safeAddress}/balances/usd/?exclude_spam=${excludeSpamTokens}` + const url = `${getSafeServiceBaseUrl(safeAddress)}/balances/usd/?exclude_spam=${excludeSpamTokens}` - return axios.get(url, { - params: { - limit: 3000, - }, - }) + return axios.get(url) } - -export default fetchTokenCurrenciesBalances diff --git a/src/logic/currencyValues/store/actions/fetchCurrencyRate.ts b/src/logic/currencyValues/store/actions/fetchCurrencyRate.ts index 72f668c6..75fe3088 100644 --- a/src/logic/currencyValues/store/actions/fetchCurrencyRate.ts +++ b/src/logic/currencyValues/store/actions/fetchCurrencyRate.ts @@ -3,7 +3,7 @@ import { setCurrencyRate } from 'src/logic/currencyValues/store/actions/setCurre import { AVAILABLE_CURRENCIES } from 'src/logic/currencyValues/store/model/currencyValues' import { Dispatch } from 'redux' -const fetchCurrencyRate = (safeAddress: string, selectedCurrency: AVAILABLE_CURRENCIES) => async ( +const fetchCurrencyRate = (safeAddress: string, selectedCurrency: string) => async ( dispatch: Dispatch, ): Promise => { if (AVAILABLE_CURRENCIES.USD === selectedCurrency) { diff --git a/src/logic/currencyValues/store/actions/setSelectedCurrency.ts b/src/logic/currencyValues/store/actions/setSelectedCurrency.ts index 3b0774a0..390b9cb7 100644 --- a/src/logic/currencyValues/store/actions/setSelectedCurrency.ts +++ b/src/logic/currencyValues/store/actions/setSelectedCurrency.ts @@ -2,20 +2,16 @@ import { createAction } from 'redux-actions' import { ThunkDispatch } from 'redux-thunk' import { AnyAction } from 'redux' import { AppReduxState } from 'src/store' -import { AVAILABLE_CURRENCIES } from '../model/currencyValues' import fetchCurrencyRate from 'src/logic/currencyValues/store/actions/fetchCurrencyRate' export const SET_CURRENT_CURRENCY = 'SET_CURRENT_CURRENCY' -const setCurrentCurrency = createAction( - SET_CURRENT_CURRENCY, - (safeAddress: string, selectedCurrency: AVAILABLE_CURRENCIES) => ({ - safeAddress, - selectedCurrency, - }), -) +const setCurrentCurrency = createAction(SET_CURRENT_CURRENCY, (safeAddress: string, selectedCurrency: string) => ({ + safeAddress, + selectedCurrency, +})) -export const setSelectedCurrency = (safeAddress: string, selectedCurrency: AVAILABLE_CURRENCIES) => ( +export const setSelectedCurrency = (safeAddress: string, selectedCurrency: string) => ( dispatch: ThunkDispatch, ): void => { dispatch(setCurrentCurrency(safeAddress, selectedCurrency)) diff --git a/src/logic/currencyValues/store/model/currencyValues.ts b/src/logic/currencyValues/store/model/currencyValues.ts index eede6d5f..26618349 100644 --- a/src/logic/currencyValues/store/model/currencyValues.ts +++ b/src/logic/currencyValues/store/model/currencyValues.ts @@ -1,41 +1,45 @@ import { List, Record, RecordOf } from 'immutable' -export enum AVAILABLE_CURRENCIES { - ETH = 'ETH', - USD = 'USD', - EUR = 'EUR', - AUD = 'AUD', - BGN = 'BGN', - BRL = 'BRL', - CAD = 'CAD', - CHF = 'CHF', - CNY = 'CNY', - CZK = 'CZK', - DKK = 'DKK', - GBP = 'GBP', - HKD = 'HKD', - HRK = 'HRK', - HUF = 'HUF', - IDR = 'IDR', - ILS = 'ILS', - INR = 'INR', - ISK = 'ISK', - JPY = 'JPY', - KRW = 'KRW', - MXN = 'MXN', - MYR = 'MYR', - NOK = 'NOK', - NZD = 'NZD', - PHP = 'PHP', - PLN = 'PLN', - RON = 'RON', - RUB = 'RUB', - SEK = 'SEK', - SGD = 'SGD', - THB = 'THB', - TRY = 'TRY', - ZAR = 'ZAR', -} +import { getNetworkInfo } from 'src/config' + +const { nativeCoin } = getNetworkInfo() + +export const AVAILABLE_CURRENCIES = { + NETWORK: nativeCoin.symbol.toLocaleUpperCase(), + USD: 'USD', + EUR: 'EUR', + AUD: 'AUD', + BGN: 'BGN', + BRL: 'BRL', + CAD: 'CAD', + CHF: 'CHF', + CNY: 'CNY', + CZK: 'CZK', + DKK: 'DKK', + GBP: 'GBP', + HKD: 'HKD', + HRK: 'HRK', + HUF: 'HUF', + IDR: 'IDR', + ILS: 'ILS', + INR: 'INR', + ISK: 'ISK', + JPY: 'JPY', + KRW: 'KRW', + MXN: 'MXN', + MYR: 'MYR', + NOK: 'NOK', + NZD: 'NZD', + PHP: 'PHP', + PLN: 'PLN', + RON: 'RON', + RUB: 'RUB', + SEK: 'SEK', + SGD: 'SGD', + THB: 'THB', + TRY: 'TRY', + ZAR: 'ZAR', +} as const export type BalanceCurrencyRecord = { currencyName?: string @@ -57,6 +61,6 @@ export type BalanceCurrencyList = List export interface CurrencyRateValue { currencyRate?: number - selectedCurrency?: AVAILABLE_CURRENCIES + selectedCurrency?: string currencyBalances?: BalanceCurrencyList } diff --git a/src/logic/currencyValues/store/utils/currencyValuesStorage.ts b/src/logic/currencyValues/store/utils/currencyValuesStorage.ts index ba716349..6f91f608 100644 --- a/src/logic/currencyValues/store/utils/currencyValuesStorage.ts +++ b/src/logic/currencyValues/store/utils/currencyValuesStorage.ts @@ -1,8 +1,7 @@ import { loadFromStorage, saveToStorage } from 'src/utils/storage' -import { AVAILABLE_CURRENCIES } from '../model/currencyValues' const SELECTED_CURRENCY_STORAGE_KEY = 'SELECTED_CURRENCY' -export const saveSelectedCurrency = async (selectedCurrency: AVAILABLE_CURRENCIES): Promise => { +export const saveSelectedCurrency = async (selectedCurrency: string): Promise => { try { await saveToStorage(SELECTED_CURRENCY_STORAGE_KEY, selectedCurrency) } catch (err) { @@ -10,6 +9,6 @@ export const saveSelectedCurrency = async (selectedCurrency: AVAILABLE_CURRENCIE } } -export const loadSelectedCurrency = async (): Promise => { +export const loadSelectedCurrency = async (): Promise => { return await loadFromStorage(SELECTED_CURRENCY_STORAGE_KEY) } diff --git a/src/logic/notifications/notificationTypes.ts b/src/logic/notifications/notificationTypes.ts index 7d4536af..97650456 100644 --- a/src/logic/notifications/notificationTypes.ts +++ b/src/logic/notifications/notificationTypes.ts @@ -1,7 +1,6 @@ import { OptionsObject } from 'notistack' -import { getNetwork } from 'src/config' -import { capitalize } from 'src/utils/css' +import { getNetworkName } from 'src/config' export const SUCCESS = 'success' export const ERROR = 'error' @@ -46,7 +45,7 @@ const NOTIFICATION_IDS = { SETTINGS_CHANGE_EXECUTED_MSG: 'SETTINGS_CHANGE_EXECUTED_MSG', SETTINGS_CHANGE_EXECUTED_MORE_CONFIRMATIONS_MSG: 'SETTINGS_CHANGE_EXECUTED_MORE_CONFIRMATIONS_MSG', SETTINGS_CHANGE_FAILED_MSG: 'SETTINGS_CHANGE_FAILED_MSG', - RINKEBY_VERSION_MSG: 'RINKEBY_VERSION_MSG', + TESTNET_VERSION_MSG: 'TESTNET_VERSION_MSG', WRONG_NETWORK_MSG: 'WRONG_NETWORK_MSG', ADDRESS_BOOK_NEW_ENTRY_SUCCESS: 'ADDRESS_BOOK_NEW_ENTRY_SUCCESS', ADDRESS_BOOK_EDIT_ENTRY_SUCCESS: 'ADDRESS_BOOK_EDIT_ENTRY_SUCCESS', @@ -193,12 +192,12 @@ export const NOTIFICATIONS: Record = { }, // Network - RINKEBY_VERSION_MSG: { - message: "Rinkeby Version: Don't send Mainnet assets to this Safe", + TESTNET_VERSION_MSG: { + message: "Testnet Version: Don't send production assets to this Safe", options: { variant: WARNING, persist: true, preventDuplicate: true }, }, WRONG_NETWORK_MSG: { - message: `Wrong network: Please use ${capitalize(getNetwork())}`, + message: `Wrong network: Please use ${getNetworkName()}`, options: { variant: WARNING, persist: true, preventDuplicate: true }, }, diff --git a/src/logic/safe/api/estimateTxGas.ts b/src/logic/safe/api/estimateTxGas.ts deleted file mode 100644 index 23a1263b..00000000 --- a/src/logic/safe/api/estimateTxGas.ts +++ /dev/null @@ -1,17 +0,0 @@ -import axios from 'axios' - -import { getRelayUrl } from 'src/config/index' - -export const estimateTxGas = (safeAddress, to, value, data, operation = 0) => { - const apiUrl = getRelayUrl() - const url = `${apiUrl}/safes/${safeAddress}/transactions/estimate/` - // const estimationValue = isTokenTransfer(tx.data) ? '0' : value.toString(10) - - return axios.post(url, { - safe: safeAddress, - to, - data: '0x', - value, - operation, - }) -} diff --git a/src/logic/safe/api/index.ts b/src/logic/safe/api/index.ts deleted file mode 100644 index 2a053635..00000000 --- a/src/logic/safe/api/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './estimateTxGas' diff --git a/src/logic/safe/hooks/useFetchTokens.tsx b/src/logic/safe/hooks/useFetchTokens.tsx index 2932d16a..7d19e373 100644 --- a/src/logic/safe/hooks/useFetchTokens.tsx +++ b/src/logic/safe/hooks/useFetchTokens.tsx @@ -2,7 +2,7 @@ import { useMemo } from 'react' import { batch, useDispatch } from 'react-redux' import { useLocation } from 'react-router-dom' -import fetchCollectibles from 'src/logic/collectibles/store/actions/fetchCollectibles' +import { fetchCollectibles } from 'src/logic/collectibles/store/actions/fetchCollectibles' import { fetchSelectedCurrency } from 'src/logic/currencyValues/store/actions/fetchSelectedCurrency' import activateAssetsByBalance from 'src/logic/tokens/store/actions/activateAssetsByBalance' import fetchSafeTokens from 'src/logic/tokens/store/actions/fetchSafeTokens' diff --git a/src/logic/safe/hooks/useSafeActions.tsx b/src/logic/safe/hooks/useSafeActions.tsx index 38bc655b..a97e09ab 100644 --- a/src/logic/safe/hooks/useSafeActions.tsx +++ b/src/logic/safe/hooks/useSafeActions.tsx @@ -1,6 +1,14 @@ import { useState, useMemo } from 'react' -const INITIAL_STATE = { +type SafeActionsState = { + sendFunds: { + isOpen: boolean + selectedToken?: string + } + showReceive: boolean +} + +const INITIAL_STATE: SafeActionsState = { sendFunds: { isOpen: false, selectedToken: undefined, @@ -13,7 +21,7 @@ type Response = { onHide: (action: string) => void showSendFunds: (token: string) => void hideSendFunds: () => void - safeActionsState: Record + safeActionsState: SafeActionsState } const useSafeActions = (): Response => { diff --git a/src/logic/safe/hooks/useSafeScheduledUpdates.tsx b/src/logic/safe/hooks/useSafeScheduledUpdates.tsx index 66c474a2..61c1ae2d 100644 --- a/src/logic/safe/hooks/useSafeScheduledUpdates.tsx +++ b/src/logic/safe/hooks/useSafeScheduledUpdates.tsx @@ -1,7 +1,7 @@ import { useEffect, useRef } from 'react' import { batch, useDispatch } from 'react-redux' -import fetchCollectibles from 'src/logic/collectibles/store/actions/fetchCollectibles' +import { fetchCollectibles } from 'src/logic/collectibles/store/actions/fetchCollectibles' import fetchSafeTokens from 'src/logic/tokens/store/actions/fetchSafeTokens' import fetchEtherBalance from 'src/logic/safe/store/actions/fetchEtherBalance' import { checkAndUpdateSafe } from 'src/logic/safe/store/actions/fetchSafe' diff --git a/src/logic/safe/store/actions/__tests__/transactionHelpers.test.ts b/src/logic/safe/store/actions/__tests__/transactionHelpers.test.ts index 4076f002..6fb7a15d 100644 --- a/src/logic/safe/store/actions/__tests__/transactionHelpers.test.ts +++ b/src/logic/safe/store/actions/__tests__/transactionHelpers.test.ts @@ -572,18 +572,6 @@ describe('calculateTransactionStatus', () => { // then expect(result).toBe(TransactionStatus.PENDING) }) - it('It should return PENDING if the tx has no confirmations', () => { - // given - const transaction = makeTransaction({ confirmations: List(), isPending: false }) - const safe = makeSafe({ threshold: 3 }) - const currentUser = safeAddress - - // when - const result = calculateTransactionStatus(transaction, safe, currentUser) - - // then - expect(result).toBe(TransactionStatus.PENDING) - }) it('It should return AWAITING_CONFIRMATIONS if the tx has confirmations bellow the threshold, the user is owner and signed', () => { // given const userAddress = 'address1' @@ -762,7 +750,36 @@ describe('calculateTransactionType', () => { describe('buildTx', () => { it('Returns a valid transaction', async () => { // given - const cancelTx1 = makeTransaction() + const cancelTx1 = { + baseGas: 0, + blockNumber: 0, + confirmations: [], + confirmationsRequired: 2, + data: null, + dataDecoded: undefined, + ethGasPrice: '0', + executionDate: null, + executor: '', + fee: '', + gasPrice: '', + gasToken: '', + gasUsed: 0, + isExecuted: false, + isSuccessful: true, + modified: '', + nonce: 0, + operation: 0, + origin: null, + refundReceiver: '', + safe: '', + safeTxGas: 0, + safeTxHash: '', + signatures: '', + submissionDate: null, + to: '', + transactionHash: null, + value: '', + } const transaction = getMockedTxServiceModel({ to: safeAddress2, value: '0' }) const userAddress = 'address1' const cancellationTxs = List([cancelTx1]) @@ -776,7 +793,7 @@ describe('buildTx', () => { }) const knownTokens = Map & Readonly>() knownTokens.set('0x00Df91984582e6e96288307E9c2f20b38C8FeCE9', token) - const outgoingTxs = List([cancelTx1]) + const outgoingTxs = [cancelTx1] const safeInstance = makeSafe({ name: 'LOADED SAFE', address: safeAddress }) const expectedTx = makeTransaction({ baseGas: 0, @@ -826,7 +843,7 @@ describe('buildTx', () => { outgoingTxs, safe: safeInstance, tx: transaction, - txCode: null, + txCode: undefined, }) // then diff --git a/src/logic/safe/store/actions/addOrUpdateSafe.ts b/src/logic/safe/store/actions/addOrUpdateSafe.ts index 8aafa0ea..92dd0faf 100644 --- a/src/logic/safe/store/actions/addOrUpdateSafe.ts +++ b/src/logic/safe/store/actions/addOrUpdateSafe.ts @@ -1,9 +1,18 @@ import { createAction } from 'redux-actions' -import { SafeRecordProps } from '../models/safe' +import { SafeOwner, SafeRecordProps } from '../models/safe' +import { List } from 'immutable' +import { makeOwner } from '../models/owner' export const ADD_OR_UPDATE_SAFE = 'ADD_OR_UPDATE_SAFE' -export const addOrUpdateSafe = createAction(ADD_OR_UPDATE_SAFE, (safe: SafeRecordProps) => ({ +export const buildOwnersFrom = (names: string[], addresses: string[]): List => { + const owners = names.map((name, index) => makeOwner({ name, address: addresses[index] })) + + return List(owners) +} + +export const addOrUpdateSafe = createAction(ADD_OR_UPDATE_SAFE, (safe: SafeRecordProps, loadedFromStorage = false) => ({ safe, + loadedFromStorage, })) diff --git a/src/logic/safe/store/actions/addSafe.ts b/src/logic/safe/store/actions/addSafe.ts deleted file mode 100644 index 90851dab..00000000 --- a/src/logic/safe/store/actions/addSafe.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { List } from 'immutable' -import { createAction } from 'redux-actions' - -import setDefaultSafe from 'src/logic/safe/store/actions/setDefaultSafe' -import { makeOwner } from 'src/logic/safe/store/models/owner' - -import { safesListSelector } from 'src/logic/safe/store/selectors' - -import { Dispatch } from 'redux' -import { AppReduxState } from 'src/store' -import { SafeOwner, SafeRecordProps } from 'src/logic/safe/store/models/safe' - -export const ADD_SAFE = 'ADD_SAFE' - -export const buildOwnersFrom = (names: string[], addresses: string[]): List => { - const owners = names.map((name, index) => makeOwner({ name, address: addresses[index] })) - - return List(owners) -} - -export const addSafe = createAction(ADD_SAFE, (safe: SafeRecordProps, loadedFromStorage = false) => ({ - safe, - loadedFromStorage, -})) - -const saveSafe = (safe: SafeRecordProps) => (dispatch: Dispatch, getState: () => AppReduxState): void => { - const state = getState() - const safeList = safesListSelector(state) - - dispatch(addSafe(safe, true)) - - if (safeList.size === 0) { - dispatch(setDefaultSafe(safe.address)) - } -} - -export default saveSafe diff --git a/src/logic/safe/store/actions/allTransactions/loadAllTransactions.ts b/src/logic/safe/store/actions/allTransactions/loadAllTransactions.ts index b054b123..bbb4c25b 100644 --- a/src/logic/safe/store/actions/allTransactions/loadAllTransactions.ts +++ b/src/logic/safe/store/actions/allTransactions/loadAllTransactions.ts @@ -1,8 +1,8 @@ import axios, { AxiosResponse } from 'axios' -import { getAllTransactionsUriFrom, getTxServiceHost } from 'src/config' +import { getSafeServiceBaseUrl } from 'src/config' import { checksumAddress } from 'src/utils/checksumAddress' -import { Transaction } from '../../models/types/transactions.d' +import { Transaction } from 'src/logic/safe/store/models/types/transactions.d' export type ServiceUriParams = { safeAddress: string @@ -21,11 +21,8 @@ type TransactionDTO = { } const getAllTransactionsUri = (safeAddress: string): string => { - const host = getTxServiceHost() const address = checksumAddress(safeAddress) - const base = getAllTransactionsUriFrom(address) - - return `${host}${base}` + return `${getSafeServiceBaseUrl(address)}/all-transactions/` } const fetchAllTransactions = async ( diff --git a/src/logic/safe/store/actions/createTransaction.ts b/src/logic/safe/store/actions/createTransaction.ts index 95ea40e5..841d1c90 100644 --- a/src/logic/safe/store/actions/createTransaction.ts +++ b/src/logic/safe/store/actions/createTransaction.ts @@ -16,7 +16,7 @@ import { saveTxToHistory, tryOffchainSigning, } from 'src/logic/safe/transactions' -import { estimateSafeTxGas } from 'src/logic/safe/transactions/gasNew' +import { estimateSafeTxGas } from 'src/logic/safe/transactions/gas' import { getCurrentSafeVersion } from 'src/logic/safe/utils/safeVersion' import { ZERO_ADDRESS } from 'src/logic/wallets/ethAddresses' import { EMPTY_DATA } from 'src/logic/wallets/ethTransactions' @@ -42,7 +42,7 @@ import { Transaction, TransactionStatus, TxArgs } from 'src/logic/safe/store/mod import { AnyAction } from 'redux' import { PayableTx } from 'src/types/contracts/types.d' import { AppReduxState } from 'src/store' -import { Dispatch } from './types' +import { Dispatch, DispatchReturn } from './types' export const removeTxFromStore = ( tx: Transaction, @@ -107,9 +107,10 @@ interface CreateTransactionArgs { txData?: string txNonce?: number | string valueInWei: string + safeTxGas?: number } -type CreateTransactionAction = ThunkAction, AppReduxState, undefined, AnyAction> +type CreateTransactionAction = ThunkAction, AppReduxState, DispatchReturn, AnyAction> type ConfirmEventHandler = (safeTxHash: string) => void type ErrorEventHandler = () => void @@ -124,10 +125,11 @@ const createTransaction = ( operation = CALL, navigateToTransactionsTab = true, origin = null, + safeTxGas: safeTxGasArg, }: CreateTransactionArgs, onUserConfirm?: ConfirmEventHandler, onError?: ErrorEventHandler, -): CreateTransactionAction => async (dispatch: Dispatch, getState: () => AppReduxState): Promise => { +): CreateTransactionAction => async (dispatch: Dispatch, getState: () => AppReduxState): Promise => { const state = getState() if (navigateToTransactionsTab) { @@ -143,7 +145,8 @@ const createTransaction = ( const nonce = await getNewTxNonce(txNonce?.toString(), lastTx, safeInstance) const isExecution = await shouldExecuteTransaction(safeInstance, nonce, lastTx) const safeVersion = await getCurrentSafeVersion(safeInstance) - const safeTxGas = await estimateSafeTxGas(safeInstance, safeAddress, txData, to, valueInWei, operation) + const safeTxGas = + safeTxGasArg || (await estimateSafeTxGas(safeInstance, safeAddress, txData, to, valueInWei, operation)) // https://docs.gnosis.io/safe/docs/docs5/#pre-validated-signatures const sigs = `0x000000000000000000000000${from.replace( diff --git a/src/logic/safe/store/actions/fetchSafe.ts b/src/logic/safe/store/actions/fetchSafe.ts index a398ffb7..201e75d3 100644 --- a/src/logic/safe/store/actions/fetchSafe.ts +++ b/src/logic/safe/store/actions/fetchSafe.ts @@ -1,5 +1,7 @@ import GnosisSafeSol from '@gnosis.pm/safe-contracts/build/contracts/GnosisSafe.json' import { List, Set, Map } from 'immutable' +import { Action, Dispatch } from 'redux' +import { AbiItem } from 'web3-utils' import generateBatchRequests from 'src/logic/contracts/generateBatchRequests' import { getLocalSafe, getSafeName } from 'src/logic/safe/utils' @@ -10,13 +12,12 @@ import addSafeOwner from 'src/logic/safe/store/actions/addSafeOwner' import removeSafeOwner from 'src/logic/safe/store/actions/removeSafeOwner' import updateSafe from 'src/logic/safe/store/actions/updateSafe' import { makeOwner } from 'src/logic/safe/store/models/owner' - import { checksumAddress } from 'src/utils/checksumAddress' -import { ModulePair, SafeOwner, SafeRecordProps } from 'src/logic/safe/store/models/safe' -import { Action, Dispatch } from 'redux' -import { SENTINEL_ADDRESS } from 'src/logic/contracts/safeContracts' +import { SafeOwner, SafeRecordProps } from 'src/logic/safe/store/models/safe' import { AppReduxState } from 'src/store' -import { latestMasterContractVersionSelector } from '../selectors' +import { latestMasterContractVersionSelector } from 'src/logic/safe/store/selectors' +import { getSafeInfo } from 'src/logic/safe/utils/safeInformation' +import { getModules } from 'src/logic/safe/utils/modules' const buildOwnersFrom = (safeOwners: string[], localSafe?: SafeRecordProps): List => { const ownersList = safeOwners.map((ownerAddress) => { @@ -40,16 +41,6 @@ const buildOwnersFrom = (safeOwners: string[], localSafe?: SafeRecordProps): Lis return List(ownersList) } -const buildModulesLinkedList = (modules: string[] | undefined, nextModule: string): Array | null => { - if (modules?.length) { - return modules.map((moduleAddress, index, modules) => { - const prevModule = modules[index + 1] - return [moduleAddress, prevModule !== undefined ? prevModule : nextModule] - }) - } - return null -} - export const buildSafe = async ( safeAdd: string, safeName: string, @@ -58,12 +49,18 @@ export const buildSafe = async ( const safeAddress = checksumAddress(safeAdd) const safeParams = ['getThreshold', 'nonce', 'VERSION', 'getOwners'] - const [[thresholdStr, nonceStr, currentVersion, remoteOwners], localSafe, ethBalance] = await Promise.all([ - generateBatchRequests({ - abi: GnosisSafeSol.abi, + const [ + [, thresholdStr, nonceStr, currentVersion, remoteOwners = []], + safeInfo, + localSafe, + ethBalance, + ] = await Promise.all([ + generateBatchRequests<[undefined, string | undefined, string | undefined, string | undefined, string[]]>({ + abi: GnosisSafeSol.abi as AbiItem[], address: safeAddress, methods: safeParams, }), + getSafeInfo(safeAddress), getLocalSafe(safeAddress), getBalanceInEtherOf(safeAddress), ]) @@ -73,6 +70,7 @@ export const buildSafe = async ( const owners = buildOwnersFrom(remoteOwners, localSafe) const needsUpdate = safeNeedsUpdate(currentVersion, latestMasterContractVersion) const featuresEnabled = enabledFeatures(currentVersion) + const modules = await getModules(safeInfo) return { address: safeAddress, @@ -81,48 +79,48 @@ export const buildSafe = async ( owners, ethBalance, nonce, - currentVersion, + currentVersion: currentVersion ?? '', needsUpdate, featuresEnabled, - balances: Map(), + balances: localSafe?.balances || Map(), latestIncomingTxBlock: 0, activeAssets: Set(), activeTokens: Set(), blacklistedAssets: Set(), blacklistedTokens: Set(), - modules: null, + modules, } } export const checkAndUpdateSafe = (safeAdd: string) => async (dispatch: Dispatch): Promise => { const safeAddress = checksumAddress(safeAdd) // Check if the owner's safe did change and update them - const safeParams = [ - 'getThreshold', - 'nonce', - 'getOwners', - // TODO: 100 is an arbitrary large number, to avoid the need for pagination. But pagination must be properly handled - { method: 'getModulesPaginated', args: [SENTINEL_ADDRESS, 100] }, - ] - const [[remoteThreshold, remoteNonce, remoteOwners, modules], localSafe] = await Promise.all([ - generateBatchRequests({ - abi: GnosisSafeSol.abi, + const safeParams = ['getThreshold', 'nonce', 'getOwners'] + const [[, remoteThreshold, remoteNonce, remoteOwners = []], safeInfo, localSafe] = await Promise.all([ + generateBatchRequests<[undefined, string | undefined, string | undefined, string[]]>({ + abi: GnosisSafeSol.abi as AbiItem[], address: safeAddress, methods: safeParams, }), + getSafeInfo(safeAddress), getLocalSafe(safeAddress), ]) // Converts from [ { address, ownerName} ] to address array const localOwners = localSafe ? localSafe.owners.map((localOwner) => localOwner.address) : [] + const modules = await getModules(safeInfo) + dispatch( updateSafe({ address: safeAddress, name: localSafe?.name, - modules: buildModulesLinkedList(modules?.array, modules?.next), + modules, nonce: Number(remoteNonce), threshold: Number(remoteThreshold), + featuresEnabled: localSafe?.currentVersion + ? enabledFeatures(localSafe?.currentVersion) + : localSafe?.featuresEnabled, }), ) diff --git a/src/logic/safe/store/actions/fetchSafeCreationTx.ts b/src/logic/safe/store/actions/fetchSafeCreationTx.ts index d0e79de4..6504d226 100644 --- a/src/logic/safe/store/actions/fetchSafeCreationTx.ts +++ b/src/logic/safe/store/actions/fetchSafeCreationTx.ts @@ -1,7 +1,7 @@ import axios from 'axios' import { List } from 'immutable' -import { buildSafeCreationTxUrl } from 'src/config' +import { buildSafeCreationTxUrl } from 'src/logic/safe/utils/buildSafeCreationTxUrl' import { addOrUpdateTransactions } from './transactions/addOrUpdateTransactions' import { makeTransaction } from 'src/logic/safe/store/models/transaction' import { TransactionTypes, TransactionStatus } from 'src/logic/safe/store/models/types/transaction' diff --git a/src/logic/safe/store/actions/loadSafesFromStorage.ts b/src/logic/safe/store/actions/loadSafesFromStorage.ts index c6009857..00e3d99f 100644 --- a/src/logic/safe/store/actions/loadSafesFromStorage.ts +++ b/src/logic/safe/store/actions/loadSafesFromStorage.ts @@ -5,7 +5,7 @@ import { SafeRecordProps } from 'src/logic/safe/store/models/safe' import { buildSafe } from 'src/logic/safe/store/reducer/safe' import { loadFromStorage } from 'src/utils/storage' -import { addSafe } from './addSafe' +import { addOrUpdateSafe } from './addOrUpdateSafe' const loadSafesFromStorage = () => async (dispatch: Dispatch): Promise => { try { @@ -13,7 +13,7 @@ const loadSafesFromStorage = () => async (dispatch: Dispatch): Promise => if (safes) { Object.values(safes).forEach((safeProps) => { - dispatch(addSafe(buildSafe(safeProps), true)) + dispatch(addOrUpdateSafe(buildSafe(safeProps), true)) }) } } catch (err) { diff --git a/src/logic/safe/store/actions/transactions/fetchTransactions/fetchTransactions.ts b/src/logic/safe/store/actions/transactions/fetchTransactions/fetchTransactions.ts index f4907bed..e97a6883 100644 --- a/src/logic/safe/store/actions/transactions/fetchTransactions/fetchTransactions.ts +++ b/src/logic/safe/store/actions/transactions/fetchTransactions/fetchTransactions.ts @@ -13,6 +13,8 @@ const getServiceUrl = (txType: string, safeAddress: string): string => { }[txType](safeAddress) } +// TODO: Remove this magic +/* eslint-disable */ async function fetchTransactions( txType: TransactionTypes.INCOMING, safeAddress: string, @@ -28,6 +30,7 @@ async function fetchTransactions( safeAddress: string, eTag: string | null, ): Promise<{ eTag: string | null; results: TxServiceModel[] | IncomingTxServiceModel[] }> { + /* eslint-enable */ try { const url = getServiceUrl(txType, safeAddress) const response = await axios.get(url, eTag ? { headers: { 'If-None-Match': eTag } } : undefined) diff --git a/src/logic/safe/store/actions/transactions/fetchTransactions/loadIncomingTransactions.ts b/src/logic/safe/store/actions/transactions/fetchTransactions/loadIncomingTransactions.ts index ec79aa23..d52130a9 100644 --- a/src/logic/safe/store/actions/transactions/fetchTransactions/loadIncomingTransactions.ts +++ b/src/logic/safe/store/actions/transactions/fetchTransactions/loadIncomingTransactions.ts @@ -1,6 +1,9 @@ import bn from 'bignumber.js' import { List, Map } from 'immutable' +import { Transaction, TransactionReceipt } from 'web3-core' +import { AbiItem } from 'web3-utils' +import { getNetworkInfo } from 'src/config' import generateBatchRequests from 'src/logic/contracts/generateBatchRequests' import { ALTERNATIVE_TOKEN_ABI } from 'src/logic/tokens/utils/alternativeAbi' import { web3ReadOnly } from 'src/logic/wallets/getWeb3' @@ -43,6 +46,7 @@ const buildIncomingTransactionFrom = ([tx, symbol, decimals, fee]: [ const batchIncomingTxsTokenDataRequest = (txs: IncomingTxServiceModel[]) => { const batch = new web3ReadOnly.BatchRequest() + const { nativeCoin } = getNetworkInfo() const whenTxsValues = txs.map((tx) => { const methods = [ @@ -52,8 +56,16 @@ const batchIncomingTxsTokenDataRequest = (txs: IncomingTxServiceModel[]) => { { method: 'getTransactionReceipt', args: [tx.transactionHash], type: 'eth' }, ] - return generateBatchRequests({ - abi: ALTERNATIVE_TOKEN_ABI, + return generateBatchRequests< + [ + IncomingTxServiceModel, + string | undefined, + string | undefined, + Transaction | undefined, + TransactionReceipt | undefined, + ] + >({ + abi: ALTERNATIVE_TOKEN_ABI as AbiItem[], address: tx.tokenAddress, batch, context: tx, @@ -64,11 +76,11 @@ const batchIncomingTxsTokenDataRequest = (txs: IncomingTxServiceModel[]) => { batch.execute() return Promise.all(whenTxsValues).then((txsValues) => - txsValues.map(([tx, symbol, decimals, { gasPrice }, { gasUsed }]) => [ + txsValues.map(([tx, symbol, decimals, ethTx, ethTxReceipt]) => [ tx, - symbol === null ? 'ETH' : symbol, - decimals === null ? '18' : decimals, - new bn(gasPrice).times(gasUsed), + symbol ? symbol : nativeCoin.symbol, + decimals ? decimals : nativeCoin.decimals, + new bn(ethTx?.gasPrice ?? 0).times(ethTxReceipt?.gasUsed ?? 0), ]), ) } diff --git a/src/logic/safe/store/actions/transactions/fetchTransactions/loadOutgoingTransactions.ts b/src/logic/safe/store/actions/transactions/fetchTransactions/loadOutgoingTransactions.ts index 89d53d95..4dca08fb 100644 --- a/src/logic/safe/store/actions/transactions/fetchTransactions/loadOutgoingTransactions.ts +++ b/src/logic/safe/store/actions/transactions/fetchTransactions/loadOutgoingTransactions.ts @@ -1,7 +1,7 @@ import { fromJS, List, Map } from 'immutable' import generateBatchRequests from 'src/logic/contracts/generateBatchRequests' -import { TOKEN_REDUCER_ID } from 'src/logic/tokens/store/reducer/tokens' +import { TOKEN_REDUCER_ID, TokenState } from 'src/logic/tokens/store/reducer/tokens' import { web3ReadOnly } from 'src/logic/wallets/getWeb3' import { PROVIDER_REDUCER_ID } from 'src/logic/wallets/store/reducer/provider' import { buildTx, isCancelTransaction } from 'src/logic/safe/store/actions/transactions/utils/transactionHelpers' @@ -59,8 +59,8 @@ export type SafeTransactionsType = { } export type OutgoingTxs = { - cancellationTxs: any - outgoingTxs: any + cancellationTxs: Record + outgoingTxs: TxServiceModel[] } export type BatchProcessTxsProps = OutgoingTxs & { @@ -97,12 +97,14 @@ const extractCancelAndOutgoingTxs = (safeAddress: string, outgoingTxs: TxService ) } +type BatchRequestReturnValues = [TxServiceModel, string | undefined] + /** * Requests Contract's code for all the Contracts the Safe has interacted with * @param transactions * @returns {Promise<[Promise<*[]>, Promise<*[]>, Promise<*[]>, Promise<*[]>, Promise<*[]>, Promise<*[]>, Promise<*[]>, Promise<*[]>, Promise<*[]>, Promise<*[]>]>} */ -const batchRequestContractCode = (transactions: any[]): Promise => { +const batchRequestContractCode = (transactions: TxServiceModel[]): Promise => { if (!transactions || !Array.isArray(transactions)) { throw new Error('`transactions` must be provided in order to lookup information') } @@ -110,7 +112,7 @@ const batchRequestContractCode = (transactions: any[]): Promise => { const batch = new web3ReadOnly.BatchRequest() const whenTxsValues = transactions.map((tx) => { - return generateBatchRequests({ + return generateBatchRequests({ abi: [], address: tx.to, batch, @@ -141,7 +143,7 @@ const batchProcessOutgoingTransactions = async ({ safe, }: BatchProcessTxsProps): Promise<{ cancel: Record - outgoing: Array + outgoing: Transaction[] }> => { // cancellation transactions const cancelTxsValues = Object.values(cancellationTxs) @@ -193,9 +195,9 @@ export const loadOutgoingTransactions = async (safeAddress: string): Promise { ) } -export const isOutgoingTransaction = (tx: TxServiceModel, safeAddress: string): boolean => { +export const isOutgoingTransaction = (tx: TxServiceModel, safeAddress?: string): boolean => { return !sameAddress(tx.to, safeAddress) && !isEmptyData(tx.data) } export const isCustomTransaction = async ( tx: TxServiceModel, - txCode: string | null, - safeAddress: string, - knownTokens: Map, + txCode?: string, + safeAddress?: string, + knownTokens?: TokenState, ): Promise => { const isOutgoing = isOutgoingTransaction(tx, safeAddress) const isErc20 = await isSendERC20Transaction(tx, txCode, knownTokens) @@ -100,12 +100,13 @@ export const getRefundParams = async ( tx: TxServiceModel, tokenInfo: (string) => Promise<{ decimals: number; symbol: string } | null>, ): Promise => { + const { nativeCoin } = getNetworkInfo() const txGasPrice = Number(tx.gasPrice) let refundParams: RefundParams | null = null if (txGasPrice > 0) { - let refundSymbol = 'ETH' - let refundDecimals = 18 + let refundSymbol = nativeCoin.symbol + let refundDecimals = nativeCoin.decimals if (tx.gasToken !== ZERO_ADDRESS) { const gasToken = await tokenInfo(tx.gasToken) @@ -161,7 +162,7 @@ export const getConfirmations = (tx: TxServiceModel): List => { export const isTransactionCancelled = ( tx: TxServiceModel, outgoingTxs: Array, - cancellationTxs: { number: TxServiceModel }, + cancellationTxs: Record, ): boolean => { return ( // not executed @@ -175,20 +176,20 @@ export const isTransactionCancelled = ( export const calculateTransactionStatus = ( tx: Transaction, - { owners, threshold }: SafeRecord, + { owners, threshold, nonce }: SafeRecord, currentUser?: string | null, ): TransactionStatusValues => { let txStatus if (tx.isExecuted && tx.isSuccessful) { txStatus = TransactionStatus.SUCCESS - } else if (tx.cancelled) { + } else if (tx.cancelled || nonce > tx.nonce) { txStatus = TransactionStatus.CANCELLED } else if (tx.confirmations.size === threshold) { txStatus = TransactionStatus.AWAITING_EXECUTION } else if (tx.creationTx) { txStatus = TransactionStatus.SUCCESS - } else if (!tx.confirmations.size || !!tx.isPending) { + } else if (!!tx.isPending) { txStatus = TransactionStatus.PENDING } else { const userConfirmed = tx.confirmations.filter((conf) => conf.owner === currentUser).size === 1 @@ -230,7 +231,7 @@ export const calculateTransactionType = (tx: Transaction): TransactionTypeValues export type BuildTx = BatchProcessTxsProps & { tx: TxServiceModel - txCode: string | null + txCode?: string } export const buildTx = async ({ @@ -243,6 +244,7 @@ export const buildTx = async ({ txCode, }: BuildTx): Promise => { const safeAddress = safe.address + const { nativeCoin } = getNetworkInfo() const isModifySettingsTx = isModifySettingsTransaction(tx, safeAddress) const isTxCancelled = isTransactionCancelled(tx, outgoingTxs, cancellationTxs) const isSendERC721Tx = isSendERC721Transaction(tx, txCode, knownTokens) @@ -255,8 +257,8 @@ export const buildTx = async ({ const decodedParams = getDecodedParams(tx) const confirmations = getConfirmations(tx) - let tokenDecimals = 18 - let tokenSymbol = 'ETH' + let tokenDecimals = nativeCoin.decimals + let tokenSymbol = nativeCoin.symbol try { if (isSendERC20Tx) { const { decimals, symbol } = await getERC20DecimalsAndSymbol(tx.to) diff --git a/src/logic/safe/store/actions/types.d.ts b/src/logic/safe/store/actions/types.d.ts index 0006a041..d95ce82c 100644 --- a/src/logic/safe/store/actions/types.d.ts +++ b/src/logic/safe/store/actions/types.d.ts @@ -3,4 +3,6 @@ import { AnyAction } from 'redux' import { AppReduxState } from 'src/store' -export type Dispatch = ThunkDispatch +export type DispatchReturn = string | undefined + +export type Dispatch = ThunkDispatch diff --git a/src/logic/safe/store/middleware/notificationsMiddleware.ts b/src/logic/safe/store/middleware/notificationsMiddleware.ts index 617bdd3d..c07ea64e 100644 --- a/src/logic/safe/store/middleware/notificationsMiddleware.ts +++ b/src/logic/safe/store/middleware/notificationsMiddleware.ts @@ -10,7 +10,6 @@ import { userAccountSelector } from 'src/logic/wallets/store/selectors' import { getIncomingTxAmount } from 'src/routes/safe/components/Transactions/TxsTable/columns' import { grantedSelector } from 'src/routes/safe/container/selector' import { ADD_INCOMING_TRANSACTIONS } from 'src/logic/safe/store/actions/addIncomingTransactions' -import { ADD_SAFE } from 'src/logic/safe/store/actions/addSafe' import { ADD_OR_UPDATE_TRANSACTIONS } from 'src/logic/safe/store/actions/transactions/addOrUpdateTransactions' import updateSafe from 'src/logic/safe/store/actions/updateSafe' import { @@ -20,8 +19,9 @@ import { } from 'src/logic/safe/store/selectors' import { loadFromStorage, saveToStorage } from 'src/utils/storage' +import { ADD_OR_UPDATE_SAFE } from '../actions/addOrUpdateSafe' -const watchedActions = [ADD_OR_UPDATE_TRANSACTIONS, ADD_INCOMING_TRANSACTIONS, ADD_SAFE] +const watchedActions = [ADD_OR_UPDATE_TRANSACTIONS, ADD_INCOMING_TRANSACTIONS, ADD_OR_UPDATE_SAFE] const sendAwaitingTransactionNotification = async ( dispatch, @@ -146,7 +146,7 @@ const notificationsMiddleware = (store) => (next) => async (action) => { }) break } - case ADD_SAFE: { + case ADD_OR_UPDATE_SAFE: { const state = store.getState() const { safe } = action.payload const currentSafeAddress = safeParamAddressFromStateSelector(state) || safe.address diff --git a/src/logic/safe/store/middleware/safeStorage.ts b/src/logic/safe/store/middleware/safeStorage.ts index ee9152c2..90b26346 100644 --- a/src/logic/safe/store/middleware/safeStorage.ts +++ b/src/logic/safe/store/middleware/safeStorage.ts @@ -1,9 +1,7 @@ -import { addAddressBookEntry } from 'src/logic/addressBook/store/actions/addAddressBookEntry' import { saveDefaultSafe, saveSafes } from 'src/logic/safe/utils' import { tokensSelector } from 'src/logic/tokens/store/selectors' import { saveActiveTokens } from 'src/logic/tokens/utils/tokensStorage' import { ACTIVATE_TOKEN_FOR_ALL_SAFES } from 'src/logic/safe/store/actions/activateTokenForAllSafes' -import { ADD_SAFE } from 'src/logic/safe/store/actions/addSafe' import { ADD_SAFE_OWNER } from 'src/logic/safe/store/actions/addSafeOwner' import { EDIT_SAFE_OWNER } from 'src/logic/safe/store/actions/editSafeOwner' import { REMOVE_SAFE } from 'src/logic/safe/store/actions/removeSafe' @@ -14,17 +12,13 @@ import { UPDATE_SAFE } from 'src/logic/safe/store/actions/updateSafe' import { UPDATE_TOKENS_LIST } from 'src/logic/safe/store/actions/updateTokensList' import { UPDATE_ASSETS_LIST } from 'src/logic/safe/store/actions/updateAssetsList' import { getActiveTokensAddressesForAllSafes, safesMapSelector } from 'src/logic/safe/store/selectors' -import { checksumAddress } from 'src/utils/checksumAddress' -import { makeAddressBookEntry } from 'src/logic/addressBook/model/addressBook' -import { addOrUpdateAddressBookEntry } from 'src/logic/addressBook/store/actions/addOrUpdateAddressBookEntry' -import { checkIfEntryWasDeletedFromAddressBook, isValidAddressBookName } from 'src/logic/addressBook/utils' -import { addressBookSelector } from 'src/logic/addressBook/store/selectors' -import { sameAddress } from 'src/logic/wallets/ethAddresses' -import { updateAddressBookEntry } from 'src/logic/addressBook/store/actions/updateAddressBookEntry' import { ADD_OR_UPDATE_SAFE } from 'src/logic/safe/store/actions/addOrUpdateSafe' +import { makeAddressBookEntry } from 'src/logic/addressBook/model/addressBook' +import { checksumAddress } from 'src/utils/checksumAddress' +import { isValidAddressBookName } from 'src/logic/addressBook/utils' +import { addOrUpdateAddressBookEntry } from 'src/logic/addressBook/store/actions/addOrUpdateAddressBookEntry' const watchedActions = [ - ADD_SAFE, UPDATE_SAFE, REMOVE_SAFE, ADD_OR_UPDATE_SAFE, @@ -60,7 +54,6 @@ const safeStorageMware = (store) => (next) => async (action) => { const state = store.getState() const { dispatch } = store const safes = safesMapSelector(state) - const addressBook = addressBookSelector(state) await saveSafes(safes.toJSON()) switch (action.type) { @@ -68,43 +61,6 @@ const safeStorageMware = (store) => (next) => async (action) => { recalculateActiveTokens(state) break } - case ADD_SAFE: { - const { safe, loadedFromStorage } = action.payload - const safeAlreadyLoaded = - loadedFromStorage || safes.find((safeIterator) => sameAddress(safeIterator.address, safe.address)) - - safe.owners.forEach((owner) => { - const checksumEntry = makeAddressBookEntry({ address: checksumAddress(owner.address), name: owner.name }) - - const ownerWasAlreadyInAddressBook = checkIfEntryWasDeletedFromAddressBook( - checksumEntry, - addressBook, - safeAlreadyLoaded, - ) - - if (!ownerWasAlreadyInAddressBook) { - dispatch(addAddressBookEntry(checksumEntry, { notifyEntryUpdate: false })) - } - const addressAlreadyExists = addressBook.find((entry) => sameAddress(entry.address, checksumEntry.address)) - if (isValidAddressBookName(checksumEntry.name) && addressAlreadyExists) { - dispatch(updateAddressBookEntry(checksumEntry)) - } - }) - const safeWasAlreadyInAddressBook = checkIfEntryWasDeletedFromAddressBook( - { address: safe.address, name: safe.name }, - addressBook, - safeAlreadyLoaded, - ) - - if (!safeWasAlreadyInAddressBook) { - dispatch( - addAddressBookEntry(makeAddressBookEntry({ address: safe.address, name: safe.name }), { - notifyEntryUpdate: true, - }), - ) - } - break - } case ADD_OR_UPDATE_SAFE: { const { safe } = action.payload safe.owners.forEach((owner) => { diff --git a/src/logic/safe/store/models/safe.ts b/src/logic/safe/store/models/safe.ts index 0311d3be..ef217e28 100644 --- a/src/logic/safe/store/models/safe.ts +++ b/src/logic/safe/store/models/safe.ts @@ -1,4 +1,5 @@ import { List, Map, Record, RecordOf, Set } from 'immutable' +import { FEATURES } from 'src/config/networks/network.d' export type SafeOwner = { name: string @@ -13,7 +14,7 @@ export type SafeRecordProps = { threshold: number ethBalance: string owners: List - modules: ModulePair[] | null + modules?: ModulePair[] | null activeTokens: Set activeAssets: Set blacklistedTokens: Set @@ -24,7 +25,7 @@ export type SafeRecordProps = { recurringUser?: boolean currentVersion: string needsUpdate: boolean - featuresEnabled: Array + featuresEnabled: Array } const makeSafe = Record({ @@ -38,7 +39,7 @@ const makeSafe = Record({ activeAssets: Set(), blacklistedTokens: Set(), blacklistedAssets: Set(), - balances: Map({}), + balances: Map(), nonce: 0, latestIncomingTxBlock: 0, recurringUser: undefined, diff --git a/src/logic/safe/store/models/transaction.ts b/src/logic/safe/store/models/transaction.ts index 3beaf658..a0d3e21c 100644 --- a/src/logic/safe/store/models/transaction.ts +++ b/src/logic/safe/store/models/transaction.ts @@ -31,6 +31,7 @@ export const makeTransaction = Record({ isCancellationTx: false, isCollectibleTransfer: false, isExecuted: false, + isPending: false, isSuccessful: true, isTokenTransfer: false, masterCopy: '', diff --git a/src/logic/safe/store/reducer/safe.ts b/src/logic/safe/store/reducer/safe.ts index 3d170f8e..5409c9e5 100644 --- a/src/logic/safe/store/reducer/safe.ts +++ b/src/logic/safe/store/reducer/safe.ts @@ -2,7 +2,6 @@ import { Map, Set, List } from 'immutable' import { handleActions } from 'redux-actions' import { ACTIVATE_TOKEN_FOR_ALL_SAFES } from 'src/logic/safe/store/actions/activateTokenForAllSafes' -import { ADD_SAFE, buildOwnersFrom } from 'src/logic/safe/store/actions/addSafe' import { ADD_SAFE_OWNER } from 'src/logic/safe/store/actions/addSafeOwner' import { EDIT_SAFE_OWNER } from 'src/logic/safe/store/actions/editSafeOwner' import { REMOVE_SAFE } from 'src/logic/safe/store/actions/removeSafe' @@ -17,7 +16,7 @@ import { makeOwner } from 'src/logic/safe/store/models/owner' import makeSafe, { SafeRecordProps } from 'src/logic/safe/store/models/safe' import { checksumAddress } from 'src/utils/checksumAddress' import { SafeReducerMap } from 'src/routes/safe/store/reducer/types/safe' -import { ADD_OR_UPDATE_SAFE } from 'src/logic/safe/store/actions/addOrUpdateSafe' +import { ADD_OR_UPDATE_SAFE, buildOwnersFrom } from 'src/logic/safe/store/actions/addOrUpdateSafe' import { sameAddress } from 'src/logic/wallets/ethAddresses' export const SAFE_REDUCER_ID = 'safes' @@ -54,8 +53,9 @@ const updateSafeProps = (prevSafe, safe) => { // We check each safe property sent in action.payload safeProperties.forEach((key) => { if (safe[key] && typeof safe[key] === 'object') { - if (safe[key].length >= 0) { - // If type is array we update the array + if (safe[key].length >= 0 || Map.isMap(safe[key])) { + // If type is array we replace it + // If type is Immutable Map we replace it record.update(key, () => safe[key]) } else if (safe[key].size >= 0) { // If type is Immutable List we replace current List @@ -99,19 +99,7 @@ export default handleActions( }) }) }, - [ADD_SAFE]: (state: SafeReducerMap, action) => { - const { safe } = action.payload - // if you add a new Safe it needs to be set as a record - // in case of update it shouldn't, because a record would be initialized - // with initial props and it would overwrite existing ones - - if (state.hasIn(['safes', safe.address])) { - return state - } - - return state.setIn(['safes', safe.address], makeSafe(safe)) - }, [ADD_OR_UPDATE_SAFE]: (state: SafeReducerMap, action) => { const { safe } = action.payload @@ -121,7 +109,7 @@ export default handleActions( return state.updateIn( ['safes', safe.address], - makeSafe({ name: 'LOADED SAFE', address: safe.address }), + makeSafe({ name: safe?.name || 'LOADED SAFE', address: safe.address }), (prevSafe) => updateSafeProps(prevSafe, safe), ) }, diff --git a/src/logic/safe/store/reducer/transactions.ts b/src/logic/safe/store/reducer/transactions.ts index fc42a6b6..3ce4df74 100644 --- a/src/logic/safe/store/reducer/transactions.ts +++ b/src/logic/safe/store/reducer/transactions.ts @@ -21,7 +21,7 @@ export default handleActions( if (stateTransactionsList) { const txsToStore = stateTransactionsList.withMutations((txsList) => { transactions.forEach((updateTx) => { - const storedTxIndex = txsList.findIndex((txIterator) => txIterator.nonce === updateTx.nonce) + const storedTxIndex = txsList.findIndex((txIterator) => txIterator.safeTxHash === updateTx.safeTxHash) if (storedTxIndex !== -1) { // Update diff --git a/src/logic/safe/transactions/__tests__/gas.test.ts b/src/logic/safe/transactions/__tests__/gas.test.ts new file mode 100644 index 00000000..589ae4d3 --- /dev/null +++ b/src/logic/safe/transactions/__tests__/gas.test.ts @@ -0,0 +1,68 @@ +import { getNonGETHErrorDataResult } from 'src/logic/safe/transactions/gas' + +describe('getOpenEthereumErrorDataResult', () => { + it(`should return data hash from given OpenEthereum response`, () => { + // given + const resultExpected = + '0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000006457' + const openEthResponse = + 'Internal JSON-RPC error.\n' + + '{\n' + + ' "code": -32015,\n' + + ' "message": "VM execution error.",\n' + + ' "data": "Reverted 0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000006457"\n' + + '}' + + // when + const result = getNonGETHErrorDataResult(openEthResponse) + + // then + expect(result).toBe(resultExpected) + }) + it(`should return undefined from empty OpenEthereum response`, () => { + // given + const resultExpected = undefined + const openEthResponse = '' + + // when + const result = getNonGETHErrorDataResult(openEthResponse) + + // then + expect(result).toBe(resultExpected) + }) + it(`should return undefined from wrong OpenEthereum response`, () => { + // given + const resultExpected = undefined + const openEthResponse = + 'Internal JSON-RPC error.\n' + + '{\n' + + ' "code": -32015,\n' + + ' "message": "VM execution error.",\n' + + ' "data": "Reverted-test0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000006457"\n' + + '}' + + // when + const result = getNonGETHErrorDataResult(openEthResponse) + + // then + expect(result).toBe(resultExpected) + }) + it(`should return data hash from given Nethermind response`, () => { + // given + const resultExpected = + '0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000006457' + const openEthResponse = + 'Internal JSON-RPC error.\n' + + '{\n' + + ' "code": -32015,\n' + + ' "message": "VM execution error.",\n' + + ' "data": "revert 0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000006457"\n' + + '}' + + // when + const result = getNonGETHErrorDataResult(openEthResponse) + + // then + expect(result).toBe(resultExpected) + }) +}) diff --git a/src/logic/safe/transactions/gas.ts b/src/logic/safe/transactions/gas.ts index abf89e4b..d4e9353b 100644 --- a/src/logic/safe/transactions/gas.ts +++ b/src/logic/safe/transactions/gas.ts @@ -1,36 +1,210 @@ -import { getGnosisSafeInstanceAt } from 'src/logic/contracts/safeContracts' +import GnosisSafeSol from '@gnosis.pm/safe-contracts/build/contracts/GnosisSafe.json' +import { BigNumber } from 'bignumber.js' +import { AbiItem } from 'web3-utils' -export const calculateTxFee = async (safe, safeAddress, from, data, to, valueInWei, operation) => { +import { CALL } from '.' + +import { getGnosisSafeInstanceAt } from 'src/logic/contracts/safeContracts' +import { generateSignaturesFromTxConfirmations } from 'src/logic/safe/safeTxSigner' +import { Transaction } from 'src/logic/safe/store/models/types/transaction' +import { ZERO_ADDRESS } from 'src/logic/wallets/ethAddresses' +import { EMPTY_DATA, calculateGasOf, calculateGasPrice } from 'src/logic/wallets/ethTransactions' +import { getAccountFrom, getWeb3 } from 'src/logic/wallets/getWeb3' +import { GnosisSafe } from 'src/types/contracts/GnosisSafe.d' +import { sameString } from 'src/utils/strings' + +const estimateDataGasCosts = (data: string): number => { + const reducer = (accumulator, currentValue) => { + if (currentValue === EMPTY_DATA) { + return accumulator + 0 + } + + if (currentValue === '00') { + return accumulator + 4 + } + + return accumulator + 16 + } + + return data.match(/.{2}/g)?.reduce(reducer, 0) +} + +export const estimateTxGasCosts = async ( + safeAddress: string, + to: string, + data: string, + tx?: Transaction, + preApprovingOwner?: string, +): Promise => { + try { + const web3 = getWeb3() + const from = await getAccountFrom(web3) + + if (!from) { + return 0 + } + + const safeInstance = (new web3.eth.Contract(GnosisSafeSol.abi as AbiItem[], safeAddress) as unknown) as GnosisSafe + const nonce = await safeInstance.methods.nonce().call() + const threshold = await safeInstance.methods.getThreshold().call() + const isExecution = tx?.confirmations.size === Number(threshold) || !!preApprovingOwner || threshold === '1' + + let txData + if (isExecution) { + // https://docs.gnosis.io/safe/docs/docs5/#pre-validated-signatures + const signatures = tx?.confirmations + ? generateSignaturesFromTxConfirmations(tx.confirmations, preApprovingOwner) + : `0x000000000000000000000000${from.replace( + EMPTY_DATA, + '', + )}000000000000000000000000000000000000000000000000000000000000000001` + txData = await safeInstance.methods + .execTransaction( + to, + tx?.value || 0, + data, + CALL, + tx?.safeTxGas || 0, + 0, + 0, + ZERO_ADDRESS, + ZERO_ADDRESS, + signatures, + ) + .encodeABI() + } else { + const txHash = await safeInstance.methods + .getTransactionHash(to, tx?.value || 0, data, CALL, 0, 0, 0, ZERO_ADDRESS, ZERO_ADDRESS, nonce) + .call({ + from, + }) + txData = await safeInstance.methods.approveHash(txHash).encodeABI() + } + + const gas = await calculateGasOf(txData, from, safeAddress) + const gasPrice = await calculateGasPrice() + + return gas * parseInt(gasPrice, 10) + } catch (err) { + console.error('Error while estimating transaction execution gas costs:') + console.error(err) + + return 10000 + } +} + +// Parses the result of OpenEthereum/Parity and Nethermind error messages and returns the value +export const getNonGETHErrorDataResult = (errorMessage: string): string | undefined => { + // Extracts JSON object from the error message + const [, ...error] = errorMessage.split('\n') + try { + const errorAsJSON = JSON.parse(error.join('')) + + if (errorAsJSON?.data) { + const [, dataResult] = errorAsJSON.data.split(' ') + return dataResult + } + } catch (error) { + console.error(`Error trying to extract data from openEthereum/Nethermind error message: ${errorMessage}`) + } +} + +const getGasEstimationTxResponse = async (txConfig: { + to: string + from: string + data: string + gasPrice?: number + gas?: number +}): Promise => { + const web3 = getWeb3() + try { + const result = await web3.eth.call(txConfig) + + // GETH Nodes + // In case that the gas is not enough we will receive an EMPTY data + // Otherwise we will receive the gas amount as hash data + + if (!sameString(result, EMPTY_DATA)) { + return new BigNumber(result.substring(138), 16).toNumber() + } + } catch (error) { + // OpenEthereum/Parity nodes + // Parity/OpenEthereum nodes always returns the response as an error + // So we try to extract the estimation result within the error in case is possible + const estimationData = getNonGETHErrorDataResult(error.message) + + if (!estimationData || sameString(estimationData, EMPTY_DATA)) { + throw error + } + + return new BigNumber(estimationData.substring(138), 16).toNumber() + } + + // This will fail in case that we receive an EMPTY_DATA on the GETH node gas estimation + // We cannot throw this error above because it will be captured again on the OpenEthereum code bellow + throw new Error('Error while estimating the gas required for tx') +} + +const calculateMinimumGasForTransaction = async ( + additionalGasBatches: number[], + safeAddress: string, + estimateData: string, + txGasEstimation: number, + dataGasEstimation: number, +): Promise => { + for (const additionalGas of additionalGasBatches) { + const amountOfGasToTryTx = txGasEstimation + dataGasEstimation + additionalGas + try { + await getGasEstimationTxResponse({ + to: safeAddress, + from: safeAddress, + data: estimateData, + gasPrice: 0, + gas: amountOfGasToTryTx, + }) + return txGasEstimation + additionalGas + } catch (error) { + console.log(`Error trying to estimate gas with amount: ${amountOfGasToTryTx}`) + } + } + + return 0 +} + +export const estimateSafeTxGas = async ( + safe: GnosisSafe | undefined, + safeAddress: string, + data: string, + to: string, + valueInWei: string, + operation: number, +): Promise => { try { let safeInstance = safe if (!safeInstance) { safeInstance = await getGnosisSafeInstanceAt(safeAddress) } - // https://docs.gnosis.io/safe/docs/docs5/#pre-validated-signatures - const sigs = `0x000000000000000000000000${from.replace( - '0x', - '', - )}000000000000000000000000000000000000000000000000000000000000000001` + const estimateData = safeInstance.methods.requiredTxGas(to, valueInWei, data, operation).encodeABI() + const gasEstimationResponse = await getGasEstimationTxResponse({ + to: safeAddress, + from: safeAddress, + data: estimateData, + }) - // we get gas limit from this call, then it needs to be multiplied by the gas price - // https://safe-relay.gnosis.pm/api/v1/gas-station/ - // https://safe-relay.rinkeby.gnosis.pm/api/v1/about/ - const estimate = await safeInstance.execTransaction.estimateGas( - to, - valueInWei, - data, - operation, - 0, - 0, - 0, - '0x0000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000', - sigs, - { from: '0xbc2BB26a6d821e69A38016f3858561a1D80d4182' }, + const txGasEstimation = gasEstimationResponse + 10000 + + // 21000 - additional gas costs (e.g. base tx costs, transfer costs) + const dataGasEstimation = estimateDataGasCosts(estimateData) + 21000 + const additionalGasBatches = [0, 10000, 20000, 40000, 80000, 160000, 320000, 640000, 1280000, 2560000, 5120000] + + return await calculateMinimumGasForTransaction( + additionalGasBatches, + safeAddress, + estimateData, + txGasEstimation, + dataGasEstimation, ) - - return estimate } catch (error) { console.error('Error calculating tx gas estimation', error) return 0 diff --git a/src/logic/safe/transactions/gasNew.ts b/src/logic/safe/transactions/gasNew.ts deleted file mode 100644 index 91015c62..00000000 --- a/src/logic/safe/transactions/gasNew.ts +++ /dev/null @@ -1,170 +0,0 @@ -import GnosisSafeSol from '@gnosis.pm/safe-contracts/build/contracts/GnosisSafe.json' -import { BigNumber } from 'bignumber.js' -import { AbiItem } from 'web3-utils' - -import { CALL } from '.' - -import { getGnosisSafeInstanceAt } from 'src/logic/contracts/safeContracts' -import { generateSignaturesFromTxConfirmations } from 'src/logic/safe/safeTxSigner' -import { Transaction } from 'src/logic/safe/store/models/types/transaction' -import { ZERO_ADDRESS } from 'src/logic/wallets/ethAddresses' -import { EMPTY_DATA, calculateGasOf, calculateGasPrice } from 'src/logic/wallets/ethTransactions' -import { getAccountFrom, getWeb3 } from 'src/logic/wallets/getWeb3' -import { GnosisSafe } from 'src/types/contracts/GnosisSafe.d' - -const estimateDataGasCosts = (data: string): number => { - const reducer = (accumulator, currentValue) => { - if (currentValue === EMPTY_DATA) { - return accumulator + 0 - } - - if (currentValue === '00') { - return accumulator + 4 - } - - return accumulator + 16 - } - - return data.match(/.{2}/g)?.reduce(reducer, 0) -} - -export const estimateTxGasCosts = async ( - safeAddress: string, - to: string, - data: string, - tx?: Transaction, - preApprovingOwner?: string, -): Promise => { - try { - const web3 = getWeb3() - const from = await getAccountFrom(web3) - - if (!from) { - return 0 - } - - const safeInstance = (new web3.eth.Contract(GnosisSafeSol.abi as AbiItem[], safeAddress) as unknown) as GnosisSafe - const nonce = await safeInstance.methods.nonce().call() - const threshold = await safeInstance.methods.getThreshold().call() - const isExecution = tx?.confirmations.size === Number(threshold) || !!preApprovingOwner || threshold === '1' - - let txData - if (isExecution) { - // https://docs.gnosis.io/safe/docs/docs5/#pre-validated-signatures - const signatures = tx?.confirmations - ? generateSignaturesFromTxConfirmations(tx.confirmations, preApprovingOwner) - : `0x000000000000000000000000${from.replace( - '0x', - '', - )}000000000000000000000000000000000000000000000000000000000000000001` - txData = await safeInstance.methods - .execTransaction( - to, - tx?.value || 0, - data, - CALL, - tx?.safeTxGas || 0, - 0, - 0, - ZERO_ADDRESS, - ZERO_ADDRESS, - signatures, - ) - .encodeABI() - } else { - const txHash = await safeInstance.methods - .getTransactionHash(to, tx?.value || 0, data, CALL, 0, 0, 0, ZERO_ADDRESS, ZERO_ADDRESS, nonce) - .call({ - from, - }) - txData = await safeInstance.methods.approveHash(txHash).encodeABI() - } - - const gas = await calculateGasOf(txData, from, safeAddress) - const gasPrice = await calculateGasPrice() - - return gas * parseInt(gasPrice, 10) - } catch (err) { - console.error('Error while estimating transaction execution gas costs:') - console.error(err) - - return 10000 - } -} - -export const estimateSafeTxGas = async ( - safe: GnosisSafe | undefined, - safeAddress: string, - data: string, - to: string, - valueInWei: string, - operation: number, -): Promise => { - try { - let safeInstance = safe - if (!safeInstance) { - safeInstance = await getGnosisSafeInstanceAt(safeAddress) - } - - const web3 = await getWeb3() - const estimateData = safeInstance.methods.requiredTxGas(to, valueInWei, data, operation).encodeABI() - const estimateResponse = await web3.eth.call({ - to: safeAddress, - from: safeAddress, - data: estimateData, - }) - const txGasEstimation = new BigNumber(estimateResponse.substring(138), 16).toNumber() + 10000 - - // 21000 - additional gas costs (e.g. base tx costs, transfer costs) - const dataGasEstimation = estimateDataGasCosts(estimateData) + 21000 - const additionalGasBatches = [10000, 20000, 40000, 80000, 160000, 320000, 640000, 1280000, 2560000, 5120000] - - const batch = new web3.BatchRequest() - const estimationRequests = additionalGasBatches.map( - (additionalGas) => - new Promise((resolve) => { - // there are no type definitions for .request, so for now ts-ignore is there - // Issue link: https://github.com/ethereum/web3.js/issues/3144 - // eslint-disable-next-line - // @ts-ignore - const request = web3.eth.call.request( - { - to: safeAddress, - from: safeAddress, - data: estimateData, - gasPrice: 0, - gasLimit: txGasEstimation + dataGasEstimation + additionalGas, - }, - (error, res) => { - // res.data check is for OpenEthereum/Parity revert messages format - const isOpenEthereumRevertMsg = res && typeof res.data === 'string' - - const isEstimationSuccessful = - !error && - ((typeof res === 'string' && res !== '0x') || (isOpenEthereumRevertMsg && res.data.slice(9) !== '0x')) - - resolve({ - success: isEstimationSuccessful, - estimation: txGasEstimation + additionalGas, - }) - }, - ) - - batch.add(request) - }), - ) - batch.execute() - - const estimationResponses = await Promise.all(estimationRequests) - const firstSuccessfulRequest: any = estimationResponses.find((res: any) => res.success) - - if (firstSuccessfulRequest) { - return firstSuccessfulRequest.estimation - } - - return 0 - } catch (error) { - console.error('Error calculating tx gas estimation', error) - return 0 - } -} diff --git a/src/logic/safe/transactions/incomingTxHistory.ts b/src/logic/safe/transactions/incomingTxHistory.ts index c7d78e54..f4cbf582 100644 --- a/src/logic/safe/transactions/incomingTxHistory.ts +++ b/src/logic/safe/transactions/incomingTxHistory.ts @@ -1,10 +1,7 @@ -import { getIncomingTxServiceUriTo, getTxServiceHost } from 'src/config' +import { getSafeServiceBaseUrl } from 'src/config' import { checksumAddress } from 'src/utils/checksumAddress' export const buildIncomingTxServiceUrl = (safeAddress: string): string => { - const host = getTxServiceHost() const address = checksumAddress(safeAddress) - const base = getIncomingTxServiceUriTo(address) - - return `${host}${base}` + return `${getSafeServiceBaseUrl(address)}/incoming-transfers/` } diff --git a/src/logic/safe/transactions/index.ts b/src/logic/safe/transactions/index.ts index fe4a24b1..4a4e7148 100644 --- a/src/logic/safe/transactions/index.ts +++ b/src/logic/safe/transactions/index.ts @@ -1,4 +1,3 @@ -export * from './gas' export * from './send' export * from './offchainSigner' export * from './txHistory' diff --git a/src/logic/safe/transactions/offchainSigner/ethSigner.ts b/src/logic/safe/transactions/offchainSigner/ethSigner.ts index 5daeedba..1d4ccd89 100644 --- a/src/logic/safe/transactions/offchainSigner/ethSigner.ts +++ b/src/logic/safe/transactions/offchainSigner/ethSigner.ts @@ -10,7 +10,7 @@ type EthSignerArgs = { } export const ethSigner = async ({ safeTxHash, sender }: EthSignerArgs): Promise => { - const web3 = await getWeb3() + const web3 = getWeb3() return new Promise(function (resolve, reject) { const provider = web3.currentProvider as AbstractProvider diff --git a/src/logic/safe/transactions/txHistory.ts b/src/logic/safe/transactions/txHistory.ts index eeb14436..08e0fc07 100644 --- a/src/logic/safe/transactions/txHistory.ts +++ b/src/logic/safe/transactions/txHistory.ts @@ -1,7 +1,7 @@ import axios from 'axios' import { GnosisSafe } from 'src/types/contracts/GnosisSafe.d' -import { getTxServiceHost, getTxServiceUriFrom } from 'src/config' +import { getSafeServiceBaseUrl } from 'src/config' import { checksumAddress } from 'src/utils/checksumAddress' const calculateBodyFrom = async ( @@ -45,10 +45,8 @@ const calculateBodyFrom = async ( } export const buildTxServiceUrl = (safeAddress: string): string => { - const host = getTxServiceHost() const address = checksumAddress(safeAddress) - const base = getTxServiceUriFrom(address) - return `${host}${base}?has_confirmations=True` + return `${getSafeServiceBaseUrl(address)}/transactions/?has_confirmations=True` } const SUCCESS_STATUS = 201 // CREATED status diff --git a/src/logic/safe/utils/buildSafeCreationTxUrl.ts b/src/logic/safe/utils/buildSafeCreationTxUrl.ts new file mode 100644 index 00000000..624bc608 --- /dev/null +++ b/src/logic/safe/utils/buildSafeCreationTxUrl.ts @@ -0,0 +1,7 @@ +import { getSafeServiceBaseUrl } from 'src/config' +import { checksumAddress } from 'src/utils/checksumAddress' + +export const buildSafeCreationTxUrl = (safeAddress: string): string => { + const address = checksumAddress(safeAddress) + return `${getSafeServiceBaseUrl(address)}/creation/` +} diff --git a/src/logic/safe/utils/buildSafeInformationUrl.ts b/src/logic/safe/utils/buildSafeInformationUrl.ts new file mode 100644 index 00000000..45fc15d3 --- /dev/null +++ b/src/logic/safe/utils/buildSafeInformationUrl.ts @@ -0,0 +1,8 @@ +import { getSafeServiceBaseUrl } from 'src/config' +import { checksumAddress } from 'src/utils/checksumAddress' + +export const buildSafeInformationUrl = (safeAddress: string): string => { + const address = checksumAddress(safeAddress) + const url = getSafeServiceBaseUrl(address) + return `${url}/` +} diff --git a/src/logic/safe/utils/modules.ts b/src/logic/safe/utils/modules.ts new file mode 100644 index 00000000..b15e2c15 --- /dev/null +++ b/src/logic/safe/utils/modules.ts @@ -0,0 +1,76 @@ +import semverLessThan from 'semver/functions/lt' + +import { getGnosisSafeInstanceAt, SENTINEL_ADDRESS } from 'src/logic/contracts/safeContracts' +import { ModulePair } from 'src/logic/safe/store/models/safe' +import { SafeInfo } from 'src/logic/safe/utils/safeInformation' + +type ModulesPaginated = { + array: string[] + next: string +} + +const buildModulesLinkedList = (modules: string[], nextModule: string = SENTINEL_ADDRESS): Array | null => { + if (modules?.length) { + return modules.map((moduleAddress, index, modules) => { + const prevModule = modules[index + 1] + return [moduleAddress, prevModule !== undefined ? prevModule : nextModule] + }) + } + + // no modules + return null +} + +/** + * Returns a list of Modules if there's any, in the form of [module, prevModule][] + * so we have an easy track of the prevModule and the currentModule when calling `disableModule` + * + * There's a slight difference on how many modules `getModules` return, depending on the Safe's version we're in: + * - for >= v1.1.1 it will return a list of up to 10 modules + * - for previous version it will return a list of all the modules enabled + * + * As we're using the safe-transactions service, and it's querying `getModules`, + * we'll fallback to `getModulesPaginated` RPC call when needed. + * + * @todo: Implement pagination for `getModulesPaginated`. We're passing an arbitrary large number to avoid pagination. + * + * @param {SafeInfo | undefined } safeInfo + * @returns Array | null | undefined + */ +export const getModules = async (safeInfo: SafeInfo | void): Promise | null | undefined> => { + if (!safeInfo) { + return + } + + if (semverLessThan(safeInfo.version, '1.1.1')) { + // we can use the `safeInfo.modules`, as versions previous to 1.1.1 return the whole list of modules + return buildModulesLinkedList(safeInfo.modules) + } else { + // newer versions `getModules` call returns up to 10 modules + if (safeInfo.modules.length < 10) { + // we're sure that we got all the modules + return buildModulesLinkedList(safeInfo.modules) + } + + try { + // lastly, if `safeInfo.modules` have 10 items, + // we'll fallback to `getModulesPaginated` RPC call + // as we're not sure if there are more than 10 modules enabled for the current Safe + const safeInstance = getGnosisSafeInstanceAt(safeInfo.address) + + // TODO: 100 is an arbitrary large number, to avoid the need for pagination. But pagination must be properly handled + const modules: ModulesPaginated = await safeInstance.methods.getModulesPaginated(SENTINEL_ADDRESS, 100).call() + + return buildModulesLinkedList(modules.array, modules.next) + } catch (e) { + console.error('Failed to retrieve Safe modules', e) + } + } +} + +export const getDisableModuleTxData = (modulePair: ModulePair, safeAddress: string): string => { + const [module, previousModule] = modulePair + const safeInstance = getGnosisSafeInstanceAt(safeAddress) + + return safeInstance.methods.disableModule(previousModule, module).encodeABI() +} diff --git a/src/logic/safe/utils/safeInformation.ts b/src/logic/safe/utils/safeInformation.ts new file mode 100644 index 00000000..80ece796 --- /dev/null +++ b/src/logic/safe/utils/safeInformation.ts @@ -0,0 +1,32 @@ +import axios, { AxiosError, AxiosResponse } from 'axios' +import { buildSafeInformationUrl } from './buildSafeInformationUrl' + +export type SafeInfo = { + address: string + nonce: number + threshold: number + owners: string[] + masterCopy: string + modules: string[] + fallbackHandler: string + version: string +} + +export type SafeInfoError = { + code: number + message: string + arguments: string[] +} + +export const getSafeInfo = (safeAddress: string): Promise => { + const safeInfoUrl = buildSafeInformationUrl(safeAddress) + return axios + .get>(safeInfoUrl) + .then((response) => response.data) + .catch((error: AxiosError) => { + console.error( + 'Failed to retrieve safe Information', + error.response?.statusText ?? error.response?.data.message ?? error, + ) + }) +} diff --git a/src/logic/safe/utils/safeVersion.ts b/src/logic/safe/utils/safeVersion.ts index 5fe5ee34..bdfa6080 100644 --- a/src/logic/safe/utils/safeVersion.ts +++ b/src/logic/safe/utils/safeVersion.ts @@ -3,15 +3,24 @@ import semverSatisfies from 'semver/functions/satisfies' import semverValid from 'semver/functions/valid' import { GnosisSafe } from 'src/types/contracts/GnosisSafe.d' -import { getSafeLastVersion } from 'src/config' import { getGnosisSafeInstanceAt, getSafeMasterContract } from 'src/logic/contracts/safeContracts' +import { LATEST_SAFE_VERSION } from 'src/utils/constants' +import { getNetworkConfigDisabledFeatures } from 'src/config' +import { FEATURES } from 'src/config/networks/network.d' -export const FEATURES = [ - { name: 'ERC721', validVersion: '>=1.1.1' }, - { name: 'ERC1155', validVersion: '>=1.1.1' }, +type FeatureConfigByVersion = { + name: FEATURES + validVersion?: string +} + +const FEATURES_BY_VERSION: FeatureConfigByVersion[] = [ + { name: FEATURES.ERC721, validVersion: '>=1.1.1' }, + { name: FEATURES.ERC1155, validVersion: '>=1.1.1' }, + { name: FEATURES.SAFE_APPS }, + { name: FEATURES.CONTRACT_INTERACTION }, ] -type Feature = typeof FEATURES[number] +type Feature = typeof FEATURES_BY_VERSION[number] export const safeNeedsUpdate = (currentVersion?: string, latestVersion?: string): boolean => { if (!currentVersion || !latestVersion) { @@ -27,13 +36,19 @@ export const safeNeedsUpdate = (currentVersion?: string, latestVersion?: string) export const getCurrentSafeVersion = (gnosisSafeInstance: GnosisSafe): Promise => gnosisSafeInstance.methods.VERSION().call() -export const enabledFeatures = (version: string): string[] => - FEATURES.reduce((acc: string[], feature: Feature) => { - if (semverSatisfies(version, feature.validVersion)) { +const checkFeatureEnabledByVersion = (featureConfig: FeatureConfigByVersion, version: string) => { + return featureConfig.validVersion ? semverSatisfies(version, featureConfig.validVersion) : true +} + +export const enabledFeatures = (version?: string): FEATURES[] => { + const disabledFeatures = getNetworkConfigDisabledFeatures() + return FEATURES_BY_VERSION.reduce((acc: FEATURES[], feature: Feature) => { + if (!disabledFeatures.includes(feature.name) && version && checkFeatureEnabledByVersion(feature, version)) { acc.push(feature.name) } return acc }, []) +} interface SafeVersionInfo { current: string @@ -60,11 +75,11 @@ export const getCurrentMasterContractLastVersion = async (): Promise => const safeMaster = await getSafeMasterContract() let safeMasterVersion try { - safeMasterVersion = await safeMaster.VERSION() + safeMasterVersion = await safeMaster.methods.VERSION().call() } catch (err) { // Default in case that it's not possible to obtain the version from the contract, returns a hardcoded value or an // env variable - safeMasterVersion = getSafeLastVersion() + safeMasterVersion = LATEST_SAFE_VERSION } return safeMasterVersion } diff --git a/src/logic/tokens/api/fetchErc20AndErc721AssetsList.ts b/src/logic/tokens/api/fetchErc20AndErc721AssetsList.ts new file mode 100644 index 00000000..c2c72bf3 --- /dev/null +++ b/src/logic/tokens/api/fetchErc20AndErc721AssetsList.ts @@ -0,0 +1,22 @@ +import axios, { AxiosResponse } from 'axios' + +import { getTokensServiceBaseUrl } from 'src/config' + +export type TokenResult = { + address: string + decimals?: number + logoUri: string + name: string + symbol: string + type: string +} + +export const fetchErc20AndErc721AssetsList = async (): Promise> => { + const url = getTokensServiceBaseUrl() + + return axios.get<{ results: TokenResult[] }>(`${url}/`, { + params: { + limit: 3000, + }, + }) +} diff --git a/src/logic/tokens/api/fetchSafeCollectibles.ts b/src/logic/tokens/api/fetchSafeCollectibles.ts new file mode 100644 index 00000000..3b023b0f --- /dev/null +++ b/src/logic/tokens/api/fetchSafeCollectibles.ts @@ -0,0 +1,24 @@ +import axios, { AxiosResponse } from 'axios' + +import { getSafeServiceBaseUrl } from 'src/config' +import { checksumAddress } from 'src/utils/checksumAddress' + +export type CollectibleResult = { + address: string + description: string | null + id: string + imageUri: string | null + logoUri: string + metadata: Record + name: string | null + tokenName: string + tokenSymbol: string + uri: string | null +} + +export const fetchSafeCollectibles = async (safeAddress: string): Promise> => { + const address = checksumAddress(safeAddress) + const url = `${getSafeServiceBaseUrl(address)}/collectibles/` + + return axios.get(url) +} diff --git a/src/logic/tokens/api/fetchToken.ts b/src/logic/tokens/api/fetchToken.ts deleted file mode 100644 index 7584521e..00000000 --- a/src/logic/tokens/api/fetchToken.ts +++ /dev/null @@ -1,16 +0,0 @@ -import axios from 'axios' - -import { getRelayUrl } from 'src/config/index' - -const fetchToken = (tokenAddress) => { - const apiUrl = getRelayUrl() - const url = `${apiUrl}/tokens/` - - return axios.get(url, { - params: { - address: tokenAddress, - }, - }) -} - -export default fetchToken diff --git a/src/logic/tokens/api/fetchTokenBalanceList.ts b/src/logic/tokens/api/fetchTokenBalanceList.ts index c446858c..f8196fb8 100644 --- a/src/logic/tokens/api/fetchTokenBalanceList.ts +++ b/src/logic/tokens/api/fetchTokenBalanceList.ts @@ -1,16 +1,18 @@ -import axios from 'axios' +import axios, { AxiosResponse } from 'axios' -import { getTxServiceHost } from 'src/config/index' +import { getSafeServiceBaseUrl } from 'src/config' +import { TokenProps } from 'src/logic/tokens/store/model/token' +import { checksumAddress } from 'src/utils/checksumAddress' -const fetchTokenBalanceList = (safeAddress) => { - const apiUrl = getTxServiceHost() - const url = `${apiUrl}safes/${safeAddress}/balances/` - - return axios.get(url, { - params: { - limit: 3000, - }, - }) +type BalanceResult = { + tokenAddress: string + token: TokenProps + balance: string } -export default fetchTokenBalanceList +export const fetchTokenBalanceList = (safeAddress: string): Promise> => { + const address = checksumAddress(safeAddress) + const url = `${getSafeServiceBaseUrl(address)}/balances/` + + return axios.get(url) +} diff --git a/src/logic/tokens/api/fetchTokenList.ts b/src/logic/tokens/api/fetchTokenList.ts deleted file mode 100644 index dd9054b0..00000000 --- a/src/logic/tokens/api/fetchTokenList.ts +++ /dev/null @@ -1,16 +0,0 @@ -import axios from 'axios' - -import { getRelayUrl } from 'src/config/index' - -const fetchTokenList = () => { - const apiUrl = getRelayUrl() - const url = `${apiUrl}tokens/` - - return axios.get(url, { - params: { - limit: 3000, - }, - }) -} - -export default fetchTokenList diff --git a/src/logic/tokens/api/index.ts b/src/logic/tokens/api/index.ts index 7ff3aa7d..9210ea14 100644 --- a/src/logic/tokens/api/index.ts +++ b/src/logic/tokens/api/index.ts @@ -1,2 +1,3 @@ -export { default as fetchTokenList } from './fetchTokenList' -export { default as fetchToken } from './fetchToken' +export { fetchErc20AndErc721AssetsList } from './fetchErc20AndErc721AssetsList' +export { fetchSafeCollectibles } from './fetchSafeCollectibles' +export { fetchTokenBalanceList } from './fetchTokenBalanceList' diff --git a/src/logic/tokens/store/actions/fetchSafeTokens.ts b/src/logic/tokens/store/actions/fetchSafeTokens.ts index 608256c6..55eca9e5 100644 --- a/src/logic/tokens/store/actions/fetchSafeTokens.ts +++ b/src/logic/tokens/store/actions/fetchSafeTokens.ts @@ -3,15 +3,12 @@ import { List, Map } from 'immutable' import { batch } from 'react-redux' import { Dispatch } from 'redux' -import fetchTokenCurrenciesBalances, { +import { + fetchTokenCurrenciesBalances, BalanceEndpoint, } from 'src/logic/currencyValues/api/fetchTokenCurrenciesBalances' import { setCurrencyBalances } from 'src/logic/currencyValues/store/actions/setCurrencyBalances' -import { - AVAILABLE_CURRENCIES, - CurrencyRateValueRecord, - makeBalanceCurrency, -} from 'src/logic/currencyValues/store/model/currencyValues' +import { CurrencyRateValueRecord, makeBalanceCurrency } from 'src/logic/currencyValues/store/model/currencyValues' import addTokens from 'src/logic/tokens/store/actions/saveTokens' import { makeToken, Token } from 'src/logic/tokens/store/model/token' import { TokenState } from 'src/logic/tokens/store/reducer/tokens' @@ -43,7 +40,7 @@ interface ExtractedData { const extractDataFromResult = (currentTokens: TokenState) => ( acc: ExtractedData, - { balance, balanceUsd, token, tokenAddress }: BalanceEndpoint, + { balance, fiatBalance, fiatCode, token, tokenAddress }: BalanceEndpoint, ): ExtractedData => { if (tokenAddress === null) { acc.ethBalance = humanReadableValue(balance, 18) @@ -57,10 +54,10 @@ const extractDataFromResult = (currentTokens: TokenState) => ( acc.currencyList = acc.currencyList.push( makeBalanceCurrency({ - currencyName: balanceUsd ? AVAILABLE_CURRENCIES.USD : undefined, + currencyName: fiatCode, tokenAddress, - balanceInBaseCurrency: balanceUsd, - balanceInSelectedCurrency: balanceUsd, + balanceInBaseCurrency: fiatBalance, + balanceInSelectedCurrency: fiatBalance, }), ) diff --git a/src/logic/tokens/store/actions/fetchTokens.ts b/src/logic/tokens/store/actions/fetchTokens.ts index 5c5bde49..20e170af 100644 --- a/src/logic/tokens/store/actions/fetchTokens.ts +++ b/src/logic/tokens/store/actions/fetchTokens.ts @@ -3,12 +3,13 @@ import HumanFriendlyToken from '@gnosis.pm/util-contracts/build/contracts/HumanF import ERC20Detailed from '@openzeppelin/contracts/build/contracts/ERC20Detailed.json' import ERC721 from '@openzeppelin/contracts/build/contracts/ERC721.json' import { List } from 'immutable' -import contract from 'truffle-contract' +import contract from '@truffle/contract/index.js' +import { AbiItem } from 'web3-utils' import saveTokens from './saveTokens' import generateBatchRequests from 'src/logic/contracts/generateBatchRequests' -import { fetchTokenList } from 'src/logic/tokens/api' +import { fetchErc20AndErc721AssetsList } from 'src/logic/tokens/api' import { makeToken, Token } from 'src/logic/tokens/store/model/token' import { tokensSelector } from 'src/logic/tokens/store/selectors' import { getWeb3 } from 'src/logic/wallets/getWeb3' @@ -53,8 +54,8 @@ export const containsMethodByHash = async (contractAddress: string, methodHash: } const getTokenValues = (tokenAddress) => - generateBatchRequests({ - abi: ERC20Detailed.abi, + generateBatchRequests<[undefined, string | undefined, string | undefined, string | undefined]>({ + abi: ERC20Detailed.abi as AbiItem[], address: tokenAddress, methods: ['decimals', 'name', 'symbol'], }) @@ -69,7 +70,7 @@ export const getTokenInfos = async (tokenAddress: string): Promise async ( const { data: { results: tokenList }, - } = await fetchTokenList() + } = await fetchErc20AndErc721AssetsList() - if (currentSavedTokens && currentSavedTokens.size === tokenList.length) { + const erc20Tokens = tokenList.filter((token) => token.type.toLowerCase() === 'erc20') + + if (currentSavedTokens?.size === erc20Tokens.length) { return } - const tokens = List(tokenList.map((token) => makeToken(token))) + const tokens = List(erc20Tokens.map((token) => makeToken(token))) dispatch(saveTokens(tokens)) } catch (err) { diff --git a/src/logic/tokens/utils/__tests__/tokenHelpers.test.ts b/src/logic/tokens/utils/__tests__/tokenHelpers.test.ts index 7afee4ed..0351af13 100644 --- a/src/logic/tokens/utils/__tests__/tokenHelpers.test.ts +++ b/src/logic/tokens/utils/__tests__/tokenHelpers.test.ts @@ -1,6 +1,7 @@ import { makeToken } from 'src/logic/tokens/store/model/token' import { getERC20DecimalsAndSymbol, isERC721Contract, isTokenTransfer } from 'src/logic/tokens/utils/tokenHelpers' import { getMockedTxServiceModel } from 'src/test/utils/safeHelper' +import { fromTokenUnit, toTokenUnit } from 'src/logic/tokens/utils/humanReadableValue' describe('isTokenTransfer', () => { const safeAddress = '0xdfA693da0D16F5E7E78FdCBeDe8FC6eBEa44f1Cf' @@ -113,7 +114,11 @@ describe('getERC20DecimalsAndSymbol', () => { const generateBatchRequests = require('src/logic/contracts/generateBatchRequests') const spyTokenInfos = fetchTokens.getTokenInfos.mockImplementationOnce(() => null) - const spyGenerateBatchRequest = generateBatchRequests.default.mockImplementationOnce(() => [decimals, symbol]) + const spyGenerateBatchRequest = generateBatchRequests.default.mockImplementationOnce(() => [ + undefined, + decimals, + symbol, + ]) // when const result = await getERC20DecimalsAndSymbol(tokenAddress) @@ -171,4 +176,31 @@ describe('isERC721Contract', () => { expect(result).toEqual(expectedResult) expect(standardContractSpy).toHaveBeenCalled() }) + it('It should return the right conversion from unit to token', () => { + // given + const decimals = Number(18) + + const expectedResult = '0.000000003' + const ESTIMATED_GAS_COST = 3e9 // 3 Gwei + + // when + const gasCosts = fromTokenUnit(ESTIMATED_GAS_COST, decimals) + + // then + expect(gasCosts).toEqual(expectedResult) + }) + + it('It should return the right conversion from token to unit', () => { + // given + const decimals = Number(18) + + const expectedResult = '300000000000000000' + const VALUE = 0.3 + + // when + const txValue = toTokenUnit(VALUE, decimals) + + // then + expect(txValue).toEqual(expectedResult) + }) }) diff --git a/src/logic/tokens/utils/humanReadableValue.ts b/src/logic/tokens/utils/humanReadableValue.ts index 7716a1d5..2d2afc17 100644 --- a/src/logic/tokens/utils/humanReadableValue.ts +++ b/src/logic/tokens/utils/humanReadableValue.ts @@ -3,3 +3,17 @@ import { BigNumber } from 'bignumber.js' export const humanReadableValue = (value: number | string, decimals = 18): string => { return new BigNumber(value).times(`1e-${decimals}`).toFixed() } + +export const fromTokenUnit = (amount: number | string, decimals: string | number): string => + new BigNumber(amount).times(`1e-${decimals}`).toFixed() + +export const toTokenUnit = (amount: number | string, decimals: string | number): string => { + const amountBN = new BigNumber(amount).times(`1e${decimals}`) + const [, amountDecimalPlaces] = amount.toString().split('.') + + if (amountDecimalPlaces?.length >= +decimals) { + return amountBN.toFixed(+decimals, BigNumber.ROUND_DOWN) + } + + return amountBN.toFixed() +} diff --git a/src/logic/tokens/utils/tokenHelpers.ts b/src/logic/tokens/utils/tokenHelpers.ts index 48134bdb..b7bb4b2f 100644 --- a/src/logic/tokens/utils/tokenHelpers.ts +++ b/src/logic/tokens/utils/tokenHelpers.ts @@ -1,4 +1,6 @@ -import logo from 'src/assets/icons/icon_etherTokens.svg' +import { AbiItem } from 'web3-utils' + +import { getNetworkInfo } from 'src/config' import generateBatchRequests from 'src/logic/contracts/generateBatchRequests' import { getStandardTokenContract, @@ -6,22 +8,18 @@ import { getERC721TokenContract, } from 'src/logic/tokens/store/actions/fetchTokens' import { makeToken, Token } from 'src/logic/tokens/store/model/token' +import { TokenState } from 'src/logic/tokens/store/reducer/tokens' import { ALTERNATIVE_TOKEN_ABI } from 'src/logic/tokens/utils/alternativeAbi' import { web3ReadOnly as web3 } from 'src/logic/wallets/getWeb3' import { isEmptyData } from 'src/logic/safe/store/actions/transactions/utils/transactionHelpers' import { TxServiceModel } from 'src/logic/safe/store/actions/transactions/fetchTransactions/loadOutgoingTransactions' -import { Map } from 'immutable' -export const ETH_ADDRESS = '0x000' export const SAFE_TRANSFER_FROM_WITHOUT_DATA_HASH = '42842e0e' export const getEthAsToken = (balance: string | number): Token => { + const { nativeCoin } = getNetworkInfo() return makeToken({ - address: ETH_ADDRESS, - name: 'Ether', - symbol: 'ETH', - decimals: 18, - logoUri: logo, + ...nativeCoin, balance, }) } @@ -44,18 +42,13 @@ export const isTokenTransfer = (tx: TxServiceModel): boolean => { return !isEmptyData(tx.data) && tx.data?.substring(0, 10) === '0xa9059cbb' && Number(tx.value) === 0 } -export const isSendERC721Transaction = ( - tx: TxServiceModel, - txCode: string | null, - knownTokens: Map, -): boolean => { +export const isSendERC721Transaction = (tx: TxServiceModel, txCode?: string, knownTokens?: TokenState): boolean => { // "0x57f1887a8BF19b14fC0dF6Fd9B2acc9Af147eA85" - ens token contract, includes safeTransferFrom // but no proper ERC721 standard implemented return ( - (txCode && - txCode.includes(SAFE_TRANSFER_FROM_WITHOUT_DATA_HASH) && + (txCode?.includes(SAFE_TRANSFER_FROM_WITHOUT_DATA_HASH) && tx.to !== '0x57f1887a8BF19b14fC0dF6Fd9B2acc9Af147eA85') || - (isTokenTransfer(tx) && !knownTokens.get(tx.to)) + (isTokenTransfer(tx) && !knownTokens?.get(tx.to)) ) } @@ -79,14 +72,16 @@ export const getERC20DecimalsAndSymbol = async ( const storedTokenInfo = await getTokenInfos(tokenAddress) if (!storedTokenInfo) { - const [tokenDecimals, tokenSymbol] = await generateBatchRequests({ - abi: ALTERNATIVE_TOKEN_ABI, + const [, tokenDecimals, tokenSymbol] = await generateBatchRequests< + [undefined, string | undefined, string | undefined] + >({ + abi: ALTERNATIVE_TOKEN_ABI as AbiItem[], address: tokenAddress, methods: ['decimals', 'symbol'], }) - return { decimals: Number(tokenDecimals), symbol: tokenSymbol } + return { decimals: Number(tokenDecimals), symbol: tokenSymbol ?? 'UNKNOWN' } } - return { decimals: storedTokenInfo.decimals as number, symbol: storedTokenInfo.symbol } + return { decimals: Number(storedTokenInfo.decimals), symbol: storedTokenInfo.symbol } } catch (err) { console.error(`Failed to retrieve token info for ERC20 token ${tokenAddress}`) } @@ -96,8 +91,8 @@ export const getERC20DecimalsAndSymbol = async ( export const isSendERC20Transaction = async ( tx: TxServiceModel, - txCode: string | null, - knownTokens: Map, + txCode?: string, + knownTokens?: TokenState, ): Promise => { let isSendTokenTx = !isSendERC721Transaction(tx, txCode, knownTokens) && isTokenTransfer(tx) diff --git a/src/logic/wallets/__tests__/ethAddresses.test.ts b/src/logic/wallets/__tests__/ethAddresses.test.ts new file mode 100644 index 00000000..28bb962b --- /dev/null +++ b/src/logic/wallets/__tests__/ethAddresses.test.ts @@ -0,0 +1,285 @@ +//@ts-nocheck +import { List } from 'immutable' + +import { + isUserAnOwner, + isUserAnOwnerOfAnySafe, + isValidEnsName, + sameAddress, + shortVersionOf, +} from 'src/logic/wallets/ethAddresses' +import makeSafe from 'src/logic/safe/store/models/safe' +import { makeOwner } from 'src/logic/safe/store/models/owner' + +describe('src/logic/wallets/ethAddresses', () => { + describe('Utility function: sameAddress', () => { + it('It should return false if no address given', () => { + // given + const safeAddress = null + const safeAddress2 = '0x344B941b1aAE2e4Be73987212FC4741687Bf0503' + + // when + const result = sameAddress(safeAddress, safeAddress2) + + // then + expect(result).toBe(false) + }) + it('It should return false if not second address given', () => { + // given + const safeAddress = '0xdfA693da0D16F5E7E78FdCBeDe8FC6eBEa44f1Cf' + const safeAddress2 = null + + // when + const result = sameAddress(safeAddress, safeAddress2) + + // then + expect(result).toBe(false) + }) + it('It should return true if two equal addresses given', () => { + // given + const safeAddress = '0xdfA693da0D16F5E7E78FdCBeDe8FC6eBEa44f1Cf' + + // when + const result = sameAddress(safeAddress, safeAddress.toLowerCase()) + + // then + expect(result).toBe(true) + }) + it('If should return false if two different addresses given', () => { + // given + const safeAddress = '0xdfA693da0D16F5E7E78FdCBeDe8FC6eBEa44f1Cf' + const safeAddress2 = '0x344B941b1aAE2e4Be73987212FC4741687Bf0503' + + // when + const result = sameAddress(safeAddress, safeAddress2) + + // then + expect(result).toBe(false) + }) + }) + + describe('Utility function: shortVersionOf', () => { + it('It should return Unknown if no address given', () => { + // given + const safeAddress = null + const cut = 5 + const expectedResult = 'Unknown' + + // when + const result = shortVersionOf(safeAddress, cut) + + // then + expect(result).toBe(expectedResult) + }) + it('It should return 0x344...f0503 if given 0x344B941b1aAE2e4Be73987212FC4741687Bf0503 and a cut = 5', () => { + // given + const safeAddress = '0x344B941b1aAE2e4Be73987212FC4741687Bf0503' + const cut = 5 + const expectedResult = `0x344...f0503` + + // when + const result = shortVersionOf(safeAddress, cut) + + // then + expect(result).toBe(expectedResult) + }) + it('If should return the same address if a cut value bigger than the address length given', () => { + // given + const safeAddress = '0x344B941b1aAE2e4Be73987212FC4741687Bf0503' + const cut = safeAddress.length + const expectedResult = safeAddress + + // when + const result = shortVersionOf(safeAddress, cut) + + // then + expect(result).toBe(expectedResult) + }) + }) + + describe('Utility function: isUserAnOwner', () => { + it("Should return false if there's no Safe", () => { + // given + const userAddress = 'address1' + const safeInstance = null + const expectedResult = false + + // when + const result = isUserAnOwner(safeInstance, userAddress) + + // then + expect(result).toBe(expectedResult) + }) + it("Should return false if there's no `userAccount`", () => { + // given + const userAddress = null + const owners = List([makeOwner({ address: userAddress })]) + const safeInstance = makeSafe({ owners }) + const expectedResult = false + + // when + const result = isUserAnOwner(safeInstance, userAddress) + + // then + expect(result).toBe(expectedResult) + }) + it('Should return false if there are no owners for the Safe', () => { + // given + const userAddress = 'address1' + const owners = null + const safeInstance = makeSafe({ owners }) + const expectedResult = false + + // when + const result = isUserAnOwner(safeInstance, userAddress) + + // then + expect(result).toBe(expectedResult) + }) + it("Should return true if `userAccount` is not in the list of Safe's owners", () => { + // given + const userAddress = 'address1' + const owners = List([makeOwner({ address: userAddress })]) + const safeInstance = makeSafe({ owners }) + const expectedResult = true + + // when + const result = isUserAnOwner(safeInstance, userAddress) + + // then + expect(result).toBe(expectedResult) + }) + it("Should return false if `userAccount` is not in the list of Safe's owners", () => { + // given + const userAddress = 'address1' + const userAddress2 = 'address2' + const owners = List([makeOwner({ address: userAddress })]) + const safeInstance = makeSafe({ owners }) + const expectedResult = false + + // when + const result = isUserAnOwner(safeInstance, userAddress2) + + // then + expect(result).toBe(expectedResult) + }) + }) + + describe('Utility function: isUserAnOwnerOfAnySafe', () => { + it('Should return true if given a list of safes, one of them has an owner equal to the userAccount', () => { + // given + const userAddress = 'address1' + const userAddress2 = 'address2' + const owners1 = List([makeOwner({ address: userAddress })]) + const owners2 = List([makeOwner({ address: userAddress2 })]) + const safeInstance = makeSafe({ owners: owners1 }) + const safeInstance2 = makeSafe({ owners: owners2 }) + const safesList = List([safeInstance, safeInstance2]) + const expectedResult = true + + // when + const result = isUserAnOwnerOfAnySafe(safesList, userAddress) + + // then + expect(result).toBe(expectedResult) + }) + it('It should return false if given a list of safes, none of them has an owner equal to the userAccount', () => { + // given + const userAddress = 'address1' + const userAddress2 = 'address2' + const userAddress3 = 'address3' + const owners1 = List([makeOwner({ address: userAddress3 })]) + const owners2 = List([makeOwner({ address: userAddress2 })]) + const safeInstance = makeSafe({ owners: owners1 }) + const safeInstance2 = makeSafe({ owners: owners2 }) + const safesList = List([safeInstance, safeInstance2]) + const expectedResult = false + + // when + const result = isUserAnOwnerOfAnySafe(safesList, userAddress) + + // then + expect(result).toBe(expectedResult) + }) + }) + + describe('Utility function: isValidEnsName', () => { + it('If should return false if given no ens name', () => { + // given + const ensName = null + const expectedResult = false + + // when + const result = isValidEnsName(ensName) + + // then + expect(result).toBe(expectedResult) + }) + it('It should return false for an ens without extension in format [value].[eth|test|xyz|luxe]', () => { + // given + const ensName = 'test' + const expectedResult = false + + // when + const result = isValidEnsName(ensName) + + // then + expect(result).toBe(expectedResult) + }) + it('It should return false for an ens without the format [value].[eth|test|xyz|luxe]', () => { + // given + const ensName = 'test.et12312' + const expectedResult = false + + // when + const result = isValidEnsName(ensName) + + // then + expect(result).toBe(expectedResult) + }) + it('It should return true for an ens in format [value].eth', () => { + // given + const ensName = 'test.eth' + const expectedResult = true + + // when + const result = isValidEnsName(ensName) + + // then + expect(result).toBe(expectedResult) + }) + it('It should return true for ens in format [value].test', () => { + // given + const ensName = 'test.test' + const expectedResult = true + + // when + const result = isValidEnsName(ensName) + + // then + expect(result).toBe(expectedResult) + }) + it('It should return true for an ens in the format [value].xyz', () => { + // given + const ensName = 'test.xyz' + const expectedResult = true + + // when + const result = isValidEnsName(ensName) + + // then + expect(result).toBe(expectedResult) + }) + it('It should return true for an ens in format [value].luxe', () => { + // given + const ensName = 'test.luxe' + const expectedResult = true + + // when + const result = isValidEnsName(ensName) + + // then + expect(result).toBe(expectedResult) + }) + }) +}) diff --git a/src/logic/wallets/ethAddresses.ts b/src/logic/wallets/ethAddresses.ts index 300becaa..d45d0fea 100644 --- a/src/logic/wallets/ethAddresses.ts +++ b/src/logic/wallets/ethAddresses.ts @@ -1,17 +1,10 @@ import { List } from 'immutable' import { SafeRecord } from 'src/logic/safe/store/models/safe' +import { sameString } from 'src/utils/strings' export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' export const sameAddress = (firstAddress: string | undefined, secondAddress: string | undefined): boolean => { - if (!firstAddress) { - return false - } - - if (!secondAddress) { - return false - } - - return firstAddress.toLowerCase() === secondAddress.toLowerCase() + return sameString(firstAddress, secondAddress) } export const shortVersionOf = (value: string, cut: number): string => { diff --git a/src/logic/wallets/ethTransactions.ts b/src/logic/wallets/ethTransactions.ts index 745ac60a..cb5b2d14 100644 --- a/src/logic/wallets/ethTransactions.ts +++ b/src/logic/wallets/ethTransactions.ts @@ -2,6 +2,7 @@ import axios from 'axios' import { BigNumber } from 'bignumber.js' import { getWeb3, web3ReadOnly } from 'src/logic/wallets/getWeb3' +import { getGasPrice, getGasPriceOracle } from 'src/config' // const MAINNET_NETWORK = 1 export const EMPTY_DATA = '0x' @@ -26,7 +27,7 @@ export const checkReceiptStatus = async (hash) => { return Promise.resolve() } -export const calculateGasPrice = async () => { +export const calculateGasPrice = async (): Promise => { /* const web3 = getWeb3() const { network } = web3.version @@ -41,11 +42,23 @@ export const calculateGasPrice = async () => { return '20000000000' } - const url = 'https://ethgasstation.info/json/ethgasAPI.json' - // const errMsg = 'Error querying gas station' - const { data } = await axios.get(url) + const gasPrice = getGasPrice() + const gasPriceOracle = getGasPriceOracle() - return new BigNumber(data.average).multipliedBy(1e8).toString() + if (gasPrice) { + // Fixed gas price in configuration. xDai uses this approach + return new BigNumber(gasPrice).toString() + } else if (gasPriceOracle) { + const { url, gasParameter } = gasPriceOracle + + // Fetch from gas price provider + const { data } = await axios.get(url) + + return new BigNumber(data[gasParameter]).multipliedBy(1e8).toString() + } else { + const errorMsg = 'gasPrice or gasPriceOracle not set in config' + return Promise.reject(errorMsg) + } } export const calculateGasOf = async (data, from, to) => { diff --git a/src/logic/wallets/getWeb3.ts b/src/logic/wallets/getWeb3.ts index c3c7b0f4..ff1e26f7 100644 --- a/src/logic/wallets/getWeb3.ts +++ b/src/logic/wallets/getWeb3.ts @@ -1,24 +1,12 @@ import Web3 from 'web3' +import { provider as Provider } from 'web3-core' +import { ContentHash } from 'web3-eth-ens' import { sameAddress } from './ethAddresses' import { EMPTY_DATA } from './ethTransactions' - -import { getNetwork } from '../../config' -import { ContentHash } from 'web3-eth-ens' -import { provider as Provider } from 'web3-core' import { ProviderProps } from './store/model/provider' - -export const ETHEREUM_NETWORK = { - MAINNET: 'MAINNET' as const, - MORDEN: 'MORDEN' as const, - ROPSTEN: 'ROPSTEN' as const, - RINKEBY: 'RINKEBY' as const, - GOERLI: 'GOERLI' as const, - KOVAN: 'KOVAN' as const, - UNKNOWN: 'UNKNOWN' as const, -} - -export type EthereumNetworks = typeof ETHEREUM_NETWORK[keyof typeof ETHEREUM_NETWORK] +import { NODE_ENV } from 'src/utils/constants' +import { getRpcServiceUrl } from 'src/config' export const WALLET_PROVIDER = { SAFE: 'SAFE', @@ -38,34 +26,16 @@ export const WALLET_PROVIDER = { TREZOR: 'TREZOR', } -export const ETHEREUM_NETWORK_IDS = { - 1: ETHEREUM_NETWORK.MAINNET, - 2: ETHEREUM_NETWORK.MORDEN, - 3: ETHEREUM_NETWORK.ROPSTEN, - 4: ETHEREUM_NETWORK.RINKEBY, - 5: ETHEREUM_NETWORK.GOERLI, - 42: ETHEREUM_NETWORK.KOVAN, -} - -export const getEtherScanLink = (type: string, value: string): string => { - const network = getNetwork() - return `https://${ - network.toLowerCase() === 'mainnet' ? '' : `${network.toLowerCase()}.` - }etherscan.io/${type}/${value}` -} - -export const getInfuraUrl = (): string => { - const isMainnet = process.env.REACT_APP_NETWORK === 'mainnet' - - return `https://${isMainnet ? 'mainnet' : 'rinkeby'}.infura.io:443/v3/${process.env.REACT_APP_INFURA_TOKEN}` -} - // With some wallets from web3connect you have to use their provider instance only for signing // And our own one to fetch data -export const web3ReadOnly = +const httpProviderOptions = { + timeout: 10_000, +} +export const web3ReadOnly = new Web3( process.env.NODE_ENV !== 'test' - ? new Web3(new Web3.providers.HttpProvider(getInfuraUrl())) - : new Web3(window.web3?.currentProvider || 'ws://localhost:8545') + ? new Web3.providers.HttpProvider(getRpcServiceUrl(), httpProviderOptions) + : window.web3?.currentProvider || 'ws://localhost:8545', +) let web3 = web3ReadOnly export const getWeb3 = (): Web3 => web3 @@ -77,7 +47,7 @@ export const resetWeb3 = (): void => { export const getAccountFrom = async (web3Provider: Web3): Promise => { const accounts = await web3Provider.eth.getAccounts() - if (process.env.NODE_ENV === 'test' && window.testAccountIndex) { + if (NODE_ENV === 'test' && window.testAccountIndex) { return accounts[window.testAccountIndex] } diff --git a/src/logic/wallets/store/actions/fetchProvider.ts b/src/logic/wallets/store/actions/fetchProvider.ts index 3a7573fc..79ce4479 100644 --- a/src/logic/wallets/store/actions/fetchProvider.ts +++ b/src/logic/wallets/store/actions/fetchProvider.ts @@ -2,10 +2,10 @@ import ReactGA from 'react-ga' import addProvider from './addProvider' -import { getNetwork } from 'src/config' +import { getNetworkId, getNetworkInfo } from 'src/config' import { NOTIFICATIONS, enhanceSnackbarForAction } from 'src/logic/notifications' import enqueueSnackbar from 'src/logic/notifications/store/actions/enqueueSnackbar' -import { ETHEREUM_NETWORK, ETHEREUM_NETWORK_IDS, getProviderInfo, getWeb3 } from 'src/logic/wallets/getWeb3' +import { getProviderInfo, getWeb3 } from 'src/logic/wallets/getWeb3' import { makeProvider } from 'src/logic/wallets/store/model/provider' import { updateStoredTransactionsStatus } from 'src/logic/safe/store/actions/transactions/utils/transactionHelpers' import { Dispatch } from 'redux' @@ -24,12 +24,13 @@ const handleProviderNotification = (provider, dispatch) => { return } - if (ETHEREUM_NETWORK_IDS[network] !== getNetwork()) { + if (network !== getNetworkId()) { dispatch(enqueueSnackbar(NOTIFICATIONS.WRONG_NETWORK_MSG)) return } - if (ETHEREUM_NETWORK.RINKEBY === getNetwork()) { - dispatch(enqueueSnackbar(enhanceSnackbarForAction(NOTIFICATIONS.RINKEBY_VERSION_MSG))) + + if (getNetworkInfo().isTestNet) { + dispatch(enqueueSnackbar(enhanceSnackbarForAction(NOTIFICATIONS.TESTNET_VERSION_MSG))) } if (available) { diff --git a/src/logic/wallets/store/model/provider.ts b/src/logic/wallets/store/model/provider.ts index 1e8ad09a..146b2ddb 100644 --- a/src/logic/wallets/store/model/provider.ts +++ b/src/logic/wallets/store/model/provider.ts @@ -1,11 +1,13 @@ import { Record, RecordOf } from 'immutable' +import { ETHEREUM_NETWORK } from 'src/config/networks/network.d' + export type ProviderProps = { name: string loaded: boolean available: boolean account: string - network: number + network: ETHEREUM_NETWORK smartContractWallet: boolean hardwareWallet: boolean } @@ -15,7 +17,7 @@ export const makeProvider = Record({ loaded: false, available: false, account: '', - network: 0, + network: ETHEREUM_NETWORK.UNKNOWN, smartContractWallet: false, hardwareWallet: false, }) diff --git a/src/logic/wallets/store/selectors/index.ts b/src/logic/wallets/store/selectors/index.ts index ed147c38..56e41f67 100644 --- a/src/logic/wallets/store/selectors/index.ts +++ b/src/logic/wallets/store/selectors/index.ts @@ -1,6 +1,6 @@ import { createSelector } from 'reselect' -import { ETHEREUM_NETWORK, ETHEREUM_NETWORK_IDS, EthereumNetworks } from 'src/logic/wallets/getWeb3' +import { ETHEREUM_NETWORK } from 'src/config/networks/network.d' import { PROVIDER_REDUCER_ID, ProviderState } from 'src/logic/wallets/store/reducer/provider' import { AppReduxState } from 'src/store' @@ -18,9 +18,10 @@ export const providerNameSelector = createSelector(providerSelector, (provider: export const networkSelector = createSelector( providerSelector, - (provider: ProviderState): EthereumNetworks => { + (provider: ProviderState): ETHEREUM_NETWORK => { const networkId = provider.get('network') - return ETHEREUM_NETWORK_IDS[networkId] || ETHEREUM_NETWORK.UNKNOWN + + return networkId ?? ETHEREUM_NETWORK.UNKNOWN }, ) diff --git a/src/logic/wallets/tests/ethAddresses.test.ts b/src/logic/wallets/tests/ethAddresses.test.ts deleted file mode 100644 index 5191d21b..00000000 --- a/src/logic/wallets/tests/ethAddresses.test.ts +++ /dev/null @@ -1,282 +0,0 @@ -//@ts-nocheck -import { - isUserAnOwner, - isUserAnOwnerOfAnySafe, - isValidEnsName, - sameAddress, - shortVersionOf, -} from 'src/logic/wallets/ethAddresses' -import makeSafe from 'src/logic/safe/store/models/safe' -import { makeOwner } from 'src/logic/safe/store/models/owner' -import { List } from 'immutable' - -describe('Utility function: sameAddress', () => { - it('It should return false if no address given', () => { - // given - const safeAddress = null - const safeAddress2 = '0x344B941b1aAE2e4Be73987212FC4741687Bf0503' - - // when - const result = sameAddress(safeAddress, safeAddress2) - - // then - expect(result).toBe(false) - }) - it('It should return false if not second address given', () => { - // given - const safeAddress = '0xdfA693da0D16F5E7E78FdCBeDe8FC6eBEa44f1Cf' - const safeAddress2 = null - - // when - const result = sameAddress(safeAddress, safeAddress2) - - // then - expect(result).toBe(false) - }) - it('It should return true if two equal addresses given', () => { - // given - const safeAddress = '0xdfA693da0D16F5E7E78FdCBeDe8FC6eBEa44f1Cf' - - // when - const result = sameAddress(safeAddress, safeAddress) - - // then - expect(result).toBe(true) - }) - it('If should return false if two different addresses given', () => { - // given - const safeAddress = '0xdfA693da0D16F5E7E78FdCBeDe8FC6eBEa44f1Cf' - const safeAddress2 = '0x344B941b1aAE2e4Be73987212FC4741687Bf0503' - - // when - const result = sameAddress(safeAddress, safeAddress2) - - // then - expect(result).toBe(false) - }) -}) - -describe('Utility function: shortVersionOf', () => { - it('It should return Unknown if no address given', () => { - // given - const safeAddress = null - const cut = 5 - const expectedResult = 'Unknown' - - // when - const result = shortVersionOf(safeAddress, cut) - - // then - expect(result).toBe(expectedResult) - }) - it('It should return 0x344...f0503 if given 0x344B941b1aAE2e4Be73987212FC4741687Bf0503 and a cut = 5', () => { - // given - const safeAddress = '0x344B941b1aAE2e4Be73987212FC4741687Bf0503' - const cut = 5 - const expectedResult = `0x344...f0503` - - // when - const result = shortVersionOf(safeAddress, cut) - - // then - expect(result).toBe(expectedResult) - }) - it('If should return the same address if a cut value bigger than the address length given', () => { - // given - const safeAddress = '0x344B941b1aAE2e4Be73987212FC4741687Bf0503' - const cut = safeAddress.length - const expectedResult = safeAddress - - // when - const result = shortVersionOf(safeAddress, cut) - - // then - expect(result).toBe(expectedResult) - }) -}) - -describe('Utility function: isUserAnOwner', () => { - it("Should return false if there's no Safe", () => { - // given - const userAddress = 'address1' - const safeInstance = null - const expectedResult = false - - // when - const result = isUserAnOwner(safeInstance, userAddress) - - // then - expect(result).toBe(expectedResult) - }) - it("Should return false if there's no `userAccount`", () => { - // given - const userAddress = null - const owners = List([makeOwner({ address: userAddress })]) - const safeInstance = makeSafe({ owners }) - const expectedResult = false - - // when - const result = isUserAnOwner(safeInstance, userAddress) - - // then - expect(result).toBe(expectedResult) - }) - it('Should return false if there are no owners for the Safe', () => { - // given - const userAddress = 'address1' - const owners = null - const safeInstance = makeSafe({ owners }) - const expectedResult = false - - // when - const result = isUserAnOwner(safeInstance, userAddress) - - // then - expect(result).toBe(expectedResult) - }) - it("Should return true if `userAccount` is not in the list of Safe's owners", () => { - // given - const userAddress = 'address1' - const owners = List([makeOwner({ address: userAddress })]) - const safeInstance = makeSafe({ owners }) - const expectedResult = true - - // when - const result = isUserAnOwner(safeInstance, userAddress) - - // then - expect(result).toBe(expectedResult) - }) - it("Should return false if `userAccount` is not in the list of Safe's owners", () => { - // given - const userAddress = 'address1' - const userAddress2 = 'address2' - const owners = List([makeOwner({ address: userAddress })]) - const safeInstance = makeSafe({ owners }) - const expectedResult = false - - // when - const result = isUserAnOwner(safeInstance, userAddress2) - - // then - expect(result).toBe(expectedResult) - }) -}) - -describe('Utility function: isUserAnOwnerOfAnySafe', () => { - it('Should return true if given a list of safes, one of them has an owner equal to the userAccount', () => { - // given - const userAddress = 'address1' - const userAddress2 = 'address2' - const owners1 = List([makeOwner({ address: userAddress })]) - const owners2 = List([makeOwner({ address: userAddress2 })]) - const safeInstance = makeSafe({ owners: owners1 }) - const safeInstance2 = makeSafe({ owners: owners2 }) - const safesList = List([safeInstance, safeInstance2]) - const expectedResult = true - - // when - const result = isUserAnOwnerOfAnySafe(safesList, userAddress) - - // then - expect(result).toBe(expectedResult) - }) - it('It should return false if given a list of safes, none of them has an owner equal to the userAccount', () => { - // given - const userAddress = 'address1' - const userAddress2 = 'address2' - const userAddress3 = 'address3' - const owners1 = List([makeOwner({ address: userAddress3 })]) - const owners2 = List([makeOwner({ address: userAddress2 })]) - const safeInstance = makeSafe({ owners: owners1 }) - const safeInstance2 = makeSafe({ owners: owners2 }) - const safesList = List([safeInstance, safeInstance2]) - const expectedResult = false - - // when - const result = isUserAnOwnerOfAnySafe(safesList, userAddress) - - // then - expect(result).toBe(expectedResult) - }) -}) - -describe('Utility function: isValidEnsName', () => { - it('If should return false if given no ens name', () => { - // given - const ensName = null - const expectedResult = false - - // when - const result = isValidEnsName(ensName) - - // then - expect(result).toBe(expectedResult) - }) - it('It should return false for an ens without extension in format [value].[eth|test|xyz|luxe]', () => { - // given - const ensName = 'test' - const expectedResult = false - - // when - const result = isValidEnsName(ensName) - - // then - expect(result).toBe(expectedResult) - }) - it('It should return false for an ens without the format [value].[eth|test|xyz|luxe]', () => { - // given - const ensName = 'test.et12312' - const expectedResult = false - - // when - const result = isValidEnsName(ensName) - - // then - expect(result).toBe(expectedResult) - }) - it('It should return true for an ens in format [value].eth', () => { - // given - const ensName = 'test.eth' - const expectedResult = true - - // when - const result = isValidEnsName(ensName) - - // then - expect(result).toBe(expectedResult) - }) - it('It should return true for ens in format [value].test', () => { - // given - const ensName = 'test.test' - const expectedResult = true - - // when - const result = isValidEnsName(ensName) - - // then - expect(result).toBe(expectedResult) - }) - it('It should return true for an ens in the format [value].xyz', () => { - // given - const ensName = 'test.xyz' - const expectedResult = true - - // when - const result = isValidEnsName(ensName) - - // then - expect(result).toBe(expectedResult) - }) - it('It should return true for an ens in format [value].luxe', () => { - // given - const ensName = 'test.luxe' - const expectedResult = true - - // when - const result = isValidEnsName(ensName) - - // then - expect(result).toBe(expectedResult) - }) -}) diff --git a/src/logic/wallets/utils/walletList.ts b/src/logic/wallets/utils/walletList.ts index 70452f18..05e2b730 100644 --- a/src/logic/wallets/utils/walletList.ts +++ b/src/logic/wallets/utils/walletList.ts @@ -1,63 +1,70 @@ -import { getInfuraUrl } from '../getWeb3' +import { WalletInitOptions } from 'bnc-onboard/dist/src/interfaces' -const isMainnet = process.env.REACT_APP_NETWORK === 'mainnet' +import { getNetworkId, getRpcServiceUrl, getNetworkConfigDisabledWallets } from 'src/config' +import { WALLETS } from 'src/config/networks/network.d' +import { FORTMATIC_KEY, PORTIS_ID } from 'src/utils/constants' -const PORTIS_DAPP_ID = isMainnet ? process.env.REACT_APP_PORTIS_ID : '852b763d-f28b-4463-80cb-846d7ec5806b' -// const SQUARELINK_CLIENT_ID = isMainnet ? process.env.REACT_APP_SQUARELINK_ID : '46ce08fe50913cfa1b78' -const FORTMATIC_API_KEY = isMainnet ? process.env.REACT_APP_FORTMATIC_KEY : 'pk_test_CAD437AA29BE0A40' +const networkId = getNetworkId() +const disabledWallets = getNetworkConfigDisabledWallets() -const infuraUrl = getInfuraUrl() +type Wallet = WalletInitOptions & { + desktop: boolean + walletName: WALLETS +} -const wallets = [ - { walletName: 'metamask', preferred: true, desktop: false }, +const rpcUrl = getRpcServiceUrl() +const wallets: Wallet[] = [ + { walletName: WALLETS.METAMASK, preferred: true, desktop: false }, { - walletName: 'walletConnect', + walletName: WALLETS.WALLET_CONNECT, preferred: true, - infuraKey: process.env.REACT_APP_INFURA_TOKEN, + // as stated in the documentation, `infuraKey` is not mandatory if rpc is provided + rpc: { [networkId]: rpcUrl }, desktop: true, bridge: 'https://safe-walletconnect.gnosis.io/', }, { - walletName: 'trezor', + walletName: WALLETS.TREZOR, appUrl: 'gnosis-safe.io', preferred: true, email: 'safe@gnosis.io', desktop: true, - rpcUrl: infuraUrl, + rpcUrl, }, { - walletName: 'ledger', + walletName: WALLETS.LEDGER, desktop: true, preferred: true, - rpcUrl: infuraUrl, + rpcUrl, LedgerTransport: (window as any).TransportNodeHid, }, - { walletName: 'trust', preferred: true, desktop: false }, - { walletName: 'dapper', desktop: false }, + { walletName: WALLETS.TRUST, preferred: true, desktop: false }, + { walletName: WALLETS.DAPPER, desktop: false }, { - walletName: 'fortmatic', - apiKey: FORTMATIC_API_KEY, + walletName: WALLETS.FORTMATIC, + apiKey: FORTMATIC_KEY, desktop: true, }, { - walletName: 'portis', - apiKey: PORTIS_DAPP_ID, + walletName: WALLETS.PORTIS, + apiKey: PORTIS_ID, desktop: true, }, - { walletName: 'authereum', desktop: false }, - { walletName: 'torus', desktop: true }, - { walletName: 'unilogin', desktop: true }, - { walletName: 'coinbase', desktop: false }, - { walletName: 'walletLink', rpcUrl: infuraUrl, desktop: false }, - { walletName: 'opera', desktop: false }, - { walletName: 'operaTouch', desktop: false }, + { walletName: WALLETS.AUTHEREUM, desktop: false }, + { walletName: WALLETS.TORUS, desktop: true }, + { walletName: WALLETS.UNILOGIN, desktop: true }, + { walletName: WALLETS.COINBASE, desktop: false }, + { walletName: WALLETS.WALLET_LINK, rpcUrl, desktop: false }, + { walletName: WALLETS.OPERA, desktop: false }, + { walletName: WALLETS.OPERA_TOUCH, desktop: false }, ] -export const getSupportedWallets = () => { +export const getSupportedWallets = (): WalletInitOptions[] => { const { isDesktop } = window as any /* eslint-disable no-unused-vars */ + if (isDesktop) { + return wallets.filter((wallet) => wallet.desktop).map(({ desktop, ...rest }) => rest) + } - if (isDesktop) return wallets.filter((wallet) => wallet.desktop).map(({ desktop, ...rest }) => rest) - - return wallets.map(({ desktop, ...rest }) => rest) + return wallets.map(({ desktop, ...rest }) => rest).filter((w) => !disabledWallets.includes(w.walletName)) } diff --git a/src/routes/load/components/DetailsForm/index.tsx b/src/routes/load/components/DetailsForm/index.tsx index 66a198b9..1524f9e1 100644 --- a/src/routes/load/components/DetailsForm/index.tsx +++ b/src/routes/load/components/DetailsForm/index.tsx @@ -73,7 +73,7 @@ export const safeFieldsValidation = async (values): Promise { @@ -112,7 +112,7 @@ const OwnerListComponent = (props) => { {address} - + diff --git a/src/routes/load/components/ReviewInformation/index.tsx b/src/routes/load/components/ReviewInformation/index.tsx index 49a7588f..2c5ba075 100644 --- a/src/routes/load/components/ReviewInformation/index.tsx +++ b/src/routes/load/components/ReviewInformation/index.tsx @@ -5,12 +5,12 @@ import React from 'react' import CopyBtn from 'src/components/CopyBtn' import EtherscanBtn from 'src/components/EtherscanBtn' import Identicon from 'src/components/Identicon' -import OpenPaper from 'src/components/Stepper/OpenPaper' import Block from 'src/components/layout/Block' import Col from 'src/components/layout/Col' import Hairline from 'src/components/layout/Hairline' import Paragraph from 'src/components/layout/Paragraph' import Row from 'src/components/layout/Row' +import OpenPaper from 'src/components/Stepper/OpenPaper' import { shortVersionOf } from 'src/logic/wallets/ethAddresses' import { FIELD_LOAD_ADDRESS, FIELD_LOAD_NAME, THRESHOLD } from 'src/routes/load/components/fields' import { getNumOwnersFrom, getOwnerAddressBy, getOwnerNameBy } from 'src/routes/open/components/fields' @@ -76,7 +76,7 @@ const ReviewComponent = ({ userAddress, values }: Props): React.ReactElement => {shortVersionOf(safeAddress, 4)} - +
@@ -121,7 +121,7 @@ const ReviewComponent = ({ userAddress, values }: Props): React.ReactElement => {address} - + diff --git a/src/routes/load/container/Load.tsx b/src/routes/load/container/Load.tsx index a3452bfd..6e4b5305 100644 --- a/src/routes/load/container/Load.tsx +++ b/src/routes/load/container/Load.tsx @@ -1,5 +1,6 @@ import * as React from 'react' import { useDispatch, useSelector } from 'react-redux' +import { ETHEREUM_NETWORK } from 'src/config/networks/network.d' import Layout from 'src/routes/load/components/Layout' import { FIELD_LOAD_ADDRESS, FIELD_LOAD_NAME } from '../components/fields' @@ -77,7 +78,12 @@ const Load = (): React.ReactElement => { return ( - + ) } diff --git a/src/routes/open/components/ReviewInformation/index.tsx b/src/routes/open/components/ReviewInformation/index.tsx index c5d6c4c1..4c901b40 100644 --- a/src/routes/open/components/ReviewInformation/index.tsx +++ b/src/routes/open/components/ReviewInformation/index.tsx @@ -1,22 +1,22 @@ import TableContainer from '@material-ui/core/TableContainer' import classNames from 'classnames' import React, { useEffect, useState } from 'react' - -import { FIELD_CONFIRMATIONS, FIELD_NAME, getNumOwnersFrom } from '../fields' - +import { fromTokenUnit } from 'src/logic/tokens/utils/humanReadableValue' +import { getNetworkInfo } from 'src/config' import CopyBtn from 'src/components/CopyBtn' import EtherscanBtn from 'src/components/EtherscanBtn' import Identicon from 'src/components/Identicon' -import OpenPaper from 'src/components/Stepper/OpenPaper' import Block from 'src/components/layout/Block' import Col from 'src/components/layout/Col' import Hairline from 'src/components/layout/Hairline' import Paragraph from 'src/components/layout/Paragraph' import Row from 'src/components/layout/Row' +import OpenPaper from 'src/components/Stepper/OpenPaper' import { estimateGasForDeployingSafe } from 'src/logic/contracts/safeContracts' import { formatAmount } from 'src/logic/tokens/utils/formatAmount' -import { getWeb3 } from 'src/logic/wallets/getWeb3' import { getAccountsFrom, getNamesFrom } from 'src/routes/open/utils/safeDataExtractor' + +import { FIELD_CONFIRMATIONS, FIELD_NAME, getNumOwnersFrom } from '../fields' import { useStyles } from './styles' type ReviewComponentProps = { @@ -24,6 +24,8 @@ type ReviewComponentProps = { values: any } +const { nativeCoin } = getNetworkInfo() + const ReviewComponent = ({ userAccount, values }: ReviewComponentProps) => { const classes = useStyles() @@ -37,11 +39,9 @@ const ReviewComponent = ({ userAccount, values }: ReviewComponentProps) => { if (!addresses.length || !numOwners || !userAccount) { return } - const web3 = getWeb3() - const { fromWei, toBN } = web3.utils - const estimatedGasCosts = await estimateGasForDeployingSafe(addresses, numOwners, userAccount) - const gasCostsAsEth = fromWei(toBN(estimatedGasCosts), 'ether') - const formattedGasCosts = formatAmount(gasCostsAsEth) + const estimatedGasCosts = (await estimateGasForDeployingSafe(addresses, numOwners, userAccount)).toString() + const gasCosts = fromTokenUnit(estimatedGasCosts, nativeCoin.decimals) + const formattedGasCosts = formatAmount(gasCosts) setGasCosts(formattedGasCosts) } @@ -118,7 +118,7 @@ const ReviewComponent = ({ userAccount, values }: ReviewComponentProps) => { {addresses[index]} - + @@ -132,8 +132,8 @@ const ReviewComponent = ({ userAccount, values }: ReviewComponentProps) => { You're about to create a new Safe and will have to confirm a transaction with your currently connected - wallet. The creation will cost approximately {gasCosts} ETH. The exact amount will be determined by your - wallet. + wallet. The creation will cost approximately {gasCosts} {nativeCoin.name}. The exact amount will be determined + by your wallet. diff --git a/src/routes/open/container/Open.tsx b/src/routes/open/container/Open.tsx index 360d3884..d6f043a3 100644 --- a/src/routes/open/container/Open.tsx +++ b/src/routes/open/container/Open.tsx @@ -22,6 +22,7 @@ import { loadFromStorage, removeFromStorage, saveToStorage } from 'src/utils/sto import { userAccountSelector } from 'src/logic/wallets/store/selectors' import { SafeRecordProps } from 'src/logic/safe/store/models/safe' import { addOrUpdateSafe } from 'src/logic/safe/store/actions/addOrUpdateSafe' +import { PromiEvent, TransactionReceipt } from 'web3-core' const SAFE_PENDING_CREATION_STORAGE_KEY = 'SAFE_PENDING_CREATION_STORAGE_KEY' @@ -60,7 +61,7 @@ export const createSafe = (values, userAccount) => { const deploymentTx = getSafeDeploymentTransaction(ownerAddresses, confirmations) - const promiEvent = deploymentTx.send({ from: userAccount, value: 0 }) + const promiEvent = deploymentTx.send({ from: userAccount }) promiEvent .once('transactionHash', (txHash) => { @@ -68,7 +69,7 @@ export const createSafe = (values, userAccount) => { }) .then(async (receipt) => { await checkReceiptStatus(receipt.transactionHash) - const safeAddress = receipt.events.ProxyCreation.returnValues.proxy + const safeAddress = receipt.events?.ProxyCreation.returnValues.proxy const safeProps = await getSafeProps(safeAddress, name, ownersNames, ownerAddresses) // returning info for testing purposes, in app is fully async return { safeAddress: safeProps.address, safeTx: receipt } @@ -83,7 +84,7 @@ export const createSafe = (values, userAccount) => { const Open = (): React.ReactElement => { const [loading, setLoading] = useState(false) const [showProgress, setShowProgress] = useState(false) - const [creationTxPromise, setCreationTxPromise] = useState() + const [creationTxPromise, setCreationTxPromise] = useState>() const [safeCreationPendingInfo, setSafeCreationPendingInfo] = useState() const [safePropsFromUrl, setSafePropsFromUrl] = useState() const userAccount = useSelector(userAccountSelector) @@ -171,7 +172,7 @@ const Open = (): React.ReactElement => { } const onRetry = async () => { - const values = await loadFromStorage<{ txHash: string }>(SAFE_PENDING_CREATION_STORAGE_KEY) + const values = await loadFromStorage<{ txHash?: string }>(SAFE_PENDING_CREATION_STORAGE_KEY) delete values?.txHash await saveToStorage(SAFE_PENDING_CREATION_STORAGE_KEY, values) setSafeCreationPendingInfo(values) diff --git a/src/routes/opening/components/Footer.tsx b/src/routes/opening/components/Footer.tsx index 292000e3..8f213484 100644 --- a/src/routes/opening/components/Footer.tsx +++ b/src/routes/opening/components/Footer.tsx @@ -2,10 +2,10 @@ import React, { SyntheticEvent } from 'react' import styled from 'styled-components' import Button from 'src/components/layout/Button' -import { getEtherScanLink } from 'src/logic/wallets/getWeb3' import { connected } from 'src/theme/variables' +import { getExplorerInfo } from 'src/config' -const EtherScanLink = styled.a` +const ExplorerLink = styled.a` color: ${connected}; ` @@ -13,24 +13,31 @@ const ButtonWithMargin = styled(Button)` margin-right: 16px; ` -export const GenericFooter = ({ safeCreationTxHash }: { safeCreationTxHash: string }) => ( - -

This process should take a couple of minutes.

-

- Follow the progress on{' '} - - Etherscan.io - - . -

-
-) +export const GenericFooter = ({ safeCreationTxHash }: { safeCreationTxHash: string }) => { + const explorerInfo = getExplorerInfo(safeCreationTxHash) + const { url, alt } = explorerInfo() + const match = /(http|https):\/\/(\w+\.\w+)\/.*/i.exec(url) + const explorerDomain = match !== null ? match[2] : 'Network Explorer' + + return ( + +

This process should take a couple of minutes.

+

+ Follow the progress on{' '} + + {explorerDomain} + + . +

+
+ ) +} export const ContinueFooter = ({ continueButtonDisabled, diff --git a/src/routes/safe/components/AddressBook/index.tsx b/src/routes/safe/components/AddressBook/index.tsx index 42597e64..b10cc4c4 100644 --- a/src/routes/safe/components/AddressBook/index.tsx +++ b/src/routes/safe/components/AddressBook/index.tsx @@ -40,7 +40,6 @@ import { addressBookQueryParamsSelector, safesListSelector } from 'src/logic/saf import { checksumAddress } from 'src/utils/checksumAddress' import { grantedSelector } from 'src/routes/safe/container/selector' import { useAnalytics, SAFE_NAVIGATION_EVENT } from 'src/utils/googleAnalytics' -import { getValidAddressBookName } from 'src/logic/addressBook/utils' const useStyles = makeStyles(styles) @@ -167,7 +166,7 @@ const AddressBookTable = (): React.ReactElement => { {column.id === AB_ADDRESS_ID ? ( ) : ( - getValidAddressBookName(row[column.id]) + row[column.id] )} ) diff --git a/src/routes/safe/components/Apps/components/ConfirmTransactionModal.tsx b/src/routes/safe/components/Apps/components/ConfirmTransactionModal.tsx index 01353288..949e5bb9 100644 --- a/src/routes/safe/components/Apps/components/ConfirmTransactionModal.tsx +++ b/src/routes/safe/components/Apps/components/ConfirmTransactionModal.tsx @@ -1,7 +1,8 @@ -import React from 'react' +import React, { useEffect, useState } from 'react' import { Icon, Text, Title, GenericModal, ModalFooterConfirmation } from '@gnosis.pm/safe-react-components' -import { Transaction } from '@gnosis.pm/safe-apps-sdk' +import { Transaction, SendTransactionParams } from '@gnosis.pm/safe-apps-sdk' import styled from 'styled-components' +import { useDispatch } from 'react-redux' import AddressInfo from 'src/components/AddressInfo' import DividerLine from 'src/components/DividerLine' @@ -14,12 +15,15 @@ import Heading from 'src/components/layout/Heading' import Img from 'src/components/layout/Img' import { getEthAsToken } from 'src/logic/tokens/utils/tokenHelpers' import { SafeApp } from 'src/routes/safe/components/Apps/types.d' -import { humanReadableValue } from 'src/logic/tokens/utils/humanReadableValue' -import { useDispatch } from 'react-redux' +import { fromTokenUnit } from 'src/logic/tokens/utils/humanReadableValue' import createTransaction from 'src/logic/safe/store/actions/createTransaction' import { MULTI_SEND_ADDRESS } from 'src/logic/contracts/safeContracts' import { DELEGATE_CALL, TX_NOTIFICATION_TYPES } from 'src/logic/safe/transactions' import { encodeMultiSendCall } from 'src/logic/safe/transactions/multisend' +import { estimateSafeTxGas } from 'src/logic/safe/transactions/gas' + +import GasEstimationInfo from './GasEstimationInfo' +import { getNetworkInfo } from 'src/config' const isTxValid = (t: Transaction): boolean => { if (!['string', 'number'].includes(typeof t.value)) { @@ -66,6 +70,7 @@ type OwnProps = { isOpen: boolean app: SafeApp txs: Transaction[] + params?: SendTransactionParams safeAddress: string safeName: string ethBalance: string @@ -74,6 +79,8 @@ type OwnProps = { onClose: () => void } +const { nativeCoin } = getNetworkInfo() + const ConfirmTransactionModal = ({ isOpen, app, @@ -81,10 +88,39 @@ const ConfirmTransactionModal = ({ safeAddress, ethBalance, safeName, + params, onUserConfirm, onClose, onTxReject, }: OwnProps): React.ReactElement | null => { + const [estimatedSafeTxGas, setEstimatedSafeTxGas] = useState(0) + const [estimatingGas, setEstimatingGas] = useState(false) + + useEffect(() => { + const estimateGas = async () => { + try { + setEstimatingGas(true) + const safeTxGas = await estimateSafeTxGas( + undefined, + safeAddress, + encodeMultiSendCall(txs), + MULTI_SEND_ADDRESS, + '0', + DELEGATE_CALL, + ) + + setEstimatedSafeTxGas(safeTxGas) + } catch (err) { + console.error(err) + } finally { + setEstimatingGas(false) + } + } + if (params?.safeTxGas) { + estimateGas() + } + }, [params, safeAddress, txs]) + const dispatch = useDispatch() if (!isOpen) { return null @@ -114,6 +150,7 @@ const ConfirmTransactionModal = ({ notifiedTransaction: TX_NOTIFICATION_TYPES.STANDARD_TX, origin: app.id, navigateToTransactionsTab: false, + safeTxGas: Math.max(params?.safeTxGas || 0, estimatedSafeTxGas), }, handleUserConfirmation, handleTxRejection, @@ -146,7 +183,9 @@ const ConfirmTransactionModal = ({ Value
Ether - {humanReadableValue(tx.value, 18)} ETH + + {fromTokenUnit(tx.value, nativeCoin.decimals)} {nativeCoin.name} +
@@ -157,6 +196,18 @@ const ConfirmTransactionModal = ({ ))} + + {params?.safeTxGas && ( +
+ SafeTxGas + {params?.safeTxGas} + +
+ )} ) diff --git a/src/routes/safe/components/Apps/components/GasEstimationInfo.tsx b/src/routes/safe/components/Apps/components/GasEstimationInfo.tsx new file mode 100644 index 00000000..07d09af7 --- /dev/null +++ b/src/routes/safe/components/Apps/components/GasEstimationInfo.tsx @@ -0,0 +1,47 @@ +import React from 'react' +import styled from 'styled-components' +import Img from 'src/components/layout/Img' +import CheckIcon from 'src/assets/icons/check.svg' +import AlertIcon from 'src/assets/icons/alert.svg' + +type OwnProps = { + appEstimation: number + internalEstimation: number + loading: boolean +} + +const Container = styled.div` + display: flex; + align-items: center; +` + +const imgStyles = { + marginRight: '5px', +} + +const GasEstimationInfo = ({ appEstimation, internalEstimation, loading }: OwnProps): React.ReactElement => { + if (loading) { + return

Checking transaction parameters...

+ } + + let content: React.ReactElement | null = null + if (appEstimation >= internalEstimation) { + content = ( + <> + Success Gas estimation is OK + + ) + } + + if (internalEstimation === 0) { + content = ( + <> + Warning Error while estimating gas. The transaction may fail. + + ) + } + + return {content} +} + +export default GasEstimationInfo diff --git a/src/routes/safe/components/Apps/hooks/useAppList.ts b/src/routes/safe/components/Apps/hooks/useAppList.ts index fc48a716..c2f13c13 100644 --- a/src/routes/safe/components/Apps/hooks/useAppList.ts +++ b/src/routes/safe/components/Apps/hooks/useAppList.ts @@ -2,6 +2,7 @@ import { useState, useEffect, useCallback } from 'react' import { loadFromStorage, saveToStorage } from 'src/utils/storage' import { getAppInfoFromUrl, staticAppsList } from '../utils' import { SafeApp, StoredSafeApp } from '../types' +import { getNetworkId } from 'src/config' const APPS_STORAGE_KEY = 'APPS_STORAGE_KEY' @@ -28,20 +29,31 @@ const useAppList = (): UseAppListReturnType => { // * third-party apps added by the user // * disabled status for both static and third-party apps const persistedAppList = (await loadFromStorage(APPS_STORAGE_KEY)) || [] - const list: (StoredSafeApp & { isDeletable?: boolean })[] = persistedAppList.map((a) => ({ + let list: (StoredSafeApp & { isDeletable: boolean; networks?: number[] })[] = persistedAppList.map((a) => ({ ...a, isDeletable: true, })) + // merge stored apps with static apps (apps added manually can be deleted by the user) staticAppsList.forEach((staticApp) => { const app = list.find((persistedApp) => persistedApp.url === staticApp.url) - if (!app) { - list.push({ ...staticApp, isDeletable: false }) - } else { + if (app) { app.isDeletable = false + app.networks = staticApp.networks + } else { + list.push({ ...staticApp, isDeletable: false }) } }) + // filter app by network + list = list.filter((app) => { + // if the app does not expose supported networks, include them. (backward compatible) + if (!app.networks) { + return true + } + return app.networks.includes(getNetworkId()) + }) + let apps: SafeApp[] = [] // using the appURL to recover app info for (let index = 0; index < list.length; index++) { diff --git a/src/routes/safe/components/Apps/hooks/useIframeMessageHandler.ts b/src/routes/safe/components/Apps/hooks/useIframeMessageHandler.ts index a1a0e695..3ca4844a 100644 --- a/src/routes/safe/components/Apps/hooks/useIframeMessageHandler.ts +++ b/src/routes/safe/components/Apps/hooks/useIframeMessageHandler.ts @@ -9,16 +9,17 @@ import { RequestId, Transaction, LowercaseNetworks, + SendTransactionParams, } from '@gnosis.pm/safe-apps-sdk' import { useDispatch, useSelector } from 'react-redux' import { useEffect, useCallback, MutableRefObject } from 'react' -import { getTxServiceHost } from 'src/config/' +import { getNetworkName, getTxServiceUrl } from 'src/config/' import { safeEthBalanceSelector, safeNameSelector, safeParamAddressFromStateSelector, } from 'src/logic/safe/store/selectors' -import { networkSelector } from 'src/logic/wallets/store/selectors' +import { web3ReadOnly } from 'src/logic/wallets/getWeb3' import { SafeApp } from 'src/routes/safe/components/Apps/types.d' type InterfaceMessageProps = { @@ -38,13 +39,11 @@ interface CustomMessageEvent extends MessageEvent { } } -interface InterfaceMessageRequest extends InterfaceMessageProps { - requestId: number | string -} +const NETWORK_NAME = getNetworkName() const useIframeMessageHandler = ( selectedApp: SafeApp | undefined, - openConfirmationModal: (txs: Transaction[], requestId: RequestId) => void, + openConfirmationModal: (txs: Transaction[], params: SendTransactionParams | undefined, requestId: RequestId) => void, closeModal: () => void, iframeRef: MutableRefObject, ): ReturnType => { @@ -52,7 +51,6 @@ const useIframeMessageHandler = ( const safeName = useSelector(safeNameSelector) const safeAddress = useSelector(safeParamAddressFromStateSelector) const ethBalance = useSelector(safeEthBalanceSelector) - const network = useSelector(networkSelector) const dispatch = useDispatch() const sendMessageToIframe = useCallback( @@ -70,17 +68,65 @@ const useIframeMessageHandler = ( ) useEffect(() => { - const handleIframeMessage = (msg: CustomMessageEvent) => { - if (!msg?.data.messageId) { + const handleIframeMessage = ( + messageId: SDKMessageIds, + messagePayload: SDKMessageToPayload[typeof messageId], + requestId: RequestId, + ): void => { + if (!messageId) { console.error('ThirdPartyApp: A message was received without message id.') return } - const { requestId } = msg.data - switch (msg.data.messageId) { + switch (messageId) { + // typescript doesn't narrow type in switch/case statements + // issue: https://github.com/microsoft/TypeScript/issues/20375 + // possible solution: https://stackoverflow.com/a/43879897/7820085 case SDK_MESSAGES.SEND_TRANSACTIONS: { - if (msg.data.data) { - openConfirmationModal(msg.data.data, requestId) + if (messagePayload) { + openConfirmationModal( + messagePayload as SDKMessageToPayload[typeof SDK_MESSAGES.SEND_TRANSACTIONS], + undefined, + requestId, + ) + } + break + } + + case SDK_MESSAGES.SEND_TRANSACTIONS_V2: { + const payload = messagePayload as SDKMessageToPayload[typeof SDK_MESSAGES.SEND_TRANSACTIONS_V2] + if (payload) { + openConfirmationModal(payload.txs, payload.params, requestId) + } + break + } + + case SDK_MESSAGES.RPC_CALL: { + const payload = messagePayload as SDKMessageToPayload['RPC_CALL'] + + if ( + web3ReadOnly.currentProvider !== null && + typeof web3ReadOnly.currentProvider !== 'string' && + 'send' in web3ReadOnly.currentProvider + ) { + web3ReadOnly.currentProvider?.send?.( + { + jsonrpc: '2.0', + method: payload?.call, + params: payload?.params, + id: '1', + }, + (err, res) => { + if (!err) { + const rpcCallMsg = { + messageId: INTERFACE_MESSAGES.RPC_CALL_RESPONSE, + data: res, + } + + sendMessageToIframe(rpcCallMsg, requestId) + } + }, + ) } break } @@ -90,14 +136,14 @@ const useIframeMessageHandler = ( messageId: INTERFACE_MESSAGES.ON_SAFE_INFO, data: { safeAddress: safeAddress as string, - network: network.toLowerCase() as LowercaseNetworks, + network: NETWORK_NAME.toLowerCase() as LowercaseNetworks, ethBalance: ethBalance as string, }, } const envInfoMessage = { messageId: INTERFACE_MESSAGES.ENV_INFO, data: { - txServiceUrl: getTxServiceHost(), + txServiceUrl: getTxServiceUrl(), }, } @@ -106,7 +152,7 @@ const useIframeMessageHandler = ( break } default: { - console.error(`ThirdPartyApp: A message was received with an unknown message id ${msg.data.messageId}.`) + console.error(`ThirdPartyApp: A message was received with an unknown message id ${messageId}.`) break } } @@ -119,7 +165,7 @@ const useIframeMessageHandler = ( console.error(`ThirdPartyApp: A message was received from an unknown origin ${message.origin}`) return } - handleIframeMessage(message) + handleIframeMessage(message.data.messageId, message.data.data, message.data.requestId) } window.addEventListener('message', onIframeMessage) @@ -132,7 +178,6 @@ const useIframeMessageHandler = ( dispatch, enqueueSnackbar, ethBalance, - network, openConfirmationModal, safeAddress, safeName, diff --git a/src/routes/safe/components/Apps/index.tsx b/src/routes/safe/components/Apps/index.tsx index d34d8dd4..64cd9b74 100644 --- a/src/routes/safe/components/Apps/index.tsx +++ b/src/routes/safe/components/Apps/index.tsx @@ -1,5 +1,11 @@ import React, { useCallback, useEffect, useRef, useState, useMemo } from 'react' -import { INTERFACE_MESSAGES, Transaction, RequestId, LowercaseNetworks } from '@gnosis.pm/safe-apps-sdk' +import { + INTERFACE_MESSAGES, + Transaction, + RequestId, + LowercaseNetworks, + SendTransactionParams, +} from '@gnosis.pm/safe-apps-sdk' import { Card, IconText, Loader, Menu, Title } from '@gnosis.pm/safe-react-components' import { useSelector } from 'react-redux' import styled, { css } from 'styled-components' @@ -10,7 +16,6 @@ import { useAppList } from './hooks/useAppList' import { SafeApp } from './types.d' import LCL from 'src/components/ListContentLayout' -import { networkSelector } from 'src/logic/wallets/store/selectors' import { grantedSelector } from 'src/routes/safe/container/selector' import { safeEthBalanceSelector, @@ -21,6 +26,7 @@ import { isSameURL } from 'src/utils/url' import { useIframeMessageHandler } from './hooks/useIframeMessageHandler' import ConfirmTransactionModal from './components/ConfirmTransactionModal' import { useAnalytics, SAFE_NAVIGATION_EVENT } from 'src/utils/googleAnalytics' +import { getNetworkName } from 'src/config' const centerCSS = css` display: flex; @@ -41,21 +47,25 @@ const StyledCard = styled(Card)` const CenteredMT = styled.div` ${centerCSS}; - margin-top: 5px; + margin-top: 16px; ` type ConfirmTransactionModalState = { isOpen: boolean txs: Transaction[] - requestId: RequestId | undefined + requestId?: RequestId + params?: SendTransactionParams } const INITIAL_CONFIRM_TX_MODAL_STATE: ConfirmTransactionModalState = { isOpen: false, txs: [], requestId: undefined, + params: undefined, } +const NETWORK_NAME = getNetworkName() + const Apps = (): React.ReactElement => { const { appList, loadingAppList, onAppToggle, onAppAdded, onAppRemoved } = useAppList() @@ -70,15 +80,15 @@ const Apps = (): React.ReactElement => { const granted = useSelector(grantedSelector) const safeAddress = useSelector(safeParamAddressFromStateSelector) const safeName = useSelector(safeNameSelector) - const network = useSelector(networkSelector) const ethBalance = useSelector(safeEthBalanceSelector) const openConfirmationModal = useCallback( - (txs: Transaction[], requestId: RequestId) => + (txs: Transaction[], params: SendTransactionParams | undefined, requestId: RequestId) => setConfirmTransactionModal({ isOpen: true, txs, requestId, + params, }), [setConfirmTransactionModal], ) @@ -155,11 +165,11 @@ const Apps = (): React.ReactElement => { messageId: INTERFACE_MESSAGES.ON_SAFE_INFO, data: { safeAddress: safeAddress as string, - network: network.toLowerCase() as LowercaseNetworks, + network: NETWORK_NAME.toLowerCase() as LowercaseNetworks, ethBalance: ethBalance as string, }, }) - }, [ethBalance, network, safeAddress, selectedApp, sendMessageToIframe]) + }, [ethBalance, safeAddress, selectedApp, sendMessageToIframe]) if (loadingAppList || !appList.length || !safeAddress) { return ( @@ -185,7 +195,7 @@ const Apps = (): React.ReactElement => { granted={granted} selectedApp={selectedApp} safeAddress={safeAddress} - network={network} + network={NETWORK_NAME} appIsLoading={appIsLoading} onIframeLoad={handleIframeLoad} /> @@ -214,6 +224,7 @@ const Apps = (): React.ReactElement => { txs={confirmTransactionModal.txs} onClose={closeConfirmationModal} onUserConfirm={onUserTxConfirm} + params={confirmTransactionModal.params} onTxReject={onTxReject} /> diff --git a/src/routes/safe/components/Apps/utils.ts b/src/routes/safe/components/Apps/utils.ts index beeba0c0..f26bfff4 100644 --- a/src/routes/safe/components/Apps/utils.ts +++ b/src/routes/safe/components/Apps/utils.ts @@ -3,9 +3,10 @@ import memoize from 'lodash.memoize' import { SafeApp } from './types.d' -import { getGnosisSafeAppsUrl } from 'src/config/index' +import { getGnosisSafeAppsUrl } from 'src/config' import { getContentFromENS } from 'src/logic/wallets/getWeb3' import appsIconSvg from 'src/routes/safe/components/Transactions/TxsTable/TxType/assets/appsIcon.svg' +import { ETHEREUM_NETWORK } from 'src/config/networks/network.d' const removeLastTrailingSlash = (url) => { if (url.substr(-1) === '/') { @@ -15,33 +16,99 @@ const removeLastTrailingSlash = (url) => { } const gnosisAppsUrl = removeLastTrailingSlash(getGnosisSafeAppsUrl()) -export const staticAppsList: Array<{ url: string; disabled: boolean }> = [ +export const staticAppsList: Array<{ url: string; disabled: boolean; networks: number[] }> = [ // 1inch - { url: `${process.env.REACT_APP_IPFS_GATEWAY}/QmUDTSghr154kCCGguyA3cbG5HRVd2tQgNR7yD69bcsjm5`, disabled: false }, + { + url: `${process.env.REACT_APP_IPFS_GATEWAY}/QmUDTSghr154kCCGguyA3cbG5HRVd2tQgNR7yD69bcsjm5`, + disabled: false, + networks: [ETHEREUM_NETWORK.MAINNET], + }, // Aave - { url: `${process.env.REACT_APP_IPFS_GATEWAY}/QmY1MUZo44UkT8EokYHs7xDvWEziYSn7n3c4ojVB6qo3SM`, disabled: false }, + { + url: `${process.env.REACT_APP_IPFS_GATEWAY}/QmY1MUZo44UkT8EokYHs7xDvWEziYSn7n3c4ojVB6qo3SM`, + disabled: false, + networks: [ETHEREUM_NETWORK.MAINNET], + }, //Balancer Exchange - { url: `${process.env.REACT_APP_IPFS_GATEWAY}/QmfPLXne1UrY399RQAcjD1dmBhQrPGZWgp311CDLLW3VTn`, disabled: false }, + { + url: `${process.env.REACT_APP_IPFS_GATEWAY}/QmfPLXne1UrY399RQAcjD1dmBhQrPGZWgp311CDLLW3VTn`, + disabled: false, + networks: [ETHEREUM_NETWORK.MAINNET], + }, //Balancer Pool - { url: `${process.env.REACT_APP_IPFS_GATEWAY}/QmaTucdZYLKTqaewwJduVMM8qfCDhyaEqjd8tBNae26K1J`, disabled: false }, + { + url: `${process.env.REACT_APP_IPFS_GATEWAY}/QmaTucdZYLKTqaewwJduVMM8qfCDhyaEqjd8tBNae26K1J`, + disabled: false, + networks: [ETHEREUM_NETWORK.MAINNET], + }, // Compound - { url: `${gnosisAppsUrl}/compound`, disabled: false }, + { url: `${gnosisAppsUrl}/compound`, disabled: false, networks: [ETHEREUM_NETWORK.MAINNET, ETHEREUM_NETWORK.RINKEBY] }, // Idle - { url: `${process.env.REACT_APP_IPFS_GATEWAY}/QmZ3oug89a3BaVqdJrJEA8CKmLF4M8snuAnphR6z1yq8V8`, disabled: false }, + { + url: `${process.env.REACT_APP_IPFS_GATEWAY}/QmZ3oug89a3BaVqdJrJEA8CKmLF4M8snuAnphR6z1yq8V8`, + disabled: false, + networks: [ETHEREUM_NETWORK.MAINNET, ETHEREUM_NETWORK.RINKEBY], + }, // request - { url: `${process.env.REACT_APP_IPFS_GATEWAY}/QmTBBaiDQyGa17DJ7DdviyHbc51fTVgf6Z5PW5w2YUTkgR`, disabled: false }, + { + url: `${process.env.REACT_APP_IPFS_GATEWAY}/QmTBBaiDQyGa17DJ7DdviyHbc51fTVgf6Z5PW5w2YUTkgR`, + disabled: false, + networks: [ETHEREUM_NETWORK.MAINNET, ETHEREUM_NETWORK.RINKEBY], + }, // Sablier - { url: `${process.env.REACT_APP_IPFS_GATEWAY}/QmeHa5CS6eAMRvQfTBwWfcXKrXZ7itZTpWSM6625ZZ522N`, disabled: false }, + { + url: `${process.env.REACT_APP_IPFS_GATEWAY}/QmboeZ9bae26Skg5xskCsXWjJuLjYk7aHgPh4BAnfRBDgo`, + disabled: false, + networks: [ETHEREUM_NETWORK.MAINNET, ETHEREUM_NETWORK.RINKEBY], + }, // Synthetix - { url: `${process.env.REACT_APP_IPFS_GATEWAY}/QmXLxxczMH4MBEYDeeN9zoiHDzVkeBmB5rBjA3UniPEFcA`, disabled: false }, + { + url: `${process.env.REACT_APP_IPFS_GATEWAY}/QmXLxxczMH4MBEYDeeN9zoiHDzVkeBmB5rBjA3UniPEFcA`, + disabled: false, + networks: [ETHEREUM_NETWORK.MAINNET, ETHEREUM_NETWORK.RINKEBY], + }, // OpenZeppelin - { url: `${process.env.REACT_APP_IPFS_GATEWAY}/QmQovvfYYMUXjZfNbysQDUEXR8nr55iJRwcYgJQGJR7KEA`, disabled: false }, + { + url: `${process.env.REACT_APP_IPFS_GATEWAY}/QmQovvfYYMUXjZfNbysQDUEXR8nr55iJRwcYgJQGJR7KEA`, + disabled: false, + networks: [ + ETHEREUM_NETWORK.MAINNET, + ETHEREUM_NETWORK.RINKEBY, + //ETHEREUM_NETWORK.ENERGY_WEB_CHAIN, + //ETHEREUM_NETWORK.VOLTA, + // ETHEREUM_NETWORK.XDAI, + ], + }, // TX-Builder - { url: `${gnosisAppsUrl}/tx-builder`, disabled: false }, + { + url: `${gnosisAppsUrl}/tx-builder`, + disabled: false, + networks: [ + ETHEREUM_NETWORK.MAINNET, + ETHEREUM_NETWORK.RINKEBY, + ETHEREUM_NETWORK.ENERGY_WEB_CHAIN, + ETHEREUM_NETWORK.VOLTA, + ETHEREUM_NETWORK.XDAI, + ], + }, // Wallet-Connect - { url: `${gnosisAppsUrl}/walletConnect`, disabled: false }, + { + url: `${gnosisAppsUrl}/walletConnect`, + disabled: false, + networks: [ + ETHEREUM_NETWORK.MAINNET, + ETHEREUM_NETWORK.RINKEBY, + ETHEREUM_NETWORK.ENERGY_WEB_CHAIN, + ETHEREUM_NETWORK.VOLTA, + ETHEREUM_NETWORK.XDAI, + ], + }, // Yearn Vaults - { url: `${process.env.REACT_APP_IPFS_GATEWAY}/Qme9HuPPhgCtgfj1CktvaDKhTesMueGCV2Kui1Sqna3Xs9`, disabled: false }, + { + url: `${process.env.REACT_APP_IPFS_GATEWAY}/Qme9HuPPhgCtgfj1CktvaDKhTesMueGCV2Kui1Sqna3Xs9`, + disabled: false, + networks: [ETHEREUM_NETWORK.MAINNET], + }, ] export const getAppInfoFromOrigin = (origin: string): Record | null => { diff --git a/src/routes/safe/components/Balances/Coins/index.tsx b/src/routes/safe/components/Balances/Coins/index.tsx index 82bfc97a..603960af 100644 --- a/src/routes/safe/components/Balances/Coins/index.tsx +++ b/src/routes/safe/components/Balances/Coins/index.tsx @@ -7,7 +7,7 @@ import TableContainer from '@material-ui/core/TableContainer' import TableRow from '@material-ui/core/TableRow' import { Skeleton } from '@material-ui/lab' -import InfoIcon from 'src/assets/icons/info.svg' +import InfoIcon from 'src/assets/icons/info_red.svg' import Img from 'src/components/layout/Img' import Table from 'src/components/Table' diff --git a/src/routes/safe/components/Balances/Collectibles/index.tsx b/src/routes/safe/components/Balances/Collectibles/index.tsx index c06b7227..fa2185da 100644 --- a/src/routes/safe/components/Balances/Collectibles/index.tsx +++ b/src/routes/safe/components/Balances/Collectibles/index.tsx @@ -1,6 +1,6 @@ import React, { useEffect } from 'react' import Card from '@material-ui/core/Card' -import { makeStyles } from '@material-ui/core/styles' +import { createStyles, makeStyles } from '@material-ui/core/styles' import { useSelector } from 'react-redux' import Item from './components/Item' @@ -8,78 +8,79 @@ import Item from './components/Item' import Paragraph from 'src/components/layout/Paragraph' import { activeNftAssetsListSelector, nftTokensSelector } from 'src/logic/collectibles/store/selectors' import SendModal from 'src/routes/safe/components/Balances/SendModal' -import { safeSelector } from 'src/logic/safe/store/selectors' import { fontColor, lg, screenSm, screenXs } from 'src/theme/variables' import { useAnalytics, SAFE_NAVIGATION_EVENT } from 'src/utils/googleAnalytics' +import { NFTToken } from 'src/logic/collectibles/sources/collectibles.d' -const useStyles = makeStyles({ - cardInner: { - boxSizing: 'border-box', - maxWidth: '100%', - padding: '52px 54px', - }, - cardOuter: { - boxShadow: '1px 2px 10px 0 rgba(212, 212, 211, 0.59)', - }, - gridRow: { - boxSizing: 'border-box', - columnGap: '30px', - display: 'grid', - gridTemplateColumns: '1fr', - marginBottom: '45px', - maxWidth: '100%', - rowGap: '45px', - - '&:last-child': { - marginBottom: '0', +const useStyles = makeStyles( + createStyles({ + cardInner: { + boxSizing: 'border-box', + maxWidth: '100%', + padding: '52px 54px', }, - - [`@media (min-width: ${screenXs}px)`]: { - gridTemplateColumns: '1fr 1fr', + cardOuter: { + boxShadow: '1px 2px 10px 0 rgba(212, 212, 211, 0.59)', }, + gridRow: { + boxSizing: 'border-box', + columnGap: '30px', + display: 'grid', + gridTemplateColumns: '1fr', + marginBottom: '45px', + maxWidth: '100%', + rowGap: '45px', - [`@media (min-width: ${screenSm}px)`]: { - gridTemplateColumns: '1fr 1fr 1fr 1fr', + '&:last-child': { + marginBottom: '0', + }, + + [`@media (min-width: ${screenXs}px)`]: { + gridTemplateColumns: '1fr 1fr', + }, + + [`@media (min-width: ${screenSm}px)`]: { + gridTemplateColumns: '1fr 1fr 1fr 1fr', + }, }, - }, - title: { - alignItems: 'center', - display: 'flex', - margin: '0 0 18px', - }, - titleImg: { - backgroundPosition: '50% 50%', - backgroundRepeat: 'no-repeat', - backgroundSize: 'contain', - borderRadius: '50%', - height: '45px', - margin: '0 10px 0 0', - width: '45px', - }, - titleText: { - color: fontColor, - fontSize: '18px', - fontWeight: 'normal', - lineHeight: '1.2', - margin: '0', - }, - titleFiller: { - backgroundColor: '#e8e7e6', - flexGrow: '1', - height: '2px', - marginLeft: '40px', - }, - noData: { - fontSize: lg, - textAlign: 'center', - }, -} as any) + title: { + alignItems: 'center', + display: 'flex', + margin: '0 0 18px', + }, + titleImg: { + backgroundPosition: '50% 50%', + backgroundRepeat: 'no-repeat', + backgroundSize: 'contain', + borderRadius: '50%', + height: '45px', + margin: '0 10px 0 0', + width: '45px', + }, + titleText: { + color: fontColor, + fontSize: '18px', + fontWeight: 'normal', + lineHeight: '1.2', + margin: '0', + }, + titleFiller: { + backgroundColor: '#e8e7e6', + flexGrow: 1, + height: '2px', + marginLeft: '40px', + }, + noData: { + fontSize: lg, + textAlign: 'center', + }, + }), +) const Collectibles = (): React.ReactElement => { const classes = useStyles() - const [selectedToken, setSelectedToken] = React.useState({}) + const [selectedToken, setSelectedToken] = React.useState() const [sendNFTsModalOpen, setSendNFTsModalOpen] = React.useState(false) - const { address, ethBalance, name } = useSelector(safeSelector) || {} const nftTokens = useSelector(nftTokensSelector) const activeAssetsList = useSelector(activeNftAssetsListSelector) const { trackEvent } = useAnalytics() @@ -88,7 +89,7 @@ const Collectibles = (): React.ReactElement => { trackEvent({ category: SAFE_NAVIGATION_EVENT, action: 'Collectibles' }) }, [trackEvent]) - const handleItemSend = (nftToken) => { + const handleItemSend = (nftToken: NFTToken) => { setSelectedToken(nftToken) setSendNFTsModalOpen(true) } @@ -125,11 +126,8 @@ const Collectibles = (): React.ReactElement => {
setSendNFTsModalOpen(false)} - safeAddress={address} - safeName={name} selectedToken={selectedToken} /> diff --git a/src/routes/safe/components/Balances/SendModal/index.tsx b/src/routes/safe/components/Balances/SendModal/index.tsx index 15df1404..ded4b980 100644 --- a/src/routes/safe/components/Balances/SendModal/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/index.tsx @@ -4,6 +4,14 @@ import cn from 'classnames' import React, { Suspense, useEffect, useState } from 'react' import Modal from 'src/components/Modal' +import { CollectibleTx } from './screens/ReviewCollectible' +import { CustomTx } from './screens/ContractInteraction/ReviewCustomTx' +import { SendFundsTx } from './screens/SendFunds' +import { ContractInteractionTx } from './screens/ContractInteraction' +import { CustomTxProps } from './screens/ContractInteraction/SendCustomTx' +import { ReviewTxProp } from './screens/ReviewTx' +import { NFTToken } from 'src/logic/collectibles/sources/collectibles' +import { SendCollectibleTxInfo } from './screens/SendCollectible' const ChooseTxType = React.lazy(() => import('./screens/ChooseTxType')) @@ -39,10 +47,24 @@ const useStyles = makeStyles({ }, }) -const SendModal = ({ activeScreenType, isOpen, onClose, recipientAddress, selectedToken }: any) => { +type Props = { + activeScreenType: string + isOpen: boolean + onClose: () => void + recipientAddress?: string + selectedToken?: string | NFTToken +} + +const SendModal = ({ + activeScreenType, + isOpen, + onClose, + recipientAddress, + selectedToken, +}: Props): React.ReactElement => { const classes = useStyles() const [activeScreen, setActiveScreen] = useState(activeScreenType || 'chooseTxType') - const [tx, setTx] = useState({}) + const [tx, setTx] = useState({}) const [isABI, setIsABI] = useState(true) useEffect(() => { @@ -53,7 +75,7 @@ const SendModal = ({ activeScreenType, isOpen, onClose, recipientAddress, select const scalableModalSize = activeScreen === 'chooseTxType' - const handleTxCreation = (txInfo) => { + const handleTxCreation = (txInfo: SendCollectibleTxInfo) => { setActiveScreen('reviewTx') setTx(txInfo) } @@ -97,22 +119,22 @@ const SendModal = ({ activeScreenType, isOpen, onClose, recipientAddress, select )} {activeScreen === 'sendFunds' && ( )} {activeScreen === 'reviewTx' && ( - setActiveScreen('sendFunds')} tx={tx} /> + setActiveScreen('sendFunds')} tx={tx as ReviewTxProp} /> )} {activeScreen === 'contractInteraction' && isABI && ( @@ -122,7 +144,7 @@ const SendModal = ({ activeScreenType, isOpen, onClose, recipientAddress, select )} {activeScreen === 'contractInteraction' && !isABI && ( )} {activeScreen === 'reviewCustomTx' && ( - setActiveScreen('contractInteraction')} tx={tx} /> + setActiveScreen('contractInteraction')} tx={tx as CustomTx} /> )} {activeScreen === 'sendCollectible' && ( )} {activeScreen === 'reviewCollectible' && ( - setActiveScreen('sendCollectible')} tx={tx} /> + setActiveScreen('sendCollectible')} + tx={tx as CollectibleTx} + /> )} diff --git a/src/routes/safe/components/Balances/SendModal/screens/ChooseTxType/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/ChooseTxType/index.tsx index 371dfb7a..6bf71077 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ChooseTxType/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ChooseTxType/index.tsx @@ -17,19 +17,21 @@ import ContractInteractionIcon from 'src/routes/safe/components/Transactions/Txs import Collectible from '../assets/collectibles.svg' import Token from '../assets/token.svg' +import { FEATURES } from 'src/config/networks/network.d' type ActiveScreen = 'sendFunds' | 'sendCollectible' | 'contractInteraction' interface ChooseTxTypeProps { onClose: () => void - recipientAddress: string + recipientAddress?: string setActiveScreen: React.Dispatch> } const ChooseTxType = ({ onClose, recipientAddress, setActiveScreen }: ChooseTxTypeProps): React.ReactElement => { const classes = useStyles() const featuresEnabled = useSelector(safeFeaturesEnabledSelector) - const erc721Enabled = featuresEnabled?.includes('ERC721') + const erc721Enabled = featuresEnabled?.includes(FEATURES.ERC721) + const contractInteractionEnabled = featuresEnabled?.includes(FEATURES.CONTRACT_INTERACTION) const [disableContractInteraction, setDisableContractInteraction] = React.useState(!!recipientAddress) React.useEffect(() => { @@ -99,22 +101,24 @@ const ChooseTxType = ({ onClose, recipientAddress, setActiveScreen }: ChooseTxTy Send collectible )} - + {contractInteractionEnabled && ( + + )} diff --git a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/ContractABI/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/ContractABI/index.tsx index fe47ee3f..0df470c8 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/ContractABI/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/ContractABI/index.tsx @@ -1,13 +1,16 @@ import React from 'react' +import { useField, useForm } from 'react-final-form' import TextareaField from 'src/components/forms/TextareaField' +import { mustBeEthereumAddress, mustBeEthereumContractAddress } from 'src/components/forms/validator' import Col from 'src/components/layout/Col' import Row from 'src/components/layout/Row' +import { getContractABI } from 'src/config' import { extractUsefulMethods } from 'src/logic/contractInteraction/sources/ABIService' export const NO_DATA = 'no data' -const mustBeValidABI = (abi: string): undefined | string => { +const hasUsefulMethods = (abi: string): undefined | string => { try { const parsedABI = extractUsefulMethods(JSON.parse(abi)) @@ -19,12 +22,42 @@ const mustBeValidABI = (abi: string): undefined | string => { } } -const ContractABI = () => ( - - - - - -) +const ContractABI = (): React.ReactElement => { + const { + input: { value: contractAddress }, + } = useField('contractAddress', { subscription: { value: true } }) + const { mutators } = useForm() + const setAbiValue = React.useRef(mutators.setAbiValue) + + React.useEffect(() => { + const validateAndSetAbi = async () => { + const isEthereumAddress = mustBeEthereumAddress(contractAddress) === undefined + const isEthereumContractAddress = (await mustBeEthereumContractAddress(contractAddress)) === undefined + + if (isEthereumAddress && isEthereumContractAddress) { + const abi = await getContractABI(contractAddress) + const isValidABI = hasUsefulMethods(abi) === undefined + + // this check may help in scenarios where the user first pastes the ABI, + // and then sets a Proxy contract that has no useful methods + if (isValidABI) { + setAbiValue.current(abi) + } + } + } + + if (contractAddress) { + validateAndSetAbi() + } + }, [contractAddress]) + + return ( + + + + + + ) +} export default ContractABI diff --git a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/EthValue/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/NativeCoinValue/index.tsx similarity index 85% rename from src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/EthValue/index.tsx rename to src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/NativeCoinValue/index.tsx index afda6213..e75258a6 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/EthValue/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/NativeCoinValue/index.tsx @@ -14,15 +14,20 @@ import Row from 'src/components/layout/Row' import { isPayable } from 'src/logic/contractInteraction/sources/ABIService' import { styles } from 'src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/style' import { safeSelector } from 'src/logic/safe/store/selectors' +import { getNetworkInfo } from 'src/config' const useStyles = makeStyles(styles) -interface EthValueProps { - onSetMax: (ethBalance: string) => void +interface NativeCoinValueProps { + onSetMax: (nativeCoinBalance: string) => void } -const EthValue = ({ onSetMax }: EthValueProps): React.ReactElement | null => { + +const { nativeCoin } = getNetworkInfo() + +export const NativeCoinValue = ({ onSetMax }: NativeCoinValueProps): React.ReactElement | null => { const classes = useStyles() const { ethBalance } = useSelector(safeSelector) || {} + const { input: { value: method }, } = useField('selectedMethod', { subscription: { value: true } }) @@ -52,7 +57,7 @@ const EthValue = ({ onSetMax }: EthValueProps): React.ReactElement | null => { component={TextField} disabled={disabled} inputAdornment={{ - endAdornment: ETH, + endAdornment: {nativeCoin.name}, disabled, }} name="value" @@ -66,5 +71,3 @@ const EthValue = ({ onSetMax }: EthValueProps): React.ReactElement | null => { ) } - -export default EthValue diff --git a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/Review/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/Review/index.tsx index 5d2d1c10..e67d8ae0 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/Review/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/Review/index.tsx @@ -1,8 +1,9 @@ -import { makeStyles } from '@material-ui/core/styles' -import { useSnackbar } from 'notistack' import React, { useEffect, useState } from 'react' +import { makeStyles } from '@material-ui/core/styles' import { useDispatch, useSelector } from 'react-redux' +import { getNetworkInfo } from 'src/config' +import { fromTokenUnit, toTokenUnit } from 'src/logic/tokens/utils/humanReadableValue' import AddressInfo from 'src/components/AddressInfo' import Block from 'src/components/layout/Block' import Button from 'src/components/layout/Button' @@ -13,10 +14,9 @@ import Paragraph from 'src/components/layout/Paragraph' import Row from 'src/components/layout/Row' import { AbiItemExtended } from 'src/logic/contractInteraction/sources/ABIService' import { TX_NOTIFICATION_TYPES } from 'src/logic/safe/transactions' -import { estimateTxGasCosts } from 'src/logic/safe/transactions/gasNew' +import { estimateTxGasCosts } from 'src/logic/safe/transactions/gas' import { formatAmount } from 'src/logic/tokens/utils/formatAmount' import { getEthAsToken } from 'src/logic/tokens/utils/tokenHelpers' -import { getWeb3 } from 'src/logic/wallets/getWeb3' import { styles } from 'src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/style' import Header from 'src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/Header' import { setImageToPlaceholder } from 'src/routes/safe/components/Balances/utils' @@ -40,23 +40,22 @@ type Props = { tx: TransactionReviewType } +const { nativeCoin } = getNetworkInfo() + const ContractInteractionReview = ({ onClose, onPrev, tx }: Props): React.ReactElement => { - const { enqueueSnackbar, closeSnackbar } = useSnackbar() const classes = useStyles() const dispatch = useDispatch() const { address: safeAddress } = useSelector(safeSelector) || {} const [gasCosts, setGasCosts] = useState('< 0.001') - useEffect(() => { let isCurrent = true const estimateGas = async (): Promise => { - const { fromWei, toBN } = getWeb3().utils const txData = tx.data ? tx.data.trim() : '' const estimatedGasCosts = await estimateTxGasCosts(safeAddress as string, tx.contractAddress as string, txData) - const gasCostsAsEth = fromWei(toBN(estimatedGasCosts), 'ether') - const formattedGasCosts = formatAmount(gasCostsAsEth) + const gasCosts = fromTokenUnit(estimatedGasCosts, nativeCoin.decimals) + const formattedGasCosts = formatAmount(gasCosts) if (isCurrent) { setGasCosts(formattedGasCosts) @@ -71,23 +70,22 @@ const ContractInteractionReview = ({ onClose, onPrev, tx }: Props): React.ReactE }, [safeAddress, tx.contractAddress, tx.data]) const submitTx = async () => { - const web3 = getWeb3() const txRecipient = tx.contractAddress const txData = tx.data ? tx.data.trim() : '' - const txValue = tx.value ? web3.utils.toWei(tx.value, 'ether') : '0' - - dispatch( - createTransaction({ - safeAddress, - to: txRecipient, - valueInWei: txValue, - txData, - notifiedTransaction: TX_NOTIFICATION_TYPES.STANDARD_TX, - enqueueSnackbar, - closeSnackbar, - } as any), - ) - + const txValue = tx.value ? toTokenUnit(tx.value, nativeCoin.decimals) : '0' + if (safeAddress) { + dispatch( + createTransaction({ + safeAddress, + to: txRecipient as string, + valueInWei: txValue, + txData, + notifiedTransaction: TX_NOTIFICATION_TYPES.STANDARD_TX, + }), + ) + } else { + console.error('There was an error trying to submit the transaction, the safeAddress was not found') + } onClose() } @@ -117,7 +115,7 @@ const ContractInteractionReview = ({ onClose, onPrev, tx }: Props): React.ReactE {tx.value || 0} - {' ETH'} + {' ' + nativeCoin.name} @@ -165,7 +163,7 @@ const ContractInteractionReview = ({ onClose, onPrev, tx }: Props): React.ReactE - {`You're about to create a transaction and will have to confirm it with your currently connected wallet. Make sure you have ${gasCosts} (fee price) ETH in this wallet to fund this confirmation.`} + {`You're about to create a transaction and will have to confirm it with your currently connected wallet. Make sure you have ${gasCosts} (fee price) ${nativeCoin.name} in this wallet to fund this confirmation.`} diff --git a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/ReviewCustomTx/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/ReviewCustomTx/index.tsx index b47b8f2f..bbe1d84c 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/ReviewCustomTx/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/ReviewCustomTx/index.tsx @@ -1,13 +1,11 @@ +import React, { useEffect, useState } from 'react' +import { useDispatch, useSelector } from 'react-redux' import IconButton from '@material-ui/core/IconButton' import { makeStyles } from '@material-ui/core/styles' import Close from '@material-ui/icons/Close' -import React, { useEffect, useState } from 'react' -import { useDispatch, useSelector } from 'react-redux' - -import ArrowDown from '../../assets/arrow-down.svg' - -import { styles } from './style' +import { getNetworkInfo } from 'src/config' +import { fromTokenUnit, toTokenUnit } from 'src/logic/tokens/utils/humanReadableValue' import CopyBtn from 'src/components/CopyBtn' import EtherscanBtn from 'src/components/EtherscanBtn' import Identicon from 'src/components/Identicon' @@ -18,41 +16,50 @@ import Hairline from 'src/components/layout/Hairline' import Img from 'src/components/layout/Img' import Paragraph from 'src/components/layout/Paragraph' import Row from 'src/components/layout/Row' -import { TX_NOTIFICATION_TYPES } from 'src/logic/safe/transactions' -import { estimateTxGasCosts } from 'src/logic/safe/transactions/gasNew' -import { formatAmount } from 'src/logic/tokens/utils/formatAmount' -import { getEthAsToken } from 'src/logic/tokens/utils/tokenHelpers' -import { getWeb3 } from 'src/logic/wallets/getWeb3' -import SafeInfo from 'src/routes/safe/components/Balances/SendModal/SafeInfo' -import { setImageToPlaceholder } from 'src/routes/safe/components/Balances/utils' import createTransaction from 'src/logic/safe/store/actions/createTransaction' import { safeSelector } from 'src/logic/safe/store/selectors' +import { TX_NOTIFICATION_TYPES } from 'src/logic/safe/transactions' +import { estimateTxGasCosts } from 'src/logic/safe/transactions/gas' +import { formatAmount } from 'src/logic/tokens/utils/formatAmount' +import { getEthAsToken } from 'src/logic/tokens/utils/tokenHelpers' +import SafeInfo from 'src/routes/safe/components/Balances/SendModal/SafeInfo' +import { setImageToPlaceholder } from 'src/routes/safe/components/Balances/utils' import { sm } from 'src/theme/variables' +import ArrowDown from '../../assets/arrow-down.svg' + +import { styles } from './style' + +export type CustomTx = { + contractAddress?: string + data?: string + value?: string +} + type Props = { onClose: () => void onPrev: () => void - tx: { contractAddress?: string; data?: string; value?: string } + tx: CustomTx } const useStyles = makeStyles(styles) +const { nativeCoin } = getNetworkInfo() + const ReviewCustomTx = ({ onClose, onPrev, tx }: Props): React.ReactElement => { const classes = useStyles() const dispatch = useDispatch() const { address: safeAddress } = useSelector(safeSelector) || {} const [gasCosts, setGasCosts] = useState('< 0.001') - useEffect(() => { let isCurrent = true const estimateGas = async () => { - const { fromWei, toBN } = getWeb3().utils const txData = tx.data ? tx.data.trim() : '' const estimatedGasCosts = await estimateTxGasCosts(safeAddress as string, tx.contractAddress as string, txData) - const gasCostsAsEth = fromWei(toBN(estimatedGasCosts), 'ether') - const formattedGasCosts = formatAmount(gasCostsAsEth) + const gasCosts = fromTokenUnit(estimatedGasCosts, nativeCoin.decimals) + const formattedGasCosts = formatAmount(gasCosts) if (isCurrent) { setGasCosts(formattedGasCosts) @@ -67,20 +74,23 @@ const ReviewCustomTx = ({ onClose, onPrev, tx }: Props): React.ReactElement => { }, [safeAddress, tx.data, tx.contractAddress]) const submitTx = async (): Promise => { - const web3 = getWeb3() const txRecipient = tx.contractAddress const txData = tx.data ? tx.data.trim() : '' - const txValue = tx.value ? web3.utils.toWei(tx.value, 'ether') : '0' + const txValue = tx.value ? toTokenUnit(tx.value, nativeCoin.decimals) : '0' - dispatch( - createTransaction({ - safeAddress: safeAddress as string, - to: txRecipient as string, - valueInWei: txValue, - txData, - notifiedTransaction: TX_NOTIFICATION_TYPES.STANDARD_TX, - }), - ) + if (safeAddress) { + dispatch( + createTransaction({ + safeAddress: safeAddress, + to: txRecipient as string, + valueInWei: txValue, + txData, + notifiedTransaction: TX_NOTIFICATION_TYPES.STANDARD_TX, + }), + ) + } else { + console.error('There was an error trying to submit the transaction, the safeAddress was not found') + } onClose() } @@ -122,7 +132,7 @@ const ReviewCustomTx = ({ onClose, onPrev, tx }: Props): React.ReactElement => { {tx.contractAddress} - + @@ -135,7 +145,7 @@ const ReviewCustomTx = ({ onClose, onPrev, tx }: Props): React.ReactElement => { Ether {tx.value || 0} - {' ETH'} + {' ' + nativeCoin.name} @@ -152,7 +162,7 @@ const ReviewCustomTx = ({ onClose, onPrev, tx }: Props): React.ReactElement => { - {`You're about to create a transaction and will have to confirm it with your currently connected wallet. Make sure you have ${gasCosts} (fee price) ETH in this wallet to fund this confirmation.`} + {`You're about to create a transaction and will have to confirm it with your currently connected wallet. Make sure you have ${gasCosts} (fee price) ${nativeCoin.name} in this wallet to fund this confirmation.`} diff --git a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/SendCustomTx/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/SendCustomTx/index.tsx index 99bbd100..9b96d130 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/SendCustomTx/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/SendCustomTx/index.tsx @@ -1,25 +1,20 @@ -import IconButton from '@material-ui/core/IconButton' -import InputAdornment from '@material-ui/core/InputAdornment' -import Switch from '@material-ui/core/Switch' -import { makeStyles } from '@material-ui/core/styles' -import Close from '@material-ui/icons/Close' import React, { useState } from 'react' import { useSelector } from 'react-redux' - -import ArrowDown from '../../assets/arrow-down.svg' - -import { styles } from './style' +import IconButton from '@material-ui/core/IconButton' +import InputAdornment from '@material-ui/core/InputAdornment' +import { makeStyles } from '@material-ui/core/styles' +import Switch from '@material-ui/core/Switch' +import Close from '@material-ui/icons/Close' import QRIcon from 'src/assets/icons/qrcode.svg' import CopyBtn from 'src/components/CopyBtn' import EtherscanBtn from 'src/components/EtherscanBtn' -import Identicon from 'src/components/Identicon' -import ScanQRModal from 'src/components/ScanQRModal' import Field from 'src/components/forms/Field' import GnoForm from 'src/components/forms/GnoForm' -import TextField from 'src/components/forms/TextField' import TextareaField from 'src/components/forms/TextareaField' -import { composeValidators, maxValue, mustBeFloat, minValue } from 'src/components/forms/validator' +import TextField from 'src/components/forms/TextField' +import { composeValidators, maxValue, minValue, mustBeFloat } from 'src/components/forms/validator' +import Identicon from 'src/components/Identicon' import Block from 'src/components/layout/Block' import Button from 'src/components/layout/Button' import ButtonLink from 'src/components/layout/ButtonLink' @@ -28,28 +23,40 @@ import Hairline from 'src/components/layout/Hairline' import Img from 'src/components/layout/Img' import Paragraph from 'src/components/layout/Paragraph' import Row from 'src/components/layout/Row' +import ScanQRModal from 'src/components/ScanQRModal' +import { safeSelector } from 'src/logic/safe/store/selectors' import SafeInfo from 'src/routes/safe/components/Balances/SendModal/SafeInfo' import AddressBookInput from 'src/routes/safe/components/Balances/SendModal/screens/AddressBookInput' -import { safeSelector } from 'src/logic/safe/store/selectors' import { sm } from 'src/theme/variables' +import ArrowDown from '../../assets/arrow-down.svg' + +import { styles } from './style' +import { getNetworkInfo } from 'src/config' + export interface CreatedTx { contractAddress: string data: string value: string | number } +export type CustomTxProps = { + contractAddress?: string +} + type Props = { - initialValues: { contractAddress?: string } + initialValues: CustomTxProps onClose: () => void onNext: (tx: CreatedTx, submit: boolean) => void isABI: boolean switchMethod: () => void - contractAddress: string + contractAddress?: string } const useStyles = makeStyles(styles) +const { nativeCoin } = getNetworkInfo() + const SendCustomTx: React.FC = ({ initialValues, onClose, onNext, contractAddress, switchMethod, isABI }) => { const classes = useStyles() const { ethBalance } = useSelector(safeSelector) || {} @@ -177,7 +184,7 @@ const SendCustomTx: React.FC = ({ initialValues, onClose, onNext, contrac - + @@ -224,7 +231,7 @@ const SendCustomTx: React.FC = ({ initialValues, onClose, onNext, contrac ETH, + endAdornment: {nativeCoin.name}, }} name="value" placeholder="Value*" diff --git a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/index.tsx index 31d28b3f..bf44d55c 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/index.tsx @@ -12,15 +12,15 @@ import Paragraph from 'src/components/layout/Paragraph' import Buttons from './Buttons' import ContractABI from './ContractABI' import EthAddressInput from './EthAddressInput' -import EthValue from './EthValue' import FormDivisor from './FormDivisor' import FormErrorMessage from './FormErrorMessage' import Header from './Header' import MethodsDropdown from './MethodsDropdown' import RenderInputParams from './RenderInputParams' import RenderOutputParams from './RenderOutputParams' -import { abiExtractor, createTxObject, formMutators, handleSubmitError, isReadMethod, ensResolver } from './utils' +import { createTxObject, formMutators, handleSubmitError, isReadMethod, ensResolver } from './utils' import { TransactionReviewType } from './Review' +import { NativeCoinValue } from './NativeCoinValue' const useStyles = makeStyles(styles) @@ -31,9 +31,13 @@ export interface CreatedTx { value: string | number } +export type ContractInteractionTx = { + contractAddress?: string +} + export interface ContractInteractionProps { - contractAddress: string - initialValues: { contractAddress?: string } + contractAddress?: string + initialValues: ContractInteractionTx isABI: boolean onClose: () => void switchMethod: () => void @@ -92,7 +96,7 @@ const ContractInteraction: React.FC = ({
= ({ /> - + diff --git a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/utils/index.ts b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/utils/index.ts index 52922fd0..c30e1eaa 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/utils/index.ts +++ b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/utils/index.ts @@ -2,9 +2,6 @@ import { FORM_ERROR, Mutator, SubmissionErrors } from 'final-form' import createDecorator from 'final-form-calculate' import { ContractSendMethod } from 'web3-eth-contract' -import { mustBeEthereumAddress, mustBeEthereumContractAddress } from 'src/components/forms/validator' -import { getNetwork } from 'src/config' -import { getConfiguredSource } from 'src/logic/contractInteraction/sources' import { AbiItemExtended } from 'src/logic/contractInteraction/sources/ABIService' import { getAddressFromENS, getWeb3 } from 'src/logic/wallets/getWeb3' import { TransactionReviewType } from 'src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/Review' @@ -12,24 +9,6 @@ import { isValidEnsName } from 'src/logic/wallets/ethAddresses' export const NO_CONTRACT = 'no contract' -export const abiExtractor = createDecorator({ - field: 'contractAddress', - updates: { - abi: async (contractAddress) => { - if ( - !contractAddress || - mustBeEthereumAddress(contractAddress) || - (await mustBeEthereumContractAddress(contractAddress)) - ) { - return - } - const network = getNetwork() - const source = getConfiguredSource() - return source.getContractABI(contractAddress, network) - }, - }, -}) - export const ensResolver = createDecorator({ field: 'contractAddress', updates: { @@ -40,12 +19,12 @@ export const ensResolver = createDecorator({ if (resolvedAddress) { return resolvedAddress } + + return contractAddress } catch (e) { console.error(e.message) return contractAddress } - - return contractAddress }, }, }) @@ -71,6 +50,9 @@ export const formMutators: Record { utils.changeValue(state, 'callResults', () => args[0]) }, + setAbiValue: (args, state, utils) => { + utils.changeValue(state, 'abi', () => args[0]) + }, } export const isAddress = (type: string): boolean => type.indexOf('address') === 0 diff --git a/src/routes/safe/components/Balances/SendModal/screens/ReviewCollectible/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/ReviewCollectible/index.tsx index 1b7cb68d..d073fd57 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ReviewCollectible/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ReviewCollectible/index.tsx @@ -1,14 +1,11 @@ +import React, { useEffect, useState } from 'react' +import { useDispatch, useSelector } from 'react-redux' import IconButton from '@material-ui/core/IconButton' import { makeStyles } from '@material-ui/core/styles' import Close from '@material-ui/icons/Close' -import { withSnackbar } from 'notistack' -import React, { useEffect, useState } from 'react' -import { useDispatch, useSelector } from 'react-redux' - -import ArrowDown from '../assets/arrow-down.svg' - -import { styles } from './style' +import { fromTokenUnit } from 'src/logic/tokens/utils/humanReadableValue' +import { getNetworkInfo } from 'src/config' import CopyBtn from 'src/components/CopyBtn' import EtherscanBtn from 'src/components/EtherscanBtn' import Identicon from 'src/components/Identicon' @@ -20,26 +17,40 @@ import Img from 'src/components/layout/Img' import Paragraph from 'src/components/layout/Paragraph' import Row from 'src/components/layout/Row' import { nftTokensSelector } from 'src/logic/collectibles/store/selectors' -import { TX_NOTIFICATION_TYPES } from 'src/logic/safe/transactions' -import { estimateTxGasCosts } from 'src/logic/safe/transactions/gasNew' -import { - containsMethodByHash, - getERC721TokenContract, - getHumanFriendlyToken, -} from 'src/logic/tokens/store/actions/fetchTokens' -import { formatAmount } from 'src/logic/tokens/utils/formatAmount' -import { SAFE_TRANSFER_FROM_WITHOUT_DATA_HASH } from 'src/logic/tokens/utils/tokenHelpers' -import { getWeb3 } from 'src/logic/wallets/getWeb3' -import SafeInfo from 'src/routes/safe/components/Balances/SendModal/SafeInfo' -import { setImageToPlaceholder } from 'src/routes/safe/components/Balances/utils' import createTransaction from 'src/logic/safe/store/actions/createTransaction' import { safeSelector } from 'src/logic/safe/store/selectors' +import { TX_NOTIFICATION_TYPES } from 'src/logic/safe/transactions' +import { estimateTxGasCosts } from 'src/logic/safe/transactions/gas' +import { getERC721TokenContract } from 'src/logic/tokens/store/actions/fetchTokens' +import { formatAmount } from 'src/logic/tokens/utils/formatAmount' +import { SAFE_TRANSFER_FROM_WITHOUT_DATA_HASH } from 'src/logic/tokens/utils/tokenHelpers' +import SafeInfo from 'src/routes/safe/components/Balances/SendModal/SafeInfo' +import { setImageToPlaceholder } from 'src/routes/safe/components/Balances/utils' import { sm } from 'src/theme/variables' import { textShortener } from 'src/utils/strings' -const useStyles = makeStyles(styles as any) +import ArrowDown from '../assets/arrow-down.svg' -const ReviewCollectible = ({ closeSnackbar, enqueueSnackbar, onClose, onPrev, tx }) => { +import { styles } from './style' + +const { nativeCoin } = getNetworkInfo() + +const useStyles = makeStyles(styles) + +export type CollectibleTx = { + recipientAddress: string + assetAddress: string + assetName: string + nftTokenId: string +} + +type Props = { + onClose: () => void + onPrev: () => void + tx: CollectibleTx +} + +const ReviewCollectible = ({ onClose, onPrev, tx }: Props): React.ReactElement => { const classes = useStyles() const shortener = textShortener() const dispatch = useDispatch() @@ -55,24 +66,24 @@ const ReviewCollectible = ({ closeSnackbar, enqueueSnackbar, onClose, onPrev, tx let isCurrent = true const estimateGas = async () => { - const { fromWei, toBN } = getWeb3().utils + try { + const methodToCall = `0x${SAFE_TRANSFER_FROM_WITHOUT_DATA_HASH}` + const transferParams = [tx.recipientAddress, tx.nftTokenId] + const params = [safeAddress, ...transferParams] + const ERC721Token = await getERC721TokenContract() + const tokenInstance = await ERC721Token.at(tx.assetAddress) + const txData = tokenInstance.contract.methods[methodToCall](...params).encodeABI() - const supportsSafeTransfer = await containsMethodByHash(tx.assetAddress, SAFE_TRANSFER_FROM_WITHOUT_DATA_HASH) - const methodToCall = supportsSafeTransfer ? `0x${SAFE_TRANSFER_FROM_WITHOUT_DATA_HASH}` : 'transfer' - const transferParams = [tx.recipientAddress, tx.nftTokenId] - const params = methodToCall === 'transfer' ? transferParams : [safeAddress, ...transferParams] + const estimatedGasCosts = await estimateTxGasCosts(safeAddress as string, tx.recipientAddress, txData) + const gasCosts = fromTokenUnit(estimatedGasCosts, nativeCoin.decimals) + const formattedGasCosts = formatAmount(gasCosts) - const ERC721Token = methodToCall === 'transfer' ? await getHumanFriendlyToken() : await getERC721TokenContract() - const tokenInstance = await ERC721Token.at(tx.assetAddress) - const txData = tokenInstance.contract.methods[methodToCall](...params).encodeABI() - - const estimatedGasCosts = await estimateTxGasCosts(safeAddress as string, tx.recipientAddress, txData) - const gasCostsAsEth = fromWei(toBN(estimatedGasCosts), 'ether') - const formattedGasCosts = formatAmount(gasCostsAsEth) - - if (isCurrent) { - setGasCosts(formattedGasCosts) - setData(txData) + if (isCurrent) { + setGasCosts(formattedGasCosts) + setData(txData) + } + } catch (error) { + console.error('Error while calculating estimated gas:', error) } } @@ -84,18 +95,25 @@ const ReviewCollectible = ({ closeSnackbar, enqueueSnackbar, onClose, onPrev, tx }, [safeAddress, tx.assetAddress, tx.nftTokenId, tx.recipientAddress]) const submitTx = async () => { - dispatch( - createTransaction({ - safeAddress, - to: tx.assetAddress, - valueInWei: '0', - txData: data, - notifiedTransaction: TX_NOTIFICATION_TYPES.STANDARD_TX, - enqueueSnackbar, - closeSnackbar, - } as any), - ) - onClose() + try { + if (safeAddress) { + dispatch( + createTransaction({ + safeAddress, + to: tx.assetAddress, + valueInWei: '0', + txData: data, + notifiedTransaction: TX_NOTIFICATION_TYPES.STANDARD_TX, + }), + ) + } else { + console.error('There was an error trying to submit the transaction, the safeAddress was not found') + } + } catch (error) { + console.error('Error creating sendCollectible Tx:', error) + } finally { + onClose() + } } return ( @@ -135,7 +153,7 @@ const ReviewCollectible = ({ closeSnackbar, enqueueSnackbar, onClose, onPrev, tx {tx.recipientAddress} - + @@ -154,7 +172,7 @@ const ReviewCollectible = ({ closeSnackbar, enqueueSnackbar, onClose, onPrev, tx )} - {`You're about to create a transaction and will have to confirm it with your currently connected wallet. Make sure you have ${gasCosts} (fee price) ETH in this wallet to fund this confirmation.`} + {`You're about to create a transaction and will have to confirm it with your currently connected wallet. Make sure you have ${gasCosts} (fee price) ${nativeCoin.name} in this wallet to fund this confirmation.`} @@ -180,4 +198,4 @@ const ReviewCollectible = ({ closeSnackbar, enqueueSnackbar, onClose, onPrev, tx ) } -export default withSnackbar(ReviewCollectible) +export default ReviewCollectible diff --git a/src/routes/safe/components/Balances/SendModal/screens/ReviewCollectible/style.ts b/src/routes/safe/components/Balances/SendModal/screens/ReviewCollectible/style.ts index 52f70b5a..e6e4fbcf 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ReviewCollectible/style.ts +++ b/src/routes/safe/components/Balances/SendModal/screens/ReviewCollectible/style.ts @@ -1,6 +1,7 @@ import { lg, md, secondaryText, sm } from 'src/theme/variables' +import { createStyles } from '@material-ui/core' -export const styles = () => ({ +export const styles = createStyles({ heading: { padding: `${md} ${lg}`, justifyContent: 'flex-start', diff --git a/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.tsx index 0ee764bb..81a48eb7 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.tsx @@ -2,13 +2,10 @@ import IconButton from '@material-ui/core/IconButton' import { makeStyles } from '@material-ui/core/styles' import Close from '@material-ui/icons/Close' import { BigNumber } from 'bignumber.js' -import { withSnackbar } from 'notistack' -import React, { useEffect, useState, useMemo } from 'react' +import React, { useEffect, useMemo, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' - -import ArrowDown from '../assets/arrow-down.svg' - -import { styles } from './style' +import { toTokenUnit, fromTokenUnit } from 'src/logic/tokens/utils/humanReadableValue' +import { getNetworkInfo } from 'src/config' import CopyBtn from 'src/components/CopyBtn' import EtherscanBtn from 'src/components/EtherscanBtn' @@ -20,23 +17,40 @@ import Hairline from 'src/components/layout/Hairline' import Img from 'src/components/layout/Img' import Paragraph from 'src/components/layout/Paragraph' import Row from 'src/components/layout/Row' +import createTransaction from 'src/logic/safe/store/actions/createTransaction' +import { safeSelector } from 'src/logic/safe/store/selectors' import { TX_NOTIFICATION_TYPES } from 'src/logic/safe/transactions' -import { estimateTxGasCosts } from 'src/logic/safe/transactions/gasNew' +import { estimateTxGasCosts } from 'src/logic/safe/transactions/gas' import { getHumanFriendlyToken } from 'src/logic/tokens/store/actions/fetchTokens' import { formatAmount } from 'src/logic/tokens/utils/formatAmount' -import { ETH_ADDRESS } from 'src/logic/tokens/utils/tokenHelpers' import { EMPTY_DATA } from 'src/logic/wallets/ethTransactions' -import { getWeb3 } from 'src/logic/wallets/getWeb3' import SafeInfo from 'src/routes/safe/components/Balances/SendModal/SafeInfo' import { setImageToPlaceholder } from 'src/routes/safe/components/Balances/utils' import { extendedSafeTokensSelector } from 'src/routes/safe/container/selector' -import createTransaction from 'src/logic/safe/store/actions/createTransaction' -import { safeSelector } from 'src/logic/safe/store/selectors' import { sm } from 'src/theme/variables' -const useStyles = makeStyles(styles as any) +import ArrowDown from '../assets/arrow-down.svg' -const ReviewTx = ({ closeSnackbar, enqueueSnackbar, onClose, onPrev, tx }) => { +import { styles } from './style' + +const useStyles = makeStyles(styles) + +const { nativeCoin } = getNetworkInfo() + +export type ReviewTxProp = { + recipientAddress: string + amount: string + txRecipient: string + token: string +} + +type ReviewTxProps = { + onClose: () => void + onPrev: () => void + tx: ReviewTxProp +} + +const ReviewTx = ({ onClose, onPrev, tx }: ReviewTxProps): React.ReactElement => { const classes = useStyles() const dispatch = useDispatch() const { address: safeAddress } = useSelector(safeSelector) || {} @@ -45,15 +59,13 @@ const ReviewTx = ({ closeSnackbar, enqueueSnackbar, onClose, onPrev, tx }) => { const [data, setData] = useState('') const txToken = useMemo(() => tokens.find((token) => token.address === tx.token), [tokens, tx.token]) - const isSendingETH = txToken?.address === ETH_ADDRESS + const isSendingETH = txToken?.address === nativeCoin.address const txRecipient = isSendingETH ? tx.recipientAddress : txToken?.address useEffect(() => { let isCurrent = true const estimateGas = async () => { - const { fromWei, toBN } = getWeb3().utils - if (!txToken) { return } @@ -69,9 +81,9 @@ const ReviewTx = ({ closeSnackbar, enqueueSnackbar, onClose, onPrev, tx }) => { txData = tokenInstance.contract.methods.transfer(tx.recipientAddress, txAmount).encodeABI() } - const estimatedGasCosts = await estimateTxGasCosts(safeAddress as string, txRecipient, txData) - const gasCostsAsEth = fromWei(toBN(estimatedGasCosts), 'ether') - const formattedGasCosts = formatAmount(gasCostsAsEth) + const estimatedGasCosts = await estimateTxGasCosts(safeAddress as string, txRecipient as string, txData) + const gasCosts = fromTokenUnit(estimatedGasCosts, nativeCoin.decimals) + const formattedGasCosts = formatAmount(gasCosts) if (isCurrent) { setGasCosts(formattedGasCosts) @@ -87,23 +99,24 @@ const ReviewTx = ({ closeSnackbar, enqueueSnackbar, onClose, onPrev, tx }) => { }, [isSendingETH, safeAddress, tx.amount, tx.recipientAddress, txRecipient, txToken]) const submitTx = async () => { - const web3 = getWeb3() // txAmount should be 0 if we send tokens // the real value is encoded in txData and will be used by the contract // if txAmount > 0 it would send ETH from the Safe - const txAmount = isSendingETH ? web3.utils.toWei(tx.amount, 'ether') : '0' + const txAmount = isSendingETH ? toTokenUnit(tx.amount, nativeCoin.decimals) : '0' - dispatch( - createTransaction({ - safeAddress, - to: txRecipient, - valueInWei: txAmount, - txData: data, - notifiedTransaction: TX_NOTIFICATION_TYPES.STANDARD_TX, - enqueueSnackbar, - closeSnackbar, - } as any), - ) + if (safeAddress) { + dispatch( + createTransaction({ + safeAddress: safeAddress, + to: txRecipient as string, + valueInWei: txAmount, + txData: data, + notifiedTransaction: TX_NOTIFICATION_TYPES.STANDARD_TX, + }), + ) + } else { + console.error('There was an error trying to submit the transaction, the safeAddress was not found') + } onClose() } @@ -149,7 +162,7 @@ const ReviewTx = ({ closeSnackbar, enqueueSnackbar, onClose, onPrev, tx }) => { {tx.recipientAddress} - + @@ -171,7 +184,7 @@ const ReviewTx = ({ closeSnackbar, enqueueSnackbar, onClose, onPrev, tx }) => { - {`You're about to create a transaction and will have to confirm it with your currently connected wallet. Make sure you have ${gasCosts} (fee price) ETH in this wallet to fund this confirmation.`} + {`You're about to create a transaction and will have to confirm it with your currently connected wallet. Make sure you have ${gasCosts} (fee price) ${nativeCoin.name} in this wallet to fund this confirmation.`} @@ -197,4 +210,4 @@ const ReviewTx = ({ closeSnackbar, enqueueSnackbar, onClose, onPrev, tx }) => { ) } -export default withSnackbar(ReviewTx) +export default ReviewTx diff --git a/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/style.ts b/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/style.ts index 52f70b5a..e6e4fbcf 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/style.ts +++ b/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/style.ts @@ -1,6 +1,7 @@ import { lg, md, secondaryText, sm } from 'src/theme/variables' +import { createStyles } from '@material-ui/core' -export const styles = () => ({ +export const styles = createStyles({ heading: { padding: `${md} ${lg}`, justifyContent: 'flex-start', diff --git a/src/routes/safe/components/Balances/SendModal/screens/SendCollectible/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/SendCollectible/index.tsx index 14c54f06..2bbb17fa 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/SendCollectible/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/screens/SendCollectible/index.tsx @@ -4,22 +4,18 @@ import Close from '@material-ui/icons/Close' import React, { useState } from 'react' import { useSelector } from 'react-redux' -import ArrowDown from '../assets/arrow-down.svg' - -import { styles } from './style' - import CopyBtn from 'src/components/CopyBtn' import EtherscanBtn from 'src/components/EtherscanBtn' -import Identicon from 'src/components/Identicon' -import { ScanQRWrapper } from 'src/components/ScanQRModal/ScanQRWrapper' -import WhenFieldChanges from 'src/components/WhenFieldChanges' import GnoForm from 'src/components/forms/GnoForm' +import Identicon from 'src/components/Identicon' import Block from 'src/components/layout/Block' import Button from 'src/components/layout/Button' import Col from 'src/components/layout/Col' import Hairline from 'src/components/layout/Hairline' import Paragraph from 'src/components/layout/Paragraph' import Row from 'src/components/layout/Row' +import { ScanQRWrapper } from 'src/components/ScanQRModal/ScanQRWrapper' +import WhenFieldChanges from 'src/components/WhenFieldChanges' import { addressBookSelector } from 'src/logic/addressBook/store/selectors' import { getNameFromAddressBook } from 'src/logic/addressBook/utils' import { nftTokensSelector, safeActiveSelectorMap } from 'src/logic/collectibles/store/selectors' @@ -29,6 +25,11 @@ import CollectibleSelectField from 'src/routes/safe/components/Balances/SendModa import TokenSelectField from 'src/routes/safe/components/Balances/SendModal/screens/SendCollectible/TokenSelectField' import { sm } from 'src/theme/variables' +import ArrowDown from '../assets/arrow-down.svg' + +import { styles } from './style' +import { NFTToken } from 'src/logic/collectibles/sources/collectibles' + const formMutators = { setMax: (args, state, utils) => { utils.changeValue(state, 'amount', () => args[0]) @@ -43,13 +44,28 @@ const formMutators = { const useStyles = makeStyles(styles) +type SendCollectibleProps = { + initialValues: any + onClose: () => void + onNext: (txInfo: SendCollectibleTxInfo) => void + recipientAddress?: string + selectedToken: NFTToken +} + +export type SendCollectibleTxInfo = { + assetAddress: string + assetName: string + nftTokenId: string + recipientAddress?: string +} + const SendCollectible = ({ initialValues, onClose, onNext, recipientAddress, - selectedToken = {}, -}): React.ReactElement => { + selectedToken, +}: SendCollectibleProps): React.ReactElement => { const classes = useStyles() const nftAssets = useSelector(safeActiveSelectorMap) const nftTokens = useSelector(nftTokensSelector) @@ -67,7 +83,7 @@ const SendCollectible = ({ } }, [selectedEntry, pristine]) - const handleSubmit = (values) => { + const handleSubmit = (values: SendCollectibleTxInfo) => { // If the input wasn't modified, there was no mutation of the recipientAddress if (!values.recipientAddress) { values.recipientAddress = selectedEntry?.address @@ -171,7 +187,7 @@ const SendCollectible = ({ - + diff --git a/src/routes/safe/components/Balances/SendModal/screens/SendFunds/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/SendFunds/index.tsx index 27db52e9..92d34615 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/SendFunds/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/screens/SendFunds/index.tsx @@ -2,22 +2,18 @@ import IconButton from '@material-ui/core/IconButton' import InputAdornment from '@material-ui/core/InputAdornment' import { makeStyles } from '@material-ui/core/styles' import Close from '@material-ui/icons/Close' +import { getNetworkInfo } from 'src/config' import React, { useState } from 'react' import { OnChange } from 'react-final-form-listeners' import { useSelector } from 'react-redux' -import ArrowDown from '../assets/arrow-down.svg' - -import { styles } from './style' - import CopyBtn from 'src/components/CopyBtn' import EtherscanBtn from 'src/components/EtherscanBtn' -import Identicon from 'src/components/Identicon' -import { ScanQRWrapper } from 'src/components/ScanQRModal/ScanQRWrapper' import Field from 'src/components/forms/Field' import GnoForm from 'src/components/forms/GnoForm' import TextField from 'src/components/forms/TextField' -import { composeValidators, minValue, maxValue, mustBeFloat, required } from 'src/components/forms/validator' +import { composeValidators, maxValue, minValue, mustBeFloat, required } from 'src/components/forms/validator' +import Identicon from 'src/components/Identicon' import Block from 'src/components/layout/Block' import Button from 'src/components/layout/Button' import ButtonLink from 'src/components/layout/ButtonLink' @@ -25,6 +21,7 @@ import Col from 'src/components/layout/Col' import Hairline from 'src/components/layout/Hairline' import Paragraph from 'src/components/layout/Paragraph' import Row from 'src/components/layout/Row' +import { ScanQRWrapper } from 'src/components/ScanQRModal/ScanQRWrapper' import { addressBookSelector } from 'src/logic/addressBook/store/selectors' import { getNameFromAddressBook } from 'src/logic/addressBook/utils' @@ -34,6 +31,10 @@ import TokenSelectField from 'src/routes/safe/components/Balances/SendModal/scre import { extendedSafeTokensSelector } from 'src/routes/safe/container/selector' import { sm } from 'src/theme/variables' +import ArrowDown from '../assets/arrow-down.svg' + +import { styles } from './style' + const formMutators = { setMax: (args, state, utils) => { utils.changeValue(state, 'amount', () => args[0]) @@ -46,20 +47,24 @@ const formMutators = { }, } -const useStyles = makeStyles(styles as any) +const useStyles = makeStyles(styles) + +export type SendFundsTx = { + amount?: string + recipientAddress?: string + token?: string +} type SendFundsProps = { - initialValues: { - amount?: string - recipientAddress?: string - token?: string - } + initialValues: SendFundsTx onClose: () => void onNext: (txInfo: unknown) => void - recipientAddress: string - selectedToken: string + recipientAddress?: string + selectedToken?: string } +const { nativeCoin } = getNetworkInfo() + const SendFunds = ({ initialValues, onClose, @@ -184,7 +189,7 @@ const SendFunds = ({ - + @@ -211,7 +216,7 @@ const SendFunds = ({ diff --git a/src/routes/safe/components/Balances/SendModal/screens/SendFunds/style.ts b/src/routes/safe/components/Balances/SendModal/screens/SendFunds/style.ts index 44d7d9bb..776dea04 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/SendFunds/style.ts +++ b/src/routes/safe/components/Balances/SendModal/screens/SendFunds/style.ts @@ -1,6 +1,7 @@ import { lg, md, secondaryText } from 'src/theme/variables' +import { createStyles } from '@material-ui/core' -export const styles = () => ({ +export const styles = createStyles({ heading: { padding: `${md} ${lg}`, justifyContent: 'flex-start', diff --git a/src/routes/safe/components/Balances/Tokens/screens/AssetsList/AssetRow.tsx b/src/routes/safe/components/Balances/Tokens/screens/AssetsList/AssetRow.tsx index 4d0af38c..9a927ad2 100644 --- a/src/routes/safe/components/Balances/Tokens/screens/AssetsList/AssetRow.tsx +++ b/src/routes/safe/components/Balances/Tokens/screens/AssetsList/AssetRow.tsx @@ -3,32 +3,32 @@ import ListItemIcon from '@material-ui/core/ListItemIcon' import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction' import ListItemText from '@material-ui/core/ListItemText' import Switch from '@material-ui/core/Switch' -import { withStyles } from '@material-ui/core/styles' import React, { memo } from 'react' -import { styles } from './style' - +import { useStyles } from 'src/routes/safe/components/Balances/Tokens/screens/TokenList/style' import Img from 'src/components/layout/Img' -import { ETH_ADDRESS } from 'src/logic/tokens/utils/tokenHelpers' -import { setImageToPlaceholder } from 'src/routes/safe/components/Balances/utils' +import { getNetworkInfo } from 'src/config' +import { setCollectibleImageToPlaceholder } from 'src/routes/safe/components/Balances/utils' export const TOGGLE_ASSET_TEST_ID = 'toggle-asset-btn' -// eslint-disable-next-line react/display-name -const AssetRow = memo(({ classes, data, index, style }: any) => { +const { nativeCoin } = getNetworkInfo() + +const AssetRow = memo(({ data, index, style }: any) => { + const classes = useStyles() const { activeAssetsAddresses, assets, onSwitch } = data - const asset = assets.get(index) + const asset = assets[index] const { address, image, name, symbol } = asset - const isActive = activeAssetsAddresses.has(asset.address) + const isActive = activeAssetsAddresses.includes(asset.address) return (
- {name} + {name} - {address !== ETH_ADDRESS && ( + {address !== nativeCoin.address && ( { ) }) -export default withStyles(styles as any)(AssetRow) +AssetRow.displayName = 'AssetRow' + +export default AssetRow diff --git a/src/routes/safe/components/Balances/Tokens/screens/AssetsList/index.tsx b/src/routes/safe/components/Balances/Tokens/screens/AssetsList/index.tsx index 1e87da0a..6f4f4e93 100644 --- a/src/routes/safe/components/Balances/Tokens/screens/AssetsList/index.tsx +++ b/src/routes/safe/components/Balances/Tokens/screens/AssetsList/index.tsx @@ -1,14 +1,14 @@ -import CircularProgress from '@material-ui/core/CircularProgress' import MuiList from '@material-ui/core/List' -import { makeStyles } from '@material-ui/core/styles' +import CircularProgress from '@material-ui/core/CircularProgress' import Search from '@material-ui/icons/Search' import cn from 'classnames' import SearchBar from 'material-ui-search-bar' import React, { useState } from 'react' import { useDispatch, useSelector } from 'react-redux' import { FixedSizeList } from 'react-window' +import Paragraph from 'src/components/layout/Paragraph' -import { styles } from './style' +import { useStyles } from './style' import Spacer from 'src/components/Spacer' import Block from 'src/components/layout/Block' @@ -25,10 +25,13 @@ import { safeBlacklistedAssetsSelector, safeParamAddressFromStateSelector, } from 'src/logic/safe/store/selectors' -const useStyles = makeStyles(styles as any) export const ADD_CUSTOM_ASSET_BUTTON_TEST_ID = 'add-custom-asset-btn' +type Props = { + setActiveScreen: (newScreen: string) => void +} + const filterBy = (filter, nfts) => nfts.filter( (asset) => @@ -38,7 +41,7 @@ const filterBy = (filter, nfts) => asset.symbol.toLowerCase().includes(filter.toLowerCase()), ) -const AssetsList = (props) => { +const AssetsList = (props: Props): React.ReactElement => { const classes = useStyles() const searchClasses = { input: classes.searchInput, @@ -128,16 +131,16 @@ const AssetsList = (props) => { - {!nftAssetsList.length && ( + {!nftAssetsList?.length && ( - + {!nftAssetsList ? : No collectibles available} )} - {nftAssetsList.length > 0 && ( + {nftAssetsFilteredList.length > 0 && ( ({ - root: { - minHeight: '52px', - }, - search: { - color: secondaryText, - paddingLeft: sm, - }, - padding: { - padding: `0 ${md}`, - }, - add: { - fontSize: '11px', - fontWeight: 'normal', - paddingRight: md, - paddingLeft: md, - }, - addBtnLabel: { - fontSize: mediumFontSize, - }, - actions: { - height: '50px', - }, - list: { - overflow: 'hidden', - overflowY: 'scroll', - padding: 0, - height: '100%', - }, - tokenIcon: { - marginRight: sm, - height: '28px', - width: '28px', - }, - searchInput: { - backgroundColor: 'transparent', - lineHeight: 'initial', - fontSize: '13px', - padding: 0, - '& > input::placeholder': { - letterSpacing: '-0.5px', +export const useStyles = makeStyles( + createStyles({ + root: { + minHeight: '52px', + }, + search: { + color: secondaryText, + paddingLeft: sm, + }, + padding: { + padding: `0 ${md}`, + }, + add: { + fontSize: '11px', + fontWeight: 'normal', + paddingRight: md, + paddingLeft: md, + }, + addBtnLabel: { fontSize: mediumFontSize, - color: 'black', }, - '& > input': { + actions: { + height: '50px', + }, + list: { + overflow: 'hidden', + overflowY: 'scroll', + padding: 0, + height: '100%', + }, + tokenIcon: { + marginRight: sm, + height: '28px', + width: '28px', + }, + searchInput: { + backgroundColor: 'transparent', + lineHeight: 'initial', + fontSize: '13px', + padding: 0, + '& > input::placeholder': { + letterSpacing: '-0.5px', + fontSize: mediumFontSize, + color: 'black', + }, + '& > input': { + letterSpacing: '-0.5px', + }, + }, + progressContainer: { + width: '100%', + height: '100%', + alignItems: 'center', + }, + searchContainer: { + width: '180px', + marginLeft: xs, + marginRight: xs, + }, + searchRoot: { letterSpacing: '-0.5px', + fontSize: '13px', + border: 'none', + boxShadow: 'none', + '& > button': { + display: 'none', + }, }, - }, - progressContainer: { - width: '100%', - height: '100%', - alignItems: 'center', - }, - searchContainer: { - width: '180px', - marginLeft: xs, - marginRight: xs, - }, - searchRoot: { - letterSpacing: '-0.5px', - fontSize: '13px', - border: 'none', - boxShadow: 'none', - '& > button': { - display: 'none', + searchIcon: { + '&:hover': { + backgroundColor: 'transparent !important', + }, }, - }, - searchIcon: { - '&:hover': { - backgroundColor: 'transparent !important', - }, - }, -}) + }), +) diff --git a/src/routes/safe/components/Balances/Tokens/screens/TokenList/TokenRow.tsx b/src/routes/safe/components/Balances/Tokens/screens/TokenList/TokenRow.tsx index 01b2501c..9b73f079 100644 --- a/src/routes/safe/components/Balances/Tokens/screens/TokenList/TokenRow.tsx +++ b/src/routes/safe/components/Balances/Tokens/screens/TokenList/TokenRow.tsx @@ -3,22 +3,33 @@ import ListItemIcon from '@material-ui/core/ListItemIcon' import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction' import ListItemText from '@material-ui/core/ListItemText' import Switch from '@material-ui/core/Switch' -import { withStyles } from '@material-ui/core/styles' -import React, { memo } from 'react' - -import { styles } from './style' +import React, { CSSProperties, memo, ReactElement } from 'react' +import { useStyles } from './style' import Img from 'src/components/layout/Img' - -import { ETH_ADDRESS } from 'src/logic/tokens/utils/tokenHelpers' +import { getNetworkInfo } from 'src/config' import { setImageToPlaceholder } from 'src/routes/safe/components/Balances/utils' +import { ItemData } from 'src/routes/safe/components/Balances/Tokens/screens/TokenList/index' export const TOGGLE_TOKEN_TEST_ID = 'toggle-token-btn' -// eslint-disable-next-line react/display-name -const TokenRow = memo(({ classes, data, index, style }: any) => { +interface TokenRowProps { + data: ItemData + index: number + style: CSSProperties +} + +const { nativeCoin } = getNetworkInfo() + +const TokenRow = memo(({ data, index, style }: TokenRowProps): ReactElement | null => { + const classes = useStyles() const { activeTokensAddresses, onSwitch, tokens } = data const token = tokens.get(index) + + if (!token) { + return null + } + const isActive = activeTokensAddresses.has(token.address) return ( @@ -28,13 +39,9 @@ const TokenRow = memo(({ classes, data, index, style }: any) => { {token.name} - {token.address !== ETH_ADDRESS && ( - - + {token.address !== nativeCoin.address && ( + + )} @@ -42,4 +49,6 @@ const TokenRow = memo(({ classes, data, index, style }: any) => { ) }) -export default withStyles(styles as any)(TokenRow) +TokenRow.displayName = 'TokenRow' + +export default TokenRow diff --git a/src/routes/safe/components/Balances/Tokens/screens/TokenList/index.tsx b/src/routes/safe/components/Balances/Tokens/screens/TokenList/index.tsx index 999dd941..7cd838cb 100644 --- a/src/routes/safe/components/Balances/Tokens/screens/TokenList/index.tsx +++ b/src/routes/safe/components/Balances/Tokens/screens/TokenList/index.tsx @@ -1,6 +1,5 @@ import CircularProgress from '@material-ui/core/CircularProgress' import MuiList from '@material-ui/core/List' -import { makeStyles } from '@material-ui/core/styles' import Search from '@material-ui/icons/Search' import cn from 'classnames' import { List, Set } from 'immutable' @@ -9,7 +8,7 @@ import React, { useState } from 'react' import { FixedSizeList } from 'react-window' import TokenRow from './TokenRow' -import { styles } from './style' +import { useStyles } from './style' import Spacer from 'src/components/Spacer' import Block from 'src/components/layout/Block' @@ -32,8 +31,6 @@ const filterBy = (filter: string, tokens: List): List => token.name.toLowerCase().includes(filter.toLowerCase()), ) -const useStyles = makeStyles(styles) - type Props = { setActiveScreen: (newScreen: string) => void tokens: List @@ -42,6 +39,12 @@ type Props = { safeAddress: string } +export type ItemData = { + tokens: List + activeTokensAddresses: Set + onSwitch: (token: Token) => () => void +} + export const TokenList = (props: Props): React.ReactElement => { const classes = useStyles() const { setActiveScreen, tokens, activeTokens, blacklistedTokens, safeAddress } = props @@ -59,7 +62,6 @@ export const TokenList = (props: Props): React.ReactElement => { const onCancelSearch = () => { setFilter('') - this.setState(() => ({ filter: '' })) } const onChangeSearchBar = (value: string) => { @@ -85,16 +87,11 @@ export const TokenList = (props: Props): React.ReactElement => { dispatch(updateBlacklistedTokens(safeAddress, newBlacklistedTokensAddresses)) } - const createItemData = ( - tokens: List, - activeTokensAddresses: Set, - ): { tokens: List; activeTokensAddresses: Set; onSwitch: (token: Token) => void } => { - return { - tokens, - activeTokensAddresses, - onSwitch: onSwitch, - } - } + const createItemData = (tokens: List, activeTokensAddresses: Set): ItemData => ({ + tokens, + activeTokensAddresses, + onSwitch, + }) const switchToAddCustomTokenScreen = () => setActiveScreen('addCustomToken') diff --git a/src/routes/safe/components/Balances/Tokens/screens/TokenList/style.ts b/src/routes/safe/components/Balances/Tokens/screens/TokenList/style.ts index ac7f8c34..18631a78 100644 --- a/src/routes/safe/components/Balances/Tokens/screens/TokenList/style.ts +++ b/src/routes/safe/components/Balances/Tokens/screens/TokenList/style.ts @@ -1,84 +1,87 @@ -import { border, md, mediumFontSize, secondaryText, sm, xs } from 'src/theme/variables' -import { createStyles } from '@material-ui/core' +import { createStyles, makeStyles } from '@material-ui/core' -export const styles = createStyles({ - root: { - minHeight: '52px', - }, - search: { - color: secondaryText, - paddingLeft: sm, - }, - padding: { - padding: `0 ${md}`, - }, - add: { - fontSize: '11px', - fontWeight: 'normal', - paddingRight: md, - paddingLeft: md, - }, - addBtnLabel: { - fontSize: mediumFontSize, - }, - actions: { - height: '50px', - }, - list: { - overflow: 'hidden', - overflowY: 'scroll', - padding: 0, - height: '100%', - }, - token: { - minHeight: '50px', - borderBottom: `1px solid ${border}`, - }, - tokenRoot: { - paddingTop: 0, - paddingBottom: 0, - }, - searchInput: { - backgroundColor: 'transparent', - lineHeight: 'initial', - fontSize: '13px', - padding: 0, - '& > input::placeholder': { - letterSpacing: '-0.5px', +import { border, md, mediumFontSize, secondaryText, sm, xs } from 'src/theme/variables' + +export const useStyles = makeStyles( + createStyles({ + root: { + minHeight: '52px', + }, + search: { + color: secondaryText, + paddingLeft: sm, + }, + padding: { + padding: `0 ${md}`, + }, + add: { + fontSize: '11px', + fontWeight: 'normal', + paddingRight: md, + paddingLeft: md, + }, + addBtnLabel: { fontSize: mediumFontSize, - color: 'black', }, - '& > input': { + actions: { + height: '50px', + }, + list: { + overflow: 'hidden', + overflowY: 'scroll', + padding: 0, + height: '100%', + }, + token: { + minHeight: '50px', + borderBottom: `1px solid ${border}`, + }, + tokenRoot: { + paddingTop: 0, + paddingBottom: 0, + }, + searchInput: { + backgroundColor: 'transparent', + lineHeight: 'initial', + fontSize: '13px', + padding: 0, + '& > input::placeholder': { + letterSpacing: '-0.5px', + fontSize: mediumFontSize, + color: 'black', + }, + '& > input': { + letterSpacing: '-0.5px', + }, + }, + tokenIcon: { + marginRight: md, + height: '28px', + width: '28px', + }, + progressContainer: { + width: '100%', + height: '100%', + alignItems: 'center', + }, + searchContainer: { + width: '180px', + marginLeft: xs, + marginRight: xs, + }, + searchRoot: { letterSpacing: '-0.5px', + fontSize: '13px', + border: 'none', + boxShadow: 'none', + '& > button': { + display: 'none', + }, }, - }, - tokenIcon: { - marginRight: md, - height: '28px', - width: '28px', - }, - progressContainer: { - width: '100%', - height: '100%', - alignItems: 'center', - }, - searchContainer: { - width: '180px', - marginLeft: xs, - marginRight: xs, - }, - searchRoot: { - letterSpacing: '-0.5px', - fontSize: '13px', - border: 'none', - boxShadow: 'none', - '& > button': { - display: 'none', + searchIcon: { + '&:hover': { + backgroundColor: 'transparent !important', + }, }, - }, - searchIcon: { - '&:hover': { - backgroundColor: 'transparent !important', - }, - }, -}) + }), +) diff --git a/src/routes/safe/components/Balances/dataFetcher.ts b/src/routes/safe/components/Balances/dataFetcher.ts index e19c215a..d2d9b7d8 100644 --- a/src/routes/safe/components/Balances/dataFetcher.ts +++ b/src/routes/safe/components/Balances/dataFetcher.ts @@ -1,29 +1,29 @@ import { BigNumber } from 'bignumber.js' import { List } from 'immutable' - +import { getNetworkInfo } from 'src/config' import { FIXED } from 'src/components/Table/sorting' import { formatAmountInUsFormat } from 'src/logic/tokens/utils/formatAmount' -import { ETH_ADDRESS } from 'src/logic/tokens/utils/tokenHelpers' import { TableColumn } from 'src/components/Table/types.d' -import { AVAILABLE_CURRENCIES, BalanceCurrencyList } from 'src/logic/currencyValues/store/model/currencyValues' +import { BalanceCurrencyList } from 'src/logic/currencyValues/store/model/currencyValues' import { Token } from 'src/logic/tokens/store/model/token' export const BALANCE_TABLE_ASSET_ID = 'asset' export const BALANCE_TABLE_BALANCE_ID = 'balance' export const BALANCE_TABLE_VALUE_ID = 'value' +const { nativeCoin } = getNetworkInfo() + const getTokenPriceInCurrency = ( token: Token, - currencySelected?: AVAILABLE_CURRENCIES, + currencySelected?: string, currencyValues?: BalanceCurrencyList, currencyRate?: number, ): string => { if (!currencySelected) { return '' } - const currencyValue = currencyValues?.find(({ tokenAddress }) => { - if (token.address === ETH_ADDRESS && !tokenAddress) { + if (token.address === nativeCoin.address && !tokenAddress) { return true } @@ -51,11 +51,12 @@ export interface BalanceData { export const getBalanceData = ( activeTokens: List, - currencySelected?: AVAILABLE_CURRENCIES, + currencySelected?: string, currencyValues?: BalanceCurrencyList, currencyRate?: number, -): List => - activeTokens.map((token) => ({ +): List => { + const { nativeCoin } = getNetworkInfo() + return activeTokens.map((token) => ({ [BALANCE_TABLE_ASSET_ID]: { name: token.name, logoUri: token.logoUri, @@ -65,9 +66,10 @@ export const getBalanceData = ( assetOrder: token.name, [BALANCE_TABLE_BALANCE_ID]: `${formatAmountInUsFormat(token.balance?.toString() || '0')} ${token.symbol}`, balanceOrder: Number(token.balance), - [FIXED]: token.symbol === 'ETH', + [FIXED]: token.symbol === nativeCoin.symbol, [BALANCE_TABLE_VALUE_ID]: getTokenPriceInCurrency(token, currencySelected, currencyValues, currencyRate), })) +} export const generateColumns = (): List => { const assetColumn: TableColumn = { diff --git a/src/routes/safe/components/Balances/index.tsx b/src/routes/safe/components/Balances/index.tsx index 1f5489c6..49bd4d8b 100644 --- a/src/routes/safe/components/Balances/index.tsx +++ b/src/routes/safe/components/Balances/index.tsx @@ -2,7 +2,7 @@ import { makeStyles } from '@material-ui/core/styles' import React, { useEffect, useState } from 'react' import { useSelector } from 'react-redux' -import Receive from 'src/components/App/ReceiveModal' +import ReceiveModal from 'src/components/App/ReceiveModal' import Tokens from './Tokens' import { styles } from './style' @@ -17,13 +17,14 @@ import SendModal from 'src/routes/safe/components/Balances/SendModal' import CurrencyDropdown from 'src/routes/safe/components/CurrencyDropdown' import { safeFeaturesEnabledSelector, - safeParamAddressFromStateSelector, safeNameSelector, + safeParamAddressFromStateSelector, } from 'src/logic/safe/store/selectors' import { wrapInSuspense } from 'src/utils/wrapInSuspense' import { useFetchTokens } from 'src/logic/safe/hooks/useFetchTokens' -import { Route, Switch, NavLink, Redirect } from 'react-router-dom' +import { NavLink, Redirect, Route, Switch } from 'react-router-dom' +import { FEATURES } from 'src/config/networks/network.d' const Collectibles = React.lazy(() => import('src/routes/safe/components/Balances/Collectibles')) const Coins = React.lazy(() => import('src/routes/safe/components/Balances/Coins')) @@ -53,12 +54,12 @@ const Balances = (): React.ReactElement => { const address = useSelector(safeParamAddressFromStateSelector) const featuresEnabled = useSelector(safeFeaturesEnabledSelector) - const safeName = useSelector(safeNameSelector) + const safeName = useSelector(safeNameSelector) ?? '' useFetchTokens(address as string) useEffect(() => { - const erc721Enabled = Boolean(featuresEnabled?.includes('ERC721')) + const erc721Enabled = Boolean(featuresEnabled?.includes(FEATURES.ERC721)) setState((prevState) => ({ ...prevState, @@ -229,7 +230,7 @@ const Balances = (): React.ReactElement => { paperClassName={receiveModal} title="Receive Tokens" > - onHide('Receive')} /> + onHide('Receive')} /> ) diff --git a/src/routes/safe/components/Balances/utils/index.ts b/src/routes/safe/components/Balances/utils/index.ts index 2fb9682f..f91f4984 100644 --- a/src/routes/safe/components/Balances/utils/index.ts +++ b/src/routes/safe/components/Balances/utils/index.ts @@ -1 +1,2 @@ -export * from './setTokenImgToPlaceholder' +export { setImageToPlaceholder } from './setTokenImgToPlaceholder' +export { setCollectibleImageToPlaceholder } from './setCollectibleImageToPlaceholder' diff --git a/src/routes/safe/components/Balances/utils/setCollectibleImageToPlaceholder.ts b/src/routes/safe/components/Balances/utils/setCollectibleImageToPlaceholder.ts new file mode 100644 index 00000000..31081dee --- /dev/null +++ b/src/routes/safe/components/Balances/utils/setCollectibleImageToPlaceholder.ts @@ -0,0 +1,8 @@ +import { SyntheticEvent } from 'react' + +import NFTIcon from 'src/routes/safe/components/Balances/assets/nft_icon.png' + +export const setCollectibleImageToPlaceholder = (error: SyntheticEvent): void => { + error.currentTarget.onerror = null + error.currentTarget.src = NFTIcon +} diff --git a/src/routes/safe/components/Balances/utils/setTokenImgToPlaceholder.ts b/src/routes/safe/components/Balances/utils/setTokenImgToPlaceholder.ts index 9d8b6519..eaa64a39 100644 --- a/src/routes/safe/components/Balances/utils/setTokenImgToPlaceholder.ts +++ b/src/routes/safe/components/Balances/utils/setTokenImgToPlaceholder.ts @@ -1,6 +1,8 @@ +import { SyntheticEvent } from 'react' + import TokenPlaceholder from 'src/routes/safe/components/Balances/assets/token_placeholder.svg' -export const setImageToPlaceholder = (e) => { - e.target.onerror = null - e.target.src = TokenPlaceholder +export const setImageToPlaceholder = (error: SyntheticEvent): void => { + error.currentTarget.onerror = null + error.currentTarget.src = TokenPlaceholder } diff --git a/src/routes/safe/components/CurrencyDropdown/index.tsx b/src/routes/safe/components/CurrencyDropdown/index.tsx index 862c0251..2304aa69 100644 --- a/src/routes/safe/components/CurrencyDropdown/index.tsx +++ b/src/routes/safe/components/CurrencyDropdown/index.tsx @@ -20,16 +20,20 @@ import { safeParamAddressFromStateSelector } from 'src/logic/safe/store/selector import { DropdownListTheme } from 'src/theme/mui' import { setImageToPlaceholder } from '../Balances/utils' import Img from 'src/components/layout/Img/index' -import etherIcon from 'src/assets/icons/icon_etherTokens.svg' +import { getNetworkInfo } from 'src/config' +import { sameString } from 'src/utils/strings' + +const { nativeCoin } = getNetworkInfo() const CurrencyDropdown = (): React.ReactElement | null => { - const currenciesList = Object.values(AVAILABLE_CURRENCIES) const safeAddress = useSelector(safeParamAddressFromStateSelector) as string const dispatch = useDispatch() const [anchorEl, setAnchorEl] = useState(null) const selectedCurrency = useSelector(currentCurrencySelector) - const [searchParams, setSearchParams] = useState('') + + const currenciesList = Object.values(AVAILABLE_CURRENCIES) + const tokenImage = nativeCoin.logoUri const classes = useDropdownStyles() const currenciesListFiltered = currenciesList.filter((currency) => currency.toLowerCase().includes(searchParams.toLowerCase()), @@ -103,11 +107,11 @@ const CurrencyDropdown = (): React.ReactElement | null => { value={currencyName} > - {currencyName === AVAILABLE_CURRENCIES.ETH ? ( + {sameString(currencyName, nativeCoin.symbol) ? ( ether ) : ( diff --git a/src/routes/safe/components/Settings/Advanced/RemoveModuleModal.tsx b/src/routes/safe/components/Settings/Advanced/RemoveModuleModal.tsx index e630c45d..a24fc72c 100644 --- a/src/routes/safe/components/Settings/Advanced/RemoveModuleModal.tsx +++ b/src/routes/safe/components/Settings/Advanced/RemoveModuleModal.tsx @@ -8,24 +8,25 @@ import React from 'react' import { useDispatch, useSelector } from 'react-redux' import styled from 'styled-components' -import { styles } from './style' +import Identicon from 'src/components/Identicon' +import Block from 'src/components/layout/Block' +import Col from 'src/components/layout/Col' +import Hairline from 'src/components/layout/Hairline' +import Link from 'src/components/layout/Link' +import Paragraph from 'src/components/layout/Paragraph' +import Row from 'src/components/layout/Row' +import Modal from 'src/components/Modal' +import { getExplorerInfo } from 'src/config' +import { getDisableModuleTxData } from 'src/logic/safe/utils/modules' +import createTransaction from 'src/logic/safe/store/actions/createTransaction' import { ModulePair } from 'src/logic/safe/store/models/safe' import { safeParamAddressFromStateSelector } from 'src/logic/safe/store/selectors' -import { getGnosisSafeInstanceAt } from 'src/logic/contracts/safeContracts' -import createTransaction from 'src/logic/safe/store/actions/createTransaction' import { TX_NOTIFICATION_TYPES } from 'src/logic/safe/transactions' -import Modal from 'src/components/Modal' -import Row from 'src/components/layout/Row' -import Paragraph from 'src/components/layout/Paragraph' -import Hairline from 'src/components/layout/Hairline' -import Block from 'src/components/layout/Block' -import Col from 'src/components/layout/Col' -import Identicon from 'src/components/Identicon' -import Link from 'src/components/layout/Link' -import { getEtherScanLink } from 'src/logic/wallets/getWeb3' import { md, secondary } from 'src/theme/variables' +import { styles } from './style' + const useStyles = makeStyles(styles) const FooterWrapper = styled.div` @@ -38,22 +39,23 @@ const openIconStyle = { color: secondary, } -interface RemoveModuleModal { +interface RemoveModuleModalProps { onClose: () => void selectedModule: ModulePair } -const RemoveModuleModal = ({ onClose, selectedModule }: RemoveModuleModal): React.ReactElement => { +const RemoveModuleModal = ({ onClose, selectedModule }: RemoveModuleModalProps): React.ReactElement => { const classes = useStyles() - const safeAddress = useSelector(safeParamAddressFromStateSelector) as string + const safeAddress = useSelector(safeParamAddressFromStateSelector) const dispatch = useDispatch() + const explorerInfo = getExplorerInfo(selectedModule[0]) + const { url } = explorerInfo() + const removeSelectedModule = async (): Promise => { try { - const safeInstance = await getGnosisSafeInstanceAt(safeAddress) - const [module, prevModule] = selectedModule - const txData = safeInstance.methods.disableModule(prevModule, module).encodeABI() + const txData = getDisableModuleTxData(selectedModule, safeAddress) dispatch( createTransaction({ @@ -101,11 +103,7 @@ const RemoveModuleModal = ({ onClose, selectedModule }: RemoveModuleModal): Reac {selectedModule[0]} - + diff --git a/src/routes/safe/components/Settings/Advanced/index.tsx b/src/routes/safe/components/Settings/Advanced/index.tsx index f53db1de..d2740777 100644 --- a/src/routes/safe/components/Settings/Advanced/index.tsx +++ b/src/routes/safe/components/Settings/Advanced/index.tsx @@ -83,7 +83,7 @@ const Advanced = (): React.ReactElement => { . - {moduleData === null ? ( + {!moduleData ? ( ) : moduleData?.length === 0 ? ( diff --git a/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.tsx b/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.tsx index 883690a8..88a170fa 100644 --- a/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.tsx +++ b/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.tsx @@ -1,5 +1,4 @@ -import { withStyles } from '@material-ui/core/styles' -import { withSnackbar } from 'notistack' +import { createStyles, makeStyles } from '@material-ui/core/styles' import React, { useEffect, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' @@ -14,11 +13,12 @@ import { TX_NOTIFICATION_TYPES } from 'src/logic/safe/transactions' import addSafeOwner from 'src/logic/safe/store/actions/addSafeOwner' import createTransaction from 'src/logic/safe/store/actions/createTransaction' -import { safeOwnersSelector, safeParamAddressFromStateSelector } from 'src/logic/safe/store/selectors' +import { safeParamAddressFromStateSelector } from 'src/logic/safe/store/selectors' import { checksumAddress } from 'src/utils/checksumAddress' import { makeAddressBookEntry } from 'src/logic/addressBook/model/addressBook' +import { Dispatch } from 'src/logic/safe/store/actions/types' -const styles = () => ({ +const styles = createStyles({ biggerModalWindow: { width: '775px', minHeight: '500px', @@ -26,7 +26,15 @@ const styles = () => ({ }, }) -export const sendAddOwner = async (values, safeAddress, ownersOld, enqueueSnackbar, closeSnackbar, dispatch) => { +const useStyles = makeStyles(styles) + +type OwnerValues = { + ownerAddress: string + ownerName: string + threshold: string +} + +export const sendAddOwner = async (values: OwnerValues, safeAddress: string, dispatch: Dispatch): Promise => { const gnosisSafe = await getGnosisSafeInstanceAt(safeAddress) const txData = gnosisSafe.methods.addOwnerWithThreshold(values.ownerAddress, values.threshold).encodeABI() @@ -37,9 +45,7 @@ export const sendAddOwner = async (values, safeAddress, ownersOld, enqueueSnackb valueInWei: '0', txData, notifiedTransaction: TX_NOTIFICATION_TYPES.SETTINGS_CHANGE_TX, - enqueueSnackbar, - closeSnackbar, - } as any), + }), ) if (txHash) { @@ -47,12 +53,17 @@ export const sendAddOwner = async (values, safeAddress, ownersOld, enqueueSnackb } } -const AddOwner = ({ classes, closeSnackbar, enqueueSnackbar, isOpen, onClose }) => { +type Props = { + isOpen: boolean + onClose: () => void +} + +const AddOwner = ({ isOpen, onClose }: Props): React.ReactElement => { + const classes = useStyles() const [activeScreen, setActiveScreen] = useState('selectOwner') const [values, setValues] = useState({}) const dispatch = useDispatch() const safeAddress = useSelector(safeParamAddressFromStateSelector) - const owners = useSelector(safeOwnersSelector) useEffect( () => () => { @@ -91,7 +102,7 @@ const AddOwner = ({ classes, closeSnackbar, enqueueSnackbar, isOpen, onClose }) onClose() try { - await sendAddOwner(values, safeAddress, owners, enqueueSnackbar, closeSnackbar, dispatch) + await sendAddOwner(values, safeAddress, dispatch) dispatch( addOrUpdateAddressBookEntry(makeAddressBookEntry({ name: values.ownerName, address: values.ownerAddress })), ) @@ -121,4 +132,4 @@ const AddOwner = ({ classes, closeSnackbar, enqueueSnackbar, isOpen, onClose }) ) } -export default withStyles(styles as any)(withSnackbar(AddOwner)) +export default AddOwner diff --git a/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/screens/Review/index.tsx b/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/screens/Review/index.tsx index dde8e118..1721a983 100644 --- a/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/screens/Review/index.tsx +++ b/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/screens/Review/index.tsx @@ -4,9 +4,8 @@ import Close from '@material-ui/icons/Close' import classNames from 'classnames' import React, { useEffect, useState } from 'react' import { useSelector } from 'react-redux' - -import { styles } from './style' - +import { fromTokenUnit } from 'src/logic/tokens/utils/humanReadableValue' +import { getNetworkInfo } from 'src/config' import CopyBtn from 'src/components/CopyBtn' import EtherscanBtn from 'src/components/EtherscanBtn' import Identicon from 'src/components/Identicon' @@ -17,13 +16,16 @@ import Hairline from 'src/components/layout/Hairline' import Paragraph from 'src/components/layout/Paragraph' import Row from 'src/components/layout/Row' import { getGnosisSafeInstanceAt } from 'src/logic/contracts/safeContracts' -import { estimateTxGasCosts } from 'src/logic/safe/transactions/gasNew' -import { formatAmount } from 'src/logic/tokens/utils/formatAmount' -import { getWeb3 } from 'src/logic/wallets/getWeb3' import { safeNameSelector, safeOwnersSelector, safeParamAddressFromStateSelector } from 'src/logic/safe/store/selectors' +import { estimateTxGasCosts } from 'src/logic/safe/transactions/gas' +import { formatAmount } from 'src/logic/tokens/utils/formatAmount' + +import { styles } from './style' export const ADD_OWNER_SUBMIT_BTN_TEST_ID = 'add-owner-submit-btn' +const { nativeCoin } = getNetworkInfo() + const ReviewAddOwner = ({ classes, onClickBack, onClose, onSubmit, values }) => { const [gasCosts, setGasCosts] = useState('< 0.001') const safeAddress = useSelector(safeParamAddressFromStateSelector) as string @@ -32,15 +34,13 @@ const ReviewAddOwner = ({ classes, onClickBack, onClose, onSubmit, values }) => useEffect(() => { let isCurrent = true const estimateGas = async () => { - const web3 = getWeb3() - const { fromWei, toBN } = web3.utils const safeInstance = await getGnosisSafeInstanceAt(safeAddress) const txData = safeInstance.methods.addOwnerWithThreshold(values.ownerAddress, values.threshold).encodeABI() const estimatedGasCosts = await estimateTxGasCosts(safeAddress, safeAddress, txData) - const gasCostsAsEth = fromWei(toBN(estimatedGasCosts), 'ether') - const formattedGasCosts = formatAmount(gasCostsAsEth) + const gasCosts = fromTokenUnit(estimatedGasCosts, nativeCoin.decimals) + const formattedGasCosts = formatAmount(gasCosts) if (isCurrent) { setGasCosts(formattedGasCosts) } @@ -118,7 +118,7 @@ const ReviewAddOwner = ({ classes, onClickBack, onClose, onSubmit, values }) => {owner.address} - + @@ -146,7 +146,7 @@ const ReviewAddOwner = ({ classes, onClickBack, onClose, onSubmit, values }) => {values.ownerAddress} - + @@ -160,7 +160,7 @@ const ReviewAddOwner = ({ classes, onClickBack, onClose, onSubmit, values }) => You're about to create a transaction and will have to confirm it with your currently connected wallet.
- {`Make sure you have ${gasCosts} (fee price) ETH in this wallet to fund this confirmation.`} + {`Make sure you have ${gasCosts} (fee price) ${nativeCoin.name} in this wallet to fund this confirmation.`}
diff --git a/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/index.tsx b/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/index.tsx index 7f6fbec5..6d750aed 100644 --- a/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/index.tsx +++ b/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/index.tsx @@ -4,28 +4,28 @@ import Close from '@material-ui/icons/Close' import React from 'react' import { useDispatch, useSelector } from 'react-redux' -import { styles } from './style' - import CopyBtn from 'src/components/CopyBtn' import EtherscanBtn from 'src/components/EtherscanBtn' -import Identicon from 'src/components/Identicon' -import Modal from 'src/components/Modal' import Field from 'src/components/forms/Field' import GnoForm from 'src/components/forms/GnoForm' import TextField from 'src/components/forms/TextField' import { composeValidators, minMaxLength, required } from 'src/components/forms/validator' +import Identicon from 'src/components/Identicon' import Block from 'src/components/layout/Block' import Button from 'src/components/layout/Button' import Hairline from 'src/components/layout/Hairline' import Paragraph from 'src/components/layout/Paragraph' import Row from 'src/components/layout/Row' +import Modal from 'src/components/Modal' import { makeAddressBookEntry } from 'src/logic/addressBook/model/addressBook' +import { addOrUpdateAddressBookEntry } from 'src/logic/addressBook/store/actions/addOrUpdateAddressBookEntry' import { NOTIFICATIONS } from 'src/logic/notifications' +import enqueueSnackbar from 'src/logic/notifications/store/actions/enqueueSnackbar' import editSafeOwner from 'src/logic/safe/store/actions/editSafeOwner' import { safeParamAddressFromStateSelector } from 'src/logic/safe/store/selectors' import { sm } from 'src/theme/variables' -import enqueueSnackbar from 'src/logic/notifications/store/actions/enqueueSnackbar' -import { addOrUpdateAddressBookEntry } from 'src/logic/addressBook/store/actions/addOrUpdateAddressBookEntry' + +import { styles } from './style' export const RENAME_OWNER_INPUT_TEST_ID = 'rename-owner-input' export const SAVE_OWNER_CHANGES_BTN_TEST_ID = 'save-owner-changes-btn' @@ -93,7 +93,7 @@ const EditOwnerComponent = ({ isOpen, onClose, ownerAddress, selectedOwnerName } {ownerAddress} - + diff --git a/src/routes/safe/components/Settings/ManageOwners/OwnerAddressTableCell/index.tsx b/src/routes/safe/components/Settings/ManageOwners/OwnerAddressTableCell/index.tsx index 13313a54..0caf445c 100644 --- a/src/routes/safe/components/Settings/ManageOwners/OwnerAddressTableCell/index.tsx +++ b/src/routes/safe/components/Settings/ManageOwners/OwnerAddressTableCell/index.tsx @@ -1,12 +1,12 @@ import * as React from 'react' +import { useEffect, useState } from 'react' import EtherScanLink from 'src/components/EtherscanLink' import Identicon from 'src/components/Identicon' import Block from 'src/components/layout/Block' import Paragraph from 'src/components/layout/Paragraph' -import { useWindowDimensions } from 'src/logic/hooks/useWindowDimensions' -import { useEffect, useState } from 'react' import { getValidAddressBookName } from 'src/logic/addressBook/utils' +import { useWindowDimensions } from 'src/logic/hooks/useWindowDimensions' type OwnerAddressTableCellProps = { address: string @@ -36,7 +36,7 @@ const OwnerAddressTableCell = (props: OwnerAddressTableCellProps): React.ReactEl {showLinks ? (
{userName && getValidAddressBookName(userName)} - +
) : ( {address} diff --git a/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/index.tsx b/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/index.tsx index e60d396f..347c131d 100644 --- a/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/index.tsx +++ b/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/index.tsx @@ -1,5 +1,4 @@ -import { withStyles } from '@material-ui/core/styles' -import { withSnackbar } from 'notistack' +import { createStyles, makeStyles } from '@material-ui/core/styles' import React, { useEffect, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' @@ -13,13 +12,10 @@ import { TX_NOTIFICATION_TYPES } from 'src/logic/safe/transactions' import createTransaction from 'src/logic/safe/store/actions/createTransaction' import removeSafeOwner from 'src/logic/safe/store/actions/removeSafeOwner' -import { - safeOwnersSelector, - safeParamAddressFromStateSelector, - safeThresholdSelector, -} from 'src/logic/safe/store/selectors' +import { safeParamAddressFromStateSelector, safeThresholdSelector } from 'src/logic/safe/store/selectors' +import { Dispatch } from 'src/logic/safe/store/actions/types' -const styles = () => ({ +const styles = createStyles({ biggerModalWindow: { width: '775px', minHeight: '500px', @@ -27,17 +23,22 @@ const styles = () => ({ }, }) +const useStyles = makeStyles(styles) + +type OwnerValues = { + ownerAddress: string + ownerName: string + threshold: string +} + export const sendRemoveOwner = async ( - values, - safeAddress, - ownerAddressToRemove, - ownerNameToRemove, - ownersOld, - enqueueSnackbar, - closeSnackbar, - threshold, - dispatch, -) => { + values: OwnerValues, + safeAddress: string, + ownerAddressToRemove: string, + ownerNameToRemove: string, + dispatch: Dispatch, + threshold?: number, +): Promise => { const gnosisSafe = await getGnosisSafeInstanceAt(safeAddress) const safeOwners = await gnosisSafe.methods.getOwners().call() const index = safeOwners.findIndex( @@ -53,9 +54,7 @@ export const sendRemoveOwner = async ( valueInWei: '0', txData, notifiedTransaction: TX_NOTIFICATION_TYPES.SETTINGS_CHANGE_TX, - enqueueSnackbar, - closeSnackbar, - } as any), + }), ) if (txHash && threshold === 1) { @@ -63,11 +62,18 @@ export const sendRemoveOwner = async ( } } -const RemoveOwner = ({ classes, closeSnackbar, enqueueSnackbar, isOpen, onClose, ownerAddress, ownerName }) => { +type RemoveOwnerProps = { + isOpen: boolean + onClose: () => void + ownerAddress: string + ownerName: string +} + +const RemoveOwner = ({ isOpen, onClose, ownerAddress, ownerName }: RemoveOwnerProps): React.ReactElement => { + const classes = useStyles() const [activeScreen, setActiveScreen] = useState('checkOwner') const [values, setValues] = useState({}) const dispatch = useDispatch() - const owners = useSelector(safeOwnersSelector) const safeAddress = useSelector(safeParamAddressFromStateSelector) const threshold = useSelector(safeThresholdSelector) @@ -99,17 +105,7 @@ const RemoveOwner = ({ classes, closeSnackbar, enqueueSnackbar, isOpen, onClose, const onRemoveOwner = () => { onClose() - sendRemoveOwner( - values, - safeAddress, - ownerAddress, - ownerName, - owners, - enqueueSnackbar, - closeSnackbar, - threshold, - dispatch, - ) + sendRemoveOwner(values, safeAddress, ownerAddress, ownerName, dispatch, threshold) } return ( @@ -142,4 +138,4 @@ const RemoveOwner = ({ classes, closeSnackbar, enqueueSnackbar, isOpen, onClose, ) } -export default withStyles(styles as any)(withSnackbar(RemoveOwner)) +export default RemoveOwner diff --git a/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/screens/CheckOwner/index.tsx b/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/screens/CheckOwner/index.tsx index eb2853ab..3ab15c42 100644 --- a/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/screens/CheckOwner/index.tsx +++ b/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/screens/CheckOwner/index.tsx @@ -4,8 +4,6 @@ import Close from '@material-ui/icons/Close' import classNames from 'classnames/bind' import React from 'react' -import { styles } from './style' - import CopyBtn from 'src/components/CopyBtn' import EtherscanBtn from 'src/components/EtherscanBtn' import Identicon from 'src/components/Identicon' @@ -16,6 +14,8 @@ import Hairline from 'src/components/layout/Hairline' import Paragraph from 'src/components/layout/Paragraph' import Row from 'src/components/layout/Row' +import { styles } from './style' + export const REMOVE_OWNER_MODAL_NEXT_BTN_TEST_ID = 'remove-owner-next-btn' const CheckOwner = ({ classes, onClose, onSubmit, ownerAddress, ownerName }) => { @@ -53,7 +53,7 @@ const CheckOwner = ({ classes, onClose, onSubmit, ownerAddress, ownerName }) => {ownerAddress} - + diff --git a/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/screens/Review/index.tsx b/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/screens/Review/index.tsx index 8328f939..d7da610a 100644 --- a/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/screens/Review/index.tsx +++ b/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/screens/Review/index.tsx @@ -4,9 +4,8 @@ import Close from '@material-ui/icons/Close' import classNames from 'classnames' import React, { useEffect, useState } from 'react' import { useSelector } from 'react-redux' - -import { styles } from './style' - +import { fromTokenUnit } from 'src/logic/tokens/utils/humanReadableValue' +import { getNetworkInfo } from 'src/config' import CopyBtn from 'src/components/CopyBtn' import EtherscanBtn from 'src/components/EtherscanBtn' import Identicon from 'src/components/Identicon' @@ -16,34 +15,34 @@ import Col from 'src/components/layout/Col' import Hairline from 'src/components/layout/Hairline' import Paragraph from 'src/components/layout/Paragraph' import Row from 'src/components/layout/Row' -import { SENTINEL_ADDRESS, getGnosisSafeInstanceAt } from 'src/logic/contracts/safeContracts' -import { estimateTxGasCosts } from 'src/logic/safe/transactions/gasNew' -import { formatAmount } from 'src/logic/tokens/utils/formatAmount' -import { getWeb3 } from 'src/logic/wallets/getWeb3' +import { getGnosisSafeInstanceAt, SENTINEL_ADDRESS } from 'src/logic/contracts/safeContracts' import { safeNameSelector, safeOwnersSelector, safeParamAddressFromStateSelector } from 'src/logic/safe/store/selectors' +import { estimateTxGasCosts } from 'src/logic/safe/transactions/gas' +import { formatAmount } from 'src/logic/tokens/utils/formatAmount' + +import { styles } from './style' export const REMOVE_OWNER_REVIEW_BTN_TEST_ID = 'remove-owner-review-btn' +const { nativeCoin } = getNetworkInfo() + const ReviewRemoveOwner = ({ classes, onClickBack, onClose, onSubmit, ownerAddress, ownerName, values }) => { const [gasCosts, setGasCosts] = useState('< 0.001') const safeAddress = useSelector(safeParamAddressFromStateSelector) as string const safeName = useSelector(safeNameSelector) const owners = useSelector(safeOwnersSelector) - useEffect(() => { let isCurrent = true const estimateGas = async () => { - const web3 = getWeb3() - const { fromWei, toBN } = web3.utils const gnosisSafe = await getGnosisSafeInstanceAt(safeAddress) const safeOwners = await gnosisSafe.methods.getOwners().call() const index = safeOwners.findIndex((owner) => owner.toLowerCase() === ownerAddress.toLowerCase()) const prevAddress = index === 0 ? SENTINEL_ADDRESS : safeOwners[index - 1] const txData = gnosisSafe.methods.removeOwner(prevAddress, ownerAddress, values.threshold).encodeABI() const estimatedGasCosts = await estimateTxGasCosts(safeAddress, safeAddress, txData) - const gasCostsAsEth = fromWei(toBN(estimatedGasCosts), 'ether') - const formattedGasCosts = formatAmount(gasCostsAsEth) + const gasCosts = fromTokenUnit(estimatedGasCosts, nativeCoin.decimals) + const formattedGasCosts = formatAmount(gasCosts) if (isCurrent) { setGasCosts(formattedGasCosts) @@ -120,7 +119,7 @@ const ReviewRemoveOwner = ({ classes, onClickBack, onClose, onSubmit, ownerAddre {owner.address} - + @@ -149,7 +148,7 @@ const ReviewRemoveOwner = ({ classes, onClickBack, onClose, onSubmit, ownerAddre {ownerAddress} - + @@ -163,7 +162,7 @@ const ReviewRemoveOwner = ({ classes, onClickBack, onClose, onSubmit, ownerAddre You're about to create a transaction and will have to confirm it with your currently connected wallet.
- {`Make sure you have ${gasCosts} (fee price) ETH in this wallet to fund this confirmation.`} + {`Make sure you have ${gasCosts} (fee price) ${nativeCoin.name} in this wallet to fund this confirmation.`}
diff --git a/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.tsx b/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.tsx index 8b743074..122a20a0 100644 --- a/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.tsx +++ b/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.tsx @@ -1,5 +1,4 @@ -import { withStyles } from '@material-ui/core/styles' -import { withSnackbar } from 'notistack' +import { createStyles, makeStyles } from '@material-ui/core/styles' import React, { useEffect, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' @@ -15,8 +14,10 @@ import replaceSafeOwner from 'src/logic/safe/store/actions/replaceSafeOwner' import { safeParamAddressFromStateSelector, safeThresholdSelector } from 'src/logic/safe/store/selectors' import { checksumAddress } from 'src/utils/checksumAddress' import { makeAddressBookEntry } from 'src/logic/addressBook/model/addressBook' +import { sameAddress } from 'src/logic/wallets/ethAddresses' +import { Dispatch } from 'src/logic/safe/store/actions/types' -const styles = () => ({ +const styles = createStyles({ biggerModalWindow: { width: '775px', minHeight: '500px', @@ -24,20 +25,24 @@ const styles = () => ({ }, }) +const useStyles = makeStyles(styles) + +type OwnerValues = { + ownerAddress: string + ownerName: string + threshold: string +} + export const sendReplaceOwner = async ( - values, - safeAddress, - ownerAddressToRemove, - enqueueSnackbar, - closeSnackbar, - threshold, - dispatch, -) => { + values: OwnerValues, + safeAddress: string, + ownerAddressToRemove: string, + dispatch: Dispatch, + threshold?: number, +): Promise => { const gnosisSafe = await getGnosisSafeInstanceAt(safeAddress) const safeOwners = await gnosisSafe.methods.getOwners().call() - const index = safeOwners.findIndex( - (ownerAddress) => ownerAddress.toLowerCase() === ownerAddressToRemove.toLowerCase(), - ) + const index = safeOwners.findIndex((ownerAddress) => sameAddress(ownerAddress, ownerAddressToRemove)) const prevAddress = index === 0 ? SENTINEL_ADDRESS : safeOwners[index - 1] const txData = gnosisSafe.methods.swapOwner(prevAddress, ownerAddressToRemove, values.ownerAddress).encodeABI() @@ -48,9 +53,7 @@ export const sendReplaceOwner = async ( valueInWei: '0', txData, notifiedTransaction: TX_NOTIFICATION_TYPES.SETTINGS_CHANGE_TX, - enqueueSnackbar, - closeSnackbar, - } as any), + }), ) if (txHash && threshold === 1) { @@ -65,7 +68,15 @@ export const sendReplaceOwner = async ( } } -const ReplaceOwner = ({ classes, closeSnackbar, enqueueSnackbar, isOpen, onClose, ownerAddress, ownerName }) => { +type ReplaceOwnerProps = { + isOpen: boolean + onClose: () => void + ownerAddress: string + ownerName: string +} + +const ReplaceOwner = ({ isOpen, onClose, ownerAddress, ownerName }: ReplaceOwnerProps): React.ReactElement => { + const classes = useStyles() const [activeScreen, setActiveScreen] = useState('checkOwner') const [values, setValues] = useState({}) const dispatch = useDispatch() @@ -94,7 +105,7 @@ const ReplaceOwner = ({ classes, closeSnackbar, enqueueSnackbar, isOpen, onClose const onReplaceOwner = async () => { onClose() try { - await sendReplaceOwner(values, safeAddress, ownerAddress, enqueueSnackbar, closeSnackbar, threshold, dispatch) + await sendReplaceOwner(values, safeAddress, ownerAddress, dispatch, threshold) dispatch( addOrUpdateAddressBookEntry(makeAddressBookEntry({ address: values.ownerAddress, name: values.ownerName })), @@ -131,4 +142,4 @@ const ReplaceOwner = ({ classes, closeSnackbar, enqueueSnackbar, isOpen, onClose ) } -export default withStyles(styles as any)(withSnackbar(ReplaceOwner)) +export default ReplaceOwner diff --git a/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/screens/OwnerForm/index.tsx b/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/screens/OwnerForm/index.tsx index c8ce72bf..c808f411 100644 --- a/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/screens/OwnerForm/index.tsx +++ b/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/screens/OwnerForm/index.tsx @@ -5,25 +5,25 @@ import classNames from 'classnames/bind' import React from 'react' import { useSelector } from 'react-redux' -import { styles } from './style' - import CopyBtn from 'src/components/CopyBtn' import EtherscanBtn from 'src/components/EtherscanBtn' -import Identicon from 'src/components/Identicon' -import { ScanQRWrapper } from 'src/components/ScanQRModal/ScanQRWrapper' import AddressInput from 'src/components/forms/AddressInput' import Field from 'src/components/forms/Field' import GnoForm from 'src/components/forms/GnoForm' import TextField from 'src/components/forms/TextField' import { composeValidators, minMaxLength, required, uniqueAddress } from 'src/components/forms/validator' +import Identicon from 'src/components/Identicon' import Block from 'src/components/layout/Block' import Button from 'src/components/layout/Button' import Col from 'src/components/layout/Col' import Hairline from 'src/components/layout/Hairline' import Paragraph from 'src/components/layout/Paragraph' import Row from 'src/components/layout/Row' +import { ScanQRWrapper } from 'src/components/ScanQRModal/ScanQRWrapper' import { safeOwnersSelector } from 'src/logic/safe/store/selectors' +import { styles } from './style' + export const REPLACE_OWNER_NAME_INPUT_TEST_ID = 'replace-owner-name-input' export const REPLACE_OWNER_ADDRESS_INPUT_TEST_ID = 'replace-owner-address-testid' export const REPLACE_OWNER_NEXT_BTN_TEST_ID = 'replace-owner-next-btn' @@ -94,7 +94,7 @@ const OwnerForm = ({ classes, onClose, onSubmit, ownerAddress, ownerName }) => { {ownerAddress} - + diff --git a/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/screens/Review/index.tsx b/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/screens/Review/index.tsx index 80939f21..0611c275 100644 --- a/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/screens/Review/index.tsx +++ b/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/screens/Review/index.tsx @@ -4,9 +4,8 @@ import Close from '@material-ui/icons/Close' import classNames from 'classnames' import React, { useEffect, useState } from 'react' import { useSelector } from 'react-redux' - -import { styles } from './style' - +import { fromTokenUnit } from 'src/logic/tokens/utils/humanReadableValue' +import { getNetworkInfo } from 'src/config' import CopyBtn from 'src/components/CopyBtn' import EtherscanBtn from 'src/components/EtherscanBtn' import Identicon from 'src/components/Identicon' @@ -16,19 +15,22 @@ import Col from 'src/components/layout/Col' import Hairline from 'src/components/layout/Hairline' import Paragraph from 'src/components/layout/Paragraph' import Row from 'src/components/layout/Row' -import { SENTINEL_ADDRESS, getGnosisSafeInstanceAt } from 'src/logic/contracts/safeContracts' -import { estimateTxGasCosts } from 'src/logic/safe/transactions/gasNew' -import { formatAmount } from 'src/logic/tokens/utils/formatAmount' -import { getWeb3 } from 'src/logic/wallets/getWeb3' +import { getGnosisSafeInstanceAt, SENTINEL_ADDRESS } from 'src/logic/contracts/safeContracts' import { safeNameSelector, safeOwnersSelector, safeParamAddressFromStateSelector, safeThresholdSelector, } from 'src/logic/safe/store/selectors' +import { estimateTxGasCosts } from 'src/logic/safe/transactions/gas' +import { formatAmount } from 'src/logic/tokens/utils/formatAmount' + +import { styles } from './style' export const REPLACE_OWNER_SUBMIT_BTN_TEST_ID = 'replace-owner-submit-btn' +const { nativeCoin } = getNetworkInfo() + const ReviewRemoveOwner = ({ classes, onClickBack, onClose, onSubmit, ownerAddress, ownerName, values }) => { const [gasCosts, setGasCosts] = useState('< 0.001') const safeAddress = useSelector(safeParamAddressFromStateSelector) as string @@ -39,16 +41,14 @@ const ReviewRemoveOwner = ({ classes, onClickBack, onClose, onSubmit, ownerAddre useEffect(() => { let isCurrent = true const estimateGas = async () => { - const web3 = getWeb3() - const { fromWei, toBN } = web3.utils const gnosisSafe = await getGnosisSafeInstanceAt(safeAddress) const safeOwners = await gnosisSafe.methods.getOwners().call() const index = safeOwners.findIndex((owner) => owner.toLowerCase() === ownerAddress.toLowerCase()) const prevAddress = index === 0 ? SENTINEL_ADDRESS : safeOwners[index - 1] const txData = gnosisSafe.methods.swapOwner(prevAddress, ownerAddress, values.ownerAddress).encodeABI() const estimatedGasCosts = await estimateTxGasCosts(safeAddress, safeAddress, txData) - const gasCostsAsEth = fromWei(toBN(estimatedGasCosts), 'ether') - const formattedGasCosts = formatAmount(gasCostsAsEth) + const gasCosts = fromTokenUnit(estimatedGasCosts, nativeCoin.decimals) + const formattedGasCosts = formatAmount(gasCosts) if (isCurrent) { setGasCosts(formattedGasCosts) } @@ -124,7 +124,7 @@ const ReviewRemoveOwner = ({ classes, onClickBack, onClose, onSubmit, ownerAddre {owner.address} - + @@ -153,7 +153,7 @@ const ReviewRemoveOwner = ({ classes, onClickBack, onClose, onSubmit, ownerAddre {ownerAddress} - + @@ -178,7 +178,7 @@ const ReviewRemoveOwner = ({ classes, onClickBack, onClose, onSubmit, ownerAddre {values.ownerAddress} - + @@ -192,7 +192,7 @@ const ReviewRemoveOwner = ({ classes, onClickBack, onClose, onSubmit, ownerAddre You're about to create a transaction and will have to confirm it with your currently connected wallet.
- {`Make sure you have ${gasCosts} (fee price) ETH in this wallet to fund this confirmation.`} + {`Make sure you have ${gasCosts} (fee price) ${nativeCoin.name} in this wallet to fund this confirmation.`}
diff --git a/src/routes/safe/components/Settings/RemoveSafeModal/index.tsx b/src/routes/safe/components/Settings/RemoveSafeModal/index.tsx index e301c1b0..5524ecd3 100644 --- a/src/routes/safe/components/Settings/RemoveSafeModal/index.tsx +++ b/src/routes/safe/components/Settings/RemoveSafeModal/index.tsx @@ -5,6 +5,7 @@ import OpenInNew from '@material-ui/icons/OpenInNew' import classNames from 'classnames' import React from 'react' import { useDispatch, useSelector } from 'react-redux' +import { getExplorerInfo } from 'src/config' import { styles } from './style' @@ -17,7 +18,6 @@ import Hairline from 'src/components/layout/Hairline' import Link from 'src/components/layout/Link' import Paragraph from 'src/components/layout/Paragraph' import Row from 'src/components/layout/Row' -import { getEtherScanLink } from 'src/logic/wallets/getWeb3' import removeSafe from 'src/logic/safe/store/actions/removeSafe' import { safeNameSelector, safeParamAddressFromStateSelector } from 'src/logic/safe/store/selectors' import { md, secondary } from 'src/theme/variables' @@ -34,7 +34,8 @@ const RemoveSafeComponent = ({ isOpen, onClose }) => { const safeAddress = useSelector(safeParamAddressFromStateSelector) as string const safeName = useSelector(safeNameSelector) const dispatch = useDispatch() - const etherScanLink = getEtherScanLink('address', safeAddress) + const explorerInfo = getExplorerInfo(safeAddress) + const { url } = explorerInfo() return ( { {safeAddress} - + diff --git a/src/routes/safe/components/Settings/ThresholdSettings/ChangeThreshold/index.tsx b/src/routes/safe/components/Settings/ThresholdSettings/ChangeThreshold/index.tsx index e821d4d3..58fb82e3 100644 --- a/src/routes/safe/components/Settings/ThresholdSettings/ChangeThreshold/index.tsx +++ b/src/routes/safe/components/Settings/ThresholdSettings/ChangeThreshold/index.tsx @@ -3,7 +3,8 @@ import MenuItem from '@material-ui/core/MenuItem' import { withStyles } from '@material-ui/core/styles' import Close from '@material-ui/icons/Close' import React, { useEffect, useState } from 'react' - +import { fromTokenUnit } from 'src/logic/tokens/utils/humanReadableValue' +import { getNetworkInfo } from 'src/config' import { styles } from './style' import Field from 'src/components/forms/Field' @@ -17,24 +18,23 @@ import Hairline from 'src/components/layout/Hairline' import Paragraph from 'src/components/layout/Paragraph' import Row from 'src/components/layout/Row' import { getGnosisSafeInstanceAt } from 'src/logic/contracts/safeContracts' -import { estimateTxGasCosts } from 'src/logic/safe/transactions/gasNew' +import { estimateTxGasCosts } from 'src/logic/safe/transactions/gas' import { formatAmount } from 'src/logic/tokens/utils/formatAmount' -import { getWeb3 } from 'src/logic/wallets/getWeb3' const THRESHOLD_FIELD_NAME = 'threshold' +const { nativeCoin } = getNetworkInfo() + const ChangeThreshold = ({ classes, onChangeThreshold, onClose, owners, safeAddress, threshold }) => { const [gasCosts, setGasCosts] = useState('< 0.001') useEffect(() => { let isCurrent = true const estimateGasCosts = async () => { - const web3 = getWeb3() - const { fromWei, toBN } = web3.utils const safeInstance = await getGnosisSafeInstanceAt(safeAddress) const txData = safeInstance.methods.changeThreshold('1').encodeABI() const estimatedGasCosts = await estimateTxGasCosts(safeAddress, safeAddress, txData) - const gasCostsAsEth = fromWei(toBN(estimatedGasCosts), 'ether') + const gasCostsAsEth = fromTokenUnit(estimatedGasCosts, nativeCoin.decimals) const formattedGasCosts = formatAmount(gasCostsAsEth) if (isCurrent) { setGasCosts(formattedGasCosts) @@ -105,7 +105,7 @@ const ChangeThreshold = ({ classes, onChangeThreshold, onClose, owners, safeAddr - {`You're about to create a transaction and will have to confirm it with your currently connected wallet. Make sure you have ${gasCosts} (fee price) ETH in this wallet to fund this confirmation.`} + {`You're about to create a transaction and will have to confirm it with your currently connected wallet. Make sure you have ${gasCosts} (fee price) ${nativeCoin.name} in this wallet to fund this confirmation.`} diff --git a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/ApproveTxModal/index.tsx b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/ApproveTxModal/index.tsx index e6eb22ee..7090aa74 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/ApproveTxModal/index.tsx +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/ApproveTxModal/index.tsx @@ -5,6 +5,8 @@ import { makeStyles } from '@material-ui/core/styles' import Close from '@material-ui/icons/Close' import React, { useEffect, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' +import { fromTokenUnit } from 'src/logic/tokens/utils/humanReadableValue' +import { getNetworkInfo } from 'src/config' import { styles } from './style' @@ -16,9 +18,8 @@ import Hairline from 'src/components/layout/Hairline' import Paragraph from 'src/components/layout/Paragraph' import Row from 'src/components/layout/Row' import { TX_NOTIFICATION_TYPES } from 'src/logic/safe/transactions' -import { estimateTxGasCosts } from 'src/logic/safe/transactions/gasNew' +import { estimateTxGasCosts } from 'src/logic/safe/transactions/gas' import { formatAmount } from 'src/logic/tokens/utils/formatAmount' -import { getWeb3 } from 'src/logic/wallets/getWeb3' import { userAccountSelector } from 'src/logic/wallets/store/selectors' import processTransaction from 'src/logic/safe/store/actions/processTransaction' @@ -61,6 +62,7 @@ type Props = { thresholdReached: boolean tx: Transaction } +const { nativeCoin } = getNetworkInfo() const ApproveTxModal = ({ canExecute, @@ -85,9 +87,6 @@ const ApproveTxModal = ({ let isCurrent = true const estimateGas = async () => { - const web3 = getWeb3() - const { fromWei, toBN } = web3.utils - const estimatedGasCosts = await estimateTxGasCosts( safeAddress, tx.recipient, @@ -95,8 +94,8 @@ const ApproveTxModal = ({ tx, approveAndExecute ? userAddress : undefined, ) - const gasCostsAsEth = fromWei(toBN(estimatedGasCosts), 'ether') - const formattedGasCosts = formatAmount(gasCostsAsEth) + const gasCosts = fromTokenUnit(estimatedGasCosts, nativeCoin.decimals) + const formattedGasCosts = formatAmount(gasCosts) if (isCurrent) { setGasCosts(formattedGasCosts) } @@ -164,7 +163,9 @@ const ApproveTxModal = ({ {`You're about to ${ approveAndExecute ? 'execute' : 'approve' - } a transaction and will have to confirm it with your currently connected wallet. Make sure you have ${gasCosts} (fee price) ETH in this wallet to fund this confirmation.`} + } a transaction and will have to confirm it with your currently connected wallet. Make sure you have ${gasCosts} (fee price) ${ + nativeCoin.name + } in this wallet to fund this confirmation.`} diff --git a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/CreationTx/index.tsx b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/CreationTx/index.tsx index d4e609b7..bae4e469 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/CreationTx/index.tsx +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/CreationTx/index.tsx @@ -1,14 +1,15 @@ import { makeStyles } from '@material-ui/core/styles' import React from 'react' import { EthHashInfo } from '@gnosis.pm/safe-react-components' -import { getNetwork } from 'src/config' import { Transaction } from 'src/logic/safe/store/models/types/transaction' + import { formatDate } from 'src/routes/safe/components/Transactions/TxsTable/columns' import Bold from 'src/components/layout/Bold' import Paragraph from 'src/components/layout/Paragraph' import Block from 'src/components/layout/Block' import { TransactionTypes } from 'src/logic/safe/store/models/types/transaction' +import { getExplorerInfo } from 'src/config' const useStyles = makeStyles({ address: { @@ -25,17 +26,19 @@ const useStyles = makeStyles({ }) type Props = { - tx: Transaction + tx?: Transaction } export const CreationTx = ({ tx }: Props): React.ReactElement | null => { const classes = useStyles() + const isCreationTx = tx?.type === TransactionTypes.CREATION - if (!tx) { + if (!tx || !isCreationTx) { return null } - - const isCreationTx = tx.type === TransactionTypes.CREATION + const explorerUrl = getExplorerInfo(tx.creator) + const scanBlockFactoryAddressUrl = getExplorerInfo(tx.factoryAddress) + const scanBlockMasterCopyUrl = getExplorerInfo(tx.masterCopy) return isCreationTx ? ( <> @@ -45,16 +48,12 @@ export const CreationTx = ({ tx }: Props): React.ReactElement | null => { Creator: - {tx.creator ? ( - - ) : ( - 'n/a' - )} + {tx.creator ? : 'n/a'} Factory: {tx.factoryAddress ? ( - + ) : ( 'n/a' )} @@ -62,7 +61,7 @@ export const CreationTx = ({ tx }: Props): React.ReactElement | null => { Mastercopy: {tx.masterCopy ? ( - + ) : ( 'n/a' )} diff --git a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/IncomingTxDescription/index.tsx b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/IncomingTxDescription/index.tsx index bab38466..532ce9ac 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/IncomingTxDescription/index.tsx +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/IncomingTxDescription/index.tsx @@ -28,7 +28,7 @@ const TransferDescription = ({ from, txFromName, value = '' }) => ( {txFromName ? ( ) : ( - + )} ) diff --git a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/OwnersColumn/OwnerComponent.tsx b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/OwnersColumn/OwnerComponent.tsx index 8ba79a83..06bbaec6 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/OwnersColumn/OwnerComponent.tsx +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/OwnersColumn/OwnerComponent.tsx @@ -3,7 +3,6 @@ import cn from 'classnames' import React from 'react' import { useSelector } from 'react-redux' import { EthHashInfo } from '@gnosis.pm/safe-react-components' -import { getNetwork } from 'src/config' import CancelSmallFilledCircle from './assets/cancel-small-filled.svg' import ConfirmSmallFilledCircle from './assets/confirm-small-filled.svg' @@ -18,6 +17,7 @@ import Button from 'src/components/layout/Button' import Img from 'src/components/layout/Img' import { getNameFromAddressBookSelector } from 'src/logic/addressBook/store/selectors' import { OwnersWithoutConfirmations } from './index' +import { getExplorerInfo } from 'src/config' export const CONFIRM_TX_BTN_TEST_ID = 'confirm-btn' export const EXECUTE_TX_BTN_TEST_ID = 'execute-btn' @@ -163,7 +163,7 @@ const OwnerComponent = (props: OwnerComponentProps): React.ReactElement => { ) } - + const explorerUrl = getExplorerInfo(owner) return (
{ shortenHash={4} showIdenticon showCopyBtn - showEtherscanBtn - network={getNetwork()} + explorerUrl={explorerUrl} /> {owner === userAddress && {isCancelTx ? rejectButton() : confirmButton()}} diff --git a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/OwnersColumn/index.tsx b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/OwnersColumn/index.tsx index ee580586..5fbf1262 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/OwnersColumn/index.tsx +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/OwnersColumn/index.tsx @@ -114,7 +114,6 @@ const OwnersColumn = ({ }: ownersColumnProps): React.ReactElement => { const classes = useStyles() let showOlderTxAnnotation - if (tx.isExecuted || cancelTx.isExecuted) { showOlderTxAnnotation = false } else { diff --git a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/RejectTxModal/index.tsx b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/RejectTxModal/index.tsx index e5372d4c..4d92a4d7 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/RejectTxModal/index.tsx +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/RejectTxModal/index.tsx @@ -3,6 +3,8 @@ import { makeStyles } from '@material-ui/core/styles' import Close from '@material-ui/icons/Close' import React, { useEffect, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' +import { fromTokenUnit } from 'src/logic/tokens/utils/humanReadableValue' +import { getNetworkInfo } from 'src/config' import { styles } from './style' @@ -14,10 +16,9 @@ import Hairline from 'src/components/layout/Hairline' import Paragraph from 'src/components/layout/Paragraph' import Row from 'src/components/layout/Row' import { TX_NOTIFICATION_TYPES } from 'src/logic/safe/transactions' -import { estimateTxGasCosts } from 'src/logic/safe/transactions/gasNew' +import { estimateTxGasCosts } from 'src/logic/safe/transactions/gas' import { formatAmount } from 'src/logic/tokens/utils/formatAmount' import { EMPTY_DATA } from 'src/logic/wallets/ethTransactions' -import { getWeb3 } from 'src/logic/wallets/getWeb3' import createTransaction from 'src/logic/safe/store/actions/createTransaction' import { safeParamAddressFromStateSelector } from 'src/logic/safe/store/selectors' @@ -31,6 +32,8 @@ type Props = { tx: Transaction } +const { nativeCoin } = getNetworkInfo() + const RejectTxModal = ({ isOpen, onClose, tx }: Props): React.ReactElement => { const [gasCosts, setGasCosts] = useState('< 0.001') const dispatch = useDispatch() @@ -40,12 +43,9 @@ const RejectTxModal = ({ isOpen, onClose, tx }: Props): React.ReactElement => { useEffect(() => { let isCurrent = true const estimateGasCosts = async () => { - const web3 = getWeb3() - const { fromWei, toBN } = web3.utils - const estimatedGasCosts = await estimateTxGasCosts(safeAddress, safeAddress, EMPTY_DATA) - const gasCostsAsEth = fromWei(toBN(estimatedGasCosts), 'ether') - const formattedGasCosts = formatAmount(gasCostsAsEth) + const gasCosts = fromTokenUnit(estimatedGasCosts, nativeCoin.decimals) + const formattedGasCosts = formatAmount(gasCosts) if (isCurrent) { setGasCosts(formattedGasCosts) } @@ -96,7 +96,7 @@ const RejectTxModal = ({ isOpen, onClose, tx }: Props): React.ReactElement => { - {`You're about to create a transaction and will have to confirm it with your currently connected wallet. Make sure you have ${gasCosts} (fee price) ETH in this wallet to fund this confirmation.`} + {`You're about to create a transaction and will have to confirm it with your currently connected wallet. Make sure you have ${gasCosts} (fee price) ${nativeCoin.name} in this wallet to fund this confirmation.`} diff --git a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/CustomDescription.tsx b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/CustomDescription.tsx index 0ed87bec..cf73ed8f 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/CustomDescription.tsx +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/CustomDescription.tsx @@ -1,6 +1,7 @@ import { IconText, Text, EthHashInfo } from '@gnosis.pm/safe-react-components' import { makeStyles } from '@material-ui/core/styles' import React from 'react' + import styled from 'styled-components' import { styles } from './styles' @@ -12,7 +13,7 @@ import { MultiSendDetails, } from 'src/routes/safe/store/actions/transactions/utils/multiSendDecodedDetails' import Bold from 'src/components/layout/Bold' -import { humanReadableValue } from 'src/logic/tokens/utils/humanReadableValue' +import { fromTokenUnit } from 'src/logic/tokens/utils/humanReadableValue' import Collapse from 'src/components/Collapse' import { useSelector } from 'react-redux' import { getNameFromAddressBookSelector } from 'src/logic/addressBook/store/selectors' @@ -23,7 +24,8 @@ import { Transaction } from 'src/logic/safe/store/models/types/transaction' import { DataDecoded } from 'src/routes/safe/store/models/types/transactions.d' import DividerLine from 'src/components/DividerLine' import { isArrayParameter } from 'src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/utils' -import { getNetwork } from 'src/config' + +import { getExplorerInfo, getNetworkInfo } from 'src/config' export const TRANSACTIONS_DESC_CUSTOM_VALUE_TEST_ID = 'tx-description-custom-value' export const TRANSACTIONS_DESC_CUSTOM_DATA_TEST_ID = 'tx-description-custom-data' @@ -55,6 +57,8 @@ const StyledMethodName = styled(Text)` white-space: nowrap; ` +const { nativeCoin } = getNetworkInfo() + const TxInfoDetails = ({ data }: { data: DataDecoded }): React.ReactElement => ( @@ -75,7 +79,7 @@ const TxInfoDetails = ({ data }: { data: DataDecoded }): React.ReactElement => ( const MultiSendCustomDataAction = ({ tx, order }: { tx: MultiSendDetails; order: number }): React.ReactElement => { const classes = useStyles() const methodName = tx.data?.method ? ` (${tx.data.method})` : '' - + const explorerUrl = getExplorerInfo(tx.to) return ( - Send {humanReadableValue(tx.value)} ETH to: - + + Send {fromTokenUnit(tx.value, nativeCoin.decimals)} {nativeCoin.name} to: + + {!!tx.data && } @@ -177,7 +183,7 @@ interface GenericCustomDataProps { const GenericCustomData = ({ amount = '0', data, recipient, storedTx }: GenericCustomDataProps): React.ReactElement => { const classes = useStyles() const recipientName = useSelector((state) => getNameFromAddressBookSelector(state, recipient)) - + const explorerUrl = getExplorerInfo(recipient) return ( @@ -188,8 +194,7 @@ const GenericCustomData = ({ amount = '0', data, recipient, storedTx }: GenericC name={recipientName === 'UNKNOWN' ? undefined : recipientName} showIdenticon showCopyBtn - showEtherscanBtn - network={getNetwork()} + explorerUrl={explorerUrl} /> diff --git a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/SettingsDescription.tsx b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/SettingsDescription.tsx index 596f3224..ccaf06fe 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/SettingsDescription.tsx +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/SettingsDescription.tsx @@ -1,12 +1,12 @@ -import { useSelector } from 'react-redux' import React from 'react' - -import { getNameFromAddressBookSelector } from 'src/logic/addressBook/store/selectors' +import { useSelector } from 'react-redux' +import EtherscanLink from 'src/components/EtherscanLink' import Block from 'src/components/layout/Block' import Bold from 'src/components/layout/Bold' -import OwnerAddressTableCell from 'src/routes/safe/components/Settings/ManageOwners/OwnerAddressTableCell' -import EtherscanLink from 'src/components/EtherscanLink' import Paragraph from 'src/components/layout/Paragraph' + +import { getNameFromAddressBookSelector } from 'src/logic/addressBook/store/selectors' +import OwnerAddressTableCell from 'src/routes/safe/components/Settings/ManageOwners/OwnerAddressTableCell' import { SAFE_METHODS_NAMES, SafeMethods } from 'src/routes/safe/store/models/types/transactions.d' export const TRANSACTIONS_DESC_ADD_OWNER_TEST_ID = 'tx-description-add-owner' @@ -29,7 +29,7 @@ const RemovedOwner = ({ removedOwner }: RemovedOwnerProps): React.ReactElement = {ownerChangedName ? ( ) : ( - + )} ) @@ -48,7 +48,7 @@ const AddedOwner = ({ addedOwner }: AddedOwnerProps): React.ReactElement => { {ownerChangedName ? ( ) : ( - + )} ) @@ -74,7 +74,7 @@ interface AddModuleProps { const AddModule = ({ module }: AddModuleProps): React.ReactElement => ( Add module: - + ) @@ -85,7 +85,7 @@ interface RemoveModuleProps { const RemoveModule = ({ module }: RemoveModuleProps): React.ReactElement => ( Remove module: - + ) diff --git a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/TransferDescription.tsx b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/TransferDescription.tsx index 4fc0be97..afc5f2c1 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/TransferDescription.tsx +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/TransferDescription.tsx @@ -1,12 +1,12 @@ import React from 'react' import { useSelector } from 'react-redux' - -import { TRANSACTIONS_DESC_SEND_TEST_ID } from './index' -import { getNameFromAddressBookSelector } from 'src/logic/addressBook/store/selectors' +import EtherscanLink from 'src/components/EtherscanLink' import Block from 'src/components/layout/Block' import Bold from 'src/components/layout/Bold' +import { getNameFromAddressBookSelector } from 'src/logic/addressBook/store/selectors' import OwnerAddressTableCell from 'src/routes/safe/components/Settings/ManageOwners/OwnerAddressTableCell' -import EtherscanLink from 'src/components/EtherscanLink' + +import { TRANSACTIONS_DESC_SEND_TEST_ID } from './index' interface TransferDescriptionProps { amount: string @@ -21,7 +21,7 @@ const TransferDescription = ({ amount = '', recipient }: TransferDescriptionProp {recipientName ? ( ) : ( - + )} ) diff --git a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/Value.tsx b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/Value.tsx index 7a0108e2..9bc97b09 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/Value.tsx +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/Value.tsx @@ -2,11 +2,11 @@ import { Text, EthHashInfo } from '@gnosis.pm/safe-react-components' import React from 'react' import styled from 'styled-components' -import { getNetwork } from 'src/config' import { isAddress, isArrayParameter, } from 'src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/utils' +import { getExplorerInfo } from 'src/config' const NestedWrapper = styled.div` padding-left: 4px; @@ -50,10 +50,9 @@ const GenericValue = ({ method, type, value }: RenderValueProps): React.ReactEle } const Value = ({ type, ...props }: RenderValueProps): React.ReactElement => { + const explorerUrl = getExplorerInfo(props.value as string) if (isAddress(type)) { - return ( - - ) + return } return diff --git a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/index.tsx b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/index.tsx index 2bc2c2bb..728f05ce 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/index.tsx +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/index.tsx @@ -13,7 +13,6 @@ import { CreationTx } from './CreationTx' import { OutgoingTx } from './OutgoingTx' import { styles } from './style' -import { getNetwork } from 'src/config' import Block from 'src/components/layout/Block' import Bold from 'src/components/layout/Bold' import Col from 'src/components/layout/Col' @@ -26,6 +25,7 @@ import { INCOMING_TX_TYPES } from 'src/logic/safe/store/models/incomingTransacti import { safeNonceSelector, safeThresholdSelector } from 'src/logic/safe/store/selectors' import { Transaction, TransactionTypes } from 'src/logic/safe/store/models/types/transaction' import IncomingTxDescription from './IncomingTxDescription' +import { getExplorerInfo, getNetworkInfo } from 'src/config' const useStyles = makeStyles(styles as any) @@ -34,9 +34,10 @@ interface ExpandedTxProps { tx: Transaction } +const { nativeCoin } = getNetworkInfo() + const ExpandedTx = ({ cancelTx, tx }: ExpandedTxProps): React.ReactElement => { const { fromWei, toBN } = getWeb3().utils - const classes = useStyles() const nonce = useSelector(safeNonceSelector) const threshold = useSelector(safeThresholdSelector) as number @@ -59,6 +60,8 @@ const ExpandedTx = ({ cancelTx, tx }: ExpandedTxProps): React.ReactElement => { } } + const explorerUrl = tx.executionTxHash ? getExplorerInfo(tx.executionTxHash) : null + return ( <> @@ -68,13 +71,7 @@ const ExpandedTx = ({ cancelTx, tx }: ExpandedTxProps): React.ReactElement => {
Hash: {tx.executionTxHash ? ( - + ) : ( 'n/a' )} @@ -88,7 +85,7 @@ const ExpandedTx = ({ cancelTx, tx }: ExpandedTxProps): React.ReactElement => { {!isCreationTx ? ( Fee: - {tx.fee ? fromWei(toBN(tx.fee)) + ' ETH' : 'n/a'} + {tx.fee ? fromWei(toBN(tx.fee)) + ` ${nativeCoin.name}` : 'n/a'} ) : null} diff --git a/src/routes/safe/container/index.tsx b/src/routes/safe/container/index.tsx index 2ca98cbf..d90de961 100644 --- a/src/routes/safe/container/index.tsx +++ b/src/routes/safe/container/index.tsx @@ -1,13 +1,15 @@ +import { GenericModal } from '@gnosis.pm/safe-react-components' import React, { useState } from 'react' import { useSelector } from 'react-redux' import { Redirect, Route, Switch, useRouteMatch } from 'react-router-dom' -import { GenericModal } from '@gnosis.pm/safe-react-components' import NoSafe from 'src/components/NoSafe' import { providerNameSelector } from 'src/logic/wallets/store/selectors' -import { safeParamAddressFromStateSelector } from 'src/logic/safe/store/selectors' +import { safeFeaturesEnabledSelector, safeParamAddressFromStateSelector } from 'src/logic/safe/store/selectors' +import { AppReduxState } from 'src/store' import { wrapInSuspense } from 'src/utils/wrapInSuspense' import { SAFELIST_ADDRESS } from 'src/routes/routes' +import { FEATURES } from 'src/config/networks/network.d' export const BALANCES_TAB_BTN_TEST_ID = 'balances-tab-btn' export const SETTINGS_TAB_BTN_TEST_ID = 'settings-tab-btn' @@ -34,7 +36,18 @@ const Container = (): React.ReactElement => { const safeAddress = useSelector(safeParamAddressFromStateSelector) const provider = useSelector(providerNameSelector) + const featuresEnabled = useSelector( + safeFeaturesEnabledSelector, + (left, right) => { + if (Array.isArray(left) && Array.isArray(right)) { + return JSON.stringify(left) === JSON.stringify(right) + } + + return left === right + }, + ) const matchSafeWithAddress = useRouteMatch<{ safeAddress: string }>({ path: `${SAFELIST_ADDRESS}/:safeAddress` }) + const safeAppsEnabled = Boolean(featuresEnabled?.includes(FEATURES.SAFE_APPS)) if (!safeAddress) { return @@ -67,7 +80,17 @@ const Container = (): React.ReactElement => { path={`${matchSafeWithAddress?.path}/transactions`} render={() => wrapInSuspense(, null)} /> - wrapInSuspense(, null)} /> + { + if (!safeAppsEnabled) { + history.push(`${matchSafeWithAddress?.url}/balances`) + } + return wrapInSuspense(, null) + }} + /> + receipt.events?.ProxyCreation.returnValues.proxy) } export default aSafe diff --git a/src/utils/constants.ts b/src/utils/constants.ts index a21a6b6c..4a9e2bb0 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -1,16 +1,26 @@ -import { ETHEREUM_NETWORK } from 'src/logic/wallets/getWeb3' - -export const NETWORK = process.env.REACT_APP_NETWORK || ETHEREUM_NETWORK.RINKEBY -export const GOOGLE_ANALYTICS_ID_RINKEBY = process.env.REACT_APP_GOOGLE_ANALYTICS_ID_RINKEBY -export const GOOGLE_ANALYTICS_ID_MAINNET = process.env.REACT_APP_GOOGLE_ANALYTICS_ID_MAINNET -export const INTERCOM_ID = process.env.REACT_APP_INTERCOM_ID -export const PORTIS_ID = process.env.REACT_APP_PORTIS_ID -export const SQUARELINK_ID = process.env.REACT_APP_SQUARELINK_ID -export const FORTMATIC_KEY = process.env.REACT_APP_FORTMATIC_KEY +export const APP_ENV = process.env.REACT_APP_ENV +export const NODE_ENV = process.env.NODE_ENV +export const NETWORK = process.env.REACT_APP_NETWORK?.toUpperCase() || 'RINKEBY' +export const INTERCOM_ID = APP_ENV === 'production' ? process.env.REACT_APP_INTERCOM_ID : 'plssl1fl' +export const GOOGLE_ANALYTICS_ID = process.env.REACT_APP_GOOGLE_ANALYTICS || '' +export const PORTIS_ID = process.env.REACT_APP_PORTIS_ID ?? '852b763d-f28b-4463-80cb-846d7ec5806b' +export const FORTMATIC_KEY = process.env.REACT_APP_FORTMATIC_KEY ?? 'pk_test_CAD437AA29BE0A40' +export const BLOCKNATIVE_KEY = process.env.REACT_APP_BLOCKNATIVE_KEY ?? '7fbb9cee-7e97-4436-8770-8b29a9a8814c' +/* + * Not being used +export const SQUARELINK_ID = { + [ETHEREUM_NETWORK.RINKEBY]: '46ce08fe50913cfa1b78', + [ETHEREUM_NETWORK.MAINNET]: process.env.REACT_APP_SQUARELINK_ID, + [ETHEREUM_NETWORK.XDAI]: process.env.REACT_APP_SQUARELINK_ID, +} + */ export const INFURA_TOKEN = process.env.REACT_APP_INFURA_TOKEN || '' -export const LATEST_SAFE_VERSION = process.env.REACT_APP_LATEST_SAFE_VERSION || 'not-defined' +export const LATEST_SAFE_VERSION = process.env.REACT_APP_LATEST_SAFE_VERSION || '1.1.1' export const APP_VERSION = process.env.REACT_APP_APP_VERSION || 'not-defined' export const OPENSEA_API_KEY = process.env.REACT_APP_OPENSEA_API_KEY || '' -export const COLLECTIBLES_SOURCE = process.env.REACT_APP_COLLECTIBLES_SOURCE || 'OpenSea' +export const COLLECTIBLES_SOURCE = process.env.REACT_APP_COLLECTIBLES_SOURCE || 'Gnosis' export const TIMEOUT = process.env.NODE_ENV === 'test' ? 1500 : 5000 export const ETHERSCAN_API_KEY = process.env.REACT_APP_ETHERSCAN_API_KEY +export const EXCHANGE_RATE_URL = 'https://api.exchangeratesapi.io/latest' +export const EXCHANGE_RATE_URL_FALLBACK = 'https://api.coinbase.com/v2/exchange-rates' +export const IPFS_GATEWAY = process.env.REACT_APP_IPFS_GATEWAY diff --git a/src/utils/intercom.ts b/src/utils/intercom.ts index 6fb98cbf..68035e7d 100644 --- a/src/utils/intercom.ts +++ b/src/utils/intercom.ts @@ -1,8 +1,8 @@ -import { getIntercomId } from 'src/config' +import { INTERCOM_ID } from 'src/utils/constants' // eslint-disable-next-line consistent-return export const loadIntercom = () => { - const APP_ID = getIntercomId() + const APP_ID = INTERCOM_ID if (!APP_ID) { console.error('[Intercom] - In order to use Intercom you need to add an appID') return null diff --git a/src/utils/storage/index.ts b/src/utils/storage/index.ts index d2dff5b7..d9f7a133 100644 --- a/src/utils/storage/index.ts +++ b/src/utils/storage/index.ts @@ -1,6 +1,6 @@ import { ImmortalStorage, IndexedDbStore, LocalStorageStore } from 'immortal-db' -import { getNetwork } from 'src/config' +import { getNetworkName } from 'src/config' // Don't use sessionStorage and cookieStorage // https://github.com/gruns/ImmortalDB/issues/22 @@ -8,7 +8,7 @@ import { getNetwork } from 'src/config' const stores = [IndexedDbStore, LocalStorageStore] export const storage = new ImmortalStorage(stores) -const PREFIX = `v2_${getNetwork()}` +const PREFIX = `v2_${getNetworkName()}` export const loadFromStorage = async (key: string): Promise => { try { diff --git a/src/utils/strings.ts b/src/utils/strings.ts index ec142be7..0d2f86f1 100644 --- a/src/utils/strings.ts +++ b/src/utils/strings.ts @@ -44,3 +44,17 @@ export const textShortener = ({ charsEnd = 10, charsStart = 10, ellipsis = '...' * @returns {string} string without side whitespaces */ export const trimSpaces = (value: string): string => (value === undefined ? '' : value.trim()) + +/** + * Util to compare two strings, comparison is case insensitive + * @param str1 + * @param str2 + * @returns {boolean} + */ +export const sameString = (str1: string | undefined, str2: string | undefined): boolean => { + if (!str1 || !str2) { + return false + } + + return str1.toLowerCase() === str2.toLowerCase() +} diff --git a/yarn.lock b/yarn.lock index 6c515216..06f2f7f4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -28,14 +28,10 @@ dependencies: "@babel/highlight" "^7.10.4" -"@babel/compat-data@^7.10.4", "@babel/compat-data@^7.11.0", "@babel/compat-data@^7.9.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.11.0.tgz#e9f73efe09af1355b723a7f39b11bad637d7c99c" - integrity sha512-TPSvJfv73ng0pfnEOh17bYMPQbI95+nGWc71Ss4vZdRBHTDqmM9Z8ZV4rYz8Ks7sfzc95n30k6ODIq5UGnXcYQ== - dependencies: - browserslist "^4.12.0" - invariant "^2.2.4" - semver "^5.5.0" +"@babel/compat-data@^7.12.0", "@babel/compat-data@^7.9.0": + version "7.12.0" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.12.0.tgz#443aea07a5aeba7942cb067de6b8272f2ab36b9e" + integrity sha512-jAbCtMANC9ptXxbSVXIqV/3H0bkh7iyyv6JS5lu10av45bcc2QmDNJXkASZCFwbBt75Q0AEq/BB+bNa3x1QgYQ== "@babel/core@7.9.0": version "7.9.0" @@ -59,19 +55,19 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@^7.1.0", "@babel/core@^7.4.5": - version "7.11.1" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.11.1.tgz#2c55b604e73a40dc21b0e52650b11c65cf276643" - integrity sha512-XqF7F6FWQdKGGWAzGELL+aCO1p+lRY5Tj5/tbT3St1G8NaH70jhhDIKknIZaDans0OQBG5wRAldROLHSt44BgQ== +"@babel/core@^7.1.0", "@babel/core@^7.4.5", "@babel/core@^7.7.5": + version "7.12.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.0.tgz#e42e07a086e978cdd4c61f4078d8230fb817cc86" + integrity sha512-iV7Gwg0DePKvdDZZWRTkj4MW+6/AbVWd4ZCg+zk8H1RVt5xBpUZS6vLQWwb3pyLg4BFTaGiQCPoJ4Ibmbne4fA== dependencies: "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.11.0" - "@babel/helper-module-transforms" "^7.11.0" + "@babel/generator" "^7.12.0" + "@babel/helper-module-transforms" "^7.12.0" "@babel/helpers" "^7.10.4" - "@babel/parser" "^7.11.1" + "@babel/parser" "^7.12.0" "@babel/template" "^7.10.4" - "@babel/traverse" "^7.11.0" - "@babel/types" "^7.11.0" + "@babel/traverse" "^7.12.0" + "@babel/types" "^7.12.0" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.1" @@ -81,34 +77,12 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@^7.7.5": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.11.0.tgz#73b9c33f1658506887f767c26dae07798b30df76" - integrity sha512-mkLq8nwaXmDtFmRkQ8ED/eA2CnVw4zr7dCztKalZXBvdK5EeNUAesrrwUqjQEzFgomJssayzB0aqlOsP1vGLqg== +"@babel/generator@^7.12.0", "@babel/generator@^7.4.0", "@babel/generator@^7.9.0": + version "7.12.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.0.tgz#91a45f1c18ca8d895a35a04da1a4cf7ea3f37f98" + integrity sha512-8lnf4QcyiQMf5XQp47BltuMTocsOh6P0z/vueEh8GzhmWWlDbdvOoI5Ziddg0XYhmnx35HyByUW51/9NprF8cA== dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.11.0" - "@babel/helper-module-transforms" "^7.11.0" - "@babel/helpers" "^7.10.4" - "@babel/parser" "^7.11.0" - "@babel/template" "^7.10.4" - "@babel/traverse" "^7.11.0" - "@babel/types" "^7.11.0" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.1" - json5 "^2.1.2" - lodash "^4.17.19" - resolve "^1.3.2" - semver "^5.4.1" - source-map "^0.5.0" - -"@babel/generator@^7.11.0", "@babel/generator@^7.4.0", "@babel/generator@^7.9.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.11.0.tgz#4b90c78d8c12825024568cbe83ee6c9af193585c" - integrity sha512-fEm3Uzw7Mc9Xi//qU20cBKatTfs2aOtKqmvy/Vm7RkJEGFQ4xc9myCfbXxqK//ZS8MR/ciOHw6meGASJuKmDfQ== - dependencies: - "@babel/types" "^7.11.0" + "@babel/types" "^7.12.0" jsesc "^2.5.1" source-map "^0.5.0" @@ -127,14 +101,14 @@ "@babel/helper-explode-assignable-expression" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/helper-builder-react-jsx-experimental@^7.10.4": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.10.5.tgz#f35e956a19955ff08c1258e44a515a6d6248646b" - integrity sha512-Buewnx6M4ttG+NLkKyt7baQn7ScC/Td+e99G914fRU8fGIUivDDgVIQeDHFa5e4CRSJQt58WpNHhsAZgtzVhsg== +"@babel/helper-builder-react-jsx-experimental@^7.10.4", "@babel/helper-builder-react-jsx-experimental@^7.11.5": + version "7.12.0" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.12.0.tgz#e8655888d0d36fd2a15c02decf77923fc18e95cd" + integrity sha512-AFzu6ib4i56olCtulkbIifcTay0O5tv8ZVK8hZMzrpu+YjsIDEcesF1DMqqTzV65clu3X61aE7qeHcJsY/gmnA== dependencies: "@babel/helper-annotate-as-pure" "^7.10.4" "@babel/helper-module-imports" "^7.10.4" - "@babel/types" "^7.10.5" + "@babel/types" "^7.12.0" "@babel/helper-builder-react-jsx@^7.10.4": version "7.10.4" @@ -144,37 +118,36 @@ "@babel/helper-annotate-as-pure" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/helper-compilation-targets@^7.10.4", "@babel/helper-compilation-targets@^7.8.7": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.4.tgz#804ae8e3f04376607cc791b9d47d540276332bd2" - integrity sha512-a3rYhlsGV0UHNDvrtOXBg8/OpfV0OKTkxKPzIplS1zpx7CygDcWWxckxZeDd3gzPzC4kUT0A4nVFDK0wGMh4MQ== +"@babel/helper-compilation-targets@^7.12.0", "@babel/helper-compilation-targets@^7.8.7": + version "7.12.0" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.0.tgz#c477d89a1f4d626c8149b9b88802f78d66d0c99a" + integrity sha512-NbDFJNjDgxE7IkrHp5gq2+Tr8bEdCLKYN90YDQEjMiTMUAFAcShNkaH8kydcmU0mEQTiQY0Ydy/+1xfS2OCEnw== dependencies: - "@babel/compat-data" "^7.10.4" + "@babel/compat-data" "^7.12.0" + "@babel/helper-validator-option" "^7.12.0" browserslist "^4.12.0" - invariant "^2.2.4" - levenary "^1.1.1" semver "^5.5.0" -"@babel/helper-create-class-features-plugin@^7.10.4", "@babel/helper-create-class-features-plugin@^7.10.5", "@babel/helper-create-class-features-plugin@^7.8.3": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz#9f61446ba80e8240b0a5c85c6fdac8459d6f259d" - integrity sha512-0nkdeijB7VlZoLT3r/mY3bUkw3T8WG/hNw+FATs/6+pG2039IJWjTYL0VTISqsNHMUTEnwbVnc89WIJX9Qed0A== +"@babel/helper-create-class-features-plugin@^7.10.4", "@babel/helper-create-class-features-plugin@^7.12.0", "@babel/helper-create-class-features-plugin@^7.8.3": + version "7.12.0" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.0.tgz#f3f2fc77bacc89e59ce6764daeabc1fb23e79a05" + integrity sha512-9tD1r9RK928vxvxcoNK8/7uwT7Q2DJZP1dnJmyMAJPwOF0yr8PPwqdpyw33lUpCfrJ765bOs5XNa4KSfUDWFSw== dependencies: "@babel/helper-function-name" "^7.10.4" - "@babel/helper-member-expression-to-functions" "^7.10.5" + "@babel/helper-member-expression-to-functions" "^7.12.0" "@babel/helper-optimise-call-expression" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-replace-supers" "^7.12.0" "@babel/helper-split-export-declaration" "^7.10.4" "@babel/helper-create-regexp-features-plugin@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz#fdd60d88524659a0b6959c0579925e425714f3b8" - integrity sha512-2/hu58IEPKeoLF45DBwx3XFqsbCXmkdAay4spVr2x0jYgRxrSNp+ePwvSsy9g6YSaNDcKIQVPXk1Ov8S2edk2g== + version "7.12.0" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.0.tgz#858cef57039f3b3a9012273597288a71e1dff8ca" + integrity sha512-YBqH+3wLcom+tko8/JLgRcG8DMqORgmjqNRNI751gTioJSZHWFybO1mRoLtJtWIlYSHY+zT9LqqnbbK1c3KIVQ== dependencies: "@babel/helper-annotate-as-pure" "^7.10.4" "@babel/helper-regex" "^7.10.4" - regexpu-core "^4.7.0" + regexpu-core "^4.7.1" "@babel/helper-define-map@^7.10.4": version "7.10.5" @@ -215,12 +188,12 @@ dependencies: "@babel/types" "^7.10.4" -"@babel/helper-member-expression-to-functions@^7.10.4", "@babel/helper-member-expression-to-functions@^7.10.5": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz#ae69c83d84ee82f4b42f96e2a09410935a8f26df" - integrity sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q== +"@babel/helper-member-expression-to-functions@^7.12.0": + version "7.12.0" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.0.tgz#48f605fa801764f3e5b2e301e49d35fe1820c4f3" + integrity sha512-I0d/bgzgzgLsJMk7UZ0TN2KV3OGjC/t/9Saz8PKb9jrcEAXhgjGysOgp4PDKydIKjUv/gj2St4ae+ov8l+T9Xg== dependencies: - "@babel/types" "^7.11.0" + "@babel/types" "^7.12.0" "@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.10.4", "@babel/helper-module-imports@^7.8.3": version "7.10.4" @@ -229,17 +202,19 @@ dependencies: "@babel/types" "^7.10.4" -"@babel/helper-module-transforms@^7.10.4", "@babel/helper-module-transforms@^7.10.5", "@babel/helper-module-transforms@^7.11.0", "@babel/helper-module-transforms@^7.9.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz#b16f250229e47211abdd84b34b64737c2ab2d359" - integrity sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg== +"@babel/helper-module-transforms@^7.10.4", "@babel/helper-module-transforms@^7.10.5", "@babel/helper-module-transforms@^7.12.0", "@babel/helper-module-transforms@^7.9.0": + version "7.12.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.12.0.tgz#8ac7d9e8716f94549a42e577c5429391950e33f3" + integrity sha512-1ZTMoCiLSzTJLbq7mSaTHki4oIrBIf/dUbzdhwTrvtMU3ZNVKwQmGae3gSiqppo7G8HAgnXmc43rfEaD8yYLLQ== dependencies: "@babel/helper-module-imports" "^7.10.4" - "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-replace-supers" "^7.12.0" "@babel/helper-simple-access" "^7.10.4" "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/helper-validator-identifier" "^7.10.4" "@babel/template" "^7.10.4" - "@babel/types" "^7.11.0" + "@babel/traverse" "^7.12.0" + "@babel/types" "^7.12.0" lodash "^4.17.19" "@babel/helper-optimise-call-expression@^7.10.4": @@ -271,15 +246,15 @@ "@babel/template" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/helper-replace-supers@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz#d585cd9388ea06e6031e4cd44b6713cbead9e6cf" - integrity sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A== +"@babel/helper-replace-supers@^7.10.4", "@babel/helper-replace-supers@^7.12.0": + version "7.12.0" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.12.0.tgz#98d3f3eb779752e59c7422ab387c9b444323be60" + integrity sha512-9kycFdq2c9e7PXZOr2z/ZqTFF9OzFu287iFwYS+CiDVPuoTCfY8hoTsIqNQNetQjlqoRsRyJFrMG1uhGAR4EEw== dependencies: - "@babel/helper-member-expression-to-functions" "^7.10.4" + "@babel/helper-member-expression-to-functions" "^7.12.0" "@babel/helper-optimise-call-expression" "^7.10.4" - "@babel/traverse" "^7.10.4" - "@babel/types" "^7.10.4" + "@babel/traverse" "^7.12.0" + "@babel/types" "^7.12.0" "@babel/helper-simple-access@^7.10.4": version "7.10.4" @@ -308,6 +283,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== +"@babel/helper-validator-option@^7.12.0": + version "7.12.0" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.0.tgz#1d1fc48a9b69763da61b892774b0df89aee1c969" + integrity sha512-NRfKaAQw/JCMsTFUdJI6cp4MoJGGVBRQTRSiW1nwlGldNqzjB9jqWI0SZqQksC724dJoKqwG+QqfS9ib7SoVsw== + "@babel/helper-wrap-function@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz#8a6f701eab0ff39f765b5a1cfef409990e624b87" @@ -336,15 +316,10 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.10.4", "@babel/parser@^7.11.1", "@babel/parser@^7.4.3", "@babel/parser@^7.7.0", "@babel/parser@^7.9.0": - version "7.11.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.3.tgz#9e1eae46738bcd08e23e867bab43e7b95299a8f9" - integrity sha512-REo8xv7+sDxkKvoxEywIdsNFiZLybwdI7hcT5uEPyQrSMB4YQ973BfC9OOrD/81MaIjh6UxdulIQXkjmiH3PcA== - -"@babel/parser@^7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.0.tgz#a9d7e11aead25d3b422d17b2c6502c8dddef6a5d" - integrity sha512-qvRvi4oI8xii8NllyEc4MDJjuZiNaRzyb7Y7lup1NqJV8TZHF4O27CcP+72WPn/k1zkgJ6WJfnIbk4jTsVAZHw== +"@babel/parser@^7.1.0", "@babel/parser@^7.10.4", "@babel/parser@^7.12.0", "@babel/parser@^7.4.3", "@babel/parser@^7.7.0", "@babel/parser@^7.9.0": + version "7.12.0" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.0.tgz#2ad388f3960045b22f9b7d4bf85e80b15a1c9e3a" + integrity sha512-dYmySMYnlus2jwl7JnnajAj11obRStZoW9cG04wh4ZuhozDn11tDUrhHcUZ9iuNHqALAhh60XqNaYXpvuuE/Gg== "@babel/plugin-proposal-async-generator-functions@^7.10.4", "@babel/plugin-proposal-async-generator-functions@^7.8.3": version "7.10.5" @@ -388,10 +363,10 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-dynamic-import" "^7.8.0" -"@babel/plugin-proposal-export-namespace-from@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.10.4.tgz#570d883b91031637b3e2958eea3c438e62c05f54" - integrity sha512-aNdf0LY6/3WXkhh0Fdb6Zk9j1NMD8ovj3F6r0+3j837Pn1S1PdNtcwJ5EG9WkVPNHPxyJDaxMaAOVq4eki0qbg== +"@babel/plugin-proposal-export-namespace-from@^7.12.0": + version "7.12.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.12.0.tgz#08b0f8100bbae1199a5f5294f38a1b0b8d8402fc" + integrity sha512-ao43U2ptSe+mIZAQo2nBV5Wx2Ie3i2XbLt8jCXZpv+bvLY1Twv0lak4YZ1Ps5OwbeLMAl3iOVScgGMOImBae1g== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" @@ -404,10 +379,10 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-json-strings" "^7.8.0" -"@babel/plugin-proposal-logical-assignment-operators@^7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.11.0.tgz#9f80e482c03083c87125dee10026b58527ea20c8" - integrity sha512-/f8p4z+Auz0Uaf+i8Ekf1iM7wUNLcViFUGiPxKeXvxTSl63B875YPiVdUDdem7hREcI0E0kSpEhS8tF5RphK7Q== +"@babel/plugin-proposal-logical-assignment-operators@^7.12.0": + version "7.12.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.12.0.tgz#830d8ff4984d800b2824e8eac0005ecb7430328e" + integrity sha512-dssjXHzdMQal4q6GCSwDTVPEbyBLdd9+7aSlzAkQbrGEKq5xG8pvhQ7u2ktUrCLRmzQphZnSzILBL5ta4xSRlA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" @@ -420,10 +395,10 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" -"@babel/plugin-proposal-nullish-coalescing-operator@^7.10.4", "@babel/plugin-proposal-nullish-coalescing-operator@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz#02a7e961fc32e6d5b2db0649e01bf80ddee7e04a" - integrity sha512-wq5n1M3ZUlHl9sqT2ok1T2/MTt6AXE0e1Lz4WzWBr95LsAZ5qDXe4KnFuauYyEyLiohvXFMdbsOTMyLZs91Zlw== +"@babel/plugin-proposal-nullish-coalescing-operator@^7.12.0", "@babel/plugin-proposal-nullish-coalescing-operator@^7.8.3": + version "7.12.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.12.0.tgz#d82174a531305df4d7079ce3782269b35b810b82" + integrity sha512-JpNWix2VP2ue31r72fKytTE13nPX1fxl1mudfTaTwcDhl3iExz5NZjQBq012b/BQ6URWoc/onI73pZdYlAfihg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" @@ -436,10 +411,10 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-numeric-separator" "^7.8.3" -"@babel/plugin-proposal-numeric-separator@^7.10.4", "@babel/plugin-proposal-numeric-separator@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.4.tgz#ce1590ff0a65ad12970a609d78855e9a4c1aef06" - integrity sha512-73/G7QoRoeNkLZFxsoCCvlg4ezE4eM+57PnOqgaPOozd5myfj7p0muD1mRVJvbUWbOzD+q3No2bWbaKy+DJ8DA== +"@babel/plugin-proposal-numeric-separator@^7.12.0", "@babel/plugin-proposal-numeric-separator@^7.8.3": + version "7.12.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.0.tgz#76de244152abaf2e72800ab0aebc9771f6de3e9a" + integrity sha512-iON65YmIy/IpEgteYJ4HfO2q30SLdIxiyjNNlsSjSl0tUxLhSH9PljE5r6sczwdW64ZZzznYNcezdcROB+rDDw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-numeric-separator" "^7.10.4" @@ -469,10 +444,10 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-optional-chaining" "^7.8.0" -"@babel/plugin-proposal-optional-chaining@^7.11.0", "@babel/plugin-proposal-optional-chaining@^7.9.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.11.0.tgz#de5866d0646f6afdaab8a566382fe3a221755076" - integrity sha512-v9fZIu3Y8562RRwhm1BbMRxtqZNFmFA2EG+pT2diuU8PT3H6T/KXoZ54KgYisfOFZHV6PfvAiBIZ9Rcz+/JCxA== +"@babel/plugin-proposal-optional-chaining@^7.12.0", "@babel/plugin-proposal-optional-chaining@^7.9.0": + version "7.12.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.0.tgz#0159b549f165016fc9f284b8607a58a37a3b71fe" + integrity sha512-CXu9aw32FH/MksqdKvhpiH8pSvxnXJ33E7I7BGNE9VzNRpWgpNzvPpds/tW9E0pjmX9+D1zAHRyHbtyeTboo2g== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/helper-skip-transparent-expression-wrappers" "^7.11.0" @@ -751,14 +726,15 @@ "@babel/helper-simple-access" "^7.10.4" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-systemjs@^7.10.4", "@babel/plugin-transform-modules-systemjs@^7.9.0": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.5.tgz#6270099c854066681bae9e05f87e1b9cadbe8c85" - integrity sha512-f4RLO/OL14/FP1AEbcsWMzpbUz6tssRaeQg11RH1BP/XnPpRoVwgeYViMFacnkaw4k4wjRSjn3ip1Uw9TaXuMw== +"@babel/plugin-transform-modules-systemjs@^7.12.0", "@babel/plugin-transform-modules-systemjs@^7.9.0": + version "7.12.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.12.0.tgz#bca842db6980cfc98ae7d0f2c907c9b1df3f874e" + integrity sha512-h2fDMnwRwBiNMmTGAWqUo404Z3oLbrPE6hyATecyIbsEsrbM5gjLbfKQLb6hjiouMlGHH+yliYBbc4NPgWKE/g== dependencies: "@babel/helper-hoist-variables" "^7.10.4" - "@babel/helper-module-transforms" "^7.10.5" + "@babel/helper-module-transforms" "^7.12.0" "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-validator-identifier" "^7.10.4" babel-plugin-dynamic-import-node "^2.3.3" "@babel/plugin-transform-modules-umd@^7.10.4", "@babel/plugin-transform-modules-umd@^7.9.0": @@ -828,11 +804,11 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-react-jsx-development@^7.10.4", "@babel/plugin-transform-react-jsx-development@^7.9.0": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.10.4.tgz#6ec90f244394604623880e15ebc3c34c356258ba" - integrity sha512-RM3ZAd1sU1iQ7rI2dhrZRZGv0aqzNQMbkIUCS1txYpi9wHQ2ZHNjo5TwX+UD6pvFW4AbWqLVYvKy5qJSAyRGjQ== + version "7.11.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.11.5.tgz#e1439e6a57ee3d43e9f54ace363fb29cefe5d7b6" + integrity sha512-cImAmIlKJ84sDmpQzm4/0q/2xrXlDezQoixy3qoz1NJeZL/8PRon6xZtluvr4H4FzwlDGI5tCcFupMnXGtr+qw== dependencies: - "@babel/helper-builder-react-jsx-experimental" "^7.10.4" + "@babel/helper-builder-react-jsx-experimental" "^7.11.5" "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-jsx" "^7.10.4" @@ -895,9 +871,9 @@ semver "^5.5.1" "@babel/plugin-transform-runtime@^7.5.5": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.11.0.tgz#e27f78eb36f19448636e05c33c90fd9ad9b8bccf" - integrity sha512-LFEsP+t3wkYBlis8w6/kmnd6Kb1dxTd+wGJ8MlxTGzQo//ehtqlVL4S9DNUa53+dtPSQobN2CXx4d81FqC58cw== + version "7.12.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.12.0.tgz#01f67ea62662e7de401af7567b6054e6a4807d65" + integrity sha512-BC8wiTo+0kEG8M6wuEBeuG7AIazTan02/Bh4dgi+wdDBE+p2iv5AXO8OUjrwD100223S/2WbALSqj7c290XTKg== dependencies: "@babel/helper-module-imports" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" @@ -943,11 +919,11 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-typescript@^7.9.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.11.0.tgz#2b4879676af37342ebb278216dd090ac67f13abb" - integrity sha512-edJsNzTtvb3MaXQwj8403B7mZoGu9ElDJQZOKjGUnvilquxBA3IQoEIOvkX/1O8xfAsnHS/oQhe2w/IXrr+w0w== + version "7.12.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.12.0.tgz#bd6422833a56e4268d8d599238f0b3c5e170078a" + integrity sha512-gahRNAWgE76hjI3TZPVEfV7vGjOCJi5ACd4eSoAItk/ErC114i2UHnk+1ScS2dOour0p6J6kB99hNFX2vzL2Ww== dependencies: - "@babel/helper-create-class-features-plugin" "^7.10.5" + "@babel/helper-create-class-features-plugin" "^7.12.0" "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-typescript" "^7.10.4" @@ -1033,25 +1009,26 @@ semver "^5.5.0" "@babel/preset-env@^7.4.5": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.11.0.tgz#860ee38f2ce17ad60480c2021ba9689393efb796" - integrity sha512-2u1/k7rG/gTh02dylX2kL3S0IJNF+J6bfDSp4DI2Ma8QN6Y9x9pmAax59fsCk6QUQG0yqH47yJWA+u1I1LccAg== + version "7.12.0" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.12.0.tgz#7d2d0c4f4a14ca0fd7d905a741070ab4745177b7" + integrity sha512-jSIHvHSuF+hBUIrvA2/61yIzhH+ceLOXGLTH1nwPvQlso/lNxXsoE/nvrCzY5M77KRzhKegB1CvdhWPZmYDZ5A== dependencies: - "@babel/compat-data" "^7.11.0" - "@babel/helper-compilation-targets" "^7.10.4" + "@babel/compat-data" "^7.12.0" + "@babel/helper-compilation-targets" "^7.12.0" "@babel/helper-module-imports" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-validator-option" "^7.12.0" "@babel/plugin-proposal-async-generator-functions" "^7.10.4" "@babel/plugin-proposal-class-properties" "^7.10.4" "@babel/plugin-proposal-dynamic-import" "^7.10.4" - "@babel/plugin-proposal-export-namespace-from" "^7.10.4" + "@babel/plugin-proposal-export-namespace-from" "^7.12.0" "@babel/plugin-proposal-json-strings" "^7.10.4" - "@babel/plugin-proposal-logical-assignment-operators" "^7.11.0" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.10.4" - "@babel/plugin-proposal-numeric-separator" "^7.10.4" + "@babel/plugin-proposal-logical-assignment-operators" "^7.12.0" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.12.0" + "@babel/plugin-proposal-numeric-separator" "^7.12.0" "@babel/plugin-proposal-object-rest-spread" "^7.11.0" "@babel/plugin-proposal-optional-catch-binding" "^7.10.4" - "@babel/plugin-proposal-optional-chaining" "^7.11.0" + "@babel/plugin-proposal-optional-chaining" "^7.12.0" "@babel/plugin-proposal-private-methods" "^7.10.4" "@babel/plugin-proposal-unicode-property-regex" "^7.10.4" "@babel/plugin-syntax-async-generators" "^7.8.0" @@ -1082,7 +1059,7 @@ "@babel/plugin-transform-member-expression-literals" "^7.10.4" "@babel/plugin-transform-modules-amd" "^7.10.4" "@babel/plugin-transform-modules-commonjs" "^7.10.4" - "@babel/plugin-transform-modules-systemjs" "^7.10.4" + "@babel/plugin-transform-modules-systemjs" "^7.12.0" "@babel/plugin-transform-modules-umd" "^7.10.4" "@babel/plugin-transform-named-capturing-groups-regex" "^7.10.4" "@babel/plugin-transform-new-target" "^7.10.4" @@ -1099,11 +1076,9 @@ "@babel/plugin-transform-unicode-escapes" "^7.10.4" "@babel/plugin-transform-unicode-regex" "^7.10.4" "@babel/preset-modules" "^0.1.3" - "@babel/types" "^7.11.0" + "@babel/types" "^7.12.0" browserslist "^4.12.0" core-js-compat "^3.6.2" - invariant "^2.2.2" - levenary "^1.1.1" semver "^5.5.0" "@babel/preset-flow@^7.0.0": @@ -1115,9 +1090,9 @@ "@babel/plugin-transform-flow-strip-types" "^7.10.4" "@babel/preset-modules@^0.1.3": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.3.tgz#13242b53b5ef8c883c3cf7dddd55b36ce80fbc72" - integrity sha512-Ra3JXOHBq2xd56xSF7lMKXdjBn3T772Y1Wet3yWnkDly9zHvJki029tAFzvAAK5cf4YV3yoxuP61crYRol6SVg== + version "0.1.4" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.4.tgz#362f2b68c662842970fdb5e254ffc8fc1c2e415e" + integrity sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" @@ -1159,9 +1134,9 @@ "@babel/plugin-transform-typescript" "^7.9.0" "@babel/runtime-corejs3@^7.10.2", "@babel/runtime-corejs3@^7.8.3": - version "7.11.2" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.11.2.tgz#02c3029743150188edeb66541195f54600278419" - integrity sha512-qh5IR+8VgFz83VBa6OkaET6uN/mJOhHONuy3m1sgF0CV6mXdPSEBdA7e1eUbVvyNtANjMbg22JUv71BaDXLY6A== + version "7.12.0" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.12.0.tgz#e74206f51ebd69a787a6be762e26593dc3e97756" + integrity sha512-CltlJftStV4CBG4/HWVVRnBWFvLkYd22BkYO4gFgX+89JOlYiKQ5+Ji9Ovqb1o3T5DkkBn3JrVq1V/xweAaeGA== dependencies: core-js-pure "^3.0.0" regenerator-runtime "^0.13.4" @@ -1173,10 +1148,17 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.1.5", "@babel/runtime@^7.10.0", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.11.0", "@babel/runtime@^7.2.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": - version "7.11.2" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.2.tgz#f549c13c754cc40b87644b9fa9f09a6a95fe0736" - integrity sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw== +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.1.5", "@babel/runtime@^7.10.0", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.11.2", "@babel/runtime@^7.2.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": + version "7.12.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.0.tgz#98bd7666186969c04be893d747cf4a6c6c8fa6b0" + integrity sha512-lS4QLXQ2Vbw2ubfQjeQcn+BZgZ5+ROHW9f+DWjEp5Y+NHYmkRGKqHSJ1tuhbUauKu2nhZNTBIvsIQ8dXfY5Gjw== + dependencies: + regenerator-runtime "^0.13.4" + +"@babel/runtime@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.1.tgz#b4116a6b6711d010b2dad3b7b6e43bf1b9954740" + integrity sha512-J5AIf3vPj3UwXaAzb5j1xM4WAQDX3EMgemF8rjCP3SoW09LfRKAXQKt6CoVYl230P6iWdRcBbnLDDdnqWxZSCA== dependencies: regenerator-runtime "^0.13.4" @@ -1189,25 +1171,25 @@ "@babel/parser" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/traverse@^7.1.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.11.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.4.5", "@babel/traverse@^7.7.0", "@babel/traverse@^7.9.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.11.0.tgz#9b996ce1b98f53f7c3e4175115605d56ed07dd24" - integrity sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg== +"@babel/traverse@^7.1.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.12.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.4.5", "@babel/traverse@^7.7.0", "@babel/traverse@^7.9.0": + version "7.12.0" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.0.tgz#ed31953d6e708cdd34443de2fcdb55f72cdfb266" + integrity sha512-ZU9e79xpOukCNPkQ1UzR4gJKCruGckr6edd8v8lmKpSk8iakgUIvb+5ZtaKKV9f7O+x5r+xbMDDIbzVpUoiIuw== dependencies: "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.11.0" + "@babel/generator" "^7.12.0" "@babel/helper-function-name" "^7.10.4" "@babel/helper-split-export-declaration" "^7.11.0" - "@babel/parser" "^7.11.0" - "@babel/types" "^7.11.0" + "@babel/parser" "^7.12.0" + "@babel/types" "^7.12.0" debug "^4.1.0" globals "^11.1.0" lodash "^4.17.19" -"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.7.0", "@babel/types@^7.9.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.0.tgz#2ae6bf1ba9ae8c3c43824e5861269871b206e90d" - integrity sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA== +"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.0", "@babel/types@^7.12.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.7.0", "@babel/types@^7.9.0": + version "7.12.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.0.tgz#b6b49f425ee59043fbc89c61b11a13d5eae7b5c6" + integrity sha512-ggIyFmT2zMaYRheOfPDQ4gz7QqV3B+t2rjqjbttDJxMcb7/LukvWCmlIl1sWcOxrvwpTDd+z0OytzqsbGeb3/g== dependencies: "@babel/helper-validator-identifier" "^7.10.4" lodash "^4.17.19" @@ -1271,9 +1253,9 @@ "@emotion/weak-memoize" "0.2.5" "@emotion/core@^10.0.20": - version "10.0.28" - resolved "https://registry.yarnpkg.com/@emotion/core/-/core-10.0.28.tgz#bb65af7262a234593a9e952c041d0f1c9b9bef3d" - integrity sha512-pH8UueKYO5jgg0Iq+AmCLxBsvuGtvlmiDCOuv8fGNYn3cowFpLN98L8zO56U0H1PjDIyAlXymgL3Wu7u7v6hbA== + version "10.0.35" + resolved "https://registry.yarnpkg.com/@emotion/core/-/core-10.0.35.tgz#513fcf2e22cd4dfe9d3894ed138c9d7a859af9b3" + integrity sha512-sH++vJCdk025fBlRZSAhkRlSUoqSqgCzYf5fMOmqqi3bM6how+sQpg3hkgJonj8GxXM4WbD7dRO+4tegDB9fUw== dependencies: "@babel/runtime" "^7.5.5" "@emotion/cache" "^10.0.27" @@ -1378,96 +1360,96 @@ "@ethersproject/strings" ">=5.0.0-beta.130" "@ethersproject/address@>=5.0.0-beta.128", "@ethersproject/address@^5.0.0": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.0.2.tgz#80d0ddfb7d4bd0d32657747fa4bdd2defef2e00a" - integrity sha512-+rz26RKj7ujGfQynys4V9VJRbR+wpC6eL8F22q3raWMH3152Ha31GwJPWzxE/bEA+43M/zTNVwY0R53gn53L2Q== - dependencies: - "@ethersproject/bignumber" "^5.0.0" - "@ethersproject/bytes" "^5.0.0" - "@ethersproject/keccak256" "^5.0.0" - "@ethersproject/logger" "^5.0.0" - "@ethersproject/rlp" "^5.0.0" - bn.js "^4.4.0" - -"@ethersproject/bignumber@>=5.0.0-beta.130", "@ethersproject/bignumber@^5.0.0": version "5.0.5" - resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.0.5.tgz#31bd7e75aad46ace345fae69b1f5bb120906af1b" - integrity sha512-24ln7PV0g8ZzjcVZiLW9Wod0i+XCmK6zKkAaxw5enraTIT1p7gVOcSXFSzNQ9WYAwtiFQPvvA+TIO2oEITZNJA== + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.0.5.tgz#2caa65f6b7125015395b1b54c985ee0b27059cc7" + integrity sha512-DpkQ6rwk9jTefrRsJzEm6nhRiJd9pvhn1xN0rw5N/jswXG5r7BLk/GVA0mMAVWAsYfvi2xSc5L41FMox43RYEA== dependencies: - "@ethersproject/bytes" "^5.0.0" - "@ethersproject/logger" "^5.0.0" + "@ethersproject/bignumber" "^5.0.7" + "@ethersproject/bytes" "^5.0.4" + "@ethersproject/keccak256" "^5.0.3" + "@ethersproject/logger" "^5.0.5" + "@ethersproject/rlp" "^5.0.3" bn.js "^4.4.0" -"@ethersproject/bytes@>=5.0.0-beta.129", "@ethersproject/bytes@^5.0.0": - version "5.0.3" - resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.0.3.tgz#b3769963ae0188a35713d343890a903bda20af9c" - integrity sha512-AyPMAlY+Amaw4Zfp8OAivm1xYPI8mqiUYmEnSUk1CnS2NrQGHEMmFJFiOJdS3gDDpgSOFhWIjZwxKq2VZpqNTA== +"@ethersproject/bignumber@>=5.0.0-beta.130", "@ethersproject/bignumber@^5.0.0", "@ethersproject/bignumber@^5.0.7": + version "5.0.8" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.0.8.tgz#cee33bd8eb0266176def0d371b45274b1d2c4ec0" + integrity sha512-KXFVAFKS1jdTXYN8BE5Oj+ZfPMh28iRdFeNGBVT6cUFdtiPVqeXqc0ggvBqA3A1VoFFGgM7oAeaagA393aORHA== dependencies: - "@ethersproject/logger" "^5.0.0" + "@ethersproject/bytes" "^5.0.4" + "@ethersproject/logger" "^5.0.5" + bn.js "^4.4.0" -"@ethersproject/constants@>=5.0.0-beta.128", "@ethersproject/constants@^5.0.0": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.0.2.tgz#f7ac0b320e2bbec1a5950da075015f8bc4e8fed1" - integrity sha512-nNoVlNP6bgpog7pQ2EyD1xjlaXcy1Cl4kK5v1KoskHj58EtB6TK8M8AFGi3GgHTdMldfT4eN3OsoQ/CdOTVNFA== +"@ethersproject/bytes@>=5.0.0-beta.129", "@ethersproject/bytes@^5.0.0", "@ethersproject/bytes@^5.0.4": + version "5.0.5" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.0.5.tgz#688b70000e550de0c97a151a21f15b87d7f97d7c" + integrity sha512-IEj9HpZB+ACS6cZ+QQMTqmu/cnUK2fYNE6ms/PVxjoBjoxc6HCraLpam1KuRvreMy0i523PLmjN8OYeikRdcUQ== dependencies: - "@ethersproject/bignumber" "^5.0.0" + "@ethersproject/logger" "^5.0.5" + +"@ethersproject/constants@>=5.0.0-beta.128", "@ethersproject/constants@^5.0.0", "@ethersproject/constants@^5.0.4": + version "5.0.5" + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.0.5.tgz#0ed19b002e8404bdf6d135234dc86a7d9bcf9b71" + integrity sha512-foaQVmxp2+ik9FrLUCtVrLZCj4M3Ibgkqvh+Xw/vFRSerkjVSYePApaVE5essxhoSlF1U9oXfWY09QI2AXtgKA== + dependencies: + "@ethersproject/bignumber" "^5.0.7" "@ethersproject/hash@>=5.0.0-beta.128": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.0.2.tgz#6d69558786961836d530b8b4a8714eac5388aec7" - integrity sha512-dWGvNwmVRX2bxoQQ3ciMw46Vzl1nqfL+5R8+2ZxsRXD3Cjgw1dL2mdjJF7xMMWPvPdrlhKXWSK0gb8VLwHZ8Cw== + version "5.0.5" + resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.0.5.tgz#e383ba2c7941834266fa6e2cf543d2b0c50a9d59" + integrity sha512-GpI80/h2HDpfNKpCZoxQJCjOQloGnlD5hM1G+tZe8FQDJhEvFjJoPDuWv+NaYjJfOciKS2Axqc4Q4WamdLoUgg== dependencies: - "@ethersproject/bytes" "^5.0.0" - "@ethersproject/keccak256" "^5.0.0" - "@ethersproject/logger" "^5.0.0" - "@ethersproject/strings" "^5.0.0" + "@ethersproject/bytes" "^5.0.4" + "@ethersproject/keccak256" "^5.0.3" + "@ethersproject/logger" "^5.0.5" + "@ethersproject/strings" "^5.0.4" -"@ethersproject/keccak256@>=5.0.0-beta.127", "@ethersproject/keccak256@^5.0.0": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.0.2.tgz#7ed4a95bb45ee502cf4532223833740a83602797" - integrity sha512-MbroXutc0gPNYIrUjS4Aw0lDuXabdzI7+l7elRWr1G6G+W0v00e/3gbikWkCReGtt2Jnt4lQSgnflhDwQGcIhA== +"@ethersproject/keccak256@>=5.0.0-beta.127", "@ethersproject/keccak256@^5.0.0", "@ethersproject/keccak256@^5.0.3": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.0.4.tgz#36ca0a7d1ae2a272da5654cb886776d0c680ef3a" + integrity sha512-GNpiOUm9PGUxFNqOxYKDQBM0u68bG9XC9iOulEQ8I0tOx/4qUpgVzvgXL6ugxr0RY554Gz/NQsVqknqPzUcxpQ== dependencies: - "@ethersproject/bytes" "^5.0.0" + "@ethersproject/bytes" "^5.0.4" js-sha3 "0.5.7" -"@ethersproject/logger@>=5.0.0-beta.129", "@ethersproject/logger@^5.0.0": +"@ethersproject/logger@>=5.0.0-beta.129", "@ethersproject/logger@^5.0.0", "@ethersproject/logger@^5.0.5": + version "5.0.6" + resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.0.6.tgz#faa484203e86e08be9e07fef826afeef7183fe88" + integrity sha512-FrX0Vnb3JZ1md/7GIZfmJ06XOAA8r3q9Uqt9O5orr4ZiksnbpXKlyDzQtlZ5Yv18RS8CAUbiKH9vwidJg1BPmQ== + +"@ethersproject/properties@>=5.0.0-beta.131", "@ethersproject/properties@^5.0.0", "@ethersproject/properties@^5.0.3": version "5.0.4" - resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.0.4.tgz#09fa4765b5691233e3afb6617cb38a700f9dd2e4" - integrity sha512-alA2LiAy1LdQ/L1SA9ajUC7MvGAEQLsICEfKK4erX5qhkXE1LwLSPIzobtOWFsMHf2yrXGKBLnnpuVHprI3sAw== - -"@ethersproject/properties@>=5.0.0-beta.131", "@ethersproject/properties@^5.0.0": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.0.2.tgz#2facb62d2f2d968c7b3d0befa5bcc884cc565d3b" - integrity sha512-FxAisPGAOACQjMJzewl9OJG6lsGCPTm5vpUMtfeoxzAlAb2lv+kHzQPUh9h4jfAILzE8AR1jgXMzRmlhwyra1Q== + resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.0.4.tgz#a67a1f5a52c30850b5062c861631e73d131f666e" + integrity sha512-UdyX3GqBxFt15B0uSESdDNmhvEbK3ACdDXl2soshoPcneXuTswHDeA0LoPlnaZzhbgk4p6jqb4GMms5C26Qu6A== dependencies: - "@ethersproject/logger" "^5.0.0" + "@ethersproject/logger" "^5.0.5" -"@ethersproject/rlp@^5.0.0": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.0.2.tgz#d6b550a2ac5e484f15f0f63337e522004d2e78cd" - integrity sha512-oE0M5jqQ67fi2SuMcrpoewOpEuoXaD8M9JeR9md1bXRMvDYgKXUtDHs22oevpEOdnO2DPIRabp6MVHa4aDuWmw== +"@ethersproject/rlp@^5.0.0", "@ethersproject/rlp@^5.0.3": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.0.4.tgz#0090a0271e84ea803016a112a79f5cfd80271a77" + integrity sha512-5qrrZad7VTjofxSsm7Zg/7Dr4ZOln4S2CqiDdOuTv6MBKnXj0CiBojXyuDy52M8O3wxH0CyE924hXWTDV1PQWQ== dependencies: - "@ethersproject/bytes" "^5.0.0" - "@ethersproject/logger" "^5.0.0" + "@ethersproject/bytes" "^5.0.4" + "@ethersproject/logger" "^5.0.5" "@ethersproject/signing-key@^5.0.0": - version "5.0.3" - resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.0.3.tgz#adb84360e147bfd336cb2fe114100120732dc10a" - integrity sha512-5QPZaBRGCLzfVMbFb3LcVjNR0UbTXnwDHASnQYfbzwUOnFYHKxHsrcbl/5ONGoppgi8yXgOocKqlPCFycJJVWQ== + version "5.0.5" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.0.5.tgz#acfd06fc05a14180df7e027688bbd23fc4baf782" + integrity sha512-Z1wY7JC1HVO4CvQWY2TyTTuAr8xK3bJijZw1a9G92JEmKdv1j255R/0YLBBcFTl2J65LUjtXynNJ2GbArPGi5g== dependencies: - "@ethersproject/bytes" "^5.0.0" - "@ethersproject/logger" "^5.0.0" - "@ethersproject/properties" "^5.0.0" + "@ethersproject/bytes" "^5.0.4" + "@ethersproject/logger" "^5.0.5" + "@ethersproject/properties" "^5.0.3" elliptic "6.5.3" -"@ethersproject/strings@>=5.0.0-beta.130", "@ethersproject/strings@^5.0.0": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.0.2.tgz#1753408c3c889813fd0992abd76393e3e47a2619" - integrity sha512-oNa+xvSqsFU96ndzog0IBTtsRFGOqGpzrXJ7shXLBT7juVeSEyZA/sYs0DMZB5mJ9FEjHdZKxR/rTyBY91vuXg== +"@ethersproject/strings@>=5.0.0-beta.130", "@ethersproject/strings@^5.0.4": + version "5.0.5" + resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.0.5.tgz#ed7e99a282a02f40757691b04a24cd83f3752195" + integrity sha512-JED6WaIV00xM/gvj8vSnd+0VWtDYdidTmavFRCTQakqfz+4tDo6Jz5LHgG+dd45h7ah7ykCHW0C7ZXWEDROCXQ== dependencies: - "@ethersproject/bytes" "^5.0.0" - "@ethersproject/constants" "^5.0.0" - "@ethersproject/logger" "^5.0.0" + "@ethersproject/bytes" "^5.0.4" + "@ethersproject/constants" "^5.0.4" + "@ethersproject/logger" "^5.0.5" "@ethersproject/transactions@^5.0.0-beta.135": version "5.0.2" @@ -1484,10 +1466,11 @@ "@ethersproject/rlp" "^5.0.0" "@ethersproject/signing-key" "^5.0.0" -"@gnosis.pm/safe-apps-sdk@0.4.0": - version "0.4.0" - resolved "https://registry.yarnpkg.com/@gnosis.pm/safe-apps-sdk/-/safe-apps-sdk-0.4.0.tgz#26c821513c995b9dc023ebbdfe103a832e731521" - integrity sha512-hUt/Siz5kSu9jgvMZXejQsxQiUo/NIow67KNAQGfMt7D0S1YoyvpCGAgSliNelY/bP7EanBhhStOnItnu7DwUA== +"@gnosis.pm/safe-apps-sdk@https://github.com/gnosis/safe-apps-sdk.git#3f0689f": + version "0.4.2" + resolved "https://github.com/gnosis/safe-apps-sdk.git#3f0689ff549c29fde4ff5ca915daf76c24aa1c8f" + dependencies: + web3-core "^1.3.0" "@gnosis.pm/safe-contracts@1.1.1-dev.2": version "1.1.1-dev.2" @@ -1501,9 +1484,9 @@ solc "0.5.14" truffle "^5.1.21" -"@gnosis.pm/safe-react-components@https://github.com/gnosis/safe-react-components.git#1bf397f": - version "0.2.0" - resolved "https://github.com/gnosis/safe-react-components.git#1bf397f2bc48ba48906824137943f0bb5804c99c" +"@gnosis.pm/safe-react-components@https://github.com/gnosis/safe-react-components.git#70e57bdd1e0fd5dfdf5768076577c1e000b5fe28": + version "0.4.0" + resolved "https://github.com/gnosis/safe-react-components.git#70e57bdd1e0fd5dfdf5768076577c1e000b5fe28" dependencies: classnames "^2.2.6" polished "3.6.5" @@ -1546,9 +1529,9 @@ integrity sha512-yN7kbciD87WzLGc5539Tn0sApjyiGHAJgKvG9W8C7O+6c7qmoQMfVs0W4bX17eqz6C78QJqqFrtgdK5EWf6Qow== "@hapi/hoek@^9.0.0": - version "9.0.4" - resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.0.4.tgz#e80ad4e8e8d2adc6c77d985f698447e8628b6010" - integrity sha512-EwaJS7RjoXUZ2cXXKZZxZqieGtc7RbvQhUy8FwDoMQtxWVi14tFjeFCYPZAM1mBCpOpiBpyaZbb9NeHc7eGKgw== + version "9.1.0" + resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.1.0.tgz#6c9eafc78c1529248f8f4d92b0799a712b6052c6" + integrity sha512-i9YbZPN3QgfighY/1X1Pu118VUz2Fmmhd6b2n0/O8YVgGGfw0FbUYoA97k7FkpGJ+pLCFEDLUmAPPV4D1kpeFw== "@hapi/joi@^15.0.0": version "15.1.1" @@ -1737,10 +1720,10 @@ "@types/yargs" "^15.0.0" chalk "^3.0.0" -"@jest/types@^26.3.0": - version "26.3.0" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.3.0.tgz#97627bf4bdb72c55346eef98e3b3f7ddc4941f71" - integrity sha512-BDPG23U0qDeAvU4f99haztXwdAg3hz4El95LkAM+tHAqqhiVzRpEGHHU8EDxT/AnxOrA65YjLBwDahdJ9pTLJQ== +"@jest/types@^26.5.2": + version "26.5.2" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.5.2.tgz#44c24f30c8ee6c7f492ead9ec3f3c62a5289756d" + integrity sha512-QDs5d0gYiyetI8q+2xWdkixVQMklReZr4ltw7GFDtb4fuJIBCE6mzj2LnitGqCuAlLap6wPyb8fpoHgwZz5fdg== dependencies: "@types/istanbul-lib-coverage" "^2.0.0" "@types/istanbul-reports" "^3.0.0" @@ -1748,78 +1731,97 @@ "@types/yargs" "^15.0.0" chalk "^4.0.0" -"@ledgerhq/devices@^5.22.0": - version "5.22.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/devices/-/devices-5.22.0.tgz#18595f3545b57cf60e50d6e9d83095dda21f575f" - integrity sha512-oJxhee/zlHmIx66zvQQTSpIsHOiiLjALemTX9oUtB4xQwFvoiptPnBCeTDTM9teode7wzk7oE9qdUAZuat+nCg== +"@jest/types@^26.6.1": + version "26.6.1" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.6.1.tgz#2638890e8031c0bc8b4681e0357ed986e2f866c5" + integrity sha512-ywHavIKNpAVrStiRY5wiyehvcktpijpItvGiK72RAn5ctqmzvPk8OvKnvHeBqa1XdQr959CTWAJMqxI8BTibyg== dependencies: - "@ledgerhq/errors" "^5.22.0" - "@ledgerhq/logs" "^5.22.0" - rxjs "^6.6.2" + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^15.0.0" + chalk "^4.0.0" -"@ledgerhq/errors@^5.22.0": - version "5.22.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/errors/-/errors-5.22.0.tgz#7327fc152d4896ddc26aada0943065db21c14880" - integrity sha512-XDT0meBn39+q+JWzUFXmiFbVYLTy+uHRFMb9napcxyZ0Q/MdKkle9/vkgtvRHjPIkGobklXpyefsgH3BZQHukA== +"@ledgerhq/cryptoassets@^5.27.0": + version "5.27.0" + resolved "https://registry.yarnpkg.com/@ledgerhq/cryptoassets/-/cryptoassets-5.27.0.tgz#6bc71a2bb4446f9a08c6733b74e19c8c39708424" + integrity sha512-d1yce05DV/eMIK6eAg5Y3qZ9B5LSjQyLjIsiq5R0Du5UjomcLoG0I5ivktLLAsYCSidQ1YQs6f2Ve/CCUNivbA== + dependencies: + invariant "2" + +"@ledgerhq/devices@^5.26.0": + version "5.26.0" + resolved "https://registry.yarnpkg.com/@ledgerhq/devices/-/devices-5.26.0.tgz#6c25ee48d0d2f49a8fa1abc11f3efd888f3fea68" + integrity sha512-atD6al6E6j2tT7vefnW5r0bbZVURsOFbvyqy4Cknv659xVO/+i4pftgRaATecGD+evprRMcI+Rt1G1WtP3z66Q== + dependencies: + "@ledgerhq/errors" "^5.26.0" + "@ledgerhq/logs" "^5.26.0" + rxjs "^6.6.3" + +"@ledgerhq/errors@^5.26.0": + version "5.26.0" + resolved "https://registry.yarnpkg.com/@ledgerhq/errors/-/errors-5.26.0.tgz#a2d3da356e8053817b6517a94eff876ca1d0c972" + integrity sha512-oMEf6ONyLqaZYkunDZWSc6Qo9uBzim5R8XDXOOyrz7zrj4hixsvxiAh8y1Jbrr1MQLG5HJ+aehee4Ot/A5iXtw== "@ledgerhq/hw-app-eth@^5.21.0": - version "5.22.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-eth/-/hw-app-eth-5.22.0.tgz#571e7d97629a9be63c5a1e5d7324cde0a7a8ffd5" - integrity sha512-O+PqA1DGsdyjZ2DFW3r6hKqtaGCq3MNqaYUmqHvdp/wTOYIlgmiBKqhaobMTA+ufa46/8CKLDheW/8WcAu7tAA== + version "5.27.0" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-eth/-/hw-app-eth-5.27.0.tgz#d272fb0b75c47e790c4c2dcccbc61f3aa624ef85" + integrity sha512-H8FBHJ7wC5S7zhgo7keYhrVtKqRdEoGVmLQWPL/Jaz8Y1vRzdHH+zgYtQGHXmo3OELc7ZiIn8pzI2wepaOkQgQ== dependencies: - "@ledgerhq/errors" "^5.22.0" - "@ledgerhq/hw-transport" "^5.22.0" - bignumber.js "^9.0.0" + "@ledgerhq/cryptoassets" "^5.27.0" + "@ledgerhq/errors" "^5.26.0" + "@ledgerhq/hw-transport" "^5.26.0" + bignumber.js "^9.0.1" rlp "^2.2.6" -"@ledgerhq/hw-transport-node-hid-noevents@^5.22.0": - version "5.22.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid-noevents/-/hw-transport-node-hid-noevents-5.22.0.tgz#b5a42a71664fe69bf5fae579854d10e4815a794e" - integrity sha512-6sxrqTcBEGvhVDOS5Vy3mKZgaVOKbHplxm4o/3PmtugJcvpEBvDNGXNh3PMWPtHXXYQ5E5C/qWh7Y+gYshMmTg== +"@ledgerhq/hw-transport-node-hid-noevents@^5.26.0": + version "5.26.0" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid-noevents/-/hw-transport-node-hid-noevents-5.26.0.tgz#84155794e5095e4db0fbc39f1442c6c2e8f482e6" + integrity sha512-XszH42vlzp+BwO7Ej2H91aCrH1TVsc5/uc/Bpciz1ac34FIp412kUMT9zAcY7H1ey2lgqTiBddSyj4uEPUB6Nw== dependencies: - "@ledgerhq/devices" "^5.22.0" - "@ledgerhq/errors" "^5.22.0" - "@ledgerhq/hw-transport" "^5.22.0" - "@ledgerhq/logs" "^5.22.0" - node-hid "^1.3.0" + "@ledgerhq/devices" "^5.26.0" + "@ledgerhq/errors" "^5.26.0" + "@ledgerhq/hw-transport" "^5.26.0" + "@ledgerhq/logs" "^5.26.0" + node-hid "1.3.0" -"@ledgerhq/hw-transport-node-hid@5.22.0": - version "5.22.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-5.22.0.tgz#00f573bd9163b9c553071af3f2a52aa19d4674c0" - integrity sha512-TrSQEGiYXBW8FQS2QEAmk/g+vwcKQ2MZVjPiIaqSCGnwVgmKOXfMetPjwgwr8k6XiQ7YMRdpsXa0GpIvTowqRA== +"@ledgerhq/hw-transport-node-hid@5.26.0": + version "5.26.0" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-5.26.0.tgz#69bc4f8067cdd9c09ef4aed0e0b3c58328936e4b" + integrity sha512-qhaefZVZatJ6UuK8Wb6WSFNOLWc2mxcv/xgsfKi5HJCIr4bPF/ecIeN+7fRcEaycxj4XykY6Z4A7zDVulfFH4w== dependencies: - "@ledgerhq/devices" "^5.22.0" - "@ledgerhq/errors" "^5.22.0" - "@ledgerhq/hw-transport" "^5.22.0" - "@ledgerhq/hw-transport-node-hid-noevents" "^5.22.0" - "@ledgerhq/logs" "^5.22.0" - lodash "^4.17.19" - node-hid "^1.3.0" + "@ledgerhq/devices" "^5.26.0" + "@ledgerhq/errors" "^5.26.0" + "@ledgerhq/hw-transport" "^5.26.0" + "@ledgerhq/hw-transport-node-hid-noevents" "^5.26.0" + "@ledgerhq/logs" "^5.26.0" + lodash "^4.17.20" + node-hid "1.3.0" usb "^1.6.3" "@ledgerhq/hw-transport-u2f@^5.21.0": - version "5.22.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-u2f/-/hw-transport-u2f-5.22.0.tgz#c39d2da6965310c44460376d643b9ad873e76228" - integrity sha512-ooSqdeFcW8Oo9BOVYfPNT4NX7IQlffVX9lZMqy2HBpHAjTW/iIViGtZOyKr5ehHrwugAw/hWNH5TqUqs7zgoyA== + version "5.26.0" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-u2f/-/hw-transport-u2f-5.26.0.tgz#b7d9d13193eb82b051fd7a838cd652372f907ec5" + integrity sha512-QTxP1Rsh+WZ184LUOelYVLeaQl3++V3I2jFik+l9JZtakwEHjD0XqOT750xpYNL/vfHsy31Wlz+oicdxGzFk+w== dependencies: - "@ledgerhq/errors" "^5.22.0" - "@ledgerhq/hw-transport" "^5.22.0" - "@ledgerhq/logs" "^5.22.0" + "@ledgerhq/errors" "^5.26.0" + "@ledgerhq/hw-transport" "^5.26.0" + "@ledgerhq/logs" "^5.26.0" u2f-api "0.2.7" -"@ledgerhq/hw-transport@^5.22.0": - version "5.22.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-5.22.0.tgz#d627948b43005ec9e7dfe85adf9aa01e130de280" - integrity sha512-MFfkVGYMYnr6fI4XGnJQNLd36JIrRpvd5WBmVSDhCO3UKUER2fJ9koVBGc97o7yXtE5IAlJKF+nR9HZJIa0lRQ== +"@ledgerhq/hw-transport@^5.26.0": + version "5.26.0" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-5.26.0.tgz#bfedc3d48400ad2fe48278d9444344b72aa9d0fe" + integrity sha512-NFeJOJmyEfAX8uuIBTpocWHcz630sqPcXbu864Q+OCBm4EK5UOKV1h/pX7e0xgNIKY8zhJ/O4p4cIZp9tnXLHQ== dependencies: - "@ledgerhq/devices" "^5.22.0" - "@ledgerhq/errors" "^5.22.0" + "@ledgerhq/devices" "^5.26.0" + "@ledgerhq/errors" "^5.26.0" events "^3.2.0" -"@ledgerhq/logs@^5.22.0": - version "5.22.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/logs/-/logs-5.22.0.tgz#a54d6b5b391cdb4c2eacc9500feb04b90475c361" - integrity sha512-jV4mJxD1aieORm+sK9bYakQd9GMLd7KAxgt2IaxhrTU+QD5Ne47mxQOTys9p7f5w25ujs3R+Px2t3KiMRASHtg== +"@ledgerhq/logs@^5.26.0": + version "5.26.0" + resolved "https://registry.yarnpkg.com/@ledgerhq/logs/-/logs-5.26.0.tgz#171bd471265259663520abb02a0eed80e949e3a1" + integrity sha512-/3EKvS9eHzKl9Om+t//SPnzJaahIoVIUlozLMSarINyO7SSh174kxl3jTNHBl7dLxvkQyDDs5imLvP04ohlQaw== "@material-ui/core@4.11.0": version "4.11.0" @@ -1911,42 +1913,42 @@ call-me-maybe "^1.0.1" glob-to-regexp "^0.3.0" +"@nodelib/fs.scandir@2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" + integrity sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw== + dependencies: + "@nodelib/fs.stat" "2.0.3" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.3", "@nodelib/fs.stat@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz#34dc5f4cabbc720f4e60f75a747e7ecd6c175bd3" + integrity sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA== + "@nodelib/fs.stat@^1.1.2": version "1.1.3" resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== +"@nodelib/fs.walk@^1.2.3": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz#011b9202a70a6366e436ca5c065844528ab04976" + integrity sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ== + dependencies: + "@nodelib/fs.scandir" "2.1.3" + fastq "^1.6.0" + "@openzeppelin/contracts@3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-3.1.0.tgz#bcea457ef89069fbe5a617f50b25b6a8272895d5" integrity sha512-dVXDnUKxrAKLzPdCRkz+N8qsVkK1XxJ6kk3zuI6zaQmcKxN7CkizoDP7lXxcs/Mi2I0mxceTRjJBqlzFffLJrQ== -"@portis/eth-json-rpc-middleware@^4.1.2": - version "4.1.2" - resolved "https://registry.yarnpkg.com/@portis/eth-json-rpc-middleware/-/eth-json-rpc-middleware-4.1.2.tgz#391e392da03dea348c8111a8111ce4550aa24a02" - integrity sha512-LUV0JgV6jphhfmYyElpFYfEzKhxaW2VYB/trWJK7+68s4PNyMMYR94hheXRh9T2lBomSVpdbySfYxjWVLAMKwA== +"@portis/web3-provider-engine@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@portis/web3-provider-engine/-/web3-provider-engine-1.1.2.tgz#97f383156ea6b70fba69ae93a945fdd94159b1ba" + integrity sha512-NiiF0UPfngf4ulo32ybEDAMaad4i7h44HJaN8ea8HHt/vaFiUcPtINjC2o21jhWaLANerW4ZbOrNs1iCLH4p6A== 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" - -"@portis/web3-provider-engine@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@portis/web3-provider-engine/-/web3-provider-engine-1.1.0.tgz#4e502fe363dd5156505ea54a5c902537944b9cf5" - integrity sha512-443QwQqgO/D0gEn7voMfo/dBc0SNzvJ4vVSOUJj1r2W9MsN3f5HeU2wDeXLc8bQryGsmemBxmghK/G+XQTXA6w== - dependencies: - "@portis/eth-json-rpc-middleware" "^4.1.2" async "^2.5.0" backoff "^2.5.0" clone "^2.0.0" @@ -1954,7 +1956,8 @@ eth-block-tracker "^4.2.0" eth-json-rpc-filters "^4.0.2" eth-json-rpc-infura "^3.1.0" - eth-sig-util "^1.4.2" + eth-json-rpc-middleware "^5.0.2" + eth-sig-util "2.5.3" ethereumjs-block "^1.2.2" ethereumjs-tx "^1.2.0" ethereumjs-util "^5.1.5" @@ -1970,11 +1973,11 @@ xtend "^4.0.1" "@portis/web3@^2.0.0-beta.57": - version "2.0.0-beta.57" - resolved "https://registry.yarnpkg.com/@portis/web3/-/web3-2.0.0-beta.57.tgz#45692bffc07687d50fa5204d514590d438b759de" - integrity sha512-OYmt0a171AJECYT/vTkPb4uc1x7xFASMfn+MN3EAjo7DRhY8WfTAMNoMJDhuFARRLC7an2HrRIsT7D4q9GNrnQ== + version "2.0.0-beta.59" + resolved "https://registry.yarnpkg.com/@portis/web3/-/web3-2.0.0-beta.59.tgz#2e5292d8e1daf6070aa3b4a8cb33c1a9e0315011" + integrity sha512-QdIdrI3uK+TyT+dxRK5bEYOi2PBlUDJ7vszR2uu0bT49wy7O52B9td6fL/5gsfk0VpCsmrYov3x3gEQYwGUyvQ== dependencies: - "@portis/web3-provider-engine" "1.1.0" + "@portis/web3-provider-engine" "1.1.2" ethereumjs-util "5.2.0" penpal "3.0.7" pocket-js-core "0.0.3" @@ -2000,16 +2003,16 @@ integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== "@storybook/addon-actions@^5.3.19": - version "5.3.19" - resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-5.3.19.tgz#50548fa6e84bc79ad95233ce23ade4878fc7cfac" - integrity sha512-gXF29FFUgYlUoFf1DcVCmH1chg2ElaHWMmCi5h7aZe+g6fXBQw0UtEdJnYLMOqZCIiWoZyuf1ETD0RbNHPhRIw== + version "5.3.21" + resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-5.3.21.tgz#16eed3eb24996adfcbf70bd476a261324d6de593" + integrity sha512-6SAF/j8UBZaAbRz/rYUlcCXda+c4LQvvNlbVJc9GHjNNNMJQQVc3/EU+M7PyFz6uDUxudAW1+AFchGk04ACJ2g== dependencies: - "@storybook/addons" "5.3.19" - "@storybook/api" "5.3.19" - "@storybook/client-api" "5.3.19" - "@storybook/components" "5.3.19" - "@storybook/core-events" "5.3.19" - "@storybook/theming" "5.3.19" + "@storybook/addons" "5.3.21" + "@storybook/api" "5.3.21" + "@storybook/client-api" "5.3.21" + "@storybook/components" "5.3.21" + "@storybook/core-events" "5.3.21" + "@storybook/theming" "5.3.21" core-js "^3.0.1" fast-deep-equal "^2.0.1" global "^4.3.2" @@ -2020,46 +2023,46 @@ uuid "^3.3.2" "@storybook/addon-links@^5.3.19": - version "5.3.19" - resolved "https://registry.yarnpkg.com/@storybook/addon-links/-/addon-links-5.3.19.tgz#3c23e886d44b56978ae254fed3bf8be54c877178" - integrity sha512-gn9u8lebREfRsyzxoDPG0O+kOf5aJ0BhzcCJGZZdqha0F6OWHhh8vJYZZvjJ/Qwze+Qt2zjrgWm+Q6+JLD8ugQ== + version "5.3.21" + resolved "https://registry.yarnpkg.com/@storybook/addon-links/-/addon-links-5.3.21.tgz#4bae11c5de77fcce1f5429be3454376870512db2" + integrity sha512-Gjg3EUGVNSubvWawgbdiXQIKOL7QoMQOCeh1Pyl+5GPozYWDMr8O+86funTbt9LPBzGE1J+RWHarDaArUc6tSw== dependencies: - "@storybook/addons" "5.3.19" - "@storybook/client-logger" "5.3.19" - "@storybook/core-events" "5.3.19" + "@storybook/addons" "5.3.21" + "@storybook/client-logger" "5.3.21" + "@storybook/core-events" "5.3.21" "@storybook/csf" "0.0.1" - "@storybook/router" "5.3.19" + "@storybook/router" "5.3.21" core-js "^3.0.1" global "^4.3.2" prop-types "^15.7.2" qs "^6.6.0" ts-dedent "^1.1.0" -"@storybook/addons@5.3.19", "@storybook/addons@^5.3.19": - version "5.3.19" - resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-5.3.19.tgz#3a7010697afd6df9a41b8c8a7351d9a06ff490a4" - integrity sha512-Ky/k22p6i6FVNvs1VhuFyGvYJdcp+FgXqFgnPyY/OXJW/vPDapdElpTpHJZLFI9I2FQBDcygBPU5RXkumQ+KUQ== +"@storybook/addons@5.3.21", "@storybook/addons@^5.3.19": + version "5.3.21" + resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-5.3.21.tgz#ee312c738c33e8c34dc11777ef93522c3c36e56a" + integrity sha512-Ji/21WADTLVbTbiKcZ64BcL0Es+h1Afxx3kNmGJqPSTUYroCwIFCT9mUzCqU6G+YyWaISAmTii5UJkTwMkChwA== dependencies: - "@storybook/api" "5.3.19" - "@storybook/channels" "5.3.19" - "@storybook/client-logger" "5.3.19" - "@storybook/core-events" "5.3.19" + "@storybook/api" "5.3.21" + "@storybook/channels" "5.3.21" + "@storybook/client-logger" "5.3.21" + "@storybook/core-events" "5.3.21" core-js "^3.0.1" global "^4.3.2" util-deprecate "^1.0.2" -"@storybook/api@5.3.19": - version "5.3.19" - resolved "https://registry.yarnpkg.com/@storybook/api/-/api-5.3.19.tgz#77f15e9e2eee59fe1ddeaba1ef39bc34713a6297" - integrity sha512-U/VzDvhNCPmw2igvJYNNM+uwJCL+3teiL6JmuoL4/cmcqhI6IqqG9dZmMP1egoCd19wXEP7rnAfB/VcYVg41dQ== +"@storybook/api@5.3.21": + version "5.3.21" + resolved "https://registry.yarnpkg.com/@storybook/api/-/api-5.3.21.tgz#8f1772de53b65e1a65d2f0257463d621a8617c58" + integrity sha512-K1o4an/Rx8daKRDooks6qzN6ZGyqizeacZZbair3F8CsSfTgrr2zCcf9pgKojLQa9koEmMHlcdb2KnS+GwPEgA== dependencies: "@reach/router" "^1.2.1" - "@storybook/channels" "5.3.19" - "@storybook/client-logger" "5.3.19" - "@storybook/core-events" "5.3.19" + "@storybook/channels" "5.3.21" + "@storybook/client-logger" "5.3.21" + "@storybook/core-events" "5.3.21" "@storybook/csf" "0.0.1" - "@storybook/router" "5.3.19" - "@storybook/theming" "5.3.19" + "@storybook/router" "5.3.21" + "@storybook/theming" "5.3.21" "@types/reach__router" "^1.2.3" core-js "^3.0.1" fast-deep-equal "^2.0.1" @@ -2074,34 +2077,34 @@ telejson "^3.2.0" util-deprecate "^1.0.2" -"@storybook/channel-postmessage@5.3.19": - version "5.3.19" - resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-5.3.19.tgz#ef9fe974c2a529d89ce342ff7acf5cc22805bae9" - integrity sha512-Iq0f4NPHR0UVVFCWt0cI7Myadk4/SATXYJPT6sv95KhnLjKEeYw571WBlThfp8a9FM80887xG+eIRe93c8dleA== +"@storybook/channel-postmessage@5.3.21": + version "5.3.21" + resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-5.3.21.tgz#9c08bf1c108ff973dbca18e582680d25178db1d4" + integrity sha512-CfoP7aEbZtJ35R9zeujMRdIwprETUi+Ve+y84DhXYQ2uJ0rR3vO4zHLZnxMMyJ5VnYOfuO042uch07+EKBz40Q== dependencies: - "@storybook/channels" "5.3.19" - "@storybook/client-logger" "5.3.19" + "@storybook/channels" "5.3.21" + "@storybook/client-logger" "5.3.21" core-js "^3.0.1" global "^4.3.2" telejson "^3.2.0" -"@storybook/channels@5.3.19": - version "5.3.19" - resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-5.3.19.tgz#65ad7cd19d70aa5eabbb2e5e39ceef5e510bcb7f" - integrity sha512-38seaeyshRGotTEZJppyYMg/Vx2zRKgFv1L6uGqkJT0LYoNSYtJhsiNFCJ2/KUJu2chAJ/j8h80bpVBVLQ/+WA== +"@storybook/channels@5.3.21": + version "5.3.21" + resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-5.3.21.tgz#53ba622b171d68b3b102983a62aa05149a49497b" + integrity sha512-OXoFs9XtBVg/cCk6lYMrxkzaNlJRf54ABdorp7YAAj7S9tRL1JxOZHxmjNQwEoiRvssmem2rAWtEAxfuEANsAA== dependencies: core-js "^3.0.1" -"@storybook/client-api@5.3.19": - version "5.3.19" - resolved "https://registry.yarnpkg.com/@storybook/client-api/-/client-api-5.3.19.tgz#7a5630bb8fffb92742b1773881e9004ee7fdf8e0" - integrity sha512-Dh8ZLrLH91j9Fa28Gmp0KFUvvgK348aNMrDNAUdj4m4witz/BWQ2pxz6qq9/xFVErk/GanVC05kazGElqgYCRQ== +"@storybook/client-api@5.3.21": + version "5.3.21" + resolved "https://registry.yarnpkg.com/@storybook/client-api/-/client-api-5.3.21.tgz#5b218a28f24219c32ab4b92a6af2a3e452fb8089" + integrity sha512-vS4DfA2Avvl7JNQymO4e3RUNoTWIGVfZJ70Irnd6PTAZNojbCXTYuigDavrmyf83F3g5rQpwmSAPjuoi/X/FRA== dependencies: - "@storybook/addons" "5.3.19" - "@storybook/channel-postmessage" "5.3.19" - "@storybook/channels" "5.3.19" - "@storybook/client-logger" "5.3.19" - "@storybook/core-events" "5.3.19" + "@storybook/addons" "5.3.21" + "@storybook/channel-postmessage" "5.3.21" + "@storybook/channels" "5.3.21" + "@storybook/client-logger" "5.3.21" + "@storybook/core-events" "5.3.21" "@storybook/csf" "0.0.1" "@types/webpack-env" "^1.15.0" core-js "^3.0.1" @@ -2115,20 +2118,20 @@ ts-dedent "^1.1.0" util-deprecate "^1.0.2" -"@storybook/client-logger@5.3.19": - version "5.3.19" - resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-5.3.19.tgz#fbbd186e82102eaca1d6a5cca640271cae862921" - integrity sha512-nHftT9Ow71YgAd2/tsu79kwKk30mPuE0sGRRUHZVyCRciGFQweKNOS/6xi2Aq+WwBNNjPKNlbgxwRt1yKe1Vkg== +"@storybook/client-logger@5.3.21": + version "5.3.21" + resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-5.3.21.tgz#912c83b0d358e70acad1ad4abe199de4c38b109f" + integrity sha512-OzQkwpZ5SK9cXD9Mv6lxPGPot+hSZvnkEW12kpt1AHfJz4ET26YTDOI3oetPsjfRJo6qYLeQX8+wF7rklfXbzA== dependencies: core-js "^3.0.1" -"@storybook/components@5.3.19": - version "5.3.19" - resolved "https://registry.yarnpkg.com/@storybook/components/-/components-5.3.19.tgz#aac1f9eea1247cc85bd93b10fca803876fb84a6b" - integrity sha512-3g23/+ktlocaHLJKISu9Neu3XKa6aYP2ctDYkRtGchSB0Q55hQsUVGO+BEVuT7Pk2D59mVCxboBjxcRoPUY4pw== +"@storybook/components@5.3.21": + version "5.3.21" + resolved "https://registry.yarnpkg.com/@storybook/components/-/components-5.3.21.tgz#17ee371a2455c6e807c3d3135a9266e63ad7651a" + integrity sha512-42QQk6qZl6wrtajP8yNCfmNS2t8Iod5QY+4V/l6iNnnT9O+j6cWOlnO+ZyvjNv0Xm0zIOt+VyVjdkKh8FUjQmA== dependencies: - "@storybook/client-logger" "5.3.19" - "@storybook/theming" "5.3.19" + "@storybook/client-logger" "5.3.21" + "@storybook/theming" "5.3.21" "@types/react-syntax-highlighter" "11.0.4" "@types/react-textarea-autosize" "^4.3.3" core-js "^3.0.1" @@ -2149,33 +2152,33 @@ simplebar-react "^1.0.0-alpha.6" ts-dedent "^1.1.0" -"@storybook/core-events@5.3.19": - version "5.3.19" - resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-5.3.19.tgz#18020cd52e0d8ef0973a8e9622a10d5f99796f79" - integrity sha512-lh78ySqMS7pDdMJAQAe35d1I/I4yPTqp09Cq0YIYOxx9BQZhah4DZTV1QIZt22H5p2lPb5MWLkWSxBaexZnz8A== +"@storybook/core-events@5.3.21": + version "5.3.21" + resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-5.3.21.tgz#41d81c3f107302a032545fc86ff344230c04b9e9" + integrity sha512-/Zsm1sKAh6pzQv8jQUmuhM7nuM01ZljIRKy8p2HjPNlMjDB5yaRkBfyeAUXUg+qXNI6aHVWa4jGdPEdwwY4oLA== dependencies: core-js "^3.0.1" -"@storybook/core@5.3.19": - version "5.3.19" - resolved "https://registry.yarnpkg.com/@storybook/core/-/core-5.3.19.tgz#1e61f35c5148343a0c580f5d5efb77f3b4243a30" - integrity sha512-4EYzglqb1iD6x9gxtAYpRGwGP6qJGiU2UW4GiYrErEmeu6y6tkyaqW5AwGlIo9+6jAfwD0HjaK8afvjKTtmmMQ== +"@storybook/core@5.3.21": + version "5.3.21" + resolved "https://registry.yarnpkg.com/@storybook/core/-/core-5.3.21.tgz#da963166ea24601f318266a3aa6bbc06fc8fb175" + integrity sha512-plD47WIsn/JoyRJDOpmH7N7mEMo/jiA8ZlOitLW55zYvzUn8UrVpRFpMYo91OJxiCT6JFoaEh3XtNdhbgUwnPA== dependencies: "@babel/plugin-proposal-class-properties" "^7.7.0" "@babel/plugin-proposal-object-rest-spread" "^7.6.2" "@babel/plugin-syntax-dynamic-import" "^7.2.0" "@babel/plugin-transform-react-constant-elements" "^7.2.0" "@babel/preset-env" "^7.4.5" - "@storybook/addons" "5.3.19" - "@storybook/channel-postmessage" "5.3.19" - "@storybook/client-api" "5.3.19" - "@storybook/client-logger" "5.3.19" - "@storybook/core-events" "5.3.19" + "@storybook/addons" "5.3.21" + "@storybook/channel-postmessage" "5.3.21" + "@storybook/client-api" "5.3.21" + "@storybook/client-logger" "5.3.21" + "@storybook/core-events" "5.3.21" "@storybook/csf" "0.0.1" - "@storybook/node-logger" "5.3.19" - "@storybook/router" "5.3.19" - "@storybook/theming" "5.3.19" - "@storybook/ui" "5.3.19" + "@storybook/node-logger" "5.3.21" + "@storybook/router" "5.3.21" + "@storybook/theming" "5.3.21" + "@storybook/ui" "5.3.21" airbnb-js-shims "^2.2.1" ansi-to-html "^0.6.11" autoprefixer "^9.7.2" @@ -2242,10 +2245,10 @@ dependencies: lodash "^4.17.15" -"@storybook/node-logger@5.3.19": - version "5.3.19" - resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-5.3.19.tgz#c414e4d3781aeb06298715220012f552a36dff29" - integrity sha512-hKshig/u5Nj9fWy0OsyU04yqCxr0A9pydOHIassr4fpLAaePIN2YvqCqE2V+TxQHjZUnowSSIhbXrGt0DI5q2A== +"@storybook/node-logger@5.3.21": + version "5.3.21" + resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-5.3.21.tgz#f11d45042bd57dc69e9037d8f374d9fd0aad8071" + integrity sha512-8xibncy873JXePCK5MC0qem1MKtWI1Lc4hv6rwURSwYpZtkO7yElay3XAFGUSfz8qFJkoDBmMTxBR3fp4Dln7g== dependencies: "@types/npmlog" "^4.1.2" chalk "^3.0.0" @@ -2267,16 +2270,16 @@ semver "^7.3.2" "@storybook/react@^5.3.19": - version "5.3.19" - resolved "https://registry.yarnpkg.com/@storybook/react/-/react-5.3.19.tgz#ad7e7a5538399e2794cdb5a1b844a2b77c10bd09" - integrity sha512-OBRUqol3YLQi/qE55x2pWkv4YpaAmmfj6/Km+7agx+og+oNQl0nnlXy7r27X/4j3ERczzURa5pJHtSjwiNaJNw== + version "5.3.21" + resolved "https://registry.yarnpkg.com/@storybook/react/-/react-5.3.21.tgz#f7f364d3d3adc70746a12cf8b6614952f41d4bd0" + integrity sha512-A50F8dDZxyLGa/dE3q0Zxt7T5r9UbomoSclqw7oJTO9GI76QOu7GfsoWrEL2gTEDAmqXreLVQqGuTLQhBz0rlA== dependencies: "@babel/plugin-transform-react-constant-elements" "^7.6.3" "@babel/preset-flow" "^7.0.0" "@babel/preset-react" "^7.0.0" - "@storybook/addons" "5.3.19" - "@storybook/core" "5.3.19" - "@storybook/node-logger" "5.3.19" + "@storybook/addons" "5.3.21" + "@storybook/core" "5.3.21" + "@storybook/node-logger" "5.3.21" "@svgr/webpack" "^4.0.3" "@types/webpack-env" "^1.15.0" babel-plugin-add-react-displayname "^0.0.5" @@ -2293,10 +2296,10 @@ ts-dedent "^1.1.0" webpack "^4.33.0" -"@storybook/router@5.3.19": - version "5.3.19" - resolved "https://registry.yarnpkg.com/@storybook/router/-/router-5.3.19.tgz#0f783b85658f99e4007f74347ad7ef17dbf7fc3a" - integrity sha512-yNClpuP7BXQlBTRf6Ggle3/R349/k6kvI5Aim4jf6X/2cFVg2pzBXDAF41imNm9PcvdxwabQLm6I48p7OvKr/w== +"@storybook/router@5.3.21": + version "5.3.21" + resolved "https://registry.yarnpkg.com/@storybook/router/-/router-5.3.21.tgz#32b08e5daa90a6ffa024bb670b874525a712a901" + integrity sha512-c29m5UikK5Q1lyd6FltOGFhIcpd6PIb855YS3OUNe3F6ZA1tfJ+aNKrCBc65d1c+fvCGG76dYYYv0RvwEmKXXg== dependencies: "@reach/router" "^1.2.1" "@storybook/csf" "0.0.1" @@ -2308,14 +2311,14 @@ qs "^6.6.0" util-deprecate "^1.0.2" -"@storybook/theming@5.3.19": - version "5.3.19" - resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-5.3.19.tgz#177d9819bd64f7a1a6ea2f1920ffa5baf9a5f467" - integrity sha512-ecG+Rq3hc1GOzKHamYnD4wZ0PEP9nNg0mXbC3RhbxfHj+pMMCWWmx9B2Uu75SL1PTT8WcfkFO0hU/0IO84Pzlg== +"@storybook/theming@5.3.21": + version "5.3.21" + resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-5.3.21.tgz#ae2dc101aa57c3be4df1724ae729e11bad118e0b" + integrity sha512-FZbxjizqdO9lV5LUixPio/7+6UdPiswCzTJn8Hcot9uwwgfnrViRdN7xyjmSYRqv9nHP3OlYbtdeCAgZ4aPq8g== dependencies: "@emotion/core" "^10.0.20" "@emotion/styled" "^10.0.17" - "@storybook/client-logger" "5.3.19" + "@storybook/client-logger" "5.3.21" core-js "^3.0.1" deep-object-diff "^1.1.0" emotion-theming "^10.0.19" @@ -2326,20 +2329,20 @@ resolve-from "^5.0.0" ts-dedent "^1.1.0" -"@storybook/ui@5.3.19": - version "5.3.19" - resolved "https://registry.yarnpkg.com/@storybook/ui/-/ui-5.3.19.tgz#ac03b67320044a3892ee784111d4436b61874332" - integrity sha512-r0VxdWab49nm5tzwvveVDnsHIZHMR76veYOu/NHKDUZ5hnQl1LMG1YyMCFFa7KiwD/OrZxRWr6/Ma7ep9kR4Gw== +"@storybook/ui@5.3.21": + version "5.3.21" + resolved "https://registry.yarnpkg.com/@storybook/ui/-/ui-5.3.21.tgz#b42568e03353b47aaab1b6449311f38858585f81" + integrity sha512-OUf8JYY9LN+XfzLSZE6KtboITGDL6C8Z0W9QOXM5LJwFLv4PkANK/f9qsB5vVHFm7vhoO96butFzs6SjTKhxkw== dependencies: "@emotion/core" "^10.0.20" - "@storybook/addons" "5.3.19" - "@storybook/api" "5.3.19" - "@storybook/channels" "5.3.19" - "@storybook/client-logger" "5.3.19" - "@storybook/components" "5.3.19" - "@storybook/core-events" "5.3.19" - "@storybook/router" "5.3.19" - "@storybook/theming" "5.3.19" + "@storybook/addons" "5.3.21" + "@storybook/api" "5.3.21" + "@storybook/channels" "5.3.21" + "@storybook/client-logger" "5.3.21" + "@storybook/components" "5.3.21" + "@storybook/core-events" "5.3.21" + "@storybook/router" "5.3.21" + "@storybook/theming" "5.3.21" copy-to-clipboard "^3.0.8" core-js "^3.0.1" core-js-pure "^3.0.1" @@ -2477,20 +2480,23 @@ defer-to-connect "^1.0.1" "@testing-library/dom@^7.22.3": - version "7.23.0" - resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-7.23.0.tgz#c54c0fa53705ad867bcefb52fc0c96487fbc10f6" - integrity sha512-H5m090auYH+obdZmsaYLrSWC5OauWD2CvNbz88KBxQJoXgkJzbU0DpAG8BS7Evj5WqCC3nAAKrLS6vw0ljUYLg== + version "7.26.0" + resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-7.26.0.tgz#da4d052dc426a4ccc916303369c6e7552126f680" + integrity sha512-fyKFrBbS1IigaE3FV21LyeC7kSGF84lqTlSYdKmGaHuK2eYQ/bXVPM5vAa2wx/AU1iPD6oQHsxy2QQ17q9AMCg== dependencies: + "@babel/code-frame" "^7.10.4" "@babel/runtime" "^7.10.3" "@types/aria-query" "^4.2.0" aria-query "^4.2.2" + chalk "^4.1.0" dom-accessibility-api "^0.5.1" + lz-string "^1.4.4" pretty-format "^26.4.2" -"@testing-library/jest-dom@5.11.4": - version "5.11.4" - resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.11.4.tgz#f325c600db352afb92995c2576022b35621ddc99" - integrity sha512-6RRn3epuweBODDIv3dAlWjOEHQLpGJHB2i912VS3JQtsD22+ENInhdDNl4ZZQiViLlIfFinkSET/J736ytV9sw== +"@testing-library/jest-dom@5.11.5": + version "5.11.5" + resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.11.5.tgz#44010f37f4b1e15f9d433963b515db0b05182fc8" + integrity sha512-XI+ClHR864i6p2kRCEyhvpVejuer+ObVUF4cjCvRSF88eOMIfqw7RoS9+qoRhyigGswMfT64L6Nt0Ufotxbwtg== dependencies: "@babel/runtime" "^7.9.2" "@types/testing-library__jest-dom" "^5.9.1" @@ -2538,9 +2544,9 @@ loglevel "^1.6.8" "@toruslabs/torus-embed@^1.8.2": - version "1.8.3" - resolved "https://registry.yarnpkg.com/@toruslabs/torus-embed/-/torus-embed-1.8.3.tgz#3c1e5c6ca755628381529402650f00e5c0e4d407" - integrity sha512-wI+mDF3oj6QsHPcLrApVEXmddBcIzrB5JMdxR/V5Jag2Rlk3bRFf7VkxI4mXz0+Qf+He6+fa2VXWCITZMlaDeQ== + version "1.8.6" + resolved "https://registry.yarnpkg.com/@toruslabs/torus-embed/-/torus-embed-1.8.6.tgz#ad149d7fbea996540921a6025b528402744b19bc" + integrity sha512-7u23gH783weAqAJMTBS9unDsBhL/n6KKkRbTVNCRF9lAqMNznxj+yYWGaVxJkmL5x6gl3P5jbLgji8/KoV0I1w== dependencies: "@chaitanyapotti/random-id" "^1.0.3" "@toruslabs/fetch-node-details" "^2.3.0" @@ -2575,29 +2581,81 @@ memory-cache "^0.2.0" web3-utils "^1.2.11" -"@truffle/blockchain-utils@^0.0.11": - version "0.0.11" - resolved "https://registry.yarnpkg.com/@truffle/blockchain-utils/-/blockchain-utils-0.0.11.tgz#9886f4cb7a9f20deded4451ac78f8567ae5c0d75" - integrity sha512-9MyQ/20M96clhIcC7fVFIckGSB8qMsmcdU6iYt98HXJ9GOLNKsCaJFz1OVsJncVreYwTUhoEXTrVBc8zrmPDJQ== +"@truffle/blockchain-utils@^0.0.25": + version "0.0.25" + resolved "https://registry.yarnpkg.com/@truffle/blockchain-utils/-/blockchain-utils-0.0.25.tgz#f4b320890113d282f25f1a1ecd65b94a8b763ac1" + integrity sha512-XA5m0BfAWtysy5ChHyiAf1fXbJxJXphKk+eZ9Rb9Twi6fn3Jg4gnHNwYXJacYFEydqT5vr2s4Ou812JHlautpw== + dependencies: + source-map-support "^0.5.19" -"@truffle/contract-schema@^3.0.14": - version "3.2.3" - resolved "https://registry.yarnpkg.com/@truffle/contract-schema/-/contract-schema-3.2.3.tgz#f7d940c0187918083fe5a605ee81ac17efe287a8" - integrity sha512-dnR5wtqCBKVfJDX5g+sCUiDF1WDucpxoWsr6ZOwq9JqgyS4Gz7iJi1wMegMmcDctOykoKjsju6iAOi+HObrkfg== +"@truffle/codec@^0.7.1": + version "0.7.1" + resolved "https://registry.yarnpkg.com/@truffle/codec/-/codec-0.7.1.tgz#2ef0fa40109040796afbebb8812c872122100ae4" + integrity sha512-mNd6KnW6J0UB1zafGBXDlTEbCMvWpmPAJmzv7aF/nAIaN/F8UePSCiQ1OTQP39Rprj6GFiCCaWVnBAwum6UGSg== + dependencies: + big.js "^5.2.2" + bn.js "^4.11.8" + borc "^2.1.2" + debug "^4.1.0" + lodash.clonedeep "^4.5.0" + lodash.escaperegexp "^4.1.2" + lodash.partition "^4.6.0" + lodash.sum "^4.0.2" + semver "^6.3.0" + source-map-support "^0.5.19" + utf8 "^3.0.0" + web3-utils "1.2.9" + +"@truffle/contract-schema@^3.3.1": + version "3.3.1" + resolved "https://registry.yarnpkg.com/@truffle/contract-schema/-/contract-schema-3.3.1.tgz#66385613d54d76df68a7a2c431fa9d352145a74b" + integrity sha512-xGBiYiCCW8hKuD/G8xb9w0WUuhdJDmQuz18A2Ens3Y8MO+jWA+Zw7xxZjCtiXAu9440Fj2V/BCXWcV6RxGKgBQ== dependencies: ajv "^6.10.0" crypto-js "^3.1.9-1" debug "^4.1.0" -"@truffle/error@^0.0.6": - version "0.0.6" - resolved "https://registry.yarnpkg.com/@truffle/error/-/error-0.0.6.tgz#75d499845b4b3a40537889e7d04c663afcaee85d" - integrity sha512-QUM9ZWiwlXGixFGpV18g5I6vua6/r+ZV9W/5DQA5go9A3eZUNPHPaTKMIQPJLYn6+ZV5jg5H28zCHq56LHF3yA== +"@truffle/contract@4.2.26": + version "4.2.26" + resolved "https://registry.yarnpkg.com/@truffle/contract/-/contract-4.2.26.tgz#c68ae32ff5c96a3dccafb3a196a21ba7374151e2" + integrity sha512-MKVb7Prf6IsY8rVjIBGrcAJoSTbw3Hx18htq+PuGZT/12r6ntzhnehKplaQbZC7thTFn7Yv1qrj3cdJ6insZ2A== + dependencies: + "@truffle/blockchain-utils" "^0.0.25" + "@truffle/contract-schema" "^3.3.1" + "@truffle/debug-utils" "^4.2.12" + "@truffle/error" "^0.0.11" + "@truffle/interface-adapter" "^0.4.17" + bignumber.js "^7.2.1" + ethereum-ens "^0.8.0" + ethers "^4.0.0-beta.1" + source-map-support "^0.5.19" + web3 "1.2.1" + web3-core-helpers "1.2.1" + web3-core-promievent "1.2.1" + web3-eth-abi "1.2.1" + web3-utils "1.2.1" + +"@truffle/debug-utils@^4.2.12": + version "4.2.13" + resolved "https://registry.yarnpkg.com/@truffle/debug-utils/-/debug-utils-4.2.13.tgz#d4014c0c089ad5b6ff5441f07ddadf5579f4f504" + integrity sha512-c2NG2JINg6tWufNQHUl5mFStLJ8IyG8TV5gu8DTkKSdV8/7D6NwYqFPoqQr9OjO3jJ+siFhXIYUUBd3WEw7vlQ== + dependencies: + "@truffle/codec" "^0.7.1" + "@trufflesuite/chromafi" "^2.2.0" + chalk "^2.4.2" + debug "^4.1.0" + highlight.js "^9.15.8" + highlightjs-solidity "^1.0.18" + +"@truffle/error@^0.0.11": + version "0.0.11" + resolved "https://registry.yarnpkg.com/@truffle/error/-/error-0.0.11.tgz#2789c0042d7e796dcbb840c7a9b5d2bcd8e0e2d8" + integrity sha512-ju6TucjlJkfYMmdraYY/IBJaFb+Sa+huhYtOoyOJ+G29KcgytUVnDzKGwC7Kgk6IsxQMm62Mc1E0GZzFbGGipw== "@truffle/hdwallet-provider@^1.0.0", "@truffle/hdwallet-provider@^1.0.27": - version "1.0.42" - resolved "https://registry.yarnpkg.com/@truffle/hdwallet-provider/-/hdwallet-provider-1.0.42.tgz#0c906b67f0950ce8b85aaa50e5bf02418c517e82" - integrity sha512-Q6+Pn6x9oLE0lTk72xC4V7il/UoI2i6dy8kSfh4xjYkE585SO9sc7ndXqX5K+epPolr7UAndEe7Lv6mHjiPmsQ== + version "1.1.0" + resolved "https://registry.yarnpkg.com/@truffle/hdwallet-provider/-/hdwallet-provider-1.1.0.tgz#caca30225ee18c69fdd6403b4de23ca316796922" + integrity sha512-hblrGs0w/S8Ij7BrmUju6GEK35NWQs2Hxc6SMBrz4chlwd9vcBzMWCGoCtYwYOi2d6o9jOv17+bLk9KNlTZR8g== dependencies: "@trufflesuite/web3-provider-engine" "15.0.13-1" "@types/web3" "^1.0.20" @@ -2610,6 +2668,37 @@ ethereumjs-wallet "^0.6.3" source-map-support "^0.5.19" +"@truffle/interface-adapter@^0.4.17": + version "0.4.18" + resolved "https://registry.yarnpkg.com/@truffle/interface-adapter/-/interface-adapter-0.4.18.tgz#1aac45596997d208085d5168f82b990624610646" + integrity sha512-P9JVSYD/CX3V+NgTWu+Bf71sLh8pMwrCpbiYRB93pRw/1H3ZTvt5iDC2MVvVxCs8FkSiy4OZzQK/DJ8+hXAmYw== + dependencies: + bn.js "^4.11.8" + ethers "^4.0.32" + source-map-support "^0.5.19" + web3 "1.2.9" + +"@trufflesuite/chromafi@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@trufflesuite/chromafi/-/chromafi-2.2.0.tgz#18cceacbb44f1e22ec956dd7ad21a2ed414b09c7" + integrity sha512-km4Px34wZ015PDjAK0wfYBx+zoCE4qR3AY9NWLUvtjnnzhCUkaRFCpZdvwDEyB75EzFBoLwV9iiqboz+mMXwBA== + dependencies: + ansi-mark "^1.0.0" + ansi-regex "^3.0.0" + array-uniq "^1.0.3" + camelcase "^4.1.0" + chalk "^2.3.2" + cheerio "^1.0.0-rc.2" + detect-indent "^5.0.0" + he "^1.1.1" + highlight.js "^9.12.0" + husky "^0.14.3" + lodash.merge "^4.6.2" + min-indent "^1.0.0" + strip-ansi "^4.0.0" + strip-indent "^2.0.0" + super-split "^1.1.0" + "@trufflesuite/eth-json-rpc-filters@^4.1.2-1": version "4.1.2-1" resolved "https://registry.yarnpkg.com/@trufflesuite/eth-json-rpc-filters/-/eth-json-rpc-filters-4.1.2-1.tgz#61ab78c52e98a883e5cf086925b34a30297b1824" @@ -2704,9 +2793,9 @@ integrity sha512-iIgQNzCm0v7QMhhe4Jjn9uRh+I6GoPmt03CbEtwx3ao8/EfoQcmgtqH4vQ5Db/lxiIGaWDv6nwvunuh0RyX0+A== "@types/babel__core@^7.1.0", "@types/babel__core@^7.1.7": - version "7.1.9" - resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.9.tgz#77e59d438522a6fb898fa43dc3455c6e72f3963d" - integrity sha512-sY2RsIJ5rpER1u3/aQ8OFSI7qGIy8o1NEEbgb2UaJcvOtXOMpd39ko723NBpjQFg9SIX7TXtjejZVGeIMLhoOw== + version "7.1.10" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.10.tgz#ca58fc195dd9734e77e57c6f2df565623636ab40" + integrity sha512-x8OM8XzITIMyiwl5Vmo2B1cR1S1Ipkyv4mdlbJjMa1lmuKvKY9FrBbEANIaMlnWn5Rf7uO+rC/VgYabNkE17Hw== dependencies: "@babel/parser" "^7.1.0" "@babel/types" "^7.0.0" @@ -2715,24 +2804,24 @@ "@types/babel__traverse" "*" "@types/babel__generator@*": - version "7.6.1" - resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.1.tgz#4901767b397e8711aeb99df8d396d7ba7b7f0e04" - integrity sha512-bBKm+2VPJcMRVwNhxKu8W+5/zT7pwNEqeokFOmbvVSqGzFneNxYcEBro9Ac7/N9tlsaPYnZLK8J1LWKkMsLAew== + version "7.6.2" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.2.tgz#f3d71178e187858f7c45e30380f8f1b7415a12d8" + integrity sha512-MdSJnBjl+bdwkLskZ3NGFp9YcXGx5ggLpQQPqtgakVhsWK0hTtNYhjpZLlWQTviGTvF8at+Bvli3jV7faPdgeQ== dependencies: "@babel/types" "^7.0.0" "@types/babel__template@*": - version "7.0.2" - resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.0.2.tgz#4ff63d6b52eddac1de7b975a5223ed32ecea9307" - integrity sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg== + version "7.0.3" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.0.3.tgz#b8aaeba0a45caca7b56a5de9459872dde3727214" + integrity sha512-uCoznIPDmnickEi6D0v11SBpW0OuVqHJCa7syXqQHy5uktSCreIlt0iglsCnmvz8yCb38hGcWeseA8cWJSwv5Q== dependencies: "@babel/parser" "^7.1.0" "@babel/types" "^7.0.0" "@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": - version "7.0.13" - resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.0.13.tgz#1874914be974a492e1b4cb00585cabb274e8ba18" - integrity sha512-i+zS7t6/s9cdQvbqKDARrcbrPvtJGlbYsMkazo03nTAK3RX9FNrLllXys22uiTGJapPOTZTQ35nHh4ISph4SLQ== + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.0.15.tgz#db9e4238931eb69ef8aab0ad6523d4d4caa39d03" + integrity sha512-Pzh9O3sTK8V6I1olsXpCfj2k/ygO2q1X0vhhnDrEQyYLHZesWz+zMZMVcwXLCYf0U36EtmyYaFGPfXlTtDHe3A== dependencies: "@babel/types" "^7.3.0" @@ -2743,25 +2832,15 @@ dependencies: "@types/node" "*" -"@types/color-name@^1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" - integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== - "@types/debug@^4.1.5": version "4.1.5" resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.5.tgz#b14efa8852b7768d898906613c23f688713e02cd" integrity sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ== -"@types/eslint-visitor-keys@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" - integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag== - "@types/fs-extra@^9.0.1": - version "9.0.1" - resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-9.0.1.tgz#91c8fc4c51f6d5dbe44c2ca9ab09310bd00c7918" - integrity sha512-B42Sxuaz09MhC3DDeW5kubRcQ5by4iuVQ0cRRWM2lggLzAa/KVom0Aft/208NgMvNQQZ86s5rVcqDdn/SH0/mg== + version "9.0.2" + resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-9.0.2.tgz#e1e1b578c48e8d08ae7fc36e552b94c6f4621609" + integrity sha512-jp0RI6xfZpi5JL8v7WQwpBEQTq63RqW2kxwTZt+m27LcJqQdPVU1yGnT1ZI4EtCDynQQJtIGyQahkiCGCS7e+A== dependencies: "@types/node" "*" @@ -2774,9 +2853,9 @@ "@types/node" "*" "@types/history@*": - version "4.7.7" - resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.7.tgz#613957d900fab9ff84c8dfb24fa3eef0c2a40896" - integrity sha512-2xtoL22/3Mv6a70i4+4RB7VgbDDORoWwjcqeNysojZA0R7NK17RbY5Gof/2QiFfJgX+KkWghbwJ+d/2SB8Ndzg== + version "4.7.8" + resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.8.tgz#49348387983075705fe8f4e02fb67f7daaec4934" + integrity sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA== "@types/history@4.6.2": version "4.6.2" @@ -2792,9 +2871,9 @@ hoist-non-react-statics "^3.3.0" "@types/html-minifier-terser@^5.0.0": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-5.1.0.tgz#551a4589b6ee2cc9c1dff08056128aec29b94880" - integrity sha512-iYCgjm1dGPRuo12+BStjd1HiVQqhlRhWDOQigNxn023HcjnhsiFz9pc6CzJj4HwDCSQca9bxTL4PxJDbkdm3PA== + version "5.1.1" + resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz#3c9ee980f1a10d6021ae6632ca3e79ca2ec4fb50" + integrity sha512-giAlZwstKbmvMk1OO7WXSj4OZ0keXAcl2TQq4LWHiiPH2ByaH7WeUzng+Qej8UPxxv+8lRTuouo0iaNDBuzIBA== "@types/is-function@^1.0.0": version "1.0.0" @@ -2829,14 +2908,6 @@ "@types/istanbul-lib-report" "*" "@types/jest@*": - version "26.0.10" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.10.tgz#8faf7e9756c033c39014ae76a7329efea00ea607" - integrity sha512-i2m0oyh8w/Lum7wWK/YOZJakYF8Mx08UaKA1CtbmFeDquVhAEdA7znacsVSf2hJ1OQ/OfVMGN90pw/AtzF8s/Q== - dependencies: - jest-diff "^25.2.1" - pretty-format "^25.2.1" - -"@types/jest@^26.0.14": version "26.0.14" resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.14.tgz#078695f8f65cb55c5a98450d65083b2b73e5a3f3" integrity sha512-Hz5q8Vu0D288x3iWXePSn53W7hAjP0H7EQ6QvDO9c7t46mR0lNOLlfuwQ+JkVxuhygHzlzPX+0jKdA3ZgSh+Vg== @@ -2844,10 +2915,18 @@ jest-diff "^25.2.1" pretty-format "^25.2.1" -"@types/json-schema@^7.0.3", "@types/json-schema@^7.0.4": - version "7.0.5" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.5.tgz#dcce4430e64b443ba8945f0290fb564ad5bac6dd" - integrity sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ== +"@types/jest@^26.0.15": + version "26.0.15" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.15.tgz#12e02c0372ad0548e07b9f4e19132b834cb1effe" + integrity sha512-s2VMReFXRg9XXxV+CW9e5Nz8fH2K1aEhwgjUqPPbQd7g95T0laAcvLv032EhFHIa5GHsZ8W7iJEQVaJq6k3Gog== + dependencies: + jest-diff "^26.0.0" + pretty-format "^26.0.0" + +"@types/json-schema@^7.0.3", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.6": + version "7.0.6" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0" + integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw== "@types/json5@^0.0.29": version "0.0.29" @@ -2862,9 +2941,9 @@ "@types/lodash" "*" "@types/lodash@*": - version "4.14.159" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.159.tgz#61089719dc6fdd9c5cb46efc827f2571d1517065" - integrity sha512-gF7A72f7WQN33DpqOWw9geApQPh4M3PxluMtaHxWHXEGSN12/WbcEk/eNSqWNQcQhF66VSZ06vCF94CrHwXJDg== + version "4.14.162" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.162.tgz#65d78c397e0d883f44afbf1f7ba9867022411470" + integrity sha512-alvcho1kRUnnD1Gcl4J+hK0eencvzq9rmzvFPRmP5rPHx9VVsJj6bKLTATPVf9ktgv4ujzh7T+XWKp+jhuODig== "@types/minimatch@*": version "3.0.3" @@ -2879,24 +2958,24 @@ "@types/node" "*" "@types/node@*": - version "14.0.27" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.27.tgz#a151873af5a5e851b51b3b065c9e63390a9e0eb1" - integrity sha512-kVrqXhbclHNHGu9ztnAwSncIgJv/FaxmzXJvGXNdcCpV1b8u1/Mi6z6m0vwy0LzKeXFTPLH0NzwmoJ3fNCIq0g== - -"@types/node@14.11.2": version "14.11.2" resolved "https://registry.yarnpkg.com/@types/node/-/node-14.11.2.tgz#2de1ed6670439387da1c9f549a2ade2b0a799256" integrity sha512-jiE3QIxJ8JLNcb1Ps6rDbysDhN4xa8DJJvuC9prr6w+1tIh+QAbYyNF3tyiZNLDBIuBCf4KEcV2UvQm/V60xfA== "@types/node@^10.12.18", "@types/node@^10.3.2": - version "10.17.28" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.28.tgz#0e36d718a29355ee51cec83b42d921299200f6d9" - integrity sha512-dzjES1Egb4c1a89C7lKwQh8pwjYmlOAG9dW1pBgxEk57tMrLnssOfEthz8kdkNaBd7lIqQx7APm5+mZ619IiCQ== + version "10.17.39" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.39.tgz#ce1122758d0608de8303667cebf171f44192629b" + integrity sha512-dJLCxrpQmgyxYGcl0Ae9MTsQgI22qHHcGFj/8VKu7McJA5zQpnuGjoksnxbo1JxSjW/Nahnl13W8MYZf01CZHA== "@types/node@^12.0.12", "@types/node@^12.12.6", "@types/node@^12.6.1": - version "12.12.54" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.54.tgz#a4b58d8df3a4677b6c08bfbc94b7ad7a7a5f82d1" - integrity sha512-ge4xZ3vSBornVYlDnk7yZ0gK6ChHf/CHB7Gl1I0Jhah8DDnEQqBzgohYG4FX4p81TNirSETOiSyn+y1r9/IR6w== + version "12.12.67" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.67.tgz#4f86badb292e822e3b13730a1f9713ed2377f789" + integrity sha512-R48tgL2izApf+9rYNH+3RBMbRpPeW3N8f0I9HMhggeq4UXwBDqumJ14SDs4ctTMhG11pIOduZ4z3QWGOiMc9Vg== + +"@types/node@^14.14.5": + version "14.14.5" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.5.tgz#e92d3b8f76583efa26c1a63a21c9d3c1143daa29" + integrity sha512-H5Wn24s/ZOukBmDn03nnGTp18A60ny9AmCwnEcgJiTgSGsCO7k+NWP7zjCCbhlcnVCoI+co52dUAt9GMhOSULw== "@types/npmlog@^4.1.2": version "4.1.2" @@ -2931,24 +3010,24 @@ integrity sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug== "@types/reach__router@^1.2.3": - version "1.3.5" - resolved "https://registry.yarnpkg.com/@types/reach__router/-/reach__router-1.3.5.tgz#14e1e981cccd3a5e50dc9e969a72de0b9d472f6d" - integrity sha512-h0NbqXN/tJuBY/xggZSej1SKQEstbHO7J/omt1tYoFGmj3YXOodZKbbqD4mNDh7zvEGYd7YFrac1LTtAr3xsYQ== + version "1.3.6" + resolved "https://registry.yarnpkg.com/@types/reach__router/-/reach__router-1.3.6.tgz#413417ce74caab331c70ce6a03a4c825188e4709" + integrity sha512-RHYataCUPQnt+GHoASyRLq6wmZ0n8jWlBW8Lxcwd30NN6vQfbmTeoSDfkgxO0S1lEzArp8OFDsq5KIs7FygjtA== dependencies: "@types/history" "*" "@types/react" "*" -"@types/react-dom@^16.9.6": - version "16.9.8" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.8.tgz#fe4c1e11dfc67155733dfa6aa65108b4971cb423" - integrity sha512-ykkPQ+5nFknnlU6lDd947WbQ6TE3NNzbQAkInC2EKY1qeYdTKp7onFusmYZb+ityzx2YviqT6BXSu+LyWWJwcA== +"@types/react-dom@^16.9.9": + version "16.9.9" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.9.tgz#d2d0a6f720a0206369ccbefff752ba37b9583136" + integrity sha512-jE16FNWO3Logq/Lf+yvEAjKzhpST/Eac8EMd1i4dgZdMczfgqC8EjpxwNgEe3SExHYLliabXDh9DEhhqnlXJhg== dependencies: "@types/react" "*" "@types/react-native@*": - version "0.63.8" - resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.63.8.tgz#73ec087122c64c309eeaf150b565b8d755f0fb1f" - integrity sha512-QRwGFRTyGafRVTUS+0GYyJrlpmS3boyBaFI0ULSc+mh/lQNxrzbdQvoL2k5X7+t9hxyqA4dTQAlP6l0ir/fNJQ== + version "0.63.25" + resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.63.25.tgz#a08bbe17a75cce993f52655a8fe75f30bf77e965" + integrity sha512-cRm+1iQecewpFYOArYJoM1qGd0JpFJ6f97KqIy9H2GawAdWkgyarSk8CBy4SMt2WOtPkysCu2EG7UwIT3vNeaA== dependencies: "@types/react" "*" @@ -2962,10 +3041,10 @@ hoist-non-react-statics "^3.3.0" redux "^4.0.0" -"@types/react-router-dom@^5.1.5": - version "5.1.5" - resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.1.5.tgz#7c334a2ea785dbad2b2dcdd83d2cf3d9973da090" - integrity sha512-ArBM4B1g3BWLGbaGvwBGO75GNFbLDUthrDojV2vHLih/Tq8M+tgvY1DSwkuNrPSwdp/GUL93WSEpTZs8nVyJLw== +"@types/react-router-dom@^5.1.6": + version "5.1.6" + resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.1.6.tgz#07b14e7ab1893a837c8565634960dc398564b1fb" + integrity sha512-gjrxYqxz37zWEdMVvQtWPFMFj1dRDb4TGOcgyOfSXTrEXdF92L00WE3C471O3TV/RF1oskcStkXsOU0Ete4s/g== dependencies: "@types/history" "*" "@types/react" "*" @@ -3008,10 +3087,10 @@ "@types/prop-types" "*" csstype "^3.0.2" -"@types/react@^16.9.49": - version "16.9.49" - resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.49.tgz#09db021cf8089aba0cdb12a49f8021a69cce4872" - integrity sha512-DtLFjSj0OYAdVLBbyjhuV9CdGVHCkHn2R+xr3XkBvK2rS1Y1tkc14XSGjYgm5Fjjr90AxH9tiSzc1pCFMGO06g== +"@types/react@^16.9.54": + version "16.9.54" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.54.tgz#140280c31825287ee74e9da95285b91c5a2e471d" + integrity sha512-GhawhYraQZpGFO2hVMArjPrYbnA/6+DS8SubK8IPhhVClmKqANihsRenOm5E0mvqK0m/BKoqVktA1O1+Xvlz9w== dependencies: "@types/prop-types" "*" csstype "^3.0.2" @@ -3031,9 +3110,9 @@ "@types/node" "*" "@types/semver@^7.3.1": - version "7.3.3" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.3.tgz#3ad6ed949e7487e7bda6f886b4a2434a2c3d7b1a" - integrity sha512-jQxClWFzv9IXdLdhSaTf16XI3NYe6zrEbckSpb5xhKfPbWgIyAY0AFyWWWfaiDcBuj3UHmMkCIwSRqpKMTZL2Q== + version "7.3.4" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.4.tgz#43d7168fec6fa0988bb1a513a697b29296721afb" + integrity sha512-+nVsLKlcUCeMzD2ufHEYuJ9a2ovstb6Dp52A5VsoKxDXgvE051XgHI/33I1EymwkRGQkwnA0LkhnUzituGs4EQ== "@types/source-list-map@*": version "0.1.2" @@ -3045,10 +3124,10 @@ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw== -"@types/styled-components@^5.1.3": - version "5.1.3" - resolved "https://registry.yarnpkg.com/@types/styled-components/-/styled-components-5.1.3.tgz#6fab3d9c8f7d9a15cbb89d379d850c985002f363" - integrity sha512-HGpirof3WOhiX17lb61Q/tpgqn48jxO8EfZkdJ8ueYqwLbK2AHQe/G08DasdA2IdKnmwOIP1s9X2bopxKXgjRw== +"@types/styled-components@^5.1.4": + version "5.1.4" + resolved "https://registry.yarnpkg.com/@types/styled-components/-/styled-components-5.1.4.tgz#11f167dbde268635c66adc89b5a5db2e69d75384" + integrity sha512-78f5Zuy0v/LTQNOYfpH+CINHpchzMMmAt9amY2YNtSgsk1TmlKm8L2Wijss/mtTrsUAVTm2CdGB8VOM65vA8xg== dependencies: "@types/hoist-non-react-statics" "*" "@types/react" "*" @@ -3061,16 +3140,16 @@ integrity sha512-W+bw9ds02rAQaMvaLYxAbJ6cvguW/iJXNT6lTssS1ps6QdrMKttqEAMEG/b5CR8TZl3/L7/lH0ZV5nNR1LXikA== "@types/testing-library__jest-dom@^5.9.1": - version "5.9.2" - resolved "https://registry.yarnpkg.com/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.9.2.tgz#59e4771a1cf87d51e89a5cc8195cd3b647cba322" - integrity sha512-K7nUSpH/5i8i0NagTJ+uFUDRueDlnMNhJtMjMwTGPPSqyImbWC/hgKPDCKt6Phu2iMJg2kWqlax+Ucj2DKMwpA== + version "5.9.4" + resolved "https://registry.yarnpkg.com/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.9.4.tgz#f5e009540bbea7b82745e352038c60db7320c327" + integrity sha512-6spmpkKOCVCO9XolAR23gfv09Nfd4QByRM3WbnYnPhVfjmOzEKlNrcj6GqFLZKduUvtJIH7Mf5t2TY6rs93zDA== dependencies: "@types/jest" "*" "@types/uglify-js@*": - version "3.9.3" - resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.9.3.tgz#d94ed608e295bc5424c9600e6b8565407b6b4b6b" - integrity sha512-KswB5C7Kwduwjj04Ykz+AjvPcfgv/37Za24O2EDzYNbwyzOo8+ydtvzUfZ5UMguiVu29Gx44l1A6VsPPcmYu9w== + version "3.11.0" + resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.11.0.tgz#2868d405cc45cd9dc3069179052103032c33afbc" + integrity sha512-I0Yd8TUELTbgRHq2K65j8rnDPAzAP+DiaF/syLem7yXwYLsHZhPd+AM2iXsWmf9P2F2NlFCgl5erZPQx9IbM9Q== dependencies: source-map "^0.6.1" @@ -3082,23 +3161,23 @@ web3 "*" "@types/webpack-env@^1.15.0": - version "1.15.2" - resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.15.2.tgz#927997342bb9f4a5185a86e6579a0a18afc33b0a" - integrity sha512-67ZgZpAlhIICIdfQrB5fnDvaKFcDxpKibxznfYRVAT4mQE41Dido/3Ty+E3xGBmTogc5+0Qb8tWhna+5B8z1iQ== + version "1.15.3" + resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.15.3.tgz#fb602cd4c2f0b7c0fb857e922075fdf677d25d84" + integrity sha512-5oiXqR7kwDGZ6+gmzIO2lTC+QsriNuQXZDWNYRV3l2XRN/zmPgnC21DLSx2D05zvD8vnXW6qUg7JnXZ4I6qLVQ== "@types/webpack-sources@*": - version "1.4.2" - resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-1.4.2.tgz#5d3d4dea04008a779a90135ff96fb5c0c9e6292c" - integrity sha512-77T++JyKow4BQB/m9O96n9d/UUHWLQHlcqXb9Vsf4F1+wKNrrlWNFPDLKNT92RJnCSL6CieTc+NDXtCVZswdTw== + version "2.0.0" + resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-2.0.0.tgz#08216ab9be2be2e1499beaebc4d469cec81e82a7" + integrity sha512-a5kPx98CNFRKQ+wqawroFunvFqv7GHm/3KOI52NY9xWADgc8smu4R6prt4EU/M4QfVjvgBkMqU4fBhw3QfMVkg== dependencies: "@types/node" "*" "@types/source-list-map" "*" source-map "^0.7.3" "@types/webpack@^4.41.13", "@types/webpack@^4.41.8": - version "4.41.21" - resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.21.tgz#cc685b332c33f153bb2f5fc1fa3ac8adeb592dee" - integrity sha512-2j9WVnNrr/8PLAB5csW44xzQSJwS26aOnICsP3pSGCEdsu6KYtfQ6QJsVUKHWRnm1bL7HziJsfh5fHqth87yKA== + version "4.41.22" + resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.22.tgz#ff9758a17c6bd499e459b91e78539848c32d0731" + integrity sha512-JQDJK6pj8OMV9gWOnN1dcLCyU9Hzs6lux0wBO4lr1+gyEhIBR9U3FMrz12t2GPkg110XAxEAw2WHF6g7nZIbRQ== dependencies: "@types/anymatch" "*" "@types/node" "*" @@ -3113,121 +3192,88 @@ integrity sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw== "@types/yargs@^13.0.0": - version "13.0.10" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-13.0.10.tgz#e77bf3fc73c781d48c2eb541f87c453e321e5f4b" - integrity sha512-MU10TSgzNABgdzKvQVW1nuuT+sgBMWeXNc3XOs5YXV5SDAK+PPja2eUuBNB9iqElu03xyEDqlnGw0jgl4nbqGQ== + version "13.0.11" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-13.0.11.tgz#def2f0c93e4bdf2c61d7e34899b17e34be28d3b1" + integrity sha512-NRqD6T4gktUrDi1o1wLH3EKC1o2caCr7/wR87ODcbVITQF106OM3sFN92ysZ++wqelOd1CTzatnOBRDYYG6wGQ== dependencies: "@types/yargs-parser" "*" "@types/yargs@^15.0.0", "@types/yargs@^15.0.5": - version "15.0.5" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.5.tgz#947e9a6561483bdee9adffc983e91a6902af8b79" - integrity sha512-Dk/IDOPtOgubt/IaevIUbTgV7doaKkoorvOyYM2CMwuDyP89bekI7H4xLIwunNYiK9jhCkmc6pUrJk3cj2AB9w== + version "15.0.8" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.8.tgz#7644904cad7427eb704331ea9bf1ee5499b82e23" + integrity sha512-b0BYzFUzBpOhPjpl1wtAHU994jBeKF4TKVlT7ssFv44T617XNcPdRoG4AzHLVshLzlrF7i3lTelH7UbuNYV58Q== dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@3.9.1": - version "3.9.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.9.1.tgz#8cf27b6227d12d66dd8dc1f1a4b04d1daad51c2e" - integrity sha512-XIr+Mfv7i4paEdBf0JFdIl9/tVxyj+rlilWIfZ97Be0lZ7hPvUbS5iHt9Glc8kRI53dsr0PcAEudbf8rO2wGgg== +"@typescript-eslint/eslint-plugin@4.6.0", "@typescript-eslint/eslint-plugin@^2.10.0", "@typescript-eslint/eslint-plugin@^4.5.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.6.0.tgz#210cd538bb703f883aff81d3996961f5dba31fdb" + integrity sha512-1+419X+Ynijytr1iWI+/IcX/kJryc78YNpdaXR1aRO1sU3bC0vZrIAF1tIX7rudVI84W7o7M4zo5p1aVt70fAg== dependencies: - "@typescript-eslint/experimental-utils" "3.9.1" + "@typescript-eslint/experimental-utils" "4.6.0" + "@typescript-eslint/scope-manager" "4.6.0" debug "^4.1.1" functional-red-black-tree "^1.0.1" regexpp "^3.0.0" semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/eslint-plugin@^2.10.0": - version "2.34.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.34.0.tgz#6f8ce8a46c7dea4a6f1d171d2bb8fbae6dac2be9" - integrity sha512-4zY3Z88rEE99+CNvTbXSyovv2z9PNOVffTWD2W8QF5s2prBQtwN2zadqERcrHpcR7O/+KMI3fcTAmUUhK/iQcQ== - dependencies: - "@typescript-eslint/experimental-utils" "2.34.0" - functional-red-black-tree "^1.0.1" - regexpp "^3.0.0" - tsutils "^3.17.1" - -"@typescript-eslint/experimental-utils@2.34.0": - version "2.34.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.34.0.tgz#d3524b644cdb40eebceca67f8cf3e4cc9c8f980f" - integrity sha512-eS6FTkq+wuMJ+sgtuNTtcqavWXqsflWcfBnlYhg/nS4aZ1leewkXGbvBhaapn1q6qf4M71bsR1tez5JTRMuqwA== +"@typescript-eslint/experimental-utils@4.6.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.6.0.tgz#f750aef4dd8e5970b5c36084f0a5ca2f0db309a4" + integrity sha512-pnh6Beh2/4xjJVNL+keP49DFHk3orDHHFylSp3WEjtgW3y1U+6l+jNnJrGlbs6qhAz5z96aFmmbUyKhunXKvKw== dependencies: "@types/json-schema" "^7.0.3" - "@typescript-eslint/typescript-estree" "2.34.0" + "@typescript-eslint/scope-manager" "4.6.0" + "@typescript-eslint/types" "4.6.0" + "@typescript-eslint/typescript-estree" "4.6.0" eslint-scope "^5.0.0" eslint-utils "^2.0.0" -"@typescript-eslint/experimental-utils@3.9.1": - version "3.9.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-3.9.1.tgz#b140b2dc7a7554a44f8a86fb6fe7cbfe57ca059e" - integrity sha512-lkiZ8iBBaYoyEKhCkkw4SAeatXyBq9Ece5bZXdLe1LWBUwTszGbmbiqmQbwWA8cSYDnjWXp9eDbXpf9Sn0hLAg== - dependencies: - "@types/json-schema" "^7.0.3" - "@typescript-eslint/types" "3.9.1" - "@typescript-eslint/typescript-estree" "3.9.1" - eslint-scope "^5.0.0" - eslint-utils "^2.0.0" - -"@typescript-eslint/parser@3.9.1": - version "3.9.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-3.9.1.tgz#ab7983abaea0ae138ff5671c7c7739d8a191b181" - integrity sha512-y5QvPFUn4Vl4qM40lI+pNWhTcOWtpZAJ8pOEQ21fTTW4xTJkRplMjMRje7LYTXqVKKX9GJhcyweMz2+W1J5bMg== - dependencies: - "@types/eslint-visitor-keys" "^1.0.0" - "@typescript-eslint/experimental-utils" "3.9.1" - "@typescript-eslint/types" "3.9.1" - "@typescript-eslint/typescript-estree" "3.9.1" - eslint-visitor-keys "^1.1.0" - -"@typescript-eslint/parser@^2.10.0": - version "2.34.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.34.0.tgz#50252630ca319685420e9a39ca05fe185a256bc8" - integrity sha512-03ilO0ucSD0EPTw2X4PntSIRFtDPWjrVq7C3/Z3VQHRC7+13YB55rcJI3Jt+YgeHbjUdJPcPa7b23rXCBokuyA== - dependencies: - "@types/eslint-visitor-keys" "^1.0.0" - "@typescript-eslint/experimental-utils" "2.34.0" - "@typescript-eslint/typescript-estree" "2.34.0" - eslint-visitor-keys "^1.1.0" - -"@typescript-eslint/types@3.9.1": - version "3.9.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-3.9.1.tgz#b2a6eaac843cf2f2777b3f2464fb1fbce5111416" - integrity sha512-15JcTlNQE1BsYy5NBhctnEhEoctjXOjOK+Q+rk8ugC+WXU9rAcS2BYhoh6X4rOaXJEpIYDl+p7ix+A5U0BqPTw== - -"@typescript-eslint/typescript-estree@2.34.0": - version "2.34.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.34.0.tgz#14aeb6353b39ef0732cc7f1b8285294937cf37d5" - integrity sha512-OMAr+nJWKdlVM9LOqCqh3pQQPwxHAN7Du8DR6dmwCrAmxtiXQnhHJ6tBNtf+cggqfo51SG/FCwnKhXCIM7hnVg== +"@typescript-eslint/parser@4.6.0", "@typescript-eslint/parser@^2.10.0", "@typescript-eslint/parser@^4.5.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.6.0.tgz#7e9ff7df2f21d5c8f65f17add3b99eeeec33199d" + integrity sha512-Dj6NJxBhbdbPSZ5DYsQqpR32MwujF772F2H3VojWU6iT4AqL4BKuoNWOPFCoSZvCcADDvQjDpa6OLDAaiZPz2Q== dependencies: + "@typescript-eslint/scope-manager" "4.6.0" + "@typescript-eslint/types" "4.6.0" + "@typescript-eslint/typescript-estree" "4.6.0" debug "^4.1.1" - eslint-visitor-keys "^1.1.0" - glob "^7.1.6" + +"@typescript-eslint/scope-manager@4.6.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.6.0.tgz#b7d8b57fe354047a72dfb31881d9643092838662" + integrity sha512-uZx5KvStXP/lwrMrfQQwDNvh2ppiXzz5TmyTVHb+5TfZ3sUP7U1onlz3pjoWrK9konRyFe1czyxObWTly27Ang== + dependencies: + "@typescript-eslint/types" "4.6.0" + "@typescript-eslint/visitor-keys" "4.6.0" + +"@typescript-eslint/types@4.6.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.6.0.tgz#157ca925637fd53c193c6bf226a6c02b752dde2f" + integrity sha512-5FAgjqH68SfFG4UTtIFv+rqYJg0nLjfkjD0iv+5O27a0xEeNZ5rZNDvFGZDizlCD1Ifj7MAbSW2DPMrf0E9zjA== + +"@typescript-eslint/typescript-estree@4.6.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.6.0.tgz#85bd98dcc8280511cfc5b2ce7b03a9ffa1732b08" + integrity sha512-s4Z9qubMrAo/tw0CbN0IN4AtfwuehGXVZM0CHNMdfYMGBDhPdwTEpBrecwhP7dRJu6d9tT9ECYNaWDHvlFSngA== + dependencies: + "@typescript-eslint/types" "4.6.0" + "@typescript-eslint/visitor-keys" "4.6.0" + debug "^4.1.1" + globby "^11.0.1" is-glob "^4.0.1" lodash "^4.17.15" semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/typescript-estree@3.9.1": - version "3.9.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-3.9.1.tgz#fd81cada74bc8a7f3a2345b00897acb087935779" - integrity sha512-IqM0gfGxOmIKPhiHW/iyAEXwSVqMmR2wJ9uXHNdFpqVvPaQ3dWg302vW127sBpAiqM9SfHhyS40NKLsoMpN2KA== +"@typescript-eslint/visitor-keys@4.6.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.6.0.tgz#fb05d6393891b0a089b243fc8f9fb8039383d5da" + integrity sha512-38Aa9Ztl0XyFPVzmutHXqDMCu15Xx8yKvUo38Gu3GhsuckCh3StPI5t2WIO9LHEsOH7MLmlGfKUisU8eW1Sjhg== dependencies: - "@typescript-eslint/types" "3.9.1" - "@typescript-eslint/visitor-keys" "3.9.1" - debug "^4.1.1" - glob "^7.1.6" - is-glob "^4.0.1" - lodash "^4.17.15" - semver "^7.3.2" - tsutils "^3.17.1" - -"@typescript-eslint/visitor-keys@3.9.1": - version "3.9.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-3.9.1.tgz#92af3747cdb71509199a8f7a4f00b41d636551d1" - integrity sha512-zxdtUjeoSh+prCpogswMwVUJfEFmCOjdzK9rpNjNBfm6EyPt99x3RrJoBOGZO23FCt0WPKUCOL5mb/9D5LjdwQ== - dependencies: - eslint-visitor-keys "^1.1.0" + "@typescript-eslint/types" "4.6.0" + eslint-visitor-keys "^2.0.0" "@unilogin/provider@^0.6.1": version "0.6.1" @@ -3237,92 +3283,97 @@ "@restless/sanitizers" "^0.2.5" reactive-properties "^0.1.11" -"@walletconnect/client@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@walletconnect/client/-/client-1.2.1.tgz#0f942aae30675e995da2007f2644261a44f7ccf9" - integrity sha512-GpldbPXgd9VTSUfE+2BDEsKr6JPUU17j+m2a9IMGeysWWmcIb0fYh5DDFrbBPLYigJY8XgFwk4YLdtPafMlueQ== +"@walletconnect/client@^1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@walletconnect/client/-/client-1.3.1.tgz#5b8160fe15615ca7017a6be1b125d885e39ddf12" + integrity sha512-G3bgGaALxffiZB6HaCAX6BvIRFYSOClvdcCN3fKfczEYYkOHrrgeEksY7oX5GXXZdNNn4s/zt+5yWnySuA+3Zg== dependencies: - "@walletconnect/core" "^1.2.1" - "@walletconnect/iso-crypto" "^1.2.1" - "@walletconnect/types" "^1.2.1" - "@walletconnect/utils" "^1.2.1" + "@walletconnect/core" "^1.3.1" + "@walletconnect/iso-crypto" "^1.3.1" + "@walletconnect/types" "^1.3.1" + "@walletconnect/utils" "^1.3.1" -"@walletconnect/core@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-1.2.1.tgz#0ba1664b8b6ee5f5e85222b7260ab798375e5327" - integrity sha512-Gj1BNYd6kHahmWwwmA9gsodxNxO2A1Gn1HVRwcALIa98d+rHl3R1D1SomXmKwN2LzPn66c/hqpoqNuSk+LQuvQ== +"@walletconnect/core@^1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-1.3.1.tgz#7f7c692ad4c7de37544c610ad0d863dddcb23b19" + integrity sha512-v0RAW4RqcMBNRkX2e6VcOVpBl5dX0oT7w3vWMiHUHwuMMnuoRXoXi1oEiib0K8VyqYuXSaeuEaaHUhYUEcvvtQ== dependencies: - "@walletconnect/socket-transport" "^1.2.1" - "@walletconnect/types" "^1.2.1" - "@walletconnect/utils" "^1.2.1" + "@walletconnect/socket-transport" "^1.3.1" + "@walletconnect/types" "^1.3.1" + "@walletconnect/utils" "^1.3.1" -"@walletconnect/http-connection@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@walletconnect/http-connection/-/http-connection-1.2.1.tgz#8db5610de9fc9b7afb29e745c0e83bf1ccc598fb" - integrity sha512-5zUhB5WAX9TGQlPE9uci5lYkh4DrY/Yt1BhnP0mICujLAyQSKsMEf+fy74hd+hYtRLbmCMj8igClqhOqqCK9AQ== +"@walletconnect/http-connection@^1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@walletconnect/http-connection/-/http-connection-1.3.1.tgz#fd5af6a3cb6014cd99b48ea827a8664b61df7f8a" + integrity sha512-Hyis8FAgtnkhF1k0oKDhe+rgDq/rPFHry/jdQckvQLZZAEwoNZLJ5s0jjWK2Yl9YP3EZybXat3H63VboieZiUA== dependencies: - "@walletconnect/types" "^1.2.1" - "@walletconnect/utils" "^1.2.1" + "@walletconnect/types" "^1.3.1" + "@walletconnect/utils" "^1.3.1" xhr2-cookies "1.1.0" -"@walletconnect/iso-crypto@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@walletconnect/iso-crypto/-/iso-crypto-1.2.1.tgz#acfc421717ab688e5b82f981750ee1cb1b2f8dcd" - integrity sha512-l5btVlALo+k3kjZN2MveE6+7Ert1Z030yn1wOdSyAvgCZaPWU0jfJDm0QzXS/oKY+5nRtSQROtWK0PfpQ9/7dg== +"@walletconnect/iso-crypto@^1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@walletconnect/iso-crypto/-/iso-crypto-1.3.1.tgz#fce8d1235a2059728dfb87a8d0dfac205f295937" + integrity sha512-u5YGYsaSQuRBSxX1623220Bc3KZDgqkIwXCt7PV8UyzhuSFp+SQGj6Cux5SoVlaUChr0iWMzkibLrKSof3yStA== dependencies: - "@walletconnect/types" "^1.2.1" - "@walletconnect/utils" "^1.2.1" + "@walletconnect/types" "^1.3.1" + "@walletconnect/utils" "^1.3.1" eccrypto-js "5.2.0" -"@walletconnect/mobile-registry@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@walletconnect/mobile-registry/-/mobile-registry-1.2.1.tgz#2dfe9005856f371d8e980fe50a97e988cc5da6d6" - integrity sha512-ivSIZ24pHPVWY96vA6mc1IQJ0qbYM4IoXLx7sLnjdTOxogTF4uBO3O104O2tvpnxemqt+9jaPHlfQNOTOBEdvA== +"@walletconnect/mobile-registry@^1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@walletconnect/mobile-registry/-/mobile-registry-1.3.1.tgz#9fdea8d7ac4655a63c59a84ed76780530820808d" + integrity sha512-wOGSqf1xCoMRvsLZ7IEYBwCnojtCbsSd+dc6dJCVWkFcRptjmnInIrP7bg7YIllUCSusWhKjPCYyRsyffNYCyQ== -"@walletconnect/qrcode-modal@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@walletconnect/qrcode-modal/-/qrcode-modal-1.2.1.tgz#af24df90e3fb6d30ad3b6bce7cf00ab30946d088" - integrity sha512-HqystXm9SW1o/e7vAVJ0LgJJK48PznHPriCOHBV7gmVO+0k8Our4vG1RJ04cgXQdlLiUtbArQAxN7icZm/PrUQ== +"@walletconnect/qrcode-modal@^1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@walletconnect/qrcode-modal/-/qrcode-modal-1.3.1.tgz#d546531fc5b18431470aeeab071939c861f8e8a2" + integrity sha512-PHwRNgnRtATtBuuxX8nsRGbSrsevB4gMHd4armJFbGM/XmIcJe89L5X0KVapb5Z8HP8qdbJ6/sMqKBPVEezkgQ== dependencies: - "@walletconnect/mobile-registry" "^1.2.1" - "@walletconnect/types" "^1.2.1" - "@walletconnect/utils" "^1.2.1" + "@walletconnect/mobile-registry" "^1.3.1" + "@walletconnect/types" "^1.3.1" + "@walletconnect/utils" "^1.3.1" preact "10.4.1" qrcode "1.4.4" -"@walletconnect/socket-transport@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@walletconnect/socket-transport/-/socket-transport-1.2.1.tgz#54ca7290a110e59cc3a524e634815e61274b5f1a" - integrity sha512-zJNMWSaPnBwfpTe39h3xcXiOqw99WdwLrX7wkUMUTzn3AK6m2B9SySPtS6TSis+2BcFX3kgnDSLeDv2qQJ8oSw== +"@walletconnect/socket-transport@^1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@walletconnect/socket-transport/-/socket-transport-1.3.1.tgz#b3854225fdae9af0d865d002f7e032cd89ae4678" + integrity sha512-JV/ZJbFGmPJaHcT5GpiuoOxdB5xlkY7SW6J0GDqIBxI92mlOoQ5ea6xY5ullI5WUXZJUIvXcgUHf/KpPG9VN/w== dependencies: - "@walletconnect/types" "^1.2.1" + "@walletconnect/types" "^1.3.1" ws "7.3.0" -"@walletconnect/types@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-1.2.1.tgz#460aa682b3d9502762041de6aca608585f633f6b" - integrity sha512-9P+QSdYMrlgoGGiByKAKlLUAbAVDE10LzCJVFp3KYoqZLsxl0OjM5Hr1YpYT9X8ws+KIWQhp7ui8+ZzC0EakLg== +"@walletconnect/types@^1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-1.3.1.tgz#fefa3d5cfb2e68c0439d07f7d32134f692775a80" + integrity sha512-lf8hAFT7OIEgyc0FkLZPPjF4bMql+Svg4SNKj1a1oMTCdA+NPlqMUwOqcIJeIolULZbpFl3DkX3omSy8RNIbkg== -"@walletconnect/utils@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-1.2.1.tgz#2e48983c16ea6dfa30515ba266f8cce1de822bad" - integrity sha512-FWK7O874QC6ZrSjMnh0k+4lt22LRKwmP56puY02XQh7HJ1bkgmWXAd2shgtVXAOr/5sfimYkUGwmhNRp31443g== +"@walletconnect/utils@^1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-1.3.1.tgz#88418856d28bdc683d53d0fad2acdc70b5c88528" + integrity sha512-r1pfAeXc6WCNbHf5zgVPenM8au+bQOYot6tdwpSDZAfdP0KtwmZ9Uro2uP8ykRWovTj2gGgKE+GMh9yVVTraaQ== dependencies: - "@walletconnect/types" "^1.2.1" + "@walletconnect/types" "^1.3.1" detect-browser "5.1.0" enc-utils "2.1.0" js-sha3 "0.8.0" + query-string "6.13.5" + rpc-payload-id "1.0.0" + safe-json-utils "1.0.0" + window-getters "1.0.0" + window-metadata "1.0.0" "@walletconnect/web3-provider@^1.1.0": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@walletconnect/web3-provider/-/web3-provider-1.2.1.tgz#5fd968fc62cd6f9ac2a0df3d16b6b1ed0dee35f9" - integrity sha512-uvRiiHU1etEHv/O8WvzGCR1Dtwms8Ic8bMOFs0cogc+fywsxD0dZ/xSxZwwKHqWFY8euERpw+FDhFPcYOfOr8w== + version "1.3.1" + resolved "https://registry.yarnpkg.com/@walletconnect/web3-provider/-/web3-provider-1.3.1.tgz#031c1cc7a52ea12287f1278929501ee91847e237" + integrity sha512-sOLtEbNLFrD8DgbvE0P/vRrmdPbF6Zufhn3gAo6/lxDQGH0ajHGmkl04sq/qcwMHKK0zHjYKRSFEG2VqNIThHg== dependencies: - "@walletconnect/client" "^1.2.1" - "@walletconnect/http-connection" "^1.2.1" - "@walletconnect/qrcode-modal" "^1.2.1" - "@walletconnect/types" "^1.2.1" - "@walletconnect/utils" "^1.2.1" + "@walletconnect/client" "^1.3.1" + "@walletconnect/http-connection" "^1.3.1" + "@walletconnect/qrcode-modal" "^1.3.1" + "@walletconnect/types" "^1.3.1" + "@walletconnect/utils" "^1.3.1" web3-provider-engine "15.0.12" "@webassemblyjs/ast@1.8.5": @@ -3639,9 +3690,9 @@ integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== abab@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.4.tgz#6dfa57b417ca06d21b2478f0e638302f99c2405c" - integrity sha512-Eu9ELJWCz/c1e9gTiCY+FceWxcqzjYEbqMgtndnuSqZSUCOL73TWNK2mHfIj4Cw2E/ongOp+JISVNCmovt2KYQ== + version "2.0.5" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" + integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q== abbrev@1: version "1.1.1" @@ -3679,9 +3730,9 @@ acorn-globals@^4.1.0, acorn-globals@^4.3.0: acorn-walk "^6.0.1" acorn-jsx@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.2.0.tgz#4c66069173d6fdd68ed85239fc256226182b2ebe" - integrity sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ== + version "5.3.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b" + integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== acorn-walk@^6.0.1: version "6.2.0" @@ -3694,14 +3745,14 @@ acorn@^5.5.3: integrity sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg== acorn@^6.0.1, acorn@^6.0.4, acorn@^6.2.1, acorn@^6.4.1: - version "6.4.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474" - integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA== + version "6.4.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" + integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== acorn@^7.1.1, acorn@^7.4.0: - version "7.4.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.0.tgz#e1ad486e6c54501634c6c397c5c121daa383607c" - integrity sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w== + version "7.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" + integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== address@1.1.2, address@^1.0.1: version "1.1.2" @@ -3765,15 +3816,15 @@ ajv-errors@^1.0.0: resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== -ajv-keywords@^3.1.0, ajv-keywords@^3.4.1: +ajv-keywords@^3.1.0, ajv-keywords@^3.4.1, ajv-keywords@^3.5.2: version "3.5.2" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== -ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.0, ajv@^6.12.2, ajv@^6.12.3: - version "6.12.4" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.4.tgz#0614facc4522127fa713445c6bfd3ebd376e2234" - integrity sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ== +ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.0, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== dependencies: fast-deep-equal "^3.1.1" fast-json-stable-stringify "^2.0.0" @@ -3824,6 +3875,17 @@ ansi-html@0.0.7: resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e" integrity sha1-gTWEAhliqenm/QOflA0S9WynhZ4= +ansi-mark@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/ansi-mark/-/ansi-mark-1.0.4.tgz#1cd4ba8d57f15f109d6aaf6ec9ca9786c8a4ee6c" + integrity sha1-HNS6jVfxXxCdaq9uycqXhsik7mw= + dependencies: + ansi-regex "^3.0.0" + array-uniq "^1.0.3" + chalk "^2.3.2" + strip-ansi "^4.0.0" + super-split "^1.1.0" + ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" @@ -3857,11 +3919,10 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1: color-convert "^1.9.0" ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" - integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== dependencies: - "@types/color-name" "^1.1.1" color-convert "^2.0.1" ansi-to-html@^0.6.11: @@ -3892,26 +3953,26 @@ anymatch@~3.1.1: normalize-path "^3.0.0" picomatch "^2.0.4" -app-builder-bin@3.5.9: - version "3.5.9" - resolved "https://registry.yarnpkg.com/app-builder-bin/-/app-builder-bin-3.5.9.tgz#a3ac0c25286bac68357321cb2eaf7128b0bc0a4f" - integrity sha512-NSjtqZ3x2kYiDp3Qezsgukx/AUzKPr3Xgf9by4cYt05ILWGAptepeeu0Uv+7MO+41o6ujhLixTou8979JGg2Kg== +app-builder-bin@3.5.10: + version "3.5.10" + resolved "https://registry.yarnpkg.com/app-builder-bin/-/app-builder-bin-3.5.10.tgz#4a7f9999fccc0c435b6284ae1366bc76a17c4a7d" + integrity sha512-Jd+GW68lR0NeetgZDo47PdWBEPdnD+p0jEa7XaxjRC8u6Oo/wgJsfKUkORRgr2NpkD19IFKN50P6JYy04XHFLQ== -app-builder-lib@22.8.0: - version "22.8.0" - resolved "https://registry.yarnpkg.com/app-builder-lib/-/app-builder-lib-22.8.0.tgz#342a8976f50ae35cfd07412dbfd4f6c895b32eac" - integrity sha512-RGaIRjCUrqkmh6QOGsyekQPEOaVynHfmeh8JZuyUymFYUOFdzBbPamkA2nhBVBTkkgfjRHsxK7LhedFKPzvWEQ== +app-builder-lib@22.8.1: + version "22.8.1" + resolved "https://registry.yarnpkg.com/app-builder-lib/-/app-builder-lib-22.8.1.tgz#02cd14c0a83d3a758675d28c327731832b2c0bc1" + integrity sha512-D/ac1+vuGIAAwEeTtXl8b+qWl7Gz/IQatFyzYl2ocag/7N8LqUjKzZFJJISQPWt6PFDPDH0oCj8/GMh63aV0yw== dependencies: "7zip-bin" "~5.0.3" "@develar/schema-utils" "~2.6.5" async-exit-hook "^2.0.1" bluebird-lst "^1.0.9" - builder-util "22.8.0" + builder-util "22.8.1" builder-util-runtime "8.7.2" chromium-pickle-js "^0.2.0" - debug "^4.1.1" + debug "^4.2.0" ejs "^3.1.3" - electron-publish "22.8.0" + electron-publish "22.8.1" fs-extra "^9.0.1" hosted-git-info "^3.0.5" is-ci "^2.0.0" @@ -4041,7 +4102,12 @@ array-union@^1.0.1: dependencies: array-uniq "^1.0.1" -array-uniq@^1.0.1: +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +array-uniq@^1.0.1, array-uniq@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= @@ -4135,15 +4201,19 @@ ast-types-flow@0.0.7, ast-types-flow@^0.0.7: resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0= -ast-types@0.11.3: - version "0.11.3" - resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.11.3.tgz#c20757fe72ee71278ea0ff3d87e5c2ca30d9edf8" - integrity sha512-XA5o5dsNw8MhyW0Q7MWXJWc4oOzZKbdsEJq45h7c8q/d9DwWZ5F2ugUc1PuMLPGsUnphCt/cNDHu8JeBbxf1qA== - ast-types@^0.13.2: - version "0.13.3" - resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.13.3.tgz#50da3f28d17bdbc7969a3a2d83a0e4a72ae755a7" - integrity sha512-XTZ7xGML849LkQP86sWdQzfhwbt3YwIO6MqbX9mUNYY98VKaaVZP7YNNm70IpwecbkkxmfC5IYAzOQ/2p29zRA== + version "0.13.4" + resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.13.4.tgz#ee0d77b343263965ecc3fb62da16e7222b2b6782" + integrity sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w== + dependencies: + tslib "^2.0.1" + +ast-types@^0.14.2: + version "0.14.2" + resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.14.2.tgz#600b882df8583e3cd4f2df5fa20fa83759d4bdfd" + integrity sha512-O0yuUDnZeQDL+ncNGlJ78BiO4jnYI3bvMsD5prT0/nsgijG/LpNBIr63gTjVTNsiGkgQhiyCShTgxt8oXOrklA== + dependencies: + tslib "^2.0.1" astral-regex@^1.0.0: version "1.0.0" @@ -4225,9 +4295,9 @@ atob@^2.1.2: integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== authereum@^0.0.4-beta.157: - version "0.0.4-beta.182" - resolved "https://registry.yarnpkg.com/authereum/-/authereum-0.0.4-beta.182.tgz#14ce9ca491a38c019b5c0b6644725e07cbcc5cc9" - integrity sha512-bVZZcosYvqwkHIx5l2HOkfQtsUcKEJSZdSl5ESzL/n70iu3pMWTxl/CYBpa81VbLci7x4e9Sq+NX7UXNfIG3kA== + version "0.0.4-beta.201" + resolved "https://registry.yarnpkg.com/authereum/-/authereum-0.0.4-beta.201.tgz#ea380efc6d231dc4222dc20cd9395b02318dd0c3" + integrity sha512-9zyS2nDsO5nW/8dD8SbGUbZLX76O5Zrx6Zq4aZG+Waa3Vsn3Bj82tn8HLPdECmd5heSOmaSEi5TNsS/sGBSiGw== dependencies: async "3.2.0" bn.js "5.1.2" @@ -4235,7 +4305,6 @@ authereum@^0.0.4-beta.157: ethers "4.0.47" eventemitter3 "4.0.0" is-buffer "2.0.4" - moment "2.24.0" penpal "4.1.1" pify "4.0.1" querystring "0.2.0" @@ -4694,13 +4763,13 @@ babel-plugin-named-asset-import@^0.3.1, babel-plugin-named-asset-import@^0.3.6: integrity sha512-1aGDUfL1qOOIoqk9QKGIo2lANk+C7ko/fqH0uIyC71x3PEGz0uVP8ISgfEsFuG+FKmjHTvFK/nNM8dowpmUxLA== babel-plugin-react-docgen@^4.0.0, babel-plugin-react-docgen@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/babel-plugin-react-docgen/-/babel-plugin-react-docgen-4.1.0.tgz#1dfa447dac9ca32d625a123df5733a9e47287c26" - integrity sha512-vzpnBlfGv8XOhJM2zbPyyqw2OLEbelgZZsaaRRTpVwNKuYuc+pUg4+dy7i9gCRms0uOQn4osX571HRcCJMJCmA== + version "4.2.1" + resolved "https://registry.yarnpkg.com/babel-plugin-react-docgen/-/babel-plugin-react-docgen-4.2.1.tgz#7cc8e2f94e8dc057a06e953162f0810e4e72257b" + integrity sha512-UQ0NmGHj/HAqi5Bew8WvNfCk8wSsmdgNd8ZdMjBCICtyCJCq9LiqgqvjCYe570/Wg7AQArSq1VQ60Dd/CHN7mQ== dependencies: + ast-types "^0.14.2" lodash "^4.17.15" react-docgen "^5.0.0" - recast "^0.14.7" "babel-plugin-styled-components@>= 1": version "1.11.1" @@ -5255,16 +5324,21 @@ big.js@^5.2.2: resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== -bignumber.js@9.0.0, bignumber.js@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.0.tgz#805880f84a329b5eac6e7cb6f8274b6d82bdf075" - integrity sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A== +bignumber.js@9.0.1, bignumber.js@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.1.tgz#8d7ba124c882bfd8e43260c67475518d0689e4e5" + integrity sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA== bignumber.js@^7.2.1: version "7.2.1" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-7.2.1.tgz#80c048759d826800807c4bfd521e50edbba57a5f" integrity sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ== +bignumber.js@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.0.tgz#805880f84a329b5eac6e7cb6f8274b6d82bdf075" + integrity sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A== + "bignumber.js@git+https://github.com/frozeman/bignumber.js-nolookahead.git": version "2.0.7" resolved "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934" @@ -5299,17 +5373,17 @@ bip66@^1.1.5: safe-buffer "^5.0.1" bl@^1.0.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" - integrity sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA== + version "1.2.3" + resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.3.tgz#1e8dd80142eac80d7158c9dccc047fb620e035e7" + integrity sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww== dependencies: readable-stream "^2.3.5" safe-buffer "^5.1.1" -bl@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/bl/-/bl-4.0.2.tgz#52b71e9088515d0606d9dd9cc7aa48dc1f98e73a" - integrity sha512-j4OH8f6Qg2bGuWfRiltT2HYGx0e1QcBTrK9KAHNMwMZdQnDZFk0ZSYIpADjYCB3U12nicC5tVJwSIhwOWjb4RQ== +bl@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.0.3.tgz#12d6287adc29080e22a705e5764b2a9522cdc489" + integrity sha512-fs4G6/Hu4/EE+F75J8DuN/0IpQqNjAdC7aEQv7Qt8MHGUH7Ckv2MwTEEeN9QehD0pfIDkMI1bkHYkKy7xHyKIg== dependencies: buffer "^5.5.0" inherits "^2.0.4" @@ -5327,7 +5401,7 @@ bluebird-lst@^1.0.9: dependencies: bluebird "^3.5.5" -bluebird@^3.3.5, bluebird@^3.5.0, bluebird@^3.5.5: +bluebird@^3.3.5, bluebird@^3.4.7, bluebird@^3.5.0, bluebird@^3.5.5: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== @@ -5357,10 +5431,10 @@ bn.js@^5.1.1, bn.js@^5.1.2: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.3.tgz#beca005408f642ebebea80b042b4d18d2ac0ee6b" integrity sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ== -bnc-onboard@1.13.1: - version "1.13.1" - resolved "https://registry.yarnpkg.com/bnc-onboard/-/bnc-onboard-1.13.1.tgz#281629e15c01ab47425f9494b33c4ce28a9db01e" - integrity sha512-Mv06oWNjkjDNU3vR8l/aJFKTBya5lj6vPfYcl9ONpyyaoY/8neZS4icQrFeRv9nDvENVz6esxcYAyX62f0+rwA== +bnc-onboard@1.13.2: + version "1.13.2" + resolved "https://registry.yarnpkg.com/bnc-onboard/-/bnc-onboard-1.13.2.tgz#031b8ec87582d686b3493be97c410e09efda3557" + integrity sha512-r5vkY0GkD/gKULyjCSlgVkRFBEtFrqN+EVncm1e8i1sUdeQLiXjr0YNQ/xOcsyfH2MxYVEIcGoaQSH/NzeX0+g== dependencies: "@ledgerhq/hw-app-eth" "^5.21.0" "@ledgerhq/hw-transport-u2f" "^5.21.0" @@ -5423,15 +5497,28 @@ boolbase@^1.0.0, boolbase@~1.0.0: resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= -boolean@^3.0.0, boolean@^3.0.1: +boolean@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/boolean/-/boolean-3.0.1.tgz#35ecf2b4a2ee191b0b44986f14eb5f052a5cbb4f" integrity sha512-HRZPIjPcbwAVQvOTxR4YE3o8Xs98NqbbL1iEZDCz7CL8ql0Lt5iOyJFxfnAB0oFs8Oh02F/lLlg30Mexv46LjA== +borc@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/borc/-/borc-2.1.2.tgz#6ce75e7da5ce711b963755117dd1b187f6f8cf19" + integrity sha512-Sy9eoUi4OiKzq7VovMn246iTo17kzuyHJKomCfpWMlI6RpfN1gk95w7d7gH264nApVLg0HZfcpz62/g4VH1Y4w== + dependencies: + bignumber.js "^9.0.0" + buffer "^5.5.0" + commander "^2.15.0" + ieee754 "^1.1.13" + iso-url "~0.4.7" + json-text-sequence "~0.1.0" + readable-stream "^3.6.0" + bowser@^2.10.0: - version "2.10.0" - resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.10.0.tgz#be3736f161c4bb8b10958027ab99465d2a811198" - integrity sha512-OCsqTQboTEWWsUjcp5jLSw2ZHsBiv2C105iFs61bOT0Hnwi9p7/uuXdd7mu8RYcarREfdjNN+8LitmEHATsLYg== + version "2.11.0" + resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.11.0.tgz#5ca3c35757a7aa5771500c70a73a9f91ef420a8f" + integrity sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA== boxen@^4.1.0, boxen@^4.2.0: version "4.2.0" @@ -5539,14 +5626,6 @@ browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: bn.js "^4.1.0" randombytes "^2.0.1" -browserify-sha3@^0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/browserify-sha3/-/browserify-sha3-0.0.4.tgz#086c47b8c82316c9d47022c26185954576dd8e26" - integrity sha1-CGxHuMgjFsnUcCLCYYWVRXbdjiY= - dependencies: - js-sha3 "^0.6.1" - safe-buffer "^5.1.1" - browserify-sign@^4.0.0: version "4.2.1" resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" @@ -5597,14 +5676,14 @@ browserslist@^3.2.6: electron-to-chromium "^1.3.47" browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.6.2, browserslist@^4.6.4, browserslist@^4.8.5, browserslist@^4.9.1: - version "4.14.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.0.tgz#2908951abfe4ec98737b72f34c3bcedc8d43b000" - integrity sha512-pUsXKAF2lVwhmtpeA3LJrZ76jXuusrNyhduuQs7CDFf9foT4Y38aQOserd2lMe5DSSrjf3fx34oHwryuvxAUgQ== + version "4.14.5" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.5.tgz#1c751461a102ddc60e40993639b709be7f2c4015" + integrity sha512-Z+vsCZIvCBvqLoYkBFTwEYH3v5MCQbsAjp50ERycpOjnPmolg1Gjy4+KaWWpm8QOJt9GHkhdqAl14NpCX73CWA== dependencies: - caniuse-lite "^1.0.30001111" - electron-to-chromium "^1.3.523" - escalade "^3.0.2" - node-releases "^1.1.60" + caniuse-lite "^1.0.30001135" + electron-to-chromium "^1.3.571" + escalade "^3.1.0" + node-releases "^1.1.61" bs58@^4.0.0: version "4.0.1" @@ -5694,6 +5773,13 @@ buffer@^5.0.5, buffer@^5.2.1, buffer@^5.4.3, buffer@^5.5.0, buffer@^5.6.0: base64-js "^1.0.2" ieee754 "^1.1.4" +bufferutil@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.1.tgz#3a177e8e5819a1243fe16b63a199951a7ad8d4a7" + integrity sha512-xowrxvpxojqkagPcWRQVXZl0YXhRhAtBEIq3VoER1NH5Mw1n1o0ojdspp+GS2J//2gCVyrzQDApQ4unGF+QOoA== + dependencies: + node-gyp-build "~3.7.0" + builder-util-runtime@8.7.2: version "8.7.2" resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.7.2.tgz#d93afc71428a12789b437e13850e1fa7da956d72" @@ -5702,19 +5788,19 @@ builder-util-runtime@8.7.2: debug "^4.1.1" sax "^1.2.4" -builder-util@22.8.0: - version "22.8.0" - resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-22.8.0.tgz#01684085d1f2370b1bd182f69cbd007426f63f64" - integrity sha512-H80P1JzVy3TGpi63x81epQDK24XalL034+jAZlrPb5IhLtYmnNNdxCCAVJvg3VjSISd73Y71O+uhqCxWpqbPHw== +builder-util@22.8.1: + version "22.8.1" + resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-22.8.1.tgz#efdfb327dbc22c59aa1e2f55adbe0e771086e839" + integrity sha512-LZG+E1xszMdut5hL5h7RkJQ7yOsQqdhJYgn1wvOP7MmF3MoUPRNDiRodLpYiWlaqZmgYhcfaipR/Mb8F/RqK8w== dependencies: "7zip-bin" "~5.0.3" "@types/debug" "^4.1.5" "@types/fs-extra" "^9.0.1" - app-builder-bin "3.5.9" + app-builder-bin "3.5.10" bluebird-lst "^1.0.9" builder-util-runtime "8.7.2" chalk "^4.1.0" - debug "^4.1.1" + debug "^4.2.0" fs-extra "^9.0.1" is-ci "^2.0.0" js-yaml "^3.14.0" @@ -5904,15 +5990,10 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001035, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001111: - version "1.0.30001114" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001114.tgz#2e88119afb332ead5eaa330e332e951b1c4bfea9" - integrity sha512-ml/zTsfNBM+T1+mjglWRPgVsu2L76GAaADKX5f4t0pbhttEp0WMawJsHDYlFkVZkoA+89uvBRrVrEE4oqenzXQ== - -caniuse-lite@^1.0.30000989: - version "1.0.30001110" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001110.tgz#9003e3c7f5a43ea6f1193d4d5acba0bfb152c71a" - integrity sha512-KqJWeat4rhSHF0ito4yz9q/JuZHkvn71SsBnxge4azjPDbowIjOUnS8i1xpKGxZxU6BFiPqO2hSV2eiCpFQVRw== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30000989, caniuse-lite@^1.0.30001035, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001135: + version "1.0.30001148" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001148.tgz#dc97c7ed918ab33bf8706ddd5e387287e015d637" + integrity sha512-E66qcd0KMKZHNJQt9hiLZGE3J4zuTqE1OnU53miEVtylFbwOEmeA5OsRu90noZful+XGSQOni1aT2tiqu/9yYw== capture-exit@^2.0.0: version "2.0.0" @@ -5999,10 +6080,22 @@ checkpoint-store@^1.1.0: dependencies: functional-red-black-tree "^1.0.1" -chokidar@3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.1.tgz#c84e5b3d18d9a4d77558fef466b1bf16bbeb3450" - integrity sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg== +cheerio@^1.0.0-rc.2: + version "1.0.0-rc.3" + resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.3.tgz#094636d425b2e9c0f4eb91a46c05630c9a1a8bf6" + integrity sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA== + dependencies: + css-select "~1.2.0" + dom-serializer "~0.1.1" + entities "~1.1.1" + htmlparser2 "^3.9.1" + lodash "^4.15.0" + parse5 "^3.0.1" + +chokidar@3.4.2: + version "3.4.2" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.2.tgz#38dc8e658dec3809741eb3ef7bb0a47fe424232d" + integrity sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A== dependencies: anymatch "~3.1.1" braces "~3.0.2" @@ -6010,7 +6103,7 @@ chokidar@3.3.1: is-binary-path "~2.1.0" is-glob "~4.0.1" normalize-path "~3.0.0" - readdirp "~3.3.0" + readdirp "~3.4.0" optionalDependencies: fsevents "~2.1.2" @@ -6034,9 +6127,9 @@ chokidar@^2.0.4, chokidar@^2.1.8: fsevents "^1.2.7" chokidar@^3.3.0, chokidar@^3.4.1: - version "3.4.2" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.2.tgz#38dc8e658dec3809741eb3ef7bb0a47fe424232d" - integrity sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A== + version "3.4.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.3.tgz#c1df38231448e45ca4ac588e6c79573ba6a57d5b" + integrity sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ== dependencies: anymatch "~3.1.1" braces "~3.0.2" @@ -6044,7 +6137,7 @@ chokidar@^3.3.0, chokidar@^3.4.1: is-binary-path "~2.1.0" is-glob "~4.0.1" normalize-path "~3.0.0" - readdirp "~3.4.0" + readdirp "~3.5.0" optionalDependencies: fsevents "~2.1.2" @@ -6065,6 +6158,11 @@ chromium-pickle-js@^0.2.0: resolved "https://registry.yarnpkg.com/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz#04a106672c18b085ab774d983dfa3ea138f22205" integrity sha1-BKEGZywYsIWrd02YPfo+oTjyIgU= +ci-info@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497" + integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A== + ci-info@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" @@ -6122,9 +6220,9 @@ clean-stack@^2.0.0: integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== cli-boxes@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.0.tgz#538ecae8f9c6ca508e3c3c95b453fe93cb4c168d" - integrity sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w== + version "2.2.1" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" + integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== cli-cursor@^2.1.0: version "2.1.0" @@ -6283,21 +6381,21 @@ color-name@^1.0.0, color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -color-string@^1.5.2: - version "1.5.3" - resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.3.tgz#c9bbc5f01b58b5492f3d6857459cb6590ce204cc" - integrity sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw== +color-string@^1.5.4: + version "1.5.4" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.4.tgz#dd51cd25cfee953d138fe4002372cc3d0e504cb6" + integrity sha512-57yF5yt8Xa3czSEW1jfQDE79Idk0+AkN/4KWad6tbdxUmAs3MvjxlWSWD4deYytcRfoZ9nhKyFl1kj5tBvidbw== dependencies: color-name "^1.0.0" simple-swizzle "^0.2.2" color@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/color/-/color-3.1.2.tgz#68148e7f85d41ad7649c5fa8c8106f098d229e10" - integrity sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg== + version "3.1.3" + resolved "https://registry.yarnpkg.com/color/-/color-3.1.3.tgz#ca67fb4e7b97d611dcde39eceed422067d91596e" + integrity sha512-xgXAcTHa2HeFCGLE9Xs/R82hujGtu9Jd9x4NW3T34+OMs7VoPsjwzRczKHvTAHeJwWFwX5j15+MgAppE8ztObQ== dependencies: color-convert "^1.9.1" - color-string "^1.5.2" + color-string "^1.5.4" colorette@^1.2.1: version "1.2.1" @@ -6340,7 +6438,7 @@ commander@3.0.2: resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== -commander@^2.11.0, commander@^2.19.0, commander@^2.20.0, commander@^2.8.1: +commander@^2.11.0, commander@^2.15.0, commander@^2.19.0, commander@^2.20.0, commander@^2.8.1: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== @@ -6858,7 +6956,7 @@ css-select-base-adapter@^0.1.1: resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" integrity sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w== -css-select@^1.1.0: +css-select@^1.1.0, css-select@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" integrity sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg= @@ -6917,9 +7015,9 @@ css-what@2.1: integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== css-what@^3.2.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.3.0.tgz#10fec696a9ece2e591ac772d759aacabac38cd39" - integrity sha512-pv9JPyatiPaQ6pf4OvD/dbfm0o5LviWmwxNWzblYf/1u9QZd0ihV+PMwy5jdQWQ3349kZmKEx9WXuSka2dM4cg== + version "3.4.2" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.4.2.tgz#ea7026fcb01777edbde52124e21f327e7ae950e4" + integrity sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ== css.escape@^1.5.1: version "1.5.1" @@ -7053,9 +7151,9 @@ csstype@^2.5.2, csstype@^2.5.7: integrity sha512-ul26pfSQTZW8dcOnD2iiJssfXw0gdNVX9IJDH/X3K5DGPfj+fUYe3kB+swUY6BF3oZDxaID3AJt+9/ojSAE05A== csstype@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.2.tgz#ee5ff8f208c8cd613b389f7b222c9801ca62b3f7" - integrity sha512-ofovWglpqoqbfLNOTBNZLSbMuGrblAf1efvvArGKOZMBrIoJeu5UsAipQolkijtyQx5MtAzT/J9IHj/CEY1mJw== + version "3.0.3" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.3.tgz#2b410bbeba38ba9633353aff34b05d9755d065f8" + integrity sha512-jPl+wbWPOWJ7SXsWyqGRk3lGecbar0Cb0OvZF/r/ZU011R4YqiRehgkQ9p4eQfo9DSDLqLL3wHwfxeJiuIsNag== currency-flags@2.1.2: version "2.1.2" @@ -7103,10 +7201,10 @@ data-urls@^1.0.0, data-urls@^1.1.0: whatwg-mimetype "^2.2.0" whatwg-url "^7.0.0" -date-fns@2.15.0, date-fns@^2.0.1: - version "2.15.0" - resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.15.0.tgz#424de6b3778e4e69d3ff27046ec136af58ae5d5f" - integrity sha512-ZCPzAMJZn3rNUvvQIMlXhDr4A+Ar07eLeGsGREoWU19a3Pqf5oYa+ccd+B3F6XVtQY6HANMFdOQ8A+ipFnvJdQ== +date-fns@2.16.1, date-fns@^2.0.1: + version "2.16.1" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.16.1.tgz#05775792c3f3331da812af253e1a935851d3834b" + integrity sha512-sAJVKx/FqrLYHAQeN7VpJrPhagZc9R4ImZIWYRFZaaohR3KzmuK88touwsSwSVT8Qcbd4zoDsnGfX4GFB4imyQ== debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.8, debug@^2.6.9: version "2.6.9" @@ -7115,10 +7213,10 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.8, debug@^2.6. dependencies: ms "2.0.0" -debug@3.2.6, debug@^3.0.0, debug@^3.1.1, debug@^3.2.5: - version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== +debug@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" + integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== dependencies: ms "^2.1.1" @@ -7129,13 +7227,20 @@ debug@=3.1.0: dependencies: ms "2.0.0" -debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" - integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== +debug@^3.0.0, debug@^3.1.1, debug@^3.2.5: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== dependencies: ms "^2.1.1" +debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1" + integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg== + dependencies: + ms "2.1.2" + decamelize-keys@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" @@ -7340,6 +7445,11 @@ delegates@^1.0.0: resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= +delimit-stream@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/delimit-stream/-/delimit-stream-0.1.0.tgz#9b8319477c0e5f8aeb3ce357ae305fc25ea1cd2b" + integrity sha1-m4MZR3wOX4rrPONXrjBfwl6hzSs= + depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" @@ -7370,6 +7480,11 @@ detect-indent@^4.0.0: dependencies: repeating "^2.0.0" +detect-indent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d" + integrity sha1-OHHMCmoALow+Wzz38zYmRnXwa50= + detect-libc@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" @@ -7416,6 +7531,11 @@ diff-sequences@^25.2.6: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-25.2.6.tgz#5f467c00edd35352b7bca46d7927d60e687a76dd" integrity sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg== +diff-sequences@^26.5.0: + version "26.5.0" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.5.0.tgz#ef766cf09d43ed40406611f11c6d8d9dd8b2fefd" + integrity sha512-ZXx86srb/iYy6jG71k++wBN9P9J05UNQ5hQHQd9MtMPvcqXPx/vKU69jfHV637D00Q2gSgPk2D+jSx3l1lDW/Q== + diff@4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" @@ -7443,13 +7563,20 @@ dir-glob@2.0.0: arrify "^1.0.1" path-type "^3.0.0" -dmg-builder@22.8.0: - version "22.8.0" - resolved "https://registry.yarnpkg.com/dmg-builder/-/dmg-builder-22.8.0.tgz#2b17127837ed444db3086317eda5cf8912f6e6a9" - integrity sha512-orePWjcrl97SYLA8F/6UUtbXJSoZCYu5KOP1lVqD4LOomr8bjGDyEVYZmZYcg5WqKmXucdmO6OpqgzH/aRMMuA== +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== dependencies: - app-builder-lib "22.8.0" - builder-util "22.8.0" + path-type "^4.0.0" + +dmg-builder@22.8.1: + version "22.8.1" + resolved "https://registry.yarnpkg.com/dmg-builder/-/dmg-builder-22.8.1.tgz#9b3bcbbc43e5fed232525d61a5567ea4b66085c3" + integrity sha512-WeGom1moM00gBII6swljl4DQGrlJuEivoUhOmh8U9p1ALgeJL+EiTHbZFERlj8Ejy62xUUjURV+liOxUKmJFWg== + dependencies: + app-builder-lib "22.8.1" + builder-util "22.8.1" fs-extra "^9.0.1" iconv-lite "^0.6.2" js-yaml "^3.14.0" @@ -7498,9 +7625,9 @@ doctrine@^3.0.0: esutils "^2.0.2" dom-accessibility-api@^0.5.1: - version "0.5.2" - resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.2.tgz#ef3cdb5d3f0d599d8f9c8b18df2fb63c9793739d" - integrity sha512-k7hRNKAiPJXD2aBqfahSo4/01cTsKWXf+LqJgglnkN2Nz8TsxXKQBXHhKe0Ye9fEfHEZY49uSA5Sr3AqP/sWKA== + version "0.5.4" + resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.4.tgz#b06d059cdd4a4ad9a79275f9d414a5c126241166" + integrity sha512-TvrjBckDy2c6v6RLxPv5QXOnU+SmF9nBII5621Ve5fu6Z/BDrENurBEvlC1f44lKEUVqOpK4w9E5Idc5/EgkLQ== dom-converter@^0.2: version "0.2.0" @@ -7525,6 +7652,14 @@ dom-serializer@0: domelementtype "^2.0.1" entities "^2.0.0" +dom-serializer@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.1.tgz#1ec4059e284babed36eec2941d4a970a189ce7c0" + integrity sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA== + dependencies: + domelementtype "^1.3.0" + entities "^1.1.1" + dom-walk@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84" @@ -7535,15 +7670,15 @@ domain-browser@^1.1.1: resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== -domelementtype@1, domelementtype@^1.3.1: +domelementtype@1, domelementtype@^1.3.0, domelementtype@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== domelementtype@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d" - integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ== + version "2.0.2" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.2.tgz#f3b6e549201e46f588b59463dd77187131fe6971" + integrity sha512-wFwTwCVebUrMgGeAwRL/NhZtHAUyT9n9yg4IMDwf10+6iCMxSkVq9MGCVEH+QZWo1nNidy8kNvwmv4zWHDTqvA== domexception@^1.0.1: version "1.0.1" @@ -7584,9 +7719,9 @@ dot-case@^3.0.3: tslib "^1.10.0" dot-prop@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.2.0.tgz#c34ecc29556dc45f1f4c22697b6f4904e0cc4fcb" - integrity sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A== + version "5.3.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" + integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q== dependencies: is-obj "^2.0.0" @@ -7692,25 +7827,25 @@ ejs@^3.1.3: dependencies: jake "^10.6.1" -electron-builder@22.8.0: - version "22.8.0" - resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-22.8.0.tgz#d2c9fc5438c834e41fd794a271fca200165a3bad" - integrity sha512-dUv4F3srJouqxhWivtKqSoQP4Df6vYgjooGdzms+iYMTFi9f0b4LlEbr7kgsPvte8zAglee7VOGOODkCRJDkUQ== +electron-builder@22.8.1: + version "22.8.1" + resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-22.8.1.tgz#84295190dae17b3892df7aa39ac334983aeaea06" + integrity sha512-Hs7KTMq1rGSvT0fwGKXrjbLiJkK6sAKDQooUSwklOkktUgWi4ATjlP0fVE3l8SmS7zcLoww2yDZonSDqxEFhaQ== dependencies: "@types/yargs" "^15.0.5" - app-builder-lib "22.8.0" + app-builder-lib "22.8.1" bluebird-lst "^1.0.9" - builder-util "22.8.0" + builder-util "22.8.1" builder-util-runtime "8.7.2" chalk "^4.1.0" - dmg-builder "22.8.0" + dmg-builder "22.8.1" fs-extra "^9.0.1" is-ci "^2.0.0" lazy-val "^1.0.4" read-config-file "6.0.0" sanitize-filename "^1.6.3" update-notifier "^4.1.0" - yargs "^15.3.1" + yargs "^15.4.1" electron-is-dev@^1.2.0: version "1.2.0" @@ -7730,14 +7865,14 @@ electron-notarize@1.0.0: debug "^4.1.1" fs-extra "^9.0.1" -electron-publish@22.8.0: - version "22.8.0" - resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-22.8.0.tgz#7f410fe043abc5d3d896c4ee9eea7a43ea352c7d" - integrity sha512-uM0Zdi9hUqqGOrPj478v7toTvV1Kgto1w11rIiI168batiXAJvNLD8VZRfehOrZT0ibUyZlw8FtxoGCrjyHUOw== +electron-publish@22.8.1: + version "22.8.1" + resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-22.8.1.tgz#747e0d7f921cd1808f999713d29f599dbb390c4f" + integrity sha512-zqI66vl7j1CJZJ60J+1ez1tQNQeuqVspW44JvYDa5kZbM5wSFDAJFMK9RWHOqRF1Ezd4LDeiBa4aeTOwOt9syA== dependencies: "@types/fs-extra" "^9.0.1" bluebird-lst "^1.0.9" - builder-util "22.8.0" + builder-util "22.8.1" builder-util-runtime "8.7.2" chalk "^4.1.0" fs-extra "^9.0.1" @@ -7756,20 +7891,15 @@ electron-settings@^4.0.2: mkdirp "^1.0.4" write-file-atomic "^3.0.3" -electron-to-chromium@^1.3.247: - version "1.3.518" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.518.tgz#c54ee9cf1a7bafd6e482a1a6cceac86448d941e8" - integrity sha512-IspiwXYDKZMxo+qc3Vof4WtwbG9BMDbJfati8PYj7uS4DJmJ67pwjCKZxlTBSAuCZSMcbRnj2Xz2H14uiKT7bQ== +electron-to-chromium@^1.3.247, electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.47, electron-to-chromium@^1.3.571: + version "1.3.580" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.580.tgz#eb27873cfa012c43c53c9e9129038b8fd7cb964f" + integrity sha512-5flHTbRpptO6h3lQUG4zdSAxryAS3PrZOkLpLS0DL5/y2LBf+l9HJ8X6UBorNs1QRBrMR7u/QvkdK+GlekW1kQ== -electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.47, electron-to-chromium@^1.3.523: - version "1.3.533" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.533.tgz#d7e5ca4d57e9bc99af87efbe13e7be5dde729b0f" - integrity sha512-YqAL+NXOzjBnpY+dcOKDlZybJDCOzgsq4koW3fvyty/ldTmsb4QazZpOWmVvZ2m0t5jbBf7L0lIGU3BUipwG+A== - -electron-updater@4.3.4: - version "4.3.4" - resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-4.3.4.tgz#6003f88be9004d7834e4dd757167033d0fc2d29a" - integrity sha512-ekpgxDrYl+Wi24ktO4qfj2CtCABxrmK1C/oekp0tai6q4VR4ZdPkit4CX8+GenvKMme7uMmfPFnLp/vwhP/ThQ== +electron-updater@4.3.5: + version "4.3.5" + resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-4.3.5.tgz#4fb36f593a031c87ea07ee141c9f064d5deffb15" + integrity sha512-5jjN7ebvfj1cLI0VZMdCnJk6aC4bP+dy7ryBf21vArR0JzpRVk0OZHA2QBD+H5rm6ZSeDYHOY6+8PrMEqJ4wlQ== dependencies: "@types/semver" "^7.3.1" builder-util-runtime "8.7.2" @@ -7779,10 +7909,10 @@ electron-updater@4.3.4: lodash.isequal "^4.5.0" semver "^7.3.2" -electron@9.3.0: - version "9.3.0" - resolved "https://registry.yarnpkg.com/electron/-/electron-9.3.0.tgz#a4f3dc17f31acc6797eb4c2c4bd0d0e25efb939b" - integrity sha512-7zPLEZ+kOjVJqfawMQ0vVuZZRqvZIeiID3tbjjbVybbxXIlFMpZ2jogoh7PV3rLrtm+dKRfu7Qc4E7ob1d0FqQ== +electron@9.3.1: + version "9.3.1" + resolved "https://registry.yarnpkg.com/electron/-/electron-9.3.1.tgz#e301932c5c0537d8c9a8850d216d3ba454dbf55c" + integrity sha512-DScrhqBT4a54KfdF0EoipALpHmdQTn3m7SSCtbpTcEcG+UDUiXad2cOfW6DHeVH7N+CVDKDG12q2PhVJjXkFAA== dependencies: "@electron/get" "^1.0.1" "@types/node" "^12.0.12" @@ -7842,9 +7972,9 @@ emoji-regex@^8.0.0: integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== emoji-regex@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.0.0.tgz#48a2309cc8a1d2e9d23bc6a67c39b63032e76ea4" - integrity sha512-6p1NII1Vm62wni/VR/cUMauVQoxmLVb9csqQlvLz+hO2gk8U2UYDfXHQSUYIBKmZwAKz867IDqG7B+u0mj+M6w== + version "9.1.1" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.1.1.tgz#1d5ffce26d8191e6c3f3a9d27987b1c5bba7d20a" + integrity sha512-AaWyDiNO9rbtMIcGl7tdxMcNu8SOLaDLxmQEFT5JhgKufOJzPPkYmgN2QwqTgw4doWMZZQttC6sUWVQjb+1VdA== emojis-list@^2.0.0: version "2.1.0" @@ -7918,7 +8048,7 @@ enquirer@^2.3.6: dependencies: ansi-colors "^4.1.1" -entities@^1.1.1, entities@^1.1.2: +entities@^1.1.1, entities@^1.1.2, entities@~1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== @@ -7948,37 +8078,37 @@ error-ex@^1.2.0, error-ex@^1.3.1: is-arrayish "^0.2.1" es-abstract@^1.17.0, es-abstract@^1.17.0-next.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.2, es-abstract@^1.17.4, es-abstract@^1.17.5: - version "1.17.6" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.6.tgz#9142071707857b2cacc7b89ecb670316c3e2d52a" - integrity sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw== + version "1.17.7" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.7.tgz#a4de61b2f66989fc7421676c1cb9787573ace54c" + integrity sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g== dependencies: es-to-primitive "^1.2.1" function-bind "^1.1.1" has "^1.0.3" has-symbols "^1.0.1" - is-callable "^1.2.0" - is-regex "^1.1.0" - object-inspect "^1.7.0" + is-callable "^1.2.2" + is-regex "^1.1.1" + object-inspect "^1.8.0" object-keys "^1.1.1" - object.assign "^4.1.0" + object.assign "^4.1.1" string.prototype.trimend "^1.0.1" string.prototype.trimstart "^1.0.1" -es-abstract@^1.18.0-next.0: - version "1.18.0-next.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.0.tgz#b302834927e624d8e5837ed48224291f2c66e6fc" - integrity sha512-elZXTZXKn51hUBdJjSZGYRujuzilgXo8vSPQzjGYXLvSlGiCo8VO8ZGV3kjo9a0WNJJ57hENagwbtlRuHuzkcQ== +es-abstract@^1.18.0-next.0, es-abstract@^1.18.0-next.1: + version "1.18.0-next.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.1.tgz#6e3a0a4bda717e5023ab3b8e90bec36108d22c68" + integrity sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA== dependencies: es-to-primitive "^1.2.1" function-bind "^1.1.1" has "^1.0.3" has-symbols "^1.0.1" - is-callable "^1.2.0" + is-callable "^1.2.2" is-negative-zero "^2.0.0" is-regex "^1.1.1" object-inspect "^1.8.0" object-keys "^1.1.1" - object.assign "^4.1.0" + object.assign "^4.1.1" string.prototype.trimend "^1.0.1" string.prototype.trimstart "^1.0.1" @@ -8043,9 +8173,9 @@ es6-promise@^4.2.8: integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== es6-shim@^0.35.5: - version "0.35.5" - resolved "https://registry.yarnpkg.com/es6-shim/-/es6-shim-0.35.5.tgz#46f59dc0a84a1c5029e8ff1166ca0a902077a9ab" - integrity sha512-E9kK/bjtCQRpN1K28Xh4BlmP8egvZBGJJ+9GtnzOwt7mdqtrjHFuVGr7QJfdjBIKqrlU5duPf3pCBoDrkjVYFg== + version "0.35.6" + resolved "https://registry.yarnpkg.com/es6-shim/-/es6-shim-0.35.6.tgz#d10578301a83af2de58b9eadb7c2c9945f7388a0" + integrity sha512-EmTr31wppcaIAgblChZiuN/l9Y7DPyw8Xtbg7fIVngn6zMW+IEBJDJngeKC3x6wr0V/vcA2wqeFnaw1bFJbDdA== es6-symbol@^3.1.1, es6-symbol@~3.1.3: version "3.1.3" @@ -8055,10 +8185,10 @@ es6-symbol@^3.1.1, es6-symbol@~3.1.3: d "^1.0.1" ext "^1.1.2" -escalade@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.0.2.tgz#6a580d70edb87880f22b4c91d0d56078df6962c4" - integrity sha512-gPYAU37hYCUhW5euPeR+Y74F7BL+IBsV93j5cvGriSaD1aG6MGsqsV1yamRdrWrb2j3aiZvb0X+UBOWpx3JWtQ== +escalade@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== escape-goat@^2.0.0: version "2.1.1" @@ -8080,7 +8210,7 @@ escape-string-regexp@2.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== -escape-string-regexp@^4.0.0: +escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== @@ -8097,10 +8227,10 @@ escodegen@^1.11.0, escodegen@^1.9.1: optionalDependencies: source-map "~0.6.1" -eslint-config-prettier@6.11.0: - version "6.11.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.11.0.tgz#f6d2238c1290d01c859a8b5c1f7d352a0b0da8b1" - integrity sha512-oB8cpLWSAjOVFEJhhyMZh6NOEOtBVziaqdDQ86+qhDHFbZXoRTM7pNSvFRfW/W/L/LrQ38C99J5CGuRBBzBsdA== +eslint-config-prettier@6.14.0: + version "6.14.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.14.0.tgz#390e7863a8ae99970981933826476169285b3a27" + integrity sha512-DbVwh0qZhAC7CNDWcq8cBdK6FcVHiMTKmCypOPWeZkp9hJ8xYwTaWSa6bb6cjfi8KOeJy0e9a8Izxyx+O4+gCQ== dependencies: get-stdin "^6.0.0" @@ -8111,7 +8241,7 @@ eslint-config-react-app@^5.2.1: dependencies: confusing-browser-globals "^1.0.9" -eslint-import-resolver-node@^0.3.2, eslint-import-resolver-node@^0.3.3: +eslint-import-resolver-node@^0.3.2, eslint-import-resolver-node@^0.3.4: version "0.3.4" resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz#85ffa81942c25012d8231096ddf679c03042c717" integrity sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA== @@ -8163,17 +8293,17 @@ eslint-plugin-import@2.20.1: read-pkg-up "^2.0.0" resolve "^1.12.0" -eslint-plugin-import@2.22.0: - version "2.22.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.22.0.tgz#92f7736fe1fde3e2de77623c838dd992ff5ffb7e" - integrity sha512-66Fpf1Ln6aIS5Gr/55ts19eUuoDhAbZgnr6UxK5hbDx6l/QgQgx61AePq+BV4PP2uXQFClgMVzep5zZ94qqsxg== +eslint-plugin-import@2.22.1: + version "2.22.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz#0896c7e6a0cf44109a2d97b95903c2bb689d7702" + integrity sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw== dependencies: array-includes "^3.1.1" array.prototype.flat "^1.2.3" contains-path "^0.1.0" debug "^2.6.9" doctrine "1.5.0" - eslint-import-resolver-node "^0.3.3" + eslint-import-resolver-node "^0.3.4" eslint-module-utils "^2.6.0" has "^1.0.3" minimatch "^3.0.4" @@ -8244,21 +8374,21 @@ eslint-plugin-react@7.19.0: string.prototype.matchall "^4.0.2" xregexp "^4.3.0" -eslint-plugin-react@^7.20.6: - version "7.20.6" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.20.6.tgz#4d7845311a93c463493ccfa0a19c9c5d0fd69f60" - integrity sha512-kidMTE5HAEBSLu23CUDvj8dc3LdBU0ri1scwHBZjI41oDv4tjsWZKU7MQccFzH1QYPYhsnTF2ovh7JlcIcmxgg== +eslint-plugin-react@^7.21.5: + version "7.21.5" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.21.5.tgz#50b21a412b9574bfe05b21db176e8b7b3b15bff3" + integrity sha512-8MaEggC2et0wSF6bUeywF7qQ46ER81irOdWS4QWxnnlAEsnzeBevk1sWh7fhpCghPpXb+8Ks7hvaft6L/xsR6g== dependencies: array-includes "^3.1.1" array.prototype.flatmap "^1.2.3" doctrine "^2.1.0" has "^1.0.3" - jsx-ast-utils "^2.4.1" + jsx-ast-utils "^2.4.1 || ^3.0.0" object.entries "^1.1.2" object.fromentries "^2.0.2" object.values "^1.1.1" prop-types "^15.7.2" - resolve "^1.17.0" + resolve "^1.18.1" string.prototype.matchall "^4.0.2" eslint-plugin-sort-destructure-keys@1.3.5: @@ -8277,11 +8407,11 @@ eslint-scope@^4.0.3: estraverse "^4.1.1" eslint-scope@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.0.tgz#d0f971dfe59c69e0cada684b23d49dbf82600ce5" - integrity sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w== + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== dependencies: - esrecurse "^4.1.0" + esrecurse "^4.3.0" estraverse "^4.1.1" eslint-utils@^1.4.3: @@ -8303,6 +8433,11 @@ eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== +eslint-visitor-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" + integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== + eslint@6.8.0, eslint@^6.6.0: version "6.8.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb" @@ -8355,7 +8490,7 @@ espree@^6.1.2: acorn-jsx "^5.2.0" eslint-visitor-keys "^1.1.0" -esprima@^4.0.0, esprima@^4.0.1, esprima@~4.0.0: +esprima@^4.0.0, esprima@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== @@ -8367,19 +8502,19 @@ esquery@^1.0.1: dependencies: estraverse "^5.1.0" -esrecurse@^4.1.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" - integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== +esrecurse@^4.1.0, esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== dependencies: - estraverse "^4.1.0" + estraverse "^5.2.0" -estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: +estraverse@^4.1.1, estraverse@^4.2.0: version "4.3.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== -estraverse@^5.1.0: +estraverse@^5.1.0, estraverse@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== @@ -8406,7 +8541,7 @@ eth-block-tracker@^4.2.0, eth-block-tracker@^4.4.1, eth-block-tracker@^4.4.2: pify "^3.0.0" safe-event-emitter "^1.0.1" -eth-ens-namehash@2.0.8: +eth-ens-namehash@2.0.8, eth-ens-namehash@^2.0.0: version "2.0.8" resolved "https://registry.yarnpkg.com/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz#229ac46eca86d52e0c991e7cb2aef83ff0f68bcf" integrity sha1-IprEbsqG1S4MmR58sq74P/D2i88= @@ -8429,14 +8564,14 @@ eth-json-rpc-errors@^2.0.2: fast-safe-stringify "^2.0.6" eth-json-rpc-filters@^4.0.2, eth-json-rpc-filters@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/eth-json-rpc-filters/-/eth-json-rpc-filters-4.1.1.tgz#15277c66790236d85f798f4d7dc6bab99a798cd2" - integrity sha512-GkXb2h6STznD+AmMzblwXgm1JMvjdK9PTIXG7BvIkTlXQ9g0QOxuU1iQRYHoslF9S30BYBSoLSisAYPdLggW+A== + version "4.2.1" + resolved "https://registry.yarnpkg.com/eth-json-rpc-filters/-/eth-json-rpc-filters-4.2.1.tgz#82204a13c99927dbf42cbb3962846650c6281f33" + integrity sha512-tPfohezq8mSmwa47xvq6PGzBDLZ0njWJMB1J+OPuv+n+1WkWDlf3l3tqJXpq96RxhrzK2q7wiweRS5aGIzpq4Q== dependencies: await-semaphore "^0.1.3" - eth-json-rpc-middleware "^4.1.4" + eth-json-rpc-middleware "^6.0.0" eth-query "^2.1.2" - json-rpc-engine "^5.1.3" + json-rpc-engine "^5.3.0" lodash.flatmap "^4.5.0" safe-event-emitter "^1.0.1" @@ -8451,14 +8586,14 @@ eth-json-rpc-infura@^3.1.0: json-rpc-error "^2.0.0" eth-json-rpc-infura@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/eth-json-rpc-infura/-/eth-json-rpc-infura-4.0.2.tgz#8af1a1a2e9a0a82aaa302bbc96fb1a4c15d69b83" - integrity sha512-dvgOrci9lZqpjpp0hoC3Zfedhg3aIpLFVDH0TdlKxRlkhR75hTrKTwxghDrQwE0bn3eKrC8RsN1m/JdnIWltpw== + version "4.1.0" + resolved "https://registry.yarnpkg.com/eth-json-rpc-infura/-/eth-json-rpc-infura-4.1.0.tgz#623478375ba65e4304dea529ed69e8bd7938270d" + integrity sha512-DFYitKovzVlCdUulEccdm4g6k/vnvyByuw7rd5OoWDBSIiaeinI8Z/SntLjSIs2c+YvE20DGwk/GLwZGCWDN1Q== dependencies: - cross-fetch "^2.1.1" - eth-json-rpc-errors "^1.0.1" - eth-json-rpc-middleware "^4.1.4" + eth-json-rpc-middleware "^4.4.0" + eth-rpc-errors "^3.0.0" json-rpc-engine "^5.1.3" + node-fetch "^2.6.0" eth-json-rpc-middleware@^1.5.0: version "1.6.0" @@ -8479,7 +8614,7 @@ eth-json-rpc-middleware@^1.5.0: promise-to-callback "^1.0.0" tape "^4.6.3" -eth-json-rpc-middleware@^4.1.1, eth-json-rpc-middleware@^4.1.4, eth-json-rpc-middleware@^4.1.5: +eth-json-rpc-middleware@^4.1.1, eth-json-rpc-middleware@^4.1.5, eth-json-rpc-middleware@^4.4.0: version "4.4.1" resolved "https://registry.yarnpkg.com/eth-json-rpc-middleware/-/eth-json-rpc-middleware-4.4.1.tgz#07d3dd0724c24a8d31e4a172ee96271da71b4228" integrity sha512-yoSuRgEYYGFdVeZg3poWOwAlRI+MoBIltmOB86MtpoZjvLbou9EB/qWMOWSmH2ryCWLW97VYY6NWsmWm3OAA7A== @@ -8499,6 +8634,43 @@ eth-json-rpc-middleware@^4.1.1, eth-json-rpc-middleware@^4.1.4, eth-json-rpc-mid pify "^3.0.0" safe-event-emitter "^1.0.1" +eth-json-rpc-middleware@^5.0.2: + version "5.1.0" + resolved "https://registry.yarnpkg.com/eth-json-rpc-middleware/-/eth-json-rpc-middleware-5.1.0.tgz#affc63ddb31205e4b2f2c451571902031dad70fc" + integrity sha512-0uq8nWgHWLKA0sMhVqViue3vSEBVuQXyk2yzjhe8GSo/dGpJUtmYN1DvDF1LQtEhHI4N/G6MKPbiR/aWSRkPmg== + dependencies: + btoa "^1.2.1" + clone "^2.1.1" + eth-query "^2.1.2" + eth-rpc-errors "^3.0.0" + eth-sig-util "^1.4.2" + ethereumjs-block "^1.6.0" + ethereumjs-tx "^1.3.7" + ethereumjs-util "^5.1.2" + ethereumjs-vm "^2.6.0" + json-rpc-engine "^5.3.0" + json-stable-stringify "^1.0.1" + node-fetch "^2.6.1" + pify "^3.0.0" + safe-event-emitter "^1.0.1" + +eth-json-rpc-middleware@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/eth-json-rpc-middleware/-/eth-json-rpc-middleware-6.0.0.tgz#4fe16928b34231a2537856f08a5ebbc3d0c31175" + integrity sha512-qqBfLU2Uq1Ou15Wox1s+NX05S9OcAEL4JZ04VZox2NS0U+RtCMjSxzXhLFWekdShUPZ+P8ax3zCO2xcPrp6XJQ== + dependencies: + btoa "^1.2.1" + clone "^2.1.1" + eth-query "^2.1.2" + eth-rpc-errors "^3.0.0" + eth-sig-util "^1.4.2" + ethereumjs-util "^5.1.2" + json-rpc-engine "^5.3.0" + json-stable-stringify "^1.0.1" + node-fetch "^2.6.1" + pify "^3.0.0" + safe-event-emitter "^1.0.1" + eth-lib@0.2.7: version "0.2.7" resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.7.tgz#2f93f17b1e23aec3759cd4a3fe20c1286a3fc1ca" @@ -8544,15 +8716,7 @@ eth-rpc-errors@^3.0.0: dependencies: fast-safe-stringify "^2.0.6" -eth-sig-util@^1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-1.4.2.tgz#8d958202c7edbaae839707fba6f09ff327606210" - integrity sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA= - dependencies: - ethereumjs-abi "git+https://github.com/ethereumjs/ethereumjs-abi.git" - ethereumjs-util "^5.1.1" - -eth-sig-util@^2.5.3: +eth-sig-util@2.5.3, eth-sig-util@^2.5.3: version "2.5.3" resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-2.5.3.tgz#6938308b38226e0b3085435474900b03036abcbe" integrity sha512-KpXbCKmmBUNUTGh9MRKmNkIPietfhzBqqYqysDavLseIiMUGl95k6UcPEkALAZlj41e9E6yioYXc1PC333RKqw== @@ -8564,6 +8728,14 @@ eth-sig-util@^2.5.3: tweetnacl "^1.0.0" tweetnacl-util "^0.15.0" +eth-sig-util@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-1.4.2.tgz#8d958202c7edbaae839707fba6f09ff327606210" + integrity sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA= + dependencies: + ethereumjs-abi "git+https://github.com/ethereumjs/ethereumjs-abi.git" + ethereumjs-util "^5.1.1" + eth-tx-summary@^3.1.2: version "3.2.4" resolved "https://registry.yarnpkg.com/eth-tx-summary/-/eth-tx-summary-3.2.4.tgz#e10eb95eb57cdfe549bf29f97f1e4f1db679035c" @@ -8602,21 +8774,16 @@ ethereum-checksum-address@0.0.2: keccak256 "^1.0.0" meow "^5.0.0" -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-cryptography@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz#8d6143cfc3d74bf79bbd8edecdf29e4ae20dd191" @@ -8638,6 +8805,18 @@ ethereum-cryptography@^0.1.3: secp256k1 "^4.0.1" setimmediate "^1.0.5" +ethereum-ens@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/ethereum-ens/-/ethereum-ens-0.8.0.tgz#6d0f79acaa61fdbc87d2821779c4e550243d4c57" + integrity sha512-a8cBTF4AWw1Q1Y37V1LSCS9pRY4Mh3f8vCg5cbXCCEJ3eno1hbI/+Ccv9SZLISYpqQhaglP3Bxb/34lS4Qf7Bg== + dependencies: + bluebird "^3.4.7" + eth-ens-namehash "^2.0.0" + js-sha3 "^0.5.7" + pako "^1.0.4" + underscore "^1.8.3" + web3 "^1.0.0-beta.34" + ethereum-private-key-to-address@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/ethereum-private-key-to-address/-/ethereum-private-key-to-address-0.0.3.tgz#1f1dccaefd1198c2dcde55501f331a846bd0aad0" @@ -8688,7 +8867,7 @@ ethereumjs-abi@0.6.8, ethereumjs-abi@^0.6.8: "ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git": version "0.6.8" - resolved "git+https://github.com/ethereumjs/ethereumjs-abi.git#1cfbb13862f90f0b391d8a699544d5fe4dfb8c7b" + resolved "git+https://github.com/ethereumjs/ethereumjs-abi.git#1ce6a1d64235fabe2aaf827fd606def55693508f" dependencies: bn.js "^4.11.8" ethereumjs-util "^6.0.0" @@ -8713,17 +8892,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.2" resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-2.2.2.tgz#c7654be7e22df489fda206139ecd63e2e9c04965" @@ -8756,17 +8924,6 @@ ethereumjs-tx@^2.1.1, ethereumjs-tx@^2.1.2: ethereumjs-common "^1.5.0" ethereumjs-util "^6.0.0" -ethereumjs-util@4.5.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: version "5.2.0" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz#3e0c0d1741471acf1036052d048623dee54ad642" @@ -8818,9 +8975,9 @@ ethereumjs-util@^6.0.0, ethereumjs-util@^6.1.0: rlp "^2.2.3" ethereumjs-util@^7.0.3: - version "7.0.4" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.0.4.tgz#f4b2022a91416bf421b35b0d5b81c21e8abd8b7f" - integrity sha512-isldtbCn9fdnhBPxedMNbFkNWVZ8ZdQvKRDSrdflame/AycAPKMer+vEpndpBxYIB3qxN6bd3Gh1YCQW9LDkCQ== + version "7.0.6" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.0.6.tgz#ce4a6391a163cd1f2217b5276273f83bdacc7ab2" + integrity sha512-E9aJ9W7XZkcBqIblfstBU+0nGSjF9Dz/Ps7s1NTFOgDZM8pwD+nX1P1GBJeSqB6Osxhj2UtuxVCqjvmrj2svzw== dependencies: "@types/bn.js" "^4.11.3" bn.js "^5.1.2" @@ -8829,22 +8986,6 @@ ethereumjs-util@^7.0.3: ethjs-util "0.1.6" rlp "^2.2.4" -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.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" @@ -8893,7 +9034,7 @@ ethers@4.0.0-beta.3: uuid "2.0.1" xmlhttprequest "1.8.0" -ethers@4.0.47, ethers@^4.0.0-beta.1, ethers@^4.0.32: +ethers@4.0.47: version "4.0.47" resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.47.tgz#91b9cd80473b1136dd547095ff9171bd1fc68c85" integrity sha512-hssRYhngV4hiDNeZmVU/k5/E8xmLG8UpcNUzg6mb7lqhgpFPH/t7nuv20RjRrEf0gblzvi2XwR5Te+V3ZFc9pQ== @@ -8908,6 +9049,21 @@ ethers@4.0.47, ethers@^4.0.0-beta.1, ethers@^4.0.32: uuid "2.0.1" xmlhttprequest "1.8.0" +ethers@^4.0.0-beta.1, ethers@^4.0.32: + version "4.0.48" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.48.tgz#330c65b8133e112b0613156e57e92d9009d8fbbe" + integrity sha512-sZD5K8H28dOrcidzx9f8KYh8083n5BexIO3+SbE4jK83L85FxtpXZBCQdXb8gkg+7sBqomcLhhkU7UHL+F7I2g== + dependencies: + aes-js "3.0.0" + bn.js "^4.4.0" + elliptic "6.5.3" + hash.js "1.1.3" + js-sha3 "0.5.7" + scrypt-js "2.0.4" + setimmediate "1.0.4" + uuid "2.0.1" + xmlhttprequest "1.8.0" + ethjs-unit@0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" @@ -8940,9 +9096,9 @@ eventemitter3@4.0.4: integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ== eventemitter3@^4.0.0: - version "4.0.5" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.5.tgz#51d81e4f1ccc8311a04f0c20121ea824377ea6d9" - integrity sha512-QR0rh0YiPuxuDQ6+T9GAO/xWTExXpxIes1Nl9RykNGTnE1HJmkuEfxJH9cubjIOQZ/GH4qNBR4u8VSHaKiWs4g== + version "4.0.7" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" + integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== events@^3.0.0, events@^3.2.0: version "3.2.0" @@ -9177,6 +9333,18 @@ fast-glob@^2.0.2: merge2 "^1.2.3" micromatch "^3.1.10" +fast-glob@^3.1.1: + version "3.2.4" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.4.tgz#d20aefbf99579383e7f3cc66529158c9b98554d3" + integrity sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.0" + merge2 "^1.3.0" + micromatch "^4.0.2" + picomatch "^2.2.1" + fast-json-parse@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/fast-json-parse/-/fast-json-parse-1.0.3.tgz#43e5c61ee4efa9265633046b770fb682a7577c4d" @@ -9197,6 +9365,13 @@ fast-safe-stringify@^2.0.6: resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz#124aa885899261f68aedb42a7c080de9da608743" integrity sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA== +fastq@^1.6.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.9.0.tgz#e16a72f338eaca48e91b5c23593bcc2ef66b7947" + integrity sha512-i7FVWL8HhVY+CTkwFxkN2mk3h+787ixS5S63eb78diVRc1MCssarHq3W5cj0av7YDSwmaV928RNag+U1etRQ7w== + dependencies: + reusify "^1.0.4" + fault@^1.0.2: version "1.0.4" resolved "https://registry.yarnpkg.com/fault/-/fault-1.0.4.tgz#eafcfc0a6d214fc94601e170df29954a4f842f13" @@ -9349,10 +9524,10 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" -final-form-calculate@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/final-form-calculate/-/final-form-calculate-1.3.1.tgz#463089114245afa97fea94712bfbfca11da8413e" - integrity sha512-vZCvQ08w9FIoHLkZMcJSIXQr5TAVLxHfLD0thmm50zcNyJESruqhgvurSjWYPLoJGnIgbIb94Rumdg5ZXX5WiQ== +final-form-calculate@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/final-form-calculate/-/final-form-calculate-1.3.2.tgz#a5e1908d1aa34eeec6faccdba3fd9516e7fd3d4f" + integrity sha512-pon2K9yNbyqmF8UTpDvxwhk+Hvqpl8Fm3qgwkHniNAmCQe+6YxB1aw4cBAHzmRc39jGl2bYsvKyabQOIWLtrPg== final-form@^4.20.1: version "4.20.1" @@ -9429,6 +9604,14 @@ find-up@4.1.0, find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" +find-up@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + find-up@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" @@ -9461,9 +9644,9 @@ flat-cache@^2.0.1: write "1.0.3" flat@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.0.tgz#090bec8b05e39cba309747f1d588f04dbaf98db2" - integrity sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw== + version "4.1.1" + resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.1.tgz#a392059cc382881ff98642f5da4dde0a959f309b" + integrity sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA== dependencies: is-buffer "~2.0.3" @@ -9845,7 +10028,7 @@ glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" -glob-parent@^5.0.0, glob-parent@~5.1.0: +glob-parent@^5.0.0, glob-parent@^5.1.0, glob-parent@~5.1.0: version "5.1.1" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== @@ -9857,7 +10040,7 @@ glob-to-regexp@^0.3.0: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= -glob@7.1.6, glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@~7.1.1, glob@~7.1.6: +glob@7.1.6, glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@~7.1.1, glob@~7.1.6: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -9968,6 +10151,18 @@ globby@8.0.2: pify "^3.0.0" slash "^1.0.0" +globby@^11.0.1: + version "11.0.1" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.1.tgz#9a2bf107a068f3ffeabc49ad702c79ede8cfd357" + integrity sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.1.1" + ignore "^5.1.4" + merge2 "^1.3.0" + slash "^3.0.0" + globby@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" @@ -10214,7 +10409,7 @@ hdkey@^2.0.1: safe-buffer "^5.1.1" secp256k1 "^4.0.0" -he@1.2.0, he@^1.2.0: +he@1.2.0, he@^1.1.1, he@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== @@ -10224,11 +10419,21 @@ hex-color-regex@^1.1.0: resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== +highlight.js@^9.12.0, highlight.js@^9.15.8: + version "9.18.3" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.18.3.tgz#a1a0a2028d5e3149e2380f8a865ee8516703d634" + integrity sha512-zBZAmhSupHIl5sITeMqIJnYCDfAEc3Gdkqj65wC1lpI468MMQeeQkhcIAvk+RylAkxrCcI9xy9piHiXeQ1BdzQ== + highlight.js@~9.13.0: version "9.13.1" resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.13.1.tgz#054586d53a6863311168488a0f58d6c505ce641e" integrity sha512-Sc28JNQNDzaH6PORtRLMvif9RSn1mYuOoX3omVjnb0+HbpPygU2ALBI0R/wsiqCb4/fcp07Gdo8g+fhtFrQl6A== +highlightjs-solidity@^1.0.18: + version "1.0.18" + resolved "https://registry.yarnpkg.com/highlightjs-solidity/-/highlightjs-solidity-1.0.18.tgz#3deb0593689a26fbadf98e631bf2cd305a6417c9" + integrity sha512-k15h0br4oCRT0F0jTRuZbimerVt5V4n0k25h7oWi0kVqlBNeXPbSr5ddw02/2ukJmYfB8jauFDmxSauJjwM7Eg== + history@4.10.1, history@^4.9.0: version "4.10.1" resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3" @@ -10276,9 +10481,9 @@ hosted-git-info@^2.1.4: integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg== hosted-git-info@^3.0.5: - version "3.0.5" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-3.0.5.tgz#bea87905ef7317442e8df3087faa3c842397df03" - integrity sha512-i4dpK6xj9BIpVOTboXIlKG9+8HMKggcrMX7WA24xZtKwX0TPelq/rbaS5rCKeNX8sJXZJGdSxpnEGtta+wismQ== + version "3.0.6" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-3.0.6.tgz#761da6d68c559238164f3f3078842ef9e8ae1607" + integrity sha512-VRvqVD5T6t9HdmNDWTwbi8H/EC722MemAhOSP5QvYAXpDAY0Nhu2I/i+bXsktu4sU5LVHSh/wmXtVU8bDtjedQ== dependencies: lru-cache "^6.0.0" @@ -10350,9 +10555,9 @@ html-webpack-plugin@4.0.0-beta.11: util.promisify "1.0.0" html-webpack-plugin@^4.0.0-beta.2: - version "4.3.0" - resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-4.3.0.tgz#53bf8f6d696c4637d5b656d3d9863d89ce8174fd" - integrity sha512-C0fzKN8yQoVLTelcJxZfJCE+aAvQiY2VUf3UuKrR4a9k5UMWYOtpDLsaXwATbcVCnI05hUS7L9ULQHWLZhyi3w== + version "4.5.0" + resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-4.5.0.tgz#625097650886b97ea5dae331c320e3238f6c121c" + integrity sha512-MouoXEYSjTzCrjIxWwg8gxL5fE2X2WZJLmBYXlaJhQUH5K/b5OrqmV7T4dB7iu0xkmJ6JlUuV6fFVtnqbPopZw== dependencies: "@types/html-minifier-terser" "^5.0.0" "@types/tapable" "^1.0.5" @@ -10364,7 +10569,7 @@ html-webpack-plugin@^4.0.0-beta.2: tapable "^1.1.3" util.promisify "1.0.0" -htmlparser2@^3.3.0: +htmlparser2@^3.3.0, htmlparser2@^3.9.1: version "3.10.1" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== @@ -10466,15 +10671,24 @@ human-signals@^1.1.1: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== -husky@^4.2.5: - version "4.2.5" - resolved "https://registry.yarnpkg.com/husky/-/husky-4.2.5.tgz#2b4f7622673a71579f901d9885ed448394b5fa36" - integrity sha512-SYZ95AjKcX7goYVZtVZF2i6XiZcHknw50iXvY7b0MiGoj5RwdgRQNEHdb+gPDPCXKlzwrybjFjkL6FOj8uRhZQ== +husky@^0.14.3: + version "0.14.3" + resolved "https://registry.yarnpkg.com/husky/-/husky-0.14.3.tgz#c69ed74e2d2779769a17ba8399b54ce0b63c12c3" + integrity sha512-e21wivqHpstpoiWA/Yi8eFti8E+sQDSS53cpJsPptPs295QTOQR0ZwnHo2TXy1XOpZFD9rPOd3NpmqTK6uMLJA== + dependencies: + is-ci "^1.0.10" + normalize-path "^1.0.0" + strip-indent "^2.0.0" + +husky@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/husky/-/husky-4.3.0.tgz#0b2ec1d66424e9219d359e26a51c58ec5278f0de" + integrity sha512-tTMeLCLqSBqnflBZnlVDhpaIMucSGaYyX6855jM4AguGeWCeSzNdb1mfyWduTZ3pe3SJVvVWGL0jO1iKZVPfTA== dependencies: chalk "^4.0.0" ci-info "^2.0.0" compare-versions "^3.6.0" - cosmiconfig "^6.0.0" + cosmiconfig "^7.0.0" find-versions "^3.2.0" opencollective-postinstall "^2.0.2" pkg-dir "^4.2.0" @@ -10527,7 +10741,7 @@ idna-uts46-hx@^2.3.1: dependencies: punycode "2.1.0" -ieee754@^1.1.4: +ieee754@^1.1.13, ieee754@^1.1.4: version "1.1.13" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== @@ -10547,6 +10761,11 @@ ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== +ignore@^5.1.4: + version "5.1.8" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" + integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== + immediate@^3.2.3: version "3.3.0" resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.3.0.tgz#1aef225517836bcdf7f2a2de2600c79ff0269266" @@ -10762,7 +10981,7 @@ interpret@^2.0.0: resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== -invariant@^2.2.2, invariant@^2.2.3, invariant@^2.2.4: +invariant@2, invariant@^2.2.2, invariant@^2.2.3, invariant@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== @@ -10860,10 +11079,17 @@ is-buffer@^1.0.2, is-buffer@^1.1.5: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== -is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.0.tgz#83336560b54a38e35e3a2df7afd0454d691468bb" - integrity sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw== +is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.2.tgz#c7c6715cd22d4ddb48d3e19970223aceabb080d9" + integrity sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA== + +is-ci@^1.0.10: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c" + integrity sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg== + dependencies: + ci-info "^1.5.0" is-ci@^2.0.0: version "2.0.0" @@ -10884,6 +11110,13 @@ is-color-stop@^1.0.0: rgb-regex "^1.0.1" rgba-regex "^1.0.0" +is-core-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.0.0.tgz#58531b70aed1db7c0e8d4eb1a0a2d1ddd64bd12d" + integrity sha512-jq1AH6C8MuteOoBPwkxHafmByhL9j5q4OaPGdbuD+ZtQJVzH+i6E3BJDQcBA09k57i2Hh2yQbEG8yObZ0jdlWw== + dependencies: + has "^1.0.3" + is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -11135,7 +11368,7 @@ is-plain-object@^3.0.0: resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-3.0.1.tgz#662d92d24c0aa4302407b0d45d21f2251c85f85b" integrity sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g== -is-regex@^1.0.4, is-regex@^1.1.0, is-regex@^1.1.1: +is-regex@^1.0.4, is-regex@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.1.tgz#c6f98aacc546f6cec5468a07b7b153ab564a57b9" integrity sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg== @@ -11265,6 +11498,11 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= +iso-url@~0.4.7: + version "0.4.7" + resolved "https://registry.yarnpkg.com/iso-url/-/iso-url-0.4.7.tgz#de7e48120dae46921079fe78f325ac9e9217a385" + integrity sha512-27fFRDnPAMnHGLq36bWTpKET+eiXct3ENlCcdcMdk+mjXrb2kw3mhBUg1B7ewAC0kVzlOPhADzQgz1SE6Tglog== + isobject@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" @@ -11442,6 +11680,16 @@ jest-diff@^25.2.1: jest-get-type "^25.2.6" pretty-format "^25.5.0" +jest-diff@^26.0.0: + version "26.6.1" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.6.1.tgz#38aa194979f454619bb39bdee299fb64ede5300c" + integrity sha512-BBNy/zin2m4kG5In126O8chOBxLLS/XMTuuM2+YhgyHk87ewPzKTuTJcqj3lOWOi03NNgrl+DkMeV/exdvG9gg== + dependencies: + chalk "^4.0.0" + diff-sequences "^26.5.0" + jest-get-type "^26.3.0" + pretty-format "^26.6.1" + jest-docblock@^24.3.0: version "24.9.0" resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-24.9.0.tgz#7970201802ba560e1c4092cc25cbedf5af5a8ce2" @@ -11505,6 +11753,11 @@ jest-get-type@^25.2.6: resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-25.2.6.tgz#0b0a32fab8908b44d508be81681487dbabb8d877" integrity sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig== +jest-get-type@^26.3.0: + version "26.3.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.3.0.tgz#e97dc3c3f53c2b406ca7afaed4493b1d099199e0" + integrity sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig== + jest-haste-map@^24.9.0: version "24.9.0" resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-24.9.0.tgz#b38a5d64274934e21fa417ae9a9fbeb77ceaac7d" @@ -11804,11 +12057,6 @@ js-sha3@0.8.0, js-sha3@^0.8.0: resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== -js-sha3@^0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.6.1.tgz#5b89f77a7477679877f58c4a075240934b1f95c0" - integrity sha1-W4n3enR3Z5h39YxKB1JAk0sflcA= - "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -11819,15 +12067,7 @@ js-tokens@^3.0.2: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= -js-yaml@3.13.1: - version "3.13.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" - integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -js-yaml@^3.13.1, js-yaml@^3.14.0: +js-yaml@3.14.0, js-yaml@^3.13.1, js-yaml@^3.14.0: version "3.14.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482" integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A== @@ -11929,6 +12169,11 @@ json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + json-rpc-engine@^3.4.0, json-rpc-engine@^3.6.0: version "3.8.0" resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-3.8.0.tgz#9d4ff447241792e1d0a232f6ef927302bb0c62a9" @@ -11941,7 +12186,7 @@ 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, json-rpc-engine@^5.1.3, json-rpc-engine@^5.1.8: +json-rpc-engine@^5.1.3, json-rpc-engine@^5.1.8, json-rpc-engine@^5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-5.3.0.tgz#7dc7291766b28766ebda33eb6d3f4c6301c44ff4" integrity sha512-+diJ9s8rxB+fbJhT7ZEf8r8spaLRignLd8jTgQ/h5JSGppAHGtNMZtCoabipCaleR1B3GTGxbXBOqhaJSGmPGQ== @@ -11996,6 +12241,13 @@ json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= +json-text-sequence@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/json-text-sequence/-/json-text-sequence-0.1.1.tgz#a72f217dc4afc4629fff5feb304dc1bd51a2f3d2" + integrity sha1-py8hfcSvxGKf/1/rME3BvVGi89I= + dependencies: + delimit-stream "0.1.0" + json2mq@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/json2mq/-/json2mq-0.2.0.tgz#b637bd3ba9eabe122c83e9720483aeb10d2c904a" @@ -12148,6 +12400,14 @@ jsx-ast-utils@^2.2.1, jsx-ast-utils@^2.2.3, jsx-ast-utils@^2.4.1: array-includes "^3.1.1" object.assign "^4.1.0" +"jsx-ast-utils@^2.4.1 || ^3.0.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.1.0.tgz#642f1d7b88aa6d7eb9d8f2210e166478444fa891" + integrity sha512-d4/UOjg+mxAWxCiF0c5UTSwyqbchkbqCvK87aBovhnh8GtysTjWmgC63tY0cJx/HzGgm9qnA147jVBdpOiQ2RA== + dependencies: + array-includes "^3.1.1" + object.assign "^4.1.1" + just-curry-it@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/just-curry-it/-/just-curry-it-3.1.0.tgz#ab59daed308a58b847ada166edd0a2d40766fbc5" @@ -12179,14 +12439,6 @@ keccak@^3.0.0: node-addon-api "^2.0.0" node-gyp-build "^4.2.0" -keccakjs@^0.2.0: - version "0.2.3" - resolved "https://registry.yarnpkg.com/keccakjs/-/keccakjs-0.2.3.tgz#5e4e969ce39689a3861f445d7752ee3477f9fe72" - integrity sha512-BjLkNDcfaZ6l8HBG9tH0tpmDv3sS2mA7FNQxFHpCdzP3Gb2MVruXBSuoM66SnVxKJpAr5dKGdkHD+bDokt8fTg== - dependencies: - browserify-sha3 "^0.0.4" - sha3 "^1.2.2" - keyv@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" @@ -12380,10 +12632,10 @@ lines-and-columns@^1.1.6: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= -lint-staged@10.4.0: - version "10.4.0" - resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-10.4.0.tgz#d18628f737328e0bbbf87d183f4020930e9a984e" - integrity sha512-uaiX4U5yERUSiIEQc329vhCTDDwUcSvKdRLsNomkYLRzijk3v8V9GWm2Nz0RMVB87VcuzLvtgy6OsjoH++QHIg== +lint-staged@^10.4.2: + version "10.4.2" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-10.4.2.tgz#9fee4635c4b5ddb845746f237c6d43494ccd21c1" + integrity sha512-OLCA9K1hS+Sl179SO6kX0JtnsaKj/MZalEhUj5yAgXsb63qPI/Gfn6Ua1KuZdbfkZNEu3/n5C/obYCu70IMt9g== dependencies: chalk "^4.1.0" cli-truncate "^2.1.0" @@ -12509,11 +12761,23 @@ locate-path@^5.0.0: dependencies: p-locate "^4.1.0" +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + lodash._reinterpolate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= +lodash.clonedeep@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" + integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= + lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" @@ -12524,6 +12788,11 @@ lodash.defaults@^4.2.0: resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw= +lodash.escaperegexp@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz#64762c48618082518ac3df4ccf5d5886dae20347" + integrity sha1-ZHYsSGGAglGKw99Mz11YhtriA0c= + lodash.flatmap@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.flatmap/-/lodash.flatmap-4.5.0.tgz#ef8cbf408f6e48268663345305c6acc0b778702e" @@ -12549,6 +12818,16 @@ lodash.memoize@^4.1.2: resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash.partition@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.partition/-/lodash.partition-4.6.0.tgz#a38e46b73469e0420b0da1212e66d414be364ba4" + integrity sha1-o45GtzRp4EILDaEhLmbUFL42S6Q= + lodash.set@^4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23" @@ -12559,6 +12838,11 @@ lodash.sortby@^4.7.0: resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= +lodash.sum@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/lodash.sum/-/lodash.sum-4.0.2.tgz#ad90e397965d803d4f1ff7aa5b2d0197f3b4637b" + integrity sha1-rZDjl5ZdgD1PH/eqWy0Bl/O0Y3s= + lodash.template@^4.4.0, lodash.template@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab" @@ -12589,27 +12873,22 @@ lodash.unset@^4.5.2: resolved "https://registry.yarnpkg.com/lodash.unset/-/lodash.unset-4.5.2.tgz#370d1d3e85b72a7e1b0cdf2d272121306f23e4ed" integrity sha1-Nw0dPoW3Kn4bDN8tJyEhMG8j5O0= -"lodash@>=3.5 <5", lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.4, lodash@^4.17.5, lodash@~4.17.10: +"lodash@>=3.5 <5", lodash@^4.0.0, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.4, lodash@^4.17.5, lodash@~4.17.10: version "4.17.20" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== -lodash@^4.17.12: - version "4.17.19" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b" - integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ== - log-driver@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" integrity sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg== -log-symbols@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4" - integrity sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ== +log-symbols@4.0.0, log-symbols@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.0.0.tgz#69b3cc46d20f448eccdb75ea1fa733d9e821c920" + integrity sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA== dependencies: - chalk "^2.4.2" + chalk "^4.0.0" log-symbols@^2.1.0: version "2.2.0" @@ -12618,13 +12897,6 @@ log-symbols@^2.1.0: dependencies: chalk "^2.0.1" -log-symbols@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.0.0.tgz#69b3cc46d20f448eccdb75ea1fa733d9e821c920" - integrity sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA== - dependencies: - chalk "^4.0.0" - log-update@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1" @@ -12636,9 +12908,9 @@ log-update@^4.0.0: wrap-ansi "^6.2.0" loglevel@^1.6.8: - version "1.6.8" - resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.8.tgz#8a25fb75d092230ecd4457270d80b54e28011171" - integrity sha512-bsU7+gc9AJ2SqpzxwU3+1fedl8zAntbtC5XYlt3s2j1hJcn2PsXSmgN8TaLG/J1/2mod4+cE/3vNL70/c1RNCA== + version "1.7.0" + resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.7.0.tgz#728166855a740d59d38db01cf46f042caa041bb0" + integrity sha512-i2sY04nal5jDcagM3FMfG++T69GEEM8CYuOfeOIvmXzOIcwE9a/CJPR0MFM97pYMj/u10lzz7/zd7+qwhrBTqQ== loglevelnext@^1.0.1: version "1.0.5" @@ -12715,6 +12987,11 @@ ltgt@~2.2.0: resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5" integrity sha1-81ypHEk/e3PaDgdJUwTxezH4fuU= +lz-string@^1.4.4: + version "1.4.4" + resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.4.4.tgz#c0d8eaf36059f705796e1e344811cf4c498d3a26" + integrity sha1-wNjq82BZ9wV5bh40SBHPTEmNOiY= + make-dir@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" @@ -12923,7 +13200,7 @@ merge-stream@^2.0.0: resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -merge2@^1.2.3: +merge2@^1.2.3, merge2@^1.3.0: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== @@ -12987,12 +13264,17 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -mime-db@1.44.0, "mime-db@>= 1.43.0 < 2": +mime-db@1.44.0: version "1.44.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg== -mime-types@^2.1.12, mime-types@^2.1.16, mime-types@^2.1.26, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24: +"mime-db@>= 1.43.0 < 2": + version "1.45.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.45.0.tgz#cceeda21ccd7c3a745eba2decd55d4b73e7879ea" + integrity sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w== + +mime-types@^2.1.12, mime-types@^2.1.16, mime-types@^2.1.27, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24: version "2.1.27" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f" integrity sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w== @@ -13198,28 +13480,28 @@ mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.4, mkdirp@^0.5.5, mkdir dependencies: minimist "^1.2.5" -mocha@8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-8.0.1.tgz#fe01f0530362df271aa8f99510447bc38b88d8ed" - integrity sha512-vefaXfdYI8+Yo8nPZQQi0QO2o+5q9UIMX1jZ1XMmK3+4+CQjc7+B0hPdUeglXiTlr8IHMVRo63IhO9Mzt6fxOg== +mocha@8.1.2: + version "8.1.2" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-8.1.2.tgz#d67fad13300e4f5cd48135a935ea566f96caf827" + integrity sha512-I8FRAcuACNMLQn3lS4qeWLxXqLvGf6r2CaLstDpZmMUUSmvW6Cnm1AuHxgbc7ctZVRcfwspCRbDHymPsi3dkJw== dependencies: ansi-colors "4.1.1" browser-stdout "1.3.1" - chokidar "3.3.1" - debug "3.2.6" + chokidar "3.4.2" + debug "4.1.1" diff "4.0.2" - escape-string-regexp "1.0.5" - find-up "4.1.0" + escape-string-regexp "4.0.0" + find-up "5.0.0" glob "7.1.6" growl "1.10.5" he "1.2.0" - js-yaml "3.13.1" - log-symbols "3.0.0" + js-yaml "3.14.0" + log-symbols "4.0.0" minimatch "3.0.4" ms "2.1.2" object.assign "4.1.0" promise.allsettled "1.0.2" - serialize-javascript "3.0.0" + serialize-javascript "4.0.0" strip-json-comments "3.0.1" supports-color "7.1.0" which "2.0.2" @@ -13227,18 +13509,13 @@ mocha@8.0.1: workerpool "6.0.0" yargs "13.3.2" yargs-parser "13.1.2" - yargs-unparser "1.6.0" + yargs-unparser "1.6.1" mock-fs@^4.1.0: version "4.13.0" resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.13.0.tgz#31c02263673ec3789f90eb7b6963676aa407a598" integrity sha512-DD0vOdofJdoaRNtnWcrXe6RQbpHkPPmtqGq14uRX0F8ZKJ5nv89CVTYl/BZdppDxBDaV0hl75htg3abpEWlPZA== -moment@2.24.0: - version "2.24.0" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b" - integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg== - move-concurrently@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" @@ -13335,9 +13612,9 @@ nan@2.13.2: integrity sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw== nan@^2.12.1, nan@^2.13.2, nan@^2.14.0, nan@^2.14.1, nan@^2.2.1: - version "2.14.1" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01" - integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw== + version "2.14.2" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19" + integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ== nano-json-stream-parser@^0.1.2: version "0.1.2" @@ -13405,9 +13682,9 @@ no-case@^3.0.3: tslib "^1.10.0" node-abi@^2.18.0, node-abi@^2.7.0: - version "2.19.0" - resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.19.0.tgz#11614ff22dd64dad3501074bf656e6923539e17a" - integrity sha512-rpKqVe24p9GvMTgtqUXdLR1WQJBGVlkYPU10qHKv9/1i9V/k04MmFLVK2WcHBf1WKKY+ZsdvARPi8F4tfJ4opA== + version "2.19.1" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.19.1.tgz#6aa32561d0a5e2fdb6810d8c25641b657a8cea85" + integrity sha512-HbtmIuByq44yhAzK7b9j/FelKlHYISKQn0mtvcBrU5QBkhoCMp5bu8Hv5AI34DcKfOAcJBcOEMwLlwO62FFu9A== dependencies: semver "^5.4.1" @@ -13436,21 +13713,26 @@ node-fetch@^1.0.1, node-fetch@~1.7.1: encoding "^0.1.11" is-stream "^1.0.1" -node-fetch@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" - integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== +node-fetch@^2.6.0, node-fetch@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" + integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== -node-forge@0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.9.0.tgz#d624050edbb44874adca12bb9a52ec63cb782579" - integrity sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ== +node-forge@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3" + integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA== node-gyp-build@^4.2.0: version "4.2.3" resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.2.3.tgz#ce6277f853835f718829efb47db20f3e4d9c4739" integrity sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg== +node-gyp-build@~3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-3.7.0.tgz#daa77a4f547b9aed3e2aac779eaf151afd60ec8d" + integrity sha512-L/Eg02Epx6Si2NXmedx+Okg+4UHqmaf3TNcxd50SF9NQGcJaON3AtU++kax69XV7YWz4tUspqZSAsVofhFKG2w== + node-gyp@^3.8.0, node-gyp@^5.1.0: version "5.1.1" resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-5.1.1.tgz#eb915f7b631c937d282e33aed44cb7a025f62a3e" @@ -13468,7 +13750,7 @@ node-gyp@^3.8.0, node-gyp@^5.1.0: tar "^4.4.12" which "^1.3.1" -node-hid@^1.3.0: +node-hid@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/node-hid/-/node-hid-1.3.0.tgz#346a468505cee13d69ccd760052cbaf749f66a41" integrity sha512-BA6G4V84kiNd1uAChub/Z/5s/xS3EHBCxotQ0nyYrUG65mXewUDHE1tWOSqA2dp3N+mV0Ffq9wo2AW9t4p/G7g== @@ -13528,10 +13810,10 @@ node-notifier@^5.4.2: shellwords "^0.1.1" which "^1.3.0" -node-releases@^1.1.29, node-releases@^1.1.52, node-releases@^1.1.60: - version "1.1.60" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.60.tgz#6948bdfce8286f0b5d0e5a88e8384e954dfe7084" - integrity sha512-gsO4vjEdQaTusZAEebUWp2a5d7dF5DYoIpDG7WySnk7BuZDW+GPpHXoXXuYawRBr/9t5q54tirPz79kFIWg4dA== +node-releases@^1.1.29, node-releases@^1.1.52, node-releases@^1.1.61: + version "1.1.63" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.63.tgz#db6dbb388544c31e888216304e8fd170efee3ff5" + integrity sha512-ukW3iCfQaoxJkSPN+iK7KznTeqDGVJatAEuXsJERYHa9tn/KaT5lBdIyxQjLEVTzSkyjJEuQ17/vaEjrOauDkg== node-sass@^4.14.1: version "4.14.1" @@ -13586,6 +13868,11 @@ normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package- semver "2 || 3 || 4 || 5" validate-npm-package-license "^3.0.1" +normalize-path@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-1.0.0.tgz#32d0e472f91ff345701c15a8311018d3b0a90379" + integrity sha1-MtDkcvkf80VwHBWoMRAY07CpA3k= + normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" @@ -13727,7 +14014,7 @@ object-hash@^2.0.1: resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.0.3.tgz#d12db044e03cd2ca3d77c0570d87225b02e1e6ea" integrity sha512-JPKn0GMu+Fa3zt3Bmr66JhokJU5BaNBIh4ZeTlaCBzrBsOeXzwcKKAK1tbLiPKgvwmPXsDvvLHoWh5Bm7ofIYg== -object-inspect@^1.7.0, object-inspect@^1.8.0: +object-inspect@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0" integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA== @@ -13738,12 +14025,12 @@ object-inspect@~1.7.0: integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== object-is@^1.0.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.2.tgz#c5d2e87ff9e119f78b7a088441519e2eec1573b6" - integrity sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ== + version "1.1.3" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.3.tgz#2e3b9e65560137455ee3bd62aec4d90a2ea1cc81" + integrity sha512-teyqLvFWzLkq5B9ki8FVWA902UER2qkxmdA4nLf+wjOLAWgxzCWZNCxpDq9MvE8MmhWNr+I8w3BN49Vx36Y6Xg== dependencies: define-properties "^1.1.3" - es-abstract "^1.17.5" + es-abstract "^1.18.0-next.1" object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" @@ -13767,7 +14054,7 @@ object-visit@^1.0.0: dependencies: isobject "^3.0.0" -object.assign@4.1.0, object.assign@^4.1.0: +object.assign@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== @@ -13777,6 +14064,16 @@ object.assign@4.1.0, object.assign@^4.1.0: has-symbols "^1.0.0" object-keys "^1.0.11" +object.assign@^4.1.0, object.assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.1.tgz#303867a666cdd41936ecdedfb1f8f3e32a478cdd" + integrity sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.18.0-next.0" + has-symbols "^1.0.1" + object-keys "^1.1.1" + object.entries@^1.1.0, object.entries@^1.1.1, object.entries@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.2.tgz#bc73f00acb6b6bb16c203434b10f9a7e797d3add" @@ -13833,6 +14130,13 @@ oboe@2.1.4: dependencies: http-https "^1.0.0" +oboe@2.1.5: + version "2.1.5" + resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.5.tgz#5554284c543a2266d7a38f17e073821fbde393cd" + integrity sha1-VVQoTFQ6ImbXo48X4HOCH73jk80= + dependencies: + http-https "^1.0.0" + obs-store@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/obs-store/-/obs-store-4.0.3.tgz#b632ec7814baa604fae084a4c97e87c0b7a6d14c" @@ -13896,14 +14200,6 @@ open@^7.0.0, open@^7.0.2: is-docker "^2.0.0" is-wsl "^2.1.1" -open@^7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/open/-/open-7.2.0.tgz#212959bd7b0ce2e8e3676adc76e3cf2f0a2498b4" - integrity sha512-4HeyhxCvBTI5uBePsAdi55C5fmqnWZ2e2MlmvWi5KW5tdH5rxoiv/aMtbeVxKZc3eWkT1GymMnLG8XC4Rq4TDQ== - dependencies: - is-docker "^2.0.0" - is-wsl "^2.1.1" - opencollective-postinstall@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz#7a0fff978f6dbfa4d006238fbac98ed4198c3259" @@ -14012,6 +14308,13 @@ p-limit@^2.0.0, p-limit@^2.2.0, p-limit@^2.3.0: dependencies: p-try "^2.0.0" +p-limit@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.0.2.tgz#1664e010af3cadc681baafd3e2a437be7b0fb5fe" + integrity sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg== + dependencies: + p-try "^2.0.0" + p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" @@ -14033,6 +14336,13 @@ p-locate@^4.1.0: dependencies: p-limit "^2.2.0" +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + p-map@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" @@ -14091,7 +14401,7 @@ package-json@^6.3.0: registry-url "^5.0.0" semver "^6.2.0" -pako@~1.0.5: +pako@^1.0.4, pako@~1.0.5: version "1.0.11" resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== @@ -14164,13 +14474,13 @@ parse-json@^4.0.0: json-parse-better-errors "^1.0.1" parse-json@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.0.1.tgz#7cfe35c1ccd641bce3981467e6c2ece61b3b3878" - integrity sha512-ztoZ4/DYeXQq4E21v169sC8qWINGpcosGv9XhTDvg9/hWvx/zrFkc9BiWxR58OJLHGk28j5BL0SDLeV2WmFZlQ== + version "5.1.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.1.0.tgz#f96088cdf24a8faa9aea9a009f2d9d942c999646" + integrity sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ== dependencies: "@babel/code-frame" "^7.0.0" error-ex "^1.3.1" - json-parse-better-errors "^1.0.1" + json-parse-even-better-errors "^2.3.0" lines-and-columns "^1.1.6" parse5@4.0.0: @@ -14183,6 +14493,13 @@ parse5@5.1.0: resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.0.tgz#c59341c9723f414c452975564c7c00a68d58acd2" integrity sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ== +parse5@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-3.0.3.tgz#042f792ffdd36851551cf4e9e066b3874ab45b5c" + integrity sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA== + dependencies: + "@types/node" "*" + parseurl@~1.3.2, parseurl@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" @@ -14324,7 +14641,7 @@ performance-now@^2.1.0: resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= -picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.0.7, picomatch@^2.2.1: +picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1: version "2.2.2" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== @@ -14448,14 +14765,14 @@ pocket-js-core@0.0.3: dependencies: axios "^0.18.0" -polished@3.6.5, polished@^3.3.1: +polished@3.6.5: version "3.6.5" resolved "https://registry.yarnpkg.com/polished/-/polished-3.6.5.tgz#dbefdde64c675935ec55119fe2a2ab627ca82e9c" integrity sha512-VwhC9MlhW7O5dg/z7k32dabcAFW1VI2+7fSe8cE/kXcfL7mVdoa5UxciYGW2sJU78ldDLT6+ROEKIZKFNTnUXQ== dependencies: "@babel/runtime" "^7.9.2" -polished@3.6.7: +polished@3.6.7, polished@^3.3.1: version "3.6.7" resolved "https://registry.yarnpkg.com/polished/-/polished-3.6.7.tgz#44cbd0047f3187d83db0c479ef0c7d5583af5fb6" integrity sha512-b4OViUOihwV0icb9PHmWbR+vPqaSzSAEbgLskvb7ANPATVXGiYv/TQFHQo65S53WU9i5EQ1I03YDOJW7K0bmYg== @@ -14509,9 +14826,9 @@ postcss-browser-comments@^3.0.0: postcss "^7" postcss-calc@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.3.tgz#d65cca92a3c52bf27ad37a5f732e0587b74f1623" - integrity sha512-IB/EAEmZhIMEIhG7Ov4x+l47UaXOS1n2f4FBUk/aKllQhtSCxWhTzn0nJgkqN7fo/jcWySvWTSB6Syk9L+31bA== + version "7.0.5" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.5.tgz#f8a6e99f12e619c2ebc23cf6c486fdc15860933e" + integrity sha512-1tKHutbGtLtEZF6PT4JSihCHfIVldU72mZ8SdZHIYriIZ9fh9k9aWSppaT8rHsyI3dX+KSR+W+Ix9BMY3AODrg== dependencies: postcss "^7.0.27" postcss-selector-parser "^6.0.2" @@ -14721,9 +15038,9 @@ postcss-lab-function@^2.0.1: postcss-values-parser "^2.0.0" postcss-load-config@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-2.1.0.tgz#c84d692b7bb7b41ddced94ee62e8ab31b417b003" - integrity sha512-4pV3JJVPLd5+RueiVVB+gFOAa7GWc25XQcMp86Zexzke69mKf6Nx9LRcQywdz7yZI9n1udOxmLuAwTBypypF8Q== + version "2.1.2" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-2.1.2.tgz#c5ea504f2c4aef33c7359a34de3573772ad7502a" + integrity sha512-/rDeGV6vMUo3mwJZmeHfEDvwnTKKqQ0S7OHUi/kJvvtx3aWtyWG2/0ZWnzCt2keEclwN6Tf0DST2v9kITdOKYw== dependencies: cosmiconfig "^5.0.0" import-cwd "^2.0.0" @@ -15097,13 +15414,14 @@ postcss-selector-parser@^5.0.0-rc.3, postcss-selector-parser@^5.0.0-rc.4: uniq "^1.0.1" postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz#934cf799d016c83411859e09dcecade01286ec5c" - integrity sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg== + version "6.0.4" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.4.tgz#56075a1380a04604c38b063ea7767a129af5c2b3" + integrity sha512-gjMeXBempyInaBqpp8gODmwZ52WaYsVOsfr4L4lDQ7n3ncD6mEyySiDtgzCT+NYC0mmeOLvtsF8iaEf0YT6dBw== dependencies: cssesc "^3.0.0" indexes-of "^1.0.1" uniq "^1.0.1" + util-deprecate "^1.0.2" postcss-svgo@^4.0.2: version "4.0.2" @@ -15153,9 +15471,9 @@ postcss@7.0.21: supports-color "^6.1.0" postcss@^7, postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.23, postcss@^7.0.26, postcss@^7.0.27, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6: - version "7.0.32" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.32.tgz#4310d6ee347053da3433db2be492883d62cec59d" - integrity sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw== + version "7.0.35" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.35.tgz#d2be00b998f7f211d8a276974079f2e92b970e24" + integrity sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg== dependencies: chalk "^2.4.2" source-map "^0.6.1" @@ -15167,9 +15485,9 @@ preact@10.4.1: integrity sha512-WKrRpCSwL2t3tpOOGhf2WfTpcmbpxaWtDbdJdKdjd0aEiTkvOmS4NBkG6kzlaAHI9AkQ3iVqbFWM3Ei7mZ4o1Q== preact@^10.3.3: - version "10.4.7" - resolved "https://registry.yarnpkg.com/preact/-/preact-10.4.7.tgz#5a530d34b4ba45f38234be8b1b3fe910098a165f" - integrity sha512-DtnnPbOm7oxW7Sxf5Co+KSIOxo7bGm0vLfJN/wGey7G2sAGKnGP5+bFyE2YIgutMISQl6xFVTsOd6l/Au88VVw== + version "10.5.4" + resolved "https://registry.yarnpkg.com/preact/-/preact-10.5.4.tgz#1e4d148f949fa54656df6c9bc9218bd4e12016e3" + integrity sha512-u0LnVtL9WWF61RLzIbEsVFOdsahoTQkQqeRwyf4eWuLMFrxTH/C47tqcnizbUH54E4KG8UzuuZaMc9KarHmpqQ== prebuild-install@^5.3.3, prebuild-install@^5.3.4: version "5.3.5" @@ -15230,9 +15548,9 @@ prettier@^1.14.2: integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== pretty-bytes@^5.1.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.3.0.tgz#f2849e27db79fb4d6cfe24764fc4134f165989f2" - integrity sha512-hjGrh+P926p4R4WbaB6OckyRtO0F0/lQBiT+0gnxjV+5kjPBrfVBFCsCLbMqVQeydvIoouYTCmmEURiH3R1Bdg== + version "5.4.1" + resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.4.1.tgz#cd89f79bbcef21e3d21eb0da68ffe93f803e884b" + integrity sha512-s1Iam6Gwz3JI5Hweaz4GoCD1WUNUIyzePFy5+Js2hjwGVt2Z79wNN+ZKOZ2vB6C+Xs6njyB84Z1IthQg8d9LxA== pretty-error@^2.1.1: version "2.1.1" @@ -15262,12 +15580,22 @@ pretty-format@^25.2.1, pretty-format@^25.5.0: ansi-styles "^4.0.0" react-is "^16.12.0" -pretty-format@^26.4.2: - version "26.4.2" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.4.2.tgz#d081d032b398e801e2012af2df1214ef75a81237" - integrity sha512-zK6Gd8zDsEiVydOCGLkoBoZuqv8VTiHyAbKznXe/gaph/DAeZOmit9yMfgIz5adIgAMMs5XfoYSwAX3jcCO1tA== +pretty-format@^26.0.0, pretty-format@^26.6.1: + version "26.6.1" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.6.1.tgz#af9a2f63493a856acddeeb11ba6bcf61989660a8" + integrity sha512-MeqqsP5PYcRBbGMvwzsyBdmAJ4EFX7pWFyl7x4+dMVg5pE0ZDdBIvEH2ergvIO+Gvwv1wh64YuOY9y5LuyY/GA== dependencies: - "@jest/types" "^26.3.0" + "@jest/types" "^26.6.1" + ansi-regex "^5.0.0" + ansi-styles "^4.0.0" + react-is "^17.0.1" + +pretty-format@^26.4.2: + version "26.5.2" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.5.2.tgz#5d896acfdaa09210683d34b6dc0e6e21423cd3e1" + integrity sha512-VizyV669eqESlkOikKJI8Ryxl/kPpbdLwNdPs2GrbQs18MpySB5S0Yo0N7zkg2xTRiFq4CFw8ct5Vg4a0xP0og== + dependencies: + "@jest/types" "^26.5.2" ansi-regex "^5.0.0" ansi-styles "^4.0.0" react-is "^16.12.0" @@ -15278,9 +15606,9 @@ pretty-hrtime@^1.0.3: integrity sha1-t+PqQkNaTJsnWdmeDyAesZWALuE= prismjs@^1.8.4: - version "1.20.0" - resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.20.0.tgz#9b685fc480a3514ee7198eac6a3bf5024319ff03" - integrity sha512-AEDjSrVNkynnw6A+B1DsFkd6AVdTnp+/WoUixFRULlCLZVRZlVQMVWio/16jv7G1FscUxQxOQhWwApgbnxr6kQ== + version "1.22.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.22.0.tgz#73c3400afc58a823dd7eed023f8e1ce9fd8977fa" + integrity sha512-lLJ/Wt9yy0AiSYBf212kK3mM5L8ycwlyTlSxHBAneXLR0nzFMlZ5y7riFPF3E33zXOF2IH95xdY5jIyZbM9z/w== optionalDependencies: clipboard "^2.0.0" @@ -15291,7 +15619,7 @@ prismjs@~1.17.0: optionalDependencies: clipboard "^2.0.0" -private@^0.1.6, private@^0.1.8, private@~0.1.5: +private@^0.1.6, private@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== @@ -15381,9 +15709,9 @@ prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, react-is "^16.8.1" property-information@^5.0.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/property-information/-/property-information-5.5.0.tgz#4dc075d493061a82e2b7d096f406e076ed859943" - integrity sha512-RgEbCx2HLa1chNgvChcx+rrCWD0ctBmGSE0M7lVm1yyv4UbvbrWoXp/BkVLZefzjrRBGW8/Js6uh/BnlHXFyjA== + version "5.6.0" + resolved "https://registry.yarnpkg.com/property-information/-/property-information-5.6.0.tgz#61675545fb23002f245c6540ec46077d4da3ed69" + integrity sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA== dependencies: xtend "^4.0.0" @@ -15526,10 +15854,19 @@ qs@~6.5.2: resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== -query-string@6.13.1: - version "6.13.1" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.13.1.tgz#d913ccfce3b4b3a713989fe6d39466d92e71ccad" - integrity sha512-RfoButmcK+yCta1+FuU8REvisx1oEzhMKwhLUNcepQTPGcNMp1sIqjnfCtfnvGSQZQEhaBHvccujtWoUV3TTbA== +query-string@6.13.5: + version "6.13.5" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.13.5.tgz#99e95e2fb7021db90a6f373f990c0c814b3812d8" + integrity sha512-svk3xg9qHR39P3JlHuD7g3nRnyay5mHbrPctEBDUxUkHRifPHXJDhBUycdCC0NBjXoDf44Gb+IsOZL1Uwn8M/Q== + dependencies: + decode-uri-component "^0.2.0" + split-on-first "^1.0.0" + strict-uri-encode "^2.0.0" + +query-string@6.13.6: + version "6.13.6" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.13.6.tgz#e5ac7c74f2a5da43fbca0b883b4f0bafba439966" + integrity sha512-/WWZ7d9na6s2wMEGdVCVgKWE9Rt7nYyNIf7k8xmHXcesPMlEzicWo3lbYwHyA4wBktI2KrXxxZeACLbE84hvSQ== dependencies: decode-uri-component "^0.2.0" split-on-first "^1.0.0" @@ -15745,15 +16082,10 @@ react-docgen-typescript-plugin@^0.5.0: react-docgen-typescript-loader "^3.7.2" tslib "^2.0.0" -react-docgen-typescript@^1.15.0: - version "1.20.2" - resolved "https://registry.yarnpkg.com/react-docgen-typescript/-/react-docgen-typescript-1.20.2.tgz#78f4a14f18a4e236e31051961c75583133752d46" - integrity sha512-tW1cZErh4AxDJIFiTxny9AfMeSwm+NI7BsXXuAXPvoIxToglFWvmJWsJF6sYhSA3zNu3zhFOIMdRMXTzQAyCpA== - -react-docgen-typescript@^1.20.1: - version "1.20.1" - resolved "https://registry.yarnpkg.com/react-docgen-typescript/-/react-docgen-typescript-1.20.1.tgz#774ed8b4a7111acaaa536cad4cfd61c504a46f7e" - integrity sha512-vU6puLsSwfCS+nI/6skQ52sJIx/uW7+9aMI/V/zPHAXr6s8OQzD5LeL9rXx/Hdt2aNfm4yTX9oJ8ClH/5PKQNg== +react-docgen-typescript@^1.15.0, react-docgen-typescript@^1.20.1: + version "1.20.5" + resolved "https://registry.yarnpkg.com/react-docgen-typescript/-/react-docgen-typescript-1.20.5.tgz#fb8d78a707243498436c2952bd3f6f488a68d4f3" + integrity sha512-AbLGMtn76bn7SYBJSSaKJrZ0lgNRRR3qL60PucM5M4v/AXyC8221cKBXW5Pyt9TfDRfe+LDnPNlg7TibxX0ovA== react-docgen@^5.0.0: version "5.3.0" @@ -15769,7 +16101,7 @@ react-docgen@^5.0.0: node-dir "^0.1.10" strip-indent "^3.0.0" -react-dom@16.13.1, react-dom@^16.8.3: +react-dom@16.13.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.13.1.tgz#c1bd37331a0486c078ee54c4740720993b2e0e7f" integrity sha512-81PIMmVLnCNLO/fFOQxdQkvEq/+Hfpv24XNJfpyZhTRfO0QcmQIF/PgCa1zCOj2w1hrn12MFLyaJ/G0+Mxtfag== @@ -15779,6 +16111,16 @@ react-dom@16.13.1, react-dom@^16.8.3: prop-types "^15.6.2" scheduler "^0.19.1" +react-dom@^16.8.3: + version "16.14.0" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.14.0.tgz#7ad838ec29a777fb3c75c3a190f661cf92ab8b89" + integrity sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + prop-types "^15.6.2" + scheduler "^0.19.1" + react-draggable@^4.0.3: version "4.4.3" resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-4.4.3.tgz#0727f2cae5813e36b0e4962bf11b2f9ef2b406f3" @@ -15792,7 +16134,7 @@ react-error-overlay@^6.0.3, react-error-overlay@^6.0.7: resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.7.tgz#1dcfb459ab671d53f660a991513cb2f0a0553108" integrity sha512-TAv1KJFh3RhqxNvhzxj6LeT5NWklP6rDr2a0jaTfsZ5wSZWHOGeqQyejUp3xxLfPt2UpyJEcVQB/zyPcmonNFA== -react-fast-compare@^3.0.1: +react-fast-compare@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb" integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA== @@ -15804,12 +16146,12 @@ react-final-form-listeners@^1.0.2: dependencies: "@babel/runtime" "^7.1.5" -react-final-form@^6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/react-final-form/-/react-final-form-6.5.1.tgz#baf798129d459c669cfda5ce60a77801ef52badc" - integrity sha512-+Hzd9PqYY1Cv3MnWzw64QOl5BjC5BtSDakx+N7Re49r0FASdFhgpXLFFCJ31fvegq2euP6hz6Ow9K6XM9BSqCA== +react-final-form@^6.5.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/react-final-form/-/react-final-form-6.5.2.tgz#d04d1eb7d92eabc6f6c35206bb0eebfc4bfd924b" + integrity sha512-c5l45FYOoxtfpvsvMFh3w2WW8KNxbuebBUrM16rUrooQkewTs0Zahmv0TuKFX5jsC9BKn5Fo84j3ZVXQdURS4w== dependencies: - "@babel/runtime" "^7.10.0" + "@babel/runtime" "^7.12.1" react-focus-lock@^2.1.0: version "2.4.1" @@ -15823,26 +16165,26 @@ react-focus-lock@^2.1.0: use-callback-ref "^1.2.1" use-sidecar "^1.0.1" -react-ga@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/react-ga/-/react-ga-3.1.2.tgz#e13f211c51a2e5c401ea69cf094b9501fe3c51ce" - integrity sha512-OJrMqaHEHbodm+XsnjA6ISBEHTwvpFrxco65mctzl/v3CASMSLSyUkFqz9yYrPDKGBUfNQzKCjuMJwctjlWBbw== +react-ga@3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/react-ga/-/react-ga-3.2.0.tgz#a8ea91e8e681f49d30afcee72d71fc5c71b67d57" + integrity sha512-YHHG5QIzRdDToB9ST1/BrGQhLZPzkrNjoeTu3SZLgwdqzeA9F2XOStuOGXAp1ak/SAo9pyR1Uo/hY0C5wZwfqA== react-helmet-async@^1.0.2: - version "1.0.6" - resolved "https://registry.yarnpkg.com/react-helmet-async/-/react-helmet-async-1.0.6.tgz#11c15c74e79b3f66670c73779bef3e0e352b1d4e" - integrity sha512-t+bhAI4NgxfEv8ez4r77cLfR4O4Z55E/FH2DT+uiE4U7yfWgAk7OAOi7IxHxuYEVLI26bqjZvlVCkpC5/5AoNA== + version "1.0.7" + resolved "https://registry.yarnpkg.com/react-helmet-async/-/react-helmet-async-1.0.7.tgz#b988fbc3abdc4b704982bb74b9cb4a08fcf062c1" + integrity sha512-By90p5uxAriGukbyejq2poK41DwTxpNWOpOjN8mIyX/BKrCd3+sXZ5pHUZXjHyjR5OYS7PGsOD9dbM61YxfFmA== dependencies: - "@babel/runtime" "^7.9.2" + "@babel/runtime" "^7.11.2" invariant "^2.2.4" prop-types "^15.7.2" - react-fast-compare "^3.0.1" + react-fast-compare "^3.2.0" shallowequal "^1.1.0" -react-hot-loader@4.12.21: - version "4.12.21" - resolved "https://registry.yarnpkg.com/react-hot-loader/-/react-hot-loader-4.12.21.tgz#332e830801fb33024b5a147d6b13417f491eb975" - integrity sha512-Ynxa6ROfWUeKWsTHxsrL2KMzujxJVPjs385lmB2t5cHUxdoRPGind9F00tOkdc1l5WBleOF4XEAMILY1KPIIDA== +react-hot-loader@4.13.0: + version "4.13.0" + resolved "https://registry.yarnpkg.com/react-hot-loader/-/react-hot-loader-4.13.0.tgz#c27e9408581c2a678f5316e69c061b226dc6a202" + integrity sha512-JrLlvUPqh6wIkrK2hZDfOyq/Uh/WeVEr8nc7hkn2/3Ul0sx1Kr5y4kOGNacNRoj7RhwLNcQ3Udf1KJXrqc0ZtA== dependencies: fast-levenshtein "^2.0.6" global "^4.3.0" @@ -15874,6 +16216,11 @@ react-is@^16.12.0, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.0, react-i resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== +react-is@^17.0.1: + version "17.0.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.1.tgz#5b3531bd76a645a4c9fb6e693ed36419e3301339" + integrity sha512-NAnt2iGDXohE5LI7uBnLnqvLQMtzhkiAOLXTmv+qnF9Ky7xAPcX8Up/xWIhxvLVGJvuLiNc4xQLtuqDRzb4fSA== + react-lifecycles-compat@^3.0.2, react-lifecycles-compat@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" @@ -16066,7 +16413,7 @@ react-window@^1.8.5: "@babel/runtime" "^7.0.0" memoize-one ">=3.1.1 <6" -react@16.13.1, react@^16.8.3: +react@16.13.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e" integrity sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w== @@ -16075,6 +16422,15 @@ react@16.13.1, react@^16.8.3: object-assign "^4.1.1" prop-types "^15.6.2" +react@^16.8.3: + version "16.14.0" + resolved "https://registry.yarnpkg.com/react/-/react-16.14.0.tgz#94d776ddd0aaa37da3eda8fc5b6b18a4c9a3114d" + integrity sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + prop-types "^15.6.2" + reactive-properties@^0.1.11: version "0.1.12" resolved "https://registry.yarnpkg.com/reactive-properties/-/reactive-properties-0.1.12.tgz#35000ddb9b516bf5ea5b4c41154a45a7a38fdedf" @@ -16210,13 +16566,6 @@ readdirp@^2.2.1: micromatch "^3.1.10" readable-stream "^2.0.2" -readdirp@~3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.3.0.tgz#984458d13a1e42e2e9f5841b129e162f369aff17" - integrity sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ== - dependencies: - picomatch "^2.0.7" - readdirp@~3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.4.0.tgz#9fdccdf9e9155805449221ac645e8303ab5b9ada" @@ -16224,6 +16573,13 @@ readdirp@~3.4.0: dependencies: picomatch "^2.2.1" +readdirp@~3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e" + integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ== + dependencies: + picomatch "^2.2.1" + realpath-native@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.1.0.tgz#2003294fea23fb0672f2476ebe22fcf498a2d65c" @@ -16231,16 +16587,6 @@ realpath-native@^1.1.0: dependencies: util.promisify "^1.0.0" -recast@^0.14.7: - version "0.14.7" - resolved "https://registry.yarnpkg.com/recast/-/recast-0.14.7.tgz#4f1497c2b5826d42a66e8e3c9d80c512983ff61d" - integrity sha512-/nwm9pkrcWagN40JeJhkPaRxiHXBRkXyRh/hgU088Z/v+qCy+zIHHY6bC6o7NaKAxPqtE6nD8zBH1LfU0/Wx6A== - dependencies: - ast-types "0.11.3" - esprima "~4.0.0" - private "~0.1.5" - source-map "~0.6.1" - rechoir@^0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" @@ -16407,10 +16753,10 @@ regexpu-core@^2.0.0: regjsgen "^0.2.0" regjsparser "^0.1.4" -regexpu-core@^4.7.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.0.tgz#fcbf458c50431b0bb7b45d6967b8192d91f3d938" - integrity sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ== +regexpu-core@^4.7.1: + version "4.7.1" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.1.tgz#2dea5a9a07233298fbf0db91fa9abc4c6e0f8ad6" + integrity sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ== dependencies: regenerate "^1.4.0" regenerate-unicode-properties "^8.2.0" @@ -16634,6 +16980,14 @@ resolve@^1.1.6, resolve@^1.10.0, resolve@^1.11.0, resolve@^1.12.0, resolve@^1.13 dependencies: path-parse "^1.0.6" +resolve@^1.18.1: + version "1.18.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.18.1.tgz#018fcb2c5b207d2a6424aee361c5a266da8f4130" + integrity sha512-lDfCPaMKfOJXjy0dPayzPdF1phampNWr3qFCjAu+rw/qbQmr5jWH5xN2hwh9QKfw9E5v4hwV7A+jrCmL8yjjqA== + dependencies: + is-core-module "^2.0.0" + path-parse "^1.0.6" + responselike@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" @@ -16674,6 +17028,11 @@ retry@^0.12.0: resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + rework-visit@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/rework-visit/-/rework-visit-1.0.0.tgz#9945b2803f219e2f7aca00adb8bc9f640f842c9a" @@ -16727,17 +17086,22 @@ rlp@^2.0.0, rlp@^2.2.3, rlp@^2.2.4, rlp@^2.2.6: bn.js "^4.11.1" roarr@^2.15.3: - version "2.15.3" - resolved "https://registry.yarnpkg.com/roarr/-/roarr-2.15.3.tgz#65248a291a15af3ebfd767cbf7e44cb402d1d836" - integrity sha512-AEjYvmAhlyxOeB9OqPUzQCo3kuAkNfuDk/HqWbZdFsqDFpapkTjiw+p4svNEoRLvuqNTxqfL+s+gtD4eDgZ+CA== + version "2.15.4" + resolved "https://registry.yarnpkg.com/roarr/-/roarr-2.15.4.tgz#f5fe795b7b838ccfe35dc608e0282b9eba2e7afd" + integrity sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A== dependencies: - boolean "^3.0.0" + boolean "^3.0.1" detect-node "^2.0.4" globalthis "^1.0.1" json-stringify-safe "^5.0.1" semver-compare "^1.0.0" sprintf-js "^1.1.2" +rpc-payload-id@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/rpc-payload-id/-/rpc-payload-id-1.0.0.tgz#ecd5cd33fa25a280ff9fc45d4ea8e3333ccb564d" + integrity sha512-Nd8ZfqqVtoPqpqz69pGHn+83XKlyGOAkj33MdoNfwnFW+jMWyLYvZsG6rqziu/KECb7hfrdeNa6J9oi0KQUH2w== + rsvp@^4.8.4: version "4.8.5" resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" @@ -16755,6 +17119,11 @@ run-async@^2.2.0, run-async@^2.4.0: resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== +run-parallel@^1.1.9: + version "1.1.10" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.10.tgz#60a51b2ae836636c81377df16cb107351bcd13ef" + integrity sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw== + run-queue@^1.0.0, run-queue@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" @@ -16767,10 +17136,10 @@ rustbn.js@~0.2.0: resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca" integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA== -rxjs@^6.4.0, rxjs@^6.5.2, rxjs@^6.5.3, rxjs@^6.5.4, rxjs@^6.5.5, rxjs@^6.6.0, rxjs@^6.6.2: - version "6.6.2" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.2.tgz#8096a7ac03f2cc4fe5860ef6e572810d9e01c0d2" - integrity sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg== +rxjs@^6.4.0, rxjs@^6.5.2, rxjs@^6.5.3, rxjs@^6.5.4, rxjs@^6.5.5, rxjs@^6.6.0, rxjs@^6.6.2, rxjs@^6.6.3: + version "6.6.3" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.3.tgz#8ca84635c4daa900c0d3967a6ee7ac60271ee552" + integrity sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ== dependencies: tslib "^1.9.0" @@ -16796,6 +17165,11 @@ safe-event-emitter@^1.0.1: dependencies: events "^3.0.0" +safe-json-utils@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/safe-json-utils/-/safe-json-utils-1.0.0.tgz#8b1d68b13cff2ac6a5b68e6c9651cf7f8bb56d9b" + integrity sha512-n0hJm6BgX8wk3G+AS8MOQnfcA8dfE6ZMUfwkHUNx69YxPlU3HDaZTHXWto35Z+C4mOjK1odlT95WutkGC+0Idw== + safe-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" @@ -16886,13 +17260,22 @@ schema-utils@^1.0.0: ajv-keywords "^3.1.0" schema-utils@^2.0.1, schema-utils@^2.5.0, schema-utils@^2.6.0, schema-utils@^2.6.1, schema-utils@^2.6.5, schema-utils@^2.6.6, schema-utils@^2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.0.tgz#17151f76d8eae67fbbf77960c33c676ad9f4efc7" - integrity sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A== + version "2.7.1" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" + integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg== dependencies: - "@types/json-schema" "^7.0.4" - ajv "^6.12.2" - ajv-keywords "^3.4.1" + "@types/json-schema" "^7.0.5" + ajv "^6.12.4" + ajv-keywords "^3.5.2" + +schema-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.0.0.tgz#67502f6aa2b66a2d4032b4279a2944978a0913ef" + integrity sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA== + dependencies: + "@types/json-schema" "^7.0.6" + ajv "^6.12.5" + ajv-keywords "^3.5.2" scrypt-js@2.0.3: version "2.0.3" @@ -16975,11 +17358,11 @@ select@^1.1.2: integrity sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0= selfsigned@^1.10.7: - version "1.10.7" - resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.7.tgz#da5819fd049d5574f28e88a9bcc6dbc6e6f3906b" - integrity sha512-8M3wBCzeWIJnQfl43IKwOmC4H/RAp50S8DF60znzjW5GVqTcSe2vWclt7hmYVPkKPlHWOu5EaWOMZ2Y6W8ZXTA== + version "1.10.8" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.8.tgz#0d17208b7d12c33f8eac85c41835f27fc3d81a30" + integrity sha512-2P4PtieJeEwVgTU9QEcwIRDQ/mXJLX8/+I3ur+Pg16nS8oNbrGxEso9NyYWy8NAmXiNl4dlAp5MwoNeCWzON4w== dependencies: - node-forge "0.9.0" + node-forge "^0.10.0" semaphore@>=1.0.1, semaphore@^1.0.3: version "1.1.0" @@ -17059,19 +17442,7 @@ serialize-error@^7.0.1: dependencies: type-fest "^0.13.1" -serialize-javascript@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-3.0.0.tgz#492e489a2d77b7b804ad391a5f5d97870952548e" - integrity sha512-skZcHYw2vEX4bw90nAr2iTTsz6x2SrHEnfxgKYmZlvJYBEZrvbKtobJWlQ20zczKb3bsHHXXTYt48zBA7ni9cw== - -serialize-javascript@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-3.1.0.tgz#8bf3a9170712664ef2561b44b691eafe399214ea" - integrity sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg== - dependencies: - randombytes "^2.1.0" - -serialize-javascript@^4.0.0: +serialize-javascript@4.0.0, serialize-javascript@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw== @@ -17171,13 +17542,6 @@ sha.js@^2.4.0, sha.js@^2.4.8: inherits "^2.0.1" safe-buffer "^5.0.1" -sha3@^1.2.2: - version "1.2.6" - resolved "https://registry.yarnpkg.com/sha3/-/sha3-1.2.6.tgz#102aa3e47dc793e2357902c3cce8760822f9e905" - integrity sha512-KgLGmJGrmNB4JWVsAV11Yk6KbvsAiygWJc7t5IebWva/0NukNrjJqhtKhzy3Eiv2AKuGvhZZt7dt1mDo7HkoiQ== - dependencies: - nan "2.13.2" - shallow-clone@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-0.1.2.tgz#5909e874ba77106d73ac414cfec1ffca87d97060" @@ -17528,9 +17892,9 @@ spdx-expression-parse@^3.0.0: spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.5" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" - integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== + version "3.0.6" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz#c80757383c28abf7296744998cbc106ae8b854ce" + integrity sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw== spdy-transport@^3.0.0: version "3.0.0" @@ -17684,9 +18048,9 @@ stealthy-require@^1.1.1: integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= store2@^2.7.1: - version "2.11.2" - resolved "https://registry.yarnpkg.com/store2/-/store2-2.11.2.tgz#a298e5e97b21b3ce7419b732540bc7c79cb007db" - integrity sha512-TQMKs+C6n9idtzLpxluikmDCYiDJrTbbIGn9LFxMg0BVTu+8JZKSlXTWYRpOFKlfKD5HlDWLVpJJyNGZ2e9l1A== + version "2.12.0" + resolved "https://registry.yarnpkg.com/store2/-/store2-2.12.0.tgz#e1f1b7e1a59b6083b2596a8d067f6ee88fd4d3cf" + integrity sha512-7t+/wpKLanLzSnQPX8WAcuLCCeuSHoWdQuh9SB3xD0kNOM38DNf+0Oa+wmvxmYueRzkmh6IcdKFtvTa+ecgPDw== store@2.0.12: version "2.0.12" @@ -17825,13 +18189,12 @@ string.prototype.padstart@^3.0.0: es-abstract "^1.17.0-next.1" string.prototype.trim@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.1.tgz#141233dff32c82bfad80684d7e5f0869ee0fb782" - integrity sha512-MjGFEeqixw47dAMFMtgUro/I0+wNqZB5GKXGt1fFr24u3TzDXCPu7J9Buppzoe3r/LqkSDLDDJzE15RGWDGAVw== + version "1.2.2" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.2.tgz#f538d0bacd98fc4297f0bef645226d5aaebf59f3" + integrity sha512-b5yrbl3BXIjHau9Prk7U0RRYcUYdN4wGSVaqoBQS50CCE3KBuYU0TYRNPFCP7aVoNMX87HKThdMRVIP3giclKg== dependencies: define-properties "^1.1.3" - es-abstract "^1.17.0-next.1" - function-bind "^1.1.1" + es-abstract "^1.18.0-next.0" string.prototype.trimend@^1.0.1: version "1.0.1" @@ -17999,12 +18362,12 @@ style-loader@0.23.1: schema-utils "^1.0.0" style-loader@^1.0.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-1.2.1.tgz#c5cbbfbf1170d076cfdd86e0109c5bba114baa1a" - integrity sha512-ByHSTQvHLkWE9Ir5+lGbVOXhxX10fbprhLvdg96wedFZb4NDekDPxVKv5Fwmio+QcMlkkNfuK+5W1peQ5CUhZg== + version "1.3.0" + resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-1.3.0.tgz#828b4a3b3b7e7aa5847ce7bae9e874512114249e" + integrity sha512-V7TCORko8rs9rIqkSrlMfkqA63DfoGBBJmK1kKGCcSi+BWb4cqz0SRsnp4l6rU5iwOEd0/2ePv68SV22VXon4Q== dependencies: loader-utils "^2.0.0" - schema-utils "^2.6.6" + schema-utils "^2.7.0" styled-components@^5.2.0: version "5.2.0" @@ -18038,7 +18401,12 @@ sumchecker@^3.0.1: dependencies: debug "^4.1.0" -supports-color@7.1.0, supports-color@^7.0.0, supports-color@^7.1.0: +super-split@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/super-split/-/super-split-1.1.0.tgz#43b3ba719155f4d43891a32729d59b213d9155fc" + integrity sha512-I4bA5mgcb6Fw5UJ+EkpzqXfiuvVGS/7MuND+oBxNFmxu3ugLNrdIatzBLfhFRMVMLxgSsRy+TjIktgkF9RFSNQ== + +supports-color@7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== @@ -18064,6 +18432,13 @@ supports-color@^6.1.0: dependencies: has-flag "^3.0.0" +supports-color@^7.0.0, supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + svg-parser@^2.0.0: version "2.0.4" resolved "https://registry.yarnpkg.com/svg-parser/-/svg-parser-2.0.4.tgz#fdc2e29e13951736140b76cb122c8ee6630eb6b5" @@ -18201,11 +18576,11 @@ tar-stream@^1.5.2: xtend "^4.0.0" tar-stream@^2.0.0: - version "2.1.3" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.1.3.tgz#1e2022559221b7866161660f118255e20fa79e41" - integrity sha512-Z9yri56Dih8IaK8gncVPx4Wqt86NDmQTSh49XLZgjWpGZL9GK9HKParS2scqHCC4w6X9Gh2jwaU45V47XTKwVA== + version "2.1.4" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.1.4.tgz#c4fb1a11eb0da29b893a5b25476397ba2d053bfa" + integrity sha512-o3pS2zlG4gxr67GmFYBLlq+dM8gyRGUOvsrHclSkvtVtQbjV0s/+ZE8OpICbaj8clrX3tjeHngYGP7rweaBnuw== dependencies: - bl "^4.0.1" + bl "^4.0.3" end-of-stream "^1.4.1" fs-constants "^1.0.0" inherits "^2.0.3" @@ -18251,7 +18626,7 @@ term-size@^2.1.0: resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.0.tgz#1f16adedfe9bdc18800e1776821734086fcc6753" integrity sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw== -terser-webpack-plugin@2.3.8: +terser-webpack-plugin@2.3.8, terser-webpack-plugin@^2.1.2: version "2.3.8" resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-2.3.8.tgz#894764a19b0743f2f704e7c2a848c5283a696724" integrity sha512-/fKw3R+hWyHfYx7Bv6oPqmk4HGQcrWLtV3X6ggvPuwPNHSnzvVV51z6OaaCOus4YLjutYGOz3pEpbhe6Up2s1w== @@ -18281,21 +18656,6 @@ terser-webpack-plugin@^1.4.3: webpack-sources "^1.4.0" worker-farm "^1.7.0" -terser-webpack-plugin@^2.1.2: - version "2.3.7" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-2.3.7.tgz#4910ff5d1a872168cc7fa6cd3749e2b0d60a8a0b" - integrity sha512-xzYyaHUNhzgaAdBsXxk2Yvo/x1NJdslUaussK3fdpBbvttm1iIwU+c26dj9UxJcwk2c5UWt5F55MUTIA8BE7Dg== - dependencies: - cacache "^13.0.1" - find-cache-dir "^3.3.1" - jest-worker "^25.4.0" - p-limit "^2.3.0" - schema-utils "^2.6.6" - serialize-javascript "^3.1.0" - source-map "^0.6.1" - terser "^4.6.12" - webpack-sources "^1.4.3" - terser@^4.1.2, terser@^4.6.12, terser@^4.6.3: version "4.8.0" resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.0.tgz#63056343d7c70bb29f3af665865a46fe03a0df17" @@ -18334,9 +18694,9 @@ throat@^4.0.0: integrity sha1-iQN8vJLFarGJJua6TLsgDhVnKmo= throttle-debounce@^2.1.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/throttle-debounce/-/throttle-debounce-2.2.1.tgz#fbd933ae6793448816f7d5b3cae259d464c98137" - integrity sha512-i9hAVld1f+woAiyNGqWelpDD5W1tpMroL3NofTz9xzwq6acWBlO2dC8k5EFSZepU6oOINtV5Q3aSPoRg7o4+fA== + version "2.3.0" + resolved "https://registry.yarnpkg.com/throttle-debounce/-/throttle-debounce-2.3.0.tgz#fd31865e66502071e411817e241465b3e9c372e2" + integrity sha512-H7oLPV0P7+jgvrk+6mwwwBDmxTaxnu9HMXmloNLXwnNO0ZxZ31Orah2n8lU1eMPvsaowP2CX+USCgyovXfdOFQ== through2@^2.0.0, through2@^2.0.3: version "2.0.5" @@ -18514,13 +18874,13 @@ tree-kill@^1.2.2: integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== trezor-connect@^8.1.9: - version "8.1.11" - resolved "https://registry.yarnpkg.com/trezor-connect/-/trezor-connect-8.1.11.tgz#b1a6d492307b83751968515b4480b8510172415b" - integrity sha512-15m+jZ0No96tUlsnMRoFykreMkpsVpwN+9i2j28OvKn0+frLAEzzeLpl1ndyykzRVD84mQV5c6GFhneo9ivNmA== + version "8.1.16" + resolved "https://registry.yarnpkg.com/trezor-connect/-/trezor-connect-8.1.16.tgz#a634b16c436311f3833aa0a6a36089c95ba4f6fd" + integrity sha512-HYSYsJk0js+OFUjO7ebsUunjYBpoUcjHI5iDBeaDoefBl0FT/Qwf6o1sd2IYVVmVCL/MtqxZ6by+/Z0/GaFBNw== dependencies: - "@babel/runtime" "^7.11.0" + "@babel/runtime" "^7.11.2" events "^3.2.0" - whatwg-fetch "^3.3.1" + whatwg-fetch "^3.4.1" trim-newlines@^1.0.0: version "1.0.0" @@ -18544,39 +18904,13 @@ trim-right@^1.0.1: dependencies: glob "^7.1.2" -truffle-contract@4.0.31: - version "4.0.31" - resolved "https://registry.yarnpkg.com/truffle-contract/-/truffle-contract-4.0.31.tgz#e43b7f648e2db352c857d1202d710029b107b68d" - integrity sha512-u3q+p1wiX5C2GpnluGx/d2iaJk7bcWshk2/TohiJyA2iQiTfkS7M4n9D9tY3JqpXR8PmD/TrA69RylO0RhITFA== - dependencies: - "@truffle/blockchain-utils" "^0.0.11" - "@truffle/contract-schema" "^3.0.14" - "@truffle/error" "^0.0.6" - bignumber.js "^7.2.1" - ethers "^4.0.0-beta.1" - truffle-interface-adapter "^0.2.5" - web3 "1.2.1" - web3-core-promievent "1.2.1" - web3-eth-abi "1.2.1" - web3-utils "1.2.1" - -truffle-interface-adapter@^0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/truffle-interface-adapter/-/truffle-interface-adapter-0.2.5.tgz#aa0bee635517b4a8e06adcdc99eacb993e68c243" - integrity sha512-EL39OpP8FcZ99ne1Rno3jImfb92Nectd4iVsZzoEUCBfbwHe7sr0k+i45guoruSoP8nMUE81Mov2s8I5pi6d9Q== - dependencies: - bn.js "^4.11.8" - ethers "^4.0.32" - lodash "^4.17.13" - web3 "1.2.1" - truffle@^5.1.21: - version "5.1.40" - resolved "https://registry.yarnpkg.com/truffle/-/truffle-5.1.40.tgz#f93a147612b3b083354808dd0abbe6723bd04f7f" - integrity sha512-frlNrytZLxy3PwN6SZ7oL7wmXr+tyNw3oDq3GwAwI7EM/koRwIyCNvSxnwTBtzYyC7Z4D0BOGQUnCh/Tuv451Q== + version "5.1.48" + resolved "https://registry.yarnpkg.com/truffle/-/truffle-5.1.48.tgz#43c78cb1fa8f51496a66de7bddfd6726ad132676" + integrity sha512-Z8485qH5Db8P05dVy7SHQHcaa+hXAekvPcVkkv8zONsVBqOmS3q48eajukdeKNbLlfPWb3m7TYdPzrGFBDcFiQ== dependencies: app-module-path "^2.2.0" - mocha "8.0.1" + mocha "8.1.2" original-require "1.0.1" truncate-utf8-bytes@^1.0.0: @@ -18587,9 +18921,9 @@ truncate-utf8-bytes@^1.0.0: utf8-byte-length "^1.0.1" ts-dedent@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ts-dedent/-/ts-dedent-1.1.1.tgz#68fad040d7dbd53a90f545b450702340e17d18f3" - integrity sha512-UGTRZu1evMw4uTPyYF66/KFd22XiU+jMaIuHrkIHQ2GivAXVlLV0v/vHrpOuTRf9BmpNHi/SO7Vd0rLu0y57jg== + version "1.2.0" + resolved "https://registry.yarnpkg.com/ts-dedent/-/ts-dedent-1.2.0.tgz#6aa2229d837159bb6d635b6b233002423b91e0b0" + integrity sha512-6zSJp23uQI+Txyz5LlXMXAHpUhY4Hi0oluXny0OgIR7g/Cromq4vDBnhtbBdyIV34g0pgwxUvnvg+jLJe4c1NA== ts-essentials@^1.0.0: version "1.0.4" @@ -18637,14 +18971,14 @@ tsconfig-paths@^3.9.0: strip-bom "^3.0.0" tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: - version "1.13.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" - integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.0.tgz#18d13fc2dce04051e20f074cc8387fd8089ce4f3" - integrity sha512-lTqkx847PI7xEDYJntxZH89L2/aXInsyF2luSafe/+0fHOMjlBNXdH6th7f70qxLDhul7KZK0zC8V5ZIyHl0/g== +tslib@^2.0.0, tslib@^2.0.1: + version "2.0.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.3.tgz#8e0741ac45fc0c226e58a17bfc3e64b9bc6ca61c" + integrity sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ== tsutils@^3.17.1: version "3.17.1" @@ -18726,9 +19060,9 @@ type@^2.0.0: integrity sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA== typechain@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/typechain/-/typechain-2.0.0.tgz#62143b48cdf8f95a777f1b76617af077b2d44eee" - integrity sha512-O+hsAUwtBpqCfoq46Grm52OEdm0GBEu78LxrEzkkGdwUdCoCZpNb2HPzPoNB1MXiRnNhEOGMFyf05UbT2/bUEw== + version "2.0.1" + resolved "https://registry.yarnpkg.com/typechain/-/typechain-2.0.1.tgz#4fa91006d871e5805d41f265880603d0817b74d6" + integrity sha512-GVigpARnr2tV9L+8WecF5huK+qEonNgh+Vp9UR/EayoTV4+3G8Yabhvf+p/QJVOz3JLM4Eo3ERxYmjjJMRXc/A== dependencies: command-line-args "^4.0.7" debug "^4.1.1" @@ -18755,10 +19089,10 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@3.9.7: - version "3.9.7" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa" - integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw== +typescript@4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.5.tgz#ae9dddfd1069f1cb5beb3ef3b2170dd7c1332389" + integrity sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ== typical@^2.6.0, typical@^2.6.1: version "2.6.1" @@ -18771,9 +19105,9 @@ u2f-api@0.2.7: integrity sha512-fqLNg8vpvLOD5J/z4B6wpPg4Lvowz1nJ9xdHcCzdUPKcFE/qNCceV2gNZxSJd5vhAZemHr/K/hbzVA0zxB5mkg== ua-parser-js@^0.7.18: - version "0.7.21" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.21.tgz#853cf9ce93f642f67174273cc34565ae6f308777" - integrity sha512-+O8/qh/Qj8CgC6eYBVBykMrNtp5Gebn4dlGD/kKXVkJNDwyrAwSIqwz8CDf+tsAIWVycKcku6gIXJ0qwx/ZXaQ== + version "0.7.22" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.22.tgz#960df60a5f911ea8f1c818f3747b99c6e177eae3" + integrity sha512-YUxzMjJ5T71w6a8WWVcMGM6YWOTX27rCoIQgLXiWaxqXSx9D7DNjiGWn1aJIRSQ5qr0xuhra77bSIh6voR/46Q== ultron@~1.1.0: version "1.1.1" @@ -18793,10 +19127,15 @@ underscore@1.9.1: resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== +underscore@^1.8.3: + version "1.11.0" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.11.0.tgz#dd7c23a195db34267186044649870ff1bab5929e" + integrity sha512-xY96SsN3NA461qIRKZ/+qox37YXPtSBswMGfiNptr+wrt6ds4HaMw23TP612fEyGekRE6LNRiLYr/aqbHXNedw== + unfetch@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/unfetch/-/unfetch-4.1.0.tgz#6ec2dd0de887e58a4dee83a050ded80ffc4137db" - integrity sha512-crP/n3eAPUJxZXM9T80/yv0YhkTEx2K1D3h7D1AJM6fzsWZrxdyRuLN0JH/dkZh1LNH8LxCnBzoPFCPbb2iGpg== + version "4.2.0" + resolved "https://registry.yarnpkg.com/unfetch/-/unfetch-4.2.0.tgz#7e21b0ef7d363d8d9af0fb929a5555f6ef97a3be" + integrity sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA== unicode-canonical-property-names-ecmascript@^1.0.4: version "1.0.4" @@ -18896,9 +19235,9 @@ upath@^1.1.1: integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== update-notifier@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-4.1.1.tgz#895fc8562bbe666179500f9f2cebac4f26323746" - integrity sha512-9y+Kds0+LoLG6yN802wVXoIfxYEwh3FlZwzMwpCZp62S2i1/Jzeqb9Eeeju3NSHccGGasfGlK5/vEHbAifYRDg== + version "4.1.3" + resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-4.1.3.tgz#be86ee13e8ce48fb50043ff72057b5bd598e1ea3" + integrity sha512-Yld6Z0RyCYGB6ckIjffGOSOmHXj1gMeE7aROz4MG+XMkmixBX4jUngrGXNYz7wPKBmtoD4MnBa2Anu7RSKht/A== dependencies: boxen "^4.2.0" chalk "^3.0.0" @@ -18915,9 +19254,9 @@ update-notifier@^4.1.0: xdg-basedir "^4.0.0" uri-js@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" - integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== + version "4.4.0" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.0.tgz#aa714261de793e8a82347a7bcc9ce74e86f28602" + integrity sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g== dependencies: punycode "^2.1.0" @@ -18936,13 +19275,13 @@ url-loader@2.3.0, url-loader@^2.0.1: schema-utils "^2.5.0" url-loader@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-4.1.0.tgz#c7d6b0d6b0fccd51ab3ffc58a78d32b8d89a7be2" - integrity sha512-IzgAAIC8wRrg6NYkFIJY09vtktQcsvU8V6HhtQj9PTefbYImzLB1hufqo4m+RyM5N3mLx5BqJKccgxJS+W3kqw== + version "4.1.1" + resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-4.1.1.tgz#28505e905cae158cf07c92ca622d7f237e70a4e2" + integrity sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA== dependencies: loader-utils "^2.0.0" - mime-types "^2.1.26" - schema-utils "^2.6.5" + mime-types "^2.1.27" + schema-utils "^3.0.0" url-parse-lax@^1.0.0: version "1.0.0" @@ -19011,6 +19350,13 @@ use@^3.1.0: resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== +utf-8-validate@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.2.tgz#63cfbccd85dc1f2b66cf7a1d0eebc08ed056bfb3" + integrity sha512-SwV++i2gTD5qh2XqaPzBnNX88N6HdyhQrNNRykvcS0QKvItV9u3vPEJr+X5Hhfb1JC0r0e1alL0iB09rY8+nmw== + dependencies: + node-gyp-build "~3.7.0" + utf8-byte-length@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz#f45f150c4c66eee968186505ab93fcbb8ad6bf61" @@ -19119,9 +19465,9 @@ value-equal@^1.0.1: integrity sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw== varint@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.0.tgz#d826b89f7490732fabc0c0ed693ed475dcb29ebf" - integrity sha1-2Ca4n3SQcy+rwMDtaT7Uddyynr8= + version "5.0.2" + resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.2.tgz#5b47f8a947eb668b848e034dcfa87d0ff8a7f7a4" + integrity sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow== vary@^1, vary@~1.1.2: version "1.1.2" @@ -19233,16 +19579,6 @@ web3-bzz@1.2.1: swarm-js "0.1.39" underscore "1.9.1" -web3-bzz@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.2.11.tgz#41bc19a77444bd5365744596d778b811880f707f" - integrity sha512-XGpWUEElGypBjeFyUhTkiPXFbDVD6Nr/S5jznE3t8cWUA0FxRf1n3n/NuIZeb0H9RkN2Ctd/jNma/k8XGa3YKg== - dependencies: - "@types/node" "^12.12.6" - got "9.6.0" - swarm-js "^0.1.40" - underscore "1.9.1" - web3-bzz@1.2.9: version "1.2.9" resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.2.9.tgz#25f8a373bc2dd019f47bf80523546f98b93c8790" @@ -19253,6 +19589,16 @@ web3-bzz@1.2.9: swarm-js "^0.1.40" underscore "1.9.1" +web3-bzz@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.3.0.tgz#83dfd77fa8a64bbb660462dffd0fee2a02ef1051" + integrity sha512-ibYAnKab+sgTo/UdfbrvYfWblXjjgSMgyy9/FHa6WXS14n/HVB+HfWqGz2EM3fok8Wy5XoKGMvdqvERQ/mzq1w== + dependencies: + "@types/node" "^12.12.6" + got "9.6.0" + swarm-js "^0.1.40" + underscore "1.9.1" + web3-core-helpers@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.2.1.tgz#f5f32d71c60a4a3bd14786118e633ce7ca6d5d0d" @@ -19262,15 +19608,6 @@ web3-core-helpers@1.2.1: web3-eth-iban "1.2.1" web3-utils "1.2.1" -web3-core-helpers@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.2.11.tgz#84c681ed0b942c0203f3b324a245a127e8c67a99" - integrity sha512-PEPoAoZd5ME7UfbnCZBdzIerpe74GEvlwT4AjOmHeCVZoIFk7EqvOZDejJHt+feJA6kMVTdd0xzRNN295UhC1A== - dependencies: - underscore "1.9.1" - web3-eth-iban "1.2.11" - web3-utils "1.2.11" - web3-core-helpers@1.2.9: version "1.2.9" resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.2.9.tgz#6381077c3e01c127018cb9e9e3d1422697123315" @@ -19280,6 +19617,15 @@ web3-core-helpers@1.2.9: web3-eth-iban "1.2.9" web3-utils "1.2.9" +web3-core-helpers@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.3.0.tgz#697cc3246a7eaaaac64ea506828d861c981c3f31" + integrity sha512-+MFb1kZCrRctf7UYE7NCG4rGhSXaQJ/KF07di9GVK1pxy1K0+rFi61ZobuV1ky9uQp+uhhSPts4Zp55kRDB5sw== + dependencies: + underscore "1.9.1" + web3-eth-iban "1.3.0" + web3-utils "1.3.0" + web3-core-method@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.2.1.tgz#9df1bafa2cd8be9d9937e01c6a47fc768d15d90a" @@ -19291,18 +19637,6 @@ web3-core-method@1.2.1: web3-core-subscriptions "1.2.1" web3-utils "1.2.1" -web3-core-method@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.2.11.tgz#f880137d1507a0124912bf052534f168b8d8fbb6" - integrity sha512-ff0q76Cde94HAxLDZ6DbdmKniYCQVtvuaYh+rtOUMB6kssa5FX0q3vPmixi7NPooFnbKmmZCM6NvXg4IreTPIw== - dependencies: - "@ethersproject/transactions" "^5.0.0-beta.135" - underscore "1.9.1" - web3-core-helpers "1.2.11" - web3-core-promievent "1.2.11" - web3-core-subscriptions "1.2.11" - web3-utils "1.2.11" - web3-core-method@1.2.9: version "1.2.9" resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.2.9.tgz#3fb538751029bea570e4f86731e2fa5e4945e462" @@ -19315,6 +19649,18 @@ web3-core-method@1.2.9: web3-core-subscriptions "1.2.9" web3-utils "1.2.9" +web3-core-method@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.3.0.tgz#a71387af842aec7dbad5dbbd1130c14cc6c8beb3" + integrity sha512-h0yFDrYVzy5WkLxC/C3q+hiMnzxdWm9p1T1rslnuHgOp6nYfqzu/6mUIXrsS4h/OWiGJt+BZ0xVZmtC31HDWtg== + dependencies: + "@ethersproject/transactions" "^5.0.0-beta.135" + underscore "1.9.1" + web3-core-helpers "1.3.0" + web3-core-promievent "1.3.0" + web3-core-subscriptions "1.3.0" + web3-utils "1.3.0" + web3-core-promievent@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.2.1.tgz#003e8a3eb82fb27b6164a6d5b9cad04acf733838" @@ -19323,13 +19669,6 @@ web3-core-promievent@1.2.1: any-promise "1.3.0" eventemitter3 "3.1.2" -web3-core-promievent@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.2.11.tgz#51fe97ca0ddec2f99bf8c3306a7a8e4b094ea3cf" - integrity sha512-il4McoDa/Ox9Agh4kyfQ8Ak/9ABYpnF8poBLL33R/EnxLsJOGQG2nZhkJa3I067hocrPSjEdlPt/0bHXsln4qA== - dependencies: - eventemitter3 "4.0.4" - web3-core-promievent@1.2.9: version "1.2.9" resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.2.9.tgz#bb1c56aa6fac2f4b3c598510f06554d25c11c553" @@ -19337,6 +19676,13 @@ web3-core-promievent@1.2.9: dependencies: eventemitter3 "3.1.2" +web3-core-promievent@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.3.0.tgz#e0442dd0a8989b6bdce09293976cee6d9237a484" + integrity sha512-blv69wrXw447TP3iPvYJpllkhW6B18nfuEbrfcr3n2Y0v1Jx8VJacNZFDFsFIcgXcgUIVCtOpimU7w9v4+rtaw== + dependencies: + eventemitter3 "4.0.4" + web3-core-requestmanager@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.2.1.tgz#fa2e2206c3d738db38db7c8fe9c107006f5c6e3d" @@ -19348,17 +19694,6 @@ web3-core-requestmanager@1.2.1: web3-providers-ipc "1.2.1" web3-providers-ws "1.2.1" -web3-core-requestmanager@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.2.11.tgz#fe6eb603fbaee18530293a91f8cf26d8ae28c45a" - integrity sha512-oFhBtLfOiIbmfl6T6gYjjj9igOvtyxJ+fjS+byRxiwFJyJ5BQOz4/9/17gWR1Cq74paTlI7vDGxYfuvfE/mKvA== - dependencies: - underscore "1.9.1" - web3-core-helpers "1.2.11" - web3-providers-http "1.2.11" - web3-providers-ipc "1.2.11" - web3-providers-ws "1.2.11" - web3-core-requestmanager@1.2.9: version "1.2.9" resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.2.9.tgz#dd6d855256c4dd681434fe0867f8cd742fe10503" @@ -19370,6 +19705,17 @@ web3-core-requestmanager@1.2.9: web3-providers-ipc "1.2.9" web3-providers-ws "1.2.9" +web3-core-requestmanager@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.3.0.tgz#c5b9a0304504c0e6cce6c90bc1a3bff82732aa1f" + integrity sha512-3yMbuGcomtzlmvTVqNRydxsx7oPlw3ioRL6ReF9PeNYDkUsZaUib+6Dp5eBt7UXh5X+SIn/xa1smhDHz5/HpAw== + dependencies: + underscore "1.9.1" + web3-core-helpers "1.3.0" + web3-providers-http "1.3.0" + web3-providers-ipc "1.3.0" + web3-providers-ws "1.3.0" + web3-core-subscriptions@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.2.1.tgz#8c2368a839d4eec1c01a4b5650bbeb82d0e4a099" @@ -19379,15 +19725,6 @@ web3-core-subscriptions@1.2.1: underscore "1.9.1" web3-core-helpers "1.2.1" -web3-core-subscriptions@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.2.11.tgz#beca908fbfcb050c16f45f3f0f4c205e8505accd" - integrity sha512-qEF/OVqkCvQ7MPs1JylIZCZkin0aKK9lDxpAtQ1F8niEDGFqn7DT8E/vzbIa0GsOjL2fZjDhWJsaW+BSoAW1gg== - dependencies: - eventemitter3 "4.0.4" - underscore "1.9.1" - web3-core-helpers "1.2.11" - web3-core-subscriptions@1.2.9: version "1.2.9" resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.2.9.tgz#335fd7d15dfce5d78b4b7bef05ce4b3d7237b0e4" @@ -19397,6 +19734,15 @@ web3-core-subscriptions@1.2.9: underscore "1.9.1" web3-core-helpers "1.2.9" +web3-core-subscriptions@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.3.0.tgz#c2622ccd2b84f4687475398ff966b579dba0847e" + integrity sha512-MUUQUAhJDb+Nz3S97ExVWveH4utoUnsbPWP+q1HJH437hEGb4vunIb9KvN3hFHLB+aHJfPeStM/4yYTz5PeuyQ== + dependencies: + eventemitter3 "4.0.4" + underscore "1.9.1" + web3-core-helpers "1.3.0" + web3-core@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.2.1.tgz#7278b58fb6495065e73a77efbbce781a7fddf1a9" @@ -19407,19 +19753,6 @@ web3-core@1.2.1: web3-core-requestmanager "1.2.1" web3-utils "1.2.1" -web3-core@1.2.11, web3-core@^1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.2.11.tgz#1043cacc1becb80638453cc5b2a14be9050288a7" - integrity sha512-CN7MEYOY5ryo5iVleIWRE3a3cZqVaLlIbIzDPsvQRUfzYnvzZQRZBm9Mq+ttDi2STOOzc1MKylspz/o3yq/LjQ== - dependencies: - "@types/bn.js" "^4.11.5" - "@types/node" "^12.12.6" - bignumber.js "^9.0.0" - web3-core-helpers "1.2.11" - web3-core-method "1.2.11" - web3-core-requestmanager "1.2.11" - web3-utils "1.2.11" - web3-core@1.2.9: version "1.2.9" resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.2.9.tgz#2cba57aa259b6409db532d21bdf57db8d504fd3e" @@ -19433,6 +19766,19 @@ web3-core@1.2.9: web3-core-requestmanager "1.2.9" web3-utils "1.2.9" +web3-core@1.3.0, web3-core@^1.2.11, web3-core@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.3.0.tgz#b818903738461c1cca0163339e1d6d3fa51242cf" + integrity sha512-BwWvAaKJf4KFG9QsKRi3MNoNgzjI6szyUlgme1qNPxUdCkaS3Rdpa0VKYNHP7M/YTk82/59kNE66mH5vmoaXjA== + dependencies: + "@types/bn.js" "^4.11.5" + "@types/node" "^12.12.6" + bignumber.js "^9.0.0" + web3-core-helpers "1.3.0" + web3-core-method "1.3.0" + web3-core-requestmanager "1.3.0" + web3-utils "1.3.0" + web3-eth-abi@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.2.1.tgz#9b915b1c9ebf82f70cca631147035d5419064689" @@ -19442,15 +19788,6 @@ web3-eth-abi@1.2.1: underscore "1.9.1" web3-utils "1.2.1" -web3-eth-abi@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.2.11.tgz#a887494e5d447c2926d557a3834edd66e17af9b0" - integrity sha512-PkRYc0+MjuLSgg03QVWqWlQivJqRwKItKtEpRUaxUAeLE7i/uU39gmzm2keHGcQXo3POXAbOnMqkDvOep89Crg== - dependencies: - "@ethersproject/abi" "5.0.0-beta.153" - underscore "1.9.1" - web3-utils "1.2.11" - web3-eth-abi@1.2.9: version "1.2.9" resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.2.9.tgz#14bedd7e4be04fcca35b2ac84af1400574cd8280" @@ -19460,6 +19797,15 @@ web3-eth-abi@1.2.9: underscore "1.9.1" web3-utils "1.2.9" +web3-eth-abi@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.3.0.tgz#387b7ea9b38be69ad8856bc7b4e9a6a69bb4d22b" + integrity sha512-1OrZ9+KGrBeBRd3lO8upkpNua9+7cBsQAgor9wbA25UrcUYSyL8teV66JNRu9gFxaTbkpdrGqM7J/LXpraXWrg== + dependencies: + "@ethersproject/abi" "5.0.0-beta.153" + underscore "1.9.1" + web3-utils "1.3.0" + web3-eth-accounts@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.2.1.tgz#2741a8ef337a7219d57959ac8bd118b9d68d63cf" @@ -19477,23 +19823,6 @@ web3-eth-accounts@1.2.1: web3-core-method "1.2.1" web3-utils "1.2.1" -web3-eth-accounts@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.2.11.tgz#a9e3044da442d31903a7ce035a86d8fa33f90520" - integrity sha512-6FwPqEpCfKIh3nSSGeo3uBm2iFSnFJDfwL3oS9pyegRBXNsGRVpgiW63yhNzL0796StsvjHWwQnQHsZNxWAkGw== - dependencies: - crypto-browserify "3.12.0" - eth-lib "0.2.8" - ethereumjs-common "^1.3.2" - ethereumjs-tx "^2.1.1" - scrypt-js "^3.0.1" - underscore "1.9.1" - uuid "3.3.2" - web3-core "1.2.11" - web3-core-helpers "1.2.11" - web3-core-method "1.2.11" - web3-utils "1.2.11" - web3-eth-accounts@1.2.9: version "1.2.9" resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.2.9.tgz#7ec422df90fecb5243603ea49dc28726db7bdab6" @@ -19511,6 +19840,23 @@ web3-eth-accounts@1.2.9: web3-core-method "1.2.9" web3-utils "1.2.9" +web3-eth-accounts@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.3.0.tgz#010acf389b2bee6d5e1aecb2fe78bfa5c8f26c7a" + integrity sha512-/Q7EVW4L2wWUbNRtOTwAIrYvJid/5UnKMw67x/JpvRMwYC+e+744P536Ja6SG4X3MnzFvd3E/jruV4qa6k+zIw== + dependencies: + crypto-browserify "3.12.0" + eth-lib "0.2.8" + ethereumjs-common "^1.3.2" + ethereumjs-tx "^2.1.1" + scrypt-js "^3.0.1" + underscore "1.9.1" + uuid "3.3.2" + web3-core "1.3.0" + web3-core-helpers "1.3.0" + web3-core-method "1.3.0" + web3-utils "1.3.0" + web3-eth-contract@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.2.1.tgz#3542424f3d341386fd9ff65e78060b85ac0ea8c4" @@ -19525,21 +19871,6 @@ web3-eth-contract@1.2.1: web3-eth-abi "1.2.1" web3-utils "1.2.1" -web3-eth-contract@1.2.11, web3-eth-contract@^1.2.11, web3-eth-contract@^1.2.9: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.2.11.tgz#917065902bc27ce89da9a1da26e62ef663663b90" - integrity sha512-MzYuI/Rq2o6gn7vCGcnQgco63isPNK5lMAan2E51AJLknjSLnOxwNY3gM8BcKoy4Z+v5Dv00a03Xuk78JowFow== - dependencies: - "@types/bn.js" "^4.11.5" - underscore "1.9.1" - web3-core "1.2.11" - web3-core-helpers "1.2.11" - web3-core-method "1.2.11" - web3-core-promievent "1.2.11" - web3-core-subscriptions "1.2.11" - web3-eth-abi "1.2.11" - web3-utils "1.2.11" - web3-eth-contract@1.2.9: version "1.2.9" resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.2.9.tgz#713d9c6d502d8c8f22b696b7ffd8e254444e6bfd" @@ -19555,6 +19886,21 @@ web3-eth-contract@1.2.9: web3-eth-abi "1.2.9" web3-utils "1.2.9" +web3-eth-contract@1.3.0, web3-eth-contract@^1.2.11, web3-eth-contract@^1.2.9: + version "1.3.0" + resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.3.0.tgz#c758340ac800788e29fa29edc8b0c0ac957b741c" + integrity sha512-3SCge4SRNCnzLxf0R+sXk6vyTOl05g80Z5+9/B5pERwtPpPWaQGw8w01vqYqsYBKC7zH+dxhMaUgVzU2Dgf7bQ== + dependencies: + "@types/bn.js" "^4.11.5" + underscore "1.9.1" + web3-core "1.3.0" + web3-core-helpers "1.3.0" + web3-core-method "1.3.0" + web3-core-promievent "1.3.0" + web3-core-subscriptions "1.3.0" + web3-eth-abi "1.3.0" + web3-utils "1.3.0" + web3-eth-ens@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.2.1.tgz#a0e52eee68c42a8b9865ceb04e5fb022c2d971d5" @@ -19569,21 +19915,6 @@ web3-eth-ens@1.2.1: web3-eth-contract "1.2.1" web3-utils "1.2.1" -web3-eth-ens@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.2.11.tgz#26d4d7f16d6cbcfff918e39832b939edc3162532" - integrity sha512-dbW7dXP6HqT1EAPvnniZVnmw6TmQEKF6/1KgAxbo8iBBYrVTMDGFQUUnZ+C4VETGrwwaqtX4L9d/FrQhZ6SUiA== - dependencies: - content-hash "^2.5.2" - eth-ens-namehash "2.0.8" - underscore "1.9.1" - web3-core "1.2.11" - web3-core-helpers "1.2.11" - web3-core-promievent "1.2.11" - web3-eth-abi "1.2.11" - web3-eth-contract "1.2.11" - web3-utils "1.2.11" - web3-eth-ens@1.2.9: version "1.2.9" resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.2.9.tgz#577b9358c036337833fb2bdc59c11be7f6f731b6" @@ -19599,6 +19930,21 @@ web3-eth-ens@1.2.9: web3-eth-contract "1.2.9" web3-utils "1.2.9" +web3-eth-ens@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.3.0.tgz#0887ba38473c104cf5fb8a715828b3b354fa02a2" + integrity sha512-WnOru+EcuM5dteiVYJcHXo/I7Wq+ei8RrlS2nir49M0QpYvUPGbCGgTbifcjJQTWamgORtWdljSA1s2Asdb74w== + dependencies: + content-hash "^2.5.2" + eth-ens-namehash "2.0.8" + underscore "1.9.1" + web3-core "1.3.0" + web3-core-helpers "1.3.0" + web3-core-promievent "1.3.0" + web3-eth-abi "1.3.0" + web3-eth-contract "1.3.0" + web3-utils "1.3.0" + web3-eth-iban@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.2.1.tgz#2c3801718946bea24e9296993a975c80b5acf880" @@ -19607,14 +19953,6 @@ web3-eth-iban@1.2.1: bn.js "4.11.8" web3-utils "1.2.1" -web3-eth-iban@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.2.11.tgz#f5f73298305bc7392e2f188bf38a7362b42144ef" - integrity sha512-ozuVlZ5jwFC2hJY4+fH9pIcuH1xP0HEFhtWsR69u9uDIANHLPQQtWYmdj7xQ3p2YT4bQLq/axKhZi7EZVetmxQ== - dependencies: - bn.js "^4.11.9" - web3-utils "1.2.11" - web3-eth-iban@1.2.9: version "1.2.9" resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.2.9.tgz#4ebf3d8783f34d04c4740dc18938556466399f7a" @@ -19623,6 +19961,14 @@ web3-eth-iban@1.2.9: bn.js "4.11.8" web3-utils "1.2.9" +web3-eth-iban@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.3.0.tgz#15b782dfaf273ebc4e3f389f1367f4e88ddce4a5" + integrity sha512-v9mZWhR4fPF17/KhHLiWir4YHWLe09O3B/NTdhWqw3fdAMJNztzMHGzgHxA/4fU+rhrs/FhDzc4yt32zMEXBZw== + dependencies: + bn.js "^4.11.9" + web3-utils "1.3.0" + web3-eth-personal@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.2.1.tgz#244e9911b7b482dc17c02f23a061a627c6e47faf" @@ -19634,18 +19980,6 @@ web3-eth-personal@1.2.1: web3-net "1.2.1" web3-utils "1.2.1" -web3-eth-personal@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.2.11.tgz#a38b3942a1d87a62070ce0622a941553c3d5aa70" - integrity sha512-42IzUtKq9iHZ8K9VN0vAI50iSU9tOA1V7XU2BhF/tb7We2iKBVdkley2fg26TxlOcKNEHm7o6HRtiiFsVK4Ifw== - dependencies: - "@types/node" "^12.12.6" - web3-core "1.2.11" - web3-core-helpers "1.2.11" - web3-core-method "1.2.11" - web3-net "1.2.11" - web3-utils "1.2.11" - web3-eth-personal@1.2.9: version "1.2.9" resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.2.9.tgz#9b95eb159b950b83cd8ae15873e1d57711b7a368" @@ -19658,6 +19992,18 @@ web3-eth-personal@1.2.9: web3-net "1.2.9" web3-utils "1.2.9" +web3-eth-personal@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.3.0.tgz#d376e03dc737d961ff1f8d1aca866efad8477135" + integrity sha512-2czUhElsJdLpuNfun9GeLiClo5O6Xw+bLSjl3f4bNG5X2V4wcIjX2ygep/nfstLLtkz8jSkgl/bV7esANJyeRA== + dependencies: + "@types/node" "^12.12.6" + web3-core "1.3.0" + web3-core-helpers "1.3.0" + web3-core-method "1.3.0" + web3-net "1.3.0" + web3-utils "1.3.0" + web3-eth@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.2.1.tgz#b9989e2557c73a9e8ffdc107c6dafbe72c79c1b0" @@ -19677,25 +20023,6 @@ web3-eth@1.2.1: web3-net "1.2.1" web3-utils "1.2.1" -web3-eth@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.2.11.tgz#4c81fcb6285b8caf544058fba3ae802968fdc793" - integrity sha512-REvxW1wJ58AgHPcXPJOL49d1K/dPmuw4LjPLBPStOVkQjzDTVmJEIsiLwn2YeuNDd4pfakBwT8L3bz1G1/wVsQ== - dependencies: - underscore "1.9.1" - web3-core "1.2.11" - web3-core-helpers "1.2.11" - web3-core-method "1.2.11" - web3-core-subscriptions "1.2.11" - web3-eth-abi "1.2.11" - web3-eth-accounts "1.2.11" - web3-eth-contract "1.2.11" - web3-eth-ens "1.2.11" - web3-eth-iban "1.2.11" - web3-eth-personal "1.2.11" - web3-net "1.2.11" - web3-utils "1.2.11" - web3-eth@1.2.9: version "1.2.9" resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.2.9.tgz#e40e7b88baffc9b487193211c8b424dc944977b3" @@ -19715,6 +20042,25 @@ web3-eth@1.2.9: web3-net "1.2.9" web3-utils "1.2.9" +web3-eth@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.3.0.tgz#898e5f5a8827f9bc6844e267a52eb388916a6771" + integrity sha512-/bzJcxXPM9EM18JM5kO2JjZ3nEqVo3HxqU93aWAEgJNqaP/Lltmufl2GpvIB2Hvj+FXAjAXquxUdQ2/xP7BzHQ== + dependencies: + underscore "1.9.1" + web3-core "1.3.0" + web3-core-helpers "1.3.0" + web3-core-method "1.3.0" + web3-core-subscriptions "1.3.0" + web3-eth-abi "1.3.0" + web3-eth-accounts "1.3.0" + web3-eth-contract "1.3.0" + web3-eth-ens "1.3.0" + web3-eth-iban "1.3.0" + web3-eth-personal "1.3.0" + web3-net "1.3.0" + web3-utils "1.3.0" + web3-net@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.2.1.tgz#edd249503315dd5ab4fa00220f6509d95bb7ab10" @@ -19724,15 +20070,6 @@ web3-net@1.2.1: web3-core-method "1.2.1" web3-utils "1.2.1" -web3-net@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.2.11.tgz#eda68ef25e5cdb64c96c39085cdb74669aabbe1b" - integrity sha512-sjrSDj0pTfZouR5BSTItCuZ5K/oZPVdVciPQ6981PPPIwJJkCMeVjD7I4zO3qDPCnBjBSbWvVnLdwqUBPtHxyg== - dependencies: - web3-core "1.2.11" - web3-core-method "1.2.11" - web3-utils "1.2.11" - web3-net@1.2.9: version "1.2.9" resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.2.9.tgz#51d248ed1bc5c37713c4ac40c0073d9beacd87d3" @@ -19742,6 +20079,15 @@ web3-net@1.2.9: web3-core-method "1.2.9" web3-utils "1.2.9" +web3-net@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.3.0.tgz#b69068cccffab58911c2f08ca4abfbefb0f948c6" + integrity sha512-Xz02KylOyrB2YZzCkysEDrY7RbKxb7LADzx3Zlovfvuby7HBwtXVexXKtoGqksa+ns1lvjQLLQGb+OeLi7Sr7w== + dependencies: + web3-core "1.3.0" + web3-core-method "1.3.0" + web3-utils "1.3.0" + web3-provider-engine@15.0.12, web3-provider-engine@^15.0.4: version "15.0.12" resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-15.0.12.tgz#24d7f2f6fb6de856824c7306291018c4fc543ac3" @@ -19806,14 +20152,6 @@ web3-providers-http@1.2.1: web3-core-helpers "1.2.1" xhr2-cookies "1.1.0" -web3-providers-http@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.2.11.tgz#1cd03442c61670572d40e4dcdf1faff8bd91e7c6" - integrity sha512-psh4hYGb1+ijWywfwpB2cvvOIMISlR44F/rJtYkRmQ5jMvG4FOCPlQJPiHQZo+2cc3HbktvvSJzIhkWQJdmvrA== - dependencies: - web3-core-helpers "1.2.11" - xhr2-cookies "1.1.0" - web3-providers-http@1.2.9: version "1.2.9" resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.2.9.tgz#e698aa5377e2019c24c5a1e6efa0f51018728934" @@ -19822,6 +20160,14 @@ web3-providers-http@1.2.9: web3-core-helpers "1.2.9" xhr2-cookies "1.1.0" +web3-providers-http@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.3.0.tgz#88227f64c88b32abed4359383c2663616e0dc531" + integrity sha512-cMKhUI6PqlY/EC+ZDacAxajySBu8AzW8jOjt1Pe/mbRQgS0rcZyvLePGTTuoyaA8C21F8UW+EE5jj7YsNgOuqA== + dependencies: + web3-core-helpers "1.3.0" + xhr2-cookies "1.1.0" + web3-providers-ipc@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.2.1.tgz#017bfc687a8fc5398df2241eb98f135e3edd672c" @@ -19831,15 +20177,6 @@ web3-providers-ipc@1.2.1: underscore "1.9.1" web3-core-helpers "1.2.1" -web3-providers-ipc@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.2.11.tgz#d16d6c9be1be6e0b4f4536c4acc16b0f4f27ef21" - integrity sha512-yhc7Y/k8hBV/KlELxynWjJDzmgDEDjIjBzXK+e0rHBsYEhdCNdIH5Psa456c+l0qTEU2YzycF8VAjYpWfPnBpQ== - dependencies: - oboe "2.1.4" - underscore "1.9.1" - web3-core-helpers "1.2.11" - web3-providers-ipc@1.2.9: version "1.2.9" resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.2.9.tgz#6159eacfcd7ac31edc470d93ef10814fe874763b" @@ -19849,6 +20186,15 @@ web3-providers-ipc@1.2.9: underscore "1.9.1" web3-core-helpers "1.2.9" +web3-providers-ipc@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.3.0.tgz#d7c2b203733b46f7b4e7b15633d891648cf9a293" + integrity sha512-0CrLuRofR+1J38nEj4WsId/oolwQEM6Yl1sOt41S/6bNI7htdkwgVhSloFIMJMDFHtRw229QIJ6wIaKQz0X1Og== + dependencies: + oboe "2.1.5" + underscore "1.9.1" + web3-core-helpers "1.3.0" + web3-providers-ws@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.2.1.tgz#2d941eaf3d5a8caa3214eff8dc16d96252b842cb" @@ -19858,16 +20204,6 @@ web3-providers-ws@1.2.1: web3-core-helpers "1.2.1" websocket "github:web3-js/WebSocket-Node#polyfill/globalThis" -web3-providers-ws@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.2.11.tgz#a1dfd6d9778d840561d9ec13dd453046451a96bb" - integrity sha512-ZxnjIY1Er8Ty+cE4migzr43zA/+72AF1myzsLaU5eVgdsfV7Jqx7Dix1hbevNZDKFlSoEyq/3j/jYalh3So1Zg== - dependencies: - eventemitter3 "4.0.4" - underscore "1.9.1" - web3-core-helpers "1.2.11" - websocket "^1.0.31" - web3-providers-ws@1.2.9: version "1.2.9" resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.2.9.tgz#22c2006655ec44b4ad2b41acae62741a6ae7a88c" @@ -19878,6 +20214,16 @@ web3-providers-ws@1.2.9: web3-core-helpers "1.2.9" websocket "^1.0.31" +web3-providers-ws@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.3.0.tgz#84adeff65acd4624d7f5bb43c5b2b22d8f0f63a4" + integrity sha512-Im5MthhJnJst8nSoq0TgbyOdaiFQFa5r6sHPOVllhgIgViDqzbnlAFW9sNzQ0Q8VXPNfPIQKi9cOrHlSRNPjRw== + dependencies: + eventemitter3 "4.0.4" + underscore "1.9.1" + web3-core-helpers "1.3.0" + websocket "^1.0.32" + web3-shh@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.2.1.tgz#4460e3c1e07faf73ddec24ccd00da46f89152b0c" @@ -19888,16 +20234,6 @@ web3-shh@1.2.1: web3-core-subscriptions "1.2.1" web3-net "1.2.1" -web3-shh@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.2.11.tgz#f5d086f9621c9a47e98d438010385b5f059fd88f" - integrity sha512-B3OrO3oG1L+bv3E1sTwCx66injW1A8hhwpknDUbV+sw3fehFazA06z9SGXUefuFI1kVs4q2vRi0n4oCcI4dZDg== - dependencies: - web3-core "1.2.11" - web3-core-method "1.2.11" - web3-core-subscriptions "1.2.11" - web3-net "1.2.11" - web3-shh@1.2.9: version "1.2.9" resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.2.9.tgz#c4ba70d6142cfd61341a50752d8cace9a0370911" @@ -19908,6 +20244,16 @@ web3-shh@1.2.9: web3-core-subscriptions "1.2.9" web3-net "1.2.9" +web3-shh@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.3.0.tgz#62d15297da8fb5f733dd1b98f9ade300590f4d49" + integrity sha512-IZTojA4VCwVq+7eEIHuL1tJXtU+LJDhO8Y2QmuwetEWW1iBgWCGPHZasipWP+7kDpSm/5lo5GRxL72FF/Os/tA== + dependencies: + web3-core "1.3.0" + web3-core-method "1.3.0" + web3-core-subscriptions "1.3.0" + web3-net "1.3.0" + web3-utils@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.2.1.tgz#21466e38291551de0ab34558de21512ac4274534" @@ -19921,20 +20267,6 @@ web3-utils@1.2.1: underscore "1.9.1" utf8 "3.0.0" -web3-utils@1.2.11, web3-utils@^1.2.11, web3-utils@^1.2.9: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.2.11.tgz#af1942aead3fb166ae851a985bed8ef2c2d95a82" - integrity sha512-3Tq09izhD+ThqHEaWYX4VOT7dNPdZiO+c/1QMA0s5X2lDFKK/xHJb7cyTRRVzN2LvlHbR7baS1tmQhSua51TcQ== - dependencies: - bn.js "^4.11.9" - eth-lib "0.2.8" - ethereum-bloom-filters "^1.0.6" - ethjs-unit "0.1.6" - number-to-bn "1.7.0" - randombytes "^2.1.0" - underscore "1.9.1" - utf8 "3.0.0" - web3-utils@1.2.9: version "1.2.9" resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.2.9.tgz#abe11735221627da943971ef1a630868fb9c61f3" @@ -19949,18 +20281,32 @@ web3-utils@1.2.9: underscore "1.9.1" utf8 "3.0.0" -web3@*: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3/-/web3-1.2.11.tgz#50f458b2e8b11aa37302071c170ed61cff332975" - integrity sha512-mjQ8HeU41G6hgOYm1pmeH0mRAeNKJGnJEUzDMoerkpw7QUQT4exVREgF1MYPvL/z6vAshOXei25LE/t/Bxl8yQ== +web3-utils@1.3.0, web3-utils@^1.2.11, web3-utils@^1.2.9: + version "1.3.0" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.3.0.tgz#5bac16e5e0ec9fe7bdcfadb621655e8aa3cf14e1" + integrity sha512-2mS5axFCbkhicmoDRuJeuo0TVGQDgC2sPi/5dblfVC+PMtX0efrb8Xlttv/eGkq7X4E83Pds34FH98TP2WOUZA== dependencies: - web3-bzz "1.2.11" - web3-core "1.2.11" - web3-eth "1.2.11" - web3-eth-personal "1.2.11" - web3-net "1.2.11" - web3-shh "1.2.11" - web3-utils "1.2.11" + bn.js "^4.11.9" + eth-lib "0.2.8" + ethereum-bloom-filters "^1.0.6" + ethjs-unit "0.1.6" + number-to-bn "1.7.0" + randombytes "^2.1.0" + underscore "1.9.1" + utf8 "3.0.0" + +web3@*, web3@^1.0.0-beta.34: + version "1.3.0" + resolved "https://registry.yarnpkg.com/web3/-/web3-1.3.0.tgz#8fe4cd6e2a21c91904f343ba75717ee4c76bb349" + integrity sha512-4q9dna0RecnrlgD/bD1C5S+81Untbd6Z/TBD7rb+D5Bvvc0Wxjr4OP70x+LlnwuRDjDtzBwJbNUblh2grlVArw== + dependencies: + web3-bzz "1.3.0" + web3-core "1.3.0" + web3-eth "1.3.0" + web3-eth-personal "1.3.0" + web3-net "1.3.0" + web3-shh "1.3.0" + web3-utils "1.3.0" web3@1.2.1: version "1.2.1" @@ -20137,9 +20483,9 @@ webpack@4.42.0: webpack-sources "^1.4.1" webpack@^4.33.0, webpack@^4.38.0: - version "4.44.1" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.44.1.tgz#17e69fff9f321b8f117d1fda714edfc0b939cc21" - integrity sha512-4UOGAohv/VGUNQJstzEywwNxqX417FnjZgZJpJQegddzPmTvph37eBIRbRTfdySXzVtJXLJfbMN3mMYhM6GdmQ== + version "4.44.2" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.44.2.tgz#6bfe2b0af055c8b2d1e90ed2cd9363f841266b72" + integrity sha512-6KJVGlCxYdISyurpQ0IPTklv+DULv05rs2hseIXer6D7KrUicRDLFb4IUM1S6LUAKypPM/nSiVSuv8jHu1m3/Q== dependencies: "@webassemblyjs/ast" "1.9.0" "@webassemblyjs/helper-module-context" "1.9.0" @@ -20194,15 +20540,16 @@ websocket-extensions@>=0.1.1: resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== -websocket@^1.0.31: - version "1.0.31" - resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.31.tgz#e5d0f16c3340ed87670e489ecae6144c79358730" - integrity sha512-VAouplvGKPiKFDTeCCO65vYHsyay8DqoBSlzIO3fayrfOgU94lQN5a1uWVnFrMLceTJw/+fQXR5PGbUVRaHshQ== +websocket@^1.0.31, websocket@^1.0.32: + version "1.0.32" + resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.32.tgz#1f16ddab3a21a2d929dec1687ab21cfdc6d3dbb1" + integrity sha512-i4yhcllSP4wrpoPMU2N0TQ/q0O94LRG/eUQjEAamRltjQ1oT1PFFKOG4i877OlJgCG8rw6LrrowJp+TYCEWF7Q== dependencies: + bufferutil "^4.0.1" debug "^2.2.0" es5-ext "^0.10.50" - nan "^2.14.0" typedarray-to-buffer "^3.1.5" + utf-8-validate "^5.0.2" yaeti "^0.0.6" "websocket@github:web3-js/WebSocket-Node#polyfill/globalThis": @@ -20227,10 +20574,10 @@ 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@>=0.10.0, whatwg-fetch@^3.0.0, whatwg-fetch@^3.3.1: - version "3.4.0" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.4.0.tgz#e11de14f4878f773fbebcde8871b2c0699af8b30" - integrity sha512-rsum2ulz2iuZH08mJkT0Yi6JnKhwdw4oeyMjokgxd+mmqYSd9cPpOQf01TIWgjxG/U4+QR+AwKq6lSbXVxkyoQ== +whatwg-fetch@>=0.10.0, whatwg-fetch@^3.0.0, whatwg-fetch@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.4.1.tgz#e5f871572d6879663fa5674c8f833f15a8425ab3" + integrity sha512-sofZVzE1wKwO+EYPbWfiwzaKovWiZXf4coEzjGP9b2GBVgQRLQUZ2QcuPpQExGDAW5GItpEm6Tl4OU5mywnAoQ== whatwg-mimetype@^2.1.0, whatwg-mimetype@^2.2.0, whatwg-mimetype@^2.3.0: version "2.3.0" @@ -20293,6 +20640,23 @@ widest-line@^3.1.0: dependencies: string-width "^4.0.0" +window-getters@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/window-getters/-/window-getters-1.0.0.tgz#b5b264538c4c79cead027f9997850222bf6d0852" + integrity sha512-xyvEFq3x+7dCA7NFhqOmTMk0fPmmAzCUYL2svkw2LGBaXXQLRP0lFnfXHzysri9WZNMkzp/FD1u0w2Qc7Co+JA== + +window-getters@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/window-getters/-/window-getters-1.0.1.tgz#a564c258413b4808789633d8bfb7ed741d798aa0" + integrity sha512-cojBfDeV58XEurDgj+rre15c7dvu27bWCPlOIpwQgreOsw6qQk0UGDR1hi7ZHKw5+L0AENUNNWGG2h4yr2Y3hQ== + +window-metadata@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/window-metadata/-/window-metadata-1.0.0.tgz#fece0446db2f50be0612a211f25fc693917e823b" + integrity sha512-eYoXsZ9X4J+6xZgbHhNAatSR5bCtT409q8B+2Ol9ySx7qsdtgVZcNfox4qszFmKlGsFtT2b1Tcmcy69bRMObcg== + dependencies: + window-getters "^1.0.0" + word-wrap@~1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" @@ -20650,6 +21014,14 @@ yargs-parser@^10.0.0: dependencies: camelcase "^4.1.0" +yargs-parser@^15.0.1: + version "15.0.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-15.0.1.tgz#54786af40b820dcb2fb8025b11b4d659d76323b3" + integrity sha512-0OAMV2mAZQrs3FkNpDQcBk1x5HXb8X4twADss4S0Iuk+2dGnLOE/fRHrsYm542GduMveyA77OF4wrNJuanRCWw== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + yargs-parser@^18.1.2: version "18.1.3" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" @@ -20658,14 +21030,16 @@ yargs-parser@^18.1.2: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-unparser@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" - integrity sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw== +yargs-unparser@1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.1.tgz#bd4b0ee05b4c94d058929c32cb09e3fce71d3c5f" + integrity sha512-qZV14lK9MWsGCmcr7u5oXGH0dbGqZAIxTDrWXZDo5zUr6b6iUmelNKO6x6R1dQT24AH3LgRxJpr8meWy2unolA== dependencies: + camelcase "^5.3.1" + decamelize "^1.2.0" flat "^4.1.0" - lodash "^4.17.15" - yargs "^13.3.0" + is-plain-obj "^1.1.0" + yargs "^14.2.3" yargs@13.3.2, yargs@^13.2.4, yargs@^13.3.0, yargs@^13.3.2: version "13.3.2" @@ -20683,7 +21057,24 @@ yargs@13.3.2, yargs@^13.2.4, yargs@^13.3.0, yargs@^13.3.2: y18n "^4.0.0" yargs-parser "^13.1.2" -yargs@^15.3.1: +yargs@^14.2.3: + version "14.2.3" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-14.2.3.tgz#1a1c3edced1afb2a2fea33604bc6d1d8d688a414" + integrity sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg== + dependencies: + cliui "^5.0.0" + decamelize "^1.2.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^15.0.1" + +yargs@^15.4.1: version "15.4.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==