From 8ff66955625a192de0e19c1e41cdc65a3c71efa8 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Wed, 1 Apr 2020 18:56:04 +0400 Subject: [PATCH 1/2] Gnosis Safe - Public Release v1.9.0 (#713) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * (Fix) Wrong value for ERC-20 tokens transfers (#679) The fix attempts to properly differentiate an ERC-721 from an ERC-20 token transaction by identifying if it's a `transfer` transaction looking for a `decimals` method in its code. It the later is not found, then it's considered an ERC-721. fixes #678 * (Fix) send tx from address book (#677) * fix: Send funds not working when selecting receipt from addressBook Also, this commit includes an intent to unify/simplify SendModal component fixes #632 * Set default value to txData for custom txs fixes #632 * bump version in package.json (#683) * Onboardjs - Get wallets by platform, fix ledger/trezor rpcUrls (#665) * Added desktop support * Added desktop option and logs for testing * Get desktop mode from window object * Add torus support and remove logs * Update function name * Upgrade onboardjs version * fix ledger/trezor rpcUrls * Bump version to 1.8.3 Co-authored-by: Mikhail Mikheev * Master/dev conflict fix (#685) * Added desktop support * Added desktop option and logs for testing * Get desktop mode from window object * Add torus support and remove logs * Update function name * Upgrade onboardjs version * v1.8.2 (#682) * (Fix) Wrong value for ERC-20 tokens transfers (#679) The fix attempts to properly differentiate an ERC-721 from an ERC-20 token transaction by identifying if it's a `transfer` transaction looking for a `decimals` method in its code. It the later is not found, then it's considered an ERC-721. fixes #678 * (Fix) send tx from address book (#677) * fix: Send funds not working when selecting receipt from addressBook Also, this commit includes an intent to unify/simplify SendModal component fixes #632 * Set default value to txData for custom txs fixes #632 * bump version in package.json (#683) Co-authored-by: Fernando * fix ledger/trezor rpcUrls * Bump version to 1.8.3 Co-authored-by: Mati Dastugue Co-authored-by: Fernando * (Fix) #423 - Pending transaction confirmation loop (#637) * Fixs duplicated notifications * Implements feedback, now the displayed txHash are stored on localstorage and once the first time we notify the user about it, they won't never appear again * Uses the last time the user logged in * Fix safe version null check Fixs date string comparison Adds the safe address to the check of last time logged in * (Feature) Erc721 modal lists (#661) * Add Assets sections * (add) collectibles tab * (add) criptokitty items * (add) collectible items, definitive edition * (fix) collectibles were overlapping with bottom banner * (fix) wording * (fix) responsive issues * Install `async-sema` dependency * Create collectible source classes - source from mocked data and opensea, it's extendable to import information from other sources * Update `Collectible` implementation to use new data source * Create constants file to better handle env variables and default values * Add description to item's cards - also added a mocked class with real data * Fix `saveTxToHistory`, remove hardcoded `CALL` * Fix after merge development * Set background color for collectible based on data info - Changed `withStyles` in favor of a hook-like approach with `makeStyles` * Enhance collectible card info and group title * Use current safeAddress to query for collectibles information - also migrated from `withStyles` to `makeStyles` * Use proper key values for lists and set more significant names * update yarn.lock after merge * Fix linting error * Move ethAsToken verification outside loop * Use absolute route for `SendModal` import * Move Collectibles into redux store * Update yarn.lock file * Selectable NFTs * Divide the `collectible` store into `nftAssets` and `nftTokens` - Also updated components to retain functionality - Created a `textShortener` function for better presentation * Update `yarn.lock` * Update `yarn.lock` * Fix item background color * Clears the tokenID select field when the collectible selected changes * Open Send modal from the assets section * Use token name for the token selection dropdown * Refactor Balances tabs: reduces the amount of props received, exported tokens lists to a component * Refactor Balances tabs: reduces the amount of props received, exported tokens lists to a component * Add openZeppelin contracts dependency * Create ERC721 getter * Fix types, default values and clean code * Fix: properly refresh list of collectibles when switching safes * Add ReviewCollectible step in send NFT * Displays the assets in the manage list * Fixs add custom token/asset modal cancel button * Change items shadow * Give option to choose what to send by clicking 'Send' button in AddressBook * Disable [Send] button for Collectibles if not owner * Set Coins as default option in assets tab - also fixed styles for `Coins` option * Use collectible icon in send modal * Set default message when no assets available - removed pagination feature * Create SafeVersionProvider to better handle version-related tasks Provides: - current and latest versions, - a boolean indicating a need for update, - an upgradeSafe callback to trigger upgrade from any place, - a list of enabled features, depending on the current version - the latter needs a refactor like extract features outside the provider and define constants for the features. * Force build * Update `yarn.lock` * Disable Manage list for NFTs * Implements manage list to add/remove assets * Implements manage list to add/remove assets * Merge branch 'feature/#469-ERC721-feature-implementation' of https://github.com/gnosis/safe-react into feature/#469-ERC721-feature-implementation # Conflicts: # src/routes/safe/components/Balances/Collectibles/index.jsx # src/routes/safe/components/Balances/index.jsx # src/utils/constants.js * Implements blacklisted assets * Fix container shadow - Also fixes tables shadow, thanks to @gabitoesmiapodo * Enable nested routes for balances (assets) tab * Default to `/balance` if invalid nested path * Disable [Send Collectible] button, if not supported by safe * Change sub-menu buttons to clickable text * Replace Paragraph with Link * Fix invalid props errors for Link component * Fallback to `transferFrom` if `safeTransferFrom` is not implemented * Use `transfer` as fallback to ERC-721's `safeTransferFrom` - need to identify ERC721 token using `transfer` and `name` methods * Display failed transactions * Use react.lazy for collectibles' modals * Identify ERC-721 token transaction * Adds initial components for AddCustomAsset support * Fix Send Collectibles modal layout/behavior - disable dropdown list if there's no item to pick - fix placeholder for tokens list - fix dropdown list styles * Set default `isSuccessful` flag to `true` * Fixs erc721Enabled check * Adds margin to modal icon Fix search bar * Fix hidding buttons in coins table * Fixs display all available assets by default * Fixs modal assets * Fixs blacklistedAssetsAddresses save to storage Fixs show token button Co-authored-by: fernandomg Co-authored-by: Gabriel Rodriguez Alsina * Remove `SafeVersionProvider` (#694) * (Feature) Safe Deployment #605 #111 #395 #606 #396 (#659) * Stepper component * proxyfactory web3 contract * add styles to body steps * Steps info * Open component: moving from class to function * remove opening route and rendering it in Open component instead * recover safe creation from txHash in localStorage * remove commented code * restore commented code * creatign TX fix * fix createSafe then function * fixing stepper * remove unused code * remove opening route and finishin both variants of create * add loader dots svg * add error state design and loader dots * fix error section * add description to steps * adding etherscan link * taking values from variables * fix heigh in body content * add success svg * add check image on last step * fix margin and heigt to body rows * remove commented code * remove commented code * fix for #396 * Fix empty_code * set error if getReceipt fails * fixes * Fix: remove txHash from pendingInfo on retry Co-authored-by: Mikhail Mikheev Co-authored-by: Agustín Longoni Co-authored-by: Fernando * Updated modal description * Update readme (#696) * Bump 1.5.0 version of onboardjs * Feature: #528 optimize network requests (#680) * Generates a cache to avoid multiples getHumanFriendlyToken() for the same token address * Adds etags implementation for transactions * Caches outgoing and incoming safe transactions based on etag value * Removes cachedSafeTransactions, cachedSafeIncommingTransactions * Refactors getTokenInstance * Avoid recreating tokens on fetchTokens() once we have them in redux * Fixs error on catch * Batch request tokens balances * Fixs missing token names Changes the tokens limit from 300 to 3000 * fix: failed to instantiate non-standard ERC-20 tokens For the batchRequest of balances, we're just using the `balanceOf` method call. So having a simple ABI with that only method prevents errors with non-standard ERC-20 Tokens. * Removes unnecessary action updateSafeThreshold Removes unnecessary action fetchEtherBalance * Updated comments in code Replaces constant with directly dispatching action * BatchRequest done right * fix: invalid action name `savedToken` -> `saveToken` * Renames getTokenInstance to getTokenInfos Fixs first load of transactions are empty * Move fetchTokenBalances to `Balances` and `SendModal` components * fix: Incoming transaction type Backend now changed the type from 'incoming' to one of: `'ERC721_TRANSFER', 'ERC20_TRANSFER', 'ETHER_TRANSFER'` * fix: tokenInstance `symbol` and `decimal` extraction * Fix property name `decimals` instead of `tokenDecimals` * Standardize non-standard ERC20 tokens discovery * fix: isStandardERC20 * Revert "Move fetchTokenBalances to `Balances` and `SendModal` components" This reverts commit ed84bd92 * Fixs Typo INCOMING_TX_TYPES Renames tokenInstance with localToken * Renames getBatchBalances to getTokenBalances Returns saved tokens instead of tokenInstance in getTokenInfos * Remove promise returns Co-authored-by: fernandomg * Feature: Offchain signatures (#668) * offchain signatures wip * offchain signing wip * offchain signatures wip * offchain signatures wip * save signatures to the history service * fix eth signer & useEfefct hook * offchain signatures wip * signature check, mainnet testing wip * dep update * disable offchain signing for smart contract wallets * Refactor EIP712 signer * bring back .env.example * Check if save version is >1.1.1 * use canTryoffchainSigning boolean variable, add comment about 4001 error * move semver selector for safe version/offchain signatures to a constant, make use of empty_data for isContractWallet * remove TYPE when sending txs to history service * add eth_signTypedData_v4 signer, dep bump, add missing await * add comments about version check for canTryOffchainSigning variable * hide "please sign notification" * dep bump * dep bump * Check if connected is ledger before trying offchain signatures * minor fixes, temp deployment to test trezor * add hardwareWallet boolean property to wallet model, disable offchain signatures for hw wallets * (Fix) Owner replacement transaction details (#688) * fix: No threshold change for owners replacement * fix: Extract added owner from addressBook When replacing an owner, the added owner's name was the same as the removed one * fix: Add or Update addressBook entry for the newly added owner * Replace `.then` with `async/await` * Optimize AddressBook entry `name` update * Revert "Optimize AddressBook entry `name` update" This reverts commit 00a75d15 * refactor: AddressBook entry from plain JS object to immutable Record * fix: merge instead of set for the AddressBookEntry record * refactor: addOrUpdateAddressBookEntry redux action changed signature to `addOrUpdateAddressBookEntry(entryAddress, entry)` Where `entry` is an object with only the required fields to be updated * Fix safe creation from walletConnect (#703) * Fixes: Offchain signatures (#706) * offchain signatures wip * offchain signing wip * offchain signatures wip * offchain signatures wip * save signatures to the history service * fix eth signer & useEfefct hook * offchain signatures wip * signature check, mainnet testing wip * dep update * disable offchain signing for smart contract wallets * Refactor EIP712 signer * bring back .env.example * Check if save version is >1.1.1 * use canTryoffchainSigning boolean variable, add comment about 4001 error * move semver selector for safe version/offchain signatures to a constant, make use of empty_data for isContractWallet * remove TYPE when sending txs to history service * add eth_signTypedData_v4 signer, dep bump, add missing await * add comments about version check for canTryOffchainSigning variable * hide "please sign notification" * dep bump * dep bump * Check if connected is ledger before trying offchain signatures * minor fixes, temp deployment to test trezor * add hardwareWallet boolean property to wallet model, disable offchain signatures for hw wallets * add personal signer * prettier fixes * offchain signatures fixes * (Fix) New owners as `UNKNOWN` (#697) * fix: No threshold change for owners replacement * fix: Extract added owner from addressBook When replacing an owner, the added owner's name was the same as the removed one * fix: Add or Update addressBook entry for the newly added owner * Replace `.then` with `async/await` * Optimize AddressBook entry `name` update * fix: store added owner in the addressBook * Revert "Optimize AddressBook entry `name` update" This reverts commit 00a75d15 * refactor: AddressBook entry from plain JS object to immutable Record * fix: merge instead of set for the AddressBookEntry record * refactor: addOrUpdateAddressBookEntry redux action changed signature to `addOrUpdateAddressBookEntry(entryAddress, entry)` Where `entry` is an object with only the required fields to be updated * refactor: update `addOrUpdateAddressBookEntry` call, due to signature change * Bug: Eth balance not updating (#709) * fix prop name for updating eth balance * remove unneccessary index in import * typo fixes in safe opening * Don't reassign transaction in getAwaitingTransactions, check for another transaction executed with the same nonce and not only cancellation ones (#710) Co-authored-by: Fernando Co-authored-by: Mati Dastugue Co-authored-by: Agustin Pane Co-authored-by: Gabriel Rodriguez Alsina Co-authored-by: nicolas Co-authored-by: Agustín Longoni Co-authored-by: lukasschor --- .env.example | 3 + package.json | 68 +- readme.md | 4 +- .../dataDisplay/IconText/index.js | 6 +- .../Loader-dots/assets/loader-dots.svg | 18 + src/components-v2/index.js | 1 + .../layouts/ListContentLayout/List.jsx | 2 +- .../navigation/Stepper/DotStep.jsx | 48 + .../navigation/Stepper/index.jsx | 69 + src/components-v2/navigation/index.js | 2 + src/components/ConnectButton/index.jsx | 5 +- src/components/CookiesBanner/index.jsx | 4 +- src/components/Header/components/Layout.jsx | 2 +- .../components/SafeListHeader/index.jsx | 2 +- src/components/Identicon/blockies.js | 16 +- src/components/Notifier/index.js | 4 +- src/components/ScanQRModal/index.jsx | 4 +- src/components/Sidebar/SafeList/index.jsx | 4 +- src/components/Sidebar/index.jsx | 4 +- src/components/Stepper/index.jsx | 4 +- src/components/Table/sorting.js | 2 +- src/components/forms/AddressInput/index.jsx | 4 +- src/components/forms/validator.js | 6 +- src/components/layout/PageFrame/index.jsx | 2 +- src/logic/addressBook/model/addressBook.js | 8 +- .../actions/addOrUpdateAddressBookEntry.js | 14 + .../actions/loadAddressBookFromStorage.js | 2 +- .../store/actions/saveAndUpdateAddressBook.js | 3 +- .../store/middleware/addressBookMiddleware.js | 5 +- .../addressBook/store/reducer/addressBook.js | 43 +- .../addressBook/store/selectors/index.js | 2 +- src/logic/addressBook/utils/index.js | 6 +- .../collectibles/store/selectors/index.js | 32 + src/logic/contracts/safeContracts.js | 33 +- .../store/actions/fetchCurrencyValues.js | 4 +- .../store/reducer/currentSession.js | 2 +- .../notifications/notificationBuilder.js | 2 +- .../store/reducer/notifications.js | 4 +- src/logic/safe/safeTxSigner.js | 2 +- .../safe/transactions/awaitingTransactions.js | 9 +- src/logic/safe/transactions/gas.js | 2 +- src/logic/safe/transactions/index.js | 2 +- .../offchainSigner/EIP712Signer.js | 100 + .../transactions/offchainSigner/ethSigner.js | 60 + .../safe/transactions/offchainSigner/index.js | 31 + .../safe/transactions/safeTxSignerEIP712.js | 98 - src/logic/safe/transactions/send.js | 1 + src/logic/safe/transactions/txHistory.js | 16 +- src/logic/safe/utils/safeVersion.js | 4 +- src/logic/tokens/api/fetchTokenBalanceList.js | 2 +- src/logic/tokens/api/fetchTokenList.js | 2 +- .../store/actions/activateAssetsByBalance.js | 49 + .../store/actions/activateTokensByBalance.js | 2 +- src/logic/tokens/store/actions/fetchTokens.js | 98 +- src/logic/tokens/store/reducer/tokens.js | 4 +- src/logic/tokens/utils/tokenHelpers.js | 15 +- src/logic/tokens/utils/tokensStorage.js | 2 +- src/logic/wallets/ethAddresses.js | 2 +- src/logic/wallets/getWeb3.js | 29 +- .../wallets/store/actions/fetchProvider.js | 10 +- src/logic/wallets/store/model/provider.js | 4 + src/logic/wallets/store/selectors/index.js | 2 +- src/logic/wallets/transactionDataCheck.js | 2 +- src/logic/wallets/utils/walletList.js | 2 +- src/routes/index.js | 14 +- .../load/components/DetailsForm/index.jsx | 2 +- src/routes/load/container/Load.jsx | 2 +- .../components/ReviewInformation/index.jsx | 14 +- .../SafeOwnersConfirmationsForm/index.jsx | 6 +- src/routes/open/components/fields.js | 2 +- src/routes/open/container/Open.jsx | 186 +- src/routes/open/utils/safeDataExtractor.js | 8 +- src/routes/opening/assets/success.svg | 4 + src/routes/opening/assets/vault-error.svg | 13 + src/routes/opening/component/index.jsx | 79 - src/routes/opening/container/index.jsx | 6 +- src/routes/opening/index.jsx | 394 +++ src/routes/routes.js | 8 - .../CreateEditEntryModal/index.jsx | 2 +- .../AddressBook/DeleteEntryModal/index.jsx | 2 +- .../EllipsisTransactionDetails/index.jsx | 2 +- .../safe/components/AddressBook/index.jsx | 9 +- src/routes/safe/components/Apps/appsList.js | 2 +- src/routes/safe/components/Apps/index.jsx | 10 +- .../safe/components/Apps/sendTransactions.js | 2 +- .../safe/components/Balances/Coins/index.jsx | 129 + .../safe/components/Balances/Coins/styles.js | 47 + .../Balances/Collectibles/components/Item.jsx | 4 +- .../Balances/Collectibles/index.jsx | 22 +- .../components/Balances/SendModal/index.jsx | 6 +- .../screens/AddressBookInput/index.jsx | 18 +- .../SendModal/screens/ReviewTx/index.jsx | 2 +- .../CollectibleSelectField/index.jsx | 4 +- .../TokenSelectField/index.jsx | 4 +- .../screens/SendCollectible/index.jsx | 14 +- .../SendModal/screens/SendCustomTx/index.jsx | 6 +- .../SendFunds/TokenSelectField/index.jsx | 4 +- .../SendModal/screens/SendFunds/index.jsx | 10 +- .../safe/components/Balances/Tokens/index.jsx | 25 +- .../Tokens/screens/AddCustomAsset/index.jsx | 190 ++ .../Tokens/screens/AddCustomAsset/style.js | 34 + .../Tokens/screens/AddCustomAsset/utils.js | 17 + .../screens/AddCustomAsset/validators.js | 25 + .../Tokens/screens/AddCustomToken/index.jsx | 12 +- .../Tokens/screens/AssetsList/AssetRow.jsx | 60 + .../Tokens/screens/AssetsList/index.jsx | 164 + .../Tokens/screens/AssetsList/style.js | 76 + .../Tokens/screens/TokenList/index.jsx | 4 +- src/routes/safe/components/Balances/index.jsx | 187 +- src/routes/safe/components/Balances/style.js | 51 +- .../utils/setTokenImgToPlaceholder.js | 2 +- .../components/DropdownCurrency/index.jsx | 6 +- src/routes/safe/components/Layout.jsx | 4 +- .../ManageOwners/AddOwnerModal/index.jsx | 14 +- .../AddOwnerModal/screens/OwnerForm/index.jsx | 4 +- .../AddOwnerModal/screens/Review/index.jsx | 2 +- .../screens/ThresholdForm/index.jsx | 2 +- .../ManageOwners/EditOwnerModal/index.jsx | 5 +- .../OwnerAddressTableCell/index.jsx | 2 +- .../ManageOwners/RemoveOwnerModal/index.jsx | 4 +- .../screens/CheckOwner/index.jsx | 2 +- .../RemoveOwnerModal/screens/Review/index.jsx | 4 +- .../screens/ThresholdForm/index.jsx | 2 +- .../ManageOwners/ReplaceOwnerModal/index.jsx | 19 +- .../screens/OwnerForm/index.jsx | 4 +- .../screens/Review/index.jsx | 4 +- .../Settings/ManageOwners/index.jsx | 2 +- .../components/Settings/SafeDetails/index.jsx | 4 +- .../ChangeThreshold/index.jsx | 2 +- .../Settings/ThresholdSettings/index.jsx | 4 +- src/routes/safe/components/Settings/index.jsx | 2 +- .../ExpandedTx/ApproveTxModal/index.jsx | 2 +- .../ExpandedTx/OwnersColumn/OwnersList.jsx | 4 +- .../ExpandedTx/OwnersColumn/index.jsx | 6 +- .../ExpandedTx/TxDescription/index.jsx | 116 +- .../ExpandedTx/TxDescription/utils.js | 14 +- .../TxsTable/ExpandedTx/index.jsx | 16 +- .../Transactions/TxsTable/columns.js | 6 +- .../Transactions/TxsTable/index.jsx | 6 +- src/routes/safe/container/actions.js | 3 + src/routes/safe/container/index.jsx | 5 +- src/routes/safe/container/selector.js | 11 +- .../safe/store/actions/createTransaction.js | 47 +- .../safe/store/actions/fetchEtherBalance.js | 12 +- src/routes/safe/store/actions/fetchSafe.js | 20 +- .../safe/store/actions/fetchTokenBalances.js | 65 +- .../safe/store/actions/fetchTransactions.js | 104 +- .../store/actions/loadSafesFromStorage.js | 2 +- .../safe/store/actions/processTransaction.js | 45 +- .../safe/store/actions/updateActiveAssets.js | 25 + .../store/actions/updateBlacklistedAssets.js | 15 + .../middleware/notificationsMiddleware.js | 69 +- .../safe/store/middleware/safeStorage.js | 7 +- .../safe/store/models/incomingTransaction.js | 4 +- src/routes/safe/store/models/safe.js | 4 + src/routes/safe/store/reducer/safe.js | 36 +- src/routes/safe/store/selectors/index.js | 45 +- src/utils/constants.js | 4 +- src/utils/googleAnalytics.js | 2 +- src/utils/timer.js | 2 +- yarn.lock | 2893 +++++++++++------ 161 files changed, 4727 insertions(+), 1833 deletions(-) create mode 100644 src/components-v2/feedback/Loader-dots/assets/loader-dots.svg create mode 100644 src/components-v2/navigation/Stepper/DotStep.jsx create mode 100644 src/components-v2/navigation/Stepper/index.jsx create mode 100644 src/components-v2/navigation/index.js create mode 100644 src/logic/addressBook/store/actions/addOrUpdateAddressBookEntry.js create mode 100644 src/logic/safe/transactions/offchainSigner/EIP712Signer.js create mode 100644 src/logic/safe/transactions/offchainSigner/ethSigner.js create mode 100644 src/logic/safe/transactions/offchainSigner/index.js delete mode 100644 src/logic/safe/transactions/safeTxSignerEIP712.js create mode 100644 src/logic/tokens/store/actions/activateAssetsByBalance.js create mode 100644 src/routes/opening/assets/success.svg create mode 100644 src/routes/opening/assets/vault-error.svg delete mode 100644 src/routes/opening/component/index.jsx create mode 100644 src/routes/opening/index.jsx create mode 100644 src/routes/safe/components/Balances/Coins/index.jsx create mode 100644 src/routes/safe/components/Balances/Coins/styles.js create mode 100644 src/routes/safe/components/Balances/Tokens/screens/AddCustomAsset/index.jsx create mode 100644 src/routes/safe/components/Balances/Tokens/screens/AddCustomAsset/style.js create mode 100644 src/routes/safe/components/Balances/Tokens/screens/AddCustomAsset/utils.js create mode 100644 src/routes/safe/components/Balances/Tokens/screens/AddCustomAsset/validators.js create mode 100644 src/routes/safe/components/Balances/Tokens/screens/AssetsList/AssetRow.jsx create mode 100644 src/routes/safe/components/Balances/Tokens/screens/AssetsList/index.jsx create mode 100644 src/routes/safe/components/Balances/Tokens/screens/AssetsList/style.js create mode 100644 src/routes/safe/store/actions/updateActiveAssets.js create mode 100644 src/routes/safe/store/actions/updateBlacklistedAssets.js diff --git a/.env.example b/.env.example index ba9a24a9..4d4114ac 100644 --- a/.env.example +++ b/.env.example @@ -23,3 +23,6 @@ REACT_APP_COLLECTIBLES_SOURCE= REACT_APP_LATEST_SAFE_VERSION= # Leave it untouched, version will set using dotenv-expand REACT_APP_APP_VERSION=$npm_package_version + +# all environments +REACT_APP_INFURA_TOKEN= \ No newline at end of file diff --git a/package.json b/package.json index 74e9558e..eb00f490 100644 --- a/package.json +++ b/package.json @@ -43,19 +43,19 @@ "dependencies": { "@gnosis.pm/safe-contracts": "1.1.1-dev.1", "@gnosis.pm/util-contracts": "2.0.6", - "@material-ui/core": "4.9.5", + "@material-ui/core": "4.9.8", "@material-ui/icons": "4.9.1", "@material-ui/lab": "4.0.0-alpha.39", "@openzeppelin/contracts": "^2.5.0", - "@testing-library/jest-dom": "5.1.1", + "@testing-library/jest-dom": "5.3.0", "@welldone-software/why-did-you-render": "4.0.5", "async-sema": "^3.1.0", "axios": "0.19.2", "bignumber.js": "9.0.0", - "bnc-onboard": "1.4.0", - "connected-react-router": "6.7.0", + "bnc-onboard": "1.5.0", + "connected-react-router": "6.8.0", "currency-flags": "^2.1.1", - "date-fns": "2.10.0", + "date-fns": "2.11.1", "dotenv": "^8.2.0", "ethereum-ens": "0.8.0", "final-form": "4.18.7", @@ -63,20 +63,20 @@ "immortal-db": "^1.0.2", "immutable": "^4.0.0-rc.9", "js-cookie": "^2.2.1", - "lint-staged": "^10.0.7", + "lint-staged": "10.0.10", "material-ui-search-bar": "^1.0.0-beta.13", "notistack": "https://github.com/gnosis/notistack.git#v0.9.4", "optimize-css-assets-webpack-plugin": "5.0.3", - "polished": "^3.4.2", + "polished": "3.5.1", "qrcode.react": "1.0.0", "query-string": "6.11.1", - "react": "16.13.0", - "react-dev-utils": "^10.0.0", - "react-dom": "16.13.0", + "react": "16.13.1", + "react-dev-utils": "10.2.1", + "react-dom": "16.13.1", "react-final-form": "6.3.5", "react-final-form-listeners": "^1.0.2", "react-ga": "^2.7.0", - "react-hot-loader": "4.12.19", + "react-hot-loader": "4.12.20", "react-qr-reader": "^2.2.1", "react-redux": "7.2.0", "react-router-dom": "5.1.2", @@ -92,7 +92,7 @@ }, "devDependencies": { "@babel/cli": "7.8.4", - "@babel/core": "7.8.7", + "@babel/core": "7.9.0", "@babel/plugin-proposal-class-properties": "7.8.3", "@babel/plugin-proposal-decorators": "7.8.3", "@babel/plugin-proposal-do-expressions": "7.8.3", @@ -104,7 +104,7 @@ "@babel/plugin-proposal-logical-assignment-operators": "7.8.3", "@babel/plugin-proposal-nullish-coalescing-operator": "7.8.3", "@babel/plugin-proposal-numeric-separator": "7.8.3", - "@babel/plugin-proposal-optional-chaining": "7.8.3", + "@babel/plugin-proposal-optional-chaining": "7.9.0", "@babel/plugin-proposal-pipeline-operator": "7.8.3", "@babel/plugin-proposal-throw-expressions": "7.8.3", "@babel/plugin-syntax-dynamic-import": "7.8.3", @@ -112,15 +112,15 @@ "@babel/plugin-transform-member-expression-literals": "7.8.3", "@babel/plugin-transform-property-literals": "7.8.3", "@babel/polyfill": "7.8.7", - "@babel/preset-env": "7.8.7", - "@babel/preset-flow": "7.8.3", - "@babel/preset-react": "7.8.3", - "@testing-library/react": "9.5.0", - "autoprefixer": "9.7.4", + "@babel/preset-env": "7.9.0", + "@babel/preset-flow": "7.9.0", + "@babel/preset-react": "7.9.4", + "@testing-library/react": "10.0.1", + "autoprefixer": "9.7.5", "babel-core": "^7.0.0-bridge.0", "babel-eslint": "10.1.0", - "babel-jest": "25.1.0", - "babel-loader": "8.0.6", + "babel-jest": "25.2.4", + "babel-loader": "8.1.0", "babel-plugin-dynamic-import-node": "^2.3.0", "babel-plugin-transform-es3-member-expression-literals": "^6.22.0", "babel-plugin-transform-es3-property-literals": "^6.22.0", @@ -130,38 +130,38 @@ "detect-port": "^1.3.0", "dotenv-expand": "^5.1.0", "eslint": "^6.8.0", - "eslint-config-prettier": "^6.10.0", - "eslint-plugin-flowtype": "^4.6.0", - "eslint-plugin-import": "^2.20.1", + "eslint-config-prettier": "6.10.1", + "eslint-plugin-flowtype": "4.7.0", + "eslint-plugin-import": "2.20.2", "eslint-plugin-jsx-a11y": "^6.2.3", "eslint-plugin-prettier": "^3.1.2", "eslint-plugin-react": "^7.18.3", "eslint-plugin-sort-destructure-keys": "^1.3.3", "ethereumjs-abi": "0.6.8", "extract-text-webpack-plugin": "^4.0.0-beta.0", - "file-loader": "5.1.0", - "flow-bin": "0.120.1", - "fs-extra": "8.1.0", - "html-loader": "^0.5.5", - "html-webpack-plugin": "^3.2.0", + "file-loader": "6.0.0", + "flow-bin": "0.121.0", + "fs-extra": "9.0.0", + "html-loader": "1.0.0", + "html-webpack-plugin": "4.0.3", "husky": "^4.2.2", - "jest": "25.1.0", + "jest": "25.2.4", "jest-dom": "4.0.0", "json-loader": "^0.5.7", "mini-css-extract-plugin": "0.9.0", "postcss-loader": "^3.0.0", "postcss-mixins": "6.2.3", "postcss-simple-vars": "^5.0.2", - "prettier": "^1.19.1", + "prettier": "2.0.2", "run-with-testrpc": "0.3.1", "style-loader": "1.1.3", "terser-webpack-plugin": "2.3.5", - "truffle": "5.1.16", + "truffle": "5.1.19", "truffle-contract": "4.0.31", "truffle-solidity-loader": "0.1.32", - "url-loader": "3.0.0", - "webpack": "4.42.0", - "webpack-bundle-analyzer": "3.6.0", + "url-loader": "4.0.0", + "webpack": "4.42.1", + "webpack-bundle-analyzer": "3.6.1", "webpack-cli": "3.3.11", "webpack-dev-server": "3.10.3", "webpack-manifest-plugin": "2.2.0" diff --git a/readme.md b/readme.md index b4c9c91d..573423c4 100644 --- a/readme.md +++ b/readme.md @@ -1,6 +1,6 @@ -# Gnosis Team Safe +# Gnosis Safe Multisig -The most secure way to manage your crypto funds collectively +The most trusted platform to store digital assets on Ethereum ## Getting Started diff --git a/src/components-v2/dataDisplay/IconText/index.js b/src/components-v2/dataDisplay/IconText/index.js index f2e8ded2..d57b28a7 100644 --- a/src/components-v2/dataDisplay/IconText/index.js +++ b/src/components-v2/dataDisplay/IconText/index.js @@ -9,16 +9,16 @@ const Wrapper = styled.div` const Icon = styled.img` max-width: 15px; max-height: 15px; - margin-right: 5px; ` const Text = styled.span` + margin-left: 5px; height: 17px; ` -const IconText = ({ iconUrl, text }: { iconUrl: string, text: string }) => ( +const IconText = ({ iconUrl, text }: { iconUrl: string, text?: string }) => ( - {text} + {text && {text}} ) diff --git a/src/components-v2/feedback/Loader-dots/assets/loader-dots.svg b/src/components-v2/feedback/Loader-dots/assets/loader-dots.svg new file mode 100644 index 00000000..bd96324c --- /dev/null +++ b/src/components-v2/feedback/Loader-dots/assets/loader-dots.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/components-v2/index.js b/src/components-v2/index.js index fbe142d0..201bd707 100644 --- a/src/components-v2/index.js +++ b/src/components-v2/index.js @@ -2,6 +2,7 @@ export * from './dataDisplay' export * from './feedback' export * from './layouts' +export * from './navigation' export * from './safeUtils' export * from './surfaces' export * from './utils' diff --git a/src/components-v2/layouts/ListContentLayout/List.jsx b/src/components-v2/layouts/ListContentLayout/List.jsx index 2ae96666..42a8f93f 100644 --- a/src/components-v2/layouts/ListContentLayout/List.jsx +++ b/src/components-v2/layouts/ListContentLayout/List.jsx @@ -37,7 +37,7 @@ type Props = { const List = ({ activeItem, classes, items, onItemClick }: Props) => { return ( - {items.map(i => ( + {items.map((i) => ( { + if (error) { + return errorColor + } + if (disabled) { + return disabledColor + } + + return secondary + }}; + color: ${backgroundColor}; + width: 24px; + height: 24px; + border-radius: 50%; + display: flex; + justify-content: center; + align-items: center; + margin-bottom: 5px; +` + +type Props = { + dotIndex: number, + currentIndex: number, + error?: boolean, +} +const DotStep = ({ currentIndex, dotIndex, error }: Props) => { + return ( + currentIndex} error={error}> + {dotIndex < currentIndex ? : dotIndex + 1} + + ) +} + +export default DotStep diff --git a/src/components-v2/navigation/Stepper/index.jsx b/src/components-v2/navigation/Stepper/index.jsx new file mode 100644 index 00000000..90c250c4 --- /dev/null +++ b/src/components-v2/navigation/Stepper/index.jsx @@ -0,0 +1,69 @@ +// @flow +import StepMUI from '@material-ui/core/Step' +import StepLabelMUI from '@material-ui/core/StepLabel' +import StepperMUI from '@material-ui/core/Stepper' +import React from 'react' +import styled from 'styled-components' + +import DotStep from './DotStep' + +import { secondaryText as disabled, error as errorColor, primary, secondary } from '~/theme/variables' + +const StyledStepper = styled(StepperMUI)` + background-color: transparent; +` + +const StyledStepLabel = styled.p` + && { + color: ${({ activeStepIndex, error, index }) => { + if (error) { + return errorColor + } + + if (index === activeStepIndex) { + return secondary + } + + if (index < activeStepIndex) { + return disabled + } + + return primary + }}; + } +` + +type Props = { + steps: Array<{ id: string | number, label: string }>, + activeStepIndex: number, + error?: boolean, + orientation: 'vertical' | 'horizontal', +} + +const Stepper = ({ activeStepIndex, error, orientation, steps }: Props) => { + return ( + + {steps.map((s, index) => { + return ( + + + } + > + + {s.label} + + + + ) + })} + + ) +} + +export default Stepper diff --git a/src/components-v2/navigation/index.js b/src/components-v2/navigation/index.js new file mode 100644 index 00000000..c819890f --- /dev/null +++ b/src/components-v2/navigation/index.js @@ -0,0 +1,2 @@ +// @flow +export { default as Stepper } from './Stepper' diff --git a/src/components/ConnectButton/index.jsx b/src/components/ConnectButton/index.jsx index 8a3320ae..bbc88f36 100644 --- a/src/components/ConnectButton/index.jsx +++ b/src/components/ConnectButton/index.jsx @@ -23,7 +23,7 @@ export const onboard = new Onboard({ dappId: BLOCKNATIVE_API_KEY, networkId: getNetworkId(), subscriptions: { - wallet: wallet => { + wallet: (wallet) => { if (wallet.provider) { // this function will intialize web3 and store it somewhere available throughout the dapp and // can also instantiate your contracts with the web3 instance @@ -31,7 +31,7 @@ export const onboard = new Onboard({ providerName = wallet.name } }, - address: address => { + address: (address) => { if (!lastUsedAddress && address) { lastUsedAddress = address store.dispatch(fetchProvider(providerName)) @@ -45,6 +45,7 @@ export const onboard = new Onboard({ }, }, walletSelect: { + description: 'Please select a wallet to connect to Gnosis Safe Multisig', wallets, }, walletCheck: [{ checkName: 'connect' }, transactionDataCheck(), { checkName: 'network' }, { checkName: 'accounts' }], diff --git a/src/components/CookiesBanner/index.jsx b/src/components/CookiesBanner/index.jsx index c020bbcb..f857685b 100644 --- a/src/components/CookiesBanner/index.jsx +++ b/src/components/CookiesBanner/index.jsx @@ -160,7 +160,7 @@ const CookiesBanner = () => { disabled label="Necessary" name="Necessary" - onChange={() => setLocalNecessary(prev => !prev)} + onChange={() => setLocalNecessary((prev) => !prev)} value={localNecessary} /> @@ -169,7 +169,7 @@ const CookiesBanner = () => { control={} label="Analytics" name="Analytics" - onChange={() => setLocalAnalytics(prev => !prev)} + onChange={() => setLocalAnalytics((prev) => !prev)} value={localAnalytics} /> diff --git a/src/components/Header/components/Layout.jsx b/src/components/Header/components/Layout.jsx index 9d0a5aaa..0fea8a87 100644 --- a/src/components/Header/components/Layout.jsx +++ b/src/components/Header/components/Layout.jsx @@ -77,7 +77,7 @@ const Layout = openHoc(({ classes, clickAway, open, providerDetails, providerInf - {providerRef => ( + {(providerRef) => ( { export default connect( // $FlowFixMe - state => ({ safesCount: safesCountSelector(state) }), + (state) => ({ safesCount: safesCountSelector(state) }), null, )(SafeListHeader) diff --git a/src/components/Identicon/blockies.js b/src/components/Identicon/blockies.js index 538b828d..bebdfb9b 100644 --- a/src/components/Identicon/blockies.js +++ b/src/components/Identicon/blockies.js @@ -1,11 +1,11 @@ /* eslint-disable */ -;(function(global, factory) { +;(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : factory((global.blockies = {})) -})(this, function(exports) { +})(this, function (exports) { 'use strict' /** @@ -40,7 +40,7 @@ return String.fromCharCode(w & 255, (w >> 8) & 255) } - var PNG = function(width, height, depth) { + var PNG = function (width, height, depth) { this.width = width this.height = height this.depth = depth @@ -115,14 +115,14 @@ } // compute the index into a png for a given pixel - this.index = function(x, y) { + this.index = function (x, y) { var i = y * (this.width + 1) + x + 1 var j = this.idat_offs + 8 + 2 + 5 * Math.floor(i / 0xffff + 1) + i return j } // convert a color and build up the palette - this.color = function(red, green, blue, alpha) { + this.color = function (red, green, blue, alpha) { alpha = alpha >= 0 ? alpha : 255 var color = (((((alpha << 8) | red) << 8) | green) << 8) | blue @@ -142,7 +142,7 @@ } // output a PNG string, Base64 encoded - this.getBase64 = function() { + this.getBase64 = function () { var s = this.getDump() var ch = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=' @@ -173,7 +173,7 @@ } // output a PNG string - this.getDump = function() { + this.getDump = function () { // compute adler32 of output pixels + row filter bytes var BASE = 65521 /* largest prime smaller than 65536 */ var NMAX = 5552 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ @@ -215,7 +215,7 @@ return '\x89PNG\r\n\x1A\n' + this.buffer.join('') } - this.fillRect = function(x, y, w, h, color) { + this.fillRect = function (x, y, w, h, color) { for (var i = 0; i < w; i++) { for (var j = 0; j < h; j++) { this.buffer[this.index(x + i, y + j)] = color diff --git a/src/components/Notifier/index.js b/src/components/Notifier/index.js index 8982b3ca..46a51d24 100644 --- a/src/components/Notifier/index.js +++ b/src/components/Notifier/index.js @@ -45,7 +45,7 @@ class Notifier extends Component { componentDidUpdate() { const { notifications = [], enqueueSnackbar, removeSnackbar } = this.props - notifications.forEach(notification => { + notifications.forEach((notification) => { // Do nothing if snackbar is already displayed if (this.displayed.includes(notification.key)) { return @@ -68,7 +68,7 @@ class Notifier extends Component { }) } - storeDisplayed = id => { + storeDisplayed = (id) => { this.displayed = [...this.displayed, id] } diff --git a/src/components/ScanQRModal/index.jsx b/src/components/ScanQRModal/index.jsx index c5a95c0b..ff4af1f1 100644 --- a/src/components/ScanQRModal/index.jsx +++ b/src/components/ScanQRModal/index.jsx @@ -72,10 +72,10 @@ const ScanQRModal = ({ classes, isOpen, onClose, onScan }: Props) => { ) : ( { + onError={(err) => { console.error(err) }} - onScan={data => { + onScan={(data) => { if (data) onScan(data) }} ref={scannerRef} diff --git a/src/components/Sidebar/SafeList/index.jsx b/src/components/Sidebar/SafeList/index.jsx index 933dba50..9d83bd85 100644 --- a/src/components/Sidebar/SafeList/index.jsx +++ b/src/components/Sidebar/SafeList/index.jsx @@ -79,7 +79,7 @@ const SafeList = ({ currentSafe, defaultSafe, onSafeClick, safes, setDefaultSafe return ( - {safes.map(safe => ( + {safes.map((safe) => ( { + onClick={(e) => { e.preventDefault() e.stopPropagation() diff --git a/src/components/Sidebar/index.jsx b/src/components/Sidebar/index.jsx index c9eb972a..13c86f93 100644 --- a/src/components/Sidebar/index.jsx +++ b/src/components/Sidebar/index.jsx @@ -69,7 +69,7 @@ const Sidebar = ({ children, currentSafe, defaultSafe, safes, setDefaultSafeActi } const toggleSidebar = () => { - setIsOpen(prevIsOpen => !prevIsOpen) + setIsOpen((prevIsOpen) => !prevIsOpen) } const handleFilterChange = (value: string) => { @@ -142,7 +142,7 @@ const Sidebar = ({ children, currentSafe, defaultSafe, safes, setDefaultSafeActi export default connect( // $FlowFixMe - state => ({ + (state) => ({ safes: sortedSafeListSelector(state), defaultSafe: defaultSafeSelector(state), currentSafe: safeParamAddressFromStateSelector(state), diff --git a/src/components/Stepper/index.jsx b/src/components/Stepper/index.jsx index d2777316..e2cfce2a 100644 --- a/src/components/Stepper/index.jsx +++ b/src/components/Stepper/index.jsx @@ -54,7 +54,7 @@ const GnoStepper = (props: Props) => { const getPageProps = (pages: React.Node): PageProps => React.Children.toArray(pages)[page].props - const updateInitialProps = newInitialProps => { + const updateInitialProps = (newInitialProps) => { setValues(newInitialProps) } @@ -107,7 +107,7 @@ const GnoStepper = (props: Props) => { return next(formValues) } - const isLastPage = pageNumber => { + const isLastPage = (pageNumber) => { const { steps } = props return pageNumber === steps.length - 1 } diff --git a/src/components/Table/sorting.js b/src/components/Table/sorting.js index 9b983c8f..6d68b8f7 100644 --- a/src/components/Table/sorting.js +++ b/src/components/Table/sorting.js @@ -39,7 +39,7 @@ export const stableSort = (dataArray: List, cmp: any, fixed: boolean): List return a[1] - b[1] }) - const sortedElems: List = stabilizedThis.map(el => el[0]) + const sortedElems: List = stabilizedThis.map((el) => el[0]) return fixedElems.concat(sortedElems) } diff --git a/src/components/forms/AddressInput/index.jsx b/src/components/forms/AddressInput/index.jsx index 8e107fff..e371de9a 100644 --- a/src/components/forms/AddressInput/index.jsx +++ b/src/components/forms/AddressInput/index.jsx @@ -20,7 +20,7 @@ type Props = { disabled?: boolean, } -const isValidEnsName = name => /^([\w-]+\.)+(eth|test|xyz|luxe)$/.test(name) +const isValidEnsName = (name) => /^([\w-]+\.)+(eth|test|xyz|luxe)$/.test(name) // an idea for second field was taken from here // https://github.com/final-form/react-final-form-listeners/blob/master/src/OnBlur.js @@ -52,7 +52,7 @@ const AddressInput = ({ validate={composeValidators(required, mustBeEthereumAddress, ...validators)} /> - {async value => { + {async (value) => { if (isValidEnsName(value)) { try { const resolverAddr = await getAddressFromENS(value) diff --git a/src/components/forms/validator.js b/src/components/forms/validator.js index a992d8e2..0a065a4e 100644 --- a/src/components/forms/validator.js +++ b/src/components/forms/validator.js @@ -8,10 +8,10 @@ import { getWeb3 } from '~/logic/wallets/getWeb3' export const simpleMemoize = (fn: Function) => { let lastArg let lastResult - return (arg: any) => { + return (arg: any, ...args: any) => { if (arg !== lastArg) { lastArg = arg - lastResult = fn(arg) + lastResult = fn(arg, ...args) } return lastResult } @@ -84,7 +84,7 @@ export const ADDRESS_REPEATED_ERROR = 'Address already introduced' export const uniqueAddress = (addresses: string[] | List) => simpleMemoize((value: string) => { - const addressAlreadyExists = addresses.some(address => sameAddress(value, address)) + const addressAlreadyExists = addresses.some((address) => sameAddress(value, address)) return addressAlreadyExists ? ADDRESS_REPEATED_ERROR : undefined }) diff --git a/src/components/layout/PageFrame/index.jsx b/src/components/layout/PageFrame/index.jsx index 0abd1c11..73119389 100644 --- a/src/components/layout/PageFrame/index.jsx +++ b/src/components/layout/PageFrame/index.jsx @@ -80,7 +80,7 @@ const PageFrame = ({ children, classes, currentNetwork }: Props) => { export default withStyles(notificationStyles)( connect( - state => ({ + (state) => ({ currentNetwork: networkSelector(state), }), null, diff --git a/src/logic/addressBook/model/addressBook.js b/src/logic/addressBook/model/addressBook.js index ce769fe1..9cf1bd0e 100644 --- a/src/logic/addressBook/model/addressBook.js +++ b/src/logic/addressBook/model/addressBook.js @@ -1,5 +1,5 @@ // @flow -import type { RecordOf } from 'immutable' +import { Record, type RecordFactory, type RecordOf } from 'immutable' export type AddressBookEntry = { address: string, @@ -11,4 +11,10 @@ export type AddressBookProps = { addressBook: Map, } +export const makeAddressBookEntry: RecordFactory = Record({ + address: '', + name: '', + isOwner: false, +}) + export type AddressBook = RecordOf diff --git a/src/logic/addressBook/store/actions/addOrUpdateAddressBookEntry.js b/src/logic/addressBook/store/actions/addOrUpdateAddressBookEntry.js new file mode 100644 index 00000000..17519cf1 --- /dev/null +++ b/src/logic/addressBook/store/actions/addOrUpdateAddressBookEntry.js @@ -0,0 +1,14 @@ +// @flow +import { createAction } from 'redux-actions' + +import type { AddressBookEntryType } from '~/logic/addressBook/model/addressBook' + +export const ADD_OR_UPDATE_ENTRY = 'ADD_OR_UPDATE_ENTRY' + +export const addOrUpdateAddressBookEntry = createAction( + ADD_OR_UPDATE_ENTRY, + (entryAddress: string, entry: AddressBookEntryType): AddressBookEntryType => ({ + entryAddress, + entry, + }), +) diff --git a/src/logic/addressBook/store/actions/loadAddressBookFromStorage.js b/src/logic/addressBook/store/actions/loadAddressBookFromStorage.js index 013dd33f..8ed33370 100644 --- a/src/logic/addressBook/store/actions/loadAddressBookFromStorage.js +++ b/src/logic/addressBook/store/actions/loadAddressBookFromStorage.js @@ -19,7 +19,7 @@ const loadAddressBookFromStorage = () => async (dispatch: ReduxDispatch { + safes.forEach((safe) => { const { address } = safe const found = adbkEntries.includes(address) if (!found) { diff --git a/src/logic/addressBook/store/actions/saveAndUpdateAddressBook.js b/src/logic/addressBook/store/actions/saveAndUpdateAddressBook.js index 48f0190e..f4063e8a 100644 --- a/src/logic/addressBook/store/actions/saveAndUpdateAddressBook.js +++ b/src/logic/addressBook/store/actions/saveAndUpdateAddressBook.js @@ -2,13 +2,14 @@ import type { Dispatch as ReduxDispatch } from 'redux' import type { AddressBook } from '~/logic/addressBook/model/addressBook' +import { makeAddressBookEntry } from '~/logic/addressBook/model/addressBook' import { updateAddressBookEntry } from '~/logic/addressBook/store/actions/updateAddressBookEntry' import { saveAddressBook } from '~/logic/addressBook/utils' import { type GlobalState } from '~/store/index' const saveAndUpdateAddressBook = (addressBook: AddressBook) => async (dispatch: ReduxDispatch) => { try { - dispatch(updateAddressBookEntry(addressBook)) + dispatch(updateAddressBookEntry(makeAddressBookEntry(addressBook))) await saveAddressBook(addressBook) } catch (err) { // eslint-disable-next-line diff --git a/src/logic/addressBook/store/middleware/addressBookMiddleware.js b/src/logic/addressBook/store/middleware/addressBookMiddleware.js index 2cdfdf2f..3482d98e 100644 --- a/src/logic/addressBook/store/middleware/addressBookMiddleware.js +++ b/src/logic/addressBook/store/middleware/addressBookMiddleware.js @@ -3,6 +3,7 @@ import type { AnyAction, Store } from 'redux' import type { AddressBookProps } from '~/logic/addressBook/model/addressBook' import { ADD_ENTRY } from '~/logic/addressBook/store/actions/addAddressBookEntry' +import { ADD_OR_UPDATE_ENTRY } from '~/logic/addressBook/store/actions/addOrUpdateAddressBookEntry' import { REMOVE_ENTRY } from '~/logic/addressBook/store/actions/removeAddressBookEntry' import { UPDATE_ENTRY } from '~/logic/addressBook/store/actions/updateAddressBookEntry' import { addressBookMapSelector } from '~/logic/addressBook/store/selectors' @@ -10,9 +11,9 @@ import { saveAddressBook } from '~/logic/addressBook/utils' import { enhanceSnackbarForAction, getNotificationsFromTxType } from '~/logic/notifications' import enqueueSnackbar from '~/logic/notifications/store/actions/enqueueSnackbar' import { TX_NOTIFICATION_TYPES } from '~/logic/safe/transactions' -import { type GlobalState } from '~/store/' +import { type GlobalState } from '~/store' -const watchedActions = [ADD_ENTRY, REMOVE_ENTRY, UPDATE_ENTRY] +const watchedActions = [ADD_ENTRY, REMOVE_ENTRY, UPDATE_ENTRY, ADD_OR_UPDATE_ENTRY] const addressBookMiddleware = (store: Store) => (next: Function) => async (action: AnyAction) => { const handledAction = next(action) diff --git a/src/logic/addressBook/store/reducer/addressBook.js b/src/logic/addressBook/store/reducer/addressBook.js index 449c74bf..93f4ebf7 100644 --- a/src/logic/addressBook/store/reducer/addressBook.js +++ b/src/logic/addressBook/store/reducer/addressBook.js @@ -3,8 +3,10 @@ import { List, Map } from 'immutable' import { type ActionType, handleActions } from 'redux-actions' import type { AddressBook, AddressBookEntry, AddressBookProps } from '~/logic/addressBook/model/addressBook' +import { makeAddressBookEntry } from '~/logic/addressBook/model/addressBook' import { ADD_ADDRESS_BOOK } from '~/logic/addressBook/store/actions/addAddressBook' import { ADD_ENTRY } from '~/logic/addressBook/store/actions/addAddressBookEntry' +import { ADD_OR_UPDATE_ENTRY } from '~/logic/addressBook/store/actions/addOrUpdateAddressBookEntry' import { LOAD_ADDRESS_BOOK } from '~/logic/addressBook/store/actions/loadAddressBook' import { REMOVE_ENTRY } from '~/logic/addressBook/store/actions/removeAddressBookEntry' import { UPDATE_ENTRY } from '~/logic/addressBook/store/actions/updateAddressBookEntry' @@ -19,7 +21,8 @@ export const buildAddressBook = (storedAdbk: AddressBook): AddressBookProps => { let addressBookBuilt = Map([]) Object.entries(storedAdbk).forEach((adbkProps: Array) => { const safeAddress = adbkProps[0] - const adbkSafeEntries = List(adbkProps[1]) + const adbkRecords = adbkProps[1].map(makeAddressBookEntry) + const adbkSafeEntries = List(adbkRecords) addressBookBuilt = addressBookBuilt.set(safeAddress, adbkSafeEntries) }) return addressBookBuilt @@ -44,11 +47,11 @@ export default handleActions( const { entry } = action.payload // Adds the entry to all the safes (if it does not already exists) - const newState = state.withMutations(map => { + const newState = state.withMutations((map) => { const adbkMap = map.get('addressBook') if (adbkMap) { - adbkMap.keySeq().forEach(safeAddress => { + adbkMap.keySeq().forEach((safeAddress) => { const safeAddressBook = state.getIn(['addressBook', safeAddress]) if (safeAddressBook) { @@ -68,13 +71,13 @@ export default handleActions( const { entry } = action.payload // Updates the entry from all the safes - const newState = state.withMutations(map => { + const newState = state.withMutations((map) => { map .get('addressBook') .keySeq() - .forEach(safeAddress => { + .forEach((safeAddress) => { const entriesList: List = state.getIn(['addressBook', safeAddress]) - const entryIndex = entriesList.findIndex(entryItem => sameAddress(entryItem.address, entry.address)) + const entryIndex = entriesList.findIndex((entryItem) => sameAddress(entryItem.address, entry.address)) const updatedEntriesList = entriesList.set(entryIndex, entry) map.setIn(['addressBook', safeAddress], updatedEntriesList) }) @@ -85,19 +88,41 @@ export default handleActions( [REMOVE_ENTRY]: (state: State, action: ActionType): State => { const { entryAddress } = action.payload // Removes the entry from all the safes - const newState = state.withMutations(map => { + const newState = state.withMutations((map) => { map .get('addressBook') .keySeq() - .forEach(safeAddress => { + .forEach((safeAddress) => { const entriesList = state.getIn(['addressBook', safeAddress]) - const entryIndex = entriesList.findIndex(entry => sameAddress(entry.address, entryAddress)) + const entryIndex = entriesList.findIndex((entry) => sameAddress(entry.address, entryAddress)) const updatedEntriesList = entriesList.remove(entryIndex) map.setIn(['addressBook', safeAddress], updatedEntriesList) }) }) return newState }, + [ADD_OR_UPDATE_ENTRY]: (state: State, action: ActionType): State => { + const { entry, entryAddress } = action.payload + + // Adds or Updates the entry to all the safes + return state.withMutations((map) => { + const addressBook = map.get('addressBook') + if (addressBook) { + addressBook.keySeq().forEach((safeAddress) => { + const safeAddressBook: List = state.getIn(['addressBook', safeAddress]) + const entryIndex = safeAddressBook.findIndex((entryItem) => sameAddress(entryItem.address, entryAddress)) + + if (entryIndex !== -1) { + const updatedEntriesList = safeAddressBook.update(entryIndex, (currentEntry) => currentEntry.merge(entry)) + map.setIn(['addressBook', safeAddress], updatedEntriesList) + } else { + const updatedSafeAdbkList = safeAddressBook.push(makeAddressBookEntry(entry)) + map.setIn(['addressBook', safeAddress], updatedSafeAdbkList) + } + }) + } + }) + }, }, Map(), ) diff --git a/src/logic/addressBook/store/selectors/index.js b/src/logic/addressBook/store/selectors/index.js index 259185db..edef7837 100644 --- a/src/logic/addressBook/store/selectors/index.js +++ b/src/logic/addressBook/store/selectors/index.js @@ -41,7 +41,7 @@ export const getNameFromAddressBook = (userAddress: string): string | null => { return null } const addressBook = useSelector(getAddressBook) - const result = addressBook.filter(addressBookItem => addressBookItem.address === userAddress) + const result = addressBook.filter((addressBookItem) => addressBookItem.address === userAddress) if (result.size > 0) { return result.get(0).name } diff --git a/src/logic/addressBook/utils/index.js b/src/logic/addressBook/utils/index.js index dd545fc7..52d98617 100644 --- a/src/logic/addressBook/utils/index.js +++ b/src/logic/addressBook/utils/index.js @@ -23,10 +23,10 @@ export const saveAddressBook = async (addressBook: AddressBook) => { } export const getAddressesListFromAdbk = (addressBook: AddressBook) => - Array.from(addressBook).map(entry => entry.address) + Array.from(addressBook).map((entry) => entry.address) const getNameFromAdbk = (addressBook: AddressBook, userAddress: string): string | null => { - const entry = addressBook.find(addressBookItem => addressBookItem.address === userAddress) + const entry = addressBook.find((addressBookItem) => addressBookItem.address === userAddress) if (entry) { return entry.name } @@ -45,7 +45,7 @@ export const getOwnersWithNameFromAddressBook = (addressBook: AddressBook, owner if (!ownerList) { return [] } - const ownersListWithAdbkNames = ownerList.map(owner => { + const ownersListWithAdbkNames = ownerList.map((owner) => { const ownerName = getNameFromAdbk(addressBook, owner.address) return { address: owner.address, diff --git a/src/logic/collectibles/store/selectors/index.js b/src/logic/collectibles/store/selectors/index.js index 5ac167c8..79c3b886 100644 --- a/src/logic/collectibles/store/selectors/index.js +++ b/src/logic/collectibles/store/selectors/index.js @@ -1,6 +1,38 @@ // @flow +import { List, Set } from 'immutable' +import type { Selector } from 'reselect' +import { createSelector } from 'reselect' + import { NFT_ASSETS_REDUCER_ID, NFT_TOKENS_REDUCER_ID } from '~/logic/collectibles/store/reducer/collectibles' +import type { NFTAssets } from '~/routes/safe/components/Balances/Collectibles/types' +import { safeActiveAssetsSelector } from '~/routes/safe/store/selectors' import type { GlobalState } from '~/store' export const nftAssetsSelector = (state: GlobalState) => state[NFT_ASSETS_REDUCER_ID] export const nftTokensSelector = (state: GlobalState) => state[NFT_TOKENS_REDUCER_ID] + +export const nftAssetsListSelector: Selector> = createSelector( + nftAssetsSelector, + (assets: NFTAssets) => { + return assets ? List(Object.entries(assets).map((item) => item[1])) : List([]) + }, +) + +export const activeNftAssetsListSelector: Selector> = createSelector( + nftAssetsListSelector, + safeActiveAssetsSelector, + (assets: List, activeAssetsList: Set) => { + return assets.filter((asset) => activeAssetsList.has(asset.address)) + }, +) + +export const safeActiveSelectorMap: Selector> = createSelector( + activeNftAssetsListSelector, + (activeAssets: List) => { + let assetsMap = {} + activeAssets.forEach((asset) => { + assetsMap[asset.address] = asset + }) + return assetsMap + }, +) diff --git a/src/logic/contracts/safeContracts.js b/src/logic/contracts/safeContracts.js index 395015b3..f5d85586 100644 --- a/src/logic/contracts/safeContracts.js +++ b/src/logic/contracts/safeContracts.js @@ -5,7 +5,7 @@ import GnosisSafeSol from '@gnosis.pm/safe-contracts/build/contracts/GnosisSafe. import SafeProxy from '@gnosis.pm/safe-contracts/build/contracts/GnosisSafeProxy.json' import { ensureOnce } from '~/utils/singleton' import { simpleMemoize } from '~/components/forms/validator' -import { getWeb3 } from '~/logic/wallets/getWeb3' +import { getWeb3, getNetworkIdFrom } from '~/logic/wallets/getWeb3' import { calculateGasOf, calculateGasPrice } from '~/logic/wallets/ethTransactions' import { ZERO_ADDRESS } from '~/logic/wallets/ethAddresses' import { isProxyCode } from '~/logic/contracts/historicProxyCode' @@ -27,9 +27,9 @@ const createGnosisSafeContract = (web3: any) => { return gnosisSafe } -const createProxyFactoryContract = (web3: any) => { - const proxyFactory = contract(ProxyFactorySol) - proxyFactory.setProvider(web3.currentProvider) +const createProxyFactoryContract = (web3: any, networkId: number) => { + const contractAddress = ProxyFactorySol.networks[networkId].address + const proxyFactory = new web3.eth.Contract(ProxyFactorySol.abi, contractAddress) return proxyFactory } @@ -39,10 +39,10 @@ const getCreateProxyFactoryContract = simpleMemoize(createProxyFactoryContract) const instantiateMasterCopies = async () => { const web3 = getWeb3() + const networkId = await getNetworkIdFrom(web3) // Create ProxyFactory Master Copy - const ProxyFactory = getCreateProxyFactoryContract(web3) - proxyFactoryMaster = await ProxyFactory.deployed() + proxyFactoryMaster = getCreateProxyFactoryContract(web3, networkId) // Initialize Safe master copy const GnosisSafe = getGnosisSafeContract(web3) @@ -70,22 +70,12 @@ export const getSafeMasterContract = async () => { return safeMaster } -export const deploySafeContract = async (safeAccounts: string[], numConfirmations: number, userAccount: string) => { - const gnosisSafeData = await safeMaster.contract.methods +export const getSafeDeploymentTransaction = (safeAccounts: string[], numConfirmations: number, userAccount: string) => { + const gnosisSafeData = safeMaster.contract.methods .setup(safeAccounts, numConfirmations, ZERO_ADDRESS, '0x', DEFAULT_FALLBACK_HANDLER_ADDRESS, ZERO_ADDRESS, 0, ZERO_ADDRESS) - .encodeABI() - const proxyFactoryData = proxyFactoryMaster.contract.methods - .createProxy(safeMaster.address, gnosisSafeData) - .encodeABI() - const gas = await calculateGasOf(proxyFactoryData, userAccount, proxyFactoryMaster.address) - const gasPrice = await calculateGasPrice() + .encodeABI() - return proxyFactoryMaster.createProxy(safeMaster.address, gnosisSafeData, { - from: userAccount, - gas, - gasPrice, - value: 0, - }) + return proxyFactoryMaster.methods.createProxy(safeMaster.address, gnosisSafeData) } export const estimateGasForDeployingSafe = async ( @@ -93,10 +83,11 @@ export const estimateGasForDeployingSafe = async ( numConfirmations: number, userAccount: string, ) => { + console.log(proxyFactoryMaster) const gnosisSafeData = await safeMaster.contract.methods .setup(safeAccounts, numConfirmations, ZERO_ADDRESS, '0x', DEFAULT_FALLBACK_HANDLER_ADDRESS, ZERO_ADDRESS, 0, ZERO_ADDRESS) .encodeABI() - const proxyFactoryData = proxyFactoryMaster.contract.methods + const proxyFactoryData = proxyFactoryMaster.methods .createProxy(safeMaster.address, gnosisSafeData) .encodeABI() const gas = await calculateGasOf(proxyFactoryData, userAccount, proxyFactoryMaster.address) diff --git a/src/logic/currencyValues/store/actions/fetchCurrencyValues.js b/src/logic/currencyValues/store/actions/fetchCurrencyValues.js index 9be3bc7c..8ad14f95 100644 --- a/src/logic/currencyValues/store/actions/fetchCurrencyValues.js +++ b/src/logic/currencyValues/store/actions/fetchCurrencyValues.js @@ -18,8 +18,8 @@ export const fetchCurrencyValues = (safeAddress: string) => async (dispatch: Red // eslint-disable-next-line max-len const currencyList = List( tokensFetched.data - .filter(currencyBalance => currencyBalance.balanceUsd) - .map(currencyBalance => { + .filter((currencyBalance) => currencyBalance.balanceUsd) + .map((currencyBalance) => { const { balanceUsd, tokenAddress } = currencyBalance return makeBalanceCurrency({ currencyName: balanceUsd ? AVAILABLE_CURRENCIES.USD : null, diff --git a/src/logic/currentSession/store/reducer/currentSession.js b/src/logic/currentSession/store/reducer/currentSession.js index 292d4b7c..d8b427ea 100644 --- a/src/logic/currentSession/store/reducer/currentSession.js +++ b/src/logic/currentSession/store/reducer/currentSession.js @@ -16,7 +16,7 @@ export default handleActions( [UPDATE_VIEWED_SAFES]: (state: State, action: ActionType): State => { const safeAddress = action.payload - const newState = state.updateIn(['viewedSafes'], prev => + const newState = state.updateIn(['viewedSafes'], (prev) => prev.includes(safeAddress) ? prev : [...prev, safeAddress], ) diff --git a/src/logic/notifications/notificationBuilder.js b/src/logic/notifications/notificationBuilder.js index 80008d7b..af5b4549 100644 --- a/src/logic/notifications/notificationBuilder.js +++ b/src/logic/notifications/notificationBuilder.js @@ -231,7 +231,7 @@ export const showSnackbar = (notification: Notification, enqueueSnackbar: Functi enqueueSnackbar(notification.message, { ...notification.options, // eslint-disable-next-line react/display-name - action: key => ( + action: (key) => ( closeSnackbar(key)}> diff --git a/src/logic/notifications/store/reducer/notifications.js b/src/logic/notifications/store/reducer/notifications.js index c588dfc8..cc955d14 100644 --- a/src/logic/notifications/store/reducer/notifications.js +++ b/src/logic/notifications/store/reducer/notifications.js @@ -23,10 +23,10 @@ export default handleActions( const { dismissAll, key } = action.payload if (key) { - return state.update(key, prev => prev.set('dismissed', true)) + return state.update(key, (prev) => prev.set('dismissed', true)) } if (dismissAll) { - return state.withMutations(map => { + return state.withMutations((map) => { map.forEach((notification, notificationKey) => { map.set(notificationKey, notification.set('dismissed', true)) }) diff --git a/src/logic/safe/safeTxSigner.js b/src/logic/safe/safeTxSigner.js index cfa5716a..fc46af26 100644 --- a/src/logic/safe/safeTxSigner.js +++ b/src/logic/safe/safeTxSigner.js @@ -23,7 +23,7 @@ export const generateSignaturesFromTxConfirmations = ( let sigs = '0x' Object.keys(confirmationsMap) .sort() - .forEach(addr => { + .forEach((addr) => { const conf = confirmationsMap[addr] if (conf.signature) { sigs += conf.signature.slice(2) diff --git a/src/logic/safe/transactions/awaitingTransactions.js b/src/logic/safe/transactions/awaitingTransactions.js index 4ac01144..1320b38d 100644 --- a/src/logic/safe/transactions/awaitingTransactions.js +++ b/src/logic/safe/transactions/awaitingTransactions.js @@ -12,22 +12,23 @@ export const getAwaitingTransactions = ( return Map({}) } - const allAwaitingTransactions = allTransactions.map(safeTransactions => { + const allAwaitingTransactions = allTransactions.map((safeTransactions) => { const nonCancelledTransactions = safeTransactions.filter((transaction: Transaction) => { // If transactions are not executed, but there's a transaction with the same nonce EXECUTED later // it means that the transaction was cancelled (Replaced) and shouldn't get executed + let isTransactionCancelled = false if (!transaction.isExecuted) { if (cancellationTransactionsByNonce.get(transaction.nonce)) { // eslint-disable-next-line no-param-reassign - transaction = transaction.set('cancelled', true) + isTransactionCancelled = true } } // The transaction is not executed and is not cancelled, so it's still waiting confirmations - if (!transaction.executionTxHash && !transaction.cancelled) { + if (!transaction.executionTxHash && !isTransactionCancelled) { // Then we check if the waiting confirmations are not from the current user, otherwise, filters this // transaction const transactionWaitingUser = transaction.confirmations.filter( - confirmation => confirmation.owner && confirmation.owner.address !== userAccount, + (confirmation) => confirmation.owner && confirmation.owner.address !== userAccount, ) return transactionWaitingUser.size > 0 diff --git a/src/logic/safe/transactions/gas.js b/src/logic/safe/transactions/gas.js index c8072f37..15d3aca4 100644 --- a/src/logic/safe/transactions/gas.js +++ b/src/logic/safe/transactions/gas.js @@ -5,7 +5,7 @@ import { getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts' import { EMPTY_DATA } from '~/logic/wallets/ethTransactions' import { getWeb3 } from '~/logic/wallets/getWeb3' -const estimateDataGasCosts = data => { +const estimateDataGasCosts = (data) => { const reducer = (accumulator, currentValue) => { if (currentValue === EMPTY_DATA) { return accumulator + 0 diff --git a/src/logic/safe/transactions/index.js b/src/logic/safe/transactions/index.js index 63d8a8b0..d6b2882a 100644 --- a/src/logic/safe/transactions/index.js +++ b/src/logic/safe/transactions/index.js @@ -1,6 +1,6 @@ // @flow export * from './gas' export * from './send' -export * from './safeTxSignerEIP712' +export * from './offchainSigner' export * from './txHistory' export * from './notifiedTransactions' diff --git a/src/logic/safe/transactions/offchainSigner/EIP712Signer.js b/src/logic/safe/transactions/offchainSigner/EIP712Signer.js new file mode 100644 index 00000000..18fc5001 --- /dev/null +++ b/src/logic/safe/transactions/offchainSigner/EIP712Signer.js @@ -0,0 +1,100 @@ +// @flow +import { EMPTY_DATA } from '~/logic/wallets/ethTransactions' +import { getWeb3 } from '~/logic/wallets/getWeb3' + +const EIP712_NOT_SUPPORTED_ERROR_MSG = "EIP712 is not supported by user's wallet" + +const generateTypedDataFrom = async ({ + baseGas, + data, + gasPrice, + gasToken, + nonce, + operation, + refundReceiver, + safeAddress, + safeTxGas, + to, + valueInWei, +}) => { + const typedData = { + types: { + EIP712Domain: [ + { + type: 'address', + name: 'verifyingContract', + }, + ], + SafeTx: [ + { type: 'address', name: 'to' }, + { type: 'uint256', name: 'value' }, + { type: 'bytes', name: 'data' }, + { type: 'uint8', name: 'operation' }, + { type: 'uint256', name: 'safeTxGas' }, + { type: 'uint256', name: 'baseGas' }, + { type: 'uint256', name: 'gasPrice' }, + { type: 'address', name: 'gasToken' }, + { type: 'address', name: 'refundReceiver' }, + { type: 'uint256', name: 'nonce' }, + ], + }, + domain: { + verifyingContract: safeAddress, + }, + primaryType: 'SafeTx', + message: { + to, + value: valueInWei, + data, + operation, + safeTxGas, + baseGas, + gasPrice, + gasToken, + refundReceiver, + nonce: Number(nonce), + }, + } + + return typedData +} + +type EIP712RpcCallVersion = 'v3' | 'v4' + +export const getEIP712Signer = (version: ?EIP712RpcCallVersion) => async (txArgs) => { + const web3 = getWeb3() + const typedData = await generateTypedDataFrom(txArgs) + + let method = 'eth_signTypedData_v3' + if (version === 'v4') { + method = 'eth_signTypedData_v4' + } + if (!version) { + method = 'eth_signTypedData' + } + + const jsonTypedData = JSON.stringify(typedData) + const signedTypedData = { + jsonrpc: '2.0', + method, + params: version === 'v3' || version === 'v4' ? [txArgs.sender, jsonTypedData] : [jsonTypedData, txArgs.sender], + from: txArgs.sender, + id: new Date().getTime(), + } + + return new Promise((resolve, reject) => { + web3.currentProvider.sendAsync(signedTypedData, (err, signature) => { + if (err) { + reject(err) + return + } + + if (signature.result == null) { + reject(new Error(EIP712_NOT_SUPPORTED_ERROR_MSG)) + return + } + + resolve(signature.result.replace(EMPTY_DATA, '')) + }) + }) +} diff --git a/src/logic/safe/transactions/offchainSigner/ethSigner.js b/src/logic/safe/transactions/offchainSigner/ethSigner.js new file mode 100644 index 00000000..42a772cb --- /dev/null +++ b/src/logic/safe/transactions/offchainSigner/ethSigner.js @@ -0,0 +1,60 @@ +// @flow +import { EMPTY_DATA } from '~/logic/wallets/ethTransactions' +import { getWeb3 } from '~/logic/wallets/getWeb3' + +const ETH_SIGN_NOT_SUPPORTED_ERROR_MSG = 'ETH_SIGN_NOT_SUPPORTED' + +export const getEthSigner = async ({ + baseGas, + data, + gasPrice, + gasToken, + nonce, + operation, + refundReceiver, + safeInstance, + safeTxGas, + sender, + to, + valueInWei, +}) => { + const web3 = await getWeb3() + const txHash = await safeInstance.getTransactionHash( + to, + valueInWei, + data, + operation, + safeTxGas, + baseGas, + gasPrice, + gasToken, + refundReceiver, + nonce, + { + from: sender, + }, + ) + + return new Promise(function (resolve, reject) { + web3.currentProvider.sendAsync( + { + jsonrpc: '2.0', + method: 'eth_sign', + params: [sender, txHash], + id: new Date().getTime(), + }, + async function (err, signature) { + if (err) { + return reject(err) + } + + if (signature.result == null) { + reject(new Error(ETH_SIGN_NOT_SUPPORTED_ERROR_MSG)) + return + } + + resolve(signature.result.replace(EMPTY_DATA, '')) + }, + ) + }) +} diff --git a/src/logic/safe/transactions/offchainSigner/index.js b/src/logic/safe/transactions/offchainSigner/index.js new file mode 100644 index 00000000..2e360d5f --- /dev/null +++ b/src/logic/safe/transactions/offchainSigner/index.js @@ -0,0 +1,31 @@ +// @flow + +import { getEIP712Signer } from './EIP712Signer' +import { getEthSigner } from './ethSigner' + +// 1. we try to sign via EIP-712 if user's wallet supports it +// 2. If not, try to use eth_sign (Safe version has to be >1.1.1) +// If eth_sign, doesn't work continue with the regular flow (on-chain signatures, more in createTransaction.js) + +const signingFuncs = [getEIP712Signer('v3'), getEIP712Signer('v4'), getEIP712Signer(), getEthSigner] + +export const SAFE_VERSION_FOR_OFFCHAIN_SIGNATURES = '>=1.1.1' + +export const tryOffchainSigning = async (txArgs) => { + let signature + for (let signingFunc of signingFuncs) { + try { + signature = await signingFunc(txArgs) + + break + } catch (err) { + console.error(err) + // Metamask sign request error code + if (err.code === 4001) { + throw new Error('User denied sign request') + } + } + } + + return signature +} diff --git a/src/logic/safe/transactions/safeTxSignerEIP712.js b/src/logic/safe/transactions/safeTxSignerEIP712.js deleted file mode 100644 index 0cdc7c44..00000000 --- a/src/logic/safe/transactions/safeTxSignerEIP712.js +++ /dev/null @@ -1,98 +0,0 @@ -// @flow -import { EMPTY_DATA } from '~/logic/wallets/ethTransactions' -import { getWeb3 } from '~/logic/wallets/getWeb3' - -const generateTypedDataFrom = async ( - safe: any, - safeAddress: string, - to: string, - valueInWei: number, - nonce: number, - data: string, - operation: number, - txGasEstimate: number, -) => { - const txGasToken = 0 - // const threshold = await safe.getThreshold() - // estimateDataGas(safe, to, valueInWei, data, operation, txGasEstimate, txGasToken, nonce, threshold) - const dataGasEstimate = 0 - const gasPrice = 0 - const refundReceiver = 0 - const typedData = { - types: { - EIP712Domain: [ - { - type: 'address', - name: 'verifyingContract', - }, - ], - SafeTx: [ - { type: 'address', name: 'to' }, - { type: 'uint256', name: 'value' }, - { type: 'bytes', name: 'data' }, - { type: 'uint8', name: 'operation' }, - { type: 'uint256', name: 'safeTxGas' }, - { type: 'uint256', name: 'dataGas' }, - { type: 'uint256', name: 'gasPrice' }, - { type: 'address', name: 'gasToken' }, - { type: 'address', name: 'refundReceiver' }, - { type: 'uint256', name: 'nonce' }, - ], - }, - domain: { - verifyingContract: safeAddress, - }, - primaryType: 'SafeTx', - message: { - to, - value: Number(valueInWei), - data, - operation, - safeTxGas: txGasEstimate, - dataGas: dataGasEstimate, - gasPrice, - gasToken: txGasToken, - refundReceiver, - nonce: Number(nonce), - }, - } - - return typedData -} - -export const generateMetamaskSignature = async ( - safe: any, - safeAddress: string, - sender: string, - to: string, - valueInWei: number, - nonce: number, - data: string, - operation: number, - txGasEstimate: number, -) => { - const web3 = getWeb3() - const typedData = await generateTypedDataFrom( - safe, - safeAddress, - to, - valueInWei, - nonce, - data, - operation, - txGasEstimate, - ) - - const jsonTypedData = JSON.stringify(typedData) - const signedTypedData = { - method: 'eth_signTypedData_v3', - // To change once Metamask fixes their status - // https://github.com/MetaMask/metamask-extension/pull/5368 - // https://github.com/MetaMask/metamask-extension/issues/5366 - params: [sender, jsonTypedData], - from: sender, - } - const txSignedResponse = await web3.currentProvider.sendAsync(signedTypedData) - - return txSignedResponse.result.replace(EMPTY_DATA, '') -} diff --git a/src/logic/safe/transactions/send.js b/src/logic/safe/transactions/send.js index 6c4f99ea..d6ce555b 100644 --- a/src/logic/safe/transactions/send.js +++ b/src/logic/safe/transactions/send.js @@ -54,6 +54,7 @@ export const getApprovalTransaction = async ({ try { const web3 = getWeb3() + const contract = new web3.eth.Contract(GnosisSafeSol.abi, safeInstance.address) return contract.methods.approveHash(txHash) diff --git a/src/logic/safe/transactions/txHistory.js b/src/logic/safe/transactions/txHistory.js index 53a1ad41..73bff589 100644 --- a/src/logic/safe/transactions/txHistory.js +++ b/src/logic/safe/transactions/txHistory.js @@ -19,10 +19,10 @@ const calculateBodyFrom = async ( gasPrice: string | number, gasToken: string, refundReceiver: string, - transactionHash: string, + transactionHash: string | null, sender: string, - confirmationType: TxServiceType, origin: string | null, + signature: ?string, ) => { const contractTransactionHash = await safeInstance.getTransactionHash( to, @@ -51,8 +51,8 @@ const calculateBodyFrom = async ( contractTransactionHash, transactionHash, sender: getWeb3().utils.toChecksumAddress(sender), - confirmationType, origin, + signature, } } @@ -75,9 +75,9 @@ export const saveTxToHistory = async ({ safeInstance, safeTxGas, sender, + signature, to, txHash, - type, valueInWei, }: { safeInstance: any, @@ -91,10 +91,10 @@ export const saveTxToHistory = async ({ gasPrice: string | number, gasToken: string, refundReceiver: string, - txHash: string, + txHash: string | null, sender: string, - type: TxServiceType, origin: string | null, + signature: ?string, }) => { const url = buildTxServiceUrl(safeInstance.address) const body = await calculateBodyFrom( @@ -109,10 +109,10 @@ export const saveTxToHistory = async ({ gasPrice, gasToken, refundReceiver, - txHash, + txHash || null, sender, - type, origin || null, + signature, ) const response = await axios.post(url, body) diff --git a/src/logic/safe/utils/safeVersion.js b/src/logic/safe/utils/safeVersion.js index e76f59fb..423ea4c7 100644 --- a/src/logic/safe/utils/safeVersion.js +++ b/src/logic/safe/utils/safeVersion.js @@ -22,7 +22,7 @@ export const safeNeedsUpdate = (currentVersion: string, latestVersion: string) = return latest ? semverLessThan(current, latest) : false } -export const getCurrentSafeVersion = gnosisSafeInstance => gnosisSafeInstance.VERSION() +export const getCurrentSafeVersion = (gnosisSafeInstance) => gnosisSafeInstance.VERSION() export const enabledFeatures = (version: string) => FEATURES.reduce((acc, feature) => { @@ -57,7 +57,7 @@ export const getCurrentMasterContractLastVersion = async () => { return safeMasterVersion } -export const getSafeVersion = async (safeAddress: string) => { +export const getSafeVersionInfo = async (safeAddress: string) => { try { const safeMaster = await getGnosisSafeInstanceAt(safeAddress) const lastSafeVersion = await getCurrentMasterContractLastVersion() diff --git a/src/logic/tokens/api/fetchTokenBalanceList.js b/src/logic/tokens/api/fetchTokenBalanceList.js index e0116e41..ee1183fb 100644 --- a/src/logic/tokens/api/fetchTokenBalanceList.js +++ b/src/logic/tokens/api/fetchTokenBalanceList.js @@ -9,7 +9,7 @@ const fetchTokenBalanceList = (safeAddress: string) => { return axios.get(url, { params: { - limit: 300, + limit: 3000, }, }) } diff --git a/src/logic/tokens/api/fetchTokenList.js b/src/logic/tokens/api/fetchTokenList.js index 7338d965..c83001fc 100644 --- a/src/logic/tokens/api/fetchTokenList.js +++ b/src/logic/tokens/api/fetchTokenList.js @@ -9,7 +9,7 @@ const fetchTokenList = () => { return axios.get(url, { params: { - limit: 300, + limit: 3000, }, }) } diff --git a/src/logic/tokens/store/actions/activateAssetsByBalance.js b/src/logic/tokens/store/actions/activateAssetsByBalance.js new file mode 100644 index 00000000..3cffa977 --- /dev/null +++ b/src/logic/tokens/store/actions/activateAssetsByBalance.js @@ -0,0 +1,49 @@ +// @flow + +import type { Dispatch as ReduxDispatch } from 'redux' + +import fetchCollectibles from '~/logic/collectibles/store/actions/fetchCollectibles' +import { nftAssetsSelector } from '~/logic/collectibles/store/selectors' +import updateActiveAssets from '~/routes/safe/store/actions/updateActiveAssets' +import { + safeActiveAssetsSelectorBySafe, + safeBlacklistedAssetsSelectorBySafe, + safesMapSelector, +} from '~/routes/safe/store/selectors' +import { type GetState, type GlobalState } from '~/store' + +const activateAssetsByBalance = (safeAddress: string) => async ( + dispatch: ReduxDispatch, + getState: GetState, +) => { + try { + await dispatch(fetchCollectibles()) + const state = getState() + const safes = safesMapSelector(state) + const availableAssets = nftAssetsSelector(state) + const alreadyActiveAssets = safeActiveAssetsSelectorBySafe(safeAddress, safes) + const blacklistedAssets = safeBlacklistedAssetsSelectorBySafe(safeAddress, safes) + + // active tokens by balance, excluding those already blacklisted and the `null` address + const activeByBalance = Object.entries(availableAssets) + .filter((asset) => { + const { address, numberOfTokens } = asset[1] + return address !== null && !blacklistedAssets.has(address) && numberOfTokens > 0 + }) + .map((asset) => { + return asset[0] + }) + + // need to persist those already active assets, despite its balances + const activeAssets = alreadyActiveAssets.union(activeByBalance) + + // update list of active tokens + dispatch(updateActiveAssets(safeAddress, activeAssets)) + } catch (err) { + console.error('Error fetching active assets list', err) + } + + return null +} + +export default activateAssetsByBalance diff --git a/src/logic/tokens/store/actions/activateTokensByBalance.js b/src/logic/tokens/store/actions/activateTokensByBalance.js index 5db61c81..da377195 100644 --- a/src/logic/tokens/store/actions/activateTokensByBalance.js +++ b/src/logic/tokens/store/actions/activateTokensByBalance.js @@ -44,7 +44,7 @@ const activateTokensByBalance = (safeAddress: string) => async ( ) // active tokens by balance, excluding those already blacklisted and the `null` address - const activeByBalance = addresses.filter(address => address !== null && !blacklistedTokens.includes(address)) + const activeByBalance = addresses.filter((address) => address !== null && !blacklistedTokens.includes(address)) // need to persist those already active tokens, despite its balances const activeTokens = alreadyActiveTokens.toSet().union(activeByBalance) diff --git a/src/logic/tokens/store/actions/fetchTokens.js b/src/logic/tokens/store/actions/fetchTokens.js index be8ad7cf..d1b82e70 100644 --- a/src/logic/tokens/store/actions/fetchTokens.js +++ b/src/logic/tokens/store/actions/fetchTokens.js @@ -10,8 +10,10 @@ import saveTokens from './saveTokens' import { fetchTokenList } from '~/logic/tokens/api' import { type TokenProps, makeToken } from '~/logic/tokens/store/model/token' +import { tokensSelector } from '~/logic/tokens/store/selectors' import { getWeb3 } from '~/logic/wallets/getWeb3' import { type GlobalState } from '~/store' +import { store } from '~/store/index' import { ensureOnce } from '~/utils/singleton' const createStandardTokenContract = async () => { @@ -37,12 +39,67 @@ const createERC721TokenContract = async () => { return erc721Token } +const OnlyBalanceToken = { + contractName: 'OnlyBalanceToken', + abi: [ + { + constant: true, + inputs: [ + { + name: 'owner', + type: 'address', + }, + ], + name: 'balanceOf', + outputs: [ + { + name: '', + type: 'uint256', + }, + ], + payable: false, + stateMutability: 'view', + type: 'function', + }, + { + constant: true, + inputs: [ + { + name: 'owner', + type: 'address', + }, + ], + name: 'balances', + outputs: [ + { + name: '', + type: 'uint256', + }, + ], + payable: false, + stateMutability: 'view', + type: 'function', + }, + ], +} + +// For the `batchRequest` of balances, we're just using the `balanceOf` method call. +// So having a simple ABI only with `balanceOf` prevents errors +// when instantiating non-standard ERC-20 Tokens. +const createOnlyBalanceToken = () => { + const web3 = getWeb3() + const contract = new web3.eth.Contract(OnlyBalanceToken.abi) + return contract +} + export const getHumanFriendlyToken = ensureOnce(createHumanFriendlyTokenContract) export const getStandardTokenContract = ensureOnce(createStandardTokenContract) export const getERC721TokenContract = ensureOnce(createERC721TokenContract) +export const getOnlyBalanceToken = ensureOnce(createOnlyBalanceToken) + export const containsMethodByHash = async (contractAddress: string, methodHash: string) => { const web3 = getWeb3() const byteCode = await web3.eth.getCode(contractAddress) @@ -50,19 +107,54 @@ export const containsMethodByHash = async (contractAddress: string, methodHash: return byteCode.indexOf(methodHash.replace('0x', '')) !== -1 } -export const fetchTokens = () => async (dispatch: ReduxDispatch) => { +export const getTokenInfos = async (tokenAddress: string) => { + if (!tokenAddress) { + return null + } + const { tokens } = store.getState() + const localToken = tokens.get(tokenAddress) + // If the token is inside the store we return the store token + if (localToken) { + return localToken + } + // Otherwise we fetch it, save it to the store and return it + const tokenContract = await getHumanFriendlyToken() + const tokenInstance = await tokenContract.at(tokenAddress) + const [tokenSymbol, tokenDecimals, name] = await Promise.all([ + tokenInstance.symbol(), + tokenInstance.decimals(), + tokenInstance.name(), + ]) + const savedToken = makeToken({ + address: tokenAddress, + name: name ? name : tokenSymbol, + symbol: tokenSymbol, + decimals: tokenDecimals, + logoUri: '', + }) + const newTokens = tokens.set(tokenAddress, savedToken) + store.dispatch(saveTokens(newTokens)) + + return savedToken +} + +export const fetchTokens = () => async (dispatch: ReduxDispatch, getState: Function) => { try { + const currentSavedTokens = tokensSelector(getState()) + const { data: { results: tokenList }, } = await fetchTokenList() + if (currentSavedTokens && currentSavedTokens.size === tokenList.length) { + return + } + const tokens = List(tokenList.map((token: TokenProps) => makeToken(token))) dispatch(saveTokens(tokens)) } catch (err) { console.error('Error fetching token list', err) - - return Promise.resolve() } } diff --git a/src/logic/tokens/store/reducer/tokens.js b/src/logic/tokens/store/reducer/tokens.js index 2454dcc6..3d9d1916 100644 --- a/src/logic/tokens/store/reducer/tokens.js +++ b/src/logic/tokens/store/reducer/tokens.js @@ -16,8 +16,8 @@ export default handleActions( [ADD_TOKENS]: (state: State, action: ActionType): State => { const { tokens } = action.payload - const newState = state.withMutations(map => { - tokens.forEach(token => { + const newState = state.withMutations((map) => { + tokens.forEach((token) => { map.set(token.address, token) }) }) diff --git a/src/logic/tokens/utils/tokenHelpers.js b/src/logic/tokens/utils/tokenHelpers.js index 02883fb9..9b6529c2 100644 --- a/src/logic/tokens/utils/tokenHelpers.js +++ b/src/logic/tokens/utils/tokenHelpers.js @@ -2,6 +2,7 @@ import { List } from 'immutable' import logo from '~/assets/icons/icon_etherTokens.svg' +import { getStandardTokenContract } from '~/logic/tokens/store/actions/fetchTokens' import { type Token, makeToken } from '~/logic/tokens/store/model/token' import { getWeb3 } from '~/logic/wallets/getWeb3' @@ -25,7 +26,7 @@ export const getEthAsToken = (balance: string) => { } export const calculateActiveErc20TokensFrom = (tokens: List) => { - const activeTokens = List().withMutations(list => + const activeTokens = List().withMutations((list) => tokens.forEach((token: Token) => { const isDeactivated = isEther(token.symbol) || !token.status if (isDeactivated) { @@ -65,3 +66,15 @@ export const isMultisendTransaction = (data: string, value: number): boolean => // 7de7edef - changeMasterCopy (550, 8) export const isUpgradeTransaction = (data: string) => !!data && data.substr(308, 8) === 'f08a0323' && data.substr(550, 8) === '7de7edef' + +export const isERC721Contract = async (contractAddress: string): boolean => { + const ERC721Token = await getStandardTokenContract() + let isERC721 = false + try { + isERC721 = true + await ERC721Token.at(contractAddress) + } catch (error) { + console.warn('Asset not found') + } + return isERC721 +} diff --git a/src/logic/tokens/utils/tokensStorage.js b/src/logic/tokens/utils/tokensStorage.js index c1aea74a..bf89f9f1 100644 --- a/src/logic/tokens/utils/tokensStorage.js +++ b/src/logic/tokens/utils/tokensStorage.js @@ -44,7 +44,7 @@ export const removeTokenFromStorage = async (safeAddress: string, token: Token) export const removeFromActiveTokens = async (safeAddress: string, token: Token) => { const activeTokens = await getActiveTokens() - const index = activeTokens.findIndex(activeToken => activeToken.name === token.name) + const index = activeTokens.findIndex((activeToken) => activeToken.name === token.name) if (index !== -1) { await saveActiveTokens(safeAddress, activeTokens.delete(index)) diff --git a/src/logic/wallets/ethAddresses.js b/src/logic/wallets/ethAddresses.js index 7b831c53..a5a0e2e2 100644 --- a/src/logic/wallets/ethAddresses.js +++ b/src/logic/wallets/ethAddresses.js @@ -49,4 +49,4 @@ export const isUserOwner = (safe: Safe, userAccount: string): boolean => { } export const isUserOwnerOnAnySafe = (safes: List, userAccount: string): boolean => - safes.some(safe => isUserOwner(safe, userAccount)) + safes.some((safe) => isUserOwner(safe, userAccount)) diff --git a/src/logic/wallets/getWeb3.js b/src/logic/wallets/getWeb3.js index 8a2aef24..a33ddc03 100644 --- a/src/logic/wallets/getWeb3.js +++ b/src/logic/wallets/getWeb3.js @@ -2,6 +2,9 @@ import ENS from 'ethereum-ens' import Web3 from 'web3' +import { sameAddress } from './ethAddresses' +import { EMPTY_DATA } from './ethTransactions' + import { getNetwork } from '~/config/index' import type { ProviderProps } from '~/logic/wallets/store/model/provider' @@ -27,6 +30,8 @@ export const WALLET_PROVIDER = { OPERA: 'OPERA', DAPPER: 'DAPPER', AUTHEREUM: 'AUTHEREUM', + LEDGER: 'LEDGER', + TREZOR: 'TREZOR', } export const INJECTED_PROVIDERS = [ @@ -88,38 +93,44 @@ export const getAccountFrom: Function = async (web3Provider): Promise 0 ? accounts[0] : null } -const getNetworkIdFrom = async web3Provider => { - const networkId = await web3Provider.eth.net.getId() +export const getNetworkIdFrom = (web3Provider) => web3Provider.eth.net.getId() - return networkId +const isHardwareWallet = (walletName: $Values) => + sameAddress(WALLET_PROVIDER.LEDGER, walletName) || sameAddress(WALLET_PROVIDER.TREZOR, walletName) + +const isSmartContractWallet = async (web3Provider, account) => { + const contractCode: string = await web3Provider.eth.getCode(account) + + return contractCode.replace(EMPTY_DATA, '').replace(/0/g, '') !== '' } export const getProviderInfo: Function = async ( web3Provider, - providerName?: string = 'Wallet', + providerName: string = 'Wallet', ): Promise => { web3 = new Web3(web3Provider) - const name = providerName const account = await getAccountFrom(web3) const network = await getNetworkIdFrom(web3) + const smartContractWallet = await isSmartContractWallet(web3, account) + const hardwareWallet = isHardwareWallet(providerName) const available = account !== null return { - name, + name: providerName, available, loaded: true, account, network, + smartContractWallet, + hardwareWallet, } } export const getAddressFromENS = async (name: string) => { const ens = new ENS(web3) - const address = await ens.resolver(name).addr() - - return address + return await ens.resolver(name).addr() } export const setWeb3 = (provider: Object) => { diff --git a/src/logic/wallets/store/actions/fetchProvider.js b/src/logic/wallets/store/actions/fetchProvider.js index 03ef5042..e9f27cb3 100644 --- a/src/logic/wallets/store/actions/fetchProvider.js +++ b/src/logic/wallets/store/actions/fetchProvider.js @@ -12,15 +12,7 @@ import type { ProviderProps } from '~/logic/wallets/store/model/provider' import { makeProvider } from '~/logic/wallets/store/model/provider' export const processProviderResponse = (dispatch: ReduxDispatch<*>, provider: ProviderProps) => { - const { account, available, loaded, name, network } = provider - - const walletRecord = makeProvider({ - name, - available, - loaded, - account, - network, - }) + const walletRecord = makeProvider(provider) dispatch(addProvider(walletRecord)) } diff --git a/src/logic/wallets/store/model/provider.js b/src/logic/wallets/store/model/provider.js index a62e4082..5750d6a5 100644 --- a/src/logic/wallets/store/model/provider.js +++ b/src/logic/wallets/store/model/provider.js @@ -8,6 +8,8 @@ export type ProviderProps = { available: boolean, account: string, network: number, + smartContractWallet: boolean, + hardwareWallet: boolean, } export const makeProvider: RecordFactory = Record({ @@ -16,6 +18,8 @@ export const makeProvider: RecordFactory = Record({ available: false, account: '', network: 0, + smartContractWallet: false, + hardwareWallet: false, }) export type Provider = RecordOf diff --git a/src/logic/wallets/store/selectors/index.js b/src/logic/wallets/store/selectors/index.js index 49239a77..8db0b068 100644 --- a/src/logic/wallets/store/selectors/index.js +++ b/src/logic/wallets/store/selectors/index.js @@ -5,7 +5,7 @@ import { ETHEREUM_NETWORK, ETHEREUM_NETWORK_IDS } from '~/logic/wallets/getWeb3' import type { Provider } from '~/logic/wallets/store/model/provider' import { PROVIDER_REDUCER_ID } from '~/logic/wallets/store/reducer/provider' -const providerSelector = (state: any): Provider => state[PROVIDER_REDUCER_ID] +export const providerSelector = (state: any): Provider => state[PROVIDER_REDUCER_ID] export const userAccountSelector = createSelector(providerSelector, (provider: Provider) => { const account = provider.get('account') diff --git a/src/logic/wallets/transactionDataCheck.js b/src/logic/wallets/transactionDataCheck.js index 58767c4d..c19df493 100644 --- a/src/logic/wallets/transactionDataCheck.js +++ b/src/logic/wallets/transactionDataCheck.js @@ -1,7 +1,7 @@ // @flow function transactionDataCheck() { let completed = false - return stateAndHelpers => { + return (stateAndHelpers) => { const { wallet } = stateAndHelpers if (wallet && wallet.name === 'Ledger' && !completed) { diff --git a/src/logic/wallets/utils/walletList.js b/src/logic/wallets/utils/walletList.js index 65f088c1..4ef3abeb 100644 --- a/src/logic/wallets/utils/walletList.js +++ b/src/logic/wallets/utils/walletList.js @@ -57,7 +57,7 @@ export const getSupportedWallets = () => { const { isDesktop } = window /* 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) } diff --git a/src/routes/index.js b/src/routes/index.js index d3c8b8fa..46e78d99 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -3,14 +3,7 @@ import React, { useEffect, useState } from 'react' import { connect } from 'react-redux' import { Redirect, Route, Switch, withRouter } from 'react-router-dom' -import { - LOAD_ADDRESS, - OPENING_ADDRESS, - OPEN_ADDRESS, - SAFELIST_ADDRESS, - SAFE_PARAM_ADDRESS, - WELCOME_ADDRESS, -} from './routes' +import { LOAD_ADDRESS, OPEN_ADDRESS, SAFELIST_ADDRESS, SAFE_PARAM_ADDRESS, WELCOME_ADDRESS } from './routes' import Welcome from './welcome/container' import Loader from '~/components/Loader' @@ -21,8 +14,6 @@ const Safe = React.lazy(() => import('./safe/container')) const Open = React.lazy(() => import('./open/container/Open')) -const Opening = React.lazy(() => import('./opening/container')) - const Load = React.lazy(() => import('./load/container/Load')) const SAFE_ADDRESS = `${SAFELIST_ADDRESS}/:${SAFE_PARAM_ADDRESS}` @@ -66,7 +57,6 @@ const Routes = ({ defaultSafe, location }: RoutesProps) => { - @@ -75,6 +65,6 @@ const Routes = ({ defaultSafe, location }: RoutesProps) => { // $FlowFixMe export default connect( - state => ({ defaultSafe: defaultSafeSelector(state) }), + (state) => ({ defaultSafe: defaultSafeSelector(state) }), null, )(withRouter(Routes)) diff --git a/src/routes/load/components/DetailsForm/index.jsx b/src/routes/load/components/DetailsForm/index.jsx index 0ee98409..1d005ca8 100644 --- a/src/routes/load/components/DetailsForm/index.jsx +++ b/src/routes/load/components/DetailsForm/index.jsx @@ -104,7 +104,7 @@ const Details = ({ classes, errors, form }: Props) => ( { + fieldMutator={(val) => { form.mutators.setValue(FIELD_LOAD_ADDRESS, val) }} inputAdornment={ diff --git a/src/routes/load/container/Load.jsx b/src/routes/load/container/Load.jsx index ada68e6e..ba155a49 100644 --- a/src/routes/load/container/Load.jsx +++ b/src/routes/load/container/Load.jsx @@ -50,7 +50,7 @@ class Load extends React.Component { await loadSafe(safeName, safeAddress, owners, addSafe) - const url = `${SAFELIST_ADDRESS}/${safeAddress}/balances/` + const url = `${SAFELIST_ADDRESS}/${safeAddress}/balances` history.push(url) } catch (error) { console.error('Error while loading the Safe', error) diff --git a/src/routes/open/components/ReviewInformation/index.jsx b/src/routes/open/components/ReviewInformation/index.jsx index b0711b0d..13298cec 100644 --- a/src/routes/open/components/ReviewInformation/index.jsx +++ b/src/routes/open/components/ReviewInformation/index.jsx @@ -98,24 +98,20 @@ const ReviewComponent = ({ classes, userAccount, values }: Props) => { const numOwners = getNumOwnersFrom(values) useEffect(() => { - let isCurrent = true const estimateGas = async () => { + 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) - if (isCurrent) { - setGasCosts(formattedGasCosts) - } + setGasCosts(formattedGasCosts) } estimateGas() - - return () => { - isCurrent = false - } - }, []) + }, [addresses, numOwners, userAccount]) return ( <> diff --git a/src/routes/open/components/SafeOwnersConfirmationsForm/index.jsx b/src/routes/open/components/SafeOwnersConfirmationsForm/index.jsx index a6f374aa..f4035f41 100644 --- a/src/routes/open/components/SafeOwnersConfirmationsForm/index.jsx +++ b/src/routes/open/components/SafeOwnersConfirmationsForm/index.jsx @@ -74,7 +74,7 @@ const SafeOwners = (props: Props) => { const [qrModalOpen, setQrModalOpen] = useState(false) const [scanQrForOwnerName, setScanQrForOwnerName] = useState(null) - const openQrModal = ownerName => { + const openQrModal = (ownerName) => { setScanQrForOwnerName(ownerName) setQrModalOpen(true) } @@ -94,7 +94,7 @@ const SafeOwners = (props: Props) => { setNumOwners(numOwners + 1) } - const handleScan = value => { + const handleScan = (value) => { let scannedAddress = value if (scannedAddress.startsWith('ethereum:')) { @@ -144,7 +144,7 @@ const SafeOwners = (props: Props) => { { + fieldMutator={(val) => { form.mutators.setValue(addressName, val) }} inputAdornment={ diff --git a/src/routes/open/components/fields.js b/src/routes/open/components/fields.js index ab5f65ae..679a7853 100644 --- a/src/routes/open/components/fields.js +++ b/src/routes/open/components/fields.js @@ -10,7 +10,7 @@ export const getOwnerAddressBy = (index: number) => `owner${index}Address` export const getNumOwnersFrom = (values: Object) => { const accounts = Object.keys(values) .sort() - .filter(key => /^owner\d+Address$/.test(key) && !!values[key]) + .filter((key) => /^owner\d+Address$/.test(key) && !!values[key]) return accounts.length } diff --git a/src/routes/open/container/Open.jsx b/src/routes/open/container/Open.jsx index 8f4ea5e7..8417a414 100644 --- a/src/routes/open/container/Open.jsx +++ b/src/routes/open/container/Open.jsx @@ -1,16 +1,18 @@ // @flow import queryString from 'query-string' -import * as React from 'react' +import React, { useEffect, useState } from 'react' import { connect } from 'react-redux' import { withRouter } from 'react-router-dom' +import Opening from '../../opening' import Layout from '../components/Layout' -import actions, { type Actions, type AddSafe } from './actions' +import actions, { type Actions } from './actions' import selector from './selector' +import { Loader } from '~/components-v2' import Page from '~/components/layout/Page' -import { deploySafeContract, getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts' +import { getSafeDeploymentTransaction } from '~/logic/contracts/safeContracts' import { checkReceiptStatus } from '~/logic/wallets/ethTransactions' import { getAccountsFrom, @@ -19,9 +21,12 @@ import { getSafeNameFrom, getThresholdFrom, } from '~/routes/open/utils/safeDataExtractor' -import { OPENING_ADDRESS, SAFELIST_ADDRESS, stillInOpeningView } from '~/routes/routes' +import { SAFELIST_ADDRESS, WELCOME_ADDRESS } from '~/routes/routes' import { buildSafe } from '~/routes/safe/store/actions/fetchSafe' import { history } from '~/store' +import { loadFromStorage, removeFromStorage, saveToStorage } from '~/utils/storage' + +const SAFE_PENDING_CREATION_STORAGE_KEY = 'SAFE_PENDING_CREATION_STORAGE_KEY' type Props = Actions & { provider: string, @@ -62,76 +67,155 @@ const validateQueryParams = ( return true } -export const createSafe = async (values: Object, userAccount: string, addSafe: AddSafe): Promise => { - const numConfirmations = getThresholdFrom(values) +export const getSafeProps = async (safeAddress, safeName, ownersNames, ownerAddresses) => { + const safeProps = await buildSafe(safeAddress, safeName) + const owners = getOwnersFrom(ownersNames, ownerAddresses) + safeProps.owners = owners + + return safeProps +} + +export const createSafe = (values: Object, userAccount: string): Promise => { + const confirmations = getThresholdFrom(values) const name = getSafeNameFrom(values) const ownersNames = getNamesFrom(values) const ownerAddresses = getAccountsFrom(values) - const safe = await deploySafeContract(ownerAddresses, numConfirmations, userAccount) - await checkReceiptStatus(safe.tx) + const deploymentTxMethod = getSafeDeploymentTransaction(ownerAddresses, confirmations, userAccount) - const safeAddress = safe.logs[0].args.proxy - const safeContract = await getGnosisSafeInstanceAt(safeAddress) - const safeProps = await buildSafe(safeAddress, name) - const owners = getOwnersFrom(ownersNames, ownerAddresses) - safeProps.owners = owners + const promiEvent = deploymentTxMethod.send({ from: userAccount, value: 0 }) - addSafe(safeProps) - if (stillInOpeningView()) { + promiEvent + .once('transactionHash', (txHash) => { + saveToStorage(SAFE_PENDING_CREATION_STORAGE_KEY, { txHash, ...values }) + }) + .then(async (receipt) => { + await checkReceiptStatus(receipt.transactionHash) + + 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 } + }) + + return promiEvent +} + +const Open = ({ addSafe, network, provider, userAccount }: Props) => { + const [loading, setLoading] = useState(false) + const [showProgress, setShowProgress] = useState() + const [creationTxPromise, setCreationTxPromise] = useState() + const [safeCreationPendingInfo, setSafeCreationPendingInfo] = useState() + const [safePropsFromUrl, setSafePropsFromUrl] = useState() + + useEffect(() => { + // #122: Allow to migrate an old Multisig by passing the parameters to the URL. + const query: SafePropsType = queryString.parse(location.search, { arrayFormat: 'comma' }) + const { name, owneraddresses, ownernames, threshold } = query + if (validateQueryParams(owneraddresses, ownernames, threshold, name)) { + setSafePropsFromUrl({ + name, + ownerAddresses: owneraddresses, + ownerNames: ownernames, + threshold, + }) + } + }) + + // check if there is a safe being created + useEffect(() => { + const load = async () => { + const pendingCreation = await loadFromStorage(SAFE_PENDING_CREATION_STORAGE_KEY) + if (pendingCreation && pendingCreation.txHash) { + setSafeCreationPendingInfo(pendingCreation) + setShowProgress(true) + } else { + setShowProgress(false) + } + setLoading(false) + } + + load() + }, []) + + const createSafeProxy = async (formValues) => { + let values = formValues + + // save form values, used when the user rejects the TX and wants to retry + if (formValues) { + const copy = { ...formValues } + saveToStorage(SAFE_PENDING_CREATION_STORAGE_KEY, copy) + } else { + values = await loadFromStorage(SAFE_PENDING_CREATION_STORAGE_KEY) + } + + const promiEvent = createSafe(values, userAccount, addSafe) + setCreationTxPromise(promiEvent) + setShowProgress(true) + } + + const onSafeCreated = async (safeAddress) => { + const pendingCreation = await loadFromStorage(SAFE_PENDING_CREATION_STORAGE_KEY) + + const name = getSafeNameFrom(pendingCreation) + const ownersNames = getNamesFrom(pendingCreation) + const ownerAddresses = getAccountsFrom(pendingCreation) + const safeProps = await getSafeProps(safeAddress, name, ownersNames, ownerAddresses) + addSafe(safeProps) + + removeFromStorage(SAFE_PENDING_CREATION_STORAGE_KEY) const url = { - pathname: `${SAFELIST_ADDRESS}/${safeContract.address}/balances`, + pathname: `${SAFELIST_ADDRESS}/${safeProps.address}/balances`, state: { name, - tx: safe.tx, + tx: pendingCreation.txHash, }, } history.push(url) } - // returning info for testing purposes, in app is fully async - return { safeAddress: safeContract.address, safeTx: safe } -} - -class Open extends React.Component { - onCallSafeContractSubmit = async values => { - try { - const { addSafe, userAccount } = this.props - createSafe(values, userAccount, addSafe) - history.push(OPENING_ADDRESS) - } catch (error) { - // eslint-disable-next-line - console.error('Error while creating the Safe: ' + error) - } + const onCancel = () => { + removeFromStorage(SAFE_PENDING_CREATION_STORAGE_KEY) + history.push({ + pathname: `${WELCOME_ADDRESS}`, + }) } - render() { - const { location, network, provider, userAccount } = this.props - const query: SafePropsType = queryString.parse(location.search, { arrayFormat: 'comma' }) - const { name, owneraddresses, ownernames, threshold } = query + const onRetry = async () => { + const values = await loadFromStorage(SAFE_PENDING_CREATION_STORAGE_KEY) + delete values.txHash + await saveToStorage(SAFE_PENDING_CREATION_STORAGE_KEY, values) + setSafeCreationPendingInfo(values) + createSafeProxy() + } - let safeProps = null - if (validateQueryParams(owneraddresses, ownernames, threshold, name)) { - safeProps = { - name, - ownerAddresses: owneraddresses, - ownerNames: ownernames, - threshold, - } - } - return ( - + if (loading || showProgress === undefined) { + return + } + + return ( + + {showProgress ? ( + + ) : ( - - ) - } + )} + + ) } export default connect(selector, actions)(withRouter(Open)) diff --git a/src/routes/open/utils/safeDataExtractor.js b/src/routes/open/utils/safeDataExtractor.js index e37d41f4..615206bd 100644 --- a/src/routes/open/utils/safeDataExtractor.js +++ b/src/routes/open/utils/safeDataExtractor.js @@ -6,17 +6,17 @@ import { type Owner, makeOwner } from '~/routes/safe/store/models/owner' export const getAccountsFrom = (values: Object): string[] => { const accounts = Object.keys(values) .sort() - .filter(key => /^owner\d+Address$/.test(key)) + .filter((key) => /^owner\d+Address$/.test(key)) - return accounts.map(account => values[account]).slice(0, values.owners) + return accounts.map((account) => values[account]).slice(0, values.owners) } export const getNamesFrom = (values: Object): string[] => { const accounts = Object.keys(values) .sort() - .filter(key => /^owner\d+Name$/.test(key)) + .filter((key) => /^owner\d+Name$/.test(key)) - return accounts.map(account => values[account]).slice(0, values.owners) + return accounts.map((account) => values[account]).slice(0, values.owners) } export const getOwnersFrom = (names: string[], addresses: string[]): List => { diff --git a/src/routes/opening/assets/success.svg b/src/routes/opening/assets/success.svg new file mode 100644 index 00000000..d635672d --- /dev/null +++ b/src/routes/opening/assets/success.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/routes/opening/assets/vault-error.svg b/src/routes/opening/assets/vault-error.svg new file mode 100644 index 00000000..a25c46b7 --- /dev/null +++ b/src/routes/opening/assets/vault-error.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/routes/opening/component/index.jsx b/src/routes/opening/component/index.jsx deleted file mode 100644 index 395bb481..00000000 --- a/src/routes/opening/component/index.jsx +++ /dev/null @@ -1,79 +0,0 @@ -// @flow -import LinearProgress from '@material-ui/core/LinearProgress' -import { withStyles } from '@material-ui/core/styles' -import OpenInNew from '@material-ui/icons/OpenInNew' -import * as React from 'react' - -import { type SelectorProps } from '../container/selector' - -import Block from '~/components/layout/Block' -import Img from '~/components/layout/Img' -import Page from '~/components/layout/Page' -import Paragraph from '~/components/layout/Paragraph' -import { getEtherScanLink } from '~/logic/wallets/getWeb3' -import { mediumFontSize, secondary, xs } from '~/theme/variables' - -type Props = SelectorProps & { - name: string, - tx: string, - classes: Object, -} - -const vault = require('../assets/vault.svg') - -const styles = { - icon: { - height: mediumFontSize, - color: secondary, - }, - follow: { - display: 'flex', - justifyContent: 'center', - marginTop: xs, - }, - etherscan: { - color: secondary, - textDecoration: 'underline', - display: 'flex', - alignItems: 'center', - marginLeft: xs, - }, -} - -const Opening = ({ classes, name = 'Safe creation process', tx }: Props) => ( - - - {name} - - - Vault - - - - - - - Transaction submitted - - - Deploying your new Safe... - - - - - This process should take a couple of minutes.
-
- {tx && ( - - Follow progress on{' '} - - Etherscan.io - - - - )} -
-
-) - -export default withStyles(styles)(Opening) diff --git a/src/routes/opening/container/index.jsx b/src/routes/opening/container/index.jsx index b52906f2..a8c1673a 100644 --- a/src/routes/opening/container/index.jsx +++ b/src/routes/opening/container/index.jsx @@ -1,8 +1,8 @@ // @flow import { connect } from 'react-redux' -import Layout from '../component' - import selector from './selector' -export default connect(selector)(Layout) +import Opening from './index' + +export default connect(selector)(Opening) diff --git a/src/routes/opening/index.jsx b/src/routes/opening/index.jsx new file mode 100644 index 00000000..791ade76 --- /dev/null +++ b/src/routes/opening/index.jsx @@ -0,0 +1,394 @@ +// @flow +import React, { useEffect, useState } from 'react' +import styled from 'styled-components' + +import { Loader, Stepper } from '~/components-v2' +import LoaderDots from '~/components-v2/feedback/Loader-dots/assets/loader-dots.svg' +import Button from '~/components/layout/Button' +import Heading from '~/components/layout/Heading' +import Img from '~/components/layout/Img' +import Paragraph from '~/components/layout/Paragraph' +import { initContracts } from '~/logic/contracts/safeContracts' +import { EMPTY_DATA } from '~/logic/wallets/ethTransactions' +import { getEtherScanLink, getWeb3 } from '~/logic/wallets/getWeb3' +import { background, connected } from '~/theme/variables' + +const successSvg = require('./assets/success.svg') +const vaultErrorSvg = require('./assets/vault-error.svg') +const vaultSvg = require('./assets/vault.svg') + +const Wrapper = styled.div` + display: grid; + grid-template-columns: 250px auto; + grid-template-rows: 62px auto; + margin-bottom: 30px; +` + +const Title = styled(Heading)` + grid-column: 1/3; + grid-row: 1; +` + +const Nav = styled.div` + grid-column: 1; + grid-row: 2; +` + +const Body = styled.div` + grid-column: 2; + grid-row: 2; + text-align: center; + background-color: #ffffff; + border-radius: 5px; + min-width: 700px; + padding-top: 50px; + box-shadow: 0 0 10px 0 rgba(33, 48, 77, 0.1); + + display: grid; + grid-template-rows: 100px 50px 70px 60px 100px; +` +const EtherScanLink = styled.a` + color: ${connected}; +` + +const CardTitle = styled.div` + font-size: 20px; +` +const FullParagraph = styled(Paragraph)` + background-color: ${background}; + padding: 24px; + font-size: 16px; + margin-bottom: 16px; +` +const ButtonMargin = styled(Button)` + margin-right: 16px; +` + +const BodyImage = styled.div` + grid-row: 1; +` +const BodyDescription = styled.div` + grid-row: 2; +` +const BodyLoader = styled.div` + grid-row: 3; + display: flex; + justify-content: center; + align-items: center; +` +const BodyInstruction = styled.div` + grid-row: 4; +` +const BodyFooter = styled.div` + grid-row: 5; + + padding: 10px 0; + display: flex; + justify-content: center; + align-items: flex-end; +` + +type Props = { + provider: string, + creationTxHash: Promise, + submittedPromise: Promise, + onRetry: () => void, + onSuccess: () => void, + onCancel: () => void, +} + +const SafeDeployment = ({ creationTxHash, onCancel, onRetry, onSuccess, provider, submittedPromise }: Props) => { + const [loading, setLoading] = useState(true) + const [stepIndex, setStepIndex] = useState() + const [safeCreationTxHash, setSafeCreationTxHash] = useState() + const [createdSafeAddress, setCreatedSafeAddress] = useState() + + const [error, setError] = useState(false) + const [intervalStarted, setIntervalStarted] = useState(false) + const [waitingSafeDeployed, setWaitingSafeDeployed] = useState(false) + const [continueButtonDisabled, setContinueButtonDisabled] = useState(false) + + const genericFooter = ( + +

This process should take a couple of minutes.

+

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

+
+ ) + + const navigateToSafe = () => { + setContinueButtonDisabled(true) + onSuccess(createdSafeAddress) + } + + const steps = [ + { + id: '1', + label: 'Waiting for transaction confirmation', + description: undefined, + instruction: 'Please confirm the Safe creation in your wallet', + footer: null, + }, + { + id: '2', + label: 'Transaction submitted', + description: undefined, + instruction: 'Please do not leave the page', + footer: genericFooter, + }, + { + id: '3', + label: 'Validating transaction', + description: undefined, + instruction: 'Please do not leave the page', + footer: genericFooter, + }, + { + id: '4', + label: 'Deploying smart contract', + description: undefined, + instruction: 'Please do not leave the page', + footer: genericFooter, + }, + { + id: '5', + label: 'Generating your Safe', + description: undefined, + instruction: 'Please do not leave the page', + footer: genericFooter, + }, + { + id: '6', + label: 'Success', + description: 'Your Safe was created successfully', + instruction: 'Click below to get started', + footer: ( + + ), + }, + ] + + const onError = (error) => { + setIntervalStarted(false) + setWaitingSafeDeployed(false) + setContinueButtonDisabled(false) + setError(true) + console.error(error) + } + + // discard click event value + const onRetryTx = () => { + setStepIndex(0) + setError(false) + onRetry() + } + + const getImage = () => { + if (error) { + return vaultErrorSvg + } + + if (stepIndex <= 4) { + return vaultSvg + } + + return successSvg + } + + useEffect(() => { + const loadContracts = async () => { + await initContracts() + setLoading(false) + } + + if (provider) { + loadContracts() + } + }, [provider]) + + // creating safe from from submission + useEffect(() => { + if (submittedPromise === undefined) { + return + } + + setStepIndex(0) + submittedPromise + .once('transactionHash', (txHash) => { + setSafeCreationTxHash(txHash) + setStepIndex(1) + setIntervalStarted(true) + }) + .on('error', onError) + }, [submittedPromise]) + + // recovering safe creation from txHash + useEffect(() => { + if (creationTxHash === undefined) { + return + } + setSafeCreationTxHash(creationTxHash) + setStepIndex(1) + setIntervalStarted(true) + }, [creationTxHash]) + + useEffect(() => { + if (!intervalStarted) { + return + } + + const isTxMined = async (txHash) => { + const web3 = getWeb3() + + const receipt = await web3.eth.getTransactionReceipt(txHash) + if (!receipt.status) { + throw Error('TX status reverted') + } + const txResult = await web3.eth.getTransaction(txHash) + return txResult.blockNumber !== null + } + + let interval = setInterval(async () => { + if (stepIndex < 4) { + setStepIndex(stepIndex + 1) + } + + // safe created using the form + if (submittedPromise !== undefined) { + submittedPromise.then(() => { + setStepIndex(4) + setWaitingSafeDeployed(true) + setIntervalStarted(false) + }) + } + + // safe pending creation recovered from storage + if (creationTxHash !== undefined) { + try { + const res = await isTxMined(creationTxHash) + if (res) { + setStepIndex(4) + setWaitingSafeDeployed(true) + setIntervalStarted(false) + } + } catch (error) { + onError(error) + } + } + }, 3000) + + return () => { + clearInterval(interval) + } + }, [creationTxHash, submittedPromise, intervalStarted, stepIndex, error]) + + useEffect(() => { + let interval + + const awaitUntilSafeIsDeployed = async () => { + try { + const web3 = getWeb3() + const receipt = await web3.eth.getTransactionReceipt(safeCreationTxHash) + + let safeAddress + + if (receipt.events) { + safeAddress = receipt.events.ProxyCreation.returnValues.proxy + } else { + // get the address for the just created safe + const events = web3.eth.abi.decodeLog( + [ + { + type: 'address', + name: 'ProxyCreation', + }, + ], + receipt.logs[0].data, + receipt.logs[0].topics, + ) + safeAddress = events[0] + } + + setCreatedSafeAddress(safeAddress) + + interval = setInterval(async () => { + const code = await web3.eth.getCode(safeAddress) + if (code !== EMPTY_DATA) { + setStepIndex(5) + } + }, 1000) + } catch (error) { + onError(error) + } + } + + if (!waitingSafeDeployed) { + return + } + + awaitUntilSafeIsDeployed() + + return () => { + clearInterval(interval) + } + }, [waitingSafeDeployed]) + + if (loading || stepIndex === undefined) { + return + } + + return ( + + Safe creation process + + + + Vault + + + + {steps[stepIndex].description || steps[stepIndex].label} + + + {!error && stepIndex <= 4 && LoaderDots} + + + + {error ? 'You can Cancel or Retry the Safe creation process.' : steps[stepIndex].instruction} + + + + + {error ? ( + <> + + Cancel + + + + ) : ( + steps[stepIndex].footer + )} + + + + ) +} + +export default SafeDeployment diff --git a/src/routes/routes.js b/src/routes/routes.js index df991cb3..a1e6cfcb 100644 --- a/src/routes/routes.js +++ b/src/routes/routes.js @@ -1,14 +1,6 @@ // @flow -import { history } from '~/store' - export const SAFE_PARAM_ADDRESS = 'address' export const SAFELIST_ADDRESS = '/safes' export const OPEN_ADDRESS = '/open' export const LOAD_ADDRESS = '/load' export const WELCOME_ADDRESS = '/welcome' -export const OPENING_ADDRESS = '/opening' - -export const stillInOpeningView = () => { - const path = history.location.pathname - return path === OPENING_ADDRESS -} diff --git a/src/routes/safe/components/AddressBook/CreateEditEntryModal/index.jsx b/src/routes/safe/components/AddressBook/CreateEditEntryModal/index.jsx index 05026e09..d43bf19f 100644 --- a/src/routes/safe/components/AddressBook/CreateEditEntryModal/index.jsx +++ b/src/routes/safe/components/AddressBook/CreateEditEntryModal/index.jsx @@ -43,7 +43,7 @@ const CreateEditEntryModalComponent = ({ newEntryModalHandler, onClose, }: Props) => { - const onFormSubmitted = values => { + const onFormSubmitted = (values) => { if (entryToEdit && !entryToEdit.entry.isNew) { editEntryModalHandler(values) } else { diff --git a/src/routes/safe/components/AddressBook/DeleteEntryModal/index.jsx b/src/routes/safe/components/AddressBook/DeleteEntryModal/index.jsx index ea1d4eaf..c99e65cd 100644 --- a/src/routes/safe/components/AddressBook/DeleteEntryModal/index.jsx +++ b/src/routes/safe/components/AddressBook/DeleteEntryModal/index.jsx @@ -26,7 +26,7 @@ type Props = { } const DeleteEntryModalComponent = ({ classes, deleteEntryModalHandler, entryToDelete, isOpen, onClose }: Props) => { - const handleDeleteEntrySubmit = values => { + const handleDeleteEntrySubmit = (values) => { deleteEntryModalHandler(values, entryToDelete.index) } diff --git a/src/routes/safe/components/AddressBook/EllipsisTransactionDetails/index.jsx b/src/routes/safe/components/AddressBook/EllipsisTransactionDetails/index.jsx index 7a928d73..62cf8ff8 100644 --- a/src/routes/safe/components/AddressBook/EllipsisTransactionDetails/index.jsx +++ b/src/routes/safe/components/AddressBook/EllipsisTransactionDetails/index.jsx @@ -43,7 +43,7 @@ const EllipsisTransactionDetails = ({ address, knownAddress }: EllipsisTransacti const dispatch = useDispatch() const currentSafeAddress = useSelector(safeParamAddressFromStateSelector) - const handleClick = event => { + const handleClick = (event) => { setAnchorEl(event.currentTarget) } diff --git a/src/routes/safe/components/AddressBook/index.jsx b/src/routes/safe/components/AddressBook/index.jsx index d3176882..10ebc8f7 100644 --- a/src/routes/safe/components/AddressBook/index.jsx +++ b/src/routes/safe/components/AddressBook/index.jsx @@ -21,6 +21,7 @@ import Col from '~/components/layout/Col' import Img from '~/components/layout/Img' import Row from '~/components/layout/Row' import type { AddressBookEntry } from '~/logic/addressBook/model/addressBook' +import { makeAddressBookEntry } from '~/logic/addressBook/model/addressBook' import { addAddressBookEntry } from '~/logic/addressBook/store/actions/addAddressBookEntry' import { removeAddressBookEntry } from '~/logic/addressBook/store/actions/removeAddressBookEntry' import { updateAddressBookEntry } from '~/logic/addressBook/store/actions/updateAddressBookEntry' @@ -50,7 +51,7 @@ type Props = { const AddressBookTable = ({ classes }: Props) => { const columns = generateColumns() - const autoColumns = columns.filter(c => !c.custom) + const autoColumns = columns.filter((c) => !c.custom) const dispatch = useDispatch() const addressBook = useSelector(getAddressBookListSelector) const [selectedEntry, setSelectedEntry] = useState(null) @@ -67,7 +68,7 @@ const AddressBookTable = ({ classes }: Props) => { useEffect(() => { if (entryAddressToEditOrCreateNew) { - const key = addressBook.findKey(entry => entry.address === entryAddressToEditOrCreateNew) + const key = addressBook.findKey((entry) => entry.address === entryAddressToEditOrCreateNew) if (key >= 0) { // Edit old entry const value = addressBook.get(key) @@ -89,13 +90,13 @@ const AddressBookTable = ({ classes }: Props) => { const newEntryModalHandler = (entry: AddressBookEntry) => { setEditCreateEntryModalOpen(false) - dispatch(addAddressBookEntry(entry)) + dispatch(addAddressBookEntry(makeAddressBookEntry(entry))) } const editEntryModalHandler = (entry: AddressBookEntry) => { setSelectedEntry(null) setEditCreateEntryModalOpen(false) - dispatch(updateAddressBookEntry(entry)) + dispatch(updateAddressBookEntry(makeAddressBookEntry(entry))) } const deleteEntryModalHandler = () => { diff --git a/src/routes/safe/components/Apps/appsList.js b/src/routes/safe/components/Apps/appsList.js index b69b9ccc..0278c4f8 100644 --- a/src/routes/safe/components/Apps/appsList.js +++ b/src/routes/safe/components/Apps/appsList.js @@ -48,7 +48,7 @@ const appList = [ export default appList export const getAppInfo = (appId: string) => { - const res = appList.find(app => app.id === appId.toString()) + const res = appList.find((app) => app.id === appId.toString()) if (!res) { return { id: 0, diff --git a/src/routes/safe/components/Apps/index.jsx b/src/routes/safe/components/Apps/index.jsx index fc64d228..4960f462 100644 --- a/src/routes/safe/components/Apps/index.jsx +++ b/src/routes/safe/components/Apps/index.jsx @@ -13,7 +13,7 @@ import ButtonLink from '~/components/layout/ButtonLink' const StyledIframe = styled.iframe` width: 100%; height: 100%; - display: ${props => (props.shouldDisplay ? 'block' : 'none')}; + display: ${(props) => (props.shouldDisplay ? 'block' : 'none')}; ` const operations = { SEND_TRANSACTIONS: 'sendTransactions', @@ -51,13 +51,13 @@ function Apps({ const [appIsLoading, setAppIsLoading] = useState(true) const [iframeEl, setframeEl] = useState(null) - const getSelectedApp = () => appsList.find(e => e.id === selectedApp) + const getSelectedApp = () => appsList.find((e) => e.id === selectedApp) const sendMessageToIframe = (messageId, data) => { iframeEl.contentWindow.postMessage({ messageId, data }, getSelectedApp().url) } - const handleIframeMessage = async data => { + const handleIframeMessage = async (data) => { if (!data || !data.messageId) { console.warn('iframe: message without messageId') return @@ -109,7 +109,7 @@ function Apps({ } } - const iframeRef = useCallback(node => { + const iframeRef = useCallback((node) => { if (node !== null) { setframeEl(node) } @@ -156,7 +156,7 @@ function Apps({ } }, [iframeEl]) - const onSelectApp = appId => { + const onSelectApp = (appId) => { setAppIsLoading(true) setSelectedApp(appId) } diff --git a/src/routes/safe/components/Apps/sendTransactions.js b/src/routes/safe/components/Apps/sendTransactions.js index ac602fcc..18d2e000 100644 --- a/src/routes/safe/components/Apps/sendTransactions.js +++ b/src/routes/safe/components/Apps/sendTransactions.js @@ -28,7 +28,7 @@ const sendTransactions = ( const encodeMultiSendCalldata = multiSend.methods .multiSend( `0x${txs - .map(tx => + .map((tx) => [ web3.eth.abi.encodeParameter('uint8', 0).slice(-2), web3.eth.abi.encodeParameter('address', tx.to).slice(-40), diff --git a/src/routes/safe/components/Balances/Coins/index.jsx b/src/routes/safe/components/Balances/Coins/index.jsx new file mode 100644 index 00000000..5f2c20eb --- /dev/null +++ b/src/routes/safe/components/Balances/Coins/index.jsx @@ -0,0 +1,129 @@ +// @flow +import TableCell from '@material-ui/core/TableCell' +import TableContainer from '@material-ui/core/TableContainer' +import TableRow from '@material-ui/core/TableRow' +import { makeStyles } from '@material-ui/core/styles' +import CallMade from '@material-ui/icons/CallMade' +import CallReceived from '@material-ui/icons/CallReceived' +import classNames from 'classnames/bind' +import React from 'react' +import { useSelector } from 'react-redux' + +import { styles } from './styles' + +import Table from '~/components/Table' +import type { Column } from '~/components/Table/TableHead' +import { cellWidth } from '~/components/Table/TableHead' +import Button from '~/components/layout/Button' +import Row from '~/components/layout/Row' +import { currencyValuesListSelector, currentCurrencySelector } from '~/logic/currencyValues/store/selectors' +import { BALANCE_ROW_TEST_ID } from '~/routes/safe/components/Balances' +import AssetTableCell from '~/routes/safe/components/Balances/AssetTableCell' +import type { BalanceRow } from '~/routes/safe/components/Balances/dataFetcher' +import { + BALANCE_TABLE_ASSET_ID, + BALANCE_TABLE_BALANCE_ID, + BALANCE_TABLE_VALUE_ID, + generateColumns, + getBalanceData, +} from '~/routes/safe/components/Balances/dataFetcher' +import { extendedSafeTokensSelector, grantedSelector } from '~/routes/safe/container/selector' + +const useStyles = makeStyles(styles) + +type Props = { + showSendFunds: Function, + showReceiveFunds: Function, +} + +const Coins = (props: Props) => { + const { showReceiveFunds, showSendFunds } = props + const classes = useStyles() + const columns = generateColumns() + const autoColumns = columns.filter((c) => !c.custom) + const currencySelected = useSelector(currentCurrencySelector) + const activeTokens = useSelector(extendedSafeTokensSelector) + const currencyValues = useSelector(currencyValuesListSelector) + const granted = useSelector(grantedSelector) + const filteredData = getBalanceData(activeTokens, currencySelected, currencyValues) + + return ( + + + {(sortedData: Array) => + sortedData.map((row: any, index: number) => ( + + {autoColumns.map((column: Column) => { + const { align, id, width } = column + let cellItem + switch (id) { + case BALANCE_TABLE_ASSET_ID: { + cellItem = + break + } + case BALANCE_TABLE_BALANCE_ID: { + cellItem =
{row[id]}
+ break + } + case BALANCE_TABLE_VALUE_ID: { + cellItem =
{row[id]}
+ break + } + default: { + cellItem = null + break + } + } + return ( + + {cellItem} + + ) + })} + + + {granted && ( + + )} + + + +
+ )) + } +
+
+ ) +} + +export default Coins diff --git a/src/routes/safe/components/Balances/Coins/styles.js b/src/routes/safe/components/Balances/Coins/styles.js new file mode 100644 index 00000000..aaa5ea0b --- /dev/null +++ b/src/routes/safe/components/Balances/Coins/styles.js @@ -0,0 +1,47 @@ +// @flow +import { sm, xs } from '~/theme/variables' + +export const styles = () => ({ + iconSmall: { + fontSize: 16, + }, + hide: { + '&:hover': { + backgroundColor: '#fff3e2', + }, + '&:hover $actions': { + visibility: 'initial', + }, + '&:focus $actions': { + visibility: 'initial', + }, + }, + actions: { + justifyContent: 'flex-end', + visibility: 'hidden', + }, + receive: { + width: '95px', + minWidth: '95px', + marginLeft: sm, + borderRadius: xs, + '& > span': { + fontSize: '14px', + }, + }, + send: { + width: '75px', + minWidth: '75px', + borderRadius: xs, + '& > span': { + fontSize: '14px', + }, + }, + leftIcon: { + marginRight: sm, + }, + currencyValueRow: { + maxWidth: '125px', + textAlign: 'right', + }, +}) diff --git a/src/routes/safe/components/Balances/Collectibles/components/Item.jsx b/src/routes/safe/components/Balances/Collectibles/components/Item.jsx index 6726b074..a9add3c3 100644 --- a/src/routes/safe/components/Balances/Collectibles/components/Item.jsx +++ b/src/routes/safe/components/Balances/Collectibles/components/Item.jsx @@ -16,7 +16,7 @@ const useStyles = makeStyles({ borderRadius: '8px', boxShadow: '0 0 10px 0 rgba(33, 48, 77, 0.10)', boxSizing: 'border-box', - cursor: props => (props.granted ? 'pointer' : 'default'), + cursor: (props) => (props.granted ? 'pointer' : 'default'), display: 'flex', flexDirection: 'column', flexGrow: '1', @@ -54,7 +54,7 @@ const useStyles = makeStyles({ zIndex: '5', }, image: { - backgroundColor: props => `#${props.backgroundColor}` || '#f0efee', + backgroundColor: (props) => `#${props.backgroundColor}` || '#f0efee', backgroundPosition: '50% 50%', backgroundRepeat: 'no-repeat', backgroundSize: 'contain', diff --git a/src/routes/safe/components/Balances/Collectibles/index.jsx b/src/routes/safe/components/Balances/Collectibles/index.jsx index 0bb8e3af..641e1041 100644 --- a/src/routes/safe/components/Balances/Collectibles/index.jsx +++ b/src/routes/safe/components/Balances/Collectibles/index.jsx @@ -7,9 +7,10 @@ import { useSelector } from 'react-redux' import Item from './components/Item' import Paragraph from '~/components/layout/Paragraph' -import type { NFTAssetsState, NFTTokensState } from '~/logic/collectibles/store/reducer/collectibles' -import { nftAssetsSelector, nftTokensSelector } from '~/logic/collectibles/store/selectors' +import type { NFTTokensState } from '~/logic/collectibles/store/reducer/collectibles' +import { activeNftAssetsListSelector, nftTokensSelector } from '~/logic/collectibles/store/selectors' import SendModal from '~/routes/safe/components/Balances/SendModal' +import { safeSelector } from '~/routes/safe/store/selectors' import { fontColor, lg, screenSm, screenXs } from '~/theme/variables' const useStyles = makeStyles({ @@ -79,11 +80,11 @@ const Collectibles = () => { const classes = useStyles() const [selectedToken, setSelectedToken] = React.useState({}) const [sendNFTsModalOpen, setSendNFTsModalOpen] = React.useState(false) - const nftAssets: NFTAssetsState = useSelector(nftAssetsSelector) + const { address, ethBalance, name } = useSelector(safeSelector) const nftTokens: NFTTokensState = useSelector(nftTokensSelector) - const nftAssetsKeys = Object.keys(nftAssets) + const activeAssetsList = useSelector(activeNftAssetsListSelector) - const handleItemSend = nftToken => { + const handleItemSend = (nftToken) => { setSelectedToken(nftToken) setSendNFTsModalOpen(true) } @@ -91,10 +92,8 @@ const Collectibles = () => { return (
- {nftAssetsKeys.length ? ( - nftAssetsKeys.map(assetAddress => { - const nftAsset = nftAssets[assetAddress] - + {activeAssetsList.size ? ( + activeAssetsList.map((nftAsset) => { return (
@@ -105,7 +104,7 @@ const Collectibles = () => {
{nftTokens .filter(({ assetAddress }) => nftAsset.address === assetAddress) - .map(nftToken => ( + .map((nftToken) => ( {
setSendNFTsModalOpen(false)} + safeAddress={address} + safeName={name} selectedToken={selectedToken} /> diff --git a/src/routes/safe/components/Balances/SendModal/index.jsx b/src/routes/safe/components/Balances/SendModal/index.jsx index 5bf4d6d0..a865518b 100644 --- a/src/routes/safe/components/Balances/SendModal/index.jsx +++ b/src/routes/safe/components/Balances/SendModal/index.jsx @@ -77,17 +77,17 @@ const SendModal = ({ activeScreenType, isOpen, onClose, recipientAddress, select const scalableModalSize = activeScreen === 'chooseTxType' - const handleTxCreation = txInfo => { + const handleTxCreation = (txInfo) => { setActiveScreen('reviewTx') setTx(txInfo) } - const handleCustomTxCreation = customTxInfo => { + const handleCustomTxCreation = (customTxInfo) => { setActiveScreen('reviewCustomTx') setTx(customTxInfo) } - const handleSendCollectible = txInfo => { + const handleSendCollectible = (txInfo) => { setActiveScreen('reviewCollectible') setTx(txInfo) } diff --git a/src/routes/safe/components/Balances/SendModal/screens/AddressBookInput/index.jsx b/src/routes/safe/components/Balances/SendModal/screens/AddressBookInput/index.jsx index b79b5ba3..fd2fc303 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/AddressBookInput/index.jsx +++ b/src/routes/safe/components/Balances/SendModal/screens/AddressBookInput/index.jsx @@ -40,7 +40,7 @@ const textFieldInputStyle = makeStyles(() => ({ }, })) -const filterAddressBookWithContractAddresses = async addressBook => { +const filterAddressBookWithContractAddresses = async (addressBook) => { const abFlags = await Promise.all( addressBook.map(async ({ address }) => { return (await mustBeEthereumContractAddress(address)) === undefined @@ -49,7 +49,7 @@ const filterAddressBookWithContractAddresses = async addressBook => { return addressBook.filter((adbkEntry, index) => abFlags[index]) } -const isValidEnsName = name => /^([\w-]+\.)+(eth|test|xyz|luxe)$/.test(name) +const isValidEnsName = (name) => /^([\w-]+\.)+(eth|test|xyz|luxe)$/.test(name) const AddressBookInput = ({ classes, @@ -69,7 +69,7 @@ const AddressBookInput = ({ const [inputAddValue, setInputAddValue] = useState(recipientAddress) - const onAddressInputChanged = async addressValue => { + const onAddressInputChanged = async (addressValue) => { setInputAddValue(addressValue) let resolvedAddress = addressValue let isValidText @@ -92,7 +92,7 @@ const AddressBookInput = ({ // First removes the entries that are not contracts if the operation is custom tx const adbkToFilter = isCustomTx ? await filterAddressBookWithContractAddresses(addressBook) : addressBook // Then Filters the entries based on the input of the user - const filteredADBK = adbkToFilter.filter(adbkEntry => { + const filteredADBK = adbkToFilter.filter((adbkEntry) => { const { address, name } = adbkEntry return ( name.toLowerCase().includes(addressValue.toLowerCase()) || @@ -137,7 +137,7 @@ const AddressBookInput = ({ closeIcon={null} disableOpenOnFocus filterOptions={(optionsArray, { inputValue }) => - optionsArray.filter(item => { + optionsArray.filter((item) => { const inputLowerCase = inputValue.toLowerCase() const foundName = item.name.toLowerCase().includes(inputLowerCase) const foundAddress = item.address.toLowerCase().includes(inputLowerCase) @@ -145,7 +145,7 @@ const AddressBookInput = ({ }) } freeSolo - getOptionLabel={adbkEntry => adbkEntry.address || ''} + getOptionLabel={(adbkEntry) => adbkEntry.address || ''} id="free-solo-demo" onChange={(event, value) => { let address = '' @@ -164,7 +164,7 @@ const AddressBookInput = ({ }} open={!blurred} options={adbkList.toArray()} - renderInput={params => ( + renderInput={(params) => ( { + onChange={(event) => { setInputTouched(true) onAddressInputChanged(event.target.value) }} @@ -193,7 +193,7 @@ const AddressBookInput = ({ variant="filled" /> )} - renderOption={adbkEntry => { + renderOption={(adbkEntry) => { const { address, name } = adbkEntry return (
diff --git a/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.jsx b/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.jsx index d9bc143b..5e837447 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.jsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.jsx @@ -53,7 +53,7 @@ const ReviewTx = ({ closeSnackbar, enqueueSnackbar, onClose, onPrev, tx }: Props const [gasCosts, setGasCosts] = useState('< 0.001') const [data, setData] = useState('') - const txToken = tokens.find(token => token.address === tx.token) + const txToken = tokens.find((token) => token.address === tx.token) const isSendingETH = txToken.address === ETH_ADDRESS const txRecipient = isSendingETH ? tx.recipientAddress : txToken.address diff --git a/src/routes/safe/components/Balances/SendModal/screens/SendCollectible/CollectibleSelectField/index.jsx b/src/routes/safe/components/Balances/SendModal/screens/SendCollectible/CollectibleSelectField/index.jsx index 27193eba..6e303952 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/SendCollectible/CollectibleSelectField/index.jsx +++ b/src/routes/safe/components/Balances/SendModal/screens/SendCollectible/CollectibleSelectField/index.jsx @@ -67,10 +67,10 @@ const CollectibleSelectField = ({ initialValue, tokens }: SelectFieldProps) => { disabled={!tokens.length} initialValue={initialValue} name="nftTokenId" - renderValue={nftTokenId => } + renderValue={(nftTokenId) => } validate={required} > - {tokens.map(token => ( + {tokens.map((token) => ( {token.name} diff --git a/src/routes/safe/components/Balances/SendModal/screens/SendCollectible/TokenSelectField/index.jsx b/src/routes/safe/components/Balances/SendModal/screens/SendCollectible/TokenSelectField/index.jsx index 33ad3a2a..735c2d0f 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/SendCollectible/TokenSelectField/index.jsx +++ b/src/routes/safe/components/Balances/SendModal/screens/SendCollectible/TokenSelectField/index.jsx @@ -69,10 +69,10 @@ const TokenSelectField = ({ assets, initialValue }: SelectFieldProps) => { disabled={!assetsAddresses.length} initialValue={initialValue} name="assetAddress" - renderValue={assetAddress => } + renderValue={(assetAddress) => } validate={required} > - {assetsAddresses.map(assetAddress => { + {assetsAddresses.map((assetAddress) => { const asset = assets[assetAddress] return ( diff --git a/src/routes/safe/components/Balances/SendModal/screens/SendCollectible/index.jsx b/src/routes/safe/components/Balances/SendModal/screens/SendCollectible/index.jsx index 2024fc63..80b07e40 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/SendCollectible/index.jsx +++ b/src/routes/safe/components/Balances/SendModal/screens/SendCollectible/index.jsx @@ -24,7 +24,7 @@ import Img from '~/components/layout/Img' import Paragraph from '~/components/layout/Paragraph' import Row from '~/components/layout/Row' import type { NFTAssetsState, NFTTokensState } from '~/logic/collectibles/store/reducer/collectibles' -import { nftAssetsSelector, nftTokensSelector } from '~/logic/collectibles/store/selectors' +import { nftTokensSelector, safeActiveSelectorMap } from '~/logic/collectibles/store/selectors' import type { NFTToken } from '~/routes/safe/components/Balances/Collectibles/types' import SafeInfo from '~/routes/safe/components/Balances/SendModal/SafeInfo' import AddressBookInput from '~/routes/safe/components/Balances/SendModal/screens/AddressBookInput' @@ -36,7 +36,7 @@ import { sm } from '~/theme/variables' type Props = { initialValues: Object, onClose: () => void, - onNext: any => void, + onNext: (any) => void, recipientAddress?: string, selectedToken?: NFTToken | {}, } @@ -58,7 +58,7 @@ const useStyles = makeStyles(styles) const SendCollectible = ({ initialValues, onClose, onNext, recipientAddress, selectedToken = {} }: Props) => { const classes = useStyles() const { address: safeAddress, ethBalance, name: safeName } = useSelector(safeSelector) - const nftAssets: NFTAssetsState = useSelector(nftAssetsSelector) + const nftAssets: NFTAssetsState = useSelector(safeActiveSelectorMap) const nftTokens: NFTTokensState = useSelector(nftTokensSelector) const [qrModalOpen, setQrModalOpen] = useState(false) const [selectedEntry, setSelectedEntry] = useState({ @@ -74,7 +74,7 @@ const SendCollectible = ({ initialValues, onClose, onNext, recipientAddress, sel } }, [selectedEntry, pristine]) - const handleSubmit = values => { + const handleSubmit = (values) => { // If the input wasn't modified, there was no mutation of the recipientAddress if (!values.recipientAddress) { values.recipientAddress = selectedEntry.address @@ -110,9 +110,9 @@ const SendCollectible = ({ initialValues, onClose, onNext, recipientAddress, sel const formState = args[2] const mutators = args[3] const { assetAddress } = formState.values - const selectedNFTTokens = nftTokens.filter(nftToken => nftToken.assetAddress === assetAddress) + const selectedNFTTokens = nftTokens.filter((nftToken) => nftToken.assetAddress === assetAddress) - const handleScan = value => { + const handleScan = (value) => { let scannedAddress = value if (scannedAddress.startsWith('ethereum:')) { @@ -144,7 +144,7 @@ const SendCollectible = ({ initialValues, onClose, onNext, recipientAddress, sel {selectedEntry && selectedEntry.address ? (
{ + onKeyDown={(e) => { if (e.keyCode !== 9) { setSelectedEntry(null) } diff --git a/src/routes/safe/components/Balances/SendModal/screens/SendCustomTx/index.jsx b/src/routes/safe/components/Balances/SendModal/screens/SendCustomTx/index.jsx index 90e40b1e..2039cfc3 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/SendCustomTx/index.jsx +++ b/src/routes/safe/components/Balances/SendModal/screens/SendCustomTx/index.jsx @@ -36,7 +36,7 @@ import { sm } from '~/theme/variables' type Props = { initialValues: Object, onClose: () => void, - onNext: any => void, + onNext: (any) => void, recipientAddress: string, } @@ -103,7 +103,7 @@ const SendCustomTx = ({ initialValues, onClose, onNext, recipientAddress }: Prop shouldDisableSubmitButton = !selectedEntry.address } - const handleScan = value => { + const handleScan = (value) => { let scannedAddress = value if (scannedAddress.startsWith('ethereum:')) { @@ -128,7 +128,7 @@ const SendCustomTx = ({ initialValues, onClose, onNext, recipientAddress }: Prop {selectedEntry && selectedEntry.address ? (
{ + onKeyDown={(e) => { if (e.keyCode !== 9) { setSelectedEntry(null) } diff --git a/src/routes/safe/components/Balances/SendModal/screens/SendFunds/TokenSelectField/index.jsx b/src/routes/safe/components/Balances/SendModal/screens/SendFunds/TokenSelectField/index.jsx index 5d629c87..56af0967 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/SendFunds/TokenSelectField/index.jsx +++ b/src/routes/safe/components/Balances/SendModal/screens/SendFunds/TokenSelectField/index.jsx @@ -64,10 +64,10 @@ const TokenSelectField = ({ classes, initialValue, isValid, tokens }: SelectFiel displayEmpty initialValue={initialValue} name="token" - renderValue={tokenAddress => } + renderValue={(tokenAddress) => } validate={required} > - {tokens.map(token => ( + {tokens.map((token) => ( {token.name} diff --git a/src/routes/safe/components/Balances/SendModal/screens/SendFunds/index.jsx b/src/routes/safe/components/Balances/SendModal/screens/SendFunds/index.jsx index 8950d711..92c5c273 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/SendFunds/index.jsx +++ b/src/routes/safe/components/Balances/SendModal/screens/SendFunds/index.jsx @@ -39,7 +39,7 @@ import { sm } from '~/theme/variables' type Props = { initialValues: Object, onClose: () => void, - onNext: any => void, + onNext: (any) => void, recipientAddress?: string, selectedToken: string, } @@ -76,7 +76,7 @@ const SendFunds = ({ initialValues, onClose, onNext, recipientAddress, selectedT } }, [selectedEntry, pristine]) - const handleSubmit = values => { + const handleSubmit = (values) => { const submitValues = values // If the input wasn't modified, there was no mutation of the recipientAddress if (!values.recipientAddress) { @@ -110,9 +110,9 @@ const SendFunds = ({ initialValues, onClose, onNext, recipientAddress, selectedT const formState = args[2] const mutators = args[3] const { token: tokenAddress } = formState.values - const selectedTokenRecord = tokens.find(token => token.address === tokenAddress) + const selectedTokenRecord = tokens.find((token) => token.address === tokenAddress) - const handleScan = value => { + const handleScan = (value) => { let scannedAddress = value if (scannedAddress.startsWith('ethereum:')) { @@ -142,7 +142,7 @@ const SendFunds = ({ initialValues, onClose, onNext, recipientAddress, selectedT {selectedEntry && selectedEntry.address ? (
{ + onKeyDown={(e) => { if (e.keyCode !== 9) { setSelectedEntry(null) } diff --git a/src/routes/safe/components/Balances/Tokens/index.jsx b/src/routes/safe/components/Balances/Tokens/index.jsx index bb06bb8b..c23bd662 100644 --- a/src/routes/safe/components/Balances/Tokens/index.jsx +++ b/src/routes/safe/components/Balances/Tokens/index.jsx @@ -4,7 +4,7 @@ import { withStyles } from '@material-ui/core/styles' import Close from '@material-ui/icons/Close' import { List } from 'immutable' import React, { useState } from 'react' -import { connect } from 'react-redux' +import { connect, useSelector } from 'react-redux' import actions, { type Actions } from './actions' import { styles } from './style' @@ -13,11 +13,18 @@ import Hairline from '~/components/layout/Hairline' import Paragraph from '~/components/layout/Paragraph' import Row from '~/components/layout/Row' import { type Token } from '~/logic/tokens/store/model/token' +import { orderedTokenListSelector } from '~/logic/tokens/store/selectors' +import AddCustomAssetComponent from '~/routes/safe/components/Balances/Tokens/screens/AddCustomAsset' import AddCustomToken from '~/routes/safe/components/Balances/Tokens/screens/AddCustomToken' +import AssetsList from '~/routes/safe/components/Balances/Tokens/screens/AssetsList' import TokenList from '~/routes/safe/components/Balances/Tokens/screens/TokenList' +import { extendedSafeTokensSelector } from '~/routes/safe/container/selector' +import { safeBlacklistedTokensSelector } from '~/routes/safe/store/selectors' export const MANAGE_TOKENS_MODAL_CLOSE_BUTTON_TEST_ID = 'manage-tokens-close-modal-btn' +type ActiveScreen = 'tokenList' | 'addCustomToken' | 'assetsList' | 'addCustomAsset' + type Props = Actions & { onClose: () => void, classes: Object, @@ -25,24 +32,25 @@ type Props = Actions & { safeAddress: string, activeTokens: List, blacklistedTokens: List, + modalScreen: ActiveScreen, } -type ActiveScreen = 'tokenList' | 'addCustomToken' const Tokens = (props: Props) => { - const [activeScreen, setActiveScreen] = useState('tokenList') const { activateTokenForAllSafes, - activeTokens, addToken, - blacklistedTokens, classes, fetchTokens, + modalScreen, onClose, safeAddress, - tokens, updateActiveTokens, updateBlacklistedTokens, } = props + const tokens = useSelector(orderedTokenListSelector) + const activeTokens = useSelector(extendedSafeTokensSelector) + const blacklistedTokens = useSelector(safeBlacklistedTokensSelector) + const [activeScreen, setActiveScreen] = useState(modalScreen) return ( <> @@ -67,18 +75,23 @@ const Tokens = (props: Props) => { updateBlacklistedTokens={updateBlacklistedTokens} /> )} + {activeScreen === 'assetsList' && } {activeScreen === 'addCustomToken' && ( )} + {activeScreen === 'addCustomAsset' && ( + + )} ) } diff --git a/src/routes/safe/components/Balances/Tokens/screens/AddCustomAsset/index.jsx b/src/routes/safe/components/Balances/Tokens/screens/AddCustomAsset/index.jsx new file mode 100644 index 00000000..cc71a1d1 --- /dev/null +++ b/src/routes/safe/components/Balances/Tokens/screens/AddCustomAsset/index.jsx @@ -0,0 +1,190 @@ +// @flow +import { withStyles } from '@material-ui/core/styles' +import { List } from 'immutable' +import React, { useState } from 'react' +import { FormSpy } from 'react-final-form' +import { useSelector } from 'react-redux' + +import { styles } from './style' +import { getSymbolAndDecimalsFromContract } from './utils' + +import Checkbox from '~/components/forms/Checkbox' +import Field from '~/components/forms/Field' +import GnoForm from '~/components/forms/GnoForm' +import TextField from '~/components/forms/TextField' +import { composeValidators, minMaxLength, mustBeEthereumAddress, required } from '~/components/forms/validator' +import Block from '~/components/layout/Block' +import Button from '~/components/layout/Button' +import Col from '~/components/layout/Col' +import Hairline from '~/components/layout/Hairline' +import Img from '~/components/layout/Img' +import Paragraph from '~/components/layout/Paragraph' +import Row from '~/components/layout/Row' +import type { NFTAssetsState } from '~/logic/collectibles/store/reducer/collectibles' +import { nftAssetsListSelector } from '~/logic/collectibles/store/selectors' +import { type Token, type TokenProps } from '~/logic/tokens/store/model/token' +import { + addressIsAssetContract, + doesntExistInAssetsList, +} from '~/routes/safe/components/Balances/Tokens/screens/AddCustomAsset/validators' +import TokenPlaceholder from '~/routes/safe/components/Balances/assets/token_placeholder.svg' + +export const ADD_CUSTOM_ASSET_ADDRESS_INPUT_TEST_ID = 'add-custom-asset-address-input' +export const ADD_CUSTOM_ASSET_SYMBOLS_INPUT_TEST_ID = 'add-custom-asset-symbols-input' +export const ADD_CUSTOM_ASSET_DECIMALS_INPUT_TEST_ID = 'add-custom-asset-decimals-input' +export const ADD_CUSTOM_ASSET_FORM = 'add-custom-asset-form' + +type Props = { + classes: Object, + addToken: Function, + updateActiveTokens: Function, + safeAddress: string, + activeTokens: List, + tokens: List, + setActiveScreen: Function, + onClose: Function, + activateTokenForAllSafes: Function, + parentList: 'assetsList' | 'tokenList', +} + +const INITIAL_FORM_STATE = { + address: '', + decimals: '', + symbol: '', + logoUri: '', +} + +const AddCustomAsset = (props: Props) => { + const { classes, onClose, parentList, setActiveScreen } = props + + const nftAssetsList: NFTAssetsState = useSelector(nftAssetsListSelector) + const [formValues, setFormValues] = useState(INITIAL_FORM_STATE) + + const handleSubmit = () => { + onClose() + } + + const populateFormValuesFromAddress = async (tokenAddress: string) => { + const tokenData = await getSymbolAndDecimalsFromContract(tokenAddress) + + if (tokenData.length) { + const [symbol, decimals] = tokenData + + setFormValues({ + address: tokenAddress, + symbol, + decimals, + name: symbol, + }) + } + } + + const formSpyOnChangeHandler = async (state) => { + const { dirty, errors, submitSucceeded, validating, values } = state + // for some reason this is called after submitting, we don't need to update the values + // after submit + if (submitSucceeded) { + return + } + + if (dirty && !validating && errors.address) { + setFormValues(INITIAL_FORM_STATE) + } + + if (!errors.address && !validating && dirty) { + await populateFormValuesFromAddress(values.address) + } + } + + const goBack = () => { + setActiveScreen(parentList) + } + + return ( + <> + + {() => ( + <> + + + Add custom asset + + + + + + + + + + + Activate assets for all Safes + + + + + Token Image + Token image + + + + + + + + + + )} + + + ) +} + +const AddCustomAssetComponent = withStyles(styles)(AddCustomAsset) + +export default AddCustomAssetComponent diff --git a/src/routes/safe/components/Balances/Tokens/screens/AddCustomAsset/style.js b/src/routes/safe/components/Balances/Tokens/screens/AddCustomAsset/style.js new file mode 100644 index 00000000..f84d16f9 --- /dev/null +++ b/src/routes/safe/components/Balances/Tokens/screens/AddCustomAsset/style.js @@ -0,0 +1,34 @@ +// @flow +import { lg, md } from '~/theme/variables' + +export const styles = () => ({ + title: { + padding: `${lg} 0 20px`, + fontSize: md, + }, + formContainer: { + padding: '0 20px', + minHeight: '369px', + }, + addressInput: { + marginBottom: '15px', + display: 'flex', + flexGrow: 1, + backgroundColor: 'red', + }, + tokenImageHeading: { + margin: '0 0 15px', + }, + checkbox: { + padding: '0 7px 0 0', + width: '18px', + height: '18px', + }, + checkboxLabel: { + letterSpacing: '-0.5px', + }, + buttonRow: { + height: '84px', + justifyContent: 'center', + }, +}) diff --git a/src/routes/safe/components/Balances/Tokens/screens/AddCustomAsset/utils.js b/src/routes/safe/components/Balances/Tokens/screens/AddCustomAsset/utils.js new file mode 100644 index 00000000..26f5fe1c --- /dev/null +++ b/src/routes/safe/components/Balances/Tokens/screens/AddCustomAsset/utils.js @@ -0,0 +1,17 @@ +// @flow +import { getHumanFriendlyToken } from '~/logic/tokens/store/actions/fetchTokens' + +export const getSymbolAndDecimalsFromContract = async (tokenAddress: string) => { + const tokenContract = await getHumanFriendlyToken() + const token = await tokenContract.at(tokenAddress) + let values + + try { + const [symbol, decimals] = await Promise.all([token.symbol(), token.decimals()]) + values = [symbol, decimals.toString()] + } catch { + values = [] + } + + return values +} diff --git a/src/routes/safe/components/Balances/Tokens/screens/AddCustomAsset/validators.js b/src/routes/safe/components/Balances/Tokens/screens/AddCustomAsset/validators.js new file mode 100644 index 00000000..6375530c --- /dev/null +++ b/src/routes/safe/components/Balances/Tokens/screens/AddCustomAsset/validators.js @@ -0,0 +1,25 @@ +// @flow +import { List } from 'immutable' + +import { simpleMemoize } from '~/components/forms/validator' +import { isERC721Contract } from '~/logic/tokens/utils/tokenHelpers' +import { sameAddress } from '~/logic/wallets/ethAddresses' +import type { NFTAsset } from '~/routes/safe/components/Balances/Collectibles/types' + +// eslint-disable-next-line +export const addressIsAssetContract = simpleMemoize(async (tokenAddress: string) => { + const isAsset = await isERC721Contract(tokenAddress) + if (!isAsset) { + return 'Not a asset address' + } +}) + +// eslint-disable-next-line +export const doesntExistInAssetsList = (assetsList: List) => + simpleMemoize((tokenAddress: string) => { + const tokenIndex = assetsList.findIndex(({ address }) => sameAddress(address, tokenAddress)) + + if (tokenIndex !== -1) { + return 'Token already exists in your token list' + } + }) diff --git a/src/routes/safe/components/Balances/Tokens/screens/AddCustomToken/index.jsx b/src/routes/safe/components/Balances/Tokens/screens/AddCustomToken/index.jsx index 10ad1c17..2eb6512f 100644 --- a/src/routes/safe/components/Balances/Tokens/screens/AddCustomToken/index.jsx +++ b/src/routes/safe/components/Balances/Tokens/screens/AddCustomToken/index.jsx @@ -38,6 +38,7 @@ type Props = { setActiveScreen: Function, onClose: Function, activateTokenForAllSafes: Function, + parentList: 'assetsList' | 'tokenList', } const INITIAL_FORM_STATE = { @@ -54,6 +55,7 @@ const AddCustomToken = (props: Props) => { addToken, classes, onClose, + parentList, safeAddress, setActiveScreen, tokens, @@ -61,7 +63,7 @@ const AddCustomToken = (props: Props) => { } = props const [formValues, setFormValues] = useState(INITIAL_FORM_STATE) - const handleSubmit = values => { + const handleSubmit = (values) => { const token = { address: values.address, decimals: values.decimals, @@ -95,7 +97,7 @@ const AddCustomToken = (props: Props) => { } } - const formSpyOnChangeHandler = async state => { + const formSpyOnChangeHandler = async (state) => { const { dirty, errors, submitSucceeded, validating, values } = state // for some reason this is called after submitting, we don't need to update the values // after submit @@ -112,8 +114,8 @@ const AddCustomToken = (props: Props) => { } } - const goBackToTokenList = () => { - setActiveScreen('tokenList') + const goBack = () => { + setActiveScreen(parentList) } return ( @@ -187,7 +189,7 @@ const AddCustomToken = (props: Props) => { - + + + + {!nftAssetsList.size && ( + + + + )} + {nftAssetsList.size > 0 && ( + + + {AssetRow} + + + )} + + ) +} + +export default AssetsList diff --git a/src/routes/safe/components/Balances/Tokens/screens/AssetsList/style.js b/src/routes/safe/components/Balances/Tokens/screens/AssetsList/style.js new file mode 100644 index 00000000..6e6f7384 --- /dev/null +++ b/src/routes/safe/components/Balances/Tokens/screens/AssetsList/style.js @@ -0,0 +1,76 @@ +// @flow +import { md, mediumFontSize, secondaryText, sm, xs } from '~/theme/variables' + +export const styles = () => ({ + 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', + 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', + }, + }, + searchIcon: { + '&:hover': { + backgroundColor: 'transparent !important', + }, + }, +}) diff --git a/src/routes/safe/components/Balances/Tokens/screens/TokenList/index.jsx b/src/routes/safe/components/Balances/Tokens/screens/TokenList/index.jsx index 1710ef8d..e87867e4 100644 --- a/src/routes/safe/components/Balances/Tokens/screens/TokenList/index.jsx +++ b/src/routes/safe/components/Balances/Tokens/screens/TokenList/index.jsx @@ -103,12 +103,12 @@ class Tokens extends React.Component { this.setState(() => ({ filter: '' })) } - onChangeSearchBar = value => { + onChangeSearchBar = (value) => { this.setState(() => ({ filter: value })) } onSwitch = (token: Token) => () => { - this.setState(prevState => { + this.setState((prevState) => { const activeTokensAddresses = prevState.activeTokensAddresses.has(token.address) ? prevState.activeTokensAddresses.remove(token.address) : prevState.activeTokensAddresses.add(token.address) diff --git a/src/routes/safe/components/Balances/index.jsx b/src/routes/safe/components/Balances/index.jsx index aad43eb7..d89f25c9 100644 --- a/src/routes/safe/components/Balances/index.jsx +++ b/src/routes/safe/components/Balances/index.jsx @@ -1,24 +1,13 @@ // @flow -import TableCell from '@material-ui/core/TableCell' -import TableContainer from '@material-ui/core/TableContainer' -import TableRow from '@material-ui/core/TableRow' import { withStyles } from '@material-ui/core/styles' -import CallMade from '@material-ui/icons/CallMade' -import CallReceived from '@material-ui/icons/CallReceived' -import classNames from 'classnames/bind' import { List } from 'immutable' import * as React from 'react' -import AssetTableCell from './AssetTableCell' import Receive from './Receive' import Tokens from './Tokens' -import { BALANCE_TABLE_ASSET_ID, type BalanceRow, generateColumns, getBalanceData } from './dataFetcher' import { styles } from './style' import Modal from '~/components/Modal' -import Table from '~/components/Table' -import { type Column, cellWidth } from '~/components/Table/TableHead' -import Button from '~/components/layout/Button' import ButtonLink from '~/components/layout/ButtonLink' import Col from '~/components/layout/Col' import Divider from '~/components/layout/Divider' @@ -27,9 +16,9 @@ import Row from '~/components/layout/Row' import type { BalanceCurrencyType } from '~/logic/currencyValues/store/model/currencyValues' import { type Token } from '~/logic/tokens/store/model/token' import { SAFELIST_ADDRESS } from '~/routes/routes' +import Coins from '~/routes/safe/components/Balances/Coins' import Collectibles from '~/routes/safe/components/Balances/Collectibles' import SendModal from '~/routes/safe/components/Balances/SendModal' -import { BALANCE_TABLE_BALANCE_ID, BALANCE_TABLE_VALUE_ID } from '~/routes/safe/components/Balances/dataFetcher' import DropdownCurrency from '~/routes/safe/components/DropdownCurrency' import { history } from '~/store' @@ -44,17 +33,19 @@ type State = { showCollectibles: boolean, showReceive: boolean, showToken: boolean, + showManageCollectibleModal: boolean, } type Props = { activateTokensByBalance: Function, + activateAssetsByBalance: Function, activeTokens: List, blacklistedTokens: List, classes: Object, - createTransaction?: Function, + createTransaction: Function, currencySelected: string, currencyValues: BalanceCurrencyType[], - ethBalance?: string, + ethBalance: string, featuresEnabled: string[], fetchCurrencyValues: Function, fetchTokens: Function, @@ -64,7 +55,7 @@ type Props = { tokens: List, } -type Action = 'Token' | 'Send' | 'Receive' +type Action = 'Token' | 'Send' | 'Receive' | 'ManageCollectibleModal' class Balances extends React.Component { constructor(props) { @@ -73,6 +64,7 @@ class Balances extends React.Component { erc721Enabled: false, subMenuOptions: [], showToken: false, + showManageCollectibleModal: false, sendFunds: { isOpen: false, selectedToken: undefined, @@ -88,9 +80,10 @@ class Balances extends React.Component { static isCollectiblesLocation = /\/balances\/collectibles$/ componentDidMount(): void { - const { activateTokensByBalance, fetchCurrencyValues, safeAddress } = this.props + const { activateAssetsByBalance, activateTokensByBalance, fetchCurrencyValues, safeAddress } = this.props fetchCurrencyValues(safeAddress) activateTokensByBalance(safeAddress) + activateAssetsByBalance(safeAddress) const showCollectibles = Balances.isCollectiblesLocation.test(history.location.pathname) const showCoins = Balances.isCoinsLocation.test(history.location.pathname) @@ -151,23 +144,17 @@ class Balances extends React.Component { } render() { - const { erc721Enabled, sendFunds, showCoins, showCollectibles, showReceive, showToken, subMenuOptions } = this.state const { - activeTokens, - blacklistedTokens, - classes, - currencySelected, - currencyValues, - granted, - safeAddress, - safeName, - tokens, - } = this.props - - const columns = generateColumns() - const autoColumns = columns.filter(c => !c.custom) - - const filteredData = getBalanceData(activeTokens, currencySelected, currencyValues) + erc721Enabled, + sendFunds, + showCoins, + showCollectibles, + showManageCollectibleModal, + showReceive, + showToken, + subMenuOptions, + } = this.state + const { activeTokens, classes, createTransaction, ethBalance, safeAddress, safeName } = this.props return ( <> @@ -190,121 +177,43 @@ class Balances extends React.Component { ))} - {showCoins && ( - <> - - - Manage List - - - - - - )} + {showCoins && } + + Manage List + + + + - {showCoins && ( - - - {(sortedData: Array) => - sortedData.map((row: any, index: number) => ( - - {autoColumns.map((column: Column) => { - const { align, id, width } = column - let cellItem - switch (id) { - case BALANCE_TABLE_ASSET_ID: { - cellItem = - break - } - case BALANCE_TABLE_BALANCE_ID: { - cellItem =
{row[id]}
- break - } - case BALANCE_TABLE_VALUE_ID: { - cellItem =
{row[id]}
- break - } - default: { - cellItem = null - break - } - } - return ( - - {cellItem} - - ) - })} - - - {granted && ( - - )} - - - -
- )) - } -
-
- )} + {showCoins && } {erc721Enabled && showCollectibles && } ({ - root: { - marginRight: sm, - width: '20px', - }, +export const styles = () => ({ controls: { alignItems: 'center', boxSizing: 'border-box', @@ -62,42 +58,12 @@ export const styles = (theme: Object) => ({ marginLeft: '0', }, }, - actionIcon: { - marginRight: theme.spacing(1), - }, - iconSmall: { - fontSize: 16, - }, receiveModal: { height: 'auto', maxWidth: 'calc(100% - 30px)', minHeight: '544px', overflow: 'hidden', }, - hide: { - '&:hover': { - backgroundColor: '#fff3e2', - }, - '&:hover $actions': { - visibility: 'initial', - }, - '&:focus $actions': { - visibility: 'initial', - }, - }, - actions: { - justifyContent: 'flex-end', - visibility: 'hidden', - }, - receive: { - width: '95px', - minWidth: '95px', - marginLeft: sm, - borderRadius: xs, - '& > span': { - fontSize: '14px', - }, - }, send: { width: '75px', minWidth: '75px', @@ -106,17 +72,4 @@ export const styles = (theme: Object) => ({ fontSize: '14px', }, }, - leftIcon: { - marginRight: sm, - }, - links: { - textDecoration: 'underline', - '&:hover': { - cursor: 'pointer', - }, - }, - currencyValueRow: { - maxWidth: '125px', - textAlign: 'right', - }, }) diff --git a/src/routes/safe/components/Balances/utils/setTokenImgToPlaceholder.js b/src/routes/safe/components/Balances/utils/setTokenImgToPlaceholder.js index 011468b8..601ab9a4 100644 --- a/src/routes/safe/components/Balances/utils/setTokenImgToPlaceholder.js +++ b/src/routes/safe/components/Balances/utils/setTokenImgToPlaceholder.js @@ -1,7 +1,7 @@ // @flow import TokenPlaceholder from '~/routes/safe/components/Balances/assets/token_placeholder.svg' -export const setImageToPlaceholder = e => { +export const setImageToPlaceholder = (e) => { e.target.onerror = null e.target.src = TokenPlaceholder } diff --git a/src/routes/safe/components/DropdownCurrency/index.jsx b/src/routes/safe/components/DropdownCurrency/index.jsx index 39c64586..edb76daa 100644 --- a/src/routes/safe/components/DropdownCurrency/index.jsx +++ b/src/routes/safe/components/DropdownCurrency/index.jsx @@ -28,7 +28,7 @@ const DropdownCurrency = () => { const [searchParams, setSearchParams] = useState('') const classes = useDropdownStyles() - const currenciesListFiltered = currenciesList.filter(currency => + const currenciesListFiltered = currenciesList.filter((currency) => currency.toLowerCase().includes(searchParams.toLowerCase()), ) @@ -83,14 +83,14 @@ const DropdownCurrency = () => { input: classes.inputInput, }} inputProps={{ 'aria-label': 'search' }} - onChange={event => setSearchParams(event.target.value)} + onChange={(event) => setSearchParams(event.target.value)} placeholder="Search…" value={searchParams} />
- {currenciesListFiltered.map(currencyName => ( + {currenciesListFiltered.map((currencyName) => ( { const { + activateAssetsByBalance, activateTokensByBalance, activeTokens, addressBook, @@ -120,7 +121,7 @@ const Layout = (props: Props) => { const etherScanLink = getEtherScanLink('address', address) const web3Instance = getWeb3() - const openGenericModal = modalConfig => { + const openGenericModal = (modalConfig) => { setModal({ ...modalConfig, isOpen: true }) } @@ -313,6 +314,7 @@ const Layout = (props: Props) => { path={`${match.path}/balances/:assetType?`} render={() => ( { + const dispatch = useDispatch() const [activeScreen, setActiveScreen] = useState('selectOwner') const [values, setValues] = useState({}) @@ -97,7 +100,7 @@ const AddOwner = ({ } const ownerSubmitted = (newValues: Object) => { - setValues(stateValues => ({ + setValues((stateValues) => ({ ...stateValues, ownerName: newValues.ownerName, ownerAddress: newValues.ownerAddress, @@ -106,7 +109,7 @@ const AddOwner = ({ } const thresholdSubmitted = (newValues: Object) => { - setValues(stateValues => ({ + setValues((stateValues) => ({ ...stateValues, threshold: newValues.threshold, })) @@ -115,8 +118,13 @@ const AddOwner = ({ const onAddOwner = async () => { onClose() + try { - sendAddOwner(values, safeAddress, owners, enqueueSnackbar, closeSnackbar, createTransaction, addSafeOwner) + await sendAddOwner(values, safeAddress, owners, enqueueSnackbar, closeSnackbar, createTransaction, addSafeOwner) + + dispatch( + addOrUpdateAddressBookEntry(values.ownerAddress, { name: values.ownerName, address: values.ownerAddress }), + ) } catch (error) { console.error('Error while removing an owner', error) } diff --git a/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/screens/OwnerForm/index.jsx b/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/screens/OwnerForm/index.jsx index e6b59533..5409529e 100644 --- a/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/screens/OwnerForm/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/screens/OwnerForm/index.jsx @@ -38,10 +38,10 @@ type Props = { } const OwnerForm = ({ classes, onClose, onSubmit, owners }: Props) => { - const handleSubmit = values => { + const handleSubmit = (values) => { onSubmit(values) } - const ownerDoesntExist = uniqueAddress(owners.map(o => o.address)) + const ownerDoesntExist = uniqueAddress(owners.map((o) => o.address)) return ( <> diff --git a/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/screens/Review/index.jsx b/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/screens/Review/index.jsx index e22b1448..e30a67f4 100644 --- a/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/screens/Review/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/screens/Review/index.jsx @@ -113,7 +113,7 @@ const ReviewAddOwner = ({ classes, onClickBack, onClose, onSubmit, owners, safeA - {owners.map(owner => ( + {owners.map((owner) => ( diff --git a/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/screens/ThresholdForm/index.jsx b/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/screens/ThresholdForm/index.jsx index c79b0e61..0d57ac9c 100644 --- a/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/screens/ThresholdForm/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/screens/ThresholdForm/index.jsx @@ -32,7 +32,7 @@ type Props = { } const ThresholdForm = ({ classes, onClickBack, onClose, onSubmit, owners, threshold }: Props) => { - const handleSubmit = values => { + const handleSubmit = (values) => { onSubmit(values) } diff --git a/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/index.jsx b/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/index.jsx index d5746dff..19058820 100644 --- a/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/index.jsx @@ -20,6 +20,7 @@ import Button from '~/components/layout/Button' import Hairline from '~/components/layout/Hairline' import Paragraph from '~/components/layout/Paragraph' import Row from '~/components/layout/Row' +import { makeAddressBookEntry } from '~/logic/addressBook/model/addressBook' import { getNotificationsFromTxType, showSnackbar } from '~/logic/notifications' import { TX_NOTIFICATION_TYPES } from '~/logic/safe/transactions' import { sm } from '~/theme/variables' @@ -52,10 +53,10 @@ const EditOwnerComponent = ({ selectedOwnerName, updateAddressBookEntry, }: Props) => { - const handleSubmit = values => { + const handleSubmit = (values) => { const { ownerName } = values editSafeOwner({ safeAddress, ownerAddress, ownerName }) - updateAddressBookEntry({ address: ownerAddress, name: ownerName }) + updateAddressBookEntry(makeAddressBookEntry({ address: ownerAddress, name: ownerName })) const notification = getNotificationsFromTxType(TX_NOTIFICATION_TYPES.OWNER_NAME_CHANGE_TX) showSnackbar(notification.afterExecution.noMoreConfirmationsNeeded, enqueueSnackbar, closeSnackbar) diff --git a/src/routes/safe/components/Settings/ManageOwners/OwnerAddressTableCell/index.jsx b/src/routes/safe/components/Settings/ManageOwners/OwnerAddressTableCell/index.jsx index facfaf8c..e1ac6466 100644 --- a/src/routes/safe/components/Settings/ManageOwners/OwnerAddressTableCell/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/OwnerAddressTableCell/index.jsx @@ -10,7 +10,7 @@ type Props = { address: string, showLinks?: boolean, knownAddress?: boolean, - userName?: boolean, + userName?: string, } const OwnerAddressTableCell = (props: Props) => { diff --git a/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/index.jsx b/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/index.jsx index b39e4015..a8454383 100644 --- a/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/index.jsx @@ -56,7 +56,9 @@ export const sendRemoveOwner = async ( ) => { const gnosisSafe = await getGnosisSafeInstanceAt(safeAddress) const safeOwners = await gnosisSafe.getOwners() - const index = safeOwners.findIndex(ownerAddress => ownerAddress.toLowerCase() === ownerAddressToRemove.toLowerCase()) + const index = safeOwners.findIndex( + (ownerAddress) => ownerAddress.toLowerCase() === ownerAddressToRemove.toLowerCase(), + ) const prevAddress = index === 0 ? SENTINEL_ADDRESS : safeOwners[index - 1] const txData = gnosisSafe.contract.methods .removeOwner(prevAddress, ownerAddressToRemove, values.threshold) diff --git a/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/screens/CheckOwner/index.jsx b/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/screens/CheckOwner/index.jsx index ce8b03d7..a6812212 100644 --- a/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/screens/CheckOwner/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/screens/CheckOwner/index.jsx @@ -28,7 +28,7 @@ type Props = { } const CheckOwner = ({ classes, onClose, onSubmit, ownerAddress, ownerName }: Props) => { - const handleSubmit = values => { + const handleSubmit = (values) => { onSubmit(values) } diff --git a/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/screens/Review/index.jsx b/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/screens/Review/index.jsx index 68bc83f6..fe080865 100644 --- a/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/screens/Review/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/screens/Review/index.jsx @@ -60,7 +60,7 @@ const ReviewRemoveOwner = ({ const { fromWei, toBN } = web3.utils const gnosisSafe = await getGnosisSafeInstanceAt(safeAddress) const safeOwners = await gnosisSafe.getOwners() - const index = safeOwners.findIndex(owner => owner.toLowerCase() === ownerAddress.toLowerCase()) + const index = safeOwners.findIndex((owner) => owner.toLowerCase() === ownerAddress.toLowerCase()) const prevAddress = index === 0 ? SENTINEL_ADDRESS : safeOwners[index - 1] const txData = gnosisSafe.contract.methods.removeOwner(prevAddress, ownerAddress, values.threshold).encodeABI() const estimatedGasCosts = await estimateTxGasCosts(safeAddress, safeAddress, txData) @@ -125,7 +125,7 @@ const ReviewRemoveOwner = ({ {owners.map( - owner => + (owner) => owner.address !== ownerAddress && ( diff --git a/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/screens/ThresholdForm/index.jsx b/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/screens/ThresholdForm/index.jsx index e47fdccc..3d4d015d 100644 --- a/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/screens/ThresholdForm/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/screens/ThresholdForm/index.jsx @@ -32,7 +32,7 @@ type Props = { } const ThresholdForm = ({ classes, onClickBack, onClose, onSubmit, owners, threshold }: Props) => { - const handleSubmit = values => { + const handleSubmit = (values) => { onSubmit(values) } const defaultThreshold = threshold > 1 ? threshold - 1 : threshold diff --git a/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.jsx b/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.jsx index a7e34cda..c1f414a1 100644 --- a/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.jsx @@ -3,11 +3,13 @@ import { withStyles } from '@material-ui/core/styles' import { List } from 'immutable' import { withSnackbar } from 'notistack' import React, { useEffect, useState } from 'react' +import { useDispatch } from 'react-redux' import OwnerForm from './screens/OwnerForm' import ReviewReplaceOwner from './screens/Review' import Modal from '~/components/Modal' +import { addOrUpdateAddressBookEntry } from '~/logic/addressBook/store/actions/addOrUpdateAddressBookEntry' import { SENTINEL_ADDRESS, getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts' import { TX_NOTIFICATION_TYPES } from '~/logic/safe/transactions' import { type Owner } from '~/routes/safe/store/models/owner' @@ -52,7 +54,9 @@ export const sendReplaceOwner = async ( ) => { const gnosisSafe = await getGnosisSafeInstanceAt(safeAddress) const safeOwners = await gnosisSafe.getOwners() - const index = safeOwners.findIndex(ownerAddress => ownerAddress.toLowerCase() === ownerAddressToRemove.toLowerCase()) + const index = safeOwners.findIndex( + (ownerAddress) => ownerAddress.toLowerCase() === ownerAddressToRemove.toLowerCase(), + ) const prevAddress = index === 0 ? SENTINEL_ADDRESS : safeOwners[index - 1] const txData = gnosisSafe.contract.methods .swapOwner(prevAddress, ownerAddressToRemove, values.ownerAddress) @@ -94,6 +98,7 @@ const ReplaceOwner = ({ safeName, threshold, }: Props) => { + const dispatch = useDispatch() const [activeScreen, setActiveScreen] = useState('checkOwner') const [values, setValues] = useState({}) @@ -114,10 +119,11 @@ const ReplaceOwner = ({ setActiveScreen('reviewReplaceOwner') } - const onReplaceOwner = () => { + const onReplaceOwner = async () => { onClose() + try { - sendReplaceOwner( + await sendReplaceOwner( values, safeAddress, ownerAddress, @@ -127,6 +133,13 @@ const ReplaceOwner = ({ replaceSafeOwner, safe, ) + + dispatch( + // Needs the `address` field because we need to provide the minimum required values to ADD a new entry + // The reducer will update all the addressBooks stored, so we cannot decide what to do beforehand, + // thus, we pass the minimum required fields (name and address) + addOrUpdateAddressBookEntry(values.ownerAddress, { name: values.ownerName, address: values.ownerAddress }), + ) } catch (error) { console.error('Error while removing an owner', error) } diff --git a/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/screens/OwnerForm/index.jsx b/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/screens/OwnerForm/index.jsx index 47c7f4da..13f876b3 100644 --- a/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/screens/OwnerForm/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/screens/OwnerForm/index.jsx @@ -44,10 +44,10 @@ type Props = { } const OwnerForm = ({ classes, onClose, onSubmit, ownerAddress, ownerName, owners }: Props) => { - const handleSubmit = values => { + const handleSubmit = (values) => { onSubmit(values) } - const ownerDoesntExist = uniqueAddress(owners.map(o => o.address)) + const ownerDoesntExist = uniqueAddress(owners.map((o) => o.address)) return ( <> diff --git a/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/screens/Review/index.jsx b/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/screens/Review/index.jsx index fd5f7d67..9b1588ee 100644 --- a/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/screens/Review/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/screens/Review/index.jsx @@ -61,7 +61,7 @@ const ReviewRemoveOwner = ({ const { fromWei, toBN } = web3.utils const gnosisSafe = await getGnosisSafeInstanceAt(safeAddress) const safeOwners = await gnosisSafe.getOwners() - const index = safeOwners.findIndex(owner => owner.toLowerCase() === ownerAddress.toLowerCase()) + const index = safeOwners.findIndex((owner) => owner.toLowerCase() === ownerAddress.toLowerCase()) const prevAddress = index === 0 ? SENTINEL_ADDRESS : safeOwners[index - 1] const txData = gnosisSafe.contract.methods.swapOwner(prevAddress, ownerAddress, values.ownerAddress).encodeABI() const estimatedGasCosts = await estimateTxGasCosts(safeAddress, safeAddress, txData) @@ -125,7 +125,7 @@ const ReviewRemoveOwner = ({ {owners.map( - owner => + (owner) => owner.address !== ownerAddress && ( diff --git a/src/routes/safe/components/Settings/ManageOwners/index.jsx b/src/routes/safe/components/Settings/ManageOwners/index.jsx index 9baf42da..9b3876ef 100644 --- a/src/routes/safe/components/Settings/ManageOwners/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/index.jsx @@ -135,7 +135,7 @@ class ManageOwners extends React.Component { } = this.state const columns = generateColumns() - const autoColumns = columns.filter(c => !c.custom) + const autoColumns = columns.filter((c) => !c.custom) const ownersAdbk = getOwnersWithNameFromAddressBook(addressBook, owners) const ownerData = getOwnerData(ownersAdbk) diff --git a/src/routes/safe/components/Settings/SafeDetails/index.jsx b/src/routes/safe/components/Settings/SafeDetails/index.jsx index 2bc19dfe..ef30a51c 100644 --- a/src/routes/safe/components/Settings/SafeDetails/index.jsx +++ b/src/routes/safe/components/Settings/SafeDetails/index.jsx @@ -57,10 +57,10 @@ const SafeDetails = (props: Props) => { const [isModalOpen, setModalOpen] = React.useState(false) const toggleModal = () => { - setModalOpen(prevOpen => !prevOpen) + setModalOpen((prevOpen) => !prevOpen) } - const handleSubmit = values => { + const handleSubmit = (values) => { updateSafe({ address: safeAddress, name: values.safeName }) const notification = getNotificationsFromTxType(TX_NOTIFICATION_TYPES.SAFE_NAME_CHANGE_TX) diff --git a/src/routes/safe/components/Settings/ThresholdSettings/ChangeThreshold/index.jsx b/src/routes/safe/components/Settings/ThresholdSettings/ChangeThreshold/index.jsx index be4b9bd3..4148e7b7 100644 --- a/src/routes/safe/components/Settings/ThresholdSettings/ChangeThreshold/index.jsx +++ b/src/routes/safe/components/Settings/ThresholdSettings/ChangeThreshold/index.jsx @@ -60,7 +60,7 @@ const ChangeThreshold = ({ classes, onChangeThreshold, onClose, owners, safeAddr } }, []) - const handleSubmit = values => { + const handleSubmit = (values) => { const newThreshold = values[THRESHOLD_FIELD_NAME] onClose() diff --git a/src/routes/safe/components/Settings/ThresholdSettings/index.jsx b/src/routes/safe/components/Settings/ThresholdSettings/index.jsx index 64655a61..bd364365 100644 --- a/src/routes/safe/components/Settings/ThresholdSettings/index.jsx +++ b/src/routes/safe/components/Settings/ThresholdSettings/index.jsx @@ -42,10 +42,10 @@ const ThresholdSettings = ({ const [isModalOpen, setModalOpen] = useState(false) const toggleModal = () => { - setModalOpen(prevOpen => !prevOpen) + setModalOpen((prevOpen) => !prevOpen) } - const onChangeThreshold = async newThreshold => { + const onChangeThreshold = async (newThreshold) => { const safeInstance = await getGnosisSafeInstanceAt(safeAddress) const txData = safeInstance.contract.methods.changeThreshold(newThreshold).encodeABI() diff --git a/src/routes/safe/components/Settings/index.jsx b/src/routes/safe/components/Settings/index.jsx index f6888c79..73d734b5 100644 --- a/src/routes/safe/components/Settings/index.jsx +++ b/src/routes/safe/components/Settings/index.jsx @@ -69,7 +69,7 @@ class Settings extends React.Component { } } - handleChange = menuOptionIndex => () => { + handleChange = (menuOptionIndex) => () => { this.setState({ menuOptionIndex }) } diff --git a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/ApproveTxModal/index.jsx b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/ApproveTxModal/index.jsx index cc294b3d..fbde98e1 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/ApproveTxModal/index.jsx +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/ApproveTxModal/index.jsx @@ -114,7 +114,7 @@ const ApproveTxModal = ({ } }, [approveAndExecute]) - const handleExecuteCheckbox = () => setApproveAndExecute(prevApproveAndExecute => !prevApproveAndExecute) + const handleExecuteCheckbox = () => setApproveAndExecute((prevApproveAndExecute) => !prevApproveAndExecute) const approveTx = () => { processTransaction({ diff --git a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/OwnersColumn/OwnersList.jsx b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/OwnersColumn/OwnersList.jsx index d2142a93..55f2856f 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/OwnersColumn/OwnersList.jsx +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/OwnersColumn/OwnersList.jsx @@ -42,7 +42,7 @@ const OwnersList = ({ userAddress, }: ListProps) => ( <> - {ownersWhoConfirmed.map(owner => ( + {ownersWhoConfirmed.map((owner) => ( ))} - {ownersUnconfirmed.map(owner => ( + {ownersUnconfirmed.map((owner) => ( { + tx.confirmations.forEach((conf) => { if (conf.owner.address === userAddress) { currentUserAlreadyConfirmed = true } @@ -55,12 +55,12 @@ function getOwnersConfirmations(tx, userAddress) { function getPendingOwnersConfirmations(owners, tx, userAddress) { const ownersUnconfirmed = owners.filter( - owner => tx.confirmations.findIndex(conf => conf.owner.address === owner.address) === -1, + (owner) => tx.confirmations.findIndex((conf) => conf.owner.address === owner.address) === -1, ) let userIsUnconfirmedOwner = false - ownersUnconfirmed.some(owner => { + ownersUnconfirmed.some((owner) => { userIsUnconfirmedOwner = owner.address === userAddress return userIsUnconfirmedOwner }) diff --git a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/index.jsx b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/index.jsx index 195f54f4..8940eff4 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/index.jsx +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/index.jsx @@ -22,6 +22,7 @@ export const TRANSACTIONS_DESC_CHANGE_THRESHOLD_TEST_ID = 'tx-description-change export const TRANSACTIONS_DESC_SEND_TEST_ID = 'tx-description-send' export const TRANSACTIONS_DESC_CUSTOM_VALUE_TEST_ID = 'tx-description-custom-value' export const TRANSACTIONS_DESC_CUSTOM_DATA_TEST_ID = 'tx-description-custom-data' +export const TRANSACTIONS_DESC_NO_DATA = 'tx-description-no-data' export const styles = () => ({ txDataContainer: { @@ -52,9 +53,10 @@ type TransferDescProps = { } type DescriptionDescProps = { - removedOwner?: string, + action: string, addedOwner?: string, newThreshold?: string, + removedOwner?: string, } type CustomDescProps = { @@ -78,39 +80,81 @@ const TransferDescription = ({ amount = '', recipient }: TransferDescProps) => { ) } -const SettingsDescription = ({ addedOwner, newThreshold, removedOwner }: DescriptionDescProps) => { - const ownerChangedName = removedOwner ? getNameFromAddressBook(removedOwner) : getNameFromAddressBook(addedOwner) +const RemovedOwner = ({ removedOwner }: { removedOwner: string }) => { + const ownerChangedName = getNameFromAddressBook(removedOwner) + return ( - <> - {removedOwner && ( - - Remove owner: - {ownerChangedName ? ( - - ) : ( - - )} - + + Remove owner: + {ownerChangedName ? ( + + ) : ( + )} - {addedOwner && ( - - Add owner: - {ownerChangedName ? ( - - ) : ( - - )} - + + ) +} + +const AddedOwner = ({ addedOwner }: { addedOwner: string }) => { + const ownerChangedName = getNameFromAddressBook(addedOwner) + + return ( + + Add owner: + {ownerChangedName ? ( + + ) : ( + )} - {newThreshold && ( - - Change required confirmations: - - {newThreshold} - - - )} - + + ) +} + +const NewThreshold = ({ newThreshold }: { newThreshold: string }) => ( + + Change required confirmations: + + {newThreshold} + + +) + +const SettingsDescription = ({ action, addedOwner, newThreshold, removedOwner }: DescriptionDescProps) => { + if (action === 'removeOwner' && removedOwner && newThreshold) { + return ( + <> + + + + ) + } + + if (action === 'changedThreshold' && newThreshold) { + return + } + + if (action === 'addOwnerWithThreshold' && addedOwner && newThreshold) { + return ( + <> + + + + ) + } + + if (action === 'swapOwner' && removedOwner && addedOwner) { + return ( + <> + + + + ) + } + + return ( + + No data available for current transaction + ) } @@ -165,6 +209,7 @@ const CustomDescription = ({ amount = 0, classes, data, recipient }: CustomDescP const TxDescription = ({ classes, tx }: Props) => { const { + action, addedOwner, cancellationTx, creationTx, @@ -179,8 +224,13 @@ const TxDescription = ({ classes, tx }: Props) => { const amount = getTxAmount(tx) return ( - {modifySettingsTx && ( - + {modifySettingsTx && action && ( + )} {!upgradeTx && customTx && ( diff --git a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/utils.js b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/utils.js index fc3403c1..7b0bb75a 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/utils.js +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/utils.js @@ -3,6 +3,7 @@ import { getWeb3 } from '~/logic/wallets/getWeb3' import { type Transaction } from '~/routes/safe/store/models/transaction' type DecodedTxData = { + action?: string, recipient: string, value?: string, modifySettingsTx?: boolean, @@ -48,21 +49,20 @@ export const getTxData = (tx: Transaction): DecodedTxData => { txData.modifySettingsTx = true if (tx.decodedParams) { - /* eslint-disable */ - if (tx.decodedParams.methodName === 'removeOwner') { + txData.action = tx.decodedParams.methodName + + if (txData.action === 'removeOwner') { txData.removedOwner = tx.decodedParams.args[1] txData.newThreshold = tx.decodedParams.args[2] - } else if (tx.decodedParams.methodName === 'changeThreshold') { + } else if (txData.action === 'changeThreshold') { txData.newThreshold = tx.decodedParams.args[0] - } else if (tx.decodedParams.methodName === 'addOwnerWithThreshold') { + } else if (txData.action === 'addOwnerWithThreshold') { txData.addedOwner = tx.decodedParams.args[0] txData.newThreshold = tx.decodedParams.args[1] - } else if (tx.decodedParams.methodName === 'swapOwner') { - txData.newThreshold = tx.decodedParams.args[0] + } else if (txData.action === 'swapOwner') { txData.removedOwner = tx.decodedParams.args[1] txData.addedOwner = tx.decodedParams.args[2] } - /* eslint-enable */ } } else if (tx.cancellationTx) { txData.cancellationTx = true diff --git a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/index.jsx b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/index.jsx index 9518f295..3fdc384a 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/index.jsx +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/index.jsx @@ -21,7 +21,7 @@ import Paragraph from '~/components/layout/Paragraph' import Row from '~/components/layout/Row' import Span from '~/components/layout/Span' import IncomingTxDescription from '~/routes/safe/components/Transactions/TxsTable/ExpandedTx/IncomingTxDescription' -import { INCOMING_TX_TYPE } from '~/routes/safe/store/models/incomingTransaction' +import { INCOMING_TX_TYPES } from '~/routes/safe/store/models/incomingTransaction' import { type Owner } from '~/routes/safe/store/models/owner' import { type Transaction } from '~/routes/safe/store/models/transaction' @@ -58,8 +58,8 @@ const ExpandedTx = ({ const [openModal, setOpenModal] = useState(null) const openApproveModal = () => setOpenModal('approveTx') const closeModal = () => setOpenModal(null) - const thresholdReached = tx.type !== INCOMING_TX_TYPE && threshold <= tx.confirmations.size - const canExecute = tx.type !== INCOMING_TX_TYPE && nonce === tx.nonce + const thresholdReached = !INCOMING_TX_TYPES.includes(tx.type) && threshold <= tx.confirmations.size + const canExecute = !INCOMING_TX_TYPES.includes(tx.type) && nonce === tx.nonce const cancelThresholdReached = !!cancelTx && threshold <= cancelTx.confirmations.size const canExecuteCancel = nonce === tx.nonce @@ -76,7 +76,9 @@ const ExpandedTx = ({ - + Hash: {tx.executionTxHash ? : 'n/a'} @@ -89,7 +91,7 @@ const ExpandedTx = ({ Fee: {tx.fee ? tx.fee : 'n/a'} - {tx.type === INCOMING_TX_TYPE ? ( + {INCOMING_TX_TYPES.includes(tx.type) ? ( <> Created: @@ -128,9 +130,9 @@ const ExpandedTx = ({ )} - {tx.type === INCOMING_TX_TYPE ? : } + {INCOMING_TX_TYPES.includes(tx.type) ? : } - {tx.type !== INCOMING_TX_TYPE && ( + {!INCOMING_TX_TYPES.includes(tx.type) && ( => { const cancelTxsByNonce = cancelTxs.reduce((acc, tx) => acc.set(tx.nonce, tx), Map()) - return transactions.map(tx => { - if (tx.type === INCOMING_TX_TYPE) { + return transactions.map((tx) => { + if (INCOMING_TX_TYPES.includes(tx.type)) { return getIncomingTxTableData(tx) } diff --git a/src/routes/safe/components/Transactions/TxsTable/index.jsx b/src/routes/safe/components/Transactions/TxsTable/index.jsx index 227ca0a9..6745c643 100644 --- a/src/routes/safe/components/Transactions/TxsTable/index.jsx +++ b/src/routes/safe/components/Transactions/TxsTable/index.jsx @@ -67,12 +67,12 @@ const TxsTable = ({ }: Props) => { const [expandedTx, setExpandedTx] = useState(null) - const handleTxExpand = safeTxHash => { - setExpandedTx(prevTx => (prevTx === safeTxHash ? null : safeTxHash)) + const handleTxExpand = (safeTxHash) => { + setExpandedTx((prevTx) => (prevTx === safeTxHash ? null : safeTxHash)) } const columns = generateColumns() - const autoColumns = columns.filter(c => !c.custom) + const autoColumns = columns.filter((c) => !c.custom) const filteredData = getTxTableData(transactions, cancellationTransactions) .sort((tx1, tx2) => { // First order by nonce diff --git a/src/routes/safe/container/actions.js b/src/routes/safe/container/actions.js index 59cf4326..9eb078be 100644 --- a/src/routes/safe/container/actions.js +++ b/src/routes/safe/container/actions.js @@ -4,6 +4,7 @@ import { updateAddressBookEntry } from '~/logic/addressBook/store/actions/update import fetchCollectibles from '~/logic/collectibles/store/actions/fetchCollectibles' import fetchCurrencyValues from '~/logic/currencyValues/store/actions/fetchCurrencyValues' import addViewedSafe from '~/logic/currentSession/store/actions/addViewedSafe' +import activateAssetsByBalance from '~/logic/tokens/store/actions/activateAssetsByBalance' import activateTokensByBalance from '~/logic/tokens/store/actions/activateTokensByBalance' import fetchTokens from '~/logic/tokens/store/actions/fetchTokens' import createTransaction from '~/routes/safe/store/actions/createTransaction' @@ -27,6 +28,7 @@ export type Actions = { fetchEtherBalance: typeof fetchEtherBalance, fetchLatestMasterContractVersion: typeof fetchLatestMasterContractVersion, activateTokensByBalance: typeof activateTokensByBalance, + activateAssetsByBalance: typeof activateAssetsByBalance, checkAndUpdateSafeOwners: typeof checkAndUpdateSafe, fetchCurrencyValues: typeof fetchCurrencyValues, loadAddressBook: typeof loadAddressBookFromStorage, @@ -43,6 +45,7 @@ export default { fetchTokens, fetchTransactions, activateTokensByBalance, + activateAssetsByBalance, updateSafe, fetchEtherBalance, fetchLatestMasterContractVersion, diff --git a/src/routes/safe/container/index.jsx b/src/routes/safe/container/index.jsx index 2eed196d..279b680a 100644 --- a/src/routes/safe/container/index.jsx +++ b/src/routes/safe/container/index.jsx @@ -125,17 +125,19 @@ class SafeView extends React.Component { fetchEtherBalance, fetchTokenBalances, fetchTransactions, + safe, safeUrl, } = this.props checkAndUpdateSafeOwners(safeUrl) fetchTokenBalances(safeUrl, activeTokens) - fetchEtherBalance(safeUrl) + fetchEtherBalance(safe) fetchTransactions(safeUrl) } render() { const { sendFunds, showReceive } = this.state const { + activateAssetsByBalance, activateTokensByBalance, activeTokens, addressBook, @@ -161,6 +163,7 @@ class SafeView extends React.Component { return ( conf.owner.address === userAddress).size === 1 - const userIsSafeOwner = safe.owners.filter(owner => owner.address === userAddress).size === 1 + const userConfirmed = tx.confirmations.filter((conf) => conf.owner.address === userAddress).size === 1 + const userIsSafeOwner = safe.owners.filter((owner) => owner.address === userAddress).size === 1 txStatus = !userConfirmed && userIsSafeOwner ? 'awaiting_your_confirmation' : 'awaiting_confirmations' } @@ -93,7 +93,7 @@ export const extendedSafeTokensSelector: Selector, balances: Map, tokensList: Map, ethAsToken: Token) => { - const extendedTokens = Map().withMutations(map => { + const extendedTokens = Map().withMutations((map) => { safeTokens.forEach((tokenAddress: string) => { const baseToken = tokensList.get(tokenAddress) const tokenBalance = balances.get(tokenAddress) @@ -129,8 +129,9 @@ const extendedTransactionsSelector: Selector< if (!tx.isExecuted) { if ( - cancellationTransactionsByNonce.get(tx.nonce) && - cancellationTransactionsByNonce.get(tx.nonce).get('isExecuted') + (cancellationTransactionsByNonce.get(tx.nonce) && + cancellationTransactionsByNonce.get(tx.nonce).get('isExecuted')) || + transactions.find((safeTx) => tx.nonce === safeTx.nonce && safeTx.isExecuted) ) { extendedTx = tx.set('cancelled', true) } diff --git a/src/routes/safe/store/actions/createTransaction.js b/src/routes/safe/store/actions/createTransaction.js index c9e888da..acebf417 100644 --- a/src/routes/safe/store/actions/createTransaction.js +++ b/src/routes/safe/store/actions/createTransaction.js @@ -1,6 +1,7 @@ // @flow import { push } from 'connected-react-router' import type { GetState, Dispatch as ReduxDispatch } from 'redux' +import semverSatisfies from 'semver/functions/satisfies' import { onboardUser } from '~/components/ConnectButton' import { getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts' @@ -8,22 +9,22 @@ import { type NotificationsQueue, getNotificationsFromTxType, showSnackbar } fro import { CALL, type NotifiedTransaction, - TX_TYPE_CONFIRMATION, - TX_TYPE_EXECUTION, getApprovalTransaction, getExecutionTransaction, saveTxToHistory, } from '~/logic/safe/transactions' +import { SAFE_VERSION_FOR_OFFCHAIN_SIGNATURES, tryOffchainSigning } from '~/logic/safe/transactions/offchainSigner' +import { getCurrentSafeVersion } from '~/logic/safe/utils/safeVersion' import { ZERO_ADDRESS } from '~/logic/wallets/ethAddresses' import { EMPTY_DATA } from '~/logic/wallets/ethTransactions' -import { userAccountSelector } from '~/logic/wallets/store/selectors' +import { providerSelector } from '~/logic/wallets/store/selectors' import { SAFELIST_ADDRESS } from '~/routes/routes' import fetchTransactions from '~/routes/safe/store/actions/fetchTransactions' import { getLastTx, getNewTxNonce, shouldExecuteTransaction } from '~/routes/safe/store/actions/utils' import { type GlobalState } from '~/store' import { getErrorMessage } from '~/test/utils/ethereumErrors' -type CreateTransactionArgs = { +export type CreateTransactionArgs = { safeAddress: string, to: string, valueInWei: string, @@ -59,11 +60,12 @@ const createTransaction = ({ const ready = await onboardUser() if (!ready) return - const from = userAccountSelector(state) + const { account: from, hardwareWallet, smartContractWallet } = providerSelector(state) const safeInstance = await getGnosisSafeInstanceAt(safeAddress) const lastTx = await getLastTx(safeAddress) const nonce = await getNewTxNonce(txNonce, lastTx, safeInstance) const isExecution = await shouldExecuteTransaction(safeInstance, nonce, lastTx) + const safeVersion = await getCurrentSafeVersion(safeInstance) // https://docs.gnosis.io/safe/docs/docs5/#pre-validated-signatures const sigs = `0x000000000000000000000000${from.replace( @@ -94,6 +96,34 @@ const createTransaction = ({ } try { + // Here we're checking that safe contract version is greater or equal 1.1.1, but + // theoretically EIP712 should also work for 1.0.0 contracts + // Also, offchain signatures are not working for ledger/trezor wallet because of a bug in their library: + // https://github.com/LedgerHQ/ledgerjs/issues/378 + // Couldn't find an issue for trezor but the error is almost the same + const canTryOffchainSigning = + !isExecution && + !smartContractWallet && + !hardwareWallet && + semverSatisfies(safeVersion, SAFE_VERSION_FOR_OFFCHAIN_SIGNATURES) + if (canTryOffchainSigning) { + const signature = await tryOffchainSigning({ ...txArgs, safeAddress }) + + if (signature) { + closeSnackbar(beforeExecutionKey) + + await saveTxToHistory({ + ...txArgs, + signature, + origin, + }) + showSnackbar(notificationsQueue.afterExecution.moreConfirmationsNeeded, enqueueSnackbar, closeSnackbar) + + dispatch(fetchTransactions(safeAddress)) + return + } + } + tx = isExecution ? await getExecutionTransaction(txArgs) : await getApprovalTransaction(txArgs) const sendParams = { from, value: 0 } @@ -110,7 +140,7 @@ const createTransaction = ({ await tx .send(sendParams) - .once('transactionHash', async hash => { + .once('transactionHash', async (hash) => { txHash = hash closeSnackbar(beforeExecutionKey) @@ -120,7 +150,6 @@ const createTransaction = ({ await saveTxToHistory({ ...txArgs, txHash, - type: isExecution ? TX_TYPE_EXECUTION : TX_TYPE_CONFIRMATION, origin, }) dispatch(fetchTransactions(safeAddress)) @@ -128,10 +157,10 @@ const createTransaction = ({ console.error(err) } }) - .on('error', error => { + .on('error', (error) => { console.error('Tx error: ', error) }) - .then(receipt => { + .then((receipt) => { closeSnackbar(pendingExecutionKey) showSnackbar( isExecution diff --git a/src/routes/safe/store/actions/fetchEtherBalance.js b/src/routes/safe/store/actions/fetchEtherBalance.js index 59ef9be0..9fdb8519 100644 --- a/src/routes/safe/store/actions/fetchEtherBalance.js +++ b/src/routes/safe/store/actions/fetchEtherBalance.js @@ -3,13 +3,17 @@ import type { Dispatch as ReduxDispatch } from 'redux' import { getBalanceInEtherOf } from '~/logic/wallets/getWeb3' import updateSafe from '~/routes/safe/store/actions/updateSafe' -import { type GlobalState } from '~/store/index' +import type { Safe } from '~/routes/safe/store/models/safe' +import { type GlobalState } from '~/store' -const fetchEtherBalance = (safeAddress: string) => async (dispatch: ReduxDispatch) => { +const fetchEtherBalance = (safe: Safe) => async (dispatch: ReduxDispatch) => { try { - const ethBalance = await getBalanceInEtherOf(safeAddress) + const { address, ethBalance } = safe + const newEthBalance = await getBalanceInEtherOf(address) - dispatch(updateSafe({ address: safeAddress, ethBalance })) + if (newEthBalance !== ethBalance) { + dispatch(updateSafe({ address, ethBalance: newEthBalance })) + } } catch (err) { // eslint-disable-next-line console.error('Error when fetching Ether balance:', err) diff --git a/src/routes/safe/store/actions/fetchSafe.js b/src/routes/safe/store/actions/fetchSafe.js index 93952555..0c4eeac5 100644 --- a/src/routes/safe/store/actions/fetchSafe.js +++ b/src/routes/safe/store/actions/fetchSafe.js @@ -69,24 +69,28 @@ export const checkAndUpdateSafe = (safeAdd: string) => async (dispatch: ReduxDis const remoteOwners = await gnosisSafe.getOwners() // Converts from [ { address, ownerName} ] to address array - const localOwners = localSafe.owners.map(localOwner => localOwner.address) + const localOwners = localSafe.owners.map((localOwner) => localOwner.address) + const localThreshold = localSafe.threshold // Updates threshold values - const threshold = await gnosisSafe.getThreshold() - localSafe.threshold = threshold.toNumber() + const remoteThreshold = await gnosisSafe.getThreshold() + localSafe.threshold = remoteThreshold.toNumber() + + if (localThreshold !== remoteThreshold.toNumber()) { + dispatch(updateSafeThreshold({ safeAddress, threshold: remoteThreshold.toNumber() })) + } - dispatch(updateSafeThreshold({ safeAddress, threshold: threshold.toNumber() })) // If the remote owners does not contain a local address, we remove that local owner - localOwners.forEach(localAddress => { - const remoteOwnerIndex = remoteOwners.findIndex(remoteAddress => sameAddress(remoteAddress, localAddress)) + localOwners.forEach((localAddress) => { + const remoteOwnerIndex = remoteOwners.findIndex((remoteAddress) => sameAddress(remoteAddress, localAddress)) if (remoteOwnerIndex === -1) { dispatch(removeSafeOwner({ safeAddress, ownerAddress: localAddress })) } }) // If the remote has an owner that we don't have locally, we add it - remoteOwners.forEach(remoteAddress => { - const localOwnerIndex = localOwners.findIndex(localAddress => sameAddress(remoteAddress, localAddress)) + remoteOwners.forEach((remoteAddress) => { + const localOwnerIndex = localOwners.findIndex((localAddress) => sameAddress(remoteAddress, localAddress)) if (localOwnerIndex === -1) { dispatch( addSafeOwner({ diff --git a/src/routes/safe/store/actions/fetchTokenBalances.js b/src/routes/safe/store/actions/fetchTokenBalances.js index a5636589..ed8a0174 100644 --- a/src/routes/safe/store/actions/fetchTokenBalances.js +++ b/src/routes/safe/store/actions/fetchTokenBalances.js @@ -5,10 +5,61 @@ import type { Dispatch as ReduxDispatch } from 'redux' import updateSafe from './updateSafe' -import { getStandardTokenContract } from '~/logic/tokens/store/actions/fetchTokens' +import { getOnlyBalanceToken, getStandardTokenContract } from '~/logic/tokens/store/actions/fetchTokens' import { type Token } from '~/logic/tokens/store/model/token' import { ETH_ADDRESS } from '~/logic/tokens/utils/tokenHelpers' +import { sameAddress } from '~/logic/wallets/ethAddresses' +import { ETHEREUM_NETWORK, getWeb3 } from '~/logic/wallets/getWeb3' import { type GlobalState } from '~/store/index' +import { NETWORK } from '~/utils/constants' + +// List of all the non-standard ERC20 tokens +const nonStandardERC20 = [ + // DATAcoin + { network: ETHEREUM_NETWORK.RINKEBY, address: '0x0cf0ee63788a0849fe5297f3407f701e122cc023' }, +] + +// This is done due to an issues with DATAcoin contract in Rinkeby +// https://rinkeby.etherscan.io/address/0x0cf0ee63788a0849fe5297f3407f701e122cc023#readContract +// It doesn't have a `balanceOf` method implemented. +const isStandardERC20 = (address: string): boolean => { + return !nonStandardERC20.find((token) => sameAddress(address, token.address) && sameAddress(NETWORK, token.network)) +} + +const getTokenBalances = (tokens: List, safeAddress: string) => { + const web3 = getWeb3() + const batch = new web3.BatchRequest() + + const safeTokens = tokens.toJS().filter(({ address }) => address !== ETH_ADDRESS) + const safeTokensBalances = safeTokens.map(({ address, decimals }: any) => { + const onlyBalanceToken = getOnlyBalanceToken() + onlyBalanceToken.options.address = address + + // As a fallback, we're using `balances` + const method = isStandardERC20(address) ? 'balanceOf' : 'balances' + + return new Promise((resolve) => { + const request = onlyBalanceToken.methods[method](safeAddress).call.request((error, balance) => { + if (error) { + // if there's no balance, we log the error, but `resolve` with a default '0' + console.error('No balance method found', error) + resolve('0') + } else { + resolve({ + address, + balance: new BigNumber(balance).div(`1e${decimals}`).toFixed(), + }) + } + }) + + batch.add(request) + }) + }) + + batch.execute() + + return Promise.all(safeTokensBalances) +} export const calculateBalanceOf = async (tokenAddress: string, safeAddress: string, decimals: number = 18) => { if (tokenAddress === ETH_ADDRESS) { @@ -34,17 +85,9 @@ const fetchTokenBalances = (safeAddress: string, tokens: List) => async ( return } try { - const withBalances = await Promise.all( - tokens.map(async token => { - const balance = await calculateBalanceOf(token.address, safeAddress, token.decimals) - return { - address: token.address, - balance, - } - }), - ) + const withBalances = await getTokenBalances(tokens, safeAddress) - const balances = Map().withMutations(map => { + const balances = Map().withMutations((map) => { withBalances.forEach(({ address, balance }) => { map.set(address, balance) }) diff --git a/src/routes/safe/store/actions/fetchTransactions.js b/src/routes/safe/store/actions/fetchTransactions.js index 1772f2a0..f1363dec 100644 --- a/src/routes/safe/store/actions/fetchTransactions.js +++ b/src/routes/safe/store/actions/fetchTransactions.js @@ -11,7 +11,7 @@ import { decodeParamsFromSafeMethod } from '~/logic/contracts/methodIds' import { buildIncomingTxServiceUrl } from '~/logic/safe/transactions/incomingTxHistory' import { type TxServiceType, buildTxServiceUrl } from '~/logic/safe/transactions/txHistory' import { getLocalSafe } from '~/logic/safe/utils' -import { getHumanFriendlyToken } from '~/logic/tokens/store/actions/fetchTokens' +import { getTokenInfos } from '~/logic/tokens/store/actions/fetchTokens' import { ALTERNATIVE_TOKEN_ABI } from '~/logic/tokens/utils/alternativeAbi' import { DECIMALS_METHOD_HASH, @@ -80,7 +80,7 @@ export const buildTransactionFrom = async (safeAddress: string, tx: TxServiceMod let ownerName = 'UNKNOWN' if (owners) { - const storedOwner = owners.find(owner => sameAddress(conf.owner, owner.address)) + const storedOwner = owners.find((owner) => sameAddress(conf.owner, owner.address)) if (storedOwner) { ownerName = storedOwner.name @@ -111,9 +111,9 @@ export const buildTransactionFrom = async (safeAddress: string, tx: TxServiceMod let refundSymbol = 'ETH' let decimals = 18 if (tx.gasToken !== ZERO_ADDRESS) { - const gasToken = await (await getHumanFriendlyToken()).at(tx.gasToken) - refundSymbol = await gasToken.symbol() - decimals = await gasToken.decimals() + const gasToken = await getTokenInfos(tx.gasToken) + refundSymbol = gasToken.symbol + decimals = gasToken.decimals } const feeString = (tx.gasPrice * (tx.baseGas + tx.safeTxGas)).toString().padStart(decimals, 0) @@ -131,10 +131,10 @@ export const buildTransactionFrom = async (safeAddress: string, tx: TxServiceMod let decimals = 18 let decodedParams if (isSendTokenTx) { - const tokenContract = await getHumanFriendlyToken() - const tokenInstance = await tokenContract.at(tx.to) + const tokenInstance = await getTokenInfos(tx.to) try { - ;[symbol, decimals] = await Promise.all([tokenInstance.symbol(), tokenInstance.decimals()]) + symbol = tokenInstance.symbol + decimals = tokenInstance.decimals } catch (err) { const alternativeTokenInstance = new web3.eth.Contract(ALTERNATIVE_TOKEN_ABI, tx.to) const [tokenSymbol, tokenDecimals] = await Promise.all([ @@ -222,23 +222,21 @@ export const buildIncomingTransactionFrom = async (tx: IncomingTxServiceModel) = let symbol = 'ETH' let decimals = 18 - const fee = await web3.eth.getTransaction(tx.transactionHash).then(({ gas, gasPrice }) => - bn(gas) - .div(gasPrice) - .toFixed(), - ) + const fee = await web3.eth + .getTransaction(tx.transactionHash) + .then(({ gas, gasPrice }) => bn(gas).div(gasPrice).toFixed()) if (tx.tokenAddress) { try { - const tokenContract = await getHumanFriendlyToken() - const tokenInstance = await tokenContract.at(tx.tokenAddress) - const [tokenSymbol, tokenDecimals] = await Promise.all([tokenInstance.symbol(), tokenInstance.decimals()]) - symbol = tokenSymbol - decimals = tokenDecimals + const tokenInstance = await getTokenInfos(tx.tokenAddress) + symbol = tokenInstance.symbol + decimals = tokenInstance.decimals } catch (err) { try { const { methods } = new web3.eth.Contract(ALTERNATIVE_TOKEN_ABI, tx.tokenAddress) - const [tokenSymbol, tokenDecimals] = await Promise.all([methods.symbol, methods.decimals].map(m => m().call())) + const [tokenSymbol, tokenDecimals] = await Promise.all( + [methods.symbol, methods.decimals].map((m) => m().call()), + ) symbol = web3.utils.hexToString(tokenSymbol) decimals = tokenDecimals } catch (e) { @@ -269,24 +267,46 @@ export type SafeTransactionsType = { cancel: Map>, } +let etagSafeTransactions = null +let etagCachedSafeIncommingTransactions = null export const loadSafeTransactions = async (safeAddress: string): Promise => { let transactions: TxServiceModel[] = addMockSafeCreationTx(safeAddress) try { + const config = etagSafeTransactions + ? { + headers: { + 'If-None-Match': etagSafeTransactions, + }, + } + : undefined + const url = buildTxServiceUrl(safeAddress) - const response = await axios.get(url) + const response = await axios.get(url, config) if (response.data.count > 0) { transactions = transactions.concat(response.data.results) + if (etagSafeTransactions === response.headers.etag) { + // The txs are the same, we can return the cached ones + return + } + etagSafeTransactions = response.headers.etag } } catch (err) { - console.error(`Requests for outgoing transactions for ${safeAddress} failed with 404`, err) + if (err && err.response && err.response.status === 304) { + // NOTE: this is the expected implementation, currently the backend is not returning 304. + // So I check if the returned etag is the same instead (see above) + return + } else { + console.error(`Requests for outgoing transactions for ${safeAddress} failed with 404`, err) + } } + // In case that the etags don't match, we parse the new transactions and save them to the cache const txsRecord: Array> = await Promise.all( transactions.map((tx: TxServiceModel) => buildTransactionFrom(safeAddress, tx)), ) - const groupedTxs = List(txsRecord).groupBy(tx => (tx.get('cancellationTx') ? 'cancel' : 'outgoing')) + const groupedTxs = List(txsRecord).groupBy((tx) => (tx.get('cancellationTx') ? 'cancel' : 'outgoing')) return { outgoing: Map().set(safeAddress, groupedTxs.get('outgoing')), @@ -297,26 +317,50 @@ export const loadSafeTransactions = async (safeAddress: string): Promise { let incomingTransactions: IncomingTxServiceModel[] = [] try { + const config = etagCachedSafeIncommingTransactions + ? { + headers: { + 'If-None-Match': etagCachedSafeIncommingTransactions, + }, + } + : undefined const url = buildIncomingTxServiceUrl(safeAddress) - const response = await axios.get(url) + const response = await axios.get(url, config) if (response.data.count > 0) { incomingTransactions = response.data.results + if (etagCachedSafeIncommingTransactions === response.headers.etag) { + // The txs are the same, we can return the cached ones + return + } + etagCachedSafeIncommingTransactions = response.headers.etag } } catch (err) { - console.error(`Requests for incoming transactions for ${safeAddress} failed with 404`, err) + if (err && err.response && err.response.status === 304) { + // We return cached transactions + return + } else { + console.error(`Requests for incoming transactions for ${safeAddress} failed with 404`, err) + } } const incomingTxsRecord = await Promise.all(incomingTransactions.map(buildIncomingTransactionFrom)) - return Map().set(safeAddress, List(incomingTxsRecord)) } export default (safeAddress: string) => async (dispatch: ReduxDispatch) => { web3 = await getWeb3() - const { cancel, outgoing }: SafeTransactionsType = await loadSafeTransactions(safeAddress) - const incomingTransactions: Map> = await loadSafeIncomingTransactions(safeAddress) - dispatch(addCancellationTransactions(cancel)) - dispatch(addTransactions(outgoing)) - dispatch(addIncomingTransactions(incomingTransactions)) + const transactions: SafeTransactionsType | undefined = await loadSafeTransactions(safeAddress) + if (transactions) { + const { cancel, outgoing } = transactions + dispatch(addCancellationTransactions(cancel)) + dispatch(addTransactions(outgoing)) + } + const incomingTransactions: Map> | undefined = await loadSafeIncomingTransactions( + safeAddress, + ) + + if (incomingTransactions) { + dispatch(addIncomingTransactions(incomingTransactions)) + } } diff --git a/src/routes/safe/store/actions/loadSafesFromStorage.js b/src/routes/safe/store/actions/loadSafesFromStorage.js index 6704387b..c6f6244e 100644 --- a/src/routes/safe/store/actions/loadSafesFromStorage.js +++ b/src/routes/safe/store/actions/loadSafesFromStorage.js @@ -14,7 +14,7 @@ const loadSafesFromStorage = () => async (dispatch: ReduxDispatch) const safes: ?{ [key: string]: SafeProps } = await loadFromStorage(SAFES_KEY) if (safes) { - Object.values(safes).forEach(safeProps => { + Object.values(safes).forEach((safeProps) => { dispatch(addSafe(buildSafe(safeProps))) }) } diff --git a/src/routes/safe/store/actions/processTransaction.js b/src/routes/safe/store/actions/processTransaction.js index 30dc2b14..263e0a05 100644 --- a/src/routes/safe/store/actions/processTransaction.js +++ b/src/routes/safe/store/actions/processTransaction.js @@ -1,18 +1,19 @@ // @flow import type { Dispatch as ReduxDispatch } from 'redux' +import semverSatisfies from 'semver/functions/satisfies' import { getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts' import { type NotificationsQueue, getNotificationsFromTxType, showSnackbar } from '~/logic/notifications' import { generateSignaturesFromTxConfirmations } from '~/logic/safe/safeTxSigner' import { type NotifiedTransaction, - TX_TYPE_CONFIRMATION, - TX_TYPE_EXECUTION, getApprovalTransaction, getExecutionTransaction, saveTxToHistory, } from '~/logic/safe/transactions' -import { userAccountSelector } from '~/logic/wallets/store/selectors' +import { SAFE_VERSION_FOR_OFFCHAIN_SIGNATURES, tryOffchainSigning } from '~/logic/safe/transactions/offchainSigner' +import { getCurrentSafeVersion } from '~/logic/safe/utils/safeVersion' +import { providerSelector } from '~/logic/wallets/store/selectors' import fetchSafe from '~/routes/safe/store/actions/fetchSafe' import fetchTransactions from '~/routes/safe/store/actions/fetchTransactions' import { getLastTx, getNewTxNonce, shouldExecuteTransaction } from '~/routes/safe/store/actions/utils' @@ -41,11 +42,12 @@ const processTransaction = ({ }: ProcessTransactionArgs) => async (dispatch: ReduxDispatch, getState: Function) => { const state: GlobalState = getState() - const from = userAccountSelector(state) + const { account: from, hardwareWallet, smartContractWallet } = providerSelector(state) const safeInstance = await getGnosisSafeInstanceAt(safeAddress) const lastTx = await getLastTx(safeAddress) const nonce = await getNewTxNonce(null, lastTx, safeInstance) const isExecution = approveAndExecute || (await shouldExecuteTransaction(safeInstance, nonce, lastTx)) + const safeVersion = await getCurrentSafeVersion(safeInstance) let sigs = generateSignaturesFromTxConfirmations(tx.confirmations, approveAndExecute && userAddress) // https://docs.gnosis.io/safe/docs/docs5/#pre-validated-signatures @@ -79,6 +81,34 @@ const processTransaction = ({ } try { + // Here we're checking that safe contract version is greater or equal 1.1.1, but + // theoretically EIP712 should also work for 1.0.0 contracts + // Also, offchain signatures are not working for ledger/trezor wallet because of a bug in their library: + // https://github.com/LedgerHQ/ledgerjs/issues/378 + // Couldn't find an issue for trezor but the error is almost the same + const canTryOffchainSigning = + !isExecution && + !smartContractWallet && + !hardwareWallet && + semverSatisfies(safeVersion, SAFE_VERSION_FOR_OFFCHAIN_SIGNATURES) + if (canTryOffchainSigning) { + const signature = await tryOffchainSigning({ ...txArgs, safeAddress }) + + if (signature) { + closeSnackbar(beforeExecutionKey) + + await saveTxToHistory({ + ...txArgs, + signature, + origin, + }) + showSnackbar(notificationsQueue.afterExecution.moreConfirmationsNeeded, enqueueSnackbar, closeSnackbar) + + dispatch(fetchTransactions(safeAddress)) + return + } + } + transaction = isExecution ? await getExecutionTransaction(txArgs) : await getApprovalTransaction(txArgs) const sendParams = { from, value: 0 } @@ -95,7 +125,7 @@ const processTransaction = ({ await transaction .send(sendParams) - .once('transactionHash', async hash => { + .once('transactionHash', async (hash) => { txHash = hash closeSnackbar(beforeExecutionKey) @@ -105,17 +135,16 @@ const processTransaction = ({ await saveTxToHistory({ ...txArgs, txHash, - type: isExecution ? TX_TYPE_EXECUTION : TX_TYPE_CONFIRMATION, }) dispatch(fetchTransactions(safeAddress)) } catch (err) { console.error(err) } }) - .on('error', error => { + .on('error', (error) => { console.error('Processing transaction error: ', error) }) - .then(receipt => { + .then((receipt) => { closeSnackbar(pendingExecutionKey) showSnackbar( diff --git a/src/routes/safe/store/actions/updateActiveAssets.js b/src/routes/safe/store/actions/updateActiveAssets.js new file mode 100644 index 00000000..9e238fea --- /dev/null +++ b/src/routes/safe/store/actions/updateActiveAssets.js @@ -0,0 +1,25 @@ +// @flow +import { Set } from 'immutable' +import type { Dispatch as ReduxDispatch } from 'redux' + +import updateSafe from './updateSafe' + +import { type GlobalState } from '~/store' + +// the selector uses ownProps argument/router props to get the address of the safe +// so in order to use it I had to recreate the same structure +// const generateMatchProps = (safeAddress: string) => ({ +// match: { +// params: { +// [SAFE_PARAM_ADDRESS]: safeAddress, +// }, +// }, +// }) + +const updateActiveAssets = (safeAddress: string, activeAssets: Set) => async ( + dispatch: ReduxDispatch, +) => { + dispatch(updateSafe({ address: safeAddress, activeAssets })) +} + +export default updateActiveAssets diff --git a/src/routes/safe/store/actions/updateBlacklistedAssets.js b/src/routes/safe/store/actions/updateBlacklistedAssets.js new file mode 100644 index 00000000..feff809b --- /dev/null +++ b/src/routes/safe/store/actions/updateBlacklistedAssets.js @@ -0,0 +1,15 @@ +// @flow +import { Set } from 'immutable' +import type { Dispatch as ReduxDispatch } from 'redux' + +import updateSafe from './updateSafe' + +import { type GlobalState } from '~/store' + +const updateBlacklistedAssets = (safeAddress: string, blacklistedAssets: Set) => async ( + dispatch: ReduxDispatch, +) => { + dispatch(updateSafe({ address: safeAddress, blacklistedAssets })) +} + +export default updateBlacklistedAssets diff --git a/src/routes/safe/store/middleware/notificationsMiddleware.js b/src/routes/safe/store/middleware/notificationsMiddleware.js index 63e754d9..80962bea 100644 --- a/src/routes/safe/store/middleware/notificationsMiddleware.js +++ b/src/routes/safe/store/middleware/notificationsMiddleware.js @@ -7,7 +7,7 @@ import { NOTIFICATIONS, enhanceSnackbarForAction } from '~/logic/notifications' import closeSnackbarAction from '~/logic/notifications/store/actions/closeSnackbar' import enqueueSnackbar from '~/logic/notifications/store/actions/enqueueSnackbar' import { getAwaitingTransactions } from '~/logic/safe/transactions/awaitingTransactions' -import { getSafeVersion } from '~/logic/safe/utils/safeVersion' +import { getSafeVersionInfo } from '~/logic/safe/utils/safeVersion' import { isUserOwner } from '~/logic/wallets/ethAddresses' import { userAccountSelector } from '~/logic/wallets/store/selectors' import { getIncomingTxAmount } from '~/routes/safe/components/Transactions/TxsTable/columns' @@ -18,9 +18,49 @@ import { ADD_TRANSACTIONS } from '~/routes/safe/store/actions/addTransactions' import updateSafe from '~/routes/safe/store/actions/updateSafe' import { safeParamAddressFromStateSelector, safesMapSelector } from '~/routes/safe/store/selectors' import { type GlobalState } from '~/store/' +import { loadFromStorage, saveToStorage } from '~/utils/storage' const watchedActions = [ADD_TRANSACTIONS, ADD_INCOMING_TRANSACTIONS, ADD_SAFE] +const sendAwaitingTransactionNotification = async ( + dispatch: Function, + safeAddress: string, + awaitingTxsSubmissionDateList: List[], + notificationKey: string, + notificationClickedCb: Function, +) => { + const LAST_TIME_USED_LOGGED_IN_ID = 'LAST_TIME_USED_LOGGED_IN_ID' + if (!dispatch || !safeAddress || !awaitingTxsSubmissionDateList || !notificationKey) { + return + } + if (awaitingTxsSubmissionDateList.size === 0) { + return + } + + let lastTimeUserLoggedInForSafes = (await loadFromStorage(LAST_TIME_USED_LOGGED_IN_ID)) || [] + let lastTimeUserLoggedIn = + lastTimeUserLoggedInForSafes && lastTimeUserLoggedInForSafes[safeAddress] + ? lastTimeUserLoggedInForSafes[safeAddress] + : null + + const filteredDuplicatedAwaitingTxList = awaitingTxsSubmissionDateList.filter((submissionDate) => { + return lastTimeUserLoggedIn ? new Date(submissionDate) > new Date(lastTimeUserLoggedIn) : true + }) + + if (filteredDuplicatedAwaitingTxList.size === 0) { + return + } + dispatch( + enqueueSnackbar(enhanceSnackbarForAction(NOTIFICATIONS.TX_WAITING_MSG, notificationKey, notificationClickedCb)), + ) + + lastTimeUserLoggedInForSafes = { + ...lastTimeUserLoggedInForSafes, + [safeAddress]: lastTimeUserLoggedIn || new Date(), + } + await saveToStorage(LAST_TIME_USED_LOGGED_IN_ID, lastTimeUserLoggedInForSafes) +} + const notificationsMiddleware = (store: Store) => (next: Function) => async (action: Action<*>) => { const handledAction = next(action) const { dispatch } = store @@ -41,23 +81,28 @@ const notificationsMiddleware = (store: Store) => (next: Function) cancellationTransactionsByNonce, userAddress, ) - const awaitingTransactionsList = awaitingTransactions.get(safeAddress, List([])) + const awaitingTxsSubmissionDateList = awaitingTransactions + .get(safeAddress, List([])) + .map((tx) => tx.submissionDate) + const safes = safesMapSelector(state) const currentSafe = safes.get(safeAddress) - if (!isUserOwner(currentSafe, userAddress) || awaitingTransactionsList.size === 0) { + if (!isUserOwner(currentSafe, userAddress) || awaitingTxsSubmissionDateList.size === 0) { break } - - const notificationKey = `${safeAddress}-${userAddress}` + const notificationKey = `${safeAddress}-awaiting` const onNotificationClicked = () => { dispatch(closeSnackbarAction({ key: notificationKey })) dispatch(push(`/safes/${safeAddress}/transactions`)) } - dispatch( - enqueueSnackbar( - enhanceSnackbarForAction(NOTIFICATIONS.TX_WAITING_MSG, notificationKey, onNotificationClicked), - ), + + await sendAwaitingTransactionNotification( + dispatch, + safeAddress, + awaitingTxsSubmissionDateList, + notificationKey, + onNotificationClicked, ) break @@ -68,7 +113,7 @@ const notificationsMiddleware = (store: Store) => (next: Function) const viewedSafes = state.currentSession ? state.currentSession.get('viewedSafes') : [] const recurringUser = viewedSafes.includes(safeAddress) - const newIncomingTransactions = incomingTransactions.filter(tx => tx.blockNumber > latestIncomingTxBlock) + const newIncomingTransactions = incomingTransactions.filter((tx) => tx.blockNumber > latestIncomingTxBlock) const { message, ...TX_INCOMING_MSG } = NOTIFICATIONS.TX_INCOMING_MSG @@ -83,7 +128,7 @@ const notificationsMiddleware = (store: Store) => (next: Function) ), ) } else { - newIncomingTransactions.forEach(tx => { + newIncomingTransactions.forEach((tx) => { dispatch( enqueueSnackbar( enhanceSnackbarForAction({ @@ -111,7 +156,7 @@ const notificationsMiddleware = (store: Store) => (next: Function) const state: GlobalState = store.getState() const currentSafeAddress = safeParamAddressFromStateSelector(state) const isUserOwner = grantedSelector(state) - const { needUpdate } = await getSafeVersion(currentSafeAddress) + const { needUpdate } = await getSafeVersionInfo(currentSafeAddress) const notificationKey = `${currentSafeAddress}` const onNotificationClicked = () => { diff --git a/src/routes/safe/store/middleware/safeStorage.js b/src/routes/safe/store/middleware/safeStorage.js index aec23055..6aca88b8 100644 --- a/src/routes/safe/store/middleware/safeStorage.js +++ b/src/routes/safe/store/middleware/safeStorage.js @@ -2,6 +2,7 @@ import { List } from 'immutable' import type { Action, Store } from 'redux' +import { makeAddressBookEntry } from '~/logic/addressBook/model/addressBook' import { addAddressBookEntry } from '~/logic/addressBook/store/actions/addAddressBookEntry' import { saveDefaultSafe, saveSafes } from '~/logic/safe/utils' import type { Token } from '~/logic/tokens/store/model/token' @@ -35,7 +36,7 @@ const recalculateActiveTokens = (state: GlobalState): void => { const tokens = tokensSelector(state) const activeTokenAddresses = getActiveTokensAddressesForAllSafes(state) - const activeTokens: List = tokens.withMutations(map => { + const activeTokens: List = tokens.withMutations((map) => { map.forEach((token: Token) => { if (!activeTokenAddresses.has(token.address)) { map.remove(token.address) @@ -64,8 +65,8 @@ const safeStorageMware = (store: Store) => (next: Function) => asyn const { safe } = action.payload const ownersArray = safe.owners.toJS() // Adds the owners to the address book - ownersArray.forEach(owner => { - dispatch(addAddressBookEntry({ ...owner, isOwner: true })) + ownersArray.forEach((owner) => { + dispatch(addAddressBookEntry(makeAddressBookEntry({ ...owner, isOwner: true }))) }) break } diff --git a/src/routes/safe/store/models/incomingTransaction.js b/src/routes/safe/store/models/incomingTransaction.js index c7caf01c..a3aedd7c 100644 --- a/src/routes/safe/store/models/incomingTransaction.js +++ b/src/routes/safe/store/models/incomingTransaction.js @@ -2,7 +2,7 @@ import { Record } from 'immutable' import type { RecordFactory, RecordOf } from 'immutable' -export const INCOMING_TX_TYPE = 'incoming' +export const INCOMING_TX_TYPES = ['ERC721_TRANSFER', 'ERC20_TRANSFER', 'ETHER_TRANSFER'] export type IncomingTransactionProps = { blockNumber: number, @@ -53,7 +53,7 @@ export const makeIncomingTransaction: RecordFactory = decimals: 18, fee: '', executionDate: '', - type: INCOMING_TX_TYPE, + type: INCOMING_TX_TYPES, status: 'success', nonce: null, confirmations: null, diff --git a/src/routes/safe/store/models/safe.js b/src/routes/safe/store/models/safe.js index 787f78ae..14792954 100644 --- a/src/routes/safe/store/models/safe.js +++ b/src/routes/safe/store/models/safe.js @@ -11,7 +11,9 @@ export type SafeProps = { owners: List, balances?: Map, activeTokens: Set, + activeAssets: Set, blacklistedTokens: Set, + blacklistedAssets: Set, ethBalance?: string, nonce: number, latestIncomingTxBlock?: number, @@ -28,7 +30,9 @@ const SafeRecord: RecordFactory = Record({ ethBalance: 0, owners: List([]), activeTokens: new Set(), + activeAssets: new Set(), blacklistedTokens: new Set(), + blacklistedAssets: new Set(), balances: Map({}), nonce: 0, latestIncomingTxBlock: 0, diff --git a/src/routes/safe/store/reducer/safe.js b/src/routes/safe/store/reducer/safe.js index 86ea92fd..988a6117 100644 --- a/src/routes/safe/store/reducer/safe.js +++ b/src/routes/safe/store/reducer/safe.js @@ -22,11 +22,13 @@ export const SAFE_REDUCER_ID = 'safes' export type SafeReducerState = Map export const buildSafe = (storedSafe: SafeProps) => { - const names = storedSafe.owners.map(owner => owner.name) - const addresses = storedSafe.owners.map(owner => getWeb3().utils.toChecksumAddress(owner.address)) + const names = storedSafe.owners.map((owner) => owner.name) + const addresses = storedSafe.owners.map((owner) => getWeb3().utils.toChecksumAddress(owner.address)) const owners = buildOwnersFrom(Array.from(names), Array.from(addresses)) const activeTokens = Set(storedSafe.activeTokens) + const activeAssets = Set(storedSafe.activeAssets) const blacklistedTokens = Set(storedSafe.blacklistedTokens) + const blacklistedAssets = Set(storedSafe.blacklistedAssets) const balances = Map(storedSafe.balances) const safe: SafeProps = { @@ -35,6 +37,8 @@ export const buildSafe = (storedSafe: SafeProps) => { balances, activeTokens, blacklistedTokens, + activeAssets, + blacklistedAssets, } return safe @@ -46,20 +50,20 @@ export default handleActions( const safe = action.payload const safeAddress = safe.address - return state.updateIn(['safes', safeAddress], prevSafe => prevSafe.merge(safe)) + return state.updateIn(['safes', safeAddress], (prevSafe) => prevSafe.merge(safe)) }, [ACTIVATE_TOKEN_FOR_ALL_SAFES]: (state: SafeReducerState, action: ActionType): SafeReducerState => { const tokenAddress = action.payload - return state.withMutations(map => { + return state.withMutations((map) => { map .get('safes') .keySeq() - .forEach(safeAddress => { + .forEach((safeAddress) => { const safeActiveTokens = map.getIn(['safes', safeAddress, 'activeTokens']) const activeTokens = safeActiveTokens.add(tokenAddress) - map.updateIn(['safes', safeAddress], prevSafe => prevSafe.merge({ activeTokens })) + map.updateIn(['safes', safeAddress], (prevSafe) => prevSafe.merge({ activeTokens })) }) }) }, @@ -71,7 +75,7 @@ export default handleActions( // with initial props and it would overwrite existing ones if (state.hasIn(['safes', safe.address])) { - return state.updateIn(['safes', safe.address], prevSafe => prevSafe.merge(safe)) + return state.updateIn(['safes', safe.address], (prevSafe) => prevSafe.merge(safe)) } return state.setIn(['safes', safe.address], SafeRecord(safe)) @@ -84,7 +88,7 @@ export default handleActions( [ADD_SAFE_OWNER]: (state: SafeReducerState, action: ActionType): SafeReducerState => { const { ownerAddress, ownerName, safeAddress } = action.payload - return state.updateIn(['safes', safeAddress], prevSafe => + return state.updateIn(['safes', safeAddress], (prevSafe) => prevSafe.merge({ owners: prevSafe.owners.push(makeOwner({ address: ownerAddress, name: ownerName })), }), @@ -93,19 +97,19 @@ export default handleActions( [REMOVE_SAFE_OWNER]: (state: SafeReducerState, action: ActionType): SafeReducerState => { const { ownerAddress, safeAddress } = action.payload - return state.updateIn(['safes', safeAddress], prevSafe => + return state.updateIn(['safes', safeAddress], (prevSafe) => prevSafe.merge({ - owners: prevSafe.owners.filter(o => o.address.toLowerCase() !== ownerAddress.toLowerCase()), + owners: prevSafe.owners.filter((o) => o.address.toLowerCase() !== ownerAddress.toLowerCase()), }), ) }, [REPLACE_SAFE_OWNER]: (state: SafeReducerState, action: ActionType): SafeReducerState => { const { oldOwnerAddress, ownerAddress, ownerName, safeAddress } = action.payload - return state.updateIn(['safes', safeAddress], prevSafe => + return state.updateIn(['safes', safeAddress], (prevSafe) => prevSafe.merge({ owners: prevSafe.owners - .filter(o => o.address.toLowerCase() !== oldOwnerAddress.toLowerCase()) + .filter((o) => o.address.toLowerCase() !== oldOwnerAddress.toLowerCase()) .push(makeOwner({ address: ownerAddress, name: ownerName })), }), ) @@ -113,18 +117,18 @@ export default handleActions( [EDIT_SAFE_OWNER]: (state: SafeReducerState, action: ActionType): SafeReducerState => { const { ownerAddress, ownerName, safeAddress } = action.payload - return state.updateIn(['safes', safeAddress], prevSafe => { + return state.updateIn(['safes', safeAddress], (prevSafe) => { const ownerToUpdateIndex = prevSafe.owners.findIndex( - o => o.address.toLowerCase() === ownerAddress.toLowerCase(), + (o) => o.address.toLowerCase() === ownerAddress.toLowerCase(), ) - const updatedOwners = prevSafe.owners.update(ownerToUpdateIndex, owner => owner.set('name', ownerName)) + const updatedOwners = prevSafe.owners.update(ownerToUpdateIndex, (owner) => owner.set('name', ownerName)) return prevSafe.merge({ owners: updatedOwners }) }) }, [UPDATE_SAFE_THRESHOLD]: (state: SafeReducerState, action: ActionType): SafeReducerState => { const { safeAddress, threshold } = action.payload - return state.updateIn(['safes', safeAddress], prevSafe => prevSafe.set('threshold', threshold)) + return state.updateIn(['safes', safeAddress], (prevSafe) => prevSafe.set('threshold', threshold)) }, [SET_DEFAULT_SAFE]: (state: SafeReducerState, action: ActionType): SafeReducerState => state.set('defaultSafe', action.payload), diff --git a/src/routes/safe/store/selectors/index.js b/src/routes/safe/store/selectors/index.js index ec1c023e..ff6c677d 100644 --- a/src/routes/safe/store/selectors/index.js +++ b/src/routes/safe/store/selectors/index.js @@ -191,6 +191,26 @@ export const safeActiveTokensSelector: OutputSelector> = createSelector( + safeSelector, + (safe: Safe) => { + if (!safe) { + return List() + } + return safe.activeAssets + }, +) + +export const safeActiveAssetsListSelector: OutputSelector> = createSelector( + safeActiveAssetsSelector, + (safeList: []) => { + if (!safeList) { + return Set([]) + } + return Set(safeList) + }, +) + export const safeBlacklistedTokensSelector: OutputSelector> = createSelector( safeSelector, (safe: Safe) => { @@ -202,12 +222,29 @@ export const safeBlacklistedTokensSelector: OutputSelector> = createSelector( + safeSelector, + (safe: Safe) => { + if (!safe) { + return List() + } + + return safe.blacklistedAssets + }, +) + export const safeActiveTokensSelectorBySafe = (safeAddress: string, safes: Map): List => safes.get(safeAddress).get('activeTokens') export const safeBlacklistedTokensSelectorBySafe = (safeAddress: string, safes: Map): List => safes.get(safeAddress).get('blacklistedTokens') +export const safeActiveAssetsSelectorBySafe = (safeAddress: string, safes: Map): List => + safes.get(safeAddress).get('activeAssets') + +export const safeBlacklistedAssetsSelectorBySafe = (safeAddress: string, safes: Map): List => + safes.get(safeAddress).get('blacklistedAssets') + export const safeBalancesSelector: OutputSelector> = createSelector( safeSelector, (safe: Safe) => { @@ -222,9 +259,9 @@ export const safeBalancesSelector: OutputSelector> = createSelector( safesListSelector, (safes: List) => { - const addresses = Set().withMutations(set => { + const addresses = Set().withMutations((set) => { safes.forEach((safe: Safe) => { - safe.activeTokens.forEach(tokenAddress => { + safe.activeTokens.forEach((tokenAddress) => { set.add(tokenAddress) }) }) @@ -237,9 +274,9 @@ export const getActiveTokensAddressesForAllSafes: OutputSelector> = createSelector( safesListSelector, (safes: List) => { - const addresses = Set().withMutations(set => { + const addresses = Set().withMutations((set) => { safes.forEach((safe: Safe) => { - safe.blacklistedTokens.forEach(tokenAddress => { + safe.blacklistedTokens.forEach((tokenAddress) => { set.add(tokenAddress) }) }) diff --git a/src/utils/constants.js b/src/utils/constants.js index f7d1d1b8..f8c61f29 100644 --- a/src/utils/constants.js +++ b/src/utils/constants.js @@ -1,5 +1,7 @@ // @flow -export const NETWORK = process.env.REACT_APP_NETWORK +import { ETHEREUM_NETWORK } from '~/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 diff --git a/src/utils/googleAnalytics.js b/src/utils/googleAnalytics.js index 6768020d..48ae64c7 100644 --- a/src/utils/googleAnalytics.js +++ b/src/utils/googleAnalytics.js @@ -39,7 +39,7 @@ export const withTracker = (WrappedComponent, options = {}) => { fetchCookiesFromStorage() }, []) - const trackPage = page => { + const trackPage = (page) => { if (!useAnalytics || !analyticsLoaded) { return } diff --git a/src/utils/timer.js b/src/utils/timer.js index aaa8356b..bd260688 100644 --- a/src/utils/timer.js +++ b/src/utils/timer.js @@ -1,2 +1,2 @@ // @flow -export const sleep: Function = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)) +export const sleep: Function = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)) diff --git a/yarn.lock b/yarn.lock index 77df07bb..68fd0df8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -34,7 +34,38 @@ invariant "^2.2.4" semver "^5.5.0" -"@babel/core@7.8.7", "@babel/core@^7.1.0", "@babel/core@^7.7.5": +"@babel/compat-data@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.9.0.tgz#04815556fc90b0c174abd2c0c1bb966faa036a6c" + integrity sha512-zeFQrr+284Ekvd9e7KAX954LkapWiOmQtsfHirhxqfdlX6MEC32iRE+pqUGlYIBchdevaCwvzxWGSy/YBNI85g== + dependencies: + browserslist "^4.9.1" + invariant "^2.2.4" + semver "^5.5.0" + +"@babel/core@7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.9.0.tgz#ac977b538b77e132ff706f3b8a4dbad09c03c56e" + integrity sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/generator" "^7.9.0" + "@babel/helper-module-transforms" "^7.9.0" + "@babel/helpers" "^7.9.0" + "@babel/parser" "^7.9.0" + "@babel/template" "^7.8.6" + "@babel/traverse" "^7.9.0" + "@babel/types" "^7.9.0" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.1" + json5 "^2.1.2" + lodash "^4.17.13" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + +"@babel/core@^7.1.0", "@babel/core@^7.7.5": version "7.8.7" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.7.tgz#b69017d221ccdeb203145ae9da269d72cf102f3b" integrity sha512-rBlqF3Yko9cynC5CCFy6+K/w2N+Sq/ff2BPy+Krp7rHlABIr5epbA7OxVeKoMHB39LZOp1UY5SuLjy6uWi35yA== @@ -65,6 +96,16 @@ lodash "^4.17.13" source-map "^0.5.0" +"@babel/generator@^7.9.0": + version "7.9.3" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.3.tgz#7c8b2956c6f68b3ab732bd16305916fbba521d94" + integrity sha512-RpxM252EYsz9qLUIq6F7YJyK1sv0wWDBFuztfDGWaQKzHjqDHysxSiRUpA/X9jmfqo+WzkAVKFaUily5h+gDCQ== + dependencies: + "@babel/types" "^7.9.0" + jsesc "^2.5.1" + lodash "^4.17.13" + source-map "^0.5.0" + "@babel/helper-annotate-as-pure@^7.0.0", "@babel/helper-annotate-as-pure@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz#60bc0bc657f63a0924ff9a4b4a0b24a13cf4deee" @@ -80,13 +121,22 @@ "@babel/helper-explode-assignable-expression" "^7.8.3" "@babel/types" "^7.8.3" -"@babel/helper-builder-react-jsx@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.8.3.tgz#dee98d7d79cc1f003d80b76fe01c7f8945665ff6" - integrity sha512-JT8mfnpTkKNCboTqZsQTdGo3l3Ik3l7QIt9hh0O9DYiwVel37VoJpILKM4YFbP2euF32nkQSb+F9cUk9b7DDXQ== +"@babel/helper-builder-react-jsx-experimental@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.9.0.tgz#066d80262ade488f9c1b1823ce5db88a4cedaa43" + integrity sha512-3xJEiyuYU4Q/Ar9BsHisgdxZsRlsShMe90URZ0e6przL26CCs8NJbDoxH94kKT17PcxlMhsCAwZd90evCo26VQ== dependencies: - "@babel/types" "^7.8.3" - esutils "^2.0.0" + "@babel/helper-annotate-as-pure" "^7.8.3" + "@babel/helper-module-imports" "^7.8.3" + "@babel/types" "^7.9.0" + +"@babel/helper-builder-react-jsx@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.9.0.tgz#16bf391990b57732700a3278d4d9a81231ea8d32" + integrity sha512-weiIo4gaoGgnhff54GQ3P5wsUQmnSwpkvU0r6ZHq6TzoSzKy4JxHEgnxNytaKbov2a9z/CVNyzliuCOUPEX3Jw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.8.3" + "@babel/types" "^7.9.0" "@babel/helper-call-delegate@^7.8.7": version "7.8.7" @@ -129,6 +179,15 @@ "@babel/helper-regex" "^7.8.3" regexpu-core "^4.6.0" +"@babel/helper-create-regexp-features-plugin@^7.8.8": + version "7.8.8" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.8.tgz#5d84180b588f560b7864efaeea89243e58312087" + integrity sha512-LYVPdwkrQEiX9+1R29Ld/wTrmQu1SSKYnuOk3g0CkcZMA1p0gsNxJFj/3gBdaJ7Cg0Fnek5z0DsMULePP7Lrqg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.8.3" + "@babel/helper-regex" "^7.8.3" + regexpu-core "^4.7.0" + "@babel/helper-define-map@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.8.3.tgz#a0655cad5451c3760b726eba875f1cd8faa02c15" @@ -183,17 +242,17 @@ dependencies: "@babel/types" "^7.8.3" -"@babel/helper-module-transforms@^7.8.3": - version "7.8.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.8.6.tgz#6a13b5eecadc35692047073a64e42977b97654a4" - integrity sha512-RDnGJSR5EFBJjG3deY0NiL0K9TO8SXxS9n/MPsbPK/s9LbQymuLNtlzvDiNS7IpecuL45cMeLVkA+HfmlrnkRg== +"@babel/helper-module-transforms@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.9.0.tgz#43b34dfe15961918707d247327431388e9fe96e5" + integrity sha512-0FvKyu0gpPfIQ8EkxlrAydOWROdHpBmiCiRwLkUiBGhCUPRRbVD2/tm3sFr/c/GWFrQ/ffutGUAnx7V0FzT2wA== dependencies: "@babel/helper-module-imports" "^7.8.3" "@babel/helper-replace-supers" "^7.8.6" "@babel/helper-simple-access" "^7.8.3" "@babel/helper-split-export-declaration" "^7.8.3" "@babel/template" "^7.8.6" - "@babel/types" "^7.8.6" + "@babel/types" "^7.9.0" lodash "^4.17.13" "@babel/helper-optimise-call-expression@^7.8.3": @@ -251,6 +310,11 @@ dependencies: "@babel/types" "^7.8.3" +"@babel/helper-validator-identifier@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.0.tgz#ad53562a7fc29b3b9a91bbf7d10397fd146346ed" + integrity sha512-6G8bQKjOh+of4PV/ThDm/rRqlU7+IGoJuofpagU5GlEl29Vv0RGqqt86ZGRV8ZuSOY3o+8yXl5y782SMcG7SHw== + "@babel/helper-wrap-function@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz#9dbdb2bb55ef14aaa01fe8c99b629bd5352d8610" @@ -270,6 +334,15 @@ "@babel/traverse" "^7.8.4" "@babel/types" "^7.8.3" +"@babel/helpers@^7.9.0": + version "7.9.2" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.9.2.tgz#b42a81a811f1e7313b88cba8adc66b3d9ae6c09f" + integrity sha512-JwLvzlXVPjO8eU9c/wF9/zOIN7X6h8DYf7mG4CiFRZRvZNKEF5dQ3H3V+ASkHoIB3mWhatgl5ONhyqHRI6MppA== + dependencies: + "@babel/template" "^7.8.3" + "@babel/traverse" "^7.9.0" + "@babel/types" "^7.9.0" + "@babel/highlight@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.8.3.tgz#28f173d04223eaaa59bc1d439a3836e6d1265797" @@ -284,6 +357,11 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.7.tgz#7b8facf95d25fef9534aad51c4ffecde1a61e26a" integrity sha512-9JWls8WilDXFGxs0phaXAZgpxTZhSk/yOYH2hTHC0X1yC7Z78IJfvR1vJ+rmJKq3I35td2XzXzN6ZLYlna+r/A== +"@babel/parser@^7.9.0": + version "7.9.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.3.tgz#043a5fc2ad8b7ea9facddc4e802a1f0f25da7255" + integrity sha512-E6SpIDJZ0cZAKoCNk+qSDd0ChfTnpiJN9FfNf3RZ20dzwA2vL2oq5IX1XTVT+4vDmRlta2nGk5HGMMskJAR+4A== + "@babel/plugin-proposal-async-generator-functions@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.8.3.tgz#bad329c670b382589721b27540c7d288601c6e6f" @@ -383,7 +461,7 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" -"@babel/plugin-proposal-numeric-separator@7.8.3": +"@babel/plugin-proposal-numeric-separator@7.8.3", "@babel/plugin-proposal-numeric-separator@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.8.3.tgz#5d6769409699ec9b3b68684cd8116cedff93bad8" integrity sha512-jWioO1s6R/R+wEHizfaScNsAx+xKgwTLNXSh7tTC4Usj3ItsPEhYkEpU4h+lpnBwq7NBVOJXfO6cRFYcX69JUQ== @@ -391,10 +469,10 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-numeric-separator" "^7.8.3" -"@babel/plugin-proposal-object-rest-spread@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.8.3.tgz#eb5ae366118ddca67bed583b53d7554cad9951bb" - integrity sha512-8qvuPwU/xxUCt78HocNlv0mXXo0wdh9VT1R04WU8HGOfaOob26pF+9P5/lYjN/q7DHOX1bvX60hnhOvuQUJdbA== +"@babel/plugin-proposal-object-rest-spread@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.0.tgz#a28993699fc13df165995362693962ba6b061d6f" + integrity sha512-UgqBv6bjq4fDb8uku9f+wcm1J7YxJ5nT7WO/jBr0cl0PLKb7t1O6RNR1kZbjgx2LQtsDI9hwoQVmn0yhXeQyow== dependencies: "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-object-rest-spread" "^7.8.0" @@ -407,10 +485,10 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" -"@babel/plugin-proposal-optional-chaining@7.8.3", "@babel/plugin-proposal-optional-chaining@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.8.3.tgz#ae10b3214cb25f7adb1f3bc87ba42ca10b7e2543" - integrity sha512-QIoIR9abkVn+seDE3OjA08jWcs3eZ9+wJCKSRgo3WdEU2csFYgdScb+8qHB3+WXsGJD55u+5hWCISI7ejXS+kg== +"@babel/plugin-proposal-optional-chaining@7.9.0", "@babel/plugin-proposal-optional-chaining@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.9.0.tgz#31db16b154c39d6b8a645292472b98394c292a58" + integrity sha512-NDn5tu3tcv4W30jNhmc2hyD5c56G6cXx4TesJubhxrJeCvuuMpttxr0OnNCqbZGhFjLrg+NIhxxC+BK5F6yS3w== dependencies: "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-optional-chaining" "^7.8.0" @@ -431,6 +509,14 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-throw-expressions" "^7.8.3" +"@babel/plugin-proposal-unicode-property-regex@^7.4.4": + version "7.8.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.8.tgz#ee3a95e90cdc04fe8cd92ec3279fa017d68a0d1d" + integrity sha512-EVhjVsMpbhLw9ZfHWSx2iy13Q8Z/eg8e8ccVWt23sWQK5l1UdkoLJPN5w69UA4uITGBnEZD2JOe4QOHycYKv8A== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.8.8" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-proposal-unicode-property-regex@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.3.tgz#b646c3adea5f98800c9ab45105ac34d06cd4a47f" @@ -544,7 +630,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-numeric-separator@^7.8.3": +"@babel/plugin-syntax-numeric-separator@^7.8.0", "@babel/plugin-syntax-numeric-separator@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.8.3.tgz#0e3fb63e09bea1b11e96467271c8308007e7c41f" integrity sha512-H7dCMAdN83PcCmqmkHB5dtp+Xa9a6LKSvA2hiFBC/5alSHxM5VgWZXFqDi0YFe8XNGT6iCa+z4V4zSt/PdZ7Dw== @@ -624,10 +710,10 @@ "@babel/helper-plugin-utils" "^7.8.3" lodash "^4.17.13" -"@babel/plugin-transform-classes@^7.8.6": - version "7.8.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.8.6.tgz#77534447a477cbe5995ae4aee3e39fbc8090c46d" - integrity sha512-k9r8qRay/R6v5aWZkrEclEhKO6mc1CCQr2dLsVHBmOQiMpN6I2bpjX3vgnldUWeEI1GHVNByULVxZ4BdP4Hmdg== +"@babel/plugin-transform-classes@^7.9.0": + version "7.9.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.9.2.tgz#8603fc3cc449e31fdbdbc257f67717536a11af8d" + integrity sha512-TC2p3bPzsfvSsqBZo0kJnuelnoK9O3welkUpqSqBQuBF6R5MN2rysopri8kNvtlGIb2jmUO7i15IooAZJjZuMQ== dependencies: "@babel/helper-annotate-as-pure" "^7.8.3" "@babel/helper-define-map" "^7.8.3" @@ -652,7 +738,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-dotall-regex@^7.8.3": +"@babel/plugin-transform-dotall-regex@^7.4.4", "@babel/plugin-transform-dotall-regex@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.8.3.tgz#c3c6ec5ee6125c6993c5cbca20dc8621a9ea7a6e" integrity sha512-kLs1j9Nn4MQoBYdRXH6AeaXMbEJFaFu/v1nQkvib6QzTj8MZI5OQzqmD83/2jEM1z0DLilra5aWO5YpyC0ALIw== @@ -675,18 +761,18 @@ "@babel/helper-builder-binary-assignment-operator-visitor" "^7.8.3" "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-flow-strip-types@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.8.3.tgz#da705a655466b2a9b36046b57bf0cbcd53551bd4" - integrity sha512-g/6WTWG/xbdd2exBBzMfygjX/zw4eyNC4X8pRaq7aRHRoDUCzAIu3kGYIXviOv8BjCuWm8vDBwjHcjiRNgXrPA== +"@babel/plugin-transform-flow-strip-types@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.9.0.tgz#8a3538aa40434e000b8f44a3c5c9ac7229bd2392" + integrity sha512-7Qfg0lKQhEHs93FChxVLAvhBshOPQDtJUTVHr/ZwQNRccCm4O9D79r9tVSoV8iNwjP1YgfD+e/fgHcPkN1qEQg== dependencies: "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-flow" "^7.8.3" -"@babel/plugin-transform-for-of@^7.8.6": - version "7.8.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.8.6.tgz#a051bd1b402c61af97a27ff51b468321c7c2a085" - integrity sha512-M0pw4/1/KI5WAxPsdcUL/w2LJ7o89YHN3yLkzNjg7Yl15GlVGgzHyCU+FMeAxevHGsLVmUqbirlUIKTafPmzdw== +"@babel/plugin-transform-for-of@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.9.0.tgz#0f260e27d3e29cd1bb3128da5e76c761aa6c108e" + integrity sha512-lTAnWOpMwOXpyDx06N+ywmF3jNbafZEqZ96CGYabxHrxNX8l5ny7dt4bK/rGwAh9utyP2b2Hv7PlZh1AAS54FQ== dependencies: "@babel/helper-plugin-utils" "^7.8.3" @@ -712,41 +798,41 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-modules-amd@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.8.3.tgz#65606d44616b50225e76f5578f33c568a0b876a5" - integrity sha512-MadJiU3rLKclzT5kBH4yxdry96odTUwuqrZM+GllFI/VhxfPz+k9MshJM+MwhfkCdxxclSbSBbUGciBngR+kEQ== +"@babel/plugin-transform-modules-amd@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.9.0.tgz#19755ee721912cf5bb04c07d50280af3484efef4" + integrity sha512-vZgDDF003B14O8zJy0XXLnPH4sg+9X5hFBBGN1V+B2rgrB+J2xIypSN6Rk9imB2hSTHQi5OHLrFWsZab1GMk+Q== dependencies: - "@babel/helper-module-transforms" "^7.8.3" + "@babel/helper-module-transforms" "^7.9.0" "@babel/helper-plugin-utils" "^7.8.3" babel-plugin-dynamic-import-node "^2.3.0" -"@babel/plugin-transform-modules-commonjs@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.8.3.tgz#df251706ec331bd058a34bdd72613915f82928a5" - integrity sha512-JpdMEfA15HZ/1gNuB9XEDlZM1h/gF/YOH7zaZzQu2xCFRfwc01NXBMHHSTT6hRjlXJJs5x/bfODM3LiCk94Sxg== +"@babel/plugin-transform-modules-commonjs@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.9.0.tgz#e3e72f4cbc9b4a260e30be0ea59bdf5a39748940" + integrity sha512-qzlCrLnKqio4SlgJ6FMMLBe4bySNis8DFn1VkGmOcxG9gqEyPIOzeQrA//u0HAKrWpJlpZbZMPB1n/OPa4+n8g== dependencies: - "@babel/helper-module-transforms" "^7.8.3" + "@babel/helper-module-transforms" "^7.9.0" "@babel/helper-plugin-utils" "^7.8.3" "@babel/helper-simple-access" "^7.8.3" babel-plugin-dynamic-import-node "^2.3.0" -"@babel/plugin-transform-modules-systemjs@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.8.3.tgz#d8bbf222c1dbe3661f440f2f00c16e9bb7d0d420" - integrity sha512-8cESMCJjmArMYqa9AO5YuMEkE4ds28tMpZcGZB/jl3n0ZzlsxOAi3mC+SKypTfT8gjMupCnd3YiXCkMjj2jfOg== +"@babel/plugin-transform-modules-systemjs@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.9.0.tgz#e9fd46a296fc91e009b64e07ddaa86d6f0edeb90" + integrity sha512-FsiAv/nao/ud2ZWy4wFacoLOm5uxl0ExSQ7ErvP7jpoihLR6Cq90ilOFyX9UXct3rbtKsAiZ9kFt5XGfPe/5SQ== dependencies: "@babel/helper-hoist-variables" "^7.8.3" - "@babel/helper-module-transforms" "^7.8.3" + "@babel/helper-module-transforms" "^7.9.0" "@babel/helper-plugin-utils" "^7.8.3" babel-plugin-dynamic-import-node "^2.3.0" -"@babel/plugin-transform-modules-umd@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.8.3.tgz#592d578ce06c52f5b98b02f913d653ffe972661a" - integrity sha512-evhTyWhbwbI3/U6dZAnx/ePoV7H6OUG+OjiJFHmhr9FPn0VShjwC2kdxqIuQ/+1P50TMrneGzMeyMTFOjKSnAw== +"@babel/plugin-transform-modules-umd@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.9.0.tgz#e909acae276fec280f9b821a5f38e1f08b480697" + integrity sha512-uTWkXkIVtg/JGRSIABdBoMsoIeoHQHPTL0Y2E7xf5Oj7sLqwVsNXOkNk0VJc7vF0IMBsPeikHxFjGe+qmwPtTQ== dependencies: - "@babel/helper-module-transforms" "^7.8.3" + "@babel/helper-module-transforms" "^7.9.0" "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-transform-named-capturing-groups-regex@^7.8.3": @@ -794,28 +880,38 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-react-jsx-self@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.8.3.tgz#c4f178b2aa588ecfa8d077ea80d4194ee77ed702" - integrity sha512-01OT7s5oa0XTLf2I8XGsL8+KqV9lx3EZV+jxn/L2LQ97CGKila2YMroTkCEIE0HV/FF7CMSRsIAybopdN9NTdg== +"@babel/plugin-transform-react-jsx-development@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.9.0.tgz#3c2a130727caf00c2a293f0aed24520825dbf754" + integrity sha512-tK8hWKrQncVvrhvtOiPpKrQjfNX3DtkNLSX4ObuGcpS9p0QrGetKmlySIGR07y48Zft8WVgPakqd/bk46JrMSw== + dependencies: + "@babel/helper-builder-react-jsx-experimental" "^7.9.0" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-jsx" "^7.8.3" + +"@babel/plugin-transform-react-jsx-self@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.9.0.tgz#f4f26a325820205239bb915bad8e06fcadabb49b" + integrity sha512-K2ObbWPKT7KUTAoyjCsFilOkEgMvFG+y0FqOl6Lezd0/13kMkkjHskVsZvblRPj1PHA44PrToaZANrryppzTvQ== dependencies: "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-jsx" "^7.8.3" -"@babel/plugin-transform-react-jsx-source@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.8.3.tgz#951e75a8af47f9f120db731be095d2b2c34920e0" - integrity sha512-PLMgdMGuVDtRS/SzjNEQYUT8f4z1xb2BAT54vM1X5efkVuYBf5WyGUMbpmARcfq3NaglIwz08UVQK4HHHbC6ag== +"@babel/plugin-transform-react-jsx-source@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.9.0.tgz#89ef93025240dd5d17d3122294a093e5e0183de0" + integrity sha512-K6m3LlSnTSfRkM6FcRk8saNEeaeyG5k7AVkBU2bZK3+1zdkSED3qNdsWrUgQBeTVD2Tp3VMmerxVO2yM5iITmw== dependencies: "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-jsx" "^7.8.3" -"@babel/plugin-transform-react-jsx@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.8.3.tgz#4220349c0390fdefa505365f68c103562ab2fc4a" - integrity sha512-r0h+mUiyL595ikykci+fbwm9YzmuOrUBi0b+FDIKmi3fPQyFokWVEMJnRWHJPPQEjyFJyna9WZC6Viv6UHSv1g== +"@babel/plugin-transform-react-jsx@^7.9.4": + version "7.9.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.9.4.tgz#86f576c8540bd06d0e95e0b61ea76d55f6cbd03f" + integrity sha512-Mjqf3pZBNLt854CK0C/kRuXAnE6H/bo7xYojP+WGtX8glDGSibcwnsWwhwoSuRg0+EBnxPC1ouVnuetUIlPSAw== dependencies: - "@babel/helper-builder-react-jsx" "^7.8.3" + "@babel/helper-builder-react-jsx" "^7.9.0" + "@babel/helper-builder-react-jsx-experimental" "^7.9.0" "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-jsx" "^7.8.3" @@ -896,12 +992,12 @@ core-js "^2.6.5" regenerator-runtime "^0.13.4" -"@babel/preset-env@7.8.7": - version "7.8.7" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.8.7.tgz#1fc7d89c7f75d2d70c2b6768de6c2e049b3cb9db" - integrity sha512-BYftCVOdAYJk5ASsznKAUl53EMhfBbr8CJ1X+AJLfGPscQkwJFiaV/Wn9DPH/7fzm2v6iRYJKYHSqyynTGw0nw== +"@babel/preset-env@7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.9.0.tgz#a5fc42480e950ae8f5d9f8f2bbc03f52722df3a8" + integrity sha512-712DeRXT6dyKAM/FMbQTV/FvRCms2hPCx+3weRjZ8iQVQWZejWWk1wwG6ViWMyqb/ouBbGOl5b6aCk0+j1NmsQ== dependencies: - "@babel/compat-data" "^7.8.6" + "@babel/compat-data" "^7.9.0" "@babel/helper-compilation-targets" "^7.8.7" "@babel/helper-module-imports" "^7.8.3" "@babel/helper-plugin-utils" "^7.8.3" @@ -909,14 +1005,16 @@ "@babel/plugin-proposal-dynamic-import" "^7.8.3" "@babel/plugin-proposal-json-strings" "^7.8.3" "@babel/plugin-proposal-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-proposal-object-rest-spread" "^7.8.3" + "@babel/plugin-proposal-numeric-separator" "^7.8.3" + "@babel/plugin-proposal-object-rest-spread" "^7.9.0" "@babel/plugin-proposal-optional-catch-binding" "^7.8.3" - "@babel/plugin-proposal-optional-chaining" "^7.8.3" + "@babel/plugin-proposal-optional-chaining" "^7.9.0" "@babel/plugin-proposal-unicode-property-regex" "^7.8.3" "@babel/plugin-syntax-async-generators" "^7.8.0" "@babel/plugin-syntax-dynamic-import" "^7.8.0" "@babel/plugin-syntax-json-strings" "^7.8.0" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + "@babel/plugin-syntax-numeric-separator" "^7.8.0" "@babel/plugin-syntax-object-rest-spread" "^7.8.0" "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" "@babel/plugin-syntax-optional-chaining" "^7.8.0" @@ -925,20 +1023,20 @@ "@babel/plugin-transform-async-to-generator" "^7.8.3" "@babel/plugin-transform-block-scoped-functions" "^7.8.3" "@babel/plugin-transform-block-scoping" "^7.8.3" - "@babel/plugin-transform-classes" "^7.8.6" + "@babel/plugin-transform-classes" "^7.9.0" "@babel/plugin-transform-computed-properties" "^7.8.3" "@babel/plugin-transform-destructuring" "^7.8.3" "@babel/plugin-transform-dotall-regex" "^7.8.3" "@babel/plugin-transform-duplicate-keys" "^7.8.3" "@babel/plugin-transform-exponentiation-operator" "^7.8.3" - "@babel/plugin-transform-for-of" "^7.8.6" + "@babel/plugin-transform-for-of" "^7.9.0" "@babel/plugin-transform-function-name" "^7.8.3" "@babel/plugin-transform-literals" "^7.8.3" "@babel/plugin-transform-member-expression-literals" "^7.8.3" - "@babel/plugin-transform-modules-amd" "^7.8.3" - "@babel/plugin-transform-modules-commonjs" "^7.8.3" - "@babel/plugin-transform-modules-systemjs" "^7.8.3" - "@babel/plugin-transform-modules-umd" "^7.8.3" + "@babel/plugin-transform-modules-amd" "^7.9.0" + "@babel/plugin-transform-modules-commonjs" "^7.9.0" + "@babel/plugin-transform-modules-systemjs" "^7.9.0" + "@babel/plugin-transform-modules-umd" "^7.9.0" "@babel/plugin-transform-named-capturing-groups-regex" "^7.8.3" "@babel/plugin-transform-new-target" "^7.8.3" "@babel/plugin-transform-object-super" "^7.8.3" @@ -952,31 +1050,44 @@ "@babel/plugin-transform-template-literals" "^7.8.3" "@babel/plugin-transform-typeof-symbol" "^7.8.4" "@babel/plugin-transform-unicode-regex" "^7.8.3" - "@babel/types" "^7.8.7" - browserslist "^4.8.5" + "@babel/preset-modules" "^0.1.3" + "@babel/types" "^7.9.0" + browserslist "^4.9.1" core-js-compat "^3.6.2" invariant "^2.2.2" levenary "^1.1.1" semver "^5.5.0" -"@babel/preset-flow@7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/preset-flow/-/preset-flow-7.8.3.tgz#52af74c6a4e80d889bd9436e8e278d0fecac6e18" - integrity sha512-iCXFk+T4demnq+dNLLvlGOgvYF6sPZ/hS1EmswugOqh1Ysp2vuiqJzpgsnp5rW8+6dLJT/0CXDzye28ZH6BAfQ== +"@babel/preset-flow@7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/preset-flow/-/preset-flow-7.9.0.tgz#fee847c3e090b0b2d9227c1949e4da1d1379280d" + integrity sha512-88uSmlshIrlmPkNkEcx3UpSZ6b8n0UGBq0/0ZMZCF/uxAW0XIAUuDHBhIOAh0pvweafH4RxOwi/H3rWhtqOYPA== dependencies: "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-transform-flow-strip-types" "^7.8.3" + "@babel/plugin-transform-flow-strip-types" "^7.9.0" -"@babel/preset-react@7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.8.3.tgz#23dc63f1b5b0751283e04252e78cf1d6589273d2" - integrity sha512-9hx0CwZg92jGb7iHYQVgi0tOEHP/kM60CtWJQnmbATSPIQQ2xYzfoCI3EdqAhFBeeJwYMdWQuDUHMsuDbH9hyQ== +"@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== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" + "@babel/plugin-transform-dotall-regex" "^7.4.4" + "@babel/types" "^7.4.4" + esutils "^2.0.2" + +"@babel/preset-react@7.9.4": + version "7.9.4" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.9.4.tgz#c6c97693ac65b6b9c0b4f25b948a8f665463014d" + integrity sha512-AxylVB3FXeOTQXNXyiuAQJSvss62FEotbX2Pzx3K/7c+MKJMdSg6Ose6QYllkdCFA8EInCJVw7M/o5QbLuA4ZQ== dependencies: "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-transform-react-display-name" "^7.8.3" - "@babel/plugin-transform-react-jsx" "^7.8.3" - "@babel/plugin-transform-react-jsx-self" "^7.8.3" - "@babel/plugin-transform-react-jsx-source" "^7.8.3" + "@babel/plugin-transform-react-jsx" "^7.9.4" + "@babel/plugin-transform-react-jsx-development" "^7.9.0" + "@babel/plugin-transform-react-jsx-self" "^7.9.0" + "@babel/plugin-transform-react-jsx-source" "^7.9.0" "@babel/runtime-corejs3@^7.7.4", "@babel/runtime-corejs3@^7.8.3": version "7.8.7" @@ -1000,6 +1111,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.9.2": + version "7.9.2" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.2.tgz#d90df0583a3a252f09aaa619665367bae518db06" + integrity sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/template@^7.7.4", "@babel/template@^7.8.3", "@babel/template@^7.8.6": version "7.8.6" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b" @@ -1024,6 +1142,21 @@ globals "^11.1.0" lodash "^4.17.13" +"@babel/traverse@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.0.tgz#d3882c2830e513f4fe4cec9fe76ea1cc78747892" + integrity sha512-jAZQj0+kn4WTHO5dUZkZKhbFrqZE7K5LAQ5JysMnmvGij+wOdr+8lWqPeW0BcF4wFwrEXXtdGO7wcV6YPJcf3w== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/generator" "^7.9.0" + "@babel/helper-function-name" "^7.8.3" + "@babel/helper-split-export-declaration" "^7.8.3" + "@babel/parser" "^7.9.0" + "@babel/types" "^7.9.0" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.13" + "@babel/types@^7.0.0", "@babel/types@^7.3.0", "@babel/types@^7.7.0", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.8.7": version "7.8.7" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.8.7.tgz#1fc9729e1acbb2337d5b6977a63979b4819f5d1d" @@ -1033,6 +1166,15 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" +"@babel/types@^7.4.4", "@babel/types@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.0.tgz#00b064c3df83ad32b2dbf5ff07312b15c7f1efb5" + integrity sha512-BS9JKfXkzzJl8RluW4JGknzpiUV7ZrvTayM6yfqLTVBEnFtyowVIOu6rqxRd5cVO6yGoWf4T8u8dgK9oB+GCng== + dependencies: + "@babel/helper-validator-identifier" "^7.9.0" + lodash "^4.17.13" + to-fast-properties "^2.0.0" + "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" @@ -1051,10 +1193,10 @@ exec-sh "^0.3.2" minimist "^1.2.0" -"@emotion/hash@^0.7.4": - version "0.7.4" - resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.7.4.tgz#f14932887422c9056b15a8d222a9074a7dfa2831" - integrity sha512-fxfMSBMX3tlIbKUdtGKxqB1fyrH6gVrX39Gsv3y8lRYKUqlgDt3UMqQyGnR1bQMa2B8aGnhLZokZgg8vT0Le+A== +"@emotion/hash@^0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413" + integrity sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow== "@emotion/is-prop-valid@^0.8.3": version "0.8.8" @@ -1191,81 +1333,80 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw== -"@jest/console@^25.1.0": - version "25.1.0" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-25.1.0.tgz#1fc765d44a1e11aec5029c08e798246bd37075ab" - integrity sha512-3P1DpqAMK/L07ag/Y9/Jup5iDEG9P4pRAuZiMQnU0JB3UOvCyYCjCoxr7sIA80SeyUCUKrr24fKAxVpmBgQonA== +"@jest/console@^25.2.3": + version "25.2.3" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-25.2.3.tgz#38ac19b916ff61457173799239472659e1a67c39" + integrity sha512-k+37B1aSvOt9tKHWbZZSOy1jdgzesB0bj96igCVUG1nAH1W5EoUfgc5EXbBVU08KSLvkVdWopLXaO3xfVGlxtQ== dependencies: - "@jest/source-map" "^25.1.0" + "@jest/source-map" "^25.2.1" chalk "^3.0.0" - jest-util "^25.1.0" + jest-util "^25.2.3" slash "^3.0.0" -"@jest/core@^25.1.0": - version "25.1.0" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-25.1.0.tgz#3d4634fc3348bb2d7532915d67781cdac0869e47" - integrity sha512-iz05+NmwCmZRzMXvMo6KFipW7nzhbpEawrKrkkdJzgytavPse0biEnCNr2wRlyCsp3SmKaEY+SGv7YWYQnIdig== +"@jest/core@^25.2.4": + version "25.2.4" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-25.2.4.tgz#382ef80369d3311f1df79db1ee19e958ae95cdad" + integrity sha512-WcWYShl0Bqfcb32oXtjwbiR78D/djhMdJW+ulp4/bmHgeODcsieqUJfUH+kEv8M7VNV77E6jds5aA+WuGh1nmg== dependencies: - "@jest/console" "^25.1.0" - "@jest/reporters" "^25.1.0" - "@jest/test-result" "^25.1.0" - "@jest/transform" "^25.1.0" - "@jest/types" "^25.1.0" + "@jest/console" "^25.2.3" + "@jest/reporters" "^25.2.4" + "@jest/test-result" "^25.2.4" + "@jest/transform" "^25.2.4" + "@jest/types" "^25.2.3" ansi-escapes "^4.2.1" chalk "^3.0.0" exit "^0.1.2" graceful-fs "^4.2.3" - jest-changed-files "^25.1.0" - jest-config "^25.1.0" - jest-haste-map "^25.1.0" - jest-message-util "^25.1.0" - jest-regex-util "^25.1.0" - jest-resolve "^25.1.0" - jest-resolve-dependencies "^25.1.0" - jest-runner "^25.1.0" - jest-runtime "^25.1.0" - jest-snapshot "^25.1.0" - jest-util "^25.1.0" - jest-validate "^25.1.0" - jest-watcher "^25.1.0" + jest-changed-files "^25.2.3" + jest-config "^25.2.4" + jest-haste-map "^25.2.3" + jest-message-util "^25.2.4" + jest-regex-util "^25.2.1" + jest-resolve "^25.2.3" + jest-resolve-dependencies "^25.2.4" + jest-runner "^25.2.4" + jest-runtime "^25.2.4" + jest-snapshot "^25.2.4" + jest-util "^25.2.3" + jest-validate "^25.2.3" + jest-watcher "^25.2.4" micromatch "^4.0.2" p-each-series "^2.1.0" - realpath-native "^1.1.0" + realpath-native "^2.0.0" rimraf "^3.0.0" slash "^3.0.0" strip-ansi "^6.0.0" -"@jest/environment@^25.1.0": - version "25.1.0" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-25.1.0.tgz#4a97f64770c9d075f5d2b662b5169207f0a3f787" - integrity sha512-cTpUtsjU4cum53VqBDlcW0E4KbQF03Cn0jckGPW/5rrE9tb+porD3+hhLtHAwhthsqfyF+bizyodTlsRA++sHg== +"@jest/environment@^25.2.4": + version "25.2.4" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-25.2.4.tgz#74f4d8dd87b427434d0b822cde37bc0e78f3e28b" + integrity sha512-wA4xlhD19/gukkDpJ5HQsTle0pgnzI5qMFEjw267lpTDC8d9N7Ihqr5pI+l0p8Qn1SQhai+glSqxrGdzKy4jxw== dependencies: - "@jest/fake-timers" "^25.1.0" - "@jest/types" "^25.1.0" - jest-mock "^25.1.0" + "@jest/fake-timers" "^25.2.4" + "@jest/types" "^25.2.3" + jest-mock "^25.2.3" -"@jest/fake-timers@^25.1.0": - version "25.1.0" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-25.1.0.tgz#a1e0eff51ffdbb13ee81f35b52e0c1c11a350ce8" - integrity sha512-Eu3dysBzSAO1lD7cylZd/CVKdZZ1/43SF35iYBNV1Lvvn2Undp3Grwsv8PrzvbLhqwRzDd4zxrY4gsiHc+wygQ== +"@jest/fake-timers@^25.2.4": + version "25.2.4" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-25.2.4.tgz#6821b6edde74fda2a42467ae92cc93095d4c9527" + integrity sha512-oC1TJiwfMcBttVN7Wz+VZnqEAgYTiEMu0QLOXpypR89nab0uCB31zm/QeBZddhSstn20qe3yqOXygp6OwvKT/Q== dependencies: - "@jest/types" "^25.1.0" - jest-message-util "^25.1.0" - jest-mock "^25.1.0" - jest-util "^25.1.0" + "@jest/types" "^25.2.3" + jest-message-util "^25.2.4" + jest-mock "^25.2.3" + jest-util "^25.2.3" lolex "^5.0.0" -"@jest/reporters@^25.1.0": - version "25.1.0" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-25.1.0.tgz#9178ecf136c48f125674ac328f82ddea46e482b0" - integrity sha512-ORLT7hq2acJQa8N+NKfs68ZtHFnJPxsGqmofxW7v7urVhzJvpKZG9M7FAcgh9Ee1ZbCteMrirHA3m5JfBtAaDg== +"@jest/reporters@^25.2.4": + version "25.2.4" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-25.2.4.tgz#aa01c20aab217150d3a6080d5c98ce0bf34b17ed" + integrity sha512-VHbLxM03jCc+bTLOluW/IqHR2G0Cl0iATwIQbuZtIUast8IXO4fD0oy4jpVGpG5b20S6REA8U3BaQoCW/CeVNQ== dependencies: "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^25.1.0" - "@jest/environment" "^25.1.0" - "@jest/test-result" "^25.1.0" - "@jest/transform" "^25.1.0" - "@jest/types" "^25.1.0" + "@jest/console" "^25.2.3" + "@jest/test-result" "^25.2.4" + "@jest/transform" "^25.2.4" + "@jest/types" "^25.2.3" chalk "^3.0.0" collect-v8-coverage "^1.0.0" exit "^0.1.2" @@ -1275,11 +1416,10 @@ istanbul-lib-report "^3.0.0" istanbul-lib-source-maps "^4.0.0" istanbul-reports "^3.0.0" - jest-haste-map "^25.1.0" - jest-resolve "^25.1.0" - jest-runtime "^25.1.0" - jest-util "^25.1.0" - jest-worker "^25.1.0" + jest-haste-map "^25.2.3" + jest-resolve "^25.2.3" + jest-util "^25.2.3" + jest-worker "^25.2.1" slash "^3.0.0" source-map "^0.6.0" string-length "^3.1.0" @@ -1288,54 +1428,54 @@ optionalDependencies: node-notifier "^6.0.0" -"@jest/source-map@^25.1.0": - version "25.1.0" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-25.1.0.tgz#b012e6c469ccdbc379413f5c1b1ffb7ba7034fb0" - integrity sha512-ohf2iKT0xnLWcIUhL6U6QN+CwFWf9XnrM2a6ybL9NXxJjgYijjLSitkYHIdzkd8wFliH73qj/+epIpTiWjRtAA== +"@jest/source-map@^25.2.1": + version "25.2.1" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-25.2.1.tgz#b62ecf8ae76170b08eff8859b56eb7576df34ab8" + integrity sha512-PgScGJm1U27+9Te/cxP4oUFqJ2PX6NhBL2a6unQ7yafCgs8k02c0LSyjSIx/ao0AwcAdCczfAPDf5lJ7zoB/7A== dependencies: callsites "^3.0.0" graceful-fs "^4.2.3" source-map "^0.6.0" -"@jest/test-result@^25.1.0": - version "25.1.0" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-25.1.0.tgz#847af2972c1df9822a8200457e64be4ff62821f7" - integrity sha512-FZzSo36h++U93vNWZ0KgvlNuZ9pnDnztvaM7P/UcTx87aPDotG18bXifkf1Ji44B7k/eIatmMzkBapnAzjkJkg== +"@jest/test-result@^25.2.4": + version "25.2.4" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-25.2.4.tgz#8fc9eac58e82eb2a82e4058e68c3814f98f59cf5" + integrity sha512-AI7eUy+q2lVhFnaibDFg68NGkrxVWZdD6KBr9Hm6EvN0oAe7GxpEwEavgPfNHQjU2mi6g+NsFn/6QPgTUwM1qg== dependencies: - "@jest/console" "^25.1.0" - "@jest/transform" "^25.1.0" - "@jest/types" "^25.1.0" + "@jest/console" "^25.2.3" + "@jest/transform" "^25.2.4" + "@jest/types" "^25.2.3" "@types/istanbul-lib-coverage" "^2.0.0" collect-v8-coverage "^1.0.0" -"@jest/test-sequencer@^25.1.0": - version "25.1.0" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-25.1.0.tgz#4df47208542f0065f356fcdb80026e3c042851ab" - integrity sha512-WgZLRgVr2b4l/7ED1J1RJQBOharxS11EFhmwDqknpknE0Pm87HLZVS2Asuuw+HQdfQvm2aXL2FvvBLxOD1D0iw== +"@jest/test-sequencer@^25.2.4": + version "25.2.4" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-25.2.4.tgz#28364aeddec140c696324114f63570f3de536c87" + integrity sha512-TEZm/Rkd6YgskdpTJdYLBtu6Gc11tfWPuSpatq0duH77ekjU8dpqX2zkPdY/ayuHxztV5LTJoV5BLtI9mZfXew== dependencies: - "@jest/test-result" "^25.1.0" - jest-haste-map "^25.1.0" - jest-runner "^25.1.0" - jest-runtime "^25.1.0" + "@jest/test-result" "^25.2.4" + jest-haste-map "^25.2.3" + jest-runner "^25.2.4" + jest-runtime "^25.2.4" -"@jest/transform@^25.1.0": - version "25.1.0" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-25.1.0.tgz#221f354f512b4628d88ce776d5b9e601028ea9da" - integrity sha512-4ktrQ2TPREVeM+KxB4zskAT84SnmG1vaz4S+51aTefyqn3zocZUnliLLm5Fsl85I3p/kFPN4CRp1RElIfXGegQ== +"@jest/transform@^25.2.4": + version "25.2.4" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-25.2.4.tgz#34336f37f13f62f7d1f5b93d5d150ba9eb3e11b9" + integrity sha512-6eRigvb+G6bs4kW5j1/y8wu4nCrmVuIe0epPBbiWaYlwawJ8yi1EIyK3d/btDqmBpN5GpN4YhR6iPPnDmkYdTA== dependencies: "@babel/core" "^7.1.0" - "@jest/types" "^25.1.0" + "@jest/types" "^25.2.3" babel-plugin-istanbul "^6.0.0" chalk "^3.0.0" convert-source-map "^1.4.0" fast-json-stable-stringify "^2.0.0" graceful-fs "^4.2.3" - jest-haste-map "^25.1.0" - jest-regex-util "^25.1.0" - jest-util "^25.1.0" + jest-haste-map "^25.2.3" + jest-regex-util "^25.2.1" + jest-util "^25.2.3" micromatch "^4.0.2" pirates "^4.0.1" - realpath-native "^1.1.0" + realpath-native "^2.0.0" slash "^3.0.0" source-map "^0.6.1" write-file-atomic "^3.0.0" @@ -1359,6 +1499,16 @@ "@types/yargs" "^15.0.0" chalk "^3.0.0" +"@jest/types@^25.2.3": + version "25.2.3" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-25.2.3.tgz#035c4fb94e2da472f359ff9a211915d59987f6b6" + integrity sha512-6oLQwO9mKif3Uph3RX5J1i3S7X7xtDHWBaaaoeKw8hOzV6YUd0qDcYcHZ6QXMHDIzSr7zzrEa51o2Ovlj6AtKQ== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^1.1.1" + "@types/yargs" "^15.0.0" + chalk "^3.0.0" + "@ledgerhq/devices@^5.11.0": version "5.11.0" resolved "https://registry.yarnpkg.com/@ledgerhq/devices/-/devices-5.11.0.tgz#34c79e80539160df3116795ddb7d2aee904645e3" @@ -1405,16 +1555,16 @@ resolved "https://registry.yarnpkg.com/@ledgerhq/logs/-/logs-5.11.0.tgz#9ad2aefceeef48cf9d77972f67e63ba478dd04cc" integrity sha512-NiFDdxLU/z1VGQy0/cbpv7UScMDQ/rU8SznqILSHYTnhK2xvvNFTUkd1W2mpmf9E/hzXFI0UAOieLQ44qovX3w== -"@material-ui/core@4.9.5": - version "4.9.5" - resolved "https://registry.yarnpkg.com/@material-ui/core/-/core-4.9.5.tgz#384869f2840b243241f7881a902f5ffc48360830" - integrity sha512-hVuUqw6847jcgRsUqzCiYCXcIJYhPUfM3gS9sNehTsbI0SF3tufLNO2B2Cgkuns8uOGy0nicD4p3L7JqhnEElg== +"@material-ui/core@4.9.8": + version "4.9.8" + resolved "https://registry.yarnpkg.com/@material-ui/core/-/core-4.9.8.tgz#21c37a9aadf4ff8a2719b8cfcad0ae9e6ca53791" + integrity sha512-4cslpG6oLoPWUfwPkX+hvbak4hAGiOfgXOu/UIYeeMrtsTEebC0Mirjoby7zhS4ny86YI3rXEFW6EZDmlj5n5w== dependencies: "@babel/runtime" "^7.4.4" - "@material-ui/styles" "^4.9.0" - "@material-ui/system" "^4.9.3" + "@material-ui/styles" "^4.9.6" + "@material-ui/system" "^4.9.6" "@material-ui/types" "^5.0.0" - "@material-ui/utils" "^4.7.1" + "@material-ui/utils" "^4.9.6" "@types/react-transition-group" "^4.2.0" clsx "^1.0.2" hoist-non-react-statics "^3.3.2" @@ -1441,18 +1591,18 @@ prop-types "^15.7.2" react-is "^16.8.0" -"@material-ui/styles@^4.9.0": - version "4.9.0" - resolved "https://registry.yarnpkg.com/@material-ui/styles/-/styles-4.9.0.tgz#10c31859f6868cfa9d3adf6b6c3e32c9d676bc76" - integrity sha512-nJHum4RqYBPWsjL/9JET8Z02FZ9gSizlg/7LWVFpIthNzpK6OQ5OSRR4T4x9/p+wK3t1qNn3b1uI4XpnZaPxOA== +"@material-ui/styles@^4.9.6": + version "4.9.6" + resolved "https://registry.yarnpkg.com/@material-ui/styles/-/styles-4.9.6.tgz#924a30bf7c9b91af9c8f19c12c8573b8a4ecd085" + integrity sha512-ijgwStEkw1OZ6gCz18hkjycpr/3lKs1hYPi88O/AUn4vMuuGEGAIrqKVFq/lADmZUNF3DOFIk8LDkp7zmjPxtA== dependencies: "@babel/runtime" "^7.4.4" - "@emotion/hash" "^0.7.4" + "@emotion/hash" "^0.8.0" "@material-ui/types" "^5.0.0" - "@material-ui/utils" "^4.7.1" + "@material-ui/utils" "^4.9.6" clsx "^1.0.2" csstype "^2.5.2" - hoist-non-react-statics "^3.2.1" + hoist-non-react-statics "^3.3.2" jss "^10.0.3" jss-plugin-camel-case "^10.0.3" jss-plugin-default-unit "^10.0.3" @@ -1463,13 +1613,13 @@ jss-plugin-vendor-prefixer "^10.0.3" prop-types "^15.7.2" -"@material-ui/system@^4.9.3": - version "4.9.3" - resolved "https://registry.yarnpkg.com/@material-ui/system/-/system-4.9.3.tgz#ee48990d7941237fdaf21b7b399981d614bb0875" - integrity sha512-DBGsTKYrLlFpHG8BUp0X6ZpvaOzef+GhSwn/8DwVTXUdHitphaPQoL9xucrI8X9MTBo//El+7nylko7lo7eJIw== +"@material-ui/system@^4.9.6": + version "4.9.6" + resolved "https://registry.yarnpkg.com/@material-ui/system/-/system-4.9.6.tgz#fd060540224da4d1740da8ca6e7af288e217717e" + integrity sha512-QtfoAePyqXoZ2HUVSwGb1Ro0kucMCvVjbI0CdYIR21t0Opgfm1Oer6ni9P5lfeXA39xSt0wCierw37j+YES48Q== dependencies: "@babel/runtime" "^7.4.4" - "@material-ui/utils" "^4.7.1" + "@material-ui/utils" "^4.9.6" prop-types "^15.7.2" "@material-ui/types@^5.0.0": @@ -1486,6 +1636,15 @@ prop-types "^15.7.2" react-is "^16.8.0" +"@material-ui/utils@^4.9.6": + version "4.9.6" + resolved "https://registry.yarnpkg.com/@material-ui/utils/-/utils-4.9.6.tgz#5f1f9f6e4df9c8b6a263293b68c94834248ff157" + integrity sha512-gqlBn0JPPTUZeAktn1rgMcy9Iczrr74ecx31tyZLVGdBGGzsxzM6PP6zeS7FuoLS6vG4hoZP7hWnOoHtkR0Kvw== + dependencies: + "@babel/runtime" "^7.4.4" + prop-types "^15.7.2" + react-is "^16.8.0" + "@mrmlnc/readdir-enhanced@^2.2.1": version "2.2.1" resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" @@ -1606,6 +1765,11 @@ resolved "https://registry.yarnpkg.com/@redux-saga/types/-/types-1.1.0.tgz#0e81ce56b4883b4b2a3001ebe1ab298b84237204" integrity sha512-afmTuJrylUU/0OtqzaRkbyYFFNgCF73Bvel/sw90pvGrWIZ+vyoIJqA6eMSoA6+nb443kTmulmBtC9NerXboNg== +"@restless/sanitizers@^0.2.4": + version "0.2.4" + resolved "https://registry.yarnpkg.com/@restless/sanitizers/-/sanitizers-0.2.4.tgz#726ea5607f1bf7e327df266e180b2702e3ffe587" + integrity sha512-BqEF+7YEPSvmM8xp5R1uM5hpf87wzVdzSK7rr323bjxM6JBQcBE2w1i6KXpYq2GEJ2Z9BIFSAbRs7jGAtgeJxw== + "@samverschueren/stream-to-observable@^0.3.0": version "0.3.0" resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz#ecdf48d532c58ea477acfcab80348424f8d0662f" @@ -1613,11 +1777,6 @@ dependencies: any-observable "^0.3.0" -"@sheerun/mutationobserver-shim@^0.3.2": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.3.tgz#5405ee8e444ed212db44e79351f0c70a582aae25" - integrity sha512-DetpxZw1fzPD5xUBrIAoplLChO2VB8DlL5Gg+I1IR9b2wPqYIca2WSUxL5g1vLeR4MsQq1NeWriXAVffV+U1Fw== - "@sindresorhus/is@^0.14.0": version "0.14.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" @@ -1637,60 +1796,57 @@ dependencies: defer-to-connect "^1.0.1" -"@testing-library/dom@^6.15.0": - version "6.15.0" - resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-6.15.0.tgz#042abea7b4685b70d9a919100da9024507dc20bb" - integrity sha512-8N24c4XwOigPicwc8n4ECgEoJW2/mMzRJBxu4Uo0zhLERZTbNzqpL5fyCigu7JGUXX+ITuiK4z9/lnHbYRHLwQ== +"@testing-library/dom@^7.0.2": + version "7.0.4" + resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-7.0.4.tgz#89909046b4a2818d423dd2c786faee4ddbe32838" + integrity sha512-+vrLcGDvopLPsBB7JgJhf8ZoOhBSeCsI44PKJL9YoKrP2AvCkqrTg+z77wEEZJ4tSNdxV0kymil7hSvsQQ7jMQ== dependencies: "@babel/runtime" "^7.8.4" - "@sheerun/mutationobserver-shim" "^0.3.2" "@types/testing-library__dom" "^6.12.1" aria-query "^4.0.2" dom-accessibility-api "^0.3.0" pretty-format "^25.1.0" - wait-for-expect "^3.0.2" -"@testing-library/jest-dom@5.1.1": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.1.1.tgz#e88a5c08f9b9f36b384f948a0532eae2abbc8204" - integrity sha512-7xnmBFcUmmUVAUhFiZ/u3CxFh1e46THAwra4SiiKNCW4By26RedCRwEk0rtleFPZG0wlTSNOKDvJjWYy93dp0w== +"@testing-library/jest-dom@5.3.0": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.3.0.tgz#2ae813b8b0eb69e8808f75d3af8efa3f0dc4d7ec" + integrity sha512-Cdhpc3BHL888X55qBNyra9eM0UG63LCm/FqCWTa1Ou/0MpsUbQTM9vW1NU6/jBQFoSLgkFfDG5XVpm2V0dOm/A== dependencies: - "@babel/runtime" "^7.8.3" - "@types/testing-library__jest-dom" "^5.0.0" + "@babel/runtime" "^7.9.2" + "@types/testing-library__jest-dom" "^5.0.2" chalk "^3.0.0" css "^2.2.4" css.escape "^1.5.1" jest-diff "^25.1.0" jest-matcher-utils "^25.1.0" lodash "^4.17.15" - pretty-format "^25.1.0" redent "^3.0.0" -"@testing-library/react@9.5.0": - version "9.5.0" - resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-9.5.0.tgz#71531655a7890b61e77a1b39452fbedf0472ca5e" - integrity sha512-di1b+D0p+rfeboHO5W7gTVeZDIK5+maEgstrZbWZSSvxDyfDRkkyBE1AJR5Psd6doNldluXlCWqXriUfqu/9Qg== +"@testing-library/react@10.0.1": + version "10.0.1" + resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-10.0.1.tgz#4f5e2a8836257c5bd3df640b21d7bea5a0d83ead" + integrity sha512-sMHWud2dcymOzq2AhEniICSijEwKeTiBX+K0y36FYNY7wH2t0SIP1o732Bf5dDY0jYoMC2hj2UJSVpZC/rDsWg== dependencies: - "@babel/runtime" "^7.8.4" - "@testing-library/dom" "^6.15.0" - "@types/testing-library__react" "^9.1.2" + "@babel/runtime" "^7.8.7" + "@testing-library/dom" "^7.0.2" + "@types/testing-library__react" "^9.1.3" -"@toruslabs/fetch-node-details@^2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@toruslabs/fetch-node-details/-/fetch-node-details-2.0.2.tgz#e2f1c2eb3d3e4e1ca1a5bb5baa10ddc286341373" - integrity sha512-kn4VZMIjZ19dJiaKPcTcd19LV4V45lDvfYl14CWwdHpxtBX1Mxkog85jU6l1mUh6cPgRfR0lcksn9rEr7kBLGQ== +"@toruslabs/fetch-node-details@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@toruslabs/fetch-node-details/-/fetch-node-details-2.0.4.tgz#42ba98f00f96f7514fc1cd7ff42a451af6533309" + integrity sha512-s0poG7sd5EMyzHJ6Dbi0nB1GFGFnEYTgUT/sjGrPj1KleoQj9Ircfcxas/40OCMfKGUYBhHe7D20Caxbk+dENg== dependencies: web3-eth-contract "^1.2.6" web3-utils "^1.2.6" -"@toruslabs/torus-embed@^1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@toruslabs/torus-embed/-/torus-embed-1.1.1.tgz#a6c17742310c342677ed94fc3c26f4a8944e18d8" - integrity sha512-tYiU854xuWkGaLhT366jDs9IHze/b/LWjjRXi43EyQpuyD556sA+cFJGkadBsdQtx8bhtTwO8NEYTGStt7RcHA== +"@toruslabs/torus-embed@^1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@toruslabs/torus-embed/-/torus-embed-1.2.4.tgz#1c35ad5c2b2c2e55e1556ee0688f84bc0c57691a" + integrity sha512-8Flyb9JTICgLSmOPMUpZBcF87K7xeVyOc29ZD/v99U0DuTjfq7cYAJGFPeKnHMOZD+2EPWY2NikqrpkC+xzkog== dependencies: "@chaitanyapotti/random-id" "^1.0.3" - "@toruslabs/fetch-node-details" "^2.0.2" - "@toruslabs/torus.js" "^1.0.7" + "@toruslabs/fetch-node-details" "^2.0.4" + "@toruslabs/torus.js" "^1.0.10" eth-json-rpc-errors "^2.0.2" fast-deep-equal "^3.1.1" json-rpc-engine "^5.1.8" @@ -1706,10 +1862,10 @@ through2 "^3.0.1" web3 "^0.20.7" -"@toruslabs/torus.js@^1.0.7": - version "1.0.7" - resolved "https://registry.yarnpkg.com/@toruslabs/torus.js/-/torus.js-1.0.7.tgz#3940cabfff0b5306568d97a3556b66b030a17ce3" - integrity sha512-JB2xSOgRRWTX57DRDUbGWjEJdAeNZjWUPfucg0M8RmqH3eETjwuBpA0ECi7e7gZKuZ0D34pBTn+a1TPBYLfTLA== +"@toruslabs/torus.js@^1.0.10": + version "1.0.10" + resolved "https://registry.yarnpkg.com/@toruslabs/torus.js/-/torus.js-1.0.10.tgz#cdc5657f6206006cc7910dd1d714ec1e105cbf19" + integrity sha512-a3r4rkqHdawvfQaJNCDfPZFrtHDplRsrjR/7VXXlH2Z0HkqaM5SNjKFTN2Ul0KM4S4MWz3mAl1r6bo3nKEJoYA== dependencies: bn.js "^5.1.1" eccrypto "^1.1.3" @@ -1970,6 +2126,11 @@ fs-extra "^7.0.1" mkdirp "^0.5.1" +"@types/anymatch@*": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@types/anymatch/-/anymatch-1.3.1.tgz#336badc1beecb9dacc38bea2cf32adf627a8421a" + integrity sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA== + "@types/babel__core@^7.1.0": version "7.1.6" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.6.tgz#16ff42a5ae203c9af1c6e190ed1f30f83207b610" @@ -2034,6 +2195,11 @@ "@types/minimatch" "*" "@types/node" "*" +"@types/html-minifier-terser@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-5.0.0.tgz#7532440c138605ced1b555935c3115ddd20e8bef" + integrity sha512-q95SP4FdkmF0CwO0F2q0H6ZgudsApaY/yCtAQNRn1gduef5fGpyEphzy0YCq/N0UFvDSnLg5V8jFK/YGXlDiCw== + "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": version "2.0.1" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff" @@ -2092,6 +2258,11 @@ resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== +"@types/prettier@^1.19.0": + version "1.19.1" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-1.19.1.tgz#33509849f8e679e4add158959fdb086440e9553f" + integrity sha512-5qOlnZscTn4xxM5MeGXAMOsIOIKIbh9e85zJWfBRVPlRMEVawzoPhINYbRGkBZCI8LxvBe7tJCdWiarA99OZfQ== + "@types/prop-types@*": version "15.7.3" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7" @@ -2124,11 +2295,21 @@ "@types/prop-types" "*" csstype "^2.2.0" +"@types/source-list-map@*": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9" + integrity sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA== + "@types/stack-utils@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw== +"@types/tapable@*", "@types/tapable@^1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.5.tgz#9adbc12950582aa65ead76bffdf39fe0c27a3c02" + integrity sha512-/gG2M/Imw7cQFp8PGvz/SwocNrmKFjFsm5Pb8HdbHkZ1K8pmuPzOX4VeVoiEecFCVf4CsN1r3/BRvx+6sNqwtQ== + "@types/testing-library__dom@*", "@types/testing-library__dom@^6.12.1": version "6.14.0" resolved "https://registry.yarnpkg.com/@types/testing-library__dom/-/testing-library__dom-6.14.0.tgz#1aede831cb4ed4a398448df5a2c54b54a365644e" @@ -2136,14 +2317,14 @@ dependencies: pretty-format "^24.3.0" -"@types/testing-library__jest-dom@^5.0.0": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.0.1.tgz#cc7f384535a3d9597e27f58d38a795f5c137cc53" - integrity sha512-GiPXQBVF9O4DG9cssD2d266vozBJvC5Tnv6aeH5ujgYJgys1DYm9AFCz7YC+STR5ksGxq3zCt+yP8T1wbk2DFg== +"@types/testing-library__jest-dom@^5.0.2": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.0.2.tgz#89b782e0f187fe1e80d6375133da74182ba02065" + integrity sha512-dZP+/WHndgCSmdaImITy0KhjGAa9c0hlGGkzefbtrPFpnGEPZECDA0zyvfSp8RKhHECJJSKHFExjOwzo0rHyIA== dependencies: "@types/jest" "*" -"@types/testing-library__react@^9.1.2": +"@types/testing-library__react@^9.1.3": version "9.1.3" resolved "https://registry.yarnpkg.com/@types/testing-library__react/-/testing-library__react-9.1.3.tgz#35eca61cc6ea923543796f16034882a1603d7302" integrity sha512-iCdNPKU3IsYwRK9JieSYAiX0+aYDXOGAmrC/3/M7AqqSDKnWWVv07X+Zk1uFSL7cMTUYzv4lQRfohucEocn5/w== @@ -2152,6 +2333,34 @@ "@types/testing-library__dom" "*" pretty-format "^25.1.0" +"@types/uglify-js@*": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.0.4.tgz#96beae23df6f561862a830b4288a49e86baac082" + integrity sha512-SudIN9TRJ+v8g5pTG8RRCqfqTMNqgWCKKd3vtynhGzkIIjxaicNAMuY5TRadJ6tzDu3Dotf3ngaMILtmOdmWEQ== + dependencies: + source-map "^0.6.1" + +"@types/webpack-sources@*": + version "0.1.7" + resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-0.1.7.tgz#0a330a9456113410c74a5d64180af0cbca007141" + integrity sha512-XyaHrJILjK1VHVC4aVlKsdNN5KBTwufMb43cQs+flGxtPAf/1Qwl8+Q0tp5BwEGaI8D6XT1L+9bSWXckgkjTLw== + dependencies: + "@types/node" "*" + "@types/source-list-map" "*" + source-map "^0.6.1" + +"@types/webpack@^4.41.8": + version "4.41.9" + resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.9.tgz#f0ed8d46d69efe11573441f8eb112d934fc4efe9" + integrity sha512-R68AotLGtaVL6HGfZRvEyYKsWcMv0CBFfSr4gxoYzhMn3LnjLV/ksP4dNi9de8dVG+Dn/GuDr1NwB/sDApB3pA== + dependencies: + "@types/anymatch" "*" + "@types/node" "*" + "@types/tapable" "*" + "@types/uglify-js" "*" + "@types/webpack-sources" "*" + source-map "^0.6.0" + "@types/yargs-parser@*": version "15.0.0" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-15.0.0.tgz#cb3f9f741869e20cce330ffbeb9271590483882d" @@ -2171,6 +2380,14 @@ dependencies: "@types/yargs-parser" "*" +"@unilogin/provider@^0.5.20": + version "0.5.20" + resolved "https://registry.yarnpkg.com/@unilogin/provider/-/provider-0.5.20.tgz#3bdfe542058eca5bf86cb6c509a84ac6c2e64b0b" + integrity sha512-lDg/rU2fblQyrUHR0Jkk8vSiRQHkBKY6pUc0pqgaeDimkQNVZJKsPK7FzbRINtIJQGQsoZpObI6a25qguO/jew== + dependencies: + "@restless/sanitizers" "^0.2.4" + reactive-properties "^0.1.11" + "@walletconnect/browser@^1.0.0-beta.47": version "1.0.0-beta.47" resolved "https://registry.yarnpkg.com/@walletconnect/browser/-/browser-1.0.0-beta.47.tgz#7e79015ed3b568e416b7532c3864cf7c160f3a3b" @@ -2242,150 +2459,149 @@ typedarray-to-buffer "^3.1.5" yaeti "^0.0.6" -"@webassemblyjs/ast@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.8.5.tgz#51b1c5fe6576a34953bf4b253df9f0d490d9e359" - integrity sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ== +"@webassemblyjs/ast@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964" + integrity sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA== dependencies: - "@webassemblyjs/helper-module-context" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/wast-parser" "1.8.5" + "@webassemblyjs/helper-module-context" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/wast-parser" "1.9.0" -"@webassemblyjs/floating-point-hex-parser@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz#1ba926a2923613edce496fd5b02e8ce8a5f49721" - integrity sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ== +"@webassemblyjs/floating-point-hex-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz#3c3d3b271bddfc84deb00f71344438311d52ffb4" + integrity sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA== -"@webassemblyjs/helper-api-error@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz#c49dad22f645227c5edb610bdb9697f1aab721f7" - integrity sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA== +"@webassemblyjs/helper-api-error@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz#203f676e333b96c9da2eeab3ccef33c45928b6a2" + integrity sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw== -"@webassemblyjs/helper-buffer@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz#fea93e429863dd5e4338555f42292385a653f204" - integrity sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q== +"@webassemblyjs/helper-buffer@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz#a1442d269c5feb23fcbc9ef759dac3547f29de00" + integrity sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA== -"@webassemblyjs/helper-code-frame@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz#9a740ff48e3faa3022b1dff54423df9aa293c25e" - integrity sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ== +"@webassemblyjs/helper-code-frame@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz#647f8892cd2043a82ac0c8c5e75c36f1d9159f27" + integrity sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA== dependencies: - "@webassemblyjs/wast-printer" "1.8.5" + "@webassemblyjs/wast-printer" "1.9.0" -"@webassemblyjs/helper-fsm@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz#ba0b7d3b3f7e4733da6059c9332275d860702452" - integrity sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow== +"@webassemblyjs/helper-fsm@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz#c05256b71244214671f4b08ec108ad63b70eddb8" + integrity sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw== -"@webassemblyjs/helper-module-context@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz#def4b9927b0101dc8cbbd8d1edb5b7b9c82eb245" - integrity sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g== +"@webassemblyjs/helper-module-context@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz#25d8884b76839871a08a6c6f806c3979ef712f07" + integrity sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g== dependencies: - "@webassemblyjs/ast" "1.8.5" - mamacro "^0.0.3" + "@webassemblyjs/ast" "1.9.0" -"@webassemblyjs/helper-wasm-bytecode@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz#537a750eddf5c1e932f3744206551c91c1b93e61" - integrity sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ== +"@webassemblyjs/helper-wasm-bytecode@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz#4fed8beac9b8c14f8c58b70d124d549dd1fe5790" + integrity sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw== -"@webassemblyjs/helper-wasm-section@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz#74ca6a6bcbe19e50a3b6b462847e69503e6bfcbf" - integrity sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA== +"@webassemblyjs/helper-wasm-section@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz#5a4138d5a6292ba18b04c5ae49717e4167965346" + integrity sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw== dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-buffer" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/wasm-gen" "1.8.5" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-buffer" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/wasm-gen" "1.9.0" -"@webassemblyjs/ieee754@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz#712329dbef240f36bf57bd2f7b8fb9bf4154421e" - integrity sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g== +"@webassemblyjs/ieee754@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz#15c7a0fbaae83fb26143bbacf6d6df1702ad39e4" + integrity sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg== dependencies: "@xtuc/ieee754" "^1.2.0" -"@webassemblyjs/leb128@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.8.5.tgz#044edeb34ea679f3e04cd4fd9824d5e35767ae10" - integrity sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A== +"@webassemblyjs/leb128@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.9.0.tgz#f19ca0b76a6dc55623a09cffa769e838fa1e1c95" + integrity sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw== dependencies: "@xtuc/long" "4.2.2" -"@webassemblyjs/utf8@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.8.5.tgz#a8bf3b5d8ffe986c7c1e373ccbdc2a0915f0cedc" - integrity sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw== +"@webassemblyjs/utf8@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.9.0.tgz#04d33b636f78e6a6813227e82402f7637b6229ab" + integrity sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w== -"@webassemblyjs/wasm-edit@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz#962da12aa5acc1c131c81c4232991c82ce56e01a" - integrity sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q== +"@webassemblyjs/wasm-edit@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz#3fe6d79d3f0f922183aa86002c42dd256cfee9cf" + integrity sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw== dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-buffer" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/helper-wasm-section" "1.8.5" - "@webassemblyjs/wasm-gen" "1.8.5" - "@webassemblyjs/wasm-opt" "1.8.5" - "@webassemblyjs/wasm-parser" "1.8.5" - "@webassemblyjs/wast-printer" "1.8.5" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-buffer" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/helper-wasm-section" "1.9.0" + "@webassemblyjs/wasm-gen" "1.9.0" + "@webassemblyjs/wasm-opt" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" + "@webassemblyjs/wast-printer" "1.9.0" -"@webassemblyjs/wasm-gen@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz#54840766c2c1002eb64ed1abe720aded714f98bc" - integrity sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg== +"@webassemblyjs/wasm-gen@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz#50bc70ec68ded8e2763b01a1418bf43491a7a49c" + integrity sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA== dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/ieee754" "1.8.5" - "@webassemblyjs/leb128" "1.8.5" - "@webassemblyjs/utf8" "1.8.5" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/ieee754" "1.9.0" + "@webassemblyjs/leb128" "1.9.0" + "@webassemblyjs/utf8" "1.9.0" -"@webassemblyjs/wasm-opt@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz#b24d9f6ba50394af1349f510afa8ffcb8a63d264" - integrity sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q== +"@webassemblyjs/wasm-opt@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz#2211181e5b31326443cc8112eb9f0b9028721a61" + integrity sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A== dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-buffer" "1.8.5" - "@webassemblyjs/wasm-gen" "1.8.5" - "@webassemblyjs/wasm-parser" "1.8.5" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-buffer" "1.9.0" + "@webassemblyjs/wasm-gen" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" -"@webassemblyjs/wasm-parser@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz#21576f0ec88b91427357b8536383668ef7c66b8d" - integrity sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw== +"@webassemblyjs/wasm-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz#9d48e44826df4a6598294aa6c87469d642fff65e" + integrity sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA== dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-api-error" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/ieee754" "1.8.5" - "@webassemblyjs/leb128" "1.8.5" - "@webassemblyjs/utf8" "1.8.5" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-api-error" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/ieee754" "1.9.0" + "@webassemblyjs/leb128" "1.9.0" + "@webassemblyjs/utf8" "1.9.0" -"@webassemblyjs/wast-parser@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz#e10eecd542d0e7bd394f6827c49f3df6d4eefb8c" - integrity sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg== +"@webassemblyjs/wast-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz#3031115d79ac5bd261556cecc3fa90a3ef451914" + integrity sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw== dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/floating-point-hex-parser" "1.8.5" - "@webassemblyjs/helper-api-error" "1.8.5" - "@webassemblyjs/helper-code-frame" "1.8.5" - "@webassemblyjs/helper-fsm" "1.8.5" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/floating-point-hex-parser" "1.9.0" + "@webassemblyjs/helper-api-error" "1.9.0" + "@webassemblyjs/helper-code-frame" "1.9.0" + "@webassemblyjs/helper-fsm" "1.9.0" "@xtuc/long" "4.2.2" -"@webassemblyjs/wast-printer@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz#114bbc481fd10ca0e23b3560fa812748b0bae5bc" - integrity sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg== +"@webassemblyjs/wast-printer@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz#4935d54c85fef637b00ce9f52377451d00d47899" + integrity sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA== dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/wast-parser" "1.8.5" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/wast-parser" "1.9.0" "@xtuc/long" "4.2.2" "@welldone-software/why-did-you-render@4.0.5": @@ -2478,11 +2694,16 @@ acorn-jsx@^5.0.0, acorn-jsx@^5.2.0: resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.2.0.tgz#4c66069173d6fdd68ed85239fc256226182b2ebe" integrity sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ== -acorn-walk@^6.0.1, acorn-walk@^6.1.1: +acorn-walk@^6.0.1: version "6.2.0" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c" integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA== +acorn-walk@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.1.1.tgz#345f0dffad5c735e7373d2fec9a1023e6a44b83e" + integrity sha512-wdlPY2tm/9XBr7QkKlq0WQVgiuGTX6YWPyRyBviSoScBuLfTVQhvwg6wJ369GJ/1nPfTLMfnrFIfjqVg6d+jQQ== + acorn@4.X: version "4.0.13" resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" @@ -2566,6 +2787,13 @@ alphanum-sort@^1.0.0: resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= +ansi-colors@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-1.1.0.tgz#6374b4dd5d4718ff3ce27a671a3b1cad077132a9" + integrity sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA== + dependencies: + ansi-wrap "^0.1.0" + ansi-colors@^3.0.0: version "3.2.4" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf" @@ -2583,6 +2811,13 @@ ansi-escapes@^4.2.1: dependencies: type-fest "^0.11.0" +ansi-gray@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-gray/-/ansi-gray-0.1.1.tgz#2962cf54ec9792c48510a3deb524436861ef7251" + integrity sha1-KWLPVOyXksSFEKPetSRDaGHvclE= + dependencies: + ansi-wrap "0.1.0" + ansi-html@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e" @@ -2628,6 +2863,11 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: "@types/color-name" "^1.1.1" color-convert "^2.0.1" +ansi-wrap@0.1.0, ansi-wrap@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" + integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768= + any-observable@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/any-observable/-/any-observable-0.3.0.tgz#af933475e5806a67d0d7df090dd5e8bef65d119b" @@ -2659,11 +2899,23 @@ app-module-path@^2.2.0: resolved "https://registry.yarnpkg.com/app-module-path/-/app-module-path-2.2.0.tgz#641aa55dfb7d6a6f0a8141c4b9c0aa50b6c24dd5" integrity sha1-ZBqlXft9am8KgUHEucCqULbCTdU= +append-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/append-buffer/-/append-buffer-1.0.2.tgz#d8220cf466081525efea50614f3de6514dfa58f1" + integrity sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE= + dependencies: + buffer-equal "^1.0.0" + aproba@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== +archy@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" + integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA= + argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -2699,16 +2951,35 @@ arr-diff@^4.0.0: resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= +arr-filter@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/arr-filter/-/arr-filter-1.1.2.tgz#43fdddd091e8ef11aa4c45d9cdc18e2dff1711ee" + integrity sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4= + dependencies: + make-iterator "^1.0.0" + arr-flatten@^1.0.1, arr-flatten@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== +arr-map@^2.0.0, arr-map@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/arr-map/-/arr-map-2.0.2.tgz#3a77345ffc1cf35e2a91825601f9e58f2e24cac4" + integrity sha1-Onc0X/wc814qkYJWAfnljy4kysQ= + dependencies: + make-iterator "^1.0.0" + arr-union@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= +array-each@^1.0.0, array-each@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/array-each/-/array-each-1.0.1.tgz#a794af0c05ab1752846ee753a1f211a05ba0c44f" + integrity sha1-p5SvDAWrF1KEbudTofIRoFugxE8= + array-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" @@ -2738,6 +3009,35 @@ array-includes@^3.0.3, array-includes@^3.1.1: es-abstract "^1.17.0" is-string "^1.0.5" +array-initial@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/array-initial/-/array-initial-1.1.0.tgz#2fa74b26739371c3947bd7a7adc73be334b3d795" + integrity sha1-L6dLJnOTccOUe9enrcc74zSz15U= + dependencies: + array-slice "^1.0.0" + is-number "^4.0.0" + +array-last@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/array-last/-/array-last-1.3.0.tgz#7aa77073fec565ddab2493f5f88185f404a9d336" + integrity sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg== + dependencies: + is-number "^4.0.0" + +array-slice@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-1.1.0.tgz#e368ea15f89bc7069f7ffb89aec3a6c7d4ac22d4" + integrity sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w== + +array-sort@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-sort/-/array-sort-1.0.0.tgz#e4c05356453f56f53512a7d1d6123f2c54c0a88a" + integrity sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg== + dependencies: + default-compare "^1.0.0" + get-value "^2.0.6" + kind-of "^5.0.2" + array-union@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" @@ -2822,16 +3122,21 @@ 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.9.6: - version "0.9.6" - resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.9.6.tgz#102c9e9e9005d3e7e3829bf0c4fa24ee862ee9b9" - integrity sha1-ECyenpAF0+fjgpvwxPok7oYu6bk= - astral-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== +async-done@^1.2.0, async-done@^1.2.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/async-done/-/async-done-1.3.2.tgz#5e15aa729962a4b07414f528a88cdf18e0b290a2" + integrity sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.2" + process-nextick-args "^2.0.0" + stream-exhaust "^1.0.1" + async-each@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" @@ -2854,6 +3159,13 @@ async-sema@^3.1.0: resolved "https://registry.yarnpkg.com/async-sema/-/async-sema-3.1.0.tgz#3a813beb261e4cc58b19213916a48e931e21d21e" integrity sha512-+JpRq3r0zjpRLDruS6q/nC4V5tzsaiu07521677Mdi5i+AkaU/aNJH38rYHJVQ4zvz+SSkjgc8FUI7qIZrR+3g== +async-settle@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/async-settle/-/async-settle-1.0.0.tgz#1d0a914bb02575bec8a8f3a74e5080f72b2c0c6b" + integrity sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs= + dependencies: + async-done "^1.2.2" + async@2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" @@ -2890,6 +3202,11 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= +at-least-node@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" + integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== + atob@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" @@ -2915,18 +3232,18 @@ authereum@^0.0.4-beta.88: web3-provider-engine "^15.0.4" web3-utils "^1.2.1" -autoprefixer@9.7.4: - version "9.7.4" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.7.4.tgz#f8bf3e06707d047f0641d87aee8cfb174b2a5378" - integrity sha512-g0Ya30YrMBAEZk60lp+qfX5YQllG+S5W3GYCFvyHTvhOki0AEQJLPEcIuGRsqVwLi8FvXPVtwTGhfr38hVpm0g== +autoprefixer@9.7.5: + version "9.7.5" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.7.5.tgz#8df10b9ff9b5814a8d411a5cfbab9c793c392376" + integrity sha512-URo6Zvt7VYifomeAfJlMFnYDhow1rk2bufwkbamPEAtQFcL11moLk4PnR7n9vlu7M+BkXAZkHFA0mIcY7tjQFg== dependencies: - browserslist "^4.8.3" - caniuse-lite "^1.0.30001020" + browserslist "^4.11.0" + caniuse-lite "^1.0.30001036" chalk "^2.4.2" normalize-range "^0.1.2" num2fraction "^1.2.2" - postcss "^7.0.26" - postcss-value-parser "^4.0.2" + postcss "^7.0.27" + postcss-value-parser "^4.0.3" await-semaphore@^0.1.3: version "0.1.3" @@ -3141,28 +3458,29 @@ babel-helpers@^6.24.1: babel-runtime "^6.22.0" babel-template "^6.24.1" -babel-jest@25.1.0, babel-jest@^25.1.0: - version "25.1.0" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-25.1.0.tgz#206093ac380a4b78c4404a05b3277391278f80fb" - integrity sha512-tz0VxUhhOE2y+g8R2oFrO/2VtVjA1lkJeavlhExuRBg3LdNJY9gwQ+Vcvqt9+cqy71MCTJhewvTB7Qtnnr9SWg== +babel-jest@25.2.4, babel-jest@^25.2.4: + version "25.2.4" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-25.2.4.tgz#b21b68d3af8f161c3e6e501e91f0dea8e652e344" + integrity sha512-+yDzlyJVWrqih9i2Cvjpt7COaN8vUwCsKGtxJLzg6I0xhxD54K8mvDUCliPKLufyzHh/c5C4MRj4Vk7VMjOjIg== dependencies: - "@jest/transform" "^25.1.0" - "@jest/types" "^25.1.0" + "@jest/transform" "^25.2.4" + "@jest/types" "^25.2.3" "@types/babel__core" "^7.1.0" babel-plugin-istanbul "^6.0.0" - babel-preset-jest "^25.1.0" + babel-preset-jest "^25.2.1" chalk "^3.0.0" slash "^3.0.0" -babel-loader@8.0.6: - version "8.0.6" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.0.6.tgz#e33bdb6f362b03f4bb141a0c21ab87c501b70dfb" - integrity sha512-4BmWKtBOBm13uoUwd08UwjZlaw3O9GWf456R9j+5YykFZ6LUIjIKLc0zEZf+hauxPOJs96C8k6FvYD09vWzhYw== +babel-loader@8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.1.0.tgz#c611d5112bd5209abe8b9fa84c3e4da25275f1c3" + integrity sha512-7q7nC1tYOrqvUrN3LQK4GwSk/TQorZSOlO9C+RZDZpODgyN4ZlCqE5q9cDsyWOliN+aU9B4JX01xK9eJXowJLw== dependencies: - find-cache-dir "^2.0.0" - loader-utils "^1.0.2" - mkdirp "^0.5.1" + find-cache-dir "^2.1.0" + loader-utils "^1.4.0" + mkdirp "^0.5.3" pify "^4.0.1" + schema-utils "^2.6.5" babel-messages@^6.23.0: version "6.23.0" @@ -3196,10 +3514,10 @@ babel-plugin-istanbul@^6.0.0: istanbul-lib-instrument "^4.0.0" test-exclude "^6.0.0" -babel-plugin-jest-hoist@^25.1.0: - version "25.1.0" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-25.1.0.tgz#fb62d7b3b53eb36c97d1bc7fec2072f9bd115981" - integrity sha512-oIsopO41vW4YFZ9yNYoLQATnnN46lp+MZ6H4VvPKFkcc2/fkl3CfE/NZZSmnEIEsJRmJAgkVEK0R7Zbl50CpTw== +babel-plugin-jest-hoist@^25.2.1: + version "25.2.1" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-25.2.1.tgz#d0003a1f3d5caa281e1107fe03bbf16b799f9955" + integrity sha512-HysbCQfJhxLlyxDbKcB2ucGYV0LjqK4h6dBoI3RtFuOxTiTWK6XGZMsHb0tGh8iJdV4hC6Z2GCHzVvDeh9i0lQ== dependencies: "@types/babel__traverse" "^7.0.6" @@ -3515,14 +3833,14 @@ babel-preset-env@^1.7.0: invariant "^2.2.2" semver "^5.3.0" -babel-preset-jest@^25.1.0: - version "25.1.0" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-25.1.0.tgz#d0aebfebb2177a21cde710996fce8486d34f1d33" - integrity sha512-eCGn64olaqwUMaugXsTtGAM2I0QTahjEtnRu0ql8Ie+gDWAc1N6wqN0k2NilnyTunM69Pad7gJY7LOtwLimoFQ== +babel-preset-jest@^25.2.1: + version "25.2.1" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-25.2.1.tgz#4ccd0e577f69aa11b71806edfe8b25a5c3ac93a2" + integrity sha512-zXHJBM5iR8oEO4cvdF83AQqqJf3tJrXy3x8nfu2Nlqvn4cneg4Ca8M7cQvC5S9BzDDy1O0tZ9iXru9J6E3ym+A== dependencies: "@babel/plugin-syntax-bigint" "^7.0.0" "@babel/plugin-syntax-object-rest-spread" "^7.0.0" - babel-plugin-jest-hoist "^25.1.0" + babel-plugin-jest-hoist "^25.2.1" babel-register@^6.26.0: version "6.26.0" @@ -3594,6 +3912,21 @@ babylon@6.18.0, babylon@^6.18.0: resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== +bach@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/bach/-/bach-1.2.0.tgz#4b3ce96bf27134f79a1b414a51c14e34c3bd9880" + integrity sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA= + dependencies: + arr-filter "^1.1.1" + arr-flatten "^1.0.1" + arr-map "^2.0.0" + array-each "^1.0.0" + array-initial "^1.0.0" + array-last "^1.1.1" + async-done "^1.2.2" + async-settle "^1.0.0" + now-and-later "^2.0.0" + backoff@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/backoff/-/backoff-2.5.0.tgz#f616eda9d3e4b66b8ca7fca79f695722c5f8e26f" @@ -3658,11 +3991,6 @@ bfj@^6.1.1: hoopy "^0.1.4" tryer "^1.0.1" -big.js@^3.1.3: - version "3.2.0" - resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" - integrity sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q== - big.js@^5.2.2: version "5.2.2" resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" @@ -3760,19 +4088,20 @@ bn.js@^5.1.1: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.1.tgz#48efc4031a9c4041b9c99c6941d903463ab62eb5" integrity sha512-IUTD/REb78Z2eodka1QZyyEk66pciRcP6Sroka0aI3tG/iwIdYLrBD62RsubR7vqdt3WyX8p4jxeatzmRSphtA== -bnc-onboard@1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/bnc-onboard/-/bnc-onboard-1.4.0.tgz#2645b3cc940addfd856c2952d63512e1ed23fc40" - integrity sha512-wPoVpvHe1Y4e97FuLUps/UZ+SFmS1Bzgxvg1JS6tPfapEA9QMg69qz4ye8WpcnbIroqrnB/wivOWxjkNLlthDg== +bnc-onboard@1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/bnc-onboard/-/bnc-onboard-1.5.0.tgz#dbb3dc62d8442827d6a3eb848a90f597fbf8916c" + integrity sha512-dKsAVqNNe94NrBdMa7gOQr/zjjcjn7HzqEsC36wSpyLcvAsPrd2cBiFSCgHftWYu/mkfFQXgdaoyJMV4orsd+Q== dependencies: "@ledgerhq/hw-app-eth" "^5.7.0" "@ledgerhq/hw-transport-u2f" "^5.7.0" "@portis/web3" "^2.0.0-beta.42" - "@toruslabs/torus-embed" "^1.1.1" + "@toruslabs/torus-embed" "^1.2.4" + "@unilogin/provider" "^0.5.20" "@walletconnect/web3-provider" "^1.0.0-beta.45" authereum "^0.0.4-beta.88" bignumber.js "^9.0.0" - bnc-sdk "1.1.0" + bnc-sdk "2.0.0" bowser "^2.5.2" ethereumjs-tx "^2.1.2" ethereumjs-util "^6.2.0" @@ -3784,11 +4113,12 @@ bnc-onboard@1.4.0: trezor-connect "7.0.1" web3-provider-engine "^15.0.4" -bnc-sdk@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/bnc-sdk/-/bnc-sdk-1.1.0.tgz#00a2a4387c2a507228d70cd622aaaf1423149a0a" - integrity sha512-H7T3982JS+h7EeokDivMuRyDmeo9riTc3kZBXCYFElflNMVm1M1sO91i+6YvCxVWi365Qv2FJcvhCwvOnyXTQQ== +bnc-sdk@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/bnc-sdk/-/bnc-sdk-2.0.0.tgz#90b5926a758b9c9050bcbd2854cf3502a5899aff" + integrity sha512-IPOtIR0qZ4MtnGlMXVsjxbShANbaIfxksVZOXh/4hjpcSRKI3Gc3N+hq+P0CqeN0nhTuDARkCavDrlq/oPKyUQ== dependencies: + crypto-es "^1.2.2" sturdy-websocket "^0.1.12" body-parser@1.19.0, body-parser@^1.16.0: @@ -3958,14 +4288,15 @@ browserify-zlib@^0.2.0: dependencies: pako "~1.0.5" -browserslist@4.8.6: - version "4.8.6" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.8.6.tgz#96406f3f5f0755d272e27a66f4163ca821590a7e" - integrity sha512-ZHao85gf0eZ0ESxLfCp73GG9O/VTytYDIkIiZDlURppLTI9wErSM/5yAKEq6rcUdxBLjMELmrYUJGg5sxGKMHg== +browserslist@4.10.0: + version "4.10.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.10.0.tgz#f179737913eaf0d2b98e4926ac1ca6a15cbcc6a9" + integrity sha512-TpfK0TDgv71dzuTsEAlQiHeWQ/tiPqgNZVdv046fvNtBZrjbv2O3TsWCDU0AWGJJKCF/KsjNdLzR9hXOsh/CfA== dependencies: - caniuse-lite "^1.0.30001023" - electron-to-chromium "^1.3.341" - node-releases "^1.1.47" + caniuse-lite "^1.0.30001035" + electron-to-chromium "^1.3.378" + node-releases "^1.1.52" + pkg-up "^3.1.0" browserslist@^3.2.6: version "3.2.8" @@ -3984,6 +4315,16 @@ browserslist@^4.0.0, browserslist@^4.8.3, browserslist@^4.8.5, browserslist@^4.9 electron-to-chromium "^1.3.363" node-releases "^1.1.50" +browserslist@^4.11.0: + version "4.11.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.11.0.tgz#aef4357b10a8abda00f97aac7cd587b2082ba1ad" + integrity sha512-WqEC7Yr5wUH5sg6ruR++v2SGOQYpyUdYYd4tZoAq1F7y+QXoLoYGXVbxhtaIqWmAJjtNTRjVD3HuJc1OXTel2A== + dependencies: + caniuse-lite "^1.0.30001035" + electron-to-chromium "^1.3.380" + node-releases "^1.1.52" + pkg-up "^3.1.0" + bs58@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/bs58/-/bs58-2.0.1.tgz#55908d58f1982aba2008fa1bed8f91998a29bf8d" @@ -4050,6 +4391,11 @@ buffer-crc32@~0.2.3: resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= +buffer-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.0.tgz#59616b498304d556abd466966b22eeda3eca5fbe" + integrity sha1-WWFrSYME1Var1GaWayLu2j7KX74= + buffer-fill@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" @@ -4232,13 +4578,13 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -camel-case@3.0.x: - version "3.0.0" - resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73" - integrity sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M= +camel-case@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.1.tgz#1fc41c854f00e2f7d0139dfeba1542d6896fe547" + integrity sha512-7fa2WcG4fYFkclIvEmxBbTvmibwF2/agfEBc6q3lOpVu0A13ltLsA+Hr/8Hp6kp5f+G7hKi6t8lys6XxP+1K6Q== dependencies: - no-case "^2.2.0" - upper-case "^1.1.1" + pascal-case "^3.1.1" + tslib "^1.10.0" camelcase-css@^2.0.1: version "2.0.1" @@ -4289,11 +4635,21 @@ 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.30001020, caniuse-lite@^1.0.30001023, caniuse-lite@^1.0.30001030: +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30001030: version "1.0.30001035" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001035.tgz#2bb53b8aa4716b2ed08e088d4dc816a5fe089a1e" integrity sha512-C1ZxgkuA4/bUEdMbU5WrGY4+UhMFFiXrgNAfxiMIqWgFTWfv/xsZCS2xEHT2LMq7xAZfuAnu6mcqyDl0ZR6wLQ== +caniuse-lite@^1.0.30001035: + version "1.0.30001036" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001036.tgz#930ea5272010d8bf190d859159d757c0b398caf0" + integrity sha512-jU8CIFIj2oR7r4W+5AKcsvWNVIb6Q6OZE3UsrXrZBHFtreT4YgTeOJtTucp+zSedEpTi3L5wASSP0LYIE3if6w== + +caniuse-lite@^1.0.30001036: + version "1.0.30001038" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001038.tgz#44da3cbca2ab6cb6aa83d1be5d324e17f141caff" + integrity sha512-zii9quPo96XfOiRD4TrfYGs+QsGZpb2cGiMAzPjtf/hpFgB6zCPZgJb7I1+EATeMw/o+lG8FyRAnI+CWStHcaQ== + capture-exit@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" @@ -4398,7 +4754,7 @@ cheerio@1.0.0-rc.2: lodash "^4.15.0" parse5 "^3.0.1" -chokidar@^2.0.2, chokidar@^2.1.8: +chokidar@^2.0.0, chokidar@^2.0.2, chokidar@^2.1.8: version "2.1.8" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== @@ -4472,7 +4828,7 @@ classnames@^2.2.5, classnames@^2.2.6: resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== -clean-css@4.2.x: +clean-css@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.3.tgz#507b5de7d97b48ee53d84adb0160ff6216380f78" integrity sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA== @@ -4552,6 +4908,11 @@ cliui@^6.0.0: strip-ansi "^6.0.0" wrap-ansi "^6.2.0" +clone-buffer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" + integrity sha1-4+JbIHrE5wGvch4staFnksrD3Fg= + clone-response@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" @@ -4564,6 +4925,11 @@ clone-stats@^0.0.1: resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1" integrity sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE= +clone-stats@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680" + integrity sha1-s3gt/4u1R04Yuba/D9/ngvh3doA= + clone@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.1.tgz#d217d1e961118e3ac9a4b8bba3285553bf647cdb" @@ -4579,6 +4945,15 @@ clone@^1.0.0, clone@^1.0.2: resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= +cloneable-readable@^1.0.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/cloneable-readable/-/cloneable-readable-1.1.3.tgz#120a00cb053bfb63a222e709f9683ea2e11d8cec" + integrity sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ== + dependencies: + inherits "^2.0.1" + process-nextick-args "^2.0.0" + readable-stream "^2.3.5" + clsx@^1.0.2, clsx@^1.0.4: version "1.1.0" resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.0.tgz#62937c6adfea771247c34b54d320fb99624f5702" @@ -4616,6 +4991,15 @@ collect-v8-coverage@^1.0.0: resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.0.tgz#150ee634ac3650b71d9c985eb7f608942334feb1" integrity sha512-VKIhJgvk8E1W28m5avZ2Gv2Ruv5YiF56ug2oclvaG9md69BuZImMG2sk9g7QNKLUbtYAKQjXjYxbYZVUlMMKmQ== +collection-map@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-map/-/collection-map-1.0.0.tgz#aea0f06f8d26c780c2b75494385544b2255af18c" + integrity sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw= + dependencies: + arr-map "^2.0.2" + for-own "^1.0.0" + make-iterator "^1.0.0" + collection-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" @@ -4666,6 +5050,11 @@ color-string@^1.5.2: color-name "^1.0.0" simple-swizzle "^0.2.2" +color-support@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" + integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== + color@^3.0.0: version "3.1.2" resolved "https://registry.yarnpkg.com/color/-/color-3.1.2.tgz#68148e7f85d41ad7649c5fa8c8106f098d229e10" @@ -4696,11 +5085,6 @@ commander@2.15.1: resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== -commander@2.17.x: - version "2.17.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" - integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== - commander@3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" @@ -4711,16 +5095,11 @@ commander@^2.11.0, commander@^2.18.0, commander@^2.20.0: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== -commander@^4.0.1: +commander@^4.0.1, commander@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== -commander@~2.19.0: - version "2.19.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" - integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== - commander@~2.8.1: version "2.8.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" @@ -4782,7 +5161,7 @@ concat-stream@1.5.1: readable-stream "~2.0.0" typedarray "~0.0.5" -concat-stream@^1.5.0, concat-stream@^1.5.1: +concat-stream@^1.5.0, concat-stream@^1.5.1, concat-stream@^1.6.0: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== @@ -4809,10 +5188,10 @@ connect-history-api-fallback@^1.6.0: resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== -connected-react-router@6.7.0: - version "6.7.0" - resolved "https://registry.yarnpkg.com/connected-react-router/-/connected-react-router-6.7.0.tgz#1c37a65684f1729533264c1b1903ee91c8ca3a15" - integrity sha512-RDmcmiwSfUWQ3U7J7RVkc9cwNtek26fUn0DWpA8pS7JylC97VNeosrsIxjJ/3CGDrzZPqnc0Hr/kZxjh75JGlw== +connected-react-router@6.8.0: + version "6.8.0" + resolved "https://registry.yarnpkg.com/connected-react-router/-/connected-react-router-6.8.0.tgz#ddc687b31d498322445d235d660798489fa56cae" + integrity sha512-E64/6krdJM3Ag3MMmh2nKPtMbH15s3JQDuaYJvOVXzu6MbHbDyIvuwLOyhQIuP4Om9zqEfZYiVyflROibSsONg== dependencies: prop-types "^15.7.2" @@ -4843,7 +5222,7 @@ content-type@~1.0.4: resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== -convert-source-map@1.X, convert-source-map@^1.1.0, convert-source-map@^1.4.0, convert-source-map@^1.5.1, convert-source-map@^1.6.0, convert-source-map@^1.7.0: +convert-source-map@1.X, convert-source-map@^1.1.0, convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.5.1, convert-source-map@^1.6.0, convert-source-map@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== @@ -4882,6 +5261,14 @@ copy-descriptor@^0.1.0: resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= +copy-props@^2.0.1: + version "2.0.4" + resolved "https://registry.yarnpkg.com/copy-props/-/copy-props-2.0.4.tgz#93bb1cadfafd31da5bb8a9d4b41f471ec3a72dfe" + integrity sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A== + dependencies: + each-props "^1.3.0" + is-plain-object "^2.0.1" + core-js-compat@^3.6.2: version "3.6.4" resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.6.4.tgz#938476569ebb6cda80d339bcf199fae4f16fff17" @@ -5034,6 +5421,11 @@ crypto-browserify@3.12.0, crypto-browserify@^3.11.0: randombytes "^2.0.0" randomfill "^1.0.3" +crypto-es@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/crypto-es/-/crypto-es-1.2.2.tgz#ed36b08af530808dff2214ffe696a2ae62497640" + integrity sha512-opab8M4wcsMWMDAMl+2G7inqlVyvAGNsJT8eOQRBOKNqsSFPQ8/WLP9tp0Q7bVxeNp/1e9TWn/x5GmcUVhRDUg== + crypto-js@^3.1.4, crypto-js@^3.1.9-1: version "3.3.0" resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-3.3.0.tgz#846dd1cce2f68aacfa156c8578f926a609b7976b" @@ -5310,10 +5702,10 @@ data-urls@^1.1.0: whatwg-mimetype "^2.2.0" whatwg-url "^7.0.0" -date-fns@2.10.0: - version "2.10.0" - resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.10.0.tgz#abd10604d8bafb0bcbd2ba2e9b0563b922ae4b6b" - integrity sha512-EhfEKevYGWhWlZbNeplfhIU/+N+x0iCIx7VzKlXma2EdQyznVlZhCptXUY+BegNpPW2kjdx15Rvq503YcXXrcA== +date-fns@2.11.1: + version "2.11.1" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.11.1.tgz#197b8be1bbf5c5e6fe8bea817f0fe111820e7a12" + integrity sha512-3RdUoinZ43URd2MJcquzBbDQo+J87cSzB8NkXdZiN5ia1UNyep0oCyitfiL88+R7clGTeq/RniXAc16gWyAu1w== date-fns@^1.27.2: version "1.30.1" @@ -5464,6 +5856,18 @@ deep-is@~0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= +deepmerge@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" + integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== + +default-compare@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/default-compare/-/default-compare-1.0.0.tgz#cb61131844ad84d84788fb68fd01681ca7781a2f" + integrity sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ== + dependencies: + kind-of "^5.0.2" + default-gateway@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-4.2.0.tgz#167104c7500c2115f6dd69b0a536bb8ed720552b" @@ -5472,6 +5876,11 @@ default-gateway@^4.2.0: execa "^1.0.0" ip-regex "^2.1.0" +default-resolution@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/default-resolution/-/default-resolution-2.0.0.tgz#bcb82baa72ad79b426a76732f1a81ad6df26d684" + integrity sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ= + defaults@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" @@ -5637,6 +6046,11 @@ diff-sequences@^25.1.0: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-25.1.0.tgz#fd29a46f1c913fd66c22645dc75bffbe43051f32" integrity sha512-nFIfVk5B/NStCsJ+zaPO4vYuLjlzQ6uFvPxzYyHlejNZ/UGa7G/n7peOXVrVNvRuyfstt+mZQYGpjxg9Z6N8Kw== +diff-sequences@^25.2.1: + version "25.2.1" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-25.2.1.tgz#fcfe8aa07dd9b0c648396a478dabca8e76c6ab27" + integrity sha512-foe7dXnGlSh3jR1ovJmdv+77VQj98eKCHHwJPbZ2eEf0fHwKbkZicpPxEch9smZ+n2dnF6QFwkOQdLq9hpeJUg== + diff@3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" @@ -5721,7 +6135,7 @@ dom-helpers@^5.0.1: "@babel/runtime" "^7.6.3" csstype "^2.6.7" -dom-serializer@0: +dom-serializer@0, dom-serializer@^0.2.1: version "0.2.2" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g== @@ -5778,6 +6192,13 @@ domhandler@^2.3.0: dependencies: domelementtype "1" +domhandler@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-3.0.0.tgz#51cd13efca31da95bbb0c5bee3a48300e333b3e9" + integrity sha512-eKLdI5v9m67kbXQbJSNn1zjh0SDzvzWVWtX+qEI3eMjZw8daH9k8rlj1FZY9memPwjiskQFbe7vHVVJIAqoEhw== + dependencies: + domelementtype "^2.0.1" + domutils@1.5, domutils@1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" @@ -5794,6 +6215,23 @@ domutils@^1.5.1, domutils@^1.7.0: dom-serializer "0" domelementtype "1" +domutils@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.0.0.tgz#15b8278e37bfa8468d157478c58c367718133c08" + integrity sha512-n5SelJ1axbO636c2yUtOGia/IcJtVtlhQbFiVDBZHKV5ReJO1ViX7sFEemtuyoAnBxk5meNSYgA8V4s0271efg== + dependencies: + dom-serializer "^0.2.1" + domelementtype "^2.0.1" + domhandler "^3.0.0" + +dot-case@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.3.tgz#21d3b52efaaba2ea5fda875bb1aa8124521cf4aa" + integrity sha512-7hwEmg6RiSQfm/GwPL4AAWXKy3YNNZA3oFv2Pdiey0mwkRCPZ9x6SZbkLcn8Ma5PYeVokzoD4Twv2n7LKp5WeA== + dependencies: + no-case "^3.0.3" + tslib "^1.10.0" + dot-prop@^4.1.0: version "4.2.0" resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" @@ -5854,6 +6292,14 @@ duplexify@^3.2.0, duplexify@^3.4.2, duplexify@^3.6.0: readable-stream "^2.0.0" stream-shift "^1.0.0" +each-props@^1.3.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/each-props/-/each-props-1.3.2.tgz#ea45a414d16dd5cfa419b1a81720d5ca06892333" + integrity sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA== + dependencies: + is-plain-object "^2.0.1" + object.defaults "^1.1.0" + easy-stack@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/easy-stack/-/easy-stack-1.0.0.tgz#12c91b3085a37f0baa336e9486eac4bf94e3e788" @@ -5889,11 +6335,21 @@ ejs@^2.6.1: resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.4.tgz#48661287573dcc53e366c7a1ae52c3a120eec9ba" integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA== -electron-to-chromium@^1.3.341, electron-to-chromium@^1.3.363, electron-to-chromium@^1.3.47: +electron-to-chromium@^1.3.363, electron-to-chromium@^1.3.47: version "1.3.376" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.376.tgz#7cb7b5205564a06c8f8ecfbe832cbd47a1224bb1" integrity sha512-cv/PYVz5szeMz192ngilmezyPNFkUjuynuL2vNdiqIrio440nfTDdc0JJU0TS2KHLSVCs9gBbt4CFqM+HcBnjw== +electron-to-chromium@^1.3.378: + version "1.3.380" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.380.tgz#1e1f07091b42b54bccd0ad6d3a14f2b73b60dc9d" + integrity sha512-2jhQxJKcjcSpVOQm0NAfuLq8o+130blrcawoumdXT6411xG/xIAOyZodO/y7WTaYlz/NHe3sCCAe/cJLnDsqTw== + +electron-to-chromium@^1.3.380: + version "1.3.386" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.386.tgz#224f97c808da76014096848f80bb9342b6a95cdb" + integrity sha512-M7JHfp32Bq6Am59AWgglh2d3nqe6y8Y94Vcb/AXUsO3DGvKUHYI5ML9+U5oNShfdOEfurrrjKSoSgFt2mz7mpw== + elegant-spinner@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e" @@ -6063,7 +6519,7 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" -es5-ext@^0.10.35, es5-ext@^0.10.50: +es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50: version "0.10.53" resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1" integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q== @@ -6072,7 +6528,7 @@ es5-ext@^0.10.35, es5-ext@^0.10.50: es6-symbol "~3.1.3" next-tick "~1.0.0" -es6-iterator@~2.0.3: +es6-iterator@^2.0.1, es6-iterator@^2.0.3, es6-iterator@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= @@ -6094,13 +6550,15 @@ es6-symbol@^3.1.1, es6-symbol@~3.1.3: d "^1.0.1" ext "^1.1.2" -es6-templates@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/es6-templates/-/es6-templates-0.2.3.tgz#5cb9ac9fb1ded6eb1239342b81d792bbb4078ee4" - integrity sha1-XLmsn7He1usSOTQrgdeSu7QHjuQ= +es6-weak-map@^2.0.1: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.3.tgz#b6da1f16cc2cc0d9be43e6bdbfc5e7dfcdf31d53" + integrity sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA== dependencies: - recast "~0.11.12" - through "~2.3.6" + d "1" + es5-ext "^0.10.46" + es6-iterator "^2.0.3" + es6-symbol "^3.1.1" escape-html@1.0.3, escape-html@~1.0.3: version "1.0.3" @@ -6146,10 +6604,10 @@ esdoc@^1.0.4: minimist "1.2.0" taffydb "2.7.3" -eslint-config-prettier@^6.10.0: - version "6.10.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.10.0.tgz#7b15e303bf9c956875c948f6b21500e48ded6a7f" - integrity sha512-AtndijGte1rPILInUdHjvKEGbIV06NuvPrqlIEaEaWtbtvJh464mDeyGMdZEQMsGvC0ZVkiex1fSNcC4HAbRGg== +eslint-config-prettier@6.10.1: + version "6.10.1" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.10.1.tgz#129ef9ec575d5ddc0e269667bf09defcd898642a" + integrity sha512-svTy6zh1ecQojvpbJSgH3aei/Rt7C6i090l5f2WQ4aB05lYHeZIR1qL4wZyyILTbtmnbHP5Yn8MrsOJMGa8RkQ== dependencies: get-stdin "^6.0.0" @@ -6169,17 +6627,17 @@ eslint-module-utils@^2.4.1: debug "^2.6.9" pkg-dir "^2.0.0" -eslint-plugin-flowtype@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-4.6.0.tgz#82b2bd6f21770e0e5deede0228e456cb35308451" - integrity sha512-W5hLjpFfZyZsXfo5anlu7HM970JBDqbEshAJUkeczP6BFCIfJXuiIBQXyberLRtOStT0OGPF8efeTbxlHk4LpQ== +eslint-plugin-flowtype@4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-4.7.0.tgz#903a6ea3eb5cbf4c7ba7fa73cc43fc39ab7e4a70" + integrity sha512-M+hxhSCk5QBEValO5/UqrS4UunT+MgplIJK5wA1sCtXjzBcZkpTGRwxmLHhGpbHcrmQecgt6ZL/KDdXWqGB7VA== dependencies: lodash "^4.17.15" -eslint-plugin-import@^2.20.1: - version "2.20.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.20.1.tgz#802423196dcb11d9ce8435a5fc02a6d3b46939b3" - integrity sha512-qQHgFOTjguR+LnYRoToeZWT62XM55MBVXObHM6SKFd1VzDcX/vqT1kAz8ssqigh5eMj8qXcRoXXGZpPP6RfdCw== +eslint-plugin-import@2.20.2: + version "2.20.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.20.2.tgz#91fc3807ce08be4837141272c8b99073906e588d" + integrity sha512-FObidqpXrR8OnCh4iNsxy+WACztJLXAHBO5hK79T1Hc77PgQZkyDGA5Ag9xAvRpglvLNxhH/zSmZ70/pZ31dHg== dependencies: array-includes "^3.0.3" array.prototype.flat "^1.2.1" @@ -6377,11 +6835,6 @@ esprima@^4.0.0, esprima@^4.0.1: resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esprima@~3.1.0: - version "3.1.3" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" - integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM= - esquery@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.1.0.tgz#c5c0b66f383e7656404f86b31334d72524eddb48" @@ -6406,7 +6859,7 @@ estree-walker@^0.6.1: resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.1.tgz#53049143f40c6eb918b23671d1fe3219f3a1b362" integrity sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w== -esutils@^2.0.0, esutils@^2.0.2: +esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== @@ -7158,17 +7611,17 @@ expand-tilde@^2.0.0, expand-tilde@^2.0.2: dependencies: homedir-polyfill "^1.0.1" -expect@^25.1.0: - version "25.1.0" - resolved "https://registry.yarnpkg.com/expect/-/expect-25.1.0.tgz#7e8d7b06a53f7d66ec927278db3304254ee683ee" - integrity sha512-wqHzuoapQkhc3OKPlrpetsfueuEiMf3iWh0R8+duCu9PIjXoP7HgD5aeypwTnXUAjC8aMsiVDaWwlbJ1RlQ38g== +expect@^25.2.4: + version "25.2.4" + resolved "https://registry.yarnpkg.com/expect/-/expect-25.2.4.tgz#b66e0777c861034ebc21730bb34e1839d5d46806" + integrity sha512-hfuPhPds4yOsZtIw4kwAg70r0hqGmpqekgA+VX7pf/3wZ6FY+xIOXZhNsPMMMsspYG/YIsbAiwqsdnD4Ht+bCA== dependencies: - "@jest/types" "^25.1.0" + "@jest/types" "^25.2.3" ansi-styles "^4.0.0" - jest-get-type "^25.1.0" - jest-matcher-utils "^25.1.0" - jest-message-util "^25.1.0" - jest-regex-util "^25.1.0" + jest-get-type "^25.2.1" + jest-matcher-utils "^25.2.3" + jest-message-util "^25.2.4" + jest-regex-util "^25.2.1" express@^4.14.0, express@^4.16.3, express@^4.17.1: version "4.17.1" @@ -7290,6 +7743,16 @@ fake-merkle-patricia-tree@^1.0.1: dependencies: checkpoint-store "^1.1.0" +fancy-log@^1.3.2: + version "1.3.3" + resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.3.tgz#dbc19154f558690150a23953a0adbd035be45fc7" + integrity sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw== + dependencies: + ansi-gray "^0.1.1" + color-support "^1.1.3" + parse-node-version "^1.0.0" + time-stamp "^1.0.0" + fast-deep-equal@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4" @@ -7327,11 +7790,6 @@ 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== -fastparse@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9" - integrity sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ== - faye-websocket@^0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4" @@ -7414,13 +7872,13 @@ file-entry-cache@^5.0.1: dependencies: flat-cache "^2.0.1" -file-loader@5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-5.1.0.tgz#cb56c070efc0e40666424309bd0d9e45ac6f2bb8" - integrity sha512-u/VkLGskw3Ue59nyOwUwXI/6nuBCo7KBkniB/l7ICwr/7cPNGsL1WCXUp3GB0qgOOKU1TiP49bv4DZF/LJqprg== +file-loader@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.0.0.tgz#97bbfaab7a2460c07bcbd72d3a6922407f67649f" + integrity sha512-/aMOAYEFXDdjG0wytpTL5YQLfZnnTmLNjn+AIrJ/6HVnTfDqLsVKUUwkDf4I4kgex36BvjuXEn/TX9B/1ESyqQ== dependencies: - loader-utils "^1.4.0" - schema-utils "^2.5.0" + loader-utils "^2.0.0" + schema-utils "^2.6.5" file-type@^3.8.0: version "3.9.0" @@ -7505,7 +7963,7 @@ finalhandler@~1.1.2: statuses "~1.5.0" unpipe "~1.0.0" -find-cache-dir@^2.0.0, find-cache-dir@^2.1.0: +find-cache-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== @@ -7560,7 +8018,7 @@ find-versions@^3.2.0: dependencies: semver-regex "^2.0.0" -findup-sync@3.0.0: +findup-sync@3.0.0, findup-sync@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-3.0.0.tgz#17b108f9ee512dfb7a5c7f3c8b27ea9e1a9c08d1" integrity sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg== @@ -7570,11 +8028,37 @@ findup-sync@3.0.0: micromatch "^3.0.4" resolve-dir "^1.0.1" +findup-sync@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc" + integrity sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw= + dependencies: + detect-file "^1.0.0" + is-glob "^3.1.0" + micromatch "^3.0.4" + resolve-dir "^1.0.1" + +fined@^1.0.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/fined/-/fined-1.2.0.tgz#d00beccf1aa2b475d16d423b0238b713a2c4a37b" + integrity sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng== + dependencies: + expand-tilde "^2.0.2" + is-plain-object "^2.0.3" + object.defaults "^1.1.0" + object.pick "^1.2.0" + parse-filepath "^1.0.1" + first-chunk-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz#59bfb50cd905f60d7c394cd3d9acaab4e6ad934e" integrity sha1-Wb+1DNkF9g18OUzT2ayqtOatk04= +flagged-respawn@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/flagged-respawn/-/flagged-respawn-1.0.1.tgz#e7de6f1279ddd9ca9aac8a5971d618606b3aab41" + integrity sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q== + flat-cache@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" @@ -7589,17 +8073,17 @@ flatted@^2.0.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08" integrity sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg== -flow-bin@0.120.1: - version "0.120.1" - resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.120.1.tgz#ab051d6df71829b70a26a2c90bb81f9d43797cae" - integrity sha512-KgE+d+rKzdXzhweYVJty1QIOOZTTbtnXZf+4SLnmArLvmdfeLreQOZpeLbtq5h79m7HhDzX/HkUkoyu/fmSC2A== +flow-bin@0.121.0: + version "0.121.0" + resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.121.0.tgz#e206bdc3d510277f9a847920540f72c49e87c130" + integrity sha512-QYRMs+AoMLj/OTaSo9+8c3kzM/u8YgvfrInp0qzhtzC02Sc2jb3BV/QZWZGjPo+XK3twyyqXrcI3s8MuL1UQRg== flow-stoplight@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/flow-stoplight/-/flow-stoplight-1.0.0.tgz#4a292c5bcff8b39fa6cc0cb1a853d86f27eeff7b" integrity sha1-SiksW8/4s5+mzAyxqFPYbyfu/3s= -flush-write-stream@^1.0.0: +flush-write-stream@^1.0.0, flush-write-stream@^1.0.2: version "1.1.1" resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8" integrity sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w== @@ -7640,6 +8124,13 @@ for-own@^0.1.4: dependencies: for-in "^1.0.1" +for-own@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/for-own/-/for-own-1.0.0.tgz#c63332f415cedc4b04dbfe70cf836494c53cb44b" + integrity sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs= + dependencies: + for-in "^1.0.1" + foreach@^2.0.4: version "2.0.5" resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" @@ -7728,14 +8219,15 @@ fs-extra@6.0.1, fs-extra@^6.0.1: jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@8.1.0, fs-extra@^8.0.1: - version "8.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" - integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== +fs-extra@9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.0.0.tgz#b6afc31036e247b2466dc99c29ae797d5d4580a3" + integrity sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g== dependencies: + at-least-node "^1.0.0" graceful-fs "^4.2.0" - jsonfile "^4.0.0" - universalify "^0.1.0" + jsonfile "^6.0.1" + universalify "^1.0.0" fs-extra@^0.24.0: version "0.24.0" @@ -7784,6 +8276,15 @@ fs-extra@^7.0.0, fs-extra@^7.0.1: jsonfile "^4.0.0" universalify "^0.1.0" +fs-extra@^8.0.1: + version "8.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" + integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^4.0.0" + universalify "^0.1.0" + fs-minipass@^1.2.5: version "1.2.7" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" @@ -7798,6 +8299,14 @@ fs-minipass@^2.0.0: dependencies: minipass "^3.0.0" +fs-mkdirp-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz#0b7815fc3201c6a69e14db98ce098c16935259eb" + integrity sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes= + dependencies: + graceful-fs "^4.1.11" + through2 "^2.0.3" + fs-readdir-recursive@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27" @@ -8025,11 +8534,39 @@ glob-stream@^5.3.2: to-absolute-glob "^0.1.1" unique-stream "^2.0.2" +glob-stream@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-6.1.0.tgz#7045c99413b3eb94888d83ab46d0b404cc7bdde4" + integrity sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ= + dependencies: + extend "^3.0.0" + glob "^7.1.1" + glob-parent "^3.1.0" + is-negated-glob "^1.0.0" + ordered-read-streams "^1.0.0" + pumpify "^1.3.5" + readable-stream "^2.1.5" + remove-trailing-separator "^1.0.1" + to-absolute-glob "^2.0.0" + unique-stream "^2.0.2" + glob-to-regexp@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= +glob-watcher@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/glob-watcher/-/glob-watcher-5.0.3.tgz#88a8abf1c4d131eb93928994bc4a593c2e5dd626" + integrity sha512-8tWsULNEPHKQ2MR4zXuzSmqbdyV5PtwwCaWSGQ1WwHsJ07ilNeN1JB8ntxhckbnpSHaf9dXFUHzIWvm1I13dsg== + dependencies: + anymatch "^2.0.0" + async-done "^1.2.0" + chokidar "^2.0.0" + is-negated-glob "^1.0.0" + just-debounce "^1.0.0" + object.defaults "^1.1.0" + glob@7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" @@ -8170,6 +8707,13 @@ globby@^6.1.0: pify "^2.0.0" pinkie-promise "^2.0.0" +glogg@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.2.tgz#2d7dd702beda22eb3bffadf880696da6d846313f" + integrity sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA== + dependencies: + sparkles "^1.0.0" + got@9.6.0: version "9.6.0" resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" @@ -8232,6 +8776,30 @@ gud@^1.0.0: resolved "https://registry.yarnpkg.com/gud/-/gud-1.0.0.tgz#a489581b17e6a70beca9abe3ae57de7a499852c0" integrity sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw== +gulp-cli@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/gulp-cli/-/gulp-cli-2.2.0.tgz#5533126eeb7fe415a7e3e84a297d334d5cf70ebc" + integrity sha512-rGs3bVYHdyJpLqR0TUBnlcZ1O5O++Zs4bA0ajm+zr3WFCfiSLjGwoCBqFs18wzN+ZxahT9DkOK5nDf26iDsWjA== + dependencies: + ansi-colors "^1.0.1" + archy "^1.0.0" + array-sort "^1.0.0" + color-support "^1.1.3" + concat-stream "^1.6.0" + copy-props "^2.0.1" + fancy-log "^1.3.2" + gulplog "^1.0.0" + interpret "^1.1.0" + isobject "^3.0.1" + liftoff "^3.1.0" + matchdep "^2.0.0" + mute-stdout "^1.0.0" + pretty-hrtime "^1.0.0" + replace-homedir "^1.0.0" + semver-greatest-satisfied-range "^1.1.0" + v8flags "^3.0.1" + yargs "^7.1.0" + gulp-sourcemaps@^1.5.2: version "1.12.1" resolved "https://registry.yarnpkg.com/gulp-sourcemaps/-/gulp-sourcemaps-1.12.1.tgz#b437d1f3d980cf26e81184823718ce15ae6597b6" @@ -8249,6 +8817,23 @@ gulp-sourcemaps@^1.5.2: through2 "2.X" vinyl "1.X" +gulp@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/gulp/-/gulp-4.0.2.tgz#543651070fd0f6ab0a0650c6a3e6ff5a7cb09caa" + integrity sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA== + dependencies: + glob-watcher "^5.0.3" + gulp-cli "^2.2.0" + undertaker "^1.2.1" + vinyl-fs "^3.0.0" + +gulplog@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/gulplog/-/gulplog-1.0.0.tgz#e28c4d45d05ecbbed818363ce8f9c5926229ffe5" + integrity sha1-4oxNRdBey77YGDY86PnFkmIp/+U= + dependencies: + glogg "^1.0.0" + gzip-size@5.1.1, gzip-size@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.1.1.tgz#cb9bee692f87c0612b232840a873904e4c135274" @@ -8393,7 +8978,7 @@ he@1.1.1: resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= -he@1.2.x: +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== @@ -8434,7 +9019,7 @@ hoist-non-react-statics@^2.3.1: resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47" integrity sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw== -hoist-non-react-statics@^3.0.0, hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.2.1, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: +hoist-non-react-statics@^3.0.0, hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== @@ -8508,41 +9093,43 @@ html-escaper@^2.0.0: resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.0.tgz#71e87f931de3fe09e56661ab9a29aadec707b491" integrity sha512-a4u9BeERWGu/S8JiWEAQcdrg9v4QArtP9keViQjGMdff20fBdd8waotXaNmODqBe6uZ3Nafi7K/ho4gCQHV3Ig== -html-loader@^0.5.5: - version "0.5.5" - resolved "https://registry.yarnpkg.com/html-loader/-/html-loader-0.5.5.tgz#6356dbeb0c49756d8ebd5ca327f16ff06ab5faea" - integrity sha512-7hIW7YinOYUpo//kSYcPB6dCKoceKLmOwjEMmhIobHuWGDVl0Nwe4l68mdG/Ru0wcUxQjVMEoZpkalZ/SE7zog== +html-loader@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/html-loader/-/html-loader-1.0.0.tgz#40000ff27bfb4fbf087d37f8438cae0b1d8b53b1" + integrity sha512-acPyjP9Mo05jEbe/oejXu5gFwtKWdFewPoaVa47VCnHmRbR43jtdx/kPhPEbCBm2qWtIn+a8uTJAW4Ocnn4olw== dependencies: - es6-templates "^0.2.3" - fastparse "^1.1.1" - html-minifier "^3.5.8" - loader-utils "^1.1.0" - object-assign "^4.1.1" + html-minifier-terser "^5.0.4" + htmlparser2 "^4.1.0" + loader-utils "^2.0.0" + parse-srcset "^1.0.2" + schema-utils "^2.6.5" -html-minifier@^3.2.3, html-minifier@^3.5.8: - version "3.5.21" - resolved "https://registry.yarnpkg.com/html-minifier/-/html-minifier-3.5.21.tgz#d0040e054730e354db008463593194015212d20c" - integrity sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA== +html-minifier-terser@^5.0.1, html-minifier-terser@^5.0.4: + version "5.0.4" + resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-5.0.4.tgz#e8cc02748acb983bd7912ea9660bd31c0702ec32" + integrity sha512-fHwmKQ+GzhlqdxEtwrqLT7MSuheiA+rif5/dZgbz3GjoMXJzcRzy1L9NXoiiyxrnap+q5guSiv8Tz5lrh9g42g== dependencies: - camel-case "3.0.x" - clean-css "4.2.x" - commander "2.17.x" - he "1.2.x" - param-case "2.1.x" - relateurl "0.2.x" - uglify-js "3.4.x" + camel-case "^4.1.1" + clean-css "^4.2.3" + commander "^4.1.1" + he "^1.2.0" + param-case "^3.0.3" + relateurl "^0.2.7" + terser "^4.6.3" -html-webpack-plugin@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz#b01abbd723acaaa7b37b6af4492ebda03d9dd37b" - integrity sha1-sBq71yOsqqeze2r0SS69oD2d03s= +html-webpack-plugin@4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-4.0.3.tgz#70659c8836210249cb6fa9dd6706a957547666d5" + integrity sha512-XCm5MGK6Yv/ey30fbhqjKIGm1r6G1HxmNorJ/xUdL/Zj3mOLtb9ZHEEIw0e4h3VzgyUrp8szCJh3VN9z1LNx7A== dependencies: - html-minifier "^3.2.3" - loader-utils "^0.2.16" - lodash "^4.17.3" - pretty-error "^2.0.2" - tapable "^1.0.0" - toposort "^1.0.0" + "@types/html-minifier-terser" "^5.0.0" + "@types/tapable" "^1.0.5" + "@types/webpack" "^4.41.8" + html-minifier-terser "^5.0.1" + loader-utils "^1.2.3" + lodash "^4.17.15" + pretty-error "^2.1.1" + tapable "^1.1.3" util.promisify "1.0.0" htmlparser2@^3.3.0, htmlparser2@^3.9.1: @@ -8557,6 +9144,16 @@ htmlparser2@^3.3.0, htmlparser2@^3.9.1: inherits "^2.0.1" readable-stream "^3.1.1" +htmlparser2@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-4.1.0.tgz#9a4ef161f2e4625ebf7dfbe6c0a2f52d18a59e78" + integrity sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q== + dependencies: + domelementtype "^2.0.1" + domhandler "^3.0.0" + domutils "^2.0.0" + entities "^2.0.0" + htmlparser2@~3.8.1: version "3.8.3" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.8.3.tgz#996c28b191516a8be86501a7d79757e5c70c1068" @@ -8929,7 +9526,7 @@ internal-slot@^1.0.2: has "^1.0.3" side-channel "^1.0.2" -interpret@1.2.0, interpret@^1.0.0: +interpret@1.2.0, interpret@^1.0.0, interpret@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw== @@ -8983,6 +9580,14 @@ is-absolute-url@^3.0.3: resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-3.0.3.tgz#96c6a22b6a23929b11ea0afb1836c36ad4a5d698" integrity sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q== +is-absolute@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-1.0.0.tgz#395e1ae84b11f26ad1795e73c17378e48a301576" + integrity sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA== + dependencies: + is-relative "^1.0.0" + is-windows "^1.0.1" + is-accessor-descriptor@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" @@ -9214,6 +9819,11 @@ is-natural-number@^4.0.1: resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" integrity sha1-q5124dtM7VHjXeDHLr7PCfc0zeg= +is-negated-glob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz#6910bca5da8c95e784b5751b976cf5a10fee36d2" + integrity sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI= + is-number@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" @@ -9303,7 +9913,7 @@ is-plain-obj@^1.0.0, is-plain-obj@^1.1.0: resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= -is-plain-object@^2.0.3, is-plain-object@^2.0.4: +is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== @@ -9344,6 +9954,13 @@ is-regexp@^1.0.0: resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk= +is-relative@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d" + integrity sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA== + dependencies: + is-unc-path "^1.0.0" + is-resolvable@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" @@ -9393,7 +10010,14 @@ is-typedarray@^1.0.0, is-typedarray@~1.0.0: resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= -is-utf8@^0.2.0: +is-unc-path@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-1.0.0.tgz#d731e8898ed090a12c352ad2eaed5095ad322c9d" + integrity sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ== + dependencies: + unc-path-regex "^0.1.2" + +is-utf8@^0.2.0, is-utf8@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= @@ -9403,6 +10027,11 @@ is-valid-glob@^0.3.0: resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-0.3.0.tgz#d4b55c69f51886f9b65c70d6c2622d37e29f48fe" integrity sha1-1LVcafUYhvm2XHDWwmItN+KfSP4= +is-valid-glob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-1.0.0.tgz#29bf3eff701be2d4d315dbacc39bc39fe8f601aa" + integrity sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao= + is-windows@^1.0.1, is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" @@ -9510,56 +10139,57 @@ isurl@^1.0.0-alpha5: has-to-string-tag-x "^1.2.0" is-object "^1.0.1" -jest-changed-files@^25.1.0: - version "25.1.0" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-25.1.0.tgz#73dae9a7d9949fdfa5c278438ce8f2ff3ec78131" - integrity sha512-bdL1aHjIVy3HaBO3eEQeemGttsq1BDlHgWcOjEOIAcga7OOEGWHD2WSu8HhL7I1F0mFFyci8VKU4tRNk+qtwDA== +jest-changed-files@^25.2.3: + version "25.2.3" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-25.2.3.tgz#ad19deef9e47ba37efb432d2c9a67dfd97cc78af" + integrity sha512-EFxy94dvvbqRB36ezIPLKJ4fDIC+jAdNs8i8uTwFpaXd6H3LVc3ova1lNS4ZPWk09OCR2vq5kSdSQgar7zMORg== dependencies: - "@jest/types" "^25.1.0" + "@jest/types" "^25.2.3" execa "^3.2.0" throat "^5.0.0" -jest-cli@^25.1.0: - version "25.1.0" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-25.1.0.tgz#75f0b09cf6c4f39360906bf78d580be1048e4372" - integrity sha512-p+aOfczzzKdo3AsLJlhs8J5EW6ffVidfSZZxXedJ0mHPBOln1DccqFmGCoO8JWd4xRycfmwy1eoQkMsF8oekPg== +jest-cli@^25.2.4: + version "25.2.4" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-25.2.4.tgz#021c2383904696597abc060dcb133c82ebd8bfcc" + integrity sha512-zeY2pRDWKj2LZudIncvvguwLMEdcnJqc2jJbwza1beqi80qqLvkPF/BjbFkK2sIV3r+mfTJS+7ITrvK6pCdRjg== dependencies: - "@jest/core" "^25.1.0" - "@jest/test-result" "^25.1.0" - "@jest/types" "^25.1.0" + "@jest/core" "^25.2.4" + "@jest/test-result" "^25.2.4" + "@jest/types" "^25.2.3" chalk "^3.0.0" exit "^0.1.2" import-local "^3.0.2" is-ci "^2.0.0" - jest-config "^25.1.0" - jest-util "^25.1.0" - jest-validate "^25.1.0" + jest-config "^25.2.4" + jest-util "^25.2.3" + jest-validate "^25.2.3" prompts "^2.0.1" - realpath-native "^1.1.0" - yargs "^15.0.0" + realpath-native "^2.0.0" + yargs "^15.3.1" -jest-config@^25.1.0: - version "25.1.0" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-25.1.0.tgz#d114e4778c045d3ef239452213b7ad3ec1cbea90" - integrity sha512-tLmsg4SZ5H7tuhBC5bOja0HEblM0coS3Wy5LTCb2C8ZV6eWLewHyK+3qSq9Bi29zmWQ7ojdCd3pxpx4l4d2uGw== +jest-config@^25.2.4: + version "25.2.4" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-25.2.4.tgz#f4f33238979f225683179c89d1e402893008975d" + integrity sha512-fxy3nIpwJqOUQJRVF/q+pNQb6dv5b9YufOeCbpPZJ/md1zXpiupbhfehpfODhnKOfqbzSiigtSLzlWWmbRxnqQ== dependencies: "@babel/core" "^7.1.0" - "@jest/test-sequencer" "^25.1.0" - "@jest/types" "^25.1.0" - babel-jest "^25.1.0" + "@jest/test-sequencer" "^25.2.4" + "@jest/types" "^25.2.3" + babel-jest "^25.2.4" chalk "^3.0.0" + deepmerge "^4.2.2" glob "^7.1.1" - jest-environment-jsdom "^25.1.0" - jest-environment-node "^25.1.0" - jest-get-type "^25.1.0" - jest-jasmine2 "^25.1.0" - jest-regex-util "^25.1.0" - jest-resolve "^25.1.0" - jest-util "^25.1.0" - jest-validate "^25.1.0" + jest-environment-jsdom "^25.2.4" + jest-environment-node "^25.2.4" + jest-get-type "^25.2.1" + jest-jasmine2 "^25.2.4" + jest-regex-util "^25.2.1" + jest-resolve "^25.2.3" + jest-util "^25.2.3" + jest-validate "^25.2.3" micromatch "^4.0.2" - pretty-format "^25.1.0" - realpath-native "^1.1.0" + pretty-format "^25.2.3" + realpath-native "^2.0.0" jest-diff@^25.1.0: version "25.1.0" @@ -9571,10 +10201,20 @@ jest-diff@^25.1.0: jest-get-type "^25.1.0" pretty-format "^25.1.0" -jest-docblock@^25.1.0: - version "25.1.0" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-25.1.0.tgz#0f44bea3d6ca6dfc38373d465b347c8818eccb64" - integrity sha512-370P/mh1wzoef6hUKiaMcsPtIapY25suP6JqM70V9RJvdKLrV4GaGbfUseUVk4FZJw4oTZ1qSCJNdrClKt5JQA== +jest-diff@^25.2.3: + version "25.2.3" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-25.2.3.tgz#54d601a0a754ef26e808a8c8dbadd278c215aa3f" + integrity sha512-VtZ6LAQtaQpFsmEzps15dQc5ELbJxy4L2DOSo2Ev411TUEtnJPkAMD7JneVypeMJQ1y3hgxN9Ao13n15FAnavg== + dependencies: + chalk "^3.0.0" + diff-sequences "^25.2.1" + jest-get-type "^25.2.1" + pretty-format "^25.2.3" + +jest-docblock@^25.2.3: + version "25.2.3" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-25.2.3.tgz#ac45280c43d59e7139f9fbe5896c6e0320c01ebb" + integrity sha512-d3/tmjLLrH5fpRGmIm3oFa3vOaD/IjPxtXVOrfujpfJ9y1tCDB1x/tvunmdOVAyF03/xeMwburl6ITbiQT1mVA== dependencies: detect-newline "^3.0.0" @@ -9583,93 +10223,100 @@ jest-dom@4.0.0: resolved "https://registry.yarnpkg.com/jest-dom/-/jest-dom-4.0.0.tgz#94eba3cbc6576e7bd6821867c92d176de28920eb" integrity sha512-gBxYZlZB1Jgvf2gP2pRfjjUWF8woGBHj/g5rAQgFPB/0K2atGuhVcPO+BItyjWeKg9zM+dokgcMOH01vrWVMFA== -jest-each@^25.1.0: - version "25.1.0" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-25.1.0.tgz#a6b260992bdf451c2d64a0ccbb3ac25e9b44c26a" - integrity sha512-R9EL8xWzoPySJ5wa0DXFTj7NrzKpRD40Jy+zQDp3Qr/2QmevJgkN9GqioCGtAJ2bW9P/MQRznQHQQhoeAyra7A== +jest-each@^25.2.3: + version "25.2.3" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-25.2.3.tgz#64067ba1508ebbd07e9b126c173ab371e8e6309d" + integrity sha512-RTlmCjsBDK2c9T5oO4MqccA3/5Y8BUtiEy7OOQik1iyCgdnNdHbI0pNEpyapZPBG0nlvZ4mIu7aY6zNUvLraAQ== dependencies: - "@jest/types" "^25.1.0" + "@jest/types" "^25.2.3" chalk "^3.0.0" - jest-get-type "^25.1.0" - jest-util "^25.1.0" - pretty-format "^25.1.0" + jest-get-type "^25.2.1" + jest-util "^25.2.3" + pretty-format "^25.2.3" -jest-environment-jsdom@^25.1.0: - version "25.1.0" - resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-25.1.0.tgz#6777ab8b3e90fd076801efd3bff8e98694ab43c3" - integrity sha512-ILb4wdrwPAOHX6W82GGDUiaXSSOE274ciuov0lztOIymTChKFtC02ddyicRRCdZlB5YSrv3vzr1Z5xjpEe1OHQ== +jest-environment-jsdom@^25.2.4: + version "25.2.4" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-25.2.4.tgz#f2783541d0538b1bc43641703372cea6a2e83611" + integrity sha512-5dm+tNwrLmhELdjAwiQnVGf/U9iFMWdTL4/wyrMg2HU6RQnCiuxpWbIigLHUhuP1P2Ak0F4k3xhjrikboKyShA== dependencies: - "@jest/environment" "^25.1.0" - "@jest/fake-timers" "^25.1.0" - "@jest/types" "^25.1.0" - jest-mock "^25.1.0" - jest-util "^25.1.0" - jsdom "^15.1.1" + "@jest/environment" "^25.2.4" + "@jest/fake-timers" "^25.2.4" + "@jest/types" "^25.2.3" + jest-mock "^25.2.3" + jest-util "^25.2.3" + jsdom "^15.2.1" -jest-environment-node@^25.1.0: - version "25.1.0" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-25.1.0.tgz#797bd89b378cf0bd794dc8e3dca6ef21126776db" - integrity sha512-U9kFWTtAPvhgYY5upnH9rq8qZkj6mYLup5l1caAjjx9uNnkLHN2xgZy5mo4SyLdmrh/EtB9UPpKFShvfQHD0Iw== +jest-environment-node@^25.2.4: + version "25.2.4" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-25.2.4.tgz#dc211dfb0d8b66dfc1965a8f846e72e54ff0c430" + integrity sha512-Jkc5Y8goyXPrLRHnrUlqC7P4o5zn2m4zw6qWoRJ59kxV1f2a5wK+TTGhrhCwnhW/Ckpdl/pm+LufdvhJkvJbiw== dependencies: - "@jest/environment" "^25.1.0" - "@jest/fake-timers" "^25.1.0" - "@jest/types" "^25.1.0" - jest-mock "^25.1.0" - jest-util "^25.1.0" + "@jest/environment" "^25.2.4" + "@jest/fake-timers" "^25.2.4" + "@jest/types" "^25.2.3" + jest-mock "^25.2.3" + jest-util "^25.2.3" + semver "^6.3.0" jest-get-type@^25.1.0: version "25.1.0" resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-25.1.0.tgz#1cfe5fc34f148dc3a8a3b7275f6b9ce9e2e8a876" integrity sha512-yWkBnT+5tMr8ANB6V+OjmrIJufHtCAqI5ic2H40v+tRqxDmE0PGnIiTyvRWFOMtmVHYpwRqyazDbTnhpjsGvLw== -jest-haste-map@^25.1.0: - version "25.1.0" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-25.1.0.tgz#ae12163d284f19906260aa51fd405b5b2e5a4ad3" - integrity sha512-/2oYINIdnQZAqyWSn1GTku571aAfs8NxzSErGek65Iu5o8JYb+113bZysRMcC/pjE5v9w0Yz+ldbj9NxrFyPyw== +jest-get-type@^25.2.1: + version "25.2.1" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-25.2.1.tgz#6c83de603c41b1627e6964da2f5454e6aa3c13a6" + integrity sha512-EYjTiqcDTCRJDcSNKbLTwn/LcDPEE7ITk8yRMNAOjEsN6yp+Uu+V1gx4djwnuj/DvWg0YGmqaBqPVGsPxlvE7w== + +jest-haste-map@^25.2.3: + version "25.2.3" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-25.2.3.tgz#2649392b5af191f0167a27bfb62e5d96d7eaaade" + integrity sha512-pAP22OHtPr4qgZlJJFks2LLgoQUr4XtM1a+F5UaPIZNiCRnePA0hM3L7aiJ0gzwiNIYwMTfKRwG/S1L28J3A3A== dependencies: - "@jest/types" "^25.1.0" + "@jest/types" "^25.2.3" anymatch "^3.0.3" fb-watchman "^2.0.0" graceful-fs "^4.2.3" - jest-serializer "^25.1.0" - jest-util "^25.1.0" - jest-worker "^25.1.0" + jest-serializer "^25.2.1" + jest-util "^25.2.3" + jest-worker "^25.2.1" micromatch "^4.0.2" sane "^4.0.3" walker "^1.0.7" + which "^2.0.2" optionalDependencies: fsevents "^2.1.2" -jest-jasmine2@^25.1.0: - version "25.1.0" - resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-25.1.0.tgz#681b59158a430f08d5d0c1cce4f01353e4b48137" - integrity sha512-GdncRq7jJ7sNIQ+dnXvpKO2MyP6j3naNK41DTTjEAhLEdpImaDA9zSAZwDhijjSF/D7cf4O5fdyUApGBZleaEg== +jest-jasmine2@^25.2.4: + version "25.2.4" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-25.2.4.tgz#5f77de83e1027f0c7588137055a80da773872374" + integrity sha512-juoKrmNmLwaheNbAg71SuUF9ovwUZCFNTpKVhvCXWk+SSeORcIUMptKdPCoLXV3D16htzhTSKmNxnxSk4SrTjA== dependencies: "@babel/traverse" "^7.1.0" - "@jest/environment" "^25.1.0" - "@jest/source-map" "^25.1.0" - "@jest/test-result" "^25.1.0" - "@jest/types" "^25.1.0" + "@jest/environment" "^25.2.4" + "@jest/source-map" "^25.2.1" + "@jest/test-result" "^25.2.4" + "@jest/types" "^25.2.3" chalk "^3.0.0" co "^4.6.0" - expect "^25.1.0" + expect "^25.2.4" is-generator-fn "^2.0.0" - jest-each "^25.1.0" - jest-matcher-utils "^25.1.0" - jest-message-util "^25.1.0" - jest-runtime "^25.1.0" - jest-snapshot "^25.1.0" - jest-util "^25.1.0" - pretty-format "^25.1.0" + jest-each "^25.2.3" + jest-matcher-utils "^25.2.3" + jest-message-util "^25.2.4" + jest-runtime "^25.2.4" + jest-snapshot "^25.2.4" + jest-util "^25.2.3" + pretty-format "^25.2.3" throat "^5.0.0" -jest-leak-detector@^25.1.0: - version "25.1.0" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-25.1.0.tgz#ed6872d15aa1c72c0732d01bd073dacc7c38b5c6" - integrity sha512-3xRI264dnhGaMHRvkFyEKpDeaRzcEBhyNrOG5oT8xPxOyUAblIAQnpiR3QXu4wDor47MDTiHbiFcbypdLcLW5w== +jest-leak-detector@^25.2.3: + version "25.2.3" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-25.2.3.tgz#4cf39f137925e0061c04c24ca65cae36465f0238" + integrity sha512-yblCMPE7NJKl7778Cf/73yyFWAas5St0iiEBwq7RDyaz6Xd4WPFnPz2j7yDb/Qce71A1IbDoLADlcwD8zT74Aw== dependencies: - jest-get-type "^25.1.0" - pretty-format "^25.1.0" + jest-get-type "^25.2.1" + pretty-format "^25.2.3" jest-matcher-utils@^25.1.0: version "25.1.0" @@ -9681,169 +10328,181 @@ jest-matcher-utils@^25.1.0: jest-get-type "^25.1.0" pretty-format "^25.1.0" -jest-message-util@^25.1.0: - version "25.1.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-25.1.0.tgz#702a9a5cb05c144b9aa73f06e17faa219389845e" - integrity sha512-Nr/Iwar2COfN22aCqX0kCVbXgn8IBm9nWf4xwGr5Olv/KZh0CZ32RKgZWMVDXGdOahicM10/fgjdimGNX/ttCQ== +jest-matcher-utils@^25.2.3: + version "25.2.3" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-25.2.3.tgz#59285bd6d6c810debc9caa585ed985e46a3f28fd" + integrity sha512-ZmiXiwQRVM9MoKjGMP5YsGGk2Th5ncyRxfXKz5AKsmU8m43kgNZirckVzaP61MlSa9LKmXbevdYqVp1ZKAw2Rw== + dependencies: + chalk "^3.0.0" + jest-diff "^25.2.3" + jest-get-type "^25.2.1" + pretty-format "^25.2.3" + +jest-message-util@^25.2.4: + version "25.2.4" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-25.2.4.tgz#b1441b9c82f5c11fc661303cbf200a2f136a7762" + integrity sha512-9wWMH3Bf+GVTv0GcQLmH/FRr0x0toptKw9TA8U5YFLVXx7Tq9pvcNzTyJrcTJ+wLqNbMPPJlJNft4MnlcrtF5Q== dependencies: "@babel/code-frame" "^7.0.0" - "@jest/test-result" "^25.1.0" - "@jest/types" "^25.1.0" + "@jest/test-result" "^25.2.4" + "@jest/types" "^25.2.3" "@types/stack-utils" "^1.0.1" chalk "^3.0.0" micromatch "^4.0.2" slash "^3.0.0" stack-utils "^1.0.1" -jest-mock@^25.1.0: - version "25.1.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-25.1.0.tgz#411d549e1b326b7350b2e97303a64715c28615fd" - integrity sha512-28/u0sqS+42vIfcd1mlcg4ZVDmSUYuNvImP4X2lX5hRMLW+CN0BeiKVD4p+ujKKbSPKd3rg/zuhCF+QBLJ4vag== +jest-mock@^25.2.3: + version "25.2.3" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-25.2.3.tgz#b37a581f59d61bd91db27a99bf7eb8b3e5e993d5" + integrity sha512-xlf+pyY0j47zoCs8zGGOGfWyxxLximE8YFOfEK8s4FruR8DtM/UjNj61um+iDuMAFEBDe1bhCXkqiKoCmWjJzg== dependencies: - "@jest/types" "^25.1.0" + "@jest/types" "^25.2.3" jest-pnp-resolver@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz#ecdae604c077a7fbc70defb6d517c3c1c898923a" integrity sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ== -jest-regex-util@^25.1.0: - version "25.1.0" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-25.1.0.tgz#efaf75914267741838e01de24da07b2192d16d87" - integrity sha512-9lShaDmDpqwg+xAd73zHydKrBbbrIi08Kk9YryBEBybQFg/lBWR/2BDjjiSE7KIppM9C5+c03XiDaZ+m4Pgs1w== +jest-regex-util@^25.2.1: + version "25.2.1" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-25.2.1.tgz#db64b0d15cd3642c93b7b9627801d7c518600584" + integrity sha512-wroFVJw62LdqTdkL508ZLV82FrJJWVJMIuYG7q4Uunl1WAPTf4ftPKrqqfec4SvOIlvRZUdEX2TFpWR356YG/w== -jest-resolve-dependencies@^25.1.0: - version "25.1.0" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-25.1.0.tgz#8a1789ec64eb6aaa77fd579a1066a783437e70d2" - integrity sha512-Cu/Je38GSsccNy4I2vL12ZnBlD170x2Oh1devzuM9TLH5rrnLW1x51lN8kpZLYTvzx9j+77Y5pqBaTqfdzVzrw== +jest-resolve-dependencies@^25.2.4: + version "25.2.4" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-25.2.4.tgz#2d904400387d74a366dff54badb40a2b3210e733" + integrity sha512-qhUnK4PfNHzNdca7Ub1mbAqE0j5WNyMTwxBZZJjQlUrdqsiYho/QGK65FuBkZuSoYtKIIqriR9TpGrPEc3P5Gg== dependencies: - "@jest/types" "^25.1.0" - jest-regex-util "^25.1.0" - jest-snapshot "^25.1.0" + "@jest/types" "^25.2.3" + jest-regex-util "^25.2.1" + jest-snapshot "^25.2.4" -jest-resolve@^25.1.0: - version "25.1.0" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-25.1.0.tgz#23d8b6a4892362baf2662877c66aa241fa2eaea3" - integrity sha512-XkBQaU1SRCHj2Evz2Lu4Czs+uIgJXWypfO57L7JYccmAXv4slXA6hzNblmcRmf7P3cQ1mE7fL3ABV6jAwk4foQ== +jest-resolve@^25.2.3: + version "25.2.3" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-25.2.3.tgz#ababeaf2bb948cb6d2dea8453759116da0fb7842" + integrity sha512-1vZMsvM/DBH258PnpUNSXIgtzpYz+vCVCj9+fcy4akZl4oKbD+9hZSlfe9RIDpU0Fc28ozHQrmwX3EqFRRIHGg== dependencies: - "@jest/types" "^25.1.0" + "@jest/types" "^25.2.3" browser-resolve "^1.11.3" chalk "^3.0.0" jest-pnp-resolver "^1.2.1" - realpath-native "^1.1.0" + realpath-native "^2.0.0" + resolve "^1.15.1" -jest-runner@^25.1.0: - version "25.1.0" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-25.1.0.tgz#fef433a4d42c89ab0a6b6b268e4a4fbe6b26e812" - integrity sha512-su3O5fy0ehwgt+e8Wy7A8CaxxAOCMzL4gUBftSs0Ip32S0epxyZPDov9Znvkl1nhVOJNf4UwAsnqfc3plfQH9w== +jest-runner@^25.2.4: + version "25.2.4" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-25.2.4.tgz#d0daf7c56b4a83b6b675863d5cdcd502c960f9a1" + integrity sha512-5xaIfqqxck9Wg2CV4b9KmJtf/sWO7zWQx7O+34GCLGPzoPcVmB3mZtdrQI1/jS3Reqjru9ycLjgLHSf6XoxRqA== dependencies: - "@jest/console" "^25.1.0" - "@jest/environment" "^25.1.0" - "@jest/test-result" "^25.1.0" - "@jest/types" "^25.1.0" + "@jest/console" "^25.2.3" + "@jest/environment" "^25.2.4" + "@jest/test-result" "^25.2.4" + "@jest/types" "^25.2.3" chalk "^3.0.0" exit "^0.1.2" graceful-fs "^4.2.3" - jest-config "^25.1.0" - jest-docblock "^25.1.0" - jest-haste-map "^25.1.0" - jest-jasmine2 "^25.1.0" - jest-leak-detector "^25.1.0" - jest-message-util "^25.1.0" - jest-resolve "^25.1.0" - jest-runtime "^25.1.0" - jest-util "^25.1.0" - jest-worker "^25.1.0" + jest-config "^25.2.4" + jest-docblock "^25.2.3" + jest-haste-map "^25.2.3" + jest-jasmine2 "^25.2.4" + jest-leak-detector "^25.2.3" + jest-message-util "^25.2.4" + jest-resolve "^25.2.3" + jest-runtime "^25.2.4" + jest-util "^25.2.3" + jest-worker "^25.2.1" source-map-support "^0.5.6" throat "^5.0.0" -jest-runtime@^25.1.0: - version "25.1.0" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-25.1.0.tgz#02683218f2f95aad0f2ec1c9cdb28c1dc0ec0314" - integrity sha512-mpPYYEdbExKBIBB16ryF6FLZTc1Rbk9Nx0ryIpIMiDDkOeGa0jQOKVI/QeGvVGlunKKm62ywcioeFVzIbK03bA== +jest-runtime@^25.2.4: + version "25.2.4" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-25.2.4.tgz#c66a421e115944426b377a7fd331f6c0902cfa56" + integrity sha512-6ehOUizgIghN+aV5YSrDzTZ+zJ9omgEjJbTHj3Jqes5D52XHfhzT7cSfdREwkNjRytrR7mNwZ7pRauoyNLyJ8Q== dependencies: - "@jest/console" "^25.1.0" - "@jest/environment" "^25.1.0" - "@jest/source-map" "^25.1.0" - "@jest/test-result" "^25.1.0" - "@jest/transform" "^25.1.0" - "@jest/types" "^25.1.0" + "@jest/console" "^25.2.3" + "@jest/environment" "^25.2.4" + "@jest/source-map" "^25.2.1" + "@jest/test-result" "^25.2.4" + "@jest/transform" "^25.2.4" + "@jest/types" "^25.2.3" "@types/yargs" "^15.0.0" chalk "^3.0.0" collect-v8-coverage "^1.0.0" exit "^0.1.2" glob "^7.1.3" graceful-fs "^4.2.3" - jest-config "^25.1.0" - jest-haste-map "^25.1.0" - jest-message-util "^25.1.0" - jest-mock "^25.1.0" - jest-regex-util "^25.1.0" - jest-resolve "^25.1.0" - jest-snapshot "^25.1.0" - jest-util "^25.1.0" - jest-validate "^25.1.0" - realpath-native "^1.1.0" + jest-config "^25.2.4" + jest-haste-map "^25.2.3" + jest-message-util "^25.2.4" + jest-mock "^25.2.3" + jest-regex-util "^25.2.1" + jest-resolve "^25.2.3" + jest-snapshot "^25.2.4" + jest-util "^25.2.3" + jest-validate "^25.2.3" + realpath-native "^2.0.0" slash "^3.0.0" strip-bom "^4.0.0" - yargs "^15.0.0" + yargs "^15.3.1" -jest-serializer@^25.1.0: - version "25.1.0" - resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-25.1.0.tgz#73096ba90e07d19dec4a0c1dd89c355e2f129e5d" - integrity sha512-20Wkq5j7o84kssBwvyuJ7Xhn7hdPeTXndnwIblKDR2/sy1SUm6rWWiG9kSCgJPIfkDScJCIsTtOKdlzfIHOfKA== +jest-serializer@^25.2.1: + version "25.2.1" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-25.2.1.tgz#51727a5fc04256f461abe0fa024a022ba165877a" + integrity sha512-fibDi7M5ffx6c/P66IkvR4FKkjG5ldePAK1WlbNoaU4GZmIAkS9Le/frAwRUFEX0KdnisSPWf+b1RC5jU7EYJQ== -jest-snapshot@^25.1.0: - version "25.1.0" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-25.1.0.tgz#d5880bd4b31faea100454608e15f8d77b9d221d9" - integrity sha512-xZ73dFYN8b/+X2hKLXz4VpBZGIAn7muD/DAg+pXtDzDGw3iIV10jM7WiHqhCcpDZfGiKEj7/2HXAEPtHTj0P2A== +jest-snapshot@^25.2.4: + version "25.2.4" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-25.2.4.tgz#08d4517579c864df4280bcc948ceea34327a4ded" + integrity sha512-nIwpW7FZCq5p0AE3Oyqyb6jL0ENJixXzJ5/CD/XRuOqp3gS5OM3O/k+NnTrniCXxPFV4ry6s9HNfiPQBi0wcoA== dependencies: "@babel/types" "^7.0.0" - "@jest/types" "^25.1.0" + "@jest/types" "^25.2.3" + "@types/prettier" "^1.19.0" chalk "^3.0.0" - expect "^25.1.0" - jest-diff "^25.1.0" - jest-get-type "^25.1.0" - jest-matcher-utils "^25.1.0" - jest-message-util "^25.1.0" - jest-resolve "^25.1.0" - mkdirp "^0.5.1" + expect "^25.2.4" + jest-diff "^25.2.3" + jest-get-type "^25.2.1" + jest-matcher-utils "^25.2.3" + jest-message-util "^25.2.4" + jest-resolve "^25.2.3" + make-dir "^3.0.0" natural-compare "^1.4.0" - pretty-format "^25.1.0" - semver "^7.1.1" + pretty-format "^25.2.3" + semver "^6.3.0" -jest-util@^25.1.0: - version "25.1.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-25.1.0.tgz#7bc56f7b2abd534910e9fa252692f50624c897d9" - integrity sha512-7did6pLQ++87Qsj26Fs/TIwZMUFBXQ+4XXSodRNy3luch2DnRXsSnmpVtxxQ0Yd6WTipGpbhh2IFP1mq6/fQGw== +jest-util@^25.2.3: + version "25.2.3" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-25.2.3.tgz#0abf95a1d6b96f2de5a3ecd61b36c40a182dc256" + integrity sha512-7tWiMICVSo9lNoObFtqLt9Ezt5exdFlWs5fLe1G4XLY2lEbZc814cw9t4YHScqBkWMfzth8ASHKlYBxiX2rdCw== dependencies: - "@jest/types" "^25.1.0" + "@jest/types" "^25.2.3" chalk "^3.0.0" is-ci "^2.0.0" - mkdirp "^0.5.1" + make-dir "^3.0.0" -jest-validate@^25.1.0: - version "25.1.0" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-25.1.0.tgz#1469fa19f627bb0a9a98e289f3e9ab6a668c732a" - integrity sha512-kGbZq1f02/zVO2+t1KQGSVoCTERc5XeObLwITqC6BTRH3Adv7NZdYqCpKIZLUgpLXf2yISzQ465qOZpul8abXA== +jest-validate@^25.2.3: + version "25.2.3" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-25.2.3.tgz#ecb0f093cf8ae71d15075fb48439b6f78f1fcb5a" + integrity sha512-GObn91jzU0B0Bv4cusAwjP6vnWy78hJUM8MOSz7keRfnac/ZhQWIsUjvk01IfeXNTemCwgR57EtdjQMzFZGREg== dependencies: - "@jest/types" "^25.1.0" + "@jest/types" "^25.2.3" camelcase "^5.3.1" chalk "^3.0.0" - jest-get-type "^25.1.0" + jest-get-type "^25.2.1" leven "^3.1.0" - pretty-format "^25.1.0" + pretty-format "^25.2.3" -jest-watcher@^25.1.0: - version "25.1.0" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-25.1.0.tgz#97cb4a937f676f64c9fad2d07b824c56808e9806" - integrity sha512-Q9eZ7pyaIr6xfU24OeTg4z1fUqBF/4MP6J801lyQfg7CsnZ/TCzAPvCfckKdL5dlBBEKBeHV0AdyjFZ5eWj4ig== +jest-watcher@^25.2.4: + version "25.2.4" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-25.2.4.tgz#dda85b914d470fa4145164a8f70bda4f208bafb6" + integrity sha512-p7g7s3zqcy69slVzQYcphyzkB2FBmJwMbv6k6KjI5mqd6KnUnQPfQVKuVj2l+34EeuxnbXqnrjtUFmxhcL87rg== dependencies: - "@jest/test-result" "^25.1.0" - "@jest/types" "^25.1.0" + "@jest/test-result" "^25.2.4" + "@jest/types" "^25.2.3" ansi-escapes "^4.2.1" chalk "^3.0.0" - jest-util "^25.1.0" + jest-util "^25.2.3" string-length "^3.1.0" jest-worker@^25.1.0: @@ -9854,14 +10513,22 @@ jest-worker@^25.1.0: merge-stream "^2.0.0" supports-color "^7.0.0" -jest@25.1.0: - version "25.1.0" - resolved "https://registry.yarnpkg.com/jest/-/jest-25.1.0.tgz#b85ef1ddba2fdb00d295deebbd13567106d35be9" - integrity sha512-FV6jEruneBhokkt9MQk0WUFoNTwnF76CLXtwNMfsc0um0TlB/LG2yxUd0KqaFjEJ9laQmVWQWS0sG/t2GsuI0w== +jest-worker@^25.2.1: + version "25.2.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-25.2.1.tgz#209617015c768652646aa33a7828cc2ab472a18a" + integrity sha512-IHnpekk8H/hCUbBlfeaPZzU6v75bqwJp3n4dUrQuQOAgOneI4tx3jV2o8pvlXnDfcRsfkFIUD//HWXpCmR+evQ== dependencies: - "@jest/core" "^25.1.0" + merge-stream "^2.0.0" + supports-color "^7.0.0" + +jest@25.2.4: + version "25.2.4" + resolved "https://registry.yarnpkg.com/jest/-/jest-25.2.4.tgz#d10941948a2b57eb7accc2e7ae78af4a0e11b40a" + integrity sha512-Lu4LXxf4+durzN/IFilcAoQSisOwgHIXgl9vffopePpSSwFqfj1Pj4y+k3nL8oTbnvjxgDIsEcepy6he4bWqnQ== + dependencies: + "@jest/core" "^25.2.4" import-local "^3.0.2" - jest-cli "^25.1.0" + jest-cli "^25.2.4" js-cookie@^2.2.1: version "2.2.1" @@ -9923,7 +10590,7 @@ jsbn@~0.1.0: resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= -jsdom@^15.1.1: +jsdom@^15.2.1: version "15.2.1" resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-15.2.1.tgz#d2feb1aef7183f86be521b8c6833ff5296d07ec5" integrity sha512-fAl1W0/7T2G5vURSyxBzrJ1LSdQn6Tr5UX/xD4PXDx/PDgwygedfW6El/KIj3xJ7FU61TTYnc/l/B7P49Eqt6g== @@ -10092,7 +10759,7 @@ json3@^3.3.2: resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.3.tgz#7fc10e375fc5ae42c4705a5cc0aa6f62be305b81" integrity sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA== -json5@^0.5.0, json5@^0.5.1: +json5@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= @@ -10111,6 +10778,13 @@ json5@^2.1.0: dependencies: minimist "^1.2.0" +json5@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.2.tgz#43ef1f0af9835dd624751a6b7fa48874fb2d608e" + integrity sha512-MoUOQ4WdiN3yxhm7NEVJSJrieAo5hNSLQ5sj05OTRHPL9HOBy8u4Bu88jsC1jvqAdN+E1bJmsUcZH+1HQxliqQ== + dependencies: + minimist "^1.2.5" + jsonfile@^2.1.0: version "2.4.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" @@ -10125,6 +10799,15 @@ jsonfile@^4.0.0: optionalDependencies: graceful-fs "^4.1.6" +jsonfile@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.0.1.tgz#98966cba214378c8c84b82e085907b40bf614179" + integrity sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg== + dependencies: + universalify "^1.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + jsonify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" @@ -10232,6 +10915,11 @@ just-curry-it@^3.1.0: resolved "https://registry.yarnpkg.com/just-curry-it/-/just-curry-it-3.1.0.tgz#ab59daed308a58b847ada166edd0a2d40766fbc5" integrity sha512-mjzgSOFzlrurlURaHVjnQodyPNvrHrf1TbQP2XU9NSqBtHQPuHZ+Eb6TAJP7ASeJN9h9K0KXoRTs8u6ouHBKvg== +just-debounce@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/just-debounce/-/just-debounce-1.0.0.tgz#87fccfaeffc0b68cd19d55f6722943f929ea35ea" + integrity sha1-h/zPrv/AtozRnVX2cilD+SnqNeo= + keccak256@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/keccak256/-/keccak256-1.0.0.tgz#1ba55ce78ed3d63fb7091d045469007da984171d" @@ -10294,7 +10982,7 @@ kind-of@^4.0.0: dependencies: is-buffer "^1.1.5" -kind-of@^5.0.0: +kind-of@^5.0.0, kind-of@^5.0.2: version "5.1.0" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== @@ -10324,6 +11012,14 @@ last-call-webpack-plugin@^3.0.0: lodash "^4.17.5" webpack-sources "^1.1.0" +last-run@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/last-run/-/last-run-1.1.1.tgz#45b96942c17b1c79c772198259ba943bebf8ca5b" + integrity sha1-RblpQsF7HHnHchmCWbqUO+v4yls= + dependencies: + default-resolution "^2.0.0" + es6-weak-map "^2.0.1" + lazy-debug-legacy@0.0.X: version "0.0.1" resolved "https://registry.yarnpkg.com/lazy-debug-legacy/-/lazy-debug-legacy-0.0.1.tgz#537716c0776e4cf79e3ed1b621f7658c2911b1b1" @@ -10350,6 +11046,13 @@ lcid@^2.0.0: dependencies: invert-kv "^2.0.0" +lead@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lead/-/lead-1.0.0.tgz#6f14f99a37be3a9dd784f5495690e5903466ee42" + integrity sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI= + dependencies: + flush-write-stream "^1.0.2" + left-pad@^1.1.3: version "1.3.0" resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.3.0.tgz#5b8a3a7765dfe001261dde915589e782f8c94d1e" @@ -10504,6 +11207,20 @@ levn@^0.3.0, levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" +liftoff@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-3.1.0.tgz#c9ba6081f908670607ee79062d700df062c52ed3" + integrity sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog== + dependencies: + extend "^3.0.0" + findup-sync "^3.0.0" + fined "^1.0.1" + flagged-respawn "^1.0.0" + is-plain-object "^2.0.4" + object.map "^1.0.0" + rechoir "^0.6.2" + resolve "^1.1.7" + lines-and-columns@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" @@ -10514,10 +11231,10 @@ linked-list@0.1.0: resolved "https://registry.yarnpkg.com/linked-list/-/linked-list-0.1.0.tgz#798b0ff97d1b92a4fd08480f55aea4e9d49d37bf" integrity sha1-eYsP+X0bkqT9CEgPVa6k6dSdN78= -lint-staged@^10.0.7: - version "10.0.8" - resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-10.0.8.tgz#0f7849cdc336061f25f5d4fcbcfa385701ff4739" - integrity sha512-Oa9eS4DJqvQMVdywXfEor6F4vP+21fPHF8LUXgBbVWUSWBddjqsvO6Bv1LwMChmgQZZqwUvgJSHlu8HFHAPZmA== +lint-staged@10.0.10: + version "10.0.10" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-10.0.10.tgz#d14d33ee02a31a31ad36cf9aa7973fc156c461b5" + integrity sha512-91vNy3eYStExElLWw1Idva5lghKpFaXh9AJqjcyrJXf7AYZrThi4EhQ+GpmiHdPmJJauKhZMMSzQR1bMB90MtA== dependencies: chalk "^3.0.0" commander "^4.0.1" @@ -10622,17 +11339,7 @@ loader-utils@1.2.3: emojis-list "^2.0.0" json5 "^1.0.1" -loader-utils@^0.2.16: - version "0.2.17" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348" - integrity sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g= - dependencies: - big.js "^3.1.3" - emojis-list "^2.0.0" - json5 "^0.5.0" - object-assign "^4.0.1" - -loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0: +loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== @@ -10641,6 +11348,15 @@ loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4 emojis-list "^3.0.0" json5 "^1.0.1" +loader-utils@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.0.tgz#e4cace5b816d425a166b5f097e10cd12b36064b0" + integrity sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ== + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^2.1.2" + locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" @@ -10778,7 +11494,7 @@ lodash@4.17.14: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.14.tgz#9ce487ae66c96254fe20b599f21b6816028078ba" integrity sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw== -"lodash@>=3.5 <5", lodash@^4, lodash@^4.1.0, lodash@^4.15.0, lodash@^4.17.1, 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.3, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.2.1: +"lodash@>=3.5 <5", lodash@^4, lodash@^4.1.0, lodash@^4.15.0, lodash@^4.17.1, 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.4, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.2.1: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== @@ -10850,10 +11566,12 @@ loud-rejection@^1.0.0: currently-unhandled "^0.4.1" signal-exit "^3.0.0" -lower-case@^1.1.1: - version "1.1.4" - resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac" - integrity sha1-miyr0bno4K6ZOkv31YdcOcQujqw= +lower-case@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.1.tgz#39eeb36e396115cc05e29422eaea9e692c9408c7" + integrity sha512-LiWgfDLLb1dwbFQZsSglpRj+1ctGnayXz3Uv0/WO8n558JycT5fg6zkNcnW0G68Nn0aEldTFeEfmjCfmqry/rQ== + dependencies: + tslib "^1.10.0" lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: version "1.0.1" @@ -10926,6 +11644,13 @@ make-dir@^3.0.0, make-dir@^3.0.2: dependencies: semver "^6.0.0" +make-iterator@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.1.tgz#29b33f312aa8f547c4a5e490f56afcec99133ad6" + integrity sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw== + dependencies: + kind-of "^6.0.2" + makeerror@1.0.x: version "1.0.11" resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" @@ -10933,11 +11658,6 @@ makeerror@1.0.x: dependencies: tmpl "1.0.x" -mamacro@^0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/mamacro/-/mamacro-0.0.3.tgz#ad2c9576197c9f1abf308d0787865bd975a3f3e4" - integrity sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA== - map-age-cleaner@^0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" @@ -10945,7 +11665,7 @@ map-age-cleaner@^0.1.1: dependencies: p-defer "^1.0.0" -map-cache@^0.2.2: +map-cache@^0.2.0, map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= @@ -10977,6 +11697,16 @@ marked@0.3.19: resolved "https://registry.yarnpkg.com/marked/-/marked-0.3.19.tgz#5d47f709c4c9fc3c216b6d46127280f40b39d790" integrity sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg== +matchdep@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/matchdep/-/matchdep-2.0.0.tgz#c6f34834a0d8dbc3b37c27ee8bbcb27c7775582e" + integrity sha1-xvNINKDY28OzfCfui7yyfHd1WC4= + dependencies: + findup-sync "^2.0.0" + micromatch "^3.0.4" + resolve "^1.4.0" + stack-trace "0.0.10" + material-ui-search-bar@^1.0.0-beta.13: version "1.0.0-beta.14" resolved "https://registry.yarnpkg.com/material-ui-search-bar/-/material-ui-search-bar-1.0.0-beta.14.tgz#6ab53f3c2c58c0c634b13a96f7ebaf068dcbb27e" @@ -11195,7 +11925,7 @@ mime-db@1.43.0, "mime-db@>= 1.43.0 < 2": resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.43.0.tgz#0a12e0502650e473d735535050e7c8f4eb4fae58" integrity sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ== -mime-types@^2.1.12, mime-types@^2.1.16, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24: +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: version "2.1.26" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.26.tgz#9c921fc09b7e149a65dfdc0da4d20997200b0a06" integrity sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ== @@ -11298,6 +12028,11 @@ minimist@^1.1.1, minimist@^1.2.0, minimist@~1.2.0: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.4.tgz#40357ef9582f8cd42ba8eaa274ddcf27f0c979b7" integrity sha512-wTiNDqe4D2rbTJGZk1qcdZgFtY0/r+iuE6GDT7V0/+Gu5MLpIDm4+CssDECR79OJs/OxLPXMzdxy153b5Qy3hg== +minimist@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + minipass-collect@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617" @@ -11384,6 +12119,13 @@ mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1: dependencies: minimist "0.0.8" +mkdirp@^0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.3.tgz#5a514b7179259287952881e94410ec5465659f8c" + integrity sha512-P+2gwrFqx8lhew375MQHHeTlY8AuOJSrGf0R5ddkEndUkmwpgUob/vQuBD1V22/Cw1/lJr4x+EjllSezBThzBg== + dependencies: + minimist "^1.2.5" + mocha@5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" @@ -11464,6 +12206,11 @@ multicast-dns@^6.0.1: dns-packet "^1.3.1" thunky "^1.0.2" +mute-stdout@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mute-stdout/-/mute-stdout-1.0.1.tgz#acb0300eb4de23a7ddeec014e3e96044b3472331" + integrity sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg== + mute-stream@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" @@ -11541,12 +12288,13 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== -no-case@^2.2.0: - version "2.3.2" - resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac" - integrity sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ== +no-case@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.3.tgz#c21b434c1ffe48b39087e86cfb4d2582e9df18f8" + integrity sha512-ehY/mVQCf9BL0gKfsJBvFJen+1V//U+0HQMPrWct40ixE4jnv0bfvxDbWtAHL9EcaPEOJHVVYKoQn1TlZUB8Tw== dependencies: - lower-case "^1.1.1" + lower-case "^2.0.1" + tslib "^1.10.0" node-dir@0.1.17, node-dir@^0.1.16: version "0.1.17" @@ -11639,13 +12387,20 @@ node-notifier@^6.0.0: shellwords "^0.1.1" which "^1.3.1" -node-releases@^1.1.47, node-releases@^1.1.50: +node-releases@^1.1.50: version "1.1.51" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.51.tgz#70d0e054221343d2966006bfbd4d98622cc00bd0" integrity sha512-1eQEs6HFYY1kMXQPOLzCf7HdjReErmvn85tZESMczdCNVWP3Y7URYLBAyYynuI7yef1zj4HN5q+oB2x67QU0lw== dependencies: semver "^6.3.0" +node-releases@^1.1.52: + version "1.1.52" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.52.tgz#bcffee3e0a758e92e44ecfaecd0a47554b0bcba9" + integrity sha512-snSiT1UypkgGt2wxPqS6ImEUICbNCMb31yaxWrOLXjhlt2z2/IBpaOxzONExqSm4y5oLnAqjjRWu+wsDzK5yNQ== + dependencies: + semver "^6.3.0" + normalize-hex@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/normalize-hex/-/normalize-hex-0.0.2.tgz#5491c43759db2f06b7168d8419f4925c271ab27e" @@ -11709,6 +12464,13 @@ normalize-url@^4.1.0: prop-types "^15.7.2" react-is "^16.9.0" +now-and-later@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/now-and-later/-/now-and-later-2.0.1.tgz#8e579c8685764a7cc02cb680380e94f43ccb1f7c" + integrity sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ== + dependencies: + once "^1.3.2" + npm-programmatic@0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/npm-programmatic/-/npm-programmatic-0.0.6.tgz#3c8f4dbb210efd65b99ee6a5ac76f27b4d5d6b78" @@ -11825,7 +12587,7 @@ object-visit@^1.0.0: dependencies: isobject "^3.0.0" -object.assign@^4.1.0: +object.assign@^4.0.4, 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== @@ -11835,6 +12597,16 @@ object.assign@^4.1.0: has-symbols "^1.0.0" object-keys "^1.0.11" +object.defaults@^1.0.0, object.defaults@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/object.defaults/-/object.defaults-1.1.0.tgz#3a7f868334b407dea06da16d88d5cd29e435fecf" + integrity sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8= + dependencies: + array-each "^1.0.1" + array-slice "^1.0.0" + for-own "^1.0.0" + isobject "^3.0.0" + object.entries@^1.1.0, object.entries@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.1.tgz#ee1cf04153de02bb093fec33683900f57ce5399b" @@ -11863,6 +12635,14 @@ object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.0 define-properties "^1.1.3" es-abstract "^1.17.0-next.1" +object.map@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object.map/-/object.map-1.0.1.tgz#cf83e59dc8fcc0ad5f4250e1f78b3b81bd801d37" + integrity sha1-z4Plncj8wK1fQlDh94s7gb2AHTc= + dependencies: + for-own "^1.0.0" + make-iterator "^1.0.0" + object.omit@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" @@ -11871,13 +12651,21 @@ object.omit@^2.0.0: for-own "^0.1.4" is-extendable "^0.1.1" -object.pick@^1.3.0: +object.pick@^1.2.0, object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= dependencies: isobject "^3.0.1" +object.reduce@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object.reduce/-/object.reduce-1.0.1.tgz#6fe348f2ac7fa0f95ca621226599096825bb03ad" + integrity sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60= + dependencies: + for-own "^1.0.0" + make-iterator "^1.0.0" + object.values@^1.1.0, object.values@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.1.tgz#68a99ecde356b7e9295a3c5e0ce31dc8c953de5e" @@ -11922,7 +12710,7 @@ on-headers@~1.0.2: resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== -once@^1.3.0, once@^1.3.1, once@^1.4.0: +once@^1.3.0, once@^1.3.1, once@^1.3.2, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= @@ -12013,6 +12801,13 @@ ordered-read-streams@^0.3.0: is-stream "^1.0.1" readable-stream "^2.0.1" +ordered-read-streams@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz#77c0cb37c41525d64166d990ffad7ec6a0e1363e" + integrity sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4= + dependencies: + readable-stream "^2.0.1" + original-require@1.0.1, original-require@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/original-require/-/original-require-1.0.1.tgz#0f130471584cd33511c5ec38c8d59213f9ac5e20" @@ -12185,12 +12980,13 @@ parallel-transform@^1.1.0: inherits "^2.0.3" readable-stream "^2.1.5" -param-case@2.1.x: - version "2.1.1" - resolved "https://registry.yarnpkg.com/param-case/-/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247" - integrity sha1-35T9jPZTHs915r75oIWPvHK+Ikc= +param-case@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.3.tgz#4be41f8399eff621c56eebb829a5e451d9801238" + integrity sha512-VWBVyimc1+QrzappRs7waeN2YmoZFCGXWASRYX1/rGHtXqEcrGEIDm+jqIwFa2fRXNgQEwrxaYuIrX0WcAguTA== dependencies: - no-case "^2.2.0" + dot-case "^3.0.3" + tslib "^1.10.0" parent-module@^1.0.0: version "1.0.1" @@ -12211,6 +13007,15 @@ parse-asn1@^5.0.0: pbkdf2 "^3.0.3" safe-buffer "^5.1.1" +parse-filepath@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/parse-filepath/-/parse-filepath-1.0.2.tgz#a632127f53aaf3d15876f5872f3ffac763d6c891" + integrity sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE= + dependencies: + is-absolute "^1.0.0" + map-cache "^0.2.0" + path-root "^0.1.1" + parse-glob@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" @@ -12251,11 +13056,21 @@ parse-json@^5.0.0: json-parse-better-errors "^1.0.1" lines-and-columns "^1.1.6" +parse-node-version@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parse-node-version/-/parse-node-version-1.0.1.tgz#e2b5dbede00e7fa9bc363607f53327e8b073189b" + integrity sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA== + parse-passwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= +parse-srcset@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/parse-srcset/-/parse-srcset-1.0.2.tgz#f2bd221f6cc970a938d88556abc589caaaa2bde1" + integrity sha1-8r0iH2zJcKk42IVWq8WJyqqiveE= + parse5@5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.0.tgz#c59341c9723f414c452975564c7c00a68d58acd2" @@ -12278,6 +13093,14 @@ parseurl@~1.3.2, parseurl@~1.3.3: resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== +pascal-case@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.1.tgz#5ac1975133ed619281e88920973d2cd1f279de5f" + integrity sha512-XIeHKqIrsquVTQL2crjq3NfJUxmdLasn3TYOU0VBM+UX2a6ztAWBlJQBePLGY7VHW8+2dRadeIPK5+KImwTxQA== + dependencies: + no-case "^3.0.3" + tslib "^1.10.0" + pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" @@ -12335,6 +13158,18 @@ path-parse@^1.0.6: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== +path-root-regex@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/path-root-regex/-/path-root-regex-0.1.2.tgz#bfccdc8df5b12dc52c8b43ec38d18d72c04ba96d" + integrity sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0= + +path-root@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/path-root/-/path-root-0.1.1.tgz#9a4a6814cac1c0cd73360a95f32083c8ea4745b7" + integrity sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc= + dependencies: + path-root-regex "^0.1.0" + path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" @@ -12481,7 +13316,7 @@ pkg-dir@^4.1.0, pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" -pkg-up@3.1.0: +pkg-up@3.1.0, pkg-up@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5" integrity sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA== @@ -12507,12 +13342,12 @@ pocket-js-core@0.0.3: dependencies: axios "^0.18.0" -polished@^3.4.2: - version "3.4.4" - resolved "https://registry.yarnpkg.com/polished/-/polished-3.4.4.tgz#ac8cd6e704887398f3b802718f9d389b9ea4307b" - integrity sha512-x9PKeExyI9AhWrJP3Q57I1k7GInujjiVBJMPFmycj9hX1yCOo/X9eu9eZwxgOziiXge3WbFQ5XOmkzunOntBSA== +polished@3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/polished/-/polished-3.5.1.tgz#657b6faf4c2308f3e0b1951196803a5e5d67b122" + integrity sha512-GVbvskpBiDV5TknurGL6OyFfLHsCknxbU8w5iMppT8rW0tLEoQHrIRfrPNPqGXNj3HGhkjRvhmg59Fy7HSnCAw== dependencies: - "@babel/runtime" "^7.6.3" + "@babel/runtime" "^7.8.7" popper.js@^1.14.1: version "1.16.1" @@ -12887,12 +13722,12 @@ postcss-value-parser@^3.0.0: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== -postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.2: +postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.2, postcss-value-parser@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.3.tgz#651ff4593aa9eda8d5d0d66593a2417aeaeb325d" integrity sha512-N7h4pG+Nnu5BEIzyeaaIYWs0LI5XC40OrRh5L60z0QjFsqGWcHcbkBvpe1WYpcIS9yQ8sOi/vIPt1ejQCrMVrg== -postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.18, postcss@^7.0.2, postcss@^7.0.21, postcss@^7.0.23, postcss@^7.0.26, postcss@^7.0.27, postcss@^7.0.5, postcss@^7.0.6: +postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.18, postcss@^7.0.2, postcss@^7.0.21, postcss@^7.0.23, postcss@^7.0.27, postcss@^7.0.5, postcss@^7.0.6: version "7.0.27" resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.27.tgz#cc67cdc6b0daa375105b7c424a85567345fc54d9" integrity sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ== @@ -12933,12 +13768,12 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" -prettier@^1.19.1: - version "1.19.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" - integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== +prettier@2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.2.tgz#1ba8f3eb92231e769b7fcd7cb73ae1b6b74ade08" + integrity sha512-5xJQIPT8BraI7ZnaDwSbu5zLrB6vvi8hVV58yHQ+QK64qrY40dULy0HSRlQ2/2IdzeBpjhDkqdcFBnFeDEMVdg== -pretty-error@^2.0.2: +pretty-error@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-2.1.1.tgz#5f4f87c8f91e5ae3f3ba87ab4cf5e03b1a17f1a3" integrity sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM= @@ -12966,21 +13801,36 @@ pretty-format@^25.1.0: ansi-styles "^4.0.0" react-is "^16.12.0" -private@^0.1.6, private@^0.1.8, private@~0.1.5: +pretty-format@^25.2.3: + version "25.2.3" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-25.2.3.tgz#ba6e9603a0d80fa2e470b1fed55de1f9bfd81421" + integrity sha512-IP4+5UOAVGoyqC/DiomOeHBUKN6q00gfyT2qpAsRH64tgOKB2yF7FHJXC18OCiU0/YFierACup/zdCOWw0F/0w== + dependencies: + "@jest/types" "^25.2.3" + ansi-regex "^5.0.0" + ansi-styles "^4.0.0" + react-is "^16.12.0" + +pretty-hrtime@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" + integrity sha1-t+PqQkNaTJsnWdmeDyAesZWALuE= + +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== +process-nextick-args@^2.0.0, process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + process-nextick-args@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" integrity sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M= -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - process@^0.11.10: version "0.11.10" resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" @@ -13132,7 +13982,7 @@ pump@^3.0.0: end-of-stream "^1.1.0" once "^1.3.1" -pumpify@^1.3.3: +pumpify@^1.3.3, pumpify@^1.3.5: version "1.5.1" resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ== @@ -13290,14 +14140,14 @@ raw-body@2.4.0: iconv-lite "0.4.24" unpipe "1.0.0" -react-dev-utils@^10.0.0: - version "10.2.0" - resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-10.2.0.tgz#b11cc48aa2be2502fb3c27a50d1dfa95cfa9dfe0" - integrity sha512-MwrvQW2TFjLblhqpDNeqCXHBkz3G5vc7k4wntgutAJZX4ia3o07eGKo6uYGhUOeJ0hfOxcpJFNFk7+4XCc1S8g== +react-dev-utils@10.2.1: + version "10.2.1" + resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-10.2.1.tgz#f6de325ae25fa4d546d09df4bb1befdc6dd19c19" + integrity sha512-XxTbgJnYZmxuPtY3y/UV0D8/65NKkmaia4rXzViknVnZeVlklSh8u6TnaEYPfAi/Gh1TP4mEOXHI6jQOPbeakQ== dependencies: "@babel/code-frame" "7.8.3" address "1.1.2" - browserslist "4.8.6" + browserslist "4.10.0" chalk "2.4.2" cross-spawn "7.0.1" detect-port-alt "1.1.6" @@ -13314,26 +14164,26 @@ react-dev-utils@^10.0.0: loader-utils "1.2.3" open "^7.0.2" pkg-up "3.1.0" - react-error-overlay "^6.0.6" + react-error-overlay "^6.0.7" recursive-readdir "2.2.2" shell-quote "1.7.2" strip-ansi "6.0.0" text-table "0.2.0" -react-dom@16.13.0: - version "16.13.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.13.0.tgz#cdde54b48eb9e8a0ca1b3dc9943d9bb409b81866" - integrity sha512-y09d2c4cG220DzdlFkPTnVvGTszVvNpC73v+AaLGLHbkpy3SSgvYq8x0rNwPJ/Rk/CicTNgk0hbHNw1gMEZAXg== +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== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" prop-types "^15.6.2" - scheduler "^0.19.0" + scheduler "^0.19.1" -react-error-overlay@^6.0.6: - version "6.0.6" - resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.6.tgz#ac4d9dc4c1b5c536c2c312bf66aa2b09bfa384e2" - integrity sha512-Yzpno3enVzSrSCnnljmr4b/2KUQSMZaPuqmS26t9k4nW7uwJk6STWmH9heNjPuvqUTO3jOSPkHoKgO4+Dw7uIw== +react-error-overlay@^6.0.7: + version "6.0.7" + resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.7.tgz#1dcfb459ab671d53f660a991513cb2f0a0553108" + integrity sha512-TAv1KJFh3RhqxNvhzxj6LeT5NWklP6rDr2a0jaTfsZ5wSZWHOGeqQyejUp3xxLfPt2UpyJEcVQB/zyPcmonNFA== react-final-form-listeners@^1.0.2: version "1.0.2" @@ -13355,10 +14205,10 @@ react-ga@^2.7.0: resolved "https://registry.yarnpkg.com/react-ga/-/react-ga-2.7.0.tgz#24328f157f31e8cffbf4de74a3396536679d8d7c" integrity sha512-AjC7UOZMvygrWTc2hKxTDvlMXEtbmA0IgJjmkhgmQQ3RkXrWR11xEagLGFGaNyaPnmg24oaIiaNPnEoftUhfXA== -react-hot-loader@4.12.19: - version "4.12.19" - resolved "https://registry.yarnpkg.com/react-hot-loader/-/react-hot-loader-4.12.19.tgz#99a1c763352828f404fa51cd887c5e16bb5b74d1" - integrity sha512-p8AnA4QE2GtrvkdmqnKrEiijtVlqdTIDCHZOwItkI9kW51bt5XnQ/4Anz8giiWf9kqBpEQwsmnChDCAFBRyR/Q== +react-hot-loader@4.12.20: + version "4.12.20" + resolved "https://registry.yarnpkg.com/react-hot-loader/-/react-hot-loader-4.12.20.tgz#c2c42362a7578e5c30357a5ff7afa680aa0bef8a" + integrity sha512-lPlv1HVizi0lsi+UFACBJaydtRYILWkfHAC/lyCs6ZlAxlOZRQIfYHDqiGaRvL/GF7zyti+Qn9XpnDAUvdFA4A== dependencies: fast-levenshtein "^2.0.6" global "^4.3.0" @@ -13446,15 +14296,20 @@ react-window@^1.8.5: "@babel/runtime" "^7.0.0" memoize-one ">=3.1.1 <6" -react@16.13.0: - version "16.13.0" - resolved "https://registry.yarnpkg.com/react/-/react-16.13.0.tgz#d046eabcdf64e457bbeed1e792e235e1b9934cf7" - integrity sha512-TSavZz2iSLkq5/oiE7gnFzmURKZMltmi193rm5HEoUDAXpzT9Kzw6oNZnGoai/4+fUnm7FqS5dwgUL34TujcWQ== +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== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" prop-types "^15.6.2" +reactive-properties@^0.1.11: + version "0.1.11" + resolved "https://registry.yarnpkg.com/reactive-properties/-/reactive-properties-0.1.11.tgz#d8678fa5a66b964c1a520ec92a3137842b8f9d52" + integrity sha512-NhOEcAlNSq94ml3WdLroKdndeUo4Idj4PSEieqfaLL5BXZU4BFo+TsOY6yiasR9EVUw27mfW2sYBYhwSUNMrLw== + read-pkg-up@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" @@ -13586,22 +14441,10 @@ readdirp@~3.3.0: dependencies: picomatch "^2.0.7" -realpath-native@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.1.0.tgz#2003294fea23fb0672f2476ebe22fcf498a2d65c" - integrity sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA== - dependencies: - util.promisify "^1.0.0" - -recast@~0.11.12: - version "0.11.23" - resolved "https://registry.yarnpkg.com/recast/-/recast-0.11.23.tgz#451fd3004ab1e4df9b4e4b66376b2a21912462d3" - integrity sha1-RR/TAEqx5N+bTktmN2sqIZEkYtM= - dependencies: - ast-types "0.9.6" - esprima "~3.1.0" - private "~0.1.5" - source-map "~0.5.0" +realpath-native@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-2.0.0.tgz#7377ac429b6e1fd599dc38d08ed942d0d7beb866" + integrity sha512-v1SEYUOXXdbBZK8ZuNgO4TBjamPsiSgcFr0aP+tEKpQZK8vooEUqV6nm6Cv502mX4NF2EfsnVqtNAHG+/6Ur1Q== rechoir@^0.6.2: version "0.6.2" @@ -13808,7 +14651,7 @@ regexpu-core@^2.0.0: regjsgen "^0.2.0" regjsparser "^0.1.4" -regexpu-core@^4.6.0: +regexpu-core@^4.6.0, 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== @@ -13844,7 +14687,7 @@ regjsparser@^0.6.4: dependencies: jsesc "~0.5.0" -relateurl@0.2.x: +relateurl@^0.2.7: version "0.2.7" resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" integrity sha1-VNvzd+UUQKypCkzSdGANP/LYiKk= @@ -13868,7 +14711,24 @@ remotedev-serialize@^0.1.8: dependencies: jsan "^3.1.13" -remove-trailing-separator@^1.0.1: +remove-bom-buffer@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz#c2bf1e377520d324f623892e33c10cac2c252b53" + integrity sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ== + dependencies: + is-buffer "^1.1.5" + is-utf8 "^0.2.1" + +remove-bom-stream@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz#05f1a593f16e42e1fb90ebf59de8e569525f9523" + integrity sha1-BfGlk/FuQuH7kOv1nejlaVJflSM= + dependencies: + remove-bom-buffer "^3.0.0" + safe-buffer "^5.1.0" + through2 "^2.0.3" + +remove-trailing-separator@^1.0.1, remove-trailing-separator@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= @@ -13906,6 +14766,20 @@ replace-ext@0.0.1: resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924" integrity sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ= +replace-ext@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" + integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs= + +replace-homedir@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/replace-homedir/-/replace-homedir-1.0.0.tgz#e87f6d513b928dde808260c12be7fec6ff6e798c" + integrity sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw= + dependencies: + homedir-polyfill "^1.0.1" + is-absolute "^1.0.0" + remove-trailing-separator "^1.1.0" + request-promise-core@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.3.tgz#e9a3c081b51380dfea677336061fea879a829ee9" @@ -14036,6 +14910,13 @@ resolve-from@^5.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== +resolve-options@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/resolve-options/-/resolve-options-1.1.0.tgz#32bb9e39c06d67338dc9378c0d6d6074566ad131" + integrity sha1-MrueOcBtZzONyTeMDW1gdFZq0TE= + dependencies: + value-or-function "^3.0.0" + resolve-pathname@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-3.0.0.tgz#99d02224d3cf263689becbb393bc560313025dcd" @@ -14051,7 +14932,7 @@ resolve@1.1.7: resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= -resolve@^1.1.6, resolve@^1.10.0, resolve@^1.11.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.15.1, resolve@^1.3.2, resolve@^1.8.1, resolve@~1.15.1: +resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.11.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.15.1, resolve@^1.3.2, resolve@^1.4.0, resolve@^1.8.1, resolve@~1.15.1: version "1.15.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.1.tgz#27bdcdeffeaf2d6244b95bb0f9f4b4653451f3e8" integrity sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w== @@ -14291,10 +15172,10 @@ sc-formatter@^3.0.1: resolved "https://registry.yarnpkg.com/sc-formatter/-/sc-formatter-3.0.2.tgz#9abdb14e71873ce7157714d3002477bbdb33c4e6" integrity sha512-9PbqYBpCq+OoEeRQ3QfFIGE6qwjjBcd2j7UjgDlhnZbtSnuGgHdcRklPKYGuYFH82V/dwd+AIpu8XvA1zqTd+A== -scheduler@^0.19.0: - version "0.19.0" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.0.tgz#a715d56302de403df742f4a9be11975b32f5698d" - integrity sha512-xowbVaTPe9r7y7RUejcK73/j8tt2jfiyTednOvHbA8JoClvMYCp+r8QegLwK/n8zWQAtZb1fFnER4XLBZXrCxA== +scheduler@^0.19.1: + version "0.19.1" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.1.tgz#4f3e2ed2c1a7d65681f4c854fa8c5a1ccb40f196" + integrity sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -14316,7 +15197,7 @@ schema-utils@^1.0.0: ajv-errors "^1.0.0" ajv-keywords "^3.1.0" -schema-utils@^2.5.0, schema-utils@^2.6.0, schema-utils@^2.6.4: +schema-utils@^2.6.0, schema-utils@^2.6.4, schema-utils@^2.6.5: version "2.6.5" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.6.5.tgz#c758f0a7e624263073d396e29cd40aa101152d8a" integrity sha512-5KXuwKziQrTVHh8j/Uxz+QUbxkaLW9X/86NBlx/gnKgtsZA2GIVMUn17qWhRFwF8jdYb3Dig5hRO/W5mZqy6SQ== @@ -14437,6 +15318,13 @@ semver-compare@^1.0.0: resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w= +semver-greatest-satisfied-range@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz#13e8c2658ab9691cb0cd71093240280d36f77a5b" + integrity sha1-E+jCZYq5aRywzXEJMkAoDTb3els= + dependencies: + sver-compat "^1.5.0" + semver-regex@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-2.0.0.tgz#a93c2c5844539a770233379107b38c7b4ac9d338" @@ -14846,7 +15734,7 @@ source-map-url@^0.4.0: resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= -source-map@^0.5.0, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.0: +source-map@^0.5.0, source-map@^0.5.6, source-map@^0.5.7: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= @@ -14866,6 +15754,11 @@ sourcemap-codec@^1.4.4: resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== +sparkles@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.1.tgz#008db65edce6c50eec0c5e228e1945061dd0437c" + integrity sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw== + spawn-args@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/spawn-args/-/spawn-args-0.1.0.tgz#3e0232a0571b387907f8b3f544aa531c6224848c" @@ -15013,6 +15906,11 @@ stable@^0.1.8: resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== +stack-trace@0.0.10: + version "0.0.10" + resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" + integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA= + stack-utils@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.2.tgz#33eba3897788558bebfc2db059dc158ec36cebb8" @@ -15057,6 +15955,11 @@ stream-each@^1.1.0: end-of-stream "^1.1.0" stream-shift "^1.0.0" +stream-exhaust@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/stream-exhaust/-/stream-exhaust-1.0.2.tgz#acdac8da59ef2bc1e17a2c0ccf6c320d120e555d" + integrity sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw== + stream-http@^2.7.2: version "2.8.3" resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" @@ -15104,7 +16007,7 @@ string-length@^3.1.0: astral-regex "^1.0.0" strip-ansi "^5.2.0" -string-width@^1.0.1: +string-width@^1.0.1, string-width@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= @@ -15391,6 +16294,14 @@ supports-hyperlinks@^2.0.0: has-flag "^4.0.0" supports-color "^7.0.0" +sver-compat@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/sver-compat/-/sver-compat-1.5.0.tgz#3cf87dfeb4d07b4a3f14827bc186b3fd0c645cd8" + integrity sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg= + dependencies: + es6-iterator "^2.0.1" + es6-symbol "^3.1.1" + svgo@^1.0.0: version "1.3.2" resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167" @@ -15564,6 +16475,15 @@ terser@^4.1.2, terser@^4.4.3: source-map "~0.6.1" source-map-support "~0.5.12" +terser@^4.6.3: + version "4.6.7" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.6.7.tgz#478d7f9394ec1907f0e488c5f6a6a9a2bad55e72" + integrity sha512-fmr7M1f7DBly5cX2+rFDvmGBAaaZyPrHYK4mMdHEDAdNTqXSZgSOfqsfGq2HqPGT/1V0foZZuCZFx8CHKgAk3g== + dependencies: + commander "^2.20.0" + source-map "~0.6.1" + source-map-support "~0.5.12" + test-exclude@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" @@ -15622,7 +16542,7 @@ through2@^3.0.1: dependencies: readable-stream "2 || 3" -through@^2.3.6, through@^2.3.8, through@~2.3.4, through@~2.3.6, through@~2.3.8: +through@^2.3.6, through@^2.3.8, through@~2.3.4, through@~2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= @@ -15639,6 +16559,11 @@ tildify@1.2.0: dependencies: os-homedir "^1.0.0" +time-stamp@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" + integrity sha1-dkpaEa9QVhkhsTPztE5hhofg9cM= + timed-out@^4.0.0, timed-out@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" @@ -15692,6 +16617,14 @@ to-absolute-glob@^0.1.1: dependencies: extend-shallow "^2.0.1" +to-absolute-glob@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz#1865f43d9e74b0822db9f145b78cff7d0f7c849b" + integrity sha1-GGX0PZ50sIItufFFt4z/fQ98hJs= + dependencies: + is-absolute "^1.0.0" + is-negated-glob "^1.0.0" + to-arraybuffer@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" @@ -15775,16 +16708,18 @@ to-space-case@^1.0.0: dependencies: to-no-case "^1.0.0" +to-through@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-through/-/to-through-2.0.0.tgz#fc92adaba072647bc0b67d6b03664aa195093af6" + integrity sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY= + dependencies: + through2 "^2.0.3" + toidentifier@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== -toposort@^1.0.0: - version "1.0.7" - resolved "https://registry.yarnpkg.com/toposort/-/toposort-1.0.7.tgz#2e68442d9f64ec720b8cc89e6443ac6caa950029" - integrity sha1-LmhELZ9k7HILjMieZEOsbKqVACk= - tough-cookie@^2.2.0, tough-cookie@^2.3.3, tough-cookie@~2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" @@ -16141,10 +17076,10 @@ truffle-solidity-loader@0.1.32: truffle-config "^1.1.19" truffle-core "^5.0.33" -truffle@5.1.16: - version "5.1.16" - resolved "https://registry.yarnpkg.com/truffle/-/truffle-5.1.16.tgz#19c5bc6b3e21cdc41266aed30b5650b9665952b8" - integrity sha512-McY2AKicKIdIclpclIXluWtCf1yj2cTJGS0ghStHkklw7XYk3ZL4MoftNyfqiYCjIjGs24qoEF9o/JlRp5qnmQ== +truffle@5.1.19: + version "5.1.19" + resolved "https://registry.yarnpkg.com/truffle/-/truffle-5.1.19.tgz#daf0aca071b9e2cdd88f456f10c1a81e840794aa" + integrity sha512-H4S7GbKCN56eW5ftLo+l160c+SLyF8C205hUF9VRfulxFBdXvmTIeHdRO/zcnBWiKfEbXzuHWSI9gyFkPtkvmw== dependencies: app-module-path "^2.2.0" mocha "5.2.0" @@ -16160,7 +17095,7 @@ ts-essentials@^5.0.0: resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-5.0.0.tgz#531d590c9cd62652c9d96284904cbdb2a1dd5ca8" integrity sha512-ftKWOm6Jq+/UCBekDfxUjLODEd5XGN2EM/+TIQV9LJ5xSV12je4GqdRyv7pXXGGYmEt/nQa6F00xTWYJ5PMjIQ== -tslib@^1.9.0: +tslib@^1.10.0, tslib@^1.9.0: version "1.11.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35" integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA== @@ -16295,14 +17230,6 @@ ua-parser-js@^0.7.18: resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.21.tgz#853cf9ce93f642f67174273cc34565ae6f308777" integrity sha512-+O8/qh/Qj8CgC6eYBVBykMrNtp5Gebn4dlGD/kKXVkJNDwyrAwSIqwz8CDf+tsAIWVycKcku6gIXJ0qwx/ZXaQ== -uglify-js@3.4.x: - version "3.4.10" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.10.tgz#9ad9563d8eb3acdfb8d38597d2af1d815f6a755f" - integrity sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw== - dependencies: - commander "~2.19.0" - source-map "~0.6.1" - ultron@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" @@ -16316,6 +17243,11 @@ unbzip2-stream@^1.0.9: buffer "^5.2.1" through "^2.3.8" +unc-path-regex@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" + integrity sha1-5z3T17DXxe2G+6xrCufYxqadUPo= + underscore@1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" @@ -16326,6 +17258,26 @@ underscore@^1.8.3: resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.2.tgz#0c8d6f536d6f378a5af264a72f7bec50feb7cf2f" integrity sha512-D39qtimx0c1fI3ya1Lnhk3E9nONswSKhnffBI0gME9C99fYOkNi04xs8K6pePLhvl1frbDemkaBQ5ikWllR2HQ== +undertaker-registry@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/undertaker-registry/-/undertaker-registry-1.0.1.tgz#5e4bda308e4a8a2ae584f9b9a4359a499825cc50" + integrity sha1-XkvaMI5KiirlhPm5pDWaSZglzFA= + +undertaker@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/undertaker/-/undertaker-1.2.1.tgz#701662ff8ce358715324dfd492a4f036055dfe4b" + integrity sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA== + dependencies: + arr-flatten "^1.0.1" + arr-map "^2.0.0" + bach "^1.0.0" + collection-map "^1.0.0" + es6-weak-map "^2.0.1" + last-run "^1.1.0" + object.defaults "^1.0.0" + object.reduce "^1.0.0" + undertaker-registry "^1.0.0" + unicode-canonical-property-names-ecmascript@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" @@ -16412,6 +17364,11 @@ universalify@^0.1.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== +universalify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-1.0.0.tgz#b61a1da173e8435b2fe3c67d29b9adf8594bd16d" + integrity sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug== + unorm@^1.3.3: version "1.6.0" resolved "https://registry.yarnpkg.com/unorm/-/unorm-1.6.0.tgz#029b289661fba714f1a9af439eb51d9b16c205af" @@ -16440,11 +17397,6 @@ upath@^1.1.1: resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== -upper-case@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598" - integrity sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg= - uri-js@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" @@ -16457,14 +17409,14 @@ urix@^0.1.0: resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= -url-loader@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-3.0.0.tgz#9f1f11b371acf6e51ed15a50db635e02eec18368" - integrity sha512-a84JJbIA5xTFTWyjjcPdnsu+41o/SNE8SpXMdUvXs6Q+LuhCD9E2+0VCiuDWqgo3GGXVlFHzArDmBpj9PgWn4A== +url-loader@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-4.0.0.tgz#946719464089e35804009270339f21124e8dd27e" + integrity sha512-sPsoBs8NkSJt9k/2zLUMDAf0rYaG00EtrFQpHRIphKrR6stGsO92LUJf/uUeQNKEoxqoJ4R4qDLqHl+AOEqolA== dependencies: - loader-utils "^1.2.3" - mime "^2.4.4" - schema-utils "^2.5.0" + loader-utils "^2.0.0" + mime-types "^2.1.26" + schema-utils "^2.6.5" url-parse-lax@^1.0.0: version "1.0.0" @@ -16539,7 +17491,7 @@ util.promisify@1.0.0: define-properties "^1.1.2" object.getownpropertydescriptors "^2.0.3" -util.promisify@^1.0.0, util.promisify@~1.0.0: +util.promisify@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.1.tgz#6baf7774b80eeb0f7520d8b81d07982a59abbaee" integrity sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA== @@ -16629,6 +17581,13 @@ v8-to-istanbul@^4.0.1: convert-source-map "^1.6.0" source-map "^0.7.3" +v8flags@^3.0.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-3.1.3.tgz#fc9dc23521ca20c5433f81cc4eb9b3033bb105d8" + integrity sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w== + dependencies: + homedir-polyfill "^1.0.1" + vali-date@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/vali-date/-/vali-date-1.0.0.tgz#1b904a59609fb328ef078138420934f6b86709a6" @@ -16647,6 +17606,11 @@ value-equal@^1.0.1: resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-1.0.1.tgz#1e0b794c734c5c0cade179c437d356d931a34d6c" integrity sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw== +value-or-function@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/value-or-function/-/value-or-function-3.0.0.tgz#1c243a50b595c1be54a754bfece8563b9ff8d813" + integrity sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM= + vary@^1, vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" @@ -16694,6 +17658,42 @@ vinyl-fs@2.4.3: vali-date "^1.0.0" vinyl "^1.0.0" +vinyl-fs@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-3.0.3.tgz#c85849405f67428feabbbd5c5dbdd64f47d31bc7" + integrity sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng== + dependencies: + fs-mkdirp-stream "^1.0.0" + glob-stream "^6.1.0" + graceful-fs "^4.0.0" + is-valid-glob "^1.0.0" + lazystream "^1.0.0" + lead "^1.0.0" + object.assign "^4.0.4" + pumpify "^1.3.5" + readable-stream "^2.3.3" + remove-bom-buffer "^3.0.0" + remove-bom-stream "^1.2.0" + resolve-options "^1.1.0" + through2 "^2.0.0" + to-through "^2.0.0" + value-or-function "^3.0.0" + vinyl "^2.0.0" + vinyl-sourcemap "^1.1.0" + +vinyl-sourcemap@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz#92a800593a38703a8cdb11d8b300ad4be63b3e16" + integrity sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY= + dependencies: + append-buffer "^1.0.2" + convert-source-map "^1.5.0" + graceful-fs "^4.1.6" + normalize-path "^2.1.1" + now-and-later "^2.0.0" + remove-bom-buffer "^3.0.0" + vinyl "^2.0.0" + vinyl@1.X, vinyl@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-1.2.0.tgz#5c88036cf565e5df05558bfc911f8656df218884" @@ -16703,6 +17703,18 @@ vinyl@1.X, vinyl@^1.0.0: clone-stats "^0.0.1" replace-ext "0.0.1" +vinyl@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.2.0.tgz#d85b07da96e458d25b2ffe19fece9f2caa13ed86" + integrity sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg== + dependencies: + clone "^2.1.1" + clone-buffer "^1.0.0" + clone-stats "^1.0.0" + cloneable-readable "^1.0.0" + remove-trailing-separator "^1.0.1" + replace-ext "^1.0.0" + vm-browserify@^1.0.1: version "1.1.2" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" @@ -16724,11 +17736,6 @@ w3c-xmlserializer@^1.1.2: webidl-conversions "^4.0.2" xml-name-validator "^3.0.0" -wait-for-expect@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/wait-for-expect/-/wait-for-expect-3.0.2.tgz#d2f14b2f7b778c9b82144109c8fa89ceaadaa463" - integrity sha512-cfS1+DZxuav1aBYbaO/kE06EOS8yRw7qOFoD3XtjTkYvCvh3zUvNST8DXK/nPaeqIzIv3P3kL3lRJn8iwOiSag== - walker@^1.0.7, walker@~1.0.5: version "1.0.7" resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" @@ -17418,13 +18425,13 @@ webidl-conversions@^4.0.2: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== -webpack-bundle-analyzer@3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.6.0.tgz#39b3a8f829ca044682bc6f9e011c95deb554aefd" - integrity sha512-orUfvVYEfBMDXgEKAKVvab5iQ2wXneIEorGNsyuOyVYpjYrI7CUOhhXNDd3huMwQ3vNNWWlGP+hzflMFYNzi2g== +webpack-bundle-analyzer@3.6.1: + version "3.6.1" + resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.6.1.tgz#bdb637c2304424f2fbff9a950c7be42a839ae73b" + integrity sha512-Nfd8HDwfSx1xBwC+P8QMGvHAOITxNBSvu/J/mCJvOwv+G4VWkU7zir9SSenTtyCi0LnVtmsc7G5SZo1uV+bxRw== dependencies: - acorn "^6.0.7" - acorn-walk "^6.1.1" + acorn "^7.1.1" + acorn-walk "^7.1.1" bfj "^6.1.1" chalk "^2.4.1" commander "^2.18.0" @@ -17530,15 +18537,15 @@ webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack- source-list-map "^2.0.0" source-map "~0.6.1" -webpack@4.42.0: - version "4.42.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.42.0.tgz#b901635dd6179391d90740a63c93f76f39883eb8" - integrity sha512-EzJRHvwQyBiYrYqhyjW9AqM90dE4+s1/XtCfn7uWg6cS72zH+2VPFAlsnW0+W0cDi0XRjNKUMoJtpSi50+Ph6w== +webpack@4.42.1: + version "4.42.1" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.42.1.tgz#ae707baf091f5ca3ef9c38b884287cfe8f1983ef" + integrity sha512-SGfYMigqEfdGchGhFFJ9KyRpQKnipvEvjc1TwrXEPCM6H5Wywu10ka8o3KGrMzSMxMQKt8aCHUFh5DaQ9UmyRg== dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-module-context" "1.8.5" - "@webassemblyjs/wasm-edit" "1.8.5" - "@webassemblyjs/wasm-parser" "1.8.5" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-module-context" "1.9.0" + "@webassemblyjs/wasm-edit" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" acorn "^6.2.1" ajv "^6.10.2" ajv-keywords "^3.4.1" @@ -17550,7 +18557,7 @@ webpack@4.42.0: loader-utils "^1.2.3" memory-fs "^0.4.1" micromatch "^3.1.10" - mkdirp "^0.5.1" + mkdirp "^0.5.3" neo-async "^2.6.1" node-libs-browser "^2.2.1" schema-utils "^1.0.0" @@ -17587,6 +18594,7 @@ websocket@1.0.29, "websocket@github:web3-js/WebSocket-Node#polyfill/globalThis": dependencies: debug "^2.2.0" es5-ext "^0.10.50" + gulp "^4.0.2" nan "^2.14.0" typedarray-to-buffer "^3.1.5" yaeti "^0.0.6" @@ -17637,6 +18645,11 @@ whatwg-url@^7.0.0: tr46 "^1.0.1" webidl-conversions "^4.0.2" +which-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" + integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8= + which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" @@ -17654,7 +18667,7 @@ which@^1.2.14, which@^1.2.9, which@^1.3.1: dependencies: isexe "^2.0.0" -which@^2.0.1: +which@^2.0.1, which@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== @@ -17931,10 +18944,10 @@ yargs-parser@^13.1.0: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^18.1.0: - version "18.1.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.0.tgz#1b0ab1118ebd41f68bb30e729f4c83df36ae84c3" - integrity sha512-o/Jr6JBOv6Yx3pL+5naWSoIA2jJ+ZkMYQG/ie9qFbukBe4uzmBatlXFOiu/tNKRWEtyf+n5w7jc/O16ufqOTdQ== +yargs-parser@^18.1.1: + version "18.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.1.tgz#bf7407b915427fc760fcbbccc6c82b4f0ffcbd37" + integrity sha512-KRHEsOM16IX7XuLnMOqImcPNbLVXMNHYAoFc3BKR8Ortl5gzDbtXvvEoGx9imk5E+X1VeNKNlcHr8B8vi+7ipA== dependencies: camelcase "^5.0.0" decamelize "^1.2.0" @@ -17947,6 +18960,13 @@ yargs-parser@^2.4.0: camelcase "^3.0.0" lodash.assign "^4.0.6" +yargs-parser@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a" + integrity sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo= + dependencies: + camelcase "^3.0.0" + yargs-parser@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9" @@ -18007,10 +19027,10 @@ yargs@4.6.0: y18n "^3.2.1" yargs-parser "^2.4.0" -yargs@^15.0.0: - version "15.3.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.3.0.tgz#403af6edc75b3ae04bf66c94202228ba119f0976" - integrity sha512-g/QCnmjgOl1YJjGsnUg2SatC7NUYEiLXJqxNOQU9qSpjzGtGXda9b+OKccr1kLTy8BN9yqEyqfq5lxlwdc13TA== +yargs@^15.3.1: + version "15.3.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.3.1.tgz#9505b472763963e54afe60148ad27a330818e98b" + integrity sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA== dependencies: cliui "^6.0.0" decamelize "^1.2.0" @@ -18022,7 +19042,26 @@ yargs@^15.0.0: string-width "^4.2.0" which-module "^2.0.0" y18n "^4.0.0" - yargs-parser "^18.1.0" + yargs-parser "^18.1.1" + +yargs@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" + integrity sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg= + dependencies: + camelcase "^3.0.0" + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + os-locale "^1.4.0" + read-pkg-up "^1.0.1" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^1.0.2" + which-module "^1.0.0" + y18n "^3.2.1" + yargs-parser "^5.0.0" yargs@^8.0.2: version "8.0.2" From 3942347b5ac6bd1201779d1dfaca278c8750a74e Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Fri, 3 Apr 2020 20:01:43 +0400 Subject: [PATCH 2/2] v1.9.2 (#734) * Bug: Invalid V in signature with eth_sign (#728) * Fix invalid V with metamask/ledger * DONT FORGET TO REVERT BEFORE MERGING: test deployment * DONT FORGET TO REVERT BEFORE MERGING 2: test deployment * Revert "DONT FORGET TO REVERT BEFORE MERGING 2: test deployment" This reverts commit 8331f2a78f7fc8f53eb893899f16edd8238c68ff. * Revert "DONT FORGET TO REVERT BEFORE MERGING: test deployment" This reverts commit 03b81e31820ce4fe078a7131c2f0caa2af4870ac. * BUG: Only injected providers are cached as last used provider (#733) * cache every used provider, not only injected one * package json update --- package.json | 2 +- src/components/Header/index.jsx | 3 +-- .../transactions/offchainSigner/ethSigner.js | 23 ++++++++++++++++++- src/logic/wallets/getWeb3.js | 7 ------ 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index bcefb6c3..efbbab53 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "safe-react", - "version": "1.9.1", + "version": "1.9.2", "description": "Allowing crypto users manage funds in a safer way", "homepage": "https://github.com/gnosis/safe-react#readme", "bugs": { diff --git a/src/components/Header/index.jsx b/src/components/Header/index.jsx index 8cdfc8e2..c3c66feb 100644 --- a/src/components/Header/index.jsx +++ b/src/components/Header/index.jsx @@ -13,7 +13,6 @@ import selector, { type SelectorProps } from './selector' import { onboard } from '~/components/ConnectButton' import { NOTIFICATIONS, showSnackbar } from '~/logic/notifications' -import { INJECTED_PROVIDERS } from '~/logic/wallets/getWeb3' import { loadLastUsedProvider } from '~/logic/wallets/store/middlewares/providerWatcher' import { type Info, logComponentStack } from '~/utils/logBoundaries' @@ -38,7 +37,7 @@ class HeaderComponent extends React.PureComponent { async componentDidMount() { const lastUsedProvider = await loadLastUsedProvider() - if (INJECTED_PROVIDERS.includes(lastUsedProvider.toUpperCase()) || process.env.NODE_ENV === 'test') { + if (lastUsedProvider) { const hasSelectedWallet = await onboard.walletSelect(lastUsedProvider) if (hasSelectedWallet) { await onboard.walletCheck() diff --git a/src/logic/safe/transactions/offchainSigner/ethSigner.js b/src/logic/safe/transactions/offchainSigner/ethSigner.js index 42a772cb..2a2d1133 100644 --- a/src/logic/safe/transactions/offchainSigner/ethSigner.js +++ b/src/logic/safe/transactions/offchainSigner/ethSigner.js @@ -53,7 +53,28 @@ export const getEthSigner = async ({ return } - resolve(signature.result.replace(EMPTY_DATA, '')) + const sig = signature.result.replace(EMPTY_DATA, '') + let sigV = parseInt(sig.slice(-2), 16) + + // Metamask with ledger returns v = 01, this is not valid for ethereum + // For ethereum valid V is 27 or 28 + // In case V = 0 or 01 we add it to 27 and then add 4 + // Adding 4 is required to make signature valid for safe contracts: + // https://gnosis-safe.readthedocs.io/en/latest/contracts/signatures.html#eth-sign-signature + switch (sigV) { + case 0: + case 1: + sigV += 31 + break + case 27: + case 28: + sigV += 4 + break + default: + throw new Error('Invalid signature') + } + + resolve(sig.slice(0, -2) + sigV.toString(16)) }, ) }) diff --git a/src/logic/wallets/getWeb3.js b/src/logic/wallets/getWeb3.js index a33ddc03..bc7faad9 100644 --- a/src/logic/wallets/getWeb3.js +++ b/src/logic/wallets/getWeb3.js @@ -34,13 +34,6 @@ export const WALLET_PROVIDER = { TREZOR: 'TREZOR', } -export const INJECTED_PROVIDERS = [ - WALLET_PROVIDER.SAFE, - WALLET_PROVIDER.METAMASK, - WALLET_PROVIDER.OPERA, - WALLET_PROVIDER.DAPPER, -] - export const ETHEREUM_NETWORK_IDS = { // $FlowFixMe 1: ETHEREUM_NETWORK.MAINNET,