mirror of
https://github.com/status-im/safe-react.git
synced 2025-02-04 22:03:41 +00:00
(Fix) - Calculates gas for SpendingLimit transactions (#1773)
* Bug: Use link tag instead of javascript navigation in apps list (#1770) * Use list instead of programmable navigation * add declaration for styled-components theme * (Fix) - Calculates gas for SpendingLimit transactions (#1773) * Calculates gas for spendingLimit transactions * Adds TransactionFees component inside UpdateSafeModal * Fix send collectible gas calculation Co-authored-by: Mikhail Mikheev <mmvsha73@gmail.com>
This commit is contained in:
parent
8a774f2e66
commit
10f1891f8f
@ -21,6 +21,7 @@ import { List } from 'immutable'
|
|||||||
import { Confirmation } from 'src/logic/safe/store/models/types/confirmation'
|
import { Confirmation } from 'src/logic/safe/store/models/types/confirmation'
|
||||||
import { checkIfOffChainSignatureIsPossible } from 'src/logic/safe/safeTxSigner'
|
import { checkIfOffChainSignatureIsPossible } from 'src/logic/safe/safeTxSigner'
|
||||||
import { ZERO_ADDRESS } from 'src/logic/wallets/ethAddresses'
|
import { ZERO_ADDRESS } from 'src/logic/wallets/ethAddresses'
|
||||||
|
import { sameString } from 'src/utils/strings'
|
||||||
|
|
||||||
export enum EstimationStatus {
|
export enum EstimationStatus {
|
||||||
LOADING = 'LOADING',
|
LOADING = 'LOADING',
|
||||||
@ -28,13 +29,19 @@ export enum EstimationStatus {
|
|||||||
SUCCESS = 'SUCCESS',
|
SUCCESS = 'SUCCESS',
|
||||||
}
|
}
|
||||||
|
|
||||||
const checkIfTxIsExecution = (threshold: number, preApprovingOwner?: string, txConfirmations?: number): boolean =>
|
const checkIfTxIsExecution = (
|
||||||
txConfirmations === threshold || !!preApprovingOwner || threshold === 1
|
threshold: number,
|
||||||
|
preApprovingOwner?: string,
|
||||||
|
txConfirmations?: number,
|
||||||
|
txType?: string,
|
||||||
|
): boolean =>
|
||||||
|
txConfirmations === threshold || !!preApprovingOwner || threshold === 1 || sameString(txType, 'spendingLimit')
|
||||||
|
|
||||||
const checkIfTxIsApproveAndExecution = (threshold: number, txConfirmations: number): boolean =>
|
const checkIfTxIsApproveAndExecution = (threshold: number, txConfirmations: number, txType?: string): boolean =>
|
||||||
txConfirmations + 1 === threshold
|
txConfirmations + 1 === threshold || sameString(txType, 'spendingLimit')
|
||||||
|
|
||||||
const checkIfTxIsCreation = (txConfirmations: number): boolean => txConfirmations === 0
|
const checkIfTxIsCreation = (txConfirmations: number, txType?: string): boolean =>
|
||||||
|
txConfirmations === 0 && !sameString(txType, 'spendingLimit')
|
||||||
|
|
||||||
type TransactionEstimationProps = {
|
type TransactionEstimationProps = {
|
||||||
txData: string
|
txData: string
|
||||||
@ -115,6 +122,7 @@ type UseEstimateTransactionGasProps = {
|
|||||||
preApprovingOwner?: string
|
preApprovingOwner?: string
|
||||||
operation?: number
|
operation?: number
|
||||||
safeTxGas?: number
|
safeTxGas?: number
|
||||||
|
txType?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
type TransactionGasEstimationResult = {
|
type TransactionGasEstimationResult = {
|
||||||
@ -136,6 +144,7 @@ export const useEstimateTransactionGas = ({
|
|||||||
preApprovingOwner,
|
preApprovingOwner,
|
||||||
operation,
|
operation,
|
||||||
safeTxGas,
|
safeTxGas,
|
||||||
|
txType,
|
||||||
}: UseEstimateTransactionGasProps): TransactionGasEstimationResult => {
|
}: UseEstimateTransactionGasProps): TransactionGasEstimationResult => {
|
||||||
const [gasEstimation, setGasEstimation] = useState<TransactionGasEstimationResult>({
|
const [gasEstimation, setGasEstimation] = useState<TransactionGasEstimationResult>({
|
||||||
txEstimationExecutionStatus: EstimationStatus.LOADING,
|
txEstimationExecutionStatus: EstimationStatus.LOADING,
|
||||||
@ -159,9 +168,9 @@ export const useEstimateTransactionGas = ({
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const isExecution = checkIfTxIsExecution(Number(threshold), preApprovingOwner, txConfirmations?.size)
|
const isExecution = checkIfTxIsExecution(Number(threshold), preApprovingOwner, txConfirmations?.size, txType)
|
||||||
const isCreation = checkIfTxIsCreation(txConfirmations?.size || 0)
|
const isCreation = checkIfTxIsCreation(txConfirmations?.size || 0, txType)
|
||||||
const approvalAndExecution = checkIfTxIsApproveAndExecution(Number(threshold), txConfirmations?.size || 0)
|
const approvalAndExecution = checkIfTxIsApproveAndExecution(Number(threshold), txConfirmations?.size || 0, txType)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const isOffChainSignature = checkIfOffChainSignatureIsPossible(isExecution, smartContractWallet, safeVersion)
|
const isOffChainSignature = checkIfOffChainSignatureIsPossible(isExecution, smartContractWallet, safeVersion)
|
||||||
@ -235,6 +244,7 @@ export const useEstimateTransactionGas = ({
|
|||||||
safeVersion,
|
safeVersion,
|
||||||
smartContractWallet,
|
smartContractWallet,
|
||||||
safeTxGas,
|
safeTxGas,
|
||||||
|
txType,
|
||||||
])
|
])
|
||||||
|
|
||||||
return gasEstimation
|
return gasEstimation
|
||||||
|
@ -6,7 +6,6 @@ import {
|
|||||||
SAFE_MASTER_COPY_ADDRESS,
|
SAFE_MASTER_COPY_ADDRESS,
|
||||||
getGnosisSafeInstanceAt,
|
getGnosisSafeInstanceAt,
|
||||||
} from 'src/logic/contracts/safeContracts'
|
} from 'src/logic/contracts/safeContracts'
|
||||||
import { DELEGATE_CALL } from 'src/logic/safe/transactions'
|
|
||||||
import { getWeb3 } from 'src/logic/wallets/getWeb3'
|
import { getWeb3 } from 'src/logic/wallets/getWeb3'
|
||||||
import { MultiSend } from 'src/types/contracts/MultiSend.d'
|
import { MultiSend } from 'src/types/contracts/MultiSend.d'
|
||||||
|
|
||||||
@ -49,7 +48,7 @@ export const getEncodedMultiSendCallData = (txs: MultiSendTx[], web3: Web3): str
|
|||||||
return encodedMultiSendCallData
|
return encodedMultiSendCallData
|
||||||
}
|
}
|
||||||
|
|
||||||
export const upgradeSafeToLatestVersion = async (safeAddress: string, createTransaction): Promise<void> => {
|
export const getUpgradeSafeTransactionHash = async (safeAddress: string): Promise<string> => {
|
||||||
const safeInstance = await getGnosisSafeInstanceAt(safeAddress)
|
const safeInstance = await getGnosisSafeInstanceAt(safeAddress)
|
||||||
const fallbackHandlerTxData = safeInstance.methods.setFallbackHandler(DEFAULT_FALLBACK_HANDLER_ADDRESS).encodeABI()
|
const fallbackHandlerTxData = safeInstance.methods.setFallbackHandler(DEFAULT_FALLBACK_HANDLER_ADDRESS).encodeABI()
|
||||||
const updateSafeTxData = safeInstance.methods.changeMasterCopy(SAFE_MASTER_COPY_ADDRESS).encodeABI()
|
const updateSafeTxData = safeInstance.methods.changeMasterCopy(SAFE_MASTER_COPY_ADDRESS).encodeABI()
|
||||||
@ -69,17 +68,5 @@ export const upgradeSafeToLatestVersion = async (safeAddress: string, createTran
|
|||||||
]
|
]
|
||||||
|
|
||||||
const web3 = getWeb3()
|
const web3 = getWeb3()
|
||||||
const encodeMultiSendCallData = getEncodedMultiSendCallData(txs, web3)
|
return getEncodedMultiSendCallData(txs, web3)
|
||||||
createTransaction({
|
|
||||||
safeAddress,
|
|
||||||
to: MULTI_SEND_ADDRESS,
|
|
||||||
valueInWei: 0,
|
|
||||||
txData: encodeMultiSendCallData,
|
|
||||||
notifiedTransaction: 'STANDARD_TX',
|
|
||||||
enqueueSnackbar: () => {},
|
|
||||||
closeSnackbar: () => {},
|
|
||||||
operation: DELEGATE_CALL,
|
|
||||||
})
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ const ReviewCollectible = ({ onClose, onPrev, tx }: Props): React.ReactElement =
|
|||||||
isCreation,
|
isCreation,
|
||||||
} = useEstimateTransactionGas({
|
} = useEstimateTransactionGas({
|
||||||
txData: data,
|
txData: data,
|
||||||
txRecipient: tx.recipientAddress,
|
txRecipient: tx.assetAddress,
|
||||||
})
|
})
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -120,6 +120,7 @@ const ReviewTx = ({ onClose, onPrev, tx }: ReviewTxProps): React.ReactElement =>
|
|||||||
} = useEstimateTransactionGas({
|
} = useEstimateTransactionGas({
|
||||||
txData: data,
|
txData: data,
|
||||||
txRecipient,
|
txRecipient,
|
||||||
|
txType: tx.txType,
|
||||||
})
|
})
|
||||||
|
|
||||||
const submitTx = async () => {
|
const submitTx = async () => {
|
||||||
|
@ -19,7 +19,7 @@ import enqueueSnackbar from 'src/logic/notifications/store/actions/enqueueSnackb
|
|||||||
import { getNotificationsFromTxType, enhanceSnackbarForAction } from 'src/logic/notifications'
|
import { getNotificationsFromTxType, enhanceSnackbarForAction } from 'src/logic/notifications'
|
||||||
import { sameAddress } from 'src/logic/wallets/ethAddresses'
|
import { sameAddress } from 'src/logic/wallets/ethAddresses'
|
||||||
import { TX_NOTIFICATION_TYPES } from 'src/logic/safe/transactions'
|
import { TX_NOTIFICATION_TYPES } from 'src/logic/safe/transactions'
|
||||||
import UpdateSafeModal from 'src/routes/safe/components/Settings/UpdateSafeModal'
|
import { UpdateSafeModal } from 'src/routes/safe/components/Settings/UpdateSafeModal'
|
||||||
import { grantedSelector } from 'src/routes/safe/container/selector'
|
import { grantedSelector } from 'src/routes/safe/container/selector'
|
||||||
import updateSafe from 'src/logic/safe/store/actions/updateSafe'
|
import updateSafe from 'src/logic/safe/store/actions/updateSafe'
|
||||||
import Link from 'src/components/layout/Link'
|
import Link from 'src/components/layout/Link'
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
import IconButton from '@material-ui/core/IconButton'
|
import IconButton from '@material-ui/core/IconButton'
|
||||||
import Close from '@material-ui/icons/Close'
|
import Close from '@material-ui/icons/Close'
|
||||||
import { withStyles } from '@material-ui/styles'
|
import React, { useEffect, useState } from 'react'
|
||||||
import React from 'react'
|
|
||||||
import { useDispatch } from 'react-redux'
|
import { useDispatch } from 'react-redux'
|
||||||
import { bindActionCreators } from 'redux'
|
|
||||||
|
|
||||||
import { styles } from './style'
|
import { styles } from './style'
|
||||||
|
|
||||||
@ -13,17 +11,61 @@ import Button from 'src/components/layout/Button'
|
|||||||
import Hairline from 'src/components/layout/Hairline'
|
import Hairline from 'src/components/layout/Hairline'
|
||||||
import Paragraph from 'src/components/layout/Paragraph'
|
import Paragraph from 'src/components/layout/Paragraph'
|
||||||
import Row from 'src/components/layout/Row'
|
import Row from 'src/components/layout/Row'
|
||||||
import { upgradeSafeToLatestVersion } from 'src/logic/safe/utils/upgradeSafe'
|
import { getUpgradeSafeTransactionHash } from 'src/logic/safe/utils/upgradeSafe'
|
||||||
import createTransaction from 'src/logic/safe/store/actions/createTransaction'
|
import createTransaction from 'src/logic/safe/store/actions/createTransaction'
|
||||||
|
import { makeStyles } from '@material-ui/core'
|
||||||
|
import { TransactionFees } from 'src/components/TransactionsFees'
|
||||||
|
import { useEstimateTransactionGas } from 'src/logic/hooks/useEstimateTransactionGas'
|
||||||
|
import { MULTI_SEND_ADDRESS } from 'src/logic/contracts/safeContracts'
|
||||||
|
import { DELEGATE_CALL } from 'src/logic/safe/transactions'
|
||||||
|
import { EMPTY_DATA } from 'src/logic/wallets/ethTransactions'
|
||||||
|
|
||||||
const UpdateSafeModal = ({ classes, onClose, safeAddress }) => {
|
const useStyles = makeStyles(styles)
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
onClose: () => void
|
||||||
|
safeAddress: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export const UpdateSafeModal = ({ onClose, safeAddress }: Props): React.ReactElement => {
|
||||||
|
const classes = useStyles()
|
||||||
const dispatch = useDispatch()
|
const dispatch = useDispatch()
|
||||||
|
const [multiSendCallData, setMultiSendCallData] = useState(EMPTY_DATA)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const calculateUpgradeSafeModal = async () => {
|
||||||
|
const encodeMultiSendCallData = await getUpgradeSafeTransactionHash(safeAddress)
|
||||||
|
setMultiSendCallData(encodeMultiSendCallData)
|
||||||
|
}
|
||||||
|
calculateUpgradeSafeModal()
|
||||||
|
}, [safeAddress])
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
// Call the update safe method
|
// Call the update safe method
|
||||||
await upgradeSafeToLatestVersion(safeAddress, bindActionCreators(createTransaction, dispatch))
|
dispatch(
|
||||||
|
createTransaction({
|
||||||
|
safeAddress,
|
||||||
|
to: MULTI_SEND_ADDRESS,
|
||||||
|
valueInWei: '0',
|
||||||
|
txData: multiSendCallData,
|
||||||
|
notifiedTransaction: 'STANDARD_TX',
|
||||||
|
operation: DELEGATE_CALL,
|
||||||
|
}),
|
||||||
|
)
|
||||||
onClose()
|
onClose()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
gasCostFormatted,
|
||||||
|
txEstimationExecutionStatus,
|
||||||
|
isExecution,
|
||||||
|
isCreation,
|
||||||
|
isOffChainSignature,
|
||||||
|
} = useEstimateTransactionGas({
|
||||||
|
txData: multiSendCallData,
|
||||||
|
txRecipient: safeAddress,
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Row align="center" className={classes.heading} grow>
|
<Row align="center" className={classes.heading} grow>
|
||||||
@ -56,6 +98,15 @@ const UpdateSafeModal = ({ classes, onClose, safeAddress }) => {
|
|||||||
have to confirm the update in case more than one confirmation is required for this Safe.
|
have to confirm the update in case more than one confirmation is required for this Safe.
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
</Row>
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<TransactionFees
|
||||||
|
gasCostFormatted={gasCostFormatted}
|
||||||
|
isExecution={isExecution}
|
||||||
|
isCreation={isCreation}
|
||||||
|
isOffChainSignature={isOffChainSignature}
|
||||||
|
txEstimationExecutionStatus={txEstimationExecutionStatus}
|
||||||
|
/>
|
||||||
|
</Row>
|
||||||
</Block>
|
</Block>
|
||||||
<Hairline style={{ position: 'absolute', bottom: 85 }} />
|
<Hairline style={{ position: 'absolute', bottom: 85 }} />
|
||||||
<Row align="center" className={classes.buttonRow}>
|
<Row align="center" className={classes.buttonRow}>
|
||||||
@ -72,5 +123,3 @@ const UpdateSafeModal = ({ classes, onClose, safeAddress }) => {
|
|||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withStyles(styles as any)(UpdateSafeModal)
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { lg, md, secondaryText, sm } from 'src/theme/variables'
|
import { lg, md, secondaryText, sm } from 'src/theme/variables'
|
||||||
|
import { createStyles } from '@material-ui/core'
|
||||||
|
|
||||||
export const styles = () => ({
|
export const styles = createStyles({
|
||||||
heading: {
|
heading: {
|
||||||
padding: `${sm} ${lg}`,
|
padding: `${sm} ${lg}`,
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user