refactor: FetchTransactions.ts from class to module

This commit is contained in:
fernandomg 2020-05-27 10:36:59 -03:00
parent e08083743d
commit 85b132de6b
5 changed files with 77 additions and 111 deletions

View File

@ -1,69 +0,0 @@
import axios from 'axios'
import { buildTxServiceUrl } from 'src/logic/safe/transactions'
import { buildIncomingTxServiceUrl } from 'src/logic/safe/transactions/incomingTxHistory'
import { TxServiceModel } from 'src/routes/safe/store/actions/transactions/fetchTransactions/loadOutgoingTransactions'
export interface FetchTransactionsInterface {
getServiceUrl(): string
getSafeAddress(): string
setPreviousEtag(eTag: string): void
fetch(): Promise<TxServiceModel[]>
}
class FetchTransactions implements FetchTransactionsInterface {
_fetchConfig: {}
_previousETag?: string | null
_safeAddress?: string | null
_txType = 'outgoing'
_url: string
constructor(safeAddress: string, txType: string) {
this._safeAddress = safeAddress
this._txType = txType
this._url = this.getServiceUrl()
}
getSafeAddress(): string {
return this._safeAddress
}
getServiceUrl(): string {
return {
incoming: buildIncomingTxServiceUrl,
outgoing: buildTxServiceUrl,
}[this._txType](this._safeAddress)
}
setPreviousEtag(eTag: string) {
this._previousETag = eTag ? eTag : this._previousETag
this._fetchConfig = eTag ? { headers: { 'If-None-Match': eTag } } : this._fetchConfig
}
async fetch(): Promise<TxServiceModel[]> {
try {
const response = await axios.get(this._url, this._fetchConfig)
if (response.data.count > 0) {
const { etag } = response.headers
if (this._previousETag !== etag) {
this.setPreviousEtag(etag)
return response.data.results
}
}
} catch (err) {
if (!(err && err.response && err.response.status === 304)) {
console.error(`Requests for outgoing transactions for ${this._safeAddress || 'unknown'} failed with 404`, err)
} else {
// NOTE: this is the expected implementation, currently the backend is not returning 304.
// So I check if the returned etag is the same instead (see above)
}
}
// defaults to an empty array to avoid type errors
return []
}
}
export default FetchTransactions

View File

@ -0,0 +1,58 @@
import axios from 'axios'
import { buildTxServiceUrl } from 'src/logic/safe/transactions'
import { buildIncomingTxServiceUrl } from 'src/logic/safe/transactions/incomingTxHistory'
import { TxServiceModel } from 'src/routes/safe/store/actions/transactions/fetchTransactions/loadOutgoingTransactions'
import { IncomingTxServiceModel } from 'src/routes/safe/store/actions/transactions/fetchTransactions/loadIncomingTransactions'
import { TransactionTypes } from 'src/routes/safe/store/models/types/transaction'
const getServiceUrl = (txType: string, safeAddress: string): string => {
return {
[TransactionTypes.INCOMING]: buildIncomingTxServiceUrl,
[TransactionTypes.OUTGOING]: buildTxServiceUrl,
}[txType](safeAddress)
}
async function fetchTransactions(
txType: TransactionTypes.INCOMING,
safeAddress: string,
eTag: string | null,
): Promise<{ eTag: string | null; results: IncomingTxServiceModel[] }>
async function fetchTransactions(
txType: TransactionTypes.OUTGOING,
safeAddress: string,
eTag: string | null,
): Promise<{ eTag: string | null; results: TxServiceModel[] }>
async function fetchTransactions(
txType: TransactionTypes.INCOMING | TransactionTypes.OUTGOING,
safeAddress: string,
eTag: string | null,
): Promise<{ eTag: string; results: TxServiceModel[] | IncomingTxServiceModel[] }> {
try {
const url = getServiceUrl(txType, safeAddress)
const response = await axios.get(url, eTag ? { headers: { 'If-None-Match': eTag } } : undefined)
if (response.data.count > 0) {
const { etag } = response.headers
if (eTag !== etag) {
return {
eTag: etag,
results: response.data.results,
}
}
}
} catch (err) {
if (!(err && err.response && err.response.status === 304)) {
console.error(`Requests for outgoing transactions for ${safeAddress || 'unknown'} failed with 404`, err)
} else {
// NOTE: this is the expected implementation, currently the backend is not returning 304.
// So I check if the returned etag is the same instead (see above)
}
}
// defaults to an empty array to avoid type errors
return { eTag, results: [] }
}
export default fetchTransactions

View File

