From abb949702c9c4ffae7e7f4295af34bf1c87c12b3 Mon Sep 17 00:00:00 2001 From: apanizo Date: Thu, 24 May 2018 13:23:04 +0200 Subject: [PATCH] WA-238 Adding create multisig tx logic --- src/routes/safe/component/Safe/index.jsx | 3 +- .../safe/component/Transactions/actions.js | 10 +++++ .../safe/component/Transactions/index.jsx | 37 +++++++++++++------ .../safe/component/Transactions/selector.js | 11 ++++++ .../Transactions/test/transactions.test.js | 22 +++++------ .../component/Transactions/transactions.js | 16 +++++++- 6 files changed, 75 insertions(+), 24 deletions(-) create mode 100644 src/routes/safe/component/Transactions/actions.js create mode 100644 src/routes/safe/component/Transactions/selector.js diff --git a/src/routes/safe/component/Safe/index.jsx b/src/routes/safe/component/Safe/index.jsx index 8ea3490f..0943067b 100644 --- a/src/routes/safe/component/Safe/index.jsx +++ b/src/routes/safe/component/Safe/index.jsx @@ -46,7 +46,8 @@ class GnoSafe extends React.PureComponent { } onAddTx = () => { - this.setState({ component: }) + const { balance, safe } = this.props + this.setState({ component: }) } onSeeTxs = () => { diff --git a/src/routes/safe/component/Transactions/actions.js b/src/routes/safe/component/Transactions/actions.js new file mode 100644 index 00000000..681ad469 --- /dev/null +++ b/src/routes/safe/component/Transactions/actions.js @@ -0,0 +1,10 @@ +// @flow +import fetchTransactions from '~/routes/safe/store/actions/fetchTransactions' + +export type Actions = { + fetchTransactions: typeof fetchTransactions, +} + +export default { + fetchTransactions, +} diff --git a/src/routes/safe/component/Transactions/index.jsx b/src/routes/safe/component/Transactions/index.jsx index 555832b5..0f5cdaa4 100644 --- a/src/routes/safe/component/Transactions/index.jsx +++ b/src/routes/safe/component/Transactions/index.jsx @@ -1,6 +1,12 @@ // @flow import * as React from 'react' +import { connect } from 'react-redux' import Stepper from '~/components/Stepper' +import { sleep } from '~/utils/timer' +import { type Safe } from '~/routes/safe/store/model/safe' +import actions, { type Actions } from './actions' +import selector, { type SelectorProps } from './selector' +import transaction, { createTransaction, TX_NAME_PARAM, TX_DESTINATION_PARAM, TX_VALUE_PARAM } from './transactions' import MultisigForm from './MultisigForm' import ReviewTx from './ReviewTx' @@ -8,14 +14,8 @@ const getSteps = () => [ 'Fill Mutlisig Tx form', 'Review Tx', ] -/* type Props = SelectorProps & Actions & { - safeAddress: string, - dailyLimit: DailyLimit, -} -*/ - -type Props = { + safe: Safe, balance: number, onReset: () => void, } @@ -32,8 +32,24 @@ class Transactions extends React.Component { } onTransaction = async (values: Object) => { - // eslint-disable-next-line - console.log("Executing transaction with params " + JSON.stringify(values)) + try { + const { safe, userAddress } = this.props + const nonce = Date.now() + const destination = values[TX_DESTINATION_PARAM] + const value = values[TX_VALUE_PARAM] + const tx = await transaction(safe.get('address'), destination, value, nonce, userAddress) + await createTransaction( + values[TX_NAME_PARAM], nonce, destination, value, userAddress, + safe.get('owners'), tx, safe.get('address'), safe.get('confirmations'), + ) + await sleep(1500) + this.props.fetchTransactions() + this.setState({ done: true }) + } catch (error) { + this.setState({ done: false }) + // eslint-disable-next-line + console.log('Error while creating multisig tx ' + error) + } } onReset = () => { @@ -68,5 +84,4 @@ class Transactions extends React.Component { } } -export default Transactions - +export default connect(selector, actions)(Transactions) diff --git a/src/routes/safe/component/Transactions/selector.js b/src/routes/safe/component/Transactions/selector.js new file mode 100644 index 00000000..9e7bfef1 --- /dev/null +++ b/src/routes/safe/component/Transactions/selector.js @@ -0,0 +1,11 @@ +// @flow +import { createStructuredSelector } from 'reselect' +import { userAccountSelector } from '~/wallets/store/selectors/index' + +export type SelectorProps = { + userAddress: userAccountSelector, +} + +export default createStructuredSelector({ + userAddress: userAccountSelector, +}) diff --git a/src/routes/safe/component/Transactions/test/transactions.test.js b/src/routes/safe/component/Transactions/test/transactions.test.js index 029814bd..dda2dff8 100644 --- a/src/routes/safe/component/Transactions/test/transactions.test.js +++ b/src/routes/safe/component/Transactions/test/transactions.test.js @@ -31,7 +31,7 @@ describe('Transactions Suite', () => { // GIVEN const txName = 'Buy butteries for project' const nonce: number = 10 - createTransaction(txName, nonce, destination, value, 'foo', owners, '', safe.get('name'), safe.get('address'), safe.get('confirmations')) + createTransaction(txName, nonce, destination, value, 'foo', owners, '', safe.get('address'), safe.get('confirmations')) // WHEN const transactions: Map> = loadSafeTransactions() @@ -51,11 +51,11 @@ describe('Transactions Suite', () => { const firstTxName = 'Buy butteries for project' const firstNonce: number = Date.now() const safeAddress = safe.get('address') - createTransaction(firstTxName, firstNonce, destination, value, 'foo', owners, '', safe.get('name'), safeAddress, safe.get('confirmations')) + createTransaction(firstTxName, firstNonce, destination, value, 'foo', owners, '', safeAddress, safe.get('confirmations')) const secondTxName = 'Buy printers for project' const secondNonce: number = firstNonce + 100 - createTransaction(secondTxName, secondNonce, destination, value, 'foo', owners, '', safe.get('name'), safeAddress, safe.get('confirmations')) + createTransaction(secondTxName, secondNonce, destination, value, 'foo', owners, '', safeAddress, safe.get('confirmations')) // WHEN const transactions: Map> = loadSafeTransactions() @@ -75,7 +75,7 @@ describe('Transactions Suite', () => { const txName = 'Buy batteris for Alplha project' const nonce = 10 const safeAddress = safe.address - createTransaction(txName, nonce, destination, value, 'foo', owners, '', safe.get('name'), safeAddress, safe.get('confirmations')) + createTransaction(txName, nonce, destination, value, 'foo', owners, '', safeAddress, safe.get('confirmations')) const secondSafe = SafeFactory.dailyLimitSafe(10, 2) const txSecondName = 'Buy batteris for Beta project' @@ -83,7 +83,7 @@ describe('Transactions Suite', () => { const secondSafeAddress = secondSafe.address createTransaction( txSecondName, txSecondNonce, destination, value, '0x03db1a8b26d08df23337e9276a36b474510f0023', - secondSafe.get('owners'), '', secondSafe.get('name'), secondSafeAddress, secondSafe.get('confirmations'), + secondSafe.get('owners'), '', secondSafeAddress, secondSafe.get('confirmations'), ) let transactions: Map> = loadSafeTransactions() @@ -102,7 +102,7 @@ describe('Transactions Suite', () => { const txFirstNonce = 11 createTransaction( txFirstName, txFirstNonce, destination, value, 'foo', - safe.get('owners'), '', safe.get('name'), safe.get('address'), safe.get('confirmations'), + safe.get('owners'), '', safe.get('address'), safe.get('confirmations'), ) transactions = loadSafeTransactions() @@ -136,10 +136,10 @@ describe('Transactions Suite', () => { // GIVEN const txName = 'Buy butteries for project' const nonce: number = 10 - createTransaction(txName, nonce, destination, value, 'foo', owners, '', safe.get('name'), safe.get('address'), safe.get('confirmations')) + createTransaction(txName, nonce, destination, value, 'foo', owners, '', safe.get('address'), safe.get('confirmations')) // WHEN - const createTxFnc = () => createTransaction(txName, nonce, destination, value, 'foo', owners, '', safe.get('name'), safe.get('address'), safe.get('confirmations')) + const createTxFnc = () => createTransaction(txName, nonce, destination, value, 'foo', owners, '', safe.get('address'), safe.get('confirmations')) expect(createTxFnc).toThrow(/Transaction with same nonce/) }) @@ -147,7 +147,7 @@ describe('Transactions Suite', () => { // GIVEN const txName = 'Buy butteries for project' const nonce: number = 10 - createTransaction(txName, nonce, destination, value, 'foo', owners, '', safe.get('name'), safe.get('address'), safe.get('confirmations')) + createTransaction(txName, nonce, destination, value, 'foo', owners, '', safe.get('address'), safe.get('confirmations')) // WHEN const transactions: Map> = loadSafeTransactions() @@ -161,7 +161,7 @@ describe('Transactions Suite', () => { const txName = 'Buy butteries for project' const nonce: number = 10 const ownerName = 'invented' - const createTxFnc = () => createTransaction(txName, nonce, destination, value, ownerName, owners, '', safe.get('name'), safe.get('address'), safe.get('confirmations')) + const createTxFnc = () => createTransaction(txName, nonce, destination, value, ownerName, owners, '', safe.get('address'), safe.get('confirmations')) expect(createTxFnc).toThrow(/The creator of the tx is not an owner/) }) @@ -172,7 +172,7 @@ describe('Transactions Suite', () => { const txName = 'Buy butteries for project' const nonce: number = 10 const tx = '' - const createTxFnc = () => createTransaction(txName, nonce, destination, value, ownerName, oneOwnerSafe.get('owners'), tx, oneOwnerSafe.get('name'), oneOwnerSafe.get('address'), oneOwnerSafe.get('confirmations')) + const createTxFnc = () => createTransaction(txName, nonce, destination, value, ownerName, oneOwnerSafe.get('owners'), tx, oneOwnerSafe.get('address'), oneOwnerSafe.get('confirmations')) expect(createTxFnc).toThrow(/The tx should be mined before storing it in safes with one owner/) }) diff --git a/src/routes/safe/component/Transactions/transactions.js b/src/routes/safe/component/Transactions/transactions.js index d70fc796..e5ab22ef 100644 --- a/src/routes/safe/component/Transactions/transactions.js +++ b/src/routes/safe/component/Transactions/transactions.js @@ -4,6 +4,8 @@ import { type Owner } from '~/routes/safe/store/model/owner' import { load, TX_KEY } from '~/utils/localStorage' import { type Confirmation, makeConfirmation } from '~/routes/safe/store/model/confirmation' import { makeTransaction, type Transaction, type TransactionProps } from '~/routes/safe/store/model/transaction' +import { getGnosisSafeContract } from '~/wallets/safeContracts' +import { getWeb3 } from '~/wallets/getWeb3' export const TX_NAME_PARAM = 'txName' export const TX_DESTINATION_PARAM = 'txDestination' @@ -29,7 +31,6 @@ export const createTransaction = ( creator: string, owners: List, tx: string, - safeName: string, safeAddress: string, safeThreshold: number, ) => { @@ -56,3 +57,16 @@ export const createTransaction = ( localStorage.setItem(TX_KEY, JSON.stringify(safeTransactions)) } + +const transactions = async (safeAddress: string, destination: string, value: number, nonce: number, user: string) => { + const web3 = getWeb3() + const GnosisSafe = await getGnosisSafeContract(web3) + const gnosisSafe = GnosisSafe.at(safeAddress) + + const valueInWei = web3.toWei(value, 'ether') + const CALL = 0 + + return gnosisSafe.approveTransactionWithParameters(destination, valueInWei, '0x', CALL, nonce, { from: user, gas: '5000000' }) +} + +export default transactions