From 87c41e4d78cd12fcc81a58c829d570a1b7f2b168 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Fri, 5 Jul 2019 19:43:36 +0400 Subject: [PATCH] add processTransaction action --- src/logic/safe/transactions/send.js | 22 +++++++++++++---- src/routes/safe/components/Layout.jsx | 3 +++ .../ExpandedTx/ApproveTxModal/index.jsx | 24 ++++++++++--------- .../TxsTable/ExpandedTx/index.jsx | 9 ++++--- .../TransactionsNew/TxsTable/index.jsx | 3 +++ .../safe/components/TransactionsNew/index.jsx | 3 +++ src/routes/safe/container/actions.js | 3 +++ src/routes/safe/container/index.jsx | 2 ++ .../safe/store/actions/processTransaction.js | 17 ++++++++++++- 9 files changed, 67 insertions(+), 19 deletions(-) diff --git a/src/logic/safe/transactions/send.js b/src/logic/safe/transactions/send.js index d1ec0b13..76c9e1d6 100644 --- a/src/logic/safe/transactions/send.js +++ b/src/logic/safe/transactions/send.js @@ -61,13 +61,27 @@ export const executeTransaction = async ( operation: Operation, nonce: string | number, sender: string, + signatures?: string, ) => { + console.log({ + to, + valueInWei, + data, + operation, + nonce, + sender, + signatures, + }) try { + let sigs = signatures + // https://gnosis-safe.readthedocs.io/en/latest/contracts/signatures.html#pre-validated-signatures - const sigs = `0x000000000000000000000000${sender.replace( - '0x', - '', - )}000000000000000000000000000000000000000000000000000000000000000001` + if (!sigs) { + sigs = `0x000000000000000000000000${sender.replace( + '0x', + '', + )}000000000000000000000000000000000000000000000000000000000000000001` + } const receipt = await safeInstance.execTransaction( to, diff --git a/src/routes/safe/components/Layout.jsx b/src/routes/safe/components/Layout.jsx index 6e1f39ea..bfbafd82 100644 --- a/src/routes/safe/components/Layout.jsx +++ b/src/routes/safe/components/Layout.jsx @@ -34,6 +34,7 @@ type Props = SelectorProps & { granted: boolean, updateSafe: Function, createTransaction: Function, + processTransaction: Function, fetchTransactions: Function, } @@ -104,6 +105,7 @@ class Layout extends React.Component { tokens, activeTokens, createTransaction, + processTransaction, fetchTransactions, updateSafe, transactions, @@ -169,6 +171,7 @@ class Layout extends React.Component { userAddress={userAddress} granted={granted} createTransaction={createTransaction} + processTransaction={processTransaction} /> )} {tabIndex === 2 && ( diff --git a/src/routes/safe/components/TransactionsNew/TxsTable/ExpandedTx/ApproveTxModal/index.jsx b/src/routes/safe/components/TransactionsNew/TxsTable/ExpandedTx/ApproveTxModal/index.jsx index 99b0401a..c7bd56e6 100644 --- a/src/routes/safe/components/TransactionsNew/TxsTable/ExpandedTx/ApproveTxModal/index.jsx +++ b/src/routes/safe/components/TransactionsNew/TxsTable/ExpandedTx/ApproveTxModal/index.jsx @@ -20,10 +20,11 @@ type Props = { onClose: () => void, classes: Object, isOpen: boolean, - createTransaction: Function, + processTransaction: Function, tx: Transaction, nonce: string, safeAddress: string, + threshold: number, thresholdReached: boolean, } @@ -42,10 +43,18 @@ const getModalTitleAndDescription = (thresholdReached: boolean) => { } const ApproveTxModal = ({ - onClose, isOpen, classes, createTransaction, tx, safeAddress, thresholdReached, + onClose, + isOpen, + classes, + processTransaction, + tx, + safeAddress, + threshold, + thresholdReached, }: Props) => { const [shouldExecuteTx, setShouldExecuteTx] = useState(false) const { title, description } = getModalTitleAndDescription(thresholdReached) + const oneConfirmationLeft = tx.confirmations.size + 1 === threshold const handleExecuteCheckbox = () => setShouldExecuteTx(prevShouldExecute => !prevShouldExecute) @@ -53,14 +62,7 @@ const ApproveTxModal = ({ {({ openSnackbar }) => { const approveTx = () => { - createTransaction( - safeAddress, - tx.recipient, - tx.value, - tx.data, - openSnackbar, - thresholdReached || shouldExecuteTx, - ) + processTransaction(safeAddress, tx, openSnackbar, thresholdReached || shouldExecuteTx) onClose() } @@ -83,7 +85,7 @@ const ApproveTxModal = ({
{tx.nonce} - {!thresholdReached && ( + {!thresholdReached && oneConfirmationLeft && ( <> Approving transaction does not execute it immediately. If you want to approve and execute the diff --git a/src/routes/safe/components/TransactionsNew/TxsTable/ExpandedTx/index.jsx b/src/routes/safe/components/TransactionsNew/TxsTable/ExpandedTx/index.jsx index a82caafc..02996bbd 100644 --- a/src/routes/safe/components/TransactionsNew/TxsTable/ExpandedTx/index.jsx +++ b/src/routes/safe/components/TransactionsNew/TxsTable/ExpandedTx/index.jsx @@ -37,6 +37,7 @@ type Props = { userAddress: string, safeAddress: string, createTransaction: Function, + processTransaction: Function, } type OpenModal = 'cancelTx' | 'approveTx' | null @@ -55,7 +56,6 @@ const txStatusToLabel = { const isCancellationTransaction = (tx: Transaction, safeAddress: string) => !tx.value && tx.data === EMPTY_DATA && tx.recipient === safeAddress - const ExpandedTx = ({ classes, tx, @@ -65,6 +65,7 @@ const ExpandedTx = ({ userAddress, safeAddress, createTransaction, + processTransaction, }: Props) => { const [tabIndex, setTabIndex] = useState(0) const [openModal, setOpenModal] = useState(null) @@ -74,7 +75,7 @@ const ExpandedTx = ({ const cancellationTx = isCancellationTransaction(tx, safeAddress) const confirmedLabel = `Confirmed [${tx.confirmations.size}/${threshold}]` const unconfirmedLabel = `Unconfirmed [${owners.size - tx.confirmations.size}]` - const thresholdReached = owners.size <= tx.confirmations.size + const thresholdReached = threshold <= tx.confirmations.size const ownersWhoConfirmed = [] const ownersUnconfirmed = [] @@ -195,11 +196,13 @@ to: /> ) diff --git a/src/routes/safe/components/TransactionsNew/TxsTable/index.jsx b/src/routes/safe/components/TransactionsNew/TxsTable/index.jsx index f9a43564..5e2ee1e8 100644 --- a/src/routes/safe/components/TransactionsNew/TxsTable/index.jsx +++ b/src/routes/safe/components/TransactionsNew/TxsTable/index.jsx @@ -36,6 +36,7 @@ type Props = { granted: boolean, safeAddress: string, createTransaction: Function, + processTransaction: Function, } const TxsTable = ({ @@ -47,6 +48,7 @@ const TxsTable = ({ userAddress, safeAddress, createTransaction, + processTransaction, }: Props) => { const [expandedTx, setExpandedTx] = useState(null) @@ -113,6 +115,7 @@ const TxsTable = ({ granted={granted} userAddress={userAddress} createTransaction={createTransaction} + processTransaction={processTransaction} safeAddress={safeAddress} /> diff --git a/src/routes/safe/components/TransactionsNew/index.jsx b/src/routes/safe/components/TransactionsNew/index.jsx index f117fa5e..317e967c 100644 --- a/src/routes/safe/components/TransactionsNew/index.jsx +++ b/src/routes/safe/components/TransactionsNew/index.jsx @@ -15,6 +15,7 @@ type Props = { userAddress: string, granted: boolean, createTransaction: Function, + processTransaction: Function, } const Transactions = ({ @@ -25,6 +26,7 @@ const Transactions = ({ granted, safeAddress, createTransaction, + processTransaction, fetchTransactions, }: Props) => { useEffect(() => { @@ -44,6 +46,7 @@ const Transactions = ({ granted={granted} safeAddress={safeAddress} createTransaction={createTransaction} + processTransaction={processTransaction} /> ) : ( diff --git a/src/routes/safe/container/actions.js b/src/routes/safe/container/actions.js index 6638a28d..a51fb28e 100644 --- a/src/routes/safe/container/actions.js +++ b/src/routes/safe/container/actions.js @@ -2,6 +2,7 @@ import fetchSafe from '~/routes/safe/store/actions/fetchSafe' import fetchTokenBalances from '~/routes/safe/store/actions/fetchTokenBalances' import createTransaction from '~/routes/safe/store/actions/createTransaction' +import processTransaction from '~/routes/safe/store/actions/processTransaction' import fetchTransactions from '~/routes/safe/store/actions/fetchTransactions' import updateSafe from '~/routes/safe/store/actions/updateSafe' import fetchTokens from '~/logic/tokens/store/actions/fetchTokens' @@ -13,12 +14,14 @@ export type Actions = { fetchTransactions: typeof fetchTransactions, updateSafe: typeof updateSafe, fetchTokens: typeof fetchTokens, + processTransaction: typeof processTransaction, } export default { fetchSafe, fetchTokenBalances, createTransaction, + processTransaction, fetchTokens, fetchTransactions, updateSafe, diff --git a/src/routes/safe/container/index.jsx b/src/routes/safe/container/index.jsx index 6d4de495..48ad1ed3 100644 --- a/src/routes/safe/container/index.jsx +++ b/src/routes/safe/container/index.jsx @@ -63,6 +63,7 @@ class SafeView extends React.Component { network, tokens, createTransaction, + processTransaction, fetchTransactions, updateSafe, transactions, @@ -79,6 +80,7 @@ class SafeView extends React.Component { network={network} granted={granted} createTransaction={createTransaction} + processTransaction={processTransaction} fetchTransactions={fetchTransactions} updateSafe={updateSafe} transactions={transactions} diff --git a/src/routes/safe/store/actions/processTransaction.js b/src/routes/safe/store/actions/processTransaction.js index 61e23504..ab1b225d 100644 --- a/src/routes/safe/store/actions/processTransaction.js +++ b/src/routes/safe/store/actions/processTransaction.js @@ -7,6 +7,20 @@ import { type GlobalState } from '~/store' import { getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts' import { approveTransaction, executeTransaction, CALL } from '~/logic/safe/transactions' +// 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) => { + let sigs = '0x' + tx.confirmations.forEach((conf) => { + sigs + += `000000000000000000000000${ + conf.owner.address.replace('0x', '') + }0000000000000000000000000000000000000000000000000000000000000000` + + '01' + }) + return sigs +} + const processTransaction = ( safeAddress: string, tx: Transaction, @@ -18,11 +32,12 @@ const processTransaction = ( const safeInstance = await getGnosisSafeInstanceAt(safeAddress) const from = userAccountSelector(state) const nonce = (await safeInstance.nonce()).toString() + const sigs = generateSignaturesFromTxConfirmations(tx) let txHash if (shouldExecute) { openSnackbar('Transaction has been submitted', 'success') - txHash = await executeTransaction(safeInstance, tx.recipient, tx.value, tx.data, CALL, nonce, from) + txHash = await executeTransaction(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')