diff --git a/package.json b/package.json index bde93d22..d5ebe776 100644 --- a/package.json +++ b/package.json @@ -77,6 +77,7 @@ "immutable": "^4.0.0-rc.9", "material-ui-search-bar": "^1.0.0-beta.13", "optimize-css-assets-webpack-plugin": "^5.0.1", + "qrcode.react": "^0.9.3", "react": "^16.8.6", "react-dom": "^16.8.6", "react-final-form": "^4.1.0", diff --git a/src/components/Header/component/ProviderDetails/UserDetails.jsx b/src/components/Header/component/ProviderDetails/UserDetails.jsx index 1338aba2..e90b3bbc 100644 --- a/src/components/Header/component/ProviderDetails/UserDetails.jsx +++ b/src/components/Header/component/ProviderDetails/UserDetails.jsx @@ -4,6 +4,7 @@ import classNames from 'classnames' import OpenInNew from '@material-ui/icons/OpenInNew' import { withStyles } from '@material-ui/core/styles' import Paragraph from '~/components/layout/Paragraph' +import Link from '~/components/layout/Link' import Button from '~/components/layout/Button' import Identicon from '~/components/Identicon' import Dot from '@material-ui/icons/FiberManualRecord' @@ -17,7 +18,7 @@ import { } from '~/theme/variables' import { upperFirst } from '~/utils/css' import { shortVersionOf } from '~/logic/wallets/ethAddresses' -import { openAddressInEtherScan } from '~/logic/wallets/getWeb3' +import { getEtherScanLink } from '~/logic/wallets/getWeb3' import CircleDot from '~/components/Header/component/CircleDot' const metamask = require('../../assets/metamask.svg') @@ -121,11 +122,9 @@ const UserDetails = ({ {address} {userAddress && ( - + + + )} diff --git a/src/components/layout/Col/index.jsx b/src/components/layout/Col/index.jsx index ad043eab..67c9782f 100644 --- a/src/components/layout/Col/index.jsx +++ b/src/components/layout/Col/index.jsx @@ -31,10 +31,26 @@ type Props = { } const Col = ({ - children, margin, layout = 'inherit', overflow, - xs, sm, md, lg, - start, center, end, top, middle, bottom, around, between, - xsOffset, smOffset, mdOffset, lgOffset, + children, + margin, + layout = 'inherit', + overflow, + xs, + sm, + md, + lg, + start, + center, + end, + top, + middle, + bottom, + around, + between, + xsOffset, + smOffset, + mdOffset, + lgOffset, className, ...props }: Props) => { @@ -64,7 +80,7 @@ const Col = ({ return (
- { children } + {children}
) } diff --git a/src/components/layout/Link/index.jsx b/src/components/layout/Link/index.jsx index 6523fbcf..5ffed167 100644 --- a/src/components/layout/Link/index.jsx +++ b/src/components/layout/Link/index.jsx @@ -18,17 +18,14 @@ type Props = { const GnosisLink = ({ to, children, color, className, padding, ...props }: Props) => { - const classes = cx( - styles.link, - color || 'regular', - padding ? capitalize(padding, 'padding') : undefined, - className, - ) + const internal = /^\/(?!\/)/.test(to) + const classes = cx(styles.link, color || 'regular', padding ? capitalize(padding, 'padding') : undefined, className) + const LinkElement = internal ? Link : 'a' return ( - - { children } - + + {children} + ) } diff --git a/src/logic/wallets/getWeb3.js b/src/logic/wallets/getWeb3.js index 12d28a07..aecfaaa4 100644 --- a/src/logic/wallets/getWeb3.js +++ b/src/logic/wallets/getWeb3.js @@ -33,9 +33,7 @@ export const ETHEREUM_NETWORK_IDS = { export const openTxInEtherScan = (tx: string, network: string) => `https://${network}.etherscan.io/tx/${tx}` -export const openAddressInEtherScan = (address: string, network: string) => () => { - window.open(`https://${network}.etherscan.io/address/${address}`) -} +export const getEtherScanLink = (address: string, network: string) => `https://${network}.etherscan.io/address/${address}` let web3 export const getWeb3 = () => web3 || new Web3(window.web3.currentProvider) diff --git a/src/routes/load/components/ReviewInformation/index.jsx b/src/routes/load/components/ReviewInformation/index.jsx index 3777617f..645a064c 100644 --- a/src/routes/load/components/ReviewInformation/index.jsx +++ b/src/routes/load/components/ReviewInformation/index.jsx @@ -6,11 +6,12 @@ import OpenInNew from '@material-ui/icons/OpenInNew' import Identicon from '~/components/Identicon' import OpenPaper from '~/components/Stepper/OpenPaper' import Row from '~/components/layout/Row' +import Link from '~/components/layout/Link' import Paragraph from '~/components/layout/Paragraph' import { xs, sm, lg, border, secondary, } from '~/theme/variables' -import { openAddressInEtherScan, getWeb3 } from '~/logic/wallets/getWeb3' +import { getEtherScanLink, getWeb3 } from '~/logic/wallets/getWeb3' import { FIELD_LOAD_NAME, FIELD_LOAD_ADDRESS } from '~/routes/load/components/fields' import { sameAddress } from '~/logic/wallets/ethAddresses' import { getGnosisSafeContract } from '~/logic/contracts/safeContracts' @@ -113,12 +114,12 @@ class ReviewComponent extends React.PureComponent { - {safeAddress} - + + {safeAddress} + + + + @@ -126,7 +127,7 @@ class ReviewComponent extends React.PureComponent { Connected wallet client is owner? - { isOwner ? 'Yes' : 'No (read-only)' } + {isOwner ? 'Yes' : 'No (read-only)'} @@ -145,5 +146,4 @@ const Review = ({ network, userAddress }: LayoutProps) => (controls: React$Node, ) - export default Review diff --git a/src/routes/open/components/ReviewInformation/index.jsx b/src/routes/open/components/ReviewInformation/index.jsx index 55a7e68b..091c458b 100644 --- a/src/routes/open/components/ReviewInformation/index.jsx +++ b/src/routes/open/components/ReviewInformation/index.jsx @@ -9,12 +9,13 @@ import Identicon from '~/components/Identicon' import OpenPaper from '~/components/Stepper/OpenPaper' import Col from '~/components/layout/Col' import Row from '~/components/layout/Row' +import Link from '~/components/layout/Link' import Paragraph from '~/components/layout/Paragraph' import { sm, md, lg, border, secondary, background, } from '~/theme/variables' import Hairline from '~/components/layout/Hairline' -import { openAddressInEtherScan } from '~/logic/wallets/getWeb3' +import { getEtherScanLink } from '~/logic/wallets/getWeb3' import { FIELD_NAME, FIELD_CONFIRMATIONS, getNumOwnersFrom } from '../fields' const openIconStyle = { @@ -128,11 +129,9 @@ const ReviewComponent = ({ values, classes, network }: Props) => { {addresses[index]} - + + + diff --git a/src/routes/safe/components/Balances/Receive/index.jsx b/src/routes/safe/components/Balances/Receive/index.jsx index 62d23420..01c75592 100644 --- a/src/routes/safe/components/Balances/Receive/index.jsx +++ b/src/routes/safe/components/Balances/Receive/index.jsx @@ -3,14 +3,26 @@ import * as React from 'react' import { withStyles } from '@material-ui/core/styles' import Close from '@material-ui/icons/Close' import IconButton from '@material-ui/core/IconButton' +import OpenInNew from '@material-ui/icons/OpenInNew' +import Link from '~/components/layout/Link' +import QRCode from 'qrcode.react' import Paragraph from '~/components/layout/Paragraph' +import Identicon from '~/components/Identicon' +import Button from '~/components/layout/Button' +import Block from '~/components/layout/Block' import Row from '~/components/layout/Row' -import { lg, md } from '~/theme/variables' +import Hairline from '~/components/layout/Hairline' +import Col from '~/components/layout/Col' +import { + xxl, lg, sm, md, background, secondary, +} from '~/theme/variables' +import { copyToClipboard } from '~/utils/clipboard' const styles = () => ({ heading: { - padding: `${md} ${lg}`, + padding: `${sm} ${lg}`, justifyContent: 'space-between', + maxHeight: '75px', }, manage: { fontSize: '24px', @@ -19,22 +31,81 @@ const styles = () => ({ height: '35px', width: '35px', }, + detailsContainer: { + backgroundColor: background, + }, + qrContainer: { + backgroundColor: '#fff', + padding: md, + borderRadius: '3px', + boxShadow: '0 0 5px 0 rgba(74, 85, 121, 0.5)', + }, + safeName: { + margin: `${xxl} 0 20px`, + }, + buttonRow: { + height: '84px', + justifyContent: 'center', + }, + button: { + height: '42px', + }, + addressContainer: { + marginTop: '28px', + }, + address: { + marginLeft: '6px', + }, }) +const openIconStyle = { + height: '16px', + color: secondary, +} + type Props = { onClose: () => void, classes: Object, + safeName: string, + safeAddress: string, + etherScanLink: string, } -const Send = ({ classes, onClose }: Props) => ( +const Receive = ({ + classes, onClose, safeAddress, safeName, etherScanLink, +}: Props) => ( - Receive Funds + + Receive funds + + + + + {safeName} + + + + + + + {safeAddress} + + + + + + + + + ) -export default withStyles(styles)(Send) +export default withStyles(styles)(Receive) diff --git a/src/routes/safe/components/Balances/Tokens/screens/AddCustomToken/index.jsx b/src/routes/safe/components/Balances/Tokens/screens/AddCustomToken/index.jsx index e764cbad..52310ba6 100644 --- a/src/routes/safe/components/Balances/Tokens/screens/AddCustomToken/index.jsx +++ b/src/routes/safe/components/Balances/Tokens/screens/AddCustomToken/index.jsx @@ -44,7 +44,15 @@ const INITIAL_FORM_STATE = { const AddCustomToken = (props: Props) => { const { - classes, setActiveScreen, onClose, addToken, updateActiveTokens, safeAddress, activeTokens, tokens, activateTokenForAllSafes, + classes, + setActiveScreen, + onClose, + addToken, + updateActiveTokens, + safeAddress, + activeTokens, + tokens, + activateTokenForAllSafes, } = props const [formValues, setFormValues] = useState(INITIAL_FORM_STATE) diff --git a/src/routes/safe/components/Balances/index.jsx b/src/routes/safe/components/Balances/index.jsx index bff62c62..998ed306 100644 --- a/src/routes/safe/components/Balances/index.jsx +++ b/src/routes/safe/components/Balances/index.jsx @@ -38,6 +38,8 @@ type Props = { tokens: List, activeTokens: List, safeAddress: string, + safeName: string, + etherScanLink: string, } type Action = 'Token' | 'Send' | 'Receive' @@ -69,7 +71,7 @@ class Balances extends React.Component { hideZero, showToken, showReceive, showSend, } = this.state const { - classes, granted, tokens, safeAddress, activeTokens, + classes, granted, tokens, safeAddress, activeTokens, safeName, etherScanLink, } = this.props const columns = generateColumns() @@ -166,7 +168,12 @@ class Balances extends React.Component { handleClose={this.onHide('Receive')} open={showReceive} > - + ) diff --git a/src/routes/safe/components/Layout.jsx b/src/routes/safe/components/Layout.jsx index c8acb4f4..25fa8a58 100644 --- a/src/routes/safe/components/Layout.jsx +++ b/src/routes/safe/components/Layout.jsx @@ -9,10 +9,11 @@ import Identicon from '~/components/Identicon' import { withStyles } from '@material-ui/core/styles' import Heading from '~/components/layout/Heading' import Row from '~/components/layout/Row' +import Link from '~/components/layout/Link' import Paragraph from '~/components/layout/Paragraph' import NoSafe from '~/components/NoSafe' import { type SelectorProps } from '~/routes/safe/container/selector' -import { openAddressInEtherScan } from '~/logic/wallets/getWeb3' +import { getEtherScanLink } from '~/logic/wallets/getWeb3' import { sm, xs, secondary, smallFontSize, } from '~/theme/variables' @@ -95,7 +96,8 @@ class Layout extends React.Component { return } - const { address, ethBalance } = safe + const { address, ethBalance, name } = safe + const etherScanLink = getEtherScanLink(address, network) return ( @@ -104,7 +106,7 @@ class Layout extends React.Component { - {safe.get('name')} + {name} {!granted && Read Only} @@ -112,11 +114,9 @@ class Layout extends React.Component { {address} - + + + @@ -135,6 +135,8 @@ class Layout extends React.Component { activeTokens={activeTokens} granted={granted} safeAddress={address} + safeName={name} + etherScanLink={etherScanLink} /> )} diff --git a/yarn.lock b/yarn.lock index b9f060e3..f10418f6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13251,6 +13251,19 @@ q@^1.1.2: resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= +qr.js@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/qr.js/-/qr.js-0.0.0.tgz#cace86386f59a0db8050fa90d9b6b0e88a1e364f" + integrity sha1-ys6GOG9ZoNuAUPqQ2baw6IoeNk8= + +qrcode.react@^0.9.3: + version "0.9.3" + resolved "https://registry.yarnpkg.com/qrcode.react/-/qrcode.react-0.9.3.tgz#91de1287912bdc5ccfb3b091737b828d6ced60c5" + integrity sha512-gGd30Ez7cmrKxyN2M3nueaNLk/f9J7NDRgaD5fVgxGpPLsYGWMn9UQ+XnDpv95cfszTQTdaf4QGLNMf3xU0hmw== + dependencies: + prop-types "^15.6.0" + qr.js "0.0.0" + qs@6.5.2, qs@~6.5.2: version "6.5.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"