allow confirming and executing tx at the same time
This commit is contained in:
parent
c40ea98b5b
commit
f06286df2f
|
@ -62,7 +62,6 @@ const ReviewTx = ({
|
|||
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)
|
||||
|
@ -139,7 +138,7 @@ const ReviewTx = ({
|
|||
</Block>
|
||||
<Hairline style={{ position: 'absolute', bottom: 85 }} />
|
||||
<Row align="center" className={classes.buttonRow}>
|
||||
<Button className={classes.button} minWidth={140} onClick={onClickBack}>
|
||||
<Button className={classes.button} minWidth={140} minHeight={42} onClick={onClickBack}>
|
||||
Back
|
||||
</Button>
|
||||
<Button
|
||||
|
@ -148,6 +147,7 @@ const ReviewTx = ({
|
|||
onClick={submitTx}
|
||||
variant="contained"
|
||||
minWidth={140}
|
||||
minHeight={42}
|
||||
color="primary"
|
||||
data-testid="submit-tx-btn"
|
||||
>
|
||||
|
|
|
@ -158,12 +158,13 @@ const SendFunds = ({
|
|||
</Row>
|
||||
<Hairline />
|
||||
<Row align="center" className={classes.buttonRow}>
|
||||
<Button className={classes.button} minWidth={140} onClick={onClose}>
|
||||
<Button className={classes.button} minWidth={140} minHeight={42} onClick={onClose}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
type="submit"
|
||||
variant="contained"
|
||||
minHeight={42}
|
||||
minWidth={140}
|
||||
color="primary"
|
||||
data-testid="review-tx-btn"
|
||||
|
|
|
@ -26,6 +26,7 @@ type Props = {
|
|||
safeAddress: string,
|
||||
threshold: number,
|
||||
thresholdReached: boolean,
|
||||
userAddress: string,
|
||||
}
|
||||
|
||||
const getModalTitleAndDescription = (thresholdReached: boolean) => {
|
||||
|
@ -51,18 +52,19 @@ const ApproveTxModal = ({
|
|||
safeAddress,
|
||||
threshold,
|
||||
thresholdReached,
|
||||
userAddress,
|
||||
}: Props) => {
|
||||
const [shouldExecuteTx, setShouldExecuteTx] = useState<boolean>(false)
|
||||
const [approveAndExecute, setApproveAndExecute] = useState<boolean>(false)
|
||||
const { title, description } = getModalTitleAndDescription(thresholdReached)
|
||||
const oneConfirmationLeft = tx.confirmations.size + 1 === threshold
|
||||
|
||||
const handleExecuteCheckbox = () => setShouldExecuteTx(prevShouldExecute => !prevShouldExecute)
|
||||
const handleExecuteCheckbox = () => setApproveAndExecute(prevApproveAndExecute => !prevApproveAndExecute)
|
||||
|
||||
return (
|
||||
<SharedSnackbarConsumer>
|
||||
{({ openSnackbar }) => {
|
||||
const approveTx = () => {
|
||||
processTransaction(safeAddress, tx, openSnackbar, thresholdReached || shouldExecuteTx)
|
||||
processTransaction(safeAddress, tx, openSnackbar, userAddress, approveAndExecute)
|
||||
onClose()
|
||||
}
|
||||
|
||||
|
@ -92,7 +94,7 @@ const ApproveTxModal = ({
|
|||
transaction right away, click on checkbox below.
|
||||
</Paragraph>
|
||||
<FormControlLabel
|
||||
control={<Checkbox onChange={handleExecuteCheckbox} checked={shouldExecuteTx} color="primary" />}
|
||||
control={<Checkbox onChange={handleExecuteCheckbox} checked={approveAndExecute} color="primary" />}
|
||||
label="Execute transaction"
|
||||
/>
|
||||
</>
|
||||
|
|
|
@ -2,9 +2,7 @@
|
|||
import React, { useState } from 'react'
|
||||
import { List } from 'immutable'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
import Tabs from '@material-ui/core/Tabs'
|
||||
import OpenInNew from '@material-ui/icons/OpenInNew'
|
||||
import Tab from '@material-ui/core/Tab'
|
||||
import Row from '~/components/layout/Row'
|
||||
import Block from '~/components/layout/Block'
|
||||
import Col from '~/components/layout/Col'
|
||||
|
@ -16,7 +14,6 @@ import { type Transaction } from '~/routes/safe/store/models/transaction'
|
|||
import { type Owner } from '~/routes/safe/store/models/owner'
|
||||
import { getEtherScanLink, openTxInEtherScan, getWeb3 } from '~/logic/wallets/getWeb3'
|
||||
import { shortVersionOf } from '~/logic/wallets/ethAddresses'
|
||||
import { TX_TYPE_CONFIRMATION } from '~/logic/safe/transactions'
|
||||
import { secondary } from '~/theme/variables'
|
||||
import OwnersColumn from './OwnersColumn'
|
||||
import CancelTxModal from './CancelTxModal'
|
||||
|
@ -150,6 +147,7 @@ to:
|
|||
processTransaction={processTransaction}
|
||||
onClose={closeModal}
|
||||
tx={tx}
|
||||
userAddress={userAddress}
|
||||
safeAddress={safeAddress}
|
||||
threshold={threshold}
|
||||
thresholdReached={thresholdReached}
|
||||
|
|
|
@ -9,13 +9,17 @@ import { approveTransaction, executeTransaction, CALL } from '~/logic/safe/trans
|
|||
|
||||
// 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
|
||||
const generateSignaturesFromTxConfirmations = (tx: Transaction) => {
|
||||
const generateSignaturesFromTxConfirmations = (tx: Transaction, preApprovingOwner?: string) => {
|
||||
// The constant parts need to be sorted so that the recovered signers are sorted ascending
|
||||
// (natural order) by address (not checksummed).
|
||||
const confirmedAdresses = tx.confirmations.map(conf => conf.owner.address).sort()
|
||||
let confirmedAdresses = tx.confirmations.map(conf => conf.owner.address)
|
||||
|
||||
if (preApprovingOwner) {
|
||||
confirmedAdresses = confirmedAdresses.push(preApprovingOwner)
|
||||
}
|
||||
|
||||
let sigs = '0x'
|
||||
confirmedAdresses.forEach((addr) => {
|
||||
confirmedAdresses.sort().forEach((addr) => {
|
||||
sigs += `000000000000000000000000${addr.replace(
|
||||
'0x',
|
||||
'',
|
||||
|
@ -28,14 +32,19 @@ const processTransaction = (
|
|||
safeAddress: string,
|
||||
tx: Transaction,
|
||||
openSnackbar: Function,
|
||||
shouldExecute?: boolean,
|
||||
userAddress: string,
|
||||
approveAndExecute?: boolean,
|
||||
) => async (dispatch: ReduxDispatch<GlobalState>, getState: GetState<GlobalState>) => {
|
||||
const state: GlobalState = getState()
|
||||
|
||||
const safeInstance = await getGnosisSafeInstanceAt(safeAddress)
|
||||
const from = userAccountSelector(state)
|
||||
const nonce = (await safeInstance.nonce()).toString()
|
||||
const sigs = generateSignaturesFromTxConfirmations(tx)
|
||||
const threshold = (await safeInstance.getThreshold()).toNumber()
|
||||
console.log(threshold, tx.confirmations.size)
|
||||
const shouldExecute = threshold === tx.confirmations.size || approveAndExecute
|
||||
const sigs = generateSignaturesFromTxConfirmations(tx, approveAndExecute && userAddress)
|
||||
|
||||
|
||||
let txHash
|
||||
if (shouldExecute) {
|
||||
|
|
Loading…
Reference in New Issue