feature: set tx's owners pending status
This commit is contained in:
parent
165d0ff0d6
commit
2c41105474
|
@ -8,6 +8,7 @@ import ConfirmSmallFilledCircle from './assets/confirm-small-filled.svg'
|
||||||
import ConfirmSmallGreenCircle from './assets/confirm-small-green.svg'
|
import ConfirmSmallGreenCircle from './assets/confirm-small-green.svg'
|
||||||
import ConfirmSmallGreyCircle from './assets/confirm-small-grey.svg'
|
import ConfirmSmallGreyCircle from './assets/confirm-small-grey.svg'
|
||||||
import ConfirmSmallRedCircle from './assets/confirm-small-red.svg'
|
import ConfirmSmallRedCircle from './assets/confirm-small-red.svg'
|
||||||
|
import PendingSmallYellowCircle from './assets/confirm-small-yellow.svg'
|
||||||
import { styles } from './style'
|
import { styles } from './style'
|
||||||
|
|
||||||
import EtherscanLink from 'src/components/EtherscanLink'
|
import EtherscanLink from 'src/components/EtherscanLink'
|
||||||
|
@ -32,6 +33,8 @@ const OwnerComponent = ({
|
||||||
onTxExecute,
|
onTxExecute,
|
||||||
onTxReject,
|
onTxReject,
|
||||||
owner,
|
owner,
|
||||||
|
pendingAcceptAction,
|
||||||
|
pendingRejectAction,
|
||||||
showConfirmBtn,
|
showConfirmBtn,
|
||||||
showExecuteBtn,
|
showExecuteBtn,
|
||||||
showExecuteRejectBtn,
|
showExecuteRejectBtn,
|
||||||
|
@ -43,18 +46,110 @@ const OwnerComponent = ({
|
||||||
const [imgCircle, setImgCircle] = React.useState(ConfirmSmallGreyCircle)
|
const [imgCircle, setImgCircle] = React.useState(ConfirmSmallGreyCircle)
|
||||||
|
|
||||||
React.useMemo(() => {
|
React.useMemo(() => {
|
||||||
|
if (pendingAcceptAction || pendingRejectAction) {
|
||||||
|
setImgCircle(PendingSmallYellowCircle)
|
||||||
|
return
|
||||||
|
}
|
||||||
if (confirmed) {
|
if (confirmed) {
|
||||||
setImgCircle(isCancelTx ? CancelSmallFilledCircle : ConfirmSmallFilledCircle)
|
setImgCircle(isCancelTx ? CancelSmallFilledCircle : ConfirmSmallFilledCircle)
|
||||||
} else if (thresholdReached || executor) {
|
return
|
||||||
setImgCircle(isCancelTx ? ConfirmSmallRedCircle : ConfirmSmallGreenCircle)
|
|
||||||
}
|
}
|
||||||
}, [confirmed, thresholdReached, executor, isCancelTx])
|
if (thresholdReached || executor) {
|
||||||
|
setImgCircle(isCancelTx ? ConfirmSmallRedCircle : ConfirmSmallGreenCircle)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
setImgCircle(ConfirmSmallGreyCircle)
|
||||||
|
}, [confirmed, thresholdReached, executor, isCancelTx, pendingAcceptAction, pendingRejectAction])
|
||||||
|
|
||||||
const getTimelineLine = () => (isCancelTx ? classes.verticalLineCancel : classes.verticalLineDone)
|
const getTimelineLine = () => {
|
||||||
|
if (pendingAcceptAction || pendingRejectAction) {
|
||||||
|
return classes.verticalPendingAction
|
||||||
|
}
|
||||||
|
if (isCancelTx) {
|
||||||
|
return classes.verticalLineCancel
|
||||||
|
}
|
||||||
|
return classes.verticalLineDone
|
||||||
|
}
|
||||||
|
|
||||||
|
const confirmButton = () => {
|
||||||
|
if (pendingRejectAction) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
if (pendingAcceptAction) {
|
||||||
|
return <Block className={classes.executor}>Pending</Block>
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{showConfirmBtn && (
|
||||||
|
<Button
|
||||||
|
className={classes.button}
|
||||||
|
color="primary"
|
||||||
|
onClick={onTxConfirm}
|
||||||
|
testId={CONFIRM_TX_BTN_TEST_ID}
|
||||||
|
variant="contained"
|
||||||
|
>
|
||||||
|
Confirm
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
{showExecuteBtn && (
|
||||||
|
<Button
|
||||||
|
className={classes.button}
|
||||||
|
color="primary"
|
||||||
|
onClick={onTxExecute}
|
||||||
|
testId={EXECUTE_TX_BTN_TEST_ID}
|
||||||
|
variant="contained"
|
||||||
|
>
|
||||||
|
Execute
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const rejectButton = () => {
|
||||||
|
if (pendingRejectAction) {
|
||||||
|
return <Block className={classes.executor}>Pending</Block>
|
||||||
|
}
|
||||||
|
if (pendingAcceptAction) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{showRejectBtn && (
|
||||||
|
<Button
|
||||||
|
className={cn(classes.button, classes.lastButton)}
|
||||||
|
color="secondary"
|
||||||
|
onClick={onTxReject}
|
||||||
|
testId={REJECT_TX_BTN_TEST_ID}
|
||||||
|
variant="contained"
|
||||||
|
>
|
||||||
|
Reject
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
{showExecuteRejectBtn && (
|
||||||
|
<Button
|
||||||
|
className={cn(classes.button, classes.lastButton)}
|
||||||
|
color="secondary"
|
||||||
|
onClick={onTxReject}
|
||||||
|
testId={EXECUTE_REJECT_TX_BTN_TEST_ID}
|
||||||
|
variant="contained"
|
||||||
|
>
|
||||||
|
Execute
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Block className={classes.container}>
|
<Block className={classes.container}>
|
||||||
<div className={cn(classes.verticalLine, (confirmed || thresholdReached || executor) && getTimelineLine())} />
|
<div
|
||||||
|
className={cn(
|
||||||
|
classes.verticalLine,
|
||||||
|
(confirmed || thresholdReached || executor || pendingAcceptAction || pendingRejectAction) &&
|
||||||
|
getTimelineLine(),
|
||||||
|
)}
|
||||||
|
/>
|
||||||
<div className={classes.circleState}>
|
<div className={classes.circleState}>
|
||||||
<Img alt="" src={imgCircle} />
|
<Img alt="" src={imgCircle} />
|
||||||
</div>
|
</div>
|
||||||
|
@ -66,61 +161,7 @@ const OwnerComponent = ({
|
||||||
<EtherscanLink className={classes.address} cut={4} type="address" value={owner} />
|
<EtherscanLink className={classes.address} cut={4} type="address" value={owner} />
|
||||||
</Block>
|
</Block>
|
||||||
<Block className={classes.spacer} />
|
<Block className={classes.spacer} />
|
||||||
{owner === userAddress && (
|
{owner === userAddress && <Block>{isCancelTx ? rejectButton() : confirmButton()}</Block>}
|
||||||
<Block>
|
|
||||||
{isCancelTx ? (
|
|
||||||
<>
|
|
||||||
{showRejectBtn && (
|
|
||||||
<Button
|
|
||||||
className={cn(classes.button, classes.lastButton)}
|
|
||||||
color="secondary"
|
|
||||||
onClick={onTxReject}
|
|
||||||
testId={REJECT_TX_BTN_TEST_ID}
|
|
||||||
variant="contained"
|
|
||||||
>
|
|
||||||
Reject
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
{showExecuteRejectBtn && (
|
|
||||||
<Button
|
|
||||||
className={cn(classes.button, classes.lastButton)}
|
|
||||||
color="secondary"
|
|
||||||
onClick={onTxReject}
|
|
||||||
testId={EXECUTE_REJECT_TX_BTN_TEST_ID}
|
|
||||||
variant="contained"
|
|
||||||
>
|
|
||||||
Execute
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
{showConfirmBtn && (
|
|
||||||
<Button
|
|
||||||
className={classes.button}
|
|
||||||
color="primary"
|
|
||||||
onClick={onTxConfirm}
|
|
||||||
testId={CONFIRM_TX_BTN_TEST_ID}
|
|
||||||
variant="contained"
|
|
||||||
>
|
|
||||||
Confirm
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
{showExecuteBtn && (
|
|
||||||
<Button
|
|
||||||
className={classes.button}
|
|
||||||
color="primary"
|
|
||||||
onClick={onTxExecute}
|
|
||||||
testId={EXECUTE_TX_BTN_TEST_ID}
|
|
||||||
variant="contained"
|
|
||||||
>
|
|
||||||
Execute
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Block>
|
|
||||||
)}
|
|
||||||
{owner === executor && <Block className={classes.executor}>Executor</Block>}
|
{owner === executor && <Block className={classes.executor}>Executor</Block>}
|
||||||
</Block>
|
</Block>
|
||||||
)
|
)
|
||||||
|
|
|
@ -38,7 +38,7 @@ const OwnersList = ({
|
||||||
userAddress={userAddress}
|
userAddress={userAddress}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
{ownersUnconfirmed.map((owner) => (
|
{ownersUnconfirmed.map(({ hasPendingAcceptActions, hasPendingRejectActions, owner }) => (
|
||||||
<OwnerComponent
|
<OwnerComponent
|
||||||
classes={classes}
|
classes={classes}
|
||||||
executor={executor}
|
executor={executor}
|
||||||
|
@ -48,6 +48,8 @@ const OwnersList = ({
|
||||||
onTxExecute={onTxExecute}
|
onTxExecute={onTxExecute}
|
||||||
onTxReject={onTxReject}
|
onTxReject={onTxReject}
|
||||||
owner={owner}
|
owner={owner}
|
||||||
|
pendingAcceptAction={hasPendingAcceptActions}
|
||||||
|
pendingRejectAction={hasPendingRejectActions}
|
||||||
showConfirmBtn={showConfirmBtn}
|
showConfirmBtn={showConfirmBtn}
|
||||||
showExecuteBtn={showExecuteBtn}
|
showExecuteBtn={showExecuteBtn}
|
||||||
showExecuteRejectBtn={showExecuteRejectBtn}
|
showExecuteRejectBtn={showExecuteRejectBtn}
|
||||||
|
|
|
@ -34,20 +34,43 @@ function getOwnersConfirmations(tx, userAddress) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPendingOwnersConfirmations(owners, tx, userAddress) {
|
function getPendingOwnersConfirmations(owners, tx, userAddress) {
|
||||||
const ownersNotConfirmed = []
|
const ownersWithNoConfirmations = []
|
||||||
let currentUserNotConfirmed = true
|
let currentUserNotConfirmed = true
|
||||||
|
|
||||||
owners.forEach((owner) => {
|
owners.forEach((owner) => {
|
||||||
const confirmationsEntry = tx.confirmations.find((conf) => conf.owner === owner.address)
|
const confirmationsEntry = tx.confirmations.find((conf) => conf.owner === owner.address)
|
||||||
if (!confirmationsEntry) {
|
if (!confirmationsEntry) {
|
||||||
ownersNotConfirmed.push(owner.address)
|
ownersWithNoConfirmations.push(owner.address)
|
||||||
}
|
}
|
||||||
if (confirmationsEntry && confirmationsEntry.owner === userAddress) {
|
if (confirmationsEntry && confirmationsEntry.owner === userAddress) {
|
||||||
currentUserNotConfirmed = false
|
currentUserNotConfirmed = false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return [ownersNotConfirmed, currentUserNotConfirmed]
|
const confirmationPendingActions = tx.ownersWithPendingActions.get('confirm')
|
||||||
|
const confirmationRejectActions = tx.ownersWithPendingActions.get('reject')
|
||||||
|
|
||||||
|
const ownersWithNoConfirmationsSorted = ownersWithNoConfirmations
|
||||||
|
.map((owner) => ({
|
||||||
|
hasPendingAcceptActions: confirmationPendingActions.includes(owner),
|
||||||
|
hasPendingRejectActions: confirmationRejectActions.includes(owner),
|
||||||
|
owner,
|
||||||
|
}))
|
||||||
|
// Reorders the list of unconfirmed owners, owners with pendingActions should be first
|
||||||
|
.sort((ownerA, ownerB) => {
|
||||||
|
// If the first owner has pending actions, A should be before B
|
||||||
|
if (ownerA.hasPendingRejectActions || ownerA.hasPendingAcceptActions) {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
// The first owner has not pending actions but the second yes, B should be before A
|
||||||
|
if (ownerB.hasPendingRejectActions || ownerB.hasPendingAcceptActions) {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
// Otherwise do not change order
|
||||||
|
return 0
|
||||||
|
})
|
||||||
|
|
||||||
|
return [ownersWithNoConfirmationsSorted, currentUserNotConfirmed]
|
||||||
}
|
}
|
||||||
|
|
||||||
const OwnersColumn = ({
|
const OwnersColumn = ({
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { push } from 'connected-react-router'
|
import { push } from 'connected-react-router'
|
||||||
import { List, Map, fromJS } from 'immutable'
|
import { List, Map } from 'immutable'
|
||||||
|
import { batch } from 'react-redux'
|
||||||
import semverSatisfies from 'semver/functions/satisfies'
|
import semverSatisfies from 'semver/functions/satisfies'
|
||||||
|
|
||||||
import { onboardUser } from 'src/components/ConnectButton'
|
import { onboardUser } from 'src/components/ConnectButton'
|
||||||
|
@ -22,30 +23,41 @@ import { getLastTx, getNewTxNonce, shouldExecuteTransaction } from 'src/routes/s
|
||||||
import { getErrorMessage } from 'src/test/utils/ethereumErrors'
|
import { getErrorMessage } from 'src/test/utils/ethereumErrors'
|
||||||
import { makeConfirmation } from '../models/confirmation'
|
import { makeConfirmation } from '../models/confirmation'
|
||||||
import fetchTransactions from './transactions/fetchTransactions'
|
import fetchTransactions from './transactions/fetchTransactions'
|
||||||
|
import { safeTransactionsSelector } from 'src/routes/safe/store/selectors'
|
||||||
|
|
||||||
export const removeTxFromStore = (tx, safeAddress, dispatch) => {
|
export const removeTxFromStore = (tx, safeAddress, dispatch, state) => {
|
||||||
if (tx.isCancellationTx) {
|
if (tx.isCancellationTx) {
|
||||||
dispatch(removeCancellationTransaction({ safeAddress, transaction: tx }))
|
const newTxStatus = 'awaiting_confirmations'
|
||||||
|
const transactions = safeTransactionsSelector(state)
|
||||||
|
const txsToUpdate = transactions
|
||||||
|
.filter((transaction) => Number(transaction.nonce) === Number(tx.nonce))
|
||||||
|
.withMutations((list) => list.map((tx) => tx.set('status', newTxStatus)))
|
||||||
|
|
||||||
|
batch(() => {
|
||||||
|
dispatch(addOrUpdateTransactions({ safeAddress, transactions: txsToUpdate }))
|
||||||
|
dispatch(removeCancellationTransaction({ safeAddress, transaction: tx }))
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
dispatch(removeTransaction({ safeAddress, transaction: tx }))
|
dispatch(removeTransaction({ safeAddress, transaction: tx }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const storeTx = async (tx, safeAddress, dispatch) => {
|
export const storeTx = async (tx, safeAddress, dispatch, state) => {
|
||||||
if (tx.isCancellationTx) {
|
if (tx.isCancellationTx) {
|
||||||
dispatch(
|
const newTxStatus = tx.isExecuted ? 'cancelled' : tx.status === 'pending' ? 'pending' : 'awaiting_confirmations'
|
||||||
addOrUpdateCancellationTransactions({
|
const transactions = safeTransactionsSelector(state)
|
||||||
safeAddress,
|
const txsToUpdate = transactions
|
||||||
transactions: Map({ [`${tx.nonce}`]: tx }),
|
.filter((transaction) => Number(transaction.nonce) === Number(tx.nonce))
|
||||||
}),
|
.withMutations((list) =>
|
||||||
)
|
list.map((tx) => tx.set('status', newTxStatus).set('cancelled', newTxStatus === 'cancelled')),
|
||||||
|
)
|
||||||
|
|
||||||
|
batch(() => {
|
||||||
|
dispatch(addOrUpdateCancellationTransactions({ safeAddress, transactions: Map({ [`${tx.nonce}`]: tx }) }))
|
||||||
|
dispatch(addOrUpdateTransactions({ safeAddress, transactions: txsToUpdate }))
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
dispatch(
|
dispatch(addOrUpdateTransactions({ safeAddress, transactions: List([tx]) }))
|
||||||
addOrUpdateTransactions({
|
|
||||||
safeAddress,
|
|
||||||
transactions: List([tx]),
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,15 +163,26 @@ const createTransaction = ({
|
||||||
|
|
||||||
pendingExecutionKey = showSnackbar(notificationsQueue.pendingExecution, enqueueSnackbar, closeSnackbar)
|
pendingExecutionKey = showSnackbar(notificationsQueue.pendingExecution, enqueueSnackbar, closeSnackbar)
|
||||||
|
|
||||||
await Promise.all([saveTxToHistory({ ...txArgs, txHash, origin }), storeTx(mockedTx, safeAddress, dispatch)])
|
await Promise.all([
|
||||||
|
saveTxToHistory({ ...txArgs, txHash, origin }),
|
||||||
|
storeTx(
|
||||||
|
mockedTx.updateIn(
|
||||||
|
['ownersWithPendingActions', mockedTx.isCancellationTx ? 'reject' : 'confirm'],
|
||||||
|
(previous) => previous.push(from),
|
||||||
|
),
|
||||||
|
safeAddress,
|
||||||
|
dispatch,
|
||||||
|
state,
|
||||||
|
),
|
||||||
|
])
|
||||||
dispatch(fetchTransactions(safeAddress))
|
dispatch(fetchTransactions(safeAddress))
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
removeTxFromStore(mockedTx, safeAddress, dispatch)
|
removeTxFromStore(mockedTx, safeAddress, dispatch, state)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.on('error', (error) => {
|
.on('error', (error) => {
|
||||||
closeSnackbar(pendingExecutionKey)
|
closeSnackbar(pendingExecutionKey)
|
||||||
removeTxFromStore(mockedTx, safeAddress, dispatch)
|
removeTxFromStore(mockedTx, safeAddress, dispatch, state)
|
||||||
console.error('Tx error: ', error)
|
console.error('Tx error: ', error)
|
||||||
})
|
})
|
||||||
.then(async (receipt) => {
|
.then(async (receipt) => {
|
||||||
|
@ -188,9 +211,16 @@ const createTransaction = ({
|
||||||
: mockedTx.set('status', 'awaiting_confirmations')
|
: mockedTx.set('status', 'awaiting_confirmations')
|
||||||
|
|
||||||
await storeTx(
|
await storeTx(
|
||||||
toStoreTx.set('confirmations', fromJS([makeConfirmation({ owner: from })])),
|
toStoreTx.withMutations((record) => {
|
||||||
|
record
|
||||||
|
.set('confirmations', List([makeConfirmation({ owner: from })]))
|
||||||
|
.updateIn(['ownersWithPendingActions', toStoreTx.isCancellationTx ? 'reject' : 'confirm'], (previous) =>
|
||||||
|
previous.pop(from),
|
||||||
|
)
|
||||||
|
}),
|
||||||
safeAddress,
|
safeAddress,
|
||||||
dispatch,
|
dispatch,
|
||||||
|
state,
|
||||||
)
|
)
|
||||||
|
|
||||||
dispatch(fetchTransactions(safeAddress))
|
dispatch(fetchTransactions(safeAddress))
|
||||||
|
|
|
@ -117,18 +117,28 @@ const processTransaction = ({
|
||||||
pendingExecutionKey = showSnackbar(notificationsQueue.pendingExecution, enqueueSnackbar, closeSnackbar)
|
pendingExecutionKey = showSnackbar(notificationsQueue.pendingExecution, enqueueSnackbar, closeSnackbar)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await saveTxToHistory({ ...txArgs, txHash })
|
await Promise.all([
|
||||||
await storeTx(mockedTx, safeAddress, dispatch)
|
saveTxToHistory({ ...txArgs, txHash }),
|
||||||
|
storeTx(
|
||||||
|
mockedTx.updateIn(
|
||||||
|
['ownersWithPendingActions', mockedTx.isCancellationTx ? 'reject' : 'confirm'],
|
||||||
|
(previous) => previous.push(from),
|
||||||
|
),
|
||||||
|
safeAddress,
|
||||||
|
dispatch,
|
||||||
|
state,
|
||||||
|
),
|
||||||
|
])
|
||||||
dispatch(fetchTransactions(safeAddress))
|
dispatch(fetchTransactions(safeAddress))
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
closeSnackbar(pendingExecutionKey)
|
closeSnackbar(pendingExecutionKey)
|
||||||
await storeTx(tx, safeAddress, dispatch)
|
await storeTx(tx, safeAddress, dispatch, state)
|
||||||
console.error(e)
|
console.error(e)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.on('error', (error) => {
|
.on('error', (error) => {
|
||||||
closeSnackbar(pendingExecutionKey)
|
closeSnackbar(pendingExecutionKey)
|
||||||
storeTx(mockedTx.set('isSuccessful', false), safeAddress, dispatch)
|
storeTx(tx, safeAddress, dispatch, state)
|
||||||
console.error('Processing transaction error: ', error)
|
console.error('Processing transaction error: ', error)
|
||||||
})
|
})
|
||||||
.then(async (receipt) => {
|
.then(async (receipt) => {
|
||||||
|
@ -159,9 +169,16 @@ const processTransaction = ({
|
||||||
: mockedTx.set('status', 'awaiting_confirmations')
|
: mockedTx.set('status', 'awaiting_confirmations')
|
||||||
|
|
||||||
await storeTx(
|
await storeTx(
|
||||||
toStoreTx.set('confirmations', fromJS([...tx.confirmations, makeConfirmation({ owner: from })])),
|
toStoreTx.withMutations((record) => {
|
||||||
|
record
|
||||||
|
.set('confirmations', fromJS([...tx.confirmations, makeConfirmation({ owner: from })]))
|
||||||
|
.updateIn(['ownersWithPendingActions', toStoreTx.isCancellationTx ? 'reject' : 'confirm'], (previous) =>
|
||||||
|
previous.pop(from),
|
||||||
|
)
|
||||||
|
}),
|
||||||
safeAddress,
|
safeAddress,
|
||||||
dispatch,
|
dispatch,
|
||||||
|
state,
|
||||||
)
|
)
|
||||||
|
|
||||||
dispatch(fetchTransactions(safeAddress))
|
dispatch(fetchTransactions(safeAddress))
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { List, Record } from 'immutable'
|
import { List, Map, Record } from 'immutable'
|
||||||
|
|
||||||
import { ZERO_ADDRESS } from 'src/logic/wallets/ethAddresses'
|
import { ZERO_ADDRESS } from 'src/logic/wallets/ethAddresses'
|
||||||
|
|
||||||
|
@ -22,6 +22,8 @@ export type TransactionStatus =
|
||||||
| 'awaiting_execution'
|
| 'awaiting_execution'
|
||||||
| 'pending'
|
| 'pending'
|
||||||
|
|
||||||
|
export type PendingActionType = 'Confirm' | 'Reject'
|
||||||
|
|
||||||
export type TransactionProps = {
|
export type TransactionProps = {
|
||||||
baseGas: number
|
baseGas: number
|
||||||
blockNumber?: number | null
|
blockNumber?: number | null
|
||||||
|
@ -48,6 +50,7 @@ export type TransactionProps = {
|
||||||
nonce?: number | null
|
nonce?: number | null
|
||||||
operation: number
|
operation: number
|
||||||
origin: string | null
|
origin: string | null
|
||||||
|
ownersWithPendingActions: Map<PendingActionType, List<any>>
|
||||||
recipient: string
|
recipient: string
|
||||||
refundParams: any
|
refundParams: any
|
||||||
refundReceiver: string
|
refundReceiver: string
|
||||||
|
@ -86,6 +89,7 @@ export const makeTransaction = Record({
|
||||||
nonce: 0,
|
nonce: 0,
|
||||||
operation: 0,
|
operation: 0,
|
||||||
origin: null,
|
origin: null,
|
||||||
|
ownersWithPendingActions: Map({ confirm: List([]), reject: List([]) }),
|
||||||
recipient: '',
|
recipient: '',
|
||||||
refundParams: null,
|
refundParams: null,
|
||||||
refundReceiver: ZERO_ADDRESS,
|
refundReceiver: ZERO_ADDRESS,
|
||||||
|
|
Loading…
Reference in New Issue