Merge pull request #184 from gnosis/141-mainnet-compatibility
Feature #141: Mainnet compatibility
This commit is contained in:
commit
4dd05b781a
27
.travis.yml
27
.travis.yml
|
@ -9,11 +9,20 @@ node_js:
|
|||
os:
|
||||
- linux
|
||||
env:
|
||||
global:
|
||||
- DOCKER_COMPOSE_VERSION=1.22.0
|
||||
matrix:
|
||||
include:
|
||||
- env:
|
||||
- REACT_APP_NETWORK='mainnet'
|
||||
- STAGING_BUCKET_NAME=${STAGING_MAINNET_BUCKET_NAME}
|
||||
if: branch = master OR tag IS present
|
||||
- env:
|
||||
- REACT_APP_NETWORK='rinkeby'
|
||||
before_install:
|
||||
# Install custom docker-compose version
|
||||
- sudo rm /usr/local/bin/docker-compose
|
||||
- curl -L https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-`uname -s`-`uname -m` > docker-compose
|
||||
- curl -Ls https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-`uname -s`-`uname -m` > docker-compose
|
||||
- chmod +x docker-compose
|
||||
- sudo mv docker-compose /usr/local/bin
|
||||
# Shut down postgres because it blocks our db container's port map to :5432
|
||||
|
@ -50,6 +59,7 @@ after_success:
|
|||
else
|
||||
export NODE_ENV=development;
|
||||
fi
|
||||
- if [[ -n "$TRAVIS_TAG" ]]; then export REACT_APP_ENV='production'; fi
|
||||
- yarn build-storybook
|
||||
- yarn build
|
||||
# Pull Request - Deploy it to a review environment
|
||||
|
@ -91,3 +101,18 @@ deploy:
|
|||
upload-dir: current
|
||||
on:
|
||||
branch: master
|
||||
|
||||
# Prepare production deployment
|
||||
- provider: s3
|
||||
bucket: $STAGING_BUCKET_NAME
|
||||
secret_access_key: $AWS_SECRET_ACCESS_KEY
|
||||
access_key_id: $AWS_ACCESS_KEY_ID
|
||||
skip_cleanup: true
|
||||
local_dir: build_webpack
|
||||
upload-dir: releases/$TRAVIS_TAG
|
||||
on:
|
||||
tags: true
|
||||
- provider: script
|
||||
script: bash config/travis/prepare_production_deployment.sh
|
||||
on:
|
||||
tags: true
|
|
@ -1,28 +1,29 @@
|
|||
// @flow
|
||||
// Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be
|
||||
// injected into the application via DefinePlugin in Webpack configuration.
|
||||
|
||||
var REACT_APP = /^REACT_APP_/i;
|
||||
const REACT_APP = /^REACT_APP_/i
|
||||
|
||||
function getClientEnvironment(publicUrl) {
|
||||
var processEnv = Object
|
||||
.keys(process.env)
|
||||
.filter(key => REACT_APP.test(key))
|
||||
.reduce((env, key) => {
|
||||
env[key] = JSON.stringify(process.env[key]);
|
||||
return env;
|
||||
}, {
|
||||
const processEnv = Object.keys(process.env)
|
||||
.filter((key) => REACT_APP.test(key))
|
||||
.reduce(
|
||||
(env, key) => {
|
||||
env[key] = JSON.stringify(process.env[key])
|
||||
return env
|
||||
},
|
||||
{
|
||||
// Useful for determining whether we’re running in production mode.
|
||||
// Most importantly, it switches React into the correct mode.
|
||||
'NODE_ENV': JSON.stringify(
|
||||
process.env.NODE_ENV || 'development'
|
||||
),
|
||||
NODE_ENV: JSON.stringify(process.env.NODE_ENV || 'development'),
|
||||
// Useful for resolving the correct path to static assets in `public`.
|
||||
// For example, <img src={process.env.PUBLIC_URL + '/img/logo.png'} />.
|
||||
// This should only be used as an escape hatch. Normally you would put
|
||||
// images into the `src` and `import` them in code to get their paths.
|
||||
'PUBLIC_URL': JSON.stringify(publicUrl)
|
||||
});
|
||||
return {'process.env': processEnv};
|
||||
PUBLIC_URL: JSON.stringify(publicUrl),
|
||||
},
|
||||
)
|
||||
return { 'process.env': processEnv }
|
||||
}
|
||||
|
||||
module.exports = getClientEnvironment;
|
||||
module.exports = getClientEnvironment
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -ev
|
||||
|
||||
# Only:
|
||||
# - Tagged commits
|
||||
# - Security env variables are available.
|
||||
if [ -n "$TRAVIS_TAG" ] && [ -n "$PROD_DEPLOYMENT_HOOK_TOKEN" ] && [ -n "$PROD_DEPLOYMENT_HOOK_URL" ]
|
||||
then
|
||||
curl --silent --output /dev/null --write-out "%{http_code}" -X POST \
|
||||
-F token="$PROD_DEPLOYMENT_HOOK_TOKEN" \
|
||||
-F ref=master \
|
||||
-F "variables[TRIGGER_RELEASE_COMMIT_TAG]=$TRAVIS_TAG" \
|
||||
$PROD_DEPLOYMENT_HOOK_URL
|
||||
else
|
||||
echo "[ERROR] Production deployment could not be prepared"
|
||||
fi
|
|
@ -17,10 +17,12 @@
|
|||
},
|
||||
"scripts": {
|
||||
"build": "node scripts/build.js",
|
||||
"build-mainnet": "REACT_APP_NETWORK=mainnet yarn build",
|
||||
"build-storybook": "build-storybook -o build_storybook",
|
||||
"flow": "flow",
|
||||
"precommit": "./precommit.sh",
|
||||
"start": "node scripts/start.js",
|
||||
"start-mainnet": "REACT_APP_NETWORK=mainnet yarn start",
|
||||
"storybook": "start-storybook -p 6006",
|
||||
"test": "NODE_ENV=test && node scripts/test.js --env=jsdom",
|
||||
"format": "prettier-eslint \"src/**/*.js\" --write"
|
||||
|
|
22
readme.md
22
readme.md
|
@ -18,7 +18,7 @@ yarn add flow-type // recommended usage of -g flag
|
|||
|
||||
We use [yarn](https://yarnpkg.com) in our infrastacture, so we decided to go with yarn in the README
|
||||
|
||||
### Installing
|
||||
### Installing and running
|
||||
|
||||
A step by step series of examples that tell you have to get a development env running
|
||||
|
||||
|
@ -30,8 +30,28 @@ ganache-cli -b 3
|
|||
Start the project in the other one
|
||||
```
|
||||
yarn install
|
||||
```
|
||||
|
||||
For Rinkeby:
|
||||
```
|
||||
yarn start
|
||||
```
|
||||
For Mainnet:
|
||||
```
|
||||
yarn start-mainnet
|
||||
```
|
||||
|
||||
### Building
|
||||
For Rinkeby:
|
||||
```
|
||||
yarn build
|
||||
```
|
||||
|
||||
For Mainnet:
|
||||
```
|
||||
yarn build-mainnet
|
||||
```
|
||||
|
||||
|
||||
## Running the tests
|
||||
|
||||
|
|
|
@ -2,11 +2,9 @@
|
|||
import React from 'react'
|
||||
import Tooltip from '@material-ui/core/Tooltip'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
import { connect } from 'react-redux'
|
||||
import Img from '~/components/layout/Img'
|
||||
import { getEtherScanLink } from '~/logic/wallets/getWeb3'
|
||||
import { xs } from '~/theme/variables'
|
||||
import { networkSelector } from '~/logic/wallets/store/selectors'
|
||||
import SearchIcon from './search.svg'
|
||||
|
||||
const styles = () => ({
|
||||
|
@ -26,17 +24,16 @@ const styles = () => ({
|
|||
type EtherscanBtnProps = {
|
||||
type: 'tx' | 'address',
|
||||
value: string,
|
||||
currentNetwork: string,
|
||||
classes: Object,
|
||||
}
|
||||
|
||||
const EtherscanBtn = ({
|
||||
type, value, currentNetwork, classes,
|
||||
type, value, classes,
|
||||
}: EtherscanBtnProps) => (
|
||||
<Tooltip title="Show details on Etherscan" placement="top">
|
||||
<a
|
||||
className={classes.container}
|
||||
href={getEtherScanLink(type, value, currentNetwork)}
|
||||
href={getEtherScanLink(type, value)}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
aria-label="Show details on Etherscan"
|
||||
|
@ -48,7 +45,4 @@ const EtherscanBtn = ({
|
|||
|
||||
const EtherscanBtnWithStyles = withStyles(styles)(EtherscanBtn)
|
||||
|
||||
export default connect<Object, Object, ?Function, ?Object>(
|
||||
(state) => ({ currentNetwork: networkSelector(state) }),
|
||||
null,
|
||||
)(EtherscanBtnWithStyles)
|
||||
export default EtherscanBtnWithStyles
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
// @flow
|
||||
import React from 'react'
|
||||
import { connect } from 'react-redux'
|
||||
import OpenInNew from '@material-ui/icons/OpenInNew'
|
||||
import { getEtherScanLink } from '~/logic/wallets/getWeb3'
|
||||
import { shortVersionOf } from '~/logic/wallets/ethAddresses'
|
||||
import { secondary } from '~/theme/variables'
|
||||
import { networkSelector } from '~/logic/wallets/store/selectors'
|
||||
|
||||
const openIconStyle = {
|
||||
height: '13px',
|
||||
|
@ -15,17 +13,13 @@ const openIconStyle = {
|
|||
type EtherscanLinkProps = {
|
||||
type: 'tx' | 'address',
|
||||
value: string,
|
||||
currentNetwork: string,
|
||||
}
|
||||
|
||||
const EtherscanLink = ({ type, value, currentNetwork }: EtherscanLinkProps) => (
|
||||
<a href={getEtherScanLink(type, value, currentNetwork)} target="_blank" rel="noopener noreferrer">
|
||||
const EtherscanLink = ({ type, value }: EtherscanLinkProps) => (
|
||||
<a href={getEtherScanLink(type, value)} target="_blank" rel="noopener noreferrer">
|
||||
{shortVersionOf(value, 4)}
|
||||
<OpenInNew style={openIconStyle} />
|
||||
</a>
|
||||
)
|
||||
|
||||
export default connect<Object, Object, ?Function, ?Object>(
|
||||
(state) => ({ currentNetwork: networkSelector(state) }),
|
||||
null,
|
||||
)(EtherscanLink)
|
||||
export default EtherscanLink
|
||||
|
|
|
@ -123,7 +123,7 @@ const UserDetails = ({
|
|||
{address}
|
||||
</Paragraph>
|
||||
{userAddress && (
|
||||
<Link className={classes.open} to={getEtherScanLink('address', userAddress, network)} target="_blank">
|
||||
<Link className={classes.open} to={getEtherScanLink('address', userAddress)} target="_blank">
|
||||
<OpenInNew style={openIconStyle} />
|
||||
</Link>
|
||||
)}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
// @flow
|
||||
import devConfig from './development'
|
||||
import { TX_SERVICE_HOST, RELAY_API_URL } from '~/config/names'
|
||||
|
||||
const devMainnetConfig = {
|
||||
...devConfig,
|
||||
[TX_SERVICE_HOST]: 'https://safe-transaction.mainnet.staging.gnosisdev.com/api/v1',
|
||||
[RELAY_API_URL]: 'https://safe-relay.gnosis.io/api/v1/',
|
||||
}
|
||||
|
||||
export default devMainnetConfig
|
|
@ -1,9 +1,14 @@
|
|||
// @flow
|
||||
import { ensureOnce } from '~/utils/singleton'
|
||||
import { ETHEREUM_NETWORK } from '~/logic/wallets/getWeb3'
|
||||
import { TX_SERVICE_HOST, SIGNATURES_VIA_METAMASK, RELAY_API_URL } from '~/config/names'
|
||||
import devConfig from './development'
|
||||
import testConfig from './testing'
|
||||
import stagingConfig from './staging'
|
||||
import prodConfig from './production'
|
||||
import mainnetDevConfig from './development-mainnet'
|
||||
import mainnetProdConfig from './production-mainnet'
|
||||
import mainnetStagingConfig from './staging-mainnet'
|
||||
|
||||
const configuration = () => {
|
||||
if (process.env.NODE_ENV === 'test') {
|
||||
|
@ -11,12 +16,18 @@ const configuration = () => {
|
|||
}
|
||||
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
return prodConfig
|
||||
if (process.env.REACT_APP_NETWORK === 'mainnet') {
|
||||
return process.env.REACT_APP_ENV === 'production' ? mainnetProdConfig : mainnetStagingConfig
|
||||
}
|
||||
|
||||
return devConfig
|
||||
return process.env.REACT_APP_ENV === 'production' ? prodConfig : stagingConfig
|
||||
}
|
||||
|
||||
return process.env.REACT_APP_NETWORK === 'mainnet' ? mainnetDevConfig : devConfig
|
||||
}
|
||||
|
||||
export const getNetwork = () => (process.env.REACT_APP_NETWORK === 'mainnet' ? ETHEREUM_NETWORK.MAINNET : ETHEREUM_NETWORK.RINKEBY)
|
||||
|
||||
const getConfig = ensureOnce(configuration)
|
||||
|
||||
export const getTxServiceHost = () => {
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
// @flow
|
||||
import prodConfig from './production'
|
||||
import { TX_SERVICE_HOST, RELAY_API_URL } from '~/config/names'
|
||||
|
||||
const prodMainnetConfig = {
|
||||
...prodConfig,
|
||||
[TX_SERVICE_HOST]: 'https://safe-transaction.mainnet.gnosis.io/api/v1',
|
||||
[RELAY_API_URL]: 'https://safe-relay.gnosis.io/api/v1/',
|
||||
}
|
||||
|
||||
export default prodMainnetConfig
|
|
@ -2,7 +2,7 @@
|
|||
import { TX_SERVICE_HOST, SIGNATURES_VIA_METAMASK, RELAY_API_URL } from '~/config/names'
|
||||
|
||||
const prodConfig = {
|
||||
[TX_SERVICE_HOST]: 'https://safe-transaction.staging.gnosisdev.com/api/v1/',
|
||||
[TX_SERVICE_HOST]: 'https://safe-transaction.rinkeby.gnosis.io/api/v1/',
|
||||
[SIGNATURES_VIA_METAMASK]: false,
|
||||
[RELAY_API_URL]: 'https://safe-relay.staging.gnosisdev.com/api/v1/',
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
// @flow
|
||||
import stagingConfig from './staging'
|
||||
import { TX_SERVICE_HOST, RELAY_API_URL } from '~/config/names'
|
||||
|
||||
const stagingMainnetConfig = {
|
||||
...stagingConfig,
|
||||
[TX_SERVICE_HOST]: 'https://safe-transaction.mainnet.staging.gnosisdev.com/api/v1',
|
||||
[RELAY_API_URL]: 'https://safe-relay.staging.gnosis.io/api/v1/',
|
||||
}
|
||||
|
||||
export default stagingMainnetConfig
|
|
@ -0,0 +1,10 @@
|
|||
// @flow
|
||||
import { TX_SERVICE_HOST, SIGNATURES_VIA_METAMASK, RELAY_API_URL } from '~/config/names'
|
||||
|
||||
const stagingConfig = {
|
||||
[TX_SERVICE_HOST]: 'https://safe-transaction.staging.gnosisdev.com/api/v1/',
|
||||
[SIGNATURES_VIA_METAMASK]: false,
|
||||
[RELAY_API_URL]: 'https://safe-relay.staging.gnosisdev.com/api/v1/',
|
||||
}
|
||||
|
||||
export default stagingConfig
|
|
@ -1,4 +1,7 @@
|
|||
// @flow
|
||||
import { getNetwork } from '~/config'
|
||||
import { capitalize } from '~/utils/css'
|
||||
|
||||
export const SUCCESS = 'success'
|
||||
export const ERROR = 'error'
|
||||
export const WARNING = 'warning'
|
||||
|
@ -65,8 +68,7 @@ export type Notifications = {
|
|||
|
||||
// Rinkeby version
|
||||
RINKEBY_VERSION_MSG: Notification,
|
||||
WRONG_NETWORK_RINKEBY_MSG: Notification,
|
||||
WRONG_NETWOEK_MAINNET_MSG: Notification,
|
||||
WRONG_NETWORK_MSG: Notification,
|
||||
}
|
||||
|
||||
export const NOTIFICATIONS: Notifications = {
|
||||
|
@ -210,15 +212,11 @@ export const NOTIFICATIONS: Notifications = {
|
|||
|
||||
// Network
|
||||
RINKEBY_VERSION_MSG: {
|
||||
message: "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: {
|
||||
message: 'Wrong network: Please use Rinkeby',
|
||||
options: { variant: WARNING, persist: true, preventDuplicate: true },
|
||||
},
|
||||
WRONG_NETWOEK_MAINNET_MSG: {
|
||||
message: 'Wrong network: Please use Mainnet',
|
||||
WRONG_NETWORK_MSG: {
|
||||
message: `Wrong network: Please use ${capitalize(getNetwork())}`,
|
||||
options: { variant: WARNING, persist: true, preventDuplicate: true },
|
||||
},
|
||||
}
|
||||
|
|
|
@ -2,12 +2,14 @@
|
|||
import Web3 from 'web3'
|
||||
import ENS from 'ethereum-ens'
|
||||
import type { ProviderProps } from '~/logic/wallets/store/model/provider'
|
||||
import { getNetwork } from '~/config/index'
|
||||
|
||||
export const ETHEREUM_NETWORK = {
|
||||
MAIN: 'MAIN',
|
||||
MAINNET: 'MAINNET',
|
||||
MORDEN: 'MORDEN',
|
||||
ROPSTEN: 'ROPSTEN',
|
||||
RINKEBY: 'RINKEBY',
|
||||
GOERLI: 'GOERLI',
|
||||
KOVAN: 'KOVAN',
|
||||
UNKNOWN: 'UNKNOWN',
|
||||
}
|
||||
|
@ -22,7 +24,7 @@ export const WALLET_PROVIDER = {
|
|||
|
||||
export const ETHEREUM_NETWORK_IDS = {
|
||||
// $FlowFixMe
|
||||
1: ETHEREUM_NETWORK.MAIN,
|
||||
1: ETHEREUM_NETWORK.MAINNET,
|
||||
// $FlowFixMe
|
||||
2: ETHEREUM_NETWORK.MORDEN,
|
||||
// $FlowFixMe
|
||||
|
@ -30,10 +32,17 @@ export const ETHEREUM_NETWORK_IDS = {
|
|||
// $FlowFixMe
|
||||
4: ETHEREUM_NETWORK.RINKEBY,
|
||||
// $FlowFixMe
|
||||
5: ETHEREUM_NETWORK.GOERLI,
|
||||
// $FlowFixMe
|
||||
42: ETHEREUM_NETWORK.KOVAN,
|
||||
}
|
||||
|
||||
export const getEtherScanLink = (type: 'address' | 'tx', value: string, network: string) => `https://${network === 'mainnet' ? '' : `${network}.`}etherscan.io/${type}/${value}`
|
||||
export const getEtherScanLink = (type: 'address' | 'tx', value: string) => {
|
||||
const network = getNetwork()
|
||||
return `https://${
|
||||
network.toLowerCase() === 'mainnet' ? '' : `${network.toLowerCase()}.`
|
||||
}etherscan.io/${type}/${value}`
|
||||
}
|
||||
|
||||
let web3
|
||||
export const getWeb3 = () => web3 || (window.web3 && new Web3(window.web3.currentProvider)) || (window.ethereum && new Web3(window.ethereum))
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// @flow
|
||||
import type { Dispatch as ReduxDispatch } from 'redux'
|
||||
import { ETHEREUM_NETWORK_IDS, ETHEREUM_NETWORK } from '~/logic/wallets/getWeb3'
|
||||
import { getNetwork } from '~/config'
|
||||
import type { ProviderProps } from '~/logic/wallets/store/model/provider'
|
||||
import { makeProvider } from '~/logic/wallets/store/model/provider'
|
||||
import { NOTIFICATIONS, showSnackbar } from '~/logic/notifications'
|
||||
|
@ -23,7 +24,6 @@ export const processProviderResponse = (dispatch: ReduxDispatch<*>, provider: Pr
|
|||
}
|
||||
|
||||
const handleProviderNotification = (
|
||||
dispatch: ReduxDispatch<*>,
|
||||
provider: ProviderProps,
|
||||
enqueueSnackbar: Function,
|
||||
closeSnackbar: Function,
|
||||
|
@ -35,11 +35,13 @@ const handleProviderNotification = (
|
|||
return
|
||||
}
|
||||
|
||||
if (ETHEREUM_NETWORK_IDS[network] !== ETHEREUM_NETWORK.RINKEBY) {
|
||||
showSnackbar(NOTIFICATIONS.WRONG_NETWORK_RINKEBY_MSG, enqueueSnackbar, closeSnackbar)
|
||||
if (ETHEREUM_NETWORK_IDS[network] !== getNetwork()) {
|
||||
showSnackbar(NOTIFICATIONS.WRONG_NETWORK_MSG, enqueueSnackbar, closeSnackbar)
|
||||
return
|
||||
}
|
||||
if (ETHEREUM_NETWORK.RINKEBY === getNetwork()) {
|
||||
showSnackbar(NOTIFICATIONS.RINKEBY_VERSION_MSG, enqueueSnackbar, closeSnackbar)
|
||||
}
|
||||
|
||||
if (available) {
|
||||
// NOTE:
|
||||
|
@ -56,6 +58,6 @@ const handleProviderNotification = (
|
|||
export default (provider: ProviderProps, enqueueSnackbar: Function, closeSnackbar: Function) => (
|
||||
dispatch: ReduxDispatch<*>,
|
||||
) => {
|
||||
handleProviderNotification(dispatch, provider, enqueueSnackbar, closeSnackbar)
|
||||
handleProviderNotification(provider, enqueueSnackbar, closeSnackbar)
|
||||
processProviderResponse(dispatch, provider)
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ const styles = {
|
|||
}
|
||||
|
||||
const Opening = ({
|
||||
classes, name = 'Safe creation process', tx, network,
|
||||
classes, name = 'Safe creation process', tx,
|
||||
}: Props) => (
|
||||
<Page align="center">
|
||||
<Paragraph color="primary" size="xxl" weight="bold" align="center">
|
||||
|
@ -70,7 +70,7 @@ const Opening = ({
|
|||
Follow progress on
|
||||
{' '}
|
||||
<a
|
||||
href={getEtherScanLink('tx', tx, network)}
|
||||
href={getEtherScanLink('tx', tx)}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className={classes.etherscan}
|
||||
|
|
|
@ -106,7 +106,7 @@ class Layout extends React.Component<Props, State> {
|
|||
}
|
||||
|
||||
const { address, ethBalance, name } = safe
|
||||
const etherScanLink = getEtherScanLink('address', address, network)
|
||||
const etherScanLink = getEtherScanLink('address', address)
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -182,6 +182,7 @@ class Layout extends React.Component<Props, State> {
|
|||
fetchTransactions={fetchTransactions}
|
||||
safeAddress={address}
|
||||
userAddress={userAddress}
|
||||
currentNetwork={network}
|
||||
granted={granted}
|
||||
createTransaction={createTransaction}
|
||||
processTransaction={processTransaction}
|
||||
|
|
|
@ -27,7 +27,6 @@ type Props = {
|
|||
safeName: string,
|
||||
owners: List<Owner>,
|
||||
threshold: number,
|
||||
network: string,
|
||||
addSafeOwner: Function,
|
||||
createTransaction: Function,
|
||||
enqueueSnackbar: Function,
|
||||
|
@ -70,7 +69,6 @@ const AddOwner = ({
|
|||
safeName,
|
||||
owners,
|
||||
threshold,
|
||||
network,
|
||||
createTransaction,
|
||||
addSafeOwner,
|
||||
enqueueSnackbar,
|
||||
|
@ -147,7 +145,6 @@ const AddOwner = ({
|
|||
onClose={onClose}
|
||||
safeName={safeName}
|
||||
owners={owners}
|
||||
network={network}
|
||||
values={values}
|
||||
onClickBack={onClickBack}
|
||||
onSubmit={onAddOwner}
|
||||
|
|
|
@ -31,14 +31,13 @@ type Props = {
|
|||
classes: Object,
|
||||
safeName: string,
|
||||
owners: List<Owner>,
|
||||
network: string,
|
||||
values: Object,
|
||||
onClickBack: Function,
|
||||
onSubmit: Function,
|
||||
}
|
||||
|
||||
const ReviewAddOwner = ({
|
||||
classes, onClose, safeName, owners, network, values, onClickBack, onSubmit,
|
||||
classes, onClose, safeName, owners, values, onClickBack, onSubmit,
|
||||
}: Props) => {
|
||||
const handleSubmit = () => {
|
||||
onSubmit()
|
||||
|
@ -80,7 +79,6 @@ const ReviewAddOwner = ({
|
|||
{values.threshold}
|
||||
{' '}
|
||||
out of
|
||||
{' '}
|
||||
{owners.size + 1}
|
||||
{' '}
|
||||
owner(s)
|
||||
|
@ -112,7 +110,7 @@ const ReviewAddOwner = ({
|
|||
<Paragraph size="md" color="disabled" noMargin>
|
||||
{owner.address}
|
||||
</Paragraph>
|
||||
<Link className={classes.open} to={getEtherScanLink('address', owner.address, network)} target="_blank">
|
||||
<Link className={classes.open} to={getEtherScanLink('address', owner.address)} target="_blank">
|
||||
<OpenInNew style={openIconStyle} />
|
||||
</Link>
|
||||
</Block>
|
||||
|
@ -141,7 +139,11 @@ const ReviewAddOwner = ({
|
|||
<Paragraph size="md" color="disabled" noMargin>
|
||||
{values.ownerAddress}
|
||||
</Paragraph>
|
||||
<Link className={classes.open} to={getEtherScanLink('address', values.ownerAddress, network)} target="_blank">
|
||||
<Link
|
||||
className={classes.open}
|
||||
to={getEtherScanLink('address', values.ownerAddress)}
|
||||
target="_blank"
|
||||
>
|
||||
<OpenInNew style={openIconStyle} />
|
||||
</Link>
|
||||
</Block>
|
||||
|
|
|
@ -37,7 +37,6 @@ type Props = {
|
|||
isOpen: boolean,
|
||||
safeAddress: string,
|
||||
ownerAddress: string,
|
||||
network: string,
|
||||
selectedOwnerName: string,
|
||||
editSafeOwner: Function,
|
||||
enqueueSnackbar: Function,
|
||||
|
@ -52,7 +51,6 @@ const EditOwnerComponent = ({
|
|||
ownerAddress,
|
||||
selectedOwnerName,
|
||||
editSafeOwner,
|
||||
network,
|
||||
enqueueSnackbar,
|
||||
closeSnackbar,
|
||||
}: Props) => {
|
||||
|
@ -105,7 +103,7 @@ const EditOwnerComponent = ({
|
|||
<Paragraph style={{ marginLeft: 10 }} size="md" color="disabled" noMargin>
|
||||
{ownerAddress}
|
||||
</Paragraph>
|
||||
<Link className={classes.open} to={getEtherScanLink('address', ownerAddress, network)} target="_blank">
|
||||
<Link className={classes.open} to={getEtherScanLink('address', ownerAddress)} target="_blank">
|
||||
<OpenInNew style={openIconStyle} />
|
||||
</Link>
|
||||
</Block>
|
||||
|
|
|
@ -29,7 +29,6 @@ type Props = {
|
|||
ownerName: string,
|
||||
owners: List<Owner>,
|
||||
threshold: number,
|
||||
network: string,
|
||||
createTransaction: Function,
|
||||
removeSafeOwner: Function,
|
||||
enqueueSnackbar: Function,
|
||||
|
@ -84,7 +83,6 @@ const RemoveOwner = ({
|
|||
ownerName,
|
||||
owners,
|
||||
threshold,
|
||||
network,
|
||||
createTransaction,
|
||||
removeSafeOwner,
|
||||
enqueueSnackbar,
|
||||
|
@ -148,7 +146,6 @@ const RemoveOwner = ({
|
|||
onClose={onClose}
|
||||
ownerAddress={ownerAddress}
|
||||
ownerName={ownerName}
|
||||
network={network}
|
||||
onSubmit={ownerSubmitted}
|
||||
/>
|
||||
)}
|
||||
|
@ -166,7 +163,6 @@ const RemoveOwner = ({
|
|||
onClose={onClose}
|
||||
safeName={safeName}
|
||||
owners={owners}
|
||||
network={network}
|
||||
values={values}
|
||||
ownerAddress={ownerAddress}
|
||||
ownerName={ownerName}
|
||||
|
|
|
@ -29,12 +29,11 @@ type Props = {
|
|||
classes: Object,
|
||||
ownerAddress: string,
|
||||
ownerName: string,
|
||||
network: string,
|
||||
onSubmit: Function,
|
||||
}
|
||||
|
||||
const CheckOwner = ({
|
||||
classes, onClose, ownerAddress, ownerName, network, onSubmit,
|
||||
classes, onClose, ownerAddress, ownerName, onSubmit,
|
||||
}: Props) => {
|
||||
const handleSubmit = (values) => {
|
||||
onSubmit(values)
|
||||
|
@ -69,7 +68,7 @@ const CheckOwner = ({
|
|||
<Paragraph size="md" color="disabled" noMargin>
|
||||
{ownerAddress}
|
||||
</Paragraph>
|
||||
<Link className={classes.open} to={getEtherScanLink('address', ownerAddress, network)} target="_blank">
|
||||
<Link className={classes.open} to={getEtherScanLink('address', ownerAddress)} target="_blank">
|
||||
<OpenInNew style={openIconStyle} />
|
||||
</Link>
|
||||
</Block>
|
||||
|
|
|
@ -31,7 +31,6 @@ type Props = {
|
|||
classes: Object,
|
||||
safeName: string,
|
||||
owners: List<Owner>,
|
||||
network: string,
|
||||
values: Object,
|
||||
ownerAddress: string,
|
||||
ownerName: string,
|
||||
|
@ -44,7 +43,6 @@ const ReviewRemoveOwner = ({
|
|||
onClose,
|
||||
safeName,
|
||||
owners,
|
||||
network,
|
||||
values,
|
||||
ownerAddress,
|
||||
ownerName,
|
||||
|
@ -126,7 +124,7 @@ Safe owner(s)
|
|||
</Paragraph>
|
||||
<Link
|
||||
className={classes.open}
|
||||
to={getEtherScanLink('address', owner.address, network)}
|
||||
to={getEtherScanLink('address', owner.address)}
|
||||
target="_blank"
|
||||
>
|
||||
<OpenInNew style={openIconStyle} />
|
||||
|
@ -160,7 +158,7 @@ Safe owner(s)
|
|||
</Paragraph>
|
||||
<Link
|
||||
className={classes.open}
|
||||
to={getEtherScanLink('address', ownerAddress, network)}
|
||||
to={getEtherScanLink('address', ownerAddress)}
|
||||
target="_blank"
|
||||
>
|
||||
<OpenInNew style={openIconStyle} />
|
||||
|
|
|
@ -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 Owner } from '~/routes/safe/store/models/owner'
|
||||
import { TX_NOTIFICATION_TYPES } from '~/logic/safe/transactions'
|
||||
import { getGnosisSafeInstanceAt, SENTINEL_ADDRESS } from '~/logic/contracts/safeContracts'
|
||||
import OwnerForm from './screens/OwnerForm'
|
||||
|
@ -26,7 +27,6 @@ type Props = {
|
|||
ownerAddress: string,
|
||||
ownerName: string,
|
||||
owners: List<Owner>,
|
||||
network: string,
|
||||
threshold: string,
|
||||
createTransaction: Function,
|
||||
replaceSafeOwner: Function,
|
||||
|
@ -83,7 +83,6 @@ const ReplaceOwner = ({
|
|||
ownerAddress,
|
||||
ownerName,
|
||||
owners,
|
||||
network,
|
||||
threshold,
|
||||
createTransaction,
|
||||
replaceSafeOwner,
|
||||
|
@ -142,7 +141,6 @@ const ReplaceOwner = ({
|
|||
ownerAddress={ownerAddress}
|
||||
ownerName={ownerName}
|
||||
owners={owners}
|
||||
network={network}
|
||||
onSubmit={ownerSubmitted}
|
||||
/>
|
||||
)}
|
||||
|
@ -151,7 +149,6 @@ const ReplaceOwner = ({
|
|||
onClose={onClose}
|
||||
safeName={safeName}
|
||||
owners={owners}
|
||||
network={network}
|
||||
values={values}
|
||||
ownerAddress={ownerAddress}
|
||||
ownerName={ownerName}
|
||||
|
|
|
@ -46,13 +46,12 @@ type Props = {
|
|||
classes: Object,
|
||||
ownerAddress: string,
|
||||
ownerName: string,
|
||||
network: string,
|
||||
onSubmit: Function,
|
||||
owners: List<Owner>,
|
||||
}
|
||||
|
||||
const OwnerForm = ({
|
||||
classes, onClose, ownerAddress, ownerName, network, onSubmit, owners,
|
||||
classes, onClose, ownerAddress, ownerName, onSubmit, owners,
|
||||
}: Props) => {
|
||||
const handleSubmit = (values) => {
|
||||
onSubmit(values)
|
||||
|
@ -102,7 +101,7 @@ const OwnerForm = ({
|
|||
</Paragraph>
|
||||
<Link
|
||||
className={classes.open}
|
||||
to={getEtherScanLink('address', ownerAddress, network)}
|
||||
to={getEtherScanLink('address', ownerAddress)}
|
||||
target="_blank"
|
||||
>
|
||||
<OpenInNew style={openIconStyle} />
|
||||
|
|
|
@ -31,7 +31,6 @@ type Props = {
|
|||
classes: Object,
|
||||
safeName: string,
|
||||
owners: List<Owner>,
|
||||
network: string,
|
||||
values: Object,
|
||||
ownerAddress: string,
|
||||
ownerName: string,
|
||||
|
@ -45,7 +44,6 @@ const ReviewRemoveOwner = ({
|
|||
onClose,
|
||||
safeName,
|
||||
owners,
|
||||
network,
|
||||
values,
|
||||
ownerAddress,
|
||||
ownerName,
|
||||
|
@ -129,7 +127,7 @@ const ReviewRemoveOwner = ({
|
|||
</Paragraph>
|
||||
<Link
|
||||
className={classes.open}
|
||||
to={getEtherScanLink('address', owner.address, network)}
|
||||
to={getEtherScanLink('address', owner.address)}
|
||||
target="_blank"
|
||||
>
|
||||
<OpenInNew style={openIconStyle} />
|
||||
|
@ -161,7 +159,7 @@ const ReviewRemoveOwner = ({
|
|||
<Paragraph size="md" color="disabled" noMargin>
|
||||
{ownerAddress}
|
||||
</Paragraph>
|
||||
<Link className={classes.open} to={getEtherScanLink('address', ownerAddress, network)} target="_blank">
|
||||
<Link className={classes.open} to={getEtherScanLink('address', ownerAddress)} target="_blank">
|
||||
<OpenInNew style={openIconStyle} />
|
||||
</Link>
|
||||
</Block>
|
||||
|
@ -187,7 +185,7 @@ const ReviewRemoveOwner = ({
|
|||
<Paragraph size="md" color="disabled" noMargin>
|
||||
{values.ownerAddress}
|
||||
</Paragraph>
|
||||
<Link className={classes.open} to={getEtherScanLink('address', values.ownerAddress, network)} target="_blank">
|
||||
<Link className={classes.open} to={getEtherScanLink('address', values.ownerAddress)} target="_blank">
|
||||
<OpenInNew style={openIconStyle} />
|
||||
</Link>
|
||||
</Block>
|
||||
|
|
|
@ -219,7 +219,6 @@ class ManageOwners extends React.Component<Props, State> {
|
|||
safeName={safeName}
|
||||
owners={owners}
|
||||
threshold={threshold}
|
||||
network={network}
|
||||
userAddress={userAddress}
|
||||
createTransaction={createTransaction}
|
||||
addSafeOwner={addSafeOwner}
|
||||
|
@ -233,7 +232,6 @@ class ManageOwners extends React.Component<Props, State> {
|
|||
ownerName={selectedOwnerName}
|
||||
owners={owners}
|
||||
threshold={threshold}
|
||||
network={network}
|
||||
userAddress={userAddress}
|
||||
createTransaction={createTransaction}
|
||||
removeSafeOwner={removeSafeOwner}
|
||||
|
@ -259,7 +257,6 @@ class ManageOwners extends React.Component<Props, State> {
|
|||
ownerAddress={selectedOwnerAddress}
|
||||
selectedOwnerName={selectedOwnerName}
|
||||
owners={owners}
|
||||
network={network}
|
||||
editSafeOwner={editSafeOwner}
|
||||
/>
|
||||
</>
|
||||
|
|
|
@ -41,7 +41,7 @@ const OwnerComponent = withStyles(styles)(({ owner, classes, isExecutor }: Owner
|
|||
<ListItemText
|
||||
primary={owner.name}
|
||||
secondary={(
|
||||
<a href={getEtherScanLink('address', owner.address, 'rinkeby')} target="_blank" rel="noopener noreferrer">
|
||||
<a href={getEtherScanLink('address', owner.address)} target="_blank" rel="noopener noreferrer">
|
||||
{shortVersionOf(owner.address, 4)}
|
||||
{' '}
|
||||
<OpenInNew style={openIconStyle} />
|
||||
|
|
|
@ -74,7 +74,7 @@ const ExpandedTx = ({
|
|||
<Paragraph noMargin>
|
||||
<Bold>TX hash: </Bold>
|
||||
{tx.executionTxHash ? (
|
||||
<a href={getEtherScanLink('tx', tx.executionTxHash, 'rinkeby')} target="_blank" rel="noopener noreferrer">
|
||||
<a href={getEtherScanLink('tx', tx.executionTxHash)} target="_blank" rel="noopener noreferrer">
|
||||
{shortVersionOf(tx.executionTxHash, 4)}
|
||||
<OpenInNew style={openIconStyle} />
|
||||
</a>
|
||||
|
|
|
@ -55,11 +55,11 @@ const TxsTable = ({
|
|||
const [expandedTx, setExpandedTx] = useState<string | null>(null)
|
||||
|
||||
const handleTxExpand = (safeTxHash) => {
|
||||
setExpandedTx(prevTx => (prevTx === safeTxHash ? null : safeTxHash))
|
||||
setExpandedTx((prevTx) => (prevTx === safeTxHash ? null : safeTxHash))
|
||||
}
|
||||
|
||||
const columns = generateColumns()
|
||||
const autoColumns = columns.filter(c => !c.custom)
|
||||
const autoColumns = columns.filter((c) => !c.custom)
|
||||
const filteredData = getTxTableData(transactions)
|
||||
|
||||
return (
|
||||
|
@ -124,8 +124,7 @@ const TxsTable = ({
|
|||
</TableCell>
|
||||
</TableRow>
|
||||
</React.Fragment>
|
||||
))
|
||||
}
|
||||
))}
|
||||
</Table>
|
||||
</Block>
|
||||
)
|
||||
|
|
|
@ -16,6 +16,7 @@ type Props = {
|
|||
granted: boolean,
|
||||
createTransaction: Function,
|
||||
processTransaction: Function,
|
||||
currentNetwork: string,
|
||||
}
|
||||
|
||||
const Transactions = ({
|
||||
|
@ -28,6 +29,7 @@ const Transactions = ({
|
|||
createTransaction,
|
||||
processTransaction,
|
||||
fetchTransactions,
|
||||
currentNetwork,
|
||||
}: Props) => {
|
||||
useEffect(() => {
|
||||
fetchTransactions(safeAddress)
|
||||
|
@ -43,6 +45,7 @@ const Transactions = ({
|
|||
threshold={threshold}
|
||||
owners={owners}
|
||||
userAddress={userAddress}
|
||||
currentNetwork={currentNetwork}
|
||||
granted={granted}
|
||||
safeAddress={safeAddress}
|
||||
createTransaction={createTransaction}
|
||||
|
|
Loading…
Reference in New Issue