From 9b6f6d68f80b3d61b1e21bbcaab07ed9599371de Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Fri, 24 Apr 2020 19:24:56 +0400 Subject: [PATCH 1/5] v2.0.0 (#806) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 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 * (Fix) Adapt app to back-end changes (#736) * refactor: Set success status to `201` (CREATED) * refactor: return `null` when there's no latestTx * (Fix) Transaction not automatically executed (#716) * feature: action/reducer to UPDATE_SAFE_NONCE * refactor: when processing txs returned from backend, extract latest tx nonce value and store it in the safe's state * chore: update `yarn.lock` * refactor: `UPDATE_SAFE_THRESHOLD` and `UPDATE_SAFE_NONCE` discarded in favor of `UPDATE_SAFE` * refactor: use `SAFE_REDUCER_ID` constant * refactor: remove `updateSafeNonce` file * (Fix) Change the order of the upgrade methods lookup (#740) * fix: change the order of the upgrade methods lookup The `isUpgradeTransaction` method was looking for the methods in an wrong order (#599). The proper order was set in #610, but `isUpgradeTransaction` wasn't updated. * fix: contract upgrade version lookup * Feature: Use eth_sign for hardware wallets connected via onboard.js (#742) * Use eth_sign for hardware wallets * install onboard.js with fix from forked repo * rebuild yarn.lock to fix cached onboard * update bnc-onboard * update package json (#743) * (Fix) Properly decode threshold value in tx details (#749) * fix: Display new threshold value when changing its value There was a typo for the `changeThreshold` action fixes #746 * refactor: use a constant for safe methods names * fix: check for `decimals` method in transferredTokens (#748) Previously we were looking for `decimals` hash in the contract `code`. There are some contracts like USDC who happen to be behind a FiatTokenProxy, making it upgradable. By directly calling the `decimals()` method, we interact with the contract and can be sure that the `decimals()` method is present. fixes #678 * Bug #747: Don't use getLastTxNonce to fetch safe nonce (#750) * don't use getLastTxNonce to fetch safe nonce * fetch safe nonce in checkAndUpdateSafe * checkAndUpdateSafe refactor * remove nonce update logic from UPDATE_SAFE reducer * handle the case when localSafe returns undefined * handle the case when localSafe returns undefined in buildTransactionFrom * bump package json version to 1.9.4 * Issue-595: Apps config from Manifest (#715) * getting apps info from its manifest * Consume app info from manifest in Apps list, Transactions and Toast * fixes * navigate to TX Tab with an app makes a TX * (Fix) If backend returns `null` for addresses the Transaction ca… (#718) This tends to solve any possible issue that there may be in the tx execution for the `gasToken` and `refundReceiver` nullish values. fixes #573 * #751 fix - Replaces decimals from backend with decimals from blockchain (#755) * Replaces decimals from backend with decimals from blockchain * Removes fetching again token info from blockchain Fixs decimals cast, now we force to move from bignumber to number For data already wrong stored as string we remove it to force fetching again the decimals * Fixs missing symbol * Add description comment * Added Unilogin provider + support for legacy paths (#719) * Added unilogin provier + support for legacy path * Bump onboardjs version * fallback to displaying custom tx when we fail to fetch token info (#767) * Create release.yml Created script for building desktop app * Feature #322: Set safeTxGas for newly created transactions (#752) * Set safeTxGas for newly created transactions * extending estimation for nested calls WIP * messing up things to implement safeTxGas estimation * simplifying base gas calculations * remove eslint disable * messing things up to make things work * bring estimateData back * pass payload to requiredTxGas * pass esimateData to estimateDataGasCosts * remove console log * use batch requests to estimate safeTxGas * use const for txGasEstimation * check the response in request simultion * sidebar fix * remove for loop * Manage Apps (#765) * getting apps info from its manifest * Consume app info from manifest in Apps list, Transactions and Toast * fixes * navigate to TX Tab with an app makes a TX * ManageApps partial implementation * update safe-react-components * changes * apps validator * fix providedBy * TextField in addApp * fix checkbox error message * validation * adding app * Manage Apps * fix modal width * update package.json * update netlify url * fix modal widh * Set layout to Non-owners allowed error * some fixes * Apply suggestions from code review Co-Authored-By: lukasschor * review changes * fix condition * Legal Disclaimer * Better error message * update yarn.lock * Error message * review fixes * upgrade safe-react-components * show for all environments * Disclaimer changes * review changes * fix re-render * visual changes Co-authored-by: Agustín Longoni Co-authored-by: lukasschor * fix scroll and fix margin layout * Add region to travis CI develop (#787) Enable region for s3 provider to allow upload development environment to different S3 regions * Feature/travis ci s3 region (#789) * Add region to travis CI develop Enable region for s3 provider to allow upload development environment to different S3 regions * Enable region for staging s3 providers * fix error on Wrapper * Add gnosis wc bridge to onboard.js wallets options array (#790) * Rename incoming-transactions url to incoming-transfers * Feature #587 - App performance improvement (#738) * Refactor Balances to functional component Removes Balances props in Layout.jsx * Replaces selectors that were using safeParamAddressSelector with safeParamAddressFromStateSelector to avoid the bug of non-loaded safe when called Also exports extendedTransactionsSelector to let the components use it * Refactors Transactions.jsx, replaces transactions.tsx with txsTable.jsx Removes all unused props from transactions.jsx Makes all childs of txsTable.jsx fetch the props they need instead of sharing all of them even if they are not used * Adds new selectors: safeNameSelector, safeNeedsUpdateSelector, safeCurrentVersionSelector * Removes unused props from layout to settings.jsx Removed props from the settings.jsx childs, now they fetch the values they need directly from the store * Removes unused redux connect * Adds safeEthBalanceSelector * Removes all the props from layout to settings * Refactor root and layout, extracts checkForUpdate and componentDidMount to components Extracts header and tabs from Layout.jsx * Makes routes.jsx use selectors instead of connect to unify the code * Loads tabs components using react suspense * Fixs warning when trying to update root component within loadStore.jsx Replaces safe with safeAddress selector in layout.jsx to reduce the unnecessary rendering Fixs setState in container.jsx * Fixs checkForUpdates fetchTokenBalances Adds FetchTokens.jsx in balances Adds safeFeaturesEnabledSelector * Fixs load addressbook action * Replaces safe with owners in manage owners * Improves buildSafe promises calls Improves the loadStorage calls * Fixs error "Uncaught (in promise) TypeError: Cannot read property 'includes' of undefined" * Extracts LoadStore from outside the router component to avoid re-loading the store Adds react lazy for Coins and Collectible tabs * Reduce the polling rate for fetching transactions * Removes unused actions.js Removes unused selector props * Fixes owners column selector usage * Fixes processTransaction usage * Optimize how the transaction list within the transactions tab are loaded * Fix lint error * Fix edit addressbook entry * Fixs show send coins modal * feature: batchRequest for incoming transactions * Fixs race condition on loadStore Fixs check for updates address null validation * Adds ensureOnceAsync for getGnosisSafeInstanceAt Adds batch request for safe params * Removes unnecessary checkAndUpdateSafe from checkForUpdates, now the safe gets updated when a transaction arrives * Fixs ensureOnce/memoization * refactor: make a generic generateBatchRequest method Create a generic method to easily build web3 batch requests * refactor: use `generateBatchRequest` in `getTokensBalances` * Removes .toJS in edit entry * Removes web3 from sendTransactions Removes pascal case FetchTokens * Replaces /layout import * Replaces CheckForUpdates component with useCheckForUpdates hook * Makes FetchTokens a hook * Removes getSafeParamsBatch, now the safes gets the data using the generic generateBatchRequests * Replaces INITIAL_STATUS with INITIAL_STATE * Replaces regex Adds spaces before return * Adds wrapInSuspense * Runs prettier * Makes checkAndUpdateSafe use generateBatchRequests * Makes checkAndUpdateSafe use generateBatchRequests * Fixs check for updates with null address * Fixs transaction details getNameFromAddressBook * Fixes zIndex between cookies banner and transaction details * fix: cast returned values to number Original code was expecting a BN instance, now it's a plain string. * Fix replace owner name * Fix race condition with adbk load * Fixes replaces owner * Fixs apps * Moved hooks into own folder * Moved LoadStore to routes.js Refactors LoadStore as Hook Move LoadStore to hooks folder * Moves useLoadStore to safes/index * Revert loadStore place change * Fixes bug with fetchEtherBalance that causes updateSafe to be called * remove useLoadStore, add useAnalytics hook * remove React.memo from SafeView * Reverts removing useLoadStore in order to maintain the consistency of the code * rewrite useLoadStore in a more hook-y way, rename it to useLoadSafe * Removes unnecessary setSafeLoaded * Removes unnecessary safeLoaded * fix: Coins values and balances The app was retrieving ERC20 tokens information from 3 different endpoints. - One from `balance/` to have the list updated - another from `balance/usd` to have the values in USD - the last one from the blockchain, to update the balances This was all simplified to `balance/usd`. Also, added a `currencyRate` to be updated when the currency is modified. The value calculation happens on a component level, so when the `balanceUsd` value is modified, the value is properly reflected on the screen. Refactored `activateTokensByBalance` to `fetchSafeTokens`, as this was doing quite more than just _activating_ and also added the `currencyList` calculation in it, so everything is updated when `balance/usd` endpoint is requested. * fix: Balance screen Collectibles weren't loading when clicking on the link Also, refactored setState usage, to properly update current state * fix: featuresEnabled undefined * fix: add/activate newly received tokens * fix: NaN Values in Coins for a newly loaded Safe Was failing to set a default value for the `currencyRate` * fix: Settings fails to load if `owners` is not loaded into store Added a `Loader` until the required Safe's data is loaded into store. * fix: prefetch txs data When building the Txs list, we requested data for every tx what was translated into several RPC calls. Now by _batchRequesting_ all the information on beforehand, Safe's loading is a bit faster. * fix: prevent requesting safe, when there's no safe available in the store * enhancement: fetch tokens when loading safe By doing this, when loading a safe in the balance screen we will have tokens immediately loaded into the coins list * fix: load collectibles when switch to collectibles screen Collectibles weren't loaded when clicking menu link for a newly loaded safe. Now every switch to the collectible's screen will trigger a fetch for collectibles. * fix: fetch only if safe is ready Co-authored-by: fernandomg Co-authored-by: Mikhail Mikheev * Fix (#777) * fix: batchRequest params order * fix: execute decodeParams for all sendTokenTxs * fix: proper amount display for tx in TxTable * Uses formatAmount * Removes unused code Fixs params props safe address form * Fixs composeValidators Adds composeValidators for apps section * Makes composeValidatorsApps a wrapper * Moves composeValidatorsApps to managesApps.js * Desktop app (#745) * Set up electron app * Update dependencies * Update package.json * Added https support * Add support for Ledger * Updated certs * Added auto updates messages * Update auto-updater method * Update package.json * Added build resources * Update preload * Update Ledger method on mac * Update build * Merge with develop * Added support for Portis * Fix electron error and updater * Update auto updater * Fix dependencies * Merge with develop * Change auto update functionality * Edit package.json and added github actions * Updated github actions * Fixed Torus + Update github actions * Updated release.yml * Try only ubuntu * Update package.json * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * Updated safe-contracts * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * Updated deploy branch * Updated script Co-authored-by: Mati Dastugue Co-authored-by: Fernando Co-authored-by: nicolas Co-authored-by: Agustin Pane Co-authored-by: Mati Dastugue Co-authored-by: Agustín Longoni Co-authored-by: lukasschor Co-authored-by: David Albela Pérez <3659067+davidalbela@users.noreply.github.com> Co-authored-by: Uxio Fuentefria Co-authored-by: Mati Dastugue --- .github/ISSUE_TEMPLATE/workflows/release.yml | 55 + .github/workflows/release.yml | 69 + .gitignore | 6 +- .travis.yml | 3 + config/webpack.config.prod.js | 4 +- package.json | 171 +- public/auto-updater/index.js | 69 + public/build/all-certs.p12 | Bin 0 -> 3203 bytes public/build/background.png | Bin 0 -> 84944 bytes public/build/entitlements.mac.plist | 22 + public/build/icon.icns | Bin 0 -> 12851 bytes public/build/icon.ico | Bin 0 -> 4911 bytes public/build/safe.png | Bin 0 -> 8821 bytes public/electron.js | 162 + public/ssl/client.crt | 20 + public/ssl/client.csr | 17 + public/ssl/client.key | 27 + public/ssl/client.p12 | Bin 0 -> 2514 bytes public/ssl/rootCA.crt | 22 + public/ssl/rootCA.key | 27 + public/ssl/rootCA.srl | 1 + public/ssl/server.crt | 20 + public/ssl/server.csr | 17 + public/ssl/server.key | 27 + public/ssl/setup.sh | 22 + scripts/notarize.js | 41 + scripts/preload.js | 18 + .../layouts/ListContentLayout/Layout.jsx | 13 +- src/components/CookiesBanner/index.jsx | 2 +- src/components/Root/index.js | 25 +- src/components/Sidebar/index.jsx | 87 +- src/components/forms/AddressInput/index.jsx | 30 - .../forms/Field/DebounceValidationField.js | 36 + src/components/layout/Page/index.scss | 4 +- src/config/index.js | 2 +- .../addressBook/store/selectors/index.js | 13 - src/logic/addressBook/utils/index.js | 2 +- .../store/actions/fetchCollectibles.js | 7 +- src/logic/contracts/generateBatchRequests.js | 58 + src/logic/contracts/methodIds.js | 4 +- src/logic/contracts/safeContracts.js | 8 +- .../api/fetchTokenCurrenciesBalances.js | 6 +- .../actions/fetchCurrencySelectedValue.js | 28 +- .../store/actions/fetchCurrencyValues.js | 41 +- .../store/actions/setCurrencyRate.js | 12 + .../store/actions/setCurrencySelected.js | 2 +- .../store/model/currencyValues.js | 5 +- .../store/reducer/currencyValues.js | 17 +- .../currencyValues/store/selectors/index.js | 3 + src/logic/safe/transactions/gas.js | 87 - src/logic/safe/transactions/gasNew.js | 87 +- .../store/actions/activateAssetsByBalance.js | 7 +- .../store/actions/activateTokensByBalance.js | 61 - .../tokens/store/actions/fetchSafeTokens.js | 100 + src/logic/tokens/store/actions/fetchTokens.js | 16 +- src/logic/tokens/utils/alternativeAbi.js | 2 +- src/routes/index.js | 34 +- .../load/components/DetailsForm/index.jsx | 3 +- .../safe/components/AddressBook/index.jsx | 8 +- .../safe/components/AddressBook/style.js | 3 +- src/routes/safe/components/Apps/ManageApps.js | 210 + src/routes/safe/components/Apps/index.jsx | 363 +- .../safe/components/Apps/sendTransactions.js | 32 +- src/routes/safe/components/Apps/utils.js | 40 +- .../safe/components/Balances/Coins/index.jsx | 14 +- .../components/Balances/Receive/index.jsx | 94 +- .../safe/components/Balances/dataFetcher.js | 37 +- src/routes/safe/components/Balances/index.jsx | 289 +- src/routes/safe/components/Layout.jsx | 400 -- .../safe/components/Layout/Header/index.jsx | 82 + .../components/{ => Layout/Header}/style.js | 31 +- .../Layout/Tabs/SettingsTab/index.jsx | 30 + .../safe/components/Layout/Tabs/index.jsx | 135 + .../safe/components/Layout/Tabs/style.js | 21 + src/routes/safe/components/Layout/index.jsx | 126 + src/routes/safe/components/Layout/style.js | 24 + .../ManageOwners/AddOwnerModal/index.jsx | 77 +- .../AddOwnerModal/screens/OwnerForm/index.jsx | 8 +- .../AddOwnerModal/screens/Review/index.jsx | 12 +- .../screens/ThresholdForm/index.jsx | 10 +- .../ManageOwners/EditOwnerModal/index.jsx | 20 +- .../ManageOwners/RemoveOwnerModal/index.jsx | 82 +- .../RemoveOwnerModal/screens/Review/index.jsx | 23 +- .../screens/ThresholdForm/index.jsx | 10 +- .../ManageOwners/ReplaceOwnerModal/index.jsx | 105 +- .../screens/OwnerForm/index.jsx | 8 +- .../screens/Review/index.jsx | 33 +- .../Settings/ManageOwners/index.jsx | 68 +- .../Settings/RemoveSafeModal/index.jsx | 149 +- .../components/Settings/SafeDetails/index.jsx | 34 +- .../Settings/ThresholdSettings/index.jsx | 51 +- .../safe/components/Settings/actions.js | 19 - src/routes/safe/components/Settings/index.jsx | 254 +- src/routes/safe/components/Settings/style.js | 1 - .../ExpandedTx/ApproveTxModal/index.jsx | 37 +- .../ExpandedTx/OwnersColumn/index.jsx | 15 +- .../TxsTable/ExpandedTx/OwnersColumn/style.js | 4 +- .../ExpandedTx/RejectTxModal/index.jsx | 41 +- .../TxsTable/ExpandedTx/index.jsx | 50 +- .../Transactions/TxsTable/TxType/index.jsx | 10 +- .../Transactions/TxsTable/columns.js | 9 +- .../Transactions/TxsTable/index.jsx | 41 +- .../components/Transactions/TxsTable/style.js | 2 +- .../safe/components/Transactions/index.jsx | 52 - .../container/Hooks/useCheckForUpdates.jsx | 32 + .../safe/container/Hooks/useFetchTokens.jsx | 30 + .../safe/container/Hooks/useLoadSafe.jsx | 30 + src/routes/safe/container/actions.js | 57 - src/routes/safe/container/index.jsx | 224 +- src/routes/safe/container/selector.js | 49 +- .../safe/store/actions/createTransaction.js | 9 +- .../safe/store/actions/fetchEtherBalance.js | 13 +- src/routes/safe/store/actions/fetchSafe.js | 50 +- .../safe/store/actions/fetchTokenBalances.js | 102 - .../safe/store/actions/fetchTransactions.js | 156 +- .../safe/store/actions/processTransaction.js | 5 - src/routes/safe/store/models/transaction.js | 10 +- src/routes/safe/store/selectors/index.js | 103 +- src/test/builder/safe.dom.utils.js | 5 +- ...js => safe.dom.funds.thresholdGt1.test.js} | 2 +- src/test/safe.dom.settings.name.test.js | 2 +- src/test/safe.dom.settings.owners.test.js | 2 +- .../transactions/transactionList.helper.js | 2 +- src/utils/constants.js | 1 + src/utils/googleAnalytics.js | 27 +- src/utils/wrapInSuspense.js | 3 + yarn.lock | 3484 ++++++++++++++--- 127 files changed, 6226 insertions(+), 2958 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/workflows/release.yml create mode 100644 .github/workflows/release.yml create mode 100644 public/auto-updater/index.js create mode 100644 public/build/all-certs.p12 create mode 100644 public/build/background.png create mode 100644 public/build/entitlements.mac.plist create mode 100644 public/build/icon.icns create mode 100644 public/build/icon.ico create mode 100644 public/build/safe.png create mode 100644 public/electron.js create mode 100644 public/ssl/client.crt create mode 100644 public/ssl/client.csr create mode 100644 public/ssl/client.key create mode 100644 public/ssl/client.p12 create mode 100644 public/ssl/rootCA.crt create mode 100644 public/ssl/rootCA.key create mode 100644 public/ssl/rootCA.srl create mode 100644 public/ssl/server.crt create mode 100644 public/ssl/server.csr create mode 100644 public/ssl/server.key create mode 100644 public/ssl/setup.sh create mode 100644 scripts/notarize.js create mode 100644 scripts/preload.js create mode 100644 src/components/forms/Field/DebounceValidationField.js create mode 100644 src/logic/contracts/generateBatchRequests.js create mode 100644 src/logic/currencyValues/store/actions/setCurrencyRate.js delete mode 100644 src/logic/tokens/store/actions/activateTokensByBalance.js create mode 100644 src/logic/tokens/store/actions/fetchSafeTokens.js create mode 100644 src/routes/safe/components/Apps/ManageApps.js delete mode 100644 src/routes/safe/components/Layout.jsx create mode 100644 src/routes/safe/components/Layout/Header/index.jsx rename src/routes/safe/components/{ => Layout/Header}/style.js (73%) create mode 100644 src/routes/safe/components/Layout/Tabs/SettingsTab/index.jsx create mode 100644 src/routes/safe/components/Layout/Tabs/index.jsx create mode 100644 src/routes/safe/components/Layout/Tabs/style.js create mode 100644 src/routes/safe/components/Layout/index.jsx create mode 100644 src/routes/safe/components/Layout/style.js delete mode 100644 src/routes/safe/components/Settings/actions.js delete mode 100644 src/routes/safe/components/Transactions/index.jsx create mode 100644 src/routes/safe/container/Hooks/useCheckForUpdates.jsx create mode 100644 src/routes/safe/container/Hooks/useFetchTokens.jsx create mode 100644 src/routes/safe/container/Hooks/useLoadSafe.jsx delete mode 100644 src/routes/safe/container/actions.js delete mode 100644 src/routes/safe/store/actions/fetchTokenBalances.js rename src/test/{safe.dom.funds.threshold>1.test.js => safe.dom.funds.thresholdGt1.test.js} (99%) create mode 100644 src/utils/wrapInSuspense.js diff --git a/.github/ISSUE_TEMPLATE/workflows/release.yml b/.github/ISSUE_TEMPLATE/workflows/release.yml new file mode 100644 index 00000000..550e1514 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/workflows/release.yml @@ -0,0 +1,55 @@ +name: Build/release + +# this will help you specify where to run +on: + push: + branches: + # this will run on the specified branch + - feature/desktop-app + +env: + REACT_APP_BLOCKNATIVE_KEY: ${{ secrets.REACT_APP_BLOCKNATIVE_KEY }} + REACT_APP_FORTMATIC_KEY: ${{ secrets.REACT_APP_FORTMATIC_KEY }} + REACT_APP_GOOGLE_ANALYTICS_ID_MAINNET: ${{ secrets.REACT_APP_GOOGLE_ANALYTICS_ID_MAINNET }} + REACT_APP_INFURA_TOKEN: ${{ secrets.REACT_APP_INFURA_TOKEN }} + REACT_APP_PORTIS_ID: ${{ secrets.REACT_APP_PORTIS_ID }} + +jobs: + release: + runs-on: ${{ matrix.os }} + + strategy: + matrix: + os: [macos-latest, ubuntu-latest] + + steps: + - name: Check out Git repository + uses: actions/checkout@v1 + + - name: Install Node.js, NPM and Yarn + uses: actions/setup-node@v1 + with: + node-version: 10.16 + + - name: Build/release Electron app + env: + # macOS notarization API key + APPLEID: ${{ secrets.APPLE_ID }} + APPLEIDPASS: ${{ secrets.APPLE_ID_PASS }} + uses: samuelmeuli/action-electron-builder@v1 + with: + #Build scipt + build_script_name: build-desktop + + # GitHub token, automatically provided to the action + # (No need to define this secret in the repo settings) + + github_token: ${{ secrets.github_token }} + + # macOS code signing certificate + mac_certs: ${{ secrets.MAC_CERTS }} + mac_certs_password: ${{ secrets.MAC_CERTS_PASSWORD }} + + # If the commit is tagged with a version (e.g. "v1.0.0"), + # release the app after building + release: ${{ startsWith(github.ref, 'refs/tags/v') }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..50461708 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,69 @@ +name: Build/Release Desktop app + +# this will help you specify where to run +on: + push: + branches: + # this will run on the specified branch + - master + +env: + REACT_APP_BLOCKNATIVE_KEY: ${{ secrets.REACT_APP_BLOCKNATIVE_KEY }} + REACT_APP_FORTMATIC_KEY: ${{ secrets.REACT_APP_FORTMATIC_KEY }} + REACT_APP_GOOGLE_ANALYTICS_ID_MAINNET: ${{ secrets.REACT_APP_GOOGLE_ANALYTICS_ID_MAINNET }} + REACT_APP_INFURA_TOKEN: ${{ secrets.REACT_APP_INFURA_TOKEN }} + REACT_APP_PORTIS_ID: ${{ secrets.REACT_APP_PORTIS_ID }} + +jobs: + release: + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: false + max-parallel: 15 + matrix: + os: [macos-latest, windows-latest, ubuntu-latest] + + steps: + - name: Check out Git repository + uses: actions/checkout@v2 + + - name: Install Node.js, NPM and Yarn + uses: actions/setup-node@v1 + with: + node-version: 10.16 + + - name: Patch node gyp on windows to support Visual Studio 2019 + if: startsWith(matrix.os, 'windows') + shell: powershell + run: | + yarn global add --production windows-build-tools --vs2015 --msvs_version=2015 + - name: Install node-gyp + if: startsWith(matrix.os, 'windows') + shell: powershell + run: | + yarn global add node-gyp + yarn config set node_gyp "$_\node_modules\node-gyp\bin\node-gyp.js" + + - name: Build/Release Desktop App + env: + # macOS notarization API key + APPLEID: ${{ secrets.APPLE_ID }} + APPLEIDPASS: ${{ secrets.APPLE_ID_PASS }} + uses: samuelmeuli/action-electron-builder@v1 + with: + #Build scipt + build_script_name: build-desktop + + # GitHub token, automatically provided to the action + # (No need to define this secret in the repo settings) + + github_token: ${{ secrets.github_token }} + + # macOS code signing certificate + mac_certs: ${{ secrets.MAC_CERTS }} + mac_certs_password: ${{ secrets.MAC_CERTS_PASSWORD }} + + # If the commit is tagged with a version (e.g. "v1.0.0"), + # release the app after building + release: ${{ startsWith(github.ref, 'refs/tags/v') }} diff --git a/.gitignore b/.gitignore index d0d3934a..f83c31b4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,11 @@ node_modules/ build_webpack/ .DS_Store -build/ +./build yarn-error.log .env* .idea/ +dist +electron-builder.yml +.yalc/ +yalc.lock diff --git a/.travis.yml b/.travis.yml index af578168..8ecf3dc7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -44,6 +44,7 @@ deploy: skip_cleanup: true local_dir: build_webpack upload-dir: app + region: $AWS_DEFAULT_REGION on: branch: development @@ -55,6 +56,7 @@ deploy: skip_cleanup: true local_dir: build_webpack upload-dir: current/app + region: $AWS_DEFAULT_REGION on: branch: master @@ -66,6 +68,7 @@ deploy: skip_cleanup: true local_dir: build_webpack upload-dir: releases/$TRAVIS_TAG + region: $AWS_DEFAULT_REGION on: tags: true - provider: script diff --git a/config/webpack.config.prod.js b/config/webpack.config.prod.js index d7a7f957..9d3f67c5 100644 --- a/config/webpack.config.prod.js +++ b/config/webpack.config.prod.js @@ -52,9 +52,11 @@ function ensureSlash(path, needsSlash) { // single-page apps that may serve index.html for nested URLs like /todos/42. // We can't use a relative path in HTML because we don't want to load something // like /todos/42/static/js/bundle.7289d.js. We have to know the root. +const buildDesktop = process.env.BUILD_FOR_DESKTOP + const homepagePath = require(paths.appPackageJson).homepage // var homepagePathname = homepagePath ? url.parse(homepagePath).pathname : '/'; -const homepagePathname = "/app/" +const homepagePathname = buildDesktop === 'true' ? "./" : "/app/" // Webpack uses `publicPath` to determine where the app is being served from. // It requires a trailing slash, or the file assets will get an incorrect path. const publicPath = ensureSlash(homepagePathname, true) diff --git a/package.json b/package.json index 07ac031e..6b96de14 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "safe-react", - "version": "1.9.7", + "version": "2.0.0", "description": "Allowing crypto users manage funds in a safer way", "homepage": "https://github.com/gnosis/safe-react#readme", "bugs": { @@ -8,16 +8,24 @@ }, "repository": { "type": "git", - "url": "https://github.com/gnosis/safe-react" + "url": "https://github.com/gnosis/safe-react.git" }, "license": "MIT", - "author": "Gnosis Team", - "directories": { - "test": "test" + "author": { + "name": "Gnosis Team", + "email": "safe@gnosis.io" }, + "main": "public/electron.js", + "postinstall": "electron-builder install-app-deps", "scripts": { - "build": "REACT_APP_APP_VERSION=$npm_package_version node scripts/build.js", - "build-mainnet": "REACT_APP_NETWORK=mainnet yarn build", + "build": "cross-env REACT_APP_APP_VERSION=$npm_package_version node scripts/build.js", + "electron-build": "electron-builder --mac --windows --linux", + "postinstall": "electron-builder install-app-deps", + "release": "electron-builder --mac --linux --windows -p always", + "electron-dev": "concurrently \"BROWSER=none yarn start\" \"wait-on http://localhost:3000 && electron .\"", + "preelectron-pack": "yarn build", + "build-mainnet": "cross-env REACT_APP_NETWORK=mainnet yarn build", + "build-desktop": "cross-env BUILD_FOR_DESKTOP=true yarn build-mainnet", "flow": "flow", "format:staged": "lint-staged", "lint:check": "eslint './src/**/*.{js,jsx}'", @@ -40,40 +48,136 @@ "prettier --write" ] }, + "productName": "Safe Electron", + "build": { + "appId": "io.gnosis.safe.macos", + "afterSign": "scripts/notarize.js", + "productName": "Safe Electron", + "asar": true, + "publish": [ + { + "provider": "github", + "owner": "gnosis", + "repo": "safe-react" + } + ], + "dmg": { + "sign": false, + "contents": [ + { + "x": 110, + "y": 150 + }, + { + "x": 240, + "y": 150, + "type": "link", + "path": "/Applications" + } + ] + }, + "files": [ + "**/*", + "!src${/*}", + "!config${/*}", + "!contracts${/*}", + "!migrations${/*}", + "!flow-typed${/*}", + "!apps${/*}", + "!build${/*}", + "!out${/*}", + "!.editorconfig", + "!.gitignore", + "!README.md", + "!yarn-error.log", + "!yarn.lock" + ], + "directories": { + "buildResources": "public/build" + }, + "mac": { + "category": "public.app-category.productivity", + "hardenedRuntime": true, + "entitlements": "public/build/entitlements.mac.plist", + "gatekeeperAssess": false, + "entitlementsInherit": "public/build/entitlements.mac.plist", + "target": [ + "dmg", + "zip" + ], + "publish": [ + { + "provider": "github", + "owner": "gnosis", + "repo": "safe-react" + } + ] + }, + "nsis": { + "deleteAppDataOnUninstall": true + }, + "linux": { + "target": [ + "AppImage", + "deb", + "zip" + ], + "icon": "./public/build/safe.png" + }, + "win": { + "target": [ + "nsis" + ], + "icon": "public/build/icon.ico" + } + }, + "resolutions": { + "node-gyp": "^5.1.0" + }, "dependencies": { - "@gnosis.pm/safe-contracts": "1.1.1-dev.1", + "@gnosis.pm/safe-contracts": "1.1.1-dev.2", "@gnosis.pm/util-contracts": "2.0.6", - "@material-ui/core": "4.9.8", + "@ledgerhq/hw-transport-node-hid": "5.12.0", + "@gnosis.pm/safe-react-components": "https://github.com/gnosis/safe-react-components.git#71e6fed", + "@material-ui/core": "4.9.10", "@material-ui/icons": "4.9.1", "@material-ui/lab": "4.0.0-alpha.39", "@openzeppelin/contracts": "^2.5.0", - "@testing-library/jest-dom": "5.3.0", - "@welldone-software/why-did-you-render": "4.0.5", + "@testing-library/jest-dom": "5.5.0", + "@welldone-software/why-did-you-render": "4.0.8", "async-sema": "^3.1.0", "axios": "0.19.2", "bignumber.js": "9.0.0", "bnc-onboard": "1.7.6", "connected-react-router": "6.8.0", + "cross-env": "^7.0.2", "currency-flags": "^2.1.1", - "date-fns": "2.11.1", + "date-fns": "2.12.0", "dotenv": "^8.2.0", + "electron-is-dev": "^1.1.0", + "electron-log": "^4.1.1", + "electron-updater": "4.2.0", "ethereum-ens": "0.8.0", - "final-form": "4.18.7", + "express": "^4.17.1", + "final-form": "4.19.1", "history": "4.10.1", "immortal-db": "^1.0.2", "immutable": "^4.0.0-rc.9", + "install": "^0.13.0", "js-cookie": "^2.2.1", - "lint-staged": "10.0.10", + "lint-staged": "10.1.3", "material-ui-search-bar": "^1.0.0-beta.13", "notistack": "https://github.com/gnosis/notistack.git#v0.9.4", + "npm": "^6.14.4", + "open": "^7.0.3", "optimize-css-assets-webpack-plugin": "5.0.3", "polished": "3.5.1", "qrcode.react": "1.0.0", - "query-string": "6.11.1", + "query-string": "6.12.1", "react": "16.13.1", "react-dev-utils": "10.2.1", "react-dom": "16.13.1", - "react-final-form": "6.3.5", + "react-final-form": "6.4.0", "react-final-form-listeners": "^1.0.2", "react-ga": "^2.7.0", "react-hot-loader": "4.12.20", @@ -86,8 +190,9 @@ "redux-actions": "^2.6.5", "redux-thunk": "^2.3.0", "reselect": "^4.0.0", - "semver": "^7.1.1", + "semver": "7.3.2", "styled-components": "^5.0.1", + "wait-on": "^4.0.1", "web3": "1.2.6" }, "devDependencies": { @@ -112,23 +217,27 @@ "@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.9.0", + "@babel/preset-env": "7.9.5", "@babel/preset-flow": "7.9.0", "@babel/preset-react": "7.9.4", - "@testing-library/react": "10.0.1", - "autoprefixer": "9.7.5", + "@testing-library/react": "10.0.2", + "autoprefixer": "9.7.6", "babel-core": "^7.0.0-bridge.0", "babel-eslint": "10.1.0", - "babel-jest": "25.2.4", + "babel-jest": "25.3.0", "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", "babel-polyfill": "^6.26.0", "classnames": "^2.2.6", - "css-loader": "3.4.2", + "concurrently": "4.1.2", + "css-loader": "3.5.2", "detect-port": "^1.3.0", "dotenv-expand": "^5.1.0", + "electron": "7.1.8", + "electron-builder": "22.2.0", + "electron-notarize": "^0.2.1", "eslint": "^6.8.0", "eslint-config-prettier": "6.10.1", "eslint-plugin-flowtype": "4.7.0", @@ -140,28 +249,28 @@ "ethereumjs-abi": "0.6.8", "extract-text-webpack-plugin": "^4.0.0-beta.0", "file-loader": "6.0.0", - "flow-bin": "0.121.0", + "flow-bin": "0.122.0", "fs-extra": "9.0.0", - "html-loader": "1.0.0", - "html-webpack-plugin": "4.0.3", + "html-loader": "1.1.0", + "html-webpack-plugin": "4.2.0", "husky": "^4.2.2", - "jest": "25.2.4", + "jest": "25.3.0", "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": "2.0.2", + "prettier": "2.0.4", "run-with-testrpc": "0.3.1", - "style-loader": "1.1.3", + "style-loader": "1.1.4", "terser-webpack-plugin": "2.3.5", - "truffle": "5.1.19", + "truffle": "5.1.21", "truffle-contract": "4.0.31", "truffle-solidity-loader": "0.1.32", - "url-loader": "4.0.0", + "url-loader": "4.1.0", "webpack": "4.42.1", - "webpack-bundle-analyzer": "3.6.1", + "webpack-bundle-analyzer": "3.7.0", "webpack-cli": "3.3.11", "webpack-dev-server": "3.10.3", "webpack-manifest-plugin": "2.2.0" diff --git a/public/auto-updater/index.js b/public/auto-updater/index.js new file mode 100644 index 00000000..7713063e --- /dev/null +++ b/public/auto-updater/index.js @@ -0,0 +1,69 @@ +const os = require('os'); +const fetch = require('node-fetch'); +const { dialog, app } = require('electron'); +const log = require('electron-log'); +const isDev = require("electron-is-dev"); +const { autoUpdater } = require("electron-updater"); + +// This logging setup is not required for auto-updates to work, +// but it sure makes debugging easier :) +//------------------------------------------------------------------- + +autoUpdater.autoDownload = false +autoUpdater.logger = log; +autoUpdater.logger.transports.file.level = 'info'; +log.info('App starting...'); + +let initialized = false; +let downloadProgress = 0; + +function init(mainWindow) { + + if(initialized || isDev) return; + + initialized = true; + + autoUpdater.on('error', (error) => { + dialog.showErrorBox('Error: ', error == null ? "unknown" : (error.stack || error).toString()); + }); + + autoUpdater.on('update-available', () => { + dialog.showMessageBox({ + type: 'info', + title: 'Found Updates', + message: 'There is a newer version of this app available. Do you want to update now?', + buttons: ['Yes', 'Remind me later'], + cancelId:1, + }).then(result => { + if(result.response === 0){ + autoUpdater.downloadUpdate(); + } + }); + + autoUpdater.on('update-downloaded', (event, releaseNotes, releaseName) => { + autoUpdater.logger.info("Update Downloaded..."); + dialog.showMessageBox({ + title: 'Install Updates', + message: process.platform === 'win32' ? releaseNotes : releaseName, + detail: 'A new version has been downloaded. Restart the application to apply the updates.', + buttons: ['Restart', 'Cancel'], + cancelId:1, + }).then(result => { + if(result.response === 0){ + autoUpdater.quitAndInstall(); + } + }); + }); + }); + + autoUpdater.on("download-progress", (d) => { + downloadProgress = d.percent; + autoUpdater.logger.info(downloadProgress); + }); + + autoUpdater.checkForUpdates(); +} + +module.exports = { + init, +}; diff --git a/public/build/all-certs.p12 b/public/build/all-certs.p12 new file mode 100644 index 0000000000000000000000000000000000000000..6f79543d77ce5d0ab6469dbc1b7d475e9735cef1 GIT binary patch literal 3203 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 literal 0 HcmV?d00001 diff --git a/public/build/background.png b/public/build/background.png new file mode 100644 index 0000000000000000000000000000000000000000..4c0b9ba39112f0218d3d35b34465abd5e08e8715 GIT binary patch literal 84944 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ℜU#1 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 hXT1MUe=8Yo2)YZn?{%%BzWo;Asj`MrwSq + + + + com.apple.security.network.client + + com.apple.security.network.server + + com.apple.security.cs.allow-jit + + com.apple.security.cs.allow-unsigned-executable-memory + + com.apple.security.device.camera + + com.apple.security.device.microphone + + com.apple.security.cs.allow-dyld-environment-variables + + com.apple.security.cs.disable-library-validation + + + \ No newline at end of file diff --git a/public/build/icon.icns b/public/build/icon.icns new file mode 100644 index 0000000000000000000000000000000000000000..a929bcba4892236fb380fbd429fcd0f9bb8b15bd GIT binary patch literal 12851 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 literal 0 HcmV?d00001 diff --git a/public/build/icon.ico b/public/build/icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..40a1cc30018ad37358bdacc763e5980963a88d37 GIT binary patch literal 4911 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 N`r2@>pZTmckRl&bscY$wR^Di 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 { + const app = express(); + const staticRoute = path.join(__dirname, '../build_webpack'); + app.use(express.static(staticRoute)); + https.createServer(options, app).listen(PORT); +} + + +let mainWindow; + +function getOpenedWindow(url,options) { + let display = electron.screen.getPrimaryDisplay(); + let width = display.bounds.width; + let height = display.bounds.height; + + // filter all requests to trezor-bridge and change origin to make it work + const filter = { + urls: ['http://127.0.0.1:21325/*'] + }; + + options.webPreferences.affinity = 'main-window'; + + if(url.includes('about:blank')){ + /* + session.defaultSession.webRequest.onBeforeSendHeaders(filter, (details, callback) => { + details.requestHeaders['Origin'] = 'https://electron.trezor.io'; + callback({cancel: false, requestHeaders: details.requestHeaders}); + }); + */ + } + + if(url.includes('wallet.portis') || url.includes('about:blank') || url.includes('app.tor.us')){ + const win = new BrowserWindow({ + width:300, + height:700, + x: width - 1300, + parent:mainWindow, + y: height - 200, + webContents: options.webContents, // use existing webContents if provided + fullscreen: false, + show: false, + }); + + win.once('ready-to-show', () => win.show()); + + if(!options.webPreferences){ + win.loadURL(url); + } + return win + } + + return null; + +} + +function createWindow() { + mainWindow = new BrowserWindow({ + show: false, + width: 1024, + height: 768, + webPreferences: { + preload: path.join(__dirname, '../scripts/preload.js'), + allowRunningInsecureContent: true, + nativeWindowOpen: true, // need to be set in order to display modal + }, + icon: path.join(__dirname, './build/safe.png'), + }); + + mainWindow.once('ready-to-show', () => { + mainWindow.show(); + }); + + mainWindow.loadURL( + isDev + ? "http://localhost:3000" + : `https://localhost:${PORT}` + ) + + if (isDev) { + // Open the DevTools. + mainWindow.webContents.openDevTools(); + //BrowserWindow.addDevToolsExtension(''); + } + + mainWindow.setMenu(null); + mainWindow.setMenuBarVisibility(false); + + mainWindow.webContents.on('new-window', function(event, url, frameName, disposition, options){ + event.preventDefault(); + const win = getOpenedWindow(url,options); + if(win){ + win.once('ready-to-show', () => win.show()); + + if(!options.webPreferences){ + win.loadURL(url); + } + + event.newGuest = win + } else open(url); + }); + + mainWindow.webContents.on('did-finish-load', () => { + autoUpdater.init(mainWindow); + }); + + mainWindow.webContents.on('crashed', () => { + log.info('App Crashed'); + mainWindow.reload(); + }); + + mainWindow.on("closed", () => (mainWindow = null)); +} + +app.userAgentFallback = process.platform ==='win32' ? +'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.100 Safari/537.36' : +'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) old-airport-include/1.0.0 Chrome Electron/7.1.7 Safari/537.36'; + +app.commandLine.appendSwitch('ignore-certificate-errors'); +app.on("ready", () =>{ + // Hide the menu + //Menu.setApplicationMenu(null); + if(!isDev) createServer(); + createWindow(); +}); + +app.on("window-all-closed", () => { + if (process.platform !== "darwin") { + app.quit(); + } +}); + +app.on("activate", () => { + if (mainWindow === null) { + createWindow(); + } +}); \ No newline at end of file diff --git a/public/ssl/client.crt b/public/ssl/client.crt new file mode 100644 index 00000000..85044731 --- /dev/null +++ b/public/ssl/client.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDTzCCAjcCFA3n/7f/k+b9g/7W6zodg+u2qC3BMA0GCSqGSIb3DQEBCwUAMGQx +CzAJBgNVBAYTAkRFMRAwDgYDVQQIDAdHZXJtYW55MREwDwYDVQQHDAhXYWxsZG9y +ZjEPMA0GA1UECgwGU0FQIFNFMQ4wDAYDVQQLDAVUb29sczEPMA0GA1UEAwwGcm9v +dENBMB4XDTIwMDMyNzIxMTkxNFoXDTIxMDgwOTIxMTkxNFowZDELMAkGA1UEBhMC +REUxEDAOBgNVBAgMB0dlcm1hbnkxETAPBgNVBAcMCFdhbGxkb3JmMQ8wDQYDVQQK +DAZTQVAgU0UxDjAMBgNVBAsMBVRvb2xzMQ8wDQYDVQQDDAZjbGllbnQwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCZ7hsC/0FOfOUUyefqhFvmiYJoqMSi +8/vvjJKn+TCXhlfX/BLxBtJN8BlFNDux+qPlPhElbCg0bldeBGkZNgD7Jt6Fjpkd +SqqoDIcfl+oxAks76Qi5hh2FKHSOp3BmHgVuur+cbzOd8J+NsskGYay32mAHLrq8 +ixPLUtkOO9W2PSKm9KQEwOdYV9R/dStvZDA5dEVEDGv3MIBgRVzyu8gGwMfjzci1 +wgwU5Eb2r2b7Vs19nAoLQwelBf4bL5Z5b2KjfW1HPhmtM1eBaf+3bMscnemAgY8I +0ZHMS0XjORLvSBKZ73Q1K9lv6dc45fQA6g3KnVvFSB0nfqbhw7vuDEXrAgMBAAEw +DQYJKoZIhvcNAQELBQADggEBAAzKry8DXN6tlIE5ZRp9z/MdT8bOSwNQM9H/E1Rn +50fP5C3m5IZioYdsfQtDvEC2bHHIYyWvqL6AAWVOzA8Pvnw1J32Sq3Tz5EwH0B5p +wRVxB2GEe7WqSQV88fd2l35/5vcpoe5A444n6qb8ZaqzdBYXgyUPyVAbzcySKEm/ +b1HuV8dhlOWZcwgGAdgf/yBhu8WN1Mau6zTAFK2osKUQM2TeXCDKX6tDAHryD6jA +MP/med+RSLJyyL5OYBl1P/gqSstH0HnpkpeYslaZpXncT2V2PHTwXOs2ywOESil6 +yEi9KcsPe87hJ5aMJ0iw/A8AkDBnSzvx2LoYtgLxWl/+4xw= +-----END CERTIFICATE----- diff --git a/public/ssl/client.csr b/public/ssl/client.csr new file mode 100644 index 00000000..316742b4 --- /dev/null +++ b/public/ssl/client.csr @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICqTCCAZECAQAwZDELMAkGA1UEBhMCREUxEDAOBgNVBAgMB0dlcm1hbnkxETAP +BgNVBAcMCFdhbGxkb3JmMQ8wDQYDVQQKDAZTQVAgU0UxDjAMBgNVBAsMBVRvb2xz +MQ8wDQYDVQQDDAZjbGllbnQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQCZ7hsC/0FOfOUUyefqhFvmiYJoqMSi8/vvjJKn+TCXhlfX/BLxBtJN8BlFNDux ++qPlPhElbCg0bldeBGkZNgD7Jt6FjpkdSqqoDIcfl+oxAks76Qi5hh2FKHSOp3Bm +HgVuur+cbzOd8J+NsskGYay32mAHLrq8ixPLUtkOO9W2PSKm9KQEwOdYV9R/dStv +ZDA5dEVEDGv3MIBgRVzyu8gGwMfjzci1wgwU5Eb2r2b7Vs19nAoLQwelBf4bL5Z5 +b2KjfW1HPhmtM1eBaf+3bMscnemAgY8I0ZHMS0XjORLvSBKZ73Q1K9lv6dc45fQA +6g3KnVvFSB0nfqbhw7vuDEXrAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEAMQNR +9TrgG1Re1z2nmxQ2lWPfpdx5wTFc2SibJhMGTahEhAW6XJEtYpTPE+S2LEIybr9k +Ya+Pg/Q6pE2MjCDMOSkmfXVcyu/Fw+Ek1anNQ1IDS68vVA3lUNpXYHPffZOTdlj6 +15n7GMUdSISLk8jZOLGli26PLQimSzHeLUjHwFaS6fs5dXrASdDEAq+GfjXw+R83 +Lh6ENb9ojdtnHhEspWsiuyJVT4GgV2U1q9m+ljZJe8fBgQP3exxVZXgnAeogpy4r ++pTjJIRuaxr3xnd/oYQDCaKpXptEuHQ5caQzFmmUM94sAZkQJQn5VVjSCfDv2ZHm +Rp+QdXH8iMjiaxKUaQ== +-----END CERTIFICATE REQUEST----- diff --git a/public/ssl/client.key b/public/ssl/client.key new file mode 100644 index 00000000..21f2401d --- /dev/null +++ b/public/ssl/client.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAme4bAv9BTnzlFMnn6oRb5omCaKjEovP774ySp/kwl4ZX1/wS +8QbSTfAZRTQ7sfqj5T4RJWwoNG5XXgRpGTYA+ybehY6ZHUqqqAyHH5fqMQJLO+kI +uYYdhSh0jqdwZh4Fbrq/nG8znfCfjbLJBmGst9pgBy66vIsTy1LZDjvVtj0ipvSk +BMDnWFfUf3Urb2QwOXRFRAxr9zCAYEVc8rvIBsDH483ItcIMFORG9q9m+1bNfZwK +C0MHpQX+Gy+WeW9io31tRz4ZrTNXgWn/t2zLHJ3pgIGPCNGRzEtF4zkS70gSme90 +NSvZb+nXOOX0AOoNyp1bxUgdJ36m4cO77gxF6wIDAQABAoIBAQCEQ+Vv8Ncz0vug +nlEp4St6b2Pf/ExiXNV5I8gMj4FiYexvSUkZVCw3Df0YyuYUa3KTE372MfZl/v4R +aibIo++53s9L4ZjNY5A6L/GXgxiXngn5Y6a8i3IoLffhcByTkm5GlC77A05OAymG +Pz6eviUEIZ9r7IpGYhbTGdAqe92J5a72yaGK7+xzA/srX1a8C1qVqsoVBT/js99m +kNGZDbpjNLZhXAaze51+Z4ehwVDjJXHgxiCRvoZprxo49DTe/xKef5k1p8rEcv78 +b56B5fYXOnIa2VavEJmEcuaX7uEAW2LT5/hRck/1ekhUBkhJ1BjzgYXqrbX9BiMO +wiSjn9pRAoGBAMtg9ewPESMLdKvxAQ9O6DEoRlN1KqHjwkoDZXM9Hw1dDWtxDsuC +MwvlzQEj0EVF1N5FedQVuaFVB6Bcq2tIcqvtYOBsflkF01Fe6CSgrqwmWps2tw4p +3TbFPNtXlQwUN0CcOzlCimo5dWoa5GT5VAEjXJBy1qmlZunbPlYJBf+pAoGBAMHB +2mdK5SKjvduEm+65W4VyhY1S40a8sGI9LcbCnMN1sZcOII0I/1CVsvJMZDj6XVbA +/dT76OkrL8uk20oYImNpfMSejiBUB4nLbhcI665jVUd9mG+H0v+wT9L6Nh9cvA8U +QNHHPGkzBFOqzXk59p8cFWoIIY5xzcPiydh7jyVzAoGBALwPn7e1wvnt6Ofphjpa +k7iI7mbT7CUgz5LTCyeBeEpKJlOYir7CWWOCDowkSr0TsqAKDHqB0FIPp2qw5k3h +AzBZ44ACst6s1Vfj87OS5ZIIMTZfZOvy6DxyLDEDDq7JrsHO9bCgCA/rq9f+n/2C +1BvtT/W+SyM58C0E7+Jsm6BpAoGBAJrP1T3q7aH7ytr23dCkcafylRsSO15trVER +KN5C6RaTl03mj8OgiL9OnShUOU/9W07R7P6cOMD1LL89/aj6F5/uzS4csdrKySsk +S9ZD3mv8GkuA4qdakxCRQ3aDTXNJmUlDGXeEBZTYmoBvXLWbxp3ixolt7cHu1EXL +kxNRxlJZAoGAO/Qzs10/joY5R7jadZdclVfleuD0Y5HmpEr2WgXvVwzB3QJqHd2i +lovuNtDpUal5ncDzDKdHacoED5gYncDIT6Quair3VfHsm3LlQWiZT86bQUWRBD+J +z/4ppzGkzePS4Rf01Cjb7RwlQ7uDCaVyPjvCbAVaPBYQVr3FvaYLJbM= +-----END RSA PRIVATE KEY----- diff --git a/public/ssl/client.p12 b/public/ssl/client.p12 new file mode 100644 index 0000000000000000000000000000000000000000..019a931b174f4e9033d2a3c31e767af831ba3e50 GIT binary patch literal 2514 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 Qhp#}Bs~jVA@E4)~0&0A%761SM literal 0 HcmV?d00001 diff --git a/public/ssl/rootCA.crt b/public/ssl/rootCA.crt new file mode 100644 index 00000000..1290586a --- /dev/null +++ b/public/ssl/rootCA.crt @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDqTCCApGgAwIBAgIUdULIRijfukG4cY7OZiPC02tL2WYwDQYJKoZIhvcNAQEL +BQAwZDELMAkGA1UEBhMCREUxEDAOBgNVBAgMB0dlcm1hbnkxETAPBgNVBAcMCFdh +bGxkb3JmMQ8wDQYDVQQKDAZTQVAgU0UxDjAMBgNVBAsMBVRvb2xzMQ8wDQYDVQQD +DAZyb290Q0EwHhcNMjAwMzI3MjExOTE0WhcNMjMwMTE1MjExOTE0WjBkMQswCQYD +VQQGEwJERTEQMA4GA1UECAwHR2VybWFueTERMA8GA1UEBwwIV2FsbGRvcmYxDzAN +BgNVBAoMBlNBUCBTRTEOMAwGA1UECwwFVG9vbHMxDzANBgNVBAMMBnJvb3RDQTCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMgq1Lz8VFNo41q0zCrZPnXM +im10M9JYUGFl5s3xRP/70scuc7EpUhQPrQy6mIUEHes7uD6kRWwViM4JtpvebH52 +T+caNNk6iTcYbXC1wENRJF/A64OHeVT1RJQxN0KqVQWMYoZLFS+R1JuXVnGj0J1B +jRBwJOL4MC/mYD90k/ik6r05OH8hATk+5DzzGpPK2pawpD6nU8q/X7C1XdRNZS05 +7jv6Of8aonkKl6k26+zCWgHXitOagWB2sOTBH7moQEwJSWeLR5CTr/5//FSP5TT8 +aR0RO1y0X/RwIif/bobBsnPZnjvpHgb83a+5ZbZt7PRz6hrvyoQofrhh2yNSogkC +AwEAAaNTMFEwHQYDVR0OBBYEFImeXkZLHA+SYuyLyBsR5cWgSL6GMB8GA1UdIwQY +MBaAFImeXkZLHA+SYuyLyBsR5cWgSL6GMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI +hvcNAQELBQADggEBAICitWFs3JzAH42GA/45FBYjfKqXorQp22rzQ2nAXFw9nPWC +FXNIv6EUWW4SsV5AnEnOGqpC+14/sXTiSWJnqgVk8ZzeOw8is/52cigGSno7wgcX +9me72WZxlehYsf0gdx7vZAnyrFSfJ2Q/N6EAJ1LSZe92xB4A58O7dqfNPqgtZrU2 +QufA81rGqr7LiWZGzPXTX8jLTV8JuXTs/yiDawSpoInasofTJMom5zdAjYoZJrcW +m+gz4yEshWzPl6qbVGvUWYdeWQ1KI9EZXUnxPzswPjqutGlE31QGcJDXvfBTeQS+ +c0XmLDf22h43UaNzYRdWc3IcPLned3qNlBPI3qY= +-----END CERTIFICATE----- diff --git a/public/ssl/rootCA.key b/public/ssl/rootCA.key new file mode 100644 index 00000000..a93aab30 --- /dev/null +++ b/public/ssl/rootCA.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAyCrUvPxUU2jjWrTMKtk+dcyKbXQz0lhQYWXmzfFE//vSxy5z +sSlSFA+tDLqYhQQd6zu4PqRFbBWIzgm2m95sfnZP5xo02TqJNxhtcLXAQ1EkX8Dr +g4d5VPVElDE3QqpVBYxihksVL5HUm5dWcaPQnUGNEHAk4vgwL+ZgP3ST+KTqvTk4 +fyEBOT7kPPMak8ralrCkPqdTyr9fsLVd1E1lLTnuO/o5/xqieQqXqTbr7MJaAdeK +05qBYHaw5MEfuahATAlJZ4tHkJOv/n/8VI/lNPxpHRE7XLRf9HAiJ/9uhsGyc9me +O+keBvzdr7lltm3s9HPqGu/KhCh+uGHbI1KiCQIDAQABAoIBAAVr240uzF3h9l5r +jSgP8DgijRE/13N3/t1UdDbZtQO131STtoBy3Q08C3TPzPe1T9YiLPBNZK/zuVvT +OYXpNUkLjUh2Fj5X7oV2fOhTk9x+4xxQzlAmqCub5PqahqOgl2LqFXULrYw3R+na +5HV5eVn4/4gVcXpQPIXfmHW/g451ZL444jcn1TQYnE0CxlUastc5kaltCR53TWY0 +5UNGbbhnbDm5d04uYBFo+a+5MmYSVJ5KDf/BrUBMKcjPetnv0jQfoBao+oka2uie +42dqtRWJG2JiJXXG8sSCiLHW9qPgjp8wVgb79AkMpIjdlabQvaI5q/7pSVyf1x2h +bLhVI4ECgYEA58RINaEZkSYhwhUnvY1agBGHajmAAz8krgyPRGj/HzYmLbwUgZI7 +OIuB6uiWgK3VtP49oVMA5szrkMW4V5pKgL9piSzCOIKtRImblOFQcqKxCt0MrSzx +D1kwJ1YIpFueZwZ9/ngZttKhIRRscNkJUSazeFi2gDrKjKXoms4LyLECgYEA3Ri5 +kMeF3yNwJmSAmupPemeuExR8L00YC5B93WWUzNcJ2pVJhSHHAPZ4OB4Z+7iLoCpM +/5iWku+kySg6AugH6fWlDoC5mTXLTa11M+rwVv1INO5PSWbxPoMe7DMTtbYkhUxW +HMMXg1P9eS4a1fFiPHnEvT+ovKuOJ4MJIzwOxNkCgYAiw1gpYx6YnOWXXOD3F4qp +hveOwU0oL4Jq8MtUcYNCxTZ4yasxvCNR2esEtxpL9scFPNU1q2OJOtdigaWiziu6 +n/tObf47x64Bh7pkXF9asnhnrrxGBWWq7a/BVrA5JtzdiyW+03jX6UPt2EhjrMou +9+UXegb1uNvEuOXowlsWIQKBgEcvx8eaxjqzIU/rOhEm8hIaQcz44ockTmKi0jOv +mjpd3llXicVou7dOpCSFZJ5MrAAUvpfpHEoRCMCPyCXZaXrl0ZAa2CdBT8Uh3UOr +GFkZ0d7g//xFPdV/yDwKsgTmsVmN24gFNJPfPhR/SLqrrpKELlk0nvKoVevY399N +Xf/5AoGBAMTYf04U30iMgjwrXCQAebCKA641DshyxplYiTZYddhGUigUslxrrSA9 +stdRoYmwlmXwwtGEyu/064sZiOQap8+MtL/mUrdpHzZfy+xK883d6UnYe/iTONgc +j7kBt543WxzQSRW/1l58xgZWltJlCE5EZCKXA7fX+IoIQZQnYRI4 +-----END RSA PRIVATE KEY----- diff --git a/public/ssl/rootCA.srl b/public/ssl/rootCA.srl new file mode 100644 index 00000000..58b8b9d9 --- /dev/null +++ b/public/ssl/rootCA.srl @@ -0,0 +1 @@ +0DE7FFB7FF93E6FD83FED6EB3A1D83EBB6A82DC1 diff --git a/public/ssl/server.crt b/public/ssl/server.crt new file mode 100644 index 00000000..c400ffb0 --- /dev/null +++ b/public/ssl/server.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDUjCCAjoCFA3n/7f/k+b9g/7W6zodg+u2qC3AMA0GCSqGSIb3DQEBCwUAMGQx +CzAJBgNVBAYTAkRFMRAwDgYDVQQIDAdHZXJtYW55MREwDwYDVQQHDAhXYWxsZG9y +ZjEPMA0GA1UECgwGU0FQIFNFMQ4wDAYDVQQLDAVUb29sczEPMA0GA1UEAwwGcm9v +dENBMB4XDTIwMDMyNzIxMTkxNFoXDTIxMDgwOTIxMTkxNFowZzELMAkGA1UEBhMC +REUxEDAOBgNVBAgMB0dlcm1hbnkxETAPBgNVBAcMCFdhbGxkb3JmMQ8wDQYDVQQK +DAZTQVAgU0UxDjAMBgNVBAsMBVRvb2xzMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx+njjit6UtTPP8IImkVc5UAYc +3XKXVpCjWSqMSL3xj1O9zWPz4Ke+0mxH4mh6Ko0yO6+eBmzozSJUO1sU/Iz8v5T8 +ZqqXANkF5v/zBjVMCPb6jiA9hLmJBpzGRB07fiuf17fI0lQ9HpuNNjsmm5x1fWBO +/D/KEM9218Bu9XkSAplIGg86xuvpdPpYLrxNbx9xWWlcRB7IRUIGfNbRFHWC0ryW +5kLzVSHhK3EYfAvak6mdIJ4iXySWuY4qaUE9/Iijud1JTuq9lKZS4qWdg7NmAGWH +bau2cSYWZeFc9ACAVNcE+YNLwzXyGIXCLgAtQ0vJCPj3Yf/lF9vvc2mQ114dAgMB +AAEwDQYJKoZIhvcNAQELBQADggEBAL/jf+OeGeXiX2f0ot3kYEe5XKflQb++8eop +iXbm6nqD9syWW6mpON1tZQ9EmIpT4dnh+D2+OFqM1QpF7zNZXRzIOrAfjKayq0yd +taA6zDdDUVPWAzHZz4R70UiMSXJFIDtKhWm7wEEjr72OgYC3nlYrvffhSS3pRrBF +kXRKpuuE9Yt60ciKeFssozS/wuflQ6fcDawTpwtzYU7z5p5B4KL1TmB6ZTXLfmD3 +aotONmHOKqNUKdvgNfH9+09S3/bNsbSsA5epWjR9rm/PidRyk4x1UZEc3FAoSkGq +4r8TBc1LXsMk6TxUTRzEbtxCsoAllpPivi+cyGUNf+iF/FIWD+U= +-----END CERTIFICATE----- diff --git a/public/ssl/server.csr b/public/ssl/server.csr new file mode 100644 index 00000000..ee3d97b8 --- /dev/null +++ b/public/ssl/server.csr @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICrDCCAZQCAQAwZzELMAkGA1UEBhMCREUxEDAOBgNVBAgMB0dlcm1hbnkxETAP +BgNVBAcMCFdhbGxkb3JmMQ8wDQYDVQQKDAZTQVAgU0UxDjAMBgNVBAsMBVRvb2xz +MRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQCx+njjit6UtTPP8IImkVc5UAYc3XKXVpCjWSqMSL3xj1O9zWPz4Ke+0mxH +4mh6Ko0yO6+eBmzozSJUO1sU/Iz8v5T8ZqqXANkF5v/zBjVMCPb6jiA9hLmJBpzG +RB07fiuf17fI0lQ9HpuNNjsmm5x1fWBO/D/KEM9218Bu9XkSAplIGg86xuvpdPpY +LrxNbx9xWWlcRB7IRUIGfNbRFHWC0ryW5kLzVSHhK3EYfAvak6mdIJ4iXySWuY4q +aUE9/Iijud1JTuq9lKZS4qWdg7NmAGWHbau2cSYWZeFc9ACAVNcE+YNLwzXyGIXC +LgAtQ0vJCPj3Yf/lF9vvc2mQ114dAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEA +I3455yEdVYmyv+9aDGNuUAPEKvnubLZOuEC6IweCT88f9cwQlvTNSkgQ8ylJ40oQ +D/akfBMQEc11NjVoRE5jFPabLMr0wC/KWL5RhXAwu82pC7l64jd8xLhHWXE1cY7h +i7pGBawcvnuqlkwPnd6OSh4c1MdHMsefBb8RKvDJ4I6iWfu1ZKBWWBknnTKwEB/y +K/jCq81z3xwlNx8r5MT43thzYMRxRIXX63Le28OurRWJNCxuyrQUh7dqGhbfXvOC +VCvFZphRc8bB9h45wvblPAgcVVDcqpKUGHvqUd456wQJ0JIer0VXhrAMIdzBiCzl +eqBFgozJ6u2jBWxvfrnHWQ== +-----END CERTIFICATE REQUEST----- diff --git a/public/ssl/server.key b/public/ssl/server.key new file mode 100644 index 00000000..97986765 --- /dev/null +++ b/public/ssl/server.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAsfp444relLUzz/CCJpFXOVAGHN1yl1aQo1kqjEi98Y9Tvc1j +8+CnvtJsR+JoeiqNMjuvngZs6M0iVDtbFPyM/L+U/GaqlwDZBeb/8wY1TAj2+o4g +PYS5iQacxkQdO34rn9e3yNJUPR6bjTY7JpucdX1gTvw/yhDPdtfAbvV5EgKZSBoP +Osbr6XT6WC68TW8fcVlpXEQeyEVCBnzW0RR1gtK8luZC81Uh4StxGHwL2pOpnSCe +Il8klrmOKmlBPfyIo7ndSU7qvZSmUuKlnYOzZgBlh22rtnEmFmXhXPQAgFTXBPmD +S8M18hiFwi4ALUNLyQj492H/5Rfb73NpkNdeHQIDAQABAoIBAD8+OebhWeaN3TNu +y1DZJJ2BCisHpciRQiRJcw0WbCiCPcecTIBEvFbafw+sLGP86t+GxgjpT5oKCsDT +trHmbFMD4PUvpj6yVmv6gcjh096I8Ppntp0lpKhEaUEqwxh45RePmAcMdlKhpbSw +KKS3dwlo2+g1SpWLE62vTPog0DzNh8WtFePAqt5SzA07fpuZSuhobchCHQpZS4Kr +Pv8mJj/uWSa3ysVqJ6FaqeIqMTNP5S5QxJw/OOLR+0Wzi8m2ET0Be16H7NO7EgXr +6xjY3GcI292oXylSFMSZkKuRf3fX08AP8hKsP7A7qjTY/S4gQ1Tte9B0s2Uq7LJx +liXmoAECgYEA3n4cfmCFZwe1NjpksKe8kLm871oq5x7UB3OsbIKPYvdp2/G3eour +175qe5oMJgJe28Jqgu7EE9zDQcGMSpV7yapbeGcIg5h7b2a1Un3TbvJIMBLBrbR6 +fGwW+gL0REeLrl7vMgrUTXO1/MbiMvoa48fUea+PLW48qQ53qGh2TR0CgYEAzMgt +oY1pBTNim+0pgjQTwAi+y0Jirc6pAfunrf72onBy5Bt0arBsYMlKjZS6yaR78aqh +JNHymXRHwQZK9oMx6tLR8jT+E9LJH7Hk2Vv5M6f8xZwF/f0zc67mSEuj+mHc0X++ +qd7lYmudyAfWM0+A3DUVAXUyMnoKZzvCO9fFhQECgYEAg5Vj9p3Q56EYW8znFc7t +503h3lCeRPfnf8y6caY5dNdMJQbscy49YCe+RAFUI/qM7T0qzuq0zeZnF/GGremA +P0FgPXH6CBHbFoRQwkumCtyBMuU05C1zrzgh0pSCsAr8IhEFN7xN2MyRGcDpsCpY +UtQw5hKdA8pJV9Y1kETPikUCgYA64z2r/Vw78KDksfiDxrH/QQSMstRposobFeEM +Ogt2fturGPILVBx2YKwdtq1YGwLBZg3c5rrawgN4UHTyGpwaKPHSssZ1sOHBSYjD +sJ0i66XWtZ1LgqpvE9aI56eJ8uZrIE8VzlEsUkIXKZnBO5WUvXcC6k67ETk4ooii +aNQWAQKBgQDOlUkeRQjVhm9fW8HrKdqUf4+1Zge4wwOi6q4fO4EdaSFu9KGnUOmS +crvagTexI5MPHuq7LuK4MsWrNlbxJ/axjazDDLqeaWaWOtJvO+L274yWQtRQ4/DY +tcTDKTbGln/v+x8eWW9OhUy/ADUFPkweXoemnI5iIdjymkZFGB/XlQ== +-----END RSA PRIVATE KEY----- diff --git a/public/ssl/setup.sh b/public/ssl/setup.sh new file mode 100644 index 00000000..e19029da --- /dev/null +++ b/public/ssl/setup.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +# From https://github.com/thojansen/client-certificates/blob/master/ssl/setup.sh +# create rootCA certificate +openssl genrsa -out rootCA.key 2048 +openssl req -x509 -new -nodes -key rootCA.key -days 1024 -out rootCA.crt -subj "/C=DE/ST=Germany/L=Walldorf/O=SAP SE/OU=Tools/CN=rootCA" + +# create server key and certificate +openssl genrsa -out server.key 2048 +openssl req -new -key server.key -out server.csr -subj "/C=DE/ST=Germany/L=Walldorf/O=SAP SE/OU=Tools/CN=localhost" +openssl x509 -req -in server.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out server.crt -days 500 + +# create client key and certificate +openssl genrsa -out client.key 2048 +openssl req -new -key client.key -out client.csr -subj "/C=DE/ST=Germany/L=Walldorf/O=SAP SE/OU=Tools/CN=client" +openssl x509 -req -in client.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out client.crt -days 500 + +# generate client.p12 file which can be easily imported to OS. +openssl pkcs12 -export -inkey client.key -in client.crt -name client -out client.p12 + +# generate a non-encrypt pem file with key and crt files, from p12 files +#openssl pkcs12 -in client.p12 -out client.pem -nodes -clcerts \ No newline at end of file diff --git a/scripts/notarize.js b/scripts/notarize.js new file mode 100644 index 00000000..be2d6d0b --- /dev/null +++ b/scripts/notarize.js @@ -0,0 +1,41 @@ +const fs = require("fs"); +const path = require("path"); +const { notarize } = require("electron-notarize"); +const envConfig = require('dotenv').config(); + +Object.entries(envConfig.parsed || {}).forEach(([key, value]) => { + process.env[key] = value; +}); + +module.exports = async function (params) { + console.log(process.env); + + // Only notarize the app on Mac OS only. + if (process.platform !== "darwin") { + return; + } + // Same appId in electron-builder. + let appId = "io.gnosis.safe.macos"; + let appPath = path.join( + params.appOutDir, + `${params.packager.appInfo.productFilename}.app` + ); + if (!fs.existsSync(appPath)) { + throw new Error(`Cannot find application at: ${appPath}`); + } + + console.log(`Notarizing ${appId} found at ${appPath}`); + + try { + await notarize({ + appBundleId: appId, + appPath: appPath, + appleId: process.env.APPLEID, + appleIdPassword: process.env.APPLEIDPASS, + }); + } catch (error) { + console.error(error); + } + + console.log(`Done notarizing ${appId}`); +}; \ No newline at end of file diff --git a/scripts/preload.js b/scripts/preload.js new file mode 100644 index 00000000..322e2fa7 --- /dev/null +++ b/scripts/preload.js @@ -0,0 +1,18 @@ +// All of the Node.js APIs are available in the preload process. +// It has the same sandbox as a Chrome extension. + +const TransportNodeHid = require("@ledgerhq/hw-transport-node-hid").default; +window.TransportNodeHid = TransportNodeHid; + +window.isDesktop = true; + +window.addEventListener('DOMContentLoaded', () => { + const replaceText = (selector, text) => { + const element = document.getElementById(selector) + if (element) element.innerText = text + } + + for (const type of ['chrome', 'node', 'electron']) { + replaceText(`${type}-version`, process.versions[type]) + } +}) \ No newline at end of file diff --git a/src/components-v2/layouts/ListContentLayout/Layout.jsx b/src/components-v2/layouts/ListContentLayout/Layout.jsx index 905a5a8d..28ad2275 100644 --- a/src/components-v2/layouts/ListContentLayout/Layout.jsx +++ b/src/components-v2/layouts/ListContentLayout/Layout.jsx @@ -4,8 +4,8 @@ import styled from 'styled-components' export const Wrapper = styled.div` display: grid; grid-template-columns: 245px auto; - grid-template-rows: 62px 500px 25px; - min-height: 500px; + grid-template-rows: 500px; + min-height: 525px; .background { box-shadow: 1px 2px 10px 0 rgba(212, 212, 211, 0.59); @@ -15,7 +15,7 @@ export const Wrapper = styled.div` export const Nav = styled.div` grid-column: 1/3; grid-row: 1; - margin: 8px 0; + margin: 0; padding: 16px 0; box-sizing: border-box; display: flex; @@ -24,23 +24,24 @@ export const Nav = styled.div` export const Menu = styled.div.attrs(() => ({ className: 'background' }))` grid-column: 1; - grid-row: 2/4; border-right: solid 2px #e8e7e6; border-top-left-radius: 8px; border-bottom-left-radius: 8px; + background-color: white; ` export const Content = styled.div.attrs(() => ({ className: 'background' }))` grid-column: 2; - grid-row: 2; border-top-right-radius: 8px; + background-color: white; ` export const Footer = styled.div.attrs(() => ({ className: 'background' }))` grid-column: 2; - grid-row: 3; + grid-row: 2; border-bottom-right-radius: 8px; display: flex; justify-content: center; align-items: center; + background-color: white; ` diff --git a/src/components/CookiesBanner/index.jsx b/src/components/CookiesBanner/index.jsx index f857685b..b8dcd88e 100644 --- a/src/components/CookiesBanner/index.jsx +++ b/src/components/CookiesBanner/index.jsx @@ -30,7 +30,7 @@ const useStyles = makeStyles({ padding: '27px 15px', position: 'fixed', width: '100%', - zIndex: '5', + zIndex: '15', }, content: { maxWidth: '100%', diff --git a/src/components/Root/index.js b/src/components/Root/index.js index 7c5dfdd4..399c541f 100644 --- a/src/components/Root/index.js +++ b/src/components/Root/index.js @@ -1,11 +1,13 @@ // @flow import 'babel-polyfill' +import { theme as styledTheme } from '@gnosis.pm/safe-react-components' import { MuiThemeProvider } from '@material-ui/core/styles' import { ConnectedRouter } from 'connected-react-router' -import React, { Suspense } from 'react' +import React from 'react' import { hot } from 'react-hot-loader/root' import { Provider } from 'react-redux' +import { ThemeProvider } from 'styled-components' import Loader from '../Loader' import PageFrame from '../layout/PageFrame' @@ -13,22 +15,21 @@ import PageFrame from '../layout/PageFrame' import AppRoutes from '~/routes' import { history, store } from '~/store' import theme from '~/theme/mui' +import { wrapInSuspense } from '~/utils/wrapInSuspense' import './index.scss' import './OnboardCustom.scss' const Root = () => ( - - - - - }> - - - - - - + + + + + {wrapInSuspense(, )} + + + + ) export default hot(Root) diff --git a/src/components/Sidebar/index.jsx b/src/components/Sidebar/index.jsx index 13c86f93..b4ccfdf8 100644 --- a/src/components/Sidebar/index.jsx +++ b/src/components/Sidebar/index.jsx @@ -1,5 +1,4 @@ // @flow -import ClickAwayListener from '@material-ui/core/ClickAwayListener' import Drawer from '@material-ui/core/Drawer' import SearchIcon from '@material-ui/icons/Search' import { List } from 'immutable' @@ -90,51 +89,49 @@ const Sidebar = ({ children, currentSafe, defaultSafe, safes, setDefaultSafeActi return ( - - - - - - } - value={filter} - /> - - - - - + + + + + } + value={filter} + /> - - - - + + + + + + + + {children} ) diff --git a/src/components/forms/AddressInput/index.jsx b/src/components/forms/AddressInput/index.jsx index e371de9a..b947cc67 100644 --- a/src/components/forms/AddressInput/index.jsx +++ b/src/components/forms/AddressInput/index.jsx @@ -63,36 +63,6 @@ const AddressInput = ({ } }} - {/* onBlur - didn't work because of the complex validation - (if you submit before it gets the address, breaks everything) */} - {/* { - const [prevActive, setPrevActive] = useState(!!meta.active) - - useEffect(() => { - async function setAddressFromENS() { - if (isValidEnsName(input.value)) { - try { - const resolverAddr = await getAddressFromENS(input.value) - fieldMutator(resolverAddr) - } catch (err) { - console.error('Error when trying to fetch address for ENS name: ', err) - } - } - } - - if (prevActive && !meta.active) { - setAddressFromENS() - } else if (prevActive !== meta.active) { - setPrevActive(meta.active) - } - }, [meta.active]) - - return null - }} - /> */} ) diff --git a/src/components/forms/Field/DebounceValidationField.js b/src/components/forms/Field/DebounceValidationField.js new file mode 100644 index 00000000..325946f5 --- /dev/null +++ b/src/components/forms/Field/DebounceValidationField.js @@ -0,0 +1,36 @@ +// @flow + +// source: https://github.com/final-form/react-final-form/issues/369#issuecomment-439823584 + +import React from 'react' +import { Field } from 'react-final-form' + +type Props = { + validate: () => void, + debounce: number, +} + +const DebounceValidationField = ({ debounce = 1000, validate, ...rest }: Props) => { + let clearTimeout + + const localValidation = (value, values, fieldState) => { + if (fieldState.active) { + return new Promise((resolve) => { + if (clearTimeout) clearTimeout() + const timerId = setTimeout(() => { + resolve(validate(value, values, fieldState)) + }, debounce) + clearTimeout = () => { + clearTimeout(timerId) + resolve() + } + }) + } else { + return validate(value, values, fieldState) + } + } + + return +} + +export default DebounceValidationField diff --git a/src/components/layout/Page/index.scss b/src/components/layout/Page/index.scss index d33b145f..7a7dfdf4 100644 --- a/src/components/layout/Page/index.scss +++ b/src/components/layout/Page/index.scss @@ -2,12 +2,12 @@ display: flex; flex: 1 0 auto; flex-direction: column; - padding: 135px 200px 0px 200px; + padding: 96px 200px 0px 200px; } @media only screen and (max-width: $(screenLg)px) { .page { - padding: 135px $lg 0px $lg; + padding: 72px $lg 0px $lg; } } diff --git a/src/config/index.js b/src/config/index.js index 24729b2e..f8b1e7c5 100644 --- a/src/config/index.js +++ b/src/config/index.js @@ -56,7 +56,7 @@ export const getTxServiceUriFrom = (safeAddress: string) => `safes/${safeAddress}/transactions/` export const getIncomingTxServiceUriTo = (safeAddress: string) => - `safes/${safeAddress}/incoming-transactions/` + `safes/${safeAddress}/incoming-transfers/` export const getRelayUrl = () => getConfig()[RELAY_API_URL] diff --git a/src/logic/addressBook/store/selectors/index.js b/src/logic/addressBook/store/selectors/index.js index edef7837..36c73f6b 100644 --- a/src/logic/addressBook/store/selectors/index.js +++ b/src/logic/addressBook/store/selectors/index.js @@ -1,7 +1,6 @@ /* eslint-disable import/named */ // @flow import { List, Map } from 'immutable' -import { useSelector } from 'react-redux' import { Selector, createSelector } from 'reselect' import type { AddressBook } from '~/logic/addressBook/model/addressBook' @@ -35,15 +34,3 @@ export const getAddressBookListSelector: Selector { - if (!userAddress) { - return null - } - const addressBook = useSelector(getAddressBook) - const result = addressBook.filter((addressBookItem) => addressBookItem.address === userAddress) - if (result.size > 0) { - return result.get(0).name - } - return null -} diff --git a/src/logic/addressBook/utils/index.js b/src/logic/addressBook/utils/index.js index 52d98617..cfd3b864 100644 --- a/src/logic/addressBook/utils/index.js +++ b/src/logic/addressBook/utils/index.js @@ -38,7 +38,7 @@ export const getNameFromAddressBook = (userAddress: string): string | null => { return null } const addressBook = useSelector(getAddressBook) - return getNameFromAdbk(addressBook, userAddress) + return addressBook ? getNameFromAdbk(addressBook, userAddress) : null } export const getOwnersWithNameFromAddressBook = (addressBook: AddressBook, ownerList: List) => { diff --git a/src/logic/collectibles/store/actions/fetchCollectibles.js b/src/logic/collectibles/store/actions/fetchCollectibles.js index 0ed61a56..7e326bec 100644 --- a/src/logic/collectibles/store/actions/fetchCollectibles.js +++ b/src/logic/collectibles/store/actions/fetchCollectibles.js @@ -1,4 +1,5 @@ // @flow +import { batch } from 'react-redux' import type { Dispatch } from 'redux' import { getNetwork } from '~/config' @@ -13,8 +14,10 @@ const fetchCollectibles = () => async (dispatch: Dispatch, getState const source = getConfiguredSource() const collectibles = await source.fetchAllUserCollectiblesByCategoryAsync(safeAddress, network) - dispatch(addNftAssets(collectibles.nftAssets)) - dispatch(addNftTokens(collectibles.nftTokens)) + batch(() => { + dispatch(addNftAssets(collectibles.nftAssets)) + dispatch(addNftTokens(collectibles.nftTokens)) + }) } export default fetchCollectibles diff --git a/src/logic/contracts/generateBatchRequests.js b/src/logic/contracts/generateBatchRequests.js new file mode 100644 index 00000000..6a0d31b8 --- /dev/null +++ b/src/logic/contracts/generateBatchRequests.js @@ -0,0 +1,58 @@ +// @flow +import { getWeb3 } from '~/logic/wallets/getWeb3' + +/** + * Generates a batch request for grouping RPC calls + * @param {object} args + * @param {object} args.abi - contract ABI + * @param {string} args.address - contract address + * @param {object|undefined} args.batch - not required. If set, batch must be initialized outside (web3.BatchRequest) + * @param {object|undefined} args.context - not required. Can be any object, to be added to the batch response + * @param {array<{ args: [any], method: string, type: 'eth'|undefined } | string>} args.methods - methods to be called + * @returns {Promise<[*]>} + */ +const generateBatchRequests = ({ abi, address, batch, context, methods }) => { + const web3 = getWeb3() + const contractInstance = new web3.eth.Contract(abi, address) + const localBatch = batch ? null : new web3.BatchRequest() + + const values = methods.map((methodObject) => { + let method, type, args = [] + + if (typeof methodObject === 'string') { + method = methodObject + } else { + ;({ method, type, args = [] } = methodObject) + } + + return new Promise((resolve) => { + const resolver = (error, result) => { + if (error) { + resolve(null) + } else { + resolve(result) + } + } + + try { + let request + if (type !== undefined) { + request = web3[type][method].request(...args, resolver) + } else { + request = contractInstance.methods[method](...args).call.request(resolver) + } + batch ? batch.add(request) : localBatch.add(request) + } catch (e) { + resolve(null) + } + }) + }) + + localBatch && localBatch.execute() + + const returnValues = context ? [context, ...values] : values + + return Promise.all(returnValues) +} + +export default generateBatchRequests diff --git a/src/logic/contracts/methodIds.js b/src/logic/contracts/methodIds.js index a946cf38..1f8d6eab 100644 --- a/src/logic/contracts/methodIds.js +++ b/src/logic/contracts/methodIds.js @@ -53,8 +53,8 @@ const METHOD_TO_ID = { '0x694e80c3': SAFE_METHODS_NAMES.CHANGE_THRESHOLD, } -export const decodeParamsFromSafeMethod = async (data: string) => { - const web3 = await getWeb3() +export const decodeParamsFromSafeMethod = (data: string) => { + const web3 = getWeb3() const [methodId, params] = [data.slice(0, 10), data.slice(10)] switch (methodId) { diff --git a/src/logic/contracts/safeContracts.js b/src/logic/contracts/safeContracts.js index f5d85586..7e53953c 100644 --- a/src/logic/contracts/safeContracts.js +++ b/src/logic/contracts/safeContracts.js @@ -3,7 +3,7 @@ import contract from 'truffle-contract' import ProxyFactorySol from '@gnosis.pm/safe-contracts/build/contracts/GnosisSafeProxyFactory.json' import GnosisSafeSol from '@gnosis.pm/safe-contracts/build/contracts/GnosisSafe.json' import SafeProxy from '@gnosis.pm/safe-contracts/build/contracts/GnosisSafeProxy.json' -import { ensureOnce } from '~/utils/singleton' +import { ensureOnce, ensureOnceAsync } from '~/utils/singleton' import { simpleMemoize } from '~/components/forms/validator' import { getWeb3, getNetworkIdFrom } from '~/logic/wallets/getWeb3' import { calculateGasOf, calculateGasPrice } from '~/logic/wallets/ethTransactions' @@ -83,7 +83,6 @@ 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() @@ -96,13 +95,12 @@ export const estimateGasForDeployingSafe = async ( return gas * parseInt(gasPrice, 10) } -export const getGnosisSafeInstanceAt = async (safeAddress: string) => { +export const getGnosisSafeInstanceAt = simpleMemoize(async (safeAddress: string) => { const web3 = getWeb3() const GnosisSafe = await getGnosisSafeContract(web3) const gnosisSafe = await GnosisSafe.at(safeAddress) - return gnosisSafe -} +}) const cleanByteCodeMetadata = (bytecode: string): string => { const metaData = 'a165' diff --git a/src/logic/currencyValues/api/fetchTokenCurrenciesBalances.js b/src/logic/currencyValues/api/fetchTokenCurrenciesBalances.js index b3c15e0b..7fa21013 100644 --- a/src/logic/currencyValues/api/fetchTokenCurrenciesBalances.js +++ b/src/logic/currencyValues/api/fetchTokenCurrenciesBalances.js @@ -10,7 +10,11 @@ const fetchTokenCurrenciesBalances = (safeAddress: string) => { const apiUrl = getTxServiceHost() const url = `${apiUrl}safes/${safeAddress}/balances/usd/` - return axios.get(url) + return axios.get(url, { + params: { + limit: 3000, + }, + }) } export default fetchTokenCurrenciesBalances diff --git a/src/logic/currencyValues/store/actions/fetchCurrencySelectedValue.js b/src/logic/currencyValues/store/actions/fetchCurrencySelectedValue.js index 9dd73823..c4129f9a 100644 --- a/src/logic/currencyValues/store/actions/fetchCurrencySelectedValue.js +++ b/src/logic/currencyValues/store/actions/fetchCurrencySelectedValue.js @@ -1,37 +1,21 @@ // @flow -import { List } from 'immutable' import { Dispatch as ReduxDispatch } from 'redux' import fetchCurrenciesRates from '~/logic/currencyValues/api/fetchCurrenciesRates' -import { setCurrencyBalances } from '~/logic/currencyValues/store/actions/setCurrencyBalances' +import { setCurrencyRate } from '~/logic/currencyValues/store/actions/setCurrencyRate' import { AVAILABLE_CURRENCIES } from '~/logic/currencyValues/store/model/currencyValues' -import { currencyValuesListSelector } from '~/logic/currencyValues/store/selectors' import type { GlobalState } from '~/store' // eslint-disable-next-line max-len -const fetchCurrencySelectedValue = (currencyValueSelected: AVAILABLE_CURRENCIES) => async ( +const fetchCurrencySelectedValue = (currencyValueSelected: $Keys) => async ( dispatch: ReduxDispatch, - getState: Function, ) => { - const state = getState() - const currencyBalancesList = currencyValuesListSelector(state) - const selectedCurrencyRateInBaseCurrency = await fetchCurrenciesRates(AVAILABLE_CURRENCIES.USD, currencyValueSelected) - - const newList = [] - for (const currencyValue of currencyBalancesList) { - const { balanceInBaseCurrency } = currencyValue - - const balanceInSelectedCurrency = balanceInBaseCurrency * selectedCurrencyRateInBaseCurrency - - const updatedValue = currencyValue.merge({ - currencyName: currencyValueSelected, - balanceInSelectedCurrency, - }) - - newList.push(updatedValue) + if (AVAILABLE_CURRENCIES.USD === currencyValueSelected) { + return dispatch(setCurrencyRate('1')) } - dispatch(setCurrencyBalances(List(newList))) + const selectedCurrencyRateInBaseCurrency = await fetchCurrenciesRates(AVAILABLE_CURRENCIES.USD, currencyValueSelected) + dispatch(setCurrencyRate(selectedCurrencyRateInBaseCurrency)) } export default fetchCurrencySelectedValue diff --git a/src/logic/currencyValues/store/actions/fetchCurrencyValues.js b/src/logic/currencyValues/store/actions/fetchCurrencyValues.js index 8ad14f95..d71b18c0 100644 --- a/src/logic/currencyValues/store/actions/fetchCurrencyValues.js +++ b/src/logic/currencyValues/store/actions/fetchCurrencyValues.js @@ -1,43 +1,32 @@ // @flow -import { List } from 'immutable' +import { batch } from 'react-redux' import type { Dispatch as ReduxDispatch } from 'redux' -import fetchTokenCurrenciesBalances from '~/logic/currencyValues/api/fetchTokenCurrenciesBalances' import fetchCurrencySelectedValue from '~/logic/currencyValues/store/actions/fetchCurrencySelectedValue' import { CURRENCY_SELECTED_KEY } from '~/logic/currencyValues/store/actions/saveCurrencySelected' -import { setCurrencyBalances } from '~/logic/currencyValues/store/actions/setCurrencyBalances' +import { setCurrencyRate } from '~/logic/currencyValues/store/actions/setCurrencyRate' import { setCurrencySelected } from '~/logic/currencyValues/store/actions/setCurrencySelected' -import { AVAILABLE_CURRENCIES, makeBalanceCurrency } from '~/logic/currencyValues/store/model/currencyValues' +import { AVAILABLE_CURRENCIES } from '~/logic/currencyValues/store/model/currencyValues' import type { GlobalState } from '~/store' import { loadFromStorage } from '~/utils/storage' -export const fetchCurrencyValues = (safeAddress: string) => async (dispatch: ReduxDispatch) => { +export const fetchCurrencyValues = () => async (dispatch: ReduxDispatch) => { try { - const tokensFetched = await fetchTokenCurrenciesBalances(safeAddress) - - // eslint-disable-next-line max-len - const currencyList = List( - tokensFetched.data - .filter((currencyBalance) => currencyBalance.balanceUsd) - .map((currencyBalance) => { - const { balanceUsd, tokenAddress } = currencyBalance - return makeBalanceCurrency({ - currencyName: balanceUsd ? AVAILABLE_CURRENCIES.USD : null, - tokenAddress, - balanceInBaseCurrency: balanceUsd, - balanceInSelectedCurrency: balanceUsd, - }) - }), - ) - - dispatch(setCurrencyBalances(currencyList)) const currencyStored = await loadFromStorage(CURRENCY_SELECTED_KEY) + if (!currencyStored) { - return dispatch(setCurrencySelected(AVAILABLE_CURRENCIES.USD)) + return batch(() => { + dispatch(setCurrencySelected(AVAILABLE_CURRENCIES.USD)) + dispatch(setCurrencyRate(1)) + }) } + const { currencyValueSelected } = currencyStored - dispatch(fetchCurrencySelectedValue(currencyValueSelected)) - dispatch(setCurrencySelected(currencyValueSelected)) + + batch(() => { + dispatch(setCurrencySelected(currencyValueSelected)) + dispatch(fetchCurrencySelectedValue(currencyValueSelected)) + }) } catch (err) { console.error('Error fetching tokens price list', err) } diff --git a/src/logic/currencyValues/store/actions/setCurrencyRate.js b/src/logic/currencyValues/store/actions/setCurrencyRate.js new file mode 100644 index 00000000..c0cee64c --- /dev/null +++ b/src/logic/currencyValues/store/actions/setCurrencyRate.js @@ -0,0 +1,12 @@ +// @flow +import { createAction } from 'redux-actions' + +import type { CurrencyValuesProps } from '~/logic/currencyValues/store/model/currencyValues' + +export const SET_CURRENCY_RATE = 'SET_CURRENCY_RATE' + +// eslint-disable-next-line max-len +export const setCurrencyRate = createAction( + SET_CURRENCY_RATE, + (currencyRate: string): CurrencyValuesProps => ({ currencyRate }), +) diff --git a/src/logic/currencyValues/store/actions/setCurrencySelected.js b/src/logic/currencyValues/store/actions/setCurrencySelected.js index f8426f34..be0f1c2b 100644 --- a/src/logic/currencyValues/store/actions/setCurrencySelected.js +++ b/src/logic/currencyValues/store/actions/setCurrencySelected.js @@ -9,5 +9,5 @@ export const SET_CURRENT_CURRENCY = 'SET_CURRENT_CURRENCY' // eslint-disable-next-line max-len export const setCurrencySelected = createAction( SET_CURRENT_CURRENCY, - (currencyValueSelected: AVAILABLE_CURRENCIES): CurrencyValuesProps => ({ currencyValueSelected }), + (currencyValueSelected: $Keys): CurrencyValuesProps => ({ currencyValueSelected }), ) diff --git a/src/logic/currencyValues/store/model/currencyValues.js b/src/logic/currencyValues/store/model/currencyValues.js index a2d07581..f9d813a9 100644 --- a/src/logic/currencyValues/store/model/currencyValues.js +++ b/src/logic/currencyValues/store/model/currencyValues.js @@ -39,7 +39,7 @@ export const AVAILABLE_CURRENCIES = { } export type BalanceCurrencyType = { - currencyName: AVAILABLE_CURRENCIES, + currencyName: $Keys, tokenAddress: string, balanceInBaseCurrency: string, balanceInSelectedCurrency: string, @@ -53,7 +53,8 @@ export const makeBalanceCurrency = Record({ }) export type CurrencyValuesProps = { - currencyValueSelected: AVAILABLE_CURRENCIES, + currencyValueSelected: $Keys, + currencyRate: string, currencyValuesList: BalanceCurrencyType[], } diff --git a/src/logic/currencyValues/store/reducer/currencyValues.js b/src/logic/currencyValues/store/reducer/currencyValues.js index 8d24aff6..2d690fcd 100644 --- a/src/logic/currencyValues/store/reducer/currencyValues.js +++ b/src/logic/currencyValues/store/reducer/currencyValues.js @@ -2,8 +2,8 @@ import { Map } from 'immutable' import { type ActionType, handleActions } from 'redux-actions' -import { SET_CURRENCY_BALANCES } from '../actions/setCurrencyBalances' - +import { SET_CURRENCY_BALANCES } from '~/logic/currencyValues/store/actions/setCurrencyBalances' +import { SET_CURRENCY_RATE } from '~/logic/currencyValues/store/actions/setCurrencyRate' import { SET_CURRENT_CURRENCY } from '~/logic/currencyValues/store/actions/setCurrencySelected' import type { State } from '~/logic/tokens/store/reducer/tokens' @@ -11,19 +11,20 @@ export const CURRENCY_VALUES_KEY = 'currencyValues' export default handleActions( { + [SET_CURRENCY_RATE]: (state: State, action: ActionType): State => { + const { currencyRate } = action.payload + + return state.set('currencyRate', currencyRate) + }, [SET_CURRENCY_BALANCES]: (state: State, action: ActionType): State => { const { currencyBalances } = action.payload - const newState = state.set('currencyBalances', currencyBalances) - - return newState + return state.set('currencyBalances', currencyBalances) }, [SET_CURRENT_CURRENCY]: (state: State, action: ActionType): State => { const { currencyValueSelected } = action.payload - const newState = state.set('currencyValueSelected', currencyValueSelected) - - return newState + return state.set('currencyValueSelected', currencyValueSelected) }, }, Map(), diff --git a/src/logic/currencyValues/store/selectors/index.js b/src/logic/currencyValues/store/selectors/index.js index 35d4c3f1..429bfef5 100644 --- a/src/logic/currencyValues/store/selectors/index.js +++ b/src/logic/currencyValues/store/selectors/index.js @@ -7,4 +7,7 @@ import { type GlobalState } from '~/store' export const currencyValuesListSelector = (state: GlobalState) => state[CURRENCY_VALUES_KEY].get('currencyBalances') ? state[CURRENCY_VALUES_KEY].get('currencyBalances') : List([]) + export const currentCurrencySelector = (state: GlobalState) => state[CURRENCY_VALUES_KEY].get('currencyValueSelected') + +export const currencyRateSelector = (state: GlobalState) => state[CURRENCY_VALUES_KEY].get('currencyRate') diff --git a/src/logic/safe/transactions/gas.js b/src/logic/safe/transactions/gas.js index 15d3aca4..6f5b16d4 100644 --- a/src/logic/safe/transactions/gas.js +++ b/src/logic/safe/transactions/gas.js @@ -1,92 +1,5 @@ // @flow -import { BigNumber } from 'bignumber.js' - import { getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts' -import { EMPTY_DATA } from '~/logic/wallets/ethTransactions' -import { getWeb3 } from '~/logic/wallets/getWeb3' - -const estimateDataGasCosts = (data) => { - const reducer = (accumulator, currentValue) => { - if (currentValue === EMPTY_DATA) { - return accumulator + 0 - } - - if (currentValue === '00') { - return accumulator + 4 - } - - return accumulator + 68 - } - - return data.match(/.{2}/g).reduce(reducer, 0) -} - -// https://docs.gnosis.io/safe/docs/docs4/#safe-transaction-data-gas-estimation -// https://github.com/gnosis/safe-contracts/blob/a97c6fd24f79c0b159ddd25a10a2ebd3ea2ef926/test/utils/execution.js -export const estimateDataGas = ( - safe: any, - to: string, - valueInWei: number, - from: string, - data: string, - operation: number, - txGasEstimate: number, - gasToken: number, - nonce: number, - signatureCount: number, - refundReceiver: number, -) => { - // numbers < 256 are 192 -> 31 * 4 + 68 - // numbers < 65k are 256 -> 30 * 4 + 2 * 68 - // For signature array length and dataGasEstimate we already calculated - // the 0 bytes so we just add 64 for each non-zero byte - const gasPrice = 0 // no need to get refund when we submit txs to metamask - const signatureCost = signatureCount * (68 + 2176 + 2176 + 6000) // array count (3 -> r, s, v) * signature count - - // https://docs.gnosis.io/safe/docs/docs5/#pre-validated-signatures - const sigs = `0x000000000000000000000000${from.replace( - '0x', - '', - )}000000000000000000000000000000000000000000000000000000000000000001` - const payload = safe.contract.methods - .execTransaction(to, valueInWei, data, operation, txGasEstimate, 0, gasPrice, gasToken, refundReceiver, sigs) - .encodeABI() - - // eslint-disable-next-line - const dataGasEstimate = estimateDataGasCosts(payload) + signatureCost + (nonce > 0 ? 5000 : 20000) + 1500 // 1500 -> hash generation costs - - return dataGasEstimate + 32000 // Add aditional gas costs (e.g. base tx costs, transfer costs) -} - -export const generateTxGasEstimateFrom = async ( - safe: any, - safeAddress: string, - data: string, - to: string, - valueInWei: number, - operation: number, -) => { - try { - let safeInstance = safe - if (!safeInstance) { - safeInstance = await getGnosisSafeInstanceAt(safeAddress) - } - - const estimateData = safeInstance.contract.methods.requiredTxGas(to, valueInWei, data, operation).encodeABI() - const estimateResponse = await getWeb3().eth.call({ - to: safeAddress, - from: safeAddress, - data: estimateData, - }) - const txGasEstimate = new BigNumber(estimateResponse.substring(138), 16) - - // Add 10k else we will fail in case of nested calls - return txGasEstimate.toNumber() + 10000 - } catch (error) { - console.error('Error calculating tx gas estimation', error) - return 0 - } -} export const calculateTxFee = async ( safe: any, diff --git a/src/logic/safe/transactions/gasNew.js b/src/logic/safe/transactions/gasNew.js index c515d7df..15c33c17 100644 --- a/src/logic/safe/transactions/gasNew.js +++ b/src/logic/safe/transactions/gasNew.js @@ -1,14 +1,32 @@ // @flow import GnosisSafeSol from '@gnosis.pm/safe-contracts/build/contracts/GnosisSafe.json' +import { BigNumber } from 'bignumber.js' import { CALL } from '.' +import { getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts' import { generateSignaturesFromTxConfirmations } from '~/logic/safe/safeTxSigner' import { ZERO_ADDRESS } from '~/logic/wallets/ethAddresses' -import { calculateGasOf, calculateGasPrice } from '~/logic/wallets/ethTransactions' +import { EMPTY_DATA, calculateGasOf, calculateGasPrice } from '~/logic/wallets/ethTransactions' import { getAccountFrom, getWeb3 } from '~/logic/wallets/getWeb3' import { type Transaction } from '~/routes/safe/store/models/transaction' +const estimateDataGasCosts = (data) => { + const reducer = (accumulator, currentValue) => { + if (currentValue === EMPTY_DATA) { + return accumulator + 0 + } + + if (currentValue === '00') { + return accumulator + 4 + } + + return accumulator + 16 + } + + return data.match(/.{2}/g).reduce(reducer, 0) +} + export const estimateTxGasCosts = async ( safeAddress: string, to: string, @@ -58,3 +76,70 @@ export const estimateTxGasCosts = async ( return 10000 } } + +export const estimateSafeTxGas = async ( + safe: any, + safeAddress: string, + data: string, + to: string, + valueInWei: number | string, + operation: number, +) => { + try { + let safeInstance = safe + if (!safeInstance) { + safeInstance = await getGnosisSafeInstanceAt(safeAddress) + } + + const web3 = await getWeb3() + const estimateData = safeInstance.contract.methods.requiredTxGas(to, valueInWei, data, operation).encodeABI() + const estimateResponse = await web3.eth.call({ + to: safeAddress, + from: safeAddress, + data: estimateData, + }) + const txGasEstimation = new BigNumber(estimateResponse.substring(138), 16).toNumber() + 10000 + + // 21000 - additional gas costs (e.g. base tx costs, transfer costs) + const dataGasEstimation = estimateDataGasCosts(estimateData) + 21000 + + const additionalGasBatches = [10000, 20000, 40000, 80000, 160000, 320000, 640000, 1280000, 2560000, 5120000] + + const batch = new web3.BatchRequest() + const estimationRequests = additionalGasBatches.map( + (additionalGas) => + new Promise((resolve) => { + const request = web3.eth.call.request( + { + to: safe.address, + from: safe.address, + data: estimateData, + gasPrice: 0, + gasLimit: txGasEstimation + dataGasEstimation + additionalGas, + }, + (error, res) => { + resolve({ + success: error || res === '0x' ? false : true, + estimation: txGasEstimation + additionalGas, + }) + }, + ) + + batch.add(request) + }), + ) + batch.execute() + + const estimationResponses = await Promise.all(estimationRequests) + const firstSuccessfulRequest = estimationResponses.find((res) => res.success) + + if (firstSuccessfulRequest) { + return firstSuccessfulRequest.estimation + } + + return 0 + } catch (error) { + console.error('Error calculating tx gas estimation', error) + return 0 + } +} diff --git a/src/logic/tokens/store/actions/activateAssetsByBalance.js b/src/logic/tokens/store/actions/activateAssetsByBalance.js index 3cffa977..61811460 100644 --- a/src/logic/tokens/store/actions/activateAssetsByBalance.js +++ b/src/logic/tokens/store/actions/activateAssetsByBalance.js @@ -17,9 +17,14 @@ const activateAssetsByBalance = (safeAddress: string) => async ( getState: GetState, ) => { try { - await dispatch(fetchCollectibles()) const state = getState() const safes = safesMapSelector(state) + + if (safes.size === 0) { + return + } + + await dispatch(fetchCollectibles()) const availableAssets = nftAssetsSelector(state) const alreadyActiveAssets = safeActiveAssetsSelectorBySafe(safeAddress, safes) const blacklistedAssets = safeBlacklistedAssetsSelectorBySafe(safeAddress, safes) diff --git a/src/logic/tokens/store/actions/activateTokensByBalance.js b/src/logic/tokens/store/actions/activateTokensByBalance.js deleted file mode 100644 index da377195..00000000 --- a/src/logic/tokens/store/actions/activateTokensByBalance.js +++ /dev/null @@ -1,61 +0,0 @@ -// @flow -import { Set } from 'immutable' -import type { Dispatch as ReduxDispatch } from 'redux' - -import fetchTokenBalanceList from '~/logic/tokens/api/fetchTokenBalanceList' -import updateActiveTokens from '~/routes/safe/store/actions/updateActiveTokens' -import updateSafe from '~/routes/safe/store/actions/updateSafe' -import { - safeActiveTokensSelectorBySafe, - safeBlacklistedTokensSelectorBySafe, - safesMapSelector, -} from '~/routes/safe/store/selectors' -import { type GetState, type GlobalState } from '~/store' - -const activateTokensByBalance = (safeAddress: string) => async ( - dispatch: ReduxDispatch, - getState: GetState, -) => { - try { - const result = await fetchTokenBalanceList(safeAddress) - const safes = safesMapSelector(getState()) - const alreadyActiveTokens = safeActiveTokensSelectorBySafe(safeAddress, safes) - const blacklistedTokens = safeBlacklistedTokensSelectorBySafe(safeAddress, safes) - - // addresses: potentially active tokens by balance - // balances: tokens' balance returned by the backend - const { addresses, balances } = result.data.reduce( - (acc, { balance, tokenAddress }) => ({ - addresses: [...acc.addresses, tokenAddress], - balances: [[tokenAddress, balance]], - }), - { - addresses: [], - balances: [], - }, - ) - - // update balance list for the safe - dispatch( - updateSafe({ - address: safeAddress, - balances: Set(balances), - }), - ) - - // active tokens by balance, excluding those already blacklisted and the `null` 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) - - // update list of active tokens - dispatch(updateActiveTokens(safeAddress, activeTokens)) - } catch (err) { - console.error('Error fetching active token list', err) - } - - return null -} - -export default activateTokensByBalance diff --git a/src/logic/tokens/store/actions/fetchSafeTokens.js b/src/logic/tokens/store/actions/fetchSafeTokens.js new file mode 100644 index 00000000..276a9ae2 --- /dev/null +++ b/src/logic/tokens/store/actions/fetchSafeTokens.js @@ -0,0 +1,100 @@ +// @flow +import { BigNumber } from 'bignumber.js' +import { List, Map } from 'immutable' +import { batch } from 'react-redux' +import type { Dispatch as ReduxDispatch } from 'redux' + +import fetchTokenCurrenciesBalances from '~/logic/currencyValues/api/fetchTokenCurrenciesBalances' +import { setCurrencyBalances } from '~/logic/currencyValues/store/actions/setCurrencyBalances' +import { AVAILABLE_CURRENCIES, makeBalanceCurrency } from '~/logic/currencyValues/store/model/currencyValues' +import { CURRENCY_VALUES_KEY } from '~/logic/currencyValues/store/reducer/currencyValues' +import addTokens from '~/logic/tokens/store/actions/saveTokens' +import { makeToken } from '~/logic/tokens/store/model/token' +import { TOKEN_REDUCER_ID } from '~/logic/tokens/store/reducer/tokens' +import updateSafe from '~/routes/safe/store/actions/updateSafe' +import { SAFE_REDUCER_ID } from '~/routes/safe/store/reducer/safe' +import { type GetState, type GlobalState } from '~/store' + +const humanReadableBalance = (balance, decimals) => BigNumber(balance).times(`1e-${decimals}`).toFixed() +const noFunc = () => {} +const updateSafeValue = (address) => (valueToUpdate) => updateSafe({ address, ...valueToUpdate }) + +const fetchSafeTokens = (safeAddress: string) => async (dispatch: ReduxDispatch, getState: GetState) => { + try { + const state = getState() + const safe = state[SAFE_REDUCER_ID].getIn([SAFE_REDUCER_ID, safeAddress]) + const currentTokens = state[TOKEN_REDUCER_ID] + + if (!safe) { + return + } + + const result = await fetchTokenCurrenciesBalances(safeAddress) + const currentEthBalance = safe.get('ethBalance') + const safeBalances = safe.get('balances') + const alreadyActiveTokens = safe.get('activeTokens') + const blacklistedTokens = safe.get('blacklistedTokens') + const currencyValues = state[CURRENCY_VALUES_KEY] + const storedCurrencyBalances = currencyValues.get('currencyBalances') + + const { balances, currencyList, ethBalance, tokens } = result.data.reduce( + (acc, { balance, balanceUsd, token, tokenAddress }) => { + if (tokenAddress === null) { + acc.ethBalance = humanReadableBalance(balance, 18) + } else { + acc.balances = acc.balances.merge({ [tokenAddress]: humanReadableBalance(balance, token.decimals) }) + + if (currentTokens && !currentTokens.get(tokenAddress)) { + acc.tokens = acc.tokens.push(makeToken({ address: tokenAddress, ...token })) + } + } + + acc.currencyList = acc.currencyList.push( + makeBalanceCurrency({ + currencyName: balanceUsd ? AVAILABLE_CURRENCIES.USD : null, + tokenAddress, + balanceInBaseCurrency: balanceUsd, + balanceInSelectedCurrency: balanceUsd, + }), + ) + + return acc + }, + { + balances: Map(), + currencyList: List(), + ethBalance: '0', + tokens: List(), + }, + ) + + // need to persist those already active tokens, despite its balances + const activeTokens = alreadyActiveTokens.toSet().union( + // active tokens by balance, excluding those already blacklisted and the `null` address + balances.keySeq().toSet().subtract(blacklistedTokens), + ) + + const update = updateSafeValue(safeAddress) + const updateActiveTokens = activeTokens.equals(alreadyActiveTokens) ? noFunc : update({ activeTokens }) + const updateBalances = balances.equals(safeBalances) ? noFunc : update({ balances }) + const updateEthBalance = ethBalance === currentEthBalance ? noFunc : update({ ethBalance }) + + const updateCurrencies = currencyList.equals(storedCurrencyBalances) ? noFunc : setCurrencyBalances(currencyList) + + const updateTokens = tokens.size === 0 ? noFunc : addTokens(tokens) + + batch(() => { + dispatch(updateActiveTokens) + dispatch(updateBalances) + dispatch(updateEthBalance) + dispatch(updateCurrencies) + dispatch(updateTokens) + }) + } catch (err) { + console.error('Error fetching active token list', err) + } + + return null +} + +export default fetchSafeTokens diff --git a/src/logic/tokens/store/actions/fetchTokens.js b/src/logic/tokens/store/actions/fetchTokens.js index fdff81a6..1971bb0f 100644 --- a/src/logic/tokens/store/actions/fetchTokens.js +++ b/src/logic/tokens/store/actions/fetchTokens.js @@ -38,7 +38,10 @@ const createERC721TokenContract = async () => { return erc721Token } -const OnlyBalanceToken = { +// 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. +export const OnlyBalanceToken = { contractName: 'OnlyBalanceToken', abi: [ { @@ -82,23 +85,12 @@ const OnlyBalanceToken = { ], } -// 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) diff --git a/src/logic/tokens/utils/alternativeAbi.js b/src/logic/tokens/utils/alternativeAbi.js index c6a8abfb..074ff62c 100644 --- a/src/logic/tokens/utils/alternativeAbi.js +++ b/src/logic/tokens/utils/alternativeAbi.js @@ -23,7 +23,7 @@ export const ALTERNATIVE_TOKEN_ABI = [ outputs: [ { name: '', - type: 'bytes32', + type: 'string', }, ], payable: false, diff --git a/src/routes/index.js b/src/routes/index.js index 46e78d99..2e274dcf 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -1,30 +1,32 @@ // @flow import React, { useEffect, useState } from 'react' -import { connect } from 'react-redux' +import { useSelector } from 'react-redux' import { Redirect, Route, Switch, withRouter } from 'react-router-dom' import { LOAD_ADDRESS, OPEN_ADDRESS, SAFELIST_ADDRESS, SAFE_PARAM_ADDRESS, WELCOME_ADDRESS } from './routes' -import Welcome from './welcome/container' import Loader from '~/components/Loader' import { defaultSafeSelector } from '~/routes/safe/store/selectors' -import { withTracker } from '~/utils/googleAnalytics' +import { useAnalytics } from '~/utils/googleAnalytics' -const Safe = React.lazy(() => import('./safe/container')) +const Welcome = React.lazy(() => import('./welcome/container')) const Open = React.lazy(() => import('./open/container/Open')) +const Safe = React.lazy(() => import('./safe/container')) + const Load = React.lazy(() => import('./load/container/Load')) const SAFE_ADDRESS = `${SAFELIST_ADDRESS}/:${SAFE_PARAM_ADDRESS}` type RoutesProps = { - defaultSafe?: string, location: Object, } -const Routes = ({ defaultSafe, location }: RoutesProps) => { +const Routes = ({ location }: RoutesProps) => { const [isInitialLoad, setInitialLoad] = useState(true) + const defaultSafe = useSelector(defaultSafeSelector) + const { trackPage } = useAnalytics() useEffect(() => { if (location.pathname !== '/') { @@ -32,6 +34,11 @@ const Routes = ({ defaultSafe, location }: RoutesProps) => { } }, []) + useEffect(() => { + const page = location.pathname + location.search + trackPage(page) + }, [location.pathname, trackPage]) + return ( { return } - setInitialLoad(false) if (defaultSafe) { return } @@ -54,17 +60,13 @@ const Routes = ({ defaultSafe, location }: RoutesProps) => { return }} /> - - - - + + + + ) } -// $FlowFixMe -export default connect( - (state) => ({ defaultSafe: defaultSafeSelector(state) }), - null, -)(withRouter(Routes)) +export default withRouter(Routes) diff --git a/src/routes/load/components/DetailsForm/index.jsx b/src/routes/load/components/DetailsForm/index.jsx index 1d005ca8..266f131e 100644 --- a/src/routes/load/components/DetailsForm/index.jsx +++ b/src/routes/load/components/DetailsForm/index.jsx @@ -8,7 +8,7 @@ import OpenPaper from '~/components/Stepper/OpenPaper' import AddressInput from '~/components/forms/AddressInput' import Field from '~/components/forms/Field' import TextField from '~/components/forms/TextField' -import { composeValidators, mustBeEthereumAddress, noErrorsOn, required } from '~/components/forms/validator' +import { mustBeEthereumAddress, noErrorsOn, required } from '~/components/forms/validator' import Block from '~/components/layout/Block' import Paragraph from '~/components/layout/Paragraph' import { SAFE_MASTER_COPY_ADDRESS_V10, getSafeMasterContract, validateProxy } from '~/logic/contracts/safeContracts' @@ -120,7 +120,6 @@ const Details = ({ classes, errors, form }: Props) => ( placeholder="Safe Address*" text="Safe Address" type="text" - validate={composeValidators(required, mustBeEthereumAddress)} /> diff --git a/src/routes/safe/components/AddressBook/index.jsx b/src/routes/safe/components/AddressBook/index.jsx index 10ebc8f7..1b776314 100644 --- a/src/routes/safe/components/AddressBook/index.jsx +++ b/src/routes/safe/components/AddressBook/index.jsx @@ -53,12 +53,13 @@ const AddressBookTable = ({ classes }: Props) => { const columns = generateColumns() const autoColumns = columns.filter((c) => !c.custom) const dispatch = useDispatch() + const safesList = useSelector(safesListSelector) + const entryAddressToEditOrCreateNew = useSelector(addressBookQueryParamsSelector) const addressBook = useSelector(getAddressBookListSelector) const [selectedEntry, setSelectedEntry] = useState(null) const [editCreateEntryModalOpen, setEditCreateEntryModalOpen] = useState(false) const [deleteEntryModalOpen, setDeleteEntryModalOpen] = useState(false) const [sendFundsModalOpen, setSendFundsModalOpen] = useState(false) - const entryAddressToEditOrCreateNew = useSelector(addressBookQueryParamsSelector) useEffect(() => { if (entryAddressToEditOrCreateNew) { @@ -86,8 +87,6 @@ const AddressBookTable = ({ classes }: Props) => { } }, [addressBook]) - const safesList = useSelector(safesListSelector) - const newEntryModalHandler = (entry: AddressBookEntry) => { setEditCreateEntryModalOpen(false) dispatch(addAddressBookEntry(makeAddressBookEntry(entry))) @@ -160,7 +159,8 @@ const AddressBookTable = ({ classes }: Props) => { className={classes.editEntryButton} onClick={() => { setSelectedEntry({ - entry: { ...row, isOwnerAddress: userOwner }, + entry: row, + isOwnerAddress: userOwner, }) setEditCreateEntryModalOpen(true) }} diff --git a/src/routes/safe/components/AddressBook/style.js b/src/routes/safe/components/AddressBook/style.js index ab6cafc2..8321abc5 100644 --- a/src/routes/safe/components/AddressBook/style.js +++ b/src/routes/safe/components/AddressBook/style.js @@ -3,7 +3,7 @@ import { lg, marginButtonImg, md, sm } from '~/theme/variables' export const styles = () => ({ formContainer: { - minHeight: '420px', + minHeight: '250px', }, title: { padding: lg, @@ -52,7 +52,6 @@ export const styles = () => ({ cursor: 'default', }, message: { - margin: `${sm} 0`, padding: `${md} 0`, maxHeight: '54px', boxSizing: 'border-box', diff --git a/src/routes/safe/components/Apps/ManageApps.js b/src/routes/safe/components/Apps/ManageApps.js new file mode 100644 index 00000000..beb3102c --- /dev/null +++ b/src/routes/safe/components/Apps/ManageApps.js @@ -0,0 +1,210 @@ +// @flow +import { ButtonLink, Checkbox, ManageListModal, Text, TextField } from '@gnosis.pm/safe-react-components' +import type { FieldValidator } from 'final-form' +import React, { useState } from 'react' +import { FormSpy } from 'react-final-form' +import styled from 'styled-components' + +import { getAppInfoFromUrl } from './utils' + +import Field from '~/components/forms/Field' +import DebounceValidationField from '~/components/forms/Field/DebounceValidationField' +import GnoForm from '~/components/forms/GnoForm' +import { composeValidators, required } from '~/components/forms/validator' +import Img from '~/components/layout/Img' +import appsIconSvg from '~/routes/safe/components/Transactions/TxsTable/TxType/assets/appsIcon.svg' + +const FORM_ID = 'add-apps-form' + +const StyledText = styled(Text)` + margin-bottom: 19px; +` + +const StyledTextFileAppName = styled(TextField)` + && { + width: 335px; + } +` + +const AppInfo = styled.div` + margin: 36px 0 24px 0; + + img { + margin-right: 10px; + } +` + +const StyledCheckbox = styled(Checkbox)` + margin: 0; +` +const APP_INFO = { iconUrl: appsIconSvg, name: '', error: false } + +type Props = { + appList: Array<{ + id: string, + iconUrl: string, + name: string, + disabled: boolean, + }>, + onAppAdded: (app: any) => void, + onAppToggle: (appId: string, enabled: boolean) => void, +} + +const urlValidator = (value: string) => { + return /(?:^|[ \t])((https?:\/\/)?(?:localhost|[\w-]+(?:\.[\w-]+)+)(:\d+)?(\/\S*)?)/gm.test(value) + ? undefined + : 'Please, provide a valid url' +} + +const composeValidatorsApps = (...validators: Function[]): FieldValidator => (value: Field, values, meta) => { + if (!meta.modified) { + return + } + return composeValidators(validators) +} + +const ManageApps = ({ appList, onAppAdded, onAppToggle }: Props) => { + const [isOpen, setIsOpen] = useState(false) + + const [appInfo, setAppInfo] = useState(APP_INFO) + const [isSubmitDisabled, setIsSubmitDisabled] = useState(true) + + const onItemToggle = (itemId: string, checked: boolean) => { + onAppToggle(itemId, checked) + } + + const handleSubmit = () => { + setIsOpen(false) + onAppAdded(appInfo) + } + + const cleanAppInfo = () => setAppInfo(APP_INFO) + + const safeAppValidator = async (value) => { + const appInfo = await getAppInfoFromUrl(value) + + if (appInfo.error) { + setAppInfo(APP_INFO) + return 'This is not a valid Safe app.' + } + + setAppInfo({ ...appInfo }) + } + + const uniqueAppValidator = (value) => { + const exists = appList.find((a) => a.url === value.trim()) + return exists ? 'This app is already registered.' : undefined + } + + const onFormStatusChange = ({ pristine, valid, validating }) => { + if (!pristine) { + setIsSubmitDisabled(validating || !valid || appInfo.error) + } + } + + const customRequiredValidator = (value) => { + if (!value || !value.length) { + setAppInfo(APP_INFO) + return 'Required' + } + } + + const getAddAppForm = () => { + return ( + + {() => ( + <> + Add custom app + + + + Token image + + + + + + + This app is not a Gnosis product and I agree to use this app
at my own risk. +

+ } + name="agreed" + type="checkbox" + validate={required} + /> + + )} +
+ ) + } + + const onSubmitForm = () => { + // This sucks, but it's the way the docs suggest + // https://github.com/final-form/react-final-form/blob/master/docs/faq.md#via-documentgetelementbyid + document.querySelectorAll(`[data-testId=${FORM_ID}]`)[0].dispatchEvent(new Event('submit', { cancelable: true })) + } + + const toggleOpen = () => setIsOpen(!isOpen) + + const closeModal = () => { + setIsOpen(false) + cleanAppInfo() + } + + const getItemList = () => + appList.map((a) => { + return { ...a, checked: !a.disabled } + }) + + return ( + <> + + Manage Apps + + {isOpen && ( + + )} + + ) +} + +export default ManageApps diff --git a/src/routes/safe/components/Apps/index.jsx b/src/routes/safe/components/Apps/index.jsx index c822d183..d25c46ba 100644 --- a/src/routes/safe/components/Apps/index.jsx +++ b/src/routes/safe/components/Apps/index.jsx @@ -1,59 +1,70 @@ // @flow +import { Card, FixedDialog, FixedIcon, IconText, Menu, Text, Title } from '@gnosis.pm/safe-react-components' import { withSnackbar } from 'notistack' import React, { useCallback, useEffect, useState } from 'react' +import { useDispatch, useSelector } from 'react-redux' +import { useHistory } from 'react-router-dom' import styled from 'styled-components' +import ManageApps from './ManageApps' import confirmTransactions from './confirmTransactions' import sendTransactions from './sendTransactions' -import { GNOSIS_APPS_URL, getAppInfoFromUrl } from './utils' +import { getAppInfoFromUrl, staticAppsList } from './utils' import { ListContentLayout as LCL, Loader } from '~/components-v2' -import ButtonLink from '~/components/layout/ButtonLink' +import { networkSelector } from '~/logic/wallets/store/selectors' +import { SAFELIST_ADDRESS } from '~/routes/routes' +import { grantedSelector } from '~/routes/safe/container/selector' +import { + safeEthBalanceSelector, + safeNameSelector, + safeParamAddressFromStateSelector, +} from '~/routes/safe/store/selectors' +import { loadFromStorage, saveToStorage } from '~/utils/storage' + +const APPS_STORAGE_KEY = 'APPS_STORAGE_KEY' +const APPS_LEGAL_DISCLAIMER_STORAGE_KEY = 'APPS_LEGAL_DISCLAIMER_STORAGE_KEY' const StyledIframe = styled.iframe` width: 100%; height: 100%; display: ${(props) => (props.shouldDisplay ? 'block' : 'none')}; ` +const Centered = styled.div` + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; +` + const operations = { - SEND_TRANSACTIONS: 'sendTransactions', - GET_TRANSACTIONS: 'getTransactions', - ON_SAFE_INFO: 'onSafeInfo', - ON_TX_UPDATE: 'onTransactionUpdate', + SEND_TRANSACTIONS: 'SEND_TRANSACTIONS', + ON_SAFE_INFO: 'ON_SAFE_INFO', } type Props = { - web3: any, - safeAddress: String, - safeName: String, - ethBalance: String, - network: String, - createTransaction: any, enqueueSnackbar: Function, closeSnackbar: Function, openModal: () => {}, closeModal: () => {}, } -function Apps({ - closeModal, - closeSnackbar, - createTransaction, - enqueueSnackbar, - ethBalance, - network, - openModal, - safeAddress, - safeName, - web3, -}: Props) { - const [appsList, setAppsList] = useState([]) +function Apps({ closeModal, closeSnackbar, enqueueSnackbar, openModal }: Props) { + const [appList, setAppList] = useState([]) + const [legalDisclaimerAccepted, setLegalDisclaimerAccepted] = useState(false) const [selectedApp, setSelectedApp] = useState() const [loading, setLoading] = useState(true) const [appIsLoading, setAppIsLoading] = useState(true) - const [iframeEl, setframeEl] = useState(null) + const [iframeEl, setIframeEl] = useState(null) + const history = useHistory() + const granted = useSelector(grantedSelector) + const safeName = useSelector(safeNameSelector) + const safeAddress = useSelector(safeParamAddressFromStateSelector) + const network = useSelector(networkSelector) + const ethBalance = useSelector(safeEthBalanceSelector) + const dispatch = useDispatch() - const getSelectedApp = () => appsList.find((e) => e.id === selectedApp) + const getSelectedApp = () => appList.find((e) => e.id === selectedApp) const sendMessageToIframe = (messageId, data) => { iframeEl.contentWindow.postMessage({ messageId, data }, getSelectedApp().url) @@ -61,7 +72,7 @@ function Apps({ const handleIframeMessage = async (data) => { if (!data || !data.messageId) { - console.warn('iframe: message without messageId') + console.error('ThirdPartyApp: A message was received without message id.') return } @@ -70,22 +81,7 @@ function Apps({ const onConfirm = async () => { closeModal() - const txHash = await sendTransactions( - web3, - createTransaction, - safeAddress, - data.data, - enqueueSnackbar, - closeSnackbar, - getSelectedApp().id, - ) - - if (txHash) { - sendMessageToIframe(operations.ON_TX_UPDATE, { - txHash, - status: 'pending', - }) - } + await sendTransactions(dispatch, safeAddress, data.data, enqueueSnackbar, closeSnackbar, getSelectedApp().id) } confirmTransactions( @@ -101,11 +97,9 @@ function Apps({ break } - case operations.GET_TRANSACTIONS: - break default: { - console.warn(`Iframe:${data.messageId} unkown`) + console.error(`ThirdPartyApp: A message was received with an unknown message id ${data.messageId}.`) break } } @@ -113,10 +107,141 @@ function Apps({ const iframeRef = useCallback((node) => { if (node !== null) { - setframeEl(node) + setIframeEl(node) } }, []) + const onSelectApp = (appId) => { + const selectedApp = getSelectedApp() + + if (selectedApp && selectedApp.id === appId) { + return + } + + setAppIsLoading(true) + setSelectedApp(appId) + } + + const redirectToBalance = () => history.push(`${SAFELIST_ADDRESS}/${safeAddress}/balances`) + + const onAcceptLegalDisclaimer = () => { + setLegalDisclaimerAccepted(true) + saveToStorage(APPS_LEGAL_DISCLAIMER_STORAGE_KEY, true) + } + + const getContent = () => { + if (!selectedApp) { + return null + } + + if (!legalDisclaimerAccepted) { + return ( + + + You are now accessing third-party apps, which we do not own, control, maintain or audit. We are not + liable for any loss you may suffer in connection with interacting with the apps, which is at your own + risk. You must read our Terms, which contain more detailed provisions binding on you relating to the + apps. + +
+ + I have read and understood the{' '} +
+ Terms + {' '} + and this Disclaimer, and agree to be bound by . + + + } + onCancel={redirectToBalance} + onConfirm={onAcceptLegalDisclaimer} + title="Disclaimer" + /> + ) + } + + if (network === 'UNKNOWN' || !granted) { + return ( + + + To use apps, you must be an owner of this Safe + + ) + } + + return ( + <> + {appIsLoading && } + + + ) + } + + const onAppAdded = (app) => { + const newAppList = [ + { url: app.url, disabled: false }, + ...appList.map((a) => ({ + url: a.url, + disabled: a.disabled, + })), + ] + saveToStorage(APPS_STORAGE_KEY, newAppList) + + setAppList([...appList, { ...app, disabled: false }]) + } + + const selectFirstApp = (apps) => { + const firstEnabledApp = apps.find((a) => !a.disabled) + if (firstEnabledApp) { + onSelectApp(firstEnabledApp.id) + } + } + + const onAppToggle = async (appId: string, enabled: boolean) => { + // update in-memory list + const copyAppList = [...appList] + + const app = copyAppList.find((a) => a.id === appId) + if (!app) { + return + } + + app.disabled = !enabled + setAppList(copyAppList) + + // update storage list + const persistedAppList = (await loadFromStorage(APPS_STORAGE_KEY)) || [] + let storageApp = persistedAppList.find((a) => a.url === app.url) + + if (!storageApp) { + storageApp = { url: app.url } + storageApp.disabled = !enabled + persistedAppList.push(storageApp) + } else { + storageApp.disabled = !enabled + } + + saveToStorage(APPS_STORAGE_KEY, persistedAppList) + + // select app + const selectedApp = getSelectedApp() + if (!selectedApp || (selectedApp && selectedApp.id === appId)) { + setSelectedApp(undefined) + selectFirstApp(copyAppList) + } + } + + const getEnabledApps = () => appList.filter((a) => !a.disabled) + // handle messages from iframe useEffect(() => { const onIframeMessage = async ({ data, origin }) => { @@ -125,7 +250,7 @@ function Apps({ } if (!getSelectedApp().url.includes(origin)) { - console.error(`Message from ${origin} is different to the App URL ${getSelectedApp().url}`) + console.error(`ThirdPartyApp: A message from was received from an unknown origin ${origin}`) return } @@ -139,35 +264,63 @@ function Apps({ } }) + // load legalDisclaimer + useEffect(() => { + const checkLegalDisclaimer = async () => { + const legalDisclaimer = await loadFromStorage(APPS_LEGAL_DISCLAIMER_STORAGE_KEY) + + if (legalDisclaimer) { + setLegalDisclaimerAccepted(true) + } + } + + checkLegalDisclaimer() + }) + // Load apps list useEffect(() => { const loadApps = async () => { - const appsUrl = process.env.REACT_APP_GNOSIS_APPS_URL ? process.env.REACT_APP_GNOSIS_APPS_URL : GNOSIS_APPS_URL - const staticAppsList = [`${appsUrl}/compound`, `${appsUrl}/uniswap`] + // recover apps from storage: + // * third-party apps added by the user + // * disabled status for both static and third-party apps + const persistedAppList = (await loadFromStorage(APPS_STORAGE_KEY)) || [] + const list = [...persistedAppList] + + staticAppsList.forEach((staticApp) => { + if (!list.some((persistedApp) => persistedApp.url === staticApp.url)) { + list.push(staticApp) + } + }) - const list = [...staticAppsList] const apps = [] + // using the appURL to recover app info for (let index = 0; index < list.length; index++) { try { - const appUrl = list[index] - const appInfo = await getAppInfoFromUrl(appUrl) - const app = { url: appUrl, ...appInfo } + const currentApp = list[index] - app.id = JSON.stringify({ url: app.url, name: app.name }) - apps.push(app) + const appInfo = await getAppInfoFromUrl(currentApp.url) + + if (appInfo.error) { + throw Error() + } + + appInfo.disabled = currentApp.disabled === undefined ? false : currentApp.disabled + + apps.push(appInfo) } catch (error) { console.error(error) } } - setAppsList([...apps]) + setAppList(apps) setLoading(false) + selectFirstApp(apps) } - if (!appsList.length) { + if (!appList.length) { loadApps() } - }, [appsList]) + }, []) // on iframe change useEffect(() => { @@ -191,57 +344,57 @@ function Apps({ } }, [iframeEl]) - const onSelectApp = (appId) => { - setAppIsLoading(true) - setSelectedApp(appId) + if (loading) { + return } - const getContent = () => { - if (!selectedApp) { - return null - } - - return ( - <> - {appIsLoading && } - - - ) - } - - if (loading || !appsList.length) { + if (loading || !appList.length) { return } return ( - - - {}} size="lg" testId="manage-tokens-btn"> - Manage Apps - - - - - - {getContent()} - - This App is provided by{' '} - window.open(getSelectedApp().providedBy.url, '_blank')} - size="lg" - testId="manage-tokens-btn" - > - {selectedApp && getSelectedApp().providedBy.name} - - - + <> + + + + {getEnabledApps().length ? ( + + + + + {getContent()} + {/* + {getSelectedApp() && getSelectedApp().providedBy && ( + <> +

This App is provided by

+ window.open(getSelectedApp().providedBy.url, '_blank')} + size="lg" + testId="manage-tokens-btn" + > + {selectedApp && getSelectedApp().providedBy.name} + + + )} +
*/} +
+ ) : ( + + + No Apps Enabled + + + )} + + + + ) } diff --git a/src/routes/safe/components/Apps/sendTransactions.js b/src/routes/safe/components/Apps/sendTransactions.js index 5a9d7c61..278686d4 100644 --- a/src/routes/safe/components/Apps/sendTransactions.js +++ b/src/routes/safe/components/Apps/sendTransactions.js @@ -1,5 +1,7 @@ // @flow import { DELEGATE_CALL } from '~/logic/safe/transactions/send' +import { getWeb3 } from '~/logic/wallets/getWeb3' +import createTransaction from '~/routes/safe/store/actions/createTransaction' const multiSendAddress = '0xB522a9f781924eD250A11C54105E51840B138AdD' const multiSendAbi = [ @@ -15,14 +17,14 @@ const multiSendAbi = [ ] const sendTransactions = ( - web3: any, - createTransaction: any, + dispatch: Function, safeAddress: String, txs: Array, enqueueSnackbar: Function, closeSnackbar: Function, origin: string, ) => { + const web3 = getWeb3() const multiSend = new web3.eth.Contract(multiSendAbi, multiSendAddress) const encodeMultiSendCalldata = multiSend.methods @@ -41,17 +43,19 @@ const sendTransactions = ( ) .encodeABI() - return createTransaction({ - safeAddress, - to: multiSendAddress, - valueInWei: 0, - txData: encodeMultiSendCalldata, - notifiedTransaction: 'STANDARD_TX', - enqueueSnackbar, - closeSnackbar, - operation: DELEGATE_CALL, - // navigateToTransactionsTab: false, - origin, - }) + return dispatch( + createTransaction({ + safeAddress, + to: multiSendAddress, + valueInWei: 0, + txData: encodeMultiSendCalldata, + notifiedTransaction: 'STANDARD_TX', + enqueueSnackbar, + closeSnackbar, + operation: DELEGATE_CALL, + // navigateToTransactionsTab: false, + origin, + }), + ) } export default sendTransactions diff --git a/src/routes/safe/components/Apps/utils.js b/src/routes/safe/components/Apps/utils.js index 2731ac9f..91cad05d 100644 --- a/src/routes/safe/components/Apps/utils.js +++ b/src/routes/safe/components/Apps/utils.js @@ -3,34 +3,56 @@ import axios from 'axios' import appsIconSvg from '~/routes/safe/components/Transactions/TxsTable/TxType/assets/appsIcon.svg' -export const GNOSIS_APPS_URL = 'https://gnosis-apps.netlify.com' +export const GNOSIS_APPS_URL = 'https://gnosis-apps.netlify.app' + +const appsUrl = process.env.REACT_APP_GNOSIS_APPS_URL ? process.env.REACT_APP_GNOSIS_APPS_URL : GNOSIS_APPS_URL +export const staticAppsList = [{ url: `${appsUrl}/compound`, disabled: false }] export const getAppInfoFromOrigin = (origin: string) => { try { return JSON.parse(origin) } catch (error) { - console.error(`Impossible to parse TX origin: ${origin}`) + console.error(`Impossible to parse TX from origin: ${origin}`) return null } } export const getAppInfoFromUrl = async (appUrl: string) => { + let cleanedUpAppUrl = appUrl.trim() + if (cleanedUpAppUrl.substr(-1) === '/') { + cleanedUpAppUrl = cleanedUpAppUrl.substr(0, cleanedUpAppUrl.length - 1) + } + + let res = { id: undefined, url: cleanedUpAppUrl, name: 'unknown', iconUrl: appsIconSvg, error: true } + try { - const appInfo = await axios.get(`${appUrl}/manifest.json`) - const res = { url: appUrl, ...appInfo.data, iconUrl: appsIconSvg } + const appInfo = await axios.get(`${cleanedUpAppUrl}/manifest.json`) + + // verify imported app fulfil safe requirements + if (!appInfo || !appInfo.data || !appInfo.data.name || !appInfo.data.description) { + throw Error('The app does not fulfil the structure required.') + } + + res = { + ...res, + ...appInfo.data, + id: JSON.stringify({ url: cleanedUpAppUrl, name: appInfo.data.name }), + error: false, + } if (appInfo.data.iconPath) { try { - const iconInfo = await axios.get(`${appUrl}/${appInfo.data.iconPath}`) + const iconInfo = await axios.get(`${cleanedUpAppUrl}/${appInfo.data.iconPath}`) if (/image\/\w/gm.test(iconInfo.headers['content-type'])) { - res.iconUrl = `${appUrl}/${appInfo.data.iconPath}` + res.iconUrl = `${cleanedUpAppUrl}/${appInfo.data.iconPath}` } } catch (error) { - console.error(`It was not possible to fetch icon from app ${res.name}`) + console.error(`It was not possible to fetch icon from app ${cleanedUpAppUrl}`) } } + return res } catch (error) { - console.error(`It was not possible to fetch app from ${appUrl}`) - return null + console.error(`It was not possible to fetch app from ${cleanedUpAppUrl}: ${error.message}`) + return res } } diff --git a/src/routes/safe/components/Balances/Coins/index.jsx b/src/routes/safe/components/Balances/Coins/index.jsx index 5f2c20eb..315b34db 100644 --- a/src/routes/safe/components/Balances/Coins/index.jsx +++ b/src/routes/safe/components/Balances/Coins/index.jsx @@ -6,6 +6,7 @@ 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 { List } from 'immutable' import React from 'react' import { useSelector } from 'react-redux' @@ -16,7 +17,11 @@ 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 { + currencyRateSelector, + 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' @@ -42,10 +47,15 @@ const Coins = (props: Props) => { const columns = generateColumns() const autoColumns = columns.filter((c) => !c.custom) const currencySelected = useSelector(currentCurrencySelector) + const currencyRate = useSelector(currencyRateSelector) const activeTokens = useSelector(extendedSafeTokensSelector) const currencyValues = useSelector(currencyValuesListSelector) const granted = useSelector(grantedSelector) - const filteredData = getBalanceData(activeTokens, currencySelected, currencyValues) + const [filteredData, setFilteredData] = React.useState(List()) + + React.useMemo(() => { + setFilteredData(getBalanceData(activeTokens, currencySelected, currencyValues, currencyRate)) + }, [currencySelected, currencyRate, activeTokens.hashCode(), currencyValues.hashCode()]) return ( diff --git a/src/routes/safe/components/Balances/Receive/index.jsx b/src/routes/safe/components/Balances/Receive/index.jsx index 3c970b4d..03657944 100644 --- a/src/routes/safe/components/Balances/Receive/index.jsx +++ b/src/routes/safe/components/Balances/Receive/index.jsx @@ -4,6 +4,7 @@ import { withStyles } from '@material-ui/core/styles' import Close from '@material-ui/icons/Close' import QRCode from 'qrcode.react' import * as React from 'react' +import { useSelector } from 'react-redux' import CopyBtn from '~/components/CopyBtn' import EtherscanBtn from '~/components/EtherscanBtn' @@ -14,6 +15,7 @@ import Col from '~/components/layout/Col' import Hairline from '~/components/layout/Hairline' import Paragraph from '~/components/layout/Paragraph' import Row from '~/components/layout/Row' +import { safeNameSelector, safeParamAddressFromStateSelector } from '~/routes/safe/store/selectors' import { lg, md, screenSm, secondaryText, sm } from '~/theme/variables' import { copyToClipboard } from '~/utils/clipboard' @@ -75,53 +77,55 @@ const styles = () => ({ type Props = { onClose: () => void, classes: Object, - safeName: string, - safeAddress: string, } -const Receive = ({ classes, onClose, safeAddress, safeName }: Props) => ( - <> - - - Receive funds - - - - - - - - This is the address of your Safe. Deposit funds by scanning the QR code or copying the address below. Only send - ETH and ERC-20 tokens to this address! - - - - {safeName} - - - - - - - { - copyToClipboard(safeAddress) - }} - > - {safeAddress} +const Receive = ({ classes, onClose }: Props) => { + const safeAddress = useSelector(safeParamAddressFromStateSelector) + const safeName = useSelector(safeNameSelector) + return ( + <> + + + Receive funds - - - - - - - - - -) + + + + + + + This is the address of your Safe. Deposit funds by scanning the QR code or copying the address below. Only send + ETH and ERC-20 tokens to this address! + + + + {safeName} + + + + + + + { + copyToClipboard(safeAddress) + }} + > + {safeAddress} + + + + + + + + + + + ) +} export default withStyles(styles)(Receive) diff --git a/src/routes/safe/components/Balances/dataFetcher.js b/src/routes/safe/components/Balances/dataFetcher.js index 13ea18c5..15fd7d40 100644 --- a/src/routes/safe/components/Balances/dataFetcher.js +++ b/src/routes/safe/components/Balances/dataFetcher.js @@ -1,4 +1,5 @@ // @flow +import { BigNumber } from 'bignumber.js' import { List } from 'immutable' import { type Column } from '~/components/Table/TableHead' @@ -23,38 +24,38 @@ export type BalanceRow = SortRow // eslint-disable-next-line max-len const getTokenPriceInCurrency = ( token: Token, - currencySelected: typeof AVAILABLE_CURRENCIES, + currencySelected: $Keys, currencyValues: List, + currencyRate: string, ): string => { if (!currencySelected) { return '' } - // eslint-disable-next-line no-restricted-syntax - for (const tokenPriceIterator of currencyValues) { - const { balanceInSelectedCurrency, currencyName, tokenAddress } = tokenPriceIterator - if (token.address === tokenAddress && currencySelected === currencyName) { - const balance = balanceInSelectedCurrency - ? parseFloat(balanceInSelectedCurrency, 10).toFixed(2) - : balanceInSelectedCurrency - return `${balance} ${currencySelected}` - } - // ETH token + const currencyValue = currencyValues.find(({ tokenAddress }) => { if (token.address === ETH_ADDRESS && !tokenAddress) { - const balance = balanceInSelectedCurrency - ? parseFloat(balanceInSelectedCurrency, 10).toFixed(2) - : balanceInSelectedCurrency - return `${balance} ${currencySelected}` + return true } + + return token.address === tokenAddress + }) + + if (!currencyValue) { + return '' } - return null + + const { balanceInBaseCurrency } = currencyValue + const balance = BigNumber(balanceInBaseCurrency).times(currencyRate).toFixed(2) + + return `${balance} ${currencySelected}` } // eslint-disable-next-line max-len export const getBalanceData = ( activeTokens: List, - currencySelected: string, + currencySelected: $Keys, currencyValues: List, + currencyRate: string, ): List => { const rows = activeTokens.map((token: Token) => ({ [BALANCE_TABLE_ASSET_ID]: { @@ -66,7 +67,7 @@ export const getBalanceData = ( [BALANCE_TABLE_BALANCE_ID]: `${formatAmount(token.balance)} ${token.symbol}`, [buildOrderFieldFrom(BALANCE_TABLE_BALANCE_ID)]: Number(token.balance), [FIXED]: token.get('symbol') === 'ETH', - [BALANCE_TABLE_VALUE_ID]: getTokenPriceInCurrency(token, currencySelected, currencyValues), + [BALANCE_TABLE_VALUE_ID]: getTokenPriceInCurrency(token, currencySelected, currencyValues, currencyRate), })) return rows diff --git a/src/routes/safe/components/Balances/index.jsx b/src/routes/safe/components/Balances/index.jsx index d89f25c9..e6fb1532 100644 --- a/src/routes/safe/components/Balances/index.jsx +++ b/src/routes/safe/components/Balances/index.jsx @@ -1,7 +1,7 @@ // @flow import { withStyles } from '@material-ui/core/styles' -import { List } from 'immutable' -import * as React from 'react' +import React, { useEffect, useState } from 'react' +import { useSelector } from 'react-redux' import Receive from './Receive' import Tokens from './Tokens' @@ -13,14 +13,15 @@ import Col from '~/components/layout/Col' import Divider from '~/components/layout/Divider' import Link from '~/components/layout/Link' 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 DropdownCurrency from '~/routes/safe/components/DropdownCurrency' +import { useFetchTokens } from '~/routes/safe/container/Hooks/useFetchTokens' +import { safeFeaturesEnabledSelector, safeParamAddressFromStateSelector } from '~/routes/safe/store/selectors' import { history } from '~/store' +import { wrapInSuspense } from '~/utils/wrapInSuspense' +const Collectibles = React.lazy(() => import('~/routes/safe/components/Balances/Collectibles')) +const Coins = React.lazy(() => import('~/routes/safe/components/Balances/Coins')) export const MANAGE_TOKENS_BUTTON_TEST_ID = 'manage-tokens-btn' export const BALANCE_ROW_TEST_ID = 'balance-row' @@ -37,71 +38,52 @@ type State = { } type Props = { - activateTokensByBalance: Function, - activateAssetsByBalance: Function, - activeTokens: List, - blacklistedTokens: List, classes: Object, - createTransaction: Function, - currencySelected: string, - currencyValues: BalanceCurrencyType[], - ethBalance: string, - featuresEnabled: string[], - fetchCurrencyValues: Function, - fetchTokens: Function, - granted: boolean, - safeAddress: string, - safeName: string, - tokens: List, } type Action = 'Token' | 'Send' | 'Receive' | 'ManageCollectibleModal' -class Balances extends React.Component { - constructor(props) { - super(props) - this.state = { - erc721Enabled: false, - subMenuOptions: [], - showToken: false, - showManageCollectibleModal: false, - sendFunds: { - isOpen: false, - selectedToken: undefined, - }, - showCoins: true, - showCollectibles: false, - showReceive: false, - } - props.fetchTokens() - } +const INITIAL_STATE: State = { + erc721Enabled: false, + subMenuOptions: [], + showToken: false, + showManageCollectibleModal: false, + sendFunds: { + isOpen: false, + selectedToken: undefined, + }, + showCoins: true, + showCollectibles: false, + showReceive: false, +} - static isCoinsLocation = /\/balances\/?$/ - static isCollectiblesLocation = /\/balances\/collectibles$/ +export const COINS_LOCATION_REGEX = /\/balances\/?$/ +export const COLLECTIBLES_LOCATION_REGEX = /\/balances\/collectibles$/ - componentDidMount(): void { - const { activateAssetsByBalance, activateTokensByBalance, fetchCurrencyValues, safeAddress } = this.props - fetchCurrencyValues(safeAddress) - activateTokensByBalance(safeAddress) - activateAssetsByBalance(safeAddress) +const Balances = (props: Props) => { + const [state, setState] = useState(INITIAL_STATE) - const showCollectibles = Balances.isCollectiblesLocation.test(history.location.pathname) - const showCoins = Balances.isCoinsLocation.test(history.location.pathname) + const address = useSelector(safeParamAddressFromStateSelector) + const featuresEnabled = useSelector(safeFeaturesEnabledSelector) + + useFetchTokens() + + useEffect(() => { + const showCollectibles = COLLECTIBLES_LOCATION_REGEX.test(history.location.pathname) + const showCoins = COINS_LOCATION_REGEX.test(history.location.pathname) + const subMenuOptions = [{ enabled: showCoins, legend: 'Coins', url: `${SAFELIST_ADDRESS}/${address}/balances` }] if (!showCollectibles && !showCoins) { - history.replace(`${SAFELIST_ADDRESS}/${this.props.safeAddress}/balances`) + history.replace(`${SAFELIST_ADDRESS}/${address}/balances`) } - const subMenuOptions = [ - { enabled: showCoins, legend: 'Coins', url: `${SAFELIST_ADDRESS}/${this.props.safeAddress}/balances` }, - ] - const erc721Enabled = this.props.featuresEnabled.includes('ERC721') + const erc721Enabled = featuresEnabled && featuresEnabled.includes('ERC721') if (erc721Enabled) { subMenuOptions.push({ enabled: showCollectibles, legend: 'Collectibles', - url: `${SAFELIST_ADDRESS}/${this.props.safeAddress}/balances/collectibles`, + url: `${SAFELIST_ADDRESS}/${address}/balances/collectibles`, }) } else { if (showCollectibles) { @@ -109,124 +91,129 @@ class Balances extends React.Component { } } - this.setState({ + setState((prevState) => ({ + ...prevState, showCoins, showCollectibles, erc721Enabled, subMenuOptions, - }) + })) + }, [history.location.pathname, featuresEnabled]) + + const onShow = (action: Action) => { + setState((prevState) => ({ ...prevState, [`show${action}`]: true })) } - onShow = (action: Action) => () => { - this.setState(() => ({ [`show${action}`]: true })) + const onHide = (action: Action) => { + setState((prevState) => ({ ...prevState, [`show${action}`]: false })) } - onHide = (action: Action) => () => { - this.setState(() => ({ [`show${action}`]: false })) - } - - showSendFunds = (tokenAddress: string) => { - this.setState({ + const showSendFunds = (tokenAddress: string) => { + setState((prevState) => ({ + ...prevState, sendFunds: { isOpen: true, selectedToken: tokenAddress, }, - }) + })) } - hideSendFunds = () => { - this.setState({ + const hideSendFunds = () => { + setState((prevState) => ({ + ...prevState, sendFunds: { isOpen: false, selectedToken: undefined, }, - }) + })) } - render() { - const { - erc721Enabled, - sendFunds, - showCoins, - showCollectibles, - showManageCollectibleModal, - showReceive, - showToken, - subMenuOptions, - } = this.state - const { activeTokens, classes, createTransaction, ethBalance, safeAddress, safeName } = this.props + const { + assetDivider, + assetTab, + assetTabActive, + assetTabs, + controls, + manageTokensButton, + receiveModal, + tokenControls, + } = props.classes + const { + erc721Enabled, + sendFunds, + showCoins, + showCollectibles, + showManageCollectibleModal, + showReceive, + showToken, + subMenuOptions, + } = state - return ( - <> - - - {subMenuOptions.length > 1 && - subMenuOptions.map(({ enabled, legend, url }, index) => ( - - {index > 0 && } - - {legend} - - - ))} - - - {showCoins && } - - Manage List - - - - - - - {showCoins && } - {erc721Enabled && showCollectibles && } - - - - - - ) - } + return ( + <> + + + {subMenuOptions.length > 1 && + subMenuOptions.map(({ enabled, legend, url }, index) => ( + + {index > 0 && } + + {legend} + + + ))} + + + {showCoins && } + onShow('ManageCollectibleModal') : () => onShow('Token')} + size="lg" + testId="manage-tokens-btn" + > + Manage List + + onHide('ManageCollectibleModal') : () => onHide('Token')} + open={showToken || showManageCollectibleModal} + title="Manage List" + > + onHide('ManageCollectibleModal') : () => onHide('Token')} + safeAddress={address} + /> + + + + {showCoins && wrapInSuspense( onShow('Receive')} showSendFunds={showSendFunds} />)} + {erc721Enabled && showCollectibles && wrapInSuspense()} + + onHide('Receive')} + open={showReceive} + paperClassName={receiveModal} + title="Receive Tokens" + > + onHide('Receive')} /> + + + ) } export default withStyles(styles)(Balances) diff --git a/src/routes/safe/components/Layout.jsx b/src/routes/safe/components/Layout.jsx deleted file mode 100644 index 66f5fd94..00000000 --- a/src/routes/safe/components/Layout.jsx +++ /dev/null @@ -1,400 +0,0 @@ -// @flow -import Badge from '@material-ui/core/Badge' -import Tab from '@material-ui/core/Tab' -import Tabs from '@material-ui/core/Tabs' -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 React, { useState } from 'react' -import { Redirect, Route, Switch, withRouter } from 'react-router-dom' - -import { type Actions } from '../container/actions' - -import Balances from './Balances' -import Receive from './Balances/Receive' -import Settings from './Settings' -import Transactions from './Transactions' -import { AddressBookIcon } from './assets/AddressBookIcon' -import { AppsIcon } from './assets/AppsIcon' -import { BalancesIcon } from './assets/BalancesIcon' -import { SettingsIcon } from './assets/SettingsIcon' -import { TransactionsIcon } from './assets/TransactionsIcon' -import { styles } from './style' - -import { GenericModal } from '~/components-v2' -import CopyBtn from '~/components/CopyBtn' -import EtherscanBtn from '~/components/EtherscanBtn' -import Identicon from '~/components/Identicon' -import Modal from '~/components/Modal' -import NoSafe from '~/components/NoSafe' -import Block from '~/components/layout/Block' -import Button from '~/components/layout/Button' -import Hairline from '~/components/layout/Hairline' -import Heading from '~/components/layout/Heading' -import Paragraph from '~/components/layout/Paragraph' -import Row from '~/components/layout/Row' -import { getEtherScanLink, getWeb3 } from '~/logic/wallets/getWeb3' -import AddressBookTable from '~/routes/safe/components/AddressBook' -import SendModal from '~/routes/safe/components/Balances/SendModal' -import { type SelectorProps } from '~/routes/safe/container/selector' -import { border } from '~/theme/variables' - -export const BALANCES_TAB_BTN_TEST_ID = 'balances-tab-btn' -export const SETTINGS_TAB_BTN_TEST_ID = 'settings-tab-btn' -export const TRANSACTIONS_TAB_BTN_TEST_ID = 'transactions-tab-btn' -export const ADDRESS_BOOK_TAB_BTN_TEST_ID = 'address-book-tab-btn' -export const SAFE_VIEW_NAME_HEADING_TEST_ID = 'safe-name-heading' - -const Apps = React.lazy(() => import('./Apps')) - -type Props = SelectorProps & - Actions & { - classes: Object, - granted: boolean, - sendFunds: Object, - showReceive: boolean, - onShow: Function, - onHide: Function, - showSendFunds: Function, - hideSendFunds: Function, - match: Object, - location: Object, - history: Object, - fetchCurrencyValues: Function, - updateAddressBookEntry: Function, - } - -const Layout = (props: Props) => { - const { - activateAssetsByBalance, - activateTokensByBalance, - activeTokens, - addressBook, - blacklistedTokens, - cancellationTransactions, - classes, - createTransaction, - currencySelected, - currencyValues, - fetchCurrencyValues, - fetchTokens, - granted, - hideSendFunds, - location, - match, - network, - onHide, - onShow, - processTransaction, - provider, - safe, - sendFunds, - showReceive, - showSendFunds, - tokens, - transactions, - updateAddressBookEntry, - updateSafe, - userAddress, - } = props - - const [modal, setModal] = useState({ - isOpen: false, - title: null, - body: null, - footer: null, - onClose: null, - }) - - const handleCallToRouter = (_, value) => { - const { history } = props - - history.push(value) - } - - if (!safe) { - return - } - - const { address, ethBalance, featuresEnabled, name } = safe - const etherScanLink = getEtherScanLink('address', address) - const web3Instance = getWeb3() - - const openGenericModal = (modalConfig) => { - setModal({ ...modalConfig, isOpen: true }) - } - - const closeGenericModal = () => { - if (modal.onClose) { - modal.onClose() - } - - setModal({ - isOpen: false, - title: null, - body: null, - footer: null, - onClose: null, - }) - } - - const labelAddressBook = ( - <> - - Address Book - - ) - - const labelApps = ( - <> - - Apps - - ) - - const labelSettings = ( - <> - - - Settings - - - ) - const labelBalances = ( - <> - - Assets - - ) - const labelTransactions = ( - <> - - Transactions - - ) - - const renderAppsTab = () => ( - - - - ) - - const tabsValue = () => { - const balanceLocation = `${match.url}/balances` - const isInBalance = new RegExp(`^${balanceLocation}.*$`) - const { pathname } = location - - if (isInBalance.test(pathname)) { - return balanceLocation - } - - return pathname - } - - return ( - <> - - - - - - - {name} - - {!granted && Read Only} - - - - {address} - - - - - - - - - - - - - - - {process.env.REACT_APP_ENV !== 'production' && ( - - )} - - - - - - ( - - )} - /> - ( - - )} - /> - {process.env.REACT_APP_ENV !== 'production' && ( - - )} - ( - - )} - /> - } /> - - - - - - - - {modal.isOpen && } - - ) -} - -export default withStyles(styles)(withRouter(Layout)) diff --git a/src/routes/safe/components/Layout/Header/index.jsx b/src/routes/safe/components/Layout/Header/index.jsx new file mode 100644 index 00000000..728cf493 --- /dev/null +++ b/src/routes/safe/components/Layout/Header/index.jsx @@ -0,0 +1,82 @@ +// @flow +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 React from 'react' +import { useSelector } from 'react-redux' + +import { styles } from './style' + +import CopyBtn from '~/components/CopyBtn' +import EtherscanBtn from '~/components/EtherscanBtn' +import Identicon from '~/components/Identicon' +import Block from '~/components/layout/Block' +import Button from '~/components/layout/Button' +import Heading from '~/components/layout/Heading' +import Paragraph from '~/components/layout/Paragraph' +import Row from '~/components/layout/Row' +import { SAFE_VIEW_NAME_HEADING_TEST_ID } from '~/routes/safe/components/Layout' +import { grantedSelector } from '~/routes/safe/container/selector' +import { safeNameSelector, safeParamAddressFromStateSelector } from '~/routes/safe/store/selectors' + +type Props = { + classes: Object, + showSendFunds: Function, + onShow: Function, +} + +const LayoutHeader = (props: Props) => { + const { classes, onShow, showSendFunds } = props + const address = useSelector(safeParamAddressFromStateSelector) + const granted = useSelector(grantedSelector) + const name = useSelector(safeNameSelector) + if (!address) return null + + return ( + + + + + + + {name} + + {!granted && Read Only} + + + + {address} + + + + + + + + + + + + ) +} +export default withStyles(styles)(LayoutHeader) diff --git a/src/routes/safe/components/style.js b/src/routes/safe/components/Layout/Header/style.js similarity index 73% rename from src/routes/safe/components/style.js rename to src/routes/safe/components/Layout/Header/style.js index b21c13db..36e48e87 100644 --- a/src/routes/safe/components/style.js +++ b/src/routes/safe/components/Layout/Header/style.js @@ -1,5 +1,5 @@ // @flow -import { screenSm, secondary, secondaryText, sm, smallFontSize, xs } from '~/theme/variables' +import { screenSm, secondaryText, sm, smallFontSize, xs } from '~/theme/variables' export const styles = () => ({ container: { @@ -34,19 +34,6 @@ export const styles = () => ({ user: { justifyContent: 'left', }, - receiveModal: { - height: 'auto', - maxWidth: 'calc(100% - 30px)', - minHeight: '544px', - overflow: 'hidden', - }, - open: { - paddingLeft: sm, - width: 'auto', - '&:hover': { - cursor: 'pointer', - }, - }, readonly: { backgroundColor: secondaryText, borderRadius: xs, @@ -99,22 +86,6 @@ export const styles = () => ({ leftIcon: { marginRight: sm, }, - tabWrapper: { - display: 'flex', - flexDirection: 'row', - '& svg': { - display: 'block', - marginRight: '5px', - }, - '& .fill': { - fill: 'rgba(0, 0, 0, 0.54)', - }, - }, - tabWrapperSelected: { - '& .fill': { - fill: secondary, - }, - }, nameText: { overflowWrap: 'break-word', wordBreak: 'break-word', diff --git a/src/routes/safe/components/Layout/Tabs/SettingsTab/index.jsx b/src/routes/safe/components/Layout/Tabs/SettingsTab/index.jsx new file mode 100644 index 00000000..9379bdcb --- /dev/null +++ b/src/routes/safe/components/Layout/Tabs/SettingsTab/index.jsx @@ -0,0 +1,30 @@ +// @flow +import Badge from '@material-ui/core/Badge' +import React from 'react' +import { useSelector } from 'react-redux' + +import { SettingsIcon } from '~/routes/safe/components/assets/SettingsIcon' +import { grantedSelector } from '~/routes/safe/container/selector' +import { safeNeedsUpdateSelector } from '~/routes/safe/store/selectors' + +const SettingsTab = () => { + const needsUpdate = useSelector(safeNeedsUpdateSelector) + const granted = useSelector(grantedSelector) + + return ( + <> + + + Settings + + + ) +} + +export default SettingsTab diff --git a/src/routes/safe/components/Layout/Tabs/index.jsx b/src/routes/safe/components/Layout/Tabs/index.jsx new file mode 100644 index 00000000..3ade3bd6 --- /dev/null +++ b/src/routes/safe/components/Layout/Tabs/index.jsx @@ -0,0 +1,135 @@ +// @flow +import Tab from '@material-ui/core/Tab' +import Tabs from '@material-ui/core/Tabs' +import { withStyles } from '@material-ui/core/styles' +import React from 'react' +import { withRouter } from 'react-router-dom' + +import { styles } from './style' + +import { + ADDRESS_BOOK_TAB_BTN_TEST_ID, + BALANCES_TAB_BTN_TEST_ID, + SETTINGS_TAB_BTN_TEST_ID, + TRANSACTIONS_TAB_BTN_TEST_ID, +} from '~/routes/safe/components/Layout' +import SettingsTab from '~/routes/safe/components/Layout/Tabs/SettingsTab' +import { AddressBookIcon } from '~/routes/safe/components/assets/AddressBookIcon' +import { AppsIcon } from '~/routes/safe/components/assets/AppsIcon' +import { BalancesIcon } from '~/routes/safe/components/assets/BalancesIcon' +import { TransactionsIcon } from '~/routes/safe/components/assets/TransactionsIcon' + +type Props = { + classes: Object, + match: Object, + history: Object, + location: Object, +} + +const TabsComponent = (props: Props) => { + const { classes, location, match } = props + + const handleCallToRouter = (_, value) => { + const { history } = props + + history.push(value) + } + + const tabsValue = () => { + const balanceLocation = `${match.url}/balances` + const isInBalance = new RegExp(`^${balanceLocation}.*$`) + const { pathname } = location + + if (isInBalance.test(pathname)) { + return balanceLocation + } + + return pathname + } + + const labelBalances = ( + <> + + Assets + + ) + + const labelAddressBook = ( + <> + + Address Book + + ) + + const labelApps = ( + <> + + Apps + + ) + + const labelTransactions = ( + <> + + Transactions + + ) + return ( + + + + {process.env.REACT_APP_ENV !== 'production' && ( + + )} + + } + value={`${match.url}/settings`} + /> + + ) +} +export default withStyles(styles)(withRouter(TabsComponent)) diff --git a/src/routes/safe/components/Layout/Tabs/style.js b/src/routes/safe/components/Layout/Tabs/style.js new file mode 100644 index 00000000..9a098b31 --- /dev/null +++ b/src/routes/safe/components/Layout/Tabs/style.js @@ -0,0 +1,21 @@ +// @flow +import { secondary } from '~/theme/variables' + +export const styles = () => ({ + tabWrapper: { + display: 'flex', + flexDirection: 'row', + '& svg': { + display: 'block', + marginRight: '5px', + }, + '& .fill': { + fill: 'rgba(0, 0, 0, 0.54)', + }, + }, + tabWrapperSelected: { + '& .fill': { + fill: secondary, + }, + }, +}) diff --git a/src/routes/safe/components/Layout/index.jsx b/src/routes/safe/components/Layout/index.jsx new file mode 100644 index 00000000..39912905 --- /dev/null +++ b/src/routes/safe/components/Layout/index.jsx @@ -0,0 +1,126 @@ +// @flow +import { makeStyles } from '@material-ui/core/styles' +import React, { useState } from 'react' +import { useSelector } from 'react-redux' +import { Redirect, Route, Switch, withRouter } from 'react-router-dom' + +import Receive from '../Balances/Receive' + +import { styles } from './style' + +import { GenericModal } from '~/components-v2' +import Modal from '~/components/Modal' +import NoSafe from '~/components/NoSafe' +import Hairline from '~/components/layout/Hairline' +import { providerNameSelector } from '~/logic/wallets/store/selectors' +import SendModal from '~/routes/safe/components/Balances/SendModal' +import LayoutHeader from '~/routes/safe/components/Layout/Header' +import TabsComponent from '~/routes/safe/components/Layout/Tabs' +import { safeParamAddressFromStateSelector } from '~/routes/safe/store/selectors' +import { border } from '~/theme/variables' +import { wrapInSuspense } from '~/utils/wrapInSuspense' + +export const BALANCES_TAB_BTN_TEST_ID = 'balances-tab-btn' +export const SETTINGS_TAB_BTN_TEST_ID = 'settings-tab-btn' +export const TRANSACTIONS_TAB_BTN_TEST_ID = 'transactions-tab-btn' +export const ADDRESS_BOOK_TAB_BTN_TEST_ID = 'address-book-tab-btn' +export const SAFE_VIEW_NAME_HEADING_TEST_ID = 'safe-name-heading' + +const Apps = React.lazy(() => import('../Apps')) +const Settings = React.lazy(() => import('../Settings')) +const Balances = React.lazy(() => import('../Balances')) +const TxsTable = React.lazy(() => import('~/routes/safe/components/Transactions/TxsTable')) +const AddressBookTable = React.lazy(() => import('~/routes/safe/components/AddressBook')) + +type Props = { + classes: Object, + sendFunds: Object, + showReceive: boolean, + onShow: Function, + onHide: Function, + showSendFunds: Function, + hideSendFunds: Function, + match: Object, + location: Object, + history: Object, +} + +const useStyles = makeStyles(styles) + +const Layout = (props: Props) => { + const classes = useStyles() + const { hideSendFunds, match, onHide, onShow, sendFunds, showReceive, showSendFunds } = props + + const [modal, setModal] = useState({ + isOpen: false, + title: null, + body: null, + footer: null, + onClose: null, + }) + + const safeAddress = useSelector(safeParamAddressFromStateSelector) + const provider = useSelector(providerNameSelector) + if (!safeAddress) { + return + } + + const openGenericModal = (modalConfig) => { + setModal({ ...modalConfig, isOpen: true }) + } + + const closeGenericModal = () => { + if (modal.onClose) { + modal.onClose() + } + + setModal({ + isOpen: false, + title: null, + body: null, + footer: null, + onClose: null, + }) + } + + return ( + <> + + + + + wrapInSuspense(, null)} /> + wrapInSuspense(, null)} /> + {process.env.REACT_APP_ENV !== 'production' && ( + wrapInSuspense(, null)} + /> + )} + wrapInSuspense(, null)} /> + wrapInSuspense(, null)} /> + + + + + + + + {modal.isOpen && } + + ) +} + +export default withRouter(Layout) diff --git a/src/routes/safe/components/Layout/style.js b/src/routes/safe/components/Layout/style.js new file mode 100644 index 00000000..0e48bc0f --- /dev/null +++ b/src/routes/safe/components/Layout/style.js @@ -0,0 +1,24 @@ +// @flow +import { screenSm, sm } from '~/theme/variables' + +export const styles = () => ({ + receiveModal: { + height: 'auto', + maxWidth: 'calc(100% - 30px)', + minHeight: '544px', + overflow: 'hidden', + }, + receive: { + borderRadius: '4px', + marginLeft: sm, + width: '50%', + + '& > span': { + fontSize: '14px', + }, + [`@media (min-width: ${screenSm}px)`]: { + minWidth: '95px', + width: 'auto', + }, + }, +}) diff --git a/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.jsx b/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.jsx index 1939aeb9..e76e1a4d 100644 --- a/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.jsx @@ -3,7 +3,7 @@ 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 { useDispatch, useSelector } from 'react-redux' import OwnerForm from './screens/OwnerForm' import ReviewAddOwner from './screens/Review' @@ -13,7 +13,10 @@ import Modal from '~/components/Modal' import { addOrUpdateAddressBookEntry } from '~/logic/addressBook/store/actions/addOrUpdateAddressBookEntry' import { getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts' import { TX_NOTIFICATION_TYPES } from '~/logic/safe/transactions' +import addSafeOwner from '~/routes/safe/store/actions/addSafeOwner' +import createTransaction from '~/routes/safe/store/actions/createTransaction' import { type Owner } from '~/routes/safe/store/models/owner' +import { safeOwnersSelector, safeParamAddressFromStateSelector } from '~/routes/safe/store/selectors' const styles = () => ({ biggerModalWindow: { @@ -28,12 +31,6 @@ type Props = { onClose: () => void, classes: Object, isOpen: boolean, - safeAddress: string, - safeName: string, - owners: List, - threshold: number, - addSafeOwner: Function, - createTransaction: Function, enqueueSnackbar: Function, closeSnackbar: Function, } @@ -45,43 +42,34 @@ export const sendAddOwner = async ( ownersOld: List, enqueueSnackbar: Function, closeSnackbar: Function, - createTransaction: Function, - addSafeOwner: Function, + dispatch: Function, ) => { const gnosisSafe = await getGnosisSafeInstanceAt(safeAddress) const txData = gnosisSafe.contract.methods.addOwnerWithThreshold(values.ownerAddress, values.threshold).encodeABI() - const txHash = await createTransaction({ - safeAddress, - to: safeAddress, - valueInWei: 0, - txData, - notifiedTransaction: TX_NOTIFICATION_TYPES.SETTINGS_CHANGE_TX, - enqueueSnackbar, - closeSnackbar, - }) + const txHash = await dispatch( + createTransaction({ + safeAddress, + to: safeAddress, + valueInWei: 0, + txData, + notifiedTransaction: TX_NOTIFICATION_TYPES.SETTINGS_CHANGE_TX, + enqueueSnackbar, + closeSnackbar, + }), + ) if (txHash) { - addSafeOwner({ safeAddress, ownerName: values.ownerName, ownerAddress: values.ownerAddress }) + dispatch(addSafeOwner({ safeAddress, ownerName: values.ownerName, ownerAddress: values.ownerAddress })) } } -const AddOwner = ({ - addSafeOwner, - classes, - closeSnackbar, - createTransaction, - enqueueSnackbar, - isOpen, - onClose, - owners, - safeAddress, - safeName, - threshold, -}: Props) => { - const dispatch = useDispatch() +const AddOwner = ({ classes, closeSnackbar, enqueueSnackbar, isOpen, onClose }: Props) => { const [activeScreen, setActiveScreen] = useState('selectOwner') const [values, setValues] = useState({}) + const dispatch = useDispatch() + const safeAddress = useSelector(safeParamAddressFromStateSelector) + const owners = useSelector(safeOwnersSelector) useEffect( () => () => { @@ -120,8 +108,7 @@ const AddOwner = ({ onClose() try { - await sendAddOwner(values, safeAddress, owners, enqueueSnackbar, closeSnackbar, createTransaction, addSafeOwner) - + await sendAddOwner(values, safeAddress, owners, enqueueSnackbar, closeSnackbar, dispatch) dispatch( addOrUpdateAddressBookEntry(values.ownerAddress, { name: values.ownerName, address: values.ownerAddress }), ) @@ -139,26 +126,12 @@ const AddOwner = ({ title="Add owner to Safe" > <> - {activeScreen === 'selectOwner' && } + {activeScreen === 'selectOwner' && } {activeScreen === 'selectThreshold' && ( - + )} {activeScreen === 'reviewAddOwner' && ( - + )} 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 5409529e..106692fd 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 @@ -2,8 +2,8 @@ import IconButton from '@material-ui/core/IconButton' import { withStyles } from '@material-ui/core/styles' import Close from '@material-ui/icons/Close' -import { List } from 'immutable' import React from 'react' +import { useSelector } from 'react-redux' import { styles } from './style' @@ -18,7 +18,7 @@ import Col from '~/components/layout/Col' import Hairline from '~/components/layout/Hairline' import Paragraph from '~/components/layout/Paragraph' import Row from '~/components/layout/Row' -import { type Owner } from '~/routes/safe/store/models/owner' +import { safeOwnersSelector } from '~/routes/safe/store/selectors' export const ADD_OWNER_NAME_INPUT_TEST_ID = 'add-owner-name-input' export const ADD_OWNER_ADDRESS_INPUT_TEST_ID = 'add-owner-address-testid' @@ -34,13 +34,13 @@ type Props = { onClose: () => void, classes: Object, onSubmit: Function, - owners: List, } -const OwnerForm = ({ classes, onClose, onSubmit, owners }: Props) => { +const OwnerForm = ({ classes, onClose, onSubmit }: Props) => { const handleSubmit = (values) => { onSubmit(values) } + const owners = useSelector(safeOwnersSelector) 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 e30a67f4..d66b5422 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 @@ -3,8 +3,8 @@ import IconButton from '@material-ui/core/IconButton' import { withStyles } from '@material-ui/core/styles' import Close from '@material-ui/icons/Close' import classNames from 'classnames' -import { List } from 'immutable' import React, { useEffect, useState } from 'react' +import { useSelector } from 'react-redux' import { styles } from './style' @@ -21,23 +21,23 @@ import { getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts' import { estimateTxGasCosts } from '~/logic/safe/transactions/gasNew' import { formatAmount } from '~/logic/tokens/utils/formatAmount' import { getWeb3 } from '~/logic/wallets/getWeb3' -import type { Owner } from '~/routes/safe/store/models/owner' +import { safeNameSelector, safeOwnersSelector, safeParamAddressFromStateSelector } from '~/routes/safe/store/selectors' export const ADD_OWNER_SUBMIT_BTN_TEST_ID = 'add-owner-submit-btn' type Props = { onClose: () => void, classes: Object, - safeName: string, - owners: List, values: Object, onClickBack: Function, onSubmit: Function, - safeAddress: string, } -const ReviewAddOwner = ({ classes, onClickBack, onClose, onSubmit, owners, safeAddress, safeName, values }: Props) => { +const ReviewAddOwner = ({ classes, onClickBack, onClose, onSubmit, values }: Props) => { const [gasCosts, setGasCosts] = useState('< 0.001') + const safeAddress = useSelector(safeParamAddressFromStateSelector) + const safeName = useSelector(safeNameSelector) + const owners = useSelector(safeOwnersSelector) useEffect(() => { let isCurrent = true const estimateGas = async () => { 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 0d57ac9c..8318d80a 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 @@ -3,8 +3,8 @@ import IconButton from '@material-ui/core/IconButton' import MenuItem from '@material-ui/core/MenuItem' import { withStyles } from '@material-ui/core/styles' import Close from '@material-ui/icons/Close' -import { List } from 'immutable' import React from 'react' +import { useSelector } from 'react-redux' import { styles } from './style' @@ -18,7 +18,7 @@ import Col from '~/components/layout/Col' import Hairline from '~/components/layout/Hairline' import Paragraph from '~/components/layout/Paragraph' import Row from '~/components/layout/Row' -import type { Owner } from '~/routes/safe/store/models/owner' +import { safeOwnersSelector, safeThresholdSelector } from '~/routes/safe/store/selectors' export const ADD_OWNER_THRESHOLD_NEXT_BTN_TEST_ID = 'add-owner-threshold-next-btn' @@ -27,11 +27,11 @@ type Props = { onClickBack: Function, onClose: () => void, onSubmit: Function, - owners: List, - threshold: number, } -const ThresholdForm = ({ classes, onClickBack, onClose, onSubmit, owners, threshold }: Props) => { +const ThresholdForm = ({ classes, onClickBack, onClose, onSubmit }: Props) => { + const threshold = useSelector(safeThresholdSelector) + const owners = useSelector(safeOwnersSelector) 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 19058820..399ffb96 100644 --- a/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/index.jsx @@ -4,6 +4,7 @@ import { withStyles } from '@material-ui/core/styles' import Close from '@material-ui/icons/Close' import { withSnackbar } from 'notistack' import React from 'react' +import { useDispatch, useSelector } from 'react-redux' import { styles } from './style' @@ -21,8 +22,11 @@ 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 { updateAddressBookEntry } from '~/logic/addressBook/store/actions/updateAddressBookEntry' import { getNotificationsFromTxType, showSnackbar } from '~/logic/notifications' import { TX_NOTIFICATION_TYPES } from '~/logic/safe/transactions' +import editSafeOwner from '~/routes/safe/store/actions/editSafeOwner' +import { safeParamAddressFromStateSelector } from '~/routes/safe/store/selectors' import { sm } from '~/theme/variables' export const RENAME_OWNER_INPUT_TEST_ID = 'rename-owner-input' @@ -32,31 +36,27 @@ type Props = { onClose: () => void, classes: Object, isOpen: boolean, - safeAddress: string, ownerAddress: string, selectedOwnerName: string, - editSafeOwner: Function, enqueueSnackbar: Function, closeSnackbar: Function, - updateAddressBookEntry: Function, } const EditOwnerComponent = ({ classes, closeSnackbar, - editSafeOwner, enqueueSnackbar, isOpen, onClose, ownerAddress, - safeAddress, selectedOwnerName, - updateAddressBookEntry, }: Props) => { + const dispatch = useDispatch() + const safeAddress = useSelector(safeParamAddressFromStateSelector) const handleSubmit = (values) => { const { ownerName } = values - editSafeOwner({ safeAddress, ownerAddress, ownerName }) - updateAddressBookEntry(makeAddressBookEntry({ address: ownerAddress, name: ownerName })) + dispatch(editSafeOwner({ safeAddress, ownerAddress, ownerName })) + dispatch(updateAddressBookEntry(makeAddressBookEntry({ address: ownerAddress, name: ownerName }))) const notification = getNotificationsFromTxType(TX_NOTIFICATION_TYPES.OWNER_NAME_CHANGE_TX) showSnackbar(notification.afterExecution.noMoreConfirmationsNeeded, enqueueSnackbar, closeSnackbar) @@ -131,6 +131,4 @@ const EditOwnerComponent = ({ ) } -const EditOwnerModal = withStyles(styles)(withSnackbar(EditOwnerComponent)) - -export default EditOwnerModal +export default withStyles(styles)(withSnackbar(EditOwnerComponent)) diff --git a/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/index.jsx b/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/index.jsx index a8454383..4b5e9ceb 100644 --- a/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/index.jsx @@ -3,6 +3,7 @@ import { withStyles } from '@material-ui/core/styles' import { List } from 'immutable' import { withSnackbar } from 'notistack' import React, { useEffect, useState } from 'react' +import { useDispatch, useSelector } from 'react-redux' import CheckOwner from './screens/CheckOwner' import ReviewRemoveOwner from './screens/Review' @@ -11,8 +12,14 @@ import ThresholdForm from './screens/ThresholdForm' import Modal from '~/components/Modal' import { SENTINEL_ADDRESS, getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts' import { TX_NOTIFICATION_TYPES } from '~/logic/safe/transactions' +import createTransaction from '~/routes/safe/store/actions/createTransaction' +import removeSafeOwner from '~/routes/safe/store/actions/removeSafeOwner' import { type Owner } from '~/routes/safe/store/models/owner' -import type { Safe } from '~/routes/safe/store/models/safe' +import { + safeOwnersSelector, + safeParamAddressFromStateSelector, + safeThresholdSelector, +} from '~/routes/safe/store/selectors' const styles = () => ({ biggerModalWindow: { @@ -27,17 +34,10 @@ type Props = { onClose: () => void, classes: Object, isOpen: boolean, - safeAddress: string, - safeName: string, ownerAddress: string, ownerName: string, - owners: List, - threshold: number, - createTransaction: Function, - removeSafeOwner: Function, enqueueSnackbar: Function, closeSnackbar: Function, - safe: Safe, } type ActiveScreen = 'checkOwner' | 'selectThreshold' | 'reviewRemoveOwner' @@ -50,9 +50,8 @@ export const sendRemoveOwner = async ( ownersOld: List, enqueueSnackbar: Function, closeSnackbar: Function, - createTransaction: Function, - removeSafeOwner: Function, - safe: Safe, + threshold: string, + dispatch: Function, ) => { const gnosisSafe = await getGnosisSafeInstanceAt(safeAddress) const safeOwners = await gnosisSafe.getOwners() @@ -64,39 +63,30 @@ export const sendRemoveOwner = async ( .removeOwner(prevAddress, ownerAddressToRemove, values.threshold) .encodeABI() - const txHash = await createTransaction({ - safeAddress, - to: safeAddress, - valueInWei: 0, - txData, - notifiedTransaction: TX_NOTIFICATION_TYPES.SETTINGS_CHANGE_TX, - enqueueSnackbar, - closeSnackbar, - }) + const txHash = await dispatch( + createTransaction({ + safeAddress, + to: safeAddress, + valueInWei: 0, + txData, + notifiedTransaction: TX_NOTIFICATION_TYPES.SETTINGS_CHANGE_TX, + enqueueSnackbar, + closeSnackbar, + }), + ) - if (txHash && safe.threshold === 1) { - removeSafeOwner({ safeAddress, ownerAddress: ownerAddressToRemove }) + if (txHash && threshold === 1) { + dispatch(removeSafeOwner({ safeAddress, ownerAddress: ownerAddressToRemove })) } } -const RemoveOwner = ({ - classes, - closeSnackbar, - createTransaction, - enqueueSnackbar, - isOpen, - onClose, - ownerAddress, - ownerName, - owners, - removeSafeOwner, - safe, - safeAddress, - safeName, - threshold, -}: Props) => { +const RemoveOwner = ({ classes, closeSnackbar, enqueueSnackbar, isOpen, onClose, ownerAddress, ownerName }: Props) => { const [activeScreen, setActiveScreen] = useState('checkOwner') const [values, setValues] = useState({}) + const dispatch = useDispatch() + const owners = useSelector(safeOwnersSelector) + const safeAddress = useSelector(safeParamAddressFromStateSelector) + const threshold = useSelector(safeThresholdSelector) useEffect( () => () => { @@ -134,9 +124,8 @@ const RemoveOwner = ({ owners, enqueueSnackbar, closeSnackbar, - createTransaction, - removeSafeOwner, - safe, + threshold, + dispatch, ) } @@ -153,13 +142,7 @@ const RemoveOwner = ({ )} {activeScreen === 'selectThreshold' && ( - + )} {activeScreen === 'reviewRemoveOwner' && ( )} 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 fe080865..8de748b8 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 @@ -3,8 +3,8 @@ import IconButton from '@material-ui/core/IconButton' import { withStyles } from '@material-ui/core/styles' import Close from '@material-ui/icons/Close' import classNames from 'classnames' -import { List } from 'immutable' import React, { useEffect, useState } from 'react' +import { useSelector } from 'react-redux' import { styles } from './style' @@ -21,36 +21,25 @@ import { SENTINEL_ADDRESS, getGnosisSafeInstanceAt } from '~/logic/contracts/saf import { estimateTxGasCosts } from '~/logic/safe/transactions/gasNew' import { formatAmount } from '~/logic/tokens/utils/formatAmount' import { getWeb3 } from '~/logic/wallets/getWeb3' -import type { Owner } from '~/routes/safe/store/models/owner' +import { safeNameSelector, safeOwnersSelector, safeParamAddressFromStateSelector } from '~/routes/safe/store/selectors' export const REMOVE_OWNER_REVIEW_BTN_TEST_ID = 'remove-owner-review-btn' type Props = { onClose: () => void, classes: Object, - safeName: string, - owners: List, values: Object, ownerAddress: string, ownerName: string, onClickBack: Function, onSubmit: Function, - safeAddress: string, } -const ReviewRemoveOwner = ({ - classes, - onClickBack, - onClose, - onSubmit, - ownerAddress, - ownerName, - owners, - safeAddress, - safeName, - values, -}: Props) => { +const ReviewRemoveOwner = ({ classes, onClickBack, onClose, onSubmit, ownerAddress, ownerName, values }: Props) => { const [gasCosts, setGasCosts] = useState('< 0.001') + const safeAddress = useSelector(safeParamAddressFromStateSelector) + const safeName = useSelector(safeNameSelector) + const owners = useSelector(safeOwnersSelector) useEffect(() => { let isCurrent = true 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 3d4d015d..7052743d 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 @@ -3,8 +3,8 @@ import IconButton from '@material-ui/core/IconButton' import MenuItem from '@material-ui/core/MenuItem' import { withStyles } from '@material-ui/core/styles' import Close from '@material-ui/icons/Close' -import { List } from 'immutable' import React from 'react' +import { useSelector } from 'react-redux' import { styles } from './style' @@ -18,7 +18,7 @@ import Col from '~/components/layout/Col' import Hairline from '~/components/layout/Hairline' import Paragraph from '~/components/layout/Paragraph' import Row from '~/components/layout/Row' -import type { Owner } from '~/routes/safe/store/models/owner' +import { safeOwnersSelector, safeThresholdSelector } from '~/routes/safe/store/selectors' export const REMOVE_OWNER_THRESHOLD_NEXT_BTN_TEST_ID = 'remove-owner-threshold-next-btn' @@ -27,11 +27,11 @@ type Props = { onClickBack: Function, onClose: () => void, onSubmit: Function, - owners: List, - threshold: number, } -const ThresholdForm = ({ classes, onClickBack, onClose, onSubmit, owners, threshold }: Props) => { +const ThresholdForm = ({ classes, onClickBack, onClose, onSubmit }: Props) => { + const owners = useSelector(safeOwnersSelector) + const threshold = useSelector(safeThresholdSelector) const handleSubmit = (values) => { onSubmit(values) } diff --git a/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.jsx b/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.jsx index c1f414a1..fdcdb5f1 100644 --- a/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.jsx @@ -1,9 +1,8 @@ // @flow 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 { useDispatch, useSelector } from 'react-redux' import OwnerForm from './screens/OwnerForm' import ReviewReplaceOwner from './screens/Review' @@ -12,8 +11,9 @@ 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' -import type { Safe } from '~/routes/safe/store/models/safe' +import createTransaction from '~/routes/safe/store/actions/createTransaction' +import replaceSafeOwner from '~/routes/safe/store/actions/replaceSafeOwner' +import { safeParamAddressFromStateSelector, safeThresholdSelector } from '~/routes/safe/store/selectors' const styles = () => ({ biggerModalWindow: { @@ -28,17 +28,10 @@ type Props = { onClose: () => void, classes: Object, isOpen: boolean, - safeAddress: string, - safeName: string, - ownerAddress: string, - ownerName: string, - owners: List, - threshold: string, - createTransaction: Function, - replaceSafeOwner: Function, enqueueSnackbar: Function, closeSnackbar: Function, - safe: Safe, + ownerAddress: string, + ownerName: string, } type ActiveScreen = 'checkOwner' | 'reviewReplaceOwner' @@ -48,9 +41,8 @@ export const sendReplaceOwner = async ( ownerAddressToRemove: string, enqueueSnackbar: Function, closeSnackbar: Function, - createTransaction: Function, - replaceSafeOwner: Function, - safe: Safe, + threshold: string, + dispatch: Function, ) => { const gnosisSafe = await getGnosisSafeInstanceAt(safeAddress) const safeOwners = await gnosisSafe.getOwners() @@ -62,45 +54,36 @@ export const sendReplaceOwner = async ( .swapOwner(prevAddress, ownerAddressToRemove, values.ownerAddress) .encodeABI() - const txHash = await createTransaction({ - safeAddress, - to: safeAddress, - valueInWei: 0, - txData, - notifiedTransaction: TX_NOTIFICATION_TYPES.SETTINGS_CHANGE_TX, - enqueueSnackbar, - closeSnackbar, - }) - - if (txHash && safe.threshold === 1) { - replaceSafeOwner({ + const txHash = await dispatch( + createTransaction({ safeAddress, - oldOwnerAddress: ownerAddressToRemove, - ownerAddress: values.ownerAddress, - ownerName: values.ownerName, - }) + to: safeAddress, + valueInWei: 0, + txData, + notifiedTransaction: TX_NOTIFICATION_TYPES.SETTINGS_CHANGE_TX, + enqueueSnackbar, + closeSnackbar, + }), + ) + + if (txHash && threshold === 1) { + dispatch( + replaceSafeOwner({ + safeAddress, + oldOwnerAddress: ownerAddressToRemove, + ownerAddress: values.ownerAddress, + ownerName: values.ownerName, + }), + ) } } -const ReplaceOwner = ({ - classes, - closeSnackbar, - createTransaction, - enqueueSnackbar, - isOpen, - onClose, - ownerAddress, - ownerName, - owners, - replaceSafeOwner, - safe, - safeAddress, - safeName, - threshold, -}: Props) => { - const dispatch = useDispatch() +const ReplaceOwner = ({ classes, closeSnackbar, enqueueSnackbar, isOpen, onClose, ownerAddress, ownerName }: Props) => { const [activeScreen, setActiveScreen] = useState('checkOwner') const [values, setValues] = useState({}) + const dispatch = useDispatch() + const safeAddress = useSelector(safeParamAddressFromStateSelector) + const threshold = useSelector(safeThresholdSelector) useEffect( () => () => { @@ -121,18 +104,8 @@ const ReplaceOwner = ({ const onReplaceOwner = async () => { onClose() - try { - await sendReplaceOwner( - values, - safeAddress, - ownerAddress, - enqueueSnackbar, - closeSnackbar, - createTransaction, - replaceSafeOwner, - safe, - ) + await sendReplaceOwner(values, safeAddress, ownerAddress, enqueueSnackbar, closeSnackbar, threshold, dispatch) dispatch( // Needs the `address` field because we need to provide the minimum required values to ADD a new entry @@ -155,13 +128,7 @@ const ReplaceOwner = ({ > <> {activeScreen === 'checkOwner' && ( - + )} {activeScreen === 'reviewReplaceOwner' && ( )} 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 13f876b3..34344b16 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 @@ -3,8 +3,8 @@ import IconButton from '@material-ui/core/IconButton' import { withStyles } from '@material-ui/core/styles' import Close from '@material-ui/icons/Close' import classNames from 'classnames/bind' -import { List } from 'immutable' import React from 'react' +import { useSelector } from 'react-redux' import { styles } from './style' @@ -22,7 +22,7 @@ import Col from '~/components/layout/Col' import Hairline from '~/components/layout/Hairline' import Paragraph from '~/components/layout/Paragraph' import Row from '~/components/layout/Row' -import { type Owner } from '~/routes/safe/store/models/owner' +import { safeOwnersSelector } from '~/routes/safe/store/selectors' export const REPLACE_OWNER_NAME_INPUT_TEST_ID = 'replace-owner-name-input' export const REPLACE_OWNER_ADDRESS_INPUT_TEST_ID = 'replace-owner-address-testid' @@ -40,13 +40,13 @@ type Props = { ownerAddress: string, ownerName: string, onSubmit: Function, - owners: List, } -const OwnerForm = ({ classes, onClose, onSubmit, ownerAddress, ownerName, owners }: Props) => { +const OwnerForm = ({ classes, onClose, onSubmit, ownerAddress, ownerName }: Props) => { const handleSubmit = (values) => { onSubmit(values) } + const owners = useSelector(safeOwnersSelector) 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 9b1588ee..953a8c67 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 @@ -3,8 +3,8 @@ import IconButton from '@material-ui/core/IconButton' import { withStyles } from '@material-ui/core/styles' import Close from '@material-ui/icons/Close' import classNames from 'classnames' -import { List } from 'immutable' import React, { useEffect, useState } from 'react' +import { useSelector } from 'react-redux' import { styles } from './style' @@ -21,38 +21,33 @@ import { SENTINEL_ADDRESS, getGnosisSafeInstanceAt } from '~/logic/contracts/saf import { estimateTxGasCosts } from '~/logic/safe/transactions/gasNew' import { formatAmount } from '~/logic/tokens/utils/formatAmount' import { getWeb3 } from '~/logic/wallets/getWeb3' -import type { Owner } from '~/routes/safe/store/models/owner' +import type { Safe } from '~/routes/safe/store/models/safe' +import { + safeNameSelector, + safeOwnersSelector, + safeParamAddressFromStateSelector, + safeThresholdSelector, +} from '~/routes/safe/store/selectors' export const REPLACE_OWNER_SUBMIT_BTN_TEST_ID = 'replace-owner-submit-btn' type Props = { onClose: () => void, classes: Object, - safeName: string, - owners: List, values: Object, ownerAddress: string, ownerName: string, onClickBack: Function, onSubmit: Function, - threshold: string, - safeAddress: string, + safe: Safe, } -const ReviewRemoveOwner = ({ - classes, - onClickBack, - onClose, - onSubmit, - ownerAddress, - ownerName, - owners, - safeAddress, - safeName, - threshold, - values, -}: Props) => { +const ReviewRemoveOwner = ({ classes, onClickBack, onClose, onSubmit, ownerAddress, ownerName, values }: Props) => { const [gasCosts, setGasCosts] = useState('< 0.001') + const safeAddress = useSelector(safeParamAddressFromStateSelector) + const safeName = useSelector(safeNameSelector) + const owners = useSelector(safeOwnersSelector) + const threshold = useSelector(safeThresholdSelector) useEffect(() => { let isCurrent = true diff --git a/src/routes/safe/components/Settings/ManageOwners/index.jsx b/src/routes/safe/components/Settings/ManageOwners/index.jsx index 9b3876ef..2b6a56ad 100644 --- a/src/routes/safe/components/Settings/ManageOwners/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/index.jsx @@ -38,7 +38,6 @@ import Row from '~/components/layout/Row' import type { AddressBook } from '~/logic/addressBook/model/addressBook' import { getOwnersWithNameFromAddressBook } from '~/logic/addressBook/utils' import type { Owner } from '~/routes/safe/store/models/owner' -import type { Safe } from '~/routes/safe/store/models/safe' export const RENAME_OWNER_BTN_TEST_ID = 'rename-owner-btn' export const REMOVE_OWNER_BTN_TEST_ID = 'remove-owner-btn' @@ -48,21 +47,9 @@ export const OWNERS_ROW_TEST_ID = 'owners-row' type Props = { classes: Object, - safeAddress: string, - safeName: string, owners: List, - network: string, - threshold: number, - userAddress: string, - createTransaction: Function, - addSafeOwner: Function, - removeSafeOwner: Function, - replaceSafeOwner: Function, - editSafeOwner: Function, - granted: boolean, - safe: Safe, addressBook: AddressBook, - updateAddressBookEntry: Function, + granted: boolean, } type State = { @@ -107,24 +94,7 @@ class ManageOwners extends React.Component { } render() { - const { - addSafeOwner, - addressBook, - classes, - createTransaction, - editSafeOwner, - granted, - network, - owners, - removeSafeOwner, - replaceSafeOwner, - safe, - safeAddress, - safeName, - threshold, - updateAddressBookEntry, - userAddress, - } = this.props + const { addressBook, classes, granted, owners } = this.props const { selectedOwnerAddress, selectedOwnerName, @@ -133,7 +103,6 @@ class ManageOwners extends React.Component { showRemoveOwner, showReplaceOwner, } = this.state - const columns = generateColumns() const autoColumns = columns.filter((c) => !c.custom) const ownersAdbk = getOwnersWithNameFromAddressBook(addressBook, owners) @@ -232,55 +201,24 @@ class ManageOwners extends React.Component { )} - + ) diff --git a/src/routes/safe/components/Settings/RemoveSafeModal/index.jsx b/src/routes/safe/components/Settings/RemoveSafeModal/index.jsx index 9c2ac62e..2261407f 100644 --- a/src/routes/safe/components/Settings/RemoveSafeModal/index.jsx +++ b/src/routes/safe/components/Settings/RemoveSafeModal/index.jsx @@ -5,9 +5,9 @@ import Close from '@material-ui/icons/Close' import OpenInNew from '@material-ui/icons/OpenInNew' import classNames from 'classnames' import React from 'react' -import { connect } from 'react-redux' +import { useDispatch, useSelector } from 'react-redux' -import actions, { type Actions } from './actions' +import { type Actions } from './actions' import { styles } from './style' import Identicon from '~/components/Identicon' @@ -19,7 +19,10 @@ import Hairline from '~/components/layout/Hairline' import Link from '~/components/layout/Link' import Paragraph from '~/components/layout/Paragraph' import Row from '~/components/layout/Row' +import { getEtherScanLink } from '~/logic/wallets/getWeb3' import { SAFELIST_ADDRESS } from '~/routes/routes' +import removeSafe from '~/routes/safe/store/actions/removeSafe' +import { safeNameSelector, safeParamAddressFromStateSelector } from '~/routes/safe/store/selectors' import { history } from '~/store' import { md, secondary } from '~/theme/variables' @@ -32,79 +35,81 @@ type Props = Actions & { onClose: () => void, classes: Object, isOpen: boolean, - safeAddress: string, - etherScanLink: string, - safeName: string, } -const RemoveSafeComponent = ({ classes, etherScanLink, isOpen, onClose, removeSafe, safeAddress, safeName }: Props) => ( - - - - Remove Safe - - - - - - - - - - - - - - - {safeName} - - - - {safeAddress} - - - - - - - +const RemoveSafeComponent = ({ classes, isOpen, onClose }: Props) => { + const safeAddress = useSelector(safeParamAddressFromStateSelector) + const safeName = useSelector(safeNameSelector) + const dispatch = useDispatch() + const etherScanLink = getEtherScanLink('address', safeAddress) + + return ( + + + + Remove Safe + + + + - - - Removing a Safe only removes it from your interface. It does not delete the Safe. You can always add it - back using the Safe's address. - + + + + + + + + + {safeName} + + + + {safeAddress} + + + + + + + + + + + + Removing a Safe only removes it from your interface. It does not delete the Safe. You can always add + it back using the Safe's address. + + + + + + + - - - - - - - -) + + ) +} -const RemoveSafeModal = withStyles(styles)(RemoveSafeComponent) - -export default connect(undefined, actions)(RemoveSafeModal) +export const RemoveSafeModal = withStyles(styles)(RemoveSafeComponent) diff --git a/src/routes/safe/components/Settings/SafeDetails/index.jsx b/src/routes/safe/components/Settings/SafeDetails/index.jsx index ef30a51c..04a6e9a5 100644 --- a/src/routes/safe/components/Settings/SafeDetails/index.jsx +++ b/src/routes/safe/components/Settings/SafeDetails/index.jsx @@ -2,7 +2,7 @@ import { makeStyles } from '@material-ui/core/styles' import { withSnackbar } from 'notistack' import React from 'react' -import { useSelector } from 'react-redux' +import { useDispatch, useSelector } from 'react-redux' import { styles } from './style' @@ -21,20 +21,21 @@ import { getNotificationsFromTxType, showSnackbar } from '~/logic/notifications' import { TX_NOTIFICATION_TYPES } from '~/logic/safe/transactions' import UpdateSafeModal from '~/routes/safe/components/Settings/UpdateSafeModal' import { grantedSelector } from '~/routes/safe/container/selector' -import { latestMasterContractVersionSelector } from '~/routes/safe/store/selectors' +import updateSafe from '~/routes/safe/store/actions/updateSafe' +import { + latestMasterContractVersionSelector, + safeCurrentVersionSelector, + safeNameSelector, + safeNeedsUpdateSelector, + safeParamAddressFromStateSelector, +} from '~/routes/safe/store/selectors' export const SAFE_NAME_INPUT_TEST_ID = 'safe-name-input' export const SAFE_NAME_SUBMIT_BTN_TEST_ID = 'change-safe-name-btn' export const SAFE_NAME_UPDATE_SAFE_BTN_TEST_ID = 'update-safe-name-btn' type Props = { - safeAddress: string, - safeCurrentVersion: string, - safeName: string, - safeNeedsUpdate: boolean, - updateSafe: Function, enqueueSnackbar: Function, - createTransaction: Function, closeSnackbar: Function, } @@ -44,24 +45,21 @@ const SafeDetails = (props: Props) => { const classes = useStyles() const isUserOwner = useSelector(grantedSelector) const latestMasterContractVersion = useSelector(latestMasterContractVersionSelector) - const { - closeSnackbar, - enqueueSnackbar, - safeAddress, - safeCurrentVersion, - safeName, - safeNeedsUpdate, - updateSafe, - } = props + const dispatch = useDispatch() + const safeName = useSelector(safeNameSelector) + const safeNeedsUpdate = useSelector(safeNeedsUpdateSelector) + const safeCurrentVersion = useSelector(safeCurrentVersionSelector) + const { closeSnackbar, enqueueSnackbar } = props const [isModalOpen, setModalOpen] = React.useState(false) + const safeAddress = useSelector(safeParamAddressFromStateSelector) const toggleModal = () => { setModalOpen((prevOpen) => !prevOpen) } const handleSubmit = (values) => { - updateSafe({ address: safeAddress, name: values.safeName }) + dispatch(updateSafe({ address: safeAddress, name: values.safeName })) const notification = getNotificationsFromTxType(TX_NOTIFICATION_TYPES.SAFE_NAME_CHANGE_TX) showSnackbar(notification.afterExecution.noMoreConfirmationsNeeded, enqueueSnackbar, closeSnackbar) diff --git a/src/routes/safe/components/Settings/ThresholdSettings/index.jsx b/src/routes/safe/components/Settings/ThresholdSettings/index.jsx index bd364365..aa5023d5 100644 --- a/src/routes/safe/components/Settings/ThresholdSettings/index.jsx +++ b/src/routes/safe/components/Settings/ThresholdSettings/index.jsx @@ -1,8 +1,8 @@ // @flow import { withStyles } from '@material-ui/core/styles' -import { List } from 'immutable' import { withSnackbar } from 'notistack' import React, { useState } from 'react' +import { useDispatch, useSelector } from 'react-redux' import ChangeThreshold from './ChangeThreshold' import { styles } from './style' @@ -16,30 +16,27 @@ import Paragraph from '~/components/layout/Paragraph' import Row from '~/components/layout/Row' import { getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts' import { TX_NOTIFICATION_TYPES } from '~/logic/safe/transactions' -import type { Owner } from '~/routes/safe/store/models/owner' +import { grantedSelector } from '~/routes/safe/container/selector' +import createTransaction from '~/routes/safe/store/actions/createTransaction' +import { + safeOwnersSelector, + safeParamAddressFromStateSelector, + safeThresholdSelector, +} from '~/routes/safe/store/selectors' type Props = { - owners: List, - threshold: number, classes: Object, - createTransaction: Function, - safeAddress: string, - granted: boolean, enqueueSnackbar: Function, closeSnackbar: Function, } -const ThresholdSettings = ({ - classes, - closeSnackbar, - createTransaction, - enqueueSnackbar, - granted, - owners, - safeAddress, - threshold, -}: Props) => { +const ThresholdSettings = ({ classes, closeSnackbar, enqueueSnackbar }: Props) => { const [isModalOpen, setModalOpen] = useState(false) + const dispatch = useDispatch() + const threshold = useSelector(safeThresholdSelector) + const safeAddress = useSelector(safeParamAddressFromStateSelector) + const owners = useSelector(safeOwnersSelector) + const granted = useSelector(grantedSelector) const toggleModal = () => { setModalOpen((prevOpen) => !prevOpen) @@ -49,15 +46,17 @@ const ThresholdSettings = ({ const safeInstance = await getGnosisSafeInstanceAt(safeAddress) const txData = safeInstance.contract.methods.changeThreshold(newThreshold).encodeABI() - createTransaction({ - safeAddress, - to: safeAddress, - valueInWei: 0, - txData, - notifiedTransaction: TX_NOTIFICATION_TYPES.SETTINGS_CHANGE_TX, - enqueueSnackbar, - closeSnackbar, - }) + dispatch( + createTransaction({ + safeAddress, + to: safeAddress, + valueInWei: 0, + txData, + notifiedTransaction: TX_NOTIFICATION_TYPES.SETTINGS_CHANGE_TX, + enqueueSnackbar, + closeSnackbar, + }), + ) } return ( diff --git a/src/routes/safe/components/Settings/actions.js b/src/routes/safe/components/Settings/actions.js deleted file mode 100644 index 686d5d16..00000000 --- a/src/routes/safe/components/Settings/actions.js +++ /dev/null @@ -1,19 +0,0 @@ -// @flow -import addSafeOwner from '~/routes/safe/store/actions/addSafeOwner' -import editSafeOwner from '~/routes/safe/store/actions/editSafeOwner' -import removeSafeOwner from '~/routes/safe/store/actions/removeSafeOwner' -import replaceSafeOwner from '~/routes/safe/store/actions/replaceSafeOwner' - -export type Actions = { - addSafeOwner: Function, - removeSafeOwner: Function, - replaceSafeOwner: Function, - editSafeOwner: Function, -} - -export default { - addSafeOwner, - removeSafeOwner, - replaceSafeOwner, - editSafeOwner, -} diff --git a/src/routes/safe/components/Settings/index.jsx b/src/routes/safe/components/Settings/index.jsx index 73d734b5..cf29994f 100644 --- a/src/routes/safe/components/Settings/index.jsx +++ b/src/routes/safe/components/Settings/index.jsx @@ -2,21 +2,21 @@ import Badge from '@material-ui/core/Badge' import { withStyles } from '@material-ui/core/styles' import cn from 'classnames' -import { List } from 'immutable' import * as React from 'react' -import { connect } from 'react-redux' +import { useState } from 'react' +import { useSelector } from 'react-redux' import ManageOwners from './ManageOwners' -import RemoveSafeModal from './RemoveSafeModal' +import { RemoveSafeModal } from './RemoveSafeModal' import SafeDetails from './SafeDetails' import ThresholdSettings from './ThresholdSettings' -import actions, { type Actions } from './actions' import { OwnersIcon } from './assets/icons/OwnersIcon' import { RequiredConfirmationsIcon } from './assets/icons/RequiredConfirmationsIcon' import { SafeDetailsIcon } from './assets/icons/SafeDetailsIcon' import RemoveSafeIcon from './assets/icons/bin.svg' import { styles } from './style' +import Loader from '~/components/Loader' import Block from '~/components/layout/Block' import ButtonLink from '~/components/layout/ButtonLink' import Col from '~/components/layout/Col' @@ -25,189 +25,101 @@ import Img from '~/components/layout/Img' import Paragraph from '~/components/layout/Paragraph' import Row from '~/components/layout/Row' import Span from '~/components/layout/Span' -import type { AddressBook } from '~/logic/addressBook/model/addressBook' -import { type Owner } from '~/routes/safe/store/models/owner' -import type { Safe } from '~/routes/safe/store/models/safe' +import { getAddressBook } from '~/logic/addressBook/store/selectors' +import { safeNeedsUpdate } from '~/logic/safe/utils/safeVersion' +import { grantedSelector } from '~/routes/safe/container/selector' +import { safeOwnersSelector } from '~/routes/safe/store/selectors' export const OWNERS_SETTINGS_TAB_TEST_ID = 'owner-settings-tab' -type State = { - showRemoveSafe: boolean, - menuOptionIndex: number, -} - -type Props = Actions & { - addSafeOwner: Function, - addressBook: AddressBook, +type Props = { classes: Object, - createTransaction: Function, - editSafeOwner: Function, - etherScanLink: string, - granted: boolean, - network: string, - owners: List, - removeSafeOwner: Function, - replaceSafeOwner: Function, - safe: Safe, - safeAddress: string, - safeName: string, - threshold: number, - updateAddressBookEntry: Function, - updateSafe: Function, - userAddress: string, +} +const INITIAL_STATE = { + showRemoveSafe: false, + menuOptionIndex: 1, } type Action = 'RemoveSafe' -class Settings extends React.Component { - constructor(props) { - super(props) +const Settings = (props: Props) => { + const [state, setState] = useState(INITIAL_STATE) + const owners = useSelector(safeOwnersSelector) + const needsUpdate = useSelector(safeNeedsUpdate) + const granted = useSelector(grantedSelector) + const addressBook = useSelector(getAddressBook) - this.state = { - showRemoveSafe: false, - menuOptionIndex: 1, - } + const handleChange = (menuOptionIndex) => () => { + setState((prevState) => ({ ...prevState, menuOptionIndex })) } - handleChange = (menuOptionIndex) => () => { - this.setState({ menuOptionIndex }) + const onShow = (action: Action) => () => { + setState((prevState) => ({ ...prevState, [`show${action}`]: true })) } - onShow = (action: Action) => () => { - this.setState(() => ({ [`show${action}`]: true })) + const onHide = (action: Action) => () => { + setState((prevState) => ({ ...prevState, [`show${action}`]: false })) } - onHide = (action: Action) => () => { - this.setState(() => ({ [`show${action}`]: false })) - } + const { menuOptionIndex, showRemoveSafe } = state + const { classes } = props - render() { - const { menuOptionIndex, showRemoveSafe } = this.state - const { - addSafeOwner, - addressBook, - classes, - createTransaction, - editSafeOwner, - etherScanLink, - granted, - network, - owners, - removeSafeOwner, - replaceSafeOwner, - safe, - safeAddress, - safeName, - threshold, - updateAddressBookEntry, - updateSafe, - userAddress, - } = this.props - - return ( - <> - - - Remove Safe - Trash Icon - - - - - - - + ) : ( + <> + + + Remove Safe + Trash Icon + + + + + + + + + - - - Safe details - - - - - - Owners - - {owners.size} - - - - - - Policies - - - - - - - {menuOptionIndex === 1 && ( - - )} - {menuOptionIndex === 2 && ( - - )} - {menuOptionIndex === 3 && ( - - )} - - - - - ) - } + Safe details + + + + + + Owners + + {owners.size} + + + + + + Policies + + + + + + + {menuOptionIndex === 1 && } + {menuOptionIndex === 2 && } + {menuOptionIndex === 3 && } + + + + + ) } -const settingsComponent = withStyles(styles)(Settings) - -export default connect(undefined, actions)(settingsComponent) +export default withStyles(styles)(Settings) diff --git a/src/routes/safe/components/Settings/style.js b/src/routes/safe/components/Settings/style.js index f9017b74..7a246c80 100644 --- a/src/routes/safe/components/Settings/style.js +++ b/src/routes/safe/components/Settings/style.js @@ -119,7 +119,6 @@ export const styles = () => ({ position: 'relative', }, message: { - margin: `${sm} 0`, padding: `${md} 0`, maxHeight: '54px', // to make it the same as row in Balances component boxSizing: 'border-box', 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 fbde98e1..472637fe 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/ApproveTxModal/index.jsx +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/ApproveTxModal/index.jsx @@ -6,6 +6,7 @@ import { withStyles } from '@material-ui/core/styles' import Close from '@material-ui/icons/Close' import { withSnackbar } from 'notistack' import React, { useEffect, useState } from 'react' +import { useDispatch, useSelector } from 'react-redux' import { styles } from './style' @@ -20,7 +21,10 @@ import { TX_NOTIFICATION_TYPES } from '~/logic/safe/transactions' import { estimateTxGasCosts } from '~/logic/safe/transactions/gasNew' import { formatAmount } from '~/logic/tokens/utils/formatAmount' import { getWeb3 } from '~/logic/wallets/getWeb3' +import { userAccountSelector } from '~/logic/wallets/store/selectors' +import processTransaction from '~/routes/safe/store/actions/processTransaction' import { type Transaction } from '~/routes/safe/store/models/transaction' +import { safeParamAddressFromStateSelector, safeThresholdSelector } from '~/routes/safe/store/selectors' export const APPROVE_TX_MODAL_SUBMIT_BTN_TEST_ID = 'approve-tx-modal-submit-btn' export const REJECT_TX_MODAL_SUBMIT_BTN_TEST_ID = 'reject-tx-modal-submit-btn' @@ -30,13 +34,8 @@ type Props = { classes: Object, isOpen: boolean, isCancelTx?: boolean, - processTransaction: Function, tx: Transaction, - nonce: string, - safeAddress: string, - threshold: number, thresholdReached: boolean, - userAddress: string, canExecute: boolean, enqueueSnackbar: Function, closeSnackbar: Function, @@ -73,13 +72,13 @@ const ApproveTxModal = ({ isCancelTx, isOpen, onClose, - processTransaction, - safeAddress, - threshold, thresholdReached, tx, - userAddress, }: Props) => { + const dispatch = useDispatch() + const userAddress = useSelector(userAccountSelector) + const threshold = useSelector(safeThresholdSelector) + const safeAddress = useSelector(safeParamAddressFromStateSelector) const [approveAndExecute, setApproveAndExecute] = useState(canExecute) const [gasCosts, setGasCosts] = useState('< 0.001') const { description, title } = getModalTitleAndDescription(thresholdReached, isCancelTx) @@ -117,15 +116,17 @@ const ApproveTxModal = ({ const handleExecuteCheckbox = () => setApproveAndExecute((prevApproveAndExecute) => !prevApproveAndExecute) const approveTx = () => { - processTransaction({ - safeAddress, - tx, - userAddress, - notifiedTransaction: TX_NOTIFICATION_TYPES.CONFIRMATION_TX, - enqueueSnackbar, - closeSnackbar, - approveAndExecute: canExecute && approveAndExecute && isTheTxReadyToBeExecuted, - }) + dispatch( + processTransaction({ + safeAddress, + tx, + userAddress, + notifiedTransaction: TX_NOTIFICATION_TYPES.CONFIRMATION_TX, + enqueueSnackbar, + closeSnackbar, + approveAndExecute: canExecute && approveAndExecute && isTheTxReadyToBeExecuted, + }), + ) onClose() } diff --git a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/OwnersColumn/index.jsx b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/OwnersColumn/index.jsx index 054e8234..524e29fb 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/OwnersColumn/index.jsx +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/OwnersColumn/index.jsx @@ -1,8 +1,8 @@ // @flow import { withStyles } from '@material-ui/core/styles' import cn from 'classnames' -import { List } from 'immutable' import React from 'react' +import { useSelector } from 'react-redux' import OwnersList from './OwnersList' import CheckLargeFilledGreenCircle from './assets/check-large-filled-green.svg' @@ -17,8 +17,9 @@ import Col from '~/components/layout/Col' import Img from '~/components/layout/Img' import Paragraph from '~/components/layout/Paragraph/index' import { TX_TYPE_CONFIRMATION } from '~/logic/safe/transactions/send' -import { type Owner } from '~/routes/safe/store/models/owner' +import { userAccountSelector } from '~/logic/wallets/store/selectors' import { type Transaction, makeTransaction } from '~/routes/safe/store/models/transaction' +import { safeOwnersSelector, safeThresholdSelector } from '~/routes/safe/store/selectors' type Props = { canExecute: boolean, @@ -29,11 +30,8 @@ type Props = { onTxReject: Function, onTxConfirm: Function, onTxExecute: Function, - owners: List, - threshold: number, thresholdReached: boolean, tx: Transaction, - userAddress: string, } function getOwnersConfirmations(tx, userAddress) { @@ -71,10 +69,7 @@ function getPendingOwnersConfirmations(owners, tx, userAddress) { const OwnersColumn = ({ tx, cancelTx = makeTransaction(), - owners, classes, - threshold, - userAddress, thresholdReached, cancelThresholdReached, onTxConfirm, @@ -90,7 +85,9 @@ const OwnersColumn = ({ } else { showOlderTxAnnotation = (thresholdReached && !canExecute) || (cancelThresholdReached && !canExecuteCancel) } - + const owners = useSelector(safeOwnersSelector) + const threshold = useSelector(safeThresholdSelector) + const userAddress = useSelector(userAccountSelector) const [ownersWhoConfirmed, currentUserAlreadyConfirmed] = getOwnersConfirmations(tx, userAddress) const [ownersUnconfirmed, userIsUnconfirmedOwner] = getPendingOwnersConfirmations(owners, tx, userAddress) const [ownersWhoConfirmedCancel, currentUserAlreadyConfirmedCancel] = getOwnersConfirmations(cancelTx, userAddress) diff --git a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/OwnersColumn/style.js b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/OwnersColumn/style.js index 1e91c63b..3250f993 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/OwnersColumn/style.js +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/OwnersColumn/style.js @@ -19,7 +19,7 @@ export const styles = () => ({ position: 'absolute', top: '-27px', width: '2px', - zIndex: '10', + zIndex: '12', }, verticalLinePending: { backgroundColor: secondaryText, @@ -78,7 +78,7 @@ export const styles = () => ({ justifyContent: 'center', marginRight: '18px', width: '20px', - zIndex: '100', + zIndex: '13', '& > img': { display: 'block', diff --git a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/RejectTxModal/index.jsx b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/RejectTxModal/index.jsx index 0a408207..980e1f95 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/RejectTxModal/index.jsx +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/RejectTxModal/index.jsx @@ -4,6 +4,7 @@ import { withStyles } from '@material-ui/core/styles' import Close from '@material-ui/icons/Close' import { withSnackbar } from 'notistack' import React, { useEffect, useState } from 'react' +import { useDispatch, useSelector } from 'react-redux' import { styles } from './style' @@ -19,31 +20,23 @@ import { estimateTxGasCosts } from '~/logic/safe/transactions/gasNew' import { formatAmount } from '~/logic/tokens/utils/formatAmount' import { EMPTY_DATA } from '~/logic/wallets/ethTransactions' import { getWeb3 } from '~/logic/wallets/getWeb3' +import createTransaction from '~/routes/safe/store/actions/createTransaction' import { type Transaction } from '~/routes/safe/store/models/transaction' +import { safeParamAddressFromStateSelector } from '~/routes/safe/store/selectors' type Props = { onClose: () => void, classes: Object, isOpen: boolean, - createTransaction: Function, tx: Transaction, - safeAddress: string, enqueueSnackbar: Function, closeSnackbar: Function, } -const RejectTxModal = ({ - classes, - closeSnackbar, - createTransaction, - enqueueSnackbar, - isOpen, - onClose, - safeAddress, - tx, -}: Props) => { +const RejectTxModal = ({ classes, closeSnackbar, enqueueSnackbar, isOpen, onClose, tx }: Props) => { const [gasCosts, setGasCosts] = useState('< 0.001') - + const dispatch = useDispatch() + const safeAddress = useSelector(safeParamAddressFromStateSelector) useEffect(() => { let isCurrent = true const estimateGasCosts = async () => { @@ -66,16 +59,18 @@ const RejectTxModal = ({ }, []) const sendReplacementTransaction = () => { - createTransaction({ - safeAddress, - to: safeAddress, - valueInWei: 0, - notifiedTransaction: TX_NOTIFICATION_TYPES.CANCELLATION_TX, - enqueueSnackbar, - closeSnackbar, - txNonce: tx.nonce, - origin: tx.origin, - }) + dispatch( + createTransaction({ + safeAddress, + to: safeAddress, + valueInWei: 0, + notifiedTransaction: TX_NOTIFICATION_TYPES.CANCELLATION_TX, + enqueueSnackbar, + closeSnackbar, + txNonce: tx.nonce, + origin: tx.origin, + }), + ) onClose() } diff --git a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/index.jsx b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/index.jsx index 3fdc384a..fdaaeee3 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/index.jsx +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/index.jsx @@ -1,8 +1,8 @@ // @flow import { makeStyles } from '@material-ui/core/styles' import cn from 'classnames' -import { List } from 'immutable' import React, { useState } from 'react' +import { useSelector } from 'react-redux' import { formatDate } from '../columns' @@ -22,39 +22,22 @@ 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_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' +import { safeNonceSelector, safeThresholdSelector } from '~/routes/safe/store/selectors' type Props = { tx: Transaction, cancelTx: Transaction, - threshold: number, - owners: List, - granted: boolean, - userAddress: string, - safeAddress: string, - createTransaction: Function, - processTransaction: Function, - nonce: number, } type OpenModal = 'rejectTx' | 'approveTx' | 'executeRejectTx' | null const useStyles = makeStyles(styles) -const ExpandedTx = ({ - cancelTx, - createTransaction, - granted, - nonce, - owners, - processTransaction, - safeAddress, - threshold, - tx, - userAddress, -}: Props) => { +const ExpandedTx = ({ cancelTx, tx }: Props) => { const classes = useStyles() + const nonce = useSelector(safeNonceSelector) + const threshold = useSelector(safeThresholdSelector) const [openModal, setOpenModal] = useState(null) const openApproveModal = () => setOpenModal('approveTx') const closeModal = () => setOpenModal(null) @@ -138,16 +121,11 @@ const ExpandedTx = ({ cancelTx={cancelTx} canExecute={canExecute} canExecuteCancel={canExecuteCancel} - granted={granted} onTxConfirm={openApproveModal} onTxExecute={openApproveModal} onTxReject={openRejectModal} - owners={owners} - safeAddress={safeAddress} - threshold={threshold} thresholdReached={thresholdReached} tx={tx} - userAddress={userAddress} /> )} @@ -157,35 +135,19 @@ const ExpandedTx = ({ canExecute={canExecute} isOpen onClose={closeModal} - processTransaction={processTransaction} - safeAddress={safeAddress} - threshold={threshold} thresholdReached={thresholdReached} tx={tx} - userAddress={userAddress} - /> - )} - {openModal === 'rejectTx' && ( - )} + {openModal === 'rejectTx' && } {openModal === 'executeRejectTx' && ( )} diff --git a/src/routes/safe/components/Transactions/TxsTable/TxType/index.jsx b/src/routes/safe/components/Transactions/TxsTable/TxType/index.jsx index 060ba740..fcb79665 100644 --- a/src/routes/safe/components/Transactions/TxsTable/TxType/index.jsx +++ b/src/routes/safe/components/Transactions/TxsTable/TxType/index.jsx @@ -31,26 +31,30 @@ const typeToLabel = { } const TxType = ({ origin, txType }: { txType: TransactionType, origin: string | null }) => { - const isThirdPartyApp = txType === 'third-party-app' const [loading, setLoading] = useState(true) const [appInfo, setAppInfo] = useState() + const [forceCustom, setForceCustom] = useState(false) useEffect(() => { const getAppInfo = async () => { const parsedOrigin = getAppInfoFromOrigin(origin) + if (!parsedOrigin) { + setForceCustom(true) + return + } const appInfo = await getAppInfoFromUrl(parsedOrigin.url) setAppInfo(appInfo) setLoading(false) } - if (!isThirdPartyApp) { + if (!origin) { return } getAppInfo() }, [txType]) - if (!isThirdPartyApp) { + if (forceCustom || !origin) { return } diff --git a/src/routes/safe/components/Transactions/TxsTable/columns.js b/src/routes/safe/components/Transactions/TxsTable/columns.js index 80b576ad..925d6bc0 100644 --- a/src/routes/safe/components/Transactions/TxsTable/columns.js +++ b/src/routes/safe/components/Transactions/TxsTable/columns.js @@ -8,6 +8,7 @@ import TxType from './TxType' import { type Column } from '~/components/Table/TableHead' import { type SortRow, buildOrderFieldFrom } from '~/components/Table/sorting' +import { formatAmount } from '~/logic/tokens/utils/formatAmount' import { getWeb3 } from '~/logic/wallets/getWeb3' import { INCOMING_TX_TYPES, type IncomingTransaction } from '~/routes/safe/store/models/incomingTransaction' import { type Transaction } from '~/routes/safe/store/models/transaction' @@ -46,7 +47,11 @@ export const getTxAmount = (tx: Transaction) => { if (tx.isTokenTransfer && tx.decodedParams) { const tokenDecimals = tx.decimals.toNumber ? tx.decimals.toNumber() : tx.decimals - txAmount = `${new BigNumber(tx.decodedParams.value).div(10 ** tokenDecimals).toString()} ${tx.symbol}` + txAmount = `${formatAmount( + BigNumber(tx.decodedParams.value) + .div(10 ** tokenDecimals) + .toString(), + )} ${tx.symbol}` } else if (Number(tx.value) > 0) { txAmount = `${fromWei(toBN(tx.value), 'ether')} ${tx.symbol}` } @@ -75,7 +80,7 @@ const getTransactionTableData = (tx: Transaction, cancelTx: ?Transaction): Trans } else if (tx.cancellationTx) { txType = 'cancellation' } else if (tx.customTx) { - txType = tx.origin ? 'third-party-app' : 'custom' + txType = 'custom' } else if (tx.creationTx) { txType = 'creation' } else if (tx.upgradeTx) { diff --git a/src/routes/safe/components/Transactions/TxsTable/index.jsx b/src/routes/safe/components/Transactions/TxsTable/index.jsx index 6745c643..f1358261 100644 --- a/src/routes/safe/components/Transactions/TxsTable/index.jsx +++ b/src/routes/safe/components/Transactions/TxsTable/index.jsx @@ -8,8 +8,8 @@ import { withStyles } from '@material-ui/core/styles' import ExpandLess from '@material-ui/icons/ExpandLess' import ExpandMore from '@material-ui/icons/ExpandMore' import cn from 'classnames' -import { List } from 'immutable' import React, { useState } from 'react' +import { useSelector } from 'react-redux' import ExpandedTxComponent from './ExpandedTx' import Status from './Status' @@ -27,9 +27,8 @@ import Table from '~/components/Table' import { type Column, cellWidth } from '~/components/Table/TableHead' import Block from '~/components/layout/Block' import Row from '~/components/layout/Row' -import type { IncomingTransaction } from '~/routes/safe/store/models/incomingTransaction' -import { type Owner } from '~/routes/safe/store/models/owner' -import { type Transaction } from '~/routes/safe/store/models/transaction' +import { extendedTransactionsSelector } from '~/routes/safe/container/selector' +import { safeCancellationTransactionsSelector } from '~/routes/safe/store/selectors' export const TRANSACTION_ROW_TEST_ID = 'transaction-row' @@ -40,32 +39,12 @@ const expandCellStyle = { type Props = { classes: Object, - transactions: List, - cancellationTransactions: List, - threshold: number, - owners: List, - userAddress: string, - granted: boolean, - safeAddress: string, - nonce: number, - createTransaction: Function, - processTransaction: Function, } -const TxsTable = ({ - cancellationTransactions, - classes, - createTransaction, - granted, - nonce, - owners, - processTransaction, - safeAddress, - threshold, - transactions, - userAddress, -}: Props) => { +const TxsTable = ({ classes }: Props) => { const [expandedTx, setExpandedTx] = useState(null) + const cancellationTransactions = useSelector(safeCancellationTransactionsSelector) + const transactions = useSelector(extendedTransactionsSelector) const handleTxExpand = (safeTxHash) => { setExpandedTx((prevTx) => (prevTx === safeTxHash ? null : safeTxHash)) @@ -156,18 +135,10 @@ const TxsTable = ({ diff --git a/src/routes/safe/components/Transactions/TxsTable/style.js b/src/routes/safe/components/Transactions/TxsTable/style.js index 730fc7b6..9b0550d3 100644 --- a/src/routes/safe/components/Transactions/TxsTable/style.js +++ b/src/routes/safe/components/Transactions/TxsTable/style.js @@ -1,7 +1,7 @@ // @flow export const styles = () => ({ container: { - marginTop: '70px', + marginTop: '56px', }, row: { cursor: 'pointer', diff --git a/src/routes/safe/components/Transactions/index.jsx b/src/routes/safe/components/Transactions/index.jsx deleted file mode 100644 index 386df602..00000000 --- a/src/routes/safe/components/Transactions/index.jsx +++ /dev/null @@ -1,52 +0,0 @@ -// @flow -import { List } from 'immutable' -import React from 'react' - -import TxsTable from '~/routes/safe/components/Transactions/TxsTable' -import { type IncomingTransaction } from '~/routes/safe/store/models/incomingTransaction' -import { type Owner } from '~/routes/safe/store/models/owner' -import { type Transaction } from '~/routes/safe/store/models/transaction' - -type Props = { - safeAddress: string, - threshold: number, - transactions: List, - cancellationTransactions: List, - owners: List, - userAddress: string, - granted: boolean, - createTransaction: Function, - processTransaction: Function, - currentNetwork: string, - nonce: number, -} - -const Transactions = ({ - transactions = List(), - cancellationTransactions = List(), - owners, - threshold, - userAddress, - granted, - safeAddress, - createTransaction, - processTransaction, - currentNetwork, - nonce, -}: Props) => ( - -) - -export default Transactions diff --git a/src/routes/safe/container/Hooks/useCheckForUpdates.jsx b/src/routes/safe/container/Hooks/useCheckForUpdates.jsx new file mode 100644 index 00000000..6cfdc4bb --- /dev/null +++ b/src/routes/safe/container/Hooks/useCheckForUpdates.jsx @@ -0,0 +1,32 @@ +// @flow +import { useEffect } from 'react' +import { batch, useDispatch, useSelector } from 'react-redux' + +import fetchCollectibles from '~/logic/collectibles/store/actions/fetchCollectibles' +import fetchSafeTokens from '~/logic/tokens/store/actions/fetchSafeTokens' +import fetchEtherBalance from '~/routes/safe/store/actions/fetchEtherBalance' +import { checkAndUpdateSafe } from '~/routes/safe/store/actions/fetchSafe' +import fetchTransactions from '~/routes/safe/store/actions/fetchTransactions' +import { safeParamAddressFromStateSelector } from '~/routes/safe/store/selectors' +import { TIMEOUT } from '~/utils/constants' + +export const useCheckForUpdates = () => { + const dispatch = useDispatch() + const safeAddress = useSelector(safeParamAddressFromStateSelector) + useEffect(() => { + if (safeAddress) { + const collectiblesInterval = setInterval(() => { + batch(() => { + dispatch(fetchEtherBalance(safeAddress)) + dispatch(fetchSafeTokens(safeAddress)) + dispatch(fetchTransactions(safeAddress)) + dispatch(fetchCollectibles) + dispatch(checkAndUpdateSafe(safeAddress)) + }) + }, TIMEOUT * 3) + return () => { + clearInterval(collectiblesInterval) + } + } + }, [safeAddress]) +} diff --git a/src/routes/safe/container/Hooks/useFetchTokens.jsx b/src/routes/safe/container/Hooks/useFetchTokens.jsx new file mode 100644 index 00000000..7065bf0e --- /dev/null +++ b/src/routes/safe/container/Hooks/useFetchTokens.jsx @@ -0,0 +1,30 @@ +// @flow +import { useMemo } from 'react' +import { batch, useDispatch, useSelector } from 'react-redux' + +import { fetchCurrencyValues } from '~/logic/currencyValues/store/actions/fetchCurrencyValues' +import activateAssetsByBalance from '~/logic/tokens/store/actions/activateAssetsByBalance' +import fetchSafeTokens from '~/logic/tokens/store/actions/fetchSafeTokens' +import { fetchTokens } from '~/logic/tokens/store/actions/fetchTokens' +import { COINS_LOCATION_REGEX, COLLECTIBLES_LOCATION_REGEX } from '~/routes/safe/components/Balances' +import { safeParamAddressFromStateSelector } from '~/routes/safe/store/selectors' +import { history } from '~/store' + +export const useFetchTokens = () => { + const dispatch = useDispatch() + const address = useSelector(safeParamAddressFromStateSelector) + useMemo(() => { + if (COINS_LOCATION_REGEX.test(history.location.pathname)) { + batch(() => { + // fetch tokens there to get symbols for tokens in TXs list + dispatch(fetchTokens()) + dispatch(fetchCurrencyValues(address)) + dispatch(fetchSafeTokens(address)) + }) + } + + if (COLLECTIBLES_LOCATION_REGEX.test(history.location.pathname)) { + dispatch(activateAssetsByBalance(address)) + } + }, [history.location.pathname]) +} diff --git a/src/routes/safe/container/Hooks/useLoadSafe.jsx b/src/routes/safe/container/Hooks/useLoadSafe.jsx new file mode 100644 index 00000000..31c12110 --- /dev/null +++ b/src/routes/safe/container/Hooks/useLoadSafe.jsx @@ -0,0 +1,30 @@ +// @flow +import { useEffect } from 'react' +import { useDispatch } from 'react-redux' + +import loadAddressBookFromStorage from '~/logic/addressBook/store/actions/loadAddressBookFromStorage' +import addViewedSafe from '~/logic/currentSession/store/actions/addViewedSafe' +import fetchSafeTokens from '~/logic/tokens/store/actions/fetchSafeTokens' +import fetchLatestMasterContractVersion from '~/routes/safe/store/actions/fetchLatestMasterContractVersion' +import fetchSafe from '~/routes/safe/store/actions/fetchSafe' +import fetchTransactions from '~/routes/safe/store/actions/fetchTransactions' + +export const useLoadSafe = (safeAddress: ?string) => { + const dispatch = useDispatch() + + useEffect(() => { + const fetchData = () => { + if (safeAddress) { + dispatch(fetchLatestMasterContractVersion()) + .then(() => dispatch(fetchSafe(safeAddress))) + .then(() => { + dispatch(fetchSafeTokens(safeAddress)) + dispatch(loadAddressBookFromStorage()) + return dispatch(fetchTransactions(safeAddress)) + }) + .then(() => dispatch(addViewedSafe(safeAddress))) + } + } + fetchData() + }, [safeAddress]) +} diff --git a/src/routes/safe/container/actions.js b/src/routes/safe/container/actions.js deleted file mode 100644 index 4118b9fb..00000000 --- a/src/routes/safe/container/actions.js +++ /dev/null @@ -1,57 +0,0 @@ -// @flow -import loadAddressBookFromStorage from '~/logic/addressBook/store/actions/loadAddressBookFromStorage' -import { updateAddressBookEntry } from '~/logic/addressBook/store/actions/updateAddressBookEntry' -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' -import fetchEtherBalance from '~/routes/safe/store/actions/fetchEtherBalance' -import fetchLatestMasterContractVersion from '~/routes/safe/store/actions/fetchLatestMasterContractVersion' -import fetchSafe, { checkAndUpdateSafe } from '~/routes/safe/store/actions/fetchSafe' -import fetchTokenBalances from '~/routes/safe/store/actions/fetchTokenBalances' -import fetchTransactions from '~/routes/safe/store/actions/fetchTransactions' -import processTransaction from '~/routes/safe/store/actions/processTransaction' -import updateSafe from '~/routes/safe/store/actions/updateSafe' - -export type Actions = { - fetchSafe: typeof fetchSafe, - fetchTokenBalances: typeof fetchTokenBalances, - createTransaction: typeof createTransaction, - fetchTransactions: typeof fetchTransactions, - updateSafe: typeof updateSafe, - fetchCollectibles: typeof fetchCollectibles, - fetchTokens: typeof fetchTokens, - processTransaction: typeof processTransaction, - fetchEtherBalance: typeof fetchEtherBalance, - fetchLatestMasterContractVersion: typeof fetchLatestMasterContractVersion, - activateTokensByBalance: typeof activateTokensByBalance, - activateAssetsByBalance: typeof activateAssetsByBalance, - checkAndUpdateSafe: typeof checkAndUpdateSafe, - fetchCurrencyValues: typeof fetchCurrencyValues, - loadAddressBook: typeof loadAddressBookFromStorage, - updateAddressBookEntry: typeof updateAddressBookEntry, - addViewedSafe: typeof addViewedSafe, -} - -export default { - fetchSafe, - fetchTokenBalances, - createTransaction, - processTransaction, - fetchCollectibles, - fetchTokens, - fetchTransactions, - activateTokensByBalance, - activateAssetsByBalance, - updateSafe, - fetchEtherBalance, - fetchLatestMasterContractVersion, - fetchCurrencyValues, - checkAndUpdateSafe, - loadAddressBook: loadAddressBookFromStorage, - updateAddressBookEntry, - addViewedSafe, -} diff --git a/src/routes/safe/container/index.jsx b/src/routes/safe/container/index.jsx index 8f2cce7b..f4787a13 100644 --- a/src/routes/safe/container/index.jsx +++ b/src/routes/safe/container/index.jsx @@ -1,199 +1,79 @@ // @flow import * as React from 'react' -import { connect } from 'react-redux' - -import actions, { type Actions } from './actions' -import selector, { type SelectorProps } from './selector' +import { useState } from 'react' +import { useSelector } from 'react-redux' import Page from '~/components/layout/Page' import { type Token } from '~/logic/tokens/store/model/token' import Layout from '~/routes/safe/components/Layout' - -type State = { - showReceive: boolean, - sendFunds: Object, -} +import { useCheckForUpdates } from '~/routes/safe/container/Hooks/useCheckForUpdates' +import { useLoadSafe } from '~/routes/safe/container/Hooks/useLoadSafe' +import { safeParamAddressFromStateSelector } from '~/routes/safe/store/selectors' type Action = 'Send' | 'Receive' -export type Props = Actions & - SelectorProps & { - granted: boolean, +const INITIAL_STATE = { + sendFunds: { + isOpen: false, + selectedToken: undefined, + }, + showReceive: false, +} + +const SafeView = () => { + const [state, setState] = useState(INITIAL_STATE) + const safeAddress = useSelector(safeParamAddressFromStateSelector) + + useLoadSafe(safeAddress) + useCheckForUpdates() + + const onShow = (action: Action) => () => { + setState((prevState) => ({ + ...prevState, + [`show${action}`]: true, + })) } -const TIMEOUT = process.env.NODE_ENV === 'test' ? 1500 : 5000 - -class SafeView extends React.Component { - state = { - sendFunds: { - isOpen: false, - selectedToken: undefined, - }, - showReceive: false, + const onHide = (action: Action) => () => { + setState((prevState) => ({ + ...prevState, + [`show${action}`]: false, + })) } - intervalId: IntervalID - - longIntervalId: IntervalID - - componentDidMount() { - const { - activeTokens, - addViewedSafe, - fetchCollectibles, - fetchCurrencyValues, - fetchLatestMasterContractVersion, - fetchSafe, - fetchTokenBalances, - fetchTokens, - fetchTransactions, - loadAddressBook, - safeUrl, - } = this.props - - fetchLatestMasterContractVersion() - .then(() => fetchSafe(safeUrl)) - .then(() => { - // The safe needs to be loaded before fetching the transactions - fetchTransactions(safeUrl) - addViewedSafe(safeUrl) - fetchCollectibles() - }) - fetchTokenBalances(safeUrl, activeTokens) - // fetch tokens there to get symbols for tokens in TXs list - fetchTokens() - fetchCurrencyValues(safeUrl) - loadAddressBook() - - this.intervalId = setInterval(() => { - this.checkForUpdates() - }, TIMEOUT) - - this.longIntervalId = setInterval(() => { - fetchCollectibles() - }, TIMEOUT * 3) - } - - componentDidUpdate(prevProps) { - const { activeTokens, fetchTransactions, safeUrl } = this.props - const oldActiveTokensSize = prevProps.activeTokens.size - - if (oldActiveTokensSize > 0 && activeTokens.size > oldActiveTokensSize) { - this.checkForUpdates() - } - - if (safeUrl !== prevProps.safeUrl) { - fetchTransactions(safeUrl) - } - } - - componentWillUnmount() { - clearInterval(this.intervalId) - clearInterval(this.longIntervalId) - } - - onShow = (action: Action) => () => { - this.setState(() => ({ [`show${action}`]: true })) - } - - onHide = (action: Action) => () => { - this.setState(() => ({ [`show${action}`]: false })) - } - - showSendFunds = (token: Token) => { - this.setState({ + const showSendFunds = (token: Token) => { + setState((prevState) => ({ + ...prevState, sendFunds: { isOpen: true, selectedToken: token, }, - }) + })) } - hideSendFunds = () => { - this.setState({ + const hideSendFunds = () => { + setState((prevState) => ({ + ...prevState, sendFunds: { isOpen: false, selectedToken: undefined, }, - }) + })) } + const { sendFunds, showReceive } = state - checkForUpdates() { - const { - activeTokens, - checkAndUpdateSafe, - fetchEtherBalance, - fetchTokenBalances, - fetchTransactions, - safe, - safeUrl, - } = this.props - checkAndUpdateSafe(safeUrl) - fetchTokenBalances(safeUrl, activeTokens) - fetchEtherBalance(safe) - fetchTransactions(safeUrl) - } - - render() { - const { sendFunds, showReceive } = this.state - const { - activateAssetsByBalance, - activateTokensByBalance, - activeTokens, - addressBook, - blacklistedTokens, - cancellationTransactions, - createTransaction, - currencySelected, - currencyValues, - fetchCurrencyValues, - fetchTokens, - granted, - network, - processTransaction, - provider, - safe, - tokens, - transactions, - updateAddressBookEntry, - updateSafe, - userAddress, - } = this.props - - return ( - - - - ) - } + return ( + + + + ) } -export default connect(selector, actions)(SafeView) +export default SafeView diff --git a/src/routes/safe/container/selector.js b/src/routes/safe/container/selector.js index cfb16f39..54cabdeb 100644 --- a/src/routes/safe/container/selector.js +++ b/src/routes/safe/container/selector.js @@ -1,27 +1,19 @@ // @flow import { List, Map } from 'immutable' -import { type Selector, createSelector, createStructuredSelector } from 'reselect' +import { type Selector, createSelector } from 'reselect' -import { safeParamAddressSelector } from '../store/selectors' - -import type { AddressBook } from '~/logic/addressBook/model/addressBook' -import { getAddressBook } from '~/logic/addressBook/store/selectors' -import type { BalanceCurrencyType } from '~/logic/currencyValues/store/model/currencyValues' -import { currencyValuesListSelector, currentCurrencySelector } from '~/logic/currencyValues/store/selectors' import { type Token } from '~/logic/tokens/store/model/token' -import { orderedTokenListSelector, tokensSelector } from '~/logic/tokens/store/selectors' +import { tokensSelector } from '~/logic/tokens/store/selectors' import { getEthAsToken } from '~/logic/tokens/utils/tokenHelpers' import { isUserOwner } from '~/logic/wallets/ethAddresses' -import { networkSelector, providerNameSelector, userAccountSelector } from '~/logic/wallets/store/selectors' +import { userAccountSelector } from '~/logic/wallets/store/selectors' import type { IncomingTransaction } from '~/routes/safe/store/models/incomingTransaction' import { type Safe } from '~/routes/safe/store/models/safe' import { type Transaction, type TransactionStatus } from '~/routes/safe/store/models/transaction' import { type RouterProps, - type SafeSelectorProps, safeActiveTokensSelector, safeBalancesSelector, - safeBlacklistedTokensSelector, safeCancellationTransactionsSelector, safeIncomingTransactionsSelector, safeSelector, @@ -29,22 +21,6 @@ import { } from '~/routes/safe/store/selectors' import { type GlobalState } from '~/store' -export type SelectorProps = { - safe: SafeSelectorProps, - provider: string, - tokens: List, - activeTokens: List, - blacklistedTokens: List, - userAddress: string, - network: string, - safeUrl: string, - currencySelected: string, - currencyValues: BalanceCurrencyType[], - transactions: List, - cancellationTransactions: List, - addressBook: AddressBook, -} - const getTxStatus = (tx: Transaction, userAddress: string, safe: Safe): TransactionStatus => { let txStatus if (tx.executionTxHash) { @@ -112,7 +88,7 @@ export const extendedSafeTokensSelector: Selector, @@ -143,20 +119,3 @@ const extendedTransactionsSelector: Selector< return List([...extendedTransactions, ...incomingTransactions]) }, ) - -export default createStructuredSelector({ - safe: safeSelector, - provider: providerNameSelector, - tokens: orderedTokenListSelector, - activeTokens: extendedSafeTokensSelector, - blacklistedTokens: safeBlacklistedTokensSelector, - granted: grantedSelector, - userAddress: userAccountSelector, - network: networkSelector, - safeUrl: safeParamAddressSelector, - transactions: extendedTransactionsSelector, - cancellationTransactions: safeCancellationTransactionsSelector, - currencySelected: currentCurrencySelector, - currencyValues: currencyValuesListSelector, - addressBook: getAddressBook, -}) diff --git a/src/routes/safe/store/actions/createTransaction.js b/src/routes/safe/store/actions/createTransaction.js index cbb2d200..2cd32ba6 100644 --- a/src/routes/safe/store/actions/createTransaction.js +++ b/src/routes/safe/store/actions/createTransaction.js @@ -13,6 +13,7 @@ import { getExecutionTransaction, saveTxToHistory, } from '~/logic/safe/transactions' +import { estimateSafeTxGas } from '~/logic/safe/transactions/gasNew' 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' @@ -66,6 +67,7 @@ const createTransaction = ({ const nonce = await getNewTxNonce(txNonce, lastTx, safeInstance) const isExecution = await shouldExecuteTransaction(safeInstance, nonce, lastTx) const safeVersion = await getCurrentSafeVersion(safeInstance) + const safeTxGas = await estimateSafeTxGas(safeInstance, safeAddress, txData, to, valueInWei, operation) // https://docs.gnosis.io/safe/docs/docs5/#pre-validated-signatures const sigs = `0x000000000000000000000000${from.replace( @@ -86,7 +88,7 @@ const createTransaction = ({ data: txData, operation, nonce, - safeTxGas: 0, + safeTxGas, baseGas: 0, gasPrice: 0, gasToken: ZERO_ADDRESS, @@ -125,11 +127,6 @@ const createTransaction = ({ const sendParams = { from, value: 0 } - // TODO find a better solution for this in dev and production. - if (process.env.REACT_APP_ENV !== 'production') { - sendParams.gasLimit = 1000000 - } - // if not set owner management tests will fail on ganache if (process.env.NODE_ENV === 'test') { sendParams.gas = '7000000' diff --git a/src/routes/safe/store/actions/fetchEtherBalance.js b/src/routes/safe/store/actions/fetchEtherBalance.js index 9fdb8519..634cd053 100644 --- a/src/routes/safe/store/actions/fetchEtherBalance.js +++ b/src/routes/safe/store/actions/fetchEtherBalance.js @@ -3,16 +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 { Safe } from '~/routes/safe/store/models/safe' +import { SAFE_REDUCER_ID } from '~/routes/safe/store/reducer/safe' +import type { GetState } from '~/store' import { type GlobalState } from '~/store' -const fetchEtherBalance = (safe: Safe) => async (dispatch: ReduxDispatch) => { +const fetchEtherBalance = (safeAddress: string) => async (dispatch: ReduxDispatch, getState: GetState) => { try { - const { address, ethBalance } = safe - const newEthBalance = await getBalanceInEtherOf(address) - + const state = getState() + const ethBalance = state[SAFE_REDUCER_ID].getIn([SAFE_REDUCER_ID, safeAddress, 'ethBalance']) + const newEthBalance = await getBalanceInEtherOf(safeAddress) if (newEthBalance !== ethBalance) { - dispatch(updateSafe({ address, ethBalance: newEthBalance })) + dispatch(updateSafe({ address: safeAddress, ethBalance: newEthBalance })) } } catch (err) { // eslint-disable-next-line diff --git a/src/routes/safe/store/actions/fetchSafe.js b/src/routes/safe/store/actions/fetchSafe.js index 76b21bb1..df9b29f3 100644 --- a/src/routes/safe/store/actions/fetchSafe.js +++ b/src/routes/safe/store/actions/fetchSafe.js @@ -1,8 +1,9 @@ // @flow +import GnosisSafeSol from '@gnosis.pm/safe-contracts/build/contracts/GnosisSafe.json' import { List } from 'immutable' import type { Dispatch as ReduxDispatch } from 'redux' -import { getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts' +import generateBatchRequests from '~/logic/contracts/generateBatchRequests' import { getLocalSafe, getSafeName } from '~/logic/safe/utils' import { enabledFeatures, safeNeedsUpdate } from '~/logic/safe/utils/safeVersion' import { sameAddress } from '~/logic/wallets/ethAddresses' @@ -13,7 +14,7 @@ import removeSafeOwner from '~/routes/safe/store/actions/removeSafeOwner' import updateSafe from '~/routes/safe/store/actions/updateSafe' import { makeOwner } from '~/routes/safe/store/models/owner' import type { SafeProps } from '~/routes/safe/store/models/safe' -import { type GlobalState } from '~/store/index' +import { type GlobalState } from '~/store' const buildOwnersFrom = ( safeOwners: string[], @@ -37,14 +38,22 @@ const buildOwnersFrom = ( export const buildSafe = async (safeAdd: string, safeName: string, latestMasterContractVersion: string) => { const safeAddress = getWeb3().utils.toChecksumAddress(safeAdd) - const gnosisSafe = await getGnosisSafeInstanceAt(safeAddress) - const ethBalance = await getBalanceInEtherOf(safeAddress) - const threshold = Number(await gnosisSafe.getThreshold()) - const nonce = Number(await gnosisSafe.nonce()) - const owners = List(buildOwnersFrom(await gnosisSafe.getOwners(), await getLocalSafe(safeAddress))) - const currentVersion = await gnosisSafe.VERSION() - const needsUpdate = await safeNeedsUpdate(currentVersion, latestMasterContractVersion) + const safeParams = ['getThreshold', 'nonce', 'VERSION', 'getOwners'] + const [[thresholdStr, nonceStr, currentVersion, remoteOwners], localSafe, ethBalance] = await Promise.all([ + generateBatchRequests({ + abi: GnosisSafeSol.abi, + address: safeAddress, + methods: safeParams, + }), + getLocalSafe(safeAddress), + getBalanceInEtherOf(safeAddress), + ]) + + const threshold = Number(thresholdStr) + const nonce = Number(nonceStr) + const owners = List(buildOwnersFrom(remoteOwners, localSafe)) + const needsUpdate = safeNeedsUpdate(currentVersion, latestMasterContractVersion) const featuresEnabled = enabledFeatures(currentVersion) const safe: SafeProps = { @@ -65,24 +74,27 @@ export const buildSafe = async (safeAdd: string, safeName: string, latestMasterC export const checkAndUpdateSafe = (safeAdd: string) => async (dispatch: ReduxDispatch<*>) => { const safeAddress = getWeb3().utils.toChecksumAddress(safeAdd) // Check if the owner's safe did change and update them - const [gnosisSafe, localSafe] = await Promise.all([getGnosisSafeInstanceAt(safeAddress), getLocalSafe(safeAddress)]) - - const [remoteOwners, remoteNonce, remoteThreshold] = await Promise.all([ - gnosisSafe.getOwners(), - gnosisSafe.nonce(), - gnosisSafe.getThreshold(), + const safeParams = ['getThreshold', 'nonce', 'getOwners'] + const [[remoteThreshold, remoteNonce, remoteOwners], localSafe] = await Promise.all([ + generateBatchRequests({ + abi: GnosisSafeSol.abi, + address: safeAddress, + methods: safeParams, + }), + getLocalSafe(safeAddress), ]) + // Converts from [ { address, ownerName} ] to address array const localOwners = localSafe ? localSafe.owners.map((localOwner) => localOwner.address) : undefined const localThreshold = localSafe ? localSafe.threshold : undefined const localNonce = localSafe ? localSafe.nonce : undefined - if (localNonce !== remoteNonce.toNumber()) { - dispatch(updateSafe({ address: safeAddress, nonce: remoteNonce.toNumber() })) + if (localNonce !== Number(remoteNonce)) { + dispatch(updateSafe({ address: safeAddress, nonce: Number(remoteNonce) })) } - if (localThreshold !== remoteThreshold.toNumber()) { - dispatch(updateSafe({ address: safeAddress, threshold: remoteThreshold.toNumber() })) + if (localThreshold !== Number(remoteThreshold)) { + dispatch(updateSafe({ address: safeAddress, threshold: Number(remoteThreshold) })) } // If the remote owners does not contain a local address, we remove that local owner diff --git a/src/routes/safe/store/actions/fetchTokenBalances.js b/src/routes/safe/store/actions/fetchTokenBalances.js deleted file mode 100644 index ed8a0174..00000000 --- a/src/routes/safe/store/actions/fetchTokenBalances.js +++ /dev/null @@ -1,102 +0,0 @@ -// @flow -import { BigNumber } from 'bignumber.js' -import { List, Map } from 'immutable' -import type { Dispatch as ReduxDispatch } from 'redux' - -import updateSafe from './updateSafe' - -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) { - return '0' - } - const erc20Token = await getStandardTokenContract() - let balance = 0 - - try { - const token = await erc20Token.at(tokenAddress) - balance = await token.balanceOf(safeAddress) - } catch (err) { - console.error('Failed to fetch token balances: ', tokenAddress, err) - } - - return new BigNumber(balance).div(10 ** decimals).toString() -} - -const fetchTokenBalances = (safeAddress: string, tokens: List) => async ( - dispatch: ReduxDispatch, -) => { - if (!safeAddress || !tokens || !tokens.size) { - return - } - try { - const withBalances = await getTokenBalances(tokens, safeAddress) - - const balances = Map().withMutations((map) => { - withBalances.forEach(({ address, balance }) => { - map.set(address, balance) - }) - }) - - dispatch(updateSafe({ address: safeAddress, balances })) - } catch (err) { - console.error('Error when fetching token balances:', err) - } -} - -export default fetchTokenBalances diff --git a/src/routes/safe/store/actions/fetchTransactions.js b/src/routes/safe/store/actions/fetchTransactions.js index dd6413df..c9ef0d11 100644 --- a/src/routes/safe/store/actions/fetchTransactions.js +++ b/src/routes/safe/store/actions/fetchTransactions.js @@ -1,4 +1,5 @@ // @flow +import ERC20Detailed from '@openzeppelin/contracts/build/contracts/ERC20Detailed.json' import axios from 'axios' import bn from 'bignumber.js' import { List, Map, type RecordInstance } from 'immutable' @@ -8,15 +9,15 @@ import type { Dispatch as ReduxDispatch } from 'redux' import { addIncomingTransactions } from './addIncomingTransactions' import { addTransactions } from './addTransactions' +import generateBatchRequests from '~/logic/contracts/generateBatchRequests' 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 { getTokenInfos } from '~/logic/tokens/store/actions/fetchTokens' +import { TOKEN_REDUCER_ID } from '~/logic/tokens/store/reducer/tokens' import { ALTERNATIVE_TOKEN_ABI } from '~/logic/tokens/utils/alternativeAbi' import { SAFE_TRANSFER_FROM_WITHOUT_DATA_HASH, - hasDecimalsMethod, isMultisendTransaction, isTokenTransfer, isUpgradeTransaction, @@ -73,7 +74,15 @@ type IncomingTxServiceModel = { from: string, } -export const buildTransactionFrom = async (safeAddress: string, tx: TxServiceModel): Promise => { +export const buildTransactionFrom = async ( + safeAddress: string, + tx: TxServiceModel, + knownTokens, + txTokenDecimals, + txTokenSymbol, + txTokenName, + code, +): Promise => { const localSafe = await getLocalSafe(safeAddress) const confirmations = List( @@ -98,10 +107,9 @@ export const buildTransactionFrom = async (safeAddress: string, tx: TxServiceMod ) const modifySettingsTx = sameAddress(tx.to, safeAddress) && Number(tx.value) === 0 && !!tx.data const cancellationTx = sameAddress(tx.to, safeAddress) && Number(tx.value) === 0 && !tx.data - const code = tx.to ? await web3.eth.getCode(tx.to) : '' const isERC721Token = - code.includes(SAFE_TRANSFER_FROM_WITHOUT_DATA_HASH) || - (isTokenTransfer(tx.data, Number(tx.value)) && !(await hasDecimalsMethod(tx.to))) + (code && code.includes(SAFE_TRANSFER_FROM_WITHOUT_DATA_HASH)) || + (isTokenTransfer(tx.data, Number(tx.value)) && !knownTokens.get(tx.to) && txTokenDecimals !== null) let isSendTokenTx = !isERC721Token && isTokenTransfer(tx.data, Number(tx.value)) const isMultiSendTx = isMultisendTransaction(tx.data, Number(tx.value)) const isUpgradeTx = isMultiSendTx && isUpgradeTransaction(tx.data) @@ -109,14 +117,8 @@ export const buildTransactionFrom = async (safeAddress: string, tx: TxServiceMod let refundParams = null if (tx.gasPrice > 0) { - let refundSymbol = 'ETH' - let decimals = 18 - if (tx.gasToken !== ZERO_ADDRESS) { - const gasToken = await getTokenInfos(tx.gasToken) - refundSymbol = gasToken.symbol - decimals = gasToken.decimals - } - + const refundSymbol = txTokenSymbol || 'ETH' + const decimals = txTokenName || 18 const feeString = (tx.gasPrice * (tx.baseGas + tx.safeTxGas)).toString().padStart(decimals, 0) const whole = feeString.slice(0, feeString.length - decimals) || '0' const fraction = feeString.slice(feeString.length - decimals) @@ -128,23 +130,21 @@ export const buildTransactionFrom = async (safeAddress: string, tx: TxServiceMod } } - let symbol = 'ETH' - let decimals = 18 + let symbol = txTokenSymbol || 'ETH' + let decimals = txTokenDecimals || 18 let decodedParams if (isSendTokenTx) { - try { - const tokenInstance = await getTokenInfos(tx.to) - symbol = tokenInstance.symbol - decimals = tokenInstance.decimals - } catch (err) { + if (txTokenSymbol === null || txTokenDecimals === null) { try { - const alternativeTokenInstance = new web3.eth.Contract(ALTERNATIVE_TOKEN_ABI, tx.to) - const [tokenSymbol, tokenDecimals] = await Promise.all([ - alternativeTokenInstance.methods.symbol().call(), - alternativeTokenInstance.methods.decimals().call(), - ]) + const [tokenSymbol, tokenDecimals] = await Promise.all( + generateBatchRequests({ + abi: ALTERNATIVE_TOKEN_ABI, + address: tx.to, + methods: ['symbol', 'decimals'], + }), + ) - symbol = web3.utils.toAscii(tokenSymbol) + symbol = tokenSymbol decimals = tokenDecimals } catch (e) { // some contracts may implement the same methods as in ERC20 standard @@ -161,9 +161,9 @@ export const buildTransactionFrom = async (safeAddress: string, tx: TxServiceMod value: params[1], } } else if (modifySettingsTx && tx.data) { - decodedParams = await decodeParamsFromSafeMethod(tx.data) + decodedParams = decodeParamsFromSafeMethod(tx.data) } else if (customTx && tx.data) { - decodedParams = await decodeParamsFromSafeMethod(tx.data) + decodedParams = decodeParamsFromSafeMethod(tx.data) } return makeTransaction({ @@ -227,36 +227,62 @@ const addMockSafeCreationTx = (safeAddress): Array => [ }, ] -export const buildIncomingTransactionFrom = async (tx: IncomingTxServiceModel) => { - let symbol = 'ETH' - let decimals = 18 +const batchRequestTxsData = (txs: any[]) => { + const web3Batch = new web3.BatchRequest() - const fee = await web3.eth - .getTransaction(tx.transactionHash) - .then(({ gas, gasPrice }) => bn(gas).div(gasPrice).toFixed()) + const whenTxsValues = txs.map((tx) => { + const methods = ['decimals', { method: 'getCode', type: 'eth', args: [tx.to] }, 'symbol', 'name'] + return generateBatchRequests({ + abi: ERC20Detailed.abi, + address: tx.to, + batch: web3Batch, + context: tx, + methods, + }) + }) - if (tx.tokenAddress) { - try { - 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()), - ) - symbol = web3.utils.hexToString(tokenSymbol) - decimals = tokenDecimals - } catch (e) { - // this is a particular treatment for the DCD token, as it seems to lack of symbol and decimal methods - if (tx.tokenAddress && tx.tokenAddress.toLowerCase() === '0xe0b7927c4af23765cb51314a0e0521a9645f0e2a') { - symbol = 'DCD' - decimals = 9 - } - // if it's not DCD, then we fall to the default values - } - } + web3Batch.execute() + + return Promise.all(whenTxsValues) +} + +const batchRequestIncomingTxsData = (txs: IncomingTxServiceModel[]) => { + const web3Batch = new web3.BatchRequest() + + const whenTxsValues = txs.map((tx) => { + const methods = ['symbol', 'decimals', { method: 'getTransaction', args: [tx.transactionHash], type: 'eth' }] + + return generateBatchRequests({ + abi: ALTERNATIVE_TOKEN_ABI, + address: tx.tokenAddress, + batch: web3Batch, + context: tx, + methods, + }) + }) + + web3Batch.execute() + + return Promise.all(whenTxsValues).then((txsValues) => + txsValues.map(([tx, symbol, decimals, { gas, gasPrice }]) => [ + tx, + symbol === null ? 'ETH' : symbol, + decimals === null ? '18' : decimals, + bn(gas).div(gasPrice).toFixed(), + ]), + ) +} + +export const buildIncomingTransactionFrom = ([tx, symbol, decimals, fee]: [ + IncomingTxServiceModel, + string, + string, + string, +]) => { + // this is a particular treatment for the DCD token, as it seems to lack of symbol and decimal methods + if (tx.tokenAddress && tx.tokenAddress.toLowerCase() === '0xe0b7927c4af23765cb51314a0e0521a9645f0e2a') { + symbol = 'DCD' + decimals = '9' } const { transactionHash, ...incomingTx } = tx @@ -278,7 +304,7 @@ export type SafeTransactionsType = { let etagSafeTransactions = null let etagCachedSafeIncommingTransactions = null -export const loadSafeTransactions = async (safeAddress: string): Promise => { +export const loadSafeTransactions = async (safeAddress: string, getState: GetState): Promise => { let transactions: TxServiceModel[] = addMockSafeCreationTx(safeAddress) try { @@ -310,9 +336,14 @@ export const loadSafeTransactions = async (safeAddress: string): Promise> = await Promise.all( - transactions.map((tx: TxServiceModel) => buildTransactionFrom(safeAddress, tx)), + txsWithData.map(([tx: TxServiceModel, decimals, code, symbol, name]) => + buildTransactionFrom(safeAddress, tx, knownTokens, decimals, symbol, name, code), + ), ) const groupedTxs = List(txsRecord).groupBy((tx) => (tx.get('cancellationTx') ? 'cancel' : 'outgoing')) @@ -352,14 +383,15 @@ export const loadSafeIncomingTransactions = async (safeAddress: string) => { } } - const incomingTxsRecord = await Promise.all(incomingTransactions.map(buildIncomingTransactionFrom)) + const incomingTxsWithData = await batchRequestIncomingTxsData(incomingTransactions) + const incomingTxsRecord = incomingTxsWithData.map(buildIncomingTransactionFrom) return Map().set(safeAddress, List(incomingTxsRecord)) } -export default (safeAddress: string) => async (dispatch: ReduxDispatch) => { +export default (safeAddress: string) => async (dispatch: ReduxDispatch, getState: GetState) => { web3 = await getWeb3() - const transactions: SafeTransactionsType | undefined = await loadSafeTransactions(safeAddress) + const transactions: SafeTransactionsType | undefined = await loadSafeTransactions(safeAddress, getState) if (transactions) { const { cancel, outgoing } = transactions diff --git a/src/routes/safe/store/actions/processTransaction.js b/src/routes/safe/store/actions/processTransaction.js index f1f19dca..042f27c1 100644 --- a/src/routes/safe/store/actions/processTransaction.js +++ b/src/routes/safe/store/actions/processTransaction.js @@ -110,11 +110,6 @@ const processTransaction = ({ const sendParams = { from, value: 0 } - // TODO find a better solution for this in dev and production. - if (process.env.REACT_APP_ENV !== 'production') { - sendParams.gasLimit = 1000000 - } - // if not set owner management tests will fail on ganache if (process.env.NODE_ENV === 'test') { sendParams.gas = '7000000' diff --git a/src/routes/safe/store/models/transaction.js b/src/routes/safe/store/models/transaction.js index 39b1440f..a6349cbd 100644 --- a/src/routes/safe/store/models/transaction.js +++ b/src/routes/safe/store/models/transaction.js @@ -7,14 +7,7 @@ import { type Confirmation } from '~/routes/safe/store/models/confirmation' export const OUTGOING_TX_TYPE = 'outgoing' -export type TransactionType = - | 'incoming' - | 'outgoing' - | 'settings' - | 'custom' - | 'creation' - | 'cancellation' - | 'third-party-app' +export type TransactionType = 'incoming' | 'outgoing' | 'settings' | 'custom' | 'creation' | 'cancellation' export type TransactionStatus = | 'awaiting_your_confirmation' @@ -24,7 +17,6 @@ export type TransactionStatus = | 'cancelled' | 'awaiting_execution' | 'pending' - | 'third-party-app' export type TransactionProps = { nonce: ?number, diff --git a/src/routes/safe/store/selectors/index.js b/src/routes/safe/store/selectors/index.js index ff6c677d..b6821955 100644 --- a/src/routes/safe/store/selectors/index.js +++ b/src/routes/safe/store/selectors/index.js @@ -1,7 +1,7 @@ // @flow import { List, Map, Set } from 'immutable' import { type Match, matchPath } from 'react-router-dom' -import { type OutputSelector, createSelector, createStructuredSelector } from 'reselect' +import { type OutputSelector, createSelector } from 'reselect' import { getWeb3 } from '~/logic/wallets/getWeb3' import { SAFELIST_ADDRESS, SAFE_PARAM_ADDRESS } from '~/routes/routes' @@ -25,10 +25,6 @@ export type RouterProps = { match: Match, } -export type SafeProps = { - safeAddress: string, -} - type TransactionProps = { transaction: Transaction, } @@ -70,6 +66,17 @@ const incomingTransactionsSelector = (state: GlobalState): IncomingTransactionsS const oneTransactionSelector = (state: GlobalState, props: TransactionProps) => props.transaction +export const safeParamAddressFromStateSelector = (state: GlobalState): string | null => { + const match = matchPath(state.router.location.pathname, { path: `${SAFELIST_ADDRESS}/:safeAddress` }) + + if (match) { + const web3 = getWeb3() + return web3.utils.toChecksumAddress(match.params.safeAddress) + } + + return null +} + export const safeParamAddressSelector = (state: GlobalState, props: RouterProps) => { const urlAdd = props.match.params[SAFE_PARAM_ADDRESS] return urlAdd ? getWeb3().utils.toChecksumAddress(urlAdd) : '' @@ -79,7 +86,7 @@ type TxSelectorType = OutputSelector export const safeTransactionsSelector: TxSelectorType = createSelector( transactionsSelector, - safeParamAddressSelector, + safeParamAddressFromStateSelector, (transactions: TransactionsState, address: string): List => { if (!transactions) { return List([]) @@ -105,7 +112,7 @@ export const addressBookQueryParamsSelector = (state: GlobalState): string => { export const safeCancellationTransactionsSelector: TxSelectorType = createSelector( cancellationTransactionsSelector, - safeParamAddressSelector, + safeParamAddressFromStateSelector, (cancellationTransactions: TransactionsState, address: string): List => { if (!cancellationTransactions) { return List([]) @@ -119,22 +126,11 @@ export const safeCancellationTransactionsSelector: TxSelectorType = createSelect }, ) -export const safeParamAddressFromStateSelector = (state: GlobalState): string | null => { - const match = matchPath(state.router.location.pathname, { path: `${SAFELIST_ADDRESS}/:safeAddress` }) - - if (match) { - const web3 = getWeb3() - return web3.utils.toChecksumAddress(match.params.safeAddress) - } - - return null -} - type IncomingTxSelectorType = OutputSelector> export const safeIncomingTransactionsSelector: IncomingTxSelectorType = createSelector( incomingTransactionsSelector, - safeParamAddressSelector, + safeParamAddressFromStateSelector, (incomingTransactions: IncomingTransactionsState, address: string): List => { if (!incomingTransactions) { return List([]) @@ -233,12 +229,6 @@ export const safeBlacklistedAssetsSelector: OutputSelector): 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') @@ -256,6 +246,63 @@ export const safeBalancesSelector: OutputSelector> = createSelector( + safeSelector, + (safe: Safe) => { + return safe ? safe.name : undefined + }, +) + +export const safeEthBalanceSelector: OutputSelector> = createSelector( + safeSelector, + (safe: Safe) => { + return safe ? safe.ethBalance : undefined + }, +) + +export const safeNeedsUpdateSelector: OutputSelector> = createSelector( + safeSelector, + (safe: Safe) => { + return safe ? safe.needsUpdate : undefined + }, +) + +export const safeCurrentVersionSelector: OutputSelector> = createSelector( + safeSelector, + (safe: Safe) => { + return safe ? safe.currentVersion : undefined + }, +) + +export const safeThresholdSelector: OutputSelector> = createSelector( + safeSelector, + (safe: Safe) => { + return safe ? safe.threshold : undefined + }, +) + +export const safeNonceSelector: OutputSelector> = createSelector( + safeSelector, + (safe: Safe) => { + return safe ? safe.nonce : undefined + }, +) + +export const safeOwnersSelector: OutputSelector> = createSelector( + safeSelector, + (safe: Safe) => { + return safe ? safe.owners : undefined + }, +) + +export const safeFeaturesEnabledSelector: OutputSelector< + GlobalState, + RouterProps, + Map, +> = createSelector(safeSelector, (safe: Safe) => { + return safe ? safe.featuresEnabled : undefined +}) + export const getActiveTokensAddressesForAllSafes: OutputSelector> = createSelector( safesListSelector, (safes: List) => { @@ -285,9 +332,3 @@ export const getBlacklistedTokensAddressesForAllSafes: OutputSelector({ - safe: safeSelector, - tokens: safeActiveTokensSelector, - blacklistedTokens: safeBlacklistedTokensSelector, -}) diff --git a/src/test/builder/safe.dom.utils.js b/src/test/builder/safe.dom.utils.js index bb2a8aab..1d8d8542 100644 --- a/src/test/builder/safe.dom.utils.js +++ b/src/test/builder/safe.dom.utils.js @@ -13,6 +13,7 @@ import { history, type GlobalState } from '~/store' import AppRoutes from '~/routes' import { SAFELIST_ADDRESS } from '~/routes/routes' import { EMPTY_DATA } from '~/logic/wallets/ethTransactions' +import { wrapInSuspense } from '~/utils/wrapInSuspense' export const EXPAND_BALANCE_INDEX = 0 export const EXPAND_OWNERS_INDEX = 1 @@ -89,9 +90,7 @@ const renderApp = (store: Store) => ({ - }> - - + {wrapInSuspense(,
)} , diff --git a/src/test/safe.dom.funds.threshold>1.test.js b/src/test/safe.dom.funds.thresholdGt1.test.js similarity index 99% rename from src/test/safe.dom.funds.threshold>1.test.js rename to src/test/safe.dom.funds.thresholdGt1.test.js index 4c507fa0..bf860399 100644 --- a/src/test/safe.dom.funds.threshold>1.test.js +++ b/src/test/safe.dom.funds.thresholdGt1.test.js @@ -9,7 +9,7 @@ import { sleep } from '~/utils/timer' import '@testing-library/jest-dom/extend-expect' import { BALANCE_ROW_TEST_ID } from '~/routes/safe/components/Balances' import { fillAndSubmitSendFundsForm } from './utils/transactions' -import { TRANSACTIONS_TAB_BTN_TEST_ID } from '~/routes/safe/components/Layout' +import { TRANSACTIONS_TAB_BTN_TEST_ID } from '~/routes/safe/components/Layout/index' import { TRANSACTION_ROW_TEST_ID } from '~/routes/safe/components/Transactions/TxsTable' import { useTestAccountAt, resetTestAccount } from './utils/accounts' import { CONFIRM_TX_BTN_TEST_ID } from '~/routes/safe/components/Transactions/TxsTable/ExpandedTx/OwnersColumn/ButtonRow' diff --git a/src/test/safe.dom.settings.name.test.js b/src/test/safe.dom.settings.name.test.js index 49822695..5f33ae16 100644 --- a/src/test/safe.dom.settings.name.test.js +++ b/src/test/safe.dom.settings.name.test.js @@ -5,7 +5,7 @@ import { aMinedSafe } from '~/test/builder/safe.redux.builder' import { renderSafeView } from '~/test/builder/safe.dom.utils' import { sleep } from '~/utils/timer' import '@testing-library/jest-dom/extend-expect' -import { SETTINGS_TAB_BTN_TEST_ID, SAFE_VIEW_NAME_HEADING_TEST_ID } from '~/routes/safe/components/Layout' +import { SETTINGS_TAB_BTN_TEST_ID, SAFE_VIEW_NAME_HEADING_TEST_ID } from '~/routes/safe/components/Layout/index' import { SAFE_NAME_INPUT_TEST_ID, SAFE_NAME_SUBMIT_BTN_TEST_ID } from '~/routes/safe/components/Settings/SafeDetails' describe('DOM > Feature > Settings - Name', () => { diff --git a/src/test/safe.dom.settings.owners.test.js b/src/test/safe.dom.settings.owners.test.js index 3350fd96..baefba87 100644 --- a/src/test/safe.dom.settings.owners.test.js +++ b/src/test/safe.dom.settings.owners.test.js @@ -10,7 +10,7 @@ import { checkRegisteredTxRemoveOwner, checkRegisteredTxReplaceOwner, } from './utils/transactions' -import { SETTINGS_TAB_BTN_TEST_ID } from '~/routes/safe/components/Layout' +import { SETTINGS_TAB_BTN_TEST_ID } from '~/routes/safe/components/Layout/index' import { OWNERS_SETTINGS_TAB_TEST_ID } from '~/routes/safe/components/Settings' import { RENAME_OWNER_BTN_TEST_ID, diff --git a/src/test/utils/transactions/transactionList.helper.js b/src/test/utils/transactions/transactionList.helper.js index bd933765..73157767 100644 --- a/src/test/utils/transactions/transactionList.helper.js +++ b/src/test/utils/transactions/transactionList.helper.js @@ -2,7 +2,7 @@ import { fireEvent } from '@testing-library/react' import { sleep } from '~/utils/timer' import { shortVersionOf } from '~/logic/wallets/ethAddresses' -import { TRANSACTIONS_TAB_BTN_TEST_ID } from '~/routes/safe/components/Layout' +import { TRANSACTIONS_TAB_BTN_TEST_ID } from '~/routes/safe/components/Layout/index' import { TRANSACTION_ROW_TEST_ID } from '~/routes/safe/components/Transactions/TxsTable' import { TRANSACTIONS_DESC_ADD_OWNER_TEST_ID, diff --git a/src/utils/constants.js b/src/utils/constants.js index f8c61f29..bc82518c 100644 --- a/src/utils/constants.js +++ b/src/utils/constants.js @@ -13,3 +13,4 @@ export const LATEST_SAFE_VERSION = process.env.REACT_APP_LATEST_SAFE_VERSION || export const APP_VERSION = process.env.REACT_APP_APP_VERSION || 'not-defined' export const OPENSEA_API_KEY = process.env.REACT_APP_OPENSEA_API_KEY || '' export const COLLECTIBLES_SOURCE = process.env.REACT_APP_COLLECTIBLES_SOURCE || 'OpenSea' +export const TIMEOUT = process.env.NODE_ENV === 'test' ? 1500 : 5000 diff --git a/src/utils/googleAnalytics.js b/src/utils/googleAnalytics.js index 48ae64c7..b4cce767 100644 --- a/src/utils/googleAnalytics.js +++ b/src/utils/googleAnalytics.js @@ -1,12 +1,11 @@ // @flow -import React, { useEffect, useState } from 'react' +import { useCallback, useEffect, useState } from 'react' import GoogleAnalytics from 'react-ga' import { getGoogleAnalyticsTrackingID } from '~/config' import { COOKIES_KEY } from '~/logic/cookies/model/cookie' import type { CookiesProps } from '~/logic/cookies/model/cookie' import { loadFromCookie } from '~/logic/cookies/utils' -import type { RouterProps } from '~/routes/safe/store/selectors' let analyticsLoaded = false export const loadGoogleAnalytics = () => { @@ -25,22 +24,22 @@ export const loadGoogleAnalytics = () => { } } -export const withTracker = (WrappedComponent, options = {}) => { - const [useAnalytics, setUseAnalytics] = useState(false) +export const useAnalytics = () => { + const [analyticsAllowed, setAnalyticsAllowed] = useState(false) useEffect(() => { async function fetchCookiesFromStorage() { const cookiesState: CookiesProps = await loadFromCookie(COOKIES_KEY) if (cookiesState) { const { acceptedAnalytics } = cookiesState - setUseAnalytics(acceptedAnalytics) + setAnalyticsAllowed(acceptedAnalytics) } } fetchCookiesFromStorage() }, []) - const trackPage = (page) => { - if (!useAnalytics || !analyticsLoaded) { + const trackPage = useCallback((page, options = {}) => { + if (!analyticsAllowed || !analyticsLoaded) { return } GoogleAnalytics.set({ @@ -48,17 +47,7 @@ export const withTracker = (WrappedComponent, options = {}) => { ...options, }) GoogleAnalytics.pageview(page) - } + }, []) - const HOC = (props: RouterProps) => { - // eslint-disable-next-line react/prop-types - const { location } = props - useEffect(() => { - const page = location.pathname + location.search - trackPage(page) - }, [location.pathname]) - return - } - - return HOC + return { trackPage } } diff --git a/src/utils/wrapInSuspense.js b/src/utils/wrapInSuspense.js new file mode 100644 index 00000000..2d7a8198 --- /dev/null +++ b/src/utils/wrapInSuspense.js @@ -0,0 +1,3 @@ +// @flow +import React from 'react' +export const wrapInSuspense = (component, fallback) => {component} diff --git a/yarn.lock b/yarn.lock index 3d835d12..736873db 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,11 @@ # yarn lockfile v1 +"7zip-bin@~5.0.3": + version "5.0.3" + resolved "https://registry.yarnpkg.com/7zip-bin/-/7zip-bin-5.0.3.tgz#bc5b5532ecafd923a61f2fb097e3b108c0106a3f" + integrity sha512-GLyWIFBbGvpKPGo55JyRZAo4lVbnBiD52cKlw/0Vt+wnmKvWJkpZvsjVoaIolyBXDeAQKSicRtqFNPem9w0WYA== + "@babel/cli@7.8.4": version "7.8.4" resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.8.4.tgz#505fb053721a98777b2b175323ea4f090b7d3c1c" @@ -397,7 +402,7 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-numeric-separator" "^7.8.3" -"@babel/plugin-proposal-object-rest-spread@^7.9.0": +"@babel/plugin-proposal-object-rest-spread@^7.9.5": version "7.9.5" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.5.tgz#3fd65911306d8746014ec0d0cf78f0e39a149116" integrity sha512-VP2oXvAf7KCYTthbUHwBlewbl1Iq059f6seJGsxMizaCdgHIeczOr7FBqELhSqfkIl04Fi8okzWzl63UKbQmmg== @@ -638,7 +643,7 @@ "@babel/helper-plugin-utils" "^7.8.3" lodash "^4.17.13" -"@babel/plugin-transform-classes@^7.9.0": +"@babel/plugin-transform-classes@^7.9.5": version "7.9.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.9.5.tgz#800597ddb8aefc2c293ed27459c1fcc935a26c2c" integrity sha512-x2kZoIuLC//O5iA7PEvecB105o7TLzZo8ofBVhP79N+DO3jaX+KYfww9TQcfBEZD0nikNyYcGB1IKtRq36rdmg== @@ -659,7 +664,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-destructuring@^7.8.3": +"@babel/plugin-transform-destructuring@^7.9.5": version "7.9.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.9.5.tgz#72c97cf5f38604aea3abf3b935b0e17b1db76a50" integrity sha512-j3OEsGel8nHL/iusv/mRd5fYZ3DrOxWC82x0ogmdN/vHfAP4MYw+AFKYanzWlktNwikKvlzUV//afBW5FTp17Q== @@ -785,7 +790,7 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/helper-replace-supers" "^7.8.3" -"@babel/plugin-transform-parameters@^7.8.7", "@babel/plugin-transform-parameters@^7.9.5": +"@babel/plugin-transform-parameters@^7.9.5": version "7.9.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.9.5.tgz#173b265746f5e15b2afe527eeda65b73623a0795" integrity sha512-0+1FhHnMfj6lIIhVvS4KGQJeuhe1GI//h5uptK4PvLt+BGBxsoUJbd3/IW002yk//6sZPlFgsG1hY6OHLcy6kA== @@ -919,10 +924,10 @@ core-js "^2.6.5" regenerator-runtime "^0.13.4" -"@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== +"@babel/preset-env@7.9.5": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.9.5.tgz#8ddc76039bc45b774b19e2fc548f6807d8a8919f" + integrity sha512-eWGYeADTlPJH+wq1F0wNfPbVS1w1wtmMJiYk55Td5Yu28AsdR9AsC97sZ0Qq8fHqQuslVSIYSGJMcblr345GfQ== dependencies: "@babel/compat-data" "^7.9.0" "@babel/helper-compilation-targets" "^7.8.7" @@ -933,7 +938,7 @@ "@babel/plugin-proposal-json-strings" "^7.8.3" "@babel/plugin-proposal-nullish-coalescing-operator" "^7.8.3" "@babel/plugin-proposal-numeric-separator" "^7.8.3" - "@babel/plugin-proposal-object-rest-spread" "^7.9.0" + "@babel/plugin-proposal-object-rest-spread" "^7.9.5" "@babel/plugin-proposal-optional-catch-binding" "^7.8.3" "@babel/plugin-proposal-optional-chaining" "^7.9.0" "@babel/plugin-proposal-unicode-property-regex" "^7.8.3" @@ -950,9 +955,9 @@ "@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.9.0" + "@babel/plugin-transform-classes" "^7.9.5" "@babel/plugin-transform-computed-properties" "^7.8.3" - "@babel/plugin-transform-destructuring" "^7.8.3" + "@babel/plugin-transform-destructuring" "^7.9.5" "@babel/plugin-transform-dotall-regex" "^7.8.3" "@babel/plugin-transform-duplicate-keys" "^7.8.3" "@babel/plugin-transform-exponentiation-operator" "^7.8.3" @@ -967,7 +972,7 @@ "@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" - "@babel/plugin-transform-parameters" "^7.8.7" + "@babel/plugin-transform-parameters" "^7.9.5" "@babel/plugin-transform-property-literals" "^7.8.3" "@babel/plugin-transform-regenerator" "^7.8.7" "@babel/plugin-transform-reserved-words" "^7.8.3" @@ -978,7 +983,7 @@ "@babel/plugin-transform-typeof-symbol" "^7.8.4" "@babel/plugin-transform-unicode-regex" "^7.8.3" "@babel/preset-modules" "^0.1.3" - "@babel/types" "^7.9.0" + "@babel/types" "^7.9.5" browserslist "^4.9.1" core-js-compat "^3.6.2" invariant "^2.2.2" @@ -1089,6 +1094,30 @@ exec-sh "^0.3.2" minimist "^1.2.0" +"@develar/schema-utils@~2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@develar/schema-utils/-/schema-utils-2.1.0.tgz#eceb1695bfbed6f6bb84666d5d3abe5e1fd54e17" + integrity sha512-qjCqB4ctMig9Gz5bd6lkdFr3bO6arOdQqptdBSpF1ZpCnjofieCciEzkoS9ujY9cMGyllYSCSmBJ3x9OKHXzoA== + dependencies: + ajv "^6.1.0" + ajv-keywords "^3.1.0" + +"@electron/get@^1.0.1": + version "1.10.0" + resolved "https://registry.yarnpkg.com/@electron/get/-/get-1.10.0.tgz#258fdda22bbd5a247e0b663ba9c525dedc1bdfff" + integrity sha512-hlueNXU51c3CwQjBw/i5fwt+VfQgSQVUTdicpCHkhEjNZaa4CXJ5W1GaxSwtLE2dvRmAHjpIjUMHTqJ53uojfg== + dependencies: + debug "^4.1.1" + env-paths "^2.2.0" + fs-extra "^8.1.0" + got "^9.6.0" + progress "^2.0.3" + sanitize-filename "^1.6.2" + sumchecker "^3.0.1" + optionalDependencies: + global-agent "^2.0.2" + global-tunnel-ng "^2.7.1" + "@emotion/hash@^0.8.0": version "0.8.0" resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413" @@ -1129,9 +1158,9 @@ bn.js "^4.4.0" "@ethersproject/bignumber@>=5.0.0-beta.130": - version "5.0.0-beta.136" - resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.0.0-beta.136.tgz#5fd90ee708f3778733b02caf58453756524c758f" - integrity sha512-G5fYkkMUpmQd7Qcxa7YdwavBkiSb44wI7GsZls/7eGFMYl2ySgmwOBMw3kj1lhheXbF73jfBfOBHvKYrN/p7pQ== + version "5.0.0-beta.137" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.0.0-beta.137.tgz#f4b76100f8df0c97c36ab2c776c4e3de5eb870dd" + integrity sha512-X96uhPzTkw4TSs4ZT8kCAVuJP/j7zi6pL1RO7CfY3f5Alg+cA1Ngpv+XjGQOau1RWrLl+qReGMaJgNxd9U9svw== dependencies: "@ethersproject/bytes" ">=5.0.0-beta.129" "@ethersproject/logger" ">=5.0.0-beta.129" @@ -1189,16 +1218,25 @@ "@ethersproject/constants" ">=5.0.0-beta.128" "@ethersproject/logger" ">=5.0.0-beta.129" -"@gnosis.pm/safe-contracts@1.1.1-dev.1": - version "1.1.1-dev.1" - resolved "https://registry.yarnpkg.com/@gnosis.pm/safe-contracts/-/safe-contracts-1.1.1-dev.1.tgz#e6bf50a30bc78a91fdba87173972fe83c7af156e" - integrity sha512-uNk7asBLrULCB722Uv3sHjWxmqQ32UlOuK99Moh1lHpF+zUEuYuaqQ6wbpX6Z1MGN4PipyfsiVWnl3rWlKhlHg== +"@gnosis.pm/safe-contracts@1.1.1-dev.2": + version "1.1.1-dev.2" + resolved "https://registry.yarnpkg.com/@gnosis.pm/safe-contracts/-/safe-contracts-1.1.1-dev.2.tgz#4a5b9a9befe66d15df87d2216237d4ea4f64118f" + integrity sha512-x0x8K3/XzfDmtmL6RaF8eSJUPJVmT7jd29kmwoodm/JlYlyOmdQNBynUZUTkmknIlF1coiypCLls9zDbx8QQfw== dependencies: + "@truffle/hdwallet-provider" "^1.0.0" dotenv "^8.0.0" openzeppelin-solidity "^2.0.0" shelljs "^0.8.3" - solc "^0.5.9" - truffle-hdwallet-provider "0.0.7-beta.1" + solc "0.5.14" + truffle "^5.1.21" + +"@gnosis.pm/safe-react-components@https://github.com/gnosis/safe-react-components.git#71e6fed": + version "0.1.1" + resolved "https://github.com/gnosis/safe-react-components.git#71e6fed337271b0b536c1ae8128d32d49fc74947" + dependencies: + classnames "^2.2.6" + polished "^3.5.1" + url-loader "^4.1.0" "@gnosis.pm/util-contracts@2.0.6": version "2.0.6" @@ -1215,6 +1253,55 @@ normalize-path "^2.0.1" through2 "^2.0.3" +"@hapi/address@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@hapi/address/-/address-4.0.1.tgz#267301ddf7bc453718377a6fb3832a2f04a721dd" + integrity sha512-0oEP5UiyV4f3d6cBL8F3Z5S7iWSX39Knnl0lY8i+6gfmmIBj44JCBNtcMgwyS+5v7j3VYavNay0NFHDS+UGQcw== + dependencies: + "@hapi/hoek" "^9.0.0" + +"@hapi/formula@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@hapi/formula/-/formula-2.0.0.tgz#edade0619ed58c8e4f164f233cda70211e787128" + integrity sha512-V87P8fv7PI0LH7LiVi8Lkf3x+KCO7pQozXRssAHNXXL9L1K+uyu4XypLXwxqVDKgyQai6qj3/KteNlrqDx4W5A== + +"@hapi/hoek@^9.0.0": + version "9.0.4" + resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.0.4.tgz#e80ad4e8e8d2adc6c77d985f698447e8628b6010" + integrity sha512-EwaJS7RjoXUZ2cXXKZZxZqieGtc7RbvQhUy8FwDoMQtxWVi14tFjeFCYPZAM1mBCpOpiBpyaZbb9NeHc7eGKgw== + +"@hapi/joi@^17.1.1": + version "17.1.1" + resolved "https://registry.yarnpkg.com/@hapi/joi/-/joi-17.1.1.tgz#9cc8d7e2c2213d1e46708c6260184b447c661350" + integrity sha512-p4DKeZAoeZW4g3u7ZeRo+vCDuSDgSvtsB/NpfjXEHTUjSeINAi/RrVOWiVQ1isaoLzMvFEhe8n5065mQq1AdQg== + dependencies: + "@hapi/address" "^4.0.1" + "@hapi/formula" "^2.0.0" + "@hapi/hoek" "^9.0.0" + "@hapi/pinpoint" "^2.0.0" + "@hapi/topo" "^5.0.0" + +"@hapi/pinpoint@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@hapi/pinpoint/-/pinpoint-2.0.0.tgz#805b40d4dbec04fc116a73089494e00f073de8df" + integrity sha512-vzXR5MY7n4XeIvLpfl3HtE3coZYO4raKXW766R6DZw/6aLqR26iuZ109K7a0NtF2Db0jxqh7xz2AxkUwpUFybw== + +"@hapi/topo@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.0.0.tgz#c19af8577fa393a06e9c77b60995af959be721e7" + integrity sha512-tFJlT47db0kMqVm3H4nQYgn6Pwg10GTZHb1pwmSiv1K4ks6drQOtfEF5ZnPjkvC+y4/bUPHK+bc87QvLcL+WMw== + dependencies: + "@hapi/hoek" "^9.0.0" + +"@iarna/cli@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@iarna/cli/-/cli-1.2.0.tgz#0f7af5e851afe895104583c4ca07377a8094d641" + integrity sha512-ukITQAqVs2n9HGmn3car/Ir7d3ta650iXhrG7pjr3EWdFmJuuOVWgYsu7ftsSe5VifEFFhjxVuX9+8F7L8hwcA== + dependencies: + signal-exit "^3.0.2" + update-notifier "^2.2.0" + yargs "^8.0.2" + "@istanbuljs/load-nyc-config@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.0.0.tgz#10602de5570baea82f8afbfa2630b24e7a8cfe5b" @@ -1240,7 +1327,18 @@ jest-util "^25.3.0" slash "^3.0.0" -"@jest/core@^25.2.4", "@jest/core@^25.3.0": +"@jest/console@^25.4.0": + version "25.4.0" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-25.4.0.tgz#e2760b532701137801ba824dcff6bc822c961bac" + integrity sha512-CfE0erx4hdJ6t7RzAcE1wLG6ZzsHSmybvIBQDoCkDM1QaSeWL9wJMzID/2BbHHa7ll9SsbbK43HjbERbBaFX2A== + dependencies: + "@jest/types" "^25.4.0" + chalk "^3.0.0" + jest-message-util "^25.4.0" + jest-util "^25.4.0" + slash "^3.0.0" + +"@jest/core@^25.3.0": version "25.3.0" resolved "https://registry.yarnpkg.com/@jest/core/-/core-25.3.0.tgz#80f97a7a8b59dde741a24f30871cc26d0197d426" integrity sha512-+D5a/tFf6pA/Gqft2DLBp/yeSRgXhlJ+Wpst0X/ZkfTRP54qDR3C61VfHwaex+GzZBiTcE9vQeoZ2v5T10+Mqw== @@ -1274,6 +1372,40 @@ slash "^3.0.0" strip-ansi "^6.0.0" +"@jest/core@^25.4.0": + version "25.4.0" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-25.4.0.tgz#cc1fe078df69b8f0fbb023bb0bcee23ef3b89411" + integrity sha512-h1x9WSVV0+TKVtATGjyQIMJENs8aF6eUjnCoi4jyRemYZmekLr8EJOGQqTWEX8W6SbZ6Skesy9pGXrKeAolUJw== + dependencies: + "@jest/console" "^25.4.0" + "@jest/reporters" "^25.4.0" + "@jest/test-result" "^25.4.0" + "@jest/transform" "^25.4.0" + "@jest/types" "^25.4.0" + ansi-escapes "^4.2.1" + chalk "^3.0.0" + exit "^0.1.2" + graceful-fs "^4.2.3" + jest-changed-files "^25.4.0" + jest-config "^25.4.0" + jest-haste-map "^25.4.0" + jest-message-util "^25.4.0" + jest-regex-util "^25.2.6" + jest-resolve "^25.4.0" + jest-resolve-dependencies "^25.4.0" + jest-runner "^25.4.0" + jest-runtime "^25.4.0" + jest-snapshot "^25.4.0" + jest-util "^25.4.0" + jest-validate "^25.4.0" + jest-watcher "^25.4.0" + micromatch "^4.0.2" + p-each-series "^2.1.0" + realpath-native "^2.0.0" + rimraf "^3.0.0" + slash "^3.0.0" + strip-ansi "^6.0.0" + "@jest/environment@^25.3.0": version "25.3.0" resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-25.3.0.tgz#587f28ddb4b0dfe97404d3d4a4c9dbfa0245fb2e" @@ -1283,6 +1415,15 @@ "@jest/types" "^25.3.0" jest-mock "^25.3.0" +"@jest/environment@^25.4.0": + version "25.4.0" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-25.4.0.tgz#45071f525f0d8c5a51ed2b04fd42b55a8f0c7cb3" + integrity sha512-KDctiak4mu7b4J6BIoN/+LUL3pscBzoUCP+EtSPd2tK9fqyDY5OF+CmkBywkFWezS9tyH5ACOQNtpjtueEDH6Q== + dependencies: + "@jest/fake-timers" "^25.4.0" + "@jest/types" "^25.4.0" + jest-mock "^25.4.0" + "@jest/fake-timers@^25.3.0": version "25.3.0" resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-25.3.0.tgz#995aad36d5c8984165ca5db12e740ab8dbf7042a" @@ -1294,6 +1435,17 @@ jest-util "^25.3.0" lolex "^5.0.0" +"@jest/fake-timers@^25.4.0": + version "25.4.0" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-25.4.0.tgz#3a9a4289ba836abd084953dca406389a57e00fbd" + integrity sha512-lI9z+VOmVX4dPPFzyj0vm+UtaB8dCJJ852lcDnY0uCPRvZAaVGnMwBBc1wxtf+h7Vz6KszoOvKAt4QijDnHDkg== + dependencies: + "@jest/types" "^25.4.0" + jest-message-util "^25.4.0" + jest-mock "^25.4.0" + jest-util "^25.4.0" + lolex "^5.0.0" + "@jest/reporters@^25.3.0": version "25.3.0" resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-25.3.0.tgz#7f39f0e6911561cc5112a1b54656de18faee269b" @@ -1325,6 +1477,37 @@ optionalDependencies: node-notifier "^6.0.0" +"@jest/reporters@^25.4.0": + version "25.4.0" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-25.4.0.tgz#836093433b32ce4e866298af2d6fcf6ed351b0b0" + integrity sha512-bhx/buYbZgLZm4JWLcRJ/q9Gvmd3oUh7k2V7gA4ZYBx6J28pIuykIouclRdiAC6eGVX1uRZT+GK4CQJLd/PwPg== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@jest/console" "^25.4.0" + "@jest/test-result" "^25.4.0" + "@jest/transform" "^25.4.0" + "@jest/types" "^25.4.0" + chalk "^3.0.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.2" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-instrument "^4.0.0" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.0.2" + jest-haste-map "^25.4.0" + jest-resolve "^25.4.0" + jest-util "^25.4.0" + jest-worker "^25.4.0" + slash "^3.0.0" + source-map "^0.6.0" + string-length "^3.1.0" + terminal-link "^2.0.0" + v8-to-istanbul "^4.1.3" + optionalDependencies: + node-notifier "^6.0.0" + "@jest/source-map@^25.2.6": version "25.2.6" resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-25.2.6.tgz#0ef2209514c6d445ebccea1438c55647f22abb4c" @@ -1344,6 +1527,16 @@ "@types/istanbul-lib-coverage" "^2.0.0" collect-v8-coverage "^1.0.0" +"@jest/test-result@^25.4.0": + version "25.4.0" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-25.4.0.tgz#6f2ec2c8da9981ef013ad8651c1c6f0cb20c6324" + integrity sha512-8BAKPaMCHlL941eyfqhWbmp3MebtzywlxzV+qtngQ3FH+RBqnoSAhNEPj4MG7d2NVUrMOVfrwuzGpVIK+QnMAA== + dependencies: + "@jest/console" "^25.4.0" + "@jest/types" "^25.4.0" + "@types/istanbul-lib-coverage" "^2.0.0" + collect-v8-coverage "^1.0.0" + "@jest/test-sequencer@^25.3.0": version "25.3.0" resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-25.3.0.tgz#271ad5f2b8f8137d092ccedc87e16a50f8676209" @@ -1354,7 +1547,17 @@ jest-runner "^25.3.0" jest-runtime "^25.3.0" -"@jest/transform@^25.2.4", "@jest/transform@^25.3.0": +"@jest/test-sequencer@^25.4.0": + version "25.4.0" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-25.4.0.tgz#2b96f9d37f18dc3336b28e3c8070f97f9f55f43b" + integrity sha512-240cI+nsM3attx2bMp9uGjjHrwrpvxxrZi8Tyqp/cfOzl98oZXVakXBgxODGyBYAy/UGXPKXLvNc2GaqItrsJg== + dependencies: + "@jest/test-result" "^25.4.0" + jest-haste-map "^25.4.0" + jest-runner "^25.4.0" + jest-runtime "^25.4.0" + +"@jest/transform@^25.3.0": version "25.3.0" resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-25.3.0.tgz#083c5447d5307d9b9494d6968115b647460e71f1" integrity sha512-W01p8kTDvvEX6kd0tJc7Y5VdYyFaKwNWy1HQz6Jqlhu48z/8Gxp+yFCDVj+H8Rc7ezl3Mg0hDaGuFVkmHOqirg== @@ -1376,7 +1579,29 @@ source-map "^0.6.1" write-file-atomic "^3.0.0" -"@jest/types@^25.2.3", "@jest/types@^25.3.0": +"@jest/transform@^25.4.0": + version "25.4.0" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-25.4.0.tgz#eef36f0367d639e2fd93dccd758550377fbb9962" + integrity sha512-t1w2S6V1sk++1HHsxboWxPEuSpN8pxEvNrZN+Ud/knkROWtf8LeUmz73A4ezE8476a5AM00IZr9a8FO9x1+j3g== + dependencies: + "@babel/core" "^7.1.0" + "@jest/types" "^25.4.0" + 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.4.0" + jest-regex-util "^25.2.6" + jest-util "^25.4.0" + micromatch "^4.0.2" + pirates "^4.0.1" + realpath-native "^2.0.0" + slash "^3.0.0" + source-map "^0.6.1" + write-file-atomic "^3.0.0" + +"@jest/types@^25.3.0": version "25.3.0" resolved "https://registry.yarnpkg.com/@jest/types/-/types-25.3.0.tgz#88f94b277a1d028fd7117bc1f74451e0fc2131e7" integrity sha512-UkaDNewdqXAmCDbN2GlUM6amDKS78eCqiw/UmF5nE0mmLTd6moJkiZJML/X52Ke3LH7Swhw883IRXq8o9nWjVw== @@ -1386,6 +1611,25 @@ "@types/yargs" "^15.0.0" chalk "^3.0.0" +"@jest/types@^25.4.0": + version "25.4.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-25.4.0.tgz#5afeb8f7e1cba153a28e5ac3c9fe3eede7206d59" + integrity sha512-XBeaWNzw2PPnGW5aXvZt3+VO60M+34RY3XDsCK5tW7kyj3RK0XClRutCfjqcBuaR2aBQTbluEDME9b5MB9UAPw== + 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.12.0", "@ledgerhq/devices@^5.13.1": + version "5.13.1" + resolved "https://registry.yarnpkg.com/@ledgerhq/devices/-/devices-5.13.1.tgz#1d65fcbcc470874968e2e74f7e87e3f350c4b332" + integrity sha512-E3zgmA51+esMkczM9xLddVz0myXTauJaT5g4bbwGxxeHQyHyvaJNyOhMmcuxZN/aa/lfRmxYGthcN2JBUPju5A== + dependencies: + "@ledgerhq/errors" "^5.13.1" + "@ledgerhq/logs" "^5.13.1" + rxjs "^6.5.5" + "@ledgerhq/devices@^5.13.0": version "5.13.0" resolved "https://registry.yarnpkg.com/@ledgerhq/devices/-/devices-5.13.0.tgz#94666aff933d5bc5a98a6c190ff1749b37a65dba" @@ -1395,6 +1639,11 @@ "@ledgerhq/logs" "^5.13.0" rxjs "^6.5.5" +"@ledgerhq/errors@^5.12.0", "@ledgerhq/errors@^5.13.1": + version "5.13.1" + resolved "https://registry.yarnpkg.com/@ledgerhq/errors/-/errors-5.13.1.tgz#1df73a8084609888fabcefbdb9edfd4c11ab3a22" + integrity sha512-IuEw9a70K3C3AZV4yVGk75HlwmKmJaR6EjMIxBAupiCw0G6rBP0d62MA1Vx4dg082LKKNXKafWcDstLG4ySpBA== + "@ledgerhq/errors@^5.13.0": version "5.13.0" resolved "https://registry.yarnpkg.com/@ledgerhq/errors/-/errors-5.13.0.tgz#8e9aa9d2326dfaceee7d00d3411e49505837f8aa" @@ -1409,6 +1658,31 @@ "@ledgerhq/hw-transport" "^5.13.0" bignumber.js "^9.0.0" +"@ledgerhq/hw-transport-node-hid-noevents@^5.12.0": + version "5.13.1" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid-noevents/-/hw-transport-node-hid-noevents-5.13.1.tgz#9e7758bca7f9b7c46523b77575270a10b04029f0" + integrity sha512-C0o8gCJueupRlULKo06p/x2ExKrLkCunHoMVOCkqJE/jRxRWSyljDmtd3hqUQZKoBlC4JntsKvXPMN/hfGRqRw== + dependencies: + "@ledgerhq/devices" "^5.13.1" + "@ledgerhq/errors" "^5.13.1" + "@ledgerhq/hw-transport" "^5.13.1" + "@ledgerhq/logs" "^5.13.1" + node-hid "^1.2.0" + +"@ledgerhq/hw-transport-node-hid@5.12.0": + version "5.12.0" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-5.12.0.tgz#5c85a59c96e7a3f52856b6fa5ca7b8da6f16ba7d" + integrity sha512-rQPNzGPmLDgfEtedDeEKAskmRJ1dqee40UZR3cGhJO0fnW7csLXDIF/Ebl/bYXcl7MgqoznPfkdAfN79VEVzbg== + dependencies: + "@ledgerhq/devices" "^5.12.0" + "@ledgerhq/errors" "^5.12.0" + "@ledgerhq/hw-transport" "^5.12.0" + "@ledgerhq/hw-transport-node-hid-noevents" "^5.12.0" + "@ledgerhq/logs" "^5.11.0" + lodash "^4.17.15" + node-hid "^1.2.0" + usb "^1.6.0" + "@ledgerhq/hw-transport-u2f@^5.7.0": version "5.13.0" resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-u2f/-/hw-transport-u2f-5.13.0.tgz#a873ff3e0a71c0d2f2d96feef8af2c0b294cb05e" @@ -1419,6 +1693,15 @@ "@ledgerhq/logs" "^5.13.0" u2f-api "0.2.7" +"@ledgerhq/hw-transport@^5.12.0", "@ledgerhq/hw-transport@^5.13.1": + version "5.13.1" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-5.13.1.tgz#b0fb8208b0fb383f3984c1af26a9b9e7a3ad3d75" + integrity sha512-TQJJY10ZoToYjaGK+u9wud0W2dK+6TBA753FGlHgptydSaRmep0uc4A2TxOLPexdVlbHXmkMa1skd3w4ZrKKdA== + dependencies: + "@ledgerhq/devices" "^5.13.1" + "@ledgerhq/errors" "^5.13.1" + events "^3.1.0" + "@ledgerhq/hw-transport@^5.13.0": version "5.13.0" resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-5.13.0.tgz#dac69b9cd17d9260fe9bad5594cd88370cdb5933" @@ -1428,25 +1711,30 @@ "@ledgerhq/errors" "^5.13.0" events "^3.1.0" +"@ledgerhq/logs@^5.11.0", "@ledgerhq/logs@^5.13.1": + version "5.13.1" + resolved "https://registry.yarnpkg.com/@ledgerhq/logs/-/logs-5.13.1.tgz#80a13031c9e0a9b874b96b6636f3f6df603ec1b2" + integrity sha512-ag2wX5VcAqPMKooCn/S6kKblVlsn74ixtagpwR+6GdFqYa/bspH8mWw+zwcdzSwa/wbOQRuY75zH52qBonfXBA== + "@ledgerhq/logs@^5.13.0": version "5.13.0" resolved "https://registry.yarnpkg.com/@ledgerhq/logs/-/logs-5.13.0.tgz#42e848f7c6f662387dfc5f3e86e3e5b4e07a5fae" integrity sha512-yMvzQiMjWDMRma3HPxQQibhvEqMaEdXXkNBk1+eaW+N47Y3neYSSyCJlyihzzMBeeoin4ChlP/5uKQaABwBeTg== -"@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== +"@material-ui/core@4.9.10": + version "4.9.10" + resolved "https://registry.yarnpkg.com/@material-ui/core/-/core-4.9.10.tgz#53f1d18bd274c258698b6cfdab3c4bee0edf7892" + integrity sha512-CQuZU9Y10RkwSdxjn785kw2EPcXhv5GKauuVQufR9LlD37kjfn21Im1yvr6wsUzn81oLhEvVPz727UWC0gbqxg== dependencies: "@babel/runtime" "^7.4.4" - "@material-ui/styles" "^4.9.6" - "@material-ui/system" "^4.9.6" - "@material-ui/types" "^5.0.0" + "@material-ui/styles" "^4.9.10" + "@material-ui/system" "^4.9.10" + "@material-ui/types" "^5.0.1" "@material-ui/utils" "^4.9.6" "@types/react-transition-group" "^4.2.0" - clsx "^1.0.2" + clsx "^1.0.4" hoist-non-react-statics "^3.3.2" - popper.js "^1.14.1" + popper.js "^1.16.1-lts" prop-types "^15.7.2" react-is "^16.8.0" react-transition-group "^4.3.0" @@ -1469,7 +1757,7 @@ prop-types "^15.7.2" react-is "^16.8.0" -"@material-ui/styles@^4.9.6": +"@material-ui/styles@^4.9.10": version "4.9.10" resolved "https://registry.yarnpkg.com/@material-ui/styles/-/styles-4.9.10.tgz#182ccdd0bc8525a459486499bbaebcd92b0db3ab" integrity sha512-EXIXlqVyFDnjXF6tj72y6ZxiSy+mHtrsCo3Srkm3XUeu3Z01aftDBy7ZSr3TQ02gXHTvDSBvegp3Le6p/tl7eA== @@ -1491,7 +1779,7 @@ jss-plugin-vendor-prefixer "^10.0.3" prop-types "^15.7.2" -"@material-ui/system@^4.9.6": +"@material-ui/system@^4.9.10": version "4.9.10" resolved "https://registry.yarnpkg.com/@material-ui/system/-/system-4.9.10.tgz#5de6ec7bea0f222b10b45e5bd5bb8b9a7b938926" integrity sha512-E+t0baX2TBZk6ALm8twG6objpsxLdMM4MDm1++LMt2m7CetCAEc3aIAfDaprk4+tm5hFT1Cah5dRWk8EeIFQYw== @@ -1500,7 +1788,7 @@ "@material-ui/utils" "^4.9.6" prop-types "^15.7.2" -"@material-ui/types@^5.0.0", "@material-ui/types@^5.0.1": +"@material-ui/types@^5.0.1": version "5.0.1" resolved "https://registry.yarnpkg.com/@material-ui/types/-/types-5.0.1.tgz#c4954063cdc196eb327ee62c041368b1aebb6d61" integrity sha512-wURPSY7/3+MAtng3i26g+WKwwNE3HEeqa/trDBR5+zWKmcjO+u9t7Npu/J1r+3dmIa/OeziN9D/18IrBKvKffw== @@ -1581,9 +1869,9 @@ xtend "^4.0.1" "@portis/web3@^2.0.0-beta.42": - version "2.0.0-beta.54" - resolved "https://registry.yarnpkg.com/@portis/web3/-/web3-2.0.0-beta.54.tgz#a46f21375bec90bb247f66e9fde776d863a6f25b" - integrity sha512-BrhlbEXUEtlJhElXMI32S8q/2hzQpuGNRLsRxEURxonWkDMzK/CjtpKO2ACoJ205Y96lMH4S3xQB0Vuc8dC/WQ== + version "2.0.0-beta.55" + resolved "https://registry.yarnpkg.com/@portis/web3/-/web3-2.0.0-beta.55.tgz#5a1667b11766acc8de82f65c7273566c96853a98" + integrity sha512-qBqetbtTYlO8TjinYkrDUzwsHvFCZGGAeRfyMuq5Prila9h84irhBL8d3WamSG/4wqaw7aBhJbslQvVMWpMg5A== dependencies: "@portis/web3-provider-engine" "1.1.0" ethereumjs-util "5.2.0" @@ -1665,7 +1953,7 @@ dependencies: defer-to-connect "^1.0.1" -"@testing-library/dom@^7.0.2": +"@testing-library/dom@^7.1.0": version "7.2.1" resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-7.2.1.tgz#bb3b31d669bbe0c4939dadd95d69caa3c1d0b372" integrity sha512-xIGoHlQ2ZiEL1dJIFKNmLDypzYF+4OJTTASRctl/aoIDaS5y/pRVHRigoqvPUV11mdJoR71IIgi/6UviMgyz4g== @@ -1676,10 +1964,10 @@ dom-accessibility-api "^0.4.2" pretty-format "^25.1.0" -"@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== +"@testing-library/jest-dom@5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.5.0.tgz#4707023e8f572021e8a84f65721303ff60828d88" + integrity sha512-7sWHrpxG4Yd8TmryI7Rtbx8Ff4mbs3ASye3oshQIuHvsCR+QHgr7rTR/PfeXvOmwUwR36wSTTAvrLKsPmr6VEQ== dependencies: "@babel/runtime" "^7.9.2" "@types/testing-library__jest-dom" "^5.0.2" @@ -1691,14 +1979,14 @@ lodash "^4.17.15" redent "^3.0.0" -"@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== +"@testing-library/react@10.0.2": + version "10.0.2" + resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-10.0.2.tgz#8eca7aa52d810cf7150048a2829fdc487162006d" + integrity sha512-YT6Mw0oJz7R6vlEkmo1FlUD+K15FeXApOB5Ffm9zooFVnrwkt00w18dUJFMOh1yRp9wTdVRonbor7o4PIpFCmA== dependencies: - "@babel/runtime" "^7.8.7" - "@testing-library/dom" "^7.0.2" - "@types/testing-library__react" "^9.1.3" + "@babel/runtime" "^7.9.2" + "@testing-library/dom" "^7.1.0" + "@types/testing-library__react" "^10.0.0" "@toruslabs/fetch-node-details@^2.2.0": version "2.2.1" @@ -1925,7 +2213,7 @@ glob "^7.1.2" web3-utils "1.2.1" -"@truffle/hdwallet-provider@^1.0.27": +"@truffle/hdwallet-provider@^1.0.0", "@truffle/hdwallet-provider@^1.0.27": version "1.0.34" resolved "https://registry.yarnpkg.com/@truffle/hdwallet-provider/-/hdwallet-provider-1.0.34.tgz#1e642c415c28e9ae3bb8142bbdbc8506adaaa06a" integrity sha512-sy7sismdclvzWQmHDjElqPGoU1+ff4w3nODKqBpauacAYpWngu865CrtgRNnETZ1c90zDElU41V6yWrUgKupAQ== @@ -2030,7 +2318,7 @@ resolved "https://registry.yarnpkg.com/@types/anymatch/-/anymatch-1.3.1.tgz#336badc1beecb9dacc38bea2cf32adf627a8421a" integrity sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA== -"@types/babel__core@^7.1.0", "@types/babel__core@^7.1.7": +"@types/babel__core@^7.1.7": version "7.1.7" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.7.tgz#1dacad8840364a57c98d0dd4855c6dd3752c6b89" integrity sha512-RL62NqSFPCDK2FM1pSDH0scHpJvsXtZNiYlMB73DgPBaG1E38ZYVL+ei5EkWRbr+KC4YNiAUNBnRj+bgwpgjMw== @@ -2075,6 +2363,11 @@ resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== +"@types/debug@^4.1.4", "@types/debug@^4.1.5": + version "4.1.5" + resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.5.tgz#b14efa8852b7768d898906613c23f688713e02cd" + integrity sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ== + "@types/estree@0.0.39": version "0.0.39" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" @@ -2142,11 +2435,21 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.19.tgz#1d31ddd5503dba2af7a901aafef3392e4955620e" integrity sha512-46/xThm3zvvc9t9/7M3AaLEqtOpqlYYYcCZbpYVAQHG20+oMZBkae/VMrn4BTi6AJ8cpack0mEXhGiKmDNbLrQ== +"@types/node@^12.0.12": + version "12.12.37" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.37.tgz#cb4782d847f801fa58316da5b4801ca3a59ae790" + integrity sha512-4mXKoDptrXAwZErQHrLzpe0FN/0Wmf5JRniSVIdwUrtDf9wnmEV1teCNLBo/TwuXhkK/bVegoEn/wmb+x0AuPg== + "@types/node@^12.6.1": version "12.12.35" resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.35.tgz#1e61b226c14380f4384f70cfe49a65c2c553ad2b" integrity sha512-ASYsaKecA7TUsDrqIGPNk3JeEox0z/0XR/WsJJ8BIX/9+SkMSImQXKWfU/yBrSyc7ZSE/NPqLu36Nur0miCFfQ== +"@types/normalize-package-data@^2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" + integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA== + "@types/parse-json@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" @@ -2189,6 +2492,11 @@ "@types/prop-types" "*" csstype "^2.2.0" +"@types/semver@^6.0.2": + version "6.2.1" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-6.2.1.tgz#a236185670a7860f1597cf73bea2e16d001461ba" + integrity sha512-+beqKQOh9PYxuHvijhVl+tIHvT6tuwOrE9m14zd+MT2A38KoKZhh7pYJ0SNleLtwDsiIxHDsIk9bv01oOxvSvA== + "@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" @@ -2218,19 +2526,19 @@ dependencies: "@types/jest" "*" -"@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== +"@types/testing-library__react@^10.0.0": + version "10.0.1" + resolved "https://registry.yarnpkg.com/@types/testing-library__react/-/testing-library__react-10.0.1.tgz#92bb4a02394bf44428e35f1da2970ed77f803593" + integrity sha512-RbDwmActAckbujLZeVO/daSfdL1pnjVqas25UueOkAY5r7vriavWf0Zqg7ghXMHa8ycD/kLkv8QOj31LmSYwww== dependencies: "@types/react-dom" "*" "@types/testing-library__dom" "*" pretty-format "^25.1.0" "@types/uglify-js@*": - version "3.0.5" - resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.0.5.tgz#2c70d5c68f6e002e3b2e4f849adc5f162546f633" - integrity sha512-L7EbSkhSaWBpkl+PZAEAqZTqtTeIsq7s/oX/q0LNnxxJoRVKQE0T81XDVyaxjiiKQwiV2vhVeYRqxdRNqGOGJw== + version "3.9.0" + resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.9.0.tgz#4490a140ca82aa855ad68093829e7fd6ae94ea87" + integrity sha512-3ZcoyPYHVOCcLpnfZwD47KFLr8W/mpUcgjpf1M4Q78TMJIw7KMAHSjiCLJp1z3ZrBR9pTLbe191O0TldFK5zcw== dependencies: source-map "^0.6.1" @@ -2491,10 +2799,10 @@ "@webassemblyjs/wast-parser" "1.9.0" "@xtuc/long" "4.2.2" -"@welldone-software/why-did-you-render@4.0.5": - version "4.0.5" - resolved "https://registry.yarnpkg.com/@welldone-software/why-did-you-render/-/why-did-you-render-4.0.5.tgz#15a8de16fc84307ab401fb3f859d9a94f2b5334c" - integrity sha512-igBq0kGqKUdwMUQFgPkDzKQS+8MHqhDvF2j2w+05yS7LqcIIZyBL7FRYf1Hvm1QABx86prS7xwiIJa0U0ev5JA== +"@welldone-software/why-did-you-render@4.0.8": + version "4.0.8" + resolved "https://registry.yarnpkg.com/@welldone-software/why-did-you-render/-/why-did-you-render-4.0.8.tgz#a685e7496421b44723f9342046f1b0dbbb39ad39" + integrity sha512-32B1YFqgEOO5fIBKT0uBIjuBAGxov/pwlxEqRZhmtvlyWTl927ouOP4PaxE6RAKuGAkkl6qoTF3yke3CokbZEQ== dependencies: lodash "^4" @@ -2508,6 +2816,14 @@ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== +JSONStream@^1.3.4, JSONStream@^1.3.5: + version "1.3.5" + resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" + integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ== + dependencies: + jsonparse "^1.2.0" + through ">=2.2.7 <3" + abab@^1.0.0: version "1.0.4" resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.4.tgz#5faad9c2c07f60dd76770f71cf025b62a63cfd4e" @@ -2518,6 +2834,11 @@ abab@^2.0.0: resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.3.tgz#623e2075e02eb2d3f2475e49f99c91846467907a" integrity sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg== +abbrev@1, abbrev@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + abi-decoder@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/abi-decoder/-/abi-decoder-1.2.0.tgz#c42882dbb91b444805f0cd203a87a5cc3c22f4a8" @@ -2631,16 +2952,32 @@ aes-js@3.0.0: resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" integrity sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0= -aes-js@^0.2.3: - version "0.2.4" - resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-0.2.4.tgz#94b881ab717286d015fa219e08fb66709dda5a3d" - integrity sha1-lLiBq3FyhtAV+iGeCPtmcJ3aWj0= - aes-js@^3.1.1: version "3.1.2" resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a" integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ== +agent-base@4, agent-base@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee" + integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg== + dependencies: + es6-promisify "^5.0.0" + +agent-base@~4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9" + integrity sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg== + dependencies: + es6-promisify "^5.0.0" + +agentkeepalive@^3.4.1: + version "3.5.2" + resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-3.5.2.tgz#a113924dd3fa24a0bc3b78108c450c2abee00f67" + integrity sha512-e0L/HNe6qkQ7H19kTlRRqUibEAwDK5AFk6y3PtMsuut2VAH6+Q4xZml1tNDJD7kSAyqmbG/K08K5WEJYtUrSlQ== + dependencies: + humanize-ms "^1.2.1" + aggregate-error@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.0.1.tgz#db2fe7246e536f40d9b5442a39e117d7dd6a24e0" @@ -2660,9 +2997,9 @@ ajv-keywords@^3.1.0, ajv-keywords@^3.4.1: integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ== ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.0, ajv@^6.5.5, ajv@^6.9.1: - version "6.12.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.0.tgz#06d60b96d87b8454a5adaba86e7854da629db4b7" - integrity sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw== + version "6.12.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.2.tgz#c629c5eced17baf314437918d2da88c99d5958cd" + integrity sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ== dependencies: fast-deep-equal "^3.1.1" fast-json-stable-stringify "^2.0.0" @@ -2674,6 +3011,20 @@ alphanum-sort@^1.0.0: resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= +ansi-align@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f" + integrity sha1-w2rsy6VjuJzrVW82kPCx2eNUf38= + dependencies: + string-width "^2.0.0" + +ansi-align@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.0.tgz#b536b371cf687caaef236c18d3e21fe3797467cb" + integrity sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw== + dependencies: + string-width "^3.0.0" + ansi-colors@^3.0.0: version "3.2.4" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf" @@ -2736,6 +3087,16 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: "@types/color-name" "^1.1.1" color-convert "^2.0.1" +ansicolors@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.3.2.tgz#665597de86a9ffe3aa9bfbe6cae5c6ea426b4979" + integrity sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk= + +ansistyles@~0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/ansistyles/-/ansistyles-0.1.3.tgz#5de60415bda071bb37127854c864f41b23254539" + integrity sha1-XeYEFb2gcbs3EnhUyGT0GyMlRTk= + any-observable@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/any-observable/-/any-observable-0.3.0.tgz#af933475e5806a67d0d7df090dd5e8bef65d119b" @@ -2762,16 +3123,100 @@ anymatch@^3.0.3, anymatch@~3.1.1: normalize-path "^3.0.0" picomatch "^2.0.4" +app-builder-bin@3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/app-builder-bin/-/app-builder-bin-3.4.3.tgz#58a74193eb882f029be6b7f0cd3f0c6805927a6b" + integrity sha512-qMhayIwi3juerQEVJMQ76trObEbfQT0nhUdxZz9a26/3NLT3pE6awmQ8S1cEnrGugaaM5gYqR8OElcDezfmEsg== + +app-builder-bin@3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/app-builder-bin/-/app-builder-bin-3.5.1.tgz#68dcbe4eb8b7d80be22945ba7f7b72c812ea1eb4" + integrity sha512-71FeTdKU+L4/afnKYeCS9S9g6wa2AyiMLxGtYms6sPnnzUEd81wBhfvRb8/O/f4tLrU1MDbkjA8aGGiK9/ZT6A== + +app-builder-lib@22.2.0: + version "22.2.0" + resolved "https://registry.yarnpkg.com/app-builder-lib/-/app-builder-lib-22.2.0.tgz#2a5b657088f66f58785a01d6eb599e6c43dd5829" + integrity sha512-0npUnokV4+mkUV14x/W8wjRaG6AZzsTcr9m4t0BARmgBwwhhU10Rd41RM+P55FvJtaDPMq8LYtvddcQraVPZTA== + dependencies: + "7zip-bin" "~5.0.3" + "@develar/schema-utils" "~2.1.0" + async-exit-hook "^2.0.1" + bluebird-lst "^1.0.9" + builder-util "22.2.0" + builder-util-runtime "8.5.0" + chromium-pickle-js "^0.2.0" + debug "^4.1.1" + ejs "^3.0.1" + electron-publish "22.2.0" + fs-extra "^8.1.0" + hosted-git-info "^3.0.2" + is-ci "^2.0.0" + isbinaryfile "^4.0.2" + js-yaml "^3.13.1" + lazy-val "^1.0.4" + minimatch "^3.0.4" + normalize-package-data "^2.5.0" + read-config-file "5.0.1" + sanitize-filename "^1.6.3" + semver "^6.3.0" + temp-file "^3.3.6" + +app-builder-lib@~21.2.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/app-builder-lib/-/app-builder-lib-21.2.0.tgz#fa1d1604601431e2c3476857e9b9b61d33ad26cc" + integrity sha512-aOX/nv77/Bti6NymJDg7p9T067xD8m1ipIEJR7B4Mm1GsJWpMm9PZdXtCRiMNRjHtQS5KIljT0g17781y6qn5A== + dependencies: + "7zip-bin" "~5.0.3" + "@develar/schema-utils" "~2.1.0" + async-exit-hook "^2.0.1" + bluebird-lst "^1.0.9" + builder-util "21.2.0" + builder-util-runtime "8.3.0" + chromium-pickle-js "^0.2.0" + debug "^4.1.1" + ejs "^2.6.2" + electron-publish "21.2.0" + fs-extra "^8.1.0" + hosted-git-info "^2.7.1" + is-ci "^2.0.0" + isbinaryfile "^4.0.2" + js-yaml "^3.13.1" + lazy-val "^1.0.4" + minimatch "^3.0.4" + normalize-package-data "^2.5.0" + read-config-file "5.0.0" + sanitize-filename "^1.6.2" + semver "^6.3.0" + temp-file "^3.3.4" + app-module-path@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/app-module-path/-/app-module-path-2.2.0.tgz#641aa55dfb7d6a6f0a8141c4b9c0aa50b6c24dd5" integrity sha1-ZBqlXft9am8KgUHEucCqULbCTdU= -aproba@^1.1.1: +aproba@^1.0.3, aproba@^1.1.1, aproba@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== +"aproba@^1.1.2 || 2", aproba@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" + integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== + +archy@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" + integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA= + +are-we-there-yet@~1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" + integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -2881,7 +3326,7 @@ arrify@^1.0.0, arrify@^1.0.1: resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= -asap@~2.0.3: +asap@^2.0.0, asap@~2.0.3: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= @@ -2947,6 +3392,11 @@ async-eventemitter@^0.2.2, async-eventemitter@^0.2.4: dependencies: async "^2.4.0" +async-exit-hook@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/async-exit-hook/-/async-exit-hook-2.0.1.tgz#8bd8b024b0ec9b1c01cccb9af9db29bd717dfaf3" + integrity sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw== + async-limiter@^1.0.0, async-limiter@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" @@ -3024,13 +3474,13 @@ authereum@^0.0.4-beta.131: web3-provider-engine "^15.0.4" web3-utils "^1.2.1" -autoprefixer@9.7.5: - version "9.7.5" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.7.5.tgz#8df10b9ff9b5814a8d411a5cfbab9c793c392376" - integrity sha512-URo6Zvt7VYifomeAfJlMFnYDhow1rk2bufwkbamPEAtQFcL11moLk4PnR7n9vlu7M+BkXAZkHFA0mIcY7tjQFg== +autoprefixer@9.7.6: + version "9.7.6" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.7.6.tgz#63ac5bbc0ce7934e6997207d5bb00d68fa8293a4" + integrity sha512-F7cYpbN7uVVhACZTeeIeealwdGM6wMtfWARVLTy5xmKtgVdBNJvbDRoCK3YO1orcs7gv/KwYlb3iXwu9Ug9BkQ== dependencies: - browserslist "^4.11.0" - caniuse-lite "^1.0.30001036" + browserslist "^4.11.1" + caniuse-lite "^1.0.30001039" chalk "^2.4.2" normalize-range "^0.1.2" num2fraction "^1.2.2" @@ -3250,20 +3700,7 @@ babel-helpers@^6.24.1: babel-runtime "^6.22.0" babel-template "^6.24.1" -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.2.4" - "@jest/types" "^25.2.3" - "@types/babel__core" "^7.1.0" - babel-plugin-istanbul "^6.0.0" - babel-preset-jest "^25.2.1" - chalk "^3.0.0" - slash "^3.0.0" - -babel-jest@^25.3.0: +babel-jest@25.3.0, babel-jest@^25.3.0: version "25.3.0" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-25.3.0.tgz#999d0c19e8427f66b796bf9ea233eedf087b957c" integrity sha512-qiXeX1Cmw4JZ5yQ4H57WpkO0MZ61Qj+YnsVUwAMnDV5ls+yHon11XjarDdgP7H8lTmiEi6biiZA8y3Tmvx6pCg== @@ -3276,6 +3713,19 @@ babel-jest@^25.3.0: chalk "^3.0.0" slash "^3.0.0" +babel-jest@^25.4.0: + version "25.4.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-25.4.0.tgz#409eb3e2ddc2ad9a92afdbb00991f1633f8018d0" + integrity sha512-p+epx4K0ypmHuCnd8BapfyOwWwosNCYhedetQey1awddtfmEX0MmdxctGl956uwUmjwXR5VSS5xJcGX9DvdIog== + dependencies: + "@jest/transform" "^25.4.0" + "@jest/types" "^25.4.0" + "@types/babel__core" "^7.1.7" + babel-plugin-istanbul "^6.0.0" + babel-preset-jest "^25.4.0" + chalk "^3.0.0" + slash "^3.0.0" + babel-loader@8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.1.0.tgz#c611d5112bd5209abe8b9fa84c3e4da25275f1c3" @@ -3302,9 +3752,9 @@ babel-plugin-check-es2015-constants@^6.22.0: babel-runtime "^6.22.0" babel-plugin-dynamic-import-node@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz#f00f507bdaa3c3e3ff6e7e5e98d90a7acab96f7f" - integrity sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ== + version "2.3.3" + resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" + integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== dependencies: object.assign "^4.1.0" @@ -3319,10 +3769,10 @@ babel-plugin-istanbul@^6.0.0: istanbul-lib-instrument "^4.0.0" test-exclude "^6.0.0" -babel-plugin-jest-hoist@^25.2.6: - version "25.2.6" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-25.2.6.tgz#2af07632b8ac7aad7d414c1e58425d5fc8e84909" - integrity sha512-qE2xjMathybYxjiGFJg0mLFrz0qNp83aNZycWDY/SuHiZNq+vQfRQtuINqyXyue1ELd8Rd+1OhFSLjms8msMbw== +babel-plugin-jest-hoist@^25.2.6, babel-plugin-jest-hoist@^25.4.0: + version "25.4.0" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-25.4.0.tgz#0c122c1b93fb76f52d2465be2e8069e798e9d442" + integrity sha512-M3a10JCtTyKevb0MjuH6tU+cP/NVQZ82QPADqI1RQYY1OphztsCeIeQmTsHmF/NS6m0E51Zl4QNsI3odXSQF5w== dependencies: "@types/babel__traverse" "^7.0.6" @@ -3654,7 +4104,7 @@ babel-preset-env@^1.7.0: invariant "^2.2.2" semver "^5.3.0" -babel-preset-jest@^25.2.1, babel-preset-jest@^25.3.0: +babel-preset-jest@^25.3.0: version "25.3.0" resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-25.3.0.tgz#9ab40aee52a19bdc52b8b1ec2403d5914ac3d86b" integrity sha512-tjdvLKNMwDI9r+QWz9sZUQGTq1dpoxjUqFUpEasAc7MOtHg9XuLT2fx0udFG+k1nvMV0WvHHVAN7VmCZ+1Zxbw== @@ -3662,6 +4112,14 @@ babel-preset-jest@^25.2.1, babel-preset-jest@^25.3.0: babel-plugin-jest-hoist "^25.2.6" babel-preset-current-node-syntax "^0.1.2" +babel-preset-jest@^25.4.0: + version "25.4.0" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-25.4.0.tgz#10037cc32b751b994b260964629e49dc479abf4c" + integrity sha512-PwFiEWflHdu3JCeTr0Pb9NcHHE34qWFnPQRVPvqQITx4CsDCzs6o05923I10XvLvn9nNsRHuiVgB72wG/90ZHQ== + dependencies: + babel-plugin-jest-hoist "^25.4.0" + babel-preset-current-node-syntax "^0.1.2" + babel-register@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" @@ -3744,11 +4202,6 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= -base-x@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/base-x/-/base-x-1.1.0.tgz#42d3d717474f9ea02207f6d1aa1f426913eeb7ac" - integrity sha1-QtPXF0dPnqAiB/bRqh9CaRPut6w= - base-x@^3.0.2: version "3.0.8" resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.8.tgz#1e1106c2537f0162e8b52474a557ebb09000018d" @@ -3824,6 +4277,18 @@ bignumber.js@^8.1.1: version "2.0.7" resolved "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934" +bin-links@^1.1.2, bin-links@^1.1.7: + version "1.1.8" + resolved "https://registry.yarnpkg.com/bin-links/-/bin-links-1.1.8.tgz#bd39aadab5dc4bdac222a07df5baf1af745b2228" + integrity sha512-KgmVfx+QqggqP9dA3iIc5pA4T1qEEEL+hOhOhNPaUm77OTrJoOXE/C05SJLNJe6m/2wUK7F1tDSou7n5TfCDzQ== + dependencies: + bluebird "^3.5.3" + cmd-shim "^3.0.0" + gentle-fs "^2.3.0" + graceful-fs "^4.1.15" + npm-normalize-package-bin "^1.0.0" + write-file-atomic "^2.3.0" + binary-extensions@^1.0.0: version "1.13.1" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" @@ -3834,7 +4299,7 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c" integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow== -bindings@^1.2.1, bindings@^1.5.0: +bindings@^1.2.1, bindings@^1.4.0, bindings@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== @@ -3878,7 +4343,23 @@ bl@^1.0.0: readable-stream "^2.3.5" safe-buffer "^5.1.1" -bluebird@^3.4.1, bluebird@^3.4.7, bluebird@^3.5.0, bluebird@^3.5.5: +bl@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.0.2.tgz#52b71e9088515d0606d9dd9cc7aa48dc1f98e73a" + integrity sha512-j4OH8f6Qg2bGuWfRiltT2HYGx0e1QcBTrK9KAHNMwMZdQnDZFk0ZSYIpADjYCB3U12nicC5tVJwSIhwOWjb4RQ== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + +bluebird-lst@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/bluebird-lst/-/bluebird-lst-1.0.9.tgz#a64a0e4365658b9ab5fe875eb9dfb694189bb41c" + integrity sha512-7B1Rtx82hjnSD4PGLAjVWeYH3tHAcVUmChh85a3lltKQm6FresXh9ErQo6oAv6CqxttczC3/kEg8SY5NluPuUw== + dependencies: + bluebird "^3.5.5" + +bluebird@^3.4.1, bluebird@^3.4.7, bluebird@^3.5.0, bluebird@^3.5.1, bluebird@^3.5.3, bluebird@^3.5.5: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== @@ -3964,11 +4445,43 @@ boolbase@^1.0.0, boolbase@~1.0.0: resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= +boolean@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/boolean/-/boolean-3.0.1.tgz#35ecf2b4a2ee191b0b44986f14eb5f052a5cbb4f" + integrity sha512-HRZPIjPcbwAVQvOTxR4YE3o8Xs98NqbbL1iEZDCz7CL8ql0Lt5iOyJFxfnAB0oFs8Oh02F/lLlg30Mexv46LjA== + bowser@^2.5.2: version "2.9.0" resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.9.0.tgz#3bed854233b419b9a7422d9ee3e85504373821c9" integrity sha512-2ld76tuLBNFekRgmJfT2+3j5MIrP6bFict8WAIT3beq+srz1gcKNAdNKMqHqauQt63NmAa88HfP1/Ypa9Er3HA== +boxen@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b" + integrity sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw== + dependencies: + ansi-align "^2.0.0" + camelcase "^4.0.0" + chalk "^2.0.1" + cli-boxes "^1.0.0" + string-width "^2.0.0" + term-size "^1.2.0" + widest-line "^2.0.0" + +boxen@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-3.2.0.tgz#fbdff0de93636ab4450886b6ff45b92d098f45eb" + integrity sha512-cU4J/+NodM3IHdSL2yN8bqYqnmlBTidDR4RC7nJs61ZmtGz8VZzM3HLQX0zY5mrSmPtR3xWwsq2jOUQqFZN8+A== + dependencies: + ansi-align "^3.0.0" + camelcase "^5.3.1" + chalk "^2.4.2" + cli-boxes "^2.2.0" + string-width "^3.0.0" + term-size "^1.2.0" + type-fest "^0.3.0" + widest-line "^2.0.0" + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -4116,7 +4629,7 @@ browserslist@^3.2.6: caniuse-lite "^1.0.30000844" electron-to-chromium "^1.3.47" -browserslist@^4.0.0, browserslist@^4.11.0, browserslist@^4.8.5, browserslist@^4.9.1: +browserslist@^4.0.0, browserslist@^4.8.5, browserslist@^4.9.1: version "4.11.1" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.11.1.tgz#92f855ee88d6e050e7e7311d987992014f1a1f1b" integrity sha512-DCTr3kDrKEYNw6Jb9HFxVLQNaue8z+0ZfRBRjmCunKDEXEBajKDj2Y+Uelg+Pi29OnvaSGwjOsnRyNEkXzHg5g== @@ -4126,17 +4639,15 @@ browserslist@^4.0.0, browserslist@^4.11.0, browserslist@^4.8.5, browserslist@^4. node-releases "^1.1.53" pkg-up "^2.0.0" -bs58@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/bs58/-/bs58-2.0.1.tgz#55908d58f1982aba2008fa1bed8f91998a29bf8d" - integrity sha1-VZCNWPGYKrogCPob7Y+RmYopv40= - -bs58@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/bs58/-/bs58-3.1.0.tgz#d4c26388bf4804cac714141b1945aa47e5eb248e" - integrity sha1-1MJjiL9IBMrHFBQbGUWqR+XrJI4= +browserslist@^4.11.1: + version "4.12.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.12.0.tgz#06c6d5715a1ede6c51fc39ff67fd647f740b656d" + integrity sha512-UH2GkcEDSI0k/lRkuDSzFl9ZZ87skSy9w2XAn1MsZnL+4c4rqbBd3e82UWHbYDpztABrPBhZsTEeuxVfHppqDg== dependencies: - base-x "^1.1.0" + caniuse-lite "^1.0.30001043" + electron-to-chromium "^1.3.413" + node-releases "^1.1.53" + pkg-up "^2.0.0" bs58@^4.0.0: version "4.0.1" @@ -4145,14 +4656,6 @@ bs58@^4.0.0: dependencies: base-x "^3.0.2" -bs58check@^1.0.8: - version "1.3.4" - resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-1.3.4.tgz#c52540073749117714fa042c3047eb8f9151cbf8" - integrity sha1-xSVABzdJEXcU+gQsMEfrj5FRy/g= - dependencies: - bs58 "^3.1.0" - create-hash "^1.1.0" - bs58check@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" @@ -4226,19 +4729,96 @@ buffer@^4.3.0: ieee754 "^1.1.4" isarray "^1.0.0" -buffer@^5.0.5, buffer@^5.2.1: - version "5.5.0" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.5.0.tgz#9c3caa3d623c33dd1c7ef584b89b88bf9c9bc1ce" - integrity sha512-9FTEDjLjwoAkEwyMGDjYJQN2gfRgOKBKRfiglhvibGbpeeU/pQn1bJxQqm32OD/AIeEuHxU9roxXxg34Byp/Ww== +buffer@^5.0.5, buffer@^5.2.1, buffer@^5.5.0: + version "5.6.0" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.6.0.tgz#a31749dc7d81d84db08abf937b6b8c4033f62786" + integrity sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw== dependencies: base64-js "^1.0.2" ieee754 "^1.1.4" +builder-util-runtime@8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.3.0.tgz#f5fac9139af6facf42a21fbe4d3aebed88fda33e" + integrity sha512-CSOdsYqf4RXIHh1HANPbrZHlZ9JQJXSuDDloblZPcWQVN62inyYoTQuSmY3KrgefME2Sv3Kn2MxHvbGQHRf8Iw== + dependencies: + debug "^4.1.1" + sax "^1.2.4" + +builder-util-runtime@8.4.0: + version "8.4.0" + resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.4.0.tgz#3163fffc078e6b8f3dd5b6eb12a8345573590682" + integrity sha512-CJB/eKfPf2vHrkmirF5eicVnbDCkMBbwd5tRYlTlgud16zFeqD7QmrVUAOEXdnsrcNkiLg9dbuUsQKtl/AwsYQ== + dependencies: + debug "^4.1.1" + sax "^1.2.4" + +builder-util-runtime@8.5.0: + version "8.5.0" + resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.5.0.tgz#0c9faa782307867cc2ec70f25e63829ef1ea49c4" + integrity sha512-ft0npBXQc5gp1AVkY/WkUXDLKWweux/R1L+YQHjtspSp9nRHqoBP6qBTxb8ca6CtBKe+yZbZYGvCw1l0ZBkx/w== + dependencies: + debug "^4.1.1" + sax "^1.2.4" + +builder-util@21.2.0, builder-util@~21.2.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-21.2.0.tgz#aba721190e4e841009d9fb4b88f1130ed616522f" + integrity sha512-Nd6CUb6YgDY8EXAXEIegx+1kzKqyFQ5ZM5BoYkeunAlwz/zDJoH1UCyULjoS5wQe5czNClFQy07zz2bzYD0Z4A== + dependencies: + "7zip-bin" "~5.0.3" + "@types/debug" "^4.1.4" + app-builder-bin "3.4.3" + bluebird-lst "^1.0.9" + builder-util-runtime "8.3.0" + chalk "^2.4.2" + debug "^4.1.1" + fs-extra "^8.1.0" + is-ci "^2.0.0" + js-yaml "^3.13.1" + source-map-support "^0.5.13" + stat-mode "^0.3.0" + temp-file "^3.3.4" + +builder-util@22.2.0, builder-util@~22.2.0: + version "22.2.0" + resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-22.2.0.tgz#f9ac6a64d4fc3da16816a02e6f48f29fe8b0bb3d" + integrity sha512-kkhDjcFuY6qGHmRhOfmYnk+raxsPauddUu7Z+TUOqMOyBVFX8ODnDjIFWQ7yDz5+KNtS9MTObJl9MTAKSRPAVQ== + dependencies: + "7zip-bin" "~5.0.3" + "@types/debug" "^4.1.5" + app-builder-bin "3.5.1" + bluebird-lst "^1.0.9" + builder-util-runtime "8.5.0" + chalk "^3.0.0" + debug "^4.1.1" + fs-extra "^8.1.0" + is-ci "^2.0.0" + js-yaml "^3.13.1" + source-map-support "^0.5.16" + stat-mode "^1.0.0" + temp-file "^3.3.6" + builtin-status-codes@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= +builtins@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" + integrity sha1-y5T662HIaWRR2zZTThQi+U8K7og= + +byline@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/byline/-/byline-5.0.0.tgz#741c5216468eadc457b03410118ad77de8c1ddb1" + integrity sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE= + +byte-size@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/byte-size/-/byte-size-5.0.1.tgz#4b651039a5ecd96767e71a3d7ed380e48bed4191" + integrity sha512-/XuKeqWocKsYa/cBY1YbSJSWWqTi4cFgr9S6OyM7PBaPbr9zvNGwWP33vt0uqGhwDdN+y3yhbXVILEUpnwEWGw== + bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" @@ -4264,7 +4844,7 @@ bytewise@~1.1.0: bytewise-core "^1.2.2" typewise "^1.0.3" -cacache@^12.0.2: +cacache@^12.0.0, cacache@^12.0.2, cacache@^12.0.3: version "12.0.4" resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.4.tgz#668bcbd105aeb5f1d92fe25570ec9525c8faa40c" integrity sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ== @@ -4345,6 +4925,11 @@ cachedown@1.0.0: abstract-leveldown "^2.4.1" lru-cache "^3.2.0" +call-limit@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/call-limit/-/call-limit-1.1.1.tgz#ef15f2670db3f1992557e2d965abc459e6e358d4" + integrity sha512-5twvci5b9eRBw2wCfPtN0GmlR2/gadZqyFpPhOK6CvMFoFgA+USnZ6Jpu1lhG9h85pQ3Ouil3PfXWRD4EUaRiQ== + call-me-maybe@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" @@ -4406,7 +4991,7 @@ camelcase@^3.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo= -camelcase@^4.1.0: +camelcase@^4.0.0, camelcase@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= @@ -4431,11 +5016,16 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30001035, caniuse-lite@^1.0.30001036, caniuse-lite@^1.0.30001038: +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30001035: version "1.0.30001041" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001041.tgz#c2ea138dafc6fe03877921ddcddd4a02a14daf76" integrity sha512-fqDtRCApddNrQuBxBS7kEiSGdBsgO4wiVw4G/IClfqzfhW45MbTumfN4cuUJGTM0YGFNn97DCXPJ683PS6zwvA== +caniuse-lite@^1.0.30001039, caniuse-lite@^1.0.30001043: + version "1.0.30001045" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001045.tgz#a770df9de36ad6ca0c34f90eaa797a2dbbb1b619" + integrity sha512-Y8o2Iz1KPcD6FjySbk1sPpvJqchgxk/iow0DABpGyzA1UeQAuxh63Xh0Enj5/BrsYbXtCN32JmR4ZxQTCQ6E6A== + capture-exit@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" @@ -4443,6 +5033,11 @@ capture-exit@^2.0.0: dependencies: rsvp "^4.8.4" +capture-stack-trace@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz#a6c0bbe1f38f3aa0b92238ecb6ff42c344d4135d" + integrity sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw== + caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" @@ -4582,7 +5177,7 @@ chokidar@^3.3.0: optionalDependencies: fsevents "~2.1.2" -chownr@^1.1.1, chownr@^1.1.2: +chownr@^1.1.1, chownr@^1.1.2, chownr@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== @@ -4594,11 +5189,28 @@ chrome-trace-event@^1.0.2: dependencies: tslib "^1.9.0" +chromium-pickle-js@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz#04a106672c18b085ab774d983dfa3ea138f22205" + integrity sha1-BKEGZywYsIWrd02YPfo+oTjyIgU= + +ci-info@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497" + integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A== + ci-info@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== +cidr-regex@^2.0.10: + version "2.0.10" + resolved "https://registry.yarnpkg.com/cidr-regex/-/cidr-regex-2.0.10.tgz#af13878bd4ad704de77d6dc800799358b3afa70d" + integrity sha512-sB3ogMQXWvreNPbJUZMRApxuRYd+KoIo4RGQ81VatjmMW6WJPo+IJZ2846FGItr9VzKo5w7DXzijPLGtSd0N3Q== + dependencies: + ip-regex "^2.1.0" + cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" @@ -4634,6 +5246,24 @@ clean-stack@^2.0.0: resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== +cli-boxes@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143" + integrity sha1-T6kXw+WclKAEzWH47lCdplFocUM= + +cli-boxes@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.0.tgz#538ecae8f9c6ca508e3c3c95b453fe93cb4c168d" + integrity sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w== + +cli-columns@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/cli-columns/-/cli-columns-3.1.2.tgz#6732d972979efc2ae444a1f08e08fa139c96a18e" + integrity sha1-ZzLZcpee/CrkRKHwjgj6E5yWoY4= + dependencies: + string-width "^2.0.0" + strip-ansi "^3.0.1" + cli-cursor@^2.0.0, cli-cursor@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" @@ -4653,6 +5283,16 @@ cli-spinners@^2.0.0: resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.3.0.tgz#0632239a4b5aa4c958610142c34bb7a651fc8df5" integrity sha512-Xs2Hf2nzrvJMFKimOR7YR0QwZ8fc0u98kdtwN1eNAZzNQgH3vK2pXzff6GJtKh7S5hoJ87ECiAiZFS2fb5Ii2w== +cli-table3@^0.5.0, cli-table3@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.5.1.tgz#0252372d94dfc40dbd8df06005f48f31f656f202" + integrity sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw== + dependencies: + object-assign "^4.1.0" + string-width "^2.1.1" + optionalDependencies: + colors "^1.1.2" + cli-truncate@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574" @@ -4662,9 +5302,9 @@ cli-truncate@^0.2.1: string-width "^1.0.1" cli-width@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" - integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= + version "2.2.1" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48" + integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw== cliui@^3.2.0: version "3.2.0" @@ -4734,6 +5374,14 @@ clsx@^1.0.2, clsx@^1.0.4: resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.0.tgz#62937c6adfea771247c34b54d320fb99624f5702" integrity sha512-3avwM37fSK5oP6M5rQ9CNe99lwxhXDOeSWVPAOYF6OazUTgZCMb0yWlJpmdD74REy1gkEaFiub2ULv4fq9GUhA== +cmd-shim@^3.0.0, cmd-shim@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-3.0.3.tgz#2c35238d3df37d98ecdd7d5f6b8dc6b21cadc7cb" + integrity sha512-DtGg+0xiFhQIntSBRzL2fRQBnmtAVwXIDo4Qq46HPpObYquxMaZS4sb82U9nH91qJrlosC1wa9gwr0QyL/HypA== + dependencies: + graceful-fs "^4.1.2" + mkdirp "~0.5.0" + co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -4753,14 +5401,6 @@ code-point-at@^1.0.0: resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= -coinstring@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/coinstring/-/coinstring-2.3.0.tgz#cdb63363a961502404a25afb82c2e26d5ff627a4" - integrity sha1-zbYzY6lhUCQEolr7gsLibV/2J6Q= - dependencies: - bs58 "^2.0.1" - create-hash "^1.1.1" - collect-v8-coverage@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" @@ -4829,6 +5469,14 @@ colors@^1.1.2: resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== +columnify@~1.5.4: + version "1.5.4" + resolved "https://registry.yarnpkg.com/columnify/-/columnify-1.5.4.tgz#4737ddf1c7b69a8a7c340570782e947eec8e78bb" + integrity sha1-Rzfd8ce2mop8NAVweC6UfuyOeLs= + dependencies: + strip-ansi "^3.0.0" + wcwidth "^1.0.0" + combined-stream@^1.0.6, combined-stream@~1.0.6: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" @@ -4837,9 +5485,9 @@ combined-stream@^1.0.6, combined-stream@~1.0.6: delayed-stream "~1.0.0" command-exists@^1.2.8: - version "1.2.8" - resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.8.tgz#715acefdd1223b9c9b37110a149c6392c2852291" - integrity sha512-PM54PkseWbiiD/mMsbvW351/u+dafwTJ0ye2qB60G1aGQP9j3xK2gmMDc+R34L3nDtx4qMCitXT75mkbkGJDLw== + version "1.2.9" + resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" + integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== commander@2.15.1: version "2.15.1" @@ -4922,7 +5570,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.2: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== @@ -4932,6 +5580,41 @@ concat-stream@^1.5.0, concat-stream@^1.5.1: readable-stream "^2.2.2" typedarray "^0.0.6" +concurrently@4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-4.1.2.tgz#1a683b2b5c41e9ed324c9002b9f6e4c6e1f3b6d7" + integrity sha512-Kim9SFrNr2jd8/0yNYqDTFALzUX1tvimmwFWxmp/D4mRI+kbqIIwE2RkBDrxS2ic25O1UgQMI5AtBqdtX3ynYg== + dependencies: + chalk "^2.4.2" + date-fns "^1.30.1" + lodash "^4.17.15" + read-pkg "^4.0.1" + rxjs "^6.5.2" + spawn-command "^0.0.2-1" + supports-color "^4.5.0" + tree-kill "^1.2.1" + yargs "^12.0.5" + +config-chain@^1.1.11, config-chain@^1.1.12: + version "1.1.12" + resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa" + integrity sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA== + dependencies: + ini "^1.3.4" + proto-list "~1.2.1" + +configstore@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.2.tgz#c6f25defaeef26df12dd33414b001fe81a543f8f" + integrity sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw== + dependencies: + dot-prop "^4.1.0" + graceful-fs "^4.1.2" + make-dir "^1.0.0" + unique-string "^1.0.0" + write-file-atomic "^2.0.0" + xdg-basedir "^3.0.0" + configstore@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/configstore/-/configstore-4.0.0.tgz#5933311e95d3687efb592c528b922d9262d227e7" @@ -4961,6 +5644,11 @@ console-browserify@^1.1.0: resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== +console-control-strings@^1.0.0, console-control-strings@^1.1.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= + constants-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" @@ -5045,6 +5733,11 @@ core-js@^2.4.0, core-js@^2.5.0, core-js@^2.6.5: resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== +core-js@^3.6.4: + version "3.6.5" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.5.tgz#7395dc273af37fb2e50e9bd3d9fe841285231d1a" + integrity sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA== + core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -5097,7 +5790,14 @@ create-ecdh@^4.0.0: bn.js "^4.1.0" elliptic "^6.0.0" -create-hash@^1.1.0, create-hash@^1.1.1, create-hash@^1.1.2, create-hash@^1.2.0: +create-error-class@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6" + integrity sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y= + dependencies: + capture-stack-trace "^1.0.0" + +create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== @@ -5120,6 +5820,13 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: safe-buffer "^5.0.1" sha.js "^2.4.8" +cross-env@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.2.tgz#bd5ed31339a93a3418ac4f3ca9ca3403082ae5f9" + integrity sha512-KZP/bMEOJEDCkDQAyRhu3RL2ZO/SUVrxQVI0G3YEQ+OLbRA3c6zgixe8Mq8a/z7+HKlNEjo8oiLUs8iRijY2Rw== + dependencies: + cross-spawn "^7.0.1" + cross-fetch@^2.1.0, cross-fetch@^2.1.1: version "2.2.3" resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-2.2.3.tgz#e8a0b3c54598136e037f8650f8e823ccdfac198e" @@ -5157,7 +5864,7 @@ cross-spawn@^5.0.1: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^7.0.0: +cross-spawn@^7.0.0, cross-spawn@^7.0.1: version "7.0.2" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.2.tgz#d0d7dcfa74e89115c7619f4f721a94e1fdb716d6" integrity sha512-PD6G8QG3S4FK/XCGFbEQrDqO2AnMMsy0meR7lerlIOHAAbkuavGU/pOqprrlvfTNjvowivTeBsjebAL0NSoMxw== @@ -5216,23 +5923,24 @@ css-declaration-sorter@^4.0.1: postcss "^7.0.1" timsort "^0.3.0" -css-loader@3.4.2: - version "3.4.2" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-3.4.2.tgz#d3fdb3358b43f233b78501c5ed7b1c6da6133202" - integrity sha512-jYq4zdZT0oS0Iykt+fqnzVLRIeiPWhka+7BqPn+oSIpWJAHak5tmB/WZrJ2a21JhCeFyNnnlroSl8c+MtVndzA== +css-loader@3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-3.5.2.tgz#6483ae56f48a7f901fbe07dde2fc96b01eafab3c" + integrity sha512-hDL0DPopg6zQQSRlZm0hyeaqIRnL0wbWjay9BZxoiJBpbfOW4WHfbaYQhwnDmEa0kZUc1CJ3IFo15ot1yULMIQ== dependencies: camelcase "^5.3.1" cssesc "^3.0.0" icss-utils "^4.1.1" loader-utils "^1.2.3" normalize-path "^3.0.0" - postcss "^7.0.23" + postcss "^7.0.27" postcss-modules-extract-imports "^2.0.0" postcss-modules-local-by-default "^3.0.2" - postcss-modules-scope "^2.1.1" + postcss-modules-scope "^2.2.0" postcss-modules-values "^3.0.0" - postcss-value-parser "^4.0.2" - schema-utils "^2.6.0" + postcss-value-parser "^4.0.3" + schema-utils "^2.6.5" + semver "^6.3.0" css-select-base-adapter@^0.1.1: version "0.1.1" @@ -5472,12 +6180,12 @@ data-urls@^1.1.0: whatwg-mimetype "^2.2.0" whatwg-url "^7.0.0" -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@2.12.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.12.0.tgz#01754c8a2f3368fc1119cf4625c3dad8c1845ee6" + integrity sha512-qJgn99xxKnFgB1qL4jpxU7Q2t0LOn1p8KMIveef3UZD7kqjT3tpFNNdXJelEHhE+rUgffriXriw/sOSU+cS1Hw== -date-fns@^1.27.2: +date-fns@^1.27.2, date-fns@^1.30.1: version "1.30.1" resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c" integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw== @@ -5519,6 +6227,11 @@ debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: dependencies: ms "^2.1.1" +debuglog@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" + integrity sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI= + decamelize-keys@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" @@ -5544,6 +6257,13 @@ decompress-response@^3.2.0, decompress-response@^3.3.0: dependencies: mimic-response "^1.0.0" +decompress-response@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-4.2.1.tgz#414023cc7a302da25ce2ec82d0d5238ccafd8986" + integrity sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw== + dependencies: + mimic-response "^2.0.0" + decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1" @@ -5621,6 +6341,11 @@ deep-equal@^1.0.1, deep-equal@~1.1.1: object-keys "^1.1.1" regexp.prototype.flags "^1.2.0" +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" @@ -5731,6 +6456,11 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= + depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" @@ -5761,6 +6491,11 @@ detect-indent@^4.0.0: dependencies: repeating "^2.0.0" +detect-indent@~5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d" + integrity sha1-OHHMCmoALow+Wzz38zYmRnXwa50= + detect-installed@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/detect-installed/-/detect-installed-2.0.4.tgz#a0850465e7c3ebcff979d6b6535ad344b80dd7c5" @@ -5768,7 +6503,12 @@ detect-installed@^2.0.4: dependencies: get-installed-path "^2.0.3" -detect-newline@2.X: +detect-libc@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= + +detect-newline@2.X, detect-newline@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" integrity sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I= @@ -5799,6 +6539,14 @@ detect-port@^1.3.0: address "^1.0.1" debug "^2.6.0" +dezalgo@^1.0.0, dezalgo@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456" + integrity sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY= + dependencies: + asap "^2.0.0" + wrappy "1" + diff-sequences@^25.2.6: version "25.2.6" resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-25.2.6.tgz#5f467c00edd35352b7bca46d7927d60e687a76dd" @@ -5826,6 +6574,19 @@ dir-glob@2.0.0: arrify "^1.0.1" path-type "^3.0.0" +dmg-builder@21.2.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/dmg-builder/-/dmg-builder-21.2.0.tgz#a9c883557cacb9abdb66c7133b30fe921c1a3ba7" + integrity sha512-9cJEclnGy7EyKFCoHDYDf54pub/t92CQapyiUxU0w9Bj2vUvfoDagP1PMiX4XD5rPp96141h9A+QN0OB4VgvQg== + dependencies: + app-builder-lib "~21.2.0" + bluebird-lst "^1.0.9" + builder-util "~21.2.0" + fs-extra "^8.1.0" + iconv-lite "^0.5.0" + js-yaml "^3.13.1" + sanitize-filename "^1.6.2" + dns-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" @@ -6004,6 +6765,11 @@ dotenv-expand@^5.1.0: resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz#3fbaf020bfd794884072ea26b1e9791d45a629f0" integrity sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA== +dotenv@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-5.0.1.tgz#a5317459bd3d79ab88cff6e44057a6a3fbb1fcef" + integrity sha512-4As8uPrjfwb7VXC+WnLCbXK7y+Ueb2B3zgNCePYfhxS1PYeaO1YTeplffTEcbfLhvFNGLAz90VvJs9yomG7bow== + dotenv@^8.0.0, dotenv@^8.2.0: version "8.2.0" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a" @@ -6070,21 +6836,122 @@ eccrypto@^1.1.3: optionalDependencies: secp256k1 "3.7.1" +editor@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/editor/-/editor-1.0.0.tgz#60c7f87bd62bcc6a894fa8ccd6afb7823a24f742" + integrity sha1-YMf4e9YrzGqJT6jM1q+3gjok90I= + ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= -ejs@^2.6.1: +ejs@^2.6.1, ejs@^2.6.2: version "2.7.4" resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.4.tgz#48661287573dcc53e366c7a1ae52c3a120eec9ba" integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA== -electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.390, electron-to-chromium@^1.3.47: +ejs@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.0.2.tgz#745b01cdcfe38c1c6a2da3bbb2d9957060a31226" + integrity sha512-IncmUpn1yN84hy2shb0POJ80FWrfGNY0cxO9f4v+/sG7qcBvAtVWUA1IdzY/8EYUmOVhoKJVdJjNd3AZcnxOjA== + +electron-builder@22.2.0: + version "22.2.0" + resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-22.2.0.tgz#f7244b4c92bb5c7323db88f3fb9a22e0ca6cf8a0" + integrity sha512-VYplQwIJOwTLMWfh8nUKL0TdDdOpx1mma9dNbTShy1guySljffZvvD2T/EinBvX1s976Ymqzcq+b+uAUA5SfoA== + dependencies: + app-builder-lib "22.2.0" + bluebird-lst "^1.0.9" + builder-util "22.2.0" + builder-util-runtime "8.5.0" + chalk "^3.0.0" + dmg-builder "21.2.0" + fs-extra "^8.1.0" + is-ci "^2.0.0" + lazy-val "^1.0.4" + read-config-file "5.0.1" + sanitize-filename "^1.6.3" + update-notifier "^3.0.1" + yargs "^15.0.2" + +electron-is-dev@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/electron-is-dev/-/electron-is-dev-1.2.0.tgz#2e5cea0a1b3ccf1c86f577cee77363ef55deb05e" + integrity sha512-R1oD5gMBPS7PVU8gJwH6CtT0e6VSoD0+SzSnYpNm+dBkcijgA+K7VAMHDfnRq/lkKPZArpzplTW6jfiMYosdzw== + +electron-log@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/electron-log/-/electron-log-4.1.1.tgz#c57e3d833f723742eb430dc2cdaa6f97d8dbcaff" + integrity sha512-vkK3rNBOciRiinxrsdgg8hyUia+ct8ZMjBblvKjgNk4uHEDjjSyn313NOwv75xOMVIKlfmYzxaN8kR/oGC33aQ== + +electron-notarize@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/electron-notarize/-/electron-notarize-0.2.1.tgz#759e8006decae19134f82996ed910db26d9192cc" + integrity sha512-oZ6/NhKeXmEKNROiFmRNfytqu3cxqC95sjooG7kBXQVEUSQkZnbiAhxVh5jXngL881G197pbwpeVPJyM7Ikmxw== + dependencies: + debug "^4.1.1" + fs-extra "^8.1.0" + +electron-publish@21.2.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-21.2.0.tgz#cc225cb46aa62e74b899f2f7299b396c9802387d" + integrity sha512-mWavuoWJe87iaeKd0I24dNWIaR+0yRzshjNVqGyK019H766fsPWl3caQJnVKFaEyrZRP397v4JZVG0e7s16AxA== + dependencies: + bluebird-lst "^1.0.9" + builder-util "~21.2.0" + builder-util-runtime "8.3.0" + chalk "^2.4.2" + fs-extra "^8.1.0" + lazy-val "^1.0.4" + mime "^2.4.4" + +electron-publish@22.2.0: + version "22.2.0" + resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-22.2.0.tgz#f391461c70a2c2d1f56babaf6372d09d9e0e6afc" + integrity sha512-B5LTO3zVTPyDfA5ayyBCIrCQ0hBdJ+o7dNOghFYH9/v4s0NDF0cvM1w6EpjRsw/eATeo4c0I1GUObEwTS/ztYw== + dependencies: + bluebird-lst "^1.0.9" + builder-util "~22.2.0" + builder-util-runtime "8.5.0" + chalk "^3.0.0" + fs-extra "^8.1.0" + lazy-val "^1.0.4" + mime "^2.4.4" + +electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.47: version "1.3.403" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.403.tgz#c8bab4e2e72bf78bc28bad1cc355c061f9cc1918" integrity sha512-JaoxV4RzdBAZOnsF4dAlZ2ijJW72MbqO5lNfOBHUWiBQl3Rwe+mk2RCUMrRI3rSClLJ8HSNQNqcry12H+0ZjFw== +electron-to-chromium@^1.3.413: + version "1.3.414" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.414.tgz#9d0a92defefda7cc1cf8895058b892795ddd6b41" + integrity sha512-UfxhIvED++qLwWrAq9uYVcqF8FdeV9sU2S7qhiHYFODxzXRrd1GZRl/PjITHsTEejgibcWDraD8TQqoHb1aCBQ== + +electron-updater@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-4.2.0.tgz#f9ecfc657f65ead737d42b9efecf628d3756b550" + integrity sha512-GuS3g7HDh17x/SaFjxjswlWUaKHczksYkV2Xc5CKj/bZH0YCvTSHtOmnBAdAmCk99u/71p3zP8f0jIqDfGcjww== + dependencies: + "@types/semver" "^6.0.2" + builder-util-runtime "8.4.0" + fs-extra "^8.1.0" + js-yaml "^3.13.1" + lazy-val "^1.0.4" + lodash.isequal "^4.5.0" + pako "^1.0.10" + semver "^6.3.0" + +electron@7.1.8: + version "7.1.8" + resolved "https://registry.yarnpkg.com/electron/-/electron-7.1.8.tgz#7cd50fdf42c55c9de86ab126e983d23fd89d5d99" + integrity sha512-1cWT7toVcSTKu3HdnhDQpbTmI5QCSKtIbg+wHUkSZCdAqjPcuH+dpm+j21g38LbE2DoIzdryaN0RTZOqTPebMA== + dependencies: + "@electron/get" "^1.0.1" + "@types/node" "^12.0.12" + extract-zip "^1.0.3" + elegant-spinner@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e" @@ -6151,7 +7018,7 @@ emojis-list@^3.0.0: resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== -encodeurl@~1.0.2: +encodeurl@^1.0.2, encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= @@ -6174,7 +7041,7 @@ encoding@^0.1.11: dependencies: iconv-lite "~0.4.13" -end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.0: +end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.0, end-of-stream@^1.4.1: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== @@ -6214,6 +7081,16 @@ entities@^2.0.0: resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== +env-paths@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.0.tgz#cdca557dc009152917d6166e2febe1f039685e43" + integrity sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA== + +err-code@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/err-code/-/err-code-1.1.2.tgz#06e0116d3028f6aef4806849eb0ea6a748ae6960" + integrity sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA= + errno@^0.1.3, errno@~0.1.1, errno@~0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" @@ -6263,6 +7140,11 @@ es5-ext@^0.10.35, es5-ext@^0.10.50: es6-symbol "~3.1.3" next-tick "~1.0.0" +es6-error@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" + integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== + es6-iterator@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" @@ -6272,11 +7154,18 @@ es6-iterator@~2.0.3: es5-ext "^0.10.35" es6-symbol "^3.1.1" -es6-promise@4.2.8: +es6-promise@4.2.8, es6-promise@^4.0.3: version "4.2.8" resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== +es6-promisify@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" + integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM= + dependencies: + es6-promise "^4.0.3" + es6-symbol@^3.1.1, es6-symbol@~3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" @@ -6295,7 +7184,7 @@ escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1 resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= -escape-string-regexp@2.0.0: +escape-string-regexp@2.0.0, escape-string-regexp@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== @@ -6418,9 +7307,9 @@ eslint-plugin-react@^7.18.3: xregexp "^4.3.0" eslint-plugin-sort-destructure-keys@^1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-sort-destructure-keys/-/eslint-plugin-sort-destructure-keys-1.3.3.tgz#f8396d1665d1eb70b0ace4972a70dcabadc8d29e" - integrity sha512-+ZI4IsCQe1Xfdxo4kTEtXwfHoOOvhV1u6nG7s8Ot1s6KSYlAlx0bnwXSsLgqGzROYkpSAy/a5JI9pPN3pJQXpw== + version "1.3.4" + resolved "https://registry.yarnpkg.com/eslint-plugin-sort-destructure-keys/-/eslint-plugin-sort-destructure-keys-1.3.4.tgz#0e564bec2bcada21a64f1be9eb243b80a880149b" + integrity sha512-isdXh0LxE6WEUkkmNtpXX0W95wqCyYI6PY3w9aEcrWQ2IqUzgHQpCfMcb8BD5Wlp2Y9i91kk2leDiII43C1kww== dependencies: natural-compare-lite "^1.4.0" @@ -6561,11 +7450,11 @@ esprima@^4.0.0, esprima@^4.0.1: integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== esquery@^1.0.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.2.0.tgz#a010a519c0288f2530b3404124bfb5f02e9797fe" - integrity sha512-weltsSqdeWIX9G2qQZz7KlTRJdkkOCTPgLYJUz1Hacf48R4YOwGPHO3+ORfWedqJKbq5WQmsgK90n+pFLIKt/Q== + version "1.3.1" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.3.1.tgz#b78b5828aa8e214e29fb74c4d5b752e1c033da57" + integrity sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ== dependencies: - estraverse "^5.0.0" + estraverse "^5.1.0" esrecurse@^4.1.0: version "4.2.1" @@ -6579,10 +7468,10 @@ estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== -estraverse@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.0.0.tgz#ac81750b482c11cca26e4b07e83ed8f75fbcdc22" - integrity sha512-j3acdrMzqrxmJTNj5dbr1YbjacrYgAxVMeF0gK16E3j494mOe7xygM/ZLIguEQ0ETwAg2hlJCtHRGav+y0Ny5A== +estraverse@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.1.0.tgz#374309d39fd935ae500e7b92e8a6b4c720e59642" + integrity sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw== estree-walker@^0.6.1: version "0.6.1" @@ -6997,7 +7886,7 @@ ethereumjs-tx@^2.1.1, ethereumjs-tx@^2.1.2: ethereumjs-common "^1.5.0" ethereumjs-util "^6.0.0" -ethereumjs-util@4.5.0, ethereumjs-util@^4.0.1, ethereumjs-util@^4.3.0, ethereumjs-util@^4.4.0: +ethereumjs-util@4.5.0, ethereumjs-util@^4.0.1, ethereumjs-util@^4.3.0: version "4.5.0" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz#3e9428b317eebda3d7260d854fddda954b1f1bc6" integrity sha1-PpQosxfuvaPXJg2FT93alUsfG8Y= @@ -7111,19 +8000,6 @@ ethereumjs-vm@^2.1.0, ethereumjs-vm@^2.3.4, ethereumjs-vm@^2.6.0: rustbn.js "~0.2.0" safe-buffer "^5.1.1" -ethereumjs-wallet@0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-0.6.0.tgz#82763b1697ee7a796be7155da9dfb49b2f98cfdb" - integrity sha1-gnY7Fpfuenlr5xVdqd+0my+Yz9s= - dependencies: - aes-js "^0.2.3" - bs58check "^1.0.8" - ethereumjs-util "^4.4.0" - hdkey "^0.7.0" - scrypt.js "^0.2.0" - utf8 "^2.1.1" - uuid "^2.0.1" - ethereumjs-wallet@0.6.3, ethereumjs-wallet@^0.6.2, ethereumjs-wallet@^0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-0.6.3.tgz#b0eae6f327637c2aeb9ccb9047b982ac542e6ab1" @@ -7156,9 +8032,9 @@ ethers@4.0.0-beta.3: xmlhttprequest "1.8.0" ethers@^4.0.0-beta.1, ethers@^4.0.27, ethers@^4.0.32, ethers@^4.0.36: - version "4.0.46" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.46.tgz#13cd3ed099487f43ece00194b89a8a8781f71507" - integrity sha512-/dPMzzpInhtiip4hKFvsDiJKeRk64IhyA+Po7CtNXneQFSOCYXg8eBFt+jXbxUQyApgWnWOtYxWdfn9+CvvxDA== + version "4.0.47" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.47.tgz#91b9cd80473b1136dd547095ff9171bd1fc68c85" + integrity sha512-hssRYhngV4hiDNeZmVU/k5/E8xmLG8UpcNUzg6mb7lqhgpFPH/t7nuv20RjRrEf0gblzvi2XwR5Te+V3ZFc9pQ== dependencies: aes-js "3.0.0" bn.js "^4.4.0" @@ -7344,6 +8220,11 @@ expand-range@^1.8.1: dependencies: fill-range "^2.1.0" +expand-template@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" + integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== + expand-tilde@^2.0.0, expand-tilde@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" @@ -7363,6 +8244,18 @@ expect@^25.3.0: jest-message-util "^25.3.0" jest-regex-util "^25.2.6" +expect@^25.4.0: + version "25.4.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-25.4.0.tgz#0b16c17401906d1679d173e59f0d4580b22f8dc8" + integrity sha512-7BDIX99BTi12/sNGJXA9KMRcby4iAmu1xccBOhyKCyEhjcVKS3hPmHdA/4nSI9QGIOkUropKqr3vv7WMDM5lvQ== + dependencies: + "@jest/types" "^25.4.0" + ansi-styles "^4.0.0" + jest-get-type "^25.2.6" + jest-matcher-utils "^25.4.0" + jest-message-util "^25.4.0" + jest-regex-util "^25.2.6" + express@^4.14.0, express@^4.16.3, express@^4.17.1: version "4.17.1" resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" @@ -7466,6 +8359,16 @@ extract-text-webpack-plugin@^4.0.0-beta.0: schema-utils "^0.4.5" webpack-sources "^1.1.0" +extract-zip@^1.0.3: + version "1.7.0" + resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.7.0.tgz#556cc3ae9df7f452c493a0cfb51cc30277940927" + integrity sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA== + dependencies: + concat-stream "^1.6.2" + debug "^2.6.9" + mkdirp "^0.5.4" + yauzl "^2.10.0" + extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" @@ -7568,7 +8471,7 @@ fetch-ponyfill@^4.0.0: dependencies: node-fetch "~1.7.1" -figgy-pudding@^3.5.1: +figgy-pudding@^3.4.1, figgy-pudding@^3.5.1: version "3.5.2" resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e" integrity sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw== @@ -7673,10 +8576,10 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" -final-form@4.18.7: - version "4.18.7" - resolved "https://registry.yarnpkg.com/final-form/-/final-form-4.18.7.tgz#c30239ac9154cbfbf4f6d19e831f5fc9cbc1ba78" - integrity sha512-XdlYYGDcoUcKKVzRJxLg8N/ZG3wVLZvhO7K7PKQWVMjCiIUWdmtBwApw2NFS4P7RJvg8OdF73qGXhhE3K5PuDQ== +final-form@4.19.1: + version "4.19.1" + resolved "https://registry.yarnpkg.com/final-form/-/final-form-4.19.1.tgz#1aa1a3bf67f7399b54ed6185d56f9a8d74cfda5a" + integrity sha512-C4RldRCUs8YZod91ydtrsT+TOeG3fwU4ip9oBDXhvbWdQ6iXl4cIrTAQkqpWijbnI3XFVA0akV7YTjSFJMJ2uw== dependencies: "@babel/runtime" "^7.8.3" @@ -7711,6 +8614,11 @@ find-cache-dir@^3.2.0: make-dir "^3.0.2" pkg-dir "^4.1.0" +find-npm-prefix@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/find-npm-prefix/-/find-npm-prefix-1.0.2.tgz#8d8ce2c78b3b4b9e66c8acc6a37c231eb841cfdf" + integrity sha512-KEftzJ+H90x6pcKtdXZEPsQse8/y/UnvzRKrOSQFprnrGaFuJ62fVkP34Iu2IYuMvyauCyoLTNkJZgrrGA2wkA== + find-up@4.1.0, find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" @@ -7777,10 +8685,10 @@ flatted@^2.0.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== -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-bin@0.122.0: + version "0.122.0" + resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.122.0.tgz#c723a2b33b1a70bd10204704ae1dc776d5d89d79" + integrity sha512-my8N5jgl/A+UVby9E7NDppHdhLgRbWgKbmFZSx2MSYMRh3d9YGnM2MM+wexpUpl0ftY1IM6ZcUwaAhrypLyvlA== flow-stoplight@^1.0.0: version "1.0.0" @@ -7885,6 +8793,14 @@ fresh@0.5.2: resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= +from2@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/from2/-/from2-1.3.0.tgz#88413baaa5f9a597cfde9221d86986cd3c061dfd" + integrity sha1-iEE7qqX5pZfP3pIh2GmGzTwGHf0= + dependencies: + inherits "~2.0.1" + readable-stream "~1.1.10" + from2@^2.1.0: version "2.3.0" resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" @@ -8001,7 +8917,16 @@ fs-readdir-recursive@^1.1.0: resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27" integrity sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA== -fs-write-stream-atomic@^1.0.8: +fs-vacuum@^1.2.10, fs-vacuum@~1.2.10: + version "1.2.10" + resolved "https://registry.yarnpkg.com/fs-vacuum/-/fs-vacuum-1.2.10.tgz#b7629bec07a4031a2548fdf99f5ecf1cc8b31e36" + integrity sha1-t2Kb7AekAxolSP35n17PHMizHjY= + dependencies: + graceful-fs "^4.1.2" + path-is-inside "^1.0.1" + rimraf "^2.5.2" + +fs-write-stream-atomic@^1.0.8, fs-write-stream-atomic@~1.0.10: version "1.0.10" resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" integrity sha1-tH31NJPvkR33VzHnCp3tAYnbQMk= @@ -8025,9 +8950,9 @@ fsevents@^1.2.7: nan "^2.12.1" fsevents@^2.1.2, fsevents@~2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.2.tgz#4c0a1fb34bc68e543b4b82a9ec392bfbda840805" - integrity sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA== + version "2.1.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" + integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== function-bind@^1.1.1, function-bind@~1.1.1: version "1.1.1" @@ -8081,11 +9006,47 @@ ganache-core@2.7.0: ethereumjs-wallet "0.6.3" web3 "1.2.1" +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + +genfun@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/genfun/-/genfun-5.0.0.tgz#9dd9710a06900a5c4a5bf57aca5da4e52fe76537" + integrity sha512-KGDOARWVga7+rnB3z9Sd2Letx515owfk0hSxHGuqjANb1M+x2bGZGqHLiozPsYMdM2OubeMni/Hpwmjq6qIUhA== + gensync@^1.0.0-beta.1: version "1.0.0-beta.1" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg== +gentle-fs@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/gentle-fs/-/gentle-fs-2.3.1.tgz#11201bf66c18f930ddca72cf69460bdfa05727b1" + integrity sha512-OlwBBwqCFPcjm33rF2BjW+Pr6/ll2741l+xooiwTCeaX2CA1ZuclavyMBe0/KlR21/XGsgY6hzEQZ15BdNa13Q== + dependencies: + aproba "^1.1.2" + chownr "^1.1.2" + cmd-shim "^3.0.3" + fs-vacuum "^1.2.10" + graceful-fs "^4.1.11" + iferr "^0.1.5" + infer-owner "^1.0.4" + mkdirp "^0.5.1" + path-is-inside "^1.0.2" + read-cmd-shim "^1.0.1" + slide "^1.1.6" + get-caller-file@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" @@ -8179,6 +9140,11 @@ github-download@^0.5.0: request "^2.12.0" vcsurl "~0.1.0" +github-from-package@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" + integrity sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4= + glob-base@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" @@ -8263,6 +9229,26 @@ glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, gl once "^1.3.0" path-is-absolute "^1.0.0" +global-agent@^2.0.2: + version "2.1.8" + resolved "https://registry.yarnpkg.com/global-agent/-/global-agent-2.1.8.tgz#99d153662b2c04cbc1199ffbc081a3aa656ac50f" + integrity sha512-VpBe/rhY6Rw2VDOTszAMNambg+4Qv8j0yiTNDYEXXXxkUNGWLHp8A3ztK4YDBbFNcWF4rgsec6/5gPyryya/+A== + dependencies: + boolean "^3.0.0" + core-js "^3.6.4" + es6-error "^4.1.1" + matcher "^2.1.0" + roarr "^2.15.2" + semver "^7.1.2" + serialize-error "^5.0.0" + +global-dirs@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" + integrity sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU= + dependencies: + ini "^1.3.4" + global-modules@1.0.0, global-modules@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" @@ -8299,6 +9285,16 @@ global-prefix@^3.0.0: kind-of "^6.0.2" which "^1.3.1" +global-tunnel-ng@^2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/global-tunnel-ng/-/global-tunnel-ng-2.7.1.tgz#d03b5102dfde3a69914f5ee7d86761ca35d57d8f" + integrity sha512-4s+DyciWBV0eK148wqXxcmVAbFVPqtc3sEtUE/GTQfuU80rySLcMhUmHKSHI7/LDj8q0gDYI1lIhRRB7ieRAqg== + dependencies: + encodeurl "^1.0.2" + lodash "^4.17.10" + npm-conf "^1.1.3" + tunnel "^0.0.6" + global@^4.3.0: version "4.4.0" resolved "https://registry.yarnpkg.com/global/-/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406" @@ -8332,6 +9328,13 @@ globals@^9.18.0: resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== +globalthis@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.1.tgz#40116f5d9c071f9e8fb0037654df1ab3a83b7ef9" + integrity sha512-mJPRTc/P39NH/iNG4mXa9aIhNymaQikTrnspeCa2ZuJ+mH2QN/rXwtX3XwKrHqWgUQFbNZKtHM105aHzJalElw== + dependencies: + define-properties "^1.1.3" + globby@8.0.2, globby@^8.0.1: version "8.0.2" resolved "https://registry.yarnpkg.com/globby/-/globby-8.0.2.tgz#5697619ccd95c5275dbb2d6faa42087c1a941d8d" @@ -8368,7 +9371,7 @@ globby@^6.1.0: pify "^2.0.0" pinkie-promise "^2.0.0" -got@9.6.0: +got@9.6.0, got@^9.6.0: version "9.6.0" resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== @@ -8385,6 +9388,23 @@ got@9.6.0: to-readable-stream "^1.0.0" url-parse-lax "^3.0.0" +got@^6.7.1: + version "6.7.1" + resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" + integrity sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA= + dependencies: + create-error-class "^3.0.0" + duplexer3 "^0.1.4" + get-stream "^3.0.0" + is-redirect "^1.0.0" + is-retry-allowed "^1.0.0" + is-stream "^1.0.0" + lowercase-keys "^1.0.0" + safe-buffer "^5.0.1" + timed-out "^4.0.0" + unzip-response "^2.0.1" + url-parse-lax "^1.0.0" + got@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a" @@ -8480,6 +9500,11 @@ has-ansi@^2.0.0: dependencies: ansi-regex "^2.0.0" +has-flag@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" + integrity sha1-6CB68cx7MNRGzHC3NLXovhj4jVE= + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -8507,6 +9532,11 @@ has-to-string-tag-x@^1.2.0: dependencies: has-symbol-support-x "^1.4.1" +has-unicode@^2.0.0, has-unicode@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= + has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" @@ -8538,6 +9568,11 @@ has-values@^1.0.0: is-number "^3.0.0" kind-of "^4.0.0" +has-yarn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77" + integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw== + has@^1.0.0, has@^1.0.3, has@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" @@ -8569,20 +9604,12 @@ hash.js@^1.0.0, hash.js@^1.0.3: inherits "^2.0.3" minimalistic-assert "^1.0.1" -hdkey@^0.7.0: - version "0.7.1" - resolved "https://registry.yarnpkg.com/hdkey/-/hdkey-0.7.1.tgz#caee4be81aa77921e909b8d228dd0f29acaee632" - integrity sha1-yu5L6BqneSHpCbjSKN0PKayu5jI= - dependencies: - coinstring "^2.0.0" - secp256k1 "^3.0.1" - hdkey@^1.1.0, hdkey@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/hdkey/-/hdkey-1.1.1.tgz#c2b3bfd5883ff9529b72f2f08b28be0972a9f64a" - integrity sha512-DvHZ5OuavsfWs5yfVJZestsnc3wzPvLWNk6c2nRUfo6X+OtxypGt20vDDf7Ba+MJzjL3KS1og2nw2eBbLCOUTA== + version "1.1.2" + resolved "https://registry.yarnpkg.com/hdkey/-/hdkey-1.1.2.tgz#c60f9cf6f90fbf24a8a52ea06893f36a0108cd3e" + integrity sha512-PTQ4VKu0oRnCrYfLp04iQZ7T2Cxz0UsEXYauk2j8eh6PJXCpbXuCFhOmtIFtbET0i3PMWmHN9J11gU8LEgUljQ== dependencies: - coinstring "^2.0.0" + bs58check "^2.1.2" safe-buffer "^5.1.1" secp256k1 "^3.0.1" @@ -8659,11 +9686,18 @@ hoopy@^0.1.4: resolved "https://registry.yarnpkg.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d" integrity sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ== -hosted-git-info@^2.1.4: +hosted-git-info@^2.1.4, hosted-git-info@^2.7.1, hosted-git-info@^2.8.8: version "2.8.8" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg== +hosted-git-info@^3.0.2: + version "3.0.4" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-3.0.4.tgz#be4973eb1fd2737b11c9c7c19380739bb249f60d" + integrity sha512-4oT62d2jwSDBbLLFLZE+1vPuQ1h8p9wjrJ8Mqx5TjsyWmBMV5B13eJqn8pvluqubLf3cJPTfiYCIwNwDNmzScQ== + dependencies: + lru-cache "^5.1.1" + hpack.js@^2.1.6: version "2.1.6" resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" @@ -8706,18 +9740,18 @@ html-escaper@^2.0.0: resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== -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== +html-loader@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/html-loader/-/html-loader-1.1.0.tgz#91915f4d274caa9d46d1c3dc847cd82bfc037dbd" + integrity sha512-zwLbEgy+i7sgIYTlxI9M7jwkn29IvdsV6f1y7a2aLv/w8l1RigVk0PFijBZLLFsdi2gvL8sf2VJhTjLlfnK8sA== dependencies: - html-minifier-terser "^5.0.4" + html-minifier-terser "^5.0.5" htmlparser2 "^4.1.0" loader-utils "^2.0.0" parse-srcset "^1.0.2" schema-utils "^2.6.5" -html-minifier-terser@^5.0.1, html-minifier-terser@^5.0.4: +html-minifier-terser@^5.0.1, html-minifier-terser@^5.0.5: version "5.0.5" resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-5.0.5.tgz#8f12f639789f04faa9f5cf2ff9b9f65607f21f8b" integrity sha512-cBSFFghQh/uHcfSiL42KxxIRMF7A144+3E44xdlctIjxEmkEfCvouxNyFH2wysXk1fCGBPwtcr3hDWlGTfkDew== @@ -8730,10 +9764,10 @@ html-minifier-terser@^5.0.1, html-minifier-terser@^5.0.4: relateurl "^0.2.7" terser "^4.6.3" -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== +html-webpack-plugin@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-4.2.0.tgz#ea46f15b620d4c1c8c73ea399395c81208e9f823" + integrity sha512-zL7LYTuq/fcJX6vV6tmmvFR508Bd9e6kvVGbS76YAjZ2CPVRzsjkvDYs/SshPevpolSdTWgaDV39D6k6oQoVFw== dependencies: "@types/html-minifier-terser" "^5.0.0" "@types/tapable" "^1.0.5" @@ -8778,6 +9812,11 @@ htmlparser2@~3.8.1: entities "1.0" readable-stream "1.1" +http-cache-semantics@^3.8.1: + version "3.8.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" + integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w== + http-cache-semantics@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" @@ -8830,6 +9869,14 @@ http-https@^1.0.0: resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.10.tgz#92c9c1374c35085f75db359ec56cc257cbb93fa4" integrity sha1-ksnBN0w1CF912zWexWzCV8u5P6Q= +http-proxy-agent@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405" + integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg== + dependencies: + agent-base "4" + debug "3.1.0" + http-proxy-middleware@0.19.1: version "0.19.1" resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz#183c7dc4aa1479150306498c210cdaf96080a43a" @@ -8863,11 +9910,26 @@ https-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= +https-proxy-agent@^2.2.3: + version "2.2.4" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b" + integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg== + dependencies: + agent-base "^4.3.0" + debug "^3.1.0" + human-signals@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== +humanize-ms@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" + integrity sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0= + dependencies: + ms "^2.0.0" + husky@^4.2.2: version "4.2.5" resolved "https://registry.yarnpkg.com/husky/-/husky-4.2.5.tgz#2b4f7622673a71579f901d9885ed448394b5fa36" @@ -8904,6 +9966,13 @@ iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@~0.4.13: dependencies: safer-buffer ">= 2.1.2 < 3" +iconv-lite@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.5.1.tgz#b2425d3c7b18f7219f2ca663d103bddb91718d64" + integrity sha512-ONHr16SQvKZNSqjQT9gy5z24Jw+uqfO02/ngBSBoqChZ+W8qXX7GPRa1RoUnzGADw8K63R1BXUMzarCVQBpY8Q== + dependencies: + safer-buffer ">= 2.1.2 < 3" + icss-utils@^4.0.0, icss-utils@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467" @@ -8933,6 +10002,18 @@ iferr@^0.1.5: resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE= +iferr@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/iferr/-/iferr-1.0.2.tgz#e9fde49a9da06dc4a4194c6c9ed6d08305037a6d" + integrity sha512-9AfeLfji44r5TKInjhz3W9DyZI1zR1JAf2hVBMGhddAKPqBsupb89jGfbCTHIGZd6fGZl9WlHdn4AObygyMKwg== + +ignore-walk@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.3.tgz#017e2447184bfeade7c238e4aefdd1e8f95b1e37" + integrity sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw== + dependencies: + minimatch "^3.0.4" + ignore@^3.3.5: version "3.3.10" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" @@ -8996,6 +10077,11 @@ import-from@^2.1.0: dependencies: resolve-from "^3.0.0" +import-lazy@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" + integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= + import-local@2.0.0, import-local@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" @@ -9037,7 +10123,7 @@ infer-owner@^1.0.3, infer-owner@^1.0.4: resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== -inflight@^1.0.4: +inflight@^1.0.4, inflight@~1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= @@ -9060,11 +10146,25 @@ inherits@2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= -ini@^1.3.4, ini@^1.3.5: +ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: version "1.3.5" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== +init-package-json@^1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/init-package-json/-/init-package-json-1.10.3.tgz#45ffe2f610a8ca134f2bd1db5637b235070f6cbe" + integrity sha512-zKSiXKhQveNteyhcj1CoOP8tqp1QuxPIPBl8Bid99DGLFqA1p87M6lNgfjJHSBoWJJlidGOv5rWjyYKEB3g2Jw== + dependencies: + glob "^7.1.1" + npm-package-arg "^4.0.0 || ^5.0.0 || ^6.0.0" + promzard "^0.3.0" + read "~1.0.1" + read-package-json "1 || 2" + semver "2.x || 3.x || 4 || 5" + validate-npm-package-license "^3.0.1" + validate-npm-package-name "^3.0.0" + inquirer@7.0.4: version "7.0.4" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.0.4.tgz#99af5bde47153abca23f5c7fc30db247f39da703" @@ -9122,6 +10222,11 @@ inquirer@^7.0.0: strip-ansi "^6.0.0" through "^2.3.6" +install@^0.13.0: + version "0.13.0" + resolved "https://registry.yarnpkg.com/install/-/install-0.13.0.tgz#6af6e9da9dd0987de2ab420f78e60d9c17260776" + integrity sha512-zDml/jzr2PKU9I8J/xyZBQn8rPCAY//UOYNmR01XwNwyfhEWObo2SWfSl1+0tm1u6PhxLwDnfsT/6jB7OUxqFA== + internal-ip@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-4.3.0.tgz#845452baad9d2ca3b69c635a137acb9a0dad0907" @@ -9166,7 +10271,7 @@ ip-regex@^2.1.0: resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" integrity sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk= -ip@^1.1.0, ip@^1.1.5: +ip@1.1.5, ip@^1.1.0, ip@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= @@ -9251,6 +10356,13 @@ is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.1.5: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== +is-ci@^1.0.10: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c" + integrity sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg== + dependencies: + ci-info "^1.5.0" + is-ci@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" @@ -9258,6 +10370,13 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" +is-cidr@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-cidr/-/is-cidr-3.1.0.tgz#72e233d8e1c4cd1d3f11713fcce3eba7b0e3476f" + integrity sha512-3kxTForpuj8O4iHn0ocsn1jxRm5VYm60GDghK6HXmpn4IyZOoRy9/GmdjFA2yEMqw91TB1/K3bFTuI7FlFNR1g== + dependencies: + cidr-regex "^2.0.10" + is-color-stop@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345" @@ -9419,11 +10538,29 @@ is-in-browser@^1.0.2, is-in-browser@^1.1.3: resolved "https://registry.yarnpkg.com/is-in-browser/-/is-in-browser-1.1.3.tgz#56ff4db683a078c6082eb95dad7dc62e1d04f835" integrity sha1-Vv9NtoOgeMYILrldrX3GLh0E+DU= +is-installed-globally@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.1.0.tgz#0dfd98f5a9111716dd535dda6492f67bf3d25a80" + integrity sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA= + dependencies: + global-dirs "^0.1.0" + is-path-inside "^1.0.0" + is-natural-number@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" integrity sha1-q5124dtM7VHjXeDHLr7PCfc0zeg= +is-npm@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4" + integrity sha1-8vtjpl5JBbQGyGBydloaTceTufQ= + +is-npm@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-3.0.0.tgz#ec9147bfb629c43f494cf67936a961edec7e8053" + integrity sha512-wsigDr1Kkschp2opC4G3yA6r9EgVA6NjRpWzIi9axXqeIaAATPRJc4uLujXe3Nd9uO8KoDyA4MD6aZSeXTADhA== + is-number@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" @@ -9535,6 +10672,11 @@ is-promise@^2.1.0: resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= +is-redirect@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" + integrity sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ= + is-reference@^1.1.2: version "1.1.4" resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.1.4.tgz#3f95849886ddb70256a3e6d062b1a68c13c51427" @@ -9628,6 +10770,11 @@ is-wsl@^2.1.1: resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.1.1.tgz#4a1c152d429df3d441669498e2486d3596ebaf1d" integrity sha512-umZHcSrwlDHo2TGMXv0DZ8dIUGunZ2Iv68YZnrmCiBPkZ4aaOhtv7pXJKeki9k3qJ3RJr0cDyitcl5wEH3AYog== +is-yarn-global@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232" + integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw== + isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" @@ -9638,6 +10785,11 @@ isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= +isbinaryfile@^4.0.2: + version "4.0.6" + resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.6.tgz#edcb62b224e2b4710830b67498c8e4e5a4d2610b" + integrity sha512-ORrEy+SNVqUhrCaal4hA4fBzhggQQ+BaLntyPOdoEiwlKZW9BZiJXjg3RMiruE4tPEI3pyVPpySHQF/dKWperg== + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -9729,21 +10881,30 @@ jest-changed-files@^25.3.0: execa "^3.2.0" throat "^5.0.0" -jest-cli@^25.2.4: - version "25.3.0" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-25.3.0.tgz#d9e11f5700cc5946583cf0d01a9bdebceed448d2" - integrity sha512-XpNQPlW1tzpP7RGG8dxpkRegYDuLjzSiENu92+CYM87nEbmEPb3b4+yo8xcsHOnj0AG7DUt9b3uG8LuHI3MDzw== +jest-changed-files@^25.4.0: + version "25.4.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-25.4.0.tgz#e573db32c2fd47d2b90357ea2eda0622c5c5cbd6" + integrity sha512-VR/rfJsEs4BVMkwOTuStRyS630fidFVekdw/lBaBQjx9KK3VZFOZ2c0fsom2fRp8pMCrCTP6LGna00o/DXGlqA== dependencies: - "@jest/core" "^25.3.0" - "@jest/test-result" "^25.3.0" - "@jest/types" "^25.3.0" + "@jest/types" "^25.4.0" + execa "^3.2.0" + throat "^5.0.0" + +jest-cli@^25.3.0: + version "25.4.0" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-25.4.0.tgz#5dac8be0fece6ce39f0d671395a61d1357322bab" + integrity sha512-usyrj1lzCJZMRN1r3QEdnn8e6E6yCx/QN7+B1sLoA68V7f3WlsxSSQfy0+BAwRiF4Hz2eHauf11GZG3PIfWTXQ== + dependencies: + "@jest/core" "^25.4.0" + "@jest/test-result" "^25.4.0" + "@jest/types" "^25.4.0" chalk "^3.0.0" exit "^0.1.2" import-local "^3.0.2" is-ci "^2.0.0" - jest-config "^25.3.0" - jest-util "^25.3.0" - jest-validate "^25.3.0" + jest-config "^25.4.0" + jest-util "^25.4.0" + jest-validate "^25.4.0" prompts "^2.0.1" realpath-native "^2.0.0" yargs "^15.3.1" @@ -9772,6 +10933,30 @@ jest-config@^25.3.0: pretty-format "^25.3.0" realpath-native "^2.0.0" +jest-config@^25.4.0: + version "25.4.0" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-25.4.0.tgz#56e5df3679a96ff132114b44fb147389c8c0a774" + integrity sha512-egT9aKYxMyMSQV1aqTgam0SkI5/I2P9qrKexN5r2uuM2+68ypnc+zPGmfUxK7p1UhE7dYH9SLBS7yb+TtmT1AA== + dependencies: + "@babel/core" "^7.1.0" + "@jest/test-sequencer" "^25.4.0" + "@jest/types" "^25.4.0" + babel-jest "^25.4.0" + chalk "^3.0.0" + deepmerge "^4.2.2" + glob "^7.1.1" + jest-environment-jsdom "^25.4.0" + jest-environment-node "^25.4.0" + jest-get-type "^25.2.6" + jest-jasmine2 "^25.4.0" + jest-regex-util "^25.2.6" + jest-resolve "^25.4.0" + jest-util "^25.4.0" + jest-validate "^25.4.0" + micromatch "^4.0.2" + pretty-format "^25.4.0" + realpath-native "^2.0.0" + jest-diff@^25.1.0, jest-diff@^25.2.1, jest-diff@^25.3.0: version "25.3.0" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-25.3.0.tgz#0d7d6f5d6171e5dacde9e05be47b3615e147c26f" @@ -9782,6 +10967,16 @@ jest-diff@^25.1.0, jest-diff@^25.2.1, jest-diff@^25.3.0: jest-get-type "^25.2.6" pretty-format "^25.3.0" +jest-diff@^25.4.0: + version "25.4.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-25.4.0.tgz#260b70f19a46c283adcad7f081cae71eb784a634" + integrity sha512-kklLbJVXW0y8UKOWOdYhI6TH5MG6QAxrWiBMgQaPIuhj3dNFGirKCd+/xfplBXICQ7fI+3QcqHm9p9lWu1N6ug== + dependencies: + chalk "^3.0.0" + diff-sequences "^25.2.6" + jest-get-type "^25.2.6" + pretty-format "^25.4.0" + jest-docblock@^25.3.0: version "25.3.0" resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-25.3.0.tgz#8b777a27e3477cd77a168c05290c471a575623ef" @@ -9805,6 +11000,17 @@ jest-each@^25.3.0: jest-util "^25.3.0" pretty-format "^25.3.0" +jest-each@^25.4.0: + version "25.4.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-25.4.0.tgz#ad4e46164764e8e77058f169a0076a7f86f6b7d4" + integrity sha512-lwRIJ8/vQU/6vq3nnSSUw1Y3nz5tkYSFIywGCZpUBd6WcRgpn8NmJoQICojbpZmsJOJNHm0BKdyuJ6Xdx+eDQQ== + dependencies: + "@jest/types" "^25.4.0" + chalk "^3.0.0" + jest-get-type "^25.2.6" + jest-util "^25.4.0" + pretty-format "^25.4.0" + jest-environment-jsdom@^25.3.0: version "25.3.0" resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-25.3.0.tgz#c493ab8c41f28001520c70ef67dd88b88be6af05" @@ -9817,6 +11023,18 @@ jest-environment-jsdom@^25.3.0: jest-util "^25.3.0" jsdom "^15.2.1" +jest-environment-jsdom@^25.4.0: + version "25.4.0" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-25.4.0.tgz#bbfc7f85bb6ade99089062a830c79cb454565cf0" + integrity sha512-KTitVGMDrn2+pt7aZ8/yUTuS333w3pWt1Mf88vMntw7ZSBNDkRS6/4XLbFpWXYfWfp1FjcjQTOKzbK20oIehWQ== + dependencies: + "@jest/environment" "^25.4.0" + "@jest/fake-timers" "^25.4.0" + "@jest/types" "^25.4.0" + jest-mock "^25.4.0" + jest-util "^25.4.0" + jsdom "^15.2.1" + jest-environment-node@^25.3.0: version "25.3.0" resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-25.3.0.tgz#9845f0e63991e8498448cb0ae804935689533db9" @@ -9829,6 +11047,18 @@ jest-environment-node@^25.3.0: jest-util "^25.3.0" semver "^6.3.0" +jest-environment-node@^25.4.0: + version "25.4.0" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-25.4.0.tgz#188aef01ae6418e001c03fdd1c299961e1439082" + integrity sha512-wryZ18vsxEAKFH7Z74zi/y/SyI1j6UkVZ6QsllBuT/bWlahNfQjLNwFsgh/5u7O957dYFoXj4yfma4n4X6kU9A== + dependencies: + "@jest/environment" "^25.4.0" + "@jest/fake-timers" "^25.4.0" + "@jest/types" "^25.4.0" + jest-mock "^25.4.0" + jest-util "^25.4.0" + semver "^6.3.0" + jest-get-type@^25.2.6: version "25.2.6" resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-25.2.6.tgz#0b0a32fab8908b44d508be81681487dbabb8d877" @@ -9853,6 +11083,25 @@ jest-haste-map@^25.3.0: optionalDependencies: fsevents "^2.1.2" +jest-haste-map@^25.4.0: + version "25.4.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-25.4.0.tgz#da7c309dd7071e0a80c953ba10a0ec397efb1ae2" + integrity sha512-5EoCe1gXfGC7jmXbKzqxESrgRcaO3SzWXGCnvp9BcT0CFMyrB1Q6LIsjl9RmvmJGQgW297TCfrdgiy574Rl9HQ== + dependencies: + "@jest/types" "^25.4.0" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.3" + jest-serializer "^25.2.6" + jest-util "^25.4.0" + jest-worker "^25.4.0" + micromatch "^4.0.2" + sane "^4.0.3" + walker "^1.0.7" + which "^2.0.2" + optionalDependencies: + fsevents "^2.1.2" + jest-jasmine2@^25.3.0: version "25.3.0" resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-25.3.0.tgz#16ae4f68adef65fb45001b26c864bcbcbf972830" @@ -9876,6 +11125,29 @@ jest-jasmine2@^25.3.0: pretty-format "^25.3.0" throat "^5.0.0" +jest-jasmine2@^25.4.0: + version "25.4.0" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-25.4.0.tgz#3d3d19514022e2326e836c2b66d68b4cb63c5861" + integrity sha512-QccxnozujVKYNEhMQ1vREiz859fPN/XklOzfQjm2j9IGytAkUbSwjFRBtQbHaNZ88cItMpw02JnHGsIdfdpwxQ== + dependencies: + "@babel/traverse" "^7.1.0" + "@jest/environment" "^25.4.0" + "@jest/source-map" "^25.2.6" + "@jest/test-result" "^25.4.0" + "@jest/types" "^25.4.0" + chalk "^3.0.0" + co "^4.6.0" + expect "^25.4.0" + is-generator-fn "^2.0.0" + jest-each "^25.4.0" + jest-matcher-utils "^25.4.0" + jest-message-util "^25.4.0" + jest-runtime "^25.4.0" + jest-snapshot "^25.4.0" + jest-util "^25.4.0" + pretty-format "^25.4.0" + throat "^5.0.0" + jest-leak-detector@^25.3.0: version "25.3.0" resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-25.3.0.tgz#5b6bf04903b35be56038915a55f47291771f769f" @@ -9884,6 +11156,14 @@ jest-leak-detector@^25.3.0: jest-get-type "^25.2.6" pretty-format "^25.3.0" +jest-leak-detector@^25.4.0: + version "25.4.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-25.4.0.tgz#cf94a160c78e53d810e7b2f40b5fd7ee263375b3" + integrity sha512-7Y6Bqfv2xWsB+7w44dvZuLs5SQ//fzhETgOGG7Gq3TTGFdYvAgXGwV8z159RFZ6fXiCPm/szQ90CyfVos9JIFQ== + dependencies: + jest-get-type "^25.2.6" + pretty-format "^25.4.0" + jest-matcher-utils@^25.1.0, jest-matcher-utils@^25.3.0: version "25.3.0" resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-25.3.0.tgz#76765788a26edaa8bc5f0100aea52ae383559648" @@ -9894,6 +11174,16 @@ jest-matcher-utils@^25.1.0, jest-matcher-utils@^25.3.0: jest-get-type "^25.2.6" pretty-format "^25.3.0" +jest-matcher-utils@^25.4.0: + version "25.4.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-25.4.0.tgz#dc3e7aec402a1e567ed80b572b9ad285878895e6" + integrity sha512-yPMdtj7YDgXhnGbc66bowk8AkQ0YwClbbwk3Kzhn5GVDrciiCr27U4NJRbrqXbTdtxjImONITg2LiRIw650k5A== + dependencies: + chalk "^3.0.0" + jest-diff "^25.4.0" + jest-get-type "^25.2.6" + pretty-format "^25.4.0" + jest-message-util@^25.3.0: version "25.3.0" resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-25.3.0.tgz#e3836826fe5ca538a337b87d9bd2648190867f85" @@ -9907,6 +11197,19 @@ jest-message-util@^25.3.0: slash "^3.0.0" stack-utils "^1.0.1" +jest-message-util@^25.4.0: + version "25.4.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-25.4.0.tgz#2899e8bc43f5317acf8dfdfe89ea237d354fcdab" + integrity sha512-LYY9hRcVGgMeMwmdfh9tTjeux1OjZHMusq/E5f3tJN+dAoVVkJtq5ZUEPIcB7bpxDUt2zjUsrwg0EGgPQ+OhXQ== + dependencies: + "@babel/code-frame" "^7.0.0" + "@jest/types" "^25.4.0" + "@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.3.0: version "25.3.0" resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-25.3.0.tgz#d72644509e40987a732a9a2534a1054f4649402c" @@ -9914,6 +11217,13 @@ jest-mock@^25.3.0: dependencies: "@jest/types" "^25.3.0" +jest-mock@^25.4.0: + version "25.4.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-25.4.0.tgz#ded7d64b5328d81d78d2138c825d3a45e30ec8ca" + integrity sha512-MdazSfcYAUjJjuVTTnusLPzE0pE4VXpOUzWdj8sbM+q6abUjm3bATVPXFqTXrxSieR8ocpvQ9v/QaQCftioQFg== + dependencies: + "@jest/types" "^25.4.0" + 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" @@ -9933,6 +11243,15 @@ jest-resolve-dependencies@^25.3.0: jest-regex-util "^25.2.6" jest-snapshot "^25.3.0" +jest-resolve-dependencies@^25.4.0: + version "25.4.0" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-25.4.0.tgz#783937544cfc40afcc7c569aa54748c4b3f83f5a" + integrity sha512-A0eoZXx6kLiuG1Ui7wITQPl04HwjLErKIJTt8GR3c7UoDAtzW84JtCrgrJ6Tkw6c6MwHEyAaLk7dEPml5pf48A== + dependencies: + "@jest/types" "^25.4.0" + jest-regex-util "^25.2.6" + jest-snapshot "^25.4.0" + jest-resolve@^25.3.0: version "25.3.0" resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-25.3.0.tgz#cb90a5bbea54a02eccdbbf4126a819595dcf91d6" @@ -9945,6 +11264,20 @@ jest-resolve@^25.3.0: realpath-native "^2.0.0" resolve "^1.15.1" +jest-resolve@^25.4.0: + version "25.4.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-25.4.0.tgz#6f4540ce0d419c4c720e791e871da32ba4da7a60" + integrity sha512-wOsKqVDFWUiv8BtLMCC6uAJ/pHZkfFgoBTgPtmYlsprAjkxrr2U++ZnB3l5ykBMd2O24lXvf30SMAjJIW6k2aA== + dependencies: + "@jest/types" "^25.4.0" + browser-resolve "^1.11.3" + chalk "^3.0.0" + jest-pnp-resolver "^1.2.1" + read-pkg-up "^7.0.1" + realpath-native "^2.0.0" + resolve "^1.15.1" + slash "^3.0.0" + jest-runner@^25.3.0: version "25.3.0" resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-25.3.0.tgz#673ef2ac79d2810eb6b2c1a3f82398375a3d1174" @@ -9970,6 +11303,31 @@ jest-runner@^25.3.0: source-map-support "^0.5.6" throat "^5.0.0" +jest-runner@^25.4.0: + version "25.4.0" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-25.4.0.tgz#6ca4a3d52e692bbc081228fa68f750012f1f29e5" + integrity sha512-wWQSbVgj2e/1chFdMRKZdvlmA6p1IPujhpLT7TKNtCSl1B0PGBGvJjCaiBal/twaU2yfk8VKezHWexM8IliBfA== + dependencies: + "@jest/console" "^25.4.0" + "@jest/environment" "^25.4.0" + "@jest/test-result" "^25.4.0" + "@jest/types" "^25.4.0" + chalk "^3.0.0" + exit "^0.1.2" + graceful-fs "^4.2.3" + jest-config "^25.4.0" + jest-docblock "^25.3.0" + jest-haste-map "^25.4.0" + jest-jasmine2 "^25.4.0" + jest-leak-detector "^25.4.0" + jest-message-util "^25.4.0" + jest-resolve "^25.4.0" + jest-runtime "^25.4.0" + jest-util "^25.4.0" + jest-worker "^25.4.0" + source-map-support "^0.5.6" + throat "^5.0.0" + jest-runtime@^25.3.0: version "25.3.0" resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-25.3.0.tgz#af4d40dbcc590fa5de9910cb6a120a13d131050b" @@ -10001,6 +11359,37 @@ jest-runtime@^25.3.0: strip-bom "^4.0.0" yargs "^15.3.1" +jest-runtime@^25.4.0: + version "25.4.0" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-25.4.0.tgz#1e5227a9e2159d26ae27dcd426ca6bc041983439" + integrity sha512-lgNJlCDULtXu9FumnwCyWlOub8iytijwsPNa30BKrSNtgoT6NUMXOPrZvsH06U6v0wgD/Igwz13nKA2wEKU2VA== + dependencies: + "@jest/console" "^25.4.0" + "@jest/environment" "^25.4.0" + "@jest/source-map" "^25.2.6" + "@jest/test-result" "^25.4.0" + "@jest/transform" "^25.4.0" + "@jest/types" "^25.4.0" + "@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.4.0" + jest-haste-map "^25.4.0" + jest-message-util "^25.4.0" + jest-mock "^25.4.0" + jest-regex-util "^25.2.6" + jest-resolve "^25.4.0" + jest-snapshot "^25.4.0" + jest-util "^25.4.0" + jest-validate "^25.4.0" + realpath-native "^2.0.0" + slash "^3.0.0" + strip-bom "^4.0.0" + yargs "^15.3.1" + jest-serializer@^25.2.6: version "25.2.6" resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-25.2.6.tgz#3bb4cc14fe0d8358489dbbefbb8a4e708ce039b7" @@ -10026,6 +11415,26 @@ jest-snapshot@^25.3.0: pretty-format "^25.3.0" semver "^6.3.0" +jest-snapshot@^25.4.0: + version "25.4.0" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-25.4.0.tgz#e0b26375e2101413fd2ccb4278a5711b1922545c" + integrity sha512-J4CJ0X2SaGheYRZdLz9CRHn9jUknVmlks4UBeu270hPAvdsauFXOhx9SQP2JtRzhnR3cvro/9N9KP83/uvFfRg== + dependencies: + "@babel/types" "^7.0.0" + "@jest/types" "^25.4.0" + "@types/prettier" "^1.19.0" + chalk "^3.0.0" + expect "^25.4.0" + jest-diff "^25.4.0" + jest-get-type "^25.2.6" + jest-matcher-utils "^25.4.0" + jest-message-util "^25.4.0" + jest-resolve "^25.4.0" + make-dir "^3.0.0" + natural-compare "^1.4.0" + pretty-format "^25.4.0" + semver "^6.3.0" + jest-util@^25.3.0: version "25.3.0" resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-25.3.0.tgz#e3b0064165818f10d78514696fd25efba82cf049" @@ -10036,6 +11445,16 @@ jest-util@^25.3.0: is-ci "^2.0.0" make-dir "^3.0.0" +jest-util@^25.4.0: + version "25.4.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-25.4.0.tgz#6a093d09d86d2b41ef583e5fe7dd3976346e1acd" + integrity sha512-WSZD59sBtAUjLv1hMeKbNZXmMcrLRWcYqpO8Dz8b4CeCTZpfNQw2q9uwrYAD+BbJoLJlu4ezVPwtAmM/9/SlZA== + dependencies: + "@jest/types" "^25.4.0" + chalk "^3.0.0" + is-ci "^2.0.0" + make-dir "^3.0.0" + jest-validate@^25.3.0: version "25.3.0" resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-25.3.0.tgz#eb95fdee0039647bcd5d4be641b21e4a142a880c" @@ -10048,6 +11467,18 @@ jest-validate@^25.3.0: leven "^3.1.0" pretty-format "^25.3.0" +jest-validate@^25.4.0: + version "25.4.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-25.4.0.tgz#2e177a93b716a137110eaf2768f3d9095abd3f38" + integrity sha512-hvjmes/EFVJSoeP1yOl8qR8mAtMR3ToBkZeXrD/ZS9VxRyWDqQ/E1C5ucMTeSmEOGLipvdlyipiGbHJ+R1MQ0g== + dependencies: + "@jest/types" "^25.4.0" + camelcase "^5.3.1" + chalk "^3.0.0" + jest-get-type "^25.2.6" + leven "^3.1.0" + pretty-format "^25.4.0" + jest-watcher@^25.3.0: version "25.3.0" resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-25.3.0.tgz#fd03fd5ca52f02bd3161ab177466bf1bfdd34e5c" @@ -10060,22 +11491,34 @@ jest-watcher@^25.3.0: jest-util "^25.3.0" string-length "^3.1.0" -jest-worker@^25.1.0, jest-worker@^25.2.6: - version "25.2.6" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-25.2.6.tgz#d1292625326794ce187c38f51109faced3846c58" - integrity sha512-FJn9XDUSxcOR4cwDzRfL1z56rUofNTFs539FGASpd50RHdb6EVkhxQqktodW2mI49l+W3H+tFJDotCHUQF6dmA== +jest-watcher@^25.4.0: + version "25.4.0" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-25.4.0.tgz#63ec0cd5c83bb9c9d1ac95be7558dd61c995ff05" + integrity sha512-36IUfOSRELsKLB7k25j/wutx0aVuHFN6wO94gPNjQtQqFPa2rkOymmx9rM5EzbF3XBZZ2oqD9xbRVoYa2w86gw== + dependencies: + "@jest/test-result" "^25.4.0" + "@jest/types" "^25.4.0" + ansi-escapes "^4.2.1" + chalk "^3.0.0" + jest-util "^25.4.0" + string-length "^3.1.0" + +jest-worker@^25.1.0, jest-worker@^25.2.6, jest-worker@^25.4.0: + version "25.4.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-25.4.0.tgz#ee0e2ceee5a36ecddf5172d6d7e0ab00df157384" + integrity sha512-ghAs/1FtfYpMmYQ0AHqxV62XPvKdUDIBBApMZfly+E9JEmYh2K45G0R5dWxx986RN12pRCxsViwQVtGl+N4whw== dependencies: 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== +jest@25.3.0: + version "25.3.0" + resolved "https://registry.yarnpkg.com/jest/-/jest-25.3.0.tgz#7a5e59741d94b8662664c77a9f346246d6bf228b" + integrity sha512-iKd5ShQSHzFT5IL/6h5RZJhApgqXSoPxhp5HEi94v6OAw9QkF8T7X+liEU2eEHJ1eMFYTHmeWLrpBWulsDpaUg== dependencies: - "@jest/core" "^25.2.4" + "@jest/core" "^25.3.0" import-local "^3.0.2" - jest-cli "^25.2.4" + jest-cli "^25.3.0" js-cookie@^2.2.1: version "2.2.1" @@ -10215,7 +11658,7 @@ json-loader@^0.5.7: resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.7.tgz#dca14a70235ff82f0ac9a3abeb60d337a365185d" integrity sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w== -json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: +json-parse-better-errors@^1.0.0, json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== @@ -10296,7 +11739,7 @@ json-stable-stringify@^1.0.1: dependencies: jsonify "~0.0.0" -json-stringify-safe@~5.0.1: +json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= @@ -10318,7 +11761,7 @@ json5@^1.0.1: dependencies: minimist "^1.2.0" -json5@^2.1.2: +json5@^2.1.0, json5@^2.1.1, json5@^2.1.2: version "2.1.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43" integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA== @@ -10353,6 +11796,11 @@ jsonify@~0.0.0: resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= +jsonparse@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" + integrity sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA= + jsonschema@^1.1.1: version "1.2.6" resolved "https://registry.yarnpkg.com/jsonschema/-/jsonschema-1.2.6.tgz#52b0a8e9dc06bbae7295249d03e4b9faee8a0c0b" @@ -10547,11 +11995,35 @@ last-call-webpack-plugin@^3.0.0: lodash "^4.17.5" webpack-sources "^1.1.0" +latest-version@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-3.1.0.tgz#a205383fea322b33b5ae3b18abee0dc2f356ee15" + integrity sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU= + dependencies: + package-json "^4.0.0" + +latest-version@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" + integrity sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA== + dependencies: + package-json "^6.3.0" + 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" integrity sha1-U3cWwHduTPeePtG2IfdljCkRsbE= +lazy-property@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lazy-property/-/lazy-property-1.0.0.tgz#84ddc4b370679ba8bd4cdcfa4c06b43d57111147" + integrity sha1-hN3Es3Bnm6i9TNz6TAa0PVcREUc= + +lazy-val@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/lazy-val/-/lazy-val-1.0.4.tgz#882636a7245c2cfe6e0a4e3ba6c5d68a137e5c65" + integrity sha512-u93kb2fPbIrfzBuLjZE+w+fJbUUMhNDXxNmMfaqNgpfQf1CO5ZSe2LfsnBqVAk7i/2NF48OSoRj+Xe2VT+lE8Q== + lazystream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4" @@ -10727,6 +12199,140 @@ levn@^0.3.0, levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" +libcipm@^4.0.7: + version "4.0.8" + resolved "https://registry.yarnpkg.com/libcipm/-/libcipm-4.0.8.tgz#dcea4919e10dfbce420327e63901613b9141bc89" + integrity sha512-IN3hh2yDJQtZZ5paSV4fbvJg4aHxCCg5tcZID/dSVlTuUiWktsgaldVljJv6Z5OUlYspx6xQkbR0efNodnIrOA== + dependencies: + bin-links "^1.1.2" + bluebird "^3.5.1" + figgy-pudding "^3.5.1" + find-npm-prefix "^1.0.2" + graceful-fs "^4.1.11" + ini "^1.3.5" + lock-verify "^2.1.0" + mkdirp "^0.5.1" + npm-lifecycle "^3.0.0" + npm-logical-tree "^1.2.1" + npm-package-arg "^6.1.0" + pacote "^9.1.0" + read-package-json "^2.0.13" + rimraf "^2.6.2" + worker-farm "^1.6.0" + +libnpm@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/libnpm/-/libnpm-3.0.1.tgz#0be11b4c9dd4d1ffd7d95c786e92e55d65be77a2" + integrity sha512-d7jU5ZcMiTfBqTUJVZ3xid44fE5ERBm9vBnmhp2ECD2Ls+FNXWxHSkO7gtvrnbLO78gwPdNPz1HpsF3W4rjkBQ== + dependencies: + bin-links "^1.1.2" + bluebird "^3.5.3" + find-npm-prefix "^1.0.2" + libnpmaccess "^3.0.2" + libnpmconfig "^1.2.1" + libnpmhook "^5.0.3" + libnpmorg "^1.0.1" + libnpmpublish "^1.1.2" + libnpmsearch "^2.0.2" + libnpmteam "^1.0.2" + lock-verify "^2.0.2" + npm-lifecycle "^3.0.0" + npm-logical-tree "^1.2.1" + npm-package-arg "^6.1.0" + npm-profile "^4.0.2" + npm-registry-fetch "^4.0.0" + npmlog "^4.1.2" + pacote "^9.5.3" + read-package-json "^2.0.13" + stringify-package "^1.0.0" + +libnpmaccess@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/libnpmaccess/-/libnpmaccess-3.0.2.tgz#8b2d72345ba3bef90d3b4f694edd5c0417f58923" + integrity sha512-01512AK7MqByrI2mfC7h5j8N9V4I7MHJuk9buo8Gv+5QgThpOgpjB7sQBDDkeZqRteFb1QM/6YNdHfG7cDvfAQ== + dependencies: + aproba "^2.0.0" + get-stream "^4.0.0" + npm-package-arg "^6.1.0" + npm-registry-fetch "^4.0.0" + +libnpmconfig@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/libnpmconfig/-/libnpmconfig-1.2.1.tgz#c0c2f793a74e67d4825e5039e7a02a0044dfcbc0" + integrity sha512-9esX8rTQAHqarx6qeZqmGQKBNZR5OIbl/Ayr0qQDy3oXja2iFVQQI81R6GZ2a02bSNZ9p3YOGX1O6HHCb1X7kA== + dependencies: + figgy-pudding "^3.5.1" + find-up "^3.0.0" + ini "^1.3.5" + +libnpmhook@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/libnpmhook/-/libnpmhook-5.0.3.tgz#4020c0f5edbf08ebe395325caa5ea01885b928f7" + integrity sha512-UdNLMuefVZra/wbnBXECZPefHMGsVDTq5zaM/LgKNE9Keyl5YXQTnGAzEo+nFOpdRqTWI9LYi4ApqF9uVCCtuA== + dependencies: + aproba "^2.0.0" + figgy-pudding "^3.4.1" + get-stream "^4.0.0" + npm-registry-fetch "^4.0.0" + +libnpmorg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/libnpmorg/-/libnpmorg-1.0.1.tgz#5d2503f6ceb57f33dbdcc718e6698fea6d5ad087" + integrity sha512-0sRUXLh+PLBgZmARvthhYXQAWn0fOsa6T5l3JSe2n9vKG/lCVK4nuG7pDsa7uMq+uTt2epdPK+a2g6btcY11Ww== + dependencies: + aproba "^2.0.0" + figgy-pudding "^3.4.1" + get-stream "^4.0.0" + npm-registry-fetch "^4.0.0" + +libnpmpublish@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/libnpmpublish/-/libnpmpublish-1.1.3.tgz#e3782796722d79eef1a0a22944c117e0c4ca4280" + integrity sha512-/3LsYqVc52cHXBmu26+J8Ed7sLs/hgGVFMH1mwYpL7Qaynb9RenpKqIKu0sJ130FB9PMkpMlWjlbtU8A4m7CQw== + dependencies: + aproba "^2.0.0" + figgy-pudding "^3.5.1" + get-stream "^4.0.0" + lodash.clonedeep "^4.5.0" + normalize-package-data "^2.4.0" + npm-package-arg "^6.1.0" + npm-registry-fetch "^4.0.0" + semver "^5.5.1" + ssri "^6.0.1" + +libnpmsearch@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/libnpmsearch/-/libnpmsearch-2.0.2.tgz#9a4f059102d38e3dd44085bdbfe5095f2a5044cf" + integrity sha512-VTBbV55Q6fRzTdzziYCr64+f8AopQ1YZ+BdPOv16UegIEaE8C0Kch01wo4s3kRTFV64P121WZJwgmBwrq68zYg== + dependencies: + figgy-pudding "^3.5.1" + get-stream "^4.0.0" + npm-registry-fetch "^4.0.0" + +libnpmteam@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/libnpmteam/-/libnpmteam-1.0.2.tgz#8b48bcbb6ce70dd8150c950fcbdbf3feb6eec820" + integrity sha512-p420vM28Us04NAcg1rzgGW63LMM6rwe+6rtZpfDxCcXxM0zUTLl7nPFEnRF3JfFBF5skF/yuZDUthTsHgde8QA== + dependencies: + aproba "^2.0.0" + figgy-pudding "^3.4.1" + get-stream "^4.0.0" + npm-registry-fetch "^4.0.0" + +libnpx@^10.2.2: + version "10.2.3" + resolved "https://registry.yarnpkg.com/libnpx/-/libnpx-10.2.3.tgz#d5e01f12d383ffca9a947807ca6a8f587d38fe2c" + integrity sha512-bCvdARu55fLQBhMfcYGF0GznF1kB2sqxq/9zKZ3652M8DDFWpVpCnpgzjzn0yWMDMez5ZGMBiX24yR11uEYZVQ== + dependencies: + dotenv "^5.0.1" + npm-package-arg "^6.0.0" + rimraf "^2.6.2" + safe-buffer "^5.1.0" + update-notifier "^2.3.0" + which "^1.3.0" + y18n "^4.0.0" + yargs "^11.0.0" + 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" @@ -10737,10 +12343,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.10: - version "10.0.10" - resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-10.0.10.tgz#d14d33ee02a31a31ad36cf9aa7973fc156c461b5" - integrity sha512-91vNy3eYStExElLWw1Idva5lghKpFaXh9AJqjcyrJXf7AYZrThi4EhQ+GpmiHdPmJJauKhZMMSzQR1bMB90MtA== +lint-staged@10.1.3: + version "10.1.3" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-10.1.3.tgz#da27713d3ac519da305381b4de87d5f866b1d2f1" + integrity sha512-o2OkLxgVns5RwSC5QF7waeAjJA5nz5gnUfqL311LkZcFipKV7TztrSlhNUK5nQX9H0E5NELAdduMQ+M/JPT7RQ== dependencies: chalk "^3.0.0" commander "^4.0.1" @@ -10886,16 +12492,50 @@ locate-path@^5.0.0: dependencies: p-locate "^4.1.0" +lock-verify@^2.0.2, lock-verify@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/lock-verify/-/lock-verify-2.2.0.tgz#12432feb68bb647071c78c44bde16029a0f7d935" + integrity sha512-BhM1Vqsu7x0s+EalTifNjdDPks+ZjdAhComvnA6VcCIlDOI5ouELXqAe1BYuEIP4zGN0W08xVm6byJV1LnCiJg== + dependencies: + "@iarna/cli" "^1.2.0" + npm-package-arg "^6.1.0" + semver "^5.4.1" + +lockfile@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/lockfile/-/lockfile-1.0.4.tgz#07f819d25ae48f87e538e6578b6964a4981a5609" + integrity sha512-cvbTwETRfsFh4nHsL1eGWapU1XFi5Ot9E85sWAwia7Y7EgB7vfqcZhTKZ+l7hCGxSPoushMv5GKhT5PdLv03WA== + dependencies: + signal-exit "^3.0.2" + lodash-es@^4.2.1: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.15.tgz#21bd96839354412f23d7a10340e5eac6ee455d78" integrity sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ== +lodash._baseuniq@~4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8" + integrity sha1-DrtE5FaBSveQXGIS+iybLVG4Qeg= + dependencies: + lodash._createset "~4.0.0" + lodash._root "~3.0.0" + +lodash._createset@~4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26" + integrity sha1-D0ZZ+7CddRlPqeK4imZE02PJ/iY= + lodash._reinterpolate@^3.0.0, lodash._reinterpolate@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= +lodash._root@~3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" + integrity sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI= + lodash.assign@^4.0.3, lodash.assign@^4.0.6, lodash.assign@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" @@ -10911,7 +12551,7 @@ lodash.assigninwith@^4.0.0: resolved "https://registry.yarnpkg.com/lodash.assigninwith/-/lodash.assigninwith-4.2.0.tgz#af02c98432ac86d93da695b4be801401971736af" integrity sha1-rwLJhDKshtk9ppW0voAUAZcXNq8= -lodash.clonedeep@^4.5.0: +lodash.clonedeep@^4.5.0, lodash.clonedeep@~4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= @@ -11000,11 +12640,21 @@ lodash.tostring@^4.0.0: resolved "https://registry.yarnpkg.com/lodash.tostring/-/lodash.tostring-4.1.4.tgz#560c27d1f8eadde03c2cce198fef5c031d8298fb" integrity sha1-Vgwn0fjq3eA8LM4Zj+9cAx2CmPs= -lodash.uniq@^4.5.0: +lodash.union@~4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88" + integrity sha1-SLtQiECfFvGCFmZkHETdGqrjzYg= + +lodash.uniq@^4.5.0, lodash.uniq@~4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= +lodash.without@~4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.without/-/lodash.without-4.4.0.tgz#3cd4574a00b67bae373a94b748772640507b7aac" + integrity sha1-PNRXSgC2e643OpS3SHcmQFB7eqw= + lodash@4.17.14: version "4.17.14" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.14.tgz#9ce487ae66c96254fe20b599f21b6816028078ba" @@ -11046,9 +12696,9 @@ log-update@^2.3.0: wrap-ansi "^3.0.1" loglevel@^1.6.6, loglevel@^1.6.7: - version "1.6.7" - resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.7.tgz#b3e034233188c68b889f5b862415306f565e2c56" - integrity sha512-cY2eLFrQSAfVPhCgH1s7JI73tMbg9YC3v3+ZHVW67sBS7UxWzNEk/ZBbSfLykBWHp33dqqtOv82gjhKEi81T/A== + version "1.6.8" + resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.8.tgz#8a25fb75d092230ecd4457270d80b54e28011171" + integrity sha512-bsU7+gc9AJ2SqpzxwU3+1fedl8zAntbtC5XYlt3s2j1hJcn2PsXSmgN8TaLG/J1/2mod4+cE/3vNL70/c1RNCA== lolex@^5.0.0: version "5.1.2" @@ -11160,6 +12810,23 @@ make-dir@^3.0.0, make-dir@^3.0.2: dependencies: semver "^6.0.0" +make-fetch-happen@^5.0.0: + version "5.0.2" + resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-5.0.2.tgz#aa8387104f2687edca01c8687ee45013d02d19bd" + integrity sha512-07JHC0r1ykIoruKO8ifMXu+xEU8qOXDFETylktdug6vJDACnP+HKevOu3PXyNPzFyTSlz8vrBYlBO1JZRe8Cag== + dependencies: + agentkeepalive "^3.4.1" + cacache "^12.0.0" + http-cache-semantics "^3.8.1" + http-proxy-agent "^2.1.0" + https-proxy-agent "^2.2.3" + lru-cache "^5.1.1" + mississippi "^3.0.0" + node-fetch-npm "^2.0.2" + promise-retry "^1.1.1" + socks-proxy-agent "^4.0.0" + ssri "^6.0.0" + makeerror@1.0.x: version "1.0.11" resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" @@ -11206,6 +12873,13 @@ marked@0.3.19: resolved "https://registry.yarnpkg.com/marked/-/marked-0.3.19.tgz#5d47f709c4c9fc3c216b6d46127280f40b39d790" integrity sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg== +matcher@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/matcher/-/matcher-2.1.0.tgz#64e1041c15b993e23b786f93320a7474bf833c28" + integrity sha512-o+nZr+vtJtgPNklyeUKkkH42OsK8WAfdgaJE2FNxcjLPg+5QbeEoT6vRj8Xq/iv18JlQ9cmKsEu0b94ixWf1YQ== + dependencies: + escape-string-regexp "^2.0.0" + 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" @@ -11238,6 +12912,11 @@ mdn-data@2.0.6: resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.6.tgz#852dc60fcaa5daa2e8cf6c9189c440ed3e042978" integrity sha512-rQvjv71olwNHgiTbfPZFkJtjNMciWgswYeciZhtvWLO8bmX3TnhyA62I6sTWOyZssWHJJjY6/KiWwqQsWWsqOA== +meant@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/meant/-/meant-1.0.1.tgz#66044fea2f23230ec806fb515efea29c44d2115d" + integrity sha512-UakVLFjKkbbUwNWJ2frVLnnAtbb7D7DsloxRd3s/gDpI8rdv8W5Hp3NaDb+POBI1fQdeussER6NB8vpcRURvlg== + media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" @@ -11461,6 +13140,11 @@ mimic-response@^1.0.0, mimic-response@^1.0.1: resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== +mimic-response@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43" + integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA== + min-document@^2.19.0: version "2.19.0" resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" @@ -11558,7 +13242,7 @@ minipass-pipeline@^1.2.2: dependencies: minipass "^3.0.0" -minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0: +minipass@^2.3.5, minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== @@ -11604,6 +13288,11 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" +mkdirp-classic@^0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.2.tgz#54c441ce4c96cd7790e10b41a87aa51068ecab2b" + integrity sha512-ejdnDQcR75gwknmMw/tx02AuRs8jCtqFoFqDZMjiNxsu85sRIJVXDKHuLYvUUPRBUtV2FpSZa9bL1BUa3BdR2g== + mkdirp-promise@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" @@ -11623,7 +13312,7 @@ mkdirp@0.5.1: dependencies: minimist "0.0.8" -mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@~0.5.1: +mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.4, mkdirp@~0.5.0, mkdirp@~0.5.1: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== @@ -11700,7 +13389,7 @@ ms@2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== -ms@^2.1.1: +ms@^2.0.0, ms@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== @@ -11723,7 +13412,7 @@ mute-stream@0.0.7: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= -mute-stream@0.0.8: +mute-stream@0.0.8, mute-stream@~0.0.4: version "0.0.8" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== @@ -11733,11 +13422,16 @@ nan@2.13.2: resolved "https://registry.yarnpkg.com/nan/-/nan-2.13.2.tgz#f51dc7ae66ba7d5d55e1e6d4d8092e802c9aefe7" integrity sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw== -nan@2.14.0, nan@^2.0.8, nan@^2.12.1, nan@^2.14.0, nan@^2.2.1: +nan@2.14.0: version "2.14.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== +nan@^2.0.8, nan@^2.12.1, nan@^2.14.0, nan@^2.2.1: + version "2.14.1" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01" + integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw== + nano-json-stream-parser@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" @@ -11765,6 +13459,11 @@ nanomatch@^1.2.9: snapdragon "^0.8.1" to-regex "^3.0.1" +napi-build-utils@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz#b1fddc0b2c46e380a0b7a76f984dd47c41a13806" + integrity sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg== + natural-compare-lite@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4" @@ -11803,6 +13502,13 @@ no-case@^3.0.3: lower-case "^2.0.1" tslib "^1.10.0" +node-abi@^2.7.0: + version "2.16.0" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.16.0.tgz#7df94e9c0a7a189f4197ab84bac8089ef5894992" + integrity sha512-+sa0XNlWDA6T+bDLmkCUYn6W5k5W6BPRL6mqzSCs6H/xUgtl4D5x2fORKDzopKiU6wsyn/+wXlRXwXeSp+mtoA== + dependencies: + semver "^5.4.1" + node-dir@0.1.17, node-dir@^0.1.16: version "0.1.17" resolved "https://registry.yarnpkg.com/node-dir/-/node-dir-0.1.17.tgz#5f5665d93351335caabef8f1c554516cf5f1e4e5" @@ -11817,6 +13523,15 @@ node-emoji@^1.8.1: dependencies: lodash.toarray "^4.4.0" +node-fetch-npm@^2.0.2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/node-fetch-npm/-/node-fetch-npm-2.0.4.tgz#6507d0e17a9ec0be3bec516958a497cec54bf5a4" + integrity sha512-iOuIQDWDyjhv9qSDrj9aq/klt6F9z1p2otB3AV7v3zBDcL/x+OfGsvGQZZCcMZbUf4Ujw1xGNQkjvGnVT22cKg== + dependencies: + encoding "^0.1.11" + json-parse-better-errors "^1.0.0" + safe-buffer "^5.1.1" + node-fetch@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.1.2.tgz#ab884e8e7e57e38a944753cec706f788d1768bb5" @@ -11835,6 +13550,32 @@ node-forge@0.9.0: resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.9.0.tgz#d624050edbb44874adca12bb9a52ec63cb782579" integrity sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ== +node-gyp@^5.0.2, node-gyp@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-5.1.0.tgz#8e31260a7af4a2e2f994b0673d4e0b3866156332" + integrity sha512-OUTryc5bt/P8zVgNUmC6xdXiDJxLMAW8cF5tLQOT9E5sOQj+UeQxnnPy74K3CLCa/SOjjBlbuzDLR8ANwA+wmw== + dependencies: + env-paths "^2.2.0" + glob "^7.1.4" + graceful-fs "^4.2.2" + mkdirp "^0.5.1" + nopt "^4.0.1" + npmlog "^4.1.2" + request "^2.88.0" + rimraf "^2.6.3" + semver "^5.7.1" + tar "^4.4.12" + which "^1.3.1" + +node-hid@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/node-hid/-/node-hid-1.2.0.tgz#d084a9750832b28fd6de6fe2ccd8063fe8e3e7c0" + integrity sha512-ap06Wo1E0aGrZf0t1zvjWSk+IzI6yvKpTDYQRIrdxLHEelifnGDx6XOb2VVlrQhxzM4etma8jH/i0M1LUB55dA== + dependencies: + bindings "^1.5.0" + nan "^2.14.0" + prebuild-install "^5.3.3" + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" @@ -11906,6 +13647,19 @@ node-releases@^1.1.52, node-releases@^1.1.53: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.53.tgz#2d821bfa499ed7c5dffc5e2f28c88e78a08ee3f4" integrity sha512-wp8zyQVwef2hpZ/dJH7SfSrIPD6YoJz6BDQDpGEkcA0s3LpAQoxBIYmfIq6QAhC1DhwsyCgTaTTcONwX8qzCuQ== +noop-logger@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2" + integrity sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI= + +nopt@^4.0.1, nopt@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48" + integrity sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg== + dependencies: + abbrev "1" + osenv "^0.1.4" + normalize-hex@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/normalize-hex/-/normalize-hex-0.0.2.tgz#5491c43759db2f06b7168d8419f4925c271ab27e" @@ -11913,7 +13667,7 @@ normalize-hex@0.0.2: dependencies: bn.js "^4.11.8" -normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: +normalize-package-data@^2.0.0, normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.4.0, normalize-package-data@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== @@ -11969,6 +13723,102 @@ normalize-url@^4.1.0: prop-types "^15.7.2" react-is "^16.9.0" +npm-audit-report@^1.3.2: + version "1.3.3" + resolved "https://registry.yarnpkg.com/npm-audit-report/-/npm-audit-report-1.3.3.tgz#8226deeb253b55176ed147592a3995442f2179ed" + integrity sha512-8nH/JjsFfAWMvn474HB9mpmMjrnKb1Hx/oTAdjv4PT9iZBvBxiZ+wtDUapHCJwLqYGQVPaAfs+vL5+5k9QndXw== + dependencies: + cli-table3 "^0.5.0" + console-control-strings "^1.1.0" + +npm-bundled@^1.0.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.1.tgz#1edd570865a94cdb1bc8220775e29466c9fb234b" + integrity sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA== + dependencies: + npm-normalize-package-bin "^1.0.1" + +npm-cache-filename@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/npm-cache-filename/-/npm-cache-filename-1.0.2.tgz#ded306c5b0bfc870a9e9faf823bc5f283e05ae11" + integrity sha1-3tMGxbC/yHCp6fr4I7xfKD4FrhE= + +npm-conf@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/npm-conf/-/npm-conf-1.1.3.tgz#256cc47bd0e218c259c4e9550bf413bc2192aff9" + integrity sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw== + dependencies: + config-chain "^1.1.11" + pify "^3.0.0" + +npm-install-checks@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/npm-install-checks/-/npm-install-checks-3.0.2.tgz#ab2e32ad27baa46720706908e5b14c1852de44d9" + integrity sha512-E4kzkyZDIWoin6uT5howP8VDvkM+E8IQDcHAycaAxMbwkqhIg5eEYALnXOl3Hq9MrkdQB/2/g1xwBINXdKSRkg== + dependencies: + semver "^2.3.0 || 3.x || 4 || 5" + +npm-lifecycle@^3.0.0, npm-lifecycle@^3.1.4: + version "3.1.5" + resolved "https://registry.yarnpkg.com/npm-lifecycle/-/npm-lifecycle-3.1.5.tgz#9882d3642b8c82c815782a12e6a1bfeed0026309" + integrity sha512-lDLVkjfZmvmfvpvBzA4vzee9cn+Me4orq0QF8glbswJVEbIcSNWib7qGOffolysc3teCqbbPZZkzbr3GQZTL1g== + dependencies: + byline "^5.0.0" + graceful-fs "^4.1.15" + node-gyp "^5.0.2" + resolve-from "^4.0.0" + slide "^1.1.6" + uid-number "0.0.6" + umask "^1.1.0" + which "^1.3.1" + +npm-logical-tree@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/npm-logical-tree/-/npm-logical-tree-1.2.1.tgz#44610141ca24664cad35d1e607176193fd8f5b88" + integrity sha512-AJI/qxDB2PWI4LG1CYN579AY1vCiNyWfkiquCsJWqntRu/WwimVrC8yXeILBFHDwxfOejxewlmnvW9XXjMlYIg== + +npm-normalize-package-bin@^1.0.0, npm-normalize-package-bin@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2" + integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA== + +"npm-package-arg@^4.0.0 || ^5.0.0 || ^6.0.0", npm-package-arg@^6.0.0, npm-package-arg@^6.1.0, npm-package-arg@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-6.1.1.tgz#02168cb0a49a2b75bf988a28698de7b529df5cb7" + integrity sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg== + dependencies: + hosted-git-info "^2.7.1" + osenv "^0.1.5" + semver "^5.6.0" + validate-npm-package-name "^3.0.0" + +npm-packlist@^1.1.12, npm-packlist@^1.4.8: + version "1.4.8" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.8.tgz#56ee6cc135b9f98ad3d51c1c95da22bbb9b2ef3e" + integrity sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A== + dependencies: + ignore-walk "^3.0.1" + npm-bundled "^1.0.1" + npm-normalize-package-bin "^1.0.1" + +npm-pick-manifest@^3.0.0, npm-pick-manifest@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-3.0.2.tgz#f4d9e5fd4be2153e5f4e5f9b7be8dc419a99abb7" + integrity sha512-wNprTNg+X5nf+tDi+hbjdHhM4bX+mKqv6XmPh7B5eG+QY9VARfQPfCEH013H5GqfNj6ee8Ij2fg8yk0mzps1Vw== + dependencies: + figgy-pudding "^3.5.1" + npm-package-arg "^6.0.0" + semver "^5.4.1" + +npm-profile@^4.0.2, npm-profile@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/npm-profile/-/npm-profile-4.0.4.tgz#28ee94390e936df6d084263ee2061336a6a1581b" + integrity sha512-Ta8xq8TLMpqssF0H60BXS1A90iMoM6GeKwsmravJ6wYjWwSzcYBTdyWa3DZCYqPutacBMEm7cxiOkiIeCUAHDQ== + dependencies: + aproba "^1.1.2 || 2" + figgy-pudding "^3.4.1" + npm-registry-fetch "^4.0.0" + npm-programmatic@0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/npm-programmatic/-/npm-programmatic-0.0.6.tgz#3c8f4dbb210efd65b99ee6a5ac76f27b4d5d6b78" @@ -11976,6 +13826,19 @@ npm-programmatic@0.0.6: dependencies: bluebird "^3.4.1" +npm-registry-fetch@^4.0.0, npm-registry-fetch@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-4.0.3.tgz#3c2179e39e04f9348b1c2979545951d36bee8766" + integrity sha512-WGvUx0lkKFhu9MbiGFuT9nG2NpfQ+4dCJwRwwtK2HK5izJEvwDxMeUyqbuMS7N/OkpVCqDorV6rO5E4V9F8lJw== + dependencies: + JSONStream "^1.3.4" + bluebird "^3.5.1" + figgy-pudding "^3.4.1" + lru-cache "^5.1.1" + make-fetch-happen "^5.0.0" + npm-package-arg "^6.1.0" + safe-buffer "^5.2.0" + npm-run-path@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" @@ -11990,6 +13853,142 @@ npm-run-path@^4.0.0: dependencies: path-key "^3.0.0" +npm-user-validate@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/npm-user-validate/-/npm-user-validate-1.0.0.tgz#8ceca0f5cea04d4e93519ef72d0557a75122e951" + integrity sha1-jOyg9c6gTU6TUZ73LQVXp1Ei6VE= + +npm@^6.14.4: + version "6.14.4" + resolved "https://registry.yarnpkg.com/npm/-/npm-6.14.4.tgz#50a1c6274fb451ca18f6ff472d2a73f006adbd66" + integrity sha512-B8UDDbWvdkW6RgXFn8/h2cHJP/u/FPa4HWeGzW23aNEBARN3QPrRaHqPIZW2NSN3fW649gtgUDNZpaRs0zTMPw== + dependencies: + JSONStream "^1.3.5" + abbrev "~1.1.1" + ansicolors "~0.3.2" + ansistyles "~0.1.3" + aproba "^2.0.0" + archy "~1.0.0" + bin-links "^1.1.7" + bluebird "^3.5.5" + byte-size "^5.0.1" + cacache "^12.0.3" + call-limit "^1.1.1" + chownr "^1.1.4" + ci-info "^2.0.0" + cli-columns "^3.1.2" + cli-table3 "^0.5.1" + cmd-shim "^3.0.3" + columnify "~1.5.4" + config-chain "^1.1.12" + detect-indent "~5.0.0" + detect-newline "^2.1.0" + dezalgo "~1.0.3" + editor "~1.0.0" + figgy-pudding "^3.5.1" + find-npm-prefix "^1.0.2" + fs-vacuum "~1.2.10" + fs-write-stream-atomic "~1.0.10" + gentle-fs "^2.3.0" + glob "^7.1.6" + graceful-fs "^4.2.3" + has-unicode "~2.0.1" + hosted-git-info "^2.8.8" + iferr "^1.0.2" + infer-owner "^1.0.4" + inflight "~1.0.6" + inherits "^2.0.4" + ini "^1.3.5" + init-package-json "^1.10.3" + is-cidr "^3.0.0" + json-parse-better-errors "^1.0.2" + lazy-property "~1.0.0" + libcipm "^4.0.7" + libnpm "^3.0.1" + libnpmaccess "^3.0.2" + libnpmhook "^5.0.3" + libnpmorg "^1.0.1" + libnpmsearch "^2.0.2" + libnpmteam "^1.0.2" + libnpx "^10.2.2" + lock-verify "^2.1.0" + lockfile "^1.0.4" + lodash._baseuniq "~4.6.0" + lodash.clonedeep "~4.5.0" + lodash.union "~4.6.0" + lodash.uniq "~4.5.0" + lodash.without "~4.4.0" + lru-cache "^5.1.1" + meant "~1.0.1" + mississippi "^3.0.0" + mkdirp "^0.5.4" + move-concurrently "^1.0.1" + node-gyp "^5.1.0" + nopt "~4.0.1" + normalize-package-data "^2.5.0" + npm-audit-report "^1.3.2" + npm-cache-filename "~1.0.2" + npm-install-checks "^3.0.2" + npm-lifecycle "^3.1.4" + npm-package-arg "^6.1.1" + npm-packlist "^1.4.8" + npm-pick-manifest "^3.0.2" + npm-profile "^4.0.4" + npm-registry-fetch "^4.0.3" + npm-user-validate "~1.0.0" + npmlog "~4.1.2" + once "~1.4.0" + opener "^1.5.1" + osenv "^0.1.5" + pacote "^9.5.12" + path-is-inside "~1.0.2" + promise-inflight "~1.0.1" + qrcode-terminal "^0.12.0" + query-string "^6.8.2" + qw "~1.0.1" + read "~1.0.7" + read-cmd-shim "^1.0.5" + read-installed "~4.0.3" + read-package-json "^2.1.1" + read-package-tree "^5.3.1" + readable-stream "^3.6.0" + readdir-scoped-modules "^1.1.0" + request "^2.88.0" + retry "^0.12.0" + rimraf "^2.7.1" + safe-buffer "^5.1.2" + semver "^5.7.1" + sha "^3.0.0" + slide "~1.1.6" + sorted-object "~2.0.1" + sorted-union-stream "~2.1.3" + ssri "^6.0.1" + stringify-package "^1.0.1" + tar "^4.4.13" + text-table "~0.2.0" + tiny-relative-date "^1.3.0" + uid-number "0.0.6" + umask "~1.1.0" + unique-filename "^1.1.1" + unpipe "~1.0.0" + update-notifier "^2.5.0" + uuid "^3.3.3" + validate-npm-package-license "^3.0.4" + validate-npm-package-name "~3.0.0" + which "^1.3.1" + worker-farm "^1.7.0" + write-file-atomic "^2.4.3" + +npmlog@^4.0.1, npmlog@^4.1.2, npmlog@~4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + nth-check@^1.0.2, nth-check@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" @@ -12064,9 +14063,12 @@ object-inspect@^1.7.0, object-inspect@~1.7.0: integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== object-is@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.0.2.tgz#6b80eb84fe451498f65007982f035a5b445edec4" - integrity sha512-Epah+btZd5wrrfjkJZq1AOB9O6OxUQto45hzFd7lXGrpHPGE0W1k+426yrZV+k6NJOzLNNW/nVsmZdIWsAqoOQ== + version "1.1.2" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.2.tgz#c5d2e87ff9e119f78b7a088441519e2eec1573b6" + integrity sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" @@ -12182,7 +14184,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.4.0, once@~1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= @@ -12203,7 +14205,7 @@ onetime@^5.1.0: dependencies: mimic-fn "^2.1.0" -open@^7.0.2: +open@^7.0.2, open@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/open/-/open-7.0.3.tgz#db551a1af9c7ab4c7af664139930826138531c48" integrity sha512-sP2ru2v0P290WFfv49Ap8MF6PkzGNnGlAwHweB4WR4mr5d2d0woiCluUeJ218w7/+PmoBy9JmYgD5A4mLcWOFA== @@ -12320,11 +14322,19 @@ os-locale@^3.0.0, os-locale@^3.1.0: lcid "^2.0.0" mem "^4.0.0" -os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: +os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= +osenv@^0.1.4, osenv@^0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" + integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + p-cancelable@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" @@ -12431,7 +14441,63 @@ p-try@^2.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== -pako@^1.0.4, pako@~1.0.5: +package-json@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/package-json/-/package-json-4.0.1.tgz#8869a0401253661c4c4ca3da6c2121ed555f5eed" + integrity sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0= + dependencies: + got "^6.7.1" + registry-auth-token "^3.0.1" + registry-url "^3.0.3" + semver "^5.1.0" + +package-json@^6.3.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0" + integrity sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ== + dependencies: + got "^9.6.0" + registry-auth-token "^4.0.0" + registry-url "^5.0.0" + semver "^6.2.0" + +pacote@^9.1.0, pacote@^9.5.12, pacote@^9.5.3: + version "9.5.12" + resolved "https://registry.yarnpkg.com/pacote/-/pacote-9.5.12.tgz#1e11dd7a8d736bcc36b375a9804d41bb0377bf66" + integrity sha512-BUIj/4kKbwWg4RtnBncXPJd15piFSVNpTzY0rysSr3VnMowTYgkGKcaHrbReepAkjTr8lH2CVWRi58Spg2CicQ== + dependencies: + bluebird "^3.5.3" + cacache "^12.0.2" + chownr "^1.1.2" + figgy-pudding "^3.5.1" + get-stream "^4.1.0" + glob "^7.1.3" + infer-owner "^1.0.4" + lru-cache "^5.1.1" + make-fetch-happen "^5.0.0" + minimatch "^3.0.4" + minipass "^2.3.5" + mississippi "^3.0.0" + mkdirp "^0.5.1" + normalize-package-data "^2.4.0" + npm-normalize-package-bin "^1.0.0" + npm-package-arg "^6.1.0" + npm-packlist "^1.1.12" + npm-pick-manifest "^3.0.0" + npm-registry-fetch "^4.0.0" + osenv "^0.1.5" + promise-inflight "^1.0.1" + promise-retry "^1.1.1" + protoduck "^5.0.1" + rimraf "^2.6.2" + safe-buffer "^5.1.2" + semver "^5.6.0" + ssri "^6.0.1" + tar "^4.4.10" + unique-filename "^1.1.1" + which "^1.3.1" + +pako@^1.0.10, pako@^1.0.4, pako@~1.0.5: version "1.0.11" resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== @@ -12589,7 +14655,7 @@ path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= -path-is-inside@^1.0.1, path-is-inside@^1.0.2: +path-is-inside@^1.0.1, path-is-inside@^1.0.2, path-is-inside@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= @@ -12795,7 +14861,14 @@ polished@3.5.1: dependencies: "@babel/runtime" "^7.8.7" -popper.js@^1.14.1: +polished@^3.5.1: + version "3.5.2" + resolved "https://registry.yarnpkg.com/polished/-/polished-3.5.2.tgz#ca132b8cd68f7ffa95ae9d423f03e7a14fda1062" + integrity sha512-vWoRDg3gY5RQBtUfcj9MRN10VCIf4EkdUikGxyXItg2Hnwk+eIVtdBiLajN0ldFeT3Vq4r/QNbjrQdhqBKrTug== + dependencies: + "@babel/runtime" "^7.8.7" + +popper.js@^1.16.1-lts: version "1.16.1" resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b" integrity sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ== @@ -12993,7 +15066,7 @@ postcss-modules-local-by-default@^3.0.2: postcss-selector-parser "^6.0.2" postcss-value-parser "^4.0.0" -postcss-modules-scope@^2.1.1: +postcss-modules-scope@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz#385cae013cc7743f5a7d7602d1073a89eaae62ee" integrity sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ== @@ -13173,7 +15246,7 @@ postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.2, postcss-value-parser@^ 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.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.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== @@ -13182,6 +15255,27 @@ postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.1 source-map "^0.6.1" supports-color "^6.1.0" +prebuild-install@^5.3.3: + version "5.3.3" + resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-5.3.3.tgz#ef4052baac60d465f5ba6bf003c9c1de79b9da8e" + integrity sha512-GV+nsUXuPW2p8Zy7SarF/2W/oiK8bFQgJcncoJ0d7kRpekEA0ftChjfEaF9/Y+QJEc/wFR7RAEa8lYByuUIe2g== + dependencies: + detect-libc "^1.0.3" + expand-template "^2.0.3" + github-from-package "0.0.0" + minimist "^1.2.0" + mkdirp "^0.5.1" + napi-build-utils "^1.0.1" + node-abi "^2.7.0" + noop-logger "^0.1.1" + npmlog "^4.0.1" + pump "^3.0.0" + rc "^1.2.7" + simple-get "^3.0.3" + tar-fs "^2.0.0" + tunnel-agent "^0.6.0" + which-pm-runs "^1.0.0" + precond@0.2: version "0.2.3" resolved "https://registry.yarnpkg.com/precond/-/precond-0.2.3.tgz#aa9591bcaa24923f1e0f4849d240f47efc1075ac" @@ -13214,10 +15308,10 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" -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== +prettier@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.4.tgz#2d1bae173e355996ee355ec9830a7a1ee05457ef" + integrity sha512-SVJIQ51spzFDvh4fIbCLvciiDMCrRhlN3mbZvv/+ycjvmF5E73bKdGfU8QDLNmjYJf+lsGnDBC4UUnvTe5OO0w== pretty-error@^2.1.1: version "2.1.1" @@ -13237,6 +15331,16 @@ pretty-format@^25.1.0, pretty-format@^25.2.1, pretty-format@^25.3.0: ansi-styles "^4.0.0" react-is "^16.12.0" +pretty-format@^25.4.0: + version "25.4.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-25.4.0.tgz#c58801bb5c4926ff4a677fe43f9b8b99812c7830" + integrity sha512-PI/2dpGjXK5HyXexLPZU/jw5T9Q6S1YVXxxVxco+LIqzUFHXIbKZKdUVt7GcX7QUCr31+3fzhi4gN4/wUYPVxQ== + dependencies: + "@jest/types" "^25.4.0" + ansi-regex "^5.0.0" + ansi-styles "^4.0.0" + react-is "^16.12.0" + private@^0.1.6, private@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" @@ -13262,16 +15366,24 @@ process@~0.5.1: resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf" integrity sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8= -progress@^2.0.0: +progress@^2.0.0, progress@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== -promise-inflight@^1.0.1: +promise-inflight@^1.0.1, promise-inflight@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= +promise-retry@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-1.1.1.tgz#6739e968e3051da20ce6497fb2b50f6911df3d6d" + integrity sha1-ZznpaOMFHaIM5kl/srUPaRHfPW0= + dependencies: + err-code "^1.0.0" + retry "^0.10.0" + promise-to-callback@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/promise-to-callback/-/promise-to-callback-1.0.0.tgz#5d2a749010bfb67d963598fcd3960746a68feef7" @@ -13295,6 +15407,13 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.4" +promzard@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/promzard/-/promzard-0.3.0.tgz#26a5d6ee8c7dee4cb12208305acfb93ba382a9ee" + integrity sha1-JqXW7ox97kyxIggwWs+5O6OCqe4= + dependencies: + read "1" + prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" @@ -13304,6 +15423,18 @@ prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, object-assign "^4.1.1" react-is "^16.8.1" +proto-list@~1.2.1: + version "1.2.4" + resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" + integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk= + +protoduck@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/protoduck/-/protoduck-5.0.1.tgz#03c3659ca18007b69a50fd82a7ebcc516261151f" + integrity sha512-WxoCeDCoCBY55BMvj4cAEjdVUFGRWed9ZxPlqTKYyw1nDDTQ4pqmnIMAGfJlg7Dx35uB/M+PHJPTmGOvaCaPTg== + dependencies: + genfun "^5.0.0" + proxy-addr@~2.0.5: version "2.0.6" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf" @@ -13471,10 +15602,10 @@ qs@~6.5.2: resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== -query-string@6.11.1: - version "6.11.1" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.11.1.tgz#ab021f275d463ce1b61e88f0ce6988b3e8fe7c2c" - integrity sha512-1ZvJOUl8ifkkBxu2ByVM/8GijMIPx+cef7u3yroO3Ogm4DOdZcF5dcrWTIlSHe3Pg/mtlt6/eFjObDfJureZZA== +query-string@6.12.1, query-string@^6.8.2: + version "6.12.1" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.12.1.tgz#2ae4d272db4fba267141665374e49a1de09e8a7c" + integrity sha512-OHj+zzfRMyj3rmo/6G8a5Ifvw3AleL/EbcHMD27YA31Q+cO5lfmQxECkImuNVjcskLcvBRVHNAB3w6udMs1eAA== dependencies: decode-uri-component "^0.2.0" split-on-first "^1.0.0" @@ -13517,6 +15648,11 @@ quick-lru@^1.0.0: resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8" integrity sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g= +qw@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/qw/-/qw-1.0.1.tgz#efbfdc740f9ad054304426acb183412cc8b996d4" + integrity sha1-77/cdA+a0FQwRCassYNBLMi5ltQ= + randomatic@^3.0.0: version "3.1.1" resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.1.tgz#b776efc59375984e36c537b2f51a1f0aff0da1ed" @@ -13561,6 +15697,16 @@ raw-body@2.4.0: iconv-lite "0.4.24" unpipe "1.0.0" +rc@^1.0.1, rc@^1.1.6, rc@^1.2.7, rc@^1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + 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" @@ -13613,13 +15759,13 @@ react-final-form-listeners@^1.0.2: dependencies: "@babel/runtime" "^7.1.5" -react-final-form@6.3.5: - version "6.3.5" - resolved "https://registry.yarnpkg.com/react-final-form/-/react-final-form-6.3.5.tgz#772781071d26d26493b0c8ef4f97f76f06fc1c0f" - integrity sha512-btqEp1+n1WO4bUDopBdvUoIuoGHf91n/EOJg0QU5YjhX9CK+4RIsBI0M41lmyT3H6hWv6NELdX5n5zBJyOIXoA== +react-final-form@6.4.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/react-final-form/-/react-final-form-6.4.0.tgz#7f9064c10a8bee6a02cd3e9b8aff06fa07f9c908" + integrity sha512-M7J7f0pnoj0o8sBq3iG6jsWJEh08pNUyl2D4wBC9SJvCNkGdol2UdyjMiEFYD3rz9LIFzQqFSG0kbRBCadqzhA== dependencies: - "@babel/runtime" "^7.8.3" - ts-essentials "^5.0.0" + "@babel/runtime" "^7.9.2" + ts-essentials "^6.0.3" react-ga@^2.7.0: version "2.7.0" @@ -13727,9 +15873,75 @@ react@16.13.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== + version "0.1.12" + resolved "https://registry.yarnpkg.com/reactive-properties/-/reactive-properties-0.1.12.tgz#35000ddb9b516bf5ea5b4c41154a45a7a38fdedf" + integrity sha512-jPpTyoAZOvMhq3pt87X/kZ1zT4j1aad8iafSRHOziYfhBYVYTiUjmIYAxZPmcFziF/4JbEsA7DXA91ZzdosQyQ== + +read-cmd-shim@^1.0.1, read-cmd-shim@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-1.0.5.tgz#87e43eba50098ba5a32d0ceb583ab8e43b961c16" + integrity sha512-v5yCqQ/7okKoZZkBQUAfTsQ3sVJtXdNfbPnI5cceppoxEVLYA3k+VtV2omkeo8MS94JCy4fSiUwlRBAwCVRPUA== + dependencies: + graceful-fs "^4.1.2" + +read-config-file@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/read-config-file/-/read-config-file-5.0.0.tgz#1487c983fae9c1b672d3acda5cac899a2d451f02" + integrity sha512-jIKUu+C84bfnKxyJ5j30CxCqgXWYjZLXuVE/NYlMEpeni+dhESgAeZOZd0JZbg1xTkMmnCdxksDoarkOyfEsOg== + dependencies: + dotenv "^8.0.0" + dotenv-expand "^5.1.0" + fs-extra "^8.1.0" + js-yaml "^3.13.1" + json5 "^2.1.0" + lazy-val "^1.0.4" + +read-config-file@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/read-config-file/-/read-config-file-5.0.1.tgz#ead3df0d9822cc96006ca16322eaa79dac8591c2" + integrity sha512-75zp4PDbvtBlECoZK1KEkNlesr9OWdMWL8oi4xq+HXAM+kKHKU+Cx2ksFt+ie2BkrmkLBOKSfONDuz+WIKWoXA== + dependencies: + dotenv "^8.2.0" + dotenv-expand "^5.1.0" + fs-extra "^8.1.0" + js-yaml "^3.13.1" + json5 "^2.1.1" + lazy-val "^1.0.4" + +read-installed@~4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/read-installed/-/read-installed-4.0.3.tgz#ff9b8b67f187d1e4c29b9feb31f6b223acd19067" + integrity sha1-/5uLZ/GH0eTCm5/rMfayI6zRkGc= + dependencies: + debuglog "^1.0.1" + read-package-json "^2.0.0" + readdir-scoped-modules "^1.0.0" + semver "2 || 3 || 4 || 5" + slide "~1.1.3" + util-extend "^1.0.1" + optionalDependencies: + graceful-fs "^4.1.2" + +"read-package-json@1 || 2", read-package-json@^2.0.0, read-package-json@^2.0.13, read-package-json@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-2.1.1.tgz#16aa66c59e7d4dad6288f179dd9295fd59bb98f1" + integrity sha512-dAiqGtVc/q5doFz6096CcnXhpYk0ZN8dEKVkGLU0CsASt8SrgF6SF7OTKAYubfvFhWaqofl+Y8HK19GR8jwW+A== + dependencies: + glob "^7.1.1" + json-parse-better-errors "^1.0.1" + normalize-package-data "^2.0.0" + npm-normalize-package-bin "^1.0.0" + optionalDependencies: + graceful-fs "^4.1.2" + +read-package-tree@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/read-package-tree/-/read-package-tree-5.3.1.tgz#a32cb64c7f31eb8a6f31ef06f9cedf74068fe636" + integrity sha512-mLUDsD5JVtlZxjSlPPx1RETkNjjvQYuweKwNVt1Sn8kP5Jh44pvYuUHCp6xSVDZWbNxVxG5lyZJ921aJH61sTw== + dependencies: + read-package-json "^2.0.0" + readdir-scoped-modules "^1.0.0" + util-promisify "^2.1.0" read-pkg-up@^1.0.1: version "1.0.1" @@ -13755,6 +15967,15 @@ read-pkg-up@^3.0.0: find-up "^2.0.0" read-pkg "^3.0.0" +read-pkg-up@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" + integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== + dependencies: + find-up "^4.1.0" + read-pkg "^5.2.0" + type-fest "^0.8.1" + read-pkg@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" @@ -13782,7 +16003,33 @@ read-pkg@^3.0.0: normalize-package-data "^2.3.2" path-type "^3.0.0" -"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: +read-pkg@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-4.0.1.tgz#963625378f3e1c4d48c85872b5a6ec7d5d093237" + integrity sha1-ljYlN48+HE1IyFhytabsfV0JMjc= + dependencies: + normalize-package-data "^2.3.2" + parse-json "^4.0.0" + pify "^3.0.0" + +read-pkg@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" + integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== + dependencies: + "@types/normalize-package-data" "^2.4.0" + normalize-package-data "^2.5.0" + parse-json "^5.0.0" + type-fest "^0.6.0" + +read@1, read@~1.0.1, read@~1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4" + integrity sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ= + dependencies: + mute-stream "~0.0.4" + +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -13815,7 +16062,7 @@ readable-stream@1.1: isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@^1.0.33: +readable-stream@^1.0.33, readable-stream@~1.1.10: version "1.1.14" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= @@ -13825,7 +16072,7 @@ readable-stream@^1.0.33: isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@^3.0.6, readable-stream@^3.1.1: +readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== @@ -13846,6 +16093,16 @@ readable-stream@~2.0.0: string_decoder "~0.10.x" util-deprecate "~1.0.1" +readdir-scoped-modules@^1.0.0, readdir-scoped-modules@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz#8d45407b4f870a0dcaebc0e28670d18e74514309" + integrity sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw== + dependencies: + debuglog "^1.0.1" + dezalgo "^1.0.0" + graceful-fs "^4.1.2" + once "^1.3.0" + readdirp@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" @@ -14079,6 +16336,35 @@ regexpu-core@^4.7.0: unicode-match-property-ecmascript "^1.0.4" unicode-match-property-value-ecmascript "^1.2.0" +registry-auth-token@^3.0.1: + version "3.4.0" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.4.0.tgz#d7446815433f5d5ed6431cd5dca21048f66b397e" + integrity sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A== + dependencies: + rc "^1.1.6" + safe-buffer "^5.0.1" + +registry-auth-token@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.1.1.tgz#40a33be1e82539460f94328b0f7f0f84c16d9479" + integrity sha512-9bKS7nTl9+/A1s7tnPeGrUpRcVY+LUh7bfFgzpndALdPfXQBfQV77rQVtqgUV3ti4vc/Ik81Ex8UJDWDQ12zQA== + dependencies: + rc "^1.2.8" + +registry-url@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942" + integrity sha1-PU74cPc93h138M+aOBQyRE4XSUI= + dependencies: + rc "^1.0.1" + +registry-url@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-5.1.0.tgz#e98334b50d5434b81136b44ec638d9c2009c5009" + integrity sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw== + dependencies: + rc "^1.2.8" + regjsgen@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" @@ -14172,7 +16458,7 @@ request-promise-core@1.1.3: dependencies: lodash "^4.17.15" -request-promise-native@^1.0.7: +request-promise-native@^1.0.7, request-promise-native@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.8.tgz#a455b960b826e44e2bf8999af64dff2bfe58cb36" integrity sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ== @@ -14191,7 +16477,7 @@ request-promise@^4.2.2: stealthy-require "^1.1.1" tough-cookie "^2.3.3" -request@^2.12.0, request@^2.55.0, request@^2.79.0, request@^2.85.0, request@^2.88.0: +request@^2.12.0, request@^2.55.0, request@^2.79.0, request@^2.85.0, request@^2.88.0, request@^2.88.2: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -14310,7 +16596,14 @@ 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.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: + version "1.16.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.16.1.tgz#49fac5d8bacf1fd53f200fa51247ae736175832c" + integrity sha512-rmAglCSqWWMrrBv/XM6sW0NuRFiKViw/W4d9EbC4pt+49H8JwHy+mcGmALTEg504AUDcLTvb1T2q3E9AnmY+ig== + dependencies: + path-parse "^1.0.6" + +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== @@ -14352,6 +16645,11 @@ ret@~0.1.10: resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== +retry@^0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4" + integrity sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q= + retry@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" @@ -14374,7 +16672,7 @@ rimraf@2.6.3, rimraf@~2.6.2: dependencies: glob "^7.1.3" -rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.3, rimraf@^2.7.1: +rimraf@^2.2.8, rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.2, rimraf@^2.6.3, rimraf@^2.7.1: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== @@ -14408,6 +16706,18 @@ rn-host-detect@^1.1.5: resolved "https://registry.yarnpkg.com/rn-host-detect/-/rn-host-detect-1.2.0.tgz#8b0396fc05631ec60c1cb8789e5070cdb04d0da0" integrity sha512-btNg5kzHcjZZ7t7mvvV/4wNJ9e3MPgrWivkRgWURzXL0JJ0pwWlU4zrbmdlz3HHzHOxhBhHB4D+/dbMFfu4/4A== +roarr@^2.15.2: + version "2.15.3" + resolved "https://registry.yarnpkg.com/roarr/-/roarr-2.15.3.tgz#65248a291a15af3ebfd767cbf7e44cb402d1d836" + integrity sha512-AEjYvmAhlyxOeB9OqPUzQCo3kuAkNfuDk/HqWbZdFsqDFpapkTjiw+p4svNEoRLvuqNTxqfL+s+gtD4eDgZ+CA== + dependencies: + boolean "^3.0.0" + detect-node "^2.0.4" + globalthis "^1.0.1" + json-stringify-safe "^5.0.1" + semver-compare "^1.0.0" + sprintf-js "^1.1.2" + rollup-plugin-commonjs@^10.1.0: version "10.1.0" resolved "https://registry.yarnpkg.com/rollup-plugin-commonjs/-/rollup-plugin-commonjs-10.1.0.tgz#417af3b54503878e084d127adf4d1caf8beb86fb" @@ -14465,7 +16775,7 @@ rustbn.js@~0.2.0: resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca" integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA== -rxjs@^6.3.3, rxjs@^6.4.0, rxjs@^6.5.3, rxjs@^6.5.5: +rxjs@^6.3.3, rxjs@^6.4.0, rxjs@^6.5.2, rxjs@^6.5.3, rxjs@^6.5.5: version "6.5.5" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.5.tgz#c5c884e3094c8cfee31bf27eb87e54ccfc87f9ec" integrity sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ== @@ -14521,7 +16831,14 @@ sane@^4.0.2, sane@^4.0.3: minimist "^1.1.1" walker "~1.0.5" -sax@^1.1.4, sax@~1.2.4: +sanitize-filename@^1.6.2, sanitize-filename@^1.6.3: + version "1.6.3" + resolved "https://registry.yarnpkg.com/sanitize-filename/-/sanitize-filename-1.6.3.tgz#755ebd752045931977e30b2025d340d7c9090378" + integrity sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg== + dependencies: + truncate-utf8-bytes "^1.0.0" + +sax@^1.1.4, sax@^1.2.4, sax@~1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== @@ -14575,10 +16892,10 @@ schema-utils@^1.0.0: ajv-errors "^1.0.0" ajv-keywords "^3.1.0" -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== +schema-utils@^2.6.4, schema-utils@^2.6.5: + version "2.6.6" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.6.6.tgz#299fe6bd4a3365dc23d99fd446caff8f1d6c330c" + integrity sha512-wHutF/WPSbIi9x6ctjGGk2Hvl0VOz5l3EKEuKbjPlB30mKZUzb9A5k9yEXRX3pwyqVLPvpfZZEllaFq/M718hA== dependencies: ajv "^6.12.0" ajv-keywords "^3.4.1" @@ -14593,14 +16910,6 @@ scrypt-js@2.0.4: resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.4.tgz#32f8c5149f0797672e551c07e230f834b6af5f16" integrity sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw== -scrypt.js@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/scrypt.js/-/scrypt.js-0.2.1.tgz#cc3f751933d6bac7a4bedf5301d7596e8146cdcd" - integrity sha512-XMoqxwABdotuW+l+qACmJ/h0kVSCgMPZXpbncA/zyBO90z/NnDISzVw+xJ4tUY+X/Hh0EFT269OYHm26VCPgmA== - dependencies: - scrypt "^6.0.2" - scryptsy "^1.2.1" - scrypt.js@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/scrypt.js/-/scrypt.js-0.3.0.tgz#6c62d61728ad533c8c376a2e5e3e86d41a95c4c0" @@ -14696,12 +17005,19 @@ 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-diff@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36" + integrity sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY= + dependencies: + semver "^5.0.3" + semver-regex@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-2.0.0.tgz#a93c2c5844539a770233379107b38c7b4ac9d338" integrity sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw== -"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: +"semver@2 || 3 || 4 || 5", "semver@2.x || 3.x || 4 || 5", "semver@^2.3.0 || 3.x || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.1: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -14716,16 +17032,16 @@ semver@7.0.0: resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== -semver@^6.0.0, semver@^6.1.2, semver@^6.3.0: +semver@7.3.2, semver@^7.1.2: + version "7.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" + integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== + +semver@^6.0.0, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -semver@^7.1.1: - version "7.2.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.2.2.tgz#d01432d74ed3010a20ffaf909d63a691520521cd" - integrity sha512-Zo84u6o2PebMSK3zjJ6Zp5wi8VnQZnEaCP13Ul/lt1ANsLACxnJxq4EEm1PY94/por1Hm9+7xpIswdS5AkieMA== - semver@~5.4.1: version "5.4.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" @@ -14750,6 +17066,13 @@ send@0.17.1: range-parser "~1.2.1" statuses "~1.5.0" +serialize-error@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-5.0.0.tgz#a7ebbcdb03a5d71a6ed8461ffe0fc1a1afed62ac" + integrity sha512-/VtpuyzYf82mHYTtI4QKtwHa79vAdU5OQpNPAmE/0UDdlGT0ZxHwC+J6gXkw29wwoVI8fMPsfcVHOwXtUQYYQA== + dependencies: + type-fest "^0.8.0" + serialize-javascript@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61" @@ -14789,7 +17112,7 @@ servify@^0.1.12: request "^2.79.0" xhr "^2.3.3" -set-blocking@^2.0.0: +set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= @@ -14844,6 +17167,13 @@ sha3@^1.2.2: dependencies: nan "2.13.2" +sha@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/sha/-/sha-3.0.0.tgz#b2f2f90af690c16a3a839a6a6c680ea51fedd1ae" + integrity sha512-DOYnM37cNsLNSGIG/zZWch5CKIRNoLdYUQTQlcgkRkoYIUwDYjqDyye16YcDZg/OPdcbUgTKMjc4SY6TB7ZAPw== + dependencies: + graceful-fs "^4.1.2" + shallowequal@^1.0.2, shallowequal@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8" @@ -14919,6 +17249,15 @@ simple-get@^2.7.0: once "^1.3.1" simple-concat "^1.0.0" +simple-get@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.1.0.tgz#b45be062435e50d159540b576202ceec40b9c6b3" + integrity sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA== + dependencies: + decompress-response "^4.2.0" + once "^1.3.1" + simple-concat "^1.0.0" + simple-swizzle@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" @@ -14960,6 +17299,16 @@ slice-ansi@^2.1.0: astral-regex "^1.0.0" is-fullwidth-code-point "^2.0.0" +slide@^1.1.6, slide@~1.1.3, slide@~1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" + integrity sha1-VusCfWW00tzmyy4tMsTUr8nh1wc= + +smart-buffer@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.1.0.tgz#91605c25d91652f4661ea69ccf45f1b331ca21ba" + integrity sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw== + snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" @@ -15026,7 +17375,37 @@ sockjs@0.3.19: faye-websocket "^0.10.0" uuid "^3.0.1" -solc@^0.5.0, solc@^0.5.9: +socks-proxy-agent@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz#3c8991f3145b2799e70e11bd5fbc8b1963116386" + integrity sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg== + dependencies: + agent-base "~4.2.1" + socks "~2.3.2" + +socks@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/socks/-/socks-2.3.3.tgz#01129f0a5d534d2b897712ed8aceab7ee65d78e3" + integrity sha512-o5t52PCNtVdiOvzMry7wU4aOqYWL0PeCXRWBEiJow4/i/wr+wpsJQ9awEu1EonLIqsfGd5qSgDdxEOvCdmBEpA== + dependencies: + ip "1.1.5" + smart-buffer "^4.1.0" + +solc@0.5.14: + version "0.5.14" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.5.14.tgz#7c3ecb2441ac10a15cdfd39207372eb63f2bd00c" + integrity sha512-I/MCeOKjnLXxcD65wA+E37BxdERoAYoLeyJ5GnXFijICLmvhzt0xz59R92Zw3TPyJYnHSErKBYpMsfnZVyQJaQ== + dependencies: + command-exists "^1.2.8" + commander "3.0.2" + fs-extra "^0.30.0" + js-sha3 "0.8.0" + memorystream "^0.3.1" + require-from-string "^2.0.0" + semver "^5.5.0" + tmp "0.0.33" + +solc@^0.5.0: version "0.5.17" resolved "https://registry.yarnpkg.com/solc/-/solc-0.5.17.tgz#8a76c50e98d49ca7610cca2fdc78ff3016540c67" integrity sha512-qpX+PGaU0Q3c6lh2vDzMoIbhv6bIrecI4bYsx+xUs01xsGFnY6Nr0L8y/QMyutTnrHN6Lb/Yl672ZVRqxka96w== @@ -15061,6 +17440,19 @@ sort-keys@^1.0.0: dependencies: is-plain-obj "^1.0.0" +sorted-object@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/sorted-object/-/sorted-object-2.0.1.tgz#7d631f4bd3a798a24af1dffcfbfe83337a5df5fc" + integrity sha1-fWMfS9OnmKJK8d/8+/6DM3pd9fw= + +sorted-union-stream@~2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/sorted-union-stream/-/sorted-union-stream-2.1.3.tgz#c7794c7e077880052ff71a8d4a2dbb4a9a638ac7" + integrity sha1-x3lMfgd4gAUv9xqNSi27Sppjisc= + dependencies: + from2 "^1.3.0" + stream-iterate "^1.1.0" + source-list-map@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" @@ -15092,10 +17484,10 @@ source-map-support@^0.4.15: dependencies: source-map "^0.5.6" -source-map-support@^0.5.16, source-map-support@^0.5.3, source-map-support@^0.5.6, source-map-support@~0.5.12: - version "0.5.16" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042" - integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ== +source-map-support@^0.5.13, source-map-support@^0.5.16, source-map-support@^0.5.3, source-map-support@^0.5.6, source-map-support@~0.5.12: + version "0.5.18" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.18.tgz#f5f33489e270bd7f7d7e7b8debf283f3a4066960" + integrity sha512-9luZr/BZ2QeU6tO2uG8N2aZpVSli4TSAOAqFOyTO51AJcD9P99c0K1h6dD6r6qo5dyT44BR5exweOaLLeldTkQ== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" @@ -15130,6 +17522,11 @@ spawn-args@^0.1.0: resolved "https://registry.yarnpkg.com/spawn-args/-/spawn-args-0.1.0.tgz#3e0232a0571b387907f8b3f544aa531c6224848c" integrity sha1-PgIyoFcbOHkH+LP1RKpTHGIkhIw= +spawn-command@^0.0.2-1: + version "0.0.2-1" + resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2-1.tgz#62f5e9466981c1b796dc5929937e11c9c6921bd0" + integrity sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A= + spdx-correct@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" @@ -15139,9 +17536,9 @@ spdx-correct@^3.0.0: spdx-license-ids "^3.0.0" spdx-exceptions@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" - integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== + version "2.3.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" + integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== spdx-expression-parse@^3.0.0: version "3.0.0" @@ -15191,6 +17588,11 @@ split-string@^3.0.1, split-string@^3.0.2: dependencies: extend-shallow "^3.0.0" +sprintf-js@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.2.tgz#da1765262bf8c0f571749f2ad6c26300207ae673" + integrity sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug== + sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -15247,7 +17649,7 @@ sshpk@^1.7.0: safer-buffer "^2.0.2" tweetnacl "~0.14.0" -ssri@^6.0.1: +ssri@^6.0.0, ssri@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8" integrity sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA== @@ -15272,6 +17674,16 @@ stack-utils@^1.0.1: resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.2.tgz#33eba3897788558bebfc2db059dc158ec36cebb8" integrity sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA== +stat-mode@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/stat-mode/-/stat-mode-0.3.0.tgz#69283b081f851582b328d2a4ace5f591ce52f54b" + integrity sha512-QjMLR0A3WwFY2aZdV0okfFEJB5TRjkggXZjxP3A1RsWsNHNu3YPv8btmtc6iCFZ0Rul3FE93OYogvhOUClU+ng== + +stat-mode@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/stat-mode/-/stat-mode-1.0.0.tgz#68b55cb61ea639ff57136f36b216a291800d1465" + integrity sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg== + static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" @@ -15322,6 +17734,14 @@ stream-http@^2.7.2: to-arraybuffer "^1.0.0" xtend "^4.0.0" +stream-iterate@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/stream-iterate/-/stream-iterate-1.2.0.tgz#2bd7c77296c1702a46488b8ad41f79865eecd4e1" + integrity sha1-K9fHcpbBcCpGSIuK1B95hl7s1OE= + dependencies: + readable-stream "^2.1.5" + stream-shift "^1.0.0" + stream-shift@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" @@ -15367,7 +17787,7 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: +"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== @@ -15476,6 +17896,11 @@ stringify-object@^3.3.0: is-obj "^1.0.1" is-regexp "^1.0.0" +stringify-package@^1.0.0, stringify-package@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/stringify-package/-/stringify-package-1.0.1.tgz#e5aa3643e7f74d0f28628b72f3dad5cecfc3ba85" + integrity sha512-sa4DUQsYciMP1xhKWGuFM04fB0LG/9DlluZoSVywUMRNvzid6XucHK0/90xGxRoHrAaROrcHK1aPKaijCtSrhg== + strip-ansi@6.0.0, strip-ansi@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" @@ -15565,7 +17990,7 @@ strip-indent@^3.0.0: dependencies: min-indent "^1.0.0" -strip-json-comments@^2.0.1: +strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= @@ -15582,13 +18007,13 @@ sturdy-websocket@^0.1.12: dependencies: lodash.defaults "^4.2.0" -style-loader@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-1.1.3.tgz#9e826e69c683c4d9bf9db924f85e9abb30d5e200" - integrity sha512-rlkH7X/22yuwFYK357fMN/BxYOorfnfq0eD7+vqlemSK4wEcejFF1dg4zxP0euBW8NrYx2WZzZ8PPFevr7D+Kw== +style-loader@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-1.1.4.tgz#1ad81283cefe51096756fd62697258edad933230" + integrity sha512-SbBHRD8fwK3pX+4UDF4ETxUF0+rCvk29LWTTI7Rt0cgsDjAj3SWM76ByTe6u2+4IlJ/WwluB7wuslWETCoPQdg== dependencies: - loader-utils "^1.2.3" - schema-utils "^2.6.4" + loader-utils "^2.0.0" + schema-utils "^2.6.5" styled-components@^5.0.1: version "5.1.0" @@ -15622,6 +18047,13 @@ sugarss@^2.0.0: dependencies: postcss "^7.0.2" +sumchecker@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/sumchecker/-/sumchecker-3.0.1.tgz#6377e996795abb0b6d348e9b3e1dfb24345a8e42" + integrity sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg== + dependencies: + debug "^4.1.0" + supports-color@5.4.0: version "5.4.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" @@ -15641,6 +18073,13 @@ supports-color@^2.0.0: resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= +supports-color@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" + integrity sha1-vnoN5ITexcXN34s9WRJQRJEvY1s= + dependencies: + has-flag "^2.0.0" + supports-color@^5.3.0, supports-color@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -15756,6 +18195,16 @@ tape@^4.6.3: string.prototype.trim "~1.2.1" through "~2.3.8" +tar-fs@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.0.1.tgz#e44086c1c60d31a4f0cf893b1c4e155dabfae9e2" + integrity sha512-6tzWDMeroL87uF/+lin46k+Q+46rAJ0SyPGz7OW7wTgblI273hsBqk2C1j0/xNadNLKDTUL9BukSjB7cwgmlPA== + dependencies: + chownr "^1.1.1" + mkdirp-classic "^0.5.2" + pump "^3.0.0" + tar-stream "^2.0.0" + tar-stream@^1.5.2: version "1.6.2" resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" @@ -15769,7 +18218,18 @@ tar-stream@^1.5.2: to-buffer "^1.1.1" xtend "^4.0.0" -tar@^4.0.2: +tar-stream@^2.0.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.1.2.tgz#6d5ef1a7e5783a95ff70b69b97455a5968dc1325" + integrity sha512-UaF6FoJ32WqALZGOIAApXx+OdxhekNMChu6axLJR85zMMjXKWFGjbIRe+J6P4UnRGg9rAwWvbTT0oI7hD/Un7Q== + dependencies: + bl "^4.0.1" + end-of-stream "^1.4.1" + fs-constants "^1.0.0" + inherits "^2.0.3" + readable-stream "^3.1.1" + +tar@^4.0.2, tar@^4.4.10, tar@^4.4.12, tar@^4.4.13: version "4.4.13" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== @@ -15782,6 +18242,14 @@ tar@^4.0.2: safe-buffer "^5.1.2" yallist "^3.0.3" +temp-file@^3.3.4, temp-file@^3.3.6: + version "3.3.7" + resolved "https://registry.yarnpkg.com/temp-file/-/temp-file-3.3.7.tgz#686885d635f872748e384e871855958470aeb18a" + integrity sha512-9tBJKt7GZAQt/Rg0QzVWA8Am8c1EFl+CAv04/aBVqlx5oyfQ508sFIABshQ0xbZu6mBrFLWIUXO/bbLYghW70g== + dependencies: + async-exit-hook "^2.0.1" + fs-extra "^8.1.0" + temp@^0.8.3: version "0.8.4" resolved "https://registry.yarnpkg.com/temp/-/temp-0.8.4.tgz#8c97a33a4770072e0a05f919396c7665a7dd59f2" @@ -15789,6 +18257,13 @@ temp@^0.8.3: dependencies: rimraf "~2.6.2" +term-size@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69" + integrity sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk= + dependencies: + execa "^0.7.0" + terminal-link@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" @@ -15845,7 +18320,7 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" -text-table@0.2.0, text-table@^0.2.0: +text-table@0.2.0, text-table@^0.2.0, text-table@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= @@ -15887,7 +18362,7 @@ through2@^0.6.0: readable-stream ">=1.0.33-1 <1.1.0-0" xtend ">=4.0.0 <4.1.0-0" -through@^2.3.6, through@^2.3.8, through@~2.3.4, through@~2.3.8: +"through@>=2.2.7 <3", 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= @@ -15931,6 +18406,11 @@ tiny-invariant@^1.0.2: resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.1.0.tgz#634c5f8efdc27714b7f386c35e6760991d230875" integrity sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw== +tiny-relative-date@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/tiny-relative-date/-/tiny-relative-date-1.3.0.tgz#fa08aad501ed730f31cc043181d995c39a935e07" + integrity sha512-MOQHpzllWxDCHHaDno30hhLfbouoYlOI8YlMNtvKe1zXbjEVhbcEovQxvZrPvtiYW630GQDoMMarCnjfyfHA+A== + tiny-warning@^1.0.0, tiny-warning@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" @@ -16079,6 +18559,11 @@ tr46@~0.0.1: resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= +tree-kill@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" + integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== + trezor-connect@7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/trezor-connect/-/trezor-connect-7.0.1.tgz#e57103729026177a92bfdefb64dd0d38f921ab1f" @@ -16321,16 +18806,6 @@ truffle-error@^0.0.5: resolved "https://registry.yarnpkg.com/truffle-error/-/truffle-error-0.0.5.tgz#6b5740c9f3aac74f47b85d654fff7fe2c1fc5e0e" integrity sha512-JpzPLMPSCE0vaZ3vH5NO5u42GpMj/Y1SRBkQ6b69PSw3xMSH1umApN32cEcg1nnh8q5FNYc5FnKu0m4tiBffyQ== -truffle-hdwallet-provider@0.0.7-beta.1: - version "0.0.7-beta.1" - resolved "https://registry.yarnpkg.com/truffle-hdwallet-provider/-/truffle-hdwallet-provider-0.0.7-beta.1.tgz#ca5107a8c470eba9811f3ca760b53ff611e8485a" - integrity sha512-klqrlm19xkXuoYKTqjz+KSR/X2BMplqsgE7GcIxFkp2oR1NKqKFd8U/eAojpkpBLYd5W7gbFHMxhWKjQYViKKA== - dependencies: - bip39 "^2.2.0" - ethereumjs-wallet "0.6.0" - web3 "^0.18.2" - web3-provider-engine "^14.0.5" - truffle-init@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/truffle-init/-/truffle-init-1.0.7.tgz#c3de57fbddfa77ae93642ae025f41c1157de2ba7" @@ -16406,24 +18881,40 @@ truffle-solidity-loader@0.1.32: truffle-config "^1.1.19" truffle-core "^5.0.33" -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== +truffle@5.1.21: + version "5.1.21" + resolved "https://registry.yarnpkg.com/truffle/-/truffle-5.1.21.tgz#f3a518f3e5bcb32d73734d21311d2b6bcab9f455" + integrity sha512-DRsG8bQZlZNydTr7LpoY87X77nQTU5ZMjkJmF66o3efyfC3dyXbMjws3ofn92iz+WsrpAw3u7/urnxF7fwtrkQ== dependencies: app-module-path "^2.2.0" mocha "5.2.0" original-require "1.0.1" +truffle@^5.1.21: + version "5.1.22" + resolved "https://registry.yarnpkg.com/truffle/-/truffle-5.1.22.tgz#564e3e245b9b5ceb53ad1075e00ec68682bd3509" + integrity sha512-E1Kz7b2y1ApxytKmEDL04Xdmz+zEjTqWNTbp0DLFh928yzxL47xzDmuZyinx4pPNrt9vnnhoHMHqeh36IFkK1Q== + dependencies: + app-module-path "^2.2.0" + mocha "5.2.0" + original-require "1.0.1" + +truncate-utf8-bytes@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz#405923909592d56f78a5818434b0b78489ca5f2b" + integrity sha1-QFkjkJWS1W94pYGENLC3hInKXys= + dependencies: + utf8-byte-length "^1.0.1" + tryer@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA== -ts-essentials@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-5.0.0.tgz#531d590c9cd62652c9d96284904cbdb2a1dd5ca8" - integrity sha512-ftKWOm6Jq+/UCBekDfxUjLODEd5XGN2EM/+TIQV9LJ5xSV12je4GqdRyv7pXXGGYmEt/nQa6F00xTWYJ5PMjIQ== +ts-essentials@^6.0.3: + version "6.0.4" + resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-6.0.4.tgz#d36055bf0a7620b1338da6aafd2268787e208aab" + integrity sha512-ZtU9zgSnn8DcAxDZY1DJF8rnxsen8M0IVkO7dVB5fTEOVs7o/0RA4V6i99PIg99bpX81Sgb0FCLjQqD5Ufz3rQ== tslib@^1.10.0, tslib@^1.9.0: version "1.11.1" @@ -16447,6 +18938,11 @@ tunnel@0.0.2: resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.2.tgz#f23bcd8b7a7b8a864261b2084f66f93193396334" integrity sha1-8jvNi3p7ioZCYbIIT2b5MZM5YzQ= +tunnel@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c" + integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg== + tweetnacl-util@^0.15.0: version "0.15.1" resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz#b80fcdb5c97bcc508be18c44a4be50f022eea00b" @@ -16479,7 +18975,17 @@ type-fest@^0.11.0: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1" integrity sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ== -type-fest@^0.8.1: +type-fest@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1" + integrity sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ== + +type-fest@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" + integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== + +type-fest@^0.8.0, type-fest@^0.8.1: version "0.8.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== @@ -16560,11 +19066,21 @@ 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== +uid-number@0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" + integrity sha1-DqEOgDXo61uOREnwbaHHMGY7qoE= + ultron@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== +umask@^1.1.0, umask@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/umask/-/umask-1.1.0.tgz#f29cebf01df517912bb58ff9c4e50fde8e33320d" + integrity sha1-8pzr8B31F5ErtY/5xOUP3o4zMg0= + unbzip2-stream@^1.0.9: version "1.4.1" resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.4.1.tgz#151b104af853df3efdaa135d8b1eca850a44b426" @@ -16697,11 +19213,50 @@ unset-value@^1.0.0: has-value "^0.3.1" isobject "^3.0.0" +unzip-response@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" + integrity sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c= + upath@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== +update-notifier@^2.2.0, update-notifier@^2.3.0, update-notifier@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.5.0.tgz#d0744593e13f161e406acb1d9408b72cad08aff6" + integrity sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw== + dependencies: + boxen "^1.2.1" + chalk "^2.0.1" + configstore "^3.0.0" + import-lazy "^2.1.0" + is-ci "^1.0.10" + is-installed-globally "^0.1.0" + is-npm "^1.0.0" + latest-version "^3.0.0" + semver-diff "^2.0.0" + xdg-basedir "^3.0.0" + +update-notifier@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-3.0.1.tgz#78ecb68b915e2fd1be9f767f6e298ce87b736250" + integrity sha512-grrmrB6Zb8DUiyDIaeRTBCkgISYUgETNe7NglEbVsrLWXeESnlCSP50WfRSj/GmzMPl6Uchj24S/p80nP/ZQrQ== + dependencies: + boxen "^3.0.0" + chalk "^2.0.1" + configstore "^4.0.0" + has-yarn "^2.1.0" + import-lazy "^2.1.0" + is-ci "^2.0.0" + is-installed-globally "^0.1.0" + is-npm "^3.0.0" + is-yarn-global "^0.3.0" + latest-version "^5.0.0" + semver-diff "^2.0.0" + xdg-basedir "^3.0.0" + uri-js@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" @@ -16714,10 +19269,10 @@ urix@^0.1.0: resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= -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== +url-loader@4.1.0, url-loader@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-4.1.0.tgz#c7d6b0d6b0fccd51ab3ffc58a78d32b8d89a7be2" + integrity sha512-IzgAAIC8wRrg6NYkFIJY09vtktQcsvU8V6HhtQj9PTefbYImzLB1hufqo4m+RyM5N3mLx5BqJKccgxJS+W3kqw== dependencies: loader-utils "^2.0.0" mime-types "^2.1.26" @@ -16763,11 +19318,25 @@ url@^0.11.0: punycode "1.3.2" querystring "0.2.0" +usb@^1.6.0: + version "1.6.3" + resolved "https://registry.yarnpkg.com/usb/-/usb-1.6.3.tgz#c0bc14994e8f9cb16f9602ec0dbadaa57cb919f5" + integrity sha512-23KYMjaWydACd8wgGKMQ4MNwFspAT6Xeim4/9Onqe5Rz/nMb4TM/WHL+qPT0KNFxzNKzAs63n1xQWGEtgaQ2uw== + dependencies: + bindings "^1.4.0" + nan "2.13.2" + prebuild-install "^5.3.3" + use@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== +utf8-byte-length@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz#f45f150c4c66eee968186505ab93fcbb8ad6bf61" + integrity sha1-9F8VDExm7uloGGUFq5P8u4rWv2E= + utf8@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/utf8/-/utf8-2.1.1.tgz#2e01db02f7d8d0944f77104f1609eb0c304cf768" @@ -16788,6 +19357,18 @@ util-deprecate@^1.0.1, util-deprecate@~1.0.1: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= +util-extend@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/util-extend/-/util-extend-1.0.3.tgz#a7c216d267545169637b3b6edc6ca9119e2ff93f" + integrity sha1-p8IW0mdUUWljeztu3GypEZ4v+T8= + +util-promisify@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/util-promisify/-/util-promisify-2.1.0.tgz#3c2236476c4d32c5ff3c47002add7c13b9a82a53" + integrity sha1-PCI2R2xNMsX/PEcAKt18E7moKlM= + dependencies: + object.getownpropertydescriptors "^2.0.3" + util.promisify@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030" @@ -16850,12 +19431,7 @@ uuid@7.0.3: resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b" integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg== -uuid@^2.0.1: - version "2.0.3" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a" - integrity sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho= - -uuid@^3.0.0, uuid@^3.0.1, uuid@^3.3.2: +uuid@^3.0.0, uuid@^3.0.1, uuid@^3.3.2, uuid@^3.3.3: version "3.4.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== @@ -16877,7 +19453,7 @@ v8-compile-cache@^2.0.3: resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e" integrity sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g== -v8-to-istanbul@^4.0.1: +v8-to-istanbul@^4.1.3: version "4.1.3" resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-4.1.3.tgz#22fe35709a64955f49a08a7c7c959f6520ad6f20" integrity sha512-sAjOC+Kki6aJVbUOXJbcR0MnbfjvBzwKZazEJymA2IX49uoOdEdk+4fBq5cXgYgiyKtAyrrJNtBZdOeDIF+Fng== @@ -16891,7 +19467,7 @@ vali-date@^1.0.0: resolved "https://registry.yarnpkg.com/vali-date/-/vali-date-1.0.0.tgz#1b904a59609fb328ef078138420934f6b86709a6" integrity sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY= -validate-npm-package-license@^3.0.1: +validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== @@ -16899,6 +19475,13 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" +validate-npm-package-name@^3.0.0, validate-npm-package-name@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz#5fa912d81eb7d0c74afc140de7317f0ca7df437e" + integrity sha1-X6kS2B630MdK/BQN5zF/DKffQ34= + dependencies: + builtins "^1.0.3" + value-equal@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-1.0.1.tgz#1e0b794c734c5c0cade179c437d356d931a34d6c" @@ -16981,6 +19564,18 @@ w3c-xmlserializer@^1.1.2: webidl-conversions "^4.0.2" xml-name-validator "^3.0.0" +wait-on@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-4.0.2.tgz#6ee9b5751b4e0329630abbb5fdba787802b32914" + integrity sha512-Qpmgm3Hw/sXm7xK68FBsYy5r+Uid94/QymwnEjn9GTpfiWTUVYm0bccivVwY/BXGYO2r+5Cd8S/DzrRZqHK/9w== + dependencies: + "@hapi/joi" "^17.1.1" + lodash "^4.17.15" + minimist "^1.2.5" + request "^2.88.2" + request-promise-native "^1.0.8" + rxjs "^6.5.5" + walker@^1.0.7, walker@~1.0.5: version "1.0.7" resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" @@ -17004,7 +19599,7 @@ wbuf@^1.1.0, wbuf@^1.7.3: dependencies: minimalistic-assert "^1.0.0" -wcwidth@^1.0.1: +wcwidth@^1.0.0, wcwidth@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g= @@ -17389,36 +19984,10 @@ web3-provider-engine@14.2.0: xhr "^2.2.0" xtend "^4.0.1" -web3-provider-engine@^14.0.5: - version "14.2.1" - resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-14.2.1.tgz#ef351578797bf170e08d529cb5b02f8751329b95" - integrity sha512-iSv31h2qXkr9vrL6UZDm4leZMc32SjWJFGOp/D92JXfcEboCqraZyuExDkpxKw8ziTufXieNM7LSXNHzszYdJw== - dependencies: - async "^2.5.0" - backoff "^2.5.0" - clone "^2.0.0" - cross-fetch "^2.1.0" - eth-block-tracker "^3.0.0" - eth-json-rpc-infura "^3.1.0" - eth-sig-util "^1.4.2" - ethereumjs-block "^1.2.2" - ethereumjs-tx "^1.2.0" - ethereumjs-util "^5.1.5" - ethereumjs-vm "^2.3.4" - json-rpc-error "^2.0.0" - json-stable-stringify "^1.0.1" - promise-to-callback "^1.0.0" - readable-stream "^2.2.9" - request "^2.85.0" - semaphore "^1.0.3" - ws "^5.1.1" - xhr "^2.2.0" - xtend "^4.0.1" - web3-provider-engine@^15.0.4: - version "15.0.6" - resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-15.0.6.tgz#bb64d49d0718bb6a12f146bdd542d5f2f8fa4e48" - integrity sha512-KdIHmRmB7VG6HeSu4hlB+Iypsbv/dAbNV/UWBDxsTwLJuuTSobmtowOq5BEsegXtjWhSSzSi9O0Ci/DVG0kB1g== + version "15.0.7" + resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-15.0.7.tgz#2439cdb145140660eb1007e7c6acd2d2d867b432" + integrity sha512-0NN0JTc4O/J9NFBtdqc4Ug+ujnniIBTCvauw3OlgZzfjnwr4irDU5CpviS5v33arYpC+WMnaDunad/OFrO/Wcw== dependencies: async "^2.5.0" backoff "^2.5.0" @@ -17610,7 +20179,7 @@ web3@1.2.6, web3@^1.0.0-beta.34: web3-shh "1.2.6" web3-utils "1.2.6" -web3@^0.18.2, web3@^0.18.4: +web3@^0.18.4: version "0.18.4" resolved "https://registry.yarnpkg.com/web3/-/web3-0.18.4.tgz#81ec1784145491f2eaa8955b31c06049e07c5e7d" integrity sha1-gewXhBRUkfLqqJVbMcBgSeB8Xn0= @@ -17642,10 +20211,10 @@ 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.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== +webpack-bundle-analyzer@3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.7.0.tgz#84da434e89442899b884d9ad38e466d0db02a56f" + integrity sha512-mETdjZ30a3Yf+NTB/wqTgACK7rAYQl5uxKK0WVTNmF0sM3Uv8s3R58YZMW7Rhu0Lk2Rmuhdj5dcH5Q76zCDVdA== dependencies: acorn "^7.1.1" acorn-walk "^7.1.1" @@ -17872,7 +20441,7 @@ which-pm-runs@^1.0.0: resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.0.0.tgz#670b3afbc552e0b55df6b7780ca74615f23ad1cb" integrity sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs= -which@^1.2.14, which@^1.2.9, which@^1.3.1: +which@^1.2.14, which@^1.2.9, which@^1.3.0, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== @@ -17886,6 +20455,20 @@ which@^2.0.1, which@^2.0.2: dependencies: isexe "^2.0.0" +wide-align@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + dependencies: + string-width "^1.0.2 || 2" + +widest-line@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.1.tgz#7438764730ec7ef4381ce4df82fb98a53142a3fc" + integrity sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA== + dependencies: + string-width "^2.1.1" + window-size@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" @@ -17896,7 +20479,7 @@ word-wrap@~1.2.3: resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== -worker-farm@^1.7.0: +worker-farm@^1.6.0, worker-farm@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.7.0.tgz#26a94c5391bbca926152002f69b84a4bf772e5a8" integrity sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw== @@ -17949,7 +20532,7 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -write-file-atomic@^2.0.0: +write-file-atomic@^2.0.0, write-file-atomic@^2.3.0, write-file-atomic@^2.4.3: version "2.4.3" resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481" integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ== @@ -18127,11 +20710,11 @@ yallist@^4.0.0: integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== yaml@^1.7.2: - version "1.8.3" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.8.3.tgz#2f420fca58b68ce3a332d0ca64be1d191dd3f87a" - integrity sha512-X/v7VDnK+sxbQ2Imq4Jt2PRUsRsP7UcpSl3Llg6+NRRqWLIvxkMFYtH1FmvwNGYRKKPa+EPA4qDBlI9WVG1UKw== + version "1.9.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.9.2.tgz#f0cfa865f003ab707663e4f04b3956957ea564ed" + integrity sha512-HPT7cGGI0DuRcsO51qC1j9O16Dh1mZ2bnXwsi0jrSpsLz0WxOLSLXfkABVl6bZO629py3CU+OMJtpNHDLB97kg== dependencies: - "@babel/runtime" "^7.8.7" + "@babel/runtime" "^7.9.2" yargs-parser@^10.0.0: version "10.1.0" @@ -18157,9 +20740,9 @@ yargs-parser@^13.1.0: decamelize "^1.2.0" yargs-parser@^18.1.1: - version "18.1.2" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.2.tgz#2f482bea2136dbde0861683abea7756d30b504f1" - integrity sha512-hlIPNR3IzC1YuL1c2UwwDKpXlNFBqD1Fswwh1khz5+d8Cq/8yc/Mn0i+rQXduu8hcrFKvO7Eryk+09NecTQAAQ== + version "18.1.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== dependencies: camelcase "^5.0.0" decamelize "^1.2.0" @@ -18179,7 +20762,14 @@ yargs-parser@^7.0.0: dependencies: camelcase "^4.1.0" -yargs@12.0.5: +yargs-parser@^9.0.2: + version "9.0.2" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077" + integrity sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc= + dependencies: + camelcase "^4.1.0" + +yargs@12.0.5, yargs@^12.0.5: version "12.0.5" resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13" integrity sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw== @@ -18232,7 +20822,25 @@ yargs@4.6.0: y18n "^3.2.1" yargs-parser "^2.4.0" -yargs@^15.3.1: +yargs@^11.0.0: + version "11.1.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.1.tgz#5052efe3446a4df5ed669c995886cc0f13702766" + integrity sha512-PRU7gJrJaXv3q3yQZ/+/X6KBswZiaQ+zOmdprZcouPYtQgvNU35i+68M4b1ZHLZtYFT5QObFLV+ZkmJYcwKdiw== + dependencies: + cliui "^4.0.0" + decamelize "^1.1.1" + find-up "^2.1.0" + get-caller-file "^1.0.1" + os-locale "^3.1.0" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^2.0.0" + which-module "^2.0.0" + y18n "^3.2.1" + yargs-parser "^9.0.2" + +yargs@^15.0.2, 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== @@ -18268,7 +20876,7 @@ yargs@^8.0.2: y18n "^3.2.1" yargs-parser "^7.0.0" -yauzl@^2.4.2: +yauzl@^2.10.0, yauzl@^2.4.2: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= From d975ec9fca2e0f4e9c15881a92cf80bef0ab8223 Mon Sep 17 00:00:00 2001 From: Mati Dastugue Date: Fri, 24 Apr 2020 17:51:52 -0300 Subject: [PATCH 2/5] Update CI Desktop script --- .github/workflows/release.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 50461708..ff157685 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,6 +13,7 @@ env: REACT_APP_GOOGLE_ANALYTICS_ID_MAINNET: ${{ secrets.REACT_APP_GOOGLE_ANALYTICS_ID_MAINNET }} REACT_APP_INFURA_TOKEN: ${{ secrets.REACT_APP_INFURA_TOKEN }} REACT_APP_PORTIS_ID: ${{ secrets.REACT_APP_PORTIS_ID }} + REACT_APP_GNOSIS_APPS_URL: ${{ secrets.REACT_APP_GNOSIS_APPS_URL }} jobs: release: @@ -32,6 +33,7 @@ jobs: uses: actions/setup-node@v1 with: node-version: 10.16 + - run: yarn install --network-concurrency 1 - name: Patch node gyp on windows to support Visual Studio 2019 if: startsWith(matrix.os, 'windows') From c783397f8fca87d6ec2c03cb9b80b2dc90c12fbc Mon Sep 17 00:00:00 2001 From: Mati Dastugue Date: Fri, 24 Apr 2020 18:33:49 -0300 Subject: [PATCH 3/5] Update CI script for windows --- .github/workflows/release.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ff157685..8442f310 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -28,18 +28,13 @@ jobs: steps: - name: Check out Git repository uses: actions/checkout@v2 - - - name: Install Node.js, NPM and Yarn - uses: actions/setup-node@v1 - with: - node-version: 10.16 - - run: yarn install --network-concurrency 1 - + - name: Patch node gyp on windows to support Visual Studio 2019 if: startsWith(matrix.os, 'windows') shell: powershell run: | yarn global add --production windows-build-tools --vs2015 --msvs_version=2015 + - name: Install node-gyp if: startsWith(matrix.os, 'windows') shell: powershell @@ -47,6 +42,12 @@ jobs: yarn global add node-gyp yarn config set node_gyp "$_\node_modules\node-gyp\bin\node-gyp.js" + - name: Install Node.js, NPM and Yarn + uses: actions/setup-node@v1 + with: + node-version: 10.16 + - run: yarn install --network-concurrency 1 + - name: Build/Release Desktop App env: # macOS notarization API key From fbaaff524e5da7d359528db8d502803999ef3ef0 Mon Sep 17 00:00:00 2001 From: nicolas Date: Mon, 27 Apr 2020 14:14:05 -0300 Subject: [PATCH 4/5] Development v2 fixes (#822) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 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 * (Fix) Adapt app to back-end changes (#736) * refactor: Set success status to `201` (CREATED) * refactor: return `null` when there's no latestTx * (Fix) Transaction not automatically executed (#716) * feature: action/reducer to UPDATE_SAFE_NONCE * refactor: when processing txs returned from backend, extract latest tx nonce value and store it in the safe's state * chore: update `yarn.lock` * refactor: `UPDATE_SAFE_THRESHOLD` and `UPDATE_SAFE_NONCE` discarded in favor of `UPDATE_SAFE` * refactor: use `SAFE_REDUCER_ID` constant * refactor: remove `updateSafeNonce` file * (Fix) Change the order of the upgrade methods lookup (#740) * fix: change the order of the upgrade methods lookup The `isUpgradeTransaction` method was looking for the methods in an wrong order (#599). The proper order was set in #610, but `isUpgradeTransaction` wasn't updated. * fix: contract upgrade version lookup * Feature: Use eth_sign for hardware wallets connected via onboard.js (#742) * Use eth_sign for hardware wallets * install onboard.js with fix from forked repo * rebuild yarn.lock to fix cached onboard * update bnc-onboard * update package json (#743) * (Fix) Properly decode threshold value in tx details (#749) * fix: Display new threshold value when changing its value There was a typo for the `changeThreshold` action fixes #746 * refactor: use a constant for safe methods names * fix: check for `decimals` method in transferredTokens (#748) Previously we were looking for `decimals` hash in the contract `code`. There are some contracts like USDC who happen to be behind a FiatTokenProxy, making it upgradable. By directly calling the `decimals()` method, we interact with the contract and can be sure that the `decimals()` method is present. fixes #678 * Bug #747: Don't use getLastTxNonce to fetch safe nonce (#750) * don't use getLastTxNonce to fetch safe nonce * fetch safe nonce in checkAndUpdateSafe * checkAndUpdateSafe refactor * remove nonce update logic from UPDATE_SAFE reducer * handle the case when localSafe returns undefined * handle the case when localSafe returns undefined in buildTransactionFrom * bump package json version to 1.9.4 * Issue-595: Apps config from Manifest (#715) * getting apps info from its manifest * Consume app info from manifest in Apps list, Transactions and Toast * fixes * navigate to TX Tab with an app makes a TX * (Fix) If backend returns `null` for addresses the Transaction ca… (#718) This tends to solve any possible issue that there may be in the tx execution for the `gasToken` and `refundReceiver` nullish values. fixes #573 * #751 fix - Replaces decimals from backend with decimals from blockchain (#755) * Replaces decimals from backend with decimals from blockchain * Removes fetching again token info from blockchain Fixs decimals cast, now we force to move from bignumber to number For data already wrong stored as string we remove it to force fetching again the decimals * Fixs missing symbol * Add description comment * Added Unilogin provider + support for legacy paths (#719) * Added unilogin provier + support for legacy path * Bump onboardjs version * fallback to displaying custom tx when we fail to fetch token info (#767) * Create release.yml Created script for building desktop app * Feature #322: Set safeTxGas for newly created transactions (#752) * Set safeTxGas for newly created transactions * extending estimation for nested calls WIP * messing up things to implement safeTxGas estimation * simplifying base gas calculations * remove eslint disable * messing things up to make things work * bring estimateData back * pass payload to requiredTxGas * pass esimateData to estimateDataGasCosts * remove console log * use batch requests to estimate safeTxGas * use const for txGasEstimation * check the response in request simultion * sidebar fix * remove for loop * Manage Apps (#765) * getting apps info from its manifest * Consume app info from manifest in Apps list, Transactions and Toast * fixes * navigate to TX Tab with an app makes a TX * ManageApps partial implementation * update safe-react-components * changes * apps validator * fix providedBy * TextField in addApp * fix checkbox error message * validation * adding app * Manage Apps * fix modal width * update package.json * update netlify url * fix modal widh * Set layout to Non-owners allowed error * some fixes * Apply suggestions from code review Co-Authored-By: lukasschor * review changes * fix condition * Legal Disclaimer * Better error message * update yarn.lock * Error message * review fixes * upgrade safe-react-components * show for all environments * Disclaimer changes * review changes * fix re-render * visual changes Co-authored-by: Agustín Longoni Co-authored-by: lukasschor * fix scroll and fix margin layout * Add region to travis CI develop (#787) Enable region for s3 provider to allow upload development environment to different S3 regions * Feature/travis ci s3 region (#789) * Add region to travis CI develop Enable region for s3 provider to allow upload development environment to different S3 regions * Enable region for staging s3 providers * fix error on Wrapper * Add gnosis wc bridge to onboard.js wallets options array (#790) * Rename incoming-transactions url to incoming-transfers * Feature #587 - App performance improvement (#738) * Refactor Balances to functional component Removes Balances props in Layout.jsx * Replaces selectors that were using safeParamAddressSelector with safeParamAddressFromStateSelector to avoid the bug of non-loaded safe when called Also exports extendedTransactionsSelector to let the components use it * Refactors Transactions.jsx, replaces transactions.tsx with txsTable.jsx Removes all unused props from transactions.jsx Makes all childs of txsTable.jsx fetch the props they need instead of sharing all of them even if they are not used * Adds new selectors: safeNameSelector, safeNeedsUpdateSelector, safeCurrentVersionSelector * Removes unused props from layout to settings.jsx Removed props from the settings.jsx childs, now they fetch the values they need directly from the store * Removes unused redux connect * Adds safeEthBalanceSelector * Removes all the props from layout to settings * Refactor root and layout, extracts checkForUpdate and componentDidMount to components Extracts header and tabs from Layout.jsx * Makes routes.jsx use selectors instead of connect to unify the code * Loads tabs components using react suspense * Fixs warning when trying to update root component within loadStore.jsx Replaces safe with safeAddress selector in layout.jsx to reduce the unnecessary rendering Fixs setState in container.jsx * Fixs checkForUpdates fetchTokenBalances Adds FetchTokens.jsx in balances Adds safeFeaturesEnabledSelector * Fixs load addressbook action * Replaces safe with owners in manage owners * Improves buildSafe promises calls Improves the loadStorage calls * Fixs error "Uncaught (in promise) TypeError: Cannot read property 'includes' of undefined" * Extracts LoadStore from outside the router component to avoid re-loading the store Adds react lazy for Coins and Collectible tabs * Reduce the polling rate for fetching transactions * Removes unused actions.js Removes unused selector props * Fixes owners column selector usage * Fixes processTransaction usage * Optimize how the transaction list within the transactions tab are loaded * Fix lint error * Fix edit addressbook entry * Fixs show send coins modal * feature: batchRequest for incoming transactions * Fixs race condition on loadStore Fixs check for updates address null validation * Adds ensureOnceAsync for getGnosisSafeInstanceAt Adds batch request for safe params * Removes unnecessary checkAndUpdateSafe from checkForUpdates, now the safe gets updated when a transaction arrives * Fixs ensureOnce/memoization * refactor: make a generic generateBatchRequest method Create a generic method to easily build web3 batch requests * refactor: use `generateBatchRequest` in `getTokensBalances` * Removes .toJS in edit entry * Removes web3 from sendTransactions Removes pascal case FetchTokens * Replaces /layout import * Replaces CheckForUpdates component with useCheckForUpdates hook * Makes FetchTokens a hook * Removes getSafeParamsBatch, now the safes gets the data using the generic generateBatchRequests * Replaces INITIAL_STATUS with INITIAL_STATE * Replaces regex Adds spaces before return * Adds wrapInSuspense * Runs prettier * Makes checkAndUpdateSafe use generateBatchRequests * Makes checkAndUpdateSafe use generateBatchRequests * Fixs check for updates with null address * Fixs transaction details getNameFromAddressBook * Fixes zIndex between cookies banner and transaction details * fix: cast returned values to number Original code was expecting a BN instance, now it's a plain string. * Fix replace owner name * Fix race condition with adbk load * Fixes replaces owner * Fixs apps * Moved hooks into own folder * Moved LoadStore to routes.js Refactors LoadStore as Hook Move LoadStore to hooks folder * Moves useLoadStore to safes/index * Revert loadStore place change * Fixes bug with fetchEtherBalance that causes updateSafe to be called * remove useLoadStore, add useAnalytics hook * remove React.memo from SafeView * Reverts removing useLoadStore in order to maintain the consistency of the code * rewrite useLoadStore in a more hook-y way, rename it to useLoadSafe * Removes unnecessary setSafeLoaded * Removes unnecessary safeLoaded * fix: Coins values and balances The app was retrieving ERC20 tokens information from 3 different endpoints. - One from `balance/` to have the list updated - another from `balance/usd` to have the values in USD - the last one from the blockchain, to update the balances This was all simplified to `balance/usd`. Also, added a `currencyRate` to be updated when the currency is modified. The value calculation happens on a component level, so when the `balanceUsd` value is modified, the value is properly reflected on the screen. Refactored `activateTokensByBalance` to `fetchSafeTokens`, as this was doing quite more than just _activating_ and also added the `currencyList` calculation in it, so everything is updated when `balance/usd` endpoint is requested. * fix: Balance screen Collectibles weren't loading when clicking on the link Also, refactored setState usage, to properly update current state * fix: featuresEnabled undefined * fix: add/activate newly received tokens * fix: NaN Values in Coins for a newly loaded Safe Was failing to set a default value for the `currencyRate` * fix: Settings fails to load if `owners` is not loaded into store Added a `Loader` until the required Safe's data is loaded into store. * fix: prefetch txs data When building the Txs list, we requested data for every tx what was translated into several RPC calls. Now by _batchRequesting_ all the information on beforehand, Safe's loading is a bit faster. * fix: prevent requesting safe, when there's no safe available in the store * enhancement: fetch tokens when loading safe By doing this, when loading a safe in the balance screen we will have tokens immediately loaded into the coins list * fix: load collectibles when switch to collectibles screen Collectibles weren't loaded when clicking menu link for a newly loaded safe. Now every switch to the collectible's screen will trigger a fetch for collectibles. * fix: fetch only if safe is ready Co-authored-by: fernandomg Co-authored-by: Mikhail Mikheev * Fix (#777) * fix: batchRequest params order * fix: execute decodeParams for all sendTokenTxs * fix: proper amount display for tx in TxTable * Uses formatAmount * Removes unused code Fixs params props safe address form * Fixs composeValidators Adds composeValidators for apps section * Makes composeValidatorsApps a wrapper * Moves composeValidatorsApps to managesApps.js * Desktop app (#745) * Set up electron app * Update dependencies * Update package.json * Added https support * Add support for Ledger * Updated certs * Added auto updates messages * Update auto-updater method * Update package.json * Added build resources * Update preload * Update Ledger method on mac * Update build * Merge with develop * Added support for Portis * Fix electron error and updater * Update auto updater * Fix dependencies * Merge with develop * Change auto update functionality * Edit package.json and added github actions * Updated github actions * Fixed Torus + Update github actions * Updated release.yml * Try only ubuntu * Update package.json * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * Updated safe-contracts * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * Updated deploy branch * Updated script Co-authored-by: Mati Dastugue * Update yarn script + SAFE_APPS env variable * Converts custom token address to checksum version (#793) * SafeTxGas calculation: Add check for openethereum/parity revert messages (#788) * add check for openethereum/parity revert messages * fix isEstimationSuccessful check * fix estimation check if revert msg is from openethereum * Issue 796 (#807) * consume gnosis componentes from npm * set safe-apps url from environment variable * fix apps padding and border radius * Apps updates * update disclaimer * fix Loader in TXList * Fix invalid origin Co-authored-by: Agustín Longoni * (Feature) Tx Table amount notations (#812) * Fix master conflicts (#819) * v2.0.0 (#806) * 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 * (Fix) Adapt app to back-end changes (#736) * refactor: Set success status to `201` (CREATED) * refactor: return `null` when there's no latestTx * (Fix) Transaction not automatically executed (#716) * feature: action/reducer to UPDATE_SAFE_NONCE * refactor: when processing txs returned from backend, extract latest tx nonce value and store it in the safe's state * chore: update `yarn.lock` * refactor: `UPDATE_SAFE_THRESHOLD` and `UPDATE_SAFE_NONCE` discarded in favor of `UPDATE_SAFE` * refactor: use `SAFE_REDUCER_ID` constant * refactor: remove `updateSafeNonce` file * (Fix) Change the order of the upgrade methods lookup (#740) * fix: change the order of the upgrade methods lookup The `isUpgradeTransaction` method was looking for the methods in an wrong order (#599). The proper order was set in #610, but `isUpgradeTransaction` wasn't updated. * fix: contract upgrade version lookup * Feature: Use eth_sign for hardware wallets connected via onboard.js (#742) * Use eth_sign for hardware wallets * install onboard.js with fix from forked repo * rebuild yarn.lock to fix cached onboard * update bnc-onboard * update package json (#743) * (Fix) Properly decode threshold value in tx details (#749) * fix: Display new threshold value when changing its value There was a typo for the `changeThreshold` action fixes #746 * refactor: use a constant for safe methods names * fix: check for `decimals` method in transferredTokens (#748) Previously we were looking for `decimals` hash in the contract `code`. There are some contracts like USDC who happen to be behind a FiatTokenProxy, making it upgradable. By directly calling the `decimals()` method, we interact with the contract and can be sure that the `decimals()` method is present. fixes #678 * Bug #747: Don't use getLastTxNonce to fetch safe nonce (#750) * don't use getLastTxNonce to fetch safe nonce * fetch safe nonce in checkAndUpdateSafe * checkAndUpdateSafe refactor * remove nonce update logic from UPDATE_SAFE reducer * handle the case when localSafe returns undefined * handle the case when localSafe returns undefined in buildTransactionFrom * bump package json version to 1.9.4 * Issue-595: Apps config from Manifest (#715) * getting apps info from its manifest * Consume app info from manifest in Apps list, Transactions and Toast * fixes * navigate to TX Tab with an app makes a TX * (Fix) If backend returns `null` for addresses the Transaction ca… (#718) This tends to solve any possible issue that there may be in the tx execution for the `gasToken` and `refundReceiver` nullish values. fixes #573 * #751 fix - Replaces decimals from backend with decimals from blockchain (#755) * Replaces decimals from backend with decimals from blockchain * Removes fetching again token info from blockchain Fixs decimals cast, now we force to move from bignumber to number For data already wrong stored as string we remove it to force fetching again the decimals * Fixs missing symbol * Add description comment * Added Unilogin provider + support for legacy paths (#719) * Added unilogin provier + support for legacy path * Bump onboardjs version * fallback to displaying custom tx when we fail to fetch token info (#767) * Create release.yml Created script for building desktop app * Feature #322: Set safeTxGas for newly created transactions (#752) * Set safeTxGas for newly created transactions * extending estimation for nested calls WIP * messing up things to implement safeTxGas estimation * simplifying base gas calculations * remove eslint disable * messing things up to make things work * bring estimateData back * pass payload to requiredTxGas * pass esimateData to estimateDataGasCosts * remove console log * use batch requests to estimate safeTxGas * use const for txGasEstimation * check the response in request simultion * sidebar fix * remove for loop * Manage Apps (#765) * getting apps info from its manifest * Consume app info from manifest in Apps list, Transactions and Toast * fixes * navigate to TX Tab with an app makes a TX * ManageApps partial implementation * update safe-react-components * changes * apps validator * fix providedBy * TextField in addApp * fix checkbox error message * validation * adding app * Manage Apps * fix modal width * update package.json * update netlify url * fix modal widh * Set layout to Non-owners allowed error * some fixes * Apply suggestions from code review Co-Authored-By: lukasschor * review changes * fix condition * Legal Disclaimer * Better error message * update yarn.lock * Error message * review fixes * upgrade safe-react-components * show for all environments * Disclaimer changes * review changes * fix re-render * visual changes Co-authored-by: Agustín Longoni Co-authored-by: lukasschor * fix scroll and fix margin layout * Add region to travis CI develop (#787) Enable region for s3 provider to allow upload development environment to different S3 regions * Feature/travis ci s3 region (#789) * Add region to travis CI develop Enable region for s3 provider to allow upload development environment to different S3 regions * Enable region for staging s3 providers * fix error on Wrapper * Add gnosis wc bridge to onboard.js wallets options array (#790) * Rename incoming-transactions url to incoming-transfers * Feature #587 - App performance improvement (#738) * Refactor Balances to functional component Removes Balances props in Layout.jsx * Replaces selectors that were using safeParamAddressSelector with safeParamAddressFromStateSelector to avoid the bug of non-loaded safe when called Also exports extendedTransactionsSelector to let the components use it * Refactors Transactions.jsx, replaces transactions.tsx with txsTable.jsx Removes all unused props from transactions.jsx Makes all childs of txsTable.jsx fetch the props they need instead of sharing all of them even if they are not used * Adds new selectors: safeNameSelector, safeNeedsUpdateSelector, safeCurrentVersionSelector * Removes unused props from layout to settings.jsx Removed props from the settings.jsx childs, now they fetch the values they need directly from the store * Removes unused redux connect * Adds safeEthBalanceSelector * Removes all the props from layout to settings * Refactor root and layout, extracts checkForUpdate and componentDidMount to components Extracts header and tabs from Layout.jsx * Makes routes.jsx use selectors instead of connect to unify the code * Loads tabs components using react suspense * Fixs warning when trying to update root component within loadStore.jsx Replaces safe with safeAddress selector in layout.jsx to reduce the unnecessary rendering Fixs setState in container.jsx * Fixs checkForUpdates fetchTokenBalances Adds FetchTokens.jsx in balances Adds safeFeaturesEnabledSelector * Fixs load addressbook action * Replaces safe with owners in manage owners * Improves buildSafe promises calls Improves the loadStorage calls * Fixs error "Uncaught (in promise) TypeError: Cannot read property 'includes' of undefined" * Extracts LoadStore from outside the router component to avoid re-loading the store Adds react lazy for Coins and Collectible tabs * Reduce the polling rate for fetching transactions * Removes unused actions.js Removes unused selector props * Fixes owners column selector usage * Fixes processTransaction usage * Optimize how the transaction list within the transactions tab are loaded * Fix lint error * Fix edit addressbook entry * Fixs show send coins modal * feature: batchRequest for incoming transactions * Fixs race condition on loadStore Fixs check for updates address null validation * Adds ensureOnceAsync for getGnosisSafeInstanceAt Adds batch request for safe params * Removes unnecessary checkAndUpdateSafe from checkForUpdates, now the safe gets updated when a transaction arrives * Fixs ensureOnce/memoization * refactor: make a generic generateBatchRequest method Create a generic method to easily build web3 batch requests * refactor: use `generateBatchRequest` in `getTokensBalances` * Removes .toJS in edit entry * Removes web3 from sendTransactions Removes pascal case FetchTokens * Replaces /layout import * Replaces CheckForUpdates component with useCheckForUpdates hook * Makes FetchTokens a hook * Removes getSafeParamsBatch, now the safes gets the data using the generic generateBatchRequests * Replaces INITIAL_STATUS with INITIAL_STATE * Replaces regex Adds spaces before return * Adds wrapInSuspense * Runs prettier * Makes checkAndUpdateSafe use generateBatchRequests * Makes checkAndUpdateSafe use generateBatchRequests * Fixs check for updates with null address * Fixs transaction details getNameFromAddressBook * Fixes zIndex between cookies banner and transaction details * fix: cast returned values to number Original code was expecting a BN instance, now it's a plain string. * Fix replace owner name * Fix race condition with adbk load * Fixes replaces owner * Fixs apps * Moved hooks into own folder * Moved LoadStore to routes.js Refactors LoadStore as Hook Move LoadStore to hooks folder * Moves useLoadStore to safes/index * Revert loadStore place change * Fixes bug with fetchEtherBalance that causes updateSafe to be called * remove useLoadStore, add useAnalytics hook * remove React.memo from SafeView * Reverts removing useLoadStore in order to maintain the consistency of the code * rewrite useLoadStore in a more hook-y way, rename it to useLoadSafe * Removes unnecessary setSafeLoaded * Removes unnecessary safeLoaded * fix: Coins values and balances The app was retrieving ERC20 tokens information from 3 different endpoints. - One from `balance/` to have the list updated - another from `balance/usd` to have the values in USD - the last one from the blockchain, to update the balances This was all simplified to `balance/usd`. Also, added a `currencyRate` to be updated when the currency is modified. The value calculation happens on a component level, so when the `balanceUsd` value is modified, the value is properly reflected on the screen. Refactored `activateTokensByBalance` to `fetchSafeTokens`, as this was doing quite more than just _activating_ and also added the `currencyList` calculation in it, so everything is updated when `balance/usd` endpoint is requested. * fix: Balance screen Collectibles weren't loading when clicking on the link Also, refactored setState usage, to properly update current state * fix: featuresEnabled undefined * fix: add/activate newly received tokens * fix: NaN Values in Coins for a newly loaded Safe Was failing to set a default value for the `currencyRate` * fix: Settings fails to load if `owners` is not loaded into store Added a `Loader` until the required Safe's data is loaded into store. * fix: prefetch txs data When building the Txs list, we requested data for every tx what was translated into several RPC calls. Now by _batchRequesting_ all the information on beforehand, Safe's loading is a bit faster. * fix: prevent requesting safe, when there's no safe available in the store * enhancement: fetch tokens when loading safe By doing this, when loading a safe in the balance screen we will have tokens immediately loaded into the coins list * fix: load collectibles when switch to collectibles screen Collectibles weren't loaded when clicking menu link for a newly loaded safe. Now every switch to the collectible's screen will trigger a fetch for collectibles. * fix: fetch only if safe is ready Co-authored-by: fernandomg Co-authored-by: Mikhail Mikheev * Fix (#777) * fix: batchRequest params order * fix: execute decodeParams for all sendTokenTxs * fix: proper amount display for tx in TxTable * Uses formatAmount * Removes unused code Fixs params props safe address form * Fixs composeValidators Adds composeValidators for apps section * Makes composeValidatorsApps a wrapper * Moves composeValidatorsApps to managesApps.js * Desktop app (#745) * Set up electron app * Update dependencies * Update package.json * Added https support * Add support for Ledger * Updated certs * Added auto updates messages * Update auto-updater method * Update package.json * Added build resources * Update preload * Update Ledger method on mac * Update build * Merge with develop * Added support for Portis * Fix electron error and updater * Update auto updater * Fix dependencies * Merge with develop * Change auto update functionality * Edit package.json and added github actions * Updated github actions * Fixed Torus + Update github actions * Updated release.yml * Try only ubuntu * Update package.json * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * Updated safe-contracts * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * Updated deploy branch * Updated script Co-authored-by: Mati Dastugue Co-authored-by: Fernando Co-authored-by: nicolas Co-authored-by: Agustin Pane Co-authored-by: Mati Dastugue Co-authored-by: Agustín Longoni Co-authored-by: lukasschor Co-authored-by: David Albela Pérez <3659067+davidalbela@users.noreply.github.com> Co-authored-by: Uxio Fuentefria Co-authored-by: Mati Dastugue * Update CI Desktop script * Update CI script for windows Co-authored-by: Mikhail Mikheev Co-authored-by: Fernando Co-authored-by: Agustin Pane Co-authored-by: Mati Dastugue Co-authored-by: Agustín Longoni Co-authored-by: lukasschor Co-authored-by: David Albela Pérez <3659067+davidalbela@users.noreply.github.com> Co-authored-by: Uxio Fuentefria Co-authored-by: Mati Dastugue Co-authored-by: Mikhail Mikheev Co-authored-by: Fernando Co-authored-by: Agustin Pane Co-authored-by: Mati Dastugue Co-authored-by: Agustín Longoni Co-authored-by: lukasschor Co-authored-by: David Albela Pérez <3659067+davidalbela@users.noreply.github.com> Co-authored-by: Uxio Fuentefria Co-authored-by: Mati Dastugue --- package.json | 6 +- .../layouts/ListContentLayout/Layout.jsx | 3 +- src/logic/safe/transactions/gasNew.js | 9 +- src/logic/tokens/store/reducer/tokens.js | 2 +- src/logic/tokens/utils/formatAmount.js | 2 +- src/routes/safe/components/Apps/index.jsx | 5 +- src/routes/safe/components/Apps/utils.js | 18 +- .../Tokens/screens/AddCustomToken/index.jsx | 4 +- .../IncomingTxDescription/index.jsx | 2 +- .../ExpandedTx/TxDescription/index.jsx | 2 +- .../TxsTable/ExpandedTx/index.jsx | 25 +- .../Transactions/TxsTable/TxType/index.jsx | 3 +- .../Transactions/TxsTable/columns.js | 48 +- .../safe/store/actions/fetchTransactions.js | 28 +- .../safe/store/models/incomingTransaction.js | 7 +- yarn.lock | 886 +++++++++++++++++- 16 files changed, 960 insertions(+), 90 deletions(-) diff --git a/package.json b/package.json index 6b96de14..7b34c5c1 100644 --- a/package.json +++ b/package.json @@ -136,9 +136,9 @@ }, "dependencies": { "@gnosis.pm/safe-contracts": "1.1.1-dev.2", - "@gnosis.pm/util-contracts": "2.0.6", - "@ledgerhq/hw-transport-node-hid": "5.12.0", - "@gnosis.pm/safe-react-components": "https://github.com/gnosis/safe-react-components.git#71e6fed", + "@gnosis.pm/util-contracts": "2.0.6", + "@gnosis.pm/safe-react-components": "https://github.com/gnosis/safe-react-components.git#a057248", + "@ledgerhq/hw-transport-node-hid": "5.12.0", "@material-ui/core": "4.9.10", "@material-ui/icons": "4.9.1", "@material-ui/lab": "4.0.0-alpha.39", diff --git a/src/components-v2/layouts/ListContentLayout/Layout.jsx b/src/components-v2/layouts/ListContentLayout/Layout.jsx index 28ad2275..0228ed6d 100644 --- a/src/components-v2/layouts/ListContentLayout/Layout.jsx +++ b/src/components-v2/layouts/ListContentLayout/Layout.jsx @@ -4,7 +4,7 @@ import styled from 'styled-components' export const Wrapper = styled.div` display: grid; grid-template-columns: 245px auto; - grid-template-rows: 500px; + grid-template-rows: 514px; min-height: 525px; .background { @@ -33,6 +33,7 @@ export const Menu = styled.div.attrs(() => ({ className: 'background' }))` export const Content = styled.div.attrs(() => ({ className: 'background' }))` grid-column: 2; border-top-right-radius: 8px; + border-bottom-right-radius: 8px; background-color: white; ` diff --git a/src/logic/safe/transactions/gasNew.js b/src/logic/safe/transactions/gasNew.js index 15c33c17..3f34178f 100644 --- a/src/logic/safe/transactions/gasNew.js +++ b/src/logic/safe/transactions/gasNew.js @@ -118,8 +118,15 @@ export const estimateSafeTxGas = async ( gasLimit: txGasEstimation + dataGasEstimation + additionalGas, }, (error, res) => { + // res.data check is for OpenEthereum/Parity revert messages format + const isOpenEthereumRevertMsg = res && typeof res.data === 'string' + + const isEstimationSuccessful = + !error && + ((typeof res === 'string' && res !== '0x') || (isOpenEthereumRevertMsg && res.data.slice(9) !== '0x')) + resolve({ - success: error || res === '0x' ? false : true, + success: isEstimationSuccessful, estimation: txGasEstimation + additionalGas, }) }, diff --git a/src/logic/tokens/store/reducer/tokens.js b/src/logic/tokens/store/reducer/tokens.js index 3d9d1916..fa4f47a2 100644 --- a/src/logic/tokens/store/reducer/tokens.js +++ b/src/logic/tokens/store/reducer/tokens.js @@ -9,7 +9,7 @@ import { type Token, makeToken } from '~/logic/tokens/store/model/token' export const TOKEN_REDUCER_ID = 'tokens' -export type State = Map> +export type State = Map export default handleActions( { diff --git a/src/logic/tokens/utils/formatAmount.js b/src/logic/tokens/utils/formatAmount.js index 6c4221af..a6b5e628 100644 --- a/src/logic/tokens/utils/formatAmount.js +++ b/src/logic/tokens/utils/formatAmount.js @@ -18,7 +18,7 @@ export const formatAmount = (number: string | number) => { let numberFloat = parseFloat(number) if (numberFloat === 0) { - numberFloat = '0.000' + numberFloat = '0' } else if (numberFloat < 0.001) { numberFloat = '< 0.001' } else if (numberFloat < 1000) { diff --git a/src/routes/safe/components/Apps/index.jsx b/src/routes/safe/components/Apps/index.jsx index d25c46ba..cda87ddf 100644 --- a/src/routes/safe/components/Apps/index.jsx +++ b/src/routes/safe/components/Apps/index.jsx @@ -26,6 +26,8 @@ const APPS_STORAGE_KEY = 'APPS_STORAGE_KEY' const APPS_LEGAL_DISCLAIMER_STORAGE_KEY = 'APPS_LEGAL_DISCLAIMER_STORAGE_KEY' const StyledIframe = styled.iframe` + padding: 24px; + box-sizing: border-box; width: 100%; height: 100%; display: ${(props) => (props.shouldDisplay ? 'block' : 'none')}; @@ -36,7 +38,6 @@ const Centered = styled.div` justify-content: center; flex-direction: column; ` - const operations = { SEND_TRANSACTIONS: 'SEND_TRANSACTIONS', ON_SAFE_INFO: 'ON_SAFE_INFO', @@ -151,7 +152,7 @@ function Apps({ closeModal, closeSnackbar, enqueueSnackbar, openModal }: Props) Terms {' '} - and this Disclaimer, and agree to be bound by . + and this Disclaimer, and agree to be bound by them. } diff --git a/src/routes/safe/components/Apps/utils.js b/src/routes/safe/components/Apps/utils.js index 91cad05d..dcd7dbe2 100644 --- a/src/routes/safe/components/Apps/utils.js +++ b/src/routes/safe/components/Apps/utils.js @@ -3,10 +3,12 @@ import axios from 'axios' import appsIconSvg from '~/routes/safe/components/Transactions/TxsTable/TxType/assets/appsIcon.svg' -export const GNOSIS_APPS_URL = 'https://gnosis-apps.netlify.app' - -const appsUrl = process.env.REACT_APP_GNOSIS_APPS_URL ? process.env.REACT_APP_GNOSIS_APPS_URL : GNOSIS_APPS_URL -export const staticAppsList = [{ url: `${appsUrl}/compound`, disabled: false }] +export const staticAppsList = [ + { url: `${process.env.REACT_APP_GNOSIS_APPS_URL}/compound`, disabled: false }, + { url: `${process.env.REACT_APP_GNOSIS_APPS_URL}/uniswap`, disabled: false }, + { url: `${process.env.REACT_APP_GNOSIS_APPS_URL}/nexus-mutual`, disabled: false }, + { url: `${process.env.REACT_APP_GNOSIS_APPS_URL}/ens`, disabled: false }, +] export const getAppInfoFromOrigin = (origin: string) => { try { @@ -18,13 +20,17 @@ export const getAppInfoFromOrigin = (origin: string) => { } export const getAppInfoFromUrl = async (appUrl: string) => { + let res = { id: undefined, url: cleanedUpAppUrl, name: 'unknown', iconUrl: appsIconSvg, error: true } + + if (!appUrl) { + return res + } + let cleanedUpAppUrl = appUrl.trim() if (cleanedUpAppUrl.substr(-1) === '/') { cleanedUpAppUrl = cleanedUpAppUrl.substr(0, cleanedUpAppUrl.length - 1) } - let res = { id: undefined, url: cleanedUpAppUrl, name: 'unknown', iconUrl: appsIconSvg, error: true } - try { const appInfo = await axios.get(`${cleanedUpAppUrl}/manifest.json`) 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 2eb6512f..085c4c5a 100644 --- a/src/routes/safe/components/Balances/Tokens/screens/AddCustomToken/index.jsx +++ b/src/routes/safe/components/Balances/Tokens/screens/AddCustomToken/index.jsx @@ -21,6 +21,7 @@ import Img from '~/components/layout/Img' import Paragraph from '~/components/layout/Paragraph' import Row from '~/components/layout/Row' import { type Token, type TokenProps } from '~/logic/tokens/store/model/token' +import { getWeb3 } from '~/logic/wallets/getWeb3' import TokenPlaceholder from '~/routes/safe/components/Balances/assets/token_placeholder.svg' export const ADD_CUSTOM_TOKEN_ADDRESS_INPUT_TEST_ID = 'add-custom-token-address-input' @@ -64,8 +65,9 @@ const AddCustomToken = (props: Props) => { const [formValues, setFormValues] = useState(INITIAL_FORM_STATE) const handleSubmit = (values) => { + const address = getWeb3().utils.toChecksumAddress(values.address) const token = { - address: values.address, + address, decimals: values.decimals, symbol: values.symbol, name: values.symbol, diff --git a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/IncomingTxDescription/index.jsx b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/IncomingTxDescription/index.jsx index a7107233..b169866c 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/IncomingTxDescription/index.jsx +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/IncomingTxDescription/index.jsx @@ -49,7 +49,7 @@ const IncomingTxDescription = ({ tx }: Props) => { const txFromName = getNameFromAddressBook(tx.from) return ( - + ) } 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 dd09fcec..54ac5a2a 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/index.jsx +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/index.jsx @@ -222,7 +222,7 @@ const TxDescription = ({ classes, tx }: Props) => { removedOwner, upgradeTx, } = getTxData(tx) - const amount = getTxAmount(tx) + const amount = getTxAmount(tx, false) return ( {modifySettingsTx && action && ( diff --git a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/index.jsx b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/index.jsx index fdaaeee3..f3e09260 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/index.jsx +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/index.jsx @@ -41,8 +41,9 @@ const ExpandedTx = ({ cancelTx, tx }: Props) => { const [openModal, setOpenModal] = useState(null) const openApproveModal = () => setOpenModal('approveTx') const closeModal = () => setOpenModal(null) - const thresholdReached = !INCOMING_TX_TYPES.includes(tx.type) && threshold <= tx.confirmations.size - const canExecute = !INCOMING_TX_TYPES.includes(tx.type) && nonce === tx.nonce + const isIncomingTx = !!INCOMING_TX_TYPES[tx.type] + const thresholdReached = !isIncomingTx && threshold <= tx.confirmations.size + const canExecute = !isIncomingTx && nonce === tx.nonce const cancelThresholdReached = !!cancelTx && threshold <= cancelTx.confirmations.size const canExecuteCancel = nonce === tx.nonce @@ -59,22 +60,22 @@ const ExpandedTx = ({ cancelTx, tx }: Props) => { - + Hash: {tx.executionTxHash ? : 'n/a'} - - Nonce: - {tx.nonce} - + {!isIncomingTx && ( + + Nonce: + {tx.nonce} + + )} Fee: {tx.fee ? tx.fee : 'n/a'} - {INCOMING_TX_TYPES.includes(tx.type) ? ( + {isIncomingTx ? ( <> Created: @@ -113,9 +114,9 @@ const ExpandedTx = ({ cancelTx, tx }: Props) => { )} - {INCOMING_TX_TYPES.includes(tx.type) ? : } + {isIncomingTx ? : } - {!INCOMING_TX_TYPES.includes(tx.type) && ( + {!isIncomingTx && ( diff --git a/src/routes/safe/components/Transactions/TxsTable/columns.js b/src/routes/safe/components/Transactions/TxsTable/columns.js index 925d6bc0..b6d47de1 100644 --- a/src/routes/safe/components/Transactions/TxsTable/columns.js +++ b/src/routes/safe/components/Transactions/TxsTable/columns.js @@ -9,7 +9,6 @@ import TxType from './TxType' import { type Column } from '~/components/Table/TableHead' import { type SortRow, buildOrderFieldFrom } from '~/components/Table/sorting' import { formatAmount } from '~/logic/tokens/utils/formatAmount' -import { getWeb3 } from '~/logic/wallets/getWeb3' import { INCOMING_TX_TYPES, type IncomingTransaction } from '~/routes/safe/store/models/incomingTransaction' import { type Transaction } from '~/routes/safe/store/models/transaction' @@ -34,29 +33,40 @@ type TxData = { export const formatDate = (date: string): string => format(parseISO(date), 'MMM d, yyyy - HH:mm:ss') -export const getIncomingTxAmount = (tx: IncomingTransaction) => { - const txAmount = tx.value ? `${new BigNumber(tx.value).div(`1e${tx.decimals}`).toFixed()}` : 'n/a' - return `${txAmount} ${tx.symbol || 'n/a'}` +type TxValues = { + value?: string | number, + decimals?: string | number, + symbol?: string, } -export const getTxAmount = (tx: Transaction) => { - const web3 = getWeb3() - const { fromWei, toBN } = web3.utils +const NOT_AVAILABLE = 'n/a' - let txAmount = 'n/a' +const getAmountWithSymbol = ({ decimals = 0, symbol = NOT_AVAILABLE, value }: TxValues, formatted = false) => { + const nonFormattedValue = BigNumber(value).times(`1e-${decimals}`).toFixed() + const finalValue = formatted ? formatAmount(nonFormattedValue).toString() : nonFormattedValue + const txAmount = finalValue === 'NaN' ? NOT_AVAILABLE : finalValue - if (tx.isTokenTransfer && tx.decodedParams) { - const tokenDecimals = tx.decimals.toNumber ? tx.decimals.toNumber() : tx.decimals - txAmount = `${formatAmount( - BigNumber(tx.decodedParams.value) - .div(10 ** tokenDecimals) - .toString(), - )} ${tx.symbol}` - } else if (Number(tx.value) > 0) { - txAmount = `${fromWei(toBN(tx.value), 'ether')} ${tx.symbol}` + return `${txAmount} ${symbol}` +} + +export const getIncomingTxAmount = (tx: IncomingTransaction, formatted: boolean = true) => { + // simple workaround to avoid displaying unexpected values for incoming NFT transfer + if (INCOMING_TX_TYPES[tx.type] === INCOMING_TX_TYPES.ERC721_TRANSFER) { + return `1 ${tx.symbol}` } - return txAmount + return getAmountWithSymbol(tx, formatted) +} + +export const getTxAmount = (tx: Transaction, formatted: boolean = true) => { + const { decimals = 18, decodedParams, isTokenTransfer, symbol } = tx + const { value } = isTokenTransfer && decodedParams && decodedParams.value ? decodedParams : tx + + if (!isTokenTransfer && !(Number(value) > 0)) { + return NOT_AVAILABLE + } + + return getAmountWithSymbol({ decimals, symbol, value }, formatted) } export type TransactionRow = SortRow @@ -106,7 +116,7 @@ export const getTxTableData = ( const cancelTxsByNonce = cancelTxs.reduce((acc, tx) => acc.set(tx.nonce, tx), Map()) return transactions.map((tx) => { - if (INCOMING_TX_TYPES.includes(tx.type)) { + if (INCOMING_TX_TYPES[tx.type]) { return getIncomingTxTableData(tx) } diff --git a/src/routes/safe/store/actions/fetchTransactions.js b/src/routes/safe/store/actions/fetchTransactions.js index c9ef0d11..267b5c3c 100644 --- a/src/routes/safe/store/actions/fetchTransactions.js +++ b/src/routes/safe/store/actions/fetchTransactions.js @@ -76,12 +76,12 @@ type IncomingTxServiceModel = { export const buildTransactionFrom = async ( safeAddress: string, - tx: TxServiceModel, knownTokens, + tx: TxServiceModel, + txTokenCode, txTokenDecimals, - txTokenSymbol, txTokenName, - code, + txTokenSymbol, ): Promise => { const localSafe = await getLocalSafe(safeAddress) @@ -108,7 +108,7 @@ export const buildTransactionFrom = async ( const modifySettingsTx = sameAddress(tx.to, safeAddress) && Number(tx.value) === 0 && !!tx.data const cancellationTx = sameAddress(tx.to, safeAddress) && Number(tx.value) === 0 && !tx.data const isERC721Token = - (code && code.includes(SAFE_TRANSFER_FROM_WITHOUT_DATA_HASH)) || + (txTokenCode && txTokenCode.includes(SAFE_TRANSFER_FROM_WITHOUT_DATA_HASH)) || (isTokenTransfer(tx.data, Number(tx.value)) && !knownTokens.get(tx.to) && txTokenDecimals !== null) let isSendTokenTx = !isERC721Token && isTokenTransfer(tx.data, Number(tx.value)) const isMultiSendTx = isMultisendTransaction(tx.data, Number(tx.value)) @@ -118,7 +118,7 @@ export const buildTransactionFrom = async ( let refundParams = null if (tx.gasPrice > 0) { const refundSymbol = txTokenSymbol || 'ETH' - const decimals = txTokenName || 18 + const decimals = txTokenDecimals || 18 const feeString = (tx.gasPrice * (tx.baseGas + tx.safeTxGas)).toString().padStart(decimals, 0) const whole = feeString.slice(0, feeString.length - decimals) || '0' const fraction = feeString.slice(feeString.length - decimals) @@ -230,8 +230,8 @@ const addMockSafeCreationTx = (safeAddress): Array => [ const batchRequestTxsData = (txs: any[]) => { const web3Batch = new web3.BatchRequest() - const whenTxsValues = txs.map((tx) => { - const methods = ['decimals', { method: 'getCode', type: 'eth', args: [tx.to] }, 'symbol', 'name'] + const txsTokenInfo = txs.map((tx) => { + const methods = [{ method: 'getCode', type: 'eth', args: [tx.to] }, 'decimals', 'name', 'symbol'] return generateBatchRequests({ abi: ERC20Detailed.abi, address: tx.to, @@ -243,7 +243,7 @@ const batchRequestTxsData = (txs: any[]) => { web3Batch.execute() - return Promise.all(whenTxsValues) + return Promise.all(txsTokenInfo) } const batchRequestIncomingTxsData = (txs: IncomingTxServiceModel[]) => { @@ -341,9 +341,15 @@ export const loadSafeTransactions = async (safeAddress: string, getState: GetSta const txsWithData = await batchRequestTxsData(transactions) // 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( - txsWithData.map(([tx: TxServiceModel, decimals, code, symbol, name]) => - buildTransactionFrom(safeAddress, tx, knownTokens, decimals, symbol, name, code), - ), + txsWithData.map(([tx: TxServiceModel, code, decimals, name, symbol]) => { + const knownToken = knownTokens.get(tx.to) + + if (knownToken) { + ;({ decimals, name, symbol } = knownToken) + } + + return buildTransactionFrom(safeAddress, knownTokens, tx, code, decimals, name, symbol) + }), ) const groupedTxs = List(txsRecord).groupBy((tx) => (tx.get('cancellationTx') ? 'cancel' : 'outgoing')) diff --git a/src/routes/safe/store/models/incomingTransaction.js b/src/routes/safe/store/models/incomingTransaction.js index ebe5d7f5..d88405b0 100644 --- a/src/routes/safe/store/models/incomingTransaction.js +++ b/src/routes/safe/store/models/incomingTransaction.js @@ -2,7 +2,12 @@ import { Record } from 'immutable' import type { RecordFactory, RecordOf } from 'immutable' -export const INCOMING_TX_TYPES = ['INCOMING', 'ERC721_TRANSFER', 'ERC20_TRANSFER', 'ETHER_TRANSFER'] +export const INCOMING_TX_TYPES = { + INCOMING: 'INCOMING', + ERC721_TRANSFER: 'ERC721_TRANSFER', + ERC20_TRANSFER: 'ERC20_TRANSFER', + ETHER_TRANSFER: 'ETHER_TRANSFER', +} export type IncomingTransactionProps = { blockNumber: number, diff --git a/yarn.lock b/yarn.lock index 736873db..aa4fcd71 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1230,9 +1230,9 @@ solc "0.5.14" truffle "^5.1.21" -"@gnosis.pm/safe-react-components@https://github.com/gnosis/safe-react-components.git#71e6fed": +"@gnosis.pm/safe-react-components@https://github.com/gnosis/safe-react-components.git#a057248": version "0.1.1" - resolved "https://github.com/gnosis/safe-react-components.git#71e6fed337271b0b536c1ae8128d32d49fc74947" + resolved "https://github.com/gnosis/safe-react-components.git#a05724802f5fc74dd759ba8d9c916eb82cf67ef0" dependencies: classnames "^2.2.6" polished "^3.5.1" @@ -3025,6 +3025,13 @@ ansi-align@^3.0.0: dependencies: string-width "^3.0.0" +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" @@ -3042,6 +3049,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" @@ -3087,6 +3101,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= + ansicolors@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.3.2.tgz#665597de86a9ffe3aa9bfbe6cae5c6ea426b4979" @@ -3194,6 +3213,13 @@ 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.0.3, aproba@^1.1.1, aproba@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" @@ -3204,7 +3230,7 @@ aproba@^1.0.3, aproba@^1.1.1, aproba@^1.1.2: resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== -archy@~1.0.0: +archy@^1.0.0, archy@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA= @@ -3252,16 +3278,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" @@ -3291,6 +3336,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" @@ -3380,6 +3454,16 @@ astral-regex@^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" @@ -3407,6 +3491,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" @@ -4190,6 +4281,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" @@ -4695,6 +4801,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" @@ -4824,6 +4935,148 @@ bytes@3.0.0: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= +builder-util-runtime@8.5.0: + version "8.5.0" + resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.5.0.tgz#0c9faa782307867cc2ec70f25e63829ef1ea49c4" + integrity sha512-ft0npBXQc5gp1AVkY/WkUXDLKWweux/R1L+YQHjtspSp9nRHqoBP6qBTxb8ca6CtBKe+yZbZYGvCw1l0ZBkx/w== + dependencies: + debug "^4.1.1" + sax "^1.2.4" + +builder-util@21.2.0, builder-util@~21.2.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-21.2.0.tgz#aba721190e4e841009d9fb4b88f1130ed616522f" + integrity sha512-Nd6CUb6YgDY8EXAXEIegx+1kzKqyFQ5ZM5BoYkeunAlwz/zDJoH1UCyULjoS5wQe5czNClFQy07zz2bzYD0Z4A== + dependencies: + "7zip-bin" "~5.0.3" + "@types/debug" "^4.1.4" + app-builder-bin "3.4.3" + bluebird-lst "^1.0.9" + builder-util-runtime "8.3.0" + chalk "^2.4.2" + debug "^4.1.1" + fs-extra "^8.1.0" + is-ci "^2.0.0" + js-yaml "^3.13.1" + source-map-support "^0.5.13" + stat-mode "^0.3.0" + temp-file "^3.3.4" + +builder-util@22.2.0, builder-util@~22.2.0: + version "22.2.0" + resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-22.2.0.tgz#f9ac6a64d4fc3da16816a02e6f48f29fe8b0bb3d" + integrity sha512-kkhDjcFuY6qGHmRhOfmYnk+raxsPauddUu7Z+TUOqMOyBVFX8ODnDjIFWQ7yDz5+KNtS9MTObJl9MTAKSRPAVQ== + dependencies: + "7zip-bin" "~5.0.3" + "@types/debug" "^4.1.5" + app-builder-bin "3.5.1" + bluebird-lst "^1.0.9" + builder-util-runtime "8.5.0" + chalk "^3.0.0" + debug "^4.1.1" + fs-extra "^8.1.0" + is-ci "^2.0.0" + js-yaml "^3.13.1" + source-map-support "^0.5.16" + stat-mode "^1.0.0" + temp-file "^3.3.6" + +builtin-status-codes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" + integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= + +builtins@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" + integrity sha1-y5T662HIaWRR2zZTThQi+U8K7og= + +byline@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/byline/-/byline-5.0.0.tgz#741c5216468eadc457b03410118ad77de8c1ddb1" + integrity sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE= + +byte-size@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/byte-size/-/byte-size-5.0.1.tgz#4b651039a5ecd96767e71a3d7ed380e48bed4191" + integrity sha512-/XuKeqWocKsYa/cBY1YbSJSWWqTi4cFgr9S6OyM7PBaPbr9zvNGwWP33vt0uqGhwDdN+y3yhbXVILEUpnwEWGw== + +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= + +builder-util-runtime@8.5.0: + version "8.5.0" + resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.5.0.tgz#0c9faa782307867cc2ec70f25e63829ef1ea49c4" + integrity sha512-ft0npBXQc5gp1AVkY/WkUXDLKWweux/R1L+YQHjtspSp9nRHqoBP6qBTxb8ca6CtBKe+yZbZYGvCw1l0ZBkx/w== + dependencies: + debug "^4.1.1" + sax "^1.2.4" + +builder-util@21.2.0, builder-util@~21.2.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-21.2.0.tgz#aba721190e4e841009d9fb4b88f1130ed616522f" + integrity sha512-Nd6CUb6YgDY8EXAXEIegx+1kzKqyFQ5ZM5BoYkeunAlwz/zDJoH1UCyULjoS5wQe5czNClFQy07zz2bzYD0Z4A== + dependencies: + "7zip-bin" "~5.0.3" + "@types/debug" "^4.1.4" + app-builder-bin "3.4.3" + bluebird-lst "^1.0.9" + builder-util-runtime "8.3.0" + chalk "^2.4.2" + debug "^4.1.1" + fs-extra "^8.1.0" + is-ci "^2.0.0" + js-yaml "^3.13.1" + source-map-support "^0.5.13" + stat-mode "^0.3.0" + temp-file "^3.3.4" + +builder-util@22.2.0, builder-util@~22.2.0: + version "22.2.0" + resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-22.2.0.tgz#f9ac6a64d4fc3da16816a02e6f48f29fe8b0bb3d" + integrity sha512-kkhDjcFuY6qGHmRhOfmYnk+raxsPauddUu7Z+TUOqMOyBVFX8ODnDjIFWQ7yDz5+KNtS9MTObJl9MTAKSRPAVQ== + dependencies: + "7zip-bin" "~5.0.3" + "@types/debug" "^4.1.5" + app-builder-bin "3.5.1" + bluebird-lst "^1.0.9" + builder-util-runtime "8.5.0" + chalk "^3.0.0" + debug "^4.1.1" + fs-extra "^8.1.0" + is-ci "^2.0.0" + js-yaml "^3.13.1" + source-map-support "^0.5.16" + stat-mode "^1.0.0" + temp-file "^3.3.6" + +builtin-status-codes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" + integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= + +builtins@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" + integrity sha1-y5T662HIaWRR2zZTThQi+U8K7og= + +byline@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/byline/-/byline-5.0.0.tgz#741c5216468eadc457b03410118ad77de8c1ddb1" + integrity sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE= + +byte-size@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/byte-size/-/byte-size-5.0.1.tgz#4b651039a5ecd96767e71a3d7ed380e48bed4191" + integrity sha512-/XuKeqWocKsYa/cBY1YbSJSWWqTi4cFgr9S6OyM7PBaPbr9zvNGwWP33vt0uqGhwDdN+y3yhbXVILEUpnwEWGw== + +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= + bytes@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" @@ -5021,6 +5274,11 @@ caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30001035: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001041.tgz#c2ea138dafc6fe03877921ddcddd4a02a14daf76" integrity sha512-fqDtRCApddNrQuBxBS7kEiSGdBsgO4wiVw4G/IClfqzfhW45MbTumfN4cuUJGTM0YGFNn97DCXPJ683PS6zwvA== +caniuse-lite@^1.0.30001038: + version "1.0.30001048" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001048.tgz#4bb4f1bc2eb304e5e1154da80b93dee3f1cf447e" + integrity sha512-g1iSHKVxornw0K8LG9LLdf+Fxnv7T1Z+mMsf0/YYLclQX4Cd522Ap0Lrw6NFqHgezit78dtyWxzlV2Xfc7vgRg== + caniuse-lite@^1.0.30001039, caniuse-lite@^1.0.30001043: version "1.0.30001045" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001045.tgz#a770df9de36ad6ca0c34f90eaa797a2dbbb1b619" @@ -5143,7 +5401,7 @@ cheerio@1.0.0-rc.2: lodash "^4.15.0" parse5 "^3.0.1" -chokidar@^2.1.8: +chokidar@^2.0.0, chokidar@^2.1.8: version "2.1.8" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== @@ -5342,6 +5600,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" @@ -5354,6 +5617,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" @@ -5369,6 +5637,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" @@ -5406,6 +5683,15 @@ collect-v8-coverage@^1.0.0: resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg== +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" @@ -5456,6 +5742,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" @@ -5570,7 +5861,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.6.2: +concat-stream@^1.5.0, concat-stream@^1.5.1, concat-stream@^1.6.0, concat-stream@^1.6.2: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== @@ -5671,7 +5962,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== @@ -5710,6 +6001,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.5" resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.6.5.tgz#2a51d9a4e25dfd6e690251aa81f99e3c05481f1c" @@ -6356,6 +6655,13 @@ deepmerge@^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" @@ -6364,6 +6670,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" @@ -6811,6 +7122,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" @@ -6924,6 +7243,11 @@ electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.47: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.403.tgz#c8bab4e2e72bf78bc28bad1cc355c061f9cc1918" integrity sha512-JaoxV4RzdBAZOnsF4dAlZ2ijJW72MbqO5lNfOBHUWiBQl3Rwe+mk2RCUMrRI3rSClLJ8HSNQNqcry12H+0ZjFw== +electron-to-chromium@^1.3.390: + version "1.3.418" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.418.tgz#840021191f466b803a873e154113620c9f53cec6" + integrity sha512-i2QrQtHes5fK/F9QGG5XacM5WKEuR322fxTYF9e8O9Gu0mc0WmjjwGpV8c7Htso6Zf2Di18lc3SIPxmMeRFBug== + electron-to-chromium@^1.3.413: version "1.3.414" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.414.tgz#9d0a92defefda7cc1cf8895058b892795ddd6b41" @@ -7131,7 +7455,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== @@ -7145,7 +7469,7 @@ es6-error@^4.1.1: resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== -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= @@ -7174,6 +7498,16 @@ es6-symbol@^3.1.1, es6-symbol@~3.1.3: d "^1.0.1" ext "^1.1.2" +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: + 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" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" @@ -8386,6 +8720,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" @@ -8656,7 +9000,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== @@ -8666,11 +9010,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" @@ -8695,7 +9065,7 @@ flow-stoplight@^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== @@ -8736,6 +9106,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" @@ -8912,6 +9289,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" @@ -9189,11 +9574,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" @@ -9371,6 +9784,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, got@^9.6.0: version "9.6.0" resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" @@ -9450,6 +9870,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" @@ -9467,6 +9911,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" @@ -10244,7 +10705,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== @@ -10298,6 +10759,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" @@ -10551,6 +11020,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-npm@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4" @@ -10650,7 +11124,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== @@ -10696,6 +11170,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" @@ -10745,7 +11226,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= @@ -10755,6 +11243,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" @@ -11903,6 +12396,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" @@ -11965,7 +12463,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== @@ -11995,6 +12493,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" + latest-version@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-3.1.0.tgz#a205383fea322b33b5ae3b18abee0dc2f356ee15" @@ -12045,6 +12551,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" @@ -12333,6 +12846,20 @@ libnpx@^10.2.2: y18n "^4.0.0" yargs "^11.0.0" +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" @@ -12827,6 +13354,13 @@ make-fetch-happen@^5.0.0: socks-proxy-agent "^4.0.0" ssri "^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" @@ -12841,7 +13375,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= @@ -12873,6 +13407,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" + matcher@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/matcher/-/matcher-2.1.0.tgz#64e1041c15b993e23b786f93320a7474bf833c28" @@ -13407,6 +13951,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" @@ -13723,6 +14272,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-audit-report@^1.3.2: version "1.3.3" resolved "https://registry.yarnpkg.com/npm-audit-report/-/npm-audit-report-1.3.3.tgz#8226deeb253b55176ed147592a3995442f2179ed" @@ -14087,7 +14643,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== @@ -14097,6 +14653,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" @@ -14125,6 +14691,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" @@ -14133,13 +14707,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" @@ -14184,7 +14766,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.4.0: +once@^1.3.0, once@^1.3.1, once@^1.3.2, once@^1.4.0, once@~1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= @@ -14275,6 +14857,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" @@ -14538,6 +15127,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" @@ -14578,6 +15176,11 @@ 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" @@ -14675,6 +15278,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" @@ -15341,21 +15956,26 @@ pretty-format@^25.4.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" @@ -15534,7 +16154,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== @@ -16413,7 +17033,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= @@ -16451,6 +17088,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" @@ -16581,6 +17232,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" @@ -16603,6 +17261,13 @@ resolve@^1.1.6, resolve@^1.10.0, resolve@^1.11.0, resolve@^1.12.0, resolve@^1.13 dependencies: path-parse "^1.0.6" +resolve@^1.1.7, resolve@^1.4.0: + version "1.17.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" + integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== + dependencies: + path-parse "^1.0.6" + resolve@~1.15.1: version "1.15.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.1.tgz#27bdcdeffeaf2d6244b95bb0f9f4b4653451f3e8" @@ -17012,6 +17677,13 @@ semver-diff@^2.0.0: dependencies: semver "^5.0.3" +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" @@ -17517,6 +18189,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" @@ -17669,6 +18346,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" @@ -17723,6 +18405,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" @@ -17778,7 +18465,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= @@ -18102,6 +18789,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" @@ -18384,6 +19079,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" @@ -18442,6 +19142,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" @@ -18525,6 +19233,13 @@ 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" @@ -19089,6 +19804,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" @@ -19099,6 +19819,26 @@ underscore@^1.8.3: resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.10.2.tgz#73d6aa3668f3188e4adb0f1943bd12cfd7efaaaf" integrity sha512-N4P+Q/BuyuEKFJ43B9gYuOj4TQUHXX+j2FqguVOpjkssLUUrnJofCcBccJSCoeturDoZU6GorDTHSvUDlSQbTg== +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" @@ -19453,7 +20193,7 @@ v8-compile-cache@^2.0.3: resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e" integrity sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g== -v8-to-istanbul@^4.1.3: +v8-to-istanbul@^4.0.1, v8-to-istanbul@^4.1.3: version "4.1.3" resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-4.1.3.tgz#22fe35709a64955f49a08a7c7c959f6520ad6f20" integrity sha512-sAjOC+Kki6aJVbUOXJbcR0MnbfjvBzwKZazEJymA2IX49uoOdEdk+4fBq5cXgYgiyKtAyrrJNtBZdOeDIF+Fng== @@ -19462,6 +20202,13 @@ v8-to-istanbul@^4.1.3: 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" @@ -19487,6 +20234,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" @@ -19534,6 +20286,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" @@ -19543,6 +20331,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" @@ -20380,7 +21180,6 @@ 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" @@ -20431,6 +21230,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" @@ -20755,6 +21559,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" @@ -20857,6 +21668,25 @@ yargs@^15.0.2, yargs@^15.3.1: y18n "^4.0.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" resolved "https://registry.yarnpkg.com/yargs/-/yargs-8.0.2.tgz#6299a9055b1cefc969ff7e79c1d918dceb22c360" From 2c13d0836dcfb6afaa913bdb75d972ac09cd4d0e Mon Sep 17 00:00:00 2001 From: nicolas Date: Mon, 27 Apr 2020 15:51:30 -0300 Subject: [PATCH 5/5] Dev to master (#824) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 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 * (Fix) Adapt app to back-end changes (#736) * refactor: Set success status to `201` (CREATED) * refactor: return `null` when there's no latestTx * (Fix) Transaction not automatically executed (#716) * feature: action/reducer to UPDATE_SAFE_NONCE * refactor: when processing txs returned from backend, extract latest tx nonce value and store it in the safe's state * chore: update `yarn.lock` * refactor: `UPDATE_SAFE_THRESHOLD` and `UPDATE_SAFE_NONCE` discarded in favor of `UPDATE_SAFE` * refactor: use `SAFE_REDUCER_ID` constant * refactor: remove `updateSafeNonce` file * (Fix) Change the order of the upgrade methods lookup (#740) * fix: change the order of the upgrade methods lookup The `isUpgradeTransaction` method was looking for the methods in an wrong order (#599). The proper order was set in #610, but `isUpgradeTransaction` wasn't updated. * fix: contract upgrade version lookup * Feature: Use eth_sign for hardware wallets connected via onboard.js (#742) * Use eth_sign for hardware wallets * install onboard.js with fix from forked repo * rebuild yarn.lock to fix cached onboard * update bnc-onboard * update package json (#743) * (Fix) Properly decode threshold value in tx details (#749) * fix: Display new threshold value when changing its value There was a typo for the `changeThreshold` action fixes #746 * refactor: use a constant for safe methods names * fix: check for `decimals` method in transferredTokens (#748) Previously we were looking for `decimals` hash in the contract `code`. There are some contracts like USDC who happen to be behind a FiatTokenProxy, making it upgradable. By directly calling the `decimals()` method, we interact with the contract and can be sure that the `decimals()` method is present. fixes #678 * Bug #747: Don't use getLastTxNonce to fetch safe nonce (#750) * don't use getLastTxNonce to fetch safe nonce * fetch safe nonce in checkAndUpdateSafe * checkAndUpdateSafe refactor * remove nonce update logic from UPDATE_SAFE reducer * handle the case when localSafe returns undefined * handle the case when localSafe returns undefined in buildTransactionFrom * bump package json version to 1.9.4 * Issue-595: Apps config from Manifest (#715) * getting apps info from its manifest * Consume app info from manifest in Apps list, Transactions and Toast * fixes * navigate to TX Tab with an app makes a TX * (Fix) If backend returns `null` for addresses the Transaction ca… (#718) This tends to solve any possible issue that there may be in the tx execution for the `gasToken` and `refundReceiver` nullish values. fixes #573 * #751 fix - Replaces decimals from backend with decimals from blockchain (#755) * Replaces decimals from backend with decimals from blockchain * Removes fetching again token info from blockchain Fixs decimals cast, now we force to move from bignumber to number For data already wrong stored as string we remove it to force fetching again the decimals * Fixs missing symbol * Add description comment * Added Unilogin provider + support for legacy paths (#719) * Added unilogin provier + support for legacy path * Bump onboardjs version * fallback to displaying custom tx when we fail to fetch token info (#767) * Create release.yml Created script for building desktop app * Feature #322: Set safeTxGas for newly created transactions (#752) * Set safeTxGas for newly created transactions * extending estimation for nested calls WIP * messing up things to implement safeTxGas estimation * simplifying base gas calculations * remove eslint disable * messing things up to make things work * bring estimateData back * pass payload to requiredTxGas * pass esimateData to estimateDataGasCosts * remove console log * use batch requests to estimate safeTxGas * use const for txGasEstimation * check the response in request simultion * sidebar fix * remove for loop * Manage Apps (#765) * getting apps info from its manifest * Consume app info from manifest in Apps list, Transactions and Toast * fixes * navigate to TX Tab with an app makes a TX * ManageApps partial implementation * update safe-react-components * changes * apps validator * fix providedBy * TextField in addApp * fix checkbox error message * validation * adding app * Manage Apps * fix modal width * update package.json * update netlify url * fix modal widh * Set layout to Non-owners allowed error * some fixes * Apply suggestions from code review Co-Authored-By: lukasschor * review changes * fix condition * Legal Disclaimer * Better error message * update yarn.lock * Error message * review fixes * upgrade safe-react-components * show for all environments * Disclaimer changes * review changes * fix re-render * visual changes Co-authored-by: Agustín Longoni Co-authored-by: lukasschor * fix scroll and fix margin layout * Add region to travis CI develop (#787) Enable region for s3 provider to allow upload development environment to different S3 regions * Feature/travis ci s3 region (#789) * Add region to travis CI develop Enable region for s3 provider to allow upload development environment to different S3 regions * Enable region for staging s3 providers * fix error on Wrapper * Add gnosis wc bridge to onboard.js wallets options array (#790) * Rename incoming-transactions url to incoming-transfers * Feature #587 - App performance improvement (#738) * Refactor Balances to functional component Removes Balances props in Layout.jsx * Replaces selectors that were using safeParamAddressSelector with safeParamAddressFromStateSelector to avoid the bug of non-loaded safe when called Also exports extendedTransactionsSelector to let the components use it * Refactors Transactions.jsx, replaces transactions.tsx with txsTable.jsx Removes all unused props from transactions.jsx Makes all childs of txsTable.jsx fetch the props they need instead of sharing all of them even if they are not used * Adds new selectors: safeNameSelector, safeNeedsUpdateSelector, safeCurrentVersionSelector * Removes unused props from layout to settings.jsx Removed props from the settings.jsx childs, now they fetch the values they need directly from the store * Removes unused redux connect * Adds safeEthBalanceSelector * Removes all the props from layout to settings * Refactor root and layout, extracts checkForUpdate and componentDidMount to components Extracts header and tabs from Layout.jsx * Makes routes.jsx use selectors instead of connect to unify the code * Loads tabs components using react suspense * Fixs warning when trying to update root component within loadStore.jsx Replaces safe with safeAddress selector in layout.jsx to reduce the unnecessary rendering Fixs setState in container.jsx * Fixs checkForUpdates fetchTokenBalances Adds FetchTokens.jsx in balances Adds safeFeaturesEnabledSelector * Fixs load addressbook action * Replaces safe with owners in manage owners * Improves buildSafe promises calls Improves the loadStorage calls * Fixs error "Uncaught (in promise) TypeError: Cannot read property 'includes' of undefined" * Extracts LoadStore from outside the router component to avoid re-loading the store Adds react lazy for Coins and Collectible tabs * Reduce the polling rate for fetching transactions * Removes unused actions.js Removes unused selector props * Fixes owners column selector usage * Fixes processTransaction usage * Optimize how the transaction list within the transactions tab are loaded * Fix lint error * Fix edit addressbook entry * Fixs show send coins modal * feature: batchRequest for incoming transactions * Fixs race condition on loadStore Fixs check for updates address null validation * Adds ensureOnceAsync for getGnosisSafeInstanceAt Adds batch request for safe params * Removes unnecessary checkAndUpdateSafe from checkForUpdates, now the safe gets updated when a transaction arrives * Fixs ensureOnce/memoization * refactor: make a generic generateBatchRequest method Create a generic method to easily build web3 batch requests * refactor: use `generateBatchRequest` in `getTokensBalances` * Removes .toJS in edit entry * Removes web3 from sendTransactions Removes pascal case FetchTokens * Replaces /layout import * Replaces CheckForUpdates component with useCheckForUpdates hook * Makes FetchTokens a hook * Removes getSafeParamsBatch, now the safes gets the data using the generic generateBatchRequests * Replaces INITIAL_STATUS with INITIAL_STATE * Replaces regex Adds spaces before return * Adds wrapInSuspense * Runs prettier * Makes checkAndUpdateSafe use generateBatchRequests * Makes checkAndUpdateSafe use generateBatchRequests * Fixs check for updates with null address * Fixs transaction details getNameFromAddressBook * Fixes zIndex between cookies banner and transaction details * fix: cast returned values to number Original code was expecting a BN instance, now it's a plain string. * Fix replace owner name * Fix race condition with adbk load * Fixes replaces owner * Fixs apps * Moved hooks into own folder * Moved LoadStore to routes.js Refactors LoadStore as Hook Move LoadStore to hooks folder * Moves useLoadStore to safes/index * Revert loadStore place change * Fixes bug with fetchEtherBalance that causes updateSafe to be called * remove useLoadStore, add useAnalytics hook * remove React.memo from SafeView * Reverts removing useLoadStore in order to maintain the consistency of the code * rewrite useLoadStore in a more hook-y way, rename it to useLoadSafe * Removes unnecessary setSafeLoaded * Removes unnecessary safeLoaded * fix: Coins values and balances The app was retrieving ERC20 tokens information from 3 different endpoints. - One from `balance/` to have the list updated - another from `balance/usd` to have the values in USD - the last one from the blockchain, to update the balances This was all simplified to `balance/usd`. Also, added a `currencyRate` to be updated when the currency is modified. The value calculation happens on a component level, so when the `balanceUsd` value is modified, the value is properly reflected on the screen. Refactored `activateTokensByBalance` to `fetchSafeTokens`, as this was doing quite more than just _activating_ and also added the `currencyList` calculation in it, so everything is updated when `balance/usd` endpoint is requested. * fix: Balance screen Collectibles weren't loading when clicking on the link Also, refactored setState usage, to properly update current state * fix: featuresEnabled undefined * fix: add/activate newly received tokens * fix: NaN Values in Coins for a newly loaded Safe Was failing to set a default value for the `currencyRate` * fix: Settings fails to load if `owners` is not loaded into store Added a `Loader` until the required Safe's data is loaded into store. * fix: prefetch txs data When building the Txs list, we requested data for every tx what was translated into several RPC calls. Now by _batchRequesting_ all the information on beforehand, Safe's loading is a bit faster. * fix: prevent requesting safe, when there's no safe available in the store * enhancement: fetch tokens when loading safe By doing this, when loading a safe in the balance screen we will have tokens immediately loaded into the coins list * fix: load collectibles when switch to collectibles screen Collectibles weren't loaded when clicking menu link for a newly loaded safe. Now every switch to the collectible's screen will trigger a fetch for collectibles. * fix: fetch only if safe is ready Co-authored-by: fernandomg Co-authored-by: Mikhail Mikheev * Fix (#777) * fix: batchRequest params order * fix: execute decodeParams for all sendTokenTxs * fix: proper amount display for tx in TxTable * Uses formatAmount * Removes unused code Fixs params props safe address form * Fixs composeValidators Adds composeValidators for apps section * Makes composeValidatorsApps a wrapper * Moves composeValidatorsApps to managesApps.js * Desktop app (#745) * Set up electron app * Update dependencies * Update package.json * Added https support * Add support for Ledger * Updated certs * Added auto updates messages * Update auto-updater method * Update package.json * Added build resources * Update preload * Update Ledger method on mac * Update build * Merge with develop * Added support for Portis * Fix electron error and updater * Update auto updater * Fix dependencies * Merge with develop * Change auto update functionality * Edit package.json and added github actions * Updated github actions * Fixed Torus + Update github actions * Updated release.yml * Try only ubuntu * Update package.json * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * Updated safe-contracts * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * Updated deploy branch * Updated script Co-authored-by: Mati Dastugue * Update yarn script + SAFE_APPS env variable * Converts custom token address to checksum version (#793) * SafeTxGas calculation: Add check for openethereum/parity revert messages (#788) * add check for openethereum/parity revert messages * fix isEstimationSuccessful check * fix estimation check if revert msg is from openethereum * Issue 796 (#807) * consume gnosis componentes from npm * set safe-apps url from environment variable * fix apps padding and border radius * Apps updates * update disclaimer * fix Loader in TXList * Fix invalid origin Co-authored-by: Agustín Longoni * (Feature) Tx Table amount notations (#812) * Fix master conflicts (#819) * v2.0.0 (#806) * 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 * (Fix) Adapt app to back-end changes (#736) * refactor: Set success status to `201` (CREATED) * refactor: return `null` when there's no latestTx * (Fix) Transaction not automatically executed (#716) * feature: action/reducer to UPDATE_SAFE_NONCE * refactor: when processing txs returned from backend, extract latest tx nonce value and store it in the safe's state * chore: update `yarn.lock` * refactor: `UPDATE_SAFE_THRESHOLD` and `UPDATE_SAFE_NONCE` discarded in favor of `UPDATE_SAFE` * refactor: use `SAFE_REDUCER_ID` constant * refactor: remove `updateSafeNonce` file * (Fix) Change the order of the upgrade methods lookup (#740) * fix: change the order of the upgrade methods lookup The `isUpgradeTransaction` method was looking for the methods in an wrong order (#599). The proper order was set in #610, but `isUpgradeTransaction` wasn't updated. * fix: contract upgrade version lookup * Feature: Use eth_sign for hardware wallets connected via onboard.js (#742) * Use eth_sign for hardware wallets * install onboard.js with fix from forked repo * rebuild yarn.lock to fix cached onboard * update bnc-onboard * update package json (#743) * (Fix) Properly decode threshold value in tx details (#749) * fix: Display new threshold value when changing its value There was a typo for the `changeThreshold` action fixes #746 * refactor: use a constant for safe methods names * fix: check for `decimals` method in transferredTokens (#748) Previously we were looking for `decimals` hash in the contract `code`. There are some contracts like USDC who happen to be behind a FiatTokenProxy, making it upgradable. By directly calling the `decimals()` method, we interact with the contract and can be sure that the `decimals()` method is present. fixes #678 * Bug #747: Don't use getLastTxNonce to fetch safe nonce (#750) * don't use getLastTxNonce to fetch safe nonce * fetch safe nonce in checkAndUpdateSafe * checkAndUpdateSafe refactor * remove nonce update logic from UPDATE_SAFE reducer * handle the case when localSafe returns undefined * handle the case when localSafe returns undefined in buildTransactionFrom * bump package json version to 1.9.4 * Issue-595: Apps config from Manifest (#715) * getting apps info from its manifest * Consume app info from manifest in Apps list, Transactions and Toast * fixes * navigate to TX Tab with an app makes a TX * (Fix) If backend returns `null` for addresses the Transaction ca… (#718) This tends to solve any possible issue that there may be in the tx execution for the `gasToken` and `refundReceiver` nullish values. fixes #573 * #751 fix - Replaces decimals from backend with decimals from blockchain (#755) * Replaces decimals from backend with decimals from blockchain * Removes fetching again token info from blockchain Fixs decimals cast, now we force to move from bignumber to number For data already wrong stored as string we remove it to force fetching again the decimals * Fixs missing symbol * Add description comment * Added Unilogin provider + support for legacy paths (#719) * Added unilogin provier + support for legacy path * Bump onboardjs version * fallback to displaying custom tx when we fail to fetch token info (#767) * Create release.yml Created script for building desktop app * Feature #322: Set safeTxGas for newly created transactions (#752) * Set safeTxGas for newly created transactions * extending estimation for nested calls WIP * messing up things to implement safeTxGas estimation * simplifying base gas calculations * remove eslint disable * messing things up to make things work * bring estimateData back * pass payload to requiredTxGas * pass esimateData to estimateDataGasCosts * remove console log * use batch requests to estimate safeTxGas * use const for txGasEstimation * check the response in request simultion * sidebar fix * remove for loop * Manage Apps (#765) * getting apps info from its manifest * Consume app info from manifest in Apps list, Transactions and Toast * fixes * navigate to TX Tab with an app makes a TX * ManageApps partial implementation * update safe-react-components * changes * apps validator * fix providedBy * TextField in addApp * fix checkbox error message * validation * adding app * Manage Apps * fix modal width * update package.json * update netlify url * fix modal widh * Set layout to Non-owners allowed error * some fixes * Apply suggestions from code review Co-Authored-By: lukasschor * review changes * fix condition * Legal Disclaimer * Better error message * update yarn.lock * Error message * review fixes * upgrade safe-react-components * show for all environments * Disclaimer changes * review changes * fix re-render * visual changes Co-authored-by: Agustín Longoni Co-authored-by: lukasschor * fix scroll and fix margin layout * Add region to travis CI develop (#787) Enable region for s3 provider to allow upload development environment to different S3 regions * Feature/travis ci s3 region (#789) * Add region to travis CI develop Enable region for s3 provider to allow upload development environment to different S3 regions * Enable region for staging s3 providers * fix error on Wrapper * Add gnosis wc bridge to onboard.js wallets options array (#790) * Rename incoming-transactions url to incoming-transfers * Feature #587 - App performance improvement (#738) * Refactor Balances to functional component Removes Balances props in Layout.jsx * Replaces selectors that were using safeParamAddressSelector with safeParamAddressFromStateSelector to avoid the bug of non-loaded safe when called Also exports extendedTransactionsSelector to let the components use it * Refactors Transactions.jsx, replaces transactions.tsx with txsTable.jsx Removes all unused props from transactions.jsx Makes all childs of txsTable.jsx fetch the props they need instead of sharing all of them even if they are not used * Adds new selectors: safeNameSelector, safeNeedsUpdateSelector, safeCurrentVersionSelector * Removes unused props from layout to settings.jsx Removed props from the settings.jsx childs, now they fetch the values they need directly from the store * Removes unused redux connect * Adds safeEthBalanceSelector * Removes all the props from layout to settings * Refactor root and layout, extracts checkForUpdate and componentDidMount to components Extracts header and tabs from Layout.jsx * Makes routes.jsx use selectors instead of connect to unify the code * Loads tabs components using react suspense * Fixs warning when trying to update root component within loadStore.jsx Replaces safe with safeAddress selector in layout.jsx to reduce the unnecessary rendering Fixs setState in container.jsx * Fixs checkForUpdates fetchTokenBalances Adds FetchTokens.jsx in balances Adds safeFeaturesEnabledSelector * Fixs load addressbook action * Replaces safe with owners in manage owners * Improves buildSafe promises calls Improves the loadStorage calls * Fixs error "Uncaught (in promise) TypeError: Cannot read property 'includes' of undefined" * Extracts LoadStore from outside the router component to avoid re-loading the store Adds react lazy for Coins and Collectible tabs * Reduce the polling rate for fetching transactions * Removes unused actions.js Removes unused selector props * Fixes owners column selector usage * Fixes processTransaction usage * Optimize how the transaction list within the transactions tab are loaded * Fix lint error * Fix edit addressbook entry * Fixs show send coins modal * feature: batchRequest for incoming transactions * Fixs race condition on loadStore Fixs check for updates address null validation * Adds ensureOnceAsync for getGnosisSafeInstanceAt Adds batch request for safe params * Removes unnecessary checkAndUpdateSafe from checkForUpdates, now the safe gets updated when a transaction arrives * Fixs ensureOnce/memoization * refactor: make a generic generateBatchRequest method Create a generic method to easily build web3 batch requests * refactor: use `generateBatchRequest` in `getTokensBalances` * Removes .toJS in edit entry * Removes web3 from sendTransactions Removes pascal case FetchTokens * Replaces /layout import * Replaces CheckForUpdates component with useCheckForUpdates hook * Makes FetchTokens a hook * Removes getSafeParamsBatch, now the safes gets the data using the generic generateBatchRequests * Replaces INITIAL_STATUS with INITIAL_STATE * Replaces regex Adds spaces before return * Adds wrapInSuspense * Runs prettier * Makes checkAndUpdateSafe use generateBatchRequests * Makes checkAndUpdateSafe use generateBatchRequests * Fixs check for updates with null address * Fixs transaction details getNameFromAddressBook * Fixes zIndex between cookies banner and transaction details * fix: cast returned values to number Original code was expecting a BN instance, now it's a plain string. * Fix replace owner name * Fix race condition with adbk load * Fixes replaces owner * Fixs apps * Moved hooks into own folder * Moved LoadStore to routes.js Refactors LoadStore as Hook Move LoadStore to hooks folder * Moves useLoadStore to safes/index * Revert loadStore place change * Fixes bug with fetchEtherBalance that causes updateSafe to be called * remove useLoadStore, add useAnalytics hook * remove React.memo from SafeView * Reverts removing useLoadStore in order to maintain the consistency of the code * rewrite useLoadStore in a more hook-y way, rename it to useLoadSafe * Removes unnecessary setSafeLoaded * Removes unnecessary safeLoaded * fix: Coins values and balances The app was retrieving ERC20 tokens information from 3 different endpoints. - One from `balance/` to have the list updated - another from `balance/usd` to have the values in USD - the last one from the blockchain, to update the balances This was all simplified to `balance/usd`. Also, added a `currencyRate` to be updated when the currency is modified. The value calculation happens on a component level, so when the `balanceUsd` value is modified, the value is properly reflected on the screen. Refactored `activateTokensByBalance` to `fetchSafeTokens`, as this was doing quite more than just _activating_ and also added the `currencyList` calculation in it, so everything is updated when `balance/usd` endpoint is requested. * fix: Balance screen Collectibles weren't loading when clicking on the link Also, refactored setState usage, to properly update current state * fix: featuresEnabled undefined * fix: add/activate newly received tokens * fix: NaN Values in Coins for a newly loaded Safe Was failing to set a default value for the `currencyRate` * fix: Settings fails to load if `owners` is not loaded into store Added a `Loader` until the required Safe's data is loaded into store. * fix: prefetch txs data When building the Txs list, we requested data for every tx what was translated into several RPC calls. Now by _batchRequesting_ all the information on beforehand, Safe's loading is a bit faster. * fix: prevent requesting safe, when there's no safe available in the store * enhancement: fetch tokens when loading safe By doing this, when loading a safe in the balance screen we will have tokens immediately loaded into the coins list * fix: load collectibles when switch to collectibles screen Collectibles weren't loaded when clicking menu link for a newly loaded safe. Now every switch to the collectible's screen will trigger a fetch for collectibles. * fix: fetch only if safe is ready Co-authored-by: fernandomg Co-authored-by: Mikhail Mikheev * Fix (#777) * fix: batchRequest params order * fix: execute decodeParams for all sendTokenTxs * fix: proper amount display for tx in TxTable * Uses formatAmount * Removes unused code Fixs params props safe address form * Fixs composeValidators Adds composeValidators for apps section * Makes composeValidatorsApps a wrapper * Moves composeValidatorsApps to managesApps.js * Desktop app (#745) * Set up electron app * Update dependencies * Update package.json * Added https support * Add support for Ledger * Updated certs * Added auto updates messages * Update auto-updater method * Update package.json * Added build resources * Update preload * Update Ledger method on mac * Update build * Merge with develop * Added support for Portis * Fix electron error and updater * Update auto updater * Fix dependencies * Merge with develop * Change auto update functionality * Edit package.json and added github actions * Updated github actions * Fixed Torus + Update github actions * Updated release.yml * Try only ubuntu * Update package.json * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * Updated safe-contracts * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * Updated deploy branch * Updated script Co-authored-by: Mati Dastugue Co-authored-by: Fernando Co-authored-by: nicolas Co-authored-by: Agustin Pane Co-authored-by: Mati Dastugue Co-authored-by: Agustín Longoni Co-authored-by: lukasschor Co-authored-by: David Albela Pérez <3659067+davidalbela@users.noreply.github.com> Co-authored-by: Uxio Fuentefria Co-authored-by: Mati Dastugue * Update CI Desktop script * Update CI script for windows Co-authored-by: Mikhail Mikheev Co-authored-by: Fernando Co-authored-by: Agustin Pane Co-authored-by: Mati Dastugue Co-authored-by: Agustín Longoni Co-authored-by: lukasschor Co-authored-by: David Albela Pérez <3659067+davidalbela@users.noreply.github.com> Co-authored-by: Uxio Fuentefria Co-authored-by: Mati Dastugue * Fix apps (#823) * v2.0.0 (#806) * 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 * (Fix) Adapt app to back-end changes (#736) * refactor: Set success status to `201` (CREATED) * refactor: return `null` when there's no latestTx * (Fix) Transaction not automatically executed (#716) * feature: action/reducer to UPDATE_SAFE_NONCE * refactor: when processing txs returned from backend, extract latest tx nonce value and store it in the safe's state * chore: update `yarn.lock` * refactor: `UPDATE_SAFE_THRESHOLD` and `UPDATE_SAFE_NONCE` discarded in favor of `UPDATE_SAFE` * refactor: use `SAFE_REDUCER_ID` constant * refactor: remove `updateSafeNonce` file * (Fix) Change the order of the upgrade methods lookup (#740) * fix: change the order of the upgrade methods lookup The `isUpgradeTransaction` method was looking for the methods in an wrong order (#599). The proper order was set in #610, but `isUpgradeTransaction` wasn't updated. * fix: contract upgrade version lookup * Feature: Use eth_sign for hardware wallets connected via onboard.js (#742) * Use eth_sign for hardware wallets * install onboard.js with fix from forked repo * rebuild yarn.lock to fix cached onboard * update bnc-onboard * update package json (#743) * (Fix) Properly decode threshold value in tx details (#749) * fix: Display new threshold value when changing its value There was a typo for the `changeThreshold` action fixes #746 * refactor: use a constant for safe methods names * fix: check for `decimals` method in transferredTokens (#748) Previously we were looking for `decimals` hash in the contract `code`. There are some contracts like USDC who happen to be behind a FiatTokenProxy, making it upgradable. By directly calling the `decimals()` method, we interact with the contract and can be sure that the `decimals()` method is present. fixes #678 * Bug #747: Don't use getLastTxNonce to fetch safe nonce (#750) * don't use getLastTxNonce to fetch safe nonce * fetch safe nonce in checkAndUpdateSafe * checkAndUpdateSafe refactor * remove nonce update logic from UPDATE_SAFE reducer * handle the case when localSafe returns undefined * handle the case when localSafe returns undefined in buildTransactionFrom * bump package json version to 1.9.4 * Issue-595: Apps config from Manifest (#715) * getting apps info from its manifest * Consume app info from manifest in Apps list, Transactions and Toast * fixes * navigate to TX Tab with an app makes a TX * (Fix) If backend returns `null` for addresses the Transaction ca… (#718) This tends to solve any possible issue that there may be in the tx execution for the `gasToken` and `refundReceiver` nullish values. fixes #573 * #751 fix - Replaces decimals from backend with decimals from blockchain (#755) * Replaces decimals from backend with decimals from blockchain * Removes fetching again token info from blockchain Fixs decimals cast, now we force to move from bignumber to number For data already wrong stored as string we remove it to force fetching again the decimals * Fixs missing symbol * Add description comment * Added Unilogin provider + support for legacy paths (#719) * Added unilogin provier + support for legacy path * Bump onboardjs version * fallback to displaying custom tx when we fail to fetch token info (#767) * Create release.yml Created script for building desktop app * Feature #322: Set safeTxGas for newly created transactions (#752) * Set safeTxGas for newly created transactions * extending estimation for nested calls WIP * messing up things to implement safeTxGas estimation * simplifying base gas calculations * remove eslint disable * messing things up to make things work * bring estimateData back * pass payload to requiredTxGas * pass esimateData to estimateDataGasCosts * remove console log * use batch requests to estimate safeTxGas * use const for txGasEstimation * check the response in request simultion * sidebar fix * remove for loop * Manage Apps (#765) * getting apps info from its manifest * Consume app info from manifest in Apps list, Transactions and Toast * fixes * navigate to TX Tab with an app makes a TX * ManageApps partial implementation * update safe-react-components * changes * apps validator * fix providedBy * TextField in addApp * fix checkbox error message * validation * adding app * Manage Apps * fix modal width * update package.json * update netlify url * fix modal widh * Set layout to Non-owners allowed error * some fixes * Apply suggestions from code review Co-Authored-By: lukasschor * review changes * fix condition * Legal Disclaimer * Better error message * update yarn.lock * Error message * review fixes * upgrade safe-react-components * show for all environments * Disclaimer changes * review changes * fix re-render * visual changes Co-authored-by: Agustín Longoni Co-authored-by: lukasschor * fix scroll and fix margin layout * Add region to travis CI develop (#787) Enable region for s3 provider to allow upload development environment to different S3 regions * Feature/travis ci s3 region (#789) * Add region to travis CI develop Enable region for s3 provider to allow upload development environment to different S3 regions * Enable region for staging s3 providers * fix error on Wrapper * Add gnosis wc bridge to onboard.js wallets options array (#790) * Rename incoming-transactions url to incoming-transfers * Feature #587 - App performance improvement (#738) * Refactor Balances to functional component Removes Balances props in Layout.jsx * Replaces selectors that were using safeParamAddressSelector with safeParamAddressFromStateSelector to avoid the bug of non-loaded safe when called Also exports extendedTransactionsSelector to let the components use it * Refactors Transactions.jsx, replaces transactions.tsx with txsTable.jsx Removes all unused props from transactions.jsx Makes all childs of txsTable.jsx fetch the props they need instead of sharing all of them even if they are not used * Adds new selectors: safeNameSelector, safeNeedsUpdateSelector, safeCurrentVersionSelector * Removes unused props from layout to settings.jsx Removed props from the settings.jsx childs, now they fetch the values they need directly from the store * Removes unused redux connect * Adds safeEthBalanceSelector * Removes all the props from layout to settings * Refactor root and layout, extracts checkForUpdate and componentDidMount to components Extracts header and tabs from Layout.jsx * Makes routes.jsx use selectors instead of connect to unify the code * Loads tabs components using react suspense * Fixs warning when trying to update root component within loadStore.jsx Replaces safe with safeAddress selector in layout.jsx to reduce the unnecessary rendering Fixs setState in container.jsx * Fixs checkForUpdates fetchTokenBalances Adds FetchTokens.jsx in balances Adds safeFeaturesEnabledSelector * Fixs load addressbook action * Replaces safe with owners in manage owners * Improves buildSafe promises calls Improves the loadStorage calls * Fixs error "Uncaught (in promise) TypeError: Cannot read property 'includes' of undefined" * Extracts LoadStore from outside the router component to avoid re-loading the store Adds react lazy for Coins and Collectible tabs * Reduce the polling rate for fetching transactions * Removes unused actions.js Removes unused selector props * Fixes owners column selector usage * Fixes processTransaction usage * Optimize how the transaction list within the transactions tab are loaded * Fix lint error * Fix edit addressbook entry * Fixs show send coins modal * feature: batchRequest for incoming transactions * Fixs race condition on loadStore Fixs check for updates address null validation * Adds ensureOnceAsync for getGnosisSafeInstanceAt Adds batch request for safe params * Removes unnecessary checkAndUpdateSafe from checkForUpdates, now the safe gets updated when a transaction arrives * Fixs ensureOnce/memoization * refactor: make a generic generateBatchRequest method Create a generic method to easily build web3 batch requests * refactor: use `generateBatchRequest` in `getTokensBalances` * Removes .toJS in edit entry * Removes web3 from sendTransactions Removes pascal case FetchTokens * Replaces /layout import * Replaces CheckForUpdates component with useCheckForUpdates hook * Makes FetchTokens a hook * Removes getSafeParamsBatch, now the safes gets the data using the generic generateBatchRequests * Replaces INITIAL_STATUS with INITIAL_STATE * Replaces regex Adds spaces before return * Adds wrapInSuspense * Runs prettier * Makes checkAndUpdateSafe use generateBatchRequests * Makes checkAndUpdateSafe use generateBatchRequests * Fixs check for updates with null address * Fixs transaction details getNameFromAddressBook * Fixes zIndex between cookies banner and transaction details * fix: cast returned values to number Original code was expecting a BN instance, now it's a plain string. * Fix replace owner name * Fix race condition with adbk load * Fixes replaces owner * Fixs apps * Moved hooks into own folder * Moved LoadStore to routes.js Refactors LoadStore as Hook Move LoadStore to hooks folder * Moves useLoadStore to safes/index * Revert loadStore place change * Fixes bug with fetchEtherBalance that causes updateSafe to be called * remove useLoadStore, add useAnalytics hook * remove React.memo from SafeView * Reverts removing useLoadStore in order to maintain the consistency of the code * rewrite useLoadStore in a more hook-y way, rename it to useLoadSafe * Removes unnecessary setSafeLoaded * Removes unnecessary safeLoaded * fix: Coins values and balances The app was retrieving ERC20 tokens information from 3 different endpoints. - One from `balance/` to have the list updated - another from `balance/usd` to have the values in USD - the last one from the blockchain, to update the balances This was all simplified to `balance/usd`. Also, added a `currencyRate` to be updated when the currency is modified. The value calculation happens on a component level, so when the `balanceUsd` value is modified, the value is properly reflected on the screen. Refactored `activateTokensByBalance` to `fetchSafeTokens`, as this was doing quite more than just _activating_ and also added the `currencyList` calculation in it, so everything is updated when `balance/usd` endpoint is requested. * fix: Balance screen Collectibles weren't loading when clicking on the link Also, refactored setState usage, to properly update current state * fix: featuresEnabled undefined * fix: add/activate newly received tokens * fix: NaN Values in Coins for a newly loaded Safe Was failing to set a default value for the `currencyRate` * fix: Settings fails to load if `owners` is not loaded into store Added a `Loader` until the required Safe's data is loaded into store. * fix: prefetch txs data When building the Txs list, we requested data for every tx what was translated into several RPC calls. Now by _batchRequesting_ all the information on beforehand, Safe's loading is a bit faster. * fix: prevent requesting safe, when there's no safe available in the store * enhancement: fetch tokens when loading safe By doing this, when loading a safe in the balance screen we will have tokens immediately loaded into the coins list * fix: load collectibles when switch to collectibles screen Collectibles weren't loaded when clicking menu link for a newly loaded safe. Now every switch to the collectible's screen will trigger a fetch for collectibles. * fix: fetch only if safe is ready Co-authored-by: fernandomg Co-authored-by: Mikhail Mikheev * Fix (#777) * fix: batchRequest params order * fix: execute decodeParams for all sendTokenTxs * fix: proper amount display for tx in TxTable * Uses formatAmount * Removes unused code Fixs params props safe address form * Fixs composeValidators Adds composeValidators for apps section * Makes composeValidatorsApps a wrapper * Moves composeValidatorsApps to managesApps.js * Desktop app (#745) * Set up electron app * Update dependencies * Update package.json * Added https support * Add support for Ledger * Updated certs * Added auto updates messages * Update auto-updater method * Update package.json * Added build resources * Update preload * Update Ledger method on mac * Update build * Merge with develop * Added support for Portis * Fix electron error and updater * Update auto updater * Fix dependencies * Merge with develop * Change auto update functionality * Edit package.json and added github actions * Updated github actions * Fixed Torus + Update github actions * Updated release.yml * Try only ubuntu * Update package.json * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * Updated safe-contracts * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * Updated deploy branch * Updated script Co-authored-by: Mati Dastugue Co-authored-by: Fernando Co-authored-by: nicolas Co-authored-by: Agustin Pane Co-authored-by: Mati Dastugue Co-authored-by: Agustín Longoni Co-authored-by: lukasschor Co-authored-by: David Albela Pérez <3659067+davidalbela@users.noreply.github.com> Co-authored-by: Uxio Fuentefria Co-authored-by: Mati Dastugue * Update CI Desktop script * Update CI script for windows * Development v2 fixes (#822) * 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 * (Fix) Adapt app to back-end changes (#736) * refactor: Set success status to `201` (CREATED) * refactor: return `null` when there's no latestTx * (Fix) Transaction not automatically executed (#716) * feature: action/reducer to UPDATE_SAFE_NONCE * refactor: when processing txs returned from backend, extract latest tx nonce value and store it in the safe's state * chore: update `yarn.lock` * refactor: `UPDATE_SAFE_THRESHOLD` and `UPDATE_SAFE_NONCE` discarded in favor of `UPDATE_SAFE` * refactor: use `SAFE_REDUCER_ID` constant * refactor: remove `updateSafeNonce` file * (Fix) Change the order of the upgrade methods lookup (#740) * fix: change the order of the upgrade methods lookup The `isUpgradeTransaction` method was looking for the methods in an wrong order (#599). The proper order was set in #610, but `isUpgradeTransaction` wasn't updated. * fix: contract upgrade version lookup * Feature: Use eth_sign for hardware wallets connected via onboard.js (#742) * Use eth_sign for hardware wallets * install onboard.js with fix from forked repo * rebuild yarn.lock to fix cached onboard * update bnc-onboard * update package json (#743) * (Fix) Properly decode threshold value in tx details (#749) * fix: Display new threshold value when changing its value There was a typo for the `changeThreshold` action fixes #746 * refactor: use a constant for safe methods names * fix: check for `decimals` method in transferredTokens (#748) Previously we were looking for `decimals` hash in the contract `code`. There are some contracts like USDC who happen to be behind a FiatTokenProxy, making it upgradable. By directly calling the `decimals()` method, we interact with the contract and can be sure that the `decimals()` method is present. fixes #678 * Bug #747: Don't use getLastTxNonce to fetch safe nonce (#750) * don't use getLastTxNonce to fetch safe nonce * fetch safe nonce in checkAndUpdateSafe * checkAndUpdateSafe refactor * remove nonce update logic from UPDATE_SAFE reducer * handle the case when localSafe returns undefined * handle the case when localSafe returns undefined in buildTransactionFrom * bump package json version to 1.9.4 * Issue-595: Apps config from Manifest (#715) * getting apps info from its manifest * Consume app info from manifest in Apps list, Transactions and Toast * fixes * navigate to TX Tab with an app makes a TX * (Fix) If backend returns `null` for addresses the Transaction ca… (#718) This tends to solve any possible issue that there may be in the tx execution for the `gasToken` and `refundReceiver` nullish values. fixes #573 * #751 fix - Replaces decimals from backend with decimals from blockchain (#755) * Replaces decimals from backend with decimals from blockchain * Removes fetching again token info from blockchain Fixs decimals cast, now we force to move from bignumber to number For data already wrong stored as string we remove it to force fetching again the decimals * Fixs missing symbol * Add description comment * Added Unilogin provider + support for legacy paths (#719) * Added unilogin provier + support for legacy path * Bump onboardjs version * fallback to displaying custom tx when we fail to fetch token info (#767) * Create release.yml Created script for building desktop app * Feature #322: Set safeTxGas for newly created transactions (#752) * Set safeTxGas for newly created transactions * extending estimation for nested calls WIP * messing up things to implement safeTxGas estimation * simplifying base gas calculations * remove eslint disable * messing things up to make things work * bring estimateData back * pass payload to requiredTxGas * pass esimateData to estimateDataGasCosts * remove console log * use batch requests to estimate safeTxGas * use const for txGasEstimation * check the response in request simultion * sidebar fix * remove for loop * Manage Apps (#765) * getting apps info from its manifest * Consume app info from manifest in Apps list, Transactions and Toast * fixes * navigate to TX Tab with an app makes a TX * ManageApps partial implementation * update safe-react-components * changes * apps validator * fix providedBy * TextField in addApp * fix checkbox error message * validation * adding app * Manage Apps * fix modal width * update package.json * update netlify url * fix modal widh * Set layout to Non-owners allowed error * some fixes * Apply suggestions from code review Co-Authored-By: lukasschor * review changes * fix condition * Legal Disclaimer * Better error message * update yarn.lock * Error message * review fixes * upgrade safe-react-components * show for all environments * Disclaimer changes * review changes * fix re-render * visual changes Co-authored-by: Agustín Longoni Co-authored-by: lukasschor * fix scroll and fix margin layout * Add region to travis CI develop (#787) Enable region for s3 provider to allow upload development environment to different S3 regions * Feature/travis ci s3 region (#789) * Add region to travis CI develop Enable region for s3 provider to allow upload development environment to different S3 regions * Enable region for staging s3 providers * fix error on Wrapper * Add gnosis wc bridge to onboard.js wallets options array (#790) * Rename incoming-transactions url to incoming-transfers * Feature #587 - App performance improvement (#738) * Refactor Balances to functional component Removes Balances props in Layout.jsx * Replaces selectors that were using safeParamAddressSelector with safeParamAddressFromStateSelector to avoid the bug of non-loaded safe when called Also exports extendedTransactionsSelector to let the components use it * Refactors Transactions.jsx, replaces transactions.tsx with txsTable.jsx Removes all unused props from transactions.jsx Makes all childs of txsTable.jsx fetch the props they need instead of sharing all of them even if they are not used * Adds new selectors: safeNameSelector, safeNeedsUpdateSelector, safeCurrentVersionSelector * Removes unused props from layout to settings.jsx Removed props from the settings.jsx childs, now they fetch the values they need directly from the store * Removes unused redux connect * Adds safeEthBalanceSelector * Removes all the props from layout to settings * Refactor root and layout, extracts checkForUpdate and componentDidMount to components Extracts header and tabs from Layout.jsx * Makes routes.jsx use selectors instead of connect to unify the code * Loads tabs components using react suspense * Fixs warning when trying to update root component within loadStore.jsx Replaces safe with safeAddress selector in layout.jsx to reduce the unnecessary rendering Fixs setState in container.jsx * Fixs checkForUpdates fetchTokenBalances Adds FetchTokens.jsx in balances Adds safeFeaturesEnabledSelector * Fixs load addressbook action * Replaces safe with owners in manage owners * Improves buildSafe promises calls Improves the loadStorage calls * Fixs error "Uncaught (in promise) TypeError: Cannot read property 'includes' of undefined" * Extracts LoadStore from outside the router component to avoid re-loading the store Adds react lazy for Coins and Collectible tabs * Reduce the polling rate for fetching transactions * Removes unused actions.js Removes unused selector props * Fixes owners column selector usage * Fixes processTransaction usage * Optimize how the transaction list within the transactions tab are loaded * Fix lint error * Fix edit addressbook entry * Fixs show send coins modal * feature: batchRequest for incoming transactions * Fixs race condition on loadStore Fixs check for updates address null validation * Adds ensureOnceAsync for getGnosisSafeInstanceAt Adds batch request for safe params * Removes unnecessary checkAndUpdateSafe from checkForUpdates, now the safe gets updated when a transaction arrives * Fixs ensureOnce/memoization * refactor: make a generic generateBatchRequest method Create a generic method to easily build web3 batch requests * refactor: use `generateBatchRequest` in `getTokensBalances` * Removes .toJS in edit entry * Removes web3 from sendTransactions Removes pascal case FetchTokens * Replaces /layout import * Replaces CheckForUpdates component with useCheckForUpdates hook * Makes FetchTokens a hook * Removes getSafeParamsBatch, now the safes gets the data using the generic generateBatchRequests * Replaces INITIAL_STATUS with INITIAL_STATE * Replaces regex Adds spaces before return * Adds wrapInSuspense * Runs prettier * Makes checkAndUpdateSafe use generateBatchRequests * Makes checkAndUpdateSafe use generateBatchRequests * Fixs check for updates with null address * Fixs transaction details getNameFromAddressBook * Fixes zIndex between cookies banner and transaction details * fix: cast returned values to number Original code was expecting a BN instance, now it's a plain string. * Fix replace owner name * Fix race condition with adbk load * Fixes replaces owner * Fixs apps * Moved hooks into own folder * Moved LoadStore to routes.js Refactors LoadStore as Hook Move LoadStore to hooks folder * Moves useLoadStore to safes/index * Revert loadStore place change * Fixes bug with fetchEtherBalance that causes updateSafe to be called * remove useLoadStore, add useAnalytics hook * remove React.memo from SafeView * Reverts removing useLoadStore in order to maintain the consistency of the code * rewrite useLoadStore in a more hook-y way, rename it to useLoadSafe * Removes unnecessary setSafeLoaded * Removes unnecessary safeLoaded * fix: Coins values and balances The app was retrieving ERC20 tokens information from 3 different endpoints. - One from `balance/` to have the list updated - another from `balance/usd` to have the values in USD - the last one from the blockchain, to update the balances This was all simplified to `balance/usd`. Also, added a `currencyRate` to be updated when the currency is modified. The value calculation happens on a component level, so when the `balanceUsd` value is modified, the value is properly reflected on the screen. Refactored `activateTokensByBalance` to `fetchSafeTokens`, as this was doing quite more than just _activating_ and also added the `currencyList` calculation in it, so everything is updated when `balance/usd` endpoint is requested. * fix: Balance screen Collectibles weren't loading when clicking on the link Also, refactored setState usage, to properly update current state * fix: featuresEnabled undefined * fix: add/activate newly received tokens * fix: NaN Values in Coins for a newly loaded Safe Was failing to set a default value for the `currencyRate` * fix: Settings fails to load if `owners` is not loaded into store Added a `Loader` until the required Safe's data is loaded into store. * fix: prefetch txs data When building the Txs list, we requested data for every tx what was translated into several RPC calls. Now by _batchRequesting_ all the information on beforehand, Safe's loading is a bit faster. * fix: prevent requesting safe, when there's no safe available in the store * enhancement: fetch tokens when loading safe By doing this, when loading a safe in the balance screen we will have tokens immediately loaded into the coins list * fix: load collectibles when switch to collectibles screen Collectibles weren't loaded when clicking menu link for a newly loaded safe. Now every switch to the collectible's screen will trigger a fetch for collectibles. * fix: fetch only if safe is ready Co-authored-by: fernandomg Co-authored-by: Mikhail Mikheev * Fix (#777) * fix: batchRequest params order * fix: execute decodeParams for all sendTokenTxs * fix: proper amount display for tx in TxTable * Uses formatAmount * Removes unused code Fixs params props safe address form * Fixs composeValidators Adds composeValidators for apps section * Makes composeValidatorsApps a wrapper * Moves composeValidatorsApps to managesApps.js * Desktop app (#745) * Set up electron app * Update dependencies * Update package.json * Added https support * Add support for Ledger * Updated certs * Added auto updates messages * Update auto-updater method * Update package.json * Added build resources * Update preload * Update Ledger method on mac * Update build * Merge with develop * Added support for Portis * Fix electron error and updater * Update auto updater * Fix dependencies * Merge with develop * Change auto update functionality * Edit package.json and added github actions * Updated github actions * Fixed Torus + Update github actions * Updated release.yml * Try only ubuntu * Update package.json * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * Updated safe-contracts * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * Updated deploy branch * Updated script Co-authored-by: Mati Dastugue * Update yarn script + SAFE_APPS env variable * Converts custom token address to checksum version (#793) * SafeTxGas calculation: Add check for openethereum/parity revert messages (#788) * add check for openethereum/parity revert messages * fix isEstimationSuccessful check * fix estimation check if revert msg is from openethereum * Issue 796 (#807) * consume gnosis componentes from npm * set safe-apps url from environment variable * fix apps padding and border radius * Apps updates * update disclaimer * fix Loader in TXList * Fix invalid origin Co-authored-by: Agustín Longoni * (Feature) Tx Table amount notations (#812) * Fix master conflicts (#819) * v2.0.0 (#806) * 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 * (Fix) Adapt app to back-end changes (#736) * refactor: Set success status to `201` (CREATED) * refactor: return `null` when there's no latestTx * (Fix) Transaction not automatically executed (#716) * feature: action/reducer to UPDATE_SAFE_NONCE * refactor: when processing txs returned from backend, extract latest tx nonce value and store it in the safe's state * chore: update `yarn.lock` * refactor: `UPDATE_SAFE_THRESHOLD` and `UPDATE_SAFE_NONCE` discarded in favor of `UPDATE_SAFE` * refactor: use `SAFE_REDUCER_ID` constant * refactor: remove `updateSafeNonce` file * (Fix) Change the order of the upgrade methods lookup (#740) * fix: change the order of the upgrade methods lookup The `isUpgradeTransaction` method was looking for the methods in an wrong order (#599). The proper order was set in #610, but `isUpgradeTransaction` wasn't updated. * fix: contract upgrade version lookup * Feature: Use eth_sign for hardware wallets connected via onboard.js (#742) * Use eth_sign for hardware wallets * install onboard.js with fix from forked repo * rebuild yarn.lock to fix cached onboard * update bnc-onboard * update package json (#743) * (Fix) Properly decode threshold value in tx details (#749) * fix: Display new threshold value when changing its value There was a typo for the `changeThreshold` action fixes #746 * refactor: use a constant for safe methods names * fix: check for `decimals` method in transferredTokens (#748) Previously we were looking for `decimals` hash in the contract `code`. There are some contracts like USDC who happen to be behind a FiatTokenProxy, making it upgradable. By directly calling the `decimals()` method, we interact with the contract and can be sure that the `decimals()` method is present. fixes #678 * Bug #747: Don't use getLastTxNonce to fetch safe nonce (#750) * don't use getLastTxNonce to fetch safe nonce * fetch safe nonce in checkAndUpdateSafe * checkAndUpdateSafe refactor * remove nonce update logic from UPDATE_SAFE reducer * handle the case when localSafe returns undefined * handle the case when localSafe returns undefined in buildTransactionFrom * bump package json version to 1.9.4 * Issue-595: Apps config from Manifest (#715) * getting apps info from its manifest * Consume app info from manifest in Apps list, Transactions and Toast * fixes * navigate to TX Tab with an app makes a TX * (Fix) If backend returns `null` for addresses the Transaction ca… (#718) This tends to solve any possible issue that there may be in the tx execution for the `gasToken` and `refundReceiver` nullish values. fixes #573 * #751 fix - Replaces decimals from backend with decimals from blockchain (#755) * Replaces decimals from backend with decimals from blockchain * Removes fetching again token info from blockchain Fixs decimals cast, now we force to move from bignumber to number For data already wrong stored as string we remove it to force fetching again the decimals * Fixs missing symbol * Add description comment * Added Unilogin provider + support for legacy paths (#719) * Added unilogin provier + support for legacy path * Bump onboardjs version * fallback to displaying custom tx when we fail to fetch token info (#767) * Create release.yml Created script for building desktop app * Feature #322: Set safeTxGas for newly created transactions (#752) * Set safeTxGas for newly created transactions * extending estimation for nested calls WIP * messing up things to implement safeTxGas estimation * simplifying base gas calculations * remove eslint disable * messing things up to make things work * bring estimateData back * pass payload to requiredTxGas * pass esimateData to estimateDataGasCosts * remove console log * use batch requests to estimate safeTxGas * use const for txGasEstimation * check the response in request simultion * sidebar fix * remove for loop * Manage Apps (#765) * getting apps info from its manifest * Consume app info from manifest in Apps list, Transactions and Toast * fixes * navigate to TX Tab with an app makes a TX * ManageApps partial implementation * update safe-react-components * changes * apps validator * fix providedBy * TextField in addApp * fix checkbox error message * validation * adding app * Manage Apps * fix modal width * update package.json * update netlify url * fix modal widh * Set layout to Non-owners allowed error * some fixes * Apply suggestions from code review Co-Authored-By: lukasschor * review changes * fix condition * Legal Disclaimer * Better error message * update yarn.lock * Error message * review fixes * upgrade safe-react-components * show for all environments * Disclaimer changes * review changes * fix re-render * visual changes Co-authored-by: Agustín Longoni Co-authored-by: lukasschor * fix scroll and fix margin layout * Add region to travis CI develop (#787) Enable region for s3 provider to allow upload development environment to different S3 regions * Feature/travis ci s3 region (#789) * Add region to travis CI develop Enable region for s3 provider to allow upload development environment to different S3 regions * Enable region for staging s3 providers * fix error on Wrapper * Add gnosis wc bridge to onboard.js wallets options array (#790) * Rename incoming-transactions url to incoming-transfers * Feature #587 - App performance improvement (#738) * Refactor Balances to functional component Removes Balances props in Layout.jsx * Replaces selectors that were using safeParamAddressSelector with safeParamAddressFromStateSelector to avoid the bug of non-loaded safe when called Also exports extendedTransactionsSelector to let the components use it * Refactors Transactions.jsx, replaces transactions.tsx with txsTable.jsx Removes all unused props from transactions.jsx Makes all childs of txsTable.jsx fetch the props they need instead of sharing all of them even if they are not used * Adds new selectors: safeNameSelector, safeNeedsUpdateSelector, safeCurrentVersionSelector * Removes unused props from layout to settings.jsx Removed props from the settings.jsx childs, now they fetch the values they need directly from the store * Removes unused redux connect * Adds safeEthBalanceSelector * Removes all the props from layout to settings * Refactor root and layout, extracts checkForUpdate and componentDidMount to components Extracts header and tabs from Layout.jsx * Makes routes.jsx use selectors instead of connect to unify the code * Loads tabs components using react suspense * Fixs warning when trying to update root component within loadStore.jsx Replaces safe with safeAddress selector in layout.jsx to reduce the unnecessary rendering Fixs setState in container.jsx * Fixs checkForUpdates fetchTokenBalances Adds FetchTokens.jsx in balances Adds safeFeaturesEnabledSelector * Fixs load addressbook action * Replaces safe with owners in manage owners * Improves buildSafe promises calls Improves the loadStorage calls * Fixs error "Uncaught (in promise) TypeError: Cannot read property 'includes' of undefined" * Extracts LoadStore from outside the router component to avoid re-loading the store Adds react lazy for Coins and Collectible tabs * Reduce the polling rate for fetching transactions * Removes unused actions.js Removes unused selector props * Fixes owners column selector usage * Fixes processTransaction usage * Optimize how the transaction list within the transactions tab are loaded * Fix lint error * Fix edit addressbook entry * Fixs show send coins modal * feature: batchRequest for incoming transactions * Fixs race condition on loadStore Fixs check for updates address null validation * Adds ensureOnceAsync for getGnosisSafeInstanceAt Adds batch request for safe params * Removes unnecessary checkAndUpdateSafe from checkForUpdates, now the safe gets updated when a transaction arrives * Fixs ensureOnce/memoization * refactor: make a generic generateBatchRequest method Create a generic method to easily build web3 batch requests * refactor: use `generateBatchRequest` in `getTokensBalances` * Removes .toJS in edit entry * Removes web3 from sendTransactions Removes pascal case FetchTokens * Replaces /layout import * Replaces CheckForUpdates component with useCheckForUpdates hook * Makes FetchTokens a hook * Removes getSafeParamsBatch, now the safes gets the data using the generic generateBatchRequests * Replaces INITIAL_STATUS with INITIAL_STATE * Replaces regex Adds spaces before return * Adds wrapInSuspense * Runs prettier * Makes checkAndUpdateSafe use generateBatchRequests * Makes checkAndUpdateSafe use generateBatchRequests * Fixs check for updates with null address * Fixs transaction details getNameFromAddressBook * Fixes zIndex between cookies banner and transaction details * fix: cast returned values to number Original code was expecting a BN instance, now it's a plain string. * Fix replace owner name * Fix race condition with adbk load * Fixes replaces owner * Fixs apps * Moved hooks into own folder * Moved LoadStore to routes.js Refactors LoadStore as Hook Move LoadStore to hooks folder * Moves useLoadStore to safes/index * Revert loadStore place change * Fixes bug with fetchEtherBalance that causes updateSafe to be called * remove useLoadStore, add useAnalytics hook * remove React.memo from SafeView * Reverts removing useLoadStore in order to maintain the consistency of the code * rewrite useLoadStore in a more hook-y way, rename it to useLoadSafe * Removes unnecessary setSafeLoaded * Removes unnecessary safeLoaded * fix: Coins values and balances The app was retrieving ERC20 tokens information from 3 different endpoints. - One from `balance/` to have the list updated - another from `balance/usd` to have the values in USD - the last one from the blockchain, to update the balances This was all simplified to `balance/usd`. Also, added a `currencyRate` to be updated when the currency is modified. The value calculation happens on a component level, so when the `balanceUsd` value is modified, the value is properly reflected on the screen. Refactored `activateTokensByBalance` to `fetchSafeTokens`, as this was doing quite more than just _activating_ and also added the `currencyList` calculation in it, so everything is updated when `balance/usd` endpoint is requested. * fix: Balance screen Collectibles weren't loading when clicking on the link Also, refactored setState usage, to properly update current state * fix: featuresEnabled undefined * fix: add/activate newly received tokens * fix: NaN Values in Coins for a newly loaded Safe Was failing to set a default value for the `currencyRate` * fix: Settings fails to load if `owners` is not loaded into store Added a `Loader` until the required Safe's data is loaded into store. * fix: prefetch txs data When building the Txs list, we requested data for every tx what was translated into several RPC calls. Now by _batchRequesting_ all the information on beforehand, Safe's loading is a bit faster. * fix: prevent requesting safe, when there's no safe available in the store * enhancement: fetch tokens when loading safe By doing this, when loading a safe in the balance screen we will have tokens immediately loaded into the coins list * fix: load collectibles when switch to collectibles screen Collectibles weren't loaded when clicking menu link for a newly loaded safe. Now every switch to the collectible's screen will trigger a fetch for collectibles. * fix: fetch only if safe is ready Co-authored-by: fernandomg Co-authored-by: Mikhail Mikheev * Fix (#777) * fix: batchRequest params order * fix: execute decodeParams for all sendTokenTxs * fix: proper amount display for tx in TxTable * Uses formatAmount * Removes unused code Fixs params props safe address form * Fixs composeValidators Adds composeValidators for apps section * Makes composeValidatorsApps a wrapper * Moves composeValidatorsApps to managesApps.js * Desktop app (#745) * Set up electron app * Update dependencies * Update package.json * Added https support * Add support for Ledger * Updated certs * Added auto updates messages * Update auto-updater method * Update package.json * Added build resources * Update preload * Update Ledger method on mac * Update build * Merge with develop * Added support for Portis * Fix electron error and updater * Update auto updater * Fix dependencies * Merge with develop * Change auto update functionality * Edit package.json and added github actions * Updated github actions * Fixed Torus + Update github actions * Updated release.yml * Try only ubuntu * Update package.json * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * Updated safe-contracts * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * v1.9.6 * Updated deploy branch * Updated script Co-authored-by: Mati Dastugue Co-authored-by: Fernando Co-authored-by: nicolas Co-authored-by: Agustin Pane Co-authored-by: Mati Dastugue Co-authored-by: Agustín Longoni Co-authored-by: lukasschor Co-authored-by: David Albela Pérez <3659067+davidalbela@users.noreply.github.com> Co-authored-by: Uxio Fuentefria Co-authored-by: Mati Dastugue * Update CI Desktop script * Update CI script for windows Co-authored-by: Mikhail Mikheev Co-authored-by: Fernando Co-authored-by: Agustin Pane Co-authored-by: Mati Dastugue Co-authored-by: Agustín Longoni Co-authored-by: lukasschor Co-authored-by: David Albela Pérez <3659067+davidalbela@users.noreply.github.com> Co-authored-by: Uxio Fuentefria Co-authored-by: Mati Dastugue Co-authored-by: Mikhail Mikheev Co-authored-by: Fernando Co-authored-by: Agustin Pane Co-authored-by: Mati Dastugue Co-authored-by: Agustín Longoni Co-authored-by: lukasschor Co-authored-by: David Albela Pérez <3659067+davidalbela@users.noreply.github.com> Co-authored-by: Uxio Fuentefria Co-authored-by: Mati Dastugue * Fix apps loader Co-authored-by: Mikhail Mikheev Co-authored-by: Fernando Co-authored-by: Agustin Pane Co-authored-by: Mati Dastugue Co-authored-by: Agustín Longoni Co-authored-by: lukasschor Co-authored-by: David Albela Pérez <3659067+davidalbela@users.noreply.github.com> Co-authored-by: Uxio Fuentefria Co-authored-by: Mati Dastugue Co-authored-by: Mikhail Mikheev Co-authored-by: Fernando Co-authored-by: Agustin Pane Co-authored-by: Mati Dastugue Co-authored-by: Agustín Longoni Co-authored-by: lukasschor Co-authored-by: David Albela Pérez <3659067+davidalbela@users.noreply.github.com> Co-authored-by: Uxio Fuentefria Co-authored-by: Mati Dastugue --- src/routes/safe/components/Apps/index.jsx | 3 +-- src/routes/safe/components/Apps/utils.js | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/routes/safe/components/Apps/index.jsx b/src/routes/safe/components/Apps/index.jsx index cda87ddf..258c4f5f 100644 --- a/src/routes/safe/components/Apps/index.jsx +++ b/src/routes/safe/components/Apps/index.jsx @@ -300,9 +300,8 @@ function Apps({ closeModal, closeSnackbar, enqueueSnackbar, openModal }: Props) const currentApp = list[index] const appInfo = await getAppInfoFromUrl(currentApp.url) - if (appInfo.error) { - throw Error() + throw Error(`There was a problem trying to load app ${currentApp.url}`) } appInfo.disabled = currentApp.disabled === undefined ? false : currentApp.disabled diff --git a/src/routes/safe/components/Apps/utils.js b/src/routes/safe/components/Apps/utils.js index dcd7dbe2..271ed738 100644 --- a/src/routes/safe/components/Apps/utils.js +++ b/src/routes/safe/components/Apps/utils.js @@ -20,7 +20,7 @@ export const getAppInfoFromOrigin = (origin: string) => { } export const getAppInfoFromUrl = async (appUrl: string) => { - let res = { id: undefined, url: cleanedUpAppUrl, name: 'unknown', iconUrl: appsIconSvg, error: true } + let res = { id: undefined, url: appUrl, name: 'unknown', iconUrl: appsIconSvg, error: true } if (!appUrl) { return res @@ -29,6 +29,7 @@ export const getAppInfoFromUrl = async (appUrl: string) => { let cleanedUpAppUrl = appUrl.trim() if (cleanedUpAppUrl.substr(-1) === '/') { cleanedUpAppUrl = cleanedUpAppUrl.substr(0, cleanedUpAppUrl.length - 1) + res.url = cleanedUpAppUrl } try {