From 8de5f8194d7cdf88d30bf57a448f55bfadf204eb Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Tue, 9 Jan 2024 11:42:11 +0100 Subject: [PATCH] chore: Remove transfers-history implementation This is unsued code that will impose unnecessary work in the v2 -> v3 migration. --- src/transfers-history/README.md | 48 ---- src/transfers-history/adapters/README.md | 3 - src/transfers-history/adapters/db/index.ts | 1 - .../adapters/db/transfers-repository.ts | 208 --------------- src/transfers-history/adapters/logger.ts | 34 --- .../adapters/web3/SpokePoolEventsQuerier.ts | 147 ---------- src/transfers-history/adapters/web3/index.ts | 1 - src/transfers-history/adapters/web3/model.ts | 14 - src/transfers-history/client.ts | 250 ------------------ src/transfers-history/config.ts | 13 - src/transfers-history/index.ts | 2 - src/transfers-history/model/README.md | 3 - src/transfers-history/model/index.ts | 1 - src/transfers-history/model/transfer.ts | 20 -- src/transfers-history/services/README.md | 6 - .../services/SpokePoolEventsQueryService.ts | 120 --------- 16 files changed, 871 deletions(-) delete mode 100644 src/transfers-history/README.md delete mode 100644 src/transfers-history/adapters/README.md delete mode 100644 src/transfers-history/adapters/db/index.ts delete mode 100644 src/transfers-history/adapters/db/transfers-repository.ts delete mode 100644 src/transfers-history/adapters/logger.ts delete mode 100644 src/transfers-history/adapters/web3/SpokePoolEventsQuerier.ts delete mode 100644 src/transfers-history/adapters/web3/index.ts delete mode 100644 src/transfers-history/adapters/web3/model.ts delete mode 100644 src/transfers-history/client.ts delete mode 100644 src/transfers-history/config.ts delete mode 100644 src/transfers-history/index.ts delete mode 100644 src/transfers-history/model/README.md delete mode 100644 src/transfers-history/model/index.ts delete mode 100644 src/transfers-history/model/transfer.ts delete mode 100644 src/transfers-history/services/README.md delete mode 100644 src/transfers-history/services/SpokePoolEventsQueryService.ts diff --git a/src/transfers-history/README.md b/src/transfers-history/README.md deleted file mode 100644 index d449540b1..000000000 --- a/src/transfers-history/README.md +++ /dev/null @@ -1,48 +0,0 @@ -# Transfers history client - -This client is used for fetching the history of the assets tranferred between chains using Across V2 contracts. - -## Usage -```ts -import { transfersHistory } from "@across/sdk-v2" - -const { TransfersHistoryClient } = transfersHistory; - -const client = new TransfersHistoryClient({ - chains: [ - { chainId: , - provider: , - spokePoolContractAddr: , - lowerBoundBlockNumber: , - } - ], - // optional - pollingIntervalSeconds: -}); -// optional -client.setLogLevel("debug"); -await client.startFetchingTransfers(); -client.on(TransfersHistoryEvent.TransfersUpdated, data => { - const { depositorAddr, filledTransfersCount, pendingTransfersCount } = data; - // do whatever you need with the data -}); - -const pendingTransfers = client.getPendingTransfers(, , ); -/** - * - * Transfers type: - * { - * depositId: number; - * depositTime: number; - * status: TransferStatus; - * filled: BigNumber; - * sourceChainId: ChainId; - * destinationChainId: number; - * assetAddr: string; - * amount: BigNumber; - * depositTxHash: string; - * }[] - */ -const filledTransfers = client.getFilledTransfers(, , ); -client.stopFetchingTransfers(); -``` diff --git a/src/transfers-history/adapters/README.md b/src/transfers-history/adapters/README.md deleted file mode 100644 index 26ba8b7dc..000000000 --- a/src/transfers-history/adapters/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Adapters - -Use this directory to isolate the logic for interfacing with any external actor/service (databases, blockchains, console, etc). Usually this is the only place where the libraries for using the external actors/services are imported. diff --git a/src/transfers-history/adapters/db/index.ts b/src/transfers-history/adapters/db/index.ts deleted file mode 100644 index 891bfa85b..000000000 --- a/src/transfers-history/adapters/db/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./transfers-repository"; diff --git a/src/transfers-history/adapters/db/transfers-repository.ts b/src/transfers-history/adapters/db/transfers-repository.ts deleted file mode 100644 index c5dec4109..000000000 --- a/src/transfers-history/adapters/db/transfers-repository.ts +++ /dev/null @@ -1,208 +0,0 @@ -import { BigNumber } from "ethers"; -import { Transfer } from "../../model"; -import { ChainId, CHAIN_IDs } from "../web3/model"; - -type TransfersStore = { - [chainId: number]: { - [address: string]: { - [depositId: number]: Transfer; - }; - }; -}; - -type UsersTransfersStore = { - [address: string]: { - pending: Transfer[]; - filled: Transfer[]; - }; -}; - -const usersTransfersStoreInitialValue: UsersTransfersStore = {}; - -const transfersStoreInitialValue: TransfersStore = { - [CHAIN_IDs.GOERLI]: {}, - [CHAIN_IDs.POLYGON]: {}, - [CHAIN_IDs.MAINNET]: {}, -}; - -export class TransfersRepository { - public transfers: TransfersStore = transfersStoreInitialValue; - public usersTransfers: UsersTransfersStore = usersTransfersStoreInitialValue; - - public insertTransfer(chainId: ChainId, depositorAddr: string, depositId: number, transfer: Transfer) { - if (!this.transfers[chainId]) { - this.transfers[chainId] = {}; - } - - if (!this.transfers[chainId][depositorAddr]) { - this.transfers[chainId][depositorAddr] = {}; - } - - if (this.transfers[chainId][depositorAddr][depositId]) { - return; - } - - this.transfers[chainId][depositorAddr][depositId] = transfer; - } - - public updateFilledAmount( - chainId: ChainId, - depositorAddr: string, - depositId: number, - filled: BigNumber, - fillTxHash: string, - appliedRelayerFeePct: BigNumber - ) { - const transfer = this.transfers?.[chainId]?.[depositorAddr]?.[depositId]; - if (!transfer) { - console.error(`couldn't fill deposit on chain ${chainId}, depositId ${depositId}, depositor ${depositorAddr}`); - return; - } - - this.transfers[chainId][depositorAddr][depositId] = { - ...transfer, - filled, - status: transfer.amount.eq(filled) ? "filled" : "pending", - fillTxs: Array.from(new Set([...transfer.fillTxs, fillTxHash])), - currentRelayerFeePct: appliedRelayerFeePct, - }; - } - - public updateRelayerFee( - sourceChainId: number, - depositorAddr: string, - depositId: number, - newRelayerFeePct: BigNumber, - speedUpTxHash: string, - timestamp: number - ) { - const transfer = this.transfers?.[sourceChainId]?.[depositorAddr]?.[depositId]; - - if (!transfer) { - console.error( - `couldn't update 'relayerFee' on chain ${sourceChainId}, depositId ${depositId}, depositor ${depositorAddr}` - ); - return; - } - - this.transfers[transfer.sourceChainId][depositorAddr][depositId] = { - ...transfer, - currentRelayerFeePct: transfer.status === "pending" ? newRelayerFeePct : transfer.currentRelayerFeePct, - speedUps: [ - // remove possible duplicates - ...transfer.speedUps.filter((speedUp) => speedUp.txHash !== speedUpTxHash), - { - txHash: speedUpTxHash, - relayerFeePct: newRelayerFeePct, - timestamp, - }, - ], - }; - } - - public getTransfersByChainAndDepositor(chainId: ChainId, depositorAddr: string) { - if (this.transfers[chainId][depositorAddr]) { - return Object.values(this.transfers[chainId][depositorAddr]); - } - - return []; - } - - public setDepositorPendingTransfers(depositorAddr: string, transfers: Transfer[]) { - if (!this.usersTransfers[depositorAddr]) { - this.usersTransfers[depositorAddr] = { pending: [], filled: [] }; - } - this.usersTransfers[depositorAddr].pending = transfers; - } - - public setDepositorFilledTransfers(depositorAddr: string, transfers: Transfer[]) { - if (!this.usersTransfers[depositorAddr]) { - this.usersTransfers[depositorAddr] = { filled: [], pending: [] }; - } - - this.usersTransfers[depositorAddr].filled = transfers; - } - - public aggregateTransfers() { - const chainsIds = Object.keys(this.transfers).map((chainId) => parseInt(chainId)); - const depositors = chainsIds.reduce( - (acc, chainId) => [...acc, ...Object.keys(this.transfers[chainId])], - [] as string[] - ); - - for (const depositorAddr of depositors) { - const transfers: Transfer[] = []; - - for (const chainId of chainsIds) { - transfers.push(...this.getTransfersByChainAndDepositor(chainId, depositorAddr)); - } - - // sort transfers by deposit time in descending order - transfers.sort((t1, t2) => t2.depositTime - t1.depositTime); - - // filter events by status - const filteredTransfers = transfers.reduce( - (acc, transfer) => ({ - pending: transfer.status === "pending" ? [...acc.pending, transfer] : acc.pending, - filled: transfer.status === "filled" ? [...acc.filled, transfer] : acc.filled, - }), - { pending: [] as Transfer[], filled: [] as Transfer[] } - ); - - this.setDepositorFilledTransfers(depositorAddr, filteredTransfers.filled); - this.setDepositorPendingTransfers(depositorAddr, filteredTransfers.pending); - } - } - - public getFilledTransfers(depositorAddr: string, limit?: number, offset?: number) { - const transfers = this.usersTransfers[depositorAddr]?.filled || []; - - if (transfers.length === 0) { - return transfers; - } - - return transfers.slice(offset, limit && offset ? limit + offset : limit); - } - - public getAllFilledTransfers(limit?: number, offset?: number) { - return Object.values(this.usersTransfers) - .flatMap((t) => t.filled) - .sort((t1, t2) => t2.depositTime - t1.depositTime) - .slice(offset, limit && offset ? limit + offset : limit); - } - - public getPendingTransfers(depositorAddr: string, limit?: number, offset?: number) { - const transfers = this.usersTransfers[depositorAddr]?.pending || []; - - if (transfers.length === 0) { - return transfers; - } - - return transfers.slice(offset, limit && offset ? limit + offset : limit); - } - - public getAllPendingTransfers(limit?: number, offset?: number) { - return Object.values(this.usersTransfers) - .flatMap((t) => t.pending) - .sort((t1, t2) => t2.depositTime - t1.depositTime) - .slice(offset, limit && offset ? limit + offset : limit); - } - - public countFilledTransfers(depositorAddr: string) { - const transfers = this.usersTransfers[depositorAddr]?.filled || []; - return transfers.length; - } - - public countAllFilledTransfers() { - return Object.values(this.usersTransfers).flatMap((t) => t.filled).length; - } - - public countPendingTransfers(depositorAddr: string) { - const transfers = this.usersTransfers[depositorAddr]?.pending || []; - return transfers.length; - } - - public countAllPendingTransfers() { - return Object.values(this.usersTransfers).flatMap((t) => t.pending).length; - } -} diff --git a/src/transfers-history/adapters/logger.ts b/src/transfers-history/adapters/logger.ts deleted file mode 100644 index 71c19e742..000000000 --- a/src/transfers-history/adapters/logger.ts +++ /dev/null @@ -1,34 +0,0 @@ -enum CliColor { - Reset = "\x1b[0m", - FgGreen = "\x1b[32m", - FgYellow = "\x1b[33m", - FgReg = "\x1b[31m", -} - -export type LogLevel = "info" | "debug"; - -export class Logger { - private currentLevel: LogLevel; - - public constructor(level?: LogLevel) { - this.currentLevel = level || "info"; - } - - public setLevel(level: LogLevel) { - this.currentLevel = level; - } - - public debug(caller: string, message: string) { - if (this.currentLevel === "debug") { - console.debug(`${new Date().toISOString()} - `, CliColor.FgYellow, caller, CliColor.Reset, message); - } - } - - public info(caller: string, message: string) { - console.log(`${new Date().toISOString()} - `, CliColor.FgGreen, caller, CliColor.Reset, message); - } - - public error(caller: string, message: string) { - console.error(`${new Date().toISOString()} - `, CliColor.FgReg, caller, CliColor.Reset, message); - } -} diff --git a/src/transfers-history/adapters/web3/SpokePoolEventsQuerier.ts b/src/transfers-history/adapters/web3/SpokePoolEventsQuerier.ts deleted file mode 100644 index 0ed5cfd41..000000000 --- a/src/transfers-history/adapters/web3/SpokePoolEventsQuerier.ts +++ /dev/null @@ -1,147 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { SpokePool, TypedEvent, TypedEventFilter } from "../../../typechain"; -import { getSamplesBetween } from "../../../utils"; -import { Web3Error, Web3ErrorCode } from "./model"; -import { Logger } from "../logger"; - -const DEFAULT_BLOCK_RANGE = 100_000; - -/** - * Interface implemented by classes that fetch contract events from the SpokePool contracts - */ -export interface ISpokePoolContractEventsQuerier { - getFundsDepositEvents: (from: number, to: number, depositorAddr?: string) => Promise[]>; - getFilledRelayEvents: (from: number, to: number, depositorAddr?: string) => Promise[]>; - getSpeedUpDepositEvents: (from: number, to: number, depositorAddr?: string) => Promise[]>; -} - -/** - * Class that wraps the queryFilter calls and has the ability to resize the block range - * in order to comply with the eventual node restrictions in terms of the block range or the - * length of the response - */ -export class SpokePoolEventsQuerier implements ISpokePoolContractEventsQuerier { - constructor( - private spokePool: SpokePool, - private blockRangeSize?: number, - private logger?: Logger - ) {} - - public getFundsDepositEvents(from: number, to: number, depositorAddr?: string): Promise[]> { - return this.getEvents(from, to, this.getDepositEventsFilters(depositorAddr)); - } - - public getFilledRelayEvents(from: number, to: number, depositorAddr?: string): Promise[]> { - return this.getEvents(from, to, this.getFilledRelayEventsFilter(depositorAddr)); - } - - public getSpeedUpDepositEvents(from: number, to: number, depositorAddr?: string): Promise[]> { - return this.getEvents(from, to, this.getSpeedUpDepositEventsFilter(depositorAddr)); - } - - private getFilledRelayEventsFilter(depositorAddr?: string) { - if (depositorAddr) { - return this.spokePool.filters.FilledRelay( - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - depositorAddr, - undefined, - undefined, - undefined - ); - } - return this.spokePool.filters.FilledRelay(); - } - - private getDepositEventsFilters(depositorAddr?: string) { - if (depositorAddr) { - return this.spokePool.filters.FundsDeposited( - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - depositorAddr.toLowerCase() - ); - } - return this.spokePool.filters.FundsDeposited(); - } - - private getSpeedUpDepositEventsFilter(depositorAddr?: string) { - if (depositorAddr) { - return this.spokePool.filters.RequestedSpeedUpDeposit( - undefined, - undefined, - depositorAddr.toLowerCase(), - undefined - ); - } - return this.spokePool.filters.RequestedSpeedUpDeposit(); - } - - private async getEvents(from: number, to: number, filters: TypedEventFilter): Promise[]> { - let events: TypedEvent[] = []; - let retryWithLowerBatchSize; - - do { - const blockRangeSizeAtStart = this.blockRangeSize; - try { - retryWithLowerBatchSize = false; - events = []; - - if (this.blockRangeSize) { - const intervals = getSamplesBetween(from, to, this.blockRangeSize); - // query events only for the first interval to make sure block range is fine - const [intervalStart, intervalEnd] = intervals[0]; - const newEvents = await this.spokePool.queryFilter(filters, intervalStart, intervalEnd); - events.push(...newEvents); - - // query the rest of block intervals in parallel in order to get the events - const newEventsList = await Promise.all( - intervals - .slice(1) - .map(([intervalStart, intervalEnd]) => this.spokePool.queryFilter(filters, intervalStart, intervalEnd)) - ); - events.push(...newEventsList.flat()); - } else { - const newEvents = await this.spokePool.queryFilter(filters, from, to); - events.push(...newEvents); - } - } catch (error) { - if ( - (error as Web3Error).error.code === Web3ErrorCode.BLOCK_RANGE_TOO_LARGE || - (error as Web3Error).error.code === Web3ErrorCode.EXCEEDED_MAXIMUM_BLOCK_RANGE - ) { - // make sure the block range size wasn't modified by a parallel function call - if (this.blockRangeSize === blockRangeSizeAtStart) { - const newBlockRangeSize = this.blockRangeSize ? this.blockRangeSize / 2 : DEFAULT_BLOCK_RANGE; - this.logger?.debug( - "[SpokePoolEventsQuerier::getEventsInBatches]", - `🔴 lowering block range size from ${this.blockRangeSize} to ${newBlockRangeSize}` - ); - this.blockRangeSize = newBlockRangeSize; - } - retryWithLowerBatchSize = true; - } else { - retryWithLowerBatchSize = false; - console.error(error); - throw error; - } - } - } while (retryWithLowerBatchSize); - - return events; - } -} diff --git a/src/transfers-history/adapters/web3/index.ts b/src/transfers-history/adapters/web3/index.ts deleted file mode 100644 index ae722abe7..000000000 --- a/src/transfers-history/adapters/web3/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./SpokePoolEventsQuerier"; diff --git a/src/transfers-history/adapters/web3/model.ts b/src/transfers-history/adapters/web3/model.ts deleted file mode 100644 index 6360fafeb..000000000 --- a/src/transfers-history/adapters/web3/model.ts +++ /dev/null @@ -1,14 +0,0 @@ -export { CHAIN_IDs } from "../../../constants"; - -export type Web3Error = { - error: { - code: Web3ErrorCode; - }; -}; - -export enum Web3ErrorCode { - BLOCK_RANGE_TOO_LARGE = -32005, - EXCEEDED_MAXIMUM_BLOCK_RANGE = -32000, -} - -export type ChainId = number; diff --git a/src/transfers-history/client.ts b/src/transfers-history/client.ts deleted file mode 100644 index c6fce377e..000000000 --- a/src/transfers-history/client.ts +++ /dev/null @@ -1,250 +0,0 @@ -import EventEmitter from "events"; -import { clientConfig } from "./config"; -import { SpokePoolEventsQueryService } from "./services/SpokePoolEventsQueryService"; -import { Logger, LogLevel } from "./adapters/logger"; -import { BigNumber, providers, ethers } from "ethers"; -import { ChainId } from "./adapters/web3/model"; -import { SpokePoolEventsQuerier } from "./adapters/web3"; -import { TransfersRepository } from "./adapters/db/transfers-repository"; -import { - SpokePool, - SpokePool__factory, - FilledRelayEvent, - FundsDepositedEvent, - RequestedSpeedUpDepositEvent, -} from "../typechain"; -import { Transfer } from "./model"; - -export enum TransfersHistoryEvent { - TransfersUpdated = "TransfersUpdated", -} - -export type TransfersUpdatedEventListenerParams = { - depositorAddr: string; - filledTransfersCount: number; - pendingTransfersCount: number; -}; - -export type TrackableAddress = "all" | string; - -export type TransfersUpdatedEventListener = (params: TransfersUpdatedEventListenerParams) => void; -export type TransfersHistoryClientEventListener = TransfersUpdatedEventListener; -export type TransfersHistoryClientParams = { - chains: { - chainId: ChainId; - provider: providers.Provider; - spokePoolContractAddr: string; - lowerBoundBlockNumber?: number; - }[]; - pollingIntervalSeconds?: number; -}; - -export class TransfersHistoryClient { - private eventEmitter = new EventEmitter(); - private web3Providers: Record = {}; - private spokePoolInstances: Record = {}; - private eventsQueriers: Record = {}; - private eventsServices: Record> = {}; - private pollingIntervalSeconds = 15; - private pollingTimers: Record = {}; - private fetchingState: Record = {}; - - constructor( - config: TransfersHistoryClientParams, - private logger = new Logger(), - private transfersRepository = new TransfersRepository() - ) { - if (typeof config.pollingIntervalSeconds === "number") { - this.pollingIntervalSeconds = config.pollingIntervalSeconds; - } - - for (const chain of config.chains) { - this.web3Providers[chain.chainId] = chain.provider; - this.spokePoolInstances[chain.chainId] = SpokePool__factory.connect( - chain.spokePoolContractAddr, - this.web3Providers[chain.chainId] - ); - this.eventsQueriers[chain.chainId] = new SpokePoolEventsQuerier( - this.spokePoolInstances[chain.chainId], - undefined, - this.logger - ); - clientConfig.spokePools[chain.chainId] = { lowerBoundBlockNumber: chain.lowerBoundBlockNumber || 0 }; - } - } - - public setLogLevel(level: LogLevel) { - this.logger.setLevel(level); - } - - public async startFetchingTransfers(depositorAddr: TrackableAddress) { - this.fetchingState[depositorAddr] = "started"; - this.initSpokePoolEventsQueryServices(depositorAddr); - await this.getEventsForDepositor(depositorAddr); - // mark that we started fetching events for depositor address - // add polling if user didn't opted out for polling - if (this.pollingIntervalSeconds > 0) { - let timer = this.pollingTimers[depositorAddr]; - - // prevent triggering multiple polling intervals for the same address - if (timer) throw new Error(`Address ${depositorAddr} is already monitored`); - - timer = setInterval(async () => { - await this.getEventsForDepositor(depositorAddr); - }, this.pollingIntervalSeconds * 1000); - this.pollingTimers[depositorAddr] = timer; - } - } - - public stopFetchingTransfers(depositorAddr: string) { - const timer = this.pollingTimers[depositorAddr]; - // mark that the fetching stopped for depositor address - this.fetchingState[depositorAddr] = "stopped"; - if (timer) { - clearInterval(timer); - delete this.pollingTimers[depositorAddr]; - } - } - - public on(event: TransfersHistoryEvent, cb: TransfersHistoryClientEventListener) { - this.eventEmitter.on(event, cb); - } - - private initSpokePoolEventsQueryServices(depositorAddr: TrackableAddress) { - const chainIds = Object.keys(this.spokePoolInstances).map((chainId) => parseInt(chainId)); - - for (const chainId of chainIds) { - if (!this.eventsServices[depositorAddr]) { - this.eventsServices[depositorAddr] = {}; - } - - if (!this.eventsServices[depositorAddr][chainId]) { - this.eventsServices[depositorAddr][chainId] = new SpokePoolEventsQueryService( - chainId, - this.web3Providers[chainId], - this.eventsQueriers[chainId], - this.logger, - depositorAddr !== "all" ? depositorAddr : undefined - ); - } - } - } - - private async getEventsForDepositor(depositorAddr: TrackableAddress) { - // query all chains to get the events for the depositor address - const events = await Promise.all( - Object.values(this.eventsServices[depositorAddr]).map((eventService) => eventService.getEvents()) - ); - const depositEvents = events - .flat() - .reduce((acc, val) => [...acc, ...val.depositEvents], [] as FundsDepositedEvent[]); - const filledRelayEvents = events - .flat() - .reduce((acc, val) => [...acc, ...val.filledRelayEvents], [] as FilledRelayEvent[]); - const speedUpDepositEvents = events.flat().reduce( - (acc, val) => [ - ...acc, - ...val.speedUpDepositEvents.map((event) => ({ - ...event, - // we have to enrich the event with this information in order to determine - // which exact `transfer` needs to be updated. - emittedFromChainId: val.emittedFromChainId, - })), - ], - [] as Array - ); - const blockTimestampMap = events - .flat() - .reduce((acc, val) => ({ ...acc, ...val.blockTimestampMap }), {} as { [blockNumber: number]: number }); - - depositEvents.map((e) => this.insertFundsDepositedEvent(e, blockTimestampMap[e.blockNumber])); - filledRelayEvents.map((e) => this.insertFilledRelayEvent(e)); - speedUpDepositEvents.map((e) => this.handleSpeedUpDepositEvent(e, blockTimestampMap[e.blockNumber])); - this.transfersRepository.aggregateTransfers(); - - const filledTransfersCount = - depositorAddr === "all" - ? this.transfersRepository.countAllFilledTransfers() - : this.transfersRepository.countFilledTransfers(depositorAddr); - const pendingTransfersCount = - depositorAddr === "all" - ? this.transfersRepository.countAllPendingTransfers() - : this.transfersRepository.countPendingTransfers(depositorAddr); - - const eventData: TransfersUpdatedEventListenerParams = { - depositorAddr, - filledTransfersCount, - pendingTransfersCount, - }; - - // emit event only if the fetching wasn't stopped for depositor address. - // this is to prevent events from being triggered after the fetching was stopped - if (this.fetchingState[depositorAddr] === "started") { - this.eventEmitter.emit(TransfersHistoryEvent.TransfersUpdated, eventData); - } - } - - private insertFundsDepositedEvent(event: FundsDepositedEvent, timestamp: number) { - const { args, transactionHash } = event; - const { amount, originToken, destinationChainId, depositId, depositor, originChainId, relayerFeePct } = args; - const transfer: Transfer = { - amount: BigNumber.from(amount), - assetAddr: originToken, - depositId: depositId, - depositTime: timestamp, - depositTxHash: transactionHash, - destinationChainId: destinationChainId.toNumber(), - filled: ethers.constants.Zero, - sourceChainId: originChainId.toNumber(), - status: "pending", - fillTxs: [], - initialRelayerFeePct: relayerFeePct, - currentRelayerFeePct: relayerFeePct, - speedUps: [], - }; - this.transfersRepository.insertTransfer(originChainId.toNumber(), depositor, depositId, transfer); - } - - private insertFilledRelayEvent(event: FilledRelayEvent) { - const { args, transactionHash } = event; - const { totalFilledAmount, depositor, depositId, originChainId, relayerFeePct } = args; - this.transfersRepository.updateFilledAmount( - originChainId.toNumber(), - depositor, - depositId, - totalFilledAmount, - transactionHash, - relayerFeePct - ); - } - - private handleSpeedUpDepositEvent( - event: RequestedSpeedUpDepositEvent & { emittedFromChainId: number }, - timestamp: number - ) { - const { args, transactionHash, emittedFromChainId } = event; - const { newRelayerFeePct, depositor, depositId } = args; - this.transfersRepository.updateRelayerFee( - emittedFromChainId, - depositor, - depositId, - newRelayerFeePct, - transactionHash, - timestamp - ); - } - - public getFilledTransfers(depositorAddr: TrackableAddress, limit?: number, offset?: number) { - if (depositorAddr === "all") { - return this.transfersRepository.getAllFilledTransfers(); - } - return this.transfersRepository.getFilledTransfers(depositorAddr, limit, offset); - } - - public getPendingTransfers(depositorAddr: TrackableAddress, limit?: number, offset?: number) { - if (depositorAddr === "all") { - return this.transfersRepository.getAllPendingTransfers(); - } - return this.transfersRepository.getPendingTransfers(depositorAddr, limit, offset); - } -} diff --git a/src/transfers-history/config.ts b/src/transfers-history/config.ts deleted file mode 100644 index 826633fd2..000000000 --- a/src/transfers-history/config.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { ChainId } from "./adapters/web3/model"; - -export type SpokePoolConfig = { - lowerBoundBlockNumber?: number; -}; - -export type ClientConfig = { - spokePools: Record; -}; - -export const clientConfig: ClientConfig = { - spokePools: {}, -}; diff --git a/src/transfers-history/index.ts b/src/transfers-history/index.ts deleted file mode 100644 index 03bf0bfb7..000000000 --- a/src/transfers-history/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./client"; -export * from "./model"; diff --git a/src/transfers-history/model/README.md b/src/transfers-history/model/README.md deleted file mode 100644 index 789c9835f..000000000 --- a/src/transfers-history/model/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Data model - -Use this directory to define data models diff --git a/src/transfers-history/model/index.ts b/src/transfers-history/model/index.ts deleted file mode 100644 index 741425db8..000000000 --- a/src/transfers-history/model/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./transfer"; diff --git a/src/transfers-history/model/transfer.ts b/src/transfers-history/model/transfer.ts deleted file mode 100644 index bd43f1f26..000000000 --- a/src/transfers-history/model/transfer.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { BigNumber } from "ethers"; -import { ChainId } from "../adapters/web3/model"; - -export type TransferStatus = "pending" | "filled"; - -export type Transfer = { - depositId: number; - depositTime: number; - status: TransferStatus; - filled: BigNumber; - sourceChainId: ChainId; - destinationChainId: number; - assetAddr: string; - amount: BigNumber; - depositTxHash: string; - fillTxs: string[]; - initialRelayerFeePct: BigNumber; - currentRelayerFeePct: BigNumber; - speedUps: { txHash: string; relayerFeePct: BigNumber; timestamp: number }[]; -}; diff --git a/src/transfers-history/services/README.md b/src/transfers-history/services/README.md deleted file mode 100644 index 2def74974..000000000 --- a/src/transfers-history/services/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# Services - -This is the directory where services can be found. The Services are classes that usually perform operations like: -1. interface with an external actor/client (db, blockchain node, etc) -> execute business/data manipulation logic -> update the state if needed -2. orchestrate the execution of multiple services -3. TBD diff --git a/src/transfers-history/services/SpokePoolEventsQueryService.ts b/src/transfers-history/services/SpokePoolEventsQueryService.ts deleted file mode 100644 index dbabc069e..000000000 --- a/src/transfers-history/services/SpokePoolEventsQueryService.ts +++ /dev/null @@ -1,120 +0,0 @@ -import { FundsDepositedEvent, FilledRelayEvent, RequestedSpeedUpDepositEvent, TypedEvent } from "../../typechain"; -import { providers } from "ethers"; -import { Logger } from "../adapters/logger"; -import { ISpokePoolContractEventsQuerier } from "../adapters/web3"; -import { ChainId } from "../adapters/web3/model"; -import { clientConfig } from "../config"; - -export class SpokePoolEventsQueryService { - private latestBlockSearched: number | undefined; - - constructor( - private chainId: ChainId, - private provider: providers.Provider, - private eventsQuerier: ISpokePoolContractEventsQuerier, - private logger: Logger, - private depositorAddr?: string - ) {} - - public async getEvents() { - let from; - let depositEvents: FundsDepositedEvent[] = []; - let filledRelayEvents: FilledRelayEvent[] = []; - let speedUpDepositEvents: RequestedSpeedUpDepositEvent[] = []; - let blockTimestampMap: { [blockNumber: number]: number } = {}; - - if (this.latestBlockSearched) { - from = this.latestBlockSearched + 1; - } else { - from = clientConfig.spokePools[this.chainId].lowerBoundBlockNumber ?? -1; - } - const to = (await this.provider.getBlock("latest")).number; - - if (from > to) { - this.logger.debug("[SpokePoolEventsQueryService]", `🔴 chain ${this.chainId}: from ${from} > to ${to}`); - - return { - emittedFromChainId: this.chainId, - depositEvents: [], - filledRelayEvents: [], - speedUpDepositEvents: [], - blockTimestampMap: {}, - }; - } - let start = new Date(); - const [depositEventsSettled, filledRelayEventsSettled, speedUpDepositEventsSettled] = await Promise.allSettled([ - this.eventsQuerier.getFundsDepositEvents(from, to, this.depositorAddr), - this.eventsQuerier.getFilledRelayEvents(from, to, this.depositorAddr), - this.eventsQuerier.getSpeedUpDepositEvents(from, to, this.depositorAddr), - ]); - depositEvents = depositEventsSettled.status === "fulfilled" ? depositEventsSettled.value : []; - filledRelayEvents = filledRelayEventsSettled.status === "fulfilled" ? filledRelayEventsSettled.value : []; - speedUpDepositEvents = speedUpDepositEventsSettled.status === "fulfilled" ? speedUpDepositEventsSettled.value : []; - let end = new Date(); - this.logger.debug( - "[SpokePoolEventsQueryService::getEvents]", - `🟢 chain ${this.chainId}: ${depositEvents.length} FundsDeposited events, ${ - filledRelayEvents.length - } FilledRelayEvents, ${speedUpDepositEvents.length} RequestedSpeedUpDeposit events, blocks: ${from} -> ${to}, ${ - (end.valueOf() - start.valueOf()) / 1000 - } seconds` - ); - start = new Date(); - blockTimestampMap = await this.getBlocksTimestamp([...depositEvents, ...speedUpDepositEvents]); - end = new Date(); - this.logger.debug( - "[SpokePoolEventsQueryService::getEvents]", - `🟢 chain ${this.chainId}: fetched block numbers in ${(end.valueOf() - start.valueOf()) / 1000} seconds` - ); - this.latestBlockSearched = to; - - return { - emittedFromChainId: this.chainId, - depositEvents, - filledRelayEvents, - speedUpDepositEvents, - blockTimestampMap, - }; - } - - /** - * Take and array of contract events and return the timestamp of the blocks as a dictionary - * @param events - */ - private async getBlocksTimestamp(events: TypedEvent[]) { - const uniqueBlockNumbers = events.reduce( - (acc, event) => { - return { ...acc, [event.blockNumber]: true }; - }, - {} as Record - ); - const uniqueBlockNumbersList = Object.keys(uniqueBlockNumbers).map((blockNumber) => parseInt(blockNumber)); - this.logger.debug( - "[getBlocksTimestamp]", - `🟢 chain ${this.chainId}: fetching ${uniqueBlockNumbersList.length} blocks` - ); - const blocksChunks = this.getArrayChunks(uniqueBlockNumbersList); - const blocks = []; - for (const blocksChunk of blocksChunks) { - const newBlocks = await Promise.all(blocksChunk.map((blockNumber) => this.provider.getBlock(blockNumber))); - blocks.push(...newBlocks); - } - const timestamps = await Promise.all(blocks.map((block) => block.timestamp)); - const blockTimestampMap = uniqueBlockNumbersList.reduce( - (acc, blockNumber, idx) => ({ - ...acc, - [blockNumber]: timestamps[idx], - }), - {} as Record - ); - - return blockTimestampMap; - } - - private getArrayChunks(array: T[], chunkSize = 50): T[][] { - return Array(Math.ceil(array.length / chunkSize)) - .fill([]) - .map((_, index) => index * chunkSize) - .map((begin) => array.slice(begin, begin + chunkSize)); - } -}