createTransaction action
This commit is contained in:
parent
ad183dfabb
commit
c3fba307c2
|
@ -12,9 +12,10 @@ import Layout from './component/Layout'
|
||||||
import actions, { type Actions } from './actions'
|
import actions, { type Actions } from './actions'
|
||||||
import selector, { type SelectorProps } from './selector'
|
import selector, { type SelectorProps } from './selector'
|
||||||
|
|
||||||
type Props = Actions & SelectorProps & {
|
type Props = Actions &
|
||||||
openSnackbar: (message: string, variant: Variant) => void,
|
SelectorProps & {
|
||||||
}
|
openSnackbar: (message: string, variant: Variant) => void,
|
||||||
|
}
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
hasError: boolean,
|
hasError: boolean,
|
||||||
|
@ -67,13 +68,15 @@ class HeaderComponent extends React.PureComponent<Props, State> {
|
||||||
return <ConnectDetails onConnect={this.onConnect} />
|
return <ConnectDetails onConnect={this.onConnect} />
|
||||||
}
|
}
|
||||||
|
|
||||||
return (<UserDetails
|
return (
|
||||||
provider={provider}
|
<UserDetails
|
||||||
network={network}
|
provider={provider}
|
||||||
userAddress={userAddress}
|
network={network}
|
||||||
connected={available}
|
userAddress={userAddress}
|
||||||
onDisconnect={this.onDisconnect}
|
connected={available}
|
||||||
/>)
|
onDisconnect={this.onDisconnect}
|
||||||
|
/>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -84,14 +87,13 @@ class HeaderComponent extends React.PureComponent<Props, State> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Header = connect(selector, actions)(HeaderComponent)
|
const Header = connect(
|
||||||
|
selector,
|
||||||
|
actions,
|
||||||
|
)(HeaderComponent)
|
||||||
|
|
||||||
const HeaderSnack = () => (
|
const HeaderSnack = () => (
|
||||||
<SharedSnackbarConsumer>
|
<SharedSnackbarConsumer>{({ openSnackbar }) => <Header openSnackbar={openSnackbar} />}</SharedSnackbarConsumer>
|
||||||
{({ openSnackbar }) => (
|
|
||||||
<Header openSnackbar={openSnackbar} />
|
|
||||||
)}
|
|
||||||
</SharedSnackbarConsumer>
|
|
||||||
)
|
)
|
||||||
|
|
||||||
export default HeaderSnack
|
export default HeaderSnack
|
||||||
|
|
|
@ -19,6 +19,7 @@ type Props = {
|
||||||
ethBalance: string,
|
ethBalance: string,
|
||||||
tokens: List<Token>,
|
tokens: List<Token>,
|
||||||
selectedToken: string,
|
selectedToken: string,
|
||||||
|
createTransaction: Function,
|
||||||
}
|
}
|
||||||
type ActiveScreen = 'chooseTxType' | 'sendFunds' | 'reviewTx'
|
type ActiveScreen = 'chooseTxType' | 'sendFunds' | 'reviewTx'
|
||||||
|
|
||||||
|
@ -47,6 +48,7 @@ const Send = ({
|
||||||
ethBalance,
|
ethBalance,
|
||||||
tokens,
|
tokens,
|
||||||
selectedToken,
|
selectedToken,
|
||||||
|
createTransaction,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const [activeScreen, setActiveScreen] = useState<ActiveScreen>('sendFunds')
|
const [activeScreen, setActiveScreen] = useState<ActiveScreen>('sendFunds')
|
||||||
const [tx, setTx] = useState<TxStateType>({})
|
const [tx, setTx] = useState<TxStateType>({})
|
||||||
|
@ -98,6 +100,7 @@ const Send = ({
|
||||||
safeName={safeName}
|
safeName={safeName}
|
||||||
ethBalance={ethBalance}
|
ethBalance={ethBalance}
|
||||||
onClickBack={onClickBack}
|
onClickBack={onClickBack}
|
||||||
|
createTransaction={createTransaction}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import OpenInNew from '@material-ui/icons/OpenInNew'
|
import OpenInNew from '@material-ui/icons/OpenInNew'
|
||||||
import { withStyles } from '@material-ui/core/styles'
|
import { withStyles } from '@material-ui/core/styles'
|
||||||
|
import { SharedSnackbarConsumer } from '~/components/SharedSnackBar/Context'
|
||||||
import Close from '@material-ui/icons/Close'
|
import Close from '@material-ui/icons/Close'
|
||||||
import IconButton from '@material-ui/core/IconButton'
|
import IconButton from '@material-ui/core/IconButton'
|
||||||
import Paragraph from '~/components/layout/Paragraph'
|
import Paragraph from '~/components/layout/Paragraph'
|
||||||
|
@ -19,7 +20,6 @@ import { setImageToPlaceholder } from '~/routes/safe/components/Balances/utils'
|
||||||
import ArrowDown from '../assets/arrow-down.svg'
|
import ArrowDown from '../assets/arrow-down.svg'
|
||||||
import { secondary } from '~/theme/variables'
|
import { secondary } from '~/theme/variables'
|
||||||
import { styles } from './style'
|
import { styles } from './style'
|
||||||
import { createTransaction } from '~/logic/safe/transactions'
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onClose: () => void,
|
onClose: () => void,
|
||||||
|
@ -30,6 +30,7 @@ type Props = {
|
||||||
onClickBack: Function,
|
onClickBack: Function,
|
||||||
ethBalance: string,
|
ethBalance: string,
|
||||||
tx: Object,
|
tx: Object,
|
||||||
|
createTransaction: Function,
|
||||||
}
|
}
|
||||||
|
|
||||||
const openIconStyle = {
|
const openIconStyle = {
|
||||||
|
@ -38,81 +39,98 @@ const openIconStyle = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const ReviewTx = ({
|
const ReviewTx = ({
|
||||||
onClose, classes, safeAddress, etherScanLink, safeName, ethBalance, tx, onClickBack,
|
onClose,
|
||||||
|
classes,
|
||||||
|
safeAddress,
|
||||||
|
etherScanLink,
|
||||||
|
safeName,
|
||||||
|
ethBalance,
|
||||||
|
tx,
|
||||||
|
onClickBack,
|
||||||
|
createTransaction,
|
||||||
}: Props) => (
|
}: Props) => (
|
||||||
<React.Fragment>
|
<SharedSnackbarConsumer>
|
||||||
<Row align="center" grow className={classes.heading}>
|
{({ openSnackbar }) => (
|
||||||
<Paragraph weight="bolder" className={classes.headingText} noMargin>
|
<React.Fragment>
|
||||||
Send Funds
|
<Row align="center" grow className={classes.heading}>
|
||||||
</Paragraph>
|
<Paragraph weight="bolder" className={classes.headingText} noMargin>
|
||||||
<Paragraph className={classes.annotation}>2 of 2</Paragraph>
|
Send Funds
|
||||||
<IconButton onClick={onClose} disableRipple>
|
|
||||||
<Close className={classes.closeIcon} />
|
|
||||||
</IconButton>
|
|
||||||
</Row>
|
|
||||||
<Hairline />
|
|
||||||
<Block className={classes.container}>
|
|
||||||
<SafeInfo safeAddress={safeAddress} etherScanLink={etherScanLink} safeName={safeName} ethBalance={ethBalance} />
|
|
||||||
<Row margin="md">
|
|
||||||
<Col xs={1}>
|
|
||||||
<img src={ArrowDown} alt="Arrow Down" style={{ marginLeft: '8px' }} />
|
|
||||||
</Col>
|
|
||||||
<Col xs={11} center="xs" layout="column">
|
|
||||||
<Hairline />
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
<Row margin="xs">
|
|
||||||
<Paragraph size="md" color="disabled" style={{ letterSpacing: '-0.5px' }} noMargin>
|
|
||||||
Recipient
|
|
||||||
</Paragraph>
|
|
||||||
</Row>
|
|
||||||
<Row margin="md" align="center">
|
|
||||||
<Col xs={1}>
|
|
||||||
<Identicon address={tx.recipientAddress} diameter={32} />
|
|
||||||
</Col>
|
|
||||||
<Col xs={11} layout="column">
|
|
||||||
<Paragraph weight="bolder" onClick={copyToClipboard} noMargin>
|
|
||||||
{tx.recipientAddress}
|
|
||||||
<Link to={etherScanLink} target="_blank">
|
|
||||||
<OpenInNew style={openIconStyle} />
|
|
||||||
</Link>
|
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
</Col>
|
<Paragraph className={classes.annotation}>2 of 2</Paragraph>
|
||||||
</Row>
|
<IconButton onClick={onClose} disableRipple>
|
||||||
<Row margin="xs">
|
<Close className={classes.closeIcon} />
|
||||||
<Paragraph size="md" color="disabled" style={{ letterSpacing: '-0.5px' }} noMargin>
|
</IconButton>
|
||||||
Amount
|
</Row>
|
||||||
</Paragraph>
|
<Hairline />
|
||||||
</Row>
|
<Block className={classes.container}>
|
||||||
<Row margin="md" align="center">
|
<SafeInfo
|
||||||
<Img src={tx.token.logoUri} height={28} alt={tx.token.name} onError={setImageToPlaceholder} />
|
safeAddress={safeAddress}
|
||||||
<Paragraph size="md" noMargin>
|
etherScanLink={etherScanLink}
|
||||||
{tx.amount}
|
safeName={safeName}
|
||||||
{' '}
|
ethBalance={ethBalance}
|
||||||
{tx.token.symbol}
|
/>
|
||||||
</Paragraph>
|
<Row margin="md">
|
||||||
</Row>
|
<Col xs={1}>
|
||||||
</Block>
|
<img src={ArrowDown} alt="Arrow Down" style={{ marginLeft: '8px' }} />
|
||||||
<Hairline style={{ position: 'absolute', bottom: 85 }} />
|
</Col>
|
||||||
<Row align="center" className={classes.buttonRow}>
|
<Col xs={11} center="xs" layout="column">
|
||||||
<Button className={classes.button} minWidth={140} onClick={onClickBack}>
|
<Hairline />
|
||||||
Back
|
</Col>
|
||||||
</Button>
|
</Row>
|
||||||
<Button
|
<Row margin="xs">
|
||||||
type="submit"
|
<Paragraph size="md" color="disabled" style={{ letterSpacing: '-0.5px' }} noMargin>
|
||||||
className={classes.button}
|
Recipient
|
||||||
onClick={async () => {
|
</Paragraph>
|
||||||
await createTransaction(safeAddress, tx.recipientAddress, tx.amount, tx.token)
|
</Row>
|
||||||
onClose()
|
<Row margin="md" align="center">
|
||||||
}}
|
<Col xs={1}>
|
||||||
variant="contained"
|
<Identicon address={tx.recipientAddress} diameter={32} />
|
||||||
minWidth={140}
|
</Col>
|
||||||
color="primary"
|
<Col xs={11} layout="column">
|
||||||
>
|
<Paragraph weight="bolder" onClick={copyToClipboard} noMargin>
|
||||||
SUBMIT
|
{tx.recipientAddress}
|
||||||
</Button>
|
<Link to={etherScanLink} target="_blank">
|
||||||
</Row>
|
<OpenInNew style={openIconStyle} />
|
||||||
</React.Fragment>
|
</Link>
|
||||||
|
</Paragraph>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row margin="xs">
|
||||||
|
<Paragraph size="md" color="disabled" style={{ letterSpacing: '-0.5px' }} noMargin>
|
||||||
|
Amount
|
||||||
|
</Paragraph>
|
||||||
|
</Row>
|
||||||
|
<Row margin="md" align="center">
|
||||||
|
<Img src={tx.token.logoUri} height={28} alt={tx.token.name} onError={setImageToPlaceholder} />
|
||||||
|
<Paragraph size="md" noMargin>
|
||||||
|
{tx.amount}
|
||||||
|
{' '}
|
||||||
|
{tx.token.symbol}
|
||||||
|
</Paragraph>
|
||||||
|
</Row>
|
||||||
|
</Block>
|
||||||
|
<Hairline style={{ position: 'absolute', bottom: 85 }} />
|
||||||
|
<Row align="center" className={classes.buttonRow}>
|
||||||
|
<Button className={classes.button} minWidth={140} onClick={onClickBack}>
|
||||||
|
Back
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
className={classes.button}
|
||||||
|
onClick={() => {
|
||||||
|
createTransaction(safeAddress, tx.recipientAddress, tx.amount, tx.token, openSnackbar)
|
||||||
|
onClose()
|
||||||
|
}}
|
||||||
|
variant="contained"
|
||||||
|
minWidth={140}
|
||||||
|
color="primary"
|
||||||
|
>
|
||||||
|
SUBMIT
|
||||||
|
</Button>
|
||||||
|
</Row>
|
||||||
|
</React.Fragment>
|
||||||
|
)}
|
||||||
|
</SharedSnackbarConsumer>
|
||||||
)
|
)
|
||||||
|
|
||||||
export default withStyles(styles)(ReviewTx)
|
export default withStyles(styles)(ReviewTx)
|
||||||
|
|
|
@ -41,6 +41,7 @@ type Props = {
|
||||||
safeName: string,
|
safeName: string,
|
||||||
etherScanLink: string,
|
etherScanLink: string,
|
||||||
ethBalance: string,
|
ethBalance: string,
|
||||||
|
createTransaction: Function,
|
||||||
}
|
}
|
||||||
|
|
||||||
type Action = 'Token' | 'Send' | 'Receive'
|
type Action = 'Token' | 'Send' | 'Receive'
|
||||||
|
@ -93,7 +94,15 @@ class Balances extends React.Component<Props, State> {
|
||||||
hideZero, showToken, showReceive, sendFunds,
|
hideZero, showToken, showReceive, sendFunds,
|
||||||
} = this.state
|
} = this.state
|
||||||
const {
|
const {
|
||||||
classes, granted, tokens, safeAddress, activeTokens, safeName, etherScanLink, ethBalance,
|
classes,
|
||||||
|
granted,
|
||||||
|
tokens,
|
||||||
|
safeAddress,
|
||||||
|
activeTokens,
|
||||||
|
safeName,
|
||||||
|
etherScanLink,
|
||||||
|
ethBalance,
|
||||||
|
createTransaction,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
const columns = generateColumns()
|
const columns = generateColumns()
|
||||||
|
@ -190,6 +199,7 @@ class Balances extends React.Component<Props, State> {
|
||||||
ethBalance={ethBalance}
|
ethBalance={ethBalance}
|
||||||
tokens={activeTokens}
|
tokens={activeTokens}
|
||||||
selectedToken={sendFunds.selectedToken}
|
selectedToken={sendFunds.selectedToken}
|
||||||
|
createTransaction={createTransaction}
|
||||||
/>
|
/>
|
||||||
<Modal
|
<Modal
|
||||||
title="Receive Tokens"
|
title="Receive Tokens"
|
||||||
|
|
|
@ -23,6 +23,7 @@ import Balances from './Balances'
|
||||||
type Props = SelectorProps & {
|
type Props = SelectorProps & {
|
||||||
classes: Object,
|
classes: Object,
|
||||||
granted: boolean,
|
granted: boolean,
|
||||||
|
createTransaction: Function,
|
||||||
}
|
}
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
|
@ -88,7 +89,7 @@ class Layout extends React.Component<Props, State> {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
safe, provider, network, classes, granted, tokens, activeTokens,
|
safe, provider, network, classes, granted, tokens, activeTokens, createTransaction,
|
||||||
} = this.props
|
} = this.props
|
||||||
const { tabIndex } = this.state
|
const { tabIndex } = this.state
|
||||||
|
|
||||||
|
@ -137,6 +138,7 @@ class Layout extends React.Component<Props, State> {
|
||||||
safeAddress={address}
|
safeAddress={address}
|
||||||
safeName={name}
|
safeName={name}
|
||||||
etherScanLink={etherScanLink}
|
etherScanLink={etherScanLink}
|
||||||
|
createTransaction={createTransaction}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
|
|
|
@ -14,7 +14,7 @@ type FormProps = {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
symbol: string
|
symbol: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
const spinnerStyle = {
|
const spinnerStyle = {
|
||||||
|
@ -25,14 +25,14 @@ const ReviewTx = ({ symbol }: Props) => (controls: React$Node, { values, submitt
|
||||||
<OpenPaper controls={controls}>
|
<OpenPaper controls={controls}>
|
||||||
<Heading tag="h2">Review the move token funds</Heading>
|
<Heading tag="h2">Review the move token funds</Heading>
|
||||||
<Paragraph align="left">
|
<Paragraph align="left">
|
||||||
<Bold>Destination: </Bold> {values[TKN_DESTINATION_PARAM]}
|
<Bold>Destination: </Bold>
|
||||||
|
{' '}
|
||||||
|
{values[TKN_DESTINATION_PARAM]}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
<Paragraph align="left">
|
<Paragraph align="left">
|
||||||
<Bold>{`Amount to transfer: ${values[TKN_VALUE_PARAM]} ${symbol}`}</Bold>
|
<Bold>{`Amount to transfer: ${values[TKN_VALUE_PARAM]} ${symbol}`}</Bold>
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
<Block style={spinnerStyle}>
|
<Block style={spinnerStyle}>{submitting && <CircularProgress size={50} />}</Block>
|
||||||
{ submitting && <CircularProgress size={50} /> }
|
|
||||||
</Block>
|
|
||||||
</OpenPaper>
|
</OpenPaper>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
// @flow
|
// @flow
|
||||||
import fetchSafe from '~/routes/safe/store/actions/fetchSafe'
|
import fetchSafe from '~/routes/safe/store/actions/fetchSafe'
|
||||||
import fetchTokenBalances from '~/routes/safe/store/actions/fetchTokenBalances'
|
import fetchTokenBalances from '~/routes/safe/store/actions/fetchTokenBalances'
|
||||||
|
import createTransaction from '~/routes/safe/store/actions/createTransaction'
|
||||||
|
|
||||||
export type Actions = {
|
export type Actions = {
|
||||||
fetchSafe: typeof fetchSafe,
|
fetchSafe: typeof fetchSafe,
|
||||||
fetchTokenBalances: typeof fetchTokenBalances,
|
fetchTokenBalances: typeof fetchTokenBalances,
|
||||||
|
createTransaction: typeof createTransaction,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
fetchSafe,
|
fetchSafe,
|
||||||
fetchTokenBalances,
|
fetchTokenBalances,
|
||||||
|
createTransaction,
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ class SafeView extends React.Component<Props> {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
safe, provider, activeTokens, granted, userAddress, network, tokens,
|
safe, provider, activeTokens, granted, userAddress, network, tokens, createTransaction,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -65,6 +65,7 @@ class SafeView extends React.Component<Props> {
|
||||||
userAddress={userAddress}
|
userAddress={userAddress}
|
||||||
network={network}
|
network={network}
|
||||||
granted={granted}
|
granted={granted}
|
||||||
|
createTransaction={createTransaction}
|
||||||
/>
|
/>
|
||||||
</Page>
|
</Page>
|
||||||
)
|
)
|
||||||
|
|
|
@ -13,7 +13,7 @@ import { getStandardTokenContract } from '~/logic/tokens/store/actions/fetchToke
|
||||||
export const ADD_TRANSACTIONS = 'ADD_TRANSACTIONS'
|
export const ADD_TRANSACTIONS = 'ADD_TRANSACTIONS'
|
||||||
export const addTransactions = createAction<string, *>(ADD_TRANSACTIONS)
|
export const addTransactions = createAction<string, *>(ADD_TRANSACTIONS)
|
||||||
|
|
||||||
export const createTransaction = async (safeAddress: string, to: string, valueInEth: string, token: Token) => async (
|
const createTransaction = (safeAddress: string, to: string, valueInEth: string, token: Token, openSnackbar: Function) => async (
|
||||||
dispatch: ReduxDispatch<GlobalState>,
|
dispatch: ReduxDispatch<GlobalState>,
|
||||||
) => {
|
) => {
|
||||||
const safeInstance = await getSafeEthereumInstance(safeAddress)
|
const safeInstance = await getSafeEthereumInstance(safeAddress)
|
||||||
|
@ -35,6 +35,7 @@ export const createTransaction = async (safeAddress: string, to: string, valueIn
|
||||||
let txHash
|
let txHash
|
||||||
if (isExecution) {
|
if (isExecution) {
|
||||||
txHash = await executeTransaction(safeInstance, to, valueInWei, txData, CALL, nonce, from)
|
txHash = await executeTransaction(safeInstance, to, valueInWei, txData, CALL, nonce, from)
|
||||||
|
openSnackbar('Transaction has been submitted', 'success')
|
||||||
} else {
|
} else {
|
||||||
// txHash = await approveTransaction(safeAddress, to, valueInWei, txData, CALL, nonce)
|
// txHash = await approveTransaction(safeAddress, to, valueInWei, txData, CALL, nonce)
|
||||||
}
|
}
|
||||||
|
@ -42,3 +43,5 @@ export const createTransaction = async (safeAddress: string, to: string, valueIn
|
||||||
|
|
||||||
return txHash
|
return txHash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default createTransaction
|
||||||
|
|
Loading…
Reference in New Issue