mirror of
https://github.com/status-im/safe-react.git
synced 2025-02-03 13:23:33 +00:00
Merge pull request #32 from gnosis/feature/WA-238-withdrawn-blockchain-requirements
WA-238 Blockchain requirements
This commit is contained in:
commit
46a1737605
@ -5,15 +5,16 @@ os:
|
||||
- linux
|
||||
before_script:
|
||||
- yarn global add surge
|
||||
- export NODE_ENV=testing
|
||||
after_success:
|
||||
- yarn build-storybook
|
||||
- yarn build
|
||||
- |
|
||||
if [ ${TRAVIS_BRANCH} = "master" ]; then
|
||||
export NODE_ENV=production;
|
||||
else
|
||||
export NODE_ENV=development;
|
||||
fi
|
||||
- yarn build-storybook
|
||||
- yarn build
|
||||
- cd build_webpack/ && cp index.html 200.html && cd ..
|
||||
- chmod ugo+x ./config/deploy/deploy.sh
|
||||
- ./config/deploy/deploy.sh
|
||||
|
@ -9,7 +9,7 @@
|
||||
"start": "node scripts/start.js",
|
||||
"build": "node scripts/build.js",
|
||||
"test": "run-with-testrpc -l 40000000 'node scripts/test.js --env=jsdom'",
|
||||
"test-local": "node scripts/test.js --env=jsdom",
|
||||
"test-local": "NODE_ENV=test && node scripts/test.js --env=jsdom",
|
||||
"precommit": "./precommit.sh",
|
||||
"flow": "flow",
|
||||
"storybook": "start-storybook -p 6006",
|
||||
@ -50,6 +50,7 @@
|
||||
"babel-plugin-dynamic-import-node": "^1.2.0",
|
||||
"babel-plugin-transform-es3-member-expression-literals": "^6.22.0",
|
||||
"babel-plugin-transform-es3-property-literals": "^6.22.0",
|
||||
"bignumber.js": "^7.2.1",
|
||||
"classnames": "^2.2.5",
|
||||
"css-loader": "^0.28.10",
|
||||
"detect-port": "^1.2.2",
|
||||
|
@ -1262,10 +1262,22 @@
|
||||
"1527420696956": {
|
||||
"events": {},
|
||||
"links": {},
|
||||
"address": "0x251be274c3a4580fc02223ee33edfa9a2dc386e5",
|
||||
"transactionHash": "0x7e0d20efecc34a31abf9e22cedf9e709811549a444d77d4889739930ad68ffb3"
|
||||
"address": "0x18449f1e7a7397fcc0efb8021e55766f5874d6bb",
|
||||
"transactionHash": "0x288775644c087eed5e41b96fecebdb23be4e6d40bef5b6fb9a2876c2a3145157"
|
||||
},
|
||||
"1527678155804": {
|
||||
"events": {},
|
||||
"links": {},
|
||||
"address": "0x4541a795062934411e9aa7debc9cd288d1ca3c3d",
|
||||
"transactionHash": "0x1de7d532cd599c2eeb5bd5eed12038de0f6556b5d22a0a4f4f8cc15a68ef552c"
|
||||
},
|
||||
"1528109761438": {
|
||||
"events": {},
|
||||
"links": {},
|
||||
"address": "0x5fd674bc2873513f8e5a19d69637d0211e476380",
|
||||
"transactionHash": "0x288775644c087eed5e41b96fecebdb23be4e6d40bef5b6fb9a2876c2a3145157"
|
||||
}
|
||||
},
|
||||
"schemaVersion": "2.0.0",
|
||||
"updatedAt": "2018-05-28T13:58:28.822Z"
|
||||
"updatedAt": "2018-06-04T10:56:37.138Z"
|
||||
}
|
@ -6685,10 +6685,22 @@
|
||||
"1527420696956": {
|
||||
"events": {},
|
||||
"links": {},
|
||||
"address": "0x904a781310cc19b414bafa5499628cd10173cbad",
|
||||
"transactionHash": "0x2ec83a0174a651dec98e783aa4e23d0b97e8487f788329f82789da4d5067c614"
|
||||
"address": "0x7318910138c97bec533269843cac7cc32e30d627",
|
||||
"transactionHash": "0xf501438a4ec967e2928d922e4af568a2a5365002f8b3f9e32117bbacfaa49331"
|
||||
},
|
||||
"1527678155804": {
|
||||
"events": {},
|
||||
"links": {},
|
||||
"address": "0xb3a1d7348482ad2556b7cc56d84e8650e9288cd2",
|
||||
"transactionHash": "0xd6ea4f9e92e49e53ee69faafc7c7ab1c54d811fd1552351f8ec5cdc6f1795843"
|
||||
},
|
||||
"1528109761438": {
|
||||
"events": {},
|
||||
"links": {},
|
||||
"address": "0x3bdceb07fddd50d259a059ca9a75ecda561d4afc",
|
||||
"transactionHash": "0xf501438a4ec967e2928d922e4af568a2a5365002f8b3f9e32117bbacfaa49331"
|
||||
}
|
||||
},
|
||||
"schemaVersion": "2.0.0",
|
||||
"updatedAt": "2018-05-28T13:58:28.821Z"
|
||||
"updatedAt": "2018-06-04T10:56:37.129Z"
|
||||
}
|
@ -9850,10 +9850,22 @@
|
||||
"1527420696956": {
|
||||
"events": {},
|
||||
"links": {},
|
||||
"address": "0x5aba3ebfac41cb9be55a7ab67b506c960982e427",
|
||||
"transactionHash": "0x370c8b71ac770f90d44d7bc1f447930a01806b3d8d7b218b21e4020865c45321"
|
||||
"address": "0x177c7d89d62a0d8bdab4a0a8a5e7225370fd1486",
|
||||
"transactionHash": "0x67117c1452ee2f4b904621b6f30790ff998d1f1a72f11c6b71ef47e3dd254724"
|
||||
},
|
||||
"1527678155804": {
|
||||
"events": {},
|
||||
"links": {},
|
||||
"address": "0x4dbf7fe3ee192b4ea00005c0a7219e4ca19971d6",
|
||||
"transactionHash": "0xbbf11bb9369aeb027629ec2279e2be554fee6c522da76160a6b535d25d966b1e"
|
||||
},
|
||||
"1528109761438": {
|
||||
"events": {},
|
||||
"links": {},
|
||||
"address": "0x8c55b458a53e8c6e9efa7f54e7be9ca76b43dd9b",
|
||||
"transactionHash": "0x67117c1452ee2f4b904621b6f30790ff998d1f1a72f11c6b71ef47e3dd254724"
|
||||
}
|
||||
},
|
||||
"schemaVersion": "2.0.0",
|
||||
"updatedAt": "2018-05-28T13:58:28.830Z"
|
||||
"updatedAt": "2018-06-04T10:56:37.124Z"
|
||||
}
|
@ -6862,10 +6862,22 @@
|
||||
"1527420696956": {
|
||||
"events": {},
|
||||
"links": {},
|
||||
"address": "0xb25140d7a0383c103745ce78d394f13ba4cf05ce",
|
||||
"transactionHash": "0x6443dda4014bb6968582b264cb829cade880976d4c08e3f3c038cbc7d180f619"
|
||||
"address": "0xb8d09a68423900f75635ae045562a8338060c9aa",
|
||||
"transactionHash": "0xa71d3b0b3752acc18733fa881f70c256d63562f28ccca9af910fad3beee9181a"
|
||||
},
|
||||
"1527678155804": {
|
||||
"events": {},
|
||||
"links": {},
|
||||
"address": "0x8bec74b923b0d2ac349b920ab7566f9c2de06ed1",
|
||||
"transactionHash": "0x846890db3c85ef38bf8ee86c789f20fbdf1c6339e44f897e15e80ba166b50de3"
|
||||
},
|
||||
"1528109761438": {
|
||||
"events": {},
|
||||
"links": {},
|
||||
"address": "0xd4edae2f2d5718d1798deb48c062b939d6e9d4f4",
|
||||
"transactionHash": "0xa71d3b0b3752acc18733fa881f70c256d63562f28ccca9af910fad3beee9181a"
|
||||
}
|
||||
},
|
||||
"schemaVersion": "2.0.0",
|
||||
"updatedAt": "2018-05-28T13:58:28.817Z"
|
||||
"updatedAt": "2018-06-04T10:56:37.114Z"
|
||||
}
|
@ -1384,10 +1384,22 @@
|
||||
"1527420696956": {
|
||||
"events": {},
|
||||
"links": {},
|
||||
"address": "0x3058a32c81f9e74ace6fa808b1906af0252c7638",
|
||||
"transactionHash": "0x025b6461e9bfe4546ffada7cbf308b8eb4c12287d93fd6079297fb9c847de4df"
|
||||
"address": "0x954fe52de6d6d18bef1da4972b7bd26dfae4b90c",
|
||||
"transactionHash": "0xb6a19a7a679a1474c09c651e4151421f210afa3f47effed019d4c0206144ee5f"
|
||||
},
|
||||
"1527678155804": {
|
||||
"events": {},
|
||||
"links": {},
|
||||
"address": "0xad40476dc43dbb9546709731e1112be5817db3d2",
|
||||
"transactionHash": "0xb329d36a169f7dae30b168e57ae72496354fde3b36d9c285a92da9ff012a6399"
|
||||
},
|
||||
"1528109761438": {
|
||||
"events": {},
|
||||
"links": {},
|
||||
"address": "0x2ebea54cbbd4f5491deba7a37605f8f0be3e3c9b",
|
||||
"transactionHash": "0xb6a19a7a679a1474c09c651e4151421f210afa3f47effed019d4c0206144ee5f"
|
||||
}
|
||||
},
|
||||
"schemaVersion": "2.0.0",
|
||||
"updatedAt": "2018-05-28T13:58:28.833Z"
|
||||
"updatedAt": "2018-06-04T10:56:37.139Z"
|
||||
}
|
@ -346,10 +346,22 @@
|
||||
"1527420696956": {
|
||||
"events": {},
|
||||
"links": {},
|
||||
"address": "0xe423b2291101fb206218ce4eeb03150e94446086",
|
||||
"transactionHash": "0xa78e4749df5af5dff57145c85a9c9ca882d3b61e6125da675388fdda421622a2"
|
||||
"address": "0x8e9d29708810d650d0b43058b41687ea02c0baee",
|
||||
"transactionHash": "0xd044f1662e339061a8cabf2b06ac94a9f86fcccf3f5d80ebd1bea2a7542d4021"
|
||||
},
|
||||
"1527678155804": {
|
||||
"events": {},
|
||||
"links": {},
|
||||
"address": "0x6655c7792ebda0b1dbea3607591995ea391c8a9e",
|
||||
"transactionHash": "0x70aa0d9af1bc4978d61d3f0c67523717246c4a588a4c1808d45609e0adb04a05"
|
||||
},
|
||||
"1528109761438": {
|
||||
"events": {},
|
||||
"links": {},
|
||||
"address": "0x3946fcaaa0ba21aaffc5e06a3cc45debc9e07f7f",
|
||||
"transactionHash": "0xd044f1662e339061a8cabf2b06ac94a9f86fcccf3f5d80ebd1bea2a7542d4021"
|
||||
}
|
||||
},
|
||||
"schemaVersion": "2.0.0",
|
||||
"updatedAt": "2018-05-28T13:58:28.823Z"
|
||||
"updatedAt": "2018-06-04T10:56:37.139Z"
|
||||
}
|
@ -997,10 +997,22 @@
|
||||
"1527420696956": {
|
||||
"events": {},
|
||||
"links": {},
|
||||
"address": "0x1f7aea763a0714a857aa537a630aa9c1489a9e8d",
|
||||
"transactionHash": "0xe6856fb57fd2c5da970b640fe9a5f8ee38444b5dbc381bb11bef2bb9cb80d648"
|
||||
"address": "0xa16e2ea106b09506111fcd01eb82c9864afa4315",
|
||||
"transactionHash": "0x75ad1066b44cd801ac66a316dbe4c09e72636d72b70fd62eb647295a0fc5e285"
|
||||
},
|
||||
"1527678155804": {
|
||||
"events": {},
|
||||
"links": {},
|
||||
"address": "0xf2bf237dc75c3a466b457a5eff498061dac4c341",
|
||||
"transactionHash": "0x0a1bf7e8030e9d4d24dd7002f35ece3848830cd266ab089664fd1d44ea95d506"
|
||||
},
|
||||
"1528109761438": {
|
||||
"events": {},
|
||||
"links": {},
|
||||
"address": "0xbefd9f4a40b1bec8ec730969a3508d1739fb2742",
|
||||
"transactionHash": "0x75ad1066b44cd801ac66a316dbe4c09e72636d72b70fd62eb647295a0fc5e285"
|
||||
}
|
||||
},
|
||||
"schemaVersion": "2.0.0",
|
||||
"updatedAt": "2018-05-28T13:58:28.811Z"
|
||||
"updatedAt": "2018-06-04T10:56:37.112Z"
|
||||
}
|
@ -7296,10 +7296,22 @@
|
||||
"1527420696956": {
|
||||
"events": {},
|
||||
"links": {},
|
||||
"address": "0xaba91d2c011e7cc4e8a7b89c7731fc355f5733f4",
|
||||
"transactionHash": "0x274449b108fc18df74c77e6dcd670fa9c486c1dd6ad7aece13cbedea6a77f75d"
|
||||
"address": "0x72c57fd020ba5c1e42d7e9a7757dd40d5febc594",
|
||||
"transactionHash": "0xf0cd95843453bdac02ad8018ef507479ea62989e56d69ad0ac1aad9d3a8515d2"
|
||||
},
|
||||
"1527678155804": {
|
||||
"events": {},
|
||||
"links": {},
|
||||
"address": "0xeda62e0821a48445ae6f6f80106e216c6a7f01ef",
|
||||
"transactionHash": "0x36c8dd7c6308c6c439014348fa486a003b509f6740a3fbb01b00d57958c4eca7"
|
||||
},
|
||||
"1528109761438": {
|
||||
"events": {},
|
||||
"links": {},
|
||||
"address": "0xfb1771240bb7edf209c70bd520a5d5424d23b084",
|
||||
"transactionHash": "0xf0cd95843453bdac02ad8018ef507479ea62989e56d69ad0ac1aad9d3a8515d2"
|
||||
}
|
||||
},
|
||||
"schemaVersion": "2.0.0",
|
||||
"updatedAt": "2018-05-28T13:58:28.837Z"
|
||||
"updatedAt": "2018-06-04T10:56:37.135Z"
|
||||
}
|
@ -5867,10 +5867,22 @@
|
||||
"1527420696956": {
|
||||
"events": {},
|
||||
"links": {},
|
||||
"address": "0x54385cc32f3e1cf1167a00d1031713005b58810d",
|
||||
"transactionHash": "0x5f41f6fd32694378659292b40446fc88ab574830bb99b43380355fd9b2454ca4"
|
||||
"address": "0xa3944632cf9b50c805788da58443efdf323e69bd",
|
||||
"transactionHash": "0x0396e1c9da4fa7bd313286e6033446dbb6e491f267956f8cf13202ce534fd0e6"
|
||||
},
|
||||
"1527678155804": {
|
||||
"events": {},
|
||||
"links": {},
|
||||
"address": "0x5b0e6b22a1d89e20256ec666ad2acab10d506258",
|
||||
"transactionHash": "0x6d60cded3abc0298631da9e4402c536e9c10604d213f4fb215f83795722ccda9"
|
||||
},
|
||||
"1528109761438": {
|
||||
"events": {},
|
||||
"links": {},
|
||||
"address": "0x589fd9eea7cca488a80e17a5105befff9616f11d",
|
||||
"transactionHash": "0x0396e1c9da4fa7bd313286e6033446dbb6e491f267956f8cf13202ce534fd0e6"
|
||||
}
|
||||
},
|
||||
"schemaVersion": "2.0.0",
|
||||
"updatedAt": "2018-05-28T13:58:28.813Z"
|
||||
"updatedAt": "2018-06-04T10:56:37.118Z"
|
||||
}
|
@ -4340,10 +4340,22 @@
|
||||
"1527420696956": {
|
||||
"events": {},
|
||||
"links": {},
|
||||
"address": "0x68493ac3f7b340768f44d3924cbf6f303a104107",
|
||||
"transactionHash": "0x45669293d5726d8b49af10473522b1c3d6232f5cbded6b626e24d366214501c8"
|
||||
"address": "0x0f2908be3c687fe9fecdfcd3f87cd7464c229723",
|
||||
"transactionHash": "0x463374c2fbc7eaff5b87e65c6a8fdc1177ef82c66084df6e7b88b506f99b193c"
|
||||
},
|
||||
"1527678155804": {
|
||||
"events": {},
|
||||
"links": {},
|
||||
"address": "0xe6986286e71b3cf130edfecefd140c7b0ef7bdc0",
|
||||
"transactionHash": "0xf135f6e2d525ab0b8889f2860a2ff124ca2c3b8660bf5352cc05206a71be9a9a"
|
||||
},
|
||||
"1528109761438": {
|
||||
"events": {},
|
||||
"links": {},
|
||||
"address": "0xca574a31a4cf1eeabeecaffc555bdc7f91c5caf9",
|
||||
"transactionHash": "0x463374c2fbc7eaff5b87e65c6a8fdc1177ef82c66084df6e7b88b506f99b193c"
|
||||
}
|
||||
},
|
||||
"schemaVersion": "2.0.0",
|
||||
"updatedAt": "2018-05-28T13:58:28.834Z"
|
||||
"updatedAt": "2018-06-04T10:56:37.132Z"
|
||||
}
|
@ -65,10 +65,10 @@ describe('React DOM TESTS > Create Safe form', () => {
|
||||
const deployed = TestUtils.findRenderedDOMComponentWithClass(open, DEPLOYED_COMPONENT_ID)
|
||||
|
||||
if (deployed) {
|
||||
const transactionHash = JSON.parse(deployed.getElementsByTagName('pre')[0].innerHTML)
|
||||
delete transactionHash.logsBloom
|
||||
const transaction = JSON.parse(deployed.getElementsByTagName('pre')[0].innerHTML)
|
||||
delete transaction.receipt.logsBloom
|
||||
// eslint-disable-next-line
|
||||
console.log(transactionHash)
|
||||
// console.log(transaction)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
@ -8,6 +8,7 @@ import { getGnosisSafeContract } from '~/wallets/safeContracts'
|
||||
import { getWeb3 } from '~/wallets/getWeb3'
|
||||
import { type Safe } from '~/routes/safe/store/model/safe'
|
||||
import { sameAddress } from '~/wallets/ethAddresses'
|
||||
import executeTransaction from '~/wallets/ethTransactions'
|
||||
|
||||
export const TX_NAME_PARAM = 'txName'
|
||||
export const TX_DESTINATION_PARAM = 'txDestination'
|
||||
@ -96,13 +97,15 @@ export const createTransaction = async (
|
||||
|
||||
const thresholdIsOne = safe.get('confirmations') === 1
|
||||
if (hasOneOwner(safe) || thresholdIsOne) {
|
||||
const txReceipt = await gnosisSafe.execTransactionIfApproved(txDestination, valueInWei, '0x', CALL, nonce, { from: user, gas: '5000000' })
|
||||
const txConfirmationData = gnosisSafe.contract.execTransactionIfApproved.getData(txDestination, valueInWei, '0x', CALL, nonce)
|
||||
const txReceipt = await executeTransaction(txConfirmationData, user, safeAddress)
|
||||
const executedConfirmations: List<Confirmation> = buildExecutedConfirmationFrom(safe.get('owners'), user)
|
||||
return storeTransaction(txName, nonce, txDestination, txValue, user, executedConfirmations, txReceipt.tx, safeAddress, safe.get('confirmations'))
|
||||
return storeTransaction(txName, nonce, txDestination, txValue, user, executedConfirmations, txReceipt, safeAddress, safe.get('confirmations'))
|
||||
}
|
||||
|
||||
const txConfirmationHash = await gnosisSafe.approveTransactionWithParameters(txDestination, valueInWei, '0x', CALL, nonce, { from: user, gas: '5000000' })
|
||||
const confirmations: List<Confirmation> = buildConfirmationsFrom(safe.get('owners'), user, txConfirmationHash.tx)
|
||||
const txConfirmationData = gnosisSafe.contract.approveTransactionWithParameters.getData(txDestination, valueInWei, '0x', CALL, nonce)
|
||||
const txConfirmationReceipt = await executeTransaction(txConfirmationData, user, safeAddress)
|
||||
const confirmations: List<Confirmation> = buildConfirmationsFrom(safe.get('owners'), user, txConfirmationReceipt)
|
||||
|
||||
return storeTransaction(txName, nonce, txDestination, txValue, user, confirmations, '', safeAddress, safe.get('confirmations'))
|
||||
}
|
||||
|
@ -10,14 +10,16 @@ import { type DailyLimit } from '~/routes/safe/store/model/dailyLimit'
|
||||
type Props = {
|
||||
dailyLimit: DailyLimit,
|
||||
onWithdrawn: () => void,
|
||||
balance: string,
|
||||
}
|
||||
|
||||
export const WITHDRAWN_BUTTON_TEXT = 'Withdrawn'
|
||||
|
||||
const DailyLimitComponent = ({ dailyLimit, onWithdrawn }: Props) => {
|
||||
const DailyLimitComponent = ({ dailyLimit, balance, onWithdrawn }: Props) => {
|
||||
const limit = dailyLimit.get('value')
|
||||
const spentToday = dailyLimit.get('spentToday')
|
||||
const disabled = spentToday >= limit
|
||||
|
||||
const disabled = spentToday >= limit || Number(balance) === 0
|
||||
const text = `${limit} ETH (spent today: ${spentToday} ETH)`
|
||||
|
||||
return (
|
||||
|
@ -71,7 +71,7 @@ class GnoSafe extends React.PureComponent<SafeProps, State> {
|
||||
<Owners owners={safe.owners} />
|
||||
<Confirmations confirmations={safe.get('confirmations')} />
|
||||
<Address address={safe.get('address')} />
|
||||
<DailyLimit dailyLimit={safe.get('dailyLimit')} onWithdrawn={this.onWithdrawn} />
|
||||
<DailyLimit balance={balance} dailyLimit={safe.get('dailyLimit')} onWithdrawn={this.onWithdrawn} />
|
||||
<MultisigTx balance={balance} onAddTx={this.onAddTx} onSeeTxs={this.onListTransactions} />
|
||||
</List>
|
||||
</Col>
|
||||
|
@ -8,6 +8,7 @@ import { getGnosisSafeContract } from '~/wallets/safeContracts'
|
||||
import { getWeb3 } from '~/wallets/getWeb3'
|
||||
import { sameAddress } from '~/wallets/ethAddresses'
|
||||
import { EXECUTED_CONFIRMATION_HASH } from '~/routes/safe/component/AddTransaction/createTransactions'
|
||||
import executeTransaction from '~/wallets/ethTransactions'
|
||||
|
||||
export const updateTransaction = (
|
||||
name: string,
|
||||
@ -49,9 +50,9 @@ const execTransaction = async (
|
||||
const CALL = getOperation()
|
||||
const web3 = getWeb3()
|
||||
const valueInWei = web3.toWei(txValue, 'ether')
|
||||
const txReceipt = await gnosisSafe.execTransactionIfApproved(destination, valueInWei, data, CALL, nonce, { from: executor, gas: '5000000' })
|
||||
const txData = await gnosisSafe.contract.execTransactionIfApproved.getData(destination, valueInWei, data, CALL, nonce)
|
||||
|
||||
return txReceipt
|
||||
return executeTransaction(txData, executor, gnosisSafe.address)
|
||||
}
|
||||
|
||||
const execConfirmation = async (
|
||||
@ -65,9 +66,10 @@ const execConfirmation = async (
|
||||
const CALL = getOperation()
|
||||
const web3 = getWeb3()
|
||||
const valueInWei = web3.toWei(txValue, 'ether')
|
||||
const txConfirmationReceipt = await gnosisSafe.approveTransactionWithParameters(txDestination, valueInWei, data, CALL, nonce, { from: executor, gas: '5000000' })
|
||||
const txConfirmationData =
|
||||
await gnosisSafe.contract.approveTransactionWithParameters.getData(txDestination, valueInWei, data, CALL, nonce)
|
||||
|
||||
return txConfirmationReceipt
|
||||
return executeTransaction(txConfirmationData, executor, gnosisSafe.address)
|
||||
}
|
||||
|
||||
const updateConfirmations = (confirmations: List<Confirmation>, userAddress: string, txHash: string) =>
|
||||
@ -103,7 +105,7 @@ export const processTransaction = async (
|
||||
}
|
||||
|
||||
const threshold = tx.get('threshold')
|
||||
const thresholdReached = threshold >= alreadyConfirmed + 1
|
||||
const thresholdReached = threshold === alreadyConfirmed + 1
|
||||
const nonce = tx.get('nonce')
|
||||
const txName = tx.get('name')
|
||||
const txValue = tx.get('value')
|
||||
@ -113,7 +115,7 @@ export const processTransaction = async (
|
||||
? await execTransaction(gnosisSafe, txDestination, txValue, nonce, userAddress)
|
||||
: await execConfirmation(gnosisSafe, txDestination, txValue, nonce, userAddress)
|
||||
|
||||
const confirmationHash = thresholdReached ? EXECUTED_CONFIRMATION_HASH : txReceipt.tx
|
||||
const confirmationHash = thresholdReached ? EXECUTED_CONFIRMATION_HASH : txReceipt
|
||||
const executedConfirmations: List<Confirmation> = updateConfirmations(tx.get('confirmations'), userAddress, confirmationHash)
|
||||
|
||||
return updateTransaction(
|
||||
@ -123,7 +125,7 @@ export const processTransaction = async (
|
||||
txValue,
|
||||
userAddress,
|
||||
executedConfirmations,
|
||||
txReceipt.tx,
|
||||
thresholdReached ? txReceipt : '',
|
||||
safeAddress,
|
||||
threshold,
|
||||
)
|
||||
|
@ -2,6 +2,7 @@
|
||||
import { getWeb3 } from '~/wallets/getWeb3'
|
||||
import { getGnosisSafeContract, getCreateDailyLimitExtensionContract } from '~/wallets/safeContracts'
|
||||
import { type DailyLimitProps } from '~/routes/safe/store/model/dailyLimit'
|
||||
import executeTransaction from '~/wallets/ethTransactions'
|
||||
|
||||
export const LIMIT_POSITION = 0
|
||||
export const SPENT_TODAY_POS = 1
|
||||
@ -42,12 +43,9 @@ const withdrawn = async (values: Object, safeAddress: string, userAccount: strin
|
||||
const destination = values[DESTINATION_PARAM]
|
||||
const value = web3.toWei(values[VALUE_PARAM], 'ether')
|
||||
|
||||
return dailyLimitModule.executeDailyLimit(
|
||||
0,
|
||||
destination,
|
||||
value,
|
||||
{ from: userAccount, gas: '5000000' },
|
||||
)
|
||||
const dailyLimitData = dailyLimitModule.contract.executeDailyLimit.getData(0, destination, value)
|
||||
|
||||
return executeTransaction(dailyLimitData, userAccount, dailyLimitModule.address)
|
||||
}
|
||||
|
||||
export default withdrawn
|
||||
|
@ -8,10 +8,11 @@ import { DEPLOYED_COMPONENT_ID } from '~/routes/open/components/FormConfirmation
|
||||
import Open from '~/routes/open/container/Open'
|
||||
import { history, type GlobalState } from '~/store'
|
||||
import { sleep } from '~/utils/timer'
|
||||
import { getProviderInfo } from '~/wallets/getWeb3'
|
||||
import { getProviderInfo, getWeb3 } from '~/wallets/getWeb3'
|
||||
import addProvider from '~/wallets/store/actions/addProvider'
|
||||
import { makeProvider } from '~/wallets/store/model/provider'
|
||||
import withdrawn, { DESTINATION_PARAM, VALUE_PARAM } from '~/routes/safe/component/Withdrawn/withdrawn'
|
||||
import { promisify } from '~/utils/promisify'
|
||||
|
||||
export const renderSafe = async (localStore: Store<GlobalState>) => {
|
||||
const provider = await getProviderInfo()
|
||||
@ -29,20 +30,34 @@ export const renderSafe = async (localStore: Store<GlobalState>) => {
|
||||
)
|
||||
}
|
||||
|
||||
const deploySafe = async (safe: React$Component<{}>, dailyLimit: string) => {
|
||||
const deploySafe = async (safe: React$Component<{}>, dailyLimit: string, threshold: number, numOwners: number) => {
|
||||
expect(threshold).toBeLessThanOrEqual(numOwners)
|
||||
const inputs = TestUtils.scryRenderedDOMComponentsWithTag(safe, 'input')
|
||||
const fieldName = inputs[0]
|
||||
const fieldOwners = inputs[1]
|
||||
const fieldConfirmations = inputs[2]
|
||||
const fieldDailyLimit = inputs[3]
|
||||
|
||||
TestUtils.Simulate.change(fieldOwners, { target: { value: '1' } })
|
||||
const web3 = getWeb3()
|
||||
const accounts = await promisify(cb => web3.eth.getAccounts(cb))
|
||||
TestUtils.Simulate.change(fieldOwners, { target: { value: `${numOwners}` } })
|
||||
await sleep(800)
|
||||
const inputsExpanded = TestUtils.scryRenderedDOMComponentsWithTag(safe, 'input')
|
||||
const ownerName = inputsExpanded[2]
|
||||
expect(inputsExpanded.length).toBe((numOwners * 2) + 4) // 2 per owner + name, dailyLimit, confirmations, numOwners
|
||||
|
||||
for (let i = 0; i < numOwners; i += 1) {
|
||||
const nameIndex = (i * 2) + 2
|
||||
const addressIndex = (i * 2) + 3
|
||||
const ownerName = inputsExpanded[nameIndex]
|
||||
const account = inputsExpanded[addressIndex]
|
||||
|
||||
TestUtils.Simulate.change(ownerName, { target: { value: `Adolfo ${i + 1} Eth Account` } })
|
||||
TestUtils.Simulate.change(account, { target: { value: accounts[i] } })
|
||||
}
|
||||
|
||||
TestUtils.Simulate.change(fieldName, { target: { value: 'Adolfo Safe' } })
|
||||
TestUtils.Simulate.change(fieldConfirmations, { target: { value: '1' } })
|
||||
TestUtils.Simulate.change(ownerName, { target: { value: 'Adolfo Eth Account' } })
|
||||
TestUtils.Simulate.change(fieldConfirmations, { target: { value: `${threshold}` } })
|
||||
|
||||
TestUtils.Simulate.change(fieldDailyLimit, { target: { value: dailyLimit } })
|
||||
|
||||
const form = TestUtils.findRenderedDOMComponentWithTag(safe, 'form')
|
||||
@ -53,7 +68,7 @@ const deploySafe = async (safe: React$Component<{}>, dailyLimit: string) => {
|
||||
|
||||
// giving some time to the component for updating its state with safe
|
||||
// before destroying its context
|
||||
await sleep(3500)
|
||||
await sleep(9000)
|
||||
|
||||
// THEN
|
||||
const deployed = TestUtils.findRenderedDOMComponentWithClass(safe, DEPLOYED_COMPONENT_ID)
|
||||
@ -67,9 +82,14 @@ const deploySafe = async (safe: React$Component<{}>, dailyLimit: string) => {
|
||||
return transactionHash
|
||||
}
|
||||
|
||||
export const aDeployedSafe = async (specificStore: Store<GlobalState>, dailyLimit?: number = 0.5) => {
|
||||
export const aDeployedSafe = async (
|
||||
specificStore: Store<GlobalState>,
|
||||
dailyLimit?: number = 0.5,
|
||||
threshold?: number = 1,
|
||||
numOwners?: number = 1,
|
||||
) => {
|
||||
const safe: React$Component<{}> = await renderSafe(specificStore)
|
||||
const deployedSafe = await deploySafe(safe, `${dailyLimit}`)
|
||||
const deployedSafe = await deploySafe(safe, `${dailyLimit}`, threshold, numOwners)
|
||||
|
||||
return deployedSafe.logs[1].args.proxy
|
||||
}
|
||||
|
59
src/routes/safe/test/Safe.multisig.3owners1threshold.test.js
Normal file
59
src/routes/safe/test/Safe.multisig.3owners1threshold.test.js
Normal file
@ -0,0 +1,59 @@
|
||||
// @flow
|
||||
import * as React from 'react'
|
||||
import TestUtils from 'react-dom/test-utils'
|
||||
import { Provider } from 'react-redux'
|
||||
import { ConnectedRouter } from 'react-router-redux'
|
||||
import { aNewStore, history } from '~/store'
|
||||
import { aDeployedSafe } from '~/routes/safe/store/test/builder/deployedSafe.builder'
|
||||
import { SAFELIST_ADDRESS } from '~/routes/routes'
|
||||
import AppRoutes from '~/routes'
|
||||
import AddTransactionComponent from '~/routes/safe/component/AddTransaction'
|
||||
import { createMultisigTxFilling, addFundsTo, checkBalanceOf, listTxsOf, getTagFromTransaction, expandTransactionOf, getTransactionFromReduxStore, confirmOwners } from '~/routes/safe/test/testMultisig'
|
||||
|
||||
const renderSafe = localStore => (
|
||||
TestUtils.renderIntoDocument((
|
||||
<Provider store={localStore}>
|
||||
<ConnectedRouter history={history}>
|
||||
<AppRoutes />
|
||||
</ConnectedRouter>
|
||||
</Provider>
|
||||
))
|
||||
)
|
||||
|
||||
describe('React DOM TESTS > Multisig transactions from safe [3 owners & 1 threshold] ', () => {
|
||||
let SafeDom
|
||||
let store
|
||||
let address
|
||||
beforeEach(async () => {
|
||||
// create store
|
||||
store = aNewStore()
|
||||
// deploy safe updating store
|
||||
address = await aDeployedSafe(store, 10, 1, 3)
|
||||
// navigate to SAFE route
|
||||
history.push(`${SAFELIST_ADDRESS}/${address}`)
|
||||
SafeDom = renderSafe(store)
|
||||
})
|
||||
|
||||
it('should execute transaction straight away', async () => {
|
||||
await addFundsTo(SafeDom, address)
|
||||
await checkBalanceOf(address, '0.1')
|
||||
await createMultisigTxFilling(SafeDom, AddTransactionComponent, store)
|
||||
await checkBalanceOf(address, '0.09')
|
||||
await listTxsOf(SafeDom)
|
||||
|
||||
await expandTransactionOf(SafeDom, 3, 1)
|
||||
await confirmOwners(SafeDom, 'Adolfo 1 Eth Account [Confirmed]', 'Adolfo 2 Eth Account [Not confirmed]', 'Adolfo 3 Eth Account [Not confirmed]')
|
||||
|
||||
const paragraphs = getTagFromTransaction(SafeDom, 'p')
|
||||
|
||||
const status = paragraphs[2].innerHTML
|
||||
expect(status).toBe('Already executed')
|
||||
|
||||
const confirmed = paragraphs[3].innerHTML
|
||||
const tx = getTransactionFromReduxStore(store, address)
|
||||
expect(confirmed).toBe(tx.get('tx'))
|
||||
|
||||
const ownerTx = paragraphs[6].innerHTML
|
||||
expect(ownerTx).toBe('Confirmation hash: EXECUTED')
|
||||
})
|
||||
})
|
101
src/routes/safe/test/Safe.multisig.3owners3threshold.test.js
Normal file
101
src/routes/safe/test/Safe.multisig.3owners3threshold.test.js
Normal file
@ -0,0 +1,101 @@
|
||||
// @flow
|
||||
import * as React from 'react'
|
||||
import TestUtils from 'react-dom/test-utils'
|
||||
import { Provider } from 'react-redux'
|
||||
import { ConnectedRouter } from 'react-router-redux'
|
||||
import { aNewStore, history } from '~/store'
|
||||
import { aDeployedSafe } from '~/routes/safe/store/test/builder/deployedSafe.builder'
|
||||
import { SAFELIST_ADDRESS } from '~/routes/routes'
|
||||
import AppRoutes from '~/routes'
|
||||
import { getWeb3 } from '~/wallets/getWeb3'
|
||||
import { sleep } from '~/utils/timer'
|
||||
import { promisify } from '~/utils/promisify'
|
||||
import AddTransactionComponent from '~/routes/safe/component/AddTransaction'
|
||||
import { processTransaction } from '~/routes/safe/component/Transactions/processTransactions'
|
||||
import { confirmationsTransactionSelector } from '~/routes/safe/store/selectors/index'
|
||||
import fetchTransactions from '~/routes/safe/store/actions/fetchTransactions'
|
||||
import { createMultisigTxFilling, addFundsTo, checkBalanceOf, listTxsOf, getTagFromTransaction, expandTransactionOf, getTransactionFromReduxStore, confirmOwners } from '~/routes/safe/test/testMultisig'
|
||||
|
||||
const renderSafe = localStore => (
|
||||
TestUtils.renderIntoDocument((
|
||||
<Provider store={localStore}>
|
||||
<ConnectedRouter history={history}>
|
||||
<AppRoutes />
|
||||
</ConnectedRouter>
|
||||
</Provider>
|
||||
))
|
||||
)
|
||||
|
||||
describe('React DOM TESTS > Multisig transactions from safe [3 owners & 3 threshold] ', () => {
|
||||
let SafeDom
|
||||
let store
|
||||
let address
|
||||
let accounts
|
||||
beforeEach(async () => {
|
||||
// create store
|
||||
store = aNewStore()
|
||||
// deploy safe updating store
|
||||
address = await aDeployedSafe(store, 10, 3, 3)
|
||||
// navigate to SAFE route
|
||||
history.push(`${SAFELIST_ADDRESS}/${address}`)
|
||||
SafeDom = renderSafe(store)
|
||||
accounts = await promisify(cb => getWeb3().eth.getAccounts(cb))
|
||||
})
|
||||
|
||||
|
||||
const getAlreadyConfirmed = () => {
|
||||
const tx = getTransactionFromReduxStore(store, address)
|
||||
const confirmed = confirmationsTransactionSelector(store.getState(), { transaction: tx })
|
||||
|
||||
return confirmed
|
||||
}
|
||||
|
||||
const makeConfirmation = async (executor) => {
|
||||
const alreadyConfirmed = getAlreadyConfirmed()
|
||||
const tx = getTransactionFromReduxStore(store, address)
|
||||
await processTransaction(address, tx, alreadyConfirmed, executor)
|
||||
await sleep(800)
|
||||
store.dispatch(fetchTransactions())
|
||||
sleep(1800)
|
||||
SafeDom = renderSafe(store)
|
||||
sleep(1800)
|
||||
await listTxsOf(SafeDom)
|
||||
sleep(800)
|
||||
await expandTransactionOf(SafeDom, 3, 3)
|
||||
sleep(800)
|
||||
}
|
||||
|
||||
it('should execute transaction after 2 owners have confirmed and the last one executed correctly', async () => {
|
||||
await addFundsTo(SafeDom, address)
|
||||
await createMultisigTxFilling(SafeDom, AddTransactionComponent, store)
|
||||
|
||||
await checkBalanceOf(address, '0.1')
|
||||
await listTxsOf(SafeDom)
|
||||
sleep(1400)
|
||||
const paragraphs = getTagFromTransaction(SafeDom, 'p')
|
||||
|
||||
const status = paragraphs[2].innerHTML
|
||||
expect(status).toBe('1 of the 3 confirmations needed')
|
||||
|
||||
const confirmed = paragraphs[3].innerHTML
|
||||
expect(confirmed).toBe('Waiting for the rest of confirmations')
|
||||
|
||||
await expandTransactionOf(SafeDom, 3, 3)
|
||||
await confirmOwners(SafeDom, 'Adolfo 1 Eth Account [Confirmed]', 'Adolfo 2 Eth Account [Not confirmed]', 'Adolfo 3 Eth Account [Not confirmed]')
|
||||
|
||||
await makeConfirmation(accounts[1])
|
||||
await confirmOwners(SafeDom, 'Adolfo 1 Eth Account [Confirmed]', 'Adolfo 2 Eth Account [Confirmed]', 'Adolfo 3 Eth Account [Not confirmed]')
|
||||
|
||||
await makeConfirmation(accounts[2])
|
||||
await confirmOwners(SafeDom, 'Adolfo 1 Eth Account [Confirmed]', 'Adolfo 2 Eth Account [Confirmed]', 'Adolfo 3 Eth Account [Confirmed]')
|
||||
|
||||
const paragraphsExecuted = getTagFromTransaction(SafeDom, 'p')
|
||||
|
||||
const statusExecuted = paragraphsExecuted[2].innerHTML
|
||||
expect(statusExecuted).toBe('Already executed')
|
||||
|
||||
const confirmedExecuted = paragraphsExecuted[3].innerHTML
|
||||
const tx = getTransactionFromReduxStore(store, address)
|
||||
expect(confirmedExecuted).toBe(tx.get('tx'))
|
||||
})
|
||||
})
|
@ -41,6 +41,7 @@ describe('React DOM TESTS > Withdrawn funds from safe', () => {
|
||||
it('should withdrawn funds under dailyLimit without needing confirmations', async () => {
|
||||
// add funds to safe
|
||||
await addEtherTo(address, '0.1')
|
||||
await sleep(3000)
|
||||
const Safe = TestUtils.findRenderedComponentWithType(SafeDom, SafeView)
|
||||
|
||||
// $FlowFixMe
|
||||
@ -48,7 +49,7 @@ describe('React DOM TESTS > Withdrawn funds from safe', () => {
|
||||
const withdrawnButton = buttons[0]
|
||||
expect(withdrawnButton.props.children).toEqual(WITHDRAWN_BUTTON_TEXT)
|
||||
TestUtils.Simulate.click(TestUtils.scryRenderedDOMComponentsWithTag(withdrawnButton, 'button')[0])
|
||||
|
||||
await sleep(4000)
|
||||
const Withdrawn = TestUtils.findRenderedComponentWithType(SafeDom, WithdrawnComponent)
|
||||
|
||||
// $FlowFixMe
|
||||
@ -63,7 +64,7 @@ describe('React DOM TESTS > Withdrawn funds from safe', () => {
|
||||
|
||||
TestUtils.Simulate.submit(form) // fill the form
|
||||
TestUtils.Simulate.submit(form) // confirming data
|
||||
await sleep(4000)
|
||||
await sleep(6000)
|
||||
|
||||
const safeBalance = await getBalanceInEtherOf(address)
|
||||
expect(safeBalance).toBe('0.09')
|
||||
@ -104,4 +105,18 @@ describe('React DOM TESTS > Withdrawn funds from safe', () => {
|
||||
|
||||
expect(addTxButton.props.disabled).toBe(false)
|
||||
})
|
||||
|
||||
it('Withdrawn button disabled when balance is 0', async () => {
|
||||
const Safe = TestUtils.findRenderedComponentWithType(SafeDom, SafeView)
|
||||
// $FlowFixMe
|
||||
const buttons = TestUtils.scryRenderedComponentsWithType(Safe, Button)
|
||||
const addTxButton = buttons[0]
|
||||
expect(addTxButton.props.children).toEqual(WITHDRAWN_BUTTON_TEXT)
|
||||
expect(addTxButton.props.disabled).toBe(true)
|
||||
|
||||
await addEtherTo(address, '0.1')
|
||||
await sleep(1800)
|
||||
|
||||
expect(addTxButton.props.disabled).toBe(false)
|
||||
})
|
||||
})
|
96
src/routes/safe/test/testMultisig.js
Normal file
96
src/routes/safe/test/testMultisig.js
Normal file
@ -0,0 +1,96 @@
|
||||
// @flow
|
||||
import TestUtils from 'react-dom/test-utils'
|
||||
import { sleep } from '~/utils/timer'
|
||||
import { getBalanceInEtherOf } from '~/wallets/getWeb3'
|
||||
import Button from '~/components/layout/Button'
|
||||
import { ADD_MULTISIG_BUTTON_TEXT, SEE_MULTISIG_BUTTON_TEXT } from '~/routes/safe/component/Safe/MultisigTx'
|
||||
import { addEtherTo } from '~/test/addEtherTo'
|
||||
import SafeView from '~/routes/safe/component/Safe'
|
||||
import TransactionsComponent from '~/routes/safe/component/Transactions'
|
||||
import TransactionComponent from '~/routes/safe/component/Transactions/Transaction'
|
||||
import { safeTransactionsSelector } from '~/routes/safe/store/selectors/index'
|
||||
|
||||
export const createMultisigTxFilling = async (SafeDom, AddTransactionComponent, store) => {
|
||||
// Get AddTransaction form component
|
||||
const AddTransaction = TestUtils.findRenderedComponentWithType(SafeDom, AddTransactionComponent)
|
||||
|
||||
// $FlowFixMe
|
||||
const inputs = TestUtils.scryRenderedDOMComponentsWithTag(AddTransaction, 'input')
|
||||
const name = inputs[0]
|
||||
const destination = inputs[1]
|
||||
const amountInEth = inputs[2]
|
||||
TestUtils.Simulate.change(name, { target: { value: 'Buying betteries' } })
|
||||
TestUtils.Simulate.change(amountInEth, { target: { value: '0.01' } })
|
||||
TestUtils.Simulate.change(destination, { target: { value: store.getState().providers.account } })
|
||||
|
||||
// $FlowFixMe
|
||||
const form = TestUtils.findRenderedDOMComponentWithTag(AddTransaction, 'form')
|
||||
|
||||
TestUtils.Simulate.submit(form) // fill the form
|
||||
TestUtils.Simulate.submit(form) // confirming data
|
||||
return sleep(4000)
|
||||
}
|
||||
|
||||
export const checkBalanceOf = async (addressToTest: string, value: string) => {
|
||||
const safeBalance = await getBalanceInEtherOf(addressToTest)
|
||||
expect(safeBalance).toBe(value)
|
||||
}
|
||||
|
||||
export const addFundsTo = async (SafeDom, destination: string) => {
|
||||
// add funds to safe
|
||||
await addEtherTo(destination, '0.1')
|
||||
const Safe = TestUtils.findRenderedComponentWithType(SafeDom, SafeView)
|
||||
|
||||
// $FlowFixMe
|
||||
const buttons = TestUtils.scryRenderedComponentsWithType(Safe, Button)
|
||||
const addTxButton = buttons[1]
|
||||
expect(addTxButton.props.children).toEqual(ADD_MULTISIG_BUTTON_TEXT)
|
||||
await sleep(1800) // Give time to enable Add button
|
||||
TestUtils.Simulate.click(TestUtils.scryRenderedDOMComponentsWithTag(addTxButton, 'button')[0])
|
||||
}
|
||||
|
||||
export const listTxsOf = (SafeDom) => {
|
||||
const Safe = TestUtils.findRenderedComponentWithType(SafeDom, SafeView)
|
||||
|
||||
// $FlowFixMe
|
||||
const buttons = TestUtils.scryRenderedComponentsWithType(Safe, Button)
|
||||
const seeTx = buttons[2]
|
||||
expect(seeTx.props.children).toEqual(SEE_MULTISIG_BUTTON_TEXT)
|
||||
TestUtils.Simulate.click(TestUtils.scryRenderedDOMComponentsWithTag(seeTx, 'button')[0])
|
||||
}
|
||||
|
||||
export const getTagFromTransaction = (SafeDom, tag: string) => {
|
||||
const Transactions = TestUtils.findRenderedComponentWithType(SafeDom, TransactionsComponent)
|
||||
if (!Transactions) throw new Error()
|
||||
const Transaction = TestUtils.findRenderedComponentWithType(Transactions, TransactionComponent)
|
||||
if (!Transaction) throw new Error()
|
||||
|
||||
return TestUtils.scryRenderedDOMComponentsWithTag(Transaction, tag)
|
||||
}
|
||||
|
||||
export const expandTransactionOf = async (SafeDom, numOwners, safeThreshold) => {
|
||||
const paragraphs = getTagFromTransaction(SafeDom, 'p')
|
||||
TestUtils.Simulate.click(paragraphs[2]) // expanded
|
||||
await sleep(1000) // Time to expand
|
||||
const paragraphsExpanded = getTagFromTransaction(SafeDom, 'p')
|
||||
const threshold = paragraphsExpanded[5]
|
||||
expect(threshold.innerHTML).toContain(`confirmation${safeThreshold === 1 ? '' : 's'} needed`)
|
||||
TestUtils.Simulate.click(threshold) // expanded
|
||||
await sleep(1000) // Time to expand
|
||||
expect(paragraphsExpanded.length).toBe(paragraphs.length + numOwners)
|
||||
}
|
||||
|
||||
export const getTransactionFromReduxStore = (store, address) => {
|
||||
const transactions = safeTransactionsSelector(store.getState(), { safeAddress: address })
|
||||
|
||||
return transactions.get(0)
|
||||
}
|
||||
|
||||
export const confirmOwners = async (SafeDom, ...statusses: string[]) => {
|
||||
const paragraphsWithOwners = getTagFromTransaction(SafeDom, 'h3')
|
||||
for (let i = 0; i < statusses.length; i += 1) {
|
||||
const ownerIndex = i + 6
|
||||
const ownerParagraph = paragraphsWithOwners[ownerIndex].innerHTML
|
||||
expect(statusses[i]).toEqual(ownerParagraph)
|
||||
}
|
||||
}
|
53
src/wallets/ethTransactions.js
Normal file
53
src/wallets/ethTransactions.js
Normal file
@ -0,0 +1,53 @@
|
||||
// @flow
|
||||
import { BigNumber } from 'bignumber.js'
|
||||
import { getWeb3 } from '~/wallets/getWeb3'
|
||||
import { promisify } from '~/utils/promisify'
|
||||
|
||||
// const MAINNET_NETWORK = 1
|
||||
|
||||
export const calculateGasPrice = async () => {
|
||||
/*
|
||||
const web3 = getWeb3()
|
||||
const { network } = web3.version
|
||||
const isMainnet = MAINNET_NETWORK === network
|
||||
|
||||
const url = isMainnet
|
||||
? 'https://safe-relay.staging.gnosisdev.com/api/v1/gas-station/'
|
||||
: 'https://safe-relay.dev.gnosisdev.com/'
|
||||
*/
|
||||
|
||||
const response = await fetch('https://ethgasstation.info/json/ethgasAPI.json', { mode: 'cors' })
|
||||
if (!response.ok) {
|
||||
throw new Error('Error querying gast station')
|
||||
}
|
||||
|
||||
const json = await response.json()
|
||||
|
||||
return new BigNumber(json.average).multipliedBy(1e8).toString()
|
||||
}
|
||||
|
||||
export const calculateGasOf = async (data: Object, from: string, to: string) => {
|
||||
const web3 = getWeb3()
|
||||
const gas = await promisify(cb => web3.eth.estimateGas({ data, from, to }, cb))
|
||||
|
||||
return gas * 2
|
||||
}
|
||||
|
||||
const executeTransaction = async (data: Object, from: string, to: string) => {
|
||||
const web3 = getWeb3()
|
||||
|
||||
const gas = await calculateGasOf(data, from, to)
|
||||
|
||||
let gasPrice
|
||||
try {
|
||||
gasPrice = await calculateGasPrice()
|
||||
} catch (err) {
|
||||
gasPrice = await promisify(cb => web3.eth.getGasPrice(cb))
|
||||
}
|
||||
|
||||
return promisify(cb => web3.eth.sendTransaction({
|
||||
from, to, data, gas, gasPrice,
|
||||
}, cb))
|
||||
}
|
||||
|
||||
export default executeTransaction
|
@ -28,8 +28,11 @@ export const getProviderInfo: Function = async (): Promise<ProviderProps> => {
|
||||
|
||||
// Use MetaMask's provider.
|
||||
web3 = new Web3(window.web3.currentProvider)
|
||||
// eslint-disable-next-line
|
||||
console.log('Injected web3 detected.')
|
||||
|
||||
if (process.env.NODE_ENV !== 'test') {
|
||||
// eslint-disable-next-line
|
||||
console.log('Injected web3 detected.')
|
||||
}
|
||||
|
||||
const name = isMetamask(web3) ? 'METAMASK' : 'UNKNOWN'
|
||||
const account = await getAccountFrom(web3)
|
||||
|
@ -1,12 +1,13 @@
|
||||
// @flow
|
||||
import contract from 'truffle-contract'
|
||||
import { promisify } from '~/utils/promisify'
|
||||
import { ensureOnce } from '~/utils/singleton'
|
||||
import { getWeb3 } from '~/wallets/getWeb3'
|
||||
import { promisify } from '~/utils/promisify'
|
||||
import GnosisSafeSol from '#/GnosisSafeTeamEdition.json'
|
||||
import ProxyFactorySol from '#/ProxyFactory.json'
|
||||
import CreateAndAddModules from '#/CreateAndAddModules.json'
|
||||
import DailyLimitModule from '#/DailyLimitModule.json'
|
||||
import { calculateGasOf, calculateGasPrice } from '~/wallets/ethTransactions'
|
||||
|
||||
let proxyFactoryMaster
|
||||
let createAndAddModuleMaster
|
||||
@ -63,45 +64,46 @@ const getCreateProxyFactoryContract = ensureOnce(createProxyFactoryContract)
|
||||
const getCreateAddExtensionContract = ensureOnce(createAddExtensionContract)
|
||||
export const getCreateDailyLimitExtensionContract = ensureOnce(createDailyLimitExtensionContract)
|
||||
|
||||
const instanciateMasterCopies = async () => {
|
||||
const web3 = getWeb3()
|
||||
|
||||
// Create ProxyFactory Master Copy
|
||||
const ProxyFactory = getCreateProxyFactoryContract(web3)
|
||||
proxyFactoryMaster = await ProxyFactory.deployed()
|
||||
|
||||
// Create AddExtension Master Copy
|
||||
const CreateAndAddExtension = getCreateAddExtensionContract(web3)
|
||||
createAndAddModuleMaster = await CreateAndAddExtension.deployed()
|
||||
|
||||
// Initialize safe master copy
|
||||
const GnosisSafe = getGnosisSafeContract(web3)
|
||||
safeMaster = await GnosisSafe.deployed()
|
||||
|
||||
// Initialize extension master copy
|
||||
const DailyLimitExtension = getCreateDailyLimitExtensionContract(web3)
|
||||
dailyLimitMaster = await DailyLimitExtension.deployed()
|
||||
}
|
||||
|
||||
// ONLY USED IN TEST ENVIRONMENT
|
||||
const createMasterCopies = async () => {
|
||||
const web3 = getWeb3()
|
||||
const accounts = await promisify(cb => web3.eth.getAccounts(cb))
|
||||
const userAccount = accounts[0]
|
||||
|
||||
// Create ProxyFactory Master Copy
|
||||
const ProxyFactory = getCreateProxyFactoryContract(web3)
|
||||
try {
|
||||
proxyFactoryMaster = await ProxyFactory.deployed()
|
||||
} catch (err) {
|
||||
proxyFactoryMaster = await ProxyFactory.new({ from: userAccount, gas: '5000000' })
|
||||
}
|
||||
proxyFactoryMaster = await ProxyFactory.new({ from: userAccount, gas: '5000000' })
|
||||
|
||||
// Create AddExtension Master Copy
|
||||
const CreateAndAddExtension = getCreateAddExtensionContract(web3)
|
||||
try {
|
||||
createAndAddModuleMaster = await CreateAndAddExtension.deployed()
|
||||
} catch (err) {
|
||||
createAndAddModuleMaster = await CreateAndAddExtension.new({ from: userAccount, gas: '5000000' })
|
||||
}
|
||||
createAndAddModuleMaster = await CreateAndAddExtension.new({ from: userAccount, gas: '5000000' })
|
||||
|
||||
// Initialize safe master copy
|
||||
const GnosisSafe = getGnosisSafeContract(web3)
|
||||
try {
|
||||
safeMaster = await GnosisSafe.deployed()
|
||||
} catch (err) {
|
||||
safeMaster = await GnosisSafe.new([userAccount], 1, 0, 0, { from: userAccount, gas: '5000000' })
|
||||
}
|
||||
safeMaster = await GnosisSafe.new([userAccount], 1, 0, 0, { from: userAccount, gas: '5000000' })
|
||||
|
||||
// Initialize extension master copy
|
||||
const DailyLimitExtension = getCreateDailyLimitExtensionContract(web3)
|
||||
try {
|
||||
dailyLimitMaster = await DailyLimitExtension.deployed()
|
||||
} catch (err) {
|
||||
dailyLimitMaster = await DailyLimitExtension.new([], [], { from: userAccount, gas: '5000000' })
|
||||
}
|
||||
dailyLimitMaster = await DailyLimitExtension.new([], [], { from: userAccount, gas: '5000000' })
|
||||
}
|
||||
|
||||
export const initContracts = ensureOnce(createMasterCopies)
|
||||
export const initContracts = ensureOnce(process.env.NODE_ENV === 'test' ? createMasterCopies : instanciateMasterCopies)
|
||||
|
||||
const getSafeDataBasedOn = async (accounts, numConfirmations, dailyLimitInEth) => {
|
||||
const web3 = getWeb3()
|
||||
@ -128,5 +130,9 @@ export const deploySafeContract = async (
|
||||
userAccount: string,
|
||||
) => {
|
||||
const gnosisSafeData = await getSafeDataBasedOn(safeAccounts, numConfirmations, dailyLimit)
|
||||
return proxyFactoryMaster.createProxy(safeMaster.address, gnosisSafeData, { from: userAccount, gas: '5000000' })
|
||||
const proxyFactoryData = proxyFactoryMaster.contract.createProxy.getData(safeMaster.address, gnosisSafeData)
|
||||
const gas = await calculateGasOf(proxyFactoryData, userAccount, proxyFactoryMaster.address)
|
||||
const gasPrice = await calculateGasPrice()
|
||||
|
||||
return proxyFactoryMaster.createProxy(safeMaster.address, gnosisSafeData, { from: userAccount, gas, gasPrice })
|
||||
}
|
||||
|
@ -2474,6 +2474,10 @@ bignumber.js@^2.1.4:
|
||||
version "2.4.0"
|
||||
resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-2.4.0.tgz#838a992da9f9d737e0f4b2db0be62bb09dd0c5e8"
|
||||
|
||||
bignumber.js@^7.2.1:
|
||||
version "7.2.1"
|
||||
resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-7.2.1.tgz#80c048759d826800807c4bfd521e50edbba57a5f"
|
||||
|
||||
"bignumber.js@git+https://github.com/debris/bignumber.js#master":
|
||||
version "2.0.7"
|
||||
resolved "git+https://github.com/debris/bignumber.js#c7a38de919ed75e6fb6ba38051986e294b328df9"
|
||||
|
Loading…
x
Reference in New Issue
Block a user