(Feature) Proper rejections (#2096)
* remove `isCancelTransaction` utility function in favor of `txInfo.isCancellation` flag provided by client-gateway * replace "cancel" concept in favor of "reject" * add circle-cross-red icon to "On-chain rejection" transaction info Adjust owner's list text color * identify queued on-chain rejection * apply styles to on-chain rejection type identifier * update awaiting messages wording * fix styles on styles to on-chain rejection * replace local svg with SRC `Icon` component wherever is possible
This commit is contained in:
parent
e48891ba2b
commit
c96e3192ff
|
@ -161,7 +161,7 @@
|
|||
"@gnosis.pm/safe-apps-sdk": "1.0.3",
|
||||
"@gnosis.pm/safe-apps-sdk-v1": "npm:@gnosis.pm/safe-apps-sdk@0.4.2",
|
||||
"@gnosis.pm/safe-contracts": "1.1.1-dev.2",
|
||||
"@gnosis.pm/safe-react-components": "https://github.com/gnosis/safe-react-components.git#a68a67e",
|
||||
"@gnosis.pm/safe-react-components": "https://github.com/gnosis/safe-react-components.git#7ebc414",
|
||||
"@gnosis.pm/util-contracts": "2.0.6",
|
||||
"@ledgerhq/hw-transport-node-hid-singleton": "5.45.0",
|
||||
"@material-ui/core": "^4.11.0",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Text } from '@gnosis.pm/safe-react-components'
|
||||
import React from 'react'
|
||||
import React, { ReactElement } from 'react'
|
||||
import styled from 'styled-components'
|
||||
|
||||
const Wrapper = styled.div`
|
||||
|
@ -12,11 +12,9 @@ const Icon = styled.img`
|
|||
margin-right: 9px;
|
||||
`
|
||||
|
||||
const CustomIconText = ({ iconUrl, text }: { iconUrl: string; text?: string }) => (
|
||||
export const CustomIconText = ({ iconUrl, text }: { iconUrl: string; text?: string }): ReactElement => (
|
||||
<Wrapper>
|
||||
<Icon alt={text} src={iconUrl} />
|
||||
{text && <Text size="xl">{text}</Text>}
|
||||
</Wrapper>
|
||||
)
|
||||
|
||||
export default CustomIconText
|
||||
|
|
|
@ -41,7 +41,7 @@ export const TransactionFailText = ({
|
|||
if (isExecution) {
|
||||
errorMessage =
|
||||
threshold && threshold > 1
|
||||
? `To save gas costs, cancel this transaction`
|
||||
? `To save gas costs, reject this transaction`
|
||||
: `To save gas costs, avoid executing the transaction.`
|
||||
}
|
||||
|
||||
|
|
|
@ -236,7 +236,7 @@ type MultiSigExecutionDetails = {
|
|||
type DetailedExecutionInfo = ModuleExecutionDetails | MultiSigExecutionDetails
|
||||
|
||||
type ExpandedTxDetails = {
|
||||
executedAt: number
|
||||
executedAt: number | null
|
||||
txStatus: TransactionStatus
|
||||
txInfo: TransactionInfo
|
||||
txData: TransactionData | null
|
||||
|
|
|
@ -4,7 +4,7 @@ import CircularProgress from '@material-ui/core/CircularProgress'
|
|||
import React, { ReactElement, useContext, useRef } from 'react'
|
||||
import styled from 'styled-components'
|
||||
|
||||
import CustomIconText from 'src/components/CustomIconText'
|
||||
import { CustomIconText } from 'src/components/CustomIconText'
|
||||
import {
|
||||
isCustomTxInfo,
|
||||
isMultiSendTxInfo,
|
||||
|
@ -24,6 +24,7 @@ import { TokenTransferAmount } from './TokenTransferAmount'
|
|||
import { TxsInfiniteScrollContext } from './TxsInfiniteScroll'
|
||||
import { TxLocationContext } from './TxLocationProvider'
|
||||
import { CalculatedVotes } from './TxQueueCollapsed'
|
||||
import { isCancelTxDetails } from './utils'
|
||||
|
||||
const TxInfo = ({ info }: { info: AssetInfo }) => {
|
||||
if (isTokenTransferAsset(info)) {
|
||||
|
@ -116,6 +117,8 @@ export const TxCollapsed = ({
|
|||
const { ref, lastItemId } = useContext(TxsInfiniteScrollContext)
|
||||
|
||||
const willBeReplaced = transaction?.txStatus === 'WILL_BE_REPLACED' ? ' will-be-replaced' : ''
|
||||
const onChainRejection =
|
||||
isCancelTxDetails(transaction.txInfo) && txLocation !== 'history' ? ' on-chain-rejection' : ''
|
||||
|
||||
const txCollapsedNonce = (
|
||||
<div className={'tx-nonce' + willBeReplaced}>
|
||||
|
@ -124,7 +127,7 @@ export const TxCollapsed = ({
|
|||
)
|
||||
|
||||
const txCollapsedType = (
|
||||
<div className={'tx-type' + willBeReplaced}>
|
||||
<div className={'tx-type' + willBeReplaced + onChainRejection}>
|
||||
<CustomIconText iconUrl={type.icon} text={type.text} />
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -46,7 +46,7 @@ export const TxCollapsedActions = ({ transaction }: TxCollapsedActionsProps): Re
|
|||
</span>
|
||||
</Tooltip>
|
||||
{canCancel && (
|
||||
<Tooltip title="Cancel" placement="top">
|
||||
<Tooltip title="Reject" placement="top">
|
||||
<span>
|
||||
<IconButton size="small" type="button" onClick={handleCancelButtonClick} disabled={isPending}>
|
||||
<Icon type="circleCross" color="error" size="sm" />
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { Icon, Link, Loader, Text } from '@gnosis.pm/safe-react-components'
|
||||
import cn from 'classnames'
|
||||
import React, { ReactElement, useContext } from 'react'
|
||||
import { useSelector } from 'react-redux'
|
||||
import styled from 'styled-components'
|
||||
|
||||
import {
|
||||
|
@ -12,7 +11,6 @@ import {
|
|||
MultiSigExecutionDetails,
|
||||
Transaction,
|
||||
} from 'src/logic/safe/store/models/types/gateway.d'
|
||||
import { safeParamAddressFromStateSelector } from 'src/logic/safe/store/selectors'
|
||||
import { TransactionActions } from './hooks/useTransactionActions'
|
||||
import { useTransactionDetails } from './hooks/useTransactionDetails'
|
||||
import { TxDetailsContainer, Centered, AlignItemsWithMargin } from './styled'
|
||||
|
@ -30,34 +28,44 @@ const NormalBreakingText = styled(Text)`
|
|||
`
|
||||
|
||||
const TxDataGroup = ({ txDetails }: { txDetails: ExpandedTxDetails }): ReactElement | null => {
|
||||
const safeAddress = useSelector(safeParamAddressFromStateSelector)
|
||||
|
||||
if (isTransferTxInfo(txDetails.txInfo) || isSettingsChangeTxInfo(txDetails.txInfo)) {
|
||||
return <TxInfo txInfo={txDetails.txInfo} />
|
||||
}
|
||||
|
||||
if (isCancelTxDetails({ executedAt: txDetails.executedAt, txInfo: txDetails.txInfo, safeAddress })) {
|
||||
if (isCancelTxDetails(txDetails.txInfo)) {
|
||||
const txNonce = `${(txDetails.detailedExecutionInfo as MultiSigExecutionDetails).nonce ?? NOT_AVAILABLE}`
|
||||
const isTxExecuted = txDetails.executedAt
|
||||
|
||||
// executed rejection transaction
|
||||
let message = `This is an on-chain rejection that didn't send any funds.
|
||||
This on-chain rejection replaced all transactions with nonce ${txNonce}.`
|
||||
|
||||
if (!isTxExecuted) {
|
||||
// queued rejection transaction
|
||||
message = `This is an on-chain rejection that doesn't send any funds.
|
||||
Executing this on-chain rejection will replace all currently awaiting transactions with nonce ${txNonce}.`
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<NormalBreakingText size="xl">
|
||||
{`This is an empty cancelling transaction that doesn't send any funds.
|
||||
Executing this transaction will replace all currently awaiting transactions with nonce ${
|
||||
(txDetails.detailedExecutionInfo as MultiSigExecutionDetails).nonce ?? NOT_AVAILABLE
|
||||
}.`}
|
||||
</NormalBreakingText>
|
||||
<Link
|
||||
href="https://help.gnosis-safe.io/en/articles/4738501-why-do-i-need-to-pay-for-cancelling-a-transaction"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
title="Why do I need to pay for cancelling a transaction?"
|
||||
>
|
||||
<AlignItemsWithMargin>
|
||||
<Text size="xl" as="span" color="primary">
|
||||
Why do I need to pay for cancelling a transaction?
|
||||
</Text>
|
||||
<Icon size="sm" type="externalLink" color="primary" />
|
||||
</AlignItemsWithMargin>
|
||||
</Link>
|
||||
<NormalBreakingText size="xl">{message}</NormalBreakingText>
|
||||
{!isTxExecuted && (
|
||||
<>
|
||||
<br />
|
||||
<Link
|
||||
href="https://help.gnosis-safe.io/en/articles/4738501-why-do-i-need-to-pay-for-cancelling-a-transaction"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
title="Why do I need to pay for rejecting a transaction?"
|
||||
>
|
||||
<AlignItemsWithMargin>
|
||||
<Text size="xl" as="span" color="primary">
|
||||
Why do I need to pay for rejecting a transaction?
|
||||
</Text>
|
||||
<Icon size="sm" type="externalLink" color="primary" />
|
||||
</AlignItemsWithMargin>
|
||||
</Link>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
@ -116,7 +124,7 @@ export const TxDetails = ({ transaction, actions }: TxDetailsProps): ReactElemen
|
|||
'will-be-replaced': transaction.txStatus === 'WILL_BE_REPLACED',
|
||||
})}
|
||||
>
|
||||
<TxOwners detailedExecutionInfo={data.detailedExecutionInfo} />
|
||||
<TxOwners txDetails={data} />
|
||||
</div>
|
||||
{!data.executedAt && txLocation !== 'history' && actions?.isUserAnOwner && (
|
||||
<div className={cn('tx-details-actions', { 'will-be-replaced': transaction.txStatus === 'WILL_BE_REPLACED' })}>
|
||||
|
|
|
@ -41,7 +41,7 @@ export const TxExpandedActions = ({ transaction }: TxExpandedActionsProps): Reac
|
|||
</Button>
|
||||
{canCancel && (
|
||||
<Button size="md" color="error" onClick={handleCancelButtonClick} className="error" disabled={isPending}>
|
||||
Cancel
|
||||
Reject
|
||||
</Button>
|
||||
)}
|
||||
</>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Text } from '@gnosis.pm/safe-react-components'
|
||||
import { Text, Icon } from '@gnosis.pm/safe-react-components'
|
||||
import React, { ReactElement } from 'react'
|
||||
import styled from 'styled-components'
|
||||
|
||||
|
@ -6,43 +6,55 @@ import Img from 'src/components/layout/Img'
|
|||
import { ExpandedTxDetails, isModuleExecutionDetails } from 'src/logic/safe/store/models/types/gateway.d'
|
||||
import TransactionListActive from './assets/transactions-list-active.svg'
|
||||
import TransactionListInactive from './assets/transactions-list-inactive.svg'
|
||||
import CheckCircleGreen from './assets/check-circle-green.svg'
|
||||
import PlusCircleGreen from './assets/plus-circle-green.svg'
|
||||
import { OwnerRow } from './OwnerRow'
|
||||
import { OwnerList, OwnerListItem } from './styled'
|
||||
|
||||
type TxOwnersProps = {
|
||||
detailedExecutionInfo: ExpandedTxDetails['detailedExecutionInfo']
|
||||
}
|
||||
import { isCancelTxDetails } from './utils'
|
||||
|
||||
const StyledImg = styled(Img)`
|
||||
background-color: transparent;
|
||||
border-radius: 50%;
|
||||
`
|
||||
|
||||
export const TxOwners = ({ detailedExecutionInfo }: TxOwnersProps): ReactElement | null => {
|
||||
export const TxOwners = ({ txDetails }: { txDetails: ExpandedTxDetails }): ReactElement | null => {
|
||||
const { txInfo, detailedExecutionInfo } = txDetails
|
||||
|
||||
if (!detailedExecutionInfo || isModuleExecutionDetails(detailedExecutionInfo)) {
|
||||
return null
|
||||
}
|
||||
|
||||
const confirmationsNeeded = detailedExecutionInfo.confirmationsRequired - detailedExecutionInfo.confirmations.length
|
||||
|
||||
const CreationNode = isCancelTxDetails(txInfo) ? (
|
||||
<OwnerListItem>
|
||||
<span className="icon">
|
||||
<Icon size="sm" type="circleCross" color="error" />
|
||||
</span>
|
||||
<div className="legend">
|
||||
<Text color="error" size="xl" strong>
|
||||
On-chain rejection created
|
||||
</Text>
|
||||
</div>
|
||||
</OwnerListItem>
|
||||
) : (
|
||||
<OwnerListItem>
|
||||
<span className="icon">
|
||||
<Icon size="sm" type="add" color="primary" />
|
||||
</span>
|
||||
<div className="legend">
|
||||
<Text color="primary" size="xl" strong>
|
||||
Created
|
||||
</Text>
|
||||
</div>
|
||||
</OwnerListItem>
|
||||
)
|
||||
|
||||
return (
|
||||
<OwnerList>
|
||||
<OwnerListItem>
|
||||
<span className="icon">
|
||||
<StyledImg alt="" src={PlusCircleGreen} />
|
||||
</span>
|
||||
<div className="legend">
|
||||
<Text color="primary" size="xl" strong>
|
||||
Created
|
||||
</Text>
|
||||
</div>
|
||||
</OwnerListItem>
|
||||
{CreationNode}
|
||||
{detailedExecutionInfo.confirmations.map(({ signer }) => (
|
||||
<OwnerListItem key={signer}>
|
||||
<span className="icon">
|
||||
<StyledImg alt="" src={CheckCircleGreen} />
|
||||
<Icon size="sm" type="circleCheck" color="primary" />
|
||||
</span>
|
||||
<div className="legend">
|
||||
<Text color="primary" size="xl" strong>
|
||||
|
@ -55,7 +67,11 @@ export const TxOwners = ({ detailedExecutionInfo }: TxOwnersProps): ReactElement
|
|||
{confirmationsNeeded <= 0 ? (
|
||||
<OwnerListItem>
|
||||
<span className="icon">
|
||||
<StyledImg alt="" src={detailedExecutionInfo.executor ? CheckCircleGreen : TransactionListActive} />
|
||||
{detailedExecutionInfo.executor ? (
|
||||
<Icon type="circleCheck" size="sm" color="primary" />
|
||||
) : (
|
||||
<StyledImg alt="" src={TransactionListActive} />
|
||||
)}
|
||||
</span>
|
||||
<div className="legend">
|
||||
<Text color="primary" size="xl" strong>
|
||||
|
|
|
@ -27,7 +27,7 @@ export const TxSummary = ({ txDetails }: { txDetails: ExpandedTxDetails }): Reac
|
|||
</Text>
|
||||
)}
|
||||
</div>
|
||||
{nonce && (
|
||||
{nonce !== undefined && (
|
||||
<div className="tx-nonce">
|
||||
<Text size="xl" strong as="span">
|
||||
Nonce:{' '}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<g>
|
||||
<g>
|
||||
<path d="M0 0H16V16H0z" transform="translate(-273 -201) translate(273 201)"/>
|
||||
<path fill="#F02525" fill-rule="nonzero" d="M8 15c3.866 0 7-3.134 7-7s-3.134-7-7-7-7 3.134-7 7 3.134 7 7 7zm0-2c-2.761 0-5-2.239-5-5s2.239-5 5-5 5 2.239 5 5-2.239 5-5 5z" transform="translate(-273 -201) translate(273 201)"/>
|
||||
<path fill="#F02525" d="M9.414 8l1.414 1.414c.391.39.391 1.024 0 1.414-.39.391-1.023.391-1.414 0L8 9.414l-1.414 1.414c-.39.391-1.024.391-1.414 0-.391-.39-.391-1.023 0-1.414L6.586 8 5.172 6.586c-.391-.39-.391-1.024 0-1.414.39-.391 1.023-.391 1.414 0L8 6.586l1.414-1.414c.39-.391 1.024-.391 1.414 0 .391.39.391 1.023 0 1.414L9.414 8z" transform="translate(-273 -201) translate(273 201)"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 936 B |
|
@ -7,7 +7,6 @@ import { getQueuedTransactionsByNonce } from 'src/logic/safe/store/selectors/gat
|
|||
import { sameAddress } from 'src/logic/wallets/ethAddresses'
|
||||
import { userAccountSelector } from 'src/logic/wallets/store/selectors'
|
||||
import { TxLocationContext } from 'src/routes/safe/components/Transactions/TxList/TxLocationProvider'
|
||||
import { isCancelTransaction } from 'src/routes/safe/components/Transactions/TxList/utils'
|
||||
import { grantedSelector } from 'src/routes/safe/container/selector'
|
||||
import { AppReduxState } from 'src/store'
|
||||
|
||||
|
@ -60,14 +59,7 @@ export const useTransactionActions = (transaction: Transaction): TransactionActi
|
|||
canConfirm,
|
||||
canConfirmThenExecute: txLocation === 'queued.next' && canConfirm && oneToGo,
|
||||
canExecute: txLocation === 'queued.next' && thresholdReached,
|
||||
canCancel: !transactionsByNonce.some(
|
||||
({ txInfo }) =>
|
||||
isCustomTxInfo(txInfo) &&
|
||||
isCancelTransaction({
|
||||
txInfo,
|
||||
safeAddress,
|
||||
}),
|
||||
),
|
||||
canCancel: !transactionsByNonce.some(({ txInfo }) => isCustomTxInfo(txInfo) && txInfo.isCancellation),
|
||||
isUserAnOwner,
|
||||
oneToGo,
|
||||
})
|
||||
|
|
|
@ -37,10 +37,10 @@ export const useTransactionStatus = (transaction: Transaction): TransactionStatu
|
|||
|
||||
switch (transaction.txStatus) {
|
||||
case 'AWAITING_CONFIRMATIONS':
|
||||
text = signaturePending(currentUser) ? 'Awaiting your confirmation' : 'Awaiting confirmations'
|
||||
text = signaturePending(currentUser) ? 'Needs your confirmation' : 'Needs confirmations'
|
||||
break
|
||||
case 'AWAITING_EXECUTION':
|
||||
text = 'Awaiting execution'
|
||||
text = 'Needs execution'
|
||||
break
|
||||
case 'PENDING':
|
||||
case 'PENDING_FAILED':
|
||||
|
|
|
@ -4,10 +4,10 @@ import { useSelector } from 'react-redux'
|
|||
import { Transaction } from 'src/logic/safe/store/models/types/gateway.d'
|
||||
import { safeParamAddressFromStateSelector } from 'src/logic/safe/store/selectors'
|
||||
import CustomTxIcon from 'src/routes/safe/components/Transactions/TxList/assets/custom.svg'
|
||||
import CircleCrossRed from 'src/routes/safe/components/Transactions/TxList/assets/circle-cross-red.svg'
|
||||
import IncomingTxIcon from 'src/routes/safe/components/Transactions/TxList/assets/incoming.svg'
|
||||
import OutgoingTxIcon from 'src/routes/safe/components/Transactions/TxList/assets/outgoing.svg'
|
||||
import SettingsTxIcon from 'src/routes/safe/components/Transactions/TxList/assets/settings.svg'
|
||||
import { isCancelTransaction } from 'src/routes/safe/components/Transactions/TxList/utils'
|
||||
|
||||
export type TxTypeProps = {
|
||||
icon: string
|
||||
|
@ -40,20 +40,8 @@ export const useTransactionType = (tx: Transaction): TxTypeProps => {
|
|||
break
|
||||
}
|
||||
|
||||
// TODO: isCancel
|
||||
// there are two 'cancelling' tx identification
|
||||
// this one is the candidate to remain when the client gateway implements
|
||||
// https://github.com/gnosis/safe-client-gateway/issues/255
|
||||
if (typeof tx.txInfo.isCancellation === 'boolean' && tx.txInfo.isCancellation) {
|
||||
setType({ icon: CustomTxIcon, text: 'Cancelling transaction' })
|
||||
break
|
||||
}
|
||||
|
||||
// TODO: isCancel
|
||||
// remove the following condition when issue#255 is implemented
|
||||
// also remove `isCancelTransaction` function
|
||||
if (isCancelTransaction({ txInfo: tx.txInfo, safeAddress })) {
|
||||
setType({ icon: CustomTxIcon, text: 'Cancelling transaction' })
|
||||
if (tx.txInfo.isCancellation) {
|
||||
setType({ icon: CircleCrossRed, text: 'On-chain rejection' })
|
||||
break
|
||||
}
|
||||
|
||||
|
|
|
@ -163,6 +163,32 @@ const failedTransaction = css`
|
|||
}
|
||||
`
|
||||
|
||||
const onChainRejection = css`
|
||||
&.on-chain-rejection {
|
||||
background-color: ${({ theme }) => theme.colors.errorTooltip};
|
||||
border-left: 4px solid ${({ theme }) => theme.colors.error};
|
||||
border-radius: 4px;
|
||||
padding-left: 7px;
|
||||
height: 22px;
|
||||
max-width: 165px;
|
||||
|
||||
> div {
|
||||
height: 17px;
|
||||
align-items: center;
|
||||
padding-top: 3px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 11px;
|
||||
line-height: 16px;
|
||||
letter-spacing: 1px;
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
margin-left: -2px;
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
export const StyledTransaction = styled.div`
|
||||
${willBeReplaced};
|
||||
${failedTransaction};
|
||||
|
@ -175,6 +201,10 @@ export const StyledTransaction = styled.div`
|
|||
align-self: center;
|
||||
}
|
||||
|
||||
.tx-type {
|
||||
${onChainRejection};
|
||||
}
|
||||
|
||||
.tx-votes {
|
||||
justify-self: center;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ import { BigNumber } from 'bignumber.js'
|
|||
|
||||
import { getNetworkInfo } from 'src/config'
|
||||
import {
|
||||
Custom,
|
||||
isCustomTxInfo,
|
||||
isTransferTxInfo,
|
||||
Transaction,
|
||||
|
@ -12,7 +11,6 @@ import {
|
|||
|
||||
import { formatAmount } from 'src/logic/tokens/utils/formatAmount'
|
||||
import { sameAddress } from 'src/logic/wallets/ethAddresses'
|
||||
import { sameString } from 'src/utils/strings'
|
||||
|
||||
export const NOT_AVAILABLE = 'n/a'
|
||||
|
||||
|
@ -90,27 +88,11 @@ export const getTxTokenData = (txInfo: Transfer): txTokenData => {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: isCancel
|
||||
// how can we be sure that it's a cancel tx without asking for tx-details?
|
||||
// can the client-gateway service provide info about the tx, Like: `isCancelTransaction: boolean`?
|
||||
// it will be solved as part of: https://github.com/gnosis/safe-client-gateway/issues/255
|
||||
export const isCancelTransaction = ({ txInfo, safeAddress }: { txInfo: Custom; safeAddress: string }): boolean =>
|
||||
sameAddress(txInfo.to, safeAddress) &&
|
||||
sameString(txInfo.dataSize, '0') &&
|
||||
sameString(txInfo.value, '0') &&
|
||||
txInfo.methodName === null
|
||||
|
||||
type IsCancelTxDetailsProps = {
|
||||
executedAt: number | null
|
||||
txInfo: Transaction['txInfo']
|
||||
safeAddress: string
|
||||
}
|
||||
export const isCancelTxDetails = ({ executedAt, txInfo, safeAddress }: IsCancelTxDetailsProps): boolean =>
|
||||
!executedAt &&
|
||||
export const isCancelTxDetails = (txInfo: Transaction['txInfo']): boolean =>
|
||||
// custom transaction
|
||||
isCustomTxInfo(txInfo) &&
|
||||
// verify that it's a cancel tx based on it's info
|
||||
isCancelTransaction({ safeAddress, txInfo })
|
||||
// flag-based identification
|
||||
txInfo.isCancellation
|
||||
|
||||
export const addressInList = (list: string[] = []) => (address: string): boolean =>
|
||||
list.some((ownerAddress) => sameAddress(ownerAddress, address))
|
||||
|
|
|
@ -1596,9 +1596,9 @@
|
|||
solc "0.5.14"
|
||||
truffle "^5.1.21"
|
||||
|
||||
"@gnosis.pm/safe-react-components@https://github.com/gnosis/safe-react-components.git#a68a67e":
|
||||
"@gnosis.pm/safe-react-components@https://github.com/gnosis/safe-react-components.git#7ebc414":
|
||||
version "0.5.0"
|
||||
resolved "https://github.com/gnosis/safe-react-components.git#a68a67e634d0be091856ebba9f6874eebb767cd7"
|
||||
resolved "https://github.com/gnosis/safe-react-components.git#7ebc414ae975d60846704c5a8db5e61c30348d12"
|
||||
dependencies:
|
||||
classnames "^2.2.6"
|
||||
react-media "^1.10.0"
|
||||
|
|
Loading…
Reference in New Issue