From c8ae33288d0ad45717e7cb3a4d271c75eef3727c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Fri, 13 Sep 2019 11:28:40 +0200 Subject: [PATCH 01/50] Remove unused params --- .../Settings/ManageOwners/ReplaceOwnerModal/index.jsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.jsx b/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.jsx index 27705bf2..02b9037e 100644 --- a/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.jsx @@ -36,8 +36,6 @@ export const sendReplaceOwner = async ( values: Object, safeAddress: string, ownerAddressToRemove: string, - ownerNameToRemove: string, - ownersOld: List, openSnackbar: Function, createTransaction: Function, replaceSafeOwner: Function, @@ -109,8 +107,6 @@ const ReplaceOwner = ({ values, safeAddress, ownerAddress, - ownerName, - owners, openSnackbar, createTransaction, replaceSafeOwner, From 7e9f9881608f31037be2b95dc1b052f8c50690c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Fri, 13 Sep 2019 12:01:35 +0200 Subject: [PATCH 02/50] Fix error when a transaction is manually rejected in MM popup --- src/routes/safe/store/actions/createTransaction.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/safe/store/actions/createTransaction.js b/src/routes/safe/store/actions/createTransaction.js index 4d9359c5..7f60f96e 100644 --- a/src/routes/safe/store/actions/createTransaction.js +++ b/src/routes/safe/store/actions/createTransaction.js @@ -42,7 +42,7 @@ const createTransaction = ( openSnackbar(notifications.CREATED_MORE_CONFIRMATIONS_NEEDED, 'success') } } catch (err) { - openSnackbar(notifications.ERROR, '') + openSnackbar(notifications.ERROR, 'error') console.error(`Error while creating transaction: ${err}`) } From 83d8c190dfc6029ffd5be6bf7fae83c2eb3b5afd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Fri, 13 Sep 2019 12:14:03 +0200 Subject: [PATCH 03/50] Refactor executeTransaction to show notification after confirmation --- src/logic/safe/transactions/send.js | 56 ++++++++++--------- .../safe/store/actions/createTransaction.js | 4 +- 2 files changed, 33 insertions(+), 27 deletions(-) diff --git a/src/logic/safe/transactions/send.js b/src/logic/safe/transactions/send.js index 0381a7f5..8e560350 100644 --- a/src/logic/safe/transactions/send.js +++ b/src/logic/safe/transactions/send.js @@ -1,4 +1,5 @@ // @flow +import GnosisSafeSol from '@gnosis.pm/safe-contracts/build/contracts/GnosisSafe.json' import { getWeb3 } from '~/logic/wallets/getWeb3' import { getStandardTokenContract } from '~/logic/tokens/store/actions/fetchTokens' import { EMPTY_DATA } from '~/logic/wallets/ethTransactions' @@ -55,6 +56,7 @@ export const approveTransaction = async ( } export const executeTransaction = async ( + showNotification: Function, safeInstance: any, to: string, valueInWei: number | string, @@ -75,33 +77,37 @@ export const executeTransaction = async ( } try { - const receipt = await safeInstance.execTransaction( - to, - valueInWei, - data, - operation, - 0, - 0, - 0, - ZERO_ADDRESS, - ZERO_ADDRESS, - sigs, - { from: sender }, - ) + const web3 = getWeb3() + const contract = new web3.eth.Contract(GnosisSafeSol.abi, safeInstance.address) - await saveTxToHistory( - safeInstance, - to, - valueInWei, - data, - operation, - nonce, - receipt.tx, // tx hash, - sender, - TX_TYPE_EXECUTION, - ) + const transactionHash = await contract.methods + .execTransaction(to, valueInWei, data, operation, 0, 0, 0, ZERO_ADDRESS, ZERO_ADDRESS, sigs) + .send({ + from: sender, + }) + .once('transactionHash', (transactionHash) => { + showNotification() + }) + .on('error', (error) => { + console.log('Tx error:', error) + }) + .then(async (receipt) => { + await saveTxToHistory( + safeInstance, + to, + valueInWei, + data, + operation, + nonce, + receipt.transactionHash, + sender, + TX_TYPE_EXECUTION, + ) - return receipt + return receipt.transactionHash + }) + + return transactionHash } catch (error) { /* eslint-disable */ const executeDataUsedSignatures = safeInstance.contract.methods diff --git a/src/routes/safe/store/actions/createTransaction.js b/src/routes/safe/store/actions/createTransaction.js index 7f60f96e..c60a3e05 100644 --- a/src/routes/safe/store/actions/createTransaction.js +++ b/src/routes/safe/store/actions/createTransaction.js @@ -33,8 +33,8 @@ const createTransaction = ( let txHash try { if (isExecution) { - openSnackbar(notifications.BEFORE_EXECUTION_OR_CREATION, 'success') - txHash = await executeTransaction(safeInstance, to, valueInWei, txData, CALL, nonce, from) + const showNotification = () => openSnackbar(notifications.BEFORE_EXECUTION_OR_CREATION, 'success') + txHash = await executeTransaction(showNotification, safeInstance, to, valueInWei, txData, CALL, nonce, from) openSnackbar(notifications.AFTER_EXECUTION, 'success') } else { openSnackbar(notifications.BEFORE_EXECUTION_OR_CREATION, 'success') From 78b5fa2eff6857bd22ade893b39dcfafdf4b3c10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Fri, 13 Sep 2019 15:59:43 +0200 Subject: [PATCH 04/50] Refactor approveTransaction to show notification after confirmation --- src/logic/safe/transactions/send.js | 55 ++++++++++++++----- .../safe/store/actions/createTransaction.js | 4 +- .../safe/store/actions/processTransaction.js | 27 +++++++-- 3 files changed, 65 insertions(+), 21 deletions(-) diff --git a/src/logic/safe/transactions/send.js b/src/logic/safe/transactions/send.js index 8e560350..128f63f8 100644 --- a/src/logic/safe/transactions/send.js +++ b/src/logic/safe/transactions/send.js @@ -15,6 +15,7 @@ export const TX_TYPE_EXECUTION = 'execution' export const TX_TYPE_CONFIRMATION = 'confirmation' export const approveTransaction = async ( + showNotification: Function, safeInstance: any, to: string, valueInWei: number | string, @@ -23,7 +24,7 @@ export const approveTransaction = async ( nonce: number, sender: string, ) => { - const contractTxHash = await safeInstance.getTransactionHash( + const txHash = await safeInstance.getTransactionHash( to, valueInWei, data, @@ -38,21 +39,45 @@ export const approveTransaction = async ( from: sender, }, ) - const receipt = await safeInstance.approveHash(contractTxHash, { from: sender }) - await saveTxToHistory( - safeInstance, - to, - valueInWei, - data, - operation, - nonce, - receipt.tx, // tx hash, - sender, - TX_TYPE_CONFIRMATION, - ) + try { + const web3 = getWeb3() + const contract = new web3.eth.Contract(GnosisSafeSol.abi, safeInstance.address) - return receipt + const transactionHash = await contract.methods.approveHash(txHash) + .send({ + from: sender, + }).once('transactionHash', () => { + showNotification() + }) + .on('error', (error) => { + console.log('Tx error:', error) + }) + .then(async (receipt) => { + await saveTxToHistory( + safeInstance, + to, + valueInWei, + data, + operation, + nonce, + receipt.transactionHash, + sender, + TX_TYPE_CONFIRMATION, + ) + + return receipt.transactionHash + }) + + return transactionHash + } catch (error) { + /* eslint-disable */ + const executeData = safeInstance.contract.methods.approveHash(txHash).encodeABI() + const errMsg = await getErrorMessage(safeInstance.address, 0, executeData, sender) + console.log(`Error executing the TX: ${errMsg}`) + + throw error + } } export const executeTransaction = async ( @@ -85,7 +110,7 @@ export const executeTransaction = async ( .send({ from: sender, }) - .once('transactionHash', (transactionHash) => { + .once('transactionHash', () => { showNotification() }) .on('error', (error) => { diff --git a/src/routes/safe/store/actions/createTransaction.js b/src/routes/safe/store/actions/createTransaction.js index c60a3e05..ad14b901 100644 --- a/src/routes/safe/store/actions/createTransaction.js +++ b/src/routes/safe/store/actions/createTransaction.js @@ -37,8 +37,8 @@ const createTransaction = ( txHash = await executeTransaction(showNotification, safeInstance, to, valueInWei, txData, CALL, nonce, from) openSnackbar(notifications.AFTER_EXECUTION, 'success') } else { - openSnackbar(notifications.BEFORE_EXECUTION_OR_CREATION, 'success') - txHash = await approveTransaction(safeInstance, to, valueInWei, txData, CALL, nonce, from) + const showNotification = () => openSnackbar(notifications.BEFORE_EXECUTION_OR_CREATION, 'success') + txHash = await approveTransaction(showNotification, safeInstance, to, valueInWei, txData, CALL, nonce, from) openSnackbar(notifications.CREATED_MORE_CONFIRMATIONS_NEEDED, 'success') } } catch (err) { diff --git a/src/routes/safe/store/actions/processTransaction.js b/src/routes/safe/store/actions/processTransaction.js index c30fd27c..1a077488 100644 --- a/src/routes/safe/store/actions/processTransaction.js +++ b/src/routes/safe/store/actions/processTransaction.js @@ -46,12 +46,31 @@ const processTransaction = ( let txHash if (shouldExecute) { - openSnackbar('Transaction has been submitted', 'success') - txHash = await executeTransaction(safeInstance, tx.recipient, tx.value, tx.data, CALL, nonce, from, sigs) + const showNotification = () => openSnackbar('Transaction has been submitted', 'success') + txHash = await executeTransaction( + showNotification, + safeInstance, + tx.recipient, + tx.value, + tx.data, + CALL, + nonce, + from, + sigs, + ) openSnackbar('Transaction has been confirmed', 'success') } else { - openSnackbar('Approval transaction has been submitted', 'success') - txHash = await approveTransaction(safeInstance, tx.recipient, tx.value, tx.data, CALL, nonce, from) + const showNotification = () => openSnackbar('Approval transaction has been submitted', 'success') + txHash = await approveTransaction( + showNotification, + safeInstance, + tx.recipient, + tx.value, + tx.data, + CALL, + nonce, + from, + ) openSnackbar('Approval transaction has been confirmed', 'success') } From ca704f7b47d34886eb34c31a746355576ca59f84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Fri, 13 Sep 2019 18:00:33 +0200 Subject: [PATCH 05/50] Display value in custom transactions detail in transaction list --- .../ExpandedTx/TxDescription/index.jsx | 26 ++++++++++++++++--- .../ExpandedTx/TxDescription/utils.js | 8 +++--- 2 files changed, 27 insertions(+), 7 deletions(-) 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 b4123640..70fbfe14 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/index.jsx +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/index.jsx @@ -13,7 +13,8 @@ export const TRANSACTIONS_DESC_ADD_OWNER_TEST_ID = 'tx-description-add-owner' export const TRANSACTIONS_DESC_REMOVE_OWNER_TEST_ID = 'tx-description-remove-owner' export const TRANSACTIONS_DESC_CHANGE_THRESHOLD_TEST_ID = 'tx-description-change-threshold' export const TRANSACTIONS_DESC_SEND_TEST_ID = 'tx-description-send' -export const TRANSACTIONS_DESC_CUSTOM_TEST_ID = 'tx-description-custom' +export const TRANSACTIONS_DESC_CUSTOM_VALUE_TEST_ID = 'tx-description-custom-value' +export const TRANSACTIONS_DESC_CUSTOM_DATA_TEST_ID = 'tx-description-custom-data' export const styles = () => ({ txDataContainer: { @@ -42,6 +43,8 @@ type DescriptionDescProps = { } type CustomDescProps = { + value: string, + recipient: string, data: String, classes: Obeject, } @@ -88,9 +91,24 @@ const SettingsDescription = ({ removedOwner, addedOwner, newThreshold }: Descrip ) -const CustomDescription = ({ data, classes }: CustomDescProps) => ( +const CustomDescription = ({ + data, value = 0, recipient, classes, +}: CustomDescProps) => ( <> - + + + Send + {' '} + {value} + {' '} + ETH + {' '} + to: + +
+ +
+ Data (hex encoded):
{data} @@ -109,7 +127,7 @@ const TxDescription = ({ tx, classes }: Props) => { )} {customTx && ( - + )} {!cancellationTx && !modifySettingsTx && !customTx && ( diff --git a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/utils.js b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/utils.js index affddad6..a55c986a 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/utils.js +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/utils.js @@ -23,6 +23,11 @@ export const getTxData = (tx: Transaction): DecodedTxData => { if (tx.isTokenTransfer && tx.decodedParams) { txData.recipient = tx.decodedParams.recipient txData.value = fromWei(toBN(tx.decodedParams.value), 'ether') + } else if (tx.customTx) { + txData.recipient = tx.recipient + txData.value = fromWei(toBN(tx.value), 'ether') + txData.data = tx.data + txData.customTx = true } else if (Number(tx.value) > 0) { txData.recipient = tx.recipient txData.value = fromWei(toBN(tx.value), 'ether') @@ -49,9 +54,6 @@ export const getTxData = (tx: Transaction): DecodedTxData => { } } else if (tx.cancellationTx) { txData.cancellationTx = true - } else if (tx.customTx) { - txData.data = tx.data - txData.customTx = true } return txData From aa1327c5af0bcf5eacc416a41bfd15ea3fb87e7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Mon, 16 Sep 2019 09:27:56 +0200 Subject: [PATCH 06/50] Update provider design --- src/components/Header/component/Layout.jsx | 1 - src/components/Header/component/Provider.jsx | 6 +++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/components/Header/component/Layout.jsx b/src/components/Header/component/Layout.jsx index 877647ea..c1fee33c 100644 --- a/src/components/Header/component/Layout.jsx +++ b/src/components/Header/component/Layout.jsx @@ -63,7 +63,6 @@ const Layout = openHoc(({ - {(providerRef) => ( diff --git a/src/components/Header/component/Provider.jsx b/src/components/Header/component/Provider.jsx index dda09c76..466200ec 100644 --- a/src/components/Header/component/Provider.jsx +++ b/src/components/Header/component/Provider.jsx @@ -5,6 +5,7 @@ import IconButton from '@material-ui/core/IconButton' import ExpandLess from '@material-ui/icons/ExpandLess' import ExpandMore from '@material-ui/icons/ExpandMore' import Col from '~/components/layout/Col' +import Divider from '~/components/layout/Divider' import { type Open } from '~/components/hoc/OpenHoc' import { sm, md } from '~/theme/variables' @@ -20,7 +21,8 @@ const styles = () => ({ height: '100%', display: 'flex', alignItems: 'center', - flexBasis: '250px', + flexBasis: '280px', + marginRight: '20px', }, provider: { padding: `${sm} ${md}`, @@ -54,12 +56,14 @@ class Provider extends React.Component { return ( <>
+ {info} {open ? : } +
{children(this.myRef)} From edfece39f9441334f6d9d2006433e0bc04fc282f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Mon, 16 Sep 2019 09:48:15 +0200 Subject: [PATCH 07/50] Remove styles error when opening the provider --- src/components/Header/component/Layout.jsx | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/components/Header/component/Layout.jsx b/src/components/Header/component/Layout.jsx index c1fee33c..9ce1e149 100644 --- a/src/components/Header/component/Layout.jsx +++ b/src/components/Header/component/Layout.jsx @@ -32,7 +32,7 @@ const styles = () => ({ padding: 0, boxShadow: '0 0 10px 0 rgba(33, 48, 77, 0.1)', minWidth: '280px', - left: '4px', + borderRadius: '8px', }, summary: { borderBottom: `solid 2px ${border}`, @@ -68,11 +68,13 @@ const Layout = openHoc(({ {({ TransitionProps }) => ( - - - {providerDetails} - - + <> + + + {providerDetails} + + + )} From d7eb196537735191adb74586c88b158cf47a3b86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Mon, 16 Sep 2019 10:52:21 +0200 Subject: [PATCH 08/50] Add styles to header --- src/components/Header/component/Layout.jsx | 4 +++- src/components/Header/component/Provider.jsx | 2 +- .../Header/component/ProviderDetails/UserDetails.jsx | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/components/Header/component/Layout.jsx b/src/components/Header/component/Layout.jsx index 9ce1e149..90af595a 100644 --- a/src/components/Header/component/Layout.jsx +++ b/src/components/Header/component/Layout.jsx @@ -33,6 +33,7 @@ const styles = () => ({ boxShadow: '0 0 10px 0 rgba(33, 48, 77, 0.1)', minWidth: '280px', borderRadius: '8px', + marginTop: '12px', }, summary: { borderBottom: `solid 2px ${border}`, @@ -41,6 +42,7 @@ const styles = () => ({ boxShadow: '0 2px 4px 0 rgba(212, 212, 211, 0.59)', backgroundColor: 'white', zIndex: 1301, + boxShadow: '0 2px 4px 0 rgba(212, 212, 211, 0.59)', }, logo: { padding: `${sm} ${md}`, @@ -65,7 +67,7 @@ const Layout = openHoc(({ {(providerRef) => ( - + {({ TransitionProps }) => ( <> diff --git a/src/components/Header/component/Provider.jsx b/src/components/Header/component/Provider.jsx index 466200ec..272283fb 100644 --- a/src/components/Header/component/Provider.jsx +++ b/src/components/Header/component/Provider.jsx @@ -21,7 +21,7 @@ const styles = () => ({ height: '100%', display: 'flex', alignItems: 'center', - flexBasis: '280px', + flexBasis: '284px', marginRight: '20px', }, provider: { diff --git a/src/components/Header/component/ProviderDetails/UserDetails.jsx b/src/components/Header/component/ProviderDetails/UserDetails.jsx index 1bdd6027..0c315325 100644 --- a/src/components/Header/component/ProviderDetails/UserDetails.jsx +++ b/src/components/Header/component/ProviderDetails/UserDetails.jsx @@ -143,7 +143,7 @@ const UserDetails = ({ - Client + Wallet {provider === 'safe' From f0e22db699d3970b2bd57cba2f611bb6c25d9a9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Mon, 16 Sep 2019 12:57:29 +0200 Subject: [PATCH 09/50] Update dependencies and install notistack --- package.json | 31 ++++----- yarn.lock | 182 +++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 177 insertions(+), 36 deletions(-) diff --git a/package.json b/package.json index 828bf019..13e9f7fd 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "immortal-db": "^1.0.2", "immutable": "^4.0.0-rc.9", "material-ui-search-bar": "^1.0.0-beta.13", + "notistack": "^0.9.0", "optimize-css-assets-webpack-plugin": "5.0.3", "qrcode.react": "^0.9.3", "react": "16.9.0", @@ -58,8 +59,8 @@ "react-router-dom": "^5.0.1", "recompose": "^0.30.0", "redux": "4.0.4", - "redux-actions": "^2.3.0", - "redux-thunk": "^2.2.0", + "redux-actions": "^2.6.5", + "redux-thunk": "^2.3.0", "reselect": "^4.0.0", "web3": "1.2.1" }, @@ -71,17 +72,17 @@ "@babel/plugin-proposal-do-expressions": "7.6.0", "@babel/plugin-proposal-export-default-from": "7.5.2", "@babel/plugin-proposal-export-namespace-from": "7.5.2", - "@babel/plugin-proposal-function-bind": "^7.0.0", + "@babel/plugin-proposal-function-bind": "^7.2.0", "@babel/plugin-proposal-function-sent": "7.5.0", - "@babel/plugin-proposal-json-strings": "^7.0.0", - "@babel/plugin-proposal-logical-assignment-operators": "^7.0.0", + "@babel/plugin-proposal-json-strings": "^7.2.0", + "@babel/plugin-proposal-logical-assignment-operators": "^7.2.0", "@babel/plugin-proposal-nullish-coalescing-operator": "7.4.4", - "@babel/plugin-proposal-numeric-separator": "^7.0.0", + "@babel/plugin-proposal-numeric-separator": "^7.2.0", "@babel/plugin-proposal-optional-chaining": "7.6.0", "@babel/plugin-proposal-pipeline-operator": "7.5.0", - "@babel/plugin-proposal-throw-expressions": "^7.0.0", - "@babel/plugin-syntax-dynamic-import": "^7.0.0", - "@babel/plugin-syntax-import-meta": "^7.0.0", + "@babel/plugin-proposal-throw-expressions": "^7.2.0", + "@babel/plugin-syntax-dynamic-import": "^7.2.0", + "@babel/plugin-syntax-import-meta": "^7.2.0", "@babel/plugin-transform-member-expression-literals": "^7.2.0", "@babel/plugin-transform-property-literals": "^7.2.0", "@babel/polyfill": "7.6.0", @@ -99,13 +100,13 @@ "babel-eslint": "10.0.3", "babel-jest": "24.9.0", "babel-loader": "8.0.6", - "babel-plugin-dynamic-import-node": "^2.2.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", - "classnames": "^2.2.5", + "classnames": "^2.2.6", "css-loader": "3.2.0", - "detect-port": "^1.2.2", - "eslint": "5.16.0", + "detect-port": "^1.3.0", + "eslint": "6.4.0", "eslint-config-airbnb": "18.0.1", "eslint-plugin-flowtype": "4.3.0", "eslint-plugin-import": "2.18.2", @@ -118,7 +119,7 @@ "flow-bin": "0.108.0", "fs-extra": "8.1.0", "html-loader": "^0.5.5", - "html-webpack-plugin": "^3.0.4", + "html-webpack-plugin": "^3.2.0", "jest": "24.9.0", "jest-dom": "4.0.0", "json-loader": "^0.5.7", @@ -130,7 +131,7 @@ "prettier-eslint-cli": "5.0.0", "run-with-testrpc": "0.3.1", "storybook-host": "5.1.0", - "storybook-router": "^0.3.3", + "storybook-router": "^0.3.4", "style-loader": "1.0.0", "truffle": "5.0.37", "truffle-contract": "4.0.31", diff --git a/yarn.lock b/yarn.lock index 6b44d191..f8477bd9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -414,7 +414,7 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-export-namespace-from" "^7.2.0" -"@babel/plugin-proposal-function-bind@^7.0.0": +"@babel/plugin-proposal-function-bind@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-function-bind/-/plugin-proposal-function-bind-7.2.0.tgz#94dc2cdc505cafc4e225c0014335a01648056bf7" integrity sha512-qOFJ/eX1Is78sywwTxDcsntLOdb5ZlHVVqUz5xznq8ldAfOVIyZzp1JE2rzHnaksZIhrqMrwIpQL/qcEprnVbw== @@ -431,7 +431,7 @@ "@babel/helper-wrap-function" "^7.2.0" "@babel/plugin-syntax-function-sent" "^7.2.0" -"@babel/plugin-proposal-json-strings@^7.0.0", "@babel/plugin-proposal-json-strings@^7.2.0": +"@babel/plugin-proposal-json-strings@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz#568ecc446c6148ae6b267f02551130891e29f317" integrity sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg== @@ -439,7 +439,7 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-json-strings" "^7.2.0" -"@babel/plugin-proposal-logical-assignment-operators@^7.0.0": +"@babel/plugin-proposal-logical-assignment-operators@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.2.0.tgz#8a5cea6c42a7c87446959e02fff5fad012c56f57" integrity sha512-0w797xwdPXKk0m3Js74hDi0mCTZplIu93MOSfb1ZLd/XFe3abWypx1QknVk0J+ohnsjYpvjH4Gwfo2i3RicB6Q== @@ -455,7 +455,7 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.2.0" -"@babel/plugin-proposal-numeric-separator@^7.0.0": +"@babel/plugin-proposal-numeric-separator@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.2.0.tgz#646854daf4cd22fd6733f6076013a936310443ac" integrity sha512-DohMOGDrZiMKS7LthjUZNNcWl8TAf5BZDwZAH4wpm55FuJTHgfqPGdibg7rZDmont/8Yg0zA03IgT6XLeP+4sg== @@ -503,7 +503,7 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-pipeline-operator" "^7.5.0" -"@babel/plugin-proposal-throw-expressions@^7.0.0": +"@babel/plugin-proposal-throw-expressions@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-throw-expressions/-/plugin-proposal-throw-expressions-7.2.0.tgz#2d9e452d370f139000e51db65d0a85dc60c64739" integrity sha512-adsydM8DQF4i5DLNO4ySAU5VtHTPewOtNBV3u7F4lNMPADFF9bWQ+iDtUUe8+033cYCUz+bFlQdXQJmJOwoLpw== @@ -541,7 +541,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-syntax-dynamic-import@7.2.0", "@babel/plugin-syntax-dynamic-import@^7.0.0", "@babel/plugin-syntax-dynamic-import@^7.2.0": +"@babel/plugin-syntax-dynamic-import@7.2.0", "@babel/plugin-syntax-dynamic-import@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz#69c159ffaf4998122161ad8ebc5e6d1f55df8612" integrity sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w== @@ -583,7 +583,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-syntax-import-meta@^7.0.0": +"@babel/plugin-syntax-import-meta@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.2.0.tgz#2333ef4b875553a3bcd1e93f8ebc09f5b9213a40" integrity sha512-Hq6kFSZD7+PHkmBN8bCpHR6J8QEoCuEV/B38AIQscYjgMZkGlXB7cHNFzP5jR4RCh5545yP1ujHdmO7hAgKtBA== @@ -1223,7 +1223,7 @@ js-levenshtein "^1.1.3" semver "^5.5.0" -"@babel/preset-flow@^7.0.0", "@babel/preset-flow@^7.0.0-beta.40": +"@babel/preset-flow@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/preset-flow/-/preset-flow-7.0.0.tgz#afd764835d9535ec63d8c7d4caf1c06457263da2" integrity sha512-bJOHrYOPqJZCkPVbG1Lot2r5OSsB+iUOaxiHdlOeB1yPWS6evswVHwvkDLZ54WTaTRIk89ds0iHmGZSnxlPejQ== @@ -1231,7 +1231,7 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-flow-strip-types" "^7.0.0" -"@babel/preset-react@7.0.0", "@babel/preset-react@^7.0.0", "@babel/preset-react@^7.0.0-beta.40": +"@babel/preset-react@7.0.0", "@babel/preset-react@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.0.0.tgz#e86b4b3d99433c7b3e9e91747e2653958bc6b3c0" integrity sha512-oayxyPS4Zj+hF6Et11BwuBkmpgT/zMxyuZgFrMeZID6Hdh3dGlk4sHCAhdBCpuCKW2ppBfl2uCCetlrUIJRY3w== @@ -1425,6 +1425,13 @@ dependencies: "@emotion/memoize" "0.7.2" +"@emotion/is-prop-valid@0.8.3": + version "0.8.3" + resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.3.tgz#cbe62ddbea08aa022cdf72da3971570a33190d29" + integrity sha512-We7VBiltAJ70KQA0dWkdPMXnYoizlxOXpvtjmu5/MBnExd+u0PGgV27WCYanmLAbCwAU30Le/xA0CQs/F/Otig== + dependencies: + "@emotion/memoize" "0.7.3" + "@emotion/memoize@0.7.2": version "0.7.2" resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.2.tgz#7f4c71b7654068dfcccad29553520f984cc66b30" @@ -1513,6 +1520,11 @@ resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.3.tgz#dfa0c92efe44a1d1a7974fb49ffeb40ef2da5a27" integrity sha512-zVgvPwGK7c1aVdUVc9Qv7SqepOGRDrqCw7KZPSZziWGxSlbII3gmvGLPzLX4d0n0BMbamBacUrN22zOMyFFEkQ== +"@emotion/weak-memoize@0.2.4": + version "0.2.4" + resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.4.tgz#622a72bebd1e3f48d921563b4b60a762295a81fc" + integrity sha512-6PYY5DVdAY1ifaQW6XYTnOMihmBVT27elqSjEoodchsGjzYlEsTQMcEhSud99kVawatyTZRTiVkJ/c6lwbQ7nA== + "@gnosis.pm/safe-contracts@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@gnosis.pm/safe-contracts/-/safe-contracts-1.0.0.tgz#2b562b1e23a0da1047a9f38ef71a70f811e75dd9" @@ -1860,7 +1872,7 @@ resolved "https://registry.yarnpkg.com/@redux-saga/types/-/types-1.0.2.tgz#1d94f02800b094753f9271c206a26c2a06ca14ee" integrity sha512-8/qcMh15507AnXJ3lBeuhsdFwnWQqnp68EpUuHlYPixJ5vjVmls7/Jq48cnUlrZI8Jd9U1jkhfCl0gaT5KMgVw== -"@sambego/storybook-state@^1.0.7": +"@sambego/storybook-state@^1.3.6": version "1.3.6" resolved "https://registry.yarnpkg.com/@sambego/storybook-state/-/storybook-state-1.3.6.tgz#9a6511095d200b8ab2d6bc39def81c90312dd420" integrity sha512-bTUE1ZTtI9ICyqz6l5gtUfo0/W77fPP7KOAd/HI1jM7m1Jxjxs1k1Qbcrqmxg1vaHemlXVkvxVCZf8BT9RzxGw== @@ -2991,6 +3003,11 @@ acorn-jsx@^5.0.0: resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.1.tgz#32a064fd925429216a09b141102bfdd185fae40e" integrity sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg== +acorn-jsx@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.2.tgz#84b68ea44b373c4f8686023a551f61a21b7c4a4f" + integrity sha512-tiNTrP1MP0QrChmD2DdupCr6HWSFeKVw5d/dHTu4Y7rkAkRhU/Dt7dphAfIUyxtHpl/eBVip5uTNSpQJHylpAw== + acorn-walk@^6.0.1, acorn-walk@^6.1.1: version "6.2.0" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c" @@ -3016,6 +3033,11 @@ acorn@^6.0.1, acorn@^6.0.7, acorn@^6.2.0, acorn@^6.2.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.2.1.tgz#3ed8422d6dec09e6121cc7a843ca86a330a86b51" integrity sha512-JD0xT5FCRDNyjDda3Lrg/IxFscp9q4tiYtxE1/nOzlKCk7hIRuYjhq1kCNkbPjMRMZuFq20HNQn1I9k8Oj0E+Q== +acorn@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.0.0.tgz#26b8d1cd9a9b700350b71c0905546f64d1284e7a" + integrity sha512-PaF/MduxijYYt7unVGRuds1vBC9bFxbNf+VWqhOClfdgy7RlVkQqt610ig1/yxTgsDIfW1cWDel5EBbOy3jdtQ== + address@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/address/-/address-1.0.3.tgz#b5f50631f8d6cec8bd20c963963afb55e06cbce9" @@ -3869,7 +3891,7 @@ babel-plugin-dynamic-import-node@2.2.0: dependencies: object.assign "^4.1.0" -babel-plugin-dynamic-import-node@^2.2.0, babel-plugin-dynamic-import-node@^2.3.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== @@ -5466,7 +5488,7 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -classnames@^2.2.5: +classnames@^2.2.5, classnames@^2.2.6: version "2.2.6" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== @@ -6692,7 +6714,7 @@ detect-port-alt@1.1.6: address "^1.0.1" debug "^2.6.0" -detect-port@^1.2.2, detect-port@^1.3.0: +detect-port@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.3.0.tgz#d9c40e9accadd4df5cac6a782aefd014d573d1f1" integrity sha512-E+B1gzkl2gqxt1IhUzwjrxBKRqx1UzC3WLONHinn8S3T6lwV/agVCyitiFOsGJ/eYuEUBvD71MZHy3Pv1G9doQ== @@ -7327,6 +7349,14 @@ eslint-scope@^4.0.0, eslint-scope@^4.0.3: esrecurse "^4.1.0" estraverse "^4.1.1" +eslint-scope@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9" + integrity sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + eslint-utils@^1.3.1: version "1.4.0" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.0.tgz#e2c3c8dba768425f897cf0f9e51fe2e241485d4c" @@ -7334,12 +7364,67 @@ eslint-utils@^1.3.1: dependencies: eslint-visitor-keys "^1.0.0" +eslint-utils@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.2.tgz#166a5180ef6ab7eb462f162fd0e6f2463d7309ab" + integrity sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q== + dependencies: + eslint-visitor-keys "^1.0.0" + eslint-visitor-keys@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" integrity sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ== -eslint@5.16.0, eslint@^5.0.0, eslint@^5.5.0: +eslint-visitor-keys@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" + integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== + +eslint@6.4.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.4.0.tgz#5aa9227c3fbe921982b2eda94ba0d7fae858611a" + integrity sha512-WTVEzK3lSFoXUovDHEbkJqCVPEPwbhCq4trDktNI6ygs7aO41d4cDT0JFAT5MivzZeVLWlg7vHL+bgrQv/t3vA== + dependencies: + "@babel/code-frame" "^7.0.0" + ajv "^6.10.0" + chalk "^2.1.0" + cross-spawn "^6.0.5" + debug "^4.0.1" + doctrine "^3.0.0" + eslint-scope "^5.0.0" + eslint-utils "^1.4.2" + eslint-visitor-keys "^1.1.0" + espree "^6.1.1" + esquery "^1.0.1" + esutils "^2.0.2" + file-entry-cache "^5.0.1" + functional-red-black-tree "^1.0.1" + glob-parent "^5.0.0" + globals "^11.7.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + inquirer "^6.4.1" + is-glob "^4.0.0" + js-yaml "^3.13.1" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.3.0" + lodash "^4.17.14" + minimatch "^3.0.4" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + optionator "^0.8.2" + progress "^2.0.0" + regexpp "^2.0.1" + semver "^6.1.2" + strip-ansi "^5.2.0" + strip-json-comments "^3.0.1" + table "^5.2.3" + text-table "^0.2.0" + v8-compile-cache "^2.0.3" + +eslint@^5.0.0, eslint@^5.5.0: version "5.16.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea" integrity sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg== @@ -7398,6 +7483,15 @@ espree@^5.0.1: acorn-jsx "^5.0.0" eslint-visitor-keys "^1.0.0" +espree@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-6.1.1.tgz#7f80e5f7257fc47db450022d723e356daeb1e5de" + integrity sha512-EYbr8XZUhWbYCqQRW0duU5LxzL5bETN6AjKBGy1302qqzPaCH10QbRg3Wvco79Z8x9WbiE8HYB4e75xl6qUYvQ== + dependencies: + acorn "^7.0.0" + acorn-jsx "^5.0.2" + eslint-visitor-keys "^1.1.0" + esprima@^3.1.3, esprima@~3.1.0: version "3.1.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" @@ -8982,6 +9076,13 @@ glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" +glob-parent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.0.0.tgz#1dc99f0f39b006d3e92c2c284068382f0c20e954" + integrity sha512-Z2RwiujPRGluePM6j699ktJYxmPpJKCfpGA13jz2hmFZC7gKetzrWvg5KN3+OsIFmydGyZ1AVwERCq1w/ZZwRg== + dependencies: + is-glob "^4.0.1" + glob-stream@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-6.1.0.tgz#7045c99413b3eb94888d83ab46d0b404cc7bdde4" @@ -9615,7 +9716,7 @@ html-tag-names@^1.1.1: resolved "https://registry.yarnpkg.com/html-tag-names/-/html-tag-names-1.1.4.tgz#51c559e36a077b5eb6c71e6cb49b1d70fffc9124" integrity sha512-QCOY1/oHmo2BNwsTzuYlW51JLXSxfmMvve+2/9i2cbhxXxT6SuhsUWzcIoMwUi0HZW/NIQBSyJaj7fbcsimoKg== -html-webpack-plugin@^3.0.4: +html-webpack-plugin@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz#b01abbd723acaaa7b37b6af4492ebda03d9dd37b" integrity sha1-sBq71yOsqqeze2r0SS69oD2d03s= @@ -9979,6 +10080,25 @@ inquirer@^6.2.0, inquirer@^6.2.2: strip-ansi "^5.1.0" through "^2.3.6" +inquirer@^6.4.1: + version "6.5.2" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca" + integrity sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ== + dependencies: + ansi-escapes "^3.2.0" + chalk "^2.4.2" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^3.0.3" + figures "^2.0.0" + lodash "^4.17.12" + mute-stream "0.0.7" + run-async "^2.2.0" + rxjs "^6.4.0" + string-width "^2.1.0" + strip-ansi "^5.1.0" + through "^2.3.6" + internal-ip@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-4.3.0.tgz#845452baad9d2ca3b69c635a137acb9a0dad0907" @@ -10269,7 +10389,7 @@ is-glob@^3.1.0: dependencies: is-extglob "^2.1.0" -is-glob@^4.0.0: +is-glob@^4.0.0, is-glob@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== @@ -12763,6 +12883,16 @@ normalize-url@^4.1.0: resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.3.0.tgz#9c49e10fc1876aeb76dba88bf1b2b5d9fa57b2ee" integrity sha512-0NLtR71o4k6GLP+mr6Ty34c5GA6CMoEsncKJxvQd8NzPxaHRJNnb5gZE8R1XF4CPIS7QPHLJ74IFszwtNVAHVQ== +notistack@^0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/notistack/-/notistack-0.9.0.tgz#d195a186f5f25f7316b9e89a91ae3abe1072125e" + integrity sha512-3SrMUuJIAn4YtxvHlY6mjYDoQ+NQnozeQUOub5ywc+WEb8n85i/9PO/vqD9lGBXINEgN34B+YEA34oo7yeGYVQ== + dependencies: + classnames "^2.2.6" + hoist-non-react-statics "^3.3.0" + prop-types "^15.7.2" + react-is "^16.8.6" + 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" @@ -15093,7 +15223,7 @@ reduce-reducers@^0.4.3: resolved "https://registry.yarnpkg.com/reduce-reducers/-/reduce-reducers-0.4.3.tgz#8e052618801cd8fc2714b4915adaa8937eb6d66c" integrity sha512-+CNMnI8QhgVMtAt54uQs3kUxC3Sybpa7Y63HR14uGLgI9/QR5ggHvpxwhGGe3wmx5V91YwqQIblN9k5lspAmGw== -redux-actions@^2.3.0: +redux-actions@^2.6.5: version "2.6.5" resolved "https://registry.yarnpkg.com/redux-actions/-/redux-actions-2.6.5.tgz#bdca548768ee99832a63910c276def85e821a27e" integrity sha512-pFhEcWFTYNk7DhQgxMGnbsB1H2glqhQJRQrtPb96kD3hWiZRzXHwwmFPswg6V2MjraXRXWNmuP9P84tvdLAJmw== @@ -15137,7 +15267,7 @@ redux-saga@1.0.0: dependencies: "@redux-saga/core" "^1.0.0" -redux-thunk@^2.2.0: +redux-thunk@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.3.0.tgz#51c2c19a185ed5187aaa9a2d08b666d0d6467622" integrity sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw== @@ -15941,7 +16071,7 @@ semver@6.2.0, semver@^6.0.0, semver@^6.1.1: resolved "https://registry.yarnpkg.com/semver/-/semver-6.2.0.tgz#4d813d9590aaf8a9192693d6c85b9344de5901db" integrity sha512-jdFC1VdUGT/2Scgbimf7FSx9iJLXoqfglSF+gJeuNWVpiE37OIbc1jywR/GJyFdz3mnkz2/id0L0J/cr0izR5A== -semver@^6.2.0, semver@^6.3.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== @@ -16525,7 +16655,7 @@ storybook-host@5.1.0: ramda "^0.25.0" tinycolor2 "^1.4.1" -storybook-router@^0.3.3: +storybook-router@^0.3.4: version "0.3.4" resolved "https://registry.yarnpkg.com/storybook-router/-/storybook-router-0.3.4.tgz#27c0c0de5eafa03b9003a850ac40e2b0c2a3ee65" integrity sha512-WU8kyx06R5zFa3KT1TZey2fOadj0nFhWs5yuq3iVcfSbUhtwSg/QNGF7V6IXjiBOtYqmvN2/hlUnYneC/oQ16w== @@ -16742,6 +16872,11 @@ strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= +strip-json-comments@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7" + integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw== + style-loader@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-1.0.0.tgz#1d5296f9165e8e2c85d24eee0b7caf9ec8ca1f82" @@ -18335,6 +18470,11 @@ v8-compile-cache@2.0.3: resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz#00f7494d2ae2b688cfe2899df6ed2c54bef91dbe" integrity sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w== +v8-compile-cache@^2.0.3: + version "2.1.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e" + integrity sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g== + v8flags@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.1.1.tgz#aab1a1fa30d45f88dd321148875ac02c0b55e5b4" @@ -19640,7 +19780,7 @@ webpack-log@^2.0.0: ansi-colors "^3.0.0" uuid "^3.3.2" -webpack-manifest-plugin@^2.0.0-rc.2: +webpack-manifest-plugin@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/webpack-manifest-plugin/-/webpack-manifest-plugin-2.0.4.tgz#e4ca2999b09557716b8ba4475fb79fab5986f0cd" integrity sha512-nejhOHexXDBKQOj/5v5IZSfCeTO3x1Dt1RZEcGfBSul891X/eLIcIVH31gwxPDdsi2Z8LKKFGpM4w9+oTBOSCg== From f6d8326179081c7b07e568d5f29aab294efce170 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Mon, 16 Sep 2019 14:08:12 +0200 Subject: [PATCH 10/50] Add snackbar basic structure --- src/components/Header/index.jsx | 12 ++- src/components/SharedSnackBar/index.jsx | 105 --------------------- src/components/layout/PageFrame/index.jsx | 17 +++- src/components/layout/PageFrame/index.scss | 16 ++++ 4 files changed, 37 insertions(+), 113 deletions(-) delete mode 100644 src/components/SharedSnackBar/index.jsx diff --git a/src/components/Header/index.jsx b/src/components/Header/index.jsx index 0511119b..6c2e1aa4 100644 --- a/src/components/Header/index.jsx +++ b/src/components/Header/index.jsx @@ -1,8 +1,8 @@ // @flow import * as React from 'react' import { connect } from 'react-redux' +import { useSnackbar } from 'notistack' import { logComponentStack, type Info } from '~/utils/logBoundaries' -import { SharedSnackbarConsumer, type Variant } from '~/components/SharedSnackBar' import { WALLET_ERROR_MSG } from '~/logic/wallets/store/actions' import { getProviderInfo } from '~/logic/wallets/getWeb3' import type { ProviderProps } from '~/logic/wallets/store/model/provider' @@ -14,6 +14,8 @@ import Layout from './component/Layout' import actions, { type Actions } from './actions' import selector, { type SelectorProps } from './selector' +type Variant = 'success' | 'error' | 'warning' | 'info' + type Props = Actions & SelectorProps & { openSnackbar: (message: string, variant: Variant) => void, @@ -116,8 +118,10 @@ const Header = connect( actions, )(HeaderComponent) -const HeaderSnack = () => ( - {({ openSnackbar }) =>
} -) +const HeaderSnack = () => { + const { enqueueSnackbar } = useSnackbar() + + return
+} export default HeaderSnack diff --git a/src/components/SharedSnackBar/index.jsx b/src/components/SharedSnackBar/index.jsx deleted file mode 100644 index c22c9213..00000000 --- a/src/components/SharedSnackBar/index.jsx +++ /dev/null @@ -1,105 +0,0 @@ -// @flow -import * as React from 'react' -import { Snackbar } from '@material-ui/core' -import SnackbarContent from '~/components/SnackbarContent' - -export const SharedSnackbar = () => ( - - {(value) => { - const { - snackbarIsOpen, message, closeSnackbar, variant, - } = value - - return ( - - - - ) - }} - -) - -type SnackbarContext = { - openSnackbar: Function, - closeSnackbar: Function, - snackbarIsOpen: boolean, - message: string, - variant: string, -} - -const SharedSnackbarContext = React.createContext({ - openSnackbar: undefined, - closeSnackbar: undefined, - snackbarIsOpen: false, - message: '', - variant: 'info', -}) - -type Props = { - children: React.Node, -} - -export type Variant = 'success' | 'error' | 'warning' | 'info' - -type State = { - isOpen: boolean, - message: string, - variant: Variant, -} - -export class SharedSnackbarProvider extends React.Component { - constructor(props: Props) { - super(props) - - this.state = { - isOpen: false, - message: '', - variant: 'info', - } - } - - openSnackbar = (message: string, variant: Variant) => { - this.setState({ - message, - variant, - isOpen: true, - }) - } - - closeSnackbar = () => { - this.setState({ - message: '', - isOpen: false, - }) - } - - render() { - const { children } = this.props - const { message, variant, isOpen } = this.state - - return ( - - - {children} - - ) - } -} - -export const SharedSnackbarConsumer = SharedSnackbarContext.Consumer diff --git a/src/components/layout/PageFrame/index.jsx b/src/components/layout/PageFrame/index.jsx index 6159ca41..126e774f 100644 --- a/src/components/layout/PageFrame/index.jsx +++ b/src/components/layout/PageFrame/index.jsx @@ -1,8 +1,9 @@ // @flow import * as React from 'react' -import Header from '~/components/Header' +import { SnackbarProvider } from 'notistack' import SidebarProvider from '~/components/Sidebar' -import { SharedSnackbarProvider } from '~/components/SharedSnackBar' +import Footer from '~/components/Footer' +import Header from '~/components/Header' import styles from './index.scss' type Props = { @@ -10,14 +11,22 @@ type Props = { } const PageFrame = ({ children }: Props) => ( - +
{children}
-
+ ) export default PageFrame diff --git a/src/components/layout/PageFrame/index.scss b/src/components/layout/PageFrame/index.scss index 9727c40e..54ceec03 100644 --- a/src/components/layout/PageFrame/index.scss +++ b/src/components/layout/PageFrame/index.scss @@ -4,3 +4,19 @@ flex: 1 1 auto; max-width: 100%; } + +.success { + background: 'purple'; +} + +.error { + background: 'blue'; +} + +.warning { + background: 'green'; +} + +.info { + background: 'yellow'; +} From 81323e18080a41b5ade91f9b23a88ac1643d259f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Tue, 17 Sep 2019 11:06:53 +0200 Subject: [PATCH 11/50] Enqueue Snackbar in provider notifications --- src/components/Header/index.jsx | 32 ++++++++----------- .../wallets/store/actions/fetchProvider.js | 12 +++---- .../wallets/store/actions/removeProvider.js | 4 +-- 3 files changed, 21 insertions(+), 27 deletions(-) diff --git a/src/components/Header/index.jsx b/src/components/Header/index.jsx index 6c2e1aa4..f4b4a60d 100644 --- a/src/components/Header/index.jsx +++ b/src/components/Header/index.jsx @@ -1,7 +1,7 @@ // @flow import * as React from 'react' import { connect } from 'react-redux' -import { useSnackbar } from 'notistack' +import { withSnackbar } from 'notistack' import { logComponentStack, type Info } from '~/utils/logBoundaries' import { WALLET_ERROR_MSG } from '~/logic/wallets/store/actions' import { getProviderInfo } from '~/logic/wallets/getWeb3' @@ -18,7 +18,7 @@ type Variant = 'success' | 'error' | 'warning' | 'info' type Props = Actions & SelectorProps & { - openSnackbar: (message: string, variant: Variant) => void, + enqueueSnackbar: (message: string, variant: Variant) => void, } type State = { @@ -41,31 +41,33 @@ class HeaderComponent extends React.PureComponent { } componentDidCatch(error: Error, info: Info) { - const { openSnackbar } = this.props + const { enqueueSnackbar } = this.props + this.setState({ hasError: true }) - openSnackbar(WALLET_ERROR_MSG, 'error') + enqueueSnackbar(WALLET_ERROR_MSG, 'error') logComponentStack(error, info) } onDisconnect = () => { - const { removeProvider, openSnackbar } = this.props + const { removeProvider, enqueueSnackbar } = this.props + clearInterval(this.providerListener) - removeProvider(openSnackbar) + removeProvider(enqueueSnackbar) } onConnect = async () => { - const { fetchProvider, openSnackbar } = this.props + const { fetchProvider, enqueueSnackbar } = this.props clearInterval(this.providerListener) let currentProvider: ProviderProps = await getProviderInfo() - fetchProvider(currentProvider, openSnackbar) + fetchProvider(currentProvider, enqueueSnackbar) this.providerListener = setInterval(async () => { const newProvider: ProviderProps = await getProviderInfo() if (JSON.stringify(currentProvider) !== JSON.stringify(newProvider)) { - fetchProvider(newProvider, openSnackbar) + fetchProvider(newProvider, enqueueSnackbar) } currentProvider = newProvider }, 2000) @@ -113,15 +115,7 @@ class HeaderComponent extends React.PureComponent { } } -const Header = connect( +export default connect( selector, actions, -)(HeaderComponent) - -const HeaderSnack = () => { - const { enqueueSnackbar } = useSnackbar() - - return
-} - -export default HeaderSnack +)(withSnackbar(HeaderComponent)) diff --git a/src/logic/wallets/store/actions/fetchProvider.js b/src/logic/wallets/store/actions/fetchProvider.js index c19f52ce..d4afa50f 100644 --- a/src/logic/wallets/store/actions/fetchProvider.js +++ b/src/logic/wallets/store/actions/fetchProvider.js @@ -26,25 +26,25 @@ const UNLOCK_MSG = 'Unlock your wallet to connect' const WRONG_NETWORK = 'You are connected to wrong network. Please use RINKEBY' export const WALLET_ERROR_MSG = 'Error connecting to your wallet' -const handleProviderNotification = (openSnackbar: Function, provider: ProviderProps) => { +const handleProviderNotification = (enqueueSnackbar: Function, provider: ProviderProps) => { const { loaded, available, network } = provider if (!loaded) { - openSnackbar(WALLET_ERROR_MSG, 'error') + enqueueSnackbar(WALLET_ERROR_MSG, 'error') return } if (ETHEREUM_NETWORK_IDS[network] !== ETHEREUM_NETWORK.RINKEBY) { - openSnackbar(WRONG_NETWORK, 'error') + enqueueSnackbar(WRONG_NETWORK, 'error') return } const msg = available ? SUCCESS_MSG : UNLOCK_MSG const variant = available ? 'success' : 'warning' - openSnackbar(msg, variant) + enqueueSnackbar(msg, variant) } -export default (provider: ProviderProps, openSnackbar: Function) => (dispatch: ReduxDispatch<*>) => { - handleProviderNotification(openSnackbar, provider) +export default (provider: ProviderProps, enqueueSnackbar: Function) => (dispatch: ReduxDispatch<*>) => { + handleProviderNotification(enqueueSnackbar, provider) processProviderResponse(dispatch, provider) } diff --git a/src/logic/wallets/store/actions/removeProvider.js b/src/logic/wallets/store/actions/removeProvider.js index 00b35973..dc85c64d 100644 --- a/src/logic/wallets/store/actions/removeProvider.js +++ b/src/logic/wallets/store/actions/removeProvider.js @@ -3,7 +3,7 @@ import type { Dispatch as ReduxDispatch } from 'redux' import { makeProvider, type ProviderProps, type Provider } from '~/logic/wallets/store/model/provider' import addProvider from './addProvider' -export default (openSnackbar: Function) => async (dispatch: ReduxDispatch<*>) => { +export default (enqueueSnackbar: Function) => async (dispatch: ReduxDispatch<*>) => { const providerProps: ProviderProps = { name: '', available: false, @@ -13,7 +13,7 @@ export default (openSnackbar: Function) => async (dispatch: ReduxDispatch<*>) => } const provider: Provider = makeProvider(providerProps) - openSnackbar('Wallet disconnected succesfully', 'info') + enqueueSnackbar('Wallet disconnected succesfully', 'info') dispatch(addProvider(provider)) } From 4dfdfed0b73372e959b93b261aa8f95e46779615 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Tue, 17 Sep 2019 11:20:00 +0200 Subject: [PATCH 12/50] Enqueue Snackbar in Safe settings --- .../Settings/ChangeSafeName/index.jsx | 16 +-- .../ManageOwners/AddOwnerModal/index.jsx | 104 +++++++------- .../ManageOwners/RemoveOwnerModal/index.jsx | 129 +++++++++--------- .../ManageOwners/ReplaceOwnerModal/index.jsx | 120 ++++++++-------- .../Settings/ThresholdSettings/index.jsx | 111 +++++++-------- 5 files changed, 225 insertions(+), 255 deletions(-) diff --git a/src/routes/safe/components/Settings/ChangeSafeName/index.jsx b/src/routes/safe/components/Settings/ChangeSafeName/index.jsx index 886016eb..7c368172 100644 --- a/src/routes/safe/components/Settings/ChangeSafeName/index.jsx +++ b/src/routes/safe/components/Settings/ChangeSafeName/index.jsx @@ -1,11 +1,11 @@ // @flow import React from 'react' import { withStyles } from '@material-ui/core/styles' +import { withSnackbar } from 'notistack' import Block from '~/components/layout/Block' import Col from '~/components/layout/Col' import Field from '~/components/forms/Field' import Heading from '~/components/layout/Heading' -import { SharedSnackbarConsumer } from '~/components/SharedSnackBar' import { composeValidators, required, minMaxLength } from '~/components/forms/validator' import TextField from '~/components/forms/TextField' import GnoForm from '~/components/forms/GnoForm' @@ -22,17 +22,17 @@ type Props = { safeAddress: string, safeName: string, updateSafe: Function, - openSnackbar: Function, + enqueueSnackbar: Function, } const ChangeSafeName = (props: Props) => { const { - classes, safeAddress, safeName, updateSafe, openSnackbar, + classes, safeAddress, safeName, updateSafe, enqueueSnackbar, } = props const handleSubmit = (values) => { updateSafe({ address: safeAddress, name: values.safeName }) - openSnackbar('Safe name changed', 'success') + enqueueSnackbar('Safe name changed', 'success') } return ( @@ -80,10 +80,4 @@ const ChangeSafeName = (props: Props) => { ) } -const withSnackbar = (props) => ( - - {({ openSnackbar }) => } - -) - -export default withStyles(styles)(withSnackbar) +export default withStyles(styles)(withSnackbar(ChangeSafeName)) diff --git a/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.jsx b/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.jsx index 1ace6021..893ba5db 100644 --- a/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.jsx @@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react' import { List } from 'immutable' import { withStyles } from '@material-ui/core/styles' -import { SharedSnackbarConsumer } from '~/components/SharedSnackBar' +import { withSnackbar } from 'notistack' import Modal from '~/components/Modal' import { type Owner } from '~/routes/safe/store/models/owner' import { getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts' @@ -29,6 +29,7 @@ type Props = { network: string, addSafeOwner: Function, createTransaction: Function, + enqueueSnackbar: Function, } type ActiveScreen = 'selectOwner' | 'selectThreshold' | 'reviewAddOwner' @@ -36,14 +37,14 @@ export const sendAddOwner = async ( values: Object, safeAddress: string, ownersOld: List, - openSnackbar: Function, + enqueueSnackbar: Function, createTransaction: Function, addSafeOwner: Function, ) => { const gnosisSafe = await getGnosisSafeInstanceAt(safeAddress) const txData = gnosisSafe.contract.methods.addOwnerWithThreshold(values.ownerAddress, values.threshold).encodeABI() - const txHash = await createTransaction(safeAddress, safeAddress, 0, txData, openSnackbar) + const txHash = await createTransaction(safeAddress, safeAddress, 0, txData, enqueueSnackbar) if (txHash) { addSafeOwner({ safeAddress, ownerName: values.ownerName, ownerAddress: values.ownerAddress }) @@ -61,6 +62,7 @@ const AddOwner = ({ network, createTransaction, addSafeOwner, + enqueueSnackbar, }: Props) => { const [activeScreen, setActiveScreen] = useState('selectOwner') const [values, setValues] = useState({}) @@ -98,59 +100,51 @@ const AddOwner = ({ setActiveScreen('reviewAddOwner') } - return ( - <> - - {({ openSnackbar }) => { - const onAddOwner = async () => { - onClose() - try { - sendAddOwner(values, safeAddress, owners, openSnackbar, createTransaction, addSafeOwner) - } catch (error) { - // eslint-disable-next-line - console.log('Error while removing an owner ' + error) - } - } + const onAddOwner = async () => { + onClose() + try { + sendAddOwner(values, safeAddress, owners, enqueueSnackbar, createTransaction, addSafeOwner) + } catch (error) { + // eslint-disable-next-line + console.log('Error while removing an owner ' + error) + } + } - return ( - - <> - {activeScreen === 'selectOwner' && ( - - )} - {activeScreen === 'selectThreshold' && ( - - )} - {activeScreen === 'reviewAddOwner' && ( - - )} - - - ) - }} - - + return ( + + <> + {activeScreen === 'selectOwner' && ( + + )} + {activeScreen === 'selectThreshold' && ( + + )} + {activeScreen === 'reviewAddOwner' && ( + + )} + + ) } -export default withStyles(styles)(AddOwner) +export default withStyles(styles)(withSnackbar(AddOwner)) diff --git a/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/index.jsx b/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/index.jsx index c245965b..a4be9c5d 100644 --- a/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/index.jsx @@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react' import { List } from 'immutable' import { withStyles } from '@material-ui/core/styles' -import { SharedSnackbarConsumer } from '~/components/SharedSnackBar' +import { withSnackbar } from 'notistack' import Modal from '~/components/Modal' import { type Owner } from '~/routes/safe/store/models/owner' import { getGnosisSafeInstanceAt, SENTINEL_ADDRESS } from '~/logic/contracts/safeContracts' @@ -31,7 +31,9 @@ type Props = { network: string, createTransaction: Function, removeSafeOwner: Function, + enqueueSnackbar: Function, } + type ActiveScreen = 'checkOwner' | 'selectThreshold' | 'reviewRemoveOwner' export const sendRemoveOwner = async ( @@ -40,7 +42,7 @@ export const sendRemoveOwner = async ( ownerAddressToRemove: string, ownerNameToRemove: string, ownersOld: List, - openSnackbar: Function, + enqueueSnackbar: Function, createTransaction: Function, removeSafeOwner: Function, ) => { @@ -54,7 +56,7 @@ export const sendRemoveOwner = async ( .removeOwner(prevAddress, ownerAddressToRemove, values.threshold) .encodeABI() - const txHash = await createTransaction(safeAddress, safeAddress, 0, txData, openSnackbar) + const txHash = await createTransaction(safeAddress, safeAddress, 0, txData, enqueueSnackbar) if (txHash) { removeSafeOwner({ safeAddress, ownerAddress: ownerAddressToRemove }) @@ -74,6 +76,7 @@ const RemoveOwner = ({ network, createTransaction, removeSafeOwner, + enqueueSnackbar, }: Props) => { const [activeScreen, setActiveScreen] = useState('checkOwner') const [values, setValues] = useState({}) @@ -104,71 +107,63 @@ const RemoveOwner = ({ setActiveScreen('reviewRemoveOwner') } - return ( - <> - - {({ openSnackbar }) => { - const onRemoveOwner = () => { - onClose() - sendRemoveOwner( - values, - safeAddress, - ownerAddress, - ownerName, - owners, - openSnackbar, - createTransaction, - removeSafeOwner, - ) - } + const onRemoveOwner = () => { + onClose() + sendRemoveOwner( + values, + safeAddress, + ownerAddress, + ownerName, + owners, + enqueueSnackbar, + createTransaction, + removeSafeOwner, + ) + } - return ( - - <> - {activeScreen === 'checkOwner' && ( - - )} - {activeScreen === 'selectThreshold' && ( - - )} - {activeScreen === 'reviewRemoveOwner' && ( - - )} - - - ) - }} - - + return ( + + <> + {activeScreen === 'checkOwner' && ( + + )} + {activeScreen === 'selectThreshold' && ( + + )} + {activeScreen === 'reviewRemoveOwner' && ( + + )} + + ) } -export default withStyles(styles)(RemoveOwner) +export default withStyles(styles)(withSnackbar(RemoveOwner)) diff --git a/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.jsx b/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.jsx index 02b9037e..26c63fb0 100644 --- a/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.jsx @@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react' import { List } from 'immutable' import { withStyles } from '@material-ui/core/styles' -import { SharedSnackbarConsumer } from '~/components/SharedSnackBar' +import { withSnackbar } from 'notistack' import Modal from '~/components/Modal' import { getGnosisSafeInstanceAt, SENTINEL_ADDRESS } from '~/logic/contracts/safeContracts' import OwnerForm from './screens/OwnerForm' @@ -29,6 +29,7 @@ type Props = { threshold: string, createTransaction: Function, replaceSafeOwner: Function, + enqueueSnackbar: Function, } type ActiveScreen = 'checkOwner' | 'reviewReplaceOwner' @@ -36,7 +37,7 @@ export const sendReplaceOwner = async ( values: Object, safeAddress: string, ownerAddressToRemove: string, - openSnackbar: Function, + enqueueSnackbar: Function, createTransaction: Function, replaceSafeOwner: Function, ) => { @@ -50,7 +51,7 @@ export const sendReplaceOwner = async ( .swapOwner(prevAddress, ownerAddressToRemove, values.ownerAddress) .encodeABI() - const txHash = await createTransaction(safeAddress, safeAddress, 0, txData, openSnackbar) + const txHash = await createTransaction(safeAddress, safeAddress, 0, txData, enqueueSnackbar) if (txHash) { replaceSafeOwner({ @@ -75,6 +76,7 @@ const ReplaceOwner = ({ threshold, createTransaction, replaceSafeOwner, + enqueueSnackbar, }: Props) => { const [activeScreen, setActiveScreen] = useState('checkOwner') const [values, setValues] = useState({}) @@ -96,67 +98,59 @@ const ReplaceOwner = ({ setActiveScreen('reviewReplaceOwner') } - return ( - <> - - {({ openSnackbar }) => { - const onReplaceOwner = () => { - onClose() - try { - sendReplaceOwner( - values, - safeAddress, - ownerAddress, - openSnackbar, - createTransaction, - replaceSafeOwner, - ) - } catch (error) { - // eslint-disable-next-line - console.log('Error while removing an owner ' + error) - } - } + const onReplaceOwner = () => { + onClose() + try { + sendReplaceOwner( + values, + safeAddress, + ownerAddress, + enqueueSnackbar, + createTransaction, + replaceSafeOwner, + ) + } catch (error) { + // eslint-disable-next-line + console.log('Error while removing an owner ' + error) + } + } - return ( - - <> - {activeScreen === 'checkOwner' && ( - - )} - {activeScreen === 'reviewReplaceOwner' && ( - - )} - - - ) - }} - - + return ( + + <> + {activeScreen === 'checkOwner' && ( + + )} + {activeScreen === 'reviewReplaceOwner' && ( + + )} + + ) } -export default withStyles(styles)(ReplaceOwner) +export default withStyles(styles)(withSnackbar(ReplaceOwner)) diff --git a/src/routes/safe/components/Settings/ThresholdSettings/index.jsx b/src/routes/safe/components/Settings/ThresholdSettings/index.jsx index 701fa6c6..44ec5e56 100644 --- a/src/routes/safe/components/Settings/ThresholdSettings/index.jsx +++ b/src/routes/safe/components/Settings/ThresholdSettings/index.jsx @@ -2,7 +2,7 @@ import React, { useState } from 'react' import { withStyles } from '@material-ui/core/styles' import { List } from 'immutable' -import { SharedSnackbarConsumer } from '~/components/SharedSnackBar' +import { withSnackbar } from 'notistack' import Heading from '~/components/layout/Heading' import Button from '~/components/layout/Button' import Bold from '~/components/layout/Bold' @@ -22,10 +22,11 @@ type Props = { createTransaction: Function, safeAddress: string, granted: boolean, + enqueueSnackbar: Function, } const ThresholdSettings = ({ - owners, threshold, classes, createTransaction, safeAddress, granted, + owners, threshold, classes, createTransaction, safeAddress, granted, enqueueSnackbar, }: Props) => { const [isModalOpen, setModalOpen] = useState(false) @@ -33,66 +34,58 @@ const ThresholdSettings = ({ setModalOpen((prevOpen) => !prevOpen) } + const onChangeThreshold = async (newThreshold) => { + const safeInstance = await getGnosisSafeInstanceAt(safeAddress) + const txData = safeInstance.contract.methods.changeThreshold(newThreshold).encodeABI() + + createTransaction(safeAddress, safeAddress, 0, txData, enqueueSnackbar) + } + return ( <> - - {({ openSnackbar }) => { - const onChangeThreshold = async (newThreshold) => { - const safeInstance = await getGnosisSafeInstanceAt(safeAddress) - const txData = safeInstance.contract.methods.changeThreshold(newThreshold).encodeABI() - - createTransaction(safeAddress, safeAddress, 0, txData, openSnackbar) - } - - return ( - <> - - Required confirmations - - Any transaction requires the confirmation of: - - - {threshold} - {' '} - out of - {' '} - {owners.size} - {' '} - owners - - {owners.size > 1 && granted && ( - - - - )} - - - - - - ) - }} - + + Required confirmations + + Any transaction requires the confirmation of: + + + {threshold} + {' '} + out of + {' '} + {owners.size} + {' '} + owners + + {owners.size > 1 && granted && ( + + + + )} + + + + ) } -export default withStyles(styles)(ThresholdSettings) +export default withStyles(styles)(withSnackbar(ThresholdSettings)) From 72f40ff494a35723a51af139242aa635a5b8a4bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Tue, 17 Sep 2019 12:18:04 +0200 Subject: [PATCH 13/50] Enqueue Snackbar in send funds and custom transactions --- src/logic/safe/transactions/send.js | 7 +- .../screens/ReviewCustomTx/index.jsx | 205 +++++++++--------- .../SendModal/screens/ReviewTx/index.jsx | 204 +++++++++-------- .../ExpandedTx/ApproveTxModal/index.jsx | 118 +++++----- .../ExpandedTx/CancelTxModal/index.jsx | 115 +++++----- .../safe/store/actions/createTransaction.js | 12 +- .../safe/store/actions/processTransaction.js | 10 +- 7 files changed, 332 insertions(+), 339 deletions(-) diff --git a/src/logic/safe/transactions/send.js b/src/logic/safe/transactions/send.js index 128f63f8..4e34a31b 100644 --- a/src/logic/safe/transactions/send.js +++ b/src/logic/safe/transactions/send.js @@ -44,13 +44,16 @@ export const approveTransaction = async ( const web3 = getWeb3() const contract = new web3.eth.Contract(GnosisSafeSol.abi, safeInstance.address) - const transactionHash = await contract.methods.approveHash(txHash) + const transactionHash = await contract.methods + .approveHash(txHash) .send({ from: sender, - }).once('transactionHash', () => { + }) + .once('transactionHash', () => { showNotification() }) .on('error', (error) => { + /* eslint-disable */ console.log('Tx error:', error) }) .then(async (receipt) => { diff --git a/src/routes/safe/components/Balances/SendModal/screens/ReviewCustomTx/index.jsx b/src/routes/safe/components/Balances/SendModal/screens/ReviewCustomTx/index.jsx index e391ada9..bfae7eb2 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ReviewCustomTx/index.jsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ReviewCustomTx/index.jsx @@ -4,7 +4,7 @@ import OpenInNew from '@material-ui/icons/OpenInNew' import { withStyles } from '@material-ui/core/styles' import Close from '@material-ui/icons/Close' import IconButton from '@material-ui/core/IconButton' -import { SharedSnackbarConsumer } from '~/components/SharedSnackBar' +import { withSnackbar } from 'notistack' import Paragraph from '~/components/layout/Paragraph' import Row from '~/components/layout/Row' import Link from '~/components/layout/Link' @@ -33,6 +33,7 @@ type Props = { ethBalance: string, tx: Object, createTransaction: Function, + enqueueSnackbar: Function, } const openIconStyle = { @@ -50,110 +51,108 @@ const ReviewCustomTx = ({ ethBalance, tx, createTransaction, -}: Props) => ( - - {({ openSnackbar }) => { - const submitTx = async () => { - const web3 = getWeb3() - const txRecipient = tx.recipientAddress - const txData = tx.data - const txValue = tx.value ? web3.utils.toWei(tx.value, 'ether') : 0 + enqueueSnackbar, +}: Props) => { + const submitTx = async () => { + const web3 = getWeb3() + const txRecipient = tx.recipientAddress + const txData = tx.data + const txValue = tx.value ? web3.utils.toWei(tx.value, 'ether') : 0 - createTransaction(safeAddress, txRecipient, txValue, txData, openSnackbar) - onClose() - } + createTransaction(safeAddress, txRecipient, txValue, txData, enqueueSnackbar) + onClose() + } - return ( - <> - - - Send Funds + return ( + <> + + + Send Funds + + 2 of 2 + + + + + + + + + + Arrow Down + + + + + + + + Recipient + + + + + + + + + {tx.recipientAddress} + + + - 2 of 2 - - - - - - - - - - Arrow Down - - - - + + + + + Value + + + + Ether + + {tx.value || 0} + {' ETH'} + + + + + Data (hex encoded) + + + + + + {tx.data} - - - Recipient - - - - - - - - - {tx.recipientAddress} - - - - - - - - - Value - - - - Ether - - {tx.value || 0} - {' ETH'} - - - - - Data (hex encoded) - - - - - - {tx.data} - - - - - - - - - - - ) - }} - -) + + + + + + + + + + ) +} -export default withStyles(styles)(ReviewCustomTx) + +export default withStyles(styles)(withSnackbar(ReviewCustomTx)) diff --git a/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.jsx b/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.jsx index b301038e..1127c336 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.jsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.jsx @@ -4,7 +4,7 @@ import OpenInNew from '@material-ui/icons/OpenInNew' import { withStyles } from '@material-ui/core/styles' import Close from '@material-ui/icons/Close' import IconButton from '@material-ui/core/IconButton' -import { SharedSnackbarConsumer } from '~/components/SharedSnackBar' +import { withSnackbar } from 'notistack' import Paragraph from '~/components/layout/Paragraph' import Row from '~/components/layout/Row' import Link from '~/components/layout/Link' @@ -35,6 +35,7 @@ type Props = { ethBalance: string, tx: Object, createTransaction: Function, + enqueueSnackbar: Function, } const openIconStyle = { @@ -52,111 +53,108 @@ const ReviewTx = ({ ethBalance, tx, createTransaction, -}: Props) => ( - - {({ openSnackbar }) => { - const submitTx = async () => { - const web3 = getWeb3() - const isSendingETH = isEther(tx.token.symbol) - const txRecipient = isSendingETH ? tx.recipientAddress : tx.token.address - let txData = EMPTY_DATA - let txAmount = web3.utils.toWei(tx.amount, 'ether') + enqueueSnackbar, +}: Props) => { + const submitTx = async () => { + const web3 = getWeb3() + const isSendingETH = isEther(tx.token.symbol) + const txRecipient = isSendingETH ? tx.recipientAddress : tx.token.address + let txData = EMPTY_DATA + let txAmount = web3.utils.toWei(tx.amount, 'ether') - if (!isSendingETH) { - const StandardToken = await getStandardTokenContract() - const tokenInstance = await StandardToken.at(tx.token.address) + if (!isSendingETH) { + const StandardToken = await getStandardTokenContract() + const tokenInstance = await StandardToken.at(tx.token.address) - txData = tokenInstance.contract.methods.transfer(tx.recipientAddress, txAmount).encodeABI() - // txAmount should be 0 if we send tokens - // the real value is encoded in txData and will be used by the contract - // if txAmount > 0 it would send ETH from the safe - txAmount = 0 - } + txData = tokenInstance.contract.methods.transfer(tx.recipientAddress, txAmount).encodeABI() + // txAmount should be 0 if we send tokens + // the real value is encoded in txData and will be used by the contract + // if txAmount > 0 it would send ETH from the safe + txAmount = 0 + } - createTransaction(safeAddress, txRecipient, txAmount, txData, openSnackbar) - onClose() - } + createTransaction(safeAddress, txRecipient, txAmount, txData, enqueueSnackbar) + onClose() + } - return ( - <> - - - Send Funds + return ( + <> + + + Send Funds + + 2 of 2 + + + + + + + + + + Arrow Down + + + + + + + + Recipient + + + + + + + + + {tx.recipientAddress} + + + - 2 of 2 - - - - - - - - - - Arrow Down - - - - - - - - Recipient - - - - - - - - - {tx.recipientAddress} - - - - - - - - - Amount - - - - {tx.token.name} - - {tx.amount} - {' '} - {tx.token.symbol} - - - - - - - - - - ) - }} - -) + + + + + Amount + + + + {tx.token.name} + + {tx.amount} + {' '} + {tx.token.symbol} + + + + + + + + + + ) +} -export default withStyles(styles)(ReviewTx) +export default withStyles(styles)(withSnackbar(ReviewTx)) 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 95630467..03e44bbf 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/ApproveTxModal/index.jsx +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/ApproveTxModal/index.jsx @@ -5,7 +5,7 @@ import IconButton from '@material-ui/core/IconButton' import { withStyles } from '@material-ui/core/styles' import FormControlLabel from '@material-ui/core/FormControlLabel' import Checkbox from '@material-ui/core/Checkbox' -import { SharedSnackbarConsumer } from '~/components/SharedSnackBar' +import { withSnackbar } from 'notistack' import Modal from '~/components/Modal' import Hairline from '~/components/layout/Hairline' import Button from '~/components/layout/Button' @@ -29,6 +29,7 @@ type Props = { threshold: number, thresholdReached: boolean, userAddress: string, + enqueueSnackbar: Function, } const getModalTitleAndDescription = (thresholdReached: boolean) => { @@ -55,6 +56,7 @@ const ApproveTxModal = ({ threshold, thresholdReached, userAddress, + enqueueSnackbar, }: Props) => { const [approveAndExecute, setApproveAndExecute] = useState(false) const { title, description } = getModalTitleAndDescription(thresholdReached) @@ -62,68 +64,62 @@ const ApproveTxModal = ({ const handleExecuteCheckbox = () => setApproveAndExecute((prevApproveAndExecute) => !prevApproveAndExecute) - return ( - - {({ openSnackbar }) => { - const approveTx = () => { - processTransaction(safeAddress, tx, openSnackbar, userAddress, approveAndExecute) - onClose() - } + const approveTx = () => { + processTransaction(safeAddress, tx, enqueueSnackbar, userAddress, enqueueSnackbar) + onClose() + } - return ( - - - - {title} + return ( + + + + {title} + + + + + + + + + {description} + + Transaction nonce: +
+ {tx.nonce} +
+ {!thresholdReached && oneConfirmationLeft && ( + <> + + Approving transaction does not execute it immediately. If you want to approve and execute the + transaction right away, click on checkbox below. - - - -
- - - - {description} - - Transaction nonce: -
- {tx.nonce} -
- {!thresholdReached && oneConfirmationLeft && ( - <> - - Approving transaction does not execute it immediately. If you want to approve and execute the - transaction right away, click on checkbox below. - - } - label="Execute transaction" - /> - - )} -
-
- - - - -
- ) - }} -
+ } + label="Execute transaction" + /> + + )} + + + + + + + ) } -export default withStyles(styles)(ApproveTxModal) +export default withStyles(styles)(withSnackbar(ApproveTxModal)) diff --git a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/CancelTxModal/index.jsx b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/CancelTxModal/index.jsx index 05c25121..3086ec7d 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/CancelTxModal/index.jsx +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/CancelTxModal/index.jsx @@ -3,7 +3,7 @@ import React from 'react' import Close from '@material-ui/icons/Close' import IconButton from '@material-ui/core/IconButton' import { withStyles } from '@material-ui/core/styles' -import { SharedSnackbarConsumer } from '~/components/SharedSnackBar' +import { withSnackbar } from 'notistack' import Modal from '~/components/Modal' import Hairline from '~/components/layout/Hairline' import Button from '~/components/layout/Button' @@ -22,67 +22,64 @@ type Props = { createTransaction: Function, tx: Transaction, safeAddress: string, + enqueueSnackbar: Function, } const CancelTxModal = ({ - onClose, isOpen, classes, createTransaction, tx, safeAddress, -}: Props) => ( - - {({ openSnackbar }) => { - const sendReplacementTransaction = () => { - createTransaction(safeAddress, safeAddress, 0, EMPTY_DATA, openSnackbar) - onClose() - } + onClose, isOpen, classes, createTransaction, tx, safeAddress, enqueueSnackbar, +}: Props) => { + const sendReplacementTransaction = () => { + createTransaction(safeAddress, safeAddress, 0, EMPTY_DATA, enqueueSnackbar) + onClose() + } - return ( - + + + Cancel transaction + + + + + + + + + + This action will cancel this transaction. A separate transaction will be performed to submit the + cancellation. + + + Transaction nonce: +
+ {tx.nonce} +
+
+
+ + + - - -
- ) - }} -
-) + Cancel Transaction + + + + ) +} -export default withStyles(styles)(CancelTxModal) +export default withStyles(styles)(withSnackbar(CancelTxModal)) diff --git a/src/routes/safe/store/actions/createTransaction.js b/src/routes/safe/store/actions/createTransaction.js index ad14b901..e3716c32 100644 --- a/src/routes/safe/store/actions/createTransaction.js +++ b/src/routes/safe/store/actions/createTransaction.js @@ -18,7 +18,7 @@ const createTransaction = ( to: string, valueInWei: string, txData: string = EMPTY_DATA, - openSnackbar: Function, + enqueueSnackbar: Function, shouldExecute?: boolean, notifications?: Notifications = DEFAULT_NOTIFICATIONS, ) => async (dispatch: ReduxDispatch, getState: GetState) => { @@ -33,16 +33,16 @@ const createTransaction = ( let txHash try { if (isExecution) { - const showNotification = () => openSnackbar(notifications.BEFORE_EXECUTION_OR_CREATION, 'success') + const showNotification = () => enqueueSnackbar(notifications.BEFORE_EXECUTION_OR_CREATION, 'success') txHash = await executeTransaction(showNotification, safeInstance, to, valueInWei, txData, CALL, nonce, from) - openSnackbar(notifications.AFTER_EXECUTION, 'success') + enqueueSnackbar(notifications.AFTER_EXECUTION, 'success') } else { - const showNotification = () => openSnackbar(notifications.BEFORE_EXECUTION_OR_CREATION, 'success') + const showNotification = () => enqueueSnackbar(notifications.BEFORE_EXECUTION_OR_CREATION, 'success') txHash = await approveTransaction(showNotification, safeInstance, to, valueInWei, txData, CALL, nonce, from) - openSnackbar(notifications.CREATED_MORE_CONFIRMATIONS_NEEDED, 'success') + enqueueSnackbar(notifications.CREATED_MORE_CONFIRMATIONS_NEEDED, 'success') } } catch (err) { - openSnackbar(notifications.ERROR, 'error') + enqueueSnackbar(notifications.ERROR, 'error') console.error(`Error while creating transaction: ${err}`) } diff --git a/src/routes/safe/store/actions/processTransaction.js b/src/routes/safe/store/actions/processTransaction.js index 1a077488..f31978bb 100644 --- a/src/routes/safe/store/actions/processTransaction.js +++ b/src/routes/safe/store/actions/processTransaction.js @@ -31,7 +31,7 @@ const generateSignaturesFromTxConfirmations = (tx: Transaction, preApprovingOwne const processTransaction = ( safeAddress: string, tx: Transaction, - openSnackbar: Function, + enqueueSnackbar: Function, userAddress: string, approveAndExecute?: boolean, ) => async (dispatch: ReduxDispatch, getState: GetState) => { @@ -46,7 +46,7 @@ const processTransaction = ( let txHash if (shouldExecute) { - const showNotification = () => openSnackbar('Transaction has been submitted', 'success') + const showNotification = () => enqueueSnackbar('Transaction has been submitted', 'success') txHash = await executeTransaction( showNotification, safeInstance, @@ -58,9 +58,9 @@ const processTransaction = ( from, sigs, ) - openSnackbar('Transaction has been confirmed', 'success') + enqueueSnackbar('Transaction has been confirmed', 'success') } else { - const showNotification = () => openSnackbar('Approval transaction has been submitted', 'success') + const showNotification = () => enqueueSnackbar('Approval transaction has been submitted', 'success') txHash = await approveTransaction( showNotification, safeInstance, @@ -71,7 +71,7 @@ const processTransaction = ( nonce, from, ) - openSnackbar('Approval transaction has been confirmed', 'success') + enqueueSnackbar('Approval transaction has been confirmed', 'success') } dispatch(fetchTransactions(safeAddress)) From e183bb3415fab7e3e6819a586d20ec1ad5c997d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Tue, 17 Sep 2019 16:02:46 +0200 Subject: [PATCH 14/50] Update enqueueSnackbar types --- src/components/Header/index.jsx | 7 ++++++- src/logic/wallets/store/actions/fetchProvider.js | 10 ++++++++-- src/logic/wallets/store/actions/removeProvider.js | 3 ++- .../SendModal/screens/ReviewCustomTx/index.jsx | 5 +++-- .../Balances/SendModal/screens/ReviewTx/index.jsx | 3 ++- .../safe/components/Settings/ChangeSafeName/index.jsx | 3 ++- .../Settings/ManageOwners/AddOwnerModal/index.jsx | 5 +++-- .../Settings/ManageOwners/RemoveOwnerModal/index.jsx | 5 +++-- .../Settings/ManageOwners/ReplaceOwnerModal/index.jsx | 5 +++-- .../components/Settings/ThresholdSettings/index.jsx | 5 +++-- .../TxsTable/ExpandedTx/ApproveTxModal/index.jsx | 3 ++- .../TxsTable/ExpandedTx/CancelTxModal/index.jsx | 3 ++- src/routes/safe/store/actions/createTransaction.js | 3 ++- src/routes/safe/store/actions/processTransaction.js | 3 ++- 14 files changed, 43 insertions(+), 20 deletions(-) diff --git a/src/components/Header/index.jsx b/src/components/Header/index.jsx index f4b4a60d..82f6f614 100644 --- a/src/components/Header/index.jsx +++ b/src/components/Header/index.jsx @@ -14,7 +14,12 @@ import Layout from './component/Layout' import actions, { type Actions } from './actions' import selector, { type SelectorProps } from './selector' -type Variant = 'success' | 'error' | 'warning' | 'info' +const SUCCESS = 'SUCCESS' +const ERROR = 'ERROR' +const WARNING = 'WARNING' +const INFO = 'INFO' + +export type Variant = SUCCESS | ERROR | WARNING | INFO type Props = Actions & SelectorProps & { diff --git a/src/logic/wallets/store/actions/fetchProvider.js b/src/logic/wallets/store/actions/fetchProvider.js index d4afa50f..dd132543 100644 --- a/src/logic/wallets/store/actions/fetchProvider.js +++ b/src/logic/wallets/store/actions/fetchProvider.js @@ -3,6 +3,7 @@ import type { Dispatch as ReduxDispatch } from 'redux' import { ETHEREUM_NETWORK_IDS, ETHEREUM_NETWORK } from '~/logic/wallets/getWeb3' import type { ProviderProps } from '~/logic/wallets/store/model/provider' import { makeProvider } from '~/logic/wallets/store/model/provider' +import { type Variant } from '~/components/Header' import addProvider from './addProvider' export const processProviderResponse = (dispatch: ReduxDispatch<*>, provider: ProviderProps) => { @@ -26,7 +27,10 @@ const UNLOCK_MSG = 'Unlock your wallet to connect' const WRONG_NETWORK = 'You are connected to wrong network. Please use RINKEBY' export const WALLET_ERROR_MSG = 'Error connecting to your wallet' -const handleProviderNotification = (enqueueSnackbar: Function, provider: ProviderProps) => { +const handleProviderNotification = ( + enqueueSnackbar: (message: string, variant: Variant) => void, + provider: ProviderProps, +) => { const { loaded, available, network } = provider if (!loaded) { @@ -44,7 +48,9 @@ const handleProviderNotification = (enqueueSnackbar: Function, provider: Provide enqueueSnackbar(msg, variant) } -export default (provider: ProviderProps, enqueueSnackbar: Function) => (dispatch: ReduxDispatch<*>) => { +export default (provider: ProviderProps, enqueueSnackbar: (message: string, variant: Variant) => void) => ( + dispatch: ReduxDispatch<*>, +) => { handleProviderNotification(enqueueSnackbar, provider) processProviderResponse(dispatch, provider) } diff --git a/src/logic/wallets/store/actions/removeProvider.js b/src/logic/wallets/store/actions/removeProvider.js index dc85c64d..5bbe142f 100644 --- a/src/logic/wallets/store/actions/removeProvider.js +++ b/src/logic/wallets/store/actions/removeProvider.js @@ -1,9 +1,10 @@ // @flow import type { Dispatch as ReduxDispatch } from 'redux' import { makeProvider, type ProviderProps, type Provider } from '~/logic/wallets/store/model/provider' +import { type Variant } from '~/components/Header' import addProvider from './addProvider' -export default (enqueueSnackbar: Function) => async (dispatch: ReduxDispatch<*>) => { +export default (enqueueSnackbar: (message: string, variant: Variant) => void) => async (dispatch: ReduxDispatch<*>) => { const providerProps: ProviderProps = { name: '', available: false, diff --git a/src/routes/safe/components/Balances/SendModal/screens/ReviewCustomTx/index.jsx b/src/routes/safe/components/Balances/SendModal/screens/ReviewCustomTx/index.jsx index bfae7eb2..cc5d1df0 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ReviewCustomTx/index.jsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ReviewCustomTx/index.jsx @@ -13,8 +13,9 @@ import Button from '~/components/layout/Button' import Img from '~/components/layout/Img' import Block from '~/components/layout/Block' import Identicon from '~/components/Identicon' -import { copyToClipboard } from '~/utils/clipboard' import Hairline from '~/components/layout/Hairline' +import { type Variant } from '~/components/Header' +import { copyToClipboard } from '~/utils/clipboard' import SafeInfo from '~/routes/safe/components/Balances/SendModal/SafeInfo' import { setImageToPlaceholder } from '~/routes/safe/components/Balances/utils' import { getWeb3 } from '~/logic/wallets/getWeb3' @@ -33,7 +34,7 @@ type Props = { ethBalance: string, tx: Object, createTransaction: Function, - enqueueSnackbar: Function, + enqueueSnackbar: (message: string, variant: Variant) => void, } const openIconStyle = { diff --git a/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.jsx b/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.jsx index 1127c336..83b251df 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.jsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.jsx @@ -15,6 +15,7 @@ import Block from '~/components/layout/Block' import Identicon from '~/components/Identicon' import { copyToClipboard } from '~/utils/clipboard' import Hairline from '~/components/layout/Hairline' +import { type Variant } from '~/components/Header' import SafeInfo from '~/routes/safe/components/Balances/SendModal/SafeInfo' import { setImageToPlaceholder } from '~/routes/safe/components/Balances/utils' import { getStandardTokenContract } from '~/logic/tokens/store/actions/fetchTokens' @@ -35,7 +36,7 @@ type Props = { ethBalance: string, tx: Object, createTransaction: Function, - enqueueSnackbar: Function, + enqueueSnackbar: (message: string, variant: Variant) => void, } const openIconStyle = { diff --git a/src/routes/safe/components/Settings/ChangeSafeName/index.jsx b/src/routes/safe/components/Settings/ChangeSafeName/index.jsx index 7c368172..339a01f6 100644 --- a/src/routes/safe/components/Settings/ChangeSafeName/index.jsx +++ b/src/routes/safe/components/Settings/ChangeSafeName/index.jsx @@ -12,6 +12,7 @@ import GnoForm from '~/components/forms/GnoForm' import Row from '~/components/layout/Row' import Paragraph from '~/components/layout/Paragraph' import Button from '~/components/layout/Button' +import { type Variant } from '~/components/Header' import { styles } from './style' export const SAFE_NAME_INPUT_TEST_ID = 'safe-name-input' @@ -22,7 +23,7 @@ type Props = { safeAddress: string, safeName: string, updateSafe: Function, - enqueueSnackbar: Function, + enqueueSnackbar: (message: string, variant: Variant) => void, } const ChangeSafeName = (props: Props) => { diff --git a/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.jsx b/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.jsx index 893ba5db..064835c1 100644 --- a/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.jsx @@ -4,6 +4,7 @@ import { List } from 'immutable' import { withStyles } from '@material-ui/core/styles' import { withSnackbar } from 'notistack' import Modal from '~/components/Modal' +import { type Variant } from '~/components/Header' import { type Owner } from '~/routes/safe/store/models/owner' import { getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts' import OwnerForm from './screens/OwnerForm' @@ -29,7 +30,7 @@ type Props = { network: string, addSafeOwner: Function, createTransaction: Function, - enqueueSnackbar: Function, + enqueueSnackbar: (message: string, variant: Variant) => void, } type ActiveScreen = 'selectOwner' | 'selectThreshold' | 'reviewAddOwner' @@ -37,7 +38,7 @@ export const sendAddOwner = async ( values: Object, safeAddress: string, ownersOld: List, - enqueueSnackbar: Function, + enqueueSnackbar: (message: string, variant: Variant) => void, createTransaction: Function, addSafeOwner: Function, ) => { diff --git a/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/index.jsx b/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/index.jsx index a4be9c5d..a67014a5 100644 --- a/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/index.jsx @@ -4,6 +4,7 @@ import { List } from 'immutable' import { withStyles } from '@material-ui/core/styles' import { withSnackbar } from 'notistack' import Modal from '~/components/Modal' +import { type Variant } from '~/components/Header' import { type Owner } from '~/routes/safe/store/models/owner' import { getGnosisSafeInstanceAt, SENTINEL_ADDRESS } from '~/logic/contracts/safeContracts' import CheckOwner from './screens/CheckOwner' @@ -31,7 +32,7 @@ type Props = { network: string, createTransaction: Function, removeSafeOwner: Function, - enqueueSnackbar: Function, + enqueueSnackbar: (message: string, variant: Variant) => void, } type ActiveScreen = 'checkOwner' | 'selectThreshold' | 'reviewRemoveOwner' @@ -42,7 +43,7 @@ export const sendRemoveOwner = async ( ownerAddressToRemove: string, ownerNameToRemove: string, ownersOld: List, - enqueueSnackbar: Function, + enqueueSnackbar: (message: string, variant: Variant) => void, createTransaction: Function, removeSafeOwner: Function, ) => { diff --git a/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.jsx b/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.jsx index 26c63fb0..3d3fea1d 100644 --- a/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.jsx @@ -4,6 +4,7 @@ import { List } from 'immutable' import { withStyles } from '@material-ui/core/styles' import { withSnackbar } from 'notistack' import Modal from '~/components/Modal' +import { type Variant } from '~/components/Header' import { getGnosisSafeInstanceAt, SENTINEL_ADDRESS } from '~/logic/contracts/safeContracts' import OwnerForm from './screens/OwnerForm' import ReviewReplaceOwner from './screens/Review' @@ -29,7 +30,7 @@ type Props = { threshold: string, createTransaction: Function, replaceSafeOwner: Function, - enqueueSnackbar: Function, + enqueueSnackbar: (message: string, variant: Variant) => void, } type ActiveScreen = 'checkOwner' | 'reviewReplaceOwner' @@ -37,7 +38,7 @@ export const sendReplaceOwner = async ( values: Object, safeAddress: string, ownerAddressToRemove: string, - enqueueSnackbar: Function, + enqueueSnackbar: (message: string, variant: Variant) => void, createTransaction: Function, replaceSafeOwner: Function, ) => { diff --git a/src/routes/safe/components/Settings/ThresholdSettings/index.jsx b/src/routes/safe/components/Settings/ThresholdSettings/index.jsx index 44ec5e56..fd4a6fb1 100644 --- a/src/routes/safe/components/Settings/ThresholdSettings/index.jsx +++ b/src/routes/safe/components/Settings/ThresholdSettings/index.jsx @@ -10,10 +10,11 @@ import Block from '~/components/layout/Block' import Row from '~/components/layout/Row' import Modal from '~/components/Modal' import Paragraph from '~/components/layout/Paragraph' +import { type Variant } from '~/components/Header' import ChangeThreshold from './ChangeThreshold' import type { Owner } from '~/routes/safe/store/models/owner' -import { styles } from './style' import { getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts' +import { styles } from './style' type Props = { owners: List, @@ -22,7 +23,7 @@ type Props = { createTransaction: Function, safeAddress: string, granted: boolean, - enqueueSnackbar: Function, + enqueueSnackbar: (message: string, variant: Variant) => void, } const ThresholdSettings = ({ 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 03e44bbf..b33e343b 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/ApproveTxModal/index.jsx +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/ApproveTxModal/index.jsx @@ -13,6 +13,7 @@ import Row from '~/components/layout/Row' import Bold from '~/components/layout/Bold' import Block from '~/components/layout/Block' import Paragraph from '~/components/layout/Paragraph' +import { type Variant } from '~/components/Header' import { type Transaction } from '~/routes/safe/store/models/transaction' import { styles } from './style' @@ -29,7 +30,7 @@ type Props = { threshold: number, thresholdReached: boolean, userAddress: string, - enqueueSnackbar: Function, + enqueueSnackbar: (message: string, variant: Variant) => void, } const getModalTitleAndDescription = (thresholdReached: boolean) => { diff --git a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/CancelTxModal/index.jsx b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/CancelTxModal/index.jsx index 3086ec7d..124c424a 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/CancelTxModal/index.jsx +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/CancelTxModal/index.jsx @@ -13,6 +13,7 @@ import Block from '~/components/layout/Block' import Paragraph from '~/components/layout/Paragraph' import { type Transaction } from '~/routes/safe/store/models/transaction' import { EMPTY_DATA } from '~/logic/wallets/ethTransactions' +import { type Variant } from '~/components/Header' import { styles } from './style' type Props = { @@ -22,7 +23,7 @@ type Props = { createTransaction: Function, tx: Transaction, safeAddress: string, - enqueueSnackbar: Function, + enqueueSnackbar: (message: string, variant: Variant) => void, } const CancelTxModal = ({ diff --git a/src/routes/safe/store/actions/createTransaction.js b/src/routes/safe/store/actions/createTransaction.js index e3716c32..5be13b7a 100644 --- a/src/routes/safe/store/actions/createTransaction.js +++ b/src/routes/safe/store/actions/createTransaction.js @@ -12,13 +12,14 @@ import { type Notifications, DEFAULT_NOTIFICATIONS, } from '~/logic/safe/transactions' +import { type Variant } from '~/components/Header' const createTransaction = ( safeAddress: string, to: string, valueInWei: string, txData: string = EMPTY_DATA, - enqueueSnackbar: Function, + enqueueSnackbar: (message: string, variant: Variant) => void, shouldExecute?: boolean, notifications?: Notifications = DEFAULT_NOTIFICATIONS, ) => async (dispatch: ReduxDispatch, getState: GetState) => { diff --git a/src/routes/safe/store/actions/processTransaction.js b/src/routes/safe/store/actions/processTransaction.js index f31978bb..99b739c0 100644 --- a/src/routes/safe/store/actions/processTransaction.js +++ b/src/routes/safe/store/actions/processTransaction.js @@ -6,6 +6,7 @@ import fetchTransactions from '~/routes/safe/store/actions/fetchTransactions' import { type GlobalState } from '~/store' import { getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts' import { approveTransaction, executeTransaction, CALL } from '~/logic/safe/transactions' +import { type Variant } from '~/components/Header' // https://gnosis-safe.readthedocs.io/en/latest/contracts/signatures.html#pre-validated-signatures // https://github.com/gnosis/safe-contracts/blob/master/test/gnosisSafeTeamEdition.js#L26 @@ -31,7 +32,7 @@ const generateSignaturesFromTxConfirmations = (tx: Transaction, preApprovingOwne const processTransaction = ( safeAddress: string, tx: Transaction, - enqueueSnackbar: Function, + enqueueSnackbar: (message: string, variant: Variant) => void, userAddress: string, approveAndExecute?: boolean, ) => async (dispatch: ReduxDispatch, getState: GetState) => { From 42f971f32b0f87a35a7857da7a0c3b900dc5322a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Tue, 17 Sep 2019 20:37:08 +0200 Subject: [PATCH 15/50] Remove old Snackbar --- src/components/SnackbarContent/index.jsx | 110 ----------------------- src/theme/mui.js | 7 -- 2 files changed, 117 deletions(-) delete mode 100644 src/components/SnackbarContent/index.jsx diff --git a/src/components/SnackbarContent/index.jsx b/src/components/SnackbarContent/index.jsx deleted file mode 100644 index 7d6a4798..00000000 --- a/src/components/SnackbarContent/index.jsx +++ /dev/null @@ -1,110 +0,0 @@ -// @flow -import SnackbarContent from '@material-ui/core/SnackbarContent' -import classNames from 'classnames/bind' -import * as React from 'react' -import CloseIcon from '@material-ui/icons/Close' -import CheckCircleIcon from '@material-ui/icons/CheckCircle' -import ErrorIcon from '@material-ui/icons/Error' -import InfoIcon from '@material-ui/icons/Info' -import IconButton from '@material-ui/core/IconButton' -import { withStyles } from '@material-ui/core/styles' -import WarningIcon from '@material-ui/icons/Warning' -import { type WithStyles } from '~/theme/mui' -import { - secondary, warning, connected, error, -} from '~/theme/variables' - -type Variant = 'success' | 'error' | 'warning' | 'info' - -type MessageProps = WithStyles & { - variant: Variant, - message: string, -} - -type Props = MessageProps & { - onClose?: () => void, -} - -type CloseProps = WithStyles & { - onClose: () => void, -} - -const variantIcon = { - success: CheckCircleIcon, - warning: WarningIcon, - error: ErrorIcon, - info: InfoIcon, -} - -const styles = (theme) => ({ - success: { - backgroundColor: '#ffffff', - }, - successIcon: { - color: connected, - }, - warning: { - backgroundColor: '#fff3e2', - }, - warningIcon: { - color: warning, - }, - error: { - backgroundColor: '#ffe6ea', - }, - errorIcon: { - color: error, - }, - info: { - backgroundColor: '#ffffff', - }, - infoIcon: { - color: secondary, - }, - icon: { - fontSize: 20, - }, - iconVariant: { - opacity: 0.9, - marginRight: theme.spacing(1), - }, - message: { - display: 'flex', - alignItems: 'center', - }, -}) - -const Close = ({ classes, onClose }: CloseProps) => ( - - - -) - -const Message = ({ classes, message, variant }: MessageProps) => { - const Icon = variantIcon[variant] - - return ( - - - {message} - - ) -} - -const GnoSnackbarContent = ({ - variant, classes, message, onClose, -}: Props) => { - const action = onClose ? [] : undefined - const messageComponent = - - return ( - - ) -} - -export default withStyles(styles)(GnoSnackbarContent) diff --git a/src/theme/mui.js b/src/theme/mui.js index 01d96c8a..0b6cb1f3 100644 --- a/src/theme/mui.js +++ b/src/theme/mui.js @@ -199,13 +199,6 @@ export default createMuiTheme({ }, }, }, - MuiSnackbarContent: { - root: { - boxShadow: '0 0 10px 0 rgba(33, 48, 77, 0.1)', - borderRadius: '3px', - color: primary, - }, - }, MuiSvgIcon: { colorSecondary: { color: secondaryText, From 97348ca1a20d77ae19d4eb10818a89d0a39f50d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Wed, 18 Sep 2019 12:27:13 +0200 Subject: [PATCH 16/50] Declare new notifications --- src/logic/notifications/index.js | 105 +++++++++++++++++++ src/logic/safe/transactions/index.js | 1 - src/logic/safe/transactions/notifications.js | 14 --- 3 files changed, 105 insertions(+), 15 deletions(-) create mode 100644 src/logic/notifications/index.js delete mode 100644 src/logic/safe/transactions/notifications.js diff --git a/src/logic/notifications/index.js b/src/logic/notifications/index.js new file mode 100644 index 00000000..c2a60d59 --- /dev/null +++ b/src/logic/notifications/index.js @@ -0,0 +1,105 @@ +// @flow + +export type Notifications = { + // Default + BEFORE_EXECUTION_OR_CREATION: string, + AFTER_EXECUTION: string, + CREATED_MORE_CONFIRMATIONS_NEEDED: string, + ERROR: string, + + // Wallet Connection + CONNECT_WALLET_MSG: string, + CONNECT_WALLET_READ_MODE_MSG: string, + WALLET_CONNECTED_MSG: string, + UNLOCK_WALLET_MSG: string, + CONNECT_WALLET_ERROR_MSG: string, + + // Regular/Custom Transactions + SIGN_TX_MSG: string, + TX_PENDING_MSG: string, + TX_PENDING_MORE_CONFIRMATIONS_MSG: string, + TX_REJECTED_MSG: string, + TX_EXECUTED_MSG: string, + TX_FAILED_MSG: string, + + // Approval Transactions + TX_CONFIRMATION_PENDING_MSG: string, + TX_CONFIRMATION_EXECUTED_MSG: string, + TX_CONFIRMATION_FAILED_MSG: string, + + // Safe Name + SAFE_NAME_CHANGED_MSG: string, + + // Owners + SIGN_OWNER_CHANGE_MSG: string, + ONWER_CHANGE_PENDING_MSG: string, + ONWER_CHANGE_PENDING_MORE_CONFIRMATIONS_MSG: string, + ONWER_CHANGE_REJECTED_MSG: string, + ONWER_CHANGE_EXECUTED_MSG: string, + ONWER_CHANGE_FAILED_MSG: string, + + // Threshold + SIGN_THRESHOLD_CHANGE_MSG: string, + THRESHOLD_CHANGE_PENDING_MSG: string, + THRESHOLD_CHANGE_PENDING_MORE_CONFIRMATIONS_MSG: string, + THRESHOLD_CHANGE_REJECTED_MSG: string, + THRESHOLD_CHANGE_EXECUTED_MSG: string, + THRESHOLD_CHANGE_FAILED_MSG: string, + + // Rinkeby version + RINKEBY_VERSION_MSG: string, + WRONG_NETWORK_RINKEBY_MSG: string, + WRONG_NETWOEK_MAINNET_MSG: string, +} + +export const NOTIFICATIONS: Notifications = { + // Default + BEFORE_EXECUTION_OR_CREATION: 'Transaction in progress', + AFTER_EXECUTION: 'Transaction successfully executed', + CREATED_MORE_CONFIRMATIONS_NEEDED: 'Transaction in progress: More confirmations required to execute', + ERROR: 'Transaction failed', + + // Wallet Connection + CONNECT_WALLET_MSG: 'Please connect wallet to continue', + CONNECT_WALLET_READ_MODE_MSG: 'You are in read-only mode: Please connect wallet', + WALLET_CONNECTED_MSG: 'Wallet connected', + UNLOCK_WALLET_MSG: 'Unlock your wallet to connect', + CONNECT_WALLET_ERROR_MSG: 'Error connecting to your wallet', + + // Regular/Custom Transactions + SIGN_TX_MSG: 'Please sign the transaction', + TX_PENDING_MSG: 'Transaction pending', + TX_PENDING_MORE_CONFIRMATIONS_MSG: 'Transaction pending: More confirmations required to execute', + TX_REJECTED_MSG: 'Transaction rejected', + TX_EXECUTED_MSG: 'Transaction successfully executed', + TX_FAILED_MSG: 'Transaction failed', + + // Approval Transactions + TX_CONFIRMATION_PENDING_MSG: 'Confirmation transaction pending', + TX_CONFIRMATION_EXECUTED_MSG: 'Confirmation transaction succesful', + TX_CONFIRMATION_FAILED_MSG: 'Confirmation transaction failed', + + // Safe Name + SAFE_NAME_CHANGED_MSG: 'Safe name changed', + + // Owners + SIGN_OWNER_CHANGE_MSG: 'Please sign the owner change', + ONWER_CHANGE_PENDING_MSG: 'Owner change pending', + ONWER_CHANGE_PENDING_MORE_CONFIRMATIONS_MSG: 'Owner change pending: More confirmations required to execute', + ONWER_CHANGE_REJECTED_MSG: 'Owner change rejected', + ONWER_CHANGE_EXECUTED_MSG: 'Owner change successfully executed', + ONWER_CHANGE_FAILED_MSG: 'Owner change failed', + + // Threshold + SIGN_THRESHOLD_CHANGE_MSG: 'Please sign the required confirmations change', + THRESHOLD_CHANGE_PENDING_MSG: 'Required confirmations change pending', + THRESHOLD_CHANGE_PENDING_MORE_CONFIRMATIONS_MSG: 'Required confirmations change pending: More confirmations required to execute', + THRESHOLD_CHANGE_REJECTED_MSG: 'Required confirmations change rejected', + THRESHOLD_CHANGE_EXECUTED_MSG: 'Required confirmations change successfully executed', + THRESHOLD_CHANGE_FAILED_MSG: 'Required confirmations change failed', + + // Network + RINKEBY_VERSION_MSG: 'Rinkeby Version: Don\'t send mainnet assets to this Safe', + WRONG_NETWORK_RINKEBY_MSG: 'Wrong network: Please use Rinkeby', + WRONG_NETWOEK_MAINNET_MSG: 'Wrong network: Please use Mainnet', +} diff --git a/src/logic/safe/transactions/index.js b/src/logic/safe/transactions/index.js index 056e5633..a085a125 100644 --- a/src/logic/safe/transactions/index.js +++ b/src/logic/safe/transactions/index.js @@ -4,4 +4,3 @@ export * from './send' export * from './safeBlockchainOperations' export * from './safeTxSignerEIP712' export * from './txHistory' -export * from './notifications' diff --git a/src/logic/safe/transactions/notifications.js b/src/logic/safe/transactions/notifications.js deleted file mode 100644 index 65bdf16e..00000000 --- a/src/logic/safe/transactions/notifications.js +++ /dev/null @@ -1,14 +0,0 @@ -// @flow -export type Notifications = { - BEFORE_EXECUTION_OR_CREATION: string, - AFTER_EXECUTION: string, - CREATED_MORE_CONFIRMATIONS_NEEDED: string, - ERROR: string, -} - -export const DEFAULT_NOTIFICATIONS: Notifications = { - BEFORE_EXECUTION_OR_CREATION: 'Transaction in progress', - AFTER_EXECUTION: 'Transaction successfully executed', - CREATED_MORE_CONFIRMATIONS_NEEDED: 'Transaction in progress: More confirmations required to execute', - ERROR: 'Transaction failed', -} From 5b5d76b47655bc72c0a9617f9b5223074191581a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Wed, 18 Sep 2019 17:50:59 +0200 Subject: [PATCH 17/50] Add notification categories --- src/components/Header/index.jsx | 10 +++++----- .../wallets/store/actions/fetchProvider.js | 17 ++++++++++------ .../wallets/store/actions/removeProvider.js | 4 ++-- .../Settings/ChangeSafeName/index.jsx | 5 +++-- .../safe/store/actions/createTransaction.js | 20 ++++++++++--------- .../safe/store/actions/processTransaction.js | 10 +++++----- 6 files changed, 37 insertions(+), 29 deletions(-) diff --git a/src/components/Header/index.jsx b/src/components/Header/index.jsx index 82f6f614..a561f59f 100644 --- a/src/components/Header/index.jsx +++ b/src/components/Header/index.jsx @@ -14,10 +14,10 @@ import Layout from './component/Layout' import actions, { type Actions } from './actions' import selector, { type SelectorProps } from './selector' -const SUCCESS = 'SUCCESS' -const ERROR = 'ERROR' -const WARNING = 'WARNING' -const INFO = 'INFO' +export const SUCCESS = 'success' +export const ERROR = 'error' +export const WARNING = 'warning' +export const INFO = 'info' export type Variant = SUCCESS | ERROR | WARNING | INFO @@ -49,7 +49,7 @@ class HeaderComponent extends React.PureComponent { const { enqueueSnackbar } = this.props this.setState({ hasError: true }) - enqueueSnackbar(WALLET_ERROR_MSG, 'error') + enqueueSnackbar(WALLET_ERROR_MSG, { variant: ERROR }) logComponentStack(error, info) } diff --git a/src/logic/wallets/store/actions/fetchProvider.js b/src/logic/wallets/store/actions/fetchProvider.js index dd132543..7d10e41e 100644 --- a/src/logic/wallets/store/actions/fetchProvider.js +++ b/src/logic/wallets/store/actions/fetchProvider.js @@ -3,7 +3,9 @@ import type { Dispatch as ReduxDispatch } from 'redux' import { ETHEREUM_NETWORK_IDS, ETHEREUM_NETWORK } from '~/logic/wallets/getWeb3' import type { ProviderProps } from '~/logic/wallets/store/model/provider' import { makeProvider } from '~/logic/wallets/store/model/provider' -import { type Variant } from '~/components/Header' +import { + type Variant, SUCCESS, ERROR, WARNING, +} from '~/components/Header' import addProvider from './addProvider' export const processProviderResponse = (dispatch: ReduxDispatch<*>, provider: ProviderProps) => { @@ -22,9 +24,12 @@ export const processProviderResponse = (dispatch: ReduxDispatch<*>, provider: Pr dispatch(addProvider(walletRecord)) } -const SUCCESS_MSG = 'Wallet connected sucessfully' + +const CONNECT_WALLET_MSG = 'Please connect wallet to continue' +const CONNECT_WALLET_READ_MODE_MSG = 'You are in read-only mode: Please connect wallet' const UNLOCK_MSG = 'Unlock your wallet to connect' -const WRONG_NETWORK = 'You are connected to wrong network. Please use RINKEBY' +const WRONG_NETWORK_RINKEBY_MSG = 'Wrong network: Please use Rinkeby' +const SUCCESS_MSG = 'Wallet connected' export const WALLET_ERROR_MSG = 'Error connecting to your wallet' const handleProviderNotification = ( @@ -34,17 +39,17 @@ const handleProviderNotification = ( const { loaded, available, network } = provider if (!loaded) { - enqueueSnackbar(WALLET_ERROR_MSG, 'error') + enqueueSnackbar(WALLET_ERROR_MSG, { variant: ERROR }) return } if (ETHEREUM_NETWORK_IDS[network] !== ETHEREUM_NETWORK.RINKEBY) { - enqueueSnackbar(WRONG_NETWORK, 'error') + enqueueSnackbar(WRONG_NETWORK_RINKEBY_MSG, { variant: ERROR, persist: true }) return } const msg = available ? SUCCESS_MSG : UNLOCK_MSG - const variant = available ? 'success' : 'warning' + const variant = { variant: (available ? SUCCESS : WARNING) } enqueueSnackbar(msg, variant) } diff --git a/src/logic/wallets/store/actions/removeProvider.js b/src/logic/wallets/store/actions/removeProvider.js index 5bbe142f..99993d41 100644 --- a/src/logic/wallets/store/actions/removeProvider.js +++ b/src/logic/wallets/store/actions/removeProvider.js @@ -1,7 +1,7 @@ // @flow import type { Dispatch as ReduxDispatch } from 'redux' import { makeProvider, type ProviderProps, type Provider } from '~/logic/wallets/store/model/provider' -import { type Variant } from '~/components/Header' +import { type Variant, INFO } from '~/components/Header' import addProvider from './addProvider' export default (enqueueSnackbar: (message: string, variant: Variant) => void) => async (dispatch: ReduxDispatch<*>) => { @@ -14,7 +14,7 @@ export default (enqueueSnackbar: (message: string, variant: Variant) => void) => } const provider: Provider = makeProvider(providerProps) - enqueueSnackbar('Wallet disconnected succesfully', 'info') + enqueueSnackbar('Wallet disconnected succesfully', { variant: INFO }) dispatch(addProvider(provider)) } diff --git a/src/routes/safe/components/Settings/ChangeSafeName/index.jsx b/src/routes/safe/components/Settings/ChangeSafeName/index.jsx index 339a01f6..51d5ca13 100644 --- a/src/routes/safe/components/Settings/ChangeSafeName/index.jsx +++ b/src/routes/safe/components/Settings/ChangeSafeName/index.jsx @@ -12,7 +12,8 @@ import GnoForm from '~/components/forms/GnoForm' import Row from '~/components/layout/Row' import Paragraph from '~/components/layout/Paragraph' import Button from '~/components/layout/Button' -import { type Variant } from '~/components/Header' +import { type Variant, SUCCESS } from '~/components/Header' +import { NOTIFICATIONS } from '~/logic/notifications' import { styles } from './style' export const SAFE_NAME_INPUT_TEST_ID = 'safe-name-input' @@ -33,7 +34,7 @@ const ChangeSafeName = (props: Props) => { const handleSubmit = (values) => { updateSafe({ address: safeAddress, name: values.safeName }) - enqueueSnackbar('Safe name changed', 'success') + enqueueSnackbar(NOTIFICATIONS.SAFE_NAME_CHANGED_MSG, { variant: SUCCESS }) } return ( diff --git a/src/routes/safe/store/actions/createTransaction.js b/src/routes/safe/store/actions/createTransaction.js index 5be13b7a..ca81e81a 100644 --- a/src/routes/safe/store/actions/createTransaction.js +++ b/src/routes/safe/store/actions/createTransaction.js @@ -9,10 +9,12 @@ import { approveTransaction, executeTransaction, CALL, - type Notifications, - DEFAULT_NOTIFICATIONS, } from '~/logic/safe/transactions' -import { type Variant } from '~/components/Header' +import { + type Notifications, + NOTIFICATIONS, +} from '~/logic/notifications' +import { type Variant, SUCCESS, ERROR } from '~/components/Header' const createTransaction = ( safeAddress: string, @@ -21,7 +23,7 @@ const createTransaction = ( txData: string = EMPTY_DATA, enqueueSnackbar: (message: string, variant: Variant) => void, shouldExecute?: boolean, - notifications?: Notifications = DEFAULT_NOTIFICATIONS, + notifications?: Notifications = NOTIFICATIONS, ) => async (dispatch: ReduxDispatch, getState: GetState) => { const state: GlobalState = getState() @@ -34,16 +36,16 @@ const createTransaction = ( let txHash try { if (isExecution) { - const showNotification = () => enqueueSnackbar(notifications.BEFORE_EXECUTION_OR_CREATION, 'success') + const showNotification = () => enqueueSnackbar(notifications.BEFORE_EXECUTION_OR_CREATION, { variant: SUCCESS }) txHash = await executeTransaction(showNotification, safeInstance, to, valueInWei, txData, CALL, nonce, from) - enqueueSnackbar(notifications.AFTER_EXECUTION, 'success') + enqueueSnackbar(notifications.AFTER_EXECUTION, { variant: SUCCESS }) } else { - const showNotification = () => enqueueSnackbar(notifications.BEFORE_EXECUTION_OR_CREATION, 'success') + const showNotification = () => enqueueSnackbar(notifications.BEFORE_EXECUTION_OR_CREATION, { variant: SUCCESS }) txHash = await approveTransaction(showNotification, safeInstance, to, valueInWei, txData, CALL, nonce, from) - enqueueSnackbar(notifications.CREATED_MORE_CONFIRMATIONS_NEEDED, 'success') + enqueueSnackbar(notifications.CREATED_MORE_CONFIRMATIONS_NEEDED, { variant: SUCCESS }) } } catch (err) { - enqueueSnackbar(notifications.ERROR, 'error') + enqueueSnackbar(notifications.ERROR, { variant: ERROR }) console.error(`Error while creating transaction: ${err}`) } diff --git a/src/routes/safe/store/actions/processTransaction.js b/src/routes/safe/store/actions/processTransaction.js index 99b739c0..ead68054 100644 --- a/src/routes/safe/store/actions/processTransaction.js +++ b/src/routes/safe/store/actions/processTransaction.js @@ -6,7 +6,7 @@ import fetchTransactions from '~/routes/safe/store/actions/fetchTransactions' import { type GlobalState } from '~/store' import { getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts' import { approveTransaction, executeTransaction, CALL } from '~/logic/safe/transactions' -import { type Variant } from '~/components/Header' +import { type Variant, SUCCESS } from '~/components/Header' // https://gnosis-safe.readthedocs.io/en/latest/contracts/signatures.html#pre-validated-signatures // https://github.com/gnosis/safe-contracts/blob/master/test/gnosisSafeTeamEdition.js#L26 @@ -47,7 +47,7 @@ const processTransaction = ( let txHash if (shouldExecute) { - const showNotification = () => enqueueSnackbar('Transaction has been submitted', 'success') + const showNotification = () => enqueueSnackbar('Transaction has been submitted', { variant: SUCCESS }) txHash = await executeTransaction( showNotification, safeInstance, @@ -59,9 +59,9 @@ const processTransaction = ( from, sigs, ) - enqueueSnackbar('Transaction has been confirmed', 'success') + enqueueSnackbar('Transaction has been confirmed', { variant: SUCCESS }) } else { - const showNotification = () => enqueueSnackbar('Approval transaction has been submitted', 'success') + const showNotification = () => enqueueSnackbar('Approval transaction has been submitted', { variant: SUCCESS }) txHash = await approveTransaction( showNotification, safeInstance, @@ -72,7 +72,7 @@ const processTransaction = ( nonce, from, ) - enqueueSnackbar('Approval transaction has been confirmed', 'success') + enqueueSnackbar('Approval transaction has been confirmed', { variant: SUCCESS }) } dispatch(fetchTransactions(safeAddress)) From 4877c419081facecc023d7aa72749acced2dcef0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Wed, 18 Sep 2019 18:44:24 +0200 Subject: [PATCH 18/50] Update dependencies --- package.json | 16 ++--- yarn.lock | 189 +++++++++++++++++++++++++++++++-------------------- 2 files changed, 123 insertions(+), 82 deletions(-) diff --git a/package.json b/package.json index 13e9f7fd..115879fb 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "immortal-db": "^1.0.2", "immutable": "^4.0.0-rc.9", "material-ui-search-bar": "^1.0.0-beta.13", - "notistack": "^0.9.0", + "notistack": "^0.9.2", "optimize-css-assets-webpack-plugin": "5.0.3", "qrcode.react": "^0.9.3", "react": "16.9.0", @@ -65,8 +65,8 @@ "web3": "1.2.1" }, "devDependencies": { - "@babel/cli": "7.6.0", - "@babel/core": "7.6.0", + "@babel/cli": "7.6.2", + "@babel/core": "7.6.2", "@babel/plugin-proposal-class-properties": "7.5.5", "@babel/plugin-proposal-decorators": "7.6.0", "@babel/plugin-proposal-do-expressions": "7.6.0", @@ -86,10 +86,10 @@ "@babel/plugin-transform-member-expression-literals": "^7.2.0", "@babel/plugin-transform-property-literals": "^7.2.0", "@babel/polyfill": "7.6.0", - "@babel/preset-env": "7.6.0", - "@babel/preset-flow": "^7.0.0-beta.40", - "@babel/preset-react": "^7.0.0-beta.40", - "@sambego/storybook-state": "^1.0.7", + "@babel/preset-env": "7.6.2", + "@babel/preset-flow": "^7.0.0", + "@babel/preset-react": "^7.0.0", + "@sambego/storybook-state": "^1.3.6", "@storybook/addon-actions": "5.2.1", "@storybook/addon-knobs": "5.2.1", "@storybook/addon-links": "5.2.1", @@ -142,6 +142,6 @@ "webpack-bundle-analyzer": "3.5.1", "webpack-cli": "3.3.9", "webpack-dev-server": "3.8.1", - "webpack-manifest-plugin": "^2.0.0-rc.2" + "webpack-manifest-plugin": "^2.1.0" } } diff --git a/yarn.lock b/yarn.lock index f8477bd9..f5084b74 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@babel/cli@7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.6.0.tgz#1470a04394eaf37862989ea4912adf440fa6ff8d" - integrity sha512-1CTDyGUjQqW3Mz4gfKZ04KGOckyyaNmKneAMlABPS+ZyuxWv3FrVEVz7Ag08kNIztVx8VaJ8YgvYLSNlMKAT5Q== +"@babel/cli@7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.6.2.tgz#4ce8b5b4b2e4b4c1b7bd841cec62085e2dfc4465" + integrity sha512-JDZ+T/br9pPfT2lmAMJypJDTTTHM9ePD/ED10TRjRzJVdEVy+JB3iRlhzYmTt5YkNgHvxWGlUVnLtdv6ruiDrQ== dependencies: commander "^2.8.1" convert-source-map "^1.1.0" @@ -53,17 +53,17 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.6.0.tgz#9b00f73554edd67bebc86df8303ef678be3d7b48" - integrity sha512-FuRhDRtsd6IptKpHXAa+4WPZYY2ZzgowkbLBecEDDSje1X/apG7jQM33or3NdOmjXBKWGOg4JmSiRfUfuTtHXw== +"@babel/core@7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.6.2.tgz#069a776e8d5e9eefff76236bc8845566bd31dd91" + integrity sha512-l8zto/fuoZIbncm+01p8zPSDZu/VuuJhAfA7d/AbzM09WR7iVhavvfNDYCNpo1VvLk6E6xgAoP9P+/EMJHuRkQ== dependencies: "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.6.0" - "@babel/helpers" "^7.6.0" - "@babel/parser" "^7.6.0" + "@babel/generator" "^7.6.2" + "@babel/helpers" "^7.6.2" + "@babel/parser" "^7.6.2" "@babel/template" "^7.6.0" - "@babel/traverse" "^7.6.0" + "@babel/traverse" "^7.6.2" "@babel/types" "^7.6.0" convert-source-map "^1.1.0" debug "^4.1.0" @@ -104,16 +104,15 @@ source-map "^0.5.0" trim-right "^1.0.1" -"@babel/generator@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.6.0.tgz#e2c21efbfd3293ad819a2359b448f002bfdfda56" - integrity sha512-Ms8Mo7YBdMMn1BYuNtKuP/z0TgEIhbcyB8HVR6PPNYp4P61lMsABiS4A3VG1qznjXVCf3r+fVHhm4efTYVsySA== +"@babel/generator@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.6.2.tgz#dac8a3c2df118334c2a29ff3446da1636a8f8c03" + integrity sha512-j8iHaIW4gGPnViaIHI7e9t/Hl8qLjERI6DcV9kEpAIDJsAOrcnXqRS7t+QbhL76pwbtqP+QCQLL0z1CyVmtjjQ== dependencies: "@babel/types" "^7.6.0" jsesc "^2.5.1" lodash "^4.17.13" source-map "^0.5.0" - trim-right "^1.0.1" "@babel/helper-annotate-as-pure@^7.0.0": version "7.0.0" @@ -311,13 +310,13 @@ "@babel/traverse" "^7.5.5" "@babel/types" "^7.5.5" -"@babel/helpers@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.6.0.tgz#21961d16c6a3c3ab597325c34c465c0887d31c6e" - integrity sha512-W9kao7OBleOjfXtFGgArGRX6eCP0UEcA2ZWEWNkJdRZnHhW4eEbeswbG3EwaRsnQUAEGWYgMq1HsIXuNNNy2eQ== +"@babel/helpers@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.6.2.tgz#681ffe489ea4dcc55f23ce469e58e59c1c045153" + integrity sha512-3/bAUL8zZxYs1cdX2ilEE0WobqbCmKWr/889lf2SS0PpDcpEIY8pb1CCyz0pEcX3pEb+MCbks1jIokz2xLtGTA== dependencies: "@babel/template" "^7.6.0" - "@babel/traverse" "^7.6.0" + "@babel/traverse" "^7.6.2" "@babel/types" "^7.6.0" "@babel/highlight@^7.0.0": @@ -339,6 +338,11 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.0.tgz#3e05d0647432a8326cb28d0de03895ae5a57f39b" integrity sha512-+o2q111WEx4srBs7L9eJmcwi655eD8sXniLqMB93TBK9GrNzGrxDWSjiqz2hLU0Ha8MTXFIP0yd9fNdP+m43ZQ== +"@babel/parser@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.2.tgz#205e9c95e16ba3b8b96090677a67c9d6075b70a1" + integrity sha512-mdFqWrSPCmikBoaBYMuBulzTIKuXVPtEISFbRRVNwMWpCms/hmE2kRq0bblUHaNRKrjRlmVbx1sDHmjmRgD2Xg== + "@babel/plugin-proposal-async-generator-functions@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz#b289b306669dce4ad20b0252889a15768c9d417e" @@ -479,6 +483,14 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-object-rest-spread" "^7.2.0" +"@babel/plugin-proposal-object-rest-spread@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.6.2.tgz#8ffccc8f3a6545e9f78988b6bf4fe881b88e8096" + integrity sha512-LDBXlmADCsMZV1Y9OQwMc0MyGZ8Ta/zlD9N67BfQT8uYwkRswiu2hU6nJKrjrt/58aH/vqfQlR/9yId/7A2gWw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-object-rest-spread" "^7.2.0" + "@babel/plugin-proposal-optional-catch-binding@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz#135d81edb68a081e55e56ec48541ece8065c38f5" @@ -520,6 +532,15 @@ "@babel/helper-regex" "^7.4.4" regexpu-core "^4.5.4" +"@babel/plugin-proposal-unicode-property-regex@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.6.2.tgz#05413762894f41bfe42b9a5e80919bd575dcc802" + integrity sha512-NxHETdmpeSCtiatMRYWVJo7266rrvAC3DTeG5exQBIH/fMIUK7ejDNznBbn3HQl/o9peymRRg7Yqkx6PdUXmMw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-regex" "^7.4.4" + regexpu-core "^4.6.0" + "@babel/plugin-syntax-async-generators@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz#69e1f0db34c6f5a0cf7e2b3323bf159a76c8cb7f" @@ -698,10 +719,10 @@ "@babel/helper-plugin-utils" "^7.0.0" lodash "^4.17.13" -"@babel/plugin-transform-block-scoping@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.6.0.tgz#c49e21228c4bbd4068a35667e6d951c75439b1dc" - integrity sha512-tIt4E23+kw6TgL/edACZwP1OUKrjOTyMrFMLoT5IOFrfMRabCgekjqFd5o6PaAMildBu46oFkekIdMuGkkPEpA== +"@babel/plugin-transform-block-scoping@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.6.2.tgz#96c33ab97a9ae500cc6f5b19e04a7e6553360a79" + integrity sha512-zZT8ivau9LOQQaOGC7bQLQOT4XPkPXgN2ERfUgk1X8ql+mVkLc4E8eKk+FO3o0154kxzqenWCorfmEXpEZcrSQ== dependencies: "@babel/helper-plugin-utils" "^7.0.0" lodash "^4.17.13" @@ -771,6 +792,15 @@ "@babel/helper-regex" "^7.4.4" regexpu-core "^4.5.4" +"@babel/plugin-transform-dotall-regex@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.6.2.tgz#44abb948b88f0199a627024e1508acaf8dc9b2f9" + integrity sha512-KGKT9aqKV+9YMZSkowzYoYEiHqgaDhGmPNZlZxX6UeHC4z30nC1J9IrZuGqbYFB1jaIGdv91ujpze0exiVK8bA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-regex" "^7.4.4" + regexpu-core "^4.6.0" + "@babel/plugin-transform-duplicate-keys@^7.2.0", "@babel/plugin-transform-duplicate-keys@^7.5.0": version "7.5.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.5.0.tgz#c5dbf5106bf84cdf691222c0974c12b1df931853" @@ -884,12 +914,12 @@ dependencies: regexp-tree "^0.1.6" -"@babel/plugin-transform-named-capturing-groups-regex@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.6.0.tgz#1e6e663097813bb4f53d42df0750cf28ad3bb3f1" - integrity sha512-jem7uytlmrRl3iCAuQyw8BpB4c4LWvSpvIeXKpMb+7j84lkx4m4mYr5ErAcmN5KM7B6BqrAvRGjBIbbzqCczew== +"@babel/plugin-transform-named-capturing-groups-regex@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.6.2.tgz#c1ca0bb84b94f385ca302c3932e870b0fb0e522b" + integrity sha512-xBdB+XOs+lgbZc2/4F5BVDVcDNS4tcSKQc96KmlqLEAwz6tpYPEvPdmDfvVG0Ssn8lAhronaRs6Z6KSexIpK5g== dependencies: - regexp-tree "^0.1.13" + regexpu-core "^4.6.0" "@babel/plugin-transform-new-target@^7.4.0", "@babel/plugin-transform-new-target@^7.4.4": version "7.4.4" @@ -1008,6 +1038,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-spread@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.6.2.tgz#fc77cf798b24b10c46e1b51b1b88c2bf661bb8dd" + integrity sha512-DpSvPFryKdK1x+EDJYCy28nmAaIMdxmhot62jAXF/o99iA33Zj2Lmcp3vDmz+MUh0LNYVPvfj5iC3feb3/+PFg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-transform-sticky-regex@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz#a1e454b5995560a9c1e0d537dfc15061fd2687e1" @@ -1049,6 +1086,15 @@ "@babel/helper-regex" "^7.4.4" regexpu-core "^4.5.4" +"@babel/plugin-transform-unicode-regex@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.6.2.tgz#b692aad888a7e8d8b1b214be6b9dc03d5031f698" + integrity sha512-orZI6cWlR3nk2YmYdb0gImrgCUwb5cBUwjf6Ks6dvNVvXERkwtJWOQaEOjPiu0Gu1Tq6Yq/hruCZZOOi9F34Dw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-regex" "^7.4.4" + regexpu-core "^4.6.0" + "@babel/polyfill@7.6.0": version "7.6.0" resolved "https://registry.yarnpkg.com/@babel/polyfill/-/polyfill-7.6.0.tgz#6d89203f8b6cd323e8d946e47774ea35dc0619cc" @@ -1111,19 +1157,19 @@ js-levenshtein "^1.1.3" semver "^5.5.0" -"@babel/preset-env@7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.6.0.tgz#aae4141c506100bb2bfaa4ac2a5c12b395619e50" - integrity sha512-1efzxFv/TcPsNXlRhMzRnkBFMeIqBBgzwmZwlFDw5Ubj0AGLeufxugirwZmkkX/ayi3owsSqoQ4fw8LkfK9SYg== +"@babel/preset-env@7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.6.2.tgz#abbb3ed785c7fe4220d4c82a53621d71fc0c75d3" + integrity sha512-Ru7+mfzy9M1/YTEtlDS8CD45jd22ngb9tXnn64DvQK3ooyqSw9K4K9DUWmYknTTVk4TqygL9dqCrZgm1HMea/Q== dependencies: "@babel/helper-module-imports" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-proposal-async-generator-functions" "^7.2.0" "@babel/plugin-proposal-dynamic-import" "^7.5.0" "@babel/plugin-proposal-json-strings" "^7.2.0" - "@babel/plugin-proposal-object-rest-spread" "^7.5.5" + "@babel/plugin-proposal-object-rest-spread" "^7.6.2" "@babel/plugin-proposal-optional-catch-binding" "^7.2.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" + "@babel/plugin-proposal-unicode-property-regex" "^7.6.2" "@babel/plugin-syntax-async-generators" "^7.2.0" "@babel/plugin-syntax-dynamic-import" "^7.2.0" "@babel/plugin-syntax-json-strings" "^7.2.0" @@ -1132,11 +1178,11 @@ "@babel/plugin-transform-arrow-functions" "^7.2.0" "@babel/plugin-transform-async-to-generator" "^7.5.0" "@babel/plugin-transform-block-scoped-functions" "^7.2.0" - "@babel/plugin-transform-block-scoping" "^7.6.0" + "@babel/plugin-transform-block-scoping" "^7.6.2" "@babel/plugin-transform-classes" "^7.5.5" "@babel/plugin-transform-computed-properties" "^7.2.0" "@babel/plugin-transform-destructuring" "^7.6.0" - "@babel/plugin-transform-dotall-regex" "^7.4.4" + "@babel/plugin-transform-dotall-regex" "^7.6.2" "@babel/plugin-transform-duplicate-keys" "^7.5.0" "@babel/plugin-transform-exponentiation-operator" "^7.2.0" "@babel/plugin-transform-for-of" "^7.4.4" @@ -1147,7 +1193,7 @@ "@babel/plugin-transform-modules-commonjs" "^7.6.0" "@babel/plugin-transform-modules-systemjs" "^7.5.0" "@babel/plugin-transform-modules-umd" "^7.2.0" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.6.0" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.6.2" "@babel/plugin-transform-new-target" "^7.4.4" "@babel/plugin-transform-object-super" "^7.5.5" "@babel/plugin-transform-parameters" "^7.4.4" @@ -1155,11 +1201,11 @@ "@babel/plugin-transform-regenerator" "^7.4.5" "@babel/plugin-transform-reserved-words" "^7.2.0" "@babel/plugin-transform-shorthand-properties" "^7.2.0" - "@babel/plugin-transform-spread" "^7.2.0" + "@babel/plugin-transform-spread" "^7.6.2" "@babel/plugin-transform-sticky-regex" "^7.2.0" "@babel/plugin-transform-template-literals" "^7.4.4" "@babel/plugin-transform-typeof-symbol" "^7.2.0" - "@babel/plugin-transform-unicode-regex" "^7.4.4" + "@babel/plugin-transform-unicode-regex" "^7.6.2" "@babel/types" "^7.6.0" browserslist "^4.6.0" core-js-compat "^3.1.1" @@ -1319,16 +1365,16 @@ globals "^11.1.0" lodash "^4.17.13" -"@babel/traverse@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.6.0.tgz#389391d510f79be7ce2ddd6717be66d3fed4b516" - integrity sha512-93t52SaOBgml/xY74lsmt7xOR4ufYvhb5c5qiM6lu4J/dWGMAfAh6eKw4PjLes6DI6nQgearoxnFJk60YchpvQ== +"@babel/traverse@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.6.2.tgz#b0e2bfd401d339ce0e6c05690206d1e11502ce2c" + integrity sha512-8fRE76xNwNttVEF2TwxJDGBLWthUkHWSldmfuBzVRmEDWOtu4XdINTgN7TDWzuLg4bbeIMLvfMFD9we5YcWkRQ== dependencies: "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.6.0" + "@babel/generator" "^7.6.2" "@babel/helper-function-name" "^7.1.0" "@babel/helper-split-export-declaration" "^7.4.4" - "@babel/parser" "^7.6.0" + "@babel/parser" "^7.6.2" "@babel/types" "^7.6.0" debug "^4.1.0" globals "^11.1.0" @@ -1425,13 +1471,6 @@ dependencies: "@emotion/memoize" "0.7.2" -"@emotion/is-prop-valid@0.8.3": - version "0.8.3" - resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.3.tgz#cbe62ddbea08aa022cdf72da3971570a33190d29" - integrity sha512-We7VBiltAJ70KQA0dWkdPMXnYoizlxOXpvtjmu5/MBnExd+u0PGgV27WCYanmLAbCwAU30Le/xA0CQs/F/Otig== - dependencies: - "@emotion/memoize" "0.7.3" - "@emotion/memoize@0.7.2": version "0.7.2" resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.2.tgz#7f4c71b7654068dfcccad29553520f984cc66b30" @@ -1520,11 +1559,6 @@ resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.3.tgz#dfa0c92efe44a1d1a7974fb49ffeb40ef2da5a27" integrity sha512-zVgvPwGK7c1aVdUVc9Qv7SqepOGRDrqCw7KZPSZziWGxSlbII3gmvGLPzLX4d0n0BMbamBacUrN22zOMyFFEkQ== -"@emotion/weak-memoize@0.2.4": - version "0.2.4" - resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.4.tgz#622a72bebd1e3f48d921563b4b60a762295a81fc" - integrity sha512-6PYY5DVdAY1ifaQW6XYTnOMihmBVT27elqSjEoodchsGjzYlEsTQMcEhSud99kVawatyTZRTiVkJ/c6lwbQ7nA== - "@gnosis.pm/safe-contracts@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@gnosis.pm/safe-contracts/-/safe-contracts-1.0.0.tgz#2b562b1e23a0da1047a9f38ef71a70f811e75dd9" @@ -12883,10 +12917,10 @@ normalize-url@^4.1.0: resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.3.0.tgz#9c49e10fc1876aeb76dba88bf1b2b5d9fa57b2ee" integrity sha512-0NLtR71o4k6GLP+mr6Ty34c5GA6CMoEsncKJxvQd8NzPxaHRJNnb5gZE8R1XF4CPIS7QPHLJ74IFszwtNVAHVQ== -notistack@^0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/notistack/-/notistack-0.9.0.tgz#d195a186f5f25f7316b9e89a91ae3abe1072125e" - integrity sha512-3SrMUuJIAn4YtxvHlY6mjYDoQ+NQnozeQUOub5ywc+WEb8n85i/9PO/vqD9lGBXINEgN34B+YEA34oo7yeGYVQ== +notistack@^0.9.2: + version "0.9.2" + resolved "https://registry.yarnpkg.com/notistack/-/notistack-0.9.2.tgz#333ca7e08e85ae10867b1e8be5d82b149676aad6" + integrity sha512-Z2zi3ankqvwmrQvUx7SHM2X3P8llbPA/O1nM1hqn2fGuffn40Fi8isw701pdxczxA6S7huSyfOE/ZPgeTpWmrQ== dependencies: classnames "^2.2.6" hoist-non-react-statics "^3.3.0" @@ -15299,7 +15333,7 @@ refractor@^2.4.1: parse-entities "^1.1.2" prismjs "~1.16.0" -regenerate-unicode-properties@^8.0.2: +regenerate-unicode-properties@^8.0.2, regenerate-unicode-properties@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e" integrity sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA== @@ -15362,11 +15396,6 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" -regexp-tree@^0.1.13: - version "0.1.13" - resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.13.tgz#5b19ab9377edc68bc3679256840bb29afc158d7f" - integrity sha512-hwdV/GQY5F8ReLZWO+W1SRoN5YfpOKY6852+tBFcma72DKBIcHjPRIlIvQN35bCOljuAfP2G2iB0FC/w236mUw== - regexp-tree@^0.1.6: version "0.1.11" resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.11.tgz#c9c7f00fcf722e0a56c7390983a7a63dd6c272f3" @@ -15405,6 +15434,18 @@ regexpu-core@^4.5.4: unicode-match-property-ecmascript "^1.0.4" unicode-match-property-value-ecmascript "^1.1.0" +regexpu-core@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.6.0.tgz#2037c18b327cfce8a6fea2a4ec441f2432afb8b6" + integrity sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg== + dependencies: + regenerate "^1.4.0" + regenerate-unicode-properties "^8.1.0" + regjsgen "^0.5.0" + regjsparser "^0.6.0" + unicode-match-property-ecmascript "^1.0.4" + unicode-match-property-value-ecmascript "^1.1.0" + regjsgen@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" @@ -19780,10 +19821,10 @@ webpack-log@^2.0.0: ansi-colors "^3.0.0" uuid "^3.3.2" -webpack-manifest-plugin@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/webpack-manifest-plugin/-/webpack-manifest-plugin-2.0.4.tgz#e4ca2999b09557716b8ba4475fb79fab5986f0cd" - integrity sha512-nejhOHexXDBKQOj/5v5IZSfCeTO3x1Dt1RZEcGfBSul891X/eLIcIVH31gwxPDdsi2Z8LKKFGpM4w9+oTBOSCg== +webpack-manifest-plugin@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/webpack-manifest-plugin/-/webpack-manifest-plugin-2.1.0.tgz#5c7c6b3bcfc28fa4a32bcd63c739a83a04eb41bf" + integrity sha512-vQn/mY9okBQUim6fQo+8lYzn/MWcSMGbGpQyKIR6c6NF++lVxfzdlZBL0FGVQsb1RFL/rPdKwu6hkbtWv6CEYg== dependencies: fs-extra "^7.0.0" lodash ">=3.5 <5" From 55f97b2e813bee1226b115707d6bc0e53ba5c0e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Wed, 18 Sep 2019 19:02:35 +0200 Subject: [PATCH 19/50] Update notifications styles --- .../layout/PageFrame/assets/alert.svg | 6 ++ .../layout/PageFrame/assets/check.svg | 6 ++ .../layout/PageFrame/assets/error.svg | 6 ++ src/components/layout/PageFrame/index.jsx | 81 +++++++++++++++---- src/components/layout/PageFrame/index.scss | 16 ---- src/theme/mui.js | 12 +++ 6 files changed, 95 insertions(+), 32 deletions(-) create mode 100644 src/components/layout/PageFrame/assets/alert.svg create mode 100644 src/components/layout/PageFrame/assets/check.svg create mode 100644 src/components/layout/PageFrame/assets/error.svg diff --git a/src/components/layout/PageFrame/assets/alert.svg b/src/components/layout/PageFrame/assets/alert.svg new file mode 100644 index 00000000..0e20a926 --- /dev/null +++ b/src/components/layout/PageFrame/assets/alert.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/components/layout/PageFrame/assets/check.svg b/src/components/layout/PageFrame/assets/check.svg new file mode 100644 index 00000000..ad3cd87b --- /dev/null +++ b/src/components/layout/PageFrame/assets/check.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/components/layout/PageFrame/assets/error.svg b/src/components/layout/PageFrame/assets/error.svg new file mode 100644 index 00000000..b4948e8f --- /dev/null +++ b/src/components/layout/PageFrame/assets/error.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/components/layout/PageFrame/index.jsx b/src/components/layout/PageFrame/index.jsx index 126e774f..5ff4c89f 100644 --- a/src/components/layout/PageFrame/index.jsx +++ b/src/components/layout/PageFrame/index.jsx @@ -2,31 +2,80 @@ import * as React from 'react' import { SnackbarProvider } from 'notistack' import SidebarProvider from '~/components/Sidebar' -import Footer from '~/components/Footer' +import { withStyles } from '@material-ui/core/styles' import Header from '~/components/Header' +import Img from '~/components/layout/Img' +import AlertLogo from './assets/alert.svg' +import CheckLogo from './assets/check.svg' +import ErrorLogo from './assets/error.svg' import styles from './index.scss' +const classes = { + success: { + background: '#ffffff', + fontFamily: 'Averta', + fontSize: '14px', + lineHeight: 1.43, + color: '#001428', + minHeight: '58px', + boxShadow: '0 0 10px 0 rgba(212, 212, 211, 0.59)', + }, + error: { + background: '#ffe6ea', + fontFamily: 'Averta', + fontSize: '14px', + lineHeight: 1.43, + color: '#001428', + minHeight: '58px', + boxShadow: '0 0 10px 0 rgba(212, 212, 211, 0.59)', + }, + warning: { + background: '#fff3e2', + fontFamily: 'Averta', + fontSize: '14px', + lineHeight: 1.43, + color: '#001428', + minHeight: '58px', + boxShadow: '0 0 10px 0 rgba(212, 212, 211, 0.59)', + }, + info: { + background: '#e8673c', + fontFamily: 'Averta', + fontSize: '14px', + lineHeight: 1.43, + color: '#001428', + minHeight: '58px', + boxShadow: '0 0 10px 0 rgba(212, 212, 211, 0.59)', + }, +} + type Props = { children: React.Node, } -const PageFrame = ({ children }: Props) => ( - -
+const PageFrame = ({ children, classes }: Props) => ( +
+ , + error: , + warning: , + }} + ><>
{children} - -
- + + +
) -export default PageFrame +export default withStyles(classes)(PageFrame) diff --git a/src/components/layout/PageFrame/index.scss b/src/components/layout/PageFrame/index.scss index 54ceec03..9727c40e 100644 --- a/src/components/layout/PageFrame/index.scss +++ b/src/components/layout/PageFrame/index.scss @@ -4,19 +4,3 @@ flex: 1 1 auto; max-width: 100%; } - -.success { - background: 'purple'; -} - -.error { - background: 'blue'; -} - -.warning { - background: 'green'; -} - -.info { - background: 'yellow'; -} diff --git a/src/theme/mui.js b/src/theme/mui.js index 0b6cb1f3..aa7dbebe 100644 --- a/src/theme/mui.js +++ b/src/theme/mui.js @@ -204,6 +204,18 @@ export default createMuiTheme({ color: secondaryText, }, }, + /* MuiSnackbar: { + anchorOriginTopRight: { + marginTop: '50px', + }, + }, */ + MuiSnackbarContent: { + message: { + '& img': { + marginRight: '5px', + }, + }, + }, MuiTab: { root: { fontFamily: 'Averta, monospace', From 92d71625477102c576e7bf59f3a0f8c5a3004439 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Fri, 20 Sep 2019 10:04:05 +0200 Subject: [PATCH 20/50] Define all notification types --- src/logic/notifications/notificationTypes.js | 213 +++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 src/logic/notifications/notificationTypes.js diff --git a/src/logic/notifications/notificationTypes.js b/src/logic/notifications/notificationTypes.js new file mode 100644 index 00000000..8a529bad --- /dev/null +++ b/src/logic/notifications/notificationTypes.js @@ -0,0 +1,213 @@ +// @flow +export const SUCCESS = 'success' +export const ERROR = 'error' +export const WARNING = 'warning' +export const INFO = 'info' + +const shortDuration = 5000 +const longDuration = 10000 + +export type Variant = SUCCESS | ERROR | WARNING | INFO + +export type Notification = { + description: string, + variant: Variant, + persist: boolean, + autoHideDuration?: shortDuration | longDuration, +} + +export type Notifications = { + // Wallet Connection + CONNECT_WALLET_MSG: string, + CONNECT_WALLET_READ_MODE_MSG: string, + WALLET_CONNECTED_MSG: string, + UNLOCK_WALLET_MSG: string, + CONNECT_WALLET_ERROR_MSG: string, + + // Regular/Custom Transactions + SIGN_TX_MSG: Notification, + TX_PENDING_MSG: Notification, + TX_PENDING_MORE_CONFIRMATIONS_MSG: Notification, + TX_REJECTED_MSG: Notification, + TX_EXECUTED_MSG: Notification, + TX_FAILED_MSG: Notification, + + // Approval Transactions + TX_CONFIRMATION_PENDING_MSG: string, + TX_CONFIRMATION_EXECUTED_MSG: string, + TX_CONFIRMATION_FAILED_MSG: string, + + // Safe Name + SAFE_NAME_CHANGED_MSG: string, + + // Owner Name + OWNER_NAME_CHANGE_EXECUTED_MSG: string, + + // Owners + SIGN_OWNER_CHANGE_MSG: string, + ONWER_CHANGE_PENDING_MSG: string, + ONWER_CHANGE_PENDING_MORE_CONFIRMATIONS_MSG: string, + ONWER_CHANGE_REJECTED_MSG: string, + ONWER_CHANGE_EXECUTED_MSG: string, + ONWER_CHANGE_FAILED_MSG: string, + + // Threshold + SIGN_THRESHOLD_CHANGE_MSG: string, + THRESHOLD_CHANGE_PENDING_MSG: string, + THRESHOLD_CHANGE_PENDING_MORE_CONFIRMATIONS_MSG: string, + THRESHOLD_CHANGE_REJECTED_MSG: string, + THRESHOLD_CHANGE_EXECUTED_MSG: string, + THRESHOLD_CHANGE_FAILED_MSG: string, + + // Rinkeby version + RINKEBY_VERSION_MSG: string, + WRONG_NETWORK_RINKEBY_MSG: string, + WRONG_NETWOEK_MAINNET_MSG: string, +} + +export const NOTIFICATIONS: Notifications = { + // Wallet Connection + CONNECT_WALLET_MSG: { + description: 'Please connect wallet to continue', + options: { variant: WARNING, persist: true }, + }, + CONNECT_WALLET_READ_MODE_MSG: { + description: 'You are in read-only mode: Please connect wallet', + options: { variant: WARNING, persist: true }, + }, + WALLET_CONNECTED_MSG: { + description: 'Wallet connected', + options: { + variant: SUCCESS, + persist: false, + autoHideDuration: shortDuration, + preventDuplicate: true, + }, + }, + UNLOCK_WALLET_MSG: { + description: 'Unlock your wallet to connect', + options: { variant: WARNING, persist: true }, + }, + CONNECT_WALLET_ERROR_MSG: { + description: 'Error connecting to your wallet', + options: { variant: ERROR, persist: true }, + }, + + // Regular/Custom Transactions + SIGN_TX_MSG: { + description: 'Please sign the transaction', + options: { variant: SUCCESS, persist: true }, + }, + TX_PENDING_MSG: { + description: 'Transaction pending', + options: { variant: SUCCESS, persist: true }, + }, + TX_PENDING_MORE_CONFIRMATIONS_MSG: { + description: 'Transaction pending: More confirmations required to execute', + options: { variant: SUCCESS, persist: true }, + }, + TX_REJECTED_MSG: { + description: 'Transaction rejected', + options: { variant: ERROR, persist: false, autoHideDuration: longDuration }, + }, + TX_EXECUTED_MSG: { + description: 'Transaction successfully executed', + options: { variant: SUCCESS, persist: false, autoHideDuration: longDuration }, + }, + TX_FAILED_MSG: { + description: 'Transaction failed', + options: { variant: ERROR, persist: false, autoHideDuration: longDuration }, + }, + + // Approval Transactions + TX_CONFIRMATION_PENDING_MSG: { + description: 'Confirmation transaction pending', + options: { variant: SUCCESS, persist: true }, + }, + TX_CONFIRMATION_EXECUTED_MSG: { + description: 'Confirmation transaction succesful', + options: { variant: SUCCESS, persist: false, autoHideDuration: longDuration }, + }, + TX_CONFIRMATION_FAILED_MSG: { + description: 'Confirmation transaction failed', + options: { variant: ERROR, persist: false, autoHideDuration: longDuration }, + }, + + // Safe Name + SAFE_NAME_CHANGE_EXECUTED_MSG: { + description: 'Safe name changed', + options: { variant: SUCCESS, persist: false, autoHideDuration: shortDuration }, + }, + + // Owner Name + OWNER_NAME_CHANGE_EXECUTED_MSG: { + description: 'Owner name changed', + options: { variant: SUCCESS, persist: false, autoHideDuration: shortDuration }, + }, + + // Owners + SIGN_OWNER_CHANGE_MSG: { + description: 'Please sign the owner change', + options: { variant: SUCCESS, persist: true }, + }, + ONWER_CHANGE_PENDING_MSG: { + description: 'Owner change pending', + options: { variant: SUCCESS, persist: true }, + }, + ONWER_CHANGE_PENDING_MORE_CONFIRMATIONS_MSG: { + description: 'Owner change pending: More confirmations required to execute', + options: { variant: SUCCESS, persist: true }, + }, + ONWER_CHANGE_REJECTED_MSG: { + description: 'Owner change rejected', + options: { variant: ERROR, persist: false, autoHideDuration: longDuration }, + }, + OWNER_CHANGE_EXECUTED_MSG: { + description: 'Owner change successfully executed', + options: { variant: SUCCESS, persist: false, autoHideDuration: longDuration }, + }, + ONWER_CHANGE_FAILED_MSG: { + description: 'Owner change failed', + options: { variant: ERROR, persist: false, autoHideDuration: longDuration }, + }, + + // Threshold + SIGN_THRESHOLD_CHANGE_MSG: { + description: 'Please sign the required confirmations change', + options: { variant: SUCCESS, persist: true }, + }, + THRESHOLD_CHANGE_PENDING_MSG: { + description: 'Required confirmations change pending', + options: { variant: SUCCESS, persist: true }, + }, + THRESHOLD_CHANGE_PENDING_MORE_CONFIRMATIONS_MSG: { + description: 'Required confirmations change pending: More confirmations required to execute', + options: { variant: SUCCESS, persist: true }, + }, + THRESHOLD_CHANGE_REJECTED_MSG: { + description: 'Required confirmations change rejected', + options: { variant: ERROR, persist: false, autoHideDuration: longDuration }, + }, + THRESHOLD_CHANGE_EXECUTED_MSG: { + description: 'Required confirmations change successfully executed', + options: { variant: SUCCESS, persist: false, autoHideDuration: longDuration }, + }, + THRESHOLD_CHANGE_FAILED_MSG: { + description: 'Required confirmations change failed', + options: { variant: ERROR, persist: false, autoHideDuration: longDuration }, + }, + + // Network + RINKEBY_VERSION_MSG: { + description: "Rinkeby Version: Don't send mainnet assets to this Safe", + options: { variant: INFO, persist: true, hideIconVariant: true }, + }, + WRONG_NETWORK_RINKEBY_MSG: { + description: 'Wrong network: Please use Rinkeby', + options: { variant: WARNING, persist: true }, + }, + WRONG_NETWOEK_MAINNET_MSG: { + description: 'Wrong network: Please use Mainnet', + options: { variant: WARNING, persist: true }, + }, +} From 11335b487d3393266b573a7504c66a13b9ee103b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Fri, 20 Sep 2019 10:55:09 +0200 Subject: [PATCH 21/50] Define notification queues --- .../notifications/notificationBuilder.js | 134 ++++++++++++++++++ .../safe/transactions/notifiedTransactions.js | 23 +++ 2 files changed, 157 insertions(+) create mode 100644 src/logic/notifications/notificationBuilder.js create mode 100644 src/logic/safe/transactions/notifiedTransactions.js diff --git a/src/logic/notifications/notificationBuilder.js b/src/logic/notifications/notificationBuilder.js new file mode 100644 index 00000000..b2b6efd2 --- /dev/null +++ b/src/logic/notifications/notificationBuilder.js @@ -0,0 +1,134 @@ +// @flow +import { NOTIFICATIONS } from './notificationTypes' +import { NOTIFIED_TRANSACTIONS } from '~/logic/safe/transactions' + +type NotificationsQueue = { + beforeExecution: Notification, + pendingExecution: { + single: Notification, + multiple: Notification, + }, + afterExecution: Notification, + afterExecutionError: Notification, + afterRejection: Notification, +} + +const standardTxNotificationsQueue: NotificationsQueue = { + beforeExecution: NOTIFICATIONS.SIGN_TX_MSG, + pendingExecution: { + single: NOTIFICATIONS.TX_PENDING_MSG, + multiple: NOTIFICATIONS.TX_PENDING_MORE_CONFIRMATIONS_MSG, + }, + afterRejection: NOTIFICATIONS.TX_REJECTED_MSG, + afterExecution: NOTIFICATIONS.TX_EXECUTED_MSG, + afterExecutionError: NOTIFICATIONS.TX_FAILED_MSG, +} + +const confirmationTxNotificationsQueue: NotificationsQueue = { + beforeExecution: NOTIFICATIONS.SIGN_TX_MSG, + pendingExecution: { + single: NOTIFICATIONS.TX_CONFIRMATION_PENDING_MSG, + multiple: null, + }, + afterRejection: NOTIFICATIONS.TX_REJECTED_MSG, + afterExecution: NOTIFICATIONS.TX_CONFIRMATION_EXECUTED_MSG, + afterExecutionError: NOTIFICATIONS.TX_CONFIRMATION_FAILED_MSG, +} + +const ownerChangeTxNotificationsQueue: NotificationsQueue = { + beforeExecution: NOTIFICATIONS.SIGN_OWNER_CHANGE_MSG, + pendingExecution: { + single: NOTIFICATIONS.ONWER_CHANGE_PENDING_MSG, + multiple: NOTIFICATIONS.ONWER_CHANGE_PENDING_MORE_CONFIRMATIONS_MSG, + }, + afterRejection: NOTIFICATIONS.ONWER_CHANGE_REJECTED_MSG, + afterExecution: NOTIFICATIONS.OWNER_CHANGE_EXECUTED_MSG, + afterExecutionError: NOTIFICATIONS.ONWER_CHANGE_FAILED_MSG, +} + +const safeNameChangeNotificationsQueue: NotificationsQueue = { + beforeExecution: null, + pendingExecution: { + single: null, + multiple: null, + }, + afterRejection: null, + afterExecution: NOTIFICATIONS.SAFE_NAME_CHANGE_EXECUTED_MSG, + afterExeCONNECT_WALLET_TXcutionError: null, +} + +const ownerNameChangeNotificationsQueue: NotificationsQueue = { + beforeExecution: null, + pendingExecution: { + single: null, + multiple: null, + }, + afterRejection: null, + afterExecution: NOTIFICATIONS.OWNER_NAME_CHANGE_EXECUTED_MSG, + afterExecutionError: null, +} + +const thresholdChangeTxNotificationsQueue: NotificationsQueue = { + beforeExecution: NOTIFICATIONS.SIGN_THRESHOLD_CHANGE_MSG, + pendingExecution: { + single: NOTIFICATIONS.THRESHOLD_CHANGE_PENDING_MSG, + multiple: NOTIFICATIONS.THRESHOLD_CHANGE_PENDING_MORE_CONFIRMATIONS_MSG, + }, + afterRejection: NOTIFICATIONS.THRESHOLD_CHANGE_REJECTED_MSG, + afterExecution: NOTIFICATIONS.THRESHOLD_CHANGE_EXECUTED_MSG, + afterExecutionError: NOTIFICATIONS.THRESHOLD_CHANGE_FAILED_MSG, +} + +const defaultNotificationsQueue: NotificationsQueue = { + beforeExecution: NOTIFICATIONS.SIGN_TX_MSG, + pendingExecution: { + single: NOTIFICATIONS.TX_PENDING_MSG, + multiple: NOTIFICATIONS.TX_PENDING_MORE_CONFIRMATIONS_MSG, + }, + afterRejection: NOTIFICATIONS.TX_REJECTED_MSG, + afterExecution: NOTIFICATIONS.TX_EXECUTED_MSG, + afterExecutionError: NOTIFICATIONS.TX_FAILED_MSG, +} + +export const getNofiticationsFromTxType = (txType: string) => { + let notificationsQueue: NotificationsQueue + + switch (txType) { + case NOTIFIED_TRANSACTIONS.CONNECT_WALLET_TX: { + break + } + case NOTIFIED_TRANSACTIONS.STANDARD_TX: { + notificationsQueue = standardTxNotificationsQueue + break + } + case NOTIFIED_TRANSACTIONS.CONFIRMATION_TX: { + notificationsQueue = confirmationTxNotificationsQueue + break + } + case NOTIFIED_TRANSACTIONS.OWNER_CHANGE_TX: { + notificationsQueue = ownerChangeTxNotificationsQueue + break + } + case NOTIFIED_TRANSACTIONS.SAFE_NAME_CHANGE_TX: { + notificationsQueue = safeNameChangeNotificationsQueue + break + } + case NOTIFIED_TRANSACTIONS.OWNER_NAME_CHANGE_TX: { + notificationsQueue = ownerNameChangeNotificationsQueue + break + } + case NOTIFIED_TRANSACTIONS.THRESHOLD_CHANGE_TX: { + notificationsQueue = thresholdChangeTxNotificationsQueue + break + } + case NOTIFIED_TRANSACTIONS.NETWORK_TX: { + break + } + default: { + notificationsQueue = defaultNotificationsQueue + break + } + } + + return notificationsQueue +} diff --git a/src/logic/safe/transactions/notifiedTransactions.js b/src/logic/safe/transactions/notifiedTransactions.js new file mode 100644 index 00000000..781f74c0 --- /dev/null +++ b/src/logic/safe/transactions/notifiedTransactions.js @@ -0,0 +1,23 @@ +// @flow + +export type NotifiedTransaction = { + CONNECT_WALLET_TX: string, + STANDARD_TX: string, + CONFIRMATION_TX: string, + OWNER_CHANGE_TX: string, + SAFE_NAME_CHANGE_TX: string, + OWNER_NAME_CHANGE_TX: string, + THRESHOLD_CHANGE_TX: string, + NETWORK_TX: string, +} + +export const NOTIFIED_TRANSACTIONS: NotifiedTransaction = { + CONNECT_WALLET_TX: 'CONNECT_WALLET_TX', + STANDARD_TX: 'STANDARD_TX', + CONFIRMATION_TX: 'CONFIRMATION_TX', + OWNER_CHANGE_TX: 'OWNER_CHANGE_TX', + SAFE_NAME_CHANGE_TX: 'SAFE_NAME_CHANGE_TX', + OWNER_NAME_CHANGE_TX: 'OWNER_NAME_CHANGE_TX', + THRESHOLD_CHANGE_TX: 'THRESHOLD_CHANGE_TX', + NETWORK_TX: 'NETWORK_TX', +} From 0e586043952004f313c1742aaa4480cccad9b19c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Fri, 20 Sep 2019 12:08:43 +0200 Subject: [PATCH 22/50] Refactor page frame component --- src/components/layout/PageFrame/index.jsx | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/components/layout/PageFrame/index.jsx b/src/components/layout/PageFrame/index.jsx index 5ff4c89f..0e2057b0 100644 --- a/src/components/layout/PageFrame/index.jsx +++ b/src/components/layout/PageFrame/index.jsx @@ -1,8 +1,8 @@ // @flow import * as React from 'react' import { SnackbarProvider } from 'notistack' -import SidebarProvider from '~/components/Sidebar' import { withStyles } from '@material-ui/core/styles' +import SidebarProvider from '~/components/Sidebar' import Header from '~/components/Header' import Img from '~/components/layout/Img' import AlertLogo from './assets/alert.svg' @@ -10,7 +10,7 @@ import CheckLogo from './assets/check.svg' import ErrorLogo from './assets/error.svg' import styles from './index.scss' -const classes = { +const notificationStyles = { success: { background: '#ffffff', fontFamily: 'Averta', @@ -51,6 +51,7 @@ const classes = { type Props = { children: React.Node, + classes: Object, } const PageFrame = ({ children, classes }: Props) => ( @@ -65,17 +66,17 @@ const PageFrame = ({ children, classes }: Props) => ( variantInfo: classes.info, }} iconVariant={{ - success: , - error: , - warning: , + success: , + error: , + warning: , }} - ><> + >
{children} - + ) -export default withStyles(classes)(PageFrame) +export default withStyles(notificationStyles)(PageFrame) From 858f7ca0381743925140f88532b712b908e4d9da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Fri, 20 Sep 2019 12:40:29 +0200 Subject: [PATCH 23/50] Add owner management notifications --- src/logic/notifications/index.js | 106 +----------------- src/logic/safe/transactions/index.js | 2 +- .../ManageOwners/AddOwnerModal/index.jsx | 21 +++- .../ManageOwners/EditOwnerModal/index.jsx | 13 ++- .../ManageOwners/RemoveOwnerModal/index.jsx | 20 +++- .../ManageOwners/ReplaceOwnerModal/index.jsx | 20 +++- 6 files changed, 62 insertions(+), 120 deletions(-) diff --git a/src/logic/notifications/index.js b/src/logic/notifications/index.js index c2a60d59..df61614c 100644 --- a/src/logic/notifications/index.js +++ b/src/logic/notifications/index.js @@ -1,105 +1,3 @@ // @flow - -export type Notifications = { - // Default - BEFORE_EXECUTION_OR_CREATION: string, - AFTER_EXECUTION: string, - CREATED_MORE_CONFIRMATIONS_NEEDED: string, - ERROR: string, - - // Wallet Connection - CONNECT_WALLET_MSG: string, - CONNECT_WALLET_READ_MODE_MSG: string, - WALLET_CONNECTED_MSG: string, - UNLOCK_WALLET_MSG: string, - CONNECT_WALLET_ERROR_MSG: string, - - // Regular/Custom Transactions - SIGN_TX_MSG: string, - TX_PENDING_MSG: string, - TX_PENDING_MORE_CONFIRMATIONS_MSG: string, - TX_REJECTED_MSG: string, - TX_EXECUTED_MSG: string, - TX_FAILED_MSG: string, - - // Approval Transactions - TX_CONFIRMATION_PENDING_MSG: string, - TX_CONFIRMATION_EXECUTED_MSG: string, - TX_CONFIRMATION_FAILED_MSG: string, - - // Safe Name - SAFE_NAME_CHANGED_MSG: string, - - // Owners - SIGN_OWNER_CHANGE_MSG: string, - ONWER_CHANGE_PENDING_MSG: string, - ONWER_CHANGE_PENDING_MORE_CONFIRMATIONS_MSG: string, - ONWER_CHANGE_REJECTED_MSG: string, - ONWER_CHANGE_EXECUTED_MSG: string, - ONWER_CHANGE_FAILED_MSG: string, - - // Threshold - SIGN_THRESHOLD_CHANGE_MSG: string, - THRESHOLD_CHANGE_PENDING_MSG: string, - THRESHOLD_CHANGE_PENDING_MORE_CONFIRMATIONS_MSG: string, - THRESHOLD_CHANGE_REJECTED_MSG: string, - THRESHOLD_CHANGE_EXECUTED_MSG: string, - THRESHOLD_CHANGE_FAILED_MSG: string, - - // Rinkeby version - RINKEBY_VERSION_MSG: string, - WRONG_NETWORK_RINKEBY_MSG: string, - WRONG_NETWOEK_MAINNET_MSG: string, -} - -export const NOTIFICATIONS: Notifications = { - // Default - BEFORE_EXECUTION_OR_CREATION: 'Transaction in progress', - AFTER_EXECUTION: 'Transaction successfully executed', - CREATED_MORE_CONFIRMATIONS_NEEDED: 'Transaction in progress: More confirmations required to execute', - ERROR: 'Transaction failed', - - // Wallet Connection - CONNECT_WALLET_MSG: 'Please connect wallet to continue', - CONNECT_WALLET_READ_MODE_MSG: 'You are in read-only mode: Please connect wallet', - WALLET_CONNECTED_MSG: 'Wallet connected', - UNLOCK_WALLET_MSG: 'Unlock your wallet to connect', - CONNECT_WALLET_ERROR_MSG: 'Error connecting to your wallet', - - // Regular/Custom Transactions - SIGN_TX_MSG: 'Please sign the transaction', - TX_PENDING_MSG: 'Transaction pending', - TX_PENDING_MORE_CONFIRMATIONS_MSG: 'Transaction pending: More confirmations required to execute', - TX_REJECTED_MSG: 'Transaction rejected', - TX_EXECUTED_MSG: 'Transaction successfully executed', - TX_FAILED_MSG: 'Transaction failed', - - // Approval Transactions - TX_CONFIRMATION_PENDING_MSG: 'Confirmation transaction pending', - TX_CONFIRMATION_EXECUTED_MSG: 'Confirmation transaction succesful', - TX_CONFIRMATION_FAILED_MSG: 'Confirmation transaction failed', - - // Safe Name - SAFE_NAME_CHANGED_MSG: 'Safe name changed', - - // Owners - SIGN_OWNER_CHANGE_MSG: 'Please sign the owner change', - ONWER_CHANGE_PENDING_MSG: 'Owner change pending', - ONWER_CHANGE_PENDING_MORE_CONFIRMATIONS_MSG: 'Owner change pending: More confirmations required to execute', - ONWER_CHANGE_REJECTED_MSG: 'Owner change rejected', - ONWER_CHANGE_EXECUTED_MSG: 'Owner change successfully executed', - ONWER_CHANGE_FAILED_MSG: 'Owner change failed', - - // Threshold - SIGN_THRESHOLD_CHANGE_MSG: 'Please sign the required confirmations change', - THRESHOLD_CHANGE_PENDING_MSG: 'Required confirmations change pending', - THRESHOLD_CHANGE_PENDING_MORE_CONFIRMATIONS_MSG: 'Required confirmations change pending: More confirmations required to execute', - THRESHOLD_CHANGE_REJECTED_MSG: 'Required confirmations change rejected', - THRESHOLD_CHANGE_EXECUTED_MSG: 'Required confirmations change successfully executed', - THRESHOLD_CHANGE_FAILED_MSG: 'Required confirmations change failed', - - // Network - RINKEBY_VERSION_MSG: 'Rinkeby Version: Don\'t send mainnet assets to this Safe', - WRONG_NETWORK_RINKEBY_MSG: 'Wrong network: Please use Rinkeby', - WRONG_NETWOEK_MAINNET_MSG: 'Wrong network: Please use Mainnet', -} +export * from './notificationTypes' +export * from './notificationBuilder' diff --git a/src/logic/safe/transactions/index.js b/src/logic/safe/transactions/index.js index a085a125..63d8a8b0 100644 --- a/src/logic/safe/transactions/index.js +++ b/src/logic/safe/transactions/index.js @@ -1,6 +1,6 @@ // @flow export * from './gas' export * from './send' -export * from './safeBlockchainOperations' export * from './safeTxSignerEIP712' export * from './txHistory' +export * from './notifiedTransactions' diff --git a/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.jsx b/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.jsx index 064835c1..4766623f 100644 --- a/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.jsx @@ -4,9 +4,9 @@ import { List } from 'immutable' import { withStyles } from '@material-ui/core/styles' import { withSnackbar } from 'notistack' import Modal from '~/components/Modal' -import { type Variant } from '~/components/Header' import { type Owner } from '~/routes/safe/store/models/owner' import { getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts' +import { NOTIFIED_TRANSACTIONS } from '~/logic/safe/transactions' import OwnerForm from './screens/OwnerForm' import ThresholdForm from './screens/ThresholdForm' import ReviewAddOwner from './screens/Review' @@ -30,7 +30,8 @@ type Props = { network: string, addSafeOwner: Function, createTransaction: Function, - enqueueSnackbar: (message: string, variant: Variant) => void, + enqueueSnackbar: Function, + closeSnackbar: Function, } type ActiveScreen = 'selectOwner' | 'selectThreshold' | 'reviewAddOwner' @@ -38,14 +39,23 @@ export const sendAddOwner = async ( values: Object, safeAddress: string, ownersOld: List, - enqueueSnackbar: (message: string, variant: Variant) => void, + enqueueSnackbar: Function, + closeSnackbar: Function, createTransaction: Function, addSafeOwner: Function, ) => { const gnosisSafe = await getGnosisSafeInstanceAt(safeAddress) const txData = gnosisSafe.contract.methods.addOwnerWithThreshold(values.ownerAddress, values.threshold).encodeABI() - const txHash = await createTransaction(safeAddress, safeAddress, 0, txData, enqueueSnackbar) + const txHash = await createTransaction( + safeAddress, + safeAddress, + 0, + txData, + NOTIFIED_TRANSACTIONS.OWNER_CHANGE_TX, + enqueueSnackbar, + closeSnackbar, + ) if (txHash) { addSafeOwner({ safeAddress, ownerName: values.ownerName, ownerAddress: values.ownerAddress }) @@ -64,6 +74,7 @@ const AddOwner = ({ createTransaction, addSafeOwner, enqueueSnackbar, + closeSnackbar, }: Props) => { const [activeScreen, setActiveScreen] = useState('selectOwner') const [values, setValues] = useState({}) @@ -104,7 +115,7 @@ const AddOwner = ({ const onAddOwner = async () => { onClose() try { - sendAddOwner(values, safeAddress, owners, enqueueSnackbar, createTransaction, addSafeOwner) + sendAddOwner(values, safeAddress, owners, enqueueSnackbar, closeSnackbar, createTransaction, addSafeOwner) } catch (error) { // eslint-disable-next-line console.log('Error while removing an owner ' + error) diff --git a/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/index.jsx b/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/index.jsx index 6fe47db6..41ecc250 100644 --- a/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/index.jsx @@ -1,5 +1,6 @@ // @flow import React from 'react' +import { withSnackbar } from 'notistack' import { withStyles } from '@material-ui/core/styles' import Close from '@material-ui/icons/Close' import OpenInNew from '@material-ui/icons/OpenInNew' @@ -14,8 +15,10 @@ import Field from '~/components/forms/Field' import TextField from '~/components/forms/TextField' import Paragraph from '~/components/layout/Paragraph' import Identicon from '~/components/Identicon' -import { getEtherScanLink } from '~/logic/wallets/getWeb3' import { composeValidators, required, minMaxLength } from '~/components/forms/validator' +import { getNofiticationsFromTxType } from '~/logic/notifications' +import { NOTIFIED_TRANSACTIONS } from '~/logic/safe/transactions' +import { getEtherScanLink } from '~/logic/wallets/getWeb3' import Modal from '~/components/Modal' import { styles } from './style' import { secondary } from '~/theme/variables' @@ -37,6 +40,7 @@ type Props = { network: string, selectedOwnerName: string, editSafeOwner: Function, + enqueueSnackbar: Function, } const EditOwnerComponent = ({ @@ -48,9 +52,14 @@ const EditOwnerComponent = ({ selectedOwnerName, editSafeOwner, network, + enqueueSnackbar, }: Props) => { const handleSubmit = (values) => { editSafeOwner({ safeAddress, ownerAddress, ownerName: values.ownerName }) + + const notification = getNofiticationsFromTxType(NOTIFIED_TRANSACTIONS.OWNER_NAME_CHANGE_TX) + enqueueSnackbar(notification.afterExecution.description, notification.afterExecution.options) + onClose() } @@ -116,6 +125,6 @@ const EditOwnerComponent = ({ ) } -const EditOwnerModal = withStyles(styles)(EditOwnerComponent) +const EditOwnerModal = withStyles(styles)(withSnackbar(EditOwnerComponent)) export default EditOwnerModal diff --git a/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/index.jsx b/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/index.jsx index a67014a5..ec160610 100644 --- a/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/index.jsx @@ -4,9 +4,9 @@ import { List } from 'immutable' import { withStyles } from '@material-ui/core/styles' import { withSnackbar } from 'notistack' import Modal from '~/components/Modal' -import { type Variant } from '~/components/Header' import { type Owner } from '~/routes/safe/store/models/owner' import { getGnosisSafeInstanceAt, SENTINEL_ADDRESS } from '~/logic/contracts/safeContracts' +import { NOTIFIED_TRANSACTIONS } from '~/logic/safe/transactions' import CheckOwner from './screens/CheckOwner' import ThresholdForm from './screens/ThresholdForm' import ReviewRemoveOwner from './screens/Review' @@ -32,7 +32,8 @@ type Props = { network: string, createTransaction: Function, removeSafeOwner: Function, - enqueueSnackbar: (message: string, variant: Variant) => void, + enqueueSnackbar: Function, + closeSnackbar: Function, } type ActiveScreen = 'checkOwner' | 'selectThreshold' | 'reviewRemoveOwner' @@ -43,7 +44,8 @@ export const sendRemoveOwner = async ( ownerAddressToRemove: string, ownerNameToRemove: string, ownersOld: List, - enqueueSnackbar: (message: string, variant: Variant) => void, + enqueueSnackbar: Function, + closeSnackbar: Function, createTransaction: Function, removeSafeOwner: Function, ) => { @@ -57,7 +59,15 @@ export const sendRemoveOwner = async ( .removeOwner(prevAddress, ownerAddressToRemove, values.threshold) .encodeABI() - const txHash = await createTransaction(safeAddress, safeAddress, 0, txData, enqueueSnackbar) + const txHash = await createTransaction( + safeAddress, + safeAddress, + 0, + txData, + NOTIFIED_TRANSACTIONS.OWNER_CHANGE_TX, + enqueueSnackbar, + closeSnackbar, + ) if (txHash) { removeSafeOwner({ safeAddress, ownerAddress: ownerAddressToRemove }) @@ -78,6 +88,7 @@ const RemoveOwner = ({ createTransaction, removeSafeOwner, enqueueSnackbar, + closeSnackbar, }: Props) => { const [activeScreen, setActiveScreen] = useState('checkOwner') const [values, setValues] = useState({}) @@ -117,6 +128,7 @@ const RemoveOwner = ({ ownerName, owners, enqueueSnackbar, + closeSnackbar, createTransaction, removeSafeOwner, ) diff --git a/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.jsx b/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.jsx index 3d3fea1d..effb19c0 100644 --- a/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.jsx @@ -4,7 +4,7 @@ import { List } from 'immutable' import { withStyles } from '@material-ui/core/styles' import { withSnackbar } from 'notistack' import Modal from '~/components/Modal' -import { type Variant } from '~/components/Header' +import { NOTIFIED_TRANSACTIONS } from '~/logic/safe/transactions' import { getGnosisSafeInstanceAt, SENTINEL_ADDRESS } from '~/logic/contracts/safeContracts' import OwnerForm from './screens/OwnerForm' import ReviewReplaceOwner from './screens/Review' @@ -30,7 +30,8 @@ type Props = { threshold: string, createTransaction: Function, replaceSafeOwner: Function, - enqueueSnackbar: (message: string, variant: Variant) => void, + enqueueSnackbar: Function, + closeSnackbar: Function, } type ActiveScreen = 'checkOwner' | 'reviewReplaceOwner' @@ -38,7 +39,8 @@ export const sendReplaceOwner = async ( values: Object, safeAddress: string, ownerAddressToRemove: string, - enqueueSnackbar: (message: string, variant: Variant) => void, + enqueueSnackbar: Function, + closeSnackbar: Function, createTransaction: Function, replaceSafeOwner: Function, ) => { @@ -52,7 +54,15 @@ export const sendReplaceOwner = async ( .swapOwner(prevAddress, ownerAddressToRemove, values.ownerAddress) .encodeABI() - const txHash = await createTransaction(safeAddress, safeAddress, 0, txData, enqueueSnackbar) + const txHash = await createTransaction( + safeAddress, + safeAddress, + 0, + txData, + NOTIFIED_TRANSACTIONS.OWNER_CHANGE_TX, + enqueueSnackbar, + closeSnackbar, + ) if (txHash) { replaceSafeOwner({ @@ -78,6 +88,7 @@ const ReplaceOwner = ({ createTransaction, replaceSafeOwner, enqueueSnackbar, + closeSnackbar, }: Props) => { const [activeScreen, setActiveScreen] = useState('checkOwner') const [values, setValues] = useState({}) @@ -107,6 +118,7 @@ const ReplaceOwner = ({ safeAddress, ownerAddress, enqueueSnackbar, + closeSnackbar, createTransaction, replaceSafeOwner, ) From 6ea3b679cab0c6c66901b5ed97a9f39538ec2c7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Fri, 20 Sep 2019 19:58:15 +0200 Subject: [PATCH 24/50] Add threshold notifications --- .../Settings/ThresholdSettings/index.jsx | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/routes/safe/components/Settings/ThresholdSettings/index.jsx b/src/routes/safe/components/Settings/ThresholdSettings/index.jsx index fd4a6fb1..87317313 100644 --- a/src/routes/safe/components/Settings/ThresholdSettings/index.jsx +++ b/src/routes/safe/components/Settings/ThresholdSettings/index.jsx @@ -10,7 +10,7 @@ import Block from '~/components/layout/Block' import Row from '~/components/layout/Row' import Modal from '~/components/Modal' import Paragraph from '~/components/layout/Paragraph' -import { type Variant } from '~/components/Header' +import { NOTIFIED_TRANSACTIONS } from '~/logic/safe/transactions' import ChangeThreshold from './ChangeThreshold' import type { Owner } from '~/routes/safe/store/models/owner' import { getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts' @@ -23,11 +23,19 @@ type Props = { createTransaction: Function, safeAddress: string, granted: boolean, - enqueueSnackbar: (message: string, variant: Variant) => void, + enqueueSnackbar: Function, + closeSnackbar: Function, } const ThresholdSettings = ({ - owners, threshold, classes, createTransaction, safeAddress, granted, enqueueSnackbar, + owners, + threshold, + classes, + createTransaction, + safeAddress, + granted, + enqueueSnackbar, + closeSnackbar, }: Props) => { const [isModalOpen, setModalOpen] = useState(false) @@ -39,7 +47,15 @@ const ThresholdSettings = ({ const safeInstance = await getGnosisSafeInstanceAt(safeAddress) const txData = safeInstance.contract.methods.changeThreshold(newThreshold).encodeABI() - createTransaction(safeAddress, safeAddress, 0, txData, enqueueSnackbar) + createTransaction( + safeAddress, + safeAddress, + 0, + txData, + NOTIFIED_TRANSACTIONS.THRESHOLD_CHANGE_TX, + enqueueSnackbar, + closeSnackbar, + ) } return ( From 1b61a0294cb44cceda9234c05e4c866ffae5ffa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Mon, 23 Sep 2019 09:47:23 +0200 Subject: [PATCH 25/50] Add approve and cancel txs notifications --- .../ExpandedTx/ApproveTxModal/index.jsx | 15 +++++++++--- .../ExpandedTx/CancelTxModal/index.jsx | 24 +++++++++++++++---- 2 files changed, 32 insertions(+), 7 deletions(-) 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 b33e343b..3d76a766 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/ApproveTxModal/index.jsx +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/ApproveTxModal/index.jsx @@ -13,7 +13,7 @@ import Row from '~/components/layout/Row' import Bold from '~/components/layout/Bold' import Block from '~/components/layout/Block' import Paragraph from '~/components/layout/Paragraph' -import { type Variant } from '~/components/Header' +import { NOTIFIED_TRANSACTIONS } from '~/logic/safe/transactions' import { type Transaction } from '~/routes/safe/store/models/transaction' import { styles } from './style' @@ -30,7 +30,8 @@ type Props = { threshold: number, thresholdReached: boolean, userAddress: string, - enqueueSnackbar: (message: string, variant: Variant) => void, + enqueueSnackbar: Function, + closeSnackbar: Function, } const getModalTitleAndDescription = (thresholdReached: boolean) => { @@ -58,6 +59,7 @@ const ApproveTxModal = ({ thresholdReached, userAddress, enqueueSnackbar, + closeSnackbar, }: Props) => { const [approveAndExecute, setApproveAndExecute] = useState(false) const { title, description } = getModalTitleAndDescription(thresholdReached) @@ -66,7 +68,14 @@ const ApproveTxModal = ({ const handleExecuteCheckbox = () => setApproveAndExecute((prevApproveAndExecute) => !prevApproveAndExecute) const approveTx = () => { - processTransaction(safeAddress, tx, enqueueSnackbar, userAddress, enqueueSnackbar) + processTransaction( + safeAddress, + tx, + userAddress, + NOTIFIED_TRANSACTIONS.CONFIRMATION_TX, + enqueueSnackbar, + closeSnackbar, + ) onClose() } diff --git a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/CancelTxModal/index.jsx b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/CancelTxModal/index.jsx index 124c424a..abec6e5d 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/CancelTxModal/index.jsx +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/CancelTxModal/index.jsx @@ -13,7 +13,7 @@ import Block from '~/components/layout/Block' import Paragraph from '~/components/layout/Paragraph' import { type Transaction } from '~/routes/safe/store/models/transaction' import { EMPTY_DATA } from '~/logic/wallets/ethTransactions' -import { type Variant } from '~/components/Header' +import { NOTIFIED_TRANSACTIONS } from '~/logic/safe/transactions' import { styles } from './style' type Props = { @@ -23,14 +23,30 @@ type Props = { createTransaction: Function, tx: Transaction, safeAddress: string, - enqueueSnackbar: (message: string, variant: Variant) => void, + enqueueSnackbar: Function, + closeSnackbar: Function, } const CancelTxModal = ({ - onClose, isOpen, classes, createTransaction, tx, safeAddress, enqueueSnackbar, + onClose, + isOpen, + classes, + createTransaction, + tx, + safeAddress, + enqueueSnackbar, + closeSnackbar, }: Props) => { const sendReplacementTransaction = () => { - createTransaction(safeAddress, safeAddress, 0, EMPTY_DATA, enqueueSnackbar) + createTransaction( + safeAddress, + safeAddress, + 0, + EMPTY_DATA, + NOTIFIED_TRANSACTIONS.CANCELLATION_TX, + enqueueSnackbar, + closeSnackbar, + ) onClose() } From f8ba0c6217dc2a44760336ab0b5473b0c7df0692 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Mon, 23 Sep 2019 10:07:43 +0200 Subject: [PATCH 26/50] Add regular and custom txs notifications --- .../SendModal/screens/ReviewCustomTx/index.jsx | 16 +++++++++++++--- .../SendModal/screens/ReviewTx/index.jsx | 16 +++++++++++++--- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/routes/safe/components/Balances/SendModal/screens/ReviewCustomTx/index.jsx b/src/routes/safe/components/Balances/SendModal/screens/ReviewCustomTx/index.jsx index cc5d1df0..9fab6db2 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ReviewCustomTx/index.jsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ReviewCustomTx/index.jsx @@ -14,11 +14,11 @@ import Img from '~/components/layout/Img' import Block from '~/components/layout/Block' import Identicon from '~/components/Identicon' import Hairline from '~/components/layout/Hairline' -import { type Variant } from '~/components/Header' import { copyToClipboard } from '~/utils/clipboard' import SafeInfo from '~/routes/safe/components/Balances/SendModal/SafeInfo' import { setImageToPlaceholder } from '~/routes/safe/components/Balances/utils' import { getWeb3 } from '~/logic/wallets/getWeb3' +import { NOTIFIED_TRANSACTIONS } from '~/logic/safe/transactions' import { getEthAsToken } from '~/logic/tokens/utils/tokenHelpers' import ArrowDown from '../assets/arrow-down.svg' import { secondary } from '~/theme/variables' @@ -34,7 +34,8 @@ type Props = { ethBalance: string, tx: Object, createTransaction: Function, - enqueueSnackbar: (message: string, variant: Variant) => void, + enqueueSnackbar: Function, + closeSnackbar: Function, } const openIconStyle = { @@ -53,6 +54,7 @@ const ReviewCustomTx = ({ tx, createTransaction, enqueueSnackbar, + closeSnackbar, }: Props) => { const submitTx = async () => { const web3 = getWeb3() @@ -60,7 +62,15 @@ const ReviewCustomTx = ({ const txData = tx.data const txValue = tx.value ? web3.utils.toWei(tx.value, 'ether') : 0 - createTransaction(safeAddress, txRecipient, txValue, txData, enqueueSnackbar) + createTransaction( + safeAddress, + txRecipient, + txValue, + txData, + NOTIFIED_TRANSACTIONS.STANDARD_TX, + enqueueSnackbar, + closeSnackbar + ) onClose() } diff --git a/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.jsx b/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.jsx index 83b251df..fb320a8d 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.jsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.jsx @@ -15,12 +15,12 @@ import Block from '~/components/layout/Block' import Identicon from '~/components/Identicon' import { copyToClipboard } from '~/utils/clipboard' import Hairline from '~/components/layout/Hairline' -import { type Variant } from '~/components/Header' import SafeInfo from '~/routes/safe/components/Balances/SendModal/SafeInfo' import { setImageToPlaceholder } from '~/routes/safe/components/Balances/utils' import { getStandardTokenContract } from '~/logic/tokens/store/actions/fetchTokens' import { EMPTY_DATA } from '~/logic/wallets/ethTransactions' import { getWeb3 } from '~/logic/wallets/getWeb3' +import { NOTIFIED_TRANSACTIONS } from '~/logic/safe/transactions' import ArrowDown from '../assets/arrow-down.svg' import { secondary } from '~/theme/variables' import { isEther } from '~/logic/tokens/utils/tokenHelpers' @@ -36,7 +36,8 @@ type Props = { ethBalance: string, tx: Object, createTransaction: Function, - enqueueSnackbar: (message: string, variant: Variant) => void, + enqueueSnackbar: Function, + closeSnackbar: Function, } const openIconStyle = { @@ -55,6 +56,7 @@ const ReviewTx = ({ tx, createTransaction, enqueueSnackbar, + closeSnackbar, }: Props) => { const submitTx = async () => { const web3 = getWeb3() @@ -74,7 +76,15 @@ const ReviewTx = ({ txAmount = 0 } - createTransaction(safeAddress, txRecipient, txAmount, txData, enqueueSnackbar) + createTransaction( + safeAddress, + txRecipient, + txAmount, + txData, + NOTIFIED_TRANSACTIONS.STANDARD_TX, + enqueueSnackbar, + closeSnackbar, + ) onClose() } From 0971e4a929aa9fe5a2e6ce14763bbeb7cd7709f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Mon, 23 Sep 2019 12:26:21 +0200 Subject: [PATCH 27/50] Refactor web3 provider enable() call --- src/logic/wallets/getWeb3.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/logic/wallets/getWeb3.js b/src/logic/wallets/getWeb3.js index b88660f7..e3a271a0 100644 --- a/src/logic/wallets/getWeb3.js +++ b/src/logic/wallets/getWeb3.js @@ -76,7 +76,14 @@ export const getProviderInfo: Function = async (): Promise => { if (window.ethereum) { web3Provider = window.ethereum - await web3Provider.enable() + try { + const accounts = await web3Provider.enable() + if (!accounts) { + console.error('Empty web3 provider') + } + } catch (error) { + console.error('Error when enabling web3 provider', error) + } } else if (window.web3) { web3Provider = window.web3.currentProvider } else { From a581135d7faaaeab7de73bccb6df7b8213ce9235 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Mon, 23 Sep 2019 12:32:46 +0200 Subject: [PATCH 28/50] Refactor web3 provider notifications --- src/components/Header/index.jsx | 21 ++---- .../notifications/notificationBuilder.js | 17 ++++- src/logic/notifications/notificationTypes.js | 73 +++++++++++-------- .../safe/transactions/notifiedTransactions.js | 2 + src/logic/wallets/getWeb3.js | 4 + .../wallets/store/actions/fetchProvider.js | 43 +++++------ .../wallets/store/actions/removeProvider.js | 6 +- .../screens/ReviewCustomTx/index.jsx | 2 +- 8 files changed, 93 insertions(+), 75 deletions(-) diff --git a/src/components/Header/index.jsx b/src/components/Header/index.jsx index a561f59f..ce1e7a72 100644 --- a/src/components/Header/index.jsx +++ b/src/components/Header/index.jsx @@ -3,9 +3,9 @@ import * as React from 'react' import { connect } from 'react-redux' import { withSnackbar } from 'notistack' import { logComponentStack, type Info } from '~/utils/logBoundaries' -import { WALLET_ERROR_MSG } from '~/logic/wallets/store/actions' import { getProviderInfo } from '~/logic/wallets/getWeb3' import type { ProviderProps } from '~/logic/wallets/store/model/provider' +import { NOTIFICATIONS } from '~/logic/notifications' import ProviderAccesible from './component/ProviderInfo/ProviderAccesible' import UserDetails from './component/ProviderDetails/UserDetails' import ProviderDisconnected from './component/ProviderInfo/ProviderDisconnected' @@ -14,16 +14,9 @@ import Layout from './component/Layout' import actions, { type Actions } from './actions' import selector, { type SelectorProps } from './selector' -export const SUCCESS = 'success' -export const ERROR = 'error' -export const WARNING = 'warning' -export const INFO = 'info' - -export type Variant = SUCCESS | ERROR | WARNING | INFO - type Props = Actions & SelectorProps & { - enqueueSnackbar: (message: string, variant: Variant) => void, + enqueueSnackbar: Function, } type State = { @@ -49,7 +42,7 @@ class HeaderComponent extends React.PureComponent { const { enqueueSnackbar } = this.props this.setState({ hasError: true }) - enqueueSnackbar(WALLET_ERROR_MSG, { variant: ERROR }) + enqueueSnackbar(NOTIFICATIONS.CONNECT_WALLET_ERROR_MSG.description, NOTIFICATIONS.CONNECT_WALLET_ERROR_MSG.options) logComponentStack(error, info) } @@ -63,16 +56,16 @@ class HeaderComponent extends React.PureComponent { } onConnect = async () => { - const { fetchProvider, enqueueSnackbar } = this.props + const { fetchProvider, enqueueSnackbar, closeSnackbar } = this.props clearInterval(this.providerListener) let currentProvider: ProviderProps = await getProviderInfo() - fetchProvider(currentProvider, enqueueSnackbar) + fetchProvider(currentProvider, enqueueSnackbar, closeSnackbar) this.providerListener = setInterval(async () => { const newProvider: ProviderProps = await getProviderInfo() - if (JSON.stringify(currentProvider) !== JSON.stringify(newProvider)) { - fetchProvider(newProvider, enqueueSnackbar) + if (currentProvider && JSON.stringify(currentProvider) !== JSON.stringify(newProvider)) { + fetchProvider(newProvider, enqueueSnackbar, closeSnackbar) } currentProvider = newProvider }, 2000) diff --git a/src/logic/notifications/notificationBuilder.js b/src/logic/notifications/notificationBuilder.js index b2b6efd2..fa2f9a85 100644 --- a/src/logic/notifications/notificationBuilder.js +++ b/src/logic/notifications/notificationBuilder.js @@ -35,6 +35,17 @@ const confirmationTxNotificationsQueue: NotificationsQueue = { afterExecutionError: NOTIFICATIONS.TX_CONFIRMATION_FAILED_MSG, } +const cancellationTxNotificationsQueue: NotificationsQueue = { + beforeExecution: NOTIFICATIONS.SIGN_TX_MSG, + pendingExecution: { + single: NOTIFICATIONS.TX_PENDING_MSG, + multiple: NOTIFICATIONS.TX_PENDING_MORE_CONFIRMATIONS_MSG, + }, + afterRejection: NOTIFICATIONS.TX_REJECTED_MSG, + afterExecution: NOTIFICATIONS.TX_EXECUTED_MSG, + afterExecutionError: NOTIFICATIONS.TX_FAILED_MSG, +} + const ownerChangeTxNotificationsQueue: NotificationsQueue = { beforeExecution: NOTIFICATIONS.SIGN_OWNER_CHANGE_MSG, pendingExecution: { @@ -54,7 +65,7 @@ const safeNameChangeNotificationsQueue: NotificationsQueue = { }, afterRejection: null, afterExecution: NOTIFICATIONS.SAFE_NAME_CHANGE_EXECUTED_MSG, - afterExeCONNECT_WALLET_TXcutionError: null, + afterExecutionError: null, } const ownerNameChangeNotificationsQueue: NotificationsQueue = { @@ -105,6 +116,10 @@ export const getNofiticationsFromTxType = (txType: string) => { notificationsQueue = confirmationTxNotificationsQueue break } + case NOTIFIED_TRANSACTIONS.CANCELLATION_TX: { + notificationsQueue = cancellationTxNotificationsQueue + break + } case NOTIFIED_TRANSACTIONS.OWNER_CHANGE_TX: { notificationsQueue = ownerChangeTxNotificationsQueue break diff --git a/src/logic/notifications/notificationTypes.js b/src/logic/notifications/notificationTypes.js index 8a529bad..fe9686dd 100644 --- a/src/logic/notifications/notificationTypes.js +++ b/src/logic/notifications/notificationTypes.js @@ -14,15 +14,17 @@ export type Notification = { variant: Variant, persist: boolean, autoHideDuration?: shortDuration | longDuration, + preventDuplicate: boolean, } export type Notifications = { // Wallet Connection - CONNECT_WALLET_MSG: string, - CONNECT_WALLET_READ_MODE_MSG: string, - WALLET_CONNECTED_MSG: string, - UNLOCK_WALLET_MSG: string, - CONNECT_WALLET_ERROR_MSG: string, + CONNECT_WALLET_MSG: Notification, + CONNECT_WALLET_READ_MODE_MSG: Notification, + WALLET_CONNECTED_MSG: Notification, + WALLET_DISCONNECTED_MSG: Notification, + UNLOCK_WALLET_MSG: Notification, + CONNECT_WALLET_ERROR_MSG: Notification, // Regular/Custom Transactions SIGN_TX_MSG: Notification, @@ -33,47 +35,47 @@ export type Notifications = { TX_FAILED_MSG: Notification, // Approval Transactions - TX_CONFIRMATION_PENDING_MSG: string, - TX_CONFIRMATION_EXECUTED_MSG: string, - TX_CONFIRMATION_FAILED_MSG: string, + TX_CONFIRMATION_PENDING_MSG: Notification, + TX_CONFIRMATION_EXECUTED_MSG: Notification, + TX_CONFIRMATION_FAILED_MSG: Notification, // Safe Name - SAFE_NAME_CHANGED_MSG: string, + SAFE_NAME_CHANGED_MSG: Notification, // Owner Name - OWNER_NAME_CHANGE_EXECUTED_MSG: string, + OWNER_NAME_CHANGE_EXECUTED_MSG: Notification, // Owners - SIGN_OWNER_CHANGE_MSG: string, - ONWER_CHANGE_PENDING_MSG: string, - ONWER_CHANGE_PENDING_MORE_CONFIRMATIONS_MSG: string, - ONWER_CHANGE_REJECTED_MSG: string, - ONWER_CHANGE_EXECUTED_MSG: string, - ONWER_CHANGE_FAILED_MSG: string, + SIGN_OWNER_CHANGE_MSG: Notification, + ONWER_CHANGE_PENDING_MSG: Notification, + ONWER_CHANGE_PENDING_MORE_CONFIRMATIONS_MSG: Notification, + ONWER_CHANGE_REJECTED_MSG: Notification, + ONWER_CHANGE_EXECUTED_MSG: Notification, + ONWER_CHANGE_FAILED_MSG: Notification, // Threshold - SIGN_THRESHOLD_CHANGE_MSG: string, - THRESHOLD_CHANGE_PENDING_MSG: string, - THRESHOLD_CHANGE_PENDING_MORE_CONFIRMATIONS_MSG: string, - THRESHOLD_CHANGE_REJECTED_MSG: string, - THRESHOLD_CHANGE_EXECUTED_MSG: string, - THRESHOLD_CHANGE_FAILED_MSG: string, + SIGN_THRESHOLD_CHANGE_MSG: Notification, + THRESHOLD_CHANGE_PENDING_MSG: Notification, + THRESHOLD_CHANGE_PENDING_MORE_CONFIRMATIONS_MSG: Notification, + THRESHOLD_CHANGE_REJECTED_MSG: Notification, + THRESHOLD_CHANGE_EXECUTED_MSG: Notification, + THRESHOLD_CHANGE_FAILED_MSG: Notification, // Rinkeby version - RINKEBY_VERSION_MSG: string, - WRONG_NETWORK_RINKEBY_MSG: string, - WRONG_NETWOEK_MAINNET_MSG: string, + RINKEBY_VERSION_MSG: Notification, + WRONG_NETWORK_RINKEBY_MSG: Notification, + WRONG_NETWOEK_MAINNET_MSG: Notification, } export const NOTIFICATIONS: Notifications = { // Wallet Connection CONNECT_WALLET_MSG: { description: 'Please connect wallet to continue', - options: { variant: WARNING, persist: true }, + options: { variant: WARNING, persist: true, preventDuplicate: true }, }, CONNECT_WALLET_READ_MODE_MSG: { description: 'You are in read-only mode: Please connect wallet', - options: { variant: WARNING, persist: true }, + options: { variant: WARNING, persist: true, preventDuplicate: true }, }, WALLET_CONNECTED_MSG: { description: 'Wallet connected', @@ -81,12 +83,19 @@ export const NOTIFICATIONS: Notifications = { variant: SUCCESS, persist: false, autoHideDuration: shortDuration, - preventDuplicate: true, + }, + }, + WALLET_DISCONNECTED_MSG: { + description: 'Wallet disconnected', + options: { + variant: SUCCESS, + persist: false, + autoHideDuration: shortDuration, }, }, UNLOCK_WALLET_MSG: { description: 'Unlock your wallet to connect', - options: { variant: WARNING, persist: true }, + options: { variant: WARNING, persist: true, preventDuplicate: true }, }, CONNECT_WALLET_ERROR_MSG: { description: 'Error connecting to your wallet', @@ -200,14 +209,14 @@ export const NOTIFICATIONS: Notifications = { // Network RINKEBY_VERSION_MSG: { description: "Rinkeby Version: Don't send mainnet assets to this Safe", - options: { variant: INFO, persist: true, hideIconVariant: true }, + options: { variant: INFO, persist: true, preventDuplicate: true }, }, WRONG_NETWORK_RINKEBY_MSG: { description: 'Wrong network: Please use Rinkeby', - options: { variant: WARNING, persist: true }, + options: { variant: WARNING, persist: true, preventDuplicate: true }, }, WRONG_NETWOEK_MAINNET_MSG: { description: 'Wrong network: Please use Mainnet', - options: { variant: WARNING, persist: true }, + options: { variant: WARNING, persist: true, preventDuplicate: true }, }, } diff --git a/src/logic/safe/transactions/notifiedTransactions.js b/src/logic/safe/transactions/notifiedTransactions.js index 781f74c0..3e82e522 100644 --- a/src/logic/safe/transactions/notifiedTransactions.js +++ b/src/logic/safe/transactions/notifiedTransactions.js @@ -4,6 +4,7 @@ export type NotifiedTransaction = { CONNECT_WALLET_TX: string, STANDARD_TX: string, CONFIRMATION_TX: string, + CANCELLATION_TX: string, OWNER_CHANGE_TX: string, SAFE_NAME_CHANGE_TX: string, OWNER_NAME_CHANGE_TX: string, @@ -15,6 +16,7 @@ export const NOTIFIED_TRANSACTIONS: NotifiedTransaction = { CONNECT_WALLET_TX: 'CONNECT_WALLET_TX', STANDARD_TX: 'STANDARD_TX', CONFIRMATION_TX: 'CONFIRMATION_TX', + CANCELLATION_TX: 'CANCELLATION_TX', OWNER_CHANGE_TX: 'OWNER_CHANGE_TX', SAFE_NAME_CHANGE_TX: 'SAFE_NAME_CHANGE_TX', OWNER_NAME_CHANGE_TX: 'OWNER_NAME_CHANGE_TX', diff --git a/src/logic/wallets/getWeb3.js b/src/logic/wallets/getWeb3.js index e3a271a0..17dc6e23 100644 --- a/src/logic/wallets/getWeb3.js +++ b/src/logic/wallets/getWeb3.js @@ -121,6 +121,10 @@ export const getAddressFromENS = async (name: string) => { } export const getBalanceInEtherOf = async (safeAddress: string) => { + if (!web3) { + return '0' + } + const funds: String = await web3.eth.getBalance(safeAddress) if (!funds) { diff --git a/src/logic/wallets/store/actions/fetchProvider.js b/src/logic/wallets/store/actions/fetchProvider.js index 7d10e41e..8cf88103 100644 --- a/src/logic/wallets/store/actions/fetchProvider.js +++ b/src/logic/wallets/store/actions/fetchProvider.js @@ -3,9 +3,7 @@ import type { Dispatch as ReduxDispatch } from 'redux' import { ETHEREUM_NETWORK_IDS, ETHEREUM_NETWORK } from '~/logic/wallets/getWeb3' import type { ProviderProps } from '~/logic/wallets/store/model/provider' import { makeProvider } from '~/logic/wallets/store/model/provider' -import { - type Variant, SUCCESS, ERROR, WARNING, -} from '~/components/Header' +import { NOTIFICATIONS } from '~/logic/notifications' import addProvider from './addProvider' export const processProviderResponse = (dispatch: ReduxDispatch<*>, provider: ProviderProps) => { @@ -24,38 +22,35 @@ export const processProviderResponse = (dispatch: ReduxDispatch<*>, provider: Pr dispatch(addProvider(walletRecord)) } - -const CONNECT_WALLET_MSG = 'Please connect wallet to continue' -const CONNECT_WALLET_READ_MODE_MSG = 'You are in read-only mode: Please connect wallet' -const UNLOCK_MSG = 'Unlock your wallet to connect' -const WRONG_NETWORK_RINKEBY_MSG = 'Wrong network: Please use Rinkeby' -const SUCCESS_MSG = 'Wallet connected' -export const WALLET_ERROR_MSG = 'Error connecting to your wallet' - -const handleProviderNotification = ( - enqueueSnackbar: (message: string, variant: Variant) => void, - provider: ProviderProps, -) => { +const handleProviderNotification = (enqueueSnackbar: Function, closeSnackbar: Function, provider: ProviderProps) => { const { loaded, available, network } = provider if (!loaded) { - enqueueSnackbar(WALLET_ERROR_MSG, { variant: ERROR }) + enqueueSnackbar(NOTIFICATIONS.CONNECT_WALLET_ERROR_MSG.description, NOTIFICATIONS.CONNECT_WALLET_ERROR_MSG.options) return } if (ETHEREUM_NETWORK_IDS[network] !== ETHEREUM_NETWORK.RINKEBY) { - enqueueSnackbar(WRONG_NETWORK_RINKEBY_MSG, { variant: ERROR, persist: true }) + enqueueSnackbar( + NOTIFICATIONS.WRONG_NETWORK_RINKEBY_MSG.description, + NOTIFICATIONS.WRONG_NETWORK_RINKEBY_MSG.options, + ) return } + enqueueSnackbar(NOTIFICATIONS.RINKEBY_VERSION_MSG.description, NOTIFICATIONS.RINKEBY_VERSION_MSG.options) - const msg = available ? SUCCESS_MSG : UNLOCK_MSG - const variant = { variant: (available ? SUCCESS : WARNING) } - enqueueSnackbar(msg, variant) + if (available) { + enqueueSnackbar(NOTIFICATIONS.WALLET_CONNECTED_MSG.description, NOTIFICATIONS.WALLET_CONNECTED_MSG.options) + } else { + enqueueSnackbar(NOTIFICATIONS.UNLOCK_WALLET_MSG.description, NOTIFICATIONS.UNLOCK_WALLET_MSG.options) + } } -export default (provider: ProviderProps, enqueueSnackbar: (message: string, variant: Variant) => void) => ( - dispatch: ReduxDispatch<*>, -) => { - handleProviderNotification(enqueueSnackbar, provider) +export default ( + provider: ProviderProps, + enqueueSnackbar: Function, + closeSnackbar: Function, +) => (dispatch: ReduxDispatch<*>) => { + handleProviderNotification(enqueueSnackbar, closeSnackbar, provider) processProviderResponse(dispatch, provider) } diff --git a/src/logic/wallets/store/actions/removeProvider.js b/src/logic/wallets/store/actions/removeProvider.js index 99993d41..c3cd2b44 100644 --- a/src/logic/wallets/store/actions/removeProvider.js +++ b/src/logic/wallets/store/actions/removeProvider.js @@ -1,10 +1,10 @@ // @flow import type { Dispatch as ReduxDispatch } from 'redux' import { makeProvider, type ProviderProps, type Provider } from '~/logic/wallets/store/model/provider' -import { type Variant, INFO } from '~/components/Header' +import { NOTIFICATIONS } from '~/logic/notifications' import addProvider from './addProvider' -export default (enqueueSnackbar: (message: string, variant: Variant) => void) => async (dispatch: ReduxDispatch<*>) => { +export default (enqueueSnackbar: Function) => async (dispatch: ReduxDispatch<*>) => { const providerProps: ProviderProps = { name: '', available: false, @@ -14,7 +14,7 @@ export default (enqueueSnackbar: (message: string, variant: Variant) => void) => } const provider: Provider = makeProvider(providerProps) - enqueueSnackbar('Wallet disconnected succesfully', { variant: INFO }) + enqueueSnackbar(NOTIFICATIONS.WALLET_DISCONNECTED_MSG.description, NOTIFICATIONS.WALLET_DISCONNECTED_MSG.options) dispatch(addProvider(provider)) } diff --git a/src/routes/safe/components/Balances/SendModal/screens/ReviewCustomTx/index.jsx b/src/routes/safe/components/Balances/SendModal/screens/ReviewCustomTx/index.jsx index 9fab6db2..0724e35c 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ReviewCustomTx/index.jsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ReviewCustomTx/index.jsx @@ -69,7 +69,7 @@ const ReviewCustomTx = ({ txData, NOTIFIED_TRANSACTIONS.STANDARD_TX, enqueueSnackbar, - closeSnackbar + closeSnackbar, ) onClose() } From 799d7631ee4fbc111236bc9316ec1bf879d7d126 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Mon, 23 Sep 2019 14:00:01 +0200 Subject: [PATCH 29/50] Hide icon in INFO notifications --- src/components/layout/PageFrame/index.jsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/layout/PageFrame/index.jsx b/src/components/layout/PageFrame/index.jsx index 0e2057b0..3dccd1a0 100644 --- a/src/components/layout/PageFrame/index.jsx +++ b/src/components/layout/PageFrame/index.jsx @@ -43,7 +43,7 @@ const notificationStyles = { fontFamily: 'Averta', fontSize: '14px', lineHeight: 1.43, - color: '#001428', + color: '#ffffff', minHeight: '58px', boxShadow: '0 0 10px 0 rgba(212, 212, 211, 0.59)', }, @@ -69,6 +69,7 @@ const PageFrame = ({ children, classes }: Props) => ( success: , error: , warning: , + info: '', }} > From 1244b4528a0e59f6f24ba1166ce81062ea3ea8b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Mon, 23 Sep 2019 21:40:28 +0200 Subject: [PATCH 30/50] Refactor change Safe name notification --- .../safe/components/Settings/ChangeSafeName/index.jsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/routes/safe/components/Settings/ChangeSafeName/index.jsx b/src/routes/safe/components/Settings/ChangeSafeName/index.jsx index 51d5ca13..52bf358f 100644 --- a/src/routes/safe/components/Settings/ChangeSafeName/index.jsx +++ b/src/routes/safe/components/Settings/ChangeSafeName/index.jsx @@ -12,8 +12,8 @@ import GnoForm from '~/components/forms/GnoForm' import Row from '~/components/layout/Row' import Paragraph from '~/components/layout/Paragraph' import Button from '~/components/layout/Button' -import { type Variant, SUCCESS } from '~/components/Header' -import { NOTIFICATIONS } from '~/logic/notifications' +import { getNofiticationsFromTxType } from '~/logic/notifications' +import { NOTIFIED_TRANSACTIONS } from '~/logic/safe/transactions' import { styles } from './style' export const SAFE_NAME_INPUT_TEST_ID = 'safe-name-input' @@ -24,7 +24,7 @@ type Props = { safeAddress: string, safeName: string, updateSafe: Function, - enqueueSnackbar: (message: string, variant: Variant) => void, + enqueueSnackbar: Function, } const ChangeSafeName = (props: Props) => { @@ -34,7 +34,9 @@ const ChangeSafeName = (props: Props) => { const handleSubmit = (values) => { updateSafe({ address: safeAddress, name: values.safeName }) - enqueueSnackbar(NOTIFICATIONS.SAFE_NAME_CHANGED_MSG, { variant: SUCCESS }) + + const notification = getNofiticationsFromTxType(NOTIFIED_TRANSACTIONS.SAFE_NAME_CHANGE_TX) + enqueueSnackbar(notification.afterExecution.description, notification.afterExecution.options) } return ( From 8d8d45dd442206d8f34fc37b4b72317676baf28a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Tue, 24 Sep 2019 11:00:37 +0200 Subject: [PATCH 31/50] Refactor execute and process transaction --- src/logic/safe/transactions/send.js | 37 +++++++++++--- .../safe/store/actions/createTransaction.js | 48 ++++++++++++------- .../safe/store/actions/processTransaction.js | 20 ++++---- 3 files changed, 74 insertions(+), 31 deletions(-) diff --git a/src/logic/safe/transactions/send.js b/src/logic/safe/transactions/send.js index 4e34a31b..b12393e9 100644 --- a/src/logic/safe/transactions/send.js +++ b/src/logic/safe/transactions/send.js @@ -7,6 +7,7 @@ import { isEther } from '~/logic/tokens/utils/tokenHelpers' import { type Token } from '~/logic/tokens/store/model/token' import { getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts' import { type Operation, saveTxToHistory } from '~/logic/safe/transactions' +import { type NotificationsQueue } from '~/logic/notifications' import { ZERO_ADDRESS } from '~/logic/wallets/ethAddresses' import { getErrorMessage } from '~/test/utils/ethereumErrors' @@ -15,7 +16,9 @@ export const TX_TYPE_EXECUTION = 'execution' export const TX_TYPE_CONFIRMATION = 'confirmation' export const approveTransaction = async ( - showNotification: Function, + notiQueue: NotificationsQueue, + enqueueSnackbar: Function, + closeSnackbar: Function, safeInstance: any, to: string, valueInWei: number | string, @@ -40,6 +43,8 @@ export const approveTransaction = async ( }, ) + const beforeExecutionKey = enqueueSnackbar(notiQueue.beforeExecution.description, notiQueue.beforeExecution.options) + let pendingExecutionKey try { const web3 = getWeb3() const contract = new web3.eth.Contract(GnosisSafeSol.abi, safeInstance.address) @@ -50,13 +55,18 @@ export const approveTransaction = async ( from: sender, }) .once('transactionHash', () => { - showNotification() + closeSnackbar(beforeExecutionKey) + pendingExecutionKey = enqueueSnackbar( + notiQueue.pendingExecution.single.description, + notiQueue.pendingExecution.single.options, + ) }) .on('error', (error) => { /* eslint-disable */ console.log('Tx error:', error) }) .then(async (receipt) => { + closeSnackbar(pendingExecutionKey) await saveTxToHistory( safeInstance, to, @@ -68,12 +78,15 @@ export const approveTransaction = async ( sender, TX_TYPE_CONFIRMATION, ) - + enqueueSnackbar(notiQueue.afterExecution.description, notiQueue.afterExecution.options) return receipt.transactionHash }) return transactionHash } catch (error) { + closeSnackbar(pendingExecutionKey) + enqueueSnackbar(notiQueue.afterExecutionError.description, notiQueue.afterExecutionError.options) + /* eslint-disable */ const executeData = safeInstance.contract.methods.approveHash(txHash).encodeABI() const errMsg = await getErrorMessage(safeInstance.address, 0, executeData, sender) @@ -84,7 +97,9 @@ export const approveTransaction = async ( } export const executeTransaction = async ( - showNotification: Function, + notiQueue: NotificationsQueue, + enqueueSnackbar: Function, + closeSnackbar: Function, safeInstance: any, to: string, valueInWei: number | string, @@ -104,6 +119,8 @@ export const executeTransaction = async ( )}000000000000000000000000000000000000000000000000000000000000000001` } + const beforeExecutionKey = enqueueSnackbar(notiQueue.beforeExecution.description, notiQueue.beforeExecution.options) + let pendingExecutionKey try { const web3 = getWeb3() const contract = new web3.eth.Contract(GnosisSafeSol.abi, safeInstance.address) @@ -114,12 +131,17 @@ export const executeTransaction = async ( from: sender, }) .once('transactionHash', () => { - showNotification() + closeSnackbar(beforeExecutionKey) + pendingExecutionKey = enqueueSnackbar( + notiQueue.pendingExecution.single.description, + notiQueue.pendingExecution.single.options, + ) }) .on('error', (error) => { console.log('Tx error:', error) }) .then(async (receipt) => { + closeSnackbar(pendingExecutionKey) await saveTxToHistory( safeInstance, to, @@ -131,12 +153,15 @@ export const executeTransaction = async ( sender, TX_TYPE_EXECUTION, ) - + enqueueSnackbar(notiQueue.afterExecution.description, notiQueue.afterExecution.options) return receipt.transactionHash }) return transactionHash } catch (error) { + closeSnackbar(beforeExecutionKey) + enqueueSnackbar(notiQueue.afterExecutionError.description, notiQueue.afterExecutionError.options) + /* eslint-disable */ const executeDataUsedSignatures = safeInstance.contract.methods .execTransaction(to, valueInWei, data, operation, 0, 0, 0, ZERO_ADDRESS, ZERO_ADDRESS, sigs) diff --git a/src/routes/safe/store/actions/createTransaction.js b/src/routes/safe/store/actions/createTransaction.js index ca81e81a..244ee24d 100644 --- a/src/routes/safe/store/actions/createTransaction.js +++ b/src/routes/safe/store/actions/createTransaction.js @@ -6,24 +6,19 @@ import fetchTransactions from '~/routes/safe/store/actions/fetchTransactions' import { type GlobalState } from '~/store' import { getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts' import { - approveTransaction, - executeTransaction, - CALL, + type NotifiedTransaction, approveTransaction, executeTransaction, CALL, } from '~/logic/safe/transactions' -import { - type Notifications, - NOTIFICATIONS, -} from '~/logic/notifications' -import { type Variant, SUCCESS, ERROR } from '~/components/Header' +import { getNofiticationsFromTxType } from '~/logic/notifications' const createTransaction = ( safeAddress: string, to: string, valueInWei: string, txData: string = EMPTY_DATA, - enqueueSnackbar: (message: string, variant: Variant) => void, + notifiedTransaction: NotifiedTransaction, + enqueueSnackbar: Function, + closeSnackbar: Function, shouldExecute?: boolean, - notifications?: Notifications = NOTIFICATIONS, ) => async (dispatch: ReduxDispatch, getState: GetState) => { const state: GlobalState = getState() @@ -33,19 +28,38 @@ const createTransaction = ( const nonce = (await safeInstance.nonce()).toString() const isExecution = threshold.toNumber() === 1 || shouldExecute + const notificationsQueue = getNofiticationsFromTxType(notifiedTransaction) + let txHash try { if (isExecution) { - const showNotification = () => enqueueSnackbar(notifications.BEFORE_EXECUTION_OR_CREATION, { variant: SUCCESS }) - txHash = await executeTransaction(showNotification, safeInstance, to, valueInWei, txData, CALL, nonce, from) - enqueueSnackbar(notifications.AFTER_EXECUTION, { variant: SUCCESS }) + txHash = await executeTransaction( + notificationsQueue, + enqueueSnackbar, + closeSnackbar, + safeInstance, + to, + valueInWei, + txData, + CALL, + nonce, + from, + ) } else { - const showNotification = () => enqueueSnackbar(notifications.BEFORE_EXECUTION_OR_CREATION, { variant: SUCCESS }) - txHash = await approveTransaction(showNotification, safeInstance, to, valueInWei, txData, CALL, nonce, from) - enqueueSnackbar(notifications.CREATED_MORE_CONFIRMATIONS_NEEDED, { variant: SUCCESS }) + txHash = await approveTransaction( + notificationsQueue, + enqueueSnackbar, + closeSnackbar, + safeInstance, + to, + valueInWei, + txData, + CALL, + nonce, + from, + ) } } catch (err) { - enqueueSnackbar(notifications.ERROR, { variant: ERROR }) console.error(`Error while creating transaction: ${err}`) } diff --git a/src/routes/safe/store/actions/processTransaction.js b/src/routes/safe/store/actions/processTransaction.js index ead68054..4cded12b 100644 --- a/src/routes/safe/store/actions/processTransaction.js +++ b/src/routes/safe/store/actions/processTransaction.js @@ -6,7 +6,7 @@ import fetchTransactions from '~/routes/safe/store/actions/fetchTransactions' import { type GlobalState } from '~/store' import { getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts' import { approveTransaction, executeTransaction, CALL } from '~/logic/safe/transactions' -import { type Variant, SUCCESS } from '~/components/Header' +import { getNofiticationsFromTxType } from '~/logic/notifications' // https://gnosis-safe.readthedocs.io/en/latest/contracts/signatures.html#pre-validated-signatures // https://github.com/gnosis/safe-contracts/blob/master/test/gnosisSafeTeamEdition.js#L26 @@ -32,8 +32,10 @@ const generateSignaturesFromTxConfirmations = (tx: Transaction, preApprovingOwne const processTransaction = ( safeAddress: string, tx: Transaction, - enqueueSnackbar: (message: string, variant: Variant) => void, userAddress: string, + notifiedTransaction: NotifiedTransaction, + enqueueSnackbar: Function, + closeSnackbar: Function, approveAndExecute?: boolean, ) => async (dispatch: ReduxDispatch, getState: GetState) => { const state: GlobalState = getState() @@ -45,11 +47,14 @@ const processTransaction = ( const shouldExecute = threshold === tx.confirmations.size || approveAndExecute const sigs = generateSignaturesFromTxConfirmations(tx, approveAndExecute && userAddress) + const notificationsQueue = getNofiticationsFromTxType(notifiedTransaction) + let txHash if (shouldExecute) { - const showNotification = () => enqueueSnackbar('Transaction has been submitted', { variant: SUCCESS }) txHash = await executeTransaction( - showNotification, + notificationsQueue, + enqueueSnackbar, + closeSnackbar, safeInstance, tx.recipient, tx.value, @@ -59,11 +64,11 @@ const processTransaction = ( from, sigs, ) - enqueueSnackbar('Transaction has been confirmed', { variant: SUCCESS }) } else { - const showNotification = () => enqueueSnackbar('Approval transaction has been submitted', { variant: SUCCESS }) txHash = await approveTransaction( - showNotification, + notificationsQueue, + enqueueSnackbar, + closeSnackbar, safeInstance, tx.recipient, tx.value, @@ -72,7 +77,6 @@ const processTransaction = ( nonce, from, ) - enqueueSnackbar('Approval transaction has been confirmed', { variant: SUCCESS }) } dispatch(fetchTransactions(safeAddress)) From f8c9539e681e0d45dbb8adc8929596c08e2b521c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Tue, 24 Sep 2019 11:38:59 +0200 Subject: [PATCH 32/50] Format code --- src/logic/safe/transactions/send.js | 13 ++++++------- src/logic/wallets/store/actions/fetchProvider.js | 8 +++----- src/routes/safe/store/actions/addSafe.js | 5 +---- src/routes/safe/store/actions/fetchTransactions.js | 2 +- src/store/index.js | 5 +---- 5 files changed, 12 insertions(+), 21 deletions(-) diff --git a/src/logic/safe/transactions/send.js b/src/logic/safe/transactions/send.js index b12393e9..94cefa83 100644 --- a/src/logic/safe/transactions/send.js +++ b/src/logic/safe/transactions/send.js @@ -62,8 +62,7 @@ export const approveTransaction = async ( ) }) .on('error', (error) => { - /* eslint-disable */ - console.log('Tx error:', error) + console.error('Tx error:', error) }) .then(async (receipt) => { closeSnackbar(pendingExecutionKey) @@ -84,13 +83,13 @@ export const approveTransaction = async ( return transactionHash } catch (error) { + closeSnackbar(beforeExecutionKey) closeSnackbar(pendingExecutionKey) enqueueSnackbar(notiQueue.afterExecutionError.description, notiQueue.afterExecutionError.options) - /* eslint-disable */ const executeData = safeInstance.contract.methods.approveHash(txHash).encodeABI() const errMsg = await getErrorMessage(safeInstance.address, 0, executeData, sender) - console.log(`Error executing the TX: ${errMsg}`) + console.error(`Error executing the TX: ${errMsg}`) throw error } @@ -138,7 +137,7 @@ export const executeTransaction = async ( ) }) .on('error', (error) => { - console.log('Tx error:', error) + console.error('Tx error:', error) }) .then(async (receipt) => { closeSnackbar(pendingExecutionKey) @@ -160,14 +159,14 @@ export const executeTransaction = async ( return transactionHash } catch (error) { closeSnackbar(beforeExecutionKey) + closeSnackbar(pendingExecutionKey) enqueueSnackbar(notiQueue.afterExecutionError.description, notiQueue.afterExecutionError.options) - /* eslint-disable */ const executeDataUsedSignatures = safeInstance.contract.methods .execTransaction(to, valueInWei, data, operation, 0, 0, 0, ZERO_ADDRESS, ZERO_ADDRESS, sigs) .encodeABI() const errMsg = await getErrorMessage(safeInstance.address, 0, executeDataUsedSignatures, sender) - console.log(`Error executing the TX: ${errMsg}`) + console.error(`Error executing the TX: ${errMsg}`) throw error } diff --git a/src/logic/wallets/store/actions/fetchProvider.js b/src/logic/wallets/store/actions/fetchProvider.js index 8cf88103..be269b54 100644 --- a/src/logic/wallets/store/actions/fetchProvider.js +++ b/src/logic/wallets/store/actions/fetchProvider.js @@ -46,11 +46,9 @@ const handleProviderNotification = (enqueueSnackbar: Function, closeSnackbar: Fu } } -export default ( - provider: ProviderProps, - enqueueSnackbar: Function, - closeSnackbar: Function, -) => (dispatch: ReduxDispatch<*>) => { +export default (provider: ProviderProps, enqueueSnackbar: Function, closeSnackbar: Function) => ( + dispatch: ReduxDispatch<*>, +) => { handleProviderNotification(enqueueSnackbar, closeSnackbar, provider) processProviderResponse(dispatch, provider) } diff --git a/src/routes/safe/store/actions/addSafe.js b/src/routes/safe/store/actions/addSafe.js index 5a6bbf1b..ccc307ea 100644 --- a/src/routes/safe/store/actions/addSafe.js +++ b/src/routes/safe/store/actions/addSafe.js @@ -24,10 +24,7 @@ export const addSafe = createAction(ADD_SAFE, (s safe, })) -const saveSafe = (safe: Safe) => ( - dispatch: ReduxDispatch, - getState: GetState, -) => { +const saveSafe = (safe: Safe) => (dispatch: ReduxDispatch, getState: GetState) => { const state = getState() const safeList = safesListSelector(state) diff --git a/src/routes/safe/store/actions/fetchTransactions.js b/src/routes/safe/store/actions/fetchTransactions.js index a56949a3..2dcf4b15 100644 --- a/src/routes/safe/store/actions/fetchTransactions.js +++ b/src/routes/safe/store/actions/fetchTransactions.js @@ -14,7 +14,7 @@ import { EMPTY_DATA } from '~/logic/wallets/ethTransactions' import { addTransactions } from './addTransactions' import { getHumanFriendlyToken } from '~/logic/tokens/store/actions/fetchTokens' import { isTokenTransfer } from '~/logic/tokens/utils/tokenHelpers' -import { TX_TYPE_EXECUTION } from '~/logic/safe/transactions/send' +import { TX_TYPE_EXECUTION } from '~/logic/safe/transactions' import { decodeParamsFromSafeMethod } from '~/logic/contracts/methodIds' let web3 diff --git a/src/store/index.js b/src/store/index.js index 0d514224..2d225d50 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -37,9 +37,6 @@ const reducers: Reducer = combineReducers({ [TRANSACTIONS_REDUCER_ID]: transactions, }) -export const store: Store = createStore( - reducers, - finalCreateStore, -) +export const store: Store = createStore(reducers, finalCreateStore) export const aNewStore = (localState?: Object): Store => createStore(reducers, localState, finalCreateStore) From 64ba0aa91741d10b7088663dc8f6cf9a49af44f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Wed, 25 Sep 2019 14:44:24 +0200 Subject: [PATCH 33/50] Remove Safe blockchain operations --- .../transactions/safeBlockchainOperations.js | 142 ------------------ 1 file changed, 142 deletions(-) delete mode 100644 src/logic/safe/transactions/safeBlockchainOperations.js diff --git a/src/logic/safe/transactions/safeBlockchainOperations.js b/src/logic/safe/transactions/safeBlockchainOperations.js deleted file mode 100644 index 8e0863e5..00000000 --- a/src/logic/safe/transactions/safeBlockchainOperations.js +++ /dev/null @@ -1,142 +0,0 @@ -// // @flow -// import { List } from 'immutable' -// import { calculateGasOf, checkReceiptStatus, calculateGasPrice } from '~/logic/wallets/ethTransactions' -// import { type Operation, saveTxToHistory } from '~/logic/safe/transactions' -// import { getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts' -// import { buildSignaturesFrom } from '~/logic/safe/safeTxSigner' -// import { generateMetamaskSignature, generateTxGasEstimateFrom, estimateDataGas } from '~/logic/safe/transactions' -// import { storeSignature, getSignaturesFrom } from '~/utils/storage/signatures' -// import { signaturesViaMetamask } from '~/config' - -// export const approveTransaction = async ( -// safeAddress: string, -// to: string, -// valueInWei: number, -// data: string, -// operation: Operation, -// nonce: number, -// sender: string, -// ) => { -// const gasPrice = await calculateGasPrice() - -// if (signaturesViaMetamask()) { -// // return executeTransaction(safeAddress, to, valueInWei, data, operation, nonce, sender) -// const safe = await getGnosisSafeInstanceAt(safeAddress) -// const txGasEstimate = await generateTxGasEstimateFrom(safe, safeAddress, data, to, valueInWei, operation) -// const signature = await generateMetamaskSignature( -// safe, -// safeAddress, -// // sender -// to, -// valueInWei, -// nonce, -// data, -// operation, -// txGasEstimate, -// ) -// storeSignature(safeAddress, nonce, signature) - -// return undefined -// } - -// const gnosisSafe = await getGnosisSafeInstanceAt(safeAddress) -// const contractTxHash = await gnosisSafe.getTransactionHash(to, valueInWei, data, operation, 0, 0, 0, 0, 0, nonce) - -// const approveData = gnosisSafe.contract.methods.approveHash(contractTxHash).encodeABI() -// const gas = await calculateGasOf(approveData, sender, safeAddress) -// const txReceipt = await gnosisSafe.approveHash(contractTxHash, { from: sender, gas, gasPrice }) - -// const txHash = txReceipt.tx -// await checkReceiptStatus(txHash) - -// await saveTxToHistory(safeAddress, to, valueInWei, data, operation, nonce, txHash, sender, 'confirmation') - -// return txHash -// } - -// // export const executeTransaction = async ( -// // safeAddress: string, -// // to: string, -// // valueInWei: number, -// // data: string, -// // operation: Operation, -// // nonce: number, -// // sender: string, -// // ownersWhoHasSigned: List, -// // ) => { -// // const gasPrice = await calculateGasPrice() - -// // if (signaturesViaMetamask()) { -// // const safe = await getSafeEthereumInstance(safeAddress) -// // const txGasEstimate = await generateTxGasEstimateFrom(safe, safeAddress, data, to, valueInWei, operation) -// // const signature = await generateMetamaskSignature( -// // safe, -// // safeAddress, -// // sender, -// // to, -// // valueInWei, -// // nonce, -// // data, -// // operation, -// // txGasEstimate, -// // ) -// // storeSignature(safeAddress, nonce, signature) - -// // const sigs = getSignaturesFrom(safeAddress, nonce) -// // const threshold = await safe.getThreshold() -// // const gas = await estimateDataGas( -// // safe, -// // to, -// // valueInWei, -// // data, -// // operation, -// // txGasEstimate, -// // 0, -// // nonce, -// // Number(threshold), -// // 0, -// // ) -// // const numOwners = await safe.getOwners() -// // const gasIncludingRemovingStoreUpfront = gas + txGasEstimate + numOwners.length * 15000 - -// // const txReceipt = await safe.execTransaction( -// // to, -// // valueInWei, -// // data, -// // operation, -// // txGasEstimate, -// // 0, // dataGasEstimate -// // 0, // gasPrice -// // 0, // txGasToken -// // 0, // refundReceiver -// // sigs, -// // { from: sender, gas: gasIncludingRemovingStoreUpfront, gasPrice }, -// // ) - -// // const txHash = txReceipt.tx -// // await checkReceiptStatus(txHash) -// // // await submitOperation(safeAddress, to, valueInWei, data, operation, nonce, txHash, sender, 'execution') - -// // return txHash -// // } - -// // const gnosisSafe = await getSafeEthereumInstance(safeAddress) -// // const signatures = buildSignaturesFrom(ownersWhoHasSigned, sender) -// // const txExecutionData = gnosisSafe.contract.methods -// // .execTransaction(to, valueInWei, data, operation, 0, 0, 0, 0, 0, signatures) -// // .encodeABI() -// // const gas = await calculateGasOf(txExecutionData, sender, safeAddress) -// // const numOwners = await gnosisSafe.getOwners() -// // const gasIncludingRemovingStoreUpfront = gas + numOwners.length * 15000 -// // const txReceipt = await gnosisSafe.execTransaction(to, valueInWei, data, operation, 0, 0, 0, 0, 0, signatures, { -// // from: sender, -// // gas: gasIncludingRemovingStoreUpfront, -// // gasPrice, -// // }) -// // const txHash = txReceipt.tx -// // await checkReceiptStatus(txHash) - -// // await submitOperation(safeAddress, to, valueInWei, data, operation, nonce, txHash, sender, 'execution') - -// // return txHash -// // } From 14b148afa651252a4d19654071c557d410bf6317 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Wed, 25 Sep 2019 14:51:36 +0200 Subject: [PATCH 34/50] Remove unused notified transaction messages --- src/logic/notifications/notificationBuilder.js | 8 +------- src/logic/notifications/notificationTypes.js | 10 ++++++---- src/logic/safe/transactions/notifiedTransactions.js | 4 ---- src/routes/safe/store/actions/addTransactions.js | 1 + 4 files changed, 8 insertions(+), 15 deletions(-) diff --git a/src/logic/notifications/notificationBuilder.js b/src/logic/notifications/notificationBuilder.js index fa2f9a85..f528f24f 100644 --- a/src/logic/notifications/notificationBuilder.js +++ b/src/logic/notifications/notificationBuilder.js @@ -1,6 +1,6 @@ // @flow -import { NOTIFICATIONS } from './notificationTypes' import { NOTIFIED_TRANSACTIONS } from '~/logic/safe/transactions' +import { type Notification, NOTIFICATIONS } from './notificationTypes' type NotificationsQueue = { beforeExecution: Notification, @@ -105,9 +105,6 @@ export const getNofiticationsFromTxType = (txType: string) => { let notificationsQueue: NotificationsQueue switch (txType) { - case NOTIFIED_TRANSACTIONS.CONNECT_WALLET_TX: { - break - } case NOTIFIED_TRANSACTIONS.STANDARD_TX: { notificationsQueue = standardTxNotificationsQueue break @@ -136,9 +133,6 @@ export const getNofiticationsFromTxType = (txType: string) => { notificationsQueue = thresholdChangeTxNotificationsQueue break } - case NOTIFIED_TRANSACTIONS.NETWORK_TX: { - break - } default: { notificationsQueue = defaultNotificationsQueue break diff --git a/src/logic/notifications/notificationTypes.js b/src/logic/notifications/notificationTypes.js index fe9686dd..993a01be 100644 --- a/src/logic/notifications/notificationTypes.js +++ b/src/logic/notifications/notificationTypes.js @@ -11,10 +11,12 @@ export type Variant = SUCCESS | ERROR | WARNING | INFO export type Notification = { description: string, - variant: Variant, - persist: boolean, - autoHideDuration?: shortDuration | longDuration, - preventDuplicate: boolean, + options: { + variant: Variant, + persist: boolean, + autoHideDuration?: shortDuration | longDuration, + preventDuplicate: boolean, + }, } export type Notifications = { diff --git a/src/logic/safe/transactions/notifiedTransactions.js b/src/logic/safe/transactions/notifiedTransactions.js index 3e82e522..51d72558 100644 --- a/src/logic/safe/transactions/notifiedTransactions.js +++ b/src/logic/safe/transactions/notifiedTransactions.js @@ -1,7 +1,6 @@ // @flow export type NotifiedTransaction = { - CONNECT_WALLET_TX: string, STANDARD_TX: string, CONFIRMATION_TX: string, CANCELLATION_TX: string, @@ -9,11 +8,9 @@ export type NotifiedTransaction = { SAFE_NAME_CHANGE_TX: string, OWNER_NAME_CHANGE_TX: string, THRESHOLD_CHANGE_TX: string, - NETWORK_TX: string, } export const NOTIFIED_TRANSACTIONS: NotifiedTransaction = { - CONNECT_WALLET_TX: 'CONNECT_WALLET_TX', STANDARD_TX: 'STANDARD_TX', CONFIRMATION_TX: 'CONFIRMATION_TX', CANCELLATION_TX: 'CANCELLATION_TX', @@ -21,5 +18,4 @@ export const NOTIFIED_TRANSACTIONS: NotifiedTransaction = { SAFE_NAME_CHANGE_TX: 'SAFE_NAME_CHANGE_TX', OWNER_NAME_CHANGE_TX: 'OWNER_NAME_CHANGE_TX', THRESHOLD_CHANGE_TX: 'THRESHOLD_CHANGE_TX', - NETWORK_TX: 'NETWORK_TX', } diff --git a/src/routes/safe/store/actions/addTransactions.js b/src/routes/safe/store/actions/addTransactions.js index 50086b5a..f608ffd8 100644 --- a/src/routes/safe/store/actions/addTransactions.js +++ b/src/routes/safe/store/actions/addTransactions.js @@ -2,4 +2,5 @@ import { createAction } from 'redux-actions' export const ADD_TRANSACTIONS = 'ADD_TRANSACTIONS' + export const addTransactions = createAction(ADD_TRANSACTIONS) From 4335ec6c09b38656bf85213552a1af7304e25ed5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Wed, 25 Sep 2019 15:00:13 +0200 Subject: [PATCH 35/50] Update dependencies --- package.json | 8 ++-- yarn.lock | 103 +++++++++++++++++++++++++-------------------------- 2 files changed, 55 insertions(+), 56 deletions(-) diff --git a/package.json b/package.json index 115879fb..179e02ae 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "axios": "0.19.0", "bignumber.js": "9.0.0", "connected-react-router": "6.5.2", - "date-fns": "2.2.1", + "date-fns": "2.3.0", "ethereum-ens": "0.7.8", "final-form": "4.18.5", "history": "4.10.1", @@ -56,7 +56,7 @@ "react-infinite-scroll-component": "4.5.3", "react-qr-reader": "^2.2.1", "react-redux": "7.1.1", - "react-router-dom": "^5.0.1", + "react-router-dom": "^5.1.0", "recompose": "^0.30.0", "redux": "4.0.4", "redux-actions": "^2.6.5", @@ -138,10 +138,10 @@ "truffle-solidity-loader": "0.1.32", "uglifyjs-webpack-plugin": "2.2.0", "url-loader": "^2.1.0", - "webpack": "4.40.2", + "webpack": "4.41.0", "webpack-bundle-analyzer": "3.5.1", "webpack-cli": "3.3.9", "webpack-dev-server": "3.8.1", - "webpack-manifest-plugin": "^2.1.0" + "webpack-manifest-plugin": "^2.1.1" } } diff --git a/yarn.lock b/yarn.lock index f5084b74..6fb03f70 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6426,10 +6426,10 @@ data-urls@^1.0.0: whatwg-mimetype "^2.2.0" whatwg-url "^7.0.0" -date-fns@2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.2.1.tgz#b3f79cf56760af106050c686f4c72586a3383ee9" - integrity sha512-4V1i5CnTinjBvJpXTq7sDHD4NY6JPcl15112IeSNNLUWQOQ+kIuCvRGOFZMQZNvkadw8F9QTyZxz59rIRU6K+w== +date-fns@2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.3.0.tgz#017eae725d0c46173b572da025fb5e4e534270fd" + integrity sha512-A8o+iXBVqQayl9Z39BHgb7m/zLOfhF7LK82t+n9Fq1adds1vaUn8ByVoADqWLe4OTc6BZYc/FdbdTwufNYqkJw== date-now@^0.1.4: version "0.1.4" @@ -7276,13 +7276,6 @@ eslint-config-airbnb@18.0.1: object.assign "^4.1.0" object.entries "^1.1.0" -eslint-config-prettier@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.3.0.tgz#e73b48e59dc49d950843f3eb96d519e2248286a3" - integrity sha512-EWaGjlDAZRzVFveh2Jsglcere2KK5CJBhkNSa1xs3KfMUGdRiT7lG089eqPdvlzWHpAqaekubOsOMu8W8Yk71A== - dependencies: - get-stdin "^6.0.0" - eslint-import-resolver-node@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a" @@ -7345,13 +7338,6 @@ eslint-plugin-jsx-a11y@6.2.3: has "^1.0.3" jsx-ast-utils "^2.2.1" -eslint-plugin-prettier@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.1.tgz#507b8562410d02a03f0ddc949c616f877852f2ba" - integrity sha512-A+TZuHZ0KU0cnn56/9mfR7/KjUJ9QNVXUhwvRFSR7PGPe0zQR6PTkmyqg1AtUUEOzTqeRsUwyKFh0oVZKVCrtA== - dependencies: - prettier-linter-helpers "^1.0.0" - eslint-plugin-react@7.14.3: version "7.14.3" resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.14.3.tgz#911030dd7e98ba49e1b2208599571846a66bdf13" @@ -8297,11 +8283,6 @@ fast-deep-equal@^2.0.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= -fast-diff@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" - integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== - fast-glob@^2.0.2: version "2.2.7" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.7.tgz#6953857c3afa475fff92ee6015d52da70a4cd39d" @@ -9003,11 +8984,6 @@ get-params@^0.1.2: resolved "https://registry.yarnpkg.com/get-params/-/get-params-0.1.2.tgz#bae0dfaba588a0c60d7834c0d8dc2ff60eeef2fe" integrity sha1-uuDfq6WIoMYNeDTA2Nwv9g7u8v4= -get-stdin@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" - integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== - get-stdin@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-7.0.0.tgz#8d5de98f15171a125c5e516643c7a6d0ea8a96f6" @@ -14248,13 +14224,6 @@ prettier-eslint@^9.0.0: typescript "^3.2.1" vue-eslint-parser "^2.0.2" -prettier-linter-helpers@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" - integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== - dependencies: - fast-diff "^1.1.2" - prettier@^1.7.0: version "1.18.2" resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.18.2.tgz#6823e7c5900017b4bd3acf46fe9ac4b4d7bda9ea" @@ -14925,23 +14894,23 @@ react-redux@7.1.1: prop-types "^15.7.2" react-is "^16.9.0" -react-router-dom@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.0.1.tgz#ee66f4a5d18b6089c361958e443489d6bab714be" - integrity sha512-zaVHSy7NN0G91/Bz9GD4owex5+eop+KvgbxXsP/O+iW1/Ln+BrJ8QiIR5a6xNPtrdTvLkxqlDClx13QO1uB8CA== +react-router-dom@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.1.0.tgz#48ad018d71fb7835212587e4c90bd2e3d2417e31" + integrity sha512-OkxKbMKjO7IkYqnoaZNX19MnwgjhxwZE871cPUTq0YU2wpIw7QwGxSnSoNRMOa7wO1TwvJJMFpgiEB4C/gVhTw== dependencies: "@babel/runtime" "^7.1.2" history "^4.9.0" loose-envify "^1.3.1" prop-types "^15.6.2" - react-router "5.0.1" + react-router "5.1.0" tiny-invariant "^1.0.2" tiny-warning "^1.0.0" -react-router@5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.0.1.tgz#04ee77df1d1ab6cb8939f9f01ad5702dbadb8b0f" - integrity sha512-EM7suCPNKb1NxcTZ2LEOWFtQBQRQXecLxVpdsP4DW4PbbqYWeRiLyV/Tt1SdCrvT2jcyXAXmVTmzvSzrPR63Bg== +react-router@5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.1.0.tgz#739d0f3a57476363374e20d6e33e97f5ce2e00a3" + integrity sha512-n9HXxaL/6yRlig9XPfGyagI8+bUNdqcu7FUAx0/Z+Us22Z8iHsbkyJ21Inebn9HOxI5Nxlfc8GNabkNSeXfhqw== dependencies: "@babel/runtime" "^7.1.2" history "^4.9.0" @@ -19821,13 +19790,14 @@ webpack-log@^2.0.0: ansi-colors "^3.0.0" uuid "^3.3.2" -webpack-manifest-plugin@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/webpack-manifest-plugin/-/webpack-manifest-plugin-2.1.0.tgz#5c7c6b3bcfc28fa4a32bcd63c739a83a04eb41bf" - integrity sha512-vQn/mY9okBQUim6fQo+8lYzn/MWcSMGbGpQyKIR6c6NF++lVxfzdlZBL0FGVQsb1RFL/rPdKwu6hkbtWv6CEYg== +webpack-manifest-plugin@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/webpack-manifest-plugin/-/webpack-manifest-plugin-2.1.1.tgz#6b3e280327815b83152c79f42d0ca13b665773c4" + integrity sha512-2zqJ6mvc3yoiqfDjghAIpljhLSDh/G7vqGrzYcYqqRCd/ZZZCAuc/YPE5xG0LGpLgDJRhUNV1H+znyyhIxahzA== dependencies: fs-extra "^7.0.0" lodash ">=3.5 <5" + object.entries "^1.1.0" tapable "^1.0.0" webpack-sources@^1.1.0, webpack-sources@^1.3.0: @@ -19846,10 +19816,10 @@ webpack-sources@^1.4.0, webpack-sources@^1.4.1: source-list-map "^2.0.0" source-map "~0.6.1" -webpack@4.40.2, webpack@^4.38.0: - version "4.40.2" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.40.2.tgz#d21433d250f900bf0facbabe8f50d585b2dc30a7" - integrity sha512-5nIvteTDCUws2DVvP9Qe+JPla7kWPPIDFZv55To7IycHWZ+Z5qBdaBYPyuXWdhggTufZkQwfIK+5rKQTVovm2A== +webpack@4.41.0: + version "4.41.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.41.0.tgz#db6a254bde671769f7c14e90a1a55e73602fc70b" + integrity sha512-yNV98U4r7wX1VJAj5kyMsu36T8RPPQntcb5fJLOsMz/pt/WrKC0Vp1bAlqPLkA1LegSwQwf6P+kAbyhRKVQ72g== dependencies: "@webassemblyjs/ast" "1.8.5" "@webassemblyjs/helper-module-context" "1.8.5" @@ -19904,6 +19874,35 @@ webpack@^4.33.0: watchpack "^1.5.0" webpack-sources "^1.3.0" +webpack@^4.38.0: + version "4.40.2" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.40.2.tgz#d21433d250f900bf0facbabe8f50d585b2dc30a7" + integrity sha512-5nIvteTDCUws2DVvP9Qe+JPla7kWPPIDFZv55To7IycHWZ+Z5qBdaBYPyuXWdhggTufZkQwfIK+5rKQTVovm2A== + dependencies: + "@webassemblyjs/ast" "1.8.5" + "@webassemblyjs/helper-module-context" "1.8.5" + "@webassemblyjs/wasm-edit" "1.8.5" + "@webassemblyjs/wasm-parser" "1.8.5" + acorn "^6.2.1" + ajv "^6.10.2" + ajv-keywords "^3.4.1" + chrome-trace-event "^1.0.2" + enhanced-resolve "^4.1.0" + eslint-scope "^4.0.3" + json-parse-better-errors "^1.0.2" + loader-runner "^2.4.0" + loader-utils "^1.2.3" + memory-fs "^0.4.1" + micromatch "^3.1.10" + mkdirp "^0.5.1" + neo-async "^2.6.1" + node-libs-browser "^2.2.1" + schema-utils "^1.0.0" + tapable "^1.1.3" + terser-webpack-plugin "^1.4.1" + watchpack "^1.6.0" + webpack-sources "^1.4.1" + webrtc-adapter@^7.2.1: version "7.2.8" resolved "https://registry.yarnpkg.com/webrtc-adapter/-/webrtc-adapter-7.2.8.tgz#1373fa874559c655aa713830c2836511588d77ab" From d4ed0d7f4a0902072b424ba403481678eaffc727 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Wed, 25 Sep 2019 15:08:33 +0200 Subject: [PATCH 36/50] Add models, reducers, actions and selectors for notification handling --- .../store/actions/closeSnackbar.js | 8 ++++ .../store/actions/enqueueSnackbar.js | 24 ++++++++++++ .../store/actions/removeSnackbar.js | 8 ++++ .../store/models/notification.js | 17 +++++++++ .../store/reducer/notifications.js | 38 +++++++++++++++++++ .../notifications/store/selectors/index.js | 15 ++++++++ .../wallets/store/actions/fetchProvider.js | 25 +++++++++--- src/store/index.js | 16 ++++++-- 8 files changed, 142 insertions(+), 9 deletions(-) create mode 100644 src/logic/notifications/store/actions/closeSnackbar.js create mode 100644 src/logic/notifications/store/actions/enqueueSnackbar.js create mode 100644 src/logic/notifications/store/actions/removeSnackbar.js create mode 100644 src/logic/notifications/store/models/notification.js create mode 100644 src/logic/notifications/store/reducer/notifications.js create mode 100644 src/logic/notifications/store/selectors/index.js diff --git a/src/logic/notifications/store/actions/closeSnackbar.js b/src/logic/notifications/store/actions/closeSnackbar.js new file mode 100644 index 00000000..4e63a1a9 --- /dev/null +++ b/src/logic/notifications/store/actions/closeSnackbar.js @@ -0,0 +1,8 @@ +// @flow +import { createAction } from 'redux-actions' + +export const CLOSE_SNACKBAR = 'CLOSE_SNACKBAR' + +const closeSnackbar = createAction(CLOSE_SNACKBAR) + +export default closeSnackbar diff --git a/src/logic/notifications/store/actions/enqueueSnackbar.js b/src/logic/notifications/store/actions/enqueueSnackbar.js new file mode 100644 index 00000000..f44ac1f8 --- /dev/null +++ b/src/logic/notifications/store/actions/enqueueSnackbar.js @@ -0,0 +1,24 @@ +// @flow +import { createAction } from 'redux-actions' +import type { Dispatch as ReduxDispatch, GetState } from 'redux' +import { type GlobalState } from '~/store' +import { type NotificationProps } from '~/logic/notifications/store/models/notification' + +export const ENQUEUE_SNACKBAR = 'ENQUEUE_SNACKBAR' + +const addSnackbar = createAction(ENQUEUE_SNACKBAR, (notification: NotificationProps): ActionReturn => ({ + notification, +})) + +const enqueueSnackbar = (notification: NotificationProps) => ( + dispatch: ReduxDispatch, + getState: GetState, +) => { + const newNotification = { + ...notification, + key: new Date().getTime() + Math.random(), + } + dispatch(addSnackbar(newNotification)) +} + +export default enqueueSnackbar diff --git a/src/logic/notifications/store/actions/removeSnackbar.js b/src/logic/notifications/store/actions/removeSnackbar.js new file mode 100644 index 00000000..8ecaee83 --- /dev/null +++ b/src/logic/notifications/store/actions/removeSnackbar.js @@ -0,0 +1,8 @@ +// @flow +import { createAction } from 'redux-actions' + +export const REMOVE_SNACKBAR = 'REMOVE_SNACKBAR' + +const removeSnackbar = createAction(REMOVE_SNACKBAR) + +export default removeSnackbar diff --git a/src/logic/notifications/store/models/notification.js b/src/logic/notifications/store/models/notification.js new file mode 100644 index 00000000..9a25a6c2 --- /dev/null +++ b/src/logic/notifications/store/models/notification.js @@ -0,0 +1,17 @@ +// @flow +import { Record } from 'immutable' +import type { RecordFactory, RecordOf } from 'immutable' + +export type NotificationProps = { + message: string, + options: Object, + dismissed: boolean, +} + +export const makeNotification: RecordFactory = Record({ + message: '', + options: {}, + dismissed: false, +}) + +export type Notification = RecordOf diff --git a/src/logic/notifications/store/reducer/notifications.js b/src/logic/notifications/store/reducer/notifications.js new file mode 100644 index 00000000..9aca1c80 --- /dev/null +++ b/src/logic/notifications/store/reducer/notifications.js @@ -0,0 +1,38 @@ +// @flow +import { Map } from 'immutable' +import { handleActions, type ActionType } from 'redux-actions' +import { makeNotification, type NotificationProps } from '~/logic/notifications/store/models/notification' +import { ENQUEUE_SNACKBAR } from '../actions/enqueueSnackbar' +import { CLOSE_SNACKBAR } from '../actions/closeSnackbar' +import { REMOVE_SNACKBAR } from '../actions/removeSnackbar' + +export const NOTIFICATIONS_REDUCER_ID = 'notifications' + +export type NotificationReducerState = Map + +export default handleActions( + { + [ENQUEUE_SNACKBAR]: (state: NotificationReducerState, action: ActionType): NotificationReducerState => { + const { notification }: { notification: NotificationProps } = action.payload + + if (state.hasIn(['notifications', notification.options.key])) { + return state.updateIn(['notifications', notification.options.key], (prev) => prev.merge(notification)) + } + return state.setIn(['notifications', notification.options.key], makeNotification(notification)) + }, + [CLOSE_SNACKBAR]: (state: NotificationReducerState, action: ActionType): NotificationReducerState => { + const { notification }: { notification: NotificationProps } = action.payload + notification.dismissed = true + + return state.updateIn(['notifications', notification.key], (prev) => prev.merge(notification)) + }, + [REMOVE_SNACKBAR]: (state: NotificationReducerState, action: ActionType): NotificationReducerState => { + const key = action.payload + + return state.deleteIn(['notification', key]) + }, + }, + Map({ + notifications: Map(), + }), +) diff --git a/src/logic/notifications/store/selectors/index.js b/src/logic/notifications/store/selectors/index.js new file mode 100644 index 00000000..2ae6eb96 --- /dev/null +++ b/src/logic/notifications/store/selectors/index.js @@ -0,0 +1,15 @@ +// @flow +import { List, Map } from 'immutable' +import { createSelector, type Selector } from 'reselect' +import { type GlobalState } from '~/store' +import { NOTIFICATIONS_REDUCER_ID } from '~/logic/notifications/store/reducer/notifications' +import { type Notification } from '~/logic/notifications/store/models/notification' + +export const notificationsMapSelector = ( + state: GlobalState, +): Map => state[NOTIFICATIONS_REDUCER_ID] + +export const notificationsListSelector: Selector> = createSelector( + notificationsMapSelector, + (notifications: Map): List => notifications.toList(), +) diff --git a/src/logic/wallets/store/actions/fetchProvider.js b/src/logic/wallets/store/actions/fetchProvider.js index be269b54..084d4e07 100644 --- a/src/logic/wallets/store/actions/fetchProvider.js +++ b/src/logic/wallets/store/actions/fetchProvider.js @@ -4,6 +4,8 @@ import { ETHEREUM_NETWORK_IDS, ETHEREUM_NETWORK } from '~/logic/wallets/getWeb3' import type { ProviderProps } from '~/logic/wallets/store/model/provider' import { makeProvider } from '~/logic/wallets/store/model/provider' import { NOTIFICATIONS } from '~/logic/notifications' +import enqueueSnackbar from '~/logic/notifications/store/actions/enqueueSnackbar' +import closeSnackbar from '~/logic/notifications/store/actions/closeSnackbar' import addProvider from './addProvider' export const processProviderResponse = (dispatch: ReduxDispatch<*>, provider: ProviderProps) => { @@ -22,7 +24,7 @@ export const processProviderResponse = (dispatch: ReduxDispatch<*>, provider: Pr dispatch(addProvider(walletRecord)) } -const handleProviderNotification = (enqueueSnackbar: Function, closeSnackbar: Function, provider: ProviderProps) => { +const handleProviderNotification = (dispatch: ReduxDispatch<*>, provider: ProviderProps) => { const { loaded, available, network } = provider if (!loaded) { @@ -40,15 +42,26 @@ const handleProviderNotification = (enqueueSnackbar: Function, closeSnackbar: Fu enqueueSnackbar(NOTIFICATIONS.RINKEBY_VERSION_MSG.description, NOTIFICATIONS.RINKEBY_VERSION_MSG.options) if (available) { - enqueueSnackbar(NOTIFICATIONS.WALLET_CONNECTED_MSG.description, NOTIFICATIONS.WALLET_CONNECTED_MSG.options) + // NOTE: + // if you want to be able to dispatch a `closeSnackbar` action later on, + // you SHOULD pass your own `key` in the options. `key` can be any sequence + // of number or characters, but it has to be unique to a given snackbar. + dispatch( + enqueueSnackbar({ + message: NOTIFICATIONS.WALLET_CONNECTED_MSG.description, + options: { + ...NOTIFICATIONS.WALLET_CONNECTED_MSG.options, + key: new Date().getTime() + Math.random(), + }, + }), + ) + // enqueueSnackbar(NOTIFICATIONS.WALLET_CONNECTED_MSG.description, NOTIFICATIONS.WALLET_CONNECTED_MSG.options) } else { enqueueSnackbar(NOTIFICATIONS.UNLOCK_WALLET_MSG.description, NOTIFICATIONS.UNLOCK_WALLET_MSG.options) } } -export default (provider: ProviderProps, enqueueSnackbar: Function, closeSnackbar: Function) => ( - dispatch: ReduxDispatch<*>, -) => { - handleProviderNotification(enqueueSnackbar, closeSnackbar, provider) +export default (provider: ProviderProps) => (dispatch: ReduxDispatch<*>) => { + handleProviderNotification(dispatch, provider) processProviderResponse(dispatch, provider) } diff --git a/src/store/index.js b/src/store/index.js index 2d225d50..1e971f98 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -5,14 +5,18 @@ import { combineReducers, createStore, applyMiddleware, compose, type Reducer, type Store, } from 'redux' import thunk from 'redux-thunk' -import provider, { PROVIDER_REDUCER_ID, type State as ProviderState } from '~/logic/wallets/store/reducer/provider' import safe, { SAFE_REDUCER_ID, type SafeReducerState as SafeState } from '~/routes/safe/store/reducer/safe' import safeStorage from '~/routes/safe/store/middleware/safeStorage' -import tokens, { TOKEN_REDUCER_ID, type State as TokensState } from '~/logic/tokens/store/reducer/tokens' import transactions, { type State as TransactionsState, TRANSACTIONS_REDUCER_ID, } from '~/routes/safe/store/reducer/transactions' +import provider, { PROVIDER_REDUCER_ID, type State as ProviderState } from '~/logic/wallets/store/reducer/provider' +import tokens, { TOKEN_REDUCER_ID, type State as TokensState } from '~/logic/tokens/store/reducer/tokens' +import notifications, { + NOTIFICATIONS_REDUCER_ID, + type State as NotificationsState, +} from '~/logic/notifications/store/reducer/notifications' export const history = createBrowserHistory() @@ -25,6 +29,7 @@ export type GlobalState = { safes: SafeState, tokens: TokensState, transactions: TransactionsState, + notifications: NotificationsState, } export type GetState = () => GlobalState @@ -35,8 +40,13 @@ const reducers: Reducer = combineReducers({ [SAFE_REDUCER_ID]: safe, [TOKEN_REDUCER_ID]: tokens, [TRANSACTIONS_REDUCER_ID]: transactions, + [NOTIFICATIONS_REDUCER_ID]: notifications, }) export const store: Store = createStore(reducers, finalCreateStore) -export const aNewStore = (localState?: Object): Store => createStore(reducers, localState, finalCreateStore) +export const aNewStore = (localState?: Object): Store => createStore( + reducers, + localState, + finalCreateStore, +) From aa613de2e70e9c44cd406108712d3aeb0ff331d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Wed, 25 Sep 2019 15:14:07 +0200 Subject: [PATCH 37/50] Add Notifier component --- src/components/Notifier/actions.js | 16 +++++ src/components/Notifier/index.js | 73 +++++++++++++++++++++++ src/components/Notifier/selector.js | 7 +++ src/components/layout/PageFrame/index.jsx | 2 + 4 files changed, 98 insertions(+) create mode 100644 src/components/Notifier/actions.js create mode 100644 src/components/Notifier/index.js create mode 100644 src/components/Notifier/selector.js diff --git a/src/components/Notifier/actions.js b/src/components/Notifier/actions.js new file mode 100644 index 00000000..7cfffca1 --- /dev/null +++ b/src/components/Notifier/actions.js @@ -0,0 +1,16 @@ +// @flow +import enqueueSnackbar from '~/logic/notifications/store/actions/enqueueSnackbar' +import closeSnackbar from '~/logic/notifications/store/actions/closeSnackbar' +import removeSnackbar from '~/logic/notifications/store/actions/removeSnackbar' + +export type Actions = { + enqueueSnackbar: typeof enqueueSnackbar, + closeSnackbar: typeof closeSnackbar, + removeSnackbar: typeof removeSnackbar, +} + +export default { + enqueueSnackbar, + closeSnackbar, + removeSnackbar, +} diff --git a/src/components/Notifier/index.js b/src/components/Notifier/index.js new file mode 100644 index 00000000..3f4ad6e9 --- /dev/null +++ b/src/components/Notifier/index.js @@ -0,0 +1,73 @@ +// @flow +import React, { Component } from 'react' +import { connect } from 'react-redux' +import { withSnackbar } from 'notistack' +import actions from './actions' +import selector from './selector' + +class Notifier extends Component { + displayed = [] + + shouldComponentUpdate({ notifications: newSnacks = [] }) { + const { notifications: currentSnacks, closeSnackbar, removeSnackbar } = this.props + + if (!newSnacks.size) { + this.displayed = [] + return false + } + let notExists = false + for (let i = 0; i < newSnacks.size; i += 1) { + const newSnack = newSnacks.get(i) + + if (newSnack.dismissed) { + closeSnackbar(newSnack.key) + removeSnackbar(newSnack.key) + } + + if (notExists) { + continue + } + notExists = notExists || !currentSnacks.filter(({ key }) => newSnack.key === key).length + } + return notExists + } + + componentDidUpdate() { + const { notifications = [], enqueueSnackbar, removeSnackbar } = this.props + + notifications.map(({ key, message, options = {} }) => { + // Do nothing if snackbar is already displayed + if (this.displayed.includes(key)) { + return + } + // Display snackbar using notistack + enqueueSnackbar(message, { + ...options, + onClose: (event, reason, key) => { + if (options.onClose) { + options.onClose(event, reason, key) + } + // Dispatch action to remove snackbar from redux store + removeSnackbar(key) + }, + }) + // Keep track of snackbars that we've displayed + this.storeDisplayed(key) + }) + } + + storeDisplayed = (id) => { + this.displayed = [...this.displayed, id] + } + + render() { + return null + } +} + +export default withSnackbar( + connect( + selector, + actions, + )(Notifier), +) diff --git a/src/components/Notifier/selector.js b/src/components/Notifier/selector.js new file mode 100644 index 00000000..148b3d3b --- /dev/null +++ b/src/components/Notifier/selector.js @@ -0,0 +1,7 @@ +// @flow +import { createStructuredSelector } from 'reselect' +import { notificationsListSelector } from '~/logic/notifications/store/selectors' + +export default createStructuredSelector({ + notifications: notificationsListSelector, +}) diff --git a/src/components/layout/PageFrame/index.jsx b/src/components/layout/PageFrame/index.jsx index 3dccd1a0..6d3c71bf 100644 --- a/src/components/layout/PageFrame/index.jsx +++ b/src/components/layout/PageFrame/index.jsx @@ -5,6 +5,7 @@ import { withStyles } from '@material-ui/core/styles' import SidebarProvider from '~/components/Sidebar' import Header from '~/components/Header' import Img from '~/components/layout/Img' +import Notifier from '~/components/Notifier' import AlertLogo from './assets/alert.svg' import CheckLogo from './assets/check.svg' import ErrorLogo from './assets/error.svg' @@ -72,6 +73,7 @@ const PageFrame = ({ children, classes }: Props) => ( info: '', }} > +
{children} From 486122d0041088c40f6774af22d2923280cf4eb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Thu, 26 Sep 2019 15:13:04 +0200 Subject: [PATCH 38/50] Rename notification model variables --- src/components/Header/index.jsx | 2 +- src/logic/notifications/notificationTypes.js | 66 +++++++++---------- src/logic/safe/transactions/send.js | 16 ++--- .../wallets/store/actions/fetchProvider.js | 31 ++++----- .../wallets/store/actions/removeProvider.js | 2 +- .../Settings/ChangeSafeName/index.jsx | 2 +- .../ManageOwners/EditOwnerModal/index.jsx | 2 +- 7 files changed, 57 insertions(+), 64 deletions(-) diff --git a/src/components/Header/index.jsx b/src/components/Header/index.jsx index ce1e7a72..3c173314 100644 --- a/src/components/Header/index.jsx +++ b/src/components/Header/index.jsx @@ -42,7 +42,7 @@ class HeaderComponent extends React.PureComponent { const { enqueueSnackbar } = this.props this.setState({ hasError: true }) - enqueueSnackbar(NOTIFICATIONS.CONNECT_WALLET_ERROR_MSG.description, NOTIFICATIONS.CONNECT_WALLET_ERROR_MSG.options) + enqueueSnackbar(NOTIFICATIONS.CONNECT_WALLET_ERROR_MSG.message, NOTIFICATIONS.CONNECT_WALLET_ERROR_MSG.options) logComponentStack(error, info) } diff --git a/src/logic/notifications/notificationTypes.js b/src/logic/notifications/notificationTypes.js index 993a01be..9d92ebbd 100644 --- a/src/logic/notifications/notificationTypes.js +++ b/src/logic/notifications/notificationTypes.js @@ -10,7 +10,7 @@ const longDuration = 10000 export type Variant = SUCCESS | ERROR | WARNING | INFO export type Notification = { - description: string, + message: string, options: { variant: Variant, persist: boolean, @@ -72,15 +72,15 @@ export type Notifications = { export const NOTIFICATIONS: Notifications = { // Wallet Connection CONNECT_WALLET_MSG: { - description: 'Please connect wallet to continue', + message: 'Please connect wallet to continue', options: { variant: WARNING, persist: true, preventDuplicate: true }, }, CONNECT_WALLET_READ_MODE_MSG: { - description: 'You are in read-only mode: Please connect wallet', + message: 'You are in read-only mode: Please connect wallet', options: { variant: WARNING, persist: true, preventDuplicate: true }, }, WALLET_CONNECTED_MSG: { - description: 'Wallet connected', + message: 'Wallet connected', options: { variant: SUCCESS, persist: false, @@ -88,7 +88,7 @@ export const NOTIFICATIONS: Notifications = { }, }, WALLET_DISCONNECTED_MSG: { - description: 'Wallet disconnected', + message: 'Wallet disconnected', options: { variant: SUCCESS, persist: false, @@ -96,129 +96,129 @@ export const NOTIFICATIONS: Notifications = { }, }, UNLOCK_WALLET_MSG: { - description: 'Unlock your wallet to connect', + message: 'Unlock your wallet to connect', options: { variant: WARNING, persist: true, preventDuplicate: true }, }, CONNECT_WALLET_ERROR_MSG: { - description: 'Error connecting to your wallet', + message: 'Error connecting to your wallet', options: { variant: ERROR, persist: true }, }, // Regular/Custom Transactions SIGN_TX_MSG: { - description: 'Please sign the transaction', + message: 'Please sign the transaction', options: { variant: SUCCESS, persist: true }, }, TX_PENDING_MSG: { - description: 'Transaction pending', + message: 'Transaction pending', options: { variant: SUCCESS, persist: true }, }, TX_PENDING_MORE_CONFIRMATIONS_MSG: { - description: 'Transaction pending: More confirmations required to execute', + message: 'Transaction pending: More confirmations required to execute', options: { variant: SUCCESS, persist: true }, }, TX_REJECTED_MSG: { - description: 'Transaction rejected', + message: 'Transaction rejected', options: { variant: ERROR, persist: false, autoHideDuration: longDuration }, }, TX_EXECUTED_MSG: { - description: 'Transaction successfully executed', + message: 'Transaction successfully executed', options: { variant: SUCCESS, persist: false, autoHideDuration: longDuration }, }, TX_FAILED_MSG: { - description: 'Transaction failed', + message: 'Transaction failed', options: { variant: ERROR, persist: false, autoHideDuration: longDuration }, }, // Approval Transactions TX_CONFIRMATION_PENDING_MSG: { - description: 'Confirmation transaction pending', + message: 'Confirmation transaction pending', options: { variant: SUCCESS, persist: true }, }, TX_CONFIRMATION_EXECUTED_MSG: { - description: 'Confirmation transaction succesful', + message: 'Confirmation transaction succesful', options: { variant: SUCCESS, persist: false, autoHideDuration: longDuration }, }, TX_CONFIRMATION_FAILED_MSG: { - description: 'Confirmation transaction failed', + message: 'Confirmation transaction failed', options: { variant: ERROR, persist: false, autoHideDuration: longDuration }, }, // Safe Name SAFE_NAME_CHANGE_EXECUTED_MSG: { - description: 'Safe name changed', + message: 'Safe name changed', options: { variant: SUCCESS, persist: false, autoHideDuration: shortDuration }, }, // Owner Name OWNER_NAME_CHANGE_EXECUTED_MSG: { - description: 'Owner name changed', + message: 'Owner name changed', options: { variant: SUCCESS, persist: false, autoHideDuration: shortDuration }, }, // Owners SIGN_OWNER_CHANGE_MSG: { - description: 'Please sign the owner change', + message: 'Please sign the owner change', options: { variant: SUCCESS, persist: true }, }, ONWER_CHANGE_PENDING_MSG: { - description: 'Owner change pending', + message: 'Owner change pending', options: { variant: SUCCESS, persist: true }, }, ONWER_CHANGE_PENDING_MORE_CONFIRMATIONS_MSG: { - description: 'Owner change pending: More confirmations required to execute', + message: 'Owner change pending: More confirmations required to execute', options: { variant: SUCCESS, persist: true }, }, ONWER_CHANGE_REJECTED_MSG: { - description: 'Owner change rejected', + message: 'Owner change rejected', options: { variant: ERROR, persist: false, autoHideDuration: longDuration }, }, OWNER_CHANGE_EXECUTED_MSG: { - description: 'Owner change successfully executed', + message: 'Owner change successfully executed', options: { variant: SUCCESS, persist: false, autoHideDuration: longDuration }, }, ONWER_CHANGE_FAILED_MSG: { - description: 'Owner change failed', + message: 'Owner change failed', options: { variant: ERROR, persist: false, autoHideDuration: longDuration }, }, // Threshold SIGN_THRESHOLD_CHANGE_MSG: { - description: 'Please sign the required confirmations change', + message: 'Please sign the required confirmations change', options: { variant: SUCCESS, persist: true }, }, THRESHOLD_CHANGE_PENDING_MSG: { - description: 'Required confirmations change pending', + message: 'Required confirmations change pending', options: { variant: SUCCESS, persist: true }, }, THRESHOLD_CHANGE_PENDING_MORE_CONFIRMATIONS_MSG: { - description: 'Required confirmations change pending: More confirmations required to execute', + message: 'Required confirmations change pending: More confirmations required to execute', options: { variant: SUCCESS, persist: true }, }, THRESHOLD_CHANGE_REJECTED_MSG: { - description: 'Required confirmations change rejected', + message: 'Required confirmations change rejected', options: { variant: ERROR, persist: false, autoHideDuration: longDuration }, }, THRESHOLD_CHANGE_EXECUTED_MSG: { - description: 'Required confirmations change successfully executed', + message: 'Required confirmations change successfully executed', options: { variant: SUCCESS, persist: false, autoHideDuration: longDuration }, }, THRESHOLD_CHANGE_FAILED_MSG: { - description: 'Required confirmations change failed', + message: 'Required confirmations change failed', options: { variant: ERROR, persist: false, autoHideDuration: longDuration }, }, // Network RINKEBY_VERSION_MSG: { - description: "Rinkeby Version: Don't send mainnet assets to this Safe", + message: "Rinkeby Version: Don't send mainnet assets to this Safe", options: { variant: INFO, persist: true, preventDuplicate: true }, }, WRONG_NETWORK_RINKEBY_MSG: { - description: 'Wrong network: Please use Rinkeby', + message: 'Wrong network: Please use Rinkeby', options: { variant: WARNING, persist: true, preventDuplicate: true }, }, WRONG_NETWOEK_MAINNET_MSG: { - description: 'Wrong network: Please use Mainnet', + message: 'Wrong network: Please use Mainnet', options: { variant: WARNING, persist: true, preventDuplicate: true }, }, } diff --git a/src/logic/safe/transactions/send.js b/src/logic/safe/transactions/send.js index 94cefa83..c702d2b1 100644 --- a/src/logic/safe/transactions/send.js +++ b/src/logic/safe/transactions/send.js @@ -43,7 +43,7 @@ export const approveTransaction = async ( }, ) - const beforeExecutionKey = enqueueSnackbar(notiQueue.beforeExecution.description, notiQueue.beforeExecution.options) + const beforeExecutionKey = enqueueSnackbar(notiQueue.beforeExecution.message, notiQueue.beforeExecution.options) let pendingExecutionKey try { const web3 = getWeb3() @@ -57,7 +57,7 @@ export const approveTransaction = async ( .once('transactionHash', () => { closeSnackbar(beforeExecutionKey) pendingExecutionKey = enqueueSnackbar( - notiQueue.pendingExecution.single.description, + notiQueue.pendingExecution.single.message, notiQueue.pendingExecution.single.options, ) }) @@ -77,7 +77,7 @@ export const approveTransaction = async ( sender, TX_TYPE_CONFIRMATION, ) - enqueueSnackbar(notiQueue.afterExecution.description, notiQueue.afterExecution.options) + enqueueSnackbar(notiQueue.afterExecution.message, notiQueue.afterExecution.options) return receipt.transactionHash }) @@ -85,7 +85,7 @@ export const approveTransaction = async ( } catch (error) { closeSnackbar(beforeExecutionKey) closeSnackbar(pendingExecutionKey) - enqueueSnackbar(notiQueue.afterExecutionError.description, notiQueue.afterExecutionError.options) + enqueueSnackbar(notiQueue.afterExecutionError.message, notiQueue.afterExecutionError.options) const executeData = safeInstance.contract.methods.approveHash(txHash).encodeABI() const errMsg = await getErrorMessage(safeInstance.address, 0, executeData, sender) @@ -118,7 +118,7 @@ export const executeTransaction = async ( )}000000000000000000000000000000000000000000000000000000000000000001` } - const beforeExecutionKey = enqueueSnackbar(notiQueue.beforeExecution.description, notiQueue.beforeExecution.options) + const beforeExecutionKey = enqueueSnackbar(notiQueue.beforeExecution.message, notiQueue.beforeExecution.options) let pendingExecutionKey try { const web3 = getWeb3() @@ -132,7 +132,7 @@ export const executeTransaction = async ( .once('transactionHash', () => { closeSnackbar(beforeExecutionKey) pendingExecutionKey = enqueueSnackbar( - notiQueue.pendingExecution.single.description, + notiQueue.pendingExecution.single.message, notiQueue.pendingExecution.single.options, ) }) @@ -152,7 +152,7 @@ export const executeTransaction = async ( sender, TX_TYPE_EXECUTION, ) - enqueueSnackbar(notiQueue.afterExecution.description, notiQueue.afterExecution.options) + enqueueSnackbar(notiQueue.afterExecution.message, notiQueue.afterExecution.options) return receipt.transactionHash }) @@ -160,7 +160,7 @@ export const executeTransaction = async ( } catch (error) { closeSnackbar(beforeExecutionKey) closeSnackbar(pendingExecutionKey) - enqueueSnackbar(notiQueue.afterExecutionError.description, notiQueue.afterExecutionError.options) + enqueueSnackbar(notiQueue.afterExecutionError.message, notiQueue.afterExecutionError.options) const executeDataUsedSignatures = safeInstance.contract.methods .execTransaction(to, valueInWei, data, operation, 0, 0, 0, ZERO_ADDRESS, ZERO_ADDRESS, sigs) diff --git a/src/logic/wallets/store/actions/fetchProvider.js b/src/logic/wallets/store/actions/fetchProvider.js index 084d4e07..1e0ecc2c 100644 --- a/src/logic/wallets/store/actions/fetchProvider.js +++ b/src/logic/wallets/store/actions/fetchProvider.js @@ -4,8 +4,8 @@ import { ETHEREUM_NETWORK_IDS, ETHEREUM_NETWORK } from '~/logic/wallets/getWeb3' import type { ProviderProps } from '~/logic/wallets/store/model/provider' import { makeProvider } from '~/logic/wallets/store/model/provider' import { NOTIFICATIONS } from '~/logic/notifications' -import enqueueSnackbar from '~/logic/notifications/store/actions/enqueueSnackbar' -import closeSnackbar from '~/logic/notifications/store/actions/closeSnackbar' +// import enqueueSnackbar as enqueueSnackbarAction from '~/logic/notifications/store/actions/enqueueSnackbar' +// import closeSnackbar as closeSnackbarAction from '~/logic/notifications/store/actions/closeSnackbar' import addProvider from './addProvider' export const processProviderResponse = (dispatch: ReduxDispatch<*>, provider: ProviderProps) => { @@ -24,44 +24,37 @@ export const processProviderResponse = (dispatch: ReduxDispatch<*>, provider: Pr dispatch(addProvider(walletRecord)) } -const handleProviderNotification = (dispatch: ReduxDispatch<*>, provider: ProviderProps) => { +const handleProviderNotification = (dispatch: ReduxDispatch<*>, provider: ProviderProps, enqueueSnackbar: Function) => { const { loaded, available, network } = provider if (!loaded) { - enqueueSnackbar(NOTIFICATIONS.CONNECT_WALLET_ERROR_MSG.description, NOTIFICATIONS.CONNECT_WALLET_ERROR_MSG.options) + enqueueSnackbar(NOTIFICATIONS.CONNECT_WALLET_ERROR_MSG.message, NOTIFICATIONS.CONNECT_WALLET_ERROR_MSG.options) return } if (ETHEREUM_NETWORK_IDS[network] !== ETHEREUM_NETWORK.RINKEBY) { enqueueSnackbar( - NOTIFICATIONS.WRONG_NETWORK_RINKEBY_MSG.description, + NOTIFICATIONS.WRONG_NETWORK_RINKEBY_MSG.message, NOTIFICATIONS.WRONG_NETWORK_RINKEBY_MSG.options, ) return } - enqueueSnackbar(NOTIFICATIONS.RINKEBY_VERSION_MSG.description, NOTIFICATIONS.RINKEBY_VERSION_MSG.options) + enqueueSnackbar(NOTIFICATIONS.RINKEBY_VERSION_MSG.message, NOTIFICATIONS.RINKEBY_VERSION_MSG.options) if (available) { // NOTE: // if you want to be able to dispatch a `closeSnackbar` action later on, // you SHOULD pass your own `key` in the options. `key` can be any sequence // of number or characters, but it has to be unique to a given snackbar. - dispatch( - enqueueSnackbar({ - message: NOTIFICATIONS.WALLET_CONNECTED_MSG.description, - options: { - ...NOTIFICATIONS.WALLET_CONNECTED_MSG.options, - key: new Date().getTime() + Math.random(), - }, - }), - ) - // enqueueSnackbar(NOTIFICATIONS.WALLET_CONNECTED_MSG.description, NOTIFICATIONS.WALLET_CONNECTED_MSG.options) + + //dispatch(enqueueSnackbarAction(NOTIFICATIONS.WALLET_CONNECTED_MSG)) + enqueueSnackbar(NOTIFICATIONS.WALLET_CONNECTED_MSG.message, NOTIFICATIONS.WALLET_CONNECTED_MSG.options) } else { - enqueueSnackbar(NOTIFICATIONS.UNLOCK_WALLET_MSG.description, NOTIFICATIONS.UNLOCK_WALLET_MSG.options) + enqueueSnackbar(NOTIFICATIONS.UNLOCK_WALLET_MSG.message, NOTIFICATIONS.UNLOCK_WALLET_MSG.options) } } -export default (provider: ProviderProps) => (dispatch: ReduxDispatch<*>) => { - handleProviderNotification(dispatch, provider) +export default (provider: ProviderProps, enqueueSnackbar: Function) => (dispatch: ReduxDispatch<*>) => { + handleProviderNotification(dispatch, provider, enqueueSnackbar) processProviderResponse(dispatch, provider) } diff --git a/src/logic/wallets/store/actions/removeProvider.js b/src/logic/wallets/store/actions/removeProvider.js index c3cd2b44..cb2e6120 100644 --- a/src/logic/wallets/store/actions/removeProvider.js +++ b/src/logic/wallets/store/actions/removeProvider.js @@ -14,7 +14,7 @@ export default (enqueueSnackbar: Function) => async (dispatch: ReduxDispatch<*>) } const provider: Provider = makeProvider(providerProps) - enqueueSnackbar(NOTIFICATIONS.WALLET_DISCONNECTED_MSG.description, NOTIFICATIONS.WALLET_DISCONNECTED_MSG.options) + enqueueSnackbar(NOTIFICATIONS.WALLET_DISCONNECTED_MSG.message, NOTIFICATIONS.WALLET_DISCONNECTED_MSG.options) dispatch(addProvider(provider)) } diff --git a/src/routes/safe/components/Settings/ChangeSafeName/index.jsx b/src/routes/safe/components/Settings/ChangeSafeName/index.jsx index 52bf358f..90c392fb 100644 --- a/src/routes/safe/components/Settings/ChangeSafeName/index.jsx +++ b/src/routes/safe/components/Settings/ChangeSafeName/index.jsx @@ -36,7 +36,7 @@ const ChangeSafeName = (props: Props) => { updateSafe({ address: safeAddress, name: values.safeName }) const notification = getNofiticationsFromTxType(NOTIFIED_TRANSACTIONS.SAFE_NAME_CHANGE_TX) - enqueueSnackbar(notification.afterExecution.description, notification.afterExecution.options) + enqueueSnackbar(notification.afterExecution.message, notification.afterExecution.options) } return ( diff --git a/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/index.jsx b/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/index.jsx index 41ecc250..96147765 100644 --- a/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/index.jsx @@ -58,7 +58,7 @@ const EditOwnerComponent = ({ editSafeOwner({ safeAddress, ownerAddress, ownerName: values.ownerName }) const notification = getNofiticationsFromTxType(NOTIFIED_TRANSACTIONS.OWNER_NAME_CHANGE_TX) - enqueueSnackbar(notification.afterExecution.description, notification.afterExecution.options) + enqueueSnackbar(notification.afterExecution.message, notification.afterExecution.options) onClose() } From b51aecafadeb82852f0972e5f9c1d3d96f663382 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Thu, 26 Sep 2019 15:14:24 +0200 Subject: [PATCH 39/50] Update notifier and notifications reducer --- src/components/Notifier/index.js | 14 +++++++------- .../notifications/store/actions/enqueueSnackbar.js | 6 ++---- .../notifications/store/models/notification.js | 2 ++ .../notifications/store/reducer/notifications.js | 11 ++++------- src/logic/wallets/store/actions/fetchProvider.js | 2 +- 5 files changed, 16 insertions(+), 19 deletions(-) diff --git a/src/components/Notifier/index.js b/src/components/Notifier/index.js index 3f4ad6e9..c4a9fd10 100644 --- a/src/components/Notifier/index.js +++ b/src/components/Notifier/index.js @@ -35,24 +35,24 @@ class Notifier extends Component { componentDidUpdate() { const { notifications = [], enqueueSnackbar, removeSnackbar } = this.props - notifications.map(({ key, message, options = {} }) => { + notifications.forEach((notification) => { // Do nothing if snackbar is already displayed - if (this.displayed.includes(key)) { + if (this.displayed.includes(notification.key)) { return } // Display snackbar using notistack - enqueueSnackbar(message, { - ...options, + enqueueSnackbar(notification.message, { + ...notification.options, onClose: (event, reason, key) => { - if (options.onClose) { - options.onClose(event, reason, key) + if (notification.options.onClose) { + notification.options.onClose(event, reason, key) } // Dispatch action to remove snackbar from redux store removeSnackbar(key) }, }) // Keep track of snackbars that we've displayed - this.storeDisplayed(key) + this.storeDisplayed(notification.key) }) } diff --git a/src/logic/notifications/store/actions/enqueueSnackbar.js b/src/logic/notifications/store/actions/enqueueSnackbar.js index f44ac1f8..e14abe0c 100644 --- a/src/logic/notifications/store/actions/enqueueSnackbar.js +++ b/src/logic/notifications/store/actions/enqueueSnackbar.js @@ -6,9 +6,7 @@ import { type NotificationProps } from '~/logic/notifications/store/models/notif export const ENQUEUE_SNACKBAR = 'ENQUEUE_SNACKBAR' -const addSnackbar = createAction(ENQUEUE_SNACKBAR, (notification: NotificationProps): ActionReturn => ({ - notification, -})) +const addSnackbar = createAction(ENQUEUE_SNACKBAR) const enqueueSnackbar = (notification: NotificationProps) => ( dispatch: ReduxDispatch, @@ -16,7 +14,7 @@ const enqueueSnackbar = (notification: NotificationProps) => ( ) => { const newNotification = { ...notification, - key: new Date().getTime() + Math.random(), + key: new Date().getTime(), } dispatch(addSnackbar(newNotification)) } diff --git a/src/logic/notifications/store/models/notification.js b/src/logic/notifications/store/models/notification.js index 9a25a6c2..7452faa9 100644 --- a/src/logic/notifications/store/models/notification.js +++ b/src/logic/notifications/store/models/notification.js @@ -3,12 +3,14 @@ import { Record } from 'immutable' import type { RecordFactory, RecordOf } from 'immutable' export type NotificationProps = { + key?: number, message: string, options: Object, dismissed: boolean, } export const makeNotification: RecordFactory = Record({ + key: 0, message: '', options: {}, dismissed: false, diff --git a/src/logic/notifications/store/reducer/notifications.js b/src/logic/notifications/store/reducer/notifications.js index 9aca1c80..c4ae1c2b 100644 --- a/src/logic/notifications/store/reducer/notifications.js +++ b/src/logic/notifications/store/reducer/notifications.js @@ -13,23 +13,20 @@ export type NotificationReducerState = Map export default handleActions( { [ENQUEUE_SNACKBAR]: (state: NotificationReducerState, action: ActionType): NotificationReducerState => { - const { notification }: { notification: NotificationProps } = action.payload + const notification: NotificationProps = action.payload - if (state.hasIn(['notifications', notification.options.key])) { - return state.updateIn(['notifications', notification.options.key], (prev) => prev.merge(notification)) - } - return state.setIn(['notifications', notification.options.key], makeNotification(notification)) + return state.set(notification.key, makeNotification(notification)) }, [CLOSE_SNACKBAR]: (state: NotificationReducerState, action: ActionType): NotificationReducerState => { const { notification }: { notification: NotificationProps } = action.payload notification.dismissed = true - return state.updateIn(['notifications', notification.key], (prev) => prev.merge(notification)) + return state.update(notification.key, (prev) => prev.merge(notification)) }, [REMOVE_SNACKBAR]: (state: NotificationReducerState, action: ActionType): NotificationReducerState => { const key = action.payload - return state.deleteIn(['notification', key]) + return state.delete(key) }, }, Map({ diff --git a/src/logic/wallets/store/actions/fetchProvider.js b/src/logic/wallets/store/actions/fetchProvider.js index 1e0ecc2c..82a4f378 100644 --- a/src/logic/wallets/store/actions/fetchProvider.js +++ b/src/logic/wallets/store/actions/fetchProvider.js @@ -47,7 +47,7 @@ const handleProviderNotification = (dispatch: ReduxDispatch<*>, provider: Provid // you SHOULD pass your own `key` in the options. `key` can be any sequence // of number or characters, but it has to be unique to a given snackbar. - //dispatch(enqueueSnackbarAction(NOTIFICATIONS.WALLET_CONNECTED_MSG)) + // dispatch(enqueueSnackbarAction(NOTIFICATIONS.WALLET_CONNECTED_MSG)) enqueueSnackbar(NOTIFICATIONS.WALLET_CONNECTED_MSG.message, NOTIFICATIONS.WALLET_CONNECTED_MSG.options) } else { enqueueSnackbar(NOTIFICATIONS.UNLOCK_WALLET_MSG.message, NOTIFICATIONS.UNLOCK_WALLET_MSG.options) From 9259d79f615853124471090c12d41ab40282d5f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Fri, 27 Sep 2019 11:20:35 +0200 Subject: [PATCH 40/50] Refactor create/confirm transactions --- src/logic/safe/transactions/send.js | 156 ++---------------- .../safe/store/actions/createTransaction.js | 103 ++++++++---- .../safe/store/actions/processTransaction.js | 116 +++++++++---- 3 files changed, 173 insertions(+), 202 deletions(-) diff --git a/src/logic/safe/transactions/send.js b/src/logic/safe/transactions/send.js index c702d2b1..ba1044a3 100644 --- a/src/logic/safe/transactions/send.js +++ b/src/logic/safe/transactions/send.js @@ -1,24 +1,14 @@ // @flow import GnosisSafeSol from '@gnosis.pm/safe-contracts/build/contracts/GnosisSafe.json' import { getWeb3 } from '~/logic/wallets/getWeb3' -import { getStandardTokenContract } from '~/logic/tokens/store/actions/fetchTokens' -import { EMPTY_DATA } from '~/logic/wallets/ethTransactions' -import { isEther } from '~/logic/tokens/utils/tokenHelpers' -import { type Token } from '~/logic/tokens/store/model/token' -import { getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts' -import { type Operation, saveTxToHistory } from '~/logic/safe/transactions' -import { type NotificationsQueue } from '~/logic/notifications' +import { type Operation } from '~/logic/safe/transactions' import { ZERO_ADDRESS } from '~/logic/wallets/ethAddresses' -import { getErrorMessage } from '~/test/utils/ethereumErrors' export const CALL = 0 export const TX_TYPE_EXECUTION = 'execution' export const TX_TYPE_CONFIRMATION = 'confirmation' -export const approveTransaction = async ( - notiQueue: NotificationsQueue, - enqueueSnackbar: Function, - closeSnackbar: Function, +export const getApprovalTransaction = async ( safeInstance: any, to: string, valueInWei: number | string, @@ -43,62 +33,19 @@ export const approveTransaction = async ( }, ) - const beforeExecutionKey = enqueueSnackbar(notiQueue.beforeExecution.message, notiQueue.beforeExecution.options) - let pendingExecutionKey try { const web3 = getWeb3() const contract = new web3.eth.Contract(GnosisSafeSol.abi, safeInstance.address) - const transactionHash = await contract.methods - .approveHash(txHash) - .send({ - from: sender, - }) - .once('transactionHash', () => { - closeSnackbar(beforeExecutionKey) - pendingExecutionKey = enqueueSnackbar( - notiQueue.pendingExecution.single.message, - notiQueue.pendingExecution.single.options, - ) - }) - .on('error', (error) => { - console.error('Tx error:', error) - }) - .then(async (receipt) => { - closeSnackbar(pendingExecutionKey) - await saveTxToHistory( - safeInstance, - to, - valueInWei, - data, - operation, - nonce, - receipt.transactionHash, - sender, - TX_TYPE_CONFIRMATION, - ) - enqueueSnackbar(notiQueue.afterExecution.message, notiQueue.afterExecution.options) - return receipt.transactionHash - }) + return contract.methods.approveHash(txHash) + } catch (err) { + console.error(`Error while approving transaction: ${err}`) - return transactionHash - } catch (error) { - closeSnackbar(beforeExecutionKey) - closeSnackbar(pendingExecutionKey) - enqueueSnackbar(notiQueue.afterExecutionError.message, notiQueue.afterExecutionError.options) - - const executeData = safeInstance.contract.methods.approveHash(txHash).encodeABI() - const errMsg = await getErrorMessage(safeInstance.address, 0, executeData, sender) - console.error(`Error executing the TX: ${errMsg}`) - - throw error + throw err } } -export const executeTransaction = async ( - notiQueue: NotificationsQueue, - enqueueSnackbar: Function, - closeSnackbar: Function, +export const getExecutionTransaction = async ( safeInstance: any, to: string, valueInWei: number | string, @@ -106,95 +53,16 @@ export const executeTransaction = async ( operation: Operation, nonce: string | number, sender: string, - signatures?: string, + sigs: string, ) => { - let sigs = signatures - - // https://gnosis-safe.readthedocs.io/en/latest/contracts/signatures.html#pre-validated-signatures - if (!sigs) { - sigs = `0x000000000000000000000000${sender.replace( - '0x', - '', - )}000000000000000000000000000000000000000000000000000000000000000001` - } - - const beforeExecutionKey = enqueueSnackbar(notiQueue.beforeExecution.message, notiQueue.beforeExecution.options) - let pendingExecutionKey try { const web3 = getWeb3() const contract = new web3.eth.Contract(GnosisSafeSol.abi, safeInstance.address) - const transactionHash = await contract.methods - .execTransaction(to, valueInWei, data, operation, 0, 0, 0, ZERO_ADDRESS, ZERO_ADDRESS, sigs) - .send({ - from: sender, - }) - .once('transactionHash', () => { - closeSnackbar(beforeExecutionKey) - pendingExecutionKey = enqueueSnackbar( - notiQueue.pendingExecution.single.message, - notiQueue.pendingExecution.single.options, - ) - }) - .on('error', (error) => { - console.error('Tx error:', error) - }) - .then(async (receipt) => { - closeSnackbar(pendingExecutionKey) - await saveTxToHistory( - safeInstance, - to, - valueInWei, - data, - operation, - nonce, - receipt.transactionHash, - sender, - TX_TYPE_EXECUTION, - ) - enqueueSnackbar(notiQueue.afterExecution.message, notiQueue.afterExecution.options) - return receipt.transactionHash - }) + return contract.methods.execTransaction(to, valueInWei, data, operation, 0, 0, 0, ZERO_ADDRESS, ZERO_ADDRESS, sigs) + } catch (err) { + console.error(`Error while creating transaction: ${err}`) - return transactionHash - } catch (error) { - closeSnackbar(beforeExecutionKey) - closeSnackbar(pendingExecutionKey) - enqueueSnackbar(notiQueue.afterExecutionError.message, notiQueue.afterExecutionError.options) - - const executeDataUsedSignatures = safeInstance.contract.methods - .execTransaction(to, valueInWei, data, operation, 0, 0, 0, ZERO_ADDRESS, ZERO_ADDRESS, sigs) - .encodeABI() - const errMsg = await getErrorMessage(safeInstance.address, 0, executeDataUsedSignatures, sender) - console.error(`Error executing the TX: ${errMsg}`) - - throw error + throw err } } - -export const createTransaction = async (safeAddress: string, to: string, valueInEth: string, token: Token) => { - const safeInstance = await getGnosisSafeInstanceAt(safeAddress) - const web3 = getWeb3() - const from = web3.currentProvider.selectedAddress - const threshold = await safeInstance.getThreshold() - const nonce = (await safeInstance.nonce()).toString() - const valueInWei = web3.utils.toWei(valueInEth, 'ether') - const isExecution = threshold.toNumber() === 1 - - let txData = EMPTY_DATA - if (!isEther(token.symbol)) { - const StandardToken = await getStandardTokenContract() - const sendToken = await StandardToken.at(token.address) - - txData = sendToken.contract.transfer(to, valueInWei).encodeABI() - } - - let txHash - if (isExecution) { - txHash = await executeTransaction(safeInstance, to, valueInWei, txData, CALL, nonce, from) - } else { - // txHash = await approveTransaction(safeAddress, to, valueInWei, txData, CALL, nonce) - } - - return txHash -} diff --git a/src/routes/safe/store/actions/createTransaction.js b/src/routes/safe/store/actions/createTransaction.js index 244ee24d..bc06da1e 100644 --- a/src/routes/safe/store/actions/createTransaction.js +++ b/src/routes/safe/store/actions/createTransaction.js @@ -6,9 +6,17 @@ import fetchTransactions from '~/routes/safe/store/actions/fetchTransactions' import { type GlobalState } from '~/store' import { getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts' import { - type NotifiedTransaction, approveTransaction, executeTransaction, CALL, + getApprovalTransaction, + getExecutionTransaction, + CALL, + type NotifiedTransaction, + TX_TYPE_CONFIRMATION, + TX_TYPE_EXECUTION, + saveTxToHistory, } from '~/logic/safe/transactions' -import { getNofiticationsFromTxType } from '~/logic/notifications' +import { getNofiticationsFromTxType, type NotificationsQueue } from '~/logic/notifications' +import { getErrorMessage } from '~/test/utils/ethereumErrors' +import { ZERO_ADDRESS } from '~/logic/wallets/ethAddresses' const createTransaction = ( safeAddress: string, @@ -28,39 +36,78 @@ const createTransaction = ( const nonce = (await safeInstance.nonce()).toString() const isExecution = threshold.toNumber() === 1 || shouldExecute - const notificationsQueue = getNofiticationsFromTxType(notifiedTransaction) + // https://gnosis-safe.readthedocs.io/en/latest/contracts/signatures.html#pre-validated-signatures + const sigs = `0x000000000000000000000000${from.replace( + '0x', + '', + )}000000000000000000000000000000000000000000000000000000000000000001` + + const notificationsQueue: NotificationsQueue = getNofiticationsFromTxType(notifiedTransaction) + const beforeExecutionKey = enqueueSnackbar( + notificationsQueue.beforeExecution.message, + notificationsQueue.beforeExecution.options, + ) + let pendingExecutionKey let txHash + let tx try { if (isExecution) { - txHash = await executeTransaction( - notificationsQueue, - enqueueSnackbar, - closeSnackbar, - safeInstance, - to, - valueInWei, - txData, - CALL, - nonce, - from, - ) + tx = await getExecutionTransaction(safeInstance, to, valueInWei, txData, CALL, nonce, from, sigs) } else { - txHash = await approveTransaction( - notificationsQueue, - enqueueSnackbar, - closeSnackbar, - safeInstance, - to, - valueInWei, - txData, - CALL, - nonce, - from, - ) + tx = await getApprovalTransaction(safeInstance, to, valueInWei, txData, CALL, nonce, from) } + + const sendParams = { from } + // if not set owner management tests will fail on ganache + if (process.env.NODE_ENV === 'test') { + sendParams.gas = '7000000' + } + + await tx + .send(sendParams) + .once('transactionHash', (hash) => { + txHash = hash + closeSnackbar(beforeExecutionKey) + pendingExecutionKey = enqueueSnackbar( + (shouldExecute) + ? notificationsQueue.pendingExecution.single.message + : notificationsQueue.pendingExecution.multiple.message, + notificationsQueue.pendingExecution.single.options, + ) + }) + .on('error', (error) => { + console.error('Tx error: ', error) + }) + .then(async (receipt) => { + closeSnackbar(pendingExecutionKey) + await saveTxToHistory( + safeInstance, + to, + valueInWei, + txData, + CALL, + nonce, + receipt.transactionHash, + from, + isExecution ? TX_TYPE_EXECUTION : TX_TYPE_CONFIRMATION, + ) + if (isExecution) { + enqueueSnackbar(notificationsQueue.afterExecution.message, notificationsQueue.afterExecution.options) + } + + return receipt.transactionHash + }) } catch (err) { - console.error(`Error while creating transaction: ${err}`) + closeSnackbar(beforeExecutionKey) + closeSnackbar(pendingExecutionKey) + enqueueSnackbar(notificationsQueue.afterExecutionError.message, notificationsQueue.afterExecutionError.options) + + const executeDataUsedSignatures = safeInstance.contract.methods + .execTransaction(to, valueInWei, txData, CALL, 0, 0, 0, ZERO_ADDRESS, ZERO_ADDRESS, sigs) + .encodeABI() + const errMsg = await getErrorMessage(safeInstance.address, 0, executeDataUsedSignatures, from) + console.error(`Error executing the TX: ${errMsg}`) } dispatch(fetchTransactions(safeAddress)) diff --git a/src/routes/safe/store/actions/processTransaction.js b/src/routes/safe/store/actions/processTransaction.js index 4cded12b..7164f54a 100644 --- a/src/routes/safe/store/actions/processTransaction.js +++ b/src/routes/safe/store/actions/processTransaction.js @@ -5,8 +5,17 @@ import { userAccountSelector } from '~/logic/wallets/store/selectors' import fetchTransactions from '~/routes/safe/store/actions/fetchTransactions' import { type GlobalState } from '~/store' import { getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts' -import { approveTransaction, executeTransaction, CALL } from '~/logic/safe/transactions' +import { + type NotificationsQueue, + getApprovalTransaction, + getExecutionTransaction, + CALL, + saveTxToHistory, + TX_TYPE_EXECUTION, + TX_TYPE_CONFIRMATION, +} from '~/logic/safe/transactions' import { getNofiticationsFromTxType } from '~/logic/notifications' +import { getErrorMessage } from '~/test/utils/ethereumErrors' // https://gnosis-safe.readthedocs.io/en/latest/contracts/signatures.html#pre-validated-signatures // https://github.com/gnosis/safe-contracts/blob/master/test/gnosisSafeTeamEdition.js#L26 @@ -45,38 +54,85 @@ const processTransaction = ( const nonce = (await safeInstance.nonce()).toString() const threshold = (await safeInstance.getThreshold()).toNumber() const shouldExecute = threshold === tx.confirmations.size || approveAndExecute - const sigs = generateSignaturesFromTxConfirmations(tx, approveAndExecute && userAddress) - const notificationsQueue = getNofiticationsFromTxType(notifiedTransaction) + let sigs = generateSignaturesFromTxConfirmations(tx, approveAndExecute && userAddress) + // https://gnosis-safe.readthedocs.io/en/latest/contracts/signatures.html#pre-validated-signatures + if (!sigs) { + sigs = `0x000000000000000000000000${from.replace( + '0x', + '', + )}000000000000000000000000000000000000000000000000000000000000000001` + } + + const notificationsQueue: NotificationsQueue = getNofiticationsFromTxType(notifiedTransaction) + const beforeExecutionKey = enqueueSnackbar( + notificationsQueue.beforeExecution.message, + notificationsQueue.beforeExecution.options, + ) + let pendingExecutionKey let txHash - if (shouldExecute) { - txHash = await executeTransaction( - notificationsQueue, - enqueueSnackbar, - closeSnackbar, - safeInstance, - tx.recipient, - tx.value, - tx.data, - CALL, - nonce, - from, - sigs, - ) - } else { - txHash = await approveTransaction( - notificationsQueue, - enqueueSnackbar, - closeSnackbar, - safeInstance, - tx.recipient, - tx.value, - tx.data, - CALL, - nonce, - from, - ) + let transaction + try { + if (shouldExecute) { + transaction = await getExecutionTransaction( + safeInstance, + tx.recipient, + tx.value, + tx.data, + CALL, + nonce, + from, + sigs, + ) + } else { + transaction = await getApprovalTransaction(safeInstance, tx.recipient, tx.value, tx.data, CALL, nonce, from) + } + + const sendParams = { from } + // if not set owner management tests will fail on ganache + if (process.env.NODE_ENV === 'test') { + sendParams.gas = '7000000' + } + + await transaction + .send(sendParams) + .once('transactionHash', (hash) => { + txHash = hash + closeSnackbar(beforeExecutionKey) + pendingExecutionKey = enqueueSnackbar( + notificationsQueue.pendingExecution.single.message, + notificationsQueue.pendingExecution.single.options, + ) + }) + .on('error', (error) => { + console.error('Processing transaction error: ', error) + }) + .then(async (receipt) => { + closeSnackbar(pendingExecutionKey) + await saveTxToHistory( + safeInstance, + tx.recipient, + tx.value, + tx.data, + CALL, + nonce, + receipt.transactionHash, + from, + shouldExecute ? TX_TYPE_EXECUTION : TX_TYPE_CONFIRMATION, + ) + enqueueSnackbar(notificationsQueue.afterExecution.message, notificationsQueue.afterExecution.options) + + return receipt.transactionHash + }) + } catch (err) { + closeSnackbar(beforeExecutionKey) + closeSnackbar(pendingExecutionKey) + enqueueSnackbar(notificationsQueue.afterExecutionError.message, notificationsQueue.afterExecutionError.options) + + const executeData = safeInstance.contract.methods.approveHash(txHash).encodeABI() + const errMsg = await getErrorMessage(safeInstance.address, 0, executeData, from) + console.error(`Error executing the TX: ${errMsg}`) } dispatch(fetchTransactions(safeAddress)) From ef229b20b060af53775cac80103fb8f3b722e45b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Fri, 27 Sep 2019 12:00:04 +0200 Subject: [PATCH 41/50] Add dimiss notification button --- src/components/Header/index.jsx | 10 +++---- .../notifications/notificationBuilder.js | 16 ++++++++++ .../wallets/store/actions/fetchProvider.js | 29 ++++++++++--------- .../wallets/store/actions/removeProvider.js | 6 ++-- .../Settings/ChangeSafeName/index.jsx | 7 +++-- .../ManageOwners/EditOwnerModal/index.jsx | 6 ++-- .../safe/store/actions/createTransaction.js | 25 +++++++++------- .../safe/store/actions/processTransaction.js | 26 +++++++++-------- 8 files changed, 76 insertions(+), 49 deletions(-) diff --git a/src/components/Header/index.jsx b/src/components/Header/index.jsx index 3c173314..c4b53361 100644 --- a/src/components/Header/index.jsx +++ b/src/components/Header/index.jsx @@ -5,7 +5,7 @@ import { withSnackbar } from 'notistack' import { logComponentStack, type Info } from '~/utils/logBoundaries' import { getProviderInfo } from '~/logic/wallets/getWeb3' import type { ProviderProps } from '~/logic/wallets/store/model/provider' -import { NOTIFICATIONS } from '~/logic/notifications' +import { NOTIFICATIONS, showSnackbar } from '~/logic/notifications' import ProviderAccesible from './component/ProviderInfo/ProviderAccesible' import UserDetails from './component/ProviderDetails/UserDetails' import ProviderDisconnected from './component/ProviderInfo/ProviderDisconnected' @@ -39,20 +39,20 @@ class HeaderComponent extends React.PureComponent { } componentDidCatch(error: Error, info: Info) { - const { enqueueSnackbar } = this.props + const { enqueueSnackbar, closeSnackbar } = this.props this.setState({ hasError: true }) - enqueueSnackbar(NOTIFICATIONS.CONNECT_WALLET_ERROR_MSG.message, NOTIFICATIONS.CONNECT_WALLET_ERROR_MSG.options) + showSnackbar(NOTIFICATIONS.CONNECT_WALLET_ERROR_MSG, enqueueSnackbar, closeSnackbar) logComponentStack(error, info) } onDisconnect = () => { - const { removeProvider, enqueueSnackbar } = this.props + const { removeProvider, enqueueSnackbar, closeSnackbar } = this.props clearInterval(this.providerListener) - removeProvider(enqueueSnackbar) + removeProvider(enqueueSnackbar, closeSnackbar) } onConnect = async () => { diff --git a/src/logic/notifications/notificationBuilder.js b/src/logic/notifications/notificationBuilder.js index f528f24f..85d4dfdb 100644 --- a/src/logic/notifications/notificationBuilder.js +++ b/src/logic/notifications/notificationBuilder.js @@ -1,4 +1,7 @@ // @flow +import * as React from 'react' +import { IconButton } from '@material-ui/core' +import { Close as IconClose } from '@material-ui/icons' import { NOTIFIED_TRANSACTIONS } from '~/logic/safe/transactions' import { type Notification, NOTIFICATIONS } from './notificationTypes' @@ -141,3 +144,16 @@ export const getNofiticationsFromTxType = (txType: string) => { return notificationsQueue } + +export const showSnackbar = ( + notification: Notification, + enqueueSnackbar: Function, + closeSnackbar: Function, +) => enqueueSnackbar(notification.message, { + ...notification.options, + action: (key) => ( + closeSnackbar(key)}> + + + ), +}) diff --git a/src/logic/wallets/store/actions/fetchProvider.js b/src/logic/wallets/store/actions/fetchProvider.js index 82a4f378..f12fdf00 100644 --- a/src/logic/wallets/store/actions/fetchProvider.js +++ b/src/logic/wallets/store/actions/fetchProvider.js @@ -3,7 +3,7 @@ import type { Dispatch as ReduxDispatch } from 'redux' import { ETHEREUM_NETWORK_IDS, ETHEREUM_NETWORK } from '~/logic/wallets/getWeb3' import type { ProviderProps } from '~/logic/wallets/store/model/provider' import { makeProvider } from '~/logic/wallets/store/model/provider' -import { NOTIFICATIONS } from '~/logic/notifications' +import { NOTIFICATIONS, showSnackbar } from '~/logic/notifications' // import enqueueSnackbar as enqueueSnackbarAction from '~/logic/notifications/store/actions/enqueueSnackbar' // import closeSnackbar as closeSnackbarAction from '~/logic/notifications/store/actions/closeSnackbar' import addProvider from './addProvider' @@ -24,22 +24,24 @@ export const processProviderResponse = (dispatch: ReduxDispatch<*>, provider: Pr dispatch(addProvider(walletRecord)) } -const handleProviderNotification = (dispatch: ReduxDispatch<*>, provider: ProviderProps, enqueueSnackbar: Function) => { +const handleProviderNotification = ( + dispatch: ReduxDispatch<*>, + provider: ProviderProps, + enqueueSnackbar: Function, + closeSnackbar: Function, +) => { const { loaded, available, network } = provider if (!loaded) { - enqueueSnackbar(NOTIFICATIONS.CONNECT_WALLET_ERROR_MSG.message, NOTIFICATIONS.CONNECT_WALLET_ERROR_MSG.options) + showSnackbar(NOTIFICATIONS.CONNECT_WALLET_ERROR_MSG, enqueueSnackbar, closeSnackbar) return } if (ETHEREUM_NETWORK_IDS[network] !== ETHEREUM_NETWORK.RINKEBY) { - enqueueSnackbar( - NOTIFICATIONS.WRONG_NETWORK_RINKEBY_MSG.message, - NOTIFICATIONS.WRONG_NETWORK_RINKEBY_MSG.options, - ) + showSnackbar(NOTIFICATIONS.WRONG_NETWORK_RINKEBY_MSG, enqueueSnackbar, closeSnackbar) return } - enqueueSnackbar(NOTIFICATIONS.RINKEBY_VERSION_MSG.message, NOTIFICATIONS.RINKEBY_VERSION_MSG.options) + showSnackbar(NOTIFICATIONS.RINKEBY_VERSION_MSG, enqueueSnackbar, closeSnackbar) if (available) { // NOTE: @@ -47,14 +49,15 @@ const handleProviderNotification = (dispatch: ReduxDispatch<*>, provider: Provid // you SHOULD pass your own `key` in the options. `key` can be any sequence // of number or characters, but it has to be unique to a given snackbar. - // dispatch(enqueueSnackbarAction(NOTIFICATIONS.WALLET_CONNECTED_MSG)) - enqueueSnackbar(NOTIFICATIONS.WALLET_CONNECTED_MSG.message, NOTIFICATIONS.WALLET_CONNECTED_MSG.options) + showSnackbar(NOTIFICATIONS.WALLET_CONNECTED_MSG, enqueueSnackbar, closeSnackbar) } else { - enqueueSnackbar(NOTIFICATIONS.UNLOCK_WALLET_MSG.message, NOTIFICATIONS.UNLOCK_WALLET_MSG.options) + showSnackbar(NOTIFICATIONS.UNLOCK_WALLET_MSG, enqueueSnackbar, closeSnackbar) } } -export default (provider: ProviderProps, enqueueSnackbar: Function) => (dispatch: ReduxDispatch<*>) => { - handleProviderNotification(dispatch, provider, enqueueSnackbar) +export default (provider: ProviderProps, enqueueSnackbar: Function, closeSnackbar: Function) => ( + dispatch: ReduxDispatch<*>, +) => { + handleProviderNotification(dispatch, provider, enqueueSnackbar, closeSnackbar) processProviderResponse(dispatch, provider) } diff --git a/src/logic/wallets/store/actions/removeProvider.js b/src/logic/wallets/store/actions/removeProvider.js index cb2e6120..ac81f7d6 100644 --- a/src/logic/wallets/store/actions/removeProvider.js +++ b/src/logic/wallets/store/actions/removeProvider.js @@ -1,10 +1,10 @@ // @flow import type { Dispatch as ReduxDispatch } from 'redux' import { makeProvider, type ProviderProps, type Provider } from '~/logic/wallets/store/model/provider' -import { NOTIFICATIONS } from '~/logic/notifications' +import { NOTIFICATIONS, showSnackbar } from '~/logic/notifications' import addProvider from './addProvider' -export default (enqueueSnackbar: Function) => async (dispatch: ReduxDispatch<*>) => { +export default (enqueueSnackbar: Function, closeSnackbar: Function) => async (dispatch: ReduxDispatch<*>) => { const providerProps: ProviderProps = { name: '', available: false, @@ -14,7 +14,7 @@ export default (enqueueSnackbar: Function) => async (dispatch: ReduxDispatch<*>) } const provider: Provider = makeProvider(providerProps) - enqueueSnackbar(NOTIFICATIONS.WALLET_DISCONNECTED_MSG.message, NOTIFICATIONS.WALLET_DISCONNECTED_MSG.options) + showSnackbar(NOTIFICATIONS.WALLET_DISCONNECTED_MSG, enqueueSnackbar, closeSnackbar) dispatch(addProvider(provider)) } diff --git a/src/routes/safe/components/Settings/ChangeSafeName/index.jsx b/src/routes/safe/components/Settings/ChangeSafeName/index.jsx index 90c392fb..95ca1c05 100644 --- a/src/routes/safe/components/Settings/ChangeSafeName/index.jsx +++ b/src/routes/safe/components/Settings/ChangeSafeName/index.jsx @@ -12,7 +12,7 @@ import GnoForm from '~/components/forms/GnoForm' import Row from '~/components/layout/Row' import Paragraph from '~/components/layout/Paragraph' import Button from '~/components/layout/Button' -import { getNofiticationsFromTxType } from '~/logic/notifications' +import { getNofiticationsFromTxType, showSnackbar } from '~/logic/notifications' import { NOTIFIED_TRANSACTIONS } from '~/logic/safe/transactions' import { styles } from './style' @@ -25,18 +25,19 @@ type Props = { safeName: string, updateSafe: Function, enqueueSnackbar: Function, + closeSnackbar: Function, } const ChangeSafeName = (props: Props) => { const { - classes, safeAddress, safeName, updateSafe, enqueueSnackbar, + classes, safeAddress, safeName, updateSafe, enqueueSnackbar, closeSnackbar, } = props const handleSubmit = (values) => { updateSafe({ address: safeAddress, name: values.safeName }) const notification = getNofiticationsFromTxType(NOTIFIED_TRANSACTIONS.SAFE_NAME_CHANGE_TX) - enqueueSnackbar(notification.afterExecution.message, notification.afterExecution.options) + showSnackbar(notification.afterExecution, enqueueSnackbar, closeSnackbar) } return ( diff --git a/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/index.jsx b/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/index.jsx index 96147765..186b386d 100644 --- a/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/index.jsx @@ -16,7 +16,7 @@ import TextField from '~/components/forms/TextField' import Paragraph from '~/components/layout/Paragraph' import Identicon from '~/components/Identicon' import { composeValidators, required, minMaxLength } from '~/components/forms/validator' -import { getNofiticationsFromTxType } from '~/logic/notifications' +import { getNofiticationsFromTxType, showSnackbar } from '~/logic/notifications' import { NOTIFIED_TRANSACTIONS } from '~/logic/safe/transactions' import { getEtherScanLink } from '~/logic/wallets/getWeb3' import Modal from '~/components/Modal' @@ -41,6 +41,7 @@ type Props = { selectedOwnerName: string, editSafeOwner: Function, enqueueSnackbar: Function, + closeSnackbar: Function, } const EditOwnerComponent = ({ @@ -53,12 +54,13 @@ const EditOwnerComponent = ({ editSafeOwner, network, enqueueSnackbar, + closeSnackbar, }: Props) => { const handleSubmit = (values) => { editSafeOwner({ safeAddress, ownerAddress, ownerName: values.ownerName }) const notification = getNofiticationsFromTxType(NOTIFIED_TRANSACTIONS.OWNER_NAME_CHANGE_TX) - enqueueSnackbar(notification.afterExecution.message, notification.afterExecution.options) + showSnackbar(notification.afterExecution, enqueueSnackbar, closeSnackbar) onClose() } diff --git a/src/routes/safe/store/actions/createTransaction.js b/src/routes/safe/store/actions/createTransaction.js index bc06da1e..de5eee45 100644 --- a/src/routes/safe/store/actions/createTransaction.js +++ b/src/routes/safe/store/actions/createTransaction.js @@ -14,7 +14,12 @@ import { TX_TYPE_EXECUTION, saveTxToHistory, } from '~/logic/safe/transactions' -import { getNofiticationsFromTxType, type NotificationsQueue } from '~/logic/notifications' +import { + type Notification, + type NotificationsQueue, + getNofiticationsFromTxType, + showSnackbar, +} from '~/logic/notifications' import { getErrorMessage } from '~/test/utils/ethereumErrors' import { ZERO_ADDRESS } from '~/logic/wallets/ethAddresses' @@ -43,10 +48,7 @@ const createTransaction = ( )}000000000000000000000000000000000000000000000000000000000000000001` const notificationsQueue: NotificationsQueue = getNofiticationsFromTxType(notifiedTransaction) - const beforeExecutionKey = enqueueSnackbar( - notificationsQueue.beforeExecution.message, - notificationsQueue.beforeExecution.options, - ) + const beforeExecutionKey = showSnackbar(notificationsQueue.beforeExecution, enqueueSnackbar, closeSnackbar) let pendingExecutionKey let txHash @@ -69,12 +71,13 @@ const createTransaction = ( .once('transactionHash', (hash) => { txHash = hash closeSnackbar(beforeExecutionKey) - pendingExecutionKey = enqueueSnackbar( - (shouldExecute) + const pendingExecutionNotification: Notification = { + message: isExecution ? notificationsQueue.pendingExecution.single.message : notificationsQueue.pendingExecution.multiple.message, - notificationsQueue.pendingExecution.single.options, - ) + options: notificationsQueue.pendingExecution.single.options, + } + pendingExecutionKey = showSnackbar(pendingExecutionNotification, enqueueSnackbar, closeSnackbar) }) .on('error', (error) => { console.error('Tx error: ', error) @@ -93,7 +96,7 @@ const createTransaction = ( isExecution ? TX_TYPE_EXECUTION : TX_TYPE_CONFIRMATION, ) if (isExecution) { - enqueueSnackbar(notificationsQueue.afterExecution.message, notificationsQueue.afterExecution.options) + showSnackbar(notificationsQueue.afterExecution, enqueueSnackbar, closeSnackbar) } return receipt.transactionHash @@ -101,7 +104,7 @@ const createTransaction = ( } catch (err) { closeSnackbar(beforeExecutionKey) closeSnackbar(pendingExecutionKey) - enqueueSnackbar(notificationsQueue.afterExecutionError.message, notificationsQueue.afterExecutionError.options) + showSnackbar(notificationsQueue.afterExecutionError, enqueueSnackbar, closeSnackbar) const executeDataUsedSignatures = safeInstance.contract.methods .execTransaction(to, valueInWei, txData, CALL, 0, 0, 0, ZERO_ADDRESS, ZERO_ADDRESS, sigs) diff --git a/src/routes/safe/store/actions/processTransaction.js b/src/routes/safe/store/actions/processTransaction.js index 7164f54a..0e481946 100644 --- a/src/routes/safe/store/actions/processTransaction.js +++ b/src/routes/safe/store/actions/processTransaction.js @@ -6,7 +6,6 @@ import fetchTransactions from '~/routes/safe/store/actions/fetchTransactions' import { type GlobalState } from '~/store' import { getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts' import { - type NotificationsQueue, getApprovalTransaction, getExecutionTransaction, CALL, @@ -14,7 +13,12 @@ import { TX_TYPE_EXECUTION, TX_TYPE_CONFIRMATION, } from '~/logic/safe/transactions' -import { getNofiticationsFromTxType } from '~/logic/notifications' +import { + type Notification, + type NotificationsQueue, + getNofiticationsFromTxType, + showSnackbar, +} from '~/logic/notifications' import { getErrorMessage } from '~/test/utils/ethereumErrors' // https://gnosis-safe.readthedocs.io/en/latest/contracts/signatures.html#pre-validated-signatures @@ -65,10 +69,7 @@ const processTransaction = ( } const notificationsQueue: NotificationsQueue = getNofiticationsFromTxType(notifiedTransaction) - const beforeExecutionKey = enqueueSnackbar( - notificationsQueue.beforeExecution.message, - notificationsQueue.beforeExecution.options, - ) + const beforeExecutionKey = showSnackbar(notificationsQueue.beforeExecution, enqueueSnackbar, closeSnackbar) let pendingExecutionKey let txHash @@ -100,10 +101,11 @@ const processTransaction = ( .once('transactionHash', (hash) => { txHash = hash closeSnackbar(beforeExecutionKey) - pendingExecutionKey = enqueueSnackbar( - notificationsQueue.pendingExecution.single.message, - notificationsQueue.pendingExecution.single.options, - ) + const notification: Notification = { + message: notificationsQueue.pendingExecution.single.message, + options: notificationsQueue.pendingExecution.single.options, + } + pendingExecutionKey = showSnackbar(notification, enqueueSnackbar, closeSnackbar) }) .on('error', (error) => { console.error('Processing transaction error: ', error) @@ -121,14 +123,14 @@ const processTransaction = ( from, shouldExecute ? TX_TYPE_EXECUTION : TX_TYPE_CONFIRMATION, ) - enqueueSnackbar(notificationsQueue.afterExecution.message, notificationsQueue.afterExecution.options) + showSnackbar(notificationsQueue.afterExecution, enqueueSnackbar, closeSnackbar) return receipt.transactionHash }) } catch (err) { closeSnackbar(beforeExecutionKey) closeSnackbar(pendingExecutionKey) - enqueueSnackbar(notificationsQueue.afterExecutionError.message, notificationsQueue.afterExecutionError.options) + showSnackbar(notificationsQueue.afterExecutionError, enqueueSnackbar, closeSnackbar) const executeData = safeInstance.contract.methods.approveHash(txHash).encodeABI() const errMsg = await getErrorMessage(safeInstance.address, 0, executeData, from) From 2afb9735aa8579ceeb0da7a3b7724de797bc7215 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Fri, 27 Sep 2019 12:06:35 +0200 Subject: [PATCH 42/50] Add approveAndExecute param to processTransaction --- .../Transactions/TxsTable/ExpandedTx/ApproveTxModal/index.jsx | 1 + 1 file changed, 1 insertion(+) 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 3d76a766..3ac906db 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/ApproveTxModal/index.jsx +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/ApproveTxModal/index.jsx @@ -75,6 +75,7 @@ const ApproveTxModal = ({ NOTIFIED_TRANSACTIONS.CONFIRMATION_TX, enqueueSnackbar, closeSnackbar, + approveAndExecute, ) onClose() } From b771ba78f86830548f483e71f282e1f8d3afe2a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Fri, 27 Sep 2019 12:07:49 +0200 Subject: [PATCH 43/50] Add alt attribute to images --- src/components/layout/PageFrame/index.jsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/layout/PageFrame/index.jsx b/src/components/layout/PageFrame/index.jsx index 6d3c71bf..9c8b1fa8 100644 --- a/src/components/layout/PageFrame/index.jsx +++ b/src/components/layout/PageFrame/index.jsx @@ -67,9 +67,9 @@ const PageFrame = ({ children, classes }: Props) => ( variantInfo: classes.info, }} iconVariant={{ - success: , - error: , - warning: , + success: Success, + error: Error, + warning: Warning, info: '', }} > From 6e52f0fddd76e459597499713c71b278a7fdf60a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Fri, 27 Sep 2019 12:10:58 +0200 Subject: [PATCH 44/50] Rename variables in pending confirmations notification --- .../notifications/notificationBuilder.js | 36 +++++++++---------- .../safe/store/actions/createTransaction.js | 11 +++--- .../safe/store/actions/processTransaction.js | 4 +-- 3 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/logic/notifications/notificationBuilder.js b/src/logic/notifications/notificationBuilder.js index 85d4dfdb..06d347aa 100644 --- a/src/logic/notifications/notificationBuilder.js +++ b/src/logic/notifications/notificationBuilder.js @@ -8,8 +8,8 @@ import { type Notification, NOTIFICATIONS } from './notificationTypes' type NotificationsQueue = { beforeExecution: Notification, pendingExecution: { - single: Notification, - multiple: Notification, + noMoreConfirmationsNeeded: Notification, + moreConfirmationsNeeded: Notification, }, afterExecution: Notification, afterExecutionError: Notification, @@ -19,8 +19,8 @@ type NotificationsQueue = { const standardTxNotificationsQueue: NotificationsQueue = { beforeExecution: NOTIFICATIONS.SIGN_TX_MSG, pendingExecution: { - single: NOTIFICATIONS.TX_PENDING_MSG, - multiple: NOTIFICATIONS.TX_PENDING_MORE_CONFIRMATIONS_MSG, + noMoreConfirmationsNeeded: NOTIFICATIONS.TX_PENDING_MSG, + moreConfirmationsNeeded: NOTIFICATIONS.TX_PENDING_MORE_CONFIRMATIONS_MSG, }, afterRejection: NOTIFICATIONS.TX_REJECTED_MSG, afterExecution: NOTIFICATIONS.TX_EXECUTED_MSG, @@ -30,8 +30,8 @@ const standardTxNotificationsQueue: NotificationsQueue = { const confirmationTxNotificationsQueue: NotificationsQueue = { beforeExecution: NOTIFICATIONS.SIGN_TX_MSG, pendingExecution: { - single: NOTIFICATIONS.TX_CONFIRMATION_PENDING_MSG, - multiple: null, + noMoreConfirmationsNeeded: NOTIFICATIONS.TX_CONFIRMATION_PENDING_MSG, + moreConfirmationsNeeded: null, }, afterRejection: NOTIFICATIONS.TX_REJECTED_MSG, afterExecution: NOTIFICATIONS.TX_CONFIRMATION_EXECUTED_MSG, @@ -41,8 +41,8 @@ const confirmationTxNotificationsQueue: NotificationsQueue = { const cancellationTxNotificationsQueue: NotificationsQueue = { beforeExecution: NOTIFICATIONS.SIGN_TX_MSG, pendingExecution: { - single: NOTIFICATIONS.TX_PENDING_MSG, - multiple: NOTIFICATIONS.TX_PENDING_MORE_CONFIRMATIONS_MSG, + noMoreConfirmationsNeeded: NOTIFICATIONS.TX_PENDING_MSG, + moreConfirmationsNeeded: NOTIFICATIONS.TX_PENDING_MORE_CONFIRMATIONS_MSG, }, afterRejection: NOTIFICATIONS.TX_REJECTED_MSG, afterExecution: NOTIFICATIONS.TX_EXECUTED_MSG, @@ -52,8 +52,8 @@ const cancellationTxNotificationsQueue: NotificationsQueue = { const ownerChangeTxNotificationsQueue: NotificationsQueue = { beforeExecution: NOTIFICATIONS.SIGN_OWNER_CHANGE_MSG, pendingExecution: { - single: NOTIFICATIONS.ONWER_CHANGE_PENDING_MSG, - multiple: NOTIFICATIONS.ONWER_CHANGE_PENDING_MORE_CONFIRMATIONS_MSG, + noMoreConfirmationsNeeded: NOTIFICATIONS.ONWER_CHANGE_PENDING_MSG, + moreConfirmationsNeeded: NOTIFICATIONS.ONWER_CHANGE_PENDING_MORE_CONFIRMATIONS_MSG, }, afterRejection: NOTIFICATIONS.ONWER_CHANGE_REJECTED_MSG, afterExecution: NOTIFICATIONS.OWNER_CHANGE_EXECUTED_MSG, @@ -63,8 +63,8 @@ const ownerChangeTxNotificationsQueue: NotificationsQueue = { const safeNameChangeNotificationsQueue: NotificationsQueue = { beforeExecution: null, pendingExecution: { - single: null, - multiple: null, + noMoreConfirmationsNeeded: null, + moreConfirmationsNeeded: null, }, afterRejection: null, afterExecution: NOTIFICATIONS.SAFE_NAME_CHANGE_EXECUTED_MSG, @@ -74,8 +74,8 @@ const safeNameChangeNotificationsQueue: NotificationsQueue = { const ownerNameChangeNotificationsQueue: NotificationsQueue = { beforeExecution: null, pendingExecution: { - single: null, - multiple: null, + noMoreConfirmationsNeeded: null, + moreConfirmationsNeeded: null, }, afterRejection: null, afterExecution: NOTIFICATIONS.OWNER_NAME_CHANGE_EXECUTED_MSG, @@ -85,8 +85,8 @@ const ownerNameChangeNotificationsQueue: NotificationsQueue = { const thresholdChangeTxNotificationsQueue: NotificationsQueue = { beforeExecution: NOTIFICATIONS.SIGN_THRESHOLD_CHANGE_MSG, pendingExecution: { - single: NOTIFICATIONS.THRESHOLD_CHANGE_PENDING_MSG, - multiple: NOTIFICATIONS.THRESHOLD_CHANGE_PENDING_MORE_CONFIRMATIONS_MSG, + noMoreConfirmationsNeeded: NOTIFICATIONS.THRESHOLD_CHANGE_PENDING_MSG, + moreConfirmationsNeeded: NOTIFICATIONS.THRESHOLD_CHANGE_PENDING_MORE_CONFIRMATIONS_MSG, }, afterRejection: NOTIFICATIONS.THRESHOLD_CHANGE_REJECTED_MSG, afterExecution: NOTIFICATIONS.THRESHOLD_CHANGE_EXECUTED_MSG, @@ -96,8 +96,8 @@ const thresholdChangeTxNotificationsQueue: NotificationsQueue = { const defaultNotificationsQueue: NotificationsQueue = { beforeExecution: NOTIFICATIONS.SIGN_TX_MSG, pendingExecution: { - single: NOTIFICATIONS.TX_PENDING_MSG, - multiple: NOTIFICATIONS.TX_PENDING_MORE_CONFIRMATIONS_MSG, + noMoreConfirmationsNeeded: NOTIFICATIONS.TX_PENDING_MSG, + moreConfirmationsNeeded: NOTIFICATIONS.TX_PENDING_MORE_CONFIRMATIONS_MSG, }, afterRejection: NOTIFICATIONS.TX_REJECTED_MSG, afterExecution: NOTIFICATIONS.TX_EXECUTED_MSG, diff --git a/src/routes/safe/store/actions/createTransaction.js b/src/routes/safe/store/actions/createTransaction.js index de5eee45..4478bd8a 100644 --- a/src/routes/safe/store/actions/createTransaction.js +++ b/src/routes/safe/store/actions/createTransaction.js @@ -71,11 +71,12 @@ const createTransaction = ( .once('transactionHash', (hash) => { txHash = hash closeSnackbar(beforeExecutionKey) - const pendingExecutionNotification: Notification = { - message: isExecution - ? notificationsQueue.pendingExecution.single.message - : notificationsQueue.pendingExecution.multiple.message, - options: notificationsQueue.pendingExecution.single.options, + const pendingExecutionNotification: Notification = isExecution ? { + message: notificationsQueue.pendingExecution.noMoreConfirmationsNeeded.message, + options: notificationsQueue.pendingExecution.noMoreConfirmationsNeeded.options, + } : { + message: notificationsQueue.pendingExecution.moreConfirmationsNeeded.message, + options: notificationsQueue.pendingExecution.moreConfirmationsNeeded.options, } pendingExecutionKey = showSnackbar(pendingExecutionNotification, enqueueSnackbar, closeSnackbar) }) diff --git a/src/routes/safe/store/actions/processTransaction.js b/src/routes/safe/store/actions/processTransaction.js index 0e481946..d2ea959d 100644 --- a/src/routes/safe/store/actions/processTransaction.js +++ b/src/routes/safe/store/actions/processTransaction.js @@ -102,8 +102,8 @@ const processTransaction = ( txHash = hash closeSnackbar(beforeExecutionKey) const notification: Notification = { - message: notificationsQueue.pendingExecution.single.message, - options: notificationsQueue.pendingExecution.single.options, + message: notificationsQueue.pendingExecution.noMoreConfirmationsNeeded.message, + options: notificationsQueue.pendingExecution.noMoreConfirmationsNeeded.options, } pendingExecutionKey = showSnackbar(notification, enqueueSnackbar, closeSnackbar) }) From 5523383781987ed2e01a5939e19e9f23c2eb80c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Fri, 27 Sep 2019 12:31:42 +0200 Subject: [PATCH 45/50] Throw error when web3 provider returns no accounts --- src/logic/wallets/getWeb3.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/logic/wallets/getWeb3.js b/src/logic/wallets/getWeb3.js index 17dc6e23..92543002 100644 --- a/src/logic/wallets/getWeb3.js +++ b/src/logic/wallets/getWeb3.js @@ -79,7 +79,7 @@ export const getProviderInfo: Function = async (): Promise => { try { const accounts = await web3Provider.enable() if (!accounts) { - console.error('Empty web3 provider') + throw new Error() } } catch (error) { console.error('Error when enabling web3 provider', error) From 85177d3ddd053b4c191af83d025ad9309b8ef7b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Fri, 27 Sep 2019 12:35:13 +0200 Subject: [PATCH 46/50] Refactor error messages --- src/logic/safe/transactions/gas.js | 6 ++---- src/logic/safe/utils/safeStorage.js | 6 ++---- src/logic/tokens/store/actions/fetchTokens.js | 3 +-- src/logic/tokens/utils/tokensStorage.js | 6 ++---- src/routes/load/container/Load.jsx | 3 +-- .../Settings/ManageOwners/AddOwnerModal/index.jsx | 3 +-- .../Settings/ManageOwners/ReplaceOwnerModal/index.jsx | 3 +-- src/utils/storage/signatures.js | 3 +-- src/utils/storage/transactions.js | 3 +-- 9 files changed, 12 insertions(+), 24 deletions(-) diff --git a/src/logic/safe/transactions/gas.js b/src/logic/safe/transactions/gas.js index 1ae8e0d0..2a0da8cb 100644 --- a/src/logic/safe/transactions/gas.js +++ b/src/logic/safe/transactions/gas.js @@ -82,8 +82,7 @@ export const generateTxGasEstimateFrom = async ( // Add 10k else we will fail in case of nested calls return txGasEstimate.toNumber() + 10000 } catch (error) { - // eslint-disable-next-line - console.log('Error calculating tx gas estimation ' + error) + console.error('Error calculating tx gas estimation', error) return 0 } } @@ -128,8 +127,7 @@ export const calculateTxFee = async ( return estimate } catch (error) { - // eslint-disable-next-line - console.log('Error calculating tx gas estimation ' + error) + console.error('Error calculating tx gas estimation', error) return 0 } } diff --git a/src/logic/safe/utils/safeStorage.js b/src/logic/safe/utils/safeStorage.js index da498908..c8e092d0 100644 --- a/src/logic/safe/utils/safeStorage.js +++ b/src/logic/safe/utils/safeStorage.js @@ -22,8 +22,7 @@ export const saveSafes = async (safes: Object) => { try { await saveToStorage(SAFES_KEY, safes) } catch (err) { - // eslint-disable-next-line - console.log('Error storing safe info in localstorage') + console.error('Error storing safe info in localstorage', err) } } @@ -32,8 +31,7 @@ export const setOwners = async (safeAddress: string, owners: List) => { const ownersAsMap = Map(owners.map((owner: Owner) => [owner.address.toLowerCase(), owner.name])) await saveToStorage(`${OWNERS_KEY}-${safeAddress}`, ownersAsMap) } catch (err) { - // eslint-disable-next-line - console.log('Error storing owners in localstorage') + console.error('Error storing owners in localstorage', err) } } diff --git a/src/logic/tokens/store/actions/fetchTokens.js b/src/logic/tokens/store/actions/fetchTokens.js index d3654f96..abaad8bc 100644 --- a/src/logic/tokens/store/actions/fetchTokens.js +++ b/src/logic/tokens/store/actions/fetchTokens.js @@ -40,8 +40,7 @@ export const fetchTokens = () => async (dispatch: ReduxDispatch) => dispatch(saveTokens(tokens)) } catch (err) { - // eslint-disable-next-line - console.log('Error fetching token list ' + err) + console.error('Error fetching token list', err) return Promise.resolve() } diff --git a/src/logic/tokens/utils/tokensStorage.js b/src/logic/tokens/utils/tokensStorage.js index 0016ebbb..ec1785c8 100644 --- a/src/logic/tokens/utils/tokensStorage.js +++ b/src/logic/tokens/utils/tokensStorage.js @@ -14,8 +14,7 @@ export const saveActiveTokens = async (tokens: Map) => { try { await saveToStorage(ACTIVE_TOKENS_KEY, tokens.toJS()) } catch (err) { - // eslint-disable-next-line - console.log('Error storing tokens in localstorage') + console.error('Error storing tokens in localstorage', err) } } @@ -38,8 +37,7 @@ export const removeTokenFromStorage = async (safeAddress: string, token: Token) const index = data.indexOf(token) await saveToStorage(CUSTOM_TOKENS_KEY, data.remove(index)) } catch (err) { - // eslint-disable-next-line - console.log('Error removing token in localstorage') + console.error('Error removing token in localstorage', err) } } diff --git a/src/routes/load/container/Load.jsx b/src/routes/load/container/Load.jsx index 86d3b6b3..181d0ec8 100644 --- a/src/routes/load/container/Load.jsx +++ b/src/routes/load/container/Load.jsx @@ -50,8 +50,7 @@ class Load extends React.Component { const url = `${SAFELIST_ADDRESS}/${safeAddress}` history.push(url) } catch (error) { - // eslint-disable-next-line - console.log('Error while loading the Safe' + error) + console.error('Error while loading the Safe', error) } } diff --git a/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.jsx b/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.jsx index 4766623f..008a7beb 100644 --- a/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.jsx @@ -117,8 +117,7 @@ const AddOwner = ({ try { sendAddOwner(values, safeAddress, owners, enqueueSnackbar, closeSnackbar, createTransaction, addSafeOwner) } catch (error) { - // eslint-disable-next-line - console.log('Error while removing an owner ' + error) + console.error('Error while removing an owner', error) } } diff --git a/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.jsx b/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.jsx index effb19c0..5de4cd97 100644 --- a/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.jsx @@ -123,8 +123,7 @@ const ReplaceOwner = ({ replaceSafeOwner, ) } catch (error) { - // eslint-disable-next-line - console.log('Error while removing an owner ' + error) + console.error('Error while removing an owner', error) } } diff --git a/src/utils/storage/signatures.js b/src/utils/storage/signatures.js index 2708cb98..a7cf5d3c 100644 --- a/src/utils/storage/signatures.js +++ b/src/utils/storage/signatures.js @@ -15,8 +15,7 @@ export const storeSignature = async (safeAddress: string, nonce: number, signatu const updatedSubjects = subjects.set(key, signatures) await saveToStorage(signaturesKey, updatedSubjects) } catch (err) { - // eslint-disable-next-line - console.log('Error storing signatures in localstorage') + console.error('Error storing signatures in localstorage', err) } } diff --git a/src/utils/storage/transactions.js b/src/utils/storage/transactions.js index ec29e002..5aca3d26 100644 --- a/src/utils/storage/transactions.js +++ b/src/utils/storage/transactions.js @@ -12,8 +12,7 @@ export const storeSubject = async (safeAddress: string, nonce: number, subject: const updatedSubjects = subjects.set(nonce, subject) saveToStorage(key, updatedSubjects) } catch (err) { - // eslint-disable-next-line - console.log('Error storing transaction subject in localstorage') + console.error('Error storing transaction subject in localstorage', err) } } From d159dba60e8109b9995e702852e87df1dbb0f6c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Sat, 28 Sep 2019 18:46:28 +0200 Subject: [PATCH 47/50] Rename TX_NOTIFICATION_TYPES --- src/logic/notifications/notificationBuilder.js | 16 ++++++++-------- .../safe/transactions/notifiedTransactions.js | 2 +- src/logic/wallets/store/actions/fetchProvider.js | 2 -- .../SendModal/screens/ReviewCustomTx/index.jsx | 4 ++-- .../SendModal/screens/ReviewTx/index.jsx | 4 ++-- .../components/Settings/ChangeSafeName/index.jsx | 4 ++-- .../ManageOwners/AddOwnerModal/index.jsx | 4 ++-- .../ManageOwners/EditOwnerModal/index.jsx | 4 ++-- .../ManageOwners/RemoveOwnerModal/index.jsx | 4 ++-- .../ManageOwners/ReplaceOwnerModal/index.jsx | 4 ++-- .../Settings/ThresholdSettings/index.jsx | 4 ++-- .../TxsTable/ExpandedTx/ApproveTxModal/index.jsx | 4 ++-- .../TxsTable/ExpandedTx/CancelTxModal/index.jsx | 4 ++-- 13 files changed, 29 insertions(+), 31 deletions(-) diff --git a/src/logic/notifications/notificationBuilder.js b/src/logic/notifications/notificationBuilder.js index 06d347aa..84b5b908 100644 --- a/src/logic/notifications/notificationBuilder.js +++ b/src/logic/notifications/notificationBuilder.js @@ -2,7 +2,7 @@ import * as React from 'react' import { IconButton } from '@material-ui/core' import { Close as IconClose } from '@material-ui/icons' -import { NOTIFIED_TRANSACTIONS } from '~/logic/safe/transactions' +import { TX_NOTIFICATION_TYPES } from '~/logic/safe/transactions' import { type Notification, NOTIFICATIONS } from './notificationTypes' type NotificationsQueue = { @@ -108,31 +108,31 @@ export const getNofiticationsFromTxType = (txType: string) => { let notificationsQueue: NotificationsQueue switch (txType) { - case NOTIFIED_TRANSACTIONS.STANDARD_TX: { + case TX_NOTIFICATION_TYPES.STANDARD_TX: { notificationsQueue = standardTxNotificationsQueue break } - case NOTIFIED_TRANSACTIONS.CONFIRMATION_TX: { + case TX_NOTIFICATION_TYPES.CONFIRMATION_TX: { notificationsQueue = confirmationTxNotificationsQueue break } - case NOTIFIED_TRANSACTIONS.CANCELLATION_TX: { + case TX_NOTIFICATION_TYPES.CANCELLATION_TX: { notificationsQueue = cancellationTxNotificationsQueue break } - case NOTIFIED_TRANSACTIONS.OWNER_CHANGE_TX: { + case TX_NOTIFICATION_TYPES.OWNER_CHANGE_TX: { notificationsQueue = ownerChangeTxNotificationsQueue break } - case NOTIFIED_TRANSACTIONS.SAFE_NAME_CHANGE_TX: { + case TX_NOTIFICATION_TYPES.SAFE_NAME_CHANGE_TX: { notificationsQueue = safeNameChangeNotificationsQueue break } - case NOTIFIED_TRANSACTIONS.OWNER_NAME_CHANGE_TX: { + case TX_NOTIFICATION_TYPES.OWNER_NAME_CHANGE_TX: { notificationsQueue = ownerNameChangeNotificationsQueue break } - case NOTIFIED_TRANSACTIONS.THRESHOLD_CHANGE_TX: { + case TX_NOTIFICATION_TYPES.THRESHOLD_CHANGE_TX: { notificationsQueue = thresholdChangeTxNotificationsQueue break } diff --git a/src/logic/safe/transactions/notifiedTransactions.js b/src/logic/safe/transactions/notifiedTransactions.js index 51d72558..1d60ec83 100644 --- a/src/logic/safe/transactions/notifiedTransactions.js +++ b/src/logic/safe/transactions/notifiedTransactions.js @@ -10,7 +10,7 @@ export type NotifiedTransaction = { THRESHOLD_CHANGE_TX: string, } -export const NOTIFIED_TRANSACTIONS: NotifiedTransaction = { +export const TX_NOTIFICATION_TYPES: NotifiedTransaction = { STANDARD_TX: 'STANDARD_TX', CONFIRMATION_TX: 'CONFIRMATION_TX', CANCELLATION_TX: 'CANCELLATION_TX', diff --git a/src/logic/wallets/store/actions/fetchProvider.js b/src/logic/wallets/store/actions/fetchProvider.js index f12fdf00..3e67c79c 100644 --- a/src/logic/wallets/store/actions/fetchProvider.js +++ b/src/logic/wallets/store/actions/fetchProvider.js @@ -4,8 +4,6 @@ import { ETHEREUM_NETWORK_IDS, ETHEREUM_NETWORK } from '~/logic/wallets/getWeb3' import type { ProviderProps } from '~/logic/wallets/store/model/provider' import { makeProvider } from '~/logic/wallets/store/model/provider' import { NOTIFICATIONS, showSnackbar } from '~/logic/notifications' -// import enqueueSnackbar as enqueueSnackbarAction from '~/logic/notifications/store/actions/enqueueSnackbar' -// import closeSnackbar as closeSnackbarAction from '~/logic/notifications/store/actions/closeSnackbar' import addProvider from './addProvider' export const processProviderResponse = (dispatch: ReduxDispatch<*>, provider: ProviderProps) => { diff --git a/src/routes/safe/components/Balances/SendModal/screens/ReviewCustomTx/index.jsx b/src/routes/safe/components/Balances/SendModal/screens/ReviewCustomTx/index.jsx index 0724e35c..aa54f6cf 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ReviewCustomTx/index.jsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ReviewCustomTx/index.jsx @@ -18,7 +18,7 @@ import { copyToClipboard } from '~/utils/clipboard' import SafeInfo from '~/routes/safe/components/Balances/SendModal/SafeInfo' import { setImageToPlaceholder } from '~/routes/safe/components/Balances/utils' import { getWeb3 } from '~/logic/wallets/getWeb3' -import { NOTIFIED_TRANSACTIONS } from '~/logic/safe/transactions' +import { TX_NOTIFICATION_TYPES } from '~/logic/safe/transactions' import { getEthAsToken } from '~/logic/tokens/utils/tokenHelpers' import ArrowDown from '../assets/arrow-down.svg' import { secondary } from '~/theme/variables' @@ -67,7 +67,7 @@ const ReviewCustomTx = ({ txRecipient, txValue, txData, - NOTIFIED_TRANSACTIONS.STANDARD_TX, + TX_NOTIFICATION_TYPES.STANDARD_TX, enqueueSnackbar, closeSnackbar, ) diff --git a/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.jsx b/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.jsx index fb320a8d..0aa41c67 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.jsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.jsx @@ -20,7 +20,7 @@ import { setImageToPlaceholder } from '~/routes/safe/components/Balances/utils' import { getStandardTokenContract } from '~/logic/tokens/store/actions/fetchTokens' import { EMPTY_DATA } from '~/logic/wallets/ethTransactions' import { getWeb3 } from '~/logic/wallets/getWeb3' -import { NOTIFIED_TRANSACTIONS } from '~/logic/safe/transactions' +import { TX_NOTIFICATION_TYPES } from '~/logic/safe/transactions' import ArrowDown from '../assets/arrow-down.svg' import { secondary } from '~/theme/variables' import { isEther } from '~/logic/tokens/utils/tokenHelpers' @@ -81,7 +81,7 @@ const ReviewTx = ({ txRecipient, txAmount, txData, - NOTIFIED_TRANSACTIONS.STANDARD_TX, + TX_NOTIFICATION_TYPES.STANDARD_TX, enqueueSnackbar, closeSnackbar, ) diff --git a/src/routes/safe/components/Settings/ChangeSafeName/index.jsx b/src/routes/safe/components/Settings/ChangeSafeName/index.jsx index 95ca1c05..764d7994 100644 --- a/src/routes/safe/components/Settings/ChangeSafeName/index.jsx +++ b/src/routes/safe/components/Settings/ChangeSafeName/index.jsx @@ -13,7 +13,7 @@ import Row from '~/components/layout/Row' import Paragraph from '~/components/layout/Paragraph' import Button from '~/components/layout/Button' import { getNofiticationsFromTxType, showSnackbar } from '~/logic/notifications' -import { NOTIFIED_TRANSACTIONS } from '~/logic/safe/transactions' +import { TX_NOTIFICATION_TYPES } from '~/logic/safe/transactions' import { styles } from './style' export const SAFE_NAME_INPUT_TEST_ID = 'safe-name-input' @@ -36,7 +36,7 @@ const ChangeSafeName = (props: Props) => { const handleSubmit = (values) => { updateSafe({ address: safeAddress, name: values.safeName }) - const notification = getNofiticationsFromTxType(NOTIFIED_TRANSACTIONS.SAFE_NAME_CHANGE_TX) + const notification = getNofiticationsFromTxType(TX_NOTIFICATION_TYPES.SAFE_NAME_CHANGE_TX) showSnackbar(notification.afterExecution, enqueueSnackbar, closeSnackbar) } diff --git a/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.jsx b/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.jsx index 008a7beb..66d51631 100644 --- a/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.jsx @@ -6,7 +6,7 @@ import { withSnackbar } from 'notistack' import Modal from '~/components/Modal' import { type Owner } from '~/routes/safe/store/models/owner' import { getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts' -import { NOTIFIED_TRANSACTIONS } from '~/logic/safe/transactions' +import { TX_NOTIFICATION_TYPES } from '~/logic/safe/transactions' import OwnerForm from './screens/OwnerForm' import ThresholdForm from './screens/ThresholdForm' import ReviewAddOwner from './screens/Review' @@ -52,7 +52,7 @@ export const sendAddOwner = async ( safeAddress, 0, txData, - NOTIFIED_TRANSACTIONS.OWNER_CHANGE_TX, + TX_NOTIFICATION_TYPES.OWNER_CHANGE_TX, enqueueSnackbar, closeSnackbar, ) diff --git a/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/index.jsx b/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/index.jsx index 186b386d..c17386c3 100644 --- a/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/index.jsx @@ -17,7 +17,7 @@ import Paragraph from '~/components/layout/Paragraph' import Identicon from '~/components/Identicon' import { composeValidators, required, minMaxLength } from '~/components/forms/validator' import { getNofiticationsFromTxType, showSnackbar } from '~/logic/notifications' -import { NOTIFIED_TRANSACTIONS } from '~/logic/safe/transactions' +import { TX_NOTIFICATION_TYPES } from '~/logic/safe/transactions' import { getEtherScanLink } from '~/logic/wallets/getWeb3' import Modal from '~/components/Modal' import { styles } from './style' @@ -59,7 +59,7 @@ const EditOwnerComponent = ({ const handleSubmit = (values) => { editSafeOwner({ safeAddress, ownerAddress, ownerName: values.ownerName }) - const notification = getNofiticationsFromTxType(NOTIFIED_TRANSACTIONS.OWNER_NAME_CHANGE_TX) + const notification = getNofiticationsFromTxType(TX_NOTIFICATION_TYPES.OWNER_NAME_CHANGE_TX) showSnackbar(notification.afterExecution, enqueueSnackbar, closeSnackbar) onClose() diff --git a/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/index.jsx b/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/index.jsx index ec160610..be59b517 100644 --- a/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/index.jsx @@ -6,7 +6,7 @@ import { withSnackbar } from 'notistack' import Modal from '~/components/Modal' import { type Owner } from '~/routes/safe/store/models/owner' import { getGnosisSafeInstanceAt, SENTINEL_ADDRESS } from '~/logic/contracts/safeContracts' -import { NOTIFIED_TRANSACTIONS } from '~/logic/safe/transactions' +import { TX_NOTIFICATION_TYPES } from '~/logic/safe/transactions' import CheckOwner from './screens/CheckOwner' import ThresholdForm from './screens/ThresholdForm' import ReviewRemoveOwner from './screens/Review' @@ -64,7 +64,7 @@ export const sendRemoveOwner = async ( safeAddress, 0, txData, - NOTIFIED_TRANSACTIONS.OWNER_CHANGE_TX, + TX_NOTIFICATION_TYPES.OWNER_CHANGE_TX, enqueueSnackbar, closeSnackbar, ) diff --git a/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.jsx b/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.jsx index 5de4cd97..498b9a62 100644 --- a/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.jsx +++ b/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.jsx @@ -4,7 +4,7 @@ import { List } from 'immutable' import { withStyles } from '@material-ui/core/styles' import { withSnackbar } from 'notistack' import Modal from '~/components/Modal' -import { NOTIFIED_TRANSACTIONS } from '~/logic/safe/transactions' +import { TX_NOTIFICATION_TYPES } from '~/logic/safe/transactions' import { getGnosisSafeInstanceAt, SENTINEL_ADDRESS } from '~/logic/contracts/safeContracts' import OwnerForm from './screens/OwnerForm' import ReviewReplaceOwner from './screens/Review' @@ -59,7 +59,7 @@ export const sendReplaceOwner = async ( safeAddress, 0, txData, - NOTIFIED_TRANSACTIONS.OWNER_CHANGE_TX, + TX_NOTIFICATION_TYPES.OWNER_CHANGE_TX, enqueueSnackbar, closeSnackbar, ) diff --git a/src/routes/safe/components/Settings/ThresholdSettings/index.jsx b/src/routes/safe/components/Settings/ThresholdSettings/index.jsx index 87317313..8afaf2a8 100644 --- a/src/routes/safe/components/Settings/ThresholdSettings/index.jsx +++ b/src/routes/safe/components/Settings/ThresholdSettings/index.jsx @@ -10,7 +10,7 @@ import Block from '~/components/layout/Block' import Row from '~/components/layout/Row' import Modal from '~/components/Modal' import Paragraph from '~/components/layout/Paragraph' -import { NOTIFIED_TRANSACTIONS } from '~/logic/safe/transactions' +import { TX_NOTIFICATION_TYPES } from '~/logic/safe/transactions' import ChangeThreshold from './ChangeThreshold' import type { Owner } from '~/routes/safe/store/models/owner' import { getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts' @@ -52,7 +52,7 @@ const ThresholdSettings = ({ safeAddress, 0, txData, - NOTIFIED_TRANSACTIONS.THRESHOLD_CHANGE_TX, + TX_NOTIFICATION_TYPES.THRESHOLD_CHANGE_TX, enqueueSnackbar, closeSnackbar, ) 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 3ac906db..aeba3ae7 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/ApproveTxModal/index.jsx +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/ApproveTxModal/index.jsx @@ -13,7 +13,7 @@ import Row from '~/components/layout/Row' import Bold from '~/components/layout/Bold' import Block from '~/components/layout/Block' import Paragraph from '~/components/layout/Paragraph' -import { NOTIFIED_TRANSACTIONS } from '~/logic/safe/transactions' +import { TX_NOTIFICATION_TYPES } from '~/logic/safe/transactions' import { type Transaction } from '~/routes/safe/store/models/transaction' import { styles } from './style' @@ -72,7 +72,7 @@ const ApproveTxModal = ({ safeAddress, tx, userAddress, - NOTIFIED_TRANSACTIONS.CONFIRMATION_TX, + TX_NOTIFICATION_TYPES.CONFIRMATION_TX, enqueueSnackbar, closeSnackbar, approveAndExecute, diff --git a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/CancelTxModal/index.jsx b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/CancelTxModal/index.jsx index abec6e5d..e7b34275 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/CancelTxModal/index.jsx +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/CancelTxModal/index.jsx @@ -13,7 +13,7 @@ import Block from '~/components/layout/Block' import Paragraph from '~/components/layout/Paragraph' import { type Transaction } from '~/routes/safe/store/models/transaction' import { EMPTY_DATA } from '~/logic/wallets/ethTransactions' -import { NOTIFIED_TRANSACTIONS } from '~/logic/safe/transactions' +import { TX_NOTIFICATION_TYPES } from '~/logic/safe/transactions' import { styles } from './style' type Props = { @@ -43,7 +43,7 @@ const CancelTxModal = ({ safeAddress, 0, EMPTY_DATA, - NOTIFIED_TRANSACTIONS.CANCELLATION_TX, + TX_NOTIFICATION_TYPES.CANCELLATION_TX, enqueueSnackbar, closeSnackbar, ) From c342277c491f8ba0edf0421675889830d33b4551 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Sat, 28 Sep 2019 18:55:41 +0200 Subject: [PATCH 48/50] Style notifications --- src/theme/mui.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/theme/mui.js b/src/theme/mui.js index aa7dbebe..06404c67 100644 --- a/src/theme/mui.js +++ b/src/theme/mui.js @@ -204,17 +204,21 @@ export default createMuiTheme({ color: secondaryText, }, }, - /* MuiSnackbar: { - anchorOriginTopRight: { - marginTop: '50px', + MuiSnackbar: { + root: { + width: '280px', }, - }, */ + }, MuiSnackbarContent: { message: { + maxWidth: '260px', '& img': { marginRight: '5px', }, }, + action: { + paddingLeft: 0, + }, }, MuiTab: { root: { From 54e4ecfba64902526717e2bcd3538690bc57858c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Sat, 28 Sep 2019 19:27:06 +0200 Subject: [PATCH 49/50] Import notistack package forked by Gnosis --- package.json | 2 +- yarn.lock | 11 +++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 179e02ae..b0a11c6b 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "immortal-db": "^1.0.2", "immutable": "^4.0.0-rc.9", "material-ui-search-bar": "^1.0.0-beta.13", - "notistack": "^0.9.2", + "notistack": "https://github.com/gnosis/notistack.git#v0.9.4", "optimize-css-assets-webpack-plugin": "5.0.3", "qrcode.react": "^0.9.3", "react": "16.9.0", diff --git a/yarn.lock b/yarn.lock index dfcc3378..64684c41 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12893,15 +12893,14 @@ normalize-url@^4.1.0: resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.3.0.tgz#9c49e10fc1876aeb76dba88bf1b2b5d9fa57b2ee" integrity sha512-0NLtR71o4k6GLP+mr6Ty34c5GA6CMoEsncKJxvQd8NzPxaHRJNnb5gZE8R1XF4CPIS7QPHLJ74IFszwtNVAHVQ== -notistack@^0.9.2: - version "0.9.2" - resolved "https://registry.yarnpkg.com/notistack/-/notistack-0.9.2.tgz#333ca7e08e85ae10867b1e8be5d82b149676aad6" - integrity sha512-Z2zi3ankqvwmrQvUx7SHM2X3P8llbPA/O1nM1hqn2fGuffn40Fi8isw701pdxczxA6S7huSyfOE/ZPgeTpWmrQ== +"notistack@https://github.com/gnosis/notistack.git#v0.9.4": + version "0.9.4" + resolved "https://github.com/gnosis/notistack.git#077aa51fd066f2c3198b2f5ce773f741e21f24df" dependencies: classnames "^2.2.6" hoist-non-react-statics "^3.3.0" prop-types "^15.7.2" - react-is "^16.8.6" + react-is "^16.9.0" now-and-later@^2.0.0: version "2.0.1" @@ -20395,4 +20394,4 @@ yauzl@^2.4.2: integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= dependencies: buffer-crc32 "~0.2.3" - fd-slicer "~1.1.0" \ No newline at end of file + fd-slicer "~1.1.0" From 286d06215539f9dea989df28edcf3b7b5b22f703 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Sat, 28 Sep 2019 20:01:30 +0200 Subject: [PATCH 50/50] Style provider info --- src/components/Header/component/Layout.jsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/components/Header/component/Layout.jsx b/src/components/Header/component/Layout.jsx index 90af595a..d5e5f85e 100644 --- a/src/components/Header/component/Layout.jsx +++ b/src/components/Header/component/Layout.jsx @@ -33,7 +33,7 @@ const styles = () => ({ boxShadow: '0 0 10px 0 rgba(33, 48, 77, 0.1)', minWidth: '280px', borderRadius: '8px', - marginTop: '12px', + marginTop: '11px', }, summary: { borderBottom: `solid 2px ${border}`, @@ -42,13 +42,15 @@ const styles = () => ({ boxShadow: '0 2px 4px 0 rgba(212, 212, 211, 0.59)', backgroundColor: 'white', zIndex: 1301, - boxShadow: '0 2px 4px 0 rgba(212, 212, 211, 0.59)', }, logo: { padding: `${sm} ${md}`, flexBasis: '95px', flexGrow: 0, }, + popper: { + zIndex: 2000, + }, }) const Layout = openHoc(({ @@ -67,7 +69,7 @@ const Layout = openHoc(({ {(providerRef) => ( - + {({ TransitionProps }) => ( <>