refactor: notifications middleware
This commit is contained in:
parent
c9a01f6892
commit
376af39f3c
|
@ -1,33 +1,18 @@
|
||||||
import { Map } from 'immutable'
|
import { List } from 'immutable'
|
||||||
|
|
||||||
export const getAwaitingTransactions = (allTransactions, cancellationTransactionsByNonce, userAccount) => {
|
import { isPendingTransaction } from 'src/routes/safe/store/actions/transactions/utils/transactionHelpers'
|
||||||
if (!allTransactions) {
|
|
||||||
return Map({})
|
|
||||||
}
|
|
||||||
|
|
||||||
const allAwaitingTransactions = allTransactions.map((safeTransactions) => {
|
export const getAwaitingTransactions = (allTransactions = List([]), cancellationTxs, userAccount: string) => {
|
||||||
const nonCancelledTransactions = safeTransactions.filter((transaction) => {
|
return allTransactions.filter((tx) => {
|
||||||
// If transactions are not executed, but there's a transaction with the same nonce EXECUTED later
|
const cancelTx = !!tx.nonce && !isNaN(Number(tx.nonce)) ? cancellationTxs.get(`${tx.nonce}`) : null
|
||||||
// it means that the transaction was cancelled (Replaced) and shouldn't get executed
|
|
||||||
let isTransactionCancelled = false
|
|
||||||
if (!transaction.isExecuted) {
|
|
||||||
if (cancellationTransactionsByNonce.get(transaction.nonce)) {
|
|
||||||
// eslint-disable-next-line no-param-reassign
|
|
||||||
isTransactionCancelled = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// The transaction is not executed and is not cancelled, so it's still waiting confirmations
|
|
||||||
if (!transaction.executionTxHash && !isTransactionCancelled) {
|
|
||||||
// Then we check if the waiting confirmations are not from the current user, otherwise, filters this
|
|
||||||
// transaction
|
|
||||||
const transactionWaitingUser = transaction.confirmations.filter(({ owner }) => owner !== userAccount)
|
|
||||||
|
|
||||||
return transactionWaitingUser.size > 0
|
// The transaction is not executed and is not cancelled, nor pending, so it's still waiting confirmations
|
||||||
}
|
if (!tx.executionTxHash && !tx.cancelled && !isPendingTransaction(tx, cancelTx)) {
|
||||||
return false
|
// Then we check if the waiting confirmations are not from the current user, otherwise, filters this transaction
|
||||||
})
|
const transactionWaitingUser = tx.confirmations.filter(({ owner }) => owner !== userAccount)
|
||||||
return nonCancelledTransactions
|
return transactionWaitingUser.size > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
})
|
})
|
||||||
|
|
||||||
return allAwaitingTransactions
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { push } from 'connected-react-router'
|
import { push } from 'connected-react-router'
|
||||||
import { List, Map } from 'immutable'
|
|
||||||
|
|
||||||
import { NOTIFICATIONS, enhanceSnackbarForAction } from 'src/logic/notifications'
|
import { NOTIFICATIONS, enhanceSnackbarForAction } from 'src/logic/notifications'
|
||||||
import closeSnackbarAction from 'src/logic/notifications/store/actions/closeSnackbar'
|
import closeSnackbarAction from 'src/logic/notifications/store/actions/closeSnackbar'
|
||||||
|
@ -12,13 +11,14 @@ import { getIncomingTxAmount } from 'src/routes/safe/components/Transactions/Txs
|
||||||
import { grantedSelector } from 'src/routes/safe/container/selector'
|
import { grantedSelector } from 'src/routes/safe/container/selector'
|
||||||
import { ADD_INCOMING_TRANSACTIONS } from 'src/routes/safe/store/actions/addIncomingTransactions'
|
import { ADD_INCOMING_TRANSACTIONS } from 'src/routes/safe/store/actions/addIncomingTransactions'
|
||||||
import { ADD_SAFE } from 'src/routes/safe/store/actions/addSafe'
|
import { ADD_SAFE } from 'src/routes/safe/store/actions/addSafe'
|
||||||
import { ADD_TRANSACTIONS } from 'src/routes/safe/store/actions/addTransactions'
|
import { ADD_OR_UPDATE_TRANSACTIONS } from 'src/routes/safe/store/actions/transactions/addOrUpdateTransactions'
|
||||||
import updateSafe from 'src/routes/safe/store/actions/updateSafe'
|
import updateSafe from 'src/routes/safe/store/actions/updateSafe'
|
||||||
|
import { CANCELLATION_TRANSACTIONS_REDUCER_ID } from 'src/routes/safe/store/reducer/cancellationTransactions'
|
||||||
import { safeParamAddressFromStateSelector, safesMapSelector } from 'src/routes/safe/store/selectors'
|
import { safeParamAddressFromStateSelector, safesMapSelector } from 'src/routes/safe/store/selectors'
|
||||||
|
|
||||||
import { loadFromStorage, saveToStorage } from 'src/utils/storage'
|
import { loadFromStorage, saveToStorage } from 'src/utils/storage'
|
||||||
|
|
||||||
const watchedActions = [ADD_TRANSACTIONS, ADD_INCOMING_TRANSACTIONS, ADD_SAFE]
|
const watchedActions = [ADD_OR_UPDATE_TRANSACTIONS, ADD_INCOMING_TRANSACTIONS, ADD_SAFE]
|
||||||
|
|
||||||
const sendAwaitingTransactionNotification = async (
|
const sendAwaitingTransactionNotification = async (
|
||||||
dispatch,
|
dispatch,
|
||||||
|
@ -59,48 +59,41 @@ const sendAwaitingTransactionNotification = async (
|
||||||
await saveToStorage(LAST_TIME_USED_LOGGED_IN_ID, lastTimeUserLoggedInForSafes)
|
await saveToStorage(LAST_TIME_USED_LOGGED_IN_ID, lastTimeUserLoggedInForSafes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onNotificationClicked = (dispatch, notificationKey, safeAddress) => () => {
|
||||||
|
dispatch(closeSnackbarAction({ key: notificationKey }))
|
||||||
|
dispatch(push(`/safes/${safeAddress}/transactions`))
|
||||||
|
}
|
||||||
|
|
||||||
const notificationsMiddleware = (store) => (next) => async (action) => {
|
const notificationsMiddleware = (store) => (next) => async (action) => {
|
||||||
const handledAction = next(action)
|
const handledAction = next(action)
|
||||||
const { dispatch } = store
|
const { dispatch } = store
|
||||||
|
|
||||||
if (watchedActions.includes(action.type)) {
|
if (watchedActions.includes(action.type)) {
|
||||||
const state = store.getState()
|
const state = store.getState()
|
||||||
|
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case ADD_TRANSACTIONS: {
|
case ADD_OR_UPDATE_TRANSACTIONS: {
|
||||||
const transactionsList = action.payload
|
const { safeAddress, transactions } = action.payload
|
||||||
const userAddress = userAccountSelector(state)
|
const userAddress: string = userAccountSelector(state)
|
||||||
const safeAddress = action.payload.keySeq().get(0)
|
const cancellationTransactions = state[CANCELLATION_TRANSACTIONS_REDUCER_ID].get(safeAddress)
|
||||||
const cancellationTransactions = state.cancellationTransactions.get(safeAddress)
|
const awaitingTransactions = getAwaitingTransactions(transactions, cancellationTransactions, userAddress)
|
||||||
const cancellationTransactionsByNonce = cancellationTransactions
|
const awaitingTxsSubmissionDateList = awaitingTransactions.map((tx) => tx.submissionDate)
|
||||||
? cancellationTransactions.reduce((acc, tx) => acc.set(tx.nonce, tx), Map())
|
|
||||||
: Map()
|
|
||||||
const awaitingTransactions = getAwaitingTransactions(
|
|
||||||
transactionsList,
|
|
||||||
cancellationTransactionsByNonce,
|
|
||||||
userAddress,
|
|
||||||
)
|
|
||||||
const awaitingTxsSubmissionDateList = awaitingTransactions
|
|
||||||
.get(safeAddress, List([]))
|
|
||||||
.map((tx) => tx.submissionDate)
|
|
||||||
|
|
||||||
const safes = safesMapSelector(state)
|
const safes = safesMapSelector(state)
|
||||||
const currentSafe = safes.get(safeAddress)
|
const currentSafe = safes.get(safeAddress)
|
||||||
|
|
||||||
if (!isUserOwner(currentSafe, userAddress) || awaitingTxsSubmissionDateList.size === 0) {
|
if (!isUserOwner(currentSafe, userAddress) || awaitingTransactions.size === 0) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
const notificationKey = `${safeAddress}-awaiting`
|
const notificationKey = `${safeAddress}-awaiting`
|
||||||
const onNotificationClicked = () => {
|
|
||||||
dispatch(closeSnackbarAction({ key: notificationKey }))
|
|
||||||
dispatch(push(`/safes/${safeAddress}/transactions`))
|
|
||||||
}
|
|
||||||
|
|
||||||
await sendAwaitingTransactionNotification(
|
await sendAwaitingTransactionNotification(
|
||||||
dispatch,
|
dispatch,
|
||||||
safeAddress,
|
safeAddress,
|
||||||
awaitingTxsSubmissionDateList,
|
awaitingTxsSubmissionDateList,
|
||||||
notificationKey,
|
notificationKey,
|
||||||
onNotificationClicked,
|
onNotificationClicked(dispatch, notificationKey, safeAddress),
|
||||||
)
|
)
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
|
@ -38,9 +38,9 @@ const finalCreateStore = composeEnhancers(
|
||||||
applyMiddleware(
|
applyMiddleware(
|
||||||
thunk,
|
thunk,
|
||||||
routerMiddleware(history),
|
routerMiddleware(history),
|
||||||
|
notificationsMiddleware,
|
||||||
safeStorage,
|
safeStorage,
|
||||||
providerWatcher,
|
providerWatcher,
|
||||||
notificationsMiddleware,
|
|
||||||
addressBookMiddleware,
|
addressBookMiddleware,
|
||||||
currencyValuesStorageMiddleware,
|
currencyValuesStorageMiddleware,
|
||||||
),
|
),
|
||||||
|
|
Loading…
Reference in New Issue