refactor: notifications middleware

This commit is contained in:
fernandomg 2020-05-22 16:50:10 -03:00
parent c9a01f6892
commit 376af39f3c
3 changed files with 32 additions and 54 deletions

View File

@ -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)
// 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)) {
// 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 transactionWaitingUser.size > 0 return transactionWaitingUser.size > 0
} }
return false return false
}) })
return nonCancelledTransactions
})
return allAwaitingTransactions
} }

View File

@ -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

View File

@ -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,
), ),