@ -28,7 +28,7 @@ export default (safeAddress: string) => async (dispatch) => {
const incomingTransactions = await loadIncomingTransactions(safeAddress)
if (incomingTransactions) {
if (incomingTransactions.get(safeAddress).size) {
dispatch(addIncomingTransactions(incomingTransactions))
}
}

View File

@ -1,14 +1,14 @@
import axios from 'axios'
import bn from 'bignumber.js'
import { List, Map } from 'immutable'
import generateBatchRequests from 'src/logic/contracts/generateBatchRequests'
import { buildIncomingTxServiceUrl } from 'src/logic/safe/transactions/incomingTxHistory'
import { ALTERNATIVE_TOKEN_ABI } from 'src/logic/tokens/utils/alternativeAbi'
import { web3ReadOnly } from 'src/logic/wallets/getWeb3'
import { makeIncomingTransaction } from 'src/routes/safe/store/models/incomingTransaction'
import fetchTransactions from 'src/routes/safe/store/actions/transactions/fetchTransactions/fetchTransactions'
import { TransactionTypes } from 'src/routes/safe/store/models/types/transaction'
type IncomingTxServiceModel = {
export type IncomingTxServiceModel = {
blockNumber: number
transactionHash: string
to: string
@ -68,37 +68,12 @@ const batchIncomingTxsTokenDataRequest = (txs: IncomingTxServiceModel[]) => {
)
}
let prevIncomingTxsEtag = null
let previousETag = null
export const loadIncomingTransactions = async (safeAddress: string) => {
let incomingTransactions: IncomingTxServiceModel[] = []
try {
const config = prevIncomingTxsEtag
? {
headers: {
'If-None-Match': prevIncomingTxsEtag,
},
}
: undefined
const url = buildIncomingTxServiceUrl(safeAddress)
const response = await axios.get(url, config)
if (response.data.count > 0) {
incomingTransactions = response.data.results
if (prevIncomingTxsEtag === response.headers.etag) {
// The txs are the same as we currently have, we don't have to proceed
return
}
prevIncomingTxsEtag = response.headers.etag
}
} catch (err) {
if (err && err.response && err.response.status === 304) {
// We return cached transactions
return
} else {
console.error(`Requests for incoming transactions for ${safeAddress} failed with 404`, err)
}
}
const { eTag, results } = await fetchTransactions(TransactionTypes.INCOMING, safeAddress, previousETag)
previousETag = eTag
const incomingTxsWithData = await batchIncomingTxsTokenDataRequest(incomingTransactions)
const incomingTxsWithData = await batchIncomingTxsTokenDataRequest(results)
const incomingTxsRecord = incomingTxsWithData.map(buildIncomingTransactionFrom)
return Map({ [safeAddress]: List(incomingTxsRecord) })
}

View File

@ -1,14 +1,15 @@
import { List, Map, fromJS } from 'immutable'
import { fromJS, List, Map } from 'immutable'
import generateBatchRequests from 'src/logic/contracts/generateBatchRequests'
import { TOKEN_REDUCER_ID } from 'src/logic/tokens/store/reducer/tokens'
import { web3ReadOnly } from 'src/logic/wallets/getWeb3'
import { PROVIDER_REDUCER_ID } from 'src/logic/wallets/store/reducer/provider'
import FetchTransactions from 'src/routes/safe/store/actions/transactions/fetchTransactions/FetchTransactions'
import { buildTx, isCancelTransaction } from 'src/routes/safe/store/actions/transactions/utils/transactionHelpers'
import { SAFE_REDUCER_ID } from 'src/routes/safe/store/reducer/safe'
import { store } from 'src/store'
import { DecodedMethods } from 'src/logic/contracts/methodIds'
import fetchTransactions from 'src/routes/safe/store/actions/transactions/fetchTransactions/fetchTransactions'
import { TransactionTypes } from 'src/routes/safe/store/models/types/transaction'
export type ConfirmationServiceModel = {
owner: string
@ -167,7 +168,7 @@ const batchProcessOutgoingTransactions = async ({
return { cancel, outgoing }
}
let fetchOutgoingTxs: FetchTransactions | null = null
let previousETag = null
export const loadOutgoingTransactions = async (safeAddress: string): Promise<SafeTransactionsType> => {
const defaultResponse = {
cancel: Map(),
@ -187,12 +188,13 @@ export const loadOutgoingTransactions = async (safeAddress: string): Promise<Saf
return defaultResponse
}
fetchOutgoingTxs =
!fetchOutgoingTxs || fetchOutgoingTxs.getSafeAddress() !== safeAddress
? new FetchTransactions(safeAddress, 'outgoing')
: fetchOutgoingTxs
const outgoingTransactions: TxServiceModel[] = await fetchOutgoingTxs.fetch()
const { cancellationTxs, outgoingTxs } = extractCancelAndOutgoingTxs(safeAddress, outgoingTransactions)
const { eTag, results }: { eTag: string | null; results: TxServiceModel[] } = await fetchTransactions(
TransactionTypes.OUTGOING,
safeAddress,
previousETag,
)
previousETag = eTag
const { cancellationTxs, outgoingTxs } = extractCancelAndOutgoingTxs(safeAddress, results)
// this should be only used for the initial load or when paginating
const { cancel, outgoing } = await batchProcessOutgoingTransactions({