import { Dispatch } from 'react' ; import { TransactionResponse } from '@ethersproject/abstract-provider' ; import { appendGasLimit , appendNonce , checkRequiresApproval } from '@helpers' ; import { ProviderHandler } from '@services' ; import { ITxHash , ITxObject , ITxSigned , ITxType , Network , StoreAccount , TStateGetter } from '@types' ; import { isTxHash , isTxSigned , isWeb3Wallet } from '@utils' ; import { filterAsync } from '@utils/asyncFilter' ; import { ActionTypes , TxMultiAction , TxMultiState } from './types' ; export const init = ( dispatch ) => async ( txs , account , network ) => { dispatch ( { type : ActionTypes . INIT_SUCCESS , payload : { txs , account , network } } ) ; } ; export const initWith = ( dispatch ) => async ( getTxs , account , network ) => { dispatch ( { type : ActionTypes . INIT_REQUEST } ) ; try { const txs = await getTxs ( ) ; const filteredTxs = await filterAsync ( txs , async ( tx ) => { if ( network && tx . txType === ITxType . APPROVAL && tx . from && tx . to ) { try { return checkRequiresApproval ( network , tx . to , tx . from , tx . data ) ; } catch ( err ) { console . error ( err ) ; } } return true ; } ) ; dispatch ( { type : ActionTypes . INIT_SUCCESS , payload : { txs : filteredTxs , account , network } } ) ; } catch ( err ) { dispatch ( { type : ActionTypes . INIT_FAILURE , payload : err , error : true } ) ; } } ; export const stopYield = ( dispatch ) => async ( ) => dispatch ( { type : ActionTypes . HALT_FLOW } ) ; export const prepareTx = ( dispatch , getState ) => async ( tx ) => { const { network , account } = getState ( ) ; dispatch ( { type : ActionTypes . PREPARE_TX_REQUEST } ) ; try { const txRaw = await Promise . resolve ( tx ) . then ( appendGasLimit ( network ! ) ) . then ( appendNonce ( network ! , account ! . address ) ) ; dispatch ( { type : ActionTypes . PREPARE_TX_SUCCESS , payload : { txRaw } } ) ; } catch ( err ) { dispatch ( { type : ActionTypes . PREPARE_TX_FAILURE , error : true , payload : err } ) ; } } ; export const sendTx = ( dispatch , getState ) => async ( walletResponse ) => { const { account } = getState ( ) ; dispatch ( { type : ActionTypes . SEND_TX_REQUEST } ) ; const provider = new ProviderHandler ( account ! . network ) ; if ( isTxHash ( walletResponse ) && isWeb3Wallet ( account ! . wallet ) ) { provider . getTransactionByHash ( walletResponse ) . then ( ( txResponse ) => { dispatch ( { type : ActionTypes . SEND_TX_SUCCESS , payload : { txHash : walletResponse , txResponse } } ) ; waitForConfirmation ( dispatch , getState ) ( walletResponse ) ; } ) ; } else if ( isTxHash ( walletResponse ) || isTxSigned ( walletResponse ) ) { provider . sendRawTx ( walletResponse ) . then ( ( txResponse ) => { dispatch ( { type : ActionTypes . SEND_TX_SUCCESS , payload : { txHash : txResponse . hash as ITxHash , txResponse } } ) ; return txResponse . hash ; } ) . then ( ( txHash ) => waitForConfirmation ( dispatch , getState ) ( txHash ) ) . catch ( ( err ) => { dispatch ( { type : ActionTypes . SEND_TX_FAILURE , error : true , payload : err } ) ; } ) ; } else { throw new Error ( `SendTx: unknown walletResponse ${ walletResponse }` ) ; } } ; const waitForConfirmation = ( dispatch , getState ) => async ( txHash ) => { const { account } = getState ( ) ; dispatch ( { type : ActionTypes . CONFIRM_TX_REQUEST } ) ; const provider = new ProviderHandler ( account ! . network ) ; try { const txReceipt = await provider . waitForTransaction ( txHash ) ; const minedAt = await provider . getBlockByNumber ( txReceipt . blockNumber ! ) . then ( ( block ) => block . timestamp ) ; dispatch ( { type : ActionTypes . CONFIRM_TX_SUCCESS , payload : { txReceipt , minedAt } } ) ; } catch ( err ) { dispatch ( { type : ActionTypes . CONFIRM_TX_FAILURE , error : true , payload : err } ) ; } } ; export const reset = ( dispatch ) => async ( ) => { dispatch ( { type : ActionTypes . RESET } ) ; } ;