send transaction for threshold = 1
This commit is contained in:
parent
051f26aa76
commit
7a8a69b528
|
@ -1,4 +1,5 @@
|
||||||
// @flow
|
// @flow
|
||||||
export * from './gas'
|
export * from './gas'
|
||||||
|
export * from './send'
|
||||||
export * from './safeBlockchainOperations'
|
export * from './safeBlockchainOperations'
|
||||||
export * from './safeTxSignerEIP712'
|
export * from './safeTxSignerEIP712'
|
||||||
|
|
|
@ -54,89 +54,89 @@ export const approveTransaction = async (
|
||||||
return txHash
|
return txHash
|
||||||
}
|
}
|
||||||
|
|
||||||
export const executeTransaction = async (
|
// export const executeTransaction = async (
|
||||||
safeAddress: string,
|
// safeAddress: string,
|
||||||
to: string,
|
// to: string,
|
||||||
valueInWei: number,
|
// valueInWei: number,
|
||||||
data: string,
|
// data: string,
|
||||||
operation: Operation,
|
// operation: Operation,
|
||||||
nonce: number,
|
// nonce: number,
|
||||||
sender: string,
|
// sender: string,
|
||||||
ownersWhoHasSigned: List<string>,
|
// ownersWhoHasSigned: List<string>,
|
||||||
) => {
|
// ) => {
|
||||||
const gasPrice = await calculateGasPrice()
|
// const gasPrice = await calculateGasPrice()
|
||||||
|
|
||||||
if (signaturesViaMetamask()) {
|
// if (signaturesViaMetamask()) {
|
||||||
const safe = await getSafeEthereumInstance(safeAddress)
|
// const safe = await getSafeEthereumInstance(safeAddress)
|
||||||
const txGasEstimate = await generateTxGasEstimateFrom(safe, safeAddress, data, to, valueInWei, operation)
|
// const txGasEstimate = await generateTxGasEstimateFrom(safe, safeAddress, data, to, valueInWei, operation)
|
||||||
const signature = await generateMetamaskSignature(
|
// const signature = await generateMetamaskSignature(
|
||||||
safe,
|
// safe,
|
||||||
safeAddress,
|
// safeAddress,
|
||||||
sender,
|
// sender,
|
||||||
to,
|
// to,
|
||||||
valueInWei,
|
// valueInWei,
|
||||||
nonce,
|
// nonce,
|
||||||
data,
|
// data,
|
||||||
operation,
|
// operation,
|
||||||
txGasEstimate,
|
// txGasEstimate,
|
||||||
)
|
// )
|
||||||
storeSignature(safeAddress, nonce, signature)
|
// storeSignature(safeAddress, nonce, signature)
|
||||||
|
|
||||||
const sigs = getSignaturesFrom(safeAddress, nonce)
|
// const sigs = getSignaturesFrom(safeAddress, nonce)
|
||||||
const threshold = await safe.getThreshold()
|
// const threshold = await safe.getThreshold()
|
||||||
const gas = await estimateDataGas(
|
// const gas = await estimateDataGas(
|
||||||
safe,
|
// safe,
|
||||||
to,
|
// to,
|
||||||
valueInWei,
|
// valueInWei,
|
||||||
data,
|
// data,
|
||||||
operation,
|
// operation,
|
||||||
txGasEstimate,
|
// txGasEstimate,
|
||||||
0,
|
// 0,
|
||||||
nonce,
|
// nonce,
|
||||||
Number(threshold),
|
// Number(threshold),
|
||||||
0,
|
// 0,
|
||||||
)
|
// )
|
||||||
const numOwners = await safe.getOwners()
|
// const numOwners = await safe.getOwners()
|
||||||
const gasIncludingRemovingStoreUpfront = gas + txGasEstimate + numOwners.length * 15000
|
// const gasIncludingRemovingStoreUpfront = gas + txGasEstimate + numOwners.length * 15000
|
||||||
|
|
||||||
const txReceipt = await safe.execTransaction(
|
// const txReceipt = await safe.execTransaction(
|
||||||
to,
|
// to,
|
||||||
valueInWei,
|
// valueInWei,
|
||||||
data,
|
// data,
|
||||||
operation,
|
// operation,
|
||||||
txGasEstimate,
|
// txGasEstimate,
|
||||||
0, // dataGasEstimate
|
// 0, // dataGasEstimate
|
||||||
0, // gasPrice
|
// 0, // gasPrice
|
||||||
0, // txGasToken
|
// 0, // txGasToken
|
||||||
0, // refundReceiver
|
// 0, // refundReceiver
|
||||||
sigs,
|
// sigs,
|
||||||
{ from: sender, gas: gasIncludingRemovingStoreUpfront, gasPrice },
|
// { from: sender, gas: gasIncludingRemovingStoreUpfront, gasPrice },
|
||||||
)
|
// )
|
||||||
|
|
||||||
const txHash = txReceipt.tx
|
// const txHash = txReceipt.tx
|
||||||
await checkReceiptStatus(txHash)
|
// await checkReceiptStatus(txHash)
|
||||||
// await submitOperation(safeAddress, to, valueInWei, data, operation, nonce, txHash, sender, 'execution')
|
// // await submitOperation(safeAddress, to, valueInWei, data, operation, nonce, txHash, sender, 'execution')
|
||||||
|
|
||||||
return txHash
|
// return txHash
|
||||||
}
|
// }
|
||||||
|
|
||||||
const gnosisSafe = await getSafeEthereumInstance(safeAddress)
|
// const gnosisSafe = await getSafeEthereumInstance(safeAddress)
|
||||||
const signatures = buildSignaturesFrom(ownersWhoHasSigned, sender)
|
// const signatures = buildSignaturesFrom(ownersWhoHasSigned, sender)
|
||||||
const txExecutionData = gnosisSafe.contract.methods
|
// const txExecutionData = gnosisSafe.contract.methods
|
||||||
.execTransaction(to, valueInWei, data, operation, 0, 0, 0, 0, 0, signatures)
|
// .execTransaction(to, valueInWei, data, operation, 0, 0, 0, 0, 0, signatures)
|
||||||
.encodeABI()
|
// .encodeABI()
|
||||||
const gas = await calculateGasOf(txExecutionData, sender, safeAddress)
|
// const gas = await calculateGasOf(txExecutionData, sender, safeAddress)
|
||||||
const numOwners = await gnosisSafe.getOwners()
|
// const numOwners = await gnosisSafe.getOwners()
|
||||||
const gasIncludingRemovingStoreUpfront = gas + numOwners.length * 15000
|
// const gasIncludingRemovingStoreUpfront = gas + numOwners.length * 15000
|
||||||
const txReceipt = await gnosisSafe.execTransaction(to, valueInWei, data, operation, 0, 0, 0, 0, 0, signatures, {
|
// const txReceipt = await gnosisSafe.execTransaction(to, valueInWei, data, operation, 0, 0, 0, 0, 0, signatures, {
|
||||||
from: sender,
|
// from: sender,
|
||||||
gas: gasIncludingRemovingStoreUpfront,
|
// gas: gasIncludingRemovingStoreUpfront,
|
||||||
gasPrice,
|
// gasPrice,
|
||||||
})
|
// })
|
||||||
const txHash = txReceipt.tx
|
// const txHash = txReceipt.tx
|
||||||
await checkReceiptStatus(txHash)
|
// await checkReceiptStatus(txHash)
|
||||||
|
|
||||||
await submitOperation(safeAddress, to, valueInWei, data, operation, nonce, txHash, sender, 'execution')
|
// await submitOperation(safeAddress, to, valueInWei, data, operation, nonce, txHash, sender, 'execution')
|
||||||
|
|
||||||
return txHash
|
// return txHash
|
||||||
}
|
// }
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
// @flow
|
||||||
|
import { getWeb3 } from '~/logic/wallets/getWeb3'
|
||||||
|
import { getStandardTokenContract } from '~/logic/tokens/store/actions/fetchTokens'
|
||||||
|
import { EMPTY_DATA } from '~/logic/wallets/ethTransactions'
|
||||||
|
import { isEther } from '~/logic/tokens/utils/tokenHelpers'
|
||||||
|
import { type Token } from '~/logic/tokens/store/model/token'
|
||||||
|
import { getSafeEthereumInstance } from '../safeFrontendOperations'
|
||||||
|
|
||||||
|
const CALL = 0
|
||||||
|
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'
|
||||||
|
|
||||||
|
export const executeTransaction = async (
|
||||||
|
safeInstance: any,
|
||||||
|
to: string,
|
||||||
|
valueInWei: number,
|
||||||
|
data: string,
|
||||||
|
operation: number | string,
|
||||||
|
nonce: string | number,
|
||||||
|
sender: string,
|
||||||
|
) => {
|
||||||
|
try {
|
||||||
|
// https://gnosis-safe.readthedocs.io/en/latest/contracts/signatures.html#pre-validated-signatures
|
||||||
|
const sigs = `0x000000000000000000000000${sender.replace(
|
||||||
|
'0x',
|
||||||
|
'',
|
||||||
|
)}000000000000000000000000000000000000000000000000000000000000000001`
|
||||||
|
|
||||||
|
const tx = await safeInstance.execTransaction(
|
||||||
|
to,
|
||||||
|
valueInWei,
|
||||||
|
data,
|
||||||
|
CALL,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
ZERO_ADDRESS,
|
||||||
|
ZERO_ADDRESS,
|
||||||
|
sigs,
|
||||||
|
{ from: sender },
|
||||||
|
)
|
||||||
|
|
||||||
|
return tx
|
||||||
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line
|
||||||
|
console.log('Error calculating tx gas estimation ' + error)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createTransaction = async (safeAddress: string, to: string, valueInEth: string, token: Token) => {
|
||||||
|
const safeInstance = await getSafeEthereumInstance(safeAddress)
|
||||||
|
const web3 = getWeb3()
|
||||||
|
const from = web3.currentProvider.selectedAddress
|
||||||
|
const threshold = await safeInstance.getThreshold()
|
||||||
|
const nonce = await safeInstance.nonce()
|
||||||
|
const valueInWei = web3.utils.toWei(valueInEth, 'ether')
|
||||||
|
const isExecution = threshold.toNumber() === 1
|
||||||
|
|
||||||
|
let txData = EMPTY_DATA
|
||||||
|
if (!isEther(token.symbol)) {
|
||||||
|
const StandardToken = await getStandardTokenContract()
|
||||||
|
const sendToken = await StandardToken.at(token.address)
|
||||||
|
|
||||||
|
txData = sendToken.contract.transfer(to, valueInWei).encodeABI()
|
||||||
|
}
|
||||||
|
|
||||||
|
let txHash
|
||||||
|
if (isExecution) {
|
||||||
|
txHash = await executeTransaction(safeInstance, to, valueInWei, txData, CALL, nonce, from)
|
||||||
|
} else {
|
||||||
|
// txHash = await approveTransaction(safeAddress, to, valueInWei, txData, CALL, nonce)
|
||||||
|
}
|
||||||
|
|
||||||
|
return txHash
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ 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,
|
||||||
|
@ -97,8 +98,18 @@ const ReviewTx = ({
|
||||||
<Button className={classes.button} minWidth={140} onClick={onClickBack}>
|
<Button className={classes.button} minWidth={140} onClick={onClickBack}>
|
||||||
Back
|
Back
|
||||||
</Button>
|
</Button>
|
||||||
<Button type="submit" className={classes.button} variant="contained" minWidth={140} color="primary">
|
<Button
|
||||||
Review
|
type="submit"
|
||||||
|
className={classes.button}
|
||||||
|
onClick={async () => {
|
||||||
|
await createTransaction(safeAddress, tx.recipientAddress, tx.amount, tx.token)
|
||||||
|
onClose()
|
||||||
|
}}
|
||||||
|
variant="contained"
|
||||||
|
minWidth={140}
|
||||||
|
color="primary"
|
||||||
|
>
|
||||||
|
SUBMIT
|
||||||
</Button>
|
</Button>
|
||||||
</Row>
|
</Row>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
|
|
10
yarn.lock
10
yarn.lock
|
@ -13671,7 +13671,7 @@ react-event-listener@^0.6.2:
|
||||||
prop-types "^15.6.0"
|
prop-types "^15.6.0"
|
||||||
warning "^4.0.1"
|
warning "^4.0.1"
|
||||||
|
|
||||||
react-fast-compare@^2.0.2, react-fast-compare@^2.0.3:
|
react-fast-compare@^2.0.2:
|
||||||
version "2.0.4"
|
version "2.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9"
|
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9"
|
||||||
integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==
|
integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==
|
||||||
|
@ -18371,14 +18371,6 @@ which@^1.2.14, which@^1.2.9, which@^1.3.0, which@^1.3.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
isexe "^2.0.0"
|
isexe "^2.0.0"
|
||||||
|
|
||||||
why-did-you-update@^1.0.6:
|
|
||||||
version "1.0.6"
|
|
||||||
resolved "https://registry.yarnpkg.com/why-did-you-update/-/why-did-you-update-1.0.6.tgz#2e2c6a04291e715755ecdff1ac8272f721df6f04"
|
|
||||||
integrity sha512-XVrdHhdrPBDuSW8b/uH6DCb1/0984qv8KElpE8NZiRvWZX8nw49av577+ZyIrxSNesi6r2cQEhpxQTKFFHTj8A==
|
|
||||||
dependencies:
|
|
||||||
lodash "^4.17.11"
|
|
||||||
react-fast-compare "^2.0.3"
|
|
||||||
|
|
||||||
wide-align@^1.1.0:
|
wide-align@^1.1.0:
|
||||||
version "1.1.3"
|
version "1.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457"
|
resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457"
|
||||||
|
|
Loading…
Reference in New Issue